第四章 · 检索策略与召回优化
本章定位:前三章把文档切块、贴元数据、向量化入库。现在用户提问了——怎么从这几万个向量里召回最相关的块?这是 RAG 的「中场」,召回质量直接决定最终答案的上限。召回率差,再好的生成模型也只能基于垃圾上下文编故事。
本章分两部分:
- 上篇 · 概念与原理(科普):纯向量检索的短板是什么?BM25 关键词检索怎么补位?混合检索怎么融合两种分数?RRF 是什么?为什么需要重排序?MMR 去冗余怎么做?
- 下篇 · SparkX 源码落地(实践):SparkX 的多通道检索架构(向量+关键词+图谱)、后处理器链(去重→父块展开→RRF→图谱扩展)、两层融合设计、重排与 MMR 协同,逐一拆解。
上篇 · 概念与原理
一、纯向量检索的短板:语义很强,但关键词很弱
第三章讲了向量检索的强大——它能理解语义,「东西坏了」能匹配到「质量问题」。但纯向量检索有三个明显的盲区。
1. 场景一:精确关键词丢失
用户搜「iPhone 15 Pro Max 的保修政策」。向量检索理解了「保修政策」的语义,但可能召回一堆「手机售后」「电子产品质保」的结果,唯独漏掉了标题里精确写着「iPhone 15 Pro Max」的那条——因为向量更看语义相近,而非字面精确。
2. 场景二:专有名词和缩写
用户问「K8s 集群怎么扩容」。向量检索可能把「容器编排」「Kubernetes」「集群管理」都召回(语义相近),但如果文档里这个词写的是「Kubernetes」而用户搜「K8s」,向量可能给不出高相似度——专有名词的字面精确匹配,向量反而不擅长。
3. 场景三:数字和编号
用户查「工单 #20240315」。向量检索对数字几乎无语义理解——「20240315」和「20240316」在向量空间里可能很近,但用户要的是精确那一条。这种场景只有关键词精确匹配能搞定。
4. 向量检索和关键词检索的互补关系
| 擅长 | 向量检索 | 关键词检索 |
|---|---|---|
| 语义理解(同义词、近义词) | ✅ 强 | ❌ 弱 |
| 精确匹配(专有名词、型号、编号) | ❌ 弱 | ✅ 强 |
| 长尾词、生僻词 | ❌ 容易漏 | ✅ 字面命中 |
结论:两者不是谁替代谁,而是互补。最好的方案是两者都做,再融合结果——这就是混合检索。
二、关键词检索:BM25 算法
1. BM25 是什么——一句话概括
BM25(Best Matching 25)是关键词检索最经典的打分算法,用来衡量「一篇文档和查询的相关度」。Elasticsearch、Lucene、PostgreSQL 全文检索都基于它的变体。
2. BM25 的核心思想
BM25 综合三个因素打分:
2.1 词频(TF):出现越多越相关,但有上限
查询词在文档里出现得越多,相关度越高。但有饱和上限——出现 100 次不一定比 10 次相关 10 倍,避免长文档靠堆字数占便宜。
2.2 逆文档频率(IDF):越稀有的词越有区分度
「的」「是」这种词每篇文档都有,几乎没有区分度;而「iPhone15」「K8s」这种稀有词一旦匹配上,相关性权重很高。IDF 让稀有词的匹配权重远高于常见词。
2.3 文档长度归一化:长文档不能占便宜
长文档天然更容易包含查询词(字多概率大),但未必更相关。BM25 对文档长度做归一化,让长短文档公平竞争。
3. BM25 vs 向量检索:不是谁替代谁
| 维度 | BM25 | 向量检索 |
|---|---|---|
| 匹配方式 | 字面精确匹配 | 语义相似度 |
| 优势 | 精确词、型号、编号、专有名词 | 同义词、近义词、模糊语义 |
| 劣势 | 不懂同义词(「坏了」≠「损坏」) | 不擅长精确匹配、数字 |
| 计算 | 快(倒排索引) | 较慢(向量运算) |
🔒 以上为本章部分预览(约 10%)
本章剩余 90% 内容包含:关键源码逐行拆解、设计细节与工程权衡、代码示例与生产实践要点。
💡 本次展示的仅为部分预览内容(约 10%)。完整的源码深度解析包含每一个技术点的完整实现细节。点击上方按钮扫码加入知识星球,解锁全部内容。