大模型开发手记(六):LangChain Agent 记忆系统:短期记忆

发布时间:2026/7/31 18:40:37

大模型开发手记(六):LangChain Agent 记忆系统:短期记忆 目录前言一、基本概念1.1 短期记忆1.2 长期记忆1.3 短期记忆的完整工作闭环二、短期记忆开发落地2.1 内存存储2.2 持久化存储2.3 自定义记忆状态 Schema三、长对话记忆管理3.1 修剪/删除消息3.2 总结历史消息前言这一篇博客主要总结agent的短期记忆这块内容什么是记忆我们可以狭义的理解为human、ai、tool等agent的对话上下文的存储、管理和获取。大模型本身是无状态的每一次调用都是独立的无法记住上一轮对话的内容此时就需要记忆系统把我们与大模型之前的聊天记录存储起来等下轮对话的时候再通过记忆系统给他这就是记忆系统的作用。但是有了记忆系统也会出现新的问题就是对话上下文过长长对话带来的上下文膨胀不仅会让模型被无关信息干扰、推理能力下降还会导致 token 成本飙升、超出模型上下文窗口限制。LangChain 的 Agent 记忆体系就是为了解决这些核心问题而生。一、基本概念讲短期记忆之前我们先弄明白长期记忆和短期记忆的区别短期记忆和长期记忆并不是存储介质的区别。1.1 短期记忆LangChain 的短期记忆是单线程此线程非彼线程 / 单对话内的交互记忆是 LangGraph 框架下为 Agent 设计的对话级上下文管理 能力说白了就是基于当前会话一个会话就是一个线程一个会话包含多次对话把每次对话中间产生的message存起来内存或者pg数据库等下次同一个会话的下一次对话把之前的对话历史拉出来让大模型理解全局会话的上下文这就是短期记忆的意义。核心特征核心载体AgentState的messages键会话历史是短期记忆的唯一核心持久化级别线程级不同会话线程thread_id的记忆完全分离仅服务于当前会话管理方式由checkpointerInMemorySaver/PostgresSaver管理随 Agent 步骤更新可随时恢复线程核心限制受 LLM上下文窗口约束长对话会出现上下文丢失需通过修剪、删除、总结文档中的before_model/after_model中间件处理核心作用保证单个会话内的上下文连贯性让 Agent 记住当前会话的前序交互比如记住用户刚说的名字、当前问题的背景。简单说短期记忆是 Agent 的「当下会话记忆」只管 “现在这个聊天里说了什么”。1.2 长期记忆langChain 的长期记忆是跨会话、跨线程的用户级 / 全局级持久化记忆是基于langchain.memory基类BaseMemory设计的全局信息存储能力说白了就是提取每次会话的短期记忆中的非常重要的message经过处理之后存入向量库或者数据库。等开启对话的时候拉出来作为上下文核心特征为核心载体ConversationSummaryMemory/VectorStoreMemory/EntityMemory等专用组件存储用户长期信息偏好、个人信息、会话关键结论、历史交互核心内容持久化级别用户级 / 全局级跨所有会话线程管理方式通过总结压缩如ConversationSummaryMemory或向量存储如VectorStoreMemory实现持久化需主动提取 / 写入关键信息核心限制无上下文窗口约束但需避免信息冗余依赖 RAG检索增强提取相关信息核心作用实现跨对话的信息复用让 Agent 记住用户的长期特征比如记住用户的职业、喜欢的产品、历史任务的结论。简单说长期记忆是 Agent 的「永久用户记忆」管 “这个用户之前所有聊天里的关键信息”。1.3 短期记忆的完整工作闭环和 Tools 的调用闭环一样记忆系统也有一套完整的执行流贯穿 Agent 的整个生命周期初始化绑定创建 Agent 时指定 Checkpointer 和 State Schema完成记忆系统的初始化状态读取调用 Agent 时传入thread_idCheckpointer 自动读取该会话的历史状态加载到 Agent 的执行上下文中前置处理在模型调用前可通过中间件对记忆中的历史消息做修剪、总结、过滤等优化处理执行更新模型推理、工具调用完成后新生成的消息、状态变更会同步更新到 State 中持久化落盘Agent 执行步骤完成后最新的 State 会通过 Checkpointer 持久化到存储中完成记忆更新上下文延续下一次同thread_id调用时会自动加载之前完整的记忆实现多轮对话的上下文连贯二、短期记忆开发落地开启 Agent 短期记忆的核心只需要两步给 Agent 绑定 Checkpointer、调用时传入 thread_id。2.1 内存存储最基础的内存级记忆实现适合本地开发、测试场景fromlangchain.agentsimportcreate_agentfromlangchain_openaiimportChatOpenAIfromlanggraph.checkpoint.memoryimportInMemorySaver# 内存级Checkpointerfromlangchain.toolsimporttool# 定义一个简单工具tooldefget_user_info(user_id:str)-str:获取用户的基础信息user_info{user_123:姓名张三职位产品经理所在城市北京,user_456:姓名李四职位研发工程师所在城市上海}returnuser_info.get(user_id,未找到对应用户)# 初始化模型modelChatOpenAI(modelgpt-4o,api_key你的API_KEY)# 核心1创建Checkpointer用于持久化记忆checkpointerInMemorySaver()# 创建Agent绑定Checkpointer开启短期记忆agentcreate_agent(modelmodel,tools[get_user_info],checkpointercheckpointer,# 核心绑定记忆持久化组件system_prompt你是一个贴心的智能助手记住用户的信息和过往对话内容)# 核心2调用时指定thread_id用于会话隔离config{configurable:{thread_id:user_conversation_001}}# 第一轮对话用户告知信息agent.invoke({messages:[{role:user,content:你好我的用户ID是user_123你可以叫我小张}]},configconfig)# 第二轮对话无需重复信息Agent通过记忆自动获取resultagent.invoke({messages:[{role:user,content:我的个人信息是什么}]},configconfig)# 打印最终回复print(result[messages][-1].content)# 输出小张你的个人信息是姓名张三职位产品经理所在城市北京2.2 持久化存储本地开发用的InMemorySaver是基于内存存储的服务重启后记忆就会丢失完全不适合生产环境。LangChain 官方提供了基于 PostgreSQL 的生产级 Checkpointer实现记忆的持久化落盘、服务重启不丢失。值得注意的是存储介质不是区分长期记忆和短期记忆的标准用数据库存储是为了解决服务重启后临时记忆缺失的问题并不是长期记忆fromlangchain.agentsimportcreate_agentfromlangchain_openaiimportChatOpenAIfromlanggraph.checkpoint.postgresimportPostgresSaver# PostgreSQL版Checkpointerfromlangchain.toolsimporttool# 工具与模型初始化tooldefget_user_info(user_id:str)-str:获取用户的基础信息return姓名张三职位产品经理所在城市北京modelChatOpenAI(modelgpt-4o,api_key你的API_KEY)# 数据库连接URI支持连接池、SSL配置等生产级参数DB_URIpostgresql://账号:密码数据库地址:端口/数据库名?sslmodedisable# 生产环境核心使用PostgresSaver实现持久化withPostgresSaver.from_conn_string(DB_URI)ascheckpointer:# 自动创建Checkpoint所需的表结构仅首次执行需要checkpointer.setup()# 创建绑定了生产级Checkpointer的Agentagentcreate_agent(modelmodel,tools[get_user_info],checkpointercheckpointer,system_prompt你是一个贴心的智能助手记住用户的信息和过往对话内容)# 会话配置thread_id可关联用户ID会话ID实现多用户多会话隔离config{configurable:{thread_id:prod_user_123_conv_001}}# 调用Agent记忆会自动持久化到PostgreSQL中resultagent.invoke({messages:[{role:user,content:你好我叫张三来自北京}]},configconfig)print(result[messages][-1].content)数据库需提前创建好对应的库setup()方法会自动创建所需的 4 张核心表无需手动建表2.3 自定义记忆状态 Schema默认的AgentState仅提供了messages字段用于存储会话历史但在真实业务场景中我们往往需要存储更多的会话级数据比如用户 ID、用户偏好、业务上下文、中间执行结果等。LangChain 支持完全自定义扩展 AgentState实现个性化的记忆字段管理fromlangchain.agentsimportcreate_agent,AgentStatefromlangchain_openaiimportChatOpenAIfromlanggraph.checkpoint.memoryimportInMemorySaverfrompydanticimportBaseModel,FieldfromtypingimportDict,List# 核心扩展AgentState自定义记忆字段classCustomAgentState(AgentState):自定义Agent状态扩展业务所需的记忆字段user_id:strField(description用户唯一标识)user_preferences:DictField(description用户偏好设置,default_factorydict)business_context:List[str]Field(description业务上下文信息,default_factorylist)# 模型与Checkpointer初始化modelChatOpenAI(modelgpt-4o,api_key你的API_KEY)checkpointerInMemorySaver()# 创建Agent指定自定义的状态Schemaagentcreate_agent(modelmodel,tools[],state_schemaCustomAgentState,# 核心传入自定义状态checkpointercheckpointer,system_prompt你是一个个性化的智能助手根据用户偏好提供服务)# 会话配置config{configurable:{thread_id:custom_state_conv_001}}# 首次调用传入自定义的记忆字段resultagent.invoke({messages:[{role:user,content:你好帮我设置一下我的偏好}],user_id:user_123,user_preferences:{theme:深色模式,language:中文,reply_style:简洁干练},business_context:[用户正在咨询产品续费相关问题,用户是企业版年付客户]},configconfig)# 后续调用无需重复传入Agent可直接从记忆中读取这些自定义字段next_resultagent.invoke({messages:[{role:user,content:按照我的偏好介绍一下企业版续费政策}]},configconfig)三、长对话记忆管理开启短期记忆后我们会立刻遇到一个核心问题随着对话轮次增加消息列表会越来越长最终超出 LLM 的上下文窗口限制导致模型报错、推理能力下降、token 成本飙升。针对这个生产环境的核心痛点LangChain 提供了 4 种成熟的记忆管理模式帮我们平衡上下文完整性和窗口限制3.1 修剪/删除消息我们可以在中间件后续会讲到中对message列表进行修剪或删除已达到控制会话上下文长度的目的中间件中修改 AgentState 的 messages 列表核心依赖返回值类型返回 BaseMessage 消息列表默认会添加在原列表之后返回 RemoveMessage 指令列表则仅删除指定消息。LangGraph agent底层中工具和中间件修改 AgentState 的方式差异核心源于二者设计定位与执行机制不同。中间件before_model/after_model是专为 Agent 状态处理设计的流程钩子执行上下文直接对接 AgentState框架原生支持返回字典键对应状态字段更新状态无需额外封装轻量化适配状态预处理 / 清理场景。而工具的核心定位是执行业务逻辑如调用接口、数据计算其默认返回值会被封装为 ToolMessage 作为业务结果而非状态更新指令且工具执行环境与 Agent 核心流程隔离需通过 Command 对象显式声明状态更新以此区分普通业务返回和状态修改请求确保框架能识别并跨隔离环境处理状态更新需求。# 示例1在 before_model 中执行删除操作返回 RemoveMessagebefore_modeldefdelete_old_in_before(state:AgentState,runtime:Runtime)-dict|None:messagesstate[messages]iflen(messages)6:# 返回 RemoveMessage 列表 → 执行删除操作delete_instructions[RemoveMessage(idm.id)forminmessages[:2]]return{messages:delete_instructions}returnNone# 示例2在 after_model 中执行修剪操作返回 BaseMessage 列表after_modeldeftrim_in_after(state:AgentState,runtime:Runtime)-dict|None:messagesstate[messages]iflen(messages)5:returnNone# 返回 BaseMessage 列表 → 执行替换修剪操作first_system_msgmessages[0]recent_messagesmessages[-4:]trimmed_messages[first_system_msg]recent_messagesreturn{messages:trimmed_messages}3.2 总结历史消息修剪和删除消息的最大问题是会丢失关键的历史信息而总结模式则是通过 LLM 对较早的历史消息进行总结用简短的摘要替换冗长的原始消息既控制了 token 占用又保留了核心的上下文信息。适用场景长对话中需要保留全程的核心信息不能简单截断比如客服对话、需求沟通、长流程任务执行等场景。LangChain 提供了开箱即用的SummarizationMiddleware无需自己写总结逻辑一行配置即可实现自动总结默认情况下总结完成后的内容会直接追加到原始 SystemMessage 的末尾最终合并为单条 SystemMessage既保留了初始的代理规则又补充了历史会话的摘要信息保证消息结构的规范性。总结的范围只是ai、human、tool这些agentstate中的message列表历史会话内容不会将systemmessage也参与总结fromlangchain.agentsimportcreate_agentfromlangchain.agents.middlewareimportSummarizationMiddlewarefromlangchain_openaiimportChatOpenAIfromlanggraph.checkpoint.memoryimportInMemorySaver# 初始化模型与CheckpointermodelChatOpenAI(modelgpt-4o,api_key你的API_KEY)checkpointerInMemorySaver()# 创建Agent绑定总结中间件agentcreate_agent(modelmodel,tools[],middleware[# 核心消息总结中间件SummarizationMiddleware(modelgpt-4o-mini,# 用于总结的模型推荐用低成本小模型max_tokens_before_summary2000,# 消息token超过2000时触发总结messages_to_keep10,# 总结后保留最近的10条原始消息)],checkpointercheckpointer,)# 会话配置config{configurable:{thread_id:summary_test_001}}# 多轮长对话历史会被自动总结核心信息不会丢失agent.invoke({messages:你好我叫小张今年28岁在北京做产品经理},config)

相关新闻