清晰的 Prompt 不是“写“出来的,是“调“出来的,多躺坑才能出好结果

清晰的 Prompt 不是“写“出来的,是“调“出来的,多躺坑才能出好结果
摘要上一篇讲了清晰比复杂重要和三个瘦身的动作。但那套方法有个隐藏前提——你已经知道自己要什么。现实里大多数时候你脑子里只有一句我想让模型帮我管库存阈值、格式、异常处理全没想清。你不是在写清晰 Prompt是在和模型来回拉扯把自己到底要什么逼出来。本文用库存补货的真实例子把四轮调试循环摊开看再盘点五个调试循环也救不了的结构性坑。预计阅读时间6 分钟目录第一轮从一个模糊需求开始第二轮补阈值看新偏差第三轮钉死格式和计算规则第四轮堵住最后一道缝异常处理被踩坑喂出来的补丁收敛而非一次性成型调试循环也救不了的五个坑跑一次才是开始上一篇我们聊了为什么清晰比复杂重要以及用三个动作把臃肿 Prompt 瘦身的办法。但那套方法论有一个隐藏的前提假设——你已经知道自己要什么只是表达得不够干净。现实远没有这么体面。大多数时候你坐在屏幕前脑子里只有一个模糊的念头“我想让模型帮我管库存”至于阈值是多少、输出什么格式、异常怎么处理你其实还没想清楚。你不是在写一个清晰的 Prompt你是在通过和模型来回拉扯把自己到底想要什么给逼出来。这个过程和写代码修 bug 没有本质区别先写一个能跑的版本运行看报错定位问题改一行再跑。下面我用一个真实的例子把清晰是怎么被一步步逼出来的全过程摊开给你看。第一轮从一个模糊需求开始起点从来不是需求文档而是一句模糊的话。我写下的第一版可能就是帮我看看这些原料库存够不够珍珠15、椰果20、芋圆8、脆波波15我明知道这不够好但还是先跑一次。这一步的目的不是要正确答案而是让模型的错误输出暴露我自己没想清楚的地方。模型果然回了一大段珍珠的库存为15从一般奶茶店的一般消耗来看这个数量偏低建议尽快补充。椰果的库存为20数量较为充足……芋圆的库存为8这个数量偏少……一看就知道三个不知道它不知道阈值是多少它不知道我要补货清单还是库存报告它不知道该用什么格式。这些不知道就是我第一版缺失的信息。我不是坐在那里苦思冥想该加什么约束而是让模型的偏差告诉我你还差什么。第二轮补阈值看新偏差模型不知道阈值我补一句对比阈值珍珠20、椰果15、芋圆10、脆波波12告诉我哪些不够。模型这次乖了输出需要补货的原料有珍珠1520、芋圆810。椰果2015和脆波波1512库存充足。阈值对了但两个新偏差冒出来它只告诉我不够没告诉我补多少输出还是一段话没法塞进程序。第三轮钉死格式和计算规则针对这两个偏差我再加两条约束只输出不够的原料。补货量 阈值 × 2 − 当前库存。以 JSON 输出字段为 material、current_stock、threshold、replenish_quantity。模型输出以下是补货清单 [{material: 珍珠, current_stock: 15, threshold: 20, replenish_quantity: 25}, {material: 芋圆, current_stock: 8, threshold: 10, replenish_quantity: 12}]几乎完美了——字段对、计算对、格式对。但开头多了一句以下是补货清单。这句引导语人看着舒服程序json.loads()解析时直接报错。第四轮堵住最后一道缝针对这个偏差加一条最小约束不要额外添加任何文字只输出 JSON 字符串。模型终于吐出纯 JSON[{material:珍珠,current_stock:15,threshold:20,replenish_quantity:25},{material:芋圆,current_stock:8,threshold:10,replenish_quantity:12}]稳定了。这时候我把这个跑通的输出拎出来固化成 Prompt 里的示例——示例不是第一步写出来的是第四轮调试完之后从正确结果里截图下来的。回头看从第一轮那句帮我看看库存够不够到第四轮的纯 JSON我加了四条约束每一条都对应一个真实出现过的偏差没有一条是以防万一凭空加上去的。这就是为什么成品的 Prompt 看起来每句话都恰到好处——因为它每句话都是被一次偏差逼出来的多余的话根本没机会存活。异常处理被踩坑喂出来的补丁还有一类东西更不可能提前设计就是异常处理。比如 Prompt 里这么一条若库存数据格式错误返回 {error: 库存数据格式错误请提供类似珍珠15、椰果20的格式}。这条规则哪来的大概率是某次测试时有人传了珍珠15个椰果20芋圆8这种带单位的乱码模型要么硬算要么胡编开发者被坑了一次才补上这条。每一条异常处理规则背后都是一次真实的事故。这也是为什么同一个 Prompt 模板在不同团队手里会越改越不一样——各自踩过的坑不同补的补丁也不同。就像同一款车的车主各自根据自己的剐蹭位置贴不同的防撞条。收敛而非一次性成型把这四轮连起来看清晰的 Prompt 是一个收敛过程的终点模糊需求 → 跑一次 → 看偏差 → 加最小必要约束 → 再跑 → 再看偏差 → 直到稳定。最后把稳定版本的约束整理成结构化的三要素角色、指令、格式补上示例和异常处理就成了你在教程里看到的那个模板。模板是结果不是起点。起点的那个跑一次才是 Prompt 工程真正开始的地方。光读模板学不会写 Prompt就像光看别人修 bug 学不会调试一样。调试循环也救不了的五个坑但有些错误不是偏差而是你在写 Prompt 时就已经埋下的结构性雷。它们的特点是哪怕你跑十轮调试循环只要没意识到根本原因怎么加约束都修不好。下面这五个是实践中出现频率最高的。坑一用否定句当约束大语言模型对否定句的理解远不如肯定句。你写不要它经常把不要后面的内容当成要执行的动作因为它顺着语义续写时注意力更容易落在名词而非否定词上。反面不要推荐全糖的奶茶。模型很可能推荐的全是全糖——因为全糖奶茶这个词被反复强化了而不要两个字在语义权重里几乎可以忽略。就像跟小孩说别想粉色大象他脑子里全是粉色大象。正面优先推荐少糖、无糖的奶茶。同样的意思把不要什么换成要什么模型就不会跑偏。这个坑在调试循环里尤其难发现因为你看到模型推荐了全糖第一反应是我明明写了不要啊然后加更强烈的否定“绝对不要推荐全糖”——结果更糟。解药只有一个把否定翻成肯定。坑二角色与任务脱节很多人把角色当装饰品堆砌写了一堆人设却和实际任务毫无关系。角色一旦与任务脱节不仅没用还会干扰模型——模型会花注意力去扮演那个角色在无关的维度上发散。反面你是一位拥有20年经验的资深营养师精通膳食搭配、微量元素代谢、临床营养学。请根据用户偏好推荐一杯奶茶。模型会忍不住从营养学角度推荐“建议选择低脂牛奶减少糖分摄入注意珍珠的热量较高……”而你要的可能只是清爽一点的果茶。角色给了它一个错误的思考框架。正面你是奶茶店店员熟悉本店所有口味。根据用户描述的偏好清爽/浓郁/香甜推荐1-2款饮品一句话说明理由。角色直接服务于任务——店员这个身份天然限定了推荐视角不需要营养学知识也不会往健康角度发散。角色不是越多越好而是越贴合任务越好。一个判断标准如果你把角色那句删掉模型的输出质量会不会下降如果不会这个角色就是多余的。坑三格式要求只说JSON不说字段输出格式不对十有八九栽在这里。你以为说了输出 JSON就够清楚但对模型来说JSON只是一种容器里面装什么字段、字段叫什么名字、值是什么类型全是空的。反面以 JSON 格式输出补货清单。模型可能给你{结果: [{原料: 珍珠, 数量: 15, 标准: 20}]}——是 JSON 没错但字段名是你没预期的中文你的程序解析material字段时直接拿到null。正面以 JSON 格式输出字段包括material原料名称字符串、current_stock当前库存整数、threshold阈值整数、replenish_quantity补货量整数。不要输出示例中不存在的字段。不仅指定了字段名还指定了类型最后一句堵住了模型自作主张加额外字段的毛病。如果模型还是不听OpenAI v1 还有一个兜底手段response_format{type: json_object}强制输出合法 JSON——但注意它只保证是合法 JSON不保证字段就是你想要的所以 Prompt 里的字段说明依然不可省。坑四Prompt 和参数打架这是最隐蔽的坑。你的 Prompt 写得再清晰只要有一个参数和它矛盾效果就会被拉低而且你很难定位问题出在参数上因为你会本能地去改 Prompt。最典型的是temperature。你在 Prompt 里写输出要稳定、一致、每次都一样但temperature设成了 0.9——模型在采样时天生带有随机性Prompt 再怎么强调稳定也压不住它。就像你一边踩油门一边喊慢一点机械结构不会听你的口号。反过来你想让模型写创意文案Prompt 里说发挥想象力多给几种风格但temperature设成 0.1它永远给你最安全的那个答案创意无从谈起。两类任务对应两档参数需要稳定、可复现的结构化输出JSON、分类、提取temperature调到0.1~0.3需要创意、发散的开放输出文案、故事、头脑风暴temperature调到0.7~1.0。Prompt 和参数必须指向同一个方向否则就是左脚踩右脚。坑五忽视模型差异同一段 Prompt 在 GPT 上跑得好好的换成国产模型通义千问、文心一言等就答非所问。这不一定是模型能力差而是不同模型对 Prompt 的阅读习惯有差异。GPT 系列对结构化标记# 角色、# 任务指令、# 输出格式这种标题式分区接受度很高能准确识别每个区块的职责。但部分国产模型对这种装饰性标题反而敏感容易把标题本身当成内容的一部分来理解导致注意力分散。破法给国产模型写 Prompt 时减少结构化标题改用更直接的自然语言句式。比如把——# 角色 你是库存监控Agent。 # 任务指令 1. 读取库存数据…… # 输出格式 以JSON输出……简化成你是库存监控Agent需要读取库存数据、对比阈值、筛选需补货的原料最后以JSON输出字段material、current_stock、threshold、replenish_quantity。一句话串完角色、动作、格式对国产模型反而更友好。遇到兼容问题第一反应不应该是这个模型不行而应该是我的 Prompt 是不是对这个模型来说太’重’了。跑一次才是开始回顾这两条线索——上一篇的三个动作教你如何精简这一篇的调试循环教你如何从零构建——你会发现它们其实是同一件事的两面精简是在已有 Prompt 上做减法调试是在空白 Prompt 上做加法而两者共同的原则都是每一条约束都必须有存在的理由。模板是别人替你跑完整个调试循环后留下的成品。你拿过来可以直接用但真正的能力不是记住模板而是会跑循环。下次面对一个新任务别急着去翻模板库先写一句最朴素的话丢给模型看它回什么。那个回什么里藏着的偏差就是你下一步该加什么的地图。