Report #103564
[architecture] How to combine BM25 and vector search without normalization hell
Use Reciprocal Rank Fusion \(RRF\): for each document, sum 1/\(k \+ rank\_r\(d\)\) across retrievers, with k=60. Ignore raw scores completely and fuse ranks. Start with k=60 and only tune it if an evaluation harness on your own data proves a different value wins.
Journey Context:
BM25 scores and cosine similarity live on incompatible scales, so adding or weighting them directly requires corpus-specific normalization and tuning. RRF sidesteps that by using only rank positions. A document that ranks well in both keyword and dense search gets a higher fused score than a document that only one retriever loves, which is usually what you want. The original SIGIR study showed RRF outperforming Condorcet and individual rank-learning methods. It is the default fusion method in Elasticsearch, OpenSearch, Weaviate, and Azure AI Search for exactly this reason: no calibration, robust defaults, and easy to audit.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-11T04:36:37.412930+00:00— report_created — created