Query Understanding and Hybrid Retrieval
~45 min read
How to process a user's raw query into a structured signal for retrieval, and why hybrid retrieval (BM25 + semantic) outperforms either method alone.
Why Query Understanding Matters
The query is the user's highest-signal input to the system. Misunderstanding the query means the entire downstream pipeline is optimizing for the wrong target.
Query quality issues you must handle:
- Spelling errors: '15% of queries have a misspelling' (Google data)
- Vocabulary mismatch: 'couch' vs. 'sofa' vs. 'divan'
- Incomplete intent: 'boots' without specifying category or use case
- Mixed intent: 'apple iphone 15 case' (product search + brand + model)
Query Understanding Pipeline (in order):
1. Text normalization (always):
def normalize(query: str) -> str: return query.strip().lower() # + unicode NFKC normalization
2. Spell correction: Methods: (a) dictionary + edit distance (Peter Norvig's algorithm) (b) Noisy channel model: P(intended | typed) ∝ P(typed | intended) × P(intended) (c) Seq2Seq neural: T5 or encoder-decoder for complex corrections Key: don't over-correct ('python' should not be corrected even though it's a snake)
3. Query expansion: Goal: increase recall by retrieving more relevant documents. Methods:
- Rule-based synonyms: curated synonym dictionary (high precision, low coverage)
- Word embedding expansion: find words with high cosine similarity to query terms
- Pseudo-relevance feedback: take top-K BM25 results, extract key terms, re-query
- Learned expansion: seq2seq model that generates expanded query from original
4. Intent classification (route to specialized handlers): Classes: product_search, brand_search, category_browse, informational Each class may warrant different retrieval strategies and result page templates
5. Query embedding (for semantic retrieval): Use a bi-encoder (same architecture as two-tower candidate generation):
- Encode full query string → dense vector (256-768d)
- This vector is the query representation for FAISS ANN search
Why BM25 + Semantic > Either Alone
BM25 excels at:
- Exact keyword matches: 'Nike Air Max 90 white size 10'
- Rare/specific terms: 'GE WX09X10004 water filter'
- Navigational queries where the user knows exactly what they want
Semantic retrieval excels at:
- Conceptual matches: 'comfortable walking shoes' → 'ergonomic footwear'
- Vocabulary mismatch: 'screen protector' → 'tempered glass'
- Natural language queries: 'something to keep my feet dry in rain'
Hybrid merge with Reciprocal Rank Fusion (RRF):
def rrf_score(bm25_rank: int, sem_rank: int, k: int = 60) -> float: return 1/(k + bm25_rank) + 1/(k + sem_rank) # Items appearing in both lists get a combined boost # Items appearing in only one list still contribute from that source
💬 Deep Dive with AI
Key points
- •Query understanding (spell correction + expansion + intent classification) is the highest-ROI investment in search quality — a misspelled query returns zero-results until corrected
- •BM25 and semantic retrieval are complementary, not competing: BM25 wins on exact/rare terms, semantic wins on vocabulary mismatch; hybrid with RRF reliably outperforms either alone
- •Query expansion improves recall but must be controlled — over-expansion ('apple' → includes 'apple fruit') creates noisy retrieval that degrades ranking precision