AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


LangChain实战 | ParentDocumentRetriever 优化长文档的向量搜索质量

发布日期:2025-03-11 05:05:15 浏览次数: 1547 来源:AI取经路
推荐语

ParentDocumentRetriever优化长文档搜索,提升问答系统准确性。

核心内容:
1. ParentDocumentRetriever解决长文档向量搜索的上下文缺失问题
2. 核心原理:分层检索,子文档检索但返回完整父文档
3. 应用场景:法律文件、研究论文等长文档处理

杨芳贤
53A创始人/腾讯云(TVP)最具价值专家


ParentDocumentRetriever 通过 分层检索 方式,解决了传统向量搜索容易导致的上下文缺失问题。

它特别适用于长文档处理,能够提高问答系统的检索质量。

  • 1. ParentDocumentRetriever 的核心原理
  • 2. ParentDocumentRetriever 的使用
  • 3. 查询结果
  • 4. 应用场景
  • 总结

在构建基于大语言模型(LLM)的问答系统时,信息检索的准确性和上下文完整性至关重要。

普通的向量检索通常会将文档拆分成较小的片段,并通过相似度搜索找到与用户查询匹配的部分。但这种方法有一个明显的缺点:检索结果往往只是文档的某个片段,容易导致信息不完整,影响最终的答案质量。

这就会碰到一个矛盾:

  • 较小的内容块在检索中提供高精度,将用户查询的具体细节与针对性、相关的内容相匹配。这减少了噪音和无关信息,提高了响应的准确性。

  • 较大的信息块提供了全面的背景,对于需要更广泛理解或本质上复杂的查询是必需的。这些信息块虽然不够精确,但通过涵盖更广泛的信息范围,可以提供更丰富的见解。

主要挑战在于平衡 详细详细、具体信息(较小块)和更广泛上下文理解(较大块)的需求。

ParentDocumentRetriever 是 LangChain 提供的一种 分层检索 方式,能够在 子文档中检索,但最终返回完整的 父文档,从而保证上下文的完整性。

这在长文档处理(如法律文件、研究论文、技术文档)等场景下尤为重要。

1. ParentDocumentRetriever 的核心原理 

普通的向量数据库检索通常是基于 句子 或 小段文本 进行索引的。这意味着当用户查询时,返回的内容通常是多个小块,而这些片段往往缺乏整体上下文。

例如,在一本书的检索中,普通的向量搜索可能会返回某个段落,但如果该段落依赖于前后的内容,单独提供这一段就可能让用户难以理解。

ParentDocumentRetriever 采用了两级索引的方法。首先,它将长文档拆分成较大的 父文档(Parent Documents),然后再进一步拆分为较小的 子文档(Child Documents),并将子文档存入向量数据库。

第一级:专注于提取更小、更精确的片段,直接针对查询的具体内容。这确保了回应的相关性和针对性。

第二级:专注这些片段所来源的更大父文档。此步骤提供了额外的背景和深度,丰富了响应,提供了更广泛的视角,以支持详细信息。

当用户查询时,检索器先在子文档中搜索相关内容,并根据匹配的子文档找到其对应的父文档,最终返回完整的父文档。

这种方式可以保证用户获得完整的上下文信息,避免答案不连贯的问题。

13-11-13-43-24a538e4f1b08f4f4f6c1b0afcab861f-c34ed3-2

这一方法的最大优势在于,它结合了 小文档的精准搜索 和 长文档的完整上下文,既保证了检索的精确度,又避免了因内容过短而导致的信息缺失。

在实际应用中,ParentDocumentRetriever 可以与 RAG(Retrieval-Augmented Generation) 结合,实现高质量的问答系统。

结合大语言模型基于检索结果生成答案。

检索到的完整父文档会作为上下文输入给 LLM,从而提高答案的准确性。

img

2. ParentDocumentRetriever 的使用 

首先,需要加载文档。这里使用 TextLoader 读取一个文本文件,例如 example.txt

"""
Python 3.13
LangChain 0.3
"""

import os

