用达标请求量衡量大模型服务容量
文章以满足延迟、输出有效性与安全要求的请求量作为容量核心指标,而非只看峰值 token 吞吐。压测应覆盖真实流量形态和完整请求路径,并区分首 token 延迟与生成耗时。
AI 深度解读
LLM 服务能扛多少流量,不能只看每秒生成多少 token,也不能拿供应商的配额当答案。作者提出的判断标准是:在真实请求组合下,每秒能交付多少个按时完成、内容合格、权限与安全检查都通过的任务,以及每个合格任务究竟花了多少钱。
这是一套面向托管 API、自建推理和混合路由的压测协议,没有提供哪种方案更快、更省的实测结论。它值得读的地方,是把「模型跑得动」变成了可以验收的产品容量。
容量应该数合格任务,不能只数 token
作者把核心指标称为 goodput,可以理解为「有效完成速率」。请求必须在对应任务的截止时间前完成,输出有效,通过质量检查,满足必要的结构要求,并且没有绕过安全或授权控制,才能计入。
按时返回错误答案,以及正确答案迟到,都不算有效产出。
这比吞吐量更接近用户感受。服务器可以持续生成大量 token,同时让队列越积越长;看板上的吞吐量很好看,用户却一直等不到能用的结果。
原文用下面三个公式区分有效产出、接受比例和目标违约比例:
accepted_goodput = accepted_requests / measurement_seconds
acceptance_rate = accepted_requests / offered_requests
SLO_miss_rate = requests_missing_latency_or_quality_gate / completed_or_offered_requests
要盯住最后一行的分母:completed_or_offered_requests 表示需要选择并公开统计口径。过载后立即拒绝的请求,也必须计入输入工作负载的失败结果,不能从统计中消失。
计时边界也要先定。交互式应用应从接受用户操作开始,到用户拿到完整、可操作的响应结束,覆盖网络、网关、排队、检索、模型输入处理、生成、工具调用、校验,以及影响等待感知的页面渲染。只测模型服务器耗时,就只能叫模型服务器耗时。
流式输出尤其需要拆开看:TTFT 是首个 token 的等待时间,TPOT 是每个输出 token 的耗时,完整响应耗时则决定任务何时真正结束。首字快,不代表任务完成快。涉及工具时,还要记录每个工具的耗时和连续模型调用轮数。
SLO,即服务级别目标,应由任务决定。实时辅助和隔夜批处理可以接受的等待时间不同;报告 p95、p99 时,也必须附上任务类别、样本数、统计窗口和纳入规则。
为什么压测必须让请求按计划到达
闭环压测会等前一个请求结束,再发送下一个。服务越慢,压测端发得越少,过载反而可能被藏起来。
开环压测让请求按照独立计划到达,不随响应速度自动减量,因此能暴露积压。作者引用的 InferBench 采用了包含 Poisson 到达和突发流量的开环设计,同时报告吞吐量、TTFT、TPOT 和受延迟约束的 goodput。
这里的证据有边界:InferBench 摘要提到对六个服务系统、一个 13B 模型的评估,但作者指出,公开摘要中的结果句缺少数值,下载也尚不可用。因此,能借鉴的是测量设计,不能补写性能数字,更不能把它当成已独立复现的结论。
测试前,先冻结工作负载。作者要求至少三个请求类别,记录典型输入、长上下文输入、典型输出和最大输出,覆盖短问答、摘要、结构化提取、检索、工具调用,以及拒绝或转人工场景。能用 tokenizer 就不要按字符数猜 token 数。
测试集应来自可合法使用的产品记录;没有真实记录,就明确标注为设计工作负载。提示词、检索文档、工具响应和预期检查都应版本化,保存提示词哈希。清单字段包括 case_id、class、input_tokens、expected_output_schema、safety_case、tool_calls_expected、priority 和 quality_check。
随后依次测试低负载、中等负载、预计峰值,以及高于峰值的短时突发。每阶段之间观察队列能否排空,冷启动与稳态分别报告。接近通过门槛的结果至少重复一次;波动很大时,先查原因,不能直接取平均。
整个过程还要冻结模型版本、region、API tier、API version、部署镜像、GPU 配置、自动扩缩容策略和输出上限。结论只对这些条件成立。
能扛住峰值,还要能从过载中恢复
生产限额不能设成「某次测试刚好通过的最高流量」。作者建议寻找尾延迟、队列年龄、拒绝率、错误率、输出有效性、安全检查或单位有效成本开始恶化的位置,再在下方留出明确余量。余量取多少属于业务决策,原文没有给通用比例。
请求之间的成本差异也不能抹平。长上下文会改变输入处理和内存需求,工具循环会增加模型调用次数。因此既要测混合流量,也要单测各类别,检查昂贵任务是否挤占关键任务。
自动扩容需要独立验收:多久发现流量上涨,多久分配资源,预热期间请求在哪里等待。如果扩容发生在突发结束之后,它就没有保护这次突发。
重试同样会吃容量。应用、SDK、代理和 worker 各自重试,可能让一次用户操作变成多次下游请求。作者要求指定一个重试负责人,限制尝试次数,使用带随机抖动的指数退避,并设置全局重试预算。校验错误、授权失败不应重试;动作可能已执行时,需要幂等或核对机制。
队列则要同时限制长度和等待年龄。降级可以缩短答案、跳过非必要检索,或把批处理转成异步,但每种降级都要重新定义允许输出及质量门槛,不能为了跑分移除权限检查。
成本也必须跟着有效任务算。原文给出的账本是:
cost_per_accepted_task =
(provider_or_GPU_cost + retrieval + tools + storage + observability
+ retries + human_review + allocated_operations_cost)
/ accepted_tasks
关键是分母 accepted_tasks。应把失败尝试、重试及必要人工修正等成本纳入账本,避免错误响应越便宜,路线看起来越划算。托管方案还要记录缓存 token、batch 折扣、服务层级和失败收费;自建方案要计入闲置资源、运维与冗余;混合路由可能同时支付两家供应商的尝试费用。
我的判断
我赞同把延迟、质量和安全设为硬门槛,再比较容量与成本。对需要结构化结果或工具执行的应用,这比 token 吞吐量更有决策价值,也能防止「快速失败」美化看板。
但这份原文是一套提议中的采购与验收协议,没有团队实践结果,也没有托管、自建和混合路线的对照数据。Google SRE 提供的是排队、异构请求和重试的系统原则;EY 提供的是成本分类框架,都不能直接证明某条 LLM 路线更划算。
落地难点在于质量基线。JSON 能解析、字段齐全,比较容易自动检查;开放式答案是否可用,则需要明确评分规则、盲审样本和分歧记录。模型裁判也只是测量工具,不能自动充当标准答案。
这套方法与供应商基准、模型排行榜可以互补。后者帮助缩小候选范围,前者验收完整业务链路。通过测试也不等于证明长期可用性,更不能预测下个月的需求。
原文提供的 Python 草图还在异常分支中途截断,而且 on_first_token=lambda: None 没有记录首 token 时间,first 始终为 None。它能提示采集字段,不能直接拿来测 TTFT,也不是完整的开环压测实现。
能拿来做什么
- 给现有 AI 功能建立任务清单,至少拆出三个实际存在的请求类别,固定输入、输出上限和验收条件。没有真实流量依据时,明确写出测试集的代表性限制。
- 在前端与 Node 链路中区分用户操作、计划到达、实际发送、首 token 和完整结束时间,并关联检索、工具调用及重试记录,定位等待发生在哪里。
- 比较模型或供应商时,使用相同语义任务、质量底线和到达计划,同时报告有效完成速率、接受率及各类别 p50、p95、p99,避免只比较平均响应时间。
- 上线前补测突发和供应商或 worker 中断,确认队列能恢复、重试有预算、操作人员能停止接收新任务,再用包含失败与人工修正的账本计算单位有效成本。