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

Add docstring to RemoteGraph #2217

Merged
merged 7 commits into from
Oct 29, 2024
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
6 changes: 6 additions & 0 deletions docs/docs/reference/remote_graph.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# RemoteGraph

Check notice on line 1 in docs/docs/reference/remote_graph.md

View workflow job for this annotation

GitHub Actions / benchmark

Benchmark results

......................................... WARNING: the benchmark result may be unstable * the standard deviation (6.98 ms) is 13% of the mean (55.7 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: 55.7 ms +- 7.0 ms ......................................... fanout_to_subgraph_10x_sync: Mean +- std dev: 46.9 ms +- 3.4 ms ......................................... fanout_to_subgraph_10x_checkpoint: Mean +- std dev: 77.9 ms +- 1.7 ms ......................................... fanout_to_subgraph_10x_checkpoint_sync: Mean +- std dev: 86.4 ms +- 0.9 ms ......................................... fanout_to_subgraph_100x: Mean +- std dev: 490 ms +- 11 ms ......................................... fanout_to_subgraph_100x_sync: Mean +- std dev: 435 ms +- 4 ms ......................................... fanout_to_subgraph_100x_checkpoint: Mean +- std dev: 863 ms +- 44 ms ......................................... fanout_to_subgraph_100x_checkpoint_sync: Mean +- std dev: 860 ms +- 22 ms ......................................... react_agent_10x: Mean +- std dev: 29.5 ms +- 0.6 ms ......................................... react_agent_10x_sync: Mean +- std dev: 23.0 ms +- 1.9 ms ......................................... react_agent_10x_checkpoint: Mean +- std dev: 49.4 ms +- 4.4 ms ......................................... WARNING: the benchmark result may be unstable * the standard deviation (4.31 ms) is 11% of the mean (39.1 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. react_agent_10x_checkpoint_sync: Mean +- std dev: 39.1 ms +- 4.3 ms ......................................... react_agent_100x: Mean +- std dev: 337 ms +- 18 ms ......................................... react_agent_100x_sync: Mean +- std dev: 268 ms +- 16 ms ......................................... react_agent_100x_checkpoint: Mean +- std dev: 943 ms +- 13 ms ......................................... react_agent_100x_checkpoint_sync: Mean +- std dev: 843 ms +- 19 ms ......................................... wide_state_25x300: Mean +- std dev: 18.7 ms +- 0.4 ms ......................................... wide_state_25x300_sync: Mean +- std dev: 11.2 ms +- 0.1 ms ......................................... wide_state_25x300_checkpoint: Mean +- std dev: 276 ms +- 6 ms ......................................... wide_state_25x300_checkpoint_sync: Mean +- std dev: 264 ms +- 3 ms ......................................... wide_state_15x600: Mean +- std dev: 21.6 ms +- 0.4 ms ......................................... wide_state_15x600_sync: Mean +- std dev: 12.8 ms +- 0.1 ms ......................................... wide_state_15x600_checkpoint: Mean +- std dev: 476 ms +- 7 ms ......................................... wide_state_15x600_checkpoint_sync: Mean +- std dev: 477 ms +- 18 ms ......................................... wide_state_9x1200: Mean +- std dev: 21.5 ms +- 0.4 ms ......................................... wide_state_9x1200_sync: Mean +- std dev: 12.8 ms +- 0.1 ms ......................................... wide_state_9x1200_checkpoint: Mean +- std dev: 310 ms +- 5 ms ......................................... wide_state_9x1200_checkpoint_sync: Mean +- std dev: 308 ms +- 16 ms

Check notice on line 1 in docs/docs/reference/remote_graph.md

View workflow job for this annotation

GitHub Actions / benchmark

Comparison against main

+-----------------------------------------+---------+-----------------------+ | Benchmark | main | changes | +=========================================+=========+=======================+ | wide_state_15x600_checkpoint | 474 ms | 476 ms: 1.00x slower | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_10x_checkpoint | 77.3 ms | 77.9 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_10x_checkpoint_sync | 85.7 ms | 86.4 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_25x300_checkpoint_sync | 261 ms | 264 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_10x | 29.2 ms | 29.5 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200_checkpoint | 306 ms | 310 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x_sync | 429 ms | 435 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_25x300_checkpoint | 272 ms | 276 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200 | 21.2 ms | 21.5 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_15x600_sync | 12.6 ms | 12.8 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x_checkpoint_sync | 847 ms | 860 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_100x_sync | 263 ms | 268 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200_sync | 12.6 ms | 12.8 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_15x600_checkpoint_sync | 469 ms | 477 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_15x600 | 21.3 ms | 21.6 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200_checkpoint_sync | 303 ms | 308 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_25x300 | 18.3 ms | 18.7 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_100x | 330 ms | 337 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_10x_sync | 22.5 ms | 23.0 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x | 477 ms | 490 ms: 1.03x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_25x300_sync | 10.9 ms | 11.2 ms: 1.03x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_100x_checkpoint | 915 ms | 943 ms: 1.03x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_100x_checkpoint_sync | 817 ms | 843 ms: 1.03x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_10x_checkpoint | 47.7 ms | 49.4 ms: 1.04x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_10x_checkpoint_sync | 37.4 ms | 39.1 ms: 1.04x slower | +---------------------------------------

::: langgraph.pregel.remote
options:
members:
- RemoteGraph
1 change: 1 addition & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ nav:
- Reference:
- "reference/index.md"
- Graphs: reference/graphs.md
- RemoteGraph: reference/remote_graph.md
- Checkpointing: reference/checkpoints.md
- Storage: reference/store.md
- Prebuilt Components: reference/prebuilt.md
Expand Down
194 changes: 193 additions & 1 deletion libs/langgraph/langgraph/pregel/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ class RemoteException(Exception):


class RemoteGraph(PregelProtocol):
"""The `RemoteGraph` class is a client implementation for calling remote
APIs that implement the LangGraph Server API specification.

For example, the `RemoteGraph` class can be used to call APIs from deployments
on LangGraph Cloud.

`RemoteGraph` behaves the same way as a `Graph` and can be used directly as
a node in another `Graph`.
"""

name: str

def __init__(
Expand All @@ -63,7 +73,17 @@ def __init__(
"""Specify `url`, `api_key`, and/or `headers` to create default sync and async clients.

If `client` or `sync_client` are provided, they will be used instead of the default clients.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would also add that if at least one of the 3 (url/client/sync_client) needs to be specified. something similar to how i describe in this how-to guide maybe https://github.com/langchain-ai/langgraph/pull/2218/files

See `LangGraphClient` and `SyncLangGraphClient` for details on the default clients.
See `LangGraphClient` and `SyncLangGraphClient` for details on the default clients. At least
one of `url`, `client`, or `sync_client` must be provided.

Args:
name: The name of the graph.
url: The URL of the remote API.
api_key: The API key to use for authentication. If not provided, it will be read from the environment (`LANGGRAPH_API_KEY`, `LANGSMITH_API_KEY`, or `LANGCHAIN_API_KEY`).
headers: Additional headers to include in the requests.
client: A `LangGraphClient` instance to use instead of creating a default client.
sync_client: A `SyncLangGraphClient` instance to use instead of creating a default client.
config: An optional `RunnableConfig` instance with additional configuration.
"""
self.name = name
self.config = config
Expand Down Expand Up @@ -121,6 +141,19 @@ def get_graph(
*,
xray: Union[int, bool] = False,
) -> DrawableGraph:
"""Get graph by graph name.

This method calls `GET /assistants/{assistant_id}/graph`.

Args:
config: This parameter is not used.
xray: Include graph representation of subgraphs. If an integer
value is provided, only subgraphs with a depth less than or
equal to the value will be included.

Returns:
The graph information for the assistant in JSON format.
"""
sync_client = self._validate_sync_client()
graph = sync_client.assistants.get_graph(
assistant_id=self.name,
Expand All @@ -137,6 +170,19 @@ async def aget_graph(
*,
xray: Union[int, bool] = False,
) -> DrawableGraph:
"""Get graph by graph name.

This method calls `GET /assistants/{assistant_id}/graph`.

Args:
config: This parameter is not used.
xray: Include graph representation of subgraphs. If an integer
value is provided, only subgraphs with a depth less than or
equal to the value will be included.

Returns:
The graph information for the assistant in JSON format.
"""
client = self._validate_client()
graph = await client.assistants.get_graph(
assistant_id=self.name,
Expand Down Expand Up @@ -268,6 +314,20 @@ def _sanitize_obj(obj: Any) -> Any:
def get_state(
self, config: RunnableConfig, *, subgraphs: bool = False
) -> StateSnapshot:
"""Get the state of a thread.

This method calls `POST /threads/{thread_id}/state/checkpoint` if a
checkpoint is specified in the config or `GET /threads/{thread_id}/state`
if no checkpoint is specified.

Args:
config: A `RunnableConfig` that includes `thread_id` in the
`configurable` field.
subgraphs: Include subgraphs in the state.

Returns:
The latest state of the thread.
"""
sync_client = self._validate_sync_client()
merged_config = merge_configs(self.config, config)

Expand All @@ -281,6 +341,20 @@ def get_state(
async def aget_state(
self, config: RunnableConfig, *, subgraphs: bool = False
) -> StateSnapshot:
"""Get the state of a thread.

This method calls `POST /threads/{thread_id}/state/checkpoint` if a
checkpoint is specified in the config or `GET /threads/{thread_id}/state`
if no checkpoint is specified.

Args:
config: A `RunnableConfig` that includes `thread_id` in the
`configurable` field.
subgraphs: Include subgraphs in the state.

Returns:
The latest state of the thread.
"""
client = self._validate_client()
merged_config = merge_configs(self.config, config)

Expand All @@ -299,6 +373,20 @@ def get_state_history(
before: Optional[RunnableConfig] = None,
limit: Optional[int] = None,
) -> Iterator[StateSnapshot]:
"""Get the state history of a thread.

This method calls `POST /threads/{thread_id}/history`.

Args:
config: A `RunnableConfig` that includes `thread_id` in the
`configurable` field.
filter: Metadata to filter on.
before: A `RunnableConfig` that includes checkpoint metadata.
limit: Max number of states to return.

Returns:
States of the thread.
"""
sync_client = self._validate_sync_client()
merged_config = merge_configs(self.config, config)

Expand All @@ -320,6 +408,20 @@ async def aget_state_history(
before: Optional[RunnableConfig] = None,
limit: Optional[int] = None,
) -> AsyncIterator[StateSnapshot]:
"""Get the state history of a thread.

This method calls `POST /threads/{thread_id}/history`.

Args:
config: A `RunnableConfig` that includes `thread_id` in the
`configurable` field.
filter: Metadata to filter on.
before: A `RunnableConfig` that includes checkpoint metadata.
limit: Max number of states to return.

Returns:
States of the thread.
"""
client = self._validate_client()
merged_config = merge_configs(self.config, config)

Expand All @@ -339,6 +441,19 @@ def update_state(
values: Optional[Union[dict[str, Any], Any]],
as_node: Optional[str] = None,
) -> RunnableConfig:
"""Update the state of a thread.

This method calls `POST /threads/{thread_id}/state`.

Args:
config: A `RunnableConfig` that includes `thread_id` in the
`configurable` field.
values: Values to update to the state.
as_node: Update the state as if this node had just executed.

Returns:
`RunnableConfig` for the updated thread.
"""
sync_client = self._validate_sync_client()
merged_config = merge_configs(self.config, config)

Expand All @@ -356,6 +471,19 @@ async def aupdate_state(
values: Optional[Union[dict[str, Any], Any]],
as_node: Optional[str] = None,
) -> RunnableConfig:
"""Update the state of a thread.

This method calls `POST /threads/{thread_id}/state`.

Args:
config: A `RunnableConfig` that includes `thread_id` in the
`configurable` field.
values: Values to update to the state.
as_node: Update the state as if this node had just executed.

Returns:
`RunnableConfig` for the updated thread.
"""
client = self._validate_client()
merged_config = merge_configs(self.config, config)

Expand Down Expand Up @@ -408,6 +536,23 @@ def stream(
interrupt_after: Optional[Union[All, Sequence[str]]] = None,
subgraphs: bool = False,
) -> Iterator[Union[dict[str, Any], Any]]:
"""Create a run and stream the results.

This method calls `POST /threads/{thread_id}/runs/stream` if a `thread_id`
is speciffed in the `configurable` field of the config or
`POST /runs/stream` otherwise.

Args:
input: Input to the graph.
config: A `RunnableConfig` for graph invocation.
stream_mode: Stream mode(s) to use.
interrupt_before: Interrupt the graph before these nodes.
interrupt_after: Interrupt the graph after these nodes.
subgraphs: Stream from subgraphs.

Yields:
The output of the graph.
"""
sync_client = self._validate_sync_client()
merged_config = merge_configs(self.config, config)
sanitized_config = self._sanitize_config(merged_config)
Expand Down Expand Up @@ -456,6 +601,23 @@ async def astream(
interrupt_after: Optional[Union[All, Sequence[str]]] = None,
subgraphs: bool = False,
) -> AsyncIterator[Union[dict[str, Any], Any]]:
"""Create a run and stream the results.

This method calls `POST /threads/{thread_id}/runs/stream` if a `thread_id`
is speciffed in the `configurable` field of the config or
`POST /runs/stream` otherwise.

Args:
input: Input to the graph.
config: A `RunnableConfig` for graph invocation.
stream_mode: Stream mode(s) to use.
interrupt_before: Interrupt the graph before these nodes.
interrupt_after: Interrupt the graph after these nodes.
subgraphs: Stream from subgraphs.

Yields:
The output of the graph.
"""
client = self._validate_client()
merged_config = merge_configs(self.config, config)
sanitized_config = self._sanitize_config(merged_config)
Expand Down Expand Up @@ -518,6 +680,21 @@ def invoke(
interrupt_before: Optional[Union[All, Sequence[str]]] = None,
interrupt_after: Optional[Union[All, Sequence[str]]] = None,
) -> Union[dict[str, Any], Any]:
"""Create a run, wait until it finishes and return the final state.

This method calls `POST /threads/{thread_id}/runs/wait` if a `thread_id`
is speciffed in the `configurable` field of the config or
`POST /runs/wait` otherwise.

Args:
input: Input to the graph.
config: A `RunnableConfig` for graph invocation.
interrupt_before: Interrupt the graph before these nodes.
interrupt_after: Interrupt the graph after these nodes.

Returns:
The output of the graph.
"""
sync_client = self._validate_sync_client()
merged_config = merge_configs(self.config, config)
sanitized_config = self._sanitize_config(merged_config)
Expand All @@ -540,6 +717,21 @@ async def ainvoke(
interrupt_before: Optional[Union[All, Sequence[str]]] = None,
interrupt_after: Optional[Union[All, Sequence[str]]] = None,
) -> Union[dict[str, Any], Any]:
"""Create a run, wait until it finishes and return the final state.

This method calls `POST /threads/{thread_id}/runs/wait` if a `thread_id`
is speciffed in the `configurable` field of the config or
`POST /runs/wait` otherwise.

Args:
input: Input to the graph.
config: A `RunnableConfig` for graph invocation.
interrupt_before: Interrupt the graph before these nodes.
interrupt_after: Interrupt the graph after these nodes.

Returns:
The output of the graph.
"""
client = self._validate_client()
merged_config = merge_configs(self.config, config)
sanitized_config = self._sanitize_config(merged_config)
Expand Down
Loading