高效处理长文本:从PDF中提取关键信息的策略与实现

引言

在处理长文本文件(如PDF)时,我们经常会遇到文本超出语言模型(LLM)上下文窗口的问题。本文旨在探讨解决此问题的两种有效策略:通过强力分块和检索增强生成(RAG)方法来提取内容。我们将提供详细的指导和代码示例,帮助您在不同场景下选择合适的方法。

主要内容

1. 强力分块(Brute Force)

强力分块是将长文档拆分为多个块,每个块的大小适合LLM的上下文窗口,然后从每个块中提取内容。此方法简单直接,但需要注意信息跨块丢失的风险。

2. RAG方法

RAG方法先将文档分块并索引,只从相关性高的分块中提取内容。此方法可以减少无关信息的处理,从而提高效率,适合于内容密集的文档。

代码示例

设置环境与数据

首先,我们需要下载一个示例数据,如Wikipedia上的汽车文章,并加载为LangChain文档。

import re
import requests
from langchain_community.document_loaders import BSHTMLLoader

# 下载内容
response = requests.get("https://en.wikipedia.org/wiki/Car")
# 将内容写入文件
with open("car.html", "w", encoding="utf-8") as f:
    f.write(response.text)
# 使用HTML解析器加载文档
loader = BSHTMLLoader("car.html")
document = loader.load()[0]
# 清理文本
document.page_content = re.sub("\n\n+", "\n", document.page_content)

print(len(document.page_content))

定义信息提取的Schema

使用Pydantic定义我们需要提取的信息结构,例如历史上的关键发展事件。

from typing import List
from langchain_core.pydantic_v1 import BaseModel, Field

class KeyDevelopment(BaseModel):
    year: int = Field(..., description="发生重大历史发展的年份。")
    description: str = Field(..., description="该年发生了什么事件?")
    evidence: str = Field(..., description="从文章中提取信息的原句。")

class ExtractionData(BaseModel):
    key_developments: List[KeyDevelopment]

强力分块方法实现

将文档分成适合LLM处理的块。

from langchain_text_splitters import TokenTextSplitter

text_splitter = TokenTextSplitter(chunk_size=2000, chunk_overlap=20)
texts = text_splitter.split_text(document.page_content)

# 限制为前3个块以便快速运行
first_few = texts[:3]

extractions = extractor.batch([{"text": text} for text in first_few],
                              {"max_concurrency": 5})  # 并行处理

# 合并结果
key_developments = []
for extraction in extractions:
    key_developments.extend(extraction.key_developments)

print(key_developments[:10])

RAG方法实现

使用向量存储来实现RAG方法。

from langchain_community.vectorstores import FAISS
from langchain_core.runnables import RunnableLambda
from langchain_openai import OpenAIEmbeddings

texts = text_splitter.split_text(document.page_content)
vectorstore = FAISS.from_texts(texts, embedding=OpenAIEmbeddings())

retriever = vectorstore.as_retriever(search_kwargs={"k": 1})
rag_extractor = {
    "text": retriever | (lambda docs: docs[0].page_content)
} | extractor

results = rag_extractor.invoke("Key developments associated with cars")

for key_development in results.key_developments:
    print(key_development)

常见问题和解决方案

  • 块间信息丢失:在强力分块中,若信息分布在多个块中,可能导致提取不完整。可以通过增加块的重叠部分来缓解。
  • 重复提取:大块重叠可能导致信息重复提取,需要进行去重处理。
  • LLM生成错误数据:特别是在大文本中寻找单一事实时,可能会得到错误生成的数据,适当的上下文管理是关键。

总结和进一步学习资源

长文本处理是文本分析中的一项重要挑战。无论是选择强力分块还是RAG方法,都需要根据应用场景来权衡选择。推荐进一步学习LangChain和Pydantic的文档以获得更深刻的理解。

参考资料

  1. LangChain Documentation
  2. Pydantic Documentation

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

—END—

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值