跳到主要内容

一个坏例子,改一次提示词 — 四版演进,和两种它治不了的错

这一章讲三件事: 一条真实的链上,提示词是怎么被一版一版改出来的; 改完之后还剩哪两种错;以及这两种错各自怎么绕过去。

它在全书链条里的位置: 迭代就是「改一版、跑一遍、再改一版」这样一轮轮往前推; 这一章是第 01 章那张八步图里第 ⑥ 步「验证迭代」的前半。 第 03 章讲的是原则,这一章是原则第一次落在真实产出上。

本章主走查:第 07 章那段提示词模板,改四次。 v1 → v2 → v3 → v4,每一版都拿一个具体问题跑一遍,给出具体的回答。 注意:v1→v2 用的是「什么是南瓜书」,v2→v3 换成了「构造提示词的原则有哪些」—— 换题是因为第一个问题上 v2 已经改好了,新毛病要新题才照得出来。这是书自己的做法。 另外:这一章跑的库和第 07 章那次不是同一个——同一个问题在那里答不上来,在这里答对了。 书没有交代这一章的库是怎么建的,详见第 2 节。 (还有一个词后面会反复出现:解析就是把一段文字按格式拆开、认出哪一部分是什么。)

1. 先拿一到三个例子把提示词调通

这一节先定这一章的工作方式,它和你熟悉的软件测试很不一样。

书对这件事的描述很实在:因为你可以在几分钟内定义一段提示词、几小时内拿到反馈, 那么停下来收集一千个测试样本就会显得极为繁琐;所以流程通常是—— 先在一到三个样本上调提示词,让它在这几个上先起效1

注意这里的顺序:先调通一两个,再去收难例子。 书接着说: 之后测试时会遇到一些棘手的例子,把这些额外的例子添加到你正在测试的集合中1

书还给了一句很少见的许可: 这个过程有趣的地方在于, 如果你觉得系统已经足够好了,可以随时停止;实际上很多已经部署的应用就在第一步或第二步停下了, 而且运行得非常好1

本章只讲「调通那一两个」。收例子收多了怎么办,是第 11 章的事。

2. v1 → v2:回答对,但太简略

这一节是主走查的第 1、2 步。

v1 就是第 07 章那段模板,关键那三句是:最多使用三句话、尽量简明扼要、 最后总是说「谢谢你的提问!」2。拿「什么是南瓜书」跑一次3:

南瓜书是对《机器学习》(西瓜书)中比较难理解的公式进行解析和补充推导细节的书籍。 南瓜书的最佳使用方法是以西瓜书为主线,遇到推导困难或看不懂的公式时再来查阅南瓜书。谢谢你的提问!

注意这次它答对了——而第 07 章那次同样的问题答的是「抱歉,我不知道南瓜书是什么」。 同一个模型、同一段提示词、同一个问题,结果相反,差别只能在库里。

第 06 章第 2 节已经核过:第 07 章那个库里的 20 块全是另一份提示工程教程,南瓜书压根没进去; 而这一章的库显然装着南瓜书——回答里那句「以西瓜书为主线」就是南瓜书使用说明里的原话但书没有交代这一章的库是什么时候、用多少块建的3。 书把这次回答记成了一个坏例子,理由写得很具体4:

问题:什么是南瓜书
存在不足:回答太简略,需要回答更具体;
「谢谢你的提问」感觉比较死板,可以去掉

图说:注意这两条不足,恰恰都是 v1 自己写进去的规矩造成的——
「最多三句话」造成了简略,「总是说谢谢你的提问」造成了死板。
坏例子的第一个来源,常常是你上一版的过度约束。

v2 的改法是把那两句换掉5:

v1 里的v2 换成
最多使用三句话。尽量使答案简明扼要。你应该使答案尽可能详细具体,但不要偏题。如果答案比较长,请酌情进行分段,以提高答案的阅读体验。
总是在回答的最后说「谢谢你的提问!」(删掉)

同一个问题,v2 的回答变成了一段一百多字的介绍—— 从「是什么」讲到「怎么用」再讲到「编写团队想帮你成为什么样的人」, 末尾还给出了在线阅读地址和最新版下载地址6书的评价是:解决了之前的问题。

3. v2 → v3:详细了,但没有重点

这一节是主走查的第 3 步。

