hybrid-retrieval-fusion

Fuse vector and BM25 keyword retrieval lists into one ranking using Reciprocal Rank Fusion.

2|Updated Aug 2, 2026
One-click install
npx skills add https://github.com/Arasz/ai-raccoon --skill hybrid-retrieval-fusion-arasz
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: hybrid-retrieval-fusion
Source: https://github.com/Arasz/ai-raccoon/tree/main/.ai-badger/skills/learned/uncategorized/hybrid-retrieval-fusion
Command: npx skills add https://github.com/Arasz/ai-raccoon --skill hybrid-retrieval-fusion-arasz

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes references (resource) components.

What problem does it solve? Combining keyword (BM25/FTS5) and vector similarity search results into a single ranking is error-prone: score scales are incompatible, one modality can silently return nothing, and untested fusion constants degrade retrieval quality. This Skill provides a decision framework, measured defaults, and debugging playbooks for fusing dense and sparse retrieval correctly. ## Core Features & Use Cases - Fusion method selection: Decision framework covering RRF, weighted RRF, score fusion (CombSUM/min-max/DBSF), and learned reranking, with production defaults from Elasticsearch, OpenSearch, Qdrant, Weaviate, Vespa, and Azure AI Search. - SQLite FTS5 + vec0 implementation guidance: Pure-SQL RRF pattern, safe FTS5 query normalization (OR-joining tokens, stripping reserved words), two-layer fusion for scope-multiplexed stores, and vec0 blob/KNN/snippet gotchas. - Validation and debugging playbooks: Golden retrieval harness spec (nDCG, MRR, Kendall-τ sweeps), content-first rank-change triage, dead-modality detection, and measured operational pitfalls like candidate-window starvation. - Use Case: When replacing a search extension in a .NET SQLite memory store, use this Skill to implement weighted RRF over FTS5 and vec0, sweep k and weights through the real pipeline, and prove parity against the old implementation with a fixed-corpus harness. ## Quick Start Ask the AI to help you fuse FTS5 BM25 and vec0 vector search results in your SQLite store using Reciprocal Rank Fusion with a swept k parameter.

Frequently Asked Questions about hybrid-retrieval-fusion

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I combine BM25 and vector search results into one ranking?

Use Reciprocal Rank Fusion: score each document as the sum of 1/(k+rank) across both lists, with k=60 as the classic default. RRF is rank-only, so it is immune to the score-scale mismatch between unbounded BM25 and bounded cosine similarity.

What k value should I use for Reciprocal Rank Fusion?

Always sweep k rather than shipping an assumed constant. Measured results show k=10 can beat k=60 (T2-RAGBench Recall@5 0.716 vs 0.695), while Qdrant ships k=2 and Elasticsearch defaults to 60. Small k emphasizes top ranks; large k flattens them.

Why does my hybrid search return identical metrics at every sweep point?

Identical metrics across all k and weight points means one retrieval list is empty, so fusion silently degrades to a single modality. A common cause is AND-joining query tokens in FTS5 MATCH, which matches nothing on natural-language queries; join tokens with OR instead.

Does .NET have a library for Reciprocal Rank Fusion?

No mainstream .NET library implements fusion. Microsoft.Extensions.VectorData and Semantic Kernel are storage abstractions without fusion APIs, and Lucene.NET lacks RRF. The practical approach is hand-composing two ranked lists in LINQ or using a pure-SQL CTE pattern.

How do I implement hybrid search with SQLite FTS5 and vec0?

Rank each list with row_number() (FTS5 by rank, vec0 by ascending vec_distance_cosine), FULL OUTER JOIN them, and sum COALESCE(1/(k+rank), 0) times per-list weights. SQLite 3.39+ is required for FULL OUTER JOIN, and vec0 KNN needs an explicit k clause.

When should I use score fusion instead of RRF?

Use score fusion (CombSUM, min-max, or DBSF) only when raw scores carry real magnitude and you can normalize per query. Min-max is outlier-sensitive and breaks on empty lists; RRF is the safer default and handles missing modalities via COALESCE.