☰
LLM推理指标从入门到精通:TaoToken视角搞懂TTFT、TPOT与Goodput
2026/10/8 6:15:13 网站建设 项目流程

1. 为什么你的推理服务“看起来快”却总被投诉

你有没有遇到过这种场面:压测报告上写着平均延迟 180ms,老板看完很满意,结果上线第二天客服群里全是“打字机卡住了”“第一个字等半天”。问题不在模型,而在你只看了平均值。LLM 推理的性能评估和传统 Web 服务完全不是一回事——它有两个阶段(Prefill 和 Decode),有流式输出,有 token 级别的抖动,单看一个数字必然翻车。

先把核心检索词摆出来:TTFT 是首 token 延迟,衡量用户从按下回车到看见第一个字的时间;TPOT 是每个输出 token 的平均生成耗时,决定流式输出“顺不顺”;Goodput 是满足 SLO 的请求占比,回答“到底有多少用户是满意的”。这三个指标分别对应体验、流畅度和服务质量,缺一个你的评估体系就是瘸腿的。

这篇文章适合谁?如果你正在用统一 Key/API 通道调用多家模型、需要横向对比不同模型的推理表现,或者你自建了 vLLM/SGLang 服务想知道瓶颈在哪,那接下来的内容可以直接抄作业。我会用 TaoToken 的统一 API 通道作为调用入口,因为它把不同厂商的模型收敛到同一套 OpenAI 兼容接口,采集指标时不用为每家写一套适配代码,省下来的时间可以多跑几轮压测。

先建立一个直觉:TTFT 主要吃 Prefill 算力,输入越长越慢;TPOT 主要吃 Decode 阶段的显存带宽和批处理效率;Goodput 则是前两者加上你的 SLO 定义共同算出来的结果。理解了这条因果链,后面调参就不会瞎试。

2. TaoToken 统一通道:把多模型指标采集收敛成一套代码

做推理性能评估最烦的不是写压测脚本,而是每换一个模型就要改一遍鉴权和请求格式。TaoToken 的价值在这里就体现出来了:它提供 OpenAI 兼容的统一 API 入口,你只需要一个 Key、一个 Base URL,就能在同一个脚本里切换不同模型跑对比测试。官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 端点是 https://taotoken.net/api ,注意这个地址后面不加任何查询参数。

具体怎么拿到 Key:登录后进入控制台,在 API Keys 页面创建一个新 Key,复制出来保存好。这个 Key 就是你在压测脚本里填的api_key。模型 ID 则根据你要测的目标填写,比如你想对比某个通用对话模型和某个代码专用模型,就在请求体的model字段里换名字即可,其余代码一行不用动。

这里要强调一个采集指标时的关键点:流式请求必须开启stream: true,否则你拿不到首 token 的时间戳,TTFT 就无从计算。很多人第一次采集 TTFT 失败,就是因为用了非流式请求,等整个响应回来才记录时间,那测出来的其实是 E2EL。所以配置里stream这个参数是硬性要求。

另外,TaoToken 的通道对并发请求是支持的,这意味着你可以用同一个 Key 发起多路并发来测吞吐和 Goodput。但要注意,压测并发数不要一上来就拉满,先从低并发跑基线,再逐步加压找到饱和点,否则你看到的全是超时错误,数据没有参考价值。

如果你后续要做长期编码或 Agent 类的高频调用,可以考虑 Coding Plan 这类方案来降低单位成本;而单纯验证模型输出质量、做对话式对比,用模型对话页面手动试几轮更直观。采集指标这件事,核心还是靠脚本自动化,手动点页面只能做定性判断。

3. 可复制的指标采集配置:从 settings 到压测脚本

这一节给你可以直接粘贴运行的配置。先建一个工作目录,然后写一个settings.json用来存放通道信息,路径就放在项目根目录下,内容如下:

