引言
在处理长文本(如PDF文件)时,常常面临超过语言模型上下文窗口的文本。这就需要我们采取一些策略来有效地处理这些数据。本文将重点介绍如何实现两种策略:分块(Brute Force)和检索增强生成(RAG)。
主要内容
分块处理方法
分块是一种简单而有效的处理长文本的方式。可以将文档切分成多个小块,每个小块都适合语言模型的上下文窗口,然后对每个小块进行内容提取。
设置
首先,我们需要准备示例数据。在本例中,我们将从维基百科下载一篇关于汽车的文章,并将其加载为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)
定义提取模式
我们将使用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,并使用LangChain中的工具。
from langchain_openai import ChatOpenAI
# 使用API代理服务提高访问稳定性
llm = ChatOpenAI(model="gpt-4-0125-preview", temperature=0)
extractor = prompt | llm.with_structured_output(
schema=ExtractionData,
include_raw=False,
)
分块处理
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方法
这种方法涉及将文本分块并仅从最相关的块中提取信息。
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("关于汽车的一些关键发展")
常见问题和解决方案
- 重复提取: 大块重叠可能导致信息重复,需去重。
- 信息遗漏: 信息分散在多个块中时,提取可能会失败。
- 虚假数据: 在大文本中寻找单一事实时,可能会遇到生成错误数据。
总结和进一步学习资源
处理长文本时,选择合适的方法至关重要。本文提供的两种方法各有优劣,建议根据具体应用场景进行选择。
参考资料
- LangChain API 文档
- 维基百科 - 汽车
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---