AI Agent学习(4):了解提示词工程

0 阅读11分钟

先提前叠个甲:本人6年开发转AI Agent,分享文章仅是我个人心得,就当看个乐呵

先说一个大概率你也遇过的场景:你让 AI「查一下这个月卖得最差的产品」,它秒回,答案具体到产品名和数字,看着特别专业。一查,编的。

它不是笨,是它压根不认识你的数据库,不知道你的统计口径。它手里只有你给的那句话。

提示词工程,说白了就是【把任务交代清楚】的学问。不改模型、不训数据,把话说对,效果就能差出一大截,这是现阶段撬动模型能力成本最低的杠杆

我的套路一句话:约束写死、示例给足、输出进 schema。这三个词什么意思,下文一个个讲:

image.png

一、为什么需要提示词:把模型当新同事

造环境:它手里只有你给的材料

把模型想象成一个聪明但完全不了解你公司的新同事

你跟他说「把这个做了」,他做出来的多半不是你要的。不是能力问题,是他缺上下文:不知道背景、不知道口径、不知道你要什么格式。

所以提示词的本质不是下指令,是【造环境】:模型手里没有你的上下文,提示词就是它能抓到的全部环境信息。材料给得越清楚,它发挥越靠谱。

分区:像入职手册一样分章节

【我的踩坑】 实际项目里有个页面操作 Agent(替人在后台页面上点按钮的智能体),我第一版把所有规则糊成三大段自然语言。结果模型时而遵守时而无视,出了问题我自己都背不住里面写了啥。

后来改成分区:角色、页面状态、操作规则、完成条件、输出格式,各占一个尖括号标签块,相当于给新同事的入职手册分好章节:

<rules> 只用明确索引;同一动作最多 3 次,页面变化后可重试 </rules>
<completion> 完整完成 / 达到最大步数 / 卡住,三种情况立即调 done </completion>
<output> 每步必须调用 AgentOutput:评估上一步 / 记忆 / 下一步目标 / 动作 </output>

分区最直观的收益是定位问题变快:某个行为不对,我能直接说「这是规则区第几条没起作用」。

一次调用里这些材料怎么拼、拼完去哪,一张图说清楚:

image.png

分层原则一句话:【稳定的放前面,多变的往后拼】。角色和红线几乎不变,放最前面的 system;字段表、示例这些每次都变的,往后拼。提示词和上下文工程怎么分界,放在 4.5 篇细说。

二、写规则的两个小技巧

技巧一:别写「不要XX」,改写成正向指令

先做个实验:接下来十秒,别想大象

你想什么了?大象。

模型一个毛病。「不要输出多余字段」「不要编造出处」这种写法,遵从率明显低于正向指令。我的理解有两层:一是「不要」反而先把注意力引到那件事上;二是负向清单永远列不全,模型遇到清单外的情况就自由发挥。

解法是逐条翻译成正向:

失效写法改成正向
不要输出多余字段输出只包含 schema 中列出的字段
不要重复点同一个按钮同一动作最多执行 3 次,页面变化后可重试
不要编造出处每个结论必须附来源字段并摘录原文
不要跳出当前页面仅在当前页面内完成全部操作

「不要」不是不能用,【只留给绝对红线】(隐私、安全这类),旁边配一条正向指令兜底。

技巧二:重点用【】、「」或加粗包裹,等于加权

字段名、枚举值、必须严格执行的规则、不能碰的红线,我会用【】、「」或直接加粗把它们包起来。原理很朴素:LLM 对这类视觉标记很敏感,被包裹的内容相当于加了权重,模型会把它们当重点对待。你现在读的这篇,满篇的【造环境】【只留给绝对红线】除了方便你扫读,同样的写法放进提示词里就是权重标记,字段名套反引号同理。

注意别滥用:满篇都是包裹,等于没有包裹。权重是相对的,一段标一到两处,真正不能出错的地方才值得标。

三、思维链 CoT:让它先列草稿再答题

是什么:先写步骤,再给结论

学生考试不写过程直接填答案,容易错,错了还不知道错在哪一步。模型一样:多步骤任务直接要答案,它凭直觉蹦结论,跳着跳着就歪了。

CoT(Chain of Thought,思维链)的人话版就一句:让它先把思考过程写出来,再给结论。两种问法的差别:

image.png

不用教它怎么拆,加一句「先列步骤再回答」,它往往自己就把任务拆开走稳了。

来历与效果:一句咒语,白捡的提升

这一句是有来历的:2022 年 Google 的论文《Chain-of-Thought Prompting》正式提出思维链,作者 Jason Wei。原版咒语是「Let's think step by step」,加在提示词里,零示例也能唤醒推理,这叫 Zero-shot CoT;另一种是 Few-shot CoT,在示例里把解题步骤完整写出来,让模型照猫画虎学推理。

效果有多猛?数学题数据集 GSM8K 上,PaLM 靠思维链提示,成绩比传统提示提高约 300%,甚至超过当时有监督训练的最优结果。一句大白话,白捡的提升。

为什么有效:模型没有「内心戏」

为什么写出来就有用?因为模型是一个 token 一个 token 往外蹦的,它没有「内心戏」:没写出来的思考,等于没发生。直接要答案,是逼它一跳到底;先写步骤,每一步写出来的文字都会变成下一步的上下文,等于给它发了一张草稿纸,答案是在草稿纸上推出来的。

实战:把「想」钉成必填字段

