Section 11.4.6 : API OpenAI — Configuration et appels avancés
🎯 Objectif pédagogique
Maîtriser l'API OpenAI en Python : configuration, appels chat completion, paramètres avancés, streaming, et gestion des coûts. Vous serez capable de construire des applications qui utilisent GPT-4o programmatiquement.
De ChatGPT à l'API — Le passage au code
Marc a utilisé ChatGPT via l'interface. Maintenant il va utiliser l'API : appeler GPT-4o directement depuis son code Python. C'est la différence entre utiliser une calculatrice et intégrer un moteur de calcul dans son application.
Configuration
# Installation
# pip install openai python-dotenv
# .env (NE JAMAIS commit ce fichier !)
# OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxx
import os
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
Appel basique — Chat Completion
def ask_gpt(prompt, system_prompt="Tu es un assistant utile.", model="gpt-4o-mini"):
"""Appel simple à l'API OpenAI."""
response = client.chat.completions.create(
model=model,
messages=[
\{"role": "system", "content": system_prompt\},
\{"role": "user", "content": prompt\}
],
temperature=0.7,
max_tokens=1000
)
return response.choices[0].message.content
# Utilisation
result = ask_gpt("Quelles sont les 3 compétences clés pour un Data Analyst en 2025 ?")
print(result)
Paramètres avancés
response = client.chat.completions.create(
model="gpt-4o",
messages=[...],
# Contrôle de la créativité
temperature=0.3, # 0=déterministe, 2=très créatif
top_p=0.9, # Alternative à temperature (nucleus sampling)
# Limites
max_tokens=2000, # Longueur max de la réponse
# Format
response_format=\{"type": "json_object"\}, # Force le JSON
# Divers
seed=42, # Reproductibilité (même seed = même réponse)
n=1, # Nombre de réponses à générer
stop=["\n\n---"], # Tokens d'arrêt
)
# Informations sur l'utilisation
usage = response.usage
print(f"Prompt tokens: \{usage.prompt_tokens\}")
print(f"Completion tokens: \{usage.completion_tokens\}")
print(f"Total tokens: \{usage.total_tokens\}")
print(f"Coût estimé: $\{usage.total_tokens / 1_000_000 * 0.15:.4f\}") # gpt-4o-mini pricing
Conversations multi-tours
class Conversation:
"""Gère une conversation avec mémoire."""
def __init__(self, system_prompt, model="gpt-4o-mini"):
self.model = model
self.messages = [\{"role": "system", "content": system_prompt\}]
def ask(self, user_message):
"""Envoyer un message et obtenir la réponse."""
self.messages.append(\{"role": "user", "content": user_message\})
response = client.chat.completions.create(
model=self.model,
messages=self.messages,
temperature=0.7
)
assistant_message = response.choices[0].message.content
self.messages.append(\{"role": "assistant", "content": assistant_message\})
return assistant_message
def get_history(self):
"""Retourne l'historique de la conversation."""
return self.messages
# Utilisation
convo = Conversation("Tu es un coach de carrière spécialisé en reconversion tech.")
print(convo.ask("Je viens de la finance et je veux devenir Data Analyst."))
print(convo.ask("Quelles formations recommandes-tu ?"))
print(convo.ask("Comment préparer mon CV pour cette transition ?"))
Streaming — Réponse en temps réel
def stream_response(prompt, system_prompt="Tu es un assistant utile."):
"""Streamer la réponse token par token."""
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
\{"role": "system", "content": system_prompt\},
\{"role": "user", "content": prompt\}
],
stream=True
)
full_response = ""
for chunk in stream:
content = chunk.choices[0].delta.content
if content:
print(content, end="", flush=True)
full_response += content
print() # Nouvelle ligne à la fin
return full_response
# L'utilisateur voit la réponse apparaître progressivement
stream_response("Explique le machine learning en 5 bullet points.")
Forcer le format JSON (Structured Output)
def analyze_job_offer(offer_text):
"""Analyser une offre d'emploi et retourner du JSON structuré."""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
\{"role": "system", "content": """Tu es un analyste d'offres d'emploi.
Réponds TOUJOURS en JSON valide avec cette structure exacte :
\{
"position": string,
"company": string,
"location": string,
"salary": string ou null,
"skills_required": string[],
"match_score": number (1-5),
"pros": string[],
"cons": string[],
"recommendation": "POSTULER" | "PASSER" | "PEUT-ÊTRE"
\}"""\},
\{"role": "user", "content": f"Analyse cette offre pour Marc (profil: Data/Python/Finance):\n\{offer_text\}"\}
],
response_format=\{"type": "json_object"\},
temperature=0.3
)
import json
return json.loads(response.choices[0].message.content)
# Utilisation
result = analyze_job_offer("""
Data Analyst — Paris — CDI
Entreprise : FinTech Leaders (50-100 employés)
Salaire : 45-55K€ + intéressement
Requis : Python, SQL, Tableau, Excel
Bonus : Expérience finance, ML basics
""")
print(json.dumps(result, indent=2, ensure_ascii=False))
Sécurité des clés API
JAMAIS de clé API dans le code source ou sur GitHub. Utilisez des variables d'environnement (.env + python-dotenv). Ajoutez .env à votre .gitignore. OpenAI facture par token — une clé exposée peut coûter des milliers d'euros.
🏋️ Exercice pratique (30 minutes)
- →Créez un compte OpenAI et générez une clé API
- →Écrivez un script qui analyse 3 offres d'emploi en JSON structuré
- →Implémentez une conversation multi-tours (coach carrière)
- →Testez le streaming et comparez l'expérience utilisateur
- →Calculez le coût de vos appels (tokens utilisés × prix)
Pourquoi utiliser response_format={'type': 'json_object'} dans l'API OpenAI ?
Quelle est la différence entre temperature=0 et temperature=1.5 ?