Lesson 6 — Versionner et tester

Versionner prompts et modèles

5 min read

This content is not translated yet. Showing the original version.

Versionner prompts et modèles

Ce qu'une « version » doit figer

Le comportement d'un appel LLM dépend de tout ce qui part au modèle. Une version qui ne fige que le texte du prompt est incomplète :

ÉlémentExemplePourquoi le figer
prompt système« Tu routes les demandes internes… »la consigne principale
gabarit utilisateurDemande : {demande}la forme de l'entrée
modèlegemini-3.5-flash-liteun autre modèle = un autre comportement
paramètrestemperature: 0, response_mime_typela température change la variabilité
flowchart TD
  R["prompts.json"] --> A["router.production = v1"]
  R --> V1["v1 : modèle, config, system, template, sha256"]
  R --> V2["v2 : modèle, config, system, template, sha256"]
  A --> V1
  C["call_llm(router, production)"] --> A
  V1 --> J["Chaque appel journalise version et sha256"]

Le registre du lab

Un simple fichier JSON, relu en revue de code comme le reste. Chaque version porte une date, une note et son empreinte :

files/prompts.json (extrait)
"v2": {
  "created": "2026-10-14",
  "note": "Prompt raccourci pour économiser des tokens (proposition à évaluer).",
  "model": "gemini-3.5-flash-lite",
  "config": {"temperature": 0, "response_mime_type": "application/json"},
  "system": "Indique en JSON le service concerné et l'urgence de la demande.",
  "template": "{demande}",
  "sha256": "0aaa739777c1"
}

L'empreinte (hash) est un résumé de 12 caractères calculé à partir du modèle, des paramètres, du prompt système et du gabarit. Si un seul caractère change, l'empreinte change. Le chargement la recalcule et refuse une version modifiée :

files/prompt_registry.py (extrait)
def fingerprint(v: dict) -> str:
    payload = json.dumps({k: v[k] for k in ("model", "config", "system", "template")},
                         sort_keys=True, ensure_ascii=False)
    return hashlib.sha256(payload.encode()).hexdigest()[:12]


def load(prompt_id: str, version: str = "production", path: Path = REGISTRY) -> PromptVersion:
    entry = json.loads(path.read_text(encoding="utf-8"))[prompt_id]
    if version == "production":
        version = entry["production"]
    v = entry["versions"][version]
    if fingerprint(v) != v["sha256"]:
        raise ValueError(f"{prompt_id}@{version} a été modifié après publication : créez une nouvelle version")

Pourquoi l'immuabilité ? Parce que les journaux disent « l'appel de mardi 10 h utilisait router@v1 ». Si v1 a été modifié depuis, cette information ne vaut plus rien.

Un collègue corrige une faute de frappe dans le prompt système de v1, déjà en production. Que se passe-t-il avec le registre du lab ?

Déployer et revenir en arrière

L'alias "production": "v1" désigne la version servie. Le code applicatif appelle call_llm("router") sans version : déployer v3, c'est changer une ligne dans prompts.json, revue et CI comprises. Revenir en arrière, c'est remettre v1. Pas de redéploiement de code.

Versionner le modèle aussi

  • Utilisez un nom de modèle stable dans le registre ; évitez les alias du type « dernière version », qui changent sans prévenir.
  • Un changement de modèle est une nouvelle version de prompt, même si le texte ne bouge pas : il passe le même test de non-régression.
  • Surveillez les annonces de fin de vie des modèles : remplacer un modèle retiré est un projet planifié, pas une urgence.
  • Sur Vertex AI, un modèle réglé (formation précédente) se référence par son endpoint : c'est une version de modèle comme une autre dans le registre.

Quels changements doivent produire une nouvelle version dans le registre ? (plusieurs réponses)

Exercice : créer v3

Créez une version v3 qui reprend v1 mais ajoute une ligne au prompt système : « Une demande d'accès à un logiciel relève de it. ». Calculez son empreinte et vérifiez que le registre la charge.

Voir la solution
  1. Copiez le bloc v1 en v3 dans prompts.json, changez created, note, ajoutez la ligne à system et mettez "sha256": "a-calculer".
  2. Lancez python prompt_registry.py : la ligne router@v3 sha256=xxxxxxxxxxxx À METTRE À JOUR donne l'empreinte.
  3. Recopiez-la dans sha256, relancez : router@v3 ... ok.
  4. pytest -q doit rester vert. Ne changez pas encore production : la leçon suivante vérifie d'abord que v3 ne régresse pas.

Résultat obtenu

Exécution réelle le 2026-10-15 : vérification du registre, puis chargement d'une copie où la température de v1 a été modifiée à 0,7 sans créer de version :

$ python prompt_registry.py
router@v1 sha256=7dc8e870b139 ok
router@v2 sha256=0aaa739777c1 ok

$ python -c "from pathlib import Path; from prompt_registry import load; load('router', 'v1', path=Path('prompts_modifie.json'))"
ValueError: router@v1 a été modifié après publication : créez une nouvelle version

Je sais faire

  • Lister ce qu'une version de prompt doit figer
  • Détecter une modification de version publiée grâce à une empreinte
  • Déployer ou revenir en arrière en changeant un alias
  • Traiter un changement de modèle comme une nouvelle version
Next