☰
提示词工程实战:任务边界、结构化输出与评测集迭代
2026/10/27 14:08:51 网站建设 项目流程

第一次被问“Prompt工程师到底是干什么的”,我的回答是“把话说清楚”,对方明显不满意,我自己也不太满意。后来经手了几十个真正上线的提示词任务,从工单分类、合同要素抽取到批量内容审核,才慢慢把这句话补全:把话说清楚只是起点,真正的活是把一个模糊的人类需求,翻译成模型能稳定执行、能被评测、能被复盘的一整套指令。这篇就按我实际干活的顺序,把提示词工程拆开讲一遍——从任务边界怎么定,到提示词骨架怎么搭,再到怎么建一个小评测集判断改动是变好还是变坏。适合两类人看:一类是刚接触大模型、还停留在收藏模板阶段的,另一类是用了一阵子但效果时好时坏、不知道该往哪调的人。

1. 先别急着背模板:提示词工程真正处理的是“任务边界”

网上流传的模板大多是“你是一位拥有二十年经验的XX专家”,很多人照着改了几天,发现效果起伏很大,就开始怀疑是不是模型不行。实际情况往往是:模板解决的是语气和风格,解决不了任务定义模糊。一个提示词写得再漂亮,如果它没有明确告诉模型“输入里哪些字段是必须用的”“输出错了要不要重来”“判断不出来的时候怎么回答”,那它在真实业务里就是个半成品。

1.1 同一句话两次输出不一样,这是特性不是故障

先把一个基础认知说透:主流对话式模型在生成时是按概率逐词采样的,同一段输入,采样温度不为零,输出路径就可能分叉。这意味着你写的提示词本质上是在约束一个概率分布,而不是调用一个确定性函数。很多人第一次遇到这种情况会以为模型“不稳定”“抽风”,其实是你给它留的决策空间太大了。

举个我早期踩过的例子。当时要做一个工单自动分级,我的提示词大意是:“请根据工单内容判断它的紧急程度。”跑十条有六条还行,剩下四条里,两条把“系统偶发卡顿但不影响业务”判成了紧急,两条把“需要当天回复”判成了普通。问题不在模型,在于“紧急程度”这四个字本身没有边界——它既可能指技术影响面,也可能指用户情绪,还可能指响应时效。

后来我把它改成三段式,效果立刻稳下来:

  • 判断维度拆开:影响面(单用户/多用户/全部)、是否阻断业务、是否有明确时限要求。
  • 每个维度给判据:阻断业务指核心流程无法继续,非阻断指可绕过。
  • 给组合规则:任一维度命中“全部”或“阻断”即为高;仅有时限要求为中;其余为低。

这背后是一个很朴素的道理:模型不擅长在你没有明说的地方替你做决策。你不定义清楚,它就会用训练数据里的平均直觉去填,而这个平均值未必符合你的业务口径。

1.2 把“帮我写个方案”翻译成机器能执行的指令

我习惯在动笔写提示词之前,先在纸上填完四格,填不满就先别写:

要素要回答的问题常见错误
任务动词到底要模型做什么?分类、抽取、改写、还是生成?一句话里塞三四个动作
输入材料哪些是任务必需的,哪些只是背景?把整篇文档全塞进去当上下文
判断标准什么算对,什么算错,边界情况怎么处理只写“准确”“专业”这类形容词
输出形态字段名、类型、取值范围、长度只说“用表格输出”

这四格里最容易糊弄过去的是“判断标准”,也是最能拉开水平差距的一格。我见过一个做简历要素抽取的需求,原始描述是“把关键信息提取出来”。这话人类听了都要追问,模型自然只能猜。补全之后变成:必须抽取姓名、最高学历、毕业年份、最近一段工作年限四个字段;字段缺失填 null,不要自行推断;毕业年份只接受四位数或 null;学历只接受给定的六种枚举值。把“判断标准”写成可验证的条件,等于把一半的评测工作提前做完了。

还有一点常被忽略:任务的失败形态要提前设计。模型判断不出来时,你是希望它输出“无法判断”加原因,还是希望它硬猜一个?这两条路在业务上的后果完全不同。前者安全但需要人工兜底流程,后者省事但会污染下游数据。我现在的做法是,凡是对准确性要求高的抽取类任务,一律要求模型在置信度不足时输出{"result": null, "reason": "..."},让人工处理兜底。

2. 一份能上生产的提示词骨架长什么样

把任务边界想清楚之后,才轮到组织语言。我自己的提示词结构基本固定成六块,顺序是:角色与场景 → 任务陈述 → 输入说明 → 规则约束 → 输出格式 → 示例。这个顺序不是玄学,是按“从上到下逐步收紧”的逻辑排的:先给模型一个词汇域,再给任务,再给材料,再收规则,最后用格式和示例把输出压死。

