Passer au contenu principal
Le développement d’applications LLM piloté par l’évaluation vous aide à améliorer systématiquement vos applications LLM en mesurant leur comportement de manière cohérente à l’aide d’exemples sélectionnés avec soin.
Dans Weave, l’objet Evaluation est au cœur du flux de travail et définit :Une fois l’Evaluation définie, vous pouvez l’exécuter sur un objet Model ou sur toute fonction personnalisée contenant la logique de l’application LLM. Chaque appel à .evaluate() déclenche un run d’évaluation. Considérez l’objet Evaluation comme un plan, et chaque run comme une mesure des performances de votre application dans cette configuration.
Pour commencer avec les évaluations, suivez les étapes suivantes :
  1. Créer un objet Evaluation
  2. Définir un jeu de données d’exemples
  3. Définir des fonctions de scoring
  4. Définir un modèle ou une fonction à évaluer
  5. Exécuter l’évaluation
Vous trouverez un exemple complet de code d’évaluation ici. Vous pouvez aussi en apprendre davantage sur les fonctionnalités avancées d’évaluation, comme les vues enregistrées et les évaluations impératives.

1. Créer un objet Evaluation

La création d’un objet Evaluation est la première étape pour définir votre configuration d’évaluation. Une Evaluation se compose de données d’exemple, d’une logique d’évaluation et d’un prétraitement facultatif. Vous l’utiliserez ensuite pour exécuter une ou plusieurs évaluations. Weave prendra chaque exemple, le fera passer par votre application et attribuera un score au résultat à l’aide de plusieurs fonctions de scoring personnalisées. Vous disposerez ainsi d’une vue d’ensemble des performances de votre application, ainsi que d’une UI riche pour examiner en détail les résultats et les scores individuels.

(Facultatif) Nommage personnalisé

Il existe deux types de noms personnalisables dans le flux d’évaluation :

Nommer l’objet Evaluation

Pour nommer l’objet Evaluation lui-même, passez un paramètre evaluation_name à la classe Evaluation. Ce nom vous aide à identifier l’objet Evaluation dans le code et dans les listes de l’interface utilisateur.
evaluation = Evaluation(
    dataset=examples, scorers=[match_score1], evaluation_name="My Evaluation"
)

Nommer des runs d’évaluation individuels

Pour nommer un run d’évaluation spécifique (un appel à evaluate()), utilisez le dictionnaire __weave avec un display_name. Cela détermine ce qui est affiché dans l’interface utilisateur pour ce run.
evaluation = Evaluation(
    dataset=examples, scorers=[match_score1]
)
evaluation.evaluate(model, __weave={"display_name": "My Evaluation Run"})

2. Définir un jeu de données d’exemples de test

Commencez par définir un objet Dataset ou une liste d’exemples, c’est-à-dire une collection d’exemples à évaluer. Ces exemples correspondent souvent à des cas d’échec que vous souhaitez tester, à la manière de tests unitaires en développement piloté par les tests (TDD).
L’exemple suivant montre un jeu de données défini comme une liste de dictionnaires :
examples = [
    {"question": "What is the capital of France?", "expected": "Paris"},
    {"question": "Who wrote 'To Kill a Mockingbird'?", "expected": "Harper Lee"},
    {"question": "What is the square root of 64?", "expected": "8"},
]

3. Définir des fonctions de scoring

Ensuite, créez une ou plusieurs fonctions de scoring. Elles servent à attribuer un score à chaque exemple du Dataset.
Chaque fonction de scoring doit avoir un paramètre output et renvoyer un dictionnaire contenant les scores. Vous pouvez aussi inclure d’autres entrées issues de vos exemples.Les fonctions de scoring doivent avoir un argument mot-clé output, mais les autres arguments sont définis par l’utilisateur et proviennent des exemples du jeu de données. Seules les clés nécessaires seront prises en compte, à partir d’une clé de dictionnaire basée sur le nom de l’argument.
Si votre scorer attend un argument output mais ne le reçoit pas, vérifiez s’il utilise encore l’ancienne clé model_output. Pour corriger cela, mettez à jour votre fonction scorer afin d’utiliser output comme argument mot-clé.
L’exemple de fonction scorer match_score1 ci-dessous utilise la valeur expected du dictionnaire examples pour le scoring.
import weave

