Évaluation

L'évaluation est une forme de test qui vous aide à valider les réponses de votre LLM et à vous assurer qu'elles répondent à vos critères de qualité.

Firebase Genkit est compatible avec des outils d'évaluation tiers via des plug-ins, associés à de puissantes fonctionnalités d'observabilité qui fournissent des insights sur l'état d'exécution de vos applications LLM. Les outils Genkit vous aident à extraire automatiquement des données, y compris des entrées, des sorties et des informations à partir d'étapes intermédiaires pour évaluer la qualité de bout en bout des réponses du LLM, ainsi que pour comprendre les performances des composants de votre système.

Types d'évaluation

Genkit est compatible avec deux types d'évaluation:

  • Évaluation basée sur l'inférence: ce type d'évaluation s'exécute sur un ensemble d'entrées prédéterminées, en évaluant la qualité des sorties correspondantes.

    Il s'agit du type d'évaluation le plus courant, adapté à la plupart des cas d'utilisation. Cette approche teste la sortie réelle d'un système pour chaque exécution d'évaluation.

    Vous pouvez effectuer l'évaluation de la qualité manuellement en inspectant visuellement les résultats. Vous pouvez également automatiser l'évaluation à l'aide d'une métrique d'évaluation.

  • Évaluation brute: ce type d'évaluation évalue directement la qualité des entrées sans aucune inférence. Cette approche est généralement utilisée avec une évaluation automatisée à l'aide de métriques. Tous les champs obligatoires pour l'évaluation (par exemple, input, context, output et reference) doivent être présents dans l'ensemble de données d'entrée. Cela est utile lorsque vous disposez de données provenant d'une source externe (par exemple, collectées à partir de vos traces de production) et que vous souhaitez obtenir une mesure objective de la qualité des données collectées.

    Pour en savoir plus, consultez la section Utilisation avancée de cette page.

Cette section explique comment effectuer une évaluation basée sur l'inférence à l'aide de Genkit.

Guide de démarrage rapide

Prérequis

  1. Utilisez une application Genkit existante ou créez-en une en suivant notre guide de [démarrage](get-started.md).
  2. Ajoutez le code suivant pour définir une application de classification RAG simple à évaluer. Pour ce guide, nous utilisons un récupérateur factice qui renvoie toujours les mêmes documents.
    import { genkit, z, Document } from "genkit";
    import {
      googleAI,
      gemini15Flash,
    } from "@genkit-ai/googleai";
    
    // Initialize Genkit
    export const ai = genkit ({
      plugins: [
        googleAI(),
      ]
    });
    
    // Dummy retriever that always returns the same docs
    export const dummyRetriever = ai.defineRetriever(
      {
        name: "dummyRetriever",
      },
      async (i) => {
        const facts = [
          "Dog is man's best friend", 
          "Dogs have evolved and were domesticated from wolves",
        ];
        // Just return facts as documents.
        return { documents: facts.map((t) => Document.fromText(t)) };
      }
    );
    
    // A simple question-answering flow
    export const qaFlow = ai.defineFlow({
        name: 'qaFlow',
        inputSchema: z.string(),
        outputSchema: z.string(),
      },
      async (query) => {
        const factDocs = await ai.retrieve({
          retriever: dummyRetriever,
          query,
        });
    
        const llmResponse = await ai.generate({
          model: gemini15Flash,
          prompt: `Answer this question with the given context ${query}`,
          docs: factDocs,
        });
        return llmResponse.text;
      }
    );
  3. (Facultatif) Ajoutez des métriques d'évaluation à votre application à utiliser lors de l'évaluation. Ce guide utilise la métrique MALICIOUSNESS du plug-in genkitEval.
    import { genkitEval, GenkitMetric } from "@genkit-ai/evaluator";
    import { gemini15Pro } from "@genkit-ai/googleai";
    
    export const ai = genkit ({
      plugins: [
        ...
        // Add this plugin to your Genkit initialization block
        genkitEval({
          judge: gemini15Pro,
          metrics: [GenkitMetric.MALICIOUSNESS],
        }),
      ]
    });
    Remarque:La configuration ci-dessus nécessite l'installation du package @genkit-ai/evaluator.
    npm install @genkit-ai/evaluator
  4. Démarrez votre application Genkit.
    genkit start -- 

