Retour d'expérience technique

Le prompt engineering qui n'a pas marché (et ce qui a marché)

J'ai écrit 13 règles explicites dans mon prompt. Le modèle en a ignoré la plupart. 108 benchmarks plus tard, j'ai compris un truc : optimiser un agent, c'est pas une ligne droite. Ce qui casse sur un modèle marche sur un autre, et les gains viennent souvent de là où tu les attends le moins.

Dans le premier article de cette série, j'expliquais pourquoi trouver le pays de fabrication d'un produit à partir de son code-barres est un problème d'IA. Les données sont éparpillées, contradictoires, et demandent du raisonnement multi-étapes.

Je développe Mio, une app qui scanne un code-barres et trouve le pays de fabrication grâce à un agent IA qui cherche sur le web, lit les pages et croise les sources.

Cet article raconte comment j'ai essayé d'améliorer cet agent — et ce que j'en ai tiré.

En trois semaines : 108 benchmarks sur un dataset de test trié à la main. 7 modèles chez 4 fournisseurs. 6 versions principales du prompt avec des dizaines de sous-variantes. Et le truc que j'en retiens : un changement qui échoue dans un contexte peut marcher dans un autre, et les gains viennent de là où on les attend le moins.

Le tableau de bord

Avant d'entrer dans le détail, voici le résumé. Chaque ligne correspond à un vrai benchmark, mesuré contre des réponses de référence vérifiées à la main. "Fausse Confiance" (FC) est notre pire mode de défaillance : l'agent dit qu'il est sûr de lui alors qu'il a tort.

Sur Gemini 3.1 Flash Lite notre premier modèle de production

ChangementPrécisionFCVerdict
Baseline (v2)60%4PRODUCTION
Règles anti-fausse-confiance43%4ANNULÉ
Recherche fallback par marque~33%13CATASTROPHIQUE
Règles de calibration confiance53%4ANNULÉ
Thinking budget à 204850%4ANNULÉ
Température 1.0 (au lieu de 0)52%~5ANNULÉ
Double résultats de recherche53%4ANNULÉ
Règle d'ambiguïté57%6ANNULÉ
3 changements d'un coup47%5ANNULÉ

Sur Gemini 3 Flash après changement de modèle

ChangementPrécisionFCVerdict
Baseline (v2, même prompt)57.8%8.7
Règles anti-FC (v3)68.6%5.7+10.8%
Nudge + anti-boucle (v4)74.5%7.7EN PROD
Variant guard (v5)71.6%7.0
Blocklist (v6a)71.6%6.3

Mêmes règles anti-FC. Flash Lite : 60% → 43%. Flash 3 : 57.8% → 68.6%. Les règles n'étaient pas mauvaises. Le modèle était trop simple pour les suivre.

Ce qui a fait la différence sur l'ensemble du projet :

ChangementImpact
Changement de modèle (2.5 Flash → 3.1 Flash Lite)+13.3% match, -3 FC
Changement de modèle (Flash Lite → 3 Flash) + recalibration prompt+20% match vs production initiale
Exécution parallèle des outils+8.2% match, -3.1 FC

Les échecs (et pourquoi ils ont quand même servi)

1. Le fallback par marque (pire run de tout le projet)

L'idée avait l'air sympa : quand l'agent ne trouve pas d'où vient le produit, chercher d'où fabrique la marque. Unilever produit dans 50+ pays, mais une petite marque française a probablement une seule usine.

Résultat : 13 cas de fausse confiance. Le pire run jamais enregistré. De loin le pire.

Ce qui s'est passé : le modèle trouvait "La marque X a une usine en Y" et l'appliquait immédiatement au produit spécifique avec une confiance totale. Chaque recherche de marque retournait un pays, et le modèle le prenait pour une réponse vérifiée.

La leçon que j'en tire, et à laquelle je reviens tout le temps : ne jamais donner au modèle un plan B qui mène à des réponses de mauvaise qualité. Il va le prendre avec ENTHOUSIASME et s'en servir pour justifier des réponses fausses mais confiantes. Le modèle veut donner une réponse. Notre boulot, c'est de rendre le chemin fainéant (abandonner) plus facile que le chemin faux (deviner à partir de données de marque).

Je n'ai pas retesté ça sur un modèle plus intelligent. Ça marcherait peut-être mieux sur un modèle capable de distinguer "la marque fabrique en X" de "ce produit spécifique est fabriqué en X". Mais l'échec était tellement spectaculaire que je suis passé à autre chose.

2. Les règles anti-fausse-confiance (le coup de théâtre)

