news 2026/9/10 15:01:03

SGLang MMMU 基准评测指南:从 VLM 服务部署到结果解析与性能剖析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SGLang MMMU 基准评测指南:从 VLM 服务部署到结果解析与性能剖析

SGLang MMMU 基准评测指南:从 VLM 服务部署到结果解析与性能剖析

【免费下载链接】sglangSGLang is a high-performance serving framework for large language models and multimodal models.项目地址: https://gitcode.com/GitHub_Trending/sg/sglang

MMMU(Massive Multi-discipline Multimodal Understanding and Reasoning)是评测视觉语言模型(VLM)跨学科多模态理解与推理能力的权威基准,涵盖艺术、商业、科学、医学、人文社科与工程技术六大领域共 30 个学科。本文以 SGLang 仓库中的 benchmark/mmmu/README.md 为骨架,完整讲解如何基于 SGLang 服务框架托管 VLM 并在 MMMU validation 集上执行评测,同时结合仓库内 bench_sglang.py、eval_utils.py 等源码,深入解析评测流程、答案提取正则、LoRA 适配器、采样参数注入以及性能剖析等实战细节。读完本文,你将掌握一套可复现、可扩展、可深挖底层原理的 MMMU 评测方案。

一、评测脚本总览

benchmark/mmmu/目录下的文件构成了完整的评测工具链:

文件作用
bench_sglang.py通过 OpenAI 兼容 API 对 SGLang 托管的 VLM 发起评测请求
bench_hf.py基于 Hugging Face Transformers 直接离线评测同一数据集
data_utils.py数据集加载、学科分类映射、prompt 构建与结果保存
eval_utils.py评测参数定义、答案解析(选择题/开放题)与准确率统计
prompt_format.yamlMMMU 的默认 prompt 模板配置(任务指令、题型格式、温度)

其中data_utils.py定义了完整的学科体系:CAT_SHORT2LONG将 30 个学科缩写(如acccsmath)映射为全名,DOMAIN_CAT2SUB_CAT又将 30 个学科归并到 Art and Design、Business、Science、Health and Medicine、Humanities and Social Science、Tech and Engineering 六个领域。最终输出会按学科与领域分别统计准确率,形成类似官方报告的分层结果。

二、用 SGLang 托管 VLM:快速起步

2.1 启动推理服务

首先启动一个 SGLang VLM 服务端。以 Qwen2-VL-7B-Instruct 为例:

python -m sglang.launch_server --model-path Qwen/Qwen2-VL-7B-Instruct --port 30000

这里--model-path既可以是 Hugging Face 仓库 ID,也可以是本地权重目录;--port指定 OpenAI 兼容 API 的监听端口,bench_sglang.py会默认向http://127.0.0.1:{port}/v1发起chat.completions请求。

2.2 降低显存占用

MMMU 评测会逐张加载测试图片,输入长度较大,官方 README 明确建议追加--mem-fraction-static参数来控制静态显存占比:

python -m sglang.launch_server --model-path Qwen/Qwen2-VL-7B-Instruct --port 30000 --mem-fraction-static 0.6

该参数限制了 KV cache 等静态内存池可使用的显存比例,值越小越保守,适合与多模态模型或显存吃紧的场景配合使用,能有效避免服务启动阶段 OOM。bench_sglang.py会从数据集逐题并行准备图片并保存到~/.cache/mmmu/images/,图片解码也会占用显存,因此显存余量不足时务必调低该值。

2.3 启动评测

服务就绪后,在仓库根目录执行:

python benchmark/mmmu/bench_sglang.py --port 30000 --concurrency 16

--concurrency控制并发发送的 OpenAI 请求数。源码中通过asyncio.Semaphore(args.concurrency)限制同时 in-flight 的请求量,并发数越高吞吐越大,但需要服务端有足够max-running-requests与显存支撑。--model参数(默认"default")用于指定 API 请求体中的model字段,多模型部署在同一服务时可用它区分。

2.4 评测输出与结果文件