{ "base_url": "https://taotoken.net/api", "api_key": "sk-你的Key粘贴在这里", "model_id": "你的目标模型ID", "slo": { "ttft_ms": 500, "tpot_ms": 100, "e2el_ms": 5000 } }

注意base_url结尾不要加/v1之外的路径,OpenAI 兼容接口的标准拼接是{base_url}/v1/chat/completions,TaoToken 的 API 地址已经处理好这层,你按上面填就行。slo这一段是给 Goodput 计算用的阈值,你可以根据业务场景调整,聊天场景 TTFT 卡 500ms 比较合理,代码补全建议压到 200ms 以内。

接下来是采集脚本,用 Python 写,依赖openai和numpy:

import json, time, statistics import numpy as np from openai import OpenAI cfg = json.load(open("settings.json")) client = OpenAI(base_url=cfg["base_url"], api_key=cfg["api_key"]) def measure_once(prompt, max_tokens=128): t_send = time.perf_counter() stream = client.chat.completions.create( model=cfg["model_id"], messages=[{"role": "user", "content": prompt}], max_tokens=max_tokens, stream=True, ) t_first = None token_times = [] for chunk in stream: delta = chunk.choices[0].delta.content if delta: now = time.perf_counter() if t_first is None: t_first = now token_times.append(now) t_end = time.perf_counter() ttft = (t_first - t_send) * 1000 e2el = (t_end - t_send) * 1000 n_out = len(token_times) tpot = (e2el - ttft) / max(n_out - 1, 1) return {"ttft": ttft, "e2el": e2el, "tpot": tpot, "tokens": n_out} results = [measure_once("用三句话解释什么是 KV Cache") for _ in range(30)] ttfts = [r["ttft"] for r in results] tpots = [r["tpot"] for r in results] print("TTFT mean/median/p99:", np.mean(ttfts), np.median(ttfts), np.percentile(ttfts, 99)) print("TPOT mean/median/p99:", np.mean(tpots), np.median(tpots), np.percentile(tpots, 99))

这段脚本的关键在于t_first的捕获时机——它在收到第一个非空 delta 的瞬间记录,而不是等 chunk 对象创建。如果你把时间戳打在create()返回时,测出来的是连接建立时间,不是 TTFT。跑 30 次是为了让 P99 有意义,样本太少分位数会失真。

Goodput 的计算在脚本里补一段:

slo = cfg["slo"] good = sum(1 for r in results if r["ttft"] < slo["ttft_ms"] and r["tpot"] < slo["tpot_ms"] and r["e2el"] < slo["e2el_ms"]) print(f"Goodput: {good}/{len(results)} = {good/len(results)*100:.1f}%")

这样一套下来,TTFT、TPOT、Goodput 三个指标全部落地。你可以把model_id换成不同模型,跑同一批 prompt,横向对比就出来了。

4. 验证请求与结果解读:一次真实压测的数据长什么样

配置写好后,先跑一次单请求确认链路通。执行脚本,如果控制台打印出 TTFT、TPOT 的数值,说明鉴权和流式解析都正常。如果卡住不动,大概率是stream没生效或者网络层缓冲了响应,检查settings.json里的base_url是否写成了带 UTM 的官网地址——API 调用必须用 https://taotoken.net/api ,官网地址是给人看的,不是给程序调的。

一次典型的 30 请求压测结果大概长这样:TTFT 的 mean 是 320ms,median 是 280ms,P99 是 890ms;TPOT 的 mean 是 42ms,median 是 38ms,P99 是 95ms;Goodput 按 TTFT<500、TPOT<100、E2EL<5000 算下来是 87%。这组数据说明什么?中位数体验不错,但 P99 的 TTFT 接近 900ms,意味着每 100 个用户里有 1 个要等将近一秒才看见第一个字,这就是长尾问题。

怎么定位这 1% 的慢请求?在脚本里把每次请求的 prompt 长度也记下来,然后按输入 token 数分桶看 TTFT。通常你会发现慢请求集中在长输入上,因为 Prefill 阶段的计算量随输入长度增长。这时候优化方向就明确了:要么启用 Prefix Caching 缓存公共前缀,要么对长输入做截断或分段。

