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

sdk-py: add versioning for assistants #1665

Merged
merged 24 commits into from
Sep 20, 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
46 changes: 46 additions & 0 deletions libs/sdk-js/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {

Check notice on line 1 in libs/sdk-js/src/client.ts

View workflow job for this annotation

GitHub Actions / benchmark

Benchmark results

......................................... fanout_to_subgraph_10x: Mean +- std dev: 59.6 ms +- 1.3 ms ......................................... WARNING: the benchmark result may be unstable * the standard deviation (6.78 ms) is 12% of the mean (57.3 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: 57.3 ms +- 6.8 ms ......................................... fanout_to_subgraph_10x_checkpoint: Mean +- std dev: 77.6 ms +- 1.3 ms ......................................... fanout_to_subgraph_10x_checkpoint_sync: Mean +- std dev: 81.5 ms +- 1.0 ms ......................................... fanout_to_subgraph_100x: Mean +- std dev: 550 ms +- 6 ms ......................................... fanout_to_subgraph_100x_sync: Mean +- std dev: 507 ms +- 4 ms ......................................... fanout_to_subgraph_100x_checkpoint: Mean +- std dev: 757 ms +- 20 ms ......................................... fanout_to_subgraph_100x_checkpoint_sync: Mean +- std dev: 801 ms +- 6 ms ......................................... react_agent_10x: Mean +- std dev: 39.5 ms +- 0.8 ms ......................................... react_agent_10x_sync: Mean +- std dev: 29.8 ms +- 0.4 ms ......................................... react_agent_10x_checkpoint: Mean +- std dev: 53.3 ms +- 1.3 ms ......................................... react_agent_10x_checkpoint_sync: Mean +- std dev: 43.2 ms +- 3.6 ms ......................................... react_agent_100x: Mean +- std dev: 416 ms +- 7 ms ......................................... react_agent_100x_sync: Mean +- std dev: 345 ms +- 14 ms ......................................... react_agent_100x_checkpoint: Mean +- std dev: 959 ms +- 17 ms ......................................... react_agent_100x_checkpoint_sync: Mean +- std dev: 839 ms +- 18 ms ......................................... wide_state_25x300: Mean +- std dev: 20.7 ms +- 0.5 ms ......................................... wide_state_25x300_sync: Mean +- std dev: 12.9 ms +- 0.3 ms ......................................... wide_state_25x300_checkpoint: Mean +- std dev: 243 ms +- 11 ms ......................................... wide_state_25x300_checkpoint_sync: Mean +- std dev: 230 ms +- 8 ms ......................................... wide_state_15x600: Mean +- std dev: 23.9 ms +- 0.5 ms ......................................... wide_state_15x600_sync: Mean +- std dev: 14.7 ms +- 0.1 ms ......................................... wide_state_15x600_checkpoint: Mean +- std dev: 422 ms +- 14 ms ......................................... wide_state_15x600_checkpoint_sync: Mean +- std dev: 409 ms +- 12 ms ......................................... wide_state_9x1200: Mean +- std dev: 24.0 ms +- 0.5 ms ......................................... wide_state_9x1200_sync: Mean +- std dev: 14.8 ms +- 0.2 ms ......................................... wide_state_9x1200_checkpoint: Mean +- std dev: 268 ms +- 7 ms ......................................... wide_state_9x1200_checkpoint_sync: Mean +- std dev: 259 ms +- 10 ms

Check notice on line 1 in libs/sdk-js/src/client.ts

View workflow job for this annotation

GitHub Actions / benchmark

Comparison against main

+-----------------------------------------+---------+-----------------------+ | Benchmark | main | changes | +=========================================+=========+=======================+ | fanout_to_subgraph_100x | 599 ms | 550 ms: 1.09x faster | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x_checkpoint | 782 ms | 757 ms: 1.03x faster | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x_sync | 523 ms | 507 ms: 1.03x faster | +-----------------------------------------+---------+-----------------------+ | react_agent_10x_sync | 30.6 ms | 29.8 ms: 1.03x faster | +-----------------------------------------+---------+-----------------------+ | react_agent_10x_checkpoint_sync | 44.2 ms | 43.2 ms: 1.02x faster | +-----------------------------------------+---------+-----------------------+ | react_agent_10x_checkpoint | 54.4 ms | 53.3 ms: 1.02x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_15x600 | 24.4 ms | 23.9 ms: 1.02x faster | +-----------------------------------------+---------+-----------------------+ | react_agent_100x | 424 ms | 416 ms: 1.02x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_15x600_sync | 14.9 ms | 14.7 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200_checkpoint | 272 ms | 268 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | react_agent_10x | 40.0 ms | 39.5 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200 | 24.2 ms | 24.0 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_10x | 59.9 ms | 59.6 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_10x_checkpoint_sync | 81.9 ms | 81.5 ms: 1.00x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200_sync | 14.8 ms | 14.8 ms: 1.00x faster | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x_checkpoint_sync | 794 ms | 801 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_100x_checkpoint_sync | 821 ms | 839 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_100x_checkpoint | 921 ms | 959 ms: 1.04x slower | +-----------------------------------------+---------+-----------------------+ | Geometric mean | (ref) | 1.01x faster | +-----------------------------------------+---------+-----------------------+ Benchmark hidden because not significant (10): wide_state_15x600_checkpoint_sync, wide_state_9x1200_checkpoint_sync, fanout_to_subgraph_10x_checkpoint, wide_state_25x300_checkpoint_sync, wide_state_25x300_sync, wide_state_25x300, fanout_to_subgraph_10x_sync, wide_state_15x600_checkpoint, react_agent_100x_sync, wide_state_25x300_checkpoint
Assistant,
AssistantGraph,
Config,
Expand All @@ -9,6 +9,7 @@
Thread,
ThreadState,
Cron,
AssistantVersion,
} from "./schema.js";
import { AsyncCaller, AsyncCallerParams } from "./utils/async_caller.js";
import {
Expand Down Expand Up @@ -244,6 +245,7 @@
metadata?: Metadata;
assistantId?: string;
ifExists?: OnConflictBehavior;
name?: string;
}): Promise<Assistant> {
return this.fetch<Assistant>("/assistants", {
method: "POST",
Expand All @@ -253,6 +255,7 @@
metadata: payload.metadata,
assistant_id: payload.assistantId,
if_exists: payload.ifExists,
name: payload.name,
},
});
}
Expand All @@ -269,6 +272,7 @@
graphId?: string;
config?: Config;
metadata?: Metadata;
name?: string;
},
): Promise<Assistant> {
return this.fetch<Assistant>(`/assistants/${assistantId}`, {
Expand All @@ -277,6 +281,7 @@
graph_id: payload.graphId,
config: payload.config,
metadata: payload.metadata,
name: payload.name,
},
});
}
Expand Down Expand Up @@ -313,6 +318,47 @@
},
});
}

