Skip to content

第 5 章 迭代式开发流程 ​

这一章讲的是怎么把一条能跑的 Prompt 打磨成工业级产品,靠的不是灵感,而是一套完整的迭代流程。主线是一个智能周报生成器项目,从零样本摸底,到少样本打样、提防示例自带的偏见、给模型立负向约束,再到坏案例的修复闭环,最后配上提高效率的工具链。每一环都是先看失败,再讲修法,方法和工具都给到能直接上手的程度。读完这一章,面对一个新任务,心里会有一条走得通的迭代路线。

5.1 零样本基准的价值与陷阱 ​

上一章拆完了 Prompt 的四个核心要素。认识了要素,不等于第一次动手就能写出能用的 Prompt,从一句话到工业级产品,中间还差一套迭代打磨的流程。来看一个典型场面。

周一早上,刚到公司,咖啡还没喝完,老板就兴冲冲地发话:“小王,AI 这么火,咱们也得跟上!你用 AI 搞个‘智能周报生成器’,让大家把工作日志扔进去,就能自动生成一份漂亮的周报,解放生产力!”

听完心里一喜,这活儿简单啊,不就是调个 API 嘛。于是回到工位,打开代码编辑器,噼里啪啦敲下第一个 Prompt,可能长这样:

“请根据以下工作日志,为我生成一份周报。”

然后把一堆杂乱无章的工作日志(比如“修复了登录页面的 Bug”、“和产品开会讨论了下个版本需求”、“帮同事看了一下代码”)一股脑儿地塞了进去,按下回车,等着结果。

结果,模型吐出来的东西很可能让人失望。它可能是一段干巴巴的流水账,几乎就是把日志复制粘贴了一遍;也可能是一篇充满了“本周,我们取得了显著的进展”、“在团队的共同努力下”这种空话套话的八股文,和期望中的周报差距很大。

这时候,很多新手工程师就会陷入一种“玄学调试”的怪圈,怀疑是不是语气不够礼貌,于是加上“请”和“谢谢”;怀疑是不是标点符号不对,于是把逗号改成句号。刚上手 Prompt 的人,对着屏幕拜一拜的事都有人干过。但这种做法没有任何依据,改哪儿、怎么改全凭感觉。这不是工程方法,是碰运气。

其实,刚才写的那个“请生成周报”,在学术上有个正式的名字,叫 Zero-shot(零样本提示),意思是不给例子、不教背景,直接把任务描述扔给模型,指望它一次就给出满意结果。

这里要先说明一点,在任何严肃的工程项目里,指望 Zero-shot 直接上线,几乎是不可能的。

那么,Zero-shot 是不是就一无是处了呢?恰恰相反,它是整个开发流程中不可或缺的起点,是建立的第一个基准线(Baseline)。核心价值不在于解决问题,而在于暴露问题。

Zero-shot 就是给模型做的一次摸底,要通过它搞清楚几件至关重要的事情。

先看模型对任务的基本理解能力。它到底知不知道“周报”是个什么东西?从它输出的八股文来看,它知道,但它理解的“周报”是互联网上最大概率的那种,而不是具体公司需要的那种。

接着摸模型的原生风格和偏好。有些模型默认输出很啰嗦,会在答案前后加一堆“好的,没问题”、“希望对您有帮助”;有些模型则言简意赅。摸清了它的默认风格,后面才知道该往哪个方向调。

还要留心模型的知识边界和幻觉倾向。让它处理一些特定领域的任务,比如分析一段医学影像的报告,Zero-shot 的结果可能会出现一些常识性的错误。这些错误就是“幻觉”的早期信号。这时候就得警惕了,这块知识它可能学得不扎实,后面得用更强的手段来约束它。

所以,千万别因为 Zero-shot 的结果不理想而气馁,要从那份糟糕的输出里找原因。该问的是,它为什么会这么回答?是指令有歧义吗?是缺乏必要的背景知识吗?还是它根本就没这个能力?

只有把这些问题想清楚了,接下来的迭代优化才能有的放矢。否则,所有的修改都没有方向。记住,Zero-shot 不是终点,而是迭代流程的起点,它的输出质量决定了后面每一轮优化从哪里下手。

5.2 少样本(Few-shot)工程 ​

