引言
在处理大量文档进行信息检索时,我们面临各式挑战:是选择小文档以确保其嵌入准确性,还是选择较大文档以便保持上下文?ParentDocumentRetriever是应对这些挑战的利器。本文将详细探讨其工作机制,并提供实际操作的代码示例,让您在数据处理上游刃有余。
主要内容
Parent Document Retriever概述
ParentDocumentRetriever的核心思想是通过分割并存储小数据块来进行初步检索,然后利用这些小块的父ID返回更大的文档对象。这里的"父文档"可以是整个原始文档或较大的片段。这种双层策略允许我们在保留上下文的同时提升检索精度。
使用步骤
- 加载文档:首先需要加载待处理的文档。
- 文本分割:将文档分割为合理大小的子文档和父文档。
- 建立向量存储:利用分割的子文档来构建向量存储,以便进行快速检索。
- 存储父文档:将分割的父文档存储在存储层中,以便最终检索时能快速定位。
代码示例
以下是一个完整的代码示例,展示了如何实现上述步骤。
from langchain.retrievers import ParentDocumentRetriever
from langchain.storage import InMemoryStore
from langchain_chroma import Chroma
from langchain_community.document_loaders import TextLoader
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 文档加载
loaders = [
TextLoader("paul_graham_essay.txt"),
TextLoader("state_of_the_union.txt"),
]
docs = []
for loader in loaders:
docs.extend(loader.load())
# 文本分割
child_splitter = RecursiveCharacterTextSplitter(chunk_size=400)
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=2000)
# 向量存储和父文档存储
vectorstore = Chroma(
collection_name="split_parents", embedding_function=OpenAIEmbeddings() # 使用API代理服务提高访问稳定性
)
store = InMemoryStore()
# 构建检索器
retriever = ParentDocumentRetriever(
vectorstore=vectorstore,
docstore=store,
child_splitter=child_splitter,
parent_splitter=parent_splitter,
)
retriever.add_documents(docs)
# 检索实例
sub_docs = vectorstore.similarity_search("justice breyer")
print(sub_docs[0].page_content)
retrieved_docs = retriever.invoke("justice breyer")
print(retrieved_docs[0].page_content)
常见问题和解决方案
如何确保文档检索的准确性?
在使用ParentDocumentRetriever时,选择合适的文本分割大小至关重要。较小的子文档有助于提高嵌入的准确性,但过小可能导致上下文丢失。建议根据具体应用场景调整分割参数。
如何解决API访问受限问题?
由于网络限制,使用API时可能需要通过代理服务来提高访问的稳定性。建议选择稳定的代理服务以确保高可用性。
总结和进一步学习资源
ParentDocumentRetriever是一个强大而灵活的工具,大大简化了文档检索流程。建议读者进一步探索以下资源以深入理解其应用:
参考资料
- LangChain 文档: python.langchain.com/
- OpenAI 嵌入API使用说明: beta.openai.com/docs/guides…
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---