在上个季度的某个时候,你团队的一名工程师在 Slack 上发了一个帖子,开头是“模型变慢了”。他们展示了一张图表:你的助手功能的 p95 延迟从早上 7 点开始稳步攀升,在东部时间上午 10 点左右达到顶峰,午餐期间处于平台期,并在下午 5 点后悄然恢复。这种形态在第二天、第三天不断重复。团队追溯了他们的部署记录,指责了分词器(tokenizer)的更改,接着是上下文长度的退化,最后发现没什么是特别确定的。修复方案从未落地,因为 Bug 根本不在你的代码里。
顶尖模型提供商运行着共享的推理集群。当你的用户醒来时,北美其他地区也醒了,再加上欧洲的下午,以及每一家购买了相同 API 的公司的每一个内部工具。提供商端的队列深度翻倍,GPU 竞争加剧,你的 p95 延迟也随之翻倍——而你的代码库没发生一行代码变更。这是你技术栈中最可预测的生产事故,但几乎没有团队会为此建立仪表板。
曲线的形态
公共延迟追踪器和提供商的事后分析都指向了同一种每日节奏。工作日期间,美国托管的主要端点峰值负载大致在东部时间上午 8 点到下午 2 点之间,在晚餐后当消费级聊天流量回升时会出现一个较小的次峰。非高峰时段——比如东部时间午夜到凌晨 6 点——在相同工作负载下的运行速度通常快 30% 到 40%,在长提示词(long prompts)情况下有时甚至更快,因为此时的首字时间(time-to-first-token)主要受预填充(prefill)调度的影响,而非解码吞吐量(decode throughput)。
这种波动不会以“停机”的形式表现出来。没有 5xx 错误,没有速率限制错误,提供商的状态页面也没有任何异常。请求仍然可以完成,只是耗时更长。凌晨 4 点只需 4 秒就能完成的工作负载,在上午 10 点可能需要 9 秒,而你的链路追踪工具会静默地将两者合并到同一个直方图中。如果你按天汇总,日平均值看起来很正常,日 p95 看起来就像是噪声。信号完全隐藏在你丢弃的时间维度中。
研究工作负载已经直接测量到了这一点。2025 年一篇关于系统论文发布的为期两个月的校园 ChatGPT 使用追踪显示,请求率在几分钟内波动高达 3 倍,同时遵循更广泛的昼夜模式,运营商被迫按峰值过度配置 GPU,仅仅为了在糟糕的时段维持其服务水平目标(SLO)。这种过度配置也是你的提供商所做的,但仅限于合同预算范围内——剩下的负载则以延迟的形式转嫁到了你身上。
为什么你的仪表板隐藏了它
大多数团队设置延迟监控的方式就像设置数据库延迟监控一样:在一个采样窗口内汇总直方图,在单张图表上显示 p50、p95 和 p99 线。对于负载由你控制的服务,这是正确的形态。但对于负载由他人的流量主导的服务,这就是错误的。
聚合隐藏了双峰性。如果 30% 的流量落在非高峰时段,70% 落在高峰时段,你的 p95 反映的是一种加权混合,没有任何单个用户会体验到这种数值。凌晨 2 点的批处理作业和上午 10 点的客户电话通过同一个客户端连接,并计入同一个桶中,尽管它们在延迟维度上处于完全不同的世界。仪表板读数显示为“尾部方差较高的稳定状态”,而事实是“两个稳定的状态,中间有一个确定性的切换”。
修复方法并不复杂:按小时进行分群(cohort by hour-of-day)。将同一个直方图切成 24 个子直方图,每小时一个,并以热力图的形式展示。昼夜模式会立即显现——通常是 UTC 时间 13:00 到 19:00 的一条“热带”,在周末会褪去。叠加分区域延迟,你可以看到欧洲的早晨在北美醒来之前就开始拉升曲线。一旦你拥有了这个视角,每一个模型端的延迟问题在寻找答案的路上都会多出一列:这个用户是在“糟糕时段”吗?
你实际能做些什么
好消息是,问题的形态本身就暗示了补救措施。坏消息是,这些措施都不是免费的。
迁移不需要同步进行的工作。 两大主要的提供商都提供批处理端点(batch endpoints),提供 50% 的折扣和 24 小时的完成窗口。在我审计过的系统中,大多数生产环境的 AI 功能都有相当一部分(20% 到 40%)工作其实不需要实时响应:每日总结、嵌入(embedding)刷新、评估运行、内容审核的回填。通过批处理 API 路由这些任务,可以将它们从你的交互式延迟曲线中移除,并将成本减半。基础设施投入仅为一个队列和一个消费者;省下的折扣在第一天就能抵消这笔开销。
调度可调度的任务。 令人惊讶的是,很大一部分 AI 工作负载是由选择了“整数时间”的人类调度的。报告在上午 9 点运行,是因为五年前有人在配置里写了“9am”。嵌入“每天早上”刷新,是因为 cron 模板默认就是那样。如果一项任务在上午 10 点需要 40 分钟,而在凌晨 3 点只需 22 分钟,且直到中午才有人看输出,那么你就是在无缘无故地支付“高峰税”。审计你的调度 AI 工作负载,并将截止日期宽松的任务移至非高峰时段。节省不仅体现在更快的任务完成速度上,还体现在由于你停止了与自己争抢速率限制配额,从而降低了同步流量的峰值负载。
将提供商负载视为路由输入,而非属性。 多提供商网关已经足够成熟,延迟感知路由(latency-aware routing)已不再新鲜。其模式很简单:在滚动窗口中跟踪每个提供商的 p95,当一个提供商开始偏离正常区间时,将一定比例的流量切换到备份。即使是 Anthropic 的 Priority Tier 也不提供延迟保证;OpenAI 的 Priority Tier 在开发者论坛上也有关于波动的投诉。两者都可以互为备份,或者备份到在你控制的基础设施上运行的开源权重模型的区域部署。难点不在于路由逻辑,而在于保持提示词契约(prompt contracts)和工具模式(tool schemas)具有足够的通用性,以便你能够真正实现故障切换。
尽可能预热预填充。 在提供商支持的情况下,提示词缓存(prompt caching)在高峰时段最有价值,因为那时预填充竞争最为激烈。缓存的系统提示词或检索到的上下文可以将 Anthropic API 的首字时间缩短一个数量级,在 OpenAI 上也有类似的比例。缓存的设置是免费的,而且在你会注意到昼夜延迟的业务规模下,缓存输入 Token 的折扣是实实在在的真金白银。如果你今天还没有缓存提示词中稳定的部分,那么高峰时段就是你为这个决定付出最高昂代价的时候。
架构转向
核心的转变在于,不再将供应商负载视为固定的环境属性,而是将其作为一等公民的调度输入。具体来说,这意味着你的推理层不再是仅仅指向单个端点的单一客户端。它是一个路由器,能够识别哪些工作负载是交互式的,哪些不是;哪些供应商当前状态良好,哪些正在降级;以及哪些工作负载可以推迟到成本更低的时间窗口。
一旦实现了这一点,“今天的模型慢吗?”这个问题就变成了一个更有价值的问题:鉴于当前的负载曲线,现在哪些工作负载应该在主供应商上同步运行,而哪些应该进行批处理、推迟或故障转移?答案在上午 9 点和晚上 9 点会截然不同,而你的系统可以每分钟询问一次。
这种投入还具有二阶效应,使其价值远超一周看板上显示的数字。供应商负载不仅仅是延迟问题,更是可靠性问题。产生最慢尾部延迟的那些时段,通常也会产生最高的超时率、瞬时 5xx 错误,以及在负载下供应商将你路由到更小模型时产生的无声质量退化。一个能够感知负载曲线并能据此重新路由的系统,也是一个无需人工介入即可从真实的供应商故障中恢复的系统,因为故障转移机制已经在日常场景中磨合完毕。
忽视代价
那些没有针对昼夜延迟波动作出设计的团队,最终会同时在三个方面付出代价。他们在原本应该进行批处理的工作负载上过度支出了实时推理费用,承担了高峰时段的全额价格。他们浪费工程师的时间去追踪那些原因仅仅是由于“日历时间”导致的幻觉般的性能退化。而且,他们向最有价值的用户交付了更糟糕的产品——这些用户在上午 10 点的工作时间内使用工具,从未见过该工具在凌晨 6 点时本可以达到的运行速度。
这一切都不需要深度的 ML 基础设施工作。它只需要你承认,AI 功能的延迟下限是由你从未见过的人决定的,并据此进行设计。那些率先在 AI 延迟看板的 X 轴上引入“一天中的小时”的团队,通常会发现困扰了他们一个季度的 Bug 就清晰地呈现在眼前,仿佛在质问为什么之前没人注意到。
会员专享
余下内容仅对会员开放。
会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
- —完整文章,包含未公开存档的部分
- —可落地的工作框架,附带权衡与决策依据
- —新文章抢先看,先于公开发布
随时取消 · 一次订阅,畅读全部