Mon agent se trompait systématiquement sur 4 produits, toujours le même pattern : il faisait confiance à des snippets "Fabriqué en France" qui faisaient référence à un autre produit sur la même page. Du coup j'ai ajouté 3 règles ciblées. Genre "les snippets de pages catalogue ne sont pas fiables, ne fais confiance qu'aux pages spécifiques au produit" et "la confiance vérifiée exige d'avoir lu la page, pas juste un snippet de recherche."

Sur Flash Lite, c'était un désastre. La précision est passée de 60% à 43%. J'ai testé 3 fois : 43%, 53%, 50%. Toujours pire. Le modèle ne savait pas distinguer "ce snippet d'une page catalogue n'est pas fiable" de "ce snippet du site du fabricant est fiable". Du coup il se méfiait de tout.

J'ai annulé et je suis passé à autre chose. Les règles étaient trop nuancées pour ce modèle.

Des semaines plus tard, j'ai basculé sur Gemini 3 Flash et testé les mêmes règles anti-FC. La précision est passée de 57.8% à 68.6%. La fausse confiance est tombée de 8.7 à 5.7. Les mêmes règles qui avaient tout cassé sur Flash Lite. Mot pour mot. Sauf que 3 Flash savait faire la différence entre une page catalogue et une page produit.

C'est là que j'ai percuté : une règle de prompt, ça marche pas "en général". Ça marche sur un modèle donné. Ce qui plante sur le modèle A peut cartonner sur le modèle B. On jette pas l'idée — on la met de côté et on y revient quand le contexte change.

3. Plus de réflexion pour de moins bons résultats

Gemini a un paramètre "thinking budget" qui contrôle combien de tokens le modèle peut utiliser pour raisonner en interne avant de répondre. Ma baseline était 1024 tokens. J'ai essayé 2048. Puis le niveau "medium" de l'API.

Les deux étaient pires. 2048 tokens : -3 match, le modèle se mettait à sur-analyser des cas simples. Medium : -2 match, +1 fausse confiance, et les itérations moyennes sont passées de 3.3 à 4.2. Le modèle utilisait le budget supplémentaire pour se remettre en question, pas pour prendre de meilleures décisions. Il trouvait un "Fabriqué en Allemagne" clair, puis passait 500 tokens à se demander si c'était bien l'Allemagne, et finissait par répondre "inconnu, confiance basse."

1024 tokens force un raisonnement concis et décisif. Plus de budget de réflexion = plus d'hésitation.

thinkingBudget = 1024 60% ← optimal thinkingLevel = "medium" 53% thinkingBudget = 2048 50% Plus de réflexion = plus d'hésitation, pas de meilleures décisions
Précision selon la configuration du thinking budget. Le budget le plus petit a produit les meilleurs résultats.

4. Température 1.0 (contre l'avis de la doc)

La documentation de Gemini dit explicitement qu'une température inférieure à 1.0 cause des "boucles ou une dégradation des performances, en particulier dans les tâches de raisonnement complexes." J'ai donc testé la température 1.0 contre ma baseline de 0.

Résultat : -7.8% de précision, +1.9% de fausse confiance. Tout a empiré. Plus de température = plus de random = plus d'hallucinations = plus de réponses fausses mais confiantes.

La température 0, c'est le bon choix pour du tool calling structuré. La doc officielle parle de génération ouverte, pas de workflows agentiques où on a besoin d'un comportement déterministe et ciblé.

5. Plus de résultats de recherche = plus de bruit

J'ai doublé le nombre de résultats de recherche par requête, de 5 à 10. Plus de données devrait aider le modèle à trouver la bonne réponse, non ?

La précision a baissé. Le modèle ne savait pas séparer le signal du bruit dans 10 résultats. Des snippets contradictoires venant de produits différents sur des sites différents l'ont perdu. 5 résultats ciblés ont fait mieux que 10 résultats bruyants.

Il y a un moment où ajouter du contexte ne fait qu'ajouter du bruit. Et ce moment arrive plus vite sur un petit modèle. C'est un truc que je voudrais retester sur un modèle plus costaud.

6. Plusieurs changements d'un coup (le problème d'accumulation)

J'ai un jour envoyé 3 changements de prompt ensemble : une nouvelle stratégie de recherche, des instructions spécifiques aux retailers, et des templates de requêtes multilingues. La précision est tombée de 60% à 47%. Les items de difficulté moyenne sont passés de 29% à 0%. Effondrement total.

Impossible de savoir quel changement a causé la régression. Peut-être les trois. Peut-être un seul. Peu importe. J'ai tout annulé et je n'ai plus jamais refait cette erreur.