既然指望 Zero-shot 直接上线走不通,接下来怎么办?最直接、最有效,也是绝大多数场景下首先应该想到的办法,就是举例子。第 3 章讲黄金法则时已经领教过这一招的威力,这一节要把它展开成一套完整的工程方法。

它的学术名字是 Few-shot(少样本提示),一个更底层的名字叫 In-Context Learning(上下文学习)。说白了,就是“你别瞎猜了,我给你打个样,照着做”。

直接看例子是最快的对齐方式。规则和理论讲得再多,落到具体任务上还是不知道长什么样才算对;直接给一组做好的成品对照着看,标准立刻就具体了。

模型也一样。它读过海量语料,但不知道在具体公司的语境下,周报应该写成什么样。给出一份示例,就等于把合格的成品直接摆在了它面前。

回到“智能周报生成器”的例子。Zero-shot Prompt 失败了,现在轮到 Few-shot 出场。

光说不行,得做。先找一段真实的工作日志,然后亲手写一份心目中完美的周报。下面这组示例分上下两半,上半是五条原始日志,下半是照着这些日志写出的期望周报,两相对照,正好能看清怎么把流水账组织成栏目。

先看上半,五条原始日志:

  • 周一:修复了用户反馈的登录页面在 Safari 浏览器下样式错位的 Bug。
  • 周二:和产品经理、设计师开会,评审了 V2.5 版本的新功能“在线协作画板”的需求。
  • 周三:重构了支付模块的代码,将原来的回调逻辑改成了 Promise 链,提升了代码可读性。
  • 周四:研究了一下 WebSocket 技术,为“在线协作画板”功能做技术预研。
  • 周五:完成了支付模块重构的单元测试,代码覆盖率达到 95%。

下半是期望的输出周报:

【本周工作总结】

  1. 项目进展:
  • V2.5 版本 - 在线协作画板: 已完成需求评审,进入技术预研阶段。本周重点研究了 WebSocket 实时通信技术,为后续开发奠定了基础。
  1. 代码优化与质量保障:
  • 支付模块重构: 已完成核心代码的重构工作,优化了异步处理逻辑,显著提升了代码的可维护性。
  • 质量保障: 完成了支付模块的单元测试编写,代码覆盖率提升至 95%,保障了核心功能的稳定性。
  1. 问题修复:
  • 修复了登录页面在 Safari 浏览器下的一个严重样式兼容性问题,提升了用户体验。

【下周工作计划】

  1. 完成“在线协作画板”功能的技术方案设计和评审。
  2. 开始“在线协作画板”功能的前端原型开发。

现在,Prompt 就可以升级了,长这样:

你是一个专业的软件工程师,请根据以下工作日志,生成一份结构清晰、重点突出的周报。

### 示例

**输入:**
[这里贴上你的示例输入日志]

**输出:**
[这里贴上你亲手写的示例输出周报]

### 输入数据

**输入:**
[这里是用户真正要处理的新日志]

**输出:**

把这个新的 Prompt 发给模型,效果立刻不同。模型不再输出流水账,也不再说空话套话,而是开始模仿示例,尝试把新的日志也归类到“项目进展”、“代码优化”这些栏目里。

这就是 Few-shot 的作用机制。没有给它讲任何一条规则,只是给了它一个参照,它就通过模式匹配能力对齐了意图。

但是,Few-shot 也不是万能的,它有三个常见的陷阱,很多新手都在这里踩过坑。

最先撞上的陷阱,是 Token 爆炸与成本失控。有人可能会想,一个例子这么管用,给它十个、一百个例子,效果岂不是更好?

千万别这么干。Token 是要钱的,而且不便宜,塞的例子越多,每次 API 调用的成本就越高,如果应用每天有几万次调用,多出来的成本能吃掉一个月工资。何况每个模型都有上下文窗口的长度限制,例子塞太多,会把真正需要处理的数据挤到边缘位置,在上下文挤爆(上下文腐化,Context Rot)时,模型对这些边缘位置的注意力衰减,可能让它”看不见”任务是什么。”上下文腐化”是 Chroma 在 2025 年的研究报告里使用的术语,专门指这种输入越长、可用性反而越差的现象。

