写点什么

【LazyLLM × MinerU】你的私人学术特工已上线!PDF 拆解黑科技来了,让 RAG 更懂你的文章!

  • 2025-04-02
    北京
  • 本文字数:6209 字

    阅读完需:约 20 分钟

【LazyLLM × MinerU】你的私人学术特工已上线!PDF拆解黑科技来了,让RAG更懂你的文章!

在大模型与 RAG 技术蓬勃发展的今天,PDF 文档解析已成为构建知识库的核心痛点。由于 PDF 在跨平台兼容性和格式固定性方面的优势,企业通常选择 PDF 作为知识资产的主要存储形式。然而,这些文档中的复杂排版(如多栏布局、嵌套表格、公式与图表混排)往往让传统解析工具难以应对。尤其在金融、法律、科研等专业领域,解析失误可能导致语义断层、数据错位,进而引发 RAG 系统"幻觉式"回答


针对 PDF 格式文档版式多样、解析难度大等难题,上海人工智能实验室推出了一款究极武器——MinerU,各位开发者在以往的开发过程中可能听说过这个名字,但这玩意儿究竟是个啥呢?本文将带你一同探索它的奇妙之处,并带大家使用 LazyLLM,结合 MinerU 打造 PDF 解析与 RAG 应用的无缝链路


当 RAG 遇上 PDF,一场 AI 的"阅读理解噩梦"


"这 PDF 怎么像俄罗斯套娃?"每个 RAG 开发者在深夜都会发出的灵魂拷问...


你永远不知道一份专业 PDF 里藏着多少"反 AI 陷阱":

🔹 金融报告里嵌套的九层表格

🔹 法律文书里突然出现的竖排注释

🔹 科研论文里公式和图表的花式排列组合

🔹 更别提那些扫描件里堪比抽象画的 OCR 结果

......



在 MagicPDF 诞生之前,市面上已经有了很多 PDF 解析工具,比如 pypdf、llama-parse,然而都存在一些能力缺陷。我们调研了市面上 n 种 PDF 解析工具后得出一个结论——某些工具处理复杂文档时,像极了用汤勺拆快递的憨憨!(小编真的笑得很大声哈哈哈哈哈哈哈~)



有人会说了:“解析组件只要基本够用就行,至于这么折腾不?”,你以为解析不准顶多让 AI 犯傻?太天真了!PDF 拆包失误轻则社会性死亡,重则引发行业地震!



这些啼笑皆非的案例背后,暴露出 RAG 对于传统 PDF 解析技术面对复杂文档的困境。接下来为大家介绍破局利器。

技术 CP 出道,当"瑞士军刀"遇上"变形金刚"

MinerU——PDF 解析界的扫地僧


