From ca7da2fc4188b7b4ddf0e5d378ed91c9a535038e Mon Sep 17 00:00:00 2001 From: Christopher Brooks Date: Tue, 19 Nov 2024 11:18:53 -0500 Subject: [PATCH 01/58] feat: Make CompiledGraph displayable in Juypyter with display() (#2159) --- libs/langgraph/langgraph/graph/graph.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libs/langgraph/langgraph/graph/graph.py b/libs/langgraph/langgraph/graph/graph.py index e91ac4a47..a1cc029e8 100644 --- a/libs/langgraph/langgraph/graph/graph.py +++ b/libs/langgraph/langgraph/graph/graph.py @@ -628,3 +628,11 @@ class CompiledGraph(Pregel): add_edge(key, end, conditional=True) return graph + + def _repr_mimebundle_(self, **kwargs) -> dict[str, Any]: + """Mime bundle used by Jupyter to display the graph""" + output = { + "text/plain": repr(self), + "image/png": self.get_graph().draw_mermaid_png() + } + return output From 253090f34dbef6656ae2e1c98e40622a24b48fa6 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 19 Nov 2024 10:29:32 -0800 Subject: [PATCH 02/58] lint --- libs/langgraph/langgraph/graph/graph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/langgraph/langgraph/graph/graph.py b/libs/langgraph/langgraph/graph/graph.py index a1cc029e8..11ef41820 100644 --- a/libs/langgraph/langgraph/graph/graph.py +++ b/libs/langgraph/langgraph/graph/graph.py @@ -633,6 +633,6 @@ class CompiledGraph(Pregel): """Mime bundle used by Jupyter to display the graph""" output = { "text/plain": repr(self), - "image/png": self.get_graph().draw_mermaid_png() + "image/png": self.get_graph().draw_mermaid_png(), } return output From 7d8205633d32f05d544f517e63c0c7754ccc75cd Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Fri, 8 Nov 2024 13:05:45 -0800 Subject: [PATCH 03/58] Add `call` function to call a node and get a future - Whereas Send is for fire-and-forget type of calls, new `call` and `acall` functions are for flows where you want to wait for the node to finish before doing something else - Because we return regular python future objects (concurrent.futures.Future or asyncio.Future) all the python primitives for working with futures work, eg. wait, gather, etc --- libs/langgraph/langgraph/constants.py | 2 + libs/langgraph/langgraph/pregel/__init__.py | 5 + libs/langgraph/langgraph/pregel/algo.py | 40 ++++++-- libs/langgraph/langgraph/pregel/loop.py | 8 +- libs/langgraph/langgraph/pregel/retry.py | 20 ++-- libs/langgraph/langgraph/pregel/runner.py | 108 ++++++++++++++------ libs/langgraph/langgraph/types.py | 38 +++++++ libs/langgraph/tests/test_pregel.py | 48 ++++----- libs/langgraph/tests/test_pregel_async.py | 74 ++++---------- 9 files changed, 197 insertions(+), 146 deletions(-) diff --git a/libs/langgraph/langgraph/constants.py b/libs/langgraph/langgraph/constants.py index e2d9f069a..b9d6f37f7 100644 --- a/libs/langgraph/langgraph/constants.py +++ b/libs/langgraph/langgraph/constants.py @@ -46,6 +46,8 @@ CONFIG_KEY_SEND = sys.intern("__pregel_send") # holds the `write` function that accepts writes to state/edges/reserved keys CONFIG_KEY_READ = sys.intern("__pregel_read") # holds the `read` function that returns a copy of the current state +CONFIG_KEY_CALL = sys.intern("__pregel_call") +# holds the `call` function that accepts a node/func, args and returns a future CONFIG_KEY_CHECKPOINTER = sys.intern("__pregel_checkpointer") # holds a `BaseCheckpointSaver` passed from parent graph to child graphs CONFIG_KEY_STREAM = sys.intern("__pregel_stream") diff --git a/libs/langgraph/langgraph/pregel/__init__.py b/libs/langgraph/langgraph/pregel/__init__.py index e714afe21..52cd2bf09 100644 --- a/libs/langgraph/langgraph/pregel/__init__.py +++ b/libs/langgraph/langgraph/pregel/__init__.py @@ -541,6 +541,11 @@ class Pregel(PregelProtocol): next_tasks[tid].writes.append((k, v)) if tasks := [t for t in next_tasks.values() if t.writes]: apply_writes(saved.checkpoint, channels, tasks, None) + print( + "next_tasks", + [(t.id, t.name, t.input, bool(t.writes)) for t in next_tasks.values()], + ) + print("pending_writes", saved.pending_writes) # assemble the state snapshot return StateSnapshot( read_channels(channels, self.stream_channels_asis), diff --git a/libs/langgraph/langgraph/pregel/algo.py b/libs/langgraph/langgraph/pregel/algo.py index 0885f12aa..a8d39674c 100644 --- a/libs/langgraph/langgraph/pregel/algo.py +++ b/libs/langgraph/langgraph/pregel/algo.py @@ -97,6 +97,11 @@ class PregelTaskWrites(NamedTuple): triggers: Sequence[str] +class Call: + func: str | Callable + input: Any + + def should_interrupt( checkpoint: Checkpoint, interrupt_nodes: Union[All, Sequence[str]], @@ -490,10 +495,16 @@ def prepare_single_task( PUSH, str(idx), ) - elif len(task_path) == 4: + elif len(task_path) >= 4: # new PUSH tasks, executed in superstep n # (PUSH, parent task path, idx of PUSH write, id of parent task) - task_path_t = cast(tuple[str, tuple, int, str], task_path) + task_path_t = cast( + Union[ + tuple[str, tuple, int, str], + tuple[str, tuple, int, str, Optional[Call]], + ], + task_path, + ) writes_for_path = [w for w in pending_writes if w[0] == task_path_t[3]] if task_path_t[2] >= len(writes_for_path): logger.warning( @@ -501,6 +512,13 @@ def prepare_single_task( ) return packet = writes_for_path[task_path_t[2]][2] + if packet is None: + if len(task_path_t) == 5: + packet = task_path_t[4] + else: + # no packet to replay, this is a "call" task + return + # TODO handle Call packets if not isinstance(packet, Send): logger.warning( f"Ignoring invalid packet type {type(packet)} in pending writes" @@ -533,7 +551,7 @@ def prepare_single_task( "langgraph_step": step, "langgraph_node": packet.node, "langgraph_triggers": triggers, - "langgraph_path": task_path, + "langgraph_path": task_path[:3], "langgraph_checkpoint_ns": task_checkpoint_ns, } if task_id_checksum is not None: @@ -572,7 +590,7 @@ def prepare_single_task( channels, managed, PregelTaskWrites( - task_path, packet.node, writes, triggers + task_path[:3], packet.node, writes, triggers ), config, ), @@ -602,12 +620,12 @@ def prepare_single_task( proc.retry_policy, None, task_id, - task_path, + task_path[:3], writers=proc.flat_writers, ) else: - return PregelTask(task_id, packet.node, task_path) + return PregelTask(task_id, packet.node, task_path[:3]) elif task_path[0] == PULL: # (PULL, node name) name = cast(str, task_path[1]) @@ -657,7 +675,7 @@ def prepare_single_task( "langgraph_step": step, "langgraph_node": name, "langgraph_triggers": triggers, - "langgraph_path": task_path, + "langgraph_path": task_path[:3], "langgraph_checkpoint_ns": task_checkpoint_ns, } if task_id_checksum is not None: @@ -696,7 +714,9 @@ def prepare_single_task( checkpoint, channels, managed, - PregelTaskWrites(task_path, name, writes, triggers), + PregelTaskWrites( + task_path[:3], name, writes, triggers + ), config, ), CONFIG_KEY_STORE: ( @@ -725,11 +745,11 @@ def prepare_single_task( proc.retry_policy, None, task_id, - task_path, + task_path[:3], writers=proc.flat_writers, ) else: - return PregelTask(task_id, name, task_path) + return PregelTask(task_id, name, task_path[:3]) def _proc_input( diff --git a/libs/langgraph/langgraph/pregel/loop.py b/libs/langgraph/langgraph/pregel/loop.py index d9af9279e..31397d22b 100644 --- a/libs/langgraph/langgraph/pregel/loop.py +++ b/libs/langgraph/langgraph/pregel/loop.py @@ -73,6 +73,7 @@ from langgraph.managed.base import ( WritableManagedValue, ) from langgraph.pregel.algo import ( + Call, GetNextVersion, PregelTaskWrites, apply_writes, @@ -307,12 +308,9 @@ class PregelLoop(LoopProtocol): self._output_writes(task_id, writes) def accept_push( - self, task: PregelExecutableTask, write_idx: int + self, task: PregelExecutableTask, write_idx: int, call: Optional[Call] = None ) -> Optional[PregelExecutableTask]: """Accept a PUSH from a task, potentially returning a new task to start.""" - # don't start if an earlier PUSH has already triggered an interrupt - if self.to_interrupt: - return # don't start if we should interrupt *after* the original task if should_interrupt(self.checkpoint, self.interrupt_after, [task]): self.to_interrupt.append(task) @@ -320,7 +318,7 @@ class PregelLoop(LoopProtocol): if pushed := cast( Optional[PregelExecutableTask], prepare_single_task( - (PUSH, task.path, write_idx, task.id), + (PUSH, task.path, write_idx, task.id, call), None, checkpoint=self.checkpoint, pending_writes=[(task.id, *w) for w in task.writes], diff --git a/libs/langgraph/langgraph/pregel/retry.py b/libs/langgraph/langgraph/pregel/retry.py index 2d0f2b6da..093859579 100644 --- a/libs/langgraph/langgraph/pregel/retry.py +++ b/libs/langgraph/langgraph/pregel/retry.py @@ -4,14 +4,12 @@ import random import sys import time from dataclasses import replace -from functools import partial -from typing import Any, Callable, Optional, Sequence +from typing import Any, Optional, Sequence from langgraph.constants import ( CONF, CONFIG_KEY_CHECKPOINT_NS, CONFIG_KEY_RESUMING, - CONFIG_KEY_SEND, NS_SEP, ) from langgraph.errors import _SEEN_CHECKPOINT_NS, GraphBubbleUp, ParentCommand @@ -25,17 +23,15 @@ SUPPORTS_EXC_NOTES = sys.version_info >= (3, 11) def run_with_retry( task: PregelExecutableTask, retry_policy: Optional[RetryPolicy], - writer: Optional[ - Callable[[PregelExecutableTask, Sequence[tuple[str, Any]]], None] - ] = None, + configurable: Optional[dict[str, Any]] = None, ) -> None: """Run a task with retries.""" retry_policy = task.retry_policy or retry_policy interval = retry_policy.initial_interval if retry_policy else 0 attempts = 0 config = task.config - if writer is not None: - config = patch_configurable(config, {CONFIG_KEY_SEND: partial(writer, task)}) + if configurable is not None: + config = patch_configurable(config, configurable) while True: try: # clear any writes from previous attempts @@ -115,17 +111,15 @@ async def arun_with_retry( task: PregelExecutableTask, retry_policy: Optional[RetryPolicy], stream: bool = False, - writer: Optional[ - Callable[[PregelExecutableTask, Sequence[tuple[str, Any]]], None] - ] = None, + configurable: Optional[dict[str, Any]] = None, ) -> None: """Run a task asynchronously with retries.""" retry_policy = task.retry_policy or retry_policy interval = retry_policy.initial_interval if retry_policy else 0 attempts = 0 config = task.config - if writer is not None: - config = patch_configurable(config, {CONFIG_KEY_SEND: partial(writer, task)}) + if configurable is not None: + config = patch_configurable(config, configurable) while True: try: # clear any writes from previous attempts diff --git a/libs/langgraph/langgraph/pregel/runner.py b/libs/langgraph/langgraph/pregel/runner.py index f46210459..067394bdb 100644 --- a/libs/langgraph/langgraph/pregel/runner.py +++ b/libs/langgraph/langgraph/pregel/runner.py @@ -1,9 +1,11 @@ import asyncio import concurrent.futures import time +from functools import partial from typing import ( Any, AsyncIterator, + Awaitable, Callable, Iterable, Iterator, @@ -16,6 +18,7 @@ from typing import ( from langgraph.constants import ( CONF, + CONFIG_KEY_CALL, CONFIG_KEY_SEND, ERROR, INTERRUPT, @@ -25,6 +28,7 @@ from langgraph.constants import ( TAG_HIDDEN, ) from langgraph.errors import GraphBubbleUp, GraphInterrupt +from langgraph.pregel.algo import Call from langgraph.pregel.executor import Submit from langgraph.pregel.retry import arun_with_retry, run_with_retry from langgraph.types import PregelExecutableTask, RetryPolicy @@ -41,7 +45,7 @@ class PregelRunner: submit: Submit, put_writes: Callable[[str, Sequence[tuple[str, Any]]], None], schedule_task: Callable[ - [PregelExecutableTask, int], Optional[PregelExecutableTask] + [PregelExecutableTask, int, Optional[Call]], Optional[PregelExecutableTask] ], use_astream: bool = False, node_finished: Optional[Callable[[str], None]] = None, @@ -67,11 +71,10 @@ class PregelRunner: prev_length = len(task.writes) # delegate to the underlying writer task.config[CONF][CONFIG_KEY_SEND](writes) - for idx, w in enumerate(task.writes): - # find the index for the newly inserted writes - if idx < prev_length: - continue - assert writes[idx - prev_length] is w + # confirm no other concurrent writes were added + # TODO could use a lock here instead, if writes can come from many threads + assert len(task.writes) == prev_length + len(writes) + for idx, w in enumerate(writes, start=prev_length): # bail if not a PUSH write if w[0] != PUSH: continue @@ -89,7 +92,10 @@ class PregelRunner: run_with_retry, next_task, retry_policy, - writer=writer, + configurable={ + CONFIG_KEY_SEND: partial(writer, next_task), + # CONFIG_KEY_CALL: partial(call, next_task), + }, __reraise_on_exit__=reraise, ) ] = next_task @@ -102,7 +108,14 @@ class PregelRunner: if len(tasks) == 1 and timeout is None and get_waiter is None: t = tasks[0] try: - run_with_retry(t, retry_policy, writer=writer) + run_with_retry( + t, + retry_policy, + configurable={ + CONFIG_KEY_SEND: partial(writer, t), + # CONFIG_KEY_CALL: partial(call, t), + }, + ) self.commit(t, None) except Exception as exc: self.commit(t, exc) @@ -123,7 +136,10 @@ class PregelRunner: run_with_retry, t, retry_policy, - writer=writer, + configurable={ + CONFIG_KEY_SEND: partial(writer, t), + # CONFIG_KEY_CALL: partial(call, t), + }, __reraise_on_exit__=reraise, ) ] = t @@ -172,21 +188,28 @@ class PregelRunner: get_waiter: Optional[Callable[[], asyncio.Future[None]]] = None, ) -> AsyncIterator[None]: def writer( - task: PregelExecutableTask, writes: Sequence[tuple[str, Any]] - ) -> None: + task: PregelExecutableTask, + writes: Sequence[tuple[str, Any]], + *, + calls: Optional[Sequence[Call]] = None, + ) -> Sequence[Optional[asyncio.Future]]: prev_length = len(task.writes) # delegate to the underlying writer task.config[CONF][CONFIG_KEY_SEND](writes) - for idx, w in enumerate(task.writes): - # find the index for the newly inserted writes - if idx < prev_length: - continue - assert writes[idx - prev_length] is w + # confirm no other concurrent writes were added + # TODO could use a lock here instead, if writes can come from many threads + assert len(task.writes) == prev_length + len(writes) + rtn: dict[int, Optional[asyncio.Future]] = {} + for idx, w in enumerate(writes, start=prev_length): # bail if not a PUSH write if w[0] != PUSH: continue # schedule the next task, if the callback returns one - if next_task := self.schedule_task(task, idx): + if next_task := self.schedule_task( + task, + idx, + calls[idx] if calls is not None else None, + ): # if the parent task was retried, # the next task might already be running if any( @@ -194,21 +217,29 @@ class PregelRunner: ): continue # schedule the next task - futures[ - cast( - asyncio.Future, - self.submit( - arun_with_retry, - next_task, - retry_policy, - stream=self.use_astream, - writer=writer, - __name__=t.name, - __cancel_on_exit__=True, - __reraise_on_exit__=reraise, - ), - ) - ] = next_task + fut = self.submit( + arun_with_retry, + next_task, + retry_policy, + stream=self.use_astream, + configurable={ + CONFIG_KEY_SEND: partial(writer, next_task), + CONFIG_KEY_CALL: partial(call, next_task), + }, + __name__=t.name, + __cancel_on_exit__=True, + __reraise_on_exit__=reraise, + ) + futures[cast(asyncio.Future, fut)] = next_task + rtn[idx] = fut + return [rtn.get(i) for i in range(len(writes))] + + def call( + task, func: str | Callable[[Any], Union[Awaitable[Any], Any]], input: Any + ) -> asyncio.Future[Any]: + (fut,) = writer(task, [(PUSH, None)], calls=[Call(func, input)]) + assert fut is not None, "writer did not return a future for call" + return fut loop = asyncio.get_event_loop() tasks = tuple(tasks) @@ -220,7 +251,13 @@ class PregelRunner: t = tasks[0] try: await arun_with_retry( - t, retry_policy, stream=self.use_astream, writer=writer + t, + retry_policy, + stream=self.use_astream, + configurable={ + CONFIG_KEY_SEND: partial(writer, t), + CONFIG_KEY_CALL: partial(call, t), + }, ) self.commit(t, None) except Exception as exc: @@ -245,7 +282,10 @@ class PregelRunner: t, retry_policy, stream=self.use_astream, - writer=writer, + configurable={ + CONFIG_KEY_SEND: partial(writer, t), + CONFIG_KEY_CALL: partial(call, t), + }, __name__=t.name, __cancel_on_exit__=True, __reraise_on_exit__=reraise, diff --git a/libs/langgraph/langgraph/types.py b/libs/langgraph/langgraph/types.py index 67c7e53f8..b49b1c45e 100644 --- a/libs/langgraph/langgraph/types.py +++ b/libs/langgraph/langgraph/types.py @@ -1,9 +1,13 @@ +import asyncio +import concurrent +import concurrent.futures import dataclasses import sys from collections import deque from typing import ( TYPE_CHECKING, Any, + Awaitable, Callable, ClassVar, Generic, @@ -11,6 +15,7 @@ from typing import ( Literal, NamedTuple, Optional, + ParamSpec, Sequence, Type, TypedDict, @@ -363,3 +368,36 @@ def interrupt(value: Any) -> Any: ), ) ) + + +P = ParamSpec("P") +T = TypeVar("T") + + +def call( + func: str | Callable[P, T], *args: P.args, **kwargs: P.kwargs +) -> concurrent.futures.Future[T]: + from langgraph.constants import CONFIG_KEY_CALL + from langgraph.utils.config import get_configurable + + conf = get_configurable() + impl = conf[CONFIG_KEY_CALL] + fut = impl(func, *args, **kwargs) + if not isinstance(fut, concurrent.futures.Future): + raise RuntimeError("In an async context, use acall() instead of call()") + return fut + + +def acall( + func: str | Callable[P, Union[T, Awaitable[T]]], *args: P.args, **kwargs: P.kwargs +) -> asyncio.Future[T]: + from langgraph.constants import CONFIG_KEY_CALL + from langgraph.utils.config import get_configurable + + conf = get_configurable() + impl = conf[CONFIG_KEY_CALL] + fut = impl(func, *args, **kwargs) + if isinstance(fut, concurrent.futures.Future): + fut = asyncio.wrap_future(fut) + fut.cancel + return fut diff --git a/libs/langgraph/tests/test_pregel.py b/libs/langgraph/tests/test_pregel.py index f69d36ed3..120b3deac 100644 --- a/libs/langgraph/tests/test_pregel.py +++ b/libs/langgraph/tests/test_pregel.py @@ -2496,7 +2496,7 @@ def test_send_react_interrupt( PregelTask( id=AnyStr(), name="foo", - path=("__pregel_push", ("__pregel_pull", "agent"), 2, AnyStr()), + path=("__pregel_push", ("__pregel_pull", "agent"), 2), error=None, interrupts=(), state=None, @@ -2653,7 +2653,7 @@ def test_send_react_interrupt( PregelTask( id=AnyStr(), name="foo", - path=("__pregel_push", ("__pregel_pull", "agent"), 2, AnyStr()), + path=("__pregel_push", ("__pregel_pull", "agent"), 2), error=None, interrupts=(), state=None, @@ -2740,7 +2740,7 @@ def test_send_react_interrupt( PregelTask( id=AnyStr(), name="foo", - path=("__pregel_push", (), 0, AnyStr()), + path=("__pregel_push", (), 0), error=None, interrupts=(), state=None, @@ -2965,7 +2965,7 @@ def test_send_react_interrupt_control( PregelTask( id=AnyStr(), name="foo", - path=("__pregel_push", ("__pregel_pull", "agent"), 2, AnyStr()), + path=("__pregel_push", ("__pregel_pull", "agent"), 2), error=None, interrupts=(), state=None, @@ -6043,9 +6043,7 @@ def test_state_graph_packets( ) }, ), - PregelTask( - AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 2, AnyStr()) - ), + PregelTask(AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 2)), ), next=("tools",), config=(app_w_interrupt.checkpointer.get_tuple(config)).config, @@ -6085,7 +6083,7 @@ def test_state_graph_packets( ), ] }, - tasks=(PregelTask(AnyStr(), "tools", (PUSH, (), 0, AnyStr())),), + tasks=(PregelTask(AnyStr(), "tools", (PUSH, (), 0)),), next=("tools",), config=app_w_interrupt.checkpointer.get_tuple(config).config, created_at=(app_w_interrupt.checkpointer.get_tuple(config)).checkpoint["ts"], @@ -6214,12 +6212,8 @@ def test_state_graph_packets( ) }, ), - PregelTask( - AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 2, AnyStr()) - ), - PregelTask( - AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 3, AnyStr()) - ), + PregelTask(AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 2)), + PregelTask(AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 3)), ), next=("tools", "tools"), config=app_w_interrupt.checkpointer.get_tuple(config).config, @@ -6366,9 +6360,7 @@ def test_state_graph_packets( ) }, ), - PregelTask( - AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 2, AnyStr()) - ), + PregelTask(AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 2)), ), next=("tools",), config=(app_w_interrupt.checkpointer.get_tuple(config)).config, @@ -6408,7 +6400,7 @@ def test_state_graph_packets( ), ] }, - tasks=(PregelTask(AnyStr(), "tools", (PUSH, (), 0, AnyStr())),), + tasks=(PregelTask(AnyStr(), "tools", (PUSH, (), 0)),), next=("tools",), config=app_w_interrupt.checkpointer.get_tuple(config).config, created_at=(app_w_interrupt.checkpointer.get_tuple(config)).checkpoint["ts"], @@ -6537,12 +6529,8 @@ def test_state_graph_packets( ) }, ), - PregelTask( - AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 2, AnyStr()) - ), - PregelTask( - AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 3, AnyStr()) - ), + PregelTask(AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 2)), + PregelTask(AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 3)), ), next=("tools", "tools"), config=app_w_interrupt.checkpointer.get_tuple(config).config, @@ -12786,7 +12774,7 @@ def test_send_to_nested_graphs( PregelTask( AnyStr(), "generate_joke", - (PUSH, ("__pregel_pull", "__start__"), 1, AnyStr()), + (PUSH, ("__pregel_pull", "__start__"), 1), state={ "configurable": { "thread_id": "1", @@ -12797,7 +12785,7 @@ def test_send_to_nested_graphs( PregelTask( AnyStr(), "generate_joke", - (PUSH, ("__pregel_pull", "__start__"), 2, AnyStr()), + (PUSH, ("__pregel_pull", "__start__"), 2), state={ "configurable": { "thread_id": "1", @@ -12850,7 +12838,7 @@ def test_send_to_nested_graphs( "checkpoint_ns": AnyStr("generate_joke:"), "langgraph_checkpoint_ns": AnyStr("generate_joke:"), "langgraph_node": "generate_joke", - "langgraph_path": [PUSH, ["__pregel_pull", "__start__"], 1, AnyStr()], + "langgraph_path": [PUSH, ["__pregel_pull", "__start__"], 1], "langgraph_step": 0, "langgraph_triggers": [PUSH], }, @@ -12895,7 +12883,7 @@ def test_send_to_nested_graphs( "checkpoint_ns": AnyStr("generate_joke:"), "langgraph_checkpoint_ns": AnyStr("generate_joke:"), "langgraph_node": "generate_joke", - "langgraph_path": [PUSH, ["__pregel_pull", "__start__"], 2, AnyStr()], + "langgraph_path": [PUSH, ["__pregel_pull", "__start__"], 2], "langgraph_step": 0, "langgraph_triggers": [PUSH], }, @@ -13021,7 +13009,7 @@ def test_send_to_nested_graphs( PregelTask( AnyStr(), "generate_joke", - (PUSH, ("__pregel_pull", "__start__"), 1, AnyStr()), + (PUSH, ("__pregel_pull", "__start__"), 1), state={ "configurable": { "thread_id": "1", @@ -13033,7 +13021,7 @@ def test_send_to_nested_graphs( PregelTask( AnyStr(), "generate_joke", - (PUSH, ("__pregel_pull", "__start__"), 2, AnyStr()), + (PUSH, ("__pregel_pull", "__start__"), 2), state={ "configurable": { "thread_id": "1", diff --git a/libs/langgraph/tests/test_pregel_async.py b/libs/langgraph/tests/test_pregel_async.py index 514703781..d8aeedd9a 100644 --- a/libs/langgraph/tests/test_pregel_async.py +++ b/libs/langgraph/tests/test_pregel_async.py @@ -2864,12 +2864,7 @@ async def test_send_dedupe_on_resume(checkpointer_name: str) -> None: PregelTask( id=AnyStr(), name="2", - path=( - "__pregel_push", - ("__pregel_pull", "1"), - 2, - AnyStr(), - ), + path=("__pregel_push", ("__pregel_pull", "1"), 2), error=None, interrupts=(), state=None, @@ -2878,12 +2873,7 @@ async def test_send_dedupe_on_resume(checkpointer_name: str) -> None: PregelTask( id=AnyStr(), name="2", - path=( - "__pregel_push", - ("__pregel_pull", "1"), - 3, - AnyStr(), - ), + path=("__pregel_push", ("__pregel_pull", "1"), 3), error=None, interrupts=(), state=None, @@ -2894,14 +2884,8 @@ async def test_send_dedupe_on_resume(checkpointer_name: str) -> None: name="2", path=( "__pregel_push", - ( - "__pregel_push", - ("__pregel_pull", "1"), - 2, - AnyStr(), - ), + ("__pregel_push", ("__pregel_pull", "1"), 2), 2, - AnyStr(), ), error=None, interrupts=(), @@ -2913,14 +2897,8 @@ async def test_send_dedupe_on_resume(checkpointer_name: str) -> None: name="flaky", path=( "__pregel_push", - ( - "__pregel_push", - ("__pregel_pull", "1"), - 3, - AnyStr(), - ), + ("__pregel_push", ("__pregel_pull", "1"), 3), 2, - AnyStr(), ), error=None, interrupts=(Interrupt(value="Bahh", when="during"),), @@ -3157,7 +3135,7 @@ async def test_send_react_interrupt(checkpointer_name: str) -> None: PregelTask( id=AnyStr(), name="foo", - path=("__pregel_push", ("__pregel_pull", "agent"), 2, AnyStr()), + path=("__pregel_push", ("__pregel_pull", "agent"), 2), error=None, interrupts=(), state=None, @@ -3314,7 +3292,7 @@ async def test_send_react_interrupt(checkpointer_name: str) -> None: PregelTask( id=AnyStr(), name="foo", - path=("__pregel_push", ("__pregel_pull", "agent"), 2, AnyStr()), + path=("__pregel_push", ("__pregel_pull", "agent"), 2), error=None, interrupts=(), state=None, @@ -3401,7 +3379,7 @@ async def test_send_react_interrupt(checkpointer_name: str) -> None: PregelTask( id=AnyStr(), name="foo", - path=("__pregel_push", (), 0, AnyStr()), + path=("__pregel_push", (), 0), error=None, interrupts=(), state=None, @@ -3625,7 +3603,7 @@ async def test_send_react_interrupt_control( PregelTask( id=AnyStr(), name="foo", - path=("__pregel_push", ("__pregel_pull", "agent"), 2, AnyStr()), + path=("__pregel_push", ("__pregel_pull", "agent"), 2), error=None, interrupts=(), state=None, @@ -6420,9 +6398,7 @@ async def test_state_graph_packets(checkpointer_name: str) -> None: ) }, ), - PregelTask( - AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 2, AnyStr()) - ), + PregelTask(AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 2)), ), next=("tools",), config=(await app_w_interrupt.checkpointer.aget_tuple(config)).config, @@ -6465,7 +6441,7 @@ async def test_state_graph_packets(checkpointer_name: str) -> None: ), ] }, - tasks=(PregelTask(AnyStr(), "tools", (PUSH, (), 0, AnyStr())),), + tasks=(PregelTask(AnyStr(), "tools", (PUSH, (), 0)),), next=("tools",), config=tup.config, created_at=tup.checkpoint["ts"], @@ -6596,12 +6572,8 @@ async def test_state_graph_packets(checkpointer_name: str) -> None: ) }, ), - PregelTask( - AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 2, AnyStr()) - ), - PregelTask( - AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 3, AnyStr()) - ), + PregelTask(AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 2)), + PregelTask(AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 3)), ), next=("tools", "tools"), config=tup.config, @@ -6751,9 +6723,7 @@ async def test_state_graph_packets(checkpointer_name: str) -> None: ) }, ), - PregelTask( - AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 2, AnyStr()) - ), + PregelTask(AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 2)), ), next=("tools",), config=(await app_w_interrupt.checkpointer.aget_tuple(config)).config, @@ -6796,7 +6766,7 @@ async def test_state_graph_packets(checkpointer_name: str) -> None: ), ] }, - tasks=(PregelTask(AnyStr(), "tools", (PUSH, (), 0, AnyStr())),), + tasks=(PregelTask(AnyStr(), "tools", (PUSH, (), 0)),), next=("tools",), config=tup.config, created_at=tup.checkpoint["ts"], @@ -6929,12 +6899,8 @@ async def test_state_graph_packets(checkpointer_name: str) -> None: ) }, ), - PregelTask( - AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 2, AnyStr()) - ), - PregelTask( - AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 3, AnyStr()) - ), + PregelTask(AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 2)), + PregelTask(AnyStr(), "tools", (PUSH, ("__pregel_pull", "agent"), 3)), ), next=("tools", "tools"), config=tup.config, @@ -11612,7 +11578,7 @@ async def test_send_to_nested_graphs(checkpointer_name: str) -> None: PregelTask( AnyStr(), "generate_joke", - (PUSH, ("__pregel_pull", "__start__"), 1, AnyStr()), + (PUSH, ("__pregel_pull", "__start__"), 1), state={ "configurable": { "thread_id": "1", @@ -11623,7 +11589,7 @@ async def test_send_to_nested_graphs(checkpointer_name: str) -> None: PregelTask( AnyStr(), "generate_joke", - (PUSH, ("__pregel_pull", "__start__"), 2, AnyStr()), + (PUSH, ("__pregel_pull", "__start__"), 2), state={ "configurable": { "thread_id": "1", @@ -11764,7 +11730,7 @@ async def test_send_to_nested_graphs(checkpointer_name: str) -> None: PregelTask( AnyStr(), "generate_joke", - (PUSH, ("__pregel_pull", "__start__"), 1, AnyStr()), + (PUSH, ("__pregel_pull", "__start__"), 1), state={ "configurable": { "thread_id": "1", @@ -11776,7 +11742,7 @@ async def test_send_to_nested_graphs(checkpointer_name: str) -> None: PregelTask( AnyStr(), "generate_joke", - (PUSH, ("__pregel_pull", "__start__"), 2, AnyStr()), + (PUSH, ("__pregel_pull", "__start__"), 2), state={ "configurable": { "thread_id": "1", From 0461d45d76d4af9f1bd214a8b77792d88e59fa2b Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Fri, 8 Nov 2024 16:33:07 -0800 Subject: [PATCH 04/58] Finish impl --- libs/langgraph/langgraph/pregel/algo.py | 107 +++++++++++++++++--- libs/langgraph/langgraph/pregel/call.py | 113 ++++++++++++++++++++++ libs/langgraph/langgraph/pregel/retry.py | 10 +- libs/langgraph/langgraph/pregel/runner.py | 52 ++++++---- 4 files changed, 241 insertions(+), 41 deletions(-) create mode 100644 libs/langgraph/langgraph/pregel/call.py diff --git a/libs/langgraph/langgraph/pregel/algo.py b/libs/langgraph/langgraph/pregel/algo.py index a8d39674c..c95c699c8 100644 --- a/libs/langgraph/langgraph/pregel/algo.py +++ b/libs/langgraph/langgraph/pregel/algo.py @@ -58,6 +58,7 @@ from langgraph.constants import ( ) from langgraph.errors import EmptyChannelError, InvalidUpdateError from langgraph.managed.base import ManagedValueMapping +from langgraph.pregel.call import get_runnable_for_func from langgraph.pregel.io import read_channel, read_channels from langgraph.pregel.log import logger from langgraph.pregel.manager import ChannelsManager @@ -98,9 +99,15 @@ class PregelTaskWrites(NamedTuple): class Call: + __slots__ = ("func", "input") + func: str | Callable input: Any + def __init__(self, func: str | Callable, input: Any) -> None: + self.func = func + self.input = input + def should_interrupt( checkpoint: Checkpoint, @@ -184,7 +191,7 @@ def local_write( """Function injected under CONFIG_KEY_SEND in task config, to write to channels. Validates writes and forwards them to `commit` function.""" for chan, value in writes: - if chan in (PUSH, TASKS): + if chan in (PUSH, TASKS) and value is not None: if not isinstance(value, Send): raise InvalidUpdateError(f"Expected Send, got {value}") if value.node not in process_keys: @@ -464,7 +471,87 @@ def prepare_single_task( configurable = config.get(CONF, {}) parent_ns = configurable.get(CONFIG_KEY_CHECKPOINT_NS, "") - if task_path[0] == PUSH: + if task_path[0] == PUSH and isinstance(task_path[-1], Call): + # (PUSH, parent task path, idx of PUSH write, id of parent task, Call) + task_path_t = cast(tuple[str, tuple, int, str, Optional[Call]], task_path) + call = task_path_t[-1] + proc = get_runnable_for_func(call.func) + name = proc.name + if name is None: + raise ValueError("`call` functions must have a `__name__` attribute") + # create task id + triggers = [PUSH] + checkpoint_ns = f"{parent_ns}{NS_SEP}{name}" if parent_ns else name + task_id = _uuid5_str( + checkpoint_id, + checkpoint_ns, + str(step), + name, + PUSH, + _tuple_str(task_path[1]), + str(task_path[2]), + ) + task_checkpoint_ns = f"{checkpoint_ns}:{task_id}" + metadata = { + "langgraph_step": step, + "langgraph_node": name, + "langgraph_triggers": triggers, + "langgraph_path": task_path[:3], + "langgraph_checkpoint_ns": task_checkpoint_ns, + } + if task_id_checksum is not None: + assert task_id == task_id_checksum, f"{task_id} != {task_id_checksum}" + if for_execution: + writes: deque[tuple[str, Any]] = deque() + return PregelExecutableTask( + name, + call.input, + proc, + writes, + patch_config( + merge_configs(config, {"metadata": metadata, "tags": proc.tags}), + run_name=name, + callbacks=( + manager.get_child(f"graph:step:{step}") if manager else None + ), + configurable={ + CONFIG_KEY_TASK_ID: task_id, + # deque.extend is thread-safe + CONFIG_KEY_SEND: partial( + local_write, + writes.extend, + processes.keys(), + ), + CONFIG_KEY_READ: partial( + local_read, + step, + checkpoint, + channels, + managed, + PregelTaskWrites(task_path[:3], name, writes, triggers), + config, + ), + CONFIG_KEY_STORE: (store or configurable.get(CONFIG_KEY_STORE)), + CONFIG_KEY_CHECKPOINTER: ( + checkpointer or configurable.get(CONFIG_KEY_CHECKPOINTER) + ), + CONFIG_KEY_CHECKPOINT_MAP: { + **configurable.get(CONFIG_KEY_CHECKPOINT_MAP, {}), + parent_ns: checkpoint["id"], + }, + CONFIG_KEY_CHECKPOINT_ID: None, + CONFIG_KEY_CHECKPOINT_NS: task_checkpoint_ns, + }, + ), + triggers, + None, + None, + task_id, + task_path[:3], + ) + else: + return PregelTask(task_id, name, task_path[:3]) + elif task_path[0] == PUSH: if len(task_path) == 2: # TODO: remove branch in 1.0 # legacy SEND tasks, executed in superstep n+1 # (PUSH, idx of pending send) @@ -498,13 +585,7 @@ def prepare_single_task( elif len(task_path) >= 4: # new PUSH tasks, executed in superstep n # (PUSH, parent task path, idx of PUSH write, id of parent task) - task_path_t = cast( - Union[ - tuple[str, tuple, int, str], - tuple[str, tuple, int, str, Optional[Call]], - ], - task_path, - ) + task_path_t = cast(tuple[str, tuple, int, str], task_path) writes_for_path = [w for w in pending_writes if w[0] == task_path_t[3]] if task_path_t[2] >= len(writes_for_path): logger.warning( @@ -513,12 +594,7 @@ def prepare_single_task( return packet = writes_for_path[task_path_t[2]][2] if packet is None: - if len(task_path_t) == 5: - packet = task_path_t[4] - else: - # no packet to replay, this is a "call" task - return - # TODO handle Call packets + return if not isinstance(packet, Send): logger.warning( f"Ignoring invalid packet type {type(packet)} in pending writes" @@ -623,7 +699,6 @@ def prepare_single_task( task_path[:3], writers=proc.flat_writers, ) - else: return PregelTask(task_id, packet.node, task_path[:3]) elif task_path[0] == PULL: diff --git a/libs/langgraph/langgraph/pregel/call.py b/libs/langgraph/langgraph/pregel/call.py new file mode 100644 index 000000000..8932697b1 --- /dev/null +++ b/libs/langgraph/langgraph/pregel/call.py @@ -0,0 +1,113 @@ +import sys +import types + +from langgraph.utils.runnable import RunnableCallable + +""" +Utilities borrowed from cloudpickle. +https://github.com/cloudpipe/cloudpickle/blob/6220b0ce83ffee5e47e06770a1ee38ca9e47c850/cloudpickle/cloudpickle.py#L265 +""" + + +def _getattribute(obj, name): + for subpath in name.split("."): + if subpath == "": + raise AttributeError( + "Can't get local attribute {!r} on {!r}".format(name, obj) + ) + try: + parent = obj + obj = getattr(obj, subpath) + except AttributeError: + raise AttributeError( + "Can't get attribute {!r} on {!r}".format(name, obj) + ) from None + return obj, parent + + +def _whichmodule(obj, name): + """Find the module an object belongs to. + + This function differs from ``pickle.whichmodule`` in two ways: + - it does not mangle the cases where obj's module is __main__ and obj was + not found in any module. + - Errors arising during module introspection are ignored, as those errors + are considered unwanted side effects. + """ + module_name = getattr(obj, "__module__", None) + + if module_name is not None: + return module_name + # Protect the iteration by using a copy of sys.modules against dynamic + # modules that trigger imports of other modules upon calls to getattr or + # other threads importing at the same time. + for module_name, module in sys.modules.copy().items(): + # Some modules such as coverage can inject non-module objects inside + # sys.modules + if ( + module_name == "__main__" + or module_name == "__mp_main__" + or module is None + or not isinstance(module, types.ModuleType) + ): + continue + try: + if _getattribute(module, name)[0] is obj: + return module_name + except Exception: + pass + return None + + +def _lookup_module_and_qualname(obj, name=None): + if name is None: + name = getattr(obj, "__qualname__", None) + if name is None: # pragma: no cover + # This used to be needed for Python 2.7 support but is probably not + # needed anymore. However we keep the __name__ introspection in case + # users of cloudpickle rely on this old behavior for unknown reasons. + name = getattr(obj, "__name__", None) + + module_name = _whichmodule(obj, name) + + if module_name is None: + # In this case, obj.__module__ is None AND obj was not found in any + # imported module. obj is thus treated as dynamic. + return None + + if module_name == "__main__": + return None + + # Note: if module_name is in sys.modules, the corresponding module is + # assumed importable at unpickling time. See #357 + module = sys.modules.get(module_name, None) + if module is None: + # The main reason why obj's module would not be imported is that this + # module has been dynamically created, using for example + # types.ModuleType. The other possibility is that module was removed + # from sys.modules after obj was created/imported. But this case is not + # supported, as the standard pickle does not support it either. + return None + + try: + obj2, parent = _getattribute(module, name) + except AttributeError: + # obj was not found inside the module it points to + return None + if obj2 is not obj: + return None + return module, name + + +def get_runnable_for_func( + func: types.FunctionType, +) -> RunnableCallable: + if func in CACHE: + return CACHE[func] + elif not _lookup_module_and_qualname(func): + return RunnableCallable(func) + else: + return CACHE.setdefault(func, RunnableCallable(func)) + + +CACHE: dict[types.FunctionType, RunnableCallable] = {} diff --git a/libs/langgraph/langgraph/pregel/retry.py b/libs/langgraph/langgraph/pregel/retry.py index 093859579..29faaab21 100644 --- a/libs/langgraph/langgraph/pregel/retry.py +++ b/libs/langgraph/langgraph/pregel/retry.py @@ -37,9 +37,7 @@ def run_with_retry( # clear any writes from previous attempts task.writes.clear() # run the task - task.proc.invoke(task.input, config) - # if successful, end - break + return task.proc.invoke(task.input, config) except ParentCommand as exc: ns: str = config[CONF][CONFIG_KEY_CHECKPOINT_NS] cmd = exc.args[0] @@ -128,10 +126,10 @@ async def arun_with_retry( if stream: async for _ in task.proc.astream(task.input, config): pass + # if successful, end + break else: - await task.proc.ainvoke(task.input, config) - # if successful, end - break + return await task.proc.ainvoke(task.input, config) except ParentCommand as exc: ns: str = config[CONF][CONFIG_KEY_CHECKPOINT_NS] cmd = exc.args[0] diff --git a/libs/langgraph/langgraph/pregel/runner.py b/libs/langgraph/langgraph/pregel/runner.py index 067394bdb..6155ce74e 100644 --- a/libs/langgraph/langgraph/pregel/runner.py +++ b/libs/langgraph/langgraph/pregel/runner.py @@ -66,20 +66,26 @@ class PregelRunner: get_waiter: Optional[Callable[[], concurrent.futures.Future[None]]] = None, ) -> Iterator[None]: def writer( - task: PregelExecutableTask, writes: Sequence[tuple[str, Any]] - ) -> None: + task: PregelExecutableTask, + writes: Sequence[tuple[str, Any]], + *, + calls: Optional[Sequence[Call]] = None, + ) -> Sequence[Optional[concurrent.futures.Future]]: prev_length = len(task.writes) # delegate to the underlying writer task.config[CONF][CONFIG_KEY_SEND](writes) # confirm no other concurrent writes were added # TODO could use a lock here instead, if writes can come from many threads assert len(task.writes) == prev_length + len(writes) + rtn: dict[int, Optional[concurrent.futures.Future]] = {} for idx, w in enumerate(writes, start=prev_length): # bail if not a PUSH write if w[0] != PUSH: continue # schedule the next task, if the callback returns one - if next_task := self.schedule_task(task, idx): + if next_task := self.schedule_task( + task, idx, calls[idx - prev_length] if calls else None + ): # if the parent task was retried, # the next task might already be running if any( @@ -87,18 +93,26 @@ class PregelRunner: ): continue # schedule the next task - futures[ - self.submit( - run_with_retry, - next_task, - retry_policy, - configurable={ - CONFIG_KEY_SEND: partial(writer, next_task), - # CONFIG_KEY_CALL: partial(call, next_task), - }, - __reraise_on_exit__=reraise, - ) - ] = next_task + fut = self.submit( + run_with_retry, + next_task, + retry_policy, + configurable={ + CONFIG_KEY_SEND: partial(writer, next_task), + CONFIG_KEY_CALL: partial(call, next_task), + }, + __reraise_on_exit__=reraise, + ) + futures[fut] = next_task + rtn[idx - prev_length] = fut + return [rtn.get(i) for i in range(len(writes))] + + def call( + task, func: str | Callable[[Any], Union[Awaitable[Any], Any]], input: Any + ) -> concurrent.futures.Future[Any]: + (fut,) = writer(task, [(PUSH, None)], calls=[Call(func, input)]) + assert fut is not None, "writer did not return a future for call" + return fut tasks = tuple(tasks) futures: dict[concurrent.futures.Future, Optional[PregelExecutableTask]] = {} @@ -113,7 +127,7 @@ class PregelRunner: retry_policy, configurable={ CONFIG_KEY_SEND: partial(writer, t), - # CONFIG_KEY_CALL: partial(call, t), + CONFIG_KEY_CALL: partial(call, t), }, ) self.commit(t, None) @@ -138,7 +152,7 @@ class PregelRunner: retry_policy, configurable={ CONFIG_KEY_SEND: partial(writer, t), - # CONFIG_KEY_CALL: partial(call, t), + CONFIG_KEY_CALL: partial(call, t), }, __reraise_on_exit__=reraise, ) @@ -208,7 +222,7 @@ class PregelRunner: if next_task := self.schedule_task( task, idx, - calls[idx] if calls is not None else None, + calls[idx - prev_length] if calls is not None else None, ): # if the parent task was retried, # the next task might already be running @@ -231,7 +245,7 @@ class PregelRunner: __reraise_on_exit__=reraise, ) futures[cast(asyncio.Future, fut)] = next_task - rtn[idx] = fut + rtn[idx - prev_length] = fut return [rtn.get(i) for i in range(len(writes))] def call( From 01a3c23a2901d06854d2cf9171452a174c0ce417 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Mon, 11 Nov 2024 10:05:34 -0800 Subject: [PATCH 05/58] WIP --- libs/langgraph/langgraph/func/__init__.py | 85 +++++++++++++++++++++++ libs/langgraph/tests/test_pregel.py | 24 +++++++ 2 files changed, 109 insertions(+) create mode 100644 libs/langgraph/langgraph/func/__init__.py diff --git a/libs/langgraph/langgraph/func/__init__.py b/libs/langgraph/langgraph/func/__init__.py new file mode 100644 index 000000000..66acba23c --- /dev/null +++ b/libs/langgraph/langgraph/func/__init__.py @@ -0,0 +1,85 @@ +import asyncio +import concurrent +import concurrent.futures +import types +from functools import partial, update_wrapper +from typing import ( + Any, + Awaitable, + Callable, + Coroutine, + Optional, + ParamSpec, + TypeVar, + Union, + overload, +) + +from langgraph.channels.ephemeral_value import EphemeralValue +from langgraph.channels.last_value import LastValue +from langgraph.checkpoint.base import BaseCheckpointSaver +from langgraph.constants import END, START, TAG_HIDDEN +from langgraph.pregel import Pregel +from langgraph.pregel.call import get_runnable_for_func +from langgraph.pregel.read import PregelNode +from langgraph.pregel.write import ChannelWrite, ChannelWriteEntry +from langgraph.store.base import BaseStore +from langgraph.types import RetryPolicy, acall, call + +P = ParamSpec("P") +T = TypeVar("T") + + +@overload +def task( + *, retry: Optional[RetryPolicy] = None +) -> Callable[ + [Callable[P, Coroutine[None, None, T]]], Callable[P, asyncio.Future[T]] +]: ... + + +@overload +def task( + *, retry: Optional[RetryPolicy] = None +) -> Callable[[Callable[P, T]], Callable[P, concurrent.futures.Future[T]]]: ... + + +def task( + *, retry: Optional[RetryPolicy] = None +) -> Callable[ + [Callable[P, Union[T, Awaitable[T]]]], + Callable[P, Union[concurrent.futures.Future[T], asyncio.Future[T]]], +]: + def _task(func: Callable[P, T]) -> Callable[P, concurrent.futures.Future[T]]: + if asyncio.iscoroutinefunction(func): + return update_wrapper(partial(acall, func), func) + else: + return update_wrapper(partial(call, func), func) + + return _task + + +def imp( + *, + checkpointer: Optional[BaseCheckpointSaver] = None, + store: Optional[BaseStore] = None, +) -> Callable[[types.FunctionType], Pregel]: + def _imp(func: types.FunctionType): + return Pregel( + nodes={ + func.__name__: PregelNode( + bound=get_runnable_for_func(func), + triggers=[START], + channels=[START], + writers=[ChannelWrite([ChannelWriteEntry(END)], tags=[TAG_HIDDEN])], + ) + }, + channels={START: EphemeralValue(Any, START), END: LastValue(Any, END)}, + input_channels=START, + output_channels=END, + stream_mode="updates", + checkpointer=checkpointer, + store=store, + ) + + return _imp diff --git a/libs/langgraph/tests/test_pregel.py b/libs/langgraph/tests/test_pregel.py index 120b3deac..356ecbadf 100644 --- a/libs/langgraph/tests/test_pregel.py +++ b/libs/langgraph/tests/test_pregel.py @@ -65,6 +65,7 @@ from langgraph.constants import ( START, ) from langgraph.errors import InvalidUpdateError, MultipleSubgraphsError, NodeInterrupt +from langgraph.func import imp, task from langgraph.graph import END, Graph, StateGraph from langgraph.graph.message import MessageGraph, MessagesState, add_messages from langgraph.managed.shared_value import SharedValue @@ -1969,6 +1970,29 @@ def test_send_sequences() -> None: ) +@pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_SYNC) +def test_imp_task(request: pytest.FixtureRequest, checkpointer_name: str) -> None: + checkpointer = request.getfixturevalue(f"checkpointer_{checkpointer_name}") + + @task() + def mapper(input: str) -> str: + print(f"mapper {input}") + return input * 2 + + @imp(checkpointer=checkpointer) + def graph(input: list[str]) -> list[str]: + futures = [mapper(i) for i in input] + mapped = [f.result() for f in futures] + # answer = interrupt("question") + # TODO raises NodeInterrupt if no answer provided yet + # returns answer (saved in writes?) if provided + # what is the API for passing the answer? + return mapped + + thread1 = {"configurable": {"thread_id": "1"}} + assert graph.invoke(["0", "1"], thread1) == ["00", "11"] + + @pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_SYNC) def test_send_dedupe_on_resume( request: pytest.FixtureRequest, checkpointer_name: str From 872f54adf1df688ab3ed90a6bdfbe15ea6d09061 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Thu, 14 Nov 2024 17:05:39 -0800 Subject: [PATCH 06/58] Get it working with interrupt (sync) --- libs/langgraph/langgraph/constants.py | 2 + libs/langgraph/langgraph/pregel/algo.py | 5 +- libs/langgraph/langgraph/pregel/call.py | 21 ++++++-- libs/langgraph/langgraph/pregel/io.py | 30 +++++------ libs/langgraph/langgraph/pregel/loop.py | 5 +- libs/langgraph/langgraph/pregel/runner.py | 62 ++++++++++++++++------- libs/langgraph/tests/test_pregel.py | 34 ++++++++++--- 7 files changed, 110 insertions(+), 49 deletions(-) diff --git a/libs/langgraph/langgraph/constants.py b/libs/langgraph/langgraph/constants.py index b9d6f37f7..cd847f9be 100644 --- a/libs/langgraph/langgraph/constants.py +++ b/libs/langgraph/langgraph/constants.py @@ -40,6 +40,8 @@ SCHEDULED = sys.intern("__scheduled__") # marker to signal node was scheduled (in distributed mode) TASKS = sys.intern("__pregel_tasks") # for Send objects returned by nodes/edges, corresponds to PUSH below +RETURN = sys.intern("__return__") +# for writes of a task where we simply record the return value # --- Reserved config.configurable keys --- CONFIG_KEY_SEND = sys.intern("__pregel_send") diff --git a/libs/langgraph/langgraph/pregel/algo.py b/libs/langgraph/langgraph/pregel/algo.py index c95c699c8..78242a9ac 100644 --- a/libs/langgraph/langgraph/pregel/algo.py +++ b/libs/langgraph/langgraph/pregel/algo.py @@ -52,6 +52,7 @@ from langgraph.constants import ( PUSH, RESERVED, RESUME, + RETURN, TAG_HIDDEN, TASKS, Send, @@ -259,7 +260,7 @@ def apply_writes( pending_writes_by_managed: dict[str, list[Any]] = defaultdict(list) for task in tasks: for chan, val in task.writes: - if chan in (NO_WRITES, PUSH, RESUME, INTERRUPT): + if chan in (NO_WRITES, PUSH, RESUME, INTERRUPT, RETURN): pass elif chan == TASKS: # TODO: remove branch in 1.0 checkpoint["pending_sends"].append(val) @@ -509,7 +510,7 @@ def prepare_single_task( proc, writes, patch_config( - merge_configs(config, {"metadata": metadata, "tags": proc.tags}), + merge_configs(config, {"metadata": metadata}), run_name=name, callbacks=( manager.get_child(f"graph:step:{step}") if manager else None diff --git a/libs/langgraph/langgraph/pregel/call.py b/libs/langgraph/langgraph/pregel/call.py index 8932697b1..6d218f702 100644 --- a/libs/langgraph/langgraph/pregel/call.py +++ b/libs/langgraph/langgraph/pregel/call.py @@ -1,7 +1,9 @@ import sys import types -from langgraph.utils.runnable import RunnableCallable +from langgraph.constants import RETURN +from langgraph.pregel.write import ChannelWrite, ChannelWriteEntry +from langgraph.utils.runnable import RunnableCallable, RunnableSeq """ Utilities borrowed from cloudpickle. @@ -101,13 +103,24 @@ def _lookup_module_and_qualname(obj, name=None): def get_runnable_for_func( func: types.FunctionType, -) -> RunnableCallable: +) -> RunnableSeq: if func in CACHE: return CACHE[func] elif not _lookup_module_and_qualname(func): - return RunnableCallable(func) + return RunnableSeq( + RunnableCallable(func, trace=False), + ChannelWrite([ChannelWriteEntry(RETURN)]), + name=func.__name__, + ) else: - return CACHE.setdefault(func, RunnableCallable(func)) + return CACHE.setdefault( + func, + RunnableSeq( + RunnableCallable(func, trace=False), + ChannelWrite([ChannelWriteEntry(RETURN)]), + name=func.__name__, + ), + ) CACHE: dict[types.FunctionType, RunnableCallable] = {} diff --git a/libs/langgraph/langgraph/pregel/io.py b/libs/langgraph/langgraph/pregel/io.py index b2596d3ad..df841ffd5 100644 --- a/libs/langgraph/langgraph/pregel/io.py +++ b/libs/langgraph/langgraph/pregel/io.py @@ -13,6 +13,7 @@ from langgraph.constants import ( NULL_TASK_ID, PUSH, RESUME, + RETURN, TAG_HIDDEN, TASKS, ) @@ -171,22 +172,21 @@ def map_output_updates( ] if not output_tasks: return - if isinstance(output_channels, str): - updated = ( - (task.name, value) - for task, writes in output_tasks - for chan, value in writes - if chan == output_channels - ) - else: - updated = ( - ( - task.name, - {chan: value for chan, value in writes if chan in output_channels}, + updated: list[tuple[str, Any]] = [] + for task, writes in output_tasks: + if rtn := next((value for chan, value in writes if chan == RETURN), None): + updated.append((task.name, rtn)) + elif isinstance(output_channels, str): + updated.extend( + (task.name, value) for chan, value in writes if chan == output_channels + ) + elif any(chan in output_channels for chan, _ in writes): + updated.append( + ( + task.name, + {chan: value for chan, value in writes if chan in output_channels}, + ) ) - for task, writes in output_tasks - if any(chan in output_channels for chan, _ in writes) - ) grouped: dict[str, list[Any]] = {t.name: [] for t, _ in output_tasks} for node, value in updated: grouped[node].append(value) diff --git a/libs/langgraph/langgraph/pregel/loop.py b/libs/langgraph/langgraph/pregel/loop.py index 31397d22b..cb141c4a1 100644 --- a/libs/langgraph/langgraph/pregel/loop.py +++ b/libs/langgraph/langgraph/pregel/loop.py @@ -347,9 +347,8 @@ class PregelLoop(LoopProtocol): # match any pending writes to the new task if self.skip_done_tasks: self._match_writes({pushed.id: pushed}) - # return the new task, to be started, if not run before - if not pushed.writes: - return pushed + # return the new task, to be started if not run before + return pushed def tick( self, diff --git a/libs/langgraph/langgraph/pregel/runner.py b/libs/langgraph/langgraph/pregel/runner.py index 6155ce74e..3dec1d84c 100644 --- a/libs/langgraph/langgraph/pregel/runner.py +++ b/libs/langgraph/langgraph/pregel/runner.py @@ -25,6 +25,7 @@ from langgraph.constants import ( NO_WRITES, PUSH, RESUME, + RETURN, TAG_HIDDEN, ) from langgraph.errors import GraphBubbleUp, GraphInterrupt @@ -88,23 +89,42 @@ class PregelRunner: ): # if the parent task was retried, # the next task might already be running - if any( - t == next_task.id for t in futures.values() if t is not None + if fut := next( + ( + f + for f, t in futures.items() + if t is not None and t == next_task.id + ), + None, ): - continue - # schedule the next task - fut = self.submit( - run_with_retry, - next_task, - retry_policy, - configurable={ - CONFIG_KEY_SEND: partial(writer, next_task), - CONFIG_KEY_CALL: partial(call, next_task), - }, - __reraise_on_exit__=reraise, - ) - futures[fut] = next_task - rtn[idx - prev_length] = fut + rtn[idx - prev_length] = fut + elif next_task.writes: + fut = concurrent.futures.Future() + if val := next(v for c, v in next_task.writes if c == RETURN): + fut.set_result(val) + elif exc := next(v for c, v in next_task.writes if c == ERROR): + fut.set_exception( + exc + if isinstance(exc, BaseException) + else Exception(exc) + ) + else: + fut.set_result(None) + rtn[idx - prev_length] = fut + else: + # schedule the next task + fut = self.submit( + run_with_retry, + next_task, + retry_policy, + configurable={ + CONFIG_KEY_SEND: partial(writer, next_task), + CONFIG_KEY_CALL: partial(call, next_task), + }, + __reraise_on_exit__=reraise, + ) + futures[fut] = next_task + rtn[idx - prev_length] = fut return [rtn.get(i) for i in range(len(writes))] def call( @@ -116,6 +136,7 @@ class PregelRunner: tasks = tuple(tasks) futures: dict[concurrent.futures.Future, Optional[PregelExecutableTask]] = {} + done_futures: set[concurrent.futures.Future] = set() # give control back to the caller yield # fast path if single task with no timeout and no waiter @@ -133,7 +154,12 @@ class PregelRunner: self.commit(t, None) except Exception as exc: self.commit(t, exc) - if reraise: + if reraise and futures: + # will be re-raised after futures are done + fut = concurrent.futures.Future() + fut.set_exception(exc) + done_futures.add(fut) + elif reraise: raise if not futures: # maybe `t` schuduled another task return @@ -157,7 +183,6 @@ class PregelRunner: __reraise_on_exit__=reraise, ) ] = t - done_futures: set[concurrent.futures.Future] = set() end_time = timeout + time.monotonic() if timeout else None while len(futures) > (1 if get_waiter is not None else 0): done, inflight = concurrent.futures.wait( @@ -183,6 +208,7 @@ class PregelRunner: del fut, task # maybe stop other tasks if _should_stop_others(done): + print("stopping others") break # give control back to the caller yield diff --git a/libs/langgraph/tests/test_pregel.py b/libs/langgraph/tests/test_pregel.py index 356ecbadf..49ee6bec5 100644 --- a/libs/langgraph/tests/test_pregel.py +++ b/libs/langgraph/tests/test_pregel.py @@ -1973,24 +1973,44 @@ def test_send_sequences() -> None: @pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_SYNC) def test_imp_task(request: pytest.FixtureRequest, checkpointer_name: str) -> None: checkpointer = request.getfixturevalue(f"checkpointer_{checkpointer_name}") + mapper_calls = 0 @task() def mapper(input: str) -> str: - print(f"mapper {input}") + nonlocal mapper_calls + mapper_calls += 1 return input * 2 @imp(checkpointer=checkpointer) def graph(input: list[str]) -> list[str]: futures = [mapper(i) for i in input] mapped = [f.result() for f in futures] - # answer = interrupt("question") - # TODO raises NodeInterrupt if no answer provided yet - # returns answer (saved in writes?) if provided - # what is the API for passing the answer? - return mapped + answer = interrupt("question") + return [m + answer for m in mapped] thread1 = {"configurable": {"thread_id": "1"}} - assert graph.invoke(["0", "1"], thread1) == ["00", "11"] + assert [*graph.stream(["0", "1"], thread1)] == [ + # TODO make test not depend on order of execution (which is not guaranteed) + {"mapper": "00"}, + {"mapper": "11"}, + { + "__interrupt__": ( + Interrupt( + value="question", + resumable=True, + ns=[AnyStr("graph:")], + when="during", + ), + ) + }, + ] + assert mapper_calls == 2 + + assert graph.invoke(Command(resume="answer"), thread1) == [ + "00answer", + "11answer", + ] + assert mapper_calls == 2 @pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_SYNC) From 76a209835f81c3521f790130d2401bc7a0aad787 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Thu, 14 Nov 2024 17:52:17 -0800 Subject: [PATCH 07/58] Comments --- libs/langgraph/langgraph/pregel/runner.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/langgraph/langgraph/pregel/runner.py b/libs/langgraph/langgraph/pregel/runner.py index 3dec1d84c..a21c3465e 100644 --- a/libs/langgraph/langgraph/pregel/runner.py +++ b/libs/langgraph/langgraph/pregel/runner.py @@ -87,8 +87,6 @@ class PregelRunner: if next_task := self.schedule_task( task, idx, calls[idx - prev_length] if calls else None ): - # if the parent task was retried, - # the next task might already be running if fut := next( ( f @@ -97,8 +95,12 @@ class PregelRunner: ), None, ): + # if the parent task was retried, + # the next task might already be running rtn[idx - prev_length] = fut elif next_task.writes: + # if it already ran, return the result + # TODO we could also set the result for non-RETURN writes fut = concurrent.futures.Future() if val := next(v for c, v in next_task.writes if c == RETURN): fut.set_result(val) From 2895a69678fe68288e740d66496029a344d5eb6c Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 19 Nov 2024 17:04:22 -0800 Subject: [PATCH 08/58] Lint --- libs/langgraph/langgraph/channels/base.py | 4 +- libs/langgraph/langgraph/func/__init__.py | 17 ++++----- libs/langgraph/langgraph/pregel/algo.py | 24 ++++++------ libs/langgraph/langgraph/pregel/call.py | 17 +++++---- libs/langgraph/langgraph/pregel/runner.py | 39 ++++++++++++-------- libs/langgraph/tests/test_pregel_async.py | 45 +++++++++++++++++++++++ 6 files changed, 99 insertions(+), 47 deletions(-) diff --git a/libs/langgraph/langgraph/channels/base.py b/libs/langgraph/langgraph/channels/base.py index 61f8908c0..4aaeb5681 100644 --- a/libs/langgraph/langgraph/channels/base.py +++ b/libs/langgraph/langgraph/channels/base.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Any, Generic, Optional, Sequence, Type, TypeVar +from typing import Any, Generic, Optional, Sequence, TypeVar from typing_extensions import Self @@ -13,7 +13,7 @@ C = TypeVar("C") class BaseChannel(Generic[Value, Update, C], ABC): __slots__ = ("key", "typ") - def __init__(self, typ: Type[Any], key: str = "") -> None: + def __init__(self, typ: Any, key: str = "") -> None: self.typ = typ self.key = key diff --git a/libs/langgraph/langgraph/func/__init__.py b/libs/langgraph/langgraph/func/__init__.py index 66acba23c..6826a8740 100644 --- a/libs/langgraph/langgraph/func/__init__.py +++ b/libs/langgraph/langgraph/func/__init__.py @@ -7,7 +7,6 @@ from typing import ( Any, Awaitable, Callable, - Coroutine, Optional, ParamSpec, TypeVar, @@ -33,22 +32,20 @@ T = TypeVar("T") @overload def task( *, retry: Optional[RetryPolicy] = None -) -> Callable[ - [Callable[P, Coroutine[None, None, T]]], Callable[P, asyncio.Future[T]] -]: ... +) -> Callable[[Callable[P, Awaitable[T]]], Callable[P, asyncio.Future[T]]]: ... @overload -def task( +def task( # type: ignore[overload-cannot-match] *, retry: Optional[RetryPolicy] = None ) -> Callable[[Callable[P, T]], Callable[P, concurrent.futures.Future[T]]]: ... def task( *, retry: Optional[RetryPolicy] = None -) -> Callable[ - [Callable[P, Union[T, Awaitable[T]]]], - Callable[P, Union[concurrent.futures.Future[T], asyncio.Future[T]]], +) -> Union[ + Callable[[Callable[P, Awaitable[T]]], Callable[P, asyncio.Future[T]]], + Callable[[Callable[P, T]], Callable[P, concurrent.futures.Future[T]]], ]: def _task(func: Callable[P, T]) -> Callable[P, concurrent.futures.Future[T]]: if asyncio.iscoroutinefunction(func): @@ -64,7 +61,7 @@ def imp( checkpointer: Optional[BaseCheckpointSaver] = None, store: Optional[BaseStore] = None, ) -> Callable[[types.FunctionType], Pregel]: - def _imp(func: types.FunctionType): + def _imp(func: types.FunctionType) -> Pregel: return Pregel( nodes={ func.__name__: PregelNode( @@ -74,7 +71,7 @@ def imp( writers=[ChannelWrite([ChannelWriteEntry(END)], tags=[TAG_HIDDEN])], ) }, - channels={START: EphemeralValue(Any, START), END: LastValue(Any, END)}, + channels={START: EphemeralValue(Any), END: LastValue(Any, END)}, input_channels=START, output_channels=END, stream_mode="updates", diff --git a/libs/langgraph/langgraph/pregel/algo.py b/libs/langgraph/langgraph/pregel/algo.py index 78242a9ac..330d46449 100644 --- a/libs/langgraph/langgraph/pregel/algo.py +++ b/libs/langgraph/langgraph/pregel/algo.py @@ -102,10 +102,10 @@ class PregelTaskWrites(NamedTuple): class Call: __slots__ = ("func", "input") - func: str | Callable + func: Callable input: Any - def __init__(self, func: str | Callable, input: Any) -> None: + def __init__(self, func: Callable, input: Any) -> None: self.func = func self.input = input @@ -451,7 +451,7 @@ def prepare_next_tasks( def prepare_single_task( - task_path: tuple[Union[str, int, tuple], ...], + task_path: tuple[Any, ...], task_id_checksum: Optional[str], *, checkpoint: Checkpoint, @@ -474,10 +474,10 @@ def prepare_single_task( if task_path[0] == PUSH and isinstance(task_path[-1], Call): # (PUSH, parent task path, idx of PUSH write, id of parent task, Call) - task_path_t = cast(tuple[str, tuple, int, str, Optional[Call]], task_path) + task_path_t = cast(tuple[str, tuple, int, str, Call], task_path) call = task_path_t[-1] - proc = get_runnable_for_func(call.func) - name = proc.name + proc_ = get_runnable_for_func(call.func) + name = proc_.name if name is None: raise ValueError("`call` functions must have a `__name__` attribute") # create task id @@ -507,7 +507,7 @@ def prepare_single_task( return PregelExecutableTask( name, call.input, - proc, + proc_, writes, patch_config( merge_configs(config, {"metadata": metadata}), @@ -586,14 +586,14 @@ def prepare_single_task( elif len(task_path) >= 4: # new PUSH tasks, executed in superstep n # (PUSH, parent task path, idx of PUSH write, id of parent task) - task_path_t = cast(tuple[str, tuple, int, str], task_path) - writes_for_path = [w for w in pending_writes if w[0] == task_path_t[3]] - if task_path_t[2] >= len(writes_for_path): + task_path_tt = cast(tuple[str, tuple, int, str], task_path) + writes_for_path = [w for w in pending_writes if w[0] == task_path_tt[3]] + if task_path_tt[2] >= len(writes_for_path): logger.warning( f"Ignoring invalid write index {task_path[2]} in pending writes" ) return - packet = writes_for_path[task_path_t[2]][2] + packet = writes_for_path[task_path_tt[2]][2] if packet is None: return if not isinstance(packet, Send): @@ -638,7 +638,7 @@ def prepare_single_task( if node := proc.node: if proc.metadata: metadata.update(proc.metadata) - writes: deque[tuple[str, Any]] = deque() + writes = deque() return PregelExecutableTask( packet.node, packet.arg, diff --git a/libs/langgraph/langgraph/pregel/call.py b/libs/langgraph/langgraph/pregel/call.py index 6d218f702..53ece995a 100644 --- a/libs/langgraph/langgraph/pregel/call.py +++ b/libs/langgraph/langgraph/pregel/call.py @@ -1,5 +1,6 @@ import sys import types +from typing import Any, Callable, Optional from langgraph.constants import RETURN from langgraph.pregel.write import ChannelWrite, ChannelWriteEntry @@ -11,7 +12,7 @@ https://github.com/cloudpipe/cloudpickle/blob/6220b0ce83ffee5e47e06770a1ee38ca9e """ -def _getattribute(obj, name): +def _getattribute(obj: Any, name: str) -> Any: for subpath in name.split("."): if subpath == "": raise AttributeError( @@ -27,7 +28,7 @@ def _getattribute(obj, name): return obj, parent -def _whichmodule(obj, name): +def _whichmodule(obj: Any, name: str) -> Optional[str]: """Find the module an object belongs to. This function differs from ``pickle.whichmodule`` in two ways: @@ -61,7 +62,9 @@ def _whichmodule(obj, name): return None -def _lookup_module_and_qualname(obj, name=None): +def _lookup_module_and_qualname( + obj: Any, name: Optional[str] = None +) -> Optional[tuple[types.ModuleType, str]]: if name is None: name = getattr(obj, "__qualname__", None) if name is None: # pragma: no cover @@ -69,6 +72,8 @@ def _lookup_module_and_qualname(obj, name=None): # needed anymore. However we keep the __name__ introspection in case # users of cloudpickle rely on this old behavior for unknown reasons. name = getattr(obj, "__name__", None) + if name is None: + return None module_name = _whichmodule(obj, name) @@ -101,9 +106,7 @@ def _lookup_module_and_qualname(obj, name=None): return module, name -def get_runnable_for_func( - func: types.FunctionType, -) -> RunnableSeq: +def get_runnable_for_func(func: Callable[..., Any]) -> RunnableSeq: if func in CACHE: return CACHE[func] elif not _lookup_module_and_qualname(func): @@ -123,4 +126,4 @@ def get_runnable_for_func( ) -CACHE: dict[types.FunctionType, RunnableCallable] = {} +CACHE: dict[Callable[..., Any], RunnableSeq] = {} diff --git a/libs/langgraph/langgraph/pregel/runner.py b/libs/langgraph/langgraph/pregel/runner.py index a21c3465e..150e84f30 100644 --- a/libs/langgraph/langgraph/pregel/runner.py +++ b/libs/langgraph/langgraph/pregel/runner.py @@ -130,7 +130,9 @@ class PregelRunner: return [rtn.get(i) for i in range(len(writes))] def call( - task, func: str | Callable[[Any], Union[Awaitable[Any], Any]], input: Any + task: PregelExecutableTask, + func: Callable[[Any], Union[Awaitable[Any], Any]], + input: Any, ) -> concurrent.futures.Future[Any]: (fut,) = writer(task, [(PUSH, None)], calls=[Call(func, input)]) assert fut is not None, "writer did not return a future for call" @@ -158,7 +160,7 @@ class PregelRunner: self.commit(t, exc) if reraise and futures: # will be re-raised after futures are done - fut = concurrent.futures.Future() + fut: concurrent.futures.Future = concurrent.futures.Future() fut.set_exception(exc) done_futures.add(fut) elif reraise: @@ -259,25 +261,30 @@ class PregelRunner: ): continue # schedule the next task - fut = self.submit( - arun_with_retry, - next_task, - retry_policy, - stream=self.use_astream, - configurable={ - CONFIG_KEY_SEND: partial(writer, next_task), - CONFIG_KEY_CALL: partial(call, next_task), - }, - __name__=t.name, - __cancel_on_exit__=True, - __reraise_on_exit__=reraise, + fut = cast( + asyncio.Future, + self.submit( + arun_with_retry, + next_task, + retry_policy, + stream=self.use_astream, + configurable={ + CONFIG_KEY_SEND: partial(writer, next_task), + CONFIG_KEY_CALL: partial(call, next_task), + }, + __name__=t.name, + __cancel_on_exit__=True, + __reraise_on_exit__=reraise, + ), ) - futures[cast(asyncio.Future, fut)] = next_task + futures[fut] = next_task rtn[idx - prev_length] = fut return [rtn.get(i) for i in range(len(writes))] def call( - task, func: str | Callable[[Any], Union[Awaitable[Any], Any]], input: Any + task: PregelExecutableTask, + func: Callable[[Any], Union[Awaitable[Any], Any]], + input: Any, ) -> asyncio.Future[Any]: (fut,) = writer(task, [(PUSH, None)], calls=[Call(func, input)]) assert fut is not None, "writer did not return a future for call" diff --git a/libs/langgraph/tests/test_pregel_async.py b/libs/langgraph/tests/test_pregel_async.py index d8aeedd9a..450606d80 100644 --- a/libs/langgraph/tests/test_pregel_async.py +++ b/libs/langgraph/tests/test_pregel_async.py @@ -62,6 +62,7 @@ from langgraph.constants import ( START, ) from langgraph.errors import InvalidUpdateError, MultipleSubgraphsError, NodeInterrupt +from langgraph.func import imp, task from langgraph.graph import END, Graph, StateGraph from langgraph.graph.message import MessageGraph, MessagesState, add_messages from langgraph.managed.shared_value import SharedValue @@ -2647,6 +2648,50 @@ async def test_send_sequences(checkpointer_name: str) -> None: ] +@pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_ASYNC) +async def test_imp_task(checkpointer_name: str) -> None: + mapper_calls = 0 + + @task() + async def mapper(input: str) -> str: + nonlocal mapper_calls + mapper_calls += 1 + return input * 2 + + async with awith_checkpointer(checkpointer_name) as checkpointer: + + @imp(checkpointer=checkpointer) + async def graph(input: list[str]) -> list[str]: + futures = [mapper(i) for i in input] + mapped = await asyncio.gather(*futures) + answer = interrupt("question") + return [m + answer for m in mapped] + + thread1 = {"configurable": {"thread_id": "1"}} + assert [c async for c in graph.astream(["0", "1"], thread1)] == [ + # TODO make test not depend on order of execution (which is not guaranteed) + {"mapper": "00"}, + {"mapper": "11"}, + { + "__interrupt__": ( + Interrupt( + value="question", + resumable=True, + ns=[AnyStr("graph:")], + when="during", + ), + ) + }, + ] + assert mapper_calls == 2 + + assert await graph.ainvoke(Command(resume="answer"), thread1) == [ + "00answer", + "11answer", + ] + assert mapper_calls == 2 + + @pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_ASYNC) async def test_send_dedupe_on_resume(checkpointer_name: str) -> None: if not FF_SEND_V2: From 2e9aea6fc8b08d66ae33f177bacb790bddec0c72 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 19 Nov 2024 17:11:12 -0800 Subject: [PATCH 09/58] Lint --- libs/langgraph/langgraph/types.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/langgraph/langgraph/types.py b/libs/langgraph/langgraph/types.py index b49b1c45e..a0949613c 100644 --- a/libs/langgraph/langgraph/types.py +++ b/libs/langgraph/langgraph/types.py @@ -15,7 +15,6 @@ from typing import ( Literal, NamedTuple, Optional, - ParamSpec, Sequence, Type, TypedDict, @@ -25,7 +24,7 @@ from typing import ( ) from langchain_core.runnables import Runnable, RunnableConfig -from typing_extensions import Self +from typing_extensions import ParamSpec, Self from langgraph.checkpoint.base import ( BaseCheckpointSaver, From a443b3b25677b83950ec3128b1f8701f456b4e84 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 19 Nov 2024 17:16:24 -0800 Subject: [PATCH 10/58] Fix --- libs/langgraph/langgraph/pregel/call.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libs/langgraph/langgraph/pregel/call.py b/libs/langgraph/langgraph/pregel/call.py index 53ece995a..a837ff4a8 100644 --- a/libs/langgraph/langgraph/pregel/call.py +++ b/libs/langgraph/langgraph/pregel/call.py @@ -1,3 +1,4 @@ +import asyncio import sys import types from typing import Any, Callable, Optional @@ -111,7 +112,9 @@ def get_runnable_for_func(func: Callable[..., Any]) -> RunnableSeq: return CACHE[func] elif not _lookup_module_and_qualname(func): return RunnableSeq( - RunnableCallable(func, trace=False), + RunnableCallable(None, func, trace=False) + if asyncio.iscoroutinefunction(func) + else RunnableCallable(func, trace=False), ChannelWrite([ChannelWriteEntry(RETURN)]), name=func.__name__, ) @@ -119,7 +122,9 @@ def get_runnable_for_func(func: Callable[..., Any]) -> RunnableSeq: return CACHE.setdefault( func, RunnableSeq( - RunnableCallable(func, trace=False), + RunnableCallable(None, func, trace=False) + if asyncio.iscoroutinefunction(func) + else RunnableCallable(func, trace=False), ChannelWrite([ChannelWriteEntry(RETURN)]), name=func.__name__, ), From 90dd2b01b6bbad852fefc4d0faeecf4ccbf669e3 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 19 Nov 2024 17:19:30 -0800 Subject: [PATCH 11/58] Comment --- libs/langgraph/langgraph/pregel/runner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/langgraph/langgraph/pregel/runner.py b/libs/langgraph/langgraph/pregel/runner.py index 150e84f30..a7a17fc09 100644 --- a/libs/langgraph/langgraph/pregel/runner.py +++ b/libs/langgraph/langgraph/pregel/runner.py @@ -248,6 +248,7 @@ class PregelRunner: # bail if not a PUSH write if w[0] != PUSH: continue + # TODO apply changes from sync version # schedule the next task, if the callback returns one if next_task := self.schedule_task( task, From 287c29fbdc641607ff71e362a5d359a8599e94a2 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Wed, 20 Nov 2024 15:38:43 -0800 Subject: [PATCH 12/58] Fix async --- libs/langgraph/langgraph/pregel/runner.py | 119 +++++++++++++++------- libs/langgraph/langgraph/types.py | 1 - 2 files changed, 80 insertions(+), 40 deletions(-) diff --git a/libs/langgraph/langgraph/pregel/runner.py b/libs/langgraph/langgraph/pregel/runner.py index a7a17fc09..7c10a72ac 100644 --- a/libs/langgraph/langgraph/pregel/runner.py +++ b/libs/langgraph/langgraph/pregel/runner.py @@ -1,5 +1,6 @@ import asyncio import concurrent.futures +import threading import time from functools import partial from typing import ( @@ -66,18 +67,26 @@ class PregelRunner: retry_policy: Optional[RetryPolicy] = None, get_waiter: Optional[Callable[[], concurrent.futures.Future[None]]] = None, ) -> Iterator[None]: + locks: dict[str, threading.Lock] = {} + def writer( task: PregelExecutableTask, writes: Sequence[tuple[str, Any]], *, calls: Optional[Sequence[Call]] = None, ) -> Sequence[Optional[concurrent.futures.Future]]: - prev_length = len(task.writes) - # delegate to the underlying writer - task.config[CONF][CONFIG_KEY_SEND](writes) - # confirm no other concurrent writes were added - # TODO could use a lock here instead, if writes can come from many threads - assert len(task.writes) == prev_length + len(writes) + if all(w[0] != PUSH for w in writes): + return task.config[CONF][CONFIG_KEY_SEND](writes) + + if task.id not in locks: + locks[task.id] = threading.Lock() + with locks[task.id]: + prev_length = len(task.writes) + # delegate to the underlying writer + task.config[CONF][CONFIG_KEY_SEND](writes) + # confirm no other concurrent writes were added + assert len(task.writes) == prev_length + len(writes) + # schedule PUSH tasks, collect futures rtn: dict[int, Optional[concurrent.futures.Future]] = {} for idx, w in enumerate(writes, start=prev_length): # bail if not a PUSH write @@ -100,7 +109,6 @@ class PregelRunner: rtn[idx - prev_length] = fut elif next_task.writes: # if it already ran, return the result - # TODO we could also set the result for non-RETURN writes fut = concurrent.futures.Future() if val := next(v for c, v in next_task.writes if c == RETURN): fut.set_result(val) @@ -212,7 +220,6 @@ class PregelRunner: del fut, task # maybe stop other tasks if _should_stop_others(done): - print("stopping others") break # give control back to the caller yield @@ -231,24 +238,31 @@ class PregelRunner: retry_policy: Optional[RetryPolicy] = None, get_waiter: Optional[Callable[[], asyncio.Future[None]]] = None, ) -> AsyncIterator[None]: + locks: dict[str, threading.Lock] = {} + def writer( task: PregelExecutableTask, writes: Sequence[tuple[str, Any]], *, calls: Optional[Sequence[Call]] = None, ) -> Sequence[Optional[asyncio.Future]]: - prev_length = len(task.writes) - # delegate to the underlying writer - task.config[CONF][CONFIG_KEY_SEND](writes) - # confirm no other concurrent writes were added - # TODO could use a lock here instead, if writes can come from many threads - assert len(task.writes) == prev_length + len(writes) + if all(w[0] != PUSH for w in writes): + return task.config[CONF][CONFIG_KEY_SEND](writes) + + if task.id not in locks: + locks[task.id] = threading.Lock() + with locks[task.id]: + prev_length = len(task.writes) + # delegate to the underlying writer + task.config[CONF][CONFIG_KEY_SEND](writes) + # confirm no other concurrent writes were added + assert len(task.writes) == prev_length + len(writes) + # schedule PUSH tasks, collect futures rtn: dict[int, Optional[asyncio.Future]] = {} for idx, w in enumerate(writes, start=prev_length): # bail if not a PUSH write if w[0] != PUSH: continue - # TODO apply changes from sync version # schedule the next task, if the callback returns one if next_task := self.schedule_task( task, @@ -257,29 +271,51 @@ class PregelRunner: ): # if the parent task was retried, # the next task might already be running - if any( - t == next_task.id for t in futures.values() if t is not None - ): - continue - # schedule the next task - fut = cast( - asyncio.Future, - self.submit( - arun_with_retry, - next_task, - retry_policy, - stream=self.use_astream, - configurable={ - CONFIG_KEY_SEND: partial(writer, next_task), - CONFIG_KEY_CALL: partial(call, next_task), - }, - __name__=t.name, - __cancel_on_exit__=True, - __reraise_on_exit__=reraise, + if fut := next( + ( + f + for f, t in futures.items() + if t is not None and t == next_task.id ), - ) - futures[fut] = next_task - rtn[idx - prev_length] = fut + None, + ): + # if the parent task was retried, + # the next task might already be running + rtn[idx - prev_length] = fut + elif next_task.writes: + # if it already ran, return the result + fut = asyncio.Future() + if val := next(v for c, v in next_task.writes if c == RETURN): + fut.set_result(val) + elif exc := next(v for c, v in next_task.writes if c == ERROR): + fut.set_exception( + exc + if isinstance(exc, BaseException) + else Exception(exc) + ) + else: + fut.set_result(None) + rtn[idx - prev_length] = fut + else: + # schedule the next task + fut = cast( + asyncio.Future, + self.submit( + arun_with_retry, + next_task, + retry_policy, + stream=self.use_astream, + configurable={ + CONFIG_KEY_SEND: partial(writer, next_task), + CONFIG_KEY_CALL: partial(call, next_task), + }, + __name__=t.name, + __cancel_on_exit__=True, + __reraise_on_exit__=reraise, + ), + ) + futures[fut] = next_task + rtn[idx - prev_length] = fut return [rtn.get(i) for i in range(len(writes))] def call( @@ -294,6 +330,7 @@ class PregelRunner: loop = asyncio.get_event_loop() tasks = tuple(tasks) futures: dict[asyncio.Future, Optional[PregelExecutableTask]] = {} + done_futures: set[asyncio.Future] = set() # give control back to the caller yield # fast path if single task with no waiter and no timeout @@ -312,7 +349,12 @@ class PregelRunner: self.commit(t, None) except Exception as exc: self.commit(t, exc) - if reraise: + if reraise and futures: + # will be re-raised after futures are done + fut: asyncio.Future = loop.create_future() + fut.set_exception(exc) + done_futures.add(fut) + elif reraise: raise if not futures: # maybe `t` schuduled another task return @@ -342,7 +384,6 @@ class PregelRunner: ), ) ] = t - done_futures: set[asyncio.Future] = set() end_time = timeout + loop.time() if timeout else None while len(futures) > (1 if get_waiter is not None else 0): done, inflight = await asyncio.wait( diff --git a/libs/langgraph/langgraph/types.py b/libs/langgraph/langgraph/types.py index a0949613c..3bdbf2049 100644 --- a/libs/langgraph/langgraph/types.py +++ b/libs/langgraph/langgraph/types.py @@ -398,5 +398,4 @@ def acall( fut = impl(func, *args, **kwargs) if isinstance(fut, concurrent.futures.Future): fut = asyncio.wrap_future(fut) - fut.cancel return fut From d93be914c7187861bdb0bd6031abee53acb993d2 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Wed, 20 Nov 2024 17:09:54 -0800 Subject: [PATCH 13/58] Fix stream order --- libs/langgraph/langgraph/func/__init__.py | 7 +- libs/langgraph/langgraph/pregel/call.py | 25 ++--- libs/langgraph/langgraph/pregel/runner.py | 94 +++++++++-------- libs/langgraph/langgraph/types.py | 18 ---- libs/langgraph/langgraph/utils/future.py | 121 ++++++++++++++++++++++ libs/langgraph/tests/test_pregel.py | 44 +++++++- libs/langgraph/tests/test_pregel_async.py | 84 +++++++++++++-- 7 files changed, 292 insertions(+), 101 deletions(-) create mode 100644 libs/langgraph/langgraph/utils/future.py diff --git a/libs/langgraph/langgraph/func/__init__.py b/libs/langgraph/langgraph/func/__init__.py index 6826a8740..b48cf32e2 100644 --- a/libs/langgraph/langgraph/func/__init__.py +++ b/libs/langgraph/langgraph/func/__init__.py @@ -23,7 +23,7 @@ from langgraph.pregel.call import get_runnable_for_func from langgraph.pregel.read import PregelNode from langgraph.pregel.write import ChannelWrite, ChannelWriteEntry from langgraph.store.base import BaseStore -from langgraph.types import RetryPolicy, acall, call +from langgraph.types import RetryPolicy, call P = ParamSpec("P") T = TypeVar("T") @@ -48,10 +48,7 @@ def task( Callable[[Callable[P, T]], Callable[P, concurrent.futures.Future[T]]], ]: def _task(func: Callable[P, T]) -> Callable[P, concurrent.futures.Future[T]]: - if asyncio.iscoroutinefunction(func): - return update_wrapper(partial(acall, func), func) - else: - return update_wrapper(partial(call, func), func) + return update_wrapper(partial(call, func), func) return _task diff --git a/libs/langgraph/langgraph/pregel/call.py b/libs/langgraph/langgraph/pregel/call.py index a837ff4a8..a9986102d 100644 --- a/libs/langgraph/langgraph/pregel/call.py +++ b/libs/langgraph/langgraph/pregel/call.py @@ -1,11 +1,10 @@ -import asyncio import sys import types from typing import Any, Callable, Optional from langgraph.constants import RETURN from langgraph.pregel.write import ChannelWrite, ChannelWriteEntry -from langgraph.utils.runnable import RunnableCallable, RunnableSeq +from langgraph.utils.runnable import RunnableSeq, coerce_to_runnable """ Utilities borrowed from cloudpickle. @@ -110,25 +109,15 @@ def _lookup_module_and_qualname( def get_runnable_for_func(func: Callable[..., Any]) -> RunnableSeq: if func in CACHE: return CACHE[func] - elif not _lookup_module_and_qualname(func): - return RunnableSeq( - RunnableCallable(None, func, trace=False) - if asyncio.iscoroutinefunction(func) - else RunnableCallable(func, trace=False), + else: + seq = RunnableSeq( + coerce_to_runnable(func, name=None, trace=False), ChannelWrite([ChannelWriteEntry(RETURN)]), name=func.__name__, ) - else: - return CACHE.setdefault( - func, - RunnableSeq( - RunnableCallable(None, func, trace=False) - if asyncio.iscoroutinefunction(func) - else RunnableCallable(func, trace=False), - ChannelWrite([ChannelWriteEntry(RETURN)]), - name=func.__name__, - ), - ) + if not _lookup_module_and_qualname(func): + return seq + return CACHE.setdefault(func, seq) CACHE: dict[Callable[..., Any], RunnableSeq] = {} diff --git a/libs/langgraph/langgraph/pregel/runner.py b/libs/langgraph/langgraph/pregel/runner.py index 7c10a72ac..8decbedec 100644 --- a/libs/langgraph/langgraph/pregel/runner.py +++ b/libs/langgraph/langgraph/pregel/runner.py @@ -34,6 +34,7 @@ from langgraph.pregel.algo import Call from langgraph.pregel.executor import Submit from langgraph.pregel.retry import arun_with_retry, run_with_retry from langgraph.types import PregelExecutableTask, RetryPolicy +from langgraph.utils.future import chain_future class PregelRunner: @@ -133,6 +134,7 @@ class PregelRunner: }, __reraise_on_exit__=reraise, ) + fut.add_done_callback(partial(self.commit, next_task)) futures[fut] = next_task rtn[idx - prev_length] = fut return [rtn.get(i) for i in range(len(writes))] @@ -165,7 +167,7 @@ class PregelRunner: ) self.commit(t, None) except Exception as exc: - self.commit(t, exc) + self.commit(t, None, exc) if reraise and futures: # will be re-raised after futures are done fut: concurrent.futures.Future = concurrent.futures.Future() @@ -183,18 +185,18 @@ class PregelRunner: # yield updates/debug output as each task finishes for t in tasks: if not t.writes: - futures[ - self.submit( - run_with_retry, - t, - retry_policy, - configurable={ - CONFIG_KEY_SEND: partial(writer, t), - CONFIG_KEY_CALL: partial(call, t), - }, - __reraise_on_exit__=reraise, - ) - ] = t + fut = self.submit( + run_with_retry, + t, + retry_policy, + configurable={ + CONFIG_KEY_SEND: partial(writer, t), + CONFIG_KEY_CALL: partial(call, t), + }, + __reraise_on_exit__=reraise, + ) + fut.add_done_callback(partial(self.commit, t)) + futures[fut] = t end_time = timeout + time.monotonic() if timeout else None while len(futures) > (1 if get_waiter is not None else 0): done, inflight = concurrent.futures.wait( @@ -213,8 +215,6 @@ class PregelRunner: else: # store for panic check done_futures.add(fut) - # task finished, commit writes - self.commit(task, _exception(fut)) else: # remove references to loop vars del fut, task @@ -264,11 +264,8 @@ class PregelRunner: if w[0] != PUSH: continue # schedule the next task, if the callback returns one - if next_task := self.schedule_task( - task, - idx, - calls[idx - prev_length] if calls is not None else None, - ): + wcall = calls[idx - prev_length] if calls is not None else None + if next_task := self.schedule_task(task, idx, wcall): # if the parent task was retried, # the next task might already be running if fut := next( @@ -314,6 +311,7 @@ class PregelRunner: __reraise_on_exit__=reraise, ), ) + fut.add_done_callback(partial(self.commit, next_task)) futures[fut] = next_task rtn[idx - prev_length] = fut return [rtn.get(i) for i in range(len(writes))] @@ -322,10 +320,15 @@ class PregelRunner: task: PregelExecutableTask, func: Callable[[Any], Union[Awaitable[Any], Any]], input: Any, - ) -> asyncio.Future[Any]: + ) -> Union[asyncio.Future[Any], concurrent.futures.Future[Any]]: (fut,) = writer(task, [(PUSH, None)], calls=[Call(func, input)]) assert fut is not None, "writer did not return a future for call" - return fut + if asyncio.iscoroutinefunction(func): + return fut + # adapted from asyncio.run_coroutine_threadsafe + sfut = concurrent.futures.Future() + loop.call_soon_threadsafe(chain_future, fut, sfut) + return sfut loop = asyncio.get_event_loop() tasks = tuple(tasks) @@ -348,7 +351,7 @@ class PregelRunner: ) self.commit(t, None) except Exception as exc: - self.commit(t, exc) + self.commit(t, None, exc) if reraise and futures: # will be re-raised after futures are done fut: asyncio.Future = loop.create_future() @@ -366,24 +369,24 @@ class PregelRunner: # yield updates/debug output as each task finishes for t in tasks: if not t.writes: - futures[ - cast( - asyncio.Future, - self.submit( - arun_with_retry, - t, - retry_policy, - stream=self.use_astream, - configurable={ - CONFIG_KEY_SEND: partial(writer, t), - CONFIG_KEY_CALL: partial(call, t), - }, - __name__=t.name, - __cancel_on_exit__=True, - __reraise_on_exit__=reraise, - ), - ) - ] = t + fut = cast( + asyncio.Future, + self.submit( + arun_with_retry, + t, + retry_policy, + stream=self.use_astream, + configurable={ + CONFIG_KEY_SEND: partial(writer, t), + CONFIG_KEY_CALL: partial(call, t), + }, + __name__=t.name, + __cancel_on_exit__=True, + __reraise_on_exit__=reraise, + ), + ) + fut.add_done_callback(partial(self.commit, t)) + futures[fut] = t end_time = timeout + loop.time() if timeout else None while len(futures) > (1 if get_waiter is not None else 0): done, inflight = await asyncio.wait( @@ -402,8 +405,6 @@ class PregelRunner: else: # store for panic check done_futures.add(fut) - # task finished, commit writes - self.commit(task, _exception(fut)) else: # remove references to loop vars del fut, task @@ -423,8 +424,13 @@ class PregelRunner: ) def commit( - self, task: PregelExecutableTask, exception: Optional[BaseException] + self, + task: PregelExecutableTask, + fut: Union[None, concurrent.futures.Future[Any], asyncio.Future[Any]], + exception: Optional[BaseException] = None, ) -> None: + if fut is not None: + exception = _exception(fut) if exception: if isinstance(exception, GraphInterrupt): # save interrupt to checkpointer diff --git a/libs/langgraph/langgraph/types.py b/libs/langgraph/langgraph/types.py index 3bdbf2049..5ce64b52b 100644 --- a/libs/langgraph/langgraph/types.py +++ b/libs/langgraph/langgraph/types.py @@ -1,4 +1,3 @@ -import asyncio import concurrent import concurrent.futures import dataclasses @@ -7,7 +6,6 @@ from collections import deque from typing import ( TYPE_CHECKING, Any, - Awaitable, Callable, ClassVar, Generic, @@ -382,20 +380,4 @@ def call( conf = get_configurable() impl = conf[CONFIG_KEY_CALL] fut = impl(func, *args, **kwargs) - if not isinstance(fut, concurrent.futures.Future): - raise RuntimeError("In an async context, use acall() instead of call()") - return fut - - -def acall( - func: str | Callable[P, Union[T, Awaitable[T]]], *args: P.args, **kwargs: P.kwargs -) -> asyncio.Future[T]: - from langgraph.constants import CONFIG_KEY_CALL - from langgraph.utils.config import get_configurable - - conf = get_configurable() - impl = conf[CONFIG_KEY_CALL] - fut = impl(func, *args, **kwargs) - if isinstance(fut, concurrent.futures.Future): - fut = asyncio.wrap_future(fut) return fut diff --git a/libs/langgraph/langgraph/utils/future.py b/libs/langgraph/langgraph/utils/future.py new file mode 100644 index 000000000..d7b8718f6 --- /dev/null +++ b/libs/langgraph/langgraph/utils/future.py @@ -0,0 +1,121 @@ +import asyncio +import concurrent.futures +from typing import Union + +AnyFuture = Union[asyncio.Future, concurrent.futures.Future] + + +def _get_loop(fut: asyncio.Future) -> asyncio.AbstractEventLoop: + # Tries to call Future.get_loop() if it's available. + # Otherwise fallbacks to using the old '_loop' property. + try: + get_loop = fut.get_loop + except AttributeError: + pass + else: + return get_loop() + return fut._loop + + +def _convert_future_exc(exc): + exc_class = type(exc) + if exc_class is concurrent.futures.CancelledError: + return asyncio.CancelledError(*exc.args) + elif exc_class is concurrent.futures.TimeoutError: + return asyncio.TimeoutError(*exc.args) + elif exc_class is concurrent.futures.InvalidStateError: + return asyncio.InvalidStateError(*exc.args) + else: + return exc + + +def _set_concurrent_future_state(concurrent, source): + """Copy state from a future to a concurrent.futures.Future.""" + assert source.done() + if source.cancelled(): + concurrent.cancel() + if not concurrent.set_running_or_notify_cancel(): + return + exception = source.exception() + if exception is not None: + concurrent.set_exception(_convert_future_exc(exception)) + else: + result = source.result() + concurrent.set_result(result) + + +def _copy_future_state(source, dest): + """Internal helper to copy state from another Future. + + The other Future may be a concurrent.futures.Future. + """ + assert source.done() + if dest.cancelled(): + return + assert not dest.done() + if source.cancelled(): + dest.cancel() + else: + exception = source.exception() + if exception is not None: + dest.set_exception(_convert_future_exc(exception)) + else: + result = source.result() + dest.set_result(result) + + +def _chain_future(source: AnyFuture, destination: AnyFuture) -> None: + """Chain two futures so that when one completes, so does the other. + + The result (or exception) of source will be copied to destination. + If destination is cancelled, source gets cancelled too. + Compatible with both asyncio.Future and concurrent.futures.Future. + """ + if not asyncio.isfuture(source) and not isinstance( + source, concurrent.futures.Future + ): + raise TypeError("A future is required for source argument") + if not asyncio.isfuture(destination) and not isinstance( + destination, concurrent.futures.Future + ): + raise TypeError("A future is required for destination argument") + source_loop = _get_loop(source) if asyncio.isfuture(source) else None + dest_loop = _get_loop(destination) if asyncio.isfuture(destination) else None + + def _set_state(future, other): + if asyncio.isfuture(future): + _copy_future_state(other, future) + else: + _set_concurrent_future_state(future, other) + + def _call_check_cancel(destination): + if destination.cancelled(): + if source_loop is None or source_loop is dest_loop: + source.cancel() + else: + source_loop.call_soon_threadsafe(source.cancel) + + def _call_set_state(source): + if destination.cancelled() and dest_loop is not None and dest_loop.is_closed(): + return + if dest_loop is None or dest_loop is source_loop: + _set_state(destination, source) + else: + if dest_loop.is_closed(): + return + dest_loop.call_soon_threadsafe(_set_state, destination, source) + + destination.add_done_callback(_call_check_cancel) + source.add_done_callback(_call_set_state) + + +def chain_future(source: AnyFuture, destination: AnyFuture) -> None: + # adapted from asyncio.run_coroutine_threadsafe + try: + _chain_future(source, destination) + except (SystemExit, KeyboardInterrupt): + raise + except BaseException as exc: + if destination.set_running_or_notify_cancel(): + destination.set_exception(exc) + raise diff --git a/libs/langgraph/tests/test_pregel.py b/libs/langgraph/tests/test_pregel.py index 49ee6bec5..ab675ea79 100644 --- a/libs/langgraph/tests/test_pregel.py +++ b/libs/langgraph/tests/test_pregel.py @@ -1976,21 +1976,21 @@ def test_imp_task(request: pytest.FixtureRequest, checkpointer_name: str) -> Non mapper_calls = 0 @task() - def mapper(input: str) -> str: + def mapper(input: int) -> str: nonlocal mapper_calls mapper_calls += 1 - return input * 2 + time.sleep(input / 100) + return str(input) * 2 @imp(checkpointer=checkpointer) - def graph(input: list[str]) -> list[str]: + def graph(input: list[int]) -> list[str]: futures = [mapper(i) for i in input] mapped = [f.result() for f in futures] answer = interrupt("question") return [m + answer for m in mapped] thread1 = {"configurable": {"thread_id": "1"}} - assert [*graph.stream(["0", "1"], thread1)] == [ - # TODO make test not depend on order of execution (which is not guaranteed) + assert [*graph.stream([0, 1], thread1)] == [ {"mapper": "00"}, {"mapper": "11"}, { @@ -2013,6 +2013,40 @@ def test_imp_task(request: pytest.FixtureRequest, checkpointer_name: str) -> Non assert mapper_calls == 2 +@pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_SYNC) +def test_imp_stream_order( + request: pytest.FixtureRequest, checkpointer_name: str +) -> None: + checkpointer = request.getfixturevalue(f"checkpointer_{checkpointer_name}") + + @task() + def foo(state: dict) -> dict: + return {"a": state["a"] + "foo", "b": "bar"} + + @task() + def bar(state: dict) -> dict: + return {"a": state["a"] + state["b"], "c": "bark"} + + @task() + def baz(state: dict) -> dict: + return {"a": state["a"] + "baz", "c": "something else"} + + @imp(checkpointer=checkpointer) + def graph(state: dict) -> dict: + fut_foo = foo(state) + fut_bar = bar(fut_foo.result()) + fut_baz = baz(fut_bar.result()) + return fut_baz.result() + + thread1 = {"configurable": {"thread_id": "1"}} + assert [c for c in graph.stream({"a": "0"}, thread1)] == [ + {"foo": {"a": "0foo", "b": "bar"}}, + {"bar": {"a": "0foobar", "c": "bark"}}, + {"baz": {"a": "0foobarbaz", "c": "something else"}}, + {"graph": {"a": "0foobarbaz", "c": "something else"}}, + ] + + @pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_SYNC) def test_send_dedupe_on_resume( request: pytest.FixtureRequest, checkpointer_name: str diff --git a/libs/langgraph/tests/test_pregel_async.py b/libs/langgraph/tests/test_pregel_async.py index 450606d80..07e16a538 100644 --- a/libs/langgraph/tests/test_pregel_async.py +++ b/libs/langgraph/tests/test_pregel_async.py @@ -2650,26 +2650,24 @@ async def test_send_sequences(checkpointer_name: str) -> None: @pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_ASYNC) async def test_imp_task(checkpointer_name: str) -> None: - mapper_calls = 0 - - @task() - async def mapper(input: str) -> str: - nonlocal mapper_calls - mapper_calls += 1 - return input * 2 - async with awith_checkpointer(checkpointer_name) as checkpointer: + mapper_calls = 0 + + @task() + async def mapper(input: int) -> str: + nonlocal mapper_calls + mapper_calls += 1 + return str(input) * 2 @imp(checkpointer=checkpointer) - async def graph(input: list[str]) -> list[str]: + async def graph(input: list[int]) -> list[str]: futures = [mapper(i) for i in input] mapped = await asyncio.gather(*futures) answer = interrupt("question") return [m + answer for m in mapped] thread1 = {"configurable": {"thread_id": "1"}} - assert [c async for c in graph.astream(["0", "1"], thread1)] == [ - # TODO make test not depend on order of execution (which is not guaranteed) + assert [c async for c in graph.astream([0, 1], thread1)] == [ {"mapper": "00"}, {"mapper": "11"}, { @@ -2692,6 +2690,70 @@ async def test_imp_task(checkpointer_name: str) -> None: assert mapper_calls == 2 +@pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_ASYNC) +async def test_imp_sync_from_async(checkpointer_name: str) -> None: + async with awith_checkpointer(checkpointer_name) as checkpointer: + + @task() + def foo(state: dict) -> dict: + return {"a": state["a"] + "foo", "b": "bar"} + + @task() + def bar(state: dict) -> dict: + return {"a": state["a"] + state["b"], "c": "bark"} + + @task() + def baz(state: dict) -> dict: + return {"a": state["a"] + "baz", "c": "something else"} + + @imp(checkpointer=checkpointer) + def graph(state: dict) -> dict: + fut_foo = foo(state) + fut_bar = bar(fut_foo.result()) + fut_baz = baz(fut_bar.result()) + return fut_baz.result() + + thread1 = {"configurable": {"thread_id": "1"}} + assert [c async for c in graph.astream({"a": "0"}, thread1)] == [ + {"foo": {"a": "0foo", "b": "bar"}}, + {"bar": {"a": "0foobar", "c": "bark"}}, + {"baz": {"a": "0foobarbaz", "c": "something else"}}, + {"graph": {"a": "0foobarbaz", "c": "something else"}}, + ] + + +@pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_ASYNC) +async def test_imp_stream_order(checkpointer_name: str) -> None: + async with awith_checkpointer(checkpointer_name) as checkpointer: + + @task() + async def foo(state: dict) -> dict: + return {"a": state["a"] + "foo", "b": "bar"} + + @task() + async def bar(state: dict) -> dict: + return {"a": state["a"] + state["b"], "c": "bark"} + + @task() + async def baz(state: dict) -> dict: + return {"a": state["a"] + "baz", "c": "something else"} + + @imp(checkpointer=checkpointer) + async def graph(state: dict) -> dict: + fut_foo = foo(state) + fut_bar = bar(await fut_foo) + fut_baz = baz(await fut_bar) + return await fut_baz + + thread1 = {"configurable": {"thread_id": "1"}} + assert [c async for c in graph.astream({"a": "0"}, thread1)] == [ + {"foo": {"a": "0foo", "b": "bar"}}, + {"bar": {"a": "0foobar", "c": "bark"}}, + {"baz": {"a": "0foobarbaz", "c": "something else"}}, + {"graph": {"a": "0foobarbaz", "c": "something else"}}, + ] + + @pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_ASYNC) async def test_send_dedupe_on_resume(checkpointer_name: str) -> None: if not FF_SEND_V2: From a91dbf9b70f7cd397e6ea666f87b390e2ecb51ad Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Thu, 21 Nov 2024 08:10:39 -0800 Subject: [PATCH 14/58] Lint --- libs/langgraph/langgraph/pregel/__init__.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libs/langgraph/langgraph/pregel/__init__.py b/libs/langgraph/langgraph/pregel/__init__.py index 52cd2bf09..e714afe21 100644 --- a/libs/langgraph/langgraph/pregel/__init__.py +++ b/libs/langgraph/langgraph/pregel/__init__.py @@ -541,11 +541,6 @@ class Pregel(PregelProtocol): next_tasks[tid].writes.append((k, v)) if tasks := [t for t in next_tasks.values() if t.writes]: apply_writes(saved.checkpoint, channels, tasks, None) - print( - "next_tasks", - [(t.id, t.name, t.input, bool(t.writes)) for t in next_tasks.values()], - ) - print("pending_writes", saved.pending_writes) # assemble the state snapshot return StateSnapshot( read_channels(channels, self.stream_channels_asis), From 0663d46c478936923988d25a5fa36edfb41d0728 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Thu, 21 Nov 2024 08:11:23 -0800 Subject: [PATCH 15/58] Rename --- libs/langgraph/langgraph/func/__init__.py | 2 +- libs/langgraph/tests/test_pregel.py | 6 +++--- libs/langgraph/tests/test_pregel_async.py | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/langgraph/langgraph/func/__init__.py b/libs/langgraph/langgraph/func/__init__.py index b48cf32e2..69e9b6c5d 100644 --- a/libs/langgraph/langgraph/func/__init__.py +++ b/libs/langgraph/langgraph/func/__init__.py @@ -53,7 +53,7 @@ def task( return _task -def imp( +def entrypoint( *, checkpointer: Optional[BaseCheckpointSaver] = None, store: Optional[BaseStore] = None, diff --git a/libs/langgraph/tests/test_pregel.py b/libs/langgraph/tests/test_pregel.py index ab675ea79..8de87ef0e 100644 --- a/libs/langgraph/tests/test_pregel.py +++ b/libs/langgraph/tests/test_pregel.py @@ -65,7 +65,7 @@ from langgraph.constants import ( START, ) from langgraph.errors import InvalidUpdateError, MultipleSubgraphsError, NodeInterrupt -from langgraph.func import imp, task +from langgraph.func import entrypoint, task from langgraph.graph import END, Graph, StateGraph from langgraph.graph.message import MessageGraph, MessagesState, add_messages from langgraph.managed.shared_value import SharedValue @@ -1982,7 +1982,7 @@ def test_imp_task(request: pytest.FixtureRequest, checkpointer_name: str) -> Non time.sleep(input / 100) return str(input) * 2 - @imp(checkpointer=checkpointer) + @entrypoint(checkpointer=checkpointer) def graph(input: list[int]) -> list[str]: futures = [mapper(i) for i in input] mapped = [f.result() for f in futures] @@ -2031,7 +2031,7 @@ def test_imp_stream_order( def baz(state: dict) -> dict: return {"a": state["a"] + "baz", "c": "something else"} - @imp(checkpointer=checkpointer) + @entrypoint(checkpointer=checkpointer) def graph(state: dict) -> dict: fut_foo = foo(state) fut_bar = bar(fut_foo.result()) diff --git a/libs/langgraph/tests/test_pregel_async.py b/libs/langgraph/tests/test_pregel_async.py index 07e16a538..c4e5174f6 100644 --- a/libs/langgraph/tests/test_pregel_async.py +++ b/libs/langgraph/tests/test_pregel_async.py @@ -62,7 +62,7 @@ from langgraph.constants import ( START, ) from langgraph.errors import InvalidUpdateError, MultipleSubgraphsError, NodeInterrupt -from langgraph.func import imp, task +from langgraph.func import entrypoint, task from langgraph.graph import END, Graph, StateGraph from langgraph.graph.message import MessageGraph, MessagesState, add_messages from langgraph.managed.shared_value import SharedValue @@ -2659,7 +2659,7 @@ async def test_imp_task(checkpointer_name: str) -> None: mapper_calls += 1 return str(input) * 2 - @imp(checkpointer=checkpointer) + @entrypoint(checkpointer=checkpointer) async def graph(input: list[int]) -> list[str]: futures = [mapper(i) for i in input] mapped = await asyncio.gather(*futures) @@ -2706,7 +2706,7 @@ async def test_imp_sync_from_async(checkpointer_name: str) -> None: def baz(state: dict) -> dict: return {"a": state["a"] + "baz", "c": "something else"} - @imp(checkpointer=checkpointer) + @entrypoint(checkpointer=checkpointer) def graph(state: dict) -> dict: fut_foo = foo(state) fut_bar = bar(fut_foo.result()) @@ -2738,7 +2738,7 @@ async def test_imp_stream_order(checkpointer_name: str) -> None: async def baz(state: dict) -> dict: return {"a": state["a"] + "baz", "c": "something else"} - @imp(checkpointer=checkpointer) + @entrypoint(checkpointer=checkpointer) async def graph(state: dict) -> dict: fut_foo = foo(state) fut_bar = bar(await fut_foo) From 09ca96471402d8594b3e9ca71e06d15a71d9868d Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Thu, 21 Nov 2024 08:55:07 -0800 Subject: [PATCH 16/58] Wire up retry policy --- libs/langgraph/langgraph/func/__init__.py | 2 +- libs/langgraph/langgraph/pregel/algo.py | 18 ++++++++++++++---- libs/langgraph/langgraph/pregel/runner.py | 12 ++++++++++-- libs/langgraph/langgraph/types.py | 6 ++++-- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/libs/langgraph/langgraph/func/__init__.py b/libs/langgraph/langgraph/func/__init__.py index 69e9b6c5d..4db234b81 100644 --- a/libs/langgraph/langgraph/func/__init__.py +++ b/libs/langgraph/langgraph/func/__init__.py @@ -48,7 +48,7 @@ def task( Callable[[Callable[P, T]], Callable[P, concurrent.futures.Future[T]]], ]: def _task(func: Callable[P, T]) -> Callable[P, concurrent.futures.Future[T]]: - return update_wrapper(partial(call, func), func) + return update_wrapper(partial(call, func, retry=retry), func) return _task diff --git a/libs/langgraph/langgraph/pregel/algo.py b/libs/langgraph/langgraph/pregel/algo.py index 330d46449..4e17dd39d 100644 --- a/libs/langgraph/langgraph/pregel/algo.py +++ b/libs/langgraph/langgraph/pregel/algo.py @@ -65,7 +65,13 @@ from langgraph.pregel.log import logger from langgraph.pregel.manager import ChannelsManager from langgraph.pregel.read import PregelNode from langgraph.store.base import BaseStore -from langgraph.types import All, LoopProtocol, PregelExecutableTask, PregelTask +from langgraph.types import ( + All, + LoopProtocol, + PregelExecutableTask, + PregelTask, + RetryPolicy, +) from langgraph.utils.config import merge_configs, patch_config GetNextVersion = Callable[[Optional[V], BaseChannel], V] @@ -100,14 +106,18 @@ class PregelTaskWrites(NamedTuple): class Call: - __slots__ = ("func", "input") + __slots__ = ("func", "input", "retry") func: Callable input: Any + retry: Optional[RetryPolicy] - def __init__(self, func: Callable, input: Any) -> None: + def __init__( + self, func: Callable, input: Any, *, retry: Optional[RetryPolicy] + ) -> None: self.func = func self.input = input + self.retry = retry def should_interrupt( @@ -545,7 +555,7 @@ def prepare_single_task( }, ), triggers, - None, + call.retry, None, task_id, task_path[:3], diff --git a/libs/langgraph/langgraph/pregel/runner.py b/libs/langgraph/langgraph/pregel/runner.py index 8decbedec..8e3f52ace 100644 --- a/libs/langgraph/langgraph/pregel/runner.py +++ b/libs/langgraph/langgraph/pregel/runner.py @@ -143,8 +143,12 @@ class PregelRunner: task: PregelExecutableTask, func: Callable[[Any], Union[Awaitable[Any], Any]], input: Any, + *, + retry: Optional[RetryPolicy] = None, ) -> concurrent.futures.Future[Any]: - (fut,) = writer(task, [(PUSH, None)], calls=[Call(func, input)]) + (fut,) = writer( + task, [(PUSH, None)], calls=[Call(func, input, retry=retry)] + ) assert fut is not None, "writer did not return a future for call" return fut @@ -320,8 +324,12 @@ class PregelRunner: task: PregelExecutableTask, func: Callable[[Any], Union[Awaitable[Any], Any]], input: Any, + *, + retry: Optional[RetryPolicy] = None, ) -> Union[asyncio.Future[Any], concurrent.futures.Future[Any]]: - (fut,) = writer(task, [(PUSH, None)], calls=[Call(func, input)]) + (fut,) = writer( + task, [(PUSH, None)], calls=[Call(func, input, retry=retry)] + ) assert fut is not None, "writer did not return a future for call" if asyncio.iscoroutinefunction(func): return fut diff --git a/libs/langgraph/langgraph/types.py b/libs/langgraph/langgraph/types.py index 5ce64b52b..c3bf175a2 100644 --- a/libs/langgraph/langgraph/types.py +++ b/libs/langgraph/langgraph/types.py @@ -372,12 +372,14 @@ T = TypeVar("T") def call( - func: str | Callable[P, T], *args: P.args, **kwargs: P.kwargs + func: str | Callable[P, T], + *args: P.args, + retry: Optional[RetryPolicy] = None, ) -> concurrent.futures.Future[T]: from langgraph.constants import CONFIG_KEY_CALL from langgraph.utils.config import get_configurable conf = get_configurable() impl = conf[CONFIG_KEY_CALL] - fut = impl(func, *args, **kwargs) + fut = impl(func, *args, retry=retry) return fut From 2fe38f394021c2e3f4d7169c791a1ee8d84054b9 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Thu, 21 Nov 2024 09:07:19 -0800 Subject: [PATCH 17/58] Fix get_state --- libs/langgraph/langgraph/func/__init__.py | 1 + libs/langgraph/tests/test_pregel.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/libs/langgraph/langgraph/func/__init__.py b/libs/langgraph/langgraph/func/__init__.py index 4db234b81..d990ae4a5 100644 --- a/libs/langgraph/langgraph/func/__init__.py +++ b/libs/langgraph/langgraph/func/__init__.py @@ -71,6 +71,7 @@ def entrypoint( channels={START: EphemeralValue(Any), END: LastValue(Any, END)}, input_channels=START, output_channels=END, + stream_channels=END, stream_mode="updates", checkpointer=checkpointer, store=store, diff --git a/libs/langgraph/tests/test_pregel.py b/libs/langgraph/tests/test_pregel.py index 8de87ef0e..cb7998430 100644 --- a/libs/langgraph/tests/test_pregel.py +++ b/libs/langgraph/tests/test_pregel.py @@ -2046,6 +2046,8 @@ def test_imp_stream_order( {"graph": {"a": "0foobarbaz", "c": "something else"}}, ] + assert graph.get_state(thread1).values == {"a": "0foobarbaz", "c": "something else"} + @pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_SYNC) def test_send_dedupe_on_resume( From 4c6323c585dc0d2e6999b5fe73a9699366004292 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 3 Dec 2024 13:54:01 -0800 Subject: [PATCH 18/58] Lint --- libs/langgraph/langgraph/utils/future.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/libs/langgraph/langgraph/utils/future.py b/libs/langgraph/langgraph/utils/future.py index d7b8718f6..eaad8e64d 100644 --- a/libs/langgraph/langgraph/utils/future.py +++ b/libs/langgraph/langgraph/utils/future.py @@ -17,7 +17,7 @@ def _get_loop(fut: asyncio.Future) -> asyncio.AbstractEventLoop: return fut._loop -def _convert_future_exc(exc): +def _convert_future_exc(exc: BaseException) -> BaseException: exc_class = type(exc) if exc_class is concurrent.futures.CancelledError: return asyncio.CancelledError(*exc.args) @@ -29,7 +29,10 @@ def _convert_future_exc(exc): return exc -def _set_concurrent_future_state(concurrent, source): +def _set_concurrent_future_state( + concurrent: concurrent.futures.Future, + source: AnyFuture, +) -> None: """Copy state from a future to a concurrent.futures.Future.""" assert source.done() if source.cancelled(): @@ -44,7 +47,7 @@ def _set_concurrent_future_state(concurrent, source): concurrent.set_result(result) -def _copy_future_state(source, dest): +def _copy_future_state(source: AnyFuture, dest: asyncio.Future) -> None: """Internal helper to copy state from another Future. The other Future may be a concurrent.futures.Future. @@ -82,20 +85,20 @@ def _chain_future(source: AnyFuture, destination: AnyFuture) -> None: source_loop = _get_loop(source) if asyncio.isfuture(source) else None dest_loop = _get_loop(destination) if asyncio.isfuture(destination) else None - def _set_state(future, other): + def _set_state(future: AnyFuture, other: AnyFuture) -> None: if asyncio.isfuture(future): _copy_future_state(other, future) else: _set_concurrent_future_state(future, other) - def _call_check_cancel(destination): + def _call_check_cancel(destination: AnyFuture) -> None: if destination.cancelled(): if source_loop is None or source_loop is dest_loop: source.cancel() else: source_loop.call_soon_threadsafe(source.cancel) - def _call_set_state(source): + def _call_set_state(source: AnyFuture) -> None: if destination.cancelled() and dest_loop is not None and dest_loop.is_closed(): return if dest_loop is None or dest_loop is source_loop: @@ -109,7 +112,7 @@ def _chain_future(source: AnyFuture, destination: AnyFuture) -> None: source.add_done_callback(_call_set_state) -def chain_future(source: AnyFuture, destination: AnyFuture) -> None: +def chain_future(source: AnyFuture, destination: concurrent.futures.Future) -> None: # adapted from asyncio.run_coroutine_threadsafe try: _chain_future(source, destination) From ec7bbe14b214f8b0e145899a866bb3254c4b95c7 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 3 Dec 2024 13:54:55 -0800 Subject: [PATCH 19/58] Lint --- libs/langgraph/langgraph/pregel/runner.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/libs/langgraph/langgraph/pregel/runner.py b/libs/langgraph/langgraph/pregel/runner.py index 8e3f52ace..6e68df66a 100644 --- a/libs/langgraph/langgraph/pregel/runner.py +++ b/libs/langgraph/langgraph/pregel/runner.py @@ -184,9 +184,7 @@ class PregelRunner: # add waiter task if requested if get_waiter is not None: futures[get_waiter()] = None - # execute tasks, and wait for one to fail or all to finish. - # each task is independent from all other concurrent tasks - # yield updates/debug output as each task finishes + # schedule tasks for t in tasks: if not t.writes: fut = self.submit( @@ -201,6 +199,9 @@ class PregelRunner: ) fut.add_done_callback(partial(self.commit, t)) futures[fut] = t + # execute tasks, and wait for one to fail or all to finish. + # each task is independent from all other concurrent tasks + # yield updates/debug output as each task finishes end_time = timeout + time.monotonic() if timeout else None while len(futures) > (1 if get_waiter is not None else 0): done, inflight = concurrent.futures.wait( @@ -334,7 +335,7 @@ class PregelRunner: if asyncio.iscoroutinefunction(func): return fut # adapted from asyncio.run_coroutine_threadsafe - sfut = concurrent.futures.Future() + sfut: concurrent.futures.Future = concurrent.futures.Future() loop.call_soon_threadsafe(chain_future, fut, sfut) return sfut @@ -372,9 +373,7 @@ class PregelRunner: # add waiter task if requested if get_waiter is not None: futures[get_waiter()] = None - # execute tasks, and wait for one to fail or all to finish. - # each task is independent from all other concurrent tasks - # yield updates/debug output as each task finishes + # schedule tasks for t in tasks: if not t.writes: fut = cast( @@ -395,6 +394,9 @@ class PregelRunner: ) fut.add_done_callback(partial(self.commit, t)) futures[fut] = t + # execute tasks, and wait for one to fail or all to finish. + # each task is independent from all other concurrent tasks + # yield updates/debug output as each task finishes end_time = timeout + loop.time() if timeout else None while len(futures) > (1 if get_waiter is not None else 0): done, inflight = await asyncio.wait( From 40d16593c7c1260dba8f7f97cd54de9a8720d7e5 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 3 Dec 2024 13:59:21 -0800 Subject: [PATCH 20/58] Lint --- libs/langgraph/langgraph/func/__init__.py | 18 +++++++++++++++++- libs/langgraph/langgraph/types.py | 22 +--------------------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/libs/langgraph/langgraph/func/__init__.py b/libs/langgraph/langgraph/func/__init__.py index d990ae4a5..d608f41f7 100644 --- a/libs/langgraph/langgraph/func/__init__.py +++ b/libs/langgraph/langgraph/func/__init__.py @@ -23,12 +23,28 @@ from langgraph.pregel.call import get_runnable_for_func from langgraph.pregel.read import PregelNode from langgraph.pregel.write import ChannelWrite, ChannelWriteEntry from langgraph.store.base import BaseStore -from langgraph.types import RetryPolicy, call +from langgraph.types import RetryPolicy P = ParamSpec("P") +P1 = TypeVar("P1") T = TypeVar("T") +def call( + func: Callable[[P1], T], + input: P1, + *, + retry: Optional[RetryPolicy] = None, +) -> concurrent.futures.Future[T]: + from langgraph.constants import CONFIG_KEY_CALL + from langgraph.utils.config import get_configurable + + conf = get_configurable() + impl = conf[CONFIG_KEY_CALL] + fut = impl(func, input, retry=retry) + return fut + + @overload def task( *, retry: Optional[RetryPolicy] = None diff --git a/libs/langgraph/langgraph/types.py b/libs/langgraph/langgraph/types.py index c3bf175a2..67c7e53f8 100644 --- a/libs/langgraph/langgraph/types.py +++ b/libs/langgraph/langgraph/types.py @@ -1,5 +1,3 @@ -import concurrent -import concurrent.futures import dataclasses import sys from collections import deque @@ -22,7 +20,7 @@ from typing import ( ) from langchain_core.runnables import Runnable, RunnableConfig -from typing_extensions import ParamSpec, Self +from typing_extensions import Self from langgraph.checkpoint.base import ( BaseCheckpointSaver, @@ -365,21 +363,3 @@ def interrupt(value: Any) -> Any: ), ) ) - - -P = ParamSpec("P") -T = TypeVar("T") - - -def call( - func: str | Callable[P, T], - *args: P.args, - retry: Optional[RetryPolicy] = None, -) -> concurrent.futures.Future[T]: - from langgraph.constants import CONFIG_KEY_CALL - from langgraph.utils.config import get_configurable - - conf = get_configurable() - impl = conf[CONFIG_KEY_CALL] - fut = impl(func, *args, retry=retry) - return fut From 2b77fdabee4b8de8bdcf88c304664a1bcbe978b7 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 3 Dec 2024 14:01:26 -0800 Subject: [PATCH 21/58] Lint --- libs/langgraph/langgraph/func/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/langgraph/langgraph/func/__init__.py b/libs/langgraph/langgraph/func/__init__.py index d608f41f7..2dda24754 100644 --- a/libs/langgraph/langgraph/func/__init__.py +++ b/libs/langgraph/langgraph/func/__init__.py @@ -8,12 +8,13 @@ from typing import ( Awaitable, Callable, Optional, - ParamSpec, TypeVar, Union, overload, ) +from typing_extensions import ParamSpec + from langgraph.channels.ephemeral_value import EphemeralValue from langgraph.channels.last_value import LastValue from langgraph.checkpoint.base import BaseCheckpointSaver From 007d7e72b124066dc1f96d2b203b0002b13d8f95 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 3 Dec 2024 15:04:55 -0800 Subject: [PATCH 22/58] Add test for cancellation --- libs/langgraph/langgraph/pregel/algo.py | 3 +- libs/langgraph/langgraph/pregel/runner.py | 24 +++++---- libs/langgraph/tests/test_pregel_async.py | 66 +++++++++++++++++++++++ 3 files changed, 83 insertions(+), 10 deletions(-) diff --git a/libs/langgraph/langgraph/pregel/algo.py b/libs/langgraph/langgraph/pregel/algo.py index 4e17dd39d..b41424fe9 100644 --- a/libs/langgraph/langgraph/pregel/algo.py +++ b/libs/langgraph/langgraph/pregel/algo.py @@ -43,6 +43,7 @@ from langgraph.constants import ( CONFIG_KEY_TASK_ID, CONFIG_KEY_WRITES, EMPTY_SEQ, + ERROR, INTERRUPT, NO_WRITES, NS_END, @@ -270,7 +271,7 @@ def apply_writes( pending_writes_by_managed: dict[str, list[Any]] = defaultdict(list) for task in tasks: for chan, val in task.writes: - if chan in (NO_WRITES, PUSH, RESUME, INTERRUPT, RETURN): + if chan in (NO_WRITES, PUSH, RESUME, INTERRUPT, RETURN, ERROR): pass elif chan == TASKS: # TODO: remove branch in 1.0 checkpoint["pending_sends"].append(val) diff --git a/libs/langgraph/langgraph/pregel/runner.py b/libs/langgraph/langgraph/pregel/runner.py index 6e68df66a..41c9e7e69 100644 --- a/libs/langgraph/langgraph/pregel/runner.py +++ b/libs/langgraph/langgraph/pregel/runner.py @@ -441,7 +441,12 @@ class PregelRunner: ) -> None: if fut is not None: exception = _exception(fut) - if exception: + if isinstance(exception, asyncio.CancelledError): + # for cancelled tasks, also save error in task, + # so loop can finish super-step + task.writes.append((ERROR, exception)) + self.put_writes(task.id, task.writes) + elif exception: if isinstance(exception, GraphInterrupt): # save interrupt to checkpointer if interrupts := [(INTERRUPT, i) for i in exception.args[0]]: @@ -472,11 +477,12 @@ def _should_stop_others( GraphInterrupts are not considered failures.""" for fut in done: if fut.cancelled(): - return True - if exc := fut.exception(): - return not isinstance(exc, GraphBubbleUp) - else: - return False + continue + elif exc := fut.exception(): + if not isinstance(exc, GraphBubbleUp): + return True + + return False def _exception( @@ -502,7 +508,9 @@ def _panic_or_proceed( done: set[Union[concurrent.futures.Future[Any], asyncio.Future[Any]]] = set() inflight: set[Union[concurrent.futures.Future[Any], asyncio.Future[Any]]] = set() for fut in futs: - if fut.done(): + if fut.cancelled(): + continue + elif fut.done(): done.add(fut) else: inflight.add(fut) @@ -515,8 +523,6 @@ def _panic_or_proceed( # raise the exception if panic: raise exc - else: - return if inflight: # if we got here means we timed out while inflight: diff --git a/libs/langgraph/tests/test_pregel_async.py b/libs/langgraph/tests/test_pregel_async.py index c4e5174f6..9f568d5c3 100644 --- a/libs/langgraph/tests/test_pregel_async.py +++ b/libs/langgraph/tests/test_pregel_async.py @@ -2648,6 +2648,10 @@ async def test_send_sequences(checkpointer_name: str) -> None: ] +@pytest.mark.skipif( + sys.version_info < (3, 11), + reason="Python 3.11+ is required for async contextvars support", +) @pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_ASYNC) async def test_imp_task(checkpointer_name: str) -> None: async with awith_checkpointer(checkpointer_name) as checkpointer: @@ -2690,6 +2694,64 @@ async def test_imp_task(checkpointer_name: str) -> None: assert mapper_calls == 2 +@pytest.mark.skipif( + sys.version_info < (3, 11), + reason="Python 3.11+ is required for async contextvars support", +) +@pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_ASYNC) +async def test_imp_task_cancel(checkpointer_name: str) -> None: + async with awith_checkpointer(checkpointer_name) as checkpointer: + mapper_calls = 0 + mapper_cancels = 0 + + @task() + async def mapper(input: int) -> str: + nonlocal mapper_calls, mapper_cancels + mapper_calls += 1 + try: + await asyncio.sleep(1) + except asyncio.CancelledError: + mapper_cancels += 1 + raise + return str(input) * 2 + + @entrypoint(checkpointer=checkpointer) + async def graph(input: list[int]) -> list[str]: + futures = [mapper(i) for i in input] + await asyncio.sleep(0.1) + futures.pop().cancel() # cancel one + mapped = await asyncio.gather(*futures) + answer = interrupt("question") + return [m + answer for m in mapped] + + thread1 = {"configurable": {"thread_id": "1"}} + assert [c async for c in graph.astream([0, 1], thread1)] == [ + {"mapper": "00"}, + { + "__interrupt__": ( + Interrupt( + value="question", + resumable=True, + ns=[AnyStr("graph:")], + when="during", + ), + ) + }, + ] + assert mapper_calls == 2 + assert mapper_cancels == 1 + + assert await graph.ainvoke(Command(resume="answer"), thread1) == [ + "00answer", + ] + assert mapper_calls == 3 + assert mapper_cancels == 2 + + +@pytest.mark.skipif( + sys.version_info < (3, 11), + reason="Python 3.11+ is required for async contextvars support", +) @pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_ASYNC) async def test_imp_sync_from_async(checkpointer_name: str) -> None: async with awith_checkpointer(checkpointer_name) as checkpointer: @@ -2722,6 +2784,10 @@ async def test_imp_sync_from_async(checkpointer_name: str) -> None: ] +@pytest.mark.skipif( + sys.version_info < (3, 11), + reason="Python 3.11+ is required for async contextvars support", +) @pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_ASYNC) async def test_imp_stream_order(checkpointer_name: str) -> None: async with awith_checkpointer(checkpointer_name) as checkpointer: From 4e8f4ce440b31336ab48d63ee4522c5c7ef5ebaf Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 3 Dec 2024 15:33:41 -0800 Subject: [PATCH 23/58] Update --- libs/scheduler-kafka/tests/test_subgraph.py | 6 ++++++ libs/scheduler-kafka/tests/test_subgraph_sync.py | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/libs/scheduler-kafka/tests/test_subgraph.py b/libs/scheduler-kafka/tests/test_subgraph.py index 4ab92676c..1e1f1e396 100644 --- a/libs/scheduler-kafka/tests/test_subgraph.py +++ b/libs/scheduler-kafka/tests/test_subgraph.py @@ -191,6 +191,7 @@ async def test_subgraph_w_interrupt( "__pregel_delegate": False, "__pregel_read": None, "__pregel_send": None, + "__pregel_call": None, "__pregel_ensure_latest": True, "__pregel_dedupe_tasks": True, "__pregel_resuming": False, @@ -257,6 +258,7 @@ async def test_subgraph_w_interrupt( "__pregel_delegate": False, "__pregel_read": None, "__pregel_send": None, + "__pregel_call": None, "__pregel_ensure_latest": True, "__pregel_dedupe_tasks": True, "__pregel_resuming": False, @@ -353,6 +355,7 @@ async def test_subgraph_w_interrupt( "__pregel_delegate": False, "__pregel_read": None, "__pregel_send": None, + "__pregel_call": None, "__pregel_ensure_latest": True, "__pregel_dedupe_tasks": True, "__pregel_resuming": False, @@ -459,6 +462,7 @@ async def test_subgraph_w_interrupt( "__pregel_delegate": False, "__pregel_read": None, "__pregel_send": None, + "__pregel_call": None, "__pregel_ensure_latest": True, "__pregel_dedupe_tasks": True, "__pregel_resuming": True, @@ -520,6 +524,7 @@ async def test_subgraph_w_interrupt( "__pregel_delegate": False, "__pregel_read": None, "__pregel_send": None, + "__pregel_call": None, "__pregel_ensure_latest": True, "__pregel_dedupe_tasks": True, "__pregel_resuming": True, @@ -637,6 +642,7 @@ async def test_subgraph_w_interrupt( "__pregel_delegate": False, "__pregel_read": None, "__pregel_send": None, + "__pregel_call": None, "__pregel_ensure_latest": True, "__pregel_dedupe_tasks": True, "__pregel_resuming": True, diff --git a/libs/scheduler-kafka/tests/test_subgraph_sync.py b/libs/scheduler-kafka/tests/test_subgraph_sync.py index 5fa43998a..210312b3b 100644 --- a/libs/scheduler-kafka/tests/test_subgraph_sync.py +++ b/libs/scheduler-kafka/tests/test_subgraph_sync.py @@ -190,6 +190,7 @@ def test_subgraph_w_interrupt( "__pregel_delegate": False, "__pregel_read": None, "__pregel_send": None, + "__pregel_call": None, "__pregel_ensure_latest": True, "__pregel_dedupe_tasks": True, "__pregel_resuming": False, @@ -256,6 +257,7 @@ def test_subgraph_w_interrupt( "__pregel_delegate": False, "__pregel_read": None, "__pregel_send": None, + "__pregel_call": None, "__pregel_ensure_latest": True, "__pregel_store": None, "__pregel_dedupe_tasks": True, @@ -352,6 +354,7 @@ def test_subgraph_w_interrupt( "__pregel_delegate": False, "__pregel_read": None, "__pregel_send": None, + "__pregel_call": None, "__pregel_ensure_latest": True, "__pregel_dedupe_tasks": True, "__pregel_store": None, @@ -457,6 +460,7 @@ def test_subgraph_w_interrupt( "__pregel_delegate": False, "__pregel_read": None, "__pregel_send": None, + "__pregel_call": None, "__pregel_ensure_latest": True, "__pregel_dedupe_tasks": True, "__pregel_store": None, @@ -518,6 +522,7 @@ def test_subgraph_w_interrupt( "__pregel_delegate": False, "__pregel_read": None, "__pregel_send": None, + "__pregel_call": None, "__pregel_ensure_latest": True, "__pregel_dedupe_tasks": True, "__pregel_store": None, @@ -635,6 +640,7 @@ def test_subgraph_w_interrupt( "__pregel_delegate": False, "__pregel_read": None, "__pregel_send": None, + "__pregel_call": None, "__pregel_ensure_latest": True, "__pregel_dedupe_tasks": True, "__pregel_resuming": True, From eb593d47ddb4226d40fbd1ff3630a85511264ff7 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 3 Dec 2024 16:37:02 -0800 Subject: [PATCH 24/58] Fix writes for task being saved against next checkpoint id --- libs/langgraph/langgraph/pregel/loop.py | 9 ++++----- libs/langgraph/langgraph/pregel/runner.py | 4 ++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/libs/langgraph/langgraph/pregel/loop.py b/libs/langgraph/langgraph/pregel/loop.py index cb141c4a1..678e355ab 100644 --- a/libs/langgraph/langgraph/pregel/loop.py +++ b/libs/langgraph/langgraph/pregel/loop.py @@ -290,16 +290,15 @@ class PregelLoop(LoopProtocol): if self.checkpointer_put_writes is not None: self.submit( self.checkpointer_put_writes, - { - **self.checkpoint_config, - CONF: { - **self.checkpoint_config[CONF], + patch_configurable( + self.checkpoint_config, + { CONFIG_KEY_CHECKPOINT_NS: self.config[CONF].get( CONFIG_KEY_CHECKPOINT_NS, "" ), CONFIG_KEY_CHECKPOINT_ID: self.checkpoint["id"], }, - }, + ), writes, task_id, ) diff --git a/libs/langgraph/langgraph/pregel/runner.py b/libs/langgraph/langgraph/pregel/runner.py index 41c9e7e69..5ba0209c8 100644 --- a/libs/langgraph/langgraph/pregel/runner.py +++ b/libs/langgraph/langgraph/pregel/runner.py @@ -423,6 +423,10 @@ class PregelRunner: break # give control back to the caller yield + # wait for pending done callbacks + # if a 2nd future finishes while `wait` is returning, it's possible + # that done callbacks for the 2nd future aren't called until next tick + await asyncio.sleep(0) # cancel waiter task for fut in futures: fut.cancel() From e1f65012e6a76b0cf1f40deecb92e1ee74b7ce4e Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 3 Dec 2024 17:11:24 -0800 Subject: [PATCH 25/58] Fix --- libs/langgraph/tests/test_pregel_async.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/langgraph/tests/test_pregel_async.py b/libs/langgraph/tests/test_pregel_async.py index 9f568d5c3..f43e76d31 100644 --- a/libs/langgraph/tests/test_pregel_async.py +++ b/libs/langgraph/tests/test_pregel_async.py @@ -9809,14 +9809,14 @@ async def test_stream_subgraphs_during_execution(checkpointer_name: str) -> None ), (FloatBetween(0.2, 0.4), ((), {"outer_1": {"my_key": " and parallel"}})), ( - FloatBetween(0.5, 0.7), + FloatBetween(0.5, 0.8), ( (AnyStr("inner:"),), {"inner_2": {"my_key": " and there", "my_other_key": "got here"}}, ), ), - (FloatBetween(0.5, 0.7), ((), {"inner": {"my_key": "got here and there"}})), - (FloatBetween(0.5, 0.7), ((), {"outer_2": {"my_key": " and back again"}})), + (FloatBetween(0.5, 0.8), ((), {"inner": {"my_key": "got here and there"}})), + (FloatBetween(0.5, 0.8), ((), {"outer_2": {"my_key": " and back again"}})), ] From 9733db03c537a82ce5b2a27d607962589a1b35b9 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Wed, 4 Dec 2024 12:04:12 -0800 Subject: [PATCH 26/58] Wait until next tick to start send task --- libs/langgraph/langgraph/pregel/executor.py | 23 ++++++++++++++++++++- libs/langgraph/langgraph/pregel/runner.py | 5 +++++ libs/langgraph/tests/test_pregel.py | 1 + 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/libs/langgraph/langgraph/pregel/executor.py b/libs/langgraph/langgraph/pregel/executor.py index 70aea29e3..46a4e6036 100644 --- a/libs/langgraph/langgraph/pregel/executor.py +++ b/libs/langgraph/langgraph/pregel/executor.py @@ -1,6 +1,7 @@ import asyncio import concurrent.futures import sys +import time from contextlib import ExitStack from contextvars import copy_context from types import TracebackType @@ -34,6 +35,7 @@ class Submit(Protocol[P, T]): __name__: Optional[str] = None, __cancel_on_exit__: bool = False, __reraise_on_exit__: bool = True, + __next_tick__: bool = False, **kwargs: P.kwargs, ) -> concurrent.futures.Future[T]: ... @@ -58,9 +60,13 @@ class BackgroundExecutor(ContextManager): __name__: Optional[str] = None, # currently not used in sync version __cancel_on_exit__: bool = False, # for sync, can cancel only if not started __reraise_on_exit__: bool = True, + __next_tick__: bool = False, **kwargs: P.kwargs, ) -> concurrent.futures.Future[T]: - task = self.executor.submit(fn, *args, **kwargs) + if __next_tick__: + task = self.executor.submit(next_tick, fn, *args, **kwargs) + else: + task = self.executor.submit(fn, *args, **kwargs) self.tasks[task] = (__cancel_on_exit__, __reraise_on_exit__) task.add_done_callback(self.done) return task @@ -137,11 +143,14 @@ class AsyncBackgroundExecutor(AsyncContextManager): __name__: Optional[str] = None, __cancel_on_exit__: bool = False, __reraise_on_exit__: bool = True, + __next_tick__: bool = False, **kwargs: P.kwargs, ) -> asyncio.Task[T]: coro = cast(Coroutine[None, None, T], fn(*args, **kwargs)) if self.semaphore: coro = gated(self.semaphore, coro) + if __next_tick__: + coro = anext_tick(coro) if self.context_not_supported: task = self.loop.create_task(coro, name=__name__) else: @@ -197,3 +206,15 @@ async def gated(semaphore: asyncio.Semaphore, coro: Coroutine[None, None, T]) -> """A coroutine that waits for a semaphore before running another coroutine.""" async with semaphore: return await coro + + +def next_tick(fn: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> T: + """A function that yields control to other threads before running another function.""" + time.sleep(0) + return fn(*args, **kwargs) + + +async def anext_tick(coro: Coroutine[None, None, T]) -> T: + """A coroutine that yields control to event loop before running another coroutine.""" + await asyncio.sleep(0) + return await coro diff --git a/libs/langgraph/langgraph/pregel/runner.py b/libs/langgraph/langgraph/pregel/runner.py index 5ba0209c8..e60ae599b 100644 --- a/libs/langgraph/langgraph/pregel/runner.py +++ b/libs/langgraph/langgraph/pregel/runner.py @@ -133,6 +133,7 @@ class PregelRunner: CONFIG_KEY_CALL: partial(call, next_task), }, __reraise_on_exit__=reraise, + __next_tick__=True, ) fut.add_done_callback(partial(self.commit, next_task)) futures[fut] = next_task @@ -228,6 +229,10 @@ class PregelRunner: break # give control back to the caller yield + # wait for pending done callbacks + # if a 2nd future finishes while `wait` is returning, it's possible + # that done callbacks for the 2nd future aren't called until next tick + time.sleep(0) # panic on failure or timeout _panic_or_proceed( done_futures.union(f for f, t in futures.items() if t is not None), diff --git a/libs/langgraph/tests/test_pregel.py b/libs/langgraph/tests/test_pregel.py index cb7998430..9948be87e 100644 --- a/libs/langgraph/tests/test_pregel.py +++ b/libs/langgraph/tests/test_pregel.py @@ -5837,6 +5837,7 @@ def test_state_graph_packets( @tool() def search_api(query: str) -> str: """Searches the API for the query.""" + time.sleep(0.1) return f"result for {query}" tools = [search_api] From de86a46b3d17091f2862cab997315d0effb3bdb8 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Wed, 4 Dec 2024 12:05:32 -0800 Subject: [PATCH 27/58] Comment --- libs/langgraph/langgraph/pregel/runner.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libs/langgraph/langgraph/pregel/runner.py b/libs/langgraph/langgraph/pregel/runner.py index e60ae599b..e680518a5 100644 --- a/libs/langgraph/langgraph/pregel/runner.py +++ b/libs/langgraph/langgraph/pregel/runner.py @@ -133,6 +133,8 @@ class PregelRunner: CONFIG_KEY_CALL: partial(call, next_task), }, __reraise_on_exit__=reraise, + # starting a new task in the next tick ensures + # updates from this tick are committed/streamed first __next_tick__=True, ) fut.add_done_callback(partial(self.commit, next_task)) @@ -319,6 +321,9 @@ class PregelRunner: __name__=t.name, __cancel_on_exit__=True, __reraise_on_exit__=reraise, + # starting a new task in the next tick ensures + # updates from this tick are committed/streamed first + __next_tick__=True, ), ) fut.add_done_callback(partial(self.commit, next_task)) From 2fa2469967148e9cd10a34bfeed46adaad265786 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Wed, 4 Dec 2024 15:18:15 -0800 Subject: [PATCH 28/58] Update --- libs/langgraph/langgraph/pregel/algo.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libs/langgraph/langgraph/pregel/algo.py b/libs/langgraph/langgraph/pregel/algo.py index b41424fe9..3adea073a 100644 --- a/libs/langgraph/langgraph/pregel/algo.py +++ b/libs/langgraph/langgraph/pregel/algo.py @@ -553,6 +553,13 @@ def prepare_single_task( }, CONFIG_KEY_CHECKPOINT_ID: None, CONFIG_KEY_CHECKPOINT_NS: task_checkpoint_ns, + CONFIG_KEY_WRITES: [ + w + for w in pending_writes + + configurable.get(CONFIG_KEY_WRITES, []) + if w[0] in (NULL_TASK_ID, task_id) + ], + CONFIG_KEY_SCRATCHPAD: {}, }, ), triggers, From 9f73dfa8d593af194150af37f51011346dab2a9f Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Wed, 4 Dec 2024 17:43:05 -0800 Subject: [PATCH 29/58] Fix --- libs/langgraph/langgraph/graph/graph.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libs/langgraph/langgraph/graph/graph.py b/libs/langgraph/langgraph/graph/graph.py index 4ecb03f5a..5e2739f02 100644 --- a/libs/langgraph/langgraph/graph/graph.py +++ b/libs/langgraph/langgraph/graph/graph.py @@ -630,10 +630,9 @@ class CompiledGraph(Pregel): return graph - def _repr_mimebundle_(self, **kwargs) -> dict[str, Any]: + def _repr_mimebundle_(self, **kwargs: Any) -> dict[str, Any]: """Mime bundle used by Jupyter to display the graph""" - output = { + return { "text/plain": repr(self), "image/png": self.get_graph().draw_mermaid_png(), } - return output From 1a46537c3a57c4cfc3ed307eefb3f4664d490ce9 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Thu, 5 Dec 2024 05:48:00 -0800 Subject: [PATCH 30/58] Codeblock ref rendering (#2649) --- libs/checkpoint-postgres/langgraph/store/postgres/base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/checkpoint-postgres/langgraph/store/postgres/base.py b/libs/checkpoint-postgres/langgraph/store/postgres/base.py index 839b2429e..84dd70364 100644 --- a/libs/checkpoint-postgres/langgraph/store/postgres/base.py +++ b/libs/checkpoint-postgres/langgraph/store/postgres/base.py @@ -573,6 +573,7 @@ class PostgresStore(BaseStore, BasePostgresStore[_pg_internal.Conn]): # Search by similarity results = store.search(("docs",), query="python programming") + ``` Note: Semantic search is disabled by default. You can enable it by providing an `index` configuration From 4b83103cf2d7df6b48c4ca7f886509bc11ab6d50 Mon Sep 17 00:00:00 2001 From: Vadym Barda Date: Thu, 5 Dec 2024 09:11:00 -0500 Subject: [PATCH 31/58] docs: relax pinned version in langgraph server tutorial (#2651) --- docs/docs/tutorials/langgraph-platform/local-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/tutorials/langgraph-platform/local-server.md b/docs/docs/tutorials/langgraph-platform/local-server.md index 0b57db2bd..359c164c1 100644 --- a/docs/docs/tutorials/langgraph-platform/local-server.md +++ b/docs/docs/tutorials/langgraph-platform/local-server.md @@ -10,7 +10,7 @@ This is a quick start guide to help you get a LangGraph app up and running local ## Install the LangGraph CLI ```bash -pip install "langgraph-cli[inmem]==0.1.58" python-dotenv +pip install -U "langgraph-cli[inmem]" python-dotenv ``` ## 🌱 Create a LangGraph App From cf961a286cf8a08f791336947070f6234d827ad8 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Thu, 5 Dec 2024 17:14:07 +0100 Subject: [PATCH 32/58] fix(sdk-js): rename Command["send"] to `goto` --- libs/sdk-js/src/types.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/sdk-js/src/types.ts b/libs/sdk-js/src/types.ts index 0073c5962..6a668ef4c 100644 --- a/libs/sdk-js/src/types.ts +++ b/libs/sdk-js/src/types.ts @@ -40,9 +40,11 @@ export interface Command { resume?: unknown; /** - * A single, or array of `Send` commands to trigger nodes. + * Determine the next node to navigate to. Can be one of the following: + * - Name(s) of the node names to navigate to next. + * - `Send` command(s) to execute node(s) with provided input. */ - send?: Send | Send[]; + goto?: Send | Send[] | string | string[]; } interface RunsInvokePayload { From b3bf4dd43c0fc9f518b87e832fecd868aec05721 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Thu, 5 Dec 2024 09:50:36 -0800 Subject: [PATCH 33/58] [docs] Update guidance on min bounds for deployment (#2652) --- docs/docs/cloud/deployment/setup.md | 4 ++-- docs/docs/cloud/deployment/setup_pyproject.md | 4 ++-- docs/docs/cloud/reference/cli.md | 5 +++++ docs/docs/concepts/langgraph_cli.md | 5 +++++ 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/docs/docs/cloud/deployment/setup.md b/docs/docs/cloud/deployment/setup.md index c1e0359ee..42e956e70 100644 --- a/docs/docs/cloud/deployment/setup.md +++ b/docs/docs/cloud/deployment/setup.md @@ -36,8 +36,8 @@ Dependencies can optionally be specified in one of the following files: `pyproje The dependencies below will be included in the image, you can also use them in your code, as long as with a compatible version range: ``` -langgraph>=0.2.30,<0.3.0 -langgraph-checkpoint>=1.0.14 +langgraph>=0.2.56,<0.3.0 +langgraph-checkpoint>=2.0.5,<3.0 langchain-core>=0.2.38,<0.4.0 langsmith>=0.1.63 orjson>=3.9.7 diff --git a/docs/docs/cloud/deployment/setup_pyproject.md b/docs/docs/cloud/deployment/setup_pyproject.md index 09e1a4975..ccb02a79d 100644 --- a/docs/docs/cloud/deployment/setup_pyproject.md +++ b/docs/docs/cloud/deployment/setup_pyproject.md @@ -36,8 +36,8 @@ Dependencies can optionally be specified in one of the following files: `pyproje The dependencies below will be included in the image, you can also use them in your code, as long as with a compatible version range: ``` -langgraph>=0.2.30,<0.3.0 -langgraph-checkpoint>=1.0.14 +langgraph>=0.2.56,<0.3.0 +langgraph-checkpoint>=2.0.5,<3.0 langchain-core>=0.2.38,<0.4.0 langsmith>=0.1.63 orjson>=3.9.7 diff --git a/docs/docs/cloud/reference/cli.md b/docs/docs/cloud/reference/cli.md index 914611ffe..6503fb583 100644 --- a/docs/docs/cloud/reference/cli.md +++ b/docs/docs/cloud/reference/cli.md @@ -134,6 +134,11 @@ langgraph [OPTIONS] COMMAND [ARGS] Run LangGraph API server in development mode with hot reloading and debugging capabilities. This lightweight server requires no Docker installation and is suitable for development and testing. State is persisted to a local directory. +!!! note "Python only" + + Currently, the CLI only supports Python >= 3.11. + JS support is coming soon. + **Installation** This command requires the "inmem" extra to be installed: diff --git a/docs/docs/concepts/langgraph_cli.md b/docs/docs/concepts/langgraph_cli.md index 0b930b45b..a302eb622 100644 --- a/docs/docs/concepts/langgraph_cli.md +++ b/docs/docs/concepts/langgraph_cli.md @@ -33,6 +33,11 @@ The `langgraph build` command builds a Docker image for the [LangGraph API serve !!! note "New in version 0.1.55" The `langgraph dev` command was introduced in langgraph-cli version 0.1.55. +!!! note "Python only" + + Currently, the CLI only supports Python >= 3.11. + JS support is coming soon. + The `langgraph dev` command starts a lightweight development server that requires no Docker installation. This server is ideal for rapid development and testing, with features like: - Hot reloading: Changes to your code are automatically detected and reloaded From 0f0e31df2413f3a5c547329e9f71c9524d6d8d7a Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:52:44 -0800 Subject: [PATCH 34/58] Nicer item repr (#2655) --- libs/checkpoint/langgraph/store/base/__init__.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/checkpoint/langgraph/store/base/__init__.py b/libs/checkpoint/langgraph/store/base/__init__.py index b2ab49527..c635e43ed 100644 --- a/libs/checkpoint/langgraph/store/base/__init__.py +++ b/libs/checkpoint/langgraph/store/base/__init__.py @@ -80,13 +80,16 @@ class Item: def dict(self) -> dict: return { - "value": self.value, - "key": self.key, "namespace": list(self.namespace), + "key": self.key, + "value": self.value, "created_at": self.created_at.isoformat(), "updated_at": self.updated_at.isoformat(), } + def __repr__(self) -> str: + return f"Item({', '.join(f'{k}={v!r}' for k, v in self.dict().items())})" + class SearchItem(Item): """Represents an item returned from a search operation with additional metadata.""" From aa4fea48ddf8fc58c9cb301872dd063d57a4a8a5 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Thu, 5 Dec 2024 13:47:38 -0800 Subject: [PATCH 35/58] lib: Add support for returning multiple commands from a node --- libs/langgraph/langgraph/graph/state.py | 147 +++++++++++++++-------- libs/langgraph/langgraph/pregel/io.py | 6 +- libs/langgraph/langgraph/pregel/write.py | 71 ++++++----- libs/langgraph/langgraph/types.py | 13 +- libs/langgraph/tests/test_pregel.py | 14 +-- 5 files changed, 152 insertions(+), 99 deletions(-) diff --git a/libs/langgraph/langgraph/graph/state.py b/libs/langgraph/langgraph/graph/state.py index e63f25111..0462008c8 100644 --- a/libs/langgraph/langgraph/graph/state.py +++ b/libs/langgraph/langgraph/graph/state.py @@ -51,7 +51,11 @@ from langgraph.managed.base import ( is_writable_managed_value, ) from langgraph.pregel.read import ChannelRead, PregelNode -from langgraph.pregel.write import SKIP_WRITE, ChannelWrite, ChannelWriteEntry +from langgraph.pregel.write import ( + ChannelWrite, + ChannelWriteEntry, + ChannelWriteTupleEntry, +) from langgraph.store.base import BaseStore from langgraph.types import All, Checkpointer, Command, RetryPolicy from langgraph.utils.fields import get_field_default @@ -608,33 +612,53 @@ class CompiledStateGraph(CompiledGraph): if is_writable_managed_value(v) ] - def _get_root(input: Any) -> Any: - if isinstance(input, Command): - if input.graph == Command.PARENT: - return SKIP_WRITE - return input.update - else: - return input - - # to avoid name collision below - node_key = key - - def _get_state_key(input: Union[None, dict, Any], *, key: str) -> Any: - if input is None: - return SKIP_WRITE - elif isinstance(input, dict): - if all(k not in output_keys for k in input): - raise InvalidUpdateError( - f"Expected node {node_key} to update at least one of {output_keys}, got {input}" - ) - return input.get(key, SKIP_WRITE) + def _get_root(input: Any) -> Optional[Sequence[tuple[str, Any]]]: + if ( + isinstance(input, (list, tuple)) + and input + and all(isinstance(i, Command) for i in input) + ): + updates: list[tuple[str, Any]] = [] + for i in input: + if i.graph == Command.PARENT: + continue + updates.extend(i._update_as_tuples()) + return updates elif isinstance(input, Command): if input.graph == Command.PARENT: - return SKIP_WRITE - return _get_state_key(input.update, key=key) + return () + return input._update_as_tuples() + elif input is not None: + return [("__root__", input)] + + def _get_updates( + input: Union[None, dict, Any], + ) -> Optional[Sequence[tuple[str, Any]]]: + if input is None: + return None + elif isinstance(input, dict): + return [(k, v) for k, v in input.items() if k in output_keys] + elif isinstance(input, Command): + if input.graph == Command.PARENT: + return None + return input._update_as_tuples() + elif ( + isinstance(input, (list, tuple)) + and input + and all(isinstance(i, Command) for i in input) + ): + updates: list[tuple[str, Any]] = [] + for i in input: + if i.graph == Command.PARENT: + continue + updates.extend(i._update_as_tuples()) + return updates elif get_type_hints(type(input)): - value = getattr(input, key, SKIP_WRITE) - return value if value is not None else SKIP_WRITE + return [ + (k, getattr(input, k)) + for k in output_keys + if getattr(input, k, None) is not None + ] else: msg = create_error_message( message=f"Expected dict, got {input}", @@ -643,14 +667,11 @@ class CompiledStateGraph(CompiledGraph): raise InvalidUpdateError(msg) # state updaters - write_entries = ( - [ChannelWriteEntry("__root__", skip_none=True, mapper=_get_root)] - if output_keys == ["__root__"] - else [ - ChannelWriteEntry(key, mapper=partial(_get_state_key, key=key)) - for key in output_keys - ] - ) + write_entries = [ + ChannelWriteTupleEntry( + mapper=_get_root if output_keys == ["__root__"] else _get_updates + ) + ] # add node and output channel if key == START: @@ -811,34 +832,54 @@ def _coerce_state(schema: Type[Any], input: dict[str, Any]) -> dict[str, Any]: def _control_branch(value: Any) -> Sequence[Union[str, Send]]: if isinstance(value, Send): return [value] - if not isinstance(value, Command): - return EMPTY_SEQ - if value.graph == Command.PARENT: - raise ParentCommand(value) - rtn: list[Union[str, Send]] = [] - if isinstance(value.goto, Send): - rtn.append(value.goto) - elif isinstance(value.goto, str): - rtn.append(value.goto) + commands: list[Command] = [] + if isinstance(value, Command): + commands.append(value) + elif ( + isinstance(value, (list, tuple)) + and value + and all(isinstance(i, Command) for i in value) + ): + commands.extend(value) else: - rtn.extend(value.goto) + return EMPTY_SEQ + rtn: list[Union[str, Send]] = [] + for command in commands: + if command.graph == Command.PARENT: + raise ParentCommand(command) + if isinstance(command.goto, Send): + rtn.append(command.goto) + elif isinstance(command.goto, str): + rtn.append(command.goto) + else: + rtn.extend(command.goto) return rtn async def _acontrol_branch(value: Any) -> Sequence[Union[str, Send]]: if isinstance(value, Send): return [value] - if not isinstance(value, Command): - return EMPTY_SEQ - if value.graph == Command.PARENT: - raise ParentCommand(value) - rtn: list[Union[str, Send]] = [] - if isinstance(value.goto, Send): - rtn.append(value.goto) - elif isinstance(value.goto, str): - rtn.append(value.goto) + commands: list[Command] = [] + if isinstance(value, Command): + commands.append(value) + elif ( + isinstance(value, (list, tuple)) + and value + and all(isinstance(i, Command) for i in value) + ): + commands.extend(value) else: - rtn.extend(value.goto) + return EMPTY_SEQ + rtn: list[Union[str, Send]] = [] + for command in commands: + if command.graph == Command.PARENT: + raise ParentCommand(command) + if isinstance(command.goto, Send): + rtn.append(command.goto) + elif isinstance(command.goto, str): + rtn.append(command.goto) + else: + rtn.extend(command.goto) return rtn diff --git a/libs/langgraph/langgraph/pregel/io.py b/libs/langgraph/langgraph/pregel/io.py index b2596d3ad..b3d6845b5 100644 --- a/libs/langgraph/langgraph/pregel/io.py +++ b/libs/langgraph/langgraph/pregel/io.py @@ -95,11 +95,7 @@ def map_command( else: yield (NULL_TASK_ID, RESUME, cmd.resume) if cmd.update: - if not isinstance(cmd.update, dict): - raise TypeError( - f"Expected cmd.update to be a dict mapping channel names to update values, got {type(cmd.update).__name__}" - ) - for k, v in cmd.update.items(): + for k, v in cmd._update_as_tuples(): yield (NULL_TASK_ID, k, v) diff --git a/libs/langgraph/langgraph/pregel/write.py b/libs/langgraph/langgraph/pregel/write.py index 3af0fe5e9..baee23ab2 100644 --- a/libs/langgraph/langgraph/pregel/write.py +++ b/libs/langgraph/langgraph/pregel/write.py @@ -36,31 +36,40 @@ class ChannelWriteEntry(NamedTuple): """Function to transform the value before writing.""" +class ChannelWriteTupleEntry(NamedTuple): + mapper: Callable[[Any], Sequence[tuple[str, Any]]] + """Function to extract tuples from value.""" + value: Any = PASSTHROUGH + """Value to write, or PASSTHROUGH to use the input.""" + + class ChannelWrite(RunnableCallable): - """Implements th logic for sending writes to CONFIG_KEY_SEND. + """Implements the logic for sending writes to CONFIG_KEY_SEND. Can be used as a runnable or as a static method to call imperatively.""" - writes: list[Union[ChannelWriteEntry, Send]] + writes: list[Union[ChannelWriteEntry, ChannelWriteTupleEntry, Send]] """Sequence of write entries or Send objects to write.""" require_at_least_one_of: Optional[Sequence[str]] """If defined, at least one of these channels must be written to.""" def __init__( self, - writes: Sequence[Union[ChannelWriteEntry, Send]], + writes: Sequence[Union[ChannelWriteEntry, ChannelWriteTupleEntry, Send]], *, tags: Optional[Sequence[str]] = None, require_at_least_one_of: Optional[Sequence[str]] = None, ): super().__init__(func=self._write, afunc=self._awrite, name=None, tags=tags) - self.writes = cast(list[Union[ChannelWriteEntry, Send]], writes) + self.writes = cast( + list[Union[ChannelWriteEntry, ChannelWriteTupleEntry, Send]], writes + ) self.require_at_least_one_of = require_at_least_one_of def get_name( self, suffix: Optional[str] = None, *, name: Optional[str] = None ) -> str: if not name: - name = f"ChannelWrite<{','.join(w.channel if isinstance(w, ChannelWriteEntry) else w.node for w in self.writes)}>" + name = f"ChannelWrite<{','.join(w.channel if isinstance(w, ChannelWriteEntry) else '...' if isinstance(w, ChannelWriteTupleEntry) else w.node for w in self.writes)}>" return super().get_name(suffix, name=name) @property @@ -79,6 +88,8 @@ class ChannelWrite(RunnableCallable): writes = [ ChannelWriteEntry(write.channel, input, write.skip_none, write.mapper) if isinstance(write, ChannelWriteEntry) and write.value is PASSTHROUGH + else ChannelWriteTupleEntry(write.mapper, input) + if isinstance(write, ChannelWriteTupleEntry) and write.value is PASSTHROUGH else write for write in self.writes ] @@ -93,6 +104,8 @@ class ChannelWrite(RunnableCallable): writes = [ ChannelWriteEntry(write.channel, input, write.skip_none, write.mapper) if isinstance(write, ChannelWriteEntry) and write.value is PASSTHROUGH + else ChannelWriteTupleEntry(write.mapper, input) + if isinstance(write, ChannelWriteTupleEntry) and write.value is PASSTHROUGH else write for write in self.writes ] @@ -106,7 +119,7 @@ class ChannelWrite(RunnableCallable): @staticmethod def do_write( config: RunnableConfig, - writes: Sequence[Union[ChannelWriteEntry, Send]], + writes: Sequence[Union[ChannelWriteEntry, ChannelWriteTupleEntry, Send]], require_at_least_one_of: Optional[Sequence[str]] = None, ) -> None: # validate @@ -118,32 +131,36 @@ class ChannelWrite(RunnableCallable): ) if w.value is PASSTHROUGH: raise InvalidUpdateError("PASSTHROUGH value must be replaced") - # split packets and entries - sends = [ - (PUSH if FF_SEND_V2 else TASKS, packet) - for packet in writes - if isinstance(packet, Send) - ] - entries = [write for write in writes if isinstance(write, ChannelWriteEntry)] - # process entries into values - values = [ - write.mapper(write.value) if write.mapper is not None else write.value - for write in entries - ] - values = [ - (write.channel, val) - for val, write in zip(values, entries) - if not write.skip_none or val is not None - ] - # filter out SKIP_WRITE values - filtered = [(chan, val) for chan, val in values if val is not SKIP_WRITE] + if isinstance(w, ChannelWriteTupleEntry): + if w.value is PASSTHROUGH: + raise InvalidUpdateError("PASSTHROUGH value must be replaced") + # assemble writes + tuples: list[tuple[str, Any]] = [] + print(writes) + for w in writes: + if isinstance(w, Send): + tuples.append((PUSH if FF_SEND_V2 else TASKS, w)) + elif isinstance(w, ChannelWriteTupleEntry): + if ww := w.mapper(w.value): + tuples.extend(ww) + elif isinstance(w, ChannelWriteEntry): + value = w.mapper(w.value) if w.mapper is not None else w.value + if value is SKIP_WRITE: + continue + if w.skip_none and value is None: + continue + tuples.append((w.channel, value)) + else: + raise ValueError(f"Invalid write entry: {w}") + print(tuples, require_at_least_one_of) + # assert required channels if require_at_least_one_of is not None: - if not {chan for chan, _ in filtered} & set(require_at_least_one_of): + if not {chan for chan, _ in tuples} & set(require_at_least_one_of): raise InvalidUpdateError( f"Must write to at least one of {require_at_least_one_of}" ) write: TYPE_SEND = config[CONF][CONFIG_KEY_SEND] - write(sends + filtered) + write(tuples) @staticmethod def is_writer(runnable: Runnable) -> bool: diff --git a/libs/langgraph/langgraph/types.py b/libs/langgraph/langgraph/types.py index 3eb4536aa..645bfb67b 100644 --- a/libs/langgraph/langgraph/types.py +++ b/libs/langgraph/langgraph/types.py @@ -263,7 +263,7 @@ class Command(Generic[N]): """ graph: Optional[str] = None - update: Optional[dict[str, Any]] = None + update: Union[dict[str, Any], Sequence[tuple[str, Any]]] = () resume: Optional[Union[Any, dict[str, Any]]] = None goto: Union[Send, Sequence[Union[Send, str]], str] = () @@ -276,6 +276,17 @@ class Command(Generic[N]): ) return f"Command({contents})" + def _update_as_tuples(self) -> Sequence[tuple[str, Any]]: + if isinstance(self.update, dict): + return list(self.update.items()) + elif isinstance(self.update, (list, tuple)) and all( + isinstance(t, tuple) and len(t) == 2 and isinstance(t[0], str) + for t in self.update + ): + return self.update + else: + return [("__root__", self.update)] + PARENT: ClassVar[Literal["__parent__"]] = "__parent__" diff --git a/libs/langgraph/tests/test_pregel.py b/libs/langgraph/tests/test_pregel.py index f69d36ed3..2515270a1 100644 --- a/libs/langgraph/tests/test_pregel.py +++ b/libs/langgraph/tests/test_pregel.py @@ -220,18 +220,6 @@ def test_graph_validation() -> None: class State(TypedDict): hello: str - def node_a(state: State) -> State: - # typo - return {"hell": "world"} - - builder = StateGraph(State) - builder.add_node("a", node_a) - builder.set_entry_point("a") - builder.set_finish_point("a") - graph = builder.compile() - with pytest.raises(InvalidUpdateError): - graph.invoke({"hello": "there"}) - graph = StateGraph(State) graph.add_node("start", lambda x: x) graph.add_edge("__start__", "start") @@ -1919,7 +1907,7 @@ def test_send_sequences() -> None: else ["|".join((self.name, str(state)))] ) if isinstance(state, Command): - return replace(state, update=update) + return [state, Command(update=update)] else: return update From 1f745ca01715db8e0db779e55d9dc7962f9455fe Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Thu, 5 Dec 2024 13:50:42 -0800 Subject: [PATCH 36/58] Lint --- libs/langgraph/langgraph/graph/state.py | 4 ++-- libs/langgraph/langgraph/pregel/write.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/langgraph/langgraph/graph/state.py b/libs/langgraph/langgraph/graph/state.py index 0462008c8..6e37c6150 100644 --- a/libs/langgraph/langgraph/graph/state.py +++ b/libs/langgraph/langgraph/graph/state.py @@ -667,7 +667,7 @@ class CompiledStateGraph(CompiledGraph): raise InvalidUpdateError(msg) # state updaters - write_entries = [ + write_entries: list[Union[ChannelWriteEntry, ChannelWriteTupleEntry]] = [ ChannelWriteTupleEntry( mapper=_get_root if output_keys == ["__root__"] else _get_updates ) @@ -706,7 +706,7 @@ class CompiledStateGraph(CompiledGraph): writers=[ # publish to this channel and state keys ChannelWrite( - [ChannelWriteEntry(key, key)] + write_entries, + write_entries + [ChannelWriteEntry(key, key)], tags=[TAG_HIDDEN], ), ], diff --git a/libs/langgraph/langgraph/pregel/write.py b/libs/langgraph/langgraph/pregel/write.py index baee23ab2..8e9cf35b3 100644 --- a/libs/langgraph/langgraph/pregel/write.py +++ b/libs/langgraph/langgraph/pregel/write.py @@ -37,7 +37,7 @@ class ChannelWriteEntry(NamedTuple): class ChannelWriteTupleEntry(NamedTuple): - mapper: Callable[[Any], Sequence[tuple[str, Any]]] + mapper: Callable[[Any], Optional[Sequence[tuple[str, Any]]]] """Function to extract tuples from value.""" value: Any = PASSTHROUGH """Value to write, or PASSTHROUGH to use the input.""" From 0c379d6cc7c6465efa73f54348297df5dcce0eb9 Mon Sep 17 00:00:00 2001 From: Vadym Barda Date: Thu, 5 Dec 2024 17:55:25 -0500 Subject: [PATCH 37/58] fix docstring (#2660) --- libs/langgraph/langgraph/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/langgraph/langgraph/types.py b/libs/langgraph/langgraph/types.py index 3eb4536aa..868139df1 100644 --- a/libs/langgraph/langgraph/types.py +++ b/libs/langgraph/langgraph/types.py @@ -251,7 +251,7 @@ class Command(Generic[N]): graph: graph to send the command to. Supported values are: - None: the current graph (default) - - GraphCommand.PARENT: closest parent graph + - Command.PARENT: closest parent graph update: update to apply to the graph's state. resume: value to resume execution with. To be used together with [`interrupt()`][langgraph.types.interrupt]. goto: can be one of the following: From ccd8920eeff1db6a912ff4ed02733ca189c06c5d Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Thu, 5 Dec 2024 15:09:13 -0800 Subject: [PATCH 38/58] Lint --- libs/langgraph/langgraph/pregel/write.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/langgraph/langgraph/pregel/write.py b/libs/langgraph/langgraph/pregel/write.py index 8e9cf35b3..a4a42c3f0 100644 --- a/libs/langgraph/langgraph/pregel/write.py +++ b/libs/langgraph/langgraph/pregel/write.py @@ -136,7 +136,6 @@ class ChannelWrite(RunnableCallable): raise InvalidUpdateError("PASSTHROUGH value must be replaced") # assemble writes tuples: list[tuple[str, Any]] = [] - print(writes) for w in writes: if isinstance(w, Send): tuples.append((PUSH if FF_SEND_V2 else TASKS, w)) @@ -152,7 +151,6 @@ class ChannelWrite(RunnableCallable): tuples.append((w.channel, value)) else: raise ValueError(f"Invalid write entry: {w}") - print(tuples, require_at_least_one_of) # assert required channels if require_at_least_one_of is not None: if not {chan for chan, _ in tuples} & set(require_at_least_one_of): From 93e4c8cc1fe754c6e4b4119ed659bffaec78dc03 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:56:39 -0800 Subject: [PATCH 39/58] Create index concurrently (#2659) --- .../langgraph/checkpoint/postgres/base.py | 11 +++++++ .../langgraph/store/postgres/aio.py | 28 +++++++--------- .../langgraph/store/postgres/base.py | 32 ++++++++----------- libs/checkpoint-postgres/poetry.lock | 27 ++++++++-------- libs/checkpoint-postgres/pyproject.toml | 2 +- libs/checkpoint-postgres/tests/test_async.py | 5 ++- libs/checkpoint-postgres/tests/test_sync.py | 5 ++- 7 files changed, 55 insertions(+), 55 deletions(-) diff --git a/libs/checkpoint-postgres/langgraph/checkpoint/postgres/base.py b/libs/checkpoint-postgres/langgraph/checkpoint/postgres/base.py index 90ba81686..b18ab8f4d 100644 --- a/libs/checkpoint-postgres/langgraph/checkpoint/postgres/base.py +++ b/libs/checkpoint-postgres/langgraph/checkpoint/postgres/base.py @@ -57,6 +57,17 @@ MIGRATIONS = [ PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id, task_id, idx) );""", "ALTER TABLE checkpoint_blobs ALTER COLUMN blob DROP not null;", + """ + """, + """ + CREATE INDEX CONCURRENTLY IF NOT EXISTS checkpoints_thread_id_idx ON checkpoints(thread_id); + """, + """ + CREATE INDEX CONCURRENTLY IF NOT EXISTS checkpoint_blobs_thread_id_idx ON checkpoint_blobs(thread_id); + """, + """ + CREATE INDEX CONCURRENTLY IF NOT EXISTS checkpoint_writes_thread_id_idx ON checkpoint_writes(thread_id); + """, ] SELECT_SQL = f""" diff --git a/libs/checkpoint-postgres/langgraph/store/postgres/aio.py b/libs/checkpoint-postgres/langgraph/store/postgres/aio.py index 4a516557a..e62d360cc 100644 --- a/libs/checkpoint-postgres/langgraph/store/postgres/aio.py +++ b/libs/checkpoint-postgres/langgraph/store/postgres/aio.py @@ -6,7 +6,6 @@ from typing import Any, Callable, Optional, Union, cast import orjson from psycopg import AsyncConnection, AsyncCursor, AsyncPipeline, Capabilities -from psycopg.errors import UndefinedTable from psycopg.rows import DictRow, dict_row from psycopg_pool import AsyncConnectionPool @@ -219,22 +218,19 @@ class AsyncPostgresStore(AsyncBatchedBaseStore, BasePostgresStore[_ainternal.Con """ async def _get_version(cur: AsyncCursor[DictRow], table: str) -> int: - try: - await cur.execute(f"SELECT v FROM {table} ORDER BY v DESC LIMIT 1") - row = await cur.fetchone() - if row is None: - version = -1 - else: - version = row["v"] - except UndefinedTable: - version = -1 - await cur.execute( - f""" - CREATE TABLE IF NOT EXISTS {table} ( - v INTEGER PRIMARY KEY - ) - """ + await cur.execute( + f""" + CREATE TABLE IF NOT EXISTS {table} ( + v INTEGER PRIMARY KEY ) + """ + ) + await cur.execute(f"SELECT v FROM {table} ORDER BY v DESC LIMIT 1") + row = cast(dict, await cur.fetchone()) + if row is None: + version = -1 + else: + version = row["v"] return version async with self._cursor() as cur: diff --git a/libs/checkpoint-postgres/langgraph/store/postgres/base.py b/libs/checkpoint-postgres/langgraph/store/postgres/base.py index 84dd70364..d47a357d2 100644 --- a/libs/checkpoint-postgres/langgraph/store/postgres/base.py +++ b/libs/checkpoint-postgres/langgraph/store/postgres/base.py @@ -21,7 +21,6 @@ from typing import ( import orjson from psycopg import Capabilities, Connection, Cursor, Pipeline -from psycopg.errors import UndefinedTable from psycopg.rows import DictRow, dict_row from psycopg.types.json import Jsonb from psycopg_pool import ConnectionPool @@ -73,7 +72,7 @@ CREATE TABLE IF NOT EXISTS store ( """, """ -- For faster lookups by prefix -CREATE INDEX IF NOT EXISTS store_prefix_idx ON store USING btree (prefix text_pattern_ops); +CREATE INDEX CONCURRENTLY IF NOT EXISTS store_prefix_idx ON store USING btree (prefix text_pattern_ops); """, ] @@ -107,7 +106,7 @@ CREATE TABLE IF NOT EXISTS store_vectors ( ), Migration( """ -CREATE INDEX IF NOT EXISTS store_vectors_embedding_idx ON store_vectors +CREATE INDEX CONCURRENTLY IF NOT EXISTS store_vectors_embedding_idx ON store_vectors USING %(index_type)s (embedding %(ops)s)%(index_params)s; """, condition=lambda store: bool( @@ -847,22 +846,19 @@ class PostgresStore(BaseStore, BasePostgresStore[_pg_internal.Conn]): """ def _get_version(cur: Cursor[dict[str, Any]], table: str) -> int: - try: - cur.execute(f"SELECT v FROM {table} ORDER BY v DESC LIMIT 1") - row = cast(dict, cur.fetchone()) - if row is None: - version = -1 - else: - version = row["v"] - except UndefinedTable: - version = -1 - cur.execute( - f""" - CREATE TABLE IF NOT EXISTS {table} ( - v INTEGER PRIMARY KEY - ) - """ + cur.execute( + f""" + CREATE TABLE IF NOT EXISTS {table} ( + v INTEGER PRIMARY KEY ) + """ + ) + cur.execute(f"SELECT v FROM {table} ORDER BY v DESC LIMIT 1") + row = cast(dict, cur.fetchone()) + if row is None: + version = -1 + else: + version = row["v"] return version with self._cursor() as cur: diff --git a/libs/checkpoint-postgres/poetry.lock b/libs/checkpoint-postgres/poetry.lock index d1cc60d52..76c2177af 100644 --- a/libs/checkpoint-postgres/poetry.lock +++ b/libs/checkpoint-postgres/poetry.lock @@ -13,24 +13,24 @@ files = [ [[package]] name = "anyio" -version = "4.6.2.post1" +version = "4.7.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.9" files = [ - {file = "anyio-4.6.2.post1-py3-none-any.whl", hash = "sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d"}, - {file = "anyio-4.6.2.post1.tar.gz", hash = "sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c"}, + {file = "anyio-4.7.0-py3-none-any.whl", hash = "sha256:ea60c3723ab42ba6fff7e8ccb0488c898ec538ff4df1f1d5e642c3601d07e352"}, + {file = "anyio-4.7.0.tar.gz", hash = "sha256:2f834749c602966b7d456a7567cafcb309f96482b5081d14ac93ccd457f9dd48"}, ] [package.dependencies] exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" sniffio = ">=1.1" -typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} +typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} [package.extras] -doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21.0b1)"] +doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"] trio = ["trio (>=0.26.1)"] [[package]] @@ -244,13 +244,13 @@ trio = ["trio (>=0.22.0,<1.0)"] [[package]] name = "httpx" -version = "0.27.2" +version = "0.28.0" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0"}, - {file = "httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2"}, + {file = "httpx-0.28.0-py3-none-any.whl", hash = "sha256:dc0b419a0cfeb6e8b34e85167c0da2671206f5095f1baa9663d23bcfd6b535fc"}, + {file = "httpx-0.28.0.tar.gz", hash = "sha256:0858d3bab51ba7e386637f22a61d8ccddaeec5f3fe4209da3a6168dbb91573e0"}, ] [package.dependencies] @@ -258,7 +258,6 @@ anyio = "*" certifi = "*" httpcore = "==1.*" idna = "*" -sniffio = "*" [package.extras] brotli = ["brotli", "brotlicffi"] @@ -342,7 +341,7 @@ typing-extensions = ">=4.7" [[package]] name = "langgraph-checkpoint" -version = "2.0.7" +version = "2.0.8" description = "Library with base interfaces for LangGraph checkpoint savers." optional = false python-versions = "^3.9.0,<4.0" @@ -741,13 +740,13 @@ typing-extensions = ">=4.6" [[package]] name = "pydantic" -version = "2.10.2" +version = "2.10.3" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.10.2-py3-none-any.whl", hash = "sha256:cfb96e45951117c3024e6b67b25cdc33a3cb7b2fa62e239f7af1378358a1d99e"}, - {file = "pydantic-2.10.2.tar.gz", hash = "sha256:2bc2d7f17232e0841cbba4641e65ba1eb6fafb3a08de3a091ff3ce14a197c4fa"}, + {file = "pydantic-2.10.3-py3-none-any.whl", hash = "sha256:be04d85bbc7b65651c5f8e6b9976ed9c6f41782a55524cef079a34a0bb82144d"}, + {file = "pydantic-2.10.3.tar.gz", hash = "sha256:cb5ac360ce894ceacd69c403187900a02c4b20b693a9dd1d643e1effab9eadf9"}, ] [package.dependencies] diff --git a/libs/checkpoint-postgres/pyproject.toml b/libs/checkpoint-postgres/pyproject.toml index f3af7d14d..1b9123b30 100644 --- a/libs/checkpoint-postgres/pyproject.toml +++ b/libs/checkpoint-postgres/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langgraph-checkpoint-postgres" -version = "2.0.7" +version = "2.0.8" description = "Library with a Postgres implementation of LangGraph checkpoint saver." authors = [] license = "MIT" diff --git a/libs/checkpoint-postgres/tests/test_async.py b/libs/checkpoint-postgres/tests/test_async.py index d4d0eb8fa..67848707c 100644 --- a/libs/checkpoint-postgres/tests/test_async.py +++ b/libs/checkpoint-postgres/tests/test_async.py @@ -63,9 +63,8 @@ async def _pipe_saver(): prepare_threshold=0, row_factory=dict_row, ) as conn: - async with conn.pipeline() as pipe: - checkpointer = AsyncPostgresSaver(conn, pipe=pipe) - await checkpointer.setup() + checkpointer = AsyncPostgresSaver(conn) + await checkpointer.setup() async with conn.pipeline() as pipe: checkpointer = AsyncPostgresSaver(conn, pipe=pipe) yield checkpointer diff --git a/libs/checkpoint-postgres/tests/test_sync.py b/libs/checkpoint-postgres/tests/test_sync.py index fbf4c1c88..52e186a55 100644 --- a/libs/checkpoint-postgres/tests/test_sync.py +++ b/libs/checkpoint-postgres/tests/test_sync.py @@ -57,9 +57,8 @@ def _pipe_saver(): prepare_threshold=0, row_factory=dict_row, ) as conn: - with conn.pipeline() as pipe: - checkpointer = PostgresSaver(conn, pipe=pipe) - checkpointer.setup() + checkpointer = PostgresSaver(conn) + checkpointer.setup() with conn.pipeline() as pipe: checkpointer = PostgresSaver(conn, pipe=pipe) yield checkpointer From 5fa80e2a92bbecf43e69fcf8424f6f53673bfeaa Mon Sep 17 00:00:00 2001 From: Vadym Barda Date: Fri, 6 Dec 2024 10:18:12 -0500 Subject: [PATCH 40/58] docs: update multi-agent tutorials to use Command (#2643) --- .../multi_agent/agent_supervisor.ipynb | 130 ++++---------- .../hierarchical_agent_teams.ipynb | 158 +++++++++--------- .../multi-agent-collaboration.ipynb | 100 +++++------ 3 files changed, 159 insertions(+), 229 deletions(-) diff --git a/docs/docs/tutorials/multi_agent/agent_supervisor.ipynb b/docs/docs/tutorials/multi_agent/agent_supervisor.ipynb index c1b8d1231..9ad48024d 100644 --- a/docs/docs/tutorials/multi_agent/agent_supervisor.ipynb +++ b/docs/docs/tutorials/multi_agent/agent_supervisor.ipynb @@ -127,30 +127,7 @@ { "cell_type": "code", "execution_count": 4, - "id": "f16c289b-10b0-47a8-a675-0bb54d299236", - "metadata": {}, - "outputs": [], - "source": [ - "from langgraph.graph import MessagesState" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "4a3baabf-18cb-415c-9473-d0546cf58b8b", - "metadata": {}, - "outputs": [], - "source": [ - "# The agent state is the input to each node in the graph\n", - "class AgentState(MessagesState):\n", - " # The 'next' field indicates where to route to next\n", - " next: str" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "311f0a58-b425-4496-adac-dc4cd8ffb912", + "id": "df2bd80b-c477-4d74-8faa-1c0548622239", "metadata": {}, "outputs": [], "source": [ @@ -158,6 +135,9 @@ "from typing_extensions import TypedDict\n", "\n", "from langchain_anthropic import ChatAnthropic\n", + "from langgraph.graph import MessagesState\n", + "from langgraph.types import Command\n", + "\n", "\n", "members = [\"researcher\", \"coder\"]\n", "# Our team supervisor is an LLM node. It just picks the next agent to process\n", @@ -182,16 +162,16 @@ "llm = ChatAnthropic(model=\"claude-3-5-sonnet-latest\")\n", "\n", "\n", - "def supervisor_node(state: AgentState) -> AgentState:\n", + "def supervisor_node(state: MessagesState) -> Command[Literal[*members, \"__end__\"]]:\n", " messages = [\n", " {\"role\": \"system\", \"content\": system_prompt},\n", " ] + state[\"messages\"]\n", " response = llm.with_structured_output(Router).invoke(messages)\n", - " next_ = response[\"next\"]\n", - " if next_ == \"FINISH\":\n", - " next_ = END\n", + " goto = response[\"next\"]\n", + " if goto == \"FINISH\":\n", + " goto = END\n", "\n", - " return {\"next\": next_}" + " return Command(goto=goto)" ] }, { @@ -206,21 +186,10 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 5, "id": "6a430af7-8fce-4e66-ba9e-d940c1bc48e8", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "from langchain_core.messages import HumanMessage\n", "from langgraph.graph import StateGraph, START, END\n", @@ -232,80 +201,51 @@ ")\n", "\n", "\n", - "def research_node(state: AgentState) -> AgentState:\n", + "def research_node(state: MessagesState) -> Command[Literal[\"supervisor\"]]:\n", " result = research_agent.invoke(state)\n", - " return {\n", - " \"messages\": [\n", - " HumanMessage(content=result[\"messages\"][-1].content, name=\"researcher\")\n", - " ]\n", - " }\n", + " return Command(\n", + " update={\n", + " \"messages\": [\n", + " HumanMessage(content=result[\"messages\"][-1].content, name=\"researcher\")\n", + " ]\n", + " },\n", + " goto=\"supervisor\",\n", + " )\n", "\n", "\n", "# NOTE: THIS PERFORMS ARBITRARY CODE EXECUTION, WHICH CAN BE UNSAFE WHEN NOT SANDBOXED\n", "code_agent = create_react_agent(llm, tools=[python_repl_tool])\n", "\n", "\n", - "def code_node(state: AgentState) -> AgentState:\n", + "def code_node(state: MessagesState) -> Command[Literal[\"supervisor\"]]:\n", " result = code_agent.invoke(state)\n", - " return {\n", - " \"messages\": [HumanMessage(content=result[\"messages\"][-1].content, name=\"coder\")]\n", - " }\n", + " return Command(\n", + " update={\n", + " \"messages\": [\n", + " HumanMessage(content=result[\"messages\"][-1].content, name=\"coder\")\n", + " ]\n", + " },\n", + " goto=\"supervisor\",\n", + " )\n", "\n", "\n", - "builder = StateGraph(AgentState)\n", + "builder = StateGraph(MessagesState)\n", "builder.add_edge(START, \"supervisor\")\n", "builder.add_node(\"supervisor\", supervisor_node)\n", "builder.add_node(\"researcher\", research_node)\n", - "builder.add_node(\"coder\", code_node)" - ] - }, - { - "cell_type": "markdown", - "id": "2c1593d5-39f7-4819-96d2-4ad7d7991d72", - "metadata": {}, - "source": [ - "Now connect all the edges in the graph." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "14778e86-077b-4e6a-893c-400e59b0cdbf", - "metadata": {}, - "outputs": [], - "source": [ - "for member in members:\n", - " # We want our workers to ALWAYS \"report back\" to the supervisor when done\n", - " builder.add_edge(member, \"supervisor\")\n", - "\n", - "# The supervisor populates the \"next\" field in the graph state\n", - "# which routes to a node or finishes\n", - "builder.add_conditional_edges(\"supervisor\", lambda state: state[\"next\"])\n", - "# Finally, add entrypoint\n", - "builder.add_edge(START, \"supervisor\")\n", - "\n", + "builder.add_node(\"coder\", code_node)\n", "graph = builder.compile()" ] }, { "cell_type": "code", - "execution_count": 9, - "id": "fb2cf698-c42b-49ba-8ade-585d207a3daa", - "metadata": {}, - "outputs": [], - "source": [ - "from IPython.display import display, Image" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "f4992dcb-33c5-4fef-b4e3-09c303737342", + "execution_count": 7, + "id": "0175fe14-5854-4197-b7e8-559335d0f81b", "metadata": {}, "outputs": [ { "data": { - "image/png": "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", + "image/jpeg": "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", "text/plain": [ "" ] @@ -315,6 +255,8 @@ } ], "source": [ + "from IPython.display import display, Image\n", + "\n", "display(Image(graph.get_graph().draw_mermaid_png()))" ] }, diff --git a/docs/docs/tutorials/multi_agent/hierarchical_agent_teams.ipynb b/docs/docs/tutorials/multi_agent/hierarchical_agent_teams.ipynb index f96e55c39..39009e852 100644 --- a/docs/docs/tutorials/multi_agent/hierarchical_agent_teams.ipynb +++ b/docs/docs/tutorials/multi_agent/hierarchical_agent_teams.ipynb @@ -289,15 +289,10 @@ "from langchain_core.language_models.chat_models import BaseChatModel\n", "\n", "from langgraph.graph import StateGraph, MessagesState, START, END\n", + "from langgraph.types import Command\n", "from langchain_core.messages import HumanMessage, trim_messages\n", "\n", "\n", - "# The agent state is the input to each node in the graph\n", - "class AgentState(MessagesState):\n", - " # The 'next' field indicates where to route to next\n", - " next: str\n", - "\n", - "\n", "def make_supervisor_node(llm: BaseChatModel, members: list[str]) -> str:\n", " options = [\"FINISH\"] + members\n", " system_prompt = (\n", @@ -313,17 +308,17 @@ "\n", " next: Literal[*options]\n", "\n", - " def supervisor_node(state: MessagesState) -> MessagesState:\n", + " def supervisor_node(state: MessagesState) -> Command[Literal[*members, \"__end__\"]]:\n", " \"\"\"An LLM-based router.\"\"\"\n", " messages = [\n", " {\"role\": \"system\", \"content\": system_prompt},\n", " ] + state[\"messages\"]\n", " response = llm.with_structured_output(Router).invoke(messages)\n", - " next_ = response[\"next\"]\n", - " if next_ == \"FINISH\":\n", - " next_ = END\n", + " goto = response[\"next\"]\n", + " if goto == \"FINISH\":\n", + " goto = END\n", "\n", - " return {\"next\": next_}\n", + " return Command(goto=goto)\n", "\n", " return supervisor_node" ] @@ -363,25 +358,33 @@ "search_agent = create_react_agent(llm, tools=[tavily_tool])\n", "\n", "\n", - "def search_node(state: AgentState) -> AgentState:\n", + "def search_node(state: MessagesState) -> Command[Literal[\"supervisor\"]]:\n", " result = search_agent.invoke(state)\n", - " return {\n", - " \"messages\": [\n", - " HumanMessage(content=result[\"messages\"][-1].content, name=\"search\")\n", - " ]\n", - " }\n", + " return Command(\n", + " update={\n", + " \"messages\": [\n", + " HumanMessage(content=result[\"messages\"][-1].content, name=\"search\")\n", + " ]\n", + " },\n", + " # We want our workers to ALWAYS \"report back\" to the supervisor when done\n", + " goto=\"supervisor\",\n", + " )\n", "\n", "\n", "web_scraper_agent = create_react_agent(llm, tools=[scrape_webpages])\n", "\n", "\n", - "def web_scraper_node(state: AgentState) -> AgentState:\n", + "def web_scraper_node(state: MessagesState) -> Command[Literal[\"supervisor\"]]:\n", " result = web_scraper_agent.invoke(state)\n", - " return {\n", - " \"messages\": [\n", - " HumanMessage(content=result[\"messages\"][-1].content, name=\"web_scraper\")\n", - " ]\n", - " }\n", + " return Command(\n", + " update={\n", + " \"messages\": [\n", + " HumanMessage(content=result[\"messages\"][-1].content, name=\"web_scraper\")\n", + " ]\n", + " },\n", + " # We want our workers to ALWAYS \"report back\" to the supervisor when done\n", + " goto=\"supervisor\",\n", + " )\n", "\n", "\n", "research_supervisor_node = make_supervisor_node(llm, [\"search\", \"web_scraper\"])" @@ -412,14 +415,7 @@ "research_builder.add_node(\"search\", search_node)\n", "research_builder.add_node(\"web_scraper\", web_scraper_node)\n", "\n", - "# Define the control flow\n", "research_builder.add_edge(START, \"supervisor\")\n", - "# We want our workers to ALWAYS \"report back\" to the supervisor when done\n", - "research_builder.add_edge(\"search\", \"supervisor\")\n", - "research_builder.add_edge(\"web_scraper\", \"supervisor\")\n", - "# Add the edges where routing applies\n", - "research_builder.add_conditional_edges(\"supervisor\", lambda state: state[\"next\"])\n", - "\n", "research_graph = research_builder.compile()" ] }, @@ -532,13 +528,17 @@ ")\n", "\n", "\n", - "def doc_writing_node(state: AgentState) -> AgentState:\n", + "def doc_writing_node(state: MessagesState) -> Command[Literal[\"supervisor\"]]:\n", " result = doc_writer_agent.invoke(state)\n", - " return {\n", - " \"messages\": [\n", - " HumanMessage(content=result[\"messages\"][-1].content, name=\"doc_writer\")\n", - " ]\n", - " }\n", + " return Command(\n", + " update={\n", + " \"messages\": [\n", + " HumanMessage(content=result[\"messages\"][-1].content, name=\"doc_writer\")\n", + " ]\n", + " },\n", + " # We want our workers to ALWAYS \"report back\" to the supervisor when done\n", + " goto=\"supervisor\",\n", + " )\n", "\n", "\n", "note_taking_agent = create_react_agent(\n", @@ -551,13 +551,17 @@ ")\n", "\n", "\n", - "def note_taking_node(state: AgentState) -> AgentState:\n", + "def note_taking_node(state: MessagesState) -> Command[Literal[\"supervisor\"]]:\n", " result = note_taking_agent.invoke(state)\n", - " return {\n", - " \"messages\": [\n", - " HumanMessage(content=result[\"messages\"][-1].content, name=\"note_taker\")\n", - " ]\n", - " }\n", + " return Command(\n", + " update={\n", + " \"messages\": [\n", + " HumanMessage(content=result[\"messages\"][-1].content, name=\"note_taker\")\n", + " ]\n", + " },\n", + " # We want our workers to ALWAYS \"report back\" to the supervisor when done\n", + " goto=\"supervisor\",\n", + " )\n", "\n", "\n", "chart_generating_agent = create_react_agent(\n", @@ -565,13 +569,19 @@ ")\n", "\n", "\n", - "def chart_generating_node(state: AgentState) -> AgentState:\n", + "def chart_generating_node(state: MessagesState) -> Command[Literal[\"supervisor\"]]:\n", " result = chart_generating_agent.invoke(state)\n", - " return {\n", - " \"messages\": [\n", - " HumanMessage(content=result[\"messages\"][-1].content, name=\"chart_generator\")\n", - " ]\n", - " }\n", + " return Command(\n", + " update={\n", + " \"messages\": [\n", + " HumanMessage(\n", + " content=result[\"messages\"][-1].content, name=\"chart_generator\"\n", + " )\n", + " ]\n", + " },\n", + " # We want our workers to ALWAYS \"report back\" to the supervisor when done\n", + " goto=\"supervisor\",\n", + " )\n", "\n", "\n", "doc_writing_supervisor_node = make_supervisor_node(\n", @@ -600,21 +610,13 @@ "outputs": [], "source": [ "# Create the graph here\n", - "paper_writing_builder = StateGraph(AgentState)\n", + "paper_writing_builder = StateGraph(MessagesState)\n", "paper_writing_builder.add_node(\"supervisor\", doc_writing_supervisor_node)\n", "paper_writing_builder.add_node(\"doc_writer\", doc_writing_node)\n", "paper_writing_builder.add_node(\"note_taker\", note_taking_node)\n", "paper_writing_builder.add_node(\"chart_generator\", chart_generating_node)\n", "\n", - "# Define the control flow\n", "paper_writing_builder.add_edge(START, \"supervisor\")\n", - "# We want our workers to ALWAYS \"report back\" to the supervisor when done\n", - "paper_writing_builder.add_edge(\"doc_writer\", \"supervisor\")\n", - "paper_writing_builder.add_edge(\"note_taker\", \"supervisor\")\n", - "paper_writing_builder.add_edge(\"chart_generator\", \"supervisor\")\n", - "# Add the edges where routing applies\n", - "paper_writing_builder.add_conditional_edges(\"supervisor\", lambda state: state[\"next\"])\n", - "\n", "paper_writing_graph = paper_writing_builder.compile()" ] }, @@ -728,37 +730,41 @@ }, "outputs": [], "source": [ - "def call_research_team(state: AgentState) -> AgentState:\n", + "def call_research_team(state: MessagesState) -> Command[Literal[\"supervisor\"]]:\n", " response = research_graph.invoke({\"messages\": state[\"messages\"][-1]})\n", - " return {\n", - " \"messages\": [\n", - " HumanMessage(content=response[\"messages\"][-1].content, name=\"research_team\")\n", - " ]\n", - " }\n", + " return Command(\n", + " update={\n", + " \"messages\": [\n", + " HumanMessage(\n", + " content=response[\"messages\"][-1].content, name=\"research_team\"\n", + " )\n", + " ]\n", + " },\n", + " goto=\"supervisor\",\n", + " )\n", "\n", "\n", - "def call_paper_writing_team(state: AgentState) -> AgentState:\n", + "def call_paper_writing_team(state: MessagesState) -> Command[Literal[\"supervisor\"]]:\n", " response = paper_writing_graph.invoke({\"messages\": state[\"messages\"][-1]})\n", - " return {\n", - " \"messages\": [\n", - " HumanMessage(content=response[\"messages\"][-1].content, name=\"writing_team\")\n", - " ]\n", - " }\n", + " return Command(\n", + " update={\n", + " \"messages\": [\n", + " HumanMessage(\n", + " content=response[\"messages\"][-1].content, name=\"writing_team\"\n", + " )\n", + " ]\n", + " },\n", + " goto=\"supervisor\",\n", + " )\n", "\n", "\n", "# Define the graph.\n", - "super_builder = StateGraph(AgentState)\n", + "super_builder = StateGraph(MessagesState)\n", "super_builder.add_node(\"supervisor\", teams_supervisor_node)\n", "super_builder.add_node(\"research_team\", call_research_team)\n", "super_builder.add_node(\"writing_team\", call_paper_writing_team)\n", "\n", - "# Define the control flow\n", "super_builder.add_edge(START, \"supervisor\")\n", - "# We want our teams to ALWAYS \"report back\" to the top-level supervisor when done\n", - "super_builder.add_edge(\"research_team\", \"supervisor\")\n", - "super_builder.add_edge(\"writing_team\", \"supervisor\")\n", - "# Add the edges where routing applies\n", - "super_builder.add_conditional_edges(\"supervisor\", lambda state: state[\"next\"])\n", "super_graph = super_builder.compile()" ] }, diff --git a/docs/docs/tutorials/multi_agent/multi-agent-collaboration.ipynb b/docs/docs/tutorials/multi_agent/multi-agent-collaboration.ipynb index 6d4bb1537..3ee863cda 100644 --- a/docs/docs/tutorials/multi_agent/multi-agent-collaboration.ipynb +++ b/docs/docs/tutorials/multi_agent/multi-agent-collaboration.ipynb @@ -2,8 +2,8 @@ "cells": [ { "attachments": { - "7d0ca3af-e391-4d23-981a-dd640e08e4c1.png": { - "image/png": "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CCCQL0BQme/BJwQQQAABBIoKEFQWZWElAggggEAnAgSVnQCxGQEEEEAAgUiAoDLC4C0CCCCAAAKlBCyoZDKEUkKsRwABBBAoJkBQWUyFdQgggAACCBQXIKgs7sJaBBBAAAEE8gQIKvM4+IAAAgggUKEAQWWFUBRDAAEEEEDACxBUchsggAACCCBQgYAFlRMmTHCDBg2qYA+KIIAAAggg4NxZZ53lRo8e7XjGMXcDAggggAACnQsQVHZuRAkEEEAAAQQcQSU3AQIIIIBAVwQIKruixj4IIIAAAu0qQFDZri3PdSOAAAIIVCzw0EMPuWHDhoXy06ZNq3g/CiKAAAIIIEBQyT2AAAIIIIBA5QIElZVbURIBBBBAoE0FCCrbtOEzctm5XM699tprbr755nO9evWquNZfffWVe+edd9wCCyzgevToUfF+FEQAgeoECCqr86I0AggggEB7CxBUtnf7c/UIIIAAAhUIEFRWgESRpgh89913bvfdd3d33XWX23DDDd2FF15YcT2032233eZmn312d+ONN7p+/fpVvC8FEUCgcgGCysqtKIkAAggggABBJfcAAggggAACnQjEQSWT6XSCxeaGCjz//PNugw02SM751FNPuVlmmSX5XO7NEkss4T7//PNQRKHlMcccU6442xBAoIsCBJVdhGM3BBBAAIG2FCCobMtm56IRQAABBKoRIKisRouyjRSYPHmyO/DAA8MpZ5ppJvf444+7GWaYoaIq7LvvvqEnpQqvueaa7rLLLqtoPwohgEB1AgSV1XlRGgEEEECgvQUIKtu7/bl6BBBAAIEKBAgqK0CiSFMEdt11V3fHHXeEc++2227u2GOPrbgeZ555pjv77LND+eWWW84p9GRBAIHaCxBU1t6UIyKAAAIItK4AQWXrti1XhgACCCBQIwH7kqnDMfS7RqgcptsCH3/8sVt66aWT4+h5kwMHDkw+d/bm6KOPdpdffnkotuCCC7q777677C56HuZbb73lXn/99TBpz2KLLeb+3//7f2X3YSMCCDhnf0NWWWUVN378eEgQQAABBBBAoIwAQWUZHDYhgAACCCAgAfuSqfcElVJgSYPAtdde6w466KBQlUUWWSTpWVlp3eKh36X2f++998Jxb7rpJvfggw92OPQ999zjBgwY0GF9qRUKOz/66KPwHM3pp5++VLGw/vrrr3d65uY+++zjZptttqTsp59+GgLTvn37hgmApptuumQbbxBIo4D9DSGoTGPrUCcEEEAAgbQJEFSmrUWoDwIIIIBA6gTsS6YqRlCZuuZp2wodccQR7qqrrgrXrzDv8MMPr8pim222ScLHTTbZxJ133nnJ/ppkR/f92LFjk3XF3owbN84NHjy42Ka8de+8844bM2ZMUl9tXGaZZULQWmx/haKqn5bf/e53TqGqAs4TTzzRXXPNNWG9/kfP5TzhhBPc0KFDk3W8QSBtAvY3hKAybS1DfRBAAAEE0ihAUJnGVqFOCCCAAAKpErAvmaoUQWWqmqatK6Nw7uGHHw4Go0ePdltssUXFHgoiNeu3LXvuuac76qijwsdPPvnEbbzxxu6NN96wzR1eFRD269cvTMbT2eQ9+plR2FhqGTFihNt+++3zNt9///1u2223Deu22267EMKut9567t13380rpw9rrLFGMoS9w0ZWIJACgfhvyLRp01JQI6qAAAIIIIBAegUIKtPbNtQMAQQQQCAlAvGXTILKlDQK1XBrr722e/XVV4PEpEmT3Iorrlixyp133ul22WWXpPwZZ5zhhg0bFj4feuihbuLEick2vdl0003dkCFD3OKLL+7mmGMO16NHj7ztpT5cffXV7rDDDsvbrGM8//zzeeuee+650DvSVsZBpQLZ77//Pq8n5dxzz+1+/vOfh16WClg33HBD25VXBFInEP8NIahMXfNQIQQQQACBlAkQVKasQagOAggggED6BOIvmQSV6Wufdq3R8ssv7z788MNw+Qr25p133oop4ol0tNPtt9/uFl100bD/oEGD8nouqsfipZdeGibQqfgEvqCeX7njjjsmuyhIVc9P1VNhzU477ZQErZpgRMNibXn22WfdRhttZB+T19lnn91pyPuWW25ZdX2Sg/AGgQYLxH9DCCobjM/pEEAAAQQyJ0BQmbkmo8IIIIAAAo0W2Hrrrd2UKVPCaQkqG63P+UoJxEHlY489VvEM3JrQRrOFa/i3FoV/jz76aNJL8rLLLnPHHnts3mnVC1LPh1xppZXy1pf6oB6Q66+/vnvppZdCkVVXXdX96U9/cn369Amfde511lknCURvuOGGvBnMNYnPyiuv3OHwt956q9Ns4ywIZEmAoDJLrUVdEUAAAQSaLUBQ2ewW4PwIIIAAAqkXIKhMfRO1ZQXjoPKWW24Jw7Irgfjb3/7m9tprr6Ro/HxKW1ksrNS2Nddc0w0fPtwtt9xyVrToq2bs3n///ZNtCi1333330JtSw9VHjRoVwlEV0PMuFbRaiKl13377rVt44YX1Nlk0JD0+ZrKBNwikXICgMuUNRPUQQAABBFIlQFCZquagMggggAACaRQgqExjq1AnPTfyySefDBCnnHJKMvlMOZmPP/449HSMJ6W566673EILLdRhNwWKer6kelsWLgosDzjggKLPxVRvyrXWWqvsZDzx8UaOHFl01m5N9hP3+tRM4J1N3BMfl/cIpEWAoDItLUE9EEAAAQSyIEBQmYVWoo4IIIAAAk0ViIPKgw46KPQoa2qFODkCXiAOPzS5jCbIUe/EUssXX3zhdt55Z/fQQw8lRTRRjYLCcouCSvWwvO666zoU05Duww8/3C277LLJtpdffjkM69YK1WfJJZdMZidPCv3w5qSTTnI77LBD4erwOZ4saO+99w7PpixakJUIpFwg/lnlGZUpbyyqhwACCCDQdAGCyqY3ARVAAAEEEEi7AEFl2luoPetXOOHM9ttv70444QTXs2fPDiAffPCBU9j38MMPJ9vmm28+d+ONN7pZZpklWVfuzZtvvukuvPBCd/nll3copuHgBx54oJtuuumcemgqENUyePBgN27cuDDLt4LU119/3fXu3Ts8j/JXv/qVU8Baaol7jJYLNEvtz3oE0iJAUJmWlqAeCCCAAAJZECCozEIrUUcEEEAAgaYKEFQ2lZ+TlxDI5XJO92bcQ1Izays0XGSRRUJvxueeey70hCwMFzWBzuTJk53CymKLZgEfOHBg0e1vv/22O//88zsElr/73e/cvvvu65544gm3+eabJ4d9/PHHw4Q9yYoK3wwZMiQZdn7IIYeEoeYV7koxBFIlQFCZquagMggggAACKRcgqEx5A1E9BBBAAIHmC8w///xJJRj6nVDwJgUCr732WngeZDVVWXDBBUPIOM888xTd7bPPPgvDtbVxm222CeHjvPPO26GshrBqJvA77rgj2TZ16tQQkP7iF79I1ik8VVAaT5aTbCzzJg4q1113XXfJJZeUKc0mBNIrQFCZ3rahZggggAAC6RMgqExfm1AjBBBAAIGUCRBUpqxBqE6ewJQpU9yuu+6aTDyTt7HgwyabbOJOPfVU17dv34ItP358//33O0ySoxm7V199dde/f/8w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fq2d++KLL8Iw07nnntvdf//9Da/fJ5984m644QZ32223uRdffNG9++67bvjw4U4hRjssI0eOdOecc47T69ChQ9vhkp0FlfqdovuumYuGoD/xxBPunnvucQMGDGh4VfbZZ58w5Luw96R+n3z22WdunnnmaXid6nnC+O8IQWU9pTk2AggggEArCBBUtkIrcg0IIIAAAnUTiL9g6iQElT9Sq3eYemS98cYbP64s8u6oo45ye+65Z5EtzVtlQaVq8Pjjj4dwtRG1UU+xCy+80F155ZVFT5eG3nZFK1bjlRZUKsRul2c2quegAulbb73VLbbYYjUWre5wFlRefPHFbv31169u526W/u6779xCCy0UjnL++ee7jTfeuJtHTP/u8d8Rgsr0txc1RAABBBBorgBBZXP9OTsCCCCAQMoF4i+YqipB5Y8N9uGHHzpNEFJsWWSRRdwss8ziFlhgAbf99tu7tA2vjoPKRvQqk5V6EI4bNy7hktE777wThgNr8pAjjzwyWCUFWviNBZUa/nvWWWe18JX+eGlrr722e/XVV93NN9/sllxyyR83NOGdBZV/+MMf3G9+85uG1kAGstDy1FNPhd8TDa1AE04W/x0hqGxCA3BKBBBAAIFMCRBUZqq5qCwCCCCAQKMF4i+YOjdBZX4LaPiohnzPNtts7re//a1TIHfmmWe6IUOG5BdM2ScNvdZz8bSoR5eek6hn9mlRaKggrVbDT5988km38847Bxsd/4ADDnDbbbedm3POOZ2elfnpp5+GZ2VqW7ssp512mrvgggtCT9Zf//rX7rXXXgs+mvlZIdZ+++3XchSbbrqp072gIf9LL710U69P9/wzzzzjlllmmTAkXT15Fd7rOZF77723Gzx4cN3qp5m+N9lkk3Du66+/vm7nSdOB478jBJVpahnqggACCCCQRgGCyjS2CnVCAAEEEEiNQPwFU5UiqCzdNDa0NQ09xkrVUj3IJk2aFIbgliqj9VdccYVbffXVQ5Fvv/3WTZw4MYQrmrW5mkXDfPfYY4+wy3zzzecuueQSt+iii1ZziKaW/f77790jjzzilltuOde7d+9QFw3d1VLtJDgKw/Qczpdffjn0Ig0HKfI/uo8mTJhQZEu2Vymc1gROkydPDp61vpo333wz/KNBfH9988034XmxOpfuRQXE6tFYbjn44IPdgQceWK5It7Y9//zz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V9my7bDxgw8+CJME6We+nh76XXDttde6mWaayT333HOZorV7ZrPNNnNjxozJVN2zWNn4bwhBZRZbkDojgAACCDRSgKCykdqcCwEEEECg5gL6AliqF2U1E+aUq1j8JZOgspwU22opoAl/nnjiCXfPPfe4AQMGlDy0hU66T+eee+6S5dplw8iRI90555zj9KrHPdRrWXfddd1LL72UuaDyww8/dHpcgJaNN97YqWcoS30F4r8hBJX1teboCCCAAALZFyCozH4bcgUIIIBAWwpU0ouymglzyiHGXzIJKstJsa2WAhZUXnzxxW799dcveWjd5++++6679dZbw0zeJQu2yQYLKnfddVdXr+d2qgerAmItWetR+fe//z2Z8Z4elY35oYj/hhBUNsacsyCAAAIIZFeAoDK7bUfNEUAAgbYVUEg5evTo8Ey+N998M8+hqxPm5B2k4ANfMgtA+NgQAQsq//CHP7jf/OY3Jc+59tpru1dffdXdfPPNbskllyxZrl02WFC55ZZburPOOqsul60h+WuuuWY49nzzzRee91iXE9XhoBMnTgzPptSht99+ezdixIg6nIVDxgL8DYk1eI8AAggggEB5AYLK8j5sRQABBBBImYAN89aX7XiZd955XXcmzImPVfieL5mFInxuhICG5T7zzDNumWWWCb339AzKL774ws0444xu7733doMHDw7V2HTTTd2TTz4ZZnFeeumlG1G1VJ/jtNNOcxdccIGbffbZ3a9//Wv32muvOQ13nmGGGZxC3f3226/b9f/HP/7h1BtRi3q0qpdcVpaxY8cm4eQhhxziDjjggKxUPbP15G9IZpuOiiOAAAIINEGAoLIJ6JwSAQQQQKB6ARvqrZ6Uhb0oazFhTrka8SWznE72tn300UfuuuuuC8OpSz3T8auvvnK5XM716dOnqgv89NNPnSbB+eUvf5ns9+2334ZJXaabbrpkXak3Gr6toE09JMstBx98sDvwwANDEZvBefLkyW655ZYrt1tmt33yySdO4eAjjzziHn744RDWHn/88W6BBRYI16QQV5Ncvfzyy2FioVIXWqtQUXWw518OGzbMnXHGGaVOmbr19vxOVUy/T7fYYovU1bHVKhT/DZk2bVqrXR7XgwACCCCAQE0FCCprysnBEEAAAQTqIaAvedaTMg4p1YtSwYNm99VrvZb4SybPF6uXcveP+/HHH7tHH33UPfbYY653794htFMPw1lnnTXv4OpBpqCy1EQiOo7Cb/XAmzJlSjiWDqBeeeqpd+WVV7q+ffs6DS1WSNivX7/k+Hou4h133OHuvfde9+WXX7ojjzwyTIij5xjuvvvunc4Yb70jkwP6N+oZuOGGG4aelUsttZRbeOGF3U9+8pOkyI477hgm3LnmmmvcCiuskKzv7E0l19PZMWy7Ql0NPX/wwQeDh8Kv2MXKFb4qxP3ss8+CZ8+ePQs3B/OTTjopzK5duPHMM88Mvai1XsPjzz333MIibpNNNgkm6pW62GKLhedJdihU4YrvvvsumUX8/vvvd9tuu23Y88ILLwztEx/mm2++cePHj3fqvShn3Wu//e1viwbJsrvqqqtCeQWtGr6vEHr11VePD5n3vjO3vML+Q1z3UaNGJTN9K/j9+c9/nle8lvdF3oHb+EP8N4Sgso1vBC4dAQQQQKAiAYLKipgohAACCCDQDAHrRamQUoFRvFgvSgWU/fv3jzfV/H38JZOgsua8NTmgQrpjjjmmaG+63XbbzR1xxBFJuKeecOoRV+rZguplpmcbKlxUL77pp5/e6ZmECiYV4sSLnlN42WWXJausd6NCs8MPPzyvPqWC0WRn/+aKK65wJ598sltrrbXc008/7d54440Qdu61115xsbz3Fo4q7Fp11VXDNvUwVJimz4ssskheeX2o9Ho67FhkhQLZXXbZJYSU8WY9V1PXIr/CRTOZq80U6mpiGi0KFeVmPU+//vrrMLz6+eefD9ttKLfabeaZZw7l1UZaNDu6HAYOHOj++9//hufXFrZNKNiF/1EvVwWhmuFbddBs37/4xS/cscceG4727LPPhvrYoUt5qK6671R3WzSUX6HkbbfdZquSVwWd+j0XL5W4WXmFkwpRL7/88jDZku4DTcok73HjxrkVV1zRTZo0yYqH11reF3kHbvMP+n2i3ytaCCrb/Gbg8hFAAAEEOhfw/4rLggACCCCAQOoEfDCZ889Py6222mo5H0zk/af12t6oReeyOjTyvI26vqyf56ijjkraR+2kzxdddFFuzz33TNb7kDH33nvvhUv1YXOy3odKeZf/n//8J7f44ouH7X627bDNDzvO+SHVYZ2O40PA8N/KK68c1j333HPJMfyzI8M6O8b++++f82FjzvcazPlecEm5St74noThWH6obtni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NwIIlTwJEMiBgATIDz74wL322mvulVdesUyln376adY7x40b57p165b1eiEuSCzdbbfd3F577eWUzKCcSjmvrZz2Kb6WKVOmuEGDBtnzOHbs2PglziEAAQhAAAIQgAAEIAABCEAAAhkJIFRmxEIlBH4j8PPPP7urrrrK3Xrrre67776rhmW99dZzW2yxhVtnnXUsDt+SJUvc7bff7iTMrLrqqm7x4sVuyy23rHZfISo+/PBD17NnT+v6vffec61atSrEMI3SZzmvrVGAFmHQqVOnupNOOsltvvnm7oEHHijCiAwBAQhAAAIQgAAEIAABCEAAAqVOAKGy1HeQ+ReUwIwZM9yhhx5aZQxZLO6+++5mMdm+ffsq18ILWV7uv//+9lLWjQcddFC4VLBjXMx76aWX3BprrFGwsYrdcTmvrdgsizXek08+6Y455hi3ySabuMcee6xYwzIOBCAAAQhAAAIQgAAEIAABCJQwAYTKEt48pl54Ap9//rnr0aOHWVPKlVsZjFdbbbVaB3744YfdgAEDonayKJNlWSFLXMxTIpM111zTzZo1y+Jmyrpys802c8svv3whp1Cwvst5bQWD1sgdK+t3v3793EYbbeSeeOKJRp4Nw0MAAkkjoPcIsnknbVeYDwQgAAEIQAACEGh8AgiVjb8HzCDhBAYPHuzuuusuSwxy6qmn5jTbX3/91V133XX2Ty7jV155pTvkkENyujdTI7mgK0amkuRI+ImXTz75xMnV+80333SjR4+OX6pyPmzYMPenP/2pSl3SX5Tz2jKxX7RokVOSpvXXX9+1bds2U5OSqQtWxQqP8Mwzz5TMvJkoBCBQeAISKUeNGuVGjBhBdvDC42YECEAAAhCAAAQgUFIEECpLaruYbGMQCEKljkoOkk/5/vvv3TfffGNu2M2aNTPLTImWsm6UtVkqlXJyL1dinoqKCrfNNtu4FVZYwYb4+OOP3aOPPur0gU5tQozMSy65xB199NHWJm5pmG1enTt3tvHkfr711ltna9bg9VqbMpDXtTTU2uo7D80/iM257FtY7zvvvOMktCqGabt27UJ1laME6Mcff9yyxz/77LPu/ffft+t6BiT0tWjRokr78ELJneTer2drxx13bBBRU8+b4rEed9xx9hxqLD17ejY7dOhgz86yyy4bpmBHWezOnDnTrbLKKq5Tp04unun+3//+t/vDH/5g8VvVT76ltjXWZU/ynQPtIQCBwhBQSBQJlRMmTMCqsjCI6RUCEIAABCAAAQiULAGEypLdOiZeLAJBqDzxxBPdeeedFw0rIUXijiwdP/vsM7N23Hvvvd3KK68ctUk/eeutt1yvXr3MKvLBBx906jNubXb44Ye7v/zlL5a858ILL0y/3V7HrTOnT5/ujjjiiGrtTj75ZLfffvu5jh07VhGPqjXMoUJC36uvvuokpElw23PPPSMxNf32r7/+2pIJPffccya+yfpTLvPbbrut23fffd1yyy2XfkvW1/VZW0POQxPMdd/Udu7cuU5798gjj+ille23394yscu6MBS1U7IZCZLpRcmZtP648BfavPjii+6cc86JRE3VS4S+4oorsvKVqCexcN68eSYq/v73v3cbbrhh6NKOt912m7vgggssruSxxx5ronx8bmPGjHEHHHCAtRVf/S7ce++9UR/a61tuucVtsMEGVqffC8VyVaiEl19+OWqXy0kua8xnT3IZkzYQgEDxCCBUFo81I0EAAhCAAAQgAIFSI4BQWWo7xnyLTiAIlRKZevfubeLRG2+84ZQsJL2ceeaZ7pRTTomqJWQq4U6wRJOVncRMiTcSLO+44w5rqzhdsriUpaSs02RtGYrETAk+EgllaSchNPQnF/MbbrjB/fDDD26rrbYyazjd99BDD5kVZeijrkdZNZ5wwglOx1A0zj333OMkbIlHSNozbdo0c49fuHBhaFrlqBidmqssR3MpdV1bQ89Dc81l3/bZZx8TKSUaShBU2XnnnSMherfddjMhzy74H9rjYGkoNscff7yTgKhs8SuuuGJGMVgC8GGHHWZd6FmQFeMLL7xgryUc6lmJl2+//dade+65VQTFcF1xI+NhBJSt/vzzz7ckULLs1JpV9thjD7d06VITMTfddNNqawz96aj+ZCGqZ1nPvuK7ap5vv/22NdNzKlfPV155xfXt27daoio1ynWNue6JDcwPCEAgUQQQKhO1HUwGAhCAAAQgAAEIJIoAQmWitoPJJJFAECqzzU0io1yqJTJJjGrTpo01DRaBl156qTvqqKOsTgJWPHmABEtZoUn8C0VWaiEWpq5L3Nthhx3C5RqPmoOs5xrCnU4WlBK+1J+KrPxat27tZE138803uwMPPNCEKQleEp70OhRZXepetVc/Y8eOdRIwJVpJEJOF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dlRAAAIQgAAEIAABCEAAAg1LAKGyYXnSGwQgkCOB2bNnu6FDh5rlZPv27d3BBx/ssKTMER7NIACBghG48cYb3aWXXlqtf9UdddRR1eqzVSxcuNCtttpqdvnZZ591l19+uRsyZIjbbbfdst3SqPU///yza968eU5zSKVS7tdff3XLLrtsTu0L3eiXX35xzZo1c8sss0ydhspn7XUaoERu+umnn9wPP/zg2rRp43R+5plnuh9//NGNHDnSLbfcciWyCqYJAQhAAAIQgECpE0CoLPUdZP4QKEECEilHjRrlJk6c6CRSdunSxaluxowZrmvXrg537xLcVKYMgTIgMGXKFHv/CUsJQmMQHV9++eVwqcbjO++84/bee297n/vjH//ohg0b5iZMmOBOOukkd84552S9V6LQK6+84mRt/vHHHzuN+9VXX1mM3lNPPdVtttlmWe+tzwUJdfvuu6/73e9+Z3Ouqa+vv/7a1iGL07vvvtttuummNTUv+DWxPu6449yKK67opk6d6lq0aJHXmA8++KA777zz3A033OB22GGHnO+VkJfvWDl3Xo+G1113nRs3bpyJ6nvssYfbaKONcu7ttNNOcy+88IL9LZ4zZ47r3r273fv666+7lVZaKed+aAgBCEAAAhCAAATqQwChsj70uBcCEKgTAVlSIlLWCR03QQACdSTw0UcfuVVXXdUtv/zy7tNPPzWX7nbt2kW9SXhSIi+Jg3vuuadTEi+JM99//737n//5H7PYO+GEE6L2NZ08+eST7phjjnHHHnusu+iii+xcdeqzb9++0a0S/ST4vfrqq+6ll15yTz31VHQt/aRz5872vpler/nKCm7ddde1BGSydKyoqMjZOlL9afwDDjjAun7jjTdc27Zt04eJXkvYO/nkk+21RLHevXtH18KJxNZbbrnFBMRtttkmVBfkeMEFF7jbbrvN+pbIttZaa+U1jkTOadOmuT59+rjKysqs94qrrP4nTZpkguh3333n9tprLzd27Nis99R2QX28++67FlqgNmtWWbEuWrTILV261K2++uquZcuWGbv//e9/79RvKBLbN9lkE7f77ru72oRL7eWbb75pz6K+PDzwwAPNKjhXgT6MyRECEIAABCAAAQjUhwBCZX3ocS8EIJA3AX3Ik/ujiqwnVbCkNAz8gAAEGoiARMfzzz/fffbZZ07CjQTBO+64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zAlInNf+UyCQD4GTTz7ZnhtvUW639e/fv8r7yrnnnpvy4TSs7tprr63StYS88L670047pT766CO7Ht6bttlmm6i993qp0q+PMRy990WNYif5ttetei/V+154H9Tc9HclfMmj+vS/A9OnT4/eq3Vd78kSHzV3fdGjOr0O5YmYsCtBVGPqX+CgdVEgAAEIQAACSSSAUJnEXWFOJU1AwmP4j6c+jMWLRMy4taXaZrK4jN/DOQQgkCwC+vAYfsf1wTle9CHQZ+RO/fjjj1YdPjyqvSwIQwnWiPogOWbMGPtwrQ/PPmxE6t133w3NMh5lMRME0TAPffCUpU2mUlv7MEd92I1baIYP8GEMHb27rg3h3cEjBrJSihef7Ty6NmXKFLs0YsQIq/Mu3ykfi9KsyPUhW4LDrbfemvIJfOJdcF7mBBAqy3yDC7A8rNixYi/AY0WXEIAABCCQUALEqCwtT31mm3AC8SQ6mmo802968hwyfCd8M5keBDIQ8AKkxdVbuHChXb3zzjudFxgztPytShm0t9xyS4vjOHr0aIvHqCvKpK2ixDV77723ndf045133nE//PBDlezbn332mVOSHv1TUfZsZR6vqKhw+bT/9ttvozmccsopbo899rBYld6d2/o99dRTLRanEuccdthhzlv9OMXdPPjgg+264mnuv//+lhhH2cJ1LZTXX3/drbTSSnbP9ddfbzEu77//fte8efPQhGMTJKCs9krQ9MknnzTB1bPkuhD461//6nyICrv1X//6l1t99dXt/JJLLnE33XSTxdW9++67LT7upZdeau81iqsbit6jFAs3W0mPwat2em9UvF09r6Eofq9ij/fs2dMts8wyodqOubaP/13Q/L0FetSP/xLKxlSF4v4+99xzFo84nohMcYO9NWl0j06U2E1xgI866iin9U+bNs0p3nG2okRu8XVla0c9BCAAAQhAoFEIJFRAZVoQKEkCwUpElkdxt+8QjytYJsmqsjZLSrmDy028tnYlCYpJQ6BECSg2Wfg9VqyvuAVitiUFd0UvAkZNgmu0LCu9sBfV60R9yjpSlonvvfeeXfPJeGxc3adYlvESj9UmS0uVfNrHXSLD2sJRrom6HlzYVe9FWqvzH7AjFqF9/OgT40TT1BrDNcXkXbJkSXRNJ3JT9x/IzdoS68oqaMryRfhbWZaLY1ENTgAr9lQKK/YG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8MNml112sSnGguyMM85YotQ3J1XLhZyvGFN7orKqav7NVT+ZzYcffmgmTpxolllmGTNgwIBknum6UAjsscce5pZbbrFpeuGFF8zUU09dqPTVOTGuJhOwKNsEuc7lx7wTgTIjoIXzKpKUUjY6n7Dj5F+Q4ZMIEAEgUCZZEJpjuETtySeftAQYiJlRo0aZBRdc0PZtPg3Dyy67zBx66KG2sLfffntz9NFHl7rgl1hiCfPJJ5/YPDzzzDNm+umnL0R+IGNdeeWV5oorrgjTJwmDlj7GHpp0ERg9erQ55JBDbKD77beflaHSjSHf0LRcWOV5WVxUa01UupPXKqn5x60APnd33HFHuDoxePBgs9NOO5kll1zSLLDAAj7ntCs4Arvttpu57bbbbCrvuusus/DCCxc8xfVKnl49k5yzLxIk+CQCRCALBPT8pw6TYZ1f4MkFoSxqFcMkAuVDoCx9w9dff21AOMpZkz6kr776arPSSis1fbr22mtDAmeTTTYxp556apObMlloohKalYsuumjPkv+///3P3HjjjebSSy81jz32WMt03HTTTWappZZq6YYfkyGgicoNN9zQnHHGGckCKKBrLRfWfWG1tkRlWQamXrQfrYGn459vvvnsqiO0LNdZZx2z7LLLmimmmEI74XsBEZAtEkha3Tu8AhaPTZJezYdFHYiDopYF00UEqo6Anv/Uqa/RmgooY5KVVa/pzB8RaI1AWfoEaA9ieyu2ubYyG2+8sTnttNOanNx6661m9913t/Y/+tGPzLnnntvkpkwWmqi87rrrzPLLL5978vv6+uz2c5z5+dJLL7WNH+dpPvDAA2baaadt65YO4iOgicrVV1/d3skQ33dxXYpcWKc5mq80SFR+iwo1mCZXjw022MBAlb6dQae72WabmS233NIstthi7Zzze48Q+NWvfmVX+xD9mWeeaVC+NMVCQBMHkjKSyoIEn0SACKSFgO5r6jgBLgsxkVZ5MxwiQASiEdD9IVwVURaExh52tt13331hRkB2rbvuuuaDDz4wd999d2iPF5/W3v3332+22247664KZI4mKi+88EKz5pprNmCQ9Y8nnnjCnvn51FNPNUSFclljjTUMzqjEeYkgmGGHi0xxLih2J9Kki4AmKqGtivpfBaP7pjrLg7UkKjlRbd2EtQZea5eTvw4dOtTAX96DxeQU8C0KgQMP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ooptueglln763DqAGEhWpo8zQyQCLgJawCdR+Q06n3/+uVlkkUXsjxdffNEMHDjQPPzww1abcvDgwWbs2LEujLn9fu+99wzKbIMNNjAgVKH1CYP0TT311LmlQ0f0v//9zyy00ELW6qqrrjIrr7yy/sz3CiFQxPoHeHU/ht9Vn0fWiqjkZBBVmoYIEIGyIaAHJh5hUbbSY3qJgDEuQVX1ySXLPBqBn/70p2b8+PENDkicNMDBH0QgdQT0PAqBcy5lzEcffWSWXnppi/VTTz1lZpppJnP33XebHXfc0Sy++OLm1ltvTb0c4gZ4xBFHmIsvvtgSM1999ZVZddVVrddXXnnF9OvXL24wqbp76aWXzLBhw2yYJ5xwgiV0U42gZoG9++675s477zRbbLGFmXLKKQuV+yLWPwBUt36s0kQlClS0kPDOiSBQyN7wvJPsMY4bA1ZL+/fvX7gBIG7603BXhfN29MDEyXUatYJhEIH8ECBJmR/WZYmJZGVZSorprBICWiYs22IR5vOPPfaY+fDDDw22oYJYPProo80UU0zRcRG98847ZqWVVrL+n3/+eTPNNNOYm2++2fzyl780yy+/vLnuuus6Drtbj4ceeqi57LLLzA033GC+/PJL85Of/MT0WsvztttuM7vttpvN2jHHHGO22267brNZa/8jR440p512msFzyy23LBQWRax/AEjLg7VQwOuruJlvvvn65G/rrbeueG57n71PP/3U4h2sxIWJefDBB63d3nvvHdoV4eU///lPH/6qbIYPH9637rrr9gWDfEfZDLY59P3rX//qyG9RPBW1/iXB55RTTrFtiH1YEtTolgj0HgFpuzIPCTTpep8opqAQCKA/l3ohT/bxhSgaJqKiCOg2V6a+eNy4cX2Qq6SfkOfjjz/eVUm9/PLLYZgS0JVXXmntdthhB7HqyfOQQw6x6UA5XXvttfYddr00J510UohXoJTTy6RUIm7B86ijjorMz8SJE/v23HPPvrPPPjvSTRYfilj/kE89p8R71Y2pegb1oISOnSZbBIJzRMJOHO8wwcHM1i5YDcs28jahByrmfTfeeKN1BUI1WC20f3ivqkHnjnr/xhtvxMoiCM2rr766TzAJVlWt/2DlNpb/IjoqSv3rBhvpx+owKHWDE/0SgSIhoCeU6IfLJBgXCccqp0X6diEe8IQdDREgAukjoNtb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qLz//vtNv379Mq9CSJn5KuQCGiCgz4ca3XvSpEnuaIzs3QBUDoEAArkXIKjMfRVzgQgg0AqBal3B1VJsmWWWMXqcffbZW1EczoFApgSyGlaq1aFaH2rkcnVdz8sUdsl/8803TY8ePfJyaam9DrXIX2ihhVz51llnHdf1W0G4pmmnndaMHDnSzDbbbO55Fv4jpMxCLVHGZgroc6FCSv0LQ0pG9m6mOsdGAIG8CBBU5qUmuQ4EEEhcwHcFVwskdQXXcz8poNxkk02MuvoQVnoVHhH4r0AWg427777b7Ljjjmbo0KHmnHPO+e/FNHhOIdZzzz1nxo8fb5588kkzzTTTmCOPPDK6P2YjT/fLL7+Yueee2x1S90tUiMzUPIFTTz3VXH/99ebDDz+sepIrr7zSrLDCClW3ScvKLP4sp8WOcuRDQJ//1Iry2muvjS5If6xWSKk/bDEhgAACCFQXIKis7sNaBBBAoG4BfUDVh1P9FT0eVg4ZMsQMHjzYaKRg3cuSCQEE/isQBhz6QjdixIj/rkzh3DXXXGMOOOAAF1YeccQRdZfw559/Nt988437XdC9e/d2+6v7tQa2+cc//tFu3emnn2423njjdsu1QF2Htf755583q666qtloo43MuuuuW3ZbLfz111+NP//3338fDZ6z3XbbmaOPPrrifpVWvPrqq+app54y77zzjjvWIoss4kYO9+eotJ+Wv/322+bOO+90rdAXW2yxapt2uK4j3/gBPv74YzPVVFOZ6aefPr6qzfM33njD+T744IOui7Z8hw8fbqaeeuo224VPfvrpJ3c/YwWS2267rWulqtHi9V4Qn/r3729WW201IzfdA7VPnz6mW7du8c1S+Tz8Gc7ifWdTiUqhMiVASJmp6qKwCCCQUgGCypRWDMVCAIFsC1QKKxloJ9v1SumbLxAGHWkPK8877zxz0kknmT322MMceOCBDkcjgU822WRVoRQk3nDDDUYtMhVWaVKrzLPPPjva98cffzTrr7++UeinSYOrKGycY445zHTTTee2V5fg+HTyySebc889N77Y3HjjjSYe/OnYxx9/vHnooYdc92K12FPL75133tntf9VVV5nll1++3bEqLVDQd+ihh7rrim+j1pkXXHBBNPiQ1n/99dfuHp9rrbWWK4eCv6233jra9ZFHHulUC/RafKOT2Jl7773XtYhVuKpJ7gp633//fdfdOhyB27eidRsG/x1yyCFm1113jZacf/755uKLLzajR482AwYMMAp95axp++23N0cddZTRa2Xfffd1LfBXXnllc/XVV7v15erKrUj5f1n62U05JcXLqACD5mS04ig2AgikToCgMnVVQoEQQCAvAgor1QWcruB5qVGuo1UCWQk8TjjhBKNASuHhn/70J9eCUK0gNbjOEkssYVZffXWz5pprtmEbNWqUOfHEE90yBY3zzjuv+c9//uNaP+60007m8MMPd+tefPFFF0bqibbTYD29evVy6yr9d8kll7gu4VqvAFL3z1Q4eOaZZxqFgTq3n15++WWz9tpr+6dlH9XNvKNz+h0nTJjgAj4fvM4333zuucJIhbK+a7OC1M0339ztJisN3KPrUytKtTb3+2sDtVbdc889/SlqeqzVVwdTUKhQ95RTTml3bIWXCoYVIPrgV93vFWJq2mqrrcx+++1nXnjhBddCUtegeR9qqiXsRRdd5I4tmwsvvLDNObRsiimmaLNMrxWFx2qNv9RSS7VZl/YnWfmZTbsj5cuuQDykZNCc7NYlJUcAgRQI2A9pTAgggAACTRSwN1Ev2dY5peWWW65kA43on57bL7ol2320pG2YEEDgvwL6mfE/L5pP43TwwQdHZfRltQFdm2VXXHFFVHQb2EXrbMBZst2s3bpw+RdffOGW2e7YpfD4Oq4NIqN9ooP+PqP9/Lm9l+1WXtp9993dOW3LvWgX2yW6ZAf4csttK8vSAw88UPrggw9Kr732WsmGl1EZn3nmmWifjmZskBrtp3Pars7RLjrf5ZdfHq2fOHGiW/fvf/87WubPa4PBkg1r3XLbsjM6Ri0zoWNHvjqeDQ+j89uu1iU7OFLps88+K911112le+65x62Tj58222wzt8y2Oi3Ze3m6f/4Y4Xba/phjjnHb+uvS68PejzKqo5deeskfNnq0Iajbx4a20bIszGThZzULjpQxuwL2j9KlYcOGuZ9f/azbluglewug7F4QJUcAAQQSFtBfk5kQQAABBJosoCDStq4p2VZN0QdZH2wosNQXPcLKJlcCh8+cQNoDkL322sv9PCsgVGD1yiuvlBQwfvnll6UddtjBrVOAZVtMlhTW+SDx0ksvbVMXYZhl70fZZp1tpVPyAZZ+Z+h42v+7775rs50duKHN7xZt58+n/VQ2P9mWktG2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ww8/NO+//77p0aOH6dOnjzn77LNNt27dWlKWJE4Svv79+fMSUvrr0SOBZahR3Hl9BgpH9SawLu5rgStHAIHsCRBUZq/OKDECCCBQlwCtK+viys3GYUBZ7j6UfiRv3YdS3XEVWBZhCsMawsrm1fgdd9xhTjrpJPP2229XPcm+++5r9t5776rbdGXlt99+a0aMGGGeeuop8+mnn1Y8lFpZqrXxzDPPXHGbLK8IX/f+OvIYUvpr0yOBZahRrPmw7mlFWay652oRQCAfAgSV+ahHrgIBBBCoKlBr60p9cVVgVZTQqipaRlfWGlD6Lt5ZHiins1UUhjaElca1Khw/frx58cUXXcvCxRdf3Mw333xmqqmmakessO/HH39024UrNaq3LI855hiz8MILm/XWW888//zz4SZGYeBaa63lWlYutNBCZp555nGtGdtsZJ+88MILbsALtbhUa0xtG59KpZJrmanfVfFynnLKKebLL780xx9/vPHdveP7r7jiiu72F2rlqYGjVLa8TuHr3V9j3kNKf516DEOrcLkM/O9B3Y+XKfsC+qwTHzBHv5fUe4QJAQQQQCA7AgSV2akrSooAAgh0WaBaYKkv/Gp5oC9um266KWFll7VbewACyvq8w/CmqGHlDz/8YM4880xz7rnnlsWT0UYbbRStUziocEddphUmTj/99NG6888/35xwwgmuK/fBBx9srrzyShcUrrzyyi4Afe+998whhxxidt1112ifcjMnn3xyu/Istthi5rzzzjOzzjprtIvuwbv//vtH5/Mrfv75ZxeA6rmC119++cWN9P3rr7+aueee29x6661uUwWrk002md8tt4/h69xfZJFCSn/NeiSwDDXyNx+vX73O9budEDp/dc0VIYBA/gUIKvNfx1whAggg0E5AX9p/+ukn90/z4dS9e3cz+eSTR//0nCm9AgqPVIcKaBTK6J+WnXXWWebiiy92o3arxZhvOVTEFpSVai8McYoWVup1om7/vmv2tNNOa3bYYQcz5ZRTmnvuucc8++yzjm2rrbYyRx11lGv5+MEHH7igUituvPFGowDRT+pefcMNN7gWkPHg87jjjjMXXnihOeCAA8yee+7pd2n3+Oijj5otttjCLVdLR92e4KGHHnLPFVLedNNNplevXu75gQceaMaOHWsUhF566aXRsd555x23TAvU/XzgwIHRus8//9wsuuii7rnuk6nfc3mewtd3eJ0TJ04MnxZuPh5oeQAF7WuvvbbRz8IUU0zhF/OYcgG9/+mPLt9//717L9Rnlqmnntq1tObzS8orj+IhgAACFQQIKivAsBgBBBBAAIEsC+j+gM899xwBZQeVGIY5RWpp9s0337guz+KZa665jFoohvdnVJij4FL3eNSAFBtuuKEJg8QJEyZEYU4YYA4fPtyceOKJbdTVFfucc84xO++8sznssMParAufaKAbDXijVpynn366a/Go4HHjjTd295dUGVQWTVqm+07Gw88jjjgiCi41iJgGyfGTggwfXOpnY8YZZ/SrcvcYvq7Di1O4Swuz30TigaWCyi233DLkYh4BBBBAAAEEEhAgqEwAnVMigAACCCDQbIH777/ftSihBWXH0mGoU5SwUq1u+/bt63DGjBkTtZQMta6++mqjbtzLLbec0bwfNbt///7m7rvvjjZVF2wFnZq23nproxaU4aRwUcbbbLONOfbYY6NVX3zxhQsjfRdyvVYVjMbDNL2Wt912W7efwslZZpnFtdzUSOJqqTl48GC3Tq0kwxHENYhU7969o/Pp3przzjuve/7kk09GrTO1QF3BvUe0Q0ZnwtdzeAlx13Bdked9YLnuuusSVBb5hcC1I4AAAgikRoCgMjVVQUEQQAABBBBonIC6wsUHGWnc0fN3pDDcKUJYGbYuVBDYr1+/dpWqcFDrll56aRdEhgPTvPnmm647eBgi6gAaLGfUqFFtjnXBBRe4+1Xq3rcjR45069QNe7XVVjNLLrmk0XoNfqNBeDQp0NSgPP4ekuqmrvtLalJYqvkNNtjAdU9XkLrbbru5Wx5owAzfZV3bjhs3zg0KpHk/zTnnnG5W1+Lndf9LtUC+/fbbo1amfvusPYav47DshJShRvn5jz/+uE14XX4rliKAAAIIIIBAswUIKpstzPERQAABBBBAIBMCYciT97BS4Z8CSI3ivd122xl1mfb3c1N3a93jVPec1HTbbbeZBRdc0IRdvNUyUttrZG21glQX7FNPPdWNnq1Wj926dYvq3A984wNPrVAoqIBxyJAhLqhUi8aVVlop2kfdk48++mjXVTsMQzUYjkYB/9vf/mauuOIKV66DDjrItcLUutVXX92opabKoPJsttlm0TE1oxHNdc2+Fanub6cyqCt7uWCzzc4pfxK+fsOiElKG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76iElOmrE95/y9cJ77/lXViKAAIIIFCfAEFlfV5sjQACCKRCoFQqmb59+7qylI5vbMwAABqMSURBVOuu/Ouvv5qPPvrIqOu3gspDDz3U7LLLLi0puwbFePPNN80HH3zguoerBWZHk65nsskm62izDtfrutXCVC0nK01qcbrwwgubFVZYwehm/37SFyxNM844o1/UsMevv/7a6F+fPn3KHlPlVhf6r776yg1+9Ic//KHsdixMjwBhZXrqIs8lIaRMX+3y/lu+Tnj/Le/CUgQQQACB+gUIKus3Yw8EEEAgcQG1AlxkkUVcOV5//XWjrszhdM4555hTTjklWjR06FDXUkmDxXTv3j1a3ugZBZR77rmnefXVV6NDa7RxdVmeeuqpo2WaefDBB939Fh966CEX0C211FJmySWXdF3KFSbGJ7XgVNDnWxBqcKDzzjvPXc+FF17oRj//7rvvTLl9NejMrrvuahZccMG6unXXck5fzjfeeMPoPmZq5RgflEfdtFVe3edz5pln9ru4R3XjVhd9daP3k46hAYuyPlK5v568PhJW5rVm03FdhJTpqId4KXj//W1wPt5/468MniOAAAIINEqAoLJRkhwHAQQQaKGAgsA111zTVBokR8HdcccdV7ZESy+9tFlooYVci0K1PmzU/SUVPG699dZlz7nttttGA9boXl+6L+S1115bdlst1L0wtY9vZamRu9XVTtPbb79t7r33XncvO7fA/rfhhhuaM844wz1VIPjkk08ajSCs+znKKhwJ3e8TPur+mxMnTjT9+vWLFtdzTu208847G41WvNtuuxl1uQ8nH1xeeumlrsWnX6cRvDWKuqZpp53WLLDAAq7seq77auqYTOkWCMMkBthJd11lrXSbb765eeyxx9oUm4Fz2nAk8oT3X95/E3nhcVIEEECgSAK2+wITAggggEDGBGwgVrKDwZTsqM9lS25bFpbs/RdLiy22mNtO25b7t/7665fdv96FL774YnT8ZZZZpjRu3LjS+++/X7KtK93yTTbZJDqkvVdmtK1t/ejKab/4lWwX9pId9Cdap31tN3K3n713XbTctkAsab/49dhuZ9E5/Iw//5lnnukXlX20gaY73iuvvBKtr/ecum6VyY4gHh1DM7alZFTWm2++OVr3f//3f9HyHXbYoWS7hrt1J554olu+zz77RNsyk24BGyZFdanX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AAIIIEBQyWsAAQQQQAABBBBAAAEEEEAAAQQQQAABBBIXIKhMvAooAAIIIIAAAggggAACCCCAAAIIIIAAAggQVPIaQAABBBBAAAEEEEAAAQQQQAABBBBAAIHEBQgqE68CCoAAAggggAACCCCAAAIIIIAAAggggAACBJW8BhBAAAEEEEAAAQQQQAABBBBAAAEEEEAgcQGCysSrgAIggAACCCCAAAIIIIAAAggggAACCCCAAEElrwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQSFyAoDLxKqAACCCAAAIIIIAAAggggAACCCCAAAIIIEBQyWsAAQQQQAABBBBAAAEEEEAAAQQQQAABBBIXIKhMvAooAAIIIIAAAggggAACCCCAAAIIIIAAAggQVPIaQAABBBBAAAEEEEAAAQQQQAABBBBAAIHEBQgqE68CCoAAAggggAACCCCAAAIIIIAAAggggAACBJW8BhBAAAEEEEAAAQQQQAABBBBAAAEEEEAgcQGCysSrgAIggAACCCCAAAIIIIAAAggggAACCCCAAEElrwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQSFyAoDLxKqAACCCAAAIIIIAAAggggAACCCCAAAIIIEBQyWsAAQQQQAABBBBAAAEEEEAAAQQQQAABBBIXIKhMvAooAAIIIIAAAggggAACCCCAAAIIIIAAAggQVPIaQAABBBBAAAEEEEAAAQQQQAABBBBAAIHEBQgqE68CCoAAAggggAACCCCAAAIIIIAAAggggAACBJW8BhBAAAEEEEAAAQQQQAABBBBAAAEEEEAgcQGCysSrgAIggAACCCCAAAIIIIAAAggggAACCCCAAEElrwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQSFyAoDLxKqAACCCAAAIIIIAAAggggAACCCCAAAIIIEBQyWsAAQQQQAABBBBAAAEEEEAAAQQQQAABBBIXIKhMvAooAAIIIIAAAggggAACCCCAAAIIIIAAAggQVPIaQAABBBBAAAEEEEAAAQQQQAABBBBAAIHEBQgqE68CCoAAAggggAACCCCAAAIIIIAAAggggAACBJW8BhBAAAEEEEAAAQQQQAABBBBAAAEEEEAgcQGCysSrgAIggAACCCCAAAIIIIAAAggggAACCCCAAEElrwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQSFyAoDLxKqAACCCAAAIIIIAAAggggAACCCCAAAIIIEBQyWsAAQQQQAABBBBAAAEEEEAAAQQQQAABBBIXIKhMvAooAAIIIIAAAggggAACCCCAAAIIIIAAAggQVPIaQAABBBBAAAEEEEAAAQQQQAABBBBAAIHEBQgqE68CCoAAAggggAACCCCAAAIIIIAAAggggAACBJW8BhBAAAEEEEAAAQQQQAABBBBAAAEEEEAgcQGCysSrgAIggAACCCCAAAIIIIAAAggggAACCCCAAEElrwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQSFyAoDLxKqAACCCAAAIIIIAAAggggAACCCCAAAIIIEBQyWsAAQQQQAABBBBAAAEEEEAAAQQQQAABBBIXIKhMvAooAAIIIIAAAggggAACCCCAAAIIIIAAAggQVPIaQAABBBBAAAEEEEAAAQQQQAABBBBAAIHEBQgqE68CCoAAAggggAACCCCAAAIIIIAAAggggAACBJW8BhBAAAEEEEAAAQQQQAABBBBAAAEEEEAgcQGCysSrgAIggAACCCCAAAIIIIAAAggggAACCCCAAEElrwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQSFyAoDLxKqAACCCAAAIIIIAAAggggAACCCCAAAIIIEBQyWsAAQQQQAABBBBAAAEEEEAAAQQQQAABBBIXIKhMvAooAAIIIIAAAggggAACCCCAAAIIIIAAAgj8f32IOSxyIyadAAAAAElFTkSuQmCC" + "8088306a-da20-4f95-bb07-c3fbd546762c.png": { + "image/png": "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LjAvIj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjEwMzI8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+MTkxNjwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlVzZXJDb21tZW50PlNjcmVlbnNob3Q8L2V4aWY6VXNlckNvbW1lbnQ+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgociYa+AAAAHGlET1QAAAACAAAAAAAAAgQAAAAoAAACBAAAAgQAAQm6VzT2TwAAQABJREFUeAHs3Qu8NXO9P/CfqOhGKrcodJFLSarnERWdiuRSDh7luJWSpDyF0JUkt05PjrskKp4HxyXl0ilJHU+kkJCUHpTSSRcVQvr3nXNm/WfNnrX22nuvtffMWu95vVgzs+bym/dv9tr7WZ/5/X6L/eOfUzIRIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQOMEFhP4Nq7OFJgAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKZgMDXjUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGGCgh8G1pxik2AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAGBr3uAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECDRUQ+Da04hSbAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECAl/3AAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBBoqIPBtaMUpNgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAS+7gECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAg0VEDg29CKU2wCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIfN0DBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQaKiAwLehFafYBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEPi6BwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBQAYFvQytOsQkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDwdQ8QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgoQIC34ZWnGITIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBA4OseIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQEMFBL4NrTjFJkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgMDXPUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGGCgh8G1pxik2AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAGBr3uAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECDRUQ+Da04hSbAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECAl/3AAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBBoqIPBtaMUpNgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAS+7gECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAg0VEDg29CKU2wCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIfN0DBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQaKiAwLehFafYBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEPi6BwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBQAYFvQytOsQkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDwdQ8QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgoQIC34ZWnGITIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBA4OseIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQEMFBL4NrTjFJkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgMDXPUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGGCgh8G1pxik2AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAGBr3uAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECDRUQ+Da04hSbAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECAl/3AAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBBoqIPBtaMUpNgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAS+7gECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAg0VEDg29CKU2wCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIfN0DBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQaKiAwLehFafYBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEPi6BwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBQAYFvQytOsQkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDwdQ8QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgoQIC34ZWnGITIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBA4OseIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQEMFBL4NrTjFJkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgMDXPUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGGCgh8G1pxik2AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAGBr3uAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECDRUQ+Da04hSbAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECAl/3AAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBBoqIPBtaMUpNgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAS+7gECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAg0VEDg29CKU2wCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIfN0DBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQaKiAwLehFafYBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEPi6BwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBQAYFvQytOsQkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDwdQ8QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgoQIC34ZWnGITIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBA4OseIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQEMFBL4NrTjFJkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgMDXPUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGGCgh8G1pxik2AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAGBr3uAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECDRUQ+Da04hSbAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECAl/3AAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBBoqIPBtaMUpNgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAS+7gECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAg0VEDg29CKU2wCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIfN0DBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQaKiAwLehFafYBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEPi6BwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBQAYFvQytOsQkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDwdQ8QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgoQIC34ZWnGITIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBA4OseIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQEMFBL4NrTjFJkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgMDXPUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGGCgh8G1pxik2AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAGBr3uAAAECBAgQIECAAAECBAgQIECAAAECBAhMQeB73/te294LFy5sLV999dWt+YnO5MfZYIMNetp11qxZldtNtgz5+fODlstRdb7yNrNnz85390qAAAECAxIQ+A4I1mEJECBAgAABAgQIECBAgAABAgQIECBAYGYFykFsuTTlQLP8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AQIECBAgQIAAAQIECBAgQIAAgXEFqrpy1jJpXDYbECBAgACBTKBT6GtYBDfITAkIfGdK3nkJECBAgAABAgQIECBAgAABAgQIzIBAVeteX1DPQEU4JQECBAg0WqDq92lckAeoGl2tjS28wLexVafgBAgQIECAAAECBAgQIECAAAECBCYmUPXltLB3Yoa2JkCAAAECuYDxfHMJrzMtIPCd6RpwfgIECBAgQIAAAQIECBAgQIAAAQLTJFDuylnYO03wTkOAAAECQynQqWtn4/kOZXXX+qIEvrWuHoUjQIAAAQIECBAgQIAAAQIECBAg0B+Bqta9d9xxR38O7igECBAgQGBEBap+vwaFh6pG9IaYocsW+M4QvNMSIECAAAECBAgQIECAAAECBAgQmC6Bqi+jfRE9XfrOQ4AAAQLDLqBr52Gv4fpfn8C3/nWkhAQIECBAgAABAgQIECBAgAABAgSmJKAr5ynx2ZkAAQIECHQV0LVzVx5vToOAwHcakJ2CAAECBAgQIECAAAECBAgQIECAwEwJlFv3GldwpmrCeQkQmIzAOeeck+699970whe+MG244YaTOYR9CEyLQPn3bX5SPWrkEl4HKSDwHaSuYxMgQIAAAQIECBAgQIAAAQIECBCYQYGqL58XLFiQZs+ePYOlcmoCBAj0JvCnP/0pvehFL2ptfPLJJ6dNN920tWyGQN0EdO1ctxoZnfIIfEenrl0pAQIECBAgQIAAAQIECBAgQIDAiAnoynnEKtzlEhgygd/85jdp1qxZrat64hOfmK677rr0+Mc/vrXODIE6CXTq2jnKeMcdd9SpqMoyZAIC3yGrUJdDgAABAgQIECBAgAABAgQIECBAIASqWvf6stm9QYBAkwQWLVqUXv3qV7cV+bLLLksveMEL2tZZIFAngarfv1E+XTvXqZaGrywC3+GrU1dEgAABAgQIECBAgAABAgQIECAw4gJVLYx80dz8m+LBBx/MWjYutthizb8YV0CgB4Hbbrstvfa1r23b8sQTT0xveMMb2tZZIFA3AV07161Ghr88At/hr2NXSIAAAQIECBAgQIAAAQIECBAgMGIC5dZFwt7m3gD33HNPOuqoo9Lll1+e7r333rTNNtukww47LC211FLNvSglJ9CjwC233JI222yztq333XfftPfee7ets0CgbgJVD15FGTfYYIM0f/78uhVXeYZAQOA7BJXoEggQIECAAAECBAgQIECAAAECBAjkAuWwN9bryjnXadbrn//856w72wh6i9Pqq6+eNt9887T22munddZZJz3rWc8qvm2ewNAI3HjjjWmLLbZou57tttsuHX300W3rLBCoo0DV7+Mop4ew6lhbzS+TwLf5degKCBAgQIAAAQIECBAgQIAAAQIECLQEnv3sZ7fmY8YXy20cjVq48sor00477TRumdddd91sTNNnPvOZaeWVV04bbrhhWmGFFcbdzwYE6i5w0003ZQ83FMu58cYbp9NPP724yjyB2gro2rm2VTN0BRP4Dl2VuiACBAgQIECAAAECBAgQIECAAIFRFahqTaR1b3PvhjPPPDMdeOCBk7qA9dZbL2sZGeOfrrrqqpM6hp0IzLRAVZfOa665Zrr00ktnumjOT6AnAV0798Rkoz4ICHz7gOgQBAgQIECAAAECBAgQIECAAAECBOogoHVvHWqhf2WIsXpPOumkKR8wArLoFnfbbbfV8nfKmg4wnQK333572mSTTdpO+bSnPS398Ic/bFtngUCdBbTyrXPtDE/ZBL7DU5euhAABAgQIECBAgAABAgQIECBAYIQFyq17N9hggzR//vwRFmn+pS9YsCDtv//+fb2QrbfeOu22224pWgCbCNRd4O67707xWVaeFi1alBZbbLHyassEaimglW8tq2XoCiXwHboqdUEECBAgQIAAAQIECBAgQIAAAQKjJlAOe+P6jd3b/Lsguq3dY489BnIhMe7v7rvvnrbcckvB2UCEHbQfAvfee296yUteMuZQt956a1pyySXHrLeCQF0Fqn5PR1n9rq5rjTWvXALf5tWZEhMgQIAAAQIECBAgQIAAAQIECBBoEyh/kewL5DaeRi5cddVVWSD717/+tVX+17zmNellL3tZWmedddIznvGMtMwyy6T7778/3XXXXSnGao7ub6+77rp0ww03tPYZb2arrbZKhx9+eHriE5843qbeJzDtAg8++GBaY401xpz3Rz/6UVp66aXHrLeCQJ0FOnXtHJ/fJgJTFRD4TlXQ/gQIECBAgAABAgQIECBAgAABAgRmUKAc9kZRBL4zWCF9OPX111+fouvl4hRh72mnnVZc1XE+uru96KKL0tlnn53uvPPOjtvlb6y++urp1FNPTfFqIlA3gfLY5FG+73//+2m55ZarW1GVh0BXgU5dO/ud3ZXNmz0KCHx7hLIZAQIECBAgQIAAAQIECBAgQIAAgToKVAW+WgvVsaZ6L9MHPvCBdO65547Z4Vvf+taEQtlHH300XXPNNenMM89MF1544ZjjFVdEC9+TTz45bbTRRsXV5gnMuMBaa62Vii3do0Df/e530yqrrDLjZVMAAhMV0Mp3omK271VA4NurlO0IECBAgAABAgQIECBAgAABAgQI1FCg3PpNS6EaVtIEi3TAAQeks846a8xeBx98cNp1113HrO9lxd13352+8IUvpJNOOqnr5uedd15af/31u27jTQLTKTB79uz061//uu2Ul19+eXrOc57Tts4CgSYIaOXbhFpqZhkFvs2sN6UmQIAAAQIECBAgQIAAAQIECBAgkLTuHc6b4KMf/Wg6/fTTx1zcLrvskg455JAx6yeyIoLfGLO3U4vfCNcWLFgwkUPalsBABTbbbLN0yy23tJ3jm9/8Znruc5/bts4CgaYIaOXblJpqVjkFvs2qL6UlQIAAAQIECBAgQIAAAQIECBAg0BLQurdFMVQzEciecMIJY65pzpw56cgjjxyzfjIrPv/5z6doMVw1XXfddWnZZZetess6AtMusN1222VdkxdPrIVvUcN80wS08m1ajTWjvALfZtSTUhIgQIAAAQIECBAgQIAAAQIECBBoE9C6t41jqBYuuOCC9L73vW/MNb397W9P0fq3H9Pf//73tPHGG6c777xzzOFOPfXU9NrXvnbM+jqtWLRoUbr99tvTz3/+83Tbbbeln/70p+nhhx9OT3/609Oaa66ZojX0iiuuWKciK8skBaIur7jiira9JzqeddvOFgjUQKBTK9/oYSF6WjARmKiAwHeiYrYnQIAAAQIECBAgQIAAAQIECBAgUAMBrXtrUAkDKkKEmK95zWvGHP29731v+sAHPpCt/8UvfpGuuuqqdP/996c11lgjvepVrxqzfbcVEZZuscUW6a9//euYzWL84Fe84hVj1s/kin/84x/pxz/+cfr617+eIhCvCqqL5YuwN1qBPuEJTyiuHtn5e+65J3OL++YFL3jBpMeCngnAd7/73elrX/ta26mHKfB94IEH0kUXXZRuuOGGrGV9PNixzDLLtF2vheET6NTKd4MNNkjz588fvgt2RQMXEPgOnNgJCBAgQIAAAQIECBAgQIAAAQIECPRXQOve/nrW7Wi/+c1v0qxZs8YU68ADD0zvete7shatW2+9dVtYG8sf/vCH03LLLTdmv+KKRx55JAuXPvGJT6R77723+FZr/pprrknLL798a7mXmThujAt89dVXpxgn+L777kurrLJKWnvttdOLX/ziFCHGYost1suh2raJVruf+9znsjGNf/3rX7e9N97Ceeedl9Zff/3xNhv3/UFd27gn7tMGDz74YNaau+j3xS9+ccxDAnE/nHHGGdmDBDfddFN2f62++uqZ4Qtf+ML06le/Oq266qo9lSoC+gjlI6S/8cYbs3v2iU98YlphhRXSy172suz+fspTntLTseJBh/KY09Hid7XVVutp/0Fs9Mc//jEb6zqcwvXRRx9Nz3nOc9I666yTXVs8hNHrtM8++6Tzzz+/tfl73vOetN9++7WWYyZ+DuJBjO985zvpBz/4Qfaz+7SnPS29/OUvT1E30SK0H/d620ktDFygUyvfO+64Y+DndoLhExD4Dl+duiICBAgQIECAAAECBAgQIECAAIEhF9C6d7grOFpjRpBTniKk3XnnndO//uu/pmuvvbb8drYc3d9uvvnmaamllspCqAiK4r9f/epXWbfH3/zmN7OukCt3/ufKCI6POeaYTm+PWR9B16WXXpo+9alPdW11+9KXvjQLpNdbb70xx+i0IsYSjuArumyezBQtgSdyvvI5Bnlt5XMNcvkPf/hDFroXz7HVVlul//iP/2itiha0YV3V4jvfKALGCBwjuO02XX/99Snu1U73aL7vhz70oRStWRdffPF8VeXrvvvum84555y292Yq8I3WuBGKf/azn+1qFeMOv//9708rrbRSW7mrFjbbbLN0yy23tN4K35tvvrm1HKFytOwvbtN6szDzla98Ja277rqFNWbrLtCpla9unetec/Usn8C3nvWiVAQIECBAgAABAgQIECBAgAABAgQqBaq+INYaqJKqsSujhWy0iC1P0bJ7m222SWuttVbXsKm8X6/L0ToxuhJ98pOf3NMuMW7u3Llzs1acPe3wz41OP/30rLVpt+2jdeiRRx6Zjj/++G6bdX0vgq9oFTqZVsVx4EFdW9dC//PNaI0bP+PROjb+i9ajEYhGF78xPvEznvGMrBV33B+9dlddFfhGl93RYjSmaBkeLX57mU477bTK7sZj3xgXOoLe2KbXKboVj/B0iSWW6LhLhJ3nnntu2/uXXXZZ1jV128oBL8Q5o5V9p5bx5dNHQP7Vr3513NC3HPjGcaJb9zDpNJ53+VyxvOeee6YDDjig6i3raixQ1cpXt841rrAaF03gW+PKUTQCBAgQIECAAAECBAgQIECAAAECZYFyd86+GC4LNX/5rrvuShtttNGYCzn55JPTpptumjbZZJOurXTH7NjDije84Q3p6KOPTk960pN62Dqln/3sZylaiXZrEVp1oGi9GOOVRve3nabDDz88nXDCCZ3eHrM+wt3oKjhC0WjZHP+98Y1vzLq6HbNxDysGeW2dTh+tsKMVa9RBL4FihIkRnkd3vuNNVYFvtLj+z//8zyxUP+KII8Y7ROv9qq6g482//e1vWYvWCDgnOkXoe9xxx3XcLR4qiO65i1MvrVkfeuihFA/DRHAavSI85jGPKR5iQvPRAjrGEp7otOaaa2bdNcc92WmqCnxvvfXWFC2l58yZ02m3Mev33nvvFK2hTc0SqHqIK65AK99m1WMdSivwrUMtKAMBAgQIECBAgAABAgQIECBAgACBHgV059wjVIM3u/3227NQt3wJp5xySnr961+fqsY0LW/b63IEsJ/85CfTm970pp5bw0b5tt12256CyapyRDe+H/3oR6veSp3C7uLGMa7sbrvtlrUUjnGCJ9uKt3jMfH6Q15afo/waLbrf9ra3jdtlb3m/qIMIiMe7/hhvttzVbwSRhx56aNY9ePm4nZajVXCMp1zu0jm6Od5jjz3St7/97U67jrv+zDPPTBtuuGHldlUtkCMcr+r2PA7w+9//PusC+fLLL28dL8ocD8vEAxMTnaJl7zvf+c6J7tbaPn9Qo7WiNFMV+IZldM3e6wMVK664Yvryl7/c9UGK0mkt1khAK98aVUaDiyLwbXDlKToBAgQIECBAgAABAgQIECBAgMBoCVS1BNKd8/DdAzFWZ4RA5SkPjm688cYUrSKnOm2//fZZF7XLLrtsz4datGhR1q10p1aoMQ5slG255ZZLl1xySTrqqKOybomLJ4jA9lvf+lZxVWs+grxurRQj4IwxjKfSWrN1stLMoK+tdLpsMcZn3WmnnSYdnscDADEW75JLLll1+GzdI488MiYIjIAwWkRXjQsbXQPH/Reth6OVbIz/HMd4/vOfP8Y9Asldd901XXPNNR3PH29Ei+RO90y8323s6Bgf+sQTT4zNWlOnlsY//vGP0+677z7mnst3zH+G8uXxXr/xjW9k4wxXbReG0d30v/zLv2TjZMe9G/d7eYqHEz7+8Y+XV7eW3/KWt6SrrrqqtRwzUa9f//rX29bFQrTEj3Bw9uzZWcvl6PI7Av2om8c//vFjtreiGQJVv9uj5H6/N6P+6lJKgW9dakI5CBAgQIAAAQIECBAgQIAAAQIECIwjUO7OeZ999snGUB1nN283TOCGG27IuksuFztCrwh8Yrr22mvTzjvv3HMLwNjnec97XlpjjTXS2muvnd785jenCKwmMkXoF2FuVUgYx47yPfe5z2075J/+9KestXI57Lv55pvHtBSNHaPr3ujCt9MU4WZ0Jd3vaTqurVzmK6+8Mgt7y+vLy9E6dfnll0/PfOYzs3F7o8VpcXrrW9+aIhTtNr3kJS/pGrjGvnGez3/+81mY2O1Y+Xsx1nK0No/ulaumCHnjAYAtt9wy6yo87oUrrrgi26e8fbS8jTC2aooxfv/93/+97a1oafy6172ubV10Uf3+97+/bV15Ia7x4osvTquuumr5rTHLncbSjg3j5zC6wl566aXb9otumCO8Lk7RurqTUWxX1WV1cf98/pBDDkm77LJLvuh1yATKvXfE5enWecgqecCXI/AdMLDDEyBAgAABAgQIECBAgAABAgQIEOiXQPkLYYFvv2TrdZxoLbnddtuNKdTxxx+fjU2bv/GLX/wiC33vvPPOfFXla7SmXW211cbt+rdy58LK6DL2oIMOKqz539kIeyOYiICvPD344IMpugIuB77RdfLiiy9e3jzdd999WeDYrSvbV77ylSnCr2gp3K9pOq6tWNbrrrsu60a7uK44H+PFRivPaLkZIWU+RQvWGJ+4PMVDAtFit9MU+8S+3aZu3SpX7Xf++een+AyqmtZbb70swI2W3uUpxh4ud+ndrYVvBMHR7XhxKv4sPProo1n31Keeempxk47zG2+8cTb+cccN/u+NvfbaK1WNSbzNNttkLXljbODyVNU6/zWveU067bTTypu2lnsZszqC7Pe9732tfcwMn4BunYevTqf7igS+0y3ufAQIECBAgAABAgQIECBAgAABAgQmIVDV5aPuHicB2YBdohVkVUu+Y489NmstWbyECFJjfNFo8dtpivFaI2SLVqKTnWJc1I022mhMi+IIef/rv/6rMuyNIO6AAw7IwuDieV/60pemaI3Zabr11luzFsjdQt/Y9x3veEc2duwznvGMTofqaf10XlsUKOosWqeWQ/B4L1qDRpi58sorx+KYqVMr1ujquuohgfwAMW5ydE/caYpWpp3C2077xPmqunKOIP6CCy4Y0/o1P87999+fIgSN7ojzqVtLxui+OcbxLU7F1u5VXT4Xt62a/9rXvpbWWWedqreydVWft/FGhMURLFeFvdGCOVpbl4P1CGq7tTyO1sqf+MQnOpYlum+OML7qAYmOO3mjcQKd7rluPxuNu0gFHqiAwHegvA5OgAABAgQIECBAgAABAgQIECBAoD8CunPuj2MTjhJdzsY4quWpU3fGDz/8cPr0pz+dTjjhhPIureUIZqO73he/+MWtdROZqepWN98/wrhoQbrSSitlq6Kr32hVPG/evBQtT8tTXFsEwd2mCH3f9a53pWgJPN4Ux4vwt6qF8Xj7xvvTeW1///vfszD/O9/5zpiiRbAXYeKTnvSkMe/lK/bee+/K7oHHa7V64IEHZqFhfpziazwQcNFFF6XHPvaxxdVd57t1dxzX9qxnPavr/vfcc0+K8Ytj3NlofZ7fO1U7VYXc+Vi8p5xySta6t2q/buvmzJmTjjzyyI6bdAqzwyrC880337zV8jpascf4vfEZXRXix8MWUT+dpgsvvLCym+t8+1488229NltAK99m199Ml17gO9M14PwECBAgQIAAAQIECBAgQIAAAQIEehAod+es1U8PaA3dpCrgikuJYPJNb3pTx6uKMWEjJO3WMjYPyjoepOKNBx54IK2//vpdjxu7ReAaXfj+8Y9/bGu9WTxkbBNhcHns0+I2+XwEacccc0w67rjj8lVdX6ML3re97W3p6U9/etftim9O97VdeumlWavkYhliPlo9f+lLX0pLLbVU+a3WcnjEGMydphtvvDE95SlPqXw7xsCN+6dqGi+QrNongunoVrs8RegZXR73c4rxbyPoLk4R9P7lL3/pON5z3GeHHXZYim7Po8vk8hTdZIdXVavZWB9jVY83Ragdx4ku1Tv9zI0XxMc5vvvd76Ydd9yx8nRxT++///6V71k5fAKdWvnqzWP46noQVyTwHYSqYxIgQIAAAQIECBAgQIAAAQIECBDoo0DVl8C+AO4jcM0OVdWFbRQxun3deeedu5b2t7/9bdY6uFsXzx/72MeyYLTrgQpvnnfeeR2DtcJmPc1O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+cpXpjvvvDNbF922xjjwwzSttdZa6a9//Ws2Vuy3vvWt7NLi3xfxc5ZP8+bNS29+85vzRa8DFoh/s33qU5/KzvLSl740/ed//ueUzvjTn/40ve51r8uOEV2SR9fkMV144YXpve99bzYf/4txg/vd1f+jjz6aHn744fT4xz++dZ5hnBn2z4npqLPyw11xTg94TYd8888h8G1+HboCAgQIECBAgMBICvzjH/9IEU7ceOON6dprr80C3ttvv71ni/gS60c/+lFaYoklet6nbhvGFxb77rtv1rVe8QuLupVzWMpz2WWXpQMPPDB7kCC+4IwvOk0Emiwwf/789MEPfrB1Cddff3166lOf2lo2Q4BA/QTKgW+U0MMa9aunppYo/q6M7ovzqXxvveQlL2k9UPn617++1Ro4377pr8WQJf6N8ZSnPCX798KWW27ZujQtP1sU0zITf3MfccQR2bmqWp1PtBAxBnX+N3yxd5PPfe5z6ROf+ETrcPHvyn72CHXFFVdkXaDHAxPxM/byl7+8da5hmxn2z4lB11dVd85xzvLn8aDL4fjNFBD4NrPelJoAAQIECBAgMHIC8UT0TTfdlLXg/f73v589dR1P4E9luuWWWxo9BtdXvvKVtPfee7cIwmW55ZZrLZvpr8CHPvSh9KUvfSk76Oqrr57ylh/9PYujEZg+gWKXznHWSy+9NK255prTVwBnIkBgwgJV4/hq9TNhxlrtEH/jxkN80fLvcY97XIqHGvfcc8+02267pZ133nlay7rXXnulr371q9k5YxiUH/7wh23nz1vAxsptt902ffrTn257v+kLxcD3mmuuScsvv3yKB/7e+c53ti7Nw1EtimmZOfnkk9MnP/nJ1rmmGnoVA99nPetZWc9QcfBo6Xvqqadm54m/heJvon5OESZHqBzTq1/96nTGGWf08/C1Otawf04MGrsq8NWd86DVh+f4At/hqUtXQoAAAQIECBAYSoH4Eiz+8X3CCSe0WhT0cqHRgjf+Eb/KKquklVZaKQtC41jR1XN8gVPspu7Pf/5zWmyxxdKTnvSkXg5dm23Kge+Xv/zltNFGG9WmfMNWkGLgG9f2k5/8JC211FLDdpmuZ4QEYszed7/73a0rPu+889L666/fWjZDgEA9BYqhVJRQt871rKfxSvU///M/6bjjjkvx91ynYUiuvvrq1hij4x2vH+9H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sS1atCgbp+3OO+/sbYcOWzXhiex+3tsdGCa1ejI/J5M60QzuFF8Gxs99fO7MxFTudq+O44DHgy7xcxjj9fXzc38mvJ2TQL8Fqlr5+mK438r9OV60DI2umfMpWsqeddZZHT/XXvnKV2afffn2p59+euo1bMz3mczrWmut1WppGC0SY0zbfPrJT36SNt1003wxXXrppan893LrzRGcid/p8Xd6jDl71VVXjRGIf8+8/e1vH7O+7isefvjhdP7552f36pve9KYxxY1AOx5oeOxjHzvmvX6siIckouV5Pg0y8M3PMdXX+FmJBzrib9nJTk39N5vPicnVeKfWvbpznpznKO8l8B3l2nftBAgQIECAAIGGCJQD33516dzr5cd4XtH1c7R4KP+jK4LB+MIrgtuY4ouv+LIsunsrB8Mx5lR84XfZZZd1PfXxxx+f3vjGN7ZtE+siCJ7oFF8oxn/R9dnqq6/e1hXfRI81SttHS+iJPlUfwd2sWbPSi1/84qw75xe+8IV96XJukO79ureLZYxwLu71aNkS3VmvscYamUuvoeZUfk6K5aia//Of/5z9vEbL1ugu/rnPfW5af/31p72b8wgx43Pti1/8YlbMeOhjmWWWyeajXPGZEl0YRgvzFVdcMa299tqZYYSenab4sjV6P4iWMNGt+9Oe9rQU3bzHZ1J0NV41/eUvf8mOnb83yBa+k7kvfve732VjJUZLxvgcizH18um+++5LF110UeuBmajL+OzdaKONshA9384rgWEWqGrlW/47ZZivvynXFp/P0RK22LrvmmuuScsvv3zHSyh3/zodPYbE76bi2KjRs0lxnPcf/OAHbWP25mPcdryIEXkjuuT92Mc+VhnyFgnKv8eK71XNx30TYz7Hw4MxTEve8jRau8Z/5X9nVB2jH+si9I8W5jFFK9X11lsvm4/7IVqo5+F2PBQbfwNHy/BOLRUjAD333HNT7HvjjTem6DY7fndvttlmHR9oiIdYYgiVfIq/E4v3ab6+Tq+HHXZYOumkk3oqUtTry172suzvnLB93vOel57xjGd0/NuteNB4aDn+9ouenyKYX2655bLPlRVWWKG42YTmp3pMnxMT4m5tLPBtUZiZooDAd4qAdidAgAABAgQIEBi8QDnwvf7663seVylaL8aXCzEOU7nLvF5LHl94ffrTn842j/AlvmCNL8U+//nP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AQQQQAABBJIhEG06Z+4XkyFOmZksYP6u0nt1XcxRv7yOJZNbmbojkLkCBHwD1HYEfAPUGFQFgQwX6NChgxw7dizsKgoLC2XIkCFh6ZESPvnkExk6dKhEGtmrQc3XX39datasGamIEqV/9dVXou/4nTVrVszAr577mWeekTZt2rjOUVBQIJs2bXKlLViwQLp06WKl/fOf/xQdebt//345dOiQfP7551KvXj3Rdx/feuutcuONN0rZsmVdn4+1o+8v/s1vfuPKds0114j+EGBBAAEEgiBgdkxonejAS23LJBLo1VE1dBaltp04GwIIIIAAArkm4OyPdF47o3udGmwj8D+BgQMHhgK8GvDVfyvOQQNM6/w/K7YQQCC1AgR8U+sd8WxmJxxP8kek4gACCMQh8MQTT8hvf/tbz5x333236BTEV111ledxTdRRtjoaWAOqZ8+e9cynI2E1T5MmTTyPlybxwoUL1ohfnSraK3DtLFuncG7VqlUoacKECaI3186lf//+ntNcO/OUZnvOnDkyffp0VxHq85e//MWVxg4CCCCQLgHzXlPrQcA3Na3hZR/pzPoboG3btqJrAr2RlEhHAAEEEEAAAb8Eot2nEPD1S5lysk3AGfDVa2Na52xrYa4HgcwVIOAbkLYzb7AI+AakYagGAhkqoEHarl27Rhwlq6NjR4wYITfccINcf/318q1vfUvOnz8v7733nixZsiRshKwXw4oVK6Rly5ZehzzTNLAwfvx4ad++vXTv3j2ud9tq4FdH/GrwOtJUz3ota9asER1Rq4vm1YC3uWzbtk2qV69uJvuyr4HxRx99NKwsDfhq4JcFAQQQSLeAea+p9SHgm5pWiTRqxnl2vfdnNK9ThG0EEEAAAQQQSIUA0zmnQplzZJuA9k/pzHH20qJFCzl+/Lir36pnz56hfio7H2sEEEAg2QIEfJMtHGf5ZiccAd844ciGAAIRBTR4e88990Q8nugBDWDq04vNmjUrURE/+tGPrMCs/SEN+j722GOiAdtYi071/PLLL8uvfvUrzxHHvXr1skYjazl60z1y5MiwIps2bWoFs7/xjW+EHSttwty5c626meWYo4/N4+wjgAACqRIw7zX1vEw1lnx9L3f7rHq/z2heW4M1AggggAACCKRDwBypaNeB0b22BGsEEEAAAQQyR4CAb0DayuwMIuAbkIahGghkuMCUKVNk4cKFvl2FvutW34dbt27dEpepTzea7wLWYK8GfTX4G8+i79vt16+fHD58OCy7vo+3XLlycu7cOencubPryUo7s06P+cILL0h+fr6dFNdaR0wfPXpUTp48aU2F3bx5c9fnnnvuOZk2bZorTXd0eunRo0eHpZOAAAIIpFrAvNfU8xPwTU0rmB2pjOZNjTtnQQABBBBAAIHYApFmIiHgG9uOHAgggAACCARNgIBvQFrE7IQj4BuQhqEaCGS4wKVLl2TGjBny9NNPl/pKNCg7a9YsSXSErAZhvQK1WrEOHTpI3759pXXr1lK7dm0rcOussE43ffDgQfnoo4+sIKrzmL29evXq0KjjTZs2SUFBgX3ItdapnydOnCi333675OXluY7ZO//5z39Ep4B+9913Zf369WHvEX7llVfkpptusrNbQeSpU6eG9u0NHdX80EMP2busEUAAgbQJmPeaWhECvqlrDp0uUe/vdeHdvKlz50wIIIAAAgggEFmA6Zwj23AEAQQQQACBTBQg4BuQVjM74Qj4BqRhqAYCWSKwaNGiiNMhx7pEDYzed999ou8kKc3Sv39/ef/99+MqQqeNrlChQiivjqyNtWzcuNF6J7GdT+u8YcMGezdsXb9+fbn11ltF11WrVpUTJ07Irl27ZMeOHXLgwIGw/M6EOXPmSO/evUNJ+v4Wrw58fZewBrJZEEAAgXQLmPeaWh8CvuluFc6PAAIIIIAAAgikT2Dp0qWybNmysArcddddor/fWRBAAAEEEEAgswQI+AakvcxOOAK+AWkYqoFAFgnotMT6Tll93+yxY8ciXplOs6yjcTUYesstt0jNmjUj5i3JAZ3OWX84aj38XurUqSObN292FatBYh1hq/999XsxA75a/uzZs2XmzJmhU6njli1bSjx9dKgANhBAAAEfBcx7TS063QFfrVNxcbGMHTvWxyulKAQQQAABBBBAAAEEEEAAAQQQQCD3BAj4BqTNzU44Ar4BaRiqgUAWCly8eFH27t0rZ86cEZ26+KuvvpLLly9bI2qvvfZaue6666RMmTJJuXJ9D65Ocex3EPbZZ58VfUewuVy4cMF6R7C+Y9evpUePHqJTX+koZOei007rO3tXrlxpJXsFhZ352UYAAQRSKWDea+q50xnwNacQTGddIrWDmhUVFVlBac3Du+wiSZGOAAIIIIAAAggg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zzzzTHjhhRfCBx98EN5///1w2WWX1VA6hM022yyXzKqpEmVuGwTefffdQHxIxsOHH34Y/vKXv4RPPvmk6vah/kUFLCtFgDi+KFrNpTFn+c0kpm+n2ddffx2WWmqp3HHB/XBfeYYC8r333oun9t5777DrrrvmZWtKGnF5iUeN8nrKKacMs88+e/jZz35WeG1P+O61115ht912K8yrE41HIJ2oKFpkUM+WMK5x7Uzs6bfffju3aiYQ2yVerj2HEL78kwkBISAEhIAQEAJCoK8hwPcQnpVSk8o3RUTHfQWBPNW73bsIX0NCWyEgBNoBARG+7dALY9qQ9zGlH4w26Zwam4Gb1quvvjrGrlt44YXDPvvsU7XrUcpCHE4++eRhggkmqPHKlbNDTj7wwAPRpWbexwrxFscaa6ww9thjV66sj+cgFmVPiAtUnWeddVYkf/o4lHW7fchVSNZ55503LLLIIl3qHT16dOAZa0T81xdffDGsu+66mWq3y8WrSNh3333DzjvvXEXO7mXp5OeffoPwhWTsZBLm0EMPDRdddFFuB5Yj/D1pinJ88803z62jEYlfffVVgHS/+eab4zZ1sV0pprBv+0477RT222+/wmbiEYFn6Ycffghzzjln6NevX2FenegeAq0gfK2l5eL6kod4uVdddVWvIFlRC/NtD8ENmY21ynV1vLj+EwJCQAgIASEgBIRADQjkzVFSXIRvDSAqa69BQO6ce01X6kaEQJ9AQIRvm3Rz3seUCN826Zwam3H55ZeHP/zhD1mpM844I6y22mrZcdHOd999F/O98sorgfivf/3rXwsVbKirTj/99PDoo4+GL774Isw000xhoYUWii5hp5122txL/OMf/4jqGU4uvfTS4ZJLLon5vvnmm3DaaadF5Y0pyCDLcD/bSPIpt5F1SASP888/P9xxxx1RETf11FOH+eabL2y66aZxW4dLxCpWXnnlqO6tpj76kwlfcKUt9Ndkk01WTdEACX/dddfFP6zeeOON6A6aOlZdddX4D4K+HQzl4uOPPx7HI5P2888/f9ULHdL2d6cPIaVwCwoZBZnOszHRRBNFgveaa64JF198caYQnWuuucKAAQPCAQccECaeeOL08t06PuaYY8LZZ59dVVnax2IQntnf/va3YbbZZgtTTTVVWZVkNRVDlKAwxl0w9+itns9/d/rHt6VV+7zf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Nueff35JffXdBasOV+TzxVdZ9EoMs0mWuEkClsQ/iX2uS2+54JZ7Xte68bDDDjNTp04Nqo1zAS7rSwnjNiXFdLVl6rmtZl9tu2s9PvY+cVtZ68raTpasn3/+eUExibQShTVeflpvvfVCF8pyBS0hyCY/Dq7yXdfcvoWwzivmri/MKt8m9342z91qYYUsaiXy9u7d2yy00ELu6dT77jzVRYrhu+OOO4bXy8pYf6v8JPfNYuULyH45jiGQdwLFRF9977mCbxorX/9512WEpadLo3n2k+YRY94840xPIACB8ggg+JbHraZX+V9cesDxXZbUtAFUDgEIQAACEIAABCCQawL+86Q6wwuQXA9pUzX+k08+KYhLKavQUuNU3nDDDeaEE04IuTz44INmhRVWCI+18+2335o5c+YElsRyLysBSgJlo1KS4KsYuXJtLTE6zhVuOe1249nK3axil5aS3DipEsUUj1fW2datreqSxfUaa6xhHnnkEbPnnnuG1cvVs9wyJyXfTbfE4bvvvrtAJNbfLonCf//738OqZK2s38laKCDLSCXFhJblp00S0BS7OSupmn21far1+Nj7FNtKhJWFrYRXNylGtSxb/SRh9eWXXw6y3fi8fnxfe53msaxllXxBWC6TJTjHpe+++65dnGlbduWVVzYSaVVHx44dbXbZW9dVvSr54x//aHbeeeeC+l599dXgnuqrmzT3tdBBnyUSBJqZgG/kUqyv+g7wr3ENYxB8ixFsvvP+fLA95P25JcEWAhBoZQIIvhkcfdw6Z3BQaBIEIAABCEAAAhDIEQH/RQjWvTkavBZoqi/qzJo1yyy22GIl9fzmm28O3D/ai6IEX3suK1tf8JUl6xVXXGHmm2++ID5oLdopC2FreVmqAOoL8xJXZY195plnFsRcPvjgg81vf/tb079//1DEU19s/NK4fk2bNq2de21Zckr0/vTTT414ySXzm2++GVeFkTW0jZnqioi64JVXXjELLrhg7LX1PFHtvqrttR6fUvnIgllzwxf5X3jhBdOpU6eC6jSXZIWvZC22db3EUf098JO11vb7rHKKo6sFAHHJ/9xp8YDmmT53m/+wIEDbaiW3X6rz7LPPLlgEYe8jV9ynnnqqGT9+vM0Kt1dffbXp169feMwOBJqRgP+cmtTHqPi+7nNtUl0sdkwim99zcSK/Oy/y2ztaDgEIQKAyAgi+lfGr2dX+A4u7eq1mN6ViCEAAAhCAAAQgAIHcE/AXD6pDvADJ/bA2VQfuu+8+s99++4V9KueF7J133mkkNNpUjpWwvbZeW194SmMBW0nbfHHMWuKmrVPur924qDYeqWIs7rbbbgXVSKi79dZbwzxZA8+cOTPWWvm1114LYptaMTq8sIQdWWf+/ve/N3369Amsf2V5bNP6669vJk+ebA8buq12X21najE+soqX9bziKUvAl6vhUpKsaSVWutbYDz30UIELd9XnuhrXscT5yy+/PDbGrV1soEUEElFtkmCrhQxJSVbpchttU6kLH+x1aba+hW+x2MK+pwJ7D3kvGDZsmOnQoYPNYguBpiMQJ9r5HbVWm355++zgvz91r7dl3Dz2800gyouR7RHjbUmwhQAEWpkAgm9GR99/YLEPOBltLs2CAAQgAAEIQAACEMgIgagXIbwAycjg0IyAgISds846K9j3Y8CmReS7Dx49erSRFWCWky/4yoXzlVdeWbMmS3AdMGBAWL/iIi633HLhcbGdM844w4wZMyYspvq6dOliZIkpN7wSBeOSxHjX5bZbTkK02uWKgu75NPuqW+6p559//qC4+qbf0Db17dvXWKswm9eIbS36avtRi/GRteyhhx5qbxEI+7LaTetmXO6KFbPWFfLlonuVVVYJ69TOMcccYyZOnBjmnXzyyQXuuCU0y7Lb1qPY0GqH3ovYPF180003BTF3w4oidvw+JcXx/vLLL41iQc+bNy+4j4413xdffHGz1FJLBfPft1Z2bylLd3feKS7wOeec4xZpty9LZ1kdu/1SoV/96ldGY1xNC+R2NycDAg0kELVAMa45+lzpe96N72sNY/z3p24dPP+6NJpj3xf+ba9Y3GpJsIUABFqdAIJvRmeA/+CD4JvRgaJZEIAABCAAAQhAIGME/BchvADJ2AC1eHNkQag4r/q9oyRLUAkwcnH67rvvBiKixJavv/46EFjWWWcds9pqq7WjphiyEvVs+vWvf22OO+44e5jJrS/4yg2txKhaJb0c1wIQmxTjdvnllw84v//++4Hb5C+++MJ07tw5EOQk4rrikhv/V+6Sdb1NfhxVm2+399xzj5EFrp8U63Xvvfc2fvxSv5wEP/FRfF7904v9qVOnhsWstbHN0P0UB9kmzSv1Xe22orA9524l5qlNskwVm2qmWvXVtrEW4xO1YEixZWWRLxfkPXv2DOaLbcM333xjPvroI/Pcc8+ZJ5980owbN65gIYDGccqUKWahhRaylwTbCy64wCimcVTS2P31r381p5xyitG42qQY3O4iAbll1v2KJbn8Vvxqm2T9LTfSElj1d0Z/eyTsysrYF13tNe5W7VO/FJ+3W7du7ilz/vnnB/k2U+7J9fetWNLfMy2SePrppwuKphGMCy7gAAI5I+C/+4xrvt6J6nl2yJAhYRH7nhTBN0TS9DtR31G20/zesSTYQgACrU4AwTfDM8B/WWdXr2W4yTQNAhCAAAQgAAEIQKCBBKJehGDd0MAB4dYhAVnrPf744+bGG28006dPD/PT7ES5YP3+++/NGmusEQo0WbHoTOqPL/iqbLU/nx9++KGRC1tZVer3YynJFc0lhK600krh5b5rWgnGEs6iUpw7Zc2BoUOHtovJK3e7//rXvwJhV6KihN6OHTsWVC23wHvttVeY57ZVmf55W1DinNoj8VnxfD/77LNA4JUYqwUGEtpskuCtuKqaV5WmWvZVbavF+Khe31W68ipJct/uziNbl2JXyx13VFIMYLk7v/jii2NdPOu6YELBlAAAQABJREFUtC7KfRE26p7l5J122mmBZa577fXXX29OOumkMEvzzhWtwxMROxKfJXL7cX1PP/10I1fRJAg0K4GoZ9eovur70hd39T3nW/6611b7O9atm/36E0iaK4x1/ceDO0IAAtkkgOCbzXEJWuU/yNjVaxluMk2DAAQgAAEIQAACEGggAf9FCKvdGzgY3DogIJercsWa5P63GCpZArquiW15Wb+54nHWX/bVUvCdPXu2GTFiRFHLWcsuautaE/pWV1GiU5wg19bWFrjede/x4osvGtXvz4MoMd+9zu7fddddQUxTe+wL/Kp3vfXWs6cr2p533nntYhSXUmGt+6q2VHt8bP9k6ay4zbLKrTRpfsi9c1SSsHnNNde0O3XEEUeYkSNHBvmyAlcc4agkd8dxgrFf/sQTT0xlCexfl3SshQSKvysLXjf5lualWvFrIcvw4cPNzTffHFYbt4AiLMAOBJqAgP/8GtWlOCtfxXGX6BuVsv5cENVm8uIJ+IZRtiS/dywJthCAAASMQfDN8Czwf8SpqXyJZXjAaBoEIAABCEAAAhBoMAH/RQgvuho8INw+cAUrK79yksSSLbbYwhxy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8ksze/ZsM3PmTPP555+bf/7zn2bllVc2559/PmJ4K02IKvb1448/bjd39tlnH3P66adX8S6tVRWunVtrvKvVWwTfapGkHghAAAIQgAAEIAABCEAAAhCAAAQgAAEI5JBAktiLRVH7AX3//ffNk08+ad58803z3XffmY4dO5qFFlrIyEJaAocVGGXh1rt37/YVRORMnDjRHHPMMQVnBg4caDQ2pPIJ+IKvanrggQdMjx49yq80R1fOmzfP3Hbbbea6664L52VS82VpvvnmmycV4RwE2hGIEnx//OMfB38n2xUmIxWBOCtfXDunwteyhRB8W3bo6TgEIAABCEAAAhCAAAQgAAEIQAACEIAABIyJsyQSG6x7/ztDPvjgg0CAlTVumrTDDjuYSy65JE1Rc+utt5ojjzyyoOxmm20WCHUFmRyURCBK8JXb2S233LKkevJWWNa7EyZMMOPHjy+p6euvv76ZPHlySddQGAJRgq+oPPPMM6Zz584AKpNA3HczC7HKBNoClyH4tsAg00UIQAACEIAABCAAAQhAAAIQgAAEIAABCEQRwLo3ikr7vNtvvz2wwJUL3FLSK6+8YhZccMGil8gN9IEHHlhQDvGtAEdZB1GC74UXXmgGDBhQVn1ZvkhxVGVVfvXVV6ey5o3riywLu3btGneafAi0IxAn+E6fPt1069atXXky0hGIs/LV1f+fvfMAl6LI/nYZAMGIKChBBUXFtCKCmHPGgIkV1wxiwogBxJwwLqKIimEXDGACxSwqKwqCrjljwISLOa3wR8XPX609X01NdU+4cy8z0+95Hpju6urqqreq5z7P/Oqcw2aswhimrRaCb9pmnPFCAAIQgAAEIAABCEAAAhCAAAQgAAEIQOBPAngQJS+Fb7/91gwePNg88MADyRVjrl599dVm9913j7n6/4sljOy///7/v+CPI+UAltCMlU4gJPhedNFF5oADDii90Qq7U2HFH3nkEXPxxRfbMON16V6nTp3smltkkUXq0gz3poxAnOCrjSyrr756ymiUd7hxm7Lw8i0v51ppDcG3VmaScUAAAhCAAAQgAAEIQAACEIAABCAAAQhAoAgCcT8kqwl+TDbm559/tuGuX3nllSKoZlddaaWVzFNPPWUWXXTR7Ave2csvv2z22GOPrNIOHTrYe7MKOSmKQEjwPe2008zRRx9dVDuVWvnZZ581ErBff/31snRRYaC7d+9elrZoJD0E4gTfYvKYp4dW8SNVfviQ4eUbopLuMgTfdM8/o4cABCAAAQhAAAIQgAAEIAABCEAAAhBIKYE4wRex1xiFx+3Xr5+ZOHFi7OpYfPHFzQYbbGDkBZwkuBXiUTpjxgyz3XbbZT1LYXUV0hMrnUBI8NW8Dho0qPRGK+DOt956y1x44YVm8uTJBfVmk002Mdq4EBeSvFu3bqZ///5miy22KKg9KkHAJRAn+Cq8+LbbbutW5bgEAnGhnflbXQLMGr8FwbfGJ5jhQQACEIAABCAAAQhAAAIQgAAEIAABCEAgRCDOa4gfkY0544wzzK233hrCZjp27GjDPEscW3jhhY1C6krUHTlyZLB+ixYtrDAngTjOZs2aZTbeeOOsy6r/5ptvZpVxUhyBkOC71VZbmX/+85+Zhn766SebD/Prr7+2c7nYYouZJk2aGH1qDpSDtFJCHP/+++/mmmuuMZdffnmm/6EDrbn99tvPbL/99uYvf/mL9TD/7bffzCeffGLeeecd8+GHH5rmzZsbfQe0a9eOPKshiJQVTCBO8NX36BFHHJFp56uvvrJr8Pvvv7ffndF71rRpU7P00kubVq1aZepykE0gLv0CXr7ZnNJ+huCb9hXA+CEAAQhAAAIQgAAEIAABCEAAAhCAAARSRwDv3vgpv+6662w+1FCNHXfc0YhdSLy94oorzLBhw0K3mcsuu8wKcMGLfxRKAFlvvfWyLiP4ZuEo6SQk+Kohib6y1157zUjoTTIJ/Lfffrtp2bJlUrV6v/Z///d/RuGox40bF/ssCb2nnnqq6dmzpxWtYytyAQJlJBAn+Oo7TBtj9I698cYbsR7mUVeU71zfr/lC4Ef10/SJl2+aZrv0sSL4ls6OOyEAAQhAAAIQgAAEIAABCEAAAhCAAAQgUJUE4rx70+4t9Omnn5pNN900OKfKsXvllVfGihHy9FXo3M8//zzn/r59+1qv4JwLfxb88ssvZrXVVsu6jOCbhaOgE4Xilrj05Zdfms8++8yceOKJeUWmQhq+6qqrzJ577llI1Xqpo7Dh8pScPn16bPvKS3zssccGNyPE3sQFCJRIYO7cufY9k9euwoWfffbZJbaUfduUKVPwOM9GkjnDyzeDgoMYAgi+MWAohgAEIAABCEAAAhCAAAQgAAEIQAACEIBALRLAuzd+ViUQ3nvvvTkVJOSOGjXKNGrUKOeaW3D11VcHw+36YYTde6JjX4RH8I3IJH8qzLE8qxWmOZ+3bnJL8VcXpOA7c+ZMc+CBB5qPP/442EGtkxtvvNFuNghWoBACZSKgHNCnnHKKmTRpUlk2UoS6heAbovK/Mrx849lw5X8EEHxZCRCAAAQgAAEIQAACEIAABCAAAQhAAAIQSBGBOME37d69r7/+utl1111zVsJKK61kHnjgAZtjMueiV/DSSy8FPUFXXHFFox/rk2yttdbKElEUnvfFF19MuqUqr7311luWp8LAbrvttmabbbap0zgGDx5sRo8eXac2km5WLtxzzjlngXjOvvDCC+aggw7KWhduX9dZZx2bO7p169ZuMccVTqDc70BDDPfnn382++67r9H3ZH2ZvIQPOeQQm9+3vp5RbLtz5swxEyZMsF7Myy67rDn88MPNMsssU2wzZauPl2/ZUNZkQwi+NTmtDAoCEIAABCAAAQhAAAIQgAAEIAABCEAAArkE8BDKZRKV6If8iRMnRqeZT5Upj2shppDCq666arBqPkE9DYLv22+/bZQH2TWJ5BJSXJMgNnbsWCuSy7NVnoV/+ctfTOfOnY1ETrWx1FJLmR9//NGeu/eWeixP2Y033thssMEGZu211zYS+iXUN23atNQm63TftGnTEvM+77zzzjbf6YLqX2hwWv/33XefUd9nzZplfvjhB9OuXTvLc/3117d8F1poodCtFV/2zDPPmMcff9x6WsuTXBsytE703mrjQpMmTQoaQ7nfgYIeWoZK8uo9+OCDy9CSse9V9+7d7bu2xhpr2BDOK6ywQmy4/LI8tMRGTjjhhKy82QqbLi9n1xSS/4477jCTJ082//73v22kAa2Pbt26mXXXXddorF26dHFvKfk47m+4vi/1HCzdBBB80z3/jB4CEIAABCAAAQhAAAIQgAAEIAABCEAgRQTivHvT/mPx7Nmz7Y/z/lKQd+dll13mFyeeK5fqgw8+mFMnn+ArodENSVyLHr4SzPr06ZPF5uKLLza9e/e2ZRJOrr32WpsrOauSd7LddtuZm266ycyYMcPouBSTcCyBV58SZdq3b18xnoVaKxJ0JXSHrF+/fua0004ziyyySOhyg5cpf/UjjzxiNJdxoafVqQ033NDmspZwXx/26quvmvvvv9+ui1atWpmBAwea5s2b1+lRavPSSy+1Yl5cQ9oYMGjQINOjR4+8a6jc70Bcn8pdrpD2Z555ZknNKiS+xMhOnTrZjRuam3KYwrk///zzdpPBe++9ZzcZaP1p84be5zZt2tgNB5tvvrkNed64ceOiH7vTTjsZbUCJzA+1/8Ybb5iTTz45q05U1/3UutSmlXJYyMtX32VjxowpR/O0UcUEEHyrePLoOgQgAAEIQAACEIAABCAAAQhAAAIQgAAEiiHg54mN7s0nRkb1avVTOVDPP//8nOE99dRTpkOHDjnlSQUPPfSQOeqoo7KqSFQMicBuJV/w9YUFt25DHM+dOzfjYSsR5fPPP7cCo8KZLrfccmb55Zc3LVu2tKJps2bNCupSSOwaMGCA6d+/vxU3999/fxs6tZDGXnvtNSOBWNyKMYlzjz76aEEhuotpt1x15RW7xx57mA8++CDY5BlnnGGOOOKI4DUVysv25ptvtt618+bNs16TEpq23377vGJkbKMJF959912j3NfFhPpVvmXltS7EJLbJK7Zt27ZmvfXWC3rSipU2WrjCnNrWu3v33Xdbb9xCnuXWkff46aefbsOPu+VJx8cdd5wV/5LqlPsdkKd7nEkQlcep+Ogd1r/ffvvNhiSWV73eYf2TAC8P2yRTWGN5txZjWseXX365KUVozfccRV648MILY98T/359n/bs2dN6zRcjvPqCr9p9//337Xs1fvx4c/zxx/uPCp7rb4LWUzmMjVvloFibbSD41ua8MioIQAACEIAABCAAAQhAAAIQgAAEIAABCGQRiAsFqZCVEmzSbPISlbeoaxIrhg0b5hYVdCyRbcSIEebhhx+2ApRCAw8fPtyKVUkN+IKv6hYixEuY+vTTT21Y5HJ4zklEveuuu6xQ43ocx/VdnsgS8OQlm89CYpfWnwTfvn37mieffDJfE5nrEvckNMur9LrrrsuURwcSeEIesvI2VPjVSrWzzjrL8gz176STTsorMMXxUHjZY445xgp8EgI1z/IQXnjhhc1nn31mvctVZ7XVVgs9Olgmr8rdd989yDl4w5+FmhsJiHHhz6N7tUlCQm5kEuq0Nt3wyXpv9a6G5lr3KUf0LbfcEjVR0KfaUu5k5VAu1q6++mrLJO6++ngHQs96+umn7Tv8yiuvhC7nlCmSgSIaxJly+B566KHBXORx75pCHxcrEsc9Pyr/4osvzLnnnluUEB/dG31qY8mpp56aE0o+uu5+hgTfd955x7z88sumV69ebtXEY33HaXNLuSy0eQsv33LRrd52EHyrd+7oOQQgAAEIQAACEIAABCAAAQhAAAIQgAAECiYQ5xVUiKhY8EOqsKLEHeXh9O322283m266qV9c1PmcOXPMYostZgrJW6qwo/LAcy3yJHPLomOFEpV3mStUK9ewxOZCcw5HbUWfyrt62GGH5XhKRtfjPvfZZx8rLuUbp7zylCvZNYUnXnrppW3YXLc86dj3ltOYJTorhKs8RzfbbDMrQEuwv+qqq7KaUv7fG264IausUk7kLStP3JApFHYhIXVDmxdC7YXKJNyNHj26oHyj8hrVvBeyKSD0LK0DidtJFgqPLg965c6Vff/99zaMsv/e+G3mE2Hd+vo+OOSQQ8z06dPd4oKP9e6FcoFHDdTXOxC1L898iZnKpVyMyRtaYYeXXHLJ2NvERh7mEpPlFbz11lvbUM3aJLD33nvnCOSKmiDhvFw2btw4+3z1o66mtT5kyJBEcV7PCAm+//rXv8wuu+wSu8nA75uiCtx22215Nzj49yWdh8I6q37a/54nMUvDNQTfNMwyY4QABCAAAQhAAAIQgAAEIAABCEAAAhBIPYGQRxDevcYoR+duu+2Wsz5ULiGyoWzXXXfNCYsbebH6fZDwobkLmYQM5VOVZ3ExJgH5wAMPLFnA22GHHYyENQnccSYRbd999826LKF78uTJWWU60TgkXEnAXWWVVay4J0F6iSWWsHk5c24IFITENeVZlcd1JZo8KENezhLXFJp40UUXzdvt0Hue9yavgsTC9ddf3yv9/6czZ840e+21V+xakWenOCvktzzd5T2qkOCuSWBUyPQk0xrXWndt5MiRRmtNXsraLKDw3PlMuWP1TuQzbdDQhocpU6YEq8qjU96h8mZXHa0jRU7wTZ7BCpUcsvp8B7799lubI7sUz2T1Vd8Z8n5X+Oxi7YILLjCaG9cuuugic8ABB7hFJR1rU4E2O+QLi19K4/lEac23vx60/h577LGcxynvtoRY5SvWu6o1/91335nVV189yys958YSCuIidowdO9Y+v4QmuaUGCCD41sAkMgQIQAACEIAABCAAAQhAAAIQgAAEIAABCOQjEBKCEHyNFZR88bQQMSof72KvSwj1vQoVNrR58+aZppSfVSLKTTfdlCkLHShn8L333luw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X1xv5xKZn3zySdu+G9Y4eqA734cccog599xzo0s18emO79lnnzVt27Y111xzjbnsssvs+FZaaSUzefLkmhhrNAjNt+bdNXn3yssXg4BPwBV8Q2Hf/fqh89mzZ5tff/3VtGnTJnS54svS+D2hSUHwrfilWa8dRPCtV7w0DgEIQAACEIAABCAAAQhAAAIQgAAEIACBBUvAz+eHl29h8zFhwgRz2mmn2XyxSXdIUJWw2lC27777Gnm2yjbccENzzz33ZB49b94807Fjx8x5LXp3uUKO5mi99dYzZ5xxhrn11lvtuLfaaivzz3/+M8OgFg5GjBhhhgwZkjUUcvhm4eDEIeAKviqeOXOmWWihhZwa8YfK+9unTx+jsNCyat1YkMbvCc2XO26ds8FLFNJjCL7pmWtGCgEIQAACEIAABCAAAQhAAAIQgAAEIJBCAgi+xU+66zGa726FVZanadOmTfNVLcv1XXfd1bz++uu2LT9H7/fff28F0OhBZ599tjnssMOi05r4VAjtf/3rX3Yst9xyi9lmm23MKaecYu68805bduCBB5oLLrigJsYaDeKcc84xGqtrF110kTnggAPcIo4hYAn4gu+bb75p5OlbiD388MPmyCOPzKqqDRTaSFFNlsbvCd+7V/Pl53ivpjmkr8UTQPAtnhl3QAACEIAABCAAAQhAAAIQgAAEIAABCECgagj4eXzVcbx+4qfv3nvvzcl5qDDBf/vb38wqq6xi5G350ksvZTXQkN6W2223nZkxY4Z9/n777ZcJZawCP9erBIC99torq6/VfiL2Ejr/+9//mqlTp5rWrVubkSNHZkTeU0891SjPcS2Zm7c5GpfW4S677BKd8gmBDAFf8FWIc32HRaYc5HEev7fffrvR95lrEosVSaBTp05ucUUfp/F7whd8ieZR0Uu0XjqH4FsvWGkUAhCAAAQgAAEIQAACEIAABCAAAQhAAAKVQQDBt/B5CLHaY489zCWXXJLx4P35559tPlXVjUyCyKuvvmoWXXTRqKjePrfeemvzwQcf2Pb79u1rBg8enHmWcg4rzHNkN910k5FAXGs2Z84cm190ySWXtEN7//33raevTiRYbbrppjU1ZG028PMSa2NCly5damqcDKY8BHzBV965ynX97rvvmjfeeCMTpl7fW0sttZT9PuvXr599+HfffWd22mkn8/nnn2d1pkeP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yzyNG5bivHsJ5+yumvQdI/imb84ZMQQgAAEIQAACEIAABCAAAQhAAAIQgECKCYTCOgtHGn80j5aBLzRI2LvooousZ2JUp5RPeavJa02mkKoSgBdeeOGcpvxcnlEFP5SqGyJWddRvVzRyw/XmE4WiZ+T7VGhheSdGJu9G9dc35RmV4BflLHWv+8K0e62+jl32dWHhen9vsskm5o477iioy/LglSdvZBED5aV1xfK48NAS++PC8CqvrRvKWGKr8sYWY6WIgEntv/zyy1miogTQSBQN3ad3TGGZ5V1biGmMm222WXB9hTxQ/Tb9DQD+df+8T58+Nu/2IossknXJz/G71157ZQn7WZXznLjvbiiUfNIakKi70EILBZ/g58KN87KPvi+0CUWbUVzTPfr+kXXo0ME89dRT7mW7QSV618vxXqjxOFFf4akVltodr/teShRXRIQ0mbt23HHj3evSSN8xgm/65pwRQwACEIAABCAAAQhAAAIQgAAEIAABCKSYQFxY57R7+SrXqTwtXRs8eLANi+uWFXrs55CNy6Opct97LnqGQuFKFIvMF3wfeughs/baa0eXTSTgRAXl+PHfDyMtj8xVVlkleoT9VNjZ448/3oZMzrrw50ldOIbaK6Rs3333tfmDo7rywixUXIzu0acbdrdQYUs5eiVARWF4JX4qV67Mz1M6fvx407lzZ3st+k+i4t57753JcxuVu58SWKNcw++//37W5oQ777zThq6WOK01EvVD3qjbbrut6dWrV0ks3Of7x2PGjDHyso1MYqXy76oPyoscib/rrLOOFbIPOOAAm2c6qp/0KbH3lFNOyXic+nXluXvssccaX5x167nzKG/offbZx+YAvvfeezPe1ponheLec889s3i67cjDt2PHjpmiunj4brDBBpm5UXhpN/+yxiyv3GjDSOaBfx688sorZplllvGL7fnPP/+cNb/6XvBzOfthn3W+2GKLZdobOXKkkSd5ZC+88IJZfvnlo9Oyvxdq2H+myrQxQO+uP1YJ5FEu30LCgqutWjG8e2tlJss/DgTf8jOlRQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIVDQBvHxzp0eerMoBKk9M1+TdqvC5u+yyS1FhW7/99tusHLfyOFXuychL7ZtvvjFXXHFFVrhjiUcS5yJxTP1whRY/ZLLvle2GdNa97733nmnUqJEO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w4dnzv2D2bNnm2uuucaMGjUqc6lFixbmiSeeMM2bN7dl9dGmH9J57Nixpnv37pk+cACBaiWA2FutM5eOfiP4pmOeGSUEIAABCEAAAhCAAAQgAAEIQAACEIAABCqGAKJvxUwFHWlgAqeffrq54447Mk997733TKNGjTLn8uCV121kb7zxhlliiSXsqbx+11prreiS/dxnn32MQjQr/HPTpk3NN998Y0NGS8i96aabsurq5M477zQbbbRRprw+2pw0aZLtU/QQha1W+GoMAtVK4LnnnjPKmT116tScIXz00Uc5ZRRAYEEQQPBdENR5JgQgAAEIQAACEIAABCAAAQhAAAIQgAAEUk5AP6D36tUrhwKhMXOQUFBDBPzwymeddZbp3bu3eeedd4y8ed0Qz/vtt5+57LLLskZ/xRVXmGHDhmWVFXKy+OKLm5tvvjnoaVvuNt9++22z4447Zrp11FFHGQndGASqkUDc3yqNBe/1apzR2u0zgm/tzi0jgwAEIAABCEAAAhCAAAQgAAEIQAACEIBARROI85pC9K3oaaNzdSBw3333meOOO66gFp599lnTtm3brLq//vqrkYAahYXOuhhz0qdPH3PooYfmtBVVL3ebam+99dbL5CFeccUVjcayyCKLRI/kEwJVQSAuGoU6j9hbFVOYqk4i+KZquhksBCAAAQhAAAIQgAAEIAABCEAAAhCAAAQqj0AoL6J6yQ/qlTdX9KhuBH755RcbUvnrr79ObEjeuNtuu22wzvz5820eXoVnlpCqsMy+derUyXoO77XXXpmQ0H4d97zcbV555ZXmqquuyjxi+vTpplWrVplzDiBQ6QQQeyt9huifTwDB1yfCOQQgAAEIQAACEIAABCAAAQhAAAIQgAAEINDgBOJ+XD/hhBPMiSee2OD94YEQqC8C48aNM1rXIdtjjz3stQ4dOoQu55RJqP3ss8/MnDlzzG+//WYaN25shdUo72/ODQUUlKPNefPmmREjRphPP/3UaCzySsYgUC0E4v4eKfqE3t3u3btXy1DoZ4oIIPimaLIZKgQgAAEIQAACEIAABCAAAQhAAAIQgAAEKplA3I/siL6VPGv0rRQCd9xxh83X+/HHH5u1117bSOjdeeedTYsWLUppjnsgAIEyEYiLOEGqgTIBppl6I4DgW29oaRgCEIAABCAAAQhAAAIQgAAEIAABCEAA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FLnTaft66BW7roupkN8JEDiSgML3SGk5VwIECBAgQIAAAQIECBAgQIAAAQIECIQKvLoAnmMbS79+vPcpAFtkfrvXInd6tp1nF7v1uGynSn4nQODoAgrfoyfo/AkQIECAAAECBAgQIECAAAECBAgQIBAo8IkCeI5xLAzHx3t/70soEY9S4rZ5bzuLsdStxxIy6RltCRAg8JOAwvcnHY8RIECAAAECBAgQIECAAAECBAgQIECAwC4EugC+3W5v+z7XtYN3EdnHqUJy7jZ93txzfrNvWnDOFbh1nDLs27u+G7ffb+m2jcZSdzrv0mN7HQECBI4uoPA9eoLOnwABAgQIECBAgAABAgQIECBAgAABAicUOGIBfMKYfj1yF7r1AqXur9k8kQABAncBha8LgQABAgQIECBAgAABAgQIECBAgAABAgQiBGpFa69YPdJK4Aj8mSGmJW49Zdxnhe4Mml0ECBBYIKDwXYDmJQQIECBAgAABAgQIECBAgAABAgQIECBwHAFF8LqsxpJ2PFJ/RPX4uBJ3FHKfAAEC7xFQ+L7H2bsQIECAAAECBAgQIECAAAECBAgQIECAwM4ExiK4Tu2I323bpGPpWvu6jO3Hx+30ueNjCttRw30CBAgcQ0Dhe4ycnCUBAgQIECBAgAABAgQIECBAgAABAgQIfFCgyuG69UdGj6cyFsXj/mfvz5W0j8pZxeyzup5PgACBXAGFb262JiNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFxA4RsesPEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgVUPjmZmsyAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCBRS+4QEbjwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXAGFb262JiNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFxA4RsesPEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgVUPjmZmsyAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCBRS+4QEbjwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXAGFb262JiNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFxA4RsesPEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgVUPjmZmsyAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCBRS+4QEbjwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXAGFb262JiNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFxA4RsesPEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgVUPjmZmsyAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCBRS+4QEbjwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXAGFb262JiNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFxA4RsesPEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgVUPjmZmsyAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCBRS+4QEbjwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXAGFb262JiNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFxA4RsesPEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgVUPjmZmsyAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCBRS+4QEbjwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXAGFb262JiNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFxA4RsesPEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgVUPjmZmsyAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCBRS+4QEbjwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXAGFb262JiNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFxA4RsesPEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgVUPjmZmsyAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCBRS+4QEbjwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXAGFb262JiNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFxA4RsesPEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgVUPjmZmsyAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCBRS+4QEbjwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXAGFb262JiNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFxA4RsesPEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgVUPjmZmsyAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCBRS+4QEbjwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXAGFb262JiNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFxA4RsesPEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgVUPjmZmsyAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCBRS+4QEbjwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXAGFb262JiNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFxA4RsesPEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgVUPjmZmsyAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCBRS+4QEbjwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXAGFb262JiNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFxA4RsesPEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgVUPjmZmsyAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCBRS+4QEbjwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXAGFb262JiNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFxA4RsesPEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgVUPjmZmsyAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCBRS+4QEbjwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXIG/6wp52VwFmL8AAAAASUVORK5CYII=" } }, "cell_type": "markdown", @@ -20,7 +20,7 @@ "\n", "The resulting graph will look something like the following diagram:\n", "\n", - "![multi_agent diagram](attachment:7d0ca3af-e391-4d23-981a-dd640e08e4c1.png)\n", + "![multi_agent diagram](attachment:8088306a-da20-4f95-bb07-c3fbd546762c.png)\n", "\n", "Before we get started, a quick note: this and other multi-agent notebooks are designed to show _how_ you can implement certain design patterns in LangGraph. If the pattern suits your needs, we recommend combining it with some of the other fundamental patterns described elsewhere in the docs for best performance.\n", "\n", @@ -162,20 +162,30 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 7, "id": "71b790ca-9cef-4b22-b469-4b1d5d8424d6", "metadata": {}, "outputs": [], "source": [ - "from langchain_core.messages import HumanMessage\n", - "from langchain_anthropic import ChatAnthropic\n", + "from typing import Literal\n", "\n", + "from langchain_core.messages import BaseMessage, HumanMessage\n", + "from langchain_anthropic import ChatAnthropic\n", "from langgraph.prebuilt import create_react_agent\n", - "from langgraph.graph import MessagesState\n", + "from langgraph.graph import MessagesState, END\n", + "from langgraph.types import Command\n", "\n", "\n", "llm = ChatAnthropic(model=\"claude-3-5-sonnet-latest\")\n", "\n", + "\n", + "def get_next_node(last_message: BaseMessage, goto: str):\n", + " if \"FINAL ANSWER\" in last_message.content:\n", + " # Any agent decided the work is done\n", + " return END\n", + " return goto\n", + "\n", + "\n", "# Research agent and node\n", "research_agent = create_react_agent(\n", " llm,\n", @@ -186,17 +196,23 @@ ")\n", "\n", "\n", - "def research_node(state: MessagesState) -> MessagesState:\n", + "def research_node(\n", + " state: MessagesState,\n", + ") -> Command[Literal[\"chart_generator\", END]]:\n", " result = research_agent.invoke(state)\n", + " goto = get_next_node(result[\"messages\"][-1], \"chart_generator\")\n", " # wrap in a human message, as not all providers allow\n", " # AI message at the last position of the input messages list\n", " result[\"messages\"][-1] = HumanMessage(\n", " content=result[\"messages\"][-1].content, name=\"researcher\"\n", " )\n", - " return {\n", - " # share internal message history of research agent with other agents\n", - " \"messages\": result[\"messages\"],\n", - " }\n", + " return Command(\n", + " update={\n", + " # share internal message history of research agent with other agents\n", + " \"messages\": result[\"messages\"],\n", + " },\n", + " goto=goto,\n", + " )\n", "\n", "\n", "# Chart generator agent and node\n", @@ -210,44 +226,21 @@ ")\n", "\n", "\n", - "def chart_node(state: MessagesState) -> MessagesState:\n", + "def chart_node(state: MessagesState) -> Command[Literal[\"researcher\", END]]:\n", " result = chart_agent.invoke(state)\n", + " goto = get_next_node(result[\"messages\"][-1], \"researcher\")\n", " # wrap in a human message, as not all providers allow\n", " # AI message at the last position of the input messages list\n", " result[\"messages\"][-1] = HumanMessage(\n", " content=result[\"messages\"][-1].content, name=\"chart_generator\"\n", " )\n", - " return {\n", - " # share internal message history of chart agent with other agents\n", - " \"messages\": result[\"messages\"],\n", - " }" - ] - }, - { - "cell_type": "markdown", - "id": "bcb30498-dbc4-4b20-980f-da08ebc9da56", - "metadata": {}, - "source": [ - "### Define Edge Logic\n", - "\n", - "We can define some of the edge logic that is needed to decide what to do based on results of the agents" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "c30f800f-99dc-4207-ba09-0164e226dade", - "metadata": {}, - "outputs": [], - "source": [ - "def router(state: MessagesState):\n", - " # This is the router\n", - " messages = state[\"messages\"]\n", - " last_message = messages[-1]\n", - " if \"FINAL ANSWER\" in last_message.content:\n", - " # Any agent decided the work is done\n", - " return END\n", - " return \"continue\"" + " return Command(\n", + " update={\n", + " # share internal message history of chart agent with other agents\n", + " \"messages\": result[\"messages\"],\n", + " },\n", + " goto=goto,\n", + " )" ] }, { @@ -262,41 +255,30 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "id": "2c4a5ade-5912-494b-bf62-8a99278f9f12", "metadata": {}, "outputs": [], "source": [ - "from langgraph.graph import StateGraph, START, END\n", + "from langgraph.graph import StateGraph, START\n", "\n", "workflow = StateGraph(MessagesState)\n", "workflow.add_node(\"researcher\", research_node)\n", "workflow.add_node(\"chart_generator\", chart_node)\n", "\n", - "workflow.add_conditional_edges(\n", - " \"researcher\",\n", - " router,\n", - " {\"continue\": \"chart_generator\", END: END},\n", - ")\n", - "workflow.add_conditional_edges(\n", - " \"chart_generator\",\n", - " router,\n", - " {\"continue\": \"researcher\", END: END},\n", - ")\n", - "\n", "workflow.add_edge(START, \"researcher\")\n", "graph = workflow.compile()" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "id": "97f8e0eb", "metadata": {}, "outputs": [ { "data": { - "image/png": "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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMUAAAFNCAIAAAA/zjymAAAAAXNSR0IArs4c6QAAIABJREFUeJztnXdAU1ffx0/IhiQkJBA2KAgOQGSoII66qohaN7VurdqqrU+rrY/S8Tyto61V626ruHAPRHGPqgyR4QBFEJxsSAjZO3n/uL4pTw2IcEfG/fxFbu4955vkyznnnvs7v0MwGo0ABwcmHLAWgGNT4H7CgRPcTzhwgvsJB05wP+HACe4nHDghYVVxXYVaIdbJJTqd2qhWGbCS8U5QaQ5kmoMji+jEIrn5ULGWY4mg7aenhfJnRbJnRXL/7o46jdGRRXThUx2IKKtoJwQHUF+hkkv0ZArh5WNF5xCnzmGMzqFOWOuyIAiozWc+uSvNPiv07kL3DnLsHOJEoVl3V6tRGp49lFc+UVQ9VcaO5nXpxcBakUWAhp/kEv2VlFo6k9hvNI/BxqyHRQhpoy77rEClMAyfzqczrKSlRQzE/fSqRHH1cN24T705fDKiFWFLY602dVvl8OnuPkF0rLVgCbJ+qn+lzjkvHLPQE7kqLIrTO6r6jea5etvvUB1BP5XkS0vzpWPtxkwQp3dUd+/DDIpgYi0EG5AaFAuq1Pf/EtmbmQAAH3zimX9FJKzRYC0EGxDxk1EPMk4LEpf7IlG45TP1a9+bJxvsMw4IET9lpDXY+axM5xCnrDMCrFVgAPx+kkv05Q9kPQewYS/ZiggfxC7JkypleqyFoA38fnpws2ngeFfYizWLTCYrKSnB6vLWGTjB9cHNJoQKt1jg91NRltgn2BH2Ys2SmJiYlpaG1eWt4xvsWJQlRqhwiwVmP1WVK129qag9S9Fo2nkbBc2StPvytkB1dHDxoFQ/UyFXhQUCv58QmnrZu3dvfHx8XFzc3Llzc3NzAQAJCQmNjY3Hjx+PiopKSEiATjtz5sy0adP69u07ePDgVatWiUQi6PhPP/00fPjwW7dujRs3LioqKi8vz+zl8BIcxap8okCiZIsF5qdp9ZXqHjHwzw7n5uZu3bp1xIgRsbGx2dnZCoUCAPDzzz8vXrw4MjLyo48+olAo0JlFRUX+/v7x8fGNjY1HjhyRy+WbNm2C3pLJZNu3b1+xYoVSqYyOjjZ7Obw4sYgvHsmRKNligdlPcrHOiQX/E9/q6moAwOTJk8PCwuLj46GD3bt3J5FIPB4vPDzcdObKlSsJBAL0N4lESk5OVqvVVCoV6t2SkpJCQkJauRxenJgkhUSHUOGWCcz9nUKCiJ/i4uJYLNY333yTmZnZ+plarXb//v2JiYmDBg06ffq0wWAwdXk0Gs1kJnRwZBEVUvuaMoDZT2SqAxGBgBQej5ecnOzn57d06dK5c+fW19ebPc1oNC5dujQ5OXnMmDFbt26FWjKD4XXwp6MjSnedJhyIBDLFusO83hWYPy2JTJA1IfIf6e/vv3nz5h07dpSXl3///fem482fZ9+9ezc3N3fFihVTp04NCQkJDAx8a7GIhlfIxToShYBc+RYIzH5yZJHkyIwYoHv76Ojo/v37myYh6XS6QPD3Y42mpiYAQNeuXZu/NLVPb/KPy2FHIdU7Mu0rwg7mzonvQ1Mr4V9c8OjRo6+//nry5MmOjo7Z2dndu3eHjvfq1evixYt79+5lsVhhYWGhoaEUCmXr1q3jxo0rKyvbs2cPAKC8vNzb29tssf+4vC3t2TuhVhpcvWnwlmnhEJv3HR1HpzE8zpUERcI8BSUWi588eXL58uXc3NyIiIiVK1cyGAwAQFhYWGlp6fnz50tKSnr06BESEtK5c+ezZ8+ePXtWp9P9+OOP9fX19+/fT0hIyMrKev78+fTp05sX+4/LO3XqBK/s7HRBQBiD7WrLgan/AP54uq3/Kl+8EeZ/dGvEaADbl5Uv2mBfXwX8N2Oh/ZwrSpU+wS2GUW/fvv3YsWNvHu/Wrdvjx4/NXrJnzx7YG49/IJPJWpol53A4pkmH5uzYsaNbt24tFfiqVBHaz+6CLOBvnwRV6quH6loJphOLxXK5mVljAqFFMW5ubiQSsgtjDAZDbW2t2be0Wi2ZbKbP4vF4rUysH/rp1fsz3LkeiMy8Wyzw/0g8LyqHTym7K+sSYX5JmrOzs7OzM+z1dhAHBwdPT9iik0vzpa5eVHszE1LxmbEJvLJ7UiRKthbK78tiE3hYq8AARPzEdCEFR7PO76lBonDL59yumu59WU5s+5p5gkDqaUBAmBPPg3rzRANC5Vssfx2rd/Oldgqx0/B5ZNdzluRJ6ytUA9AK/8WcmycaPDrRYJ9+syKQfVrZNZrJ5JDTdlQBW188ZDSA09urnF3J9mwmlPJhVJQq/jrW0L0vK2oYB+m6MCHvcmNpvnTQJDfvLnadvAC9fD1GA8i5ICzMEEcNdfEJpttGMq76CnVFqSL/SmPPgew+I7gE+4pMMQ96+Z8AABqVoTBD/LRQppDogiJZBAJwZBGduWS93jq6QyKRIBZo5RIdAITSAgnDmdQ5jNGzP5tMta+glFZA1U8m5GJ99VOltEkrF+sBADIxzCEulZWVRqPRx8cH3mIZbBIBAEcWkckhewbQnVj2OCPQOtj4CWn++OMPAMD8+fOxFmJ34H0+DpzgfsKBE1vLZgnh5ORkk/245WObfjIbD4ODArbZ35FIJAcH2/xoFo5ttk86nX2tyrUcbNNPVCoVHz9hgm36Sa1WYy3BTrFNPzEYDLx9wgTb9JNMJsNagp1imzdBDg4Opqw9OGhim+1TKzkLcBDFNtsnHKywzfYJym6Agz626Sd8PI4VeH+HAye22T6RyWR8SI4JtuknrVaLtQQ7xTb95OTkhLdPmGCbfsLjn7ACH4/jwIlt+gmPp8MK2+zv8Hg6rMD/iXHgBPcTDpzYZn+Hx9NhhW36CX9+hxV4f4cDJ7ifcODENvs7EomEj58wwTb9hM8/YQXe3+HAiW22T3Q6He/vMME2/aRUKrGWYKfg/R0OnOB+woET3E84cGKb4yf8+R1W2Kaf8Od3WGGbfsLXI2CFTeWzHz16NIFAMBgMMpmMQCAwmUzIVenp6VhLsxdsqn3y8fHJyckxRY5LpVKDwRAbG4u1LjvCpu7vZs+ezWb/zxb1bDZ75syZ2CmyO2zKT9HR0UFBQc2PdO3aNTo6GjtFdodN+QlqolgsFvQ3i8WaPXs21orsC1vzU58+fbp16wb93aNHD7xxQhlb8xMAYPr06SwWi8vlzpo1C2stdgcM93dKmV5YrVEp9XDogQEePaRX0EgHBwdnUnD5A0uZ2KTRiFwvCp1h41swdmj+yWgEF/fVVpUrvbo46rS2M4+FBCQSoapc4RVIHznTHdhu6uH2+0mrNp7YXBk5hOcRYO+bered6qfKe9cEEz73JlNs01Pt99Ohn1/FfeDO4VPglmTjCGvUOen1ictg3tvYQmjneLwkV+oV4ISbqR1wPaju/o6lBVKshSBCO/1UV6GiM23qWQ2a0BnE+grb3LGonX5SKw0sLhluMfYCi0dRK2wz/KGdftIoDQY9fkPXTgw6o1phKdMr8GKD85k4GIL7CQdOcD/hwAnuJxw4wf2EAye4n3DgBPcTDpzgfsKBE9xPOHCC+wkHTnA/4cAJ7icAADhx8tB7Q6IUCgXWQqwe3E84cIKNnzBJmoBopbaUBqIjoBQTJxY3fTB+6MIFn5eVl2Zl3ejSpevmTbsAAGlnThw7niIQ1Lu7ew4ZPGLK5OlUKlWlUm3avC47+xYAICys1+JPl7m7ewAA7t3P/3PX1qdPn3A4Lr3Co+fNXcTl8gAAFy6eOX362LPn5XS6Y+/omMWLlrHZHADAb5t/unnr2rIvkrbv3FhVVbH+l+2REb3r6mp3JW/Ly7utUMgDAoImT5r23qBhkMiMjOuHjuxtaKgLDQlf9uU3rq5u0PGW6p09d3In/wB//4BTqUd8ff2hT2TnoBpjmZKye+zYSb+u30kkEgEAe/f9cfxEyvhxiX5+nSsqXhw9tr+y6tXKFf89dHjPpUvps2ct5HJ5ly6n0+l0AEDB3dwV//5s2ND4cR9MkUrEJ08d/mLZwt93pNBotOLiIl9f/2HD4kWixlOpR+QK+drVm6Aa5XLZ7j3bl36+QqVSRvSKFgoFi5bM0uv1iVNmcNguhUX3BIJ6k7z9B/6cPHm6Wq3af+DPteu+3fDrztbrBQDk5d1WqVVrftwICLa5vuBdQdVP3buHzpu7CPpbIGg4eCg5adXqgQOGQEe4XNeNm9YuXrSspraaTqdP/XAWiUQaFf8B9O6Wrb+MThj/2ZKvoJdRUX1nzp6Yl3+7f9x7X/xrJeH/f04SiZRyMFmtVlOpVACARqNZ9kVSt24h0Lv7D/zZ1CRK3nXU19cfAPD++wnN5f26fifUEOp0uj93bRWLm5yd2a3UCwAgkkjfrFoDOR4HbT9FRPQ2/V1QcEen061ek7R6TRJ0BBqCCBrqhw4Zee3axa9XLFn06ZedOwcCAGpra16+fF5VVZF+LrV5gfX1dQAArVZ7KvXIlavn6+trqVSawWBoahLx+e4AABqNZjITAOBOblZEr2jITG/CYjlDf3TuFAgAqG+oUyqVrdQLAOjWLQQ3U3NQ9RON9vdXL2wUAADWrN7k5spvfo6np3fnzoFr1/y28/dNcz9OHBX/wdLPV4hEQgDAzBnzB/Qf3PxkFxee0WhcuWpp6ZPimTPmd+8elpFx/cjR/Qbj6+hsOt2x+fkiUWNkRJ+36iQ4OAAA9Hp9K/W+Lp+Gm+l/wGyNCpP5OguK2daiT+/Y6Ki+J08d3r5jI5/vMWjgUACAWq168+T79wsK7uauWvnj0CEjAABVla9aqZTBYDaKhG0XyWAwW6oXxyyYzT/16hVNIBBSTx81HTFtaqDRaAAADg4OkyZ+xOO5lpWVeHv78vnuFy6eMZ2j0+m0Wi0AQCxpAgAEdekKHYdetpQ8M6JX9N27uTW11aYjre8c1Eq9OGbBrH3y9vIZPy7x5KnDK5P+FddvkFAoOJ12bO2a34K6dD2VeiQr++awofFCYYNA0BAc3J1AICz69Mtvv1u+aMmsMaMnGvT6S5fThw2LnzhhavduoRQK5c9dW0eNGvfsWdmhw3sAAM+flXt5er9Z6fRp87Jv31q8ZPb4cYkuLtz8/Bw63XHZl0ktiWylXoS/HmsFy/nxRZ9+8cnCpc+flW/ctPbc+dT+ce+58tygIZRWo9mxc+O586fHj0+cMnk6AKB/3HtrV28ik8jbtv+6P2UXn+8RFhYBAHB1dUtatbqsvOT7/3xVUHBnw6+/9+0bdyr1iNkafX39t/yWHBgQlHJw944dG2vrasLDo1oX2VK9OGZpZ/6C9D9rOvdk+QQ7ISDJ9nn1WP7ioWTUPA+shcAP/vwOB05wP+HACe4nHDjB/YQDJ7ifcOAE9xMOnOB+woET3E84cIL7CQdOcD/hwAnuJxw4wf2EAye4n3DgpJ1+YnJINrwJCdIQCIDJsc1s2+30kyOLJKhQwS3GXqivUDk52+ZGU+30k393J0kjHvbaTqQijX932wwda6efXL0pXgG0zNQ6uPXYPhmpdb5BjlxP29z6pkP73xVlScofyHy7Mly9aSQyPp5qDZ3W0FCpflUi7xLuFBLLwloOUnTITwCAmheqx3ckcrFeVKdp+1UymYxOpxGJSK2G0GjUwAgoVCqMZTY2CslkMpVKI5PJhHdfXc7hU5ycid16szw60WBUZWl01E/tIC8vr6ysbOpUBJeI/PHHHwCA+fPnw1XgvXv3Vq5cWV9fT6PReDyej49PXFxcZGRkly5d4KrCNkDVT/fu3fP19SWTyaYt7RGirKwMAADvjz19+vTHjx9DfxuNRiKR6ObmxuFwDhw4AGMt1g5685lFRUXbtm3jcrlImwlyEuwtx6hRo0ik1x00gUAwGAy1tbXFxcXw1mLtoOQnpVKpVCp37UIpQ1JGRsatW7fgLXPgwIFubm7Nj/B4vIKCAnhrsXYQ95NSqRw+fDiZTO7du3cbToeHx48fl5SUwFumh4dHcHCw6SWDwbh48SK8VdgAiK83v3r16uHDh009BTpMmDABiXFhQkJCfn6+VCqFzFReXu7t7Q0lFsOBQHA8npKSMm3aNIQKx4qxY8c2NjZmZGRAo/L+/ftfuHCByWRirctSQKq/O3r0aOupSxDl5s2bCHVGaWlpkJmgUXlmZmZ6ejqUEAYHQT8FBwfPmjULocLfSlVV1aNHj9Cp68MPP5RIJCaT2Tnw+2nGjBkAgPDwcNhLbjtDhgyZMGECatXxeLyTJ0/W1NSgVqPFAvP4acuWLZMmTXJ3d4exTGuhuLjY19eXwWBgLQRLYPaTRqOhULB/cv7w4cP8/Hz0O1ypVJqSkvLJJ5+gXK/lAFt/N2TIEIPBYAlmgmydlZWFfr1MJpPD4eTn56NftYUAT/u0c+fOefPmoTzJ1AoymaywsDA2NhaT2l+9ekWlUvl8fhvOtTVg8JNKpaJSqe0I4bBhlErll19+uX37dqyFoE1H+7s5c+aUlpZaoJn+85//YDgBRqfTZ86c+fDhQ6wEYEWH2qfMzEwPD4+AgABYJcHDpEmTfvrpp86dO2OoQSKRoBBMYVFgEE+HDrm5uX5+fpgPYk6cOFFeXr5ixQpsZaBGO/1UXFy8efPmnTt3IiDJ1rh27RqXy8V2ghc12umnZcuWrVu3znJu6N6kuLj40aNHkyZNwlqIfdHO8fj69est2UwAAFdX1927d2Ot4jVVVVVffPEF1irQ4J399ODBg0OHDiEjBk5cXV1/+OEHlcoiFjF7eXkFBwenpaVhLQRx3rm/69u3b2ZmpoU3TjhY8c7tU05OjrWY6cmTJ+vXr8daxd88ffq0srISaxXI8g5+UigUDx48QFIMzAQFBd26dauqqgprIa/RaDQ2P3HwDn5auXKlVCpFUgz87Nq1y3Ja027dug0cOFAkEmEtBEHaOn6qra3Nzs4eP3488pJwrBibnR83ceDAAblcvnDhQqyFAGjhckNDA1aBDyjQpv5OJBL9/vvvyItBhOnTpz9//txCemqhUGgVsy3tpk1ji+TkZA8PK97876effsJawmu6du0aFxeHtQoEaVN/V1ZWFhgYaIFBKW3n+PHjnTp1iop6y+6uOB3E9sdPJkaOHLlv375/5CBAGa1Wm5aWNnHiRAw1IMrbx08//PDDlStXUBGDLBcuXOByudhqkMvlO3bswFYDorzdT5mZmTbT5dfU1OTk5GAogEKh2HbIgx31dxB79uyRy+WLFy/GWoht8hY/yeVyIpFoYylEZDIZiUTC5EMJhcKCgoLhw4ejXzU6vKW/W7RoEZQ70JZgMBiZmZmYLA8vKiq6dOkS+vWiRmt+MhgMdXV1oaGhKOpBiaFDhy5ZsuT58+co18tisYYNG4ZypWhid+On5lRVVXl6elr1vJql0Vr7JBaLbfthOJ/P/+uvv9CsMS8vr7q6Gs0aUaY1P/3666/Z2dkoikEbEonk6+s7ZcoU1Gr8+eefLSQEGSFa8xORSAwLC0NRDAYEBgYeOnRIrVabjgwcOHDfvn0IVTd48GBsl5gijV2Pn0zU1dXJZLKAgIABAwbI5fLIyEhohwWcd6XF9kmtVt+/fx9dMZjB5/MvX77cp08fhUJBIBBqamqEQiHstVRWVtr8V9qinwoLC+1q+e++ffv0ej30t0wmM22tASNHjhxBoliLokU/6XS6gQMHoisGG8aPHx8ZGdk8GYtUKr19+zbsFfXt23fo0KGwF2tRtBhPFxMTExMTg64YbAgODob6OFPaZ6PRiMRGGjbzWL0ViN9//73ZN168eKHX6x0dHVGXhDZDhw6NiYnhcrlCoZBEIkFDKCqV2r9/f2dnZ7hqEQgE+/fvt/mAvhbbp/Xr10+bNg3VgCEj0KgNcokevRr/HybNY8zIqWNGTs3Pz8/IyHj+/LlQKMzLfsx4D7ZExRk37jVUK0X11rrpshOTSKE5vHVT+xbnC7755psFCxZ4e3sjou4NHmZLHtxqUkh0VCfsN/42Go16vR7ehXtGgwEQCNb7bEcp1bNcyGH9nXvEtJYhzSLmn+5cFIkatD0HuDDYlrL2EudNZE26BzcbOW7kPiM4LZ3T4v0danGMt88J5U36fmPccDNZOAw2qd9YN5lYf/tci5Nz5v2kUCiWL1+OpLbXiOq1ojpt9EgeCnXhwELvEbzGOq2o3vwWSOb9pNFoEhISEBYGAAANlbb8cNRmMQJBlXk/YTx+unutSWcgdOsN2205DgoU324iU0DEYPabb5lvn5qamjIzM5EXBrQag0aJwQQBTkfQqAw6jcHsW+b9VFZWlpKSgrAqHBvEvJ/YbLbNP2nCQQLzt+hdunTp0qUL6mJwrB7z7dPLly/tedMtnHZj3k93795FaD9nHNvGfH/n6+vr5OSEuhgcq8e8nyIjI1FXgmMLmO/vysvL7XDvNpyOY759yszMlEqlISEhqOvBsW7M+ykgIECrtdbILxwMMe+n/v37o64ExxYwP356+vRpeXk56mI6xOixg3bs3NTxcmpra2pqrTXFgF6vLyrCcomfeT9du3bt+vXrqIvBnqrqyqnTxpSWFmMtpJ388usPGzatwVCAeT/5+vr6+PigLgZLoLgdvU7X7gCeyspXcIsyQ+vyNM0SMcBYbNvBOP7pzoVGrRb0HOjyTledv5B2KvXIq1cvGAxmbMyAuXM+5XBcRo8dNKD/EI1Wk5V1w5nFTkycOXbMRCg2cP+BP69fv1TfUMfl8oYPGzVr5gIikQgAmD13cif/AH//gFOpR9Rq1dbNe+bN/9BUy/vvJ6z4yvxiMgihULBl6y8FBXdIZHJkZJ9bt679viOlU6cAAEDamRPHjqcIBPXu7p5DBo+YMnk6lUotKy9d8tmcdWs2/7Fry9OnT/h8jwUff9av3+tFszW11du3byi4e4dCoQZ16Tpnzqddg7sDAH7b/NPNW9eWfZG0fefGqqqK9b9s9/H2271n+507WXK5zMfHb+qHs4cOGQEAWPfz95cupZvkHTp4xsPdEwBw+fK5g4f3VFdXcrm8UfHjPpo628HBQSxu+mD80IULPi8rL83KuhEc3H3ThrambLj/VyOVBnqPMPOrmR+PV1VVGY1G1Ba3vBN79/2+b/+fgwYOnTThI1FTY17ebRKZDL114eKZ94cn/Gvpyut/Xdr027pO/gFhYb2IRGJBwZ2Y2AGeHt7l5aUpB5OZTNbkSdOgS/LybqvUqjU/blQoFT4+fqtW/rh6TdLsWQt7hUdxOK25XK/Xr1y1tFEk/PzzFY2Ngj93be0VHgWZae++P46fSBk/LtHPr3NFxYujx/ZXVr1aueK/UFaI//ywYsni5R7unnv27vxxzaojh9KdndlCoWDJZ3O8vHwWL1pGIBAuXz73+dJ5O7cfgAqUy2W792xf+vkKlUoZ0Su6pra6pOTR2DETnVnsW5nXV69J8vLy6da1x7Spcxrq62pqqv694r8AAK4LDwBw6VL6up+/HzJkxNw5nxYXFyXv2QEAmD5tLvQpUlJ2jx076df1O+FazGO+lHPnzgEA5s+fD0sdMNLQUJ9yMHnYsHjo5wEAJE6ZYXp3+LBRX3/1HQCgf9x7k6eMvHHzCuSn7dv2mRYqVddU3sq4bvITkUT6ZtUaOp0OvQzq0hUA4OvrHxr6lu3IHz9++KSs5Ltv1w0aOBQA8OrViwsXz2g0GolEfPBQctKq1QMHDIHO5HJdN25au3jRMujlksXLB783HAAwb97iBQunPSi8O6D/4AMpuzhsl19/2QH9rsOGxk+b8UH6+dQli5ZBTeyyL5K6dXs9Hejp4bU3+Tj0iUaOHDtuwtCsrBvduvbw9vZ1dmY3ioQm8UajcVfyttDQ8KSVPwIABvQfLJVKjhzdN2H862a4e/fQeXMXwfTjgBb95ObmZgnrqN6k4O4dvV4/drT5/QWcnV9HoNJoNE9P7/qGOuilSNS4/8Cfefk5UqkEAMBkME2XdOsWYjLTOwEV7un5ugn39vY1GAxKpaKg4I5Op1u9Jmn1miToLeibFDTUQy/ptNfV8fkeAACBoAEAcOdOVn1DXXzC39M0Wq22ob7O9HFMZoIof/pk777fofsGvV7f2Gh+wUll5SuBoGHK5OmmI9HRMecvpFVWveK7uQMAIiJ6t+Ozt4J5P33wwQfwVgMX0Bfn6sp/65kORCKUL6WxUTh/4Ud0uuOc2Z94enonJ2+vqHxpOs30674rXl4+AICiovtQk/b48UMez9XZmS1sFAAA1qze5Pa/Ij09vZ+/eNr8CJlEBgAYDHoAQKNIGBPTf/68Jc1PcHJivBZJ/59V/3fv5X29Ykmv8Kivln/n5Oj07ffLDUbz0bcyuQwAwGb/3XEzmSzI3JCfaO39+C1h3k8CgcBoNLq6usJbWcdhMJjQt+/m9nZLQZw5e1Ikaty2ZS+f7w4AcHNzb+6ndhMc1C06qu8ff26uq6tpEouysm8mrVpt+sGgTrPtpTGZLLG4qY2XHDiwy9PTe83qTVDn+I9/ieYdC+RpsbjJdEQkamwuEnbMzxecOnUqNTUVoSo7Qq/wKADA+fOnTUea59kxi0TSxGZzIDMBAMSSpla6ciqVBgAQChraImbJ4uXe3r4VlS/ZzpytW/ZAA6levaIJBELq6aOm05RK5VuLiojo/fDhg9Inf2eHauUqsaQpMCAIMpNGo1EoFQbD6/aJRqM3NgpNL7lcnjvfIzc3y3TtzZtXaTRaYGBwWz5gOzDfPnG5XMscP/n4+CWMGnc2/ZREIo6OjhGLm86ePblhw+/QjbFZwsOjUk8fS96zo0ePnhkZ1+/cyTIYDGJxk2mw1Rw3N76nh9exEyk0Ol0iEY8fl0ilUs0Wq9PpPl08c9LEaV5ePgQCQSqVyGQyBoPh7eUzflziyVOHVyb9K67fIKFQcDrt2No1v0HdYkvMnDE/Jydz+VeLJk+axuG45OZm6w36H//7a0uf6NKls+cvpLGYzsdPHpRKJS+ePzUajQQCoWdYxIWLZzZsXBMaEs7FQpieAAAOl0lEQVRksmJjB8yauWDdz9//sv6H6OiYu3dzM7NuzJwxn06nazTtnKlqHfN+mjBhAhKVwcK/lv7b3d0zPf1UVvZNV55bdHQMidjave6A/oNnTJ+XevrY6dPHYmIHbNu6d+26b1NPH501c8GbJxMIhKSkNT//8p+t29a7ubm/N2i4u7v5jSRJJFJUZN8DKbtMDSSTwdz8225//86LPv3CzY2fmno0L+82l8vrH/eeK+8tm6R5eXpv3Zy84/dNBw8lEwiELl26jvugxazDc2Z90igUbNn6C5PJShg1fvLEaRs2rbl3Pz+iV/SwYfGlT4ovXzl3OydjxPujY2MHvP9+gkqtOn7i4OUr53hc1/kfL2l+Rww75uczhUKh0Wjk8RBfBt6++UwLQa/XQ/OiRqOxuqZq3seJkydNmz3LIjYqRpR3ns88efKkZc4/oUxOTubqtUlm39qw/vd1P3/n5ubeMyyCTKYUFd1TqVQBAUGoa7QsrGz8hDLh4VF//G5++2hnFnv4sFHXr1/as3cnhULp1Cnwu2/XDeg/GHWNloVVPr/DwZZW+jvz8wVCoVAgECAvDMfWMO+ntLS0o0ePmn0LB6cVzI+f+Hx+W2bhcHD+gXk/jRo1CnUlOLZAi/mfkNjABMfmMe+nc+fOIbdnF44NY76/Y7PZ+PgJpx3g4yccODHf36lUKolEgroYHKvHvJ+uX7/+yy+/oC4Gx+ox39+xWCwmk2n2LXih0AgEYmt7GONYIBS6A8V8VFgL7VNcXNxXX32FrCgAAAAsF3LdSwUKFeHASN1LJcuFbPYt835SKpV1dXUIqwIAAL4fDYVacOCFAICbr/kGyryfSkpKVq1ahbAqAG0x4xvsePNYLQp14cDCzeO1vl0dW9q8yfxRDoeD2uLgngOcaU4O11KqQwe4cPgUMhUfTlkiGpWhqUFTeLOxe19WcCSjpdMsYv87AMDLx4r7N5rqK1U6jUXo6TjQF2u9Gyj+AyKJ4O5PCx/E9g1ubQtg837S6/UCgYDPb+saNxjRa23ET7t37wYAzJ07F2sh8EAkt+kfw3x/p9VqJ0yYgM6WQP+gjbotn/CIMKPRaDMfp42Y9xONRmMwGDqdDt49dO2K3r1hTg1gFVjK+Mn2KCoqMhgMPXv2xFoIqrR4MyWXy03LlnHawe3bt+/cuYO1CrRp0U+fffZZYWEhumJsikGDBg0cOBBrFWjT4vDI398fD4HqCEFB9ri2Ex8/IUV+fj6NRrO3PSZa7O8EAkFDQ5vS1uCY5erVqyUlJVirQJsW/ZSTk7Nt2zZ0xdgUgwYNssNtulr0k7//O6RXw3mTvn37durUCWsVaIOPn5AiNTU1JibG3d0dayGo0trD/KamplbexWmdPXv2QAlh7YrW/LRgwQKr2xXIchg7diwmD9SxpTU/hYWFVVdb605LmDN37lw7fPqJj58QobKyMj8/32LTuCNHa+2TTCZ79QqNPZNsj5s3bz579gxrFRjQmp/IZHJiYiKKYmwHPz+/MWPGYK0CA97S3x0+fHjgwIGeni1m98bBaQ4+foIfkUh08uTJefPmYS0EA96ymEQikTx48AAtMTZCWlqaSqXCWgU2vMVPLBbr22+/raysREuPLdCjR48ZMxDcg8CSeXt/l5GRQSAQ4uLi0JKEY8Xg4yeY2bBhQ79+/fr06YO1EGxo02Lco0ePFhQUIC/G6nny5ElxcbHdmqmt7VNNTc3HH3+cnp7+1jNx7Jy29ncSiYRCodBoeDqUFnn27JlcLg8NDcVaCJa0NfkEi8XCd+BohZKSkm+//dbOzfQOfgIAPH/+fOnSpUiKsW4OHDiAtQTsebf7u7y8PA6HExgYiKQk6yM/Pz8kJAQfDLxb+wQAiI6O9vPzw6cYmjNx4kQej4ebCeKdk3eRyeRJkya9ePECGT1WRm1t7eHDh/G1GybakwzuxIkTRUVFdr56WCAQ7Ny5093dnUw2n5nUPmn//LhWq719+/aAAQPglmQdjBgxIj093Q4jelun/ckqyWRyamrq3bt3YdVjBTx69AgAcPHiRdxMb9Kh5KcbN260t8CMr7/+Wq1WY63CculoMt3Y2FgAQFJSks0v1tNoNCKRaNiwYREREVhrsVzgiS+oq6vbtGnT2rVr4ZBkiVy9epXP5/fo0cPBAU9n3RrwfDt8Ph8y05UrV2Ap0KIoLCy8evVqaGgobqa3AvMX5OTktHDhQnjLxBa9Xk+n09etW4e1EOsA/ni6wsLCsLCw2tpaa08FIRAIRo4cmZeXh7UQawL+BjwsLAwAcOPGjSNHjsBeOJrk5OTYYULVDoLUgCAxMbGioqL5Td+4cePi4+PLysoQqrHdlJWVJSQkjBs3znRk06ZNAICEhAR8wPSuIPh9LV++nEql1tTUNDY2AgAqKirq6+sPHz6MXI3t49ChQzU1NS9fvoRezps3LyoqCmtR1gri6xF0Ot3IkSNlMplWqwUAeHh4bN261c/PD9FK286LFy+WLFlSU1MD7d2Tl5dXV1dnh3l24ALx9pxEImm1WshMUCi6RY2rjh07ZspJZDQa+/Xrh5upIyDup9GjR8tksuZHbt++bSGZg2trazMzM5tvKaZWq+0zjwVcIOunKVOm1NXVGQyG5r1qVVWVhYyijh07BvV0EEaj0Wg0VlVVYSrKukF8/HT8+PHCwsLnz58rlUqZTCYWi7VarYeHx+HDh9HZQr0lmpqaPvroI2ibZBaLRaPROByOj49Pjx49pk+fjqEwqwZxPwmqNOUPZLUv1NImtUKmc6Do1WIHIzASiURE620Ler2eAAhUlsGgJToyySw2he9PDezJ4HlSsJZmrSDopzsXREXZYgeigxPXkc6ikqlEEpVEohCBpYWfEwg6jV6n1uk0eoVYLRcqjHpDSD/nPiM4WCuzPhDxU/7VpjvnBe5BXBbfiUzDvh16V7QqnbhOUVcm7DuKFzmYjbUcawJmP2nU4OTmagKZxA/iWvtOzEaDsa6s0ajTTljiRaFircZKgNNPYqH2wI8vu8R6Uxm2E6KvlmrLcyqnJ/mxXGznQyEHbH6SiHSnd9T69vKApTSLwmgEFfdrxn3qzmTjAeNvAZ75J63GmLLmpU2aCQBAIADfXh77f3ih11nYnYTlAY+fUta8DOzrDUtRFktgjPeBNXg29rcAg59unRSwvdgURxvvC6hOZGcP58zTeJKZ1uion2RNutK7Uo43ljPdqMHxZhbnShUSu9s1qu101E+3UgWuAS4wibECXANcbqbiTVSLdMhPSpmh5oWa7cGATw9s3MlPW/ZNH4kE5t+e48mofqpUKwzwFmszdMhPzx/KHJ3tLk8N3Zn27KGsDSfaIx3yU9l9uRPXET4x1gGD61R2T461CgulQzdlCqme702HT8zfaDSqC1d33Cu8pNWqXXl+g+I+Cg8dBgC4lX34ftHVAbEfXri6QyoVeHl2nTT2326ur9MvVVWXnj6/oaKqmMXkuXJ9kRAGAGDw6HWPxQgVbu203086jVFUr/YIgf8pncFgSD74pUhUM3jATAbD5emzgpRjSWqNsk/kGADAq8qHN7MOThq7Uq/XnTiz9sip/362IBkAUNfwYkfyJ06O7PhhnxIdSFdu7IZdGIQDkSCqU+u0RhLZyp9QIkD7/SSX6Kh0RGIHior/ev7i/sovTzuzXAEAEWHvqzWKzNtHIT8BAGZ/tJ7F5AIA4vpOPnvxN7lC7OTofO7SFgLBYcmC3QwnDgCA4OBw6uzPSMgDAFDoRIVEz+La+JRbO2j/N6KQ6lmuiHR2j0uz9Abdmg1/L4gzGPR02t93kVTK63o5bA8AgETSQCZRS8tzYqInQGYCABAdEPyxnV3pSpkO99ObtP8boTk6SAUqVwRS/UplQhaTt3D2tuYHHcz5g0QkQ26TSAV6vc6Fg9IDRIlARXW0o1m3ttN+PzmySBoVIjPFjnSWTC7isD3I5LaGHUHNkkwmQkLPm2hUOkem9cUJokD75wuodAcCARgN8D9yDwyINhj02bknTUfUmrfkfqXRnHhcnwePrul0Wtj1/AOjwUgkEig0fCm6GTo0AmC7URRitRMH5inNyJ4j7+SfTr+0RdRU4+URXF1bVlR846vPjlIorVU0/L15h058t+WPeb0jEggODhm3j8KryoSiSc12wxcsmKdDfuoS7lT2UAG7n0gk8sczN5+/vO1e4eXbeamuXN/Y3uOJxLdIjeg5QqmU3sg6mH55C9+1s59PSIPgJbzCIGQCRZdwJyRKtgE6FJ/Z1KA9uaU6IMbGI5/+QXl2xaTPvZx5ePivGTrW37mSnV0pSomGzmqx/U9aPcTscT+f0JcVRW8ed6I7//uLUx1R9Q+27VpQU1f+5nE2i98kqXtXAYomNdeDipupJToaP179THX1sMA3osUb9UZRtfk3jARAMFM1geDAYcOZ2E4sadDrzQzSdTotiWTGFq0LeFFQPWKaq7u/3T0FbyMdnZHz7ExjsB2kDUpmC3ObLhzPDlbRQaBJdliQ1CvYXCJuplaA4aY3fpa74FkjHGIsHcGzxvhZtrnmAi5g8BPNyWH4NNdXd2vacK4V8/Ju9YiZbhQ6/gy4NeCZlPMKpMcmcCqL6mEpzQKpKqof8IGLZ2dEnlfaErBN8gb2dOoznPmyoIXRtzXzIr+67whWpx74nNPbgTl/QfUz5aUDDVw/NotvC9++uE4ufC6Kn8N398PH4G0C/vwqGpXxwt5aUb3OLZDryLHWPBIKkaquXMjlk+PnuONxc20HqfxPda/UORdE9a9UTlxHlpsj3ZlKJFn6A1SDzqAQqyX1CrlQ4eZLi4nnuPlY6/8DViCbn07aqHtaJH9yV9ZYozYYjBQ6kcGlqWWIhwC8EzQGWSpUaZR6IonAcacG9WIEhDkxOXisXHtAPN+hCZ3WqJDoVHKDAYEQl47gQCTQHB0cWSS8X+s46PkJxx6w9DENjnWB+wkHTnA/4cAJ7iccOMH9hAMnuJ9w4OT/ALH07uaVI+vLAAAAAElFTkSuQmCC", "text/plain": [ "" ] From 85fc26db43f9d9ba79b1105e48178f5b4ddefa15 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Fri, 6 Dec 2024 08:03:26 -0800 Subject: [PATCH 41/58] lib: Support returning mixed list of commands and state updates --- libs/langgraph/langgraph/graph/state.py | 37 ++++++++++++++----------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/libs/langgraph/langgraph/graph/state.py b/libs/langgraph/langgraph/graph/state.py index 6e37c6150..0c4d0c15c 100644 --- a/libs/langgraph/langgraph/graph/state.py +++ b/libs/langgraph/langgraph/graph/state.py @@ -613,21 +613,23 @@ class CompiledStateGraph(CompiledGraph): ] def _get_root(input: Any) -> Optional[Sequence[tuple[str, Any]]]: - if ( - isinstance(input, (list, tuple)) - and input - and all(isinstance(i, Command) for i in input) - ): - updates: list[tuple[str, Any]] = [] - for i in input: - if i.graph == Command.PARENT: - continue - updates.extend(i._update_as_tuples()) - return updates - elif isinstance(input, Command): + if isinstance(input, Command): if input.graph == Command.PARENT: return () return input._update_as_tuples() + elif ( + isinstance(input, (list, tuple)) + and input + and any(isinstance(i, Command) for i in input) + ): + updates: list[tuple[str, Any]] = [] + for i in input: + if isinstance(i, Command): + if i.graph == Command.PARENT: + continue + updates.extend(i._update_as_tuples()) + else: + updates.append(("__root__", i)) elif input is not None: return [("__root__", input)] @@ -645,13 +647,16 @@ class CompiledStateGraph(CompiledGraph): elif ( isinstance(input, (list, tuple)) and input - and all(isinstance(i, Command) for i in input) + and any(isinstance(i, Command) for i in input) ): updates: list[tuple[str, Any]] = [] for i in input: - if i.graph == Command.PARENT: - continue - updates.extend(i._update_as_tuples()) + if isinstance(i, Command): + if i.graph == Command.PARENT: + continue + updates.extend(i._update_as_tuples()) + else: + updates.extend(_get_updates(i) or ()) return updates elif get_type_hints(type(input)): return [ From 015bf5e0a6139629e11b8947518ae116cf50049d Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Fri, 6 Dec 2024 08:17:50 -0800 Subject: [PATCH 42/58] Add tests, missing return stmt --- libs/langgraph/langgraph/graph/state.py | 1 + libs/langgraph/tests/test_pregel.py | 28 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/libs/langgraph/langgraph/graph/state.py b/libs/langgraph/langgraph/graph/state.py index 0c4d0c15c..c416d5f6a 100644 --- a/libs/langgraph/langgraph/graph/state.py +++ b/libs/langgraph/langgraph/graph/state.py @@ -630,6 +630,7 @@ class CompiledStateGraph(CompiledGraph): updates.extend(i._update_as_tuples()) else: updates.append(("__root__", i)) + return updates elif input is not None: return [("__root__", input)] diff --git a/libs/langgraph/tests/test_pregel.py b/libs/langgraph/tests/test_pregel.py index 2515270a1..a3f5a6d48 100644 --- a/libs/langgraph/tests/test_pregel.py +++ b/libs/langgraph/tests/test_pregel.py @@ -14807,3 +14807,31 @@ def test_interrupt_loop(request: pytest.FixtureRequest, checkpointer_name: str): assert [event for event in graph.stream(Command(resume="19"), thread1)] == [ {"node": {"age": 19}}, ] + + +def test_root_mixed_return() -> None: + def my_node(state: list[str]): + return [Command(update=["a"]), ["b"]] + + graph = StateGraph(Annotated[list[str], operator.add]) + + graph.add_node(my_node) + graph.add_edge(START, "my_node") + graph = graph.compile() + + assert graph.invoke([]) == ["a", "b"] + + +def test_dict_mixed_return() -> None: + class State(TypedDict): + foo: Annotated[str, operator.add] + + def my_node(state: State): + return [Command(update={"foo": "a"}), {"foo": "b"}] + + graph = StateGraph(State) + graph.add_node(my_node) + graph.add_edge(START, "my_node") + graph = graph.compile() + + assert graph.invoke({"foo": ""}) == {"foo": "ab"} From 4e0e9a4effe38e150089aa433c6c43c8bd0b2219 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Fri, 6 Dec 2024 08:20:41 -0800 Subject: [PATCH 43/58] Fix --- libs/langgraph/tests/test_pregel_async.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/langgraph/tests/test_pregel_async.py b/libs/langgraph/tests/test_pregel_async.py index 514703781..b278d9f77 100644 --- a/libs/langgraph/tests/test_pregel_async.py +++ b/libs/langgraph/tests/test_pregel_async.py @@ -9670,14 +9670,14 @@ async def test_stream_subgraphs_during_execution(checkpointer_name: str) -> None ), (FloatBetween(0.2, 0.4), ((), {"outer_1": {"my_key": " and parallel"}})), ( - FloatBetween(0.5, 0.7), + FloatBetween(0.5, 0.8), ( (AnyStr("inner:"),), {"inner_2": {"my_key": " and there", "my_other_key": "got here"}}, ), ), - (FloatBetween(0.5, 0.7), ((), {"inner": {"my_key": "got here and there"}})), - (FloatBetween(0.5, 0.7), ((), {"outer_2": {"my_key": " and back again"}})), + (FloatBetween(0.5, 0.8), ((), {"inner": {"my_key": "got here and there"}})), + (FloatBetween(0.5, 0.8), ((), {"outer_2": {"my_key": " and back again"}})), ] From b37c9d8a012ed67d6b1c4feec65b752791a47ee1 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Sat, 7 Dec 2024 11:49:10 -0800 Subject: [PATCH 44/58] 0.2.57 --- libs/langgraph/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/langgraph/pyproject.toml b/libs/langgraph/pyproject.toml index 0a1f0b084..925be91ff 100644 --- a/libs/langgraph/pyproject.toml +++ b/libs/langgraph/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langgraph" -version = "0.2.56" +version = "0.2.57" description = "Building stateful, multi-actor applications with LLMs" authors = [] license = "MIT" From 3f1bdb9ebf5effb39b7177cb536e5d0e4b9106ce Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Mon, 9 Dec 2024 07:12:52 -0800 Subject: [PATCH 45/58] Add sync support for the AsyncPostgresStore (#2673) --- .../langgraph/store/postgres/aio.py | 3 - .../tests/test_async_store.py | 132 +++++++++++++++++- libs/checkpoint/langgraph/store/base/batch.py | 111 ++++++++++++++- libs/langgraph/tests/test_pregel_async.py | 10 ++ 4 files changed, 250 insertions(+), 6 deletions(-) diff --git a/libs/checkpoint-postgres/langgraph/store/postgres/aio.py b/libs/checkpoint-postgres/langgraph/store/postgres/aio.py index e62d360cc..2354b3a8f 100644 --- a/libs/checkpoint-postgres/langgraph/store/postgres/aio.py +++ b/libs/checkpoint-postgres/langgraph/store/postgres/aio.py @@ -155,9 +155,6 @@ class AsyncPostgresStore(AsyncBatchedBaseStore, BasePostgresStore[_ainternal.Con return results - def batch(self, ops: Iterable[Op]) -> list[Result]: - return asyncio.run_coroutine_threadsafe(self.abatch(ops), self.loop).result() - @classmethod @asynccontextmanager async def from_conn_string( diff --git a/libs/checkpoint-postgres/tests/test_async_store.py b/libs/checkpoint-postgres/tests/test_async_store.py index eda0e2820..068ec1502 100644 --- a/libs/checkpoint-postgres/tests/test_async_store.py +++ b/libs/checkpoint-postgres/tests/test_async_store.py @@ -1,8 +1,10 @@ # type: ignore +import asyncio import itertools import sys import uuid from collections.abc import AsyncIterator +from concurrent.futures import ThreadPoolExecutor from contextlib import asynccontextmanager from typing import Any, Optional @@ -10,7 +12,13 @@ import pytest from langchain_core.embeddings import Embeddings from psycopg import AsyncConnection -from langgraph.store.base import GetOp, Item, ListNamespacesOp, PutOp, SearchOp +from langgraph.store.base import ( + GetOp, + Item, + ListNamespacesOp, + PutOp, + SearchOp, +) from langgraph.store.postgres import AsyncPostgresStore from tests.conftest import ( DEFAULT_URI, @@ -63,6 +71,128 @@ async def store(request) -> AsyncIterator[AsyncPostgresStore]: await conn.execute(f"DROP DATABASE {database}") +async def test_no_running_loop(store: AsyncPostgresStore) -> None: + with pytest.raises(asyncio.InvalidStateError): + store.put(("foo", "bar"), "baz", {"val": "baz"}) + with pytest.raises(asyncio.InvalidStateError): + store.get(("foo", "bar"), "baz") + with pytest.raises(asyncio.InvalidStateError): + store.delete(("foo", "bar"), "baz") + with pytest.raises(asyncio.InvalidStateError): + store.search(("foo", "bar")) + with pytest.raises(asyncio.InvalidStateError): + store.list_namespaces(prefix=("foo",)) + with pytest.raises(asyncio.InvalidStateError): + store.batch([PutOp(namespace=("foo", "bar"), key="baz", value={"val": "baz"})]) + with ThreadPoolExecutor(max_workers=1) as executor: + future = executor.submit(store.put, ("foo", "bar"), "baz", {"val": "baz"}) + result = await asyncio.wrap_future(future) + assert result is None + future = executor.submit(store.get, ("foo", "bar"), "baz") + result = await asyncio.wrap_future(future) + assert result.value == {"val": "baz"} + result = await asyncio.wrap_future( + executor.submit(store.list_namespaces, prefix=("foo",)) + ) + + +async def test_large_batches(request: Any, store: AsyncPostgresStore) -> None: + N = 100 # less important that we are performant here + M = 10 + + with ThreadPoolExecutor(max_workers=10) as executor: + futures = [] + for m in range(M): + for i in range(N): + futures += [ + executor.submit( + store.put, + ("test", "foo", "bar", "baz", str(m % 2)), + f"key{i}", + value={"foo": "bar" + str(i)}, + ), + executor.submit( + store.get, + ("test", "foo", "bar", "baz", str(m % 2)), + f"key{i}", + ), + executor.submit( + store.list_namespaces, + prefix=None, + max_depth=m + 1, + ), + executor.submit( + store.search, + ("test",), + ), + executor.submit( + store.put, + ("test", "foo", "bar", "baz", str(m % 2)), + f"key{i}", + value={"foo": "bar" + str(i)}, + ), + executor.submit( + store.put, + ("test", "foo", "bar", "baz", str(m % 2)), + f"key{i}", + None, + ), + ] + + results = await asyncio.gather( + *(asyncio.wrap_future(future) for future in futures) + ) + assert len(results) == M * N * 6 + + +async def test_large_batches_async(store: AsyncPostgresStore) -> None: + N = 1000 + M = 10 + coros = [] + for m in range(M): + for i in range(N): + coros.append( + store.aput( + ("test", "foo", "bar", "baz", str(m % 2)), + f"key{i}", + value={"foo": "bar" + str(i)}, + ) + ) + coros.append( + store.aget( + ("test", "foo", "bar", "baz", str(m % 2)), + f"key{i}", + ) + ) + coros.append( + store.alist_namespaces( + prefix=None, + max_depth=m + 1, + ) + ) + coros.append( + store.asearch( + ("test",), + ) + ) + coros.append( + store.aput( + ("test", "foo", "bar", "baz", str(m % 2)), + f"key{i}", + value={"foo": "bar" + str(i)}, + ) + ) + coros.append( + store.adelete( + ("test", "foo", "bar", "baz", str(m % 2)), + f"key{i}", + ) + ) + + results = await asyncio.gather(*coros) + assert len(results) == M * N * 6 + + async def test_abatch_order(store: AsyncPostgresStore) -> None: # Setup test data await store.aput(("test", "foo"), "key1", {"data": "value1"}) diff --git a/libs/checkpoint/langgraph/store/base/batch.py b/libs/checkpoint/langgraph/store/base/batch.py index 33c502574..6cfc11419 100644 --- a/libs/checkpoint/langgraph/store/base/batch.py +++ b/libs/checkpoint/langgraph/store/base/batch.py @@ -1,6 +1,7 @@ import asyncio +import functools import weakref -from typing import Any, Literal, Optional, Union +from typing import Any, Callable, Iterable, Literal, Optional, TypeVar, Union from langgraph.store.base import ( BaseStore, @@ -11,11 +12,39 @@ from langgraph.store.base import ( NamespacePath, Op, PutOp, + Result, SearchItem, SearchOp, _validate_namespace, ) +F = TypeVar("F", bound=Callable) + + +def _check_loop(func: F) -> F: + @functools.wraps(func) + def wrapper(store: "AsyncBatchedBaseStore", *args: Any, **kwargs: Any) -> Any: + method_name: str = func.__name__ + try: + current_loop = asyncio.get_running_loop() + if current_loop is store._loop: + replacement_str = ( + f"Specifically, replace `store.{method_name}(...)` with `await store.a{method_name}(...)" + if method_name + else "For example, replace `store.get(...)` with `await store.aget(...)`" + ) + raise asyncio.InvalidStateError( + f"Synchronous calls to {store.__class__.__name__} detected in the main event loop. " + "This can lead to deadlocks or performance issues. " + "Please use the asynchronous interface for main thread operations. " + f"{replacement_str} " + ) + except RuntimeError: + pass + return func(store, *args, **kwargs) + + return wrapper + class AsyncBatchedBaseStore(BaseStore): """Efficiently batch operations in a background task.""" @@ -23,6 +52,7 @@ class AsyncBatchedBaseStore(BaseStore): __slots__ = ("_loop", "_aqueue", "_task") def __init__(self) -> None: + super().__init__() self._loop = asyncio.get_running_loop() self._aqueue: dict[asyncio.Future, Op] = {} self._task = self._loop.create_task(_run(self._aqueue, weakref.ref(self))) @@ -99,6 +129,82 @@ class AsyncBatchedBaseStore(BaseStore): self._aqueue[fut] = op return await fut + @_check_loop + def batch(self, ops: Iterable[Op]) -> list[Result]: + return asyncio.run_coroutine_threadsafe(self.abatch(ops), self._loop).result() + + @_check_loop + def get( + self, + namespace: tuple[str, ...], + key: str, + ) -> Optional[Item]: + return asyncio.run_coroutine_threadsafe( + self.aget(namespace, key=key), self._loop + ).result() + + @_check_loop + def search( + self, + namespace_prefix: tuple[str, ...], + /, + *, + query: Optional[str] = None, + filter: Optional[dict[str, Any]] = None, + limit: int = 10, + offset: int = 0, + ) -> list[SearchItem]: + return asyncio.run_coroutine_threadsafe( + self.asearch( + namespace_prefix, query=query, filter=filter, limit=limit, offset=offset + ), + self._loop, + ).result() + + @_check_loop + def put( + self, + namespace: tuple[str, ...], + key: str, + value: dict[str, Any], + index: Optional[Union[Literal[False], list[str]]] = None, + ) -> None: + _validate_namespace(namespace) + asyncio.run_coroutine_threadsafe( + self.aput(namespace, key=key, value=value, index=index), self._loop + ).result() + + @_check_loop + def delete( + self, + namespace: tuple[str, ...], + key: str, + ) -> None: + asyncio.run_coroutine_threadsafe( + self.adelete(namespace, key=key), self._loop + ).result() + + @_check_loop + def list_namespaces( + self, + *, + prefix: Optional[NamespacePath] = None, + suffix: Optional[NamespacePath] = None, + max_depth: Optional[int] = None, + limit: int = 100, + offset: int = 0, + ) -> list[tuple[str, ...]]: + return asyncio.run_coroutine_threadsafe( + self.alist_namespaces( + prefix=prefix, + suffix=suffix, + max_depth=max_depth, + limit=limit, + offset=offset, + ), + self._loop, + ).result() + def _dedupe_ops(values: list[Op]) -> tuple[Optional[list[int]], list[Op]]: """Dedupe operations while preserving order for results. @@ -144,7 +250,8 @@ def _dedupe_ops(values: list[Op]) -> tuple[Optional[list[int]], list[Op]]: async def _run( - aqueue: dict[asyncio.Future, Op], store: weakref.ReferenceType[BaseStore] + aqueue: dict[asyncio.Future, Op], + store: weakref.ReferenceType[BaseStore], ) -> None: while True: await asyncio.sleep(0) diff --git a/libs/langgraph/tests/test_pregel_async.py b/libs/langgraph/tests/test_pregel_async.py index f43e76d31..b3317e5ae 100644 --- a/libs/langgraph/tests/test_pregel_async.py +++ b/libs/langgraph/tests/test_pregel_async.py @@ -12621,9 +12621,19 @@ async def test_store_injected_async(checkpointer_name: str, store_name: str) -> ) return {"count": 1} + def other_node(inputs: State, config: RunnableConfig, store: BaseStore): + assert isinstance(store, BaseStore) + store.put(("not", "interesting"), "key", {"val": "val"}) + item = store.get(("not", "interesting"), "key") + assert item is not None + assert item.value == {"val": "val"} + return {"count": 0} + builder = StateGraph(State) builder.add_node("node", Node()) + builder.add_node("other_node", other_node) builder.add_edge("__start__", "node") + builder.add_edge("node", "other_node") N = 500 M = 1 From e0a0958a60079d2425965c199baae6eb9d4886b6 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Mon, 9 Dec 2024 08:14:41 -0800 Subject: [PATCH 46/58] lib: imperative api: Generators use yield to publish stream_mode=custom events --- libs/langgraph/langgraph/func/__init__.py | 29 ++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/libs/langgraph/langgraph/func/__init__.py b/libs/langgraph/langgraph/func/__init__.py index 2dda24754..26d583ed2 100644 --- a/libs/langgraph/langgraph/func/__init__.py +++ b/libs/langgraph/langgraph/func/__init__.py @@ -1,6 +1,7 @@ import asyncio import concurrent import concurrent.futures +import inspect import types from functools import partial, update_wrapper from typing import ( @@ -24,7 +25,7 @@ from langgraph.pregel.call import get_runnable_for_func from langgraph.pregel.read import PregelNode from langgraph.pregel.write import ChannelWrite, ChannelWriteEntry from langgraph.store.base import BaseStore -from langgraph.types import RetryPolicy +from langgraph.types import RetryPolicy, StreamMode, StreamWriter P = ParamSpec("P") P1 = TypeVar("P1") @@ -76,10 +77,32 @@ def entrypoint( store: Optional[BaseStore] = None, ) -> Callable[[types.FunctionType], Pregel]: def _imp(func: types.FunctionType) -> Pregel: + if inspect.isgeneratorfunction(func): + + def gen_wrapper(*args: Any, writer: StreamWriter, **kwargs: Any) -> Any: + for chunk in func(*args, **kwargs): + writer(chunk) + + bound = get_runnable_for_func(gen_wrapper) + stream_mode: StreamMode = "custom" + elif inspect.isasyncgenfunction(func): + + async def agen_wrapper( + *args: Any, writer: StreamWriter, **kwargs: Any + ) -> Any: + async for chunk in func(*args, **kwargs): + writer(chunk) + + bound = get_runnable_for_func(agen_wrapper) + stream_mode = "custom" + else: + bound = get_runnable_for_func(func) + stream_mode = "updates" + return Pregel( nodes={ func.__name__: PregelNode( - bound=get_runnable_for_func(func), + bound=bound, triggers=[START], channels=[START], writers=[ChannelWrite([ChannelWriteEntry(END)], tags=[TAG_HIDDEN])], @@ -89,7 +112,7 @@ def entrypoint( input_channels=START, output_channels=END, stream_channels=END, - stream_mode="updates", + stream_mode=stream_mode, checkpointer=checkpointer, store=store, ) From a64f9f80c0ad50b164adff2b0d22a98f63a8fc99 Mon Sep 17 00:00:00 2001 From: Vadym Barda Date: Mon, 9 Dec 2024 20:18:29 -0500 Subject: [PATCH 47/58] docs: add a how to for multi-agent network (#2675) --- docs/docs/how-tos/index.md | 6 + docs/docs/how-tos/multi-agent-network.ipynb | 566 ++++++++++++++++++++ docs/mkdocs.yml | 2 + 3 files changed, 574 insertions(+) create mode 100644 docs/docs/how-tos/multi-agent-network.ipynb diff --git a/docs/docs/how-tos/index.md b/docs/docs/how-tos/index.md index 8256a9adb..b26656117 100644 --- a/docs/docs/how-tos/index.md +++ b/docs/docs/how-tos/index.md @@ -91,6 +91,12 @@ These how-to guides show common patterns for tool calling with LangGraph: - [How to view and update state in subgraphs](subgraphs-manage-state.ipynb) - [How to transform inputs and outputs of a subgraph](subgraph-transform-state.ipynb) +### Multi-agent + +- [How to build a multi-agent network](multi-agent-network.ipynb) + +See the [multi-agent tutorials](../tutorials/index.md#multi-agent-systems) for implementations of other multi-agent architectures. + ### State Management - [How to use Pydantic model as state](state-model.ipynb) diff --git a/docs/docs/how-tos/multi-agent-network.ipynb b/docs/docs/how-tos/multi-agent-network.ipynb new file mode 100644 index 000000000..4dde1ac79 --- /dev/null +++ b/docs/docs/how-tos/multi-agent-network.ipynb @@ -0,0 +1,566 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "87684b48-150e-4e15-b0a5-a9dd7851f8fb", + "metadata": {}, + "source": [ + "# How to build a multi-agent network" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "2c65639c-9705-49f1-840a-370718852e98", + "metadata": {}, + "source": [ + "!!! info \"Prerequisites\"\n", + " This guide assumes familiarity with the following:\n", + "\n", + " - [Node](../../concepts/low_level/#nodes)\n", + " - [Command](../../concepts/low_level/#command)\n", + " - [Multi-agent systems](../../concepts/multi_agent)\n", + "\n", + "\n", + "In this how-to guide we will demonstrate how to implement a [multi-agent network](../../concepts/multi_agent#network) architecture.\n", + "\n", + "Each agent can be represented as a node in the graph that executes agent step(s) and decides what to do next - finish execution or route to another agent (including routing to itself, e.g. running in a loop). A common pattern for routing in multi-agent architectures is handoffs. Handoffs allow you to specify:\n", + "\n", + "1. which agent to navigate to next and (e.g. name of the node to go to)\n", + "2. what information to pass to that agent (e.g. state update)\n", + "\n", + "To implement handoffs, agent nodes can return `Command` object that allows you to [combine both control flow and state updates](../command):\n", + "\n", + "```python\n", + "def agent(state) -> Command[Literal[\"agent\", \"another_agent\"]]:\n", + " # the condition for routing/halting can be anything, e.g. LLM tool call / structured output, etc.\n", + " goto = get_next_agent(...) # 'agent' / 'another_agent'\n", + " if goto:\n", + " return Command(goto=goto, update={\"my_state_key\": \"my_state_value\"})\n", + " \n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "faaa4444-cd06-4813-b9ca-c9700fe12cb7", + "metadata": {}, + "source": [ + "## Setup\n", + "\n", + "First, let's install the required packages" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "05038da0-31df-4066-a1a4-c4ccb5db4d3a", + "metadata": {}, + "outputs": [], + "source": [ + "%%capture --no-stderr\n", + "%pip install -U langgraph langchain-openai" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "0bcff5d4-130e-426d-9285-40d0f72c7cd3", + "metadata": {}, + "outputs": [ + { + "name": "stdin", + "output_type": "stream", + "text": [ + "OPENAI_API_KEY: ········\n" + ] + } + ], + "source": [ + "import getpass\n", + "import os\n", + "\n", + "\n", + "def _set_env(var: str):\n", + " if not os.environ.get(var):\n", + " os.environ[var] = getpass.getpass(f\"{var}: \")\n", + "\n", + "\n", + "_set_env(\"OPENAI_API_KEY\")" + ] + }, + { + "cell_type": "markdown", + "id": "c3ec6e48-85dc-4905-ba50-985e5d4788e6", + "metadata": {}, + "source": [ + "
\n", + "

Set up LangSmith for LangGraph development

\n", + "

\n", + " Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. LangSmith lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph — read more about how to get started here. \n", + "

\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "4a53f304-3709-4df7-8714-1ca61e615743", + "metadata": {}, + "source": [ + "## Travel Recommendations Example" + ] + }, + { + "cell_type": "markdown", + "id": "34cd131b-f0c2-4b69-887f-2cbd5afb14a7", + "metadata": {}, + "source": [ + "In this example we will build a team of travel assistant agents that can communicate with each other via handoffs.\n", + "\n", + "We will create 3 agents:\n", + "\n", + "* `travel_advisor`: can help with general travel destination recommendations. Can ask `sightseeing_advisor` and `hotel_advisor` for help.\n", + "* `sightseeing_advisor`: can help with sightseeing recommendations. Can ask `travel_advisor` and `hotel_advisor` for help.\n", + "* `hotel_advisor`: can help with hotel recommendations. Can ask `sightseeing_advisor` and `hotel_advisor` for help.\n", + "\n", + "This is a fully-connected network - every agent can talk to any other agent. \n", + "\n", + "To implement the handoffs between the agents we'll be using LLMs with structured output. Each agent's LLM will return an output with both its text response (`response`) as well as which agent to route to next (`goto`). If the agent has enough information to respond to the user, `goto` will contain `finish`.\n", + "\n", + "Now, let's define our agent nodes and graph!" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "aa4bdbff-9461-46cc-aee9-8a22d3c3d9ec", + "metadata": {}, + "outputs": [], + "source": [ + "from typing_extensions import TypedDict, Literal\n", + "\n", + "from langchain_openai import ChatOpenAI\n", + "from langgraph.graph import MessagesState, StateGraph, START, END\n", + "from langgraph.types import Command\n", + "\n", + "model = ChatOpenAI(model=\"gpt-4o\")\n", + "\n", + "\n", + "def make_agent_node(*, name: str, destinations: list[str], system_prompt: str):\n", + " def agent_node(state: MessagesState) -> Command[Literal[*destinations, END]]:\n", + " # define schema for the structured output:\n", + " # - model's text response (`response`)\n", + " # - name of the node to go to next (or 'finish')\n", + " class Response(TypedDict):\n", + " response: str\n", + " goto: Literal[*destinations, \"finish\"]\n", + "\n", + " messages = [{\"role\": \"system\", \"content\": system_prompt}] + state[\"messages\"]\n", + " response = model.with_structured_output(Response).invoke(messages)\n", + " goto = response[\"goto\"]\n", + " if goto == \"finish\":\n", + " goto = END\n", + "\n", + " # handoff to another agent or halt\n", + " ai_msg = {\"role\": \"ai\", \"content\": response[\"response\"], \"name\": name}\n", + " return Command(goto=goto, update={\"messages\": ai_msg})\n", + "\n", + " return agent_node\n", + "\n", + "\n", + "travel_advisor = make_agent_node(\n", + " name=\"travel_advisor\",\n", + " destinations=[\"sightseeing_advisor\", \"hotel_advisor\"],\n", + " system_prompt=(\n", + " \"You are a general travel expert that can recommend travel destinations (e.g. countries, cities, etc). \"\n", + " \"If you need specific sightseeing recommendations, ask 'sightseeing_advisor' for help. \"\n", + " \"If you need hotel recommendations, ask 'hotel_advisor' for help. \"\n", + " \"If you have enough information to respond to the user, return 'finish'. \"\n", + " \"Never mention other agents by name.\"\n", + " ),\n", + ")\n", + "sightseeing_advisor = make_agent_node(\n", + " name=\"sightseeing_advisor\",\n", + " destinations=[\"travel_advisor\", \"hotel_advisor\"],\n", + " system_prompt=(\n", + " \"You are a travel expert that can provide specific sightseeing recommendations for a given destination. \"\n", + " \"If you need general travel help, go to 'travel_advisor' for help. \"\n", + " \"If you need hotel recommendations, go to 'hotel_advisor' for help. \"\n", + " \"If you have enough information to respond to the user, return 'finish'. \"\n", + " \"Never mention other agents by name.\"\n", + " ),\n", + ")\n", + "hotel_advisor = make_agent_node(\n", + " name=\"hotel_advisor\",\n", + " destinations=[\"travel_advisor\", \"sightseeing_advisor\"],\n", + " system_prompt=(\n", + " \"You are a travel expert that can provide hotel recommendations for a given destination. \"\n", + " \"If you need general travel help, ask 'travel_advisor' for help. \"\n", + " \"If you need specific sightseeing recommendations, ask 'sightseeing_advisor' for help. \"\n", + " \"If you have enough information to respond to the user, return 'finish'. \"\n", + " \"Never mention other agents by name.\"\n", + " ),\n", + ")\n", + "\n", + "\n", + "builder = StateGraph(MessagesState)\n", + "builder.add_node(\"travel_advisor\", travel_advisor)\n", + "builder.add_node(\"sightseeing_advisor\", sightseeing_advisor)\n", + "builder.add_node(\"hotel_advisor\", hotel_advisor)\n", + "# we'll always start with a general travel advisor\n", + "builder.add_edge(START, \"travel_advisor\")\n", + "\n", + "graph = builder.compile()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "d77921f6-599d-443f-8b15-56b1adafd3a8", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from IPython.display import display, Image\n", + "\n", + "display(Image(graph.get_graph().draw_mermaid_png()))" + ] + }, + { + "cell_type": "markdown", + "id": "af856e1b-41fc-4041-8cbf-3818a60088e0", + "metadata": {}, + "source": [ + "First, let's invoke it with a generic input:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "26a0d4df-ff99-40f0-92a8-0b3f2c591040", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'travel_advisor': {'messages': {'role': 'ai', 'content': 'The Caribbean is a fantastic choice for warm, sunny weather and beautiful beaches. Here are a few destinations you might consider:\\n\\n1. **Jamaica**: Known for its vibrant culture, reggae music, and stunning beaches like Negril and Montego Bay.\\n\\n2. **Bahamas**: With over 700 islands, the Bahamas offers clear turquoise waters and beautiful sandy beaches, perfect for relaxation and water sports.\\n\\n3. **Dominican Republic**: Known for its resorts, beaches, and golfing. Punta Cana and Puerto Plata are popular destinations.\\n\\n4. **Barbados**: Offers beautiful beaches and a rich history, with plenty of activities and festivals.\\n\\n5. **Puerto Rico**: A mix of Spanish heritage and modern resorts, with opportunities for hiking in El Yunque National Forest and enjoying the vibrant nightlife in San Juan.\\n\\n6. **Aruba**: Known for its dry climate and sunny days, with beautiful beaches and activities like snorkeling and diving.\\n\\nEach of these destinations has its own unique charm and appeal. If you need specific sightseeing or hotel recommendations, let me know!', 'name': 'travel_advisor'}}}\n", + "\n", + "\n" + ] + } + ], + "source": [ + "for chunk in graph.stream(\n", + " {\"messages\": [(\"user\", \"i wanna go somewhere warm in the caribbean\")]}\n", + "):\n", + " print(chunk)\n", + " print(\"\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "997ea9aa-36ee-40a1-a5fc-b44a079786a9", + "metadata": {}, + "source": [ + "You can see that in this case only the first agent (`travel_advisor`) ran. Let's now ask for more recommendations:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "68a547d4-0a15-43bd-aeed-c9ba1dfe388f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'travel_advisor': {'messages': {'role': 'ai', 'content': \"I recommend visiting Barbados for a warm Caribbean getaway. It's known for its beautiful beaches, vibrant culture, and friendly locals. Let me gather some sightseeing and hotel recommendations for you.\", 'name': 'travel_advisor'}}}\n", + "\n", + "\n", + "{'sightseeing_advisor': {'messages': {'role': 'ai', 'content': \"Barbados is a fantastic destination to experience the warmth of the Caribbean. Here are some things to do and places to stay:\\n\\n### Sightseeing Recommendations:\\n1. **Harrison's Cave**: Explore this stunning limestone cave with its impressive stalactites and stalagmites. \\n2. **Bathsheba Beach**: Known for its unique rock formations and surf-friendly waves, it's perfect for a day of relaxation and exploration.\\n3. **St. Nicholas Abbey**: Visit this historic plantation house, distillery, and museum for a glimpse into the island's colonial past.\\n4. **Animal Flower Cave**: Located at the northern tip of Barbados, this sea cave offers incredible views and natural rock pools.\\n5. **Oistins Fish Fry**: Experience local culture and cuisine with fresh seafood, music, and dancing every Friday night.\\n\\n### Hotel Recommendations:\\n1. **Sandy Lane**: A luxurious resort offering world-class amenities, golf courses, and a private beach.\\n2. **The Crane Resort**: Known for its historic charm and stunning ocean views, it provides a unique blend of luxury and culture.\\n3. **Sea Breeze Beach House**: Offers an all-inclusive experience with multiple dining options and beachfront access.\\n4. **The House by Elegant Hotels**: A boutique, adults-only hotel perfect for a romantic getaway with personalized service and beachfront location.\\n\\nEnjoy your trip to Barbados!\", 'name': 'sightseeing_advisor'}}}\n", + "\n", + "\n" + ] + } + ], + "source": [ + "for chunk in graph.stream(\n", + " {\n", + " \"messages\": [\n", + " (\n", + " \"user\",\n", + " \"i wanna go somewhere warm in the caribbean. pick one destination, give me some things to do and hotel recommendations\",\n", + " )\n", + " ]\n", + " }\n", + "):\n", + " print(chunk)\n", + " print(\"\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "c1c66f91-39b0-4ed2-91e8-6daf6d124f47", + "metadata": {}, + "source": [ + "Voila - `travel_advisor` makes a decision to first get some sightseeing recommendations from `sightseeing_advisor`, and then `sightseeing_advisor` in turn calls `hotel_advisor` for more info. Notice that we never explicitly defined the order in which the agents should be executed!" + ] + }, + { + "cell_type": "markdown", + "id": "3f9930b9-16b4-4179-9990-7ddf48cb3ed7", + "metadata": {}, + "source": [ + "## Game NPCs Example" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "3f7b49c5-070e-4289-88aa-afbfae44cc98", + "metadata": {}, + "source": [ + "In this example we will create a team of [non-player characters (NPCs)](https://en.wikipedia.org/wiki/Non-player_character) that all run at the same time and share game state (resources). At each step, each NPC will inspect the state and decide whether to halt or continue acting at the next step. If it continues, it will update the shared game state (produce or consume resources).\n", + "\n", + "We will create 4 NPC agents:\n", + "\n", + "- `villager`: produces wood and food until there is enough, then halts\n", + "- `guard`: protects gold and consumes food. When there is not enough food, leaves duty and halts\n", + "- `merchant`: trades wood for gold. When there is not enough wood, halts\n", + "- `thief`: checks if the guard is on duty and steals all of the gold when the guard leaves, then halts\n", + "\n", + "Our NPC agents will be simple node functions (`villager`, `guard`, etc.). At each step of the graph execution, the agent function will inspect the resource values in the state and decide whether it should halt or continue. If it decides to continue, it will update the resource values in the state and loop back to itself to run at the next step.\n", + "\n", + "Now, let's define our agent nodes and graph!" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "f15c38c0-c88a-404b-9687-a9ef9ff20ffc", + "metadata": {}, + "outputs": [], + "source": [ + "from typing_extensions import Annotated, TypedDict, Literal\n", + "\n", + "from langchain_core.runnables import RunnableConfig\n", + "from langgraph.graph import StateGraph, START, END\n", + "from langgraph.types import Command\n", + "\n", + "import operator\n", + "\n", + "\n", + "class GameState(TypedDict):\n", + " # note that we're defining a reducer (operator.add) here.\n", + " # This will allow all agents to write their updates for resources concurrently.\n", + " wood: Annotated[int, operator.add]\n", + " food: Annotated[int, operator.add]\n", + " gold: Annotated[int, operator.add]\n", + " guard_on_duty: bool\n", + "\n", + "\n", + "def villager(state: GameState) -> Command[Literal[\"villager\", END]]:\n", + " \"\"\"Villager NPC that gathers wood and food.\"\"\"\n", + " current_resources = state[\"wood\"] + state[\"food\"]\n", + " if current_resources < 15: # Continue gathering until we have enough resources\n", + " print(\"Villager gathering resources.\")\n", + " # Loop back to the 'villager' agent\n", + " return Command(goto=\"villager\", update={\"wood\": 3, \"food\": 1})\n", + " # NOTE: Returning Command(goto=END) is not necessary for the graph to run correctly\n", + " # but it's useful for visualization, to show that the agent actually halts\n", + " else:\n", + " return Command(goto=END)\n", + "\n", + "\n", + "def guard(state: GameState) -> Command[Literal[\"guard\", END]]:\n", + " \"\"\"Guard NPC that protects gold and consumes food.\"\"\"\n", + " if not state[\"guard_on_duty\"]:\n", + " return Command(goto=END)\n", + "\n", + " if state[\"food\"] > 0: # Guard needs food to keep patrolling\n", + " print(\"Guard patrolling.\")\n", + " # Loop back to the 'guard' agent\n", + " return Command(\n", + " goto=\"guard\",\n", + " update={\"food\": -1}, # Consume food while patrolling\n", + " )\n", + " else:\n", + " print(\"Guard leaving to get food.\")\n", + " return Command(goto=END, update={\"guard_on_duty\": False}) # Leave to get food\n", + "\n", + "\n", + "def merchant(state: GameState) -> Command[Literal[\"merchant\", END]]:\n", + " \"\"\"Merchant NPC that trades wood for gold.\"\"\"\n", + " if state[\"wood\"] >= 5: # Trade wood for gold when available\n", + " print(\"Merchant trading wood for gold.\")\n", + " return Command(goto=\"merchant\", update={\"wood\": -5, \"gold\": 1})\n", + " else:\n", + " return Command(goto=END)\n", + "\n", + "\n", + "def thief(state: GameState) -> Command[Literal[\"thief\", END]]:\n", + " \"\"\"Thief NPC that steals gold if the guard leaves to get food.\"\"\"\n", + " if not state[\"guard_on_duty\"]:\n", + " print(\"Thief stealing gold.\")\n", + " return Command(goto=END, update={\"gold\": -state[\"gold\"]})\n", + " else:\n", + " # keep thief on standby (loop back to the 'thief' agent)\n", + " return Command(goto=\"thief\")\n", + "\n", + "\n", + "builder = StateGraph(GameState)\n", + "\n", + "# Add NPC nodes\n", + "builder.add_node(villager)\n", + "builder.add_node(guard)\n", + "builder.add_node(merchant)\n", + "builder.add_node(thief)\n", + "\n", + "# All NPCs start running in parallel\n", + "builder.add_edge(START, \"villager\")\n", + "builder.add_edge(START, \"guard\")\n", + "builder.add_edge(START, \"merchant\")\n", + "builder.add_edge(START, \"thief\")\n", + "graph = builder.compile()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "ab4cc03e-4e25-44ac-88b1-e415fcbce151", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(Image(graph.get_graph().draw_mermaid_png()))" + ] + }, + { + "cell_type": "markdown", + "id": "5a3ea167-c302-41f7-906e-60fd0e5cd004", + "metadata": {}, + "source": [ + "Let's run it with some initial state!" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "83f50671-9371-46dd-847d-5db824c1141e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Game state {'wood': 10, 'food': 3, 'gold': 10, 'guard_on_duty': True}\n", + "\n", + "\n", + "Villager gathering resources.\n", + "Guard patrolling.\n", + "Merchant trading wood for gold.\n", + "Game state {'wood': 8, 'food': 3, 'gold': 11, 'guard_on_duty': True}\n", + "\n", + "\n", + "Villager gathering resources.\n", + "Guard patrolling.\n", + "Merchant trading wood for gold.\n", + "Game state {'wood': 6, 'food': 3, 'gold': 12, 'guard_on_duty': True}\n", + "\n", + "\n", + "Villager gathering resources.\n", + "Guard patrolling.\n", + "Merchant trading wood for gold.\n", + "Game state {'wood': 4, 'food': 3, 'gold': 13, 'guard_on_duty': True}\n", + "\n", + "\n", + "Villager gathering resources.\n", + "Guard patrolling.\n", + "Game state {'wood': 7, 'food': 3, 'gold': 13, 'guard_on_duty': True}\n", + "\n", + "\n", + "Villager gathering resources.\n", + "Guard patrolling.\n", + "Game state {'wood': 10, 'food': 3, 'gold': 13, 'guard_on_duty': True}\n", + "\n", + "\n", + "Villager gathering resources.\n", + "Guard patrolling.\n", + "Game state {'wood': 13, 'food': 3, 'gold': 13, 'guard_on_duty': True}\n", + "\n", + "\n", + "Guard patrolling.\n", + "Game state {'wood': 13, 'food': 2, 'gold': 13, 'guard_on_duty': True}\n", + "\n", + "\n", + "Guard patrolling.\n", + "Game state {'wood': 13, 'food': 1, 'gold': 13, 'guard_on_duty': True}\n", + "\n", + "\n", + "Guard patrolling.\n", + "Game state {'wood': 13, 'food': 0, 'gold': 13, 'guard_on_duty': True}\n", + "\n", + "\n", + "Guard leaving to get food.\n", + "Game state {'wood': 13, 'food': 0, 'gold': 13, 'guard_on_duty': False}\n", + "\n", + "\n", + "Thief stealing gold.\n", + "Game state {'wood': 13, 'food': 0, 'gold': 0, 'guard_on_duty': False}\n", + "\n", + "\n" + ] + } + ], + "source": [ + "initial_state = {\"wood\": 10, \"food\": 3, \"gold\": 10, \"guard_on_duty\": True}\n", + "for state in graph.stream(initial_state, stream_mode=\"values\"):\n", + " print(\"Game state\", state)\n", + " print(\"\\n\")" + ] + } + ], + "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.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index bc1ff59ea..d83eec8cf 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -199,6 +199,8 @@ nav: - how-tos/subgraph.ipynb - how-tos/subgraphs-manage-state.ipynb - how-tos/subgraph-transform-state.ipynb + - Multi-agent: + - how-tos/multi-agent-network.ipynb - State Management: - State Management: how-tos#state-management - how-tos/state-model.ipynb From e1d8c6b11314c587ccb28bb416d5bf5478fb9951 Mon Sep 17 00:00:00 2001 From: Vadym Barda Date: Mon, 9 Dec 2024 21:01:14 -0500 Subject: [PATCH 48/58] docs: update multi-agent concept doc (#2684) --- docs/docs/concepts/multi_agent.md | 204 ++++++++++++++++++++++-------- 1 file changed, 153 insertions(+), 51 deletions(-) diff --git a/docs/docs/concepts/multi_agent.md b/docs/docs/concepts/multi_agent.md index d8ef0a73b..61bed3fd7 100644 --- a/docs/docs/concepts/multi_agent.md +++ b/docs/docs/concepts/multi_agent.md @@ -26,13 +26,88 @@ There are several ways to connect agents in a multi-agent system: - **Hierarchical**: you can define a multi-agent system with [a supervisor of supervisors](https://langchain-ai.github.io/langgraph/tutorials/multi_agent/hierarchical_agent_teams/). This is a generalization of the supervisor architecture and allows for more complex control flows. - **Custom multi-agent workflow**: each agent communicates with only a subset of agents. Parts of the flow are deterministic, and only some agents can decide which other agents to call next. +### Handoffs + +In multi-agent architectures, agents can be represented as graph nodes. Each agent node executes its step(s) and decides whether to finish execution or route to another agent, including potentially routing to itself (e.g., running in a loop). A common pattern in multi-agent interactions is handoffs, where one agent hands off control to another. Handoffs allow you to specify: + +- __destination__: target agent to navigate to (e.g., name of the node to go to) +- __payload__: [information to pass to that agent](#communication-between-agents) (e.g., state update) + +To implement handoffs in LangGraph, agent nodes can return [`Command`](./low_level.md#command) object that allows you to combine both control flow and state updates: + +```python +def agent(state) -> Command[Literal["agent", "another_agent"]]: + # the condition for routing/halting can be anything, e.g. LLM tool call / structured output, etc. + goto = get_next_agent(...) # 'agent' / 'another_agent' + return Command( + # Specify which agent to call next + goto=goto, + # Update the graph state + update={"my_state_key": "my_state_value"} + ) +``` + +In a more complex scenario where each agent node is itself a graph (i.e., a [subgraph](./low_level.md#subgraphs)), a node in one of the agent subgraphs might want to navigate to a different agent. For example, if you have two agents, `alice` and `bob` (subgraph nodes in a parent graph), and `alice` needs to navigate to `bob`, you can set `graph=Command.PARENT` in the `Command` object: + +```python +def some_node_inside_alice(state) + return Command( + goto="bob", + update={"my_state_key": "my_state_value"}, + # specify which graph to navigate to (defaults to the current graph) + graph=Command.PARENT, + ) +``` + +!!! note + If you need to support visualization for subgraphs communicating using `Command(graph=Command.PARENT)` you would need to wrap them in a node function with `Command` annotation, e.g. instead of this: + + ```python + builder.add_node(alice) + ``` + + you would need to do this: + + ```python + def call_alice(state) -> Command[Literal["bob"]]: + return alice.invoke(state) + + builder.add_node("alice", call_alice) + ``` + +#### Handoffs as tools + +One of the most common agent types is a ReAct-style tool-calling agents. For those types of agents, a common pattern is wrapping a handoff in a tool call, e.g.: + +```python +def transfer_to_bob(state): + """Transfer to bob.""" + return Command( + goto="bob", + update={"my_state_key": "my_state_value"}, + graph=Command.PARENT, + ) +``` + +This is a special case of [updating the graph state from tools](../how-tos/update-state-from-tools.ipynb) where in addition the state update, the control flow is included as well. + +!!! important + +If you want to use tools that return `Command`, you can either use prebuilt [`create_react_agent`][langgraph.prebuilt.chat_agent_executor.create_react_agent] / [`ToolNode`][langgraph.prebuilt.tool_node.ToolNode] components, or implement your own tool-executing node that collects `Command` objects returned by the tools and returns a list of them, e.g.: + +```python +def call_tools(state): + ... + commands = [tools_by_name[call["name"].invoke(call, config={"coerce_tool_content": False}) for tool_call in tool_calls] + return commands +``` + +Let's now take a closer look at the different multi-agent architectures. + ### Network In this architecture, agents are defined as graph nodes. Each agent can communicate with every other agent (many-to-many connections) and can decide which agent to call next. This architecture is good for problems that do not have a clear hierarchy of agents or a specific sequence in which agents should be called. -### Supervisor - -In this architecture, we define agents as nodes and add a supervisor node (LLM) that decides which agent nodes should be called next. We use [conditional edges](./low_level.md#conditional-edges) to route execution to the appropriate agent node based on supervisor's decision. This architecture also lends itself well to running multiple agents in parallel or using [map-reduce](../how-tos/map-reduce.ipynb) pattern. ```python from typing import Literal @@ -41,39 +116,83 @@ from langgraph.graph import StateGraph, MessagesState, START model = ChatOpenAI() -class AgentState(MessagesState): - next: Literal["agent_1", "agent_2", "__end__"] - -def supervisor(state: AgentState): +def agent_1(state: MessagesState) -> Command[Literal["agent_2", "agent_3", END]]: # you can pass relevant parts of the state to the LLM (e.g., state["messages"]) # to determine which agent to call next. a common pattern is to call the model # with a structured output (e.g. force it to return an output with a "next_agent" field) response = model.invoke(...) - # the "next" key will be used by the conditional edges to route execution - # to the appropriate agent - return {"next": response["next_agent"]} + # route to one of the agents or exit based on the LLM's decision + # if the LLM returns "__end__", the graph will finish execution + return Command( + goto=response["next_agent"], + update={"messages": [response["content"]]}, + ) -def agent_1(state: AgentState): +def agent_2(state: MessagesState) -> Command[Literal["agent_1", "agent_3", END]]: + response = model.invoke(...) + return Command( + goto=response["next_agent"], + update={"messages": [response["content"]]}, + ) + +def agent_3(state: MessagesState) -> Command[Literal["agent_1", "agent_2", END]]: + ... + return Command( + goto=response["next_agent"], + update={"messages": [response["content"]]}, + ) + +builder = StateGraph(MessagesState) +builder.add_node(agent_1) +builder.add_node(agent_2) +builder.add_node(agent_3) + +builder.add_edge(START, "agent_1") +network = builder.compile() +``` + +### Supervisor + +In this architecture, we define agents as nodes and add a supervisor node (LLM) that decides which agent nodes should be called next. We use [conditional edges](./low_level.md#conditional-edges) to route execution to the appropriate agent node based on supervisor's decision. This architecture also lends itself well to running multiple agents in parallel or using [map-reduce](../how-tos/map-reduce.ipynb) pattern. + +```python +from typing import Literal +from langchain_openai import ChatOpenAI +from langgraph.graph import StateGraph, MessagesState, START, END + +model = ChatOpenAI() + +def supervisor(state: MessagesState) -> Command[Literal["agent_1", "agent_2", END]]: + # you can pass relevant parts of the state to the LLM (e.g., state["messages"]) + # to determine which agent to call next. a common pattern is to call the model + # with a structured output (e.g. force it to return an output with a "next_agent" field) + response = model.invoke(...) + # route to one of the agents or exit based on the supervisor's decision + # if the supervisor returns "__end__", the graph will finish execution + return Command(goto=response["next_agent"]) + +def agent_1(state: MessagesState) -> Command[Literal["supervisor"]]: # you can pass relevant parts of the state to the LLM (e.g., state["messages"]) # and add any additional logic (different models, custom prompts, structured output, etc.) response = model.invoke(...) - return {"messages": [response]} + return Command( + goto="supervisor", + update={"messages": [response]}, + ) -def agent_2(state: AgentState): +def agent_2(state: MessagesState) -> Command[Literal["supervisor"]]: response = model.invoke(...) - return {"messages": [response]} + return Command( + goto="supervisor", + update={"messages": [response]}, + ) -builder = StateGraph(AgentState) +builder = StateGraph(MessagesState) builder.add_node(supervisor) builder.add_node(agent_1) builder.add_node(agent_2) builder.add_edge(START, "supervisor") -# route to one of the agents or exit based on the supervisor's decisiion -# if the supervisor returns "__end__", the graph will finish execution -builder.add_conditional_edges("supervisor", lambda state: state["next"]) -builder.add_edge("agent_1", "supervisor") -builder.add_edge("agent_2", "supervisor") supervisor = builder.compile() ``` @@ -121,37 +240,29 @@ To address this, you can design your system _hierarchically_. For example, you c ```python from typing import Literal from langchain_openai import ChatOpenAI -from langgraph.graph import StateGraph, MessagesState, START +from langgraph.graph import StateGraph, MessagesState, START, END model = ChatOpenAI() # define team 1 (same as the single supervisor example above) -class Team1State(MessagesState): - next: Literal["team_1_agent_1", "team_1_agent_2", "__end__"] -def team_1_supervisor(state: Team1State): +def team_1_supervisor(state: MessagesState) -> Command[Literal["team_1_agent_1", "team_1_agent_2", END]]: response = model.invoke(...) - return {"next": response["next_agent"]} + return Command(goto=response["next_agent"]) -def team_1_agent_1(state: Team1State): +def team_1_agent_1(state: MessagesState) -> Command[Literal["team_1_supervisor"]]: response = model.invoke(...) - return {"messages": [response]} + return Command(goto="team_1_supervisor", update={"messages": [response]}) -def team_1_agent_2(state: Team1State): +def team_1_agent_2(state: MessagesState) -> Command[Literal["team_1_supervisor"]]: response = model.invoke(...) - return {"messages": [response]} + return Command(goto="team_1_supervisor", update={"messages": [response]}) team_1_builder = StateGraph(Team1State) team_1_builder.add_node(team_1_supervisor) team_1_builder.add_node(team_1_agent_1) team_1_builder.add_node(team_1_agent_2) team_1_builder.add_edge(START, "team_1_supervisor") -# route to one of the agents or exit based on the supervisor's decisiion -# if the supervisor returns "__end__", the graph will finish execution -team_1_builder.add_conditional_edges("team_1_supervisor", lambda state: state["next"]) -team_1_builder.add_edge("team_1_agent_1", "team_1_supervisor") -team_1_builder.add_edge("team_1_agent_2", "team_1_supervisor") - team_1_graph = team_1_builder.compile() # define team 2 (same as the single supervisor example above) @@ -174,31 +285,22 @@ team_2_graph = team_2_builder.compile() # define top-level supervisor -class TopLevelState(MessagesState): - next: Literal["team_1", "team_2", "__end__"] - -builder = StateGraph(TopLevelState) -def top_level_supervisor(state: TopLevelState): +builder = StateGraph(MessagesState) +def top_level_supervisor(state: MessagesState): # you can pass relevant parts of the state to the LLM (e.g., state["messages"]) # to determine which team to call next. a common pattern is to call the model # with a structured output (e.g. force it to return an output with a "next_team" field) response = model.invoke(...) - # the "next" key will be used by the conditional edges to route execution - # to the appropriate team - return {"next": response["next_team"]} + # route to one of the teams or exit based on the supervisor's decision + # if the supervisor returns "__end__", the graph will finish execution + return Command(goto=response["next_team"]) -builder = StateGraph(TopLevelState) +builder = StateGraph(MessagesState) builder.add_node(top_level_supervisor) builder.add_node(team_1_graph) builder.add_node(team_2_graph) builder.add_edge(START, "top_level_supervisor") -# route to one of the teams or exit based on the supervisor's decision -# if the top-level supervisor returns "__end__", the graph will finish execution -builder.add_conditional_edges("top_level_supervisor", lambda state: state["next"]) -builder.add_edge("team_1_graph", "top_level_supervisor") -builder.add_edge("team_2_graph", "top_level_supervisor") - graph = builder.compile() ``` @@ -208,7 +310,7 @@ In this architecture we add individual agents as graph nodes and define the orde - **Explicit control flow (normal edges)**: LangGraph allows you to explicitly define the control flow of your application (i.e. the sequence of how agents communicate) explicitly, via [normal graph edges](./low_level.md#normal-edges). This is the most deterministic variant of this architecture above — we always know which agent will be called next ahead of time. -- **Dynamic control flow (conditional edges)**: in LangGraph you can allow LLMs to decide parts of your application control flow. This can be achieved by using [conditional edges](./low_level.md#conditional-edges). A special case of this is a [supervisor tool-calling](#supervisor-tool-calling) architecture. In that case, the tool-calling LLM powering the supervisor agent will make decisions about the order in which the tools (agents) are being called. +- **Dynamic control flow (Command)**: in LangGraph you can allow LLMs to decide parts of your application control flow. This can be achieved by using [`Command`](./low_level.md#command). A special case of this is a [supervisor tool-calling](#supervisor-tool-calling) architecture. In that case, the tool-calling LLM powering the supervisor agent will make decisions about the order in which the tools (agents) are being called. ```python from langchain_openai import ChatOpenAI From d81dec653d0760fdbc80b01000a4dcbb9b1aeac7 Mon Sep 17 00:00:00 2001 From: Vadym Barda Date: Mon, 9 Dec 2024 21:09:32 -0500 Subject: [PATCH 49/58] docs: temporarily fix link (#2685) --- docs/docs/concepts/multi_agent.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/concepts/multi_agent.md b/docs/docs/concepts/multi_agent.md index 61bed3fd7..c9bdd5d89 100644 --- a/docs/docs/concepts/multi_agent.md +++ b/docs/docs/concepts/multi_agent.md @@ -89,7 +89,7 @@ def transfer_to_bob(state): ) ``` -This is a special case of [updating the graph state from tools](../how-tos/update-state-from-tools.ipynb) where in addition the state update, the control flow is included as well. +This is a special case of updating the graph state from tools where in addition the state update, the control flow is included as well. !!! important From 43b6c06f5c0fc055db1320ac8fa9f8436c393ed7 Mon Sep 17 00:00:00 2001 From: Vadym Barda Date: Mon, 9 Dec 2024 21:19:16 -0500 Subject: [PATCH 50/58] docs: update Command concept doc (#2686) --- docs/docs/concepts/low_level.md | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/docs/docs/concepts/low_level.md b/docs/docs/concepts/low_level.md index 1d059568b..297f97ec9 100644 --- a/docs/docs/concepts/low_level.md +++ b/docs/docs/concepts/low_level.md @@ -339,37 +339,6 @@ def my_node(state: State) -> Command[Literal["my_other_node"]]: ) ``` -`Command` has the following properties: - -| Property | Description | -| --- | --- | -| `graph` | Graph to send the command to. Supported values:
- `None`: the current graph (default)
- `Command.PARENT`: closest parent graph | -| `update` | Update to apply to the graph's state. | -| `resume` | Value to resume execution with. To be used together with [`interrupt()`][langgraph.types.interrupt]. | -| `goto` | Can be one of the following:
- name of the node to navigate to next (any node that belongs to the specified `graph`)
- sequence of node names to navigate to next
- `Send` object (to execute a node with the input provided)
- sequence of `Send` objects
If `goto` is not specified and there are no other tasks left in the graph, the graph will halt after executing the current superstep. | - -```python -from langgraph.graph import StateGraph, START -from langgraph.types import Command -from typing_extensions import Literal, TypedDict - -class State(TypedDict): - foo: str - -def my_node(state: State) -> Command[Literal["my_other_node"]]: - return Command(update={"foo": "bar"}, goto="my_other_node") - -def my_other_node(state: State): - return {"foo": state["foo"] + "baz"} - -builder = StateGraph(State) -builder.add_edge(START, "my_node") -builder.add_node("my_node", my_node) -builder.add_node("my_other_node", my_other_node) - -graph = builder.compile() -``` - With `Command` you can also achieve dynamic control flow behavior (identical to [conditional edges](#conditional-edges)): ```python @@ -380,7 +349,7 @@ def my_node(state: State) -> Command[Literal["my_other_node"]]: !!! important - When returning `Command` in your node functions, you must add return type annotations with the list of node names the node is routing to, e.g. `Command[Literal["node_b", "node_c"]]`. This is necessary for the graph compilation and rendering, and tells LangGraph that `node_a` can navigate to `node_b` and `node_c`. + When returning `Command` in your node functions, you must add return type annotations with the list of node names the node is routing to, e.g. `Command[Literal["my_other_node"]]`. This is necessary for the graph rendering and tells LangGraph that `my_node` can navigate to `my_other_node`. Check out this [how-to guide](../how-tos/command.ipynb) for an end-to-end example of how to use `Command`. From 33fe467d1f32d080beb607c1241766ba72824708 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Mon, 9 Dec 2024 18:22:53 -0800 Subject: [PATCH 51/58] lib: Treat Command as "resuming" signal (#2682) - so it works w interrupt_before/after --------- Co-authored-by: Eugene Yurtsev --- libs/langgraph/langgraph/pregel/loop.py | 27 +++++++++-------- libs/langgraph/tests/test_pregel.py | 40 +++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/libs/langgraph/langgraph/pregel/loop.py b/libs/langgraph/langgraph/pregel/loop.py index 678e355ab..e96276259 100644 --- a/libs/langgraph/langgraph/pregel/loop.py +++ b/libs/langgraph/langgraph/pregel/loop.py @@ -535,9 +535,23 @@ class PregelLoop(LoopProtocol): # - receiving None input (outer graph) or RESUMING flag (subgraph) configurable = self.config.get(CONF, {}) is_resuming = bool(self.checkpoint["channel_versions"]) and bool( - configurable.get(CONFIG_KEY_RESUMING, self.input is None) + configurable.get( + CONFIG_KEY_RESUMING, + self.input is None or isinstance(self.input, Command), + ) ) + # map command to writes + if isinstance(self.input, Command): + writes: defaultdict[str, list[tuple[str, Any]]] = defaultdict(list) + # group writes by task ID + for tid, c, v in map_command(self.input, self.checkpoint_pending_writes): + writes[tid].append((c, v)) + if not writes: + raise EmptyInputError("Received empty Command input") + # save writes + for tid, ws in writes.items(): + self.put_writes(tid, ws) # proceed past previous checkpoint if is_resuming: self.checkpoint["versions_seen"].setdefault(INTERRUPT, {}) @@ -549,17 +563,6 @@ class PregelLoop(LoopProtocol): self._emit( "values", map_output_values, self.output_keys, True, self.channels ) - # map command to writes - elif isinstance(self.input, Command): - writes: defaultdict[str, list[tuple[str, Any]]] = defaultdict(list) - # group writes by task ID - for tid, c, v in map_command(self.input, self.checkpoint_pending_writes): - writes[tid].append((c, v)) - if not writes: - raise EmptyInputError("Received empty Command input") - # save writes - for tid, ws in writes.items(): - self.put_writes(tid, ws) # map inputs to channel updates elif input_writes := deque(map_input(input_keys, self.input)): # TODO shouldn't these writes be passed to put_writes too? diff --git a/libs/langgraph/tests/test_pregel.py b/libs/langgraph/tests/test_pregel.py index 1cbadf099..91d7907d0 100644 --- a/libs/langgraph/tests/test_pregel.py +++ b/libs/langgraph/tests/test_pregel.py @@ -14904,3 +14904,43 @@ def test_dict_mixed_return() -> None: graph = graph.compile() assert graph.invoke({"foo": ""}) == {"foo": "ab"} + + +def test_command_with_static_breakpoints() -> None: + """Test that we can use Command to resume and update with static breakpoints.""" + + class State(TypedDict): + """The graph state.""" + + foo: str + + def node1(state: State): + return { + "foo": state["foo"] + "|node-1", + } + + def node2(state: State): + return { + "foo": state["foo"] + "|node-2", + } + + builder = StateGraph(State) + builder.add_node("node1", node1) + builder.add_node("node2", node2) + builder.add_edge(START, "node1") + builder.add_edge("node1", "node2") + + # A checkpointer must be enabled for interrupts to work! + checkpointer = MemorySaver() + graph = builder.compile(checkpointer=checkpointer, interrupt_before=["node1"]) + + config = { + "configurable": { + "thread_id": uuid.uuid4(), + } + } + + # Start the graph and interrupt at the first node + graph.invoke({"foo": "abc"}, config) + result = graph.invoke(Command(resume="node1"), config) + assert result == {"foo": "abc|node-1|node-2"} From c2a41039def5e7e5268d1e0f622874370430952a Mon Sep 17 00:00:00 2001 From: Vadym Barda Date: Mon, 9 Dec 2024 22:44:47 -0500 Subject: [PATCH 52/58] docs: remove GraphCommand references (#2688) --- docs/docs/how-tos/command.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/how-tos/command.ipynb b/docs/docs/how-tos/command.ipynb index 3f3a4c0ef..b0ab12188 100644 --- a/docs/docs/how-tos/command.ipynb +++ b/docs/docs/how-tos/command.ipynb @@ -25,7 +25,7 @@ "\n", "```python\n", "def my_node(state: State) -> Command[Literal[\"my_other_node\"]]:\n", - " return GraphCommand(\n", + " return Command(\n", " # state update\n", " update={\"foo\": \"bar\"},\n", " # control flow\n", @@ -144,7 +144,7 @@ "id": "badc25eb-4876-482e-bb10-d763023cdaad", "metadata": {}, "source": [ - "We can now create the `StateGraph` with the above nodes. Notice that the graph doesn't have [conditional edges](../../concepts/low_level#conditional-edges) for routing! This is because control flow is defined with `GraphCommand` inside `node_a`." + "We can now create the `StateGraph` with the above nodes. Notice that the graph doesn't have [conditional edges](../../concepts/low_level#conditional-edges) for routing! This is because control flow is defined with `Command` inside `node_a`." ] }, { From 038bec2e7831e1e748372b95725c5234e38d9b87 Mon Sep 17 00:00:00 2001 From: Vadym Barda Date: Mon, 9 Dec 2024 23:27:44 -0500 Subject: [PATCH 53/58] update callout (#2689) --- docs/docs/concepts/multi_agent.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/concepts/multi_agent.md b/docs/docs/concepts/multi_agent.md index c9bdd5d89..6979c249c 100644 --- a/docs/docs/concepts/multi_agent.md +++ b/docs/docs/concepts/multi_agent.md @@ -93,7 +93,7 @@ This is a special case of updating the graph state from tools where in addition !!! important -If you want to use tools that return `Command`, you can either use prebuilt [`create_react_agent`][langgraph.prebuilt.chat_agent_executor.create_react_agent] / [`ToolNode`][langgraph.prebuilt.tool_node.ToolNode] components, or implement your own tool-executing node that collects `Command` objects returned by the tools and returns a list of them, e.g.: + If you want to use tools that return `Command`, you can either use prebuilt [`create_react_agent`][langgraph.prebuilt.chat_agent_executor.create_react_agent] / [`ToolNode`][langgraph.prebuilt.tool_node.ToolNode] components, or implement your own tool-executing node that collects `Command` objects returned by the tools and returns a list of them, e.g.: ```python def call_tools(state): From 59bfa5d0090554f378ca4579bc418a1398e39a7e Mon Sep 17 00:00:00 2001 From: Vadym Barda Date: Tue, 10 Dec 2024 10:18:04 -0500 Subject: [PATCH 54/58] langgraph: allow tools to return Command in tool node (#2656) --- .../langgraph/langgraph/prebuilt/tool_node.py | 251 +++++-- libs/langgraph/langgraph/types.py | 10 +- libs/langgraph/poetry.lock | 12 +- libs/langgraph/pyproject.toml | 2 +- libs/langgraph/tests/test_prebuilt.py | 643 +++++++++++++++++- 5 files changed, 846 insertions(+), 72 deletions(-) diff --git a/libs/langgraph/langgraph/prebuilt/tool_node.py b/libs/langgraph/langgraph/prebuilt/tool_node.py index 38c349edb..d3d0751e2 100644 --- a/libs/langgraph/langgraph/prebuilt/tool_node.py +++ b/libs/langgraph/langgraph/prebuilt/tool_node.py @@ -1,7 +1,7 @@ import asyncio import inspect import json -from copy import copy +from copy import copy, deepcopy from typing import ( Any, Callable, @@ -20,6 +20,7 @@ from langchain_core.messages import ( AnyMessage, ToolCall, ToolMessage, + convert_to_messages, ) from langchain_core.runnables import RunnableConfig from langchain_core.runnables.config import ( @@ -35,6 +36,7 @@ from typing_extensions import Annotated, get_args, get_origin from langgraph.errors import GraphBubbleUp from langgraph.store.base import BaseStore +from langgraph.types import Command from langgraph.utils.runnable import RunnableCallable INVALID_TOOL_NAME_ERROR_TEMPLATE = ( @@ -47,7 +49,7 @@ def msg_content_output(output: Any) -> Union[str, list[dict]]: recognized_content_block_types = ("image", "image_url", "text", "json") if isinstance(output, str): return output - elif all( + elif isinstance(output, list) and all( [ isinstance(x, dict) and x.get("type") in recognized_content_block_types for x in output @@ -210,12 +212,31 @@ class ToolNode(RunnableCallable): *, store: BaseStore, ) -> Any: - tool_calls, output_type = self._parse_input(input, store) + tool_calls, input_type = self._parse_input(input, store) config_list = get_config_list(config, len(tool_calls)) + input_types = [input_type] * len(tool_calls) with get_executor_for_config(config) as executor: - outputs = [*executor.map(self._run_one, tool_calls, config_list)] - # TypedDict, pydantic, dataclass, etc. should all be able to load from dict - return outputs if output_type == "list" else {self.messages_key: outputs} + outputs = [ + *executor.map(self._run_one, tool_calls, input_types, config_list) + ] + + # preserve existing behavior for non-command tool outputs for backwards compatibility + if not any(isinstance(output, Command) for output in outputs): + # TypedDict, pydantic, dataclass, etc. should all be able to load from dict + return outputs if input_type == "list" else {self.messages_key: outputs} + + # LangGraph will automatically handle list of Command and non-command node updates + combined_outputs: list[ + Command | list[ToolMessage] | dict[str, list[ToolMessage]] + ] = [] + for output in outputs: + if isinstance(output, Command): + combined_outputs.append(output) + else: + combined_outputs.append( + [output] if input_type == "list" else {self.messages_key: [output]} + ) + return combined_outputs def invoke( self, input: Input, config: Optional[RunnableConfig] = None, **kwargs: Any @@ -242,26 +263,97 @@ class ToolNode(RunnableCallable): *, store: BaseStore, ) -> Any: - tool_calls, output_type = self._parse_input(input, store) + tool_calls, input_type = self._parse_input(input, store) outputs = await asyncio.gather( - *(self._arun_one(call, config) for call in tool_calls) + *(self._arun_one(call, input_type, config) for call in tool_calls) ) - # TypedDict, pydantic, dataclass, etc. should all be able to load from dict - return outputs if output_type == "list" else {self.messages_key: outputs} - def _run_one(self, call: ToolCall, config: RunnableConfig) -> ToolMessage: + # preserve existing behavior for non-command tool outputs for backwards compatibility + if not any(isinstance(output, Command) for output in outputs): + # TypedDict, pydantic, dataclass, etc. should all be able to load from dict + return outputs if input_type == "list" else {self.messages_key: outputs} + + # LangGraph will automatically handle list of Command and non-command node updates + combined_outputs: list[ + Command | list[ToolMessage] | dict[str, list[ToolMessage]] + ] = [] + for output in outputs: + if isinstance(output, Command): + combined_outputs.append(output) + else: + combined_outputs.append( + [output] if input_type == "list" else {self.messages_key: [output]} + ) + return combined_outputs + + def _run_one( + self, + call: ToolCall, + input_type: Literal["list", "dict"], + config: RunnableConfig, + ) -> ToolMessage: if invalid_tool_message := self._validate_tool_call(call): return invalid_tool_message try: input = {**call, **{"type": "tool_call"}} - tool_message: ToolMessage = self.tools_by_name[call["name"]].invoke( - input, config + response = self.tools_by_name[call["name"]].invoke(input) + + # GraphInterrupt is a special exception that will always be raised. + # It can be triggered in the following scenarios: + # (1) a NodeInterrupt is raised inside a tool + # (2) a NodeInterrupt is raised inside a graph node for a graph called as a tool + # (3) a GraphInterrupt is raised when a subgraph is interrupted inside a graph called as a tool + # (2 and 3 can happen in a "supervisor w/ tools" multi-agent architecture) + except GraphBubbleUp as e: + raise e + except Exception as e: + if isinstance(self.handle_tool_errors, tuple): + handled_types: tuple = self.handle_tool_errors + elif callable(self.handle_tool_errors): + handled_types = _infer_handled_types(self.handle_tool_errors) + else: + # default behavior is catching all exceptions + handled_types = (Exception,) + + # Unhandled + if not self.handle_tool_errors or not isinstance(e, handled_types): + raise e + # Handled + else: + content = _handle_tool_error(e, flag=self.handle_tool_errors) + return ToolMessage( + content=content, + name=call["name"], + tool_call_id=call["id"], + status="error", ) - tool_message.content = cast( - Union[str, list], msg_content_output(tool_message.content) + + if isinstance(response, Command): + return self._validate_tool_command(response, call, input_type) + elif isinstance(response, ToolMessage): + response.content = cast( + Union[str, list], msg_content_output(response.content) ) - return tool_message + return response + else: + raise TypeError( + f"Tool {call['name']} returned unexpected type: {type(response)}" + ) + + async def _arun_one( + self, + call: ToolCall, + input_type: Literal["list", "dict"], + config: RunnableConfig, + ) -> ToolMessage: + if invalid_tool_message := self._validate_tool_call(call): + return invalid_tool_message + + try: + input = {**call, **{"type": "tool_call"}} + response = await self.tools_by_name[call["name"]].ainvoke(input) + # GraphInterrupt is a special exception that will always be raised. # It can be triggered in the following scenarios: # (1) a NodeInterrupt is raised inside a tool @@ -286,50 +378,24 @@ class ToolNode(RunnableCallable): else: content = _handle_tool_error(e, flag=self.handle_tool_errors) - return ToolMessage( - content=content, name=call["name"], tool_call_id=call["id"], status="error" - ) - - async def _arun_one(self, call: ToolCall, config: RunnableConfig) -> ToolMessage: - if invalid_tool_message := self._validate_tool_call(call): - return invalid_tool_message - - try: - input = {**call, **{"type": "tool_call"}} - tool_message: ToolMessage = await self.tools_by_name[call["name"]].ainvoke( - input, config + return ToolMessage( + content=content, + name=call["name"], + tool_call_id=call["id"], + status="error", ) - tool_message.content = cast( - Union[str, list], msg_content_output(tool_message.content) + + if isinstance(response, Command): + return self._validate_tool_command(response, call, input_type) + elif isinstance(response, ToolMessage): + response.content = cast( + Union[str, list], msg_content_output(response.content) + ) + return response + else: + raise TypeError( + f"Tool {call['name']} returned unexpected type: {type(response)}" ) - return tool_message - # GraphInterrupt is a special exception that will always be raised. - # It can be triggered in the following scenarios: - # (1) a NodeInterrupt is raised inside a tool - # (2) a NodeInterrupt is raised inside a graph node for a graph called as a tool - # (3) a GraphInterrupt is raised when a subgraph is interrupted inside a graph called as a tool - # (2 and 3 can happen in a "supervisor w/ tools" multi-agent architecture) - except GraphBubbleUp as e: - raise e - except Exception as e: - if isinstance(self.handle_tool_errors, tuple): - handled_types: tuple = self.handle_tool_errors - elif callable(self.handle_tool_errors): - handled_types = _infer_handled_types(self.handle_tool_errors) - else: - # default behavior is catching all exceptions - handled_types = (Exception,) - - # Unhandled - if not self.handle_tool_errors or not isinstance(e, handled_types): - raise e - # Handled - else: - content = _handle_tool_error(e, flag=self.handle_tool_errors) - - return ToolMessage( - content=content, name=call["name"], tool_call_id=call["id"], status="error" - ) def _parse_input( self, @@ -341,14 +407,14 @@ class ToolNode(RunnableCallable): store: BaseStore, ) -> Tuple[list[ToolCall], Literal["list", "dict"]]: if isinstance(input, list): - output_type = "list" + input_type = "list" message: AnyMessage = input[-1] elif isinstance(input, dict) and (messages := input.get(self.messages_key, [])): - output_type = "dict" + input_type = "dict" message = messages[-1] elif messages := getattr(input, self.messages_key, None): # Assume dataclass-like state that can coerce from dict - output_type = "dict" + input_type = "dict" message = messages[-1] else: raise ValueError("No message found in input") @@ -359,7 +425,7 @@ class ToolNode(RunnableCallable): tool_calls = [ self._inject_tool_args(call, input, store) for call in message.tool_calls ] - return tool_calls, output_type + return tool_calls, input_type def _validate_tool_call(self, call: ToolCall) -> Optional[ToolMessage]: if (requested_tool := call["name"]) not in self.tools_by_name: @@ -453,6 +519,67 @@ class ToolNode(RunnableCallable): tool_call_with_store = self._inject_store(tool_call_with_state, store) return tool_call_with_store + def _validate_tool_command( + self, command: Command, call: ToolCall, input_type: Literal["list", "dict"] + ) -> Command: + if isinstance(command.update, dict): + # input type is dict when ToolNode is invoked with a dict input (e.g. {"messages": [AIMessage(..., tool_calls=[...])]}) + if input_type != "dict": + raise ValueError( + f"Tools can provide a dict in Command.update only when using dict with '{self.messages_key}' key as ToolNode input, " + f"got: {command.update} for tool '{call['name']}'" + ) + + updated_command = deepcopy(command) + state_update = cast(dict[str, Any], updated_command.update) or {} + messages_update = state_update.get(self.messages_key, []) + elif isinstance(command.update, list): + # input type is list when ToolNode is invoked with a list input (e.g. [AIMessage(..., tool_calls=[...])]) + if input_type != "list": + raise ValueError( + f"Tools can provide a list of messages in Command.update only when using list of messages as ToolNode input, " + f"got: {command.update} for tool '{call['name']}'" + ) + + updated_command = deepcopy(command) + messages_update = updated_command.update + else: + return command + + # convert to message objects if updates are in a dict format + messages_update = convert_to_messages(messages_update) + have_seen_tool_messages = False + for message in messages_update: + if not isinstance(message, ToolMessage): + continue + + if have_seen_tool_messages: + raise ValueError( + f"Expected at most one ToolMessage in Command.update for tool '{call['name']}', got multiple: {messages_update}." + ) + + if message.tool_call_id != call["id"]: + raise ValueError( + f"ToolMessage.tool_call_id must match the tool call id. Expected: {call['id']}, got: {message.tool_call_id} for tool '{call['name']}'." + ) + + message.name = call["name"] + have_seen_tool_messages = True + + # validate that we always have exactly one ToolMessage in Command.update if command is sent to the CURRENT graph + if updated_command.graph is None and not have_seen_tool_messages: + example_update = ( + '`Command(update={"messages": [ToolMessage("Success", tool_call_id=tool_call_id), ...]}, ...)`' + if input_type == "dict" + else '`Command(update=[ToolMessage("Success", tool_call_id=tool_call_id), ...], ...)`' + ) + raise ValueError( + f"Expected exactly one message (ToolMessage) in Command.update for tool '{call['name']}', got: {messages_update}. " + "Every tool call (LLM requesting to call a tool) in the message history MUST have a corresponding ToolMessage. " + f"You can fix it by modifying the tool to return {example_update}." + ) + return updated_command + def tools_condition( state: Union[list[AnyMessage], dict[str, Any], BaseModel], diff --git a/libs/langgraph/langgraph/types.py b/libs/langgraph/langgraph/types.py index 1c23ad4de..2086552f9 100644 --- a/libs/langgraph/langgraph/types.py +++ b/libs/langgraph/langgraph/types.py @@ -32,6 +32,14 @@ if TYPE_CHECKING: from langgraph.store.base import BaseStore +try: + from langchain_core.messages.tool import ToolOutputMixin +except ImportError: + + class ToolOutputMixin: # type: ignore[no-redef] + pass + + All = Literal["*"] """Special value to indicate that graph should interrupt on all nodes.""" @@ -244,7 +252,7 @@ N = TypeVar("N", bound=Hashable) @dataclasses.dataclass(**_DC_KWARGS) -class Command(Generic[N]): +class Command(Generic[N], ToolOutputMixin): """One or more commands to update the graph's state and send messages to nodes. Args: diff --git a/libs/langgraph/poetry.lock b/libs/langgraph/poetry.lock index 634b9d8db..bdb2a4da6 100644 --- a/libs/langgraph/poetry.lock +++ b/libs/langgraph/poetry.lock @@ -1325,13 +1325,13 @@ files = [ [[package]] name = "langchain-core" -version = "0.3.15" +version = "0.3.23" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.9" files = [ - {file = "langchain_core-0.3.15-py3-none-any.whl", hash = "sha256:3d4ca6dbb8ed396a6ee061063832a2451b0ce8c345570f7b086ffa7288e4fa29"}, - {file = "langchain_core-0.3.15.tar.gz", hash = "sha256:b1a29787a4ffb7ec2103b4e97d435287201da7809b369740dd1e32f176325aba"}, + {file = "langchain_core-0.3.23-py3-none-any.whl", hash = "sha256:550c0b996990830fa6515a71a1192a8a0343367999afc36d4ede14222941e420"}, + {file = "langchain_core-0.3.23.tar.gz", hash = "sha256:f9e175e3b82063cc3b160c2ca2b155832e1c6f915312e1204828f97d4aabf6e1"}, ] [package.dependencies] @@ -1382,7 +1382,7 @@ url = "../checkpoint-duckdb" [[package]] name = "langgraph-checkpoint-postgres" -version = "2.0.7" +version = "2.0.8" description = "Library with a Postgres implementation of LangGraph checkpoint saver." optional = false python-versions = "^3.9.0,<4.0" @@ -1418,7 +1418,7 @@ url = "../checkpoint-sqlite" [[package]] name = "langgraph-sdk" -version = "0.1.42" +version = "0.1.43" description = "SDK for interacting with LangGraph API" optional = false python-versions = "^3.9.0,<4.0" @@ -3413,4 +3413,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = ">=3.9.0,<4.0" -content-hash = "2df4d5d5e61917bdfff0ba430067a17662666eedee2858d841fa02e594cf69d0" +content-hash = "936530a5f00f329aeff2e6e921fe64480be317fad2c0a59cd54ea9018d089304" diff --git a/libs/langgraph/pyproject.toml b/libs/langgraph/pyproject.toml index 925be91ff..cf29b2375 100644 --- a/libs/langgraph/pyproject.toml +++ b/libs/langgraph/pyproject.toml @@ -9,7 +9,7 @@ repository = "https://www.github.com/langchain-ai/langgraph" [tool.poetry.dependencies] python = ">=3.9.0,<4.0" -langchain-core = ">=0.2.43,<0.4.0,!=0.3.0,!=0.3.1,!=0.3.2,!=0.3.3,!=0.3.4,!=0.3.5,!=0.3.6,!=0.3.7,!=0.3.8,!=0.3.9,!=0.3.10,!=0.3.11,!=0.3.12,!=0.3.13,!=0.3.14" +langchain-core = ">=0.2.43,<0.4.0,!=0.3.0,!=0.3.1,!=0.3.2,!=0.3.3,!=0.3.4,!=0.3.5,!=0.3.6,!=0.3.7,!=0.3.8,!=0.3.9,!=0.3.10,!=0.3.11,!=0.3.12,!=0.3.13,!=0.3.14,!=0.3.15,!=0.3.16,!=0.3.17,!=0.3.18,!=0.3.19,!=0.3.20,!=0.3.21,!=0.3.22" langgraph-checkpoint = "^2.0.4" langgraph-sdk = "^0.1.42" diff --git a/libs/langgraph/tests/test_prebuilt.py b/libs/langgraph/tests/test_prebuilt.py index 0997668b2..9c6541d9a 100644 --- a/libs/langgraph/tests/test_prebuilt.py +++ b/libs/langgraph/tests/test_prebuilt.py @@ -46,7 +46,7 @@ from langgraph.prebuilt import ( create_react_agent, tools_condition, ) -from langgraph.prebuilt.chat_agent_executor import _validate_chat_history +from langgraph.prebuilt.chat_agent_executor import AgentState, _validate_chat_history from langgraph.prebuilt.tool_node import ( TOOL_CALL_ERROR_TEMPLATE, InjectedState, @@ -56,7 +56,7 @@ from langgraph.prebuilt.tool_node import ( ) from langgraph.store.base import BaseStore from langgraph.store.memory import InMemoryStore -from langgraph.types import Interrupt +from langgraph.types import Command, Interrupt, interrupt from tests.conftest import ( ALL_CHECKPOINTERS_ASYNC, ALL_CHECKPOINTERS_SYNC, @@ -988,6 +988,645 @@ def test_tool_node_node_interrupt(): assert task.interrupts == (Interrupt(value="foo", when="during"),) +@pytest.mark.skipif( + not IS_LANGCHAIN_CORE_030_OR_GREATER, + reason="Langchain core 0.3.0 or greater is required", +) +async def test_tool_node_command(): + from langchain_core.tools.base import InjectedToolCallId + + @dec_tool + def transfer_to_bob(tool_call_id: Annotated[str, InjectedToolCallId]): + """Transfer to Bob""" + return Command( + update={ + "messages": [ + ToolMessage(content="Transferred to Bob", tool_call_id=tool_call_id) + ] + }, + goto="bob", + graph=Command.PARENT, + ) + + @dec_tool + async def async_transfer_to_bob(tool_call_id: Annotated[str, InjectedToolCallId]): + """Transfer to Bob""" + return Command( + update={ + "messages": [ + ToolMessage(content="Transferred to Bob", tool_call_id=tool_call_id) + ] + }, + goto="bob", + graph=Command.PARENT, + ) + + class CustomToolSchema(BaseModel): + tool_call_id: Annotated[str, InjectedToolCallId] + + class MyCustomTool(BaseTool): + def _run(*args: Any, **kwargs: Any): + return Command( + update={ + "messages": [ + ToolMessage( + content="Transferred to Bob", + tool_call_id=kwargs["tool_call_id"], + ) + ] + }, + goto="bob", + graph=Command.PARENT, + ) + + async def _arun(*args: Any, **kwargs: Any): + return Command( + update={ + "messages": [ + ToolMessage( + content="Transferred to Bob", + tool_call_id=kwargs["tool_call_id"], + ) + ] + }, + goto="bob", + graph=Command.PARENT, + ) + + custom_tool = MyCustomTool( + name="custom_transfer_to_bob", + description="Transfer to bob", + args_schema=CustomToolSchema, + ) + async_custom_tool = MyCustomTool( + name="async_custom_transfer_to_bob", + description="Transfer to bob", + args_schema=CustomToolSchema, + ) + + # test mixing regular tools and tools returning commands + def add(a: int, b: int) -> int: + """Add two numbers""" + return a + b + + result = ToolNode([add, transfer_to_bob]).invoke( + { + "messages": [ + AIMessage( + "", + tool_calls=[ + {"args": {"a": 1, "b": 2}, "id": "1", "name": "add"}, + {"args": {}, "id": "2", "name": "transfer_to_bob"}, + ], + ) + ] + } + ) + + assert result == [ + { + "messages": [ + ToolMessage( + content="3", + tool_call_id="1", + name="add", + ) + ] + }, + Command( + update={ + "messages": [ + ToolMessage( + content="Transferred to Bob", + tool_call_id="2", + name="transfer_to_bob", + ) + ] + }, + goto="bob", + graph=Command.PARENT, + ), + ] + + # test tools returning commands + + # test sync tools + for tool in [transfer_to_bob, custom_tool]: + result = ToolNode([tool]).invoke( + { + "messages": [ + AIMessage( + "", tool_calls=[{"args": {}, "id": "1", "name": tool.name}] + ) + ] + } + ) + assert result == [ + Command( + update={ + "messages": [ + ToolMessage( + content="Transferred to Bob", + tool_call_id="1", + name=tool.name, + ) + ] + }, + goto="bob", + graph=Command.PARENT, + ) + ] + + # test async tools + for tool in [async_transfer_to_bob, async_custom_tool]: + result = await ToolNode([tool]).ainvoke( + { + "messages": [ + AIMessage( + "", tool_calls=[{"args": {}, "id": "1", "name": tool.name}] + ) + ] + } + ) + assert result == [ + Command( + update={ + "messages": [ + ToolMessage( + content="Transferred to Bob", + tool_call_id="1", + name=tool.name, + ) + ] + }, + goto="bob", + graph=Command.PARENT, + ) + ] + + # test multiple commands + result = ToolNode([transfer_to_bob, custom_tool]).invoke( + { + "messages": [ + AIMessage( + "", + tool_calls=[ + {"args": {}, "id": "1", "name": "transfer_to_bob"}, + {"args": {}, "id": "2", "name": "custom_transfer_to_bob"}, + ], + ) + ] + } + ) + assert result == [ + Command( + update={ + "messages": [ + ToolMessage( + content="Transferred to Bob", + tool_call_id="1", + name="transfer_to_bob", + ) + ] + }, + goto="bob", + graph=Command.PARENT, + ), + Command( + update={ + "messages": [ + ToolMessage( + content="Transferred to Bob", + tool_call_id="2", + name="custom_transfer_to_bob", + ) + ] + }, + goto="bob", + graph=Command.PARENT, + ), + ] + + # test validation (mismatch between input type and command.update type) + with pytest.raises(ValueError): + + @dec_tool + def list_update_tool(tool_call_id: Annotated[str, InjectedToolCallId]): + """My tool""" + return Command( + update=[ToolMessage(content="foo", tool_call_id=tool_call_id)] + ) + + ToolNode([list_update_tool]).invoke( + { + "messages": [ + AIMessage( + "", + tool_calls=[ + {"args": {}, "id": "1", "name": "list_update_tool"} + ], + ) + ] + } + ) + + # test validation (missing tool message in the update for current graph) + with pytest.raises(ValueError): + + @dec_tool + def no_update_tool(): + """My tool""" + return Command(update={"messages": []}) + + ToolNode([no_update_tool]).invoke( + { + "messages": [ + AIMessage( + "", + tool_calls=[{"args": {}, "id": "1", "name": "no_update_tool"}], + ) + ] + } + ) + + # test validation (missing tool message in the update for parent graph is OK) + @dec_tool + def node_update_parent_tool(): + """No update""" + return Command(update={"messages": []}, graph=Command.PARENT) + + assert ToolNode([node_update_parent_tool]).invoke( + { + "messages": [ + AIMessage( + "", + tool_calls=[ + {"args": {}, "id": "1", "name": "node_update_parent_tool"} + ], + ) + ] + } + ) == [Command(update={"messages": []}, graph=Command.PARENT)] + + # test validation (multiple tool messages) + with pytest.raises(ValueError): + for graph in (None, Command.PARENT): + + @dec_tool + def multiple_tool_messages_tool(): + """My tool""" + return Command( + update={ + "messages": [ + ToolMessage(content="foo", tool_call_id=""), + ToolMessage(content="bar", tool_call_id=""), + ] + }, + graph=graph, + ) + + ToolNode([multiple_tool_messages_tool]).invoke( + { + "messages": [ + AIMessage( + "", + tool_calls=[ + { + "args": {}, + "id": "1", + "name": "multiple_tool_messages_tool", + } + ], + ) + ] + } + ) + + +@pytest.mark.skipif( + not IS_LANGCHAIN_CORE_030_OR_GREATER, + reason="Langchain core 0.3.0 or greater is required", +) +async def test_tool_node_command_list_input(): + from langchain_core.tools.base import InjectedToolCallId + + @dec_tool + def transfer_to_bob(tool_call_id: Annotated[str, InjectedToolCallId]): + """Transfer to Bob""" + return Command( + update=[ + ToolMessage(content="Transferred to Bob", tool_call_id=tool_call_id) + ], + goto="bob", + graph=Command.PARENT, + ) + + @dec_tool + async def async_transfer_to_bob(tool_call_id: Annotated[str, InjectedToolCallId]): + """Transfer to Bob""" + return Command( + update=[ + ToolMessage(content="Transferred to Bob", tool_call_id=tool_call_id) + ], + goto="bob", + graph=Command.PARENT, + ) + + class CustomToolSchema(BaseModel): + tool_call_id: Annotated[str, InjectedToolCallId] + + class MyCustomTool(BaseTool): + def _run(*args: Any, **kwargs: Any): + return Command( + update=[ + ToolMessage( + content="Transferred to Bob", + tool_call_id=kwargs["tool_call_id"], + ) + ], + goto="bob", + graph=Command.PARENT, + ) + + async def _arun(*args: Any, **kwargs: Any): + return Command( + update=[ + ToolMessage( + content="Transferred to Bob", + tool_call_id=kwargs["tool_call_id"], + ) + ], + goto="bob", + graph=Command.PARENT, + ) + + custom_tool = MyCustomTool( + name="custom_transfer_to_bob", + description="Transfer to bob", + args_schema=CustomToolSchema, + ) + async_custom_tool = MyCustomTool( + name="async_custom_transfer_to_bob", + description="Transfer to bob", + args_schema=CustomToolSchema, + ) + + # test mixing regular tools and tools returning commands + def add(a: int, b: int) -> int: + """Add two numbers""" + return a + b + + result = ToolNode([add, transfer_to_bob]).invoke( + [ + AIMessage( + "", + tool_calls=[ + {"args": {"a": 1, "b": 2}, "id": "1", "name": "add"}, + {"args": {}, "id": "2", "name": "transfer_to_bob"}, + ], + ) + ] + ) + + assert result == [ + [ + ToolMessage( + content="3", + tool_call_id="1", + name="add", + ) + ], + Command( + update=[ + ToolMessage( + content="Transferred to Bob", + tool_call_id="2", + name="transfer_to_bob", + ) + ], + goto="bob", + graph=Command.PARENT, + ), + ] + + # test tools returning commands + + # test sync tools + for tool in [transfer_to_bob, custom_tool]: + result = ToolNode([tool]).invoke( + [AIMessage("", tool_calls=[{"args": {}, "id": "1", "name": tool.name}])] + ) + assert result == [ + Command( + update=[ + ToolMessage( + content="Transferred to Bob", + tool_call_id="1", + name=tool.name, + ) + ], + goto="bob", + graph=Command.PARENT, + ) + ] + + # test async tools + for tool in [async_transfer_to_bob, async_custom_tool]: + result = await ToolNode([tool]).ainvoke( + [AIMessage("", tool_calls=[{"args": {}, "id": "1", "name": tool.name}])] + ) + assert result == [ + Command( + update=[ + ToolMessage( + content="Transferred to Bob", + tool_call_id="1", + name=tool.name, + ) + ], + goto="bob", + graph=Command.PARENT, + ) + ] + + # test multiple commands + result = ToolNode([transfer_to_bob, custom_tool]).invoke( + [ + AIMessage( + "", + tool_calls=[ + {"args": {}, "id": "1", "name": "transfer_to_bob"}, + {"args": {}, "id": "2", "name": "custom_transfer_to_bob"}, + ], + ) + ] + ) + assert result == [ + Command( + update=[ + ToolMessage( + content="Transferred to Bob", + tool_call_id="1", + name="transfer_to_bob", + ) + ], + goto="bob", + graph=Command.PARENT, + ), + Command( + update=[ + ToolMessage( + content="Transferred to Bob", + tool_call_id="2", + name="custom_transfer_to_bob", + ) + ], + goto="bob", + graph=Command.PARENT, + ), + ] + + # test validation (mismatch between input type and command.update type) + with pytest.raises(ValueError): + + @dec_tool + def list_update_tool(tool_call_id: Annotated[str, InjectedToolCallId]): + """My tool""" + return Command( + update={ + "messages": [ToolMessage(content="foo", tool_call_id=tool_call_id)] + } + ) + + ToolNode([list_update_tool]).invoke( + [ + AIMessage( + "", + tool_calls=[{"args": {}, "id": "1", "name": "list_update_tool"}], + ) + ] + ) + + # test validation (missing tool message in the update for current graph) + with pytest.raises(ValueError): + + @dec_tool + def no_update_tool(): + """My tool""" + return Command(update=[]) + + ToolNode([no_update_tool]).invoke( + [ + AIMessage( + "", + tool_calls=[{"args": {}, "id": "1", "name": "no_update_tool"}], + ) + ] + ) + + # test validation (missing tool message in the update for parent graph is OK) + @dec_tool + def node_update_parent_tool(): + """No update""" + return Command(update=[], graph=Command.PARENT) + + assert ToolNode([node_update_parent_tool]).invoke( + [ + AIMessage( + "", + tool_calls=[{"args": {}, "id": "1", "name": "node_update_parent_tool"}], + ) + ] + ) == [Command(update=[], graph=Command.PARENT)] + + # test validation (multiple tool messages) + with pytest.raises(ValueError): + for graph in (None, Command.PARENT): + + @dec_tool + def multiple_tool_messages_tool(): + """My tool""" + return Command( + update=[ + ToolMessage(content="foo", tool_call_id=""), + ToolMessage(content="bar", tool_call_id=""), + ], + graph=graph, + ) + + ToolNode([multiple_tool_messages_tool]).invoke( + [ + AIMessage( + "", + tool_calls=[ + { + "args": {}, + "id": "1", + "name": "multiple_tool_messages_tool", + } + ], + ) + ] + ) + + +@pytest.mark.skipif( + not IS_LANGCHAIN_CORE_030_OR_GREATER, + reason="Langchain core 0.3.0 or greater is required", +) +def test_react_agent_update_state(): + from langchain_core.tools.base import InjectedToolCallId + + class State(AgentState): + user_name: str + + @dec_tool + def get_user_name(tool_call_id: Annotated[str, InjectedToolCallId]): + """Retrieve user name""" + user_name = interrupt("Please provider user name:") + return Command( + update={ + "user_name": user_name, + "messages": [ + ToolMessage( + "Successfully retrieved user name", tool_call_id=tool_call_id + ) + ], + } + ) + + def state_modifier(state: State): + user_name = state.get("user_name") + if user_name is None: + return state["messages"] + + system_msg = f"User name is {user_name}" + return [{"role": "system", "content": system_msg}] + state["messages"] + + checkpointer = MemorySaver() + tool_calls = [[{"args": {}, "id": "1", "name": "get_user_name"}]] + model = FakeToolCallingModel(tool_calls=tool_calls) + agent = create_react_agent( + model, + [get_user_name], + state_schema=State, + state_modifier=state_modifier, + checkpointer=checkpointer, + ) + config = {"configurable": {"thread_id": "1"}} + # run until interrpupted + agent.invoke({"messages": [("user", "what's my name")]}, config) + # supply the value for the interrupt + response = agent.invoke(Command(resume="Archibald"), config) + # confirm that the state was updated + assert response["user_name"] == "Archibald" + assert len(response["messages"]) == 4 + tool_message: ToolMessage = response["messages"][-2] + assert tool_message.content == "Successfully retrieved user name" + assert tool_message.tool_call_id == "1" + assert tool_message.name == "get_user_name" + + def my_function(some_val: int, some_other_val: str) -> str: return f"{some_val} - {some_other_val}" From a9f5507006ebdbe7e9fe5926a7e9ffba70b0787e Mon Sep 17 00:00:00 2001 From: Vadym Barda Date: Tue, 10 Dec 2024 10:19:59 -0500 Subject: [PATCH 55/58] langgraph: release 0.2.58 (#2692) --- libs/langgraph/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/langgraph/pyproject.toml b/libs/langgraph/pyproject.toml index cf29b2375..a5fa31c74 100644 --- a/libs/langgraph/pyproject.toml +++ b/libs/langgraph/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langgraph" -version = "0.2.57" +version = "0.2.58" description = "Building stateful, multi-actor applications with LLMs" authors = [] license = "MIT" From 1c3f65c931af0d0a183edf1d49aa6f84fbcfd5e2 Mon Sep 17 00:00:00 2001 From: Vadym Barda Date: Tue, 10 Dec 2024 10:22:17 -0500 Subject: [PATCH 56/58] docs: add tool use for Command concepts (#2669) To be merged after #2656 --- docs/docs/concepts/low_level.md | 24 ++++++++++++++++++++++++ docs/docs/how-tos/command.ipynb | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/docs/docs/concepts/low_level.md b/docs/docs/concepts/low_level.md index 297f97ec9..a3ab96bf1 100644 --- a/docs/docs/concepts/low_level.md +++ b/docs/docs/concepts/low_level.md @@ -353,6 +353,30 @@ def my_node(state: State) -> Command[Literal["my_other_node"]]: Check out this [how-to guide](../how-tos/command.ipynb) for an end-to-end example of how to use `Command`. +### Using inside tools + +A common use case is updating graph state from inside a tool. For example, in a customer support application you might want to look up customer information based on their account number or ID in the beginning of the conversation. To update the graph state from the tool, you can return `Command(update={"my_custom_key": "foo", "messages": [...]})` from the tool: + +```python +@tool +def lookup_user_info(tool_call_id: Annotated[str, InjectedToolCallId], config: RunnableConfig): + """Use this to look up user information to better assist them with their questions.""" + user_info = get_user_info(config.get("configurable", {}).get("user_id")) + return Command( + update={ + # update the state keys + "user_info": user_info, + # update the message history + "messages": [ToolMessage("Successfully looked up user information", tool_call_id=tool_call_id)] + } + ) +``` + +!!! important + You MUST include `messages` (or any state key used for the message history) in `Command.update` when returning `Command` from a tool and the list of messages in `messages` MUST contain a `ToolMessage`. This is necessary for the resulting message history to be valid (LLM providers require AI messages with tool calls to be followed by the tool result messages). + +If you are using tools that update state via `Command`, we recommend using prebuilt [`ToolNode`][langgraph.prebuilt.tool_node.ToolNode] which automatically handles tools returning `Command` objects and propagates them to the graph state. If you're writing a custom node that calls tools, you would need to manually propagate `Command` objects returned by the tools as the update from node. + ## Persistence LangGraph provides built-in persistence for your agent's state using [checkpointers][langgraph.checkpoint.base.BaseCheckpointSaver]. Checkpointers save snapshots of the graph state at every superstep, allowing resumption at any time. This enables features like human-in-the-loop interactions, memory management, and fault-tolerance. You can even directly manipulate a graph's state after its execution using the diff --git a/docs/docs/how-tos/command.ipynb b/docs/docs/how-tos/command.ipynb index b0ab12188..acc9ff2b4 100644 --- a/docs/docs/how-tos/command.ipynb +++ b/docs/docs/how-tos/command.ipynb @@ -171,7 +171,7 @@ "source": [ "!!! important\n", "\n", - " You might have noticed that we used `Command` as a return type annotation, e.g. `Command[Literal[\"node_b\", \"node_c\"]]`. This is necessary for the graph compilation and rendering, and tells LangGraph that `node_a` can navigate to `node_b` and `node_c`." + " You might have noticed that we used `Command` as a return type annotation, e.g. `Command[Literal[\"node_b\", \"node_c\"]]`. This is necessary for the graph rendering and tells LangGraph that `node_a` can navigate to `node_b` and `node_c`." ] }, { From fdfc5d9cdafef65793e3e3f3a81a30d4cd3a3ffd Mon Sep 17 00:00:00 2001 From: vbarda Date: Tue, 10 Dec 2024 10:35:01 -0500 Subject: [PATCH 57/58] Revert "langgraph: release 0.2.58 (#2692)" This reverts commit a9f5507006ebdbe7e9fe5926a7e9ffba70b0787e. --- libs/langgraph/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/langgraph/pyproject.toml b/libs/langgraph/pyproject.toml index a5fa31c74..cf29b2375 100644 --- a/libs/langgraph/pyproject.toml +++ b/libs/langgraph/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langgraph" -version = "0.2.58" +version = "0.2.57" description = "Building stateful, multi-actor applications with LLMs" authors = [] license = "MIT" From 97a51014c3a4eac7fe7580187a456d4f2f7ad9ec Mon Sep 17 00:00:00 2001 From: Vadym Barda Date: Tue, 10 Dec 2024 11:20:50 -0500 Subject: [PATCH 58/58] docs: add a how-to on updating state from tools (#2670) --- docs/docs/how-tos/index.md | 1 + .../how-tos/update-state-from-tools.ipynb | 383 ++++++++++++++++++ docs/mkdocs.yml | 1 + poetry.lock | 23 +- 4 files changed, 394 insertions(+), 14 deletions(-) create mode 100644 docs/docs/how-tos/update-state-from-tools.ipynb diff --git a/docs/docs/how-tos/index.md b/docs/docs/how-tos/index.md index b26656117..d93488d94 100644 --- a/docs/docs/how-tos/index.md +++ b/docs/docs/how-tos/index.md @@ -81,6 +81,7 @@ These how-to guides show common patterns for tool calling with LangGraph: - [How to handle tool calling errors](tool-calling-errors.ipynb) - [How to pass runtime values to tools](pass-run-time-values-to-tools.ipynb) - [How to pass config to tools](pass-config-to-tools.ipynb) +- [How to update graph state from tools](update-state-from-tools.ipynb) - [How to handle large numbers of tools](many-tools.ipynb) ### Subgraphs diff --git a/docs/docs/how-tos/update-state-from-tools.ipynb b/docs/docs/how-tos/update-state-from-tools.ipynb new file mode 100644 index 000000000..41147688e --- /dev/null +++ b/docs/docs/how-tos/update-state-from-tools.ipynb @@ -0,0 +1,383 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7c58c957-83d8-44ff-8580-a9b3dd39a0a9", + "metadata": {}, + "source": [ + "# How to update graph state from tools" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "95f30587-8dd2-40be-920d-59539089c09f", + "metadata": {}, + "source": [ + "!!! info \"Prerequisites\"\n", + " This guide assumes familiarity with the following:\n", + " \n", + " - [Command](../../concepts/low_level/#command)\n", + "\n", + "A common use case is updating graph state from inside a tool. For example, in a customer support application you might want to look up customer account number or ID in the beginning of the conversation. To update the graph state from the tool, you can return `Command(update={\"my_custom_key\": \"foo\", \"messages\": [...]})` from the tool:\n", + "\n", + "```python\n", + "@tool\n", + "def lookup_user_info(tool_call_id: Annotated[str, InjectedToolCallId], config: RunnableConfig):\n", + " \"\"\"Use this to look up user information to better assist them with their questions.\"\"\"\n", + " user_info = get_user_info(config)\n", + " return Command(\n", + " update={\n", + " # update the state keys\n", + " \"user_info\": user_info,\n", + " # update the message history\n", + " \"messages\": [ToolMessage(\"Successfully looked up user information\", tool_call_id=\"\")]\n", + " }\n", + " )\n", + "```\n", + "\n", + "!!! important\n", + "\n", + " If you want to use tools that return `Command` and update graph state, you can either use prebuilt [`create_react_agent`][langgraph.prebuilt.chat_agent_executor.create_react_agent] / [`ToolNode`][langgraph.prebuilt.tool_node.ToolNode] components, or implement your own tool-executing node that collects `Command` objects returned by the tools and returns a list of them, e.g.:\n", + " \n", + " ```python\n", + " def call_tools(state):\n", + " ...\n", + " commands = [tools_by_name[call[\"name\"].invoke(call, config={\"coerce_tool_content\": False}) for tool_call in tool_calls]\n", + " return commands\n", + " ```\n", + "\n", + "This guide shows how you can do this using LangGraph's prebuilt components ([`create_react_agent`][langgraph.prebuilt.chat_agent_executor.create_react_agent] / [`ToolNode`][langgraph.prebuilt.tool_node.ToolNode]).\n", + "\n", + "!!! note\n", + "\n", + " Support for tools that return [`Command`][langgraph.types.Command] was added in LangGraph `v0.2.57`.\n", + "\n", + "## Setup\n", + "\n", + "First, let's install the required packages and set our API keys:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "64500eca-1cdc-43d9-9401-f4cd9999881f", + "metadata": {}, + "outputs": [], + "source": [ + "%%capture --no-stderr\n", + "%pip install -U langgraph langchain-openai" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "a3f92fb2-9175-47fa-9c7d-ad5f44bfd20e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Please provide your OPENAI_API_KEY ········\n" + ] + } + ], + "source": [ + "import os\n", + "import getpass\n", + "\n", + "\n", + "def _set_if_undefined(var: str):\n", + " if not os.environ.get(var):\n", + " os.environ[var] = getpass.getpass(f\"Please provide your {var}\")\n", + "\n", + "\n", + "_set_if_undefined(\"OPENAI_API_KEY\")" + ] + }, + { + "cell_type": "markdown", + "id": "caf6ff9f-c1e6-499e-a230-9fa231ea7d2f", + "metadata": {}, + "source": [ + "
\n", + "

Set up LangSmith for LangGraph development

\n", + "

\n", + " Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. LangSmith lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph — read more about how to get started here. \n", + "

\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "10e9a9c6-fa3f-416c-bac0-3e58d7259908", + "metadata": {}, + "source": [ + "Let's create a simple ReAct style agent that can look up user information and personalize the response based on the user info." + ] + }, + { + "cell_type": "markdown", + "id": "4255b9b9-cf67-4cc3-8018-1708f5dfcfd2", + "metadata": {}, + "source": [ + "## Define tool" + ] + }, + { + "cell_type": "markdown", + "id": "7de6b010-aab1-4fe8-8251-907fcae78583", + "metadata": {}, + "source": [ + "First, let's define the tool that we'll be using to look up user information. We'll use a naive implementation that simply looks user information up using a dictionary:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8d070c9f-6e61-4724-85dc-ac4531b9c79a", + "metadata": {}, + "outputs": [], + "source": [ + "USER_INFO = [\n", + " {\"user_id\": \"1\", \"name\": \"Bob Dylan\", \"location\": \"New York, NY\"},\n", + " {\"user_id\": \"2\", \"name\": \"Taylor Swift\", \"location\": \"Beverly Hills, CA\"},\n", + "]\n", + "\n", + "USER_ID_TO_USER_INFO = {info[\"user_id\"]: info for info in USER_INFO}" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "08d1ecca-ee57-4e97-b8d0-e09de85337d4", + "metadata": {}, + "outputs": [], + "source": [ + "from langgraph.prebuilt.chat_agent_executor import AgentState\n", + "from langgraph.types import Command\n", + "from langchain_core.tools import tool\n", + "from langchain_core.tools.base import InjectedToolCallId\n", + "from langchain_core.messages import ToolMessage\n", + "from langchain_core.runnables import RunnableConfig\n", + "\n", + "from typing_extensions import Any, Annotated\n", + "\n", + "\n", + "class State(AgentState):\n", + " # user provided\n", + " last_name: str\n", + " # updated by the tool\n", + " user_info: dict[str, Any]\n", + "\n", + "\n", + "@tool\n", + "def lookup_user_info(\n", + " tool_call_id: Annotated[str, InjectedToolCallId], config: RunnableConfig\n", + "):\n", + " \"\"\"Use this to look up user information to better assist them with their questions.\"\"\"\n", + " user_id = config.get(\"configurable\", {}).get(\"user_id\")\n", + " if user_id is None:\n", + " raise ValueError(\"Please provide user ID\")\n", + "\n", + " if user_id not in USER_ID_TO_USER_INFO:\n", + " raise ValueError(f\"User '{user_id}' not found\")\n", + "\n", + " user_info = USER_ID_TO_USER_INFO[user_id]\n", + " return Command(\n", + " update={\n", + " # update the state keys\n", + " \"user_info\": user_info,\n", + " # update the message history\n", + " \"messages\": [\n", + " ToolMessage(\n", + " \"Successfully looked up user information\", tool_call_id=tool_call_id\n", + " )\n", + " ],\n", + " }\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "b99e5f24-5e5e-4a34-baae-467182675bb5", + "metadata": {}, + "source": [ + "## Define prompt" + ] + }, + { + "cell_type": "markdown", + "id": "cbb06aea-6654-4245-91f8-af6e8f2b5377", + "metadata": {}, + "source": [ + "Let's now add personalization: we'll respond differently to the user based on the state values AFTER the state has been updated from the tool. To achieve this, let's define a function that will dynamically construct the system prompt based on the graph state. It will be called ever time the LLM is called and the function output will be passed to the LLM:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "c553d062-d145-4145-84bd-9b798f7c95c2", + "metadata": {}, + "outputs": [], + "source": [ + "def state_modifier(state: State):\n", + " user_info = state.get(\"user_info\")\n", + " if user_info is None:\n", + " return state[\"messages\"]\n", + "\n", + " system_msg = (\n", + " f\"User name is {user_info['name']}. User lives in {user_info['location']}\"\n", + " )\n", + " return [{\"role\": \"system\", \"content\": system_msg}] + state[\"messages\"]" + ] + }, + { + "cell_type": "markdown", + "id": "c5acdd5d-68be-466b-9c21-46cbed91d2bc", + "metadata": {}, + "source": [ + "## Define graph" + ] + }, + { + "cell_type": "markdown", + "id": "afb65028-0359-46c8-b09c-ffc90180f759", + "metadata": {}, + "source": [ + "Finally, let's combine this into a single graph using the prebuilt `create_react_agent`:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "2d59db29-fd51-4d29-9854-21763a4855e3", + "metadata": {}, + "outputs": [], + "source": [ + "from langgraph.prebuilt import create_react_agent\n", + "from langchain_openai import ChatOpenAI\n", + "\n", + "model = ChatOpenAI(model=\"gpt-4o\")\n", + "\n", + "agent = create_react_agent(\n", + " model,\n", + " # pass the tool that can update state\n", + " [lookup_user_info],\n", + " state_schema=State,\n", + " # pass dynamic prompt function\n", + " state_modifier=state_modifier,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "0782b8ab-a603-47b8-9a76-77f593402678", + "metadata": {}, + "source": [ + "## Use it!" + ] + }, + { + "cell_type": "markdown", + "id": "6165e153-ab28-4404-adea-796c7bd0701b", + "metadata": {}, + "source": [ + "Let's now try running our agent. We'll need to provide user ID in the config so that our tool knows what information to look up:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "de34a58b-1765-4b63-a232-d46790aff884", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'agent': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_7LSUh6ZDvGJAUvlWvXiCK4Gf', 'function': {'arguments': '{}', 'name': 'lookup_user_info'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 11, 'prompt_tokens': 56, 'total_tokens': 67, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_9d50cd990b', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-57eeb216-e35d-4501-aaac-b5c6b26fb17c-0', tool_calls=[{'name': 'lookup_user_info', 'args': {}, 'id': 'call_7LSUh6ZDvGJAUvlWvXiCK4Gf', 'type': 'tool_call'}], usage_metadata={'input_tokens': 56, 'output_tokens': 11, 'total_tokens': 67, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]}}\n", + "\n", + "\n", + "{'tools': {'user_info': {'user_id': '1', 'name': 'Bob Dylan', 'location': 'New York, NY'}, 'messages': [ToolMessage(content='Successfully looked up user information', name='lookup_user_info', id='168d8ff8-b021-4c8b-a11a-3b50c30a072c', tool_call_id='call_7LSUh6ZDvGJAUvlWvXiCK4Gf')]}}\n", + "\n", + "\n", + "{'agent': {'messages': [AIMessage(content=\"Hi Bob! Since you're in New York, NY, there are plenty of exciting things to do over the weekend. Here are some suggestions:\\n\\n1. **Explore Central Park**: Take a leisurely walk, rent a bike, or have a picnic in this iconic park.\\n\\n2. **Visit a Museum**: Check out The Metropolitan Museum of Art or the Museum of Modern Art (MoMA) for an enriching cultural experience.\\n\\n3. **Broadway Show**: Catch a Broadway show or an off-Broadway performance for some world-class entertainment.\\n\\n4. **Food Tour**: Explore different neighborhoods like Greenwich Village or Williamsburg for diverse culinary experiences.\\n\\n5. **Brooklyn Bridge Walk**: Take a walk across the Brooklyn Bridge for stunning views of the city skyline.\\n\\n6. **Visit a Rooftop Bar**: Enjoy a drink with a view at one of New York’s many rooftop bars.\\n\\n7. **Explore a New Neighborhood**: Discover the unique charm of areas like SoHo, Chelsea, or Astoria.\\n\\n8. **Live Music**: Check out live music venues for a night of great performances.\\n\\n9. **Art Galleries**: Visit some of the smaller art galleries around Chelsea or the Lower East Side.\\n\\n10. **Attend a Local Event**: Look up any local events or festivals happening this weekend.\\n\\nFeel free to let me know if you want more details on any of these activities!\", additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 285, 'prompt_tokens': 95, 'total_tokens': 380, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_9d50cd990b', 'finish_reason': 'stop', 'logprobs': None}, id='run-f13ce15b-02b6-40e6-8264-c4d9edd0d03a-0', usage_metadata={'input_tokens': 95, 'output_tokens': 285, 'total_tokens': 380, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]}}\n", + "\n", + "\n" + ] + } + ], + "source": [ + "for chunk in agent.stream(\n", + " {\"messages\": [(\"user\", \"hi, what should i do this weekend?\")]},\n", + " # provide user ID in the config\n", + " {\"configurable\": {\"user_id\": \"1\"}},\n", + "):\n", + " print(chunk)\n", + " print(\"\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "d9b2281f-269c-41dd-b6b2-4c743f11ffc9", + "metadata": {}, + "source": [ + "We can see that the model correctly recommended some New York activities for Bob Dylan! Let's try getting recommendations for Taylor Swift:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "9d71af94-572a-4961-88a7-665e792cf96a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'agent': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_5HLtJtzcgmKbtmK6By21wW5Y', 'function': {'arguments': '{}', 'name': 'lookup_user_info'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 11, 'prompt_tokens': 56, 'total_tokens': 67, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_c7ca0ebaca', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-bacacd7d-76cc-4f6b-9e9b-d9e6f00b9391-0', tool_calls=[{'name': 'lookup_user_info', 'args': {}, 'id': 'call_5HLtJtzcgmKbtmK6By21wW5Y', 'type': 'tool_call'}], usage_metadata={'input_tokens': 56, 'output_tokens': 11, 'total_tokens': 67, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]}}\n", + "\n", + "\n", + "{'tools': {'user_info': {'user_id': '2', 'name': 'Taylor Swift', 'location': 'Beverly Hills, CA'}, 'messages': [ToolMessage(content='Successfully looked up user information', name='lookup_user_info', id='d81ef31e-6d77-4f13-ae86-e2e6ba567e3d', tool_call_id='call_5HLtJtzcgmKbtmK6By21wW5Y')]}}\n", + "\n", + "\n", + "{'agent': {'messages': [AIMessage(content=\"Hi Taylor! Since you're in Beverly Hills, here are a few suggestions for a fun weekend:\\n\\n1. **Hiking at Runyon Canyon**: Enjoy a scenic hike with beautiful views of Los Angeles. It's a great way to get some exercise and enjoy the outdoors.\\n\\n2. **Visit Rodeo Drive**: Spend some time shopping or window shopping at the famous Rodeo Drive. You might even spot some celebrities!\\n\\n3. **Explore the Getty Center**: Check out the art collections and beautiful gardens at the Getty Center. The architecture and views are stunning.\\n\\n4. **Relax at a Spa**: Treat yourself to a relaxing day at one of Beverly Hills' luxurious spas.\\n\\n5. **Dining Out**: Try a new restaurant or visit your favorite spot for a delicious meal. Beverly Hills has a fantastic dining scene.\\n\\n6. **Attend a Local Event**: Check out any local events or concerts happening this weekend. Beverly Hills often hosts exciting events.\\n\\nEnjoy your weekend!\", additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 198, 'prompt_tokens': 95, 'total_tokens': 293, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_c7ca0ebaca', 'finish_reason': 'stop', 'logprobs': None}, id='run-2057df76-f192-4c69-a66a-1f0a86bf5d66-0', usage_metadata={'input_tokens': 95, 'output_tokens': 198, 'total_tokens': 293, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]}}\n", + "\n", + "\n" + ] + } + ], + "source": [ + "for chunk in agent.stream(\n", + " {\"messages\": [(\"user\", \"hi, what should i do this weekend?\")]},\n", + " {\"configurable\": {\"user_id\": \"2\"}},\n", + "):\n", + " print(chunk)\n", + " print(\"\\n\")" + ] + } + ], + "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.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index d83eec8cf..da7eaf3e3 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -192,6 +192,7 @@ nav: - how-tos/tool-calling.ipynb - how-tos/tool-calling-errors.ipynb - how-tos/pass-run-time-values-to-tools.ipynb + - how-tos/update-state-from-tools.ipynb - how-tos/pass-config-to-tools.ipynb - how-tos/many-tools.ipynb - Subgraphs: diff --git a/poetry.lock b/poetry.lock index e0a15a09c..e2317d365 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2933,13 +2933,13 @@ tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<9.0.0" [[package]] name = "langchain-core" -version = "0.3.21" +version = "0.3.23" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.9" files = [ - {file = "langchain_core-0.3.21-py3-none-any.whl", hash = "sha256:7e723dff80946a1198976c6876fea8326dc82566ef9bcb5f8d9188f738733665"}, - {file = "langchain_core-0.3.21.tar.gz", hash = "sha256:561b52b258ffa50a9fb11d7a1940ebfd915654d1ec95b35e81dfd5ee84143411"}, + {file = "langchain_core-0.3.23-py3-none-any.whl", hash = "sha256:550c0b996990830fa6515a71a1192a8a0343367999afc36d4ede14222941e420"}, + {file = "langchain_core-0.3.23.tar.gz", hash = "sha256:f9e175e3b82063cc3b160c2ca2b155832e1c6f915312e1204828f97d4aabf6e1"}, ] [package.dependencies] @@ -3035,7 +3035,7 @@ langchain-core = ">=0.3.0,<0.4.0" [[package]] name = "langgraph" -version = "0.2.54" +version = "0.2.57" description = "Building stateful, multi-actor applications with LLMs" optional = false python-versions = ">=3.9.0,<4.0" @@ -3043,7 +3043,7 @@ files = [] develop = true [package.dependencies] -langchain-core = ">=0.2.43,<0.4.0,!=0.3.0,!=0.3.1,!=0.3.2,!=0.3.3,!=0.3.4,!=0.3.5,!=0.3.6,!=0.3.7,!=0.3.8,!=0.3.9,!=0.3.10,!=0.3.11,!=0.3.12,!=0.3.13,!=0.3.14" +langchain-core = ">=0.2.43,<0.4.0,!=0.3.0,!=0.3.1,!=0.3.2,!=0.3.3,!=0.3.4,!=0.3.5,!=0.3.6,!=0.3.7,!=0.3.8,!=0.3.9,!=0.3.10,!=0.3.11,!=0.3.12,!=0.3.13,!=0.3.14,!=0.3.15,!=0.3.16,!=0.3.17,!=0.3.18,!=0.3.19,!=0.3.20,!=0.3.21,!=0.3.22" langgraph-checkpoint = "^2.0.4" langgraph-sdk = "^0.1.42" @@ -3070,7 +3070,7 @@ url = "libs/checkpoint" [[package]] name = "langgraph-checkpoint-postgres" -version = "2.0.7" +version = "2.0.8" description = "Library with a Postgres implementation of LangGraph checkpoint saver." optional = false python-versions = "^3.9.0,<4.0" @@ -3106,7 +3106,7 @@ url = "libs/checkpoint-sqlite" [[package]] name = "langgraph-sdk" -version = "0.1.42" +version = "0.1.43" description = "SDK for interacting with LangGraph API" optional = false python-versions = "^3.9.0,<4.0" @@ -3585,6 +3585,7 @@ optional = false python-versions = ">=3.6" files = [ {file = "mkdocs-redirects-1.2.1.tar.gz", hash = "sha256:9420066d70e2a6bb357adf86e67023dcdca1857f97f07c7fe450f8f1fb42f861"}, + {file = "mkdocs_redirects-1.2.1-py3-none-any.whl", hash = "sha256:497089f9e0219e7389304cffefccdfa1cac5ff9509f2cb706f4c9b221726dffb"}, ] [package.dependencies] @@ -5096,7 +5097,6 @@ description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs optional = false python-versions = ">=3.8" files = [ - {file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"}, {file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"}, ] @@ -5107,7 +5107,6 @@ description = "A collection of ASN.1-based protocols modules" optional = false python-versions = ">=3.8" files = [ - {file = "pyasn1_modules-0.4.1-py3-none-any.whl", hash = "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd"}, {file = "pyasn1_modules-0.4.1.tar.gz", hash = "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c"}, ] @@ -6167,11 +6166,6 @@ files = [ {file = "scikit_learn-1.5.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f60021ec1574e56632be2a36b946f8143bf4e5e6af4a06d85281adc22938e0dd"}, {file = "scikit_learn-1.5.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:394397841449853c2290a32050382edaec3da89e35b3e03d6cc966aebc6a8ae6"}, {file = "scikit_learn-1.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:57cc1786cfd6bd118220a92ede80270132aa353647684efa385a74244a41e3b1"}, - {file = "scikit_learn-1.5.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9a702e2de732bbb20d3bad29ebd77fc05a6b427dc49964300340e4c9328b3f5"}, - {file = "scikit_learn-1.5.2-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:b0768ad641981f5d3a198430a1d31c3e044ed2e8a6f22166b4d546a5116d7908"}, - {file = "scikit_learn-1.5.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:178ddd0a5cb0044464fc1bfc4cca5b1833bfc7bb022d70b05db8530da4bb3dd3"}, - {file = "scikit_learn-1.5.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7284ade780084d94505632241bf78c44ab3b6f1e8ccab3d2af58e0e950f9c12"}, - {file = "scikit_learn-1.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:b7b0f9a0b1040830d38c39b91b3a44e1b643f4b36e36567b80b7c6bd2202a27f"}, {file = "scikit_learn-1.5.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:757c7d514ddb00ae249832fe87100d9c73c6ea91423802872d9e74970a0e40b9"}, {file = "scikit_learn-1.5.2-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:52788f48b5d8bca5c0736c175fa6bdaab2ef00a8f536cda698db61bd89c551c1"}, {file = "scikit_learn-1.5.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:643964678f4b5fbdc95cbf8aec638acc7aa70f5f79ee2cdad1eec3df4ba6ead8"}, @@ -6962,6 +6956,7 @@ description = "Automatically mock your HTTP interactions to simplify and speed u optional = false python-versions = ">=3.8" files = [ + {file = "vcrpy-6.0.1-py2.py3-none-any.whl", hash = "sha256:621c3fb2d6bd8aa9f87532c688e4575bcbbde0c0afeb5ebdb7e14cac409edfdd"}, {file = "vcrpy-6.0.1.tar.gz", hash = "sha256:9e023fee7f892baa0bbda2f7da7c8ac51165c1c6e38ff8688683a12a4bde9278"}, ]