评估是一种测试形式,可帮助您验证 LLM 的回答,并确保其符合您的质量标准。
Firebase Genkit 通过插件支持第三方评估工具,并搭配强大的可观测性功能,可深入了解采用 LLM 的应用的运行时状态。Genkit 工具可帮助您自动从中间步骤中提取数据(包括输入、输出和信息),以评估 LLM 回答的端到端质量,以及了解系统构建块的性能。
评估类型
Genkit 支持两种类型的评估:
基于推理的评估:此类评估会针对一组预先确定的输入运行,评估相应输出的质量。
这是最常见的评估类型,适用于大多数用例。此方法会针对每次运行的评估测试系统的实际输出。
您可以通过直观地检查结果来手动执行质量评估。或者,您也可以使用评估指标自动执行评估。
原始评估:此类评估会直接评估输入的质量,而无需进行任何推理。此方法通常与使用指标的自动评估方法搭配使用。评估所需的所有必填字段(例如
input
、context
、output
和reference
)必须存在于输入数据集中。如果您有来自外部来源(例如从生产轨迹收集的数据)的数据,并且希望客观衡量收集数据的质量,此方法非常有用。如需了解详情,请参阅本页的高级使用部分。
本部分介绍了如何使用 Genkit 执行基于推理的评估。
快速入门
设置
- 使用现有的 Genkit 应用,或按照我们的 [开始使用](get-started) 指南创建新应用。
- 添加以下代码以定义要评估的简单 RAG 应用。在本指南中,我们使用一个始终返回相同文档的虚构检索工具。 ```js import { genkit, z, Document } from "genkit"; import { googleAI, gemini15Flash, gemini15Pro, } 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, options: { k: 2 }, }); const llmResponse = await ai.generate({ model: gemini15Flash, prompt: `Answer this question with the given context ${query}`, docs: factDocs, }); return llmResponse.text; } ); ```
- (可选)向应用添加评估指标,以便在评估时使用。本指南使用 `genkitEval` 插件中的 `MALICIOUSNESS` 指标。 ```js 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`](https://www.npmjs.com/package/@genkit-ai/evaluator) 软件包。 ```posix-terminal npm install @genkit-ai/evaluator ```
- 启动 Genkit 应用
```posix-terminal
genkit start --
```
创建数据集
创建一个数据集,以定义我们要用于评估流程的示例。
前往
http://localhost:4000
中的开发者界面,然后点击 Datasets(数据集)按钮以打开“Datasets”(数据集)页面。点击创建数据集按钮,打开创建数据集对话框。
a. 为新数据集提供
datasetId
。本指南使用myFactsQaDataset
。b. 选择
Flow
数据集类型。c. 将验证目标字段留空,然后点击保存
系统随即会显示新数据集页面,其中显示了一个空数据集。请按照以下步骤为其添加示例:
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 个示例,其中包含上述值。
运行评估并查看结果
如需开始评估流程,请点击开发者界面中的 Evaluations
标签页,然后点击运行新评估按钮即可开始。
选择
Flow
单选按钮以评估流程。选择
qaFlow
作为要评估的目标流程。选择
myFactsQaDataset
作为要用于评估的目标数据集。(可选)如果您使用 Genkit 插件安装了评估器指标,则可以在本页面中看到这些指标。选择您要在此评估运行中使用的指标。这完全是可选的:如果省略此步骤,系统仍会在评估运行中返回结果,但不会显示任何关联的指标。
最后,点击运行评估以开始评估。这可能需要一段时间,具体取决于您要测试的流程。评估完成后,系统会显示一条成功消息,其中包含用于查看结果的链接。点击该链接可前往评估详情页面。
您可以在此页面上查看评估的详细信息,包括原始输入、提取的上下文和指标(如果有)。
核心概念
术语
评估:评估是评估系统性能的过程。在 Genkit 中,此类系统通常是 Genkit 基元,例如流或模型。评估可以是自动评估,也可以是人工评估。
批量推理:推理是指在流或模型上运行输入以获取相应输出的过程。批量推理涉及对多个输入同时执行推理。
指标:评估指标是用于为推理结果评分的标准。例如准确性、忠实性、恶意性、输出是否为英语等。
数据集:数据集是用于基于推理的评估的示例集合。数据集通常由
input
和可选的reference
字段组成。reference
字段不会影响评估的推理步骤,但会原样传递给任何评估指标。在 Genkit 中,您可以通过开发者界面创建数据集。Genkit 中有两种类型的数据集:流程数据集和模型数据集。
架构验证
数据集在开发者界面中是否支持架构验证取决于其类型:
流数据集支持对 Genkit 应用中流的数据集的
input
和reference
字段进行验证。架构验证是可选的,只有在目标流程上指定架构时才会强制执行。模型数据集具有隐式架构,同时支持
string
和GenerateRequest
输入类型。字符串验证提供了一种便捷的方式来评估简单的文本提示,而GenerateRequest
则可针对高级用例(例如提供模型参数、消息历史记录、工具等)提供完全控制。您可以在我们的 API 参考文档中找到GenerateRequest
的完整架构。
支持的评估器
Genkit 评估程序
Genkit 包含少数几个受 RAGAS 启发的原生评估器,可帮助您上手使用:
- 忠实度 - 衡量生成的回答与给定上下文的事实一致性
- 回答相关性 - 评估生成的回答与给定问题的相关程度
- 恶意性 - 衡量生成的输出是否意图欺骗、伤害或利用
评估器插件
Genkit 通过插件支持其他评估器,例如 Vertex Rapid 评估器,您可以通过 VertexAI 插件访问这些评估器。
高级用法
使用 CLI 进行评估
Genkit CLI 提供了丰富的 API 来执行评估。在开发者界面不可用(例如在 CI/CD 工作流中)的环境中,此功能尤为有用。
Genkit CLI 提供了 3 个主要的评估命令:eval:flow
、eval:extractData
和 eval: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"
}
]
如果您的流程需要身份验证,您可以使用 --auth
参数指定它:
genkit eval:flow qaFlow --input testInputs.json --auth "{\"email_verified\": true}"
默认情况下,eval:flow
和 eval:run
命令会使用所有可用指标进行评估。如需在部分配置的评估器上运行,请使用 --evaluators
标志,并按名称提供以英文逗号分隔的评估器列表:
genkit eval:flow qaFlow --input testInputs.json --evaluators=genkit/faithfulness,genkit/answer_relevancy
您可以在开发者界面 (localhost:4000/evaluate
) 中查看运行评估的结果。
eval:extractData
和 eval: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
的开发者界面的评估页面中。
自定义提取器
Genkit 提供了合理的默认逻辑,用于在执行评估时提取必要的字段(input
、output
和 context
)。不过,您可能需要更好地控制这些字段的提取逻辑。Genkit 支持自定义提取器来实现此目的。您可以提供要在 eval:extractData
和 eval: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,
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;
}
);
接下来,配置自定义提取器,以便在评估此流程时使用 factModified
步骤的输出。
如果您没有用于配置自定义提取器的 tools-config 文件,请将一个名为 genkit-tools.conf.js
的文件添加到项目根目录。
cd /path/to/your/genkit/app
touch genkit-tools.conf.js
在 tools 配置文件中,添加以下代码:
module.exports = {
evaluators: [
{
actionRef: '/flow/qaFlow',
extractors: {
context: { outputOf: 'factModified' },
},
},
],
};
此配置会替换 Genkit 工具的默认提取器,具体来说,会更改在评估此流程时将哪些内容视为 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, 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;
}
);
然后,您可以使用此命令将数据导出到文件中,以供评估。
genkit flow:run synthesizeQuestions '"my_input.pdf"' --output synthesizedQuestions.json