评测与部署:用 lmms-eval 量化抗幻觉,用 SGLang 把 VLM 推上线|多模态大模型专栏⑧

一句话讲透本篇:同一个模型、同一张图、两次 greedy 推理可能给出不同分数——这往往不是模型变差了,而是评分规则太脆弱。用 lmms-eval 跑标准基准、用 SGLang 部署服务,本篇打通从训练到上线的最后一公里。


写在前面

经过前七篇,文档 VLM 已经具备"看图答问、SFT 对齐、DPO 抗幻觉"的能力。但"训出来"不等于"能用"——还需回答两个问题:模型究竟有多好(评测),以及如何让它服务真实流量(部署)。

本篇覆盖评测与部署的完整链条。核心认知:VLM 评测远不如 NLP 稳定,部署也比纯 LLM 多几个坑(动态分辨率、视觉 token 显存)。一份零依赖 demo(评测稳定性)附带真实运行结果。

阅读本篇后可获得:

  • ✅ 识别 VLM 评测不稳定的三个根因,掌握"评分规则脆弱性"这一最可控因素
  • ✅ 选择文档 VLM 的最小验证集与对应评分规则(ANLS / relaxed acc / POPE F1)
  • ✅ 用 lmms-eval 一条命令跑通多个基准并正确解读报告
  • ✅ 用 SGLang 完成部署的五个生命周期步骤,掌握压测与量化决策

一、VLM 评测为何不稳定

VLM 评测有一个反直觉的特性:同样提示、两次 greedy 推理可能给出不同答案。这源于三个原因:

原因 机理 缓解
CUDA 非确定性 即使 do_sample=False + 固定 seed,attention kernel 在不同 batch 大小下浮点累加顺序不同,1e-4 级差异经 softmax 放大后可能改变 argmax 固定 batch_size=1,或多次跑取众数
Batch 组成漂移 padding 长度受同 batch 其他样本影响,改变某些算子的数值路径 评测时 batch_size=1(牺牲速度换确定性)
评分规则脆弱 "1,234 wan yuan" vs "1,234 万元" vs "1234 万元" 语义都对,exact match 只认第一个 用 benchmark 官方评分规则

第三个原因贡献最大且最易控制code/05_eval_deploy/eval_stability_demo.py(纯标准库可跑)用 ground truth "1,234 wan yuan" 与 10 个候选输出(前 8 个语义正确)演示:

评分规则对比(demo 实测)

候选输出 exact normalized edit-sim numeric
1,234 wan yuan(精确) 1.0 1.0 1.0 1.0
1,234 wan yuan(多空格) 0.0 1.0 0.93 1.0
1,234 wan yuan.(尾点) 0.0 1.0 0.93 1.0
1,234 万元(中文单位) 0.0 0.0 0.43 1.0
Revenue: 1,234 wan yuan(前缀) 0.0 0.0 0.61 1.0
12,345 wan yuan真错 0.0 0.0 0.80 0.0

exact 在 8 个正确答案里给 7 个打 0 分——这不是模型差,是评分规则差numeric match(抽取数字比较)对格式宽容、对幻觉数字严苛,是文档 VLM 的推荐规则。

同一模型、10 次运行的方差

模拟同一模型对同一图采样 10 次(仅表面形式变化),各评分规则的均值:

评分规则 10 次均值
exact 0.100(在 0 与 1 间剧烈摆动)
normalized exact 0.500
edit similarity 0.794
numeric match 0.800(稳定)

exact 的摆动是纯噪声——这就是"重跑评测得到不同分数"的根因。缓解策略:用仍能捕捉真实错误的最宽松规则(此处 numeric match),并对 N≥3 次运行取均值。


二、必跑基准与评分规则

文档 VLM 的最小验证集为 DocVQA + ChartQA + OCRBench + POPE,覆盖核心能力面(理解 + OCR + 抗幻觉):

Benchmark 测试内容 评分规则 文档相关度
DocVQA 文档 VQA ANLS(0–1 软分,非 exact match) ⭐⭐⭐⭐⭐
ChartQA 图表问答 relaxed accuracy(±5% 容差) ⭐⭐⭐⭐⭐
InfoVQA 信息密集文档 ANLS ⭐⭐⭐⭐⭐
OCRBench OCR 能力 专用 lookup table ⭐⭐⭐⭐
POPE 物体存在幻觉 F1 / accuracy ⭐⭐
HallusionBench 综合幻觉 自定义 ⭐⭐⭐

三条评分规则速记:

  • ANLS(Average Normalized Levenshtein Similarity):(1 − edit_distance / max_len),0–1 连续分,允许拼写小错。DocVQA / InfoVQA 采用。
  • relaxed accuracy:数字答案在 GT ±5% 内即算对。ChartQA 采用。
  • POPE F1:是/否二分类看 F1 而非 accuracy——因为"否"占多数会刷高 accuracy,掩盖保守倾向。

三、lmms-eval 实操

lmms-eval 一条命令跑多个 benchmark,自动支持 Qwen2-VL / LLaVA / InternVL,自动下载缓存数据集,输出标准 JSON 报告。code/05_eval_deploy/eval.sh 的核心调用:

python -m lmms_eval \
  --model qwen2_5_vl \
  --model_args pretrained=./merged_dpo_model,dtype=bfloat16 \
  --tasks docvqa_val,chartqa_test,ocrbench,textvqa_val,infovqa_val,pope,mmbench_dev_en \
  --batch_size 1 \          # 高分图安全起见用 1
  --output_path ./eval_results \
  --log_samples

典型报告(建议同一 checkpoint 跑 3 次取 mean ± std):

Task Metric Value Std (3 runs)
docvqa_val anls 0.812 ±0.004
chartqa relaxed_acc 0.643 ±0.011
ocrbench score 547 ±3 (/1000,500 及格)
pope f1 0.871 ±0.006
pope accuracy 0.889 ±0.005

报告解读要点:DocVQA ANLS 0.81 约对应 EM ≈ 70%(粗略换算 ANLS×100−10 ≈ EM%);POPE F1 < accuracy 说明模型偏向答"否"(保守,常见于 DPO 后期),需回调 β。


四、部署:为何选 SGLang

选项 优点 缺点
transformers 简单稳定 慢,无 PagedAttention
vLLM 快、生态大 VLM 支持滞后
SGLang VLM 最先支持、RadixAttention 较新,文档少
TensorRT-LLM 最快 部署复杂,VLM 模型少

文档 VLM 推荐 SGLang:原生支持 Qwen2-VL / LLaVA-OneVision,对动态分辨率友好。两个杀手锏:

  1. RadixAttention(前缀复用):多轮对话中前面的"图 + prompt"KV cache 可复用。同一张图第二次提问(如先问"有什么文字"再问"总营收"),前缀已在 cache,吞吐提升 3–5×。对应参数 --enable-radix-cache
  2. 视觉 token 高效调度:把变长视觉 token 当"软"序列处理,不会因 AnyRes 多 tile 就 OOM,比 vLLM 在高分图上更稳定。

五、部署的五步生命周期

可上线的部署远不止 launch_server

1. 合并 LoRA
swift export --merge_lora

2. 起服务
sglang.launch_server

3. 冒烟测试
file:// 与 base64 两种路径

4. 压测
确定并发上限

5. 监控埋点
显存/QPS/TTFT/TPOT

步骤 1:合并 LoRA——推理不需要 adapter,必须先合并:

swift export --model_id_or_path Qwen/Qwen2.5-VL-7B-Instruct \
  --adapters ./output_sft/checkpoint-xxx --merge_lora true \
  --output_dir ./merged_model

步骤 2:起服务code/05_eval_deploy/sglang_serve.sh):

