fastrag.retrieval#

Retrieval: turning one query into the documents that answer it.

Retrieval is a first-class, composable layer — not an implementation detail of prompting or chat. A retriever is fully specified as an object: k and whatever else it needs are constructor configuration, so it can be passed around, swapped, and benchmarked without its call sites knowing anything about it. VectorRetriever is the base case; RerankingRetriever wraps a vector search to narrow its over-fetch on relevance with a Reranker such as CohereReranker. BM25Retriever and HybridRetriever add lexical retrieval and replaceable rank fusion across any SDK retrievers. LanguageAwareRetriever keeps one translation of each page and prefers the question’s language.

class fastrag.retrieval.SectionContext(document_id, section_id, content, source_spans, heading_path)[source]#

Bases: object

Original retained section syntax, with document-scoped provenance.

Parameters:
class fastrag.retrieval.SectionIndex(documents=())[source]#

Bases: object

Keep source parents outside vector chunks and resolve merged sections.

Parameters:

documents (Iterable[NormalizedDocument])

add(document)[source]#

Register a validated parent; conflicting document IDs are rejected.

Parameters:

document (NormalizedDocument)

Return type:

None

resolve(chunk, *, ancestors=False, missing='raise')[source]#

Return all source sections in source order, optionally with ancestors.

Parameters:
Return type:

tuple[SectionContext, …]

class fastrag.retrieval.BM25Retriever(*, store, filter=None)[source]#

Bases: Retriever

Rank query terms with the store’s BM25 implementation.

store is any LexicalStore: the same open vector store a sibling VectorRetriever searches, when the backend supports both, or a separate lexical database when it does not.

Parameters:
async retrieve(query, *, k=5)[source]#

Return at most k lexical matches.

Parameters:
Return type:

list[Document]

class fastrag.retrieval.HybridRetriever(*, retrievers, fusion=None, candidate_k=40)[source]#

Bases: Retriever

Fetch candidates from each retriever concurrently, then fuse their ranks.

Parameters:
async retrieve(query, *, k=5)[source]#

Fuse the candidate rankings down to k documents.

Parameters:
Return type:

list[Document]

class fastrag.retrieval.LanguageAwareRetriever(*, retriever, detector, candidate_k=40, other_language_weight=0.8)[source]#

Bases: Retriever

Prefer documents in the question’s language, one translation per page.

Over-fetches candidate_k documents from retriever, best first, and detects the language of the question and of each document (a document’s own metadata["language"] wins over detection). Then:

  1. Translations collapse. Documents whose source_uri differs only by a leading locale path segment naming one of detector.languages (/docs/a, /en/docs/a, /ca/docs/a) are copies of one page, and only one URL’s documents are kept: one written in the question’s language, preferably under its locale, if any was retrieved, else the best-ranked one. The same file served under every locale collapses too.

  2. Documents written in another language have their score scaled by other_language_weight and the rest are re-sorted, so they yield to documents of similar relevance in the question’s language but still outrank much weaker ones. Documents without a numeric score keep retriever’s order.

The first k are returned with their rank restated and their metadata["language"] set where known, so a prompt can show it. A question whose language is not detected skips step 2.

retriever = LanguageAwareRetriever(
    retriever=RerankingRetriever(retriever=hybrid, reranker=reranker),
    detector=LinguaLanguageDetector(["en", "es", "ca", "zh"]),
)
Parameters:
  • retriever (Retriever) – Ranks the candidates. A RerankingRetriever returns comparable scores across languages.

  • detector (LanguageDetector) – Detects the question’s and the documents’ languages.

  • candidate_k (int) – How many documents to fetch from retriever before choosing k.

  • other_language_weight (float) – Factor, in (0, 1], applied to the score of a document written in another language than the question. A negative score is divided by it instead, so it always demotes.

async retrieve(query, *, k=5)[source]#

Return the k best documents, preferring the question’s language.

Parameters:
Return type:

list[Document]

class fastrag.retrieval.LanguageDetector[source]#

Bases: ABC

Names the language each text is written in.

languages#

The ISO 639-1 codes detect() can return. A URL path segment naming one of them is read as a locale (see LanguageAwareRetriever).

Type:

frozenset[str]

languages: frozenset[str]#
abstractmethod detect(texts)[source]#

Return the ISO 639-1 code of each text’s language, or None if unsure.

Blocking: LanguageAwareRetriever runs it in a worker thread.

Parameters:

texts (Sequence[str])

Return type:

list[str | None]

class fastrag.retrieval.LinguaLanguageDetector(languages, *, minimum_relative_distance=0.0)[source]#

Bases: LanguageDetector

Detects languages offline with Lingua, choosing among a corpus’s own.

