Aller au contenu principal
Leçon 14 sur 16 · Production — Batch, Optimisation et Observabilité

Évaluations hors ligne : mesurer avant de déployer

Leçon 14 sur 16 Mis à jour le 3 novembre 2026 Avancé
Sur cette page
  1. Passer du cas unitaire à l’échelle
  2. Le modèle mental
  3. Une première évaluation
  4. Des évaluateurs de deux natures
  5. Comparer des versions
  6. Fixer des objectifs
  7. Points clés à retenir

Leçon réécrite le 2 novembre 2026 d’après la documentation Offline evaluations de Mistral : les « Campaigns » de l’ancienne version, et leurs méthodes campaigns.*, n’existent plus ; l’évaluation à grande échelle passe par le SDK d’évaluation mistralai-evaluations, qui fait tourner une tâche sur un dataset, la note avec des évaluateurs et publie les résultats dans Studio. Sources : Offline evaluations · Evaluators · Goals. Complément du 3 novembre : mistralai-evaluations 0.9.1 exige mistralai < 3 et remplace le SDK 3.x par une version 2.x quand on l’installe à côté ; la leçon recommande un environnement dédié (dépendances sur PyPI).

Passer du cas unitaire à l’échelle

Un juge validé sur vingt conversations ne dit encore rien de votre application dans son ensemble. Pour décider si un nouveau prompt, un nouveau modèle ou un nouveau réglage vaut mieux que l’actuel, il faut le mesurer sur un jeu de cas représentatif, toujours le même, et comparer. C’est le rôle des évaluations hors ligne.

Elles sont réservées aux organisations Enterprise, et demandent Python 3.12 ou plus :

pip install mistralai-evaluations

Installez-le dans un environnement à part. La version 0.9.1, la plus récente au 3 novembre 2026, exige mistralai 2.x (mistralai>=2.7.1,<3). Dans un environnement qui contient déjà le SDK 3.x, pip désinstalle celui-ci et installe une version 2.x, sans autre avertissement que ses lignes de sortie : vérifié avec mistralai 3.7.0, remplacé par la 2.10.1. Un environnement virtuel dédié aux évaluations évite de faire régresser votre application.

Le modèle mental

Le SDK suit un enchaînement simple :

Dataset  →  Tâche  →  Évaluateurs  →  Résultats
  • Dataset : une liste d’enregistrements (des dictionnaires) ou un dataset de Studio
  • Tâche : une fonction, de préférence asynchrone, qui reçoit un TaskContext et produit une sortie — c’est le code que vous évaluez
  • Évaluateurs : des fonctions qui reçoivent un ScorerContext et notent chaque sortie
  • Résultats : des statistiques et des scores par enregistrement, affichés dans le terminal et publiés dans Studio

Une première évaluation

import asyncio
import os

from mistralai.evaluations import (
    Evaluation, Evaluator, Goal, Mistral, Project, ScorerContext, System, TaskContext,
)

client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])

dataset = [
    {"ticket": "Je n'arrive plus à me connecter depuis ce matin.", "categorie": "acces"},
    {"ticket": "Ma facture d'octobre compte deux fois le même abonnement.", "categorie": "facturation"},
    {"ticket": "L'export PDF plante dès que le rapport dépasse 50 pages.", "categorie": "bug"},
]


async def tache(ctx: TaskContext) -> str:
    reponse = await client.chat.complete_async(
        model=str(ctx.system.params["model"]),
        messages=[
            {"role": "system", "content": str(ctx.system.params["system_prompt"])},
            {"role": "user", "content": ctx.input_record["ticket"]},
        ],
    )
    return str(reponse.choices[0].message.content)


def exactitude(ctx: ScorerContext) -> int:
    return 1 if ctx.input_record["categorie"] == str(ctx.output).strip().lower() else 0


async def main():
    run = await client.evaluation.run(
        project=Project(name="Tri des tickets"),
        evaluation=Evaluation(name="Exactitude du classement"),
        system=System(name="small-prompt-v1", params={
            "model": "mistral-small-latest",
            "system_prompt": "Classe le ticket : acces, facturation ou bug. Réponds par le seul mot.",
        }),
        dataset=dataset,
        task=tache,
        evaluators=[
            Evaluator(
                name="exactitude",
                description="1 si la catégorie prédite est la bonne, 0 sinon.",
                scorer=exactitude,
                goal=Goal.gte(0.8),
            ),
        ],
    )
    run.show(level="records")


asyncio.run(main())

Les résultats s’affichent dans le terminal et sont publiés dans Studio, sous Observability > Evaluate > Evaluations. Le SDK calcule pour chaque évaluateur moyenne, minimum, maximum et écart type.

Préférez une tâche asynchrone pour les traitements longs : une tâche synchrone tourne sur la boucle d’événements qui envoie aussi les signaux de vie du run à Studio, et un appel bloqué plusieurs minutes peut faire marquer le run comme annulé.

Des évaluateurs de deux natures

Un évaluateur associe un nom, une description facultative, une fonction de notation et, au besoin, un objectif. La fonction peut être :

  • fondée sur des règles : un calcul direct sur la sortie — exact, rapide et gratuit ;
  • un juge LLM : une fonction qui appelle un modèle pour noter ce qui se code mal — utilité, exactitude factuelle, ton.
CONSIGNE_JUGE = """Tu es un correcteur exigeant. Note de 0 à 5 l'utilité de la réponse
pour la demande ci-dessous. Réponds par le seul chiffre.

Demande : {demande}
Réponse : {reponse}
"""


def juge_utilite(ctx: ScorerContext) -> int:
    reponse = client.chat.complete(
        model="mistral-large-latest",
        messages=[{"role": "user", "content": CONSIGNE_JUGE.format(
            demande=ctx.input_record["ticket"], reponse=ctx.output)}],
        temperature=0,
    )
    brut = str(reponse.choices[0].message.content).strip()
    return int(brut[0]) if brut[:1].isdigit() else 0

Les deux natures se mêlent librement dans un même run : passez-les ensemble dans la liste evaluators. Un évaluateur peut aussi rendre une chaîne ou un booléen ; le SDK produit alors une distribution de fréquences plutôt que des moyennes.

Comparer des versions

L’objet System sort la configuration de la tâche : modèle, température, prompt système, ou tout autre réglage, dans un dictionnaire libre. Chaque run enregistre son System, et Studio permet de comparer les runs côte à côte. Pour départager deux prompts ou deux modèles, relancez la même évaluation avec deux System différents, sans toucher au code de la tâche.

Fixer des objectifs

Un objectif transforme un score en verdict PASS ou FAIL : Goal.gte(0.8) exige une moyenne d’au moins 0,8, Goal.lte(...) un plafond, Goal.between(...) un intervalle. Chaque objectif vise la moyenne par défaut, ou une autre statistique avec metric ("min", "max", "std") : Goal.gte(0.8, metric="min") exige que chaque enregistrement atteigne 0,8. C’est ce qui fait d’une évaluation un garde-fou : une nouvelle version qui fait baisser un score sous son objectif ne part pas en production.

Points clés à retenir

  • Les évaluations hors ligne (mistralai-evaluations, Python 3.12+, organisations Enterprise) remplacent les anciennes Campaigns
  • Dataset, tâche, évaluateurs, résultats : client.evaluation.run(...) enchaîne le tout et publie dans Studio
  • Les évaluateurs sont des fonctions : règles exactes ou juges LLM, librement combinés
  • System enregistre la configuration évaluée et permet de comparer les versions
  • Les objectifs (Goal.gte, Goal.lte, Goal.between) donnent des verdicts PASS ou FAIL