**如何有效处理长文本:AI提取策略与实现指南**

146 阅读2分钟
# 引言

在处理PDF等大文件时,您可能会遇到文本超出语言模型(LLM)上下文窗口的问题。这篇文章将介绍几种策略以有效处理这种情况,尤其是关注如何通过分块(Brute Force)和检索增强生成(RAG)方法来提取有用的信息。

# 主要内容

## 选择合适的LLM或策略

对于长文本提取,以下几种策略可供选择:
1. **更换LLM**:选择支持较大上下文窗口的LLM。
2. **分块处理**:将文档分块,并从每个块中提取内容。
3. **RAG方法**:将文档分块、索引,重点提取最相关的部分。

每种方法各有优劣,具体应用时需根据您的项目需求选择合适的策略。

## 实现分块和RAG的准备工作

首先,获取待处理的文本数据,并进行适当的清理和格式化。

```python
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)

代码示例

定义数据提取模式

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_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4-0125-preview", temperature=0)

分块方法实现

from langchain_text_splitters import TokenTextSplitter

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

# 并行提取
extractions = extractor.batch(
    [{"text": text} for text in texts[:3]],  # 仅限于前三个块以加快执行速度
    {"max_concurrency": 5},
)

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

RAG方法实现

from langchain_community.vectorstores import FAISS
from langchain_core.documents import Document
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import CharacterTextSplitter

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)

常见问题和解决方案

  1. 信息跨块分布:信息的分布可能导致提取不完整。增加块重叠可以部分解决此问题。
  2. 重复提取:较大的块重叠可能导致相同信息多次提取,需要进行去重操作。
  3. 数据虚构:LLMs可能生成虚假数据,需要对提取结果进行额外验证。

总结和进一步学习资源

本文详细介绍了如何通过分块和RAG方法处理长文本的提取问题。更多关于LLM和自然语言处理的深入讲解,可参考以下资源:

参考资料

  • LangChain 文档
  • OpenAI API 文档

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

---END---