# Rassemblez vos exemples
examples = [
    {"question": "What is the capital of France?", "expected": "Paris"},
    {"question": "Who wrote 'To Kill a Mockingbird'?", "expected": "Harper Lee"},
    {"question": "What is the square root of 64?", "expected": "8"},
]

# Définissez une fonction de scoring personnalisée
@weave.op()
def match_score1(expected: str, output: dict) -> dict:
    # C'est ici que vous définissez la logique pour évaluer la sortie du modèle
    return {'match': expected == output['generated_text']}

(Facultatif) Définir une classe Scorer personnalisée

Dans certaines applications, vous pouvez vouloir créer des classes Scorer personnalisées. Par exemple, une classe LLMJudge standardisée avec des paramètres spécifiques (par exemple, modèle de chat, prompt), une logique de scoring propre à chaque ligne et un calcul spécifique du score agrégé.Voir le tutoriel sur la définition d’une classe Scorer dans Model-Based Evaluation of RAG applications pour plus d’informations.

4. Définir un modèle ou une fonction à évaluer

Pour évaluer un Model, appelez evaluate dessus en utilisant une Evaluation. Les Models sont utilisés lorsque vous avez des paramètres avec lesquels vous souhaitez expérimenter et que vous voulez capturer dans Weave.
from weave import Model, Evaluation
import asyncio

class MyModel(Model):
    prompt: str

    @weave.op()
    def predict(self, question: str):
        # c'est ici que vous ajouteriez votre appel LLM et renverriez la sortie
        return {'generated_text': 'Hello, ' + self.prompt}

model = MyModel(prompt='World')

evaluation = Evaluation(
    dataset=examples, scorers=[match_score1]
)
weave.init('intro-example') # commencer à suivre les résultats avec weave
asyncio.run(evaluation.evaluate(model))
Cela exécute predict sur chaque exemple et attribue un score à la sortie à l’aide de chaque fonction de scoring.

(Facultatif) Définir une fonction à évaluer

Vous pouvez également évaluer une fonction personnalisée suivie par @weave.op().
@weave.op
def function_to_evaluate(question: str):
    # c'est ici que vous ajouteriez votre appel LLM et renverriez la sortie
    return  {'generated_text': 'some response'}

asyncio.run(evaluation.evaluate(function_to_evaluate))

5. Lancez l’évaluation

Pour lancer une évaluation, appelez .evaluate() sur l’objet Evaluation.
En supposant un objet Evaluation nommé evaluation et un objet Model à évaluer nommé model, le code suivant lance un run d’évaluation.
asyncio.run(evaluation.evaluate(model))

(Facultatif) Exécuter plusieurs essais

Vous pouvez définir le paramètre trials sur l’objet Evaluation pour exécuter chaque exemple plusieurs fois.
evaluation = Evaluation(
    dataset=examples,
    scorers=[match_score],
    trials=3
)
Le run transmet chaque exemple au modèle trois fois, et chaque run reçoit un score et s’affiche indépendamment dans Weave.

Exemple complet de code d’évaluation

L’exemple de code suivant montre un run d’évaluation complet, du début à la fin. Le dictionnaire examples est utilisé par les fonctions de scoring match_score1 et match_score2 pour évaluer MyModel à partir de la valeur de prompt, ainsi qu’une fonction personnalisée, function_to_evaluate. Les évaluations du Model et de la fonction sont lancées avec asyncio.run(evaluation.evaluate()).
from weave import Evaluation, Model
import weave
import asyncio
weave.init('intro-example')
examples = [
    {"question": "What is the capital of France?", "expected": "Paris"},
    {"question": "Who wrote 'To Kill a Mockingbird'?", "expected": "Harper Lee"},
    {"question": "What is the square root of 64?", "expected": "8"},
]

@weave.op()
def match_score1(expected: str, output: dict) -> dict:
    return {'match': expected == output['generated_text']}

@weave.op()
def match_score2(expected: dict, output: dict) -> dict:
    return {'match': expected == output['generated_text']}

class MyModel(Model):
    prompt: str

    @weave.op()
    def predict(self, question: str):
        # c'est ici que vous ajouteriez votre appel LLM et renverriez la sortie
        return {'generated_text': 'Hello, ' + question + self.prompt}