Créer un ensemble de données

Créez un ensemble de données pour définir les exemples que vous souhaitez utiliser pour évaluer votre flux.

  1. Accédez à l'UI de développement à l'adresse http://localhost:4000, puis cliquez sur le bouton Datasets (Ensembles de données) pour ouvrir la page "Datasets" (Ensembles de données).

  2. Cliquez sur le bouton Créer un ensemble de données pour ouvrir la boîte de dialogue de création d'un ensemble de données.

    a. Indiquez un datasetId pour votre nouvel ensemble de données. Ce guide utilise myFactsQaDataset.

    b. Sélectionnez le type d'ensemble de données Flow.

    c. Laissez le champ de cible de validation vide, puis cliquez sur Enregistrer.

  3. La page de votre nouvel ensemble de données s'affiche, avec un ensemble de données vide. Ajoutez-y des exemples en procédant comme suit:

    a. Cliquez sur le bouton Ajouter un exemple pour ouvrir le panneau de l'éditeur d'exemples.

    b. Seul le champ input est obligatoire. Saisissez "Who is man's best friend?" dans le champ input, puis cliquez sur Enregistrer pour ajouter l'exemple has à votre ensemble de données.

    c. Répétez les étapes (a) et (b) plusieurs fois pour ajouter d'autres exemples. Ce guide ajoute les exemples d'entrées suivants à l'ensemble de données:

    "Can I give milk to my cats?"
    "From which animals did dogs evolve?"
    

    À la fin de cette étape, votre ensemble de données doit contenir trois exemples, avec les valeurs mentionnées ci-dessus.

Exécuter l'évaluation et afficher les résultats

Pour commencer à évaluer le flux, cliquez sur le bouton Exécuter une nouvelle évaluation sur la page de votre ensemble de données. Vous pouvez également lancer une nouvelle évaluation dans l'onglet Évaluations.

  1. Sélectionnez la case d'option Flow pour évaluer un flux.

  2. Sélectionnez qaFlow comme flux cible à évaluer.

  3. Sélectionnez myFactsQaDataset comme ensemble de données cible à utiliser pour l'évaluation.

  4. (Facultatif) Si vous avez installé une métrique d'évaluation à l'aide de plug-ins Genkit, vous pouvez afficher ces métriques sur cette page. Sélectionnez les métriques que vous souhaitez utiliser pour cette exécution d'évaluation. Cette étape est entièrement facultative: si vous l'ignorez, les résultats de l'exécution d'évaluation seront toujours renvoyés, mais sans métriques associées.

  5. Enfin, cliquez sur Exécuter l'évaluation pour lancer l'évaluation. En fonction du flux que vous testez, cette opération peut prendre un certain temps. Une fois l'évaluation terminée, un message de réussite s'affiche avec un lien permettant d'afficher les résultats. Cliquez sur le lien pour accéder à la page Détails de l'évaluation.

Vous pouvez consulter les détails de votre évaluation sur cette page, y compris l'entrée d'origine, le contexte extrait et les métriques (le cas échéant).

Concepts fondamentaux

