mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-21 23:22:27 +02:00
232 lines
23 KiB
Plaintext
232 lines
23 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "95a87145-34d0-4f97-b45f-5c9fd8532c8a",
|
|
"metadata": {},
|
|
"source": [
|
|
"# How to create map-reduce branches for parallel execution\n",
|
|
"\n",
|
|
"A common pattern in agents is to generate a list of objects, do some work on each of those objects, and then combine the results. This is very similar to the common [map-reduce](https://en.wikipedia.org/wiki/MapReduce) operation. This can be tricky for a few reasons. First, it can be tough to define a structured graph ahead of time because the length of the list of objects may be unknown. Second, in order to do this map-reduce you need multiple versions of the state to exist... but the graph shares a common shared state, so how can this be?\n",
|
|
"\n",
|
|
"LangGraph supports this via the `Send` api. This can be used to allow a conditional edge to `Send` multiple different states to multiple nodes. The state it sends can be different from the state of the core graph.\n",
|
|
"\n",
|
|
"Let's see what this looks like in action! We'll put together a toy example of generating a list of words, and then writing a joke about each word, and then judging what the best joke is."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "3eb04cd1",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%pip install -U langchain-anthropic langgraph"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "dc292321",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import os\n",
|
|
"import getpass\n",
|
|
"\n",
|
|
"\n",
|
|
"def _set_env(name: str):\n",
|
|
" if not os.getenv(name):\n",
|
|
" os.environ[name] = getpass.getpass(f\"{name}: \")\n",
|
|
"\n",
|
|
"\n",
|
|
"_set_env(\"ANTHROPIC_API_KEY\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "0f0f78e4-423d-4e2d-aa1a-01efaec4715f",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import operator\n",
|
|
"from typing import Annotated, TypedDict\n",
|
|
"\n",
|
|
"from langchain_core.pydantic_v1 import BaseModel\n",
|
|
"from langchain_anthropic import ChatAnthropic\n",
|
|
"\n",
|
|
"from langgraph.constants import Send\n",
|
|
"from langgraph.graph import END, StateGraph, START\n",
|
|
"\n",
|
|
"# Model and prompts\n",
|
|
"# Define model and prompts we will use\n",
|
|
"subjects_prompt = \"\"\"Generate a comma separated list of between 2 and 5 {topic}.\"\"\"\n",
|
|
"joke_prompt = \"\"\"Generate a joke about {subject}\"\"\"\n",
|
|
"best_joke_prompt = \"\"\"Below are a bunch of jokes about {topic}. Select the best one! Return the ID of the best one.\n",
|
|
"\n",
|
|
"{jokes}\"\"\"\n",
|
|
"\n",
|
|
"\n",
|
|
"class Subjects(BaseModel):\n",
|
|
" subjects: list[str]\n",
|
|
"\n",
|
|
"\n",
|
|
"class Joke(BaseModel):\n",
|
|
" joke: str\n",
|
|
"\n",
|
|
"\n",
|
|
"class BestJoke(BaseModel):\n",
|
|
" id: int\n",
|
|
"\n",
|
|
"\n",
|
|
"model = ChatAnthropic(model=\"claude-3-5-sonnet-20240620\")\n",
|
|
"\n",
|
|
"# Graph components: define the components that will make up the graph\n",
|
|
"\n",
|
|
"\n",
|
|
"# This will be the overall state of the main graph.\n",
|
|
"# It will contain a topic (which we expect the user to provide)\n",
|
|
"# and then will generate a list of subjects, and then a joke for\n",
|
|
"# each subject\n",
|
|
"class OverallState(TypedDict):\n",
|
|
" topic: str\n",
|
|
" subjects: list\n",
|
|
" # Notice here we use the operator.add\n",
|
|
" # This is because we want combine all the jokes we generate\n",
|
|
" # from individual nodes back into one list - this is essentially\n",
|
|
" # the \"reduce\" part\n",
|
|
" jokes: Annotated[list, operator.add]\n",
|
|
" best_selected_joke: str\n",
|
|
"\n",
|
|
"\n",
|
|
"# This will be the state of the node that we will \"map\" all\n",
|
|
"# subjects to in order to generate a joke\n",
|
|
"class JokeState(TypedDict):\n",
|
|
" subject: str\n",
|
|
"\n",
|
|
"\n",
|
|
"# This is the function we will use to generate the subjects of the jokes\n",
|
|
"def generate_topics(state: OverallState):\n",
|
|
" prompt = subjects_prompt.format(topic=state[\"topic\"])\n",
|
|
" response = model.with_structured_output(Subjects).invoke(prompt)\n",
|
|
" return {\"subjects\": response.subjects}\n",
|
|
"\n",
|
|
"\n",
|
|
"# Here we generate a joke, given a subject\n",
|
|
"def generate_joke(state: JokeState):\n",
|
|
" prompt = joke_prompt.format(subject=state[\"subject\"])\n",
|
|
" response = model.with_structured_output(Joke).invoke(prompt)\n",
|
|
" return {\"jokes\": [response.joke]}\n",
|
|
"\n",
|
|
"\n",
|
|
"# Here we define the logic to map out over the generated subjects\n",
|
|
"# We will use this an edge in the graph\n",
|
|
"def continue_to_jokes(state: OverallState):\n",
|
|
" # We will return a list of `Send` objects\n",
|
|
" # Each `Send` object consists of the name of a node in the graph\n",
|
|
" # as well as the state to send to that node\n",
|
|
" return [Send(\"generate_joke\", {\"subject\": s}) for s in state[\"subjects\"]]\n",
|
|
"\n",
|
|
"\n",
|
|
"# Here we will judge the best joke\n",
|
|
"def best_joke(state: OverallState):\n",
|
|
" jokes = \"\\n\\n\".format()\n",
|
|
" prompt = best_joke_prompt.format(topic=state[\"topic\"], jokes=jokes)\n",
|
|
" response = model.with_structured_output(BestJoke).invoke(prompt)\n",
|
|
" return {\"best_selected_joke\": state[\"jokes\"][response.id]}\n",
|
|
"\n",
|
|
"\n",
|
|
"# Construct the graph: here we put everything together to construct our graph\n",
|
|
"graph = StateGraph(OverallState)\n",
|
|
"graph.add_node(\"generate_topics\", generate_topics)\n",
|
|
"graph.add_node(\"generate_joke\", generate_joke)\n",
|
|
"graph.add_node(\"best_joke\", best_joke)\n",
|
|
"graph.add_edge(START, \"generate_topics\")\n",
|
|
"graph.add_conditional_edges(\"generate_topics\", continue_to_jokes, [\"generate_joke\"])\n",
|
|
"graph.add_edge(\"generate_joke\", \"best_joke\")\n",
|
|
"graph.add_edge(\"best_joke\", END)\n",
|
|
"app = graph.compile()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "37ed1f71-63db-416f-b715-4617b33d4b7f",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"image/jpeg": "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",
|
|
"text/plain": [
|
|
"<IPython.core.display.Image object>"
|
|
]
|
|
},
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"from IPython.display import Image\n",
|
|
"\n",
|
|
"Image(app.get_graph().draw_mermaid_png())"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "fd90cace",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"{'generate_topics': {'subjects': ['lion', 'elephant', 'penguin', 'giraffe']}}\n",
|
|
"{'generate_joke': {'jokes': [\"Why don't you see penguins in Britain? Because they're afraid of Wales!\"]}}\n",
|
|
"{'generate_joke': {'jokes': [\"Why don't elephants use computers? They're afraid of the mouse!\"]}}\n",
|
|
"{'generate_joke': {'jokes': [\"Why don't lions like fast food? Because they can't catch it!\"]}}\n",
|
|
"{'generate_joke': {'jokes': [\"Why don't giraffes ever get caught in traffic jams? Because they can always stick their necks out and see what's ahead!\"]}}\n",
|
|
"{'best_joke': {'best_selected_joke': \"Why don't elephants use computers? They're afraid of the mouse!\"}}\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Call the graph: here we call it to generate a list of jokes\n",
|
|
"for s in app.stream({\"topic\": \"animals\"}):\n",
|
|
" print(s)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "f28eaf56",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3 (ipykernel)",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.12.2"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|