你的评测套件也是生产负载:当每晚测试耗尽线上流量配额时
一个团队最成功的 AI 功能在周二凌晨 2:14 宕机了。传呼机显示模型 API 在稳态下返回 429 错误。模型是健康的。供应商是健康的。团队自身的生产流量也是正常的。蚕食额度的是每晚运行的评测套件(eval suite)——正是团队在前一周引以为傲并进行扩展的那个套件。评测系统和产品共享同一个组织密钥(organization key),在那个夜晚,评测系统成了那个打破室友宁静的“吵闹邻居”。
评测系统并没有异常行为。它正在按照开发者的设计运行:针对生产模型标识符(identifier)进行一千个案例的测试,按节奏、按计划运行——这个计划因为已经静默运行了两年,早就被大家遗忘了。这次最终导致超限的扩展增加了三百个案例。该 PR 经过了评测负责人和 Prompt 负责人的审核。评审线程中没有一个人想到要问:这会消耗多少每日 Token 额度?
那个问题——“这个离线负载消耗了生产额度的多少比例?”——是将“视评测为副业”的团队与“视评测为生产任务”的团队区分开来的关键。前者最终在写 复盘报告(post-mortems),后者最终在写仪表盘(dashboards)。
评测不是单元测试
在大多数工程文化中,“测试”一词预设了资源模型。单元测试在托管运行器(hosted runner)的 CI 中运行,其 CPU 由你的平台团队统一买单。增加一个断言的边际成本只是 CI 发票上的四舍五入误差。工程师们很早就学会了肆无忌惮地编写测试,因为测试消耗的资源是同质化且充足的。
LLM 评测继承了“测试”这个词,但完全没有继承其资源模型。增加一个评测案例的边际成本是供应商发票上实打实的扣费,而且——至关重要的一点是——它从支撑公司运营的产品所使用的同一个额度池中扣除。供应商的速率限制通常是按组织(organization)而非按密钥(key)计算的。在同一个组织下创建第二个 API 密钥并不会让你的 TPM 翻倍,它只是瓜分了现有的资源池。如果工程师在心理模型中将评测成本视为“像单元测试一样免费”,那就是在犯一种账单系统会礼貌地拒绝纠正的分类错误。
额度模型是多维的。供应商通常会同时强制执行四个独立的维度:每分钟请求数(RPM)、每分钟 Token 数(TPM)、每天请求数(RPD)和每天 Token 数(TPD)。一个在 TPM 范围内运行良好的负载仍可能突破 RPD。一个在 15 分钟窗口内运行的每晚评测,是针对每日预算的每秒脉冲式冲击,而这恰恰是最难恢复的维度——滚动日窗口不会像每分钟桶那样迅速重新开启。
失败的具体表现
一个典型的事故时间线如下:
- 02:14 AM:评测 Worker 在 1,000 个案例的批处理中启动了第一个案例。
- 02:14:08 AM:评测系统在 8 秒内消耗了 1.8% 的每日 Token 数。
- 02:18 AM:评测进行到第 280 个案例,凌晨 2 点的生产负载流量(虽然小但非零)加入了竞争。
- 02:21 AM:合并使用量突破了每日 Token 上限。
- 02:21 AM 至 04:00 AM:每一个同步生产请求都返回 429。评测本身也开始收到 429,但评测带指数退避(exponential backoff)的重试循环即使在 TPD 耗尽的情况下仍在继续消耗 RPM 预算。
- 04:00 AM:滚动窗口边缘推进到足以让重试成功。
- 09:00 AM:值班工程师看到仪表盘,追踪到原因是评测系统,并在复盘文档中更新了一句以“评测套件按计划运行且”开头的句子。
复盘报告随后提出了本应在设计阶段就提出的问题:为什么允许非生产负载消耗生产容量?而答案总是某种形式的:负责评测准确性的团队和负责供应商额度的团队是不同的,两个团队的评审都没有捕捉到这个交叉限制。
“隔离评测”究竟意味着什么
修复方案在结构上很简单,但在操作上被低估了:为评测提供独立的供应商账号,或者至少是独立的组织(organization),并拥有独立的额度池。评测账号糟糕的一天不会变成生产账号糟糕的一天,因为它们在供应商的账单系统中是不同的账号。这是供应商中立的网关工具(gateway tools)一直在悄悄推行的标准做法,也是直接对接供应商 API 的团队往往会跳过的一步,因为没有人的操作手册(runbook)会告诉他们这样做。
具体来说,“隔离评测”可以分解为以下几项决策,且它们的性质各不相同:
- 账号级隔离。 为评测设立独立的供应商组织。这是最强有力的形式,因为供应商的速率限制是在组织层级执行的。代价是运营成本:多了一层账单关系、多了一个需要管理的席位、多了一份需要核对的发票。好处是失控的评测绝不会让生产环境饿死,彻底解决问题。
- 网关级隔离。 由内部 LLM 网关签发的虚拟密钥,具有独立于生产虚拟密钥的预算上限和速率上限。评测负载底层仍与同一个供应商组织通信,但网关会在供应商之前对其进行限流。这比账号级隔离成本更低,但留有残余风险:在供应商层级,这两个负载仍共享一个池,任何池级限制都适用于两者之和。
- 代码级隔离。 在评测上设置 Worker 池并发上限,并向评测调度器提供背压(backpressure)。这是最弱的形式。它假设评测作者能准确预测评测的最坏情况额度消耗,而这恰恰是最初事故证明不可靠的预测。
最强的形式推理起来最简单,但设置起来最昂贵。大多数团队停留在中间选项并以此为准,只要团队理解网关无法保护他们免受哪些风险,这就是合理的。
那个没人会在 PR 审查中提出的问题
当一个 PR 增加了 300 个评估(eval)用例时,审查线程里为什么没人询问对配额(quota)的影响,其结构性原因是什么?在大多数组织中,评估文件存放在 /evals 目录下,diff 看起来就像数据——YAML 或 JSON 测试用例,有时是对运行脚本的微小改动。对数据文件的代码审查往往会形成一种浅尝辄止的反射动作。审查者在寻找拼写错误、格式错误,或者重复的标签。审查者不会去对每天的 token 消耗量进行粗略的估算。
一种有效的干预手段是让计算自动化。评估框架可以在每次运行结束时发送一行遥测数据:本次评估消耗了 N 个 token;生产环境每日配额为 M;本次评估消耗了每日配额的 N/M。 当这个数值超过某个阈值时——对于每天运行一次的工作负载,5% 是一个合理的起点;对于运行更频繁的工作负载,这个比例应该更低——该 PR 就必须获得配额负责人的签准(sign-off)。这种规范通过数字而非会议弥合了跨团队之间的鸿沟。
阈值的大小不如“数值门槛”的存在重要。那些依赖“评估负责人觉得没问题”的团队,最终会发布导致生产环境崩溃的扩展。而那些依赖“预计每日配额消耗低于 5%”的团队则不会,因为数字不再是主观意见。
评估调度是一项容量决策
即使配额是隔离的,评估运行的“时间点”也很重要。凌晨 2 点运行的评估是“礼貌”的,因为在大多数时区,凌晨 2 点是自然流量最低的时候。而下 午 2 点运行的评估则是“敌对”的,因为即便每日预算充足,下午 2 点也会在每分钟的并发请求中竞争相同的资源。
调度不仅仅是为了延迟层面的礼貌,更关乎故障模式的局部性。如果评估和产品共享任何维度的容量,运行时间的选择将决定评估故障与产品故障是正相关还是负相关。大多数团队希望的是负相关:评估应该在生产环境空闲时全力运行,这样生产环境流量高峰期的配额消耗就不会与评估的高峰重叠。
一种合理的调度策略包含三个部分:
- 评估运行在产品最繁忙时区的流量最低窗口。 这是最廉价且最易理解的杠杆。
- 当生产环境配额利用率超过上限时,暂停评估。 在评估调度器上设置一个断路器,检查生产环境网关最近的利用率,如果产品消耗了超过(例如)70% 的 TPM,则推迟下一批次。这会让评估损失一些完整性——每个季度会有几个晚上评估运行不全——但代价是换取了任何评估扩展都不会与流量激增产生共振。
- 即使在不竞争时,评估也会自我限流。 在评估工作程序上设置一个自发的 RPM 上限,远低于供应商的层级限制,这样评估中的 bug(例如意外重复的批处理、配置错误的循环)就不会在有人察觉之前耗尽配额池。
第三项经常会遭到反对,因为它会降低评估速度。评估负责人希望在早上拿到结果;而自设的上限可能会将运行时间从 15 分钟延长到 40 分钟。权衡逻辑很简单:一个不会耗尽预算的慢速评估,绝对比一个可能导致预算爆炸的快速评估更廉价。供应商的账单是用美元支付的,而评估延迟是用等待时间支付的。
必须存在的告警
独立于上述所有预防措施,有一项可观测性指标是不可或缺的:当任何非生产工作负载消耗超过共享配额的特定比例时,必须触发告警。该告警设置在网关或供应商的使用情况控制面板上,通过虚拟密钥或 API 密钥对流量进行细分,并在滑动窗口上运行——而不只是针对每日总量。
告警是最后的安全网。早期的预防措施旨在确保这种情况永远不会发生。而告警则假设预防措施最终会失效——比如在未经过审查的情况下添加了新的工作负载、虚拟密钥配置错误、或者开发人员将生产环境凭证复制到了临时脚本中——并在影响客户之前给值班人员(on-call)一个捕获问题的机会。
告警阈值应该比供应商自身的限制更严格。如果供应商在 100% TPM 时限流,告警应该在 70% 时就触发。告警的意义在于,在供应商不再“客气”之前,给人工干预留出反应时间。
架构上的领悟
一个调用付费 API 的评估套件其实就是一个生产工作负载,其 SLO 是不得破坏其所评分的系统。一个没有明确说出这个 SLO 的团队,距离一次评估扩展导致的自发故障仅有一步之遥,到时候的复盘报告读起来会像喜剧:“工程团队的质量保证流程消耗了所有的质量,导致客户无质可用。”
更深层的感悟是,“生产环境”从来不在于代码是否在特定环境中运行,也不在于流量是否来自特定用户。生产环境是客户会感知到其故障的工作负载集合 。根据这个定义,一个竞争生产配额的评估套件就是生产环境——它的故障就是生产故障,只是通过一个不太明显的机制传导。
明白这一点的团队,不再像审查单元测试变更那样审查评估变更。他们开始像审查容量变更一样审查评估变更:有预算、有阈值、有签准,还有紧急开关。评估变成了与其评分的工作负载地位对等的同伴,而不是一个白嫖房间的房客。
- https://developers.openai.com/api/docs/guides/rate-limits
- https://inference.net/content/openai-rate-limits-guide/
- https://devtk.ai/en/blog/ai-api-rate-limits-comparison-2026/
- https://tokenmix.ai/blog/ai-api-rate-limits-guide
- https://learn.microsoft.com/en-us/azure/api-management/llm-token-limit-policy
- https://learn.microsoft.com/en-us/azure/foundry/openai/quotas-limits
- https://www.clawpulse.org/blog/llm-api-rate-limiting-best-practices-avoid-429-errors-and-save-40-on-costs
- https://www.datawiza.com/blog/industry/llm-api-key-management-and-identity-aware-rate-limiting/
- https://www.datawiza.com/blog/industry/why-shared-llm-api-keys-break-enterprise-ai-development/
- https://www.datawiza.com/blog/industry/per-app-and-per-agent-rate-limits-for-llm-apis/
- https://portkey.ai/blog/rate-limiting-for-llm-applications/
- https://portkey.ai/blog/tracking-llm-token-usage-across-providers-teams-and-workloads/
- https://werun.dev/blog/how-to-handle-llm-api-rate-limits-in-production
- https://orq.ai/blog/api-rate-limit
- https://docs.helicone.ai/features/advanced-usage/custom-rate-limits
- https://www.truefoundry.com/blog/rate-limiting-ai-agents-preventing-llm-api-exhaustion
- https://www.truefoundry.com/blog/rate-limiting-in-llm-gateway
- https://agentgateway.dev/blog/2025-11-02-rate-limit-quota-llm/
- https://www.braintrust.dev/articles/turn-llm-production-failures-into-regression-tests
- https://www.braintrust.dev/articles/llm-evaluation-guide
- https://www.braintrust.dev/articles/how-to-track-llm-costs-2026
- https://www.hivenet.com/post/llm-rate-limiting-quotas
- https://www.getmaxim.ai/articles/how-to-set-up-virtual-keys-for-llm-access-control/
- https://reintech.io/blog/llm-rate-limiting-quota-management-production-best-practices
