本页目录
Lesson 05 — Prompt 工程:把检索结果喂给大模型
本课目标:搞懂怎么组织 prompt,让模型基于检索到的材料答得又准又稳。检索质量再好,prompt 写得烂,模型照样会瞎编或答非所问。
前面 4 课解决了"怎么找到相关材料",这一课解决"怎么用好这些材料"。
1. RAG prompt 的标准结构
一个标准的 RAG prompt 由三部分组成:
[指令] 你是一个严谨的问答助手。请只根据下面提供的材料回答用户问题。
如果材料里没有相关信息,请直接回答"我不知道",不要编造。
[上下文] 【材料1】年假:入职满 1 年有 5 天带薪年假……
【材料2】病假需提供三甲医院病假条……
[问题] 我工作 4 年,能休几天年假?
三部分缺一不可: - 指令:告诉模型角色、任务、约束(最重要!) - 上下文:检索到的材料(RAG 的核心价值就在这) - 问题:用户到底想问什么
2. 防幻觉的核心:明确约束 + 拒答机制
这是 RAG prompt 最关键的设计。不加约束时,大模型会:
- 🚫 材料里没有的,它根据自己的预训练知识"补"上(幻觉)
- 🚫 材料和问题不匹配时,它强行编一个答案
- 🚫 多条材料冲突时,它挑一个自信地说,不告诉你有冲突
加了下面这条约束,情况大不一样:
"请只根据下面提供的材料回答用户问题。如果材料里没有相关信息,请直接回答'我不知道',不要编造。"
这条指令做了两件事: 1. 限定信息来源:只能用材料里的内容,不准用预训练知识 2. 允许拒答:没有就说没有,比硬编一个错答案好得多
🎯 关键认知:在 RAG 场景里,"我不知道"往往比"一个错误答案"有价值得多。用户至少知道这个问题系统答不了,可以换种问法或找人工。
还有哪些有效的约束?
| 约束 | 作用 |
|---|---|
| "答案末尾标注引用的材料编号" | 引用溯源,方便核对 |
| "如果多条材料冲突,请指出冲突" | 避免模型隐瞒矛盾 |
| "分点陈述,每点对应一条材料" | 结构化输出 |
| "不要输出与材料无关的寒暄" | 减少噪声 |
3. 引用溯源
让模型标注"这段答案来自哪条材料",这是生产级 RAG 的标配:
问题:年假有几天?
答案:根据【材料1】,入职满 1 年有 5 天带薪年假,满 3 年 10 天……
实现方式就是在指令里要求:"请在答案中用【材料N】标注信息来源。"
好处: - 用户能核对答案真伪(点开材料看原文) - 出错时容易定位是"检索错了"还是"生成错了" - 增加可信度
4. 上下文窗口管理:材料太多怎么办?
检索回来 10 段材料,但模型窗口放不下,怎么办?
| 策略 | 做法 | 适用 |
|---|---|---|
| 截断 | 只取 Top-K 中最相关的前几段 | 最简单,常用 |
| 压缩 | 让小模型先把每段压缩成摘要,再拼接 | 省空间,但有信息损失 |
| Map-Reduce | 每段单独问模型,再汇总答案 | 精度高但成本高 |
本课用截断(Top-K 已经控制了数量),压缩和 Map-Reduce 留到进阶。
5. 本课代码会做什么
code.py 会做三个对比实验:
① 防幻觉对比(最核心)
用同一个文档里没有的问题(比如"公司 wifi 密码"),分别用: - 无约束 prompt:直接发问题+材料,不加任何约束 - 防幻觉 prompt:加上"只依据材料,没有就说不知道"
你会亲眼看到无约束时模型瞎编,有约束时模型老实地答"我不知道"。
② 引用溯源
要求模型在答案里标注【材料N】,让答案可追溯。
③ 流式输出
用流式 API 边生成边打印,体验真实产品的"打字机"效果。
6. 跑起来
python lessons/05_prompt/code.py
终端会打印三个实验的对比。重点看实验①——同一个问题,两种 prompt,模型回答天差地别。
下一课 Lesson 06 — 进阶检索 会讲:单纯向量检索不够用,怎么用混合检索 + Rerank 提升召回质量。