> ## Content Index
> Fetch the complete content index at: https://www.hubwiz.com/blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# 混合搜索：向量 + 关键词
- URL: https://www.hubwiz.com/blog/hybrid-search-vector-plus-keyword/
- Published: 2026-04-16T07:32:16.000Z
- Updated: 2026-10-13T16:16:31.000Z
- Description: 当向量搜素不够用时，你可以搭配BM25关键词搜素。
- Author: admin
- Tags: RAG, BM25, #Import 2026-10-14 14:41

向量搜索很强大。你将查询和文档块转换为密集Embedding，测量余弦相似度，并返回最匹配的结果。它捕获语义含义——搜索"输出电压"会找到关于"Vout规格"的块，即使没有共享关键词。

但它有一个关键的盲点。

问：**"第34页上R\_COMP的值是多少？"**

向量搜索会找到语义相似的关于补偿、电阻和组件的块。但`R_COMP`是一个特定的技术符号。它在像`all-MiniLM-L6-v2`这样的通用模型中的Embedding可能无法准确表示它——模型从未见过这个特定IC的文档。你可能会错过 exact page。

这就是**BM25**的用武之地。

## 1、两种搜索范式

```
┌─────────────────────────────────────────────────────────────────┐
│                   搜索范式比较                    │
│                                                                 │
│  向量搜索（FAISS）          BM25关键词搜索             │
│  ─────────────────────          ──────────────────              │
│                                                                 │
│  查询──► Embed──► [0.2, 0.8, ...]    查询──► 分词      │
│                           │                           │         │
│  块──► Embed──► 矩阵            块──► 词频    │
│                           │                           │         │
│  余弦相似度 ◄──────┘             BM25分数 ◄┘         │
│                                                                 │
│  发现：语义相似            发现：精确术语匹配 │
│  遗漏：稀有精确术语               遗漏：改写    │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

```

- BM25——智能关键词搜索

BM25（最佳匹配25）是大多数经典搜索算法（包括Elasticsearch默认）的算法。它根据三个因素对文档进行排名：

- 因素1——词频（TF）

查询词在这个块中出现多少次？更多出现=更高相关性（有递减回报）。

- 因素2——逆文档频率（IDF）

这个词在所有块中稀有吗？稀有术语获得更高权重。像"the"、"is"、"a"这样的常见词获得接近零的权重。

- 因素3——文档长度归一化

长块被惩罚，以防止它们仅因有更多文本而获胜。

**BM25公式：**

```
Score(query, doc) = Σ IDF(t) × [TF(t,d) × (k1+1)] / [TF(t,d) + k1 × (1 - b + b × |d|/avgdl)]

```

其中：

- `k1 = 1.5`——控制TF饱和
- `b = 0.75`——控制长度归一化
- `|d|`——文档长度
- `avgdl`——语料库中平均文档长度

## 2、仅使用单一搜索的问题

让我们用真实查询示例来具体说明：

**查询："软启动期间的静态电流是多少？"**

- 向量搜索：找到关于"启动行为"、"电流限制"、"上电序列"的块——好的语义匹配
- BM25："静态"可能不会出现在附近块中——差的关键词匹配
- **获胜者：向量搜索**

**查询："ISL81801 UVLO阈值是多少？"**

- 向量搜索：`ISL81801`是特定零件号，`UVLO`是特定首字母缩写。这些稀有token的Embedding可能很弱
- BM25：找到`ISL81801`和`UVLO`的精确匹配——直接关键词命中
- **获胜者：BM25**

没有一个能总是获胜。你需要两者。

## 3、倒数排名融合（RRF）

RRF将两个排名列表合并为一个，无需跨不同系统标准化分数。

```python
def reciprocal_rank_fusion(rank_lists, k=60):
    scores = {}
    for rank_list in rank_lists:
        for rank, chunk in enumerate(rank_list):
            chunk_id = chunk["chunk_id"]
            # RRF分数: 1 / (k + rank_position)
            # k=60是防止排名1占主导的平滑常数
            score = 1 / (k + rank + 1)
            if chunk_id not in scores:
                scores[chunk_id] = {"chunk": chunk, "score": 0}
            # 从所有排名列表累积分数
            scores[chunk_id]["score"] += score
    # 按累积的RRF分数排序
    sorted_chunks = sorted(
        scores.values(),
        key=lambda x: x["score"],
        reverse=True
    )
    return [x["chunk"] for x in sorted_chunks]

```

为什么RRF有效？

**示例：3个块，2个搜索系统（k=60）：**

```
FAISS 排名：         BM25 排名：
  排名1: 块A         排名1: 块B
  排名2: 块B         排名2: 块A
  排名3: 块C         排名3: 块D
RRF分数 (k=60):
  块A: 1/(60+1) + 1/(60+2) = 0.01639 + 0.01613 = 0.03252
  块B: 1/(60+2) + 1/(60+1) = 0.01613 + 0.01639 = 0.03252
  块C: 1/(60+3) + 0         = 0.01587 + 0       = 0.01587
  块D: 0        + 1/(60+3)  =       + 0.01587  = 0.01587
最终排名：
  1. 块A（并列）
  2. 块B（并列）
  3. 块C / 块D

```

在**两个**列表中出现的块获得双倍积分。只在一个列表中的块仍然获得部分积分——它们不会被丢弃。

## 4、完整的混合检索流程

```
用户查询："UVLO阈值电压是多少？"
                    │
         ┌──────────┴──────────┐
          │                     │
          ▼                     ▼
   FAISS向量搜索           BM25关键词搜索
   (top_k=5)              (top_k=5)
          │                     │
          │  [第3页]           │  [第3页]   ←两者一致
          │  [第12页]          │  [第7页]
          │  [第7页]           │  [第15页]
          │  [第19页]          │  [第19页]
          │  [第34页]          │  [第34页]  ←两者一致
          │                     │
          └──────────┬──────────┘
                     │
                     ▼
             RRF融合 (k=60)
                     │
               [第3页]   ←顶部（两者都出现，高排名）
               [第34页]  ←强（两者，中排名）
               [第7页]
               [第12页]
               [第19页]
               [第15页]
                     │
                     ▼
           Cross-encoder重排器
           (最终top-3选择)

```

在两个搜索运行之前，查询使用领域特定的同义词进行扩展：

```python
SYNONYMS = {
    "input voltage":    "vin input supply voltage operating voltage",
    "output voltage":   "vout output regulation output range",
    "switching frequency": "fsw oscillator frequency",
    "efficiency":       "efficiency power conversion efficiency",
}
for key, value in SYNONYMS.items():
    if key in query:
        query += " " + value

```

这为BM25提供更多匹配术语，为向量编码器提供更丰富的语义输入。

## 5、结束语

关键洞察：混合搜索在术语查询上比纯向量搜索提供约15%的MRR改进。BM25处理那些让Embedding模型犯错的精确缩写和零件号。

---

原文链接：[Hybrid Search: Why Vector Search Alone Is Not Enough](https://medium.com/@arunsarathi/hybrid-search-why-vector-search-alone-is-not-enough-3ed8fc323228?ref=hubwiz.com)汇智网翻译整理，转载时请标明出处

> **这是「RAG / 数据 / 文档智能」专题的一部分。**完整地图见：[RAG / 数据 / 文档智能完全指南](https://www.hubwiz.com/blog/rag-data-stack/)