一、概述
长期记忆让你的代理能够在不同对话和会话中存储和回忆信息。
| 记忆类型 | 作用域 | 载体 |
|---|---|---|
| 短期记忆 | 单个线程(单次对话) | Checkpointer + State |
| 长期记忆 | 跨线程,随时可调用 | LangGraphStore |
长期记忆是建立在LangGraph Store基础上的,数据保存为
按命名空间(namespace)和键(key)分类的 JSON 文档。
二、用法
要为代理添加长期记忆,创建一个 store 并传给create_agent:
fromlangchain.agentsimportcreate_agentfromlangchain_core.runnablesimportRunnablefromlanggraph.store.memoryimportInMemoryStore# InMemoryStore 将数据保存到内存字典中。生产环境请使用 DB 支撑的 store。store=InMemoryStore()agent:Runnable=create_agent("claude-sonnet-4-6",tools=[],store=store,)更多 store 后端:包括 Redis 和 MongoDB,参见「存储集成清单」。
MongoDB 攻略参见「MongoDB 的长期记忆」。
工具随后可以使用runtime.store参数从存储器读取和写入。
深入探讨:关于记忆类型(语义记忆、情景记忆、程序记忆)及记忆书写策略,
参见「记忆概念指南」。
三、内存存储(Memory store)
LangGraph 将长期记忆存储为 JSON 文档,存储在 store 中。
每个内存分别被组织在自定义的namespace(类似文件夹)和独立的key(类似文件名)下。
namespace 通常包含用户或组织 ID 或其他标签,以便于信息组织。
这种结构使记忆能够进行层级组织,并通过内容筛选支持跨命名空间搜索。
fromcollections.abcimportSequencefromlanggraph.store.baseimportIndexConfigfromlanggraph.store.memoryimportInMemoryStoredefembed(texts:Sequence[str])->list[list[float]]:# 替换为实际的 embedding 函数或 LangChain embeddings 对象return[[1.0,2.0]for_intexts]# InMemoryStore 将数据保存到内存字典中。生产环境请使用 DB 支撑的 store。store=InMemoryStore(index=IndexConfig(embed=embed,dims=2))user_id="my-user"application_context="chitchat"namespace=(user_id,application_context)store.put(namespace,"a-memory",{"rules":["User likes short, direct language","User only speaks English & python",],"my-key":"my-value",},)# 通过 ID 获取该 "memory"item=store.get(namespace,"a-memory")# 在该命名空间内搜索 "memories",按内容等价性过滤,按向量相似度排序items=store.search(namespace,filter={"my-key":"my-value"},query="language preferences")关于 memory store 的更多信息,参见「Persistence guide」。
Store 核心 API
| 方法 | 作用 | 备注 |
|---|---|---|
store.put(namespace, key, data) | 写入 | namespace 为元组,如(user_id, context) |
store.get(namespace, key) | 按键读取 | 返回含value和元数据的对象 |
store.search(namespace, filter=..., query=...) | 搜索 | filter按内容过滤,query按向量相似度排序(需配IndexConfig) |
向量检索配置
InMemoryStore(index=IndexConfig(embed=embed,dims=2))
embed可以是任意 embedding 函数,或 LangChain embeddings 对象;dims为向量维度。生产用替换成真实 embedding。
四、在工具中读取长期记忆
工具通过runtime.store访问 store(与传给create_agent的是同一个)。
fromdataclassesimportdataclassfromlangchain.agentsimportcreate_agentfromlangchain.toolsimportToolRuntime,toolfromlangchain_core.runnablesimportRunnablefromlanggraph.store.memoryimportInMemoryStore@dataclassclassContext:user_id:str# InMemoryStore 将数据保存到内存字典中。生产环境请使用 DB 支撑的 store。store=InMemoryStore()# 使用 put 方法写入示例数据store.put(("users",),# 命名空间,用于将相关数据分组(users 命名空间存放用户数据)"user_123",# 命名空间内的键(这里用 user ID 作为键){"name":"John Smith","language":"English",},# 为该用户存储的数据)@tooldefget_user_info(runtime:ToolRuntime[Context])->str:"""Look up user info."""# 访问 store - 与提供给 `create_agent` 的相同assertruntime.storeisnotNoneuser_id=runtime.context.user_id# 从 store 检索数据 - 返回带有 value 和 metadata 的 StoreValue 对象user_info=runtime.store.get(("users",),user_id)returnstr(user_info.value)ifuser_infoelse"Unknown user"agent:Runnable=create_agent(model="openai:gpt-5.5",tools=[get_user_info],# 把 store 传给 agent - 使 agent 在运行工具时能访问 storestore=store,context_schema=Context,)# 运行代理agent.invoke({"messages":[{"role":"user","content":"look up user information"}]},context=Context(user_id="user_123"),)要点:
runtime.store类型为Optional,使用前建议assert runtime.store is not Noneget()返回的是StoreValue 对象,需通过.value取数据- 未命中时返回
None(示例中兜底返回"Unknown user") - 用户身份从
runtime.context.user_id取,需在create_agent配context_schema
五、从工具中写入长期记忆
fromdataclassesimportdataclassfromlangchain.agentsimportcreate_agentfromlangchain.toolsimportToolRuntime,toolfromlangchain_core.runnablesimportRunnablefromlanggraph.store.memoryimportInMemoryStorefromtyping_extensionsimportTypedDict# InMemoryStore 将数据保存到内存字典中。生产环境请使用 DB 支撑的 store。store=InMemoryStore()@dataclassclassContext:user_id:str# TypedDict 定义给 LLM 看的用户信息结构classUserInfo(TypedDict):name:str# 允许代理更新用户信息的工具(对聊天应用很有用)@tooldefsave_user_info(user_info:UserInfo,runtime:ToolRuntime[Context])->str:"""Save user info."""# 访问 store - 与提供给 `create_agent` 的相同assertruntime.storeisnotNonestore=runtime.store user_id=runtime.context.user_id# 在 store 中存储数据 (namespace, key, data)store.put(("users",),user_id,dict(user_info))return"Successfully saved user info."agent:Runnable=create_agent(model="openai:gpt-5.5",tools=[save_user_info],store=store,context_schema=Context,)# 运行代理agent.invoke({"messages":[{"role":"user","content":"My name is John Smith"}]},# user_id 在 context 中传入,用于标识正在更新谁的信息context=Context(user_id="user_123"),)# 你也可以直接访问 store 来获取值item=store.get(("users",),"user_123")要点:
- 用
TypedDict定义参数结构,让 LLM 知道该填什么 store.put(("users",), user_id, dict(user_info))—— TypedDict 需转成普通 dict 存入- store 对象在工具外部仍可直接访问(
store.get(...)),便于验证与调试
六、速查表
短期 vs 长期记忆
| 维度 | 短期记忆(State) | 长期记忆(Store) |
|---|---|---|
| 作用域 | 单线程(单次对话) | 跨线程 / 跨会话 |
| 载体 | 代理 State(含messages) | LangGraphStore |
| 传入方式 | create_agent(..., checkpointer=...) | create_agent(..., store=...) |
| 工具内访问 | runtime.state | runtime.store |
| 写入方式 | 返回Command(update={...}) | store.put(namespace, key, data) |
| 数据结构 | 扁平字段(messages 等) | 层级:namespace(元组)+ key |
| 检索 | 直接读字段 | get/search(支持内容过滤 + 向量相似度) |
| 生产方案 | PostgresSaver/AsyncPostgresSaver | Postgres /Redis/MongoDBstore |
| 典型用途 | 当前消息、上传文件、认证状态 | 用户偏好、提取的洞察、历史数据 |
Store API
| 操作 | 代码 |
|---|---|
| 写入 | store.put((ns1, ns2), key, data_dict) |
| 读取 | store.get((ns1, ns2), key)→StoreValue(.value) |
| 搜索 | store.search(ns, filter={...}, query="...") |
| 启用向量检索 | InMemoryStore(index=IndexConfig(embed=fn, dims=n)) |
工具内标准写法
@tooldefmy_tool(runtime:ToolRuntime[Context])->str:"""..."""assertruntime.storeisnotNoneuser_id=runtime.context.user_id# 从 Context 取身份item=runtime.store.get(("users",),user_id)# 读runtime.store.put(("users",),user_id,{...})# 写returnstr(item.value)ifitemelse"Unknown user"常用导入
fromlangchain.agentsimportcreate_agentfromlangchain.toolsimporttool,ToolRuntimefromlanggraph.store.memoryimportInMemoryStorefromlanggraph.store.baseimportIndexConfig# 生产后端:PostgresStore / RedisStore / MongoDBStore七、要点小结
- 长期记忆跨线程持久,随时可调用;短期记忆只在单线程内有效——二者互补、常一起使用。
- 底层是LangGraph Store,数据为 JSON 文档,按namespace + key组织(namespace 类似文件夹,key 类似文件名)。
- 启用方式极简:
create_agent(..., store=store)。 - namespace通常包含用户/组织 ID 或其他标签,便于信息组织与层级划分。
- 三种 API:
put(写)、get(读,返回 StoreValue 的.value)、search(内容过滤 + 向量相似度排序)。 - 向量检索需显式配置
IndexConfig(embed=..., dims=...);embed可用任意函数或 LangChain embeddings 对象。 - 工具通过
runtime.store访问,与传给create_agent的是同一个实例。 - ⚠️
runtime.store是Optional,使用前应assert ... is not None(或做 None 判断)。 - 用户身份通常从
runtime.context取(需配context_schema),再拼到 namespace/key 上做隔离。 - 给 LLM 的结构化入参用TypedDict定义,存入前用
dict(...)转换。 - ⚠️生产环境不要用
InMemoryStore(数据存内存字典,进程重启即失)——换 Postgres / Redis / MongoDB store。 - 记忆类型(语义 / 情景 / 程序)与记忆书写策略参见「记忆概念指南」。