RAG 系列之二:PDF 文件的解析

news2024/9/20 6:42:52

在 RAG(检索增强生成)简介的流程图中,有一个环节是检索向量数据库(下图中红色框标识的部分)。向量数据库存储了外部知识库经过向量化处理的内容。在检索之前,我们首先需要创建向量数据库,而创建的第一步是解析知识库中的文件,提取其中的文本、表格等信息。由于 PDF 格式的文件占据了文件的大部分,因此如何从 PDF 文件中精确且高效地提取这些信息,便成为创建向量数据库的关键。本文将介绍如何解析 PDF 文件,帮助实现这一目标。

PDF,即便携式文档格式(英语:Portable Document Format,缩写 PDF),是一种能够独立于应用程序、硬件和操作系统呈现文档的文件格式。PDF 之所以受欢迎,是因为它能够完全保留原文档的格式,不受设备、软件或系统的影响,这对于传播信息来说意义重大。试想一下,如果你使用的是 Word 文档,一旦更换设备,字体、图片、颜色和格式等可能都会发生变化。但 PDF 不会出现这种情况,它能够原汁原味地保留重要的图文信息,不用担心设备的影响。正是为了实现这种显示的一致性,PDF 牺牲了可编辑性。这里有一点需要注意,不是 PDF 不想做到容易编辑,也不是故意让你无法修改,而是为了极致的显示一致性,必须牺牲可编辑性。PDF 会将文本的位置、字体、间距、缩放比例、页边距等所有属性在文件格式中限定死,让软件没有自由发挥的空间。这就是为什么不同软硬件打开 PDF 效果都能一致的原因。本质上,PDF 的格式限制确保了它在任何设备上的显示效果都一样。比如,一个包含 “Hello World” 字样的 PDF 文件用 PDF 阅读器打开时,效果如下面的左边所示。如果用文本编辑器打开这个 PDF 文件,显示结果如下面的右边所示。

看到上面的这个文件内容,我们也就明白了 PDF 为什么难于编辑的原因了。但也正是这个文件,会手把手地告诉电脑,怎么一点一点把这个文件的内容在屏幕上打印出来,最大程度地确保了所有人看到这个文件的效果都一样。

上面说的这类 PDF 文件是文本 PDF,也就是机器生成的 PDF。还有一类 PDF 文本 是扫描 PDF,这类文件的每一页都是一张图片,所用到的解析方法和文本 PDF 也是不一样的。下面就分别把解析两类 PDF 文件效果还不错的工具介绍给大家。

文本 PDF 的解析

文本的提取

能够进行文本提取的 Python 库包括:pdfminer.sixPyMuPDFPyPDF2pdfplumber,效果最好的是 PyMuPDF,PyMuPDF 在进行文本提取时能够最大限度地保留 PDF 的阅读顺序,这对于双栏 PDF 文件的抽取非常有用。下面就以难度比较大的双栏 PDF 为例,来介绍使用 PyMuPDF 库进行文字抽取的效果。

我们以下面的 PDF 为例来看使用 PyMuPDF 进行文字提取的效果。

进行文本提取的代码如下:


import pymupdf

pages = pymupdf.open("bert.pdf")
text = pages[0].get_text()

print(text)

打印的结果如下:

BERT: Pre-training of Deep Bidirectional Transformers for
Language Understanding
Jacob Devlin
Ming-Wei Chang
Kenton Lee
Kristina Toutanova
Google AI Language
{jacobdevlin,mingweichang,kentonl,kristout}@google.com
Abstract
We introduce a new language representa-
tion ......
(5.1 point absolute improvement).
1
Introduction
Language model pre-training has been shown to
......
De Meulder, 2003; Rajpurkar et al., 2016).
There are two existing strategies for apply-
ing ......
predict the original vocabulary id of the masked
arXiv:1810.04805v2  [cs.CL]  24 May 2019

提取出的文字遵循了原 PDF 文件的阅读顺序,也就是先读左边栏的文字,再读右边栏的文字,(为了节省版面,对部分文字进行了省略),这样提取出的文本也就保持了原 PDF 的语义。

除了上面的这种提取方式之外,我们还可以将文本提取为文本块的列表。代码如下:

import pymupdf

pages = pymupdf.open("bert.pdf")
text = pages[0].get_text("blocks")

print(text)

打印的结果如下:

