Reciprocal rank fusion
Lesson: Hybrid Retrieval with BM25 and Dense EmbeddingsCheat sheetTrack: RAG building blocks
Problem
Reciprocal rank fusion (RRF) merges ranked lists from different retrievers into one list. It uses only the rank of each document, not the raw score. A BM25 score and a cosine similarity have different scales, but their ranks are comparable. Hybrid search uses RRF to merge keyword and vector results.
Task
Write two functions.
rrf_scores(rankings, k=60, weights=None)returns the fused score of each document.fuse(rankings, k=60, weights=None)returns the documents sorted by fused score.
Each ranking is a list of document ids, best first. The first document of a list has rank 1. The fused score of document d is
The sum runs over the lists that contain d. A list that does not contain d adds nothing. When weights is None, every w_i is 1.
If weights is not None and its length is not the number of lists, raise ValueError.
Tie rule: fuse sorts from the highest score to the lowest. When two documents have the same score, the lower doc id comes first.
Input and output
| Name | Type | Shape | Meaning |
|---|---|---|---|
rankings | list of lists of int | L lists | each list holds distinct doc ids, best first |
k | int | scalar | the RRF constant, default 60 |
weights | list of float or None | L values | the weight of each list |
rrf_scoresreturns adictthat maps each doc id in any list to its fused score as afloat.fusereturns alistof(doc_id, score)tuples, best first. It holds every document ofrrf_scores.
Constraints
0 <= L <= 10and each list has at most 1000 ids. A list can be empty.- Doc ids are non negative ints. An id occurs at most once in one list.
k >= 1and each weight is positive.- Do not change the input lists.
- Use Python and numpy only.
Examples
pythonbm25 = [3, 1, 4]
dense = [1, 5, 3]
fuse([bm25, dense])text[(1, 0.03252247488101534), (3, 0.032266458495966696), (5, 0.016129032258064516), (4, 0.015873015873015872)]Document 1 has ranks 2 and 1, so its score is 1/62 + 1/61. Document 3 has ranks 1 and 3, so its score is 1/61 + 1/63. Document 1 comes first.
pythonfuse([bm25, dense], weights=[2.0, 1.0])text[(3, 0.04865990111891751), (1, 0.048651507139079855), (4, 0.031746031746031744), (5, 0.016129032258064516)]Hints
4 hintsSolution and notes
LockedPass every check with Submit to open the reference solution and the notes.
Run it on your computer
Clone the repository, install numpy and run the same checks in a terminal:
python3 scripts/practice/run.py reciprocal-rank-fusion my_answer.py
python3 scripts/practice/run.py reciprocal-rank-fusion my_answer.py --examplesStart my_answer.py from starter.py.
Your code is saved in this browser as you type. On a phone you can read and edit the code, but the checks are easier to use on a desktop.
Keyboard shortcuts
- Ctrl Enter
- Run the examples
- Ctrl Shift Enter
- Submit
- Tab / Shift Tab
- Indent or outdent the lines
- Esc then Tab
- Move the focus out of the editor
- Alt H
- Show the next hint
On a Mac, use Cmd in place of Ctrl.
Select Run to check the examples, or Submit to run every check.