Relancer les enregistrements en échec

Une évaluation peut échouer partiellement : une erreur API transitoire, une limite de débit ou un bug dans votre scorer. Plutôt que de relancer toute l'évaluation depuis le début, le SDK permet de relancer uniquement les enregistrements en échec et de mettre à jour les résultats sur place.

Pourquoi c'est important

Pourquoi c'est important

Une exécution d'évaluation typique peut impliquer des centaines ou des milliers d'appels à un LLM. Si cinq enregistrements sur 500 échouent, tout relancer fait perdre du temps et de l'argent. retry_failed_records() identifie les enregistrements qui ont échoué, au niveau de la génération ou du scoring, relance uniquement ceux-ci et met à jour l'exécution d'origine afin de conserver vos résultats au même endroit dans Studio.

workflow de base

workflow de base

import asyncio
import os

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

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

dataset = [
    {"prompt": "Say hello", "expected": "hello"},
    {"prompt": "Say goodbye", "expected": "goodbye"},
]

async def task(ctx: TaskContext):
    response = await client.chat.complete_async(
        model=str(ctx.system.params["model"]),
        messages=[{"role": "user", "content": ctx.input_record["prompt"]}],
    )
    return str(response.choices[0].message.content)

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

async def main():
    system = System(name="mistral-small", params={"model": "mistral-small-latest"})

    # Step 1: run the evaluation
    run = await client.evaluation.run(
        evaluation=Evaluation(name="My Eval"),
        system=system,
        dataset=dataset,
        task=task,
        evaluators=[Evaluator(name="accuracy", scorer=scorer)],
    )

    # Step 2: if some records failed, retry them
    result = await client.evaluation.retry_failed_records(
        run_id=run.run_id,
        dataset=dataset,
        task=task,
        evaluators=[Evaluator(name="accuracy", scorer=scorer)],
        system=system,
    )
    print(f"Retried: {result.retried_count}, Patched: {result.patched_count}")

asyncio.run(main())
Corriger la tâche avant de relancer

Corriger la tâche avant de relancer

Vous n'avez pas à relancer avec la même tâche. Si les échecs sont dus à un bug dans votre code, corrigez-le et transmettez la version corrigée :

# Fix the task, retry only the failed records
async def fixed_task(ctx: TaskContext):
    response = await client.chat.complete_async(
        model=str(ctx.system.params["model"]),
        messages=[{"role": "user", "content": ctx.input_record["prompt"]}],
    )
    return str(response.choices[0].message.content)

result = await client.evaluation.retry_failed_records(
    run_id=run.run_id,
    dataset=dataset,
    task=fixed_task,
    evaluators=[Evaluator(name="accuracy", scorer=scorer)],
    system=system,
)
Les enregistrements en échec ne sont pas notés

Les enregistrements en échec ne sont pas notés

Les évaluateurs ne s'exécutent pas sur une génération en échec, qui est donc absente des statistiques et des objectifs (tout comme un score en échec). Une exécution dont la moitié des enregistrements sont en échec peut quand même afficher une moyenne parfaite. Vérifiez le nombre d'enregistrements en échec avant de lire les scores :

run = await client.evaluation.run(...)
if run.failed_record_count:
    print(f"{run.failed_record_count}/{len(run.output_records)} records failed")

run.show() affiche la même ligne, et le plugin d'évaluation de workflow la renvoie sous la forme de EvalResult.failed_record_count. Cette fonctionnalité nécessite le SDK 0.10.0+.

Ce qui se passe

Ce qui se passe

  1. Studio sélectionne côté serveur les enregistrements à relancer : ceux sans Sortie, ceux dont le nombre de générations diffère de num_generations, ceux dont une génération ou un score a un statut autre que "success", ou ceux auxquels il manque des scores pour les évaluateurs fournis.
  2. Seuls ces enregistrements sont retraités avec la tâche et les évaluateurs fournis.
  3. Les résultats réussis sont ajoutés à l'exécution d'origine.
  4. Si vous passez run_evaluators à cet Appel, leurs scores sont recalculés avec les données mises à jour. Sinon, les scores des évaluateurs de l'exécution ne sont pas recalculés.

L'exécution d'origine dans Studio est mise à jour sur place. Pas d'exécutions en double, pas de nettoyage manuel.

Où apparaissent les enregistrements en échec

Où apparaissent les enregistrements en échec

L'exécution conserve le nombre de ses enregistrements téléchargés et de ceux dont la tâche ou au moins un score a échoué. L'API les expose sous la forme de record_count et failed_record_count.

Studio affiche ce nombre dans la liste des exécutions (par exemple, « 3 en échec »), sur la page de l'exécution, à côté des objectifs, et dans la comparaison d'exécutions. Après une relance ou un nouveau calcul des scores, ce nombre n'inclut que les enregistrements qui échouent encore. Les exécutions créées avant l'ajout de ce compteur ne l'affichent pas tant qu'elles n'ont pas été relancées ou que leurs scores n'ont pas été recalculés.

Référence API

Référence API

client.evaluation.retry_failed_records(...) prend les paramètres suivants :

ParamètreTypeDescription
run_idstrObligatoire. ID de l'exécution contenant les enregistrements en échec.
datasetSequence[Mapping[str, Any]]Obligatoire. Même ensemble de données que celui utilisé dans l'exécution d'origine.
taskTaskFunctionObligatoire. Fonction de tâche, qui peut être une version corrigée.
evaluatorslist[Evaluator]Obligatoire. Évaluateurs à utiliser pour recalculer les scores.
run_evaluatorslist[RunEvaluator]Évaluateurs au niveau de l'exécution à recalculer après la mise à jour.
num_generationsintNombre de générations par enregistrement (par défaut : 1).
systemSystemParamètres système à injecter dans la tâche.
max_concurrencyintNombre maximal de tâches simultanées (par défaut : 10).
upload_batch_sizeintTaille de batch pour télécharger les résultats mis à jour (par défaut : 10).

Elle renvoie un RetryFailedRecordsResult :

ChampTypeDescription
run_idstrID de l'exécution relancée.
retried_countintNombre d'enregistrements relancés.
patched_countintNombre d'enregistrements mis à jour avec succès.
run_scores_recomputedboolIndique si les scores au niveau de l'exécution ont été recalculés.