尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

我加了 `InMemorySaver`,为什么 Agent 还是没记忆?

我加了 `InMemorySaver`,为什么 Agent 还是没记忆?
📅 发布时间:2026/7/7 18:06:20

Agent 能调工具之后,我开始做一件看起来很基础但很容易踩坑的事:让 Agent 记住上下文。

我按照文档加了checkpointer=InMemorySaver(),满心期待 Agent 能像 ChatGPT 一样记得上一句。结果第二次运行脚本,它又问"这是我们的第一次对话吗?"

我一度怀疑InMemorySaver是个假的记忆组件。后来才搞明白:不是没记忆,是我的用法让它没法记忆。


一、我当时想干什么

我想实现最简单的多轮对话:

  1. 第一轮:我问"旧金山天气怎么样?"
  2. 第二轮:我问"那明天呢?"
  3. Agent 应该能理解"明天"指的是"旧金山明天的天气"

我写的代码:

fromlangchain.agentsimportcreate_agentfromlangchain_core.toolsimporttoolfromlangchain_core.utils.uuidimportuuid7fromlangchain_openaiimportChatOpenAIfromlanggraph.checkpoint.memoryimportInMemorySaver@tooldefsearch(query:str)->str:"""搜索工具"""returnf"搜索结果:{query}"llm=ChatOpenAI(model="deepseek-chat",temperature=0,openai_api_key="你的 api key",openai_api_base="https://api.deepseek.com/v1",)agent=create_agent(model=llm,tools=[search],checkpointer=InMemorySaver(),)config={"configurable":{"thread_id":str(uuid7())}}result=agent.invoke({"messages":[{"role":"user","content":"旧金山天气怎么样?"}]},config=config,)result=agent.invoke({"messages":[{"role":"user","content":"那明天呢?"}]},config=config,)

在这个脚本里,记忆是工作的。但当我再次运行脚本,问"上一轮我问了什么",Agent 说"这是我们的第一次对话"。


二、我写的代码

要让记忆跨脚本运行保持,必须保证thread_id不变,并且使用持久化存储。测试时最简单的办法是固定thread_id:

# 不要每次都用新的 uuidconfig={"configurable":{"thread_id":"user-chenzc-001"}}

或者把thread_id存到文件里:

importos THREAD_ID_FILE="thread_id.txt"defget_thread_id():ifos.path.exists(THREAD_ID_FILE):withopen(THREAD_ID_FILE,"r")asf:returnf.read().strip()new_id="user-chenzc-001"withopen(THREAD_ID_FILE,"w")asf:f.write(new_id)returnnew_id config={"configurable":{"thread_id":get_thread_id()}}

真正生产环境应该用 SQLite 或 Postgres:

fromlanggraph.checkpoint.sqliteimportSqliteSaverwithSqliteSaver.from_conn_string("checkpoints.sqlite")ascheckpointer:agent=create_agent(model=llm,tools=[search],checkpointer=checkpointer,)

三、我遇到的坑

坑 1:InMemorySaver只存当前进程

我以为InMemorySaver像 Redis 一样会持久化。实际上它就是内存里的一个字典,脚本结束就清空。

fromlanggraph.checkpoint.memoryimportInMemorySaver checkpointer=InMemorySaver()# 这个对象在进程里存数据# 进程结束,数据消失

如果你要跨运行保持记忆,必须换成SqliteSaver或PostgresSaver。

坑 2:uuid7()每次运行都变

我的代码里:

config={"configurable":{"thread_id":str(uuid7())}}

每次运行脚本,uuid7()都会生成一个新的thread_id。LangGraph 把每个新thread_id当成一次全新对话,自然没有历史。

这就好比你每次打开微信都用一个新微信号,当然看不到昨天的聊天记录。

坑 3:流式输出也忘了传config

我改成stream_events后,又踩了一次同样的坑:

stream=agent.stream_events({"messages":[{"role":"user","content":"搜索 AI 新闻并总结"}]},version="v3",)

报错:

KeyError: 'thread_id'

因为 Agent 配置了checkpointer,所以stream_events也必须传config:

stream=agent.stream_events({"messages":[{"role":"user","content":"搜索 AI 新闻并总结"}]},config=config,version="v3",)

坑 4:一次脚本运行只算一轮对话

我最初的测试方式是:运行脚本 → 输入一个问题 → 得到回答 → 脚本退出 → 再次运行脚本。

这种方式下,即使thread_id固定、用了持久化 checkpointer,第二轮运行时 Agent 看到的"历史"也只有第一轮那一条消息。因为脚本一次运行只发了一次invoke。

要测试真正的多轮对话,应该把输入放在while循环里:

config={"configurable":{"thread_id":"user-chenzc-001"}}whileTrue:user_input=input("你:")ifuser_input.lower()in["exit","quit"]:breakresult=agent.invoke({"messages":[{"role":"user","content":user_input}]},config=config,)print(result["messages"][-1].content)

四、搞清楚后的结论

LangChain Agent 的记忆机制有三个层级:

每次 invoke 独立

同一进程内多轮

跨进程持久化

无 checkpointer

无记忆

InMemorySaver + 固定 thread_id

进程内记忆

SqliteSaver/PostgresSaver + 固定 thread_id

长期记忆

关键认知:

  1. checkpointer 负责存,thread_id负责定位是哪次对话
  2. InMemorySaver只保当前进程,重启就丢
  3. uuid7()适合一次会话内的临时 ID,跨运行要用固定 ID 或持久化生成
  4. invoke和stream_events都需要config

五、我的收获

记忆不是默认开启的,它需要你显式地告诉系统"这是谁的对话、存在哪里"。

我以前以为加了checkpointer就万事大吉,结果发现它只是基础设施。真正让记忆生效的是thread_id的一致性和存储介质的持久性。

这件事也让我意识到 LangChain 的设计哲学:它把每个能力都拆成显式配置,而不是隐式魔法。记忆如此,工具如此,Agent 也如此。


下一篇我会写 Middleware——怎么给 Agent 加容错、人工审核和文件操作能力。

相关新闻

  • Airtest自动化测试第二篇:图像识别脚本编写——核心API详解与实战技巧
  • 2026最新7款AI编程工具平替实测合集
  • [SQL实战] 对账总是对不上?先把主键、时间口径和异常明细拆出来再查

最新新闻

  • 物联网Node-Red开发教程-第2章工作界面与流程基础
  • IDM激活脚本完全指南:永久解锁下载管理器的三大方法
  • openEuler安全加固工具自动化部署:企业级安全基线实施终极指南
  • 如何快速部署MQTT-Proxy:5分钟搭建高可用物联网消息平台
  • Open-eBackup用户指南:轻松掌握多场景备份策略与最佳实践
  • 为什么选择kail_dnn_adapter?鲲鹏AI加速与oneDNN生态整合的终极方案

日新闻

  • Android逆向分析全能助手:集成化工具链与自动化工作流设计
  • 面搜索(Faceted Search)原理与工程实践指南
  • 神经网络调参避坑指南:从5个常见Loss曲线形态定位超参数问题

周新闻

  • 基于YOLOv12的番茄成熟度智能检测系统开发
  • 终极RimWorld模组管理指南:用RimSort告别模组冲突烦恼
  • AI Agent框架开发:从理论到实践的完整指南

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号