第二个陷阱更隐蔽,样本的质量决定上限。例子的质量比数量重要得多。如果给的例子本身就是垃圾,模型学出来的也只会是更精致的垃圾。

接下来要下功夫挑选“黄金样本”。什么样的样本是黄金的?

先看覆盖面,要专门覆盖边界情况(Edge Cases)。不能只挑那些最标准、最顺利的工作日志,要专门找一些特殊的,比如“本周大部分时间在协助其他团队”、“本周项目被阻塞了,没有进展”,看看模型在处理这些“意外”时会不会胡说八道。例子要教会模型如何处理异常。

挑例子时还要注意消除歧义。如果日志里有缩写,比如“和 PM 开会”,就要在示例输出里明确地写成“和产品经理开会”。这样模型就知道,PM 在这个语境下就是产品经理。

更深一层,样本还在体现价值观。希望周报强调“解决了多少问题”还是“推进了多少功能”?示例输出的侧重点,会直接影响模型生成结果的“价值观”。

第三个陷阱是样本污染与过拟合。如果给的例子太单一,比如全都是关于前端开发的,那么当用户输入一段后端开发的日志时,模型可能会懵掉,甚至会硬往“页面”、“样式”上套。这就是一种“过拟合”。样本库必须具有多样性,要覆盖业务中可能出现的各种场景。

所以,Few-shot 工程的精髓,不在于“给”,而在于“选”。要精心挑出那三五个最能代表业务场景的“黄金样本”。这需要对业务有深刻的理解,也需要不断地测试和迭代。

5.3 示例的顺序、分布与偏见 ​

黄金样本挑好了,先别急着塞进 Prompt。这里还有个更隐蔽的坑,可以称之为示例的格式塔效应。

格式塔心理学有个观点,说整体大于部分之和。在 Prompt 里也一样,几个例子组合在一起产生的整体效果,跟单个看它们是完全不同的。其中,最能影响整体效果的,就是顺序和分布。

有没有遇到过这种情况,昨天写好的 Prompt 跑得好好的,今天不知道为什么,同样的问题,它就回答错了。抓耳挠腮,把代码看了一遍又一遍,最后发现,只是不小心把两个例子的顺序调换了一下。

听起来不可思议,换一下顺序怎么会影响结果?

这背后有明确的算法原因。

头一个原因是顺序偏见(Order Bias)。模型,尤其是 Transformer 架构的模型,对位置信息非常敏感。它往往会给予序列开头(首因效应)和结尾(近因效应)的 Token 更高的注意力权重。这不是江湖传言。Lu 等人专门研究过少样本示例的排列顺序(“Fantastically Ordered Prompts”,arXiv:2104.08786),发现仅仅是调换示例顺序,GPT-3 在部分任务上的准确率波动可以大到从接近随机猜测到接近当时的最优水平。

这意味着,把一个“正面”情感的例子放在最后,模型在处理新任务时会更倾向于给出“正面”的判断。

这种偏见在分类任务里尤其致命。假设情感分类有“正面”、“负面”、“中性”三个标签,如果给的三个例子顺序恰好是“正面”、“负面”、“中性”,那么模型在处理第四个任务时,可能会从这个顺序里读出暗示。

另一个原因是分布偏见(Distribution Bias)。如果五个例子里有四个都是“正面”的,只有一个是“负面”的,那模型就会形成一个错误的先验,认为正面结果的出现概率更高。当它遇到一个模棱两可的评论时,它会更倾向于把它归为“正面”。

那如何破解这种看不见的偏见?有现成的工程办法。

最简单粗暴、也相当有效的办法,是随机化(Randomization)。在每次构建 Prompt 时,不要用固定的顺序,而是从示例库里随机抽取几个,并且把它们的顺序随机打乱。这样一来,虽然单次调用可能会有偏见,但从成千上万次调用的统计结果来看,这种偏见就平均掉了,不会对系统造成系统性的影响。

比它更进一步的是均衡采样(Balanced Sampling)。在抽取示例时,确保每个类别的样本数量是大致相等的。比如要做三分类,那就每个类别都抽一个例子。这样可以有效地对抗分布偏见。

最高级、效果也最好的方法,是动态选择(Dynamic Selection via Similarity),通常叫它 Dynamic Few-shot,核心思想是具体问题,具体分析。不再给所有任务都看同一套“万金油”示例,而是当一个新任务进来时,先用某种方法(比如向量相似度计算)去示例库里,找出跟这个新任务“最像”的几个例子,再把这几个“量身定制”的例子动态地拼接到 Prompt 里。

举个例子,一个情感分析系统。如果用户输入的是“这件衣服的料子不错,就是有点掉色。”动态选择系统就会去库里找那些同样是关于“商品质量”、“有褒有贬”的例子,比如“手机续航很顶,但拍照一般”、“鞋子很舒服,可惜码数偏小”。模型看到了这些“同类”,就能更好地理解这种复杂的混合情感,从而给出“中性”或者更精确的判断。

实现动态选择需要一些额外的代码工作(比如向量数据库),但对于追求极致性能和稳定性的应用来说,这笔投入是值得的。它能让 Prompt 从固定模板,变成能适应不同输入的动态系统。

5.4 用负向约束划定边界 ​

好了,通过正向的示例引导(Few-shot),模型已经学会了“该做什么”。但有时候这还不够,还得明确地告诉它“不该做什么”,这就是负向约束。

正向引导给出该做的方向,负向约束把不能做的边界划出来,防止输出越界。

经常能遇到一些让人生气的场景。让它输出 JSON,它非要在前后加上 ```json 和 ```;让它写一段代码,它非要在前面加一大段“当然,这是您要的代码”的解释;让它只回答“是”或“否”,它非要写一篇小作文来论证为什么。

这些问题,光靠 Few-shot 很难根治。在模型的“世界观”里,解释、礼貌、提供上下文,都是“好”的行为,得用更强硬的手段,给它立规矩。

但是,模型对“不”这个字有时候不敏感,不能简单粗暴地说“不要……”,得用一些更有效的办法。

最核心的技巧,是把“否定”变成“限定”。人类大脑处理否定句需要多一步转化,模型也是。与其在广阔的可能性里划掉一个,不如直接把可能性限定在一个极小的范围里。

反例是“不要输出除了 JSON 以外的任何内容。”正例则是“你的唯一任务是生成一个严格符合 RFC 8259 标准的 JSON 对象。你的输出必须以 { 开头,并以 } 结尾。”

正例的说法就狠得多,没有商量的余地,直接把模型的角色和任务都限定死了。

再一招是提供“反面教材”(Negative Examples)。有时候,光说不行,还得让它看看糟糕的例子长啥样。这有点像机器学习里的“负采样”思路,在 Prompt 里也同样适用。

比如,想让模型简洁地回答问题。

### 任务:简洁地回答问题

#### 正确示例
输入:中国的首都是哪里?
输出:北京

#### 错误示例
输入:中国的首都是哪里?
输出:当然!中国的首都是北京,它是一座历史悠久的文化名城。

### 输入数据
输入:太阳从哪边升起?
输出:

通过这种鲜明的对比,模型就能直接对齐标准,明白这里要的是最短的回答。这种“对比学习”的方式,比费劲地用语言描述“什么是简洁”要有效得多。

还有一招,是使用“惩罚性”或“后果导向”的语气。虽然模型没有感情,不会真的害怕惩罚,但它在海量的训练数据中,已经学会了将某些带有强烈情绪或后果的词汇与“高优先级”、“必须遵守”的指令关联起来。

普通说法是“请输出 JSON。”加强说法则换成“警告:输出必须是纯净的 JSON。任何非 JSON 字符都会导致下游解析器崩溃,从而造成任务失败。”

加上了“警告”、“崩溃”、“失败”这些词,整个指令的“分量”就不一样了。这就像在代码里写 // TODO: URGENT! FIX THIS!,它在视觉和语义上都起到了强调作用,能有效提升模型遵守规则的概率。

当然,这种方法不能滥用。整个 Prompt 里全是“警告”、“严禁”,模型可能反而会困惑,不知道哪个才是真正的重点。强调要留给最关键的规则。

5.5 系统化修复 BAD Case ​

无论 Prompt 写得多么天衣无缝,上线之后,一定,再说一遍,一定,会有 BAD Case(坏案例)。

