ir.retrieve¶
Retrieval — hard metadata filtering + dense / lexical / hybrid ranking.
search() embeds the query, applies a hard metadata filter to narrow the
candidate set (the vd Mongo-style filter language — ownership, name, tags),
then ranks the survivors. Three ranking modes share that one filtered candidate
set:
"dense"(default) — exact brute-force cosine over the embedding matrix."lexical"— Okapi BM25 over the candidates’ text (vd.bm25_lexical_search)."hybrid"— dense and lexical fused, either by Reciprocal Rank Fusion (fusion="rrf", the defaultvd.reciprocal_rank_fusionrank-based fuse that sidesteps the cosine/BM25 score-scale mismatch) or by a magnitude-preserving convex blend (fusion="blend") that keeps the dense cosine’s absolute scale for better abstention separability (see ir_08).
Hybrid matters for short, identifier-heavy capability text (skill / package /
tool names), the regime where dense-only retrieval fails silently on exact
identifiers and rare terms. An optional rerank hook (any
ef.Reranker) re-scores the top fused candidates with a cross-encoder;
it defaults to None so retrieval stays offline and API-free out of the box.
All ranking is exact brute force — correct and instant at ir’s corpus
sizes — and surface-hits collapse to the best surface per artifact. Lexical and
fusion reuse vd; if vd is unavailable, hybrid degrades to dense and
lexical returns no results (both with a warning), so a missing optional dep
never hard-fails a search.
Beyond the within-corpus channel fusion above, fuse_hits() merges ranked
hit lists from different sources (corpora / embedders / modes) by weighted
Reciprocal Rank Fusion — raw scores never cross a source boundary, only ranks
do. It is the shared cross-source merge primitive consumed by federated
ir.discover() and by an orchestration layer’s fan-in reranker (ir_09 §3).
Every search hit carries its corpus name as source
and its surface’s plan position as surface_index.
Two optional ranking signals act inside search(): surface_weights
multiplies the first-stage score per surface kind, and dep_boost adds a
structural score per candidate after the reranker (the shipped
dependency_evidence_boost() rewards dependencies on a caller-supplied
library set). Both default to off.
records_for_artifact() is the hit-operation beneath retrieval-time
context expansion: given a hit’s artifact_id, it returns all of that
artifact’s stored records (its sibling surfaces), ordered — resolved through
the ledger, never by re-deriving record ids. The expansion operator itself
(ir.expand.expand() — retrieve → expand → rerank) builds on it.
Module Attributes
Ranking modes accepted by |
|
Hybrid fusion methods accepted by |
|
RRF rank constant — the |
|
Dense weight in the |
|
|
|
|
|
|
|
|
Functions
|
Bind ONE corpus to the uniform |
|
A |
|
Merge per-source ranked hit lists into one ranking — by rank, not score. |
|
All stored records of artifact_id, ordered by |
|
Return the top-k |
Exceptions
The corpus has no ledger entry for the requested artifact. |
- ir.retrieve.DFLT_BLEND_ALPHA = 0.5¶
Dense weight in the
"blend"fusion convex combination (1-alphaon the bounded lexical term).0.5weighs the two equally.
- ir.retrieve.DFLT_BM25_SAT_K = 8.0¶
bm25 -> bm25/(bm25+k), a bounded squash to[0, 1)that needs no per-query normalization (which would erase the absolute-magnitude signal abstention calibration depends on).- Type:
BM25 saturation constant for
"blend"fusion
- ir.retrieve.DFLT_RRF_K = 60¶
RRF rank constant — the
kof1 / (k + rank)(standard default 60).
- ir.retrieve.FUSIONS = ('rrf', 'blend')¶
Hybrid fusion methods accepted by
search()(mode="hybrid")."rrf"is the rank-based default;"blend"preserves score magnitude (see_blend_fuse()and ir_08) for better abstention separability.
- ir.retrieve.Identity¶
None(default — hits from different sources never merge; same id, different corpus = different artifact), the string"pointer"(merge hits whosepointermatch — opt-in, for corpora that genuinely index the same files), or anyhit -> hashablecallable (a falsy key falls back to per-source identity).- Type:
How cross-source duplicates are detected in
fuse_hits()
- exception ir.retrieve.NoLedgerEntry[source]¶
Bases:
KeyErrorThe corpus has no ledger entry for the requested artifact.
The benign miss (unknown artifact, or a corpus built without ledger bookkeeping) — distinct from a stale/torn ledger, which raises a plain
KeyErrordescribing the corruption. AKeyErrorsubclass so existingexcept KeyErrorcallers keep working; the disclosure seam catches this one specifically and tolerates it per hit.
- ir.retrieve.Retriever¶
(query, **overrides) -> list[SearchHit]— ir_09’s Retriever leaf (one query, one corpus) as a swappable callable.as_retriever()binds one corpus to this contract so an orchestration layer (e.g.raglab) can register an ir corpus as one source key without importing ir internals.- Type:
A retriever
alias of
Callable[[…],list[SearchHit]]
- ir.retrieve.ScoreBoost¶
hit -> float, added to each candidate’s score after fusion and the reranker, before the per-artifact collapse. Seedependency_evidence_boost().- Type:
A ranking-time score boost
- ir.retrieve.as_retriever(corpus_or_name, **search_defaults)[source]¶
Bind ONE corpus to the uniform
Retrievercontract.Returns
retrieve(query, **overrides) -> list[SearchHit]that callssearch()withsearch_defaults(a per-call kwarg overrides a bound default). A corpus name is resolved once viair.open_corpus(); pass an openCorpusto skip that. The returned callable carries the bound corpus on.corpusfor introspection.>>> retr = as_retriever(corpus, mode="hybrid", k=20) >>> hits = retr("how do I deploy the app") >>> hits = retr("deploy", filter={"owner": "me"})
- ir.retrieve.dependency_evidence_boost(relevant_libs, *, weight, saturate=1, deps_field='deps')[source]¶
A
dep_boostforsearch(): reward dependencies on relevant_libs.Reads the candidate’s
depsfilter field (asPackagestores it), reduces each spec to its bare, PEP 503-normalized name, and returnsweight * min(n, saturate) / saturatewherencounts the dependencies found in relevant_libs. With the defaultsaturate=1a single relevant dependency earns the fullweight. A structural signal, cheap and model-free, that a prose reranker cannot be fooled out of: an async-task package whose README says “DAG” does not depend on graph libraries.relevant_libs is the caller’s call: which libraries matter for a goal is a planning decision that belongs to the agent layer, never to
ir.weightis added to the score on the search’s scale (an RRF fused score is near0.03, a cosine near0.5, a sigmoid reranker in(0, 1)), so tune it per configuration.>>> from ir.base import SearchHit >>> boost = dependency_evidence_boost({"networkx"}, weight=0.1) >>> boost(SearchHit("unbox", "description", 0.4, "", {"deps": ["networkx>=3"]})) 0.1 >>> boost(SearchHit("au", "description", 0.5, "", {"deps": ["anyio"]})) 0.0
- ir.retrieve.fuse_hits(hits_by_source, *, rrf_k=60, weights=None, identity=None, k=None)[source]¶
Merge per-source ranked hit lists into one ranking — by rank, not score.
The cross-source counterpart of the within-corpus hybrid fusion: scores from different (corpus, mode, embedder) tuples live on incommensurable scales (ir_07: “a different model re-scales everything”), so **raw scores never cross the source boundary** — within each source they order and dedup that source’s hits (one scale, sound), and across sources only ranks interact, via weighted Reciprocal Rank Fusion: each hit contributes
weights[source] / (rrf_k + rank).- Parameters:
hits_by_source (
Mapping[str|None,Sequence[SearchHit]]) –{source_name: ranked hits}. Hits without asourceare stamped with their mapping key (existing tags win, so one corpus bound under two keys still counts as one source). ANonekey is the untagged pseudo-source: its hits fuse as one rank group and stay unattributed (source=None). Within each list, duplicate artifacts — and, whenidentityis given, identity-duplicates — collapse to their best raw score before ranking, so a multi-query / multi-round pool can never double-count one artifact’s RRF mass.rrf_k (
int) – the RRF rank constant (standard default 60).weights (
Mapping[str,float] |None) – optional per-source trust dial (default 1.0 each) — a source’s contribution scales linearly, no score comparability needed. Keys naming sources absent fromhits_by_sourceare ignored (a per-round pool may legitimately lack a configured source); callers with a closed source set should validate keys upfront, as federatedir.discover()does.identity (
Union[Callable[[SearchHit],Any],str,None]) – how cross-source duplicates merge — seeIdentity. DefaultNone: never; each(source, artifact_id)stays a distinct result.k (
int|None) – truncate the fused ranking to this many hits.
- Return type:
- Returns:
the fused hits, best-first. Each carries the fused score in
scoreand keeps its pre-fusion magnitude asmetadata["source_score"](+"source_rank"), so downstream consumers (abstention gates, LLM judges) never lose the per-source signal. When anidentitymerge combined several sources’ hits,metadata["fused_sources"]lists them and the representative hit is the one with the best rank. Single-source input passes through with raw scores (RRF of one list is that list’s order — same convention as the hybrid fusion’s single-channel fallback), so the fused-score rescaling only happens when there is genuinely something to fuse. The post-fusionscoreis ordinal: valid for ordering and relative cuts, meaningless against absolute floors — apply calibratedmin_scorefloors per source, before fusing (see ir_07/ir_08 andir.discover’s federated form).
- ir.retrieve.records_for_artifact(store_or_corpus, artifact_id, *, surface_kind=None)[source]¶
All stored records of artifact_id, ordered by
surface_index.The sibling-addressing primitive beneath retrieval-time context expansion: a
SearchHitnames its artifact (and, viasurface_index, which surface of it matched); this returns every surface of that artifact, in plan order, so an expansion policy can stitch neighbors / parents around the hit.Resolution is ledger-backed only: the artifact’s ledger entry lists its
record_ids. Record ids are never re-derived from a per-kind index likemetadata["chunk_index"]— on multi-kind strategies that index differs from the plan-globalsurface_indexbaked into the id (seeir.base.Record.make_id()), so derivation would fetch wrong or missing siblings.- Parameters:
store_or_corpus – a
CorpusStore, anything carrying one as.store(e.g. aCorpus), or a corpus name — resolved straight to its local store: sibling lookup never embeds, so unlikeir.open_corpus()no embedder is loaded.artifact_id (
str) – the artifact whose surfaces to fetch.surface_kind (
str|None) – restrict to one surface kind (e.g."readme_chunk"); a known artifact with no surfaces of that kind yields[].
- Raises:
NoLedgerEntry – the ledger has no entry for artifact_id (an unknown artifact, or a corpus built without
ir.index.build()’s ledger bookkeeping). AKeyErrorsubclass.KeyError – an entry exists but lists a record missing from the store (a stale ledger: interrupted build or out-of-band
delete_record) — data corruption, named in the message.
- Return type:
- ir.retrieve.search(corpus, query, *, k=10, filter=None, surfaces=None, per_artifact=True, mode='dense', fusion='rrf', rrf_k=60, alpha=0.5, bm25_sat_k=8.0, fetch_k=None, rerank=None, rerank_text='surface', rerank_max_chars=2000, bm25=None, formulate=None, surface_weights=None, dep_boost=None)[source]¶
Return the top-k
SearchHitfor query.- Parameters:
k (
int)per_artifact (
bool)mode (
str) – (dense + BM25 fused). Hybrid is the strongest default for short, identifier-heavy text;"dense"is the historical behavior and is kept as the default for backward compatibility.fusion (
str) – rank-based Reciprocal Rank Fusion) or"blend"(magnitude-preserving convex blend; better abstention separability — see ir_08). Ignored for non-hybrid modes.rrf_k (
int)alpha (
float)bm25_sat_k (
float)fetch_k (
int|None) – (defaultmax(k*5, 50)when collapsing per artifact or reranking, elsek).rerank (
Union[Callable,str,None]) – that re-scores the ranked candidates after fusion – the precision stage. The reranker sees the full candidate list (up tofetch_kitems) and may reorder it; reranked hits carry the reranker’s score, which is on its own scale (seeir.rerank, andir.rerank.calibration_key()for abstention floors). Pass"cross-encoder"(or"cross-encoder:<model>") for ef’s sentence-transformers cross-encoder, imported lazily; when that extra (ir[rerank]) is missing the search warns once and keeps the first-stage ranking. DefaultNonekeeps retrieval offline (no model download / API call).rerank_text (
Union[str,Callable]) – (default; the matched surface’s text),"artifact"(the artifact’s sibling surfaces joined in plan order, so a thin description is judged against its full README), or a callable(corpus, meta) -> str.rerank_max_chars (
int)bm25 (
Mapping[str,Any] |None) – (e.g.{"k1": 1.5, "b": 0.75}).formulate (
Optional[Callable[[str],str|Sequence[str]]]) – [str, …]``) applied before retrieval — rewrite / expand / HyDE (ir_09 §3). Identity by default (embed the query verbatim). When it returns several queries, ir runs each and fuses the results (best surface per artifact). Seeir.make_llm_formulator().surface_weights (
Mapping[str,float] |None) –{"deps": 2.0}to let a high-precisiondepssurface outrank prose chunks. Each surface-hit’s first-stage score (the fused score in hybrid mode) is multiplied by its kind’s weight (default 1.0). Each channel still retrieves its own topfetch_k; the weights reorder those candidates (in hybrid mode, the whole fused union) before the cut tofetch_k, the reranker and the per-artifact collapse. Setting them makes the search over-fetch likererankdoes, and formulated sub-searches inherit them. Kinds the corpus lacks are ignored; weights must be finite and non-negative. Meant for the non-negative scores of hybrid fusion and BM25 (a negative dense cosine moves down when multiplied by a weight above 1). Weighted scores are on a different scale from unweighted ones, so a calibrated floor does not apply to them (discover(min_score="auto")warns and skips it). DefaultNoneweighs every surface equally, as before.dep_boost (
Optional[Callable[[SearchHit],float]]) – added to each fetched candidate’s score after fusion and the reranker, before the per-artifact collapse – a structural signal next to the reranker’s textual one.dependency_evidence_boost()builds one from a caller-supplied library set. It reorders the fetched candidates (raisefetch_kto show it more); boosted scores need their own abstention floor (discover(min_score="auto")warns and skips it). Likererankandsurface_weights, it makes the search over-fetch (max(k*5, 50)) even withper_artifact=False, so pinfetch_kwhen comparing runs with and without it. DefaultNone: no boost.
- Return type: