跳到主要内容

系统提示词为他人调优的备选模型

· 阅读需 12 分钟
Tian Pan
Software Engineer

你的可靠性仪表盘显示为 99.95% 。但你的支持收件箱却在诉说另一番景象。每周有那么两次,每次持续 10 到 20 分钟,极少数用户会遇到一个说话风格完全像另一家公司的产品版本。拒绝响应读起来很奇怪。一个原本总是渲染为整洁双栏卡片的结构化字段,现在变成了一个塞满了项目符号的段落。语气从“冷静的专家”变成了“热情的助手”。没有人会为此提交工单——他们只会直接关闭标签页,稍后再试。

你的供应商宕机了。故障转移生效了。延迟保持在 SLO 之下。错误预算没有变动。然而,用户在那个窗口期获得的体验,并不是你真正发布的那款产品。

大多数团队在采用多供应商架构时所持的心智模型是:系统提示词(System Prompt)是可移植的——它是一份与“能力出众的模型”这一抽象概念达成的协议,任何理解 LLM 方言的模型都能读懂。这种模型是错误的。系统提示词是一个经过调优的产物(Artifact)。它是针对特定模型的偏好、拒绝语法、格式习惯和指令遵循偏差进行调优的。当故障转移发生时,你并不是将同样的合同交给一个对等的签约方,而是将一份用主模型(Primary Model)的习语编写的合同,交给了一个阅读习惯完全不同却依然强行签字的模型。

提示词是调优后的产物,而非规范

回顾一下过去六个月对生产环境系统提示词的修改。几乎每一行都可以追溯到特定模型发生的特定事件。围绕工具清单的 XML 包装之所以存在,是因为 Claude 在有此类标签时能更干净地解析结构化输入—— <tools> 代码块的存在是因为 Anthropic 在 XML 分隔的示例上进行了训练,模型已经将这种包装内化为一种结构性提示。那句“如果用户询问价格,请委婉拒绝并引导他们访问销售页面”之所以这样表述,是因为之前的表述方式泄露了律师不希望泄露的答案。关于输出格式的那两个段落之所以在那儿,是因为模型偶尔会在代码块的代码块里返回 JSON ,而目前提示词中的表述是唯一能稳定阻止这种情况发生的。

这些修改没有一个是随意的。每一行都是一个微小的合同条款,通过解决特定模型上的特定失败模式来赚回它所占用的 Token 。最终形成的提示词之所以在主模型上表现出色,是因为它是针对主模型的行为,逐行雕琢出来的。

这是大家在接受“多模型网关”这种说法时,从未考虑过的代价。抽象层实现了调用的可移植性,但它并没有让提示词也具备可移植性。提示词是那个耗费了六个月进行调优的部分,而且一旦备选模型不再是主模型的忠实克隆,你就必须从头开始重新调优。

故障转移边界处的质量与可用性解耦

故障转移包含在 SLO 中。质量却不在。这种不对称性正是问题的症结所在。

你的监控栈——完全从它起步的传统服务中照搬而来——追踪延迟、错误率、吞吐量和 5xx 状态码。在故障转移期间,这四个指标的表现都正常。主模型返回 502 错误,网关路由到备选模型,备选模型返回 200 响应,仪表盘保持绿色。按照你团队商定监控的每一项标准来看,可靠性工程都在发挥作用。

仪表盘无法看到的是:虽然结构化提取字段的 Schema 验证通过,但其内容却存在微妙的错误;原本简洁的拒绝响应现在变得傲慢;下游组件渲染出的 Markdown 布局偏移了 3 个像素;原本小心翼翼保持中立的语气现在变得有些难以察觉的过于欢快。这些不是错误状态,而是行为状态。它们产生 200 响应并通过 Schema 验证。一周后,它们会作为“AI 表现很奇怪”出现在你的支持收件箱里,并被归类到与故障转移窗口期无关的类别中,因为没有人会将这两者关联起来。

更深层的问题是结构性的。可用性是请求生命周期的属性:请求是否完成、是否准时、是否没有错误码。而质量是响应内容的属性:它是否是用户需要的答案,且符合你产品预期的形式。这两者由不同的系统测量,由不同的团队负责,并在不同的评审会议中报告。在故障转移的边界处,它们发生了解耦——可用性保持标称水平,而质量下降——而你测量的那一半完全无法告诉你发生了什么。

如果故障转移正常工作,主要供应商长达数小时的故障并不会导致你的产品停摆数小时。它只会产生一个长达数小时的窗口期,在此期间,同一个 API 背后的模型变成了一个具有不同指纹特征的其他模型。如果你无法从仪表盘中看出这个窗口期的存在,你也无法判断它让你付出了什么代价,这意味着你无法诚实地权衡“我们维持了可用性”与“我们交付了更差的体验”之间的利弊。

跨模型格式脆性比人们承认的还要严重

最近的跨模型研究表明,在相同提示词下,不同模型之间的操作成功率范围大约相差半个标准差,而语义成功率的差距也几乎同样大。换句话说:当你把一个在你调优的模型上拥有 90% 通过率的提示词,运行在来自不同供应商的同类模型上时,你可能会在没做错任何事的情况下损失 40 到 50 个百分点的通过率。提示词格式正确。模型能力达标。但适配性很差。