/**
* List all versions of an assistant.
*
* @param assistantId ID of the assistant.
* @returns List of assistant versions.
*/
async getVersions(
assistantId: string,
payload?: {
metadata?: Metadata;
limit?: number;
offset?: number;
},
): Promise<AssistantVersion[]> {
return this.fetch<AssistantVersion[]>(
`/assistants/${assistantId}/versions`,
{
method: "POST",
json: {
metadata: payload?.metadata ?? undefined,
limit: payload?.limit ?? 10,
offset: payload?.offset ?? 0,
},
},
);
}

/**
* Change the version of an assistant.
*
* @param assistantId ID of the assistant.
* @param version The version to change to.
* @returns The updated assistant.
*/
async setLatest(assistantId: string, version: number): Promise<Assistant> {
return this.fetch<Assistant>(`/assistants/${assistantId}/set_latest`, {
method: "POST",
json: { version },
});
}
}

export class ThreadsClient extends BaseClient {
Expand Down
3 changes: 3 additions & 0 deletions libs/sdk-js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export { Client } from "./client.js";

export type {
Assistant,
AssistantVersion,
AssistantGraph,
Config,
DefaultValues,
Expand All @@ -12,3 +13,5 @@ export type {
ThreadState,
Cron,
} from "./schema.js";

export type { OnConflictBehavior } from "./types.js";
11 changes: 9 additions & 2 deletions libs/sdk-js/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,20 @@ export interface GraphSchema {

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

export interface Assistant {
export interface AssistantBase {
assistant_id: string;
graph_id: string;
config: Config;
created_at: string;
updated_at: string;
metadata: Metadata;
version: number;
}

export interface AssistantVersion extends AssistantBase {}

export interface Assistant extends AssistantBase {
updated_at: string;
name: string;
}
export type AssistantGraph = Record<string, Array<Record<string, unknown>>>;

Expand Down
69 changes: 68 additions & 1 deletion libs/sdk-py/langgraph_sdk/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import langgraph_sdk
from langgraph_sdk.schema import (
Assistant,
AssistantVersion,
Config,
Cron,
DisconnectMode,
Expand Down Expand Up @@ -417,6 +418,7 @@ async def create(
metadata: Json = None,
assistant_id: Optional[str] = None,
if_exists: Optional[OnConflictBehavior] = None,
name: Optional[str] = None,
) -> Assistant:
"""Create a new assistant.

Expand All @@ -429,6 +431,7 @@ async def create(
assistant_id: Assistant ID to use, will default to a random UUID if not provided.
if_exists: How to handle duplicate creation. Defaults to 'raise' under the hood.
Must be either 'raise' (raise error if duplicate), or 'do_nothing' (return existing assistant).
name: The name of the assistant. Defaults to 'Untitled' under the hood.

Returns:
Assistant: The created assistant.
Expand All @@ -440,7 +443,8 @@ async def create(
config={"configurable": {"model_name": "openai"}},
metadata={"number":1},
assistant_id="my-assistant-id",
if_exists="do_nothing"
if_exists="do_nothing",
name="my_name"
)
""" # noqa: E501
payload: Dict[str, Any] = {
Expand All @@ -454,6 +458,8 @@ async def create(
payload["assistant_id"] = assistant_id
if if_exists:
payload["if_exists"] = if_exists
if name:
payload["name"] = name
return await self.http.post("/assistants", json=payload)

async def update(
Expand All @@ -463,6 +469,7 @@ async def update(
graph_id: Optional[str] = None,
config: Optional[Config] = None,
metadata: Json = None,
name: Optional[str] = None,
) -> Assistant:
"""Update an assistant.

Expand Down Expand Up @@ -495,6 +502,8 @@ async def update(
payload["config"] = config
if metadata:
payload["metadata"] = metadata
if name:
payload["name"] = name
return await self.http.patch(
f"/assistants/{assistant_id}",
json=payload,
Expand Down Expand Up @@ -563,6 +572,64 @@ async def search(
json=payload,
)

async def get_versions(
self,
assistant_id: str,
metadata: Json = None,
limit: int = 10,
offset: int = 0,
) -> list[AssistantVersion]:
"""List all versions of an assistant.

Args:
assistant_id: The assistant ID to delete.

Returns:
list[Assistant]: A list of assistants.

Example Usage:

assistant_versions = await client.assistants.get_versions(
assistant_id="my_assistant_id"
)

""" # noqa: E501

payload: Dict[str, Any] = {
"limit": limit,
"offset": offset,
}
if metadata:
payload["metadata"] = metadata
return await self.http.post(
f"/assistants/{assistant_id}/versions", json=payload
)

async def set_latest(self, assistant_id: str, version: int) -> Assistant:
"""Change the version of an assistant.

Args:
assistant_id: The assistant ID to delete.
version: The version to change to.

Returns:
Assistant: Assistant Object.

Example Usage:

new_version_assistant = await client.assistants.set_latest(
assistant_id="my_assistant_id",
version=3
)

""" # noqa: E501

payload: Dict[str, Any] = {"version": version}

return await self.http.post(
f"/assistants/{assistant_id}/set_latest", json=payload
)


class ThreadsClient:
def __init__(self, http: HttpClient) -> None:
Expand Down
23 changes: 19 additions & 4 deletions libs/sdk-py/langgraph_sdk/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ class GraphSchema(TypedDict):
Missing if unable to generate JSON schema from graph."""


class Assistant(TypedDict):
"""Assistant model."""
class AssistantBase(TypedDict):
"""Assistant base model."""

assistant_id: str
"""The ID of the assistant."""
Expand All @@ -68,10 +68,25 @@ class Assistant(TypedDict):
"""The assistant config."""
created_at: datetime
"""The time the assistant was created."""
updated_at: datetime
"""The last time the assistant was updated."""
metadata: Json
"""The assistant metadata."""
version: int
"""The version of the assistant"""


class AssistantVersion(AssistantBase):
"""Assistant version model."""

pass


class Assistant(AssistantBase):
"""Assistant model."""

updated_at: datetime
"""The last time the assistant was updated."""
name: str
"""The name of the assistant"""


class Thread(TypedDict):
Expand Down
Loading