Appearance
7.3.2 为什么高分结果之间也要去重和聚合?
先给结论:高分不等于高信息增量。很多看起来都很相关的结果,实际上可能来自同一文档、描述同一事实、只是在切块边界上略有不同。若不去重和聚合,模型看到的会是重复证据,而不是更多有效信息。
这件事在真实系统里非常常见。原因并不复杂:
- 一个重要段落可能被切成多个相邻块
- 一个定义可能在文档开头、FAQ、总结页里反复出现
- 一个高频术语可能让多个相似块都得到高分
- 一个版本说明可能在多个页面里留下近似内容
所以候选结果分数高,只能说明它们各自都像相关内容,不能说明:
- 它们彼此之间不重复
不去重会带来什么问题
最直接的问题是浪费上下文预算。
模型的上下文窗口虽然越来越大,但真正高质量的证据位仍然有限。如果前几条结果其实在表达同一件事,系统就会把预算花在重复信息上。
更进一步的问题包括:
- 真正不同角度的证据被挤掉
- 模型误以为某个观点更重要,只因为它被重复了很多次
- 来自同一文档的小片段过多,导致缺少跨文档补充信息
- 最终回答变得啰嗦、偏科,甚至重复引用
为什么“高分也要去重”
很多人会误以为:
- 高分结果既然都排在前面,说明它们都该保留
这不够稳。因为排序分数解决的是:
- 每条结果相对问题的相关性
它不自动解决的是:
- 这些结果彼此之间的信息重复度
也就是说,排序和去重解决的是两类不同问题:
- 排序回答“哪些更相关”
- 去重回答“哪些只是重复表达”
常见的重复类型
1. 相邻块重复
同一文档切块时,为了保留上下文,往往会加 overlap。这样召回结果里就很容易出现:
- 前后两个块都命中了
- 它们大段内容相同
这类重复最常见,也最值得优先处理。
2. 模板重复
很多知识库文档都有固定模板,比如:
- 文档头说明
- 版本声明
- 版权信息
- 常规安全提醒
这些内容可能因为高频关键词而一起被召回,但它们对回答当前问题未必重要。
3. 多页面同义重复
同一个规则可能同时存在于:
- 产品说明页
- FAQ
- 帮助中心
- 更新公告
这些内容不一定完全重复,但它们常常只是在不同地方重复表达同一事实。
去重和聚合分别在做什么
这两个动作经常放在一起说,但侧重点不完全一样。
去重
更偏向移除明显重复或高度近似的候选,比如:
- 相同
chunk_id - 相同
document_id + span - 文本高度相似
聚合
更偏向把本来就属于同一证据单元的候选合并处理,比如:
- 同一文档的多个相邻块
- 同一章节下的多个命中块
- 来自同一条 FAQ 的多个拆分片段
去重是防止浪费,聚合是恢复结构。
一个最小示意
python
candidates = retrieve(query, top_k=20)
candidates = deduplicate_by_similarity(candidates)
candidates = merge_adjacent_chunks(candidates)
final_context = select_top_context(candidates, max_chunks=6)这段代码想表达的是:
- 候选拿到后,不能立刻直接截前几条
- 先去重和聚合,才能更准确决定最终该给模型什么
实际落地时怎么判断该不该合并
可以先问三个问题:
- 这几个高分结果是不是来自同一文档、同一章节或同一段附近
- 它们表达的是同一事实,还是互补信息
- 如果只保留其中一条,会不会丢掉回答所需的关键上下文
如果答案更接近“同一事实的重复表达”,就应该偏去重。
如果答案更接近“同一证据链的不同片段”,就应该偏聚合。
一个常见误区
很多人只在索引前做内容去重,却忽略了:
- 检索后仍然会出现结果级重复
这很正常。因为索引前去重解决的是“库里别放太多重复内容”,而检索后去重解决的是:
- 当前问题下,最终候选别重复占位
这两层都需要。
一句话总结
高分结果之间也要去重和聚合,因为高分只代表“各自都相关”,不代表“彼此信息不重复”。去重能防止上下文预算被重复内容浪费,聚合能把本来碎掉的证据重新组织成更适合模型使用的上下文单元。