RAG 准确率上不去?先查文档解析这一关

0 阅读7分钟

文章定位:深度长文,面向有 RAG 系统经验、想提升文档处理质量的工程师关键词:MinerU、文档解析、RAG、LangChain、VLM、PDF 处理


一、调了半年参数,问题出在最上游

搭了半年 RAG 系统,检索准确率一直上不去。调了 embedding 模型,试了各种 chunking 策略,改了 reranker……最后发现问题出在最上游:文档解析根本就是错的

把一篇双栏学术论文喂给 PyPDFLoader,输出是这样的:

Introduction 1. Methodology The proposed framework utilizes...
Results Our approach achieves 94.2% accuracy... Discussion

左栏和右栏的文字混在一起,段落顺序乱了,表格变成一堆数字碎片。向量化这种内容,检索出来的东西对 LLM 来说也是废的。

这不是孤例。财务报告、技术手册、扫描件……这些场景里,传统工具的输出质量都很不稳定。

二、传统工具的根本问题:提文字,但不懂结构

传统 PDF 解析工具(PyMuPDF、PDFMiner、pdfplumber)的工作方式本质上是提取文字流,再按坐标拼接。文字是对的,但结构关系丢了。

这类工具无法回答这些问题:

  • 这段文字是正文还是页脚?
  • 这些数字是表格里的单元格还是正文里的数据?
  • 这个符号是普通文本还是公式的一部分?
  • 这一页是双栏还是单栏?

对 LLM 来说,结构信息和文字内容同样重要。一个完整的表格和一堆散乱的数字字符,语义完全不同。这个问题靠调 chunking 策略解决不了——垃圾进,垃圾出。

三、MinerU:用视觉模型"读懂"文档

MinerU 是上海人工智能实验室 OpenDataLab 团队开发的开源文档解析工具,诞生于 InternLM 大模型的预训练数据构建过程中。GitHub:github.com/opendatalab/MinerU,当前 60k+ star。

和传统工具不同,MinerU 的核心解析后端使用视觉语言模型,直接在视觉层面理解文档——哪里是标题,哪里是表格,哪里是公式,哪个区域是图注。这和人类阅读文档的方式更接近。

两种解析模式

pipeline 模式传统多模型流水线,速度快。适合结构相对简单的文档、需要批量处理、对速度敏感的场景。

**vlm 模式(推荐)**使用 MinerU2.5 视觉语言模型(1.2B 参数),专为文档解析场景训练。适合学术论文、财报、复杂混排文档。在 OmniDocBench 基准上,1.2B 的 MinerU2.5 超过了多个 72B 级别的通用大模型——因为它只需要理解文档版面,不需要通用推理能力。

输出格式

内容类型

输出

普通文本

Markdown(保留标题层级、阅读顺序)

表格

HTML(结构完整,支持跨页合并)

数学公式

LaTeX(行内 + 块级)

图片

提取文件 + 文字描述

扫描件 / 图片 PDF

自动 OCR,109 种语言

四、横向评测:6 款主流工具,谁在 RAG 场景真正能打

知道了 MinerU 是什么,来看它在实际评测中和其他工具差距有多大。

RAG 场景里文档解析的四个核心指标:阅读顺序(双栏有没有乱)、表格还原(结构能不能保住)、公式识别(LaTeX 还原准不准)、扫描件 OCR(图片 PDF 能不能识别)。

PyMuPDF / pdfplumber / PDFMiner:传统文字流提取,速度极快,无需模型,适合文字简单的原生 PDF。

Unstructured:开源文档处理框架,支持多种格式,规则 + 模型混合方案。

LlamaParse:LlamaIndex 出品的云端解析服务,针对 RAG 优化,收费。

Marker:基于深度学习的开源 PDF→Markdown 工具,本地运行。

Docling:IBM 开源,支持 PDF、DOCX、PPTX 多格式,专注结构理解。

MinerU:上海 AI Lab,vlm 模式 1.2B 专项训练模型,开源 + 免费 API。

评测数据(OmniDocBench,CVPR 2025)

工具

综合准确率

文字提取

公式(LaTeX)

表格(HTML)

阅读顺序

MinerU 2.5

90.7%

93.2%

87.4%

85.6%

94.1%

LlamaParse

~76%

82%

65%

74%

78%

PyMuPDF(原生 PDF)

~82%*

91%

60%

67%

Unstructured(API)

~68%

75%

22%

61%

70%

Marker

~74%

80%

71%

68%

77%

Docling

~72%

79%

58%

72%

75%

\PyMuPDF 在纯文字原生 PDF 上文字提取很强,但不处理公式,遇到复杂文档表格和阅读顺序都掉得厉害。

各工具的真实软肋

PyMuPDF / pdfplumber:遇到双栏就乱,表格变成数字碎片,公式完全不处理。简单原生 PDF 够用,稍微复杂一点就不行。

Unstructured:格式支持广,但准确率偏低,公式识别只有 22%。

LlamaParse:准确率不错,接入简单,但收费,闭源云服务,数据要出去。

Marker:开源可本地跑,公式比传统工具强,但跨页内容容易断。

Docling:多格式支持是亮点,但公式(58%)和复杂混排的阅读顺序弱于 MinerU。