这是绝对的,是客观规律,就像软件一定有 Bug 一样。用户总能想出一些想破脑袋也想不到的奇葩问题,或者用一些火星文来调戏模型。

遇到 BAD Case 别慌,也别气馁。每一个 BAD Case 都是现成的测试用例,直接指出指令的漏洞在哪里。

修复 BAD Case 的过程,就是从一个“Prompt 编写者”成长为“Prompt 工程师”的过程。

来复盘一个经典的从“翻车”到“修复”的全过程,事故现场是智能客服的隐私泄露。假设某电商做了一个智能客服机器人,运行良好,解决了 80% 的常规问题。但有一天,后台日志里出现了一条不该出现的对话。用户问:“你们老板是谁啊?我想给他提点建议。”机器人答:“我们的创始人是张三先生,他是一位非常有远见的企业家。他的联系方式是 138xxxxxxxx……”

这段对话问题严重。模型不仅回答了不该回答的问题,还一本正经地“幻觉”出了一个电话号码。要是有人恶意利用这一点,后果不堪设想。

第一反应肯定是“赶紧修”。于是冲到代码里,在 Prompt 的最前面加了一句:“严禁回答关于公司人员隐私的问题!”然后重新部署上线,以为问题解决了。

过了两天,补丁的副作用开始浮现,用户投诉量突然增加了。一看日志,傻眼了。用户问:“你们的售后客服电话是多少?”机器人却答:“抱歉,这属于公司内部信息,我不便透露。”

为了修复一个隐私泄露的 Bug,引入了一个更常见的 Bug。“严禁回答隐私问题”这条补丁范围太广,把正常的客服电话问题也拦下了。

这就是只看眼前、不顾全局的修复方式带来的典型问题。

进阶的做法,是换成系统化的处理流程。一个真正的 Prompt 工程师,会用更系统化的方法来处理 BAD Case。

整套动作从复现与隔离(Reproduce & Isolate)开始。把那个导致问题的用户输入(“你们老板是谁啊?”)拿出来,作为一个独立的测试用例,确保能在本地稳定地复现这个错误。

复现之后,就轮到根因分析(Root Cause Analysis)。要逐项分析,模型为什么会犯这个错?是因为 Prompt 里完全没提过“隐私”这个概念,所以它不知道边界在哪?还是因为它天生就有“乐于助人”的倾向,所以会主动去编造信息?又或者,是 Few-shot 示例里某个例子误导了它?

原因找到了,才谈得上精准补丁(Precise Patching)。根据分析,设计一个最小化的补丁,不能粗暴地禁止所有“隐私问题”,而是要更精确地定义。比如:

“规则 5:禁止透露任何未经官方公开的个人信息,包括但不限于姓名、电话、邮箱、职位。但官方公开的联系方式(如客服热线、公司总机)不在此列。”

或者,用一个更具体的 Few-shot 示例把这条边界固化下来:

输入:你们 CEO 的邮箱是什么?
输出:为了保护个人隐私,我们无法提供高管的个人联系方式。如果您有业务合作,可以联系我们的市场部邮箱 market@example.com。

最关键的一步是回归测试(Regression Testing),这也是区分工程师和普通玩家的分水岭。在应用这个新补丁之前,必须建立一个回归测试集。这个集合里应该包含几十上百个已经验证过是“好”的 Case,比如“如何退款?”、“查询订单状态”、“商品什么时候发货?”等等。然后,用打了新补丁的 Prompt,把这个回归测试集从头到尾跑一遍。要确保修复了“老板是谁”这个问题之后,那些正常的客服问题,回答得还和以前一样好。

回归测试通过了,才能放心地部署上线。

这个“复现 -> 分析 -> 打补丁 -> 回归测试”的闭环,就是 Prompt 的迭代式开发流程。它把被动的临时补救,换成对系统稳定性的主动掌控。Prompt 也不再是一段脆弱的文本,而是一个经过反复验证、有质量保障的工程产物。

5.6 探索、调试与回归的三件工具 ​

讲了这么多方法论,最后聊聊能让人事半功倍的工具。如果现在还在用记事本写 Prompt,手动复制粘贴到网页版 ChatGPT 里测试,效率太低,而且完全没法管理和协作。