书在这里做了一件很关键的事:它没有停在「问题解决了」,而是主动去想这次改动的副作用。 原话是:要求模型给出具体、详细的回答,是否会导致针对一些有要点的回答没有重点、模糊不清?7

于是换一个更需要条理的问题来试:「使用大模型时,构造 Prompt 的原则有哪些」7。 v2 的回答是四大段连续文字,以「首先……其次……」开头。书的判词是8:

问题:使用大模型时,构造 Prompt 的原则有哪些
存在不足:没有重点,模糊不清

图说:答案本身没有错,内容也确实来自知识库。
错在形式——四段散文里藏着两条原则,读者要自己去数。

v3 只加了一句9:

如果答案有几点,你应该分点标号回答,让答案清晰具体。

同一个问题,v3 的回答变成了五条编号10:

1. 编写清晰、具体的指令是构造 Prompt 的第一原则……
2. 给予模型充足思考时间是构造 Prompt 的第二原则……
3. 在设计 Prompt 时,要指定完成任务所需的步骤……
4. 迭代优化是构造 Prompt 的常用策略……
5. 添加表格描述是优化 Prompt 的一种方法……
总之,构造 Prompt 的原则包括……

图说:前两条正是第 03 章那两条原则。第 3 条是原则二的技巧之一。
第 4、5 条来自知识库里另外的段落——它们是「知识库里有,但第 03 章没讲」的部分。

4. v3 → v4:让它把来源原文附上

这一节是主走查的第 4 步,也是这一章最实用的一版。

这次的动机不是回答不好,是信不过。书的原话是: 由于大模型存在幻觉问题,有时我们会怀疑模型回答并非源于已有知识库内容, 这对一些需要保证真实性的场景来说尤为重要11

v4 又只加了一句12:

请你附上回答的来源原文,以保证回答的正确性。

先交代一个马上要出现的词:智能体就是一个能自己决定下一步做什么的程序, 本章第 7 节还会正式用到它。拿「强化学习的定义是什么」跑一次,v4 的回答末尾多了一截13:

强化学习是一种机器学习方法,旨在让智能体通过与环境的交互学习如何做出一系列好的决策…… 强化学习的应用非常广泛,包括游戏玩法、机器人控制、交通管理等领域。 【来源:蘑菇书一语二语二强化学习教程】。

代价书也当场说了:附上原文来源往往会导致上下文的增加以及回复速度的降低, 需要根据业务场景酌情考虑14

这个做法和第 07 章那个参数不是一回事,必须分清: 这一节是让模型自己从取回的块里抄一段来源——它会跟着模型一起出错,模型编来源它就编来源; 第 07 章那个 return_source_documents 是程序拿到的元数据——它不会错,但它给不了「原文的哪一句」。 两者可以并用:一个给准确的文件与页码,一个给具体引到了哪句话。

5. 它照样在编,只是这次编得很难看出来

这一节是本章第一处另起走查,而且它是这一章最值钱的发现。

第 01、03 两章那种幻觉是整段瞎编——南瓜种植的书、三个 404 的链接,你一查就露馅接了知识库之后的幻觉换了一种形态。 书给的坏例子是15:

问题:我们应该如何去构造一个 LLM 项目
回答:六个步骤——确定项目目标和需求、收集和准备数据、设计 Prompt 和指令微调、
进行模型训练和微调、测试和评估模型、部署和应用模型
存在不足:知识库中关于如何构造 LLM 项目的内容是「使用 LLM API 去搭建一个应用」,
模型的回答看似有道理,实则是大模型的幻觉,
将部分相关的文本拼接得到,存在问题

图说:注意第 4 步「进行模型训练和微调」——
这门课从第 01 章起就明说不训练模型。
这一步不在知识库里,是模型从别处的常识里补进来的。

这种幻觉为什么更难发现,值得单独说清楚:

比什么整段瞎编(第 01、03 章)拿碎片拼(这一章)
每一句大多经不起查单独看每一句都像是对的
破绽在哪一个具体事实(链接、书名)在句子之间的连接处——某一步不属于这份资料
怎么发现查一下就知道必须知道知识库里到底有什么

所以这一类幻觉的检出成本,取决于你对自己知识库的熟悉程度。 这也正是第 07 章那个「把用到的块还给我」的参数最值钱的地方。

