1. 模型不是人:它"读"提示词的方式决定了你的写法
1.1 自回归机制下,上下文就是概率分布的方向盘
先抛一个可能让很多人意外的结论:大语言模型并不真的"理解"你的需求,它做的最核心的一件事,是根据已有的文本预测下一个词。你在对话框里写的每个字,都会进入它的上下文窗口,成为下一轮预测的依据。这个机制听起来简单,但它能解释大量日常使用中的怪现象。
比如同一个问题,你直接问"15和27的最小公倍数是多少",模型常常能给出正确结果;但如果你把这个问题塞在一大段背景介绍的最后一行,它反而容易算错。原因不是模型"分心了",而是它的注意力在长上下文里被分散,关键信息被其他内容稀释了。
我用一个类比来记这件事:模型像一个非常擅长模仿的临时助理。你交给他一份资料,只说"整理一下",他只能按自己印象里"最普遍的整理方式"发挥,结果当然不可控。而提示词工程做的事,本质上就是给这个临时助理一份足够具体的上下文,让他不用猜、也不许猜。
所以,"提示词写得好不好"首先不是修辞问题,而是信息结构问题。你在什么位置强调什么、哪些内容靠近问题核心、哪些示例放在哪里,都在实质性地改变模型产出的概率分布。理解了这一层,后面所有的技巧才有落脚点。
1.2 温度、长度和信息密度:三个被忽略的隐藏变量
提示词之外,还有几个参数经常被忽略,但它们对输出质量的影响一点不比文字内容小。
第一个是温度。温度控制模型从概率分布中取词时的"冒险程度":温度接近0时,模型总是选概率最高的词,输出稳定但略显呆板;温度升高后,它开始接受概率更低的选择,输出变得多样甚至飘。对格式提取、数据整理这类任务,我几乎永远把温度设在0到0.3之间;只有写文案、起标题这类创意任务,才会把温度往上调。
第二个是最大输出长度。很多人习惯给一个很大的上限,觉得"多给空间总没错"。但模型生成时会有一种"顺着惯性写下去"的倾向,长度上限给得太大,它反而不急着收尾,容易在结尾处添加与任务无关的补充说明。更稳的做法是把合理的长度直接写进提示词,比如"不超过150字",让模型在生成时就自我约束。
第三个是信息密度,也就是提示词里有效信息占全部文本的比例。一些模板把背景、示例、注意事项全部堆在一起,真正决定任务的句子只有一两句,模型的注意力自然容易被带偏。我习惯把提示词控制在"一个内行同事不用追问就能完成"的长度,多一句交代背景,少一句无关废话。
另外提醒一句:调提示词时参数一定要固定,否则你就是在两个变量同时变化的情况下做判断,永远分不清输出变好是因为改对了提示词,还是因为改了温度。这个习惯能帮你省掉大量无效返工。
2. 一条靠谱提示词的三层骨架:指令、上下文、输出
2.1 指令层:用"做什么"代替"别做什么"
我见过最多的坏写法,是把要求写成堆否定句:不要啰嗦、不要编造、不要用列表。模型对否定句的处理能力并不好,你越强调"不要编造",它反而越容易生成出带编造嫌疑的内容。原因不难理解:否定句把"编造"这个动作放进了上下文中心,模型更容易顺着这个动作的空间去采样。
更好的写法是正面描述动作。拿内容整理类任务举例:
- 模糊版:"帮我分析一下这个市场情况,写个简单报告。"
- 清晰版:"请基于以下三组数据,分析某目标人群的市场情况。要求:1)200字以内;2)包含现状、趋势、风险三个小节;3)每条结论必须标注对应的数据编号;4)若数据不足,输出'数据不足',不要猜测。"
清晰版把任务类型、篇幅、结构、约束全部钉死,模型几乎没有发挥空间,结果自然稳定。写指令层的几个原则我一直贴在工位上:一是用动词开头,避免"分析一下""大概看看"这类模糊说法;二是每个句子只放一个要求,多个要求拆成编号列表;三是有冲突时明确优先级,比如"以近三个月数据为准,历史数据仅作参考"。
这层是整个提示词的地基,地基不稳,后面的上下文和输出格式做得再好也是白搭。
2.2 上下文层:背景资料、示例与限制条件的摆放顺序
上下文层的任务是为模型补充"完成任务所需的领域信息"。但补多少、怎么摆,很多人没有仔细想过。我的排序习惯是:任务定义放最前面,背景资料放中间,示例紧随其后,附加限制条件放最后。
这个顺序不是随便定的。任务定义放最前面,相当于先告诉模型"你接下来要干什么",让它在后续阅读资料时带着明确的目的;示例放在资料后面、限制条件前面,是因为示例承担着"展示期望输出长什么样"的功能,要紧挨着输出要求;限制条件放最后,则可以起到收尾兜底的作用,把模型刚要开始发挥的边缘拉回来。
上下文层最常见的误区是给得太少或太多。给太少,模型只能凭训练数据里的平均印象作答;给太多,又会造成指令稀释。一个相对可靠的判断标准是:把提示词拿给不了解这个任务的同事看一遍,如果他能不追问就完成任务,说明上下文给得刚好够。
还有一个小技巧:当背景资料比较长时,不要原封不动贴进去,先在指令里做一次剪裁。比如"请从下面的对话中提取与退换货相关的信息"就比"请根据以下对话进行总结"精确得多,因为前者帮模型划定了注意力范围。
2.3 输出层:把格式钉死,模型就不敢乱来
输出层是投入产出比最高的一层。很多时候提示词已经写得不错了,输出内容也正确,就是格式乱成一团,下游程序没法解析。这时候只要在输出层加约束,问题立刻解决大半。
比如做客服对话信息提取,我会直接写:"请从下面的对话中提取信息,输出JSON对象,字段包括customer_name、issue_type、urgency、suggested_action。字段缺失时置为null,不要自行补全。"模型看到这种结构化的输出约束,会自动进入"字段匹配模式",很少再自由发挥。
输出层的另一种常见用法是叠加自检指令:"答案生成后,请逐条核对每个结论是否能在原文中找到依据,如果找不到,删除该结论。"这种自检对精确度要求高的任务特别管用,虽然会让响应时间增加一点,但换来的质量提升通常很值。
还有一个经验值得单独说:输出格式的约束不要只在指令里写一次,最好在结尾再强调一遍。这是利用了模型对上下文结尾内容更敏感的特性,省得它在长篇生成中途把格式要求"忘了"。
3. 高频技巧背后的原理:角色、少样本示例与思维链
3.1 角色设定何时有效、何时失效
"你是一名资深律师""你是一位经验丰富的编辑",这类角色设定几乎出现在所有提示词分享里。它的原理不难理解:模型在训练时见过大量以特定身份写作的文本,当你赋予它一个角色,等于把生成方向往"这个身份常见的表达方式"上引导。对文案、翻译、客服回复这类"风格很重要"的任务,角色设定的效果立竿见影。
不过角色设定有明确失效条件。一个常见的失效场景是"角色与指令冲突":你让它扮演严谨的审计师,又说"随便写写就行",模型通常会受靠后的指令影响,演一半就出戏。另一个更危险的问题是"角色幻觉":当模型对某个专业领域的知识储备不足时,为了维持专业形象,它会更倾向于自信地编造答案。医疗建议、法律解释、财务判断这类场景,我基本不靠角色设定来保证正确性,而是把注意力放在"要求模型标注信息来源、区分事实与推测"上。
所以我的结论是:角色设定是风格工具,不是事实工具。它能让语气更贴合场景,但不会让模型突然变聪明。需要精确推理和事实核查时,应该用下面的思维链技巧,而不是换一个更"权威"的角色。
3.2 少样本示例:数量与选择比"多放几个"重要
少样本示例是让模型对齐"你想要的输出长什么样"最直接的手段。但网上很多教程有个误区:以为示例越多越好。我的实测结论是,三到五个精心挑选的示例,通常胜过十几个重复性很高的示例。数量太多会让提示词变长,反而稀释模型的注意力。
选择示例比增加数量更重要。我挑示例一般看三点:一是覆盖任务的主要变体,比如做文本分类,至少要有正常类、边界类、缺失信息类各一个;二是格式必须与目标输出严格一致,包括标点和字段顺序,因为模型会模仿示例里的所有细节;三是刻意放一两个"容易犯错"的输入,比如字段缺失的样例,明确告诉模型"这种情况该输出什么"。
示例的放置位置也影响效果。我习惯放在任务指令之后、输出要求之前,相当于先讲规则、再看示范、最后说清验收标准。如果示例放在很靠后的位置,模型容易把示例当成"最近发生的指令"去执行,反而压过你前面的规则。
一个踩过的坑:示例本身要反复核对。有次我做字段抽取,手工写示例时漏了一个字段,模型的输出从第三轮开始就跟着漏,排查了半天才发现是示例带坏了节奏。从那以后,凡是用在提示词里的示例,我都要求先在测试集上跑一遍,确认它不会把坏习惯传染给模型。
3.3 思维链提示:把隐形推理变成显式步骤
思维链被讨论得很多,但很多人只记得那句"让我们一步一步思考",然后发现效果时好时坏。问题的关键在于,那句话只是一个引子,真正有效的是把推理过程的结构显式定义出来。
我常用的写法是把步骤写死,例如:"请按以下步骤完成任务:1)列出题目中给出的所有已知条件;2)判断每个条件与问题的关联;3)逐步推导结论;4)用一句话给出最终答案。"当模型拿到这样一份可执行清单,它的推理稳定性会明显提升。这种写法对计算、逻辑判断、方案比较类任务尤其管用。
思维链也有取舍:显式推理会让输出变长,增加时间和费用。如果业务场景只需要最终答案,我一般会在步骤后面加一句"最终回答控制在50字以内"。还有一类更高级的用法是隐藏式推理——让模型"在内部思考,只输出结论",不过这是否有效很大程度上取决于具体模型的能力和指令遵循水平,建议自己实测后再决定要不要用。
4. 一次完整迭代实录:投诉转工单提示词的五版进化
4.1 V1到V5:每次改动改了什么、为什么这么改
光讲理论容易虚,我拿一个真实场景走一遍完整的提示词迭代过程。任务是:把一段客户投诉文本转换成熟练工单概要,需要提取问题类型、紧急程度、用户诉求、涉及商品,并生成一段摘要。
第一版提示词非常简单:"把下面的投诉转成工单概要。"结果输出是散文式的一段话,字段不固定,紧急程度忽高忽低,完全没法直接入库。这一版给我的教训是:自由度越大,模型越会按"训练数据里最常见的表达方式"来写,而不是按你的业务标准来写。
第二版我加了输出结构限制:"请提取以下字段:问题类型、紧急程度、用户诉求、涉及商品,输出为JSON对象。"这一版之后字段名总算统一了,但问题类型仍然五花八门,"商品损坏""质量问题""物流太慢"混在一起写,没有对齐系统预设的分类枚举,下游照样没法聚合统计。
第三版加入分类体系定义和两个示例:一个正常案例、一个信息不足案例。字段值终于落在预设集合里,但新问题出现了——模型开始模仿示例里的措辞风格,示例写得稍微口语化,它的输出也跟着口语化。这让我意识到,示例的"风格信息"和"格式信息"同样会被模型学习。
4.2 同一段输入,两版提示词的输出对比
V4和V5的改动思路是继续做收口:V4把输出要求调整为"语气中性,仅陈述事实,短语不超过20字",并把示例换成两种不同风格,避免模型误以为示例风格是固定模板;V5增加自检步骤,要求模型在输出前区分"原文可直接确认的信息"和"基于推断的信息"。
不用把每一次改动都背下来,关键是看效果差异。下面用同一段输入对比V2和V5的输出。输入大意是:用户反馈某商品到货延迟三天,且外包装破损,申请换货,希望补偿运费。
V2的输出(只有格式约束):
{ "问题类型": "物流问题", "紧急程度": "高", "用户诉求": "换货、补偿运费", "涉及商品": "某商品", "摘要": "用户投诉商品到货延迟,外包装破损,申请换货和运费补偿。" }V5的输出(带自检与信息边界规则):
{ "问题类型": "到货延迟、外包装破损", "紧急程度": "中", "用户诉求": ["申请换货", "希望补偿运费"], "涉及商品": "某商品(原文未提供具体名称)", "摘要": "用户反馈到货延迟三天,外包装破损,希望换货并补偿运费。其中'补偿运费'为用户主观诉求,非平台承诺。", "信息边界说明": ["到货延迟三天:原文可直接确认", "外包装破损:原文可直接确认", "紧急程度:根据延迟加破损推断"] }看到差别了吗?V2把紧急程度直接判定为"高",其实是模型在猜;V5会主动说明这是推断,还会在摘要里区分事实与用户诉求。对只做人工查看的场景,V2勉强能用;但要入库、要自动化流转,V5的"信息边界说明"就是决定性的——下游系统可以放心使用可回溯字段,风险因此大幅下降。代价是V5生成的token数量大概多一倍,对需要入生产环境的数据来说,这点成本非常划算。
4.3 可复用的提示词迭代工作流
这一段是我想重点留给你的部分。提示词优化不是"凭感觉改一句看看效果",而是一套可以重复执行的工程流程,我把它总结成四步。
第一步,建立小测试集。选5到10条真实输入,必须覆盖正常情况、边界情况、信息缺失情况,缺一类都会让后续评估失真。
第二步,定义评分标准。我给常用的任务定了四个维度:格式合规率、字段完整率、内容可回溯率、无幻觉信息率。每个维度单独打分,避免"整体感觉还行"这种无法量化的判断。
第三步,单变量修改。一次只改一层,要么改指令、要么换示例、要么加自检,改完跑一遍同样的测试集,对比结果。如果同时改了三处,效果变好或变坏,你都无法定位到具体原因。
第四步,记录版本。把每版提示词、改动点、测试结果放进一张表,写明"预期变化"和"实际变化"。没有记录,三天后你就说不清今天的效果是哪个改动带来的。
| 版本 | 主要改动 | 观察结果 |
|---|---|---|
| V1 | 首次尝试,无约束 | 格式混乱,字段不固定,无法入库 |
| V2 | 增加JSON输出约束 | 字段名统一,分类值仍不收敛 |
| V3 | 加入分类体系与两个示例 | 分类值收敛,示例风格被连带模仿 |
| V4 | 输出要求收口、替换示例风格 | 风格稳定,仍有推测性填充 |
| V5 | 增加自检与信息边界规则 | 输出稳定,可回溯字段可入下游流程 |
提示:单变量修改是提示词迭代里最难坚持但最有效的一条纪律。一次只改一处,才能准确归因。
这套流程最大的价值在于:它把"这次运气不错"变成"这次规则有效"。哪怕某次改动失败了,记录也能告诉你失败在哪个环节,下一次就不会重复踩坑。
5. 容易翻车的细节与补救:膨胀、污染、位置与评估
5.1 提示词越长不一定越好,警惕指令膨胀
很多团队有个直觉:提示词写得越详细,模型越听话。这个直觉在小范围内成立,但一旦过了某个度,反而会出问题。我见过一条写了快三千字的提示词,把各种边界条件、业务知识、特殊规则全部塞进去,结果模型开始"挑着执行"——开头的要求遵守了,中间的规则被忽略,结尾的要求倒是每条都执行,整体呈现出一种典型的顾头不顾尾。
我把这个现象叫指令膨胀:关键约束被大量次要信息淹没,模型注意力跟不上,执行的确定性反而下降。应对办法其实很简单,就是做减法:删掉与任务无关的修饰语,合并重复要求,把真正的关键约束控制在十条以内;背景资料如果很多,压缩成结构化要点而不是大段文字。
自检的方法是"信息密度测试":把提示词里除了关键指令之外的句子全删掉,看任务是否还成立。如果删完发现关键信息没丢,说明原来的版本里确实有不少废话。
5.2 示例里的坏习惯会被模型学走
示例的双刃剑效应比大多数人预期的更严重。模型不会自动区分你给的示例是"正面教材"还是"反面教材",它只会把它当成可模仿的样本。示例里的口语化表达、省略字段、甚至一个小到不仔细看就发现不了的错别字,都会成为模型复制的对象。
我自己就栽过一次:做一个数据清洗的提示词,示例里的"标准输出"是我手工敲的,结果漏填了一个字段,模型从第一轮开始就跟着漏。我花了几小时以为是输出解析的问题,最后才发现是示例本身带坏了节奏。这件事之后我养成了两个习惯:第一,提示词里的示例一律用程序生成加人工核对,绝不用随手打的临时文本;第二,每次改动示例,必须重新跑一遍测试集——示例和指令是一个互相影响的整体,不能只测其中一部分。
5.3 关键指令的位置:开头和结尾最容易被记住
模型对上下文不同位置的敏感度不一样,这个特性在实际使用中会带来明显的效果差异。简单说,开头的内容负责建立任务框架,结尾的内容在生成时更容易被激活,中间段落经常沦为"被快速扫过"的信息带。
这个特性能解释很多怪现象。比如你把"输出JSON格式"放在提示词中间,模型经常写一半就忘了加反括号;同样的要求挪到开头和结尾各出现一次,问题立刻消失。我遇到过好几次"模型老忘掉某个要求"的情况,起初以为是指令不够强,反复加"注意"两个字也没用,直到调整了位置,才真正解决。
所以定位这类问题时,先别急着加权重,先检查这个要求出现在提示词的哪个位置。凡是关键约束,尽量在开头定义、结尾重申,中间专心放资料和示例。
5.4 用测试集和评分标准,把"碰运气"变成"做工程"
最后聊一个最容易被忽视、却最能拉开水平差距的话题:评估。模型生成有随机性,同一个提示词跑几次结果都可能不一样。如果你只凭"这次输出看起来像样"来判断提示词好坏,本质上就是在碰运气,运气不好时还容易得出错误结论。
最基本的做法是准备一个几十条样本的测试集,每次修改后批量跑几轮,统计一个简单的通过率,比如字段完整率、格式合规率。更进一步,可以写个几行的自动化脚本,批量调用模型接口,把输出和预期字段做比对,定期回归——这会让"提示词维护"进入真正的工程化状态。
注意:测试集必须与业务输入同步更新,否则它只会给你虚假的安全感。
我想提醒这一点,是因为自己项目里就吃过亏:有段时间上游数据格式变了,但测试集没有同步更新,提示词在本地跑分一直很好看,实际业务效果却在悄悄下滑。保持测试集与真实输入同步,和保持代码与需求同步一样重要。
这大概就是我在提示词工程这件事上最想说的部分:它不是一个可以速成的技巧清单,而是一套需要持续维护的小型系统。你越是把它当作工程来对待,它就越是会给你稳定的回报。