记忆,让 Agent 从"工具"变成"助手"一个没有记忆的 Agent,每次对话都是从零开始。你告诉它你叫李雷、你是 Python 工程师、你喜欢动手实践——下次对话,它完全不记得。这不是 Bug,是架构缺失。LLM 本身没有持久记忆,每次调用都是无状态的。要让 Agent 记住事情,需要在架构层显式地存储、管理和读取记忆。这就是记忆管理模块要解决的问题。本篇从四个维度拆解 Agent 记忆:记忆类型的分类模型、上下文管理的三种策略、LangGraph 提供的两种记忆机制(checkpointer 和 store)、以及超长对话的自动压缩方案。四种记忆类型:从认知科学到工程实现借鉴认知科学对人类记忆的分类,Agent 的记忆也可以分为四层,每一层在 LangGraph 中都有对应的实现方式:┌──────────────────────────────────────────────────────────┐ │ 记忆层级 │ ├──────────────────────┬───────────────────────────────────┤ │ 感觉记忆 (Sensory) │ 当前 Turn 的 in-flight 消息 │ │ │ 生命周期:单次 LLM 调用 │ ├──────────────────────┼───────────────────────────────────┤ │ 工作记忆 (Working) │ 对话历史 MessageHistory(有限 K 轮)│ │ │ 实现:messages 列表注入 Prompt │ ├──────────────────────┼───────────────────────────────────┤ │ 情景记忆 (Episodic) │ 向量化/摘要化的历史片段 │ │ │ 实现:摘要压缩 + VectorStore 检索 │ ├──────────────────────┼───────────────────────────────────┤ │ 语义记忆 (Semantic) │ 长期存储的用户偏好、事实 │ │ │ 实现:LangGraph store (KV Store) │ └──────────────────────┴───────────────────────────────────┘感觉记忆:当前 Turn 的消息最短暂的记忆。一次 LLM 调用的输入和输出,用完即弃:q="Python 中 len([1, 2, 3]) 等于多少"answer=llm.invoke([HumanMessage(q)])# answer.content → "len([1, 2, 3]) 的结果等于 3。"# 这次 invoke 结束后,这个 answer 就消失了不需要任何机制来"管理"感觉记忆——它是 LLM 调用本身。工作记忆:有限的对话历史把之前几轮对话消息拼接进 Prompt,是最直接的记忆实现。效果立竿见影:history=[HumanMessage("我叫李雷,是一名 Python 工程师"),AIMessage("你好,李雷!很高兴认识你。"),HumanMessage("我最近在学习 LangGraph"),AIMessage("LangGraph 很强大,特别适合构建有状态的 Agent。"),]test_q="我之前告诉你我叫什么名字?"实测对比:有历史 → "是的,你之前告诉我你的名字是李雷,并且你是一名 Python 工程师..." 无历史 → "抱歉,我无法回忆起您之前告诉我的名字,因为作为一个 AI,我没有 持久的记忆功能来存储个人数据..."差距非常直观。工作记忆的限制是 Token 成本随对话长度线性增长,需要结合截断或摘要来管理。情景记忆:摘要化的历史片段当对话历史很长时,把全部历史直接塞进 Prompt 代价太高。情景记忆的做法是先压缩,再存储:long_history=history*4# 16 条消息summary=llm.invoke([SystemMessage("将以下对话压缩为 60 字以内的摘要,保留关键信息"),HumanMessage(str([m.contentforminlong_history])),])# → "李雷,Python工程师,积极学习LangGraph,赞其强大,适合构建有状态Agent。"16 条消息压缩成 28 个字,下一轮用摘要代替原始历史,Token 消耗大幅下降。语义记忆:跨会话的用户事实最持久的记忆层。不随对话结束而消失,专门存储关于用户的长期事实(姓名、职业、偏好等):# 把用户信息存入 KV Store,下一次会话直接读取user_profile={"name":"李雷","role":"Python 工程师","interests":["LangGraph","Agent 开发"],"level":"中级",}# 基于这些信息,Agent 能给出个性化的回答# "下一步学习方向
Agent系列(六):记忆管理——让 Agent 记住重要的事
记忆,让 Agent 从"工具"变成"助手"一个没有记忆的 Agent,每次对话都是从零开始。你告诉它你叫李雷、你是 Python 工程师、你喜欢动手实践——下次对话,它完全不记得。这不是 Bug,是架构缺失。LLM 本身没有持久记忆,每次调用都是无状态的。要让 Agent 记住事情,需要在架构层显式地存储、管理和读取记忆。这就是记忆管理模块要解决的问题。本篇从四个维度拆解 Agent 记忆:记忆类型的分类模型、上下文管理的三种策略、LangGraph 提供的两种记忆机制(checkpointer 和 store)、以及超长对话的自动压缩方案。四种记忆类型:从认知科学到工程实现借鉴认知科学对人类记忆的分类,Agent 的记忆也可以分为四层,每一层在 LangGraph 中都有对应的实现方式:┌──────────────────────────────────────────────────────────┐ │ 记忆层级 │ ├──────────────────────┬───────────────────────────────────┤ │ 感觉记忆 (Sensory) │ 当前 Turn 的 in-flight 消息 │ │ │ 生命周期:单次 LLM 调用 │ ├──────────────────────┼───────────────────────────────────┤ │ 工作记忆 (Working) │ 对话历史 MessageHistory(有限 K 轮)│ │ │ 实现:messages 列表注入 Prompt │ ├──────────────────────┼───────────────────────────────────┤ │ 情景记忆 (Episodic) │ 向量化/摘要化的历史片段 │ │ │ 实现:摘要压缩 + VectorStore 检索 │ ├──────────────────────┼───────────────────────────────────┤ │ 语义记忆 (Semantic) │ 长期存储的用户偏好、事实 │ │ │ 实现:LangGraph store (KV Store) │ └──────────────────────┴───────────────────────────────────┘感觉记忆:当前 Turn 的消息最短暂的记忆。一次 LLM 调用的输入和输出,用完即弃:q="Python 中 len([1, 2, 3]) 等于多少"answer=llm.invoke([HumanMessage(q)])# answer.content → "len([1, 2, 3]) 的结果等于 3。"# 这次 invoke 结束后,这个 answer 就消失了不需要任何机制来"管理"感觉记忆——它是 LLM 调用本身。工作记忆:有限的对话历史把之前几轮对话消息拼接进 Prompt,是最直接的记忆实现。效果立竿见影:history=[HumanMessage("我叫李雷,是一名 Python 工程师"),AIMessage("你好,李雷!很高兴认识你。"),HumanMessage("我最近在学习 LangGraph"),AIMessage("LangGraph 很强大,特别适合构建有状态的 Agent。"),]test_q="我之前告诉你我叫什么名字?"实测对比:有历史 → "是的,你之前告诉我你的名字是李雷,并且你是一名 Python 工程师..." 无历史 → "抱歉,我无法回忆起您之前告诉我的名字,因为作为一个 AI,我没有 持久的记忆功能来存储个人数据..."差距非常直观。工作记忆的限制是 Token 成本随对话长度线性增长,需要结合截断或摘要来管理。情景记忆:摘要化的历史片段当对话历史很长时,把全部历史直接塞进 Prompt 代价太高。情景记忆的做法是先压缩,再存储:long_history=history*4# 16 条消息summary=llm.invoke([SystemMessage("将以下对话压缩为 60 字以内的摘要,保留关键信息"),HumanMessage(str([m.contentforminlong_history])),])# → "李雷,Python工程师,积极学习LangGraph,赞其强大,适合构建有状态Agent。"16 条消息压缩成 28 个字,下一轮用摘要代替原始历史,Token 消耗大幅下降。语义记忆:跨会话的用户事实最持久的记忆层。不随对话结束而消失,专门存储关于用户的长期事实(姓名、职业、偏好等):# 把用户信息存入 KV Store,下一次会话直接读取user_profile={"name":"李雷","role":"Python 工程师","interests":["LangGraph","Agent 开发"],"level":"中级",}# 基于这些信息,Agent 能给出个性化的回答# "下一步学习方向