Module 3: Essential Features for RAG
Capsule 03: Hybrid Search (Keyword + Semantic)
🎯 Capsule objective
Understand WHY pure semantic search fails on certain queries, how hybrid search (BM25 + vector) improves accuracy 15-20%, and when to use each strategy.
By the end of this capsule:
- ✅ You'll explain the limitations of pure semantic search
- ✅ You'll understand how hybrid search combines keyword + semantic
- ✅ You'll compare ranking strategies (RRF, weighted fusion)
- ✅ You'll decide when to use hybrid vs pure semantic
Estimated time: 10-12 minutes
🔍 Problem: Pure Semantic Search fails on specific queries
What is semantic search?
Semantic search = Searching by meaning (embeddings) instead of exact words.
Example:
Query: "automobile repair"
Embedding: [0.2, 0.5, 0.8, ...]
Top results (semantic):
1. "Car maintenance guide" ✅ (similar meaning)
2. "Vehicle troubleshooting" ✅ (similar meaning)
3. "How to fix your vehicle" ✅ (similar meaning)
Advantage: Finds conceptually similar documents (not just exact keyword matches).
But... semantic search fails on specific queries
Problem 1: Proper nouns
Query: "GPT-4 API documentation"
Embedding: [0.1, 0.7, 0.3, ...]
Pure semantic results:
1. "OpenAI models overview" ⚠️ (mentions GPT-3, Claude)
2. "API integration guide" ⚠️ (general, no GPT-4)
3. "Language model comparison" ⚠️ (GPT-3 vs PaLM)
Expected:
1. "GPT-4 API reference" ← Missing because "GPT-4" didn't dominate the embedding
Why it fails: "GPT-4" is a proper noun (a specific token), but the embedding captures the general concept "language model API".
Problem 2: IDs, codes, exact numbers
Query: "Invoice #INV-2024-001234"
Pure semantic results:
1. "Invoice management guide" ❌
2. "Billing documentation" ❌
3. "Payment processing" ❌
Expected:
1. Invoice #INV-2024-001234 ← Missing because the embedding doesn't capture the exact ID
Why it fails: Embeddings aren't designed to capture exact strings (they're semantic representations).
Problem 3: Queries with typos or exact variants
Query: "PostgreSQL"
Pure semantic results:
1. "Database management" ✅ (general)
2. "SQL tutorial" ✅ (general)
3. "MySQL guide" ⚠️ (a different DB!)
Missing:
- "PostgreSQL installation" ← Should be #1
Why it fails: The embeddings of "PostgreSQL" and "MySQL" are similar (both are SQL databases).
🔀 Solution: Hybrid Search (BM25 + Vector)
What is hybrid search?
Hybrid search = Combining keyword search (BM25) + semantic search (vector) to get the best of both worlds.
Keyword search (BM25):
- Finds exact keyword matches
- Excellent for proper nouns, IDs, codes
- Terrible for synonyms, concepts
Semantic search (Vector):
- Finds similar concepts
- Excellent for conceptual queries
- Terrible for exact matches
Hybrid = Keyword + Semantic:
- Combines results from both
- Ranks using a fusion algorithm (RRF, weighted)
Hybrid Search architecture
User Query: "GPT-4 API documentation"
│
├─────────────────┬─────────────────┐
↓ ↓ ↓
[Keyword Search] [Semantic Search]
(BM25) (Vector HNSW)
│ │
1. GPT-4 docs 1. OpenAI API guide
2. API reference 2. LLM integration
3. OpenAI guide 3. GPT-3 docs
│ │
└─────────────────┴─────────────────┐
↓
[Fusion Algorithm]
(RRF or Weighted)
↓
Merged Top-10:
1. GPT-4 API docs ✅
2. OpenAI API guide ✅
3. GPT-4 reference ✅
Key: Keyword captures the exact "GPT-4", Semantic captures the concept "API documentation".
📊 Benchmark: Pure Semantic vs Hybrid
Scenario: Technical Documentation RAG
Setup:
- Database: 100K technical docs
- Queries: 1000 test queries (mix of conceptual + specific)
- Metric: MRR (Mean Reciprocal Rank) + NDCG@10
Test A: Pure Semantic Search
results = db.query(
query_embedding=embed(query),
k=10
)
Results:
- Conceptual queries: 92% accuracy ✅
- Specific queries (names, IDs): 68% accuracy ❌
- Overall: 78% accuracy
Typical failures:
- "GPT-4 docs" → Returns GPT-3 docs
- "React 18 features" → Returns general React
- "Invoice #12345" → Not found
Test B: Pure Keyword Search (BM25)
results = bm25_search(query, k=10)
Results:
- Specific queries: 95% accuracy ✅
- Conceptual queries: 55% accuracy ❌
- Overall: 72% accuracy
Typical failures:
- "automobile repair" → Doesn't find "car maintenance" (synonym)
- "password reset" → Doesn't find "credential recovery" (similar concept)
Test C: Hybrid Search (BM25 + Vector)
# Keyword results
keyword_results = bm25_search(query, k=20)
# Semantic results
semantic_results = db.query(
query_embedding=embed(query),
k=20
)
# Fusion (RRF)
final_results = reciprocal_rank_fusion(
[keyword_results, semantic_results],
k=10
)
Results:
- Conceptual queries: 91% accuracy ✅ (almost equal to pure semantic)
- Specific queries: 94% accuracy ✅ (almost equal to pure keyword)
- Overall: 92% accuracy ✅
Gain: 14% improvement vs pure semantic, 20% vs pure keyword.
🔧 Fusion Algorithms
1. Reciprocal Rank Fusion (RRF)
Definition: Assign a score based on position (rank) in each list.
Formula:
RRF_score(doc) = Σ (1 / (k + rank_i))
where:
- k = constant (typically 60)
- rank_i = position of the doc in list i (1-indexed)
Example:
Keyword results:
1. Doc A (rank=1)
2. Doc B (rank=2)
3. Doc C (rank=3)
Semantic results:
1. Doc B (rank=1)
2. Doc D (rank=2)
3. Doc A (rank=3)
RRF scores:
Doc A: 1/(60+1) + 1/(60+3) = 0.0164 + 0.0159 = 0.0323
Doc B: 1/(60+2) + 1/(60+1) = 0.0161 + 0.0164 = 0.0325 ← Highest
Doc C: 1/(60+3) + 0 = 0.0159
Doc D: 0 + 1/(60+2) = 0.0161
Final ranking: B, A, D, C
Advantages:
- ✅ No need to normalize scores (only ranks)
- ✅ Robust to outliers (one very high score doesn't dominate)
- ✅ Simple to implement
Disadvantages:
- ❌ Doesn't consider the magnitude of scores (only position)
- ❌ Can penalize docs with a high score but low rank
Used by: Weaviate (default)
2. Weighted Score Fusion
Definition: Combine normalized scores with weights.
Formula:
Final_score(doc) = α × keyword_score + (1-α) × semantic_score
where:
- α = weight for keyword (typically 0.3-0.7)
- keyword_score, semantic_score = normalized [0,1]
Example:
Keyword results:
Doc A: score=0.9
Doc B: score=0.7
Doc C: score=0.5
Semantic results:
Doc A: score=0.6
Doc B: score=0.9
Doc D: score=0.8
Weighted (α=0.5):
Doc A: 0.5×0.9 + 0.5×0.6 = 0.75
Doc B: 0.5×0.7 + 0.5×0.9 = 0.80 ← Highest
Doc D: 0.5×0 + 0.5×0.8 = 0.40
Doc C: 0.5×0.5 + 0.5×0 = 0.25
Final ranking: B, A, D, C
Advantages:
- ✅ Considers the magnitude of scores
- ✅ Flexible (adjust α based on query type)
- ✅ Intuitive
Disadvantages:
- ❌ Requires normalizing scores (BM25 and cosine similarity have different ranges)
- ❌ Sensitive to outliers
Used by: Pinecone (custom), Elasticsearch
RRF vs Weighted: Which to choose?
| Criterion | RRF | Weighted |
|---|---|---|
| Simplicity | ✅ Simple | ⚠️ Requires normalization |
| Robustness | ✅ Robust to outliers | ❌ Sensitive |
| Flexibility | ❌ Fixed (not adjustable) | ✅ Adjustable (α) |
| Performance | ✅ Similar | ✅ Similar |
| Recommended | Default (Weaviate) | Custom tuning (Pinecone) |
Recommendation: Start with RRF (simple, robust). Move to weighted if you need fine control.
🎯 When to use Hybrid vs Pure Semantic
Decision Tree
┌─────────────────────────────────────────┐
│ Does your query contain proper nouns, │
│ IDs, codes, or very specific terms? │
│ │
└─────────────────────────────────────────┘
│
┌──────────┴──────────┐
│ │
Yes No
│ │
↓ ↓
┌──────────────┐ ┌─────────────────┐
│ Hybrid Search│ │ Pure Semantic │
│ (BM25 + Vec) │ │ (Vector only) │
└──────────────┘ └─────────────────┘
Examples: Examples:
- "GPT-4 docs" - "car repair"
- "Invoice #123" - "fix bug"
- "React 18" - "improve performance"
- "user_id: abc" - "reduce latency"
Use cases: Hybrid Search
1. Technical Documentation
Query: "Kubernetes 1.28 ingress"
→ Hybrid captures exact "Kubernetes 1.28" + the concept "ingress"
2. E-commerce Product Search
Query: "Nike Air Max red size 10"
→ Hybrid captures exact "Nike Air Max" + the concept "red shoes"
3. Legal Document Search
Query: "Case #2024-CV-12345"
→ Hybrid captures the exact case number
4. Code Search
Query: "def authenticate_user()"
→ Hybrid captures the exact function name
Use cases: Pure Semantic
1. Conceptual Queries
Query: "How to improve database performance?"
→ Semantic captures the concept (optimization, indexes, caching)
2. Ambiguous Queries
Query: "fix connection issues"
→ Semantic captures multiple interpretations (network, DB, API)
3. Synonyms Expected
Query: "automobile maintenance"
→ Semantic finds "car repair", "vehicle service"
🏭 Hybrid Search in Vector Databases
Weaviate (native Hybrid Search)
# Weaviate supports hybrid search out-of-the-box
results = client.query.get("Document", ["content"])\
.with_hybrid(
query="GPT-4 API documentation",
alpha=0.5 # 0=pure keyword, 1=pure vector
)\
.with_limit(10)\
.do()
# Fusion: RRF (default)
Advantage: Built-in, no custom code.
Pinecone + Keyword Search (Custom)
# Pinecone doesn't have native hybrid
# Option 1: Combine with Elasticsearch
# 1. Keyword search in Elasticsearch
keyword_results = es.search(
index="docs",
body={"query": {"match": {"content": query}}}
)
# 2. Semantic search in Pinecone
semantic_results = pinecone_index.query(
vector=embed(query),
top_k=20
)
# 3. Manual fusion
final_results = weighted_fusion(keyword_results, semantic_results, alpha=0.5)
Disadvantage: Requires 2 systems (Pinecone + ES).
ChromaDB + BM25 (Custom implementation)
# ChromaDB doesn't have native hybrid
# Implement BM25 manually
from rank_bm25 import BM25Okapi
# 1. Index documents with BM25
corpus = [doc['content'] for doc in documents]
tokenized_corpus = [doc.split() for doc in corpus]
bm25 = BM25Okapi(tokenized_corpus)
# 2. Keyword search
tokenized_query = query.split()
keyword_scores = bm25.get_scores(tokenized_query)
# 3. Semantic search
semantic_results = collection.query(
query_embeddings=[embed(query)],
n_results=20
)
# 4. Fusion (RRF)
final_results = rrf_fusion(keyword_scores, semantic_results)
Disadvantage: Requires a custom implementation.
📊 Impact on Accuracy: A real example
Scenario: API Documentation RAG
Dataset: 50K API documentation pages (OpenAI, Anthropic, AWS, Azure)
Test queries (100):
- 50 conceptual: "How to handle rate limits?"
- 50 specific: "GPT-4 turbo pricing"
Pure Semantic
Conceptual queries: 94% accuracy
Specific queries: 72% accuracy ← Fails on "GPT-4 turbo"
Overall: 83%
Hybrid (α=0.5)
Conceptual queries: 92% accuracy (similar)
Specific queries: 96% accuracy ← Improves 24%
Overall: 94%
Gain: 11% overall, 24% on specific queries.
✅ Comprehension checklist
Verify that you understood this capsule:
-
Why does pure semantic search fail on "GPT-4 API docs"?
- Answer: The embedding captures the general concept "API documentation" but doesn't prioritize the exact name "GPT-4". Keyword search captures the exact "GPT-4".
-
What is hybrid search?
- Answer: Combining keyword search (BM25) + semantic search (vector) using a fusion algorithm (RRF or weighted).
-
What is RRF?
- Answer: Reciprocal Rank Fusion. It assigns a score based on position (rank) in each list. Formula: 1/(60+rank).
-
When to use hybrid vs pure semantic?
- Answer: Hybrid if the query has proper nouns, IDs, codes. Pure semantic if the query is conceptual/ambiguous.
-
What's the typical accuracy improvement of hybrid?
- Answer: 15-20% overall, 20-30% on specific queries.
If you answered 4-5/5 correctly → ✅ Ready for Capsule 04 (Multi-tenancy)
🔗 Connection with RAG
How does hybrid search improve your RAG?
Case A: Technical Docs Chatbot
Pure semantic:
User: "Show me Kubernetes 1.28 networking changes"
RAG: Returns general Kubernetes networking (mix of versions)
LLM: Response contaminated with info from old versions
Hybrid:
User: "Show me Kubernetes 1.28 networking changes"
RAG: Returns docs specific to v1.28 (keyword match) + networking concepts
LLM: Precise and up-to-date response
Case B: E-commerce Search
Pure semantic:
User: "Nike Air Jordan 1 Retro High OG"
RAG: Returns general Nike shoes (Jordan 1, 3, 4...)
Hybrid:
User: "Nike Air Jordan 1 Retro High OG"
RAG: Returns exactly "Jordan 1 Retro High OG" (exact keyword match)
🚀 Next step
You now know the 2 most critical features: Metadata filtering and Hybrid search. Now you'll learn feature #3 for SaaS: Multi-tenancy.
Next capsule: 04 - Multi-tenancy (Data isolation)
You'll learn:
- Multi-tenancy strategies (collection per tenant, metadata filtering, namespace)
- Security considerations (data leakage prevention)
- Performance trade-offs (horizontal vs vertical scale)
- When it's critical (SaaS, enterprise RAG)
Key: Multi-tenancy is essential for SaaS RAG (isolating data per customer).
Reading time: 10-12 minutes
Next: 04-multi-tenancy.md