近期三个问题的事后复盘

这是一份关于三个 bug 的技术报告,这些 bug 曾间歇性降低 Claude 的响应质量。下文会解释发生了什么、为什么修复花了时间,以及我们正在改变什么。

来源:https://www.anthropic.com/engineering/a-postmortem-of-three-recent-issues
发布日期:2025-09-17

近期三个问题的事后复盘题图

8 月到 9 月初之间,三个基础设施 bug 间歇性降低了 Claude 的响应质量。我们现在已经解决这些问题,并希望解释发生了什么。

8 月初,一些用户开始报告 Claude 响应质量下降。这些初始报告很难与用户反馈中的正常波动区分开来。到 8 月下旬,这些报告出现的频率和持续性都在增加,促使我们启动调查,并最终发现了三个相互独立的基础设施 bug。

直白地说:我们从不会因为需求量、一天中的时间或服务器负载而降低模型质量。用户报告的问题完全由基础设施 bug 导致。

我们知道用户期待 Claude 提供一致的质量,也一直以极高标准确保基础设施变更不会影响模型输出。在近期这些事件中,我们没有达到这个标准。下面的事后复盘会解释哪里出了问题,为什么检测和解决所花时间比我们希望的更长,以及我们正在做哪些改变来防止类似事件再次发生。

我们通常不会分享如此详细的基础设施技术细节,但这些问题的范围和复杂性值得进行更全面的说明。

我们如何规模化服务 Claude

我们通过第一方 API、Amazon Bedrock 和 Google Cloud 的 Vertex AI 向数百万用户提供 Claude。我们在多个硬件平台上部署 Claude,具体包括 AWS Trainium、NVIDIA GPU 和 Google TPU。这种方式提供了服务全球用户所需的容量和地理分布。

每个硬件平台都有不同特性,并需要特定优化。尽管存在这些差异,我们对模型实现有严格的一致性标准。我们的目标是,无论请求由哪个平台处理,用户都应获得相同质量的响应。这种复杂性意味着,任何基础设施变更都需要在所有平台和配置上经过仔细验证。

事件时间线

Claude API 上事件的示意时间线。黄色:检测到问题,红色:质量下降加重,绿色:部署修复。

Claude API 上事件的示意时间线。黄色:检测到问题,红色:质量下降加重,绿色:部署修复。

这些 bug 相互重叠,使诊断尤其困难。第一个 bug 于 8 月 5 日引入,影响了约 0.8% 发往 Sonnet 4 的请求。另两个 bug 来自 8 月 25 日和 26 日的部署。

虽然初始影响有限,但 8 月 29 日的一项负载均衡变更开始增加受影响流量。这导致更多用户遇到问题,而其他用户仍看到正常表现,从而产生了混乱且互相矛盾的报告。

三个重叠问题

下面我们描述导致质量下降的三个 bug、它们发生的时间,以及我们如何解决:

1. 上下文窗口路由错误

8 月 5 日,一些 Sonnet 4 请求被错误路由到为即将推出的 1M token 上下文窗口配置的服务器。这个 bug 最初影响 0.8% 的请求。8 月 29 日,一项常规负载均衡变更无意中增加了被路由到 1M 上下文服务器的短上下文请求数量。在 8 月 31 日受影响最严重的一个小时中,16% 的 Sonnet 4 请求受到影响。

在此期间发出请求的 Claude Code 用户中,约 30% 至少有一条消息被路由到错误服务器类型,导致响应质量下降。在 Amazon Bedrock 上,从 8 月 12 日起,被错误路由的流量峰值达到所有 Sonnet 4 请求的 0.18%。8 月 27 日到 9 月 16 日之间,Google Cloud 的 Vertex AI 上受错误路由影响的请求少于 0.0004%。

不过,有些用户受到的影响更严重,因为我们的路由是「粘性」的。这意味着,一旦某个请求由错误服务器处理,后续跟进请求也很可能继续由同一错误服务器处理。

**解决方案:**我们修复了路由逻辑,确保短上下文和长上下文请求被导向正确的服务器池。我们于 9 月 4 日部署了修复。到 9 月 16 日,我们完成了在第一方平台和 Google Cloud 的 Vertex AI 上的 rollout;到 9 月 18 日完成了在 AWS Bedrock 上的 rollout。

2. 输出损坏