运行结束后脚本会打印Benchmark time,并写出两个 JSON 文件(默认写在当前工作目录):

  • ./answer_sglang.json:逐题记录pred_ans(解析后的预测答案)、original_response(模型原始回复)、ground_truth(标准答案)与question_type
  • ./val_sglang.json:按 30 个学科、6 大领域及 Overall 汇总的准确率与样本数。

这两个路径分别由脚本内的args.output_path = "./answer_sglang.json"eval_result(..., eval_output_path="./val_sglang.json")决定,也可通过--result-filename覆盖。

三、关键评测参数详解

--port--concurrency外,bench_sglang.py通过 eval_utils.py 中的EvalArgs暴露了一批高价值参数。下表汇总了默认值、含义与源码出处:

参数默认值说明
--seed1随机种子,用于可复现的数据处理与随机兜底选答案
--splitvalidation数据集划分,官方评测通常用 validation
--dataset-pathMMMU/MMMUHugging Face 数据集路径,可替换为本地镜像
--prompt-format-fileprompt_format.yaml自定义 prompt 模板 YAML 路径
--result-filename./val_sglang.json评测结果输出路径
--image-pixels-limit-1超过该像素数(宽×高)的图片直接跳过,-1 表示不限制
--max-new-tokensNone每个样本的最大生成长度,经max_completion_tokens传入请求体
--temperatureNone采样温度,仅在显式指定时覆盖默认值(YAML 中默认为 0)
--response-answer-regex(?s)(.*)从原始回复中提取答案的正则,捕获组即答案
--lora-pathNone评测时使用的 LoRA 适配器名称,随每个请求以lora_path字段发送
--reasoning-effortNone推理模型(如 GLM-4.5V)的推理强度,取值none/high
--extra-request-bodyNone以 JSON 字符串形式向每个请求体追加任意生成参数
--profileFalse是否开启服务端 profile(需配合start_profile/stop_profile接口)
--profile-number5profile 模式下只评测前 N 个样本

3.1 采样参数合并逻辑

get_sampling_params()展示了参数合并的优先级:先解析--extra-request-body中的 JSON 作为基底,再叠加--max-new-tokens(映射为max_completion_tokens)与--temperature。也就是说,--extra-request-body提供的是"额外生成参数"的通用注入通道,适合一次性传多个参数:

python3 bench_sglang.py --extra-request-body '{"max_new_tokens": 128, "temperature": 0.01}'

3.2 自定义答案提取正则

MMMU 许多题目要求模型输出形如Answer: A的结论。--response-answer-regex允许你用正则从模型原始输出中截取最终答案片段,捕获组group(1)会被strip()后送入解析器。官方示例针对 GLM-4.1V 的 box 格式:

python3 -m sglang.launch_server --model-path zai-org/GLM-4.1V-9B-Thinking --reasoning-parser glm45 python3 bench_sglang.py --response-answer-regex "<\|begin_of_box\|>(.*)<\|end_of_box\|>" --concurrency 64

注意:--response-answer-regex只决定"提取哪一段作为模型答案",后续选择题解析(parse_multi_choice_response)仍会从该片段中进一步寻找A/B/C/D字母。

四、LoRA 适配器评测

当需要验证 LoRA 微调后的视觉模型效果时,分两步走。

第一步:服务端加载 LoRA。使用--lora-paths名称=路径的键值对形式注册适配器(多个适配器用逗号分隔),同时按需追加--disable-radix-cache避免前缀缓存干扰:

# Launch server with LoRA enabled python -m sglang.launch_server --model-path microsoft/Phi-4-multimodal-instruct --port 30000 --trust-remote-code --disable-radix-cache --lora-paths vision=<LoRA path>

第二步:评测时指定适配器。--lora-path vision传入的是注册名而非磁盘路径:

# Apply LoRA adapter during inferencing python -m benchmark/mmmu/bench_sglang.py --concurrency 8 --lora-path vision

从源码看,process_sample()会把{"lora_path": lora_path}放入extra_body,随每个 OpenAI 请求发送,从而实现"同一服务、动态切换适配器"的批量评测。

五、评测流程的源码级拆解

5.1 样本准备阶段

