Aller au contenu principal

Module 4 — Chaîne de pensée et décomposition des étapes

Demander au modèle « raisonne étape par étape » est devenu un réflexe. Comme tout réflexe, il aide dans certains cas et il nuit dans d'autres. Ce module explique quand cette technique paie, quand elle coûte inutilement, et ce qu'elle devient face aux modèles à raisonnement intégré.

Ce que fait la chaîne de pensée

Une chaîne de pensée (chain of thought) est une consigne qui demande au modèle de produire son raisonnement avant sa réponse. La formulation canonique tient en une phrase :

Réfléchis étape par étape, puis donne la réponse finale.

Le mécanisme est simple : générer les étapes intermédiaires en jetons condition la suite du texte sur ces étapes. Une réponse arithmétique qui apparaît immédiatement a été « devinée » ; la même réponse qui suit trois lignes de décomposition a été « déduite » — au sens où sa probabilité P(yx)P(y \mid x) est calculée en tenant compte de la trace intermédiaire.

Quand la chaîne de pensée aide

Elle aide sur les tâches qui décomposent un problème en sous-étapes enchaînées dont chaque étape est fiable individuellement :

  • Arithmétique en plusieurs opérations
  • Raisonnement logique à plusieurs implications
  • Analyse d'un document long où il faut d'abord extraire, puis comparer, puis conclure
  • Rédaction d'une réponse qui doit citer les passages du document sur lesquels elle s'appuie

Sur notre fil rouge, un courriel qui mentionne « livraison retardée provoquant l'annulation d'un événement demain » demande implicitement deux étapes : identifier le motif (livraison) puis évaluer l'urgence (élevée à cause de la contrainte temporelle). Une chaîne de pensée courte améliore mesurablement la précision sur ce type de cas :

CONSIGNE = """
Tu extrais quatre champs d'un courriel de réclamation.

Procède ainsi :
1. Identifie le motif principal.
2. Repère les contraintes temporelles éventuelles pour évaluer l'urgence.
3. Décide de l'action demandée.
4. Rends un objet JSON final avec les clés motif, produit, urgence,
action_demandee, et rien d'autre.
""".strip()

Notez la contrainte finale : rends uniquement le JSON. Sans elle, le modèle rend son raisonnement suivi du JSON, ce qui casse la sortie consommable par un logiciel. C'est un piège classique traité au module 5.

Quand la chaîne de pensée nuit

Trois situations où elle dégrade la performance ou le coût :

Tâches de reconnaissance directe. Classer un courriel spam / non spam, détecter la langue d'un texte, extraire un montant en euros : le modèle « sait » la réponse en une passe. Forcer un raisonnement ajoute des jetons et augmente la variance sans améliorer la précision.

Tâches où le raisonnement est faux mais convaincant. Sur les puzzles logiques mal posés ou les questions à énoncé trompeur, le modèle produit une chaîne de pensée grammaticalement impeccable qui conduit à une réponse fausse — et l'auditeur humain croit d'autant plus à cette réponse qu'elle est « justifiée ». On mesure alors une régression de fiabilité.

Coût en jetons de sortie. Chaque étape de raisonnement est facturée en sortie, souvent au tarif le plus élevé. Sur un million d'appels par mois, une chaîne de pensée de 200 jetons ajoute deux ordres de grandeur au coût final.

Δcouˆt=NappelsJˉraisonnementCsortie\Delta_{\text{coût}} = N_{\text{appels}} \cdot \bar{J}_{\text{raisonnement}} \cdot C_{\text{sortie}}
La chaîne de pensée n'est pas une garantie de correction

Un modèle peut produire un raisonnement plausible et une réponse fausse ; c'est même la combinaison la plus dangereuse pour l'utilisateur, qui adhère d'autant plus à l'erreur qu'elle semble justifiée. Toujours évaluer la performance avec et sans, sur le même jeu de test, avant de décider.

Auto-cohérence : plusieurs raisonnements, un vote

Une extension classique : lancer la même consigne avec chaîne de pensée plusieurs fois en jouant sur la température, puis voter la réponse finale à la majorité.

def extraire_par_vote(courriel: str, k: int = 5) -> dict:
reponses = []
for _ in range(k):
r = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "system", "content": CONSIGNE},
{"role": "user", "content": courriel}],
temperature=0.7,
)
reponses.append(extraire_json(r.choices[0].message.content))
return vote_majoritaire(reponses)

Le gain de précision est mesurable sur les tâches où la chaîne de pensée aide déjà. Le coût est multiplié par kk. La question devient un compromis : sur une extraction courrielle, doubler le coût pour gagner deux points de précision n'est presque jamais justifié. Sur un diagnostic médical assisté, cela le devient.

Décomposition en sous-appels

Quand la tâche est vraiment complexe, une meilleure stratégie que « une consigne à tout faire avec chaîne de pensée » consiste à découper en plusieurs appels enchaînés, chacun avec sa propre consigne minimaliste :

def analyser(courriel: str) -> dict:
langue = detecter_langue(courriel) # appel 1
resume = resumer_pour_extraction(courriel, langue)# appel 2
champs = extraire_champs(resume) # appel 3
return champs

Trois avantages : chaque appel est testable isolément, les échecs sont localisés (« l'erreur vient de l'appel 2 »), et chaque consigne reste courte, donc bon marché et lisible. Le coût cumulé est parfois inférieur au coût d'une consigne unique très longue qui traite tout.

Trois inconvénients : la latence s'additionne, la logique de flux se déplace dans le code Python, et une erreur en amont se propage sans qu'un appel aval ne puisse la rattraper.

ApprocheAvantage principalCoût typique
Consigne monolithique1 appel, 1 latencejetons élevés en entrée
Chaîne de penséecorrection sur cas ambigusjetons élevés en sortie
Auto-cohérenceprécision maximalemultiplié par kk
Décompositiontestabilité, lisibilitélatence cumulée

Les modèles à raisonnement intégré

Une génération de modèles récents — souvent identifiés par un « r » ou « reasoning » dans leur nom — produit un raisonnement caché avant de répondre, sans qu'il faille le demander. La chaîne de pensée manuelle devient alors non seulement inutile mais parfois contre-productive : le modèle raisonne déjà, l'ajout d'une consigne « réfléchis étape par étape » soit n'a aucun effet, soit interfère avec son processus interne.

Sur ces modèles, la bonne pratique est inversée : consignes courtes, directes, sans instruction de raisonnement. Le modèle décide seul de la profondeur d'analyse. Les tokens de raisonnement sont facturés séparément et n'apparaissent pas dans la sortie visible.

Toujours mesurer avant de généraliser

La chaîne de pensée est l'exemple parfait d'une technique dont l'efficacité varie selon le modèle, la tâche et le jeu de test. Avant de l'imposer en production, comparer sur au moins 50 cas la précision avec et sans, ainsi que la latence et le coût. Le résultat est parfois surprenant : sur une tâche que l'on croyait complexe, la version sans chaîne de pensée gagne par sa stabilité.

En résumé

  • La chaîne de pensée conditionne la réponse sur les jetons de raisonnement, ce qui aide sur les tâches en plusieurs étapes.
  • Elle nuit sur les tâches de reconnaissance directe, et elle rend les erreurs plus convaincantes qu'elles ne sont réellement.
  • L'auto-cohérence multiplie le coût par kk pour gagner quelques points de précision ; à réserver aux enjeux qui le justifient.
  • La décomposition en sous-appels est souvent supérieure à une chaîne de pensée dans une consigne monolithique, au prix de la latence.

Module suivant : les sorties structurées, où l'on force le modèle à ne produire qu'un JSON valide conforme à un schéma.