Skip to content

< all problems47 · Level 02, Search

Fuse BM25 and Dense Search With RRF

medium · implement · Embeddings & Retrieval

BM25 ranks documents by exact words; dense search ranks them by meaning. Their scores live on different scales, so merge the ranks, not the scores.

Implement rrf(rankings, k=60), reciprocal rank fusion. rankings is a list of ranked lists of document ids. Each document's fused score is the sum, over every ranking it appears in, of 1 / (k + rank), with rank starting at 1. Return the ids ordered by fused score, highest first; break exact ties by id so the output is stable.

Then hybrid_search(query, docs, k=3): BM25 ranking from the provided bm25_rank, dense ranking from the provided dense_rank, fused with rrf, top k documents back.

A document ranked first by both gets 2/(k+1), the most possible; one ranked first by a single ranker still gets 1/(k+1), which usually beats anything ranked fifth by both. k=60 is the value from the original paper.