From e0554b72f4fcbc7ae7f38abed7766a2582f86ef6 Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Mon, 13 May 2024 13:59:26 +0300 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=92=A5=20#15=20Apply=20the=20latest?= =?UTF-8?q?=20breaking=20API=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/lang/chat_stream_async.py | 4 ++-- pyproject.toml | 4 ++-- src/glide/exceptions.py | 4 ++-- src/glide/lang/router_async.py | 4 ++-- src/glide/lang/schemas.py | 20 ++++++++++---------- src/glide/schames.py | 2 -- src/glide/typing.py | 2 +- 7 files changed, 19 insertions(+), 21 deletions(-) diff --git a/examples/lang/chat_stream_async.py b/examples/lang/chat_stream_async.py index e8c1c15..5478c81 100644 --- a/examples/lang/chat_stream_async.py +++ b/examples/lang/chat_stream_async.py @@ -40,7 +40,7 @@ async def chat_stream() -> None: continue if err := message.error: - print(f"💥ERR: {err.message} (code: {err.err_code})") + print(f"💥ERR ({err.name}): {err.message}") print("🧹 Restarting the stream") continue @@ -50,7 +50,7 @@ async def chat_stream() -> None: if last_msg and last_msg.chunk and last_msg.finish_reason: # LLM gen context - provider_name = last_msg.chunk.provider_name + provider_name = last_msg.chunk.provider_id model_name = last_msg.chunk.model_name finish_reason = last_msg.finish_reason diff --git a/pyproject.toml b/pyproject.toml index 359fa3a..d2e4c02 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,8 +26,8 @@ requires-python = ">=3.8" [project.urls] Homepage = "https://glide.einstack.ai/" Documentation = "https://glide.einstack.ai/" -Repository = "https://github.com/me/spam.git" -Issues = "https://github.com/EinStack/glide-python" +Repository = "https://github.com/EinStack/glide-py.git" +Issues = "https://github.com/EinStack/glide-py/issues/" [tool.pdm.version] source = "scm" diff --git a/src/glide/exceptions.py b/src/glide/exceptions.py index 3c7d435..5bdc16d 100644 --- a/src/glide/exceptions.py +++ b/src/glide/exceptions.py @@ -29,7 +29,7 @@ class GlideChatStreamError(GlideError): Occurs when chat stream ends with an error """ - def __init__(self, message: str, err_code: str) -> None: + def __init__(self, message: str, err_name: str) -> None: super().__init__(message) - self.err_code = err_code + self.err_name = err_name diff --git a/src/glide/lang/router_async.py b/src/glide/lang/router_async.py index 1d1b15b..f10ce42 100644 --- a/src/glide/lang/router_async.py +++ b/src/glide/lang/router_async.py @@ -82,8 +82,8 @@ async def chat_stream( if err := message.ended_with_err: # fail only on fatal errors that indicate stream stop raise GlideChatStreamError( - f"Chat stream {req.id} ended with an error: {err.message} (code: {err.err_code})", - err.err_code, + f"Chat stream {req.id} ended with an error ({err.name}): {err.message}", + err.name, ) yield message # returns content chunk and some error messages diff --git a/src/glide/lang/schemas.py b/src/glide/lang/schemas.py index 63e7b13..10549d1 100644 --- a/src/glide/lang/schemas.py +++ b/src/glide/lang/schemas.py @@ -8,7 +8,7 @@ from pydantic import Field from glide.schames import Schema -from glide.typing import RouterId, ProviderName, ModelName +from glide.typing import RouterId, ProviderId, ModelName ChatRequestId = str Metadata = Dict[str, Any] @@ -45,7 +45,7 @@ class ModelMessageOverride(Schema): class ChatRequest(Schema): message: ChatMessage message_history: List[ChatMessage] = Field(default_factory=list) - override: Optional[ModelMessageOverride] = None + override_params: Optional[ModelMessageOverride] = None class TokenUsage(Schema): @@ -57,16 +57,16 @@ class TokenUsage(Schema): class ModelResponse(Schema): response_id: Dict[str, str] message: ChatMessage - token_count: TokenUsage + token_usage: TokenUsage class ChatResponse(Schema): id: ChatRequestId - created: datetime - provider: ProviderName - router: RouterId + created_at: datetime + provider_id: ProviderId + router_id: RouterId model_id: str - model: ModelName + model_name: ModelName model_response: ModelResponse @@ -74,7 +74,7 @@ class ChatStreamRequest(Schema): id: ChatRequestId = Field(default_factory=lambda: str(uuid.uuid4())) message: ChatMessage message_history: List[ChatMessage] = Field(default_factory=list) - override: Optional[ModelMessageOverride] = None + override_params: Optional[ModelMessageOverride] = None metadata: Optional[Metadata] = None @@ -90,7 +90,7 @@ class ChatStreamChunk(Schema): model_id: str - provider_name: ProviderName + provider_id: ProviderId model_name: ModelName model_response: ModelChunkResponse @@ -99,7 +99,7 @@ class ChatStreamChunk(Schema): class ChatStreamError(Schema): id: ChatRequestId - err_code: str + name: str message: str finish_reason: Optional[FinishReason] = None diff --git a/src/glide/schames.py b/src/glide/schames.py index e37f9ab..5902a49 100644 --- a/src/glide/schames.py +++ b/src/glide/schames.py @@ -1,7 +1,6 @@ # Copyright EinStack # SPDX-License-Identifier: APACHE-2.0 from pydantic import BaseModel, ConfigDict -from pydantic.alias_generators import to_camel class Schema(BaseModel): @@ -10,7 +9,6 @@ class Schema(BaseModel): """ model_config = ConfigDict( - alias_generator=to_camel, populate_by_name=True, from_attributes=True, protected_namespaces=(), diff --git a/src/glide/typing.py b/src/glide/typing.py index 49916ea..5d068c2 100644 --- a/src/glide/typing.py +++ b/src/glide/typing.py @@ -2,5 +2,5 @@ # SPDX-License-Identifier: APACHE-2.0 RouterId = str -ProviderName = str +ProviderId = str ModelName = str From cb86385994390914b4d4ca08ce3ec74183bc5c4c Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Mon, 13 May 2024 14:04:55 +0300 Subject: [PATCH 2/5] #15: Added logging on client task cancelation --- src/glide/lang/router_async.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/glide/lang/router_async.py b/src/glide/lang/router_async.py index f10ce42..9c0b99a 100644 --- a/src/glide/lang/router_async.py +++ b/src/glide/lang/router_async.py @@ -113,7 +113,7 @@ async def _sender(self) -> None: await self._ws_client.send(chat_request.json()) except asyncio.CancelledError: - # TODO: log + logger.debug("chat stream sender task is canceled") break async def _receiver(self) -> None: @@ -136,6 +136,7 @@ async def _receiver(self) -> None: exc_info=True, ) except asyncio.CancelledError: + logger.debug("chat stream receiver task is canceled") break except Exception as e: logger.exception(e) From 97fd6779a3bd833168586faece39ab9c016d73e5 Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Mon, 13 May 2024 14:20:26 +0300 Subject: [PATCH 3/5] #15 Fixed the metadata field name --- src/glide/lang/schemas.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/glide/lang/schemas.py b/src/glide/lang/schemas.py index 10549d1..19ad639 100644 --- a/src/glide/lang/schemas.py +++ b/src/glide/lang/schemas.py @@ -55,7 +55,7 @@ class TokenUsage(Schema): class ModelResponse(Schema): - response_id: Dict[str, str] + metadata: Dict[str, str] message: ChatMessage token_usage: TokenUsage From f7eaad03a6613bf69a8cecbec0762b95a9ab1e10 Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Mon, 13 May 2024 14:50:57 +0300 Subject: [PATCH 4/5] #15: Introduced a new named errors --- src/glide/exceptions.py | 16 ++++++++++++++ src/glide/lang/router_async.py | 39 +++++++++++++++++++++------------- src/glide/lang/schemas.py | 5 +++++ 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/glide/exceptions.py b/src/glide/exceptions.py index 5bdc16d..03cfa63 100644 --- a/src/glide/exceptions.py +++ b/src/glide/exceptions.py @@ -17,6 +17,22 @@ class GlideClientError(GlideError): Occurs when there is an issue with sending a Glide request """ + def __init__(self, message: str, err_name: str) -> None: + super().__init__(message) + + self.err_name = err_name + + +class GlideServerError(GlideError): + """ + Occurs when there is an issue with sending a Glide request related to Glide server issues + """ + + def __init__(self, message: str, err_name: str) -> None: + super().__init__(message) + + self.err_name = err_name + class GlideClientMismatch(GlideError): """ diff --git a/src/glide/lang/router_async.py b/src/glide/lang/router_async.py index 9c0b99a..98edc6c 100644 --- a/src/glide/lang/router_async.py +++ b/src/glide/lang/router_async.py @@ -18,9 +18,15 @@ GlideClientError, GlideClientMismatch, GlideChatStreamError, + GlideServerError, ) from glide.lang import schemas -from glide.lang.schemas import ChatStreamRequest, ChatStreamMessage, ChatRequestId +from glide.lang.schemas import ( + ChatStreamRequest, + ChatStreamMessage, + ChatRequestId, + ChatError, +) from glide.logging import logger from glide.typing import RouterId @@ -214,33 +220,36 @@ async def chat( """ Send a chat request to a specified language router """ - try: - headers = {} + headers = {} - if self._user_agent: - headers["User-Agent"] = self._user_agent + if self._user_agent: + headers["User-Agent"] = self._user_agent + try: resp = await self._http_client.post( f"/language/{router_id}/chat", headers=headers, json=request.dict(by_alias=True), ) - except httpx.NetworkError as e: - raise GlideUnavailable() from e + if resp.is_error: + err_data = ChatError(**resp.json()) - if not resp.is_success: - raise GlideClientError( - f"Failed to send a chat request: {resp.text} (status_code: {resp.status_code})" - ) + if resp.is_client_error: + raise GlideClientError(err_data.message, err_data.name) - try: - raw_response = resp.json() + if resp.is_server_error: + raise GlideServerError(err_data.message, err_data.name) + + raw_resp = resp.json() - return schemas.ChatResponse(**raw_response) + return schemas.ChatResponse(**raw_resp) + except httpx.NetworkError as e: + raise GlideUnavailable() from e except pydantic.ValidationError as err: raise GlideClientMismatch( - "Failed to validate Glide API response. Please make sure Glide API and client versions are compatible" + "Failed to validate Glide API response. " + "Please make sure Glide API and client versions are compatible" ) from err def stream_client(self, router_id: RouterId) -> AsyncStreamChatClient: diff --git a/src/glide/lang/schemas.py b/src/glide/lang/schemas.py index 19ad639..6c3913c 100644 --- a/src/glide/lang/schemas.py +++ b/src/glide/lang/schemas.py @@ -14,6 +14,11 @@ Metadata = Dict[str, Any] +class ChatError(Schema): + name: str + message: str + + class FinishReason(str, Enum): # generation is finished successfully without interruptions COMPLETE = "complete" From cdf80f50b49b6eed27d3b9275fd2a761e35e905a Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Mon, 13 May 2024 14:56:23 +0300 Subject: [PATCH 5/5] #15: allowed to run the notification workflow on PR created from forks --- .github/workflows/activity-notifications.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/activity-notifications.yaml b/.github/workflows/activity-notifications.yaml index 9606641..1dd6ea2 100644 --- a/.github/workflows/activity-notifications.yaml +++ b/.github/workflows/activity-notifications.yaml @@ -1,7 +1,7 @@ name: Pull Request Activity Notifications on: - pull_request: + pull_request_target: types: [opened, closed, reopened] jobs: