RAG 混合检索为何采用排名融合
一个销售情报 RAG 原型结合向量检索与 BM25,分别处理语义改写和精确词匹配,再用 RRF 融合排名,避免直接混合不同尺度的分数。项目包含 50 个单元测试和 20 道评估题,尚未部署。
AI 深度解读
做 RAG 时,检索不到正确材料,后面的回答再流畅也没用。作者用一个 B2B 销售情报原型说明:语义检索和关键词检索各有盲区,先用倒数排名融合(RRF)合并候选,再重排,比单押一种检索方式更适合这批数据。
这份原型有 50 个单元测试、20 道评估题,没有部署。它值得看的地方,是把检索、切块和评估拆开验证;但这些结果能支持哪些判断,也需要划清范围。
为什么懂语义,还会漏掉客户名称
销售人员可能会问:上个季度,东北地区哪些客户在通话中提过预算冻结?证据散落在 CRM 备注、通话转录和客户计划里,一次查询同时包含两种需求:理解意思,以及认准具体名称。
稠密检索(Dense retrieval)通过嵌入向量匹配语义,能把「预算冻结」和「暂停支出」联系起来。但客户编码、产品 SKU、姓氏、地区字符串这类精确标记,是它的弱项。
稀疏检索(Sparse retrieval)中的 BM25 擅长匹配具体词项和日期,却不擅长识别改写。同一件事换一种表达,就可能漏掉。
因此,作者让两路检索一起工作。在这批销售语料上,BM25 单独使用优于稠密检索,融合后又优于两者。作者给出的解释是:销售问题里专有名词很多。
这也提醒我们,检索方案要跟着问题走。「能理解语义」并不自动等于「更适合业务」。
为什么合并排名,比直接混合分数省事
最直接的合并方式是 final = a * dense_score + b * bm25_score。问题在于,两路分数的尺度和分布不同,直接相加,数值较大的一路可能占尽优势;换一批语料,合适的 a、b 也可能变化。
RRF 避开了分数尺度,改看名次。每个检索器输出有序文档列表,每份文档按 1 / (k + rank) 获得贡献,再把各路贡献相加,k 通常取 60。
大白话理解:不比较两位评委各自打了多少分,而是比较他们把候选排在第几。两路都排第一的文档会领先,只被一路排在前面的文档也保留机会。
下面这段代码负责把多份排名合成一个结果列表:
def rrf(ranked_lists, k=60, weights=None):
scores = defaultdict(float)
for i, docs in enumerate(ranked_lists):
w = (weights or [1.0] * len(ranked_lists))[i]
for rank, doc_id in enumerate(docs, start=1):
scores[doc_id] += w / (k + rank)
return sorted(scores, key=scores.get, reverse=True)
要看的是 scores[doc_id] += w / (k + rank):它累计名次贡献,不使用原始相关性分数;rank 从 1 开始,weights 则允许调整各路权重。
作者说,评估中权重几乎不需要改动。不过,「只剩一个调节旋钮」是简化表述:函数仍暴露了 k=60,权重本身也可能有多个取值。更准确的收益是减少处理异构分数的麻烦。
前 50 条找得全,不代表前 5 条排得准
作者把 RRF 和重排分成两步:融合负责得到较好的前 50 个候选,重排负责改善前 5 个结果。
交叉编码器(cross-encoder)会把问题与每个候选一起读取,直接判断相关性。它不适合扫描整个语料库,但可以处理缩小后的候选集合。原型使用了一个小型开放 cross-encoder,具体模型名没有交代。
在这次评估里,从融合结果到重排结果,是作者观察到的最大质量提升。原文没有给出提升幅度,也没有延迟数据,所以还不能据此判断其他项目能获得多少收益。
评估集只有 20 道题,每题包含预期来源文档和参考答案。作者分别检查两件事:
- 用 recall at k 衡量检索召回,检查预期文档有多少进入前 k 个结果。
- 用 LLM judge 评价回答是否忠于检索上下文,以及是否覆盖参考答案。
检索有没有找对材料,应该和回答写得怎么样分开评估。
这套题还暴露了两个问题。首先,切块大小比嵌入模型选择更影响结果:通话转录适合较小且有重叠的块,客户计划适合保留完整章节。其次,LLM judge 对含糊、保守的回答偏宽容,忠实度评分需要严格规则,否则容易奖励没有提供多少信息的回答。
我的判断
我认同这条路线的工程价值:先用互补检索扩大候选,再用重排提高前列质量,同时用独立指标检查每一步。相比直接调分数加权,RRF 的处理方式更容易解释,也少了一部分校准负担。
但「融合胜过单路」「切块比模型重要」「重排提升最大」,都是作者在这批语料和 20 道题上的观察。原文没有列出具体召回率、对照模型或统计结果,应把它们当作值得验证的经验,不能当成通用结论。
运行状态也要算进判断:依赖锁定在 CI 中未能解析,50 个单元测试只在本地运行过,没有部署和生产流量。作者对 RRF 长期可靠性的评价同样属于经验之谈。
另外,示例问题包含地区和季度约束,原文没有说明如何做结构化过滤。BM25 能匹配日期词项,并不等于已经正确实现时间范围筛选。
能拿来做什么
- 给现有 RAG 留一组真实问题,并标注预期来源文档;改检索方式前后,先比较 recall at k,再比较回答质量。
- 当问题同时包含业务术语、客户名称和语义改写时,把 BM25、稠密检索和 RRF 作为三组对照,验证融合是否适合自己的语料。
- 按文档类型调整切块:通话转录尝试小块加重叠,客户计划尝试保留章节,不要只盯着更换嵌入模型。
- 如果候选已包含正确证据但排序靠后,再评估 cross-encoder 重排;同时记录每次查询的文档 ID 和分数,方便回放失败案例,并检查销售材料的新鲜度。