为什么做父子索引?
如果直接对文本做chunk切分然后召回,问题在于可能chunk切得较细回答的上下文不足而导致回答的质量出现问题,尤其是政策,法务,客服这些场景里面,可能检索到结果但是没有回答出 例外。
比如 用户可能问试用转正式会员后可以退款吗?检索到的:用户从免费试用自动转为正式订阅后,原则上不支持全额退款。由于chunk太细,文档的约束 比如用户在扣费后 24 小时内提交申请,且未实际使用高级功能,可按例外流程处理。这句排到了后面,导致回答出现问题。
那为什么不能调大chunk,因为将chunk调大又会造成其他问题,比如向量语义变糊,召回变差之类的。
怎么做父子索引?
一般来说就是小块负责找,大块负责答。每个子块都带一个 parent_id,指向它属于哪个父块。
查询时先召回子块,再按 parent_id 回表拿父块,最后把父块喂给模型。这个也要经历去重、回填、扩窗,最后才把父块或父块内窗口送给 LLM。
容易踩的坑
第一坑:parent 太大。
会导致召回后上下文污染、token 爆炸、rerank 失真。
第二坑:parent 边界不贴合结构。
如果 parent 跨了多个主题,child 命中对了,回填还是会带很多噪音。
第三坑:只按 child 排名,不做 parent 聚合。
结果可能 top10 都来自同一 parent 的相邻 child,覆盖面很差。
第四坑:整段 parent 直接喂 LLM。
很多时候应该回填局部窗口而不是完整 parent。
第五坑:没评测就调参数。
父子索引非常依赖语料形态,不做 recall@k、MRR、nDCG、answer faithfulness、context precision,很容易越改越玄学。
什么时候该做?
当遇见小块更适合检索,大块更适合生成的时候就该做这一层。
信号包括:
把 chunk 切小,命中率变高,但回答经常“只抓到一句话、解释不完整”;把 chunk 切大,回答完整一些。
同一个 parent 下的多个 child 经常一起命中。
答案经常需要定位 + 展开解释两步。
文档天然有层级结构。
可选替代方案:sentence window