6. 治法:把提示词拆成两步,第二步让它自己回头查

这一节是上一节的解法。

书的诊断是:大模型往往能很好地理解并执行指令,但模型本身还存在一些能力的限制—— 幻觉、无法理解较为复杂的指令、无法执行复杂步骤; 办法是把提示词构造成一系列步骤16

新版提示词把原来一整段拆成了两步17:

请你依次执行以下步骤:
① 使用以下上下文来回答最后的问题。……(这里是 v3 的全部内容)
② 基于提供的上下文,反思回答中有没有不正确或不是基于上下文得到的内容,
如果有,回答你不知道
确保你执行了每一个步骤,不要跳过任意一个步骤。

图说:第 ② 步是新加的。它让模型把自己刚写的答案再和取回的块对一遍。
最后那句「不要跳过任意一个步骤」是必要的——不写,它会只做第 ①步。

同一个问题再跑一次,回答变成了另外五步:确定项目目标、设计 Prompt、调用 API 接口、 分析结果、不断改进18「进行模型训练和微调」那一步不见了。

书的评价是:要求模型做出自我反思之后,模型修复了自己的幻觉,给出了正确的答案18

这正是第 03 章那条原则的又一次应用:你给了它一个回头检查的位置,它就检查了。

7. 用户提的格式要求被模板吃掉了

这一节是本章第二处另起走查,治的是另一类错。

坏例子是这样的19:

问题:LLM的分类是什么?给我返回一个 Python List
回答:根据上下文提供的信息,LLM 的分类可以分为两种类型,即基础 LLM 和指令微调 LLM。
基础 LLM 是……指令微调 LLM 则是……
根据上下文,可以返回一个 Python List,其中包含 LLM 的两种分类:["基础LLM", "指令微调LLM"]
存在不足:没有按照指令中的要求输出

图说:它其实听见了那个要求——最后一行真的给了那个列表。
但前面还有两大段解释,程序拿到这坨东西没法直接用。

书的诊断很准:用户问题中存在的格式要求往往会被忽略,因为它被包裹在模板中19说白了:你的模板对着模型说了一堆话,用户那句要求只是被填进 {question} 的一小段文字。

书给的解法是在检索链之前再加一层:先用一次模型调用,把「格式要求」和「问题本身」拆开20:

第 ① 次调模型:请判断以下问题中是否包含对输出的格式要求……
返回一个可解析的 Python 列表,第一个元素是格式要求,第二个是去掉格式要求的问题原文
输入:LLM的分类是什么?给我返回一个 Python List
输出:["给我返回一个 Python List", "LLM的分类是什么?"]

第 ② 步:拿拆出来的「LLM的分类是什么?」去走第 07 章那条检索问答链
得到一段自然语言的回答

第 ③ 次调模型:按第 ① 步拆出来的格式要求,把第 ② 步那段回答重排一遍
输出:['基础LLM', '指令微调LLM']

图说:一共调了三次模型(拆、答、重排),换来一个程序能直接用的结果。

书对这个做法给了一个名字上的定位:这样的思路其实就是目前大火的智能体机制的雏形—— 智能体就是一个专门用来理解指令、判断该调什么工具、再去调用的模型, 而每一个工具可以是另一个用了不同提示词的模型,也可以是数据库、接口这些东西21

书同时提醒:框架本身提供了成熟的智能体与格式解析工具,这里只是用最原始的接口手搓了一遍21

8. 边界:改一版要重跑一遍,而这个次数长得很快

这一节交出一件下一章交不了的事。

上面四版加两处另起,每一次改动都只验证了这一次那个坏例子但你还必须回头确认:之前对的那些,没有被这一版改坏。

书把这条纪律写得很硬:在这一过程中,你应该时刻谨记之前章节中所讲述的一系列开发原则与技巧, 并时刻保证改过之后的系统不会在原先表现良好的样例上出现失误22; 在讲评估时它又说了一遍:每改一次之后,我们会重新对验证集中所有验证案例进行验证, 从而保证系统不会在原有好例子上失去能力或表现降级23

这条纪律的代价是一个乘法:

你手上有 N 个例子(好的坏的都算)。
每改一版提示词 → 全部 N 个重跑一遍、人眼看一遍。