2.1 六件套的排列顺序为什么这么定

角色放最前面,作用其实没传说中那么大,但它有两个实际价值:一是把模型拉进某个专业词汇域,让它后续用对术语;二是统一输出的语气调性。我一般只写一句,比如“你是负责电商售后工单初级分诊的运营人员”,不会堆“资深”“专家”“十年经验”这类修饰——堆得越多,模型越容易过度发挥,写出漂亮的废话。

任务陈述要短,最好一句话说清楚动作和对象:“阅读下面的工单正文,判断它属于哪一类问题,并输出结构化结果。”动词必须是可执行的,“理解”“分析”这类词太虚,“判断”“抽取”“改写”“按……排序”才是有明确产出的。

输入说明容易被写成流水账。我的做法是用分隔符把材料和指令隔开,并在材料前说明它的结构。比如:

<工单> 标题:{{title}} 正文:{{content}} 提交渠道:{{channel}} </工单>

用尖括号或其他标记包裹材料,好处是模型能明确区分“这是数据”和“这是指令”,降低把用户内容当指令执行的风险。这一点在有用户自由输入的场景里尤其重要,属于必做项而不是加分项。

规则约束是整份提示词里信息密度最高的部分。我写规则有三条自我要求:能用条件句就不用形容词;能列枚举就不写“等等”;规则之间不能打架。见过一份提示词里同时写着“回答要详细”和“控制在三句话以内”,模型最后两边各取一半,输出两段短句加一句长的,谁的需求都没满足。

输出格式和示例放最后。格式部分我倾向于直接给一个 JSON 骨架或者字段表,示例则选最有代表性的两到三个,不要贪多。示例选得不好会产生副作用:如果三个示例都是长文本输入,模型遇到短输入时也可能硬凑长度。

2.2 用输出格式约束替代反复叮嘱

一个很实用的经验:能用格式约束解决的问题,不要用文字反复强调。“务必只输出 JSON,不要输出任何解释性文字”这种句子写三遍,效果往往不如直接把期望结构摆出来,并且补一句“第一个字符必须是左花括号”。

我常用的写法是这样:

输出要求: 仅输出一个 JSON 对象,不要包含 markdown 代码块标记,不要有任何前后说明文字。 字段定义: - category:字符串,取值必须是 [物流, 质量, 售后, 其他] 之一 - confidence:数字,0 到 1 之间,保留两位小数 - reason:字符串,20 字以内,说明判断依据 如果无法判断,category 填"其他",confidence 填 0,reason 写"信息不足"。

这段的价值在于它把“输出什么”变成了一个可被程序校验的契约。下游代码可以直接做 schema 校验,字段缺失、枚举越界、类型不对都能第一时间发现。相比之下,“请用规范的格式输出”这种要求,除了让模型紧张之外没有任何作用。

顺带说一句结构化的容错。即使你把格式写得再死,模型偶尔还是会加一句“好的,以下是结果”。我的处理方式不是继续在提示词里加感叹号,而是在代码侧做一个简单的清洗:找到第一个{和最后一个}之间的内容再解析。工程上多写五行代码,比在提示词里反复拉扯省心得多。

3. 指令之外的硬功夫:上下文组织与信息密度控制

提示词写多了会发现,前 20% 的功夫在措辞,后 80% 的功夫在放什么材料进去、怎么放。同一个任务,上下文组织方式不同,准确率能差出一大截。这部分工作没什么技巧感,但特别吃经验。

3.1 长文档场景:把资料切成能被引用的块

做文档问答或者要素抽取时,最原始的做法是把整篇文档粘进提示词。文档短的时候还行,长了以后会出现一个典型现象:模型对开头和结尾的段落记得清楚,中间部分容易漏。这不是模型偷懒,是长上下文里信息权重分布本身就不均匀。

我的处理方式是分块加编号,并在指令里要求模型引用块号:

下面提供了若干条资料,每条以 [S1]、[S2] 这样的编号开头。 只允许使用资料中的内容作答,每条结论后必须标注来源编号,如 [S2]。 如果资料中没有相关信息,直接回答"资料不足",不要推测。 [S1] ... [S2] ... [S3] ...

要求标注来源编号,表面上是给用户看的,实际上是给开发者看的——它能让你快速定位是检索给了错材料,还是模型读错了材料。这两种失败的处理方式完全不同:前者要改检索,后者要改提示词。没有来源标注,你只能看到一个错答案,然后凭感觉乱改。

另外一个细节:分块的时候不要机械按字数切。我一般按语义段落切,单块控制在几百字,块与块之间保留一点重叠,避免一个完整论述被切成两半。块太多的时候(比如超过二十块),考虑先做一轮粗筛再喂给模型,别指望它自己从三十块里挑出相关的那三块。

3.2 少即是多:删掉那些让模型分心的废话

