Add message history (memory)
The RunnableWithMessageHistory
let's us add message history to certain types of chains.
Specifically, it can be used for any Runnable that takes as input one of
- a list of
BaseMessage
- an object with a key that takes a list of
BaseMessage
- an object with a key that takes the latest message(s) as a string or list of
BaseMessage
, and a separate key that takes historical messages
And returns as output one of
- a string that can be treated as the contents of an
AIMessage
- a list of
BaseMessage
- an object with a key that contains a list of
BaseMessage
Let's take a look at some examples to see how it works.
- npm
- Yarn
- pnpm
npm install @langchain/openai
yarn add @langchain/openai
pnpm add @langchain/openai
import { ChatOpenAI } from "@langchain/openai";
import {
ChatPromptTemplate,
MessagesPlaceholder,
} from "@langchain/core/prompts";
import {
RunnableConfig,
RunnableWithMessageHistory,
} from "@langchain/core/runnables";
import { ChatMessageHistory } from "@langchain/community/stores/message/in_memory";
// Instantiate your model and prompt.
const model = new ChatOpenAI({});
const prompt = ChatPromptTemplate.fromMessages([
["ai", "You are a helpful assistant"],
new MessagesPlaceholder("history"),
["human", "{input}"],
]);
// Create a simple runnable which just chains the prompt to the model.
const runnable = prompt.pipe(model);
// Define your session history store.
// This is where you will store your chat history.
const messageHistory = new ChatMessageHistory();
// Create your `RunnableWithMessageHistory` object, passing in the
// runnable created above.
const withHistory = new RunnableWithMessageHistory({
runnable,
// Optionally, you can use a function which tracks history by session ID.
getMessageHistory: (_sessionId: string) => messageHistory,
inputMessagesKey: "input",
// This shows the runnable where to insert the history.
// We set to "history" here because of our MessagesPlaceholder above.
historyMessagesKey: "history",
});
// Create your `configurable` object. This is where you pass in the
// `sessionId` which is used to identify chat sessions in your message store.
const config: RunnableConfig = { configurable: { sessionId: "1" } };
// Pass in your question, in this example we set the input key
// to be "input" so we need to pass an object with an "input" key.
let output = await withHistory.invoke(
{ input: "Hello there, I'm Archibald!" },
config
);
console.log("output 1:", output);
/**
output 1: AIMessage {
lc_namespace: [ 'langchain_core', 'messages' ],
content: 'Hello, Archibald! How can I assist you today?',
additional_kwargs: { function_call: undefined, tool_calls: undefined }
}
*/
output = await withHistory.invoke({ input: "What's my name?" }, config);
console.log("output 2:", output);
/**
output 2: AIMessage {
lc_namespace: [ 'langchain_core', 'messages' ],
content: 'Your name is Archibald, as you mentioned earlier. Is there anything specific you would like assistance with, Archibald?',
additional_kwargs: { function_call: undefined, tool_calls: undefined }
}
*/
/**
* You can see the LangSmith traces here:
* output 1 @link https://smith.langchain.com/public/686f061e-bef4-4b0d-a4fa-04c107b6db98/r
* output 2 @link https://smith.langchain.com/public/c30ba77b-c2f4-440d-a54b-f368ced6467a/r
*/
API Reference:
- ChatOpenAI from
@langchain/openai
- ChatPromptTemplate from
@langchain/core/prompts
- MessagesPlaceholder from
@langchain/core/prompts
- RunnableConfig from
@langchain/core/runnables
- RunnableWithMessageHistory from
@langchain/core/runnables
- ChatMessageHistory from
@langchain/community/stores/message/in_memory
Pass config through the constructor
You don't always have to pass the config
object through the invoke
method. RunnableWithMessageHistory
supports passing it through the constructor as well.
To do this, the only change you need to make is remove the second arg (or just the configurable
key from the second arg) from the invoke
method, and add it in through the config
key in the constructor.
This is a simple example building on top of what we have above:
import { ChatOpenAI } from "@langchain/openai";
import {
ChatPromptTemplate,
MessagesPlaceholder,
} from "@langchain/core/prompts";
import {
RunnableConfig,
RunnableWithMessageHistory,
} from "@langchain/core/runnables";
import { ChatMessageHistory } from "@langchain/community/stores/message/in_memory";
// Construct your runnable with a prompt and chat model.
const model = new ChatOpenAI({});
const prompt = ChatPromptTemplate.fromMessages([
["ai", "You are a helpful assistant"],
new MessagesPlaceholder("history"),
["human", "{input}"],
]);
const runnable = prompt.pipe(model);
const messageHistory = new ChatMessageHistory();
// Define a RunnableConfig object, with a `configurable` key.
const config: RunnableConfig = { configurable: { sessionId: "1" } };
const withHistory = new RunnableWithMessageHistory({
runnable,
getMessageHistory: (_sessionId: string) => messageHistory,
inputMessagesKey: "input",
historyMessagesKey: "history",
// Passing config through here instead of through the invoke method
config,
});
const output = await withHistory.invoke({
input: "Hello there, I'm Archibald!",
});
console.log("output:", output);
/**
output: AIMessage {
lc_namespace: [ 'langchain_core', 'messages' ],
content: 'Hello, Archibald! How can I assist you today?',
additional_kwargs: { function_call: undefined, tool_calls: undefined }
}
*/
/**
* You can see the LangSmith traces here:
* output @link https://smith.langchain.com/public/ee264a77-b767-4b5a-8573-efcbebaa5c80/r
*/
API Reference:
- ChatOpenAI from
@langchain/openai
- ChatPromptTemplate from
@langchain/core/prompts
- MessagesPlaceholder from
@langchain/core/prompts
- RunnableConfig from
@langchain/core/runnables
- RunnableWithMessageHistory from
@langchain/core/runnables
- ChatMessageHistory from
@langchain/community/stores/message/in_memory