三起近期问题的故障复盘
从 8 月到 9 月初,三项基础设施 Bug 间歇性地降低了 Claude 的响应质量。我们现在已经解决这些问题,并希望解释到底发生了什么。
8 月初,一些用户开始反馈 Claude 的响应质量下降。最开始,这些报告很难与正常的用户反馈波动区分开来。到了 8 月下旬,相关反馈的频率和持续性不断增加,促使我们正式展开调查,并最终发现了三个彼此独立的基础设施 Bug。
需要明确说明的是:
我们绝不会因为需求量、一天中的时间,或者服务器负载而主动降低模型质量。
用户所报告的问题,完全是基础设施 Bug 导致的。
我们知道,用户期望 Claude 始终保持一致的质量,而我们对基础设施变更是否会影响模型输出,一直有非常高的标准。在这些近期事件中,我们没有达到这一标准。
这篇复盘将解释:
- 到底哪里出了问题;
- 为什么发现和解决问题所花的时间,比我们期望的更长;
- 我们准备做哪些改动,以避免类似问题再次发生。
我们通常不会公开这么多基础设施层面的技术细节。
但由于这次问题的范围和复杂度都比较高,我们认为有必要做一次更加完整的说明。
我们如何大规模提供 Claude 服务
我们通过多个渠道向数百万用户提供 Claude,包括:
- 第一方 API;
- Amazon Bedrock;
- Google Cloud Vertex AI。
Claude 会被部署在多种不同硬件平台上,主要包括:
- AWS Trainium;
- NVIDIA GPU;
- Google TPU。
这种方式可以提供:
- 足够的总容量;
- 足够广泛的地理分布;
从而为全球用户提供服务。
但不同硬件平台拥有不同特性,也需要不同的针对性优化。
尽管如此,我们对不同平台上的模型实现有非常严格的:
等价性标准。
目标是:
无论一个请求最终由哪种硬件平台处理,用户都应该得到质量一致的回答。
但这种复杂性也意味着:
任何基础设施改动,都必须在不同:
- 硬件平台;
- 配置;
上进行仔细验证。
事件时间线
这几个 Bug 的重叠,是整个问题最难诊断的原因之一。
第一个 Bug 在:
8 月 5 日
被引入。
它影响了大约:
0.8% 的 Sonnet 4 请求。
之后又有两个 Bug,分别来自:
8 月 25 日和 26 日
的部署。
一开始,它们造成的影响都比较有限。
但:
8 月 29 日
的一次负载均衡改动,开始让受影响的流量比例增加。
于是:
- 越来越多用户开始遇到问题;
- 同时另一些用户的体验依然完全正常。
这就造成了非常混乱、甚至彼此矛盾的反馈。
三个互相重叠的问题
下面分别说明三个导致质量下降的 Bug:
- 什么时候发生;
- 造成了什么影响;
- 我们如何解决。
1. 上下文窗口路由错误
8 月 5 日,一部分 Sonnet 4 请求被错误路由到了一批原本为即将推出的:
100 万 Token Context Window
配置的服务器。
最开始,这个 Bug 只影响:
0.8% 的请求。
但 8 月 29 日的一次常规负载均衡调整,无意中让更多短上下文请求被送进了 100 万 Token Context Server。
最严重的时间点是在:
8 月 31 日。
当时某一个小时内:
16% 的 Sonnet 4 请求
都受到了影响。
大约:
30% 的 Claude Code 用户
如果在这段期间发送过请求,至少有一条消息被路由到了错误的服务器类型,从而得到质量下降的回答。
在 Amazon Bedrock 上,从 8 月 12 日开始:
错误路由流量的峰值占所有 Sonnet 4 请求的:
0.18%。
在 Google Cloud Vertex AI 上:
8 月 27 日到 9 月 16 日之间,
错误路由影响了不到:
0.0004% 的请求。
不过,有些用户受到的影响会比平均值严重得多。
因为我们的 Routing 是:
Sticky Routing。
也就是说:
一旦某个请求被错误服务器处理,
之后的后续对话很可能继续落到同一个错误服务器上。
解决方案
我们修复了路由逻辑,确保:
- 短上下文请求;
- 长上下文请求;
分别被送往正确的 Server Pool。
修复在:
9 月 4 日
完成部署。
随后:
- 第一方平台和 Google Cloud Vertex AI:9 月 16 日前完成全部 Rollout;
- AWS Bedrock:9 月 18 日前完成全部 Rollout。
2. 输出损坏
8 月 25 日,我们向 Claude API 的 TPU Server 部署了一个错误配置。
它会在 Token 生成过程中触发异常。
问题来自一个 Runtime Performance Optimization。
这个优化在某些情况下,会错误地给一些按当前上下文来说:
本不应该高概率出现的 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 日,我们部署了一段用于改进 Claude 文本生成期间 Token 选择逻辑的代码。
这个改动意外触发了 XLA:TPU 编译器中的一个潜在 Bug。
我们已经确认:
这个 Bug 会影响:
Claude Haiku 3.5。
我们也认为:
它可能影响了 Claude API 上的一部分:
- Sonnet 4;
- Opus 3。
第三方平台没有受到影响。
解决方案
我们最先在:
Haiku 3.5
上观察到这个 Bug。
于是:
9 月 4 日
我们进行了回滚。
后来,我们注意到部分 Opus 3 用户报告的问题与这个 Bug 的表现一致。
因此:
9 月 12 日
我们也对 Opus 3 回滚了相关改动。
经过大量调查后,我们始终无法在 Sonnet 4 上稳定复现同样问题。
不过出于谨慎考虑:
我们还是决定把相关改动也从 Sonnet 4 中撤掉。
与此同时,我们也并行推进了两项工作:
- 与 XLA:TPU 团队合作修复编译器 Bug;
- 切换到更高精度的 Exact Top-K 实现。
下面详细解释这个问题。
深入理解 XLA 编译器 Bug
这个问题非常适合说明:
为什么这类基础设施错误很难诊断。
Claude 在生成文本时,会为所有可能的下一个 Token 计算概率。
然后:
从这个概率分布中随机采样一个 Token。
为了避免输出非常荒谬的低概率 Token,我们使用:
Top-P Sampling。
也就是:
只考虑累计概率达到某个阈值之前的那些 Token。
常见阈值是:
- 0.99;
- 0.999。
在 TPU 上,我们的模型运行在:
多个芯片之上。
所以概率计算也分散在不同位置。
为了对这些概率排序,我们必须:
在多个 Chip 之间协调数据。
这本身就是一项复杂操作。[^1]
2024 年 12 月发现的第一个问题
2024 年 12 月,我们发现:
TPU 实现中,
当:
temperature = 0
时,
系统偶尔会:
把最高概率 Token 丢掉。
于是我们部署了一个 Workaround。
最开始,我们以为这个 Bug 已经被绕过去了。
但后来发现:
它只是更深层问题的一部分。
根因:混合精度计算
模型使用:
bf16
也就是 16-bit 浮点数,
来计算 Next-token Probability。
但 TPU 的 Vector Processor 原生使用:
fp32
也就是 32-bit 浮点数。
因此,TPU Compiler,也就是 XLA,会为了提高运行效率:
把某些运算自动提升为 fp32。
这个优化由:
xla_allow_excess_precision
控制。
默认值是:
true
于是问题出现了。
一些理论上应该对:
哪个 Token 概率最高
达成一致的操作,
实际上使用了不同精度:
- 有的使用 bf16;
- 有的使用 fp32。
因为精度不同,
它们偶尔会对:
哪个 Token 才是最高概率
产生不同结论。
结果就是:
真正最高概率的 Token,
有时会直接从候选集合中消失。
8 月 26 日的重写
8 月 26 日,我们部署了新的 Sampling Code。
目标是:
- 修复精度问题;
- 改进靠近 Top-P Threshold 边缘的概率处理。
在修复这些问题后,我们认为:
12 月的那个 Workaround 已经不再需要。
于是把它移除了。
但正是在这里,我们暴露出了一个更加隐蔽的问题:
Approximate Top-K Operation 的 Bug。
什么是 Approximate Top-K
Approximate Top-K 是一个性能优化。
它的目标是:
快速找出概率最高的一小批 Token。
作为近似算法,它本来就允许:
对那些最低概率 Token 有少量误差。
理论上:
这不应该影响模型质量。
因为那些 Token 本来就几乎不可能被选中。
但实际 Bug 的行为是:
有时它会直接:
把真正最高概率的 Token 丢掉。
而且只会在某些:
- Batch Size;
- Model Configuration;
下发生。
之前那个 12 月 Workaround:
无意中掩盖了这个问题。
这个 Bug 的行为极其不稳定
它最麻烦的地方是:
表现会随着一些理论上毫不相关的因素改变。
比如:
- Approximate Top-K 之前运行了什么操作;
- 之后运行了什么操作;
- Debug Tool 是否启用。
于是:
同一个 Prompt,
可能:
- 这一次完全正常;
- 下一次突然失败。
这让问题的定位非常困难。
最终切换到 Exact Top-K
在调查过程中,我们还发现:
过去曾经性能开销很高的:
Exact Top-K
现在已经不再那么昂贵。
于是我们决定:
彻底从 Approximate Top-K 切换到 Exact Top-K。
同时还把一些额外操作统一到:
fp32 Precision。
这会带来少量效率损失。
但我们的原则很明确:
模型质量不可妥协。
为什么这些问题如此难被发现
我们的常规验证流程通常依赖:
- Benchmark;
- Safety Eval;
- Performance Metric。
工程团队还会:
- 人工 Spot Check;
- 先向小规模 Canary 用户部署。
但这次事件暴露出了一些我们本应该更早识别的缺口。
现有 Eval 没有捕捉到用户看到的问题
我们运行的评测并没有稳定捕捉到用户反馈的质量下降。
原因之一是:
Claude 在发生单次错误后,
经常能够:
很好地自我恢复。
因此:
Eval 可能观察到一次错误,
但最终回答仍然看起来可以接受。
而真实用户可能更敏感地感觉到:
- 逻辑突然不稳定;
- 风格异常;
- 中间推理出现怪异行为。
隐私实践也增加了调查难度
我们内部有严格的:
- 隐私;
- 安全控制。
这些控制会限制工程师:
什么时候、以什么方式
能够访问用户与 Claude 的实际交互内容。
特别是:
如果用户没有明确把那段交互作为 Feedback 提交给我们,
工程师往往无法直接查看。
这很好地保护了用户隐私。
但也意味着:
当某个 Bug 只在特定真实交互中出现时,
工程师更难:
- 查看问题样本;
- 重现 Bug;
- 定位根因。
三个 Bug 的表现不同
这三个 Bug:
- 在不同平台;
- 以不同频率;
- 产生不同症状。
于是外部反馈看起来就像:
随机、不一致的质量下降。
没有一个单一症状,可以直接指向同一个根因。
我们过度依赖高噪声 Eval
更根本的问题是:
我们太依赖:
噪声较大的评测。
我们已经注意到网上负面反馈在增加。
但我们没有一个清晰机制,把这些信号和:
最近的某一次基础设施改动
明确关联起来。
例如:
当 8 月 29 日负面反馈突然增加时,
我们没有立刻想到:
这可能和一次看起来非常普通的负载均衡改动有关。
接下来我们会做什么
随着基础设施继续演进,我们也在改进:
所有 Claude Serving Platform 上,
用于发现和预防这类问题的方法。
主要变化包括以下几类。
更敏感的 Eval
为了帮助定位具体问题根因,我们已经开发了一些新的评测。
这些 Eval 更擅长区分:
- 正常模型实现;
- 已经损坏的模型实现。
未来我们还会继续加强这些测试,
让模型质量变化更容易被观察到。
在更多地方运行质量评测
我们一直会定期运行模型 Eval。
但之后会进一步:
直接在真实生产系统上持续运行。
这样可以捕获:
只在真实 Routing、Load Balancing、Hardware Pool 组合下才出现的问题。
比如这次:
Context Window Load Balancing Error
就属于典型案例。
更快的 Debugging Tool
我们会建设新的基础设施和工具,
在不牺牲用户隐私的前提下,
更好地分析:
来自社区的反馈。
此外,这次事故期间临时开发的一些专用工具,
未来也会被保留下来。
目标是:
如果以后再遇到类似事故,
能够显著缩短:
Remediation Time。
用户信号依然非常重要
Eval 和 Monitoring 很重要。
但这次事件也说明:
我们仍然需要来自真实用户的持续信号。
尤其是:
当 Claude 回答质量明显低于平时水平时。
以下反馈特别有价值:
- 你观察到的具体变化;
- 某个意外行为的完整案例;
- 不同使用场景中反复出现的模式。
这些反馈帮助我们最终隔离出了:
此次事故中的多个问题。
因此,我们仍然非常希望用户继续直接反馈异常行为。
开发者和研究人员经常会设计一些新的模型质量评测方法。
这些外部方法可以很好地补充内部测试。
我们也非常感谢社区持续提供这些贡献。
总结
这次事件不是一个单一 Bug。
而是三个基础设施问题:
- 上下文窗口路由错误;
- 输出 Token 损坏;
- XLA:TPU Approximate Top-K 编译问题;
在相似时间段内重叠发生。
这使得:
- 外部症状互相混杂;
- 平台影响范围不同;
- 单个 Eval 很难复现;
- Debugging 过程显著变慢。
这次复盘暴露出一个很重要的事实:
模型 Serving 基础设施中的“正确性”,不仅仅是系统还能不能运行。
系统可以:
- 不 Crash;
- Latency 正常;
- Throughput 正常;
但模型质量仍然可能已经发生退化。
因此:
模型质量本身必须被当作一种生产系统健康指标持续监控。
而且:
它需要真正运行在生产路径上,
而不是只在离线测试环境中验证。
- 点赞
- 收藏
- 关注作者
评论(0)