[(116.51899719238281, 67.92063903808594, 481.02740478515625, 102.5250473022461, 'BERT: Pre-training of Deep Bidirectional Transformers for\nLanguage Understanding\n', 0, 0), (107.78799438476562, 128.531005859375, 492.7443542480469, 179.3809814453125, 'Jacob Devlin\nMing-Wei Chang\nKenton Lee\nKristina Toutanova\nGoogle AI Language\n{jacobdevlin,mingweichang,kentonl,kristout}@google.com\n', 1, 0), (158.89096069335938, 222.02301025390625, 203.37625122070312, 237.57672119140625, 'Abstract\n', 2, 0), ...... , (10.940000534057617, 256.5899658203125, 37.619998931884766, 609.8900146484375, 'arXiv:1810.04805v2  [cs.CL]  24 May 2019\n', 8, 0)]

由上面的结果可以看出,每个文本块包含了文本块的坐标、文本块的内容以及文本块的序号(为了节省版面,对部分文本块进行了省略)。有了每个文本块的上述信息,我们便可以知道文本块的阅读顺序;如果需要的话,还可以使用每个文本块的坐标信息对版面进行恢复。

表格的提取

表格提取效果比较好的库有 camelottabula ,表格又可以分为有线表和少线表。下面就分别以有线表和少线表为例来介绍 camelottabula 的使用。

有线表

我们以下面的 PDF 为例来看使用 camelottabula 进行有线表格提取的效果。

  1. 使用 camelot 进行表格提取的代码如下:
import camelot

tables = camelot.read_pdf('data.pdf')
print(tables[0].df)

输出结果如下:

  1. 使用 tabula 进行表格提取的代码如下:
import tabula

dfs = tabula.read_pdf("data.pdf")
print(dfs[0])

输出结果如下:

从结果可以看出,在提取有线表时,不管是 camelot 还是 tabula 都能很好地进行提取,而且不需要过多的参数设置。

少线表

我们以下面的 PDF 为例来看使用 camelottabula 进行少线表格提取的效果。

  1. 使用 camelot 进行少线表格提取的代码如下:
import camelot

tables = camelot.read_pdf('bert-6.pdf', flavor='stream')
tables[0].df

在使用 camelot 进行少线表格的提取时,需要将参数 flavor 设置成 stream ,输出结果如下:

  1. 使用 tabula 进行少线表格提取的代码如下:
import tabula

dfs = tabula.read_pdf("bert-6.pdf", stream=True)
dfs[0]

在使用 tabula 进行少线表格的提取时,需要将参数 stream 设置成 True ,输出结果如下:

在使用 camelottabula 进行少线表格的提取时,需要设置相应的参数。

扫描 PDF 的解析

文本的提取

在从扫描的 PDF 文件中提取文本时,使用开源的 PaddleOCR,并且用 PPStructure 做版面的分析。我们还是以下面的 PDF 文件为例,不过这是的 PDF 文件是扫描 PDF。

提取文本的代码如下:

import os
import cv2
from paddleocr import PPStructure, draw_structure_result, save_structure_res
from PIL import Image

img_path = "./bert-1.png"

table_engine = PPStructure(show_log=True)
save_folder = './output'
img = cv2.imread(img_path)
result = table_engine(img)
save_structure_res(result, save_folder, os.path.basename(img_path).split('.')[0])

font_path = './fonts/simfang.ttf'
image = Image.open(img_path).convert('RGB')
im_show = draw_structure_result(image, result, font_path=font_path)
im_show = Image.fromarray(im_show)
im_show.save('result.jpg')

得到的结果如下:

图中的左边是根据给出的版面分析结果画出来的,可以看出对双栏 PDF 做了正确的解析。右边是根据识别出来的文本以及文本的坐标画出来的,可以看出基本上和左边的版面以及内容是一致的。

表格的提取

我们还是以下面的 PDF 文件为例,不过这是的 PDF 文件是扫描 PDF。

代码如下:

import os
import cv2
from paddleocr import PPStructure,draw_structure_result,save_structure_res
from PIL import Image
 
table_engine = PPStructure(show_log=True)
save_folder = './output'
img_path = './bert-6.png'
img = cv2.imread(img_path)
result = table_engine(img)
save_structure_res(result, save_folder,os.path.basename(img_path).split('.')[0])

for line in result:
    line.pop('img')
    print(line)

在上面的输出结果中,有一行类型为 table 的输出,我们将这一行中 html 标签下的内容拷贝出来,放到一个 html 文件中,得到如下的表格:

可以看出在表头这一块还是有一些差异,但是其他的信息基本都是正确的,应该说效果还是不错的。

总结

