三个基础设施 bug 的复盘:我们从不因负载而降低 Claude 质量
8 月到 9 月初,三个基础设施 bug 间歇性地拉低了 Claude 的回答质量。现在都已修复,我们想说清楚到底发生了什么。
8 月初,一些用户开始反馈 Claude 回答变差。这些初期反馈很难和正常的用户反馈波动区分开。到 8 月下旬,反馈的频率和持续性不断上升,促使我们立案调查,最终挖出三个独立的基础设施 bug。
⭐ 把话讲明白:我们绝不会因为需求量、时段或服务器负载而降低模型质量。 用户遇到的问题,纯粹是基础设施 bug 造成的。
我们通常不会公开这种程度的基础设施技术细节,但这次问题的范围和复杂度值得一份更完整的说明。
我们如何大规模地提供 Claude
我们通过自有 API、Amazon Bedrock 和 Google Cloud Vertex AI 服务数百万用户,并把 Claude 部署在多种硬件平台上:AWS Trainium、NVIDIA GPU、Google TPU。
每种硬件特性不同、需要专门优化。尽管如此,我们对模型实现有严格的等价标准:不管哪个平台服务你的请求,回答质量都应一致。这也意味着——任何基础设施改动都得在所有平台和配置上仔细验证。
三个重叠的 bug
这几个 bug 互相重叠,让诊断格外困难。第一个 8 月 5 日引入,初期只影响约 0.8% 的 Sonnet 4 请求;另两个来自 8 月 25、26 日的部署。8 月 29 日一次例行的负载均衡改动意外放大了受影响流量——很多用户开始遇到问题,另一些却一切正常,造成自相矛盾的混乱报告。
1. Context window 路由错配
8 月 5 日,部分 Sonnet 4 请求被错误路由到了为即将上线的 100 万 token 上下文配置的服务器。初期影响 0.8%;8 月 29 日负载均衡改动后,被错误送往 1M 上下文服务器的短上下文请求大增,8 月 31 日最差那一小时,16% 的 Sonnet 4 请求受影响。约 30% 的 Claude Code 用户在此期间至少有一条消息被路由到错误服务器。
更糟的是我们的路由是「粘性的(sticky)」:一旦某个请求被错误服务器处理,后续追问很可能还落到同一台错误服务器上。
修复:纠正路由逻辑,确保短/长上下文请求进对的服务器池。9 月 4 日部署,9 月 16/18 日在各平台完成。
2. 输出损坏
8 月 25 日,我们给 Claude API 的 TPU 服务器部署了一个配置错误,导致 token 生成出错。一个运行时性能优化偶尔会给「按上下文本不该出现的 token」赋予过高概率——比如对英文 prompt 蹦出泰文或中文字符、或在代码里产生明显语法错误。用英文提问的一小部分用户,可能在回答中间看到一句「สวัสดี」。
影响 Opus 4.1/Opus 4(8 月 25–28)和 Sonnet 4(8 月 25–9 月 2)。第三方平台未受影响。
修复:9 月 2 日回滚,并在部署流程里加了「异常字符输出」的检测测试。
3. Approximate top-k 的 XLA:TPU 误编译
8 月 25 日,我们部署了改进 token 选择的代码,却意外触发了 XLA:TPU 编译器里一个潜伏已久的 bug,已确认影响 Claude Haiku 3.5(也可能波及部分 Sonnet 4 和 Opus 3)。
修复:先后于 9 月 4 日、9 月 12 日回滚;同时(a)与 XLA:TPU 团队合作修编译器,(b)改用精确 top-k + 增强精度。
深入看那个 XLA 编译器 bug
为了说明这些问题有多复杂,看看这个 XLA bug 是怎么冒出来、又为何特别难诊断的。
Claude 生成文本时,会算出每个候选下一个词的概率,再从这个分布里随机采样。我们用 top-p 采样避免胡言乱语——只考虑累积概率达到阈值(通常 0.99 或 0.999)的词。在 TPU 上,模型跨多块芯片运行,概率计算分散在不同位置,要对这些概率排序就得跨芯片协调数据,很复杂。
根因是混合精度运算。 模型用 bf16(16 位浮点)算概率,但向量处理器是 fp32 原生的,于是 TPU 编译器(XLA)为优化运行时会把某些运算转成 fp32(由默认开启的 xla_allow_excess_precision 标志控制)。这造成了精度错配:那些本该对「最高概率 token 是谁」达成一致的运算,跑在了不同精度上、于是不一致,导致最高概率的 token 有时彻底从候选里消失。
2024 年 12 月我们就发现过:温度为 0 时 TPU 实现偶尔会丢掉最可能的 token,当时打了个 workaround 绕过去。8 月 26 日我们重写采样代码修这个精度问题,自以为根治了、于是移除了 12 月的 workaround——结果暴露出一个更深的 bug:approximate top-k(一个快速找高概率 token 的性能优化)有时返回完全错误的结果,但只在特定批大小和模型配置下。原来 12 月那个 workaround 一直在无意中掩盖这个问题。
这个 bug 的行为气人地不稳定:它的表现取决于「之前/之后跑了什么运算」「调试工具开没开」这些不相关因素;同一个 prompt 这次完美、下次就挂。调查中我们还发现,精确 top-k 早已不再有当初那种「禁止性的性能代价」了——于是我们从 approximate 换成 exact top-k,并把一些运算统一到 fp32。模型质量不容妥协,我们接受了这点微小的效率损失。
为什么检测这么难
我们的验证流程通常靠 benchmark + 安全评估 + 性能指标,工程团队做抽检、先发小范围「金丝雀(canary)」群体。但这次暴露了几个该早点发现的关键缺口:
- 评估没抓到用户报告的退化——部分原因是 Claude 常常能从孤立的错误里自我恢复,掩盖了问题。
- 我们自己的隐私实践造成了调查障碍:内部隐私与安全控制限制了工程师访问用户交互(尤其是没作为反馈报上来的),保护了隐私,但也让工程师拿不到复现 bug 所需的问题交互。
- 每个 bug 在不同平台、以不同比率产生不同症状,混成一锅看不出单一原因的报告,像是随机、无规律的退化。
- 我们太依赖嘈杂的评估。虽然注意到线上反馈增多,却没有清晰的办法把它们和近期某次改动挂上钩——8 月 29 日负面反馈激增时,我们没立刻联想到那次看似标准的负载均衡改动。
我们要改什么
| 改进 | 内容 |
|---|---|
| 更敏感的评估 | 开发能更可靠区分「正常实现」和「坏掉实现」的评估,持续打磨 |
| 评估铺到更多地方 | 不只定期跑,要在真实生产系统上持续跑,以捕捉像上下文路由这种错误 |
| 更快的调试工具 | 在不牺牲用户隐私的前提下,更好地调试社区反馈;并准备专用工具缩短未来类似事件的修复时间 |
evals 和监控很重要,但这几起事件表明:我们还需要来自用户的持续信号。当 Claude 回答没达到平常水准时,「具体观察到什么变化、异常行为的例子、跨用例的模式」都帮我们隔离了问题。
请继续直接给我们反馈:在 Claude Code 里用
/bug,或在 Claude app 里点「踩」。开发者和研究者常创造出有趣的新方式来评估模型质量,欢迎发到 feedback@anthropic.com。
总结
我们对「基础设施改动不影响模型输出」一向维持极高的标准,这几起事件里我们没达到那个标准。一份好的 postmortem,价值不在于宣布问题已修,而在于诚实地剖出「检测和解决为何比预期更久」——以及把它变成日后不再重蹈覆辙的具体改动。