Passer au contenu principal
Dans Weave, les évaluateurs servent à évaluer les sorties de l’IA et à renvoyer des métriques d’évaluation. Ils prennent la sortie de l’IA, l’analysent et renvoient un dictionnaire de résultats. Les évaluateurs peuvent utiliser vos données d’entrée comme référence si nécessaire et produire également des informations supplémentaires, comme des explications ou le raisonnement issu de l’évaluation.
Les évaluateurs sont transmis à un objet weave.Evaluation pendant l’évaluation. Il existe deux types d’évaluateurs dans Weave :
  1. évaluateurs basés sur des fonctions : fonctions Python simples décorées avec @weave.op.
  2. évaluateurs basés sur des classes : classes Python qui héritent de weave.Scorer pour des évaluations plus complexes.
Les évaluateurs doivent renvoyer un dictionnaire et peuvent renvoyer plusieurs métriques, des métriques imbriquées et des valeurs non numériques, comme du texte renvoyé par un LLM-évaluateur sur son raisonnement.

Créez vos propres évaluateurs

Évaluateurs prêts à l’emploi Bien que ce guide vous montre comment créer des évaluateurs personnalisés, Weave propose plusieurs évaluateurs prédéfinis et évaluateurs SLM locaux que vous pouvez utiliser immédiatement, notamment :

évaluateurs basés sur des fonctions

Il s’agit de fonctions décorées avec @weave.op qui renvoient un dictionnaire. Elles conviennent parfaitement à des évaluations simples comme :
import weave

@weave.op
def evaluate_uppercase(text: str) -> dict:
    return {"text_is_uppercase": text.isupper()}

my_eval = weave.Evaluation(
    dataset=[{"text": "HELLO WORLD"}],
    scorers=[evaluate_uppercase]
)
Lors de l’exécution de l’évaluation, evaluate_uppercase vérifie si le texte est entièrement en majuscules.

Scorers basés sur des classes

Pour des évaluations plus avancées, en particulier lorsque vous devez suivre des métadonnées supplémentaires associées au scorer, essayer différents prompts pour vos évaluateurs LLM ou effectuer plusieurs appels de fonction, vous pouvez utiliser la classe Scorer.Exigences :
  1. Héritez de weave.Scorer.
  2. Définissez une méthode score décorée avec @weave.op.
  3. La méthode score doit renvoyer un dictionnaire.
Exemple :
import weave
from openai import OpenAI
from weave import Scorer

llm_client = OpenAI()

class SummarizationScorer(Scorer):
    model_id: str = "gpt-4o"
    system_prompt: str = "Evaluate whether the summary is good."

    @weave.op
    def some_complicated_preprocessing(self, text: str) -> str:
        processed_text = "Original text: \n" + text + "\n"
        return processed_text

    @weave.op
    def call_llm(self, summary: str, processed_text: str) -> dict:
        res = llm_client.chat.completions.create(
            messages=[
                {"role": "system", "content": self.system_prompt},
                {"role": "user", "content": (
                    f"Analyze how good the summary is compared to the original text."
                    f"Summary: {summary}\n{processed_text}"
                )}])
        return {"summary_quality": res}

    @weave.op
    def score(self, output: str, text: str) -> dict:
        """Évalue la qualité du résumé.

        Arguments:
            output: Le résumé généré par un système d'IA
            text: Le texte original à résumer
        """
        processed_text = self.some_complicated_preprocessing(text)
        eval_result = self.call_llm(summary=output, processed_text=processed_text)
        return {"summary_quality": eval_result}

evaluation = weave.Evaluation(
    dataset=[{"text": "The quick brown fox jumps over the lazy dog."}],
    scorers=[summarization_scorer])
Cette classe évalue la qualité d’un résumé en le comparant au texte original.

Fonctionnement des évaluateurs

Arguments par mot-clé du scorer

Les évaluateurs peuvent accéder à la fois à la sortie de votre système d’IA et aux données d’entrée de la ligne du jeu de données.
  • Entrée : Si vous voulez que votre scorer utilise des données de la ligne de votre jeu de données, comme une colonne “label” ou “target”, vous pouvez facilement les mettre à sa disposition en ajoutant un argument par mot-clé label ou target à la définition de votre scorer.
Par exemple, si vous vouliez utiliser une colonne appelée “label” de votre jeu de données, votre fonction de scorer (ou votre méthode de classe score) aurait une liste de paramètres comme celle-ci :
@weave.op
def my_custom_scorer(output: str, label: int) -> dict:
    ...
