Embeddings & Retrieval · 2 to 3 hours
Compare lexical and dense retrieval on fixtures
Rank four help articles by shared words and by cosine similarity, score both rankings against labels, and explain a dense miss and an accidental lexical success.
3 h
Overview
Compare lexical and dense retrieval using explicit relevance judgments and reproducible fixtures. You rank four articles both ways, score each ranking with precision and recall, and locate where a relevant item was lost before proposing a fix.
Study time: 2 to 3 hours
Interview format: Hands-on debugging with deterministic fixtures
By the end you can
- Implement lexical and cosine rankings with a deterministic tie rule
- Calculate precision@k, recall@k, and reciprocal rank from a ranked list
- Recognize a ranking that succeeds by accident rather than by evidence
- Identify the stage where a relevant item disappeared
- Explain why lexical and dense scores should not be added directly, and how rank fusion avoids it
Prerequisites
Helpful background: Basic TypeScript, JavaScript, or Python and arithmetic are enough.
This topic finds and ranks candidates. RAG & Data Pipelines covers ingestion, grounding, citations, and the document lifecycle.
Establish a retrieval contract
Define the searchable unit, eligible corpus, query preprocessing, ranking direction, tie behavior, and result count. Decide whether evaluation judgments apply to documents or passages. Multiple passages from one document should not accidentally count as several relevant documents when evaluation is document-level.
For this exercise, each item is one document with a stable ID. All items are eligible. Return at most two results, break equal scores by ID, and evaluate against explicit document-level labels. Production access control is a separate mandatory eligibility check.
Build a baseline before adding complexity
Start with a lexical baseline and an exact dense search baseline. Exact dense search gives a reference for later approximate-index tuning. Record model configuration, metric, normalization, and document revision along with results.
A simple term-overlap scorer can expose behavior on tiny fixtures. Use a production full-text ranking method such as BM25 when evaluating a real search stack. The exercise scorer below deliberately measures shared unique words only.
Understand cosine calculations
Cosine similarity is dot(query, document) / (norm(query) × norm(document)). Vectors must have matching dimensions, finite values, and nonzero length. A zero vector has no defined cosine similarity.
The fixture uses two-dimensional vectors to make calculations inspectable. Real embedding generation is intentionally replaced by supplied numbers so the exercise runs offline. These numbers illustrate ranking mechanics rather than model quality.
A reproducible ranking exercise
Four help articles, each one document with a stable ID. Every document is eligible.
| ID | Text | Vector |
|---|---|---|
| D1 | Reset your password using a recovery link | [1, 0] |
| D2 | Resolve E104 when a login token expires | [0.8, 0.6] |
| D3 | Download a billing invoice | [0, 1] |
| D4 | Change your profile display name | [-1, 0] |
Three queries, each with a supplied query vector and one relevant document.
| Query | Query vector | Relevant |
|---|---|---|
| forgot secret | [1, 0] | D1 |
| E104 | [1, 0] | D2 |
| billing invoice | [0, 1] | D3 |
Rules:
- Lexical score: lowercase both texts, split them into runs of letters and digits, and count the unique query words that also appear in the document. This measures shared words only; it is not BM25.
- Dense score: cosine similarity between the query vector and the document vector.
- Ranking: higher score first, equal scores broken by ascending ID, at most two results. Documents that score zero are still returned, so every query gets two results.
Code exercise
Lexical and dense ranking
Implement cosine, rankLexical, rankDense, precisionAtK, and recallAtK (snake_case names in Python) for the fixture above. Rankings return at most k IDs, highest score first, with equal scores broken by ascending ID. Cosine throws for empty, mismatched, non-finite, or zero vectors, and recall throws when there are no relevant documents.
Limitations
The vectors are hand-made fixtures, not model output, and the cosine helper is meant for small finite vectors of ordinary magnitude; production numerical handling should follow the chosen library. The lexical scorer counts shared unique words rather than BM25 and returns zero-score items to keep a fixed ranking. There is no approximate index, filtering, or fusion.
Predict the expected rankings
Predict the outcome
Predict the expected rankings
Trace each query by hand: write every document's lexical and cosine score, apply the tie rule, and keep two results. Then reveal the expected rankings.
| Query | Relevant | Lexical top two | Dense top two |
|---|---|---|---|
| forgot secret | D1 | ? | ? |
| E104 | D2 | ? | ? |
| billing invoice | D3 | ? | ? |
Calculate retrieval metrics
Precision@k is the number of relevant items in the first k ranks divided by k under this exercise's fixed-k convention. Recall@k is the number of relevant items retrieved divided by the total number of relevant items in the eligible corpus. If fewer than k results are returned, document whether precision uses k or the actual returned count.
The reciprocal rank of a query is 1 divided by the rank of its first relevant result. Mean reciprocal rank (MRR) averages reciprocal ranks across queries, with zero assigned when no relevant item appears within the evaluated result window. It emphasizes the first relevant hit. Recall is more useful when several pieces of evidence must be recovered.
When a query has no relevant items, recall has a zero denominator. Define a separate no-answer metric or exclusion rule instead of inventing a recall value. Report how many queries fall into that category.
Score the E104 rankings
Predict the outcome
Score the E104 rankings
Only D2 is relevant for the E104 query. Using your rankings from the exercise above and the fixed-k convention, work out which IDs fall inside each cutoff and the resulting precision and recall, then reveal the answers.
| Method and cutoff | IDs in the window | Precision | Recall |
|---|---|---|---|
| Dense, k = 1 | ? | ? | ? |
| Dense, k = 2 | ? | ? | ? |
| Lexical, k = 1 | ? | ? | ? |
Separate failure locations
| Failure | Diagnostic evidence | Possible correction |
|---|---|---|
| Relevant item is absent from the corpus | Stable-ID lookup fails | Fix ingestion or publication eligibility |
| Item exists but is filtered out | Metadata and effective filters | Correct metadata or filter logic |
| Exact dense search ranks it poorly | Exact baseline and source text | Improve representation or add lexical retrieval |
| Exact search finds it but approximate search misses it | Same query, metric, and eligibility set | Tune the approximate index |
| Candidate is retrieved but removed later | Stage-by-stage candidate IDs | Inspect fusion, deduplication, or reranking |
| Old version wins | Document revision and active-state metadata | Enforce freshness and revision rules |
Increasing top-k can help expose a relevant candidate at a lower rank, but it cannot recover an item that was never indexed or was excluded by policy. More results can also increase downstream cost and distract a generator.
Combine ranked lists carefully
Lexical and dense scores may have unrelated scales and distributions. Adding a BM25-like score of 12 to a cosine score of 0.8 has no automatic interpretation. Score normalization requires evaluation and can be unstable across queries.
Rank-based fusion is an alternative. Reciprocal rank fusion (RRF) adds contributions of 1 / (c + rank) for each list in which a document appears, using one-based ranks and a positive rank constant c. An absent document contributes zero. Candidate list size and c affect results.
When two lists hold the same two documents in opposite orders, such as lexical [A, B] and dense [B, A], equal-weight RRF gives both documents the same score, 1 / (c + 1) + 1 / (c + 2). A deterministic tie rule ensures reproducibility, but it does not resolve which document is relevant. Query-aware exact-code handling or a reranker may be needed.
Filtering and normalization checks
Use the same eligible set when comparing methods. Otherwise apparent quality differences may actually be permission or metadata differences. Apply authorization before any content reaches an external reranker or generator, and verify authorization again when fetching mutable records if required by the consistency model.
Check query and document model versions, dimensions, and normalization. Equal dimensions can still hide incompatible embeddings. If an engine reports distance, inspect its direction before sorting. A reversed sort can produce convincing-looking yet irrelevant results.
Completion checklist
- Reproduce the expected rankings for all three fixtures.
- Calculate dense precision@2 and recall@2 for E104.
- Explain why the lexical result for “forgot secret” is misleading.
- Locate a retrieval failure in a named stage before proposing a change.
Sources
- Sentence Transformers semantic search Explains embedding-based search and query and document encoding.
- Faiss metric types and distances Explains inner product, Euclidean distance, and cosine search on normalized vectors.
- Sentence Transformers retrieve and rerank Describes candidate retrieval followed by cross-encoder reranking.
- Elastic reciprocal rank fusion Documents combining ranked lists through reciprocal ranks.
The vectors, articles, queries, scores, timing budgets, exercises, and rubrics are original synthetic teaching material. They do not describe the measured performance of a named model or search engine. Study times and readiness thresholds are editorial estimates. Check the chosen embedding model's and search engine's current documentation before implementation.
Related on CodeSnatch
Lessons, problems, and articles that build the skills this question uses.
System Design
Shows the analyzer pipeline and BM25 that a shared-word scorer simplifies, and how hybrid queries fuse results.
Practice problem
Practice reporting each rate over a named denominator, with per-slice results and missing outputs kept visible.
AI Engineering
Applies stage-by-stage failure location to a RAG pipeline, from ingestion and eligibility to context packing.
DSA lesson
Covers set intersection, the operation behind a lexical score that counts unique shared query words.
Question bank
Drills multi-key comparators and top-N selection, the sort-then-slice that every ranking in this exercise performs.
Practice the interview question
Answer it in your own words before you look at the reference answer.
