跳到内容

记忆

LangGraph 支持构建对话式智能体所需的两种基本记忆类型

  • 短期记忆:通过维护会话内的消息历史来跟踪进行中的对话。
  • 长期记忆:存储跨会话的用户特定或应用级别数据。

本指南演示了如何在 LangGraph 中将这两种记忆类型与智能体结合使用。如需更深入地了解记忆概念,请参阅LangGraph 记忆文档

image

短期长期记忆都需要持久化存储,以在 LLM 交互中保持连续性。在生产环境中,这些数据通常存储在数据库中。

术语

在 LangGraph 中

  • 短期记忆也称为线程级记忆
  • 长期记忆也称为跨线程记忆

一个线程代表由同一个 thread_id 分组的一系列相关运行。

短期记忆

短期记忆使智能体能够跟踪多轮对话。要使用它,您必须

  1. 创建智能体时提供一个 checkpointercheckpointer 启用智能体状态的持久性
  2. 运行智能体时在 config 中提供一个 thread_idthread_id 是会话的唯一标识符。
import { MemorySaver } from "@langchain/langgraph-checkpoint";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const checkpointer = new MemorySaver();  // (1)!

const getWeather = tool(
  async (input: { city: string }) => {
    return `It's always sunny in ${input.city}!`;
  },
  {
    name: "getWeather",
    schema: z.object({
      city: z.string().describe("The city to get the weather for"),
    }),
    description: "Get weather for a given city.",
  }
);

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  tools: [getWeather],
  checkpointer  // (2)!
});

// Run the agent
const config = { configurable: { thread_id: "1" } };  // (3)!
const sfResponse = await agent.invoke(
  { messages: [ { role: "user", content: "what is the weather in sf" } ] },
  config  // (4)!
);
const nyResponse = await agent.invoke(
  { messages: [ { role: "user", content: "what about new york?" } ] },
  config
);
  1. MemorySaver 是一个将智能体状态存储在内存中的 checkpointer。在生产环境中,您通常会使用数据库或其他持久化存储。请查阅checkpointer 文档以获取更多选项。如果您使用 LangGraph Platform 进行部署,平台将为您提供生产级的 checkpointer
  2. checkpointer 会传递给智能体。这使得智能体能够跨调用持久化其状态。请注意,
  3. 在 config 中提供了一个唯一的 thread_id。此 ID 用于标识会话。该值由用户控制,可以是任何字符串。
  4. 智能体将使用相同的 thread_id 继续对话。这将允许智能体推断用户正在专门询问纽约的天气

当使用相同的 thread_id 第二次调用智能体时,第一次对话的原始消息历史会自动包含进来,从而允许智能体推断用户正在专门询问纽约的天气

LangGraph Platform 提供生产级 checkpointer

如果您使用LangGraph Platform 进行部署,在部署期间您的 checkpointer 将自动配置为使用生产级数据库。

长期记忆

使用长期记忆存储跨对话的用户特定或应用特定数据。这对于聊天机器人等应用很有用,您希望记住用户偏好或其他信息。

要使用长期记忆,您需要

  1. 配置一个存储,以在调用之间持久化数据。
  2. 使用 config.store 从工具或提示中访问存储。

读取

智能体可用于查找用户信息的工具
import { initChatModel } from "langchain/chat_models/universal";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
// highlight-next-line
import { InMemoryStore } from "@langchain/langgraph-checkpoint";
// highlight-next-line
import { getStore } from "@langchain/langgraph";
import { LangGraphRunnableConfig } from "@langchain/langgraph";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const store = new InMemoryStore(); // (1)!

await store.put(  // (2)!
  ["users"],  // (3)!
  "user_123",  // (4)!
  {
    name: "John Smith",
    language: "English",
  } // (5)!
);

