第 6 章:RAG 进阶优化
章节定位
上一章你已经搭出基础 RAG:文档进来,检索片段,模型生成答案。
但基础 RAG 往往只能证明“能跑”,不能证明“好用”。这章要解决的就是四个问题:
- 检索出来的内容准不准
- 切分后的片段是不是太碎
- 上下文是不是塞了太多无关信息
- 模型回答是不是过度发挥了
在 AI 学习助手 中,这一章会把“能回答课程资料”升级成“回答更稳、更准、更可控”。
配套示例
- 目录:
examples/chapter-06 - 入口:
examples/chapter-06/main.py - 依赖:
examples/chapter-06/requirements.txt - 运行:
cd examples/chapter-06 && python3 main.py
示例层级与边界
- 层级:
教学版 - 本章重点:训练你识别 RAG 问题出在切分、检索、上下文还是生成阶段。
- 不要误判:示例中的优化策略是教学化对比,不等于真实生产环境里的召回评测、索引调参或在线实验体系。
本章目标
学完这一章,你应该能:
- 判断基础 RAG 的主要失败点
- 根据资料类型调整切分策略
- 优化 Retriever 的检索质量
- 对上下文拼装方式做基本控制
- 让模型回答更贴近资料、更少编造
前置知识
你需要先理解:
- RAG 的基本流程
- 文档切分、Embedding、Vector Store、Retriever 的作用
- 模型生成阶段为什么需要提示词约束
为什么基础 RAG 还不够
很多人第一次做 RAG 时,系统看起来能跑,但一用就暴露问题:
- 问题稍微复杂一点就检索偏了
- 文档一多,返回的片段很杂
- 模型会根据检索内容“补脑”
- 回答里混进很多没必要的上下文
基础 RAG 的问题不是单点,而是链路上的每一步都可能影响结果。
所以优化 RAG 的思路不是“换一个更大模型就行了”,而是要逐层排查:
- 文档有没有切对
- 检索有没有找对
- 上下文有没有组织好
- 生成有没有被约束住
优化的四个方向
1. 切分优化
切分决定了后续检索的“候选池”质量。
切得太碎:
- 段落信息不完整
- 检索命中后上下文不够
切得太粗:
- 片段里混了太多主题
- 检索结果不够精准
因此切分要结合内容类型:
- 课程说明文档适合中等粒度切分
- FAQ 适合问答对粒度切分
- 长篇技术文档适合按标题层级和语义段落切分
2. 检索优化
Retriever 不只是“取相似度最高的几段”。
你可以在检索阶段做一些控制:
- 调整
top_k - 设置相似度阈值
- 查询改写
- 多查询融合
这一步的目标是减少“看起来相近,实际上无关”的片段。
3. 上下文优化
检索到内容后,并不是越多越好。
如果上下文太长,模型会:
- 分心
- 被噪音干扰
- 更容易忽略真正相关的部分
所以要控制上下文组织方式:
- 去掉重复片段
- 排序相关性
- 只保留必要段落
- 必要时做压缩总结
4. 生成优化
最后一步仍然是生成,但这一步经常被低估。
你要明确告诉模型:
- 只能基于资料回答
- 资料不足时要说明不足
- 不要自行扩展课程外结论
- 尽量引用相关片段中的表述
这会显著降低“模型一本正经胡说八道”的概率。
优化思路怎么落到工程里
可以把优化流程理解成一个调试漏斗:
- 先看资料切得是否合理
- 再看检索命中的片段是否相关
- 再看上下文是否过长或过乱
- 最后看模型输出是否忠于资料
这意味着你不应该只盯着最终答案,而要记录每一层的中间结果。
在 AI 学习助手 中,最好给每次问答都保留:
- 原始问题
- 检索到的片段
- 拼装后的上下文
- 最终回答
这样才知道问题到底出在前面还是后面。
最小示例:从基础 RAG 升级到可控 RAG
下面这个示例展示的是优化思路,不是特定版本 API。
python
# 伪代码:重点看策略,不看具体库函数名
question = "RAG 和普通问答相比,为什么更适合课程学习站?"
# 1. 先把问题改写得更适合检索
search_query = rewrite_query(question)
# 2. 检索多个候选片段
candidates = retriever.retrieve(search_query, top_k=8)
# 3. 按相关性过滤、去重、排序
filtered_chunks = filter_and_rank(candidates)
# 4. 必要时压缩上下文
context = compress_context(filtered_chunks, max_chars=3000)
# 5. 用更严格的提示词生成答案
prompt = """
你是课程学习助手。只能基于资料回答。
如果资料不能支持结论,请明确说明“不足以判断”。
资料:
{context}
问题:
{question}
"""
answer = llm.generate(prompt.format(context=context, question=question))这个示例说明一个关键点:优化不只是“调一个参数”,而是对完整链路进行控制。
真实框架版对照
examples/chapter-06/main.py 增加了一组 framework-baseline 和 framework-optimized 对照输出。
这两组对照重点不是追求“更强”,而是让你看到真实工程里常见的接口拆分:
- query rewrite 先把问题改写成更适合检索的查询
- retriever 负责返回候选片段
- 重排和压缩负责把上下文收敛成可交给模型的证据
- 最后仍然是 prompt + model 的生成阶段
从这里开始,你应该逐渐把“优化 RAG”理解成一条可调试的数据流,而不是只调某个模型参数。
切分优化怎么做
切分优化的原则很简单:让片段保持语义完整。
你可以观察三类指标:
- 片段是否能独立表达一个意思
- 片段之间是否有适度重叠
- 片段是否保留标题和上下文信息
对于课程站这类资料,建议保留章节标题、模块标题等结构信息。因为用户问的往往不是某一句话,而是“这一节讲了什么”。
检索优化怎么做
检索优化的思路不是追求“最多”,而是追求“更准”。
常用方法:
- 增加候选数,再二次过滤
- 对问题做简短改写
- 针对不同问题类型使用不同检索策略
比如:
- “第几章讲什么”这类问题,标题信息很重要
- “为什么这样设计”这类问题,解释段落更重要
- “怎么写示例”这类问题,代码块附近的说明更重要
也就是说,检索策略应该和问题类型匹配。
上下文优化怎么做
上下文优化最重要的原则是:只放对回答有帮助的内容。
常见做法:
- 去重
- 排序
- 截断
- 压缩
尤其是在课程站这种文档很多但单次问题很明确的场景里,不要把全部候选都塞给模型。你要让模型看的是“证据”,不是“噪音合集”。
生成优化怎么做
生成优化主要靠提示词控制。
你需要明确写出三类约束:
- 回答边界:只基于资料
- 不足处理:资料不足就说不足
- 输出风格:尽量简洁、结构化、可追溯
如果你希望答案更稳,还可以让模型:
- 先给结论
- 再给依据
- 再指出资料中的相关位置
这样用户更容易判断答案是否可信。
本章实践
这一章最值得做的实践,是给 AI 学习助手 做一次系统优化。
建议你按下面的顺序推进:
- 先保存基础 RAG 的问答日志
- 找 10 个典型问题做测试
- 观察哪些问题经常答偏
- 分别检查切分、检索、上下文、提示词四个环节
- 每次只改一个变量,避免你不知道到底是哪一步起作用
实践目标不是“追求绝对正确”,而是建立可重复的优化流程。
常见坑
坑 1:只调模型,不调检索
很多 RAG 问题本质是检索问题,不是模型问题。
如果片段都找错了,模型再强也只能在错误上下文里回答。
坑 2:上下文过长
把太多片段塞给模型,只会增加噪音。
RAG 的关键不是“喂更多”,而是“喂更相关”。
坑 3:不记录中间过程
如果你不记录检索结果和上下文拼装过程,就很难定位问题。
RAG 调试应该看链路,不该只看最终答案。
坑 4:答案看起来很顺,但其实没依据
这通常说明生成约束太弱。
你要让模型明确知道:资料不足时,不要硬编。
练习题
- 如果一个问题经常检索到无关内容,你会优先检查哪三个环节?
- 为什么课程站不适合把所有候选片段都直接送给模型?
- 试着为
AI 学习助手写一段更严格的回答提示词,要求模型只根据资料作答。 - 说明“切分优化”和“检索优化”的区别。
本章总结
基础 RAG 解决的是“能不能查资料再回答”,优化 RAG 解决的是“能不能答得准、稳、可解释”。
这章的核心不是某个单独技巧,而是一个系统思维:
- 切分影响候选质量
- 检索影响相关性
- 上下文影响模型注意力
- 提示词影响回答边界
把这四层理顺,你的 RAG 系统才算进入可用状态。
学完本章,你现在应该会
- 把一个 RAG 问题拆到切分、检索、上下文、生成四层里定位
- 说明为什么“答偏”不一定是模型能力问题
- 设计一次小规模、可重复的 RAG 优化实验
- 为
AI 学习助手写出更严格的资料边界和回答约束
最小验收 checklist
- [ ] 我至少记录过一次基础 RAG 的问题案例和中间过程
- [ ] 我能说出本次优化到底改的是哪一层,而不是“整体感觉更好”
- [ ] 我知道什么时候该减少上下文,而不是继续增加片段数量
- [ ] 我能解释为什么优化要一次只改一个变量
建议你动手改一版
- 选 5 到 10 个问题做一个小评测表,对比优化前后的命中率或完整性
- 给回答模板补上“先结论、再依据、最后说明资料边界”的结构
- 试着只改
top-k或切分粒度中的一个参数,记录它对结果的影响
卡住时先回看这里
- 如果你不知道该从哪里排查,回看 chapter-06-rag-optimization.md 里的
## 优化的四个方向 - 如果你想直接调模型却说不清问题来源,回看 chapter-06-rag-optimization.md 里的
## 本章实践 - 如果你对“只根据资料作答”的约束写不出来,回看 chapter-06-rag-optimization.md 里的
## 生成优化怎么做
下一章预告
下一章会从“知识问答”转向“动作执行”。
你会学习:
- 什么是 Tool Calling
- 为什么 Agent 需要工具
- 如何让
AI 学习助手不只会回答,还能调用外部能力