Échanger des modèles de LLM en toute sécurité : étiquettes humaines, métriques par étape, paramètres d’effort
Comment migrer un pipeline LLM à plusieurs étapes vers de nouveaux modèles sans craindre des régressions inexistantes : vérité factuelle fournie par des humains, métriques par étape, prompts obsolètes et effort de raisonnement.
Sources: Migrating off gpt-5: the models were fine, my measurements were not
Changer le nom d’un modèle dans un fichier de configuration semble être une tâche qui ne prend que cinq minutes. Dans un pipeline d’LLM en plusieurs étapes, ce n’est généralement pas le cas, et la raison réside souvent non pas dans le nouveau modèle, mais dans les critères utilisés pour l’évaluer. En procédant à une migration réaliste d’un pipeline de filtrage depuis une ancienne famille de modèles, vous verrez comment créer des données de référence fiables, attribuer les pertes aux différentes étapes, distinguer une requête obsolète provenant d’un modèle moins performant, et considérer l’effort de raisonnement comme une configuration par tâche plutôt que comme un réglage global.
Le déclencheur concret dans ce scénario est une désactivation. OpenAI a annoncé le 11 décembre 2026 comme date de retrait pour quatre modèles : gpt-5, ses variantes mini et nano, ainsi que gpt-5-pro. C’est le calendrier en vigueur au moment de la rédaction ; veuillez donc le confirmer sur la page officielle des désactivations. Le pipeline en question reposait sur les deux modèles les plus petits parmi ceux-ci, ce qui rendait ce changement obligatoire. Deux options de remplacement étaient envisagées : gpt-5.4 dans ses différentes tailles, et gpt-5.6-luna. Les noms de modèles, les paramètres par défaut et les tarifs évoluent rapidement, il convient donc de considérer les détails ci-dessous comme une vue instantanée et la méthode elle-même comme l’élément durable.
Le pipeline qui est migré
Le système traite environ 2 600 articles par mois et en réduit le nombre à une centaine de candidats, que quelqu’un examine ensuite manuellement. Cette réduction ne s’obtient pas grâce à une seule instruction ; il s’agit d’un agent conçu avec LangGraph, composé d’une douzaine de nœuds dans le graphe, dont dix représentent des appels à des modèles distincts. Trois de ces appels fournissent l’essentiel de l’information : un filtre de pertinence à l’entrée, puis deux classificateurs, l’un pour le type de contenu et l’autre pour le sujet. Après eux viennent une vérification de nouveauté, une étape d’évaluation et une étape de résumé.
Une caractéristique du design influence chaque décision qui suit. Le premier nœud a pour but d’éliminer le bruit plutôt que de juger la qualité, et ses deux types d’erreurs ont des coûts très différents :
- Un faux rejet est peu coûteux ; un modèle plus puissant ultérieurement, ou l’examinateur humain en fin de processus, le détectera.
Toute évaluation qui traite ces deux erreurs de manière symétrique vous induira en erreur concernant le fonctionnement du processus.
La configuration livrée
L’état final a été délibérément déséquilibré. Neuf des dix appels ont été transférés vers gpt-5.6-luna, qui s’est montré fiable jusqu’à présent. Le filtre de pertinence est resté sur gpt-5.4-nano ; justifier cette exception a occupé la majeure partie de l’enquête. De plus, chaque appel définit désormais explicitement les efforts de raisonnement requis au lieu d’hériter des paramètres par défaut du modèle, et ce choix s’est avéré plus important que le choix même du modèle.
Le coût a permis de réduire la liste des candidats avant même d’évaluer la qualité, mais ce n’était pas en se basant sur les prix affichés. Presque tout le trafic est facturé dans le cadre du programme de partage de données d’OpenAI, et luna bénéficie de la même allocation quotidienne plus importante que celle des modèles les moins chers déjà en usage. La facture mensuelle reste donc de quelques centimes dans tous les cas. Les modèles plus puissants de la même génération relèvent d’une allocation bien plus faible, qui serait épuisée dès midi par cette charge de travail, ce qui les excluait déjà, quel que soit leur niveau de qualité.
Voici quatre surprises, dans l’ordre où elles sont apparues. Cet ordre constitue également une liste de contrôle utile pour votre propre migration.
Leçon 1 : ne pas utiliser l’ancien modèle comme référence
La première évaluation a comparé chaque configuration candidate avec les résultats du modèle obsolète : dans quelle mesure la nouvelle configuration reproduisait-elle le résultat précédent ? Cette comparaison a révélé une régression de 31 articles et a déclenché une recherche d’un défaut du modèle qui n’existait pas en réalité.
A posteriori, le problème est évident. La première étape du processus génère des configurations candidates, dont 40 à 60 pour cent sont ensuite supprimées par l’examinateur humain. Mesurer la concordance avec ces résultats revient donc à mesurer la concordance avec un filtre déjà connu pour être médiocre. Une configuration candidate est récompensée lorsqu’elle reproduit les erreurs du modèle ancien et pénalisée lorsqu’elle les corrige.
Les décisions humaines constituent déjà des valeurs de référence enregistrées
Un ensemble d’étiquettes bien meilleur se trouvait sous contrôle de version. L’étape d’examen par un humain supprime des entrées de la liste des candidats, et chaque suppression donne naissance à un commit. Au cours du mois utilisé pour les tests, la première passe d’examen a réduit le nombre de candidats de 122 à 72, et des passes ultérieures en ont supprimé davantage. En comparant ce commit avec son parent, on obtient deux groupes étiquetés : les articles que quelqu’un a conservés et les articles que quelqu’un a rejetés.
La réévaluation des 31 articles « perdus » selon ces étiquettes a complètement changé la situation. Quarante-trois pour cent d’entre eux étaient des articles que l’examinateur avait de toute façon éliminés. Selon le jugement humain, la perte réelle se limitait à 15 articles de qualité, soit environ la moitié de ce qui semblait être une régression. De plus, comme ces étiquettes peuvent être associées aux décisions prises à chaque étape, elles indiquent quel nœud a entraîné la perte de chacun de ces 15 articles. (Ces données étiquetées proviennent de la configuration avec gpt-5.4-mini, et non de celle utilisée pour Luna, car l’exécution sur Luna a été interrompue prématurément.) Un seul nœud était responsable de ce changement ; aucune autre étape n’a entraîné une modification supérieure à un article. Un problème localisé concernant 15 articles dans une seule requête est bien plus facile à gérer qu’une perte inexplicable de 31 articles.
Leçon générale : chaque fois qu’une personne passe l’appel final dans votre système, son appel constitue la vérité de référence, et il existe généralement déjà un enregistrement de celui-ci. Examinez les files d’attente d’approbation, les modifications apportées par la modération, les tickets de support réclassés, ou les éditions effectuées par les utilisateurs sur des brouillons générés. L’article existant sur l’évaluation des systèmes RAG selon leur étape d’échec avance un argument similaire pour attribuer les erreurs au composant qui les a causées.
La mesure étape par étape révèle également des bugs sans rapport avec la migration. Dans ce cas, elle a montré que le vérificateur de nouveauté invente des noms de sujets qui ne figurent nulle part dans la liste qu’il reçoit, un nom fictif différent pour chacune de ses 24 réjections, et ce, tant avec les anciens que les nouveaux modèles.
Leçon 2 : un modèle plus strict peut interpréter correctement votre demande
Lorsque la cause du problème fut attribuée au filtre de sujets, l’idée tentante était d’ajuster son prompt jusqu’à ce que le nouveau modèle se comporte correctement. Cela aurait cependant causé de réels dommages, car un modèle plus puissant utilisé ultérieurement dans le processus charge justement ces fichiers de prompts. Assouplir une règle afin qu’un modèle de première étape accepte plus d’articles sans problème affaiblit l’étape chargée du jugement approfondi, et rien de ce qui est mesuré à la première étape ne permettrait jamais de le détecter.
Au lieu d’éditer le prompt, l’enquête a demandé au modèle de se justifier. Pour chaque article rejeté par le filtre de sujets, la raison indiquée par GPT-5.4-mini a été enregistrée, pour un total d’environ vingt appels.
Les explications étaient cohérentes. Ils ont mentionné des règles spécifiques et cité fidèlement l’instruction initiale. Dans un cas, le modèle a répété, presque mot pour mot, une règle qui excluait l’optimisation des coûts liés à l’IA « même lorsqu’elle est mise en œuvre via une passerelle API », et l’a utilisée pour supprimer un article que le réviseur avait en réalité conservé.
L’ancienne version gpt-5-mini n’avait tout simplement jamais appliqué cette règle. À l’examen, deux des règles qu’elle ignorait étaient effectivement obsolètes : l’une ne prévoyait aucune exception pour les schémas de messagerie intégrés à une application ; l’autre avait été écrite avant que les passerelles d’IA ne deviennent une infrastructure méritant d’être prise en compte. Ces deux règles ont été corrigées, les autres laissées intactes, et la correction a fait l’objet d’un commit distinct de celle relative au modèle, afin que chacune puisse être évaluée indépendamment.
Un test simple permettant de distinguer deux diagnostics opposés
C’est le test qu’il convient de réaliser en premier lors de toute migration. Lorsqu’un modèle plus récent rejette davantage d’éléments lors d’une étape de jugement, la cause est souvent un suivi plus rigoureux des instructions en conflit avec une instruction qui a évolué au fil d’un an. Consultez un exemple des raisons indiquées :
- Lorsque les explications citent correctement vos règles réelles, l’instruction est devenue obsolète, et la corriger aide toutes les étapes qui l’utilisent.
- Lorsque le modèle invoque des règles qui ne correspondent clairement pas à l’élément, votre instruction est valide et c’est le modèle qui a tort.
Ces conclusions indiquent des directions opposées, et un simple comptage des rejets ne permet pas de les distinguer.
Leçon 3 : un jugement plus strict n’est pas automatiquement un pire jugement
Le filtre de pertinence a raconté une histoire similaire sous un angle différent. À ce niveau, Luna a rejeté le double du nombre d’articles par rapport à GPT-5.4-Nano. L’interprétation évidente était que Luna était simplement moins performante pour cette tâche, et c’est presque devenu la décision finale.
Cependant, ce filtre répond en réalité à trois questions distinctes : est-ce suffisamment récent, la langue est-elle l’anglais, et le sujet relève-t-il du champ d’application ? Seul le verdict combiné avait été examiné jusqu’à présent.
En analysant séparément les verdicts, on a découvert des différences significatives. Pour la question de la langue, les modèles ont donné exactement le même résultat, en marquant les quatre mêmes articles. Toute la différence résidait dans la question du sujet : Luna a rejeté 64 articles tandis que GPT-5.4-Nano en a rejeté 32.
La lecture des raisons avancées par Luna a révélé des jugements cohérents et, pour la plupart, défendables : parmi les refus figurait une bibliothèque destinée aux groupes de travail Go, une plateforme pour créer des agents vocaux, ainsi qu’un document sur la migration de bases de données dans le cloud. Rien n’était défectueux. Luna interprète l’expression « priorité principale » de manière plus restreinte que ce que l’auteur de la demande avait en tête.
Cela exige une solution différente. Une vérification défaillante doit être corrigée. Il vaut mieux contourner une interprétation défendable mais plus stricte d’une demande vague, appliquée au seul point de contrôle qui alimente tout le reste, où les erreurs deviennent permanentes. C’est pourquoi cette seule requête est restée sur gpt-5.4-nano. De manière plus générale, un score global ne vous indique que quelque chose a changé. Si une étape répond à plusieurs questions, enregistrez chaque réponse séparément avant de formuler la moindre théorie au sujet du modèle.
Leçon 4 : l’effort de raisonnement ne se transfère pas d’un modèle à un autre ni d’une tâche à une autre
Lorsque gpt-5.4-nano a été choisi pour le filtre de pertinence, la question qui restait en suspens était de déterminer à quel point il devait réfléchir. Les modèles de raisonnement présentent un paramètre d’effort qui contrôle approximativement le niveau de délibération interne avant de fournir une réponse. L’hypothèse de travail était que cet effort fonctionnait comme un curseur de qualité qui s’ajuste toujours dans la même direction, chaque modèle répondant ainsi à sa propre manière caractéristique.
Les mesures ont révélé deux schémas très différents :
- Au niveau du filtre de pertinence, augmenter l’effort a presque doublé le nombre de rejets pour gpt-5.4-nano, tandis que luna n’a montré aucune réaction à cette modification.
- Au niveau du filtre de sujet, le même modèle luna a éliminé 49 articles sur toute la gamme d’effort, continuant néanmoins à rejeter des articles même avec la valeur maximale.
- Le modèle gpt-5-nano, désormais obsolète, était la configuration la plus permissive de toutes.
Ainsi, une affirmation comme « Luna nécessite un effort élevé » n’est pas un fait reutilisable. Elle était valable pour Luna sur une tâche mais n’avait aucun sens pour elle sur une autre. L’effort est une propriété d’un modèle spécifique sur une tâche donnée, et chaque combinaison de ce type nécessite sa propre mesure.
Un modèle plus grand ne remplace pas cette mesure. Une étude distincte comprenant 80 articles sur le mécanisme de pertinence, avec chaque modèle fonctionnant à un effort moyen, a entraîné 31 rejets de la part de GPT-5.4-mini, 34 de la part de Luna et 30 de la part de GPT-5.4-nano. Un modèle plus grand n’a pratiquement pas modifié les résultats ; en désactivant complètement le mécanisme de raisonnement de GPT-5.4-nano, on a obtenu des résultats bien différents.
L’effort présente également un profil de coûts unique, car il peut augmenter sans limite stricte. Augmenter le filtre de sujet d’un niveau d’effort a permis d’éviter 10 rejets, mais cela nécessitait environ trois fois plus d’unités de token, un compromis qui a été refusé.
Ce qui n’a pas été mesuré
Être explicite sur les lacunes fait partie de la méthode.
- La configuration luna livrée n’a jamais été évaluée par rapport aux étiquettes manuelles ; cette expérience a été interrompue prématurément. Elle fonctionne en production sans aucune erreur dans les appels au modèle, ce qui ne dit rien sur une perte de qualité.
- Un seul point de données suggère que luna performe moins bien que gpt-5.4-mini pour la classification du type de contenu, en échouant sur 9 articles de qualité alors que gpt-5.4-mini n’en a échoué que 5, avec un niveau d’effort non enregistré. Si le volume de sortie diminue, c’est ce premier élément qu’il faut examiner.
Détails de la mesure
Deux ensembles d’échantillons ont été utilisés. Les expériences de charge ont envoyé tous les 198 articles mémorisés directement vers un seul nœud, de sorte qu’aucun élément en amont ne pouvait varier. Les expériences bout en bout ont fait passer un échantillon de 200 lignes à travers chaque nœud ; il comprenait 72 articles approuvés par des humains et 49 articles rejetés par eux.
Évaluation en fonction de ces étiquettes humaines :
- Configuration ancienne (gpt-5-mini plus gpt-5-nano) : 48 articles de qualité ont été conservés sur 72 ; 27 des 49 articles de mauvaise qualité ont été autorisés.
- gpt-5.4-mini gérant les nœuds de jugement, avec les corrections de prompt appliquées : 33 articles sur 72 ont été conservés ; 18 des 49 ont été autorisés.
- Configuration actuelle (luna lors de neuf sur dix appels) : pas encore évaluée par rapport à aucun des ensembles.
Cette dernière entrée reste vide jusqu’à la revue mensuelle, car les étiquettes n’apparaissent qu’après l’application du commit de suppression, et septembre n’avait pas encore fait l’objet d’une suppression au moment de l’analyse.
Signal de production précoce
Les données de production constituent un substitut partiel. Luna a été mise en service le 30 août. Les taux d’inclusion pour des périodes comparables sont les suivants :
- Modèles précédents du 1er au 29 août : 4,55 pour cent (121 inclus sur 2 658).
- Modèles précédents durant les huit derniers jours avant le changement : 4,86 pour cent (32 sur 658).
- Luna du 30 août au 6 septembre : 4,08 pour cent (26 sur 638).
En comparant les deux périodes de huit jours correspondantes au moyen d’un test z à deux proportions, on obtient 0,69, ce qui relève clairement du bruit statistique. À titre de comparaison, le système précédent présentait un taux de 3,98 % au cours des huit premiers jours d’août, ce qui représente une variation plus importante dans son propre historique que celle introduite par luna. Une semaine et un jour constituent une période courte, et le taux d’inclusion ne mesure pas la qualité ; cependant, l’issue la plus redoutée, à savoir que luna affame silencieusement le pipeline, ne s’est pas produite.
Pendant la période d’exploitation de Luna, on a également obtenu la première analyse détaillée des rejets par nœud. Luna a exclu 603 articles durant cette période. Le filtre de pertinence en était responsable à 42 %, le filtre de type de contenu à 38 %, le filtre de sujet à 16 % et la vérification de nouveauté à 3 %. En revanche, l’ancienne configuration avait exclu 2 526 articles entre le 1er et le 29 août sans enregistrer la moindre raison ; par conséquent, pour reconstituer ces données, il fallait relire les articles plutôt que de simplement interroger les données d’exploitation. Si votre pipeline ne consigne pas aujourd’hui la raison des rejets à chaque étape, l’ajouter constitue l’amélioration la moins coûteuse que vous puissiez apporter avant une migration.
Limites de la vérité absolue et d’une seule exécution
Les étiquettes humaines présentent deux limites intrinsèques. Elles ne couvrent que les articles que l’ancien processus autorisait, de sorte qu’une nouvelle configuration ne peut jamais être créditée pour avoir sauvé quelque chose que l’ancienne avait erronément écarté. De plus, environ 79 lignes sur un échantillon de 200 ne disposent d’aucun jugement humain du tout.
La variance d’une exécution à l’autre est importante. Trois exécutions répétées d’une même configuration sur les mêmes 200 lignes ont donné des taux de rejet de 37 %, 48 % et 55 % dans un seul nœud, une marge bien plus large que ce que le bruit d’échantillonnage pourrait expliquer. La répétition d’une exécution complète de bout en bout avec cette même configuration a produit quatre nouveaux articles et fait disparaître quatre autres. En relançant la configuration obsolète avec les résultats qu’elle avait elle-même générés en production, seuls 75 des 121 articles étiquetés ont pu être récupérés, ce qui signifie qu’elle correspondait à son propre historique seulement dans environ 62 % des cas. En pratique, une seule exécution ne permet de distinguer que des différences d’environ 20 points dans un nœud, ou d’environ huit articles dans l’ensemble du pipeline.
Une approche plus efficace pour valider les modifications individuelles consiste à vérifier chaque modification uniquement sur les éléments qu’elle est censée corriger, ainsi que sur un petit ensemble fixe qu’elle ne doit pas toucher, en se fiant uniquement aux tests globaux comme alerte grossière en cas de dommages collatéraux importants. Une correction rapide a montré pourquoi : elle a fait dépasser quatre articles cibles le nœud qu’elle avait réparé, sans pour autant modifier significativement le résultat final, car trois de ces quatre articles ont été rejetés par la suite pour des raisons sans rapport.
Où vont réellement les tokens
Le raisonnement consomme des tokens de sortie, mais ce n’est pas la sortie elle-même qui épuise cette allocation. Avec les modèles précédents, la sortie représentait 13 % de tous les tokens, tandis qu’avec les nouveaux modèles ce chiffre est inférieur à 3 % ; comme les prompts sont longs, c’est l’entrée qui domine.
Au moment de la rédaction, le programme de partage de données propose deux lots quotidiens. Le plus grand, soit 2,5 millions de tokens par jour, s’applique à Luna ainsi qu’aux versions nano et mini de GPT-5.4. Le plus petit, soit 250 000 tokens par jour, concerne les modèles de taille moyenne et supérieure. En journée ordinaire, le système consommait environ 1,95 million de tokens avec les modèles précédents et environ 1,15 million avec la nouvelle gamme. Le mois exporté, composé principalement de la configuration ancienne ainsi que de huit jours avec la nouvelle, aurait coûté environ 4 dollars aux tarifs flex sans aucun abattement.
Pour mille requêtes, les coûts varient considérablement selon les modèles :
- GPT-5-Nano : 0,32 $
- GPT-5.4-Nano : 0,52 $
- GPT-5.6-Luna : 0,65 $
- GPT-5-Mini : 1,49 $
- GPT-5.4-Mini : 3,29 $ (échantillon restreint)
Luna n’est pas la plus avantageuse en termes de prix par requête, et cela est acceptable. Son coût par requête est bien inférieur à celui des modèles mini, et elle tire ses ressources du même pool que les modèles nano.
Surcoût lié aux écritures dans le cache
La liste des prix cache un détail qui mérite une attention particulière. Parmi les modèles considérés, seul Luna facture les écritures dans le cache, à un prix 25 % plus élevé que pour une entrée normale sans mise en cache. Comme les requêtes arrivent de manière sporadique tout au long de la journée plutôt que par vagues, les entrées du cache expirent entre les requêtes : 57 % des entrées de Luna ont été facturées comme des écritures dans le cache, tandis que seules 41 % ont été facturées comme des lectures dans le cache. La mise en cache reste avantageuse, réduisant la facture de 23 % par rapport à l’absence de mise en cache, mais cela est loin des 90 % promis par la réduction pour les lectures. Si votre charge de travail est irrégulière, vous bénéficierez davantage de cette réduction ; si elle est constante, prévoyez le surcoût lié aux écritures dans le cache.
Pièges API qui font échouer chaque requête
Quelques comportements des paramètres transforment un simple changement de nom en panne. Comme indiqué au moment de la rédaction (vérifier avec la documentation actuelle) :
- L’effort de raisonnement par défaut n’est pas constant d’une génération à l’autre : moyen pour gpt-5, nul pour la famille 5.4, et à nouveau moyen pour 5.6. Un simple changement de modèle modifie donc silencieusement le niveau d’effort requis pour chaque appel.
- Le niveau d’effort maximal n’est disponible que sur les modèles 5.6 ; en le demandant sur un modèle 5.4, chaque requête échoue.
- Au point de terminaison des complétions de chat, tout effort supérieur à zéro combiné à l’utilisation d’outils fonctionnels est rejeté ; de tels appels doivent être dirigés vers le point de terminaison des réponses. Comme la valeur par défaut de luna est moyenne, il est impossible d’utiliser des outils avec luna pour les complétions de chat à moins que l’effort ne soit explicitement réduit.
Aucun de ces éléments ne peut être récupéré en temps de exécution. La logique de tentative typique gère les erreurs serveur, les délais d’attente et les limites de fréquence, mais pas les requêtes invalides ; par conséquent, une mauvaise combinaison de modèle et d’effort échoue pour chaque ligne du traitement plutôt qu’une seule fois. Vérifiez la combinaison modèle/effort lorsque le processus démarre, avant que la première ligne ne soit traitée. Pour en savoir plus sur ces deux points d’entrée, consultez l’article existant sur les items versus les messages dans l’API Responses d’OpenAI.
Points clés
- N’évaluez jamais un modèle de remplacement en fonction de sa concordance avec le modèle qu’il remplace ; utilisez plutôt des décisions humaines enregistrées comme référence fiable.
- Attribuez chaque perte à une étape du pipeline, et divisez les étapes comportant plusieurs questions en verdicts distincts, tous enregistrés.