openai/openai-python
Publicmirrored from https://github.com/openai/openai-pythonAvailable
src/openai/__init__.py
372lines · modecode
| 1 | # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. |
| 2 | |
| 3 | from __future__ import annotations |
| 4 | |
| 5 | import os as _os |
| 6 | import typing as _t |
| 7 | from typing_extensions import override |
| 8 | |
| 9 | from . import types |
| 10 | from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes |
| 11 | from ._utils import file_from_path |
| 12 | from ._client import Client, OpenAI, Stream, Timeout, Transport, AsyncClient, AsyncOpenAI, AsyncStream, RequestOptions |
| 13 | from ._models import BaseModel |
| 14 | from ._version import __title__, __version__ |
| 15 | from ._response import APIResponse as APIResponse, AsyncAPIResponse as AsyncAPIResponse |
| 16 | from ._constants import DEFAULT_TIMEOUT, DEFAULT_MAX_RETRIES, DEFAULT_CONNECTION_LIMITS |
| 17 | from ._exceptions import ( |
| 18 | APIError, |
| 19 | OpenAIError, |
| 20 | ConflictError, |
| 21 | NotFoundError, |
| 22 | APIStatusError, |
| 23 | RateLimitError, |
| 24 | APITimeoutError, |
| 25 | BadRequestError, |
| 26 | APIConnectionError, |
| 27 | AuthenticationError, |
| 28 | InternalServerError, |
| 29 | PermissionDeniedError, |
| 30 | LengthFinishReasonError, |
| 31 | UnprocessableEntityError, |
| 32 | APIResponseValidationError, |
| 33 | ContentFilterFinishReasonError, |
| 34 | ) |
| 35 | from ._base_client import DefaultHttpxClient, DefaultAsyncHttpxClient |
| 36 | from ._utils._logs import setup_logging as _setup_logging |
| 37 | from ._legacy_response import HttpxBinaryResponseContent as HttpxBinaryResponseContent |
| 38 | |
| 39 | __all__ = [ |
| 40 | "types", |
| 41 | "__version__", |
| 42 | "__title__", |
| 43 | "NoneType", |
| 44 | "Transport", |
| 45 | "ProxiesTypes", |
| 46 | "NotGiven", |
| 47 | "NOT_GIVEN", |
| 48 | "Omit", |
| 49 | "OpenAIError", |
| 50 | "APIError", |
| 51 | "APIStatusError", |
| 52 | "APITimeoutError", |
| 53 | "APIConnectionError", |
| 54 | "APIResponseValidationError", |
| 55 | "BadRequestError", |
| 56 | "AuthenticationError", |
| 57 | "PermissionDeniedError", |
| 58 | "NotFoundError", |
| 59 | "ConflictError", |
| 60 | "UnprocessableEntityError", |
| 61 | "RateLimitError", |
| 62 | "InternalServerError", |
| 63 | "LengthFinishReasonError", |
| 64 | "ContentFilterFinishReasonError", |
| 65 | "Timeout", |
| 66 | "RequestOptions", |
| 67 | "Client", |
| 68 | "AsyncClient", |
| 69 | "Stream", |
| 70 | "AsyncStream", |
| 71 | "OpenAI", |
| 72 | "AsyncOpenAI", |
| 73 | "file_from_path", |
| 74 | "BaseModel", |
| 75 | "DEFAULT_TIMEOUT", |
| 76 | "DEFAULT_MAX_RETRIES", |
| 77 | "DEFAULT_CONNECTION_LIMITS", |
| 78 | "DefaultHttpxClient", |
| 79 | "DefaultAsyncHttpxClient", |
| 80 | ] |
| 81 | |
| 82 | if not _t.TYPE_CHECKING: |
| 83 | from ._utils._resources_proxy import resources as resources |
| 84 | |
| 85 | from .lib import azure as _azure, pydantic_function_tool as pydantic_function_tool |
| 86 | from .version import VERSION as VERSION |
| 87 | from .lib.azure import AzureOpenAI as AzureOpenAI, AsyncAzureOpenAI as AsyncAzureOpenAI |
| 88 | from .lib._old_api import * |
| 89 | from .lib.streaming import ( |
| 90 | AssistantEventHandler as AssistantEventHandler, |
| 91 | AsyncAssistantEventHandler as AsyncAssistantEventHandler, |
| 92 | ) |
| 93 | |
| 94 | _setup_logging() |
| 95 | |
| 96 | # Update the __module__ attribute for exported symbols so that |
| 97 | # error messages point to this module instead of the module |
| 98 | # it was originally defined in, e.g. |
| 99 | # openai._exceptions.NotFoundError -> openai.NotFoundError |
| 100 | __locals = locals() |
| 101 | for __name in __all__: |
| 102 | if not __name.startswith("__"): |
| 103 | try: |
| 104 | __locals[__name].__module__ = "openai" |
| 105 | except (TypeError, AttributeError): |
| 106 | # Some of our exported symbols are builtins which we can't set attributes for. |
| 107 | pass |
| 108 | |
| 109 | # ------ Module level client ------ |
| 110 | import typing as _t |
| 111 | import typing_extensions as _te |
| 112 | |
| 113 | import httpx as _httpx |
| 114 | |
| 115 | from ._base_client import DEFAULT_TIMEOUT, DEFAULT_MAX_RETRIES |
| 116 | |
| 117 | api_key: str | None = None |
| 118 | |
| 119 | organization: str | None = None |
| 120 | |
| 121 | project: str | None = None |
| 122 | |
| 123 | base_url: str | _httpx.URL | None = None |
| 124 | |
| 125 | timeout: float | Timeout | None = DEFAULT_TIMEOUT |
| 126 | |
| 127 | max_retries: int = DEFAULT_MAX_RETRIES |
| 128 | |
| 129 | default_headers: _t.Mapping[str, str] | None = None |
| 130 | |
| 131 | default_query: _t.Mapping[str, object] | None = None |
| 132 | |
| 133 | http_client: _httpx.Client | None = None |
| 134 | |
| 135 | _ApiType = _te.Literal["openai", "azure"] |
| 136 | |
| 137 | api_type: _ApiType | None = _t.cast(_ApiType, _os.environ.get("OPENAI_API_TYPE")) |
| 138 | |
| 139 | api_version: str | None = _os.environ.get("OPENAI_API_VERSION") |
| 140 | |
| 141 | azure_endpoint: str | None = _os.environ.get("AZURE_OPENAI_ENDPOINT") |
| 142 | |
| 143 | azure_ad_token: str | None = _os.environ.get("AZURE_OPENAI_AD_TOKEN") |
| 144 | |
| 145 | azure_ad_token_provider: _azure.AzureADTokenProvider | None = None |
| 146 | |
| 147 | |
| 148 | class _ModuleClient(OpenAI): |
| 149 | # Note: we have to use type: ignores here as overriding class members |
| 150 | # with properties is technically unsafe but it is fine for our use case |
| 151 | |
| 152 | @property # type: ignore |
| 153 | @override |
| 154 | def api_key(self) -> str | None: |
| 155 | return api_key |
| 156 | |
| 157 | @api_key.setter # type: ignore |
| 158 | def api_key(self, value: str | None) -> None: # type: ignore |
| 159 | global api_key |
| 160 | |
| 161 | api_key = value |
| 162 | |
| 163 | @property # type: ignore |
| 164 | @override |
| 165 | def organization(self) -> str | None: |
| 166 | return organization |
| 167 | |
| 168 | @organization.setter # type: ignore |
| 169 | def organization(self, value: str | None) -> None: # type: ignore |
| 170 | global organization |
| 171 | |
| 172 | organization = value |
| 173 | |
| 174 | @property # type: ignore |
| 175 | @override |
| 176 | def project(self) -> str | None: |
| 177 | return project |
| 178 | |
| 179 | @project.setter # type: ignore |
| 180 | def project(self, value: str | None) -> None: # type: ignore |
| 181 | global project |
| 182 | |
| 183 | project = value |
| 184 | |
| 185 | @property |
| 186 | @override |
| 187 | def base_url(self) -> _httpx.URL: |
| 188 | if base_url is not None: |
| 189 | return _httpx.URL(base_url) |
| 190 | |
| 191 | return super().base_url |
| 192 | |
| 193 | @base_url.setter |
| 194 | def base_url(self, url: _httpx.URL | str) -> None: |
| 195 | super().base_url = url # type: ignore[misc] |
| 196 | |
| 197 | @property # type: ignore |
| 198 | @override |
| 199 | def timeout(self) -> float | Timeout | None: |
| 200 | return timeout |
| 201 | |
| 202 | @timeout.setter # type: ignore |
| 203 | def timeout(self, value: float | Timeout | None) -> None: # type: ignore |
| 204 | global timeout |
| 205 | |
| 206 | timeout = value |
| 207 | |
| 208 | @property # type: ignore |
| 209 | @override |
| 210 | def max_retries(self) -> int: |
| 211 | return max_retries |
| 212 | |
| 213 | @max_retries.setter # type: ignore |
| 214 | def max_retries(self, value: int) -> None: # type: ignore |
| 215 | global max_retries |
| 216 | |
| 217 | max_retries = value |
| 218 | |
| 219 | @property # type: ignore |
| 220 | @override |
| 221 | def _custom_headers(self) -> _t.Mapping[str, str] | None: |
| 222 | return default_headers |
| 223 | |
| 224 | @_custom_headers.setter # type: ignore |
| 225 | def _custom_headers(self, value: _t.Mapping[str, str] | None) -> None: # type: ignore |
| 226 | global default_headers |
| 227 | |
| 228 | default_headers = value |
| 229 | |
| 230 | @property # type: ignore |
| 231 | @override |
| 232 | def _custom_query(self) -> _t.Mapping[str, object] | None: |
| 233 | return default_query |
| 234 | |
| 235 | @_custom_query.setter # type: ignore |
| 236 | def _custom_query(self, value: _t.Mapping[str, object] | None) -> None: # type: ignore |
| 237 | global default_query |
| 238 | |
| 239 | default_query = value |
| 240 | |
| 241 | @property # type: ignore |
| 242 | @override |
| 243 | def _client(self) -> _httpx.Client: |
| 244 | return http_client or super()._client |
| 245 | |
| 246 | @_client.setter # type: ignore |
| 247 | def _client(self, value: _httpx.Client) -> None: # type: ignore |
| 248 | global http_client |
| 249 | |
| 250 | http_client = value |
| 251 | |
| 252 | |
| 253 | class _AzureModuleClient(_ModuleClient, AzureOpenAI): # type: ignore |
| 254 | ... |
| 255 | |
| 256 | |
| 257 | class _AmbiguousModuleClientUsageError(OpenAIError): |
| 258 | def __init__(self) -> None: |
| 259 | super().__init__( |
| 260 | "Ambiguous use of module client; please set `openai.api_type` or the `OPENAI_API_TYPE` environment variable to `openai` or `azure`" |
| 261 | ) |
| 262 | |
| 263 | |
| 264 | def _has_openai_credentials() -> bool: |
| 265 | return _os.environ.get("OPENAI_API_KEY") is not None |
| 266 | |
| 267 | |
| 268 | def _has_azure_credentials() -> bool: |
| 269 | return azure_endpoint is not None or _os.environ.get("AZURE_OPENAI_API_KEY") is not None |
| 270 | |
| 271 | |
| 272 | def _has_azure_ad_credentials() -> bool: |
| 273 | return ( |
| 274 | _os.environ.get("AZURE_OPENAI_AD_TOKEN") is not None |
| 275 | or azure_ad_token is not None |
| 276 | or azure_ad_token_provider is not None |
| 277 | ) |
| 278 | |
| 279 | |
| 280 | _client: OpenAI | None = None |
| 281 | |
| 282 | |
| 283 | def _load_client() -> OpenAI: # type: ignore[reportUnusedFunction] |
| 284 | global _client |
| 285 | |
| 286 | if _client is None: |
| 287 | global api_type, azure_endpoint, azure_ad_token, api_version |
| 288 | |
| 289 | if azure_endpoint is None: |
| 290 | azure_endpoint = _os.environ.get("AZURE_OPENAI_ENDPOINT") |
| 291 | |
| 292 | if azure_ad_token is None: |
| 293 | azure_ad_token = _os.environ.get("AZURE_OPENAI_AD_TOKEN") |
| 294 | |
| 295 | if api_version is None: |
| 296 | api_version = _os.environ.get("OPENAI_API_VERSION") |
| 297 | |
| 298 | if api_type is None: |
| 299 | has_openai = _has_openai_credentials() |
| 300 | has_azure = _has_azure_credentials() |
| 301 | has_azure_ad = _has_azure_ad_credentials() |
| 302 | |
| 303 | if has_openai and (has_azure or has_azure_ad): |
| 304 | raise _AmbiguousModuleClientUsageError() |
| 305 | |
| 306 | if (azure_ad_token is not None or azure_ad_token_provider is not None) and _os.environ.get( |
| 307 | "AZURE_OPENAI_API_KEY" |
| 308 | ) is not None: |
| 309 | raise _AmbiguousModuleClientUsageError() |
| 310 | |
| 311 | if has_azure or has_azure_ad: |
| 312 | api_type = "azure" |
| 313 | else: |
| 314 | api_type = "openai" |
| 315 | |
| 316 | if api_type == "azure": |
| 317 | _client = _AzureModuleClient( # type: ignore |
| 318 | api_version=api_version, |
| 319 | azure_endpoint=azure_endpoint, |
| 320 | api_key=api_key, |
| 321 | azure_ad_token=azure_ad_token, |
| 322 | azure_ad_token_provider=azure_ad_token_provider, |
| 323 | organization=organization, |
| 324 | base_url=base_url, |
| 325 | timeout=timeout, |
| 326 | max_retries=max_retries, |
| 327 | default_headers=default_headers, |
| 328 | default_query=default_query, |
| 329 | http_client=http_client, |
| 330 | ) |
| 331 | return _client |
| 332 | |
| 333 | _client = _ModuleClient( |
| 334 | api_key=api_key, |
| 335 | organization=organization, |
| 336 | project=project, |
| 337 | base_url=base_url, |
| 338 | timeout=timeout, |
| 339 | max_retries=max_retries, |
| 340 | default_headers=default_headers, |
| 341 | default_query=default_query, |
| 342 | http_client=http_client, |
| 343 | ) |
| 344 | return _client |
| 345 | |
| 346 | return _client |
| 347 | |
| 348 | |
| 349 | def _reset_client() -> None: # type: ignore[reportUnusedFunction] |
| 350 | global _client |
| 351 | |
| 352 | _client = None |
| 353 | |
| 354 | |
| 355 | from ._module_client import ( |
| 356 | beta as beta, |
| 357 | chat as chat, |
| 358 | audio as audio, |
| 359 | evals as evals, |
| 360 | files as files, |
| 361 | images as images, |
| 362 | models as models, |
| 363 | batches as batches, |
| 364 | uploads as uploads, |
| 365 | responses as responses, |
| 366 | containers as containers, |
| 367 | embeddings as embeddings, |
| 368 | completions as completions, |
| 369 | fine_tuning as fine_tuning, |
| 370 | moderations as moderations, |
| 371 | vector_stores as vector_stores, |
| 372 | ) |