【文档解析】一文吃透 MinerU2.5:模型训练细节及本地部署效果测试
一、MinerU2.5模型技术细节
MinerU2.5 是一个拥有 12 亿参数的视觉-语言模型(VLM),专用于文档解析,在保持高计算效率的同时实现了业界领先的准确率。它采用两阶段解析策略:首先在下采样图像上进行高效的全局版面分析,然后在原始分辨率裁剪区域上对文本、公式和表格执行细粒度内容识别。借助一个大规模、多样化的数据引擎支持预训练和微调,MinerU2.5 在多个基准测试中持续优于通用模型和领域专用模型,同时保持较低的计算开销。
主要改进 :
- 全面且精细的版面分析:不仅保留页眉、页脚和页码等非正文元素以确保内容完整性,还采用更精细、标准化的标注方案,使列表、参考文献和代码块等元素呈现得更加清晰、结构化。
- 公式解析的重大突破:能够高质量解析复杂、长篇幅的数学公式,并准确识别中英混合的方程式。
- 表格解析鲁棒性增强:轻松应对旋转表格、无边框表格以及部分边框缺失等挑战性场景。

1.1、研究背景
MinerU2.5的核心研究目标是实现高效的高分辨率文档解析。当前文档图像普遍具有高分辨率、内容密集、结构布局复杂的特点,这给解析工作带来了三大核心难点:一是高分辨率输入导致的计算开销过大;二是文档文本密集且篇幅长,对模型的参数效率和鲁棒性提出了更高要求;三是OCR解析不仅需要精准识别文本,还依赖可靠的布局分析和高效的推理能力。
目前文档智能解析的相关方案主要分为两类:传统基于管道的方法,虽采用模块化设计,但存在错误传播、复杂布局处理能力不足的问题;基于视觉语言模型(VLMs)的端到端方法,语义建模能力较强,但在长文档处理中易出现幻觉,且高分辨率输入下效率低下。MinerU2.5正是为解决这些痛点而研发。
1.2、核心创新
1.2.1 关键核心创新
MinerU2.5的核心创新在于采用解耦架构,通过“由粗到细”的两阶段推理机制,将全局布局分析与局部内容识别分离,兼顾效率与精度:第一阶段对下采样的文档图像进行快速全局布局分析,以最低计算成本捕捉文档整体结构;第二阶段根据布局检测结果,从原始高分辨率图像中裁剪关键区域,进行细粒度内容识别,既保留原始分辨率优势,又确保解析精度。
除此之外,其创新点还包括:
- 精细化布局分析:完整保留页眉、页脚、页码等非主体元素,采用标准化标签方案,使列表、引用、代码块等元素的表示更清晰结构化。
- 高效解析能力:采用ADR框架实现复杂冗长数学公式的高精度解析,支持中英文混合方程式;优化表格识别,可轻松处理旋转、无边框、部分边框等复杂表格案例。
- 轻量且高效:仅1.2B参数,在长文档、高密度内容场景中适应性强,兼顾解析精度与推理效率。
- 技术优化:将布局分析定义为多任务问题,同步预测文档元素的位置、类别、旋转角度和阅读顺序;引入PageIoU度量,解决传统指标在文档布局评估中的适用性问题;采用OTSL中间表示优化表格识别,缩短序列长度、提升准确性;搭建封闭循环数据引擎,保障模型在各类场景下的鲁棒性。
1.3、与前期MinerU版本对比
相较于前期MinerU版本,MinerU2.5在核心性能和功能上均有显著提升:通过两阶段解耦策略大幅提升计算效率与解析精度,优化了布局分析、公式解析和表格识别的核心能力,同时凭借轻量级设计和多技术创新,在长文档、复杂布局等场景下的适应性和鲁棒性更优,整体解析表现更为出色。
1.4、MinerU2.5 核心架构与训练流程
1.4.1 模型基础架构
MinerU2.5 由三大标准组件构成,整体设计简洁高效:
- 语言模型:采用 0.5B 参数 Qwen2-Instruct,以 M-RoPE 替代原生 1D-RoPE,提升多分辨率场景下的泛化能力。
- 视觉编码器:使用 675M 参数 NaViT,支持动态分辨率与 2D-RoPE 位置编码,通过分桶机制适配不同尺寸输入。
- 补丁合并器:基于像素混洗实现计算效率与解析性能的平衡,作为视觉与语言模态间的特征桥梁。

