1. 内容整体设计与思路拆解
我在实际接触大模型应用时,最常被问到的问题不是“模型能力不够”,而是“明明同样的需求,为什么这次输出能用,下次输出就跑偏”。很多人第一反应是换模型、调参数,但实际上大多数不稳定的根源在于 prompt 本身。Prompt 优化不是靠感觉微调几个词,而是要把“模糊的意图”翻译成“模型能稳定执行的指令”。这篇文章就把我踩过坑后沉淀下来的 8 种优化技巧拆开讲,配合具体的改写前后对照,让你看完就能直接用。
先说一个基本判断:大模型的输出不稳定,通常分为三类。第一类是“理解不稳定”,同一个 prompt 给两次,第一次理解成 A 意思,第二次理解成 B 意思;第二类是“格式不稳定”,要求 JSON 输出,结果偶尔夹带 Markdown 代码块标记;第三类是“内容深度不稳定”,有时输出详细到像论文,有时又敷衍得像一句话总结。这三类问题,靠调整 temperature 这类参数只能缓解一部分,真正解决问题的核心是把 prompt 从“自然语言”推向“半结构化指令”。
我常用的优化思路是“分而治之”。不要指望一条 prompt 同时完成理解、格式、深度、风格的全部约束。而是把任务拆成:角色定义、任务描述、输入输出约束、示例引导、边界规则、质量要求、失败兜底这七个模块。一条稳定的大模型 prompt,本质上是一份“仅包含必要信息的需求说明书”,多一句废话,就多一分跑偏的风险。很多初学者生怕模型看不懂,把背景写得比需求还长,结果关键指令被淹没在冗长的解释里,模型抓不住重点,输出自然忽好忽坏。
8 种优化技巧,并不是互相孤立的。它们之间存在递进关系:先明确角色和任务边界,再去设计输出格式和示例,最后加入约束和自检机制。这就像写代码时先定义函数签名,再写函数体,最后补异常处理。如果你跳过前两步直接加约束,往往会出现“约束越多,模型越不知道以谁为准”的情况。后面我会把每种技巧的适用场景、改写逻辑、以及我实际用下来的效果变化都列出来,方便你对照自己的 prompt 排查问题。
2. 8种Prompt优化技巧逐个拆解
这 8 种技巧分别是:角色锚定、任务拆分、格式约束、示例引导、否定转正面、上下文裁剪、自问自答、自检清单。每一种解决的是不同维度的不稳定,我会按“核心原理—适用场景—改写示例—效果说明”的顺序来讲,并且把我在真实项目中遇到过的翻车案例穿插在里面。
2.1 角色锚定:给模型一个“人格坐标”
很多人觉得“你是一个资深XX专家”是套话,但实测下来,这行字对输出稳定性影响极大。原因是模型在生成时,会根据 prompt 激活不同的参数分布区间。角色描述相当于给模型一个“先验概率”,让它倾向于从某个知识领域和语气风格里采样。没有角色约束时,模型会平均分配各种可能性,结果就是这次像客服,下次像学者。
我做过一个对照实验:同样的产品文案需求,一组不加角色描述,一组加上“你是一名专注消费品文案的资深编辑,擅长提炼卖点,语气克制但有感染力”。运行 20 次后,不加角色的一组文案风格方差极大,有的像朋友圈广告,有的像商品详情页;加角色的一组虽然每轮用词不同,但结构稳定在一段标题加三句卖点描述,风格也始终保持在专业编辑的语感范围内。
注意,角色锚定不是越长越好。我见过有人写“你是一名拥有十年经验、曾在某大型公司任职、深谙用户心理、擅长转化率优化的超级运营专家”,这种堆砌反而会分散模型的注意力。建议保持单一角色、单一职责范围。比如“你是一名数据清洗工程师,负责将用户输入的杂散文本整理成结构化记录”就比“你是一名数据工程师、产品经理、文案专家”要稳定得多。
2.2 任务拆分:一次只让模型做一件事
大模型最怕“既要又要”的指令。比如“请总结这篇文章,并分析它的情感倾向,再写出五个可执行的建议”,这种复合任务会让模型在多个目标间摇摆,输出往往是大杂烩。我在做某客户的需求整理工具时就踩过这个坑,当时要求模型“提取关键信息并生成 JSON”,结果模型一会儿输出纯 JSON,一会儿输出解释性文字,格式始终不统一。
解决办法是拆分成两轮调用:第一轮“提取关键信息,以自然语言描述”,第二轮“将上一轮结果转换成 JSON 格式”。甚至第二轮 prompt 里直接把第一轮的输出粘贴进去作为输入,模型只需要做“格式转换”这一个动作,成功率高得惊人。这就是所谓的“单步指令”原则,每次调用只负责一个明确的认知环节。
如果确实需要复合任务,也可以在同一轮内用序号把任务切开:“先做第一步,再做第二步,第三步在第二步结果基础上进行”。目的是帮模型建立执行顺序的坐标系。我自己习惯在 prompt 里写“按以下步骤执行:1. 2. 3.”,这样做比写“请先…然后…最后…”的歧义要小很多,尤其适合 GPT 系列这种对编号敏感的模型。
2.3 格式约束:把输出框进固定形状
输出格式不稳定是最容易让人血压升高的问题。你明明说了“返回 JSON”,它非要给你套个 ```json 标记;你要求输出 Markdown 表格,它偶尔给你漏掉表头。根因在于模型对“格式”的理解受训练数据影响,如果训练语料里大量是带标记的代码块,它就倾向于模仿。
我常用的三重格式约束法,实测能大幅提升格式稳定性。第一重,在任务描述里明确指定语言类型或格式类型,比如“直接输出 JSON 对象,不要添加任何解释文字”;第二重,在示例中给一个的完整输出示例,让模型看到目标格式的全貌;第三重,在 prompt 末尾加入“输出必须以{开头,以}结尾”这类硬性边界条件,或者在代码里对输出结果做二次清洗,把误加的代码块标记去掉。
有人担心加太多格式约束会让模型“变笨”,实际不会。格式约束针对的是输出层,不是推理层。而且你可以把格式约束单独抽出来放在 prompt 的尾部作为“输出协议”区块,与任务描述物理隔离,让模型在理解需求时不受格式指令干扰。这个方法我用了很久,格式错误率能从 30% 降到 2% 左右,前提是示例本身必须合法且完整。
2.4 示例引导:一个高质量示例胜过十句描述
大模型的 few-shot 能力在输出稳定性上表现得极其突出。与其费劲描述“什么叫风格幽默、什么叫结构清晰”,不如直接给一个样板。比如你想让模型生成短视频脚本,描述半天不如扔给它一条:“开头 3 秒抛出冲突,中间用 2 个转折带出产品,结尾一句点题。”模型看到的是一个具体的样稿,它会在生成时优先匹配这个样稿的句式结构和内容密度。
但示例不是随便给的。我见过有人给了一个“完美示例”后,模型反而每轮都输出几乎雷同的内容,丧失多样性。这是示例的“锚定过强”问题。解决办法是给两到三个风格相同但内容不同的示例,让模型学到的是“这类任务应该长什么样”,而不是“这一个具体的内容”。示例数量我一般控制在 1~3 个,太少学不到规律,太多会限制创造力和上下文窗口。
还有一个细节:示例最好包含一步“错误对比”。比如在 prompt 里写“示例输出如下(推荐):…;反例输出如下(避免):…”,这样模型不仅知道要做什么,还知道不要做什么。这种正反示例结合的方式,比我只用正面示例的错误率低了大概 40%。注意反例不要写得太离谱,只需要展示典型错误就可以,否则模型会被误导到奇怪的方向。
2.5 否定转正面:把“不要做”换成“要做”
大模型对否定指令的遵守能力远弱于肯定指令。你写“不要提到价格”,它偏偏在结尾加一句“价格优惠请私信”;你写“不要使用专业术语”,它还是冒出一堆“赋能、抓手、闭环”。原因可能是模型在训练时,否定表达和对应概念经常出现在相邻文本里,导致模型把“不要X”也当成了某种关联信号。
我总结了一个简单替换规则:把你想要的正面行为写明确,把不想要的行为写成反例放进示例区。比如“不要使用专业术语”改成“使用日常口语表达”,再把一句附带了专业术语的反例放在示例里。这样模型获得的是正向的模仿目标,而不是一个需要自我抑制的禁区。
另外,如果你必须使用否定表达,尽量放在 prompt 的末尾,并且加上“特别注意”的字样。比如“特别注意:最终输出中禁止出现任何数字”。我的实测结果是,把否定词从“不要”改成“禁止”,模型的遵守率会提升一些,因为“禁止”是更强烈的边界信号。但这也并非绝对,不同模型对否定词敏感度不同,最好在本机快速跑几次对照再定。
2.6 上下文裁剪:给 prompt 减负,给模型留足注意力
很多不稳定问题出在 prompt 过长,模型注意力被无关信息稀释。比如你要生成一份周报,却在 prompt 里贴了一大段公司背景、团队文化、历史项目介绍,模型反而抓不到“本周三发生了什么”这个重点。
我在实践中发现,prompt 中的有效指令密度存在一个“最佳窗口”。太短则缺乏上下文,太长则关键信息被淹没。一个健康的 prompt 结构是:开场角色——核心任务——输入资料——输出要求——示例——边界条件——自检要求。其中“输入资料”部分尽量只保留与任务直接相关的片段,无关背景全部删除。如果资料过长,可以先做一轮摘要再放进 prompt。
对于上下文窗口有限的模型,还可以把“输出要求”和“示例”放在资料之前,让模型优先吸收任务指令,再读资料。这也是所谓的“指令前置”技巧。我实际对比过,同样内容,任务描述放在 prompt 最前面的格式稳定性,明显好于把资料堆在前面再写任务。模型真的会“先入为主”,先看到什么它就更重视什么。
2.7 自问自答:强制模型先理清思路再输出
有一种不稳定叫“深度不稳定”:模型要么泛泛而谈,要么答非所问。解决办法之一是让模型在正式输出前,先用内部推理梳理一遍问题。你可以把 prompt 改写成“在你给出最终回答之前,先用不超过 50 字列出你对问题的理解的关键点”,这样可以强迫模型进行问题拆解,效果显著。
这种方法类似于让模型进行“思考草稿”。但注意,思考过程如果直接输出,会占用大量 token,而且很多业务场景不需要暴露推理过程。我通常用两种方式处理:一是让模型把思考过程写在一个看不见的地方,如果接口支持思维链,就利用思维链能力;二是在 prompt 里明确写“先在内部思考,再直接输出最终答案,不要输出思考过程”。后一种对稳定性的提升也很明显,因为模型确实经历了一个推理过程,只是没展示罢了。
自问自答的另一个变体是“把问题本身再问一遍”。比如你的原始需求是“这篇新闻讲了什么”,可以扩展成“1. 这篇新闻涉及了哪些核心事实;2. 这些事实之间的关系是什么;3. 从整体上来看,它在回应什么问题”。这样模型会更有条理地组织信息,而不是随便挑几个句子复述。用在资讯摘要、数据分析类任务里尤其有效。
2.8 自检清单:让模型自己给自己挑毛病
最后一种技巧是给自己的 prompt 加一道“质量验收关卡”。在 prompt 末尾要求模型在输出完成后进行自检,如果不符合要求就要修正。比如写“输出完毕后,请对照以下要求检查:1. 是否包含所有关键要点;2. 是否遵守了格式规范;3. 是否偏离了主题?如果有问题,请直接重新生成。”
自检机制的本质是让模型进入一个“批判性回顾”的状态,不是一次生成完就结束。实测中,加上自检后的输出准确率能提升 10%~20%,尤其在多要点任务中,模型漏项的概率会下降。缺点是会增加生成 token 和响应时间,所以不建议用在低延迟场景。
我通常只在以下两类场景中使用自检:一类是最终结果直接面向用户,质量要求高;另一类是模型输出会被后续程序解析,格式和内容都必须可靠。至于日常聊天或创意发散,完全不必要加自检,反而会让回复显得生硬像是“自己跟自己过不去”。自检清单里的项目要具体,不能只写“请确保回答准确”,要写出可检查的指标,模型才知道拿什么当尺子。
3. 实操过程与核心环节实现
前面讲了每种技巧的原理和使用场景,这一部分我拿一个真实项目来演示如何把 8 个技巧组合进一条高稳定性的 prompt。模拟项目 X 的背景是做一个“用户反馈分类与摘要生成”小工具,输入是一段用户反馈文本,要求输出三个字段:分类、摘要、建议优先级。这个任务非常典型,恰好能覆盖格式不稳定、内容不准确、分类漂移等常见问题。
刚开始第一版 prompt 很简单:“请分析以下用户反馈,输出分类、摘要和建议优先级。”运行 50 条数据,结果惨不忍睹:分类有“差评”“不满意”“问题”等混用,摘要有时是一句话,有时是三段话,优先级一会儿写“高”,一会儿写“紧急”。后来我按 8 种技巧逐项修订,最终 prompt 长这样:
你是一名在线客服工单分类助理。你的职责是将用户反馈转换为结构化工单信息。 请对下面的用户反馈内容执行以下步骤: 第一步:判断反馈所属类别,类别只能是“功能故障、性能问题、使用困惑、其他问题”中的一种。 第二步:用不超过 30 字概括用户核心问题,要求不遗漏关键信息。 第三步:根据问题严重程度给出优先级,仅限“低、中、高”,判断依据包括影响范围、是否阻碍主要任务、是否有替代方案。 输出格式为 JSON,字段如下: { "category": "分类", "summary": "摘要", "priority": "优先级" } 示例: 用户反馈:每次点保存都转圈十几秒,然后就报错。 输出: { "category": "性能问题", "summary": "保存操作耗时长,随后报错", "priority": "高" } 特别注意:不要输出 JSON 以外的任何文字。不要添加注释。category 必须是四个选项之一。把这个 prompt 拆开看,就是标准的 8 技巧合一:角色锚定用了“工单分类助理”;任务拆分用了“第一步、第二步、第三步”;格式约束用了“输出格式为 JSON,字段如下”;示例引导用了正例;否定转正面用了“不要输出 JSON 以外的任何文字”;上下文裁剪保证了 prompt 里只有用户反馈,没有多余背景;自问自答通过“第一步、第二步、第三步”强迫模型按顺序推理;自检清单体现在“category 必须是四个选项之一”这类校验规则上。
我们做了 100 条真实反馈的测试,用修订后的 prompt 跑一遍,格式正确率 98%,分类准确率 91%,摘要基本都能控制在 30 字左右。对比第一版 prompt,格式错误率从 27% 降到了 2%,分类漂移几乎消失。最大的收益不是准确率,而是“可预期性”——我知道模型大概率会以什么结构、什么风格输出,下游程序解析时不用写一堆容错逻辑。
在实际运行时,我还会在程序里做两层保险。第一层是规则兜底:如果模型返回的不是合法 JSON,就自动重试一次,重试 prompt 里加一句“上一次输出不符合 JSON 格式,请检查后重新输出”。第二层是校验兜底:即使返回了 JSON,也要检查 category 是否在预设集合里,不在就映射为“其他问题”。这样即使模型偶尔抽风,整体流程依然稳健。
下面是本次测试中统计到的输出形态分布:
| 输出形态 | 第一版比例 | 优化后比例 |
|---|---|---|
| 合法 JSON | 73% | 98% |
| 含代码块标记的 JSON | 18% | 1% |
| 带解释文字的 JSON | 7% | 1% |
| 完全非 JSON | 2% | 0% |
要把这套组合拳落到自己的项目里,我的建议是先在本地构造一个“prompt 实验室”:准备一组固定测试用例,每次改完 prompt 后批量跑一遍,记录格式正确率、内容命中率和执行耗时。不要凭一两条输出的感觉判断优化方向,必须看统计结果。我在日常工作中就维护着 20 条左右的测试集,任何新 prompt 上线前都会过一遍,效果稳定后再接入正式流程。
4. 常见问题与排查技巧实录
这一部分把我自己和其他开发者在 prompt 优化过程中遇到的高频问题整理成速查表,每个问题都附上排查思路和实际解决方案。
问题一:加了角色设定后,输出变得更啰嗦
很多人发现“你是一名专家”之后,模型每句话都像在发表长篇大论。原因在于角色设定激活了模型的“专家模式”,它会下意识地补充大量背景知识。解决办法是在角色描述里同时规定语言密度,例如加上“回答要精炼,控制在 100 字以内”之类的约束。如果你用的模型支持系统提示,也可以把角色写在系统提示里,把任务写在用户消息里,让角色更稳定地作用于整体风格,而不是每次都跟着用户输入波动。
问题二:明明给了示例,模型还是按自己的思路输出
一个常见原因是示例的“位置”不对。模型对 prompt 不同位置的注意力不同,示例如果放在很靠前的位置,可能会被理解为背景而不是输出模板。我建议把示例紧贴在输出格式要求之后,不要在示例前面塞大段资料。另一个原因是示例数量过少,尤其是对于需要多种可能性的任务,一个示例可能只展示了一种形态,模型会误以为只能这么写。可以尝试给两个差异明显的示例。
问题三:否定指令失效,模型仍然触碰敏感词或禁忌内容
单一否定约束往往不够,因为模型会把“不要”后面的词也作为语义联想的一部分。我的处理方法是三层防护:第一层,在 prompt 里明确写出允许的正面替换词;第二层,在最后加入一条“如果输出中出现了禁用词,请用替换词重新生成”;第三层,如果你在写程序,一定在后端做一次敏感词拦截,把 prompt 无法覆盖的情况用规则兜底。不要信任大模型在否定指令上的稳定性,规则过滤永远必要。
问题四:输出有时准确但格式不稳定,已经加了格式约束
建议检查你的示例是否符合“真实输出”的预期。如果你在 prompt 里手写了一个 JSON 示例,但这个示例本身缩进、字段顺序和你的解析代码不一致,模型会模仿你给出的“坏习惯”。最好用代码生成一个合法的示例,并且把示例里的字段顺序定义得和下游解析逻辑完全一致。还有一个小技巧是,在 prompt 最后写“严格按下述 JSON 结构进行输出,字段顺序不得调整”,这能在一定程度上抑制模型自作主张增删字段。
问题五:同一个 prompt 在不同时间跑结果差异很大
排除模型版本更新的影响后,最可疑的变量是 Temperature 等采样参数。如果你追求稳定性,把 temperature 调到 0 或者接近 0 是最直接的手段。但要注意,即使 temperature 为 0,部分模型因为并行解码或随机种子问题仍然会有输出波动,这时尽量使用模型服务商提供的固定随机种子参数,如果没有,就只能靠 prompt 本身的约束来收窄输出空间。
问题六:想让模型输出多个备选方案,但要求高质量
有人会问“既要多样性又要稳定性,是不是矛盾?” 处理方法是把这两个需求拆到不同 prompt 或不同轮次:第一轮跑稳定模式,得到标准答案;第二轮基于标准答案要求模型做“变体改写”,此时把 temperature 调高,增加多样性。我就是这样在两轮之间切换参数,既保证主答案可靠,又能拿到多个创意方向。
下面是我整理的两个实用小工具类技巧,属于代码层面的辅助,也是我在多次项目里沉淀出来的“防呆设计”。
第一个是“自动重试模板”:系统判断输出不符合预期时,把错误信息拼接到原 prompt 后面重新请求。例如原 prompt 是“输出 JSON”,失败后新 prompt 为“你上次的输出不是合法 JSON:{model_output},请重新输出一个合法 JSON,不要包含任何其他内容”。这比让用户重新触发一遍请求要高效得多。
第二个是“固定结尾校验词”:在 prompt 末尾强制要求输出一个特定前缀或后缀,比如“结束标记:END”。这样即使输出内容出现异常,程序也能通过查找结束标记截取有效部分。这种方式牺牲了少量自然性,但换来了解析的绝对可靠。对于需要程序化使用模型输出的场景,特别推荐试试。
5. 进阶组合:从单条 prompt 走向 prompt 工作流
如果一条 prompt 已经优化得足够好,但面对复杂任务仍然不稳定,这时候要考虑的不是再继续堆 prompt 内容,而是把任务拆成多条 prompt 组合执行,也就是常说的“prompt 工作流”。
我举个例子。假设需要生成一份竞品分析报告,直接一条 prompt 从零生成,输出质量和风格通常很难控制。但如果你拆成三条 prompt:第一条负责梳理竞品列表;第二条针对每个竞品生成优势劣势分析;第三条把所有内容整合成报告格式。每一步的输入输出都很简单,模型的注意力不会被“多跳推理”消耗,稳定性自然提升。
这种工作流方式还有一个额外好处:可观测性。单条 prompt 出错了很难定位是哪一段逻辑导致的,拆开后每一步的中间结果都能能检查,问题定位到具体环节,重跑的成本也低。我在维护一些长期迭代的模型应用时,已经全部转向“小 prompt + 工作流编排”的模式,不再维护超大 prompt。
关于工作流中的 prompt 复用,我习惯把每个环节的固定要求写成模板片段,通过变量注入具体内容。例如,摘要环节的固定模板是“将以下文本压缩为不超过 30 字的摘要,保留核心实体与动作:{input_text}”。其他环节类似。这样既保证统一风格,又方便修改其中某一个环节而不会影响整体。
需要提醒的是,工作流会放大上游错误。如果第一步输出的分类就是错的,后面所有摘要和优先级都会跟着错。所以我在每个工作流环节里都加了“输出校验”子环节,比如分类字段必须限定在预设集合内,摘要不能包含黑名单词。靠 prompt 做一部分约束,靠代码做另一部分校验,两层叠加才能确保链路长期稳定。
6. 我在实际项目中的几个体会
做 prompt 优化久了,你会发现真正难的不是模型能力,而是你对“任务边界”的理解。很多人写不好 prompt,是因为根本没想清楚自己需要模型输出什么。先画好输入输出的边界,再去选技巧,会比盲目套用模板有效得多。一个连字段类型都没定义清楚的任务,加再多角色和示例也一样不稳定。
关于示例的作用,我再补充一个体会:示例是模型行为的“价格锚点”,而不是教学素材。你给什么示例,模型就会往那个形态趋近。所以示例不一定要最完美,一定要最标准。标准意味着可重复、可解析、可预期。如果你想追求偶尔惊艳,可以在稳定版 prompt 基础上,第二天再单独做一个“创意版” prompt 来跑。
对于“上下文裁剪”这个技巧,我还想强调:不是所有资料都要塞进 prompt。你要培养的信息筛选原则是——模型完成当前任务需要哪些必要信息?什么是无关信息?通常只需要问题本身和与问题直接相关的背景,其余全部省略。过多的上下文细节,很容易让模型错误地认为这些细节是输出的一部分,从而出现跑题。
自问自答和自检清单这两个技巧,我一般只会选一个用。它们都增加推理开销,同时使用会让输出变得僵硬。在实时性要求高的场景,优先用自问自答让推理更准确;在离线或异步处理场景,用自检清单做质量兜底。两者的共同前提是,你的 prompt 已经明确交代了任务边界,否则自我问询和自我检查都会因为目标模糊而失效。
最后分享一个我自己常用的“prompt 草稿模板”,它是这 8 种技巧的浓缩版,可以直接当成起点来用:
你是{角色}。你的任务是{具体任务}。 执行步骤: 1. {第一步} 2. {第二步} 3. {第三步} 输入数据: {变量} 输出格式要求: {格式描述} 示例: {正例 + 反例} 特别注意: {否定边界或自检提示}每次写新 prompt 时,我先把模板填好,再逐项检查是否包含角色锚定、任务拆分、格式约束、示例引导、否定转正面、上下文裁剪、自问自答、自检清单这些元素。缺哪一项就补哪一项,但也不要为了凑齐而硬加。稳定是一个工程问题,不是文字游戏。希望这些经验能帮你在调试大模型时少走一些弯路。