OPENAI_API_KEY = 'hk-iwtbie4a91e427'# 设置OpenAI API密钥
os.environ['OpenAI_API_KEY'] = OPENAI_API_KEY  # 将API密钥设置为环境变量


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(file_path="../data/西游记1.txt", encoding='utf-8'),
    TextLoader(file_path="../data/西游记2.txt", encoding='utf-8')
]
docs = []
for loader in loaders:
    docs.extend(loader.load())

在加载文档后,接下来需要对文档进行拆分。ParentDocumentRetriever 采用两级拆分方式,因此首先创建 父文档拆分器,然后创建 子文档拆分器

# 创建OpenAI嵌入实例
embeddings = OpenAIEmbeddings(model="text-embedding-3-large", base_url="https://api.openai-hk.com/v1")


# 这个文本分割器用于创建父文档
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=2000)
# 此文本分割器用于创建子文档。创建比父文档更小的文档。
child_splitter = RecursiveCharacterTextSplitter(chunk_size=400)

接下来,需要创建向量数据库,用于存储子文档的嵌入向量。这里使用 Chroma 作为向量数据库,并使用 OpenAIEmbeddings 进行文本嵌入。

# 用于索引子块的vectorstore
vectorstore = Chroma(
    collection_name="split_parents", embedding_function=embeddings
)
# 父文档的存储层
store = InMemoryStore()

创建 ParentDocumentRetriever 时,需要提供 vectorstore,并指定文档拆分策略。

# 检索小块内容,然后检索它们的父文档。
retriever = ParentDocumentRetriever(
    vectorstore=vectorstore,              # 用于存储小块及其嵌入向量的基础向量存储
    docstore=store,                       # 父文档的存储接口
    child_splitter=child_splitter,        # 用于创建子文档的文本分割器。
    parent_splitter=parent_splitter,      # 用于创建父文档的文本分离器
)
# 将文档添加到 docstore 和 vectorstore.
print("开始处理文档")
retriever.add_documents(docs)

此时,向量数据库已经存储了子文档的嵌入向量,而 ParentDocumentRetriever 也已经准备就绪,可以进行查询。

# 从向量库直接查询关键字,返回小块
sub_docs = vectorstore.similarity_search("赤脚大罗仙")
print(sub_docs)
print("================================")
print("子文档:")
print(sub_docs[0].page_content)
print()

# 从检索器查询相同的关键字,返回父文档
retrieved_docs = retriever.invoke("赤脚大罗仙")

print("父文档:")
print(retrieved_docs[0].page_content)

当用户输入查询时,检索器会在子文档中找到最匹配的内容,然后返回完整的父文档,确保答案的上下文完整。

3. 查询结果 

screenshot (10)

4. 应用场景 

在实际应用中,ParentDocumentRetriever 适用于各种长文档的处理需求。

例如,在 法律文档分析 中,法律条款往往很长,单独匹配一两个段落可能导致理解不完整,因此可以使用 ParentDocumentRetriever 返回完整的法条,提高法律咨询系统的可靠性。

在 企业内部知识库 场景下,员工手册、产品文档等往往包含大量信息,用户的查询可能与多个部分相关。使用 ParentDocumentRetriever,可以确保用户获取的内容完整,而不会因为返回碎片化信息而造成困惑。

技术文档,如 API 文档或开发手册,往往结构复杂,多个部分之间有逻辑关联。普通的向量搜索可能只返回部分代码示例或单个 API 说明,但 ParentDocumentRetriever 能够返回完整的上下文,提高开发者的阅读体验。

总结 

ParentDocumentRetriever 通过 分层检索 方式,解决了传统向量搜索容易导致的上下文缺失问题。

它特别适用于长文档处理,能够提高问答系统的检索质量。

结合 RAG,它可以与 LLM 进行无缝集成,实现更智能的知识检索和问答。对于希望优化向量搜索质量的开发者来说,它是一个不可或缺的工具。

53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费场景POC验证,效果验证后签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

添加专属顾问

回到顶部

加载中...

扫码咨询