// Look up user info tool
const getUserInfo = tool(
  async (input: Record<string, any>, config: LangGraphRunnableConfig): Promise<string> => {
    // Same as that provided to `createReactAgent`
    const store = config.store; // (6)!
    if (!store) {
      throw new Error("store is required when compiling the graph");
    }

    const userId = config.configurable?.userId;
    if (!userId) {
      throw new Error("userId is required in the config");
    }

    const userInfo = await store.get(["users"], userId); // (7)!
    return userInfo ? JSON.stringify(userInfo.value) : "Unknown user";
  },
  {
    name: "get_user_info",
    description: "Look up user info.",
    schema: z.object({}),
  }
);

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  tools: [getUserInfo],
  store, // (8)!
});

// Run the agent
const response = await agent.invoke(
  { messages: [ { role: "user", content: "look up user information" } ] },
  { configurable: { userId: "user_123" } }
);
  1. InMemoryStore 是一个将数据存储在内存中的存储。在生产环境中,您通常会使用数据库或其他持久化存储。请查阅文档以获取更多选项。如果您使用 LangGraph Platform 进行部署,平台将为您提供生产级的存储。
  2. 在此示例中,我们使用 put 方法向存储写入一些示例数据。请参阅 BaseStore.put API 参考以获取更多详细信息。
  3. 第一个参数是命名空间。这用于将相关数据分组在一起。在此示例中,我们使用 users 命名空间来分组用户数据。
  4. 命名空间中的一个键。此示例使用用户 ID 作为键。
  5. 我们希望为给定用户存储的数据。
  6. 您可以从节点、工具和提示中的任何位置通过 config.store 访问存储。它包含创建智能体时传递给智能体的存储。
  7. get 方法用于从存储中检索数据。第一个参数是命名空间,第二个参数是键。这将返回一个 StoreValue 对象,其中包含值以及有关该值的元数据。
  8. 存储会传递给智能体。这使得智能体在运行工具时能够访问存储。

写入

更新用户信息的工具示例
import { initChatModel } from "langchain/chat_models/universal";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { InMemoryStore } from "@langchain/langgraph-checkpoint";
import { getStore } from "@langchain/langgraph";
import { LangGraphRunnableConfig } from "@langchain/langgraph";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const store = new InMemoryStore(); // (1)!

interface UserInfo { // (2)!
  name: string;
}

// Save user info tool
const saveUserInfo = tool(  // (3)!
  async (input: UserInfo, config: LangGraphRunnableConfig): Promise<string> => {
    // Same as that provided to `createReactAgent`
    // highlight-next-line
    const store = config.store; // (4)!
    if (!store) {
      throw new Error("store is required when compiling the graph");
    }

    const userId = config.configurable?.userId;
    if (!userId) {
      throw new Error("userId is required in the config");
    }

    await store.put(["users"], userId, input); // (5)!
    return "Successfully saved user info.";
  },
  {
    name: "save_user_info",
    description: "Save user info.",
    schema: z.object({
      name: z.string(),
    }),
  }
);

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  tools: [saveUserInfo],
  // highlight-next-line
  store,
});

// Run the agent
await agent.invoke(
  { messages: [ { role: "user", content: "My name is John Smith" } ] },
  { configurable: { userId: "user_123" } } // (6)!
);

// You can access the store directly to get the value
const userInfo = await store.get(["users"], "user_123")
userInfo.value
  1. InMemoryStore 是一个将数据存储在内存中的存储。在生产环境中,您通常会使用数据库或其他持久化存储。请查阅存储文档以获取更多选项。如果您使用 LangGraph Platform 进行部署,平台将为您提供生产级的存储。
  2. UserInfo 类是一个定义用户信息结构的接口。我们将在下方使用 zod 对象指定相同的模式,以便 LLM 根据该模式格式化响应。
  3. saveUserInfo 是一个允许智能体更新用户信息的工具。这对于用户希望更新其个人资料信息的聊天应用程序可能有用。
  4. 您可以从节点、工具和提示中的任何位置通过 config.store 访问存储。它包含创建智能体时传递给智能体的存储。
  5. put 方法用于将数据存储在存储中。第一个参数是命名空间,第二个参数是键。这会将用户信息存储在存储中。
  6. userId 会在 config 中传递。这用于标识正在更新其信息的用户。

附加资源