☰
大模型推理服务性能压测教程:用 llm_benchmark.py 测透 TTFT 与吞吐,TaoToken 统一 Key 接入
2026/10/10 12:30:42 网站建设 项目流程

1. 上线前不压测,等于把事故留给用户

大模型推理服务性能压测,说白了就是在服务正式对外之前,用一套可复现的脚本把它的极限摸清楚。你要回答三个问题:首 Token 多久能吐出来(TTFT)、每秒能稳定生成多少 Token(吞吐)、并发涨到多少开始崩(饱和点)。这三个数不测,容量规划就是拍脑袋,线上第一次流量高峰就会教你做人。

我见过太多团队的做法是:本地 curl 发一条请求,看到有返回就认为服务没问题。结果上线后 20 个用户同时提问,TTFT 从 0.1 秒飙到 5 秒,前端转圈转到用户关页面。问题不在于模型不行,而在于没人系统性地跑过并发梯度。

这篇教程围绕llm_benchmark.py这个压测脚本展开,它针对 Chat 类大模型接口设计,兼容 OpenAI Chat Completion 流式格式,能一次性输出 TTFT 的 avg/p50/p90/p99、单请求生成速率、系统总 TPS、QPS 和端到端延迟分布。适合谁:负责推理服务上线的后端工程师、做模型部署的算法同学、需要写性能验收报告的技术负责人。

测试矩阵按 T1 到 T4 四组场景设计,从最短输出到长文生成,覆盖真实业务里从"打招呼"到"写文档"的全部形态。同时我会演示怎么用 TaoToken 的统一 Key 和 API 通道接入被测服务——这样你压测不同模型时不用来回改鉴权逻辑,一套 Key 打通多个推理端点,横向对比时特别省事。

判定标准也很直接:TTFT P90 突增说明排队严重,system_tps 涨幅低于 5% 说明到饱和点了,失败率大于 0 说明服务扛不住当前并发。下面从环境准备开始,一步步走完。

2. 压测环境准备与 llm_benchmark.py 参数速查

2.1 客户端环境

压测客户端建议用 Linux,openEuler 或 Ubuntu 都行,Python 版本不低于 3.8。核心依赖只有一个 aiohttp,因为脚本用异步协程发流式请求,同步库在高并发下会拖后腿。

pip install aiohttp --break-system-packages # 若系统有保护,可加 --user

网络这块有个坑要提前说:压测客户端和被测服务尽量在同一内网,避免公网延迟污染 TTFT 数据。TTFT 本身就在百毫秒量级,公网抖动几十毫秒足以让结论失真。

把llm_benchmark.py下载到工作目录,可选赋执行权限:

chmod +x llm_benchmark.py

确认被测服务的地址和模型名,接口必须兼容 OpenAI Chat Completion 流式格式,也就是支持stream和stream_options。记录两个值:

URL: http://1xx.xx.xx.6x:233xx/v1/chat/completions Model: QwQ-32B

2.2 参数速查表

先跑一次帮助命令看全量参数:

python llm_benchmark.py --help

关键参数对照如下:

参数必填说明示例
--url是服务端 API 地址http://127.0.0.1:8000/v1/chat/completions
--model是模型名称,须服务端识别Qwen2.5-14B
--prompt否测试用提示词,默认脚本内置"你好"
--max-tokens否最大输出 token 数,默认 5122048
--timeout否单请求超时秒数,默认 120180
--num-requests否每个并发档位的请求总数,默认 20,建议 ≥5050
--concurrency否固定单一并发数,与 sweep 二选一10
--concurrency-sweep否并发扫描档位,逗号分隔1,5,10,20,50
--api-key否服务需要认证时填 Bearer 后的值sk-xxx

--num-requests这个参数值得单独强调。分位数 P90/P99 的统计意义依赖样本量,脚本在成功样本数小于 10 时会打印警告。想拿到可信的 P99,每个档位至少 50 个请求,100 个更稳。

2.3 用 TaoToken 统一 Key 接入被测服务

压测经常要横向对比多个模型,如果每个模型一套鉴权、一个地址,脚本参数改到崩溃。TaoToken 提供统一的 Key 和 API 通道,把不同推理端点收敛到一个入口,压测时只改--model就行。

