Where we left off
Lesson 7 showed weighted-sum fusion's fragility with hand-rolled scores. Now that both retrievers are real libraries (Lesson 21), this lesson revisits alpha-blending one more time, and puts it head-to-head against RRF on the same two queries, so the tradeoff is concrete rather than abstract.
The code, piece by piece
distances = results["distances"][0]dense_scores = {doc_id: 1 - distance for doc_id, distance in zip(ids, distances)}chromadb returns distance (lower means closer), the opposite convention from this course's own cosine similarity (higher means closer). Flipping it with 1 - distance isn't exact cosine similarity, but it restores the "higher is better" direction min-max normalization and blending both assume, the same care Lesson 10 took with score conventions before combining anything.
blended = sorted(names, key=lambda n: ALPHA * dense_norm[n] + (1 - ALPHA) * sparse_norm[n], reverse=True)fused = reciprocal_rank_fusion([dense_ranking, sparse_ranking])Both fusion methods run on the exact same two underlying rankings, so this lesson isn't comparing different retrievers, only different ways of combining the same two opinions.
Checkpoint
- Alpha-blending works fine here, the same way it did in Lesson 7, once every retriever's score convention (similarity vs. distance) is handled correctly first.
- RRF and alpha-blending aren't "one is right," they're a genuine tradeoff: RRF costs you score information, alpha-blending costs you the complexity of normalizing and tuning correctly across retrievers that don't speak the same scale.
- This course defaults to RRF throughout for the reason Lesson 8 gave: fewer ways for a real system to get subtly wrong.
If anything here still feels unclear, ask before moving to Lesson 23.