165 lines
7.6 KiB
Markdown
165 lines
7.6 KiB
Markdown
# ⚡ LLM 速度测试台
|
||
|
||
大模型推理性能基准测试工具,用于测量不同上下文长度下的 **预填充速度(prefill)**、**首字延迟(TTFT)** 与 **解码吞吐(decode)**,并以网页 + Excel 形式输出结果。
|
||
|
||
- **访问地址:** `http://<IP>:16097/`
|
||
- **技术栈:** Python 3 + Flask + SQLite(纯 REST,无额外依赖)
|
||
- **版本:** v2.0.0
|
||
|
||
---
|
||
|
||
## 功能特性
|
||
|
||
### 🔌 大模型接口配置
|
||
- 支持 **OpenAI 兼容**(OpenAI / DeepSeek / 火山方舟 / 任意兼容网关)、**Anthropic(Claude)**、**Google Gemini** 三类提供商
|
||
- 配置项:配置名称、Base URL(留空自动使用官方默认)、API Key(可显示/隐藏)、模型名称、温度
|
||
- 配置可**保存/加载/删除**,方便多模型对比
|
||
|
||
### 🚀 速度测试配置
|
||
- **测试名称(主题)**:可为每次测试命名,用于标注测试内容/主题,展示在历史列表、详情弹窗与导出报表中
|
||
- **多上下文长度测试**:默认为 `512 / 2048 / 8192 / 32768 / 131072` tokens,可通过标签点击启用/禁用,并支持手动添加任意自定义长度(≥16)
|
||
- **解码输出长度(max tokens)**:默认为 `128`,可手动自定义
|
||
- **每个长度采样次数**:默认为 `2`,可手动自定义
|
||
- **测试前预热(空转)**:默认开启,先发一次不计速度的空转请求,避免冷启动/首请求偏慢污染真实采样数据
|
||
- **避免缓存**:默认开启,为每次采样追加随机前缀,测量真实预填充性能
|
||
|
||
### 📊 指标与结果
|
||
- 实时指标卡:首字延迟、预填充速度、解码速度、上文/输出 tokens、总耗时
|
||
- **整体统计(平均/最小/最大)**:详情弹窗与 Excel 汇总展示首字延迟、预填充速度、解码速度、总耗时的平均/最小/最大
|
||
- **推理型模型兼容**:支持 Qwen3 / DeepSeek 等思维链模型(`reasoning_content` / `thinking` / `thought`),思维过程计入输出,不会误报“未收到输出”
|
||
- **采样失败不中断**:单次采样失败会记录并继续,不会让整个测试半途终止;全部失败才标记 error
|
||
- 实时控制台日志:校准、预热、每次采样明细全程可追溯
|
||
- **每次完整测试**支持:
|
||
- **网页点击查看**:历史记录「查看」按钮弹出详情(整体统计 + 按上下文长度分组 + 每次采样明细 + 完整日志)
|
||
- **文件下载 Excel(xlsx)**:历史记录「Excel」按钮或详情弹窗「导出 Excel」,包含 汇总 / 采样明细 / 日志 三个 Sheet
|
||
- **文件下载 JSON**:详情弹窗「导出 JSON」
|
||
- 测试历史留存(含测试名称),可随时刷新、查看、导出、删除
|
||
|
||
### 🔌 开放 API
|
||
- 页面所有功能均通过 REST API 提供,前端只是可视化客户端
|
||
- **API 文档见 [API.md](API.md)**
|
||
|
||
---
|
||
|
||
## 快速开始
|
||
|
||
### 环境要求
|
||
- Python 3.10+(推荐使用 openclaw conda 环境)
|
||
- 依赖见 `requirements.txt`
|
||
|
||
### 安装
|
||
```bash
|
||
pip install -r requirements.txt
|
||
# 或使用 conda 环境
|
||
/home/hz1/miniconda3/envs/openclaw/bin/pip install -r requirements.txt
|
||
```
|
||
|
||
### 启动
|
||
```bash
|
||
./start.sh # 启动(默认端口 16097)
|
||
./start.sh stop # 停止
|
||
./start.sh restart # 重启
|
||
```
|
||
|
||
启动成功后访问 `http://<IP>:16097/`。
|
||
|
||
---
|
||
|
||
## 使用说明
|
||
|
||
1. **配置接口**:选择提供商 → 填写配置名称 / Base URL(可留空)/ API Key / 模型名称 → 点「保存」可留存,或直接点「🔍 测试连接」验证连通性
|
||
2. **配置测试参数**:勾选要测试的上下文长度(默认 5 档),设置解码输出长度与采样次数,按需开关预热/避免缓存
|
||
3. **开始测试**:点「▶ 开始测试」,右侧实时展示指标与日志;可随时「■ 停止」
|
||
4. **查看与导出**:测试完成后,在「测试历史」中点「查看」看完整详情,点「Excel」或详情内「导出 Excel」下载 xlsx 报告
|
||
|
||
### 指标含义
|
||
| 指标 | 含义 |
|
||
|------|------|
|
||
| 首字延迟 TTFT (ms) | 从请求发出到收到第一个 token 的时间(含预填充) |
|
||
| 预填充速度 (tok/s) | prompt tokens / 首字延迟,衡量上文处理吞吐 |
|
||
| 解码速度 (tok/s) | 输出 tokens / 解码阶段耗时,衡量逐 token 生成吞吐 |
|
||
| 上下文/输出 tokens | 实际发送的提示词 token 数与模型返回的 token 数 |
|
||
|
||
---
|
||
|
||
## API
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/api/health` | 健康检查 |
|
||
| GET/POST | `/api/configs` | 配置列表 / 新增配置 |
|
||
| GET/PUT/DELETE | `/api/configs/<id>` | 单个配置 / 更新(局部)/ 删除 |
|
||
| POST | `/api/configs/test` | 测试连接 |
|
||
| GET/POST | `/api/tests?limit=n` | 测试历史 / 启动测试(异步) |
|
||
| GET | `/api/tests/<id>` | 测试详情(含 runs / logs / summary / 按长度分组) |
|
||
| GET | `/api/tests/<id>/logs?after=<id>` | 增量日志(前端轮询用) |
|
||
| POST | `/api/tests/<id>/cancel` | 停止测试 |
|
||
| DELETE | `/api/tests/<id>` | 删除测试 |
|
||
| GET | `/api/tests/<id>/export.xlsx` | 导出 Excel 报告(汇总/采样明细/日志三 Sheet) |
|
||
| GET | `/api/tests/<id>/export.json` | 导出完整测试 JSON |
|
||
|
||
> 完整字段说明、响应示例与 curl 示例见 **API.md**。
|
||
|
||
### 启动测试请求示例
|
||
```json
|
||
POST /api/tests
|
||
{
|
||
"config": {
|
||
"provider": "openai",
|
||
"name": "DeepSeek-V4",
|
||
"base_url": "https://api.deepseek.com/v1",
|
||
"api_key": "sk-xxx",
|
||
"model": "deepseek-chat",
|
||
"temperature": 0.7
|
||
},
|
||
"gen": {
|
||
"context_lengths": [512, 2048, 8192, 32768, 131072],
|
||
"max_tokens": 128,
|
||
"samples": 2,
|
||
"warmup": true,
|
||
"avoid_cache": true
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
llm-speed-tester/
|
||
├── app.py # Flask 主应用(路由 + Excel 导出)
|
||
├── config.py # 全局配置(端口/超时/路径)
|
||
├── database.py # SQLite 存储(配置/测试/采样/日志)
|
||
├── tester.py # 测试执行器(校准 → 预热 → 多长度采样 → 汇总)
|
||
├── llm_providers.py # 提供商适配器(OpenAI / Anthropic / Gemini)
|
||
├── requirements.txt
|
||
├── start.sh # 启动/停止脚本
|
||
├── static/ # 前端(index.html / js/app.js / css/style.css)
|
||
├── data/ # SQLite 数据库(llm_speed_tester.db)
|
||
└── logs/ # 运行日志 + PID
|
||
```
|
||
|
||
### 测试执行流程
|
||
1. **校准**:发送一个短探测请求,估算 `token/字符` 比例
|
||
2. **逐上下文长度**:对每个选中的长度构造对应 token 量的基准提示词
|
||
3. **预热(空转,不计速度)**:每个长度先发一次请求,规避冷启动偏差
|
||
4. **采样**:每个长度按采样次数重复请求,记录每次指标
|
||
5. **汇总**:按长度分组 + 整体平均,写入测试记录
|
||
|
||
---
|
||
|
||
## 常见问题
|
||
|
||
- **连接测试提示“未收到任何输出内容”**:多为推理型模型(Qwen3/DeepSeek 思维链)或只返回 usage 的网关。已兼容 `reasoning_content` 等思维字段,连接成功即视为通过;若仍出现,请检查 API Key/Base URL/模型名。
|
||
- **无 openpyxl**:`pip install openpyxl`(已加入 requirements.txt)
|
||
- **老版本数据库**:程序启动时自动迁移,为 `test_runs` 表补充 `context_length` 列,无需手动处理
|
||
- **慢模型/长上文超时**:连接超时 60s、两次数据包间隔 300s(`config.STREAM_READ_TIMEOUT` 可调);推理型模型思考阶段停顿不计超时,超长文(131072)生成慢属正常,请耐心等待
|
||
|
||
---
|
||
|
||
## Git
|
||
|
||
- **仓库:** `hz4th_coder/llm-speed-tester`
|
||
- **版本:** v2.1.0(多上下文长度测试 + 预热 + Excel/JSON 导出 + 测试名称 + 整体统计平均/最小/最大 + 开放 API + 推理型模型兼容)
|