输出听着精致但不可执行:原因 + 对症修复

AI 给的几段建议读着像顾问 deck——没文件路径、没命令、没要查的配置值。本文讲怎么用 schema(含 API 层 structured outputs)强制 AI 交出可执行交付物,而不是靠加形容词。

你让它帮你调试一次部署。模型回了四段精致 prose,讲”先考虑环境配置”、“调查部署流水线”、“复盘相关日志”。没文件路径、没具体命令、没要查的配置值。读起来像顾问 deck,不是修复。

最快修复: 换动词,明确要工件。把 "对发布修复给点建议" 换成 "产出一份编号修复方案。每一步必须含:一条代码块里的 shell 命令、一个文件路径、一行预期结果。给不出具体命令时写 INSUFFICIENT_INFO 并说明你需要什么数据。" 光这一改,大多数精致 prose 就会变成 runbook。如果你是在调 API、需要硬保证,那就别靠 prompt,直接用原生 structured outputs(约束解码),让模型在该填 command 字段的位置物理上吐不出 prose——见 Step 2。

光精致没工件就是装饰:它满足了”有用回答”的形态,却没给任何人能动手的抓手。模型不是不帮忙,是太礼貌。训练让 chat 模型在开放任务上走”顾问腔”、爱 hedge,而这种腔调里工件本来就稀少。截至 2026 年 6 月这点已被反复记录:对 Claude Opus 4.7 的独立评测都指出它过度 hedge、爱加无谓免责声明;GPT-5.5 则偏另一头,有时会断言一个它没真正验证过的步骤。两种默认都不是 runbook。要 runbook,你得要它的形态,而不是它的语气。

你属于哪一类?

你输出里的症状可能原因跳到
像”你可以考虑复盘一下日志”这种 proseprompt 要建议,不要工件Step 1
有步骤,但没命令/路径/数字没要求工件Step 2
输出回声”你也许可以考虑……”软动词从 prompt 漏进来了Step 3
步骤很泛,套到任何项目都行没给示例 + 输入太泛Step 4 和 6
基本每隔一句就有”可能""也许""取决于”开放任务上的 RLHF hedgeStep 3

常见原因

1. Prompt 要建议,不要工件

“我该怎么思考 X”得到思考框架。“产出 X”得到 X。动词决定你拿到的是讨论还是交付物。

如何判断: 你的动词是”建议”、“解释怎么”、“讨论”、“考虑”。

2. 没要求工件

你没说”至少 1 个文件路径、1 个命令、1 个数字”,模型就略掉,因为 prose 更便宜、读着更像在思考。

如何判断: 你的 prompt 没有工件清单。

3. 软动词从 prompt 漏到输出里

你 prompt 说”考虑是否……”,模型就回声”你也许可以考虑……”。软动词会传染。

如何判断: prompt 含”考虑”、“想想”、“探索”、“看一下”。

4. 没给可执行输出示例

你描述了”可执行”但没展示。模型走训练分布的”可执行”平均态,大多还是 prose。

如何判断: prompt 描述了形态,却没展示一个实例。

5. 开放任务上的 RLHF 礼貌与 hedge

现代 chat 模型在开放问题上打太极避免出错。打太极把工件藏在”可能”、“也许”、“取决于”后面。这跟 Opus 4.7 这类模型爱加免责声明是同一个倾向;解法是明确禁掉 hedge 词(Step 3)。

如何判断: 基本每隔一句就有一个 hedge 词。

动手前先确认

  • 列出有用答案该含哪些工件:文件路径、命令、数字、版本号、代码片段、schema 片段、命名工具。
  • 保存精致输出,好跟可执行版本做 diff。
  • 想清楚谁来执行、需要什么才能动手。
  • 规划一个把工件作为字段强制的 schema 或模板。
  • 标出当前 prompt 里要替换的软动词。

需要收集的信息

  • 当前 prompt。
  • 不可执行的那份精致输出。
  • 可执行版本该含的工件清单。
  • 输出的下游消费者(同事、脚本、CI 任务)。
  • 用的模型 + 任何 system prompt。

最短修复路径

Step 1:把”建议”换成”产出”

差:  "对发布修复给点建议。"
好:  "产出 5 步修复,编号列表。每步必须含:
       - 一条要运行的命令(代码块)、
       - 一个要查或改的文件路径、
       - 预期结果(1 行)。"

“产出”这个动词加上工件清单,逼出具体性。

Step 2:用 schema 强制工件(并在 API 层落地)

在对话里,把 schema 贴进去,让模型逐字段填:

输出 schema:
[
  {
    "step": <int>,
    "command": "<准确 shell 命令>",
    "file": "<绝对或相对路径>",
    "expected_output": "<一行字符串>"
  }
]

Schema 字段不能填 prose。模型没有具体的,就只能写 UNKNOWN

