Skip to main content

A reusable RAG core library built on FAISS and Ollama

Project description

๐Ÿง  pyragcore

A reusable, modular RAG (Retrieval-Augmented Generation) core library built on FAISS and Ollama. Use it as the foundation for any AI project that needs document ingestion, semantic search, and LLM-powered responses.


Features

  • ๐Ÿ—‚๏ธ FAISS vector store with persistence, deduplication, and metadata filtering
  • ๐Ÿ”ข SentenceTransformer embeddings with GPU support
  • ๐Ÿ” Semantic retrieval with MMR search and metadata filtering
  • ๐Ÿค– Ollama LLM integration for local, private inference
  • ๐ŸŽ™๏ธ Voice input/output support
  • ๐Ÿงฑ Abstract base classes for building custom pipelines
  • ๐Ÿ“ฆ Modular optional dependencies โ€” install only what you need

Installation

pip install pyragcore          # core only (FAISS + tqdm)
pip install pyragcore[embeddings]  # + SentenceTransformers
pip install pyragcore[ollama]      # + Ollama LLM
pip install pyragcore[voice]       # + speech input/output
pip install pyragcore[all]         # everything

Quick Start

from pyragcore.pipeline.base_pipeline import BasePipeline
from pyragcore.embeddings.embedder import Embedder
from pyragcore.retrieval.vector_store import VectorStore
from pyragcore.retrieval.retriver import Retriver
from pyragcore.llm.responder import Responder

# Extend BasePipeline for your use case
class MyPipeline(BasePipeline):
    def ingest(self, source: str) -> str:
        # implement your ingestion logic
        ...

pipeline = MyPipeline(persist_dir="./memory", output_folder="./output")
source_id = pipeline.ingest("./my_document.pdf")
answer = pipeline.ask("What is this document about?", source_id=source_id)
print(answer)

Architecture

pyragcore/
โ”œโ”€โ”€ embeddings/
โ”‚   โ””โ”€โ”€ embedder.py          # SentenceTransformer wrapper with GPU support
โ”œโ”€โ”€ retrieval/
โ”‚   โ”œโ”€โ”€ vector_store.py      # FAISS vector store with persistence
โ”‚   โ””โ”€โ”€ retriver.py          # Semantic search with metadata filtering
โ”œโ”€โ”€ ingestion/
โ”‚   โ”œโ”€โ”€ base_loader.py       # Abstract base loader
โ”‚   โ”œโ”€โ”€ base_chunker.py      # Abstract base chunker
โ”‚   โ””โ”€โ”€ chunker.py           # Token-based chunker (tiktoken)
โ”œโ”€โ”€ llm/
โ”‚   โ”œโ”€โ”€ responder.py         # Ollama LLM wrapper
โ”‚   โ””โ”€โ”€ prompt.py            # Prompt builder with chat history
โ”œโ”€โ”€ pipeline/
โ”‚   โ””โ”€โ”€ base_pipeline.py     # Abstract base pipeline
โ”œโ”€โ”€ utils_io/
โ”‚   โ”œโ”€โ”€ voice.py             # Speech input/output
โ”‚   โ”œโ”€โ”€ choose_model.py      # Ollama model picker
โ”‚   โ””โ”€โ”€ logger.py            # Logging utility
โ””โ”€โ”€ exceptions.py            # Custom exceptions

Building a Custom Pipeline

Extend BasePipeline and implement ingest():

from pyragcore.pipeline.base_pipeline import BasePipeline
from pyragcore.ingestion.base_loader import BaseLoader
from pyragcore.ingestion.chunker import Chunker
from tqdm import tqdm

class MyLoader(BaseLoader):
    def read(self, path) -> dict:
        # read your source and return
        return {
            "text": "...",
            "metadatas": {
                "file_id": "unique_id",
                "file_name": "my_file.txt",
                "source": path,
            }
        }

