摘要

本系列博客用于介绍正在搭建的一个面向学术场景的文献解析平台,我们将实现包括pdf文献解析,文献搜索,文献追踪,文献深度,深度理解问答在内的11+个功能模块。本篇博客是用于介绍本平台的第一个功能模块PDF文献解析功能的实现。该模块在实现过程中经历多次技术尝试,包括使用了pypdf包,maker开源库等,最后效果均不理想,最后尝试了一个Mineru的开源库进行实现。

一、PDF的原理

PDF实际上本质并非是文档,word、网页的排版都是流式排版。文字会自动换行适应屏幕,文档里存放的是段落标题列表等等语义结构,但是PDF是固定布局,每一页都是写死的,不会自适应电脑,同时文档里几乎不存在语义,只存在什么地方画什么矢量图,也就是说PDF的本质实际上存储的并不是文字而是一条一条的绘画指令。没有任何的表格、段落、标题,所有的显示的实际上都是靠坐标进行绘画的一张画布,因此解析PDF实际上就是解析这一系列的绘图指令。它具备矢量特性,在放大后永远清晰不失真。

总结来说PDF实际上是画出来的一个页面,而不是写出来的文档,这也是PDF难以解析的本质所在

二、PDF解析功能的痛点

1.开始时我们以为PDF解析仅仅是把文字读取出来,但是实际做下来之后我们发现,PDF的解析是一个相当困难的功能,要进行学术PDF的解析难点远远不只是文本的智能提取:

具体包括但不限于:

1.同一页中存在双栏排版,简单的PDF解析容易顺序混乱,甚至是出现前言不搭后语

2.图片与正文交错:在学术文献中有大量的图片,而PDF中的图片解析并且解析后在正确位置显示也是一件相当困难的事

3.表格不是规则的文本:正如我们之前在PDF原理所说,PDF实际上是画出来的一个画布,没有语义结构,因此解析报表格也是困难所在

4.公式的识别与渲染:我们即使相当调用视觉模型或其他的一些PDF解析进行文字提取,想以此来提取PDF中的文字,但也会出现学术文献场景下的数学公式的正确显示问题,往往提取出来的公式显示的就是一团latex代码,并非我们人眼识别的数学公式

5.章节层级的恢复问题:这也是因为PDF实际上不具备语义结构,因此原本的标题段落在解析之后,如何正确识别出来也是一大难点所在

6.阅读顺序必须正确:不会出现段落间的文本顺序错误

三、Mineru

3.1Mineru是什么?

MinerU 是上海人工智能实验室 OpenDataLab 团队研发的开源智能数据提取工具,核心聚焦于复杂 PDF 文档的高效解析与内容抽取工作。这款工具能够把搭载图片、公式、表格等多元元素的多模态 PDF 文件,转换为更易开展数据分析工作的 Markdown 格式,同时还支持从网页、电子书等载体中提取文本内容。该工具配备了高精度的 PDF 模型解析工具链,可适配多种输入模型,具备自动识别文档乱码的能力,在转换环节能完整留存原文档的结构框架,还可将公式精准转化为 LaTex 格式。MinerU 的应用场景广泛,覆盖学术科研、财务统计、法律文书等诸多领域,既支持 CPU 运行也兼容 GPU 加速,适配 Windows、Linux、Mac 三大主流操作系统,整体运行性能表现出众。

总体来说Mineru=视觉语言模型 + 专业 PDF 理解模型,huggingface上已开源他的参数权重

这是其官网的地址:MinerU-免费全能的文档解析神器

3.2为何选择Mineru

我们最开始也尝试过其他的PDF接续工具+大模型的模式来进行解析,但是发现最后的效果都不是很好,存在大量的乱码,表格位置混乱,图片不能显示,文本丢失等大量的问题。

经过我们团队队员的调研以及查询PDF解析的主流技术,我们发现,Mineru非常适配于我们的学术平台:

1.Mineru对学术PDF的适配能力强

2.不仅仅只是提取文本,还可以处理图片、表格、公式理解等复杂的元素

3.输出格式有较多格式,包括markdown、JSON、中间结果文件

4.开源,包括其相关模型的权重均开源,适合我们用于平台的解析层实现

