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