如何管理内存
本指南假设您熟悉以下内容
聊天机器人的一个关键功能是能够将以前的对话回合的内容用作上下文。这种状态管理可以采用多种形式,包括
- 简单地将以前的消息填充到聊天模型提示中。
- 上面的方法,但会修剪旧消息以减少模型需要处理的干扰信息。
- 更复杂的修改,例如为长时间运行的对话合成摘要。
我们将在下面更详细地介绍一些技术!
设置
您需要安装一些软件包,并设置任何 LLM API 密钥
让我们也设置一个聊天模型,我们将在下面的示例中使用它
选择您的聊天模型
- OpenAI
- Anthropic
- FireworksAI
- MistralAI
- Groq
- VertexAI
安装依赖项
请参阅 本节了解有关安装集成软件包的一般说明.
- npm
- yarn
- pnpm
npm i @langchain/openai
yarn add @langchain/openai
pnpm add @langchain/openai
添加环境变量
OPENAI_API_KEY=your-api-key
实例化模型
import { ChatOpenAI } from "@langchain/openai";
const model = new ChatOpenAI({
model: "gpt-4o-mini",
temperature: 0
});
安装依赖项
请参阅 本节了解有关安装集成软件包的一般说明.
- npm
- yarn
- pnpm
npm i @langchain/anthropic
yarn add @langchain/anthropic
pnpm add @langchain/anthropic
添加环境变量
ANTHROPIC_API_KEY=your-api-key
实例化模型
import { ChatAnthropic } from "@langchain/anthropic";
const model = new ChatAnthropic({
model: "claude-3-5-sonnet-20240620",
temperature: 0
});
安装依赖项
请参阅 本节了解有关安装集成软件包的一般说明.
- npm
- yarn
- pnpm
npm i @langchain/community
yarn add @langchain/community
pnpm add @langchain/community
添加环境变量
FIREWORKS_API_KEY=your-api-key
实例化模型
import { ChatFireworks } from "@langchain/community/chat_models/fireworks";
const model = new ChatFireworks({
model: "accounts/fireworks/models/llama-v3p1-70b-instruct",
temperature: 0
});
安装依赖项
请参阅 本节了解有关安装集成软件包的一般说明.
- npm
- yarn
- pnpm
npm i @langchain/mistralai
yarn add @langchain/mistralai
pnpm add @langchain/mistralai
添加环境变量
MISTRAL_API_KEY=your-api-key
实例化模型
import { ChatMistralAI } from "@langchain/mistralai";
const model = new ChatMistralAI({
model: "mistral-large-latest",
temperature: 0
});
安装依赖项
请参阅 本节了解有关安装集成软件包的一般说明.
- npm
- yarn
- pnpm
npm i @langchain/groq
yarn add @langchain/groq
pnpm add @langchain/groq
添加环境变量
GROQ_API_KEY=your-api-key
实例化模型
import { ChatGroq } from "@langchain/groq";
const model = new ChatGroq({
model: "mixtral-8x7b-32768",
temperature: 0
});
安装依赖项
请参阅 本节了解有关安装集成软件包的一般说明.
- npm
- yarn
- pnpm
npm i @langchain/google-vertexai
yarn add @langchain/google-vertexai
pnpm add @langchain/google-vertexai
添加环境变量
GOOGLE_APPLICATION_CREDENTIALS=credentials.json
实例化模型
import { ChatVertexAI } from "@langchain/google-vertexai";
const model = new ChatVertexAI({
model: "gemini-1.5-flash",
temperature: 0
});
消息传递
最简单的内存形式是简单地将聊天历史消息传递到链中。以下是一个示例
import { HumanMessage, AIMessage } from "@langchain/core/messages";
import {
ChatPromptTemplate,
MessagesPlaceholder,
} from "@langchain/core/prompts";
const prompt = ChatPromptTemplate.fromMessages([
[
"system",
"You are a helpful assistant. Answer all questions to the best of your ability.",
],
new MessagesPlaceholder("messages"),
]);
const chain = prompt.pipe(llm);
await chain.invoke({
messages: [
new HumanMessage(
"Translate this sentence from English to French: I love programming."
),
new AIMessage("J'adore la programmation."),
new HumanMessage("What did you just say?"),
],
});
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: `I said "J'adore la programmation," which means "I love programming" in French.`,
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: `I said "J'adore la programmation," which means "I love programming" in French.`,
name: undefined,
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {
tokenUsage: { completionTokens: 21, promptTokens: 61, totalTokens: 82 },
finish_reason: "stop"
},
tool_calls: [],
invalid_tool_calls: []
}
我们可以看到,通过将以前的对话传递到链中,它可以使用它作为上下文来回答问题。这是聊天机器人内存的底层基本概念 - 本指南的其余部分将演示用于传递或重新格式化消息的便捷技术。
聊天历史
将消息直接存储和传递为数组是完全可以的,但我们可以使用 LangChain 的内置消息历史记录类来存储和加载消息。此类的实例负责从持久存储中存储和加载聊天消息。LangChain 与许多提供商集成,但为了演示,我们将使用一个短暂的演示类。
以下是如何使用 API 的示例
import { ChatMessageHistory } from "langchain/stores/message/in_memory";
const demoEphemeralChatMessageHistory = new ChatMessageHistory();
await demoEphemeralChatMessageHistory.addMessage(
new HumanMessage(
"Translate this sentence from English to French: I love programming."
)
);
await demoEphemeralChatMessageHistory.addMessage(
new AIMessage("J'adore la programmation.")
);
await demoEphemeralChatMessageHistory.getMessages();
[
HumanMessage {
lc_serializable: true,
lc_kwargs: {
content: "Translate this sentence from English to French: I love programming.",
additional_kwargs: {},
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "Translate this sentence from English to French: I love programming.",
name: undefined,
additional_kwargs: {},
response_metadata: {}
},
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: "J'adore la programmation.",
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: {},
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "J'adore la programmation.",
name: undefined,
additional_kwargs: {},
response_metadata: {},
tool_calls: [],
invalid_tool_calls: []
}
]
我们可以直接使用它来存储我们链的对话回合
await demoEphemeralChatMessageHistory.clear();
const input1 =
"Translate this sentence from English to French: I love programming.";
await demoEphemeralChatMessageHistory.addMessage(new HumanMessage(input1));
const response = await chain.invoke({
messages: await demoEphemeralChatMessageHistory.getMessages(),
});
await demoEphemeralChatMessageHistory.addMessage(response);
const input2 = "What did I just ask you?";
await demoEphemeralChatMessageHistory.addMessage(new HumanMessage(input2));
await chain.invoke({
messages: await demoEphemeralChatMessageHistory.getMessages(),
});
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: 'You just asked me to translate the sentence "I love programming" from English to French.',
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: 'You just asked me to translate the sentence "I love programming" from English to French.',
name: undefined,
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {
tokenUsage: { completionTokens: 18, promptTokens: 73, totalTokens: 91 },
finish_reason: "stop"
},
tool_calls: [],
invalid_tool_calls: []
}
自动历史记录管理
前面的示例将消息显式传递给链。这是一种完全可以接受的方法,但它确实需要外部管理新消息。LangChain 还包含一个用于 LCEL 链的包装器,可以自动处理此过程,称为 RunnableWithMessageHistory
。
为了展示其工作原理,让我们稍微修改上述提示,添加一个最终的 `input` 变量,该变量在聊天历史之后填充 `HumanMessage` 模板。这意味着我们期望一个 `chat_history` 参数,它包含当前消息之前的 **所有** 消息,而不是所有消息。
const runnableWithMessageHistoryPrompt = ChatPromptTemplate.fromMessages([
[
"system",
"You are a helpful assistant. Answer all questions to the best of your ability.",
],
new MessagesPlaceholder("chat_history"),
["human", "{input}"],
]);
const chain2 = runnableWithMessageHistoryPrompt.pipe(llm);
我们将最新的输入传递到这里,并让 `RunnableWithMessageHistory` 类包装我们的链并完成将该 `input` 变量追加到聊天历史的工作。
接下来,让我们声明我们包装的链。
import { RunnableWithMessageHistory } from "@langchain/core/runnables";
const demoEphemeralChatMessageHistoryForChain = new ChatMessageHistory();
const chainWithMessageHistory = new RunnableWithMessageHistory({
runnable: chain2,
getMessageHistory: (_sessionId) => demoEphemeralChatMessageHistoryForChain,
inputMessagesKey: "input",
historyMessagesKey: "chat_history",
});
除了我们要包装的链之外,此类还需要一些参数。
- 一个工厂函数,它为给定的会话 ID 返回消息历史记录。这允许您的链通过为不同的对话加载不同的消息来同时处理多个用户。
- 一个 `inputMessagesKey`,指定输入的哪一部分应该被跟踪并存储在聊天历史中。在本例中,我们希望跟踪作为输入传入的字符串。
- 一个 `historyMessagesKey`,指定之前的消息应该注入到提示中的内容。我们的提示有一个名为 `chat_history` 的 `MessagesPlaceholder`,因此我们指定此属性以匹配。(对于具有多个输出的链)一个 `outputMessagesKey`,指定哪个输出存储为历史记录。这是 `inputMessagesKey` 的反向。
我们可以像往常一样调用这个新链,并带有一个额外的 `configurable` 字段,它指定传递给工厂函数的特定 `sessionId`。这对于演示没有用,但在现实世界的链中,您需要返回一个与传递的会话相对应的聊天历史。
await chainWithMessageHistory.invoke(
{
input:
"Translate this sentence from English to French: I love programming.",
},
{ configurable: { sessionId: "unused" } }
);
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: `The translation of "I love programming" in French is "J'adore la programmation."`,
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: `The translation of "I love programming" in French is "J'adore la programmation."`,
name: undefined,
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {
tokenUsage: { completionTokens: 20, promptTokens: 39, totalTokens: 59 },
finish_reason: "stop"
},
tool_calls: [],
invalid_tool_calls: []
}
await chainWithMessageHistory.invoke(
{
input: "What did I just ask you?",
},
{ configurable: { sessionId: "unused" } }
);
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: 'You just asked for the translation of the sentence "I love programming" from English to French.',
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: 'You just asked for the translation of the sentence "I love programming" from English to French.',
name: undefined,
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {
tokenUsage: { completionTokens: 19, promptTokens: 74, totalTokens: 93 },
finish_reason: "stop"
},
tool_calls: [],
invalid_tool_calls: []
}
修改聊天历史记录
修改存储的聊天消息可以帮助您的聊天机器人处理各种情况。以下是一些示例。
修剪消息
LLM 和聊天模型的上下文窗口有限,即使您没有直接遇到限制,您可能也希望限制模型必须处理的干扰数量。一种解决方案是只加载和存储最新的 `n` 条消息。让我们使用一个带有预加载消息的示例历史记录。
await demoEphemeralChatMessageHistory.clear();
await demoEphemeralChatMessageHistory.addMessage(
new HumanMessage("Hey there! I'm Nemo.")
);
await demoEphemeralChatMessageHistory.addMessage(new AIMessage("Hello!"));
await demoEphemeralChatMessageHistory.addMessage(
new HumanMessage("How are you today?")
);
await demoEphemeralChatMessageHistory.addMessage(new AIMessage("Fine thanks!"));
await demoEphemeralChatMessageHistory.getMessages();
[
HumanMessage {
lc_serializable: true,
lc_kwargs: {
content: "Hey there! I'm Nemo.",
additional_kwargs: {},
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "Hey there! I'm Nemo.",
name: undefined,
additional_kwargs: {},
response_metadata: {}
},
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: "Hello!",
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: {},
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "Hello!",
name: undefined,
additional_kwargs: {},
response_metadata: {},
tool_calls: [],
invalid_tool_calls: []
},
HumanMessage {
lc_serializable: true,
lc_kwargs: {
content: "How are you today?",
additional_kwargs: {},
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "How are you today?",
name: undefined,
additional_kwargs: {},
response_metadata: {}
},
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: "Fine thanks!",
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: {},
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "Fine thanks!",
name: undefined,
additional_kwargs: {},
response_metadata: {},
tool_calls: [],
invalid_tool_calls: []
}
]
让我们将此消息历史记录与上面声明的 `RunnableWithMessageHistory` 链一起使用。
const chainWithMessageHistory2 = new RunnableWithMessageHistory({
runnable: chain2,
getMessageHistory: (_sessionId) => demoEphemeralChatMessageHistory,
inputMessagesKey: "input",
historyMessagesKey: "chat_history",
});
await chainWithMessageHistory2.invoke(
{
input: "What's my name?",
},
{ configurable: { sessionId: "unused" } }
);
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: "Your name is Nemo!",
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "Your name is Nemo!",
name: undefined,
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {
tokenUsage: { completionTokens: 6, promptTokens: 66, totalTokens: 72 },
finish_reason: "stop"
},
tool_calls: [],
invalid_tool_calls: []
}
我们可以看到该链记住了预加载的名称。
但是假设我们有一个非常小的上下文窗口,并且我们想将传递给链的消息数量修剪为仅保留最新的两条消息。我们可以使用 `clear` 方法删除消息,并将它们重新添加到历史记录中。我们不必这样做,但让我们将此方法放在链的最前面,以确保它始终被调用。
import {
RunnablePassthrough,
RunnableSequence,
} from "@langchain/core/runnables";
const trimMessages = async (_chainInput: Record<string, any>) => {
const storedMessages = await demoEphemeralChatMessageHistory.getMessages();
if (storedMessages.length <= 2) {
return false;
}
await demoEphemeralChatMessageHistory.clear();
for (const message of storedMessages.slice(-2)) {
demoEphemeralChatMessageHistory.addMessage(message);
}
return true;
};
const chainWithTrimming = RunnableSequence.from([
RunnablePassthrough.assign({ messages_trimmed: trimMessages }),
chainWithMessageHistory2,
]);
让我们调用这个新链并在之后检查消息。
await chainWithTrimming.invoke(
{
input: "Where does P. Sherman live?",
},
{ configurable: { sessionId: "unused" } }
);
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: 'P. Sherman is a fictional character who lives at 42 Wallaby Way, Sydney, from the movie "Finding Nem'... 3 more characters,
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: 'P. Sherman is a fictional character who lives at 42 Wallaby Way, Sydney, from the movie "Finding Nem'... 3 more characters,
name: undefined,
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {
tokenUsage: { completionTokens: 26, promptTokens: 53, totalTokens: 79 },
finish_reason: "stop"
},
tool_calls: [],
invalid_tool_calls: []
}
await demoEphemeralChatMessageHistory.getMessages();
[
HumanMessage {
lc_serializable: true,
lc_kwargs: {
content: "What's my name?",
additional_kwargs: {},
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "What's my name?",
name: undefined,
additional_kwargs: {},
response_metadata: {}
},
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: "Your name is Nemo!",
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "Your name is Nemo!",
name: undefined,
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {
tokenUsage: { completionTokens: 6, promptTokens: 66, totalTokens: 72 },
finish_reason: "stop"
},
tool_calls: [],
invalid_tool_calls: []
},
HumanMessage {
lc_serializable: true,
lc_kwargs: {
content: "Where does P. Sherman live?",
additional_kwargs: {},
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "Where does P. Sherman live?",
name: undefined,
additional_kwargs: {},
response_metadata: {}
},
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: 'P. Sherman is a fictional character who lives at 42 Wallaby Way, Sydney, from the movie "Finding Nem'... 3 more characters,
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: 'P. Sherman is a fictional character who lives at 42 Wallaby Way, Sydney, from the movie "Finding Nem'... 3 more characters,
name: undefined,
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {
tokenUsage: { completionTokens: 26, promptTokens: 53, totalTokens: 79 },
finish_reason: "stop"
},
tool_calls: [],
invalid_tool_calls: []
}
]
我们可以看到我们的历史记录已删除了两个最旧的消息,同时仍在最后添加了最新的对话。下次调用链时,`trimMessages` 将再次被调用,并且只有最新的两条消息将被传递给模型。在这种情况下,这意味着模型将忘记我们下次调用它时给它的名字。
await chainWithTrimming.invoke(
{
input: "What is my name?",
},
{ configurable: { sessionId: "unused" } }
);
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: "I'm sorry, I don't have access to your personal information. Can I help you with anything else?",
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "I'm sorry, I don't have access to your personal information. Can I help you with anything else?",
name: undefined,
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {
tokenUsage: { completionTokens: 22, promptTokens: 73, totalTokens: 95 },
finish_reason: "stop"
},
tool_calls: [],
invalid_tool_calls: []
}
await demoEphemeralChatMessageHistory.getMessages();
[
HumanMessage {
lc_serializable: true,
lc_kwargs: {
content: "Where does P. Sherman live?",
additional_kwargs: {},
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "Where does P. Sherman live?",
name: undefined,
additional_kwargs: {},
response_metadata: {}
},
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: 'P. Sherman is a fictional character who lives at 42 Wallaby Way, Sydney, from the movie "Finding Nem'... 3 more characters,
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: 'P. Sherman is a fictional character who lives at 42 Wallaby Way, Sydney, from the movie "Finding Nem'... 3 more characters,
name: undefined,
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {
tokenUsage: { completionTokens: 26, promptTokens: 53, totalTokens: 79 },
finish_reason: "stop"
},
tool_calls: [],
invalid_tool_calls: []
},
HumanMessage {
lc_serializable: true,
lc_kwargs: {
content: "What is my name?",
additional_kwargs: {},
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "What is my name?",
name: undefined,
additional_kwargs: {},
response_metadata: {}
},
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: "I'm sorry, I don't have access to your personal information. Can I help you with anything else?",
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "I'm sorry, I don't have access to your personal information. Can I help you with anything else?",
name: undefined,
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {
tokenUsage: { completionTokens: 22, promptTokens: 73, totalTokens: 95 },
finish_reason: "stop"
},
tool_calls: [],
invalid_tool_calls: []
}
]
总结记忆
我们也可以用其他方式使用这种模式。例如,我们可以在调用我们的链之前使用额外的 LLM 调用来生成对话摘要。让我们重新创建我们的聊天历史记录和聊天机器人链。
await demoEphemeralChatMessageHistory.clear();
await demoEphemeralChatMessageHistory.addMessage(
new HumanMessage("Hey there! I'm Nemo.")
);
await demoEphemeralChatMessageHistory.addMessage(new AIMessage("Hello!"));
await demoEphemeralChatMessageHistory.addMessage(
new HumanMessage("How are you today?")
);
await demoEphemeralChatMessageHistory.addMessage(new AIMessage("Fine thanks!"));
const runnableWithSummaryMemoryPrompt = ChatPromptTemplate.fromMessages([
[
"system",
"You are a helpful assistant. Answer all questions to the best of your ability. The provided chat history includes facts about the user you are speaking with.",
],
new MessagesPlaceholder("chat_history"),
["human", "{input}"],
]);
const summaryMemoryChain = runnableWithSummaryMemoryPrompt.pipe(llm);
const chainWithMessageHistory3 = new RunnableWithMessageHistory({
runnable: summaryMemoryChain,
getMessageHistory: (_sessionId) => demoEphemeralChatMessageHistory,
inputMessagesKey: "input",
historyMessagesKey: "chat_history",
});
现在,让我们创建一个函数,将之前的交互提炼成一个摘要。我们也可以将这个函数添加到链的最前面。
const summarizeMessages = async (_chainInput: Record<string, any>) => {
const storedMessages = await demoEphemeralChatMessageHistory.getMessages();
if (storedMessages.length === 0) {
return false;
}
const summarizationPrompt = ChatPromptTemplate.fromMessages([
new MessagesPlaceholder("chat_history"),
[
"user",
"Distill the above chat messages into a single summary message. Include as many specific details as you can.",
],
]);
const summarizationChain = summarizationPrompt.pipe(llm);
const summaryMessage = await summarizationChain.invoke({
chat_history: storedMessages,
});
await demoEphemeralChatMessageHistory.clear();
demoEphemeralChatMessageHistory.addMessage(summaryMessage);
return true;
};
const chainWithSummarization = RunnableSequence.from([
RunnablePassthrough.assign({
messages_summarized: summarizeMessages,
}),
chainWithMessageHistory3,
]);
让我们看看它是否记住了我们给它的名字。
await chainWithSummarization.invoke(
{
input: "What did I say my name was?",
},
{
configurable: { sessionId: "unused" },
}
);
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: 'You introduced yourself as "Nemo."',
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: 'You introduced yourself as "Nemo."',
name: undefined,
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {
tokenUsage: { completionTokens: 8, promptTokens: 87, totalTokens: 95 },
finish_reason: "stop"
},
tool_calls: [],
invalid_tool_calls: []
}
await demoEphemeralChatMessageHistory.getMessages();
[
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: "The conversation consists of a greeting from someone named Nemo and a general inquiry about their we"... 86 more characters,
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "The conversation consists of a greeting from someone named Nemo and a general inquiry about their we"... 86 more characters,
name: undefined,
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {
tokenUsage: { completionTokens: 34, promptTokens: 62, totalTokens: 96 },
finish_reason: "stop"
},
tool_calls: [],
invalid_tool_calls: []
},
HumanMessage {
lc_serializable: true,
lc_kwargs: {
content: "What did I say my name was?",
additional_kwargs: {},
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "What did I say my name was?",
name: undefined,
additional_kwargs: {},
response_metadata: {}
},
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: 'You introduced yourself as "Nemo."',
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: 'You introduced yourself as "Nemo."',
name: undefined,
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {
tokenUsage: { completionTokens: 8, promptTokens: 87, totalTokens: 95 },
finish_reason: "stop"
},
tool_calls: [],
invalid_tool_calls: []
}
]
请注意,再次调用链将生成另一个摘要,该摘要是从初始摘要加上新消息生成的,依此类推。您也可以设计一种混合方法,其中保留一定数量的聊天历史记录中的消息,而其他消息则进行总结。
下一步
您现在已经学习了如何在聊天机器人中管理内存。
接下来,查看本节中的其他一些指南,例如 如何为您的聊天机器人添加检索。