درس 6 — Comparer et déployer

Construire un banc d'essai qualité + latence

5 دقائق قراءة

هذا المحتوى غير مترجم بعد. تُعرض النسخة الأصلية.

Construire un banc d'essai qualité + latence

Les trois ingrédients d'un banc d'essai

  1. Des questions qui ressemblent à votre usage réel, pas à un examen générique. Ici : calculs de TVA, dates d'échéance, extraction JSON, tri de tickets, lecture de politiques internes, agrégats de données, SQL.
  2. Une réponse attendue vérifiable, avec un format imposé (« réponds par le nombre seul ») pour que la vérification soit fiable.
  3. Un protocole fixe : même message système, temperature: 0, requêtes l'une après l'autre (pour que la latence d'une question ne soit pas perturbée par les autres).
flowchart LR
  Q["questions.json"] --> L["pour chaque modèle, pour chaque question"]
  L --> A["client.discuter() : réponse + latence"]
  A --> N["noter() : règle déterministe"]
  N --> T["score /15, latence médiane, latence max"]
  T --> J["resultats.json + tableau Markdown"]

Les questions

files/questions.json (extrait)
{"id": "q02", "categorie": "calcul", "question": "Un abonnement coûte 240 € HT par an. Quel est le prix TTC avec une TVA de 20 % ? Réponds par le nombre seul, en euros.", "type": "nombre", "attendu": 288},
{"id": "q06", "categorie": "extraction", "question": "Extrais en JSON avec les clés nom, ville et montant (nombre) : « Commande de Léa Martin, livrée à Nantes, pour un total de 129,90 euros. » Réponds uniquement par le JSON.", "type": "json", "attendu": {"nom": "Léa Martin", "ville": "Nantes", "montant": 129.9}},
{"id": "q10", "categorie": "lecture", "question": "Politique interne : « … Au-delà de 500 €, l'accord du manager est obligatoire. » Une dépense de 650 € faite il y a 10 jours nécessite-t-elle l'accord du manager ? Réponds par OUI ou NON.", "type": "contient", "attendu": ["OUI"]}

Les noms et montants sont fictifs. Le jeu complet : questions.json.

La notation sans LLM-juge

Un LLM-juge (un modèle qui note les réponses d'un autre) est pratique pour des réponses ouvertes, mais il coûte des appels, peut se tromper et favorise parfois sa propre famille de modèles. Quand on peut imposer un format, une règle déterministe est plus fiable :

TypeRègleExemple accepté
contientun des mots attendus, comme mot entier, sans tenir compte de la casse« Négatif » pour NÉGATIF
nombreun nombre du texte égal à l'attendu (à 0,01 près), formats 1 350 et 288,00 compris« 1 350 / 15 = 90 »
jsonpremier bloc {…} décodé, chaque clé comparéeJSON entouré de ```json
regexexpression régulièreSELECT COUNT(*) FROM commandes WHERE statut = 'annulee'
files/bench.py (extrait)
def noter(q: dict, texte: str) -> bool:
    """Note une réponse sans LLM-juge : règles déterministes selon le type de question."""
    if q["type"] == "contient":
        return any(re.search(rf"(?<!\w){re.escape(a)}(?!\w)", texte, re.I) for a in q["attendu"])
    if q["type"] == "nombre":
        return any(abs(n - q["attendu"]) < 0.01 for n in nombres(texte))
    ...

La question q11 attend NON. Le modèle répond « Non, jamais le lundi. ». La règle contient l'accepte-t-elle ?

La latence

On mesure le temps de réponse complet côté client (de l'envoi de la requête à la réception de la réponse entière), et on résume par la médiane (la valeur du milieu, peu sensible à une réponse exceptionnellement lente) et le maximum.

Pourquoi le banc envoie-t-il les questions l'une après l'autre plutôt qu'en parallèle ?

Exercice : une question ouverte

Vous voulez ajouter « Résume cette politique de télétravail en une phrase ». Pourquoi ne rentre-t-elle dans aucun type existant, et que proposez-vous ?

Voir la solution

Un résumé n'a pas de réponse unique : aucune règle contient ou regex ne distingue un bon résumé d'un mauvais. Deux options :

  1. La contraindre : « Combien de jours de télétravail sont autorisés et quel jour est exclu ? Réponds au format N;JOUR », vérifiable par regex (2;lundi).
  2. Ajouter un type juge : un modèle (de préférence d'une autre famille que celui évalué) note la réponse selon une grille courte (exactitude, concision), avec quelques réponses notées à la main pour vérifier que le juge est fiable. Comptez ses appels dans le budget.

Résultat obtenu

Les 22 tests du banc (notation, nettoyage, configuration, client simulé, banc complet à 15/15 sur un faux serveur) passent sans clé le 2026-10-15 :

test_bench.py::test_quinze_questions_bien_formees PASSED                 [  4%]
test_bench.py::test_notation[q02-288,00-True] PASSED                     [ 22%]
test_bench.py::test_notation[q03-1 350 / 15 = 90-True] PASSED            [ 31%]
test_bench.py::test_notation[q06-{"nom": "Léa Martin", "ville": "Nantes", "montant": "129,90"}-False] PASSED [ 50%]
test_bench.py::test_notation[q11-Non, jamais-True] PASSED                [ 68%]
test_bench.py::test_banc_complet_avec_faux_serveur PASSED                [100%]
============================== 22 passed in 0.04s ==============================

Je sais faire

  • Écrire des questions représentatives avec un format de réponse vérifiable
  • Noter automatiquement par règles (contient, nombre, json, regex)
  • Choisir la métrique de latence adaptée (complète, premier token, débit)
  • Connaître les limites d'une notation automatique
التالي