跳到主要内容

服务商侧安全漂移:当你的产品在未发布的情况下发生回退

· 阅读需 10 分钟
Tian Pan
Software Engineer

周二还能用的提示词(prompt),到周四就返回了“我无法提供帮助”。CI 评估依然是绿色的。你配置中的模型名称没变。提示词在字节层面完全一致,在源码控制中也经过了哈希处理和固定。然而,一个围绕新出现的拒绝回答(refusal)的客户支持线程正在形成——AI 团队在两周内都不会察觉到这一点,因为它必须经过一级支持、分类,最后才落到能读取追踪信息(trace)的人手中。

这就是服务商侧的安全漂移(provider-side safety drift),它是当今生产环境 AI 中构建最不完善的监控缺口。前沿服务商会以不在你发布日程上的频率,在服务端调整安全过滤器、拒绝阈值和内容分类器。你的团队没有订阅这些变更,通常也没有发布说明。而且这种退化是具有非对称性的,以一种确实难以察觉的方式呈现:正当意图的拒绝率悄悄爬升,而你认为服务商会过滤的有害查询却开始悄悄溜过。边界在两端独立移动,且毫无预警。

你实际调用的三组件模型

大多数团队采用的心智模型是“我们调用模型”。那个模型是错误的。你实际调用的是至少包含三个独立版本化组件的系统:

  1. 权重 (Weights) —— 训练好的网络。这就是模型 ID 表面上固定的内容。
  2. 系统工具链 (System tooling) —— 围绕权重的服务端脚手架:结构化输出强制、工具调用编排、函数调用清洗器、系统提示词前置内容、信任与安全分类器链。
  3. 安全策略 (Safety policy) —— 那些分类器上的阈值配置、拒绝准则、被视为禁止的类别、针对特定用例的例外处理。

Anthropic 和 OpenAI 都已转向使用不可变的、带日期的快照 ID 来表示 权重。尤其是 Anthropic 声称,固定的 Claude 快照 ID 在该 ID 的生命周期内是稳定的 —— claude-sonnet-4-5-20250929 的底层权重不会改变。这一承诺很有意义,但未被充分利用。

但该约定仅涵盖了三个组件中的一个。系统工具链和安全策略的调整频率远高于权重发布频率,而且调整时不会铸造新的模型 ID,因为权重没有改变。因此,你的代码调用的 API 端点 —— messages.create(model="claude-sonnet-4-5-20250929", …) —— 针对相同的输入和相同的模型 ID,可能会在周复一周的情况下返回实质上不同的输出,而这完全符合服务商所陈述的稳定性承诺。

那些固定了模型 ID 并假设这就意味着“行为已冻结”的团队,实际上是在产品中植入了一个服务商从未承诺过的关键假设。

为什么退化是非对称的

令人痛苦的模式是,漂移在安全边界的两个方向上都会发生,而你通常只对其中一个方向有遥测数据。

方向 1:针对正当意图的误报拒绝(false-positive refusals)。 一个摘要提取端点开始拒绝总结 PDF,因为安全链认为某些文档类别“可能受版权保护”。一个根据监管准则经过仔细评估的医疗信息聊天机器人,现在对过去能回答的问题开始闪烁其词。一个代码助手拒绝解释 CVE 报告,因为表面文本包含漏洞利用术语。这些在三个月前你与团队协商的政策中都不是被禁止的。分类器的行为发生了偏移。

方向 2:针对禁止意图的漏报泄露(false-negative leakage)。 这是一个更隐蔽且更糟糕的方向。团队在构建内容审核策略时,假设特定的服务商分类器能捕获,比如 99% 的违规类别提示词。随后,分类器为了减少过度拒绝(这是某些已发布的模型规范中明确提到的目标)而进行了重新调整,导致你所关注类别的召回率下降到了 92%。团队对此没有评估,因为评估隐含地假设了服务商提供了兜底保障。

这种非对称性之所以有害,是因为大多数团队会反射性地对方向 1 进行监控(拒绝是用户可见的,会产生投诉),而对方向 2 则完全没有监控(在出事之前,泄露看起来就像正常的响应)。一次既增加了过度拒绝、又减少了拦截不足的安全退化,在聚合指标中看起来可能像什么都没发生一样。用户满意度(CSAT)略有波动,投诉量有所偏移,但没有人会收到报警。

哪些内容必须纳入监控

缓解措施在概念上很简单,但几乎没有人去执行。原因是它们要求 AI 团队负责跟踪针对动态目标的行为,而大多数产品组织并未将此纳入 AI 路线图的范围。

每日拒绝金丝雀集(canary set)。 维护一个固定的、包含故意设定的边缘提示词的语料库(五十到几百个),用于测试你的产品关注的安全边界。每天针对生产环境的模型 ID 运行这些提示词。按类别跟踪拒绝率的时间序列。重点不在于金丝雀语料库代表生产流量,而在于金丝雀是不变的,因此其输出的任何变动,从结构上看都是服务商的变动。金丝雀提示词应包括:正当但接近红线的请求(用于检测过度拒绝漂移),以及你产品实际涉及类别中明确禁止的请求(用于检测泄露漂移)。

