RAG 系列(十二):高级分块策略——Parent-Child 与 Contextual Retrieval
分块的两难困境RAG 系统里有一个经典矛盾:Chunk 太小:向量匹配精准,但返回给 LLM 的内容是片段,缺乏上下文,无法完整回答问题Chunk 太大:内容完整,但语义太分散,embedding 质量下降,检索命中率降低这不是调参能解决的问题,而是 Naive 分块的结构性缺陷。小块适合检索,大块适合生成——这两个需求本来就是矛盾的,用同一个尺寸的 chunk 同时满足两者,必然顾此失彼。本篇介绍两种突破这一困境的方案:Parent-Child Chunking:用小块做检索,命中后返回对应的大块Contextual Retrieval(Anthropic 方案):给每个 Chunk 加上文档上下文描述,让 embedding 更"聪明"Parent-Child Chunking核心思路索引阶段: 父文档(800字)→ 存储在 docstore(InMemoryStore) ↓ 切割 子 Chunk(200字)→ 存入向量库 检索阶段: query → 向量检索匹配子 Chunk(精准) → 找到子 Chunk 对应的父文档 → 返回父文档给 LLM(完整)检索用的是小 chunk,LLM 拿到的是大 chunk。两个需求,各自最优,互不干扰。代码实现LangChain 的ParentDocumentRetriever封装了这个逻辑:fromlangchain_classic.retrieversimportParentDocumentRetrieverfromlangchain_classic.storageimportInMemoryStorefromlangchain_text_splittersimportRecursiveCharacterTextSplitter child_splitter=RecursiveCharacterTextSplitter(chunk_size=200,# 小块:用于向量检索chunk_overlap=20,)parent_splitter=RecursiveCharacterTextSplitter(chunk_size=800,# 大块:命中后返回给 LLMchunk_overlap=50,)vectorstore=Chroma(collection_name="parent_child",embedding_function=embeddings)store=InMemoryStore()# 存储父文档的 docstoreretriever