父子扩展(Parent-Child Retrieval)
父子扩展(Parent-Child Retrieval)是一种检索策略,核心思路是:用小块检索,用大块回答。
为什么需要父子扩展
分块时面临一个矛盾:
块越小 → 向量语义聚焦,检索越精准
块越大 → 上下文完整,LLM 理解越准确
两者不可兼得——小块检索准但上下文残缺,大块上下文完整但检索不准
父子扩展就是同时要两个好处的解法。
具体怎么做
索引阶段: 把同一段文本切成两个粒度,建立父子关系
原文(500字的一节):
┌─────────────────────────────────────┐
│ 父块(500字) │
│ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │子块1 │ │子块2 │ │子块3 │ │
│ │128字 │ │128字 │ │128字 │ │
│ └──────┘ └──────┘ └──────┘ │
└─────────────────────────────────────┘
向量数据库里只存子块的向量(用于检索)
同时记录每个子块属于哪个父块(用于扩展)
查询阶段: 用子块命中,返回父块内容
用户问:"退款到账需要几天?"
↓
向量检索命中:子块2(128字,包含"3个工作日"这句话)✅
↓
父子扩展:找到子块2所属的父块(500字,完整的退款政策段落)
↓
把父块(500字)送给 LLM,而不是子块(128字)
↓
LLM 拿到完整上下文,回答更准确
没有父子扩展会怎样
只用小块检索 + 小块送给 LLM:
子块2(128字)的内容可能是:
"...退款将在审核通过后3个工作日内到账。如需查询退款进度..."
这128字孤立来看,LLM 不知道:
- 审核通过是什么条件
- 什么情况下会退款失败
- 退款到哪个账户
如果有父块(500字),这些上下文都有,回答会完整得多
父子关系不只是两层
也可以做三层:句子 → 段落 → 章节
检索粒度:句子级(最精准)
扩展粒度:段落级(平衡)
兜底粒度:章节级(最完整)
LlamaIndex 里叫做 Auto-Merging Retrieval(自动合并检索),命中相邻多个子块时,自动合并返回它们共同的父块,而不是把多个碎片分别送给 LLM。