向量检索策略与召回优化
作者:程序员马丁
Ragent AI —— 从 0 到 1 纯手工打造企业级 Agentic RAG,拒绝 Demo 玩具!AI 时代,助你拿个offer。
上一篇讲完向量数据库,咱们已经能用 Milvus 做向量检索了——把用户的问题转成向量,在 Milvus 里找最相似的 chunk,看起来很完美。但实际跑起来,你会发现有些场景下纯向量检索会翻车。
假设你在维护一个电商客服知识库,用户问:订单号 2026012345 的物流状态是什么?你把这句话向量化后去 Milvus 里检索,返回的 Top-5 结果可能是:
- 物流配送时效说明
- 如何查询订单物流
- 物流异常处理流程
- 快递公司合作列表
- 订单状态说明
看起来都和物流以及订单相关,但没有一个包含具体的订单号 2026012345。向量检索把 订单号 2026012345 理解成了物流相关的语义,匹配到一堆通用规则,但丢掉了最关键的精确信息——那个具体的订单号。
这就是纯向量检索的短板:它擅长理解语义, 但对精确关键词不敏感。这一篇咱们就来聊聊怎么解决这个问题——通过关键词检索、混合检索、重排序,把检索质量提上去。
纯向量检索的短板:语义很强,但关键词很弱
1. 场景一:精确关键词丢失
再看一个例子。用户问:iPhone 16 Pro Max 的退货政策是什么?
向量检索会把这句话理解成"退货政策"的语义,返回所有和退货相关的 chunk:
- 七天无理由退货说明
- 退货流程和注意事项
- 不支持退货的商品类型
- 退货运费承担规则
- 退货审核时效
这些 chunk 确实都和退货有关,但用户要的是 iPhone 16 Pro Max 这个具体型号的退货政策。如果知识库里有一条专门针对这个型号的规则(比如 iPhone 16 Pro Max 因屏幕定制不支持七天无理由退货),向量检索不一定能把它排到前面,因为它更关注退货这个语义,而不是 iPhone 16 Pro Max 这个精确关键词。
2. 场景二:专有名词和缩写
用户问:RMA 流程是什么?
RMA(Return Merchandise Authorization,退货授权)是一个专有缩写。向量检索可能把它理解成退货流程的语义,返回一堆通用的退货说明,但如果知识库里有一条专门讲 RMA 流程的文档,关键词匹配能直接命中,而向量检索可能把它排到很后面。
3. 场景三:数字和编号
用户问:2026 年春节发货安排是什么?
向量检索会把 2026 年春节理解成春节发货的语义,可能返回历年的春节发货安排(2024 年、2025 年、2026 年都有),但不一定优先返回 2026 年的那条。关键词检索能精确匹配 2026 这个数字,直接命中最相关的结果。
4. 向量检索和关键词检索的互补关系
看完这几个例子,你会发现向量检索和关键词检索各有擅长的地方:
| 维度 | 向量检索 | 关键词检索 |
|---|---|---|
| 擅长场景 | 语义理解、同义词、跨语言、意图匹配 | 精确关键词、专有名词、数字编号、缩写 |
| 典型 query | 买了一周的东西还能退吗(同义词) | 订单号 2026012345(精确匹配) |
| 短板 | 对精确关键词不敏感,容易丢失具体信息 | 无法理解语义,同义词匹配不上 |
| 底层原理 | 把文本转成向量,计算语 义相似度 | 统计词频和文档频率,计算关键词重要性 |
它们不是谁替代谁的关系,而是互补的。理想的检索策略是把两者结合起来——用向量检索理解语义,用关键词检索补充精确匹配,取长补短。
关键词检索:BM25 算法
1. BM25 是什么——一句话概括
BM25(Best Matching 25)是一个经典的关键词检索算法,用来衡量一个查询词在某个文档中有多重要。它是搜索引擎(如 Elasticsearch)的默认排序算法,也是混合检索中关键词检索部分的核心。
打个比方,你在图书馆找书,关键词检索就像是看书名和目录里有没有你要找的词。如果一本书的书名里出现了你要找的词,而且这个词在其他书里很少出现(说明它很有区分度),那这本书大概率就是你要的。
2. BM25 的核心思想
BM25 不需要理解语义,它只看三个核心因素:
2.1 词频(TF):出现越多越相关,但有上限
如果一个词在文档里出现得越多,说明这个文档和这个词越相关。比如用户搜退货,一个文档里退货出现了 10 次,另一个文档里只出现了 1 次,前者大概率更相关。
但这里有个问题:如果一个文档里退货出现了 100 次,是不是就比出现 10 次的文档相关 10 倍?不一定。可能只是这个文档比较啰嗦,或者是机器生成的垃圾内容。所以 BM25 对词频做了饱和处理——出现次数从 1 增加到 10,分数涨得快;从 10 增加到 100,分数涨得慢;再往上基本不涨了。
用一句话概括:出现越多越相关,但有上限,避免长文档刷词占便宜。
2.2 逆文档频率(IDF):越稀有的词越有区分度
如果一个词在所有文档里都很常见(比如:的、是、有),那它没什么区分度,出现了也不能说明文档和查询相关。反过来,如果一个词很稀有(比如:iPhone 16 Pro Max、RMA、订单号 2026012345),那它出现在哪个文档里,哪个文档就很可能是用户要找的。
BM25 用逆文档频率(Inverse Document Frequency,IDF)来衡量一个词的稀有程度。计算方式是:看这个词在多少个文档里出现过,出现得越少,IDF 越高,权重越大。
用一句话概括:越稀有的词越有区分度,越能帮你找到目标文档。
2.3 文档长度归一化 :长文档不能占便宜
如果一个文档很长(比如 5000 字),另一个文档很短(比如 500 字),长文档里出现查询词的概率天然更高。但这不代表长文档就更相关——可能只是因为它废话多。
BM25 会对文档长度做归一化:如果一个文档比平均长度长,它的分数会被打折;如果比平均长度短,分数会被提升。这样长文档和短文档就站在同一起跑线上了。
用一句话概括:长文档不能因为块头大就占便宜,要按长度归一化。
3. BM25 vs 向量检索:不是谁替代谁
把 BM25 和向量检索放在一起对比,你会发现它们的设计思路完全不同:
| 维度 | BM25 关键词检索 | 向量检索 |
|---|---|---|
| 核心思想 | 统计词频和文档频率,计算关键词重要性 | 把文本转成向量,计算语义相似度 |
| 能否理解语义 | 不能。“七天无理由退货”和”买了一周的东西还能退吗”匹配不上 | 能。两句话语义相近,向量距离也近 |
| 能否精确匹配 | 能。“订单号 2026012345”能精确命中 | 不能。数字和编号容易被理解成语义,丢失精确信息 |
| 对同义词的处理 | 不行。“手机”和“移动电话”匹配不上 | 行。Embedding 模型能把同义词映射到相近的向 量 |
| 对专有名词的处理 | 很强。“iPhone 16 Pro Max”能精确匹配 | 一般。可能被拆成“iPhone16”“Pro”“Max”分别理解 |
| 计算成本 | 低。只需要统计词频,不需要调用模型 | 高。需要调用 Embedding 模型把 query 转成向量 |
| 典型应用 | 搜索引擎(Google、Elasticsearch) | 语义搜索、推荐系统、RAG |
看完这个表,你会发现它们是互补的:BM25 擅长精确匹配,向量检索擅长语义理解。所以实际 RAG 系统中,通常会把两者结合起来,这就是“混合检索”(Hybrid Search)。
4. Milvus 中的 BM25 支持
Milvus 从 2.5 版本开始内置了全文检索能力,支持 BM25 算法。你可以在创建 Collection 时指定一个 VarChar 字段用于全文检索,Milvus 会自动对这个字段做分词和倒排索引,支持 BM25 检索。
如果你用的 Milvus 版本低于 2.5,或者对中文分词有更高要求,也可以用外部方案——比如用 Elasticsearch 做关键词检索,Milvus 做向量检索,应用层把两路结果融合起来。这种方案架构复杂一些,但全文检索能力更强。
这一篇咱们用 Milvus 2.5+ 的原生方案,降低环境搭建成本。