如果你调 API,别只靠 prompt。截至 2026 年 6 月,两家主要厂商都已经提供原生 structured outputs:把你的 JSON Schema 编译成语法、约束解码,模型在生成时根本吐不出会破坏 schema 的 token:

  • OpenAI(GPT-5.5):传 response_formattype: "json_schema"strict: true(在 Responses API 里这个字段叫 text.format)。开 strict: true 后,每个属性都要列进 required,每个对象都要 additionalProperties: false;可选字段用带 null 类型的 anyOf 标注。见 OpenAI structured-outputs 文档
  • Anthropic(Sonnet 4.6 / Opus 4.7):用 output_format 参数并发 anthropic-beta: structured-outputs-2025-11-13 头;或者在工具定义里设 "strict": true 并用 tool_choice 强制调用。见 Anthropic structured-outputs 文档

约束解码就是”请返回 JSON”(指望)和”这个字段只能装一条命令”(保证)之间的区别。一个 command 字符串字段没法被塞进”你可以考虑”。

Step 3:禁软动词

禁用:"考虑"、"也许可以"、"你或许"、"可能"、"探索"。
给不出具体下一步时写 "INSUFFICIENT_INFO"
并询问需要什么具体数据。

禁掉 hedge 逼模型要么提交要么升级。配合 Step 2 的 UNKNOWN 字段,模型就有一个合法的”我不知道”出口,而不必拿 prose 来凑。

Step 4:给具体示例

像这样:
1. 运行 `vercel logs --since=10m --level=error` 查看最近报错。
   文件:vercel.json(看 buildCommand)
   预期:日志里有 "Error: env STRIPE_KEY missing"

不要这样:
1. 可以考虑复盘部署日志,看看有没有
   和问题相关的异常。

对比让形态毫不含糊。一个真实示例,胜过三句”描述这个示例”的话。

Step 5:让模型自审

末尾加:

写完后数每步的工件:
- 每步是否恰好 1 命令、1 文件、1 预期? 是/否
- 全文工件总数:<数>
- 5 步输出全文工件少于 15 个时,重写以加具体性。

工件计数是机械活,模型做机械检查很稳。

Step 6:用真实输入数据

prompt 泛(“帮我调 bug”),输出就泛。粘真实报错、真实配置、真实日志行。具体输入拉具体输出。这一条比任何措辞技巧都重要:没有具体信息,模型只能返回训练平均态,也就是 prose。

怎么确认已经修好

  • 输出每个逻辑单元(每步、每条 bullet、每节)有 3 个以上工件。
  • 同事读完能直接动手,不需要追问。
  • 软动词(考虑、也许、可能)出现 0 次。
  • 同 prompt + 同输入,多次输出的工件密度相近。
  • 输出读起来像 runbook,不像 memo。

常见问题

我都要它具体点了,为什么还在 hedge?

Hedge 是一种默认腔调,不是内容选择,所以”请具体点”基本盖不住它。你得把 hedge 的空间也拿掉:一个叫 command 的 JSON 字段,没地方塞”你也许可以”。用 Step 2 的 schema;调 API 时用原生 structured outputs,让约束在解码时强制生效,而不是在 prose 里请求。

换个更强的模型能自己解决吗?

部分能。截至 2026 年 6 月,推理档(picker 里的 “Thinking” / “Pro” 选项)产出的步骤比 instant 档具体;约束解码模式在厂商基准里把 schema 合规率拉到约 99%。但模型选择替代不了工件要求。最干净的结果来自”强模型 + schema”两者一起,而不是二选一。

什么才算”工件”?

任何读者不用再解读就能复制、就能动手的东西:一条准确的 shell 命令、一个文件路径、一个配置键和它的值、一个版本号、一段代码、一个精确的报错字符串、一个命名工具或菜单路径。“检查一下你的设置”不是工件;“在 vercel.json 里设 maxDuration: 60”是工件。

模型写了 INSUFFICIENT_INFO,是 prompt 失败了吗?

不,那是 prompt 在起作用。它说明就你粘的这些输入而言,任务确实没有具体抓手。补上缺的输入(真实报错、真实配置)再跑一遍。一个承认自己缺数据的模型,比一个编出自信但错误命令的模型有用得多。

不碰 API 能不能强制这套?

能。在对话里把 schema 贴进 prompt,再加上 Step 5 的自审。你失去了硬解码保证,但”schema + 自审”这套组合本身就能去掉大部分 prose 注水。原生 structured outputs 留给重复或自动化任务——那种”格式一错就把下游脚本搞崩”的场景。

如果还是没修好

  1. 就你的输入而言,任务可能真的没有具体抓手——多粘输入数据。
  2. 把模型切到推理档(“Thinking” 或 “Pro”),它在开放任务上比 instant 档 hedge 少。
  3. 拆成多步工作流:第一个 prompt 抽事实,第二个从事实产出行动方案。
  4. 重复任务在 API 层用原生 structured outputs 落一个 JSON Schema 行动方案模板(Step 2)。

预防建议

  • 默认:每个”建议型” prompt 都写明要产出的工件。
  • 每个任务类型维护一份”可执行输出”清单(发布修复、code review、PRD)。
  • 没工件的输出当草稿,不当交付。
  • 审已接受的输出:数工件密度;密度低,说明 prompt 该收紧了。
  • 默认动词从”建议/讨论/考虑”换成”产出/列出/写”。
  • 团队工作流商定最低工件密度(如”每步必须含一条命令”)。

相关阅读

标签: #排查 #Prompt #Prompt 质量 #回答太泛