# How QMD Uses the RRF Fusion Algorithm to Combine Search Results

> Learn how QMD uses Reciprocal Rank Fusion RRF to combine BM25 and vector search results. Discover weighted fusion with a top-rank bonus for superior ranking accuracy.

- Repository: [Tobias Lütke/qmd](https://github.com/tobi/qmd)
- Tags: deep-dive
- Published: 2026-02-16

---

**QMD applies a weighted Reciprocal Rank Fusion (RRF) algorithm with a top-rank bonus to merge BM25 full-text and vector similarity results, using a default k value of 60 and position-aware blending for final ranking.**

The RRF fusion algorithm serves as the core mechanism in QMD (Query Markdown Database) that enables robust hybrid search by combining ranked results from multiple retrieval backends. By merging SQLite FTS5 BM25 scores with vector similarity rankings and handling query expansions through weighted reciprocal rank contributions, QMD delivers more relevant results than any single retrieval method alone.

## How the RRF Fusion Algorithm Works in QMD

### Parallel Retrieval and Weighted Inputs

QMD executes queries against both the SQLite-FTS5 BM25 index and the vector index in parallel, generating multiple ranked lists of `RankedResult` objects. The system distinguishes between the original query and expanded query variants by applying differential weights: original query result lists receive a **×2 weight boost**, while expanded query lists use a standard weight of 1.

### The RRF Scoring Formula

For every document appearing at rank *r* (0-indexed) in a given result list, QMD calculates its reciprocal rank contribution using the formula implemented in `reciprocalRankFusion`:

```typescript
rrfContribution = weight / (k + r + 1)

```

Where:
- **weight** is the list-specific multiplier (2 for original queries, 1 for expansions)
- **k** is a constant that defaults to **60** (as defined in the source)
- **r** is the zero-based rank position in the list

### Top-Rank Bonus Protection

To prevent exact matches from being drowned out by query expansion noise, QMD applies a **top-rank bonus** after summing all RRF contributions:
- **+0.05** for documents at rank 0 in any list
- **+0.02** for documents at ranks 1-2 in any list

This ensures that documents ranking first for the original query maintain prominence in the final fused list.

## Implementation Details in QMD Source Code

The core RRF fusion algorithm resides in **[`src/store.ts`](https://github.com/tobi/qmd/blob/main/src/store.ts)**, specifically within the `reciprocalRankFusion` function. This utility aggregates multiple `RankedResult` arrays, applies the weighted scoring formula, and returns a single fused list sorted by accumulated RRF scores.

The search pipeline orchestrating this process is implemented in the `query` method of the same file. It:
1. Collects results from BM25 and vector indices for both original and expanded queries
2. Assigns weights `[2, 2, 1, 1]` corresponding to `[ftsOriginal, vecOriginal, ftsExpanded, vecExpanded]`
3. Invokes `reciprocalRankFusion` with `k = 60`
4. Slices the top 30 candidates for LLM reranking
5. Applies position-aware score blending (75% retrieval weight for top 3, 60% for ranks 4-10, 40% for remainder)

## Code Examples

### Using `reciprocalRankFusion` Directly

```typescript
import { reciprocalRankFusion, RankedResult } from "./src/store.ts";

// Results from BM25 full-text search
const ftsResults: RankedResult[] = [
  { file: "architecture.md", displayPath: "architecture.md", title: "System Architecture", body: "...", score: 0 },
  { file: "api.md", displayPath: "api.md", title: "API Reference", body: "...", score: 0 },
];

// Results from vector similarity search
const vecResults: RankedResult[] = [
  { file: "deployment.md", displayPath: "deployment.md", title: "Deployment Guide", body: "...", score: 0 },
  { file: "architecture.md", displayPath: "architecture.md", title: "System Architecture", body: "...", score: 0 },
];

// Apply RRF with original query weighted 2x
const fused = reciprocalRankFusion([ftsResults, vecResults], [2, 1]);

console.log(fused.map(r => `${r.file}: ${r.score.toFixed(4)}`));
// Output: architecture.md appears highest due to presence in both lists plus top-rank bonus

```

### High-Level Query Pipeline

```typescript
// Simplified excerpt from src/store.ts query() method
const resultLists: RankedResult[][] = [];

// Original query results (2x weight)
resultLists.push(ftsOriginal);   // weight 2
resultLists.push(vecOriginal);   // weight 2

// Expanded query results (1x weight)
resultLists.push(ftsExpanded);   // weight 1
resultLists.push(vecExpanded);   // weight 1

// Fuse with k=60
const fused = reciprocalRankFusion(resultLists, [2, 2, 1, 1]);

// Top 30 for LLM reranking
const candidates = fused.slice(0, 30);

```

## Summary

- **RRF fusion algorithm** in QMD combines BM25 and vector search results using weighted reciprocal rank contributions with a default k value of 60.
- **Weighting strategy** applies a 2× boost to original query results versus expanded query variants, ensuring exact matches retain priority.
- **Top-rank bonus** adds +0.05 for rank 0 and +0.02 for ranks 1-2 to prevent exact matches from being diluted by expansion noise.
- **Implementation** resides in `reciprocalRankFusion` within [`src/store.ts`](https://github.com/tobi/qmd/blob/main/src/store.ts), handling multiple ranked lists and returning a unified, sorted result set.
- **Position-aware blending** combines RRF scores with LLM reranker scores using tiered weights (75%, 60%, 40%) based on result position.

## Frequently Asked Questions

### How does QMD's RRF fusion algorithm differ from standard Reciprocal Rank Fusion?

Standard RRF typically uses the formula `1/(k + r)` with equal weighting across all result lists. QMD's variant introduces **list-specific weights** (2× for original queries, 1× for expansions) and a **top-rank bonus** (+0.05 for first place, +0.02 for second and third) to protect exact matches from being overwhelmed by query expansion noise. The implementation also uses `k = 60` as the default constant.

### What is the default k value in QMD's reciprocalRankFusion function?

The default **k value is 60**, as defined in the `reciprocalRankFusion` implementation in [`src/store.ts`](https://github.com/tobi/qmd/blob/main/src/store.ts). This constant appears in the denominator of the scoring formula `weight / (k + r + 1)`, where higher k values dampen the impact of rank position differences, creating a more gradual scoring curve across the result list.

### How does QMD handle weighting between different search backends?

QMD applies **differential weights** based on query provenance rather than backend type. Results from the **original query** receive a weight of **2**, while results from **expanded query variants** receive a weight of **1**. This applies uniformly across both the BM25 (SQLite FTS5) and vector similarity backends, ensuring that exact matches to the user's original query terms retain priority over semantically similar expansion terms.

### Why does QMD add a top-rank bonus to the RRF calculation?

The **top-rank bonus** (+0.05 for rank 0, +0.02 for ranks 1-2) serves as a **protection mechanism** for exact matches. Without this bonus, documents that rank first for the original query could be mathematically overtaken by documents that appear in multiple expanded query result lists, even if those documents are less relevant to the user's actual intent. The bonus ensures that high-confidence exact matches maintain prominence in the final fused ranking.