上下文窗口管理:长对话不丢重点

当你和模型聊了几十轮,突然发现它「忘了」开头定下的规则或偏好,多半不是模型记性差,而是上下文窗口管理没做好。窗口是固定长度的,超出的内容会被截断,而即便没截断,过长上下文也会让模型更难聚焦重点。如何在有限窗口里不丢关键信息,是长对话与长文档任务的核心工程问题。

窗口限制的表现

  • 截断:超过上限的历史直接被丢弃,模型对早期约定一无所知。
  • 早期信息被遗忘:即使内容在窗口内,离当前越远,模型在生成时赋予的注意力权重往往越低,关键前提被稀释。

这类问题在客服长会话、代码长上下文、多步骤推理中尤其常见。

管理策略

  • 滚动摘要:定期把较早的对话压缩成一段摘要,替换掉原始多轮内容,腾出空间给近期交互。
  • 重要信息置顶:把用户偏好、任务目标、硬性约束等「元信息」固定在提示开头,每轮都可见,避免被后续内容淹没。
  • 分层记忆:区分「工作记忆」(当前几轮)与「长期记忆」(已存数据库或摘要),需要时再取回,而不是把所有历史都塞进窗口。

下面是一段把多轮对话折叠成摘要的示例:

def summarize_history(history, summarizer, keep_recent=4):
    recent = history[-keep_recent:]                 # 保留最近几轮原文
    older = history[:-keep_recent]
    if not older:
        return recent
    digest = summarizer(older)                       # 把更早的轮次压成摘要
    return [{"role": "system", "content": "此前摘要:" + digest}] + recent

核心思想是:越久远越该被压缩,越近期越该保真。

何时改用向量检索

当历史长到摘要也放不下,或需要跨大量文档精确回忆时,全量上下文不再经济。此时更合适的做法是把历史或文档写入向量库,按需检索最相关的片段注入当前窗口,也就是把「记忆」外置。这比把所有内容常驻上下文更省 token,也更能抗截断。

需要权衡的是:检索会引入相关性与召回问题,关键但罕见的信息可能没被检索到,因此常把「重要信息置顶」与「向量检索」结合使用。

小结

上下文窗口管理通过滚动摘要、重要信息置顶与分层记忆,在固定长度的窗口里保住关键前提与近期交互,缓解截断与注意力稀释。当历史或文档过长、摘要也难以容纳时,应把记忆外置到向量检索,按需注入当前上下文。置顶元信息与检索结合,是在成本与保真之间最稳健的折中。

参考与延伸阅读

  • 关于对话记忆与摘要的研究可追溯至对话系统的摘要式记忆方案;具体算法与开源实现以各框架文档为准。待核实。
  • 向量检索替代全量上下文的思路与 RAG 一致,可参考向量数据库与检索增强生成的相关文档。待核实。
本文累计阅读