Agent Engineering 课程阅读
首页/课程一 · RAG 手写/Prompt 工程:把检索结果喂给大模型

在 GitHub 查看原文

本页目录

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 提升召回质量。