diff --git a/.github/workflows/create-releases.yml b/.github/workflows/create-releases.yml deleted file mode 100644 index c8c94db105..0000000000 --- a/.github/workflows/create-releases.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Create releases -on: - schedule: - - cron: '0 5 * * *' # every day at 5am UTC - push: - branches: - - main - -jobs: - release: - name: release - if: github.ref == 'refs/heads/main' && github.repository == 'openai/openai-python' - runs-on: ubuntu-latest - environment: publish - - steps: - - uses: actions/checkout@v3 - - - uses: stainless-api/trigger-release-please@v1 - id: release - with: - repo: ${{ github.event.repository.full_name }} - stainless-api-key: ${{ secrets.STAINLESS_API_KEY }} - - - name: Install Rye - if: ${{ steps.release.outputs.releases_created }} - run: | - curl -sSf https://rye-up.com/get | bash - echo "$HOME/.rye/shims" >> $GITHUB_PATH - env: - RYE_VERSION: 0.15.2 - RYE_INSTALL_OPTION: "--yes" - - - name: Publish to PyPI - if: ${{ steps.release.outputs.releases_created }} - run: | - bash ./bin/publish-pypi - env: - PYPI_TOKEN: ${{ secrets.OPENAI_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 026ed29c22..e690e0d985 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -1,9 +1,13 @@ -# workflow for re-running publishing to PyPI in case it fails for some reason -# you can run this workflow by navigating to https://www.github.com/openai/openai-python/actions/workflows/publish-pypi.yml +# This workflow is triggered when a GitHub release is created. +# It can also be run manually to re-publish to PyPI in case it failed for some reason. +# You can run this workflow by navigating to https://www.github.com/openai/openai-python/actions/workflows/publish-pypi.yml name: Publish PyPI on: workflow_dispatch: + release: + types: [published] + jobs: publish: name: publish diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 108aa5973a..20af127ffc 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -19,5 +19,4 @@ jobs: run: | bash ./bin/check-release-environment env: - STAINLESS_API_KEY: ${{ secrets.STAINLESS_API_KEY }} PYPI_TOKEN: ${{ secrets.OPENAI_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.gitignore b/.gitignore index 29b329e98a..39427019f2 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ codegen.log # Ignore the MkDocs build artifact directory site/ + +# Random ignores +.DS_Store \ No newline at end of file diff --git a/.release-please-manifest.json b/.release-please-manifest.json index de0960aba8..f94eeca267 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.12.0" + ".": "1.13.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ef0b80e87..00c364af0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## 1.13.0 (2024-02-19) + +Full Changelog: [v1.12.0...v1.13.0](https://github.com/openai/openai-python/compare/v1.12.0...v1.13.0) + +### Features + +* **api:** updates ([#1146](https://github.com/openai/openai-python/issues/1146)) ([79b7675](https://github.com/openai/openai-python/commit/79b7675e51fb7d269a6ea281a568bc7812ba2ace)) + + +### Bug Fixes + +* **api:** remove non-GA instance_id param ([#1164](https://github.com/openai/openai-python/issues/1164)) ([1abe139](https://github.com/openai/openai-python/commit/1abe139b1a5f5cc41263738fc12856056dce5697)) + + +### Chores + +* **ci:** move github release logic to github app ([#1155](https://github.com/openai/openai-python/issues/1155)) ([67cfac2](https://github.com/openai/openai-python/commit/67cfac2564dfb718da0465e34b90ac6928fa962a)) +* **client:** use correct accept headers for binary data ([#1161](https://github.com/openai/openai-python/issues/1161)) ([e536437](https://github.com/openai/openai-python/commit/e536437ae0b2cb0ddf2d74618722005d37403f32)) +* **internal:** refactor release environment script ([#1158](https://github.com/openai/openai-python/issues/1158)) ([7fe8ec3](https://github.com/openai/openai-python/commit/7fe8ec3bf04ecf85e3bd5adf0d9992c051f87b81)) + ## 1.12.0 (2024-02-08) Full Changelog: [v1.11.1...v1.12.0](https://github.com/openai/openai-python/compare/v1.11.1...v1.12.0) diff --git a/bin/check-release-environment b/bin/check-release-environment index b0c8d34f0c..5471b69edb 100644 --- a/bin/check-release-environment +++ b/bin/check-release-environment @@ -2,17 +2,13 @@ errors=() -if [ -z "${STAINLESS_API_KEY}" ]; then - errors+=("The STAINLESS_API_KEY secret has not been set. Please contact Stainless for an API key & set it in your organization secrets on GitHub.") -fi - if [ -z "${PYPI_TOKEN}" ]; then errors+=("The OPENAI_PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.") fi -len=${#errors[@]} +lenErrors=${#errors[@]} -if [[ len -gt 0 ]]; then +if [[ lenErrors -gt 0 ]]; then echo -e "Found the following errors in the release environment:\n" for error in "${errors[@]}"; do diff --git a/docs/index.md b/docs/index.md index 9a97cc32c2..e03e772879 100644 --- a/docs/index.md +++ b/docs/index.md @@ -10,7 +10,7 @@ Welcome to Marsh's totally unofficial and totally unsupported documentation for ## About these docs -These docs are officially unofficial and unsupported, but you're welcome to use and improve them until OpenAI brings up their own (1) or they ask me to take them down. +These docs are officially unofficial, but you're welcome to use and improve them until OpenAI brings up their own (1) or they ask me to take them down. { .annotate } 1. I'll likely decommission this site when OpenAI [publishes their own Python API reference](https://community.openai.com/t/where-is-the-documentation-for-the-python-openai-sdk/583643). @@ -30,4 +30,4 @@ That said, I use these docs myself and thus intend to keep them (mostly) current 1. That means you might encounter inaccuracies or you might not find what you think should be here. In either case, you should refer to [openai/openai-python](https://github.com/openai/openai-python) as the source of truth. -:material-hand-wave: *Enjoy!* —[Marsh](https://github.com/mmacy) \ No newline at end of file +:material-peace: *Enjoy!* —[Marsh](https://github.com/mmacy) \ No newline at end of file diff --git a/docs/reference/include/openai.resources.py b/docs/reference/include/openai.resources.py new file mode 100644 index 0000000000..96d5bbc853 --- /dev/null +++ b/docs/reference/include/openai.resources.py @@ -0,0 +1,86 @@ +"""Snippets in this docstring are ingested by other documentation (including library docstrings) during the MkDocs build process. + +# --8<-- [start:audio] +The `audio` module provides classes for handling various audio processing operations, including transcription of audio to text, translation of spoken content, and speech synthesis. + +This module supports synchronous and asynchronous operations, and offers interfaces for direct interaction with audio data, as well as handling of raw and streaming responses. Designed for applications that require audio input processing like automated transcription services, real-time translation of spoken language, and generating spoken content from text. +# --8<-- [end:audio] + +# --8<-- [start:beta] +The `beta` modules provides a unified interface for accessing beta features of the API, encapsulating synchronous and asynchronous access to resources in beta. + +The module aggregates the beta functionalities related to features like yet considered generally available (GA), offering a simplified entry point for interacting with these resources. It is designed to facilitate easy access to the cutting-edge features still under development, enabling developers to experiment with and leverage new capabilities before they become GA. +# --8<-- [end:beta] + +# --8<-- [start:chat] +The `chat` module provides classes for creating and managing chat sessions that leverage OpenAI's language models to generate conversational responses. + +The module supports both synchronous and asynchronous operations, offering interfaces for direct interaction with the completion endpoints tailored for chat applications. Designed for developers looking to integrate AI-powered chat functionalities into their applicationsand features like raw and streaming response handling for more flexible integration. +# --8<-- [end:chat] + +# --8<-- [start:chat_completions] +The `chat.completions` module provides access to the chat completions endpoint of the OpenAI API. It supports +the latest models including `gpt-4`, `gpt-4-turbo-preview`, `gpt-4-vision-preview`, `gpt-4-32k`, `gpt-3.5-turbo`, +and their respective dated model releases, along with fine-tuned versions of `gpt-3.5-turbo`. + +This module interacts with the `/v1/chat/completions` endpoint and replaces the the legacy [`resources.completions`][src.openai.resources.completions] module. You're *strongly encouraged* to migrate existing applications that use the legacy `resources.completions` module to this one before the expected [deprecation](https://platform.openai.com/docs/deprecations) of the `/v1/completions` endpoint. +# --8<-- [end:chat_completions] + +# --8<-- [start:completions] +The `completions` module provides access to the legacy completions endpoint of the OpenAI API. Use the [`chat.completions`][src.openai.resources.chat.completions] module instead for new applications. + +This module interacts with a [legacy](https://platform.openai.com/docs/deprecations) endpoint, `/v1/completions`, indicating that the endpoint no longer receives updates and is expected to be deprecated. This module is for use only in applications that require compatibility with the legacy endpoint and should **not** be used for new projects. + +You're *strongly encouraged* to migrate existing applications to the [`chat.completions`][src.openai.resources.chat.completions] module⁠—which interacts with the current (non-legacy) `/v1/chat/completions` endpoint—prior to the [deprecation](https://platform.openai.com/docs/deprecations) of the `/v1/completions` endpoint. +# --8<-- [end:completions] + +# --8<-- [start:embeddings] +The `embeddings` module provides classes for creating embeddings from text inputs using OpenAI's models and supports both synchronous and asynchronous operations as well as the handling of raw responses and streaming response capabilities. + +The module is appropriate for use in applications that require semantic analysis of text, like similarity searches, text clustering, and other natural language processing tasks that can benefit from high-dimensional vector representations of text. +# --8<-- [end:embeddings] + +# --8<-- [start:files] +The `files` module provides classes for uploading, retrieving, listing, and deleting files used across various OpenAI API endpoints. + +The module supports both synchronous and asynchronous operations, along with handling of raw responses and streaming of file content. Designed for use cases that involve managing large datasets or files for purposes like fine-tuning models or using assistants, this module facilitates the efficient handling of file-related operations on the OpenAI platform. +# --8<-- [end:files] + +# --8<-- [start:fine_tuning] +The `fine_tuning` module provides classes for handling fine-tuning operations, including the initiation, management, and retrieval of fine-tuning jobs. + +The module supports synchronous and asynchronous operations, offering interfaces for working with jobs directly, as well as with raw or streaming responses. Designed for use in applications requiring custom model training on specific datasets to improve model performance for tailored tasks. +# --8<-- [end:fine_tuning] + +# --8<-- [start:fine_tuning_jobs] +The `jobs` module provides synchronous and asynchronous access to fine-tuning job resources and enables you to create, retrieve, list, and cancel fine-tuning jobs and list the events associated with them. + +Fine-tuning jobs allow you to customize pre-trained models with your own datasets, optimizing performance for specific tasks or improving understanding of particular data types. The classes in the `jobs` module includes methods for managing fine-tuning jobs, like creating a new job, fetching details of an existing job, listing all jobs, canceling a job, and listing events associated with a job. +# --8<-- [end:fine_tuning_jobs] + +# --8<-- [start:images] +The `image` module provides functionality for creating variations of images, editing images based on textual prompts, and generating new images from prompts using specified models. + +The module supports both synchronous and asynchronous operations, with capabilities for handling raw responses and streaming. Suitable for applications requiring dynamic image generation or modification through the OpenAI API, this module leverages models like DALL-E to interpret text prompts into visual content. +# --8<-- [end:images] + +# --8<-- [start:models] +The `models` module facilitates the retrieval, listing, and deletion of models on the OpenAI platform and supports both synchronous and asynchronous operations. + +The module enables developers to interact with models, providing functionalities like fetching detailed information about a specific model, listing all available models, and deleting fine-tuned models. +# --8<-- [end:models] + +# --8<-- [start:moderations] +The `moderations` module provides functionality to submit text for moderation to determine whether it violates OpenAI's content policy. + +Moderation is particularly useful for developers looking to ensure the content generated or processed by their applications adheres to OpenAI's content policy. By leveraging the content moderation models provided by OpenAI, applications can automatically classify and filter out text that might be considered harmful or inappropriate. +# --8<-- [end:moderations] + +# --8<-- [start:assistants] +The `assistants` module offers functionalities to create, retrieve, update, list, and delete Assistants. Assistants are AI models configured to perform specific tasks based on instructions, files, and other parameters. +# --8<-- [end:assistants] + +# --8<-- [start:threads] +The `threads` module facilitates the creation, retrieval, update, deletion, and execution of Threads. Threads represent a series of messages or interactions with an assistant and support a conversational context or a sequence of operations. +# --8<-- [end:threads] +""" \ No newline at end of file diff --git a/docs/reference/include/openai_init.py b/docs/reference/include/openai_init.py new file mode 100644 index 0000000000..01bfc8fa3e --- /dev/null +++ b/docs/reference/include/openai_init.py @@ -0,0 +1,28 @@ +"""Snippets in this docstring are ingested by other documentation (including library docstrings) during the MkDocs build process. + +# --8<-- [start:openai] +The [openai](https://pypi.org/project/openai/) package is the core library to install in Python projects that need +to call the [OpenAI REST API](https://platform.openai.com/docs/api-reference). It inclues modules for working with OpenAI +resources that provide access to its AI [models](https://platform.openai.com/docs/models), +including large language models (LLMs) like GPT-4 and models for working with images and audio. The `openai` package +provides both synchronous and asynchronous API clients, options to configure their behavior, and modules that provide +Python code with an API surface to interact with the OpenAI platform. + +To get started, check out the documentation for the module representing the [resource][src.openai.resources] you're interested in using for your +project. For example, the [`resources.chat.completions`][src.openai.resources.chat.completions] module is what you'd use +for conversational chat-style interactions with an LLM like [GPT-4 Turbo](https://platform.openai.com/docs/models/gpt-4-and-gpt-4-turbo). +Or, maybe you need the [`resources.audio`][src.openai.resources.audio] module for performing audio transcription, translation, and +speech synthesis in your app. + +Documentation for the library's main API client classes, [`OpenAI`][src.openai.OpenAI] and +[`AsyncOpenAI`][src.openai.AsyncOpenAI], is another good place to start. The clients are the primary contact point for +your code that needs to work with any of the resources available on OpenAI API endpoints. + +For more information about the REST API this package talks to or to find client libraries for other programming +languages, see: + +- [REST API reference documentation](https://platform.openai.com/docs/api-reference) for the OpenAPI REST API (platform.openai.com) +- [OpenAPI Description (OAD)](https://github.com/openai/openai-openapi) file for the OpenAPI REST API (GitHub) +- More [client libraries](https://platform.openai.com/docs/libraries) for the OpenAI API (platform.openai.com) +# --8<-- [end:openai] +""" diff --git a/docs/reference/index.md b/docs/reference/index.md index 2b37911c53..864f61d018 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -1,3 +1,5 @@ # openai -::: src.openai \ No newline at end of file +::: src.openai + options: + docstring_section_style: spacy \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index b771abff6e..b8cb55945d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -9,7 +9,7 @@ watch: [README.md, src/openai] theme: name: material icon: - repo: fontawesome/brands/github + repo: fontawesome/brands/git-alt palette: - media: "(prefers-color-scheme: light)" @@ -68,6 +68,8 @@ markdown_extensions: - pymdownx.inlinehilite - pymdownx.snippets - pymdownx.superfences + - pymdownx.tasklist: + custom_checkbox: true plugins: - search @@ -98,7 +100,7 @@ plugins: inherited_members: false merge_init_into_class: true separate_signature: true - show_bases: true + show_bases: false show_if_no_docstring: true show_root_full_path: false show_root_heading: false diff --git a/pyproject.toml b/pyproject.toml index 163297ee2b..d7c017f99d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openai" -version = "1.12.0" +version = "1.13.0" description = "The official Python library for the openai API" readme = "README.md" license = "Apache-2.0" diff --git a/src/openai/__init__.py b/src/openai/__init__.py index 118fe8ee93..1c44acbf75 100644 --- a/src/openai/__init__.py +++ b/src/openai/__init__.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai_init.py:openai' """ from __future__ import annotations import os as _os diff --git a/src/openai/_base_client.py b/src/openai/_base_client.py index 73bd2411fd..1a1a6cac07 100644 --- a/src/openai/_base_client.py +++ b/src/openai/_base_client.py @@ -147,8 +147,7 @@ def __init__( class BasePage(GenericModel, Generic[_T]): - """ - Defines the core interface for pagination. + """Defines the core interface for pagination. Type Args: ModelT: The pydantic model that represents an item in the response. @@ -419,8 +418,7 @@ def _build_headers(self, options: FinalRequestOptions) -> httpx.Headers: return headers def _prepare_url(self, url: str) -> URL: - """ - Merge a URL argument together with any 'base_url' on the client, + """Merge a URL argument together with any 'base_url' on the client, to create the URL used for the outgoing request. """ # Copied from httpx's `_merge_url` method. diff --git a/src/openai/_client.py b/src/openai/_client.py index 5043d60e2a..304d5f8013 100644 --- a/src/openai/_client.py +++ b/src/openai/_client.py @@ -47,6 +47,58 @@ class OpenAI(SyncAPIClient): + """Primary synchronous client interface for interacting with the services (resources) provided by the OpenAI API. + + An instance of the `OpenAI` class is the top-level object you interact with to make synchronous calls to the + OpenAI API. The client provides access to OpenAI's services, or *resources*, like text completion, chat, + embeddings, image and audio processing, and managing the files used by these resources. + + The API authenticates requests to its endpoints by validating your API key, which you provide to the `OpenAI` + client object in one of two ways: + + :material-checkbox-marked-circle-outline: **Set an environment variable** named `OPENAI_API_KEY` that contains + your API key and then instantiate the client *without* passing the `api_key` parameter. This is the preferred + method. + + :material-alert: **Pass the `api_key` parameter explicitly** when you instantiate the client object. Choose this + method *only* if you're unwilling or unable to use a more secure method like setting the `OPENAI_API_KEY` + environment variable. + + Danger: + To prevent unauthorized access to OpenAI services, securely manage credentials like your OpenAI API key. + + Examples: + The following code snippets each create an instance of the `OpenAI` class ready to call the API. To interact + with an OpenAI service (a [`resource`][src.openai.resources] in the API), you access the appropriate + attribute on the initialized client object and call the the methods provided by that resource. + + - Create client using **inferred API key** ⁠— The API key is obtained by the `OpenAI` client automatically from + the `OPENAI_API_KEY` environment variable if you *omit* the `api_key` constructor argument. + + ```python + from openai import OpenAI + + # Instantiate the client with NO 'api_key' param so the client will + # read the OPENAI_API_KEY variable from the environment automatically + client = OpenAI() + ``` + + - Create client using **explicit API key** ⁠— Passing the API key explicitly directs the `OpenAI` client to use + that key instead of the `OPENAI_API_KEY` environment variable (if set). + + :material-alert: This instantiation method can pose an increased **security risk**. For example, by + instantiating the client this way in your code, it's easier to accidentally commit your API key to version + control, which you should *never* do. + + ```python + from openai import OpenAI + + # !!! USE WITH CAUTION !!! + + # Instantiate the client and pass the API key explicitly + client = OpenAI(api_key='your_api_key_here') + ``` + """ completions: resources.Completions chat: resources.Chat embeddings: resources.Embeddings @@ -86,11 +138,41 @@ def __init__( # part of our public interface in the future. _strict_response_validation: bool = False, ) -> None: - """Construct a new synchronous openai client instance. - - This automatically infers the following arguments from their corresponding environment variables if they are not provided: - - `api_key` from `OPENAI_API_KEY` - - `organization` from `OPENAI_ORG_ID` + """Initializes a new instance of the OpenAI client for making synchronous API requests. + + Args: + api_key (str | None, optional): The API key used for authenticating requests to OpenAI. If not provided, the + client attempts to retrieve the API key from the `OPENAI_API_KEY` environment variable. Defaults to None. + organization (str | None, optional): The ID of the organization under which the API calls are made. This is + optional and typically used for OpenAI services that require organization-level access control. If not + provided, the client attempts to retrieve the organization ID from the `OPENAI_ORG_ID` environment + variable. Defaults to None. + base_url (str | httpx.URL | None, optional): The base URL for the OpenAI API. This allows for custom API + endpoints like those used for testing or specific API versions. If not provided, defaults to the + official OpenAI API URL. + timeout (Union[float, Timeout, None, NotGiven], optional): The timeout for API requests. This can be + specified as a float representing seconds, a `httpx.Timeout` object for fine-grained control, or `None` + to use the default timeout. Defaults to `NOT_GIVEN`, which utilizes the `httpx` default timeout settings. + max_retries (int, optional): The maximum number of retries for failed requests. This can help handle + transient network issues or rate limit errors gracefully. Defaults to a predefined constant + `DEFAULT_MAX_RETRIES`. + default_headers (Mapping[str, str] | None, optional): Default headers to include with every request. This + can be used to set global headers like `User-Agent` or custom headers required for integration. + Defaults to None. + default_query (Mapping[str, object] | None, optional): Default query parameters to include with every + request. This is useful for setting global parameters that should be included in all API calls. Defaults + to None. + http_client (httpx.Client | None, optional): An instance of `httpx.Client` to be used for making HTTP + requests. This allows for custom configuration of the HTTP client, like setting proxies or client-side + SSL certificates. If not provided, a default `httpx.Client` instance is used. Defaults to None. + _strict_response_validation (bool, optional): Enables or disables strict validation of API responses against + the expected schema. This is primarily used for development and debugging purposes to ensure the API + responses match the expected format. Note that this argument may be removed or changed in future releases. + Defaults to False. + + Raises: + OpenAIError: If neither the `api_key` is provided nor the `OPENAI_API_KEY` environment variable is set, + indicating that the client's requests to the OpenAI API would fail authentication. """ if api_key is None: api_key = os.environ.get("OPENAI_API_KEY") @@ -171,8 +253,7 @@ def copy( set_default_query: Mapping[str, object] | None = None, _extra_kwargs: Mapping[str, Any] = {}, ) -> Self: - """ - Create a new client instance re-using the same options given to the current client with optional overriding. + """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") @@ -369,8 +450,7 @@ def copy( set_default_query: Mapping[str, object] | None = None, _extra_kwargs: Mapping[str, Any] = {}, ) -> Self: - """ - Create a new client instance re-using the same options given to the current client with optional overriding. + """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") diff --git a/src/openai/_version.py b/src/openai/_version.py index 6db2292c7b..0b4a88eb78 100644 --- a/src/openai/_version.py +++ b/src/openai/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. __title__ = "openai" -__version__ = "1.12.0" # x-release-please-version +__version__ = "1.13.0" # x-release-please-version diff --git a/src/openai/lib/azure.py.BUSTED b/src/openai/lib/azure.py.BUSTED deleted file mode 100644 index 2c8b4dcd88..0000000000 --- a/src/openai/lib/azure.py.BUSTED +++ /dev/null @@ -1,529 +0,0 @@ -from __future__ import annotations - -import os -import inspect -from typing import Any, Union, Mapping, TypeVar, Callable, Awaitable, overload -from typing_extensions import Self, override - -import httpx - -from .._types import NOT_GIVEN, Omit, Timeout, NotGiven -from .._utils import is_given, is_mapping -from .._client import OpenAI, AsyncOpenAI -from .._models import FinalRequestOptions -from .._streaming import Stream, AsyncStream -from .._exceptions import OpenAIError -from .._base_client import DEFAULT_MAX_RETRIES, BaseClient - -_deployments_endpoints = set( - [ - "/completions", - "/chat/completions", - "/embeddings", - "/audio/transcriptions", - "/audio/translations", - "/audio/speech", - "/images/generations", - ] -) - - -AzureADTokenProvider = Callable[[], str] -AsyncAzureADTokenProvider = Callable[[], "str | Awaitable[str]"] -_HttpxClientT = TypeVar("_HttpxClientT", bound=Union[httpx.Client, httpx.AsyncClient]) -_DefaultStreamT = TypeVar("_DefaultStreamT", bound=Union[Stream[Any], AsyncStream[Any]]) - - -# we need to use a sentinel API key value for Azure AD -# as we don't want to make the `api_key` in the main client Optional -# and Azure AD tokens may be retrieved on a per-request basis -API_KEY_SENTINEL = "".join(["<", "missing API key", ">"]) - - -class MutuallyExclusiveAuthError(OpenAIError): - def __init__(self) -> None: - super().__init__( - "The `api_key`, `azure_ad_token` and `azure_ad_token_provider` arguments are mutually exclusive; Only one can be passed at a time" - ) - - -class BaseAzureClient(BaseClient[_HttpxClientT, _DefaultStreamT]): - @override - def _build_request( - self, - options: FinalRequestOptions, - ) -> httpx.Request: - if options.url in _deployments_endpoints and is_mapping(options.json_data): - model = options.json_data.get("model") - if model is not None and not "/deployments" in str(self.base_url): - options.url = f"/deployments/{model}{options.url}" - - return super()._build_request(options) - - -class AzureOpenAI(BaseAzureClient[httpx.Client, Stream[Any]], OpenAI): - @overload - def __init__( - self, - *, - azure_endpoint: str, - azure_deployment: str | None = None, - api_version: str | None = None, - api_key: str | None = None, - azure_ad_token: str | None = None, - azure_ad_token_provider: AzureADTokenProvider | None = None, - organization: str | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, - max_retries: int = DEFAULT_MAX_RETRIES, - default_headers: Mapping[str, str] | None = None, - default_query: Mapping[str, object] | None = None, - http_client: httpx.Client | None = None, - _strict_response_validation: bool = False, - ) -> None: - ... - - @overload - def __init__( - self, - *, - azure_deployment: str | None = None, - api_version: str | None = None, - api_key: str | None = None, - azure_ad_token: str | None = None, - azure_ad_token_provider: AzureADTokenProvider | None = None, - organization: str | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, - max_retries: int = DEFAULT_MAX_RETRIES, - default_headers: Mapping[str, str] | None = None, - default_query: Mapping[str, object] | None = None, - http_client: httpx.Client | None = None, - _strict_response_validation: bool = False, - ) -> None: - ... - - @overload - def __init__( - self, - *, - base_url: str, - api_version: str | None = None, - api_key: str | None = None, - azure_ad_token: str | None = None, - azure_ad_token_provider: AzureADTokenProvider | None = None, - organization: str | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, - max_retries: int = DEFAULT_MAX_RETRIES, - default_headers: Mapping[str, str] | None = None, - default_query: Mapping[str, object] | None = None, - http_client: httpx.Client | None = None, - _strict_response_validation: bool = False, - ) -> None: - ... - - def __init__( - self, - *, - api_version: str | None = None, - azure_endpoint: str | None = None, - azure_deployment: str | None = None, - api_key: str | None = None, - azure_ad_token: str | None = None, - azure_ad_token_provider: AzureADTokenProvider | None = None, - organization: str | None = None, - base_url: str | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, - max_retries: int = DEFAULT_MAX_RETRIES, - default_headers: Mapping[str, str] | None = None, - default_query: Mapping[str, object] | None = None, - http_client: httpx.Client | None = None, - _strict_response_validation: bool = False, - ) -> None: - """Construct a new synchronous azure openai client instance. - - This automatically infers the following arguments from their corresponding environment variables if they are not provided: - - `api_key` from `AZURE_OPENAI_API_KEY` - - `organization` from `OPENAI_ORG_ID` - - `azure_ad_token` from `AZURE_OPENAI_AD_TOKEN` - - `api_version` from `OPENAI_API_VERSION` - - `azure_endpoint` from `AZURE_OPENAI_ENDPOINT` - - Args: - azure_endpoint: Your Azure endpoint, including the resource, e.g. `https://example-resource.azure.openai.com/` - - azure_ad_token: Your Azure Active Directory token, https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id - - azure_ad_token_provider: A function that returns an Azure Active Directory token, will be invoked on every request. - - azure_deployment: A model deployment, if given sets the base client URL to include `/deployments/{azure_deployment}`. - Note: this means you won't be able to use non-deployment endpoints. - """ - if api_key is None: - api_key = os.environ.get("AZURE_OPENAI_API_KEY") - - if azure_ad_token is None: - azure_ad_token = os.environ.get("AZURE_OPENAI_AD_TOKEN") - - if api_key is None and azure_ad_token is None and azure_ad_token_provider is None: - raise OpenAIError( - "Missing credentials. Please pass one of `api_key`, `azure_ad_token`, `azure_ad_token_provider`, or the `AZURE_OPENAI_API_KEY` or `AZURE_OPENAI_AD_TOKEN` environment variables." - ) - - if api_version is None: - api_version = os.environ.get("OPENAI_API_VERSION") - - if api_version is None: - raise ValueError( - "Must provide either the `api_version` argument or the `OPENAI_API_VERSION` environment variable" - ) - - if default_query is None: - default_query = {"api-version": api_version} - else: - default_query = {**default_query, "api-version": api_version} - - if base_url is None: - if azure_endpoint is None: - azure_endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT") - - if azure_endpoint is None: - raise ValueError( - "Must provide one of the `base_url` or `azure_endpoint` arguments, or the `AZURE_OPENAI_ENDPOINT` environment variable" - ) - - if azure_deployment is not None: - base_url = f"{azure_endpoint}/openai/deployments/{azure_deployment}" - else: - base_url = f"{azure_endpoint}/openai" - else: - if azure_endpoint is not None: - raise ValueError("base_url and azure_endpoint are mutually exclusive") - - if api_key is None: - # define a sentinel value to avoid any typing issues - api_key = API_KEY_SENTINEL - - super().__init__( - api_key=api_key, - organization=organization, - base_url=base_url, - timeout=timeout, - max_retries=max_retries, - default_headers=default_headers, - default_query=default_query, - http_client=http_client, - _strict_response_validation=_strict_response_validation, - ) - self._api_version = api_version - self._azure_ad_token = azure_ad_token - self._azure_ad_token_provider = azure_ad_token_provider - - @override - def copy( - self, - *, - api_key: str | None = None, - organization: str | None = None, - api_version: str | None = None, - azure_ad_token: str | None = None, - azure_ad_token_provider: AzureADTokenProvider | None = None, - base_url: str | httpx.URL | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, - http_client: httpx.Client | None = None, - max_retries: int | NotGiven = NOT_GIVEN, - default_headers: Mapping[str, str] | None = None, - set_default_headers: Mapping[str, str] | None = None, - default_query: Mapping[str, object] | None = None, - set_default_query: Mapping[str, object] | None = None, - _extra_kwargs: Mapping[str, Any] = {}, - ) -> Self: - """ - Create a new client instance re-using the same options given to the current client with optional overriding. - """ - return super().copy( - api_key=api_key, - organization=organization, - base_url=base_url, - timeout=timeout, - http_client=http_client, - max_retries=max_retries, - default_headers=default_headers, - set_default_headers=set_default_headers, - default_query=default_query, - set_default_query=set_default_query, - _extra_kwargs={ - "api_version": api_version or self._api_version, - "azure_ad_token": azure_ad_token or self._azure_ad_token, - "azure_ad_token_provider": azure_ad_token_provider or self._azure_ad_token_provider, - **_extra_kwargs, - }, - ) - - with_options = copy - - def _get_azure_ad_token(self) -> str | None: - if self._azure_ad_token is not None: - return self._azure_ad_token - - provider = self._azure_ad_token_provider - if provider is not None: - token = provider() - if not token or not isinstance(token, str): # pyright: ignore[reportUnnecessaryIsInstance] - raise ValueError( - f"Expected `azure_ad_token_provider` argument to return a string but it returned {token}", - ) - return token - - return None - - @override - def _prepare_options(self, options: FinalRequestOptions) -> None: - headers: dict[str, str | Omit] = {**options.headers} if is_given(options.headers) else {} - options.headers = headers - - azure_ad_token = self._get_azure_ad_token() - if azure_ad_token is not None: - if headers.get("Authorization") is None: - headers["Authorization"] = f"Bearer {azure_ad_token}" - elif self.api_key is not API_KEY_SENTINEL: - if headers.get("api-key") is None: - headers["api-key"] = self.api_key - else: - # should never be hit - raise ValueError("Unable to handle auth") - - return super()._prepare_options(options) - - -class AsyncAzureOpenAI(BaseAzureClient[httpx.AsyncClient, AsyncStream[Any]], AsyncOpenAI): - @overload - def __init__( - self, - *, - azure_endpoint: str, - azure_deployment: str | None = None, - api_version: str | None = None, - api_key: str | None = None, - azure_ad_token: str | None = None, - azure_ad_token_provider: AsyncAzureADTokenProvider | None = None, - organization: str | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, - max_retries: int = DEFAULT_MAX_RETRIES, - default_headers: Mapping[str, str] | None = None, - default_query: Mapping[str, object] | None = None, - http_client: httpx.AsyncClient | None = None, - _strict_response_validation: bool = False, - ) -> None: - ... - - @overload - def __init__( - self, - *, - azure_deployment: str | None = None, - api_version: str | None = None, - api_key: str | None = None, - azure_ad_token: str | None = None, - azure_ad_token_provider: AsyncAzureADTokenProvider | None = None, - organization: str | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, - max_retries: int = DEFAULT_MAX_RETRIES, - default_headers: Mapping[str, str] | None = None, - default_query: Mapping[str, object] | None = None, - http_client: httpx.AsyncClient | None = None, - _strict_response_validation: bool = False, - ) -> None: - ... - - @overload - def __init__( - self, - *, - base_url: str, - api_version: str | None = None, - api_key: str | None = None, - azure_ad_token: str | None = None, - azure_ad_token_provider: AsyncAzureADTokenProvider | None = None, - organization: str | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, - max_retries: int = DEFAULT_MAX_RETRIES, - default_headers: Mapping[str, str] | None = None, - default_query: Mapping[str, object] | None = None, - http_client: httpx.AsyncClient | None = None, - _strict_response_validation: bool = False, - ) -> None: - ... - - def __init__( - self, - *, - azure_endpoint: str | None = None, - azure_deployment: str | None = None, - api_version: str | None = None, - api_key: str | None = None, - azure_ad_token: str | None = None, - azure_ad_token_provider: AsyncAzureADTokenProvider | None = None, - organization: str | None = None, - base_url: str | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, - max_retries: int = DEFAULT_MAX_RETRIES, - default_headers: Mapping[str, str] | None = None, - default_query: Mapping[str, object] | None = None, - http_client: httpx.AsyncClient | None = None, - _strict_response_validation: bool = False, - ) -> None: - """Construct a new asynchronous azure openai client instance. - - This automatically infers the following arguments from their corresponding environment variables if they are not provided: - - `api_key` from `AZURE_OPENAI_API_KEY` - - `organization` from `OPENAI_ORG_ID` - - `azure_ad_token` from `AZURE_OPENAI_AD_TOKEN` - - `api_version` from `OPENAI_API_VERSION` - - `azure_endpoint` from `AZURE_OPENAI_ENDPOINT` - - Args: - azure_endpoint: Your Azure endpoint, including the resource, e.g. `https://example-resource.azure.openai.com/` - - azure_ad_token: Your Azure Active Directory token, https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id - - azure_ad_token_provider: A function that returns an Azure Active Directory token, will be invoked on every request. - - azure_deployment: A model deployment, if given sets the base client URL to include `/deployments/{azure_deployment}`. - Note: this means you won't be able to use non-deployment endpoints. - """ - if api_key is None: - api_key = os.environ.get("AZURE_OPENAI_API_KEY") - - if azure_ad_token is None: - azure_ad_token = os.environ.get("AZURE_OPENAI_AD_TOKEN") - - if api_key is None and azure_ad_token is None and azure_ad_token_provider is None: - raise OpenAIError( - "Missing credentials. Please pass one of `api_key`, `azure_ad_token`, `azure_ad_token_provider`, or the `AZURE_OPENAI_API_KEY` or `AZURE_OPENAI_AD_TOKEN` environment variables." - ) - - if api_version is None: - api_version = os.environ.get("OPENAI_API_VERSION") - - if api_version is None: - raise ValueError( - "Must provide either the `api_version` argument or the `OPENAI_API_VERSION` environment variable" - ) - - if default_query is None: - default_query = {"api-version": api_version} - else: - default_query = {**default_query, "api-version": api_version} - - if base_url is None: - if azure_endpoint is None: - azure_endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT") - - if azure_endpoint is None: - raise ValueError( - "Must provide one of the `base_url` or `azure_endpoint` arguments, or the `AZURE_OPENAI_ENDPOINT` environment variable" - ) - - if azure_deployment is not None: - base_url = f"{azure_endpoint}/openai/deployments/{azure_deployment}" - else: - base_url = f"{azure_endpoint}/openai" - else: - if azure_endpoint is not None: - raise ValueError("base_url and azure_endpoint are mutually exclusive") - - if api_key is None: - # define a sentinel value to avoid any typing issues - api_key = API_KEY_SENTINEL - - super().__init__( - api_key=api_key, - organization=organization, - base_url=base_url, - timeout=timeout, - max_retries=max_retries, - default_headers=default_headers, - default_query=default_query, - http_client=http_client, - _strict_response_validation=_strict_response_validation, - ) - self._api_version = api_version - self._azure_ad_token = azure_ad_token - self._azure_ad_token_provider = azure_ad_token_provider - - @override - def copy( - self, - *, - api_key: str | None = None, - organization: str | None = None, - api_version: str | None = None, - azure_ad_token: str | None = None, - azure_ad_token_provider: AsyncAzureADTokenProvider | None = None, - base_url: str | httpx.URL | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, - http_client: httpx.AsyncClient | None = None, - max_retries: int | NotGiven = NOT_GIVEN, - default_headers: Mapping[str, str] | None = None, - set_default_headers: Mapping[str, str] | None = None, - default_query: Mapping[str, object] | None = None, - set_default_query: Mapping[str, object] | None = None, - _extra_kwargs: Mapping[str, Any] = {}, - ) -> Self: - """ - Create a new client instance re-using the same options given to the current client with optional overriding. - """ - return super().copy( - api_key=api_key, - organization=organization, - base_url=base_url, - timeout=timeout, - http_client=http_client, - max_retries=max_retries, - default_headers=default_headers, - set_default_headers=set_default_headers, - default_query=default_query, - set_default_query=set_default_query, - _extra_kwargs={ - "api_version": api_version or self._api_version, - "azure_ad_token": azure_ad_token or self._azure_ad_token, - "azure_ad_token_provider": azure_ad_token_provider or self._azure_ad_token_provider, - **_extra_kwargs, - }, - ) - - with_options = copy - - async def _get_azure_ad_token(self) -> str | None: - if self._azure_ad_token is not None: - return self._azure_ad_token - - provider = self._azure_ad_token_provider - if provider is not None: - token = provider() - if inspect.isawaitable(token): - token = await token - if not token or not isinstance(token, str): - raise ValueError( - f"Expected `azure_ad_token_provider` argument to return a string but it returned {token}", - ) - return token - - return None - - @override - async def _prepare_options(self, options: FinalRequestOptions) -> None: - headers: dict[str, str | Omit] = {**options.headers} if is_given(options.headers) else {} - options.headers = headers - - azure_ad_token = await self._get_azure_ad_token() - if azure_ad_token is not None: - if headers.get("Authorization") is None: - headers["Authorization"] = f"Bearer {azure_ad_token}" - elif self.api_key is not API_KEY_SENTINEL: - if headers.get("api-key") is None: - headers["api-key"] = self.api_key - else: - # should never be hit - raise ValueError("Unable to handle auth") - - return await super()._prepare_options(options) diff --git a/src/openai/resources/audio/__init__.py b/src/openai/resources/audio/__init__.py index 63d06494b8..3635164d02 100644 --- a/src/openai/resources/audio/__init__.py +++ b/src/openai/resources/audio/__init__.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:audio' """ from .audio import ( Audio, AsyncAudio, diff --git a/src/openai/resources/audio/audio.py b/src/openai/resources/audio/audio.py index bafacf4422..b88ba5f583 100644 --- a/src/openai/resources/audio/audio.py +++ b/src/openai/resources/audio/audio.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:audio' """ from __future__ import annotations from .speech import ( diff --git a/src/openai/resources/audio/speech.py b/src/openai/resources/audio/speech.py index 4e94d4aaef..fbdc1ecff1 100644 --- a/src/openai/resources/audio/speech.py +++ b/src/openai/resources/audio/speech.py @@ -78,6 +78,7 @@ def create( timeout: Override the client-level default timeout for this request, in seconds """ + extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})} return self._post( "/audio/speech", body=maybe_transform( @@ -149,6 +150,7 @@ async def create( timeout: Override the client-level default timeout for this request, in seconds """ + extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})} return await self._post( "/audio/speech", body=maybe_transform( diff --git a/src/openai/resources/beta/__init__.py b/src/openai/resources/beta/__init__.py index 973c6ba54e..c1fe838d95 100644 --- a/src/openai/resources/beta/__init__.py +++ b/src/openai/resources/beta/__init__.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:beta' """ from .beta import ( Beta, AsyncBeta, diff --git a/src/openai/resources/beta/assistants/assistants.py b/src/openai/resources/beta/assistants/assistants.py index e926c31642..0c19405aaf 100644 --- a/src/openai/resources/beta/assistants/assistants.py +++ b/src/openai/resources/beta/assistants/assistants.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:assistants' """ from __future__ import annotations from typing import List, Iterable, Optional diff --git a/src/openai/resources/beta/beta.py b/src/openai/resources/beta/beta.py index 7081cff305..8c8840874e 100644 --- a/src/openai/resources/beta/beta.py +++ b/src/openai/resources/beta/beta.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:beta' """ from __future__ import annotations from .threads import ( diff --git a/src/openai/resources/beta/threads/threads.py b/src/openai/resources/beta/threads/threads.py index dd079ac533..f9c55d6952 100644 --- a/src/openai/resources/beta/threads/threads.py +++ b/src/openai/resources/beta/threads/threads.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:threads' """ from __future__ import annotations from typing import Iterable, Optional diff --git a/src/openai/resources/chat/__init__.py b/src/openai/resources/chat/__init__.py index a9668053c0..41804ae20f 100644 --- a/src/openai/resources/chat/__init__.py +++ b/src/openai/resources/chat/__init__.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:chat' """ from .chat import ( Chat, AsyncChat, diff --git a/src/openai/resources/chat/chat.py b/src/openai/resources/chat/chat.py index b6effa4e63..4cea5bd709 100644 --- a/src/openai/resources/chat/chat.py +++ b/src/openai/resources/chat/chat.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:chat' """ from __future__ import annotations from ..._compat import cached_property diff --git a/src/openai/resources/chat/completions.py b/src/openai/resources/chat/completions.py index 88834839a5..6f66f1e2a7 100644 --- a/src/openai/resources/chat/completions.py +++ b/src/openai/resources/chat/completions.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:chat_completions' """ from __future__ import annotations from typing import Dict, List, Union, Iterable, Optional, overload @@ -660,142 +660,6 @@ def create( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ChatCompletion | Stream[ChatCompletionChunk]: - """ - Creates a model response for the given chat conversation. - - Args: - messages: A list of messages comprising the conversation so far. - [Example Python code](https://cookbook.openai.com/examples/how_to_format_inputs_to_chatgpt_models). - - model: ID of the model to use. See the - [model endpoint compatibility](https://platform.openai.com/docs/models/model-endpoint-compatibility) - table for details on which models work with the Chat API. - - frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their - existing frequency in the text so far, decreasing the model's likelihood to - repeat the same line verbatim. - - [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation/parameter-details) - - function_call: Deprecated in favor of `tool_choice`. - - Controls which (if any) function is called by the model. `none` means the model - will not call a function and instead generates a message. `auto` means the model - can pick between generating a message or calling a function. Specifying a - particular function via `{"name": "my_function"}` forces the model to call that - function. - - `none` is the default when no functions are present. `auto` is the default if - functions are present. - - functions: Deprecated in favor of `tools`. - - A list of functions the model may generate JSON inputs for. - - logit_bias: Modify the likelihood of specified tokens appearing in the completion. - - Accepts a JSON object that maps tokens (specified by their token ID in the - tokenizer) to an associated bias value from -100 to 100. Mathematically, the - bias is added to the logits generated by the model prior to sampling. The exact - effect will vary per model, but values between -1 and 1 should decrease or - increase likelihood of selection; values like -100 or 100 should result in a ban - or exclusive selection of the relevant token. - - logprobs: Whether to return log probabilities of the output tokens or not. If true, - returns the log probabilities of each output token returned in the `content` of - `message`. This option is currently not available on the `gpt-4-vision-preview` - model. - - max_tokens: The maximum number of [tokens](/tokenizer) that can be generated in the chat - completion. - - The total length of input tokens and generated tokens is limited by the model's - context length. - [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) - for counting tokens. - - n: How many chat completion choices to generate for each input message. Note that - you will be charged based on the number of generated tokens across all of the - choices. Keep `n` as `1` to minimize costs. - - presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on - whether they appear in the text so far, increasing the model's likelihood to - talk about new topics. - - [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation/parameter-details) - - response_format: An object specifying the format that the model must output. Compatible with - [GPT-4 Turbo](https://platform.openai.com/docs/models/gpt-4-and-gpt-4-turbo) and - all GPT-3.5 Turbo models newer than `gpt-3.5-turbo-1106`. - - Setting to `{ "type": "json_object" }` enables JSON mode, which guarantees the - message the model generates is valid JSON. - - **Important:** when using JSON mode, you **must** also instruct the model to - produce JSON yourself via a system or user message. Without this, the model may - generate an unending stream of whitespace until the generation reaches the token - limit, resulting in a long-running and seemingly "stuck" request. Also note that - the message content may be partially cut off if `finish_reason="length"`, which - indicates the generation exceeded `max_tokens` or the conversation exceeded the - max context length. - - seed: This feature is in Beta. If specified, our system will make a best effort to - sample deterministically, such that repeated requests with the same `seed` and - parameters should return the same result. Determinism is not guaranteed, and you - should refer to the `system_fingerprint` response parameter to monitor changes - in the backend. - - stop: Up to 4 sequences where the API will stop generating further tokens. - - stream: If set, partial message deltas will be sent, like in ChatGPT. Tokens will be - sent as data-only - [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - as they become available, with the stream terminated by a `data: [DONE]` - message. - [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). - - temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will - make the output more random, while lower values like 0.2 will make it more - focused and deterministic. - - We generally recommend altering this or `top_p` but not both. - - tool_choice: Controls which (if any) function is called by the model. `none` means the model - will not call a function and instead generates a message. `auto` means the model - can pick between generating a message or calling a function. Specifying a - particular function via - `{"type": "function", "function": {"name": "my_function"}}` forces the model to - call that function. - - `none` is the default when no functions are present. `auto` is the default if - functions are present. - - tools: A list of tools the model may call. Currently, only functions are supported as a - tool. Use this to provide a list of functions the model may generate JSON inputs - for. - - top_logprobs: An integer between 0 and 5 specifying the number of most likely tokens to return - at each token position, each with an associated log probability. `logprobs` must - be set to `true` if this parameter is used. - - top_p: An alternative to sampling with temperature, called nucleus sampling, where the - model considers the results of the tokens with top_p probability mass. So 0.1 - means only the tokens comprising the top 10% probability mass are considered. - - We generally recommend altering this or `temperature` but not both. - - user: A unique identifier representing your end-user, which can help OpenAI to monitor - and detect abuse. - [Learn more](https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids). - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ return self._post( "/chat/completions", body=maybe_transform( @@ -1463,141 +1327,125 @@ async def create( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ChatCompletion | AsyncStream[ChatCompletionChunk]: - """ - Creates a model response for the given chat conversation. + """Generates a chat completion by submitting a conversation history and model parameters, supporting various configurations to tailor the chat completion process, including penalties, response formats, and streaming outputs. + + Returns: + AsyncStream[ChatCompletionChunk]: Stream of chat completion chunks for incremental output consumption. + ChatCompletion: An object containing the generated chat completion and other relevant details, such as + the chosen tokens and any associated metadata. + + Raises: + OpenAIError: If there's an issue with API request or parsing the response. + + Examples: + ```python + completion = client.Completions().create( + messages=[{"role": "user", "content": "Tell me a joke."}], + model="text-davinci-003", + max_tokens=60 + ) + print(completion.choices[0].text) + ``` + + ```python + completion = client.Completions().create( + messages=[{"role": "user", "content": "How do you make a latte?"}], + model="gpt-3.5-turbo", + max_tokens=150 + ) + print(completion.choices[0].text) + ``` + + ```python + async with client.AsyncCompletions().create( + messages=[{"role": "user", "content": "What's the weather like in Tokyo?"}], + model="text-davinci-003", + frequency_penalty=0.5, + presence_penalty=0.5 + ) as stream: + async for chunk in stream: + print(chunk.text) + ``` Args: - messages: A list of messages comprising the conversation so far. - [Example Python code](https://cookbook.openai.com/examples/how_to_format_inputs_to_chatgpt_models). - - model: ID of the model to use. See the - [model endpoint compatibility](https://platform.openai.com/docs/models/model-endpoint-compatibility) - table for details on which models work with the Chat API. - - frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their - existing frequency in the text so far, decreasing the model's likelihood to - repeat the same line verbatim. - - [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation/parameter-details) - - function_call: Deprecated in favor of `tool_choice`. - - Controls which (if any) function is called by the model. `none` means the model - will not call a function and instead generates a message. `auto` means the model - can pick between generating a message or calling a function. Specifying a - particular function via `{"name": "my_function"}` forces the model to call that - function. - - `none` is the default when no functions are present. `auto` is the default if - functions are present. - - functions: Deprecated in favor of `tools`. - - A list of functions the model may generate JSON inputs for. - - logit_bias: Modify the likelihood of specified tokens appearing in the completion. - - Accepts a JSON object that maps tokens (specified by their token ID in the - tokenizer) to an associated bias value from -100 to 100. Mathematically, the - bias is added to the logits generated by the model prior to sampling. The exact - effect will vary per model, but values between -1 and 1 should decrease or - increase likelihood of selection; values like -100 or 100 should result in a ban - or exclusive selection of the relevant token. - - logprobs: Whether to return log probabilities of the output tokens or not. If true, - returns the log probabilities of each output token returned in the `content` of - `message`. This option is currently not available on the `gpt-4-vision-preview` - model. - - max_tokens: The maximum number of [tokens](/tokenizer) that can be generated in the chat - completion. - - The total length of input tokens and generated tokens is limited by the model's - context length. - [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) - for counting tokens. - - n: How many chat completion choices to generate for each input message. Note that - you will be charged based on the number of generated tokens across all of the - choices. Keep `n` as `1` to minimize costs. - - presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on - whether they appear in the text so far, increasing the model's likelihood to - talk about new topics. - - [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation/parameter-details) - - response_format: An object specifying the format that the model must output. Compatible with - [GPT-4 Turbo](https://platform.openai.com/docs/models/gpt-4-and-gpt-4-turbo) and - all GPT-3.5 Turbo models newer than `gpt-3.5-turbo-1106`. - - Setting to `{ "type": "json_object" }` enables JSON mode, which guarantees the - message the model generates is valid JSON. - - **Important:** when using JSON mode, you **must** also instruct the model to - produce JSON yourself via a system or user message. Without this, the model may - generate an unending stream of whitespace until the generation reaches the token - limit, resulting in a long-running and seemingly "stuck" request. Also note that - the message content may be partially cut off if `finish_reason="length"`, which - indicates the generation exceeded `max_tokens` or the conversation exceeded the - max context length. - - seed: This feature is in Beta. If specified, our system will make a best effort to - sample deterministically, such that repeated requests with the same `seed` and - parameters should return the same result. Determinism is not guaranteed, and you - should refer to the `system_fingerprint` response parameter to monitor changes - in the backend. - - stop: Up to 4 sequences where the API will stop generating further tokens. - - stream: If set, partial message deltas will be sent, like in ChatGPT. Tokens will be - sent as data-only - [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - as they become available, with the stream terminated by a `data: [DONE]` - message. - [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). - - temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will - make the output more random, while lower values like 0.2 will make it more - focused and deterministic. - - We generally recommend altering this or `top_p` but not both. - - tool_choice: Controls which (if any) function is called by the model. `none` means the model - will not call a function and instead generates a message. `auto` means the model - can pick between generating a message or calling a function. Specifying a - particular function via - `{"type": "function", "function": {"name": "my_function"}}` forces the model to - call that function. - - `none` is the default when no functions are present. `auto` is the default if - functions are present. - - tools: A list of tools the model may call. Currently, only functions are supported as a - tool. Use this to provide a list of functions the model may generate JSON inputs - for. - - top_logprobs: An integer between 0 and 5 specifying the number of most likely tokens to return - at each token position, each with an associated log probability. `logprobs` must - be set to `true` if this parameter is used. - - top_p: An alternative to sampling with temperature, called nucleus sampling, where the - model considers the results of the tokens with top_p probability mass. So 0.1 - means only the tokens comprising the top 10% probability mass are considered. - - We generally recommend altering this or `temperature` but not both. - - user: A unique identifier representing your end-user, which can help OpenAI to monitor - and detect abuse. - [Learn more](https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids). - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds + messages (Iterable[ChatCompletionMessageParam]): A sequence of message objects that make up the + conversation so far. Each message is a dictionary that should include the keys `role` and + `content`, where `role` is either `user` or `assistant`, indicating who is speaking, and + `content` is a string containing the message text. This parameter is essential for + constructing the conversational context for the model's response. + model (Union[str, Literal[...]]): The model ID of the OpenAI GPT model to use for generating the chat + completion. This parameter specifies which version of the model to use, for example, + `text-davinci-003` for general-purpose completions or `gpt-3.5-turbo` for optimized + performance. The choice of model affects the quality, style, and capabilities of the + generated content. + stream (Optional[bool]): Whether the response should be streamed. Streaming can be useful for + receiving responses as they are generated, especially for long completions. This approach + enables real-time interaction and processing of the model's output. + frequency_penalty (Optional[float]): Adjusts the likelihood of the model repeating the same line + verbatim. Values can range from -2.0 to 2.0, with positive values making repeats less likely. + This parameter helps in controlling the diversity of the generated text. + function_call (Optional[FunctionCall]): Deprecated. Originally used to specify whether the model + should execute a function call. While it is still accepted for backward compatibility, the + `tool_choice` parameter is recommended for new implementations. + functions (Optional[Iterable[Function]]): Deprecated. Originally provided a list of functions the + model could choose to call during generation. Like `function_call`, this parameter has been + superseded by `tools`. + logit_bias (Optional[Dicst[str, int]]): Modifies token likelihood, mapping token IDs to bias values + (-100 to 100), influencing selection. This mechanism allows for fine-tuning the presence or + avoidance of specific words or phrases in the generated text. + logprobs (Optional[bool]): Whether to return the log probabilities of the tokens generated in the + completion. Useful for model introspection and understanding the model's decision-making + process. Note: This feature might not be available for all models. + max_tokens (Optional[int]): The maximum number of tokens to generate in the completion. This limit + includes the tokens in the prompt. Careful management of this parameter is crucial for + controlling the length and computational cost of model operations. + n (Optional[int]): The number of completions to generate for each prompt. Higher values allow for + more diversity in the responses but increase computational cost. Balancing this parameter + is key to achieving desired output variability while managing resource use. + presence_penalty (Optional[float]): Encourages new content by penalizing token presence, with values + from -2.0 to 2.0. This parameter influences the model to explore new topics and ideas, + enhancing the creativity and variability of the output. + response_format (Optional[ResponseFormat]): Specifies how the model's responses should be formatted. + For example, responses can be structured as plain text, JSON objects, or other formats + depending on the model's capabilities. This flexibility allows for tailored outputs to suit + different applications and processing needs. + seed (Optional[int]): Seed for deterministic randomness, ensuring same inputs yield consistent + outputs. This feature is beneficial for reproducibility and debugging purposes, allowing + users to obtain the same results from identical requests. + stop (Optional[Union[str, List[str]]]): Sequences where the API will stop generating further tokens. + This can be used to indicate the end of a message or section, providing a mechanism to + control the scope and completion of the generated content. + temperature (Optional[float]): Controls the randomness of the output. A lower temperature results in + more deterministic output, while a higher temperature results in more diversity. Adjusting + this parameter allows users to balance between predictability and creativity in the model's + responses. + tool_choice (Optional[ToolChoiceOptionParam]): Specifies which tool the model should use if it + decides to make an external call. This replaces `function_call` and offers more granular + control over the model's interactive capabilities. + tools (Optional[Iterable[ToolParam]]): Lists tools available for response generation, including + functions and APIs. This parameter expands the model's ability to incorporate external data + and functionalities into its responses, broadening the scope of possible applications. + top_logprobs (Optional[int]): Specifies the number of top logits to return, providing insight into + the model's decision-making process. This information can be valuable for analyzing the + model's preferences and the statistical distribution of its predictions. + top_p (Optional[float]): Nucleus sampling strategy focusing on top P% probability mass, influencing + token selection. This parameter adjusts the scope of the token set considered at each step, + effectively adjusting the diversity and unpredictability of the output. A balance between + coherence and variety can be achieved by tuning this parameter. + user (Optional[str]): Identifies the end user of the API, aiding in monitoring usage patterns and + detecting potential misuse. This parameter helps maintain the security and integrity of the + system, ensuring that the API is used responsibly and in accordance with OpenAI's guidelines. + [End user identification best practices](https://platform.openai.com/docs/guides/safety-best-practices/end user-ids) + extra_headers (Optional[Headers]): Additional HTTP headers to send with the request. This allows for + customizing the request headers for scenarios that require specific HTTP header entries. + extra_query (Optional[Query]): Extra query parameters for the request URL. These parameters are + appended to the URL query string, providing a flexible way to extend the request with + additional data. + extra_body (Optional[Body]): Additional body parameters to include in the POST request. This can be + used to pass extra information that is not covered by the standard parameters. + timeout (Optional[float | httpx.Timeout]): Custom timeout for the request, overriding the default. + Setting this parameter ensures that operations adhere to specific timing requirements, + preventing excessively long waits or premature termination of requests. """ return await self._post( "/chat/completions", diff --git a/src/openai/resources/completions.py b/src/openai/resources/completions.py index f3d1375d6e..2ae1a86828 100644 --- a/src/openai/resources/completions.py +++ b/src/openai/resources/completions.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:completions' """ from __future__ import annotations from typing import Dict, List, Union, Iterable, Optional, overload diff --git a/src/openai/resources/embeddings.py b/src/openai/resources/embeddings.py index cfef025bc2..ce8ab8d7fe 100644 --- a/src/openai/resources/embeddings.py +++ b/src/openai/resources/embeddings.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:embeddings' """ from __future__ import annotations import base64 diff --git a/src/openai/resources/files.py b/src/openai/resources/files.py index 58a2a217c7..2c7f21c920 100644 --- a/src/openai/resources/files.py +++ b/src/openai/resources/files.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:files' """ from __future__ import annotations import time @@ -238,6 +238,7 @@ def content( """ if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + extra_headers = {"Accept": "application/binary", **(extra_headers or {})} return self._get( f"/files/{file_id}/content", options=make_request_options( @@ -272,7 +273,6 @@ def retrieve_content( """ if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") - extra_headers = {"Accept": "application/json", **(extra_headers or {})} return self._get( f"/files/{file_id}/content", options=make_request_options( @@ -511,6 +511,7 @@ async def content( """ if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + extra_headers = {"Accept": "application/binary", **(extra_headers or {})} return await self._get( f"/files/{file_id}/content", options=make_request_options( @@ -545,7 +546,6 @@ async def retrieve_content( """ if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") - extra_headers = {"Accept": "application/json", **(extra_headers or {})} return await self._get( f"/files/{file_id}/content", options=make_request_options( diff --git a/src/openai/resources/fine_tuning/__init__.py b/src/openai/resources/fine_tuning/__init__.py index ab0c28ef4b..4d0a1a644c 100644 --- a/src/openai/resources/fine_tuning/__init__.py +++ b/src/openai/resources/fine_tuning/__init__.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:fine_tuning' """ from .jobs import ( Jobs, AsyncJobs, diff --git a/src/openai/resources/fine_tuning/fine_tuning.py b/src/openai/resources/fine_tuning/fine_tuning.py index 33b25baec9..5acc0f6807 100644 --- a/src/openai/resources/fine_tuning/fine_tuning.py +++ b/src/openai/resources/fine_tuning/fine_tuning.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:fine_tuning' """ from __future__ import annotations from .jobs import ( diff --git a/src/openai/resources/fine_tuning/jobs.py b/src/openai/resources/fine_tuning/jobs.py index 6b59932982..9d551f786a 100644 --- a/src/openai/resources/fine_tuning/jobs.py +++ b/src/openai/resources/fine_tuning/jobs.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:fine_tuning_jobs' """ from __future__ import annotations from typing import Union, Optional diff --git a/src/openai/resources/images.py b/src/openai/resources/images.py index 91530e47ca..1ca6400614 100644 --- a/src/openai/resources/images.py +++ b/src/openai/resources/images.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:images' """ from __future__ import annotations from typing import Union, Mapping, Optional, cast diff --git a/src/openai/resources/models.py b/src/openai/resources/models.py index 3536f083d2..42e456d78c 100644 --- a/src/openai/resources/models.py +++ b/src/openai/resources/models.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:models' """ from __future__ import annotations import httpx diff --git a/src/openai/resources/moderations.py b/src/openai/resources/moderations.py index 540d089071..0c88d9620c 100644 --- a/src/openai/resources/moderations.py +++ b/src/openai/resources/moderations.py @@ -1,5 +1,5 @@ # File generated from our OpenAPI spec by Stainless. - +""" --8<-- 'docs/reference/include/openai.resources.py:moderations' """ from __future__ import annotations from typing import List, Union