8 月 25 日,我们向 Claude API TPU 服务器部署了一个错误配置,导致 token 生成过程中出现错误。由运行时性能优化引发的一个问题,会偶尔给在当前上下文中本应极少生成的 token 分配较高概率,例如在英文提示词的响应中生成泰语或中文字符,或在代码中生成明显语法错误。比如,一小部分用英文提问的用户,可能会在响应中间看到 "สวัสดี"。

这种损坏影响了 8 月 25-28 日发往 Opus 4.1 和 Opus 4 的请求,以及 8 月 25 日至 9 月 2 日发往 Sonnet 4 的请求。第三方平台未受此问题影响。

**解决方案:**我们识别出该问题,并于 9 月 2 日回滚了变更。我们已在部署流程中加入用于检测意外字符输出的测试。

3. approximate top-k XLA:TPU 错误编译

8 月 25 日,我们部署了用于改进 Claude 在文本生成期间选择 token 方式的代码。这项变更无意中触发了 XLA:TPU[1] 编译器中的一个潜伏 bug,并已确认影响发往 Claude Haiku 3.5 的请求。

我们也认为,这可能影响了 Claude API 上一部分 Sonnet 4 和 Opus 3 请求。第三方平台未受此问题影响。

**解决方案:**我们最初观察到该 bug 影响 Haiku 3.5,并于 9 月 4 日将其回滚。之后我们注意到用户关于 Opus 3 问题的报告与该 bug 相符,并于 9 月 12 日将其回滚。经过广泛调查,我们无法在 Sonnet 4 上复现这个 bug,但出于高度谨慎,也决定将其回滚。

与此同时,我们(a)一直在与 XLA:TPU 团队合作修复编译器 bug,并且(b)推出了使用增强精度 exact top-k 的修复。详情请见下面的深入分析。

深入了解 XLA 编译器 bug

为了说明这些问题的复杂性,下面介绍 XLA 编译器 bug 是如何表现出来的,以及为什么它特别难诊断。

当 Claude 生成文本时,它会计算每个可能下一个词的概率,然后从这个概率分布中随机采样。我们使用 "top-p sampling" 避免无意义输出,也就是只考虑累计概率达到某个阈值(通常为 0.99 或 0.999)的词。在 TPU 上,我们的模型跨多个芯片运行,概率计算发生在不同位置。为了排序这些概率,我们需要在芯片之间协调数据,这很复杂。[2]

2024 年 12 月,我们发现 TPU 实现会在 temperature 为零时偶尔丢弃最高概率 token。我们部署了一个 workaround 来修复这种情况。

2024 年 12 月 patch 的代码片段,用于规避 temperature = 0 时意外丢弃 token 的 bug。

2024 年 12 月 patch 的代码片段,用于规避 temperature = 0 时意外丢弃 token 的 bug。

根因涉及混合精度算术。我们的模型以 bf16(16 位浮点)计算下一个 token 概率。不过,向量处理器是 fp32-native,因此 TPU 编译器(XLA)可以通过将某些操作转换为 fp32(32 位)来优化运行时。这个优化 pass 由 xla_allow_excess_precision 标志保护,该标志默认为 true。

这造成了不匹配:本应对最高概率 token 达成一致的操作,在不同精度级别上运行。精度不匹配意味着它们并不同意哪个 token 拥有最高概率。这导致最高概率 token 有时会完全从考虑范围中消失。

8 月 26 日,我们部署了采样代码重写,以修复精度问题,并改进我们对达到 top-p 阈值边界的概率的处理方式。但在修复这些问题时,我们暴露了一个更棘手的问题。

代码片段展示了作为 8 月 11 日变更一部分合并的最小复现,该变更定位了 2024 年 12 月被 workaround 规避的“bug”的根因;实际上,这是 xla_allow_excess_precision 标志的预期行为。

代码片段展示了作为 8 月 11 日变更一部分合并的最小复现,该变更定位了 2024 年 12 月被 workaround 规避的 "bug" 的根因。实际上,这是 xla_allow_excess_precision 标志的预期行为。

我们的修复移除了 12 月的 workaround,因为我们认为已经解决了根因。这导致 approximate top-k 操作中更深层的 bug 暴露出来。approximate top-k 是一种性能优化,用于快速找到最高概率 token。[3] 这种近似有时会返回完全错误的结果,但只在某些 batch size 和模型配置下发生。12 月的 workaround 无意中遮蔽了这个问题。

