混合检索: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
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 查询的组合。
{
"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 值。