破解长文本提取难题:实用策略与实现指南
引言
在处理PDF等文件时,常常会遇到超过语言模型上下文窗口的文本。能够有效处理这些长文本对于提取有意义的信息至关重要。在本文中,我们将探讨两种主要的策略,以帮助您在设计应用时有效地处理长文本。
主要内容
1. 粗暴分块策略
粗暴分块策略是将文档切割成多块,每块在语言模型的上下文窗口内进行处理和提取。这一方法简单直接,但需要对每个块单独处理,可能导致重复或遗漏信息。
2. 基于RAG的策略
RAG(Retrieval-Augmented Generation)策略则通过将文档分块并索引,仅对看似“相关”的子集块进行内容提取。此方法更为智能,但需要额外的步骤来识别相关性。
代码示例
下面的代码演示如何实现这两种策略。
import re
import requests
from langchain_community.document_loaders import BSHTMLLoader
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_openai import ChatOpenAI
from langchain_text_splitters import TokenTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
# 下载内容
response = requests.get("https://en.wikipedia.org/wiki/Car")
with open("car.html", "w", encoding="utf-8") as f:
f.write(response.text)
# 加载并清理内容
loader = BSHTMLLoader("car.html")
document = loader.load()[0]
document.page_content = re.sub("\n\n+", "\n", document.page_content)
# 定义提取信息的模式
class KeyDevelopment(BaseModel):
year: int
description: str
evidence: str
class ExtractionData(BaseModel):
key_developments: List[KeyDevelopment]
prompt = ChatPromptTemplate.from_messages([
("system", "You are an expert at identifying key historic development in text."),
("human", "{text}"),
])
# 使用 OpenAI 的 LLM 进行提取
llm = ChatOpenAI(model="gpt-4-0125-preview", temperature=0)
extractor = prompt | llm.with_structured_output(schema=ExtractionData)
# 文本分块器
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})
# 合并结果
key_developments = []
for extraction in extractions:
key_developments.extend(extraction.key_developments)
# 基于RAG的提取
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)
常见问题和解决方案
- 信息重复:由于分块重叠,可能会导致信息重复,需要去重处理。
- 信息缺失:若信息跨多个块,可能会遗漏。
- 模型捏造数据:在收集单一事实时,注意数据的真实性。
总结和进一步学习资源
处理长文本是一个复杂而多样的任务。选择合适的策略(如粗暴分块或RAG)需要考虑应用场景和需求。以下是一些推荐的学习资源:
参考资料
- LangChain官方文档
- OpenAI API文档
- Wikipedia文章
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---