Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: internal doc nits #2946

Merged
merged 5 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions libs/langgraph/langgraph/graph/graph.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import asyncio

Check notice on line 1 in libs/langgraph/langgraph/graph/graph.py

View workflow job for this annotation

GitHub Actions / benchmark

Benchmark results

......................................... fanout_to_subgraph_10x: Mean +- std dev: 61.4 ms +- 1.4 ms ......................................... fanout_to_subgraph_10x_sync: Mean +- std dev: 53.2 ms +- 0.7 ms ......................................... fanout_to_subgraph_10x_checkpoint: Mean +- std dev: 74.8 ms +- 1.0 ms ......................................... fanout_to_subgraph_10x_checkpoint_sync: Mean +- std dev: 96.2 ms +- 2.9 ms ......................................... fanout_to_subgraph_100x: Mean +- std dev: 613 ms +- 25 ms ......................................... fanout_to_subgraph_100x_sync: Mean +- std dev: 514 ms +- 11 ms ......................................... fanout_to_subgraph_100x_checkpoint: Mean +- std dev: 731 ms +- 10 ms ......................................... fanout_to_subgraph_100x_checkpoint_sync: Mean +- std dev: 950 ms +- 16 ms ......................................... react_agent_10x: Mean +- std dev: 30.7 ms +- 0.7 ms ......................................... react_agent_10x_sync: Mean +- std dev: 22.8 ms +- 0.2 ms ......................................... react_agent_10x_checkpoint: Mean +- std dev: 38.1 ms +- 0.7 ms ......................................... react_agent_10x_checkpoint_sync: Mean +- std dev: 36.6 ms +- 0.3 ms ......................................... react_agent_100x: Mean +- std dev: 340 ms +- 7 ms ......................................... react_agent_100x_sync: Mean +- std dev: 270 ms +- 2 ms ......................................... react_agent_100x_checkpoint: Mean +- std dev: 631 ms +- 6 ms ......................................... react_agent_100x_checkpoint_sync: Mean +- std dev: 614 ms +- 5 ms ......................................... wide_state_25x300: Mean +- std dev: 23.1 ms +- 0.4 ms ......................................... wide_state_25x300_sync: Mean +- std dev: 15.2 ms +- 0.1 ms ......................................... wide_state_25x300_checkpoint: Mean +- std dev: 249 ms +- 12 ms ......................................... wide_state_25x300_checkpoint_sync: Mean +- std dev: 245 ms +- 12 ms ......................................... wide_state_15x600: Mean +- std dev: 26.9 ms +- 0.6 ms ......................................... wide_state_15x600_sync: Mean +- std dev: 17.7 ms +- 0.6 ms ......................................... wide_state_15x600_checkpoint: Mean +- std dev: 431 ms +- 14 ms ......................................... wide_state_15x600_checkpoint_sync: Mean +- std dev: 428 ms +- 15 ms ......................................... wide_state_9x1200: Mean +- std dev: 27.2 ms +- 0.8 ms ......................................... wide_state_9x1200_sync: Mean +- std dev: 17.9 ms +- 0.3 ms ......................................... wide_state_9x1200_checkpoint: Mean +- std dev: 288 ms +- 18 ms ......................................... wide_state_9x1200_checkpoint_sync: Mean +- std dev: 278 ms +- 14 ms

Check notice on line 1 in libs/langgraph/langgraph/graph/graph.py

View workflow job for this annotation

GitHub Actions / benchmark

Comparison against main

+-----------------------------------------+---------+-----------------------+ | Benchmark | main | changes | +=========================================+=========+=======================+ | fanout_to_subgraph_100x_checkpoint | 751 ms | 731 ms: 1.03x faster | +-----------------------------------------+---------+-----------------------+ | react_agent_100x_checkpoint_sync | 630 ms | 614 ms: 1.03x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_15x600 | 27.4 ms | 26.9 ms: 1.02x faster | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x_checkpoint_sync | 966 ms | 950 ms: 1.02x faster | +-----------------------------------------+---------+-----------------------+ | react_agent_10x_sync | 23.1 ms | 22.8 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | react_agent_10x_checkpoint | 38.6 ms | 38.1 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | react_agent_100x_checkpoint | 638 ms | 631 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | react_agent_10x_checkpoint_sync | 37.0 ms | 36.6 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x_sync | 520 ms | 514 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | react_agent_100x_sync | 272 ms | 270 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_25x300 | 23.2 ms | 23.1 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | react_agent_100x | 343 ms | 340 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200 | 27.4 ms | 27.2 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_10x_sync | 53.5 ms | 53.2 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | react_agent_10x | 30.9 ms | 30.7 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_25x300_sync | 15.3 ms | 15.2 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200_sync | 17.8 ms | 17.9 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x | 600 ms | 613 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200_checkpoint | 279 ms | 288 ms: 1.03x slower | +-----------------------------------------+---------+-----------------------+ | Geometric mean | (ref) | 1.01x faster | +-----------------------------------------+---------+-----------------------+ Benchmark hidden because not significant (9): wide_state_15x600_checkpoint_sync, wide_state_15x600_sync, wide_state_15x600_checkpoint, fanout_to_subgraph_10x, fanout_to_subgraph_10x_checkpoint, fanout_to_subgraph_10x_checkpoint_sync, wide_state_25x300_checkpoint_sync, wide_state_9x1200_checkpoint_sync, wide_state_25x300_checkpoint
import logging
from collections import defaultdict
from typing import (
Expand Down Expand Up @@ -257,7 +257,7 @@
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.
Expand Down Expand Up @@ -308,7 +308,7 @@
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)

Expand All @@ -334,7 +334,7 @@
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)

Expand All @@ -347,7 +347,7 @@
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)

Expand Down
13 changes: 6 additions & 7 deletions libs/langgraph/langgraph/graph/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
"""
...

Expand All @@ -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.
"""
...

Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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.")
Expand Down
6 changes: 3 additions & 3 deletions libs/langgraph/langgraph/pregel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
9 changes: 5 additions & 4 deletions libs/langgraph/langgraph/pregel/call.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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:
Expand Down
7 changes: 5 additions & 2 deletions libs/langgraph/langgraph/pregel/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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:
Expand Down Expand Up @@ -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
Expand Down
8 changes: 7 additions & 1 deletion libs/langgraph/langgraph/pregel/loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'")

Expand Down
11 changes: 6 additions & 5 deletions libs/langgraph/langgraph/utils/runnable.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading