LangGraph:记忆
短期记忆(线程内记忆)
对话内记忆,主要记住该对话内容
长期记忆(跨线程记忆)
跨对话记忆,能够记忆好几个对话中的内容,如用户说“请记住我提供的这些偏好设置”,能够通过长期记忆记住这些偏好设置,然后在不同对话之间流通使用。
综合对比
在 LangGraph 中,短记忆和长记忆是通过在编译图(graph.compile()
)时传入不同的参数来分别进行保存的。
-
保存短记忆 (Short-term memory)
短记忆是通过checkpointer
参数来保存的。它会自动保存整个图的状态(State),通常用于记录当前对话线程(thread_id
)中的消息历史等信息。代码示例:
from langgraph.checkpoint.memory import InMemorySaver from langgraph.checkpoint.postgres import PostgresSaver # 生产环境推荐 from langgraph.graph import StateGraph# 选择一个 Checkpointer,例如内存中的(开发用)或 Postgres(生产用) checkpointer = InMemorySaver() # 或 PostgresSaver.from_conn_string(DB_URI)builder = StateGraph(...) # 定义你的图结构 graph = builder.compile(checkpointer=checkpointer) # 在编译时传入 checkpointer# 调用图时,通过 config 指定线程ID graph.invoke({"messages": [{"role": "user", "content": "hi! i am Bob"}]},{"configurable": {"thread_id": "1"}}, # 这个 thread_id 用于区分不同的对话 )
- 核心参数:
checkpointer
- 作用: 自动持久化图的整个状态,实现对话上下文的跟踪。
- 核心参数:
-
保存长记忆 (Long-term memory)
长记忆是通过store
参数来保存的。它提供了一个键值存储(Key-Value Store),允许你按命名空间(namespace)和键(key)来手动存取数据,这些数据可以跨不同的对话线程(thread_id
)被访问。代码示例:
from langgraph.store.memory import InMemoryStore from langgraph.store.postgres import PostgresStore # 生产环境推荐 from langgraph.graph import StateGraph# 选择一个 Store,例如内存中的(开发用)或 Postgres(生产用) store = InMemoryStore() # 或 PostgresStore.from_conn_string(DB_URI)builder = StateGraph(...) # 定义你的图结构 graph = builder.compile(store=store) # 在编译时传入 store# 在你的节点函数中,可以手动读写 store def call_model(state, config, *, store):user_id = config["configurable"]["user_id"]namespace = ("memories", user_id)# 读取长记忆memories = store.search(namespace, query="...")info = "..." # 处理读取到的信息# 写入长记忆 (例如,当用户要求记住某些信息时)if "remember" in state["messages"][-1].content.lower():store.put(namespace, "some_key", {"data": "User name is Bob"})# ... 调用模型并返回响应
- 核心参数:
store
- 作用: 提供一个独立的、可手动操作的存储空间,用于保存需要在多次会话间持久化的用户或应用数据。
- 核心参数:
总结:
- 短记忆 (
checkpointer
) 是自动的、基于状态的,绑定到特定的thread_id
,用于管理单次对话的上下文。 - 长记忆 (
store
) 是手动的、基于键值的,绑定到特定的user_id
或命名空间,用于管理跨会话的持久化数据。
你可以同时使用两者:
graph = builder.compile(checkpointer=checkpointer, # 用于短记忆store=store # 用于长记忆
)
长记忆保存机制
长记忆(Long-term memory)不会自动保存。它需要你在图的节点(Node)函数中手动调用 store.put()
或 store.aput()
方法来显式地写入数据。
这与短记忆(Short-term memory)的机制完全不同:
- 短记忆 (
checkpointer
):是自动的。当你在graph.compile(checkpointer=...)
中配置了检查点后,LangGraph 会在每次状态更新时自动保存整个图的状态(包括消息历史等)。你无需在节点函数中编写额外的保存代码。 - 长记忆 (
store
):是手动的。虽然你在编译图时通过graph.compile(store=...)
提供了存储后端,但这只是让store
对象在节点函数中可用。实际的数据读写操作(store.search()
,store.put()
,store.get()
)必须由你在业务逻辑中显式调用。
为什么这样设计?
长记忆通常用于存储用户档案、偏好设置、重要事件等关键的、跨会话的持久化信息。这些信息并非每次交互都会产生或改变,而是需要根据特定的业务逻辑或用户指令(例如,当用户说“记住我的名字是Bob”时)来决定何时保存。因此,手动控制提供了更大的灵活性和精确性。
如何手动保存?
正如文档中的示例所示,你需要在你的节点函数中访问 store
对象,并根据条件执行保存操作:
def call_model(state: MessagesState,config: RunnableConfig,*,store: BaseStore, # store 作为参数传入节点函数
):user_id = config["configurable"]["user_id"]namespace = ("memories", user_id)# ... 处理逻辑 ...# 手动判断并保存长记忆last_message = state["messages"][-1]if "remember" in last_message.content.lower():memory_data = "User name is Bob"# 手动调用 put 方法保存store.put(namespace, str(uuid.uuid4()), {"data": memory_data})# ... 返回响应 ...
总结来说,长记忆的保存是一个主动的、由开发者控制的过程,而不是一个被动的、自动发生的后台任务。