diff --git a/docs/docs/how-tos/state-reducers.md b/docs/docs/how-tos/state-reducers.md index 6784bbb70..3853f7c2c 100644 --- a/docs/docs/how-tos/state-reducers.md +++ b/docs/docs/how-tos/state-reducers.md @@ -11,14 +11,11 @@ We will use [messages](../concepts/low_level.md/#messagesstate) in our examples. First, let's install langgraph: -=== "Python" - ```shell - pip install -U langgraph - ``` -=== "TypeScript" - ```shell - npm install @langchain/langgraph - ``` + +```python +%%capture --no-stderr +%pip install -U langgraph +```

Set up LangSmith for better debugging

@@ -27,37 +24,25 @@ First, let's install langgraph:

- ## Example graph ### Define state - [State](../concepts/low_level.md/#state) in LangGraph can be a `TypedDict`, `Pydantic` model, or dataclass. Below we will use `TypedDict`. See [this guide](../how-tos/state-model.ipynb) for detail on using Pydantic. By default, graphs will have the same input and output schema, and the state determines that schema. See [this guide](../how-tos/input_output_schema.ipynb) for how to define distinct input and output schemas. Let's consider a simple example: -=== "Python" - ```python exec="on" source="above" session="1" - from langchain_core.messages import AnyMessage - from typing_extensions import TypedDict - - - class State(TypedDict): - messages: list[AnyMessage] - extra_field: int - ``` -=== "TypeScript" - ```typescript exec="1" source="above" session="1" - import { BaseMessage } from "@langchain/core/messages"; - import { Annotation } from "@langchain/langgraph"; - - const StateAnnotation = Annotation.Root({ - messages: Annotation(), - extraField: Annotation(), - }); - ``` + +```python exec="on" source="above" session="1" +from langchain_core.messages import AnyMessage +from typing_extensions import TypedDict + + +class State(TypedDict): + messages: list[AnyMessage] + extra_field: int +``` This state tracks a list of [message](https://python.langchain.com/docs/concepts/messages/) objects, as well as an extra integer field. @@ -80,12 +65,11 @@ This node simply appends a message to our message list, and populates an extra f !!! important -``` -Nodes should return updates to the state directly, instead of mutating the state. -``` + Nodes should return updates to the state directly, instead of mutating the state. Let's next define a simple graph containing this node. We use [StateGraph](../concepts/low_level.md#stategraph) to define a graph that operates on this state. We then use [add_node](../concepts/low_level.md#messagesstate) populate our graph. + ```python exec="on" source="above" session="1" from langgraph.graph import StateGraph @@ -97,6 +81,7 @@ graph = graph_builder.compile() LangGraph provides built-in utilities for visualizing your graph. Let's inspect our graph. See [this guide](../how-tos/visualization.ipynb) for detail on visualization. + ```python from IPython.display import Image, display @@ -111,6 +96,7 @@ In this case, our graph just executes a single node. Let's proceed with a simple invocation: + ```python exec="on" source="above" session="1" result="ansi" from langchain_core.messages import HumanMessage @@ -125,6 +111,7 @@ Note that: For convenience, we frequently inspect the content of [message objects](https://python.langchain.com/docs/concepts/messages/) via pretty-print: + ```python exec="on" source="above" session="1" result="ansi" for message in result["messages"]: message.pretty_print() @@ -138,6 +125,7 @@ For `TypedDict` state schemas, we can define reducers by annotating the correspo In the earlier example, our node updated the `"messages"` key in the state by appending a message to it. Below, we add a reducer to this key, such that updates are automatically appended: + ```python exec="on" source="above" session="1" from typing_extensions import Annotated @@ -155,6 +143,7 @@ class State(TypedDict): Now our node can be simplified: + ```python exec="on" source="above" session="1" def node(state: State): new_message = AIMessage("Hello!") @@ -162,6 +151,7 @@ def node(state: State): return {"messages": [new_message], "extra_field": 10} ``` + ```python exec="on" source="above" session="1" result="ansi" from langgraph.graph import START @@ -183,6 +173,7 @@ In practice, there are additional considerations for updating lists of messages: LangGraph includes a built-in reducer `add_messages` that handles these considerations: + ```python exec="on" source="above" session="1" from langgraph.graph.message import add_messages @@ -201,6 +192,7 @@ def node(state: State): graph = StateGraph(State).add_node(node).set_entry_point("node").compile() ``` + ```python exec="on" source="above" session="1" result="ansi" # highlight-next-line input_message = {"role": "user", "content": "Hi"} @@ -213,6 +205,7 @@ for message in result["messages"]: This is a versatile representation of state for applications involving [chat models](https://python.langchain.com/docs/concepts/chat_models/). LangGraph includes a pre-built `MessagesState` for convenience, so that we can have: + ```python exec="on" source="above" session="1" from langgraph.graph import MessagesState