Ingénierie de l'IAJune 13, 2026·8 min de lecture·Miracle KaluMiracle Kalu

L'art du prompt one-shot : comment j'obtiens des premières versions utiles du premier coup

A developer typing a structured prompt into an AI coding assistant on a clean desk.

Le mythe de la ligne magique

La plupart des captures d'écran d'outils de codage IA montrent un utilisateur tapant « build me a payment system » et recevant en retour une intégration Stripe fonctionnelle. Ces démos sont les infopublicités de musculation du génie logiciel : impressionnantes, virales et en grande partie déconnectées de la réalité de la production.

J'ai passé les dix-huit derniers mois à intégrer de grands modèles de langage dans mon flux de travail. La plus grande surprise n'a pas été tout ce qu'ils peuvent faire. C'est à quel point la sortie dépend de la forme du premier prompt. Un prompt one-shot bien conçu peut faire gagner des heures. Un prompt bâclé crée de la dette technique plus vite que n'importe quel junior. Cet article traite de comment écrire la première catégorie — tout en gardant des attentes honnêtes.

Pourquoi les prompts de démo échouent en production

Les prompts de démo fonctionnent parce que la démo est le produit. Dans du vrai code, le produit est le cas limite. Un prompt de cinq mots ne peut encoder ni votre philosophie de gestion d'erreurs, ni vos conventions existantes, ni le fait que votre type Order a déjà un couponId nullable. Le résultat semble correct jusqu'à ce qu'il rencontre la base de données.

Ce pour quoi j'utilise réellement les one-shots

J'utilise les prompts one-shot pour des transformations bornées, pas pour de l'invention from scratch. Refactoriser cette fonction. Générer des types à partir de ce schéma. Écrire des fixtures de test pour ces cas. Résumer ce diff. Chaque tâche a une entrée claire, une sortie claire et un petit rayon d'action si le modèle se trompe.

Ce qu'est réellement un prompt one-shot

Un prompt one-shot n'est pas une phrase unique. C'est un paquet de contexte complet livré en un seul message. Il contient la tâche, les contraintes, le format de sortie attendu et assez d'informations contextuelles pour que le modèle en déduise les bons compromis. L'objectif est d'éviter le long va-et-vient que la plupart des gens associent au « vibe coding ».

One-shot versus zero-shot

Un prompt zero-shot décrit ce que vous voulez. Un prompt one-shot montre à quoi doit ressembler le bon résultat. Pour le génie logiciel, cela signifie généralement un petit exemple du format d'entrée et de sortie attendu, plus les règles que l'exemple illustre. L'exemple fait la différence entre « écris du code propre » et « écris du code qui ressemble à ça ».

Le contexte minimum viable

Chaque prompt que j'envoie a au moins quatre parties : qui parle, ce qu'on fait, sur quoi on le fait et ce qu'on n'a pas le droit de changer. Si l'une d'elles manque, le modèle l'inventera. L'invention est l'ennemie de la cohérence.

L'anatomie d'un prompt one-shot prêt pour la production

J'utilise la même structure pour presque toutes les tâches de développement. Elle ressemble à ceci :

## Rôle
Tu es un ingénieur TypeScript senior qui vérifie une fonction pour sa correction et son style.

## Tâche
Refactorise la fonction ci-dessous pour utiliser des retours précoces, supprimer les conditions imbriquées et préserver le comportement.

## Entrée
    function processOrder(order: Order | null): Result {
      if (order !== null) {
        if (order.items.length > 0) {
          if (order.status === "confirmed") {
            return { ok: true, total: order.items.reduce((a, b) => a + b.price, 0) };
          } else {
            return { ok: false, error: "Order not confirmed" };
          }
        } else {
          return { ok: false, error: "No items" };
        }
      } else {
        return { ok: false, error: "Missing order" };
      }
    }

## Règles
- Ne change pas la signature de la fonction.
- N'ajoute pas de dépendances externes.
- Retourne uniquement le code refactorisé, dans un bloc TypeScript.

## Exemple de style attendu
    function validateUser(user: User | null): Validation {
      if (!user) return { ok: false, error: "Missing user" };
      if (!user.emailVerified) return { ok: false, error: "Email not verified" };
      return { ok: true, user };
    }