Lorsqu’une Evaluation Weave est exécutée, la sortie du système d’IA est transmise au paramètre output. L’Evaluation essaie aussi automatiquement de faire correspondre les noms des arguments supplémentaires du scorer avec les colonnes de votre jeu de données. Si vous ne pouvez pas personnaliser les arguments de votre scorer ou les colonnes du jeu de données, vous pouvez utiliser un mapping de colonnes — voir ci-dessous pour en savoir plus.
  • Sortie : Incluez un paramètre output dans la signature de la fonction de votre scorer pour accéder à la sortie du système d’IA.

Mapper les noms de colonnes avec column_map

Il arrive que les noms d’arguments des méthodes score ne correspondent pas aux noms de colonnes de votre jeu de données. Vous pouvez résoudre ce problème avec column_map.Si vous utilisez un scorer basé sur une classe, transmettez un dictionnaire à l’attribut column_map de Scorer lorsque vous initialisez votre classe de scorer. Ce dictionnaire fait correspondre les noms d’arguments de votre méthode score aux noms de colonnes du jeu de données, selon le format suivant : {scorer_keyword_argument: dataset_column_name}.Exemple :
import weave
from weave import Scorer

# Un jeu de données contenant des articles de presse à résumer
dataset = [
    {"news_article": "The news today was great...", "date": "2030-04-20", "source": "Bright Sky Network"},
    ...
]

# Classe de scorer
class SummarizationScorer(Scorer):

    @weave.op
    def score(self, output, text) -> dict:
        """
            output: résumé généré par un système de résumé par LLM
            text: le texte à résumer
        """
        ...  # évaluer la qualité du résumé

# créer un scorer avec un mapping de colonnes associant l'argument `text` à la colonne de données `news_article`
scorer = SummarizationScorer(column_map={"text" : "news_article"})
Désormais, l’argument text de la méthode score recevra les données de la colonne news_article du jeu de données.Notes :
  • Une autre option équivalente pour mapper vos colonnes consiste à sous-classer Scorer et à surcharger la méthode score en faisant explicitement correspondre les colonnes.
import weave
from weave import Scorer

class MySummarizationScorer(SummarizationScorer):

    @weave.op
    def score(self, output: str, news_article: str) -> dict:  # Ajout d'annotations de type
        # surcharger la méthode score et faire correspondre les colonnes manuellement
        return super().score(output=output, text=news_article)

Accéder aux variables de vos ops dans les prompts de scoring

Dans les prompts de scoring pour les scorers LLM-as-a-judge, vous pouvez faire référence à des variables de votre op. Ces valeurs sont automatiquement extraites lorsque le scorer s’exécute. Pour une fonction comme :
@weave.op
def summarize_article(article: str, max_length: int) -> str:
    # Votre logique de résumé ici
    return summary
Les variables suivantes sont disponibles :
VariableDescription
{article}La valeur de l’argument d’entrée article
{max_length}La valeur de l’argument d’entrée max_length
{inputs}Un dictionnaire JSON de tous les arguments d’entrée
{output}Le résultat renvoyé par votre op
Exemple de prompt d’évaluation :
Évaluez la qualité de ce résumé.

Article original : {article}
Résumé : {output}
Longueur maximale demandée : {max_length}

Évaluez le résumé sur une échelle de 1 à 10 selon les critères suivants :
- Exactitude : représente-t-il fidèlement l'article ?
- Exhaustivité : couvre-t-il les points clés ?
- Concision : est-il suffisamment bref ?

Renvoyez un objet JSON avec votre note et votre justification.

Résumé final du scorer

Pendant l’évaluation, le scorer est calculé pour chaque ligne de votre jeu de données. Pour produire un score final pour l’évaluation, nous utilisons auto_summarize, qui dépend du type de retour de la sortie.
  • Les moyennes sont calculées pour les colonnes numériques
  • Le nombre et la proportion pour les colonnes booléennes
  • Les autres types de colonnes sont ignorés
Vous pouvez redéfinir la méthode summarize de la classe Scorer et fournir votre propre manière de calculer les scores finaux. La fonction summarize attend :
  • Un seul paramètre, score_rows : il s’agit d’une liste de dictionnaires, où chaque dictionnaire contient les scores renvoyés par la méthode score pour une ligne de votre jeu de données.
  • Elle doit renvoyer un dictionnaire contenant les scores récapitulatifs.
Pourquoi est-ce utile ?Lorsque vous devez scorer toutes les lignes avant de pouvoir déterminer la valeur finale du score pour le jeu de données.
class MyBinaryScorer(Scorer):
    """
    Renvoie True si la sortie complète correspond à la cible, sinon False
    """

    @weave.op
    def score(self, output, target):
        return {"match": output == target}

    def summarize(self, score_rows: list) -> dict:
        full_match = all(row["match"] for row in score_rows)
        return {"full_match": full_match}
Dans cet exemple, auto_summarize aurait renvoyé par défaut le nombre et la proportion de valeurs True.
Si vous voulez en savoir plus, consultez l’implémentation de CorrectnessLLMJudge.

