当前位置: 首页 > news >正文

LangChain 短期记忆 --(Short-term Memory)

一、短期记忆是什么?

▎ 短期记忆让您的应用程序能够记住单个线程或对话中的先前交互。

打个比方:短期记忆就是"这一通电话里的记性"——你跟智能体在这一个对话中聊过的所有内容,它都记得。但换一个对话(挂断重拨)
,就从头开始。

关键概念:线程(thread)

▎ 线程将一次会话中的多次交互组织起来,类似于电子邮件将消息归入单个对话中的方式。

一句话:一个线程 = 一次连续对话。短期记忆就是"按线程保存的记忆"。


二、为什么需要专门管理短期记忆?

几个痛点:

  1. 上下文窗口有限:完整对话历史可能塞不进 LLM 的上下文窗口,导致"上下文丢失或错误"。
  2. 长上下文表现变差:即使模型支持长上下文,也会因陈旧/无关内容"分心",且响应变慢、成本增加。
  3. 消息会不断增长:聊天中人类输入和模型回复交替,消息列表越来越长。

所以需要"移除或遗忘陈旧信息"的技术来管理记忆。

▎ 区分:要记住跨对话的信息,请用长期记忆(store),本文讲的是短期记忆(单线程内)。


三、怎么启用短期记忆?—— checkpointer

核心一句话:

▎ 要为智能体添加短期记忆,需要在创建智能体时指定一个 checkpointer(检查点器)。

checkpointer 就是负责"把状态存下来、下次能恢复"的组件。最简单的内存版:

fromlangchain.agentsimportcreate_agentfromlanggraph.checkpoint.memoryimportInMemorySaver agent=create_agent("gpt-5.4",tools=[get_user_info],checkpointer=InMemorySaver(),# 关键:加 checkpointer)# 调用时用 thread_id 标识"这是哪个对话"agent.invoke({"messages":[{"role":"user","content":"Hi! My name is Bob."}]},{"configurable":{"thread_id":"1"}},# 线程 ID)

两个关键点:

  • checkpointer:决定记忆存哪(内存/数据库)
  • thread_id:标识哪个对话线程,相同 thread_id = 同一个对话

生产环境:用数据库版 checkpointer

InMemorySaver 重启就丢,生产要用持久化的,比如 Postgres:

pip install langgraph-checkpoint-postgresfromlanggraph.checkpoint.postgresimportPostgresSaver DB_URI="postgresql://postgres:postgres@localhost:5442/postgres?sslmode=disable"withPostgresSaver.from_conn_string(DB_URI)ascheckpointer:checkpointer.setup()# 自动建表agent=create_agent("gpt-5.4",tools=[get_user_info],checkpointer=checkpointer,)

短期记忆的工作机制

  • 短期记忆作为智能体状态的一部分管理,存在图状态里
  • 通过 checkpointer 持久化到数据库(或内存),线程可随时恢复
  • 更新时机:调用智能体或完成一步(如工具调用)时更新
  • 读取时机:每一步开始时读取状态

四、自定义智能体记忆

默认智能体用 AgentState 管理短期记忆(通过 messages 键存对话历史)。你可以扩展 AgentState 添加额外字段:

fromlangchain.agentsimportcreate_agent,AgentStatefromlanggraph.checkpoint.memoryimportInMemorySaverclassCustomAgentState(AgentState):user_id:strpreferences:dictagent=create_agent("gpt-5.4",tools=[get_user_info],state_schema=CustomAgentState,# 传入自定义状态checkpointer=InMemorySaver(),)# 调用时可以传入自定义状态字段result=agent.invoke({"messages":[{"role":"user","content":"Hello"}],"user_id":"user_123","preferences":{"theme":"dark"}},{"configurable":{"thread_id":"1"}})

这样除了对话历史,还能在这个线程里记住 user_id、preferences 等额外信息。


五、长对话的管理策略(核心!)

启用短期记忆后,长对话可能超出上下文窗口。页面给出四种常见策略:

策略做法适用场景
截断消息调用 LLM 前移除部分消息(保留最近的)防止超出 token 上限
删除消息永久删除 LangGraph 状态中的消息移除特定消息或清空历史
总结消息总结早期消息,用摘要替换它们既省空间又尽量不丢信息
自定义策略如消息过滤等特殊需求

策略 1:截断消息(@before_model 中间件)

用 @before_model 中间件,在调用模型之前修剪消息历史。思路是:保留第一条消息 + 最近几条,中间的丢掉:

fromlangchain.messagesimportRemoveMessagefromlanggraph.graph.messageimportREMOVE_ALL_MESSAGESfromlangchain.agentsimportcreate_agent,AgentStatefromlangchain.agents.middlewareimportbefore_modelfromlanggraph.runtimeimportRuntimefromtypingimportAny@before_modeldeftrim_messages(state:AgentState,runtime:Runtime)->dict[str,Any]|None:"""Keep only the last few messages to fit context window."""messages=state["messages"]iflen(messages)<=3:# 消息不多就不用动returnNonefirst_msg=messages[0]# 保留第一条recent_messages=messages[-3:]# 保留最近几条new_messages=[first_msg]+recent_messagesreturn{"messages":[RemoveMessage(id=REMOVE_ALL_MESSAGES),# 先清空*new_messages# 再放回保留的]}agent=create_agent("gpt-5-nano",tools=[],middleware=[trim_messages],# 挂上中间件checkpointer=InMemorySaver(),)

效果:即使中间聊了很多轮,模型也只看到"开头 + 最近几条"


策略 2:删除消息(RemoveMessage)

用 RemoveMessage 删除特定消息或全部消息。需要状态键带 add_messages reducer(默认 AgentState 已提供)。

删除特定消息(最早的 2 条):

fromlangchain.messagesimportRemoveMessagedefdelete_messages(state):messages=state["messages"]iflen(messages)>2:return{"messages":[RemoveMessage(id=m.id)forminmessages[:2]]}

删除所有消息:

fromlanggraph.graph.messageimportREMOVE_ALL_MESSAGESdefdelete_messages(state):return{"messages":[RemoveMessage(id=REMOVE_ALL_MESSAGES)]}

⚠️ 重要提醒:删除消息后要确保消息历史仍然有效,否则模型会报错:

  • 某些厂商要求消息历史以 user 消息开头
  • 大多数厂商要求带工具调用的 assistant 消息后必须跟对应的 tool 结果消息(不能拆散)

实战中常用 @after_model 中间件在模型回复后删除旧消息:

fromlangchain.agents.middlewareimportafter_model@after_modeldefdelete_old_messages(state:AgentState,runtime:Runtime)->dict|None:"""Remove old messages to keep conversation manageable."""messages=state["messages"]iflen(messages)>2:return{"messages":[RemoveMessage(id=m.id)forminmessages[:2]]}returnNoneagent=create_agent("gpt-5-nano",tools=[],system_prompt="Please be concise and to the point.",middleware=[delete_old_messages],checkpointer=InMemorySaver(),)

策略 3:总结消息(SummarizationMiddleware)

截断/删除的问题:会丢失信息。更聪明的方法是用模型把早期消息总结成摘要,再用摘要替换它们。

LangChain 提供内置的 SummarizationMiddleware:

fromlangchain.agentsimportcreate_agentfromlangchain.agents.middlewareimportSummarizationMiddleware agent=create_agent(model="gpt-5.4",tools=[],middleware=[SummarizationMiddleware(model="gpt-5.4-mini",# 用小模型做总结,省钱trigger=("tokens",4000),# 触发条件:token 达到 4000keep=("messages",20)# 保留最近 20 条消息不总结)],checkpointer=InMemorySaver(),)

三个参数:

  • model:用哪个模型做总结(推荐用便宜的小模型)
  • trigger:什么时候触发总结(这里设为 token 数到 4000)
  • keep:保留多少条最近消息不被总结

效果:长对话中,早期内容被压缩成摘要,模型既能看到历史梗概,又不会超出窗口


六、访问短期记忆的三种途径

短期记忆(状态)可以通过三个地方访问和修改:

途径 1:工具里访问(runtime.state)

用 ToolRuntime 参数在工具中读写状态(对模型隐藏):

fromlangchain.toolsimporttool,ToolRuntimefromlangchain.agentsimportcreate_agent,AgentStateclassCustomState(AgentState):user_id:str@tooldefget_user_info(runtime:ToolRuntime)->str:"""Look up user info."""user_id=runtime.state["user_id"]# 读短期记忆return"User is John Smith"ifuser_id=="user_123"else"Unknown user"

工具还能写入短期记忆——直接返回 Command(update={…}):

fromlanggraph.typesimportCommandfromlangchain.messagesimportToolMessage@tooldefupdate_user_info(runtime:ToolRuntime[CustomContext,CustomState])->Command:"""Look up and update user info."""user_id=runtime.context.user_id name="John Smith"ifuser_id=="user_123"else"Unknown user"returnCommand(update={"user_name":name,# 写入自定义状态字段"messages":[ToolMessage("Successfully looked up user information",tool_call_id=runtime.tool_call_id)]})

途径 2:提示里访问(@dynamic_prompt 中间件)

根据状态/上下文生成动态系统提示:

fromlangchain.agents.middlewareimportdynamic_prompt,ModelRequestclassCustomContext(TypedDict):user_name:str@dynamic_promptdefdynamic_system_prompt(request:ModelRequest)->str:user_name=request.runtime.context["user_name"]returnf"You are a helpful assistant. Address the user as{user_name}."agent=create_agent(model="gpt-5-nano",tools=[get_weather],middleware=[dynamic_system_prompt],context_schema=CustomContext,)

效果:系统提示会变成 “Address the user as John Smith”,模型回复时就会称呼用户名字。


途径 3:模型执行前/后访问(@before_model / @after_model)

  • @before_model:调用模型前处理消息(如截断历史)
  • @after_model:调用模型后处理消息(如删除含敏感词的回复)
fromlangchain.agents.middlewareimportafter_model@after_modeldefvalidate_response(state:AgentState,runtime:Runtime)->dict|None:"""Remove messages containing sensitive words."""STOP_WORDS=["password","secret"]last_message=state["messages"][-1]ifany(wordinlast_message.contentforwordinSTOP_WORDS):return{"messages":[RemoveMessage(id=last_message.id)]}returnNone

七、访问记忆途径总览

途径装饰器/方式时机典型用途
工具runtime: ToolRuntime工具执行时在工具中读写状态
提示@dynamic_prompt生成系统提示时根据状态/上下文定制提示
模型执行前@before_model调用模型前截断/修剪消息历史
模型执行后@after_model调用模型后删除敏感词、清理消息

八、一句话总结

▎ 短期记忆 = 单个线程(对话)内的记忆,靠 checkpointer + thread_id 实现"同一对话记得住、能恢复"。
▎ 长对话靠四种策略管理:截断 / 删除 / 总结 /自定义。
▎ 访问记忆有四个切入点:工具(runtime.state)、动态提示(@dynamic_prompt)、模型执行前(@before_model)、模型执行后(@after_model)。


九、和前几讲的关系

把这几讲串起来:

  • 短期记忆:线程内对话历史,存 state[“messages”],靠 checkpointer 持久化
  • 长期记忆(store):跨线程永久保存,靠 runtime.store
  • 工具访问上下文:工具用 runtime.state / runtime.context / runtime.store 读写这些记忆
  • 消息(messages):短期记忆的载体,四种类型组成对话历史

一句话:短期记忆是"这次通话的草稿纸",checkpointer 是"草稿纸的存档",thread_id 是"通话编号"。

http://www.jsqmd.com/news/1100783/

相关文章:

  • AutoTask:Android自动化助手终极指南,释放手机潜能
  • 如何用ShaderGlass为Windows桌面添加实时视觉特效:完整实践指南
  • AI-Agent 中 Function-Calling 机制技术报告
  • 叶黄素和花青素哪个对眼睛好?两大热门护眼成分全面对比
  • 从思科课堂到华三机房:H3C交换机基础命令保姆级迁移指南
  • 终极自动化革命:AutoTask如何彻底改变你的手机使用习惯
  • 从RAG到LangGraph:大模型应用开发核心技术与面试实战指南
  • 别再只盯着耦合效率了!用OpticStudio的POP功能,从光束质量M²值重新审视你的单模光纤耦合设计
  • 怎么防止图纸泄密?分享5种方法有效防止图纸泄密,赶紧收藏
  • 青少年视力健康告急!叶黄素能帮什么忙?
  • 解放双手的智能助手:taskt自动化工具深度指南
  • C++11 std::thread 实现
  • Java毕业设计-基于 SpringBoot 的车险寿险业务运维与数据统计系统的设计与实现 基于 SpringBoot 的保险企业业务数据可视化(源码+LW+部署文档+全bao+远程调试+代码讲解等)
  • 别再死磕手册了!手把手教你用Vivado 2023.1搞定7系列FPGA的GTX收发器IP核配置
  • 2026年贵阳本地生活优惠新趋势
  • 告别真机调试!用Unidbg在Windows/Mac上模拟运行Android SO文件(保姆级环境搭建)
  • DX-BT24蓝牙模块保姆级配置指南:从串口调试到手机APP透传,一次搞定
  • 信息化监理在国企信息化建设项目中的关键作用
  • 长期久坐肌肉紧绷?草本外用贴剂日常养护科普
  • 第一章Netty,Selector之Read读事件
  • Windows系统下Drozer环境搭建与Android应用渗透测试实战指南
  • 星辰变:归来手游官网下载:星辰变:归来最新官方下载渠道
  • Burp Suite插件HaE实战:基于正则的敏感信息提取与自动化安全测试
  • 12分钟零成本部署DeepSeek-Coder:打造媲美Copilot的本地AI编程助手
  • 【万字文档+源码】小程序小区服务平台-可用于毕设-课程设计-练手学习-学习资料分享
  • AI 赋能自媒体全链路实操,广告、分销、私域复利增收全套方案
  • 逆向工程实战:从零破解a_bogus签名参数生成算法
  • 给嵌入式工程师的AutoSAR-CP入门指南:从STM32库到汽车软件架构的思维转变
  • OpenMontage:开源AI视频自动化流水线,打通从文本到成片全链路
  • 青蓝送水商城小程序开发(快速上线)