TPOT 的解读要看抖动。如果 mean 是 42ms 但 P99 到了 95ms,说明生成过程中有卡顿,可能是批处理调度不均或者 KV Cache 换页导致。这时候可以观察并发数对 TPOT 的影响:低并发时 TPOT 稳定,高并发时 TPOT 飙升,说明 Decode 阶段成了瓶颈,需要调 batch size 或者上量化。

Goodput 是最直观的验收指标。87% 意味着有 13% 的请求没达标,你可以进一步拆解:是 TTFT 超标的多,还是 TPOT 超标的多?如果 TTFT 超标占大头,优化 Prefill;如果 TPOT 超标占大头,优化 Decode。这个拆解动作比盯着一个总分有用得多。

5. 常见报错排查:401、local proxy failed 与 reading choices

采集过程中最容易撞上的几个错误,这里逐个拆。

第一个是 401 Unauthorized。报错信息通常是Error code: 401 - {'error': {'message': 'Invalid API key'}}。原因就两个:Key 复制时带了空格,或者 Key 已经被删除/过期。排查方法是把 Key 打印出来看首尾字符,确认没有换行符。另外注意,如果你在环境变量里存 Key,某些 shell 会吞掉特殊字符,建议直接读settings.json。

第二个是local proxy failed或连接超时。这个报错说明请求根本没到达服务端,通常是base_url写错了。检查你的配置里是不是误填了官网地址或者带了多余的路径。正确的 API 地址是 https://taotoken.net/api ,程序会自动拼接/v1/chat/completions。如果你手动在 base_url 后面又加了/v1,就会变成/api/v1/v1/...,直接 404。

第三个是reading choices相关的解析错误,典型信息是KeyError: 'choices'或者list index out of range。这通常发生在流式解析时,某些 chunk 的choices数组为空(比如心跳包或结束标记),你的代码直接取chunk.choices[0]就崩了。修复方法是加一层判断:

for chunk in stream: if not chunk.choices: continue delta = chunk.choices[0].delta.content if delta: ...

第四个是 OAuth 或鉴权头格式问题。如果你用的是某些 SDK 的旧版本,可能默认走 OAuth 流程而不是 Bearer Token。确认你用的是标准 OpenAI SDK,并且api_key参数传的是 Bearer 格式。如果报错里出现OAuth字样,检查是不是误用了需要额外授权的端点。

还有一个隐蔽的坑:并发压测时出现大量Rate limit exceeded。这不是代码问题,是通道的速率限制。解决办法是降低并发数,或者在脚本里加指数退避重试。压测的目的是找饱和点,不是把服务打挂,看到限流错误说明你已经越过了合理并发区间。

6. 把指标用起来:从采集到持续监控

指标采集一次不算完,真正有价值的是把它变成持续监控。你可以把上面的脚本包装成一个定时任务,每 5 分钟跑一轮小样本(比如 10 个请求),把 TTFT、TPOT、Goodput 写入时序数据库,然后用 Grafana 画趋势图。这样模型服务一有劣化,你当天就能发现,而不是等用户投诉。

对于需要长期跑编码或 Agent 任务的场景,调用频率高、对 TPOT 敏感,可以考虑用 Coding Plan 来稳定成本和配额;而日常做模型能力验证、对比不同模型的输出质量,用模型对话页面手动跑几个 case 更省事。指标采集脚本负责量化,手动对话负责定性,两者配合才完整。

最后给一个实操建议:每次换模型或改配置后,先跑 5 个请求确认没有报错,再跑 30 个请求看分位数,最后跑 100 个请求算 Goodput。这个渐进式流程能帮你在早期就发现问题,避免跑了一大轮压测才发现 Key 填错了。指标体系的搭建不难,难的是坚持采集和解读,把这三个指标变成你发布前的固定检查项,推理服务的质量就有了可量化的保障。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询