混合检索(Hybrid Search)
一句话
关键词检索 + 语义检索,双路并行,结果合并。 既能精准命中冷门术语,又能理解同义改写。
为什么需要它
纯 BM25 和纯 Embedding 各有软肋:
| 场景 | BM25 | Embedding |
|---|---|---|
| 搜「LangGraph」这种专有名词 | ✅ 精准命中 | ⚠️ 可能被语义稀释 |
| 搜「怎么让 AI 自己决定查几次」 | ❌ 关键词对不上 | ✅ 语义理解 |
搜缩写/别名(如 MQ → 消息队列) | ❌ 不认识 | ✅ 训练时学过 |
搜代码/编号(如 ERR-5001) | ✅ 精确匹配 | ❌ 向量漂移 |
混合检索 = 取两边的并集,各自发挥优势。
流程
┌─→ ES BM25 关键词检索 ─→ hits_es ─┐
用户问题 ──┤ ├─→ 合并去重 ─→ Rerank
└─→ Milvus Embedding 语义检索 ─→ hits_milvus ─┘实际项目中的典型配置
text
ES: 召回 top 10 (关键词)
Milvus: 召回 top 10 (语义)
合并去重: 按 id,保留分数更高的
Rerank: 精排取 top 3应用场景
| 场景 | 说明 |
|---|---|
| 企业知识库 | 用户可能搜「HR-001 政策」也搜「请假规定怎么走」——术语和自然语言都要覆盖 |
| 电商搜索 | 「iPhone 15 Pro Max 256GB 钛金色」= 关键词;「适合跑步的手机」= 语义 |
| 技术文档 | 函数名、错误码用关键词精准命中;实现方案和教程用语义检索 |
横向对比
| 纯 BM25/ES | 纯 Embedding/Milvus | 混合检索 | |
|---|---|---|---|
| 专有名词/编号 | 🟢 精准 | 🔴 可能漂移 | 🟢 互补 |
| 自然语言问题 | 🔴 词对不上 | 🟢 语义理解 | 🟢 互补 |
| 召回完整性 | 🟡 有漏 | 🟡 有漏 | 🟢 最全 |
| 实现复杂度 | ⭐ | ⭐⭐ | ⭐⭐⭐ |
| 存储成本 | 低 | 高(向量库) | 高(两套) |
优缺点
优点: 互补短长,关键词命中术语、语义兜底表达方式,是当前 RAG 召回阶段的最优解 缺点: 需要同时维护 ES 和 Milvus 两套基础设施,存储成本翻倍,合并去重逻辑需要调校(怎么归一化两种不同维度的分数)
如何选择
text
你的文档特点——
├─→ 都是代码/日志/编号(高度结构化) → 纯 BM25 就够
├─→ 都是教程/博客(自然语言为主) → 纯 Embedding 就够
└─→ 混合(有代码有文档有 FAQ) → 混合检索,不纠结小结
混合检索是 RAG 召回阶段的工程最优解。它不是「哪个更好」的选择题,而是「两个都要」的加法——当你无法预测用户的提问方式时,两条腿走路一定比一条腿稳。