diff --git a/libs/langgraph/langgraph/graph/graph.py b/libs/langgraph/langgraph/graph/graph.py index 5e2739f023..dce0be20c8 100644 --- a/libs/langgraph/langgraph/graph/graph.py +++ b/libs/langgraph/langgraph/graph/graph.py @@ -257,7 +257,7 @@ def add_conditional_edges( selected by `path`. Returns: - None + Self: The instance of the graph, allowing for method chaining. Note: Without typehints on the `path` function's return value (e.g., `-> Literal["foo", "__end__"]:`) or a path_map, the graph visualization assumes the edge could transition to any node in the graph. @@ -308,7 +308,7 @@ def set_entry_point(self, key: str) -> Self: key (str): The key of the node to set as the entry point. Returns: - None + Self: The instance of the graph, allowing for method chaining. """ return self.add_edge(START, key) @@ -334,7 +334,7 @@ def set_conditional_entry_point( selected by `path`. Returns: - None + Self: The instance of the graph, allowing for method chaining. """ return self.add_conditional_edges(START, path, path_map, then) @@ -347,7 +347,7 @@ def set_finish_point(self, key: str) -> Self: key (str): The key of the node to set as the finish point. Returns: - None + Self: The instance of the graph, allowing for method chaining. """ return self.add_edge(key, END) diff --git a/libs/langgraph/langgraph/graph/state.py b/libs/langgraph/langgraph/graph/state.py index 7b950556be..3fbb312299 100644 --- a/libs/langgraph/langgraph/graph/state.py +++ b/libs/langgraph/langgraph/graph/state.py @@ -107,7 +107,6 @@ class StateGraph(Graph): config_schema (Optional[Type[Any]]): The schema class that defines the configuration. Use this to expose configurable parameters in your API. - Examples: >>> from langchain_core.runnables import RunnableConfig >>> from typing_extensions import Annotated, TypedDict @@ -243,7 +242,7 @@ def add_node( ValueError: If the key is already being used as a state key. Returns: - StateGraph + Self: The instance of the state graph, allowing for method chaining. """ ... @@ -267,7 +266,7 @@ def add_node( ValueError: If the key is already being used as a state key. Returns: - StateGraph + Self: The instance of the state graph, allowing for method chaining. """ ... @@ -290,10 +289,10 @@ def add_node( metadata (Optional[dict[str, Any]]): The metadata associated with the node. (default: None) input (Optional[Type[Any]]): The input schema for the node. (default: the graph's input schema) retry (Optional[RetryPolicy]): The policy for retrying the node. (default: None) + Raises: ValueError: If the key is already being used as a state key. - Examples: ```pycon >>> from langgraph.graph import START, StateGraph @@ -320,7 +319,7 @@ def add_node( ``` Returns: - StateGraph + Self: The instance of the state graph, allowing for method chaining. """ if not isinstance(node, str): action = node @@ -416,7 +415,7 @@ def add_edge(self, start_key: Union[str, list[str]], end_key: str) -> Self: ValueError: If the start key is 'END' or if the start key or end key is not present in the graph. Returns: - StateGraph + Self: The instance of the state graph, allowing for method chaining. """ if isinstance(start_key, str): return super().add_edge(start_key, end_key) @@ -455,7 +454,7 @@ def add_sequence( ValueError: if the sequence contains duplicate node names. Returns: - StateGraph + Self: The instance of the state graph, allowing for method chaining. """ if len(nodes) < 1: raise ValueError("Sequence requires at least one node.") diff --git a/libs/langgraph/langgraph/pregel/__init__.py b/libs/langgraph/langgraph/pregel/__init__.py index 36c2517820..981e1e5192 100644 --- a/libs/langgraph/langgraph/pregel/__init__.py +++ b/libs/langgraph/langgraph/pregel/__init__.py @@ -1652,10 +1652,10 @@ def get_waiter() -> concurrent.futures.Future[None]: else: get_waiter = None # type: ignore[assignment] # Similarly to Bulk Synchronous Parallel / Pregel model - # computation proceeds in steps, while there are channel updates - # channel updates from step N are only visible in step N+1 + # computation proceeds in steps, while there are channel updates. + # Channel updates from step N are only visible in step N+1 # channels are guaranteed to be immutable for the duration of the step, - # with channel updates applied only at the transition between steps + # with channel updates applied only at the transition between steps. while loop.tick(input_keys=self.input_channels): for _ in runner.tick( loop.tasks.values(), diff --git a/libs/langgraph/langgraph/pregel/call.py b/libs/langgraph/langgraph/pregel/call.py index a9986102d9..d6b6e6d828 100644 --- a/libs/langgraph/langgraph/pregel/call.py +++ b/libs/langgraph/langgraph/pregel/call.py @@ -1,3 +1,5 @@ +"""Utility to convert a user provided function into a Runnable with a ChannelWrite.""" + import sys import types from typing import Any, Callable, Optional @@ -6,10 +8,9 @@ from langgraph.pregel.write import ChannelWrite, ChannelWriteEntry from langgraph.utils.runnable import RunnableSeq, coerce_to_runnable -""" -Utilities borrowed from cloudpickle. -https://github.com/cloudpipe/cloudpickle/blob/6220b0ce83ffee5e47e06770a1ee38ca9e47c850/cloudpickle/cloudpickle.py#L265 -""" +## +# Utilities borrowed from cloudpickle. +# https://github.com/cloudpipe/cloudpickle/blob/6220b0ce83ffee5e47e06770a1ee38ca9e47c850/cloudpickle/cloudpickle.py#L265 def _getattribute(obj: Any, name: str) -> Any: diff --git a/libs/langgraph/langgraph/pregel/executor.py b/libs/langgraph/langgraph/pregel/executor.py index 46a4e6036f..8ba4debdcc 100644 --- a/libs/langgraph/langgraph/pregel/executor.py +++ b/libs/langgraph/langgraph/pregel/executor.py @@ -51,6 +51,7 @@ class BackgroundExecutor(ContextManager): def __init__(self, config: RunnableConfig) -> None: self.stack = ExitStack() self.executor = self.stack.enter_context(get_executor_for_config(config)) + # mapping of Future to (__cancel_on_exit__, __reraise_on_exit__) flags self.tasks: dict[concurrent.futures.Future, tuple[bool, bool]] = {} def submit( # type: ignore[valid-type] @@ -68,10 +69,12 @@ def submit( # type: ignore[valid-type] else: task = self.executor.submit(fn, *args, **kwargs) self.tasks[task] = (__cancel_on_exit__, __reraise_on_exit__) + # add a callback to remove the task from the tasks dict when it's done task.add_done_callback(self.done) return task def done(self, task: concurrent.futures.Future) -> None: + """Remove the task from the tasks dict when it's done.""" try: task.result() except GraphBubbleUp: @@ -103,9 +106,9 @@ def __exit__( concurrent.futures.wait(pending) # shutdown the executor self.stack.__exit__(exc_type, exc_value, traceback) - # re-raise the first exception that occurred in a task + # if there's already an exception being raised, don't raise another one if exc_type is None: - # if there's already an exception being raised, don't raise another one + # re-raise the first exception that occurred in a task for task, (_, reraise) in tasks.items(): if not reraise: continue diff --git a/libs/langgraph/langgraph/pregel/loop.py b/libs/langgraph/langgraph/pregel/loop.py index 0644183904..ca0885c11d 100644 --- a/libs/langgraph/langgraph/pregel/loop.py +++ b/libs/langgraph/langgraph/pregel/loop.py @@ -359,7 +359,13 @@ def tick( input_keys: Union[str, Sequence[str]], ) -> bool: """Execute a single iteration of the Pregel loop. - Returns True if more iterations are needed.""" + + Args: + input_keys: The key(s) to read input from. + + Returns: + True if more iterations are needed. + """ if self.status != "pending": raise RuntimeError("Cannot tick when status is no longer 'pending'") diff --git a/libs/langgraph/langgraph/utils/runnable.py b/libs/langgraph/langgraph/utils/runnable.py index 7cd6a85b99..94de679756 100644 --- a/libs/langgraph/langgraph/utils/runnable.py +++ b/libs/langgraph/langgraph/utils/runnable.py @@ -298,21 +298,22 @@ def coerce_to_runnable( class RunnableSeq(Runnable): - """A simpler version of RunnableSequence.""" + """Sequence of Runnables, where the output of each is the input of the next. + + RunnableSeq is a simpler version of RunnableSequence that is internal to + LangGraph. + """ def __init__( self, *steps: RunnableLike, name: Optional[str] = None, ) -> None: - """Create a new RunnableSequence. + """Create a new RunnableSeq. Args: steps: The steps to include in the sequence. name: The name of the Runnable. Defaults to None. - first: The first Runnable in the sequence. Defaults to None. - middle: The middle Runnables in the sequence. Defaults to None. - last: The last Runnable in the sequence. Defaults to None. Raises: ValueError: If the sequence has less than 2 steps.