3.3Mineru功能

1.复杂PDF文档高效解析与内容抽取

2.多模态PDF(图片、公式、表格)可转markdown

3.网页、电子书等载体文本提取

4.高解读PDF解析,适配多种输入模型

5.自动识别文档乱码

6.完整保留源文档结构框架

7.公式精准转换为latex格式

8.支持CPU运行与GPU加速

四、PDF解析模块的最终实现过程

我们的项目实现过程中使用的是AI+人工修改的方式,让根据我们的需求搭建出我们需要的功能模块,然后再对其中的问题进行再修改,使用的模型是chatgpt-5.3-codex,并且不再记录我们之前的失败技术,仅记录最后使用Mineru成功的过程

4.1给AI的prompt

你是一位后端专家,现在我需要搭建一个学术阅读平台,目前的进度是需要完成我们架构中的解析层,请你帮我完成这个功能模块的实现,实现过程请你采用软件工程的实现范式,模块化编程,记录你写好的api接口(包括如何调用,参数,接口作用)以方便我们进行人工代码审核与修改及后的功能与之后的代码实现。同时实现功能过程中不要使用其他PDF解析技术,指定你使用Mineru这个开源库来进行实现,Mineru需要使用的模型的相关权重已在huggingface上进开源,你可以直接下载。https://github.com/opendat该网址是Mineru在github上的地址。同时请你记住,在开发过程中对于不知道的问题请不要擅自修改,对于有疑问的地方请你直接向我提问,不得凭空捏造,如出现技术困难无法实现之处,请你不得擅自修改技术选型,开发语言python,现在请你开始完成

4.2ai开发工程中的问题

约20min后ai帮助我们完成了第一版的实现,但是经过我的测试,第一版功能并没有实现,存在大量的报错,且无法实现解析功能,如下图所示:

之后我们详细追踪了报错日志,发现是问题在于该功能有复杂的依赖链,ai有大量的依赖库未安装,包括如下的依赖:

fastapi==0.116.1
uvicorn==0.35.0
python-multipart==0.0.20
httpx==0.28.1
mineru==3.0.9
--extra-index-url https://download.pytorch.org/whl/cpu
torch==2.5.1+cpu
torchvision==0.20.1+cpu
transformers==4.52.4
tokenizers==0.21.4
huggingface-hub==0.34.4
numpy==2.2.6
opencv-python==4.13.0.92
shapely==2.1.2
albumentations==2.0.8
omegaconf==2.3.0
ftfy==6.3.1
pyclipper==1.4.0

这些依赖是github上给出,以及部分我们环境所需的依赖,使用pip install +依赖项 完成所有的依赖安装后,第一版功能成功跑通

4.3效果展示:

此时我们的文献可以看到几乎已经正确显示,但是扔存在如顶部所示的部分letex公式显示问题。经过我的查询,发现可以使用前端渲染来解决这个问题,因此我们又重新向ai说了:当前功能存在letex公式无法正确渲染问题,问题出在前段渲染,请你考虑使用渲染清除这些噪声点。并经过几轮的反复调试,最终消除了噪声点,对于我们传入的文献几乎都可以完美的显示出来

五.PDF解析模块实现的原理与数据流

5.1功能涉及技术

1.后端架构本次使用FastAPI,用于提供上传,任务状态,结果获取,资源访问接口

2.任务化解析:上传后生成一个task_id,后台线程执行Mineru,状态写入task.json

3.MinerU集成:后端会执行Mineru。把输入出写进任务目录并回收md/json

4.资源可视化 :静态资源路由 + Markdown 图片链接重写提供 /api/v1/tasks/{task_id}/assets/... 并把 Markdown 里的相对路径改为可访问 URL

5.2模块职责划分

1.MinerU(解析引擎)负责
-文档理解流水线:版面分析、OCR、公式识别、表格识别、阅读顺序重建
-生成解析产物:Markdown、JSON、图片资源与中间文件
2.我们的后端(FastAPI)负责
- 提供上传接口与任务接口:创建任务、查询状态、获取结果
- 以 CLI 方式调用 MinerU,控制输入/输出目录
- 统一整理结果文件(写 result.md/result.json )
- 提供图片等资源的可访问接口,并对 Markdown 图片链接做重写
3.我们的前端负责
- 上传 PDF、轮询任务状态
- Markdown 渲染(marked)
- 公式渲染(MathJax)与少量噪声清洗
- 展示图片/表格(通过后端 assets 路由加载)