N = 3 时:改一版看 3 次 —— 几分钟
N = 10 时:改一版看 10 次 —— 半小时起
N = 50 时:改一版看 50 次 —— 一个下午

图说:改动次数和例子数是相乘的,而例子数只增不减
(每发现一个坏例子就加一个,而且加进去就不能删)。
这就是为什么「手工看一遍」这件事迟早会崩。
(右边那三个时间是我们按「人眼读一条回答大约几分钟」估的,
书里没有这笔账;书自己算的是另一笔,在第 11 章。)

下一章要解决的正是这个乘法。 本章只钉死两件事: 第一,「原来答对的不许被改坏」是一条纪律,不是可选项; 第二,你必须留着一份跑过的例子清单,否则你连「有没有改坏」都无从判断。

判断(我们的,不是书里的): 这一章四版演进里真正可复用的,不是那四句话, 是那个动作:每一版只加一句、只针对一个具体不足、加完立刻用同一个问题重跑。 一次改两处,你就不知道是哪一处起了作用。 如果错,会错在: 如果模型对提示词的敏感度足够低(改一句几乎不影响输出), 那么一次只改一处就是浪费时间,该一次多改几处再看整体效果。判据是: 你改完一句之后,输出有没有肉眼可见的变化——这一章四次都有。

9. 可带走的

  1. 工作方式是:先拿一到三个例子把提示词调通,再去收难例子——不是先攒一千条测试用例;
  2. 书还给了一句许可:觉得够好就可以随时停,很多线上应用就停在第一两步;
  3. 坏例子的第一个来源常常是你上一版的过度约束:「最多三句话」造成简略,「总说谢谢」造成死板;
  4. v2 加的是「尽可能详细具体 + 酌情分段」;
  5. 每改一版都要主动想副作用——书正是这么发现「详细了但没重点」的;
  6. v3 加的是「有几点就分点标号」,四段散文变成五条编号;
  7. v4 加的是「请附上回答的来源原文」,代价是上下文变长、回复变慢;
  8. 让模型自己抄来源 ≠ 程序拿元数据:前者会跟着模型一起错,后者给不了具体哪一句;两者可以并用;
  9. 接了知识库之后的幻觉换了形态:拿库里的碎片拼出一段没人说过的话——每一句都像对的,错在连接处;
  10. 治法是把提示词拆成两步,第二步让它对着取回的块自查,并且要写「不要跳过任意一个步骤」;
  11. 用户提的格式要求会被模板吃掉;治法是在链前面加一层,先把格式要求和问题拆开,答完再按那个格式重写一遍;
  12. 那一层就是智能体机制的雏形:一个专管「理解指令、决定调什么」的模型;
  13. 每改一版都要把之前对的全部重跑一遍——这个次数是「改动次数 × 例子数」,而例子数只增不减。

10. 原文地图

主题原书章原文位置
先在一到三个样本上调如何评估 LLM 应用text/06-p101-120.txt:541(搜「到三个样本的」) · text/06-p101-120.txt:547(搜「随时停")
v1 与它的回答评估并优化生成部分text/06-p101-120.txt:622(搜「template_v1」) · text/06-p101-120.txt:644(搜「南瓜书是对《机器学习》」)
v1 的两条不足评估并优化生成部分text/06-p101-120.txt:648(搜「寻找 Bad Case 的思路有很多」) · text/06-p101-120.txt:653(搜「回答太简略」)
v2 与它的回答评估并优化生成部分text/06-p101-120.txt:657(搜「template_v2」) · text/06-p101-120.txt:677(搜「南瓜书是⼀本针对周志华」)
v2 的副作用与新坏例子评估并优化生成部分text/06-p101-120.txt:686(搜「构造 Prompt 的原则有哪些」) · text/06-p101-120.txt:704(搜「导致答案不是特别重点清晰」) · text/06-p101-120.txt:709(搜「没有重点,模糊不清」)
v3 与那五条编号评估并优化生成部分text/06-p101-120.txt:717(搜「分点标号回答」) · text/07-p121-140.txt:6(搜「迭代优化是构造Prompt的常」) · text/07-p121-140.txt:9(搜「添加表格描述」)
v4:附上来源原文评估并优化生成部分text/07-p121-140.txt:20(搜「怀疑模型回答并非源于已有知识库内容」) · text/07-p121-140.txt:41(搜「请你附上回答的来源原文」) · text/07-p121-140.txt:62(搜「蘑菇书」) · text/07-p121-140.txt:64(搜「上下文的增加以及回复速度的降低」)
拼碎片式幻觉评估并优化生成部分text/07-p121-140.txt:77(搜「知识库中中关于如何构造LLM项」) · text/07-p121-140.txt:78(搜「将部分相关的文本拼接得到」)
两步反思评估并优化生成部分text/07-p121-140.txt:68(搜「模型本⾝还存在⼀些能⼒的限制」) · text/07-p121-140.txt:118(搜「反思回答中有没有不正确」) · text/07-p121-140.txt:155(搜「要求模型做出⾃我反思之后」)
格式要求被吃掉与那一层解析评估并优化生成部分text/07-p121-140.txt:173(搜「该输出要求被包裹在 Template 中被模型忽略掉」) · text/07-p121-140.txt:179(搜「增加⼀层 LLM 来实现指令的解析」) · text/07-p121-140.txt:239(搜「个 Python List」) · text/07-p121-140.txt:277(搜「基础LLM', '指令微调LLM'」)
不许把原来对的改坏评估并优化生成部分 · 大模型评估方法text/07-p121-140.txt:292(搜「不会在原先表现良好的样例上出现失误」) · text/07-p121-140.txt:301(搜「在原有 Good Case 上失去能」)

Footnotes

  1. 出处:「如何评估 LLM 应用」第 541 至 548 段(text/06-p101-120.txt:541,搜「到三个样本的」;那句许可见 text/06-p101-120.txt:547,搜「随时停」)。原文这一段还有一句本章没用的话:大模型开发相较传统 AI 开发更注重验证迭代 2 3

  2. 出处:「评估并优化生成部分」第 622 至 630 段(text/06-p101-120.txt:622,搜「template_v1」)。这一版和第 07 章那段模板一字不差,书在这里给它编了号叫 template_v1

  3. 出处:「评估并优化生成部分」第 640 至 645 段(text/06-p101-120.txt:644,搜「南瓜书是对《机器学习》」)。两处加载的库路径确实不同:这一章写的是 ../../data_base/vector_db/chroma(text/06-p101-120.txt:601,搜「持久化路径」),第 07 章那次写的是 ../C3 搭建知识库/data_base/vector_db/chroma(text/06-p101-120.txt:35,搜「C3 搭建知识库/data_base」)。但书从头到尾没有说这一章的库是什么时候、用多少块建的,也没有提这两次结果为什么相反。「差别在库里」是我们能给出的唯一解释,不是书的说法。 2

  4. 出处:「评估并优化生成部分」第 648 至 653 段(text/06-p101-120.txt:648,搜「寻找 Bad Case 的思路有很多」;两条不足见 text/06-p101-120.txt:653,搜「回答太简略」)。图说里那句「坏例子的第一个来源常常是你上一版的过度约束」是我们的观察,书没有点破这一层。

  5. 出处:「评估并优化生成部分」第 655 至 663 段(text/06-p101-120.txt:655,搜「加入要求其回答具体」)。那张两行对照表是我们把 v1 与 v2 逐句比出来的,书只是把两版模板各印了一遍。

  6. 出处:「评估并优化生成部分」第 673 至 683 段(text/06-p101-120.txt:677,搜「南瓜书是⼀本针对周志华」;书的评价见 text/06-p101-120.txt:683,搜「改进后的 v2 版本」)。原文的回答比这里概括的长,本章只描述了它的结构。

  7. 出处:「评估并优化生成部分」第 683 至 686 段(text/06-p101-120.txt:686,搜「构造 Prompt 的原则有哪些」)。原文那句自问是:「但是我们可以进一步思考,要求模型给出具体、详细的回答,是否会导致针对一些有要点的回答没有重点、模糊不清?」 2

  8. 出处:「评估并优化生成部分」第 703 至 709 段(text/06-p101-120.txt:704,搜「导致答案不是特别重点清晰」;坏例子记录见 text/06-p101-120.txt:709,搜「没有重点,模糊不清」)。原文对那次回答的评价是:确实详细具体,也充分参考了课程内容,但用「首先、其次」开头、分成四段,不容易阅读。

  9. 出处:「评估并优化生成部分」第 713 至 720 段(text/06-p101-120.txt:717,搜「分点标号回答」)。

  10. 出处:「评估并优化生成部分」第 734 段起,跨到下一页(text/07-p121-140.txt:6,搜「迭代优化是构造Prompt的常」;第 5 条见 text/07-p121-140.txt:9,搜「添加表格描述」)。图说里对这五条来源的分析是我们做的,书没有分析过它们出自哪里。

  11. 出处:「评估并优化生成部分」第 19 至 21 段(text/07-p121-140.txt:20,搜「怀疑模型回答并非源于已有知识库内容」)。

  12. 出处:「评估并优化生成部分」第 36 至 44 段(text/07-p121-140.txt:41,搜「请你附上回答的来源原文」)。注意书把这一版也叫 template_v4,而后面讲思维链那一节又有另一个 template_v4——两个同名的不同版本,是书里的编号疏忽。

  13. 出处:「评估并优化生成部分」第 53 至 62 段(text/07-p121-140.txt:57,搜「强化学习是⼀种机器学习⽅法」;来源那一行见 text/07-p121-140.txt:62,搜「蘑菇书」)。同一个问题在 v3 下也答过一次(text/07-p121-140.txt:27,搜「强化学习是⼀种机器学习⽅法」),内容几乎一样,差别只有末尾那个来源。

  14. 出处:「评估并优化生成部分」第 64 至 65 段(text/07-p121-140.txt:64,搜「上下文的增加以及回复速度的降低」)。

  15. 出处:「评估并优化生成部分」第 73 至 103 段(坏例子记录见 text/07-p121-140.txt:77,搜「知识库中中关于如何构造LLM项」;判词见 text/07-p121-140.txt:78,搜「将部分相关的文本拼接得到」)。原文那句里「知识库中中」多了一个字,是书里的笔误。 那张三行对照表是我们排的,书没有对两类幻觉做过区分。

  16. 出处:「评估并优化生成部分」第 67 至 71 段(text/07-p121-140.txt:68,搜「模型本⾝还存在⼀些能⼒的限制」)。这一节的标题是「构造思维链」——本组拆解第 03 章提到过,书是在这里用这个名字的。

  17. 出处:「评估并优化生成部分」第 107 至 120 段(text/07-p121-140.txt:118,搜「反思回答中有没有不正确」)。图说里「不写这句它会只做第 ① 步」是我们的推断,书只是照抄了那句要求,没有解释它为什么必要。

  18. 出处:「评估并优化生成部分」第 133 至 156 段(书的评价见 text/07-p121-140.txt:155,搜「要求模型做出⾃我反思之后」)。新五步的名字是我们从原文那段回答里摘的,原文每一步下面还各有两三句展开。 2

  19. 出处:「评估并优化生成部分」第 158 至 177 段(回答见 text/07-p121-140.txt:171,搜「基础LLM', '指令微调LLM'」;诊断见 text/07-p121-140.txt:173,搜「该输出要求被包裹在 Template 中被模型忽略掉」;坏例子记录见 text/07-p121-140.txt:177,搜「没有按照指令中的要求输出」)。 2

  20. 出处:「评估并优化生成部分」第 222 至 277 段(第一次调用的输出见 text/07-p121-140.txt:239,搜「个 Python List」;最终结果见 text/07-p121-140.txt:277,搜「基础LLM', '指令微调LLM'」)。「一共调了三次模型」这个计数是我们数的,书没有算过这笔账。

  21. 出处:「评估并优化生成部分」第 179 至 183 段与第 279 至 281 段(text/07-p121-140.txt:179,搜「增加⼀层 LLM 来实现指令的解析」;那句提醒见 text/07-p121-140.txt:280,搜「Parser 机制」)。原文说框架里其实有现成的智能体机制,但本教程就不再赘述了——这是书自己划的边界。 2

  22. 出处:「评估并优化生成部分」第 290 至 292 段(text/07-p121-140.txt:292,搜「不会在原先表现良好的样例上出现失误」)。

  23. 出处:「大模型评估方法」第 299 至 302 段(text/07-p121-140.txt:301,搜「在原有 Good Case 上失去能」)。那张「N = 3 / 10 / 50」的表是我们算的,书里没有这三行;书给的是另一笔账(维度数 × 版本数 × 案例数),那笔账在第 11 章。