-
Notifications
You must be signed in to change notification settings - Fork 115
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into brace/fix-api-ref-urls
- Loading branch information
Showing
3 changed files
with
233 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# How to define graph state\n", | ||
"\n", | ||
"This how to guide will cover how to define the state of your graph. This implementation has changed, and there is a new recommended method of defining the state of your graph. This new method is through the [`Annotation`](https://langchain-ai.github.io/langgraphjs/reference/functions/langgraph.Annotation-1.html) function.\n", | ||
"\n", | ||
"## Prerequisites\n", | ||
"\n", | ||
"- [State conceptual guide](https://langchain-ai.github.io/langgraphjs/concepts/low_level/#state) - Conceptual guide on defining the state of your graph.\n", | ||
"- [Building graphs](https://langchain-ai.github.io/langgraphjs/tutorials/quickstart/) - This how to assumes you have a basic understanding of how to build graphs.\n", | ||
"\n", | ||
"## Setup\n", | ||
"\n", | ||
"This guide requires installing the `@langchain/langgraph`, and `@langchain/core` packages:\n", | ||
"\n", | ||
"```bash\n", | ||
"npm install @langchain/langgraph @langchain/core\n", | ||
"```\n", | ||
"\n", | ||
"## Getting started\n", | ||
"\n", | ||
"The `Annotation` function is the recommended way to define your graph state for new `StateGraph` graphs. The `Annotation.Root` function is used to create the top-level state object, where each field represents a channel in the graph.\n", | ||
"\n", | ||
"Here's an example of how to define a simple graph state with one channel called `messages`:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 1, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import { BaseMessage } from \"@langchain/core/messages\";\n", | ||
"import { Annotation } from \"@langchain/langgraph\";\n", | ||
"\n", | ||
"const GraphAnnotation = Annotation.Root({\n", | ||
" // Define a 'messages' channel to store an array of BaseMessage objects\n", | ||
" messages: Annotation<BaseMessage[]>({\n", | ||
" // Reducer function: Combines the current state with new messages\n", | ||
" reducer: (currentState, updateValue) => currentState.concat(updateValue),\n", | ||
" // Default function: Initialize the channel with an empty array\n", | ||
" default: () => [],\n", | ||
" })\n", | ||
"});" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Each channel can optionally have `reducer` and `default` functions:\n", | ||
"- The `reducer` function defines how new values are combined with the existing state.\n", | ||
"- The `default` function provides an initial value for the channel.\n", | ||
"\n", | ||
"For more information on reducers, see the [reducers conceptual guide](https://langchain-ai.github.io/langgraphjs/concepts/low_level/#reducers)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"const QuestionAnswerAnnotation = Annotation.Root({\n", | ||
" question: Annotation<string>,\n", | ||
" answer: Annotation<string>,\n", | ||
"});" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Above, all we're doing is defining the channels, and then passing the un-instantiated `Annotation` function as the value. It is important to note we always pass in the TypeScript type of each channel as the first generics argument to `Annotation`. Doing this ensures our graph state is type safe, and we can get the proper types when defining our nodes. Below shows how you can extract the typings from the `Annotation` function:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 3, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"type QuestionAnswerAnnotationType = typeof QuestionAnswerAnnotation.State;" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"This is equivalent to the following type:\n", | ||
"\n", | ||
"```typescript\n", | ||
"type QuestionAnswerAnnotationType = {\n", | ||
" question: string;\n", | ||
" answer: string;\n", | ||
"}\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Merging states\n", | ||
"\n", | ||
"If you have two graph state annotations, you can merge the two into a single annotation by using the `spec` value:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 4, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"const MergedAnnotation = Annotation.Root({\n", | ||
" ...QuestionAnswerAnnotation.spec,\n", | ||
" ...GraphAnnotation.spec,\n", | ||
"})" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"The type of the merged annotation is the intersection of the two annotations:\n", | ||
"\n", | ||
"```typescript\n", | ||
"type MergedAnnotation = {\n", | ||
" messages: BaseMessage[];\n", | ||
" question: string;\n", | ||
" answer: string;\n", | ||
"}\n", | ||
"```\n", | ||
"\n", | ||
"Finally, instantiating your graph using the annotations is as simple as passing the annotation to the `StateGraph` constructor:\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 5, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import { StateGraph } from \"@langchain/langgraph\";\n", | ||
"\n", | ||
"const workflow = new StateGraph(MergedAnnotation);" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## State channels\n", | ||
"\n", | ||
"The `Annotation` function is a convince wrapper around the low level implementation of how states are defined in LangGraph. Defining state using the `channels` object (which is what `Annotation` is a wrapper of) is still possible, although not recommended for most cases. The below example shows how to implement a graph using this pattern:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 6, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import { StateGraph } from \"@langchain/langgraph\";\n", | ||
"\n", | ||
"interface WorkflowChannelsState {\n", | ||
" messages: BaseMessage[];\n", | ||
" question: string;\n", | ||
" answer: string;\n", | ||
"}\n", | ||
"\n", | ||
"const workflowWithChannels = new StateGraph<WorkflowChannelsState>({\n", | ||
" channels: {\n", | ||
" messages: {\n", | ||
" reducer: (currentState, updateValue) => currentState.concat(updateValue),\n", | ||
" default: () => [],\n", | ||
" },\n", | ||
" question: null,\n", | ||
" answer: null,\n", | ||
" }\n", | ||
"});" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Above, we set the value of `question` and `answer` to `null`, as it does not contain a default value. To set a default value, the channel should be implemented how the `messages` key is, with the `default` factory returing the default value. The `reducer` function is optional, and can be added to the channel object if needed." | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "TypeScript", | ||
"language": "typescript", | ||
"name": "tslab" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"mode": "typescript", | ||
"name": "javascript", | ||
"typescript": true | ||
}, | ||
"file_extension": ".ts", | ||
"mimetype": "text/typescript", | ||
"name": "typescript", | ||
"version": "3.7.2" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters