首 Token 耗时 TTFT 怎么看
TTFT 反映用户等待模型开始输出的时间;它不同于完整请求总耗时,也不同于 curl 看到响应头的 HTTP 首字节。
三个时间不要混用
| 指标 | 起点与终点 | 适合判断 |
|---|---|---|
| TTFB | 请求发出到收到 HTTP 首字节或响应头 | 网络、TLS、代理建立响应的速度 |
| TTFT | 请求开始到收到首个实际模型输出事件 | 用户体感、排队和模型启动延迟 |
| Duration | 请求开始到流式终态或完整响应结束 | 整次任务耗时 |
平台的首 Token 以首个实际输出事件为准,会排除只包含 usage 的空事件。它比单纯使用 curl 的
time_starttransfer 更接近真实用户体感。在平台页面查看
- 登录后打开“用量记录”。
- 在表格中找到“延迟”列。
- “首字”对应
first_token_ms,“总耗时”对应duration_ms。 - 需要批量分析时导出 CSV,使用
First Token (ms)列。
非流式请求没有可见的逐 Token 输出,first_token_ms 为空是正常现象。不要把空值当作 0,也不要把非流式请求加入 TTFT 平均值。
用 Responses 流准确测量
下面的 Node.js 18+ 脚本只在收到 response.output_text.delta 时记录 TTFT,避免把连接建立事件误当作首 Token。
const started = performance.now();
const response = await fetch("https://sub.tidba.com/v1/responses", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.TIDBA_API_KEY}`
},
body: JSON.stringify({
model: "gpt-5.6-sol",
input: "用一句话回答:连接是否正常?",
stream: true
})
});
if (!response.ok) {
throw new Error(`${response.status} ${await response.text()}`);
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
let firstToken = null;
while (true) {
const { value, done } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop();
for (const line of lines) {
if (!line.startsWith("data: ")) continue;
const data = line.slice(6);
if (data === "[DONE]") continue;
const event = JSON.parse(data);
if (firstToken === null &&
event.type === "response.output_text.delta") {
firstToken = performance.now() - started;
console.log(`TTFT: ${firstToken.toFixed(0)} ms`);
}
}
}
console.log(`Total: ${(performance.now() - started).toFixed(0)} ms`);
TIDBA_API_KEY="YOUR_KEY" node ttft.mjs
看 P50、P95,不看单次最快值
- P50代表日常中位体验,适合比较模型或线路的常态。
- P95代表较差时段的用户体验,适合判断抖动和容量风险。
- P99容易受少量超长请求影响,适合告警,不适合单独评价日常速度。
- 同一组比较至少保持模型、推理等级、提示词规模、流式模式和客户端地区一致。
平台运营面板会按真正记录了 TTFT 的流式样本计算分位数,而不是拿全部成功请求稀释结果。
TTFT 变慢时怎么定位
| 现象 | 优先检查 |
|---|---|
| 所有模型同时变慢 | 客户端网络、DNS、TLS、代理和平台整体排队 |
| 只有一个模型变慢 | 该模型容量、推理等级、上游账号状态 |
| TTFT 正常但总耗时很长 | 输出长度、工具调用次数、推理等级 |
| TTFT 为空 | 请求是否为流式,是否在首个输出前中断 |
| P50 正常但 P95 很高 | 偶发排队、账号切换、跨区网络抖动 |
出现容量类错误时参考 Selected model is at capacity 排查;出现 502 时参考 502 排查。
先建立可重复的基线
固定模型和提示词,连续采集一组流式请求再比较。