微信扫码
添加专属顾问
我要投稿
ParentDocumentRetriever优化长文档搜索,提升问答系统准确性。 核心内容: 1. ParentDocumentRetriever解决长文档向量搜索的上下文缺失问题 2. 核心原理:分层检索,子文档检索但返回完整父文档 3. 应用场景:法律文件、研究论文等长文档处理
ParentDocumentRetriever
通过 分层检索 方式,解决了传统向量搜索容易导致的上下文缺失问题。
它特别适用于长文档处理,能够提高问答系统的检索质量。
在构建基于大语言模型(LLM)的问答系统时,信息检索的准确性和上下文完整性至关重要。
普通的向量检索通常会将文档拆分成较小的片段,并通过相似度搜索找到与用户查询匹配的部分。但这种方法有一个明显的缺点:检索结果往往只是文档的某个片段,容易导致信息不完整,影响最终的答案质量。
这就会碰到一个矛盾:
较小的内容块在检索中提供高精度,将用户查询的具体细节与针对性、相关的内容相匹配。这减少了噪音和无关信息,提高了响应的准确性。
较大的信息块提供了全面的背景,对于需要更广泛理解或本质上复杂的查询是必需的。这些信息块虽然不够精确,但通过涵盖更广泛的信息范围,可以提供更丰富的见解。
主要挑战在于平衡 详细详细、具体信息(较小块)和更广泛上下文理解(较大块)的需求。
ParentDocumentRetriever
是 LangChain 提供的一种 分层检索 方式,能够在 子文档中检索,但最终返回完整的 父文档,从而保证上下文的完整性。
这在长文档处理(如法律文件、研究论文、技术文档)等场景下尤为重要。
普通的向量数据库检索通常是基于 句子 或 小段文本 进行索引的。这意味着当用户查询时,返回的内容通常是多个小块,而这些片段往往缺乏整体上下文。
例如,在一本书的检索中,普通的向量搜索可能会返回某个段落,但如果该段落依赖于前后的内容,单独提供这一段就可能让用户难以理解。
ParentDocumentRetriever
采用了两级索引的方法。首先,它将长文档拆分成较大的 父文档(Parent Documents),然后再进一步拆分为较小的 子文档(Child Documents),并将子文档存入向量数据库。
第一级:专注于提取更小、更精确的片段,直接针对查询的具体内容。这确保了回应的相关性和针对性。
第二级:专注这些片段所来源的更大父文档。此步骤提供了额外的背景和深度,丰富了响应,提供了更广泛的视角,以支持详细信息。
当用户查询时,检索器先在子文档中搜索相关内容,并根据匹配的子文档找到其对应的父文档,最终返回完整的父文档。
这种方式可以保证用户获得完整的上下文信息,避免答案不连贯的问题。
这一方法的最大优势在于,它结合了 小文档的精准搜索 和 长文档的完整上下文,既保证了检索的精确度,又避免了因内容过短而导致的信息缺失。
在实际应用中,ParentDocumentRetriever
可以与 RAG(Retrieval-Augmented Generation) 结合,实现高质量的问答系统。
结合大语言模型基于检索结果生成答案。
检索到的完整父文档会作为上下文输入给 LLM,从而提高答案的准确性。
首先,需要加载文档。这里使用 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)
当用户输入查询时,检索器会在子文档中找到最匹配的内容,然后返回完整的父文档,确保答案的上下文完整。
在实际应用中,ParentDocumentRetriever
适用于各种长文档的处理需求。
例如,在 法律文档分析 中,法律条款往往很长,单独匹配一两个段落可能导致理解不完整,因此可以使用 ParentDocumentRetriever
返回完整的法条,提高法律咨询系统的可靠性。
在 企业内部知识库 场景下,员工手册、产品文档等往往包含大量信息,用户的查询可能与多个部分相关。使用 ParentDocumentRetriever
,可以确保用户获取的内容完整,而不会因为返回碎片化信息而造成困惑。
技术文档,如 API 文档或开发手册,往往结构复杂,多个部分之间有逻辑关联。普通的向量搜索可能只返回部分代码示例或单个 API 说明,但 ParentDocumentRetriever
能够返回完整的上下文,提高开发者的阅读体验。
ParentDocumentRetriever
通过 分层检索 方式,解决了传统向量搜索容易导致的上下文缺失问题。
它特别适用于长文档处理,能够提高问答系统的检索质量。
结合 RAG,它可以与 LLM 进行无缝集成,实现更智能的知识检索和问答。对于希望优化向量搜索质量的开发者来说,它是一个不可或缺的工具。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费场景POC验证,效果验证后签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2025-03-11
LangChainGo中的提示词工程(Prompt Engineering)
2025-03-10
手把手教你用LangChain自动写SQL做数据分析可视化
2025-03-05
Agent 最全 Playbook:场景、记忆和交互创新
2025-03-05
基于LangGraph的智能文章生成Agent架构设计思路
2025-03-02
LangGraph全新4大预构建Agents框架登场
2025-03-01
极简LangChain智能体开发入门指南
2025-03-01
释放 Langflow 的力量:使用 Rag 构建多工具代理
2025-02-28
用 LangGraph 构建 Agent 逐步指南
2024-10-10
2024-04-08
2024-07-13
2024-06-03
2024-09-04
2024-08-18
2024-04-08
2024-06-24
2024-07-10
2024-03-28
2025-02-05
2024-12-02
2024-11-25
2024-10-30
2024-10-11
2024-08-18
2024-08-16
2024-08-04