MinerU 是由上海人工智能实验室(上海 AI 实验室)大模型数据基座 OpenDataLab 团队开源的全新的智能数据提取工具(官网:https://github.com/opendatalab/MinerU。MinerU 能够快速识别 PDF 版面元素,将文档转化为清晰、通顺、易读的 Markdown 格式。


核心能力在于:


  • 保留原文档的结构和格式,包括标题、段落、列表等;

  • 自动删除页眉、页脚、脚注、页码等元素;

  • 准确提取图片、表格和公式等多模态内容;

  • 符合人类阅读顺序的排版格式


MinerU 代码公开之后,凭借精准、快速的 SOTA 效果,媲美甚至超过商业软件的性能,获国内外多个技术大 V 点赞,GitHub Star 累计飙升 29K+,登顶 GitHub Python Trending(2024 年 7 月 28 日-29 日),成为 AI 数据清洗中一个亮眼的开源工具。


业界反馈确实不错:



精准解析只是开始,如何把解析能力融入到 RAG 框架,提升知识提取与问答能力,协同解决复杂文件数据抽取与智能问答的瓶颈?


解决方案来了!

LazyLLM——RAG 框架里的乐高大师

LazyLLM 是一个开源大模型应用开发框架,可以让我们像搭建积木一样,快速构建出具有生产力的 AI 大模型应用(官网:https://github.com/LazyAGI/LazyLLM )。LazyLLM 旨在以最简单的方法和最少的代码,快速构建复杂、强大的多 Agent AI 应用原型,即使没有大模型应用开发背景也能轻松上手。


LazyLLM 架构图:


  • 数据流为核心的应用开发范式,集成丰富的标准组件,像搭积木一样开发大模型应用,低至 10 行代码搭建多路召回的 RAG;

  • 同一模块的不同技术选型提供一致的使用体验,用户可以零成本切换基模型、数据库、训推理框架等组件;

  • 复杂应用一键部署:利用轻量网关实现分布式应用一键部署,助力用户产品落地;

  • 多 Agent 编排:封装 FunctionCall、React、ReWOO、Plan-and-Solve 等多种业界主流的 Agent;

  • 跨平台:兼容多个操作系统(如 Windows、MacOS 或 Linux)和多种 IaaS 平台(如裸金属、k8s、slurm、公有云)。


让 RAG 变为阅读理解大师:LazyLLM × MinerU 联合解决方案


如果说 PDF 解析是 RAG 的“眼睛”知识编排则是它的“大脑”。本节将深入解析两大开源利器如何从技术架构协同、应用场景适配、部署流程贯通三个维度,打造“能读会想”的 RAG 系统。通过实测案例,展示从复杂 PDF 文档到精准问答的完整技术链路。


快速部署方案——从安装、模型下载配置到无缝接入 LazyLLM


1.1 安装配置


1.LazyLLM 安装

可参考 LazyLLM 官方项目进行安装,或直接在命令行中运行以下命令:

pip install lazyllm
复制代码

2.MinerU 安装配置及模型选择

参考 MinerU 官方项目进行安装配置

a.magic-pdf 安装

pip install -U "magic-pdf[full]" --extra-index-url https://wheels.myhloli.com -i https://mirrors.aliyun.com/pypi/simple
复制代码


b.模型和配置文件下载

可参考官方文档通过脚本一键下载

pip install modelscopewget  https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/scripts/download_models.py -O download_models.py python download_models.py
复制代码

至此,环境已就绪,所需模型也已下载完毕。接下来,我们将结合 MinerU 与 LazyLLM 搭建完整的 RAG 流程,实现高效精准的知识检索与生成。


1.2 通过自定义 reader 接入 LazyLLM 代码示例


LazyLLM 提供了一套默认的文档解析器,开箱即用,同时也支持用户自定义解析器,用户只需将封装好的可调用对象注册为 Document 类型解析器,即可实现个性化解析方案。


基于此,我们首先利用 MinerU 构建 PDF 解析器,处理其输出的解析结果为 LazyLLM 的标准节点 DocNode。


class MagicPDFReader:    """    PDF 文档解析器,支持文本、图片、表格的解析,返回结构化文档节点。    """    def __call__(self, file: Path, split_documents: Optional[bool] = True, **kwargs) -> List[DocNode]:        ...
def _load_data(self, file: Path, split_documents: Optional[bool] = True) -> List[DocNode]: """节点转化"""
def _parse_pdf_elements(self, pdf_path: Path) -> List[dict]: """MinerU调用"""
复制代码


(喜欢动手的朋友们可以在文档后面找到详细的代码~)


接下来用 LazyLLM 搭建 RAG 流程的 Demo

仅需不到 20 行代码

只要把刚刚定义的 MagicPDFReader

注册为 pdf 文档的解析器

就能轻松搞定!

import lazyllmfrom lazyllm import pipeline, parallel, bind, Document, Retriever, Reranker, SentenceSplitter
prompt = 'You will play the role of an AI Q&A assistant and complete a dialogue task. In this task, you need to provide your answer based on the given context and question.'
documents = Document(dataset_path="rag_master", embed=OnlineEmbeddingModule(), manager=False)documents.create_node_group(name="sentences", transform=SentenceSplitter, chunk_size=1024, chunk_overlap=100)documents.add_reader("**/*.pdf", MagicPDFReader)
with pipeline() as ppl: with parallel().sum as ppl.prl: prl.retriever1 = Retriever(documents, group_name="sentences", similarity="cosine", topk=3) prl.retriever2 = Retriever(documents, "CoarseChunk", "bm25_chinese", 0.003, topk=3) ppl.reranker = Reranker("ModuleReranker", model=OnlineEmbeddingModule(type="rerank"), topk=1, output_format='content', join=True) | bind(query=ppl.input) ppl.formatter = (lambda nodes, query: dict(context_str=nodes, query=query)) | bind(query=ppl.input) ppl.llm = lazyllm.OnlineChatModule(stream=False).prompt(lazyllm.ChatPrompter(prompt, extra_keys=["context_str"]))
if __name__ == "__main__": query = "your query" answer = ppl(query)
复制代码


以下为 rag 框架的流程图,接收到用户 query 后,通过多路召回(retriever)得到节点,然后通过 rerank 重排序到输入大模型得到最终回答。每个 retriever 可以绑定多个 document,自定义的解析器仅需通过 documents.add_reader("**/*.pdf", MagicPDFReader)注册到流程中。


⚒️实验室暴击现场⚒️


当 MinerU 遇上 PyPDF,降维打击太残忍了!


有了以上启动代码,我们直接运行并测试一下,看看 MagicPDF 到底给我们的 RAG 应用带来了什么改变。对比效果如下:


MinerU 解析结果:



PyPDF 解析结果:



结果不出所料,MagicPDF 直接把 PyPDF 按在地上摩擦...通过更多的测试,我们也总结了二者在 PDF 文档解析中备受关注的多个角度对比结论:



单独的文档解析环节比拼,MagicPDF 胜出——1:0。


问答效果


我们为本次评测选择了两种较为复杂的场景,分别是基于复杂表格问答和基于复杂问题的问答。


案例 1:基于复杂表格提问

"3 月 15 日政府发行国债的净融资量是多少?"


  • MinerU:提取表格结构 → 表头文字精准对应 →大模型秒答"2595.70 亿元"

  • PyPDF 菜鸟:把表格拆成散装文字 → 对不上 → 回答"融资量为 2220.7.00 亿元“(幻觉模式)


这一案例较为考验大模型对于表格结构的理解能力,但由于表格解析成先前那个样子,复杂表格这一环节 PyPDF 理所当然的指望不上了... MagicPDF 胜出——2:0。


案例 2:基于复杂结构的提问"关于珀莱雅的投资建议?"

  • MinerU:跨页拼接文本+分离穿插表格 → 语义完整性 MAX → 生成专业建议

  • PyPDF

    丢失关键段落+表格文字粘连 → 大模型东拼西凑 → 回答当场翻车



3:0 啊...除了“残忍”二字,已经找不到别的词能够形容这场 PK 了。同时,能够这么快完成效果验证,除了小编的聪明才智(不是)MagicPDF 的强力支持,还有懒懒猫(LazyLLM 中文名)短短几行代码就能把这个复杂应用构建出来,简直是妙上加喵,喵喵妙~


进阶优化方案——充分利用 MinerU 输出的多元信息,让 RAG 更懂你的文章


除了以上最基本的使用,我们还带来了一些使用技巧,助力开发者更好的玩转 MagicPDF。


📌坐标追踪模式:给每行文字装上 GPS


在某些讲求严谨性的专业场景中,RAG 系统不仅需要 "知道答案",更要 "解释答案的来龙去脉"。这意味着 AI 不仅要能检索到正确的答案,还要能够提供强有力的证据链,指向原文中的具体位置。例如,在法律、财务、医学等领域,AI 需要做到 "可溯源",让用户不仅能获取答案,还能直接看到它是如何得出的。


想象一个法律检索场景,律师问 AI 某个合同条款是否允许提前终止,RAG 系统不仅要回答 "允许",还需要指着合同第 8 页第 3 段第 5 行说:"就是这里!" 这极大增强了 AI 生成内容的可信度,使其更加符合专业场景的严谨性和透明性要求。


对此,MinerU 已经支持行级别的位置信息,但当前版本默认不输出这些细节信息。不过,这并不妨碍我们自己挖掘和利用它!通过重写部分函数,我们可以深入解析 MinerU 的底层数据结构,精确提取 block 级别和 line 级别的位置信息,并以结构化的方式返回。这一能力将极大提升 RAG 系统的可解释性,使其能够支持精准文本定位、高亮展示、证据链构建、可视化分析等高级应用。


# add patchs to magic-pdffrom magic_pdf.dict2md import ocr_mkcontent
def para_to_standard_format_v2(para_block, img_buket_path, page_idx, drop_reason=None): """修改输出bbox信息"""
ocr_mkcontent.para_to_standard_format_v2 = para_to_standard_format_v2
复制代码


【部分修改】:



接下来介绍一种简单利用坐标信息的方式,在 RAG pipeline 中插入一个模块实现:根据目标文档的召回块画出 box 并保存,待问答后查看,就可以精准定位到你的问答依据!


def draw_pdf_bbox(nodes, query, **kwargs):    """在召回PDF文档中绘制box并标注query"""    for node in nodes:        bbox_list = node.metadata['bbox']        output_path = os.path.join(get_pdf_output_path(), f"query[{query}] -- {node.metadata['file_name']}")        draw_bboxes_on_pdf(node.metadata['file_path'], bbox_list, output_path, query)    return "\n".join([node.get_content() for node in nodes])
def draw_bboxes_on_pdf(input_pdf_path, bbox_list, output_pdf_path, query): # 打开PDF文档 pdf_document = fitz.open(input_pdf_path)
# 遍历每一页 for page_num in range(len(pdf_document)): page = pdf_document.load_page(page_num)
# 遍历bbox列表 for bbox in bbox_list: if bbox['page'] == page_num: # 检查bbox是否属于当前页 rect = fitz.Rect(*bbox['bbox']) # 创建矩形框 page.draw_rect(rect, color=(1, 0, 0), width=2) # 绘制红色矩形框
# 保存带有bbox的PDF文档 pdf_document.save(output_pdf_path) pdf_document.close()
复制代码

接下来将其插入到 pipeline 流程中:



📌定制精细化的本文分块策略:告别"切香肠式"文本处理


MinerU 能够输出丰富的元信息,这为 RAG 应用提供了极大的灵活性。传统的文本切分方法通常采用固定长度或简单的句子切割,这种方式容易破坏语义完整性,导致信息割裂,影响 RAG 问答的内容质量。而 MinerU 的元信息可以用于构建更加智能的 内容结构化分块策略,确保每个分块都保持完整的语义单元,提升检索与生成的准确性。


在 MinerU 中,我们可以自定义更加灵活的分块方式,以适应不同的业务场景。例如,项目中提供了一种基于章节标题进行分块的通用算法,在实际应用中,可以结合业务需求进一步优化分块策略,确保信息的完整性。例如:


1. 招股书处理

传统切分:固定字数切分,可能导致"业务概览"和"财务数据"混杂,信息断裂。

优化方案:按 “业务概览 → 财务数据 → 风险因素” 进行模块化分块,保证业务逻辑清晰,不破坏上下文连贯性。


2. 学术论文分析

传统切分:可能导致假设、实验和数据分析混在不同块中,使得推理链断裂。

优化方案:按照 “假设 → 实验 → 数据 → 结论” 进行切分,确保逻辑链条完整,提高生成答案的可靠性。


3. 医疗报告解析

传统切分:可能会将影像描述与诊断意见分离,使得问答系统难以精准匹配。

优化方案:按 “检查项目 → 影像描述 → 诊断意见” 切割或组合,确保影像结论与描述保持一致,提高问答准确度。


假设有一份 CT 影像报告,内容如下:

患者姓名:张三  检查项目:胸部 CT  影像描述:双肺下叶可见多发小结节,边界清晰,未见明显钙化。  诊断意见:考虑良性病变,建议 3 个月后复查。
复制代码


1. 传统固定长度切分(错误示例)

分块 1:患者姓名:张三 检查项目:胸部 CT 影像描述:双肺下叶可见多发小结节分块 2:边界清晰,未见明显钙化。 诊断意见:考虑良性病变,建议 3 个月后复查。
复制代码


问题:影像描述和诊断意见被拆开,导致问答系统在生成答案时可能无法准确关联病变特征和医生建议。


2. Mineru 元信息辅助的结构化分块(优化示例)

患者姓名:张三  检查项目:胸部 CT  影像描述:双肺下叶可见多发小结节,边界清晰,未见明显钙化。  诊断意见:考虑良性病变,建议 3 个月后复查。
复制代码


优化点:每个块都是完整的语义单元,不会因固定长度切割导致信息断裂。


在 LazyLLM 搭建的 rag 框架中自定义切分算法只需继承 NodeTransform 并且将该类注册到 document 的分组中:

class MagicPDFTransform(NodeTransform):    def __init__(self, **kwargs):        super().__init__()
def transform(self, document: DocNode, **kwargs) -> List[Union[str, DocNode]]: """自定义切分算法"""
# 在你的rag代码中:documents.create_node_group(name="magic-pdf", transform=MagicPDFTransform)
复制代码


总结


以上就是基于 LazyLLM 融合 MinerU 实现 PDF 解析与 RAG 的应用与进阶,让 PDF 解析从 “机械拆分” 迈向 “智能重构”,更多高级玩法有待探索。

(以上代码请参考项目 👉https://github.com/jisyST/LazyRAG-Mineru#


更多信息请移步“LazyLLM”gzh!

发布于: 2025-04-02阅读数: 5
用户头像

用AI大模型,找商汤大装置。 2023-04-04 加入

还未添加个人简介

评论

发布
暂无评论
【LazyLLM × MinerU】你的私人学术特工已上线!PDF拆解黑科技来了,让RAG更懂你的文章!_AI_商汤万象开发者_InfoQ写作社区