先在控制台创建 API Key:

https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=console

拿到 Key 后,把被测地址指向 TaoToken 的 API 入口,鉴权用同一个 Key:

python llm_benchmark.py \ --url https://taotoken.net/api/v1/chat/completions \ --model QwQ-32B \ --api-key sk-你的Key \ --concurrency-sweep 1,5,10,20,50 \ --num-requests 50

这样 T1 到 T4 四组场景、多个模型,全部共用一套鉴权。API 入口是https://taotoken.net/api,注意这个地址不带 UTM 参数,直接用于脚本配置。Key 的管理和轮换在 API Keys 页面:

https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=api-keys

如果你要压测的是自建推理服务,也可以把 TaoToken 当作对照基准——同一套脚本、同一套 Key,分别打自建端点和统一通道,横向数据直接可比。

3. 可复制的压测配置与四场景测试矩阵

3.1 测试场景设计 T1~T4

压测不能只测一种输入。短输出和长输出的瓶颈完全不同:短输出考验调度和 prefill,长输出考验 decode 阶段的持续吞吐。所以设计四组场景:

场景编号场景名称--max-tokensprompt 核心目的
T1TTFT 基线16"你好"排除生成耗时,获取纯调度/prefill 延迟基线
T2实时对话64"用一句话总结人工智能在建筑领域最核心的应用。"模拟实时交互,体验响应速度
T3基准场景512"请详细介绍一下人工智能在建筑行业的应用场景,包括但不限于智能监控、人脸识别等方面,尽量展开说明。"横向对比主场景,最贴近业务
T4文书生成2048与 T3 相同 prompt隔离输出长度变量,测试长输出稳定性

关键点:T3 和 T4 必须用相同 prompt,只有--max-tokens不同。这样才能干净地对比输出长度对 TPS 的影响,否则 prompt 一变,prefill 成本也变了,结论就不纯。

3.2 单场景并发扫描

以 T3 为例,跑一次并发扫描:

python llm_benchmark.py \ --url https://taotoken.net/api/v1/chat/completions \ --model QwQ-32B \ --api-key sk-你的Key \ --prompt "请详细介绍一下人工智能在建筑行业的应用场景,包括但不限于智能监控、人脸识别等方面,尽量展开说明。" \ --max-tokens 512 \ --timeout 120 \ --num-requests 50 \ --concurrency-sweep 1,5,10,20,50

3.3 四场景自动化脚本

手动跑四遍容易漏参数,写个 Shell 脚本顺序执行,每次之间 sleep 5 秒让服务恢复:

#!/bin/bash MODEL_URL="https://taotoken.net/api/v1/chat/completions" MODEL_NAME="QwQ-32B" API_KEY="sk-你的Key" # T1 python llm_benchmark.py --url $MODEL_URL --model $MODEL_NAME --api-key $API_KEY \ --prompt "你好" --max-tokens 16 --timeout 120 --num-requests 50 \ --concurrency-sweep 1,5,10,20,50 sleep 5 # T2 python llm_benchmark.py --url $MODEL_URL --model $MODEL_NAME --api-key $API_KEY \ --prompt "用一句话总结人工智能在建筑领域最核心的应用。" --max-tokens 64 \ --timeout 120 --num-requests 50 --concurrency-sweep 1,5,10,20,50 sleep 5 # T3 python llm_benchmark.py --url $MODEL_URL --model $MODEL_NAME --api-key $API_KEY \ --prompt "请详细介绍一下人工智能在建筑行业的应用场景,包括但不限于智能监控、人脸识别等方面,尽量展开说明。" \ --max-tokens 512 --timeout 120 --num-requests 50 --concurrency-sweep 1,5,10,20,50 sleep 5 # T4 python llm_benchmark.py --url $MODEL_URL --model $MODEL_NAME --api-key $API_KEY \ --prompt "请详细介绍一下人工智能在建筑行业的应用场景,包括但不限于智能监控、人脸识别等方面,尽量展开说明。" \ --max-tokens 2048 --timeout 120 --num-requests 50 --concurrency-sweep 1,5,10,20,50

T4 高并发下如果大量超时,脚本可能卡住,可以提前 Ctrl+C 终止该档位,记录失败率后继续下一档。输出重定向到日志文件,方便后续提取数据:

