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

[Bug Fix] retry_on handling and add support for lists in RetryPolicy #1753

Merged
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
34 changes: 27 additions & 7 deletions libs/langgraph/langgraph/pregel/retry.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import asyncio

Check notice on line 1 in libs/langgraph/langgraph/pregel/retry.py

View workflow job for this annotation

GitHub Actions / benchmark

Benchmark results

......................................... WARNING: the benchmark result may be unstable * the standard deviation (8.67 ms) is 14% of the mean (63.2 ms) Try to rerun the benchmark with more runs, values and/or loops. Run 'python -m pyperf system tune' command to reduce the system jitter. Use pyperf stats, pyperf dump and pyperf hist to analyze results. Use --quiet option to hide these warnings. fanout_to_subgraph_10x: Mean +- std dev: 63.2 ms +- 8.7 ms ......................................... WARNING: the benchmark result may be unstable * the standard deviation (8.61 ms) is 15% of the mean (56.8 ms) Try to rerun the benchmark with more runs, values and/or loops. Run 'python -m pyperf system tune' command to reduce the system jitter. Use pyperf stats, pyperf dump and pyperf hist to analyze results. Use --quiet option to hide these warnings. fanout_to_subgraph_10x_sync: Mean +- std dev: 56.8 ms +- 8.6 ms ......................................... fanout_to_subgraph_10x_checkpoint: Mean +- std dev: 76.8 ms +- 1.2 ms ......................................... fanout_to_subgraph_10x_checkpoint_sync: Mean +- std dev: 81.7 ms +- 0.9 ms ......................................... fanout_to_subgraph_100x: Mean +- std dev: 594 ms +- 21 ms ......................................... fanout_to_subgraph_100x_sync: Mean +- std dev: 502 ms +- 7 ms ......................................... fanout_to_subgraph_100x_checkpoint: Mean +- std dev: 815 ms +- 27 ms ......................................... fanout_to_subgraph_100x_checkpoint_sync: Mean +- std dev: 782 ms +- 6 ms ......................................... react_agent_10x: Mean +- std dev: 39.0 ms +- 0.6 ms ......................................... react_agent_10x_sync: Mean +- std dev: 30.4 ms +- 0.4 ms ......................................... react_agent_10x_checkpoint: Mean +- std dev: 52.7 ms +- 1.5 ms ......................................... react_agent_10x_checkpoint_sync: Mean +- std dev: 40.1 ms +- 0.6 ms ......................................... react_agent_100x: Mean +- std dev: 424 ms +- 19 ms ......................................... react_agent_100x_sync: Mean +- std dev: 349 ms +- 17 ms ......................................... react_agent_100x_checkpoint: Mean +- std dev: 1.02 sec +- 0.02 sec ......................................... react_agent_100x_checkpoint_sync: Mean +- std dev: 915 ms +- 23 ms ......................................... wide_state_25x300: Mean +- std dev: 20.1 ms +- 0.2 ms ......................................... wide_state_25x300_sync: Mean +- std dev: 12.7 ms +- 0.1 ms ......................................... wide_state_25x300_checkpoint: Mean +- std dev: 246 ms +- 10 ms ......................................... wide_state_25x300_checkpoint_sync: Mean +- std dev: 238 ms +- 8 ms ......................................... wide_state_15x600: Mean +- std dev: 23.3 ms +- 0.3 ms ......................................... wide_state_15x600_sync: Mean +- std dev: 14.6 ms +- 0.3 ms ......................................... wide_state_15x600_checkpoint: Mean +- std dev: 421 ms +- 13 ms ......................................... wide_state_15x600_checkpoint_sync: Mean +- std dev: 416 ms +- 15 ms ......................................... wide_state_9x1200: Mean +- std dev: 23.3 ms +- 0.3 ms ......................................... wide_state_9x1200_sync: Mean +- std dev: 14.6 ms +- 0.1 ms ......................................... wide_state_9x1200_checkpoint: Mean +- std dev: 274 ms +- 8 ms ......................................... wide_state_9x1200_checkpoint_sync: Mean +- std dev: 264 ms +- 8 ms

Check notice on line 1 in libs/langgraph/langgraph/pregel/retry.py

View workflow job for this annotation

GitHub Actions / benchmark

Comparison against main

