等级 L4 · 每天 40 分钟 · 场景:做RAG→二、检索链路怎么搭
一句话:RAG 的本质是「先查再答」——把相关资料检索出来塞进上下文,让模型基于它回答而不是靠记忆编。所以 RAG 项目做不好,九成是检索没做好,不是模型不行。它本质是个搜索工程问题。
学习地图
| 你的问题 | 看哪一节 |
|---|---|
| 「什么时候该上 RAG」 | 一、先判断要不要做 |
| 「整条链路怎么搭」 | 二、检索链路怎么搭 |
| 「文档怎么切」 | 三、切块 |
| 「检索出来的不相关」 | 四、召回与重排 |
| 「怎么知道效果好不好」 | 五、评估 |
| 「检索不到时怎么办」 | 六、失败路径 |
前置:LLM应用开发——RAG 是在它之上加了一层检索。
一、先判断要不要做
RAG 不是默认选项。 三种更简单的方案先排除掉:
| 场景 | 更该用 |
|---|---|
| 资料量小(几万 token 以内)且相对固定 | 直接全塞进上下文 + prompt caching。没有检索环节就没有检索错误 |
| 只是术语/规则的口径统一 | 写进系统提示词 |
| 结构化数据的精确查询 | 老老实实查数据库。「上季度华东区销量」是 SQL 问题,不是 RAG 问题 |
上下文窗口越来越大,第一种方案的适用范围在扩大。别因为「RAG 听起来更专业」就上一套检索系统。
什么时候确实该上
- 资料量远超上下文窗口(内部文档库、历史工单、代码库)
- 资料频繁更新,不可能每次全量塞
- 需要引用来源(「这个结论出自哪份文档」)
- 全量塞成本上不划算
一个常被忽略的前提:资料本身得靠谱
RAG 的天花板是你的资料质量。资料本身过期、矛盾、缺失,RAG 只会把错误答案检索得更快。 上 RAG 前先问:这批文档有人维护吗?矛盾的版本清理过吗?
二、检索链路怎么搭
【离线】原始文档 → 清洗 → 切块 → 向量化 → 写入索引
【在线】用户提问 → 改写 → 混合检索 → 重排 → 拼上下文 → 生成 → 引用标注
每一环都可能是效果瓶颈。排查顺序应该反着来:先确认检索出来的东西对不对,再怀疑生成环节。
一个实用的诊断方法:把检索结果直接打印出来自己看。如果人看了都找不到答案,那问题在检索,调提示词没用。这一步能省掉大量瞎调。
三、切块
切块是最影响效果、也最容易被随便对付的一环。
三种切法
| 策略 | 做法 | 适用 |
|---|---|---|
| 固定长度 | 按 token 数硬切 | 兜底方案,效果最差 |
| 结构感知 | 按标题层级/段落/章节切 | Markdown、有格式的文档,首选 |
| 语义感知 | 按语义相似度找切分点 | 长篇无结构文本,成本高 |
优先按文档自身结构切。 Markdown 按标题层级、代码按函数/类、工单按字段——文档作者已经帮你划好边界了,不用再猜。
两个关键参数
块大小:太小丢上下文(一句话不知道在说什么),太大引入噪音(一块里混了三个主题)。没有普适值——要按你的资料实测,从中等粒度开始双向试。
重叠:相邻块之间保留一定重叠,防止答案正好被切在边界上。经验值是块大小的 15~20%。
给每块带上元数据
这是低成本高收益的一步:
块内容:……
元数据:文档标题 / 所属章节 / 更新时间 / 来源链接 / 权限标签
好处有三个:过滤(只检索某个产品线、某个时间之后的)、权限(用户只能检索到他有权看的)、引用(回答时能指出来源)。权限过滤必须在检索层做,不能靠提示词让模型「不要透露」——那挡不住。
四、召回与重排
只用向量检索是不够的
纯向量检索的弱点很明确:精确匹配差。用户搜一个错误码、一个产品型号、一个人名,向量检索经常召不回——因为它匹配的是语义相似度,不是字面。
默认方案应该是混合检索:向量检索(语义)+ 关键词检索(BM25,字面)结果融合。两者互补,这是当前的工程共识,不是可选优化。
加一层重排
检索先粗召回一批(比如 50 条),再用重排模型精排,取 top 几条进上下文。
为什么值得加一层:
- 粗召回优化的是「别漏」,重排优化的是「排得准」,目标不同
- 进上下文的条数直接影响成本和效果——塞太多反而变差(相关信息被噪音淹没)
- 重排模型比向量检索更懂「这段是不是真的回答了这个问题」
查询改写
用户的原始提问经常不适合直接拿去检索:
- 口语化、有指代(「它的价格呢」——「它」是上一轮说的东西)
- 太短,信息不足
- 一个问题里包含多个子问题
常见处理:多轮对话中把指代补全成完整问题;复杂问题拆成多个子查询分别检索。
五、评估
没有评估集,RAG 调优就是玄学。 这是 RAG 项目最容易跳过、也最致命的一步——凭感觉调,调到后面自己都不知道是变好了还是变坏了。
最小可用的评估集
不需要很大,30~50 条真实问题就能开始:
| 字段 | 说明 |
|---|---|
| 问题 | 真实用户会问的,不是你编的 |
| 期望答案要点 | 不用逐字,列出必须提到的关键点 |
| 标准来源 | 答案应该来自哪个文档/哪一段 |
分开评检索和生成
这是关键——两个环节要分开测,否则你不知道该改哪里:
| 环节 | 看什么 | 怎么判断 |
|---|---|---|
| 检索 | 标准来源有没有被召回、排第几 | 召回率、命中位置 |
| 生成 | 答案要点覆盖了几个、有没有编造 | 逐条人工核 / 用模型辅助打分 |
先保证检索指标,再调生成。 检索没召回,提示词怎么调都是无米之炊。
用模型当裁判要小心
用另一个模型给答案打分能省人力,但它自己也会出错。做法:先人工标 20 条,验证裁判模型的打分和人工一致,再用它批量跑。不验证就直接用,可能在优化一个错误的指标。
六、失败路径
生产 RAG 的核心问题不是「怎么杜绝检索失败」——它一定会失败,用户会问文档里根本没覆盖的问题。真正该设计的是:检索失败时系统怎么表现。
三种表现,从坏到好:
| 表现 | 后果 |
|---|---|
| 检索为空,仍然让模型自由回答 | ❌ 最糟——直接输出幻觉,用户还以为有依据 |
| 检索为空,返回「没找到」 | 🟡 及格 |
| 检索为空,返回「没找到」+ 相近内容 + 引导 | ✅ 好 |
三条工程约束
① 检索结果为空/低分时要短路
设一个相关性阈值。低于阈值就直接返回「没有找到相关资料」,不要把空上下文丢给模型让它自由发挥——那正是幻觉最容易发生的地方。
② 强制要求引用
在提示词里明确:只能基于给定资料回答,每个结论标注来自哪一段;资料里没有的,明确说没有。
这不只是体验——引用让用户能自己验证,把「相信 AI」变成「核对来源」。
③ 让用户能反馈
「这个回答有用吗」的按钮不是产品需求,是你的评估集来源。用户点踩的问题,就是下一轮该补的评估用例。
常见追问
-
上下文窗口都上百万了,还需要 RAG 吗? 需要,但门槛提高了。三个原因窗口大解决不了:贵(每次塞满的成本极高)、慢(输入越长首字延迟越高)、准(相关信息淹没在无关内容里,效果反而下降)。现在的实际影响是:切块可以更粗、召回条数可以更多,但检索这一环不能省。
-
向量库怎么选? 先问数据量。百万级以下,你现有的数据库可能就够——主流关系库和搜索引擎都有向量检索能力,省一个组件比引入一个新中间件划算得多。真到了需要专用向量库的量级时,选型考虑的是过滤能力、混合检索支持、运维成本,而不是宣传的检索速度。
-
嵌入模型怎么选? 三个实际约束:支不支持中文(很多模型中文效果差)、维度和成本(维度越高存储和检索越贵)、能不能私有化部署(数据不出内网时是硬约束)。选定后不要随便换——换嵌入模型意味着全量重新向量化。
-
文档更新了怎么同步? 按更新频率选:低频全量重建最简单;高频要做增量(按文档 ID 删旧块写新块)。一定要有版本/时间戳,否则删不干净会留下幽灵块——用户拿到已删除文档的内容,这是很难排查的事故。
-
RAG 和微调怎么选? RAG 解决「模型不知道这些事实」,微调解决「模型不会这种表达方式/任务格式」。知识更新用 RAG,风格定制用微调,绝大多数业务需求是前者。先把 RAG 和提示词调到极限,再考虑微调——微调的数据准备和迭代成本高一个量级。