实时流量的拒绝原因直方图。 不要只记录“模型拒绝了”。通过解析模型给出的原因或对拒绝文本进行分类,记录拒绝的 类别 —— 版权、自残、暴力、法律建议、个人数据等。绘制分布图。当分布在输入分布未变的情况下发生偏移时,说明服务商移动了其边界。大多数团队从未构建过这种仪表盘,因为他们的日志将拒绝视为二进制布尔值,这丢掉了区分服务商漂移与用户行为变化的唯一信号。

为有条件的产品建立固定快照 A/B 测试。 如果服务商提供了仍在服务的旧快照,并行地将一小部分流量路由到该快照并进行对比。相同输入下拒绝率的差异是两个快照之间策略漂移的直接信号。这是一种廉价且机械的方法,但几乎没有团队运行它,因为 A/B 测试的肌肉记忆是针对 代码的,而不是为了捕获 现有 代码中未宣布的漂移。

针对已知基准快照的每周比对(diff)。 如果你维护有一套回归测试套件,请定期针对当前的生产快照和固定的参考快照运行它。两者之间的差异就是服务商的增量(deltas)—— 而这正是服务商在发布说明中没有发送给你的数据。

没人预约过的合同谈判

这既是一个产品工程问题,也是一个供应商管理问题,它存在于双方通常都不负责的尴尬地带。

如果你的规模大到供应商配有专门的客户团队,请要求提供安全配置的变更日志通知。询问是否存在或计划推出“稳定安全层(stable safety tier)”。一些企业级合同包含此内容;许多产品团队从不询问,因为他们以为带日期的模型 ID 就是合同的全部。询问是否可以针对特定快照选择退出自动分类器更新,或者当你依赖的模型出现政策漂移时,能否被列入通知名单。

有意识地建立与供应商支持团队的关系,而不是被动响应。如果你只在出现紧急情况时才联系他们,你就不在那个能提前收到下一次收紧预警的社交圈内。与供应商进行季度同步的团队会在分类器工作发布前几周获悉,并能准备好金丝雀测试(canaries)。而那些不这样做的团队,则会从用户那里听到消息。

这是件乏味的工作,看起来不像 AI 工程。这也是一个每季度被突发状况惊吓两次的团队与一个从容应对的团队之间的区别。

隐藏在评估流水线中的组织失效模式

这是一个让成熟团队也掉进去的陷阱。安全团队负责原本可以检测到回归(regression)的评估(eval)。评估是全面的、精心策划的,并且在 CI 中运行。但它指向的是团队当初训练时的模型快照,或者更糟,指向的是两年前设置的内部 API 端点,而那个端点指向的是一个现在根本没人使用的模型。

当客户投诉出现了不该发生的拒绝(refusal)时,安全团队运行评估并报告结果为绿色(通过)。评估确实是绿色的 —— 针对它所连接的版本而言。而今天早上在生产环境中返回回归输出的版本,从未经过该评估。这两句陈述都是事实,加在一起就是一场调试噩梦。

解决办法是机械性的:每一个决定发布的评估必须针对生产环境调用的 确切 模型 ID 和 确切 端点运行,且频率要与生产流量一致。如果你的评估流水线指向不同的快照、沙箱端点或“稳定”的内部镜像,那么你建立的信心并非源自你的产品。测试你发布的,发布你测试的。权重之前的分类器链也是你发布内容的一部分。

这对技术栈意味着什么

架构上的启示是,“模型”不再是一个有用的依赖跟踪单位。固定(Pinning)模型 ID 是必要的,但并不足够。实际的依赖关系是(权重、工具、政策)三元组,而该三元组中只有第一个成员受稳定性合同约束。

实际后果:

  • 你的版本固定策略需要一个 行为 组件,而不仅仅是一个标识符组件。金丝雀输出,而非版本字符串,才是真正的固定标准。
  • 你的事件响应需要将“供应商是否有所变动?”作为一个一级假设分支,而不是在排除掉自己代码的所有问题后,到第三天才去检查的事情。
  • 你的评估套件需要一个拒绝分布维度,独立于准确性和帮助性之外。拒绝不是一种二元错误模式,它是一种具有自身分布且会发生漂移的行为。
  • 你的供应商管理流程需要一条 AI 专有的通道。你想要的供应商关系是:在你的用户发现之前,你就能获悉分类器的收紧情况。

大多数团队会以缓慢的方式构建起这套技术栈:一次客户可见的回归,一次复盘,一个 Jira epic。率先实现的团队将是那些意识到自己调用的模型是一个移动目标的人 —— 并且意识到他们原本认为拥有的合同,其实只覆盖了那些实际上并没有移动的部分。

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