Rôle et tâche

Le rôle définit le niveau d'expertise. Je ne demande pas au modèle d'être « utile ». Je lui demande d'être un ingénieur TypeScript senior, un relecteur de code strict ou un rédacteur technique. La tâche est une seule action. Si j'ai besoin de deux actions, j'écris deux prompts. Regrouper des tâches, c'est obtenir un résultat moitié juste à deux endroits.

Entrée et règles

L'entrée est le code exact, le schéma ou les données sur lesquels le modèle doit travailler. Les règles retirent des degrés de liberté. Je suis explicite sur les signatures, les dépendances et le format de sortie, car sinon le modèle devinera. Deviner, c'est rapide et faux.

L'exemple qui enseigne le style

L'exemple montre la forme souhaitée sans donner la réponse. Il doit illustrer le motif, pas la solution. Si l'exemple est trop proche de l'entrée, le modèle le répétera. S'il est trop abstrait, le modèle l'ignorera.

Exemple : d'une demande vague à un prompt exécutable

Voici un vrai refactor que j'ai récemment délégué. La demande initiale d'un collègue était « rends cette validation plus propre ». Ce n'est pas un prompt ; c'est une humeur. J'en ai fait un prompt one-shot et j'ai obtenu un premier brouillon qui n'a nécessité qu'une relecture au lieu de cinq.

L'original brouillon

La fonction gérait la validation des coupons pour un checkout e-commerce. Elle vérifiait l'existence, la date d'expiration, les limites d'utilisation et l'éligibilité produit dans un seul bloc imbriqué. La complexité cyclomatique était élevée, les messages d'erreur inconsistants, et ajouter une nouvelle règle de validation signifiait ajouter un nouveau niveau d'imbrication.

Le prompt que j'ai écrit

Le prompt one-shot incluait le chemin du fichier, les tests existants, la complexité cyclomatique maximale souhaitée et un court exemple de validation par clauses de garde. Il incluait aussi une règle stipulant que chaque erreur devait utiliser une union typée pour que l'appelant puisse bifurquer proprement.

Le premier brouillon reçu

type CouponError = "EXPIRED" | "USAGE_LIMIT" | "NOT_APPLICABLE" | "INVALID";

function applyCoupon(coupon: Coupon, cart: Cart): Result<Coupon, CouponError> {
  if (!coupon.active) return err("INVALID");
  if (coupon.expiresAt < Date.now()) return err("EXPIRED");
  if (coupon.usedCount >= coupon.maxUses) return err("USAGE_LIMIT");
  if (!cart.items.some((item) => coupon.productIds.includes(item.productId))) {
    return err("NOT_APPLICABLE");
  }
  return ok(coupon);
}

Le résultat n'était pas parfait. Il utilisait un type Result personnalisé que j'ai dû aligner avec notre convention d'erreur existante, et j'ai resserré quelques noms de variables. Mais la structure était bonne, la logique était solide, et la relecture a duré cinq minutes au lieu de trente.

Transformer le motif en fonction réutilisable

Une fois la structure en place, je l'ai enveloppée dans un petit helper pour que chaque prompt de refactor respecte le même contrat. L'helper n'appelle pas le modèle. Il assemble simplement le contexte et effectue quelques vérifications avant que je n'envoie quoi que ce soit.

interface PromptParts<T> {
  role: string;
  task: string;
  input: string;
  rules: string[];
  example: string;
}

function buildOneShotPrompt<T>(parts: PromptParts<T>): string {
  if (!parts.task.trim()) throw new Error("Task is required");
  if (!parts.input.trim()) throw new Error("Input is required");

  return [
    `## Role\n${parts.role}`,
    `## Task\n${parts.task}`,
    `## Input\n${parts.input}`,
    `## Rules\n${parts.rules.map((r) => `- ${r}`).join("\n")}`,
    `## Example of expected style\n${parts.example}`,
  ].join("\n\n");
}

const prompt = buildOneShotPrompt({
  role: "You are a senior TypeScript engineer.",
  task: "Refactor the function to use early returns and preserve behavior.",
  input: processOrderFunction.toString(),
  rules: [
    "Do not change the function signature.",
    "Do not add external dependencies.",
    "Return only the refactored code.",
  ],
  example: validateUserFunction.toString(),
});

