AI Agent 核心架构短期记忆Working Memory全解析与面试通关指南在开发 AI Agent 时我们经常会遇到这样一个尴尬的场景大模型虽然“上知天文下知地理”但它居然记不住你上一句话说了什么为了让大模型具备连贯对话的能力我们需要为它装上“记忆系统”。在 Agent 的记忆分类中最基础、最直接、也是面试最常考的就是短期记忆Short-term / Working Memory。这篇博客将用最通俗的大白话带你彻底搞懂短期记忆的核心机制、主流工程落地策略并附带大厂面试级别的实战代码。无论是入门学习还是面试突击看这一篇就够了 一、 什么是短期记忆大白话秒懂通俗概念短期记忆在认知科学中也被称为工作记忆Working Memory。对于大语言模型LLM来说短期记忆就是当前对话的上下文Chat History。它就像是你的“办公桌”——你需要处理什么文件就得把文件放在桌子上。大模型需要结合什么历史信息来回答问题你就得把这些历史信息拼接在本次提问的 Prompt 里发给它。核心痛点大模型的“办公桌”大小是有限的这被称为上下文窗口限制Context Window Limit。如果你和 AI 聊了三天三夜产生的文本有几百万字你不可能把这些聊天记录全塞进 Prompt 里。即使强行塞进去也会面临成本爆炸Token 极其昂贵和中间遗忘现象模型记不住中间的内容。因此短期记忆工程的核心就是“如何在有限的 Token 预算内保留最有价值的历史对话”。️ 二、 短期记忆的四大主流策略面试必背面对越来越长的聊天记录业界通常采用以下四种策略来管理短期记忆。在面试时请务必清晰地对比它们的优缺点记忆策略 原理与机制 优点⚠️ 缺点与适用场景全量记忆 (Buffer Memory)简单粗暴把历史以来的所有对话原封不动地全部保留每次全部发给大模型。信息 100% 完整绝对不会漏掉任何历史细节。极易爆 Token成本极高。仅适用于极短的单次单点任务。滑动窗口 (Window Memory)只保留最近的 N 轮对话比如最近 5 轮把更早的对话直接丢弃滑走。极其轻量永远不会超出上下文限制成本完全可控。会发生“硬遗忘”。比如 10 轮前你告诉它你叫张三它现在已经忘了。适合普通的闲聊机器人。Token 滑动窗口 (Token Window)不按“轮数”截断而是按“Token 数量”截断。严格保证历史记录总数不超过设定的 Token 阈值。比按轮数截断更精确防止某几轮回复过长导致 API 报错。依然存在硬遗忘问题。适合对 API 预算控制极严的生产环境。摘要记忆 (Summary Memory)当对话长度达到阈值时在后台悄悄调一个小模型把之前的对话提炼成一段精简的摘要替换掉长长的原始记录。兼顾了“保存远古记忆”和“节省当前 Token”两大需求。后台生成摘要需要消耗额外算力和时间。适合超长周期的虚拟伴侣或个人助理。 三、 高频面试 QA 实战演练Q1滑动窗口记忆Window Memory和摘要记忆Summary Memory在实际业务中该如何取舍标准答案在真实的工业落地中我们通常不会二选一而是将两者结合使用。架构设计通常是设定一个最近 N 轮的滑动窗口来保存“高清的近期原话”保证接话的连贯性而对于被滑出窗口的更早期的对话我们不直接丢弃而是交给一个后台守护进程Daemon去生成摘要作为“模糊的远期记忆”放在 Prompt 顶部。这种结合方案兼顾了当前对话的流畅度和对历史设定的遵循度。Q2对于大模型来说把历史对话作为短期记忆传入时格式上有什么讲究标准答案现代的大模型 API如 OpenAI, Anthropic已经原生支持了统一的messages数组格式。在传入短期记忆时必须严格区分角色system存放最高指令和人设。user存放人类用户的历史提问。assistant存放 AI 历史生成的回答。这种严谨的结构化历史记录能极大降低大模型产生幻觉的概率防止大模型在角色扮演中“串戏”。Q3在生产环境中短期记忆存在哪里标准答案短期记忆是具有会话级别Session-level特征的高频读写数据。通常绝对不存放在关系型数据库如 MySQL中。工业界的标准做法是存放在Redis等内存数据库中设置一个过期时间TTL比如 24 小时无交互自动清空以保证极高的读写速度和合理的服务器资源利用。 四、 面试加分代码手写工业级“Token 滑动窗口记忆”在面试白板环节如果面试官让你写一个记忆管理模块千万别只写一个简单的 Listappend。写出一个带**长度保护滑动截断**的记忆类能完美展现你的工程健壮性意识importjsonfromcollectionsimportdequeclassTokenWindowMemory: 工业级短期记忆管理器 (Token 滑动窗口策略) 为了方便演示这里用“字符长度”来近似模拟“Token 数量”。 def__init__(self,max_tokens:int1000):# 使用 deque (双端队列) 方便我们在超过阈值时从头部(最早的记忆)弹出数据self.chat_historydeque()self.max_tokensmax_tokens self.current_token_count0def_estimate_tokens(self,text:str)-int: 估算文本的 Token 数量。 真实生产环境中这里应该调用 tiktoken 库等专用的分词器。 此处简单使用字符长度来近似模拟。 returnlen(text)defadd_message(self,role:str,content:str): 向短期记忆中添加一条新消息并触发滑动窗口裁剪机制。 # 1. 构建标准的消息体new_message{role:role,content:content}msg_tokensself._estimate_tokens(content)# 2. 将新消息加入队列并更新当前总 Token 数self.chat_history.append(new_message)self.current_token_countmsg_tokensprint(f [新记忆存入] 角色:{role}| 消耗 Token:{msg_tokens})# 3. 核心滑动窗口逻辑如果总 Token 超标了就开始遗忘最早的记忆self._trim_memory()def_trim_memory(self): 私有方法裁剪超出的记忆保证不爆 Token whileself.current_token_countself.max_tokensandlen(self.chat_history)1:# 从队列左侧(头部)弹出一个最古老的消息oldest_messageself.chat_history.popleft()freed_tokensself._estimate_tokens(oldest_message[content])self.current_token_count-freed_tokensprint(f️ [触发遗忘] 为了节省空间已遗忘早期对话。释放 Token:{freed_tokens})defget_context(self)-list: 获取当前经过裁剪的、可以直接发给 LLM API 的上下文列表 returnlist(self.chat_history)# # 模拟运行与面试讲解# if__name____main__:# 面试展示故意把最大 Token 设得很小限制为 50 个字符以此触发滑动遗忘机制memory_systemTokenWindowMemory(max_tokens50)# 回合 1简单的问候安全存入memory_system.add_message(user,你好我是张三。)memory_system.add_message(assistant,你好张三很高兴认识你)# 此时查看一下记忆print(\n目前的上下文:,json.dumps(memory_system.get_context(),ensure_asciiFalse,indent2))print(-*40)# 回合 2用户发送了一大段话导致 Token 超出阈值# 这会触发 _trim_memory把回合 1 的对话从工作记忆中“滑走”long_text今天天气真不错我想去打篮球但是发现球鞋坏了你能帮我推荐一双性价比高的实战篮球鞋吗memory_system.add_message(user,long_text)print(\n目前的上下文:,json.dumps(memory_system.get_context(),ensure_asciiFalse,indent2))# 面试讲解要点# 正如您所见在生产环境中直接传递无限延长的 List 是极其危险的。# 我在这里实现了一个基于 Token 估算的滑动窗口队列。# 当用户的长段落涌入时系统会自动将最初的问候语丢弃确保最终返回的 context 列表# 永远处于大模型 API 的安全容量限制内不仅避免了请求报错还实现了成本的精准控制。