提示词工程这几个字,差不多是这两年大模型语境里被讨论最多、也被误解最多的概念之一。很多人把它当成“会说话的技术”,觉得只要问得礼貌一点、多套几个万能模板就能解决问题。但真正在大模型落地的项目里摸爬滚打过就会明白——Prompt Engineering 的本质是“面向大模型写源码”,提示词是程序,模型只是执行器,你的思考质量会直接编译成输出质量。
这篇东西我会从一次接近真实的业务需求出发,一步步展示如何把零散的对话式提问,变成一段结构完整、输出稳定、可复用可评审的“文字代码”。适合正在调大模型接口的开发者、需要批量处理文本的内容运营、做知识库问答的技术负责人,以及所有被模型“一本正经地胡说八道”折磨过的人。看完你能带走一套可以直接照抄的提示词结构、一套排查思路,还有几个我用真金白银换来的避坑经验。
1. 先看本质:Prompt Engineering 到底解决什么问题
1.1 语言当代码写,思维方式先要切换
最开始接触大模型时,我和大多数人一样,把它当成“更聪明的搜索引擎”。需要什么就直接打字问,模型答得不对,就再补一句“不对,重来”。这种交互方式在个人尝鲜时没有任何问题,但一旦把模型接入业务流程,比如让它每天自动整理几十份销售会议纪要、把非结构化的客户反馈转成固定格式的报表,问题就全暴露出来了——今天给的是表格,明天给的是纯文本,后天它在表格里多塞了一列根本不存在的数据。
回过头去看,根子在于我把“提问”当成了“编程”。传统编程是要把每一步逻辑写清楚,变量、分支、循环、输出格式都要定义好。而大模型的提示词本质上也是一套逻辑指令,只是它用自然语言承载。你把需求说得像聊天,模型就会像聊天一样自由发挥;你把需求写得像需求文档,模型才可能交出需求文档级别的结果。
我在调试某个内部知识库项目时,对这个转变体会特别深。最开始大家写的提示词基本是:“帮我总结这篇文档。”后来我把提示词改成“你是一名知识库编辑,请严格按照以下结构输出:核心结论、支持依据、存疑点、待办事项。输入文档用XML标签包裹……”——输出质量立刻有了肉眼可见的提升。语言变成编程语言的前提,是你愿意用编程的严谨去对待那段文字。
1.2 提示词工程要拿下的三个目标:稳定、可控、可维护
如果只说一句话来概括提示词工程的目标,我认为是:让模型行为尽可能接近一个“可预测的执行器”。
稳定是第一位的。同样的输入,今天跑和明天跑,结果不能相差十万八千里。模型本身有随机性,但通过结构性约束,比如给出明确的分步指令、锁死输出格式、提供锚定示例,可以把随机波动压到业务可接受的范围。我之前帮某团队做客服工单自动分类,一开始准确率波动超过十几个百分点,后来把“判断标准”逐条写进提示词,并在最后要求“必须优先输出分类编号”,波动很快就降下来了。
可控紧随其后。你需要让模型清楚边界:哪些能做、哪些绝对不能做、遇到不确定的输入怎么办。比如做合同关键信息抽取时,我会明确写“不要根据常识补全缺失字段,信息不足请输出'未提供',并在备注中说明”。没有这句兜底约束,模型就会为了“看起来完整”而去编造合同编号、编造签约日期,这在实际业务里是要出事故的。
可维护性最容易被忽略。提示词写出来后,今天这个版本能用,明天需求一变,提示词怎么改、改了会不会影响其他场景?我在实践中强烈建议把提示词当作代码资产来管理——有版本号、有变更记录、有一组固定的测试输入。后面章节我会专门讲怎么建立这套机制。没有可维护性,所谓“工程化”就只是一次性的手工作坊。
2. 核心组件拆解:写提示词前必须理解的六个模块
2.1 角色设定要具体到“可行动”
“你是一位资深的文案专家”——这句话写进提示词有没有用?有用,但效果有限。因为“资深”无法操作。更好的做法是,把角色能力描述与你期望的执行方式绑定在一起。
我常用的一种写法是:“你是一名有十年经验的财务数据分析师,你的任务不是直接给结论,而是先列出你使用的分析口径和数据来源,再给出结论。”这里角色不只是“身份标签”,还附带了“工作方式”。这相当于告诉模型,它要以什么立场、按什么流程来处理任务。
还要注意一个细节:角色和目标不能互相打架。比如你让模型扮演“幽默段子手”,又要求它“严谨地输出数据结论”,这种组合会让输出风格变得非常奇怪。选定角色时要想清楚,这个角色是否有助于实现当前任务目标,而不是为了“看起来专业”而堆砌。
2.2 背景和上下文要克制,不是越多越好
很多人在提示词里塞入大量背景,觉得信息越充模型越懂。这在早期确实有一定效果,因为模型能从中提取更多线索。但背景过多会带来三个问题:一是占用上下文窗口,挤压真正重要的指令空间;二是冗余信息会干扰模型对重点的注意力;三是背景里的某些观点可能被模型当成“事实”采纳,造成误导。
我的经验是,背景信息按“模型完成本任务必须知道的最小集”来提供。如果任务依赖一篇长文档,不要直接把整篇扔进去,而是先让模型做摘要或抽取,再把摘要作为提示词的一部分。这个过程可以分步做。比如我做一个行业报告自动解读的项目时,第一步用短提示词抽取报告“核心数据、观点、口径”,第二步再基于抽出的结构化信息写解读。这样既控制了上下文长度,又提升了精准度。
2.3 任务指令要说清边界和验收标准
任务指令最常见的毛病是只写“做什么”,不写“做到什么程度算好”。比如“翻译下面这段文字”——模型不知道你要信达雅,还是只要基本意思对,也不知道是否要保留格式、是否要补充注释。
我建议在任务描述里包含四要素:输入内容、操作动作、产出形式、验收要点。一个实际案例:
输入内容:用户留言,用引号包裹。 操作动作:把留言中的问题分成“功能咨询”“故障反馈”“建议”三类。 产出形式:输出 JSON,字段为 category 和 reason,reason 不超过20个字。 验收要点:分类只能从三类中选择;无法判断时输出 category 为“其他”,并在 reason 中说明原因。有了验收要点,后续做自动测试时,就有一个明确的判断依据,而不是“感觉这次回答得不错”。
2.4 输出格式约束是工程红线
如果模型输出要被程序进一步处理,格式约束就是最重要的部分,没有之一。你要做的不是“建议”模型输出某种格式,而是“命令”模型严格遵守,并且最好给它一个格式示例。
我常用的做法是在提示词末尾放一个“输出示例”区块,用代码块或缩进标明。比如:
{ "category": "故障反馈", "reason": "用户反馈登录页面加载失败", "confidence": 0.93 }有了这个示例,模型在绝大多数情况下会照着骨架来填内容。相比纯文字描述“请输出JSON格式”,示例的约束力要强得多。
另外需要特别注意,输出的字段名要避免歧义。我见过有人让模型输出“result”字段,模型有时候给字符串,有时候给对象,解析直接报错。改成“result_text”和“result_code”这种带类型暗示的字段名后,问题就消失了。格式约束这件事,宁可冗余,不可含糊。
2.5 示例驱动:给模型“锚点”
即使你描述得再细致,总有一些东西是文字说不清的,比如语气、风格、什么程度的细节算“足够”。这时候最有效的办法是给示例。
示例可以分两种。一种是“正向示例”,展示理想输出长什么样;另一种是“负向示例”,展示哪些情况就算错误。我调试一个文本风格改写模块时,提示词里文字描述换了好几种说法,模型始终找不到感觉。后来直接给了两三个“原文→改写后”的对组,模型立刻稳定下来。
示例的位置也有讲究。放在提示词的前半部分叫“上下文铺垫”,放在后半部分叫“输出模板”。对于执行类任务,我倾向于把示例放在输出格式约束附近,让它作为格式的补充说明;对于推理类任务,示例则放在任务描述之后,作为思考方式的示范。
2.6 兜底与边界:面对“不确定”时的行为设计
很多提示词构造者忘了设计模型在边界情况下的行为。模型遇到它不知道或不确定的信息时,默认会尽力编一个答案,因为它被训练成“必须回应”。你不给它“拒绝/存疑”的出口,它就会自己造一个出口。
因此,在提示词里明确写上“哪些情况需要主动承认不知道”,非常关键。比如我做法规问答时,会写:“当你无法从提供的参考材料中找到答案时,请直接回复'未找到相关依据',并列出你检索过的小标题,不要尝试自行推断。”这一句话就把幻觉率降了非常多。
边界设计还包括:输入格式不合规时怎么办;任务被卷入无关内容时怎么办;用户要求模型做超出角色范围的事时怎么办。把这些问题提前在提示词里写清楚,比在结果里发现问题再补救要省力得多。
3. 完整实操:从混沌需求到一个能稳定复用的提示词
3.1 一个真实场景的改造全过程
我用一个不算罕见的场景演示完整的改造过程:某销售团队每周有十几份会议纪要,格式混乱、废话很多,需要转成一张包含“决策事项、负责人、截止时间、风险点”的汇总表。
最初我收到的需求描述只有一句话:“帮我把这些会议纪要整理成表格。”如果照着写,模型会给你一个“看起来还行”的表格,但字段可能每天都不一样。下面是从初版到可用的完整演化。
第一版提示词:
请把下面的会议纪要整理成表格: (这里粘贴纪要内容)结果问题很明显:字段自己发明,有的行没有截止时间,风险点要么没有要么写得像散文。我统计了几条输出,几乎找不到两个结构完全一致的表格。
第二版我开始加角色和结构约束:
你是一名销售运营助理,请把会议纪要中的信息抽取到如下字段:决策事项、负责人、截止时间、风险点。 如果原纪要没有提到某项,请填写“未提及”。 只输出 Markdown 表格。这一版好了一些,字段稳定了,但“决策事项”经常直接复制原文整段话,不够精炼;“风险点”默认填写“无”,实际上有些风险只是用了别的词表达。
第三版引入示例和进一步约束:
你是一名销售运营助理,负责把会议纪要整理为结构化管理表格。 要求如下: 1. 只基于输入内容抽取信息,不得补充原纪要中不存在的信息。 2. “决策事项”用一句话概括,不超过30个字,使用动宾结构。 3. “负责人”只保留人名,去掉职位前缀。 4. “截止时间”使用 YYYY-MM-DD 格式;如果原文是相对时间(如“下周五”),请根据会议日期推算。 5. “风险点”只有在原文中出现了明确的风险描述才算有,没有就写“未提及”,不要写“无”。 6. 只输出 Markdown 表格,不要输出任何解释。 输入会议纪要: --- (会议纪要内容) --- 输出示例: |决策事项|负责人|截止时间|风险点| |---|---|---|---| |推进华东区客户回访|张三|2025-03-14|未提及|这一版已经可以上线用了。它的核心变化在于:把输出约束从“字段名”细化到了“字段填充规则”,同时用示例锁定了表格结构。
3.2 调试流程怎么走:逐步逼近而不是一步到位
我从这个案例里总结出了一套调试节奏,分享给大家。
第一步,先跑通最小闭环。不要一开始就追求完美,用最朴素的提示词,让模型先完整完成任务。目标是把流程跑通,看看输入是否合适、输出能否被下游程序解析。很多人在这一步就卡住了,因为他们期望第一版就完美。
第二步,针对“每一条不满意的输出”找原因。模型输出有问题时,先判断是“格式问题”还是“理解问题”。格式问题优先用“输出格式约束+示例”来解决;理解问题则要回头改任务描述、补边界条件。
第三步,每改一次提示词,只改一个点。同时跑原来的测试集,对比新旧版本的表现差异。多人协作时,这个习惯特别重要——如果一次改了十个地方,结果变好了,你也不知道是哪个改动起了作用;结果变差了,也没法定位是哪句话引入的问题。
第四步,构建你的回归测试集。不必很多,十来个典型输入就够了。每次修改提示词后,全部跑一遍,确认旧场景没有被改坏。我见过太多项目因为一条新提示词优化了A场景、弄坏了B场景,最后在线上才发现。回归测试是成本最低的安全网。
3.3 参数配合:温度、最大长度、惩罚系数怎么配
提示词不是唯一的变量,模型参数同样会影响最终效果。有些参数层面的问题,靠改提示词是解决不了的。
温度参数(temperature)控制随机性。数值越低,输出越保守、越稳定,适合分类、抽取、格式化这类任务,我常用0到0.3。数值越高,输出越发散、越有创造性,适合头脑风暴、创意写作,这类场景可以用0.7以上。如果你碰到同一个输入偶尔出现一个离谱答案,第一反应应该是降低温度,而不是加一大堆“不要乱说”的提示词。
最大输出长度(max_tokens)决定模型最多能输出多少个 token。很多人不设置这个参数,结果生成长文本时中途截断,误以为“模型能力不行”。做结构化输出时,把最大长度设置成略大于预期输出,可以有效防止模型“啰嗦”。反过来,如果输出总是超出预期,也可以通过这个参数倒逼模型精简。
频率惩罚和存在惩罚参数,用于抑制重复。当模型开始复读某些短语或钻牛角尖时,适当提高“频率惩罚”会比你在提示词里写五次“不要重复”更管用。另外,这类参数和温度参数是配合使用的,如果你把温度调到很低,那输出本来就偏保守,惩罚参数的作用就不明显了。
4. 体系化协作:单点提示词之外的工程化问题
4.1 多人协作时,提示词也是需要评审的代码
当提示词从个人手里传到团队里,事情就变了。如果你的同事接手你的提示词,他改了一句话,然后整条提示词失效了,而你不在场,这个项目就陷入困境。
所以在团队项目里,我给提示词文件加了头部注释,包含用途、适用范围、依赖的模型和参数、已知限制、最近修改人。我会把提示词放在单独的文本文件或配置项里,而不是硬编码在业务代码中间。下游程序把提示词作为模板加载。这样一来,修改提示词不需要动代码逻辑,也不会出现“改了一行字符串导致整个服务要重新发布”的情况。
评审也很重要。提示词的评审和代码评审类似,重点关注:有没有编造信息的风险、输出格式是否严格、示例是否和约束冲突。有一次同事加了一个新示例,内容是“把负责人写成'张经理'”,结果后续所有输出都自动带上“经理”后缀,和“只保留人名”的约束冲突。这类问题不经过评审很难发现。
4.2 拆任务比堆大提示词更可靠
面对复杂任务时,有人喜欢写一个超长的提示词,把所有要求都塞进去。这在上下文窗口足够时好像可以,但实际效果往往不稳定。模型对长提示词不同部分的“注意力”会分散,后面的指令可能弱化前面的约束。
我现在的习惯是:把复杂任务拆成多个小步骤,每步用一个短小精干的提示词,前一步的输出作为后一步的输入。以“长文生成行业摘要”为例,我不会让模型一口气读完3000字直接给摘要,而是先抽关键数据和观点,再基于数据写摘要,最后压缩语言。每一阶段都更轻、更稳定,出错了也容易定位。
这种“串行提示词”的思路其实很像传统软件工程里的函数拆分。每个提示词只负责一件事,输入输出都有明确的“接口约定”。大批量处理时,中间结果落盘保存,还可以在任意步骤做人工抽查,不用从头来过。
4.3 与外部系统配合的边界问题
模型往往不是单独工作,而是嵌在流程里:前面有业务系统传入数据,后面有程序解析输出。这时,提示词设计要和“上下游”保持一致。
下游解析端最怕模型输出意外的内容。我的做法是,在系统层面做“输出校验”,而不仅仅依赖提示词。例如,要求输出JSON时,程序里要同时准备一个“解析失败兜底逻辑”——捕获到非JSON内容时,重试一次或进入人工处理队列。只靠提示词约束,无法100%保证格式稳定,程序端一定要有容错。这属于工程判断的范畴,凡是线上要跑的流程,都要做最坏的打算。
上游数据同样要提前清洗。如果输入里带有多余的全角引号、乱码、超长段落,模型再聪明也会被带偏。让提示词去做“清理数据”的活,成本太高。正确的做法是:上游程序先把数据转成规范格式,提示词只负责加工,不负责修复脏数据。
4.4 幻觉防控:区分“整理”与“创造”
幻觉是大家对大模型最头疼的问题之一。幻觉产生的场景很多,但提示词层面有办法显著降低,虽不能根除,但可以控制。
方法是把“任务目标”从“生成答案”改成“提取和整理给定材料中的信息”。我经常写这一句:“你的回答只能基于输入内容中的信息,不得加入你的背景知识;如果输入内容不足以回答,请明说。”这句话能拦掉不少凭空编造的回复。
还要在提示词里建立“来源意识”。例如:回答一个具体数字时,必须注明出自原文哪一段;当原文存在互相矛盾的信息时,要专门列出一节“矛盾说明”,而不是擅自选择一种结论。模型是概率性的,它天然倾向于“平滑地补全”,所以你在提示词里反复给的指令,其实是帮它对抗自己的默认倾向。
5. 常见问题排查与一批避坑技巧
5.1 典型症状速查表
| 现象 | 常见原因 | 调整方向 |
|---|---|---|
| 输出格式天天变,解析报错 | 格式约束不够,示例缺失 | 加输出示例,锁字段类型,必要时用正则校验兜底 |
| 同一个输入偶尔出一个离谱结果 | 温度参数偏高 | 调低温度(0~0.3);保留一条重试逻辑 |
| 输出总是生成一半就断 | max_tokens 设置不足或示例太长 | 调大最大输出长度,缩短示例,减少冗余要求 |
| 效果今天好明天差 | 模型版本变动或参数被改 | 锁模型版本和参数,建立回归测试集 |
| “一本正经胡说八道” | 缺少来源约束 | 提示词强调“只能基于给定信息”,增加存疑出口 |
| 分类任务结果飘忽 | 类别定义不够互斥 | 为每个类别写明判定标准,加正反示例 |
| 长输出里重复表述 | 频率惩罚不足或上下文太长 | 提高频率惩罚系数,精简背景,压缩输入 |
| 加了示例后反而变差 | 示例和约束冲突 | 检查示例是否符合所有规则,逐项比对 |
表格只能定位方向,细节还要靠实际操作验证。我见过很多团队拿着一张表对号入座,改完还是不行——因为真实情况往往是“多个因素叠加”。排查时要保持耐心。
5.2 三个排查套路:最小化、对照实验、回归验证
遇到棘手问题,我有一套固定打法,分享出来供参考。
第一步,最小化复现。把提示词删到只剩角色+任务+输出格式,再跑一次。如果问题消失了,说明是某段冗余指令干扰了模型;如果问题还在,说明是核心结构或参数的问题,和那些锦上添花的细节无关。这个套路能快速把问题范围缩小一个数量级。
第二步,做对照实验。每次只改一个变量,其他全部不动。比如想验证“示例放在前面和放在后面哪个效果好”,就写两个版本,同一个输入跑五次,看输出的稳定度和准确度。切忌一次改三处,然后凭印象说“好像变好了”。
第三步,回归验证。在确认新方案有效后,把以前所有测试用例重新跑一遍。这个步骤省不了。我有一次优化了“总结类”提示词,结果让“审核类”任务的输出全部改变,因为没有做回归测试,差点带着问题上线。
5.3 容易踩的坑:我拿钱换来的教训
这里写几个比较隐蔽的坑,希望大家不要重复踩。
提示词里用“不要干什么”要注意度。过度使用否定式约束,模型反而可能出错。与其反复写“不要啰嗦”“不要解释”,不如正面写“请用一句话回答,只输出关键词”。模型对否定指令的遵从效果普遍弱于正面指令,尤其在输出长度和格式这类问题上,正面引导更有效。
分隔符要一致。如果输入内容本身包含反引号、连字符这类与分隔符相同的内容,模型就可能混淆结构。我在模板里要求输入内容统一用XML标签包裹,而标签内不再嵌套同名字段,能有效降低解析错乱。关键不是用什么符号,而是“要有统一且不被内容干扰的分隔方案”。
示例不是写得越多越好。给太多示例,模型容易陷入“模仿模式”,反而忽略了你真正要它执行的规则,特别是当示例之间存在风格或格式不一致时。我一般控制在三到五个,且示例之间差异要大,覆盖面要广。
不要把模型能力当成“理所当然”。很多提示词的问题,其实是用错了模型。比如任务需要镜面推理或者复杂数学计算,你却用了一个轻量级模型。这种情况下,再精致的提示词也只是修补匠。承认模型的能力边界,换更强模型或拆分任务,往往更高效。
最后,还有一个最容易被忽略的问题:没有定期回顾和清理旧提示词。项目跑久了,提示词文件可能积累了各种历史遗留的约束,有的已经冲突,有的过时了。我建议每隔一段时间,把线上提示词重新精简一遍,只用测试集验证它是否还能满足当前需求。这部分工作就像重构代码,短期看不出收益,但它会阻止你进入“每个需求都要另起炉灶”的泥潭。
6. 最后再分享一点个人体会
提示词工程做了这几年,我最大的感受是:这个方向并不会永远停留在“靠感觉调词”的阶段,但它也永远不会退化成“什么都不用做”。随着模型能力增强,很多琐碎的提示词技巧可能会越来越不重要,但“把需求拆清楚、把边界说明白、把格式定下来”的底层能力,在任何一代模型上都有价值。
如果你刚接触这个领域,我的建议很简单:不要沉迷于收集各种花哨的提示词模板,先把一个真实任务从头到尾调试到稳定上线。这个过程跑完,你对提示词的理解会超过看一百篇文章。如果已经有了一些实践经验,不妨给手头跑着的提示词做一次“代码体检”,砍掉冗余约束,补上边界设计,建一组回归测试。这些工作带来的收益,会比再找十个新模板大得多。