Predict the RRF (Reciprocal Rank Fusion) output ranking given these two retrievers' results.
You're combining two retrievers via Reciprocal Rank Fusion with k=60 (the standard). Dense retriever returns (in rank order): rank 1: chunk_A rank 2: chunk_B rank 3: chunk_C rank 4: chunk_D BM25 retriever returns (in rank order): rank 1: chunk_E rank 2: chunk_A rank 3: chunk_F rank 4: chunk_B RRF formula per chunk: score(c) = sum over retrievers of 1 / (k + rank_in_that_retriever). Unseen chunks in a retriever contribute 0 from that retriever. Question: what's the final RRF-ranked top-4?
Sum 1/(60+rank) per retriever for each chunk. chunk_A wins on consensus (in both lists) over chunk_E, which tops only BM25. Final top-4: A, B, E, C.
Imagine two judges ranking the same contestants. Reciprocal Rank Fusion gives each contestant points based on where each judge placed them: rank 1 is worth a bit more than rank 2, and so on, but the gaps are tiny because we add a big buffer (60) to every rank. Then you add up a contestant's points from both judges. A contestant who placed second with both judges beats one who placed first with only one judge and was ignored by the other. Two agreeing judges outweigh one enthusiastic judge. That is the whole trick: it rewards contestants both lists agree on, and it never has to compare the judges' raw scores, which might be on totally different scales.
Detailed answer & concept explanation~6 min readEverything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example.
Everything important, quickly.
4 min: compute all six chunk scores, explain why consensus beats single rank-1, the role of k, and the chunk_C/chunk_F tie.
from collections import defaultdict
def rrf(rankings, k=60):
# rankings: list of retriever outputs, each an ordered list of chunk ids
scores = defaultdict(float)
for ranked_list in rankings:
for rank, doc in enumerate(ranked_list, start=1): # ranks are 1-indexed
scores[doc] += 1.0 / (k + rank)
return sorted(scores.items(), key=lambda kv: kv[1], reverse=True)
dense = ["chunk_A", "chunk_B", "chunk_C", "chunk_D"]
bm25 = ["chunk_E", "chunk_A", "chunk_F", "chunk_B"]
for doc, score in rrf([dense, bm25])[:4]:
print(f"{doc}: {score:.5f}")
# chunk_A: 0.03252 chunk_B: 0.03175 chunk_E: 0.01639 chunk_C: 0.01587 (C/F tie broken by sort)Real products, models, and research that use this idea.
- Elasticsearch and OpenSearch both ship a native RRF retriever to fuse BM25 with dense kNN results in hybrid search.
- Weaviate's hybrid search supports a ranked fusion mode that combines keyword (BM25F) and vector results.
- Qdrant's Query API exposes RRF as a built in fusion method for multi-vector and hybrid pipelines.
- LangChain's EnsembleRetriever uses Reciprocal Rank Fusion to merge several retrievers with configurable weights.
What an interviewer would ask next. Try answering before peeking at the approach.
QHow does the choice of k change which chunks win, and what happens as k approaches 0 or infinity?
QWhen would you add per-retriever weights to RRF instead of treating both lists equally?
QRRF ignores raw scores entirely. When is that a liability rather than a virtue?
Don't say thisRed flags and common mistakes that signal junior thinking. Click to expand.
Red flags and common mistakes that signal junior thinking. Click to expand.
Assuming the chunk that ranks #1 in one retriever wins overall. RRF rewards consensus: a chunk ranked highly in both lists beats a chunk that tops only one.
The night-before-the-interview bullets. Scan these on the way to the call.
Primary sources. Skim if you want the original framing.
Same topic, related formats. Practice these next.