0
RAG Engineering
Phase 3Module 7 of 18

Hybrid Search

Vector search fails on exact matches: product SKUs, error codes, legal citations, person names, and rare technical terms. BM25 fails on paraphrases. Hybrid search gives the best of both — the default architecture for production RAG in 2024+.

Hybrid search is like finding a restaurant using both 'similar cuisine' recommendations (semantic) and 'exactly named on the sign' lookup (keyword) — together you never miss the right place.

Visual Workflows

Start here — study each diagram, then use + / to zoom if needed.

100%
Loading diagram...

Scroll inside the frame · use + / − to zoom

Key Takeaways

  • 1.Hybrid search combines dense vector retrieval (semantic similarity) with sparse keyword retrieval (BM25) and fuses results — capturing both meaning-based matches and exact keyword/symbol matches that embeddings miss.
  • 2.Pipeline: run vector search (top-k₁) and BM25 search (top-k₂) in parallel → fusion algorithm combines scores → optional re-ranker refines top results.
  • 3.Fusion methods: Reciprocal Rank Fusion (RRF, most popular — rank-based, no score normalization needed), weighted linear combination (requires score normalization), and convex combination.
  • 4.RRF score = Σ 1/(k + rank_i) where k=60 typically.
  • 5.Production: tune k₁ and k₂ independently, A/B test hybrid vs pure vector on your eval set, and monitor which leg contributes to final results.

Real Example

Scenario

Query: 'error ECONNREFUSED in payment service'. BM25 matches the exact error code in logs. Vector search finds semantically related troubleshooting docs. RRF fusion surfaces both — neither alone would rank the combined result set optimally.

What you would do

In RAG Engineering, apply Hybrid Search to this scenario: Query: 'error ECONNREFUSED in payment service'. Identify the inputs, run the technique, validate the output, and note one thing you would monitor in production.

Practice Task

Open the Code Walkthrough below and run it locally. Change one parameter related to Hybrid Search (e.g. model, temperature, top_k, or tool name), observe the difference in output, and write 2–3 sentences explaining what changed.

Code Walkthrough

Highlighted lines show where Hybrid Search happens in the code.

Hybrid Search
1def reciprocal_rank_fusion(results_lists: list[list[str]], k: int = 60) -> list[tuple[str, float]]:  # define a reusable function2  scores: dict[str, float] = {}3  for results in results_lists:4    for rank, doc_id in enumerate(results):5      scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank + 1)6  return sorted(scores.items(), key=lambda x: x[1], reverse=True)  # return the result7
8vector_ids = ["doc_a", "doc_c", "doc_b"]  # from ANN search9bm25_ids = ["doc_b", "doc_d", "doc_a"]   # from BM2510fused = reciprocal_rank_fusion([vector_ids, bm25_ids])11# doc_a and doc_b score highest (appear in both lists)

Cheat Sheet

Quick recap

quick ref
  • RRF k=60 default
  • Parallel vector + BM25
  • Vector=meaning, BM25=exact
  • Fuse top-20 → return top-10
  • Re-rank after fusion
  • A/B test before deploying

Common Mistakes

  • Averaging incomparable scores from vector and BM25 directly
  • Only using vector search for technical/support corpora
  • Not running searches in parallel — doubles latency unnecessarily
  • Skipping eval on keyword-heavy query subset
  • Fusing too many candidates without re-ranking — noise in context