# Parameters
BATCH_MODE = "true"8. Reasoning Models
# Parameters
BATCH_MODE = "true"Modèles de Raisonnement : gpt-5-mini
Navigation : Index | << Précédent | Suivant >>
Les modèles de raisonnement représentent une évolution majeure des LLMs. Ils s’appuient sur le chain-of-thought (Wei et al., 2022) – démontrer le raisonnement étape par étape améliore la précision – et sur l’idée que l’on peut échanger du temps de calcul contre de la qualité (Snell et al., 2024). La sortie des modèles de type o1 (OpenAI, 2024, Learning to Reason with LLMs) a institutionnalisé ce paradigme : le modèle produit un raisonnement interne (caché) avant de répondre. Contrairement aux modèles de chat classiques, ils prennent le temps de “réfléchir” avant de répondre, ce qui améliore significativement leurs performances sur les tâches complexes.
Objectifs : - Comprendre les différences architecturales (thinking time) - Maîtriser reasoning_effort (low, medium, high) - Choisir le bon modèle selon la tâche - Analyser les performances et coûts
Prérequis : Notebook 2 (Prompt Engineering)
Durée estimée : 60 minutes
from pathlib import Path
%pip install openai python-dotenv --quiet
import os
import time
from openai import OpenAI
from dotenv import load_dotenv
# Chargement robuste de la configuration .env
# Recherche du .env dans tous les parents (pour Papermill qui change le cwd)
current_path = Path.cwd()
env_loaded = False
for _ in range(10):
env_path = current_path / ".env"
if env_path.exists():
load_dotenv(env_path)
print(f".env charge depuis: {env_path.name}")
env_loaded = True
break
if current_path.name == "GenAI" or len(current_path.parts) <= 1:
break
current_path = current_path.parent
if not env_loaded:
print("WARNING: .env non trouve, utilisation variables environnement")
# Configuration OpenRouter pour acces aux modeles gpt-5-x
client = OpenAI(
api_key=os.getenv("OPENROUTER_API_KEY"),
base_url=os.getenv("OPENROUTER_BASE_URL", "https://openrouter.ai/api/v1")
)
# Modeles disponibles via OpenRouter
DEFAULT_CHAT_MODEL = os.getenv("OPENAI_MODEL", "openai/gpt-5-mini")
DEFAULT_REASONING_MODEL = "openai/gpt-5-mini"
BATCH_MODE = os.getenv("BATCH_MODE", "false").lower() == "true"
print("Client OpenRouter initialise !")
print(f"Modele chat par defaut: {DEFAULT_CHAT_MODEL}")
print(f"Modele reasoning par defaut: {DEFAULT_REASONING_MODEL}")
print(f"Mode: {'BATCH' if BATCH_MODE else 'INTERACTIF'}")Note: you may need to restart the kernel to use updated packages.
.env charge depuis: .env
Client OpenRouter initialise !
Modele chat par defaut: openai/gpt-5-mini
Modele reasoning par defaut: openai/gpt-5-mini
Mode: INTERACTIF
0. Configuration de l’environnement
Imports nécessaires
Ce notebook utilise : - openai : Bibliothèque officielle OpenAI pour interagir avec l’API - python-dotenv : Chargement des variables d’environnement (clés API) - time : Mesure des temps de réponse pour comparaison
Structure du notebook
Nous allons explorer progressivement : 1. Comparaison chat vs reasoning models 2. Paramètre reasoning_effort (low/medium/high) 3. Messages developer et formatage 4. Génération de code complexe 5. Modèles avancés et benchmarks 6. Analyse coût/performance
Mode batch : Si BATCH_MODE=true dans .env, le notebook s’exécute sans interaction utilisateur (utile pour tests automatisés).
1. Chat Models vs Reasoning Models
Ancrage scholarly. Les reasoning models (OpenAI, 2024 – Learning to Reason with LLMs, série o1) matérialisent à l’échelle industrielle le chain-of-thought (Wei et al., 2022) : le modèle génère un raisonnement intermédiaire (tokens de réflexion, souvent masqués dans l’API) avant la réponse finale. Le compromis “temps de réflexion <-> qualité” est formalisé par Snell et al. (2024) – d’où le paramètre
reasoning_effortutilisé ci-dessous.
Différences fondamentales
| Aspect | Chat Models | Reasoning Models |
|---|---|---|
| Réponse | Immédiate | Temps de réflexion |
| Optimisation | Dialogue fluide | Problèmes complexes |
| Exemples | gpt-5-mini, gpt-5-pro | gpt-5-mini avec reasoning_effort |
| Vitesse | Rapide (1-3s) | Variable (5-30s+) |
| Précision | Bonne | Excellente sur tâches complexes |
Quand utiliser quoi ?
Chat Models : - Conversations naturelles - Questions factuelles simples - Génération de contenu créatif - Traduction, résumé
Reasoning Models : - Mathématiques et logique - Programmation complexe - Analyse multi-étapes - Problèmes d’optimisation - Déduction et inférence
Note importante : Dans ce notebook, nous utilisons le même modèle (gpt-5-mini) pour les deux approches. La différence est l’utilisation du paramètre
reasoning_effortpour activer le mode raisonnement.
probleme_math = """
Alice a 54 pommes. Elle en donne la moitié à Bob.
Bob mange 13 pommes puis rend le reste à Alice.
Alice achète ensuite 33 pommes de plus.
Combien de pommes Alice a-t-elle maintenant?
Donne uniquement le nombre final.
"""
# Fonction helper pour extraire le contenu en toute sécurité
def get_content(response):
"""Extrait le contenu de manière sécurisée, gère les réponses None."""
content = response.choices[0].message.content
if content is None:
# Essayer de récupérer le reasoning si disponible
if hasattr(response.choices[0].message, 'reasoning') and response.choices[0].message.reasoning:
return f"[Reasoning only] {response.choices[0].message.reasoning[:200]}..."
return "[Response content is null - try increasing max_tokens]"
return content.strip()
# Test avec un chat model (gpt-5-mini via OpenRouter)
start = time.time()
response_chat = client.chat.completions.create(
model=DEFAULT_CHAT_MODEL,
messages=[{"role": "user", "content": probleme_math}],
max_completion_tokens=4000, # Augmenté pour éviter content null
)
time_chat = time.time() - start
# Test avec un reasoning model (gpt-5-mini avec reasoning_effort via OpenRouter)
start = time.time()
try:
response_reasoning = client.chat.completions.create(
model=DEFAULT_REASONING_MODEL,
messages=[
{"role": "user", "content": probleme_math}
],
max_completion_tokens=4000, # Augmenté pour éviter content null
extra_body={"reasoning_effort": "medium"}
)
time_reasoning = time.time() - start
reasoning_available = True
except Exception as e:
print(f"Reasoning model non disponible: {type(e).__name__}: {str(e)[:100]}")
print("Utilisation du chat model comme fallback.")
response_reasoning = response_chat
time_reasoning = time_chat
reasoning_available = False
print("=== Comparaison Chat vs Reasoning ===")
print(f"\n{DEFAULT_CHAT_MODEL} ({time_chat:.2f}s):")
print(f" Réponse: {get_content(response_chat)}")
if reasoning_available:
print(f"\n{DEFAULT_REASONING_MODEL} avec reasoning_effort ({time_reasoning:.2f}s):")
print(f" Réponse: {get_content(response_reasoning)}")
print(f"\n[Réponse correcte: 74 pommes (Alice donne 27, récupère 14, achète 33 → 54 - 27 + 14 + 33 = 74)]")
if reasoning_available:
print(f"\nNote: Le reasoning model analyse pas à pas, le chat model répond directement.")=== Comparaison Chat vs Reasoning ===
openai/gpt-5-mini (4.93s):
Réponse: 74
openai/gpt-5-mini avec reasoning_effort (4.82s):
Réponse: 74
[Réponse correcte: 74 pommes (Alice donne 27, récupère 14, achète 33 → 54 - 27 + 14 + 33 = 74)]
Note: Le reasoning model analyse pas à pas, le chat model répond directement.
Interprétation des résultats
Dans cet exemple, les deux modèles ont donné la bonne réponse (74 pommes), mais observez :
Temps de réponse : - gpt-5-mini (chat mode) : (s live – regle #9434) - gpt-5-mini (reasoning mode) : (s live – regle #9434) (sur cette exécution, plus rapide que le mode chat)
Précision : - Sur ce problème simple, les deux modes réussissent - La différence devient significative sur des problèmes plus complexes nécessitant plusieurs étapes de raisonnement
Quand la différence compte : - Problèmes avec plusieurs contraintes simultanées - Calculs nécessitant de garder plusieurs valeurs en mémoire - Raisonnement nécessitant de tester plusieurs hypothèses
Trade-off : Le mode raisonnement peut ajouter un temps de réflexion (et donc de la latence) en échange d’une meilleure garantie de précision sur les problèmes complexes. L’écart de latence varie selon la charge du service — ici il était négligeable. À vous de choisir selon vos besoins !
Note technique : Ici, nous utilisons le même modèle (gpt-5-mini) dans deux modes différents. Le mode chat est le mode par défaut (rapide), tandis que le mode reasoning active le paramètre
reasoning_effortpour une analyse plus approfondie.
Analyse des résultats par niveau
Observations importantes :
- Tous les niveaux donnent la bonne réponse sur ce problème simple
- low (~2.76s) : Raisonnement rapide, réponse correcte
- medium (~4.43s) : Équilibre réflexion/temps
- high (~5.95s) : Analyse approfondie (mais pas nécessaire ici)
- Différence de temps :
- low → medium : +60% temps
- medium → high : +34% temps
- Le surcoût augmente de façon non-linéaire
- Formulation similaire :
- Les 3 niveaux produisent des explications presque identiques
- Sur un problème simple, la différence est minime
Quand utiliser chaque niveau ?
| Niveau | Durée typique | Cas d’usage |
|---|---|---|
| low | 2-10s | Logique simple, calculs directs, questions factuelles avec raisonnement minimal |
| medium | 5-20s | Choix par défaut - équilibre optimal pour la plupart des tâches |
| high | 10-60s+ | Problèmes très complexes, optimisation multi-contraintes, preuves formelles |
Recommandation : Commencez toujours par low ou medium. N’utilisez high que si les résultats sont insuffisants.
Impact sur les coûts : Chaque niveau génère plus de tokens de réflexion cachés (facturés). Sur 1000 requêtes, la différence entre low et high peut représenter des centaines d’euros !
2. Paramètre reasoning_effort
Les modèles de raisonnement exposent un paramètre crucial : reasoning_effort. Il contrôle le budget de calcul au moment du test (test-time compute) alloué au raisonnement interne – le trade-off étudié par Snell et al. (2024), qui montrent qu’optimiser ce budget peut être plus efficace qu’agrandir le modèle.
Niveaux disponibles
| Niveau | Temps de réflexion | Qualité | Usage typique |
|---|---|---|---|
| low | Minimal (5-10s) | Bonne | Problèmes simples nécessitant un peu de réflexion |
| medium | Équilibré (10-20s) | Très bonne | Cas d’usage général |
| high | Approfondi (20-60s+) | Excellente | Problèmes très complexes |
Règles empiriques
- low : Questions de logique simple, calculs directs
- medium : Programmation standard, analyses multi-étapes
- high : Optimisation mathématique, preuve formelle, debugging complexe
Note importante : Plus de réflexion = plus de coût en tokens. Choisissez judicieusement !
probleme_logique = """
Dans une course, tu dépasses le 2ème.
Quelle est ta position finale?
Explique ton raisonnement en une phrase.
"""
def get_content_safe(response):
"""Extrait le contenu de manière sécurisée."""
if response is None:
return "[Response is None]"
if not hasattr(response, 'choices') or response.choices is None:
return "[Response has no choices]"
if len(response.choices) == 0:
return "[Empty choices array]"
if response.choices[0] is None:
return "[First choice is None]"
if not hasattr(response.choices[0], 'message'):
return "[Choice has no message]"
content = response.choices[0].message.content
if content is None:
return "[Content null - response truncated or reasoning-only]"
return content.strip()
print("=== Impact du reasoning_effort ===\n")
# gpt-5-mini avec reasoning_effort via OpenRouter
for effort in ["low", "medium", "high"]:
start = time.time()
try:
response = client.chat.completions.create(
model=DEFAULT_REASONING_MODEL,
messages=[
{"role": "developer", "content": "Formatting re-enabled"},
{"role": "user", "content": probleme_logique}
],
max_completion_tokens=4000, # Augmenté pour éviter content null
extra_body={"reasoning_effort": effort}
)
duration = time.time() - start
print(f"reasoning_effort='{effort}' ({duration:.2f}s):")
print(f" {get_content_safe(response)}")
print()
except Exception as e:
print(f"reasoning_effort='{effort}': Non supporté - {str(e)[:50]}")
break
print("[Réponse correcte: 2ème position - tu prends la place de celui que tu dépasses]")
print("\nObservation: Les 3 niveaux devraient donner la bonne réponse, mais 'high' peut fournir")
print("une explication plus détaillée. La différence est surtout visible sur des problèmes complexes.")=== Impact du reasoning_effort ===
reasoning_effort='low' (2.91s):
Tu es 2ᵉ : en dépassant la personne qui était 2ᵉ tu prends sa place, donc tu deviens la deuxième.
reasoning_effort='medium' (6.52s):
Tu es deuxième : en dépassant le concurrent qui était 2ᵉ, tu prends sa place.
reasoning_effort='high' (11.89s):
Tu termines 2ᵉ, car en dépassant le coureur qui était 2ᵉ tu prends sa place.
[Réponse correcte: 2ème position - tu prends la place de celui que tu dépasses]
Observation: Les 3 niveaux devraient donner la bonne réponse, mais 'high' peut fournir
une explication plus détaillée. La différence est surtout visible sur des problèmes complexes.
Exercice 1 : Chain-of-thought manuel vs automatique
L’objectif est de comparer une resolution “directe” (sans reflexion) avec une resolution “pas a pas” (chain-of-thought) sur un problème de calcul multi-étapes, en utilisant le mode chat standard.
Indices : - # Étape 1 : Définir un problème de calcul avec 3-4 étapes (ex: prix avec taxe, remise et frais de port) - # Étape 2 : Appeler le modèle avec un prompt direct (“Donne uniquement la reponse finale”) - # Étape 3 : Appeler le modèle avec un prompt chain-of-thought (“Resous étape par étape, montre chaque calcul”) - # Étape 4 : Comparer les deux reponses avec la reponse correcte et afficher les résultats
# Exercice 1 : Chain-of-thought manuel vs automatique
# TODO etudiant : Comparer prompt direct vs prompt chain-of-thought sur un calcul multi-etapes
# - Definir un probleme : "Un article coute 80EUR. TVA 20%, puis remise 15% sur le prix TTC, puis frais de port 5EUR. Prix final?"
# - Prompt direct : "Calcule le prix final. Donne uniquement le nombre."
# - Prompt CoT : "Resous etape par etape en montrant chaque calcul intermediaire."
# - Comparer les deux reponses avec la reponse correcte (80*1.2*0.85+5 = 86.60 EUR)
direct_prompt = None # TODO etudiant : definir le prompt direct
cot_prompt = None # TODO etudiant : definir le prompt chain-of-thought
# Indice : reponse correcte = 80 * 1.20 * 0.85 + 5 = 86.60 EUR
print("Exercice a completer")Exercice a completer
Analyse de la qualité du code généré
Le modèle gpt-5-mini avec reasoning_effort='high' a produit une solution de très haute qualité :
Points forts de l’implémentation :
- Algorithme optimal : Expansion autour du centre (O(n²))
- Considère les palindromes de longueur impaire (centre sur un caractère)
- Considère les palindromes de longueur paire (centre entre deux caractères)
- Complexité théorique minimale pour approche directe
- Code propre et lisible :
- Fonction helper
expand_around_centeravec logique claire - Variables bien nommées (
start,max_len,curr_len) - Commentaires pertinents
- Fonction helper
- Tests exhaustifs :
- Chaîne vide
- Un seul caractère
- Palindrome complet
- Pas de palindrome (> 1)
- Cas ambigus (“babad” → “bab” ou “aba”)
- Robustesse :
- Gestion des cas limites (n < 2)
- Validation avec assertions
- Message de succès clair
Comparaison avec le mode chat :
Le mode chat (sans reasoning_effort) aurait probablement : - Fourni une implémentation correcte mais moins optimisée - Tests moins complets - Moins d’explications sur la complexité
Temps de génération : 17.29s est un excellent compromis pour obtenir du code de cette qualité. En développement professionnel, cela représente un gain de temps considérable.
Alternative possible : L’algorithme de Manacher (O(n)) existe mais est beaucoup plus complexe. Pour la plupart des usages, O(n²) est suffisant et plus maintenable.
3. Messages developer et contrôle du formatage
Rôle developer
Les modèles de raisonnement (gpt-5-mini avec reasoning_effort) utilisent un rôle spécial : developer.
- Remplace le rôle
systemdes chat models - Définit des instructions méta (comportement, formatage)
- Moins strict que
system, plus flexible
“Formatting re-enabled”
Par défaut, les modèles raisonnants retournent du texte brut. Pour activer le markdown (formules LaTeX, code, listes), ajoutez :
{"rôle": "developer", "content": "Formatting re-enabled"}Ceci permet : - Formules mathématiques : $E = mc^2$ - Blocs de code avec syntax highlighting - Tableaux, listes, titres markdown
Sans ce message, vous obtenez du texte brut (pas de formatage riche).
Analyse du problème d’optimisation
Le modèle a fourni une solution complète et rigoureuse :
Étapes mathématiques couvertes :
- Variables : x (profondeur perpendiculaire au mur), y (longueur le long du mur)
- Contrainte : 2x + y = 100 (le mur remplace un côté, 3 côtés à clôturer)
- Fonction objectif : A(x) = x(100 − 2x) = 100x − 2x²
- Optimisation : Dérivée A’(x) = 100 − 4x = 0 ⇒ x = 25 m
- Vérification : Dérivée seconde A’’(x) = −4 < 0 (maximum confirmé), contrôle des bornes (A(0)=A(50)=0)
Résultat : profondeur 25 m, longueur 50 m, surface maximale 1250 m² — confirmé par la sortie du modèle.
Note technique (issue #3571) : cette solution détaillée (5 étapes complètes + vérification) n’apparaît que si
max_completion_tokenslaisse assez de place au contenu final après les tokens de raisonnement. Avec un budget trop bas, la réponse était tronquée en cours d’étape 5.
Ce que le raisonnement apporte :
- Structure claire : Chaque étape est explicite et justifiée
- Notation mathématique : Formules LaTeX bien formatées
- Validation : Vérifie que c’est bien un maximum (dérivée seconde négative + contrôle des bornes)
- Résultat concret : Dimensions finales et surface maximale
Comparaison avec le mode chat :
Le mode chat (sans reasoning_effort) aurait probablement : - Donné le bon résultat final - Mais sauté certaines étapes de vérification - Moins de rigueur dans la démonstration
Cas d’usage similaires : - Optimisation de budget/ressources - Problèmes de géométrie (surface, volume) - Calcul de marges maximales en finance - Conception de systèmes avec contraintes multiples
def get_content_safe(response, max_len=800):
"""Extrait le contenu de manière sécurisée."""
content = response.choices[0].message.content
if content is None:
return "[Content null - response may be reasoning-only or truncated]"
return content[:max_len]
# Sans "Formatting re-enabled"
response_no_format = client.chat.completions.create(
model=DEFAULT_REASONING_MODEL,
messages=[{"role": "user", "content": "Explique le théorème de Pythagore avec des formules."}],
max_completion_tokens=4000,
)
# Avec "Formatting re-enabled"
response_with_format = client.chat.completions.create(
model=DEFAULT_REASONING_MODEL,
messages=[
{"role": "developer", "content": "Formatting re-enabled"},
{"role": "user", "content": "Explique le théorème de Pythagore avec des formules."}
],
max_completion_tokens=4000,
)
print("=== Sans 'Formatting re-enabled' ===")
print(get_content_safe(response_no_format))
print("\n...\n")
print("\n=== Avec 'Formatting re-enabled' ===")
print(get_content_safe(response_with_format))
print("\n...\n")
print("\nDifférence: Avec formatage, vous obtenez du markdown propre (formules LaTeX, code blocks, etc.)")=== Sans 'Formatting re-enabled' ===
Énoncé
- Dans un triangle rectangle, le carré de la longueur de l'hypoténuse est égal à la somme des carrés des longueurs des deux autres côtés.
- Si on note a et b les longueurs des deux cathètes (côtés adjacents à l'angle droit) et c la longueur de l'hypoténuse, alors :
a^2 + b^2 = c^2.
Preuve 1 (géométrie par similarité)
- Soit ABC un triangle rectangle en C, avec AC = b, BC = a et AB = c. On trace la hauteur CH issue de C sur l'hypoténuse AB; H est le pied de la hauteur. Les triangles ACH, BCH et ABC sont semblables.
- De la similarité on obtient les rapports :
AC^2 = AB · AH (donc b^2 = c · AH)
BC^2 = AB · HB (donc a^2 = c · HB)
- En additionnant : a^2 + b^2 = c(AH + HB) = c · AB = c · c = c^2.
- D'où a^2 + b^2 = c^2.
Preuve 2 (coordonnées)
- Placer le triangle dans le plan
...
=== Avec 'Formatting re-enabled' ===
Énoncé
- Dans un triangle rectangle, les carrés des longueurs des deux côtés adjacents à l'angle droit (les « côtés de l'angle droit », ou cathets) ont pour somme le carré de la longueur du côté opposé à l'angle droit (l'hypoténuse).
- Si on note a et b les longueurs des deux cathets et c la longueur de l'hypoténuse, alors :
a^2 + b^2 = c^2.
Preuves (quelques démonstrations rapides)
1) Preuve par coordonnées
- Placer le triangle rectangle dans le plan avec les points (0,0), (a,0) et (0,b). La distance entre (a,0) et (0,b) est
c = sqrt((a-0)^2 + (0-b)^2) = sqrt(a^2 + b^2).
- En élevant au carré on obtient c^2 = a^2 + b^2.
2) Preuve par similitude (avec la hauteur sur l'hypoténuse)
- Soit ABC triangle rectangle en C, AB = c, AC = b, BC = a. On trace la hauteur CD sur AB; on appelle AD
...
Différence: Avec formatage, vous obtenez du markdown propre (formules LaTeX, code blocks, etc.)
Interprétation de la différence de formatage
Résultat obtenu : Les deux appels (avec et sans "Formatting re-enabled") produisent une explication complète du théorème de Pythagore, avec les notations mathématiques (a^2 + b^2 = c^2) et des preuves (par les aires, par triangles semblables). La différence porte surtout sur la présentation.
Ce que le paramètre "Formatting re-enabled" fait :
| Sans formatage | Avec formatage |
|---|---|
Texte brut, notation textuelle (c² = a² + b²) |
Markdown riche avec formules LaTeX ($a^2 + b^2 = c^2$) |
| Structure simple (numérotation) | Titres, listes, blocs de code avec syntax highlighting |
| Pas de mise en forme | Présentation professionnelle |
Quand activer le formatage ?
| Cas d’usage | Formatting re-enabled ? |
|---|---|
| Documentation technique | Oui (formules, code) |
| Rapports scientifiques | Oui (LaTeX, tableaux) |
| Extraction de données brutes | Non (traitement programmatique) |
| API backend | Non (texte simple plus facile à parser) |
| Interface utilisateur | Oui (présentation soignée) |
Note technique (issue #3571) : si une réponse reasoning revient vide (
content=None), c’est généralement quemax_completion_tokensétait trop bas — les tokens de raisonnement ont consommé tout le budget. Le relever (ici 4000) garantit une réponse visible.
Conseil : Pour les notebooks Jupyter, le formatage markdown est automatiquement rendu, ce qui rend les réponses beaucoup plus lisibles.
4. Cas d’usage : Génération de code complexe
Les modèles de raisonnement excellent dans la génération de code nécessitant : - Analyse algorithmique - Optimisation de complexité - Tests edge cases - Debugging multi-étapes
Exemple : Algorithme du plus long palindrome
Problème classique d’algorithmique : - Approche naïve : O(n³) - Approche optimisée : O(n²) avec expansion autour du centre - Approche avancée : O(n) avec Manacher’s algorithm
Un modèle raisonnant peut analyser les différentes approches et choisir la meilleure.
Analyse du benchmark
Résultats obtenus :
| Problème | Chat (gpt-5-mini) | Reasoning (gpt-5-mini) | Correct |
|---|---|---|---|
| 17 × 23 | 391 (runtime machine-dep) | 391 (runtime machine-dep) | 391 |
| Chats/souris | 3 (runtime machine-dep) | 3 (runtime machine-dep) | 3 chats |
| Trains | 10h13min20s (runtime machine-dep) | 10h13min20s (runtime machine-dep) | environ 10h30 |
Temps moyens : Chat = runtime machine-dep, Reasoning = runtime machine-dep
Constat : Sur ces trois problèmes, les deux modes donnent des réponses cohérentes entre elles (et proches de la réponse attendue). Comme attendu, le mode reasoning est plus lent (runtime machine-dep du Chat vs runtime machine-dep du Reasoning, soit un ratio machine-dep ~1.6×) — le surcoût de la phase de réflexion reste mesuré mais systématique sur ces prompts courts.
Note technique (issue #3571) :
gpt-5-miniest un modèle de raisonnement dont les tokens de raisonnement sont déduits demax_completion_tokens. Avec un budget trop bas (≤100), tout le budget pouvait être consommé par le raisonnement sans produire de contenu final visible ([null content]). Le budget est relevé à 4000 pour garantir une réponse non vide.
En théorie, le mode reasoning devrait : - Être plus précis sur les problèmes multi-étapes (trains, optimisation) - Prendre plus de temps (speedup wall-clock machine-dep) en raison de la phase de réflexion - Être plus fiable sur les calculs complexes
probleme_code = """
Écris une fonction Python qui trouve le plus long palindrome dans une chaîne.
La fonction doit être optimisée (O(n²) maximum).
Inclus des tests avec plusieurs cas (chaîne vide, un seul caractère, palindrome complet, pas de palindrome).
"""
print(f"=== Génération de code avec {DEFAULT_REASONING_MODEL} (reasoning_effort=high) ===\n")
start = time.time()
try:
response = client.chat.completions.create(
model=DEFAULT_REASONING_MODEL,
messages=[
{"role": "developer", "content": "Formatting re-enabled"},
{"role": "user", "content": probleme_code}
],
extra_body={"reasoning_effort": "high"}
)
duration = time.time() - start
print(f"Temps de génération: {duration:.2f}s\n")
print(response.choices[0].message.content)
except Exception as e:
print(f"Erreur avec reasoning mode: {e}")
print("\nFallback vers chat mode...")
response = client.chat.completions.create(
model=DEFAULT_CHAT_MODEL,
messages=[
{"role": "user", "content": probleme_code}
]
)
print(response.choices[0].message.content)
print("\n" + "="*60)
print("Le modèle devrait fournir :")
print(" 1. Une implémentation avec expansion autour du centre (O(n²))")
print(" 2. Des tests complets couvrant les edge cases")
print(" 3. Des commentaires expliquant la logique")=== Génération de code avec openai/gpt-5-mini (reasoning_effort=high) ===
Temps de génération: 31.75s
Voici une implémentation en Python qui trouve la plus longue sous‑chaîne palindrome en O(n²) (technique "expand around center"). Si plusieurs palindromes ont la même longueur, la première occurrence est renvoyée. Tests inclus : chaîne vide, un seul caractère, palindrome complet, pas de palindrome (aucun palindrome de longueur > 1).
```python
def longest_palindrome(s: str) -> str:
"""
Retourne la plus longue sous-chaîne palindrome de s.
Complexité : O(n^2) en temps, O(1) en espace.
Si plusieurs palindromes de même longueur existent, la première occurrence est renvoyée.
"""
n = len(s)
if n <= 1:
return s
start = 0
max_len = 1
for i in range(n):
# palindrome de longueur impaire (centre en i)
l, r = i, i
while l >= 0 and r < n and s[l] == s[r]:
curr_len = r - l + 1
if curr_len > max_len:
max_len = curr_len
start = l
l -= 1
r += 1
# palindrome de longueur paire (centre entre i et i+1)
l, r = i, i + 1
while l >= 0 and r < n and s[l] == s[r]:
curr_len = r - l + 1
if curr_len > max_len:
max_len = curr_len
start = l
l -= 1
r += 1
return s[start:start + max_len]
# Tests demandés
if __name__ == "__main__":
tests = [
("", ""), # chaîne vide
("x", "x"), # un seul caractère
("racecar", "racecar"), # palindrome complet
("abcde", "a"), # pas de palindrome (plus long que 1) -> on renvoie 'a' (premier caractère)
]
for inp, expected in tests:
out = longest_palindrome(inp)
assert out == expected, f"Échec pour {inp!r} : attendu {expected!r}, obtenu {out!r}"
print("Tous les tests demandés sont passés.")
```
Remarque : la méthode "expand around center" explore pour chaque centre (2n centres : impairs et pairs) l'expansion maximale ; dans le pire cas (chaîne répétitive) cela prend O(n²) comparaisons. Si vous voulez une solution en O(n) vous pouvez utiliser l'algorithme de Manacher, plus complexe à implémenter.
============================================================
Le modèle devrait fournir :
1. Une implémentation avec expansion autour du centre (O(n²))
2. Des tests complets couvrant les edge cases
3. Des commentaires expliquant la logique
Exercice 2 : Comparaison multi-niveau sur un problème complexe
L’objectif est de comparer les 3 niveaux de reasoning_effort sur un problème de logique multi-étapes, et de mesurer le compromis temps/qualite.
Indices : - # Étape 1 : Définir un problème de logique a plusieurs étapes (ex: enigme des 3 portes, problème de transvasement) - # Étape 2 : Boucler sur les 3 niveaux (“low”, “medium”, “high”) - # Étape 3 : Pour chaque niveau, mesurer le temps de reponse et stocker le résultat - # Étape 4 : Afficher un tableau comparatif avec les temps, les reponses et la reponse correcte
# Exercice 2 : Comparaison multi-niveau sur un probleme complexe
# TODO etudiant : Implementer un benchmark qui compare reasoning_effort low/medium/high
# - Definir un probleme de logique (ex: "Tu as un bidon de 5L et un de 3L. Comment obtenir exactement 4L?")
# - Boucler sur ["low", "medium", "high"]
# - Pour chaque niveau : mesurer le temps, appeler le modele, extraire la reponse
# - Stocker les resultats dans une liste de dicts {"effort", "time", "answer"}
# - Afficher un tableau comparatif avec la reponse correcte
results = None # TODO etudiant : implementer le benchmark
# Indice : utiliser time.time() pour mesurer, et extra_body={"reasoning_effort": effort}
# pour activer le mode reasoning
print("Exercice a completer")Exercice a completer
Déconstruction du processus de raisonnement
Le modèle gpt-5-mini en mode reasoning a identifié le problème de performance avec une analyse structurée remarquable :
1. Diagnostic du problème : - Identifie la récursion redondante - Explique que les mêmes valeurs sont recalculées plusieurs fois - Quantifie l’ampleur du problème (millions d’appels pour n=35-40)
2. Analyse de complexité : - Formule la complexité O(2ⁿ) explicitement - Explique pourquoi : “l’arbre d’appels double à chaque niveau” - Donne des ordres de grandeur concrets
3. Solutions proposées : - Option A : Mémoïsation avec @lru_cache (simple, élégant) - Option B : Approche itérative (plus performante, O(1) en espace) - Les deux solutions réduisent à O(n) en temps
4. Code production-ready : - Docstrings claires - Commentaires pertinents - Tests intégrés dans if __name__ == "__main__"
Ce que révèle ce processus :
Un modèle en mode reasoning ne se contente pas de “connaître la réponse”. Il : 1. Analyse le code existant 2. Identifie le point de friction 3. Explique les causes profondes 4. Propose plusieurs solutions avec trade-offs 5. Implémente du code de qualité professionnelle
Comparaison avec le mode chat :
Le mode chat aurait probablement : - Identifié le problème (récursion) - Proposé une solution (mémoïsation) - Mais sauté l’analyse de complexité détaillée - Fourni moins d’explications sur les choix de conception
Cas d’usage similaires pour le debugging : - Fuites mémoire - Problèmes de concurrence - Optimisation de requêtes SQL - Analyse de goulots d’étranglement (profiling)
5. Modèles de Raisonnement Avancés
Panorama des modèles raisonnants disponibles
| Modèle | Disponibilité | Caractéristiques |
|---|---|---|
| gpt-5-mini | Disponible | Rapide, économique, bonne précision |
| gpt-5-pro | Disponible | Plus puissant, plus lent |
| gpt-5-mini avec reasoning_effort | Disponible | Mode raisonnement activable (low/medium/high) |
Recommandations pratiques
- gpt-5-mini (mode chat) : Premier choix pour conversations et tâches simples
- gpt-5-mini (mode reasoning) : Activer avec
reasoning_effortpour problèmes complexes - gpt-5-pro : Pour tâches nécessitant plus de capacité ou de précision
Note : La disponibilité des modèles dépend de votre niveau d’accès API. Les exemples ci-dessous utilisent les modèles accessibles publiquement via OpenRouter.
Point important : Contrairement aux notebooks précédents qui utilisaient des modèles distincts (o4-mini, o3-mini), ce notebook utilise gpt-5-mini dans deux modes différents : mode chat (rapide) et mode reasoning (avec reasoning_effort).
probleme_complexe = """
Résous ce problème d'optimisation:
Un fermier veut construire un enclos rectangulaire contre un mur existant.
Il a 100 mètres de clôture disponible (le mur fait office d'un côté).
Quelle doit être la dimension de l'enclos pour maximiser la surface?
Détaille toutes les étapes mathématiques :
1. Définition des variables
2. Équation de contrainte
3. Fonction à optimiser
4. Calcul de la dérivée
5. Résolution et vérification
"""
print(f"=== Modèle raisonnant sur problème d'optimisation avec {DEFAULT_REASONING_MODEL} (reasoning_effort=high) ===\n")
try:
start = time.time()
response = client.chat.completions.create(
model=DEFAULT_REASONING_MODEL,
messages=[
{"role": "developer", "content": "Formatting re-enabled"},
{"role": "user", "content": probleme_complexe}
],
extra_body={"reasoning_effort": "high"}
)
duration = time.time() - start
print(f"Temps: {duration:.2f}s\n")
print(response.choices[0].message.content)
except Exception as e:
print(f"Erreur avec reasoning mode: {e}")
print(f"\nFallback vers {DEFAULT_CHAT_MODEL}...")
start = time.time()
response = client.chat.completions.create(
model=DEFAULT_CHAT_MODEL,
messages=[{"role": "user", "content": probleme_complexe}]
)
duration = time.time() - start
print(f"Temps: {duration:.2f}s\n")
print(response.choices[0].message.content)
print("\n" + "="*60)
print("Réponse correcte: Longueur 50m (parallèle au mur), Largeur 25m, Surface 1250m²")
print("Équation: S(x) = x(100-2x), dérivée S'(x) = 100 - 4x, max en x=25")=== Modèle raisonnant sur problème d'optimisation avec openai/gpt-5-mini (reasoning_effort=high) ===
Temps: 22.37s
Voici la solution détaillée en 5 étapes demandées.
1) Définition des variables
Soit x la profondeur de l'enclos (côté perpendiculaire au mur, en mètres) et y la longueur le long du mur (en mètres). On utilise la clôture pour les deux côtés de longueur x et pour le côté opposé au mur de longueur y.
2) Équation de contrainte
La longueur totale de clôture disponible est 100 m, donc :
2x + y = 100.
D'où y = 100 − 2x.
3) Fonction à optimiser
L'aire A de l'enclos est A = x·y. En remplaçant y :
A(x) = x(100 − 2x) = 100x − 2x^2.
Domaine physique : x > 0 et y > 0 ⇒ 0 < x < 50.
4) Calcul de la dérivée
A'(x) = d/dx (100x − 2x^2) = 100 − 4x.
On cherche les points critiques en résolvant A'(x) = 0 :
100 − 4x = 0 ⇒ x = 25.
5) Résolution et vérification
Deuxième dérivée : A''(x) = −4 < 0, donc la fonction A a un maximum local (et ici global sur le domaine). Vérification aux bornes : A(0) = 0 et A(50) = 0, donc le maximum intérieur est bien le maximum global.
Calcul des dimensions et de l'aire :
x = 25 m, y = 100 − 2·25 = 50 m.
Aire maximale = 25 · 50 = 1250 m^2.
Conclusion : pour maximiser la surface avec 100 m de clôture contre un mur, l'enclos doit mesurer 25 m en profondeur (deux côtés) et 50 m le long du mur ; aire maximale = 1250 m^2.
============================================================
Réponse correcte: Longueur 50m (parallèle au mur), Largeur 25m, Surface 1250m²
Équation: S(x) = x(100-2x), dérivée S'(x) = 100 - 4x, max en x=25
6. Comparaison coût/performance
Tarification (approximative, vérifiez les tarifs actuels)
| Modèle | Input (\(/1M tokens) | Output (\)/1M tokens) | Vitesse | Précision | |
|---|---|---|---|---|
| gpt-5-mini (chat) | 0.15 | 0.60 | ⚡⚡⚡ | ⭐⭐⭐ |
| gpt-5-pro | 2.50 | 10.00 | ⚡⚡ | ⭐⭐⭐⭐ |
| gpt-5-mini (reasoning) | 0.30-1.50 | 1.20-6.00 | ⚡⚡ | ⭐⭐⭐⭐⭐ (problèmes complexes) |
Note : Les coûts du mode reasoning varient selon le niveau de
reasoning_effort(low/medium/high). Plus l’effort est élevé, plus de tokens de réflexion sont générés (et facturés).
Guide de choix
def choisir_modele(tâche):
if tâche.type == "conversation" or tâche.complexite == "faible":
return "gpt-5-mini" # Rapide, économique
elif tâche.type == "generation_creative" or tâche.complexite == "moyenne":
return "gpt-5-mini" # Équilibre qualité/vitesse
elif tâche.type in ["math", "code", "logique"] and tâche.complexite == "élevée":
return "gpt-5-mini avec reasoning_effort='medium'" # Raisonnement économique
elif tâche.complexite == "très élevée" or tâche.precision_requise == "maximale":
return "gpt-5-mini avec reasoning_effort='high'" # Pour les cas difficiles
else:
return "gpt-5-mini" # Par défautTokens de raisonnement
Les modèles en mode reasoning génèrent des tokens de réflexion (non visibles) avant la réponse finale. - reasoning_effort="low" : ~500-1000 tokens de réflexion - reasoning_effort="medium" : ~1000-3000 tokens - reasoning_effort="high" : ~3000-10000+ tokens
Ces tokens sont facturés ! Optimisez selon vos besoins.
7. Benchmark : Chat vs Reasoning
Testons les deux approches sur plusieurs problèmes types.
import statistics
def get_content_safe(response):
"""Extrait le contenu de manière sécurisée."""
content = response.choices[0].message.content
if content is None:
return "[null content]"
return content.strip()
problemes = [
("Combien font 17 * 23?", "391"),
("Si 3 chats attrapent 3 souris en 3 minutes, combien de chats faut-il pour attraper 100 souris en 100 minutes?", "3 chats"),
("Un train part de Paris à 8h et roule à 120 km/h. Un autre part de Lyon (450km) à 9h à 150 km/h vers Paris. À quelle heure se croisent-ils?", "environ 10h30")
]
print("=== Benchmark Chat vs Reasoning ===\n")
temps_chat = []
temps_reasoning = []
for i, (prob, correct) in enumerate(problemes):
print(f"Problème {i+1}: {prob[:60]}...")
# Chat model (gpt-5-mini via OpenRouter)
start = time.time()
resp_chat = client.chat.completions.create(
model=DEFAULT_CHAT_MODEL,
messages=[{"role": "user", "content": prob + " Réponds uniquement avec le résultat."}],
max_completion_tokens=4000
)
t_chat = time.time() - start
temps_chat.append(t_chat)
# Reasoning model (gpt-5-mini avec reasoning_effort via OpenRouter)
start = time.time()
try:
resp_reason = client.chat.completions.create(
model=DEFAULT_REASONING_MODEL,
messages=[
{"role": "user", "content": prob + " Réponds uniquement avec le résultat."}
],
max_completion_tokens=4000,
extra_body={"reasoning_effort": "medium"}
)
t_reason = time.time() - start
temps_reasoning.append(t_reason)
reasoning_ok = True
except Exception as e:
print(f" Reasoning mode erreur: {str(e)[:50]}")
resp_reason = resp_chat
t_reason = t_chat
temps_reasoning.append(t_reason)
reasoning_ok = False
print(f" {DEFAULT_CHAT_MODEL} ({t_chat:.2f}s): {get_content_safe(resp_chat)}")
print(f" {DEFAULT_REASONING_MODEL} reasoning ({t_reason:.2f}s): {get_content_safe(resp_reason)}")
print(f" [Correct: {correct}]\n")
print("\n=== Statistiques ===")
if temps_chat:
print(f"Temps moyen {DEFAULT_CHAT_MODEL}: {statistics.mean(temps_chat):.2f}s")
if temps_reasoning:
print(f"Temps moyen {DEFAULT_REASONING_MODEL} reasoning: {statistics.mean(temps_reasoning):.2f}s")
print(f"\nObservation: Le mode reasoning est plus lent mais généralement plus précis")
print(f"sur les problèmes nécessitant plusieurs étapes de calcul.")=== Benchmark Chat vs Reasoning ===
Problème 1: Combien font 17 * 23?...
openai/gpt-5-mini (2.68s): 391
openai/gpt-5-mini reasoning (1.52s): 391
[Correct: 391]
Problème 2: Si 3 chats attrapent 3 souris en 3 minutes, combien de chats...
openai/gpt-5-mini (6.48s): 3
openai/gpt-5-mini reasoning (6.24s): 3
[Correct: 3 chats]
Problème 3: Un train part de Paris à 8h et roule à 120 km/h. Un autre pa...
openai/gpt-5-mini (6.75s): 10h13min20s
openai/gpt-5-mini reasoning (10.87s): 10h13min20s
[Correct: environ 10h30]
=== Statistiques ===
Temps moyen openai/gpt-5-mini: 5.30s
Temps moyen openai/gpt-5-mini reasoning: 6.21s
Observation: Le mode reasoning est plus lent mais généralement plus précis
sur les problèmes nécessitant plusieurs étapes de calcul.
8. Exemple pratique : Débogage de code
Les modèles de raisonnement excellent dans le debugging complexe.
code_buggue = '''
def fibonacci(n):
"""Calcule le n-ième nombre de Fibonacci."""
if n <= 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n-1) + fibonacci(n-2)
# Test
for i in range(40):
print(f"F({i}) = {fibonacci(i)}")
'''
prompt_debug = f"""
Analyse ce code Python et identifie le(s) problème(s) :
```python
{code_buggue}
```
Le code fonctionne mais devient TRÈS lent pour n >= 35.
1. Identifie le problème de performance
2. Explique pourquoi (complexité algorithmique)
3. Propose une solution optimisée
4. Fournis le code corrigé
"""
print(f"=== Débogage avec {DEFAULT_REASONING_MODEL} (reasoning_effort=high) ===\n")
try:
response = client.chat.completions.create(
model=DEFAULT_REASONING_MODEL,
messages=[
{"role": "developer", "content": "Formatting re-enabled"},
{"role": "user", "content": prompt_debug}
],
extra_body={"reasoning_effort": "high"}
)
print(response.choices[0].message.content)
except Exception as e:
print(f"Erreur avec reasoning mode: {e}")
print("\nFallback vers chat mode...")
response = client.chat.completions.create(
model=DEFAULT_CHAT_MODEL,
messages=[{"role": "user", "content": prompt_debug}]
)
print(response.choices[0].message.content)
print("\n" + "="*60)
print("Le modèle devrait identifier:")
print(" - Complexité O(2^n) due aux appels récursifs redondants")
print(" - Solution: mémoïsation ou approche itérative (O(n))")=== Débogage avec openai/gpt-5-mini (reasoning_effort=high) ===
Voici l'analyse demandée et une correction.
1) Problème de performance
- L'implémentation recursive naïve calcule plusieurs fois les mêmes sous-problèmes (chevauchement important). Par exemple fibonacci(5) recalculera fibonacci(3) plusieurs fois, etc. Pour n >= 35 le nombre d'appels récursifs devient énorme et l'exécution est très lente.
2) Pourquoi (complexité algorithmique)
- La recurrence des appels satisfait T(n) = T(n-1) + T(n-2) + O(1). Cela donne une complexité temporelle exponentielle : T(n) = Θ(φ^n) où φ = (1+√5)/2 ≈ 1.618 (on parle souvent approximativement de O(2^n)).
- En réalité le nombre d'appels de fonction est C(n) = 2·F(n+1) - 1, donc pour n = 35 on a ~29.8 millions d'appels, pour n = 40 ~331 millions d'appels — d'où la lenteur.
- De plus, la profondeur de récursion est O(n) (risque de dépasser la limite de récursion pour n très grand).
3) Solution optimisée (propositions)
- Méthode simple et efficace : approche itérative (programmation dynamique bottom-up) — complexité O(n) en temps, O(1) en mémoire.
- Alternative facile : mémoisation (top-down) avec functools.lru_cache — réduit à O(n) temps mais utilise O(n) mémoire et garde la récursion (profondeur O(n)).
- Solution la plus rapide asymptotiquement : algorithme "fast doubling" — O(log n) temps et O(log n) récursion (ou itératif), utile pour n très grand.
4) Code corrigé (version recommandée : itérative O(n), constante en mémoire)
```python
def fibonacci(n):
"""Calcule le n-ième nombre de Fibonacci (F(0)=0, F(1)=1).
Complexité : O(n) temps, O(1) mémoire.
"""
if not isinstance(n, int):
raise TypeError("n doit être un entier")
if n < 0:
raise ValueError("n doit être >= 0")
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a
# Test
for i in range(40):
print(f"F({i}) = {fibonacci(i)}")
```
Options alternatives (rapides) — si utile :
- Mémoisation avec lru_cache (O(n) temps, O(n) mémoire) :
```python
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci_memo(n):
if n < 0:
raise ValueError("n doit être >= 0")
if n < 2:
return n
return fibonacci_memo(n-1) + fibonacci_memo(n-2)
```
- Fast doubling (O(log n) temps) :
```python
def fibonacci_fast(n):
"""Retourne F(n) en O(log n) (fast doubling)."""
if not isinstance(n, int):
raise TypeError("n doit être un entier")
if n < 0:
raise ValueError("n doit être >= 0")
def _fib_pair(k):
# renvoie (F(k), F(k+1))
if k == 0:
return (0, 1)
a, b = _fib_pair(k // 2)
c = a * (2 * b - a)
d = a * a + b * b
if k % 2 == 0:
return (c, d)
else:
return (d, c + d)
return _fib_pair(n)[0]
```
Choisissez l'approche selon vos besoins : pour la plupart des usages l'approche itérative suffit et est très simple et rapide ; pour des n très grands (par ex. millions) préférez fast doubling.
============================================================
Le modèle devrait identifier:
- Complexité O(2^n) due aux appels récursifs redondants
- Solution: mémoïsation ou approche itérative (O(n))
Exercice 3 : Verification de reponse par raisonnement
L’objectif est de créer une fonction qui demande au modèle de verifier si une reponse donnee a un problème mathematique est correcte, en utilisant le mode reasoning pour valider pas a pas.
Indices : - # Étape 1 : Construire un prompt qui presente le problème ET la reponse a verifier - # Étape 2 : Utiliser reasoning_effort=‘medium’ pour permettre une verification approfondie - # Étape 3 : Demander au modèle de repondre uniquement par “CORRECT” ou “INCORRECT” suivi de la justification - # Étape 4 : Parser la reponse pour extraire le verdict et l’explication
# Exercice 3 : Verification de reponse par raisonnement
# TODO etudiant : Implementer une fonction verify_answer(problem, claimed_answer)
# - Construit un prompt : "Verifie si cette reponse est correcte. Probleme: {problem}. Reponse proposee: {claimed_answer}"
# - Utilise le modele reasoning avec reasoning_effort='medium'
# - Retourne un dict {"verdict": "CORRECT"|"INCORRECT", "explanation": "..."}
def verify_answer(problem, claimed_answer):
return None # TODO etudiant : implementer
# Test :
# result = verify_answer("Combien font 17 * 23?", "391")
# print(f"Verdict: {result['verdict']}, Explication: {result['explanation']}")
# result2 = verify_answer("Combien font 17 * 23?", "400")
# print(f"Verdict: {result2['verdict']}, Explication: {result2['explanation']}")
print("Exercice a completer")Exercice a completer
9. Limites et considérations
Limites des modèles de raisonnement
- Temps de réponse : Peuvent être lents (30-60s+) pour
reasoning_effort="high" - Coût : Tokens de réflexion facturés même s’ils ne sont pas visibles
- Pas toujours nécessaires : Sur-utiliser peut gaspiller temps et argent
- Pas magiques : Ne garantissent pas la correction (vérifiez toujours les résultats)
Bonnes pratiques
- Commencez simple : Testez d’abord avec le mode chat
- Montez progressivement : gpt-5-mini (chat) → gpt-5-mini (reasoning low) → gpt-5-mini (reasoning medium) → gpt-5-mini (reasoning high)
- Ajustez reasoning_effort : Commencez par “low”, augmentez si nécessaire
- Validez les résultats : Surtout pour le code et les calculs critiques
- Mesurez le ROI : Le temps/coût supplémentaire est-il justifié ?
Cas où le mode chat suffit
- Conversations naturelles
- Résumés et synthèses
- Traduction simple
- Génération de contenu créatif
- Questions factuelles directes
- Code simple (CRUD, scripts basiques)
10. Conclusion et ressources
Points clés à retenir
- Mode reasoning = temps de réflexion + meilleure précision sur tâches complexes
- gpt-5-mini : Excellent modèle polyvalent (chat et reasoning)
- reasoning_effort : Contrôle le compromis temps/qualité (low/medium/high)
- Messages developer : Remplacent
system,"Formatting re-enabled"active le markdown - Choisir judicieusement : Ne pas sur-utiliser le mode reasoning (coût)
- Même modèle, deux modes : gpt-5-mini peut être utilisé en mode chat (rapide) ou mode reasoning (avec reasoning_effort)
Tableau récapitulatif
| Tâche | Modèle recommandé | reasoning_effort |
|---|---|---|
| Conversation | gpt-5-mini (chat) | N/A |
| Code simple | gpt-5-mini (chat) | N/A |
| Algorithme complexe | gpt-5-mini | medium |
| Optimisation math | gpt-5-mini | high |
| Preuve formelle | gpt-5-mini | high |
| Debugging approfondi | gpt-5-mini | high |
Exercices suggérés
- Comparaison : Testez un problème de logique avec gpt-5-mini (chat) vs gpt-5-mini (reasoning)
- Optimisation : Demandez à gpt-5-mini (reasoning) d’optimiser un algorithme de tri
- Reasoning effort : Comparez low/medium/high sur un problème d’optimisation
- Code generation : Demandez l’implémentation d’un algorithme complexe (Dijkstra, A*)
- Multi-étapes : Problème nécessitant analyse → planification → exécution
Ressources
Références académiques : - Wei, J. et al. (2022) - Chain-of-Thought Prompting Elicits Reasoning in Large Language Models. arXiv:2201.11903. (CoT, précurseur des reasoning models.) - OpenAI (2024) - Learning to Reason with LLMs (rapport technique o1). (Reasoning models, tokens de réflexion.) - Snell, C. et al. (2024) - Scaling LLM Test-Time Compute Optimally can be More Effective than Scaling Model Parameters. arXiv:2408.03314. (Trade-off effort/qualité, fonde reasoning_effort.) - Wang, X. et al. (2022) - Self-Consistency Improves Chain of Thought Reasoning in Language Models. arXiv:2203.11171. (Self-consistency, voisin.)
Documentation API : - Documentation OpenAI - Reasoning Models - Guide des tarifs - OpenRouter - Available Models
Prochaines étapes
Notebook suivant : 09_Production_Patterns.ipynb (Patterns de production : Conversations API, Background Mode, Rate Limiting)
Note de mise à jour
Ce notebook a été mis à jour pour utiliser exclusivement les modèles gpt-5-x. Contrairement aux versions précédentes qui comparaient des modèles distincts (o4-mini, o3-mini), cette version utilise gpt-5-mini dans deux modes différents : - Mode chat : Réponses rapides, conversations - Mode reasoning : Activé avec reasoning_effort (low/medium/high) pour une analyse approfondie
Cette approche reflète l’évolution de l’API OpenAI où les modèles de raisonnement sont maintenant intégrés dans les modèles standards via le paramètre reasoning_effort.