Terminologie

  • Évaluation: processus qui évalue les performances du système. Dans Genkit, un tel système est généralement une primitive Genkit, comme un flux ou un modèle. Une évaluation peut être automatisée ou manuelle (évaluation humaine).

  • Inférence groupée L'inférence consiste à exécuter une entrée sur un flux ou un modèle pour obtenir la sortie correspondante. L'inférence groupée consiste à effectuer des inférences sur plusieurs entrées simultanément.

  • Métrique Une métrique d'évaluation est un critère sur lequel une inférence est évaluée. Il peut s'agir, par exemple, de la précision, de la fidélité, de la malveillance, de la langue de la sortie, etc.

  • Ensemble de données Un ensemble de données est un ensemble d'exemples à utiliser pour l'évaluation basée sur l'inférence. Un ensemble de données se compose généralement de champs input et reference facultatifs. Le champ reference n'affecte pas l'étape d'inférence de l'évaluation, mais il est transmis tel quel à toutes les métriques d'évaluation. Dans Genkit, vous pouvez créer un ensemble de données via l'interface utilisateur de développement. Il existe deux types d'ensembles de données dans Genkit: les ensembles de données Flow et les ensembles de données Model.

Validation de schéma

Selon le type, les ensembles de données sont compatibles avec la validation de schéma dans l'interface utilisateur de développement:

  • Les ensembles de données de flux permettent de valider les champs input et reference de l'ensemble de données par rapport à un flux dans l'application Genkit. La validation de schéma est facultative et n'est appliquée que si un schéma est spécifié sur le flux cible.

  • Les ensembles de données de modèle ont un schéma implicite, qui accepte les types d'entrée string et GenerateRequest. La validation de chaîne permet d'évaluer facilement des requêtes textuelles simples, tandis que GenerateRequest offre un contrôle complet pour les cas d'utilisation avancés (par exemple, en fournissant des paramètres de modèle, l'historique des messages, des outils, etc.). Vous trouverez le schéma complet de GenerateRequest dans notre documentation de référence de l'API.

Évaluateurs acceptés

Évaluateurs Genkit

Genkit inclut un petit nombre d'évaluateurs natifs, inspirés des RAGAS, pour vous aider à vous lancer:

  • Fidélité : mesure la cohérence factuelle de la réponse générée par rapport au contexte donné
  • Pertinence de la réponse : évalue la pertinence de la réponse générée par rapport à l'invite donnée
  • Malveillance : mesure si la sortie générée a pour but de tromper, de nuire ou d'exploiter

Plug-ins d'évaluation

Genkit est compatible avec des évaluateurs supplémentaires via des plug-ins, comme les évaluateurs rapides Vertex, auxquels vous pouvez accéder via le plug-in VertexAI.

Utilisation avancée

Évaluation à l'aide de la CLI

La CLI Genkit fournit une API riche pour effectuer des évaluations. Cela est particulièrement utile dans les environnements où l'UI de développement n'est pas disponible (par exemple, dans un workflow CI/CD).

La CLI Genkit fournit trois commandes d'évaluation principales: eval:flow, eval:extractData et eval:run.

Commande eval:flow

La commande eval:flow exécute une évaluation basée sur l'inférence sur un ensemble de données d'entrée. Cet ensemble de données peut être fourni sous forme de fichier JSON ou en référençant un ensemble de données existant dans votre environnement d'exécution Genkit.

# Referencing an existing dataset
genkit eval:flow qaFlow --input myFactsQaDataset
# or, using a dataset from a file
genkit eval:flow qaFlow --input testInputs.json

Ici, testInputs.json doit être un tableau d'objets contenant un champ input et un champ reference facultatif, comme ci-dessous:

[
  {
    "input": "What is the French word for Cheese?",
  },
  {
    "input": "What green vegetable looks like cauliflower?",
    "reference": "Broccoli"
  }
]

Si votre flux nécessite une authentification, vous pouvez la spécifier à l'aide de l'argument --context:

genkit eval:flow qaFlow --input testInputs.json --context '{"auth": {"email_verified": true}}'

Par défaut, les commandes eval:flow et eval:run utilisent toutes les métriques disponibles pour l'évaluation. Pour exécuter sur un sous-ensemble des évaluateurs configurés, utilisez l'option --evaluators et fournissez une liste d'évaluateurs par nom, séparés par une virgule:

genkit eval:flow qaFlow --input testInputs.json --evaluators=genkitEval/maliciousness,genkitEval/answer_relevancy

