3.1 短期记忆:上下文窗口的经济学


3.1 短期记忆:上下文窗口的经济学

本节摘要:上下文窗口是智能体的工作台——容量按 token 计价、装得越满注意力越稀。本节把窗口拆成五块内容算清预算账,给出滚动截断与中段摘要的实现,并解释为什么"窗口越大越好"是本册要纠正的第一个迷思。

「上下文窗口」这个词容易让人误解成一个大口袋。把它想成按字符计费的办公桌更准确:桌面大小有限(窗口上限),摊开的每张纸都占地方(输入计费),而且纸张堆到一定厚度后,你反而找不到压在中层的那张关键便签(注意力稀释)。经济学思维因此贯穿本节:每一块内容都要回答"值不值得占这个位置"。

窗口的五块内容与预算分配

一轮决策的输入,由五块内容构成,各有各的占用规律:

内容块 占用规律 挤占后果 预算建议(占比)
系统提示 + 契约 固定,一次写好 契约失效,行为漂移 10% 左右,尽量精炼
工具定义 随工具数线性涨 选错工具、参数瞎编 控制在 15% 内,超了做工具筛选
任务目标与约束 固定,首轮写入 跑偏、忘记验收标准 5% 左右
对话历史与观察 持续增长的大头 中段信息被"遗忘" 45% 上限,滚动管理
输出预留 固定预留 回答被截断 15% 起,写长报告再加
检索回填资料 按需波动 相关事实缺席 10% 机动

这张表的关键列是中间那列:挤占的代价不是均质的。挤掉一段闲聊历史,模型只是少点背景;挤掉工具定义,它会开始编造工具名;挤掉输出预留,回答被物理截断。所以滚动管理的次序必须是:先挤历史中段,再挤旧观察,工具定义和输出预留动都别动。

为什么装得下不等于用得上

各家服务的窗口从十几万到上百万 token 不等,于是流行一种"全塞进去"的方案。实测里它有两个坑。其一,中间盲区:注意力对开头和结尾的内容明显强于中段,把关键约束埋在一万 token 的对话正中间,模型视而不见的概率显著上升——它不是没读到,是读到没在意。其二,计费线性:窗口按输入总量计费,一个五十轮的任务若从不清理历史,成本随轮次平方级累积,延迟也同步恶化。

def manage_window(messages, budget: int, keep_recent: int = 6): """滚动窗口:保住头(契约+目标),滚动腰(历史),保住尾(最近几轮)。""" head, tail = messages[:2], messages[-keep_recent:] # 头两轮 + 最近 N 轮 middle = messages[2:-keep_recent] used = count_tokens(head) + count_tokens(tail) if used > budget: # 极端情况:先压缩尾部 tail = compress_tail(tail, keep_last=2) if middle: digest = summarize(middle) # 中段压成摘要 digest_msg = {"role": "system", "content": f"[历史摘要] 此前发生:{digest}"} if used + count_tokens(digest_msg) <= budget: return insert_after_head(head, digest_msg, tail) return head + tail # 没空间就纯滚动

两个实现细节决定这套机制的成败。摘要由谁做:用便宜的小模型做中段摘要,主模型只消费摘要结果——把省下的预算换成主模型的注意力。摘要保什么:保结论与决定("用户确认了 A 方案""已尝试重启无效"),丢过程与寒暄;摘要里出现"等等、之类"这种含糊收尾,说明压缩器在偷懒,后续决策会为这份含糊买单。

案例:一次越聊越笨的排障

背景:运维智能体处理一次数据库故障,前八轮表现正常,第九轮开始重复已排除的方案,第十二轮把用户最初否决的重启操作又提了出来。

操作:回放轨迹发现,历史里堆满了每次查询返回的大段状态输出(每段三四千 token),到第九轮,最初的故障现象描述已被滚动挤出窗口——模型不是变笨了,是忘了自己 why 来

结果:改法分两步——观察回填前先过 2.4 节的清洗管道(状态输出压到五百 token 内);故障现象、已排除方案这两类信息在产生时即写入"任务便签"(一条置顶的 system 消息),每轮可见。修改后同规模故障全程无跑偏。

解读:任务便签是滚动窗口的关键搭档:滚动负责丢弃,便签负责永生。凡是"从第一轮起就决定了对错"的信息(目标、约束、已排除项),都该进便签而不是指望历史里留着它。

变式:多任务并行的助理场景,每个任务一组独立窗口(session 隔离),切换任务时旧任务压成一条摘要挂起——这就是操作系统的进程切换思路,比多个任务挤一个窗口干净得多。

⚠️ 常见坑:把"窗口够大"当容量规划。窗口只解决短期,跨会话的偏好、事实、教训一概不在窗口里——那正是下一节长期记忆的地盘。用大窗口顶长期记忆,账单会替你记住这个决定。

本节要点回顾

  • 窗口是计费的工作台:五块内容按"挤占代价"排序管理,工具定义与输出预留是碰不得的地基。
  • 装得下 ≠ 用得上:中间盲区让中段信息形同虚设;成本随未清理的历史平方级累积。
  • 滚动 + 摘要 + 便签:中段压摘要、结论进便签、最近几轮保全文,三者配合才稳。
  • 短期记忆的边界:只管当前任务;跨会话的东西从产生那一刻就该写往长期库。

窗口的账算清楚了,下一节走出当前对话:什么值得存进长期记忆、向量检索的参数怎么定,以及那笔容易被忽略的工程账。

排错现场:三类窗口病的识别

窗口管理的问题上线后通常以三种面目出现,各有速判特征。

第一种,失忆症:模型在第 N 轮遗忘了第 2 轮的信息。翻轨迹看第 N 轮的实际输入——如果早期消息已被滚动挤出窗口,诊断成立。修法是把被遗忘的信息分级:属于"一直重要"的进任务便签,属于"曾经重要"的接受遗忘。不必对失忆零容忍,多数任务的早期细节本来就该忘。

第二种,近视症:给了长文档,模型只回应开头结尾。这是注意力分布问题,不是窗口容量问题——材料还在窗口里,只是中段没被"看见"。修法不是换更大的窗口(那只会让中段更远),而是改变材料结构:关键内容前置或后置、长文档分页按需读取、检索定位到相关段落后只回填局部。

第三种,挤出症:工具定义或输出预留被历史挤掉,模型开始编造工具名或回答戛然而止。这是最危险的一种,因为它以诡异的形式出现(编造工具名很像模型抽风),容易被误诊为能力退化。修法在 3.1 的预算表里:给工具定义与输出预留划出保护区,滚动逻辑永远不碰这两块。

三种病的共同预防措施只有一条:把窗口当成需要主动管理的资源,从第一版就实现预算分配与滚动逻辑,而不是等出事再补。事后补救的窗口管理,往往要带着线上流量做手术。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U