格式脆性主要源于以下几个反复出现的方面:

  • 模型训练遵循的结构惯例:Claude 将 <document><example> 标签视为语义内容边界,因为 Anthropic 是以这种方式界定训练文档的。GPT 类模型则倾向于更自由形式的散文,并对 Markdown 风格的结构和对话式支架响应更可靠。同样的 <output_format>...</output_format> 块在一个模型上能提升解析精度,在另一个模型上则会被视为可见内容。
  • 按血统演化的拒绝语法差异:每个模型家族对于拒绝、模棱两可和工具不适用情况都有习得的措辞。你的提示词拒绝指令要么是为了配合该语法而调优(使模型产生一致的拒绝),要么是为了覆盖它(使模型以你产品的口吻产生拒绝)。无论哪种情况,备用模型都有不同的基准线,你的覆盖指令无法以相同的方式生效。
  • 输出格式锚定:模型返回 JSON 的方式、格式化表格的方式、处理嵌套代码块(code fences)的方式——这些都是累积的小习惯。你的下游解析器是针对主模型的习惯进行测试的。备用模型的习惯虽然通过了校验,但渲染效果却不同。
  • 指令遵循偏差:相同的指令会产生细微不同的服从模式。“始终在 200 字以内回答”在某些模型中被严格执行,而在其他模型中只是近似执行。“永远不要包含免责声明”在一个模型上能干净利落地生效,而在另一个模型上则会被暗中添加免责声明。

这些都不是备用模型中的 Bug。它们是针对一个非该模型目标的提示词所做出的正确行为。

缩小差距的模式

有三种方法可以将故障转移(failover)的边界从“尽力而为的相似性”提升到“工程化的一致性”。它们都不是免费的。

针对每个模型的提示词变体,作为一等资产进行维护。 提示词不只是一个文件。它是每个受支持模型对应一个文件,统一版本化,统一部署,并独立测试。XML 支架存在于 Claude 变体中;Markdown 支架存在于 GPT 变体中。拒绝语法针对每个模型进行调优。输出格式提示根据每个模型的解析器偏好进行校准。当故障转移启动时,网关不仅更换了模型,还更换了提示词。这会增加你的持续维护成本——每一次产品驱动的提示词变更都会变成 N 次变更——但这是让故障转移成为受控行为而非“寄予厚望”的唯一方法。

故障转移应是协调式的切换,而非简单的透传。 幼稚的网关将故障转移视为 Header 的重写:内容(body)相同,上游(upstream)不同。协调式网关将故障转移视为契约变更:模型更换、提示词更换、工具描述更换(因为工具描述也是调优过的产物)、温度和其他采样参数更换为针对备用模型调优的值。网关不再只是一个负载均衡器。它是一个配置开关,知道哪些配置与哪些模型配对。

使用与主模型相同的评估标准对备用模型进行评估(Eval)覆盖。 备用模型不是“备胎”。它是你的用户在没有察觉的情况下定期触达的生产模型。它理应获得相同的评估标准,以相同的节奏运行,并具备相同的回归门禁。当你通过修改主模型的提示词来修复某个行为时,你也有责任在备用模型的提示词上进行相同的修复——并且你需要对备用模型进行一次评估运行,证明修复也在那里生效了。这是大多数团队会跳过的环节,因为故障转移发生的概率只有 1%,且评估成本是真实存在的。略过这一步,你就是在运行一个未受监控的生产环境。

一个有用的测试可以判断你是否在认真对待这件事:随机挑选一个你最近对主系统提示词所做的更改。打开备用系统提示词中对应的更改。如果没有对应的更改,那么你拥有的只是一个主模型和一个愿望。

“备用模型”不等于“备用体验”

值得向领导层提出的论点,也是应该出现在路线图评审中的:这两个词组并不是同义词。

“我们有一个备用模型”是关于基础设施的表述。这意味着网关可以路由,SDK 可以讲两种方言,账单已设置好向两个供应商付费。这是一句真实且有用的话。这也是可靠性工程在结构上被激励去止步的地方,因为当这句话成立时,它所属的仪表盘就会显示绿色。

“我们有一个备用体验”是关于产品的表述。这意味着当故障转移启动时,用户会以你的语气、你的格式、你的拒绝方式,根据你的评估标准,获得你在只有这一条路径时也会发布的质量响应。这意味着提示词针对备用模型进行了调优,工具针对备用模型进行了描述,解析器针对备用模型进行了测试。这是一句难得多的真话,它根本不会出现在可靠性仪表盘上——它会出现在用户在你遭遇供应商事故期间对你产品的评价中。

这两句话都值得实现。可靠性那句话为你赢得看板上的数字。体验那句话为你赢得一个不会在你看不到也无法衡量的窗口期内(每周两次,每次十分钟)突然改变身份的产品。如果你这个季度只能负担得起其中一个,执行顺序应该是:先交付可靠性,因为用户会注意到停机;然后立即开始体验部分,因为即使用户不提交工单,他们也会注意到产品变得不对劲。

故障转移边界处可用性与质量之间的接缝,属于那种不会出现在任何单一团队职责范围内的接缝。可靠性团队负责故障转移。产品团队负责体验。平台团队负责提示词。没有人负责这三个部分各自完好但组合起来却很糟糕的情况。这个所有权缺口正是需要填补的地方,而填补它始于在你的操作手册中写下:备用模型和备用体验不是一回事。

References:Let's stay in touch and Follow me for more thoughts and updates