Needs the “language” extra (lingua-language-detector). Naming only the languages the corpus is written in keeps short questions reliable: a short Catalan question is told apart from Spanish far more often when those are among a handful of candidates rather than 75.

detector = LinguaLanguageDetector(["en", "es", "ca", "zh"])
detector.detect(["How can I obtain a credential?"])  # ["en"]
Parameters:
  • languages (frozenset[str]) – ISO 639-1 codes of the languages to choose among, at least two.

  • minimum_relative_distance (float) – How far ahead of the runner-up the most likely language must be, from 0.0 to 0.99; text that does not clear it gets None. 0.0 always names a language.

languages: frozenset[str]#
detect(texts)[source]#

Detect every text’s language, in parallel.

Parameters:

texts (Sequence[str])

Return type:

list[str | None]

class fastrag.retrieval.RerankingRetriever(*, reranker, retriever=None, vector_store=None, embedder=None, candidate_k=None)[source]#

Bases: Retriever

Over-fetch with a retriever, then narrow on relevance.

Composition, not configuration: a plain VectorRetriever over-fetches k candidates on cosine similarity, and reranker then narrows them to top_k on relevance — a cross-encoder reading query and document together, which similarity search alone cannot do. The returned score/rank are the reranker’s own, not the vector search’s — see rerank().

async with MilvusVectorStore(url=MILVUS_URI) as vector_store:
    retriever = RerankingRetriever(
        vector_store=vector_store,
        embedder=Model2VecEmbedder(model=EMBEDDING_MODEL),
        reranker=CohereReranker(
            model="rerank-v3.5", base_url=RERANK_BASE_URL, api_key=api_key
        ),
    )
    documents = await retriever.retrieve("What is AgrospAI?", k=200, top_k=5)
Parameters:
  • vector_store (VectorStore | None) – The collection to over-fetch from. Opened by the caller; this retriever neither opens nor closes it.

  • embedder (Embedder | None) – Embeds the query text — see VectorRetriever.

  • retriever (Retriever | None) – Any SDK retriever, including a hybrid retriever. Mutually exclusive with the legacy vector_store/embedder pair.

  • candidate_k (int | None) – Optional over-fetch count used even when the caller requests only the final k results.

  • reranker (Reranker) – Scores the over-fetched documents against the query.

async retrieve(query, *, k=5, top_k=None)[source]#

Fetch candidates through the wrapped retriever, then rerank to top_k.

Parameters:
  • query (str) – Natural-language query text.

  • k (int) – How many documents the vector store over-fetches.

  • top_k (int | None) – How many documents the reranker keeps, best first. Defaults to k when omitted.

Return type:

list[Document]

class fastrag.retrieval.Retriever[source]#

Bases: ABC

Turns one query into the documents that answer it, best first.

One method, one required argument. Every other knob — k, filters, thresholds — is constructor configuration, so a retriever is a fully specified object that can be passed around, swapped, and benchmarked without its call sites knowing anything about it.

abstractmethod async retrieve(query, *, k=5)[source]#

Return at most k documents relevant to query, best first.

Parameters:
  • query (str) – Natural-language query text.

  • k (int) – Maximum number of documents to return.

Return type:

list[Document]

class fastrag.retrieval.VectorRetriever(*, vector_store, embedder)[source]#

Bases: Retriever

Dense similarity search: the base retriever every other one over-fetches from.

Holds its collaborators without owning their lifecycles: the caller opens vector_store (async with MilvusVectorStore(...) as vector_store:) and this retriever never opens or closes it. embedder is used only for its embed() method — never run as a pipeline step, never cached, never batched — so a single query embeds as one call.

async with MilvusVectorStore(url=MILVUS_URI) as vector_store:
    retriever = VectorRetriever(
        vector_store=vector_store,
        embedder=Model2VecEmbedder(model=EMBEDDING_MODEL),
    )
    documents = await retriever.retrieve("What is AgrospAI?", k=5)
Parameters:
  • vector_store (VectorStore) – The collection to search. Opened by the caller.

  • embedder (Embedder) – Embeds the query text with the same model the collection was indexed with.

async retrieve(query, *, k=5)[source]#

Embed query and return the k nearest documents, best first.

Parameters:
Return type:

list[Document]

Modules

base

The Retriever contract: turning a query into documents.

bm25

Lexical retrieval through the SDK's LexicalStore contract.

fusion

Pluggable ranking fusion strategies.

hybrid

Composable hybrid retrieval with replaceable ranking fusion.

language

Retrieval that prefers documents in the language of the question.

reranking

Reranking: scoring documents against a query.

reranking_retriever

RerankingRetriever: narrowing any retrieval strategy with a reranker.

sections

Database-independent exact source context for structural retrieval hits.

vector

VectorRetriever: dense similarity search over a VectorStore.