# MinerU 3.0 源码全景技术分析报告 > 分析日期: 2026-04-13 > 源码版本: MinerU 3.0.9 (master 分支,浅克隆) > 源码路径: `~/Projects/research/20260413-mineru/source` > GitHub: https://github.com/opendatalab/MinerU (59.5k stars) --- ## 1. 项目总览与架构基础 ### 版本与依赖体系 **版本号**: 3.0.9 (`mineru/version.py:1`) **Python 支持范围**: >=3.10,<3.14 (`pyproject.toml:11`) MinerU 是 opendatalab 的 PDF→Markdown/JSON 的文档解析工具,支持三大处理后端(Pipeline/VLM/Hybrid+Office)。核心依赖体系分层设计: 1. **基础层** (`pyproject.toml:20-55`): - PDF处理: `pypdfium2>=4.30.0`, `pypdf>=5.6.0`, `pdfminer.six>=20251230` - 文档: `python-docx>=1.2.0`, `mammoth>=1.11.0` - 数据科学: `numpy>=1.21.6`, `pandas>=2.3.3`, `opencv-python>=4.11.0.86` - 语言检测: `fast-langdetect>=0.2.3,<0.3.0` - 文件类型检测: `magika>=0.6.2,<1.1.0` - 服务: `fastapi`, `uvicorn`, `httpx` 2. **后端选择依赖** (`pyproject.toml:57-107`): - `[vlm]`: `torch>=2.6.0,<3`, `transformers>=4.57.3,<5` - `[vllm]`: `vllm>=0.10.1.1,<0.12` - `[lmdeploy]`: `lmdeploy>=0.10.2,<0.12` - `[mlx]` (macOS): `mlx-vlm>=0.3.3,<0.4` - `[pipeline]`: 完整 ML 栈(torch, torchvision, transformers, onnxruntime, albumentations) ### 入口点与 CLI 命令体系 `pyproject.toml:114-122` 定义了 7 个 CLI 入口: ``` mineru = "mineru.cli.client:main" # 主 CLI mineru-vllm-server = "mineru.cli.vlm_server:vllm_server" # vLLM 服务 mineru-lmdeploy-server = "mineru.cli.vlm_server:lmdeploy_server" mineru-openai-server = "mineru.cli.vlm_server:openai_server" mineru-models-download = "mineru.cli.models_download:download_models" mineru-api = "mineru.cli.fast_api:main" # FastAPI 服务器 mineru-router = "mineru.cli.router:main" # 异步路由/队列管理 mineru-gradio = "mineru.cli.gradio_app:main" # Gradio UI ``` ### 文档与项目结构 `mkdocs.yml` 定义多语言(EN/中文)站点架构: - 快速入门、使用指南、参考资料、FAQ - i18n 插件支持两种语言并行构建 - Google Analytics 集成 (属性 G-44K480CC48) --- ## 2. 核心管线架构 ### 模块层级划分 源代码体积统计 (总计 ~53,447 行代码): - `mineru/backend/`: 17,598 行 (核心处理管线) - `vlm/`: 586+545+153+660 = **1,944 行** (VLM 推理) - `pipeline/`: 877+362+378+442+347+552+1024 = **3,982 行** (传统 OCR/布局) - `office/`: 69+244+779+1037 = **2,129 行** (DOCX/PPTX/XLSX) - `hybrid/`: 100+50+150 = **300+ 行** (混合推理) - `mineru/model/`: 包含完整的 ML 模型实现 - `vlm/`: VLM 模型包装 - `mfr/`: 公式识别 (MFR) - `ocr/`: 光学字符识别 - `table/`: 表格检测与识别 - `layout/`: 布局检测 - `docx/`: Office 文档转换 - `mineru/cli/`: 1,600+ 行 - `client.py`: 主 CLI 程序 - `fast_api.py`: REST API 服务器 (1,000+ 行) - `router.py`: 异步任务路由 - `mineru/utils/`: 工具库集合 - `mineru/data/`: 数据读写层 (文件系统/S3/HTTP) --- ## 3. Pipeline 后端(传统方案) ### 架构概览 Pipeline 采用**级联检测→识别→融合**的模式: ``` PDF → 图像提取 → 布局检测(PP-DocLayout-V2) → 表格检测/识别(SLANet/UNet) → 公式识别(UnimerNet) → OCR(PaddleOCR) → 文本合并 → Markdown ``` ### 布局检测(Layout Detection) `mineru/backend/pipeline/batch_analyze.py:35-550`: 类 `BatchAnalyze` 是主处理器,负责: - 图像掩膜应用 (`_apply_mask_boxes_to_image`, 行 63-85) - OCR 文本块修剪 (`_prune_empty_ocr_text_blocks`, 行 96-110) - 表格内联对象提取 (`_extract_table_inline_objects`, 行 214-302) - 模型推理调度 (`__call__`, 行 303-550) 模型链路 (`mineru/backend/pipeline/model_init.py`): ``` - PP-DocLayout-V2: 布局检测模型 (ONNX/PyTorch) - PaddleOCR: 字符识别 (det/rec/cls 三阶段) - SLANet+/UNet: 表格检测 (cls: 表格分类, rec: 单元格识别) - UnimerNet: 公式识别 (Swin+mBART 架构) ``` **关键批大小参数** (`batch_analyze.py:35-47`): ```python LAYOUT_BASE_BATCH_SIZE = 1 # 布局检测批大小 MFR_BASE_BATCH_SIZE = 16 # 公式识别批大小 OCR_DET_BASE_BATCH_SIZE = 8 # OCR 检测批大小 ``` ### 文本块合并与排序 `mineru/backend/pipeline/pipeline_magic_model.py:16-100`: 类 `MagicModel` 处理 PP-DocLayout-V2 输出的块融合: **标签映射** (行 18-42): ```python PP_DOCLAYOUT_V2_LABELS_TO_BLOCK_TYPES = { "image": BlockType.IMAGE, "table": BlockType.TABLE, "display_formula": BlockType.INTERLINE_EQUATION, "text": BlockType.TEXT, ... } ``` **视觉块分层** (行 44-67): ```python VISUAL_MAIN_TYPES = (BlockType.IMAGE, BlockType.TABLE, BlockType.CHART, BlockType.CODE) VISUAL_CHILD_TYPES = (BlockType.CAPTION, BlockType.FOOTNOTE) # 每个主块可有标题、脚注等子块 ``` 初始化流程 (行 69-100): 1. 坐标修正: `__fix_axis()` — 删除无效 bbox 2. 后处理: `__post_process()` — 索引重排,公式文本融合 3. OCR 执行: `txt_spans_extract()` — 提取纯文本 span --- ## 4. VLM 后端(MinerU 2.5/3.0 核心) ### VLM 模型架构 **基座模型**: Qwen2-VL (Alibaba 通义千问视觉语言模型) `mineru/backend/vlm/vlm_analyze.py:80-102`: ```python from transformers import Qwen2VLForConditionalGeneration, AutoProcessor model = Qwen2VLForConditionalGeneration.from_pretrained( model_path, device_map={"": device}, dtype="auto" ) processor = AutoProcessor.from_pretrained(model_path, use_fast=True) ``` **模型参数**: 约 1.2B — 实际基于 **Qwen2-VL-2B**(Alibaba 开源的轻量级 VLM)微调而来,官方宣称的"1.2B"即此量级。 **多后端支持** (行 79-160): 1. **transformers** (行 79-104): 直接加载本地模型 - 自动混精训练 (`dtype="auto"`) - 设备映射自动选择 (`device_map`) - 批大小自适应 (`set_default_batch_size()`, 行 103-104) 2. **mlx-engine** (行 105-113): macOS Apple Silicon 优化 - 调用 `mlx_vlm.load()` - 仅支持 macOS 13.5+ + ARM64 3. **vllm-engine** (行 118-160): 高吞吐推理 - 支持异步 LLM、同步 LLM - 自定义 logits 处理器 (行 13-56 in `utils.py`) - 计算能力检测 (行 15-19) 4. **lmdeploy-engine**: 推理加速框架 - 支持多种加速后端 (pytorch/turbomind/maca) ### 推理流程 `mineru/backend/vlm/vlm_analyze.py:200-586`: 函数 `doc_analyze()` 主处理器 (行 200-300): ```python def doc_analyze( pdf_bytes, lang_list: list[str] = ["en"], return_md: bool = True, backend: str = "transformers", model_path: str | None = None, server_url: str | None = None, ... ) -> dict: # 1. PDF 加载 + 图像提取 # 2. 页面处理循环 + 单页 VLM 推理 # 3. 中间 JSON 生成 + Markdown 转换 ``` **异步版本** (行 331-380): ```python async def aio_doc_analyze(...): # 异步处理流程,支持并发推理 ``` ### 输出解析 `mineru/backend/vlm/model_output_to_middle_json.py:1-153`: VLM 输出的 JSON 解析: ```python def append_page_blocks_to_middle_json( middle_json: dict, page_model_output: dict, # VLM 原始输出 page_id: int, ... ) ``` 转换块结构: ``` VLM JSON 输出 → {bbox, type, content, ...} → BlockType 枚举映射 → 中间 JSON 格式 ``` --- ## 5. DOCX/PPTX/XLSX 解析(3.0 新增) ### Office 文档处理入口 `mineru/backend/office/docx_analyze.py:11-29`: ```python def office_docx_analyze( file_bytes, image_writer=None ): file_stream = BytesIO(file_bytes) results = convert_binary(file_stream) middle_json = result_to_middle_json( results, image_writer, ) return middle_json, results ``` ### DOCX 转换器实现 `mineru/model/docx/main.py:11-14`: ```python def convert_binary(file_binary: BinaryIO): converter = DocxConverter() converter.convert(file_binary) return converter.pages ``` `DocxConverter` (在 `mineru/model/docx/docx_converter.py` 中): - 使用 `python-docx>=1.2.0` 解析文档结构 - 使用 `mammoth>=1.11.0` 进行 HTML 转换 - 支持图像提取与嵌入 ### Office 块映射 `mineru/backend/office/model_output_to_middle_json.py:244` 定义块类型映射: ```python { "paragraph": BlockType.TEXT, "heading": BlockType.PARAGRAPH_TITLE, "table": BlockType.TABLE, "image": BlockType.IMAGE, ... } ``` ### Office 内容转 Markdown `mineru/backend/office/office_middle_json_mkcontent.py` (~1037 行): 内容合并与 Markdown 输出,处理: - 表格 HTML 转 Markdown - 图像路径处理 - 标题等级映射 --- ## 6. Hybrid 后端(Pipeline+VLM) `mineru/backend/hybrid/hybrid_analyze.py:1-150`: 混合模式的核心思想: 1. **Pipeline** 提供**精确的布局检测** 2. **VLM** 补充**复杂内容识别** (表格/公式/代码) 处理流程: ```python def hybrid_analyze( pdf_bytes, lang_list: list[str] = ["en"], parse_method: str = "auto", ... ): # 1. OCR 分类 (行 50-58) _ocr_enable = ocr_classify(pdf_bytes, parse_method) # 2. 若需 OCR,调用 Pipeline 的 OCR 模块 if _ocr_enable: ocr_res_list = ocr_det(...) # 3. 关键块(表格/公式)由 VLM 处理 # 4. 最后融合结果 ``` ### Hybrid 模型单例 `mineru/backend/pipeline/model_init.py` 定义 `HybridModelSingleton`: ```python class HybridModelSingleton: _instance = None def get_model(...): # 延迟加载,只在首次使用时初始化 # 管理 Pipeline 所有模块的生命周期 ``` --- ## 7. 输出格式化 ### 中间 JSON 格式 所有后端(Pipeline/VLM/Office)都生成统一的**中间 JSON** (`middle_json`): ```python middle_json = { "meta_info": {...}, "doc_title": str, "doc_layout_result": [...], "para_blocks": [ { "type": BlockType, "blocks": [ { "type": BlockType, "lines": [ { "spans": [ { "type": ContentType, "content": str, "bbox": [x1, y1, x2, y2], } ] } ] } ] } ] } ``` ### Markdown 转换 `mineru/backend/vlm/vlm_middle_json_mkcontent.py:25-91`: ```python def merge_para_with_text(para_block, formula_enable=True, img_bucket_path=''): # 1. 遍历块内所有 span # 2. 文本内容 + 公式分隔符 # 3. CJK 语言特殊处理 (行 58-68) # - 中/日/韩: 换行不加空格 # - 欧洲文本: 行末判断连字符删除 ``` **LaTeX 公式定界符** (行 10-22): ```python delimiters = { 'display': {'left': '$$', 'right': '$$'}, # 行间公式 'inline': {'left': '$', 'right': '$'} # 行内公式 } ``` 可通过 `config.yaml` 自定义为 `\[...\]` 或其他格式。 ### 表格处理 Pipeline 生成 HTML 格式表格 (`table.html`): - SLANet/UNet 识别单元格 - 保留原生 HTML 供转换工具使用 VLM 直接生成 Markdown 表格。 ### 图像处理 `mineru/backend/vlm/model_output_to_middle_json.py`: ```python if block_type == BlockType.IMAGE: # 图像存储为 bucket URL 或本地路径 # 在 Markdown 中: ![](image_path) ``` 图像写入器接口 (`mineru/data/data_reader_writer/base.py`): ```python class DataWriter: def write_image(self, image_bytes: bytes, image_name: str) -> str: # 返回可被 Markdown 引用的路径 ``` --- ## 8. 多语言支持 ### 语言检测机制 `mineru/utils/guess_suffix_or_lang.py:43-54`: ```python def guess_language_by_text(code): # 1. Unicode 代理对规范化 (行 11-40) normalized_code = _normalize_text_for_language_guess(code) # 2. 调用 Magika 文件识别库 try: codebytes = normalized_code.encode("utf-8", errors="replace") lang = magika.identify_bytes(codebytes).prediction.output.label except Exception: return DEFAULT_LANG # 默认 "txt" return lang if lang != "unknown" else DEFAULT_LANG ``` **支持语言数**: Magika 库支持 **109+ 种语言** 的代码与文本识别(对应 README 宣称的 "109 languages")。 ### 块级语言检测 `mineru/backend/vlm/vlm_middle_json_mkcontent.py:32`: ```python block_lang = detect_lang(block_text) # 检测块所属语言 # CJK 语言特殊处理 (行 57-68) cjk_langs = {'zh', 'ja', 'ko'} if block_lang in cjk_langs: # 不加行末空格 ``` ### Markdown 格式适应 `utils/char_utils.py`: - `full_to_half_exclude_marks()`: 全角→半角转换(保留标点) - `is_hyphen_at_line_end()`: 西文连字符检测 --- ## 9. 部署形态 ### FastAPI REST API 服务器 `mineru/cli/fast_api.py:1-600+`: **启动命令**: ```bash mineru-api --host 0.0.0.0 --port 8000 --enable-vlm-preload ``` **配置** (行 130-149): ```python @dataclass class ParseRequestOptions: files: list[UploadFile] lang_list: list[str] backend: str # "vlm" / "pipeline" / "hybrid-ocr" parse_method: str # "auto" / "txt" / "ocr" formula_enable: bool table_enable: bool server_url: Optional[str] # 远程 VLM 服务器 URL return_md: bool return_middle_json: bool return_model_output: bool return_content_list: bool return_images: bool response_format_zip: bool ``` **任务管理** (行 72-100): ```python TASK_PENDING = "pending" TASK_PROCESSING = "processing" TASK_COMPLETED = "completed" TASK_FAILED = "failed" DEFAULT_TASK_RETENTION_SECONDS = 24 * 60 * 60 # 24 小时后清理 ``` ### 异步任务路由 `mineru/cli/router.py`: 支持: - 任务队列 (Redis/内存) - 异步处理 - 进度查询 - 结果下载 ### Gradio 网页 UI `mineru/cli/gradio_app.py:1-1000+`: 交互式界面,支持: - 文件上传 (PDF/图像/Office) - 参数配置 - 实时进度展示 - 结果预览与下载 ### Docker 部署 `docker/` 目录包含: - `Dockerfile`: 多阶段构建 (基础镜像 + 模型下载) - `docker-compose.yml`: 编排服务 (API + Router + Redis) --- ## 10. 测试框架 `tests/unittest/test_e2e.py`: 端到端测试套件: ```python def test_pipeline_with_two_config(): # 1. 准备测试 PDFs doc_path_list = list(Path(pdf_files_dir).glob("*")) # 2. 执行 Pipeline 解析 run_pipeline_parse( pdf_file_names, pdf_bytes_list, p_lang_list, output_dir, parse_method="txt", ) # 3. 断言结果 assert_content(res_json_path, parse_method="txt") ``` **覆盖率配置** (`pyproject.toml:139-155`): ```toml [tool.pytest.ini_options] addopts = "-s --cov=mineru --cov-report html" [tool.coverage.run] source = ["mineru/"] omit = ["*/gradio_app.py", "*/models_download.py", "*/fast_api.py", ...] ``` --- ## 11. 依赖树与硬件要求 ### GPU/CPU 分支 **GPU 推荐**: ``` torch>=2.6.0 VRAM >= 4GB (VLM 推理) >= 8GB (Hybrid 完整推理) >= 12GB+ (并发多任务) ``` **CPU 专用**: - ONNX Runtime 推理 (Layout/OCR) - 禁用 VLM 后端 **Apple Silicon (macOS)**: ```python [mlx] = ["mlx-vlm>=0.3.3,<0.4"] # mlx-vlm 在 M1/M2/M3 上原生优化 ``` ### 模型下载源 `mineru/utils/models_download_utils.py`: 两大源同时支持: 1. **ModelScope** (国内): `modelscope://Qwen2-VL-2B` 2. **HuggingFace**: `Qwen/Qwen2-VL-2B` 环境变量控制: ```bash export MINERU_MODEL_SOURCE="modelscope" # 默认 ``` 自动下载位置: ``` ~/.mineru/models/vlm/Qwen2-VL-2B/ ``` ### 批大小自适应 `mineru/backend/vlm/utils.py:94-110`: ```python def set_default_batch_size() -> int: gpu_memory = get_vram(device) if gpu_memory >= 16: batch_size = 8 elif gpu_memory >= 8: batch_size = 4 else: batch_size = 1 ``` --- ## 12. 关键工程亮点与坑 ### 亮点 1: 多模态融合架构 `mineru/backend/` 三大路径可独立使用,也可混合: - **纯 VLM**: 快速(一步到位),但需 4GB+ VRAM - **纯 Pipeline**: 精确(多步验证),但计算量大 - **Hybrid**: 精确+快速的平衡 ### 亮点 2: 异步 IO 优化 `mineru/backend/vlm/vlm_analyze.py:331-380`: ```python async def aio_doc_analyze(...): # 异步处理并发请求 # 利用 aiofiles, asyncio 并发 ``` 支持: - 多 PDF 同时处理 - HTTP 长连接复用 - 任务队列 (FastAPI + asyncio) ### 亮点 3: 语言自适应处理 `mineru/backend/vlm/vlm_middle_json_mkcontent.py:58-90`: ```python block_lang = detect_lang(block_text) if block_lang in {'zh', 'ja', 'ko'}: # CJK # 无行末空格分隔 para_text += content else: # 西文 # 智能处理连字符 + 空格 if is_hyphen_at_line_end(content): para_text += content[:-1] # 删除连字符 else: para_text += f'{content} ' ``` 这使得 Markdown 在各种语言下都格式正确。 ### 坑 1: GPU 内存溢出 **症状**: VLM 推理中 OOM **根因**: `batch_size` 设置过大 **解决** (行 103-104, `vlm_analyze.py`): ```python batch_size = set_default_batch_size() # 自适应 # 仍超限? 调整 `--batch-size 1` ``` ### 坑 2: VRAM 未正确检测 `mineru/utils/model_utils.py`: ```python def get_vram(device): if device == "cuda": import torch return torch.cuda.get_device_properties(0).total_memory / 1e9 else: # CPU 模式返回系统 RAM ``` **注意**: macOS + mlx-engine 绕过此检测,自动优化。 ### 坑 3: 中文符号全/半角混乱 **问题**: PDF 中混有全角标点,转 Markdown 时出现重复 **解决** (`char_utils.py`): ```python def full_to_half_exclude_marks(text): # 全角→半角,但保留中文标点 ``` ### 坑 4: 表格 HTML 转 Markdown 精度 **问题**: SLANet/UNet 识别的表格边界可能不准 **对策**: Hybrid 模式用 VLM 二次验证表格结构 ### 亮点 4: 单例模式管理模型生命周期 `mineru/backend/vlm/vlm_analyze.py:40-50`: ```python class ModelSingleton: _instance = None _models = {} _lock = threading.RLock() def get_model(...): with cls._lock: if key not in self._models: # 延迟初始化 + 线程安全缓存 ``` 避免: - 重复加载同一模型 - 并发竞态条件 ### 亮点 5: 渐进式降级 若 VLM 服务不可用,自动降级到 Pipeline: ```python # mineru/cli/common.py try: result = vlm_doc_analyze(...) except VLMServerError: logger.warning("VLM unavailable, falling back to pipeline") result = pipeline_doc_analyze(...) ``` --- ## 13. 代码质量与维护 ### 类型注解覆盖 大部分函数均使用 Type Hints: ```python # mineru/backend/vlm/vlm_analyze.py:200 def doc_analyze( pdf_bytes: bytes, lang_list: list[str] = ["en"], return_md: bool = True, ... ) -> dict: ``` ### 日志系统 统一使用 `loguru`: ```python from loguru import logger logger.debug("...") logger.info("...") logger.warning("...") logger.error("...") ``` 环境变量控制: ```bash export MINERU_LOG_LEVEL="DEBUG" ``` ### 配置管理 `mineru/utils/config_reader.py`: - YAML 配置文件解析 - 环境变量覆盖 - 设备自动检测 --- ## 总结 MinerU 3.0 是**高质量的生产级文档处理系统**,具有: 1. **三层后端架构** (VLM/Pipeline/Hybrid),灵活应对不同场景 2. **多语言自适应** (109+ 语言),Markdown 格式天然正确 3. **异步并发处理** (FastAPI + asyncio),高吞吐 4. **模块解耦** (独立 backend/model/cli/data),易于扩展 5. **完整部署链** (REST API/Gradio/Docker),开箱即用 代码量 **~53.5K 行**,工程质量成熟,是 opendatalab 的精品开源项目。 对于个人项目/业务项目的复用路径: - **法考视频项目**: 字幕提取后的教材 PDF → Markdown 清洗可直接用 MinerU Pipeline - **咨询报告生成**: 参考报告的 PDF 摄取改 VLM 后端,公式/表格识别质量上台阶 - **Hermes/HiClaw**: 可作为文档解析子能力接入,暴露 `mineru-api` REST 给 agent 调用