Benchmarks/Retrieval
Hybrid search: BM25 + vectors, alpha swept 0 to 1
Should you fuse BM25 with vector search, and with what weight?
α 0.8balanced blend: 0.782 / 0.753 / 0.722 MRR
Short answer: No single retriever wins everywhere. Pure BM25 beat pure vectors on exact code identifiers (0.772 vs 0.279 MRR). Pure vectors beat BM25 on paraphrased questions (0.768 vs 0.566). An RRF blend at alpha 0.8 kept all three query styles above 0.72.
- heading MRR
- identifier MRR
- paraphrase MRR
What the numbers say
- alpha = 1.0 is pure BM25, alpha = 0.0 is pure vectors.
- Identifier queries need BM25: vectors alone found the right chunk first only 20.7% of the time.
- Paraphrase queries peaked at alpha 0.4 (0.806 MRR).
MRR by alpha
| 0.0 | 0.491 | 0.279 | 0.768 |
| 0.2 | 0.581 | 0.471 | 0.794 |
| 0.4 | 0.642 | 0.569 | 0.806 |
| 0.5 | 0.679 | 0.696 | 0.751 |
| 0.6 | 0.710 | 0.735 | 0.731 |
| 0.8 | 0.782 | 0.753 | 0.722 |
| 0.9 | 0.813 | 0.768 | 0.678 |
| 1.0 | 0.859 | 0.772 | 0.566 |
hit@1 and hit@5 at selected alphas
| 0.0 | 0.207 | 0.397 | 0.667 | 0.933 |
| 0.4 | 0.515 | 0.656 | 0.667 | 0.967 |
| 0.8 | 0.662 | 0.889 | 0.533 | 0.933 |
| 1.0 | 0.692 | 0.889 | 0.367 | 0.867 |
Setup
FastAPI English docs (151 Markdown files, 2,713 heading-aware chunks), sentence-transformers 6.1.0 with all-MiniLM-L6-v2 (384-dim), Python 3.12.14, faiss-cpu 1.15.1. 773 heading queries, 305 exact-identifier queries, 30 hand-written paraphrase queries. Full script and raw output at the end.