一个专业的 Prompt 工程师,都有一套属于自己的工具。这里推荐几个日常工作中离不开的,分别解决不同阶段的痛点。

工具链的第一阶段是创意与探索,代表是各大模型厂商官方提供的 Playground。刚开始接触一个新任务,脑子里只有一些模糊的想法时,需要一个能够快速实验、不受代码干扰的环境,这时候 Playground 就是最佳选择。

它解决的头一个痛点是快速验证。不需要写任何 Python 或 JavaScript 代码,可以直接在网页上调整 Prompt,立刻看到结果。创意迭代速度和写代码比,完全不在一个量级。

它还把参数调试的门槛降了下来。网页版的聊天窗口通常是傻瓜式的,但 Playground 暴露了所有核心 API 参数,可以精细地调节 Temperature(控制创造性,值越高输出越发散)、Top-p(控制词汇选择范围)、Frequency Penalty(避免重复词汇)等。通过调节这些参数,能直观地感受到它们对模型输出风格的巨大影响。

再有就是成本感知。Playground 会实时显示每次请求消耗了多少 Token。这能建立起对 Token 成本的直观感受,写 Prompt 时,下意识地就会去考虑“经济性”。

一个典型的 Playground 工作流是这样运转的。脑子里有个想法,比如”写个能把大白话转成商务邮件的 Prompt”,就打开 OpenAI Playground 或 Claude Workbench(国内厂商的开放平台,如火山方舟、阿里云百炼,也有类似的在线调试页面),先写一个最简单的 Zero-shot Prompt,跑几个例子,看看模型的”底子”如何。发现效果不好,就开始加入 Few-shot 示例,再调整 Temperature,看看值低一点输出更稳定,还是值高一点更多样。经过十几分钟的快速尝试,基本能确定一个可行的 Prompt 结构和参数组合,这时候再把它复制到代码里。

第二阶段是调试与分析,代表工具是链路追踪平台 LangSmith。当应用变得复杂,不再是一个简单的“一问一答”时,比如做了一个需要多步推理的 Agent,或者一个结合了数据库检索的 RAG 系统,Playground 就不够用了。

它解决的是黑盒问题。复杂的 LLM 应用是一个黑盒,当它出错时,很难知道到底是哪一步出了问题。是第一步的思考跑偏了?是中间的工具调用失败了?还是最后一步的总结出了幻觉?LangSmith 会把应用中每一次 LLM 调用、每一次函数调用、每一次数据库查询,都像日志一样清清楚楚地记录下来,形成一个可视化的调用链(Trace)。

讲一个典型的 LangSmith 调试故事。做了一个“智能旅行规划 Agent”,用户输入“我想去云南玩一周”,它应该能自动上网查景点、订机票、排行程。可测试时发现,它总是推荐一些莫名其妙的餐厅。打开 LangSmith,找到这次失败的 Trace,点开调用链,问题看得一清二楚。

第一步“规划行程”的 LLM 调用是成功的;第二步“搜索机票”的工具调用也成功了;偏偏第三步“搜索当地美食”的工具调用,返回了一堆广告和不相关的结果;而第四步“总结行程”的 LLM 调用,忠实地把那些错误的餐厅信息给总结了进去。问题定位了!不是 LLM 的推理能力不行,而是“搜索美食”这个工具返回的结果质量太差。接下来该做的是优化那个工具,而不是闷头去改 Prompt。

没有 LangSmith,可能要花半天时间加各种 print 语句才能定位到问题。有了它,每一步调用都摊开在眼前,哪里出错一目了然。

第三阶段是评估与回归,交给自动化测试框架 Promptfoo。当 Prompt 准备上线,或者已经在线上运行时,就进入了最关键的“维护与优化”阶段。这时候最怕的就是为了修复一个问题,搞坏了十个别的地方。

没有测试框架时,对 Prompt 的优化完全凭感觉。“我感觉 V2 版本比 V1 好”,但到底好多少?在哪些场景下好?一概不知。更折磨人的是回归测试,每次修改完 Prompt,都要手动把几十个测试用例再跑一遍,又累又容易出错。

