Remove client.chat resource (#105)
This was always temporary, but we are finally removing the chat resource from the ``Arcade`` and ``AsyncArcade`` clients.
This commit is contained in:
parent
6b716d6dde
commit
ff092ac303
6 changed files with 30 additions and 38 deletions
|
|
@ -8,7 +8,7 @@ from typing import Any, Optional
|
|||
from urllib.parse import urlencode
|
||||
|
||||
import typer
|
||||
from openai import OpenAIError
|
||||
from openai import OpenAI, OpenAIError
|
||||
from rich.console import Console
|
||||
from rich.markup import escape
|
||||
from rich.text import Text
|
||||
|
|
@ -256,7 +256,10 @@ def chat(
|
|||
history.append({"role": "user", "content": user_input})
|
||||
|
||||
try:
|
||||
chat_result = handle_chat_interaction(client, model, history, user_email, stream)
|
||||
openai_client = OpenAI(api_key=config.api.key, base_url=config.engine_url)
|
||||
chat_result = handle_chat_interaction(
|
||||
openai_client, model, history, user_email, stream
|
||||
)
|
||||
except OpenAIError as e:
|
||||
console.print(f"❌ Arcade Chat failed with error: {e!s}", style="bold red")
|
||||
continue
|
||||
|
|
@ -273,7 +276,7 @@ def chat(
|
|||
try:
|
||||
history.pop()
|
||||
chat_result = handle_chat_interaction(
|
||||
client, model, history, user_email, stream
|
||||
openai_client, model, history, user_email, stream
|
||||
)
|
||||
except OpenAIError as e:
|
||||
console.print(f"❌ Arcade Chat failed with error: {e!s}", style="bold red")
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ from pathlib import Path
|
|||
from typing import Callable, Union
|
||||
|
||||
import typer
|
||||
from openai import OpenAI
|
||||
from openai.resources.chat.completions import ChatCompletionChunk, Stream
|
||||
from openai.types.chat.chat_completion import Choice as ChatCompletionChoice
|
||||
from openai.types.chat.chat_completion_chunk import Choice as ChatCompletionChunkChoice
|
||||
|
|
@ -247,7 +248,7 @@ class ChatInteractionResult:
|
|||
|
||||
|
||||
def handle_chat_interaction(
|
||||
client: Arcade, model: str, history: list[dict], user_email: str | None, stream: bool = False
|
||||
client: OpenAI, model: str, history: list[dict], user_email: str | None, stream: bool = False
|
||||
) -> ChatInteractionResult:
|
||||
"""
|
||||
Handle a single chat-request/chat-response interaction for both streamed and non-streamed responses.
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ from arcade.client.errors import (
|
|||
RateLimitError,
|
||||
UnauthorizedError,
|
||||
)
|
||||
from arcade.client.schema import OPENAI_API_VERSION
|
||||
|
||||
T = TypeVar("T")
|
||||
ResponseT = TypeVar("ResponseT")
|
||||
|
|
@ -22,11 +21,15 @@ ResponseT = TypeVar("ResponseT")
|
|||
class BaseResource(Generic[T]):
|
||||
"""Base class for all resources."""
|
||||
|
||||
_path: str
|
||||
_path: str = ""
|
||||
_version: str = "v1"
|
||||
|
||||
def __init__(self, client: T) -> None:
|
||||
self._client = client
|
||||
self._resource_path = self._client._base_url + self._path # type: ignore[attr-defined]
|
||||
self._resource_path = urljoin(
|
||||
self._client._base_url, # type: ignore[attr-defined]
|
||||
f"{self._version}/{self._path}",
|
||||
)
|
||||
|
||||
|
||||
class BaseArcadeClient:
|
||||
|
|
@ -37,8 +40,8 @@ class BaseArcadeClient:
|
|||
base_url: str | None = None,
|
||||
api_key: str | None = None,
|
||||
headers: dict[str, str] | None = None,
|
||||
timeout: float | Timeout = 10.0,
|
||||
retries: int = 3,
|
||||
timeout: float | Timeout = 30.0,
|
||||
retries: int = 1,
|
||||
):
|
||||
"""
|
||||
Initialize the BaseArcadeClient.
|
||||
|
|
@ -70,12 +73,6 @@ class BaseArcadeClient:
|
|||
"""
|
||||
return urljoin(self._base_url, path)
|
||||
|
||||
def _chat_url(self, base_url: str) -> str:
|
||||
chat_url = str(base_url)
|
||||
if not base_url.endswith(OPENAI_API_VERSION):
|
||||
chat_url = f"{base_url}/{OPENAI_API_VERSION}"
|
||||
return chat_url
|
||||
|
||||
def _handle_http_error(self, e: httpx.HTTPStatusError) -> None:
|
||||
error_map = {
|
||||
400: BadRequestError,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import json
|
||||
from typing import Any, TypeVar, Union
|
||||
|
||||
from httpx import Timeout
|
||||
from openai import AsyncOpenAI, OpenAI
|
||||
from openai.resources.chat import AsyncChat, Chat
|
||||
|
||||
from arcade.client.base import (
|
||||
AsyncArcadeClient,
|
||||
|
|
@ -120,7 +119,7 @@ class ToolResource(BaseResource[ClientT]):
|
|||
tool_name: str,
|
||||
user_id: str,
|
||||
tool_version: str | None = None,
|
||||
inputs: dict[str, Any] | None = None,
|
||||
inputs: dict[str, Any] | str | None = None,
|
||||
) -> ExecuteToolResponse:
|
||||
"""
|
||||
Send a request to execute a tool and return the response.
|
||||
|
|
@ -131,6 +130,12 @@ class ToolResource(BaseResource[ClientT]):
|
|||
tool_version: The version of the tool to execute (if not provided, the latest version will be used).
|
||||
inputs: The inputs for the tool.
|
||||
"""
|
||||
if not isinstance(inputs, str):
|
||||
try:
|
||||
inputs = json.dumps(inputs)
|
||||
except Exception:
|
||||
raise ValueError("Inputs must be a valid JSON object or serializable dictionary")
|
||||
|
||||
request_data = {
|
||||
"tool_name": tool_name,
|
||||
"user_id": user_id,
|
||||
|
|
@ -399,12 +404,6 @@ class Arcade(SyncArcadeClient):
|
|||
self.auth: AuthResource = AuthResource(self)
|
||||
self.tools: ToolResource = ToolResource(self)
|
||||
self.health: HealthResource = HealthResource(self)
|
||||
chat_url = self._chat_url(self._base_url)
|
||||
self._openai_client = OpenAI(base_url=chat_url, api_key=self._api_key)
|
||||
|
||||
@property
|
||||
def chat(self) -> Chat:
|
||||
return self._openai_client.chat
|
||||
|
||||
def _execute_request(self, method: str, url: str, **kwargs: Any) -> Any:
|
||||
"""
|
||||
|
|
@ -422,12 +421,6 @@ class AsyncArcade(AsyncArcadeClient):
|
|||
self.auth: AsyncAuthResource = AsyncAuthResource(self)
|
||||
self.tools: AsyncToolResource = AsyncToolResource(self)
|
||||
self.health: AsyncHealthResource = AsyncHealthResource(self)
|
||||
chat_url = self._chat_url(self._base_url)
|
||||
self._openai_client = AsyncOpenAI(base_url=chat_url, api_key=self._api_key)
|
||||
|
||||
@property
|
||||
def chat(self) -> AsyncChat:
|
||||
return self._openai_client.chat
|
||||
|
||||
async def _execute_request(self, method: str, url: str, **kwargs: Any) -> Any:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
import os
|
||||
from enum import Enum
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from arcade.core.schema import ToolAuthorizationContext, ToolCallOutput
|
||||
|
||||
OPENAI_API_VERSION = os.getenv("OPENAI_API_VERSION", "v1")
|
||||
|
||||
|
||||
class AuthProvider(str, Enum):
|
||||
google = "google"
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ except ImportError:
|
|||
"Use `pip install arcade-ai[evals]` to install the required dependencies for evaluation."
|
||||
)
|
||||
|
||||
from arcade.client.client import AsyncArcade
|
||||
from openai import AsyncOpenAI
|
||||
|
||||
from arcade.sdk.error import WeightError
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -520,12 +521,12 @@ class EvalSuite:
|
|||
)
|
||||
self.cases.append(new_case)
|
||||
|
||||
async def run(self, client: AsyncArcade, model: str) -> dict[str, Any]:
|
||||
async def run(self, client: AsyncOpenAI, model: str) -> dict[str, Any]:
|
||||
"""
|
||||
Run the evaluation suite.
|
||||
|
||||
Args:
|
||||
client: The AsyncArcade client instance.
|
||||
client: The AsyncOpenAI client instance.
|
||||
model: The model to evaluate.
|
||||
|
||||
Returns:
|
||||
|
|
@ -651,11 +652,11 @@ def tool_eval() -> Callable[[Callable], Callable]:
|
|||
raise TypeError("Eval function must return an EvalSuite")
|
||||
suite.max_concurrent = max_concurrency
|
||||
results = []
|
||||
async with AsyncArcade(
|
||||
async with AsyncOpenAI(
|
||||
api_key=config.api.key,
|
||||
base_url=config.engine_url,
|
||||
) as client:
|
||||
result = await suite.run(client, model) # type: ignore[arg-type]
|
||||
result = await suite.run(client, model)
|
||||
results.append(result)
|
||||
return results
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue