Métaphore visuelle opposant un système probabiliste chaotique à un graphe déterministe structuré pilotant un agent IA, dans le contexte de la réservation de voyages.
Artificial IntelligenceSoftware EngineeringMachine Learning

GPT-4 a échoué 99,4 % du temps — alors nous avons cessé de le laisser décider

Ashutosh SinghalAshutosh Singhal16 février 202613 min

Il était presque minuit, et je regardais notre agent réserver un vol vers la mauvaise ville pour la troisième fois d'affilée.

Pas une mauvaise ville différente à chaque fois — la même mauvaise ville. Delhi au lieu de Dehradun. L'utilisateur avait tapé « Dehradun » clairement. Le LLM l'avait correctement interprété dans son raisonnement en chaîne de pensée. Et ensuite, lorsqu'il a généré l'appel d'API, il a substitué le code d'aéroport de Delhi. Avec assurance. En silence. Trois fois.

Mon cofondateur était au téléphone. Il a dit : « Il connaît la bonne réponse. Regarde la trace de raisonnement. Il dit littéralement Dehradun. Et ensuite il fait autre chose. »

C'est cette nuit-là que j'ai cessé de croire que de meilleurs prompts nous sauveraient.

Nous avions construit un agent IA pour la réservation de voyages — le genre qui dialogue avec les systèmes de distribution mondiaux comme Amadeus et Sabre, ces backends d'un autre âge, hérités de l'ère des mainframes, qui font tourner toutes les réservations aériennes de la planète. Et nous faisions ce que tout le monde faisait en 2023 : envelopper GPT-4 dans une fine couche d'orchestration, lui donner des outils, et prier.

La prière ne fonctionnait pas.

Le chiffre qui a tout changé

Quelques semaines après cet incident de Dehradun, je suis tombé sur le benchmark TravelPlanner — une évaluation académique rigoureuse qui teste les LLM sur la planification d'itinéraires sur plusieurs jours avec des contraintes réelles : budgets, transport, restauration, hébergement. Le genre de chose qu'un agent de voyage compétent fait en vingt minutes.

Le taux de réussite global de GPT-4 : 0,6 %.

Pas 60 %. Pas 6 %. Zéro virgule six pour cent.

Je l'ai lu trois fois. Puis j'ai consulté la méthodologie pour m'assurer qu'ils n'avaient pas fait d'erreur. Ils n'en avaient pas fait. Quand vous demandez au modèle de langage le plus avancé au monde de planifier un voyage qui respecte un budget, qui relie les vols aux hôtels et aux restaurants, et qui ne viole pas la logique temporelle de base — il échoue 99,4 % du temps.

Lorsqu'on a demandé à GPT-4 de planifier des voyages avec des contraintes réelles, il a réussi 0,6 % du temps. Un agent neuro-symbolique résolvant le même problème a obtenu 97 %.

Le système qui a obtenu 97 % n'utilisait pas un modèle plus intelligent. Il utilisait une architecture fondamentalement différente — une architecture où le LLM traduisait la requête de l'utilisateur en données structurées, puis un solveur déterministe effectuait la planification proprement dite. Le LLM était le traducteur. Le code était le cerveau.

Ce benchmark n'a pas seulement validé notre frustration. Il nous a donné un plan directeur.

Pourquoi votre agent IA continue-t-il d'échouer ?

Une infographie illustrant la dégradation exponentielle de la fiabilité des étapes LLM enchaînées — le problème de la « chaîne de probabilités » — avec des pourcentages de réussite concrets à 1, 5 et 10 étapes.

Voici ce dont personne dans la ruée vers l'or des « agents IA » ne veut parler : les LLM ne raisonnent pas. Ils prédisent.

Quand GPT-4 « décide » d'appeler une API de recherche, il n'exécute pas une logique. Il prédit le prochain token statistiquement le plus probable en fonction des motifs présents dans ses données d'entraînement. Dans une conversation, cette prédiction est généralement suffisante. Dans un flux de travail d'API à dix étapes où chaque étape dépend de la sortie exacte de la précédente ? C'est un désastre.

