流式 LLM 响应有两个独立指标——TTFT(首Token时间)和 TPS(生成速率),分别受不同因素驱动。缩短系统提示无助于 TPS,缩短回答长度也无助于 TTFT;用单一「延迟」数字无法判断该优化哪个指标。
两个数字,精确界定
注意两者各自缺少了什么。将系统 prompt 减半,对 TPS 毫无作用。要求一个更短的答案,对 TTFT 也毫无作用。如果你只报一个数字,根本无法判断该拉哪个杠杆,而通常的结果是拉错了杠杆,然后得出"优化没效果"的结论。
读者比你想象的慢
对于任何人类在接收过程中观看的文本,有一个阈值——超过这个阈值后,生成速度再快也感知不到,而且这个阈值很低。心理学语言学文献中,成人默读普通散文的速率大约在每分钟 200–300 词;以 250 作为工作假设。英语在常见词汇下大约每 token 0.75 个词。于是:
reader demand = 250 words/min / 0.75 words/token / 60 s
~= 5.6 tokens/second (assumption: 250 wpm, 0.75 w/tok)
大约每秒六个 token 就能跟上读者。托管模型的流式输出通常是这个速度的很多倍。这意味着,对于聊天界面,超过一个相当低的 TPS 基准线之后,再快也无法被用户感知;而 TTFT 的每一毫秒都是他们在盯着看的空白时间。
需要诚实说明的是:读者会略读、会回滚,文本以可见的 burst 形式到达感觉比相同 token 均匀到达要差——但数量级是成立的。如果你的用户在阅读,TTFT 是关键数字。
均匀性值得作为独立属性来处理,而不是并入速率中。一个每秒 60 token 但每三分之一秒 burst 20 个的流,和一个均匀输出的流有相同的平均值,但阅读体验差得多——眼睛注意到的不是吞吐量而是停顿。产生这个问题的原因有两个:服务器端 batch 组合效应,以及你自己的传输层中积累 chunk 后才 flush 的缓冲。只有第二个是你能控制的,值得检查,因为路径中某处的一个小 write buffer 是常见且完全可修复的"速率看起来健康但感觉卡顿"的原因。
当 TTFT 完全不再重要时
现在把人类移除。一个 agent 循环顺序调用六次模型,每次产生 400 token,只向用户展示最终答案,其算术完全不同:
6 steps x (TTFT 0.4 s + 400 tokens / TPS)
TPS = 30 -> 6 * (0.4 + 13.3) = 82 s TTFT is 3% of it
TPS = 90 -> 6 * (0.4 + 4.4) = 29 s TTFT is 8% of it
生成速度占主导,TTFT 是舍入误差,上面的数字是基于假设速率的示例算术,不是任何 provider 的实测数据。代入你自己的 step 数和 token 数;答案的结构不会变。没有人看中间 token,所以让它们流得更快是缩短等待的唯一方式。
同样适用于任何非流式消费者:分类任务、批量 enrichment、从响应中解析 JSON 的工具。如果第一个 token 从未展示,它的到达时间对用户没有任何可见含义。
第三个数字,针对推理模型
在回答前消耗 token 进行思考的模型打破了上面的定义,而且这个打破不是表面上的。到达的第一个 token 可能是第一个推理 token,界面要么隐藏它,要么在单独面板中展示。那么 ttft 测量的就是用户没在看的东西的开始,而用户实际感受的那个数字没有人记录:
time to first ANSWER token
= ttft + reasoning_tokens / rate
reasoning budget 1500 tokens, rate 60 tok/s, ttft 0.5 s
-> 0.5 + 25 = 25.5 s of a blank answer pane
二十五秒不是你能通过调优 prefill 解决的延迟问题。这是一个产品问题,可用的答案也是产品答案:展示推理过程让等待可见,展示中间结构,或者减少思考 token。如果 API 提供了 reasoning-effort 或 thinking-budget 控制选项,这个控制是目前为止你手中最大的延迟旋钮——比模型选择和 prompt 长度的影响都大。
测量的后果:对于推理模型,记录三个时间戳而不是两个——第一个 token、第一个非推理 token、以及结束。将中间那个作为感受延迟报告,把只有第一个时间戳的 dashboard 视为在测量一个没有人经历过的东西。
有用户在读 token 吗?如果是,优化 TTFT:缩短并缓存 prompt 前缀,选择离用户近的 region,复用连接,从第一个字节开始流式传输而不是在 proxy 中缓冲。接受任何高于大约 10 的 TPS。
输出是被整体消费的吗?那就只有总时间存在。先优化输出长度——这是你最直接控制的项——然后 TPS,最后才是 TTFT。
是多步骤 agent 吗?把所有数字乘以 step 数,然后减少 step 数。少一次往返胜过任何单次调优。
根本没有截止时间吗?那两个数字都不是你的指标;每任务成本才是,异步批量端点通常会全面胜出。
这些数字如何被误报
三个失败模式占据了大多数令人困惑的延迟数字。缓冲 proxy 让 TTFT 等于总时间,所以一个完全健康的模型看起来像是灾难性地慢——检查你的 CDN、ingress 和任何框架响应包装器是否都无缓冲地传递 chunk。在一个中途停顿的请求中平均 TPS 完全隐藏了停顿,因为平均速率会恢复尽管用户看到了三秒冻结;同时报告 inter-token 最大值和平均值。引用均值而不是百分位数会让一个队列延迟的请求定义一个没有人实际经历过的数字。
每个请求报告四个数字,每一个这类问题都会消失:TTFT、总时长、输出 token 数、以及连续 token 之间的最大间隔。
如果你想要每个请求的这些数字而不是来自 leaderboard,Multigrid 按模型和 provider 分别发布吞吐量和延迟,这才是唯一能回答问题的方式。
What Happens Between Your Request and the First Token
Measuring p50, p95 and p99 for LLM Calls
Prefill vs Decode: The Two Halves of Inference