+190 XP

L'API : vos premiers vrais appels

Le moyen le plus rapide de dépasser la fenêtre ChatGPT, c'est de faire répondre le même modèle depuis votre propre code, et avec OpenAI cela prend une dizaine de lignes. Cette leçon porte sur ces dix lignes : ce qui est spécifique à OpenAI, pourquoi la Responses API est désormais le choix par défaut, et comment streamer les tokens à mesure qu'ils arrivent.

Une configuration unique, puis on oublie

Récupérez une clé sur la page des clés API. Traitez-la comme un mot de passe : elle est liée à la facturation, et quiconque la détient peut dépenser vos crédits. Ne la collez jamais dans du code et ne la committez jamais dans git.

Définissez-la comme variable d'environnement pour que le SDK la trouve automatiquement :

bash
export OPENAI_API_KEY="sk-proj-..."
pip install openai

Le SDK Python officiel lit OPENAI_API_KEY tout seul, vous n'écrivez donc jamais la clé dans votre script. Une frontière importante : votre compte API et votre abonnement ChatGPT sont distincts. ChatGPT Plus ou Pro ne vous donne pas de crédits API, et l'usage de l'API est facturé au token sur un solde différent. Ils partagent les modèles, pas le porte-monnaie.

Votre premier vrai appel

Voici un script complet et exécutable utilisant la Responses API, l'interface principale actuelle d'OpenAI :

python
from openai import OpenAI

client = OpenAI()

response = client.responses.create(
    model="gpt-4.1-mini",
    instructions="You are a terse assistant. Answer in one sentence.",
    input="Explain what an idempotent API request is.",
)

print(response.output_text)

Exécutez-le et vous obtenez une seule phrase, nette. Décortiquons maintenant les éléments spécifiques à OpenAI.

client = OpenAI()

Cela construit le client et récupère silencieusement votre clé d'environnement. Tout ce que vous faites passe par cet objet : génération de texte, embeddings, fichiers, audio. Vous le configurez une fois.

model="gpt-4.1-mini"

La chaîne de modèle est un vrai choix, facturable, pas une étiquette. OpenAI propose plusieurs familles : la ligne GPT-4.1 pour le travail généraliste, les variantes plus petites mini et nano pour des appels moins chers et plus rapides, et les modèles de raisonnement (la série o, comme o4-mini) qui réfléchissent plus longtemps avant de répondre. Choisissez selon la tâche. Un classifieur ou un formateur veut mini ou nano. Une tâche de planification multi-étapes veut un modèle de raisonnement. Vérifiez la liste et les tarifs en cours sur la page des modèles, car la gamme bouge.

instructions vs input

C'est l'amélioration la plus nette qu'apporte la Responses API. instructions est le pilotage au niveau système (persona, règles, format de sortie). input est le tour utilisateur proprement dit. Vous ne construisez plus à la main une liste de dictionnaires de messages étiquetés par rôle pour les appels simples. Pour un échange unique, deux chaînes suffisent.

response.output_text

Un accesseur de confort qui aplatit la réponse en une chaîne de texte finale. L'objet response complet en contient davantage : consommation de tokens, modèle qui vous a réellement servi, appels d'outils et blocs de contenu structurés. Pour du travail rapide, output_text est ce qu'il vous faut ; en production, vous lirez les champs plus riches.

Responses ou chat completions ?

Vous verrez les deux dans les tutoriels, autant connaître la différence.

Chat Completions (client.chat.completions.create) est l'interface plus ancienne, largement recopiée. Elle prend une liste messages de dicts {"role": ..., "content": ...}. Elle fonctionne toujours et n'est pas dépréciée, le code existant est donc sûr.

Responses (client.responses.create) est ce qu'OpenAI recommande désormais pour les nouveaux projets. Elle se prête au mode stateful, embarque des outils intégrés (web search, file search, code interpreter) que vous activez sans les câbler vous-même, et elle gère plus proprement l'usage d'outils en plusieurs étapes. La documentation de la Responses API est la référence canonique.

Règle simple : nouveau code, commencez avec Responses. Ne revenez à Chat Completions que si vous étendez quelque chose qui l'utilise déjà.

Streaming : les tokens à mesure qu'ils arrivent

