别再只看 tok/s:我做了一套开源的本地大模型标准测试工具 LLST
导读与项目速览
– 开源协议:Apache-2.0
– 当前版本:v1.0.0-rc1(Release Candidate)
– 核心特性:Manifest 锁定 102 道固定样本、Token 级确定性负载、Tokenizer 指纹校验、Docker 沙箱隔离
– 支持后端:llama.cpp (llama-server)、vLLM、SGLang、Ollama 等任何标准 OpenAI-compatible API
– 首发案例:Baseline #001(双 AMD RX 7900 XTX 24GB + Qwen3.8-Flash-Next)
– GitHub 仓库:https://github.com/yang2020chen/local-llm-standard-test
一、 别再被 30 tok/s 绑架:本地模型到底该怎么测?
最近一直在高频测试各种本地大模型。随着测试的机器和模型越来越多,我遇到了一个比“哪个模型更快”更本质的问题:
本地大模型到底应该怎么测?
现在的评测很多时候最后都会简化成一句话:“这个模型在我的卡上能跑 30 tok/s。”
但 30 tok/s 到底代表什么?它仅仅说明在特定硬件与单批次无上下文的理想环境下,模型的单纯生成速度。它完全无法回答以下几个在实际生产中更致命的问题:
1. 真实能力如何:中文表现怎样?写代码能不能直接跑?数学与多步推理是不是明显偏弱?
2. 长文本代价多大:当上下文拉长到 4K、16K、28K 之后,速度会跌掉多少?
3. 真实交互延迟有多高:首字生成时间(TTFT)到底要等多久?
4. 横向可比性是否存在:换了一台机器、换了一套驱动后,两次跑出的数字到底能不能公平比较?
速度快,不代表模型真的好用。一个模型可能生成速度飞快,但指令遵循一塌糊涂、代码漏洞百出;另一个模型虽然慢了 3 tok/s,却能高质量胜任复杂的 Agent 任务。
为了打破这种“只看单一生成吞吐”的虚假跑分,我把过去积累的一整套测试方法抽象并开源成了一个标准工具:Local LLM Standard Test,简称 LLST。它不关心“谁的峰值数字好看”,而是一次性为本地用户回答模型能力、性能衰减、首字延迟以及长期可用性。
二、 LLST 的标准化架构:能力与压力双维度
LLST v1.0 的设计核心是:在完全相同的输入压力下,完成对模型能力与极限性能的标准化体检。整个流程由两大部分构成。
Local LLM Standard Test (LLST)
│
┌────────────────┴────────────────┐
▼ ▼
【Part 1: 能力基准测试】 【Part 2: 梯度压力测试】
102 道锁定样本 (固定评测集) 512 ~ 28K 确定性 Token 负载
│ │
└────────────────┬────────────────┘
▼
OpenAI-compatible API
│
┌───────────────────────┼───────────────────────┐
▼ ▼ ▼
llama.cpp / llama-server vLLM / SGLang Ollama
1. 第一部分:102 道固定能力测试
我们从 5 组主流 Benchmark 中抽取出 102 道具有高度代表性的核心题目:
| Benchmark | 题量 | 核心考察能力 | 样本锁定与验证机制 |
|---|---|---|---|
| MMLU-Pro | 42 | 综合专业知识与多步推理 | Manifest Hash 校验 |
| IFEval | 20 | 严格格式与约束遵循能力 | 确定性格式断言 |
| AIME-2024 | 10 | 高难度数学与逻辑推导 | 严格数值比对 |
| C-Eval | 20 | 中文通识与专业知识 | 四选一客观选择题 |
| LiveCodeBench | 10 | 真实代码生成与解决逻辑 | Docker Sandbox 隔离运行 |
| 总计 | 102 | 全方位综合体检 | 全量 Manifest 防漂移 |
拒绝隐式漂移:很多传统测试仅靠指定
limit=10抽取题目,一旦上游数据集发生更新,半年后跑出来的已经不是同一套题。LLST 将每个样本的sample_id、prompt_sha256、target_sha256和record_sha256固化在清单中。测试启动前进行全量离线切片自检,任何一道题发生篡改或漂移,直接终止测试。
2. 第二部分:确定性长上下文性能测试
性能测试固定四档真实压力梯度,统一参数为 Parallel=1、Temperature=0、Stream=true,每档重复采样:
- 512 Tokens 输入 $\rightarrow$ 固定输出 512 Tokens
- 4,096 Tokens 输入 $\rightarrow$ 固定输出 512 Tokens
- 16,384 Tokens 输入 $\rightarrow$ 固定输出 512 Tokens
- 28,672 Tokens 输入 $\rightarrow$ 固定输出 512 Tokens
评测将精准采集 TTFT(首字延迟)、TPOT(单 Token 生成耗时)、Decode Throughput(生成吞吐) 以及 总吞吐,真实展现长上下文下的性能衰减曲线。
三、 为什么普通跑分不可靠?LLST 的 4 层“防坑”工程设计
在开发 LLST 的过程中,我踩过数个极其隐蔽但影响巨大的大坑。正是为了解决这些问题,LLST 构筑了 4 层严谨的工程防御体系:
1. Token 级精准负载(杜绝字符长度翻倍陷阱)
最初测试长上下文时,我曾使用常规工具生成固定长度的纯文本字符串。理论设定的字符输入为 1 / 6144 / 14336 / 30720,结果服务端实际解析出的 Token 数量却变成了 2 / 12288 / 28672 / 61440——整整翻了一倍,最后一档甚至直接击穿了 32K 显存上限导致服务崩溃!
原因在于:字符数绝不等于 Token 数。不同架构、不同语言环境下,Tokenizer 拆分逻辑大相径庭。因此,LLST 彻底摒弃字符估算,在测试端实现 Token 级别的绝对数量锁定,确保输入进模型的压力不多不少正好是 512、4K、16K 和 28K。
2. 固定种子 Workload(保证绝对相同的输入压力)
即便 Token 数量一致,如果今天随机生成的 28K 文本全是简单重复单词,而明天生成的是高熵复杂代码,两台机器面临的注意力矩阵计算负荷依然不可比。LLST 使用固定随机种子 20260917,提前固化可复现的高压测试 Payload 并校验 SHA256,让 RTX 4090、RX 7900 XTX 与 Mac Studio 面对同一块“磨刀石”。
3. Tokenizer 指纹锁定(防止分词规则静默篡改)
同一个模型名称,不同发布者或不同量化分支中的 tokenizer.json 可能暗中发生微调。LLST 在运行前会自动采集并校验 Tokenizer 指纹(包含 Tokenizer 类名、词表规模 Vocab Size、核心配置文件 SHA256 以及特定 Token 行为序列 Hash)。只有在分词规则完全匹配时才允许产生对比数据。
4. Docker 沙箱隔离与 Fail-Closed(安全与纪律红线)
LiveCodeBench 需要运行模型生成的代码。在宿主机裸机执行大模型未知代码等同于开门揖盗。LLST 强制要求代码评测必须在受限的 Docker Sandbox 容器中执行。
同时,系统内置针对篡改与环境异动的 N1~N5 故障注入校验机制:测试前进行环境自检,一旦发现 Prompt 篡改、ID 漂移、指纹异常或沙箱不可用,系统坚决执行熔断(Fail-Closed),彻底杜绝“差不多能跑”的糊涂账。
四、 3 分钟快速上手:Preflight、Smoke 到全量测试
LLST 已经完全工程化为开箱即用的命令行工具。
1. 安装与准备
# 克隆仓库
git clone https://github.com/yang2020chen/local-llm-standard-test.git
cd local-llm-standard-test
# 执行依赖与沙箱初始化
./scripts/install.sh
2. 配置机器环境
复制机器配置模板并填入本机的模型与 API 地址:
cp configs/machines/machine.example.yaml configs/machines/machine.local.yaml
在 machine.local.yaml 中指定模型参数与 API 路径,并通过环境变量配置密钥:
export LLST_API_KEY="your-local-api-key"
3. 三阶执行流程
# 步骤 1:环境与协议自检(数十秒验证 API、Tokenizer 与沙箱完整性)
./scripts/run_standard_test.sh --check
# 步骤 2:冒烟测试(极小步长端到端跑通,验证链路顺畅)
./scripts/run_standard_test.sh --smoke
# 步骤 3:正式启动全量标准体检
./scripts/run_standard_test.sh
测试结束后,系统会自动在控制台输出 Markdown 标准表格,并在 results/ 目录下生成包含全流程 SHA256 校验的完整报告。
五、 Baseline #001 实测:双 RX 7900 XTX 运行 Qwen3.8-Flash-Next
作为 LLST 的第一个实操范例,我们将这套标准应用在了一套极具代表性的高性价比硬件配置上:
# Baseline #001 硬件与模型环境
Hardware:
GPU: "2 × AMD Radeon RX 7900 XTX 24GB (总显存 48GB)"
Driver: "ROCm 6.2+"
Software:
Backend: "llama.cpp (llama-server)"
Model: "Qwen3.8-Flash-Next"
Quantization: "UD-Q3_K_XL (MTP 启用)"
Context Window: 32768 (32K)
1. 102 道题能力体检参考数据
数据客观性说明:当前
v1.0.0-rc1正在进行基于新版 Manifest 防漂移机制的全量自动化复验,Baseline #001 目前在仓库中标记为VALIDATING。以下为前一轮完整实测的参考表现:
| 评估维度 | 测试基准 | 题目数量 | 实测表现 | 综合准确率 |
|---|---|---|---|---|
| 知识推理 | MMLU-Pro | 42 | 37 / 42 | 88.10% |
| 指令遵循 | IFEval | 20 | Strict 汇总 | 100% * |
| 深度数学 | AIME-2024 | 10 | 3 / 10 | 30.00% |
| 中文通识 | C-Eval | 20 | 18 / 20 | 90.00% |
| 代码生成 | LiveCodeBench | 10 | 8 / 10 | 80.00% |
*注:关于 IFEval 结果,部分用例在不同评测器环境下的断言判定存在统计抖动,LLST 坚持客观保留原始记录,不刻意将其宣传为官方绝对满分。
2. 长上下文实测:颠覆认知的性能拐点
在 512 到 28,672 Tokens 的长上下文压力测试中,我们观察到了一个极具启发性的现象:
| 输入 Token 负载 | 固定输出长度 | 首字延迟 (TTFT) | 生成速度 (Decode) |
|---|---|---|---|
| 512 | 512 | 1.24 s | 28.24 tok/s |
| 4,096 | 512 | 4.66 s | 27.85 tok/s |
| 16,384 | 512 | 21.04 s | 26.50 tok/s |
| 28,672 | 512 | 38.13 s | 25.43 tok/s |
关键发现:杀死长文本体验的不是生成,而是 Prefill!
- Decode 吞吐极其稳健:从 512 Tokens 暴增至 28,672 Tokens(上下文扩大了整整 56 倍),生成速度仅仅从
28.24 tok/s轻微滑落到25.43 tok/s,仅下降了约 10%!在双 7900 XTX 充足的显存带宽支撑下,模型在生成阶段完全没有崩溃。 - TTFT 呈现几何级暴增:真正产生断崖式体验落差的是首字等待时间——从 512 时的 1.24 秒直接暴增到 28K 时的 38.13 秒。
这给实际生产带来了极其明确的工程指导:
模型支持 32K 上下文,绝对不意味着我们在日常对话或多轮 Agent 中应该长期塞满 32K。如果你让模型处理 28K 的全量历史,每次敲下回车都要等待近 40 秒才有反应。上下文的智能管理(Prompt 裁剪、动态 RAG、定期对话摘要与 Memory 压缩)本身就是最立竿见影的性能优化。
六、 常见问题 (FAQ)
Q1:LLST 与官方的 llama-bench 有什么本质区别?
A:两者定位互补但关注层级完全不同:
– llama-bench:适合纯硬件与底层的微基准测试(如 GPU 算力利用率、不同量化类型的内联汇编加速、Prompt Processing 纯内核吞吐)。
– LLST:关注的是“一个已经部署完毕、暴露标准 OpenAI API 的模型服务”,在面对真实业务调用时的综合能力表现。它不仅测吞吐,还测代码能否跑通、指令能否遵循、首字延迟多长。无论底层使用的是 llama.cpp、vLLM 还是 SGLang,都可以用同一套协议进行评测。
Q2:普通消费级单卡(如 12GB/16GB 显存)可以使用 LLST 吗?
A:完全可以。在 machine.local.yaml 中,你可以根据本机的物理显存显式指定受支持的上下文上限(例如截断至 8K 或 16K),同时全量 102 道能力评测可以在任何能跑起本地模型服务的机器上无缝执行。
Q3:正式的 v1.0.0 Stable 什么时候发布?
A:目前 v1.0.0-rc1 正式版本已经发布在 GitHub。一旦当前这轮由自动化脚本推进的 102 题 + 8 次梯度压力验收完全通过,Baseline #001 的状态将转为 Verified,项目也将正式步入 v1.0.0 Stable。
七、 开源与后续:建立真实硬件的本地评测数据库
这套工具最开始只是为了满足我自己换卡、换驱动、对比模型时的自用需求。但我逐渐意识到:比起某一次孤立的跑分数据,让更多人拥有一把标准、防篡改的“尺子”才更有意义。
Baseline #001 仅仅是一个起点。依托于这套固定且透明的测试协议,后续我们将持续推进更丰富的真实环境横向对比:
– Baseline #002:Qwen3.8-27B 完整规格实测
– Baseline #003:主流 MoE 架构模型真实表现
– Baseline #004:24GB 单卡 vs 48GB 双卡性能与上下文边界
– Baseline #005:AMD ROCm 与 NVIDIA CUDA 平台横向对标
– Baseline #006:Mac Studio (Apple Silicon) 统一内存实机表现
我们非常欢迎社区使用 LLST 测试你自己的显卡与模型,并将你的配置文件与结果提交至仓库,共同构建一个不掺杂宣传水分、真正属于本地玩家的真实硬件基准数据库。
╔════════════════════════════════════════════════════════════════════════╗
║ 🛠️ Local LLM Standard Test (LLST) ║
╠════════════════════════════════════════════════════════════════════════╣
║ 🌐 GitHub 仓库: https://github.com/yang2020chen/local-llm-standard-test ║
║ 📦 当前版本: v1.0.0-rc1 (Release Candidate) ║
║ 📜 开源协议: Apache-2.0 License ║
║ ║
║ 🎯 核心使命: 拒绝虚假 tok/s,用一套标准尺子完成本地大模型真实能力体检 ║
║ 💡 欢迎 Star 支持与提交 Issue / PR 补充你的机器 Baseline! ║
╚════════════════════════════════════════════════════════════════════════╝
1 thought on “别再只看 tok/s:我做了一套开源的本地大模型标准测试工具 LLST”