一名 PM 用英文写了一份功能规范 (feature spec)。一名工程师将其翻译成带有惯用 LLM 模式的系统提示词 (system prompt) —— 思维链 (CoT) 脚手架、输出格式强制,以及一些涵盖规范中从未提到的失败模式的避险条款。一位评估 (eval) 作者打开同一份规范,冷读一遍,并根据自己的理解编写 JSON 测试用例。三周后,这三个产物各不相同,没人能说清楚一个回归到底是提示词的 bug、规范与实现的差异,还是从第一天就写错的评估。
这就是规范翻译税 (specification translation tax)。传统软件也有这种问题 —— PRD 与代码之间、代码与测试之间的差距 —— 但编译器和类型系统缩小了这种差距。AI 功能没有这种兜底保障。提示词是系统实际阅读的文档。评估是没人签署的合同。规范是没人执行的意图描述。每一项都是将同一意图翻译成不同的媒介,如果没有双向的一致性,行为就会通过那个最容易编辑的产物泄露进来。
三个产物,三个编辑者,没有权威源
结构性问题在于所有权。提示词处于产品意图、法律解释和技术执行的交汇点 —— 现有的角色中没有一个能自然地拥有它们。PM 拥有规范,因为是他们写的。工程师拥有提示词,因为是他们发布的。评估作者 —— 有时是第三个人,有时是戴着不同帽子的同一个工程师 —— 拥有测试套件,因为是他们构建了框架。他们中没有人真正拥有这三者之间的 共识 (agreement) 。
在健康的传统系统中,规范描述意图,代码实现意图,测试验证实现。流程是单向的:规范 → 代码 → 测试。当测试失败时,你会先看代码,因为规范很少是开始调试行为的有意义的起点。审阅者通过阅读与关联工单的差异 (diff) 来发现 PR 中的规范/代码偏离。
在 LLM 功能中,关系是三角形且循环的。提示词编码了规范未指定的行为(因为避险条款在提示词工程中浮现)。评估验证了提示词并未真正承诺的行为(因为评估作者将他们对规范的理解投射到了测试用例上)。规范描述了提示词和评估都未反映的意图(因为在提示词和评估演进时,规范从未更新)。这三者都是动态文档。没有一个是权威的。当它们不一致时,没有编译器报错 —— 只有未来没人能归因的回归。
我最近交流过的一个团队描述了正是这种失败:在一次提示词编辑后,一个评估开始失败,事后分析花了三天时间,因为团队必须从头开始重新推导 预期 行为是什么 —— 规范是 18 个月前的,提示词已经吸收了打了几十个零散的补丁。修复方案不是代码更改,而是一次会议。
偏离是如何积累的
提示词比规范偏离得更快,因为它们的编辑成本更低。工程师注意到模型在下游解析器预期纯文本时返回了 markdown —— 他们在系统提示词中加入了“仅以纯文本响应”。更改发布了。规范没有提到输出格式,因为最初的 PM 没考虑到。评估没有发现这一变化,因为测试用例是在模型仍返回 markdown 时构建的,且评估在比较前对格式进行了归一化。六个月后,一名新工程师看到“仅以纯文本响应”这一行,认为它是多余的指令并将其删除。下游解析器在生产环境中崩溃。这是谁的错?
评估的偏离方向相反 —— 它们更难编辑,因此往往编码了对正确性的 旧 理解。当行为发生变化(有意的)时,评估被更新以匹配新行为,但断言通常是被放宽而不是重写 —— “回复应提到用户名”变成了“回复应与用户相关”,因为评估作者找到了让失败测试通过的快速方法。合同被无声地削弱了。规范、提示词和评估现在描述的是三种不同的东西,而评估描述的是最宽松的那种。
规范偏离最慢,因为上线后没人读。规范是在行为存在之前编写的产物。一旦功能发布,在大多数团队的工作模式中,规范的任务就完成了。PM 转向下一个功能。工程师再也不会打开它。评估作者在构建测试用例时参考过一次,之后再也没看过。规范钙化成了遗留文档,关于功能 应该 做什么的权威理解迁移成了团队内部的零散知识 —— 通常存在于发布该功能的工程师脑中,而他通常会在 18 个月内离开团队。
规范鸿沟 (The Gulf of Specification) —— 即我们希望 LLM 做什么与我们的提示词实际指示它做什么之间的差距 —— 存在于这条链条的每一步,每一次翻译都在扩大它。未详细说明的提示词迫使模型猜测意图,这导致输出不一致,进而导致评估试图编码模型碰巧做的任何事情,这便成了新的事实规范。系统会向最容易查询的产物优化,而那几乎永远不会是 PM 写的文档。
以规范作为唯一事实来源的真正要求
规范驱动开发(Spec-driven development)作为一种趋势,其诊断是正确的:规范必须是唯一事实来源,而不是代码。但仅仅移动事实来源并没有帮助,除非其他产物是从这个权威来源“生成”或“对照检查”的。如果规范存在于一份单独的文档中,以不同的频率进行编辑,且与 Prompt 和 Eval 之间没有强制的一致性,那么它只是另一种会产生漂移的翻译。
真正有效的是结构化的行为契约——这是一个单一产物,它以一种可以机械化生成 Prompt 片段和 Eval 测试用例的形式捕捉预期行为。具体来说,这看起来像是一个 YAML 或 JSON 文档,包含命名的行为,每个行为都有:自然语言描述、输入 Schema、预期输出 Schema、正例列表、反例列表(附带拒绝或升级的原因)以及一个负责人。Prompt 组装流水线读取此文档,并将行为描述拼接进系统 Prompt 中。Eval 流水线读取同一文档,并将示例转换为测试用例。当规范发生变化时,Prompt 和 Eval 随之改变——这不是因为有人记得更新它们,而是因为它们是从同一个源重新生成的。
这就是 GitHub 的 spec-kit、Kiro 和 Tessl 趋于一致的模型,尽管各有差异:规范是一个结构化产物,实现是生成的或根据它严格检查的,而 Eval 案例可以从同一个源导出。采用这种方式的阻力并非来自技术——Schema 和代码生成并不难。阻力来自于组织。PM 不想写结构化文档;他们想写叙事性的规范。工程师不想放弃在不提交规范 PR 的情况下向 Prompt 添加规避性条款的自由。Eval 作者不希望他们的固定配置(fixtures)从一个他们无法完全控制的源头重新生成。
成功落地的团队将结构化规范作为变更控制下的唯一产物。Prompt 和 Eval 是规范的“输出”,不允许手动编辑。当工程师想在 Prompt 中添加规避性条款时,他们会针对规范提交 PR。当 Eval 作者想添加测试用例时,他们也会针对规范提交 PR。规范 PR 会触发下游产物的重新生成,针对重新生成的 Prompt 运行完整的 Eval 套件,并在 PR 差异中体现出任何行为变化。PM、工程师和 Eval 作者都汇聚在同一个评审界面上,因为行为定义的地方只有一个。
漂移检测应作为 CI 检查,而非季度审计 即使有了权威规范,漂移仍会通过模型悄然渗透。Prompt 没变,规范没变,Eval 也没变。但模型的小版本更新了,默认的 Temperature 偏移了,分词器(tokenizer)对 Unicode 的归一化方式变了,输出分布也随之移动。如果没有显式的漂移监控,这会在六周后表现为用户投诉,最终追溯到大家都忘了发生过的模型更新。
必须建立的规范是将漂移检测视为 CI 检查,而非审计。具体来说:每一个涉及 Prompt、规范或模型版本的 PR 都要运行完整的 Eval 套件,并与之前的基准线比较得分,如果任何指标的退化超过配置的阈值,则阻止合并。对生产环境 Prompt 进行定期运行(每天或每周,而非每季度),可以捕捉到并非由代码变更触发的、由模型驱动的漂移。对生产流量进行采样,并根据相同的 Eval 准则进行评分,从而使线下 Eval 和线上行为保持挂钩。
工具已经存在。Promptfoo、Braintrust、Statsig、Agenta、Galileo 以及其他数十种工具都提供了某种形式的“针对 Eval 套件对每个 Prompt 版本进行评分,并在回归时报警”。阻碍因素很少是工具。阻碍因素是缺失的产物——即 Eval 套件所“对照检查”的结构化规范。没有它,Eval 就会变成它自己的事实来源,而规范与 Eval 的漂移问题会在更高一层重新出现:Eval 套件编码了规范从未授权的行为,团队针对 Eval 分数而非用户可见的正确性进行优化。
为每个行为契约指定负责人 组织上的失败在于将规范、Prompt 和 Eval 视为三个由不同人拥有的产物。解决方法是为每个“行为契约”(结构化规范中定义的单元)指定一名负责人,并让该负责人负责保持这三个产物在契约上的一致性。这不同于让某人成为“Prompt 负责人”或“Eval 负责人”。那些定义方式会滋生漂移,因为每个产物负责人都会倾向于捍卫自己的产物,而不是它们之间的共识。
行为契约负责人负责:定义行为的规范条目、实现行为的 Prompt 片段、验证行为的 Eval 案例,以及确认其奏效的生产遥测数据。当其中任何一项发生漂移时,负责人都要负责。当出现功能回归时,复盘(post-mortem)应寻找受影响行为的负责人,而不是修改 Prompt 的工程师。
这种模式自然地契合了成熟 LLM 团队的工作结构——由业务领域对齐的负责人(产品负责人、领域专家)负责每个行为的语义含义和业务意图,而 AI 平台团队负责评估方法、部署基础设施和 Prompt 组装模板。平台团队通过流程设计消除漂移的可能性(Prompt 是重新生成的,Eval 是重新生成的,一致性是被强制执行的)。行为负责人则决定行为应该是怎样的。
不付出的代价 如果团队在交付 AI 功能时没有明确的规范-提示词-评估(spec-prompt-eval)一致性,他们就在积累语义债(semantic debt)——这与传统软件在测试、代码和文档发生偏离时积累的债务类似,但有两个复合因素。首先,提示词本身也是系统读取的文档,因此提示词漂移(prompt drift)比文档字符串(docstring)漂移更危险。其次,模型是一个不断变化的目标,因此每次模型更新都是一次潜在的、未经许可的静默迁移。
当这笔债务到期时,代价就是整个功能的重写。当团队无法再回答“这个功能到底是做什么的?”时——因为规范已过时,提示词积累了成堆的补丁,而评估(eval)记录的只是提示词在一年前凑巧生成的输出——唯一的出路就是将这三者全部推倒,根据用户研究和生产追踪记录重新推导其行为。这种重写的成本比开发原始功能还要高。而付出这一代价的团队可能并不会吸取正确的教训;他们会由三个不同的负责人并行重写规范、提示词和评估,然后让漂移再次开始。
这种纪律并不光鲜。结构化行为契约。生成的提示词。生成的评估。每个契约指定负责人。CI 中的漂移检测。这些都不是什么研究突破。它们全都是乏味的基础设施,但这正是让一个能持续产生复利价值的 AI 功能与一个每 18 个月就得重做的功能之间的区别所在。这种“转换税”终究是要交的——要么通过保持产出物一致性的纪律预先支付,要么在以后通过重写来支付。
会员专享
余下内容仅对会员开放。 会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
— 完整文章,包含未公开存档的部分 — 可落地的工作框架,附带权衡与决策依据 — 新文章抢先看,先于公开发布 登录以继续阅读→ 随时取消 · 一次订阅,畅读全部