Attendre qu'une longue réponse soit entièrement générée avant d'afficher quoi que ce soit donne aux utilisateurs l'impression d'un bug. Le streaming envoie les tokens au fur et à mesure que le modèle les produit, exactement l'effet machine à écrire que vous voyez dans ChatGPT.

Vous l'activez avec stream=True et vous itérez sur les événements :

python
from openai import OpenAI

client = OpenAI()

stream = client.responses.create(
    model="gpt-4.1-mini",
    input="Write a two-line haiku about slow APIs.",
    stream=True,
)

for event in stream:
    if event.type == "response.output_text.delta":
        print(event.delta, end="", flush=True)
print()

Le stream renvoie des événements typés, pas seulement du texte brut. Vous filtrez sur response.output_text.delta pour attraper les fragments de texte incrémentaux. D'autres types d'événements signalent le démarrage de la réponse, l'appel d'un outil et la fin de la génération. Le flush=True force chaque fragment vers le terminal immédiatement au lieu de le mettre en tampon.

Le streaming ne change rien au coût ni au résultat final. Il change seulement *quand* vous voyez les octets. Utilisez-le pour toute interface visible par l'utilisateur ; évitez-le pour les traitements batch que personne ne regarde.

Trois spécificités OpenAI à connaître tôt

Structured Outputs

Quand vous avez besoin que le modèle renvoie des données que votre code peut parser, ne le suppliez pas de produire du JSON dans le prompt en espérant que ça marche. Utilisez les Structured Outputs, qui forcent la réponse à respecter un schéma que vous définissez. Vous passez un JSON Schema (ou un modèle Pydantic en Python) et OpenAI garantit la forme, vous n'écrirez donc plus jamais de parsing défensif pour une clôture markdown égarée.

python
from pydantic import BaseModel
from openai import OpenAI

client = OpenAI()

class Ticket(BaseModel):
    priority: str
    summary: str

response = client.responses.parse(
    model="gpt-4.1-mini",
    input="My checkout button has been broken for two days, losing sales.",
    text_format=Ticket,
)

ticket = response.output_parsed
print(ticket.priority, "|", ticket.summary)

response.output_parsed vous remet un objet Ticket typé. C'est le plus gros gain de fiabilité pour quiconque construit de vraies fonctionnalités. Le guide Structured Outputs couvre les règles de schéma.

Function calling

Le modèle peut décider d'appeler des fonctions que vous exposez, en renvoyant le nom de la fonction et les arguments pour que vous l'exécutiez. Vous décrivez vos fonctions, le modèle en choisit une quand c'est pertinent, vous l'exécutez, puis vous lui renvoyez le résultat. C'est la primitive sous les assistants utilisateurs d'outils. Notez la frontière : le function calling de l'API n'est pas la même chose que les GPT Actions des Custom GPTs. Les Actions sont la version no-code à l'intérieur du produit ChatGPT ; le function calling est le mécanisme brut que vous contrôlez dans le code.

OpenAI Function Calling Explained

Watch on YouTube

Le SDK agents

Quand un appel de fonction devient une boucle de planification, d'appels d'outils et de vérification des résultats, vous passez à l'Agents SDK. C'est le framework officiel d'OpenAI pour les agents multi-étapes : il gère la boucle d'appels d'outils, les handoffs entre agents spécialisés et les guardrails, pour que vous n'écriviez pas l'orchestration à la main. Vous n'en avez pas besoin pour vos premiers appels, mais c'est l'étape suivante naturelle dès qu'un seul appel Responses ne suffit plus. Il s'appuie directement sur la Responses API.

Vérification des acquis

1. Pourquoi définir votre clé OpenAI comme variable d'environnement plutôt que de l'écrire directement dans votre script ?

2. Un collègue affirme que son abonnement ChatGPT Plus devrait couvrir son usage de l'API. Quelle est la bonne clarification ?

3. Vous devez construire un classifieur de texte rapide et peu coûteux qui se contente d'étiqueter les messages entrants. Quel choix de modèle convient le mieux ?

CHOIX MULTIPLES

4. Sélectionnez TOUTES les affirmations correctes sur la Responses API et le client OpenAI telles que décrites dans la leçon.

Sélectionnez toutes les réponses correctes.