J'ai commencé à appeler cela le problème de la chaîne de probabilités. Supposons que votre LLM réussisse chaque étape 90 % du temps — une estimation généreuse pour un usage complexe d'outils. Voici le calcul :

  • 1 étape : 90 % de réussite
  • 5 étapes : ~59 % de réussite
  • 10 étapes : ~34 % de réussite

Un flux de travail de réservation de vol — rechercher, filtrer, sélectionner, tarifer, collecter les détails du passager, créer le PNR, valider, payer, émettre le billet — dépasse couramment dix étapes. À 34 % de réussite théorique, vous ne construisez pas un logiciel. Vous construisez une machine à sous.

Et 34 %, c'est le plafond. Les performances réelles sont pires en raison de deux phénomènes que nous rencontrions sans cesse en production.

La cascade d'hallucinations

Le premier est ce que j'appelle la cascade d'hallucinations. Dans une architecture enchaînée, la sortie de l'étape 2 devient l'entrée de l'étape 3. Si le LLM commet une erreur subtile tôt — en interprétant une heure d'arrivée de vol comme 14 h 00 au lieu de 2 h 00 — cette erreur n'est pas détectée. Elle se propage. L'agent réserve l'enregistrement à l'hôtel pour le mauvais jour, sur la base de l'heure hallucinée. L'API du GDS ne connaît pas l'intention de l'agent, seulement son entrée, elle traite donc la demande avec succès. L'agent voit une réponse 200 OK et renforce sa propre erreur.

Vous vous retrouvez avec une trace d'exécution « réussie » qui produit un résultat catastrophique dans le monde réel. L'agent pense qu'il a tout réussi. Le client se présente à l'aéroport et découvre le contraire.

Le second phénomène est la dérive de contexte. À mesure que l'agent progresse dans un plan à plusieurs étapes, la fenêtre de contexte se remplit de données intermédiaires — résultats de recherche, réponses d'API, messages de l'utilisateur. Le mécanisme d'attention du modèle se disperse de plus en plus finement sur tous ces tokens. À l'étape 10, il a effectivement « oublié » la contrainte budgétaire qu'il avait correctement identifiée à l'étape 2. Les scores d'attention, régis par la fonction softmax, se diluent sur trop de tokens non pertinents.

J'ai vu cela se produire en direct lors d'une démonstration pour un partenaire potentiel. L'agent avait trouvé un hôtel dans le budget à l'étape 3. À l'étape 8, au moment de sélectionner un restaurant, il avait complètement perdu le fil du budget restant. Il a recommandé un endroit qui aurait dépassé la limite de dépenses de l'utilisateur de 40 %. Le partenaire s'est tourné vers moi et a dit : « Alors il... oublie, tout simplement ? »

Ouais. Il oublie, tout simplement.

Que se passe-t-il quand l'IA rencontre un mainframe ?

Pour vraiment comprendre pourquoi nous avions besoin d'une approche différente, il faut comprendre à quoi ressemble le travail avec les systèmes de distribution mondiaux.

Amadeus, Sabre, Travelport — voilà l'épine dorsale du transport aérien mondial. Ils ont été conçus à l'ère des mainframes, et ils se comportent en conséquence. Une réservation de vol n'est pas un simple appel d'API. C'est une machine à états finis avec une séquence précise d'opérations qui ne peuvent être réordonnées, sautées ou approximées.

Vous vous authentifiez et obtenez un jeton de session. Ce jeton doit être transmis dans chaque en-tête suivant — si le LLM l'« oublie » ou en hallucine un nouveau, tout le contexte de la transaction est perdu. Ensuite, vous recherchez des vols, et le GDS renvoie d'énormes charges utiles JSON imbriquées — souvent plus de 50 Ko — contenant des codes de base tarifaire, des modèles de bagages, des références de segments. Le LLM doit en extraire un offerId spécifique pour poursuivre. Mais les LLM sont des compresseurs à perte. Ils résument. Ils tronquent. Ils normalisent « obligeamment » des formats de données que le GDS exige exacts, à l'octet près.

