Appearance
12.2.2 什么是递归检索(Recursive Retrieval)?
先给结论:递归检索是一种“分阶段、逐层缩小范围”的检索方式。它不是一次性 top-k,而是先检索到上层节点,再在该节点内继续检索,直到拿到足够细节或达到终止条件。
分层检索强调“结构化索引”,递归检索强调“结构内的逐层搜索”。在大文档里,这两者通常配套使用。
递归检索解决的核心问题
- 需要“先找范围,再找细节”的问题(例如先找到章节,再找到条款)
- 文档层级很深,单次检索无法跨层定位
- 复杂问题需要多次定位,才能把关键证据拼起来
递归检索的典型流程
一套可工作的递归检索通常包含以下步骤:
- 第一层检索:在章节级或文档级索引里找候选节点
- 进入子空间:对命中节点的子块再次检索
- 多轮递归:重复执行,直到命中足够细节
- 终止条件:达到最大深度、命中分数足够高或结果数量达到上限
下面是一个最小流程示意(伪代码):
python
def recursive_retrieval(query, node, depth, max_depth=2):
hits = node.retriever.search(query, top_k=5)
if depth >= max_depth or confident_enough(hits):
return hits
expanded = []
for hit in hits:
expanded += recursive_retrieval(query, hit.child_scope, depth + 1)
return rerank(query, expanded)重点不在“递归写法”,而在“每次检索都只在更小的范围内发生”。
什么时候值得用递归检索
如果你遇到这些现象,递归检索通常很有效:
- top-k chunk 经常命中“正确章节”的错误段落
- 需要在文档内做“先定位章节,再定位条款”的问题
- 一次检索返回的证据不完整,必须在局部范围继续找
控制递归检索成本的关键
递归检索最大的风险是成本和延迟。建议至少做三类控制:
- 深度上限:最多 2-3 层,不要无限深入
- 子空间大小:对子块数量做上限控制,避免范围爆炸
- 终止阈值:命中分数高或证据齐备就提前退出
这些控制会决定递归检索是否“稳而可控”,否则它很快变成不可用的暴力搜索。
常见误区
误区一:递归检索只是“多跑几次 top-k”
递归检索的核心不是次数,而是“每次都缩小范围”。如果你只是重复 top-k,而范围没有变,效果不会提升。
误区二:递归层数越多越好
层数越多,延迟和噪声越大。递归检索需要一个明确的上限,否则会吞掉成本而不一定提升效果。
误区三:递归检索可以替代重排
递归检索解决的是“范围定位”,重排解决的是“结果排序”。两者是互补关系,不是替代关系。
自检清单
- 每一层检索是否都在更小范围内进行?
- 是否有明确的终止条件,能稳定控制成本?
- 最终返回结果是否能组成连贯证据链?
一句话总结
递归检索的价值在于“先缩小范围,再找细节”。它把大文档问题拆成多次有限检索,让结构成为检索的一部分。