破解长文本提取难题:实用策略与实现指南

115 阅读2分钟

破解长文本提取难题:实用策略与实现指南

引言

在处理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)

常见问题和解决方案

  1. 信息重复:由于分块重叠,可能会导致信息重复,需要去重处理。
  2. 信息缺失:若信息跨多个块,可能会遗漏。
  3. 模型捏造数据:在收集单一事实时,注意数据的真实性。

总结和进一步学习资源

处理长文本是一个复杂而多样的任务。选择合适的策略(如粗暴分块或RAG)需要考虑应用场景和需求。以下是一些推荐的学习资源:

参考资料

  • LangChain官方文档
  • OpenAI API文档
  • Wikipedia文章

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

---END---