prepare_samples()的工作分四步:加载prompt_format.yaml并展开列表项 → 用ThreadPoolExecutor并行从MMMU/MMMU加载 30 个学科子集并concatenate_datasets合并 → 并行处理每个样本(process_single_sample抽取题目/选项/答案/图片,construct_prompt按题型套用模板)→ 按final_input_prompt排序保证顺序稳定。

construct_prompt()展示了两种题型模板的实际拼装:

  • 选择题使用multi_choice_example_format,将选项格式化为(A) ...(B) ...并在末尾追加指令Answer with the option's letter from the given choices directly.
  • 开放题使用short_ans_example_format,指令为Answer the question using a single word or phrase.

这些模板定义在 prompt_format.yaml 中,task_instructions默认为空字符串,temperature默认为 0。

5.2 请求构造与并发控制

process_sample()将 prompt 按<>拆成 prefix 与 suffix,图片则按 MIME 类型转成data:image/png;base64,...内联到image_url,最终拼成 OpenAI 多模态消息格式:

messages: [ {role: "user", content: [ {type: "text", text: prefix}, {type: "image_url", image_url: {url: image_url}}, {type: "text", text: suffix}, ]} ]

并发大于 1 时,脚本用asyncio.Semaphore包裹每个样本的请求任务并通过asyncio.as_completed驱动;并发等于 1 时则退化为顺序执行,保证请求顺序与样本顺序一致——这正是 profile 场景下官方推荐--concurrency 1的原因(见下文 profiling 一节)。

5.3 答案解析与打分

process_result()按题型分流:选择题调用parse_multi_choice_response(),开放题则直接以原始回复作为pred_ans(真正的开放题归一化发生在最终打分阶段)。

选择题解析器parse_multi_choice_response()的判定优先级从源码可以清晰看出:

  1. 优先匹配显式结论模式(_EXPLICIT_ANSWER_PATTERNS):如answer: XFinal answer: X、独立成行的(X)、LaTeX 的\boxed{X}the answer is X,取所有匹配中位置最靠后的一个;
  2. 依次在回复中寻找(A)/(B)括号形式、A空格形式;
  3. 长度超过 5 个词时尝试匹配选项内容文本;
  4. 全部失败则随机选一个字母兜底。

最终打分eval_result()会按 30 个学科分别调用evaluate(),再用calculate_ins_level_acc()按样本数加权汇总出六个领域的 Overall 与全局 Overall 准确率,结果通过pprint打印并写入val_sglang.json

六、用 Hugging Face 基线对比

为了与 HF Transformers 参考实现做公平对比(例如验证 SGLang 服务化推理与原生 PyTorch 的精度一致性),仓库提供了离线评测脚本:

python benchmark/mmmu/bench_hf.py --model-path Qwen/Qwen2-VL-7B-Instruct

bench_hf.py的关键行为:

  • 优先尝试AutoModelForImageTextToText加载;失败则回退到AutoModel.from_pretrained,其中 InternVL 系列走sglang.srt.multimodal.internvl_utils.image_to_pixel_values做 448×448 分块与缩略图预处理;
  • 支持--limit N只评测前 N 个样本,便于快速冒烟验证;
  • 使用GenerationConfig(max_new_tokens=..., do_sample=False)贪心解码,温度固定为 0;
  • 结果输出为{model_path}_answer_hf.json{model_path}_val_hf.json,格式与 SGLang 版本一致,可直接对比。

需要说明的是:HF 脚本与 SGLang 脚本共用同一套EvalArgs与样本准备逻辑,因此两者的差异仅来自推理后端本身,对比结果具有较强说服力。

七、MMMU 评测下的性能剖析(Profiling)

当需要定位 SGLang 服务在 MMMU 负载下的性能瓶颈(如多模态编码器耗时、prefill 阶段 kernel 开销)时,可以使用--profile模式:

python3 bench_sglang.py --profile --profile-number 5 --concurrency 1

官方 README 明确建议:若开启 profile 选项,请遵循 docs/docs/developer_guide/benchmark_and_profiling.mdx 中的标准剖析说明,并推荐使用--concurrency 1以保证一致性,让剖析与调试更简单。

