Why raw score blending is fragile
Dense retrieval ranks records by the relationship between an embedding for the query and embeddings for stored content. Sparse retrieval with BM25 ranks records from term occurrences and weighting rules. Both produce an ordered list, but their numeric scores do not inherently mean the same thing.
A fixed formula such as dense_score + bm25_score can therefore behave unpredictably. A small change to an embedding model, document chunking strategy, analyzer, or BM25 configuration may alter score distributions and silently change which retrieval mode dominates the combined ranking.
- Dense search can retrieve paraphrases and conceptually related passages.
- BM25 can strongly reward exact identifiers, error messages, names, and rare terms.
- Score ranges may vary between queries as well as between retrieval methods.
Fuse ranks instead of scores
RRF replaces raw-score comparison with a simple rank-based contribution. Retrieve a candidate list from dense search and another from BM25, then assign each result a contribution based on its position in each list. A document appearing near the top of either list receives more credit than one appearing near the bottom.
For each document d, calculate RRF(d) = sum of 1 divided by k plus rank_i(d), across the retrieval lists where d appears. Here, rank_i starts at 1 and k is a constant chosen to reduce the difference between nearby ranks. Sort documents by the resulting fused score.
- Deduplicate results by a stable document or chunk identifier before presenting the final list.
- Use the same query text for both retrieval paths unless your application intentionally reformulates queries.
- Choose candidate depths large enough to create useful overlap and complementary coverage.
- Treat k as a tuning parameter, not as a universal constant.
Apply the pattern with Talqora's retrieval building blocks
Talqora uses regional S3 Vectors for dense search and Quickwit BM25 for sparse search. A hybrid application flow can issue a dense request against the vector representation of the query and a BM25 request against the original text, then perform RRF in the application layer over the two returned rankings.
Log the source rank, fused rank, and retrieval path for each selected result. These traces make debugging practical: they show whether a result won because it was semantically close, because it matched important terms, or because both methods independently surfaced it. Evaluate changes with representative queries that include natural-language questions, exact identifiers, and mixed queries.
- Keep retrieval metadata with each chunk so fused results can be filtered or grouped consistently.
- Inspect queries where dense and BM25 disagree; these are often the most informative tuning cases.
- Use human relevance judgments or application outcomes to assess ranking changes.
- Re-test fusion after changing embedding models, chunking, or sparse indexing settings.