MinerU:四个维度全面领先。主要劣势是首次加载慢(模型加载约 30-60 秒)。

怎么选

  • 简单报告(原生 PDF,无公式表格) → PyMuPDF 够用,速度快
  • 需要本地运行 + 不想付费 → MinerU 或 Marker
  • 多格式(DOCX、PPTX、PDF 混合) → Docling 或 Unstructured
  • 学术论文、财报、技术手册 → MinerU,目前没有更好的开源选项
  • 不想自己搭、愿意付费 → LlamaParse

五、解析质量怎么直接影响检索结果

横评数据说明了准确率,但准确率高一点对 RAG 到底有多大实际影响?拿同一份 arXiv 论文对比。

MinerU 输出的 Markdown 有完整标题层级(######),用 MarkdownHeaderTextSplitter 按标题切块,每块对应一个完整的逻辑章节。

PyPDFLoader 的输出只能按字符数切:

块1(500字符):
"Abstract The proposed method...
1 Introduction In this paper we..."
(摘要和引言混在一块)

块2(500字符):
"ables when ε is small. Table 1
shows results on MNIST..."
(一个单词被切断,表格只有标题)

MinerU + MarkdownHeaderSplitter:

块1(section="Abstract"):完整摘要段落
块2(section="1 Introduction"):完整引言段落
块3(section="4 Results"):完整结果段落(含 HTML 格式表格)

检索"实验结果准确率是多少?":

  • PyPDFLoader:检索到含数字的片段,但上下文破碎,LLM 无法判断这个数字属于哪个实验
  • MinerU:检索到完整 Results 章节,表格结构完整,LLM 能直接引用

表格的差距更明显——PyPDFLoader 输出散乱数字字符串,向量化后几乎无法正确检索;MinerU 输出 HTML,LLM 能正确理解每行每列的语义。

六、5 分钟接入

MinerU 提供云端 API,不需要本地部署或下载模型。

Token 申请(免费)

mineru.net/apiManage/token 注册后直接获取,没有审核等待。单文件上限 200MB / 200 页,批量最多 200 个文件/次。

export MINERU_TOKEN="your-token-here"

安装

pip install langchain-mineru langchain-openai langchain-community chromadb

验证:

python -c "from langchain_mineru import MinerULoader; print('langchain-mineru 安装正常')"

完整代码

import os
from langchain_mineru import MinerULoader
from langchain.text_splitter import MarkdownHeaderTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain.chains import RetrievalQA
from langchain.schema import Document

# Step 1: 解析文档
loader = MinerULoader(source="paper.pdf", mode="precision")
docs = loader.load()

# Step 2: 按标题层级分块
splitter = MarkdownHeaderTextSplitter(
    headers_to_split_on=[
        ("#",   "section"),
        ("##",  "subsection"),
        ("###", "subsubsection"),
    ]
)

chunks = []
for doc in docs:
    for s in splitter.split_text(doc.page_content):
        chunks.append(Document(
            page_content=s.page_content,
            metadata={**doc.metadata, **s.metadata}
        ))

# Step 3: 向量化
vectorstore = Chroma.from_documents(
    documents=chunks,
    embedding=OpenAIEmbeddings(),
    persist_directory="./chroma_db"
)

# Step 4: 问答
qa_chain = RetrievalQA.from_chain_type(
    llm=ChatOpenAI(model="gpt-4o", temperature=0),
    retriever=vectorstore.as_retriever(
        search_type="mmr",
        search_kwargs={"k": 6, "fetch_k": 20}
    ),
    return_source_documents=True
)

result = qa_chain({"query": "这篇论文的主要贡献是什么?"})
print(result["result"])

七、生态现状:不只是一个 Python 包

MinerU 的接入方式比很多人想象的要多。

直接用,不写代码

  • 在线 Demo:mineru.net/OpenSourceTools/Extractor
  • 桌面客户端:mineru.net/client — Windows / macOS / Linux,免费
  • Hugging Face:huggingface.co/spaces/opendatalab/MinerU

SDK(多语言)

pip install mineru-open-sdk                                        # Python
go get github.com/opendatalab/MinerU-Ecosystem/sdk/go@latest      # Go
npm install mineru-open-sdk                                        # TypeScript / Node.js

AI 框架集成

  • LangChainpip install langchain-mineru
  • LlamaIndexpip install llama-index-readers-mineru
  • MCP Servernpm install mineru-mcp,Claude / Cursor 里直接调用
  • n8nnpm install n8n-nodes-mineru

低代码平台

Dify、Coze、FastGPT、RagFlow、Cherry Studio 都有官方插件,不需要自己写对接代码。详见:github.com/opendatalab/MinerU-Ecosystem


八、小结

文档解析是 RAG 的地基。地基不稳,调什么参数都是治标。

传统工具解决的是"提文字",MinerU 解决的是"理解文档结构"——两个层次不同的问题。对需要处理复杂文档的场景,在解析这一步换成 MinerU,后续分块和检索准确率都会有明显改善,其他代码不用动。

Token 免费申请:mineru.net/apiManage/tokenGitHub:github.com/opendatalab/MinerU


本文基于 MinerU v3.x、langchain-mineru 最新版本,代码已验证可运行。OmniDocBench 评测数据来源:github.com/opendatalab/OmniDocBench(CVPR 2025)。