Un changement à la fois. Toujours. Si on ne peut pas mesurer l'impact individuel, on ne peut rien en apprendre.

7. Le piège UE (quand le modèle dit non)

J'ai ajouté un champ region à la sortie de l'agent pour que les produits marqués "Made in EU" retournent "UE" au lieu de "inconnu." Ça avait l'air d'un petit ajout propre.

Le modèle l'a complètement ignoré. Sur 6 benchmarks. J'ai renforcé l'instruction dans le prompt. Toujours ignoré. Je l'ai ajouté à la description de l'outil. Toujours ignoré. Le country match et la fausse confiance restaient exactement les mêmes que le champ existe ou non.

Le prompt engineering ne peut pas forcer un modèle à remplir un champ dont il ne comprend pas l'utilité. Après une semaine d'essais, j'ai déplacé la logique dans du code en post-traitement. Déterministe. Marche à chaque fois.

Parfois la solution, c'est pas un meilleur prompt. C'est du code.

Ce qui a marché

1. Changer de modèle (le déblocage de tout le reste)

Mon premier modèle de production était Gemini 2.5 Flash. Le passage à 3.1 Flash Lite a gagné +13.3% match et -3 fausse confiance. Meilleur modèle, même prompt, résultat immédiat. Mais Flash Lite s'est avéré être un plafond, pas une fondation. Chaque changement de prompt que j'ai tenté dessus a dégradé les résultats.

Pourquoi je suis resté dans la famille Gemini : coût et latence. C'est une app grand public où les gens scannent des produits en magasin et attendent une réponse en secondes. Avant le benchmark gold-curated, j'ai testé Haiku (Claude) en profondeur. Il obtenait une précision comparable ou légèrement meilleure sur certains runs, mais à 0.01-0.02$ par scan et 20-29 secondes de latence. Gemini Flash coûtait 0.002-0.004$ par scan avec 8-13 secondes. À 4-5x le coût et 2-3x la latence, Haiku n'était pas viable pour de la production, quelle que soit la précision. GPT-4.1 avait des problèmes de coût similaires et une latence très variable.

Le déblocage, c'est le passage à Gemini 3 Flash. Sur son premier run avec le même prompt v2, il a obtenu la meilleure précision brute jamais vue (66.7%) mais aussi la pire fausse confiance (7 FC). Il répondait à plus de questions, mais hallucinait aussi plus.

Mais voilà le truc : une fois sur 3 Flash, le prompt engineering a recommencé à marcher. Les règles anti-FC qui avaient échoué sur Flash Lite ? +10.8% sur 3 Flash. Les règles de nudge et anti-boucle ? Ça l'a poussé à 74.5%. J'ai testé 4 variantes de prompt sur 3 Flash, chacune 3 fois pour tenir compte de la variance, et chacune montrait des différences significatives.

Changer de modèle, ça n'a pas juste amélioré la précision. Ça a débloqué tout un espace d'amélioration qui n'existait pas avant.

2. Exécution parallèle des outils (+8.2% de précision)

C'est le changement dont j'attendais le moins.

Mon agent exécutait les appels d'outils séquentiellement. Recherche, attente, lecture de page, attente, nouvelle recherche, attente. J'ai changé deux choses : le code exécute maintenant les appels d'outils en parallèle (Promise.all au lieu de await séquentiels), et j'ai ajouté une ligne dans le prompt pour dire au modèle qu'il peut grouper plusieurs appels d'outils en un seul tour.

Résultat : +8.2% match, -3.1 fausse confiance. La meilleure amélioration individuelle de tout le projet. Et remarquablement stable : le pire run avec ce changement (76.1%) battait quand même la moyenne de la version précédente (70.1%).

Le modèle s'est mis à lancer deux recherches avec des angles différents dans le même tour au lieu de les faire séquentiellement. Plus de couverture dans le même budget d'outils. L'amélioration venait des deux côtés : le changement de prompt (le modèle groupe plus) et le changement d'infra (les appels groupés tournent en parallèle).

C'est un bon exemple des trois dimensions qui marchent ensemble. Le prompt disait au modèle qu'il pouvait grouper. L'outillage rendait le groupement rapide. Et le modèle (3 Flash) était assez malin pour le faire efficacement.

3. La config qui a tenu

Température 0 et thinking budget 1024. Pas glamour. Mais c'étaient les réglages de base que chaque expérience sur chaque modèle n'a pas réussi à battre. J'ai testé température 1.0 (pire), thinking budget 2048 (pire), thinking level "medium" (pire). Les benchmarks ne mentent pas.

La leçon : trois leviers, pas un

