ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

LLM推理基准测试完全指南:用TaoToken统一Key跑通从理论到实践的性能评估

LLM推理基准测试完全指南:用TaoToken统一Key跑通从理论到实践的性能评估 1. 为什么个人开发者也需要做 LLM 推理基准测试很多人第一次接触 LLM 推理基准测试是因为线上服务突然变慢用户抱怨首字要等三四秒或者并发一上来就大面积超时。这时候你打开监控发现 GPU 利用率忽高忽低显存占用逼近上限但具体瓶颈在哪、换一个模型或换一组参数能提升多少完全说不清。LLM 推理基准测试就是解决这个问题的它用可重复的脚本在受控条件下测量推理服务的延迟、吞吐和资源占用把「感觉慢」变成「TTFT 1.8s、TPOT 42ms、输出吞吐 380 tok/s」这样的数字。它和模型能力评测MMLU、SWE-bench 那类是两回事。能力评测关心模型答得对不对推理基准测试关心模型跑得快不快、稳不稳、贵不贵。适合谁个人开发者、小团队后端、做 Agent 应用的工程师以及需要给老板或客户解释「为什么要升级显卡/换推理框架」的人。你不需要有集群一台带 GPU 的开发机加一个统一 API 通道就能跑通全流程。我试过用不同厂商的模型做横向对比最麻烦的从来不是脚本而是每家 Key 的鉴权方式、Base URL、模型名都不一样脚本里到处是 if-else。所以这篇会以 TaoToken 统一 Key/API 通道作为接入层把「被测模型」抽象成一个 OpenAI 兼容端点这样同一份基准脚本可以换模型名就跑评测流程才真正可复用。下面从指标含义讲起再给可复制的配置和跑分命令最后附排错对照表。2. 核心指标与 TaoToken 统一接入前置准备2.1 吞吐、延迟、显存到底在测什么先把指标说清楚不然跑出来的数字没法解读。延迟侧最常看三个TTFTTime To First Token首 Token 延迟从发出请求到收到第一个输出 Token 的时间直接决定用户「等多久才看到字」TPOTTime Per Output Token每输出 Token 耗时等于端到端延迟 − TTFT/输出 Token 数 − 1决定「字吐得快不快」端到端延迟则是整个请求从提交到结束的总时间。吞吐侧看输入吞吐输入 Token / TTFT和输出吞吐(输出 Token − 1) / 输出延迟以及单位时间请求数RPS/QPS。显存则关注峰值占用和 KV Cache 占比它往往是你并发上不去的真正原因。一个容易踩的坑不同工具对 TPOT 的分母定义略有差异有的用输出 Token 数有的减 1。做横向对比时务必确认口径一致否则 5% 的差异可能只是算法不同。另一个坑是流式和非流式混用——非流式请求拿不到 TTFT只能测端到端所以基准脚本默认走流式。2.2 用 TaoToken 统一 Key 屏蔽多模型差异TaoToken 在这里的角色是「统一入口」它提供 OpenAI 兼容的 API 通道你用同一个 Key、同一个 Base URL只改 model 字段就能切换被测模型。官网在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 端点是 https://taotoken.net/api 注意这个地址不加 UTM 参数。对基准测试来说这带来两个实际好处一是脚本里只需要维护一份鉴权逻辑二是可以快速做 A/B 对照把「模型差异」和「接入差异」分开。前置准备清单一个可用的 API Key在控制台创建地址 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite Python 3.10 环境以及 requests、openai、numpy 三个库。被测模型建议先选一个你熟悉的比如通用的对话模型跑通流程后再换。如果你还没确定用哪个模型可以先去模型对话页面试一下响应风格地址 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。注意基准测试会产生真实请求和费用建议先用小规模如 20 个请求验证脚本正确再放大到 200 请求。所有 Key 请通过环境变量注入不要硬编码进脚本。3. 可复制的基准脚本配置与指标采集命令3.1 环境变量与统一配置片段先建一个.env或直接 export把 Base URL、Key、模型名三件套固定下来。这是整个流程能复用的关键。export TAOTOKEN_BASE_URLhttps://taotoken.net/api export TAOTOKEN_API_KEYsk-你的Key export BENCH_MODEL你的模型ID对应的 Python 配置片段建议单独放一个config.py方便脚本 importimport os BASE_URL os.environ[TAOTOKEN_BASE_URL] API_KEY os.environ[TAOTOKEN_API_KEY] MODEL_ID os.environ.get(BENCH_MODEL, default-model) # 基准测试参数 CONCURRENCY 8 # 并发数 NUM_REQUESTS 100 # 总请求数 MAX_TOKENS 256 # 每个请求最大输出 PROMPT_TOKENS 512 # 输入长度近似 TEMPERATURE 0.0 # 基准测试固定为 0保证可复现如果你用 JSON 配置文件管理多组实验可以这样写bench_config.json{ base_url: https://taotoken.net/api, model: your-model-id, concurrency: 8, num_requests: 100, max_tokens: 256, prompt_tokens: 512, temperature: 0.0, stream: true }3.2 流式请求与 TTFT/TPOT 采集脚本核心思路用流式接口记录首 Token 到达时间和最后一个 Token 到达时间从 usage 或本地 tokenizer 拿 Token 数。下面是一个可直接运行的采集脚本bench.pyimport time, json, statistics from concurrent.futures import ThreadPoolExecutor from openai import OpenAI from config import BASE_URL, API_KEY, MODEL_ID, CONCURRENCY, NUM_REQUESTS, MAX_TOKENS, PROMPT_TOKENS, TEMPERATURE client OpenAI(base_urlBASE_URL, api_keyAPI_KEY) def build_prompt(n_tokens): # 用重复文本近似构造指定长度的输入 return 请阅读以下内容并简要总结 (基准测试输入填充。 * (n_tokens // 8)) def one_request(idx): prompt build_prompt(PROMPT_TOKENS) start time.perf_counter() ttft None last None out_tokens 0 try: stream client.chat.completions.create( modelMODEL_ID, messages[{role: user, content: prompt}], max_tokensMAX_TOKENS, temperatureTEMPERATURE, streamTrue, ) for chunk in stream: delta chunk.choices[0].delta.content if delta: now time.perf_counter() if ttft is None: ttft now - start last now out_tokens 1 e2e last - start tpot (e2e - ttft) / max(out_tokens - 1, 1) return {ok: True, ttft: ttft, e2e: e2e, tpot: tpot, out_tokens: out_tokens} except Exception as e: return {ok: False, error: str(e)} def main(): results [] with ThreadPoolExecutor(max_workersCONCURRENCY) as pool: for r in pool.map(one_request, range(NUM_REQUESTS)): results.append(r) ok [r for r in results if r[ok]] err len(results) - len(ok) if ok: print(json.dumps({ requests: len(results), errors: err, error_rate: err / len(results), ttft_p50: statistics.median([r[ttft] for r in ok]), ttft_p95: sorted([r[ttft] for r in ok])[int(len(ok)*0.95)-1], tpot_p50: statistics.median([r[tpot] for r in ok]), e2e_p50: statistics.median([r[e2e] for r in ok]), output_throughput: sum(r[out_tokens] for r in ok) / sum(r[e2e] for r in ok), }, ensure_asciiFalse, indent2)) if __name__ __main__: main()运行命令python bench.py | tee result_$(date %s).json这个脚本输出 P50/P95 的 TTFT、TPOT、端到端延迟以及输出吞吐和错误率。P95 比平均值更能反映用户体验的尾部情况做 SLO 评估时优先看它。3.3 用 guidellm 做交叉验证自研脚本适合快速迭代但为了结果可信建议再用社区工具交叉验证一次。guidellm 支持 OpenAI 兼容端点安装后指向同一个 Base URL 即可pip install guidellm guidellm benchmark \ --target https://taotoken.net/api \ --model $BENCH_MODEL \ --rate-type constant \ --rate 4 \ --max-seconds 60 \ --data prompt_tokens512,output_tokens256注意 guidellm 的鉴权通过环境变量OPENAI_API_KEY读取跑之前先export OPENAI_API_KEY$TAOTOKEN_API_KEY。两套工具跑出来的 TTFT 若差异在 10% 以内说明你的自研脚本口径基本正确。4. 验证请求与成功结果解读4.1 先发一个最小请求确认通道在跑全量基准前先用一条 curl 确认 Base URL、Key、模型名三件套都对curl -s https://taotoken.net/api/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: $BENCH_MODEL, messages: [{role: user, content: 只回复ok}], max_tokens: 8, stream: false }返回里能看到choices[0].message.content和usage字段就说明通道正常。usage.prompt_tokens和usage.completion_tokens是后续计算吞吐的基准务必确认它们存在。4.2 结果对照表怎么读跑完 100 个请求后你会得到类似下面的输出。把它整理成对照表横向对比不同模型或不同并发指标并发 4并发 8并发 16TTFT P50 (ms)4206101180TTFT P95 (ms)78013502900TPOT P50 (ms)283147端到端 P50 (s)7.68.412.9输出吞吐 (tok/s)142258341错误率0%0%2%读法并发从 4 升到 8吞吐几乎翻倍而 TTFT 只涨了 45%说明系统还有余量升到 16 时吞吐增幅变小、TTFT P95 暴涨、开始出现错误说明已经接近饱和点。这个「饱和点」就是容量规划的关键数字。显存方面如果并发 16 时出现 OOM 或错误率跳升优先怀疑 KV Cache 不足而不是算力不够。4.3 复现验证步骤要让别人能复现你的结果至少固定四件事模型 ID、输入输出长度分布、并发与请求总数、temperature0。把bench_config.json和结果 JSON 一起存档注明运行时间和环境。换机器或换时间重跑若 TTFT 波动超过 20%先排查是不是共享 GPU 或网络抖动而不是急着下结论。5. 常见报错排查对照表基准测试跑不起来九成是下面几类问题。按报错信息对照处理报错/现象可能原因处理方式401 UnauthorizedKey 错误、未带 Bearer 前缀、环境变量没生效检查Authorization: Bearer $KEYecho $TAOTOKEN_API_KEY确认非空404 model not found模型 ID 拼写错误或该模型未开通去模型对话页确认可用模型名注意大小写local proxy failed / connection refused本地代理拦截、Base URL 写错确认 Base URL 为https://taotoken.net/api关闭本地代理干扰reading choices 报错 / KeyError choices返回体不是预期结构通常是鉴权失败返回了错误 JSON打印原始 response.text先看是不是 401/429OAuth / token expiredKey 过期或被禁用到控制台重新生成 Key429 Too Many Requests触发限流降低并发加指数退避重试结果 TTFT 异常小50ms请求被缓存或根本没发出检查是否真的流式、是否复用了连接错误率随并发线性上升达到服务端并发上限记录饱和点作为容量规划依据提示遇到reading choices这类解析错误不要急着改脚本先把response.status_code和response.text打出来八成是鉴权或限流问题伪装成了结构错误。排查顺序建议先 curl 单请求 → 再单线程跑 5 个 → 再上并发。每一步都确认通过再往下能省掉大量猜测时间。6. 把基准测试接入你的日常开发流程跑通一次不难难的是让它持续产生价值。我的做法是把bench.py和bench_config.json放进项目仓库每次换模型、调参数或升级推理框架后跑一轮 100 请求的基准把结果 JSON 追加到一个bench_history/目录。这样几周后你就有了一条性能曲线能清楚看到某次改动到底带来了多少提升。如果你要做长期的模型对比和 Agent 场景压测可以考虑用 Coding Plan 把多模型调用额度统一管理地址 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 这样基准脚本和实际业务共用一套 Key切换模型时不用改两处配置。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有完整的参数说明和示例遇到字段不确定时先查文档再改脚本。最后一个实用技巧把 TTFT P95 和错误率设成 CI 里的软阈值比如 P95 超过 2s 或错误率超过 1% 就打印警告。它不会阻塞合并但能让你在性能悄悄退化时第一时间发现。基准测试的价值不在于跑出一个漂亮数字而在于让性能变化可见、可追溯、可复现。
返回列表