Bạn có thể mở rộng Firebase Genkit để hỗ trợ tính năng đánh giá tuỳ chỉnh, sử dụng LLM làm trình đánh giá hoặc đánh giá có lập trình (tìm kiếm quy tắc).
Định nghĩa về trình đánh giá
Trình đánh giá là các hàm đánh giá phản hồi của LLM. Có hai phương pháp chính để đánh giá tự động: đánh giá phỏng đoán và đánh giá dựa trên LLM. Trong phương pháp phỏng đoán, bạn xác định một hàm xác định. Ngược lại, trong quy trình đánh giá dựa trên LLM, nội dung được đưa trở lại LLM và LLM được yêu cầu tính điểm cho kết quả đầu ra theo các tiêu chí được đặt trong câu lệnh.
Phương thức ai.defineEvaluator
mà bạn sử dụng để xác định hành động của trình đánh giá trong Genkit hỗ trợ cả hai phương pháp. Tài liệu này khám phá một số ví dụ về cách sử dụng phương thức này cho các hoạt động đánh giá dựa trên phương pháp phỏng đoán và LLM.
Trình đánh giá dựa trên LLM
Trình đánh giá dựa trên LLM tận dụng LLM để đánh giá input
, context
và output
của tính năng AI tạo sinh.
Trình đánh giá dựa trên LLM trong Genkit bao gồm 3 thành phần:
- Lời nhắc
- Hàm tính điểm
- Hành động của trình đánh giá
Xác định lời nhắc
Trong ví dụ này, trình đánh giá tận dụng LLM để xác định xem một món ăn (output
) có ngon hay không. Trước tiên, hãy cung cấp ngữ cảnh cho LLM, sau đó mô tả những gì bạn muốn LLM làm và cuối cùng, hãy đưa ra một vài ví dụ để LLM dựa vào đó để phản hồi.
Tiện ích definePrompt
của Genkit cung cấp một cách dễ dàng để xác định lời nhắc bằng tính năng xác thực đầu vào và đầu ra. Đoạn mã sau đây là ví dụ về cách thiết lập lời nhắc đánh giá bằng definePrompt
.
import { z } from "genkit";
const DELICIOUSNESS_VALUES = ['yes', 'no', 'maybe'] as const;
const DeliciousnessDetectionResponseSchema = z.object({
reason: z.string(),
verdict: z.enum(DELICIOUSNESS_VALUES),
});
function getDeliciousnessPrompt(ai: Genkit) {
return ai.definePrompt({
name: 'deliciousnessPrompt',
input: {
schema: z.object({
responseToTest: z.string(),
}),
},
output: {
schema: DeliciousnessDetectionResponseSchema,
}
prompt: `You are a food critic. Assess whether the provided output sounds delicious, giving only "yes" (delicious), "no" (not delicious), or "maybe" (undecided) as the verdict.
Examples:
Output: Chicken parm sandwich
Response: { "reason": "A classic and beloved dish.", "verdict": "yes" }
Output: Boston Logan Airport tarmac
Response: { "reason": "Not edible.", "verdict": "no" }
Output: A juicy piece of gossip
Response: { "reason": "Metaphorically 'tasty' but not food.", "verdict": "maybe" }
New Output: {{ responseToTest }}
Response:
`
});
}
Xác định hàm tính điểm
Xác định một hàm lấy một ví dụ có chứa output
như yêu cầu của câu lệnh và tính điểm cho kết quả. Các trường hợp kiểm thử Genkit bao gồm input
là trường bắt buộc, với output
và context
là các trường không bắt buộc.
Người đánh giá có trách nhiệm xác thực rằng tất cả các trường cần thiết cho việc đánh giá đều có sẵn.
import { ModelArgument } from 'genkit';
import { BaseEvalDataPoint, Score } from 'genkit/evaluator';
/**
* Score an individual test case for delciousness.
*/
export async function deliciousnessScore<
CustomModelOptions extends z.ZodTypeAny,
>(
ai: Genkit,
judgeLlm: ModelArgument<CustomModelOptions>,
dataPoint: BaseEvalDataPoint,
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 and generate an evaluation result
const deliciousnessPrompt = getDeliciousnessPrompt(ai);
const response = await deliciousnessPrompt(
{
responseToTest: d.output as string,
},
{
model: judgeLlm,
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 },
};
}
Xác định hành động của trình đánh giá
Bước cuối cùng là viết một hàm xác định EvaluatorAction
.
import { EvaluatorAction } from 'genkit/evaluator';
/**
* Create the Deliciousness evaluator action.
*/
export function createDeliciousnessEvaluator<
ModelCustomOptions extends z.ZodTypeAny,
>(
ai: Genkit,
judge: ModelArgument<ModelCustomOptions>,
judgeConfig?: z.infer<ModelCustomOptions>
): EvaluatorAction {
return ai.defineEvaluator(
{
name: `myCustomEvals/deliciousnessEvaluator`,
displayName: 'Deliciousness',
definition: 'Determines if output is considered delicous.',
isBilled: true,
},
async (datapoint: BaseEvalDataPoint) => {
const score = await deliciousnessScore(ai, judge, datapoint, judgeConfig);
return {
testCaseId: datapoint.testCaseId,
evaluation: score,
};
}
);
}
Phương thức defineEvaluator
tương tự như các hàm khởi tạo Genkit khác như
defineFlow
và defineRetriever
. Phương thức này yêu cầu phải cung cấp EvaluatorFn
làm lệnh gọi lại. Phương thức EvaluatorFn
chấp nhận đối tượng BaseEvalDataPoint
, tương ứng với một mục trong tập dữ liệu đang được đánh giá, cùng với tham số tuỳ chọn tuỳ chọn tuỳ chỉnh nếu được chỉ định. Hàm này xử lý điểm dữ liệu và trả về một đối tượng EvalResponse
.
Giản đồ Zod cho BaseEvalDataPoint
và EvalResponse
như sau.
BaseEvalDataPoint
export const BaseEvalDataPoint = z.object({
testCaseId: z.string(),
input: z.unknown(),
output: z.unknown().optional(),
context: z.array(z.unknown()).optional(),
reference: z.unknown().optional(),
testCaseId: z.string().optional(),
traceIds: z.array(z.string()).optional(),
});
export const EvalResponse = z.object({
sampleIndex: z.number().optional(),
testCaseId: z.string(),
traceId: z.string().optional(),
spanId: z.string().optional(),
evaluation: z.union([ScoreSchema, z.array(ScoreSchema)]),
});
ScoreSchema
const ScoreSchema = z.object({
id: z.string().describe('Optional ID to differentiate multiple scores').optional(),
score: z.union([z.number(), z.string(), z.boolean()]).optional(),
error: z.string().optional(),
details: z
.object({
reasoning: z.string().optional(),
})
.passthrough()
.optional(),
});
Đối tượng defineEvaluator
cho phép người dùng cung cấp tên, tên hiển thị dễ đọc và định nghĩa cho trình đánh giá. Tên hiển thị và định nghĩa sẽ xuất hiện cùng với kết quả đánh giá trong Giao diện người dùng dành cho nhà phát triển.
Tệp này cũng có một trường isBilled
không bắt buộc để đánh dấu xem trình đánh giá này có thể dẫn đến việc thanh toán hay không (ví dụ: sử dụng LLM hoặc API đã thanh toán). Nếu người đánh giá được tính phí, giao diện người dùng sẽ nhắc người dùng xác nhận trong CLI trước khi cho phép họ chạy quy trình đánh giá. Bước này giúp ngăn chặn các khoản chi tiêu ngoài ý muốn.
Trình đánh giá quy trình phỏng đoán
Trình đánh giá phỏng đoán có thể là bất kỳ hàm nào dùng để đánh giá input
, context
hoặc output
của tính năng AI tạo sinh.
Trình đánh giá phỏng đoán trong Genkit bao gồm 2 thành phần:
- Hàm tính điểm
- Hành động của trình đánh giá
Xác định hàm tính điểm
Cũng như với trình đánh giá dựa trên LLM, hãy xác định hàm tính điểm. Trong trường hợp này, hàm tính điểm không cần LLM của người đánh giá.
import { BaseEvalDataPoint, Score } from 'genkit/evaluator';
const US_PHONE_REGEX =
/[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4}/i;
/**
* Scores whether a datapoint output contains a US Phone number.
*/
export async function usPhoneRegexScore(
dataPoint: BaseEvalDataPoint
): 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 US_PHONE_REGEX`
: `Output did not match US_PHONE_REGEX`;
return {
score: matches,
details: { reasoning },
};
}
Xác định hành động của trình đánh giá
import { Genkit } from 'genkit';
import { BaseEvalDataPoint, EvaluatorAction } from 'genkit/evaluator';
/**
* Configures a regex evaluator to match a US phone number.
*/
export function createUSPhoneRegexEvaluator(ai: Genkit): EvaluatorAction {
return ai.defineEvaluator(
{
name: `myCustomEvals/usPhoneRegexEvaluator`,
displayName: "Regex Match for US PHONE NUMBER",
definition: "Uses Regex to check if output matches a US phone number",
isBilled: false,
},
async (datapoint: BaseEvalDataPoint) => {
const score = await usPhoneRegexScore(datapoint);
return {
testCaseId: datapoint.testCaseId,
evaluation: score,
};
}
);
}
Tổng hợp kiến thức đã học
Định nghĩa về trình bổ trợ
Trình bổ trợ được đăng ký với khung bằng cách cài đặt các trình bổ trợ đó tại thời điểm khởi chạy Genkit. Để xác định một trình bổ trợ mới, hãy sử dụng phương thức trình trợ giúp genkitPlugin
để tạo bản sao cho tất cả thao tác Genkit trong ngữ cảnh trình bổ trợ.
Mẫu mã này cho thấy hai trình đánh giá: trình đánh giá độ ngon dựa trên LLM và trình đánh giá số điện thoại ở Hoa Kỳ dựa trên biểu thức chính quy. Việc tạo bản sao cho các trình đánh giá này trong ngữ cảnh trình bổ trợ sẽ đăng ký các trình đánh giá đó với trình bổ trợ.
import { GenkitPlugin, genkitPlugin } from 'genkit/plugin';
export function myCustomEvals<
ModelCustomOptions extends z.ZodTypeAny
>(options: {
judge: ModelArgument<ModelCustomOptions>;
judgeConfig?: ModelCustomOptions;
}): GenkitPlugin {
// Define the new plugin
return genkitPlugin("myCustomEvals", async (ai: Genkit) => {
const { judge, judgeConfig } = options;
// The plugin instatiates our custom evaluators within the context
// of the `ai` object, making them available
// throughout our Genkit application.
createDeliciousnessEvaluator(ai, judge, judgeConfig);
createUSPhoneRegexEvaluator(ai);
});
}
export default myCustomEvals;
Định cấu hình Genkit
Thêm trình bổ trợ myCustomEvals
vào cấu hình Genkit.
Để đánh giá bằng Gemini, hãy tắt các chế độ cài đặt an toàn để người đánh giá có thể chấp nhận, phát hiện và tính điểm nội dung có khả năng gây hại.
import { gemini15Pro } from '@genkit-ai/googleai';
const ai = genkit({
plugins: [
vertexAI(),
...
myCustomEvals({
judge: gemini15Pro,
}),
],
...
});
Sử dụng trình đánh giá tuỳ chỉnh
Sau khi bạn tạo bản sao của trình đánh giá tuỳ chỉnh trong ngữ cảnh ứng dụng Genkit (thông qua trình bổ trợ hoặc trực tiếp), bạn có thể sử dụng các trình đánh giá đó. Ví dụ sau đây minh hoạ cách thử trình đánh giá độ ngon với một số dữ liệu đầu vào và đầu ra mẫu.
- 1. Tạo tệp json `deliciousness_dataset.json` có nội dung sau:
[
{
"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."
}
]
- 2. Sử dụng Genkit CLI để chạy trình đánh giá theo các trường hợp kiểm thử này.
# Start your genkit runtime genkit start -- <command to start your app>
genkit eval:run deliciousness_dataset.json --evaluators=myCustomEvals/deliciousnessEvaluator
- 3. Chuyển đến `localhost:4000/evaluate` để xem kết quả trong giao diện người dùng Genkit.
Điều quan trọng cần lưu ý là độ tin cậy của các trình đánh giá tuỳ chỉnh sẽ tăng lên khi bạn đo điểm chuẩn cho các trình đánh giá đó bằng các tập dữ liệu hoặc phương pháp tiêu chuẩn. Lặp lại các kết quả của các điểm chuẩn đó để cải thiện hiệu suất của người đánh giá cho đến khi đạt được mức chất lượng mục tiêu.