Aller au contenu principal

Évaluer votre modèle fine-tuné

Pourquoi l’évaluation est indispensable

Un fine-tuning réussi ne se mesure pas uniquement à la loss. La vraie question est : votre modèle fine-tuné est-il réellement meilleur que le modèle de base pour votre cas d’usage ? Cette leçon vous montre comment construire un protocole d’évaluation rigoureux.

Construire un jeu de test

Votre jeu de test doit être séparé de vos données d’entraînement ET de validation. Il représente les situations réelles que votre modèle rencontrera en production.

import json
import random

def preparer_jeux(fichier: str, ratios: tuple = (0.8, 0.1, 0.1)):
    """Sépare les données en train/validation/test."""
    with open(fichier, "r") as f:
        exemples = [json.loads(l) for l in f]

    random.shuffle(exemples)
    n = len(exemples)
    i1 = int(n * ratios[0])
    i2 = int(n * (ratios[0] + ratios[1]))

    jeux = {
        "train": exemples[:i1],
        "validation": exemples[i1:i2],
        "test": exemples[i2:]
    }

    for nom, data in jeux.items():
        with open(f"{nom}.jsonl", "w") as f:
            for ex in data:
                f.write(json.dumps(ex, ensure_ascii=False) + "\n")
        print(f"{nom} : {len(data)} exemples")

    return jeux

preparer_jeux("toutes_les_donnees.jsonl")

Évaluation automatique

Évaluation par métriques

from openai import OpenAI

client = OpenAI()

def evaluer_modele(modele: str, exemples_test: list[dict]) -> dict:
    """Évalue un modèle sur un jeu de test."""
    resultats = []

    for ex in exemples_test:
        # Extraire la question (sans la réponse attendue)
        messages_input = [
            m for m in ex["messages"] if m["role"] != "assistant"
        ]
        reponse_attendue = next(
            m["content"] for m in ex["messages"] if m["role"] == "assistant"
        )

        # Obtenir la réponse du modèle
        response = client.responses.create(
            model=modele,
            input=messages_input
        )
        reponse_modele = response.output_text

        resultats.append({
            "input": messages_input[-1]["content"],
            "attendu": reponse_attendue,
            "obtenu": reponse_modele
        })

    return resultats

Évaluation par LLM juge

Une technique puissante consiste à utiliser un modèle performant pour juger la qualité des réponses :

def evaluer_avec_juge(resultats: list[dict]) -> list[dict]:
    """Utilise GPT-5.4 comme juge pour évaluer les réponses."""
    evaluations = []

    for r in resultats:
        prompt_juge = f"""Évaluez la qualité de la réponse obtenue par rapport à la réponse attendue.

Question : {r['input']}

Réponse attendue : {r['attendu']}

Réponse obtenue : {r['obtenu']}

Critères (notez chacun de 1 à 5) :
1. Exactitude : les informations sont-elles correctes ?
2. Complétude : tous les points importants sont-ils couverts ?
3. Style : le ton et le format sont-ils appropriés ?
4. Concision : la réponse est-elle de longueur appropriée ?

Répondez en JSON : {{"exactitude": N, "completude": N, "style": N, "concision": N, "commentaire": "..."}}"""

        response = client.responses.create(
            model="gpt-5.4",
            input=prompt_juge
        )

        try:
            evaluation = json.loads(response.output_text)
            evaluations.append(evaluation)
        except json.JSONDecodeError:
            evaluations.append({"erreur": "Réponse non parseable"})

    return evaluations

Métriques spécialisées

Pour la classification

def metriques_classification(resultats: list[dict]) -> dict:
    """Calcule précision, rappel et F1 pour une tâche de classification."""
    correct = sum(
        1 for r in resultats
        if r["attendu"].strip().lower() == r["obtenu"].strip().lower()
    )
    total = len(resultats)
    precision = correct / total if total > 0 else 0

    print(f"Précision : {precision:.2%} ({correct}/{total})")
    return {"precision": precision, "correct": correct, "total": total}

Pour le function calling

def metriques_function_calling(resultats: list[dict]) -> dict:
    """Évalue la qualité des appels de fonctions."""
    stats = {"bonne_fonction": 0, "bons_params": 0, "total": 0}

    for r in resultats:
        stats["total"] += 1
        if r.get("fonction_attendue") == r.get("fonction_obtenue"):
            stats["bonne_fonction"] += 1
        if r.get("params_attendus") == r.get("params_obtenus"):
            stats["bons_params"] += 1

    print(f"Bonne fonction : {stats['bonne_fonction']}/{stats['total']}")
    print(f"Bons paramètres : {stats['bons_params']}/{stats['total']}")
    return stats

Évaluation humaine

L’évaluation automatique ne capture pas tout. Préparez un protocole d’évaluation humaine :

  1. Échantillonnez 20 à 50 réponses aléatoires
  2. Définissez des critères clairs et mesurables
  3. Utilisez une grille de notation standardisée
  4. Faites évaluer par plusieurs personnes pour réduire le biais
  5. Calculez l’accord inter-évaluateurs

Grille d’évaluation type

Critère 1 (Mauvais) 3 (Acceptable) 5 (Excellent)
Pertinence Hors sujet Partiellement pertinent Parfaitement ciblé
Ton Inapproprié Correct sans plus Parfaitement aligné
Format Non respecté Partiellement respecté Parfaitement respecté

Rapport d’évaluation

def rapport_evaluation(resultats_auto: dict, resultats_humains: dict):
    """Génère un rapport d'évaluation combiné."""
    print("=" * 60)
    print("RAPPORT D'ÉVALUATION DU MODÈLE FINE-TUNÉ")
    print("=" * 60)

    print(f"\nMétriques automatiques :")
    for k, v in resultats_auto.items():
        print(f"  {k} : {v}")

    print(f"\nÉvaluation humaine :")
    for k, v in resultats_humains.items():
        print(f"  {k} : {v}")

    print(f"\nRecommandation :")
    score_moyen = sum(resultats_humains.values()) / len(resultats_humains)
    if score_moyen >= 4:
        print("  Le modèle est prêt pour la production")
    elif score_moyen >= 3:
        print("  Améliorations nécessaires — itérez sur les données")
    else:
        print("  Résultats insuffisants — revoyez votre approche")

Points clés à retenir

  • Séparez toujours un jeu de test indépendant (ni train, ni validation)
  • Combinez évaluation automatique et évaluation humaine
  • L’évaluation par LLM juge est un bon compromis entre les deux
  • Définissez des critères mesurables avant de commencer
  • Un score de loss bas ne garantit pas la qualité en production