混合检索到底在混什么:为什么纯向量检索会认错人——Hybrid RAG 系列之一

一句话价值:RAG 的检索不能只靠向量。向量能抓住「意思像不像」,却抓不住「词对不对」------专业术语、人名、订单号这类精确实体,纯语义检索会认错人。混合检索就是让「关键词检索」和「语义检索」互补,用两套索引各管一半,再融合成一份结果。这是检索从「能查到」到「查得准」的关键一步。


先看纯向量检索的三个翻车现场

前面系列提过「高血糖 / 低血糖」语义相近、向量分不清。其实这类翻车每天都在发生,而且更隐蔽:

  • 精确实体:问「第 40 回讲了什么」,向量可能返回「第 39 回」或「第 41 回」------三者的语义都是「某个回目的剧情」,向量距离很近,但它分不清数字。
  • 专有名词:问「段誉」,向量可能优先返回「乔峰」相关段落------两人都是主角、都活跃在江湖,语义上「近」,但用户要的是精确命中「段誉」两个字。
  • 型号 / 订单号:问「PO-20250409-K9 这个订单」,向量对这类精确串几乎无能为力------它记的是「含义」,不是「字符」。

根子在哪? 向量检索回答的是「哪段话和问题意思最像 」,而很多查询要的是「哪段话包含这个词」。这是两件不同的事,一个模型干不了两个活。

三个存储,各管一件事

聊混合检索之前,先把三种存储的定位摆正------很多人把 ES 当 MySQL 用、把 Milvus 当「又一个数据库」,这是混乱的开始:

MySQL Milvus Elasticsearch
类型 关系型数据库 向量数据库 搜索引擎
底层索引 B+ 树 向量索引(HNSW) 倒排索引
核心动词 存 比 找
擅长 精确查询、事务、关联 语义相似度 关键词精确命中

记住最后一行:MySQL 是「存」、Milvus 是「比」、ES 是「找」。它们不冲突,反而互补。混合检索就是让「比」(Milvus)和「找」(ES)各干各的,再合到一起。

ES 的杀手锏:倒排索引

ES 为什么能毫秒级在几亿条文档里「找词」?因为它用倒排索引把「搜内容」变成了「查表」。

正排 vs 倒排。 正排是「文档 → 词」(MySQL 的思路),要查「哪些文档包含『杭州』」,只能一条条扫描正文。倒排把它反着存------「词 → 文档列表」:

css 复制代码
杭州 → [doc1, doc3]
西湖 → [doc1]
城市 → [doc2]

查询「杭州」时,直接查词典找到「杭州」,立刻拿到 [doc1, doc3]------不扫任何文档。

三层结构。 真正的倒排索引比上面这张图更细:

  1. 词典(Term Dictionary):所有不重复的词,按字典序排好,是「入口」。
  2. 倒排列表(Posting List):每个词对应的一串文档 ID。
  3. 附加信息 :每个 doc ID 后面还跟着 TF(词频) 和 Position(位置)------前者算相关度,后者做短语匹配和高亮。

写入与查询两段式。 写入时,文档经过 analyzer 分词(比如 IK 中文分词),把词逐个登记进倒排索引;查询时,query 分词后查词典拿列表、取交集/并集,再用 BM25 打分排序------BM25 的核心是「词越罕见(IDF 高)、出现越频繁(TF 高)、文档越短,越相关」。

中文检索的关键是 IK 分词器 :写入用 ik_max_word(最细粒度,保证召回),查询用 ik_smart(最粗粒度,保证精度)。没有它,中文会被切成一个个单字,倒排索引直接失效。

落地到 create.mjs,就是建索引时给正文字段配上这套分词策略:

js 复制代码
note_body: {
  type: 'text',
  analyzer: 'ik_max_word',      // 写入:切得细,召回多
  search_analyzer: 'ik_smart'   // 查询:切得准,噪声少
}

混合检索的骨架:两条腿走路

于是答案浮出水面:

flowchart LR A[chunk 内容] --> B[embeddings 向量] --> C[Milvus 语义 Top-K] A --> D[Elasticsearch 倒排] --> E[关键词 Top-K] C --> F[RRF 融合] E --> F F --> G[rerank 精排] G --> H[生成]
  • ES 管「词对不对」:精确名词、编号、术语,倒排索引精确命中。
  • Milvus 管「意思像不像」:换种说法、语义相近但用词不同,向量能捞回来。
  • 两路召回后,还要融合 (RRF)和精排(rerank)------这是后面两篇的事。

本篇小结

  1. 纯向量检索抓「意思」,抓不住「词」------精确实体、专有名词、型号会认错人。
  2. 三种存储定位:MySQL 存 、Milvus 比 、ES 找,各管一件事。
  3. ES 的倒排索引把「搜内容」变成「查表」,靠「词 → 文档列表」毫秒级命中。
  4. 混合检索 = ES 关键词 + Milvus 语义,两路互补,再融合精排。

系列预告

  • 下一篇:Milvus 向量 + RRF 融合------语义侧怎么召回,两路「量纲不可比」的分数怎么合成一份。
  • 之后:rerank 精排------为什么融合完还要再「拧一遍」,完整三段式怎么落地到代码。
相关推荐
Jlzn88883 小时前
华东电芯分选通道数怎么配才不堵线
java·人工智能·架构·自动化·制造
CCblandy3 小时前
雪花 ID 四个边界实测:时钟回拨重号 500 个,前端 JSON.parse 直接丢精度
后端·python·算法·性能优化·架构
阡陌数智4 小时前
Gemini 4 Argon 百万 Token 输出能力解析:原生长输出模型的工程落地与并发成本治理
人工智能·架构
海宇数据7 小时前
零信任架构实战:基于海宇入职背调报告构建自动化即时配送与网约车众包运力准入鉴权网关
运维·人工智能·架构·自动化
天远API7 小时前
零信任架构实战:基于天远公安二要素政务版构建自动化不动产交易与契税核算实名核实网关
人工智能·架构·自动化·php
预知同行8 小时前
深入解析 MoE 混合专家模型:从 Router 到 All-to-All 的架构全景与生产实践
后端·架构
Linye8 小时前
换个会话就忘了方案?我把项目约定写成了一个文件
架构
KylinLab8 小时前
四条主张五条禁令:人不在环内的组织级契约
架构
奔跑的架构师8 小时前
[A-51]ARMv9/v8-SCMI系统架构
linux·arm开发·架构·系统架构·arm
糖果豆豆8 小时前
让 AI 自查三遍,它只会把错的说得更像对的——检查的人和被检查的,是同一个
算法·架构