Skip to content

RAG 混合检索与 RRF:向量检索、BM25 如何组合

单独使用向量检索,擅长理解“意思相近”的问题;单独使用 BM25,擅长匹配产品名、错误码、接口名和专有词。企业知识库往往同时包含自然语言说明和大量精确术语,因此 RAG 检索通常需要把两类信号组合起来。

混合检索不是把两个结果列表简单拼接,而是分别召回、统一过滤和去重,再用一个可解释的融合方法计算候选排序。RRF(Reciprocal Rank Fusion)是其中较容易落地的一种方案。

为什么向量检索和 BM25 互补

向量检索把 Query 和文档映射到向量空间,通过相似度寻找语义相关内容。它对同义表达和自然语言提问比较友好,但可能忽略低频关键词、版本号或精确错误码。

BM25 根据词项频率、逆文档频率和文档长度计算相关性。它对 ERR-4012CreateOrder、产品型号等精确词很有效,但对改写、同义词和表达差异不够鲁棒。

可以这样理解两者的分工:

  • 向量召回回答“这段内容是不是在讨论同一个问题”。
  • BM25 召回回答“这段内容是否包含用户明确提到的词”。
  • 混合融合在两种信号都可用时扩大候选覆盖,再交给重排模型或规则做最后筛选。

RRF 的计算方式

RRF 不要求不同检索器返回可直接比较的分数,只使用每个结果在各自列表中的名次。常见公式是:

text
RRF_score(d) = Σ 1 / (k + rank_i(d))

其中 d 是文档或 Chunk,rank_i(d) 是它在第 i 个检索结果中的排名,k 是平滑常数。一个 Chunk 如果同时出现在向量和 BM25 的前列,会累积更高的融合分数;只在单个列表中靠后的 Chunk,得分会相对较低。

例如,设置 k = 60

text
Chunk A: 向量排名 1,BM25 排名 4
score = 1 / 61 + 1 / 64

Chunk B: 只在向量排名 2 出现
score = 1 / 62

RRF 的优点是简单、稳定、容易解释。它不会自动理解业务重要性,也不会替代重排模型。对于需要考虑时效、权限、文档质量或字段权重的系统,还要在融合前后加入明确规则。

一条可维护的混合检索链路

text
Query
  -> 规范化与权限条件构建
  -> 向量召回 topK_vector
  -> BM25 召回 topK_bm25
  -> 权限、租户、状态和版本过滤
  -> 按稳定 chunk_id 去重
  -> RRF 融合
  -> 可选 Reranker 重排
  -> 上下文压缩与生成

权限过滤必须进入检索链路,而不是只在生成后隐藏引用。否则模型可能已经接收到用户无权访问的内容。文档状态、租户和版本也应尽可能在召回阶段过滤,减少无效候选进入上下文。

去重时不要用正文全文作为唯一键,因为相同正文可能来自不同文档版本。更适合使用稳定的 document_id + chunk_id + version,并在版本替换时明确是否保留旧版本。

topK 和融合参数怎么调

先确定目标是提高候选覆盖,还是降低上下文噪音。向量和 BM25 的候选数量可以不同:术语很多的知识库可以提高 BM25 候选数,长文档和自然语言问题则可能需要更多向量候选。

建议用固定评估集进行网格试验,至少记录:

  • 向量召回 Top-K 的证据命中率。
  • BM25 召回 Top-K 的证据命中率。
  • 融合后的 Recall@K 和 MRR。
  • 去重后候选数量与重复比例。
  • 重排后的答案准确性、延迟和 Token 成本。

不要只用最终回答是否“看起来正确”来调参。先确认证据能否进入候选集,再观察重排和生成是否正确使用证据,这样才能定位问题属于召回、排序还是生成。

生产实现中的边界

查询词处理

BM25 对词法很敏感。可以根据业务维护同义词、别名和错误码词典,但不要无条件扩展 Query,否则会引入大量噪音。向量检索也可以使用查询改写,但应记录原始 Query 和改写结果,方便审计和评估。

文档质量与时效

融合排序不能弥补错误文档。索引任务要有文档版本、更新时间和删除状态;同一事实存在多个版本时,应明确最新版本策略,并避免旧版本在 BM25 中因词频高而长期占据前列。

超时和降级

向量服务或 BM25 服务不可用时,系统应有明确降级策略:允许单路检索、返回可解释的暂时不可用,或使用缓存结果。每次召回都应记录耗时、结果数和错误类型,而不是只记录最终 LLM 响应。

常见误区

  • 直接比较向量距离和 BM25 分数,忽略两者量纲不同。
  • 两路结果简单拼接,导致一路结果淹没另一路。
  • 融合前不做权限和版本过滤,把无效内容交给模型。
  • 用正文相等做去重,误删不同来源或不同版本的证据。
  • 只调 RRF 的 k,却没有先建立可重复的评估集。

继续学习

🚀 学习遇到瓶颈?想进大厂?

看完这篇技术文章,如果还是觉得不够系统,或者想在实战中快速提升?
王中阳的就业陪跑训练营,提供定制化学习路线 + 企业级实战项目 + 简历优化 + 模拟面试。