询问任何工程主管,他们是否被模型供应商锁定了,他们都会指向抽象层。“我们通过网关路由所有内容。更换供应商只是配置更改。”端点只有一行代码。Base URL 是一个环境变量。在纸面上,迁移只需要一个周二下午。
然后他们尝试了。他们将配置切换到不同的模型系列,集成测试依然通过,但生产环境却悄然崩溃。原本总能解析的 JSON 现在被包裹在 Markdown 代码块中。准确率曾达 94% 的分类器降到了 80% 出头。一个稳定运行了一年的提示词开始因为无人能复现的原因,在每 20 个请求中拒绝 1 个。端点在几秒钟内完成了切换,但行为并没有随之迁移。
这就是没人预料到的锁定。它不在你的合同或 SDK 中,而是在你的提示词(prompts)中——你的团队为了适应单一模型系列的特性,一次又一次地做出的数千个细微调整。你选的不是模型,而是与之“联姻”,而“婚前协议”就是你发布过的每一个提示词。
锁定发生在提示词,而非 API
当人们想象供应商锁定时,他们想到的是基础设施:私有 SDK、自定义分词器(tokenizers)、无法重新生成的嵌入(embeddings)、连接到特定仪表盘的监控。这一层确实存在,而像兼容 OpenAI 的路由器这样体面的网关可以掩盖大部分问题。请求格式标准化了,响应结构标准化了,账单也合并了。
但网关只标准化的外壳。它无法标准化提示词 内部 的内容,而这正是真正的耦合积累的地方。每个模型系列都有其个性——一套格式习惯、指令遵循惯例、拒绝反应和推理风格。你的提示词并非在真空环境下编写的,而是针对这种个性编写的,并在每次出现问题时针对它进行调整。
想想一个提示词实际上是如何演变的。初稿要求返回 JSON,模型偶尔会加一段前言,于是有人加上了“仅返回有效的 JSON,不要包含其他文字”。模型有时会模棱两可,于是有人加上了“语气要果断”。它在某种良性的边缘案例中过度拒绝,于是有人加了一句话向它保证请求是合法的。六个月后,那个提示词有了 11 个类似的补丁,而 其中每一个补丁都是它所针对调优的那个模型的“指纹”。迁移到新的模型系列,这些补丁不仅不再起作用,其中好几个甚至会起到反作用,因为它们正在修正一个新模型根本不存在的倾向。
将这种情况乘以你产品中的几百个提示词,你就得到了没人列入路线图的迁移成本。行业估计,实际的模型迁移成本占原始开发时间的 20% 到 50%,而最主要的支出项并不是工程上的切换,而是重新推导那些你以为属于自己、实则是“租赁”来的提示词行为。
你一直在默默忍受的三种特性
锁定之所以会加剧,是因为这些适配工作是隐形的。它们给人的感觉像是“提示词的工作方式”,而不是“这个模型 的工作方式”。在切换模型时,有三类情况造成的损害最大。
格式和输出纪律。 模型在履行输出约定方面的可靠程度大相径庭。有的系列在你要求时会返回干净的 JSON;有的默认将其包裹在代码块中;第三种则倾向于在正文前进行叙述,除非你极力阻止。你的解析层编码了对你最初使用的模型的假设。即使是原生的结构化输出和函数调用功能在严格程度上也各不相同——什么算作有效模式、枚举如何处理、模型极是否会在模糊情况下捏造字段。切换的那天,你的下游解析器会遇到它们从未准备好去处理的输出。
拒绝边界。 这是最被低估的锁定形式,也是最难测试的。每个供应商划定的安全线都略有不同,而且那条线并不是一个清晰的阈值,而是一个嘈杂的局部决策边界。最近的评估工作发现,即使两个来自同一供应商的模型拒绝了超过 94% 明确禁止的提示词,大约三分之一的基础提示词在经过细微的、保持原意的改写后,其拒绝行为也会发生逆转。在 不同 供应商之间,这种差异甚至更大。你的提示词已经悄悄地围绕当前模型的精确边界进行了塑造——能够通过的措辞、能让良性但处于边缘的请求得以执行的保证、你学会避开的话题。这些都无法迁移。切换之后,你会像用户一样发现新的边界:在生产环境中,一次又一次地遇到错误的拒绝。
指令遵循惯例和推理风格。 某些模型系列对简洁、命令式的指令反应最好;另一些则更青睐详细的角色和背景设定。经过推理调优的模型通常需要与非推理同类模型 不同 的提示词——思维链(CoT)引导可以帮助一个模型,但可能会降低另一个在内部进行推理的模型性能。为一个模型系列优化的提示词在另一个模型上可能会表现欠佳,这不一定是因为新模型更差,而是因为它需要不同的提问方式。“通用的提示词”是一个神话,它只能维持到你第一次迁移之前。
“只需更换端点”是一种范畴错误
“只需更换端点”这种说法将模型视为一个具有稳定契约的无状态函数:输入相同,输出等效,像数据库驱动程序一样可以互换。正是这种心智模型导致了预算规划的偏差。
模型并不是一个背后有实现的接口。它本身就是实现,而接口——也就是你的提示词——是经过数月的迭代与它共同设计的。更换端点改变了实现,却保留了为旧实现量身定制的接口。这当然会出问题。你不会在从 Postgres 切换到文档数据库时原封不动地保留 SQL 查询,并将其称为配置更改;因为查询是针对某种引擎的语义编写的。提示词是针对模型语义的查询,只不过这种语义是统计性的、没有文档记录的,并且会在版本之间发生漂移。
这也是为什么抽象层虽然有用,却会让你产生一种可以轻松移植的错觉。网关为你提供了一种向任何模型发送请求的统一方式。它并不能提供一个在任何模型上都有效的请求。它标准化了调用的语法,却把提示词的语义完全留给你去解决。更糟糕的是,过度依赖“最小公分母”——即只使用每个供应商都共有的功能——意味着放弃了你付钱购买的原生能力。通过拒绝使用任何特色功能换取来的移植性,最终只会让你感到懊悔。
还有一个更隐蔽的陷阱:不仅是供应商锁定,还有版本锁定。供应商会弃用并退役模型快照。当你当前使用的模型被停用时,即使你没打算迁移,也会被迫进行迁移。此时,你必须在截止日期前匆忙重新推导提示词,而不是按照自己的计划进行。原地踏步并不能避免这种成本,只会将其推迟到最不方便的时刻。
在账单到期前衡量你的风险敞口
你无法消除提示词层面的锁定——适应模型的怪癖本身就是提示词工程的大部分工作。但你可以衡量你的风险敞口,这样切换工作就会是一个有计划的项目,而不是一次紧急突击。目标是在被迫买单之前,将迁移成本作为一个数字了然于胸。
首先构建一个供应商中立的评估集。 在接触第二个模型之前,冻结一套具有代表性的输入及分级预期——不是“它是否返回了 JSON”,而是“提取的字段是否匹配”、“它是否拒绝了该拒绝的并允许了该允许的”、“语气是否保持一致”。这套评估方案是唯一能让“新模型效果更差”从一种模糊的感觉变成可衡量断言的工具。如果你没有评估方案,那么你实际上被完全锁定了,因为你根本无法判断切换是否成功。
持续运行影子模型,而不是仅运行一次。 选择第二个模型系列,悄悄地将生产流量的采样切片发送给它,对照评估集对输出进行评分,但不将结果提供给用户。这会将迁移成本转化为一个实时的仪表板指标。随着两个模型的更新,你会看到主模型和影子模型之间的差距在扩大或缩小,从而在任何特定的一天都能确切知道切换工作大概需要多少工作量。第一次运行影子模型总是让人感到羞愧——差异往往比任何人预想的都要大。
记录你的“补丁”。 审计提示词中为了适应模型而做的调整:例如“仅返回 JSON”的防御性语句、反模棱两可指令、拒绝绕过方案、格式强制转换等。每一个调整都是一个锁定单元。统计它们可以让你获得粗略的迁移评估,更实用的是,它能告诉你哪些提示词过度拟合了某个模型的个性,应该在没有压力的时候立即进行简化。
将持久提示词与模型特定层分离。 在可能的情况下,将提示词拆分为供应商中立的核心部分(任务、输入、成功标准)和持有格式微调与怪癖修正的薄薄的模型系列适配层。你无法在所有地方都实现彻底分离,但通过这种方式重构的每个提示词都能缩小切换时必须重新推导的范围,并使适配层成为进行针对性调优的理想场所。
令人不安的事实是,与某个模型“建立婚约”是不可避免的,甚至是正确的——想要榨取模型的真实性能,就意味着要针对它进行调优,而针对它调优就意味着与之耦合。错误不在于这种绑定,而在于假装自己还单身。那些吃亏的团队往往认为端点就是关系的全部,结果却痛苦地发现,提示词才是真正的誓言。了解你的迁移成本,防止它悄悄膨胀,这样你就能选择何时迁移——而不是在模型被弃用的那天发现,你以为的配置更改变成了一个你毫无准备的季度任务。
会员专享
余下内容仅对会员开放。
会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
- —完整文章,包含未公开存档的部分
- —可落地的工作框架,附带权衡与决策依据
- —新文章抢先看,先于公开发布
随时取消 · 一次订阅,畅读全部