
如果你最近用多模态大模型读过论文里的图表大概率遇到过类似场面模型能准确说出“这是一张柱状图横轴是年份纵轴是销量”可一旦你追问“2019 年到 2020 年的增长幅度是多少”它要么算错数值要么忽略单位要么直接一本正经地给出一个完全对不上的结论。这个现象不是个别模型的抽风而是当前多模态模型评测体系的一个系统性盲区。过去两年大家习惯了用图文匹配、视觉问答、常识问答来衡量多模态模型但“看得到图”和“看得懂图”之间隔着一条巨大的鸿沟。尤其是科学图表它把坐标轴、刻度、标签、符号、注解、趋势、数据点压缩在一张静态图里模型需要完成的不是“描述”而是“在图上做推理”。这就是 Diagram-MMU 这类科学图表多模态评测基准出现的背景。本文想围绕 Diagram-MMU 说清楚三件事科学图表评测到底在考什么它和通用多模态评测有什么本质区别以及当你想把这类基准用到自己的模型评测流程里时怎么设计数据、写脚本、做结果归一化。先给一个判断Diagram-MMU 这类基准不是简单增加了一个排行榜它代表的是多模态评测从“感知层”下沉到“推理层”。如果你正在做多模态模型选型、RAG 场景中的图表问答、或者教育类 AI 产品这篇文章值得读完。1. 为什么通用多模态 Benchmark 不够用过去流行的多模态评测基准绝大多数把“理解”定义成这样一个任务给一张图让模型从几个候选答案里选出正确的一项或者生成一句自然语言描述。这种设计对自然图像、日常物体、常见场景是有效的因为模型不需要做严格推理靠视觉特征和先验知识就能答对。但科学图表完全不同。一张气象图里的等温线一张生物论文里的系统发育树一张物理试卷里的电路图它们的信息密度极高而且几乎所有关键信息都藏在符号关系里而不是像素语义里。坐标轴的刻度间距、横纵轴的单位、图例的对应关系、数据点的趋势走向这些要素单独看都不难组合在一起就构成了“视觉语言”和“领域知识”的双重门槛。通用基准失效的根本原因是它们测不出模型在图表上的两类短板第一符号解读能力。模型需要知道“kPa”是压强单位“μM”是浓度单位“log scale”表示对数坐标。一个在自然图像上表现很好的模型遇到这些科学符号时可能完全失去判断力。第二多步推理能力。回答“哪一年的增长率最高”模型至少要做三步定位数据列、做数值比较或计算、结合时间轴判断。通用 VQA 基准里的问题通常一步到位推理链很短根本暴露不了这种缺陷。所以问题不是模型“不够聪明”而是评测任务本身没有把科学图表推理拆出足够细的层级。Diagram-MMU 这类基准的价值正在于把这个场景单独拎出来专门设计任务和评估方式。2. 什么是 Diagram-MMU定位与核心设计意图从项目名称看Diagram-MMU 是一个面向科学图表的多模态评测基准全称可以理解为 Diagram Massive Multimodal Understanding延续了 MMU 这类大规模多模态理解评测的命名习惯。和 CMMMU、MathVista 等基准不同Diagram-MMU 把注意力集中在“科学图表”这个垂直领域。这里说的科学图表不是指一张普通的柱状图折线图而是覆盖科学研究、工程实践、教育教学里真正会出现的图表类型包括但不限于实验数据图柱状图、折线图、散点图、箱线图、误差棒图科学示意图电路图、流程图、系统架构图、化学分子结构图统计图形直方图、饼图、面积图、热力图、雷达图领域图表地质剖面图、天气图、生物进化树、解剖图关键不在于图表类型多而在于它们承载的任务维度多。同一张图表可以出描述题、计算题、关系判断题、原因分析题难度梯度完全不一样。Diagram-MMU 这类基准通常会围绕这些维度构造问题推动模型从“认出图表”走向“使用图表”。从设计意图来看它可以整理成三个层面第一层是感知识别。模型能否正确指出图表的类型、坐标轴标签、图例内容、数据点的大致分布。这一层考的是 OCR 和图结构理解。第二层是数值提取与计算。模型能否从刻度中读出具体数值能否根据柱高、折线位置估算数据点能否完成单位换算和基本运算。第三层是推理与判断。模型能否基于图表趋势做出结论能否比较不同序列的差异能否回答“如果某个变量变化结果会怎样”这类条件推理题。这三层是有依赖关系的。感知不清后面的计算和推理都会出错。这也是评测科学图表比评测自然图像更复杂的原因——一个错误可能发生在任意一层排查起来需要层层分解。3. 科学图表理解到底难在哪里很多开发者在第一次评测多模态模型时容易低估科学图表的难度觉得“图都摆在那里了怎么可能读不准”。实际跑一遍就发现模型犯的错误往往非常低级且稳定。这里梳理五个最典型的难点。第一坐标轴与刻度读取。模型需要理解坐标轴刻度的间隔是否相等、是否从非零值开始、是否是对数坐标。对数坐标是最常见的陷阱很多模型会把纵轴上的“10、100、1000”当作线性等差导致趋势判断完全错误。第二科学符号与单位识别。化学式里的下标、数学公式里的希腊字母、物理单位的大小写比如 m米和 M摩尔浓度这些细节对模型是极大的考验。OCR 可能识别出了符号但模型未必理解符号对应的科学含义。第三空间布局关系。系统发育树的分支先后代表物种亲缘关系电路图中的节点连接代表电流路径地质剖面图的层位顺序代表时间演化。图表里的“位置关系”往往是核心语义而现有模型的空间推理能力普遍不足。第四数据点定位与数值估算。柱状图的柱高、折线图的点、散点图的位置模型需要从像素位置反推数值。遇到坐标轴刻度不是整数或者图表被压缩过的情况误差会迅速放大。第五跨模态融合。科学图表往往混合了图形、文字、数字、公式、颜色标识。模型需要把所有这些信息统一到一个推理框架里。比如图例里用蓝色表示实验组红色表示对照组模型必须先在视觉上完成颜色对应再到文字上理解组别含义最后在数据上做比较。这些难点决定了一个单纯提升 OCR 能力的方案解决不了 Diagram-MMU 里的大部分问题。它需要模型在视觉编码、符号理解、数值推理三个层面同时做强。4. Diagram-MMU 的评测维度拆解从评测方法论的角度这类科学图表基准通常会从以下几个维度定义题目和评分方式。4.1 图表类型覆盖评测集要回答的第一个问题是模型见过多少种图表如果只有柱状图和折线图评测结果只能说明模型会看图不能说明模型懂科学图表。覆盖面越广评测越能反映真实应用但数据构造难度也越高。4.2 问题类型分层这是 Diagram-MMU 这类基准最值得学习的地方。它不会只出“图中哪个年份销量最高”这种单步问题而是会构造分层难度Level 1直接描述。图表类型、坐标轴标签、图例项。Level 2信息定位。找到某个特定数据点、读出某个序列的值。Level 3数值运算。计算差值、增长率、比例、均值。Level 4关系推理。比较趋势、判断相关性、归纳结论。层次化设计的好处是模型评测完以后你可以直接看到它在哪个层级开始失分。如果模型前面两层正确率高、后面两层骤降说明问题出在推理能力而不是视觉感知。4.3 答案类型与评估方式科学图表评测的答案类型比通用问答更复杂至少包括单选和多选。适合感知类问题评估简单。开放式数值。需要模型计算并输出数值评估时要做容差处理。约束文本。模型需要输出包含特定关键信息的短句比如“实验组的平均响应时间显著低于对照组”。单位相关答案。模型必须输出带正确单位的数值。答案类型直接决定了评估脚本的复杂度。单选可以用准确率一键计算而开放数值和单位相关答案需要仔细设计归一化逻辑否则会出现“答案对了但被判错”和“答案错了但被放过”两种误导性结果。4.4 抗干扰与鲁棒性好的基准还会考察模型对图表变体、噪声、风格变化的鲁棒性。比如同一组数据用不同配色或不同图表样式呈现模型是否还能得到一致结论。这个维度在真实工程中很重要因为产品里的图表往往不是标准论文格式。5. Diagram-MMU 与其他多模态评测基准的对比为了理解 Diagram-MMU 的定位可以把它和几类常见评测基准做对比。评测基准类型主要考察点常见任务形式典型局限Diagram-MMU 的差异化定位通用图文匹配图像语义理解图文检索、Caption不深入图表细节聚焦科学图表通用视觉问答图像内容问答单选、开放问答问题一步到位缺乏多层推理分层设计推理链条更长数学多模态评测数学题求解解题、公式推理图表只是题目配图不是核心图表本身就是推理对象文档理解评测版面、OCR、表格信息抽取、阅读理解通常忽略图形数据关系强调图形、符号、数值融合Diagram-MMU科学图表完整理解感知、计算、推理多类型——面向科学图表分层全流程评测从这张对比表可以看出一条主线之前的评测更像在考“模型能不能从图里找到信息”而 Diagram-MMU 这类基准在考“模型能不能用图里的信息完成专业判断”。前者是检索和描述后者是推理和应用。6. 把 Diagram-MMU 用在自己的模型评测中如果你手头没有 Diagram-MMU 的官方数据集也可以参考它的设计思路搭一套适用于自己业务场景的图表评测流程。下面演示一个最小可行方案。6.1 定义评测数据格式先把评测样本组织成结构化 JSON。每个样本包括图表路径、问题、选项如果有、参考答案、答案类型。{ sample_id: diagram_mmu_demo_001, image: charts/gdp_bar_chart_2015_2020.png, question: Which year had the highest GDP growth rate compared to the previous year?, options: [2016, 2017, 2018, 2019], answer: 2018, answer_type: single_choice }再来看一个开放数值题的样本。开放数值题必须带上单位否则模型输出的“12.5”和“12.5%”无法判断对错。{ sample_id: diagram_mmu_demo_002, image: charts/line_chart_temperature.png, question: Calculate the average temperature from March to May. Output the value with unit., options: null, answer: 18.3°C, answer_type: free_form_number_with_unit }这种结构的好处是你可以在同一个文件里混合不同难度、不同类型的题目测评时按 answer_type 分组统计观察模型在不同题型上的差异。6.2 设计模型推理的统一接口为了让评测脚本不绑定具体厂商 API定义一个统一的模型调用函数。实际使用时把它替换成你自己的模型推理代码即可。# file: eval_runner.py from typing import Any, Dict, List, Optional import json import random def model_chat(image_path: str, prompt: str) - str: 调用你选定的多模态模型返回文本回答。 这里替换为实际模型推理逻辑例如 - 开源模型加载本地 checkpoint 后 img - tensor - generate - 闭源模型调用 HTTP API 并解析返回结果 # TODO(you): 接入真实模型推理 return def build_prompt(sample: Dict[str, Any], few_shot_prompts: Optional[List[Dict[str, Any]]] None) - str: prompt [SCIENCE DIAGRAM QUESTION]\n prompt fQuestion: {sample[question]}\n if sample.get(options): for idx, opt in enumerate(sample[options]): prompt f {chr(65 idx)}. {opt}\n prompt Output the choice letter only.\n else: prompt Output the answer with the correct unit. Do not include explanations.\n return prompt def normalize_answer(raw_answer: str) - str: 归一化模型输出方便后续比较。 return raw_answer.strip().lower().replace(,, ).replace( , ) def exact_match(pred: str, gold: str) - bool: return normalize_answer(pred) normalize_answer(gold) def evaluate(dataset_path: str, model_chat_fn) - Dict[str, Any]: with open(dataset_path, r, encodingutf-8) as f: samples json.load(f) results {single_choice: {total: 0, correct: 0}, free_form: {total: 0, correct: 0}} for sample in samples: prompt build_prompt(sample) pred model_chat_fn(sample[image], prompt) answer_type sample[answer_type] if answer_type single_choice: results[single_choice][total] 1 # 只取输出中的第一个字母作为预测选项 pred_letter pred.strip().upper()[:1] gold_letter sample[answer].strip().upper()[:1] if pred_letter gold_letter: results[single_choice][correct] 1 else: results[free_form][total] 1 if exact_match(pred, sample[answer]): results[free_form][correct] 1 # 统计准确率 for key in results: total results[key][total] correct results[key][correct] results[key][accuracy] correct / total if total 0 else 0.0 return results if __name__ __main__: # 示例用法 result evaluate(diagram_mmu_sample.json, model_chat) print(json.dumps(result, ensure_asciiFalse, indent2))这个脚本把评测过程拆成了模型调用、Prompt 构造、答案归一化、分组统计四个部分。在实际工程中你只需要替换 model_chat 函数其它部分可以直接复用。6.3 处理数值类答案的归一化开放数值题最怕的是“答案算对了但格式不对”。模型可能输出“18.3 ℃”“18.3°C”“18.3 degrees Celsius”“18.3C”如果你直接用字符串比较结果会非常不稳定。一个更稳的做法是分两步处理先提取数值再判断单位是否匹配。# file: numeric_utils.py import re def extract_number(text: str): 从模型输出中提取数值优先提取第一个浮点数。 candidates re.findall(r-?\d(?:\.\d)?, text) if not candidates: return None return float(candidates[0]) def normalize_unit(unit: str) - str: 把各种写法统一成标准单位降低单位匹配难度。 unit unit.strip().lower().replace(degrees, ).replace(°, ) unit unit.replace(degreescelsius, c).replace(celsius, c) unit unit.replace(percent, %).replace(percentage, %) return unit.replace( , ) def numeric_answer_match(pred_text: str, gold_value: float, gold_unit: str, tolerance: float 1e-2) - bool: pred_value extract_number(pred_text) if pred_value is None: return False if abs(pred_value - gold_value) tolerance: return False # 如果参考答案明确带单位模型输出也必须带单位 if gold_unit: unit_markers [c, %, km, kg, ml, mpa, mm] if not any(marker in pred_text.lower() for marker in unit_markers): return False return True这种归一化并不能覆盖所有情况但至少能解决最常见的格式不一致问题。更复杂的场景比如单位换算需要在评测集构造时就给出明确约定不要在评估脚本层面做过多隐式换算否则会掩盖模型真正的错误。7. 评测中的 Prompt 设计技巧Prompt 对科学图表评测结果的影响远比你想象的大。先看一个反面写法请回答图中的数据。这个 Prompt 不清不楚模型不知道你要它做数值提取、趋势判断还是原因分析。更常见的坑是模型自己决定要输出一大段解释导致最后解析答案时非常痛苦。推荐的做法是在 Prompt 里显式约束三件事任务类型、输出格式、是否带单位。You are an expert at reading scientific diagrams. Given the diagram image, answer the question strictly following the output format. Question: {question} Requirements: 1. If the question has options, output only the choice letter (A/B/C/D). 2. If the question asks for a numeric value, output the number with the correct unit, e.g. 12.5km. 3. Do NOT include explanations, chain-of-thought, or markdown code blocks. 4. If you cannot determine the answer, output UNKNOWN.最后这条“UNKNOWN”很重要。它避免模型在不确定时强行给答案。在评测流程里把“UNKNOWN”当作错误答案统计你才能真正看到模型的能力边界而不是被随机猜测的命中率误导。有一个实践经验值得记住对多模态模型做评测时few-shot 设置要格外小心。给一两个示例往往能让模型更快理解输出格式但如果示例和实际题目来自同一个图表可能会泄露答案。正确做法是示例用另一张完全不同的图并且在示例里同样明确标注“这是示例”。8. 常见问题与排查清单跑科学图表评测时下面这些问题出现频率非常高很多看起来是“模型不行”实际上是评测流程自身的问题。问题现象可能原因排查方式解决方案模型输出一大段解释解析不到答案Prompt 未约束输出格式查看模型原始输出在 Prompt 中显式要求“只输出答案”并在解析脚本中做正则提取数值算对了单位不一致归一化函数对单位处理不完整打印预测值和参考答案引入单位归一化函数先提取数值再匹配单位关键词单选题准确率异常高或异常低模型输出第一个字符不一定对应选项顺序检查多选和单选是否混在一起统计按 answer_type 分组统计单选只比对选项字母模型直接拒绝回答安全策略把科学图表识别为敏感内容查看拒绝原因日志调整系统提示词明确说明这是学术评测任务同一题多次运行结果不一致模型采样随机性太大固定 temperature或运行多次取多数在评测配置中固定随机种子规范 temperature 设置对数坐标图表判断错误模型把对数坐标当作线性坐标单独统计对数坐标题目的错误率在评测集中单独标记“log_scale”做分层分析图例对应关系读错模型对颜色和文字组合理解不足检查图表是否标注了图例映射在图表构造时避免使用相近颜色或改用不同阴影纹理9. 最佳实践与工程建议真正要把 Diagram-MMU 这类基准落地到日常评测体系里建议从这几个角度做规划。第一评测集要分层、可追溯。不要只记录“最终准确率”要给每个样本加上图表类型、问题难度、答案类型、特殊标记这些元信息。这样当模型效果下降时你能立刻定位到是哪一类图表、哪一层级问题出了问题。第二单一指标会骗人。准确率看起来不低可能是因为简单题目多或者模型擅长输出 UNKNOWN。建议至少同时报告按问题类型分层的准确率、回答率、拒绝率。一个“只挑简单题答、难题一律 UNKNOWN”的模型整体准确率可能很高但实际使用价值很低。第三评测时控制模型参数。temperature 要固定推荐调低一些又不过度降低多样性使用 beam search 或采样策略时要保持一致。评测的意义在于横向对比任何非确定性的设置都会降低结果的可复现性。第四注意图表数据泄漏。如果你用的评测图表来自论文或公开数据集训练数据里很可能包含相近图表的记忆痕迹。构造评测集时优先选用自己生成的图表或者在图表样式、配色、坐标范围上做去重变异降低模型靠记忆作答的概率。第五对拒绝率单独监控。多模态模型面对陌生图表时有时会因为无法识别内容而输出“无法回答”。在学术评测里这不是坏事甚至比乱猜更好。但在产品里你需要把它当作“待补充能力”的清单而不是简单归为答错。第六做回归基线。在模型迭代过程中把同一份评测集固定下来每次模型更新后跑一遍对比前一次的得分。科学图表评测要能长期复用才值得投入时间搭建。10. 结语科学图表评测的意义不止于榜单Diagram-MMU 这类科学图表多模态评测基准的出现真正的价值在于它重新定义了“多模态模型理解的瓶颈在哪里”。过去大家在评测报告里看的是综合分数现在可以拆开看感知、数值提取、推理、单位理解各自到了什么水平。这种拆解对技术选型很有用你的业务是靠 OCR 抽取信息还是靠图表做决策判断决定了你该优先优化模型的哪个维度。如果你正在做多模态相关的产品选型或模型评测可以考虑按本文的思路搭建一套自己的图表评测集。不需要一开始就追求大而全先选 100 到 200 个贴合业务的图表样本明确答案类型写一个可复用的评测脚本跑通之后再做扩展。等评测流程稳定了再看模型在感知层、计算层、推理层的分层得分那时候你对模型能力的判断会比任何一份宣传材料都更接近真实水平。