AI API 延迟指标:TTFT、首个有效响应与输出速度
用一条请求时间线区分上游 Header、首个 SSE Event、首个有效响应、首个可见文本、端到端延迟与输出速度。
AI API 延迟不是一个数字。对于流式请求,应分别记录上游 Header 到达、首个非空 SSE Event 到达、首个有效内容或动作出现、首个可见文本出现,以及响应完成的时间。这些里程碑回答的问题不同,不应全部被称为“TTFT”。
对于纯文本对话,首个可见文本通常就是面向用户的延迟。对于使用推理或工具的工作流,首个有效输出可能更早以推理元数据或函数参数的形式出现。输出开始后的生成速度是另一个独立指标。
先建立请求时间线,再给指标命名
客户端或网关层的时间戳应使用单调时钟和统一起点。一次流式请求可以表示为:
t0 gateway receives request
t1 gateway starts upstream request
t2 upstream response headers arrive
t3 first non-empty SSE event arrives
t4 first effective content or action arrives
t5 first visible text delta arrives
t6 upstream body completes or closes
t7 gateway handler finishes
并非每个请求都会产生所有里程碑。非流式响应没有可用的 SSE 时间线;只返回 Function Call 的响应可能完全没有可见文本;被取消的 Stream 可能已经开始却没有正常完成。缺失值应保持缺失,不能写成零,否则会错误地表示该事件立即发生。
Modelflare 在 other.timing 中记录请求级元数据。各字段与时间线的对应关系如下:
| 字段 | 测量内容 | 重要边界 |
|---|---|---|
auth_ms |
Token 与用户鉴权耗时 | 本地阶段耗时,不是上游时间 |
distribution_ms |
渠道选择与路由策略耗时 | 本地阶段耗时 |
body_read_ms |
读取下游请求 Body 的耗时 | 能暴露进入路由前的慢上传 |
upstream_headers_ms |
从发起上游请求到收到响应 Header | 起点是发起上游请求,不是网关最初收到请求 |
first_sse_event_ms |
从网关收到请求到首个非空上游 SSE Event | Event 可能只有元数据,没有有效输出 |
first_response_ms |
从网关收到请求到首个有效内容或动作 Delta | 包含可见文本、推理摘要、函数参数或自定义工具输入 |
first_text_delta_ms |
从网关收到请求到首个可见文本 Delta | 只有实际出现可见流式文本时才存在 |
upstream_done_ms |
从网关收到请求到上游 Body 完成或关闭 | 连接关闭不等于成功完成 |
total_handler_ms |
从网关收到请求到 Relay 当前已知的最后完成点 | 最接近网关视角的端到端耗时 |
visible_output_tps |
输出 Token 数除以首个可见文本到上游完成的时间 | 可见输出诊断值,不是系统总 TPS |
这张映射可以避免一个常见错误:对起点不同的时间值直接做减法。例如,upstream_headers_ms 从上游请求发起时开始计算,而 first_response_ms 从网关收到请求时开始计算。
TTFT 在实践中有多种含义
Time to First Token 的传统定义,是从提交请求到收到第一个输出 Token 的时间。NVIDIA NIM 基准指标指南指出,它通常包含网络延迟、排队和 Prompt Prefill,且不应把没有内容的初始响应算作第一个 Token。
该定义适用于文本生成基准,但现代 API Stream 可能在可见文本之前发送多种内容:
- Response Created 或元数据 Event;
- 推理摘要 Delta;
- Function Call 参数片段;
- 自定义工具输入;
- 空 Heartbeat 或提供商特有的 Envelope。
在 Dashboard 与事故报告中使用明确名称:
| 名称 | 建议定义 | 最适合的用途 |
|---|---|---|
| Time to Headers | 从请求开始到上游 Header | 网络、代理与上游准入诊断 |
| Time to First Event | 从请求开始到首个非空 SSE Event | 仅判断传输是否活跃 |
| Time to First Effective Response | 从请求开始到有效内容或动作 | Agent 与推理工作流响应性 |
| Time to First Visible Text | 从请求开始到用户可渲染的文本 | 对话与用户感知响应性 |
如果图表只写“TTFT”,必须注明它指向表中的哪一行。否则两个团队可能为同一个请求报告不同数值,而且表面上都没有错。
分开测量响应速度与生成速度
端到端延迟是从提交请求到完整接收响应的总时长。根据所选边界,它可以包含排队、Prefill、Decode、网络传输、上游 Stream 中体现的工具等待,以及网关处理。
对于正常完成的简单文本 Stream:
end_to_end_latency = final_response_time - request_start_time
visible_generation_window = final_response_time - first_visible_text_time
visible_output_tps = output_tokens / visible_generation_window_seconds
Inter-token Latency 也称 Time per Output Token,通常表示第一个 Token 之后,相邻输出 Token 的平均间隔。NVIDIA AIPerf 的定义排除 TTFT,并用剩余时长除以 output_tokens - 1。当输出足够长时,它的倒数接近单用户 Decode 吞吐。
不要通过统计 SSE Event 或 Text Delta 的数量来计算 Token 级 ITL。一个 Event 可能包含零个、一个或多个 Token,Token 边界也取决于模型的 Tokenizer。Modelflare 的 visible_output_tps 使用记录的输出 Token 数和可见生成窗口;它并不声称是逐 Token Event 间隔,也不是系统总吞吐。
这些指标回答不同问题:
- 首个文本很快但输出速度慢,体验是先响应、后卡顿;
- 首个文本很慢但输出速度快,体验是长时间等待后迅速完成;
- 单用户输出速度低,不能证明并发下系统总吞吐低;
- 聚合 TPS 高,也不能保证单个用户的延迟良好。
推理和工具可能早于可见文本
在纯文本流程中,first_response_ms 与 first_text_delta_ms 可能几乎相同。在推理或 Function Calling 流程中,两者之间的间隔可能非常有意义。
假设模型在 1.8 秒时开始发出 Function Call 参数,应用或提供商侧工具流程继续运行,到 6.4 秒才出现可见文本。系统在 1.8 秒已经产生可执行结果,但用户直到 6.4 秒才看到文字。把这两个值都叫 TTFT,会掩盖延迟究竟发生在规划之前、工具步骤期间,还是回答渲染之前。
应根据产品体验解释字段:
- 对终端 Agent,首个有效动作可能是最合适的响应性指标;
- 对只显示正文的聊天 UI,首个可见文本才是用户指标;
- 对由代码消费的 Tool Call API,可见文本可能不存在,不应把它设为必需;
- 对推理模型,早到的 SSE Envelope 只能证明连接有进展,不能证明工作有实质进展。
AI API 流式指南说明了 SSE 解析、取消与 Idle Timeout。只有解析器已经区分 Envelope 与有效输出后,才能计算正确的延迟指标。
按固定顺序诊断慢阶段
从上游边界开始,再检查本地阶段。这样可以避免请求主要时间都在等待模型,却先归因于鉴权或路由。
| 现象 | 首要指标 | 优先检查的层 | 下一项检查 |
|---|---|---|---|
| 收到 Header 之前很慢 | upstream_headers_ms |
网络路径、上游准入、提供商队列、代理路由 | 对比渠道、区域、状态与并发 |
| Header 很快,有效输出很晚 | first_response_ms 减去早期阶段 |
模型排队、Prompt Prefill、推理、上游调度 | 对比输入 Token、模型、路由与 Inflight Count |
| 首个 Event 很快,有效输出很晚 | first_sse_event_ms 到 first_response_ms 的间隔 |
纯元数据 Event、Heartbeat、推理启动 | 检查安全的 Event Type,不读取原始内容 |
| 有效动作很快,可见文本很晚 | first_response_ms 到 first_text_delta_ms 的间隔 |
工具/推理阶段或回答组织 | 检查请求的工具与输出模式 |
| 文本开始很快,之后生成缓慢 | visible_output_tps 与 upstream_done_ms |
Decode 吞吐、资源争用、长 Context、网络背压 | 对比输出长度与渠道 Inflight Count |
| 所有上游指标都正常 | auth_ms、distribution_ms、body_read_ms |
本地鉴权、策略选择、客户端上传 | 只检查实际升高的阶段 |
任何单一指标都不能证明根因。例如,较高的 upstream_headers_ms 同时覆盖多种可能性,还需要结合路由、区域、提供商与并发负载证据才能区分。
阅读三条合成 Trace
下列数据仅用于演示诊断,不是 Modelflare 生产平均值,也不是提供商 Benchmark。
Trace A:等待上游 Header
| 指标 | 数值 |
|---|---|
upstream_headers_ms |
6,100 ms |
first_sse_event_ms |
6,300 ms |
first_response_ms |
6,350 ms |
first_text_delta_ms |
6,400 ms |
total_handler_ms |
9,200 ms |
visible_output_tps |
42 |
大部分时间都发生在收到 Header 之前,而可见文本开始后的生成相对正常。应先检查选择的上游路由、提供商准入、网络路径、区域与并发负载,而不是优化客户端渲染器。
Trace B:有效动作早于可见正文
| 指标 | 数值 |
|---|---|
upstream_headers_ms |
240 ms |
first_sse_event_ms |
310 ms |
first_response_ms |
2,900 ms |
first_text_delta_ms |
8,700 ms |
total_handler_ms |
10,200 ms |
visible_output_tps |
55 |
传输很早就处于活跃状态,2.9 秒时也已经出现有效动作,但可见文本又等待了 5.8 秒。如果请求使用推理或工具,应检查对应阶段。提高 Header Timeout 无法解决这种模式。
Trace C:开始很快,生成很慢
| 指标 | 数值 |
|---|---|
upstream_headers_ms |
260 ms |
first_sse_event_ms |
330 ms |
first_response_ms |
420 ms |
first_text_delta_ms |
430 ms |
total_handler_ms |
20,430 ms |
visible_output_tps |
9.8 |
请求很快就显示文本,但随后生成约 20 秒。应对比输出长度、Context 长度、所选渠道、Inflight Count 与提供商行为。First-output Timeout 会通过,因此无法发现这种故障模式。
只在受控条件下比较延迟
公平比较需要保持工作负载契约稳定。至少记录:
- 精确模型 ID 与路由或分组;
- 输入与输出 Token 的分布,而不只是平均值;
- 流式或非流式模式;
- 启用的 Reasoning Effort 与工具;
- 区域以及客户端到网关的网络路径;
- 并发数或请求到达率;
- Sampling 参数与最大输出长度;
- Warmup 策略、重试策略和被排除的失败;
- 样本量、时间窗口与分位数计算方法。
应比较 p50、p95 与 p99,而不是只展示一个平均值。失败也必须保留:删除 Timeout 与错误请求,会让一条不可靠的路由看起来更快。不要用不同 Prompt、输出长度、并发或端点行为测试两个提供商,再把结果描述成模型速度排名。
保留诊断元数据,而不是内容
延迟诊断不需要保存 Prompt、Response、API Key 或明文客户端身份。一条有用的请求记录可以包含:
- 生成的 Request ID 与时间戳;
- 模型、分组和所选渠道引用;
- 状态与终止结果;
- 可用时的输入、输出与缓存 Token 数;
- 上述 Timing 字段;
- Stream Event 与 Text Delta 数量;
- 渠道 Inflight Count;
- 粗粒度区域和经过隐私审查的网络 Trace 标识;
upstream_headers_slow或generation_slow_tps等粗粒度分类。
即使只是元数据,也要设置保留期限和访问控制。Request ID、路由选择、时间模式与 Token 数结合后,仍然可能暴露运营行为。
诊断应从完整请求时间线开始,而不是一个模糊的 TTFT 标签。然后使用 Reliable AI API Routing对比每次尝试的确切路由,再通过 AI API 错误排查把时间与最终状态结合起来。这样才能用证据区分准入延迟、模型启动、推理或工具工作、可见生成,以及本地网关开销。