評估

評估是一種測試形式,可協助您驗證 LLM 的回覆,並確保回覆符合品質標準。

Firebase Genkit 可透過外掛程式支援第三方評估工具,並搭配強大的可觀察性功能,深入瞭解 LLM 支援應用程式的執行階段狀態。Genkit 工具可協助您自動擷取資料,包括中繼步驟的輸入內容、輸出內容和資訊,以評估 LLM 回應的端對端品質,並瞭解系統的構件效能。

評估類型

Genkit 支援兩種評估方式:

  • 以推論為準的評估:這類評估會針對一組預先決定的輸入內容執行,評估對應輸出內容的品質。

    這是最常見的評估類型,適用於多數用途。這種方法會針對每次評估作業測試系統的實際輸出內容。

    您可以透過視覺檢查結果,手動執行品質評估。或者,您也可以使用評估指標自動執行評估作業。

  • 原始評估:這類評估會直接評估輸入內容的品質,不進行任何推論。這種方法通常會搭配使用指標的自動評估機制。評估作業的所有必填欄位 (例如 inputcontextoutputreference) 必須出現在輸入資料集中。如果您有來自外部來源的資料 (例如從實際工作環境的追蹤記錄收集而來),且想要客觀評估所收集資料的品質,這項功能就非常實用。

    詳情請參閱本頁的「進階使用」一節。

本節說明如何使用 Genkit 執行以推論為基礎的評估作業。

快速入門導覽課程

設定

  1. 您可以使用現有的 Genkit 應用程式,也可以按照我們的 [入門指南](get-started.md)建立新的應用程式。
  2. 新增下列程式碼,定義要評估的簡易 RAG 應用程式。在本指南中,我們使用了一個一律傳回相同文件的虛擬擷取器。
    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. (選用) 在應用程式中加入評估指標,以便在評估時使用。本指南使用 genkitEval 外掛程式的 MALICIOUSNESS 指標。
    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],
        }),
      ]
    });
    注意:上述設定需要安裝 @genkit-ai/evaluator 套件。
    npm install @genkit-ai/evaluator
  4. 啟動 Genkit 應用程式。
    genkit start -- 

建立資料集

建立資料集,定義要用於評估流程的範例。

  1. 前往 http://localhost:4000 的開發人員 UI,然後按一下「Datasets」按鈕,開啟「Datasets」頁面。

  2. 按一下「Create Dataset」按鈕,開啟建立資料集對話方塊。

    a. 為新資料集提供 datasetId。本指南使用 myFactsQaDataset

    b. 選取 Flow 資料集類型。

    c. 將驗證目標欄位留空,然後按一下「儲存」

  3. 新的資料集頁面隨即顯示,並顯示空白資料集。請按照下列步驟新增範例:

    a. 按一下「新增範例」按鈕,開啟範例編輯器面板。

    b. 您只需要提供 input 欄位。在 input 欄位中輸入 "Who is man's best friend?",然後按一下「儲存」,將範例 has 新增至資料集。

    c. 重複執行步驟 (a) 和 (b) 幾次,即可新增更多示例。本指南會在資料集中新增下列範例輸入內容:

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

    完成這個步驟後,資料集應包含 3 個範例,並包含上述的值。

執行評估並查看結果

如要開始評估流程,請在資料集頁面中按一下「執行新評估」按鈕。您也可以透過「評估」分頁開始新的評估作業。

  1. 選取「Flow」圓形按鈕,即可評估流程。

  2. 選取 qaFlow 做為要評估的目標流程。

  3. 選取 myFactsQaDataset 做為評估用目標資料集。

  4. (選用) 如果您已使用 Genkit 外掛程式安裝評估指標,可以在這個頁面中查看這些指標。選取要用於這項評估作業的指標。這完全是可選步驟:省略這個步驟仍會在評估執行期間傳回結果,但不會傳回任何相關指標。

  5. 最後,按一下「Run evaluation」即可開始評估。視您要測試的流程而定,這可能需要一些時間。評估完成後,系統會顯示成功訊息,並附上可用來查看結果的連結。按一下連結即可前往「評估詳細資料」頁面。

您可以在這個頁面上查看評估結果的詳細資料,包括原始輸入內容、擷取的內容和指標 (如果有的話)。

核心概念

術語

  • 評估:評估是一種評估系統效能的程序。在 Genkit 中,這類系統通常是 Genkit 基本元素,例如流程或模型。評估作業可以是自動評估或人工評估。

  • 大量推論推論是指在資料流或模型上執行輸入內容,以取得相應輸出內容的行為。大量推論涉及同時對多個輸入內容執行推論。

  • 指標:評估指標是評估推論分數的標準。例如準確度、忠實度、惡意性、輸出內容是否為英文等。

  • 資料集:資料集是用於推論評估的範例集合。資料集通常包含 input 和選用的 reference 欄位。reference 欄位不會影響評估的推論步驟,但會逐字傳遞至任何評估指標。在 Genkit 中,您可以透過開發人員 UI 建立資料集。Genkit 中有兩種類型的資料集:流程資料集和模型資料集。

結構定義驗證

