Skip to content

Retrieval

retold.retrieve.retriever

The complete retrieval pipeline from a principal and request to an auditable response.

Retriever

Retrieve scope-filtered memories and persist a complete decision trail for every request.

search

search(
    principal: Principal, request: SearchRequest
) -> SearchResponse

Run each retrieval stage in order and record all intermediate results before returning.

retold.retrieve.gate

Relevance floors for tool- and host-issued memory retrieval.

GateDecision dataclass

The survivors, rejected candidates, and a user-facing reason for an empty result.

Gate

Bases: Protocol

Apply calibrated relevance rules to fused candidates.

apply

apply(
    candidates: Sequence[Candidate],
    records: Mapping[str, Record],
    request: SearchRequest,
) -> GateDecision

Return candidates that have sufficient independent relevance evidence.

FloorGate

Apply absolute signal floors before a channel-aware relative RRF floor.

apply

apply(
    candidates: Sequence[Candidate],
    records: Mapping[str, Record],
    request: SearchRequest,
) -> GateDecision

Keep exact entity matches or candidates that satisfy an absolute relevance floor.

exclude_source_kinds

exclude_source_kinds(
    candidates: Sequence[Candidate],
    records: Mapping[str, Record],
    request: SearchRequest,
    config: GateConfig,
) -> GateDecision

The gate's policy rules alone, without its relevance floors.

cross_encoder_only ranking uses this in place of :class:FloorGate: the auto-retrieval source-kind exclusion still applies, because it is a policy about what a host-issued search may surface, and the cross-encoder floor then makes the only relevance decision. Scope, status, and expiry were applied before candidate generation and are not repeated here.

retold.retrieve.rewrite

Optional query rewriting: a no-op default and a hosted implementation behind the same protocol.

The rewriter sees raw queries and the current-turn context, never candidate records, the store, or earlier results. A hosted rewrite may only resolve references and name the subject. A rewrite that introduces a capitalised name absent from the queries and the context is refused and the raw queries are used, so the stage cannot invent an entity or a private fact on the way into retrieval.

QueryRewriter

Bases: Protocol

Rewrite raw search queries using only the supplied current-turn context.

rewrite

rewrite(queries: list[str], context: str) -> RewriteResult

Return the same number of standalone queries, or raise RewriteError.

HostedLLMQueryRewriter

One structured call with the versioned prompt; anything outside the contract is a failed rewrite.

NoRewriter

The default slot that leaves raw queries unchanged without a hosted call.

rewrite

rewrite(queries: list[str], context: str) -> RewriteResult

Return the supplied raw queries unchanged.

rewriter_from_config

rewriter_from_config(config: RetoldConfig) -> QueryRewriter

The rewriter the configuration asks for: a no-op unless retrieval.rewrite.enabled.

retold.index.reranker

Reranker protocol, the no-op placeholder, and the lazily loaded cross-encoder.

RerankError

Bases: RuntimeError

The cross-encoder pass timed out or failed and the configuration says not to fall back.

Reranker

Bases: Protocol

Score query-record pairs with a higher-is-better relevance value.

is_loaded property

is_loaded: bool

Return whether the reranker can score without loading a model.

score

score(query: str, document: str) -> float

Return one relevance score for a query-record pair.

score_pairs

score_pairs(
    pairs: Sequence[tuple[str, str]],
) -> list[float]

Return one score per pair, in order; the cross-encoder scores them as one batch.

NoReranker

A placeholder that preserves original ordering while reranking is disabled.

is_loaded property

is_loaded: bool

Return true because the no-op implementation has no model to load.

score

score(query: str, document: str) -> float

Return a neutral score when explicitly used in a test-only no-op path.

BgeReranker

BAAI/bge-reranker-v2-m3 through sentence-transformers' CrossEncoder, loaded on first use.

The model has one output label, so predict applies a sigmoid and scores lie in (0, 1); the configured floor is compared on that scale.

warm

warm() -> None

Load the model now, so the first search does not spend its timeout on the load.

RerankOutcome dataclass

What one cross-encoder pass produced, or why it did not.

reranker_from_config

reranker_from_config(config: RetoldConfig) -> Reranker

The reranker the configuration asks for: a no-op unless reranker.enabled.

rerank

rerank(
    candidates: Sequence[Candidate],
    records: Mapping[str, Record],
    queries: Sequence[str],
    reranker: Reranker,
) -> tuple[list[Candidate], list[dict[str, object]]]

Score every query-record pair in one batch, keep each record's best score, and sort by it.

rerank_with_timeout

rerank_with_timeout(
    candidates: Sequence[Candidate],
    records: Mapping[str, Record],
    queries: Sequence[str],
    reranker: Reranker,
    *,
    timeout_ms: int,
    on_failure: RerankFailure,
) -> RerankOutcome

Run :func:rerank in a worker thread and give up on it after timeout_ms.

The worker scores copies of the candidates, so a pass that is abandoned cannot write scores into the list the search went on to use. With on_failure="fallback" a timeout or a scoring error returns the input order unchanged and says so in status; with "fail" it raises :class:RerankError.