RRF(Reciprocal Rank Fusion,倒数秩融合)是一种在信息检索中用来**合并多个不同检索引擎结果**的经典排序算法。
在上一节提到的**混合检索(Hybrid Search)**中,我们通常会同时使用基于关键词的 BM25 和基于语义的向量检索(Vector Search)。这就带来了一个核心问题:**两者的打分体系完全不同,无法直接相加**。
* BM25 的得分可能是一个没有固定上限的绝对数值(如 15.6、42.8)。
* 向量检索的得分通常是余弦相似度,被归一化在 0 到 1 之间(如 0.85、0.92)。
RRF 的巧妙之处在于:它**完全抛弃了绝对得分(Score)**,只关注文档在各个检索结果中的**排名(Rank)**,从而完美解决了不同打分体系无法直接对比的问题。
RRF 核心公式
RRF 的算法非常简单,它通过取排名的倒数来计算一个综合得分,排名越靠前,倒数越大,得分越高。对于文档 d,它的 RRF 总分计算如下:
\\text{RRF}(d) = \\sum_{r \\in R} \\frac{1}{k + \\text{rank}_r(d)}
* R:代表所有的检索策略集合(例如 R = \\{\\text{BM25检索}, \\text{向量检索}\\})。
* \\text{rank}_r(d):文档 d 在第 r 种检索策略集里的具体排名(第1名就是1,第2名就是2)。
* k:一个平滑常数,用来减缓排名的权重衰减速度。在工业界(包括最初提出该算法的论文中),**k 的默认最佳实践值通常设为 60**。
计算示例
假设我们搜索"苹果公司的产品",有两个文档 A 和 B,以及两个检索器(BM25 和 向量检索),k 设为 60:
| 文档 | BM25 排名 | 向量检索 排名 | RRF 计算过程 | 最终 RRF 得分 |
|---|---|---|---|---|
| **文档 A** | 第 1 名 | 第 4 名 | \\frac{1}{60 + 1} + \\frac{1}{60 + 4} | ~0.0320 |
| **文档 B** | 第 3 名 | 第 2 名 | \\frac{1}{60 + 3} + \\frac{1}{60 + 2} | ~0.0320 |
| **文档 C** | 未命中 | 第 1 名 | 0 + \\frac{1}{60 + 1} | ~0.0163 |
在这个例子中,文档 A(偏向关键词精确匹配)和文档 B(两边表现都很均衡)最终的总得分基本持平,而偏科严重的文档 C(虽然语义排第一,但完全没命中关键词)总分较低。这种机制鼓励**在多个检索策略中都表现不错的文档排到前面**。
为什么在现代 RAG 架构中偏爱 RRF?
-
**无需训练(Zero-shot):** 它是一个纯数学统计方法,不需要提供标注数据去训练权重参数。
-
**极强的鲁棒性:** 无论 BM25 算法怎么微调,或者你更换了不同维度的 Embedding 向量模型(导致相似度得分大变),都不影响 RRF 的融合逻辑,因为它只看名次。
-
**抗偏科能力:** 即使某个文档在 BM25 中得分异常地高(比如恶意堆砌关键词),但在向量检索中排名垫底,RRF 也会压低它的最终综合排名。
**RRF 的局限性:**
由于彻底抛弃了原始分数,RRF 无法感知名次之间的"分数断层"。例如,第 1 名得分为 0.99,第 2 名得分为 0.98,第 3 名得分为 0.60。在 RRF 看来,1、2、3 名之间的差距是等距的,它忽略了第 3 名其实质量已经大幅下降的事实。因此,在要求极高的场景下,通常会在 RRF 之后再接入一个 **Reranker(重排模型)** 进行最终把关。
这是一个非常典型且专业的工业级 RAG(检索增强生成)架构问题。
简单来说:**RRF 只是在做"盲人摸象"式的统计合并,而 Rerank 才是真正带有阅读理解能力的"精算师"。**
在业界标准的搜索推荐架构中,我们通常把检索分为两个阶段:**召回(Recall / 粗排)** 和 **精排(Ranking)**。你提到的架构完美对应了这个漏斗模型。有了 RRF 还要加 Rerank,核心原因有以下三点:
1. RRF 只看"名次"不看"内容",存在"分数盲区"
就像我们在上一节提到的,RRF 彻底抛弃了文档的原始相关性得分,只做名次的倒数相加。
* 假设在向量检索中,第 1 名的分数是 0.99(完美匹配),第 2 名的分数是 0.40(完全不相关)。
* 在 RRF 眼里,它们仅仅是"第1名"和"第2名",它感知不到这 0.59 的巨大断层。
* 这会导致一些**其实质量很差的凑数文档,仅仅因为在两个列表中都排到了前列(比如第5名),就被 RRF 融合到了最前面**。
Rerank(重排模型)的作用就是打破这种"名次错觉",直接读取真实文本,给出一个绝对精准的相关性打分(0到1之间),把不够格的文档无情踢掉。
2. 向量检索存在"语义折叠",而 Reranker 能做到"深度阅读"
这涉及到两种底层模型的架构差异:
* **向量检索(Bi-Encoder 双塔模型):** 把用户的查询和文档**分别、独立**压缩成一长串数字(向量)。打分只是比较两个向量的距离。这就像相亲时,男女双方各自填一张表,红娘比对表格匹配度。它速度极快,但容易丢失复杂的逻辑细节(比如否定词"不"、"非",或者特定的因果关系)。
* **重排模型(Cross-Encoder 交叉编码器):** 它把"用户查询 + 文档内容"拼凑在一起,**整体**丢进大语言模型(如 BERT)中计算。查询中的每一个词都会和文档中的每一个词产生注意力交互(Self-Attention)。这就像两个人直接面对面深度交谈。它能极其精准地判断这段话到底有没有回答用户的问题。
3. 为什么不直接用 Rerank?算力与漏斗的妥协
既然 Rerank 这么准,为什么还要前面的 BM25、向量和 RRF?
因为 **Cross-Encoder 计算极其昂贵且缓慢**。如果你有 100 万篇文档,每次用户提问都让 Rerank 去两两计算,服务器会瞬间宕机,延迟可能高达几分钟。
因此,现代 RAG 架构采用了**"漏斗策略(Funnel)"**:
| 阶段 | 使用技术 | 作用 | 处理数据量 |
| :--- | :--- | :--- | :--- |
| **查询处理** | 意图识别 (Intent) + 查询改写 (Rewrite) | 搞清楚用户到底想问什么,提取关键词和扩展同义词。 | 1 个 Query |
| **多路召回 (Recall)** | 向量检索 + BM25 | 快速在大海捞针,宁可错杀一千,不放过一个。分别捞出前 100 篇。 | 百万级 → 100 篇 |
| **多路融合** | **RRF 融合** | 统一排行榜,把基于关键词的 100 篇和语义的 100 篇,通过排名合并成一个候选池。 | 200 篇 → Top 50 |
| **精准排序 (Ranking)** | **Rerank 重排** | 让精算师对这 50 篇进行深度阅读理解,剔除"似是而非"的内容。 | 50 篇 → Top 3~5 |
| **生成回答** | LLM (大模型生成) | 把最终最精确的 3~5 篇喂给大模型,生成最终回答。 | 3~5 篇 → 1 个回答 |
总结
RRF 是为了解决**"关键词检索和向量检索得分无法相加"**的工程统计问题,属于**粗排阶段**;而 Rerank 是为了解决**"精准判断文档到底能不能回答该问题"**的语义理解问题,属于**精排阶段**。两者结合,才能既保证不漏掉资料(召回率),又保证大模型不会吃到垃圾信息(准确率)。
**什麼是「語義折疊」(Semantic Folding / 信息瓶頸)?**
向量檢索的核心,是把一段長文本(如 1000 字的文章)送進 Embedding 模型,壓縮成一個固定長度的浮點數數組(通常是 768 或 1536 維的向量)。這就好比**把一本厚厚的小說,濃縮成了一頁紙的「劇情大綱」**。
<Image alt="將一句話壓縮成一個浮點數向量數組的過程圖解" caption="文本被壓縮(折疊)為固定維度的向量" src="image_agent_tag_4066409591021340835"/>
在這個壓縮過程中,模型會抓取文本的「核心主旨」和「整體氛圍」,但必然會**丟掉(折疊掉)那些高頻但語義不顯著的細節**。這種信息遺失的現象就是「語義折疊」。
後果是:像具體的數字、日期、專有名詞、貨號,甚至是「不」這樣的否定詞,在龐大的語義空間中權重被稀釋了。模型能理解「這是一篇關於蘋果手機退貨政策的文章」,但可能無法區分裡面寫的是 `iPhone 14` 還是 `iPhone 15`。
有了向量,為什麼還要 BM25?
因為向量檢索有「盲區」,而這正是 BM25(關鍵詞精確匹配)的強項。如果不加 BM25,你的 RAG(檢索增強生成)系統在以下三種場景會徹底翻車:
* **專有名詞與精確 ID(如貨號、型號、錯誤碼):**
假設用戶搜 `Error Code 404` 和 `Error Code 500`。在向量模型看來,這倆都是「伺服器報錯信息」,語義極度相似,甚至會錯誤召回 `Error Code 502` 的文檔。但 BM25 知道 `404` 就是 `404`,差一個數字都不行。
* **特定詞彙或新造詞(Out-of-Vocabulary):**
如果用戶搜索一個極度冷門的專業術語或昨天剛發布的新產品(例如某個內部代號),向量模型可能根本沒見過這個詞,只能把它瞎猜成「某種名詞」。而 BM25 是基於字面匹配的,只要文檔裡有這個詞就能被精準撈出來。
* **短查詢與強過濾條件:**
當用戶只輸入「2023年 財報」時,向量模型可能會召回所有「財務相關」的文章(甚至包含2022年的),而 BM25 能精準鎖定標題或內容中完全包含這幾個字的文檔。
你可以透過下方的模擬器,直觀感受兩者在面對不同查詢場景時的表現差異:
<GenerateWidget component_placeholder_id="im_ae26bc4cea3240f8" height="600px" title="檢索策略對比模擬器">
```json
{
"widgetSpec": {
"id": "vector-vs-bm25-simulator",
"height": "600px",
"prompt": "Objective: Compare BM25 keyword matching with Vector Semantic Search.\nData State: initialValues: none.\nStrategy: Standard Layout.\nLibraries: D3.js.\nInputs:\n- 查詢類型 (Dropdown: '精確型號 Exact SKU', '模糊概念 Broad Concept', '錯別字 Misspelled Word')\n- 檢索方式 (Toggle: 'BM25', '向量檢索 Vector Search', '混合檢索 Hybrid')\nBehavior: Show a visual representation of a document database (nodes or list). When '精確型號' and 'BM25' are selected, highlight one exact match node. If '向量檢索' is used for '精確型號', highlight a fuzzy cluster of partially relevant nodes. Demonstrate how '混合檢索' uses both methods to isolate the best overall document across different query types."
}
}
```
</GenerateWidget>
> **總結:** 向量檢索負責「懂你的意思,哪怕你打錯字或換了說法」;而 BM25 負責「死記硬背,一字不差地找到你要的暗號」。兩者結合的**混合檢索(Hybrid Search)**,才是確保不漏掉細節的黃金標準。
<FollowUp label="想知道如何分配混合檢索的權重比例嗎?" query="在混合檢索中,BM25 和向量檢索的權重比例(Alpha 參數)通常該如何設置和調優?"/>