Appliquer des évaluateurs à un appel

Pour appliquer des évaluateurs à vos ops Weave, vous devez utiliser la méthode .call(), qui vous donne accès à la fois au résultat de l’opération et à ses informations de suivi. Cela vous permet d’associer les résultats des évaluateurs à des appels spécifiques dans la base de données de Weave. Pour plus d’informations sur l’utilisation de la méthode .call(), consultez le guide Calling Ops.
Voici un exemple simple :
# Obtenir à la fois le résultat et l'objet Call
result, call = generate_text.call("Say hello")

# Appliquer un scorer
score = await call.apply_scorer(MyScorer())
Vous pouvez également appliquer plusieurs évaluateurs au même appel :
# Appliquer plusieurs évaluateurs en parallèle
await asyncio.gather(
    call.apply_scorer(quality_scorer),
    call.apply_scorer(toxicity_scorer)
)
Notes :
  • Les résultats des évaluateurs sont automatiquement stockés dans la base de données de Weave
  • Les évaluateurs s’exécutent de manière asynchrone une fois l’opération principale terminée
  • Vous pouvez consulter les résultats des évaluateurs dans l’UI ou les interroger via l’API
Pour plus d’informations sur l’utilisation des évaluateurs comme garde-fous ou moniteurs, y compris les bonnes pratiques en production et des exemples complets, consultez notre guide Guardrails and Monitors.

Utiliser preprocess_model_input

Vous pouvez utiliser le paramètre preprocess_model_input pour modifier les exemples du jeu de données avant qu’ils n’atteignent votre modèle pendant l’évaluation. Pour plus d’informations sur l’utilisation et pour un exemple, voir Utiliser preprocess_model_input pour mettre en forme les lignes du jeu de dataset avant l’évaluation.

Analyse des scores

Dans cette section, nous vous montrons comment analyser les scores pour un seul Appel, plusieurs appels et tous les appels évalués par un scorer spécifique.

Analyser les scores d’un Appel unique

API pour un appel unique

Pour récupérer les appels associés à un appel donné, vous pouvez utiliser la méthode get_call.
client = weave.init("my-project")

# Obtenir un appel unique
call = client.get_call("call-uuid-here")

# Obtenir le feedback de l'appel qui contient les scores
feedback = list(call.feedback)

UI d’un appel individuel

Onglet Scores d’un appel
Les scores d’un appel individuel s’affichent dans le panneau des détails de l’appel, sous l’onglet « Scores ».

Analyser les scores de plusieurs Appels

API des appels multiples

Pour récupérer plusieurs appels, vous pouvez utiliser la méthode get_calls.
client = weave.init("my-project")

# Obtenir plusieurs appels - utilisez les filtres souhaités et incluez les retours
calls = client.get_calls(..., include_feedback=True)

# Itérer sur les appels et accéder aux retours contenant les scores
for call in calls:
    feedback = list(call.feedback)

Interface des appels multiples

Onglet Appels multiples
Les scores de plusieurs appels sont affichés dans le tableau des traces, dans la colonne « Scores ».

Analyser tous les Appels évalués par un scorer spécifique

API de tous les appels par scorer

Pour récupérer tous les appels auxquels un scorer spécifique a attribué un score, vous pouvez utiliser la méthode get_calls.
client = weave.init("my-project")

# Pour obtenir tous les appels évalués par n'importe quelle version d'un scorer, utilisez le nom du scorer (généralement le nom de la classe)
calls = client.get_calls(scored_by=["MyScorer"], include_feedback=True)

# Pour obtenir tous les appels évalués par une version spécifique d'un scorer, utilisez la référence complète
# Les références peuvent être obtenues depuis l'objet scorer ou via l'interface utilisateur.
calls = client.get_calls(scored_by=[myScorer.ref.uri()], include_feedback=True)

# Parcourir les appels et accéder aux retours qui contiennent les scores
for call in calls:
    feedback = list(call.feedback)

Tous les appels d’un Scorer dans l’UI

Enfin, si vous souhaitez voir tous les appels évalués par un Scorer, accédez à l’onglet Scorers dans l’UI et sélectionnez l’onglet “Programmatic Scorer”. Cliquez sur votre Scorer pour ouvrir la page de détails du Scorer.
Page de détails du Scorer
Ensuite, cliquez sur le bouton View Traces sous Scores pour voir tous les appels évalués par votre Scorer.
Appels filtrés sur la version du Scorer
Par défaut, cela affiche la version sélectionnée du Scorer. Vous pouvez supprimer le filtre de version pour voir tous les appels évalués par n’importe quelle version du Scorer.
Appels filtrés sur le nom du Scorer