为什么需要 RAG
大模型的知识来自训练数据,有两个硬伤:时间滞后(不知道训练截止之后发生的事)与领域缺失(不了解你的内部文档)。重新训练成本高、见效慢;RAG(检索增强生成)的做法更直接:回答问题前,先从你的资料里检索出相关片段,放进上下文,让模型基于这些片段作答。
最小流程
- 切分:按语义把文档切成 200–800 字的片段,避免整篇塞入;
- 向量化:用嵌入模型把片段转成向量,存入向量库;
- 检索:把用户问题也向量化,取相似度最高的 3–8 个片段;
- 重排(可选):用更精细的模型对候选重新排序,提升命中率;
- 组装提示:片段 + 问题 + 约束(只依据片段作答,缺失就说明);
- 引用回溯:输出时标注片段来源,便于人工核验。
上下文窗口不是越大越好
| 做法 | 优点 | 代价 |
|---|---|---|
| 长上下文全量塞入 | 实现简单 | 费用高、延迟长,关键信息易被淹没 |
| 检索 top-k 片段 | 成本低、聚焦 | 依赖检索质量,漏召回就没救 |
| 检索 + 重排 | 命中率更高 | 多一次调用,工程复杂度上升 |
实践中常提到「中间失效」:很长的上下文里,模型对开头与结尾最敏感,中间内容容易被忽略。因此把关键片段放在提示的前部或末尾,往往比单纯加长上下文更有效。
五个常见坑
- 切片破坏语义:按固定字数硬切会截断表格与代码块,应按段落/标题切分并保留少量重叠;
- 只做向量检索:对型号、编号、人名等精确匹配很差,应与关键词检索(如 BM25)混合;
- 不更新索引:文档改了但向量库没重建,答案会引用过期内容;
- 没有引用标注:无法核验来源,也难以定位是检索错还是生成错;
- 忽略权限过滤:检索阶段未做权限控制,会把用户无权查看的内容带进答案。
如何验证效果
- 准备 30–50 个真实问题与标准答案,其中要包含「文档里没有」的情况;
- 分别评估检索命中率与最终答案正确率,以定位问题出在检索还是生成;
- 重点看「该说不知道时是否说了」——自信的错误答案比拒答更危险。
常见问题
RAG 能消除幻觉吗?能显著降低凭空编造,但不能根除:片段可能过时、不相关,模型也可能误读。必须上向量数据库吗?不必。片段量小(几千条)时用普通数据库或内存检索即可,规模上来后再引入专用向量库。和微调怎么选?要注入事实知识用 RAG,要改变输出风格与格式用微调,两者可以叠加。
动手试试:JSON 格式化与校验(校验检索结果的结构化输出)
分块与检索质量
- 按语义分块:优先按标题与段落切分,避免把一句话从中间截断;块大小通常在 200–500 字之间做实验;
- 加重叠:相邻块留 10%–20% 重叠,能显著减少“答案正好跨在边界上”的检索失败;
- 元数据过滤:给每块带上来源、时间与权限标签,先过滤再检索,避免召回无权访问的内容;
- 评估要可量化:准备一组“问题 → 期望命中文档”的样本,改动分块策略后跑一遍,别凭感觉判断好坏。
上下文里的优先级
窗口有限时要有明确的取舍顺序:系统指令 → 当前任务与约束 → 检索到的证据 → 历史对话。历史对话最容易被截断,因此关键结论应写进任务描述或备注,而不是依赖“之前说过”。
过滤与检索的顺序
先用元数据过滤缩小范围,再做向量检索,通常比“先全库召回再过滤”效果更好:既能提升相关性,也避免召回大量无权访问的内容后才发现需要丢弃。检索数量(top-k)不宜过大,过多无关片段会稀释关键证据,反而降低回答质量。