高级RAG 02揭秘PDF解析
包含关键点、图表和代码
对于RAG,从文档中提取信息是一个不可避免的场景。确保从源文件中有效提取内容对于提高最终输出的质量至关重要。
这一过程的重要性不容小觑。在实施RAG时,解析过程中信息提取不充分可能导致对PDF文件所含信息的理解和利用受限。
RAG中解析过程的位置如图1所示:
在实际工作中,非结构化数据远比结构化数据丰富。如果这些海量数据无法被解析,其巨大的价值将无法实现。
在非结构化数据中,PDF文档占据了大部分。有效处理PDF文档也能极大地辅助管理其他类型的非结构化文档。
本文主要介绍解析PDF文件的方法。它提供了算法和建议,以有效解析PDF文档并尽可能提取有用信息。
PDF解析的挑战
PDF文档代表了非结构化文档的典型,然而,从PDF文档中提取信息是一个具有挑战性的过程。
与其说PDF是一种数据格式,更准确地描述它是一系列打印指令的集合。一个PDF文件由一系列指令组成,这些指令指导PDF阅读器或打印机在屏幕或纸张上的何处以及如何显示符号。这与HTML和docx等文件格式形成对比,后者使用诸如<p>、<w:p>、<table>和<w:tbl>等标签来组织不同的逻辑结构,如图2所示:

解析PDF文档的挑战在于准确提取整个页面的布局,并将内容(包括表格、标题、段落和图像)转换为文档的文本表示。这一过程涉及处理文本提取的不准确性、图像识别以及表格中行列关系的混淆。
如何解析PDF文档
通常,解析PDF有三种方法:
- 基于规则的方法:根据文档的组织特征确定每个部分的样式和内容。然而,这种方法的通用性不强,因为PDF的类型和布局繁多,无法用预定义的规则覆盖所有情况。
- 基于深度学习模型的方法:如结合对象检测和OCR模型的流行解决方案。
- 基于多模态大型模型解析复杂结构或提取PDF中的关键信息。
基于规则的方法
最具代表性的工具之一是 pypdf ,这是一个广泛使用的基于规则的解析器。它是 LangChain 和 LlamaIndex 中用于解析 PDF 文件的标准方法。
以下是使用 pypdf 尝试解析“Attention Is All You Need ”论文第 6 页的示例。原始页面如图 3 所示。

代码如下:
1 | import PyPDF2 |
执行结果如下(为简洁起见省略其余部分):
1 | (py) Florian:~ Florian$ pip list | grep pypdf |
根据 PyPDF 的检测结果,可以观察到它将 PDF 中的字符序列序列化为一个长序列,而不保留结构信息。换句话说,它将文档的每一行视为由换行符“\n”分隔的序列,这使得无法准确识别段落或表格。
这一限制是基于规则方法的固有特性。
基于深度学习模型的方法
这种方法的优势在于其能够准确识别整个文档的布局,包括表格和段落,甚至能理解表格内部的结构。这意味着它可以将文档分割成定义明确、完整的信息单元,同时保留预期的意义和结构。
然而,也存在一些局限性。目标检测和OCR阶段可能会耗时较长。因此,建议使用GPU或其他加速设备,并采用多进程和多线程进行处理。
这种方法涉及目标检测和OCR模型,我测试了几个具有代表性的开源框架:
- Unstructured :它已被集成到langchain中 。使用
infer_table_structure=True的hi_res策略进行表格识别效果良好。然而,fast策略表现不佳,因为它不使用目标检测模型,错误地识别了许多图像和表格。 - Layout-parser :如果需要识别复杂的结构化PDF,建议使用最大的模型以获得更高的准确性,尽管可能会稍慢一些。此外,似乎Layout-parser的模型 在过去两年内没有更新。
- PP-StructureV2 :使用多种模型组合进行文档分析,性能中等偏上。架构如图4所示:

除了开源工具外,还有如ChatDOC这样的付费工具,采用基于布局的识别+OCR方法来解析PDF文档。
接下来,我们将解释如何使用开源的unstructured 框架解析PDF,解决三个关键挑战。
挑战1:如何从表格和图像中提取数据
这里,我们以unstructured 框架为例。检测到的表格数据可以直接导出为HTML。代码如下:
1 | from unstructured.partition.pdf import partition_pdf |
我追踪了**partition_pdf**函数的内部流程。图5是一个基本流程图。