Faire respecter le contrat

L'helper garantit que chaque prompt a les mêmes cinq sections. La cohérence rend la sortie prévisible. Une sortie prévisible est une sortie révisable.

Attraper les entrées manquantes

L'helper attrape aussi l'erreur la plus courante : oublier d'inclure l'entrée réelle. J'ai écrit des prompts qui décrivaient magnifiquement une fonction sans jamais l'inclure. Le modèle hallucine volontiers une fonction avec le même nom. L'helper rend cela impossible.

Pourquoi les fenêtres de contexte récompensent la brièveté et la structure

Les modèles modernes ont de grandes fenêtres de contexte, mais cela ne signifie pas que vous devriez vider toute votre codebase dans le prompt. La taille de la fenêtre de contexte et le contexte utile sont deux choses différentes. Plus vous ajoutez de bruit, plus le modèle risque de s'accrocher à un motif non pertinent.

Discipline du budget de tokens

Je garde mes prompts one-shot sous 1 500 tokens d'instruction et d'exemple. Cette limite m'oblige à décider de ce qui compte vraiment. Si je ne peux pas expliquer la tâche dans ce budget, je ne la comprends pas assez bien pour la déléguer.

Quand découper la tâche

Si la tâche nécessite plus de contexte que le budget ne le permet, je n'écris pas un plus gros prompt. Je découpe la tâche. Le prompting one-shot fonctionne mieux pour des transformations bornées. Il échoue à « design this system » parce que la conception de système est intrinsèquement itérative.

Les modes de défaillance que vous rencontrerez

Surapprentissage de l'exemple

Si votre exemple est trop proche de l'entrée réelle, le modèle copie des détails de surface au lieu de suivre la règle. J'ai un jour utilisé userId dans un exemple, et chaque fonction générée par la suite utilisait aussi userId, même quand le domaine était les commandes.

Présupposer un contexte partagé

Le modèle ne connaît pas vos règles de lint, votre philosophie de test ou vos contraintes de déploiement si vous ne les lui dites pas. J'ajoute désormais une section de contraintes dans chaque prompt, même quand cela semble redondant. La redondance est moins chère que le nettoyage.

Demander trop d'artefacts

Un prompt qui demande du code, des tests, de la documentation et un script de migration en une seule fois produit des versions superficielles des quatre. Je préfère un prompt par artefact, puis une passe de synthèse si nécessaire.

Quand ne pas utiliser le one-shot

Le prompting one-shot est le mauvais outil pour le travail exploratoire. Si je ne sais pas à quoi doit ressembler la bonne abstraction, j'utilise une session conversationnelle et itérative pour esquisser des idées. Si le problème touche à la sécurité, l'intégrité des données ou l'argent, je demande au modèle de générer des options et je décide moi-même. Et si la tâche nécessite de comprendre une grande codebase inconnue, je commence par des questions ciblées plutôt qu'un seul prompt de transformation.

La vraie puissance des prompts one-shot ne réside pas dans le remplacement de la réflexion ou de la relecture. Elle réside dans la compression des parties évidentes de l'implémentation, pour que je puisse concentrer mon attention sur les parties qui comptent.

Takeaways

  • Un prompt one-shot est un paquet de contexte complet, pas une phrase unique.
  • Structure : rôle, tâche, entrée, règles et un exemple de style qui ne donne pas la réponse.
  • Enveloppez le motif dans un helper pour faire respecter le contrat et attraper les entrées manquantes.
  • Gardez les prompts sous ~1 500 tokens d'instruction ; découpez les tâches plus grandes.
  • Incluez les contraintes explicitement. Le modèle ne peut pas deviner vos standards.
  • Utilisez les prompts one-shot pour des transformations bornées, pas pour la conception de système ou l'architecture exploratoire.
  • Relisez chaque sortie. Le prompt fixe le plafond ; la relecture fixe le plancher.

Partager :

XLinkedIn
Miracle Kalu

Écrit par

Miracle Kalu

Senior Full Stack Engineer

Vous avez aimé cet article ?

Je suis disponible pour des rôles d'ingénierie senior et du conseil technique. Parlons-en.

Prendre contact →

Publié le 13 juin 2026 · 8 min de lecture

Continuer la lecture