便携式文档格式(PDF) (opens in a new tab),简称 ISO 32000,是 Adobe 于 1992 年开发的文件格式,用于呈现文档,包括文字格式和图像,与应用软件,硬件和操作系统无关。
本篇介绍如何将 PDF 文档加载到我们后续使用的文档格式中。
使用 PyPDF
使用 pypdf 将 PDF 加载到文档数组中,每个文档包含页面内容和具有 page 编号的元数据。
pip install pypdffrom langchain_community.document_loaders import PyPDFLoader
loader = PyPDFLoader("example_data/layout-parser-paper.pdf")
pages = loader.load_and_split()pages[0]Document(page_content='LayoutParser : A Uni\x0ced Toolkit for Deep\nLearning Based Document Image Analysis\n...', metadata={'source': 'example_data/layout-parser-paper.pdf', 'page': 0})这种方法的一个优势是文档可以带页码检索。
我们想使用 OpenAIEmbeddings,因此需要获取 OpenAI API Key。
import os
import getpass
os.environ['OPENAI_API_KEY'] = getpass.getpass('OpenAI API Key:')from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
faiss_index = FAISS.from_documents(pages, OpenAIEmbeddings())
docs = faiss_index.similarity_search("How will the community be engaged?", k=2)
for doc in docs:
print(str(doc.metadata["page"]) + ":", doc.page_content[:300])9: 10 Z. Shen et al.
...
3: 4 Z. Shen et al.
...提取图像
使用 rapidocr-onnxruntime 包可以将图像提取为文本:
pip install rapidocr-onnxruntimeloader = PyPDFLoader("https://arxiv.org/pdf/2103.15348.pdf", extract_images=True)
pages = loader.load()
pages[4].page_content'LayoutParser : A Unified Toolkit for DL-Based DIA 5\nTable 1: Current layout detection models in the LayoutParser model zoo\n...'使用 PyMuPDF
这是 PDF 解析选项中最快的一种,包含关于 PDF 及其页面的详细元数据,并且每页返回一个文档。
from langchain_community.document_loaders import PyMuPDFLoaderloader = PyMuPDFLoader("example_data/layout-parser-paper.pdf")data = loader.load()data[0]Document(page_content='LayoutParser: A Unified Toolkit for Deep\nLearning Based Document Image Analysis\n...', metadata={'file_path': 'example_data/layout-parser-paper.pdf', 'page_number': 1, 'total_pages': 16, 'format': 'PDF 1.5', ...})此外,你可以将 PyMuPDF 文档 (opens in a new tab) 中的任意选项作为关键字参数传入 load 调用,它会传递给 get_text() 调用。
使用 MathPix
灵感来自 Daniel Gross 的 https://gist.github.com/danielgross/3ab4104e14faccc12b49200843adab21 (opens in a new tab)
from langchain_community.document_loaders import MathpixPDFLoaderloader = MathpixPDFLoader("example_data/layout-parser-paper.pdf")data = loader.load()使用 Unstructured
unstructured[all-docs] 包目前支持加载文本文件、powerpoint、html、pdf、图像等。
pip install unstructured[pdf]from langchain_community.document_loaders import UnstructuredPDFLoaderloader = UnstructuredPDFLoader("example_data/layout-parser-paper.pdf")data = loader.load()保留元素
底层,Unstructured 为不同的文本块创建不同的“元素”。默认我们将它们组合在一起,但是您可以通过指定 mode="elements" 来保留此分隔。
loader = UnstructuredPDFLoader("example_data/layout-parser-paper.pdf", mode="elements")data = loader.load()data[0]Document(page_content='LayoutParser: A Unified Toolkit for Deep\nLearning Based Document Image Analysis\n...', metadata={...})使用 Unstructured 获取远程 PDF
这包括如何将在线 PDF 加载到我们可以在下游使用的文档格式中。这可用于各种在线 PDF 站点,如 https://open.umn.edu/opentextbooks/textbooks/ (opens in a new tab) 和 https://arxiv.org/archive/ (opens in a new tab)
请注意:所有其他 PDF 加载程序也可以用于获取远程 PDF,但 OnlinePDFLoader 是一个遗留函数,专门与 UnstructuredPDFLoader 一起使用。
from langchain_community.document_loaders import OnlinePDFLoaderloader = OnlinePDFLoader("https://arxiv.org/pdf/2302.03803.pdf")data = loader.load()print(data)[Document(page_content='A WEAK ( k, k ) -LEFSCHETZ THEOREM FOR PROJECTIVE TORIC ORBIFOLDS\n...', metadata={'source': '.../online_file.pdf'})]使用 PyPDFium2
from langchain_community.document_loaders import PyPDFium2Loaderloader = PyPDFium2Loader("example_data/layout-parser-paper.pdf")data = loader.load()使用 PDFMiner
PDFMiner 是一个可以帮助从 PDF 文档中提取信息和分析数据的工具。
pip install pdfminer.sixfrom langchain_community.document_loaders import PDFMinerLoaderloader = PDFMinerLoader("example_data/layout-parser-paper.pdf")data = loader.load()使用 PDFMiner 生成 HTML 文本
这对于将文本按语义分块为章节很有帮助,因为输出的 html 内容可以通过 BeautifulSoup 解析,以获取关于字体大小、页码、PDF 页眉/页脚等更结构化和丰富的信息。
from langchain_community.document_loaders import PDFMinerPDFasHTMLLoaderloader = PDFMinerPDFasHTMLLoader("example_data/layout-parser-paper.pdf")data = loader.load()[0] # 整个 PDF 作为单个 Document 加载from bs4 import BeautifulSoup
soup = BeautifulSoup(data.page_content,'html.parser')
content = soup.find_all('div')import re
cur_fs = None
cur_text = ''
snippets = [] # 首先收集所有具有相同字体大小的片段
for c in content:
sp = c.find('span')
if not sp:
continue
st = sp.get('style')
if not st:
continue
fs = re.findall('font-size:(\d+)px',st)
if not fs:
continue
fs = int(fs[0])
if not cur_fs:
cur_fs = fs
if fs == cur_fs:
cur_text += c.text
else:
snippets.append((cur_text,cur_fs))
cur_fs = fs
cur_text = c.text
snippets.append((cur_text,cur_fs))
# 注意:上面的逻辑非常直接。也可以添加更多策略,例如移除重复的片段(因为 PDF 中的
# 页眉/页脚会出现在多个页面上,所以如果我们发现重复,可以安全地认为它是冗余信息)from langchain_community.docstore.document import Document
cur_idx = -1
semantic_snippets = []
# 假设:标题的字体大小大于其相应内容的字体大小
for s in snippets:
# 如果当前片段的字体大小 > 上一节的标题字体大小 => 这是一个新标题
if not semantic_snippets or s[1] > semantic_snippets[cur_idx].metadata['heading_font']:
metadata={'heading':s[0], 'content_font': 0, 'heading_font': s[1]}
metadata.update(data.metadata)
semantic_snippets.append(Document(page_content='',metadata=metadata))
cur_idx += 1
continue
# 如果当前片段的字体大小 <= 上一节的内容字体大小 => 内容属于同一节(如果需要,也可以
# 为子节创建树状结构,但这可能需要更多思考且可能与数据相关)
if not semantic_snippets[cur_idx].metadata['content_font'] or s[1] <= semantic_snippets[cur_idx].metadata['content_font']:
semantic_snippets[cur_idx].page_content += s[0]
semantic_snippets[cur_idx].metadata['content_font'] = max(s[1], semantic_snippets[cur_idx].metadata['content_font'])
continue
# 如果当前片段的字体大小 > 上一节的内容字体大小但小于上一节的标题字体大小,那么也创建
# 一个新节(例如 PDF 的标题将具有最大的字体大小,但我们不希望它包含所有节)
metadata={'heading':s[0], 'content_font': 0, 'heading_font': s[1]}
metadata.update(data.metadata)
semantic_snippets.append(Document(page_content='',metadata=metadata))
cur_idx += 1semantic_snippets[4]Document(page_content='Recently, various DL models and datasets have been developed for layout analysis\ntasks. ...', metadata={'heading': '2 Related Work\n', 'content_font': 9, 'heading_font': 11, 'source': 'example_data/layout-parser-paper.pdf'})PyPDF 目录
从目录加载 PDF
from langchain_community.document_loaders import PyPDFDirectoryLoaderloader = PyPDFDirectoryLoader("example_data/")docs = loader.load()使用 PDFPlumber
与 PyMuPDF 类似,输出的 Documents 包含关于 PDF 及其页面的详细元数据,并且每页返回一个文档。
from langchain_community.document_loaders import PDFPlumberLoaderloader = PDFPlumberLoader("example_data/layout-parser-paper.pdf")data = loader.load()data[0]Document(page_content='LayoutParser: A Unified Toolkit for Deep\nLearning Based Document Image Analysis\n...', metadata={'source': 'example_data/layout-parser-paper.pdf', 'file_path': 'example_data/layout-parser-paper.pdf', 'page': 1, 'total_pages': 16, ...})使用 AmazonTextractPDFParser
AmazonTextractPDFLoader 调用 Amazon Textract 服务 (opens in a new tab) 将 PDF 转换为 Document 结构。该加载器目前进行纯 OCR,更多功能(如布局支持)正在计划中,取决于需求。支持单页和多页文档,最多 3000 页和 512 MB 大小。
为了使调用成功,需要一个 AWS 账户,类似于 AWS CLI (opens in a new tab) 的要求。
除了 AWS 配置外,它与其他 PDF 加载器非常相似,同时还支持 JPEG、PNG 和 TIFF 以及非原生 PDF 格式。
from langchain_community.document_loaders import AmazonTextractPDFLoader
loader = AmazonTextractPDFLoader("example_data/alejandro_rosalez_sample-small.jpeg")
documents = loader.load()使用 AzureAIDocumentIntelligenceLoader
Azure AI 文档智能 (opens in a new tab)(以前称为 Azure Form Recognizer)是基于机器学习的服务,用于从数字或扫描的 PDF、图像、Office 和 HTML 文件中提取文本(包括手写)、表、文档结构(例如标题、节标题等)和键值对。文档智能支持 PDF、JPEG/JPG、PNG、BMP、TIFF、HEIF、DOCX、XLSX、PPTX 和 HTML。
这个使用 文档智能 的当前实现 (opens in a new tab)可以逐页合并内容并将其转换为 LangChain 文档。默认的输出格式是 markdown,可以轻松地与 MarkdownHeaderTextSplitter 链接以进行语义文档分块。您还可以使用 mode="single" 或 mode="page" 来返回纯文本,一个页面或根据页面拆分的文档。
前提条件
在 3 个预览区域之一拥有 Azure AI 文档智能资源:East US、West US2、West Europe - 如果没有,请参考此文档 (opens in a new tab) 创建一份。您将作为参数传递 <endpoint> 和 <key> 给加载器。
%pip install --upgrade --quiet langchain langchain-community azure-ai-documentintelligence
from langchain_community.document_loaders import AzureAIDocumentIntelligenceLoader
file_path = "<filepath>"
endpoint = "<endpoint>"
key = "<key>"
loader = AzureAIDocumentIntelligenceLoader(
api_endpoint=endpoint, api_key=key, file_path=file_path, api_model="prebuilt-layout"
)
documents = loader.load()使用 UpstageLayoutAnalysisLoader
UpstageLayoutAnalysisLoader 调用 Upstage Layout Analysis API (opens in a new tab) 来检测文档元素,包括来自各种文档格式的表格和图形。该加载器使用纯 OCR 提取文本信息并检测文档中的元素,如 JPEG、PNG、BMP、PDF、TIFF 和 HEIC 文件。对于数字生成的 PDF 文档,用户可以选择放弃 OCR,并通过设置 use_ocr=False 来利用文件中的文本信息,这是默认值。支持单页和多页文档,当 use_ocr=True 时限制为 100 页和 50 MB 文件大小,而 use_ocr=False 时没有限制(仅适用于 PDF 文件)。
前提条件
要访问 Upstage Layout Analysis API,您需要一个 API 访问令牌。请参考提供的快速入门指南 (opens in a new tab) 获取访问令牌并开始使用 Upstage Layout Analysis API。
pip install langchain_upstage示例
import os
os.environ["UPSTAGE_DOCUMENT_AI_API_KEY"] = "YOUR_API_KEY"
from langchain_upstage import UpstageLayoutAnalysisLoader
file_path = "/PATH/TO/FILE.pdf"
loader = UpstageLayoutAnalysisLoader(file_path)
data = loader.load()