多模态模型评测实战:MMBench与OpenCompass从原理到落地
发布时间:2026/9/16 3:38:38 作者:尧图编辑部 阅读量:1,286

多模态模型这两年可以说是遍地开花从开源社区的Qwen-VL、InternVL到各家闭源的GPT-4V、Claude代码能力、推理能力一个比一个能打。但真到了要落地选型的时候问题就来了排行榜上那些分数到底靠不靠谱同一个模型A榜单说第一B榜单说垫底论文里晒的指标和自己在业务数据上跑出来的效果经常是两回事。这种时候一个设计合理、维度清晰、能复现的评测基准就非常重要了。今天想聊的MMBench就是OpenCompass体系里专门针对多模态模型设计的一套评测基准也是我实际用下来觉得最顺手、最能说明问题的一套工具。这篇文章主要面向三类人一是准备在论文里放评测结果的同学二是想从一堆开源多模态模型里挑一个来用的工程师三是自己微调了模型、想验证一下效果到底有没有提升的研究者。我会把MMBench到底考什么、怎么在OpenCompass里跑通、结果怎么看、以及自己接模型时容易踩的坑一次讲清楚。1. MMBench在考什么从总分好看到能力画像清晰1.1 为什么需要一套独立的多模态评测基准先说说背景。多模态模型和纯文本模型有个本质区别输入不仅有文字还有图像模型需要先看懂图再结合文字指令给出答案。这就意味着评测一个多模态模型光看它文本能力有多强是不够的还得看它的视觉感知、视觉推理、跨模态对齐能力。很多早期的评测基准其实是直接把纯文本benchmark套过来在问题里加一张图就完事了维度很粗糙模型瞎猜也能拿不错的分数。MMBench的思路不太一样。它的全称是A Comprehensive Multi-modal Benchmark主打的就是细粒度能力拆解。它不是给你一个笼统的正确率而是把视觉理解拆成二十个左右的能力维度比如OCR识别、属性推理、空间位置推理、图表理解、动作识别、常识推理等等每个维度单独出题、单独计分。跑完一轮评测你拿到的不是这个模型准确率82%而是一张能力雷达图OCR很强空间推理一般动作理解偏弱。这种颗粒度对于模型选型和迭代方向判断价值比总分高得多。1.2 选择题为主的设计逻辑与防偏置技巧MMBench的大部分题目是四选一或多选的选择题少数是判断题和填空题。为什么用选择题因为自动评测需要稳定、可比的打分标准。生成式答案要拿去和参考答案做匹配这对模型的输出格式要求太高稍有不一致就误判选择题则天然适合程序判分模型只需要输出字母选项就行。但选择题有个隐患模型可能瞎猜。四个选项蒙也有25%的正确率。为了压低随机猜测的影响MMBench的题目并不是简单地把正确答案放在固定位置而是会做选项打乱和干扰项设计。我在跑评测的时候还注意到一个细节same/different这类对比题和顺序推理题命题上会刻意让模型必须真正理解图像内容才能做对光靠语言先验和上下文套路是答不出来的。这也是为什么MMBench的分数比很多看图说话型基准更有区分度。1.3 DEV测试集与TEST测试集本地调试和官方验证怎么分工用过OpenCompass的朋友应该见过MMBench_DEV和MMBench_TEST这两类数据集名。DEV是开发集题目数量少主要用于本地快速验证代码有没有跑通、模型有没有加载成功、prompt格式对不对。TEST才是正式测试集题目多、覆盖全但不会直接公开标准答案需要把模型输出提交到官方服务器或者用官方脚本判分。这里有个常见的认知误区DEV集的分数不能当作最终成绩写进论文它只能用来做开发阶段的冒烟测试和调参。真正的结论一定要基于TEST集的结果。版本方面目前主流的是MMBench_V1.0和更新版本的MMBench_2024系列。我在后面的章节里给出的命令默认基于OpenCompass 0.7.x以上版本和2024版数据集。如果你还在用旧版本建议尽快升一下因为旧版数据集在题目清洗和标注质量上确实有些小问题。2. 在OpenCompass里跑通MMBench完整实操流程2.1 环境准备和最容易漏掉的依赖OpenCompass的安装其实不算复杂官方推荐用conda建独立环境conda create -n opencompass python3.10 -y conda activate opencompass pip install -U opencompass但这里有个坑如果你要评测的是HuggingFace上的开源模型OpenCompass需要依赖推理后端来做模型加载和生成。默认用的是lmdeploy或vllm这两者安装的时候有很多系统级依赖比如CUDA Toolkit版本需要和你的显卡驱动匹配。我建议先安装PyTorch再装lmdeploy最后装opencompass这个顺序踩坑最少pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 pip install lmdeploy pip install opencompass装完以后可以跑一下自检命令确认各个模块都正常python -m opencompass.cli.main --help如果工具版本冲突常见于mmcv、mmdet这类视觉库之间的依赖打架。我的建议是别用最新的就用官方requirements.txt里锁定的版本省心很多。2.2 内置的MMBench数据集和模型配置说明OpenCompass的一个设计亮点是模型配置和数据集配置分离。你要做的只有两件事写一个模型文件告诉它我要测哪些模型写一个数据集参数告诉它用哪个基准跑。MMBench在OpenCompass里内置的数据集名是MMBench_DEV_EN英文开发集MMBench_DEV_CN中文开发集MMBench_TEST_EN英文测试集MMBench_TEST_CN中文测试集MMBench_2024_DEV_EN、MMBench_2024_TEST_EN等更新的版本实际跑评测时你不需要自己写数据加载代码直接用字符串指定就行。模型端则支持两类方式一类是直接在HuggingFace上跑transformers加载适合快速验证另一类是走lmdeploy/vllm等推理后端适合追求吞吐和批量评测。我自己一般先用transformers方式跑通小样本再用lmdeploy跑全量TEST集两个后端的结果一致性在OpenCompass里处理得还算不错。2.3 跑通一个最小可复现的评测命令假设我想评测HuggingFace上的Qwen/Qwen2.5-VL-7B-Instruct模型在英文开发集上做验证命令长这样python run.py \ --models hf_llava_qwen2 \ # 这只是示意实际有对应的配置名 --datasets MMBench_DEV_EN \ --debug不过说实话直接用run.py加内置配置名的方式对自定义模型并不友好因为内置配置里的模型路径基本都是预设好的。更通用的做法是写一个Python配置文件然后传给OpenCompass执行。我先给一个最小可跑的示例。在configs/models/下新建my_mllm.pyfrom opencompass.models import HuggingFacewithChatTemplate from opencompass.utils.text_postprocessors import first_capital_postprocess models [ dict( typeHuggingFacewithChatTemplate, abbrqwen2.5-vl-7b-instruct, pathQwen/Qwen2.5-VL-7B-Instruct, max_out_len512, batch_size4, model_kwargsdict(device_mapauto, trust_remote_codeTrue), run_cfgdict(num_gpus1), ) ]在configs/datasets/下指定数据集from opencompass.configs.datasets.mmbench.mmbench_2024_gen import mmbench_2024_datasets datasets mmbench_2024_datasets然后执行python run.py --config configs/eval_my_mllm.py跑完以后OpenCompass的outputs/目录会生成时间戳文件夹里面包含模型的推理结果jsonl、评测打分结果json和一份summary汇总文件。这些都是可直接查的。2.4 评测结果都输出到了哪里很多新手跑完run.py之后一脸懵结果呢其实OpenCompass的输出目录结构是**outputs/{任务时间戳}/{模型名}/{数据集名}/**时间戳文件夹下会有完整的运行日志。最核心的文件是.jsonl格式的推理结果每条记录都带着输入图片路径、原文问题、模型预测输出、参考答案results/下的打分json按数据集、按科目类别列出准确率和样本数summary/下的汇总表多个模型横向对比时看这个最方便我的习惯是跑完先看jsonl文件抽查几十条模型预测和参考答案。这一步能在几分钟内发现很多分数解释不了的问题比如模型可能输出了正确答案但格式是中文括号、多打了空格导致判分失败。光看总分很容易被误导。3. 从分数看到的东西MMBench指标解读与对比技巧3.1 整体准确率 vs 细分维度准确率MMBench评测结果里除了一个整体accuracy之外还会按能力维度输出细分准确率。以2024版为例常见的细分维度包括字符识别、物体属性、空间关系、计数、图表理解、常识推理、情感理解等。看分数时我的建议是先看整体准确率判断模型在这套基准上大概处于什么水平和公开SOTA差距有多大再看细分维度找出模型的短板。比如一个OCR能力很强的模型字符识别分数可能接近90%但空间关系只有50%多这就说明它在定位和相对位置理解上还需要提升对比两个模型时不要只比总分。模型A总分略高于模型B但模型B在中文科目和图表理解上大幅领先那在具体场景里模型B可能反而是更好的选择。我举一个实际对比的例子数值仅供示意模型整体准确率字符识别空间关系图表理解中文题目模型A82.3%91.5%68.2%76.4%79.8%模型B80.7%85.2%74.6%83.1%86.3%如果只看总分模型A赢了但从我的使用场景看模型B的图表理解更稳中文指令兼容性更好总分低的2个百分点完全可以用prompt优化或微调补回来。这就是细粒度评测的价值。3.2 几个判断分数可信度的信号评测过程中我发现有些分数偏低不是模型能力问题而是评测链路出问题了。总结几个高频信号所有题目都输出同一个选项这种情况多半是模型的chat template和MMBench的prompt模板不匹配模型根本没理解指令一直在重复系统提示词或第一个选项。检查模型配置里的HuggingFacewithChatTemplate应用是否正确。分数接近随机水平选择题25%左右要么模型本身真的没视觉能力要么图像没有正确传进去。视觉模型输入需要走特殊的message格式如果直接按纯文本格式拼图部分模型会直接忽略图片。中文题目分数异常低但英文正常可能是中文分词或指令模板里用了英文的标点符号导致模型对中文指令理解偏弱。这个时候可以先检查prompt里的中文标点是否有问题。3.3 对比实验时必须要对齐的条件做模型横向对比时最忌讳的是各跑各的、参数不统一。我给自己定了几条强制对齐规则max_out_len一致输出长度限制影响模型回答完整度。一个限制128另一个限制1024分数几乎没有可比性。batch_size保持一致虽然理论上batch大小不影响单条样本结果但在lmdeploy等推理后端下batch变化可能影响beam search的行为导致细微差异。少样本示例数量一致MMBench默认是zero-shot评测但有些模型在OpenCompass配置里会带上few-shot的示例。对比前一定要确认所有模型都处于同样的few-shot设置否则就是拿榜单分数和自家分数硬比没有意义。运行环境可复现设置固定随机种子RANDOM_SEED虽然模型推理本身是确定性的但数据加载顺序、打乱逻辑会影响最后的汇总结果。4. 微调/部署自己的多模态模型这样把它接进评测4.1 为什么默认配置不够用OpenCompass内置的模型配置都是针对公开模型写的路径直接指向HuggingFace上的官方权重。如果你自己微调过一个模型或者把模型量化了、换了基础底座就需要自定义模型配置。这一节我会讲两种主流方式一种是直接写HuggingFace加载配置另一种是走推理后端的方式。4.2 用HuggingFace加载配置接入评测最简单的方式是写一个Python配置让OpenCompass用transformers的AutoModelForVision2Seq方式加载模型from opencompass.models import HuggingFacewithChatTemplate models [ dict( typeHuggingFacewithChatTemplate, abbrmy-finetuned-vlm, path/path/to/your/model, # 本地路径或HuggingFace模型ID max_out_len1024, batch_size1, model_kwargsdict( device_mapauto, torch_dtypebfloat16, ), run_cfgdict(num_gpus1, gpu_ids[0]), ) ]这里最关键的参数是typeHuggingFacewithChatTemplate。它会按照模型自身的chat template自动包装对话格式不用你手动拼prompt。对于多模态模型OpenCompass会把图像嵌入成特殊的message格式传进去避免图片没真正输入的尴尬。4.3 unsloth加速加载与评测的实践思路如果你的模型是用unsloth微调的或者你想用unsloth的低显存加载特性来降低评测门槛也有办法。unsloth的FastLanguageModel.from_pretrained在底层是兼容HuggingFace权重格式的所以微调出的模型可以直接当成普通模型路径传给OpenCompass不冲突。我在本地评测一台24GB显存的卡上跑7B级别的多模态模型时就先用unsloth把模型转换成4bit加载再接入OpenCompass跑MMBench_DEV。过程和直接加载原模型完全一样占用的显存从接近20GB降到了10GB左右。不过要提醒一下4bit量化会略微损失精度分数可能比bf16加载低1到3个百分点所以正式出论文结果时建议用bf16或fp16跑一遍确认。如果你只是想先快速看看unsloth模型在MMBench上的表现可以在自己的脚本里这样加载模型和处理器from unsloth import FastLanguageModel from transformers import AutoProcessor model, tokenizer FastLanguageModel.from_pretrained( model_nameyour-finetuned-model, max_seq_length4096, load_in_4bitTrue, ) processor AutoProcessor.from_pretrained(your-finetuned-model) # 然后可以自己写一个循环读MMBench的jsonl # 按OpenCompass的格式逐条构造对话最后算accuracy这样绕过了OpenCompass的调度但可以快速验证模型有没有基本的多模态能力适合在正式接入OpenCompass之前做冒烟测试。注意实际评测时还是要以OpenCompass的结果为准因为prompt模板和判分逻辑都经过严格校准。4.4 接入API模型的配置思路如果你要评测的是API模型比如GPT-4V或ClaudeOpenCompass也提供了对应的API模型类型例如GPT4V、QwenVLAPI等。配置方式类似from opencompass.models import GPT4V models [ dict( typeGPT4V, abbrgpt-4v, keyYOUR_API_KEY, max_out_len1024, run_cfgdict(num_gpus0), ) ]跑API模型的好处是本地不需要任何GPU资源但要注意API限流。MMBench测试集题目多一次性全跑可能会触发限流报错建议在配置里降低batch_size或增加任务重试次数。我这个月跑API模型时就被限流过两次所以现在都会在run_cfg里加retry3。5. 实操中我踩过的坑与避坑经验5.1 视觉模型显存占用比想象中高MMBench的题目是图加文的组合输入视觉编码器、连接层和语言模型三块都要驻留显存。我第一次用batch_size8跑一个13B模型直接OOM。后来把batch_size降到2再配合device_mapauto才稳定跑完。经验是7B模型的batch_size建议不超过413B模型的batch_size建议1到2。多卡的话可以在run_cfg里指定num_gpus2OpenCompass会自动做张量并行。5.2 chat template不一致导致莫名其妙低分这是最坑的一次排错经历。我用一个刚微调完的模型跑MMBench分数低得离谱30%不到。排查链路是这样的先看OpenCompass的推理结果文件发现模型输出的是正常的英文句子不是字母选项。再仔细看模型的输出里经常出现Explanation: ...这类推理过程把答案埋在一大段文字里。判分逻辑是提取首字母或查找选项字母结果自然找不到。根因是我的微调数据里包含大量先推理后作答的思维链样本模型学会了长篇输出而MMBench指令只要求在末尾输出选项字母。解决方案有两种一是在prompt里追加一句Answer with the option letter only.二是在配置里设置postprocessor例如用OpenCompass内置的first_capital_postprocess函数提取输出文本中第一个大写字母作为答案。from opencompass.utils.text_postprocessors import first_capital_postprocess dict( typeHuggingFacewithChatTemplate, ... postprocessorfirst_capital_postprocess, )这个坑说明一个很重要的问题评测分数低先别急着否定模型先看原始输出格式是否满足判分要求。5.3 DEV和TEST选错的教训有一次跑通了DEV集结果很理想我顺手把评测脚本里的数据集名从MMBench_DEV_EN直接改成MMBench_TEST_EN心里想着无非是题目多一点、跑久一点。结果跑了两个多小时看到输出文件里有些图片是损坏的、有些选项没对齐最后那一轮数据几乎报废。后来问了社区才知道TEST集有些样本的图片存储在第三方图床网络环境不稳会加载失败。现在的做法是跑TEST集之前先检查图片是否全部成功下载如果失败用OpenCompass提供的下载脚本把图片预取到本地缓存。网络条件稳定的环境下TEST集的题目质量明显高于DEV集但前提是数据完整加载。5.4 随机性和复现评测结果波动多少算正常有人问我同一个模型跑两次MMBench分数差1.5个百分点正常吗正常。原因有几个少样本评测时会随机采样示例不同次运行示例不同结果自然有波动多模态模型的图像处理器可能引入微小的预处理随机性批量推理时推理后端的beam search和采样参数在不同显存布局下也会有细微差异。为了尽量复现我在每次跑之前固定几个东西固定seed在OpenCompass里可以通过环境变量或配置文件设置固定推理后端的采样参数temperature0do_sampleFalse用贪心解码固定数据集加载时的shuffle种子但即便如此不同机器不同版本下1到2个百分点的波动依然存在。所以我的习惯是重要榜单结果要跑三次取均值。这虽然费点时间但可信度完全不一样。特别是要向外部报告数字的时候单次分数很容易被质疑。5.5 中文评测集和英文评测集要分开看MMBench有英文和中文两个版本道理上中文版只是把题干和选项翻译成中文但实测下来很多模型的英文分数和中文分数能差到15个百分点以上。原因主要有两点一是模型的中文指令跟随能力本身有差异二是中文题目涉及的古诗词、俗语、成语等文化常识对很多主要在英文语料上训练的模型来说难度更大。所以如果你的业务场景是中文一定要单独跑MMBench_DEV_CN和MMBench_TEST_CN不能直接用英文TEST集分数代表一切。我自己在项目里就是中英文分开记录的选型的时候也看具体业务语言分布来决定权重。单纯追求英文榜单第一对国内业务落地帮助其实有限。我在实际使用OpenCompass和MMBench的过程中最大的感受是它把原来看一眼模型输出凭感觉说好坏的评测过程变成了一套可有迹可循、可分维度拆解的量化体系。跑一次不容易但跑完拿到的信息密度比单纯刷榜单高太多了。最后再分享一个小技巧如果你要在论文里报告MMBench分数官方实际上是要求使用OpenCompass指定版本来跑的论文里也建议注明MMBench (OpenCompass version)因为不同工具链、不同prompt模板下同一模型的分数可能差好几个点。提交结果之前多核对一眼自己的版本号和配置能省掉很多审稿人追问的麻烦。