Technology · Discipline

Hybrid retrieval

Dense embeddings fused with BM25 and reranked, with every constant found by sweep.

Dense · BM25 · reciprocal-rank fusionFAFOHive · Capabilities modelCross-encoder rerank
One query white rule: the weight a classifier sets for this query; lit: one chunk that every stream ranked
Fused by reciprocal rank · reranked · near-duplicates dropped
the chunk all three streams agreed on
the next best match
a near-duplicate of the first
a different source on the same point
  • ~294,000structure-aware chunks from about 19,000 files in one code index
  • 129configuration cells swept for the baseline's constants
  • 5embedding models in the bake-off before the sweep

Two kinds of question, three streams

The memory service in FAFOHive serves agents that ask two kinds of question: an exact identifier such as a function name, and a description of behaviour in plain language. A dense vector search alone misses the first and lexical search alone misses the second, so I made code search and decision search hybrid.

A query runs up to three streams at once (dense similarity on embeddings from a multilingual embedding model, weighted full-text search, and a metadata stream) and the ranked lists are fused with reciprocal-rank fusion. A classifier looks at each query first and sets how much each stream counts, because identifier queries and descriptive queries need different blends.

An identifier, such as a function name
lexical and symbol
meaning

exact-symbol handling lifts the chunk where it is defined

A description of behaviour
lexical and symbol
meaning
Widths show which side leads, not measured weights.

Holding up under agent load

After fusion, an optional cross-encoder rerank reorders the top results and a diversity pass drops near-duplicates, so an agent does not receive five copies of one paragraph. Capacity is part of the design: the embedding and rerank endpoints are bounded, and under load the reranker is the first stage dropped.

Default
embedthree streamsfusererankdiversity
Reranker saturated
embedthree streamsfusererank: skippedresults + flag
Keyword-only
no embedfull-textfuse
Dependency mode
→→callers, the hit, callees from the code graph

The graph side of the service is A code explainer that is not allowed to invent.

A baseline as strong as I could build

Capabilities model needed a bar to beat, and I ruled that the bar would be the strongest classical retriever I could build. That retriever is hybrid retrieval: dense embeddings fused with BM25 over the full tool catalog, with every weight and cutoff chosen by a sweep after an embedding-model bake-off.

I swept the baseline's constants, because a baseline tuned less carefully than the model it judges proves nothing.

Midway through the experiment a known-answer control failed to reproduce; the cause was a GPU precision setting that changed rankings relative to the CPU, and I pinned it off and re-ran the whole matrix. Every ranker in the experiment ran on both catalog sizes, so no comparison could pair a 42-tool model with a 2,000-entry baseline. The tie is the result I publish: The baseline that tied us.

Recall at 5
Model0.955Hybrid baseline0.949
Recall at 10
Model0.977Hybrid baseline0.977
Fifteen long, buried requests
Model0.67Hybrid baseline0.90

Bars on a 0 to 1 scale.

The embedding models, the reranker and BM25 are third-party; the fusion, routing, capacity behaviour and measurement are mine.