【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 lazyllm
from 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-pdf
from 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!

<think>好的,用户需要查找一篇关于通过图基重排序改进RAG的论文。首先,我需要确认用户的需求是什么。他们可能是在研究RAG(检索增强生成)的优化方法,特别是如何利用图结构来进行重排序,提升检索效果。用户提到“图基重排序”,这可能指的是利用图算法或图神经网络对检索到的文档进行重新排序,以提高生成质量。 接下来,我应该回忆一下相关的文献。RAG本身结合了检索和生成,但传统方法可能存在检索结果不够精准的问题,重排序技术可以优化这一点。图结构在信息检索中的应用,比如构建文档之间的关系图,或者利用图嵌入来捕捉文档间的语义关联,可能是一个研究方向。 然后,我需要检查提供的引用内容。引用[1]提到高级RAG技术,包括模块化框架,但没有直接提到图基重排序。引用[2]讨论了RAG的发展和应用场景,但同样没有具体提到图方法。引用[3]是一个原型应用的链接,可能不涉及论文内容。因此,提供的引用中可能没有直接相关的论文,需要引导用户去外部数据库查找。 不过,用户可能希望我根据现有知识推荐可能的论文方向或方法。例如,图神经网络(GNN)在文档重排序中的应用,或者知识图谱增强的RAG系统。此外,可以建议用户搜索关键词如“RAG graph-based reranking”、“GNN for document reranking”或“knowledge graph RAG”来查找相关论文。 另外,考虑到RAG的优化通常涉及检索器和生成器的协同改进,图基方法可能在检索阶段构建文档间的关系,或者在重排序阶段利用这些关系调整顺序。例如,使用PageRank算法或社区检测来评估文档的重要性,进而重新排序。这样的方法可能在信息检索领域有相关研究,用户可能需要查阅最近的顶会论文,如ACL、EMNLP、SIGIR等。 最后,确保回答符合用户的要求:结构清晰、分步解决问题,并引用提供的资料。由于提供的引用中没有直接相关的论文,需要如实告知,并给出建议的搜索方向和关键词,帮助用户自行查找。同时生成相关问题,如优化RAG的其他技术、图基方法的应用场景等。</think>根据您对图基重排序改进RAG的论文需求,结合当前RAG技术发展,以下是分步解答: 1. **研究领域定位** 图基重排序属于RAG技术中检索优化模块的改进方向,需聚焦"检索增强生成"与"图神经网络"交叉领域。引用[1]提到的模块化RAG框架中,重排序模块可作为独立算子存在,这为图算法的集成提供了理论支持[^1]。 2. **推荐搜索策略** - 关键词组合:`"RAG" + ("graph neural network" | "knowledge graph") + reranking` - 会议筛选:优先查看ACL/EMNLP/NAACL/SIGIR近三年论文 - 论文预印平台:arXiv.org使用筛选条件`cs.CL + cs.IR` 3. **相关技术线索** 虽然现有引用未直接提及图基重排序论文,但引用[2]指出模块化RAG支持路由、调度和融合机制的创新设计[^2],这与图结构处理节点关系的能力高度契合。例如: - 使用图注意力机制建模文档间语义关联 - 基于社区发现算法优化检索结果聚类 $$ \text{NodeScore}(d_i) = \sum_{d_j \in N(d_i)} \alpha_{ij}Wv_j $$ 其中$d_i$为文档节点,$N(d_i)$是其邻居节点集 4. **实验性验证方法** 引用[3]提供的Mememo平台支持快速原型开发[^3],可尝试: ```python # 伪代码示例:图基重排序实现 def graph_reranking(docs): graph = build_knowledge_graph(docs) scores = page_rank(graph) return sort_by_score(docs, scores) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值