Lección 6 — Tester et versionner

Tester le déclenchement

7 min de lectura

Este contenido aún no está traducido. Se muestra la versión original.

Tester le déclenchement

Un skill qui ne se déclenche pas ne sert à rien, et personne ne s'en plaint : l'assistant répond quand même, moins bien. Un skill qui se déclenche à tort coûte des tokens et produit une réponse hors sujet, et là encore personne n'ouvre de ticket. Le seul moyen de savoir si vos descriptions font leur travail est un jeu de requêtes étiquetées, rejoué à chaque modification d'une description, d'un modèle ou du catalogue.

Le mécanisme

Le jeu (evals/triggering.json) associe chaque requête au skill attendu, ou à null quand aucun ne doit se déclencher. Il suit les conseils du guide Optimizing skill descriptions : varier la formulation (formelle, familière, fautes, anglais et français), l'explicitation (« note de frais » ou seulement des lignes de dépenses), le détail et la complexité, et surtout écrire des quasi-homonymes négatifs, qui partagent le vocabulaire d'un skill sans en relever.

GroupeNombreExemple
Positifs, 4 par skill24« cr de la reunion svp : - budget ok - Marc s'occupe du devis avant vendredi »
Quasi-homonymes négatifs5« Crée-moi un modèle de tableau vierge pour saisir mes notes de frais »
Négatif sans rapport1« Quelle est la différence entre la médiane et la moyenne ? »
Dont paires piégées entre skills (comptées dans les positifs)3« What's the company rule on reimbursing a first-class train ticket? » : hr-policy-qa, pas expense-report-checker
flowchart LR
  J["30 requêtes étiquetées"] --> R["N passages par requête (premier tour seulement)"]
  R --> C{"Comparaison attendu / obtenu"}
  C --> E["Exactitude : décisions justes, « aucun » compris"]
  C --> P["Précision : activations justes / activations"]
  C --> RA["Rappel : positifs servis par le bon skill"]
  C --> F["Faux déclenchements sur les négatifs"]
  E --> G{"Exactitude >= TRIGGER_MIN_ACCURACY ?"}
  G -->|"non"| X["CI rouge : la description fautive est dans la liste d'erreurs"]

Quatre métriques, parce qu'une seule cache les défauts : un harness qui n'active jamais rien a une précision indéfinie et zéro faux déclenchement ; un harness qui active toujours le skill le plus proche a un rappel parfait.

La mise en œuvre

La fonction de métriques est pure et testée sans réseau (evals.py) :

files/skillkit/evals.py
def trigger_metrics(rows: list[dict]) -> dict:
    n = len(rows)
    ok = sum(r["got"] == r["expected"] for r in rows)
    fired = [r for r in rows if r["got"] is not None]
    pos = [r for r in rows if r["expected"] is not None]
    neg = [r for r in rows if r["expected"] is None]
    return {
        "exactitude": round(ok / n, 3) if n else 0.0,
        "precision": round(sum(r["got"] == r["expected"] for r in fired) / len(fired), 3) if fired else 0.0,
        "rappel": round(sum(r["got"] == r["expected"] for r in pos) / len(pos), 3) if pos else 0.0,
        "faux_declenchements": sum(r["got"] is not None for r in neg),
        "n": n,
    }

run.py eval-trigger --runs 2 rejoue chaque requête deux fois avec le modèle, calcule les scores de similarité pour quatre seuils, écrit sorties/triggering-<modèle>.json et sort en erreur si l'exactitude tombe sous TRIGGER_MIN_ACCURACY (0,85 par défaut). C'est cette sortie en erreur qui en fait une porte de CI (ci/github-actions.yml).

Résultat obtenu

