8 月初到 9 月初,用户开始零星报告 Claude 的回答变差了。Anthropic 一开始把这些反馈当成了正常的噪声, 到 8 月底才开始系统调查 ——查到了三个独立、但时间叠加在一起的基础设施 Bug。 这篇是他们公开的事故复盘。
三个 bug 同时发生,让诊断变得格外棘手:短上下文请求被路由到 1M 上下文服务器、 TPU 上的运行时优化让模型偶尔吐出泰文/中文乱码、XLA 编译器在近似 top-k 上选错 token。 没有任何一个 bug 是"故意降级"。
一句关键澄清:Anthropic 从不因为流量、时段或服务器负载主动降低模型质量。 用户感受到的下降,全部来自基础设施层面的真实 bug。
Anthropic 通过一方 API、Amazon Bedrock 和 Google Cloud Vertex AI 给数百万用户服务 Claude。 模型同时运行在 AWS Trainium、NVIDIA GPU 和 Google TPU 上 —— 这种多平台部署带来了容量和地理覆盖,也让任何基础设施改动的验证成本变得很高。
每种硬件性格不同,需要各自的优化路径。但 Anthropic 给自己设的硬约束是: 不论请求落到哪个平台,用户得到的回答质量应该是一致的。 这意味着任何一个底层修改,都要在所有平台和配置下重新验证一遍。
这次事故里几乎所有的麻烦都源自这个等效约束:bug 在不同硬件上以不同形式露出来 —— TPU 路径上是输出乱码和编译器选错 token,第三方平台上是路由错误 —— 症状的多样性反而模糊了"这是同一类问题"的信号。
多平台部署提供地理覆盖与冗余,但每次基础设施改动都要在所有平台上等效验证。
这次事故中,TPU 路径暴露了两个独立问题(输出乱码 + XLA top-k); 路由 bug 则跨所有平台。
第一个 bug 在 8 月 5 日就引入了,但只影响 Sonnet 4 的 0.8% 请求 —— 噪声水平。 8 月 25 / 26 日又叠加了两个 bug。真正让事故被注意到的,是 8 月 29 日的一次负载均衡变更, 它意外把更多短上下文请求路由到了为 1M 上下文配置的服务器,让一切症状被放大。
三张并列卡片,从「请求送到哪台机」、「token 怎么算」、「token 怎么排序」三个层面分别展开。 点开每张卡片可以看影响范围、根因、表现样例和修复方式。
8 月 5 日,部分 Sonnet 4 请求被错误地路由到了为即将上线的 1M token 上下文窗口配置的服务器上。 最初只影响约 0.8% 的请求 —— 在噪声里几乎看不出。
8 月 29 日的一次"例行"负载均衡变更,无意中把更多短上下文请求也送到了 1M 上下文服务器。 到 8 月 31 日的最差时段,16% 的 Sonnet 4 请求被影响。
放大效应来自路由是「黏滞」的:一旦某次请求落在错误的服务器,它的后续 follow-up 通常也会粘在同一台服务器上 —— 少数用户因此被反复打到错误路径。
8 月 25 日,Anthropic 在 Claude API 的 TPU 服务器上部署了一次错误配置。 一个为运行时性能引入的优化,导致 token 生成阶段偶尔给本不该出现的 token 分配了高概率 —— 比如英文 prompt 的回答中间冒出泰文或中文,或者代码里出现明显的语法错误。
影响窗口:Opus 4.1 / Opus 4 是 8/25 – 8/28;Sonnet 4 是 8/25 – 9/2。 第三方平台(Bedrock / Vertex AI)不受影响,因为它们走的不是这条 TPU 路径。
8 月 25 日,Anthropic 部署了一份新代码来改进文本生成中如何选 token —— 意图是修一个 12 月就发现的混合精度问题,结果意外触发了 XLA:TPU 编译器里一个潜伏 bug。
已确认影响 Claude Haiku 3.5 的请求;怀疑也影响了一方 API 上的 Sonnet 4 子集和 Opus 3。 Bedrock / Vertex AI 不受影响。
这个 bug 是整篇 postmortem 里最技术、也最值得展开的部分。下一节有完整故事 —— 从一年前的 workaround,到表层修复反而暴露出更深的问题。
这是整起事故里最有教育意义的一段。它讲的是一个看起来"修好了"的问题, 其实只是一个编译器优化的预期行为;而原本被它意外掩盖的真正 bug, 在表层修复之后才浮上来。
XLA = Accelerated Linear Algebra,Google 出的 ML 编译器。
它把 JAX / TensorFlow 写的高层数学(比如 softmax(x @ w + b))
翻译成 TPU / GPU 的底层指令,并在中间做整图融合优化(把多个相邻算子合成一个 kernel,省掉显存来回搬运)。
TPU 上几乎所有 ML 代码都要经过它 —— 这个事故里被点名的「XLA:TPU」就是它的 TPU 后端。
所以 XLA 不等于 CUDA,而是更像「ML 版 GCC + cuDNN」。 在 NVIDIA GPU 上,专家可以绕开框架直接写 CUDA / Triton kernel(FlashAttention 就是这么写的); 但 TPU 上没有这个逃生出口 —— XLA 是唯一一条路。
理解了 XLA 这一层之后,接下来的故事就清晰了。Claude 生成文本时,对每个候选 token 算一个概率,再按这个分布随机采样。 我们用 top-p sampling 来避免胡言乱语 —— 只考虑累计概率达到阈值(通常 0.99 或 0.999)的那些 token。
在 TPU 上,模型是跨多颗 chip 切分的,概率计算分布在不同位置。要给这些概率排序, chip 之间必须协调数据 —— 这是一个分布式排序问题,比单机上写一行 sort 复杂得多。
团队在 TPU 实现里观察到 温度为 0 时偶尔会丢掉概率最高的 token。 当时打了一个 patch 来 work around 这种情况 —— 但没有真正搞清楚它为什么发生。
模型用 bf16(16 位浮点)算下一 token 概率。但 TPU 的向量处理器是 fp32 原生的,
所以 XLA 编译器会自动把一部分操作提升到 fp32 来跑得更快 —— 这个优化由
xla_allow_excess_precision 标志控制,默认开启。
这导致同一组本应一致的概率,在不同精度下被算了出来,于是它们对"谁是最高概率"的判断不一致 —— 最高概率 token 偶尔从候选里整个消失。
通过最小复现,团队认定 12 月看到的现象其实不是编译器 bug,
而是 xla_allow_excess_precision 默认开启情况下的预期行为。
既然根因是混合精度,团队重写了采样代码、把精度问题修对, 并移除了那个原以为多余的 workaround。 ——表面上一切看起来更干净了。
近似 top-k是 XLA:TPU 上的一个性能优化,能更快地找出最高概率的几个 token。 它的设计假设是「在最低概率的 token 上接受一点不准确」,正常情况下不影响质量 —— 除非它把最高概率 token 给丢了。
移除 12 月的 workaround 后,这个 approximate top-k 在某些 batch size 和模型配置下会返回完全错的结果, 而 12 月的 workaround 之前一直误打误撞地把它盖住了。
更糟的是,bug 的行为极度不稳定:依赖前后跑了什么操作、依赖是否打开了调试工具, 同一个 prompt 一次能跑对一次跑错。
调研中团队发现:exact top-k 在今天的 TPU 上已经没有当年那么大的性能代价了。 于是切换 approximate → exact top-k,并把若干额外操作标准化为 fp32 精度。 「模型质量是非 negotiable 的,效率上的微小代价可以接受。」
同时和 XLA:TPU 编译器团队推进底层 bug 的修复 —— 这条线在写文章时仍在进行。
概率在不同精度下不一致 → 12 月加了 workaround 让"最高 token 偶尔丢"看不见 → workaround 同时也在意外掩盖近似 top-k 在某些 batch 下的失灵。
统一精度、改用 exact top-k。 性能代价小、质量稳,并把对 approximate top-k 的隐含信任改成显式选择。
Anthropic 的发布流程里有 benchmark、安全评估、性能监控、Spot Check、Canary 灰度。但在这次事故里, 这些手段集体失灵 —— 不是任何一道关卡彻底失效,而是它们都不够灵敏,捕捉不到"用户真正感受到的下降"。
Claude 经常能从一次孤立的错误里恢复回正常水平 —— 这让标准 benchmark 看上去「分数还行」,但用户在真实多轮对话里能感觉到不对。 这种钝化让团队对早期信号一直"半信半疑"。
Anthropic 的内部隐私和安全控制限制工程师在何时何地查看用户与 Claude 的交互 —— 特别是当这些交互没有作为反馈主动报上来时。 这保护了隐私,但也让"找到能复现 bug 的样本"变得困难。
每个 bug 表现都不一样,加上不同平台不同发生率 —— 整体看上去像是"随机的、零星的质量下降",而不是某个具体改动出的问题。 反馈拼不出一个明确的原因。
更深一层,团队过度依赖了"嘈杂的评估"。8 月 29 日负面反馈集中爆发那天, 他们当然注意到了,但没有把它和当天那次「看起来很标准」的负载均衡变更联系起来 —— 这个变更在自己的指标看板上完全没出问题。
Anthropic 把这归结为「缺少把社区反馈和具体内部变更对齐起来的机制」。 换句话说,问题不是没人在看,而是没人能把外部信号和内部时间线对上。
Anthropic 给出了三条具体改动方向。每一条都对应上一节的一个失灵点。
已经做出能更可靠区分「实现正常 / 实现损坏」的新评估。 会持续完善这些评估来更紧密地盯模型质量 —— 补的就是「Claude 能从单次失败恢复,所以总体分数还行」这个盲区。
以前是在专门系统上跑。现在会在真实生产系统上持续跑 —— 确保像「上下文窗口 + 负载均衡」这类组合错误能在用户感知前被指标抓住。
会开发新的基础设施和工具,在不破坏用户隐私的前提下处理社区反馈。 这次事故中临时打造的一些工具,未来事故里可以直接用来缩短定位时间。
评估和监控很重要,但这场事故说明:在 Claude 表现不如平时时,我们也需要来自用户的持续信号。 你们对具体变化的描述、不正常行为的样例、不同使用场景中观察到的模式 —— 都是我们这次定位问题的关键拼图。
在 Claude Code 里用 /bug 命令,或在 Claude 应用里点「踩」,都能直接把反馈送回给我们。 如果你做出了好玩的、能补充我们内部测试的评估方法,欢迎写信到 feedback@anthropic.com。
— Anthropic Engineering · Sam McAllister 等