AI Agent 的记忆系统怎么设计从短期记忆到长期记忆我踩过的 6 个坑适合正在开发 AI Agent、想让 Agent 记住历史对话和用户偏好的开发者。本文讲解 AI Agent 记忆系统的 3 层架构设计附 Python 实现代码。为什么 Agent 需要记忆没有记忆的 AI Agent 就像一个每天失忆的人——你今天告诉它我喜欢简洁的写作风格明天它就忘了又写一堆废话。记忆系统解决的核心问题问题没有记忆有记忆用户偏好每次重新交代自动记住历史上下文只看当前对话能回忆过去知识积累每次从零开始持续学习个性化千人一面越用越懂你记忆系统的 3 层架构┌─────────────────────────────────────┐ │ 长期记忆Long-term │ 用户画像、偏好、历史知识 ├─────────────────────────────────────┤ │ 工作记忆Working │ 当前任务的上下文 ├─────────────────────────────────────┤ │ 感官记忆Sensory │ 最近几轮对话原文 └─────────────────────────────────────┘感官记忆最近几轮对话最简单的记忆就是把最近 N 轮对话原文塞进 prompt。classSensoryMemory:感官记忆保存最近 N 轮对话def__init__(self,max_turns10):self.history[]self.max_turnsmax_turnsdefadd(self,role,content):self.history.append({role:role,content:content})# 超过上限删除最早的iflen(self.history)self.max_turns*2:self.historyself.history[-self.max_turns*2:]defget_context(self):返回最近的对话历史returnself.historydefclear(self):self.history[]问题对话越来越长token 超限。10 轮对话可能就占了 3000 token。工作记忆当前任务上下文工作记忆保存当前正在做的事情的关键信息不是对话原文而是摘要。classWorkingMemory:工作记忆当前任务的关键信息摘要def__init__(self):self.summaryself.current_taskself.key_facts[]defupdate(self,task,facts):更新工作记忆self.current_tasktask self.key_factsfacts self.summaryf当前任务:{task}\n关键信息:{, .join(facts)}defget_context(self):返回工作记忆上下文ifnotself.summary:returnreturnf[工作记忆]\n{self.summary}defadd_fact(self,fact):添加一个关键信息iffactnotinself.key_facts:self.key_facts.append(fact)self.summaryf当前任务:{self.current_task}\n关键信息:{, .join(self.key_facts)}长期记忆用户画像和历史知识长期记忆存在外部存储数据库/文件包含用户偏好、历史交互总结、学到的知识。importjsonfrompathlibimportPathclassLongTermMemory:长期记忆持久化存储用户画像和历史知识def__init__(self,storage_pathmemory.json):self.pathPath(storage_path)self.dataself._load()def_load(self):ifself.path.exists():returnjson.loads(self.path.read_text(encodingutf-8))return{user_profile:{},preferences:[],learned:[]}def_save(self):self.path.write_text(json.dumps(self.data,ensure_asciiFalse,indent2),encodingutf-8)defadd_preference(self,key,value):记录用户偏好self.data[preferences][pforpinself.data[preferences]ifp[key]!key]self.data[preferences].append({key:key,value:value})self._save()defadd_learned(self,knowledge):记录学到的知识ifknowledgenotinself.data[learned]:self.data[learned].append(knowledge)self._save()defget_context(self):返回长期记忆上下文parts[]ifself.data[preferences]:prefs[f{p[key]}:{p[value]}forpinself.data[preferences]]parts.append(f[用户偏好]\n\n.join(prefs))ifself.data[learned]:parts.append(f[历史知识]\n\n.join(self.data[learned][-10:]))# 最近 10 条return\n\n.join(parts)3 层记忆组合使用classAgentMemory:Agent 记忆系统3 层组合def__init__(self):self.sensorySensoryMemory(max_turns10)self.workingWorkingMemory()self.long_termLongTermMemory()defadd_turn(self,role,content):添加一轮对话self.sensory.add(role,content)defbuild_prompt(self,system_prompt):组装完整的 prompt包含所有记忆层messages[{role:system,content:system_prompt}]# 长期记忆放在 system prompt 里lt_ctxself.long_term.get_context()iflt_ctx:messages[0][content]f\n\n{lt_ctx}# 工作记忆wk_ctxself.working.get_context()ifwk_ctx:messages[0][content]f\n\n{wk_ctx}# 感官记忆最近对话messages.extend(self.sensory.get_context())returnmessagesdeflearn_from_conversation(self):从对话中提取值得记住的信息# 简化实现让 LLM 总结对话中的关键信息recentself.sensory.get_context()iflen(recent)4:returnsummary_promptf从以下对话中提取值得长期记住的信息用户偏好、关键知识。 只输出 JSON 格式 {{preferences: [{{key: xxx, value: xxx}}], learned: [xxx]}} 对话{json.dumps(recent[-6:],ensure_asciiFalse)}# 调用 LLM 提取这里简化处理# result local_chat(summary_prompt)# parsed json.loads(result)# for p in parsed.get(preferences, []):# self.long_term.add_preference(p[key], p[value])pass使用示例# 初始化memoryAgentMemory()# 模拟对话memory.add_turn(user,帮我写一篇关于 Python 的文章风格要口语化)memory.add_turn(assistant,好的我来写一篇口语化的 Python 文章...)memory.add_turn(user,不错但代码注释太少了)memory.add_turn(assistant,明白了以后代码我会加更多注释)# 记住用户偏好memory.long_term.add_preference(写作风格,口语化)memory.long_term.add_preference(代码要求,需要详细注释)# 下次对话时Agent 自动知道用户的偏好messagesmemory.build_prompt(你是一个技术写作助手)# messages 会包含[系统提示 用户偏好 工作记忆 最近对话]记忆压缩对话太长怎么办对话超过 20 轮后token 会超限。这时候需要压缩把旧对话总结成摘要只保留最近几轮原文。defcompress_history(history,keep_recent6):压缩对话历史旧的总结成摘要最近的保留原文iflen(history)keep_recent:returnhistory oldhistory[:-keep_recent]recenthistory[-keep_recent:]# 让 LLM 总结旧对话old_textjson.dumps(old,ensure_asciiFalse)summary_promptf用 100 字总结这段对话的要点\n{old_text}summarylocal_chat(summary_prompt)# 用摘要替代旧对话compressed[{role:system,content:f[历史摘要]{summary}}]compressed.extend(recent)returncompressed踩坑记录坑 1记忆太多prompt 超限症状长期记忆存了几百条全部塞进 prompt 直接超 token 限制。原因没有限制记忆的长度。解决长期记忆只取最近 10 条偏好只取 top 5 最重要的。坑 2记忆过时症状用户 3 个月前说我喜欢蓝色现在说我喜欢红色Agent 还是推荐蓝色。原因旧偏好没有被更新新旧共存。解决偏好用 key-value 结构同 key 的自动覆盖旧值。坑 3记忆冲突症状用户说我喜欢简洁但后来又说这篇文章太短了要详细点。两个偏好矛盾。原因没有冲突检测和解决机制。解决新偏好优先。或者在 prompt 里告诉 Agent如果偏好有冲突以最新的为准。坑 4从对话中自动提取记忆不准症状让 LLM 自动总结对话中的关键信息经常提取错误或者遗漏。原因LLM 的总结能力有限尤其是长对话。解决不要完全自动关键偏好让用户手动确认。或者用更简单的规则提取正则匹配关键词。坑 5隐私问题症状Agent 记住了用户的敏感信息手机号、地址存在文件里不安全。原因没有做敏感信息过滤。解决提取记忆时加一层过滤手机号、身份证号等不存入长期记忆。坑 6多用户记忆混淆症状同一个 Agent 服务多个用户把 A 的偏好用在了 B 身上。原因记忆没有按用户隔离。解决每个用户一个独立的记忆文件/数据库按 user_id 隔离。总结3 条核心经验3 层记忆各司其职。感官记忆管最近对话工作记忆管当前任务长期记忆管用户画像。不要混在一起。记忆要压缩。对话超过 20 轮就总结旧的只保留最近几轮原文。否则 token 会爆。新偏好覆盖旧偏好。用户今天说的比 3 个月前说的更重要。用 key-value 结构自动覆盖。你在开发 AI Agent 时遇到过记忆相关的问题吗评论区交流。