+-----------------------------------------+---------+------------------------+ | Benchmark | main | changes | +=========================================+=========+========================+ | wide_state_15x600_checkpoint | 417 ms | 421 ms: 1.01x slower | +-----------------------------------------+---------+------------------------+ | wide_state_25x300_checkpoint_sync | 236 ms | 238 ms: 1.01x slower | +-----------------------------------------+---------+------------------------+ | wide_state_25x300_checkpoint | 243 ms | 246 ms: 1.01x slower | +-----------------------------------------+---------+------------------------+ | wide_state_15x600 | 22.9 ms | 23.3 ms: 1.02x slower | +-----------------------------------------+---------+------------------------+ | wide_state_25x300 | 19.7 ms | 20.1 ms: 1.02x slower | +-----------------------------------------+---------+------------------------+ | wide_state_9x1200 | 22.9 ms | 23.3 ms: 1.02x slower | +-----------------------------------------+---------+------------------------+ | react_agent_10x | 38.1 ms | 39.0 ms: 1.02x slower | +-----------------------------------------+---------+------------------------+ | react_agent_10x_sync | 29.7 ms | 30.4 ms: 1.02x slower | +-----------------------------------------+---------+------------------------+ | wide_state_9x1200_sync | 14.2 ms | 14.6 ms: 1.03x slower | +-----------------------------------------+---------+------------------------+ | fanout_to_subgraph_10x_checkpoint | 74.6 ms | 76.8 ms: 1.03x slower | +-----------------------------------------+---------+------------------------+ | react_agent_10x_checkpoint_sync | 38.9 ms | 40.1 ms: 1.03x slower | +-----------------------------------------+---------+------------------------+ | wide_state_25x300_sync | 12.3 ms | 12.7 ms: 1.03x slower | +-----------------------------------------+---------+------------------------+ | react_agent_100x_sync | 339 ms | 349 ms: 1.03x slower | +-----------------------------------------+---------+------------------------+ | react_agent_100x | 411 ms | 424 ms: 1.03x slower | +-----------------------------------------+---------+------------------------+ | wide_state_15x600_sync | 14.2 ms | 14.6 ms: 1.03x slower | +-----------------------------------------+---------+------------------------+ | react_agent_10x_checkpoint | 51.0 ms | 52.7 ms: 1.03x slower | +-----------------------------------------+---------+------------------------+ | fanout_to_subgraph_100x_sync | 485 ms | 502 ms: 1.04x slower | +-----------------------------------------+---------+------------------------+ | fanout_to_subgraph_100x_checkpoint_sync | 754 ms | 782 ms: 1.04x slower | +-----------------------------------------+---------+------------------------+ | fanout_to_subgraph_10x | 60.9 ms | 63.2 ms: 1.04x slower | +-----------------------------------------+---------+------------------------+ | fanout_to_subgraph_10x_checkpoint_sync | 78.6 ms | 81.7 ms: 1.04x slower | +-----------------------------------------+---------+------------------------+ | react_agent_100x_checkpoint_sync | 864 ms | 915 ms: 1.06x slower | +-----------------------------------------+---------+------------------------+ | react_agent_100x_checkpoint | 961 ms | 1.02 sec: 1.06x slower | +-----------------------------------------+---------+------------------------+ | fanout_to_subgraph_10x_sync | 52.6 ms | 56.8 ms: 1.08x slower | +-----------------------------------------+---------+------------------------+ | fanout_to_subgraph_100x | 536 ms | 594 ms: 1.11x slower | +-----------------------------------------+---------+------------------------+ | fanout_to_subgraph_100x_checkpoint | 732 ms | 815 ms: 1.11x
import logging
import random
import time
from typing import Optional
from typing import Optional, Sequence

from langgraph.constants import CONFIG_KEY_RESUMING
from langgraph.errors import GraphInterrupt
Expand Down Expand Up @@ -38,11 +38,21 @@
# increment attempts
attempts += 1
# check if we should retry
if callable(retry_policy.retry_on):
if isinstance(retry_policy.retry_on, Sequence):
if not isinstance(exc, tuple(retry_policy.retry_on)):
raise
elif isinstance(retry_policy.retry_on, type) and issubclass(
retry_policy.retry_on, Exception
):
if not isinstance(exc, retry_policy.retry_on):
raise
elif callable(retry_policy.retry_on):
if not retry_policy.retry_on(exc):
raise
elif not isinstance(exc, retry_policy.retry_on):
raise
else:
raise TypeError(
"retry_on must be an Exception class, a list or tuple of Exception classes, or a callable"
)
# check if we should give up
if attempts >= retry_policy.max_attempts:
raise
Expand Down Expand Up @@ -94,11 +104,21 @@
# increment attempts
attempts += 1
# check if we should retry
if callable(retry_policy.retry_on):
if isinstance(retry_policy.retry_on, Sequence):
if not isinstance(exc, tuple(retry_policy.retry_on)):
raise
elif isinstance(retry_policy.retry_on, type) and issubclass(
retry_policy.retry_on, Exception
):
if not isinstance(exc, retry_policy.retry_on):
raise
elif callable(retry_policy.retry_on):
if not retry_policy.retry_on(exc):
raise
elif not isinstance(exc, retry_policy.retry_on):
raise
else:
raise TypeError(
"retry_on must be an Exception class, a list or tuple of Exception classes, or a callable"
)
# check if we should give up
if attempts >= retry_policy.max_attempts:
raise
Expand Down
4 changes: 2 additions & 2 deletions libs/langgraph/langgraph/pregel/types.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from collections import deque
from typing import Any, Callable, Literal, NamedTuple, Optional, Type, Union
from typing import Any, Callable, Literal, NamedTuple, Optional, Sequence, Type, Union

from langchain_core.runnables import Runnable, RunnableConfig

Expand Down Expand Up @@ -52,7 +52,7 @@ class RetryPolicy(NamedTuple):
jitter: bool = True
"""Whether to add random jitter to the interval between retries."""
retry_on: Union[
Type[Exception], tuple[Type[Exception], ...], Callable[[Exception], bool]
Type[Exception], Sequence[Type[Exception]], Callable[[Exception], bool]
] = default_retry_on
"""List of exception classes that should trigger a retry, or a callable that returns True for exceptions that should trigger a retry."""

Expand Down
Loading