Aller au contenu
Garder la main
Sommaire
02Chapitre 2·45 min·Fondamentaux

Prompt Engineering

L'anatomie d'un prompt qui tient en production

Anatomie d'un prompt qui marche, par modèle. Bibliothèque copiable par cas d'usage.

Ce que tu sauras faire
  • 01Maîtriser l'anatomie d'un prompt de qualité production
  • 02Appliquer des techniques avancées : interview, injection documentaire, critique itérative
  • 03Connaître les différences de style entre Claude, Gemini, ChatGPT, Mistral
  • 04Constituer une bibliothèque de prompts réutilisables

1. L'anatomie d'un prompt de qualité

Un prompt de développement performant tient sur cinq éléments. Sur une tâche complexe, les cinq comptent. En sauter un, c'est laisser l'IA combler le trou à ta place.

Framework R.C.T.C.F.

Prompt
[RÔLE] → Qui est l'IA dans ce contexte ? [CONTEXTE] → Quelle est la situation actuelle du code ? [TÂCHE] → Que doit-elle faire précisément ? [CONTRAINTES] → Quelles sont les limites (stack, perf, sécurité) ? [FORMAT] → Que dois-tu recevoir en sortie ?

Exemple — vague vs structuré

Prompt vague :

Prompt
Écris-moi une fonction pour retenter les appels HTTP qui échouent

Prompt structuré :

Prompt
[RÔLE] Tu es un senior backend engineer TypeScript. [CONTEXTE] Service d'intégration NestJS (v10) qui appelle des APIs partenaires via le HttpService de @nestjs/axios. Le mapping d'erreurs existant est dans @src/http/error-mapper.ts [TÂCHE] Écris withRetry<T>(fn: () => Promise<T>, opts?: RetryOptions): Promise<T> qui retente l'appel en backoff exponentiel avec jitter. [CONTRAINTES] - Aucune dépendance externe - Ne retente que les erreurs réseau et les statuts 429 et 5xx. Jamais un 4xx métier : une requête invalide le restera. - Respecte l'en-tête Retry-After quand le serveur le renvoie - Abandonne immédiatement si l'AbortSignal passé en option est déclenché - 3 tentatives par défaut, plafond de délai configurable [FORMAT] - Fonction uniquement (pas de classe) - JSDoc complet - 3 tests Jest inline en commentaire : succès à la 2e tentative, 4xx non retenté, abort pendant l'attente

Différence : le second prompt réduit à zéro les ambiguïtés. L'IA sait exactement ce qu'on attend, dans quel contexte, avec quelles contraintes.


2. Techniques avancées

2.1 La technique "Claude Interview"

Au lieu de tout spécifier toi-même, laisse l'IA identifier ce qui manque.

Prompt
Je veux implémenter [description brève]. Avant de commencer, interviewe-moi en détail. Pose des questions sur : l'implémentation technique, les edge cases, les tradeoffs, les contraintes non évidentes. Ne pose pas de questions triviales. Creuse les parties difficiles. Continue jusqu'à avoir tout ce qu'il faut, puis génère une spec dans SPEC.md.

Quand l'utiliser : pour les features nouvelles ou complexes où tu ne sais pas encore exactement ce que tu veux.

Résultat : une spec validée avant d'écrire une seule ligne de code. Commence ensuite une nouvelle session avec cette spec comme contexte.


2.2 L'injection documentaire Just-in-Time

Problème : le modèle ne connaît pas tes librairies internes ou les APIs trop récentes.

Solution : n'injecte pas toute la documentation, seulement les signatures d'interface pertinentes.

// À éviter
"Lis toute la doc de notre AuthService et implémente..."

// Bonne approche
"Voici l'interface de notre AuthService :
interface AuthService {
  login(credentials: LoginDto): Promise<TokenPair>;
  refresh(refreshToken: string): Promise<TokenPair>;
  logout(userId: string): Promise<void>;
}

Implémente maintenant le LoginController en utilisant STRICTEMENT  
ces méthodes. N'invente aucune méthode non listée ici."

2.3 La critique itérative (Reviewer Pattern)

Ne corrige pas manuellement le code généré par l'IA. Demande-lui de se relire elle-même.

