· liyu · algorithm · 8 min read · — 次浏览

RRF 倒数排名融合:混合检索里的"排名仲裁者"

向量语义召回与 BM25 关键词召回的分数天然不可比,混合检索需要一个仲裁者。本文以混合检索为例讲解 RRF(Reciprocal Rank Fusion)算法的公式与 k 常数的数学直觉,并横向对比分数级融合、名次级融合与学习排序三类融合策略的取舍。

一、问题起点:两路召回,分数不可比

上一篇写向量数据库时,混合检索反复出现。它的标准形态是两路并行召回:

  • 向量检索:Query 与文档都编码为 Embedding,按余弦相似度取 Top-K,负责语义泛化;
  • BM25 关键词检索:基于词频的稀疏检索,负责专有名词、型号、代码标识的精确命中。

两路各返回一份排好序的列表之后,问题来了:怎么合并?

余弦相似度落在 [-1, 1],BM25 分数是无上界的正数,量纲与分布完全不同。直接把分数相加,等于让两个不同单位的量比赛——数值大的那一路会垄断排序。加权求和理论上可行,但权重怎么定?每换一个语料库、换一个 Embedding 模型,就要重新调一遍。

RRF(Reciprocal Rank Fusion,倒数排名融合)的思路是釜底抽薪:不比分数,只比名次。

二、算法本体:一行公式

score(d) = Σᵢ  1 / (k + rankᵢ(d))
  • rankᵢ(d):文档 d 在第 i 路列表中的名次(第 1 名记 1);
  • k:平滑常数,业界惯例取 60;
  • 文档未出现在某路列表中,该路贡献 0 分。

算法出自 Cormack 等人 2009 年的论文,实验中它击败了 Condorcet 融合与按名次训练的融合方法,此后成了信息检索领域的经典基线。

完整算一遍

取 k = 60,两路各返回 Top-3:

文档向量检索名次BM25 名次RRF 得分
A1—1/61 ≈ 0.0164
B311/63 + 1/61 ≈ 0.0323
C241/62 + 1/64 ≈ 0.0318

最终排序 B > C > A:A 是向量检索的头名,但 BM25 一票没投;B 两路都靠前,融合后登顶。“两路都点头”的文档被优先,这正是混合检索想要的仲裁逻辑。

k = 60 在平滑什么

1/(k + r) 是一条平缓递减的曲线,k 决定了”名次差距”被压缩到什么程度。极端对比:k = 0 时,第 1 名的得分是第 10 名的 10 倍,单路召回的头名几乎一票定胜负;k = 60 时,两者只差约 15%,每一路的意见都被拉到接近”一人一票”。

60 这个数字没有玄学——论文实验中它在多个数据集上稳定表现良好,后来就成了社区默认值,ES、Milvus 的文档里也都沿用 60。

三、融合策略对比:RRF 在光谱的哪个位置

“两路结果怎么合”这个问题,按用分数还是用名次、要不要训练,可以排成一条光谱:

策略代表方法优点代价
分数级融合加权和、加权平均保留置信度强弱信息,效果上限高必须先归一化(min-max / z-score),分数分布一变就失真,权重需逐场景调参
名次级融合Borda 计数、RRF免归一化、免调参,对异常分布鲁棒丢弃分数强度:第 1 名比第 2 名好多少,这个信息没了
学习排序(LTR)LambdaMART、交叉编码器重排效果上限最高需要标注数据训练,推理成本高,通常作为召回后的重排层

名次级融合内部也有一处分野。Borda 计数是最朴素的方案:直接把各路名次相加。它与 RRF 的差别在衰减曲线的形状——Borda 是线性衰减,第 1 名与第 2 名的差距,恒等于第 9 名与第 10 名的差距;RRF 用倒数曲线,头部名次之间区分更平滑,中后部的差异则被进一步压平。

这条倒数曲线的工程价值在于抗噪:当某一路召回偶发”自信的错误”(把不相关文档顶到很前),1/(k + r) 的平缓性会让这个异常名次对全局排序的破坏被显著稀释;换成线性名次相加或未归一化的分数相加,同样异常的杀伤力要大得多。论文的实验结论正是:这条简单的倒数曲线在多路融合场景里比精心设计的对手更稳。

实践中三类策略常常是分工而非互斥:RRF 负责便宜地把多路召回合并成一份候选列表,LTR(如交叉编码器重排)再对候选做精排——一个管仲裁,一个管精修。这也是目前主流 RAG 流水线的标准两层结构。

四、工程落地速览

  • Elasticsearch / OpenSearch:RRF 是混合查询的官方一等公民,一个参数开启;
  • Milvus:混合检索内置 RRFRanker,同场的 WeightedRanker 即分数级路线,正好对应光谱的两端;
  • pgvector:没有内置函数,但手写 SQL 反而最能看清算法本色:
-- 两路各自 ROW_NUMBER 排名,再按严格 RRF(k = 60)融合
SELECT id,
  1.0 / (60 + v_rank) + 1.0 / (60 + t_rank) AS rrf_score
FROM (
  SELECT id,
    ROW_NUMBER() OVER (ORDER BY embedding <=> $1) AS v_rank,
    ROW_NUMBER() OVER (ORDER BY ts_rank(to_tsvector('simple', content), $2) DESC) AS t_rank
  FROM docs
) t
ORDER BY rrf_score DESC
LIMIT 10;

五、小结

RRF 用一行公式回答了混合检索最棘手的问题——异构分数如何公平合议:放弃分数、只用名次,用倒数曲线加常数 60,把多路召回变成一场低方差、免调参的投票。它不是效果上限最高的融合策略,却是性价比最高的默认选项——ES、OpenSearch、Milvus 纷纷把它做成内置能力,就是最好的背书。

当你下次在 RAG 系统里同时启用向量库和 BM25 时,中间那个不起眼的融合器,做的就是这件事。

Share:

回看感悟累计回看 — 次

加载中…

Back to Blog

Related Posts

View All Posts »

文本向量化演进:从 Word2Vec 到现代 Embedding 模型

文本向量化是搜索、推荐与 RAG 共同的地基。本文快速回顾 one-hot、TF-IDF、Word2Vec 等经典方案的思路与局限,重点拆解现代 Embedding 模型的三大支柱:BERT 上下文表示、Sentence-BERT 句向量专用化与对比学习训练范式,并盘点 BGE、GTE、E5、OpenAI text-embedding-3 等主流模型与 MRL、指令前缀等关键技术。

TF-IDF 原理与应用:搜索打分与文本向量化的起点

TF-IDF 用「词频 × 稀缺度」给词打分,是信息检索绕不开的经典。本文快速讲透它的核心原理,重点展开两大应用:搜索系统里的相关性打分,以及把文本变成稀疏向量后的分类、相似度与关键词提取。

当双塔模型遇见 RAG:召回与检索,殊途同归

搜广推系统中的双塔模型和 RAG 中的向量检索,一个诞生于推荐系统,一个兴起于大模型时代。当我把两者的架构图放在一起时,突然发现它们竟如此相似——本质上都是在向量空间中寻找最近的"灵魂伴侣"。

搜索算法基石:从 TF-IDF 到 BM25 的演进之路

在搜广推系统中,搜索是最核心的能力之一。本文从信息检索的经典算法 TF-IDF 出发,深入剖析其原理与局限,再引出工业界广泛使用的 BM25 算法,探讨它如何优雅地解决 TF-IDF 的不足。