代码的运行结果如下:
1 | Layer Type Self-Attention Recurrent Convolutional Self-Attention (restricted) Complexity per Layer O(n2 · d) O(n · d2) O(k · n · d2) O(r · n · d) Sequential Maximum Path Length Operations O(1) O(n) O(1) O(1) O(1) O(n) O(logk(n)) O(n/r) |
复制HTML标签并保存为HTML文件,然后用Chrome打开,如图6所示:

可以看出,unstructured的算法在很大程度上还原了整个表格。
挑战2:如何重新排列检测到的块?特别是对于双栏PDF。
处理双栏PDF时,以论文“BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding ”为例。阅读顺序如图中的红色箭头所示:

识别布局后,unstructured框架会将每一页分割成多个矩形块,如图8所示。

每个矩形块的详细信息可以以下列格式获取:
1 | [ |
此时,您可以选择调整页面的阅读顺序。Unstructured 自带一个排序算法,但在处理双栏情况时,我发现排序结果并不十分令人满意。
因此,有必要设计一个算法。最简单的方法是先按左上顶点的水平坐标排序,如果水平坐标相同,则再按垂直坐标排序。其伪代码如下:
1 | layout.sort(key=lambda z: (z.bbox.x1, z.bbox.y1, z.bbox.x2, z.bbox.y2)) |
然而,我们发现即使是在同一栏中的块,其水平坐标也可能有所不同。如图 9 所示,紫色线条块的水平坐标 bbox.x1 实际上更靠左。排序时,它会排在绿色线条块之前,这显然违反了阅读顺序。

在这种情况下,可以使用以下算法:
- 首先,对所有左上 x 坐标
**x1**进行排序,得到**x1_min** - 然后,对所有右下 x 坐标
**x2**进行排序,得到**x2_max** - 接下来,确定页面中心线的 x 坐标为:
1 | x1_min = min([el.bbox.x1 for el in layout]) |
接下来,**如果 bbox.x1 < mid_line_x_coordinate**,则该块被归类为左栏的一部分。否则,它被视为右栏的一部分。
分类完成后,根据 y 坐标对每栏中的块进行排序。最后,将右栏连接到左栏的右侧。
1 | left_column = [] |
值得一提的是,这一改进同样适用于单栏 PDF。
挑战 3:如何提取多级标题
提取标题,包括多级标题的目的,是为了提高 LLM 回答的准确性。
例如,如果用户想知道图 9 中第 2.1 节的主要内容,通过准确提取第 2.1 节的标题,并将其与相关内容一起作为上下文发送给 LLM,最终答案的准确性将显著提高。
该算法仍然依赖于图 9 中显示的布局块。我们可以提取 **type=’Section-header’** 的块,并计算高度差 (**bbox.y2 — bbox.y1**)。高度差最大的块对应一级标题,其次是二级标题,然后是三级标题。
基于多模态大模型的PDF复杂结构解析
多模态模型爆发后,我们也可以利用多模态模型来解析表格。有几种选择 :
- 检索相关图像(PDF页面)并发送至GPT4-V以响应查询。
- 将每个PDF页面视为图像,让GPT4-V对每个页面进行图像推理。为图像推理构建文本向量存储索引。针对图像推理向量存储进行查询以获取答案。
- 使用Table Transformer从检索到的图像中裁剪表格信息,然后将这些裁剪后的图像发送至GPT4-V以响应查询。
- 对裁剪后的表格图像应用OCR,并将数据发送至GPT4/GPT-3.5以回答查询。
经过测试,确定第三种方法最为有效。
此外,我们可以利用多模态模型从图像(PDF文件可轻松转换为图像)中提取或总结关键信息,如图10所示。

结论
总体而言,非结构化文档提供了高度的灵活性,并需要多种解析技术。然而,目前尚无关于最佳方法的共识。
在这种情况下,建议选择最适合您项目需求的方法。根据不同类型的PDF文件,建议采用特定的处理方式。例如,论文、书籍和财务报表可能基于其特性具有独特的设计。
尽管如此,如果条件允许,仍建议选择基于深度学习或多模态的方法。这些方法能有效将文档分割成定义明确且完整的信息单元,从而最大限度地保留文档的意图和结构。
最后,如果您有任何疑问,欢迎在评论区讨论。
- 标题: 高级RAG 02揭秘PDF解析
- 作者: Barry
- 创建于 : 2024-02-03 00:01:39
- 更新于 : 2024-08-31 06:59:45
- 链接: https://wx.role.fun/2024/02/03/b889523ea0c54730921658c4dbf80df6/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。