Firebase Genkit dapat diperluas untuk mendukung evaluasi kustom output kasus pengujian, baik dengan menggunakan LLM sebagai juri, maupun secara terprogram.
Definisi evaluator
Evaluator adalah fungsi yang menilai konten yang diberikan kepada dan dihasilkan oleh LLM. Ada dua pendekatan utama untuk evaluasi otomatis (pengujian): penilaian heuristik dan penilaian berbasis LLM. Dalam pendekatan heuristik, Anda menentukan fungsi deterministik seperti fungsi pengembangan perangkat lunak tradisional. Dalam penilaian berbasis LLM, konten dimasukkan kembali ke LLM, lalu LLM diminta untuk menilai output sesuai kriteria yang ditetapkan dalam prompt.
Evaluator berbasis LLM
Evaluator berbasis LLM memanfaatkan LLM untuk mengevaluasi input, konteks, atau output fitur AI generatif Anda.
Evaluator berbasis LLM di Genkit terdiri dari 3 komponen:
- Prompt
- Fungsi penskoran
- Tindakan evaluator
Menentukan perintah
Dalam contoh ini, prompt akan meminta LLM untuk menilai seberapa lezat output yang diberikan. Pertama, berikan konteks ke LLM, lalu jelaskan apa yang Anda inginkan, dan terakhir, berikan beberapa contoh sebagai dasar responsnya.
Genkit dilengkapi dengan dotprompt
, yang menyediakan cara mudah untuk menentukan dan mengelola perintah dengan fitur seperti validasi skema input/output. Berikut cara menggunakan dotprompt
untuk menentukan perintah evaluasi.
import { defineDotprompt } from '@genkit-ai/dotprompt';
// Define the expected output values
const DELICIOUSNESS_VALUES = ['yes', 'no', 'maybe'] as const;
// Define the response schema expected from the LLM
const DeliciousnessDetectionResponseSchema = z.object({
reason: z.string(),
verdict: z.enum(DELICIOUSNESS_VALUES),
});
type DeliciousnessDetectionResponse = z.infer<
typeof DeliciousnessDetectionResponseSchema
>;
const DELICIOUSNESS_PROMPT = defineDotprompt(
{
input: {
schema: z.object({
output: z.string(),
}),
},
output: {
schema: DeliciousnessDetectionResponseSchema,
},
},
`You are a food critic with a wide range in taste. Given the output, decide if it sounds delicious and provide your reasoning. Use only "yes" (if delicous), "no" (if not delicious), "maybe" (if you can't decide) as the verdict.
Here are a few examples:
Output:
Chicken parm sandwich
Response:
{ "reason": "This is a classic sandwich enjoyed by many - totally delicious", "verdict":"yes"}
Output:
Boston logan international airport tarmac
Response:
{ "reason": "This is not edible and definitely not delicious.", "verdict":"no"}
Output:
A juicy piece of gossip
Response:
{ "reason": "Gossip is sometimes metaphorically referred to as tasty.", "verdict":"maybe"}
Here is a new submission to assess:
Output:
{{output}}
Response:
`
);
Menentukan fungsi penskoran
Sekarang, tentukan fungsi yang akan mengambil contoh yang menyertakan output
seperti yang diperlukan oleh perintah dan beri skor hasilnya. Kasus pengujian Genkit mencakup input
sebagai kolom wajib diisi, dengan kolom opsional untuk output
dan context
. Adalah tanggung jawab evaluator untuk memvalidasi bahwa semua {i>field<i} yang diperlukan untuk evaluasi ada.
/**
* Score an individual test case for delciousness.
*/
export async function deliciousnessScore<
CustomModelOptions extends z.ZodTypeAny,
>(
judgeLlm: ModelArgument<CustomModelOptions>,
dataPoint: BaseDataPoint,
judgeConfig?: CustomModelOptions
): Promise<Score> {
const d = dataPoint;
// Validate the input has required fields
if (!d.output) {
throw new Error('Output is required for Deliciousness detection');
}
//Hydrate the prompt
const finalPrompt = DELICIOUSNESS_PROMPT.renderText({
output: d.output as string,
});
// Call the LLM to generate an evaluation result
const response = await generate({
model: judgeLlm,
prompt: finalPrompt,
config: judgeConfig,
});
// Parse the output
const parsedResponse = response.output();
if (!parsedResponse) {
throw new Error(`Unable to parse evaluator response: ${response.text()}`);
}
// Return a scored response
return {
score: parsedResponse.verdict,
details: { reasoning: parsedResponse.reason },
};
}
Menentukan tindakan evaluator
Langkah terakhir adalah menulis fungsi yang mendefinisikan tindakan evaluator itu sendiri.
/**
* Create the Deliciousness evaluator action.
*/
export function createDeliciousnessEvaluator<
ModelCustomOptions extends z.ZodTypeAny,
>(
judge: ModelReference<ModelCustomOptions>,
judgeConfig: z.infer<ModelCustomOptions>
): EvaluatorAction {
return defineEvaluator(
{
name: `myAwesomeEval/deliciousness`,
displayName: 'Deliciousness',
definition: 'Determines if output is considered delicous.',
},
async (datapoint: BaseDataPoint) => {
const score = await deliciousnessScore(judge, datapoint, judgeConfig);
return {
testCaseId: datapoint.testCaseId,
evaluation: score,
};
}
);
}
Evaluator Heuristik
Evaluator heuristik dapat berupa fungsi apa pun yang digunakan untuk mengevaluasi input, konteks, atau output fitur AI generatif Anda.
Evaluator heuristik di Genkit terdiri dari 2 komponen:
- Fungsi penskoran
- Tindakan evaluator
Menentukan fungsi penskoran
Sama seperti evaluator berbasis LLM, tentukan fungsi skor. Dalam hal ini, fungsi penskoran tidak perlu mengetahui tentang LLM juri atau konfigurasinya.
const US_PHONE_REGEX =
/^[\ ]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4}$/i;
/**
* Scores whether an individual datapoint matches a US Phone Regex.
*/
export async function usPhoneRegexScore(
dataPoint: BaseDataPoint
): Promise<Score> {
const d = dataPoint;
if (!d.output || typeof d.output !== 'string') {
throw new Error('String output is required for regex matching');
}
const matches = US_PHONE_REGEX.test(d.output as string);
const reasoning = matches
? `Output matched regex ${regex.source}`
: `Output did not match regex ${regex.source}`;
return {
score: matches,
details: { reasoning },
};
}
Menentukan tindakan evaluator
/**
* Configures a regex evaluator to match a US phone number.
*/
export function createUSPhoneRegexEvaluator(
metrics: RegexMetric[]
): EvaluatorAction[] {
return metrics.map((metric) => {
const regexMetric = metric as RegexMetric;
return defineEvaluator(
{
name: `myAwesomeEval/${metric.name.toLocaleLowerCase()}`,
displayName: 'Regex Match',
definition:
'Runs the output against a regex and responds with 1 if a match is found and 0 otherwise.',
isBilled: false,
},
async (datapoint: BaseDataPoint) => {
const score = await regexMatchScore(datapoint, regexMetric.regex);
return fillScores(datapoint, score);
}
);
});
}
Konfigurasi
Opsi Plugin
Tentukan PluginOptions
yang akan digunakan oleh plugin evaluator kustom. Objek ini tidak memiliki persyaratan ketat dan bergantung pada jenis evaluator yang ditetapkan.
Anda setidaknya perlu menentukan metrik mana yang akan dicatat.
export enum MyAwesomeMetric {
WORD_COUNT = 'WORD_COUNT',
US_PHONE_REGEX_MATCH = 'US_PHONE_REGEX_MATCH',
}
export interface PluginOptions {
metrics?: Array<MyAwesomeMetric>;
}
Jika plugin baru ini menggunakan LLM sebagai juri dan plugin mendukung penukaran LLM mana yang akan digunakan, tentukan parameter tambahan dalam objek PluginOptions
.
export enum MyAwesomeMetric {
DELICIOUSNESS = 'DELICIOUSNESS',
US_PHONE_REGEX_MATCH = 'US_PHONE_REGEX_MATCH',
}
export interface PluginOptions<ModelCustomOptions extends z.ZodTypeAny> {
judge: ModelReference<ModelCustomOptions>;
judgeConfig?: z.infer<ModelCustomOptions>;
metrics?: Array<MyAwesomeMetric>;
}
Definisi plugin
Plugin didaftarkan ke framework melalui file genkit.config.ts
dalam sebuah project. Agar dapat mengonfigurasi plugin baru, tentukan fungsi yang menentukan GenkitPlugin
dan mengonfigurasinya dengan PluginOptions
yang ditentukan di atas.
Dalam hal ini, kita memiliki dua evaluator DELICIOUSNESS
dan US_PHONE_REGEX_MATCH
. Di sinilah evaluator tersebut terdaftar dengan plugin dan Firebase Genkit.
export function myAwesomeEval<ModelCustomOptions extends z.ZodTypeAny>(
params: PluginOptions<ModelCustomOptions>
): PluginProvider {
// Define the new plugin
const plugin = genkitPlugin(
'myAwesomeEval',
async (params: PluginOptions<ModelCustomOptions>) => {
const { judge, judgeConfig, metrics } = params;
const evaluators: EvaluatorAction[] = metrics.map((metric) => {
// We'll create these functions in the next step
switch (metric) {
case DELICIOUSNESS:
// This evaluator requires an LLM as judge
return createDeliciousnessEvaluator(judge, judgeConfig);
case US_PHONE_REGEX_MATCH:
// This evaluator does not require an LLM
return createUSPhoneRegexEvaluator();
}
});
return { evaluators };
}
);
// Create the plugin with the passed params
return plugin(params);
}
export default myAwesomeEval;
Konfigurasikan Genkit
Tambahkan plugin yang baru ditetapkan ke konfigurasi Genkit Anda.
Untuk evaluasi dengan Gemini, nonaktifkan setelan keamanan agar evaluator dapat menerima, mendeteksi, dan menilai konten yang berpotensi berbahaya.
import { gemini15Flash } from '@genkit-ai/googleai';
export default configureGenkit({
plugins: [
...
myAwesomeEval({
judge: gemini15Flash,
judgeConfig: {
safetySettings: [
{
category: 'HARM_CATEGORY_HATE_SPEECH',
threshold: 'BLOCK_NONE',
},
{
category: 'HARM_CATEGORY_DANGEROUS_CONTENT',
threshold: 'BLOCK_NONE',
},
{
category: 'HARM_CATEGORY_HARASSMENT',
threshold: 'BLOCK_NONE',
},
{
category: 'HARM_CATEGORY_SEXUALLY_EXPLICIT',
threshold: 'BLOCK_NONE',
},
],
},
metrics: [
MyAwesomeMetric.DELICIOUSNESS,
MyAwesomeMetric.US_PHONE_REGEX_MATCH
],
}),
],
...
});
Pengujian
Masalah yang sama yang berlaku untuk mengevaluasi kualitas output fitur AI generatif juga berlaku untuk mengevaluasi kapasitas penjurian dari evaluator berbasis LLM.
Untuk mendapatkan gambaran tentang apakah evaluator kustom berperforma pada tingkat yang diharapkan, buat kumpulan kasus pengujian yang memiliki jawaban benar dan salah yang jelas.
Untuk mengetahui kelezatannya, contohnya mungkin terlihat seperti file json deliciousness_dataset.json
:
[
{
"testCaseId": "delicous_mango",
"input": "What is a super delicious fruit",
"output": "A perfectly ripe mango – sweet, juicy, and with a hint of tropical sunshine."
},
{
"testCaseId": "disgusting_soggy_cereal",
"input": "What is something that is tasty when fresh but less tasty after some time?",
"output": "Stale, flavorless cereal that's been sitting in the box too long."
}
]
Contoh ini dapat dibuat oleh manusia atau Anda dapat meminta LLM untuk membantu membuat serangkaian kasus pengujian yang dapat diseleksi. Ada banyak {i>dataset<i} tolok ukur yang tersedia yang juga dapat digunakan.
Kemudian, gunakan Genkit CLI untuk menjalankan evaluator terhadap kasus pengujian ini.
genkit eval:run deliciousness_dataset.json
Lihat hasil Anda di UI Genkit.
genkit start
Buka localhost:4000/evaluate
.