乐于分享
好东西不私藏

RAG文档明明检索到了,为什么还是排不到前面?RRF 排名算法一次讲清楚

RAG文档明明检索到了,为什么还是排不到前面?RRF 排名算法一次讲清楚

RRF 倒数排名融合算法

在 RAG 系统中,我们通常不会只使用一种检索方式。

为了尽可能找到正确文档,很多系统会同时使用:

  • • BM25 关键词检索
  • • 向量语义检索

BM25 擅长匹配关键词、产品型号和专业术语;向量检索更擅长理解语义,找到表达方式不同但含义相近的内容。

两种检索方式结合,确实能够召回更多相关文档。

但新的问题也随之出现:

两路检索都返回了一批文档,最终应该按照什么顺序排列?

这正是 RRF 要解决的问题。


一、为什么不能直接合并检索分数?

假设用户搜索:

手机无法充电怎么办?

BM25 检索后,文档 A 的相关性分数是 12.6;向量检索后,文档 B 的相似度是 0.86

那么,12.6 和 0.86 哪个更高?

从数字上看,12.6 显然更大,但这并不代表文档 A 一定更加相关。

因为这两个分数来自完全不同的计算方式:

  • • BM25 分数衡量关键词匹配程度
  • • 向量相似度衡量语义相似程度
  • • 两者的取值范围和计算标准并不一样

这就像两场考试:

  • • 第一场满分是 100 分
  • • 第二场满分是 10 分

一个人考了 80 分,另一个人考了 9 分。只看数字大小,80 大于 9,但不能因此判断前者表现一定更好。

同样,BM25 的 12.6 分和向量检索的 0.86,也不能直接比较或相加。

于是,多路检索面临一个关键问题:

不同检索器的原始分数没有统一标准,应该怎么融合?

RRF 给出了一种非常直接的解决思路。


二、RRF 是什么?

RRF 的全称是 Reciprocal Rank Fusion,中文通常叫作倒数排名融合

它是一种用于融合多个检索结果的排序算法。

RRF 的核心思想只有一句话:

不比较不同检索器给出的原始分数,只比较文档在每一路检索结果中排第几。

也就是说,RRF 不关心:

  • • BM25 到底给了多少分
  • • 向量相似度具体是多少
  • • 不同检索器的分数范围是否一致

它只看文档的名次

例如,同一篇文档:

  • • 在 BM25 中排第 1
  • • 在向量检索中排第 3

RRF 会根据这两个排名分别给文档加分,再把分数累加起来。

可以把多路检索理解成多位评委给文档排名:

  • • BM25 是评委一
  • • 向量检索是评委二
  • • 每位评委都会给出一份榜单
  • • RRF 根据文档在不同榜单中的名次综合计分

计分规则也很简单:

  1. 1. 排名越靠前,获得的分数越高
  2. 2. 排名越靠后,获得的分数越低
  3. 3. 同一篇文档出现在多路结果中,分数可以累加

因此,一篇文档如果在多个检索结果中都排名靠前,最终通常也会排在前面。

RRF 寻找的并不是某一路检索中分数最高的文档,而是:

被多路检索共同认可的文档。


三、RRF 是怎么计算的?

RRF 的计算公式如下:

其中:

  • •  表示某一篇文档
  • •  表示文档在第  路检索结果中的排名
  • •  是平滑参数
  • • 同一篇文档在多路检索中的得分会累加

公式看起来有些抽象,但整个过程只有四步:

假设参数 

如果文档 A:

  • • 在 BM25 中排第 1
  • • 在向量检索中排第 3

那么它的 RRF 分数就是:

也就是:

如果文档 B:

  • • 在 BM25 中排第 2
  • • 在向量检索中排第 1

那么它的 RRF 分数就是:

也就是:

最后,将每篇文档在所有检索结果中的得分相加,再按照总分从高到低重新排序。


四、用一个完整案例讲清楚

假设用户搜索:

手机无法充电怎么办?

BM25 关键词检索返回:

排名
文档
1
文档 A:充电接口故障排查
2
文档 B:手机无法充电处理方法
3
文档 C:电池保养说明

向量语义检索返回:

排名
文档
1
文档 B:手机无法充电处理方法
2
文档 D:设备无法正常供电
3
文档 A:充电接口故障排查

可以看到:

  • • 文档 A 在两路检索中分别排第 1 和第 3
  • • 文档 B 在两路检索中分别排第 2 和第 1
  • • 文档 C 只出现在 BM25 结果中
  • • 文档 D 只出现在向量检索结果中

假设 ,分别计算每篇文档的 RRF 分数。

文档 A

文档 B

文档 C

文档 C 只出现在 BM25 结果中,并且排第 3:

文档 D

文档 D 只出现在向量检索结果中,并且排第 2:

最终融合排序为:

最终排名
文档
RRF 分数
1
文档 B
0.03252
2
文档 A
0.03227
3
文档 D
0.01613
4
文档 C
0.01587

为什么文档 B 排到了第一?

因为它在两路检索中分别排第 2 和第 1,两边的排名都很靠前。

文档 A 虽然在 BM25 中排第一,但它在向量检索中只排第三,所以融合总分略低于文档 B。

文档 C 和文档 D 只出现在一路检索结果中,只能获得一次加分,因此最终得分相对较低。

这就是 RRF 的排序逻辑:

一篇文档不一定要在某一路检索中排第一,只要它在多路检索中都表现稳定,最终就可能排到前面。


五、参数  有什么作用?

RRF 公式中还有一个参数 ,常见设置是:

它的作用,是让不同排名之间的分数变化更加平缓。

假设公式中没有 ,直接计算排名的倒数:

排名
得分
第 1 名
1
第 2 名
0.5
第 3 名
0.333

可以看到,第 1 名和第 2 名之间的分数差距非常大。

这意味着,只要某篇文档在某一路检索中排第一,就可能对最终结果产生过大的影响。

加入  后:

排名
得分
第 1 名
第 2 名
第 3 名

此时,不同名次之间的分数差距明显变小。

可以简单理解为:

  • •  越小,越强调前几名的优势
  • •  越大,不同名次之间的得分越接近

因此,加入  后,可以避免某一路检索中的第一名过度主导最终结果,让融合排序更关注一篇文档是否被多路检索共同认可。

需要注意的是, 是常见设置,并不代表所有场景都必须固定使用 60。


六、RRF 的完整执行过程

把前面的内容连起来,RRF 的执行过程就是:

BM25 返回一份文档榜单              +向量检索返回一份文档榜单              ↓记录每篇文档在各个榜单中的排名              ↓使用 1 ÷(k + 排名)计算单路得分              ↓累加同一篇文档的多路得分              ↓按照总分从高到低重新排序

RRF 不需要比较 BM25 分数和向量相似度,也不需要先把两种分数强行调整到同一个范围。

只要每一路检索能够给出文档排名,RRF 就可以完成融合。


总结

多路检索融合最麻烦的问题,是不同检索器的原始分数通常不在同一套标准下。

BM25 的 12.6 分和向量检索的 0.86,并不能直接比较。

RRF 的解决办法很直接:

既然分数不好比较,那就不比较分数,只比较排名。

它会把文档在每一路检索中的排名转换成倒数分数,再累加多路得分,最终得到统一排序。

排名越靠前,获得的分数越高;被多路检索同时召回,并且在多个榜单中都排名靠前的文档,最终更容易排在前面。