Une nuit, nous avons passé quatre heures à déboguer un échec de réservation. Le LLM avait « corrigé » un code de base tarifaire — il avait changé une lettre minuscule en majuscule, parce que cela paraissait plus « correct » à un modèle entraîné sur du texte anglais. Le GDS l'a rejeté avec une erreur cryptique : ERR 1209 - SEQUENCE ERROR. Aucune explication. Aucune suggestion. Juste un mur.

Les LLM sont des compresseurs à perte. Lorsqu'ils transfèrent des données entre des appels d'API, ils « corrigent automatiquement » et « normalisent » d'une manière qui rompt l'intégrité cryptographique exigée par les systèmes d'entreprise.

Et lorsque le GDS renvoie une erreur comme UC (Unable to Confirm, impossible de confirmer), le LLM n'a aucune idée de quoi faire. Il est entraîné à être serviable, alors il interprète l'erreur comme un pépin et retente exactement la même requête. Encore. Et encore. Nous avons vu des agents brûler des milliers de tokens et atteindre les limites de débit des API, coincés dans ce que nous avons commencé à appeler la « boucle de la mort » — se cognant à répétition contre un mur qu'ils ne pouvaient pas comprendre.

La nuit où nous avons inversé l'architecture

Le tournant est survenu au cours d'une dispute.

Nous étions trois mois après le début du projet. Mon responsable de l'ingénierie voulait continuer à améliorer les prompts — des messages système plus longs, plus d'exemples, des instructions en chaîne de pensée. « On y est presque », répétait-il. « Si seulement on structure mieux le prompt pour l'étape de création du PNR... »

J'ai ouvert nos journaux. La semaine précédente, nous avions eu 47 tentatives de réservation échouées dans notre environnement de test. Onze étaient la boucle de la mort. Neuf étaient des codes d'aéroport hallucinés. Six étaient le LLM tentant de valider un PNR avant d'ajouter le champ obligatoire « Received From » — une erreur de séquence qu'aucune quantité de prompting ne semblait corriger, parce que le modèle n'avait aucune notion intrinsèque de l'ordonnancement temporel au-delà de ce qu'il avait absorbé des données d'entraînement.

« On n'y est pas presque », ai-je dit. « On est au plafond. C'est l'architecture qui pose problème. »

Cette semaine-là, nous avons tout réécrit. Nous avons cessé de demander au LLM d'orchestrer. Nous avons cessé de le laisser décider quelle étape venait ensuite. Nous avons cessé de lui fournir des réponses brutes du GDS en espérant qu'il en extrairait les bons champs.

À la place, nous avons construit un graphe.

Pour l'analyse technique complète de ce que nous avons construit et pourquoi, j'ai rédigé un article de recherche détaillé qui approfondit l'architecture.

Comment fonctionne réellement l'IA neuro-symbolique ?

Un schéma d'architecture annoté illustrant la séparation neuro-symbolique en deux couches — le LLM comme couche de traduction/interface face au graphe déterministe comme couche d'exécution/gestion — avec des exemples précis de ce que gère chaque couche.

L'idée centrale est d'une simplicité trompeuse : le flux de contrôle n'est pas une tâche linguistique.

Décider quoi faire ensuite dans un processus métier rigide ne devrait pas être une affaire de prédiction de tokens. Cela devrait être une affaire de logique conditionnelle. La décision de « demander le paiement » ne devrait se déclencher que si « le vol est sélectionné » ET « le prix est confirmé ». C'est une condition booléenne, pas une suggestion probabiliste.

Nous avons divisé notre système en deux couches :

Le LLM est devenu la couche d'interface — le traducteur. Il analyse le langage naturel de l'utilisateur (« Je veux un vol le matin pour Dehradun, pas trop cher ») en données structurées : {origin: "DEL", destination: "DED", date: "2024-03-15", time_preference: "morning", budget: "economy"}. Voilà ce en quoi les LLM sont réellement excellents : comprendre l'intention humaine désordonnée.

Le graphe est devenu la couche d'exécution — le gestionnaire. Il reçoit ces données structurées et exécute la logique métier à l'aide de code déterministe. Des nœuds codés en dur. Des schémas d'état typés. Des arêtes conditionnelles qui inspectent des variables, pas des impressions.

