fix: Fix import sort violations in hanzoai package

- Fix 9 I001 import block violations
- pkg/hanzoai/__init__.py
- pkg/hanzoai/grpo/*.py (6 files)
- tests/test_memory.py
- tests/test_signal_handling.py
- Also format all hanzoai files
This commit is contained in:
2025-12-09 16:04:55 -08:00
parent 93fbf2cb82
commit f630ab1cf3
97 changed files with 789 additions and 1878 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
# Import new modules
from . import mcp, auth, types, agents, cluster, grpo
from . import mcp, auth, grpo, types, agents, cluster
from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes
from ._utils import file_from_path
from ._client import (
+31 -99
View File
@@ -240,9 +240,7 @@ class BaseSyncPage(BasePage[_T], Generic[_T]):
)
options = self._info_to_options(info)
return self._client._request_api_list(
self._model, page=self.__class__, options=options
)
return self._client._request_api_list(self._model, page=self.__class__, options=options)
class AsyncPaginator(Generic[_T, AsyncPageT]):
@@ -322,9 +320,7 @@ class BaseAsyncPage(BasePage[_T], Generic[_T]):
)
options = self._info_to_options(info)
return await self._client._request_api_list(
self._model, page=self.__class__, options=options
)
return await self._client._request_api_list(self._model, page=self.__class__, options=options)
_HttpxClientT = TypeVar("_HttpxClientT", bound=Union[httpx.Client, httpx.AsyncClient])
@@ -403,9 +399,7 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
) -> _exceptions.APIStatusError:
raise NotImplementedError()
def _build_headers(
self, options: FinalRequestOptions, *, retries_taken: int = 0
) -> httpx.Headers:
def _build_headers(self, options: FinalRequestOptions, *, retries_taken: int = 0) -> httpx.Headers:
custom_headers = options.headers or {}
headers_dict = _merge_mappings(self.default_headers, custom_headers)
self._validate_headers(headers_dict, custom_headers)
@@ -414,14 +408,8 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
headers = httpx.Headers(headers_dict)
idempotency_header = self._idempotency_header
if (
idempotency_header
and options.method.lower() != "get"
and idempotency_header not in headers
):
headers[idempotency_header] = (
options.idempotency_key or self._idempotency_key()
)
if idempotency_header and options.method.lower() != "get" and idempotency_header not in headers:
headers[idempotency_header] = options.idempotency_key or self._idempotency_key()
# Don't set these headers if they were already set or removed by the caller. We check
# `custom_headers`, which can contain `Omit()`, instead of `headers` to account for the removal case.
@@ -429,11 +417,7 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
if "x-stainless-retry-count" not in lower_custom_headers:
headers["x-stainless-retry-count"] = str(retries_taken)
if "x-stainless-read-timeout" not in lower_custom_headers:
timeout = (
self.timeout
if isinstance(options.timeout, NotGiven)
else options.timeout
)
timeout = self.timeout if isinstance(options.timeout, NotGiven) else options.timeout
if isinstance(timeout, Timeout):
timeout = timeout.read
if timeout is not None:
@@ -475,9 +459,7 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
elif is_mapping(json_data):
json_data = _merge_mappings(json_data, options.extra_json)
else:
raise RuntimeError(
f"Unexpected JSON data type, {type(json_data)}, cannot merge with `extra_body`"
)
raise RuntimeError(f"Unexpected JSON data type, {type(json_data)}, cannot merge with `extra_body`")
headers = self._build_headers(options, retries_taken=retries_taken)
params = _merge_mappings(self.default_query, options.params)
@@ -521,28 +503,20 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
# TODO: report this error to httpx
return self._client.build_request( # pyright: ignore[reportUnknownMemberType]
headers=headers,
timeout=(
self.timeout
if isinstance(options.timeout, NotGiven)
else options.timeout
),
timeout=(self.timeout if isinstance(options.timeout, NotGiven) else options.timeout),
method=options.method,
url=prepared_url,
# the `Query` type that we use is incompatible with qs'
# `Params` type as it needs to be typed as `Mapping[str, object]`
# so that passing a `TypedDict` doesn't cause an error.
# https://github.com/microsoft/pyright/issues/3526#event-6715453066
params=(
self.qs.stringify(cast(Mapping[str, Any], params)) if params else None
),
params=(self.qs.stringify(cast(Mapping[str, Any], params)) if params else None),
json=json_data if is_given(json_data) else None,
files=files,
**kwargs,
)
def _serialize_multipartform(
self, data: Mapping[object, object]
) -> dict[str, object]:
def _serialize_multipartform(self, data: Mapping[object, object]) -> dict[str, object]:
items = self.qs.stringify_items(
# TODO: type ignore is required as stringify_items is well typed but we can't be
# well typed without heavy validation.
@@ -572,9 +546,7 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
return serialized
def _maybe_override_cast_to(
self, cast_to: type[ResponseT], options: FinalRequestOptions
) -> type[ResponseT]:
def _maybe_override_cast_to(self, cast_to: type[ResponseT], options: FinalRequestOptions) -> type[ResponseT]:
if not is_given(options.headers):
return cast_to
@@ -668,9 +640,7 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
@base_url.setter
def base_url(self, url: URL | str) -> None:
self._base_url = self._enforce_trailing_slash(
url if isinstance(url, URL) else URL(url)
)
self._base_url = self._enforce_trailing_slash(url if isinstance(url, URL) else URL(url))
def platform_headers(self) -> Dict[str, str]:
# the actual implementation is in a separate `lru_cache` decorated
@@ -678,9 +648,7 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
# https://github.com/python/cpython/issues/88476
return platform_headers(self._version, platform=self._platform)
def _parse_retry_after_header(
self, response_headers: Optional[httpx.Headers] = None
) -> float | None:
def _parse_retry_after_header(self, response_headers: Optional[httpx.Headers] = None) -> float | None:
"""Returns a float of the number of seconds (not milliseconds) to wait after retrying, or None if unspecified.
About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
@@ -837,9 +805,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
else:
timeout = DEFAULT_TIMEOUT
if http_client is not None and not isinstance(
http_client, httpx.Client
): # pyright: ignore[reportUnnecessaryIsInstance]
if http_client is not None and not isinstance(http_client, httpx.Client): # pyright: ignore[reportUnnecessaryIsInstance]
raise TypeError(
f"Invalid `http_client` argument; Expected an instance of `httpx.Client` but got {type(http_client)}"
)
@@ -944,9 +910,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
stream_cls: type[_StreamT] | None = None,
) -> ResponseT | _StreamT:
if remaining_retries is not None:
retries_taken = (
options.get_max_retries(self.max_retries) - remaining_retries
)
retries_taken = options.get_max_retries(self.max_retries) - remaining_retries
else:
retries_taken = 0
@@ -1080,9 +1044,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
else:
log.debug("%i retries left", remaining_retries)
timeout = self._calculate_retry_timeout(
remaining_retries, options, response_headers
)
timeout = self._calculate_retry_timeout(remaining_retries, options, response_headers)
log.info("Retrying request to %s in %f seconds", options.url, timeout)
# In a synchronous context we are blocking the entire thread. Up to the library user to run the client in a
@@ -1111,9 +1073,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
if inspect.isclass(origin) and issubclass(origin, BaseAPIResponse):
if not issubclass(origin, APIResponse):
raise TypeError(
f"API Response types must subclass {APIResponse}; Received {origin}"
)
raise TypeError(f"API Response types must subclass {APIResponse}; Received {origin}")
response_cls = cast("type[BaseAPIResponse[Any]]", cast_to)
return cast(
@@ -1135,9 +1095,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
api_response = APIResponse(
raw=response,
client=self,
cast_to=cast(
"type[ResponseT]", cast_to
), # pyright: ignore[reportUnnecessaryCast]
cast_to=cast("type[ResponseT]", cast_to), # pyright: ignore[reportUnnecessaryCast]
stream=stream,
stream_cls=stream_cls,
options=options,
@@ -1210,9 +1168,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
opts = FinalRequestOptions.construct(method="get", url=path, **options)
# cast is required because mypy complains about returning Any even though
# it understands the type variables
return cast(
ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)
)
return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))
@overload
def post(
@@ -1270,9 +1226,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
files=to_httpx_files(files),
**options,
)
return cast(
ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)
)
return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))
def patch(
self,
@@ -1282,9 +1236,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
body: Body | None = None,
options: RequestOptions = {},
) -> ResponseT:
opts = FinalRequestOptions.construct(
method="patch", url=path, json_data=body, **options
)
opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, **options)
return self.request(cast_to, opts)
def put(
@@ -1313,9 +1265,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
body: Body | None = None,
options: RequestOptions = {},
) -> ResponseT:
opts = FinalRequestOptions.construct(
method="delete", url=path, json_data=body, **options
)
opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, **options)
return self.request(cast_to, opts)
def get_api_list(
@@ -1328,9 +1278,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
options: RequestOptions = {},
method: str = "get",
) -> SyncPageT:
opts = FinalRequestOptions.construct(
method=method, url=path, json_data=body, **options
)
opts = FinalRequestOptions.construct(method=method, url=path, json_data=body, **options)
return self._request_api_list(model, page, opts)
@@ -1395,9 +1343,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
else:
timeout = DEFAULT_TIMEOUT
if http_client is not None and not isinstance(
http_client, httpx.AsyncClient
): # pyright: ignore[reportUnnecessaryIsInstance]
if http_client is not None and not isinstance(http_client, httpx.AsyncClient): # pyright: ignore[reportUnnecessaryIsInstance]
raise TypeError(
f"Invalid `http_client` argument; Expected an instance of `httpx.AsyncClient` but got {type(http_client)}"
)
@@ -1499,9 +1445,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
remaining_retries: Optional[int] = None,
) -> ResponseT | _AsyncStreamT:
if remaining_retries is not None:
retries_taken = (
options.get_max_retries(self.max_retries) - remaining_retries
)
retries_taken = options.get_max_retries(self.max_retries) - remaining_retries
else:
retries_taken = 0
@@ -1637,9 +1581,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
else:
log.debug("%i retries left", remaining_retries)
timeout = self._calculate_retry_timeout(
remaining_retries, options, response_headers
)
timeout = self._calculate_retry_timeout(remaining_retries, options, response_headers)
log.info("Retrying request to %s in %f seconds", options.url, timeout)
await anyio.sleep(timeout)
@@ -1666,9 +1608,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
if inspect.isclass(origin) and issubclass(origin, BaseAPIResponse):
if not issubclass(origin, AsyncAPIResponse):
raise TypeError(
f"API Response types must subclass {AsyncAPIResponse}; Received {origin}"
)
raise TypeError(f"API Response types must subclass {AsyncAPIResponse}; Received {origin}")
response_cls = cast("type[BaseAPIResponse[Any]]", cast_to)
return cast(
@@ -1690,9 +1630,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
api_response = AsyncAPIResponse(
raw=response,
client=self,
cast_to=cast(
"type[ResponseT]", cast_to
), # pyright: ignore[reportUnnecessaryCast]
cast_to=cast("type[ResponseT]", cast_to), # pyright: ignore[reportUnnecessaryCast]
stream=stream,
stream_cls=stream_cls,
options=options,
@@ -1821,9 +1759,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
body: Body | None = None,
options: RequestOptions = {},
) -> ResponseT:
opts = FinalRequestOptions.construct(
method="patch", url=path, json_data=body, **options
)
opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, **options)
return await self.request(cast_to, opts)
async def put(
@@ -1852,9 +1788,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
body: Body | None = None,
options: RequestOptions = {},
) -> ResponseT:
opts = FinalRequestOptions.construct(
method="delete", url=path, json_data=body, **options
)
opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, **options)
return await self.request(cast_to, opts)
def get_api_list(
@@ -1867,9 +1801,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
options: RequestOptions = {},
method: str = "get",
) -> AsyncPaginator[_T, AsyncPageT]:
opts = FinalRequestOptions.construct(
method=method, url=path, json_data=body, **options
)
opts = FinalRequestOptions.construct(method=method, url=path, json_data=body, **options)
return self._request_api_list(model, page, opts)
+71 -215
View File
@@ -208,9 +208,7 @@ class Hanzo(SyncAPIClient):
base_url_env = os.environ.get("HANZO_BASE_URL")
if is_given(base_url) and base_url is not None:
# cast required because mypy doesn't understand the type narrowing
base_url = cast(
"str | httpx.URL", base_url
) # pyright: ignore[reportUnnecessaryCast]
base_url = cast("str | httpx.URL", base_url) # pyright: ignore[reportUnnecessaryCast]
elif is_given(environment):
if base_url_env and base_url is not None:
raise ValueError(
@@ -332,14 +330,10 @@ class Hanzo(SyncAPIClient):
Create a new client instance re-using the same options given to the current client with optional overriding.
"""
if default_headers is not None and set_default_headers is not None:
raise ValueError(
"The `default_headers` and `set_default_headers` arguments are mutually exclusive"
)
raise ValueError("The `default_headers` and `set_default_headers` arguments are mutually exclusive")
if default_query is not None and set_default_query is not None:
raise ValueError(
"The `default_query` and `set_default_query` arguments are mutually exclusive"
)
raise ValueError("The `default_query` and `set_default_query` arguments are mutually exclusive")
headers = self._custom_headers
if default_headers is not None:
@@ -404,14 +398,10 @@ class Hanzo(SyncAPIClient):
return _exceptions.BadRequestError(err_msg, response=response, body=body)
if response.status_code == 401:
return _exceptions.AuthenticationError(
err_msg, response=response, body=body
)
return _exceptions.AuthenticationError(err_msg, response=response, body=body)
if response.status_code == 403:
return _exceptions.PermissionDeniedError(
err_msg, response=response, body=body
)
return _exceptions.PermissionDeniedError(err_msg, response=response, body=body)
if response.status_code == 404:
return _exceptions.NotFoundError(err_msg, response=response, body=body)
@@ -420,17 +410,13 @@ class Hanzo(SyncAPIClient):
return _exceptions.ConflictError(err_msg, response=response, body=body)
if response.status_code == 422:
return _exceptions.UnprocessableEntityError(
err_msg, response=response, body=body
)
return _exceptions.UnprocessableEntityError(err_msg, response=response, body=body)
if response.status_code == 429:
return _exceptions.RateLimitError(err_msg, response=response, body=body)
if response.status_code >= 500:
return _exceptions.InternalServerError(
err_msg, response=response, body=body
)
return _exceptions.InternalServerError(err_msg, response=response, body=body)
return APIStatusError(err_msg, response=response, body=body)
@@ -532,9 +518,7 @@ class AsyncHanzo(AsyncAPIClient):
base_url_env = os.environ.get("HANZO_BASE_URL")
if is_given(base_url) and base_url is not None:
# cast required because mypy doesn't understand the type narrowing
base_url = cast(
"str | httpx.URL", base_url
) # pyright: ignore[reportUnnecessaryCast]
base_url = cast("str | httpx.URL", base_url) # pyright: ignore[reportUnnecessaryCast]
elif is_given(environment):
if base_url_env and base_url is not None:
raise ValueError(
@@ -656,14 +640,10 @@ class AsyncHanzo(AsyncAPIClient):
Create a new client instance re-using the same options given to the current client with optional overriding.
"""
if default_headers is not None and set_default_headers is not None:
raise ValueError(
"The `default_headers` and `set_default_headers` arguments are mutually exclusive"
)
raise ValueError("The `default_headers` and `set_default_headers` arguments are mutually exclusive")
if default_query is not None and set_default_query is not None:
raise ValueError(
"The `default_query` and `set_default_query` arguments are mutually exclusive"
)
raise ValueError("The `default_query` and `set_default_query` arguments are mutually exclusive")
headers = self._custom_headers
if default_headers is not None:
@@ -728,14 +708,10 @@ class AsyncHanzo(AsyncAPIClient):
return _exceptions.BadRequestError(err_msg, response=response, body=body)
if response.status_code == 401:
return _exceptions.AuthenticationError(
err_msg, response=response, body=body
)
return _exceptions.AuthenticationError(err_msg, response=response, body=body)
if response.status_code == 403:
return _exceptions.PermissionDeniedError(
err_msg, response=response, body=body
)
return _exceptions.PermissionDeniedError(err_msg, response=response, body=body)
if response.status_code == 404:
return _exceptions.NotFoundError(err_msg, response=response, body=body)
@@ -744,17 +720,13 @@ class AsyncHanzo(AsyncAPIClient):
return _exceptions.ConflictError(err_msg, response=response, body=body)
if response.status_code == 422:
return _exceptions.UnprocessableEntityError(
err_msg, response=response, body=body
)
return _exceptions.UnprocessableEntityError(err_msg, response=response, body=body)
if response.status_code == 429:
return _exceptions.RateLimitError(err_msg, response=response, body=body)
if response.status_code >= 500:
return _exceptions.InternalServerError(
err_msg, response=response, body=body
)
return _exceptions.InternalServerError(err_msg, response=response, body=body)
return APIStatusError(err_msg, response=response, body=body)
@@ -764,47 +736,29 @@ class HanzoWithRawResponse:
self.openai = openai.OpenAIResourceWithRawResponse(client.openai)
self.engines = engines.EnginesResourceWithRawResponse(client.engines)
self.chat = chat.ChatResourceWithRawResponse(client.chat)
self.completions = completions.CompletionsResourceWithRawResponse(
client.completions
)
self.embeddings = embeddings.EmbeddingsResourceWithRawResponse(
client.embeddings
)
self.completions = completions.CompletionsResourceWithRawResponse(client.completions)
self.embeddings = embeddings.EmbeddingsResourceWithRawResponse(client.embeddings)
self.images = images.ImagesResourceWithRawResponse(client.images)
self.audio = audio.AudioResourceWithRawResponse(client.audio)
self.assistants = assistants.AssistantsResourceWithRawResponse(
client.assistants
)
self.assistants = assistants.AssistantsResourceWithRawResponse(client.assistants)
self.threads = threads.ThreadsResourceWithRawResponse(client.threads)
self.moderations = moderations.ModerationsResourceWithRawResponse(
client.moderations
)
self.moderations = moderations.ModerationsResourceWithRawResponse(client.moderations)
self.utils = utils.UtilsResourceWithRawResponse(client.utils)
self.model = model.ModelResourceWithRawResponse(client.model)
self.model_group = model_group.ModelGroupResourceWithRawResponse(
client.model_group
)
self.model_group = model_group.ModelGroupResourceWithRawResponse(client.model_group)
self.routes = routes.RoutesResourceWithRawResponse(client.routes)
self.responses = responses.ResponsesResourceWithRawResponse(client.responses)
self.batches = batches.BatchesResourceWithRawResponse(client.batches)
self.rerank = rerank.RerankResourceWithRawResponse(client.rerank)
self.fine_tuning = fine_tuning.FineTuningResourceWithRawResponse(
client.fine_tuning
)
self.credentials = credentials.CredentialsResourceWithRawResponse(
client.credentials
)
self.fine_tuning = fine_tuning.FineTuningResourceWithRawResponse(client.fine_tuning)
self.credentials = credentials.CredentialsResourceWithRawResponse(client.credentials)
self.vertex_ai = vertex_ai.VertexAIResourceWithRawResponse(client.vertex_ai)
self.gemini = gemini.GeminiResourceWithRawResponse(client.gemini)
self.cohere = cohere.CohereResourceWithRawResponse(client.cohere)
self.anthropic = anthropic.AnthropicResourceWithRawResponse(client.anthropic)
self.bedrock = bedrock.BedrockResourceWithRawResponse(client.bedrock)
self.eu_assemblyai = eu_assemblyai.EuAssemblyaiResourceWithRawResponse(
client.eu_assemblyai
)
self.assemblyai = assemblyai.AssemblyaiResourceWithRawResponse(
client.assemblyai
)
self.eu_assemblyai = eu_assemblyai.EuAssemblyaiResourceWithRawResponse(client.eu_assemblyai)
self.assemblyai = assemblyai.AssemblyaiResourceWithRawResponse(client.assemblyai)
self.azure = azure.AzureResourceWithRawResponse(client.azure)
self.langfuse = langfuse.LangfuseResourceWithRawResponse(client.langfuse)
self.config = config.ConfigResourceWithRawResponse(client.config)
@@ -815,17 +769,13 @@ class HanzoWithRawResponse:
self.key = key.KeyResourceWithRawResponse(client.key)
self.user = user.UserResourceWithRawResponse(client.user)
self.team = team.TeamResourceWithRawResponse(client.team)
self.organization = organization.OrganizationResourceWithRawResponse(
client.organization
)
self.organization = organization.OrganizationResourceWithRawResponse(client.organization)
self.customer = customer.CustomerResourceWithRawResponse(client.customer)
self.spend = spend.SpendResourceWithRawResponse(client.spend)
self.global_ = global_.GlobalResourceWithRawResponse(client.global_)
self.provider = provider.ProviderResourceWithRawResponse(client.provider)
self.cache = cache.CacheResourceWithRawResponse(client.cache)
self.guardrails = guardrails.GuardrailsResourceWithRawResponse(
client.guardrails
)
self.guardrails = guardrails.GuardrailsResourceWithRawResponse(client.guardrails)
self.add = add.AddResourceWithRawResponse(client.add)
self.delete = delete.DeleteResourceWithRawResponse(client.delete)
self.files = files.FilesResourceWithRawResponse(client.files)
@@ -842,53 +792,29 @@ class AsyncHanzoWithRawResponse:
self.openai = openai.AsyncOpenAIResourceWithRawResponse(client.openai)
self.engines = engines.AsyncEnginesResourceWithRawResponse(client.engines)
self.chat = chat.AsyncChatResourceWithRawResponse(client.chat)
self.completions = completions.AsyncCompletionsResourceWithRawResponse(
client.completions
)
self.embeddings = embeddings.AsyncEmbeddingsResourceWithRawResponse(
client.embeddings
)
self.completions = completions.AsyncCompletionsResourceWithRawResponse(client.completions)
self.embeddings = embeddings.AsyncEmbeddingsResourceWithRawResponse(client.embeddings)
self.images = images.AsyncImagesResourceWithRawResponse(client.images)
self.audio = audio.AsyncAudioResourceWithRawResponse(client.audio)
self.assistants = assistants.AsyncAssistantsResourceWithRawResponse(
client.assistants
)
self.assistants = assistants.AsyncAssistantsResourceWithRawResponse(client.assistants)
self.threads = threads.AsyncThreadsResourceWithRawResponse(client.threads)
self.moderations = moderations.AsyncModerationsResourceWithRawResponse(
client.moderations
)
self.moderations = moderations.AsyncModerationsResourceWithRawResponse(client.moderations)
self.utils = utils.AsyncUtilsResourceWithRawResponse(client.utils)
self.model = model.AsyncModelResourceWithRawResponse(client.model)
self.model_group = model_group.AsyncModelGroupResourceWithRawResponse(
client.model_group
)
self.model_group = model_group.AsyncModelGroupResourceWithRawResponse(client.model_group)
self.routes = routes.AsyncRoutesResourceWithRawResponse(client.routes)
self.responses = responses.AsyncResponsesResourceWithRawResponse(
client.responses
)
self.responses = responses.AsyncResponsesResourceWithRawResponse(client.responses)
self.batches = batches.AsyncBatchesResourceWithRawResponse(client.batches)
self.rerank = rerank.AsyncRerankResourceWithRawResponse(client.rerank)
self.fine_tuning = fine_tuning.AsyncFineTuningResourceWithRawResponse(
client.fine_tuning
)
self.credentials = credentials.AsyncCredentialsResourceWithRawResponse(
client.credentials
)
self.vertex_ai = vertex_ai.AsyncVertexAIResourceWithRawResponse(
client.vertex_ai
)
self.fine_tuning = fine_tuning.AsyncFineTuningResourceWithRawResponse(client.fine_tuning)
self.credentials = credentials.AsyncCredentialsResourceWithRawResponse(client.credentials)
self.vertex_ai = vertex_ai.AsyncVertexAIResourceWithRawResponse(client.vertex_ai)
self.gemini = gemini.AsyncGeminiResourceWithRawResponse(client.gemini)
self.cohere = cohere.AsyncCohereResourceWithRawResponse(client.cohere)
self.anthropic = anthropic.AsyncAnthropicResourceWithRawResponse(
client.anthropic
)
self.anthropic = anthropic.AsyncAnthropicResourceWithRawResponse(client.anthropic)
self.bedrock = bedrock.AsyncBedrockResourceWithRawResponse(client.bedrock)
self.eu_assemblyai = eu_assemblyai.AsyncEuAssemblyaiResourceWithRawResponse(
client.eu_assemblyai
)
self.assemblyai = assemblyai.AsyncAssemblyaiResourceWithRawResponse(
client.assemblyai
)
self.eu_assemblyai = eu_assemblyai.AsyncEuAssemblyaiResourceWithRawResponse(client.eu_assemblyai)
self.assemblyai = assemblyai.AsyncAssemblyaiResourceWithRawResponse(client.assemblyai)
self.azure = azure.AsyncAzureResourceWithRawResponse(client.azure)
self.langfuse = langfuse.AsyncLangfuseResourceWithRawResponse(client.langfuse)
self.config = config.AsyncConfigResourceWithRawResponse(client.config)
@@ -899,17 +825,13 @@ class AsyncHanzoWithRawResponse:
self.key = key.AsyncKeyResourceWithRawResponse(client.key)
self.user = user.AsyncUserResourceWithRawResponse(client.user)
self.team = team.AsyncTeamResourceWithRawResponse(client.team)
self.organization = organization.AsyncOrganizationResourceWithRawResponse(
client.organization
)
self.organization = organization.AsyncOrganizationResourceWithRawResponse(client.organization)
self.customer = customer.AsyncCustomerResourceWithRawResponse(client.customer)
self.spend = spend.AsyncSpendResourceWithRawResponse(client.spend)
self.global_ = global_.AsyncGlobalResourceWithRawResponse(client.global_)
self.provider = provider.AsyncProviderResourceWithRawResponse(client.provider)
self.cache = cache.AsyncCacheResourceWithRawResponse(client.cache)
self.guardrails = guardrails.AsyncGuardrailsResourceWithRawResponse(
client.guardrails
)
self.guardrails = guardrails.AsyncGuardrailsResourceWithRawResponse(client.guardrails)
self.add = add.AsyncAddResourceWithRawResponse(client.add)
self.delete = delete.AsyncDeleteResourceWithRawResponse(client.delete)
self.files = files.AsyncFilesResourceWithRawResponse(client.files)
@@ -926,53 +848,29 @@ class HanzoWithStreamedResponse:
self.openai = openai.OpenAIResourceWithStreamingResponse(client.openai)
self.engines = engines.EnginesResourceWithStreamingResponse(client.engines)
self.chat = chat.ChatResourceWithStreamingResponse(client.chat)
self.completions = completions.CompletionsResourceWithStreamingResponse(
client.completions
)
self.embeddings = embeddings.EmbeddingsResourceWithStreamingResponse(
client.embeddings
)
self.completions = completions.CompletionsResourceWithStreamingResponse(client.completions)
self.embeddings = embeddings.EmbeddingsResourceWithStreamingResponse(client.embeddings)
self.images = images.ImagesResourceWithStreamingResponse(client.images)
self.audio = audio.AudioResourceWithStreamingResponse(client.audio)
self.assistants = assistants.AssistantsResourceWithStreamingResponse(
client.assistants
)
self.assistants = assistants.AssistantsResourceWithStreamingResponse(client.assistants)
self.threads = threads.ThreadsResourceWithStreamingResponse(client.threads)
self.moderations = moderations.ModerationsResourceWithStreamingResponse(
client.moderations
)
self.moderations = moderations.ModerationsResourceWithStreamingResponse(client.moderations)
self.utils = utils.UtilsResourceWithStreamingResponse(client.utils)
self.model = model.ModelResourceWithStreamingResponse(client.model)
self.model_group = model_group.ModelGroupResourceWithStreamingResponse(
client.model_group
)
self.model_group = model_group.ModelGroupResourceWithStreamingResponse(client.model_group)
self.routes = routes.RoutesResourceWithStreamingResponse(client.routes)
self.responses = responses.ResponsesResourceWithStreamingResponse(
client.responses
)
self.responses = responses.ResponsesResourceWithStreamingResponse(client.responses)
self.batches = batches.BatchesResourceWithStreamingResponse(client.batches)
self.rerank = rerank.RerankResourceWithStreamingResponse(client.rerank)
self.fine_tuning = fine_tuning.FineTuningResourceWithStreamingResponse(
client.fine_tuning
)
self.credentials = credentials.CredentialsResourceWithStreamingResponse(
client.credentials
)
self.vertex_ai = vertex_ai.VertexAIResourceWithStreamingResponse(
client.vertex_ai
)
self.fine_tuning = fine_tuning.FineTuningResourceWithStreamingResponse(client.fine_tuning)
self.credentials = credentials.CredentialsResourceWithStreamingResponse(client.credentials)
self.vertex_ai = vertex_ai.VertexAIResourceWithStreamingResponse(client.vertex_ai)
self.gemini = gemini.GeminiResourceWithStreamingResponse(client.gemini)
self.cohere = cohere.CohereResourceWithStreamingResponse(client.cohere)
self.anthropic = anthropic.AnthropicResourceWithStreamingResponse(
client.anthropic
)
self.anthropic = anthropic.AnthropicResourceWithStreamingResponse(client.anthropic)
self.bedrock = bedrock.BedrockResourceWithStreamingResponse(client.bedrock)
self.eu_assemblyai = eu_assemblyai.EuAssemblyaiResourceWithStreamingResponse(
client.eu_assemblyai
)
self.assemblyai = assemblyai.AssemblyaiResourceWithStreamingResponse(
client.assemblyai
)
self.eu_assemblyai = eu_assemblyai.EuAssemblyaiResourceWithStreamingResponse(client.eu_assemblyai)
self.assemblyai = assemblyai.AssemblyaiResourceWithStreamingResponse(client.assemblyai)
self.azure = azure.AzureResourceWithStreamingResponse(client.azure)
self.langfuse = langfuse.LangfuseResourceWithStreamingResponse(client.langfuse)
self.config = config.ConfigResourceWithStreamingResponse(client.config)
@@ -983,17 +881,13 @@ class HanzoWithStreamedResponse:
self.key = key.KeyResourceWithStreamingResponse(client.key)
self.user = user.UserResourceWithStreamingResponse(client.user)
self.team = team.TeamResourceWithStreamingResponse(client.team)
self.organization = organization.OrganizationResourceWithStreamingResponse(
client.organization
)
self.organization = organization.OrganizationResourceWithStreamingResponse(client.organization)
self.customer = customer.CustomerResourceWithStreamingResponse(client.customer)
self.spend = spend.SpendResourceWithStreamingResponse(client.spend)
self.global_ = global_.GlobalResourceWithStreamingResponse(client.global_)
self.provider = provider.ProviderResourceWithStreamingResponse(client.provider)
self.cache = cache.CacheResourceWithStreamingResponse(client.cache)
self.guardrails = guardrails.GuardrailsResourceWithStreamingResponse(
client.guardrails
)
self.guardrails = guardrails.GuardrailsResourceWithStreamingResponse(client.guardrails)
self.add = add.AddResourceWithStreamingResponse(client.add)
self.delete = delete.DeleteResourceWithStreamingResponse(client.delete)
self.files = files.FilesResourceWithStreamingResponse(client.files)
@@ -1010,84 +904,46 @@ class AsyncHanzoWithStreamedResponse:
self.openai = openai.AsyncOpenAIResourceWithStreamingResponse(client.openai)
self.engines = engines.AsyncEnginesResourceWithStreamingResponse(client.engines)
self.chat = chat.AsyncChatResourceWithStreamingResponse(client.chat)
self.completions = completions.AsyncCompletionsResourceWithStreamingResponse(
client.completions
)
self.embeddings = embeddings.AsyncEmbeddingsResourceWithStreamingResponse(
client.embeddings
)
self.completions = completions.AsyncCompletionsResourceWithStreamingResponse(client.completions)
self.embeddings = embeddings.AsyncEmbeddingsResourceWithStreamingResponse(client.embeddings)
self.images = images.AsyncImagesResourceWithStreamingResponse(client.images)
self.audio = audio.AsyncAudioResourceWithStreamingResponse(client.audio)
self.assistants = assistants.AsyncAssistantsResourceWithStreamingResponse(
client.assistants
)
self.assistants = assistants.AsyncAssistantsResourceWithStreamingResponse(client.assistants)
self.threads = threads.AsyncThreadsResourceWithStreamingResponse(client.threads)
self.moderations = moderations.AsyncModerationsResourceWithStreamingResponse(
client.moderations
)
self.moderations = moderations.AsyncModerationsResourceWithStreamingResponse(client.moderations)
self.utils = utils.AsyncUtilsResourceWithStreamingResponse(client.utils)
self.model = model.AsyncModelResourceWithStreamingResponse(client.model)
self.model_group = model_group.AsyncModelGroupResourceWithStreamingResponse(
client.model_group
)
self.model_group = model_group.AsyncModelGroupResourceWithStreamingResponse(client.model_group)
self.routes = routes.AsyncRoutesResourceWithStreamingResponse(client.routes)
self.responses = responses.AsyncResponsesResourceWithStreamingResponse(
client.responses
)
self.responses = responses.AsyncResponsesResourceWithStreamingResponse(client.responses)
self.batches = batches.AsyncBatchesResourceWithStreamingResponse(client.batches)
self.rerank = rerank.AsyncRerankResourceWithStreamingResponse(client.rerank)
self.fine_tuning = fine_tuning.AsyncFineTuningResourceWithStreamingResponse(
client.fine_tuning
)
self.credentials = credentials.AsyncCredentialsResourceWithStreamingResponse(
client.credentials
)
self.vertex_ai = vertex_ai.AsyncVertexAIResourceWithStreamingResponse(
client.vertex_ai
)
self.fine_tuning = fine_tuning.AsyncFineTuningResourceWithStreamingResponse(client.fine_tuning)
self.credentials = credentials.AsyncCredentialsResourceWithStreamingResponse(client.credentials)
self.vertex_ai = vertex_ai.AsyncVertexAIResourceWithStreamingResponse(client.vertex_ai)
self.gemini = gemini.AsyncGeminiResourceWithStreamingResponse(client.gemini)
self.cohere = cohere.AsyncCohereResourceWithStreamingResponse(client.cohere)
self.anthropic = anthropic.AsyncAnthropicResourceWithStreamingResponse(
client.anthropic
)
self.anthropic = anthropic.AsyncAnthropicResourceWithStreamingResponse(client.anthropic)
self.bedrock = bedrock.AsyncBedrockResourceWithStreamingResponse(client.bedrock)
self.eu_assemblyai = (
eu_assemblyai.AsyncEuAssemblyaiResourceWithStreamingResponse(
client.eu_assemblyai
)
)
self.assemblyai = assemblyai.AsyncAssemblyaiResourceWithStreamingResponse(
client.assemblyai
)
self.eu_assemblyai = eu_assemblyai.AsyncEuAssemblyaiResourceWithStreamingResponse(client.eu_assemblyai)
self.assemblyai = assemblyai.AsyncAssemblyaiResourceWithStreamingResponse(client.assemblyai)
self.azure = azure.AsyncAzureResourceWithStreamingResponse(client.azure)
self.langfuse = langfuse.AsyncLangfuseResourceWithStreamingResponse(
client.langfuse
)
self.langfuse = langfuse.AsyncLangfuseResourceWithStreamingResponse(client.langfuse)
self.config = config.AsyncConfigResourceWithStreamingResponse(client.config)
self.test = test.AsyncTestResourceWithStreamingResponse(client.test)
self.health = health.AsyncHealthResourceWithStreamingResponse(client.health)
self.active = active.AsyncActiveResourceWithStreamingResponse(client.active)
self.settings = settings.AsyncSettingsResourceWithStreamingResponse(
client.settings
)
self.settings = settings.AsyncSettingsResourceWithStreamingResponse(client.settings)
self.key = key.AsyncKeyResourceWithStreamingResponse(client.key)
self.user = user.AsyncUserResourceWithStreamingResponse(client.user)
self.team = team.AsyncTeamResourceWithStreamingResponse(client.team)
self.organization = organization.AsyncOrganizationResourceWithStreamingResponse(
client.organization
)
self.customer = customer.AsyncCustomerResourceWithStreamingResponse(
client.customer
)
self.organization = organization.AsyncOrganizationResourceWithStreamingResponse(client.organization)
self.customer = customer.AsyncCustomerResourceWithStreamingResponse(client.customer)
self.spend = spend.AsyncSpendResourceWithStreamingResponse(client.spend)
self.global_ = global_.AsyncGlobalResourceWithStreamingResponse(client.global_)
self.provider = provider.AsyncProviderResourceWithStreamingResponse(
client.provider
)
self.provider = provider.AsyncProviderResourceWithStreamingResponse(client.provider)
self.cache = cache.AsyncCacheResourceWithStreamingResponse(client.cache)
self.guardrails = guardrails.AsyncGuardrailsResourceWithStreamingResponse(
client.guardrails
)
self.guardrails = guardrails.AsyncGuardrailsResourceWithStreamingResponse(client.guardrails)
self.add = add.AsyncAddResourceWithStreamingResponse(client.add)
self.delete = delete.AsyncDeleteResourceWithStreamingResponse(client.delete)
self.files = files.AsyncFilesResourceWithStreamingResponse(client.files)
+2 -6
View File
@@ -88,9 +88,7 @@ def parse_obj(model: type[_ModelT], value: object) -> _ModelT:
if PYDANTIC_V2:
return model.model_validate(value)
else:
return cast(
_ModelT, model.parse_obj(value)
) # pyright: ignore[reportDeprecated, reportUnnecessaryCast]
return cast(_ModelT, model.parse_obj(value)) # pyright: ignore[reportDeprecated, reportUnnecessaryCast]
def field_is_required(field: FieldInfo) -> bool:
@@ -216,9 +214,7 @@ if TYPE_CHECKING:
@overload
def __get__(self, instance: object, owner: type[Any] | None = None) -> _T: ...
def __get__(
self, instance: object, owner: type[Any] | None = None
) -> _T | Self:
def __get__(self, instance: object, owner: type[Any] | None = None) -> _T | Self:
raise NotImplementedError()
def __set_name__(self, owner: type[Any], name: str) -> None: ...
+1 -3
View File
@@ -8,9 +8,7 @@ OVERRIDE_CAST_TO_HEADER = "____stainless_override_cast_to"
# default timeout is 1 minute
DEFAULT_TIMEOUT = httpx.Timeout(timeout=60, connect=5.0)
DEFAULT_MAX_RETRIES = 2
DEFAULT_CONNECTION_LIMITS = httpx.Limits(
max_connections=100, max_keepalive_connections=20
)
DEFAULT_CONNECTION_LIMITS = httpx.Limits(max_connections=100, max_keepalive_connections=20)
INITIAL_RETRY_DELAY = 0.5
MAX_RETRY_DELAY = 8.0
+10 -30
View File
@@ -37,9 +37,7 @@ class APIError(HanzoError):
If there was no response associated with this error then it will be `None`.
"""
def __init__(
self, message: str, request: httpx.Request, *, body: object | None
) -> None: # noqa: ARG002
def __init__(self, message: str, request: httpx.Request, *, body: object | None) -> None: # noqa: ARG002
super().__init__(message)
self.request = request
self.message = message
@@ -72,18 +70,14 @@ class APIStatusError(APIError):
response: httpx.Response
status_code: int
def __init__(
self, message: str, *, response: httpx.Response, body: object | None
) -> None:
def __init__(self, message: str, *, response: httpx.Response, body: object | None) -> None:
super().__init__(message, response.request, body=body)
self.response = response
self.status_code = response.status_code
class APIConnectionError(APIError):
def __init__(
self, *, message: str = "Connection error.", request: httpx.Request
) -> None:
def __init__(self, *, message: str = "Connection error.", request: httpx.Request) -> None:
super().__init__(message, request, body=None)
@@ -93,45 +87,31 @@ class APITimeoutError(APIConnectionError):
class BadRequestError(APIStatusError):
status_code: Literal[400] = (
400 # pyright: ignore[reportIncompatibleVariableOverride]
)
status_code: Literal[400] = 400 # pyright: ignore[reportIncompatibleVariableOverride]
class AuthenticationError(APIStatusError):
status_code: Literal[401] = (
401 # pyright: ignore[reportIncompatibleVariableOverride]
)
status_code: Literal[401] = 401 # pyright: ignore[reportIncompatibleVariableOverride]
class PermissionDeniedError(APIStatusError):
status_code: Literal[403] = (
403 # pyright: ignore[reportIncompatibleVariableOverride]
)
status_code: Literal[403] = 403 # pyright: ignore[reportIncompatibleVariableOverride]
class NotFoundError(APIStatusError):
status_code: Literal[404] = (
404 # pyright: ignore[reportIncompatibleVariableOverride]
)
status_code: Literal[404] = 404 # pyright: ignore[reportIncompatibleVariableOverride]
class ConflictError(APIStatusError):
status_code: Literal[409] = (
409 # pyright: ignore[reportIncompatibleVariableOverride]
)
status_code: Literal[409] = 409 # pyright: ignore[reportIncompatibleVariableOverride]
class UnprocessableEntityError(APIStatusError):
status_code: Literal[422] = (
422 # pyright: ignore[reportIncompatibleVariableOverride]
)
status_code: Literal[422] = 422 # pyright: ignore[reportIncompatibleVariableOverride]
class RateLimitError(APIStatusError):
status_code: Literal[429] = (
429 # pyright: ignore[reportIncompatibleVariableOverride]
)
status_code: Literal[429] = 429 # pyright: ignore[reportIncompatibleVariableOverride]
class InternalServerError(APIStatusError):
+6 -21
View File
@@ -26,20 +26,13 @@ def is_base64_file_input(obj: object) -> TypeGuard[Base64FileInput]:
def is_file_content(obj: object) -> TypeGuard[FileContent]:
return (
isinstance(obj, bytes)
or isinstance(obj, tuple)
or isinstance(obj, io.IOBase)
or isinstance(obj, os.PathLike)
isinstance(obj, bytes) or isinstance(obj, tuple) or isinstance(obj, io.IOBase) or isinstance(obj, os.PathLike)
)
def assert_is_file_content(obj: object, *, key: str | None = None) -> None:
if not is_file_content(obj):
prefix = (
f"Expected entry at `{key}`"
if key is not None
else f"Expected file input `{obj!r}`"
)
prefix = f"Expected entry at `{key}`" if key is not None else f"Expected file input `{obj!r}`"
raise RuntimeError(
f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/hanzoai/python-sdk/tree/main#file-uploads"
) from None
@@ -62,9 +55,7 @@ def to_httpx_files(files: RequestFiles | None) -> HttpxRequestFiles | None:
elif is_sequence_t(files):
files = [(key, _transform_file(file)) for key, file in files]
else:
raise TypeError(
f"Unexpected file type input {type(files)}, expected mapping or sequence"
)
raise TypeError(f"Unexpected file type input {type(files)}, expected mapping or sequence")
return files
@@ -80,9 +71,7 @@ def _transform_file(file: FileTypes) -> HttpxFileTypes:
if is_tuple_t(file):
return (file[0], _read_file_content(file[1]), *file[2:])
raise TypeError(
"Expected file types input to be a FileContent type or to be a tuple"
)
raise TypeError("Expected file types input to be a FileContent type or to be a tuple")
def _read_file_content(file: FileContent) -> HttpxFileContent:
@@ -108,9 +97,7 @@ async def async_to_httpx_files(files: RequestFiles | None) -> HttpxRequestFiles
elif is_sequence_t(files):
files = [(key, await _async_transform_file(file)) for key, file in files]
else:
raise TypeError(
"Unexpected file type input {type(files)}, expected mapping or sequence"
)
raise TypeError("Unexpected file type input {type(files)}, expected mapping or sequence")
return files
@@ -126,9 +113,7 @@ async def _async_transform_file(file: FileTypes) -> HttpxFileTypes:
if is_tuple_t(file):
return (file[0], await _async_read_file_content(file[1]), *file[2:])
raise TypeError(
"Expected file types input to be a FileContent type or to be a tuple"
)
raise TypeError("Expected file types input to be a FileContent type or to be a tuple")
async def _async_read_file_content(file: FileContent) -> HttpxFileContent:
+12 -39
View File
@@ -209,9 +209,7 @@ class BaseModel(pydantic.BaseModel):
key = name
if key in values:
fields_values[name] = _construct_field(
value=values[key], field=field, key=key
)
fields_values[name] = _construct_field(value=values[key], field=field, key=key)
_fields_set.add(name)
else:
fields_values[name] = field_get_default(field)
@@ -460,9 +458,7 @@ def construct_type(*, value: object, type_: object) -> object:
if is_union(origin):
try:
return validate_type(
type_=cast("type[object]", original_type or type_), value=value
)
return validate_type(type_=cast("type[object]", original_type or type_), value=value)
except Exception:
pass
@@ -480,13 +476,9 @@ def construct_type(*, value: object, type_: object) -> object:
#
# without this block, if the data we get is something like `{'kind': 'bar', 'value': 'foo'}` then
# we'd end up constructing `FooType` when it should be `BarType`.
discriminator = _build_discriminated_union_meta(
union=type_, meta_annotations=meta
)
discriminator = _build_discriminated_union_meta(union=type_, meta_annotations=meta)
if discriminator and is_mapping(value):
variant_value = value.get(
discriminator.field_alias_from or discriminator.field_name
)
variant_value = value.get(discriminator.field_alias_from or discriminator.field_name)
if variant_value and isinstance(variant_value, str):
variant_type = discriminator.mapping.get(variant_value)
if variant_type:
@@ -506,10 +498,7 @@ def construct_type(*, value: object, type_: object) -> object:
return value
_, items_type = get_args(type_) # Dict[_, items_type]
return {
key: construct_type(value=item, type_=items_type)
for key, item in value.items()
}
return {key: construct_type(value=item, type_=items_type) for key, item in value.items()}
if (
not is_literal_type(type_)
@@ -517,10 +506,7 @@ def construct_type(*, value: object, type_: object) -> object:
and (issubclass(origin, BaseModel) or issubclass(origin, GenericModel))
):
if is_list(value):
return [
cast(Any, type_).construct(**entry) if is_mapping(entry) else entry
for entry in value
]
return [cast(Any, type_).construct(**entry) if is_mapping(entry) else entry for entry in value]
if is_mapping(value):
if issubclass(type_, BaseModel):
@@ -605,19 +591,14 @@ class DiscriminatorDetails:
self.field_alias_from = discriminator_alias
def _build_discriminated_union_meta(
*, union: type, meta_annotations: tuple[Any, ...]
) -> DiscriminatorDetails | None:
def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, ...]) -> DiscriminatorDetails | None:
if isinstance(union, CachedDiscriminatorType):
return union.__discriminator__
discriminator_field_name: str | None = None
for annotation in meta_annotations:
if (
isinstance(annotation, PropertyInfo)
and annotation.discriminator is not None
):
if isinstance(annotation, PropertyInfo) and annotation.discriminator is not None:
discriminator_field_name = annotation.discriminator
break
@@ -645,9 +626,7 @@ def _build_discriminated_union_meta(
if isinstance(entry, str):
mapping[entry] = variant
else:
field_info = cast("dict[str, FieldInfo]", variant.__fields__).get(
discriminator_field_name
) # pyright: ignore[reportDeprecated, reportUnnecessaryCast]
field_info = cast("dict[str, FieldInfo]", variant.__fields__).get(discriminator_field_name) # pyright: ignore[reportDeprecated, reportUnnecessaryCast]
if not field_info:
continue
@@ -671,9 +650,7 @@ def _build_discriminated_union_meta(
return details
def _extract_field_schema_pv2(
model: type[BaseModel], field_name: str
) -> ModelField | None:
def _extract_field_schema_pv2(model: type[BaseModel], field_name: str) -> ModelField | None:
schema = model.__pydantic_core_schema__
if schema["type"] == "definitions":
schema = schema["schema"]
@@ -723,9 +700,7 @@ else:
if PYDANTIC_V2:
from pydantic import TypeAdapter as _TypeAdapter
_CachedTypeAdapter = cast(
"TypeAdapter[object]", lru_cache(maxsize=None)(_TypeAdapter)
)
_CachedTypeAdapter = cast("TypeAdapter[object]", lru_cache(maxsize=None)(_TypeAdapter))
if TYPE_CHECKING:
from pydantic import TypeAdapter
@@ -828,9 +803,7 @@ class FinalRequestOptions(pydantic.BaseModel):
}
if PYDANTIC_V2:
return super().model_construct(_fields_set, **kwargs)
return cast(
FinalRequestOptions, super().construct(_fields_set, **kwargs)
) # pyright: ignore[reportDeprecated]
return cast(FinalRequestOptions, super().construct(_fields_set, **kwargs)) # pyright: ignore[reportDeprecated]
if not TYPE_CHECKING:
# type checkers incorrectly complain about this assignment
+6 -22
View File
@@ -64,9 +64,7 @@ class Querystring:
array_format=array_format,
nested_format=nested_format,
)
return flatten(
[self._stringify_item(key, value, opts) for key, value in params.items()]
)
return flatten([self._stringify_item(key, value, opts) for key, value in params.items()])
def _stringify_item(
self,
@@ -81,11 +79,7 @@ class Querystring:
items.extend(
self._stringify_item(
# TODO: error if unknown format
(
f"{key}.{subkey}"
if nested_format == "dots"
else f"{key}[{subkey}]"
),
(f"{key}.{subkey}" if nested_format == "dots" else f"{key}[{subkey}]"),
subvalue,
opts,
)
@@ -98,11 +92,7 @@ class Querystring:
return [
(
key,
",".join(
self._primitive_value_to_str(item)
for item in value
if item is not None
),
",".join(self._primitive_value_to_str(item) for item in value if item is not None),
),
]
elif array_format == "repeat":
@@ -111,9 +101,7 @@ class Querystring:
items.extend(self._stringify_item(key, item, opts))
return items
elif array_format == "indices":
raise NotImplementedError(
"The array indices format is not supported yet"
)
raise NotImplementedError("The array indices format is not supported yet")
elif array_format == "brackets":
items = []
key = key + "[]"
@@ -158,9 +146,5 @@ class Options:
array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN,
nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN,
) -> None:
self.array_format = (
qs.array_format if isinstance(array_format, NotGiven) else array_format
)
self.nested_format = (
qs.nested_format if isinstance(nested_format, NotGiven) else nested_format
)
self.array_format = qs.array_format if isinstance(array_format, NotGiven) else array_format
self.nested_format = qs.nested_format if isinstance(nested_format, NotGiven) else nested_format
+21 -55
View File
@@ -132,7 +132,9 @@ class BaseAPIResponse(Generic[R]):
@override
def __repr__(self) -> str:
return f"<{self.__class__.__name__} [{self.status_code} {self.http_response.reason_phrase}] type={self._cast_to}>"
return (
f"<{self.__class__.__name__} [{self.status_code} {self.http_response.reason_phrase}] type={self._cast_to}>"
)
def _parse(self, *, to: type[_T] | None = None) -> R | _T:
cast_to = to if to is not None else self._cast_to
@@ -150,9 +152,7 @@ class BaseAPIResponse(Generic[R]):
if self._is_sse_stream:
if to:
if not is_stream_class_type(to):
raise TypeError(
f"Expected custom parse type to be a subclass of {Stream} or {AsyncStream}"
)
raise TypeError(f"Expected custom parse type to be a subclass of {Stream} or {AsyncStream}")
return cast(
_T,
@@ -221,9 +221,7 @@ class BaseAPIResponse(Generic[R]):
# the response class ourselves but that is something that should be supported directly in httpx
# as it would be easy to incorrectly construct the Response object due to the multitude of arguments.
if cast_to != httpx.Response:
raise ValueError(
f"Subclasses of httpx.Response cannot be passed to `cast_to`"
)
raise ValueError(f"Subclasses of httpx.Response cannot be passed to `cast_to`")
return cast(R, response)
if (
@@ -231,9 +229,7 @@ class BaseAPIResponse(Generic[R]):
and not issubclass(origin, BaseModel)
and issubclass(origin, pydantic.BaseModel)
):
raise TypeError(
"Pydantic models must subclass our base model type, e.g. `from hanzoai import BaseModel`"
)
raise TypeError("Pydantic models must subclass our base model type, e.g. `from hanzoai import BaseModel`")
if (
cast_to is not object
@@ -670,12 +666,8 @@ def to_streamed_response_wrapper(
"""
@functools.wraps(func)
def wrapped(
*args: P.args, **kwargs: P.kwargs
) -> ResponseContextManager[APIResponse[R]]:
extra_headers: dict[str, str] = {
**(cast(Any, kwargs.get("extra_headers")) or {})
}
def wrapped(*args: P.args, **kwargs: P.kwargs) -> ResponseContextManager[APIResponse[R]]:
extra_headers: dict[str, str] = {**(cast(Any, kwargs.get("extra_headers")) or {})}
extra_headers[RAW_RESPONSE_HEADER] = "stream"
kwargs["extra_headers"] = extra_headers
@@ -695,21 +687,15 @@ def async_to_streamed_response_wrapper(
"""
@functools.wraps(func)
def wrapped(
*args: P.args, **kwargs: P.kwargs
) -> AsyncResponseContextManager[AsyncAPIResponse[R]]:
extra_headers: dict[str, str] = {
**(cast(Any, kwargs.get("extra_headers")) or {})
}
def wrapped(*args: P.args, **kwargs: P.kwargs) -> AsyncResponseContextManager[AsyncAPIResponse[R]]:
extra_headers: dict[str, str] = {**(cast(Any, kwargs.get("extra_headers")) or {})}
extra_headers[RAW_RESPONSE_HEADER] = "stream"
kwargs["extra_headers"] = extra_headers
make_request = func(*args, **kwargs)
return AsyncResponseContextManager(
cast(Awaitable[AsyncAPIResponse[R]], make_request)
)
return AsyncResponseContextManager(cast(Awaitable[AsyncAPIResponse[R]], make_request))
return wrapped
@@ -725,12 +711,8 @@ def to_custom_streamed_response_wrapper(
"""
@functools.wraps(func)
def wrapped(
*args: P.args, **kwargs: P.kwargs
) -> ResponseContextManager[_APIResponseT]:
extra_headers: dict[str, Any] = {
**(cast(Any, kwargs.get("extra_headers")) or {})
}
def wrapped(*args: P.args, **kwargs: P.kwargs) -> ResponseContextManager[_APIResponseT]:
extra_headers: dict[str, Any] = {**(cast(Any, kwargs.get("extra_headers")) or {})}
extra_headers[RAW_RESPONSE_HEADER] = "stream"
extra_headers[OVERRIDE_CAST_TO_HEADER] = response_cls
@@ -754,12 +736,8 @@ def async_to_custom_streamed_response_wrapper(
"""
@functools.wraps(func)
def wrapped(
*args: P.args, **kwargs: P.kwargs
) -> AsyncResponseContextManager[_AsyncAPIResponseT]:
extra_headers: dict[str, Any] = {
**(cast(Any, kwargs.get("extra_headers")) or {})
}
def wrapped(*args: P.args, **kwargs: P.kwargs) -> AsyncResponseContextManager[_AsyncAPIResponseT]:
extra_headers: dict[str, Any] = {**(cast(Any, kwargs.get("extra_headers")) or {})}
extra_headers[RAW_RESPONSE_HEADER] = "stream"
extra_headers[OVERRIDE_CAST_TO_HEADER] = response_cls
@@ -767,9 +745,7 @@ def async_to_custom_streamed_response_wrapper(
make_request = func(*args, **kwargs)
return AsyncResponseContextManager(
cast(Awaitable[_AsyncAPIResponseT], make_request)
)
return AsyncResponseContextManager(cast(Awaitable[_AsyncAPIResponseT], make_request))
return wrapped
@@ -781,9 +757,7 @@ def to_raw_response_wrapper(func: Callable[P, R]) -> Callable[P, APIResponse[R]]
@functools.wraps(func)
def wrapped(*args: P.args, **kwargs: P.kwargs) -> APIResponse[R]:
extra_headers: dict[str, str] = {
**(cast(Any, kwargs.get("extra_headers")) or {})
}
extra_headers: dict[str, str] = {**(cast(Any, kwargs.get("extra_headers")) or {})}
extra_headers[RAW_RESPONSE_HEADER] = "raw"
kwargs["extra_headers"] = extra_headers
@@ -802,9 +776,7 @@ def async_to_raw_response_wrapper(
@functools.wraps(func)
async def wrapped(*args: P.args, **kwargs: P.kwargs) -> AsyncAPIResponse[R]:
extra_headers: dict[str, str] = {
**(cast(Any, kwargs.get("extra_headers")) or {})
}
extra_headers: dict[str, str] = {**(cast(Any, kwargs.get("extra_headers")) or {})}
extra_headers[RAW_RESPONSE_HEADER] = "raw"
kwargs["extra_headers"] = extra_headers
@@ -826,9 +798,7 @@ def to_custom_raw_response_wrapper(
@functools.wraps(func)
def wrapped(*args: P.args, **kwargs: P.kwargs) -> _APIResponseT:
extra_headers: dict[str, Any] = {
**(cast(Any, kwargs.get("extra_headers")) or {})
}
extra_headers: dict[str, Any] = {**(cast(Any, kwargs.get("extra_headers")) or {})}
extra_headers[RAW_RESPONSE_HEADER] = "raw"
extra_headers[OVERRIDE_CAST_TO_HEADER] = response_cls
@@ -851,9 +821,7 @@ def async_to_custom_raw_response_wrapper(
@functools.wraps(func)
def wrapped(*args: P.args, **kwargs: P.kwargs) -> Awaitable[_AsyncAPIResponseT]:
extra_headers: dict[str, Any] = {
**(cast(Any, kwargs.get("extra_headers")) or {})
}
extra_headers: dict[str, Any] = {**(cast(Any, kwargs.get("extra_headers")) or {})}
extra_headers[RAW_RESPONSE_HEADER] = "raw"
extra_headers[OVERRIDE_CAST_TO_HEADER] = response_cls
@@ -877,8 +845,6 @@ def extract_response_type(typ: type[BaseAPIResponse[Any]]) -> type:
"""
return extract_type_var_from_base(
typ,
generic_bases=cast(
"tuple[type, ...]", (BaseAPIResponse, APIResponse, AsyncAPIResponse)
),
generic_bases=cast("tuple[type, ...]", (BaseAPIResponse, APIResponse, AsyncAPIResponse)),
index=0,
)
+4 -15
View File
@@ -227,9 +227,7 @@ class SSEDecoder:
if data:
yield data
async def aiter_bytes(
self, iterator: AsyncIterator[bytes]
) -> AsyncIterator[ServerSentEvent]:
async def aiter_bytes(self, iterator: AsyncIterator[bytes]) -> AsyncIterator[ServerSentEvent]:
"""Given an iterator that yields raw binary data, iterate over it & yield every event encountered"""
async for chunk in self._aiter_chunks(iterator):
# Split before decoding so splitlines() only uses \r and \n
@@ -239,9 +237,7 @@ class SSEDecoder:
if sse:
yield sse
async def _aiter_chunks(
self, iterator: AsyncIterator[bytes]
) -> AsyncIterator[bytes]:
async def _aiter_chunks(self, iterator: AsyncIterator[bytes]) -> AsyncIterator[bytes]:
"""Given an iterator that yields raw binary data, iterate over it and yield individual SSE chunks"""
data = b""
async for chunk in iterator:
@@ -257,12 +253,7 @@ class SSEDecoder:
# See: https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation # noqa: E501
if not line:
if (
not self._event
and not self._data
and not self._last_event_id
and self._retry is None
):
if not self._event and not self._data and not self._last_event_id and self._retry is None:
return None
sse = ServerSentEvent(
@@ -313,9 +304,7 @@ class SSEBytesDecoder(Protocol):
"""Given an iterator that yields raw binary data, iterate over it & yield every event encountered"""
...
def aiter_bytes(
self, iterator: AsyncIterator[bytes]
) -> AsyncIterator[ServerSentEvent]:
def aiter_bytes(self, iterator: AsyncIterator[bytes]) -> AsyncIterator[ServerSentEvent]:
"""Given an async iterator that yields raw binary data, iterate over it & yield every event encountered"""
...
+2 -6
View File
@@ -52,9 +52,7 @@ if TYPE_CHECKING:
FileContent = Union[IO[bytes], bytes, PathLike[str]]
else:
Base64FileInput = Union[IO[bytes], PathLike]
FileContent = Union[
IO[bytes], bytes, PathLike
] # PathLike is not subscriptable in Python 3.8.
FileContent = Union[IO[bytes], bytes, PathLike] # PathLike is not subscriptable in Python 3.8.
FileTypes = Union[
# file (or bytes)
FileContent,
@@ -79,9 +77,7 @@ HttpxFileTypes = Union[
# (filename, file (or bytes), content_type, headers)
Tuple[Optional[str], HttpxFileContent, Optional[str], Mapping[str, str]],
]
HttpxRequestFiles = Union[
Mapping[str, HttpxFileTypes], Sequence[Tuple[str, HttpxFileTypes]]
]
HttpxRequestFiles = Union[Mapping[str, HttpxFileTypes], Sequence[Tuple[str, HttpxFileTypes]]]
# Workaround to support (cast_to: Type[ResponseT]) -> ResponseT
# where ResponseT includes `None`. In order to support directly
+1 -4
View File
@@ -39,7 +39,4 @@ def assert_signatures_in_sync(
continue
if errors:
raise AssertionError(
f"{len(errors)} errors encountered when comparing signatures:\n\n"
+ "\n\n".join(errors)
)
raise AssertionError(f"{len(errors)} errors encountered when comparing signatures:\n\n" + "\n\n".join(errors))
+1 -3
View File
@@ -88,9 +88,7 @@ def asyncify(
and returns the result.
"""
async def wrapper(
*args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs
) -> T_Retval:
async def wrapper(*args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs) -> T_Retval:
return await to_thread(function, *args, **kwargs)
return wrapper
+15 -55
View File
@@ -170,20 +170,13 @@ def _transform_recursive(
if origin == dict and is_mapping(data):
items_type = get_args(stripped_type)[1]
return {
key: _transform_recursive(value, annotation=items_type)
for key, value in data.items()
}
return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()}
if (
# List[T]
(is_list_type(stripped_type) and is_list(data))
# Iterable[T]
or (
is_iterable_type(stripped_type)
and is_iterable(data)
and not isinstance(data, str)
)
or (is_iterable_type(stripped_type) and is_iterable(data) and not isinstance(data, str))
):
# dicts are technically iterable, but it is an iterable on the keys of the dict and is not usually
# intended as an iterable, so we don't transform it.
@@ -191,10 +184,7 @@ def _transform_recursive(
return cast(object, data)
inner_type = extract_type_arg(stripped_type, 0)
return [
_transform_recursive(d, annotation=annotation, inner_type=inner_type)
for d in data
]
return [_transform_recursive(d, annotation=annotation, inner_type=inner_type) for d in data]
if is_union_type(stripped_type):
# For union types we run the transformation against all subtypes to ensure that everything is transformed.
@@ -221,9 +211,7 @@ def _transform_recursive(
return data
def _format_data(
data: object, format_: PropertyFormat, format_template: str | None
) -> object:
def _format_data(data: object, format_: PropertyFormat, format_template: str | None) -> object:
if isinstance(data, (date, datetime)):
if format_ == "iso8601":
return data.isoformat()
@@ -243,9 +231,7 @@ def _format_data(
binary = binary.encode()
if not isinstance(binary, bytes):
raise RuntimeError(
f"Could not read bytes from {data}; Received {type(binary)}"
)
raise RuntimeError(f"Could not read bytes from {data}; Received {type(binary)}")
return base64.b64encode(binary).decode("ascii")
@@ -264,9 +250,7 @@ def _transform_typeddict(
# we do not have a type annotation for this field, leave it as is
result[key] = value
else:
result[_maybe_transform_key(key, type_)] = _transform_recursive(
value, annotation=type_
)
result[_maybe_transform_key(key, type_)] = _transform_recursive(value, annotation=type_)
return result
@@ -302,9 +286,7 @@ async def async_transform(
It should be noted that the transformations that this function does are not represented in the type system.
"""
transformed = await _async_transform_recursive(
data, annotation=cast(type, expected_type)
)
transformed = await _async_transform_recursive(data, annotation=cast(type, expected_type))
return cast(_T, transformed)
@@ -336,20 +318,13 @@ async def _async_transform_recursive(
if origin == dict and is_mapping(data):
items_type = get_args(stripped_type)[1]
return {
key: _transform_recursive(value, annotation=items_type)
for key, value in data.items()
}
return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()}
if (
# List[T]
(is_list_type(stripped_type) and is_list(data))
# Iterable[T]
or (
is_iterable_type(stripped_type)
and is_iterable(data)
and not isinstance(data, str)
)
or (is_iterable_type(stripped_type) and is_iterable(data) and not isinstance(data, str))
):
# dicts are technically iterable, but it is an iterable on the keys of the dict and is not usually
# intended as an iterable, so we don't transform it.
@@ -357,12 +332,7 @@ async def _async_transform_recursive(
return cast(object, data)
inner_type = extract_type_arg(stripped_type, 0)
return [
await _async_transform_recursive(
d, annotation=annotation, inner_type=inner_type
)
for d in data
]
return [await _async_transform_recursive(d, annotation=annotation, inner_type=inner_type) for d in data]
if is_union_type(stripped_type):
# For union types we run the transformation against all subtypes to ensure that everything is transformed.
@@ -370,9 +340,7 @@ async def _async_transform_recursive(
# TODO: there may be edge cases where the same normalized field name will transform to two different names
# in different subtypes.
for subtype in get_args(stripped_type):
data = await _async_transform_recursive(
data, annotation=annotation, inner_type=subtype
)
data = await _async_transform_recursive(data, annotation=annotation, inner_type=subtype)
return data
if isinstance(data, pydantic.BaseModel):
@@ -386,16 +354,12 @@ async def _async_transform_recursive(
annotations = get_args(annotated_type)[1:]
for annotation in annotations:
if isinstance(annotation, PropertyInfo) and annotation.format is not None:
return await _async_format_data(
data, annotation.format, annotation.format_template
)
return await _async_format_data(data, annotation.format, annotation.format_template)
return data
async def _async_format_data(
data: object, format_: PropertyFormat, format_template: str | None
) -> object:
async def _async_format_data(data: object, format_: PropertyFormat, format_template: str | None) -> object:
if isinstance(data, (date, datetime)):
if format_ == "iso8601":
return data.isoformat()
@@ -415,9 +379,7 @@ async def _async_format_data(
binary = binary.encode()
if not isinstance(binary, bytes):
raise RuntimeError(
f"Could not read bytes from {data}; Received {type(binary)}"
)
raise RuntimeError(f"Could not read bytes from {data}; Received {type(binary)}")
return base64.b64encode(binary).decode("ascii")
@@ -436,7 +398,5 @@ async def _async_transform_typeddict(
# we do not have a type annotation for this field, leave it as is
result[key] = value
else:
result[_maybe_transform_key(key, type_)] = await _async_transform_recursive(
value, annotation=type_
)
result[_maybe_transform_key(key, type_)] = await _async_transform_recursive(value, annotation=type_)
return result
+3 -10
View File
@@ -45,9 +45,7 @@ def is_typevar(typ: type) -> bool:
return type(typ) == TypeVar # type: ignore
_TYPE_ALIAS_TYPES: tuple[type[typing_extensions.TypeAliasType], ...] = (
typing_extensions.TypeAliasType,
)
_TYPE_ALIAS_TYPES: tuple[type[typing_extensions.TypeAliasType], ...] = (typing_extensions.TypeAliasType,)
if sys.version_info >= (3, 12):
_TYPE_ALIAS_TYPES = (*_TYPE_ALIAS_TYPES, typing.TypeAliasType)
@@ -80,9 +78,7 @@ def extract_type_arg(typ: type, index: int) -> type:
try:
return cast(type, args[index])
except IndexError as err:
raise RuntimeError(
f"Expected type {typ} to have a type argument at index {index} but it did not"
) from err
raise RuntimeError(f"Expected type {typ} to have a type argument at index {index} but it did not") from err
def extract_type_var_from_base(
@@ -150,7 +146,4 @@ def extract_type_var_from_base(
return extracted
raise RuntimeError(
failure_message
or f"Could not resolve inner type variable at index {index} for {typ}"
)
raise RuntimeError(failure_message or f"Could not resolve inner type variable at index {index} for {typ}")
+2 -9
View File
@@ -109,9 +109,7 @@ def _extract_items(
item,
path,
index=index,
flattened_key=(
flattened_key + "[]" if flattened_key is not None else "[]"
),
flattened_key=(flattened_key + "[]" if flattened_key is not None else "[]"),
)
for item in obj
]
@@ -261,12 +259,7 @@ def required_args(*variants: Sequence[str]) -> Callable[[CallableT], CallableT]:
else: # no break
if len(variants) > 1:
variations = human_join(
[
"("
+ human_join([quote(arg) for arg in variant], final="and")
+ ")"
for variant in variants
]
["(" + human_join([quote(arg) for arg in variant], final="and") + ")" for variant in variants]
)
msg = f"Missing required arguments; Expected either {variations} arguments to be given"
else:
+4 -12
View File
@@ -42,9 +42,7 @@ except ImportError:
# Provide a helpful error message
def _agents_not_installed(*args, **kwargs):
raise ImportError(
"hanzo-agents is not installed. Install it with: pip install hanzo-agents"
)
raise ImportError("hanzo-agents is not installed. Install it with: pip install hanzo-agents")
# Create placeholder classes/functions
Agent = State = Network = Tool = History = _agents_not_installed
@@ -58,9 +56,7 @@ except ImportError:
AgentConfig = NetworkConfig = _agents_not_installed
def create_agent(
name: str, model: str = "anthropic/claude-3-5-sonnet-20241022", **kwargs
):
def create_agent(name: str, model: str = "anthropic/claude-3-5-sonnet-20241022", **kwargs):
"""Create a new AI agent.
Args:
@@ -72,9 +68,7 @@ def create_agent(
Agent instance
"""
if not AGENTS_AVAILABLE:
raise ImportError(
"hanzo-agents is not installed. Install it with: pip install hanzo-agents"
)
raise ImportError("hanzo-agents is not installed. Install it with: pip install hanzo-agents")
config = AgentConfig(name=name, model=model, **kwargs)
return LocalAgent(config)
@@ -92,9 +86,7 @@ def create_network(agents: list, router=None, **kwargs):
Network instance
"""
if not AGENTS_AVAILABLE:
raise ImportError(
"hanzo-agents is not installed. Install it with: pip install hanzo-agents"
)
raise ImportError("hanzo-agents is not installed. Install it with: pip install hanzo-agents")
if router is None:
router = sequential_router()
+5 -15
View File
@@ -184,9 +184,7 @@ class HanzoAuth:
if self._token:
# Revoke token
async with httpx.AsyncClient() as client:
await client.post(
f"{self.base_url}/api/logout", headers=self._get_headers()
)
await client.post(f"{self.base_url}/api/logout", headers=self._get_headers())
self._token = None
self.api_key = None
@@ -202,9 +200,7 @@ class HanzoAuth:
return self._user_info
async with httpx.AsyncClient() as client:
response = await client.get(
f"{self.api_base_url}/v1/user", headers=self._get_headers()
)
response = await client.get(f"{self.api_base_url}/v1/user", headers=self._get_headers())
response.raise_for_status()
self._user_info = response.json()
@@ -247,9 +243,7 @@ class HanzoAuth:
List of API key information
"""
async with httpx.AsyncClient() as client:
response = await client.get(
f"{self.api_base_url}/v1/api-keys", headers=self._get_headers()
)
response = await client.get(f"{self.api_base_url}/v1/api-keys", headers=self._get_headers())
response.raise_for_status()
return response.json().get("keys", [])
@@ -261,9 +255,7 @@ class HanzoAuth:
name: Key name to revoke
"""
async with httpx.AsyncClient() as client:
response = await client.delete(
f"{self.api_base_url}/v1/api-keys/{name}", headers=self._get_headers()
)
response = await client.delete(f"{self.api_base_url}/v1/api-keys/{name}", headers=self._get_headers())
response.raise_for_status()
async def save_credentials(self, path: Path):
@@ -324,9 +316,7 @@ class HanzoAuth:
# MCP Authentication Flow
async def authenticate_for_mcp(
server_name: str = "hanzo-mcp", permissions: List[str] = None
) -> str:
async def authenticate_for_mcp(server_name: str = "hanzo-mcp", permissions: List[str] = None) -> str:
"""Authenticate and get token for MCP server.
Args:
+4 -12
View File
@@ -57,9 +57,7 @@ class HanzoCluster:
# Try to install exo
print("exo not found. Installing exo-explore...")
try:
subprocess.run(
["pip", "install", "exo-explore"], check=True, capture_output=True
)
subprocess.run(["pip", "install", "exo-explore"], check=True, capture_output=True)
# Try importing again
import exo
from exo import ExoNode as _ExoNode, ExoCluster as _ExoCluster
@@ -76,9 +74,7 @@ class HanzoCluster:
async def start(self):
"""Start the cluster node."""
if not EXO_AVAILABLE:
raise RuntimeError(
"exo is not available. Please install: pip install exo-explore"
)
raise RuntimeError("exo is not available. Please install: pip install exo-explore")
# Build exo command
cmd = ["exo"]
@@ -140,9 +136,7 @@ class HanzoCluster:
# Default exo API endpoint
return f"http://localhost:8000"
async def inference(
self, prompt: str, model: str = None, **kwargs
) -> Dict[str, Any]:
async def inference(self, prompt: str, model: str = None, **kwargs) -> Dict[str, Any]:
"""Run inference on the cluster.
Args:
@@ -171,9 +165,7 @@ class HanzoCluster:
class HanzoMiner:
"""Hanzo Miner for distributed AI compute contribution."""
def __init__(
self, wallet_address: str = None, cluster_config: ClusterConfig = None
):
def __init__(self, wallet_address: str = None, cluster_config: ClusterConfig = None):
"""Initialize the miner.
Args:
+20 -22
View File
@@ -1,9 +1,9 @@
"""Training-Free GRPO implementation for Hanzo AI.
This module provides Training-Free Group Relative Policy Optimization (GRPO)
This module provides Training-Free Group Relative Policy Optimization (GRPO)
from Tencent's youtu-agent paper (arXiv:2510.08191v1).
Training-Free GRPO improves LLM performance via context expansion rather than
Training-Free GRPO improves LLM performance via context expansion rather than
parameter updates, using semantic advantages extracted via LLM introspection.
Key components:
@@ -18,28 +18,26 @@ Key components:
Example usage:
```python
from hanzoai.grpo import DeepSeekAdapter, ExperienceManager, SemanticExtractor, LLMClient
# Initialize components
target_model = DeepSeekAdapter(api_key="your-api-key")
semantic_llm = LLMClient(api_key="your-api-key", base_url="https://api.deepseek.com/v1")
exp_manager = ExperienceManager(checkpoint_path="./experiences/experiences.json")
extractor = SemanticExtractor(semantic_llm, max_operations=5)
# Generate rollouts with experience injection
query = "Solve: 2x + 5 = 13"
group_size = 5
trajectories = []
for i in range(group_size):
experiences_text = exp_manager.format_for_prompt()
response = target_model.generate_with_experiences(
query=query,
experiences=experiences_text,
temperature=0.7 + (i * 0.1)
query=query, experiences=experiences_text, temperature=0.7 + (i * 0.1)
)
# Evaluate and create trajectory
# trajectories.append(Trajectory(query=query, output=response, reward=score))
# Extract semantic advantages and update experience library
group_operations = extractor.extract_group_advantage(trajectories, exp_manager.format_for_prompt())
exp_manager.apply_operations(group_operations)
@@ -51,28 +49,28 @@ https://arxiv.org/abs/2510.08191
"""
# Basic implementations
from .experience_manager import ExperienceManager
from .semantic_extractor import SemanticExtractor, Trajectory, LLMClient
from .api_model_adapter import (
APIModelAdapter,
APIModelConfig,
DeepSeekAdapter,
OpenAIAdapter,
APIModelConfig,
APIModelAdapter,
DeepSeekAdapter,
)
from .experience_manager import ExperienceManager
from .semantic_extractor import LLMClient, Trajectory, SemanticExtractor
from .enhanced_api_model_adapter import (
EnhancedOpenAIAdapter,
EnhancedAPIModelConfig,
EnhancedAPIModelAdapter,
EnhancedDeepSeekAdapter,
)
# Enhanced implementations with full Tencent feature parity
from .enhanced_semantic_extractor import (
EnhancedSemanticExtractor,
EnhancedLLMClient,
Trajectory as EnhancedTrajectory,
EnhancedLLMClient,
EnhancedSemanticExtractor,
rollout_with_timeout,
)
from .enhanced_api_model_adapter import (
EnhancedAPIModelAdapter,
EnhancedAPIModelConfig,
EnhancedDeepSeekAdapter,
EnhancedOpenAIAdapter,
)
__all__ = [
# Basic
+52 -93
View File
@@ -15,16 +15,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import List, Optional, Dict, Any
from typing import Any, Dict, List, Optional
from dataclasses import dataclass
@dataclass
class APIModelConfig:
"""Configuration for API-hosted models.
Supports DeepSeek, OpenAI, and any OpenAI-compatible API.
"""
api_key: str
base_url: str = "https://api.deepseek.com/v1"
model: str = "deepseek-chat"
@@ -35,25 +36,21 @@ class APIModelConfig:
class APIModelAdapter:
"""Adapter for using API-hosted models in Training-Free GRPO.
This enables using models like:
- DeepSeek-V3 (deepseek-chat, deepseek-reasoner)
- OpenAI GPT-4o (gpt-4o, gpt-4o-mini)
- Any OpenAI-compatible API
Benefits over local models:
- No GPU required
- Faster inference (optimized infrastructure)
- Better base models (DeepSeek-V3 is SOTA)
- Lower total cost (no local compute)
- Easy scaling
Example:
>>> config = APIModelConfig(
... api_key="sk-xxx",
... base_url="https://api.deepseek.com/v1",
... model="deepseek-chat"
... )
>>> config = APIModelConfig(api_key="sk-xxx", base_url="https://api.deepseek.com/v1", model="deepseek-chat")
>>> adapter = APIModelAdapter(config)
>>> response = adapter.generate("What is 5 + 3?")
>>> print(response) # "8"
@@ -61,108 +58,96 @@ class APIModelAdapter:
def __init__(self, config: APIModelConfig):
"""Initialize API model adapter.
Args:
config: API model configuration
"""
self.config = config
try:
from openai import OpenAI
except ImportError:
raise ImportError(
"OpenAI package not found. Install with: pip install openai"
)
self.client = OpenAI(
api_key=config.api_key,
base_url=config.base_url
)
raise ImportError("OpenAI package not found. Install with: pip install openai")
self.client = OpenAI(api_key=config.api_key, base_url=config.base_url)
def generate(
self,
prompt: str,
self,
prompt: str,
temperature: Optional[float] = None,
max_tokens: Optional[int] = None,
system_prompt: Optional[str] = None
system_prompt: Optional[str] = None,
) -> str:
"""Generate a response from the API model.
Args:
prompt: User prompt/query
temperature: Sampling temperature (overrides config)
max_tokens: Max tokens to generate (overrides config)
system_prompt: Optional system prompt
Returns:
response: Generated text
"""
messages = []
if system_prompt:
messages.append({"role": "system", "content": system_prompt})
messages.append({"role": "user", "content": prompt})
response = self.client.chat.completions.create(
model=self.config.model,
messages=messages,
temperature=temperature or self.config.temperature,
max_tokens=max_tokens or self.config.max_tokens,
top_p=self.config.top_p
top_p=self.config.top_p,
)
return response.choices[0].message.content
def generate_batch(
self,
self,
prompts: List[str],
temperature: Optional[float] = None,
max_tokens: Optional[int] = None,
system_prompt: Optional[str] = None
system_prompt: Optional[str] = None,
) -> List[str]:
"""Generate responses for a batch of prompts.
Note: Currently sequential. For true parallel execution,
use asyncio version or API batching features.
Args:
prompts: List of prompts
temperature: Sampling temperature (overrides config)
max_tokens: Max tokens to generate (overrides config)
system_prompt: Optional system prompt
Returns:
responses: List of generated texts
"""
responses = []
for prompt in prompts:
response = self.generate(
prompt,
temperature=temperature,
max_tokens=max_tokens,
system_prompt=system_prompt
prompt, temperature=temperature, max_tokens=max_tokens, system_prompt=system_prompt
)
responses.append(response)
return responses
def generate_with_experiences(
self,
query: str,
experiences: str,
temperature: Optional[float] = None,
max_tokens: Optional[int] = None
self, query: str, experiences: str, temperature: Optional[float] = None, max_tokens: Optional[int] = None
) -> str:
"""Generate response with experiences injected into prompt.
This is the core method for Training-Free GRPO rollout generation.
Args:
query: Problem/query to solve
experiences: Formatted experience library
temperature: Sampling temperature
max_tokens: Max tokens to generate
Returns:
response: Generated solution/output
"""
@@ -180,13 +165,9 @@ Now solve the problem step by step."""
{query}
Solve the problem step by step."""
return self.generate(
enhanced_prompt,
temperature=temperature,
max_tokens=max_tokens
)
return self.generate(enhanced_prompt, temperature=temperature, max_tokens=max_tokens)
def __repr__(self) -> str:
"""Return string representation."""
return f"APIModelAdapter(model={self.config.model}, base_url={self.config.base_url})"
@@ -194,74 +175,52 @@ Solve the problem step by step."""
class DeepSeekAdapter(APIModelAdapter):
"""Convenience wrapper for DeepSeek models.
Supports:
- deepseek-chat (V3, recommended for Training-Free GRPO)
- deepseek-reasoner (V3 with reasoning traces)
Example:
>>> adapter = DeepSeekAdapter(
... api_key="sk-xxx",
... model="deepseek-chat"
... )
>>> adapter = DeepSeekAdapter(api_key="sk-xxx", model="deepseek-chat")
>>> response = adapter.generate("Solve: x + 5 = 10")
"""
def __init__(
self,
api_key: str,
model: str = "deepseek-chat",
temperature: float = 0.7
):
def __init__(self, api_key: str, model: str = "deepseek-chat", temperature: float = 0.7):
"""Initialize DeepSeek adapter.
Args:
api_key: DeepSeek API key
model: Model name (deepseek-chat or deepseek-reasoner)
temperature: Sampling temperature
"""
config = APIModelConfig(
api_key=api_key,
base_url="https://api.deepseek.com/v1",
model=model,
temperature=temperature
api_key=api_key, base_url="https://api.deepseek.com/v1", model=model, temperature=temperature
)
super().__init__(config)
class OpenAIAdapter(APIModelAdapter):
"""Convenience wrapper for OpenAI models.
Supports:
- gpt-4o (latest GPT-4 Omni)
- gpt-4o-mini (smaller, faster, cheaper)
- o1-preview (reasoning model)
Example:
>>> adapter = OpenAIAdapter(
... api_key="sk-xxx",
... model="gpt-4o-mini"
... )
>>> adapter = OpenAIAdapter(api_key="sk-xxx", model="gpt-4o-mini")
>>> response = adapter.generate("Solve: x + 5 = 10")
"""
def __init__(
self,
api_key: str,
model: str = "gpt-4o-mini",
temperature: float = 0.7
):
def __init__(self, api_key: str, model: str = "gpt-4o-mini", temperature: float = 0.7):
"""Initialize OpenAI adapter.
Args:
api_key: OpenAI API key
model: Model name (gpt-4o, gpt-4o-mini, etc.)
temperature: Sampling temperature
"""
config = APIModelConfig(
api_key=api_key,
base_url="https://api.openai.com/v1",
model=model,
temperature=temperature
api_key=api_key, base_url="https://api.openai.com/v1", model=model, temperature=temperature
)
super().__init__(config)
+52 -61
View File
@@ -15,17 +15,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import asyncio
import os
import time
import asyncio
from typing import Tuple, Optional
from dataclasses import dataclass
from typing import Optional, Tuple
@dataclass
class EnhancedAPIModelConfig:
"""Enhanced configuration for API-hosted models with full feature support.
Attributes:
api_key: API key (can be set via HANZO_GRPO_API_KEY or DEEPSEEK_API_KEY env var)
base_url: API base URL (default: https://api.deepseek.com/v1)
@@ -38,6 +38,7 @@ class EnhancedAPIModelConfig:
timeout: Request timeout in seconds
support_reasoning: Whether model supports reasoning content (e.g., o1 models)
"""
api_key: str
base_url: str = "https://api.deepseek.com/v1"
model: str = "deepseek-chat"
@@ -48,28 +49,28 @@ class EnhancedAPIModelConfig:
retry_delay: float = 1.0
timeout: Optional[float] = None
support_reasoning: bool = False
@classmethod
def from_env(cls, **kwargs) -> "EnhancedAPIModelConfig":
"""Create config from environment variables with overrides.
Environment variables:
- HANZO_GRPO_API_KEY or DEEPSEEK_API_KEY: API key
- HANZO_GRPO_BASE_URL: API base URL
- HANZO_GRPO_MODEL: Model name
- HANZO_GRPO_MAX_RETRIES: Maximum retries
- HANZO_GRPO_TIMEOUT: Request timeout
Args:
**kwargs: Override any config parameter
Returns:
EnhancedAPIModelConfig instance
"""
api_key = kwargs.get("api_key") or os.getenv("HANZO_GRPO_API_KEY") or os.getenv("DEEPSEEK_API_KEY")
if not api_key:
raise ValueError("API key required. Set HANZO_GRPO_API_KEY or DEEPSEEK_API_KEY env var")
defaults = {
"api_key": api_key,
"base_url": os.getenv("HANZO_GRPO_BASE_URL", "https://api.deepseek.com/v1"),
@@ -77,16 +78,16 @@ class EnhancedAPIModelConfig:
"max_retries": int(os.getenv("HANZO_GRPO_MAX_RETRIES", "3")),
"timeout": float(os.getenv("HANZO_GRPO_TIMEOUT", "0")) or None,
}
# Merge with provided kwargs
defaults.update(kwargs)
return cls(**defaults)
class EnhancedAPIModelAdapter:
"""Enhanced API model adapter with retry, reasoning, and async support.
Features:
- Automatic retry with exponential backoff
- Reasoning content support (for o1 models)
@@ -94,27 +95,19 @@ class EnhancedAPIModelAdapter:
- Environment variable configuration
- Experience injection for Training-Free GRPO
"""
def __init__(self, config: EnhancedAPIModelConfig):
"""Initialize enhanced adapter.
Args:
config: Enhanced API model configuration
"""
from openai import OpenAI, AsyncOpenAI
self.config = config
self.client = OpenAI(
api_key=config.api_key,
base_url=config.base_url,
timeout=config.timeout
)
self.async_client = AsyncOpenAI(
api_key=config.api_key,
base_url=config.base_url,
timeout=config.timeout
)
self.client = OpenAI(api_key=config.api_key, base_url=config.base_url, timeout=config.timeout)
self.async_client = AsyncOpenAI(api_key=config.api_key, base_url=config.base_url, timeout=config.timeout)
def generate(
self,
prompt: str,
@@ -123,19 +116,19 @@ class EnhancedAPIModelAdapter:
return_reasoning: bool = False,
) -> str | Tuple[str, Optional[str]]:
"""Generate response with retry logic.
Args:
prompt: User prompt
temperature: Override default temperature
max_tokens: Override default max_tokens
return_reasoning: If True, return (response, reasoning) tuple
Returns:
Response string, or (response, reasoning) tuple if return_reasoning=True
"""
temp = temperature if temperature is not None else self.config.temperature
tokens = max_tokens if max_tokens is not None else self.config.max_tokens
for attempt in range(self.config.max_retries):
try:
response = self.client.chat.completions.create(
@@ -145,24 +138,24 @@ class EnhancedAPIModelAdapter:
max_tokens=tokens,
top_p=self.config.top_p,
)
response_text = response.choices[0].message.content.strip()
if return_reasoning and self.config.support_reasoning:
reasoning = getattr(response.choices[0].message, "reasoning_content", None)
return response_text, reasoning
return response_text
except Exception as e:
if attempt < self.config.max_retries - 1:
delay = self.config.retry_delay * (2 ** attempt)
delay = self.config.retry_delay * (2**attempt)
print(f"Generation failed (attempt {attempt + 1}/{self.config.max_retries}): {e}")
print(f"Retrying in {delay}s...")
time.sleep(delay)
else:
raise Exception(f"Generation failed after {self.config.max_retries} attempts: {e}")
async def generate_async(
self,
prompt: str,
@@ -172,23 +165,24 @@ class EnhancedAPIModelAdapter:
timeout: Optional[float] = None,
) -> str | Tuple[str, Optional[str]]:
"""Generate response asynchronously with timeout.
Args:
prompt: User prompt
temperature: Override default temperature
max_tokens: Override default max_tokens
return_reasoning: If True, return (response, reasoning) tuple
timeout: Request timeout (overrides config.timeout)
Returns:
Response string, or (response, reasoning) tuple if return_reasoning=True
"""
temp = temperature if temperature is not None else self.config.temperature
tokens = max_tokens if max_tokens is not None else self.config.max_tokens
request_timeout = timeout or self.config.timeout
for attempt in range(self.config.max_retries):
try:
async def make_request():
response = await self.async_client.chat.completions.create(
model=self.config.model,
@@ -198,23 +192,23 @@ class EnhancedAPIModelAdapter:
top_p=self.config.top_p,
)
return response
if request_timeout:
response = await asyncio.wait_for(make_request(), timeout=request_timeout)
else:
response = await make_request()
response_text = response.choices[0].message.content.strip()
if return_reasoning and self.config.support_reasoning:
reasoning = getattr(response.choices[0].message, "reasoning_content", None)
return response_text, reasoning
return response_text
except asyncio.TimeoutError:
if attempt < self.config.max_retries - 1:
delay = self.config.retry_delay * (2 ** attempt)
delay = self.config.retry_delay * (2**attempt)
print(f"Generation timeout (attempt {attempt + 1}/{self.config.max_retries})")
print(f"Retrying in {delay}s...")
await asyncio.sleep(delay)
@@ -222,13 +216,13 @@ class EnhancedAPIModelAdapter:
raise Exception(f"Generation timeout after {self.config.max_retries} attempts")
except Exception as e:
if attempt < self.config.max_retries - 1:
delay = self.config.retry_delay * (2 ** attempt)
delay = self.config.retry_delay * (2**attempt)
print(f"Generation failed (attempt {attempt + 1}/{self.config.max_retries}): {e}")
print(f"Retrying in {delay}s...")
await asyncio.sleep(delay)
else:
raise Exception(f"Generation failed after {self.config.max_retries} attempts: {e}")
def generate_with_experiences(
self,
query: str,
@@ -238,14 +232,14 @@ class EnhancedAPIModelAdapter:
return_reasoning: bool = False,
) -> str | Tuple[str, Optional[str]]:
"""Generate response with experiences injected into prompt.
Args:
query: User query/problem
experiences: Formatted experiences string
temperature: Override default temperature
max_tokens: Override default max_tokens
return_reasoning: If True, return (response, reasoning) tuple
Returns:
Response string, or (response, reasoning) tuple if return_reasoning=True
"""
@@ -262,14 +256,11 @@ Now solve the problem step by step."""
{query}
Solve the problem step by step."""
return self.generate(
enhanced_prompt,
temperature=temperature,
max_tokens=max_tokens,
return_reasoning=return_reasoning
enhanced_prompt, temperature=temperature, max_tokens=max_tokens, return_reasoning=return_reasoning
)
async def generate_with_experiences_async(
self,
query: str,
@@ -280,7 +271,7 @@ Solve the problem step by step."""
timeout: Optional[float] = None,
) -> str | Tuple[str, Optional[str]]:
"""Generate response with experiences asynchronously.
Args:
query: User query/problem
experiences: Formatted experiences string
@@ -288,7 +279,7 @@ Solve the problem step by step."""
max_tokens: Override default max_tokens
return_reasoning: If True, return (response, reasoning) tuple
timeout: Request timeout
Returns:
Response string, or (response, reasoning) tuple if return_reasoning=True
"""
@@ -305,19 +296,19 @@ Now solve the problem step by step."""
{query}
Solve the problem step by step."""
return await self.generate_async(
enhanced_prompt,
temperature=temperature,
max_tokens=max_tokens,
return_reasoning=return_reasoning,
timeout=timeout
timeout=timeout,
)
class EnhancedDeepSeekAdapter(EnhancedAPIModelAdapter):
"""Convenience wrapper for DeepSeek models with enhanced features."""
def __init__(
self,
api_key: Optional[str] = None,
@@ -327,7 +318,7 @@ class EnhancedDeepSeekAdapter(EnhancedAPIModelAdapter):
timeout: Optional[float] = None,
):
"""Initialize DeepSeek adapter with env var fallback.
Args:
api_key: API key (or set DEEPSEEK_API_KEY env var)
model: Model name
@@ -348,7 +339,7 @@ class EnhancedDeepSeekAdapter(EnhancedAPIModelAdapter):
class EnhancedOpenAIAdapter(EnhancedAPIModelAdapter):
"""Convenience wrapper for OpenAI models with enhanced features."""
def __init__(
self,
api_key: Optional[str] = None,
@@ -359,7 +350,7 @@ class EnhancedOpenAIAdapter(EnhancedAPIModelAdapter):
support_reasoning: bool = False,
):
"""Initialize OpenAI adapter with env var fallback.
Args:
api_key: API key (or set OPENAI_API_KEY env var)
model: Model name (e.g., "gpt-4o", "o1-preview")
+103 -102
View File
@@ -15,22 +15,24 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import asyncio
import os
import copy
import json
import os
import time
from collections import defaultdict
from concurrent.futures import ThreadPoolExecutor, as_completed
from dataclasses import dataclass
import asyncio
from typing import Any, Dict, List, Callable, Optional
from pathlib import Path
from typing import Any, Callable, Dict, List, Optional
from collections import defaultdict
from dataclasses import dataclass
from concurrent.futures import ThreadPoolExecutor, as_completed
try:
from tqdm import tqdm
TQDM_AVAILABLE = True
except ImportError:
TQDM_AVAILABLE = False
# Fallback progress indicator
class tqdm:
def __init__(self, iterable=None, total=None, desc=None, **kwargs):
@@ -38,10 +40,10 @@ except ImportError:
self.total = total
self.desc = desc
self.n = 0
def __iter__(self):
return iter(self.iterable) if self.iterable else iter([])
def update(self, n=1):
self.n += n
if self.desc and self.total:
@@ -62,6 +64,7 @@ class Trajectory:
retry_count: Number of retries attempted
task_time: Time taken for this trajectory in seconds
"""
query: str
output: str
reward: float
@@ -74,14 +77,14 @@ class Trajectory:
class EnhancedLLMClient:
"""Enhanced LLM client with retry logic, reasoning support, and env config.
Features:
- Automatic retry with exponential backoff
- Reasoning content support (for OpenAI o1 models)
- Environment variable configuration
- Max retries and timeout control
"""
def __init__(
self,
api_key: Optional[str] = None,
@@ -92,14 +95,14 @@ class EnhancedLLMClient:
timeout: Optional[float] = None,
):
"""Initialize LLM client with env var fallback.
Environment variables (if parameters not provided):
- HANZO_GRPO_API_KEY or DEEPSEEK_API_KEY
- HANZO_GRPO_BASE_URL
- HANZO_GRPO_MODEL
"""
from openai import OpenAI
# Use env vars as fallback
self.api_key = api_key or os.getenv("HANZO_GRPO_API_KEY") or os.getenv("DEEPSEEK_API_KEY")
self.base_url = base_url or os.getenv("HANZO_GRPO_BASE_URL", "https://api.deepseek.com/v1")
@@ -107,12 +110,12 @@ class EnhancedLLMClient:
self.max_retries = max_retries
self.retry_delay = retry_delay
self.timeout = timeout
if not self.api_key:
raise ValueError("API key required. Set HANZO_GRPO_API_KEY or pass api_key parameter.")
self.client = OpenAI(api_key=self.api_key, base_url=self.base_url, timeout=timeout)
def chat(
self,
prompt: str,
@@ -121,13 +124,13 @@ class EnhancedLLMClient:
return_reasoning: bool = False,
) -> str | tuple[str, Optional[str]]:
"""Call LLM with automatic retry logic.
Args:
prompt: User prompt
temperature: Sampling temperature
max_tokens: Maximum tokens to generate
return_reasoning: If True, return (response, reasoning) tuple
Returns:
Response string, or (response, reasoning) tuple if return_reasoning=True
"""
@@ -139,19 +142,19 @@ class EnhancedLLMClient:
temperature=temperature,
max_tokens=max_tokens,
)
response_text = response.choices[0].message.content.strip()
if return_reasoning:
# For OpenAI o1 models or models with reasoning_content
reasoning = getattr(response.choices[0].message, "reasoning_content", None)
return response_text, reasoning
return response_text
except Exception as e:
if attempt < self.max_retries - 1:
delay = self.retry_delay * (2 ** attempt) # Exponential backoff
delay = self.retry_delay * (2**attempt) # Exponential backoff
print(f"LLM call failed (attempt {attempt + 1}/{self.max_retries}): {e}")
print(f"Retrying in {delay}s...")
time.sleep(delay)
@@ -161,7 +164,7 @@ class EnhancedLLMClient:
class EnhancedSemanticExtractor:
"""Enhanced semantic extractor with full Tencent feature parity.
New Features:
- File caching for intermediate results (single_rollout_summary.json, etc.)
- Parallel processing with ThreadPoolExecutor
@@ -172,7 +175,7 @@ class EnhancedSemanticExtractor:
- Reasoning content support for o1 models
- Environment-based configuration
"""
def __init__(
self,
llm_client: EnhancedLLMClient,
@@ -184,7 +187,7 @@ class EnhancedSemanticExtractor:
filter_partial_correct: bool = True,
):
"""Initialize enhanced semantic extractor.
Args:
llm_client: Enhanced LLM client with retry logic
max_operations: Max operations per group critique
@@ -201,13 +204,13 @@ class EnhancedSemanticExtractor:
self.enable_caching = enable_caching
self.enable_parallel = enable_parallel
self.filter_partial_correct = filter_partial_correct
def _get_cache_path(self, filename: str) -> Optional[Path]:
"""Get cache file path if caching enabled."""
if not self.enable_caching or not self.cache_dir:
return None
return Path(self.cache_dir) / filename
def _load_cache(self, filename: str) -> Optional[Any]:
"""Load from cache if exists."""
cache_path = self._get_cache_path(filename)
@@ -218,7 +221,7 @@ class EnhancedSemanticExtractor:
print(f"Loaded from cache: {cache_path}")
return data
return None
def _save_cache(self, filename: str, data: Any):
"""Save to cache."""
cache_path = self._get_cache_path(filename)
@@ -227,18 +230,18 @@ class EnhancedSemanticExtractor:
with open(cache_path, "w") as f:
json.dump(data, f, indent=2)
print(f"Saved to cache: {cache_path}")
def summarize_trajectories(
self,
trajectories: List[Trajectory],
use_groundtruth: bool = True,
) -> Dict[str, List[Trajectory]]:
"""Stage 1: Summarize trajectories step-by-step with caching and parallel processing.
Args:
trajectories: List of trajectories to summarize
use_groundtruth: Whether to use ground truth in summarization
Returns:
Dict mapping query to list of summarized trajectories
"""
@@ -250,12 +253,12 @@ class EnhancedSemanticExtractor:
for query, trajs in cached.items():
result[query] = [Trajectory(**t) for t in trajs]
return result
# Group by query
query_to_trajectories = defaultdict(list)
for traj in trajectories:
query_to_trajectories[traj.query].append(traj)
# Filter to partial correct groups if enabled
all_trajectories_to_process = []
for trajs in query_to_trajectories.values():
@@ -266,7 +269,7 @@ class EnhancedSemanticExtractor:
all_trajectories_to_process.extend(trajs)
else:
all_trajectories_to_process.extend(trajs)
def process_trajectory(traj: Trajectory) -> Optional[Trajectory]:
"""Process single trajectory with LLM."""
try:
@@ -299,7 +302,7 @@ Only return the trajectory summary of each step, e.g.,
</trajectory>
Only return the trajectory summary of each step."""
summary = self.llm.chat(prompt)
result = copy.copy(traj)
result.summary = summary
@@ -307,21 +310,20 @@ Only return the trajectory summary of each step."""
except Exception as e:
print(f"Warning: Failed to summarize trajectory: {e}")
return None
# Parallel or sequential processing
results = defaultdict(list)
if self.enable_parallel and self.max_workers > 1:
with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
future_to_traj = {
executor.submit(process_trajectory, traj): traj
for traj in all_trajectories_to_process
executor.submit(process_trajectory, traj): traj for traj in all_trajectories_to_process
}
iterator = as_completed(future_to_traj)
if TQDM_AVAILABLE:
iterator = tqdm(iterator, total=len(all_trajectories_to_process), desc="Summarizing trajectories")
for future in iterator:
result = future.result()
if result:
@@ -331,22 +333,30 @@ Only return the trajectory summary of each step."""
iterator = all_trajectories_to_process
if TQDM_AVAILABLE:
iterator = tqdm(iterator, desc="Summarizing trajectories")
for traj in iterator:
result = process_trajectory(traj)
if result:
results[result.query].append(result)
# Save to cache
cache_data = {
query: [{"query": t.query, "output": t.output, "reward": t.reward,
"groundtruth": t.groundtruth, "summary": t.summary} for t in trajs]
query: [
{
"query": t.query,
"output": t.output,
"reward": t.reward,
"groundtruth": t.groundtruth,
"summary": t.summary,
}
for t in trajs
]
for query, trajs in results.items()
}
self._save_cache("single_rollout_summary.json", cache_data)
return results
def extract_group_advantages(
self,
query_to_summarized_trajectories: Dict[str, List[Trajectory]],
@@ -354,12 +364,12 @@ Only return the trajectory summary of each step."""
use_groundtruth: bool = True,
) -> List[Dict]:
"""Stage 2: Extract group advantages from summarized trajectories.
Args:
query_to_summarized_trajectories: Dict of query to summarized trajectories
experiences: Formatted experiences string
use_groundtruth: Whether to use ground truth
Returns:
List of critique dictionaries with operations
"""
@@ -367,7 +377,7 @@ Only return the trajectory summary of each step."""
cached = self._load_cache("single_query_critique.json")
if cached:
return cached
# Filter to partial correct groups if enabled
all_groups = []
for trajs in query_to_summarized_trajectories.values():
@@ -378,18 +388,20 @@ Only return the trajectory summary of each step."""
all_groups.append(trajs)
else:
all_groups.append(trajs)
def process_group(trajs: List[Trajectory]) -> Optional[Dict]:
"""Process single group of trajectories."""
try:
query = trajs[0].query
groundtruth = trajs[0].groundtruth if use_groundtruth else None
formatted_trajs = "\n\n".join([
f"Trajectory {i+1} (Answer {'correct' if t.reward > 0 else 'wrong'}):\n{t.summary}"
for i, t in enumerate(trajs)
])
formatted_trajs = "\n\n".join(
[
f"Trajectory {i + 1} (Answer {'correct' if t.reward > 0 else 'wrong'}):\n{t.summary}"
for i, t in enumerate(trajs)
]
)
if use_groundtruth and groundtruth:
prompt = f"""Given the problem and several trajectory summaries with grading, generate semantic experiences that could help future rollouts.
@@ -420,34 +432,27 @@ Trajectories:
Generate up to {self.max_operations} operations to update experiences.
Return JSON array: [{{"option": "add", "experience": "..."}}, ...]"""
response = self.llm.chat(prompt)
response_clean = response.split("```json")[-1].split("```")[0].strip()
operations = json.loads(response_clean)
return {
"trajectories": trajs,
"critique": response,
"operations": operations[:self.max_operations]
}
return {"trajectories": trajs, "critique": response, "operations": operations[: self.max_operations]}
except Exception as e:
print(f"Warning: Failed to extract group advantage: {e}")
return None
# Parallel or sequential processing
results = []
if self.enable_parallel and self.max_workers > 1:
with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
future_to_group = {
executor.submit(process_group, trajs): trajs
for trajs in all_groups
}
future_to_group = {executor.submit(process_group, trajs): trajs for trajs in all_groups}
iterator = as_completed(future_to_group)
if TQDM_AVAILABLE:
iterator = tqdm(iterator, total=len(all_groups), desc="Extracting group advantages")
for future in iterator:
result = future.result()
if result:
@@ -456,28 +461,28 @@ Return JSON array: [{{"option": "add", "experience": "..."}}, ...]"""
iterator = all_groups
if TQDM_AVAILABLE:
iterator = tqdm(iterator, desc="Extracting group advantages")
for trajs in iterator:
result = process_group(trajs)
if result:
results.append(result)
# Save to cache
self._save_cache("single_query_critique.json", results)
return results
def consolidate_batch(
self,
all_group_operations: List[List[Dict]],
experiences: Dict[str, str],
) -> Dict[str, str]:
"""Stage 3: Consolidate all group operations into final experience updates.
Args:
all_group_operations: List of operation lists from each group
experiences: Current experience dictionary
Returns:
Updated experience dictionary
"""
@@ -485,21 +490,21 @@ Return JSON array: [{{"option": "add", "experience": "..."}}, ...]"""
cached = self._load_cache("batch_update.json")
if cached:
return cached.get("new_experiences", experiences)
print("Batch consolidation")
# Collect all operations
all_operations = []
for ops in all_group_operations:
all_operations.extend(ops)
print(f"- Total operations to process: {len(all_operations)}")
# Split into add and modify operations
candidate_experiences = copy.deepcopy(experiences)
to_modify = []
max_id = 0
for operation in all_operations:
if operation.get("option") == "modify":
if operation.get("modified_from") in candidate_experiences:
@@ -507,11 +512,11 @@ Return JSON array: [{{"option": "add", "experience": "..."}}, ...]"""
elif operation.get("option") == "add":
candidate_experiences[f"C{max_id}"] = operation["experience"]
max_id += 1
print(f"- Added experiences: {max_id}")
print(f"- Experiences to modify: {len(to_modify)}")
print(f"- Candidate experiences: {len(candidate_experiences)}")
# Use LLM to create revision plan
if len(to_modify) > 0:
prompt = f"""Given candidate experiences and modification requests, create a revision plan.
@@ -527,7 +532,7 @@ Create a revision plan as JSON array with operations:
- {{"option": "merge", "merged_from": ["ID1", "ID2"], "experience": "..."}}
Return only the JSON array."""
try:
response = self.llm.chat(prompt)
response_clean = response.split("```json")[-1].split("```")[0].strip()
@@ -537,7 +542,7 @@ Return only the JSON array."""
revision_plan = []
else:
revision_plan = []
# Apply revision plan
new_experiences = copy.deepcopy(candidate_experiences)
for operation in revision_plan:
@@ -552,9 +557,9 @@ Return only the JSON array."""
max_id += 1
except Exception as e:
print(f"Error applying operation {operation}: {e}")
print(f"- Final experiences: {len(new_experiences)}")
# Save to cache
cache_data = {
"operations": all_operations,
@@ -562,30 +567,26 @@ Return only the JSON array."""
"new_experiences": new_experiences,
}
self._save_cache("batch_update.json", cache_data)
# Reassign IDs
final_experiences = {f"G{i}": exp for i, exp in enumerate(new_experiences.values())}
return final_experiences
# Async rollout support with timeout
async def rollout_with_timeout(
generate_func: Callable,
query: str,
timeout: float = 3600,
max_retries: int = 3,
**kwargs
generate_func: Callable, query: str, timeout: float = 3600, max_retries: int = 3, **kwargs
) -> Optional[str]:
"""Execute rollout with timeout and retry support.
Args:
generate_func: Function to call for generation (must be async-compatible)
query: Query/prompt to generate from
timeout: Timeout in seconds
max_retries: Maximum retry attempts
**kwargs: Additional arguments to pass to generate_func
Returns:
Generated response or None if failed
"""
@@ -596,21 +597,21 @@ async def rollout_with_timeout(
coro = generate_func(query, **kwargs)
else:
coro = asyncio.to_thread(generate_func, query, **kwargs)
result = await asyncio.wait_for(coro, timeout=timeout)
return result
except asyncio.TimeoutError:
print(f"Rollout timeout (attempt {attempt + 1}/{max_retries})")
if attempt < max_retries - 1:
await asyncio.sleep(2 ** attempt) # Exponential backoff
await asyncio.sleep(2**attempt) # Exponential backoff
else:
print(f"Rollout failed after {max_retries} timeout attempts")
return None
except Exception as e:
print(f"Rollout error (attempt {attempt + 1}/{max_retries}): {e}")
if attempt < max_retries - 1:
await asyncio.sleep(2 ** attempt)
await asyncio.sleep(2**attempt)
else:
print(f"Rollout failed after {max_retries} attempts")
return None
+24 -27
View File
@@ -15,8 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import Dict, List, Literal
import json
from typing import Dict, List, Literal
from pathlib import Path
Operation = Literal["add", "delete", "modify", "merge", "keep"]
@@ -24,11 +24,11 @@ Operation = Literal["add", "delete", "modify", "merge", "keep"]
class ExperienceManager:
"""Manages the experience library E for Training-Free GRPO.
The experience library stores generalizable strategic insights extracted
from trajectory groups. Each experience is a concise (≤32 words) natural
language statement that guides future problem-solving.
Example experiences:
- "When solving equations, verify solutions by substitution to catch errors."
- "For optimization problems, check boundary conditions before applying calculus."
@@ -37,7 +37,7 @@ class ExperienceManager:
def __init__(self, checkpoint_path: str = None):
"""Initialize experience manager.
Args:
checkpoint_path: Path to load/save experiences (JSON format)
"""
@@ -50,10 +50,10 @@ class ExperienceManager:
def add(self, experience: str) -> str:
"""Add new experience, return assigned ID.
Args:
experience: Natural language experience statement (≤32 words)
Returns:
exp_id: Assigned experience ID (format: "G{N}")
"""
@@ -64,10 +64,10 @@ class ExperienceManager:
def delete(self, exp_id: str) -> bool:
"""Delete experience by ID.
Args:
exp_id: Experience ID to delete
Returns:
success: True if deleted, False if ID not found
"""
@@ -78,11 +78,11 @@ class ExperienceManager:
def modify(self, exp_id: str, new_experience: str) -> bool:
"""Modify existing experience.
Args:
exp_id: Experience ID to modify
new_experience: New experience text
Returns:
success: True if modified, False if ID not found
"""
@@ -93,13 +93,13 @@ class ExperienceManager:
def merge(self, exp_ids: List[str], merged_experience: str) -> str:
"""Merge multiple experiences into one.
Deletes the original experiences and creates a new merged one.
Args:
exp_ids: List of experience IDs to merge
merged_experience: Merged experience text
Returns:
new_exp_id: ID of the newly created merged experience
"""
@@ -111,10 +111,10 @@ class ExperienceManager:
def apply_operations(self, operations: List[Dict]) -> None:
"""Apply batch of operations from LLM.
This is the main interface for updating the experience library based
on LLM-extracted semantic advantages.
Args:
operations: List of operation dictionaries with keys:
- "option": One of ["add", "modify", "delete", "merge", "keep"]
@@ -122,7 +122,7 @@ class ExperienceManager:
- "modified_from": Original experience ID (for modify)
- "delete_id": Experience ID to delete (for delete)
- "merged_from": List of experience IDs to merge (for merge)
Example:
operations = [
{"option": "add", "experience": "When solving..."},
@@ -145,15 +145,15 @@ class ExperienceManager:
elif option == "merge":
self.merge(op["merged_from"], op["experience"])
# "keep" option does nothing
def format_for_prompt(self) -> str:
"""Format experiences for injection into prompts.
Returns:
formatted: Multi-line string with numbered experiences
Example output:
[G0]. When solving equations, verify solutions by substitution.
[G1]. For optimization, check boundary conditions first.
@@ -170,21 +170,18 @@ class ExperienceManager:
def save(self, path: str) -> None:
"""Save experiences to JSON file.
Args:
path: Output file path
"""
Path(path).parent.mkdir(parents=True, exist_ok=True)
with open(path, 'w') as f:
json.dump({
"experiences": self.experiences,
"next_id": self._next_id
}, f, indent=2)
with open(path, "w") as f:
json.dump({"experiences": self.experiences, "next_id": self._next_id}, f, indent=2)
def load(self, path: str) -> None:
"""Load experiences from JSON file.
Args:
path: Input file path
"""
+44 -62
View File
@@ -15,16 +15,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import List, Dict, Optional, Any
from dataclasses import dataclass
import json
import re
import json
from typing import Any, Dict, List, Optional
from dataclasses import dataclass
@dataclass
class Trajectory:
"""Single rollout trajectory.
Attributes:
query: Input query/problem statement
output: Model-generated output/response
@@ -32,6 +32,7 @@ class Trajectory:
groundtruth: Optional ground truth answer for supervised learning
summary: Optional LLM-generated step-by-step summary
"""
query: str
output: str
reward: float
@@ -41,19 +42,19 @@ class Trajectory:
class SemanticExtractor:
"""Extracts semantic advantages from groups of trajectories.
Implements the 3-stage LLM process from Training-Free GRPO paper:
1. Trajectory Summarization (Figure 11): Analyze each rollout step-by-step
2. Group Advantage Extraction (Figure 12): Compare G trajectories to identify patterns
3. Batch Consolidation (Figure 13): Merge/modify/delete experiences across batch
This replaces numerical advantages with natural language experiences,
enabling learning without parameter updates.
"""
def __init__(self, llm_client: Any, max_operations: int = 3):
"""Initialize semantic extractor.
Args:
llm_client: LLM client with .chat() method (e.g., OpenAI, DeepSeek)
max_operations: Max operations per group critique (default: 3)
@@ -65,38 +66,34 @@ class SemanticExtractor:
# STAGE 1: Trajectory Summarization (Figure 11)
# =========================================================================
def summarize_trajectory(
self,
trajectory: Trajectory,
use_groundtruth: bool = True
) -> str:
def summarize_trajectory(self, trajectory: Trajectory, use_groundtruth: bool = True) -> str:
"""Summarize a single trajectory step-by-step.
This stage analyzes what happened in each step of the trajectory,
identifies which experiences were used, and highlights any errors
or detours that occurred.
Args:
trajectory: Trajectory to summarize
use_groundtruth: Whether to include ground truth in prompt
Returns:
summary: Step-by-step analysis of the trajectory
"""
# Determine evaluation status
evaluation = (
"This trajectory delivers **correct** answer"
if trajectory.reward > 0
"This trajectory delivers **correct** answer"
if trajectory.reward > 0
else "This trajectory delivers **wrong** answer"
)
# Include groundtruth if available and requested
groundtruth_section = (
f"\n<groundtruth>{trajectory.groundtruth}</groundtruth>"
if use_groundtruth and trajectory.groundtruth
f"\n<groundtruth>{trajectory.groundtruth}</groundtruth>"
if use_groundtruth and trajectory.groundtruth
else ""
)
prompt = f"""An agent system may be provided with some experiences, and then it produces the following trajectory to solve the given problem. Please summarize the trajectory step-by-step:
1. For each step, describe what action is being taken, and which experience has been used in this step.
@@ -124,22 +121,19 @@ Only return the trajectory summary of each step, e.g.,
# =========================================================================
def extract_group_advantage(
self,
trajectories: List[Trajectory],
experiences: str,
use_groundtruth: bool = True
self, trajectories: List[Trajectory], experiences: str, use_groundtruth: bool = True
) -> List[Dict]:
"""Extract semantic advantage from a group of trajectories.
This stage compares multiple trajectories (both correct and incorrect)
to identify patterns, extract insights, and propose updates to the
experience library.
Args:
trajectories: List of G trajectories for the same query
experiences: Formatted experience library string
use_groundtruth: Whether to include ground truth in prompt
Returns:
operations: List of operations to apply to experience library
Example: [
@@ -157,16 +151,14 @@ Only return the trajectory summary of each step, e.g.,
for i, traj in enumerate(trajectories):
status = "correct" if traj.reward > 0 else "wrong"
content = traj.summary or traj.output
formatted_trajectories.append(
f"Attempt {i+1} (Answer {status}):\n{content}"
)
formatted_trajectories.append(f"Attempt {i + 1} (Answer {status}):\n{content}")
trajectories_text = "\n\n".join(formatted_trajectories)
# Include groundtruth if available
groundtruth_section = (
f"\n<groundtruth>{trajectories[0].groundtruth}</groundtruth>"
if use_groundtruth and trajectories[0].groundtruth
f"\n<groundtruth>{trajectories[0].groundtruth}</groundtruth>"
if use_groundtruth and trajectories[0].groundtruth
else ""
)
@@ -238,23 +230,19 @@ Note that your updated experiences may not need to cover all the options.
# STAGE 3: Batch Consolidation (Figure 13)
# =========================================================================
def consolidate_batch(
self,
all_group_operations: List[List[Dict]],
experiences: str
) -> List[Dict]:
def consolidate_batch(self, all_group_operations: List[List[Dict]], experiences: str) -> List[Dict]:
"""Consolidate all group advantages into final experience updates.
This stage merges operations from all groups in the batch, ensuring:
- Experiences are ≤32 words
- No redundancy between experiences
- Strategic focus (not specific calculations)
- Generalizable insights
Args:
all_group_operations: List of operations from each group
experiences: Current formatted experience library
Returns:
final_operations: Consolidated list of operations to apply
"""
@@ -318,25 +306,21 @@ After generating the step-by-step reasoning, you need to give the final experien
# Helper Methods
# =========================================================================
def _parse_json_operations(
self,
response: str,
max_ops: Optional[int] = None
) -> List[Dict]:
def _parse_json_operations(self, response: str, max_ops: Optional[int] = None) -> List[Dict]:
"""Parse JSON operations from LLM response.
Extracts JSON block from markdown code fence and validates format.
Args:
response: LLM response text
max_ops: Optional limit on number of operations
Returns:
operations: List of operation dictionaries
"""
# Extract JSON block from markdown code fence
json_match = re.search(r'```json\s*(.*?)\s*```', response, re.DOTALL)
json_match = re.search(r"```json\s*(.*?)\s*```", response, re.DOTALL)
if json_match:
try:
operations = json.loads(json_match.group(1))
@@ -351,7 +335,7 @@ After generating the step-by-step reasoning, you need to give the final experien
# Also try to find plain JSON arrays (without code fence)
try:
# Look for array pattern
array_match = re.search(r'\[\s*\{.*?\}\s*\]', response, re.DOTALL)
array_match = re.search(r"\[\s*\{.*?\}\s*\]", response, re.DOTALL)
if array_match:
operations = json.loads(array_match.group(0))
if max_ops:
@@ -365,14 +349,14 @@ After generating the step-by-step reasoning, you need to give the final experien
class LLMClient:
"""Simple wrapper for LLM API clients.
Provides a unified .chat() interface for various LLM providers.
Supports OpenAI-compatible APIs (OpenAI, DeepSeek, etc.).
"""
def __init__(self, api_key: str, base_url: str = "https://api.deepseek.com/v1", model: str = "deepseek-chat"):
"""Initialize LLM client.
Args:
api_key: API key for the LLM service
base_url: Base URL for the API endpoint
@@ -381,21 +365,19 @@ class LLMClient:
try:
from openai import OpenAI
except ImportError:
raise ImportError(
"OpenAI package not found. Install with: pip install openai"
)
raise ImportError("OpenAI package not found. Install with: pip install openai")
self.client = OpenAI(api_key=api_key, base_url=base_url)
self.model = model
def chat(self, prompt: str, temperature: float = 0.7, max_tokens: int = 4096) -> str:
"""Send chat request to LLM.
Args:
prompt: User prompt
temperature: Sampling temperature (default: 0.7)
max_tokens: Max tokens to generate (default: 4096)
Returns:
response: LLM response text
"""
@@ -403,7 +385,7 @@ class LLMClient:
model=self.model,
messages=[{"role": "user", "content": prompt}],
temperature=temperature,
max_tokens=max_tokens
max_tokens=max_tokens,
)
return response.choices[0].message.content
+2 -6
View File
@@ -98,9 +98,7 @@ class SimpleLLMClient:
"scope": "openid profile email",
"state": "hanzoai-login",
}
auth_url = (
f"{HANZO_IAM_BASE}/login/oauth/authorize?{urlencode(auth_params)}"
)
auth_url = f"{HANZO_IAM_BASE}/login/oauth/authorize?{urlencode(auth_params)}"
print(f"Opening browser for Hanzo AI login...")
print(f"If browser doesn't open, visit: {auth_url}")
@@ -121,9 +119,7 @@ class SimpleLLMClient:
except Exception as e:
print(f"IAM login failed: {e}")
print(
"Please set HANZO_API_KEY environment variable or pass api_key parameter"
)
print("Please set HANZO_API_KEY environment variable or pass api_key parameter")
def completion(self, **kwargs):
"""
+4 -12
View File
@@ -36,9 +36,7 @@ except ImportError:
# Provide a helpful error message
def _mcp_not_installed(*args, **kwargs):
raise ImportError(
"hanzo-mcp is not installed. Install it with: pip install hanzo-mcp"
)
raise ImportError("hanzo-mcp is not installed. Install it with: pip install hanzo-mcp")
# Create placeholder classes/functions
HanzoMCPServer = create_server = _mcp_not_installed
@@ -63,9 +61,7 @@ def create_mcp_server(name: str = "hanzo-mcp", allowed_paths: list = None, **kwa
HanzoMCPServer instance
"""
if not MCP_AVAILABLE:
raise ImportError(
"hanzo-mcp is not installed. Install it with: pip install hanzo-mcp"
)
raise ImportError("hanzo-mcp is not installed. Install it with: pip install hanzo-mcp")
return create_server(name=name, allowed_paths=allowed_paths, **kwargs)
@@ -79,9 +75,7 @@ def run_mcp_server(name: str = "hanzo-mcp", transport: str = "stdio", **kwargs):
**kwargs: Additional server options
"""
if not MCP_AVAILABLE:
raise ImportError(
"hanzo-mcp is not installed. Install it with: pip install hanzo-mcp"
)
raise ImportError("hanzo-mcp is not installed. Install it with: pip install hanzo-mcp")
server = create_server(name=name, **kwargs)
server.run(transport=transport)
@@ -97,9 +91,7 @@ class MCPClient:
server_command: Command to start the server (e.g., ["python", "-m", "hanzo_mcp"])
"""
if not MCP_AVAILABLE:
raise ImportError(
"hanzo-mcp is not installed. Install it with: pip install hanzo-mcp"
)
raise ImportError("hanzo-mcp is not installed. Install it with: pip install hanzo-mcp")
self.server_command = server_command or ["python", "-m", "hanzo_mcp"]
self._client = None
+2 -6
View File
@@ -68,9 +68,7 @@ class AddResource(SyncAPIResource):
"""
return self._post(
"/add/allowed_ip",
body=maybe_transform(
{"ip": ip}, add_add_allowed_ip_params.AddAddAllowedIPParams
),
body=maybe_transform({"ip": ip}, add_add_allowed_ip_params.AddAddAllowedIPParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -126,9 +124,7 @@ class AsyncAddResource(AsyncAPIResource):
"""
return await self._post(
"/add/allowed_ip",
body=await async_maybe_transform(
{"ip": ip}, add_add_allowed_ip_params.AddAddAllowedIPParams
),
body=await async_maybe_transform({"ip": ip}, add_add_allowed_ip_params.AddAddAllowedIPParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
+10 -30
View File
@@ -62,9 +62,7 @@ class AnthropicResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._post(
f"/anthropic/{endpoint}",
options=make_request_options(
@@ -100,9 +98,7 @@ class AnthropicResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._get(
f"/anthropic/{endpoint}",
options=make_request_options(
@@ -138,9 +134,7 @@ class AnthropicResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._put(
f"/anthropic/{endpoint}",
options=make_request_options(
@@ -176,9 +170,7 @@ class AnthropicResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._delete(
f"/anthropic/{endpoint}",
options=make_request_options(
@@ -214,9 +206,7 @@ class AnthropicResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._patch(
f"/anthropic/{endpoint}",
options=make_request_options(
@@ -273,9 +263,7 @@ class AsyncAnthropicResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._post(
f"/anthropic/{endpoint}",
options=make_request_options(
@@ -311,9 +299,7 @@ class AsyncAnthropicResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._get(
f"/anthropic/{endpoint}",
options=make_request_options(
@@ -349,9 +335,7 @@ class AsyncAnthropicResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._put(
f"/anthropic/{endpoint}",
options=make_request_options(
@@ -387,9 +371,7 @@ class AsyncAnthropicResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._delete(
f"/anthropic/{endpoint}",
options=make_request_options(
@@ -425,9 +407,7 @@ class AsyncAnthropicResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._patch(
f"/anthropic/{endpoint}",
options=make_request_options(
+10 -30
View File
@@ -62,9 +62,7 @@ class AssemblyaiResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._post(
f"/assemblyai/{endpoint}",
options=make_request_options(
@@ -100,9 +98,7 @@ class AssemblyaiResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._get(
f"/assemblyai/{endpoint}",
options=make_request_options(
@@ -138,9 +134,7 @@ class AssemblyaiResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._put(
f"/assemblyai/{endpoint}",
options=make_request_options(
@@ -176,9 +170,7 @@ class AssemblyaiResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._delete(
f"/assemblyai/{endpoint}",
options=make_request_options(
@@ -214,9 +206,7 @@ class AssemblyaiResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._patch(
f"/assemblyai/{endpoint}",
options=make_request_options(
@@ -273,9 +263,7 @@ class AsyncAssemblyaiResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._post(
f"/assemblyai/{endpoint}",
options=make_request_options(
@@ -311,9 +299,7 @@ class AsyncAssemblyaiResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._get(
f"/assemblyai/{endpoint}",
options=make_request_options(
@@ -349,9 +335,7 @@ class AsyncAssemblyaiResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._put(
f"/assemblyai/{endpoint}",
options=make_request_options(
@@ -387,9 +371,7 @@ class AsyncAssemblyaiResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._delete(
f"/assemblyai/{endpoint}",
options=make_request_options(
@@ -425,9 +407,7 @@ class AsyncAssemblyaiResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._patch(
f"/assemblyai/{endpoint}",
options=make_request_options(
+2 -6
View File
@@ -119,9 +119,7 @@ class AssistantsResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not assistant_id:
raise ValueError(
f"Expected a non-empty value for `assistant_id` but received {assistant_id!r}"
)
raise ValueError(f"Expected a non-empty value for `assistant_id` but received {assistant_id!r}")
return self._delete(
f"/v1/assistants/{assistant_id}",
options=make_request_options(
@@ -235,9 +233,7 @@ class AsyncAssistantsResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not assistant_id:
raise ValueError(
f"Expected a non-empty value for `assistant_id` but received {assistant_id!r}"
)
raise ValueError(f"Expected a non-empty value for `assistant_id` but received {assistant_id!r}")
return await self._delete(
f"/v1/assistants/{assistant_id}",
options=make_request_options(
+1 -3
View File
@@ -131,6 +131,4 @@ class AsyncAudioResourceWithStreamingResponse:
@cached_property
def transcriptions(self) -> AsyncTranscriptionsResourceWithStreamingResponse:
return AsyncTranscriptionsResourceWithStreamingResponse(
self._audio.transcriptions
)
return AsyncTranscriptionsResourceWithStreamingResponse(self._audio.transcriptions)
@@ -80,9 +80,7 @@ class TranscriptionsResource(SyncAPIResource):
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._post(
"/v1/audio/transcriptions",
body=maybe_transform(
body, transcription_create_params.TranscriptionCreateParams
),
body=maybe_transform(body, transcription_create_params.TranscriptionCreateParams),
files=files,
options=make_request_options(
extra_headers=extra_headers,
@@ -149,9 +147,7 @@ class AsyncTranscriptionsResource(AsyncAPIResource):
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._post(
"/v1/audio/transcriptions",
body=await async_maybe_transform(
body, transcription_create_params.TranscriptionCreateParams
),
body=await async_maybe_transform(body, transcription_create_params.TranscriptionCreateParams),
files=files,
options=make_request_options(
extra_headers=extra_headers,
+10 -30
View File
@@ -64,9 +64,7 @@ class AzureResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._post(
f"/azure/{endpoint}",
options=make_request_options(
@@ -104,9 +102,7 @@ class AzureResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._put(
f"/azure/{endpoint}",
options=make_request_options(
@@ -144,9 +140,7 @@ class AzureResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._delete(
f"/azure/{endpoint}",
options=make_request_options(
@@ -184,9 +178,7 @@ class AzureResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._get(
f"/azure/{endpoint}",
options=make_request_options(
@@ -224,9 +216,7 @@ class AzureResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._patch(
f"/azure/{endpoint}",
options=make_request_options(
@@ -285,9 +275,7 @@ class AsyncAzureResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._post(
f"/azure/{endpoint}",
options=make_request_options(
@@ -325,9 +313,7 @@ class AsyncAzureResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._put(
f"/azure/{endpoint}",
options=make_request_options(
@@ -365,9 +351,7 @@ class AsyncAzureResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._delete(
f"/azure/{endpoint}",
options=make_request_options(
@@ -405,9 +389,7 @@ class AsyncAzureResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._get(
f"/azure/{endpoint}",
options=make_request_options(
@@ -445,9 +427,7 @@ class AsyncAzureResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._patch(
f"/azure/{endpoint}",
options=make_request_options(
+18 -54
View File
@@ -105,9 +105,7 @@ class BatchesResource(SyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=maybe_transform(
{"provider": provider}, batch_create_params.BatchCreateParams
),
query=maybe_transform({"provider": provider}, batch_create_params.BatchCreateParams),
),
cast_to=object,
)
@@ -148,9 +146,7 @@ class BatchesResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not batch_id:
raise ValueError(
f"Expected a non-empty value for `batch_id` but received {batch_id!r}"
)
raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}")
return self._get(
f"/v1/batches/{batch_id}",
options=make_request_options(
@@ -158,9 +154,7 @@ class BatchesResource(SyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=maybe_transform(
{"provider": provider}, batch_retrieve_params.BatchRetrieveParams
),
query=maybe_transform({"provider": provider}, batch_retrieve_params.BatchRetrieveParams),
),
cast_to=object,
)
@@ -253,13 +247,9 @@ class BatchesResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
if not batch_id:
raise ValueError(
f"Expected a non-empty value for `batch_id` but received {batch_id!r}"
)
raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}")
return self._post(
f"/{provider}/v1/batches/{batch_id}/cancel",
options=make_request_options(
@@ -308,9 +298,7 @@ class BatchesResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
return self._post(
f"/{provider}/v1/batches",
options=make_request_options(
@@ -355,9 +343,7 @@ class BatchesResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
return self._get(
f"/{provider}/v1/batches",
options=make_request_options(
@@ -412,13 +398,9 @@ class BatchesResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
if not batch_id:
raise ValueError(
f"Expected a non-empty value for `batch_id` but received {batch_id!r}"
)
raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}")
return self._get(
f"/{provider}/v1/batches/{batch_id}",
options=make_request_options(
@@ -498,9 +480,7 @@ class AsyncBatchesResource(AsyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=await async_maybe_transform(
{"provider": provider}, batch_create_params.BatchCreateParams
),
query=await async_maybe_transform({"provider": provider}, batch_create_params.BatchCreateParams),
),
cast_to=object,
)
@@ -541,9 +521,7 @@ class AsyncBatchesResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not batch_id:
raise ValueError(
f"Expected a non-empty value for `batch_id` but received {batch_id!r}"
)
raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}")
return await self._get(
f"/v1/batches/{batch_id}",
options=make_request_options(
@@ -551,9 +529,7 @@ class AsyncBatchesResource(AsyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=await async_maybe_transform(
{"provider": provider}, batch_retrieve_params.BatchRetrieveParams
),
query=await async_maybe_transform({"provider": provider}, batch_retrieve_params.BatchRetrieveParams),
),
cast_to=object,
)
@@ -646,13 +622,9 @@ class AsyncBatchesResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
if not batch_id:
raise ValueError(
f"Expected a non-empty value for `batch_id` but received {batch_id!r}"
)
raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}")
return await self._post(
f"/{provider}/v1/batches/{batch_id}/cancel",
options=make_request_options(
@@ -701,9 +673,7 @@ class AsyncBatchesResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
return await self._post(
f"/{provider}/v1/batches",
options=make_request_options(
@@ -748,9 +718,7 @@ class AsyncBatchesResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
return await self._get(
f"/{provider}/v1/batches",
options=make_request_options(
@@ -805,13 +773,9 @@ class AsyncBatchesResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
if not batch_id:
raise ValueError(
f"Expected a non-empty value for `batch_id` but received {batch_id!r}"
)
raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}")
return await self._get(
f"/{provider}/v1/batches/{batch_id}",
options=make_request_options(
+4 -12
View File
@@ -82,9 +82,7 @@ class CancelResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not batch_id:
raise ValueError(
f"Expected a non-empty value for `batch_id` but received {batch_id!r}"
)
raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}")
return self._post(
f"/batches/{batch_id}/cancel",
options=make_request_options(
@@ -92,9 +90,7 @@ class CancelResource(SyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=maybe_transform(
{"provider": provider}, cancel_cancel_params.CancelCancelParams
),
query=maybe_transform({"provider": provider}, cancel_cancel_params.CancelCancelParams),
),
cast_to=object,
)
@@ -157,9 +153,7 @@ class AsyncCancelResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not batch_id:
raise ValueError(
f"Expected a non-empty value for `batch_id` but received {batch_id!r}"
)
raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}")
return await self._post(
f"/batches/{batch_id}/cancel",
options=make_request_options(
@@ -167,9 +161,7 @@ class AsyncCancelResource(AsyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=await async_maybe_transform(
{"provider": provider}, cancel_cancel_params.CancelCancelParams
),
query=await async_maybe_transform({"provider": provider}, cancel_cancel_params.CancelCancelParams),
),
cast_to=object,
)
+10 -30
View File
@@ -62,9 +62,7 @@ class BedrockResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._post(
f"/bedrock/{endpoint}",
options=make_request_options(
@@ -100,9 +98,7 @@ class BedrockResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._get(
f"/bedrock/{endpoint}",
options=make_request_options(
@@ -138,9 +134,7 @@ class BedrockResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._put(
f"/bedrock/{endpoint}",
options=make_request_options(
@@ -176,9 +170,7 @@ class BedrockResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._delete(
f"/bedrock/{endpoint}",
options=make_request_options(
@@ -214,9 +206,7 @@ class BedrockResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._patch(
f"/bedrock/{endpoint}",
options=make_request_options(
@@ -273,9 +263,7 @@ class AsyncBedrockResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._post(
f"/bedrock/{endpoint}",
options=make_request_options(
@@ -311,9 +299,7 @@ class AsyncBedrockResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._get(
f"/bedrock/{endpoint}",
options=make_request_options(
@@ -349,9 +335,7 @@ class AsyncBedrockResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._put(
f"/bedrock/{endpoint}",
options=make_request_options(
@@ -387,9 +371,7 @@ class AsyncBedrockResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._delete(
f"/bedrock/{endpoint}",
options=make_request_options(
@@ -425,9 +407,7 @@ class AsyncBedrockResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._patch(
f"/bedrock/{endpoint}",
options=make_request_options(
+7 -21
View File
@@ -58,9 +58,7 @@ class BudgetResource(SyncAPIResource):
budget_id: Optional[str] | NotGiven = NOT_GIVEN,
max_budget: Optional[float] | NotGiven = NOT_GIVEN,
max_parallel_requests: Optional[int] | NotGiven = NOT_GIVEN,
model_max_budget: (
Optional[Dict[str, budget_create_params.ModelMaxBudget]] | NotGiven
) = NOT_GIVEN,
model_max_budget: (Optional[Dict[str, budget_create_params.ModelMaxBudget]] | NotGiven) = NOT_GIVEN,
rpm_limit: Optional[int] | NotGiven = NOT_GIVEN,
soft_budget: Optional[float] | NotGiven = NOT_GIVEN,
tpm_limit: Optional[int] | NotGiven = NOT_GIVEN,
@@ -147,9 +145,7 @@ class BudgetResource(SyncAPIResource):
budget_id: Optional[str] | NotGiven = NOT_GIVEN,
max_budget: Optional[float] | NotGiven = NOT_GIVEN,
max_parallel_requests: Optional[int] | NotGiven = NOT_GIVEN,
model_max_budget: (
Optional[Dict[str, budget_update_params.ModelMaxBudget]] | NotGiven
) = NOT_GIVEN,
model_max_budget: (Optional[Dict[str, budget_update_params.ModelMaxBudget]] | NotGiven) = NOT_GIVEN,
rpm_limit: Optional[int] | NotGiven = NOT_GIVEN,
soft_budget: Optional[float] | NotGiven = NOT_GIVEN,
tpm_limit: Optional[int] | NotGiven = NOT_GIVEN,
@@ -318,9 +314,7 @@ class BudgetResource(SyncAPIResource):
"""
return self._post(
"/budget/info",
body=maybe_transform(
{"budgets": budgets}, budget_info_params.BudgetInfoParams
),
body=maybe_transform({"budgets": budgets}, budget_info_params.BudgetInfoParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -403,9 +397,7 @@ class AsyncBudgetResource(AsyncAPIResource):
budget_id: Optional[str] | NotGiven = NOT_GIVEN,
max_budget: Optional[float] | NotGiven = NOT_GIVEN,
max_parallel_requests: Optional[int] | NotGiven = NOT_GIVEN,
model_max_budget: (
Optional[Dict[str, budget_create_params.ModelMaxBudget]] | NotGiven
) = NOT_GIVEN,
model_max_budget: (Optional[Dict[str, budget_create_params.ModelMaxBudget]] | NotGiven) = NOT_GIVEN,
rpm_limit: Optional[int] | NotGiven = NOT_GIVEN,
soft_budget: Optional[float] | NotGiven = NOT_GIVEN,
tpm_limit: Optional[int] | NotGiven = NOT_GIVEN,
@@ -492,9 +484,7 @@ class AsyncBudgetResource(AsyncAPIResource):
budget_id: Optional[str] | NotGiven = NOT_GIVEN,
max_budget: Optional[float] | NotGiven = NOT_GIVEN,
max_parallel_requests: Optional[int] | NotGiven = NOT_GIVEN,
model_max_budget: (
Optional[Dict[str, budget_update_params.ModelMaxBudget]] | NotGiven
) = NOT_GIVEN,
model_max_budget: (Optional[Dict[str, budget_update_params.ModelMaxBudget]] | NotGiven) = NOT_GIVEN,
rpm_limit: Optional[int] | NotGiven = NOT_GIVEN,
soft_budget: Optional[float] | NotGiven = NOT_GIVEN,
tpm_limit: Optional[int] | NotGiven = NOT_GIVEN,
@@ -624,9 +614,7 @@ class AsyncBudgetResource(AsyncAPIResource):
"""
return await self._post(
"/budget/delete",
body=await async_maybe_transform(
{"id": id}, budget_delete_params.BudgetDeleteParams
),
body=await async_maybe_transform({"id": id}, budget_delete_params.BudgetDeleteParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -665,9 +653,7 @@ class AsyncBudgetResource(AsyncAPIResource):
"""
return await self._post(
"/budget/info",
body=await async_maybe_transform(
{"budgets": budgets}, budget_info_params.BudgetInfoParams
),
body=await async_maybe_transform({"budgets": budgets}, budget_info_params.BudgetInfoParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
+2 -6
View File
@@ -91,9 +91,7 @@ class CompletionsResource(SyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=maybe_transform(
{"model": model}, completion_create_params.CompletionCreateParams
),
query=maybe_transform({"model": model}, completion_create_params.CompletionCreateParams),
),
cast_to=object,
)
@@ -165,9 +163,7 @@ class AsyncCompletionsResource(AsyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=await async_maybe_transform(
{"model": model}, completion_create_params.CompletionCreateParams
),
query=await async_maybe_transform({"model": model}, completion_create_params.CompletionCreateParams),
),
cast_to=object,
)
+10 -30
View File
@@ -62,9 +62,7 @@ class CohereResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._post(
f"/cohere/{endpoint}",
options=make_request_options(
@@ -100,9 +98,7 @@ class CohereResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._get(
f"/cohere/{endpoint}",
options=make_request_options(
@@ -138,9 +134,7 @@ class CohereResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._put(
f"/cohere/{endpoint}",
options=make_request_options(
@@ -176,9 +170,7 @@ class CohereResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._delete(
f"/cohere/{endpoint}",
options=make_request_options(
@@ -214,9 +206,7 @@ class CohereResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._patch(
f"/cohere/{endpoint}",
options=make_request_options(
@@ -273,9 +263,7 @@ class AsyncCohereResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._post(
f"/cohere/{endpoint}",
options=make_request_options(
@@ -311,9 +299,7 @@ class AsyncCohereResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._get(
f"/cohere/{endpoint}",
options=make_request_options(
@@ -349,9 +335,7 @@ class AsyncCohereResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._put(
f"/cohere/{endpoint}",
options=make_request_options(
@@ -387,9 +371,7 @@ class AsyncCohereResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._delete(
f"/cohere/{endpoint}",
options=make_request_options(
@@ -425,9 +407,7 @@ class AsyncCohereResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._patch(
f"/cohere/{endpoint}",
options=make_request_options(
+2 -6
View File
@@ -88,9 +88,7 @@ class CompletionsResource(SyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=maybe_transform(
{"model": model}, completion_create_params.CompletionCreateParams
),
query=maybe_transform({"model": model}, completion_create_params.CompletionCreateParams),
),
cast_to=object,
)
@@ -159,9 +157,7 @@ class AsyncCompletionsResource(AsyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=await async_maybe_transform(
{"model": model}, completion_create_params.CompletionCreateParams
),
query=await async_maybe_transform({"model": model}, completion_create_params.CompletionCreateParams),
),
cast_to=object,
)
+4 -12
View File
@@ -72,9 +72,7 @@ class ConfigResourceWithRawResponse:
@cached_property
def pass_through_endpoint(self) -> PassThroughEndpointResourceWithRawResponse:
return PassThroughEndpointResourceWithRawResponse(
self._config.pass_through_endpoint
)
return PassThroughEndpointResourceWithRawResponse(self._config.pass_through_endpoint)
class AsyncConfigResourceWithRawResponse:
@@ -83,9 +81,7 @@ class AsyncConfigResourceWithRawResponse:
@cached_property
def pass_through_endpoint(self) -> AsyncPassThroughEndpointResourceWithRawResponse:
return AsyncPassThroughEndpointResourceWithRawResponse(
self._config.pass_through_endpoint
)
return AsyncPassThroughEndpointResourceWithRawResponse(self._config.pass_through_endpoint)
class ConfigResourceWithStreamingResponse:
@@ -94,9 +90,7 @@ class ConfigResourceWithStreamingResponse:
@cached_property
def pass_through_endpoint(self) -> PassThroughEndpointResourceWithStreamingResponse:
return PassThroughEndpointResourceWithStreamingResponse(
self._config.pass_through_endpoint
)
return PassThroughEndpointResourceWithStreamingResponse(self._config.pass_through_endpoint)
class AsyncConfigResourceWithStreamingResponse:
@@ -107,6 +101,4 @@ class AsyncConfigResourceWithStreamingResponse:
def pass_through_endpoint(
self,
) -> AsyncPassThroughEndpointResourceWithStreamingResponse:
return AsyncPassThroughEndpointResourceWithStreamingResponse(
self._config.pass_through_endpoint
)
return AsyncPassThroughEndpointResourceWithStreamingResponse(self._config.pass_through_endpoint)
@@ -127,9 +127,7 @@ class PassThroughEndpointResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint_id:
raise ValueError(
f"Expected a non-empty value for `endpoint_id` but received {endpoint_id!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint_id` but received {endpoint_id!r}")
return self._post(
f"/config/pass_through_endpoint/{endpoint_id}",
options=make_request_options(
@@ -319,9 +317,7 @@ class AsyncPassThroughEndpointResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint_id:
raise ValueError(
f"Expected a non-empty value for `endpoint_id` but received {endpoint_id!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint_id` but received {endpoint_id!r}")
return await self._post(
f"/config/pass_through_endpoint/{endpoint_id}",
options=make_request_options(
+2 -6
View File
@@ -140,9 +140,7 @@ class CredentialsResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not credential_name:
raise ValueError(
f"Expected a non-empty value for `credential_name` but received {credential_name!r}"
)
raise ValueError(f"Expected a non-empty value for `credential_name` but received {credential_name!r}")
return self._delete(
f"/credentials/{credential_name}",
options=make_request_options(
@@ -270,9 +268,7 @@ class AsyncCredentialsResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not credential_name:
raise ValueError(
f"Expected a non-empty value for `credential_name` but received {credential_name!r}"
)
raise ValueError(f"Expected a non-empty value for `credential_name` but received {credential_name!r}")
return await self._delete(
f"/credentials/{credential_name}",
options=make_request_options(
+8 -24
View File
@@ -67,9 +67,7 @@ class CustomerResource(SyncAPIResource):
default_model: Optional[str] | NotGiven = NOT_GIVEN,
max_budget: Optional[float] | NotGiven = NOT_GIVEN,
max_parallel_requests: Optional[int] | NotGiven = NOT_GIVEN,
model_max_budget: (
Optional[Dict[str, customer_create_params.ModelMaxBudget]] | NotGiven
) = NOT_GIVEN,
model_max_budget: (Optional[Dict[str, customer_create_params.ModelMaxBudget]] | NotGiven) = NOT_GIVEN,
rpm_limit: Optional[int] | NotGiven = NOT_GIVEN,
soft_budget: Optional[float] | NotGiven = NOT_GIVEN,
tpm_limit: Optional[int] | NotGiven = NOT_GIVEN,
@@ -330,9 +328,7 @@ class CustomerResource(SyncAPIResource):
"""
return self._post(
"/customer/delete",
body=maybe_transform(
{"user_ids": user_ids}, customer_delete_params.CustomerDeleteParams
),
body=maybe_transform({"user_ids": user_ids}, customer_delete_params.CustomerDeleteParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -382,9 +378,7 @@ class CustomerResource(SyncAPIResource):
"""
return self._post(
"/customer/block",
body=maybe_transform(
{"user_ids": user_ids}, customer_block_params.CustomerBlockParams
),
body=maybe_transform({"user_ids": user_ids}, customer_block_params.CustomerBlockParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -481,9 +475,7 @@ class CustomerResource(SyncAPIResource):
"""
return self._post(
"/customer/unblock",
body=maybe_transform(
{"user_ids": user_ids}, customer_unblock_params.CustomerUnblockParams
),
body=maybe_transform({"user_ids": user_ids}, customer_unblock_params.CustomerUnblockParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -526,9 +518,7 @@ class AsyncCustomerResource(AsyncAPIResource):
default_model: Optional[str] | NotGiven = NOT_GIVEN,
max_budget: Optional[float] | NotGiven = NOT_GIVEN,
max_parallel_requests: Optional[int] | NotGiven = NOT_GIVEN,
model_max_budget: (
Optional[Dict[str, customer_create_params.ModelMaxBudget]] | NotGiven
) = NOT_GIVEN,
model_max_budget: (Optional[Dict[str, customer_create_params.ModelMaxBudget]] | NotGiven) = NOT_GIVEN,
rpm_limit: Optional[int] | NotGiven = NOT_GIVEN,
soft_budget: Optional[float] | NotGiven = NOT_GIVEN,
tpm_limit: Optional[int] | NotGiven = NOT_GIVEN,
@@ -789,9 +779,7 @@ class AsyncCustomerResource(AsyncAPIResource):
"""
return await self._post(
"/customer/delete",
body=await async_maybe_transform(
{"user_ids": user_ids}, customer_delete_params.CustomerDeleteParams
),
body=await async_maybe_transform({"user_ids": user_ids}, customer_delete_params.CustomerDeleteParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -841,9 +829,7 @@ class AsyncCustomerResource(AsyncAPIResource):
"""
return await self._post(
"/customer/block",
body=await async_maybe_transform(
{"user_ids": user_ids}, customer_block_params.CustomerBlockParams
),
body=await async_maybe_transform({"user_ids": user_ids}, customer_block_params.CustomerBlockParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -940,9 +926,7 @@ class AsyncCustomerResource(AsyncAPIResource):
"""
return await self._post(
"/customer/unblock",
body=await async_maybe_transform(
{"user_ids": user_ids}, customer_unblock_params.CustomerUnblockParams
),
body=await async_maybe_transform({"user_ids": user_ids}, customer_unblock_params.CustomerUnblockParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
+2 -6
View File
@@ -68,9 +68,7 @@ class DeleteResource(SyncAPIResource):
"""
return self._post(
"/delete/allowed_ip",
body=maybe_transform(
{"ip": ip}, delete_create_allowed_ip_params.DeleteCreateAllowedIPParams
),
body=maybe_transform({"ip": ip}, delete_create_allowed_ip_params.DeleteCreateAllowedIPParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -126,9 +124,7 @@ class AsyncDeleteResource(AsyncAPIResource):
"""
return await self._post(
"/delete/allowed_ip",
body=await async_maybe_transform(
{"ip": ip}, delete_create_allowed_ip_params.DeleteCreateAllowedIPParams
),
body=await async_maybe_transform({"ip": ip}, delete_create_allowed_ip_params.DeleteCreateAllowedIPParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
+2 -6
View File
@@ -86,9 +86,7 @@ class EmbeddingsResource(SyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=maybe_transform(
{"model": model}, embedding_create_params.EmbeddingCreateParams
),
query=maybe_transform({"model": model}, embedding_create_params.EmbeddingCreateParams),
),
cast_to=object,
)
@@ -155,9 +153,7 @@ class AsyncEmbeddingsResource(AsyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=await async_maybe_transform(
{"model": model}, embedding_create_params.EmbeddingCreateParams
),
query=await async_maybe_transform({"model": model}, embedding_create_params.EmbeddingCreateParams),
),
cast_to=object,
)
+2 -6
View File
@@ -78,9 +78,7 @@ class ChatResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not model:
raise ValueError(
f"Expected a non-empty value for `model` but received {model!r}"
)
raise ValueError(f"Expected a non-empty value for `model` but received {model!r}")
return self._post(
f"/engines/{model}/chat/completions",
options=make_request_options(
@@ -153,9 +151,7 @@ class AsyncChatResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not model:
raise ValueError(
f"Expected a non-empty value for `model` but received {model!r}"
)
raise ValueError(f"Expected a non-empty value for `model` but received {model!r}")
return await self._post(
f"/engines/{model}/chat/completions",
options=make_request_options(
+4 -12
View File
@@ -87,9 +87,7 @@ class EnginesResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not model:
raise ValueError(
f"Expected a non-empty value for `model` but received {model!r}"
)
raise ValueError(f"Expected a non-empty value for `model` but received {model!r}")
return self._post(
f"/engines/{model}/completions",
options=make_request_options(
@@ -136,9 +134,7 @@ class EnginesResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not model:
raise ValueError(
f"Expected a non-empty value for `model` but received {model!r}"
)
raise ValueError(f"Expected a non-empty value for `model` but received {model!r}")
return self._post(
f"/engines/{model}/embeddings",
options=make_request_options(
@@ -212,9 +208,7 @@ class AsyncEnginesResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not model:
raise ValueError(
f"Expected a non-empty value for `model` but received {model!r}"
)
raise ValueError(f"Expected a non-empty value for `model` but received {model!r}")
return await self._post(
f"/engines/{model}/completions",
options=make_request_options(
@@ -261,9 +255,7 @@ class AsyncEnginesResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not model:
raise ValueError(
f"Expected a non-empty value for `model` but received {model!r}"
)
raise ValueError(f"Expected a non-empty value for `model` but received {model!r}")
return await self._post(
f"/engines/{model}/embeddings",
options=make_request_options(
+10 -30
View File
@@ -62,9 +62,7 @@ class EuAssemblyaiResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._post(
f"/eu.assemblyai/{endpoint}",
options=make_request_options(
@@ -100,9 +98,7 @@ class EuAssemblyaiResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._get(
f"/eu.assemblyai/{endpoint}",
options=make_request_options(
@@ -138,9 +134,7 @@ class EuAssemblyaiResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._put(
f"/eu.assemblyai/{endpoint}",
options=make_request_options(
@@ -176,9 +170,7 @@ class EuAssemblyaiResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._delete(
f"/eu.assemblyai/{endpoint}",
options=make_request_options(
@@ -214,9 +206,7 @@ class EuAssemblyaiResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._patch(
f"/eu.assemblyai/{endpoint}",
options=make_request_options(
@@ -273,9 +263,7 @@ class AsyncEuAssemblyaiResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._post(
f"/eu.assemblyai/{endpoint}",
options=make_request_options(
@@ -311,9 +299,7 @@ class AsyncEuAssemblyaiResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._get(
f"/eu.assemblyai/{endpoint}",
options=make_request_options(
@@ -349,9 +335,7 @@ class AsyncEuAssemblyaiResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._put(
f"/eu.assemblyai/{endpoint}",
options=make_request_options(
@@ -387,9 +371,7 @@ class AsyncEuAssemblyaiResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._delete(
f"/eu.assemblyai/{endpoint}",
options=make_request_options(
@@ -425,9 +407,7 @@ class AsyncEuAssemblyaiResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._patch(
f"/eu.assemblyai/{endpoint}",
options=make_request_options(
+4 -12
View File
@@ -76,13 +76,9 @@ class ContentResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
if not file_id:
raise ValueError(
f"Expected a non-empty value for `file_id` but received {file_id!r}"
)
raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
return self._get(
f"/{provider}/v1/files/{file_id}/content",
options=make_request_options(
@@ -153,13 +149,9 @@ class AsyncContentResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
if not file_id:
raise ValueError(
f"Expected a non-empty value for `file_id` but received {file_id!r}"
)
raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
return await self._get(
f"/{provider}/v1/files/{file_id}/content",
options=make_request_options(
+14 -42
View File
@@ -97,9 +97,7 @@ class FilesResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
body = deepcopy_minimal(
{
"file": file,
@@ -163,13 +161,9 @@ class FilesResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
if not file_id:
raise ValueError(
f"Expected a non-empty value for `file_id` but received {file_id!r}"
)
raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
return self._get(
f"/{provider}/v1/files/{file_id}",
options=make_request_options(
@@ -218,9 +212,7 @@ class FilesResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
return self._get(
f"/{provider}/v1/files",
options=make_request_options(
@@ -228,9 +220,7 @@ class FilesResource(SyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=maybe_transform(
{"purpose": purpose}, file_list_params.FileListParams
),
query=maybe_transform({"purpose": purpose}, file_list_params.FileListParams),
),
cast_to=object,
)
@@ -272,13 +262,9 @@ class FilesResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
if not file_id:
raise ValueError(
f"Expected a non-empty value for `file_id` but received {file_id!r}"
)
raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
return self._delete(
f"/{provider}/v1/files/{file_id}",
options=make_request_options(
@@ -353,9 +339,7 @@ class AsyncFilesResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
body = deepcopy_minimal(
{
"file": file,
@@ -419,13 +403,9 @@ class AsyncFilesResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
if not file_id:
raise ValueError(
f"Expected a non-empty value for `file_id` but received {file_id!r}"
)
raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
return await self._get(
f"/{provider}/v1/files/{file_id}",
options=make_request_options(
@@ -474,9 +454,7 @@ class AsyncFilesResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
return await self._get(
f"/{provider}/v1/files",
options=make_request_options(
@@ -484,9 +462,7 @@ class AsyncFilesResource(AsyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=await async_maybe_transform(
{"purpose": purpose}, file_list_params.FileListParams
),
query=await async_maybe_transform({"purpose": purpose}, file_list_params.FileListParams),
),
cast_to=object,
)
@@ -528,13 +504,9 @@ class AsyncFilesResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not provider:
raise ValueError(
f"Expected a non-empty value for `provider` but received {provider!r}"
)
raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}")
if not file_id:
raise ValueError(
f"Expected a non-empty value for `file_id` but received {file_id!r}"
)
raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
return await self._delete(
f"/{provider}/v1/files/{file_id}",
options=make_request_options(
@@ -70,9 +70,7 @@ class CancelResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not fine_tuning_job_id:
raise ValueError(
f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}"
)
raise ValueError(f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}")
return self._post(
f"/v1/fine_tuning/jobs/{fine_tuning_job_id}/cancel",
options=make_request_options(
@@ -137,9 +135,7 @@ class AsyncCancelResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not fine_tuning_job_id:
raise ValueError(
f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}"
)
raise ValueError(f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}")
return await self._post(
f"/v1/fine_tuning/jobs/{fine_tuning_job_id}/cancel",
options=make_request_options(
+4 -12
View File
@@ -68,9 +68,7 @@ class JobsResource(SyncAPIResource):
custom_llm_provider: Literal["openai", "azure", "vertex_ai"],
model: str,
training_file: str,
hyperparameters: (
Optional[job_create_params.Hyperparameters] | NotGiven
) = NOT_GIVEN,
hyperparameters: (Optional[job_create_params.Hyperparameters] | NotGiven) = NOT_GIVEN,
integrations: Optional[List[str]] | NotGiven = NOT_GIVEN,
seed: Optional[int] | NotGiven = NOT_GIVEN,
suffix: Optional[str] | NotGiven = NOT_GIVEN,
@@ -167,9 +165,7 @@ class JobsResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not fine_tuning_job_id:
raise ValueError(
f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}"
)
raise ValueError(f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}")
return self._get(
f"/v1/fine_tuning/jobs/{fine_tuning_job_id}",
options=make_request_options(
@@ -268,9 +264,7 @@ class AsyncJobsResource(AsyncAPIResource):
custom_llm_provider: Literal["openai", "azure", "vertex_ai"],
model: str,
training_file: str,
hyperparameters: (
Optional[job_create_params.Hyperparameters] | NotGiven
) = NOT_GIVEN,
hyperparameters: (Optional[job_create_params.Hyperparameters] | NotGiven) = NOT_GIVEN,
integrations: Optional[List[str]] | NotGiven = NOT_GIVEN,
seed: Optional[int] | NotGiven = NOT_GIVEN,
suffix: Optional[str] | NotGiven = NOT_GIVEN,
@@ -367,9 +361,7 @@ class AsyncJobsResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not fine_tuning_job_id:
raise ValueError(
f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}"
)
raise ValueError(f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}")
return await self._get(
f"/v1/fine_tuning/jobs/{fine_tuning_job_id}",
options=make_request_options(
+10 -30
View File
@@ -62,9 +62,7 @@ class GeminiResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._post(
f"/gemini/{endpoint}",
options=make_request_options(
@@ -100,9 +98,7 @@ class GeminiResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._get(
f"/gemini/{endpoint}",
options=make_request_options(
@@ -138,9 +134,7 @@ class GeminiResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._put(
f"/gemini/{endpoint}",
options=make_request_options(
@@ -176,9 +170,7 @@ class GeminiResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._delete(
f"/gemini/{endpoint}",
options=make_request_options(
@@ -214,9 +206,7 @@ class GeminiResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._patch(
f"/gemini/{endpoint}",
options=make_request_options(
@@ -273,9 +263,7 @@ class AsyncGeminiResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._post(
f"/gemini/{endpoint}",
options=make_request_options(
@@ -311,9 +299,7 @@ class AsyncGeminiResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._get(
f"/gemini/{endpoint}",
options=make_request_options(
@@ -349,9 +335,7 @@ class AsyncGeminiResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._put(
f"/gemini/{endpoint}",
options=make_request_options(
@@ -387,9 +371,7 @@ class AsyncGeminiResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._delete(
f"/gemini/{endpoint}",
options=make_request_options(
@@ -425,9 +407,7 @@ class AsyncGeminiResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._patch(
f"/gemini/{endpoint}",
options=make_request_options(
+2 -6
View File
@@ -148,9 +148,7 @@ class SpendResource(SyncAPIResource):
api_key: Optional[str] | NotGiven = NOT_GIVEN,
customer_id: Optional[str] | NotGiven = NOT_GIVEN,
end_date: Optional[str] | NotGiven = NOT_GIVEN,
group_by: (
Optional[Literal["team", "customer", "api_key"]] | NotGiven
) = NOT_GIVEN,
group_by: (Optional[Literal["team", "customer", "api_key"]] | NotGiven) = NOT_GIVEN,
internal_user_id: Optional[str] | NotGiven = NOT_GIVEN,
start_date: Optional[str] | NotGiven = NOT_GIVEN,
team_id: Optional[str] | NotGiven = NOT_GIVEN,
@@ -338,9 +336,7 @@ class AsyncSpendResource(AsyncAPIResource):
api_key: Optional[str] | NotGiven = NOT_GIVEN,
customer_id: Optional[str] | NotGiven = NOT_GIVEN,
end_date: Optional[str] | NotGiven = NOT_GIVEN,
group_by: (
Optional[Literal["team", "customer", "api_key"]] | NotGiven
) = NOT_GIVEN,
group_by: (Optional[Literal["team", "customer", "api_key"]] | NotGiven) = NOT_GIVEN,
internal_user_id: Optional[str] | NotGiven = NOT_GIVEN,
start_date: Optional[str] | NotGiven = NOT_GIVEN,
team_id: Optional[str] | NotGiven = NOT_GIVEN,
+2 -6
View File
@@ -92,9 +92,7 @@ class HealthResource(SyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=maybe_transform(
{"model": model}, health_check_all_params.HealthCheckAllParams
),
query=maybe_transform({"model": model}, health_check_all_params.HealthCheckAllParams),
),
cast_to=object,
)
@@ -290,9 +288,7 @@ class AsyncHealthResource(AsyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=await async_maybe_transform(
{"model": model}, health_check_all_params.HealthCheckAllParams
),
query=await async_maybe_transform({"model": model}, health_check_all_params.HealthCheckAllParams),
),
cast_to=object,
)
+6 -18
View File
@@ -775,9 +775,7 @@ class KeyResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not path_key:
raise ValueError(
f"Expected a non-empty value for `path_key` but received {path_key!r}"
)
raise ValueError(f"Expected a non-empty value for `path_key` but received {path_key!r}")
extra_headers = {
**strip_not_given({"hanzo-changed-by": hanzo_changed_by}),
**(extra_headers or {}),
@@ -875,9 +873,7 @@ class KeyResource(SyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=maybe_transform(
{"key": key}, key_retrieve_info_params.KeyRetrieveInfoParams
),
query=maybe_transform({"key": key}, key_retrieve_info_params.KeyRetrieveInfoParams),
),
cast_to=object,
)
@@ -1316,9 +1312,7 @@ class AsyncKeyResource(AsyncAPIResource):
}
return await self._post(
"/key/block",
body=await async_maybe_transform(
{"key": key}, key_block_params.KeyBlockParams
),
body=await async_maybe_transform({"key": key}, key_block_params.KeyBlockParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -1679,9 +1673,7 @@ class AsyncKeyResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not path_key:
raise ValueError(
f"Expected a non-empty value for `path_key` but received {path_key!r}"
)
raise ValueError(f"Expected a non-empty value for `path_key` but received {path_key!r}")
extra_headers = {
**strip_not_given({"hanzo-changed-by": hanzo_changed_by}),
**(extra_headers or {}),
@@ -1779,9 +1771,7 @@ class AsyncKeyResource(AsyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=await async_maybe_transform(
{"key": key}, key_retrieve_info_params.KeyRetrieveInfoParams
),
query=await async_maybe_transform({"key": key}, key_retrieve_info_params.KeyRetrieveInfoParams),
),
cast_to=object,
)
@@ -1835,9 +1825,7 @@ class AsyncKeyResource(AsyncAPIResource):
}
return await self._post(
"/key/unblock",
body=await async_maybe_transform(
{"key": key}, key_unblock_params.KeyUnblockParams
),
body=await async_maybe_transform({"key": key}, key_unblock_params.KeyUnblockParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
+10 -30
View File
@@ -65,9 +65,7 @@ class LangfuseResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._post(
f"/langfuse/{endpoint}",
options=make_request_options(
@@ -106,9 +104,7 @@ class LangfuseResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._get(
f"/langfuse/{endpoint}",
options=make_request_options(
@@ -147,9 +143,7 @@ class LangfuseResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._put(
f"/langfuse/{endpoint}",
options=make_request_options(
@@ -188,9 +182,7 @@ class LangfuseResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._delete(
f"/langfuse/{endpoint}",
options=make_request_options(
@@ -229,9 +221,7 @@ class LangfuseResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._patch(
f"/langfuse/{endpoint}",
options=make_request_options(
@@ -291,9 +281,7 @@ class AsyncLangfuseResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._post(
f"/langfuse/{endpoint}",
options=make_request_options(
@@ -332,9 +320,7 @@ class AsyncLangfuseResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._get(
f"/langfuse/{endpoint}",
options=make_request_options(
@@ -373,9 +359,7 @@ class AsyncLangfuseResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._put(
f"/langfuse/{endpoint}",
options=make_request_options(
@@ -414,9 +398,7 @@ class AsyncLangfuseResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._delete(
f"/langfuse/{endpoint}",
options=make_request_options(
@@ -455,9 +437,7 @@ class AsyncLangfuseResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._patch(
f"/langfuse/{endpoint}",
options=make_request_options(
+2 -6
View File
@@ -104,9 +104,7 @@ class InfoResource(SyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=maybe_transform(
{"hanzo_model_id": hanzo_model_id}, info_list_params.InfoListParams
),
query=maybe_transform({"hanzo_model_id": hanzo_model_id}, info_list_params.InfoListParams),
),
cast_to=object,
)
@@ -191,9 +189,7 @@ class AsyncInfoResource(AsyncAPIResource):
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=await async_maybe_transform(
{"hanzo_model_id": hanzo_model_id}, info_list_params.InfoListParams
),
query=await async_maybe_transform({"hanzo_model_id": hanzo_model_id}, info_list_params.InfoListParams),
),
cast_to=object,
)
+1 -3
View File
@@ -249,9 +249,7 @@ class AsyncModelResource(AsyncAPIResource):
"""
return await self._post(
"/model/delete",
body=await async_maybe_transform(
{"id": id}, model_delete_params.ModelDeleteParams
),
body=await async_maybe_transform({"id": id}, model_delete_params.ModelDeleteParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
+4 -12
View File
@@ -94,9 +94,7 @@ class UpdateResource(SyncAPIResource):
self,
model_id: str,
*,
hanzo_params: (
Optional[update_partial_params.LitellmParams] | NotGiven
) = NOT_GIVEN,
hanzo_params: (Optional[update_partial_params.LitellmParams] | NotGiven) = NOT_GIVEN,
model_info: Optional[ModelInfoParam] | NotGiven = NOT_GIVEN,
model_name: Optional[str] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -130,9 +128,7 @@ class UpdateResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not model_id:
raise ValueError(
f"Expected a non-empty value for `model_id` but received {model_id!r}"
)
raise ValueError(f"Expected a non-empty value for `model_id` but received {model_id!r}")
return self._patch(
f"/model/{model_id}/update",
body=maybe_transform(
@@ -221,9 +217,7 @@ class AsyncUpdateResource(AsyncAPIResource):
self,
model_id: str,
*,
hanzo_params: (
Optional[update_partial_params.LitellmParams] | NotGiven
) = NOT_GIVEN,
hanzo_params: (Optional[update_partial_params.LitellmParams] | NotGiven) = NOT_GIVEN,
model_info: Optional[ModelInfoParam] | NotGiven = NOT_GIVEN,
model_name: Optional[str] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -257,9 +251,7 @@ class AsyncUpdateResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not model_id:
raise ValueError(
f"Expected a non-empty value for `model_id` but received {model_id!r}"
)
raise ValueError(f"Expected a non-empty value for `model_id` but received {model_id!r}")
return await self._patch(
f"/model/{model_id}/update",
body=await async_maybe_transform(
@@ -78,9 +78,7 @@ class ChatResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not model:
raise ValueError(
f"Expected a non-empty value for `model` but received {model!r}"
)
raise ValueError(f"Expected a non-empty value for `model` but received {model!r}")
return self._post(
f"/openai/deployments/{model}/chat/completions",
options=make_request_options(
@@ -153,9 +151,7 @@ class AsyncChatResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not model:
raise ValueError(
f"Expected a non-empty value for `model` but received {model!r}"
)
raise ValueError(f"Expected a non-empty value for `model` but received {model!r}")
return await self._post(
f"/openai/deployments/{model}/chat/completions",
options=make_request_options(
@@ -87,9 +87,7 @@ class DeploymentsResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not model:
raise ValueError(
f"Expected a non-empty value for `model` but received {model!r}"
)
raise ValueError(f"Expected a non-empty value for `model` but received {model!r}")
return self._post(
f"/openai/deployments/{model}/completions",
options=make_request_options(
@@ -136,9 +134,7 @@ class DeploymentsResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not model:
raise ValueError(
f"Expected a non-empty value for `model` but received {model!r}"
)
raise ValueError(f"Expected a non-empty value for `model` but received {model!r}")
return self._post(
f"/openai/deployments/{model}/embeddings",
options=make_request_options(
@@ -212,9 +208,7 @@ class AsyncDeploymentsResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not model:
raise ValueError(
f"Expected a non-empty value for `model` but received {model!r}"
)
raise ValueError(f"Expected a non-empty value for `model` but received {model!r}")
return await self._post(
f"/openai/deployments/{model}/completions",
options=make_request_options(
@@ -261,9 +255,7 @@ class AsyncDeploymentsResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not model:
raise ValueError(
f"Expected a non-empty value for `model` but received {model!r}"
)
raise ValueError(f"Expected a non-empty value for `model` but received {model!r}")
return await self._post(
f"/openai/deployments/{model}/embeddings",
options=make_request_options(
+10 -30
View File
@@ -76,9 +76,7 @@ class OpenAIResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._post(
f"/openai/{endpoint}",
options=make_request_options(
@@ -116,9 +114,7 @@ class OpenAIResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._get(
f"/openai/{endpoint}",
options=make_request_options(
@@ -156,9 +152,7 @@ class OpenAIResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._put(
f"/openai/{endpoint}",
options=make_request_options(
@@ -196,9 +190,7 @@ class OpenAIResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._delete(
f"/openai/{endpoint}",
options=make_request_options(
@@ -236,9 +228,7 @@ class OpenAIResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._patch(
f"/openai/{endpoint}",
options=make_request_options(
@@ -301,9 +291,7 @@ class AsyncOpenAIResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._post(
f"/openai/{endpoint}",
options=make_request_options(
@@ -341,9 +329,7 @@ class AsyncOpenAIResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._get(
f"/openai/{endpoint}",
options=make_request_options(
@@ -381,9 +367,7 @@ class AsyncOpenAIResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._put(
f"/openai/{endpoint}",
options=make_request_options(
@@ -421,9 +405,7 @@ class AsyncOpenAIResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._delete(
f"/openai/{endpoint}",
options=make_request_options(
@@ -461,9 +443,7 @@ class AsyncOpenAIResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._patch(
f"/openai/{endpoint}",
options=make_request_options(
@@ -69,9 +69,7 @@ class InputItemsResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not response_id:
raise ValueError(
f"Expected a non-empty value for `response_id` but received {response_id!r}"
)
raise ValueError(f"Expected a non-empty value for `response_id` but received {response_id!r}")
return self._get(
f"/v1/responses/{response_id}/input_items",
options=make_request_options(
@@ -135,9 +133,7 @@ class AsyncInputItemsResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not response_id:
raise ValueError(
f"Expected a non-empty value for `response_id` but received {response_id!r}"
)
raise ValueError(f"Expected a non-empty value for `response_id` but received {response_id!r}")
return await self._get(
f"/v1/responses/{response_id}/input_items",
options=make_request_options(
+4 -12
View File
@@ -113,9 +113,7 @@ class ResponsesResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not response_id:
raise ValueError(
f"Expected a non-empty value for `response_id` but received {response_id!r}"
)
raise ValueError(f"Expected a non-empty value for `response_id` but received {response_id!r}")
return self._get(
f"/v1/responses/{response_id}",
options=make_request_options(
@@ -158,9 +156,7 @@ class ResponsesResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not response_id:
raise ValueError(
f"Expected a non-empty value for `response_id` but received {response_id!r}"
)
raise ValueError(f"Expected a non-empty value for `response_id` but received {response_id!r}")
return self._delete(
f"/v1/responses/{response_id}",
options=make_request_options(
@@ -260,9 +256,7 @@ class AsyncResponsesResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not response_id:
raise ValueError(
f"Expected a non-empty value for `response_id` but received {response_id!r}"
)
raise ValueError(f"Expected a non-empty value for `response_id` but received {response_id!r}")
return await self._get(
f"/v1/responses/{response_id}",
options=make_request_options(
@@ -305,9 +299,7 @@ class AsyncResponsesResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not response_id:
raise ValueError(
f"Expected a non-empty value for `response_id` but received {response_id!r}"
)
raise ValueError(f"Expected a non-empty value for `response_id` but received {response_id!r}")
return await self._delete(
f"/v1/responses/{response_id}",
options=make_request_options(
+6 -18
View File
@@ -89,9 +89,7 @@ class CallbackResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not team_id:
raise ValueError(
f"Expected a non-empty value for `team_id` but received {team_id!r}"
)
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return self._get(
f"/team/{team_id}/callback",
options=make_request_options(
@@ -109,9 +107,7 @@ class CallbackResource(SyncAPIResource):
*,
callback_name: str,
callback_vars: Dict[str, str],
callback_type: (
Optional[Literal["success", "failure", "success_and_failure"]] | NotGiven
) = NOT_GIVEN,
callback_type: (Optional[Literal["success", "failure", "success_and_failure"]] | NotGiven) = NOT_GIVEN,
hanzo_changed_by: str | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -176,9 +172,7 @@ class CallbackResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not team_id:
raise ValueError(
f"Expected a non-empty value for `team_id` but received {team_id!r}"
)
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
extra_headers = {
**strip_not_given({"hanzo-changed-by": hanzo_changed_by}),
**(extra_headers or {}),
@@ -265,9 +259,7 @@ class AsyncCallbackResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not team_id:
raise ValueError(
f"Expected a non-empty value for `team_id` but received {team_id!r}"
)
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return await self._get(
f"/team/{team_id}/callback",
options=make_request_options(
@@ -285,9 +277,7 @@ class AsyncCallbackResource(AsyncAPIResource):
*,
callback_name: str,
callback_vars: Dict[str, str],
callback_type: (
Optional[Literal["success", "failure", "success_and_failure"]] | NotGiven
) = NOT_GIVEN,
callback_type: (Optional[Literal["success", "failure", "success_and_failure"]] | NotGiven) = NOT_GIVEN,
hanzo_changed_by: str | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -352,9 +342,7 @@ class AsyncCallbackResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not team_id:
raise ValueError(
f"Expected a non-empty value for `team_id` but received {team_id!r}"
)
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
extra_headers = {
**strip_not_given({"hanzo-changed-by": hanzo_changed_by}),
**(extra_headers or {}),
+8 -24
View File
@@ -454,9 +454,7 @@ class TeamResource(SyncAPIResource):
}
return self._post(
"/team/delete",
body=maybe_transform(
{"team_ids": team_ids}, team_delete_params.TeamDeleteParams
),
body=maybe_transform({"team_ids": team_ids}, team_delete_params.TeamDeleteParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -563,9 +561,7 @@ class TeamResource(SyncAPIResource):
"""
return self._post(
"/team/block",
body=maybe_transform(
{"team_id": team_id}, team_block_params.TeamBlockParams
),
body=maybe_transform({"team_id": team_id}, team_block_params.TeamBlockParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -609,9 +605,7 @@ class TeamResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not team_id:
raise ValueError(
f"Expected a non-empty value for `team_id` but received {team_id!r}"
)
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return self._post(
f"/team/{team_id}/disable_logging",
options=make_request_options(
@@ -805,9 +799,7 @@ class TeamResource(SyncAPIResource):
"""
return self._post(
"/team/unblock",
body=maybe_transform(
{"team_id": team_id}, team_unblock_params.TeamUnblockParams
),
body=maybe_transform({"team_id": team_id}, team_unblock_params.TeamUnblockParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -1263,9 +1255,7 @@ class AsyncTeamResource(AsyncAPIResource):
}
return await self._post(
"/team/delete",
body=await async_maybe_transform(
{"team_ids": team_ids}, team_delete_params.TeamDeleteParams
),
body=await async_maybe_transform({"team_ids": team_ids}, team_delete_params.TeamDeleteParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -1372,9 +1362,7 @@ class AsyncTeamResource(AsyncAPIResource):
"""
return await self._post(
"/team/block",
body=await async_maybe_transform(
{"team_id": team_id}, team_block_params.TeamBlockParams
),
body=await async_maybe_transform({"team_id": team_id}, team_block_params.TeamBlockParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -1418,9 +1406,7 @@ class AsyncTeamResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not team_id:
raise ValueError(
f"Expected a non-empty value for `team_id` but received {team_id!r}"
)
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return await self._post(
f"/team/{team_id}/disable_logging",
options=make_request_options(
@@ -1614,9 +1600,7 @@ class AsyncTeamResource(AsyncAPIResource):
"""
return await self._post(
"/team/unblock",
body=await async_maybe_transform(
{"team_id": team_id}, team_unblock_params.TeamUnblockParams
),
body=await async_maybe_transform({"team_id": team_id}, team_unblock_params.TeamUnblockParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
+4 -12
View File
@@ -65,9 +65,7 @@ class MessagesResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not thread_id:
raise ValueError(
f"Expected a non-empty value for `thread_id` but received {thread_id!r}"
)
raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}")
return self._post(
f"/v1/threads/{thread_id}/messages",
options=make_request_options(
@@ -106,9 +104,7 @@ class MessagesResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not thread_id:
raise ValueError(
f"Expected a non-empty value for `thread_id` but received {thread_id!r}"
)
raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}")
return self._get(
f"/v1/threads/{thread_id}/messages",
options=make_request_options(
@@ -168,9 +164,7 @@ class AsyncMessagesResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not thread_id:
raise ValueError(
f"Expected a non-empty value for `thread_id` but received {thread_id!r}"
)
raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}")
return await self._post(
f"/v1/threads/{thread_id}/messages",
options=make_request_options(
@@ -209,9 +203,7 @@ class AsyncMessagesResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not thread_id:
raise ValueError(
f"Expected a non-empty value for `thread_id` but received {thread_id!r}"
)
raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}")
return await self._get(
f"/v1/threads/{thread_id}/messages",
options=make_request_options(
+2 -6
View File
@@ -64,9 +64,7 @@ class RunsResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not thread_id:
raise ValueError(
f"Expected a non-empty value for `thread_id` but received {thread_id!r}"
)
raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}")
return self._post(
f"/v1/threads/{thread_id}/runs",
options=make_request_options(
@@ -125,9 +123,7 @@ class AsyncRunsResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not thread_id:
raise ValueError(
f"Expected a non-empty value for `thread_id` but received {thread_id!r}"
)
raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}")
return await self._post(
f"/v1/threads/{thread_id}/runs",
options=make_request_options(
+2 -6
View File
@@ -115,9 +115,7 @@ class ThreadsResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not thread_id:
raise ValueError(
f"Expected a non-empty value for `thread_id` but received {thread_id!r}"
)
raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}")
return self._get(
f"/v1/threads/{thread_id}",
options=make_request_options(
@@ -211,9 +209,7 @@ class AsyncThreadsResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not thread_id:
raise ValueError(
f"Expected a non-empty value for `thread_id` but received {thread_id!r}"
)
raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}")
return await self._get(
f"/v1/threads/{thread_id}",
options=make_request_options(
+2 -6
View File
@@ -506,9 +506,7 @@ class UserResource(SyncAPIResource):
}
return self._post(
"/user/delete",
body=maybe_transform(
{"user_ids": user_ids}, user_delete_params.UserDeleteParams
),
body=maybe_transform({"user_ids": user_ids}, user_delete_params.UserDeleteParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -1039,9 +1037,7 @@ class AsyncUserResource(AsyncAPIResource):
}
return await self._post(
"/user/delete",
body=await async_maybe_transform(
{"user_ids": user_ids}, user_delete_params.UserDeleteParams
),
body=await async_maybe_transform({"user_ids": user_ids}, user_delete_params.UserDeleteParams),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
+10 -30
View File
@@ -64,9 +64,7 @@ class VertexAIResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._post(
f"/vertex_ai/{endpoint}",
options=make_request_options(
@@ -104,9 +102,7 @@ class VertexAIResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._get(
f"/vertex_ai/{endpoint}",
options=make_request_options(
@@ -144,9 +140,7 @@ class VertexAIResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._put(
f"/vertex_ai/{endpoint}",
options=make_request_options(
@@ -184,9 +178,7 @@ class VertexAIResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._delete(
f"/vertex_ai/{endpoint}",
options=make_request_options(
@@ -224,9 +216,7 @@ class VertexAIResource(SyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return self._patch(
f"/vertex_ai/{endpoint}",
options=make_request_options(
@@ -285,9 +275,7 @@ class AsyncVertexAIResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._post(
f"/vertex_ai/{endpoint}",
options=make_request_options(
@@ -325,9 +313,7 @@ class AsyncVertexAIResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._get(
f"/vertex_ai/{endpoint}",
options=make_request_options(
@@ -365,9 +351,7 @@ class AsyncVertexAIResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._put(
f"/vertex_ai/{endpoint}",
options=make_request_options(
@@ -405,9 +389,7 @@ class AsyncVertexAIResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._delete(
f"/vertex_ai/{endpoint}",
options=make_request_options(
@@ -445,9 +427,7 @@ class AsyncVertexAIResource(AsyncAPIResource):
timeout: Override the client-level default timeout for this request, in seconds
"""
if not endpoint:
raise ValueError(
f"Expected a non-empty value for `endpoint` but received {endpoint!r}"
)
raise ValueError(f"Expected a non-empty value for `endpoint` but received {endpoint!r}")
return await self._patch(
f"/vertex_ai/{endpoint}",
options=make_request_options(
+1 -3
View File
@@ -17,9 +17,7 @@ class LlmBudgetTable(BaseModel):
max_parallel_requests: Optional[int] = None
api_model_max_budget: Optional[object] = FieldInfo(
alias="model_max_budget", default=None
)
api_model_max_budget: Optional[object] = FieldInfo(alias="model_max_budget", default=None)
rpm_limit: Optional[int] = None
@@ -12,8 +12,6 @@ __all__ = ["CredentialUpdateParams"]
class CredentialUpdateParams(TypedDict, total=False):
credential_info: Required[object]
body_credential_name: Required[
Annotated[str, PropertyInfo(alias="credential_name")]
]
body_credential_name: Required[Annotated[str, PropertyInfo(alias="credential_name")]]
credential_values: Required[object]
@@ -17,9 +17,7 @@ class LlmBudgetTable(BaseModel):
max_parallel_requests: Optional[int] = None
api_model_max_budget: Optional[object] = FieldInfo(
alias="model_max_budget", default=None
)
api_model_max_budget: Optional[object] = FieldInfo(alias="model_max_budget", default=None)
rpm_limit: Optional[int] = None
+3 -9
View File
@@ -49,17 +49,11 @@ class GenerateKeyResponse(BaseModel):
metadata: Optional[object] = None
api_model_max_budget: Optional[object] = FieldInfo(
alias="model_max_budget", default=None
)
api_model_max_budget: Optional[object] = FieldInfo(alias="model_max_budget", default=None)
api_model_rpm_limit: Optional[object] = FieldInfo(
alias="model_rpm_limit", default=None
)
api_model_rpm_limit: Optional[object] = FieldInfo(alias="model_rpm_limit", default=None)
api_model_tpm_limit: Optional[object] = FieldInfo(
alias="model_tpm_limit", default=None
)
api_model_tpm_limit: Optional[object] = FieldInfo(alias="model_tpm_limit", default=None)
models: Optional[List[object]] = None
+1 -3
View File
@@ -43,9 +43,7 @@ class KeyBlockResponse(BaseModel):
metadata: Optional[object] = None
api_model_max_budget: Optional[object] = FieldInfo(
alias="model_max_budget", default=None
)
api_model_max_budget: Optional[object] = FieldInfo(alias="model_max_budget", default=None)
api_model_spend: Optional[object] = FieldInfo(alias="model_spend", default=None)
+1 -3
View File
@@ -60,9 +60,7 @@ class KeyUserAPIKeyAuth(BaseModel):
metadata: Optional[object] = None
api_model_max_budget: Optional[object] = FieldInfo(
alias="model_max_budget", default=None
)
api_model_max_budget: Optional[object] = FieldInfo(alias="model_max_budget", default=None)
api_model_spend: Optional[object] = FieldInfo(alias="model_spend", default=None)
+1 -3
View File
@@ -58,9 +58,7 @@ class KeyUpdateParams(TypedDict, total=False):
team_id: Optional[str]
temp_budget_expiry: Annotated[
Union[str, datetime, None], PropertyInfo(format="iso8601")
]
temp_budget_expiry: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
temp_budget_increase: Optional[float]
+1 -3
View File
@@ -14,6 +14,4 @@ class HanzoModelTable(BaseModel):
updated_by: str
api_model_aliases: Union[str, object, None] = FieldInfo(
alias="model_aliases", default=None
)
api_model_aliases: Union[str, object, None] = FieldInfo(alias="model_aliases", default=None)
+1 -3
View File
@@ -22,9 +22,7 @@ class HanzoUserTable(BaseModel):
metadata: Optional[object] = None
api_model_max_budget: Optional[object] = FieldInfo(
alias="model_max_budget", default=None
)
api_model_max_budget: Optional[object] = FieldInfo(alias="model_max_budget", default=None)
api_model_spend: Optional[object] = FieldInfo(alias="model_spend", default=None)
@@ -25,9 +25,7 @@ class UpdateFullParams(TypedDict, total=False):
model_name: Optional[str]
LitellmParamsConfigurableClientsideAuthParam: TypeAlias = Union[
str, ConfigurableClientsideParamsCustomAuthParam
]
LitellmParamsConfigurableClientsideAuthParam: TypeAlias = Union[str, ConfigurableClientsideParamsCustomAuthParam]
class LitellmParamsTyped(TypedDict, total=False):
@@ -45,9 +43,7 @@ class LitellmParamsTyped(TypedDict, total=False):
budget_duration: Optional[str]
configurable_clientside_auth_params: Optional[
List[LitellmParamsConfigurableClientsideAuthParam]
]
configurable_clientside_auth_params: Optional[List[LitellmParamsConfigurableClientsideAuthParam]]
custom_llm_provider: Optional[str]
@@ -25,9 +25,7 @@ class UpdatePartialParams(TypedDict, total=False):
model_name: Optional[str]
LitellmParamsConfigurableClientsideAuthParam: TypeAlias = Union[
str, ConfigurableClientsideParamsCustomAuthParam
]
LitellmParamsConfigurableClientsideAuthParam: TypeAlias = Union[str, ConfigurableClientsideParamsCustomAuthParam]
class LitellmParamsTyped(TypedDict, total=False):
@@ -45,9 +43,7 @@ class LitellmParamsTyped(TypedDict, total=False):
budget_duration: Optional[str]
configurable_clientside_auth_params: Optional[
List[LitellmParamsConfigurableClientsideAuthParam]
]
configurable_clientside_auth_params: Optional[List[LitellmParamsConfigurableClientsideAuthParam]]
custom_llm_provider: Optional[str]
+2 -6
View File
@@ -26,9 +26,7 @@ class ModelCreateParams(TypedDict, total=False):
model_name: Required[str]
LitellmParamsConfigurableClientsideAuthParam: TypeAlias = Union[
str, ConfigurableClientsideParamsCustomAuthParam
]
LitellmParamsConfigurableClientsideAuthParam: TypeAlias = Union[str, ConfigurableClientsideParamsCustomAuthParam]
class LitellmParamsTyped(TypedDict, total=False):
@@ -48,9 +46,7 @@ class LitellmParamsTyped(TypedDict, total=False):
budget_duration: Optional[str]
configurable_clientside_auth_params: Optional[
List[LitellmParamsConfigurableClientsideAuthParam]
]
configurable_clientside_auth_params: Optional[List[LitellmParamsConfigurableClientsideAuthParam]]
custom_llm_provider: Optional[str]
@@ -25,9 +25,7 @@ class LlmBudgetTable(BaseModel):
max_parallel_requests: Optional[int] = None
api_model_max_budget: Optional[object] = FieldInfo(
alias="model_max_budget", default=None
)
api_model_max_budget: Optional[object] = FieldInfo(alias="model_max_budget", default=None)
rpm_limit: Optional[int] = None
@@ -43,9 +41,7 @@ class MemberLlmBudgetTable(BaseModel):
max_parallel_requests: Optional[int] = None
api_model_max_budget: Optional[object] = FieldInfo(
alias="model_max_budget", default=None
)
api_model_max_budget: Optional[object] = FieldInfo(alias="model_max_budget", default=None)
rpm_limit: Optional[int] = None
@@ -80,9 +76,7 @@ class TeamLlmModelTable(BaseModel):
updated_by: str
api_model_aliases: Union[str, object, None] = FieldInfo(
alias="model_aliases", default=None
)
api_model_aliases: Union[str, object, None] = FieldInfo(alias="model_aliases", default=None)
class Team(BaseModel):
@@ -27,9 +27,7 @@ class OrganizationDeleteResponseItemLlmBudgetTable(BaseModel):
max_parallel_requests: Optional[int] = None
api_model_max_budget: Optional[object] = FieldInfo(
alias="model_max_budget", default=None
)
api_model_max_budget: Optional[object] = FieldInfo(alias="model_max_budget", default=None)
rpm_limit: Optional[int] = None
@@ -45,9 +43,7 @@ class OrganizationDeleteResponseItemMemberLlmBudgetTable(BaseModel):
max_parallel_requests: Optional[int] = None
api_model_max_budget: Optional[object] = FieldInfo(
alias="model_max_budget", default=None
)
api_model_max_budget: Optional[object] = FieldInfo(alias="model_max_budget", default=None)
rpm_limit: Optional[int] = None
@@ -67,9 +63,7 @@ class OrganizationDeleteResponseItemMember(BaseModel):
budget_id: Optional[str] = None
llm_budget_table: Optional[OrganizationDeleteResponseItemMemberLlmBudgetTable] = (
None
)
llm_budget_table: Optional[OrganizationDeleteResponseItemMemberLlmBudgetTable] = None
"""Represents user-controllable params for a LLM_BudgetTable record"""
spend: Optional[float] = None
@@ -84,9 +78,7 @@ class OrganizationDeleteResponseItemTeamLlmModelTable(BaseModel):
updated_by: str
api_model_aliases: Union[str, object, None] = FieldInfo(
alias="model_aliases", default=None
)
api_model_aliases: Union[str, object, None] = FieldInfo(alias="model_aliases", default=None)
class OrganizationDeleteResponseItemTeam(BaseModel):
@@ -27,9 +27,7 @@ class OrganizationListResponseItemLlmBudgetTable(BaseModel):
max_parallel_requests: Optional[int] = None
api_model_max_budget: Optional[object] = FieldInfo(
alias="model_max_budget", default=None
)
api_model_max_budget: Optional[object] = FieldInfo(alias="model_max_budget", default=None)
rpm_limit: Optional[int] = None
@@ -45,9 +43,7 @@ class OrganizationListResponseItemMemberLlmBudgetTable(BaseModel):
max_parallel_requests: Optional[int] = None
api_model_max_budget: Optional[object] = FieldInfo(
alias="model_max_budget", default=None
)
api_model_max_budget: Optional[object] = FieldInfo(alias="model_max_budget", default=None)
rpm_limit: Optional[int] = None
@@ -82,9 +78,7 @@ class OrganizationListResponseItemTeamLlmModelTable(BaseModel):
updated_by: str
api_model_aliases: Union[str, object, None] = FieldInfo(
alias="model_aliases", default=None
)
api_model_aliases: Union[str, object, None] = FieldInfo(alias="model_aliases", default=None)
class OrganizationListResponseItemTeam(BaseModel):
@@ -17,9 +17,7 @@ class LlmBudgetTable(BaseModel):
max_parallel_requests: Optional[int] = None
api_model_max_budget: Optional[object] = FieldInfo(
alias="model_max_budget", default=None
)
api_model_max_budget: Optional[object] = FieldInfo(alias="model_max_budget", default=None)
rpm_limit: Optional[int] = None
@@ -25,9 +25,7 @@ class LlmBudgetTable(BaseModel):
max_parallel_requests: Optional[int] = None
api_model_max_budget: Optional[object] = FieldInfo(
alias="model_max_budget", default=None
)
api_model_max_budget: Optional[object] = FieldInfo(alias="model_max_budget", default=None)
rpm_limit: Optional[int] = None
@@ -43,9 +41,7 @@ class MemberLlmBudgetTable(BaseModel):
max_parallel_requests: Optional[int] = None
api_model_max_budget: Optional[object] = FieldInfo(
alias="model_max_budget", default=None
)
api_model_max_budget: Optional[object] = FieldInfo(alias="model_max_budget", default=None)
rpm_limit: Optional[int] = None
@@ -80,9 +76,7 @@ class TeamLlmModelTable(BaseModel):
updated_by: str
api_model_aliases: Union[str, object, None] = FieldInfo(
alias="model_aliases", default=None
)
api_model_aliases: Union[str, object, None] = FieldInfo(alias="model_aliases", default=None)
class Team(BaseModel):
+1 -5
View File
@@ -61,8 +61,4 @@ class UserCreateParams(TypedDict, total=False):
user_id: Optional[str]
user_role: Optional[
Literal[
"proxy_admin", "proxy_admin_viewer", "internal_user", "internal_user_viewer"
]
]
user_role: Optional[Literal["proxy_admin", "proxy_admin_viewer", "internal_user", "internal_user_viewer"]]
+4 -14
View File
@@ -50,17 +50,11 @@ class UserCreateResponse(BaseModel):
metadata: Optional[object] = None
api_model_max_budget: Optional[object] = FieldInfo(
alias="model_max_budget", default=None
)
api_model_max_budget: Optional[object] = FieldInfo(alias="model_max_budget", default=None)
api_model_rpm_limit: Optional[object] = FieldInfo(
alias="model_rpm_limit", default=None
)
api_model_rpm_limit: Optional[object] = FieldInfo(alias="model_rpm_limit", default=None)
api_model_tpm_limit: Optional[object] = FieldInfo(
alias="model_tpm_limit", default=None
)
api_model_tpm_limit: Optional[object] = FieldInfo(alias="model_tpm_limit", default=None)
models: Optional[List[object]] = None
@@ -88,8 +82,4 @@ class UserCreateResponse(BaseModel):
user_id: Optional[str] = None
user_role: Optional[
Literal[
"proxy_admin", "proxy_admin_viewer", "internal_user", "internal_user_viewer"
]
] = None
user_role: Optional[Literal["proxy_admin", "proxy_admin_viewer", "internal_user", "internal_user_viewer"]] = None
+1 -5
View File
@@ -55,8 +55,4 @@ class UserUpdateParams(TypedDict, total=False):
user_id: Optional[str]
user_role: Optional[
Literal[
"proxy_admin", "proxy_admin_viewer", "internal_user", "internal_user_viewer"
]
]
user_role: Optional[Literal["proxy_admin", "proxy_admin_viewer", "internal_user", "internal_user_viewer"]]
+4 -10
View File
@@ -2,8 +2,8 @@
"""Test memory management system."""
import sys
import tempfile
import shutil
import tempfile
from pathlib import Path
import pytest
@@ -31,24 +31,18 @@ class TestMemoryManager:
def test_add_memory_fact(self, memory_manager):
"""Test adding a fact memory."""
memory_id = memory_manager.add_memory(
"User prefers Python over JavaScript", type="fact", priority=5
)
memory_id = memory_manager.add_memory("User prefers Python over JavaScript", type="fact", priority=5)
assert memory_id is not None
assert len(memory_id) > 0
def test_add_memory_instruction(self, memory_manager):
"""Test adding an instruction memory."""
memory_id = memory_manager.add_memory(
"Always use type hints in Python code", type="instruction", priority=8
)
memory_id = memory_manager.add_memory("Always use type hints in Python code", type="instruction", priority=8)
assert memory_id is not None
def test_add_memory_context(self, memory_manager):
"""Test adding a context memory."""
memory_id = memory_manager.add_memory(
"Working on REST API project", type="context", priority=3
)
memory_id = memory_manager.add_memory("Working on REST API project", type="context", priority=3)
assert memory_id is not None
def test_get_all_memories(self, memory_manager):
+2 -5
View File
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
"""Test signal handling for hanzo net command."""
import sys
import os
import sys
import time
import signal
import subprocess
@@ -21,10 +21,7 @@ class TestSignalHandling:
env["PYTHONPATH"] = pkg_path + ":" + env.get("PYTHONPATH", "")
return env
@pytest.mark.skipif(
sys.platform == "win32",
reason="Signal handling test not supported on Windows"
)
@pytest.mark.skipif(sys.platform == "win32", reason="Signal handling test not supported on Windows")
def test_sigint_graceful_shutdown(self, env_with_pythonpath):
"""Test that Ctrl-C (SIGINT) properly stops hanzo net."""
import fcntl