跳到内容

如何添加线程级持久性(函数式 API)

先决条件

本指南假定您熟悉以下内容

许多 AI 应用程序需要内存来跨同一线程上的多次交互(例如,对话的多个回合)共享上下文。在 LangGraph 函数式 API 中,这种内存可以添加到任何使用entrypoint()工作流,方法是使用线程级持久性

在创建 LangGraph 工作流时,您可以通过使用检查点保存器将其设置为持久保存其结果

  1. 创建检查点保存器的实例

    import { MemorySaver } from "@langchain/langgraph";
    
    const checkpointer = new MemorySaver();
    
  2. checkpointer 实例传递给 entrypoint() 包装函数

    import { entrypoint } from "@langchain/langgraph";
    const workflow = entrypoint({
      name: "workflow",
      checkpointer,
    }, async (inputs) => {
      ...
    });
    
  3. 从工作流中先前执行中检索 previous 状态

    import { entrypoint, getPreviousState } from "@langchain/langgraph";
    
    const workflow = entrypoint({
      name: "workflow",
      checkpointer,
    }, async (inputs) => {
      const previous = getPreviousState();
      const result = doSomething(previous, inputs);
      ...
    });
    
  4. 可选地选择哪些值将从工作流返回,哪些值将由检查点保存器另存为 previous

    import { entrypoint, getPreviousState } from "@langchain/langgraph";
    
    const workflow = entrypoint({
      name: "workflow",
      checkpointer,
    }, async (inputs) => {
      const previous = getPreviousState();
      const result = doSomething(previous, inputs);
      ...
      return entrypoint.final({
        value: result,
        save: combineState(inputs, result),
      });
    });
    

本指南展示了如何将线程级持久性添加到您的工作流。

注意

如果您需要跨多个对话或用户共享的内存(跨线程持久性),请查看此操作指南

注意

如果您需要将线程级持久性添加到 StateGraph,请查看此操作指南

设置

注意

本指南需要 @langchain/langgraph>=0.2.42

首先,安装此示例所需的依赖项

npm install @langchain/langgraph @langchain/anthropic @langchain/core zod

接下来,我们需要为 Anthropic(我们将使用的 LLM)设置 API 密钥

process.env.ANTHROPIC_API_KEY = "YOUR_API_KEY";

设置 LangSmith 以进行 LangGraph 开发

注册 LangSmith 以快速发现问题并提高 LangGraph 项目的性能。LangSmith 使您可以使用跟踪数据来调试、测试和监控使用 LangGraph 构建的 LLM 应用程序 — 阅读更多关于如何开始使用 此处

示例:具有短期记忆的简单聊天机器人

我们将使用一个包含单个任务的工作流,该任务调用聊天模型

首先让我们定义我们将要使用的模型

import { ChatAnthropic } from "@langchain/anthropic";

const model = new ChatAnthropic({
  model: "claude-3-5-sonnet-latest",
});

现在我们可以定义我们的任务和工作流。要添加持久性,我们需要将检查点保存器传递给entrypoint()包装函数。

import type { BaseMessage, BaseMessageLike } from "@langchain/core/messages";
import {
  addMessages,
  entrypoint,
  task,
  getPreviousState,
  MemorySaver,
} from "@langchain/langgraph";

const callModel = task("callModel", async (messages: BaseMessageLike[]) => {
  const response = model.invoke(messages);
  return response;
});

const checkpointer = new MemorySaver();

const workflow = entrypoint({
  name: "workflow",
  checkpointer,
}, async (inputs: BaseMessageLike[]) => {
  const previous = getPreviousState<BaseMessage>() ?? [];
  const messages = addMessages(previous, inputs);
  const response = await callModel(messages);
  return entrypoint.final({
    value: response,
    save: addMessages(messages, response),
  });
});

如果我们尝试使用此工作流,对话的上下文将在交互过程中持久保存。

注意

如果您正在使用 LangGraph Cloud 或 LangGraph Studio,则无需将检查点保存器传递给 entrypoint 包装器,因为它会自动完成。

以下是它在实践中的工作方式

const config = {
  configurable: { thread_id: "1" },
  streamMode: "values" as const,
};
const inputMessage = { role: "user", content: "hi! I'm bob" };

const stream = await workflow.stream(
  [inputMessage],
  config,
);

for await (const chunk of stream) {
  console.log("=".repeat(30), `${chunk.getType()} message`, "=".repeat(30));
  console.log(chunk.content);
}
============================== ai message ==============================
Hi Bob! I'm Claude. Nice to meet you! How can I help you today?
您可以随时恢复以前的线程

const followupStream = await workflow.stream(
  [{ role: "user", content: "what's my name?" }], 
  config,
);

for await (const chunk of followupStream) {
  console.log("=".repeat(30), `${chunk.getType()} message`, "=".repeat(30));
  console.log(chunk.content);
}
============================== ai message ==============================
Your name is Bob - you just told me that in your first message.
如果我们想开始新的对话,我们可以传入不同的 thread_id。嘭!所有记忆都消失了!

const newStream = await workflow.stream(
  [{ role: "user", content: "what's my name?" }],
  {
    configurable: {
      thread_id: "2",
    },
    streamMode: "values",
  },
);

for await (const chunk of newStream) {
  console.log("=".repeat(30), `${chunk.getType()} message`, "=".repeat(30));
  console.log(chunk.content);
}
============================== ai message ==============================
I don't know your name as we just started chatting. Would you like to introduce yourself?

流式传输令牌

如果您想从您的聊天机器人流式传输 LLM 令牌,您可以使用 streamMode: "messages"。查看此操作指南以了解更多信息。