bash run_test.sh 2>&1 | tee model_name_T3.log

3.4 用 settings 片段固化配置

如果你用 Cline 或 Claude Code 这类工具做压测编排,可以把连接配置写成 JSON,避免每次手敲参数。以 Cline MCP 风格的配置为例:

{ "mcpServers": { "llm-benchmark": { "command": "python", "args": ["llm_benchmark.py"], "env": { "BASE_URL": "https://taotoken.net/api/v1/chat/completions", "API_KEY": "sk-你的Key", "MODEL_ID": "QwQ-32B" } } } }

三件套记牢:Base URL 指向https://taotoken.net/api,Key 用控制台创建的,Model ID 填服务端能识别的模型名。这三者缺一不可,配错任何一个都会在验证阶段报错。

4. 验证请求与成功结果解读

4.1 脚本输出示例

跑完一轮并发扫描,终端会打印每个档位的汇总。以并发 50 为例:

并发数: 50 | 请求数: 50 (成功 50 / 失败 0) 墙钟总耗时: 52.34s | QPS: 0.96 系统总Token吞吐 (system TPS): 1003.44 tokens/s <-- 核心并发能力指标 单请求平均生成速率: 39.87 tokens/s TTFT avg/p50/p90/p99: 0.083s / 0.083s / 0.091s / 0.097s 总延迟 avg/p50/p90/p99: 12.84s / 12.58s / 13.51s / 14.05s

看到这组数,说明服务在 50 并发下还没崩:失败率 0,TTFT P99 不到 0.1 秒,系统吞吐稳定在 1000 tokens/s 以上。

4.2 指标定义与业务含义

指标含义业务意义
TTFT P50/P90/P99首 Token 延迟分布用户感知的"响应速度",P90 反映绝大多数体验
system_tps所有请求累计 token 数 ÷ 墙钟总耗时服务端总吞吐能力,横向对比核心
单请求平均生成速率token 数 ÷ 该请求总耗时(纯生成阶段)模型本身生成速度,不含排队
总延迟 P50/P90/P99端到端完整响应耗时用户等待完整结果的时间
饱和拐点system_tps 不再随并发增加而增长的点容量规划上限,超过则排队加剧

4.3 关键判断规则

TTFT 劣化拐点:观察 TTFT P90 随并发变化。如果某个并发下突增,比如从 0.5 秒跳到 3 秒,说明服务开始严重排队,这个并发就是体验红线。

吞吐拐点:在汇总对比表里,当 system_tps 涨幅显著减小(低于 5%)或开始下降时,当前并发即为饱和点。继续加压只会让延迟涨、吞吐不涨。

稳定性:失败率大于 0% 说明服务不堪重负,需要降低并发或优化。哪怕只有 1 个失败,也要在报告里标注。

4.4 汇总对比表

脚本在多个档位跑完后会自动打印汇总表:

汇总对比表 (寻找系统吞吐的拐点/饱和点): 并发 成功率 系统TPS QPS TTFT_p50(s) TTFT_p90(s) 延迟_p50(s) 延迟_p90(s) 1 50/50 39.87 0.96 0.083 0.091 12.84 13.51 5 50/50 198.20 4.80 0.085 0.095 12.90 13.60 10 50/50 395.10 9.55 0.090 0.110 13.00 13.80 20 50/50 780.50 18.90 0.120 0.210 13.20 14.20 50 50/50 1003.44 24.30 0.150 0.460 13.50 15.10

从这张表能读出:并发从 1 涨到 50,system_tps 从 39 涨到 1003,但 20 到 50 这段涨幅明显放缓,TTFT P90 从 0.21 秒涨到 0.46 秒。说明 50 并发接近饱和,再往上加收益很小、延迟代价很大。

4.5 填写单请求基准(T3 并发=1)

从 T3 并发=1 的行里提取:平均 TTFT、单请求 TPS、平均总延迟。平均输出 Token 数/请求 ≈ 单请求 TPS × 平均总延迟。还要查服务端返回的finish_reason:如果输出 token 数远小于--max-tokens且 finish_reason 为 stop,说明模型提前结束,TPS 会虚高,报告里要注明。

