Skip to content

Commit

Permalink
core[docs]: Docs & example for runnable history (#3527)
Browse files Browse the repository at this point in the history
* core[docs]: Docs & example for runnable history

* cr

* cr

* cr

* chore: yarn prettier

* cr

* cr

* cr

* chore: lint files

* cr
  • Loading branch information
bracesproul authored Dec 6, 2023
1 parent e2b3fef commit 4348fb7
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 1 deletion.
53 changes: 53 additions & 0 deletions docs/core_docs/docs/expression_language/how_to/with_history.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import CodeBlock from "@theme/CodeBlock";
import Example from "@examples/guides/expression_language/runnable_history.ts";

# 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.

<CodeBlock language="typescript">{Example}</CodeBlock>

## 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:

```typescript
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,
});

let output = await withHistory.invoke({ input: "Hello there, I'm Archibald!" });
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 }
}
*/
```
69 changes: 69 additions & 0 deletions examples/src/guides/expression_language/runnable_history.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { ChatOpenAI } from "langchain/chat_models/openai";
import { ChatMessageHistory } from "langchain/stores/message/in_memory";
import { ChatPromptTemplate, MessagesPlaceholder } from "langchain/prompts";
import {
RunnableConfig,
RunnableWithMessageHistory,
} from "langchain/runnables";

// 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
*/
5 changes: 4 additions & 1 deletion langchain-core/src/runnables/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import { RunnablePassthrough } from "./passthrough.js";
type GetSessionHistoryCallable = (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...args: Array<any>
) => Promise<BaseChatMessageHistory | BaseListChatMessageHistory>;
) =>
| Promise<BaseChatMessageHistory | BaseListChatMessageHistory>
| BaseChatMessageHistory
| BaseListChatMessageHistory;

export interface RunnableWithMessageHistoryInputs<RunInput, RunOutput>
extends Omit<
Expand Down

2 comments on commit 4348fb7

@vercel
Copy link

@vercel vercel bot commented on 4348fb7 Dec 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 4348fb7 Dec 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

langchainjs-docs – ./docs/core_docs/

langchainjs-docs-ruddy.vercel.app
langchainjs-docs-langchain.vercel.app
langchainjs-docs-git-main-langchain.vercel.app
js.langchain.com

Please sign in to comment.