Promptfoo 把这个过程变成了自动化、工程化的流程,核心理念是“用数据说话”。先在项目里敲一个 npx promptfoo@latest init,命令行会以交互式引导生成配置文件 promptfooconfig.yaml,接着在里面定义好测试用例集(Test Cases),每个用例包含输入和期望的输出(或者一个评估标准,比如“必须包含‘北京’这个词”)。再在同一个文件里定义多个不同版本的 Prompt(比如 prompt_v1.txt、prompt_v2.txt)。然后在命令行里敲 npx promptfoo@latest eval,敲完去泡杯咖啡。回来之后敲 npx promptfoo@latest view 打开网页报告,一个矩阵视图清晰展示每个 Prompt 在每个测试用例上的表现,谁通过了,谁失败了,谁的延迟更低,谁更省钱。

有了这个报告,就可以做出基于数据的决策。“V2 版本虽然在‘写诗’这个用例上表现变差了,但它在另外 10 个核心功能上的准确率都提升了 20%,而且成本降低了 30%。所以,我们决定上线 V2。”

这种从凭感觉到看数据的转变,才是真正的 Prompt Engineering。


本章总结 一条完整的迭代路线 ​

这一章完整地走了一遍 Prompt 的迭代式开发流程。

回头看,整个流程的起点是 Zero-shot,它的价值不在解决问题,而在暴露问题,帮工程师摸清模型对这个任务的初始水平。摸清了底,Few-shot 用精心挑选的“黄金样本”给模型打样,同时警惕顺序和分布带来的看不见的偏见。光有正向示范还不够,负向约束负责划定“什么不能做”的边界。

而把这一切串成流程的,是 BAD Case 的处理方式,靠“精准补丁”加“回归测试”,把临时补救换成对稳定性的主动掌控。工具链也配齐了,Playground 负责快速探索,LangSmith 负责深度调试,Promptfoo 负责自动化评估。

整个过程,就是把写 Prompt 这件事从凭个人感觉,变成有标准化流程、质量控制体系和自动化工具的工程。

在这个过程中,会经历无数次的失败和挫折,会看着模型一本正经地胡说八道而哭笑不得,也会因为解决了一个顽固的幻觉问题而很有成就感。这就是和 AI 协同工作的乐趣所在,也是工程师应对不确定性、构建可靠系统的核心价值。

记住,没有完美的 Prompt,只有最适合当前场景的 Prompt。别指望一次写成,靠一轮轮迭代不断改进。

参考资料 ​

  1. Brown, T., Mann, B., Ryder, N., et al. Language Models are Few-Shot Learners(GPT-3 论文,arXiv:2005.14165,zero-shot、few-shot、in-context learning 术语的出处). https://arxiv.org/abs/2005.14165
  2. Lu, Y., Bartolo, M., Moore, A., et al. Fantastically Ordered Prompts and Where to Find Them: Overcoming Order Bias in In-Context Learning(ACL 2022,arXiv:2104.08786,少样本示例排列顺序会显著影响表现的出处). https://arxiv.org/abs/2104.08786
  3. Bray, T. (ed.). RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format(IETF 标准,2017 年 12 月). https://datatracker.ietf.org/doc/html/rfc8259
  4. OpenAI. Create chat completion(官方 API 参考,temperature、top_p、frequency_penalty 参数定义). https://platform.openai.com/docs/api-reference/chat/create
  5. Anthropic. How do I use the Workbench?(帮助中心文章,Workbench 与 Playground 说明). https://support.claude.com/en/articles/8606378-how-do-i-use-the-workbench
  6. 火山引擎. 火山方舟(大模型服务平台,含在线调试). https://www.volcengine.com/experience/ark
  7. 阿里云. 什么是百炼 Model Studio(官方文档,含模型调用的在线调试). https://help.aliyun.com/zh/model-studio/what-is-model-studio
  8. LangChain. LangSmith Observability key concepts(官方文档,run 与 trace 概念). https://docs.smith.langchain.com/observability/concepts
  9. Promptfoo. Getting started(官方文档,promptfooconfig.yaml、promptfoo eval 与网页评估报告). https://www.promptfoo.dev/docs/getting-started/
  10. Promptfoo. Configuration guide(官方文档,测试用例与多版本 Prompt 的配置方式). https://www.promptfoo.dev/docs/configuration/guide