新手写提示词有个普遍倾向:怕说不清楚,于是把所有能想到的注意事项都写上去。结果提示词变成两千字的小作文,里面还夹着互相矛盾的条款。我做过一次对比,同一个分类任务,一份 1500 字、包含大量“注意”“务必”“请严格遵守”的提示词,和一份 400 字、只有任务、判据、格式三块的提示词,在二十条测试用例上的准确率,后者反而高了几个点。

原因不复杂:指令越多,模型需要同时满足的约束越多,冲突概率越大。而且那些没有具体指向的强调词——“务必准确”“严格专业”——本身不携带任何可执行信息,只会稀释真正有用的那几句。

我现在删提示词的标准是三条:这句话能不能翻译成一个可检查的条件?不能就删。这条规则和前面某条规则有没有重叠?重叠就合并。这句话是不是只在极少数边界情况才有用?是的话挪到边界规则里单独写,别放在主干。

信息密度这件事还有个反向的坑:把不该给的背景当成“有帮助的上下文”塞进去。比如做一个情感判断,你把用户的历史订单金额、会员等级也带上,本意是让模型更懂业务,结果模型开始用“高价值用户抱怨更严重”这种它自己发明的逻辑来判断情感。上下文不是越多越好,每多给一段材料,你就多承担一份它被误用的风险。

4. 迭代不是玄学:给自己建一个小评测集

提示词改到第三版之后,凭感觉已经判断不出好坏了。这时候最该做的一件事,是攒一个十几二十条的小评测集。听着像正经算法团队才干的事,其实门槛很低,一个表格就够。

4.1 用十几条用例替代“感觉好多了”

我的评测集通常这么组:六到八条正常样本,覆盖主要业务类型;四到六条边界样本,就是那种人判起来也要想两秒的;三到四条对抗样本,包括信息缺失、格式错乱、包含干扰指令的输入。总数控制在二十条以内,因为再多我就懒得跑了——能坚持跑的小集合,比跑一次就荒废的大集合有用得多。

跑的方式很土:把每条输入喂进去,把输出贴回表格,人工对照期望结果打勾或打叉。后来嫌麻烦,写了个脚本批量跑,输出和期望值丢给一个规则校验函数(字段是否存在、枚举是否合法)先过一遍,剩下格式合法的再人工看内容。一天之内改三版提示词,每版都跑一遍,用不了多少时间。

这里有个细节值得说:别用同一批样本反复调到全对。调十轮之后,你的提示词很可能只是把这二十条背下来了。我的做法是留五条“只在大版本更新时才跑”的样本,平时不动它们,用来检验是不是真的泛化了。

4.2 失败归因:先分清是提示词问题还是任务不可解

看到错例,第一反应不该是改提示词,而是分类。我习惯按下面四类归档,不同类别对应完全不同的处理动作:

失败类型表现处理方向
定义缺失模型按自己的理解答了,但和你的口径不同补判据、补枚举,改提示词
信息不足输入里确实没有判断依据改上游数据,提示词加兜底分支
指令冲突输出来回摇摆,或者两段自相矛盾删减规则,合并重复条款
任务超出能力需要专业计算或多步推理才能得出拆成多步,或换方案,别硬调

表格里最后一行最容易被忽视。有些任务就是不适合让模型一步做完,比如“根据这份财报判断公司是否值得投资”,你无论怎么优化提示词,它给的也只是一个像模像样的猜测。这种情况下正确的动作是把任务拆解:先抽取关键财务指标,再用规则或公式计算,最后让模型做文字归纳。提示词工程师的价值有时候体现在“知道什么不该交给模型”。

归因这个动作还顺带解决了团队协作里的一大矛盾。产品说“效果不行”,工程师说“模型就这样”,双方都说不清。有了分类表,讨论就能落到具体某一条错例属于哪一类,谁的活谁去改,比空对空吵有效得多。

5. 那些让效果打对折的写法

有几类写法我踩过坑,也在别人交上来的提示词里反复见到。单独拎出来说,是因为它们的破坏力往往被低估——不是让效果下降一点,而是直接砍半。

5.1 否定式指令与“不要”的陷阱

“不要输出解释性文字”“不要使用口语”“不要编造信息”——这些句子写在提示词里,模型经常会做出某种奇怪的反应:它确实照做了,但同时把有用的内容也一起删了;或者它在开头写一句“我不会编造信息”,然后继续编。

原因在于,否定式指令只告诉模型要避开什么,没告诉它该做什么。模型的注意力被“解释性文字”这几个字吸引,反而更容易生成相关内容。同一件事,换成肯定式表述会稳得多:

  • “不要输出解释” → “只输出 JSON 对象本身”
  • “不要编造信息” → “资料中没有的信息一律填 null”
  • “不要太啰嗦” → “每条结论控制在 30 字以内”
  • “不要用口语” → “使用书面语,避免‘挺’‘蛮’‘搞’这类词”

