Ocena

Oceny to forma testowania, która pomaga weryfikować odpowiedzi LLM i upewniać się, że spełniają one Twoje wymagania dotyczące jakości.

Firebase Genkit obsługuje narzędzia do oceny innych firm za pomocą wtyczek oraz zaawansowanych funkcji obserwowalności, które zapewniają wgląd w stan aplikacji korzystających z LLM w czasie działania. Narzędzia Genkit pomagają automatycznie wyodrębniać dane, w tym dane wejściowe, wyjściowe i informacje z etapów pośrednich, aby ocenić kompleksową jakość odpowiedzi LLM oraz zrozumieć działanie elementów składowych systemu.

Jeśli na przykład masz proces RAG, Genkit wyodrębni zbiór dokumentów zwrócony przez retrievera, aby można było ocenić jakość retrievera podczas jego działania w kontekście procesu, jak pokazano poniżej za pomocą wskaźników wierności i trafności odpowiedzi Genkit:

import { genkit } from 'genkit';
import { genkitEval, GenkitMetric } from '@genkit-ai/evaluator';
import { vertexAI, textEmbedding004, gemini15Flash } from '@genkit-ai/vertexai';

const ai = genkit({
  plugins: [
    vertexAI(),
    genkitEval({
      judge: gemini15Flash,
      metrics: [GenkitMetric.FAITHFULNESS, GenkitMetric.ANSWER_RELEVANCY],
      embedder: textEmbedding004, // GenkitMetric.ANSWER_RELEVANCY requires an embedder
    }),
  ],
  // ...
});

Uwaga: powyższa konfiguracja wymaga zainstalowania pakietów genkit, @genkit-ai/googleai, @genkit-ai/evaluator@genkit-ai/vertexai.

  npm install @genkit-ai/evaluator @genkit-ai/vertexai

Zacznij od zdefiniowania zbioru danych wejściowych o nazwie testInputs.json, którego chcesz użyć jako zbioru danych wejściowych. Ten zbiór danych wejściowych reprezentuje przypadki testowe, których użyjesz do wygenerowania danych wyjściowych na potrzeby oceny.

["Cheese", "Broccoli", "Spinach and Kale"]

Jeśli weryfikator potrzebuje danych wyjściowych referencyjnych do oceny przepływu, możesz przekazać dane wejściowe i dane wyjściowe referencyjne w tym formacie:

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

Pamiętaj, że w wejściowym pliku JSON możesz użyć dowolnego typu danych JSON. Genkit przekaże je wraz z tym samym typem danych do Twojego przepływu.

Następnie możesz użyć polecenia eval:flow, aby ocenić przepływ danych na podstawie testów podanych w dokumentacji testInputs.json.

genkit eval:flow menuSuggestionFlow --input testInputs.json

Jeśli Twój proces wymaga uwierzytelniania, możesz go określić za pomocą argumentu --auth:

genkit eval:flow menuSuggestionFlow --input testInputs.json --auth "{\"email_verified\": true}"

Następnie możesz wyświetlić wyniki oceny w interfejsie dla deweloperów, wykonując:

genkit start

Następnie otwórz localhost:4000/evaluate.

Możesz też przesłać plik wyjściowy, aby sprawdzić dane wyjściowe w pliku JSON.

genkit eval:flow menuSuggestionFlow --input testInputs.json --output eval-result.json

Uwaga: poniżej znajdziesz przykład tego, jak LLM może pomóc w generowaniu testów.

Obsługiwane oceny

Oceniacze Genkit

Genkit zawiera niewielką liczbę natywnych oceniaczy zainspirowanych RAGAS, aby ułatwić Ci rozpoczęcie:

  • Wierność
  • Trafność odpowiedzi
  • Złośliwość

Wtyczki oceny

Genkit obsługuje dodatkowych oceniających za pomocą wtyczek, takich jak VertexAI Rapid Evaluators za pomocą wtyczki VertexAI.

Zaawansowane zastosowanie

eval:flow to wygodny sposób na szybką ocenę przepływu, ale czasami może być potrzebna większa kontrola nad krokami oceny. Może się tak zdarzyć, jeśli używasz innego frameworku i masz już dane wyjściowe, które chcesz ocenić. Możesz wykonać wszystkie czynności, które eval:flow wykonuje w pośredni sposób ręcznie.

Możesz uruchomić w grupie przepływ Genkit i dodać do niego unikalną etykietę, która posłuży do wyodrębnienia zbioru danych do oceny (zbiór danych wejściowych, wyjściowych i kontekstów).

Przeprowadź proces na danych testowych:

genkit flow:batchRun myRagFlow test_inputs.json --output flow_outputs.json --label customLabel

