🧮 How AI Ranks Better with RRF: The Genius of Merging Search Results


🧠 What Is Reciprocal Rank Fusion?
Reciprocal Rank Fusion (RRF) is a ranking algorithm that combines the results from multiple queries (like in Fan-Out retrieval). Instead of picking one “best” result per query, RRF fuses all results by scoring them based on how high they appear in each list — giving more weight to results that consistently rank well.
Think of it like crowd voting — the chunks that show up most often and highest in multiple lists rise to the top.
🧰 Why Do We Need RRF?
When you use techniques like Fan-Out Retrieval, you end up with multiple lists of relevant chunks. But:
They may overlap.
Some chunks might appear low in one list but high in another.
You want to merge and rank them smartly.
That's where RRF shines.
🔢 How RRF Scoring Works
For each retrieved chunk, we use this scoring formula:
RRFscore=∑(1/(k+rank))RRF_score = ∑ (1 / (k + rank)) RRFscore=∑(1/(k+rank))
Where:
k is a constant (often 60 to avoid divide-by-zero).
rank is the position in the retrieved list (1 = top).
Higher scores = better relevance across multiple lists.
📘 Example Scenario
Suppose you have 3 query variations:
“What is machine learning?”
“How does machine learning work?”
“Intro to ML”
Each retrieves 5 chunks. Some chunks show up in multiple results — RRF helps us merge these lists into one ranked list of top content chunks.
💻 Python Code: Implementing RRF with LangChain + Qdrant
from collections import defaultdict
from langchain.vectorstores import Qdrant
from qdrant_client import QdrantClient
from langchain.embeddings import OpenAIEmbeddings
from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
# Initialize components
qdrant_client = QdrantClient(url="http://localhost:6333")
embedding_model = OpenAIEmbeddings()
vector_store = Qdrant(client=qdrant_client, collection_name="my_collection", embeddings=embedding_model)
llm = ChatOpenAI()
# Prompt template to generate similar queries
prompt_template = PromptTemplate(
input_variables=["query"],
template="Generate 3 semantically similar queries to: {query}"
)
llm_chain = LLMChain(llm=llm, prompt=prompt_template)
# Original query
user_query = "What is machine learning?"
query_variants = llm_chain.run(user_query).split('\n')
# Retrieve and store ranked chunks for each variant
all_ranked_results = []
for query in query_variants:
results = vector_store.similarity_search_with_score(query, k=5)
all_ranked_results.append(results)
# RRF scoring
rrf_scores = defaultdict(float)
k = 60 # Constant in the formula
for result_set in all_ranked_results:
for rank, (doc, _) in enumerate(result_set):
doc_id = doc.page_content
rrf_scores[doc_id] += 1 / (k + rank)
# Sort by RRF score
sorted_docs = sorted(rrf_scores.items(), key=lambda x: x[1], reverse=True)
# Display top results
print("📄 Top Ranked Chunks by RRF:")
for doc_id, score in sorted_docs[:5]:
print(f"Score: {score:.4f} | Chunk: {doc_id}")
✅ Pros and ❌ Cons of Reciprocal Rank Fusion
Pros 👍 | Cons 👎 |
Smart merging of results across queries | Adds extra computation and logic |
Reduces noise from one-off irrelevant chunks | May promote less relevant chunks if they appear frequently |
Simple and effective scoring formula | Doesn’t consider chunk content, just position |
Great for Fan-Out or Decomposition combination | Needs enough overlapping chunks to be effective |
Easy to implement in vector DB pipelines | Rare chunks might be unfairly penalized |
🎯 Best Use Cases
Fan-Out Retrieval: Merge similar query outputs smartly.
Multi-step Chains: Combine results from decomposed queries.
Summarization Pipelines: Ensure best content is passed to LLMs.
🔜 Next Up: Blog 4 – Zoom In or Out: Query Decomposition for Smarter Retrieval
Thank you for reading our article! We appreciate your support and encourage you to follow us for more engaging content. Stay tuned for exciting updates and valuable insights in the future. Don't miss out on our upcoming articles—stay connected and be part of our community!
YouTube : youtube.com/@mycodingjourney2245
LinkedIn : linkedin.com/in/nidhi-jagga-149b24278
GitHub : github.com/nidhijagga
HashNode : https://mycodingjourney.hashnode.dev/
A big shoutout to Piyush Garg Hitesh Choudhary for kickstarting the GenAI Cohort and breaking down the world of Generative AI in such a simple, relatable, and impactful way! 🚀
Your efforts are truly appreciated — learning GenAI has never felt this fun and accessible. 🙌
#ChaiCode #ChaiAndCode #GenAI #ChaiAndCode #RRF #ReciprocalRankFusion #AIRelevance #SearchRanking #LangChainTips #GenAI #ChaiCode #ChaiAndCode #LLMInfra
Subscribe to my newsletter
Read articles from Nidhi Jagga directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
