一架梯子,一头程序猿,仰望星空!
LangChain教程(JS版本) > 内容正文

AI记忆能力


AI记忆组件

默认情况下,链和代理是无状态的,这意味着它们独立地处理每个传入的查询(就像底层的LLM和聊天模型本身一样)。在一些应用中,比如聊天机器人,记住先前的交互信息(包括短期和长期的)是非常重要的。Memory(内存)类正是为此而设计的。

LangChain以两种形式提供内存组件。首先,LangChain提供了帮助管理和操作之前的聊天消息的辅助工具。这些工具被设计成可以模块化和有用,无论如何使用它们。其次,LangChain提供了将这些工具集成到链中的简便方法。

入门

在用户与语言模型的交互过程中,内存涉及到在整个过程中保留状态的概念。用户与语言模型的交互被捕捉在ChatMessages的概念中,因此这归结为从一系列聊天消息中摄取、捕获、转换和提取知识。有很多不同的方式来做到这一点,每种方式都作为其独立的内存类型存在。

通常情况下,对于每种类型的内存,有两种方法来理解和使用。一种是独立的函数,用于从一系列消息中提取信息,另一种是在链中使用这种类型的内存的方式。

内存可以返回多个信息片段(例如,最近的N条消息和所有以前消息的摘要)。返回的信息可以是字符串或消息列表。

我们将介绍内存的最简单形式:”缓冲区”内存,它只涉及保留所有先前消息的缓冲区。我们将展示如何在这里使用模块化工具函数,然后展示如何在链中使用它(既返回字符串,也返回消息列表)。

ChatMessageHistory

支持大多数(如果不是全部)内存模块的核心实用类之一是 ChatMessageHistory 类。这是一个超轻量级的包装器,提供了保存人类消息、AI消息以及获取所有消息的便捷方法。

通过对该类进行子类化,您可以使用不同的存储解决方案,例如Redis,以保持持久的聊天消息记录。

import { ChatMessageHistory } from "langchain/memory";

const history = new ChatMessageHistory();

await history.addUserMessage("Hi!");

await history.addAIChatMessage("What's up?");

const messages = await history.getMessages();

console.log(messages);

/*
  [
    HumanMessage {
      content: 'Hi!',
    },
    AIMessage {
      content: "What's up?",
    }
  ]
*/

您还可以通过创建并传入ChatHistory对象来将消息加载到内存实例中。这样可以轻松地从过去的对话中获取状态。除了上述技术外,您还可以这样做:

import { BufferMemory, ChatMessageHistory } from "langchain/memory";
import { HumanChatMessage, AIChatMessage } from "langchain/schema";

const pastMessages = [
  new HumanMessage("My name's Jonas"),
  new AIMessage("Nice to meet you, Jonas!"),
];

const memory = new BufferMemory({
  chatHistory: new ChatMessageHistory(pastMessages),
});

BufferMemory

现在我们来展示如何在链中使用这个简单的概念。我们首先展示BufferMemory,它是一个封装ChatMessageHistory的类,用于提取消息并将其存储在输入变量中。

import { OpenAI } from "langchain/llms/openai";
import { BufferMemory } from "langchain/memory";
import { ConversationChain } from "langchain/chains";

const model = new OpenAI({});
const memory = new BufferMemory();
// This chain is preconfigured with a default prompt
const chain = new ConversationChain({ llm: model, memory: memory });
const res1 = await chain.call({ input: "Hi! I'm Jim." });
console.log({ res1 });
{response: " Hi Jim! It's nice to meet you. My name is AI. What would you like to talk about?"}
const res2 = await chain.call({ input: "What's my name?" });
console.log({ res2 });
{response: ' You said your name is Jim. Is there anything else you would like to talk about?'}

还有很多不同类型的内存,查看我们的示例以了解更多!

创建自己的内存类

BaseMemory接口有两个方法:

export type InputValues = Record;

export type OutputValues = Record;

interface BaseMemory {
  loadMemoryVariables(values: InputValues): Promise;

  saveContext(
    inputValues: InputValues,
    outputValues: OutputValues
  ): Promise;
}

要实现自己的内存类,有两种选择:

继承BaseChatMemory

这是实现自己的内存类最简单的方法。你可以继承BaseChatMemory类,它会负责通过将输入和输出保存为聊天消息来处理saveContext方法,并且只需实现loadMemoryVariables方法。这个方法负责返回与当前输入值相关的内存变量。

abstract class BaseChatMemory extends BaseMemory {
  chatHistory: ChatMessageHistory;

  abstract loadMemoryVariables(values: InputValues): Promise;
}

继承BaseMemory

如果你想实现一个更自定义的内存类,可以继承BaseMemory类并实现loadMemoryVariablessaveContext方法。saveContext方法负责将输入和输出值存储在内存中,loadMemoryVariables方法负责返回与当前输入值相关的内存变量。

abstract class BaseMemory {
  abstract loadMemoryVariables(values: InputValues): Promise;

  abstract saveContext(
    inputValues: InputValues,
    outputValues: OutputValues
  ): Promise;
}


关联主题