热路径快速入门指南¶
记忆可以通过两种方式创建
- 👉 在热路径中(本指南):代理使用工具主动保存笔记。
- 在后台:记忆会从对话中自动“潜意识地”提取(参见后台快速入门)。
在本指南中,我们将创建一个 LangGraph 代理,该代理通过 LangMem 的 manage_memory
工具主动管理其自身的长期记忆。
先决条件¶
首先,安装 LangMem
使用您喜欢的 LLM 提供商的 API 密钥配置您的环境
代理¶
这里有一个完整示例,展示了如何创建一个在跨对话中保持记忆的代理
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import create_react_agent
from langgraph.store.memory import InMemoryStore
from langgraph.utils.config import get_store
from langmem import (
# Lets agent create, update, and delete memories (1)
create_manage_memory_tool,
)
def prompt(state):
"""Prepare the messages for the LLM."""
# Get store from configured contextvar; (5)
store = get_store() # Same as that provided to `create_react_agent`
memories = store.search(
# Search within the same namespace as the one
# we've configured for the agent
("memories",),
query=state["messages"][-1].content,
)
system_msg = f"""You are a helpful assistant.
## Memories
<memories>
{memories}
</memories>
"""
return [{"role": "system", "content": system_msg}, *state["messages"]]
store = InMemoryStore(
index={ # Store extracted memories (4)
"dims": 1536,
"embed": "openai:text-embedding-3-small",
}
)
checkpointer = MemorySaver() # Checkpoint graph state (2)
agent = create_react_agent(
"anthropic:claude-3-5-sonnet-latest",
prompt=prompt,
tools=[ # Add memory tools (3)
# The agent can call "manage_memory" to
# create, update, and delete memories by ID
# Namespaces add scope to memories. To
# scope memories per-user, do ("memories", "{user_id}"): (6)
create_manage_memory_tool(namespace=("memories",)),
],
# Our memories will be stored in this provided BaseStore instance
store=store,
# And the graph "state" will be checkpointed after each node
# completes executing for tracking the chat history and durable execution
checkpointer=checkpointer,
)
-
工具
create_manage_memory_tool
和create_search_memory_tool
允许代理手动存储和检索其记忆中的信息。namespace
参数限定了记忆的范围,确保数据根据您的配置保持分离。在这里,我们将所有记忆保存到 (
"memories"
,) 命名空间,这意味着无论哪个用户与代理交互,所有记忆都将共享在同一个目录下。我们也可以通过其他方式配置它来组织记忆。例如:组织模式 命名空间示例 用例 按用户 (
"memories"
,"{user_id}"
)按用户分隔记忆 按助手 (
"memories"
,"{assistant_id}"
)一个助手可能拥有跨多个用户的记忆 按用户和组织 (
"memories"
,"{organization_id}"
,"{user_id}"
)允许您跨组织搜索,同时按用户限定记忆范围 进一步细分 (
"memories"
,"{user_id}"
,"manual_memories"
)组织不同类型的用户数据 命名空间中的每个条目都像计算机上的目录。如果您提供一个带括号的命名空间变量(例如
"{user_id}"
),LangMem 将在运行时用RunnableConfig
中configurable
字段的值替换它。 -
MemorySaver
检查点器在每个“线程”内维护对话历史记录。您可以将线程视为对话,类似于电子邮件线程。这种“短期”记忆跟踪代理/图的状态,确保对话保持独立。对于生产部署,请使用像
AsyncPostgresStore
这样的持久存储。InMemoryStore
在开发时很好用,但在重启之间不持久化数据。 -
这些工具(以及任何其他有状态组件)也将在
StateGraph
、@entrypoint
和任何其他 langgraph 图中的任何节点中工作。我们在这里使用create_react_agent
是因为它易于使用且编写简洁。请查阅其 api 参考以获取有关该代理的更多信息。 -
InMemoryStore
提供适合开发的临时存储。在生产环境中,请将其替换为数据库支持的BaseStore
实现以实现持久性。在 LangGraph 平台部署时,会自动提供一个基于 postgres 的存储。此存储允许从任何命名空间保存和检索信息,使您可以按用户、代理、组织或其他任意类别限定记忆范围。请注意,
Store
与检查点器 / “MemorySaver
” 不同。Store
允许您根据首选层次结构存储任何信息。检查点器跟踪每个“线程”内的状态(包括对话历史记录),以实现持久执行。它们可以解决重叠的问题,但存储更加灵活,并且非常适合长期、跨线程的记忆。
-
get_store()
获取您已编译到图中的任何存储。这比必须显式地将其传递给每个函数更容易。LangGraph 使用 contextvars 管理一些对象(例如
config
、store
等);这使您可以从上下文获取存储或其他已配置信息,而无需将它们添加到所有函数签名中。这在使用tools
或在此处的prompt
函数中获取上下文信息时特别方便。 -
要了解如何动态配置命名空间,请参阅如何动态配置命名空间。
使用代理¶
您可以通过 invoke
图来与之交互。如果代理决定保存记忆,它将调用 manage_memory
工具。
config = {"configurable": {"thread_id": "thread-a"}}
# Use the agent. The agent hasn't saved any memories,
# so it doesn't know about us
response = agent.invoke(
{
"messages": [
{"role": "user", "content": "Know which display mode I prefer?"}
]
},
config=config,
)
print(response["messages"][-1].content)
# Output: "I don't seem to have any stored memories about your display mode preferences..."
agent.invoke(
{
"messages": [
{"role": "user", "content": "dark. Remember that."}
]
},
# We will continue the conversation (thread-a) by using the config with
# the same thread_id
config=config,
)
# New thread = new conversation!
new_config = {"configurable": {"thread_id": "thread-b"}}
# The agent will only be able to recall
# whatever it explicitly saved using the manage_memories tool
response = agent.invoke(
{"messages": [{"role": "user", "content": "Hey there. Do you remember me? What are my preferences?"}]},
config=new_config,
)
print(response["messages"][-1].content)
# Output: "Based on my memory search, I can see that you've previously indicated a preference for dark display mode..."
此示例演示了记忆在跨对话中的持久性以及用户之间的线程隔离。代理在一个线程中存储用户的深色模式偏好设置,并通过搜索可以从另一个线程访问它。
下一步¶
在此快速入门中,您配置了一个代理,使其使用工具在“热路径中”管理其记忆。请查看以下指南以了解其他功能
- 反射快速入门 – 了解如何使用
create_memory_store_manager
在“后台”管理记忆。