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

feat(sdk-js): add support for subgraphs, match schema #1879

Merged
merged 6 commits into from
Sep 27, 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
2 changes: 2 additions & 0 deletions libs/sdk-js/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/docs

Check notice on line 1 in libs/sdk-js/.gitignore

View workflow job for this annotation

GitHub Actions / benchmark

Benchmark results

......................................... fanout_to_subgraph_10x: Mean +- std dev: 60.5 ms +- 1.5 ms ......................................... WARNING: the benchmark result may be unstable * the standard deviation (7.70 ms) is 13% of the mean (58.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. fanout_to_subgraph_10x_sync: Mean +- std dev: 58.1 ms +- 7.7 ms ......................................... fanout_to_subgraph_10x_checkpoint: Mean +- std dev: 77.9 ms +- 1.3 ms ......................................... fanout_to_subgraph_10x_checkpoint_sync: Mean +- std dev: 82.5 ms +- 1.7 ms ......................................... fanout_to_subgraph_100x: Mean +- std dev: 574 ms +- 14 ms ......................................... fanout_to_subgraph_100x_sync: Mean +- std dev: 507 ms +- 6 ms ......................................... fanout_to_subgraph_100x_checkpoint: Mean +- std dev: 777 ms +- 23 ms ......................................... fanout_to_subgraph_100x_checkpoint_sync: Mean +- std dev: 800 ms +- 8 ms ......................................... react_agent_10x: Mean +- std dev: 42.2 ms +- 3.7 ms ......................................... react_agent_10x_sync: Mean +- std dev: 30.2 ms +- 0.2 ms ......................................... react_agent_10x_checkpoint: Mean +- std dev: 54.0 ms +- 1.4 ms ......................................... react_agent_10x_checkpoint_sync: Mean +- std dev: 44.1 ms +- 4.0 ms ......................................... react_agent_100x: Mean +- std dev: 418 ms +- 7 ms ......................................... react_agent_100x_sync: Mean +- std dev: 335 ms +- 3 ms ......................................... react_agent_100x_checkpoint: Mean +- std dev: 958 ms +- 18 ms ......................................... react_agent_100x_checkpoint_sync: Mean +- std dev: 840 ms +- 18 ms ......................................... wide_state_25x300: Mean +- std dev: 20.9 ms +- 0.5 ms ......................................... wide_state_25x300_sync: Mean +- std dev: 12.9 ms +- 0.2 ms ......................................... wide_state_25x300_checkpoint: Mean +- std dev: 241 ms +- 7 ms ......................................... wide_state_25x300_checkpoint_sync: Mean +- std dev: 243 ms +- 17 ms ......................................... wide_state_15x600: Mean +- std dev: 24.2 ms +- 0.4 ms ......................................... wide_state_15x600_sync: Mean +- std dev: 15.1 ms +- 0.2 ms ......................................... wide_state_15x600_checkpoint: Mean +- std dev: 423 ms +- 14 ms ......................................... wide_state_15x600_checkpoint_sync: Mean +- std dev: 423 ms +- 20 ms ......................................... wide_state_9x1200: Mean +- std dev: 24.2 ms +- 0.4 ms ......................................... wide_state_9x1200_sync: Mean +- std dev: 15.0 ms +- 0.2 ms ......................................... wide_state_9x1200_checkpoint: Mean +- std dev: 270 ms +- 9 ms ......................................... wide_state_9x1200_checkpoint_sync: Mean +- std dev: 269 ms +- 16 ms

Check notice on line 1 in libs/sdk-js/.gitignore

View workflow job for this annotation

GitHub Actions / benchmark

Comparison against main

+-----------------------------------------+---------+-----------------------+ | Benchmark | main | changes | +=========================================+=========+=======================+ | wide_state_25x300_checkpoint | 239 ms | 241 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x_sync | 502 ms | 507 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_15x600_checkpoint | 418 ms | 423 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200_checkpoint_sync | 265 ms | 269 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200_sync | 14.7 ms | 15.0 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x_checkpoint_sync | 788 ms | 800 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_100x_sync | 329 ms | 335 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_100x | 411 ms | 418 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_25x300_sync | 12.7 ms | 12.9 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_10x | 59.5 ms | 60.5 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_10x_checkpoint_sync | 81.1 ms | 82.5 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_10x_sync | 29.6 ms | 30.2 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_10x_checkpoint | 76.4 ms | 77.9 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_10x_checkpoint | 53.0 ms | 54.0 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_15x600_sync | 14.7 ms | 15.1 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_100x_checkpoint_sync | 822 ms | 840 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_25x300_checkpoint_sync | 237 ms | 243 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_10x | 41.2 ms | 42.2 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_10x_checkpoint_sync | 43.0 ms | 44.1 ms: 1.03x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200 | 23.5 ms | 24.2 ms: 1.03x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_15x600 | 23.5 ms | 24.2 ms: 1.03x slower | +-----------------------------------------+---------+-----------------------+ | wide_state_25x300 | 20.4 ms | 20.9 ms: 1.03x slower | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x_checkpoint | 750 ms | 777 ms: 1.04x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_100x_checkpoint | 922 ms | 958 ms: 1.04x slower | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_10x_sync | 55.9 ms | 58.1 ms: 1.04x slower | +---------------------------------------
/*.tgz
/*.tar
## GENERATED create-entrypoints.js
/client.cjs
/client.js
Expand Down
1 change: 1 addition & 0 deletions libs/sdk-js/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
74 changes: 65 additions & 9 deletions libs/sdk-js/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
ThreadState,
Cron,
AssistantVersion,
Subgraphs,
Checkpoint,
} from "./schema.js";
import { AsyncCaller, AsyncCallerParams } from "./utils/async_caller.js";
import {
Expand Down Expand Up @@ -221,8 +223,13 @@ export class AssistantsClient extends BaseClient {
* @param assistantId The ID of the assistant.
* @returns Serialized graph
*/
async getGraph(assistantId: string): Promise<AssistantGraph> {
return this.fetch<AssistantGraph>(`/assistants/${assistantId}/graph`);
async getGraph(
assistantId: string,
options?: { xray?: boolean },
): Promise<AssistantGraph> {
return this.fetch<AssistantGraph>(`/assistants/${assistantId}/graph`, {
params: { xray: options?.xray },
});
}

/**
Expand All @@ -234,6 +241,31 @@ export class AssistantsClient extends BaseClient {
return this.fetch<GraphSchema>(`/assistants/${assistantId}/schemas`);
}

/**
* Get the schemas of an assistant by ID.
*
* @param assistantId The ID of the assistant to get the schema of.
* @param options Additional options for getting subgraphs, such as namespace or recursion extraction.
* @returns The subgraphs of the assistant.
*/
async getSubgraphs(
assistantId: string,
options?: {
namespace?: string;
recurse?: boolean;
},
): Promise<Subgraphs> {
if (options?.namespace) {
return this.fetch<Subgraphs>(
`/assistants/${assistantId}/subgraphs/${options.namespace}`,
{ params: { recurse: options?.recurse } },
);
}
return this.fetch<Subgraphs>(`/assistants/${assistantId}/subgraphs`, {
params: { recurse: options?.recurse },
});
}

/**
* Create a new assistant.
* @param payload Payload for creating an assistant.
Expand Down Expand Up @@ -479,13 +511,30 @@ export class ThreadsClient extends BaseClient {
*/
async getState<ValuesType = DefaultValues>(
threadId: string,
checkpointId?: string,
checkpoint?: Checkpoint | string,
options?: { subgraphs?: boolean },
): Promise<ThreadState<ValuesType>> {
return this.fetch<ThreadState<ValuesType>>(
checkpointId != null
? `/threads/${threadId}/state/${checkpointId}`
: `/threads/${threadId}/state`,
);
if (checkpoint != null) {
if (typeof checkpoint !== "string") {
return this.fetch<ThreadState<ValuesType>>(
`/threads/${threadId}/state/checkpoint`,
{
method: "POST",
json: { checkpoint, subgraphs: options?.subgraphs },
},
);
}

// deprecated
return this.fetch<ThreadState<ValuesType>>(
`/threads/${threadId}/state/${checkpoint}`,
{ params: { subgraphs: options?.subgraphs } },
);
}

return this.fetch<ThreadState<ValuesType>>(`/threads/${threadId}/state`, {
params: { subgraphs: options?.subgraphs },
});
}

/**
Expand All @@ -496,7 +545,12 @@ export class ThreadsClient extends BaseClient {
*/
async updateState<ValuesType = DefaultValues>(
threadId: string,
options: { values: ValuesType; checkpointId?: string; asNode?: string },
options: {
values: ValuesType;
checkpoint?: Checkpoint;
checkpointId?: string;
asNode?: string;
},
): Promise<Pick<Config, "configurable">> {
return this.fetch<Pick<Config, "configurable">>(
`/threads/${threadId}/state`,
Expand All @@ -505,6 +559,7 @@ export class ThreadsClient extends BaseClient {
json: {
values: options.values,
checkpoint_id: options.checkpointId,
checkpoint: options.checkpoint,
as_node: options?.asNode,
},
},
Expand Down Expand Up @@ -608,6 +663,7 @@ export class RunsClient extends BaseClient {
config: payload?.config,
metadata: payload?.metadata,
stream_mode: payload?.streamMode,
stream_subgraphs: payload?.streamSubgraphs,
feedback_keys: payload?.feedbackKeys,
assistant_id: assistantId,
interrupt_before: payload?.interruptBefore,
Expand Down
2 changes: 2 additions & 0 deletions libs/sdk-js/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ export interface GraphSchema {
config_schema?: JSONSchema7;
}

export type Subgraphs = Record<string, GraphSchema>;

export type Metadata = Optional<Record<string, unknown>>;

export interface AssistantBase {
Expand Down
5 changes: 5 additions & 0 deletions libs/sdk-js/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ export interface RunsStreamPayload extends RunsInvokePayload {
*/
streamMode?: StreamMode | Array<StreamMode>;

/**
* Stream output from subgraphs. By default, streams only the top graph.
*/
streamSubgraphs?: boolean;

/**
* Pass one or more feedbackKeys if you want to request short-lived signed URLs
* for submitting feedback to LangSmith with this key for this run.
Expand Down
16 changes: 12 additions & 4 deletions libs/sdk-py/langgraph_sdk/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,11 +304,14 @@ async def get(self, assistant_id: str) -> Assistant:
""" # noqa: E501
return await self.http.get(f"/assistants/{assistant_id}")

async def get_graph(self, assistant_id: str) -> dict[str, list[dict[str, Any]]]:
async def get_graph(
self, assistant_id: str, *, xray: bool = False
) -> dict[str, list[dict[str, Any]]]:
"""Get the graph of an assistant by ID.

Args:
assistant_id: The ID of the assistant to get the graph of.
xray: Include graph representation of subgraphs.

Returns:
Graph: The graph information for the assistant in JSON format.
Expand Down Expand Up @@ -338,7 +341,9 @@ async def get_graph(self, assistant_id: str) -> dict[str, list[dict[str, Any]]]:


""" # noqa: E501
return await self.http.get(f"/assistants/{assistant_id}/graph")
return await self.http.get(
f"/assistants/{assistant_id}/graph", params={"xray": xray}
)

async def get_schemas(self, assistant_id: str) -> GraphSchema:
"""Get the schemas of an assistant by ID.
Expand Down Expand Up @@ -2068,11 +2073,14 @@ def get(self, assistant_id: str) -> Assistant:
""" # noqa: E501
return self.http.get(f"/assistants/{assistant_id}")

def get_graph(self, assistant_id: str) -> dict[str, list[dict[str, Any]]]:
def get_graph(
self, assistant_id: str, *, xray: bool = False
) -> dict[str, list[dict[str, Any]]]:
"""Get the graph of an assistant by ID.

Args:
assistant_id: The ID of the assistant to get the graph of.
xray: Include graph representation of subgraphs.

Returns:
Graph: The graph information for the assistant in JSON format.
Expand Down Expand Up @@ -2102,7 +2110,7 @@ def get_graph(self, assistant_id: str) -> dict[str, list[dict[str, Any]]]:


""" # noqa: E501
return self.http.get(f"/assistants/{assistant_id}/graph")
return self.http.get(f"/assistants/{assistant_id}/graph", params={"xray": xray})

def get_schemas(self, assistant_id: str) -> GraphSchema:
"""Get the schemas of an assistant by ID.
Expand Down
Loading