其原理在源码中清晰可见:--profile开启后,脚本会先调用服务端的/start_profile接口启动 SGLang 内置剖析器,随后只评测前--profile-number(默认 5)个样本,最后调用/stop_profile结束采样。剖析期间使用串行模式(--concurrency 1)可以避免并发请求互相抢占 GPU 导致的时间线互相污染,从而得到干净、可归因的 kernel 耗时数据。剖析产出的 trace 可配合 PyTorch Profiler、Nsight Systems 等工具进一步分析,详见仓库中的官方 profiling 文档。

八、完整实战流程总结

一个端到端的 MMMU 评测流程可以归纳为四步:

  1. 准备数据:脚本会自动从 Hugging Face 加载MMMU/MMMU的 validation 划分,并把处理后的图片缓存到~/.cache/mmmu/images/(首次运行需要下载,耗时较长;可通过--dataset-path指向已镜像的数据集加速);
  2. 启动服务python -m sglang.launch_server --model-path <VLM> --port 30000,显存紧张时追加--mem-fraction-static 0.6,需要 LoRA 时追加--lora-paths <name>=<path>
  3. 执行评测python benchmark/mmmu/bench_sglang.py --port 30000 --concurrency <N>,按需叠加--response-answer-regex--extra-request-body--lora-path等参数;
  4. 阅读结果:查看控制台打印的分层准确率,以及./answer_sglang.json(逐题明细)与./val_sglang.json(汇总统计)两个文件;需要对照基线时运行bench_hf.py生成 HF 版结果。

如果还需要复现官方论文式的严谨结论,建议固定--seed保证数据顺序与随机兜底行为可复现,并保持 SGLang 服务端与评测脚本版本一致后再横向对比不同模型的 MMMU 分数。

【免费下载链接】sglangSGLang is a high-performance serving framework for large language models and multimodal models.项目地址: https://gitcode.com/GitHub_Trending/sg/sglang

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 15:00:22

50KW储能逆变器设计:工商业应用的核心挑战与解决方案

1. 项目概述&#xff1a;50KW储能逆变器变流器的核心价值储能逆变器作为新能源系统的"心脏"&#xff0c;其设计质量直接决定了整个储能系统的效率和可靠性。50KW这个功率段在工商业储能应用中尤为常见——它既能够满足中型商业体&#xff08;如商场、写字楼&#xff…

作者头像 李华
网站建设 2026/9/10 14:52:35

Wand-Enhancer 完整教程:本地构建补丁器,解锁 WeMod 专业版

Wand-Enhancer 完整教程&#xff1a;本地构建补丁器&#xff0c;解锁 WeMod 专业版 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer 你正在为 WeMod…

作者头像 李华
网站建设 2026/9/10 14:52:31

Gradio 自定义进度条实战:gr.Progress 与 tqdm 全攻略

Gradio 自定义进度条实战&#xff1a;gr.Progress 与 tqdm 全攻略 【免费下载链接】gradio Build and share delightful machine learning apps, all in Python. &#x1f31f; Star to support our work! 项目地址: https://gitcode.com/GitHub_Trending/gr/gradio 本指…

作者头像 李华
网站建设 2026/9/10 14:50:56

楼宇微网虚拟储能系统优化与PSO算法实现

1. 项目概述&#xff1a;楼宇微网与虚拟储能系统的融合优化在能源管理领域&#xff0c;楼宇微网作为分布式能源系统的重要载体&#xff0c;正面临如何高效整合需求侧资源的挑战。传统物理储能设备存在投资成本高、占地面积大等痛点&#xff0c;而虚拟储能系统&#xff08;Virtu…

作者头像 李华
网站建设 2026/9/10 14:50:51

商超蔬菜价格弹性与补货策略:Python数据清洗到报童模型实战

简介&#xff1a;针对某商超蔬菜价格与补货策略的建模分析压缩包&#xff0c;适合数学建模参赛者、数据分析师及商超运营人员&#xff0c;可用于赛题复现、业务复盘或教学参考。资源围绕数据采集清洗、时间序列预测、回归定价、库存优化等展开&#xff0c;内含源码、数据集、可…

作者头像 李华