Hybrid Search

混合检索

向量检索 + BM25 关键词检索结合,弥补各自的盲区。

详解

混合检索(Hybrid Search)把语义向量检索和 BM25 关键词检索的结果融合,弥补两者各自的盲区。纯向量检索理解语义,但对精确词汇(产品型号、人名、代码关键字)不敏感——搜"iPhone 15 Pro Max"时可能返回泛谈苹果手机的文章;BM25 精确匹配关键词,但不理解语义——搜"汽车维修"找不到"车辆保养"的文章。融合通常用 RRF(互惠排名融合,Reciprocal Rank Fusion):对每条文档取两路结果的名次倒数之和作为最终分数,公式为 score = Σ 1/(k + rank),k 通常取 60。RRF 的优势是只看名次不看原始分数,避免了 BM25 分数(0-∞)和余弦相似度(0-1)量纲不统一的问题。实测在多个基准集上,混合检索的排序质量比单一向量检索提升约 5-8%。

一个类比
找餐厅时同时问两个朋友:一个朋友(BM25)严格按你说的关键词推荐,"川菜"就找含"川菜"的店;另一个朋友(向量)理解你的偏好,推荐口味相近的重庆火锅或贵州酸汤鱼。综合两人的推荐列表,排名靠前的优先——结果比只听一个人强。
举个例子
RRF 融合两路检索结果(示意):

```python
def rrf_merge(bm25_ranks: list, vector_ranks: list, k: int = 60) -> dict:
    """输入两路文档名次列表,输出融合后的分数字典"""
    scores: dict[str, float] = {}
    for rank, doc_id in enumerate(bm25_ranks, start=1):
        scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank)
    for rank, doc_id in enumerate(vector_ranks, start=1):
        scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank)
    return dict(sorted(scores.items(), key=lambda x: x[1], reverse=True))

bm25_result   = ["doc_A", "doc_C", "doc_B"]
vector_result = ["doc_B", "doc_A", "doc_D"]
print(rrf_merge(bm25_result, vector_result))
# doc_A 两路都排前列,分数最高
```
PYTHON 示例
相关概念