随着大语言模型支持的上下文窗口越来越长(从最初的几千 tokens 扩展到如今的几十万甚至上百万 tokens),一个直观的想法出现了:是不是可以把所有相关文档一股脑塞给模型,让模型自己去筛选和生成?然而在实际工程中,长上下文并不等于高效利用,不合理的填充方式反而会降低回答质量、增加成本和延迟。RAG 系统需要精心设计上下文窗口的分配策略,才能在信息完整性与生成质量之间取得平衡。
1. 长上下文的诱惑与陷阱
把尽可能多的资料喂给模型,看起来能提高“覆盖面”,减少因为检索遗漏导致的信息缺失。但这样做会带来几个实际代价:
- 注意力稀释:模型在处理超长输入时,对中间位置和靠后部分的信息关注度会自然衰减。真正关键的片段如果被埋在海量文本中间,很可能被模型忽略或错误概括。
- 成本线性增长:大多数 LLM 按输入 token 数量计费,上下文越长,每次调用的费用越高。看似只多塞了几段文本,实际累计产生的开销非常可观。
- 延迟增加:更长的输入意味着更长的处理时间,直接影响用户体验,尤其在需要实时响应的对话场景中。
- 信噪比恶化:如果检索回来五个片段,其中只有两个高度相关,另外三个是勉强沾边的内容,那么额外片段实际上是噪音。模型可能被噪音带偏,或者花费“注意力”去理解无关内容,反而干扰了正确回答。
2. 窗口分配的核心原则:质量优先于数量
上下文窗口是一种有限资源,应该将它分配给质量最高、最相关的信息,而不是盲目求多。实践中的一个有效原则是:
宁可给模型 3 段精准切题的文本,也不要塞 10 段似是而非的碎片。
具体来说,窗口分配时应考虑以下几个维度:
- 相关度得分:检索阶段通常会返回每个片段与问题的相似度分数。分配时可设定一个最低阈值,只让高于阈值的片段进入上下文,低于阈值的内容直接丢弃,哪怕这意味着只用了不到一半的窗口容量。
- 信息去重与互补:如果检索到的多个片段内容高度重叠,重复投入窗口资源意义不大。可以预先做一次简单的去重,或者优先选择来自不同文档、提供不同角度信息的片段,提升单位窗口的信息增量。
- 片段排序:实验表明,模型对开头和结尾部分的信息更敏感。因此可将最相关或最核心的片段放在提示词的开头或结尾,次相关片段放在中间,即便注意力衰减,也不至于遗漏关键信息。
- 保留“生成空间”:上下文窗口不仅用于输入,还要为模型保留足够的输出空间。如果窗口被输入全部占满,模型的回答长度会受到严重限制,可能导致截断或不完整的输出。
3. 实用的窗口分配策略
以下是在 RAG 系统中经过验证的几种实用策略,可根据场景灵活组合。
策略一:Top-K 截断 + 重排序
这是最常见的基础方案。先由检索器返回 Top-K 个片段(K 通常设为 3~10),然后利用一个轻量级的重排序模型(reranker)对这些片段进行二次评分,选出最终保留的 Top-N 个片段送入生成模型。重排序模型一般比嵌入模型更精准,能够将真正与问题语义契合的片段排到前面。
- 优点:简单可靠,适用于大多数知识问答场景。
- 建议参数:K 可以适当放宽(如 20),N 则根据窗口大小限制(如 5),保证进入上下文的都是精挑细选后的内容。
策略二:动态窗口填充
不预先固定要填充的片段数量,而是根据片段长度和目标窗口预算实时计算。例如设定“用于检索内容的最大 token 数”为 2000 tokens,然后从得分最高的片段开始逐个累加,直到总长度接近但不超过该上限,其余不再塞入。这样能避免因为某条片段意外很长而挤爆窗口,也避免了因为全是短片段而浪费可用容量。
策略三:分层处理与摘要压缩
当某个问题确实需要大量背景信息(例如需要结合一整份合同或多份历史记录)时,可以先让模型对检索到的多段内容进行摘要整合,生成一个“中间层摘要”,然后再将该摘要与原始问题一起送入最终生成模型。这相当于用模型的处理能力换取上下文空间的压缩——初次调用模型提炼信息,第二次调用基于提炼后的结果生成最终回答。虽然多了一次调用,但有效解决了上下文溢出和注意力稀释的问题。
策略四:滑动窗口与分段生成
对于非常长的源文档(如一本手册或一份长篇报告),检索可能只命中了其中某几个部分,但每个部分本身都很大。此时可以将长章节进一步切分为更小的单元,检索到具体的小单元后,只送入这些窄段落,而不是整个章节。通过精细化的切分和索引,能在检索阶段就实现窗口的精准使用,避免后期被迫做裁剪。
4. 监控与持续调优
窗口分配策略不是一劳永逸的,需要根据实际运行数据持续调整:
- 统计窗口利用率:记录每次请求实际使用了多少比例的窗口空间,如果长期低于 30%,说明策略过于保守,可以考虑放宽片段数量;如果经常碰到窗口上限甚至截断,则需要收紧。
- 关注被丢弃的相关信息:偶尔抽查被丢弃的低分片段是否真的无关,如果发现有价值的片段被错误过滤,就需要调整检索召回数量或阈值。
- A/B 测试不同策略:在确保回答质量的前提下,可以测试不同 Top-N 数值、是否启用重排序、是否使用摘要压缩等组合,找出成本与质量之间的最佳平衡点。
5. 一个实际的配置案例
某公司技术文档助手在处理“怎么配置双因素认证”这类典型问题时,采用了如下配置:
- 检索召回:从知识库中召回 Top-10 个相关片段;
- 重排序:使用 BGE Reranker 对 10 个片段重新打分,取 Top-4;
- 窗口分配:设定检索内容上限为 1500 tokens,将 4 个片段按其长度依次填入,接近上限时停止;
- 提示词结构:将最相关的片段放在提示词的最前面,回答要求中注明“请基于以下资料回答,如果资料不足请明确说明”;
- 输出预留:模型最大输出设置为 512 tokens,确保回答不被截断。
上线一个月后,回答准确率提升 12%,单次调用平均输入 tokens 减少 30%,整体成本和延迟均有明显改善。
长上下文的合理利用,本质上是在“给模型足够信息”和“不给模型过多干扰”之间做权衡。通过精心设计窗口分配策略,完全可以让 RAG 系统同时拥有精准的信息基础和流畅的生成体验,而不会被海量上下文拖入成本与质量的双重陷阱。