Slack 消息展示了与开发该算法的 XLA:TPU 工程师共享的底层 approximate top-k bug 复现。代码在 CPU 上运行时会返回正确结果。

开发该算法的 XLA:TPU 工程师共享的底层 approximate top-k bug 复现。代码在 CPU 上运行时会返回正确结果。

这个 bug 的行为不一致得令人沮丧。它会随着无关因素变化,例如它前后运行了哪些操作,以及是否启用了调试工具。同一个提示词可能在一次请求中完全正常,在下一次请求中失败。

调查期间,我们还发现 exact top-k 操作不再像过去那样有令人难以接受的性能惩罚。我们从 approximate top-k 切换到 exact top-k,并将一些额外操作标准化为 fp32 精度。[4] 模型质量不可妥协,因此我们接受了轻微的效率影响。

为什么检测很困难

我们的验证流程通常依赖基准测试、安全评估和性能指标。工程团队会先做抽查,并部署到小规模 "canary" 组。

这些问题暴露了我们本应更早识别出的关键缺口。我们运行的评估根本没有捕捉到用户报告的质量下降,部分原因是 Claude 往往能从孤立错误中很好地恢复。我们自己的隐私实践也给调查报告带来了挑战。我们的内部隐私和安全控制限制了工程师访问用户与 Claude 交互的方式和时机,尤其是当这些交互没有作为反馈报告给我们时。这保护了用户隐私,但也阻止工程师检查识别或复现 bug 所需的问题交互。

每个 bug 在不同平台上以不同频率产生不同症状。这造成了混杂的报告,无法指向任何单一原因。它看起来像随机、不一致的质量下降。

更根本的是,我们过度依赖了噪声较大的评估。虽然我们知道网上报告有所增加,但缺少一种清晰方式将这些报告与最近每项变更连接起来。当负面报告在 8 月 29 日激增时,我们没有立即把它与一个原本标准的负载均衡变更联系起来。

我们正在改变什么

随着我们继续改进基础设施,我们也在改进评估和预防上述 bug 的方式,覆盖所有服务 Claude 的平台。下面是我们正在改变的内容:

  • **更敏感的评估:**为了帮助发现任何给定问题的根因,我们开发了能更可靠地区分正常实现和故障实现的评估。我们会继续改进这些评估,以便更密切关注模型质量。
  • **在更多位置运行质量评估:**虽然我们会对系统运行常规评估,但我们将持续在真实生产系统上运行它们,以捕捉上下文窗口负载均衡错误这类问题。
  • **更快的调试工具:**我们会开发基础设施和工具,更好地调试来自社区的反馈,同时不牺牲用户隐私。此外,这次开发的一些定制工具会用于减少未来类似事件的修复时间,如果此类事件再次发生的话。

Evals 和监控很重要。但这些事件表明,当 Claude 的响应没有达到通常标准时,我们也需要来自用户的持续信号。观察到的具体变化报告、遇到的意外行为示例,以及不同用例中的模式,都帮助我们隔离了问题。

用户继续直接向我们发送反馈仍然特别有帮助。你可以在 Claude Code 中使用 /bug 命令,也可以在 Claude apps 中使用 "thumbs down" 按钮。开发者和研究人员经常会创造新的、有趣的模型质量评估方式,以补充我们的内部测试。如果你想分享你的方法,请联系 feedback@anthropic.com

我们仍然感谢社区作出的这些贡献。

致谢

作者:Sam McAllister。感谢 Stuart Ritchie、Jonathan Gray、Kashyap Murali、Brennan Saeta、Oliver Rausch、Alex Palcuie 以及许多其他人。

[1] XLA:TPU 是优化编译器,会将 XLA High Level Optimizing 语言(通常使用 JAX 编写)翻译成 TPU 机器指令。

[2] 我们的模型太大,无法放在单个芯片上,会被分区到数十个或更多芯片上,使我们的排序操作成为分布式排序。TPU(就像 GPU 和 Trainium 一样)也具有不同于 CPU 的性能特征,需要使用向量化操作而不是串行算法等不同实现技术。

[3] 我们此前一直使用这种近似操作,因为它带来了显著性能提升。近似的工作方式是接受最低概率 token 中潜在的不准确性,而这本不应影响质量,除非该 bug 导致它丢弃最高概率 token。

[4] 请注意,现在正确的 top-k 实现可能会导致 top-p 阈值附近 token 的纳入出现轻微差异,在少数情况下,用户可能会受益于重新调整 top-p 的选择。