LangChain - 文档加载

news2024/11/27 21:06:00

文章目录

    • 一、关于 检索
    • 二、文档加载器
      • 入门指南
    • 三、CSV
      • 1、使用每个文档一行的 CSV 数据加载
      • 2、自定义 csv 解析和加载
      • 3、指定用于标识文档来源的列
    • 四、文件目录 file_directory
      • 1、加载文件目录数据
      • 2、显示进度条 (tqdm
      • 3、使用多线程 use_multithreading
      • 4、更改加载器类
      • 5、使用 TextLoader 自动检测文件编码
        • A. 默认行为
        • B. 静默失败
        • C. 自动检测编码
    • 五、HTML
      • 1、加载 html
      • 2、使用 BeautifulSoup4 加载 HTML
    • 六、JSON
      • 1、使用 jq 加载数据
      • 2、使用 JSONLoader
      • 3、提取元数据 (Extracting metadata)
      • 4、`metadata_func`
      • 5、jq schema 中常见的 JSON 结构
    • 七、Markdown
      • 保留元素(Retain Elements)
    • 八、PDF
      • 1、使用 PyPDF
      • 2、使用 MathPix
      • 3、Using Unstructured
      • 4、保留元素 (Retain Elements)
      • 4、使用 Unstructured 获取远程 PDF
      • 5、使用 PyPDFium2
      • 6、使用 PDFMiner
        • 使用 PDFMiner 生成 HTML 文本
      • 7、使用 PyMuPDF
      • 8、PyPDF 目录
      • 9、使用 pdfplumber


一、关于 检索

许多LLM应用程序需要用户特定数据,这些数据不是模型的训练集的一部分。
完成这一任务的主要方法是通过检索增强生成(RAG)。
在此过程中,检索外部数据,然后在生成步骤中将其传递给LLM。

LangChain为RAG应用程序提供了所有的构建模块 - 从简单到复杂。
本文档部分涵盖了与检索步骤相关的所有内容,例如数据的获取。
虽然听起来很简单,但可能有微妙的复杂性. 这涵盖了几个关键模块。


在这里插入图片描述


文档加载器

从许多不同来源加载文档. LangChain提供了100多种不同的文档加载器,并与空间中的其他主要提供商(如AirByte和Unstructured)集成。
我们提供了加载各种类型文档(HTML、PDF、代码)的集成,从各种位置(私人S3存储桶、公共网站)加载。


文档转换器

检索的一个关键部分是仅获取文档的相关部分,为了最好地准备文档以进行检索,这涉及几个转换步骤,其中一个主要步骤是 将大型文档分割(或分块)为较小的块
LangChain提供了几种不同的算法来完成此操作,以及针对特定文档类型(代码、markdown等)进行优化的逻辑.


文本嵌入模型

检索的另一个关键部分是 为文档创建嵌入。
嵌入捕捉文本的语义含义,使您能够 快速高效地查找其他相似的文本。
LangChain与25多个不同的嵌入提供商和方法进行集成, 从开源到专有API, 使您能够选择最适合您需求的一种。
LangChain提供了标准接口,使您可以轻松切换模型。


向量存储

随着嵌入的兴起,出现了对支持这些嵌入的数据库的需求。
LangChain与50多个不同的向量存储进行集成,从开源本地存储到云托管专有存储, 使您能够选择最适合您需求的一种。
LangChain公开了标准接口,使您可以轻松切换向量存储。


检索器

一旦数据在数据库中,您仍然需要检索它。
LangChain支持许多不同的检索算法,并且是我们增加最多价值的地方之一。
我们支持 易于入门的基本方法 - 即简单的语义搜索。
但是,我们还添加了一系列算法以提高性能,这些算法包括:

  • 父文档检索器: 允许您为每个父文档 创建 多个嵌入,允许您查找较小的块 但返回较大的上下文。
  • 自查询检索器: 用户的问题通常包含 对不仅仅是语义的东西的引用,而是表达一些 最好用元数据过滤器 表示的逻辑。
    自查询允许您从查询中解析出语义 部分和查询中存在的其他元数据过滤器
  • 集合检索器: 有时您可能希望 从 多个不同的来源 或 使用多个不同的算法 检索文档。
    集合检索器使您可以轻松实现此目的。


二、文档加载器

前往Integrations 以获取与第三方工具 集成的内置文档 加载器 的文档。

使用文档加载器从源加载数据作为Document
Document是一段文本和相关元数据。
例如,有用于加载简单的.txt文件的文档加载器,用于加载任何网页的文本内容,甚至用于加载YouTube视频的转录稿。

文档加载器提供了一个“load”方法,用于从配置的源加载数据作为文档。
它们还可以选择实现“延迟加载”,以便将数据惰性加载到内存中。


入门指南

最简单的加载器将文件作为文本读入,并将其全部放入一个文档中。

from langchain.document_loaders import TextLoader

loader = TextLoader("./index.md")
loader.load()

[
    Document(
      page_content='---\nsidebar_position: 0\n---\n# Document loaders\n\nUse document loaders to load data from a source as `Document`\'s. ... They optionally implement:\n\n3. "Lazy load": load documents into memory lazily\n', 
      metadata={'source': '../docs/docs_skeleton/docs/modules/data_connection/document_loaders/index.md'})
]


三、CSV

逗号分隔值(CSV) 文件是一种使用逗号分隔值的定界文本文件。
文件的每一行是一个数据记录;每个记录由一个或多个字段组成,字段之间用逗号分隔。


1、使用每个文档一行的 CSV 数据加载

from langchain.document_loaders.csv_loader import CSVLoader

loader = CSVLoader(file_path='./example_data/mlb_teams_2012.csv')
data = loader.load()

print(data)

    [Document(page_content='Team: Nationals\n"Payroll (millions)": 81.34\n"Wins": 98', lookup_str='', metadata={'source': './example_data/mlb_teams_2012.csv', 'row': 0}, lookup_index=0), 
    ...
    Document(page_content='Team: Astros\n"Payroll (millions)": 60.65\n"Wins": 55', lookup_str='', metadata={'source': './example_data/mlb_teams_2012.csv', 'row': 29}, lookup_index=0)]


2、自定义 csv 解析和加载

参见 csv 模块 文档,了解支持的 csv 参数的更多信息。

loader = CSVLoader(file_path='./example_data/mlb_teams_2012.csv', csv_args={
    'delimiter': ',',
    'quotechar': '"',
    'fieldnames': ['MLB Team', 'Payroll in millions', 'Wins']
})

data = loader.load()

print(data)

    [Document(
      page_content='MLB Team: Team\nPayroll in millions: "Payroll (millions)"\nWins: "Wins"', 
      lookup_str='', 
      metadata={'source': './example_data/mlb_teams_2012.csv', 'row': 0}, 
      lookup_index=0), 
    ...
    Document(
    		page_content='MLB Team: Astros\nPayroll in millions: 60.65\nWins: 55', 
    		lookup_str='', 
    		metadata={'source': './example_data/mlb_teams_2012.csv', 'row': 30}, 
    		lookup_index=0)]


3、指定用于标识文档来源的列

使用 source_column 参数指定从每一行创建的文档的来源。
否则,file_path 将作为从 CSV 文件创建的所有文档的来源。

在使用基于来源回答问题的链时,这非常有用。

loader = CSVLoader(file_path='./example_data/mlb_teams_2012.csv', source_column="Team")

data = loader.load()

data :

    [Document(page_content='Team: Nationals\n"Payroll (millions)": 81.34\n"Wins": 98', lookup_str='', metadata={'source': 'Nationals', 'row': 0}, lookup_index=0), 
    ...
    Document(page_content='Team: Astros\n"Payroll (millions)": 60.65\n"Wins": 55', lookup_str='', metadata={'source': 'Astros', 'row': 29}, lookup_index=0)]


四、文件目录 file_directory

这里介绍了如何加载目录中的所有文档。

在底层,默认情况下使用 UnstructuredLoader

我们可以使用 glob 参数来控制要加载的文件。

请注意,这里不加载 .rst 文件或 .html文件。


1、加载文件目录数据

from langchain.document_loaders import DirectoryLoader
loader = DirectoryLoader('../', glob="**/*.md")
docs = loader.load()
len(docs) # -> 1

2、显示进度条 (tqdm

默认情况下,不会显示进度条。
要显示进度条,请安装 tqdm 库(如 pip install tqdm),并将 show_progress 参数设置为 True

loader = DirectoryLoader('../', glob="**/*.md", show_progress=True)
docs = loader.load()

    Requirement already satisfied: tqdm in /Users/jon/.pyenv/versions/3.9.16/envs/microbiome-app/lib/python3.9/site-packages (4.65.0)

    0it [00:00, ?it/s]


3、使用多线程 use_multithreading

默认情况下,加载操作在 一个线程 中进行。
为了利用多个线程,将 use_multithreading标志设置为 True。

loader = DirectoryLoader('../', glob="**/*.md", use_multithreading=True)
docs = loader.load() 


4、更改加载器类

默认情况下使用 UnstructuredLoader 类。但是,您可以相当容易地 更改加载器的类型。

from langchain.document_loaders import TextLoader

loader = DirectoryLoader('../', glob="**/*.md", loader_cls=TextLoader)

docs = loader.load()
len(docs)
# -> 1

如果需要加载 Python 源代码文件,请使用 PythonLoader

from langchain.document_loaders import PythonLoader
loader = DirectoryLoader('../../../../../', glob="**/*.py", loader_cls=PythonLoader)
docs = loader.load()
len(docs)
# ->  691

5、使用 TextLoader 自动检测文件编码

在这个示例中,我们将看到一些在使用 TextLoader 类从目录加载一系列任意文件时可能有用的策略。

首先为了说明问题,让我们尝试加载多个具有任意编码的文本。

path = '../../../../../tests/integration_tests/examples'
loader = DirectoryLoader(path, glob="**/*.txt", loader_cls=TextLoader)


A. 默认行为
loader.load()

<pre style="white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"><span style="color: #800000; text-decoration-color: #800000">╭─────────────────────────────── </span><span style="color: #800000; text-decoration-color: #800000; font-weight: bold">Traceback </span><span style="color: #bf7f7f; text-decoration-color: #bf7f7f; font-weight: bold">(most recent call last)</span><span style="color: #800000; text-decoration-color: #800000"> ────────────────────────────────╮</span>
<span style="color: #800000; text-decoration-color: #800000"></span>  

...
<span style="color: #800000; text-decoration-color: #800000">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</span>
<span style="color: #ff0000; text-decoration-color: #ff0000; font-weight: bold">RuntimeError: </span>Error loading ..<span style="color: #800080; text-decoration-color: #800080">/../../../../tests/integration_tests/examples/</span><span style="color: #ff00ff; text-decoration-color: #ff00ff">example-non-utf8.txt</span>
</pre>

文件 example-non-utf8.txt 使用了不同的编码,load() 函数会失败,并显示一条有用的消息指示哪个文件解码失败。

使用 TextLoader 的默认行为,任何一个文档加载失败,整个加载过程都将失败,并且不会加载任何文档。


B. 静默失败

我们可以将参数 silent_errors 传递给 DirectoryLoader,以跳过无法加载的文件并继续加载过程。

loader = DirectoryLoader(path, glob="**/*.txt", loader_cls=TextLoader, silent_errors=True)
docs = loader.load()

    Error loading ../../../../../tests/integration_tests/examples/example-non-utf8.txt

doc_sources = [doc.metadata['source']  for doc in docs]
doc_sources

    ['../../../../../tests/integration_tests/examples/whatsapp_chat.txt',
     '../../../../../tests/integration_tests/examples/example-utf8.txt']

C. 自动检测编码

我们也可以 在失败前,使用 TextLoader 来自动检测文件编码。传递 autodetect_encoding 来加载这个类。

text_loader_kwargs={'autodetect_encoding': True}

loader = DirectoryLoader(path, 
				glob="**/*.txt", 
				loader_cls=TextLoader, 
				loader_kwargs=text_loader_kwargs)
				
docs = loader.load()
doc_sources = [doc.metadata['source']  for doc in docs]

doc_sources :

    ['../../../../../tests/integration_tests/examples/example-non-utf8.txt',
     '../../../../../tests/integration_tests/examples/whatsapp_chat.txt',
     '../../../../../tests/integration_tests/examples/example-utf8.txt']

五、HTML

超文本标记语言或 HTML 是用于在 Web 浏览器中显示的文档的标准标记语言。


1、加载 html

这部分介绍如何将 HTML 文档加载到 我们可以在下游使用的文档格式中。

from langchain.document_loaders import UnstructuredHTMLLoader
loader = UnstructuredHTMLLoader("example_data/fake-content.html")
data = loader.load()

data :

    [Document(page_content='My First Heading\n\nMy first paragraph.', lookup_str='', metadata={'source': 'example_data/fake-content.html'}, lookup_index=0)]

2、使用 BeautifulSoup4 加载 HTML

我们还可以使用 BeautifulSoup4 使用 BSHTMLLoader 加载 HTML 文档。
这将提取 HTML 中的文本到 page_content,并将页面标题作为 metadatatitle

from langchain.document_loaders import BSHTMLLoader
loader = BSHTMLLoader("example_data/fake-content.html")
data = loader.load()

data :

    [Document(page_content='\n\nTest Title\n\n\nMy First Heading\nMy first paragraph.\n\n\n', metadata={'source': 'example_data/fake-content.html', 'title': 'Test Title'})]

六、JSON

JSON (JavaScript Object Notation) 是一种开放标准的文件格式和数据交换格式,存储和传输方便,且可读。

JSON 对象由属性 key - 值 value 对和数组(或其他可序列化值)组成的数据对象。


1、使用 jq 加载数据

JSONLoader 使用指定的 jq schema 来解析 JSON 文件。

它使用 jq python 包。 查看这个 手册 来详细了解 jq 语法。

pip install jq

import json
from pathlib import Path
from pprint import pprint

from langchain.document_loaders import JSONLoader

file_path='./example_data/facebook_chat.json'
data = json.loads(Path(file_path).read_text())

data :

    {'image': 
    		{'creation_timestamp': 1675549016, 'uri': 'image_of_the_chat.jpg'},
     'is_still_participant': True,
     'joinable_mode': {'link': '', 'mode': 1},
     'magic_words': [],
     'messages': [{'content': 'Bye!',
                   'sender_name': 'User 2',
                   'timestamp_ms': 1675597571851},
                  ...
                  {'content': 'Hi! Im interested in your bag. Im offering $50. Let me know if you are interested. Thanks!',
                   'sender_name': 'User 1',
                   'timestamp_ms': 1675549022673}],
     'participants': [{'name': 'User 1'}, {'name': 'User 2'}],
     'thread_path': 'inbox/User 1 and User 2 chat',
     'title': 'User 1 and User 2 chat'}


2、使用 JSONLoader

假设我们有兴趣提取 JSON 数据中 messages 键下的 content 字段的值。
通过以下示例可以轻松完成这项工作。

loader = JSONLoader(
    file_path='./example_data/facebook_chat.json',
    jq_schema='.messages[].content')

data = loader.load()

data :

    [Document(page_content='Bye!', 
    					metadata={'source': '/Users/xx/facebook_chat.json', 
    					'seq_num': 1}),
    ...
     Document(page_content='Hi! Thanks!', 
     					metadata={'source': '/Users/xx/facebook_chat.json', 'seq_num': 11})]


3、提取元数据 (Extracting metadata)

通常,我们希望将 JSON 文件中的元数据包含到从内容创建的文档中。

下面演示了如何使用 JSONLoader 提取元数据。

需要注意一些关键的更改。在前一个示例中,我们没有收集元数据,在模式中直接指定了 page_content 的值的提取位置。

.messages[].content

在当前示例中,我们必须告诉加载器迭代 messages 字段中的记录。
因此,jq_schema 必须是以下形式:

.messages[]

这样我们就可以将记录(字典)传递给必须实现的 metadata_func
metadata_func负责确定哪些记录中的信息应该包含在最终 Document 对象中的元数据中。

此外,现在我们必须通过加载器显式指定 content_key 参数,用于从记录中提取 page_content 的值的键。

Define the metadata extraction function.
def metadata_func(record: dict, metadata: dict) -> dict:

    metadata["sender_name"] = record.get("sender_name")
    metadata["timestamp_ms"] = record.get("timestamp_ms")

    return metadata

loader = JSONLoader(
    file_path='./example_data/facebook_chat.json',
    jq_schema='.messages[]',
    content_key="content",
    metadata_func=metadata_func
)

data = loader.load()

data :

    [Document(page_content='Bye!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1, 'sender_name': 'User 2', 'timestamp_ms': 1675597571851}),
    ...
     Document(page_content='Hi! Im interested in your bag. Im offering $50. Let me know if you are interested. Thanks!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 11, 'sender_name': 'User 1', 'timestamp_ms': 1675549022673})]

现在,您将看到文档包含与我们提取的内容相关联的元数据。


4、metadata_func

如上所示,metadata_func 接受 JSONLoader 生成的默认元数据。这允许用户完全控制元数据的格式。

例如,默认元数据包含 sourceseq_num 键。
然而,JSON 数据中可能也包含这些键。
用户可以利用 metadata_func 重命名默认键并使用 JSON 数据中的键。

下面的示例展示了如何修改 source,只包含与 langchain 目录相关的文件来源信息。

Define the metadata extraction function.
def metadata_func(record: dict, metadata: dict) -> dict:

    metadata["sender_name"] = record.get("sender_name")
    metadata["timestamp_ms"] = record.get("timestamp_ms")

    if "source" in metadata:
        source = metadata["source"].split("/")
        source = source[source.index("langchain"):]
        metadata["source"] = "/".join(source)

    return metadata

loader = JSONLoader(
    file_path='./example_data/facebook_chat.json',
    jq_schema='.messages[]',
    content_key="content",
    metadata_func=metadata_func
)

data = loader.load()

data :

    [Document(page_content='Bye!', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1, 'sender_name': 'User 2', 'timestamp_ms': 1675597571851}),
    ...
     Document(page_content='Hi! Im interested in your bag. Im offering $50. Let me know if you are interested. Thanks!', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 11, 'sender_name': 'User 1', 'timestamp_ms': 1675549022673})]

5、jq schema 中常见的 JSON 结构

下面的列表提供了 用户可以根据结构 从 JSON 数据中 提取内容时 使用的可能的 jq_schema 的参考。

JSON        -> [{"text": ...}, {"text": ...}, {"text": ...}]
jq_schema   -> ".[].text"

JSON        -> {"key": [{"text": ...}, {"text": ...}, {"text": ...}]}
jq_schema   -> ".key[].text"

JSON        -> ["...", "...", "..."]
jq_schema   -> ".[]"



七、Markdown

Markdown 是一种轻量级标记语言,用于使用纯文本编辑器创建格式化文本。

这部分内容介绍了如何将 Markdown 文档 加载到我们可以在应用程序中 要使用的文档格式中。

! pip install unstructured > /dev/null

from langchain.document_loaders import UnstructuredMarkdownLoader
markdown_path = "../../../../../README.md"
loader = UnstructuredMarkdownLoader(markdown_path)
data = loader.load()

data :

    [Document(page_content=\x9f¦\x9cï¸\x8fð\x9f\x97 LangChain\n\nâ\x9a¡ Building applications with LLMs through composability â\x9a¡\n\nLooking for the JS/TS version? Check out LangChain.js.\n\nProduction Support: As you move your LangChains into production, we'd love to offer more comprehensive support.
    ...
    Evaluation:\n\n[BETA] Generative models are notoriously hard to evaluate with traditional metrics.  ... For detailed information on how to contribute, see here.", metadata={'source': '../../../../../README.md'})]


保留元素(Retain Elements)

在底层,Unstructured 为不同的文本块创建不同的“元素”。
默认情况下,我们将它们组合在一起,但通过指定 mode="elements" 可以轻松保留该分离。

loader = UnstructuredMarkdownLoader(markdown_path, mode="elements")
data = loader.load()

data[0]

    Document(page_content='ð\x9f¦\x9cï¸\x8fð\x9f”\x97 LangChain', metadata={'source': '../../../../../README.md', 'page_number': 1, 'category': 'Title'})


八、PDF

便携式文档格式(PDF),标准化为 ISO 32000,是 Adobe 于 1992 年开发的一种文件格式,用于以与应用软件、硬件和操作系统无关的方式呈现文档,包括文本格式和图像。

这涵盖了如何将 PDF 文档加载到我们在下游使用的 Document 格式中。


1、使用 PyPDF

使用 pypdf 将 PDF 加载到文档数组中,其中每个文档包含页面内容和元数据,以及 page 号码。

pip install pypdf

from langchain.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
    ...
    Introduction\nDeep Learning(DL)-based approaches are the state-of-the-art for a wide range of\ndocument image analysis (DIA) tasks including document image classi\x0ccation [ 11,arXiv:2103.15348v2  [cs.CV]  21 Jun 2021', metadata={'source': 'example_data/layout-parser-paper.pdf', 'page': 0})

这种方法的优点是可以通过页面号码检索文档。

我们想使用 OpenAIEmbeddings,所以我们需要获取 OpenAI API 密钥。

import os
import getpass

os.environ['OPENAI_API_KEY'] = getpass.getpass('OpenAI API Key:')

    OpenAI API Key: ········

from langchain.vectorstores import FAISS
from langchain.embeddings.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.
    Fig. 4: Illustration of (a) the original historical Japanese document with layout
    detection results and (b) a recreated version of the document image that achieves
    much better character recognition recall. The reorganization algorithm rearranges
    the tokens based on the their detect
    3: 4 Z. Shen et al.
    Efficient Data AnnotationC u s t o m i z e d  M o d e l  T r a i n i n gModel Cust omizationDI A Model HubDI A Pipeline SharingCommunity PlatformLa y out Detection ModelsDocument Images 
    T h e  C o r e  L a y o u t P a r s e r  L i b r a r yOCR ModuleSt or age & VisualizationLa y ou


2、使用 MathPix

受 Daniel Gross 的 https://gist.github.com/danielgross/3ab4104e14faccc12b49200843adab21 的启发

from langchain.document_loaders import MathpixPDFLoader

loader = MathpixPDFLoader("example_data/layout-parser-paper.pdf")
data = loader.load()

3、Using Unstructured

from langchain.document_loaders import UnstructuredPDFLoader
loader = UnstructuredPDFLoader("example_data/layout-parser-paper.pdf")
data = loader.load()

4、保留元素 (Retain Elements)

在内部,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
    ...
    Introduction\nDeep Learning(DL)-based approaches are the state-of-the-art for a wide range of\ndocument image analysis (DIA) tasks including document image classification [11,\narXiv:2103.15348v2  [cs.CV]  21 Jun 2021\n', lookup_str='', metadata={'file_path': 'example_data/layout-parser-paper.pdf', 'page_number': 1, 'total_pages': 16, 'format': 'PDF 1.5', 'title': '', 'author': '', 'subject': '', 'keywords': '', 'creator': 'LaTeX with hyperref', 'producer': 'pdfTeX-1.40.21', 'creationDate': 'D:20210622012710Z', 'modDate': 'D:20210622012710Z', 'trapped': '', 'encryption': None}, lookup_index=0)


4、使用 Unstructured 获取远程 PDF

这涵盖了如何将在线 PDF 加载到我们可以在下游使用的文档格式中。这可用于各种在线 PDF 网站,如 https://open.umn.edu/opentextbooks/textbooks/和https://arxiv.org/archive/

注意:所有其他 PDF 加载器也可用于获取远程 PDF,但 OnlinePDFLoader 是一个旧版本函数,专门与 UnstructuredPDFLoader 配合使用。

from langchain.document_loaders import OnlinePDFLoader
loader = OnlinePDFLoader("https://arxiv.org/pdf/2302.03803.pdf")
data = loader.load()

data

    [Document(page_content='A WEAK ( k, k ) -LEFSCHETZ THEOREM FOR PROJECTIVE TORIC ORBIFOLDS\n\nWilliam D. Montoya\n\nInstituto de Matem´atica, Estat´ıstica e Computa¸c˜ao Cient´ıfica,
    ...
    Cohomology of complete intersections in toric varieties. Pub-', lookup_str='', metadata={'source': '/var/folders/ph/hhm7_zyx4l13k3v8z02dwp1w0000gn/T/tmpgq0ckaja/online_file.pdf'}, lookup_index=0)]


5、使用 PyPDFium2

from langchain.document_loaders import PyPDFium2Loader

loader = PyPDFium2Loader("example_data/layout-parser-paper.pdf")

data = loader.load()

6、使用 PDFMiner

from langchain.document_loaders import PDFMinerLoader
loader = PDFMinerLoader("example_data/layout-parser-paper.pdf")
data = loader.load()

使用 PDFMiner 生成 HTML 文本

这对于将文本语义分块到部分中非常有用,因为输出的 HTML 内容可以通过 BeautifulSoup 解析,以获取有关字体大小、页码、PDF 标题/页脚等更结构化和丰富的信息。

from langchain.document_loaders import PDFMinerPDFasHTMLLoader

loader = PDFMinerPDFasHTMLLoader("example_data/layout-parser-paper.pdf")

data = loader.load()[0]   # entire pdf is loaded as a single 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 = []   # first collect all snippets that have the same font size
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))
# Note: The above logic is very straightforward. One can also add more strategies such as removing duplicate snippets (as
# headers/footers in a PDF appear on multiple pages so if we find duplicatess safe to assume that it is redundant info)

from langchain.docstore.document import Document
cur_idx = -1
semantic_snippets = []
# Assumption: headings have higher font size than their respective content
for s in snippets:
    # if current snippet's font size > previous section's heading => it is a new heading
    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 current snippet's font size <= previous section's content => content belongs to the same section (one can also create
    # a tree like structure for sub sections if needed but that may require some more thinking and may be data specific)
    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
    
    # if current snippet's font size > previous section's content but less tha previous section's heading than also make a new 
    # section (e.g. title of a pdf will have the highest font size but we don't want it to subsume all sections)
    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

semantic_snippets[4]

    Document(page_content='Recently, various DL models and datasets have been developed for layout analysis\ntasks. 
    ...
    A spectrum of models\ntrained on these datasets are currently available in the LayoutParser model zoo\nto support different use cases.\n', 
    metadata={'heading': '2 Related Work\n', 'content_font': 9, 'heading_font': 11, 'source': 'example_data/layout-parser-paper.pdf'})


7、使用 PyMuPDF

这是 PDF 解析选项中最快的,并且包含有关 PDF 及其页面的详细元数据,以及每个页面返回一个文档。

from langchain.document_loaders import PyMuPDFLoader

loader = 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...
    Open Source library · Toolkit.\n1\nIntroduction\nDeep Learning(DL)-based approaches are the state-of-the-art for a wide range of\ndocument image analysis (DIA) tasks including document image classification [11,\narXiv:2103.15348v2  [cs.CV]  21 Jun 2021\n', lookup_str='', metadata={'file_path': 'example_data/layout-parser-paper.pdf', 'page_number': 1, 'total_pages': 16, 'format': 'PDF 1.5', 'title': '', 'author': '', 'subject': '', 'keywords': '', 'creator': 'LaTeX with hyperref', 'producer': 'pdfTeX-1.40.21', 'creationDate': 'D:20210622012710Z', 'modDate': 'D:20210622012710Z', 'trapped': '', 'encryption': None}, lookup_index=0)

此外,您可以将 PyMuPDF 文档 中的任何选项作为关键字参数传递给 load 调用,并将其传递给 get_text() 调用。


8、PyPDF 目录

从目录加载 PDF

from langchain.document_loaders import PyPDFDirectoryLoader

loader = PyPDFDirectoryLoader("example_data/")

docs = loader.load()

9、使用 pdfplumber

与 PyMuPDF 类似,输出的文档包含有关 PDF 及其页面的详细元数据,并且每个页面返回一个文档。

from langchain.document_loaders import PDFPlumberLoader
loader = 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\nZejiang Shen1 ((cid:0)), Ruochen Zhang2, Melissa Dell3, Benjamin Charles Germain\nLee4, Jacob Carlson3, and Weining Li5\n1 Allen Institute for AI
    ...
    of\ndocumentimageanalysis(DIA)tasksincludingdocumentimageclassification[11,', metadata={'source': 'example_data/layout-parser-paper.pdf', 'file_path': 'example_data/layout-parser-paper.pdf', 'page': 1, 'total_pages': 16, 'Author': '', 'CreationDate': 'D:20210622012710Z', 'Creator': 'LaTeX with hyperref', 'Keywords': '', 'ModDate': 'D:20210622012710Z', 'PTEX.Fullbanner': 'This is pdfTeX, Version 3.14159265-2.6-1.40.21 (TeX Live 2020) kpathsea version 6.3.2', 'Producer': 'pdfTeX-1.40.21', 'Subject': '', 'Title': '', 'Trapped': 'False'})

2024-04-08(一)

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

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

相关文章

通用开发技能系列:Scrum、Kanban等敏捷管理策略

云原生学习路线导航页&#xff08;持续更新中&#xff09; 本文是 通用开发技能系列 文章&#xff0c;主要对编程通用技能 Scrum、Kanban等敏捷管理策略 进行学习 1.什么是敏捷开发 敏捷是一个描述软件开发方法的术语&#xff0c;它强调增量交付、团队协作、持续规划和持续学习…

如何使用生成式人工智能撰写关于新产品发布的文章?

利用生成式人工智能撰写新产品发布文章确实是一种既有创意又高效的内容生成方式。以下是如何做到这一点的指南&#xff0c;附带一些背景信息&#xff1a; • 背景&#xff1a;在撰写文章之前&#xff0c;收集有关您的新产品的信息。这包括产品的名称、类别、特点、优势、目标受…

git 常用命令和使用方法

作者简介&#xff1a; 一个平凡而乐于分享的小比特&#xff0c;中南民族大学通信工程专业研究生在读&#xff0c;研究方向无线联邦学习 擅长领域&#xff1a;驱动开发&#xff0c;嵌入式软件开发&#xff0c;BSP开发 作者主页&#xff1a;一个平凡而乐于分享的小比特的个人主页…

DJ的打碟是什么意思 FL Studio怎么制作打碟的效果

在如今的音乐文化中&#xff0c;DJ打碟已经成为一种重要的表演形式和音乐创作方式。但是&#xff0c;对于许多人来说&#xff0c;仍然会对DJ的打碟到底意味着什么存在疑惑&#xff0c;接下来给大家介绍DJ的打碟是什么意思&#xff0c;FL Studio怎么制作打碟的效果的具体内容。 …

Pentaho Data Integration(kettle)下载

Kettle已然是改了名了&#xff0c;新名字叫Pentaho Data Integration 网上常见的下载地址已经失效&#xff0c;被提示找不到Date Integration目录&#xff1a; https://sourceforge.net/projects/pentaho/files/Data%20Integration/ 点击页面上的pdf&#xff0c;下载文件后打…

基于单片机16路多路抢答器仿真系统设计

**单片机设计介绍&#xff0c;基于单片机16路多路抢答器仿真系统设计 文章目录 一 概要二、功能设计三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机16路多路抢答器仿真系统的设计概要主要涵盖硬件设计、软件编程以及功能实现等方面。以下是针对该设计的详细概…

ABAP 弹出输入框/弹出屏幕选择条件框

简单输入框 代码 DATA:TAB TYPE TABLE OF SVAL WITH HEADER LINE ,CODE TYPE C . TAB-TABNAME ZTAB_XX."表 TAB-FIELDNAME XXXX."字段 TAB-FIELDTEXT 条码扫描 ."说明 APPEND TAB. "弹出填写数据的框 CALL FUNCTION POPUP_GE…

mysql安装初始化(windows)

文章目录 一、下载二、 初始化数据库三、把mysql注册成服务 一、下载 https://downloads.mysql.com/archives/community/ 二、 初始化数据库 mysqld --initialize-insecure初始化完成后&#xff0c;可以开黑框运行数据库 mysqld --console三、把mysql注册成服务 mysqld -…

博士推荐 | 西安交通大学毕业的机械工程博士,EIT认证机械工程师

编辑 / 木子 审核 / 朝阳 伟骅英才 伟骅英才致力于以大数据、区块链、AI人工智能等前沿技术打造开放的人力资本生态&#xff0c;用科技解决职业领域问题&#xff0c;提升行业数字化服务水平&#xff0c;提供创新型的产业与人才一体化服务的人力资源解决方案和示范平台&#x…

webpack5如何关闭全屏错误

1、找到vue.config.js 2、在上面的devServer里面添加如下&#xff1a; client: {overlay: false, // 禁用全局错误提示},

灶具分析:电炉灶(电焰灶)、电磁炉和燃气灶到底哪个好?

在烹饪设备中&#xff0c;电炉灶、电磁炉和燃气灶都是常见的选择。每种设备都有其独特的特点和优势&#xff0c;因此&#xff0c;要决定哪一个更好&#xff0c;需要考虑到个人的需求、预算、烹饪习惯以及家庭环境等因素。下面&#xff0c;下面我将以华火电炉灶为例&#xff0c;…

2024年【道路运输企业主要负责人】报名考试及道路运输企业主要负责人证考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 道路运输企业主要负责人报名考试根据新道路运输企业主要负责人考试大纲要求&#xff0c;安全生产模拟考试一点通将道路运输企业主要负责人模拟考试试题进行汇编&#xff0c;组成一套道路运输企业主要负责人全真模拟考…

【御控物联】 JavaScript JSON结构转换(21):数组To对象——综合应用

文章目录 一、JSON结构转换是什么&#xff1f;二、术语解释三、案例之《JSON数组 To JSON对象》四、代码实现五、在线转换工具六、技术资料 一、JSON结构转换是什么&#xff1f; JSON结构转换指的是将一个JSON对象或JSON数组按照一定规则进行重组、筛选、映射或转换&#xff0…

oracle hang分析使用

oracle hang分析测试 使用hang分析大部分原因在于产生锁资源的争用 1-2:只有hanganalyze输出&#xff0c;不dump任何进程 3&#xff1a;Level2Dump出在IN_HANG状态的进程 4&#xff1a;Level3Dump出在等待链里面的blockers(状态为LLEAF/LEAF_NW/IGN_DMP&#xff09; 5&…

船气废弃锅炉三维仿真vr交互展示降低培训门槛

火化炉是殡葬行业的核心设备&#xff0c;其操作技艺对于专业人才的培养至关重要。然而&#xff0c;传统实践教学受限于时间、场地、设备损耗等多重因素&#xff0c;难以给予学生充分的实操机会。面对这一挑战&#xff0c;我们创新推出了火化炉vr三维仿真培训软件&#xff0c;以…

C语言---浮点数在内存中的存储

前面跟大家介绍了整数在内存中的存储&#xff0c;这次再向大家介绍下浮点数在内存中的存储。 我们常见的浮点数有3.14&#xff0c;1E10 等等&#xff0c;浮点数家族包括float&#xff0c;double&#xff0c;long double类型。 浮点数的表示范围在头文件 float.h 定义。 1.浮…

记录一次hss不能防护主机的问题

场景&#xff1a;hss的控制台显示不在防护中&#xff0c;其他云主机并没有这个情况。 故障发生的时间是昨天下午15点半左右&#xff0c;运维同事做了重启网卡的操作。service network restart 排查分析&#xff1a; 于是仔细的查看日志&#xff0c;发现报错如下&#xff1a…

中颖51芯片学习3. 定时器

中颖51芯片学习3. 定时器 一、SH79F9476定时器简介1. 简介2. 定时器运行模式 二、定时器21. 说明&#xff08;1&#xff09;时钟&#xff08;2&#xff09;工作模式 2. 寄存器&#xff08;1&#xff09;控制寄存器 T2CON&#xff08;2&#xff09;定时器2模式控制寄存器 T2MOD …

【NOI】二叉树的定义与基本性质

文章目录 前言一、二叉树的定义1. 树的定义2. 二叉树的定义 二、满二叉树、完全二叉树和非完全二叉树1.满二叉树2.完全二叉树3.非完全二叉树 三、二叉树的性质性质1: 在二叉树的第i层上至多有2^(i-1)个结点 (i≥1)。性质2: 深度为h的二叉树至多有2^h - 1个结点 (h≥1)。性质3: …

超越基准 | 基于每个高斯变形的3D高斯溅射方法及其高效训练策略

作者&#xff1a;小柠檬 | 来源&#xff1a;3DCV 在公众号「3DCV」后台&#xff0c;回复「原论文」可获取论文pdf 添加微信&#xff1a;dddvision&#xff0c;备注&#xff1a;3D高斯&#xff0c;拉你入群。文末附行业细分群 详细内容请关注3DCV 3D视觉精品课程&#xff1a;…