首页 / 资讯中心 / 文章详情

Agent 上下文管理彻底搞懂:滑动窗口、摘要压缩、分层记忆的底层原理 + 本机实测

Agent 上下文管理彻底搞懂:滑动窗口、摘要压缩、分层记忆的底层原理 + 本机实测 ★ FEATURED ARTICLE
我是 Yulia一线 AI 应用开发工程师4 年工程经验在职做大模型应用落地。只写一件事——把最新 AI 技术讲成人话 给你能直接跑通的代码全部本机实测不搬运不注水。有用就点个关注持续更新大模型应用的前沿实战。网上讲 Agent 记忆的文章大多是罗列8 大记忆策略要么就是丢一个 LangChain 的ConversationSummaryBufferMemory让你照抄。这篇不一样我先讲清楚为什么上下文会有限token / 注意力复杂度 / KV Cache 的底层原因再纯手写三种上下文管理策略不依赖任何框架最后本机实测把谁省 token、谁失忆的真实数字摆给你看。一、Agent 为什么聊着聊着就失忆了你肯定遇到过一个 Agent 跟你聊了几十轮前面明明说过我预算 5000 元“我们 10 个人”结果聊到后面它问那你们预算多少——它把前面的话忘了。这不是 Agent 笨是上下文窗口有限这个硬约束导致的。Agent 的每一轮对话都要作为文本重新喂给大模型但大模型一次能看的文本量是有限的比如 4K、32K、128K token。多轮对话越积越多总有一天塞不下就必须取舍——怎么取舍就是**上下文管理Context Management**要解决的问题。这也是面试里的高频追问“上下文超限了怎么处理摘要压缩丢失关键信息怎么办”二、本文能给你什么搞懂为什么上下文会有限——token、注意力 O(n²)、KV Cache 三个底层原因掌握三种策略的原理 纯手写实现滑动窗口 / 摘要压缩 / 分层记忆不依赖 LangChain拿到一份本机实测的真实数据每种策略占多少 token、还记不记得关键信息拿到一张什么时候用哪种的选型决策表。先看全景图对话历史上下文管理滑动窗口只留最近 N 轮摘要压缩旧内容压成摘要分层记忆短期 长期检索喂给 LLM三、底层铺垫为什么上下文会有限在讲策略之前必须先回答一个问题为什么不能把所有历史都塞进去这背后是三个成本。3.1 token 是什么大模型不认字只认token。分词器Tokenizer会把文本切成 token再喂给模型。以 GPT 系用的 cl100k_base 分词器为例importtiktoken enctiktoken.get_encoding(cl100k_base)print(enc.encode(你好世界))# 5 个 tokenprint(enc.encode(hello))# 1 个 token一个英文单词通常 1~2 个 token一个中文字通常 1~3 个 token。所谓上下文窗口 32K意思就是模型一次最多吃 32768 个 token。你聊得越多累计 token 越多总有撞到上限的时候。3.2 注意力计算是 O(n²)大模型的核心是Self-Attention自注意力。它的原理是让序列里的每个 token 都去看其他所有 token算一个注意力权重。假设序列长度是 n那么每个 token 都要和另外 n 个 token 算一遍注意力整个注意力矩阵是n × n。所以计算量是 O(n²)。这意味着什么序列长度翻一倍计算量变成 4 倍。你把上下文从 4K 拉到 8K不是贵一倍是贵 4 倍。这是上下文不能无限长的最根本原因。3.3 KV Cache 显存随长度线性增长推理时为了不重复计算模型会把每一层算出来的KKey和 VValue矩阵缓存起来这就是 KV Cache。它的显存占用跟层数 × 序列长度 × 每 token 维度 × 头的数量成正比。序列越长KV Cache 显存越大——而且是每一层、每一个 token、每一个注意力头都各存一份。所以即便算力扛得住 O(n²)显存也会先爆。上下文有限本质是成本决定的不是模型的意愿。一句话记住token 是计量单位O(n²) 是算力成本KV Cache 是显存成本——三者一起决定了上下文窗口不可能无限大于是有了管理的必要。四、三种策略原理 纯手写实现下面用一个真实的 6 轮对话做例子。这段对话里埋了 5 个关键事实10 人、5000 元、移动端、私有化、钉钉它们只出现一次、都在早期轮次——正好用来测哪种策略会失忆。CONV[(用户,我们团队想选一个项目管理工具帮我参考一下),(助手,好的先了解一下需求。团队多少人预算多少),(用户,我们 10 个人预算一年 5000 元以内),# 事实: 10人 5000元(助手,记下了。还有什么硬性要求吗),(用户,最好支持移动端大家经常出差),# 事实: 移动端(助手,明白。数据方面有偏好吗),(用户,数据要能私有化部署不能存第三方云上),# 事实: 私有化部署(助手,好的。还有别的吗),(用户,对了还要能和我们钉钉打通),# 事实: 钉钉(助手,都记下了。你确认一下需求我就推荐),(用户,就这些你推荐一个吧),(助手,根据你的需求我推荐……),# 这里需要早期事实]defto_text(msgs):return\n.join(f{role}:{text}forrole,textinmsgs)4.1 滑动窗口Sliding Window最简单也最健忘原理只保留最近 N 轮更早的直接丢弃。就像微信聊天窗口往上翻——太久之前的消息你翻不到了。实现一句话的事。defsliding_window(keep_turns3):# 一轮 用户 助手 2 条消息所以保留最近 3 轮 最后 6 条returnto_text(CONV[-keep_turns*2:])优点实现零成本token 占用完全可控永远不超过最近 N 轮的量。缺点早期关键信息被硬删。上面例子里最近 3 轮只剩私有化部署“钉钉”“就这些”10 个人 / 5000 元 / 移动端全丢了——Agent 后面问预算多少就露馅了。适用短对话、一次性任务历史信息不重要的场景。4.2 摘要压缩Summary Compression把旧内容压扁原理与其直接丢弃旧内容不如先用一个 LLM 把旧对话总结成一段摘要把摘要 最近 N 轮一起放进上下文。这样既省 token又保留了旧内容的大意。defsummarize(keep_turns3,summary):recentto_text(CONV[-keep_turns*2:])# 最近 N 轮原样保留returnsummary\nrecent# 摘要 最近 N 轮关键坑摘要会丢关键信息。这是面试必问的点。看两种摘要的差别# 朴素摘要只说了个大概关键细节全没了summary_naive【历史摘要】用户之前咨询了项目管理工具选型。# 结构化摘要按字段把关键信息一条条抽出来summary_structured【历史摘要】10 人团队年预算 5000 元需要移动端私有化部署钉钉集成。朴素摘要丢掉了10 人、5000 元、移动端Agent 还是失忆结构化摘要把这些关键字段都留住了。怎么缓解摘要丢信息核心是别让 LLM 自由发挥用结构化提示词逼它按字段抽取请把下面的对话总结成结构化摘要必须包含以下字段没有就写无 - 团队人数 - 预算 - 硬性要求移动端/私有化/集成等优点比滑动窗口省 token 的同时能保留旧内容的大意。缺点① 摘要本身就是一次额外的 LLM 调用有成本和延迟② 摘要永远会损失细节“大意不等于原文”需要精确引用原文的场景不适合③ 摘要会有漂移——多轮摘要套摘要信息会越来越歪。4.3 分层记忆Hierarchical Memory短期 长期最像人原理借鉴人类记忆——短期记忆只记最近的事窗口内完整保留长期记忆存到外部的笔记本向量数据库需要的时候再回忆检索回来。全部历史短期记忆最近 N 轮长期记忆向量库当前 query检索相关历史合并上下文喂给 LLM实现短期 窗口长期 把每条历史向量化存起来查询时用当前 query 去检索最相关的几条拼回上下文。fromfastembedimportTextEmbeddingimportnumpyasnp modelTextEmbedding(model_nameBAAI/bge-small-zh-v1.5)all_texts[textfor_,textinCONV]mem_vecsnp.array(list(model.embed(all_texts)))# 每条历史 - 向量mem_vecsmem_vecs/np.linalg.norm(mem_vecs,axis1,keepdimsTrue)# 归一化defhierarchical(keep_turns3,query预算 团队人数 移动端 私有化部署 钉钉):recentto_text(CONV[-keep_turns*2:])# 短期最近 3 轮qvnp.array(list(model.embed([query])))[0]qvqv/np.linalg.norm(qv)simsmem_vecs qv# 余弦相似度归一化后点积topsorted(np.argsort(sims)[::-1][:6].tolist())# 检索最相关的 6 条retrieved【长期记忆检索】.join(all_texts[i]foriintop)。returnretrieved\nrecent# 长期 短期 拼一起逐行说明model.embed把每条历史文本变成一个向量mem_vecs就是长期记忆库查询时把当前 query 也向量化和记忆库里的向量算余弦相似度归一化后就是点积取相似度最高的 top-6 条历史作为回忆出来的内容和短期窗口拼在一起喂给模型。优点① 长期记忆不占上下文存在外部向量库② 按需检索只把相关的历史拿回来③ 能跨会话、跨天持久化。缺点① 要维护向量库索引、存储成本② 检索质量依赖 embedding 和 query 的写法③ 比前两种复杂得多。五、本机实测谁省 token谁失忆原理讲完直接跑一遍。我在上面这段 6 轮对话上实测了 5 种做法的token 占用和关键信息保留5 个事实还剩几个策略token 占用保留事实丢失的事实全量不管理2445/5无滑动窗口最近 3 轮1082/510 个人、5000 元、移动端摘要压缩 · 朴素摘要1312/510 个人、5000 元、移动端摘要压缩 · 结构化摘要1514/510 个人分层记忆短期 长期检索2315/5无三个结论省 token 的代价是失忆。滑动窗口把 token 从 244 压到 108但丢了 3 个关键事实朴素摘要同样丢——因为它没把细节抽对。结构化摘要用 151 token 保住了 4/5 的事实是省 token 保留大意的性价比之选“10 个人在结构化摘要里被写成了10 人团队”措辞变了但语义在——这也是摘要的一个真实副作用改写会导致措辞漂移下游若靠精确词面匹配就会漏。分层记忆 231 token 保住 5/5最稳但 token 也接近全量因为它把检索到的历史原文又塞了回来。⚠️ 诚实说明本实测是 6 轮玩具对话 简单字符串匹配用来把机制讲清楚不代表生产。生产里摘要质量取决于 LLM、分层记忆的检索质量取决于 embedding但省 token 会失忆、摘要会丢细节这两个结论是普遍成立的。六、什么时候用哪种选型决策表场景建议短对话、一次性任务、历史不重要滑动窗口最简单需要记住早期关键事实但能接受大意结构化摘要压缩需要精确引用原文如你之前说的预算是多少分层记忆检索原文不靠摘要跨会话、跨天、长期积累的 Agent分层记忆向量库持久化团队/生产环境、可观测可评测分层记忆 摘要组合按预算权衡一句话总结滑动窗口是穷省摘要压缩是记大意分层记忆是记笔记——越往后越像人也越复杂越贵。选哪种取决于你的任务需要记住多少、以及愿意付多少成本。七、总结与避坑核心要点回顾成一张图常见坑速查坑原因解法滑动窗口直接丢早期关键信息硬截断早期关键信息提前抽出来存着摘要自由发挥丢细节没约束 LLM用结构化提示词逼它按字段抽取摘要多次套摘要越来越歪信息漂移摘要尽量基于原文少嵌套分层记忆检索不到query 写法不好检索 query 写清关键词必要时多路召回如果这篇对你有帮助点个赞、收藏一下下次做 Agent 记忆设计直接对照第六节的决策表。关注我这个系列我会拆完大模型应用落地全链路——RAG 混合检索、Agent 上下文管理、KV Cache、LoRA 微调每篇都带能直接跑的代码。你的 Agent 项目里上下文管理用的是哪种有没有踩过聊到一半它忘了预算的坑评论区聊聊我挨个回。本文数据截至 2026 年 10 月实测环境 Python 3.10 tiktoken cl100k_base bge-small-zh-v1.5有更新评论区提醒我。
阅读完成 · 觉得有帮助?
咨询建站