LangChain Parent Document Retriever (父文档检索器) 学习总结
知识要点
1️⃣ 这是什么
父文档检索器是 LangChain 中用于平衡检索精度和上下文完整性的高级检索器。 它通过将文档分成两个层级来解决 RAG 系统中的核心矛盾:
- 小文档块:检索更精准,但上下文信息不足
- 大文档块:上下文完整,但检索不够精准
父文档检索器通过"存储小块,检索大块"的策略,实现了两者的平衡。
工作原理:
- 将文档分成小块(子文档),用于向量检索
- 将文档分成大块(父文档),用于返回完整上下文
- 检索时先找到匹配的子文档,然后返回对应的父文档
2️⃣ 有什么用
主要用途:
- 需要高精度检索同时保留完整上下文的场景
- 长文档的智能检索(如技术文档、法律文书)
- 构建需要提供详细信息的问答系统
- 解决 RAG 应用中检索粒度与上下文的矛盾
- 电商产品详情、API 文档等结构化内容的检索
3️⃣ 示例代码
模式一:仅子分割器(原始文档作为父文档)
python
import dotenv
import weaviate
from langchain_classic.retrievers import ParentDocumentRetriever
from langchain_classic.storage import LocalFileStore
from langchain_community.document_loaders import UnstructuredFileLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_weaviate import WeaviateVectorStore
from langchain_community.embeddings import QianfanEmbeddingsEndpoint
from weaviate.auth import AuthApiKey
dotenv.load_dotenv()
# 1. 加载文档
loaders = [
UnstructuredFileLoader("./电商产品数据.txt"),
UnstructuredFileLoader("./项目API文档.md"),
]
docs = []
for loader in loaders:
docs.extend(loader.load())
# 2. 仅创建子分割器
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
)
# 3. 创建向量数据库与文档存储
vector_store = WeaviateVectorStore(
client=weaviate.connect_to_wcs(
cluster_url="your-cluster-url",
auth_credentials=AuthApiKey("your-api-key"),
),
index_name="ParentDocument",
text_key="text",
embedding=QianfanEmbeddingsEndpoint(),
)
byte_store = LocalFileStore("./parent-document")
# 4. 创建父文档检索器
retriever = ParentDocumentRetriever(
vectorstore=vector_store,
byte_store=byte_store,
child_splitter=text_splitter,
)
# 5. 添加文档
retriever.add_documents(docs, ids=None)
# 6. 检索并返回内容
search_docs = retriever.invoke("分享关于LLMOps的一些应用配置")
print(search_docs)
模式二:父子分割器(推荐)
python
import dotenv
import weaviate
from langchain_classic.retrievers import ParentDocumentRetriever
from langchain_classic.storage import InMemoryStore
from langchain_community.document_loaders import UnstructuredFileLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_weaviate import WeaviateVectorStore
from langchain_community.embeddings import QianfanEmbeddingsEndpoint
from weaviate.auth import AuthApiKey
dotenv.load_dotenv()
# 1. 加载文档
loaders = [
UnstructuredFileLoader("./电商产品数据.txt"),
UnstructuredFileLoader("./项目API文档.md"),
]
docs = []
for loader in loaders:
docs.extend(loader.load())
# 2. 创建父子分割器
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=2000)
child_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
# 3. 创建向量数据库与文档存储
vector_store = WeaviateVectorStore(
client=weaviate.connect_to_wcs(
cluster_url="your-cluster-url",
auth_credentials=AuthApiKey("your-api-key"),
),
index_name="ParentDocument",
text_key="text",
embedding=QianfanEmbeddingsEndpoint(),
)
store = InMemoryStore()
# 4. 创建父文档检索器
retriever = ParentDocumentRetriever(
vectorstore=vector_store,
byte_store=store,
parent_splitter=parent_splitter,
child_splitter=child_splitter,
)
# 5. 添加文档
retriever.add_documents(docs, ids=None)
# 6. 检索并返回内容
search_docs = retriever.invoke("分享关于LLMOps的一些应用配置")
print(search_docs)
4️⃣ 流程图
text
┌─────────────────────────────────────────────────────────┐
│ 原始文档 │
└─────────────────────────────────────────────────────────┘
│
┌─────────┴─────────┐
│ │
【父分割器】 【子分割器】
chunk_size=2000 chunk_size=500
│ │
▼ ▼
┌───────────┐ ┌───────────┐
│ 父文档块 │ │ 子文档块 │
│ (大块) │◄────────│ (小块) │
└───────────┘ 关联 └───────────┘
│ │
byte_store vector_store
│ │
└─────────┬─────────┘
│
【检索流程】
查询 → 子文档 → 父文档