Pourquoi. Si tu corriges à la main, l'IA ne voit jamais ce qui clochait : elle refera la même erreur au prompt suivant. En la forçant à se relire avec un rôle et des critères précis, toi tu comprends pourquoi son premier jet était mauvais, et tu peux mettre à jour ton prompt (ou ton fichier de contexte : CLAUDE.md / AGENTS.md / GEMINI.md) pour qu'elle ne retombe plus dedans.

Prompt
Agis maintenant en tant qu'Architecte Senior. Analyse le code que tu viens de produire selon ces critères : 1. Performance : y a-t-il des N+1, des allocations inutiles ? 2. Sécurité : injection, gestion des erreurs, exposition de données ? 3. SOLID : couplage fort ? responsabilité unique respectée ? 4. Maintenabilité : complexité cyclomatique, lisibilité ? Pour chaque problème trouvé, propose une version refactorisée.

Résultat : les problèmes évidents sortent avant que tu ouvres le diff, et tu vois où ton prompt était trop flou. Attention à ne pas te tromper sur ce que ça t'apporte : la critique dégrossit, elle ne valide pas. C'est toi qui lis le résultat final.


2.4 Le Plan Mode (Explore sans écrire)

Avant toute implémentation sur du code existant :

Prompt
[MODE ANALYSE UNIQUEMENT — N'écris aucun code] Analyse le fichier OrderService.ts. Identifie : 1. Toutes les dépendances sortantes (injections, imports) 2. Les effets de bord si je modifie la méthode processOrder() 3. Les tests existants qui couvrent cette méthode 4. Les risques de régression Livre un rapport d'analyse structuré. Si l'analyse révèle une incompréhension, arrête et signale-le.

2.5 Ne sur-explique pas à un modèle de raisonnement

Vieux réflexe à désapprendre : ajouter « réfléchis étape par étape » à la fin de chaque prompt. Ça datait de l'époque où les modèles ne raisonnaient pas tout seuls. Aujourd'hui, un modèle de raisonnement (Claude en extended thinking, GPT en mode reasoning, Gemini Deep Think) le fait déjà, en interne. Lui redemander par-dessus ne l'aide pas : au mieux c'est neutre, souvent ça brouille sa propre logique et ça coûte des tokens pour rien.

La bonne façon de faire avec ces modèles :

  • Dis le quoi et le pourquoi, pas le comment. Donne l'objectif, les contraintes, le résultat attendu. Laisse-le trouver le chemin : c'est justement ce qu'il sait faire.
  • Évite les recettes trop détaillées (« d'abord fais ci, ensuite ça, puis vérifie… »). Sur un modèle de raisonnement, ça l'enferme au lieu de l'aider.
  • Garde les instructions pas-à-pas pour les modèles rapides (sans raisonnement), qui eux en profitent vraiment.

3. Différences par modèle

Claude (Anthropic)

Style optimal : contexte riche en amont, demandes de clarification bienvenues.

Spécificités :

  • Donne l'objectif et les contraintes plutôt qu'une recette d'étapes (voir §2.5). Le pas-à-pas reste utile sur les modèles rapides, pas sur les modèles de raisonnement
  • Très bon pour respecter les contraintes négatives ("ne fais pas X")
  • Le tag <context>...</context> améliore la séparation signal/bruit
  • Préfixe tes règles critiques avec IMPORTANT: ou YOU MUST:
<context>
  Stack: NestJS 10, TypeScript 5.3, PostgreSQL 15
  Pattern: Repository + Service + Controller
  Voir fichier existant : @src/users/users.service.ts
</context>

IMPORTANT: N'utilise pas de raw SQL. Utilise uniquement TypeORM QueryBuilder.

Tâche : Ajoute une méthode findByEmailOrUsername(query: string) au UserRepository.

Gemini (Google)

Style optimal : structure ta demande avec des sections claires, cite tes sources.

Spécificités :

  • Très bon pour les tâches qui nécessitent de montrer son raisonnement ("show your work")
  • Supporte les très longs context windows → bon pour analyser tout un module
  • Répond bien aux demandes de comparaison et de synthèse
Prompt
## Contexte [Colle le fichier complet] ## Tâche Analyse ce service et identifie les problèmes de performance. Montre ton raisonnement étape par étape. Pour chaque problème, cite la ligne concernée. ## Format attendu Tableau : Ligne | Problème | Sévérité | Fix recommandé

ChatGPT / GPT-5.x (OpenAI)

Style optimal : format d'abord, puis contenu.

Spécificités :

  • Très réactif aux exemples de format en début de prompt
  • Bon pour les tâches structurées avec des sorties prédictibles (JSON, tables)
  • Le system prompt a un impact fort sur le ton et la forme
Prompt
Réponds uniquement en JSON avec ce format : { "issue": "description", "severity": "high|medium|low", "fix": "code corrigé", "explanation": "pourquoi" } Analyse ce code TypeScript pour les problèmes de typage : [code]

Mistral (Mistral AI)

Style optimal : instructions denses et directes, va droit au but.

Spécificités :

  • Concis par défaut : inutile de lui demander d'être bref, c'est son penchant naturel
  • Bon suiveur de format explicite (JSON, tableaux) et de rôle système
  • Codestral est spécialisé code : excellent en complétion et fill-in-the-middle (FIM), pas en longue conversation d'architecture
  • Poids ouverts → même prompt utilisable en cloud ou en self-hosted
Prompt
[Rôle système] Tu es un développeur backend senior. Réponds sans préambule. Contexte : service NestJS + TypeORM (PostgreSQL). Tâche : écris findByEmailOrUsername(query: string) sur UserRepository. Contrainte : QueryBuilder uniquement, pas de raw SQL. Sortie : le code seul, puis 2 lignes d'explication max.

4. Bibliothèque de prompts essentiels

Dix prompts prêts à l'emploi, un par cas d'usage réel. Chaque carte est copiable d'un clic : remplace les [crochets] par ton contexte et les @fichier par tes vrais chemins. Ils appliquent tout ce qui précède : cadrage R.C.T.C.F., contraintes négatives, mode analyse avant écriture, deux-temps diagnostic → plan.

Comprendre & analyser

Comprendre un module inconnu
Tu es un développeur senior qui découvre cette codebase. Explique-moi @[fichier/module] comme à un nouvel arrivant : Le rôle métier : quel problème ce code résout, en une phrase. Le flux principal : entrée → traitements → sortie. Les dépendances clés (ce dont il a besoin pour tourner). Les zones fragiles ou surprenantes (dette, hacks, TODO, contournements). Ne paraphrase pas le code ligne à ligne. Vise la carte mentale, pas le commentaire.
Analyse d'impact avant modification
[MODE ANALYSE : n'écris aucun code]Je veux modifier [comportement attendu] dans @[fichier]. Cartographie avant que je touche à quoi que ce soit : Les appelants de [fonction/méthode] : qui casse si je change la signature. Les effets de bord (I/O, état partagé, événements émis, cache). Les tests qui couvrent ce chemin, et les trous de couverture. Le risque de régression, noté de 1 à 5, avec justification. Termine par le plan de modification le plus sûr, en petits pas. Si tu détectes une ambiguïté ou une incompréhension, arrête-toi et signale-le.

Produire & corriger

Debug — cause racine, pas symptôme
Erreur : [stack trace complète] Ce que je faisais : [contexte + comportement attendu vs obtenu] Fréquence : [systématique / aléatoire / depuis tel changement]Trouve la cause racine, pas le symptôme. Avant tout correctif : Formule 2 ou 3 hypothèses, classées par probabilité. Dis-moi précisément quoi vérifier (log, valeur, ligne) pour trancher entre elles. Ne masque pas l'erreur (pas de try/catch qui l'avale, pas de valeur par défaut qui la cache). Une fois la cause confirmée, propose le correctif minimal et explique pourquoi il n'ouvre pas de régression.
Nouveau endpoint / feature
Tu es un développeur [backend/fullstack] senior sur notre stack. Stack : [NestJS 10 / Express / Laravel / ...] Pattern à suivre : @[fichier existant similaire]. Respecte sa structure et ses conventions. À livrer : [méthode] [route] → [comportement métier]. Contraintes : [auth, validation d'entrée, pagination, idempotence, perf...]. Cas limites à gérer explicitement : [liste]. Format : Controller + DTO validé + méthode Service + 1 test du happy path.N'invente aucune méthode d'un service existant : si tu as besoin d'une signature, demande-la-moi.
Génération de tests
Tu es QA engineer senior : tu couvres les risques, pas les lignes. Écris des tests [Vitest/Jest/JUnit/pytest] pour @[fonction/service]. Couvre, par ordre de priorité : Le contrat métier (ce que la fonction promet de faire). Les edge cases : null/undefined, vide, valeurs limites, entrées malformées. Les erreurs attendues (exceptions, codes de retour). La concurrence / l'idempotence si pertinent. Données réalistes, pas de mock trivial. Le nom de chaque test dit l'intention testée. Si un cas n'est pas testable sans refactorer le code, signale-le au lieu de l'ignorer.
Refactoring en deux temps
Ce code marche mais doit être amélioré : @[fichier]. Objectif : [lisibilité / perf / baisse de complexité / découplage / SOLID]. Contrat : ne change pas l'interface publique, garde les tests au vert, pas de nouvelle dépendance sans me demander.Procède en deux temps : Diagnostic : les 3 problèmes qui coûtent le plus, du pire au moindre. Plan de refacto par petits pas réversibles. Attends ma validation du plan avant d'écrire la moindre ligne.

Vérifier & documenter

Audit sécurité (OWASP)
Tu es expert AppSec, référentiel OWASP Top 10 2021. Audite @[fichier/module]. Pour chaque faille : Catégorie OWASP + ligne concernée. Scénario d'exploitation concret : comment un attaquant en profite. Sévérité (Critical / High / Medium / Low) + justification. Correctif, avec le code patché. Priorité : injection (SQL/NoSQL/commande/XSS), autorisation manquante ou contournable, secrets en dur ou dans les logs, désérialisation non sûre, validation d'entrée absente, fuite de données sensibles. Pas de faux positif de principe : si un point est sûr, ne le liste pas.
Revue de code (tech lead, pas assistant complaisant)
Agis en tech lead qui review une PR, pas en assistant qui approuve tout. Relis @[fichier / diff] sur : correction, sécurité, perf (N+1, allocations inutiles), lisibilité, couverture de tests. Pour chaque remarque : gravité (bloquant / à corriger / nit), ligne, et le pourquoi. Distingue ce qui est réellement faux de ce qui n'est qu'une préférence de style.Si le code est bon, dis-le plutôt que d'inventer des remarques. Termine par un verdict : mergeable en l'état ? oui / non, et pourquoi.
Documentation orientée « pourquoi »
Génère la doc [JSDoc/PHPDoc/JavaDoc/docstring] de @[fonction/classe]. Inclus : description orientée « pourquoi » (pas la paraphrase du code), @param typés et décrits, @returns, @throws, un @example concret et exécutable. Documente les préconditions et les effets de bord non évidents.Reste concis : si le nom d'un paramètre est déjà explicite, ne le redécris pas.
Message de commit + description de PR
Voici mon diff : [git diff, ou description des changements]. Rédige : Un message de commit en Conventional Commits, type(scope): sujet à l'impératif (< 72 caractères), puis un corps qui explique le POURQUOI, pas le quoi. Une description de PR : contexte, ce qui change, comment tester, risques et points d'attention pour le reviewer. Reste factuel : ne mentionne que ce qui est réellement dans le diff, sans survendre.

5. Les anti-patterns de prompt

Anti-patternExemplePourquoi c'est mauvaisFix
Trop vague"améliore ce code"L'IA improvise selon ses propres critèresSpécifier les critères d'amélioration
Trop autoritaire"sois clean et SOLID"Vague, interprétation variableDonner des exemples concrets
Contexte absent"répare le bug"L'IA ne sait pas ce qui est casséColler le stack trace + contexte
Correction en boucleCorriger 3× sans changer de promptLe contexte se pollue, qualité baisse/clear + nouveau prompt enrichi
Demande trop large"réécris tout le module"Résultat imprévisible, non reviewableDécouper en étapes atomiques