免费的图库网站,公司网站备案电话,wordpress语音,thinkphp旅游网站源码1. 简介
版面分析作为RAG的第一步工作#xff0c;其效果对于下游工作至关重要。
前常见的 PDF 解析方法包括三种
基于规则#xff1a;根据 PDF 的组织特征确定每个部分的规则#xff08;风格和内容#xff09;缺点#xff1a;不通用#xff08;PDF格式不固定#xf…1. 简介
版面分析作为RAG的第一步工作其效果对于下游工作至关重要。
前常见的 PDF 解析方法包括三种
基于规则根据 PDF 的组织特征确定每个部分的规则风格和内容缺点不通用PDF格式不固定基于深度学习目标检查和 OCR 结合的流行解决方案基于多模态大模型对复杂的结构进行Pasing或提取PDF中的关键信息
1.1 基于规则的pdf解析
代表框架
pdfplumberPyMuPDFpypdf
1.1.1 pdfplumber
pdfplumber 按照每一页处理 pdf获得 pdf 的页面文字提取表格最终将 pdf 文件生成对应的 txt 文件。 缺点按页进行处理有时候一段上下文连续的文字分散到两页并不好进行处理。
## 纯文本
file_name ./example_data/焦点科技__2019年__年度报告.pdf
output_file ./example_data/焦点科技__2019年__年度报告.txt
with pdfplumber.open(file_name) as pdf, open(output_file, wt, encodingutf-8) as f:for page in pdf.pages: # pdf.pages是⼀个Page对象的列表text page.extract_text() # 调⽤Page对象的extract_text()⽅法提取⽂本f.write(text)f.write(\n)## 表格
with pdfplumber.open(file_name) as pdf, open(output_file, wt, encodingutf-8) as f:for page in pdf.pages: # pdf.pages是⼀个Page对象的列表text page.extract_table() # 提取每⻚的表格⽂字信息# page.extract_tables() 提取多个表格print(text)if text:f.write(str(text))f.write(\n)## 表格保存为excel
from openpyxl import Workbook
with pdfplumber.open(file_name) as pdf:for i in pdf.pages:table i.extract_table()if table:workbook Workbook() # 创建⼀个⼯作簿sheet workbook.active # 获取当前活跃的sheet默认是第⼀个sheetfor row in table:sheet.append(row)workbook.save(output_file) # 保存⼯作簿break## 提取图片保存到本地
with pdfplumber.open(file_name) as pdf:for i in pdf.pages:print(⻚码:, i.page_number)print(⻚宽:, i.width)print(⻚⾼:, i.height)print(⻚⽂本:, i.extract_text())print(⻚表格:, i.extract_table())print(⻚图⽚:, i.images)for img in i.images:# 获取图⽚的⼆进制流img_data img[stream].get_data()with open(output_file, wb) as f:f.write(img_data)break # 解析第⼀⻚1.1.2 pymupdf
pymupdf 支持将文字修改写入 pdf 的界面支持提取所有类型的文档支持的功能特别多基本上各种文件都可以处理
import fitz
pdf_path /example_data/安靠智电__2019年__年度报告.pdf
doc fitz.open(pdf_path)# 基本的pdf信息
title doc.metadata[title] # 标题
author doc.metadata[author] # 作者
create_time doc.metadata[creationDate] # 创建时间
num_pages doc.page_count # ⻚数
page doc.load_page(0) # 加载第⼀⻚
page_width page.rect.width # ⻚宽
page_height page.rect.height # ⻚⾼
page_text page.get_text() # ⻚⽂本
page_images page.get_images(fullTrue) # ⻚图⽚
print(标题:, title)
print(作者:, author)
print(创建时间:, create_time)
print(⻚数:, num_pages)
print(⻚码:, 1)
print(⻚宽:, page_width)
print(⻚⾼:, page_height)
print(⻚⽂本:, page_text)
print(⻚图⽚:, page_images)num_pages doc.page_count # ⻚数
for page_index in range(num_pages):page doc.load_page(page_idpage_index)page_text page.get_text() # ⻚⽂本print(page_text)breakfor page_index in range(num_pages):page doc.load_page(page_idpage_index)image_list page.get_images() # 图⽚print(image_list)# 两种⽅式# 1for img in image_list:xref img[0]base_image doc.extract_image(xref)image_bytes base_image[image] # 图⽚⼆进制数据image_ext base_image[ext] # 图⽚格式# image_path f./example_data/__焦点科技__2019年__年度报告__page_{page_index}__image_{xref}.{image_ext}# with open(image_path, wb) as f:# f.write(image_bytes)# 2pix fitz.Pixmap(doc, xref)pix.save(f./example_data/焦点科技__2019年__年度报告__page_{page_index}__image_{xref}.png)break## 获取表格
for page_index in range(num_pages):page doc.load_page(page_idpage_index)tables page.find_tables() # 表格print(tables)# 提取表格数据并存储为csv⽂件for table in tables:df table.to_pandas()print(df.head())df.to_csv(f./example_data/焦点科技__2019年__年度报告_page_{page_index}__table_{table}.csv,indexFalse)break## PDF文档分割
output_dir ./example_data/{0}.pdf
for page_index in range(num_pages):print(page_index)# 创建⼀个新的Document对象包含当前⻚⾯new_pdf fitz.open()new_pdf.insert_pdf(doc, from_pagepage_index, to_pagepage_index)# 保存为单独的pdf⽂件new_pdf.save(output_dir.format(page_index))new_pdf.close()break
doc.close()1.1.3 pypdf
pypdf 就是一种基于规侧广泛使用的解析器也是 LangChain 和 Llamalndex 中解析 PDF文件的标准方法。
pip install PyPDF2import PyPDF2
filename ./example_data/焦点科技_2019年__年度报告.pdf
pdf_file open(filename, rb)
reader PyPDF2.PdfReader(pdf_file)
page_num 0
page reader.pages[page_num]
text page.extract_text()
print(--------------------------------------------------)
print(text)
pdf_file.close()焦点科技股份有限公司 2019年年度报告全⽂
1
焦点科技股份有限公司
Focus Technology Co., Ltd.
南京江北新区星⽕路软件⼤厦 A 座12F
⼆〇⼀九年年度报告
⼆〇⼆〇年⼆⽉1.2 基于深度学习的pdf解析
基于深度学习模型的方法能够准确地识别整个文档的布局包括表格和段落。它甚至可以理解表中的结构。这意味着它可以将文档划分为定义明确、完整的信息单元。同时保留预期的含义和结构。 代表性的开源框架
Unstructured: 已经集成到langchain中。使用hi_res策略设置infer_table_structureTrue 可以很好的识别表格信息。然而 fast策略因为不使用目标检测模型在识别图像和表格方面表现比较差。Layout-parser如果需要识别复杂的结构化PDF ,建议使用最大的模型以获得更高的精度但是会比较慢。此外Layout解析器的模型在过去几年中似乎没有更新。PP-StructureV2 可以组合各种模型用于文档分析性能高于平均水平。
Unstructured
from unstructured.partition.pdf import partition_pdf
filename ../paper/bert.pdf
# infer_table_structureTrue automatically selects hi_res strategy
elements partition_pdf(filenamefilename, infer_table_structureTrue)
tables [el for el in elements if el.category Table]
print(tables[0].text)
print(--------------------------------------------------)
print(tables[0].metadata.text_as_html)1.3 基于多模态的pdf解析复杂结构
LlamaIndex例子检索相关图像PDF页面并将其发送到GPT4-V 以响应查询。
将每个PDF页面视为一个图像让GPT4-V 对每个页面进行图像推理为图像推理构建文本矢量存储索引根据图像矢量存储查询答案。使用Table Transformer从检索到的图像中裁剪表信息然后将这些裁剪的图像发送到GPT4-V 进行查询相应。对裁剪的表图像应用OCR,并将数据发送到GPT4 以回答查询。
经测试确定第三种方法最有效。 此外可以试用多模态模型从图像中提取或者总结关键信息PDF文件可以很容易转换为图像
1.3.1 解析pdf文档存在哪些挑战
挑战在于准确提取整个页面的布局并将表格、标题、段落和图片在内的内容翻译成文档的文本表示。这个过程涉及到处理文本提取、图像识别中的不确定之处以及表中行-列关系的混乱。
1.3.1.1 挑战一如何从表格和图像中提取数据问题
使用unstructured框架作为示例检测到的表格数据可以直接导出为HTML: 复制HTML标记并将其另存为HTML文件使用Chrome打开如下
1.3.1.2 挑战二如何重新排列检测到的块特别对于双列PDF? 在确定布局后unstructured框架会将每个页面划分成几个矩形块 每个矩形块的详细信息可以通过以下格式获取 其中x1, y1是左上顶点的坐标x2, y2是右下顶点的坐标 此时可以选择重新调整页面的阅读顺序。unstructured 有一个内置排序算法。但是实际排序结果不是很满意。 因此有必要设计一种排序算法。最简单的方法就是先按左上角顶点的水平座标排序如果水平座标相同则按垂直坐标排序。伪代码如下
layout.sort(keylambda z:(z.bbox.x1, z.bbox.y1, z.bbox.x2, z.bbox.y2))然而还发现即使同一列中的块其水平坐标也可能发生变化。如下图提取到的紫色线条块的水平坐标bbox.x1 实际更靠左。排序时他将位于路线块之前显然违反了阅读顺序。 在这种情况下使用一种可能的算法
首先对左上角所有x坐标x1 进行排序可以得到X1_min然后对所有右下角x坐标x2进行排序可以得到x2_max接下来将页面中心线的x坐标确定x1_min min([el.bbox.x1 for el in layout]) ; x2_max max([el.bbox.x2 for el in layout]); mid_line_x_cooedinate (x2_max x1_min)/2接下来如果bbox.x1 mid_line_x_cordinate 则块被分类为左列的一部分。否则被视为右边的一部分。分类完成后根据列中的y坐标对每个块进行排序。最后将右侧列连接到左侧列的右侧
left_column, right_column [], []
for el in layout:if el.bbox.x1 mid_line_x_cooedinate:left_column.append(el)else:right_column.append(el)left_column.sort(key lambda z: z.bbox.y1)
right_column.sort(key lambda z: z.bbox.y1)
sorted_layout left_column right_column值得一提的是这种改进也与单列pdf兼容.
1.3.1.3 挑战三如何提取多级标题
提取多级标题的目的是提高LLM答案的准确性。 该算法依然依赖与上面提到的布局快。我们可以设置type‘Section-hearder’的块并计算高度差bbox.y2-bbox.y1。高度差最大的块对应第一级标题其次是第二级标题…
补充PPT类文档解析问题
难点如何对PPT 中的大量的流程图架构图进行提取因为这些图多以形状元素在PPT中呈现如果只提取文字大量潜藏的信息会大量丢失。解决办法将PPT转为pdf形式然后用户上述处理PDF 的形式进行解析。 参考 版面分析–优化策略篇 【知识库构建——知识文本分块】 【知识库构建——文档切分优化策略篇】