Utiliser des évaluateurs au niveau de l’exécution

Si les évaluateurs classiques notent chaque enregistrement individuellement, les évaluateurs d’exécution agissent sur l’ensemble complet des résultats après que tous les enregistrements ont été traités. Utilisez-les pour les assertions globales, les métriques agrégées comme le F1 ou les analyses inter-enregistrements.

Évaluateur d’exécution de base

Un évaluateur d’exécution reçoit un RunEvaluatorContext contenant tous les enregistrements, les statistiques et les métadonnées :

import asyncio
import os

from mistralai.observability import (
    Evaluation, Evaluator, Mistral, RunEvaluator, RunEvaluatorContext,
    ScorerContext, System, TaskContext,
)

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

def accuracy_scorer(ctx: ScorerContext) -> int:
    return 1 if ctx.input_record["expected"].lower() in str(ctx.output).lower() else 0

def accuracy_gate(ctx: RunEvaluatorContext):
    return ctx.statistics["accuracy"].avg > 0.8

async def task(ctx: TaskContext) -> str:
    r = await client.chat.complete_async(
        model="mistral-small-latest",
        messages=[{"role": "user", "content": ctx.input_record["prompt"]}],
    )
    return str(r.choices[0].message.content)

async def main():
    run = await client.evaluation.run(
        evaluation=Evaluation(name="Gated Eval"),
        dataset=dataset,
        task=task,
        evaluators=[Evaluator(name="accuracy", description="1 if the expected answer appears in the output.", scorer=accuracy_scorer)],
        run_evaluators=[
            RunEvaluator(
                name="accuracy_above_80pct",
                description="True if average accuracy exceeds 80%.",
                scorer=accuracy_gate,
            ),
        ],
    )
    print(run.run_scores)  # {"accuracy_above_80pct": True}

asyncio.run(main())

Calcul du score F1 avec get_score

L’assistant get_score() extrait les notes individuelles des évaluateurs à partir des enregistrements d’évaluateurs d’exécution :

from mistralai.observability import RunEvaluator, RunEvaluatorContext, Score, get_score

def f1_scorer(ctx: RunEvaluatorContext) -> Score:
    tp = fp = fn = 0
    for record in ctx.records:
        predicted = get_score(record, "predicted_label").value
        expected = get_score(record, "expected_label").value
        if predicted == 1 and expected == 1:
            tp += 1
        elif predicted == 1 and expected == 0:
            fp += 1
        elif predicted == 0 and expected == 1:
            fn += 1

    precision = tp / (tp + fp) if (tp + fp) > 0 else 0
    recall = tp / (tp + fn) if (tp + fn) > 0 else 0
    f1 = 2 * precision * recall / (precision + recall) if (precision + recall) > 0 else 0

    return Score(
        value=f1,
        rationale=f"precision={precision:.2f}, recall={recall:.2f}",
    )

run = await client.evaluation.run(
    # ...
    run_evaluators=[RunEvaluator(name="f1", description="Harmonic mean of precision and recall across all records.", scorer=f1_scorer)],
)

Référence de RunEvaluatorContext

ChampTypeDescription
recordslist[RunEvaluatorRecord]Tous les enregistrements traités avec leurs scores
statisticsdict[str, EvaluatorStatistics]Statistiques agrégées par évaluateur
metadatadict[str, JsonValue]Métadonnées de l’exécution
system`SystemNone`

Ajout d’objectifs

Les évaluateurs d’exécution prenant en charge les objectifs de réussite ou d’échec de la même manière que les évaluateurs classiques :

from mistralai.observability import Goal

RunEvaluator(
    name="f1",
    description="Harmonic mean of precision and recall.",
    scorer=f1_scorer,
    goal=Goal.gte(0.85),
)

Consultez Objectifs pour le guide complet.