Wyodrębnij dane oceny:

genkit eval:extractData myRagFlow --label customLabel --output customLabel_dataset.json

Dane wyeksportowane zostaną w pliku JSON, a każdy test będzie miał format:

[
  {
    "testCaseId": string,
    "input": string,
    "output": string,
    "context": array of strings,
    "traceIds": array of strings,
  }
]

Wyodrętnik danych automatycznie odnajdzie retrievery i doda wygenerowane dokumenty do tablicy kontekstu. Domyślnie eval:run będzie działać na wszystkich skonfigurowanych oceniaczach. Podobnie jak w przypadku eval:flow wyniki eval:run będą się wyświetlać na stronie oceny w interfejsie dla programistów (localhost:4000/evaluate).

Ekstraktory niestandardowe

Możesz też podać niestandardowe ekstraktory do użycia w komadach eval:extractDataeval:flow. Ekstraktory niestandardowe umożliwiają zastąpienie domyślnej logiki ekstrakcji, co daje większe możliwości tworzenia i oceny zbiorów danych.

Aby skonfigurować niestandardowe narzędzia wyodrębniające, dodaj do katalogu głównego projektu plik konfiguracyjny narzędzi o nazwie genkit-tools.conf.js, jeśli go jeszcze nie masz.

cd $GENKIT_PROJECT_HOME
touch genkit-tools.conf.js

W pliku konfiguracji narzędzi dodaj ten kod:

module.exports = {
  evaluators: [
    {
      actionRef: '/flow/myFlow',
      extractors: {
        context: { outputOf: 'foo-step' },
        output: 'bar-step',
      },
    },
  ],
};

W tym przykładzie skonfigurujesz ekstraktor dla procesu myFlow. Konfiguracja zastępuje ekstraktory dla pól contextoutput oraz używa domyślnej logiki dla pola input.

Specyfikacja ekstraktorów oceny:

  • Pole evaluators akceptuje tablicę obiektów EvaluatorConfig, które są ograniczone do zakresu flowName
  • extractors to obiekt, który określa zastąpienia ekstraktora. Obecne obsługiwane klucze w polu extractors to [input, output, context]. Akceptowane typy wartości:
    • string – powinien to być ciąg znaków z nazwą kroku. Dane wyjściowe tego kroku są wyodrębnione dla tego klucza.
    • { inputOf: string } lub { outputOf: string } – te obiekty reprezentują konkretne kanały (wejściowe lub wyjściowe) kroku. Na przykład { inputOf: 'foo-step' } wyodrębni dane wejściowe z etapu foo-step dla tego klucza.
    • (trace) => string; – aby zwiększyć elastyczność, możesz podać funkcję, która przyjmuje ślad Genkit i zwraca string, oraz określić logikę wyodrębniania w tej funkcji. Schemat danych TraceData znajdziesz w dokumentacji genkit/genkit-tools/common/src/types/trace.ts.

Uwaga: wyodrębnione dane w przypadku wszystkich tych kroków będą ciągiem znaków JSON. Narzędzia automatycznie przeanalizują ten ciąg znaków JSON w momencie oceny. Jeśli udostępniasz funkcję wyodrębniania, upewnij się, że dane wyjściowe to prawidłowy ciąg JSON. Na przykład: "Hello, world!" nie jest prawidłowym ciągiem tekstowym JSON, ale "\"Hello, world!\"" jest prawidłowy.

Uruchamianie na istniejących zbiorach danych

Aby przeprowadzić ocenę na podstawie wyodrębnionego już zbioru danych:

genkit eval:run customLabel_dataset.json

Aby zapisać dane w innym miejscu, użyj flagi --output.

genkit eval:flow menuSuggestionFlow --input testInputs.json --output customLabel_evalresult.json

Aby uruchomić proces na podzbiorze skonfigurowanych oceniających, użyj flagi --evaluators i podaj listę oceniających posortowaną według nazwy i rozdzieloną przecinkami:

genkit eval:run customLabel_dataset.json --evaluators=genkit/faithfulness,genkit/answer_relevancy

Tworzenie danych testowych za pomocą modelu LLM

Oto przykładowy przepływ, który wykorzystuje plik PDF do generowania możliwych pytań użytkowników na jego temat.

import { genkit, run, z } from "genkit";
import { googleAI, gemini15Flash } from "@genkit-ai/googleai";
import { chunk } from "llm-chunk";
import path from 'path';

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;

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.
    // See our RAG documentation for more details. 
    const pdfTxt = await run("extract-text", () => extractText(filePath));

    const chunks = await 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;
  }
);

Następnie możesz użyć tego polecenia, aby wyeksportować dane do pliku i sprawdzić je.

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