Découvrez comment créer un pipeline d’évaluation avec Weave Models et Evaluations
Ce tutoriel vous guide dans la création d’un pipeline d’évaluation de bout en bout dans Weave afin que vous puissiez mesurer et suivre la qualité d’une application LLM au fil de vos itérations. Les évaluations vous aident à comparer les modifications à un ensemble cohérent d’exemples et à détecter les régressions avant qu’elles n’atteignent les utilisateurs. Ce tutoriel s’adresse aux développeurs qui créent des applications basées sur des LLM et souhaitent disposer d’une méthode reproductible pour les tester.Weave offre une prise en charge native du suivi des évaluations avec les classes Model et Evaluation. Les API sont conçues pour faire le moins d’hypothèses possible, ce qui les rend flexibles pour un large éventail de cas d’usage.
Créer un jeu de données de référence pour tester les réponses d’un LLM.
Définir une fonction de score pour comparer les sorties du modèle aux sorties attendues.
Exécuter une évaluation qui teste le modèle sur le jeu de données à l’aide de la fonction de score et d’un scorer intégré supplémentaire.
Afficher les résultats de l’évaluation dans l’interface Weave.
À la fin, vous disposerez d’un pipeline d’évaluation opérationnel qui attribue des scores à un modèle d’exemple sur un jeu de données et journalise les résultats vers Weave.
Une fois les bibliothèques en place, l’étape suivante consiste à définir le modèle que vous souhaitez évaluer.Dans Weave, les Models sont des objets qui capturent à la fois le comportement de votre modèle ou agent (logique, prompt, paramètres) et ses métadonnées versionnées (paramètres, code, micro-configuration), afin que vous puissiez le suivre, le comparer, l’évaluer et itérer dessus en toute fiabilité.Lorsque vous instanciez un Model, Weave capture automatiquement sa configuration et son comportement, puis met à jour sa version lorsqu’il change. Vous pouvez ainsi suivre ses performances au fil du temps à mesure que vous l’améliorez.Pour déclarer un Model, créez une sous-classe de Model et implémentez une fonction predict qui prend un exemple en entrée et renvoie la réponse.Le modèle d’exemple suivant utilise OpenAI pour extraire les noms, les couleurs et les saveurs de fruits extraterrestres à partir de phrases d’entrée.
Python
TypeScript
class ExtractFruitsModel(weave.Model): model_name: str prompt_template: str @weave.op() async def predict(self, sentence: str) -> dict: client = openai.AsyncClient() response = await client.chat.completions.create( model=self.model_name, messages=[ {"role": "user", "content": self.prompt_template.format(sentence=sentence)} ], ) result = response.choices[0].message.content if result is None: raise ValueError("No response from model") parsed = json.loads(result) return parsed
// Remarque : weave.Model n'est pas encore pris en charge en TypeScript.// À la place, encapsulez votre fonction de type modèle avec weave.opimport * asweave from 'weave';importOpenAI from 'openai';constopenaiClient = newOpenAI();constmodel =weave.op(async functionmyModel({datasetRow}) { constprompt = `Extract fields ("fruit": <str>, "color": <str>, "flavor") from the following text, as json: ${datasetRow.sentence}`; constresponse = awaitopenaiClient.chat.completions.create({model: 'gpt-3.5-turbo',messages: [{ role: 'user', content:prompt }],response_format: { type: 'json_object' } }); returnJSON.parse(response.choices[0].message.content);});
La classe ExtractFruitsModel hérite de weave.Model, ce qui permet à Weave de suivre l’objet instancié. @weave.op décore la fonction predict pour suivre ses entrées et ses sorties.Vous pouvez instancier des objets Model comme ceci :
Python
TypeScript
# Définissez votre équipe et le nom du projetweave.init('[YOUR-TEAM]/eval_pipeline_quickstart')model = ExtractFruitsModel( model_name='gpt-3.5-turbo-1106', prompt_template='Extract fields ("fruit": <str>, "color": <str>, "flavor": <str>) from the following text, as json: {sentence}')sentence = "There are many fruits that were found on the recently discovered planet Goocrux. There are neoskizzles that grow there, which are purple and taste like candy."print(asyncio.run(model.predict(sentence)))# si vous êtes dans un notebook Jupyter, exécutez :# await model.predict(sentence)
awaitweave.init('eval_pipeline_quickstart');constsentence = "There are many fruits that were found on the recently discovered planet Goocrux. There are neoskizzles that grow there, which are purple and taste like candy.";constresult = awaitmodel({ datasetRow: { sentence } });console.log(result);
Une fois un Model défini, vous avez maintenant besoin d’un jeu de données pour l’évaluer. Un Dataset est une collection d’exemples stockée comme objet Weave. Publier le jeu de données dans Weave le versionne et le rend réutilisable dans plusieurs runs d’évaluation.L’exemple de jeu de données suivant définit trois phrases d’entrée et leurs réponses correctes (labels), puis les met en forme dans un tableau JSON que les fonctions de scoring peuvent lire.Cet exemple construit une liste d’exemples dans le code, mais vous pouvez aussi les journaliser une par une depuis votre application en cours d’exécution.
Python
TypeScript
sentences = ["There are many fruits that were found on the recently discovered planet Goocrux. There are neoskizzles that grow there, which are purple and taste like candy.","Pounits are a bright green color and are more savory than sweet.","Finally, there are fruits called glowls, which have a very sour and bitter taste which is acidic and caustic, and a pale orange tinge to them."]labels = [ {'fruit': 'neoskizzles', 'color': 'purple', 'flavor': 'candy'}, {'fruit': 'pounits', 'color': 'bright green', 'flavor': 'savory'}, {'fruit': 'glowls', 'color': 'pale orange', 'flavor': 'sour and bitter'}]examples = [ {'id': '0', 'sentence': sentences[0], 'target': labels[0]}, {'id': '1', 'sentence': sentences[1], 'target': labels[1]}, {'id': '2', 'sentence': sentences[2], 'target': labels[2]}]
constsentences = [ "There are many fruits that were found on the recently discovered planet Goocrux. There are neoskizzles that grow there, which are purple and taste like candy.", "Pounits are a bright green color and are more savory than sweet.", "Finally, there are fruits called glowls, which have a very sour and bitter taste which is acidic and caustic, and a pale orange tinge to them."];constlabels = [ { fruit: 'neoskizzles', color: 'purple', flavor: 'candy' }, { fruit: 'pounits', color: 'bright green', flavor: 'savory' }, { fruit: 'glowls', color: 'pale orange', flavor: 'sour and bitter' }];constexamples =sentences.map((sentence, i) => ({id:i.toString(),sentence,target:labels[i]}));
Créez ensuite votre jeu de données avec la classe weave.Dataset() et publiez-le :
Maintenant que vous avez un modèle et un jeu de données, vous avez besoin d’un moyen de mesurer les performances du modèle sur chaque exemple. Les fonctions de score comparent l’output du modèle à la cible attendue et produisent les métriques qu’une évaluation rapporte.Lorsque vous utilisez les évaluations Weave, Weave s’attend à recevoir une target à comparer à output. La fonction de score suivante prend deux dictionnaires (target et output) et renvoie un dictionnaire de valeurs booléennes indiquant si la sortie correspond à la cible. Le décorateur @weave.op() permet à Weave de suivre l’exécution de la fonction de score.
Pour plus d’informations sur la création de votre propre fonction de score, consultez le guide Scorers.Dans certaines applications, vous souhaiterez peut-être créer des classes Scorer personnalisées. Par exemple, vous pouvez créer une classe LLMJudge standardisée avec des paramètres spécifiques (comme un modèle de chat ou un prompt), une logique de scoring par ligne spécifique et un calcul de score agrégé. Pour plus d’informations, voir le tutoriel sur la définition d’une classe Scorer dans l’évaluation des applications RAG basée sur des modèles.
Utiliser un évaluateur intégré et exécuter l’évaluation
Avec le modèle, le jeu de données et un évaluateur personnalisé en place, vous êtes prêt à tout intégrer dans un run d’évaluation.En plus des fonctions de score personnalisées, vous pouvez aussi utiliser les évaluateurs intégrés de Weave. Dans l’évaluation suivante, weave.Evaluation() utilise la fonction fruit_name_score définie dans la section précédente ainsi que l’évaluateur intégré MultiTaskBinaryClassificationF1, qui calcule les scores F1.L’exemple suivant exécute une évaluation de ExtractFruitsModel sur le jeu de données fruits à l’aide de ces deux fonctions de score et journalise les résultats dans Weave.
Python
TypeScript
weave.init('eval_pipeline_quickstart')evaluation = weave.Evaluation( name='fruit_eval', dataset=dataset, scorers=[ MultiTaskBinaryClassificationF1(class_names=["fruit", "color", "flavor"]), fruit_name_score ],)print(asyncio.run(evaluation.evaluate(model)))# si vous êtes dans un notebook Jupyter, exécutez :# await evaluation.evaluate(model)
Si vous exécutez ce code depuis un script Python, vous devrez utiliser asyncio.run. En revanche, si vous l’exécutez dans un notebook Jupyter, vous pouvez utiliser directement await.
Pipeline d’évaluation complet dans un script unique :
Python
TypeScript
import jsonimport asyncioimport openaiimport weavefrom weave.scorers import MultiTaskBinaryClassificationF1# Initialiser Weave une seule foisweave.init('eval_pipeline_quickstart')# 1. Définir le modèleclass ExtractFruitsModel(weave.Model): model_name: str prompt_template: str @weave.op() async def predict(self, sentence: str) -> dict: client = openai.AsyncClient() response = await client.chat.completions.create( model=self.model_name, messages=[{"role": "user", "content": self.prompt_template.format(sentence=sentence)}], ) result = response.choices[0].message.content if result is None: raise ValueError("No response from model") return json.loads(result)# 2. Instancier le modèlemodel = ExtractFruitsModel( model_name='gpt-3.5-turbo-1106', prompt_template='Extract fields ("fruit": <str>, "color": <str>, "flavor": <str>) from the following text, as json: {sentence}')# 3. Créer le datasetsentences = ["There are many fruits that were found on the recently discovered planet Goocrux. There are neoskizzles that grow there, which are purple and taste like candy.","Pounits are a bright green color and are more savory than sweet.","Finally, there are fruits called glowls, which have a very sour and bitter taste which is acidic and caustic, and a pale orange tinge to them."]labels = [ {'fruit': 'neoskizzles', 'color': 'purple', 'flavor': 'candy'}, {'fruit': 'pounits', 'color': 'bright green', 'flavor': 'savory'}, {'fruit': 'glowls', 'color': 'pale orange', 'flavor': 'sour and bitter'}]examples = [ {'id': '0', 'sentence': sentences[0], 'target': labels[0]}, {'id': '1', 'sentence': sentences[1], 'target': labels[1]}, {'id': '2', 'sentence': sentences[2], 'target': labels[2]}]dataset = weave.Dataset(name='fruits', rows=examples)weave.publish(dataset)# 4. Définir la fonction de score@weave.op()def fruit_name_score(target: dict, output: dict) -> dict: return {'correct': target['fruit'] == output['fruit']}# 5. Lancer l'évaluationevaluation = weave.Evaluation( name='fruit_eval', dataset=dataset, scorers=[ MultiTaskBinaryClassificationF1(class_names=["fruit", "color", "flavor"]), fruit_name_score ],)print(asyncio.run(evaluation.evaluate(model)))
import * asweave from 'weave';importOpenAI from 'openai';// Initialiser Weave une seule foisawaitweave.init('eval_pipeline_quickstart');// 1. Définir le modèle// Remarque : weave.Model n'est pas encore pris en charge en TypeScript.// À la place, encapsulez votre fonction de type modèle avec weave.opconstopenaiClient = newOpenAI();constmodel =weave.op(async functionmyModel({datasetRow}) { constprompt = `Extract fields ("fruit": <str>, "color": <str>, "flavor": <str>) from the following text, as json: ${datasetRow.sentence}`; constresponse = awaitopenaiClient.chat.completions.create({model: 'gpt-3.5-turbo',messages: [{ role: 'user', content:prompt }],response_format: { type: 'json_object' } }); returnJSON.parse(response.choices[0].message.content);});// 2. Créer le datasetconstsentences = [ "There are many fruits that were found on the recently discovered planet Goocrux. There are neoskizzles that grow there, which are purple and taste like candy.", "Pounits are a bright green color and are more savory than sweet.", "Finally, there are fruits called glowls, which have a very sour and bitter taste which is acidic and caustic, and a pale orange tinge to them."];constlabels = [ { fruit: 'neoskizzles', color: 'purple', flavor: 'candy' }, { fruit: 'pounits', color: 'bright green', flavor: 'savory' }, { fruit: 'glowls', color: 'pale orange', flavor: 'sour and bitter' }];constexamples =sentences.map((sentence, i) => ({id:i.toString(),sentence,target:labels[i]}));constdataset = newweave.Dataset({name: 'fruits',rows:examples});awaitdataset.save();// 3. Définir la fonction de scoreconstfruitNameScorer =weave.op( functionfruitNameScore({target, output}) { return { correct:target.fruit ===output.fruit }; });// 4. Lancer l'évaluationconstevaluation = newweave.Evaluation({name: 'fruit_eval',dataset:dataset,scorers: [fruitNameScorer],});constresults = awaitevaluation.evaluate(model);console.log(results);
Une fois l’évaluation terminée, vous pouvez inspecter chaque prédiction et chaque résultat du scorer dans l’interface Weave. Weave capture automatiquement les traces de chaque prédiction et de chaque score. Cliquez sur le lien affiché par l’évaluation pour consulter les résultats dans l’interface Weave.
Vous disposez maintenant d’un pipeline d’évaluation complet. Pour approfondir les fonctionnalités d’évaluation de Weave, consultez les ressources suivantes :