La biblioteca OpenAI Python proporciona un acceso conveniente a la API REST de OpenAI desde cualquier aplicación Python 3.8+. La biblioteca incluye definiciones de tipos para todos los parámetros de solicitud y campos de respuesta, y ofrece clientes sincrónicos y asincrónicos con tecnología httpx.
Se genera a partir de nuestra especificación OpenAPI con Inoxidable.
La documentación de la API REST se puede encontrar en platform.openai.com. La API completa de esta biblioteca se puede encontrar en api.md.
Importante
El SDK se reescribió en la versión 1, que se lanzó el 6 de noviembre de 2023. Consulte la guía de migración de la versión 1, que incluye secuencias de comandos para actualizar automáticamente su código.
# install from PyPI
pip install openai
La API completa de esta biblioteca se puede encontrar en 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" ,
)
Si bien puede proporcionar un argumento de palabra clave api_key
, recomendamos usar python-dotenv para agregar OPENAI_API_KEY="My API Key"
a su archivo .env
para que su clave API no se almacene en el control de código fuente.
Con una imagen alojada:
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 } " },
},
],
}
],
)
Con la imagen como una cadena codificada 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 } " },
},
],
}
],
)
Al interactuar con la API, algunas acciones, como iniciar una ejecución y agregar archivos a almacenes de vectores, son asincrónicas y tardan en completarse. El SDK incluye funciones auxiliares que sondearán el estado hasta que alcance un estado terminal y luego devolverán el objeto resultante. Si un método API da como resultado una acción que podría beneficiarse del sondeo, habrá una versión correspondiente del método que terminará en '_and_poll'.
Por ejemplo, para crear una ejecución y sondear hasta que alcance un estado terminal, puede ejecutar:
run = client . beta . threads . runs . create_and_poll (
thread_id = thread . id ,
assistant_id = assistant . id ,
)
Puede encontrar más información sobre el ciclo de vida de una ejecución en la documentación del ciclo de vida de la ejecución.
Al crear e interactuar con almacenes de vectores, puede utilizar asistentes de sondeo para monitorear el estado de las operaciones. Para mayor comodidad, también proporcionamos un asistente de carga masiva que le permite cargar varios archivos simultáneamente.
sample_files = [ Path ( "sample-paper.pdf" ), ...]
batch = await client . vector_stores . file_batches . upload_and_poll (
store . id ,
files = sample_files ,
)
El SDK también incluye ayudas para procesar transmisiones y manejar eventos entrantes.
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 )
Puede encontrar más información sobre los asistentes de transmisión en la documentación dedicada: helpers.md
Simplemente importe AsyncOpenAI
en lugar de OpenAI
y use await
con cada llamada a la 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 ())
Por lo demás, la funcionalidad entre los clientes síncronos y asíncronos es idéntica.
Brindamos soporte para la transmisión de respuestas mediante eventos del lado del servidor (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 = "" )
El cliente asíncrono utiliza exactamente la misma interfaz.
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 ())
Importante
Recomendamos encarecidamente crear instancias de clientes en lugar de depender del cliente global.
También exponemos una instancia de cliente global a la que se puede acceder de manera similar a las versiones anteriores a 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 )
La API es exactamente la misma que la API estándar basada en instancias de cliente.
Está pensado para usarse dentro de REPL o cuadernos para una iteración más rápida, no en el código de la aplicación.
Le recomendamos que siempre cree una instancia de un cliente (por ejemplo, con client = OpenAI()
) en el código de la aplicación porque:
Los parámetros de solicitud anidados son TypedDicts. Las respuestas son modelos Pydantic que también proporcionan métodos auxiliares para cosas como:
model.to_json()
model.to_dict()
Las solicitudes y respuestas escritas proporcionan autocompletar y documentación dentro de su editor. Si desea ver errores de tipo en VS Code para ayudar a detectar errores antes, configure python.analysis.typeCheckingMode
en basic
.
Los métodos de lista en la API de OpenAI están paginados.
Esta biblioteca proporciona iteradores de paginación automática con cada respuesta de lista, por lo que no es necesario solicitar páginas sucesivas manualmente:
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 )
O, de forma asincrónica:
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 ())
Alternativamente, puede usar los métodos .has_next_page()
, .next_page_info()
o .get_next_page()
para un control más granular al trabajar con páginas:
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.
O simplemente trabaje directamente con los datos devueltos:
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.
Los parámetros anidados son diccionarios, escritos usando TypedDict
, por ejemplo:
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" },
)
Los parámetros de solicitud que corresponden a la carga de archivos se pueden pasar como bytes
, una instancia PathLike
o una tupla 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" ,
)
El cliente asíncrono utiliza exactamente la misma interfaz. Si pasa una instancia PathLike
, el contenido del archivo se leerá de forma asincrónica y automática.
Cuando la biblioteca no puede conectarse a la API (por ejemplo, debido a problemas de conexión de red o un tiempo de espera), se genera una subclase de openai.APIConnectionError
.
Cuando la API devuelve un código de estado no exitoso (es decir, respuesta 4xx o 5xx), se genera una subclase de openai.APIStatusError
, que contiene status_code
y propiedades response
.
Todos los errores heredan 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 )
Los códigos de error son los siguientes:
Código de estado | Tipo de error |
---|---|
400 | BadRequestError |
401 | AuthenticationError |
403 | PermissionDeniedError |
404 | NotFoundError |
422 | UnprocessableEntityError |
429 | RateLimitError |
>=500 | InternalServerError |
N / A | APIConnectionError |
Para obtener más información sobre las solicitudes de depuración, consulte estos documentos
Todas las respuestas de objetos en el SDK proporcionan una propiedad _request_id
que se agrega desde el encabezado de respuesta x-request-id
para que pueda registrar rápidamente las solicitudes fallidas e informarlas a 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
Tenga en cuenta que, a diferencia de otras propiedades que utilizan un prefijo _
, la propiedad _request_id
es pública. A menos que se documente lo contrario, todas las demás propiedades, métodos y módulos del prefijo _
son privados .
Ciertos errores se reintentan automáticamente 2 veces de forma predeterminada, con un breve retroceso exponencial. Los errores de conexión (por ejemplo, debido a un problema de conectividad de red), 408 Tiempo de espera de solicitud, 409 Conflicto, 429 Límite de velocidad y >=500 errores internos se reintentan de forma predeterminada.
Puede utilizar la opción max_retries
para configurar o deshabilitar la configuración de reintento:
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" ,
)
De forma predeterminada, las solicitudes expiran después de 10 minutos. Puedes configurar esto con una opción timeout
, que acepta un objeto flotante o 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" ,
)
Cuando se agota el tiempo de espera, se genera un APITimeoutError
.
Tenga en cuenta que las solicitudes cuyo tiempo de espera se agota se reintentan dos veces de forma predeterminada.
Usamos el módulo logging
de biblioteca estándar.
Puede habilitar el registro configurando la variable de entorno OPENAI_LOG
en info
.
$ export OPENAI_LOG=info
O para debug
para un registro más detallado.
None
significa null
o falta En una respuesta de API, un campo puede ser explícitamente null
o faltar por completo; en cualquier caso, su valor es None
en esta biblioteca. Puedes diferenciar los dos casos con .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}.' )
Se puede acceder al objeto de respuesta "sin procesar" anteponiendo el prefijo .with_raw_response.
a cualquier llamada a un método HTTP, por ejemplo,
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 )
Estos métodos devuelven un objeto LegacyAPIResponse
. Esta es una clase heredada ya que la cambiaremos ligeramente en la próxima versión principal.
Para el cliente de sincronización, esto será prácticamente igual con la excepción de que content
y text
serán métodos en lugar de propiedades. En el cliente asíncrono, todos los métodos serán asíncronos.
Se proporcionará un script de migración y la migración en general debería ser fluida.
.with_streaming_response
La interfaz anterior lee con entusiasmo el cuerpo completo de la respuesta cuando realiza la solicitud, que puede no siempre ser lo que desea.
Para transmitir el cuerpo de la respuesta, use .with_streaming_response
en su lugar, lo que requiere un administrador de contexto y solo lee el cuerpo de la respuesta una vez que llama a .read()
, .text()
, .json()
, .iter_bytes()
, .iter_text()
, .iter_lines()
o .parse()
. En el cliente asíncrono, estos son métodos asíncronos.
Como tal, los métodos .with_streaming_response
devuelven un objeto APIResponse
diferente y el cliente asíncrono devuelve un objeto 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 )
El administrador de contexto es necesario para que la respuesta se cierre de manera confiable.
Esta biblioteca está escrita para facilitar el acceso a la API documentada.
Si necesita acceder a puntos finales, parámetros o propiedades de respuesta no documentados, aún puede utilizar la biblioteca.
Para realizar solicitudes a puntos finales no documentados, puede realizar solicitudes utilizando client.get
, client.post
y otros verbos http. Se respetarán las opciones del cliente (como los reintentos) al realizar esta solicitud.
import httpx
response = client . post (
"/foo" ,
cast_to = httpx . Response ,
body = { "my_param" : True },
)
print ( response . headers . get ( "x-foo" ))
Si desea enviar explícitamente un parámetro adicional, puede hacerlo con las opciones de solicitud extra_query
, extra_body
y extra_headers
.
Para acceder a propiedades de respuesta no documentadas, puede acceder a campos adicionales como response.unknown_prop
. También puede obtener todos los campos adicionales en el modelo de Pydantic como un diccionario con response.model_extra
.
Puede anular directamente el cliente httpx para personalizarlo según su caso de uso, incluido:
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" ),
),
)
También puede personalizar el cliente por solicitud utilizando with_options()
:
client . with_options ( http_client = DefaultHttpxClient (...))
De forma predeterminada, la biblioteca cierra las conexiones HTTP subyacentes cada vez que se recolecta basura del cliente. Puede cerrar manualmente el cliente usando el método .close()
si lo desea, o con un administrador de contexto que se cierra al salir.
Para usar esta biblioteca con Azure OpenAI, use la clase AzureOpenAI
en lugar de la clase OpenAI
.
Importante
La forma de la API de Azure difiere de la forma de la API principal, lo que significa que los tipos estáticos para respuestas/parámetros no siempre serán correctos.
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 ())
Además de las opciones proporcionadas en el cliente OpenAI
base, se proporcionan las siguientes opciones:
azure_endpoint
(o la variable de entorno AZURE_OPENAI_ENDPOINT
)azure_deployment
api_version
(o la variable de entorno OPENAI_API_VERSION
)azure_ad_token
(o la variable de entorno AZURE_OPENAI_AD_TOKEN
)azure_ad_token_provider
Puede encontrar un ejemplo del uso del cliente con Microsoft Entra ID (anteriormente conocido como Azure Active Directory) aquí.
Este paquete generalmente sigue las convenciones de SemVer, aunque ciertos cambios incompatibles con versiones anteriores pueden publicarse como versiones menores:
Nos tomamos muy en serio la compatibilidad con versiones anteriores y trabajamos arduamente para garantizar que pueda confiar en una experiencia de actualización fluida.
Estamos interesados en recibir sus comentarios; abra un problema con preguntas, errores o sugerencias.
Si actualizó a la última versión pero no ve ninguna característica nueva que esperaba, entonces es probable que su entorno Python todavía esté usando una versión anterior.
Puede determinar la versión que se utiliza en tiempo de ejecución con:
import openai
print ( openai . __version__ )
Python 3.8 o superior.
Consulte la documentación contribuyente.