Multi-Document RAG

On this page

Overview

MultiDocumentRAGSystem manages a collection of independently-chunked documents, letting queries be scoped to a subset (filter_docs) and providing per-document lifecycle operations (add/update/remove) on top of shared vector_db, chunker, and context_manager collaborators.

MultiDocumentRAGSystem

Constructor

Python · 8 lines
def __init__(
    self,
    vector_db: Any,
    llm: Any,
    chunker: Any,
    context_manager: Any,
    config: Optional[Any] = None,
)

All four collaborators are required positional dependencies — this class does not construct them internally. chunker and context_manager are externally-defined objects not present in this archive; see Installation for their inferred contract.

Document lifecycle

MethodSignatureDescription
add_document(doc_id, text, metadata=None, language=None, chunk_independently=True) -> Dict[str, Any]Adds one document; _chunk_document splits it safely and flexibly using the injected chunker.
add_documents(documents: Union[Dict[str, str], List[Dict[str, Any]]], global_metadata=None) -> Dict[str, Dict[str, Any]]Bulk add. Accepts either {doc_id: text} or [{"doc_id": ..., "text": ..., "metadata": {...}}, ...].
update_document(doc_id, new_text, metadata=None) -> Dict[str, Any]Replaces an existing document's content/metadata.
remove_document(doc_id) -> Dict[str, Any]Removes a document and (implied by design) its chunks from the vector store.

_detect_language(text) -> str auto-detects language when not explicitly provided to add_document.

query(query, top_k=None, filter_docs=None, include_sources=True, language="ar", **llm_kwargs) -> Dict[str, Any]

ParameterDescription
top_kNumber of results; None means "all".
filter_docsList of document IDs to restrict the search to — the core feature distinguishing this from a flat single-corpus RAG system.
include_sourcesWhether to extract and return source attributions (_extract_sources).
languageAnswer language (defaults to "ar").
**llm_kwargsPassed through to the LLM call.

Internally builds an enhanced prompt via _build_prompt(query, context, language).

Introspection

MethodPurpose
get_document_info(doc_id) -> Optional[Dict[str, Any]]Metadata/chunk-count for one document.
list_documents() -> List[Dict[str, Any]]All registered documents.
get_stats() -> Dict[str, Any]Comprehensive system statistics.
get_document_stats_summary() -> Dict[str, Any]Aggregated per-document stats summary.

Persistence

Python · 3 lines
def save(self, path: str) -> None: ...
@classmethod
def load(cls, path: str, vector_db, llm, chunker, context_manager, config=None) -> "MultiDocumentRAGSystem": ...

Note that load() still requires the four collaborator objects to be supplied fresh — only the document/chunk state is restored from path, not the collaborators themselves.

Async API

agenerate(query, **kwargs) -> str, aretrieve(query, **kwargs), plus __aenter__/__aexit__.

Complete example

Python · 18 lines
from zerda.rag.types.multi_doc_rag import MultiDocumentRAGSystem

system = MultiDocumentRAGSystem(vector_db, llm, chunker, context_manager)

system.add_documents({
    "handbook_2024": handbook_text,
    "policy_v2": policy_text,
})

result = system.query(
    "What is the remote-work policy?",
    filter_docs=["policy_v2"],
    language="en",
)
print(result["answer"])

print(system.list_documents())
system.save("state/multi_doc.json")

Best practices

  • Use filter_docs rather than maintaining separate MultiDocumentRAGSystem instances per document subset — it reuses the same vector index and collaborators.
  • Call get_document_stats_summary() periodically in long-running services to catch documents that silently failed chunking.

Common mistakes

  • Calling load() without re-supplying the same chunker/context_manager configuration used originally — behavior on subsequent add_document calls may differ if the collaborator objects changed.
  • Passing a document ID in filter_docs that hasn't been added — the query will run against an effectively empty filtered set with no chunks returned.
  • Domain-Specific RAG — orthogonal filtering (topic vs. document identity); the two can be composed.

Related pages