python -m sglang.launch_server \
  --model-path ./merged_model --port 30000 --host 0.0.0.0 \
  --dtype bfloat16 --mem-fraction-static 0.85 \
  --context-length 8192 --chat-template qwen2_5_vl \
  --enable-radix-cache

mem-fraction-static 0.85 留 15% 给 KV cache 增长与视觉 token buffer,调高易 OOM。

步骤 3:冒烟测试——file:// 本地路径与 base64 内嵌两种图像传法都要测,许多 bug 只在 base64 路径出现(如 MIME 推断错误)。

步骤 4:压测——VLM 压测不能只看 QPS,图像大小决定首 token 延迟。关键指标:TTFT(time to first token,1024×1024 图应 ≤ 1.5s)、TPOT(≤ 30ms)、显存峰值(跑满并发时 < 95% 上限)。A100 80GB 上 Qwen2.5-VL-7B 的可达成指标:

并发 TTFT P50 TPOT 显存
1 0.8s 18ms 28 GB
8 1.4s 25ms 52 GB
16 2.6s 40ms 71 GB
32 OOM 风险

步骤 5:监控埋点——显存利用率(OOM 预警)、QPS/TTFT/TPOT、生成长度分布(VLM 易"无限描述",设 max_tokens 截断)、图像尺寸分布(异常大图往往是上游 bug)。


六、量化决策与完成标准

A100 80GB 无需量化;其他卡按延迟要求决策:极致延迟选 TensorRT-LLM INT8,平衡选 AWQ INT4(最常用),易部署选 GPTQ INT4(精度略低)。

VLM 量化的特殊风险:视觉编码器对量化更敏感(SigLIP 量化后 zero-shot 掉 3–5%),常见做法是只量化 LLM、视觉编码器保 bf16(SGLang 的 --quantize llm_int8)。

文档 VLM 的完成标准

指标 及格线
DocVQA ANLS ≥ 0.80(约 EM ≥ 70%)
ChartQA relaxed-acc ≥ 60%
OCRBench ≥ 500
POPE F1 ≥ 85%
接口 TTFT P50 ≤ 2s(1024×1024 图)

达不到 → 回阶段 3 调数据,而非无脑训练。诊断顺序:

  1. ANLS 低 + OCRBench 低 → 分辨率不够,开 AnyRes / 升到 1024+;
  2. ANLS 低 + OCRBench 高 → 指令对齐不够,加 SFT 数据多样性;
  3. POPE F1 低 → 幻觉,进阶段 4 做 DPO;
  4. 部署后掉点 → 99% 是 chat template / 预处理不一致。

📎 本篇涉及代码

文件 说明
code/05_eval_deploy/eval_stability_demo.py 评测稳定性 / 评分规则对比(零依赖)
code/05_eval_deploy/eval.sh lmms-eval 多 benchmark 评测脚本
code/05_eval_deploy/sglang_serve.sh SGLang 部署脚本

小结

主题 要点
评测不稳定 三因:CUDA 非确定性、batch 漂移、评分规则脆弱(最可控)
评分规则 exact 脆弱,文档任务用 numeric match / ANLS
最小验证集 DocVQA + ChartQA + OCRBench + POPE
部署框架 SGLang(RadixAttention 前缀复用 + 视觉 token 调度)
部署 5 步 合并 LoRA → 起服务 → 冒烟 → 压测 → 监控
量化 仅量化 LLM,视觉编码器保 bf16

下一篇是专栏收尾的前沿方向:Chameleon / Emu3 / Llama 4 的 early fusion 路线——视觉也被离散化为 vocab、单模型单 loss,这是 VLM 的下一代范式。

专栏:《从 NLP 到 VLM:多模态大模型研发实战》
上一篇:⑦ 多模态 RL · DPO + GRPO | 本篇:⑧ 评测与部署 · lmms-eval + SGLang | 下一篇:⑨ 前沿方向 · Early Fusion

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