2026-10-15, 30 requêtes, gemini-3.5-flash deux passages (60 décisions, 2 min 52 s, 1 632 tokens d'entrée par décision en moyenne) et gemini-3.5-flash-lite un passage :

"modele": {"model": "gemini-3.5-flash", "runs": 2,
  "metrics": {"exactitude": 1.0, "precision": 1.0, "rappel": 1.0, "faux_declenchements": 0, "n": 60},
  "erreurs": [], "tokens_entree_moyens": 1632}

"modele": {"model": "gemini-3.5-flash-lite", "runs": 1,
  "metrics": {"exactitude": 0.967, "precision": 0.96, "rappel": 1.0, "faux_declenchements": 1, "n": 30},
  "erreurs": ["attendu None -> obtenu leave-balance-calculator : \"Pose 3 jours de congés du 4 au 6 novembre dans l'outil RH pour moi.\""]}

Comment lire un score parfait. Zéro erreur sur 60 décisions ne prouve pas un taux d'erreur nul : la règle de trois donne, à 95 % de confiance, un taux d'erreur réel qui peut atteindre environ 3/60, soit 5 %, et les deux passages d'une même requête ne sont pas indépendants. Surtout, un score parfait signale souvent un jeu trop facile. Le seul échec observé (modèle léger, « poser des congés ») indique où durcir le jeu : des demandes d'action proches d'un skill de calcul ou de consultation.

Ce qui casse en production

SymptômeCauseParade
100 % en CI, plaintes en productionrequêtes de test rédigées par l'auteur du skill, avec ses motsrequêtes tirées des journaux réels (anonymisées), quasi-homonymes écrits par un tiers
Le score varie de 5 points d'un jour à l'autreun seul passage, sélection non déterministe3 passages, taux de déclenchement par requête, seuil 0,5 comme le propose agentskills.io
La description améliorée régresse sur d'autres requêtesoptimisation sur tout le jeu, surapprentissageséparation fixe 60 % entraînement, 40 % validation ; on ne regarde la validation qu'à la fin
Un nouveau skill fait chuter un ancienles descriptions se recouvrentle jeu teste le catalogue entier, pas chaque skill isolément ; relancer à chaque ajout
Coût des évals en hausse3 passages x 30 requêtes x plusieurs modèles à chaque commitévals sur étiquette de PR, make test (sans réseau) à chaque commit

La règle de décision

Rejouez le jeu de déclenchement à chaque modification d'une description, d'un modèle ou du catalogue, et bloquez la fusion sous un seuil d'exactitude fixé à l'avance. Exigez au moins un quasi-homonyme négatif par skill. Visez une centaine de requêtes pour un catalogue en production : à 30 requêtes, vous détectez les régressions grossières, pas une dégradation de quelques points. Surveillez en production la part de conversations où un skill a été activé puis non utilisé (aucun script, réponse générique) : c'est le faux déclenchement que votre jeu n'a pas prévu.

Pratique

Votre jeu de 20 requêtes donne 100 % d'exactitude depuis trois mois. Les utilisateurs disent que le skill de calcul de congés « se lance pour rien ». Que faites-vous ?

Vous réécrivez la description de hr-policy-qa. Sur l'ensemble d'entraînement, l'exactitude passe de 0,90 à 0,97 ; sur l'ensemble de validation, de 0,92 à 0,88. Que décidez-vous ?

Exercice. Écrivez cinq requêtes supplémentaires qui font échouer gemini-3.5-flash-lite (demandes d'action proches d'un skill de calcul ou de consultation), ajoutez-les au jeu, puis modifiez une description pour les corriger sans dégrader les 30 autres.

Voir la solution

Exemples de requêtes à null : « Valide la note de frais de Léa dans l'outil », « Envoie le récap de réunion à l'équipe », « Ferme les tickets en doublon », « Annule mes congés de décembre », « Supprime les doublons de ce CSV et renvoie-le ». Ce sont des actions qu'aucun skill n'effectue.

Correction type : ajouter à chaque description concernée une phrase « It computes / drafts only and never submits, approves, sends or closes anything ». Relancez MODEL=gemini-3.5-flash-lite python run.py eval-trigger --runs 3, comparez les erreurs avant et après, et vérifiez que le rappel sur les 24 positifs reste à 1,0. Si la correction ne tient que pour le modèle léger, gardez-la quand même : la description sert tous les clients.

  • Je sais construire un jeu de déclenchement avec quasi-homonymes
  • Je sais distinguer exactitude, précision, rappel et faux déclenchements
  • Je sais lire un score parfait avec prudence
  • Je sais transformer l'éval en porte de CI
Siguiente