5. 常见报错排查与真实错误对照

5.1 ModuleNotFoundError: No module named 'aiohttp'

脚本启动就报这个,说明依赖没装。执行:

pip install aiohttp

系统受限时加--user或--break-system-packages(Python 3.11+)。

5.2 HTTP 401: Unauthorized

这是压测里最高频的报错。原因通常是 Key 没传、传错,或者 Base URL 和 Key 不匹配。检查三点:--api-key是否填了 Bearer 后的值;URL 是否指向https://taotoken.net/api/v1/chat/completions;Key 是否在控制台被禁用或过期。重新在 API Keys 页面生成一个再试。

5.3 local proxy failed / connection refused

报错里出现 local proxy failed,一般是客户端网络配置问题,或者被测地址写错。先确认 URL 能通:

curl -I https://taotoken.net/api/v1/chat/completions

如果 curl 也失败,说明地址或网络层有问题,不是脚本的锅。注意不要用任何非正规网络工具,企业内网直接走正常出口即可。

5.4 reading choices 相关解析错误

脚本解析流式响应时,如果服务端返回格式不标准,可能报 choices 解析异常。检查服务端是否真的返回 OpenAI 兼容的 SSE 格式,每行以data:开头,最后有data: [DONE]。如果服务端返回的是自定义格式,需要改脚本的解析逻辑。

5.5 OAuth / 鉴权方式不匹配

有些服务用 OAuth 而非 Bearer Token,脚本默认发Authorization: Bearer xxx。如果服务端要求 OAuth 流程,需要先换 token 再填入--api-key。用 TaoToken 统一通道时不存在这个问题,标准 Bearer 即可。

5.6 高并发下大量超时

T4 场景 2048 tokens 输出,50 并发下很容易超时。两个处理办法:把--timeout调小(如 60s)让失败快速返回;或者直接 Ctrl+C 终止当前档位,记录失败率后继续。报告里注明"并发=50 时因超时主动终止"。

5.7 分位数不稳定

P90/P99 波动大,通常是样本太少。--num-requests至少 30,建议 50 以上。脚本在成功样本数小于 10 时会打印警告,看到警告就加请求数重测。

5.8 不同模型 sweep 档位不一致

横向对比时,所有模型的--concurrency-sweep必须一致,否则对比失去意义。如果某模型在 50 并发下全失败,仍执行 50 档并记录失败率,但性能数据留空。

5.9 能否测 Embedding 或 Reranker

本脚本只针对 Chat 类流式输出。Embedding/Reranker 有独立的压测脚本,指标是 sentences/s 或 pairs/s,用法类似但输出结构不同,别混用。

6. 用统一 Key 把压测流程固化下来

压测做完一轮,最有价值的不是某一次的绝对数字,而是可复现的对比能力。下次模型升级、服务扩容、参数调整,你要能用同一套脚本、同一套 Key、同一套场景矩阵再跑一遍,直接对比。

TaoToken 在这里的作用是把鉴权和地址收敛掉。你不需要为每个模型维护一套 Key,也不用在脚本里写一堆 if-else 切地址。Base URL 固定为https://taotoken.net/api,Key 在控制台统一管理,Model ID 按需切换。压测脚本里只改--model一个参数,横向对比就成立了。

如果你要长期做推理服务的性能验证,建议把压测纳入 CI 流程:每次模型版本更新自动跑 T1~T4,把 system_tps 和 TTFT P90 存进时序库,画趋势图。一旦某次更新导致 TTFT P90 劣化超过阈值,自动告警。这套流程的入口就是统一 Key 加固定脚本。

需要长期跑编码类 Agent 压测的,可以看 Coding Plan:

https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=coding-plan

想先手动验证模型返回是否正常,用模型对话页面发一条请求确认通道通:

https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=model-chat

接入细节和参数说明在文档里:

https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=doc

最后给一个实操建议:压测报告里一定要写清楚测试条件——客户端配置、网络环境、并发档位、请求数、prompt 内容、max-tokens。没有这些上下文,数字就是孤立的,别人无法复现,也无法判断你的结论是否可信。把run_test.sh和日志一起归档,下次对比时直接翻出来。

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

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

立即咨询