搞懂 RAG 检索召回全链路:从文档切分到阈值匹配
很多开发者第一次做 RAG,上来就纠结用哪个向量模型,结果系统效果怎么调都不行。其实 RAG 的命门不在"生成",而在"检索"——能不能把正确的段落找出来,决定了一切。
这篇文章不写代码、不堆公式,用类比和图把整条链路讲透:文档切分 → 向量化 → 索引 → 检索召回 → 阈值匹配 → 重排 → 生成。读完你能建立一张完整的认知地图,知道每个环节在干嘛、为什么这么干、踩坑点在哪。
适合人群:有开发经验、想系统理解 RAG 原理的工程师。
一、先搞清楚:RAG 到底在解决什么问题
一句话——让大模型"开卷考试"。
大模型有两个硬伤:知识有截止日期(训练完之后的事不知道),也不知道你公司的内部资料。
RAG(Retrieval-Augmented Generation,检索增强生成)的思路朴素得不能再朴素:
用户提问 → 先去文档库里把相关的几段找出来 → 连同问题一起塞给大模型 → 大模型基于这些段落作答。
类比一下就懂了:
- 不用 RAG= 让学生闭卷考试,全凭脑子记,记不全就瞎编(这就是"幻觉"的来源)。
- 用 RAG= 让学生开卷考试,先把相关章节翻出来照着答。
所以 RAG 的核心不是"生成",而是**“检索”**。检索召回这一步做不好,后面的生成再强也是垃圾进垃圾出。
二、整条链路的全景图
RAG 分两个阶段,先记住这张图:
一个关键认知:两个阶段用的必须是同一个 embedding 模型。因为你是用同一种"语言"把文本变成坐标,才能比较问题与段落的距离。就像查字典——建库用中文字典,查的时候也得用同一本,否则对不上。
下面逐块拆。最容易踩坑的四块——切分、检索、阈值、提升效果——是本文重点。
三、文档切分:被 90% 新手低估的地基
很多人一上来就纠结向量模型,其实切分质量对效果的影响往往比模型还大。地基没打好,上面全白搭。
为什么要切
两个原因:大模型有输入长度限制,整本手册塞不进去;整章作为一个检索单元,召回时九成是无关内容,会干扰模型。所以要把长文档切成一段段小块(chunk),每块几百字。
切多大是个权衡
| 块太大 | 块太小 |
|---|---|
| 召回夹带大量无关内容,干扰模型 | 语义被切碎,完整意思跨在两块里 |
| 存储省、检索快 | 块数爆炸、检索慢、重复召回 |
| 阈值判断不准 | 信息冗余 |
经验值:英文 256~512 token,中文 300~800 字。没有标准答案,要按文档类型调。类比切肉——太大不入味,太小吃不出肉味。
重叠(Overlap):防止切断语义
按"每 500 字切一刀、不重叠",骑在边界上的句子会被劈成两半。解决办法是块与块之间留一段重叠,比如每块 500 字、下一块从第 400 字开始(重叠 100 字),边界内容就有冗余保护。
文档: AAAAAA BBBBBB CCCCCC DDDDDD EEEEEE 不重叠(块长3): [AAA][BBB][CCC][DDD][EEE] ← 边界易断 重叠(块长3,重叠1): [AAA][ABB][BBC][CCC]... ← 边界有冗余保护经验值:重叠设为块大小的 10%~20%。
切分策略的演进
- 固定长度切:最简单,但可能劈断句子。
- 按分隔符切:按段落、句号切,保证句子完整。
- 递归切分:先按章节标题切,太大就按段落,再大就按句号,层层降级。LangChain 默认做法,推荐起步用。
- 按结构切:Markdown 按
#标题、代码按函数、HTML 按标签切,能保留章节归属信息。 - 语义切分:用模型判断语义连贯度,在语义跳跃处切。最智能,但最慢最贵。
别忘了元数据
切的时候顺手给每块打标签:来源文件、章节、页码、时间、类别、权限。检索时可以先按元数据过滤再算相似度(“只在 2024 年合同里找”),精准度大幅提升。
口诀:块要"语义完整 + 大小适中 + 带重叠 + 带元数据"。
四、检索召回原理:RAG 的心脏
分四步:向量化 → 相似度 → 加速索引 → 两种流派。
4.1 向量化(Embedding):把文字变成坐标
计算机不懂"苹果",只懂数字。Embedding 模型把任意文本翻译成一串浮点数(768 或 1536 个):
"如何退货" → [0.12, -0.45, 0.88, ..., 0.03] "退款流程" → [0.10, -0.41, 0.85, ..., 0.05] "今天天气" → [-0.77, 0.20, -0.11, ..., -0.60]精妙之处:意思相近的文字坐标离得近,意思无关的离得远。"如何退货"和"退款流程"坐标接近,"今天天气"离得老远。Embedding 本质是给语义建了一张地图。
两个要点:维度(数字个数,常见 768/1024/1536,越高表达越强但越贵);方向比绝对位置重要(下面相似度会用到)。
4.2 怎么算"像不像":相似度计算
三种主流算法,记住结论就行:
| 方法 | 直觉 | RAG 里 |
|---|---|---|
| 余弦相似度(Cosine) | 比两个向量"朝向"夹角 | ✅最常用,首选 |
| 点积(Dot Product) | 既看方向又看长度 | 偶尔用,需先归一化 |
| 欧氏距离(L2) | 两点直线距离 | 较少用 |
为什么余弦最常用?因为它只看方向不看长度。文本向量长度受字数影响,你不想让一段很长的段落"仅因为长就显得更像",所以只比方向更公平。余弦分数范围 -1~1,文本场景实际多为 0~1:接近 1 高度相似,接近 0 几乎无关。
关键认知:相似度 0.8 不是有绝对意义的标量,它是"在当前这个 embedding 模型下"的相对分数。换模型同样的文本分数会变。所以阈值不能抄别人的,得用自己的数据和模型测出来。
4.3 找得快靠什么:近似最近邻(ANN)索引
朴素做法是把问题和全库每个段落两两算一遍——一百万条数据每次提问都算,扛不住。所以向量数据库用索引结构加速,核心思想是用速度换一点精度,快速找到"基本最相似"的,这叫近似最近邻搜索(ANN)。
几种主流索引,知道名字和特点就够:
| 索引类型 | 特点 | 适合 |
|---|---|---|
| HNSW | 图结构,查询快、召回准,吃内存 | 最主流,百万级以下首选 |
| IVF | 先聚类分桶,只在相关桶里找 | 数据量大、要求快 |
| PQ(乘积量化) | 压缩向量省内存 | 海量数据、内存吃紧 |
| Flat(暴力) | 不建索引,两两比 | 数据极小(几千条),100%准确 |
实际产品(Milvus、Qdrant、pgvector、Faiss)常组合使用,如 IVF+PQ。学习者记住默认选 HNSW 就行。还有个ef_search/nprobe旋钮,本质都是"查得越细越准但越慢",是调优杠杆。
4.4 最重要的认知:稠密 vs 稀疏两大流派
这是新手最容易忽略、却最关键的一点。
稠密检索(Dense)= 向量检索:懂语义。问"退货"能召回写着"退款流程"的段落。但对专有名词、编号、人名不敏感——搜"ISO-9001 认证"或"张三的合同"可能一脸懵,因为这些是"符号",没语义可言。
稀疏检索(Sparse)= 关键词检索(经典算法 BM25):精确匹配强。“ISO-9001"“张三"一把就中。但不懂语义,问"退货”、文档写"退款流程”,一个字对不上就召不回。
| 稠密(向量) | 稀疏(BM25) | |
|---|---|---|
| 擅长 | 语义、同义词、泛化 | 精确词、专有名词、编号 |
| 短板 | 符号、罕见词 | 同义改写、跨语言 |
| 类比 | "听懂意思"的助手 | "按字面找"的助手 |
最高心法:好的 RAG 系统几乎都用"混合检索"——两路都跑,结果合并。只要文档里有专有名词、编号、人名,就必须上混合检索,纯向量必翻车。
4.5 召回 vs 排序,别混了
- 召回(Retrieve):从库里捞候选,追求别漏掉该有的,宁可多捞。
- 排序(Ranking):对候选重排,追求把最该靠前的排前面。
工业系统通常召回求全、排序求精,分两步。后面讲的重排就是干排序的。
五、阈值与匹配度:分数到底什么意思
这块踩坑的人最多。把概念彻底拆开。
分数的本质
RAG 里看到的"相似度 0.78"或"匹配度 85%",来源是:向量检索给的是余弦相似度(0~1);BM25 给的是没有固定上下界的分数(可能 0.5 也可能 30);产品为了好看会归一化成 0~100%。
所以"匹配度 85%"离开具体模型和归一化方式,没有绝对意义。它的真正含义是"在这批召回结果里相对排得靠前"。
阈值(Threshold):砍掉不相关的
Top-K 里可能混进分数排进前 K、但其实不相关的段落,阈值就是用一条线把它们砍掉,避免模型被带偏。比如 Top-5 分数[0.86, 0.82, 0.79, 0.55, 0.41],阈值设 0.7,就只把前三条喂模型。
阈值怎么定?这是经验活,没有万能值。那些说"设 0.7"的教程是误导。正确做法:
- 准备一批真实测试问答(50~200 个,带"应召回段落"标注);
- 跑一遍检索,记录每个问题的召回段落和分数;
- 看分数分布:相关的落哪个区间?不相关的落哪?
- 选一个"尽量留住相关、尽量砍掉不相关"的分界线;
- 没有标准答案,持续观察持续调。
新手误区:照抄 0.7;一上来设太高结果啥都召不回;完全不设阈值让模型胡说。
Top-K 怎么选
| K 太小 | K 太大 |
|---|---|
| 可能漏掉正确段落、召回率低 | 噪声多、模型被干扰、占 token 费钱 |
起步值 K = 3~5。简单问题小 K,复杂问题(需综合多处信息)可放大到 10,但配合重排筛掉。
召回太多 vs 太少
- 太少(总得到"没找到"):阈值调低、K 调大、检查切分是不是太碎、检查 embedding 模型是不是太弱、上混合检索。
- 太多但都不准(模型被带偏):阈值调高、K 调小、上重排、检查切分是不是太大。
小结:分数是相对的,阈值要用自己的数据测,Top-K 起步 3~5,永远配一个兜底。
六、提升效果:从"能用"到"好用"
按性价比从高到低排。
6.1 混合检索(性价比第一)
稠密 + 稀疏两路都跑,结果合并。合并不是简单求和(量纲不同),要用加权或归一化:
- RRF(Reciprocal Rank Fusion):不看分数只看排名,"在两路里都靠前"的段落得分高。简单粗暴有效,起步首选。
- 加权融合:两路分数各自归一化到 0~1,按权重相加(如向量 0.7 + 关键词 0.3)。权重靠测试调。
6.2 重排 Rerank(性价比第二)
召回阶段为了快,用的是 embedding(双塔模型,问题和段落各自编码再比相似度,快但粗)。重排用的是交叉编码器(Cross-Encoder):把问题和段落拼在一起喂给模型,细看两者关系,给更准的分数。
召回(embedding): 快、粗、能处理百万候选 → 捞 Top-50 重排(cross-encoder):慢、精、只能处理几十条 → 精排出 Top-5经典的漏斗结构:召回求全,重排求精。重排几乎是生产系统标配。代价是慢,所以只对召回的 Top-N(如 50)重排,不能全库重排。
6.3 查询改写(性价比第三)
用户提问往往口语、模糊、太短,直接检索效果差。常见优化:
- 查询扩展:让大模型把"退货"扩写成"退货 退款 售后 运费"再检索。
- HyDE(假设性文档):先让大模型"猜"一个答案段落,拿这个猜测去检索("答案像答案"比"问题像答案"更易命中)。
- 多查询(Multi-Query):把一个问题改写成 3~5 个不同角度的问法,各检索一遍合并。
- 子问题分解:复杂问题拆成几个子问题分别检索。
核心思想:别拿用户那句粗糙原文去检索,先打磨一下。
6.4 评估指标:被 90% 新手忽略的关键
不评估就是瞎调。准备一个评测集(几十到几百个真实问题,标注"正确答案来自哪些段落"),跑这些指标:
| 指标 | 通俗解释 | 关注点 |
|---|---|---|
| Recall@K | 正确段落有没有进 Top-K | 召回阶段核心指标,越高越好 |
| MRR | 正确段落排第几,排越前分越高 | 看排序质量 |
| NDCG | 排得准不准,重要的排更前得分更高 | 更严格的排序指标 |
| 精确率@K | Top-K 里有多少相关 | 看噪声多少 |
起步盯死 Recall@K(如 Recall@5):让"该出现的段落"尽量进 Top-K,这个上去了重排才有意义。先建评测集,再谈调优,没有评测集的调参都是玄学。
6.5 其他实用技巧
- 上下文扩展:召回某块后把它前后相邻块也带上。
- 元数据过滤:先按来源/时间/类别过滤再向量检索。
- 父子块:小块做精准召回,召回后替换成所属大块喂模型,兼得精度与完整度。
- 去重:混合检索多路结果会重复,记得合并。
- 定期重建索引:文档更新后 embedding 也要更新。
七、一张总图串起所有概念
┌─────────── 用户提问 ───────────┐ │ │ ▼ │ [查询改写/扩展] ← 提升效果 │ │ │ ▼ │ [问题向量化] │ (同 embedding 模型) │ │ │ ┌───────────┴───────────┐ │ ▼ ▼ │ 稠密检索(向量) 稀疏检索(BM25) ← 两大流派 (HNSW 索引加速) (倒排索引) ← 索引 │ │ │ └───────────┬───────────┘ │ ▼ │ [混合融合 RRF] ← 混合检索 │ │ │ ▼ │ Top-50 候选 │ │ │ ▼ │ [重排 Cross-Encoder] ← 重排 │ │ │ ▼ │ Top-5 + 阈值过滤 ← 阈值 │ │ │ ▼ │ [拼 Prompt 喂大模型] │ │ │ ▼ │ 最终回答 │ 离线侧(建库): 文档 → 切分(带重叠+元数据) → 向量化 → 存向量库 ← 切分是地基 持续:用评测集(Recall@K)量化效果,迭代调参 ← 评估是基石八、推荐的学习路线
按这个顺序推进,每一步看得见效果再进下一步,别贪多:
- 第一步(1 天):用 LangChain / LlamaIndex 跑通最简 RAG(固定切分 + 向量检索 + Top-3 + 直接喂模型),目的是建立体感。
- 第二步(2~3 天):换成递归切分 + 重叠 + 元数据,体会切分的影响。
- 第三步(2 天):建小评测集(20~50 个问题),算 Recall@5。从这一刻起告别瞎调。
- 第四步(3~5 天):上混合检索(向量 + BM25 + RRF),对比 Recall 提升。
- 第五步(2~3 天):上重排模型,对比 MRR 和最终回答质量。
- 第六步:查询改写、阈值精调、上下文扩展,按业务痛点逐个加。
每一步都用评测集量化前后对比——这是成长最快的路径。
名词速查表
| 术语 | 一句话解释 |
|---|---|
| RAG | 检索增强生成,先查文档再回答 |
| Chunk | 文档切成的小块 |
| Embedding | 把文本变成一串数字(向量) |
| 向量 | 那串数字,代表文本在语义地图上的坐标 |
| 余弦相似度 | 比较两个向量"方向"夹角,0~1,越大越像 |
| HNSW | 最主流的向量索引,快且准 |
| ANN | 近似最近邻搜索,用速度换一点精度 |
| 稠密检索 | 向量检索,懂语义 |
| 稀疏检索 / BM25 | 关键词检索,精确匹配 |
| 混合检索 (Hybrid) | 稠密 + 稀疏两路合并 |
| RRF | 一种合并多路检索结果的算法(按排名融合) |
| Rerank / Cross-Encoder | 重排模型,对少量候选精排 |
| Top-K | 取相似度最高的 K 条 |
| 阈值 (Threshold) | 砍掉分数过低的不相关结果 |
| Recall@K | 正确段落有没有进 Top-K,核心评估指标 |
| MRR | 正确段落的平均排名质量 |
| Query Rewriting | 查询改写/扩展,先打磨用户问题再检索 |
| 评测集 | 带标准答案的测试问题集,调优的基石 |
写在最后
RAG 这件事,难的不是某一个算法,而是整条链路的每个环节都做到及格。木桶效应在 RAG 上体现得淋漓尽致:切分没做好,向量模型再贵也白搭;检索没召回,重排再强也是无米之炊;没有评测集,所有调参都是凭感觉。
记住三个最容易翻车的点:切分是地基、混合检索是刚需、评估集是前提。把这三件事先做扎实,你已经超过大多数"跑通 demo 就以为搞懂 RAG"的人了。