Après 108 runs, j'ai arrêté de penser au "prompt engineering" comme un truc isolé. En fait il y a trois leviers :

Le prompt (ce qu'on dit au modèle), l'outillage (ce que le modèle peut faire), et le modèle (sa capacité à suivre des instructions). Et derrière tout ça, une contrainte qui élimine des options : le coût et la latence. Un modèle brillant à 0.02$/scan qui met 25 secondes, c'est mort pour une app grand public.

Diagramme d'optimisation à trois axes : Prompt, Modèle et Outillage, avec la configuration de production positionnée à l'intersection, contrainte par le coût et la latence
L'espace d'optimisation a trois axes. Une règle qui échoue sur un modèle peut réussir sur un autre. Les trois sont contraints par le coût et la latence.

Les règles anti-FC ont planté sur Flash Lite et cartonné sur 3 Flash — c'est le prompt qui dépend du modèle. L'exécution parallèle a marché parce qu'on a changé le prompt ET l'infra en même temps — c'est le prompt qui dépend de l'outillage. Et changer de modèle a débloqué des optimisations de prompt qui n'existaient pas avant. Rester chez Gemini malgré des tests sur d'autres fournisseurs ? C'est la contrainte coût/latence qui tranche.

Mais le vrai conseil, c'est de tout noter. Les règles anti-FC que j'avais "abandonnées" sur Flash Lite sont devenues une de mes meilleures améliorations quand je les ai retestées sur 3 Flash des semaines plus tard. Si j'avais pas gardé de trace, j'aurais pensé "les règles anti-FC, ça marche pas" et j'aurais jamais réessayé.

Quand un truc échoue, on le jette pas — on note pourquoi ça a échoué (modèle trop limité ? bottleneck outillage ? mauvaise config ?), et on y revient quand le contexte change.

Les sept échecs d'affilée sur 3.1 Flash Lite, c'était pas du temps perdu. À force de voir ce qui ne marchait pas, j'ai fini par comprendre les limites du modèle — et c'est exactement ça qui m'a poussé à en changer, et qui m'a dit quoi retester sur le nouveau.

Rien de tout ça n'est visible sans benchmark. La plupart de ces changements "avaient l'air" de marcher quand je les testais sur 3-4 exemples. Les règles anti-FC corrigeaient pile les items que je ciblais. Le pivot par marque trouvait des réponses correctes pour certains produits. Sans mesurer sur 30+ items avec des labels de référence, j'aurais mis en prod des changements cassés sans jamais m'en rendre compte.

C'est d'ailleurs le sujet du prochain article de cette série.

Prochain article : Pourquoi un agent IA a besoin d'un benchmark avant d'avoir besoin d'un prompt. Comment on a construit le framework d'évaluation, pourquoi on mesure la fausse confiance plutôt que la précision, et le jour où on a découvert que 17% des items changent de résultat entre deux runs identiques.

Cet article fait partie d'une série sur la construction d'un agent IA en production pour Mio. Précédent : Pourquoi trouver l'origine d'un produit est un problème d'IA.

Questions fréquentes

Questions fréquentes

  • Non. Les mêmes règles peuvent échouer sur un modèle et fonctionner sur un autre. Dans nos tests, les règles anti-fausse-confiance ont fait chuter la précision de 17% sur Gemini 3.1 Flash Lite mais l'ont améliorée de 10.8% sur Gemini 3 Flash. La capacité du modèle détermine s'il peut suivre des instructions nuancées.
  • La fausse confiance, c'est quand l'agent rapporte une confiance élevée alors qu'il se trompe. Par exemple, affirmer "vérifié : fabriqué en France" alors que le produit vient de Chine. C'est le mode de défaillance le plus dangereux parce que les utilisateurs font confiance aux réponses confiantes.
  • Pas forcément. Dans nos tests, doubler le thinking budget de 1024 à 2048 tokens a dégradé les résultats. Le modèle se mettait à sur-analyser des cas simples, à remettre en question des preuves claires, et finissait par répondre "inconnu" pour des produits qu'il trouvait avant. Un budget de raisonnement restreint force des décisions nettes.
  • Le choix du modèle et l'exécution parallèle des outils. Passer de Gemini 3.1 Flash Lite à Gemini 3 Flash a débloqué +20% de précision. L'exécution parallèle des outils (laisser l'agent lancer plusieurs recherches en un seul tour) a ajouté +8.2% de précision et réduit la fausse confiance de 3.1 points.

Scannez votre
premier produit.

Gratuit, sans pub, sans inscription. Disponible sur iOS et Android.

Gratuit · Illimité · Sans pub · Sans inscription