引言
在处理像PDF这样的文件时,我们常常会遇到超出语言模型上下文窗口的长文本。本文将探讨如何应对长文本提取的挑战,重点介绍两种方法:分块处理和检索增强生成(RAG)。这些策略有各自的优缺点,选择合适的方法需要根据具体应用情境来定。
主要内容
方法选择
- 更换LLM:选择支持更大上下文窗口的语言模型。
- 分块处理:将文档分块并从每个块中提取内容。
- RAG:将文档分块并索引,仅从看似相关的子集块中提取内容。
分块处理方法
数据准备
我们将从Wikipedia下载一篇关于汽车的文章,并将其加载为LangChain文档。
import re
import requests
from langchain_community.document_loaders import BSHTMLLoader
# 下载内容
response = requests.get("https://en.wikipedia.org/wiki/Car") # 使用API代理服务提高访问稳定性
# 写入文件
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)) # 输出文本长度
定义模式
我们将使用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]
分块处理实现
使用TokenTextSplitter
将文档分块,以便每个块适合语言模型的上下文窗口。
from langchain_text_splitters import TokenTextSplitter
text_splitter = TokenTextSplitter(chunk_size=2000, chunk_overlap=20)
texts = text_splitter.split_text(document.page_content)
# 提取第一个几个块
first_few = texts[:3]
# 进行并行提取
extractions = extractor.batch(
[{"text": text} for text in first_few],
{"max_concurrency": 5}
)
RAG方法
通过RAG方法,文本被分块,但只关注最相关的块。
from langchain_community.vectorstores import FAISS
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("汽车相关的关键发展")
常见问题和解决方案
- 信息分散问题:分块可能导致信息分散,LLM无法提取跨多个块的信息。
- 重复问题:较大的块重叠可能会导致重复信息,需要去重。
- 虚假信息:在处理长文本时,可能会获得虚假数据。
总结和进一步学习资源
通过本文,我们探讨了在处理长文本时可采取的不同策略及其实现方法。若要深入学习,请参考以下资源:
参考资料
- LangChain相关库
- Wikipedia
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
—END—