La bibliothèque OpenAI Python offre un accès pratique à l'API REST OpenAI à partir de n'importe quelle application Python 3.8+. La bibliothèque comprend des définitions de type pour tous les paramètres de requête et champs de réponse, et propose des clients synchrones et asynchrones alimentés par httpx.
Il est généré à partir de notre spécification OpenAPI avec Stainless.
La documentation de l'API REST est disponible sur platform.openai.com. L'API complète de cette bibliothèque peut être trouvée dans api.md.
Important
Le SDK a été réécrit dans la v1, publiée le 6 novembre 2023. Consultez le guide de migration v1, qui comprend des scripts pour mettre automatiquement à jour votre code.
# install from PyPI
pip install openai
L'API complète de cette bibliothèque peut être trouvée dans api.md.
import os
from openai import OpenAI
client = OpenAI (
api_key = os . environ . get ( "OPENAI_API_KEY" ), # This is the default and can be omitted
)
chat_completion = client . chat . completions . create (
messages = [
{
"role" : "user" ,
"content" : "Say this is a test" ,
}
],
model = "gpt-4o" ,
)
Bien que vous puissiez fournir un argument de mot-clé api_key
, nous vous recommandons d'utiliser python-dotenv pour ajouter OPENAI_API_KEY="My API Key"
à votre fichier .env
afin que votre clé API ne soit pas stockée dans le contrôle de code source.
Avec une image hébergée :
response = client . chat . completions . create (
model = "gpt-4o-mini" ,
messages = [
{
"role" : "user" ,
"content" : [
{ "type" : "text" , "text" : prompt },
{
"type" : "image_url" ,
"image_url" : { "url" : f" { img_url } " },
},
],
}
],
)
Avec l'image sous forme de chaîne codée en base64 :
response = client . chat . completions . create (
model = "gpt-4o-mini" ,
messages = [
{
"role" : "user" ,
"content" : [
{ "type" : "text" , "text" : prompt },
{
"type" : "image_url" ,
"image_url" : { "url" : f"data: { img_type } ;base64, { img_b64_str } " },
},
],
}
],
)
Lors de l'interaction avec l'API, certaines actions telles que le démarrage d'une exécution et l'ajout de fichiers aux magasins de vecteurs sont asynchrones et prennent du temps. Le SDK comprend des fonctions d'assistance qui interrogeront l'état jusqu'à ce qu'il atteigne un état terminal, puis renverront l'objet résultant. Si une méthode API aboutit à une action qui pourrait bénéficier d'une interrogation, il y aura une version correspondante de la méthode se terminant par « _and_poll ».
Par exemple, pour créer un Run et un sondage jusqu'à ce qu'il atteigne un état terminal, vous pouvez exécuter :
run = client . beta . threads . runs . create_and_poll (
thread_id = thread . id ,
assistant_id = assistant . id ,
)
Plus d'informations sur le cycle de vie d'une exécution peuvent être trouvées dans la documentation sur le cycle de vie de l'exécution.
Lors de la création et de l'interaction avec des magasins de vecteurs, vous pouvez utiliser des assistants d'interrogation pour surveiller l'état des opérations. Pour plus de commodité, nous fournissons également un assistant de téléchargement groupé pour vous permettre de télécharger simultanément plusieurs fichiers à la fois.
sample_files = [ Path ( "sample-paper.pdf" ), ...]
batch = await client . vector_stores . file_batches . upload_and_poll (
store . id ,
files = sample_files ,
)
Le SDK comprend également des assistants pour traiter les flux et gérer les événements entrants.
with client . beta . threads . runs . stream (
thread_id = thread . id ,
assistant_id = assistant . id ,
instructions = "Please address the user as Jane Doe. The user has a premium account." ,
) as stream :
for event in stream :
# Print the text from text delta events
if event . type == "thread.message.delta" and event . data . delta . content :
print ( event . data . delta . content [ 0 ]. text )
Plus d’informations sur les assistants de streaming peuvent être trouvées dans la documentation dédiée : helpers.md
Importez simplement AsyncOpenAI
au lieu d' OpenAI
et utilisez await
avec chaque appel d'API :
import os
import asyncio
from openai import AsyncOpenAI
client = AsyncOpenAI (
api_key = os . environ . get ( "OPENAI_API_KEY" ), # This is the default and can be omitted
)
async def main () -> None :
chat_completion = await client . chat . completions . create (
messages = [
{
"role" : "user" ,
"content" : "Say this is a test" ,
}
],
model = "gpt-4o" ,
)
asyncio . run ( main ())
La fonctionnalité entre les clients synchrones et asynchrones est par ailleurs identique.
Nous fournissons une prise en charge des réponses en streaming à l'aide des événements côté serveur (SSE).
from openai import OpenAI
client = OpenAI ()
stream = client . chat . completions . create (
messages = [
{
"role" : "user" ,
"content" : "Say this is a test" ,
}
],
model = "gpt-4o" ,
stream = True ,
)
for chunk in stream :
print ( chunk . choices [ 0 ]. delta . content or "" , end = "" )
Le client asynchrone utilise exactement la même interface.
import asyncio
from openai import AsyncOpenAI
client = AsyncOpenAI ()
async def main ():
stream = await client . chat . completions . create (
model = "gpt-4" ,
messages = [{ "role" : "user" , "content" : "Say this is a test" }],
stream = True ,
)
async for chunk in stream :
print ( chunk . choices [ 0 ]. delta . content or "" , end = "" )
asyncio . run ( main ())
Important
Nous vous recommandons fortement d'instancier des instances client au lieu de vous fier au client global.
Nous exposons également une instance client globale accessible de la même manière que les versions antérieures à la v1.
import openai
# optional; defaults to `os.environ['OPENAI_API_KEY']`
openai . api_key = '...'
# all client options can be configured just like the `OpenAI` instantiation counterpart
openai . base_url = "https://..."
openai . default_headers = { "x-foo" : "true" }
completion = openai . chat . completions . create (
model = "gpt-4o" ,
messages = [
{
"role" : "user" ,
"content" : "How do I output all files in a directory using Python?" ,
},
],
)
print ( completion . choices [ 0 ]. message . content )
L'API est exactement la même que l'API standard basée sur une instance client.
Ceci est destiné à être utilisé dans les REPL ou les notebooks pour une itération plus rapide, pas dans le code d'application.
Nous vous recommandons de toujours instancier un client (par exemple, avec client = OpenAI()
) dans le code de l'application car :
Les paramètres de requête imbriqués sont TypedDicts. Les réponses sont des modèles Pydantic qui fournissent également des méthodes d'assistance pour des choses telles que :
model.to_json()
model.to_dict()
Les requêtes et réponses saisies fournissent une saisie semi-automatique et une documentation dans votre éditeur. Si vous souhaitez voir les erreurs de type dans VS Code pour vous aider à détecter les bogues plus tôt, définissez python.analysis.typeCheckingMode
sur basic
.
Les méthodes de liste de l'API OpenAI sont paginées.
Cette bibliothèque fournit des itérateurs à pagination automatique avec chaque réponse de liste, vous n'avez donc pas besoin de demander manuellement des pages successives :
from openai import OpenAI
client = OpenAI ()
all_jobs = []
# Automatically fetches more pages as needed.
for job in client . fine_tuning . jobs . list (
limit = 20 ,
):
# Do something with job here
all_jobs . append ( job )
print ( all_jobs )
Ou, de manière asynchrone :
import asyncio
from openai import AsyncOpenAI
client = AsyncOpenAI ()
async def main () -> None :
all_jobs = []
# Iterate through items across all pages, issuing requests as needed.
async for job in client . fine_tuning . jobs . list (
limit = 20 ,
):
all_jobs . append ( job )
print ( all_jobs )
asyncio . run ( main ())
Vous pouvez également utiliser les méthodes .has_next_page()
, .next_page_info()
ou .get_next_page()
pour un contrôle plus granulaire de l'utilisation des pages :
first_page = await client . fine_tuning . jobs . list (
limit = 20 ,
)
if first_page . has_next_page ():
print ( f"will fetch next page using these details: { first_page . next_page_info () } " )
next_page = await first_page . get_next_page ()
print ( f"number of items we just fetched: { len ( next_page . data ) } " )
# Remove `await` for non-async usage.
Ou travaillez simplement directement avec les données renvoyées :
first_page = await client . fine_tuning . jobs . list (
limit = 20 ,
)
print ( f"next page cursor: { first_page . after } " ) # => "next page cursor: ..."
for job in first_page . data :
print ( job . id )
# Remove `await` for non-async usage.
Les paramètres imbriqués sont des dictionnaires, saisis à l'aide de TypedDict
, par exemple :
from openai import OpenAI
client = OpenAI ()
completion = client . chat . completions . create (
messages = [
{
"role" : "user" ,
"content" : "Can you generate an example json object describing a fruit?" ,
}
],
model = "gpt-4o" ,
response_format = { "type" : "json_object" },
)
Les paramètres de requête qui correspondent aux téléchargements de fichiers peuvent être transmis sous forme bytes
, d'instance PathLike
ou de tuple de (filename, contents, media type)
.
from pathlib import Path
from openai import OpenAI
client = OpenAI ()
client . files . create (
file = Path ( "input.jsonl" ),
purpose = "fine-tune" ,
)
Le client asynchrone utilise exactement la même interface. Si vous transmettez une instance PathLike
, le contenu du fichier sera lu automatiquement de manière asynchrone.
Lorsque la bibliothèque ne parvient pas à se connecter à l'API (par exemple, en raison de problèmes de connexion réseau ou d'un délai d'attente), une sous-classe de openai.APIConnectionError
est générée.
Lorsque l'API renvoie un code d'état d'échec (c'est-à-dire une réponse 4xx ou 5xx), une sous-classe de openai.APIStatusError
est générée, contenant status_code
et les propriétés response
.
Toutes les erreurs héritent de openai.APIError
.
import openai
from openai import OpenAI
client = OpenAI ()
try :
client . fine_tuning . jobs . create (
model = "gpt-4o" ,
training_file = "file-abc123" ,
)
except openai . APIConnectionError as e :
print ( "The server could not be reached" )
print ( e . __cause__ ) # an underlying Exception, likely raised within httpx.
except openai . RateLimitError as e :
print ( "A 429 status code was received; we should back off a bit." )
except openai . APIStatusError as e :
print ( "Another non-200-range status code was received" )
print ( e . status_code )
print ( e . response )
Les codes d'erreur sont les suivants :
Code d'état | Type d'erreur |
---|---|
400 | BadRequestError |
401 | AuthenticationError |
403 | PermissionDeniedError |
404 | NotFoundError |
422 | UnprocessableEntityError |
429 | RateLimitError |
>=500 | InternalServerError |
N / A | APIConnectionError |
Pour plus d'informations sur les requêtes de débogage, consultez ces documents
Toutes les réponses d'objet dans le SDK fournissent une propriété _request_id
qui est ajoutée à partir de l'en-tête de réponse x-request-id
afin que vous puissiez rapidement enregistrer les demandes ayant échoué et les signaler à OpenAI.
completion = await client . chat . completions . create (
messages = [{ "role" : "user" , "content" : "Say this is a test" }], model = "gpt-4"
)
print ( completion . _request_id ) # req_123
Notez que contrairement aux autres propriétés qui utilisent un préfixe _
, la propriété _request_id
est publique. Sauf indication contraire, toutes les autres propriétés, méthodes et modules du préfixe _
sont private .
Certaines erreurs sont automatiquement réessayées 2 fois par défaut, avec un court délai exponentiel. Les erreurs de connexion (par exemple, en raison d'un problème de connectivité réseau), 408 Request Timeout, 409 Conflict, 429 Rate Limit et >=500 Internal Errors sont toutes réessayées par défaut.
Vous pouvez utiliser l'option max_retries
pour configurer ou désactiver les paramètres de nouvelle tentative :
from openai import OpenAI
# Configure the default for all requests:
client = OpenAI (
# default is 2
max_retries = 0 ,
)
# Or, configure per-request:
client . with_options ( max_retries = 5 ). chat . completions . create (
messages = [
{
"role" : "user" ,
"content" : "How can I get the name of the current day in JavaScript?" ,
}
],
model = "gpt-4o" ,
)
Par défaut, les demandes expirent après 10 minutes. Vous pouvez configurer cela avec une option timeout
, qui accepte un float ou un objet httpx.Timeout
:
from openai import OpenAI
# Configure the default for all requests:
client = OpenAI (
# 20 seconds (default is 10 minutes)
timeout = 20.0 ,
)
# More granular control:
client = OpenAI (
timeout = httpx . Timeout ( 60.0 , read = 5.0 , write = 10.0 , connect = 2.0 ),
)
# Override per-request:
client . with_options ( timeout = 5.0 ). chat . completions . create (
messages = [
{
"role" : "user" ,
"content" : "How can I list all files in a directory using Python?" ,
}
],
model = "gpt-4o" ,
)
En cas d'expiration, une APITimeoutError
est levée.
Notez que les demandes qui expirent sont réessayées deux fois par défaut.
Nous utilisons le module logging
de bibliothèque standard.
Vous pouvez activer la journalisation en définissant la variable d'environnement OPENAI_LOG
sur info
.
$ export OPENAI_LOG=info
Ou pour debug
pour une journalisation plus détaillée.
None
signifie null
ou manquant Dans une réponse API, un champ peut être explicitement null
ou entièrement manquant ; dans les deux cas, sa valeur est None
dans cette bibliothèque. Vous pouvez différencier les deux cas avec .model_fields_set
:
if response . my_field is None :
if 'my_field' not in response . model_fields_set :
print ( 'Got json like {}, without a "my_field" key present at all.' )
else :
print ( 'Got json like {"my_field": null}.' )
L'objet Response "brut" est accessible en préfixant .with_raw_response.
à n'importe quel appel de méthode HTTP, par exemple,
from openai import OpenAI
client = OpenAI ()
response = client . chat . completions . with_raw_response . create (
messages = [{
"role" : "user" ,
"content" : "Say this is a test" ,
}],
model = "gpt-4o" ,
)
print ( response . headers . get ( 'X-My-Header' ))
completion = response . parse () # get the object that `chat.completions.create()` would have returned
print ( completion )
Ces méthodes renvoient un objet LegacyAPIResponse
. Il s'agit d'une classe héritée car nous la modifions légèrement dans la prochaine version majeure.
Pour le client de synchronisation, ce sera essentiellement la même chose, à l'exception du content
et text
qui seront des méthodes au lieu de propriétés. Dans le client asynchrone, toutes les méthodes seront asynchrones.
Un script de migration sera fourni et la migration en général devrait se dérouler en douceur.
.with_streaming_response
L'interface ci-dessus lit avec impatience le corps complet de la réponse lorsque vous faites la demande, ce qui n'est pas toujours ce que vous souhaitez.
Pour diffuser le corps de la réponse, utilisez plutôt .with_streaming_response
, qui nécessite un gestionnaire de contexte et ne lit le corps de la réponse qu'une fois que vous appelez .read()
, .text()
, .json()
, .iter_bytes()
, .iter_text()
, .iter_lines()
ou .parse()
. Dans le client asynchrone, ce sont des méthodes asynchrones.
En tant que telles, les méthodes .with_streaming_response
renvoient un objet APIResponse
différent et le client asynchrone renvoie un objet AsyncAPIResponse
.
with client . chat . completions . with_streaming_response . create (
messages = [
{
"role" : "user" ,
"content" : "Say this is a test" ,
}
],
model = "gpt-4o" ,
) as response :
print ( response . headers . get ( "X-My-Header" ))
for line in response . iter_lines ():
print ( line )
Le gestionnaire de contexte est requis pour que la réponse soit fermée de manière fiable.
Cette bibliothèque est typée pour un accès pratique à l'API documentée.
Si vous devez accéder à des points de terminaison, des paramètres ou des propriétés de réponse non documentés, la bibliothèque peut toujours être utilisée.
Pour envoyer des requêtes à des points de terminaison non documentés, vous pouvez effectuer des requêtes à l'aide de client.get
, client.post
et d'autres verbes http. Les options sur le client seront respectées (telles que les tentatives) lors de cette demande.
import httpx
response = client . post (
"/foo" ,
cast_to = httpx . Response ,
body = { "my_param" : True },
)
print ( response . headers . get ( "x-foo" ))
Si vous souhaitez envoyer explicitement un paramètre supplémentaire, vous pouvez le faire avec les options de requête extra_query
, extra_body
et extra_headers
.
Pour accéder aux propriétés de réponse non documentées, vous pouvez accéder aux champs supplémentaires comme response.unknown_prop
. Vous pouvez également obtenir tous les champs supplémentaires du modèle Pydantic sous forme de dict avec response.model_extra
.
Vous pouvez directement remplacer le client httpx pour le personnaliser en fonction de votre cas d'utilisation, notamment :
from openai import OpenAI , DefaultHttpxClient
client = OpenAI (
# Or use the `OPENAI_BASE_URL` env var
base_url = "http://my.test.server.example.com:8083/v1" ,
http_client = DefaultHttpxClient (
proxies = "http://my.test.proxy.example.com" ,
transport = httpx . HTTPTransport ( local_address = "0.0.0.0" ),
),
)
Vous pouvez également personnaliser le client requête par requête en utilisant with_options()
:
client . with_options ( http_client = DefaultHttpxClient (...))
Par défaut, la bibliothèque ferme les connexions HTTP sous-jacentes chaque fois que le client est récupéré. Vous pouvez fermer manuellement le client à l'aide de la méthode .close()
si vous le souhaitez, ou avec un gestionnaire de contexte qui se ferme à la sortie.
Pour utiliser cette bibliothèque avec Azure OpenAI, utilisez la classe AzureOpenAI
au lieu de la classe OpenAI
.
Important
La forme de l'API Azure diffère de la forme de l'API principale, ce qui signifie que les types statiques des réponses/paramètres ne seront pas toujours corrects.
from openai import AzureOpenAI
# gets the API Key from environment variable AZURE_OPENAI_API_KEY
client = AzureOpenAI (
# https://learn.microsoft.com/azure/ai-services/openai/reference#rest-api-versioning
api_version = "2023-07-01-preview" ,
# https://learn.microsoft.com/azure/cognitive-services/openai/how-to/create-resource?pivots=web-portal#create-a-resource
azure_endpoint = "https://example-endpoint.openai.azure.com" ,
)
completion = client . chat . completions . create (
model = "deployment-name" , # e.g. gpt-35-instant
messages = [
{
"role" : "user" ,
"content" : "How do I output all files in a directory using Python?" ,
},
],
)
print ( completion . to_json ())
En plus des options fournies dans le client OpenAI
de base, les options suivantes sont proposées :
azure_endpoint
(ou la variable d'environnement AZURE_OPENAI_ENDPOINT
)azure_deployment
api_version
(ou la variable d'environnement OPENAI_API_VERSION
)azure_ad_token
(ou la variable d'environnement AZURE_OPENAI_AD_TOKEN
)azure_ad_token_provider
Un exemple d'utilisation du client avec Microsoft Entra ID (anciennement connu sous le nom d'Azure Active Directory) peut être trouvé ici.
Ce package suit généralement les conventions SemVer, bien que certaines modifications rétrocompatibles puissent être publiées sous forme de versions mineures :
Nous prenons la compatibilité ascendante au sérieux et travaillons dur pour garantir que vous puissiez compter sur une expérience de mise à niveau fluide.
Nous sommes impatients de recevoir vos commentaires ; veuillez ouvrir un problème avec des questions, des bugs ou des suggestions.
Si vous avez effectué la mise à niveau vers la dernière version mais que vous ne voyez aucune nouvelle fonctionnalité que vous attendiez, votre environnement Python utilise probablement encore une ancienne version.
Vous pouvez déterminer la version utilisée au moment de l'exécution avec :
import openai
print ( openai . __version__ )
Python 3.8 ou supérieur.
Voir la documentation contributive.