Ocena

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

Firebase Genkit obsługuje narzędzia do oceny innych firm za pomocą wtyczek oraz zaawansowane funkcje obserwacji, 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.

Typy oceny

Genkit obsługuje 2 rodzaje oceny:

  • Ocena na podstawie wnioskowania: ten typ oceny jest wykonywany na podstawie zbioru wstępnie określonych danych wejściowych i oceny jakości odpowiednich danych wyjściowych.

    Jest to najczęstszy typ oceny, odpowiedni do większości przypadków użycia. W tym przypadku sprawdzany jest rzeczywisty wynik systemu w przypadku każdego uruchomienia oceny.

    Ocenę jakości możesz przeprowadzić ręcznie, wizualnie sprawdzając wyniki. Możesz też zautomatyzować ocenę, używając wskaźnika oceny.

  • Surowa ocena: ten typ oceny bezpośrednio ocenia jakość danych wejściowych bez żadnych wniosków. Takie podejście jest zwykle stosowane w przypadku automatycznej oceny za pomocą danych. Wszystkie wymagane pola do oceny (np. W zbiorze danych wejściowych muszą występować pola input, context, outputreference. Jest to przydatne, gdy masz dane pochodzące ze źródła zewnętrznego (np. zebrane z śladów produkcyjnych) i chcesz obiektywnie zmierzyć jakość zebranych danych.

    Więcej informacji znajdziesz w sekcji Użycie zaawansowane na tej stronie.

W tej sekcji wyjaśniamy, jak przeprowadzić ocenę na podstawie wnioskowania za pomocą Genkit.

Krótkie wprowadzenie

Konfiguracja

  1. Użyj istniejącej aplikacji Genkit lub utwórz nową, postępując zgodnie z [instrukcjami](get-started) dla początkujących.
  2. Aby zdefiniować prostą aplikację RAG do oceny, dodaj ten kod: W tym przewodniku używamy fikcyjnego modułu wyszukiwania, który zawsze zwraca te same dokumenty. ```js import { genkit, z, Document } from "genkit"; import { googleAI, gemini15Flash, gemini15Pro, } from "@genkit-ai/googleai"; // Inicjuj 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)) }; } ); // Prosty przepływ pracy polegający na udzielaniu odpowiedzi na pytania export const qaFlow = ai.defineFlow({ name: 'qaFlow', inputSchema: z.string(), outputSchema: z.string(), }, async (query) => { const factDocs = await ai.retrieve({ retriever: dummyRetriever, query, options: { k: 2 }, }); const llmResponse = await ai.generate({ model: gemini15Flash, prompt: `Answer this question with the given context ${query}`, docs: factDocs, }); return llmResponse.text; } ); ```
  3. (Opcjonalnie) Dodaj do aplikacji dane oceny, których chcesz używać podczas oceny. Ten przewodnik używa wskaźnika „MALICIOUSNESS” z pluginu „genkitEval”. ```js import { genkitEval, GenkitMetric } from "@genkit-ai/evaluator"; import { gemini15Pro } from "@genkit-ai/googleai"; export const ai = genkit ({ plugins: [ ... // Dodaj ten wtyczkę do bloku inicjalizacji Genkit genkitEval({ judge: gemini15Pro, metrics: [GenkitMetric.MALICIOUSNESS], }), ] }); ``` **Uwaga:** powyższa konfiguracja wymaga zainstalowania pakietu [`@genkit-ai/evaluator`](https://www.npmjs.com/package/@genkit-ai/evaluator). ```posix-terminal npm install @genkit-ai/evaluator ```
  4. Uruchom aplikację Genkit: ```posix-terminal genkit start -- ```

Tworzenie zbioru danych

Utwórz zbiór danych, aby zdefiniować przykłady, których chcesz użyć do oceny przepływu.

  1. Otwórz interfejs dla programistów (http://localhost:4000) i kliknij przycisk Zbiory danych, aby otworzyć stronę Zbiory danych.

  2. Kliknij przycisk Utwórz zbiór danych, aby otworzyć okno tworzenia zbioru danych.

    a. Podaj datasetId dla nowego zbioru danych. W tym przewodniku używamy myFactsQaDataset.

    b. Wybierz typ zbioru danych Flow.

    c. Pole docelowe weryfikacji pozostaw puste i kliknij Zapisz.

  3. Pojawi się strona nowego zbioru danych z pustym zbiorem danych. Aby dodać przykłady, wykonaj te czynności:

    a. Kliknij przycisk Dodaj przykład, aby otworzyć panel edytora przykładu.

    b. Wymagane jest tylko pole input. Wpisz "Who is man's best friend?" w polu input i kliknij Zapisz, aby dodać przykładowe hasło do zbioru danych.

    c. Powtórz kroki (a) i (b) kilka razy, aby dodać więcej przykładów. Ten przewodnik dodaje do zbioru danych te przykładowe dane wejściowe:

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

    Po zakończeniu tego kroku Twój zbiór danych powinien zawierać 3 przykłady z wymienionymi powyżej wartościami.

Przeprowadzanie oceny i wyświetlanie wyników

Aby rozpocząć ocenę przepływu, w interfejsie programisty kliknij kartę Evaluations, a potem kliknij przycisk Uruchom nową ocenę.

  1. Aby ocenić przepływ danych, kliknij Flow.

  2. Jako docelowy przepływ danych do oceny wybierz qaFlow.

  3. Jako docelowy zbiór danych do oceny wybierz zbiór danych myFactsQaDataset.

  4. (Opcjonalnie) Jeśli zainstalowałeś wskaźnik evaluatora za pomocą wtyczek Genkit, możesz wyświetlić te dane na tej stronie. Wybierz dane, których chcesz użyć w ramach tej oceny. Jest to całkowicie opcjonalne: pominięcie tego kroku spowoduje nadal zwróci wyniki w ramach uruchomienia oceny, ale bez żadnych powiązanych danych.

  5. Na koniec kliknij Przeprowadź ocenę, aby rozpocząć ocenę. W zależności od testowanego procesu może to trochę potrwać. Po zakończeniu oceny pojawi się komunikat z linkiem do wyświetlenia wyników. Kliknij link, aby przejść na stronę Szczegóły oceny.

Na tej stronie możesz zobaczyć szczegóły oceny, w tym oryginalne dane wejściowe, wyekstrahowany kontekst i dane (jeśli są dostępne).

Podstawowe pojęcia

Terminologia

  • Ocena: ocena to proces oceny skuteczności systemu. W Genkit taki system jest zwykle prymitywnym elementem Genkit, np. przepływem lub modelem. Ocena może być automatyczna lub manualna (weryfikacja przez człowieka).

  • Masowe wnioskowanie Wnioskowanie to działanie polegające na przetworzeniu danych wejściowych w ramach przepływu lub modelu w celu uzyskania odpowiednich danych wyjściowych. Przetwarzanie zbiorcze polega na jednoczesnym przetwarzaniu wielu danych wejściowych.

  • Dane to kryterium, według którego oceniane jest wnioskowanie. Dokładność, wierność, złośliwość, język wyjściowy itp.

  • Zbiór danych Zbiór danych to zbiór przykładów, których można używać do oceny opartej na wnioskowaniu. Zbiór danych składa się zwykle z pól input i opcjonalnych pól reference. Pole reference nie ma wpływu na krok wnioskowania oceny, ale jest przekazywane do wszystkich wskaźników oceny w postaci dosłownej. W Genkit możesz utworzyć zbiór danych za pomocą interfejsu programisty. W Genkit są 2 typy zbiorów danych: zbiory danych przepływumodelu.

Weryfikacja schematu

W zależności od typu zbiory danych mają obsługę sprawdzania poprawności schematu w interfejsie programisty:

  • Zbiory danych przepływu obsługują weryfikację pól inputreference zbioru danych na podstawie przepływu w aplikacji Genkit. Weryfikacja schematu jest opcjonalna i jest wymuszana tylko wtedy, gdy w schemacie docelowym jest określony schemat.

  • Dane wyjściowe modelu mają schemat domyślny, który obsługuje typy danych stringGenerateRequest. Walidacja ciągu znaków umożliwia wygodne ocenianie prostych tekstowych promptów, a GenerateRequest zapewnia pełną kontrolę w zaawansowanych przypadkach użycia (np.udostępnianie parametrów modelu, historii wiadomości, narzędzi itp.). Pełny schemat GenerateRequest znajdziesz w dokumentach dokumentacji interfejsu API.

Obsługiwane oceny

Oceniacze Genkit

Genkit zawiera niewielką liczbę natywnych evaluatorów zainspirowanych RAGAS, która ułatwi Ci rozpoczęcie pracy:

  • Zgodność – mierzy zgodność faktów wygenerowanej odpowiedzi z danym kontekstem.
  • Trafność odpowiedzi – określa, na ile wygenerowana odpowiedź jest trafna w stosunku do danego prompta.
  • Maliciousness (złośliwość) – określa, czy wygenerowany wynik ma na celu oszukanie, wyrządzenie szkody lub wykorzystanie.

Wtyczki evaluator

Genkit obsługuje dodatkowe ewaluatory za pomocą wtyczek, takich jak Vertex Rapid Evaluators, do których dostęp uzyskujesz za pomocą wtyczki VertexAI.

Zaawansowane zastosowanie

Ocena za pomocą interfejsu wiersza poleceń

Genkit CLI udostępnia bogaty interfejs API do przeprowadzania oceny. Jest to szczególnie przydatne w środowiskach, w których interfejs dla programistów jest niedostępny (np. w przepływie pracy CI/CD).

Genkit CLI udostępnia 3 główne polecenia oceny: eval:flow, eval:extractData i eval:run.

eval:flow polecenie

Polecenie eval:flow przeprowadza ocenę na podstawie wnioskowania na zbiorze danych wejściowych. Ten zbiór danych może być dostarczony jako plik JSON lub przez odniesienie do istniejącego zbioru danych w Genkit runtime.

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

Tutaj testInputs.json powinna być tablicą obiektów zawierającą pole input i opcjonalne pole reference, jak w tym przykładzie:

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

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

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

Domyślnie polecenia eval:floweval:run używają do oceny wszystkich dostępnych danych. Aby uruchomić proces na podzbiorze skonfigurowanych oceniających, użyj flagi --evaluators i podaj listę oceniających oddzieloną przecinkami:

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

Wyniki uruchomienia oceny możesz wyświetlić w interfejsie programisty na stronie localhost:4000/evaluate.

Polecenia eval:extractDataeval:run

Aby umożliwić ocenę surowych danych, Genkit udostępnia narzędzia do wyodrębniania danych z śladów oraz do uruchamiania wskaźników oceny na podstawie wyodrębnionych danych. Jest to przydatne, jeśli do oceny używasz innego frameworka lub zbierasz wnioski z innego środowiska, aby lokalnie testować jakość danych wyjściowych.

Możesz uruchomić w grupie przepływ Genkit i dodać do niego unikalną etykietę, która posłuży do wyodrębnienia danych do oceny. Nieprzetworzony zbiór danych do oceny to zbiór danych wejściowych dla danych oceny, bez wcześniejszego wnioskowania.

Przeprowadź proces na danych testowych:

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

Wyodrębnij dane oceny:

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

Dane wyeksportowane mają format inny niż format zbioru danych przedstawiony wcześniej. Dzieje się tak, ponieważ te dane są przeznaczone do bezpośredniego stosowania w przypadku wskaźników oceny, bez żadnego kroku wnioskowania. Oto składnia wyodrębnionych danych.

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

Wyodrętnik danych automatycznie wyszukuje retrievery i dodaje wygenerowane dokumenty do tablicy kontekstu. Możesz uruchomić dane oceny na tym wyodrębnionym zbiorze danych, używając polecenia eval:run.

genkit eval:run factsEvalDataset.json

Domyślnie eval:run jest wykonywane na wszystkich skonfigurowanych oceniaczach. Podobnie jak w przypadku eval:flow, wyniki eval:run są widoczne na stronie oceny w interfejsie programisty pod adresem localhost:4000/evaluate.

Ekstraktory niestandardowe

Genkit udostępnia rozsądną domyślną logikę wyodrębniania niezbędnych pól (input, outputcontext) podczas oceny. Może się jednak okazać, że potrzebujesz większej kontroli nad logiką wyodrębniania w przypadku tych pól. Genkit obsługuje wyodrębnianie niestandardowych danych. Możesz podać niestandardowe ekstraktory do użycia w poleceniach eval:extractDataeval:flow.

Najpierw, jako krok przygotowawczy, wprowadź w naszym przykładzie qaFlow krok pomocniczy:

export const qaFlow = ai.defineFlow({
    name: 'qaFlow',
    inputSchema: z.string(),
    outputSchema: z.string(),
  },
  async (query) => {
    const factDocs = await ai.retrieve({
      retriever: dummyRetriever,
      query,
      options: { k: 2 },
    });
    const factDocsModified = await 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: factDocs,
    });
    return llmResponse.text;
  }
);

Następnie skonfiguruj niestandardowy moduł wyodrębniania, aby używać danych wyjściowych kroku factModified podczas oceny tego przepływu danych.

Jeśli nie masz pliku tools-config do konfigurowania niestandardowych ekstraktorów, dodaj plik o nazwie genkit-tools.conf.js do katalogu głównego projektu.

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

W pliku konfiguracji narzędzi dodaj ten kod:

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

Ta konfiguracja zastępuje domyślne narzędzia do wyodrębniania w Genkit, a w szczególności zmienia to, co jest uważane za context podczas oceny tego procesu.

Ponowne uruchomienie oceny ujawnia, że kontekst jest teraz wypełniany jako dane wyjściowe kroku factModified.

genkit eval:flow qaFlow --input testInputs.json

Wyodrębnianie wartości odbywa się w ten sposób:

  • 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ębnia dane wejściowe z kroku foo-step dla tego klucza.
    • (trace) => string; – aby zwiększyć elastyczność, możesz podać funkcję, która przyjmuje ślad Genkit i zwraca wartość typu any, a w tej funkcji określić logikę wyodrębniania. Dokładny schemat TraceData znajdziesz w dokumentacji genkit/genkit-tools/common/src/types/trace.ts.

Uwaga: wyodrębnione dane we wszystkich tych modułach wyodrębniania mają typ odpowiadający modułowi. Jeśli na przykład używasz kontekstu { outputOf: 'foo-step' }, a foo-step zwraca tablicę obiektów, wyekstrahowany kontekst jest też tablicą obiektów.

Tworzenie danych testowych za pomocą modelu LLM

Oto przykładowy proces, w którym do generowania potencjalnych pytań użytkowników używany jest plik PDF.

import { genkit, run, 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 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