5.3整体流程(数据流)

用户(浏览器)→ 我们的前端页面:选择 PDF,点击上传
前端 → 我们的后端(FastAPI):上传 PDF 文件(multipart/form-data)
后端 → 文件系统:保存 PDF 到任务目录 data/parsed/<task_id>/xxx.pdf ,写入 task.json 后端 → 后台线程:启动解析线程(异步执行)

后台线程 → MinerU(CLI):传入输入 PDF 路径、输出目录,执行解析命令
MinerU → 文件系统:在输出目录写 Markdown/JSON/图片等产物
后台线程 → 文件系统:把“最终结果”落成 result.md/result.json ,并更新 task.json 为 succeeded/failed
前端 ⇄ 后端:轮询任务状态;成功后请求结果与资源
后端 → 前端:返回 Markdown/JSON(结果 API)+ 图片资源(assets API)
前端:把 Markdown 渲染成 HTML,MathJax 渲染公式,图片通过 assets URL 加载

上传阶段实现方案

前端通过POST请求发送PDF文件到/api/v1/tasks接口,使用multipart/form-data格式上传,字段名为file。后端接收文件后生成唯一task_id,创建任务目录结构。

data/parsed/<task_id>/
├── <filename>.pdf
└── task.json
 

后端立即返回JSON响应包含任务基础信息:

{
  "task_id": "uuidv4",
  "status": "pending",
  "output_dir": "/data/parsed/<task_id>"
}
 

解析阶段技术细节

后台线程通过TaskService._run_task启动处理流程,更新任务状态为running。调用MinerU解析时使用预定义命令模板:

MINERU_COMMAND_TEMPLATE = (
    'py -3.10 -c "from mineru.cli.client import main; main()" '
    '-p "{input_path}" -o "{output_dir}" -b pipeline'
)
 

执行命令前需验证Python环境与MinerU模块是否可用。输出目录设置为data/parsed/<task_id>/mineru_output保持隔离

结果标准化处理

解析完成后,后端从MinerU输出目录提取有效结果进行标准化:

  1. 合并多个.md文件为单个result.md
  2. 转换中间JSON为统一结构的result.json
  3. 移动图片资源到标准位置
  4. 执行Markdown链接重写

前端交互流程

轮询接口返回完整任务状态对象

{
  "status": "succeeded",
  "created_at": "ISO8601",
  "updated_at": "ISO8601",
  "error": null
}
 

总结来说就是:“前端上传 PDF 到后端 → 后端创建 task_id 并保存文件 → 后台线程调用 MinerU CLI 解析 → MinerU 在任务目录产出 Markdown/JSON/图片 → 后端统一整理成 result.md/result.json 并更新任务状态 → 前端轮询状态成功后拉取结果 → 前端渲染 Markdown+MathJax,图片通过后端 assets 接口按需加载。”

六、开发总结

最后的感受是PDF解析功能是一个相当复杂的功能,如果不依赖开源库,单单以我们学生的理解以及编码能力,是无法完成如此复杂功能的实现的,该功能的实现更多的依赖了开源库与chatgpt的编程能力,帮助我们省下了很多的编码时间

现在的编码确实已经进入了ai'编码时代,但是根据我在开发过程中的感受来看,ai现在编码还是倾向于需要人类提出需求,设计好架构,功能耦合,ai写出的功能能在第一次完成百分之80+正确,但是最后百分之20的调试往往需要更多的时间精力以及人工干涉排错等等,需要对技术选型需要足够的了解,当出现问题时才知道如何解决,如何采取其他技术去解决,如果仅交由ai全处理,往往最后的功能会偏离预想

最后经过检查,ai写的接口文档全部正确,可以供我们进行后续功能的拓展与开发,之后我们将基于Langgraph框架,来实现多agent编排的其余功能搭建与实现

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