Lexical and Dense Ranking
Part of AI Engineering: Compare lexical and dense retrieval on fixtures
Lexical and Dense Ranking
A help center compares two ways of ranking its articles for a query: lexical matching on shared words, and dense ranking on supplied embedding vectors. It then scores each ranking against labeled relevant articles. Implement the five helpers below.
| Function | Returns |
|---|---|
cosine(a, b) | Cosine similarity: dot(a, b) / (norm(a) * norm(b)) |
rankLexical(items, query, k) | IDs of the top k items by lexical score |
rankDense(items, queryVector, k) | IDs of the top k items by cosine similarity to queryVector |
precisionAtK(ranked, relevant, k) | Relevant IDs found in the first k ranks, divided by k |
recallAtK(ranked, relevant, k) | Relevant IDs found in the first k ranks, divided by the number of relevant IDs |
Each item is { id, text, vector }. ranked and relevant are arrays of IDs.
Rules
- Lexical score. Lowercase the query and the item text, then split each into runs of letters and digits (
[a-z0-9]+). The score is the number of unique query words that also appear in the item text. For example, the query"Billing billing INVOICE"scores 2 against"Download a billing invoice.". - Ranking. Higher score first. Break equal scores by ascending ID, using plain string comparison. Return at most
kIDs, or every ID when there are fewer thankitems. Items that score zero are still returned. - Cosine. Throw an error when the vectors are empty or have different lengths, when any value is not finite (
NaNor infinity), or when either vector has zero length: cosine is undefined for a zero vector. - Metrics. A relevant ID counts once, even if it appears twice in the ranking. Precision always divides by
k, even when the ranking holds fewer thankIDs. Recall divides by the number of relevant IDs; when there are none, recall is undefined, so throw an error. You may assumekis a positive integer andrelevanthas no duplicates.
Fixtures
Every document is eligible and labels are document-level.
| 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] |
With k = 2:
| Query | Query vector | Relevant | Lexical top two | Dense top two |
|---|---|---|---|---|
| forgot secret | [1, 0] | D1 | D1, D2 | D1, D2 |
| E104 | [1, 0] | D2 | D2, D1 | D1, D2 |
| billing invoice | [0, 1] | D3 | D3, D1 | D3, D2 |
In Python, implement cosine, rank_lexical, rank_dense, precision_at_k, and recall_at_k. Items are dicts with "id", "text", and "vector" keys, and every error is a ValueError.
MEDIUM
AI Engineering
Semantic Search
Full-Text Search
Ranking
Intermediate
0 views
Solution
Hints
Hint 1
Hint 2
Premium
Hint 3
Premium
This section is available for CodeSnatch Premium members only.