class MyPipeline(BasePipeline):
    def __init__(self, persist_dir: str, output_folder: str, model_name: str = "llama3.2"):
        super().__init__(persist_dir, output_folder, model_name)
        self.chunker = Chunker()

    def ingest(self, source: str) -> str:
        loader = MyLoader()
        content = loader.read(source)
        text = content.get("text", "")
        metadata = content.get("metadatas", {})
        source_id = metadata.get("file_id", "")

        if self._is_ingested(source_id):
            print("Already ingested, skipping...")
            return source_id

        chunks = self.chunker.chunk(text, metadata)
        documents, metadatas, ids = [], [], []

        for i, item in enumerate(chunks):
            documents.append(item["chunk"])
            metadatas.append(item["metadatas"])
            ids.append(f"{source_id}_chunk_{i}")

        BATCH_SIZE = 64
        all_embeddings = []
        for start in tqdm(range(0, len(documents), BATCH_SIZE), desc="Embedding"):
            batch = documents[start:start + BATCH_SIZE]
            all_embeddings.extend(self.embedder.embed(batch))

        self.vector_store.add(
            embeddings=all_embeddings,
            documents=documents,
            metadata=metadatas,
            ids=ids
        )
        return source_id

VectorStore

from pyragcore.retrieval.vector_store import VectorStore

store = VectorStore(dim=768, persist_path="./memory", autosave=True)

# add documents
store.add(embeddings=[[...]], documents=["text"], metadata=[{"file_id": "abc"}], ids=["id_0"])

# search
results = store.search(query_embedding=[...], k=5)

# search with filter
results = store.search_with_filter(query_embedding=[...], k=5, where={"file_id": "abc"})

# MMR search for diversity
results = store.mmr_search(query_embedding=[...], k=5, lamda_param=0.5)

# list ingested files
files = store.list_files()

Embedder

from pyragcore.embeddings.embedder import Embedder

embedder = Embedder(model_name="all-mpnet-base-v2")

# embed multiple texts
embeddings = embedder.embed(["text one", "text two"])

# embed a single query
embedding = embedder.embed_one("what is a database?")

Requirements

  • Python 3.13+
  • Ollama installed and running (for LLM features)
  • NVIDIA GPU with CUDA 12.8+ (optional, falls back to CPU)

PyTorch with CUDA

pyragcore does not pin a specific PyTorch version to stay flexible. Install the version that matches your system:

# CUDA 12.8
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu128

# CPU only
pip install torch torchvision

Exceptions

from pyragcore.exceptions import (
    BotRagException,        # base exception
    EmbeddingException,     # embedding failed
    RetrievalException,     # retrieval failed
    VectorStoreException,   # vector store error
    ModelNotFoundException, # ollama model not found
)

Projects Built with pyragcore

  • StudyBot โ€” Chat with your documents and YouTube videos
  • Coder-Assistant โ€” AI assistant for your codebase (WIP) (Soon)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyragcore-0.1.5.tar.gz (17.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyragcore-0.1.5-py3-none-any.whl (18.9 kB view details)

Uploaded Python 3

File details

Details for the file pyragcore-0.1.5.tar.gz.

File metadata

  • Download URL: pyragcore-0.1.5.tar.gz
  • Upload date:
  • Size: 17.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for pyragcore-0.1.5.tar.gz
Algorithm Hash digest
SHA256 ceb73b5f8375d10ac7a0043904af51c8ac38cd58b4946a877344fca77d73bd6c
MD5 8f41557e9ca0e9852b2bc218bba0ab8c
BLAKE2b-256 6f2569efdd984442435dcf77874aed0fedf7a1427f1509b9469a9433720896ab

See more details on using hashes here.

File details

Details for the file pyragcore-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: pyragcore-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 18.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for pyragcore-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 07c980665b8417a39a6f873fe60b6ef4fc928c9df30e5961b920e4f7f4462409
MD5 fa03c74d5e9be863e96f77570d34c8f2
BLAKE2b-256 020f0f6050d633bbe09d9a9e42de1b7cdb9ac08756360caf3cd467e7577249c4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page