Skip to content

Repository files navigation

基于 MinerU 的材料文献智能解析应用

从 200+ 篇材料科学 PDF 文献中自动抽取结构化信息(材料身份、结构、性能、合成、应用、元数据),跨文献实体融合,并提供 Streamlit Web 可视化界面。


一、项目概述

本项目是一个面向材料科学领域的智能文献解析系统,作为竞赛 Demo 实现。系统接收约 210 篇 PDF 格式的材料文献(包括期刊论文和学位论文),通过以下技术栈完成端到端的结构化信息抽取:

  • MinerU 精准解析 API(VLM 模型):将 PDF 转为结构化 JSON(含表格、公式、图片、章节层级)
  • DeepSeek-V4-Pro(思考模式 + JSON Output):基于大模型做 Schema 级结构化抽取
  • Streamlit:提供 Web 可视化查询界面

整个流程分为 PDF 解析 → 语义分块 → Schema 抽取 → 原文溯源校验 → 跨文献聚合 五个阶段,支持断点续跑、并行加速、失败重试。


二、整体架构

材料文献/赛题数据/*.pdf  (210 篇)
        │
        ▼
┌─────────────────────────────────────────┐
│  pdf_splitter.py                        │  长 PDF 本地切片(>180 页,规避 MinerU 200 页限制)
└─────────────┬───────────────────────────┘
              ▼
┌─────────────────────────────────────────┐
│  run_parse.py  →  mineru_client.py      │  批量提交 MinerU API,多 key 并行,chunk 级状态机
└─────────────┬───────────────────────────┘
              ▼  data/parsed/{chunk_id}/content_list.json
┌─────────────────────────────────────────┐
│  doc_chunker.py                         │  MinerU 输出 → Document(章节、摘要、表格、全文)
└─────────────┬───────────────────────────┘
              ▼
┌─────────────────────────────────────────┐
│  extractor.py                           │  两阶段抽取(DeepSeek-V4-Pro)
│    Phase 1 串行: 摘要锚点 + Material + Metadata
│    Phase 2 并行: Structure + Properties + Synthesis + Application + Relationships
│    后处理: verify_original_texts 原文溯源校验
│    可选: refine_extraction 迭代精炼
└─────────────┬───────────────────────────┘
              ▼  data/extracted/{stem}.json
┌─────────────────────────────────────────┐
│  aggregator.py                          │  Union-Find 三级匹配(精确→别名→模糊 Jaccard)
│                                         │  + 实体关系知识图谱
└─────────────┬───────────────────────────┘
              ▼  data/aggregated/entities.json + properties.tsv + relationships.json
┌─────────────────────────────────────────┐
│  app.py (Streamlit)                     │  总览 / 单文献 / 实体浏览 / 性能查询 / 流水线
└─────────────────────────────────────────┘

三、环境安装

3.1 系统要求

  • Python 3.10+(推荐 3.11 或 3.12)
  • conda 或 miniconda(用于环境管理)
  • 网络连接(需要访问 MinerU API 和 DeepSeek API)

3.2 创建 conda 环境并安装依赖

# 创建环境
conda create -n minerU_env python=3.11 -y
conda activate minerU_env

# 安装依赖包
pip install streamlit openai requests pypdf

项目中用到的外部 Python 包只有 4 个:

包名 用途 最低版本建议
streamlit Web 可视化界面 ≥1.30
openai 调用 DeepSeek API(OpenAI SDK 兼容) ≥1.0
requests 调用 MinerU API ≥2.28
pypdf PDF 切片(处理超长文献) ≥3.0

其余均为 Python 标准库(json、re、difflib、concurrent.futures、dataclasses、pathlib、argparse、threading、zipfile 等),无需额外安装。

3.3 目录结构确认

确保项目目录结构如下:

基于MinerU的材料文献智能解析应用/
├── config.json                 ← API 密钥配置(需手动填写)
├── 材料文献/
│   └── 赛题数据/               ← 放置 210 篇 PDF(1.pdf ~ 210.pdf)
├── 赛题说明/
│   ├── Schema.json             ← 抽取目标 Schema 定义
│   └── *.json                  ← 2 份赛题标注样本(用作 few-shot)
├── src/                        ← 全部源代码
├── data/                       ← 运行时自动生成
├── run_streamlit.bat           ← Windows 启动脚本
└── run_streamlit.sh            ← Linux/Git Bash 启动脚本

四、配置文件

4.1 config.json

在项目根目录创建 config.json,填入你的 API 密钥:

{
  "mineru_api_keys": [
    "<MinerU JWT Token 1>",
    "<MinerU JWT Token 2>"
  ],
  "deepseek_api_key": "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "deepseek_user_id": "mineru_extract"
}

各字段说明:

  • mineru_api_keys:MinerU 精准解析 API 的 JWT Token 数组。支持多个 key 并行解析,至少填 1 个。可在 MinerU 官网 注册获取。
  • deepseek_api_key:DeepSeek API 密钥。在 DeepSeek 开放平台 获取。
  • deepseek_user_id(可选):用于 DeepSeek 并发隔离的标识符,不同 user_id 各自独立享有 500 并发上限。默认值 "mineru_extract"。多批次并行跑时建议为每批设不同的 user_id。

4.2 兼容旧格式

config.py 同时兼容以下旧格式,无需手动迁移:

{
  "api_key": "<单个 MinerU Token>",
  "deepseek_api_key": "sk-xxx"
}

或散列格式:

{
  "api_key_1": "<Token 1>",
  "api_key_2": "<Token 2>",
  "deepseek_api_key": "sk-xxx"
}

五、运行流程

第一步:统计 PDF 页数

扫描所有 PDF,统计页数和文件大小,输出到 data/pdf_meta.json。

conda activate minerU_env
python src/utils/survey_pdfs.py

这一步会识别出超过 MinerU 200 页限制的长 PDF(如学位论文),为后续切片做准备。

第二步:长 PDF 切片

将超过 180 页的 PDF 在本地切分成多个小块(每块 ≤180 页,留 20 页缓冲)。

# 生成切片计划(读取上一步的 pdf_meta.json)
python src/pdf_splitter.py

# 执行并行切片(实际切割 PDF 文件)
python src/utils/split_all_parallel.py

pdf_splitter.py 读取 data/pdf_meta.json,规划哪些 PDF 需要切片,输出 data/split_plan.json。split_all_parallel.py 则实际执行切割,将切片 PDF 输出到 data/splits/{stem}/ 目录。短 PDF(≤180 页)不做切片,直接以原文件参与后续流程。

第三步:批量 MinerU 解析

将所有 PDF chunk 提交到 MinerU 精准解析 API,转为结构化 JSON。

# 先跑一小批测试(每个 key 只提交 1 个 batch)
python src/run_parse.py --max-batches-per-key 1

# 确认无误后全量运行
python src/run_parse.py

命令行参数:

参数 默认值 说明
--poll-interval 60 轮询间隔(秒)
--max-batches-per-key 无限制 每个 key 最多提交几个 batch(用于测试)
--max-per-batch 50 每个 batch 最多几个文件
--keys all 使用哪些 key(all 或逗号分隔的索引如 0,1)
--harvest-only false 仅收割已完成的 batch,不提交新任务

特性:

  • 多 key 并行:每个 MinerU key 跑独立工作线程
  • 断点续跑:状态持久化在 data/parse_state.json,中断后再跑会自动跳过已完成的 chunk
  • 失败隔离:单个 chunk 失败不影响其他 chunk

失败重试: 如果有解析失败的 chunk,可用 retry_failed.py 自动重试:

# 查看哪些 chunk 失败了(不修改状态)
python src/retry_failed.py --dry-run

# 执行重试(根据错误类型自动选择策略:开启 OCR / 调整切片大小)
python src/retry_failed.py

# 强制某些文献以 OCR 模式重提
python src/retry_failed.py --force-ocr-stems 15,42
参数 默认值 说明
--dry-run false 仅打印,不修改 state
--max-retries 3 同一 chunk 最大重试次数
--force-ocr-stems 空 逗号分隔的 stem 列表,强制以 OCR 模式重提

第四步:Schema 抽取

对每个 MinerU 解析完成的文献执行大模型结构化抽取。

# 冒烟测试 10 篇
python src/run_extract.py --limit 10 --user-id smoke_10

# 扩大到 30 篇
python src/run_extract.py --limit 30 --user-id smoke_30

# 全量并行(10 篇同时抽取)
python src/run_extract.py --concurrent 10

# 只抽取指定文献
python src/run_extract.py --only 3,7,15

# 启用迭代精炼(抽完后自查修补 1 轮)
python src/run_extract.py --refine 1 --concurrent 5

命令行参数:

参数 默认值 说明
--limit 全部 最多抽取多少篇(冒烟测试用)
--concurrent 1 文档级并行数(建议 5-15,每篇内部 5 路并行)
--only 全部 只抽取指定的文献编号(逗号分隔)
--force false 强制重新抽取已有结果
--user-id 自动 DeepSeek user_id(不同批次用不同 id 隔离并发)
--refine 0 迭代精炼轮数(0=不精炼,1=自查修补一轮)

单篇抽取: 也可以直接调用 extractor.py 抽取单篇(默认抽取第 3 篇):

python src/extractor.py           # 抽取 data/parsed/3 → data/extracted/3.json

第五步:跨文献聚合

将所有抽取结果做实体融合和关系图谱构建。

python src/aggregator.py

输出文件:

  • data/aggregated/entities.json — 同一材料跨文献合并(含所有性能、合成、应用数据)
  • data/aggregated/properties.tsv — 全部性能数据扁平化表格(带文献溯源)
  • data/aggregated/relationships.json — 材料间关系知识图谱(节点 + 边)

第六步:启动 Web 界面

# Windows
run_streamlit.bat

# 或手动启动
streamlit run src/app.py --server.port 8501

浏览器打开 http://localhost:8501 即可使用。Web 界面包含 5 个页面:

  1. 总览 Dashboard — 抽取进度、文献统计、性能类别分布
  2. 单文献详情 — 查看某篇文献的完整抽取结果(6 个 Schema 块)
  3. 实体浏览器 — 跨文献融合后的材料实体,含关系图谱可视化;支持重新聚合
  4. 性能数据查询 — 按材料名、性能类别、关键词搜索所有性能数据
  5. 抽取流水线 — 上传新 PDF 并在线执行抽取

六、模块说明

核心模块

模块 说明
config.py 统一配置加载,兼容多种 config.json 格式
mineru_client.py MinerU 精准解析 API 客户端(上传→轮询→下载解压)
pdf_splitter.py 长 PDF 本地切片(pypdf,180 页/块)
doc_chunker.py MinerU content_list.json → Document 对象(章节分块、摘要识别、表格提取)
deepseek_client.py DeepSeek-V4-Pro 客户端(OpenAI SDK 兼容,启用 thinking 模式 + JSON Output + 429 退避)
extractor.py 两阶段 Schema 抽取核心(Phase 1 串行锚点 + Phase 2 并行 5 块 + 原文校验 + 迭代精炼)
schema_validator.py 抽取结果结构化校验(字段存在性、类型检查)
few_shot.py Few-shot 示例管理(静态标注 + 动态验证池,上下文感知智能选择)
aggregator.py 跨文献实体聚合(Union-Find 三级匹配)+ 关系知识图谱

入口脚本

脚本 说明
run_parse.py 批量 MinerU 解析入口(多 key 并行,chunk 级状态机,断点续跑)
run_extract.py 批量 Schema 抽取入口(文档级并行,冒烟测试,迭代精炼)
retry_failed.py 自动重试 MinerU 解析失败的 chunk(开启 OCR / 调整切片大小)
app.py Streamlit Web 应用

工具脚本

脚本 说明
utils/survey_pdfs.py 统计全部 PDF 页数和大小 → data/pdf_meta.json
utils/split_all_parallel.py 并行切片所有超长 PDF → data/split_plan.json

七、数据目录

运行时自动生成的文件全部在 data/ 下:

data/
├── parsed/                  MinerU 解析输出(每个 chunk 一个子目录)
│   ├── {chunk_id}/
│   │   ├── *_content_list.json    结构化内容(核心输入)
│   │   ├── full.md                全文 Markdown
│   │   ├── full.html              全文 HTML
│   │   ├── layout.json            版面分析
│   │   └── images/                提取的图片
│   └── ...
├── splits/                  长 PDF 切片(本地生成的小 PDF)
├── raw_zips/                MinerU 返回的原始 zip 包(备份)
├── extracted/               Schema 抽取结果(每篇一个 JSON)
│   ├── 1.json
│   ├── 2.json
│   └── ...
├── aggregated/              跨文献聚合结果
│   ├── entities.json        实体融合
│   ├── properties.tsv       性能数据扁平表
│   └── relationships.json   关系知识图谱
├── fewshot_pool/            动态 few-shot 样本池(人工校验后的高质量结果)
├── logs/                    运行日志
├── parse_state.json         MinerU 解析状态机(断点续跑)
├── split_plan.json          PDF 切片计划
└── pdf_meta.json            PDF 页数/大小统计

八、抽取 Schema 说明

系统按赛题定义的 Schema 抽取 6 个顶层块,以下是各块的字段概要(详见 赛题说明/Schema.json):

Schema 块 主要内容 关键特征
Material CAS 号、通用名、缩写、化学名、材料类型/子类型 聚合主键
Structure 分子式、SMILES、基本单元、分子量、拓扑结构、结晶度、孔结构等 软校验
Properties 性能类别(11 类)、名称、表征方法、条件、值、单位、原文引用 数组,严格原文校验
Synthesis 合成工艺、原料清单、催化剂、溶剂、参数、设备、后处理 参数原文校验
Application 应用领域、应用描述 —
Metadata 来源、标题、年份、作者及机构 —

Properties 的 11 个性能类别:PHYSICAL、MECHANICAL、THERMAL、ELECTRICAL、MAGNETIC、OPTICAL、CHEMICAL、SURFACE、PROCESS、ENVIRONMENTAL、FUNCTIONAL。


九、核心技术特点

  1. 摘要锚点引导全文:Phase 1 先从摘要抽出材料名/缩写/性能/工艺关键词作为"锚点",Phase 2 用锚点指导全文各块抽取,确保摘要与正文的一致性。

  2. 严格原文溯源校验:Properties 和 Synthesis.Parameters 的每条数据必须包含 Original text 字段,系统会在全文中做五级匹配验证(精确→归一化→高模糊→低模糊→n-gram),无法溯源的条目会被剔除。Structure 和其他块采用软校验(标注置信度但不丢弃)。

  3. 两阶段并行抽取:Phase 1 串行抽取 Material + Metadata(作为后续块的上下文锚点),Phase 2 用 ThreadPoolExecutor 5 路并行抽取 Structure / Properties / Synthesis / Application / Relationships。

  4. Union-Find 三级实体聚合:精确主键匹配(CAS > Chemical Name > Generic Name)→ 别名交叉引用 → Token Jaccard 模糊匹配(阈值 0.75),解决同一材料在不同文献中命名不一致的问题。

  5. 动态 Few-shot 示例池:静态层(赛题标注样本)+ 动态层(人工校验过的抽取结果),按 11 个性能类别和材料子类型做智能选择,确保示例覆盖度和相关性。

  6. 迭代精炼机制:可选的 verify-patch 轮次,第一轮抽完后将结果和原文关键段落发回大模型自查,增量修补缺漏,带去重防止重复条目。

  7. 实体关系知识图谱:额外抽取 8 种材料间关系(共聚物、共混物、复合材料、改性、变体、前驱体、组分、对比),跨文献聚合后构建节点-边图。


十、常见问题

Q: MinerU 解析报错 "number of pages exceeds limit" 确保已执行第二步(PDF 切片)。pdf_splitter.py 会将超过 180 页的 PDF 切成小块。如果仍有问题,可运行 python src/retry_failed.py 自动处理。

Q: DeepSeek API 返回 429 Too Many Requests 系统已内置 429 退避逻辑。如果频繁出现,降低 --concurrent 参数值,或使用 --user-id 为不同批次设置不同标识符以隔离并发额度。

Q: 抽取结果中某些字段为空 正常现象。并非所有文献都包含全部字段(如部分文献无 Synthesis 或 Application 信息)。schema_validator.py 会在日志中标注缺失的必填字段。

Q: 如何重新抽取某篇文献

# 删除旧结果后重抽
del data\extracted\3.json
python src/run_extract.py --only 3

# 或强制重抽
python src/run_extract.py --only 3 --force

Q: 如何将人工校验过的结果加入 few-shot 池 在 Python 中调用:

from few_shot import add_to_pool
add_to_pool("3", extraction_result)  # stem="3", result 为校验过的 JSON

之后所有抽取都会自动利用这份高质量样本作为 few-shot 示例。


十一、快速复现(完整命令汇总)

# 0. 环境准备
conda create -n minerU_env python=3.11 -y
conda activate minerU_env
pip install streamlit openai requests pypdf

# 1. 填写 config.json(见第四节)

# 2. PDF 统计 + 切片
python src/utils/survey_pdfs.py
python src/pdf_splitter.py
python src/utils/split_all_parallel.py

# 3. MinerU 批量解析
python src/run_parse.py --max-batches-per-key 1    # 测试
python src/run_parse.py                             # 全量

# 4. 失败重试(可选)
python src/retry_failed.py --dry-run                # 先看看
python src/retry_failed.py                          # 执行

# 5. Schema 抽取
python src/run_extract.py --limit 10 --user-id smoke  # 冒烟
python src/run_extract.py --concurrent 10              # 全量

# 6. 跨文献聚合
python src/aggregator.py

# 7. 启动 Web 界面
streamlit run src/app.py --server.port 8501

About

基于 MinerU + DeepSeek 的材料文献智能解析系统:两阶段并行 LLM 抽取、五级原文溯源校验、UnionFind 跨文献实体聚合、FastAPI + Streamlit 可视化检索

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages