对话历史撑爆上下文窗口,是所有 LLM 应用迟早遇到的问题。业界有一套成熟的组合拳,但每招都有代价,选错场景比不选更糟。按"输入太多"和"输出太多"两个场景拆开讲。
场景一:历史塞不下
滑动窗口与截断。 保留系统提示词加最近 N 轮,直接丢掉最早的对话。实现最简单,延迟零增加。适用日常闲聊、轻量客服——用户只关心眼前的问题。风险是任务型对话里"用户二十轮前说过的约束"被无声丢掉,模型开始自相矛盾。
滚动摘要。 历史快到上限时调一次 LLM,把最早的若干轮总结成短文,新窗口装"摘要 + 近期对话"。适用超长陪伴类对话和长线任务。代价有二:摘要必丢细节(丢的往往是用户随口提但后来关键的约束),且每次总结都是额外算力和延迟。
RAG 外挂记忆。 历史入库(向量库),提问时检索最相关的历史片段塞回上下文。适用知识库问答、超长项目讨论。它解决的是"选择性回忆",但不能替代近期对话的完整性——最近几轮仍然要全量保留。
KV Cache 驱逐(StreamingLLM 思路)。 底层优化:模型对开头(系统提示词)和结尾(最新对话)注意力最高,把中间不重要 token 的 KV Cache 从显存里清掉,只留"开头的 Attention Sink"和"最近的 token",即可无限流式处理超长文本。这是唯一不损失近期精度的无限方案,但需要改推理栈,应用层用不上。
场景二:回答写不完
输出超限的解法完全不同:分段生成 + 结构化大纲(先让模型列大纲,再逐节展开,每节独立生成);流式输出把生成过程直接推给前端,用户感知不到截断;任务本身太大时做子任务拆解,每步的输入输出都在窗口内。
组合拳与验收
增量提醒(原文没展开的组合策略与判定):生产系统很少单用一招,常见组合是"滚动摘要打底 + RAG 补细节"——摘要保叙事连贯,RAG 兜回被摘要丢掉的关键实体。验收方法:构造 50 条"早期约束 + 近期追问"的测试对话(例如第 3 轮说"只用 PostgreSQL",第 30 轮问"那我的库怎么连"),统计约束保持率。判定标准:纯滑动窗口这类问题保持率通常低于 60%,摘要 + RAG 组合应做到 90% 以上,达不到就说明摘要 prompt 里没有强制"保留所有技术约束"的指令。
另一个容易忽略的成本项:滚动摘要的总结调用本身也烧钱,长对话场景下它能占到总 token 的 15%~25%,容量规划时别漏。
一句话收束:窗口不够的本质是"信息的时效性与完整性不可兼得",选策略就是选你愿意牺牲哪一头——工程上没有全都要。

评论0