CHOIX MULTIPLES

5. Sélectionnez TOUTES les affirmations correctes sur la distinction entre « instructions » et « input » dans la Responses API.

Sélectionnez toutes les réponses correctes.

Lire correctement l'objet response

Pour tout ce qui dépasse la démo, arrêtez d'afficher output_text et commencez à inspecter l'objet entier. Deux champs comptent immédiatement.

Usage. Chaque réponse rapporte des décomptes de tokens :

python
print(response.usage.input_tokens, response.usage.output_tokens)

C'est ainsi que vous mesurez le coût. Les tokens d'entrée (votre prompt et vos instructions) et les tokens de sortie (la génération) sont tarifés différemment, et la sortie est généralement le côté le plus cher. Logguer l'usage dès le premier jour vous évite une facture surprise plus tard.

Le modèle servi. Le champ model vous dit quelle version exacte du modèle a répondu. Lorsque vous épinglez un snapshot daté plutôt qu'un alias qui se met à jour automatiquement, c'est ce champ qui vous confirme ce qui a tourné. Pour un comportement reproductible en production, épinglez un snapshot précis plutôt qu'un alias flottant.

Les erreurs que vous rencontrerez vraiment

Les vrais appels échouent pour de vraies raisons. Gérez explicitement les plus courantes :

python
from openai import OpenAI, RateLimitError, APIError

client = OpenAI()

try:
    response = client.responses.create(
        model="gpt-4.1-mini",
        input="Summarize the API economy in one line.",
    )
    print(response.output_text)
except RateLimitError:
    print("Slow down or upgrade your tier, then retry with backoff.")
except APIError as err:
    print(f"OpenAI-side issue: {err}")

RateLimitError est celle que les débutants rencontrent en premier. Les nouveaux comptes API démarrent sur un tier d'usage bas avec des limites par minute modestes ; les tiers montent automatiquement à mesure que le compte vieillit et que vous dépensez. Ne prenez pas une limite de débit pour un bug. Prenez-la comme un signal d'ajouter un retry-with-backoff, que le SDK peut faire pour vous via le réglage max_retries sur le client. APIError et ses sous-classes couvrent l'authentification, les requêtes mal formées et les erreurs serveur transitoires. Attrapez-les pour qu'un seul hoquet ne fasse pas planter votre application.

Garder latence et coût sous contrôle

Quelques habitudes rapportent tout de suite :

  • Plafonnez la sortie. Réglez max_output_tokens pour qu'un modèle bavard ne s'étale pas et ne fasse pas grimper la facture. Un résumeur a rarement besoin de plus de deux cents tokens.
  • Dimensionnez le modèle correctement. La plupart du trafic de production n'a pas besoin de votre plus gros modèle. Routez les appels simples vers un mini ou un nano et réservez les modèles lourds ou de raisonnement aux tâches qui en ont réellement besoin.
  • Streamez ce qui est visible, batchez le reste. La vitesse perçue vient du streaming ; le débit réel vient de l'envoi d'appels indépendants en parallèle plutôt que dans une boucle lente.

Ces trois leviers (plafond de sortie, choix du modèle, concurrence) couvrent l'essentiel du réglage de coût et de latence que vous ferez au début.

Points clés

  • Démarrez tout nouveau code sur la Responses API (client.responses.create) avec instructions et input ; ne gardez Chat Completions que pour les bases de code existantes.
  • Définissez `OPENAI_API_KEY` en variable d'environnement et rappelez-vous que votre solde API est distinct de tout abonnement ChatGPT.
  • Utilisez les Structured Outputs (`responses.parse` avec un modèle Pydantic) dès que vous avez besoin de données parsables, au lieu de demander du JSON en espérant.
  • Lisez `response.usage` dès le premier jour et plafonnez max_output_tokens pour que le coût reste visible et borné.
  • Streamez pour toute interface visible par l'utilisateur en filtrant les événements response.output_text.delta, et attrapez RateLimitError avec du backoff plutôt que de laisser votre application planter.

À faire, tiré de cette leçon

Ces actions sont compilées dans le plan d'action du rôle.

  • Démarrez tout nouveau code sur l'API Responses et lisez response.usage dès le premier jour
Voir le plan d'action complet →