Vous pouvez consulter les résultats de votre exécution d'évaluation dans l'UI de développement à l'adresse localhost:4000/evaluate.

Commandes eval:extractData et eval:run

Pour prendre en charge l'évaluation brute, Genkit fournit des outils permettant d'extraire des données à partir de traces et d'exécuter des métriques d'évaluation sur les données extraites. Cela est utile, par exemple, si vous utilisez un autre framework pour l'évaluation ou si vous collectez des inférences à partir d'un autre environnement pour tester localement la qualité des sorties.

Vous pouvez exécuter votre flux Genkit par lot et ajouter un libellé unique à l'exécution, qui peut ensuite être utilisé pour extraire un ensemble de données d'évaluation. Un ensemble de données d'évaluation brut est un ensemble d'entrées pour les métriques d'évaluation, sans exécuter d'inférence préalable.

Exécutez votre flux sur vos entrées de test:

genkit flow:batchRun qaFlow testInputs.json --label firstRunSimple

Extrayez les données d'évaluation:

genkit eval:extractData qaFlow --label firstRunSimple --output factsEvalDataset.json

Les données exportées ont un format différent de celui de l'ensemble de données présenté précédemment. En effet, ces données sont destinées à être utilisées directement avec les métriques d'évaluation, sans aucune étape d'inférence. Voici la syntaxe des données extraites.

Array<{
  "testCaseId": string,
  "input": any,
  "output": any,
  "context": any[],
  "traceIds": string[],
}>;

L'extracteur de données localise automatiquement les récupérateurs et ajoute les documents produits au tableau de contexte. Vous pouvez exécuter des métriques d'évaluation sur cet ensemble de données extrait à l'aide de la commande eval:run.

genkit eval:run factsEvalDataset.json

Par défaut, eval:run s'exécute sur tous les évaluateurs configurés. Comme pour eval:flow, les résultats de eval:run s'affichent sur la page d'évaluation de l'interface utilisateur du développeur, située à l'adresse localhost:4000/evaluate.

Extracteurs personnalisés

Genkit fournit une logique par défaut raisonnable pour extraire les champs nécessaires (input, output et context) lors d'une évaluation. Toutefois, vous constaterez peut-être que vous avez besoin de plus de contrôle sur la logique d'extraction de ces champs. Genkit est compatible avec les extracteurs personnalisés pour y parvenir. Vous pouvez fournir des extracteurs personnalisés à utiliser dans les commandes eval:extractData et eval:flow.

Tout d'abord, comme étape préparatoire, introduisez une étape auxiliaire dans notre exemple qaFlow:

export const qaFlow = ai.defineFlow({
    name: 'qaFlow',
    inputSchema: z.string(),
    outputSchema: z.string(),
  },
  async (query) => {
    const factDocs = await ai.retrieve({
      retriever: dummyRetriever,
      query,
    });
    const factDocsModified = await ai.run('factModified', async () => {
        // Let us use only facts that are considered silly. This is a 
        // hypothetical step for demo purposes, you may perform any 
        // arbitrary task inside a step and reference it in custom 
        // extractors.
        //
        // Assume you have a method that checks if a fact is silly
        return factDocs.filter(d => isSillyFact(d.text));
    });

    const llmResponse = await ai.generate({
      model: gemini15Flash,
      prompt: `Answer this question with the given context ${query}`,
      docs: factDocsModified,
    });
    return llmResponse.text;
  }
);

Ensuite, configurez un extracteur personnalisé pour utiliser la sortie de l'étape factModified lors de l'évaluation de ce flux.

Si vous ne disposez pas d'un fichier tools-config pour configurer les extracteurs personnalisés, ajoutez-en un nommé genkit-tools.conf.js à la racine de votre projet.

cd /path/to/your/genkit/app
touch genkit-tools.conf.js

Dans le fichier de configuration des outils, ajoutez le code suivant:

