From 8b95adb1bdda2ca7459b119e38f77ce4077f4351 Mon Sep 17 00:00:00 2001 From: Isaac Francisco <78627776+isahers1@users.noreply.github.com> Date: Fri, 20 Sep 2024 16:48:19 -0700 Subject: [PATCH] sdk-py: add versioning for assistants (#1665) * add get_versions to python sdk * fml * add change_version to sdk * add assistant name to create * document assistant name * change method * version in payload * fml * add js methods and types * name -> assistant_name * export onconflictbehavior * add assistant name to create * add metadata/limit/offset to sdk * add assistant_name to update * assistantversion schema * export assistnatversion * add metadata/limit/offset to sdk * assistantversion schema * fmt * fmt * change version -> set version * fmt * assistant_name -> name * naming --- libs/sdk-js/src/client.ts | 46 +++++++++++++++++++ libs/sdk-js/src/index.ts | 3 ++ libs/sdk-js/src/schema.ts | 11 ++++- libs/sdk-py/langgraph_sdk/client.py | 69 ++++++++++++++++++++++++++++- libs/sdk-py/langgraph_sdk/schema.py | 23 ++++++++-- 5 files changed, 145 insertions(+), 7 deletions(-) diff --git a/libs/sdk-js/src/client.ts b/libs/sdk-js/src/client.ts index 76473a531..ceceaf271 100644 --- a/libs/sdk-js/src/client.ts +++ b/libs/sdk-js/src/client.ts @@ -9,6 +9,7 @@ import { Thread, ThreadState, Cron, + AssistantVersion, } from "./schema.js"; import { AsyncCaller, AsyncCallerParams } from "./utils/async_caller.js"; import { @@ -244,6 +245,7 @@ export class AssistantsClient extends BaseClient { metadata?: Metadata; assistantId?: string; ifExists?: OnConflictBehavior; + name?: string; }): Promise { return this.fetch("/assistants", { method: "POST", @@ -253,6 +255,7 @@ export class AssistantsClient extends BaseClient { metadata: payload.metadata, assistant_id: payload.assistantId, if_exists: payload.ifExists, + name: payload.name, }, }); } @@ -269,6 +272,7 @@ export class AssistantsClient extends BaseClient { graphId?: string; config?: Config; metadata?: Metadata; + name?: string; }, ): Promise { return this.fetch(`/assistants/${assistantId}`, { @@ -277,6 +281,7 @@ export class AssistantsClient extends BaseClient { graph_id: payload.graphId, config: payload.config, metadata: payload.metadata, + name: payload.name, }, }); } @@ -313,6 +318,47 @@ export class AssistantsClient extends BaseClient { }, }); } + + /** + * 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 { + return this.fetch( + `/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 { + return this.fetch(`/assistants/${assistantId}/set_latest`, { + method: "POST", + json: { version }, + }); + } } export class ThreadsClient extends BaseClient { diff --git a/libs/sdk-js/src/index.ts b/libs/sdk-js/src/index.ts index 793f8d4f7..1f7e7948a 100644 --- a/libs/sdk-js/src/index.ts +++ b/libs/sdk-js/src/index.ts @@ -2,6 +2,7 @@ export { Client } from "./client.js"; export type { Assistant, + AssistantVersion, AssistantGraph, Config, DefaultValues, @@ -12,3 +13,5 @@ export type { ThreadState, Cron, } from "./schema.js"; + +export type { OnConflictBehavior } from "./types.js"; diff --git a/libs/sdk-js/src/schema.ts b/libs/sdk-js/src/schema.ts index 1d772b7eb..e25aff0c3 100644 --- a/libs/sdk-js/src/schema.ts +++ b/libs/sdk-js/src/schema.ts @@ -75,13 +75,20 @@ export interface GraphSchema { export type Metadata = Optional>; -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>>; diff --git a/libs/sdk-py/langgraph_sdk/client.py b/libs/sdk-py/langgraph_sdk/client.py index f6d30d0e9..f92ed2961 100644 --- a/libs/sdk-py/langgraph_sdk/client.py +++ b/libs/sdk-py/langgraph_sdk/client.py @@ -23,6 +23,7 @@ import langgraph_sdk from langgraph_sdk.schema import ( Assistant, + AssistantVersion, Config, Cron, DisconnectMode, @@ -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. @@ -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. @@ -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] = { @@ -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( @@ -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. @@ -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, @@ -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: diff --git a/libs/sdk-py/langgraph_sdk/schema.py b/libs/sdk-py/langgraph_sdk/schema.py index 5f58f02c2..f99a71fc8 100644 --- a/libs/sdk-py/langgraph_sdk/schema.py +++ b/libs/sdk-py/langgraph_sdk/schema.py @@ -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.""" @@ -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):