model = MyModel(prompt='World')
evaluation = Evaluation(dataset=examples, scorers=[match_score1, match_score2])

asyncio.run(evaluation.evaluate(model))

@weave.op()
def function_to_evaluate(question: str):
    # c'est ici que vous ajouteriez votre appel LLM et renverriez la sortie
    return  {'generated_text': 'some response' + question}

asyncio.run(evaluation.evaluate(function_to_evaluate("What is the capitol of France?")))
Visuel des évaluations

Utilisation avancée de l’évaluation

Formater les lignes du jeu de dataset avant d’évaluer

La fonction preprocess_model_input est appliquée uniquement aux entrées avant leur transmission à la fonction de prédiction du modèle. Les fonctions de scorer reçoivent toujours l’exemple original du jeu de données, sans prétraitement.
Le paramètre preprocess_model_input vous permet de transformer les exemples de votre jeu de données avant qu’ils ne soient transmis à votre fonction d’évaluation. Cela est utile lorsque vous devez :
  • Renommer des champs pour qu’ils correspondent aux entrées attendues par votre modèle
  • Transformer les données dans le bon format
  • Ajouter ou supprimer des champs
  • Charger des données supplémentaires pour chaque exemple
Voici un exemple simple montrant comment utiliser preprocess_model_input pour renommer des champs :
import weave
from weave import Evaluation
import asyncio

# Notre jeu de données contient "input_text", mais notre modèle attend "question"
examples = [
    {"input_text": "What is the capital of France?", "expected": "Paris"},
    {"input_text": "Who wrote 'To Kill a Mockingbird'?", "expected": "Harper Lee"},
    {"input_text": "What is the square root of 64?", "expected": "8"},
]

@weave.op()
def preprocess_example(example):
    # Renommer input_text en question
    return {
        "question": example["input_text"]
    }

@weave.op()
def match_score(expected: str, output: dict) -> dict:
    return {'match': expected == output['generated_text']}

@weave.op()
def function_to_evaluate(question: str):
    return {'generated_text': f'Answer to: {question}'}

# Créer l’évaluation avec prétraitement
evaluation = Evaluation(
    dataset=examples,
    scorers=[match_score],
    preprocess_model_input=preprocess_example
)

# Exécuter l’évaluation
weave.init('preprocessing-example')
asyncio.run(evaluation.evaluate(function_to_evaluate))
Dans cet exemple, notre jeu de données contient des exemples avec un champ input_text, mais notre fonction d’évaluation attend un paramètre question. La fonction preprocess_example transforme chaque exemple en renommant ce champ, ce qui permet à l’évaluation de fonctionner correctement.La fonction de prétraitement :
  1. Reçoit l’exemple brut de votre jeu de données
  2. Renvoie un dictionnaire contenant les champs attendus par votre modèle
  3. Est appliquée à chaque exemple avant sa transmission à votre fonction d’évaluation
C’est particulièrement utile lorsque vous travaillez avec des jeux de données externes dont les noms de champs ou les structures diffèrent de ce qu’attend votre modèle.

Utiliser des jeux de données HuggingFace avec les évaluations

Nous améliorons continuellement nos intégrations avec des services et des bibliothèques tiers.En attendant des intégrations plus fluides, vous pouvez utiliser preprocess_model_input comme solution de contournement temporaire pour utiliser des jeux de données HuggingFace dans les évaluations Weave.Voir notre cookbook sur l’utilisation de jeux de données HuggingFace dans les évaluations pour connaître l’approche actuelle.

Vues enregistrées

Vous pouvez enregistrer les configurations, filtres et tris de votre tableau Evals sous forme de vues enregistrées afin d’accéder rapidement à la configuration de votre choix. Vous pouvez configurer les vues enregistrées et y accéder dans l’interface utilisateur ainsi qu’avec le SDK Python. Pour plus d’informations, voir Vues enregistrées.

Évaluations impératives (EvaluationLogger)

Si vous préférez un framework d’évaluation plus souple, consultez EvaluationLogger de Weave. EvaluationLogger est disponible en Python et en TypeScript, et offre davantage de flexibilité pour les flux de travail complexes, tandis que le framework d’évaluation standard apporte plus de structure et d’encadrement.