Aller au contenu principal

Notation par code

Mis à jour le 30 juillet 2026

Après l’évaluateur par modèle, voici son complément mécanique : la notation par code. Elle ajoute une couche de validation supplémentaire en vérifiant si la sortie du modèle respecte le format attendu et a une syntaxe valide — un verdict déterministe, instantané et gratuit, là où l’évaluateur par modèle coûte un appel API par note. Elle est particulièrement utile quand vous demandez au modèle de générer du code, du JSON ou des expressions régulières : exactement notre projet AWS.

Deux critères évalués

  1. Conformité du format : la sortie contient-elle uniquement le format demandé (Python, JSON ou regex) sans explications ?
  2. Syntaxe valide : la sortie peut-elle être analysée ou compilée avec succès ?

Le barème est volontairement binaire : si le code est analysé avec succès, il obtient un score de 10 ; si l’analyse échoue, il obtient 0. C’est assumé — la syntaxe ne connaît pas de demi-mesure : un JSON « presque valide » est un JSON invalide, qui plantera le parseur de production exactement comme un charabia complet.

Fonctions de validation

def validate_json(text):
    try:
        json.loads(text.strip())
        return 10
    except json.JSONDecodeError:
        return 0

def validate_python(text):
    try:
        ast.parse(text.strip())
        return 10
    except SyntaxError:
        return 0

def validate_regex(text):
    try:
        re.compile(text.strip())
        return 10
    except re.error:
        return 0

Le même motif trois fois : tenter de parser, convertir le succès ou l’échec en score. Ces fonctions utilisent les capacités d’analyse natives de Python — json.loads() valide le JSON, ast.parse() crée un arbre syntaxique abstrait Python, et re.compile() valide les expressions régulières. Un choix mérite d’être souligné : ast.parse analyse la syntaxe sans exécuter le code — indispensable quand on valide du code généré par un modèle, qu’on ne lance jamais aveuglément. Le strip() absorbe les sauts de ligne parasites en bordure, cause classique de faux échecs.

Format attendu dans le jeu de données

Pour router chaque sortie vers le bon validateur, votre jeu de test doit spécifier le format attendu de chaque tâche :

{
    "task": "Description de la tâche",
    "format": "python"
}

Le champ format contient "json", "python" ou "regex" selon le type de sortie attendu — et la fonction de notation s’en sert comme d’un aiguillage vers validate_json, validate_python ou validate_regex. Si votre jeu de données est généré par Claude, ajoutez simplement cette exigence au prompt de génération : le générateur remplira le champ lui-même.

Améliorer le prompt

Première leçon concrète que cet évaluateur enseigne : dès la première exécution, les scores révèlent un défaut invisible à l’œil — Claude entoure volontiers son code d’explications, et ce texte fait échouer le parsing même quand le code est parfait. Pour obtenir de meilleurs résultats, rendez les instructions plus précises :

  • Répondre uniquement avec du Python, du JSON ou une Regex brute
  • Ne pas ajouter de commentaires, de contexte ou d’explication

Et doublez la consigne d’une contrainte mécanique : le pré-remplissage du message assistant avec des blocs de code et des séquences d’arrêt garantit un formatage propre de la sortie — la technique de la section précédente, exactement là où elle sert.

Combiner les scores

La validation syntaxique ne dit rien de la pertinence — une fonction Python parfaitement valide peut résoudre le mauvais problème. D’où la combinaison avec l’évaluateur par modèle :

model_grade = grade_by_model(test_case, output)
model_score = model_grade["score"]
syntax_score = grade_syntax(output, test_case)

score = (model_score + syntax_score) / 2

La moyenne simple donne un poids égal à la qualité du contenu (évaluateur modèle) et à la correction technique (évaluateur code) — un point de départ raisonnable. Ajustez la pondération selon ce qui compte le plus pour votre cas d’usage : si toute sortie non parsable plante votre application, la syntaxe mérite peut-être un droit de veto pur et simple. Et gardez la perspective : un score isolé ne dit pas grand-chose — la vraie valeur vient de la comparaison des scores au fil des itérations sur vos prompts.

Points clés à retenir

  • La notation par code est déterministe et gratuite — mais ne juge que le vérifiable mécaniquement
  • json.loads, ast.parse, re.compile : parser natif = validateur ; ast.parse n’exécute jamais le code
  • Barème binaire assumé : la syntaxe ne connaît pas le « presque valide »
  • Le champ format du jeu de données route chaque sortie vers son validateur
  • Combinez contenu (modèle) et technique (code) avec une pondération qui reflète votre production