本文重要介绍了文本 PDF 和 扫描 PDF 的解析,了解到了 PDF 文件解析的复杂性。要想 RAG(检索增强生成)后面的环节取得比较好的效果,文件解析的准确性至关重要。如果在文件解析这一环节质量不高的话,后面的环节不论怎么优化,也不会达到很好的效果。所以花大力气在文件的解析上,后面会收到事半功倍的效果。

如何系统的去学习大模型LLM ?

大模型时代,火爆出圈的LLM大模型让程序员们开始重新评估自己的本领。 “AI会取代那些行业?”“谁的饭碗又将不保了?”等问题热议不断。

不如成为「掌握AI工具的技术人」,毕竟AI时代,谁先尝试,谁就能占得先机!

但是LLM相关的内容很多,现在网上的老课程老教材关于LLM又太少。所以现在小白入门就只能靠自学,学习成本和门槛很高

针对所有自学遇到困难的同学们,我帮大家系统梳理大模型学习脉络,将这份 LLM大模型资料 分享出来:包括LLM大模型书籍、640套大模型行业报告、LLM大模型学习视频、LLM大模型学习路线、开源大模型学习教程等, 😝有需要的小伙伴,可以 扫描下方二维码领取🆓↓↓↓

👉[CSDN大礼包🎁:全网最全《LLM大模型入门+进阶学习资源包》免费分享(安全链接,放心点击)]()👈

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2037854.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

虚拟化—XenServer安装教程详细(附客户端连接)

🏡作者主页:点击! 🐧Linux基础知识(初学):点击! 🐧Linux高级管理防护和群集专栏:点击! 🔐Linux中firewalld防火墙:点击! ⏰️创作…

积鼎 VirtualFlow 案例|高精度工程雾化模型,优化离心旋流喷嘴雾化效果

雾化喷嘴已广泛渗透于航空航天、车辆工程、医药制造、精密生产、食品加工、环境保护以及现代农业等众多工业领域,成为提升各行业生产效率与性能的关键工具。因此,雾化喷嘴的仿真技术显得尤为重要,通过准确模拟喷嘴的雾化过程,帮助…

idea项目注册在nacos错误:Cannot determine local hostname

一开始想把项目注册在nacos上,启动报错是这样的,而且yml文件也不生效,因为默认端口是8080,我在yml文件中写了8081没用,正好nacos的配置也在yml文件中。各种百度,各种依赖添加删除,反复启动没用 …

Redis7-分布式锁

目录 基本原理 分布式锁的实现 基于Redis的分布式锁 Redis分布式锁误删 分布式锁的原子性问题 基于Redis的分布式锁优化 Redission概述 Redisson入门 Redisson可重入锁原理 ​编辑 Reddisson锁重试和WatchDog机制 Redisson分布式锁原理 Redission的MultiLock原理 …

《江南:在爱开始的地方等你》定档9月15日,愿有情人终成眷属

由康锐原创小说《月落姑苏》改编,并由康锐导演、编剧,赖雨濛、刘冬沁领衔主演、朱丹妮、王沛为、金巧巧、阎青妤、李菁菁、苇青等共同主演的电影《江南:在爱开始的地方等你》官宣定档中秋。 影片讲述了陆骁(刘冬沁饰)…

Excel VBA批量获取文件夹内文件名及重命名文件教程

在本文中,我们将介绍如何使用Excel VBA宏来批量获取文件夹内的文件名,并将其输出到Excel单元格区域。此外,我们还将展示如何根据Excel中的列表批量重命名这些文件。 一、批量获取文件夹内文件名 首先,我们需要编写一个VBA宏来列出…

【《Kafka 入门指南:从零基础到精通》】

前言: 💞💞大家好,我是书生♡,本阶段和大家一起分享和探索KAFKA,本篇文章主要讲述了:消息队列的基础知识,KAFKA消息队列等等。欢迎大家一起探索讨论!!&#x…

用7EPhone云手机进行TikTok的矩阵运营

“根据市局机构Statista发布的报告显示,截至2024年4月,TikTok全球下载量超过49.2亿次,月度活跃用户数超过15.82亿。TikTok的流量受欢迎程度可想而知,也一跃成为了全球第五大最受欢迎的社交APP。” 人群密集的地方社区也是适合推广…

《pygame游戏开发实战指南》第八节 Sprite类和Group类

