Skip to content

混合检索:BM25 与向量检索的加权融合

在 RAG 系统中,我们最先想到的就是向量检索(Semantic Search)。 它能理解“苹果”和“水果”是相似的,这是关键词检索做不到的。 但是,它有一个致命弱点:精确匹配 (Exact Match)。 用户搜 "Error 503",向量检索可能会给你找出一堆关于 "服务器错误"、"网络连接" 的文档,但就是找不到包含 "503" 这个具体数字的那一篇。 这时候,传统的关键词检索(Keyword Search / BM25)就显得无可替代了。

1. 什么是混合检索?

混合检索 (Hybrid Search) 就是同时使用向量检索和关键词检索,并将两者的结果进行加权融合。

  • Vector Search:负责语义理解,召回语义相关但词汇不完全匹配的文档。
  • Keyword Search:负责精确匹配,召回包含特定术语、数字、代码的文档。

2. 融合算法:Reciprocal Rank Fusion (RRF)

如何将两个不同维度的分数(Score)合并?

  • Vector Score:0.85 (Cosine Similarity)
  • BM25 Score:12.5 (TF-IDF based) 这两个分数不在一个量级,不能直接相加。 RRF 是一种简单而有效的排名融合算法。 它不关心具体分数,只关心排名(Rank)。

2.1 RRF 公式

$$ RRF(d) = \sum_{r \in R} \frac{1}{k + r(d)} $$ 其中,$d$ 是文档,$r(d)$ 是该文档在某个检索列表中的排名,$k$ 是常数(通常取 60)。

2.2 示例

假设有两个检索列表:

  • List A (Vector): [Doc1, Doc2, Doc3]
  • List B (BM25): [Doc3, Doc1, Doc4]

计算 Doc1 的 RRF 分数:

  • Rank in A: 1 -> Score: 1/(60+1) = 0.0164
  • Rank in B: 2 -> Score: 1/(60+2) = 0.0161
  • Total RRF: 0.0164 + 0.0161 = 0.0325

计算 Doc3 的 RRF 分数:

  • Rank in A: 3 -> Score: 1/(60+3) = 0.0159
  • Rank in B: 1 -> Score: 1/(60+1) = 0.0164
  • Total RRF: 0.0159 + 0.0164 = 0.0323

Doc1 > Doc3,所以最终排序是 [Doc1, Doc3, ...]。

3. 工程实现:Elasticsearch / Weaviate

现代向量数据库(如 Weaviate, Qdrant)和搜索引擎(Elasticsearch)都内置了 Hybrid Search。

3.1 Weaviate Example

python
response = (
    client.query
    .get("Article", ["title", "content"])
    .with_hybrid(
        query="What is the capital of France?",
        alpha=0.5, # 权重因子:0.5 表示 Vector 和 Keyword 各占一半
    )
    .do()
)

3.2 Elasticsearch KNN + BM25

ES 8.x 支持 knn 查询和普通 match 查询的组合。

json
{
  "knn": {
    "field": "embedding",
    "query_vector": [...],
    "k": 10,
    "num_candidates": 100
  },
  "query": {
    "match": {
      "content": "France capital"
    }
  },
  "rank": {
    "rrf": { # 使用 RRF 融合
      "window_size": 100,
      "rank_constant": 60
    }
  }
}

4. 权重调节 (Alpha Tuning)

alpha 参数决定了 Vector 和 Keyword 的重要性。

  • Alpha = 1: 纯 Vector Search。
  • Alpha = 0: 纯 Keyword Search。
  • Alpha = 0.5: 均衡。

最佳实践

  • 对于专业领域(医疗、法律、代码),关键词往往非常精确,调低 Alpha(如 0.3),侧重 Keyword。
  • 对于通用问答(客服、闲聊),用户表达比较随意,调高 Alpha(如 0.7),侧重 Vector。

混合检索是 RAG 系统的标配。 不要指望单一的向量检索能搞定所有 Query。 特别是当用户搜 "iPhone 15 Pro Max 256GB" 这种极其具体的型号时,BM25 比 Embedding 靠谱得多。 架构师的任务,就是根据业务场景,找到那个最佳的 Alpha 值。