Nous avons utilisé LangGraph pour construire cela, parce qu'il vous fournit les primitives dont vous avez besoin : un schéma d'état partagé (adossé à une base de données, et non à un historique de conversation), des nœuds qui sont simplement des fonctions Python, et des arêtes conditionnelles qui acheminent en fonction de valeurs de variables réelles.

Le LLM devrait être l'ouvrier — extraire des données, résumer du texte, formater du JSON — tandis que le gestionnaire devrait être un logiciel codé en dur. Cette inversion du contrôle est la caractéristique déterminante des systèmes agentiques robustes.

Dans notre architecture, le LLM ne peut littéralement pas sauter d'étapes. Il est physiquement impossible pour le système de tenter une réservation avant que la variable selected_offer_id ne soit renseignée dans l'état. Non pas parce que nous avons dit au LLM « ne fais pas ça » dans un prompt, mais parce que l'arête du graphe ne se déclenchera pas. C'est comme tenter de traverser un mur en voiture — le code ne le permet tout simplement pas.

À quoi ressemble le système réel ?

Un organigramme détaillé, nœud par nœud, du véritable pipeline de réservation décrit dans l'article, montrant chaque type de nœud (Collecteur, Récupérateur, Résumeur, Sélecteur, Contrôleur, Transacteur), s'il utilise un LLM ou du code, et la capacité de suspension/reprise au niveau du Contrôleur.

Laissez-moi vous décrire ce qui se passe lorsque quelqu'un dit « Réserve-moi un vol de Mumbai à Londres mardi prochain. »

D'abord, un nœud Collecteur — propulsé par un LLM — analyse cette phrase en champs structurés. Il utilise la génération guidée (mode JSON) pour produire un schéma spécifique. Un validateur Python vérifie si les codes d'aéroport sont réels. « Londres » est ambigu — Heathrow ou Gatwick ? — le graphe achemine donc vers un nœud de désambiguïsation. Le LLM ne devine pas. Il demande.

Une fois que nous avons des critères de recherche validés, un nœud Récupérateur appelle l'API Amadeus. C'est du code pur. Aucun LLM impliqué. La réponse revient, est mise en cache dans l'état, et c'est seulement alors qu'un nœud Résumeur — un LLM — convertit les cinq meilleurs résultats en un message lisible par un humain. Mais il est strictement contraint : il ne peut afficher que les données présentes dans le JSON mis en cache. Il ne peut ni inventer d'avantages ni modifier les prix.

L'utilisateur choisit une option. Un nœud Sélecteur résout « le deuxième » vers le hash offer_id spécifique. Un nœud Contrôleur vérifie les règles métier — est-ce conforme à la politique de l'entreprise ? Le transporteur est-il sur liste noire ? En cas de violation, le graphe se suspend. Il persiste son état dans la base de données, envoie une demande d'approbation à un responsable, et attend. Des heures plus tard, lorsque le responsable clique sur « Approuver », le graphe recharge l'état exact et reprend au nœud de réservation.

Enfin, un nœud Transacteur exécute la séquence de création du PNR — segments, détails du passager, tarification, validation — dans l'ordre exact requis par le GDS. Si le GDS renvoie un avertissement de changement de prix (courant dans le voyage), le nœud s'interrompt et demande à l'utilisateur de confirmer. Il ne réserve pas automatiquement au tarif supérieur.

Chaque transition de nœud est journalisée. Chaque décision est traçable. Un auditeur peut lire le journal d'exécution et comprendre exactement pourquoi le système a réservé un vol spécifique — non pas en interprétant un fatras de tokens, mais en lisant un enregistrement structuré : Node:Gatekeeper | Input: Price=1200 | Rule: Policy_Limit=1000 | Output: REJECT_NEED_APPROVAL.

J'ai écrit sur l'architecture complète, y compris les schémas interactifs, dans la version interactive du livre blanc.

N'est-ce pas juste... de l'ingénierie logicielle ordinaire ?