Sprite(精灵)是游戏中一个非常重要的概念。在游戏开发中,‌Sprite指的是一个可以移动、‌旋转或变换的二维图像,‌它负责管理游戏中的图像元素,‌使得开发者可以轻松地在游戏中创建各种动态效果和角色。‌pygame.sprite模块提供了Sprite类和G…

分类预测|基于鲸鱼优化-卷积-长短期记忆网络-注意力数据分类预测Matlab程序 WOA-CNN-LSTM-Attention

分类预测|基于鲸鱼优化-卷积-长短期记忆网络-注意力数据分类预测Matlab程序 WOA-CNN-LSTM-Attention 文章目录 前言分类预测|基于鲸鱼优化-卷积-长短期记忆网络-注意力数据分类预测Matlab程序 WOA-CNN-LSTM-Attention 一、WOA-CNN-LSTM-Attention模型1. 鲸鱼优化算法&#xff0…

产品经理的具体职责有哪些?

产品经理作为产品团队的核心角色,负责从概念到市场发布的整个过程,确保产品能够满足用户需求,实现商业目标。其工作职责广泛且深入,涵盖了产品规划、设计、开发、运营、推广等多个方面。以下是详细的工作职责描述以及产品经理的核…

一文彻底搞懂Transformer - 注意力机制

Transformer 一、注意力机制 Seq2Seq 注意力机制目标 Attention模块的主要作用是确定在给定上下文中哪些嵌入向量与当前任务最相关,并据此更新或调整这些嵌入向量的表示。 Transformer注意力机制 注意力机制案例 注意力机制计算公式 生成Q、K、V向量:对…

智能升降晾衣架:NRK3301语音识别模块ic让家务变得更轻松

对于经常做家务的人来说,洗衣服和晾衣服是一件非常耗费体力和时间的任务。传统的晾衣架安装在了一个固定的高度,挂衣服和取衣服需要通过撑衣杆来晾取衣物,即便是电动升降的晾衣架,也需要人手动去操作,增加了工作量。然…

Vue 项目中导入文件时如何默认找寻该文件夹下的 index.vue 文件

文章目录 需求分析 需求 如下图,在Vue 项目中导入 frequencyChange 文件夹时如何默认找寻该文件夹下的 index.vue 文件 分析 确保项目结构和命名约定 首先,确保你的 Vue 单文件组件按照约定命名,例如: components/Example/inde…

Python酷库之旅-第三方库Pandas(080)

目录 一、用法精讲 331、pandas.Series.str.repeat方法 331-1、语法 331-2、参数 331-3、功能 331-4、返回值 331-5、说明 331-6、用法 331-6-1、数据准备 331-6-2、代码示例 331-6-3、结果输出 332、pandas.Series.str.replace方法 332-1、语法 332-2、参数 33…

【QT常用技术讲解】QTableView添加QCheckBox、QPushButton

前言 QT展示列表信息的时候通常用到列表(比如用户信息、机构信息、设备信息等菜单),当需要对某列进行修改、删除操作时,就需要加入按钮(QPushButton),当需要对多列进行右键菜单操作时&#xff0…

DjangoRF-15-分布式celery应用

前面我们同步实现了测试任务的执行,但是它有一个致命的问题。 实际项目测试任务耗时会非常长,而django框架的请求是有超时的,哪怕没有超时,这么做显然不妥。所以需要使 用异步任务的方式来执行测试任务。 发送一个执行任务的请求&…

沐风老师3DMAX纹理工具箱TexTools使用方法详解

DMAX纹理工具箱TexTools是一组工具,可帮助任何纹理艺术家完成UV和纹理相关任务。主要理念是将典型步骤简化为简单的上下文相关单击。 大多数功能仅在3dMax中处于editUVW模式时才起作用(展开UVW修改器,然后单击编辑按钮)。 【版本要求】 3dMax9及更高版本 【安装方法】 将…

EmbeddedBuilder_v1.4.1.23782 - 在工程中添加自己的C实现文件

文章目录 EmbeddedBuilder_v1.4.1.23782 - 在工程中添加自己的C实现文件概述笔记添加自己的文件夹在文件夹中建立新文件在文件夹中载入已经存在的文件修改工程编译时的包含路径和库路径添加包含路径添加实现路径 在main.c或其他实现中添加自己的头文件引用和自己的函数调用保存…

Seaborn库

目录 主要功能和特点 使用方法 实例应用 Seaborn库的最新版本有哪些新功能和改进? 如何在Seaborn中实现复杂的数据预处理步骤,例如数据清洗和转换? Seaborn与其他数据可视化库(如Matplotlib、Plotly)相比有哪些优…