news 2026/7/20 15:25:36

【langgraph 从入门到精通graphApi 篇】Memory 与长期记忆

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【langgraph 从入门到精通graphApi 篇】Memory 与长期记忆

文章目录

    • 第 8 章:Memory 与长期记忆
      • 8.1 本章目标
      • 8.2 核心概念
        • Checkpoint vs Store
        • 短期记忆 vs 长期记忆架构
        • Store 命名空间设计
      • 8.3 实战
        • 实战 1:用户偏好记忆
        • 实战 2:语义记忆搜索
      • 8.4 API 速查
      • 8.5 错误与避坑指南
        • 坑 1:混淆 Store 和 Checkpoint
        • 坑 2:命名空间设计不当
        • 坑 3:语义搜索未配置 embedding
        • 坑 4:忘记在 compile 时传入 store
      • 8.6 最佳实践总结

第 8 章:Memory 与长期记忆

8.1 本章目标

学完本章你将能够:

  1. 理解短期记忆(Checkpoint)与长期记忆(Store)的区别
  2. 掌握 InMemoryStore / PostgresStore 的配置和使用
  3. 学会在节点中通过 Runtime 访问 Store
  4. 实现语义记忆搜索功能

8.2 核心概念

Checkpoint vs Store
特性Checkpoint(短期记忆)Store(长期记忆)
存储内容图状态快照(State 的完整副本)应用定义的键值数据
作用范围单个 Thread(对话线程)跨 Thread(跨会话)
生命周期对话结束后可清理持久保留
典型用途对话连续性、HITL、容错用户偏好、知识库、共享信息
访问方式自动(每个 super-step 保存)手动(节点中显式读写)

比喻:Checkpoint 就像"草稿自动保存"——每次编辑后自动保存当前状态。Store 就像"客户档案"——记录客户的长期偏好,所有对话都能访问。

短期记忆 vs 长期记忆架构

Store (长期记忆)

Checkpointer (短期记忆)

会话 2 (thread-2)

会话 1 (thread-1)

自动保存

自动保存

读写

读写

对话1

对话2

对话3

对话1

对话2

thread-1
checkpoints

thread-2
checkpoints

用户偏好
历史摘要
共享知识

Store 命名空间设计
# 命名空间使用 tuple 结构,支持层级隔离("user_123","memories")# 用户 123 的记忆("user_123","preferences")# 用户 123 的偏好("user_456","memories")# 用户 456 的记忆("global","knowledge")# 全局知识库

8.3 实战

实战 1:用户偏好记忆
fromtypingimportTypedDict,Annotatedfromdataclassesimportdataclassfromlanggraph.graphimportStateGraph,START,END,add_messagesfromlanggraph.checkpoint.memoryimportMemorySaverfromlanggraph.store.memoryimportInMemoryStorefromlanggraph.runtimeimportRuntimefromlangchain_core.messagesimportBaseMessage,HumanMessage,AIMessage# ============================================# 定义 Context(运行时上下文)# ============================================@dataclassclassContext:user_id:str# ============================================# 定义 State# ============================================classState(TypedDict):messages:Annotated[list[BaseMessage],add_messages]# ============================================# 定义节点(使用 Runtime 访问 Store)# ============================================asyncdefmemory_node(state:State,runtime:Runtime[Context])->dict:""" 使用 Runtime 访问 Store 实现长期记忆。 关键点: 1. 在函数签名中声明 runtime: Runtime[Context] 参数 2. LangGraph 自动注入 Runtime 实例 3. 通过 runtime.context 访问上下文 4. 通过 runtime.store 访问 Store """user_id=runtime.context.user_id namespace=(user_id,"memories")# 从 Store 读取用户记忆memories=awaitruntime.store.asearch(namespace,limit=10)# 构建包含记忆的回复ifmemories:memory_text="我记得以下信息:\n"+"\n".join(f" -{m.value.get('content','')}"forminmemories)else:memory_text="我还没有关于你的记忆。"# 如果有新信息,存入 Storelast_msg=state["messages"][-1]if"记住"inlast_msg.contentor"我叫"inlast_msg.content:awaitruntime.store.aput(namespace,f"memory_{len(memories)+1}",{"content":last_msg.content},)return{"messages":[AIMessage(content=f"收到!{memory_text}")]}# ============================================# 构建图# ============================================store=InMemoryStore()checkpointer=MemorySaver()builder=StateGraph(State)builder.add_node("memory",memory_node)builder.add_edge(START,"memory")builder.add_edge("memory",END)# 编译时传入 store 和 context_schemagraph=builder.compile(checkpointer=checkpointer,store=store,context_schema=Context,)# ============================================# 异步运行# ============================================importasyncioasyncdefmain():config={"configurable":{"thread_id":"mem-001"}}context=Context(user_id="user_123")# 第一次对话result=awaitgraph.ainvoke({"messages":[HumanMessage(content="我叫小明,记住这个")]},config=config,context=context,)print(f"AI:{result['messages'][-1].content}")# 第二次对话(新 thread,但同一 user_id)config2={"configurable":{"thread_id":"mem-002"}}result=awaitgraph.ainvoke({"messages":[HumanMessage(content="你还记得我叫什么吗?")]},config=config2,context=context,)print(f"AI:{result['messages'][-1].content}")asyncio.run(main())
实战 2:语义记忆搜索
fromlanggraph.store.memoryimportInMemoryStore# 创建带语义搜索的 Storestore=InMemoryStore(index={"embed":"openai:text-embedding-3-small",# 嵌入模型"dims":1536,# 嵌入维度"fields":["content","$"],# 要索引的字段})# 存储带语义信息的记忆asyncdefstore_with_semantics():awaitstore.aput(("user_123","memories"),"mem_1",{"content":"用户喜欢喝咖啡,尤其是拿铁"},)awaitstore.aput(("user_123","memories"),"mem_2",{"content":"用户是 Python 程序员"},)awaitstore.aput(("user_123","memories"),"mem_3",{"content":"用户住在北京朝阳区"},)# 语义搜索:自然语言查询results=awaitstore.asearch(("user_123","memories"),query="用户喜欢喝什么饮料?",# 自然语言查询limit=3,)foriteminresults:print(f" [{item.key}]{item.value['content']}")# 输出: [mem_1] 用户喜欢喝咖啡,尤其是拿铁asyncio.run(store_with_semantics())

8.4 API 速查

API完整签名入参说明返回值说明
InMemoryStore()InMemoryStore(index=...)index: 语义搜索配置(可选)Store 对象内存存储
PostgresStore(conn)PostgresStore(conn)conn: 数据库连接Store 对象Postgres 持久化
store.put(namespace, key, value)put(ns: tuple, key: str, value: dict)ns: 命名空间;key: 键;value: 值None存储数据
store.search(namespace, query, limit)search(ns: tuple, query: str, limit: int)ns: 命名空间;query: 查询;limit: 数量结果列表语义搜索(需 index)
store.aget/get/adelete异步版本同上同上节点中异步调用
Runtime[Context]Runtime[Context]Context: 上下文类型运行时对象节点中注入上下文
context_schemacompile(context_schema=Type)context_schema: Context 类型CompiledGraph编译时声明 Context

8.5 错误与避坑指南

坑 1:混淆 Store 和 Checkpoint
# ❌ 错误:把用户偏好存在 Checkpoint 中# Checkpoint 是 thread 级别的,换 thread 就丢失了!classState(TypedDict):user_preferences:dict# 不应该放在 State 中# ✅ 正确:用户偏好存在 Store 中# Store 跨 thread 共享,通过 user_id 隔离awaitstore.aput(("user_123","preferences"),"key",value)
坑 2:命名空间设计不当
# ❌ 错误:所有用户共享命名空间awaitstore.aput(("memories"),"key",value)# 所有用户混在一起# ✅ 正确:按用户 ID 隔离awaitstore.aput(("user_123","memories"),"key",value)awaitstore.aput(("user_456","memories"),"key",value)
坑 3:语义搜索未配置 embedding
# ❌ 错误:没有配置 indexstore=InMemoryStore()# 没有 indexawaitstore.asearch(ns,query="自然语言查询")# 无法语义搜索,只能精确匹配# ✅ 正确:配置 indexstore=InMemoryStore(index={"embed":"openai:text-embedding-3-small","dims":1536,"fields":["content"],})
坑 4:忘记在 compile 时传入 store
# ❌ 错误graph=builder.compile(checkpointer=...)# 节点中 runtime.store 不可用!# ✅ 正确graph=builder.compile(checkpointer=...,store=store,# 必须传入)

8.6 最佳实践总结

  1. 用户级数据用 Store,会话级数据用 Checkpoint:按数据生命周期选择存储
  2. 命名空间使用(user_id, "category")结构:层级隔离,清晰明了
  3. 生产环境使用 PostgresStore 持久化:数据不丢失,支持高并发
  4. 语义搜索时选择合适的 embedding 模型:平衡成本和效果
  5. Context Schema 用于注入运行时信息:如 user_id、tenant_id 等,不需要放在 State 中
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/20 15:23:33

1位量化技术革命:Bonsai-8B-GGUF如何在5分钟内实现跨平台AI部署

1位量化技术革命:Bonsai-8B-GGUF如何在5分钟内实现跨平台AI部署 【免费下载链接】Bonsai-8B-gguf 项目地址: https://ai.gitcode.com/hf_mirrors/prism-ml/Bonsai-8B-gguf 当开发者面临大语言模型部署的困境时,往往需要在性能、体积和兼容性之间…

作者头像 李华
网站建设 2026/7/20 15:22:10

告别「握手」:MCP 2026-07-28 如何让 AI Agent 真正走向企业级部署

告别「握手」:MCP 2026-07-28 如何让 AI Agent 真正走向企业级部署一、MCP 从哪里来,又走到了哪里二、一次工具调用,为什么要先「握手」三、2026-07-28:把状态从协议核心中拿出去四、企业基础设施为什么在意这件事五、不只是无状态…

作者头像 李华
网站建设 2026/7/20 15:21:13

TinyMCE终极指南:如何在富文本编辑中无缝集成Markdown高效输入

TinyMCE终极指南:如何在富文本编辑中无缝集成Markdown高效输入 【免费下载链接】tinymce The worlds #1 JavaScript library for rich text editing. Available for React, Vue and Angular 项目地址: https://gitcode.com/gh_mirrors/ti/tinymce TinyMCE作为…

作者头像 李华
网站建设 2026/7/20 15:21:12

2026年AI写作工具深度测评:全面解析写小说软件与创作平台的优劣势

AI 写小说的工具 2026 年已经多到让人选择困难。但说句实话——大部分工具只能陪你"聊着写",管不了一本书。我花了两个月,把市面上主流的 AI 写小说工具全部跑了一遍。不讲参数表,只讲一个问题:这个东西到底能不能帮我把…

作者头像 李华