Skip to content

第 6 课:召回策略:Dense、BM25 与 Hybrid

RAG 课程 · 06 |目标:为一个问题选择并实现合适的召回策略|用时:25 分钟

前几课默认使用向量相似搜索,但“语义相似”不是唯一的相关性信号。一个可靠的 RAG 检索层通常会同时考虑语义、关键词、metadata 和候选数量。

三种基本召回方式

Dense retrieval

把 query 和 chunk 分别编码为向量,用 cosine、dot product 或 L2 距离找近邻:

text
query → embedding → 向量索引 → top-k chunks

它擅长处理同义表达,例如 query 是“怎么申请年假”,文档写的是“年度休假办理流程”。它可能不擅长精确的产品编号、错误码、版本号和人名。

Sparse retrieval / BM25

BM25 基于词项匹配和词频、逆文档频率、文档长度进行评分。它擅长精确命中:

  • ERR_CONNECTION_RESET
  • PostgreSQL 15
  • RAGAS
  • 特定合同编号或产品型号

它不会因为“语义相近”就自动理解所有同义表达,但对稀有关键词往往非常有效。

Hybrid retrieval

Hybrid retrieval 同时运行 dense 和 sparse 检索,再合并候选:

text
query
 ├─→ dense search  ─┐
 └─→ BM25 search    ├─→ 融合排序 → 去重 → rerank

这通常比单一检索更稳,但也带来更多参数:两路各取多少、如何融合、重复结果如何处理、延迟是否可接受。

为什么不能只调 top-k

top_k 只是候选数量,不是相关性保证:

  • k 太小:正确 chunk 可能根本进不来。
  • k 太大:噪声进入上下文,增加重排和生成成本。
  • dense 和 BM25 的分数尺度不同,不能直接相加后就认为结果合理。

推荐区分两个参数:

text
candidate_k = 20  # 初始召回,保证覆盖率
context_k = 4     # 重排后进入 prompt 的数量

初始召回服务 Recall@k,最终上下文服务精度、成本和模型可读性。

结果融合

加权分数融合

如果两路分数已经经过校准,可以使用:

text
final_score = α × dense_score + (1 - α) × bm25_score

但不同系统的分数范围和分布往往不同,直接加权可能不稳定。

Reciprocal Rank Fusion

RRF 只使用排名而不是原始分数:

text
rrf_score(doc) = Σ 1 / (k + rank_i(doc))

同一 chunk 在多路结果中都排名靠前,就会获得更高的融合分数。它不需要强行校准不同检索器的分数,适合作为混合召回的可靠基线。

查询处理和过滤顺序

一个实际检索函数可能是:

python
def retrieve(query, user):
    query = rewrite_query(query)

    filters = {
        "tenant_id": user.tenant_id,
        "allowed_groups": {"$in": user.groups},
        "status": "published",
    }

    dense_hits = vector_search(query, filters=filters, limit=20)
    sparse_hits = bm25_search(query, filters=filters, limit=20)
    candidates = reciprocal_rank_fusion(dense_hits, sparse_hits)
    return deduplicate(candidates)[:20]

权限过滤必须在检索层强制执行,不能把不该看的 chunk 召回后再依赖 prompt 要求模型“不要使用”。

什么时候使用哪种策略

数据或问题特征优先策略
同义表达多、自然语言问题Dense
错误码、编号、版本、专有名词BM25 或 Hybrid
企业知识库中既有概念问答又有精确标识符Hybrid
数据量很小、需要建立准确基线Exact/Dense + 人工检查
有权限、租户、时间等强约束任意策略 + metadata filter

不要先凭经验决定最终方案。至少建立 dense、BM25、hybrid 三个基线,在相同 query 集上比较 Recall@k、MRR、p95 延迟和成本。

本课练习

为“公司请假制度”和“服务错误码文档”分别选择召回策略,并回答:

  1. 哪些 query 更适合 dense?
  2. 哪些 query 必须保留 BM25?
  3. hybrid 的 candidate_k 和 context_k 如何设置?
  4. 你会如何验证融合策略真的带来了收益?

主读材料

Introduction to Information Retrieval。重点阅读词项匹配、倒排索引和检索评测相关章节;向量检索是检索系统的一种扩展,不应脱离信息检索基础。

下一步

有任何不清楚的地方,直接向老师提问。