module.exports = {
  evaluators: [
    {
      actionRef: '/flow/qaFlow',
      extractors: {
        context: { outputOf: 'factModified' },
      },
    },
  ],
};

Cette configuration remplace les extracteurs par défaut des outils de Genkit, en modifiant spécifiquement ce qui est considéré comme context lors de l'évaluation de ce flux.

L'exécution de l'évaluation révèle à nouveau que le contexte est maintenant renseigné en tant que résultat de l'étape factModified.

genkit eval:flow qaFlow --input testInputs.json

Les extracteurs d'évaluation sont spécifiés comme suit:

  • Le champ evaluators accepte un tableau d'objets EvaluatorConfig, qui sont définis par flowName.
  • extractors est un objet qui spécifie les forçages de l'extracteur. Les clés actuellement acceptées dans extractors sont [input, output, context]. Voici les types de valeurs acceptés :
    • string : doit être un nom d'étape, spécifié sous forme de chaîne. La sortie de cette étape est extraite pour cette clé.
    • { inputOf: string } ou { outputOf: string } : ces objets représentent des canaux spécifiques (entrée ou sortie) d'une étape. Par exemple, { inputOf: 'foo-step' } extrait l'entrée de l'étape foo-step pour cette clé.
    • (trace) => string; : pour plus de flexibilité, vous pouvez fournir une fonction qui accepte une trace Genkit et renvoie une valeur de type any, et spécifier la logique d'extraction dans cette fonction. Consultez genkit/genkit-tools/common/src/types/trace.ts pour connaître le schéma TraceData exact.

Remarque:Les données extraites pour tous ces extracteurs correspondent au type de l'extracteur. Par exemple, si vous utilisez context: { outputOf: 'foo-step' } et que foo-step renvoie un tableau d'objets, le contexte extrait est également un tableau d'objets.

Synthétiser des données de test à l'aide d'un LLM

Voici un exemple de flux qui utilise un fichier PDF pour générer des questions potentielles des utilisateurs.

import { genkit, z } from "genkit";
import { googleAI, gemini15Flash } from "@genkit-ai/googleai";
import { chunk } from "llm-chunk"; // npm i llm-chunk
import path from "path";
import { readFile } from "fs/promises";
import pdf from "pdf-parse"; // npm i pdf-parse

const ai = genkit({ plugins: [googleAI()] });

const chunkingConfig = {
  minLength: 1000, // number of minimum characters into chunk
  maxLength: 2000, // number of maximum characters into chunk
  splitter: "sentence", // paragraph | sentence
  overlap: 100, // number of overlap chracters
  delimiters: "", // regex for base split method
} as any;

async function extractText(filePath: string) {
  const pdfFile = path.resolve(filePath);
  const dataBuffer = await readFile(pdfFile);
  const data = await pdf(dataBuffer);
  return data.text;
}

export const synthesizeQuestions = ai.defineFlow(
  {
    name: "synthesizeQuestions",
    inputSchema: z.string().describe("PDF file path"),
    outputSchema: z.array(z.string()),
  },
  async (filePath) => {
    filePath = path.resolve(filePath);
    // `extractText` loads the PDF and extracts its contents as text.
    const pdfTxt = await ai.run("extract-text", () => extractText(filePath));

    const chunks = await ai.run("chunk-it", async () =>
      chunk(pdfTxt, chunkingConfig)
    );

    const questions: string[] = [];
    for (var i = 0; i < chunks.length; i++) {
      const qResponse = await ai.generate({
        model: gemini15Flash,
        prompt: {
          text: `Generate one question about the text below: ${chunks[i]}`,
        },
      });
      questions.push(qResponse.text);
    }
    return questions;
  }
);

Vous pouvez ensuite utiliser cette commande pour exporter les données dans un fichier et les utiliser à des fins d'évaluation.

genkit flow:run synthesizeQuestions '"my_input.pdf"' --output synthesizedQuestions.json