Les gens me posent constamment cette question. « Alors vous dites qu'on devrait écrire du code au lieu d'utiliser l'IA ? Révolutionnaire. »

Non. Je dis que l'industrie de l'IA a été tellement grisée par la magie des modèles de langage qu'elle a oublié les soixante dernières années d'informatique. Machines à états, schémas typés, branchement conditionnel, intégrité transactionnelle — ce ne sont pas des concepts dépassés. C'est la raison pour laquelle votre banque ne vire pas accidentellement de l'argent sur le mauvais compte.

L'approche neuro-symbolique n'est pas anti-IA. Elle est pro-architecture. Nous utilisons les LLM de manière intensive — pour l'analyse d'intention, pour la désambiguïsation, pour le résumé, pour gérer le problème réellement difficile de comprendre ce qu'un humain veut dire lorsqu'il tape quelque chose d'ambigu. Mais nous ne laissons pas le LLM toucher au volant quand la voiture est sur l'autoroute.

Vous pouvez construire un chatbot qui parle de faire le travail, ou vous pouvez concevoir un agent qui fait le travail. La différence, c'est le graphe.

Il y a aussi un argument de coût qui m'a surpris. Les agents purement LLM sont coûteux — non pas parce que l'inférence est chère par appel, mais à cause des boucles d'échec. Quand un agent reste coincé à retenter une erreur du GDS en hallucinant de nouveaux paramètres, il brûle des milliers de tokens avant d'expirer. Une seule session bloquée peut coûter de 5 à 10 $ en crédits d'API. Nos gestionnaires d'erreurs codés en dur interceptent ces échecs sans aucun coût en tokens. Et parce que nous n'envoyons au LLM que les 5 champs pertinents d'une réponse GDS de 50 Ko au lieu de la totalité, nous réduisons l'utilisation de la fenêtre de contexte d'environ 90 %.

Mais les modèles ne finiront-ils pas par devenir assez bons ?

Peut-être. Je ne sais sincèrement pas si GPT-6 ou GPT-7 seront assez fiables pour orchestrer des flux de travail d'API à dix étapes sans garde-fous. Mais je sais deux choses.

Premièrement, même si les modèles s'améliorent radicalement, le problème de la chaîne de probabilités est mathématique, pas technologique. Si votre modèle est fiable à 99 % par étape — une réussite extraordinaire — un flux de travail à dix étapes échoue encore 10 % du temps. Pour des transactions d'entreprise, c'est toujours inacceptable. Le graphe élimine cela entièrement parce que l'acheminement n'est pas probabiliste.

Deuxièmement, attendre que les modèles s'améliorent est un luxe que la plupart des entreprises ne peuvent pas se permettre. Elles ont besoin d'agents qui fonctionnent maintenant, qui sont auditables maintenant, qui respectent les exigences de transparence de l'EU AI Act maintenant. L'approche neuro-symbolique ne parie pas sur l'avenir. Elle s'appuie sur des principes d'ingénierie éprouvés tout en exploitant les meilleures capacités d'IA disponibles aujourd'hui.

L'architecture est le produit

J'ai passé assez de temps dans des salles avec des investisseurs et des acheteurs d'entreprise pour savoir que l'industrie de l'IA commence à se réveiller. La question se déplace de « Qui a le modèle le plus intelligent ? » vers « Qui a le système le plus robuste ? » Les démonstrations qui éblouissent lors d'une conférence — celles où un agent réserve un vol sans faute dans un environnement contrôlé — sont bon marché. Ce qui est coûteux, et ce qui compte, c'est de construire quelque chose qui fonctionne à la dix-millième requête aussi fiablement qu'à la première.

Nous entrons dans une ère où la différenciation ne sera pas le modèle. Ce sera le graphe. Le schéma d'état. Les gestionnaires d'erreurs. Les arêtes conditionnelles. L'ingénierie logicielle ennuyeuse, rigoureuse et déterministe qui enveloppe la magie probabiliste et l'empêche de faire brûler la maison.

La magie n'a jamais été dans le prompt. Elle a toujours été dans l'architecture.

Related Research

Also Published On