【我的进阶玩法】 不只要它想,还把「想」钉成固定字段。第一节骨架里的 AgentOutput,三个反思字段(评估上一步 / 记忆 / 下一步目标)排在动作前面,等于把 CoT 从「建议」升级成必答题,模型想跳过都不行。

早期我只在提示词里写「请一步步思考」,模型有时把思考缩成一句「好的」,有时干脆不写;钉成字段后,反思质量稳定多了。这招对长循环 Agent 尤其值钱:几十步跑下来,每步的记忆字段就是天然的调试日志。

配套一句:这类要稳的推理任务,把温度压低(temperature 调到 0.1 一档),别让随机性把思维链抖散。

边界:什么时候别用

但别迷信,两个硬局限。一是模型太小玩不转:推理能力要规模到位才「涌现」,20B 以下的小模型加 CoT 基本无效,硬加还容易出幻觉。二是推理对了,算术照样翻车:论文里模型步骤全对,最后把 6×13 算成 68。草稿纸给了它推理的空间,没给它计算器;精确计算,还是得代码上(第五节的语义层校验就是干这个的)。

CoT 也不是免费午餐:输出更长更慢,token 就是钱。我的开关标准:【多步骤、多条件、要排步骤的任务才开】;一眼就有答案的简单活(提取字段、改写语气),开了纯属多花钱。

顺带一提:新一代推理模型(o1、DeepSeek-R1 这类)把这步内置了,模型自己先想再答,思维链在 API 里单独计费。手工加「先列步骤再回答」是普通模型时代的打法,两者不冲突,但你要知道自己在用哪种。

四、Few-shot 示例:讲不清的道理,做一遍给他看

什么时候必须给例子

教人做菜,念菜谱不如直接做一遍给他看。

所以规则讲不清楚的时候,给例子比讲道理稳。两类场景最灵:一是格式固定的活儿,讲半天不如贴一个样例;二是「只可意会」的判断(语气、风格、边界口味),语言很难定义清楚,例子一下就对齐。数量 2 到 5 个够用,多了反而把模型带偏、还塞上下文。

我的踩坑:手写示例的两个问题

示例从哪来,这里有大学问。我最开始手写 3 条兜底示例硬编码在提示词里,后来发现两个问题:

  1. 跟格式说明里自带的示例内容重复,格式化后约 550 字符,白白把提示词撑长;
  2. 手写例子是我猜的「典型情况」,跟线上真实数据分布对不上,模型学了个偏的。

最后的解法:从真实数据检索注入

few-shot 不手写,整条流水线长这样:

image.png

示例分布永远跟线上对齐,数据变了重跑一次入库脚本就自动更新。

还有一个反直觉的决定:检索失败或无结果时,我一条示例都不给,也不回退到手写兜底,因为格式说明里本来就带标准示例,够用了。兜底示例抚慰的是我的心理,对模型是负资产。

五、结构化输出:让程序接得住它的回答

为什么要结构化:程序得接得住它的回答

前面讲的是让模型想明白、说明白。但做 Agent,你的程序还得能【吃下】它的回答。

自然语言太自由,今天多一句明天少一句,代码没法稳定解析。人话版解法:让同事填表,别让他写散文。约定好必须返回哪些字段、什么类型、枚举值是哪几个,这就是 schema(输出结构约定)。

那怎么让模型真的按 schema 吐?这不是一招,是一个三级阶梯,可靠性从低到高,按需选:

image.png

第一级:提示词约定

在提示词里写死字段、类型、枚举,模型自觉遵守。最简单也最不牢靠:模型偶尔加一句「好的,以下是结果」,markdown 代码围栏忘了摘,输出一长,后半段格式开始漂。小任务、验证想法的阶段用它。

第二级:工具调用(Function Calling)

把输出定义成工具的参数 schema,模型「调工具」这个动作本身就是结构化输出,参数天然受约束。【我的极端玩法】 页面 Agent 的「单工具模式」就是这一级:只给它 AgentOutput 一个工具且每步必须调用,于是「输出结构」同时就是「行为结构」,不吐合法 JSON 就什么都干不了。顺带掰一个容易混的概念:现在工具生态的主流接线标准是 MCP,但 MCP 管的是工具从哪来、怎么接给模型;输出受 schema 约束,靠的是 FC 这套机制。两回事,别打包理解。

第三级:API 强制

OpenAI 的 structured outputs(response_format 带 json_schema)、开源推理框架 vLLM / SGLang 的 guided_json:在解码阶段每个 token 只从合法集合里采样,语法上不可能产出非法 JSON。可靠性天花板,前提是你的模型或平台支持。

阶梯之后:语义层交给代码

那有了三级阶梯,还要不要代码校验?要。因为阶梯管的是语法(是不是合法 JSON、类型对不对),管不了语义(字段值在不在白名单、操作符允不允许、数字合不合理)。我在翻译节点后面照样接纯 Python 硬校验,不过关就退回重翻或降级。语法层交给模型侧的阶梯,语义层交给代码,各管一段:

image.png

保命两件事

最后两件保命事,比任何写作技巧都值钱:

  1. 版本管理:提示词别硬编码散在代码里,要配置化、可热加载,并且版本号随每次调用记录进 trace。不然「这个 badcase 是不是我上周改提示词改出来的」永远答不出来。
  2. 固定问题集回归:我把 20 个典型用例存成脚本,每次改完提示词全量跑一遍、肉眼对比。没有这一步,改提示词就是蒙着眼开盲盒。

结尾

提示词工程说到底就一句话:把模糊的期待,写成机器可校验的约定