跳到内容

内存

LangGraph 支持两种对于构建对话代理至关重要的内存类型

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

本指南演示了如何在 LangGraph 中将这两种内存类型与代理结合使用。要更深入地了解内存概念,请参阅LangGraph 内存文档

image

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

术语

在 LangGraph 中

  • 短期内存也称为线程级内存
  • 长期内存也称为跨线程内存

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

短期内存

短期内存使代理能够跟踪多轮对话。要使用它,您必须

  1. 在创建代理时提供一个 checkpointercheckpointer 能够实现代理状态的持久性
  2. 在运行代理时,在配置中提供一个 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 是一个检查点器,用于在内存中存储代理的状态。在生产环境中,您通常会使用数据库或其他持久存储。请查阅检查点器文档以获取更多选项。如果您使用 LangGraph Platform 进行部署,平台将为您提供生产就绪的检查点器。
  2. checkpointer 会传递给代理。这使得代理能够在多次调用之间保持其状态。请注意
  3. 配置中提供了一个唯一的 thread_id。此 ID 用于标识会话。该值由用户控制,可以是任何字符串。
  4. 代理将使用相同的 thread_id 继续对话。这将允许代理推断用户正在专门询问纽约的天气

当代理第二次以相同的 thread_id 被调用时,第一次对话的原始消息历史会自动包含在内,允许代理推断用户正在专门询问纽约的天气

LangGraph Platform 提供生产就绪的检查点器

如果您正在使用LangGraph Platform,在部署期间,您的检查点器将自动配置为使用生产就绪的数据库。

长期内存

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

要使用长期内存,您需要

  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. store 会传递给代理。这使得代理能够在运行工具时访问存储。

写入

更新用户信息的工具示例
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 对象指定相同的 schema,以便 LLM 根据 schema 格式化响应。
  3. saveUserInfo 是一个允许代理更新用户信息的工具。这对于用户希望更新其个人资料信息的聊天应用程序可能很有用。
  4. 您可以从节点、工具和提示中的任何位置通过 config.store 访问存储。它包含创建代理时传递给代理的存储。
  5. put 方法用于将数据存储在存储中。第一个参数是命名空间,第二个参数是键。这将把用户信息存储在存储中。
  6. userId 在配置中传递。这用于标识正在更新其信息的用户。

额外资源