Skip to content
🔗 分享本题
查看我的学习进度 →

父文档与句子窗口检索动漫知识图:用小粒度内容精准检索,再分别回填父章节或相邻句子窗口以补全上下文

记忆点:小粒度检索、大范围回填;结构选父子,局部语义选窗口。

💡 答案要点

核心问题:RAG 分块的粒度矛盾

小 chunk(256 tokens):检索精准,但语义不完整 → 生成答案缺上下文
大 chunk(2000 tokens):语义完整,但检索不精准 → 召回很多无关内容

解决方案:检索小块,返回大块

Parent-Document Retrieval(父文档检索)

python
from langchain.retrievers import ParentDocumentRetriever
from langchain.storage import InMemoryStore
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 两套分块器
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=2000)  # 大块:语义完整
child_splitter  = RecursiveCharacterTextSplitter(chunk_size=400)   # 小块:检索精准

# 存储:小块向量库,大块内存/数据库
vectorstore  = Chroma(embedding_function=OpenAIEmbeddings())
docstore     = InMemoryStore()  # 存储父文档

retriever = ParentDocumentRetriever(
    vectorstore=vectorstore,
    docstore=docstore,
    child_splitter=child_splitter,
    parent_splitter=parent_splitter,
)

# 添加文档:自动切成小块建索引,同时保存父文档
retriever.add_documents(documents)

# 检索:用小块向量找,返回对应的大块(语义完整)
results = retriever.get_relevant_documents("如何优化 RAG 检索")
# → 检索到小块,但返回 2000 token 的父文档

图示:

原始文档(5000 tokens)
    ↓ parent_splitter(2000 tokens/块)
父文档 P1(2000t)│ 父文档 P2(2000t)│ 父文档 P3(1000t)
    ↓ child_splitter(400 tokens/块)
[C1][C2][C3][C4]  [C5][C6][C7][C8]  [C9][C10][C11]
    ↑ 向量检索命中 C3
    ↓ 返回 C3 所属的父文档 P1(语义完整的 2000 tokens)

Sentence Window Retrieval(句子窗口检索)

python
from llama_index.core.node_parser import SentenceWindowNodeParser
from llama_index.core.postprocessor import MetadataReplacementPostProcessor

# 按句子切分,但每个节点携带"前后 N 句"的窗口
node_parser = SentenceWindowNodeParser.from_defaults(
    window_size=3,  # 前后各 3 句
    window_metadata_key="window",
    original_text_metadata_key="original_text",
)

# 检索时用单句向量精准命中
# 生成时用 window(该句 + 前后各3句)提供上下文

postprocessor = MetadataReplacementPostProcessor(
    target_metadata_key="window"  # 把节点内容替换为窗口内容
)

query_engine = index.as_query_engine(
    similarity_top_k=5,
    node_postprocessors=[postprocessor]
)

两种方案对比:

方案检索粒度返回粒度适用场景
Parent-Document小 chunk(400t)父文档(2000t)长文档、结构化文档
Sentence Window单句(~50t)句子+上下文窗口需要精确定位+上下文

面试话术:

"Parent-Document Retrieval 是解决'检索精准和上下文完整'矛盾的最优方案。核心是两套分块:400 token 小块用于向量检索(精准),2000 token 大块用于 LLM 生成(完整)。命中小块后返回它的父文档给 LLM,既精准又完整。我在知识库问答项目用这个方案,比纯大块 chunking 的答案完整度提升 30%,比纯小块 chunking 的检索准确率提升 25%。"