1.4.2 两阶段解析流程
模型采用 “由粗到细” 的解耦推理策略,兼顾速度与精度:
-
阶段一:全局布局分析
将原图统一缩放至 1036×1036 进行快速检测,识别标题、页码、表格、公式等结构元素,以低开销完成全局结构捕捉,避免高分辨率全图计算。
-
阶段二:局部细粒度识别
依据布局结果从原图裁剪关键区域,以原生分辨率(上限 2048×2048)执行文本、公式、表格精准识别,在细节保留与计算量之间取得最优平衡。
1.4.3 三阶段训练体系
MinerU2.5的训练分为三个阶段:模态对齐阶段、文档解析预训练阶段和文档解析微调阶段。
模态对齐阶段
为了让模型拥有可靠的视觉-语言对齐能力和基础的OCR识别效果,研究团队先在VQA数据集上进行了两阶段的模态对齐训练。
第一阶段只训练块合并器中的两层MLP,同时冻结视觉编码器和语言模型的参数,利用图像-标题对数据将视觉特征映射到语言模型的嵌入空间,实现模态对齐,既保证对齐效果,又避免破坏模型原有能力;
第二阶段则解冻全部参数,在带指令的图像和OCR数据上进行微调,把基础的对齐能力转化为可实际使用的理解与响应能力,让模型能够根据需求完成图文理解、文字识别等真实场景任务。
文档解析预训练
这个阶段主要是给模型打好文档理解的基础能力,采用全参数开放训练,依靠大规模、多样化的数据让模型真正学会处理文档。一方面让模型学会对整页图片做全局布局分析,识别标题、页码、表格、公式等版面结构;另一方面针对裁切后的文本、公式、表格区域做专项识别,分别用“布局检测:”“文本识别:”“公式识别:”“表格识别:”等提示词进行引导训练。整个过程一共训练2个epoch,每轮约690万样本,其中布局分析、文本、公式、表格数据均衡分布。经过这一阶段训练后,模型在常规和中等难度的文档上已经能稳定完成版面分析与内容识别,既为后续微调提供了可靠的基底模型,也能在数据处理中自动筛选出难解析样本,为后续优化提供方向。
文档解析微调
文档解析微调阶段的核心思路是兼顾原有能力与难点突破,在保留模型已习得能力的前提下进一步提升解析性能。训练中一方面从预训练数据中筛选高质量、多样化的样本继续学习,防止模型出现“学新忘旧”的灾难性遗忘;另一方面针对海量PDF中模型表现不佳的困难场景,补充高质量人工标注数据进行专项优化。本次微调共开展3轮,每轮使用约63万条样本,其中布局分析4.3万条、文本块30万条、公式块14.7万条、表格块14万条,实现了基础能力与复杂场景效果的同步提升。训练后的模型在旋转表格、长公式、密集文本、扫描件等高难度场景解析精度大幅提升,同时保持常规文档的稳定输出,泛化性显著增强。
数据增强
为让模型适配真实世界中模糊、倾斜、带干扰的各类文档,在预训练 + 微调两个阶段都加入针对性数据增强,模拟真实文档干扰,强化模型抗干扰能力。
(1)空间变换类
模拟文档拍摄、扫描的几何畸变,提升布局与位置识别稳定性:
- 缩放(Scaling):调整文档尺寸,适配不同分辨率输入。
- 网格扭曲(Grid Distortion):模拟纸张褶皱、扫描变形。
- 旋转(Rotation):覆盖 0°-360° 旋转,适配倾斜文档、倒置表格。
(2)背景与画质变换类
模拟真实文档的画质损耗与背景干扰,提升 OCR 与内容识别鲁棒性:
- 纹理 / 天气效果:添加纸张纹理、噪点、阴影,模拟旧文档、打印瑕疵。
- 图像背景替换:切换不同底色、水印背景,适配复杂版式文档。
- 画质退化:高斯模糊、振动模糊、腐蚀 / 膨胀,模拟低清扫描件、拍照模糊。
(3)色彩变换类
适配彩色文档、褪色文档,提升色彩复杂场景的识别能力:
- 亮度、对比度、光照调整:模拟过曝、欠曝拍摄效果。
- RGB 通道偏移:适配褪色、偏色的旧文档与彩色印刷品。
二、本地部署实战
2.1、环境搭建
(1)基础环境
conda create -n mineru2.5 python=3.10 -y
conda activate mineru2.5
pip install torch vllm pillow opencv-python
(2)安装vllm框架
要使用vllm框架进行推理,执行下述命令安装即可,这里vllm库的版本要大于0.10.1。
pip install "mineru-vl-utils[vllm]"
2.2、模型下载
(1)modelscope下载,建议用modelscope下载,win系统可通过git下载:https://modelscope.cn/models/OpenDataLab/MinerU2.5-2509-1.2B
(2)Hugging Face下载:https://huggingface.co/opendatalab/MinerU2.5-2509-1.2B/tree/main
2.3、模型推理代码
import os
from pathlib import Path
from typing import List, Dict
from vllm import LLM
from PIL import Image
from mineru_vl_utils import MinerUClient, MinerULogitsProcessor
def convert_blocks_to_markdown(
blocks: List[Dict],
output_md_path: str,
original_image: Image.Image,
image_subdir: str = "images"
) -> None:
"""
将 MinerU 提取的块结构转换为带图片的 Markdown 文件
:param blocks: 模型返回的文本/图片块列表
:param output_md_path: 输出的 .md 文件路径
:param original_image: 原始输入图片(PIL Image)
:param image_subdir: 图片保存的子文件夹名称(相对md文件)
"""
# 路径处理
output_path = Path(output_md_path)
output_dir = output_path.parent
images_dir = output_dir / image_subdir
images_dir.mkdir(exist_ok=True)
img_width, img_height = original_image.size
image_counter = 0
with open(output_path, "w", encoding="utf-8") as f:
for block in blocks:
content = block.get("content", "").strip()
block_type = block.get("type", "")
bbox = block.get("bbox")
# 处理图片块
if block_type == "image" and bbox is not None and len(bbox) == 4:
try:
left, top, right, bottom = bbox
# 归一化坐标 → 像素坐标
left_px = max(0, int(left * img_width))
top_px = max(0, int(top * img_height))
right_px = min(img_width, int(right * img_width))
bottom_px = min(img_height, int(bottom * img_height))
# 裁剪并保存
cropped_img = original_image.crop((left_px, top_px, right_px, bottom_px))
image_counter += 1
img_filename = f"img_{image_counter:03d}.png"
img_save_path = images_dir / img_filename
cropped_img.save(img_save_path)
# Markdown 图片引用(相对路径)
rel_path = os.path.relpath(img_save_path, output_dir)
f.write(f"\n\n")
except Exception as e:
print(f"⚠️ 图片块处理失败: {e}")
continue
# 处理文本块
else:
if not content:
continue
if block_type == "title":
f.write(f"# {content}\n\n")
else:
f.write(f"{content}\n\n")
print(f"✅ Markdown 已保存: {output_path.resolve()}")
def main():
# ===================== 配置项(你只需要改这里)=====================
MODEL_PATH = "/path/to/MinerU-2.5-vl" # 你的本地模型文件夹
TEST_IMAGE_PATH = "test_img/p5.jpg" # 测试图片
OUTPUT_MD_PATH = "output/p5.md" # 输出markdown
GPU_MEM_UTIL = 0.8 # GPU显存利用率
# 初始化 vLLM
print("🔄 正在加载 vLLM 模型...")
llm = LLM(
model=MODEL_PATH,
logits_processors=[MinerULogitsProcessor()], # 修复:必须实例化
gpu_memory_utilization=GPU_MEM_UTIL,
trust_remote_code=True,
dtype="bfloat16"
)
# 初始化 MinerU 客户端
print("🔄 初始化 MinerU 客户端...")
client = MinerUClient(
backend="vllm-engine",
vllm_llm=llm
)
# 加载图片并提取内容
print(f"🖼️ 正在解析图片: {TEST_IMAGE_PATH}")
with Image.open(TEST_IMAGE_PATH) as img:
extracted_blocks = client.two_step_extract(img)
# 导出 Markdown
convert_blocks_to_markdown(
blocks=extracted_blocks,
output_md_path=OUTPUT_MD_PATH,
original_image=img
)
print("🎉 全部处理完成!")
if __name__ == "__main__":
main()
2.4、推理测试
输入图片:
测试效果:

三、资源链接
论文题目: MinerU2.5: A Decoupled Vision-Language Model for Efficient High-Resolution Document Parsing
论文链接: https://arxiv.org/abs/2509.22186
github链接: https://github.com/opendatalab/MinerU
模型下载链接: https://modelscope.cn/models/OpenDataLab/MinerU2.5-2509-1.2B
官方体验链接:https://mineru.net/OpenSourceTools/Extractor
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)