視資料集類型而定,開發人員 UI 支援架構驗證:

  • 流程資料集可針對 Genkit 應用程式中的流程,驗證資料集的 inputreference 欄位。結構定義驗證為選用功能,只有在目標流程中指定結構定義時才會強制執行。

  • 模型資料集含有隱含的架構,同時支援 stringGenerateRequest 輸入類型。字串驗證可讓您輕鬆評估簡單的文字提示,而 GenerateRequest 則可提供完整的進階用途控制項 (例如提供模型參數、訊息記錄、工具等)。您可以在 API 參考文件中找到 GenerateRequest 的完整結構定義。

支援的評估工具

Genkit 評估工具

Genkit 包含少數原生評估工具,這些工具的靈感來自 RAGAS,可協助您開始使用:

  • 忠實度:評估生成答案與指定上下文的事實一致性
  • 答案相關性:評估系統產生的答案與給定提示的相關程度
  • 惡意性:評估產生的輸出內容是否意圖欺騙、傷害或濫用

評估工具外掛程式

Genkit 可透過外掛程式支援其他評估工具,例如 Vertex Rapid 評估工具,您可以透過 Vertex AI 外掛程式存取這些工具。

進階用途

使用 CLI 進行評估

Genkit CLI 提供豐富的 API 可用於執行評估。在無法使用開發人員 UI 的環境中 (例如 CI/CD 工作流程中),這項功能就特別實用。

Genkit CLI 提供 3 個主要評估指令:eval:floweval:extractDataeval:run

eval:flow 指令

eval:flow 指令會對輸入資料集執行以推論為基礎的評估作業。您可以以 JSON 檔案的形式提供這項資料集,也可以在 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

在此,testInputs.json 應為物件陣列,其中包含 input 欄位和選用的 reference 欄位,如下所示:

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

如果流程需要驗證,您可以使用 --context 引數指定驗證:

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

根據預設,eval:floweval:run 指令會使用所有可用的評估指標。如要針對已設定的評估工具子集執行,請使用 --evaluators 旗標,並以逗號分隔的清單提供評估工具名稱:

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

您可以在 localhost:4000/evaluate 的開發人員 UI 中查看評估執行結果。

eval:extractDataeval:run 指令

為了支援原始評估,Genkit 提供工具,可從追蹤記錄中擷取資料,並針對擷取的資料執行評估指標。舉例來說,如果您使用其他評估架構,或是從其他環境收集推論,以便在本機測試輸出品質,這項功能就很實用。

您可以批次執行 Genkit 流程,並在執行時加入專屬標籤,然後用於擷取評估資料集。原始評估資料集是評估指標的輸入集合,執行任何先前推論。

在測試輸入內容上執行流程:

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

擷取評估資料:

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

匯出的資料格式與先前顯示的資料集格式不同。這是因為這類資料的用途是直接與評估指標搭配使用,不需任何推論步驟。以下是擷取資料的語法。

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

資料擷取器會自動尋找擷取器,並將產生的文件新增至內容陣列。您可以使用 eval:run 指令,對這個擷取的資料集執行評估指標。

genkit eval:run factsEvalDataset.json

根據預設,eval:run 會針對所有已設定的評估工具執行,而與 eval:flow 一樣,eval:run 的結果會顯示在位於 localhost:4000/evaluate 的開發人員 UI 評估頁面中。

自訂擷取器

Genkit 提供合理的預設邏輯,可在評估期間擷取必要欄位 (inputoutputcontext)。不過,您可能需要對這些欄位的擷取邏輯進行更多控制。Genkit 支援自訂擷取器,可達成這項目標。您可以提供自訂擷取器,用於 eval:extractDataeval:flow 指令。

首先,我們在 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;
  }
);

接下來,請設定自訂擷取器,在評估此流程時使用 factModified 步驟的輸出內容。

如果您沒有用來設定自訂擷取器的工具設定檔,請在專案根目錄中新增名為 genkit-tools.conf.js 的檔案。

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

在工具設定檔案中新增下列程式碼:

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

這項設定會覆寫 Genkit 工具的預設擷取工具,特別是變更評估此流程時視為 context 的內容。

再次執行評估作業,您會發現現在已將 context 填入做為步驟 factModified 的輸出內容。

genkit eval:flow qaFlow --input testInputs.json

評估擷取器的指定方式如下:

  • evaluators 欄位可接受 EvaluatorConfig 物件的陣列,其範圍由 flowName 指定
  • extractors 是用於指定擷取器覆寫值的物件。extractors 目前支援的鍵為 [input, output, context]。可接受的值類型如下:
    • string:應為步驟名稱,以字串形式指定。系統會為這個鍵擷取這個步驟的輸出內容。
    • { inputOf: string }{ outputOf: string }:這些物件代表步驟的特定管道 (輸入或輸出)。舉例來說,{ inputOf: 'foo-step' } 會為這個鍵擷取步驟 foo-step 的輸入內容。
    • (trace) => string;:為進一步提升彈性,您可以提供可接受 Genkit 追蹤記錄並傳回 any 類型值的函式,並在該函式中指定擷取邏輯。如需確切的 TraceData 結構定義,請參閱 genkit/genkit-tools/common/src/types/trace.ts

注意:所有擷取器的擷取資料都是對應擷取器的類型。舉例來說,如果您使用 context: { outputOf: 'foo-step' },而 foo-step 傳回物件的陣列,則擷取的內容也是物件的陣列。

使用 LLM 合成測試資料

以下是使用 PDF 檔案產生潛在使用者問題的流程範例。

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;
  }
);

接著,您可以使用這個指令將資料匯出至檔案,並用於評估。

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