跳至主要内容

如何添加消息历史记录

RunnableWithMessageHistory 允许我们将消息历史记录添加到某些类型的链中。

具体来说,它可用于任何接受以下之一作为输入的可运行对象:

  • 一系列BaseMessages
  • 包含接受一系列 BaseMessage 的键的字典
  • 包含接受最新消息(作为字符串或一系列 BaseMessage)的键和接受历史消息的单独键的字典

并返回以下之一作为输出:

  • 可以被视为 AIMessage 内容的字符串
  • 一系列 BaseMessage
  • 包含包含一系列 BaseMessage 的键的字典

让我们看一些示例,了解它的工作原理。

设置

我们将使用 Upstash 存储我们的聊天消息历史记录,并使用 Anthropic 的 claude-2 模型,因此我们需要安装以下依赖项

npm install @langchain/anthropic @langchain/community @upstash/redis

您需要设置 ANTHROPIC_API_KEY 的环境变量,并获取您的 Upstash REST URL 和秘密令牌。

LangSmith

LangSmith 对于消息历史记录注入等情况特别有用,在这种情况下,否则很难理解各种链部分的输入。

请注意,LangSmith 不是必需的,但它很有用。如果您确实想使用 LangSmith,在您在上面的链接中注册后,请确保取消注释下面的内容并设置您的环境变量以开始记录跟踪

export LANGCHAIN_TRACING_V2="true"
export LANGCHAIN_API_KEY="<your-api-key>"

# Reduce tracing latency if you are not in a serverless environment
# export LANGCHAIN_CALLBACKS_BACKGROUND=true

让我们创建一个简单的可运行对象,它接受字典作为输入并返回 BaseMessage

在本例中,输入中的 "question" 键代表我们的输入消息,而 "history" 键是注入历史消息的地方。

import {
ChatPromptTemplate,
MessagesPlaceholder,
} from "@langchain/core/prompts";
import { ChatAnthropic } from "@langchain/anthropic";
import { UpstashRedisChatMessageHistory } from "@langchain/community/stores/message/upstash_redis";
// For demos, you can also use an in-memory store:
// import { ChatMessageHistory } from "langchain/stores/message/in_memory";

const prompt = ChatPromptTemplate.fromMessages([
["system", "You're an assistant who's good at {ability}"],
new MessagesPlaceholder("history"),
["human", "{question}"],
]);

const chain = prompt.pipe(
new ChatAnthropic({ model: "claude-3-sonnet-20240229" })
);

添加消息历史记录

要将消息历史记录添加到我们的原始链中,我们将它包装在 RunnableWithMessageHistory 类中。

至关重要的是,我们还需要定义一个 getMessageHistory() 方法,它接受一个 sessionId 字符串并根据它返回 BaseChatMessageHistory。给定相同的输入,此方法应返回等效的输出。

在本例中,我们还需要指定 inputMessagesKey(将被视为最新输入消息的键)和 historyMessagesKey(将向其添加历史消息的键)。

import { RunnableWithMessageHistory } from "@langchain/core/runnables";

const chainWithHistory = new RunnableWithMessageHistory({
runnable: chain,
getMessageHistory: (sessionId) =>
new UpstashRedisChatMessageHistory({
sessionId,
config: {
url: process.env.UPSTASH_REDIS_REST_URL!,
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
},
}),
inputMessagesKey: "question",
historyMessagesKey: "history",
});

使用配置调用

每当我们使用消息历史记录调用链时,都需要包含一个额外的配置对象,其中包含 session_id

{
configurable: {
sessionId: "<SESSION_ID>";
}
}

给定相同的配置,我们的链应该从相同的聊天消息历史记录中提取。

const result = await chainWithHistory.invoke(
{
ability: "math",
question: "What does cosine mean?",
},
{
configurable: {
sessionId: "foobarbaz",
},
}
);

console.log(result);

/*
AIMessage {
content: 'Cosine refers to one of the basic trigonometric functions. Specifically:\n' +
'\n' +
'- Cosine is one of the three main trigonometric functions, along with sine and tangent. It is often abbreviated as cos.\n' +
'\n' +
'- For a right triangle with sides a, b, and c (where c is the hypotenuse), cosine represents the ratio of the length of the adjacent side (a) to the length of the hypotenuse (c). So cos(A) = a/c, where A is the angle opposite side a.\n' +
'\n' +
'- On the Cartesian plane, cosine represents the x-coordinate of a point on the unit circle for a given angle. So if you take an angle θ on the unit circle, the cosine of θ gives you the x-coordinate of where the terminal side of that angle intersects the circle.\n' +
'\n' +
'- The cosine function has a periodic waveform that oscillates between 1 and -1. Its graph forms a cosine wave.\n' +
'\n' +
'So in essence, cosine helps relate an angle in a right triangle to the ratio of two of its sides. Along with sine and tangent, it is foundational to trigonometry and mathematical modeling of periodic functions.',
name: undefined,
additional_kwargs: {
id: 'msg_01QnnAkKEz7WvhJrwLWGbLBm',
type: 'message',
role: 'assistant',
model: 'claude-3-sonnet-20240229',
stop_reason: 'end_turn',
stop_sequence: null
}
}
*/

const result2 = await chainWithHistory.invoke(
{
ability: "math",
question: "What's its inverse?",
},
{
configurable: {
sessionId: "foobarbaz",
},
}
);

console.log(result2);

/*
AIMessage {
content: 'The inverse of the cosine function is the arcsine or inverse sine function, often written as sin−1(x) or sin^{-1}(x).\n' +
'\n' +
'Some key properties of the inverse cosine function:\n' +
'\n' +
'- It accepts values between -1 and 1 as inputs and returns angles from 0 to π radians (0 to 180 degrees). This is the inverse of the regular cosine function, which takes angles and returns the cosine ratio.\n' +
'\n' +
'- It is also called cos−1(x) or cos^{-1}(x) (read as "cosine inverse of x").\n' +
'\n' +
'- The notation sin−1(x) is usually preferred over cos−1(x) since it relates more directly to the unit circle definition of cosine. sin−1(x) gives the angle whose sine equals x.\n' +
'\n' +
'- The arcsine function is one-to-one on the domain [-1, 1]. This means every output angle maps back to exactly one input ratio x. This one-to-one mapping is what makes it the mathematical inverse of cosine.\n' +
'\n' +
'So in summary, arcsine or inverse sine, written as sin−1(x) or sin^{-1}(x), gives you the angle whose cosine evaluates to the input x, undoing the cosine function. It is used throughout trigonometry and calculus.',
additional_kwargs: {
id: 'msg_01PYRhpoUudApdJvxug6R13W',
type: 'message',
role: 'assistant',
model: 'claude-3-sonnet-20240229',
stop_reason: 'end_turn',
stop_sequence: null
}
}
*/

查看第二个调用的 Langsmith 跟踪,我们可以看到,在构建提示时,已注入一个“history”变量,它是一个包含两条消息的列表(我们的第一个输入和第一个输出)。


本页是否有用?


您也可以在 GitHub.