实在无法转成肯定式的时候,我的做法是给出替代方案:“如果无法从资料中确认,请输出‘无法确认’并说明缺少哪个字段”——它不仅说了不要做什么,还铺好了另一条路。

5.2 多重任务混在一条提示词里

第二个高频问题是一条提示词里塞了好几个任务:先总结,再分类,然后写回复话术,最后给出置信度。写的人觉得效率高,一次调用全搞定,实际上每个任务的准确率都在下降,而且你根本不知道是哪一步出的问题。

我吃过这个亏。当时一个客服场景,一条提示词里做了意图识别、情绪判断、回复生成三件事。上线后回复质量时好时坏,排查了半天才发现:情绪判断错了,回复话术就跟着错,但错误表现在最后一环,看起来像是生成能力的问题。

后来拆成两条:第一条只做结构化判断,输出意图、情绪、是否需要人工介入三个字段;第二条拿这三个字段和原始问题去生成回复。多了一次调用,但每一步都能单独评测,出问题也能立刻定位。多花的那点调用成本,远低于排查成本。

除了拆分,还有个折中办法:在多任务提示词里强制分段输出,比如要求先输出### 判断,再输出### 回复。这样至少能从输出结构上看出来是哪一段出了问题。不过这只是缓解,真要长期维护,还是拆开干净。

第三个要提一下的是模糊量词。“简短一点”“详细一些”“专业一些”,这类要求对模型来说等于没说。我见过最离谱的一份提示词,通篇是“请务必写得专业、准确、简洁、全面”,四个词互相打架,模型最后产出一段又干又空的东西。把这些换成具体数字和具体禁令——字数上限、必须包含哪几项、禁止出现哪类词——效果立刻不一样。

6. 从单条提示词到可维护的提示词资产

提示词写到一个程度,就不再是随手写在对话框里的一段话,而是要进代码库、被多人修改、跟着业务变化迭代的东西。这时候管理方式就得跟上,不然半年后没人说得清某句规则为什么在那儿。

6.1 版本记录该写什么,不该写什么

我的习惯是在提示词文件头部留一小段注释,只记三件事:版本号、改动日期、改动原因。原因那一栏最关键,不写“优化提示词”“调整措辞”这种废话,要写清楚是哪个场景出了问题、改完解决了什么。比如“v3:工单分类中‘退款进度’被误判为售后咨询,补充渠道判据”。半年后回头看,这一行比整份提示词都有价值。

改动幅度大的时候,我更倾向于新建文件而不是原地改。保留旧版本,用评测集对比新旧两版的表现,确认新版本在全部样本上不退化再切换。这个流程听着重,但比“改完上线发现某个老场景挂了再回滚”要轻得多。

另外,把提示词里的可变部分抽成变量是必须做的。用户输入、检索到的资料、当前时间、可选的枚举列表,这些东西硬编码在提示词里,改一次枚举就得动整段文字,非常容易漏。抽成模板变量之后,提示词本身保持稳定,业务参数从外部注入,维护成本能降一大截。

6.2 结构化输出和工具调用场景下的写法差异

纯文本生成和结构化输出,提示词的写法重心完全不同。纯文本任务,你可以花篇幅去调语气、调节奏、给风格示例;结构化输出任务,重心全在字段定义的严密性上。

字段定义有几条硬要求:每个字段的类型必须明确;取值范围是枚举的必须列全;可空字段要说明什么情况下为空;字段之间的依赖关系要写清楚,比如“state 为 rejected 时 reason 必须有值”。这几条听起来像写接口文档,实际上就是——把模型当成一个需要严格契约的调用方。

工具调用场景还有个额外的坑:工具描述本身也是提示词的一部分。参数名起得含糊、描述写得空洞,模型就会传错参数或者干脆不调用。我改过一个查询工具,原本参数说明写的是“查询条件”,模型经常传一整句话进去。改成“日期,格式 YYYY-MM-DD,例如 2024-03-01”之后,传参正确率明显上来了。这件事的启示是:优化工具描述,有时候比优化主提示词的收益更大,而且改动成本极低。

最后一个实践上的建议:把提示词、示例、评测用例放在同一个目录下管理,改提示词的时候顺手能跑一遍用例。这套东西搭起来不到半天,但能让后续每一次改动都心里有底。

我个人在实际操作中的体会是,提示词工程里最难的部分从来不是写,而是判断“这次改动到底算不算变好”。前面那套二十条样本的小评测集,帮我挡掉了至少三四次自以为是的“优化”——有些改动在顺手挑的那几条例子上表现很好,跑到边界样本上就原形毕露。如果只能给一条建议,我会说:先花两个小时把评测集攒起来,再动手改提示词。顺序反了,后面全是白费劲。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询