每秒四百九十词元的标称值:解码速度要做成档位,不能做成口号

一、快是四个互相牵制的口径,不是一个数
据公开报道,有厂商在一个编码类产品里上线了高速版本的模型,有网友晒出接近每秒五百个词元的解码速度,体验资格随机发放给订阅用户,还带着一个具体的客户端版本号。这里的厂商、版本号与那个速度值都不作为本篇的判断依据,本篇只接它暴露出来的交付问题:企业客户想把速度写进服务协议,却发现”快”这个字没法测。
一个推理请求的时间结构至少切成四段。第一段是首词元延迟,从请求进入服务端到第一个词元产出,它由排队、提示词预处理与首轮前向计算决定,用户感知的”卡不卡”绝大多数来自这一段。第二段是逐词元间隔,也就是稳定输出阶段相邻两个词元之间的时间,宣传里那个”每秒多少个词元”通常是它的倒数。第三段是端到端吞吐,单位时间内整个服务处理完的词元总量,它随并发上去而上去,和单用户体验可以是反着走的。第四段是并发上限,超出之后请求开始堆积,前三段同时劣化。
这四段互相牵制的原因是批处理。把多个请求合进一次前向计算,吞吐和单词元成本会变好,代价是每个请求进入批次的等待变长、显存带宽争用让逐词元间隔出现抖动。想压首词元延迟就得让批次更小甚至独占,账单立刻反过来。所以我们不接受”这个模型很快”这种表述,只接受客户在四个口径上各自说出一个能认的数。
测量点必须同时定下来,否则同一次请求会有三个不同的”速度”。客户端埋点拿到的是用户真实体验,里面混进了公网往返、网关排队、SDK 缓冲和前端渲染节奏;网关侧打点去掉了用户网络的不确定性,但仍然包含服务自己的排队;推理实例侧最纯净,只反映计算,却是客户完全看不见的黑盒。三个点都留着,两两相减就是网络成本、排队成本与计算成本。只留一个点的口径,事后一定会吵。
二、标称值与承诺值之间隔着四个变量
同一个高速版本,宣传速度和企业实际拿到的速度经常差出一截,差距不是因为虚标,而是四个变量没被固定。
批处理大小是第一变量。共享池里的批次随流量变化,低谷期批次小、延迟低,高峰期批次大、逐词元间隔抖。上下文长度是第二变量,长提示会把首词元延迟推高,而解码阶段要读的历史也更长,速度随上下文增长而下滑。第三是思考链长度,如果这个型号会先生成一段内部推理再给答案,那么”输出速度”和”用户看到答案的速度”就是两件事,中间多出来的那段时间既不算首词元也不算最终结果,最容易被口径漏掉。第四是缓存命中,前缀缓存命中时首词元延迟可以低很多,而命中率取决于客户的提示词是否结构稳定。
这四个变量里,前三个由调用方部分可控,最后那个由服务方的池化策略决定。据公开报道里那个晒出来的速度值,没有任何公开信息说明它是在什么上下文长度、什么并发、什么思考预算下得到的,所以我们把它当作一个宣传口径,而不是一个可承诺口径。这个区分很关键:宣传口径不需要条件,承诺口径必须把条件全部写出来。
三、随机发放的灰度会让企业侧回归失效
对消费者来说,随机拿到高速通道是惊喜;对企业交付来说,随机是一件很麻烦的事。麻烦不在于慢,而在于同一个型号名背后可能同时存在两套推理配置:一套被抽中的账号使用,另一套留给其余账号。企业的回归测试是在某个账号上跑的,测出来的速度和行为无法保证生产环境也能拿到,即使拿到了也不保证下一周还有。
因此我们把型号名当作不可信字段处理。凡是依赖速度或行为的验收,都要在服务方回包里拿到一个配置指纹——它可以是版本标识、后端标识或任何在服务侧稳定生成、能区分不同推理配置的串。指纹变了,之前建立的速度基线与质量基线全部作废,重新跑一轮。这个动作和”名字没变模型被换了”的处理是同一套纪律,本篇不重复展开,只强调速度维度上的后果:没有指纹,速度台账里的数据就没法分组,你甚至不知道两个数是同一种配置跑出来的。
灰度还带来一个合同层面的问题:如果体验资格由服务方随机分配,那么承诺的速度就不是服务方单方能保证的。条款要写成”在生效范围内可用”,并要求服务方说明范围如何划定、如何扩量、客户是否有权要求固定档位。能把档位固定下来,才谈得上验收。
四、把速度写进 SLO:分位数、时段分档与降级路径
均值在服务协议里几乎没有价值,一次长尾会把整天的数字抹平。我们的写法是每个口径都记分位数,并且按时段分档,因为低谷期与高峰期的合格线本来就不该一样。以下是我们做推理服务速度口径表时的固定字段。
| 指标 | 定义 | 测量点 | 统计量 | 采样工况 | 超限判定 |
|---|---|---|---|---|---|
| 首词元延迟 | 请求到达到首个词元产出 | 网关侧为主,客户端侧对照 | p50 / p95 / p99 | 短提示、中提示、长提示各一档 | 任一分位数连续超限即记录偏差 |
| 逐词元间隔 | 稳定输出阶段相邻词元时间差 | 客户端埋点与网关侧各一份 | p50 / p95 / p99 | 固定采样参数、固定输出生成量 | 与首词元分开判定,不合并 |
| 端到端吞吐 | 单位时间完成词元总量 | 推理实例侧计数 | 日累计与峰值时段 | 与并发上限一同标注 | 只作容量参考,不作体验承诺 |
| 并发上限 | 不触发明显排队的同时在处理请求数 | 网关侧在途计数 | 达到上限的时间点 | 压测得出,非自然流量 | 超上限后的排队时长单列 |
| 思考链时长 | 内部推理阶段占用的时间 | 实例侧与网关侧差值 | p50 / p95 | 按是否启用分两组 | 启用时必须与首词元一并承诺 |
表格里最后两列最容易被省掉,一省掉整个口径就失效了:没有采样工况,别人就无法复现你的数;没有超限判定,数字只能用来汇报不能用来定责。
SLO 条款本身要包含这六项字段:口径名称与测量点;工况边界(上下文长度区间、思考预算是否启用、单次最大输出生成量);承诺的分位数与阈值;时段划分(工作时段与非工作时段分别给线);测量失败的处理(服务方回包缺少时间戳或指纹时按违约计入,而不是剔除样本);超出预算后的降级路径。降级路径是这一套里最实用的一条,要提前写清楚:慢到什么程度切到备选后端、由谁判断、切换后原来的档位承诺是否顺延。没有这一条,客户只能在事故里现场发明流程。
五、变更通知要落成字段,不是落成一句公告
速度承诺能不能守住,取决于服务方改动时告诉你什么。我们的供应商管理清单里,任何影响推理行为的变更通知必须包含六个字段,缺一项就要求补充说明。
- 权重版本标识:换了权重还是只换了配置,两者对行为的影响完全不同。
- 量化策略:位宽与量化方式变更会同时改变速度、显存占用与数值表现。
- 推理后端与运行时版本:同一权重在不同后端上的速度与容差不同。
- 批处理与并发上限:共享池的调度参数变了,首词元延迟的分布就变了。
- 生效范围:哪些账号、哪些区域、多大比例的流量,是否包含灰度抽中。
- 生效时间与回滚窗口:从通知到生效留多久,出问题时回滚到哪一个已知可用组合。
洹拓把这六项作为供应商季度对账的固定议题,因为它们直接决定我们的速度台账要不要断档。通知的送达方式也要定:字段化的变更要落到机器可读的位置,例如随回包返回或提供可查询的接口,而不是只发一封邮件;邮件只能作为提醒,不能作为唯一凭证。
六、验收动作:固定输入、连续采样、台账落到分位数
验收不是”跑一下看看快不快”,而是一段有边界的小流程。我们的固定做法是四步。
第一步建固定提示集。按业务真实分布取三档上下文长度,每档若干条,内容不随时间替换;其中包含一条长思考链的请求,用来观察思考阶段占用多少时间。提示集本身入版本库,任何人改动都要留记录。第二步固定采样参数并锁定工况:温度、Top P、最大输出生成量、是否启用思考模式都写死,验收期内不许调。第三步连续采样七天,每天覆盖工作时段与非工作时段各若干轮,全部走同一条链路,测量点三份时间戳同时记录。第四步把结果写进台账,字段包括记录时间、时段、配置指纹、三个分位数、错误率、被限流的请求数。台账里要能一眼看出哪几天是同一个指纹,指纹断档的那几天单独成组,不与历史合并计算。
验收结论我们只给三种。通过是各档位分位数在工况内都满足承诺;有条件通过是只有非工作时段满足,或峰值时段超限但降级路径可用,此时把时段分档写进合同而不是抹平;不通过是拿不到配置指纹或变更通知字段不全——这一条看起来很程序化,但它决定了三个月后你能不能证明自己拿到的速度和当初验收的不是同一种东西。
最后留一句给客户的话:如果你正在采购推理服务,而对方的报价单上只有一个”每秒多少词元”,那不是一个可比较的数字。把口径表发回去,让对方在自己的数字旁边填上测量点、工况和分位数,填不出来的部分就是你将来要自己承担的风险。