| """High-level facade tying ingestion, retrieval, and answering together.""" |
| from __future__ import annotations |
|
|
| from pathlib import Path |
|
|
| from .config import settings |
| from .embeddings import get_embedder |
| from .ingestion import ingest_documents |
| from .llm import Answer, answer |
| from .retrieval import Retriever, RetrievalMode |
| from .store import VectorStore |
|
|
|
|
| class RagEngine: |
| def __init__(self, store: VectorStore | None = None) -> None: |
| self.embedder = get_embedder() |
| self.store = store or VectorStore(dim=self.embedder.dim) |
| self.retriever = Retriever(self.store, self.embedder) |
|
|
| def add_documents(self, documents: list[dict], **kwargs) -> int: |
| ingest_documents(documents, store=self.store, embedder=self.embedder, **kwargs) |
| self.retriever._bm25 = None |
| return len(self.store) |
|
|
| def query(self, question: str, k: int = 5, mode: RetrievalMode = "hybrid") -> Answer: |
| chunks = self.retriever.retrieve(question, k=k, mode=mode) |
| return answer(question, chunks) |
|
|
| |
| def save(self, directory: str | Path | None = None) -> None: |
| self.store.save(directory or settings.index_dir) |
|
|
| @classmethod |
| def load(cls, directory: str | Path | None = None) -> "RagEngine": |
| store = VectorStore.load(directory or settings.index_dir) |
| return cls(store=store) |
|
|