[精通长文本处理:如何有效进行信息提取]

112 阅读2分钟

引言

在处理长文本文件时,如PDF,您可能会遇到超出语言模型上下文窗口的文本。本文旨在介绍几种策略,以帮助您在这种情况下进行信息提取。

主要内容

改变LLM

选择支持更大上下文窗口的不同LLM。

暴力分块策略

将文档划分为小块,并从每个块中提取内容。

RAG策略

划分文档、索引块,仅从“相关”块的子集提取内容。需要注意的是,各种策略有不同的权衡,最佳策略取决于您的具体应用。

以下是如何实现策略2和3的指南。

代码示例

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]

创建提取器

from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "你是识别文本中关键历史发展的专家。"),
        ("human", "{text}"),
    ]
)

from langchain_openai import ChatOpenAI
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)

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)

print(key_developments[:10])

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("关于汽车的关键发展")

for key_development in results.key_developments:
    print(key_development)

常见问题和解决方案

  • 信息分块问题:如果信息跨多个块,LLM可能会提取失败。解决方案是优化分块策略。
  • 重复信息:大块重叠可能导致重复信息。解决方案是去重处理。

总结和进一步学习资源

长文本处理需要根据具体应用选择合适的策略。建议进一步学习关于LLM上下文窗口和RAG方法的资料。

参考资料

  1. LangChain Documentation
  2. OpenAI API Documentation

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

---END---