Viết Trình đánh giá Genkit

Bạn có thể mở rộng Firebase Genkit để hỗ trợ đánh giá tuỳ chỉnh kết quả của trường hợp kiểm thử, bằng cách sử dụng LLM làm trình đánh giá hoặc hoàn toàn theo phương thức lập trình.

Định nghĩa về trình đánh giá

Trình đánh giá là các hàm đánh giá nội dung do LLM cung cấp và tạo ra. Có hai phương pháp chính để đánh giá tự động (kiểm thử): đá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 như các hàm trong quá trình phát triển phần mềm truyền thống. 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 chấm điểm kết quả theo các tiêu chí được đặt trong câu lệnh.

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á dữ liệu đầu vào, ngữ cảnh hoặc đầu ra 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

Đối với ví dụ này, câu lệnh sẽ yêu cầu LLM đánh giá độ ngon của kết quả. 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. Dưới đây là cách thiết lập lời nhắc đánh giá bằng definePrompt.

const DELICIOUSNESS_VALUES = ['yes', 'no', 'maybe'] as const;

const DeliciousnessDetectionResponseSchema = z.object({
  reason: z.string(),
  verdict: z.enum(DELICIOUSNESS_VALUES),
});
type DeliciousnessDetectionResponse = z.infer<typeof DeliciousnessDetectionResponseSchema>;

const DELICIOUSNESS_PROMPT = ai.definePrompt(
  {
    name: 'deliciousnessPrompt',
    inputSchema: z.object({
      output: z.string(),
    }),
    outputSchema: DeliciousnessDetectionResponseSchema,
  },
  `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:
  {{output}}
  Response:
  `
);

Xác định hàm tính điểm

Bây giờ, hãy xác định hàm sẽ lấy một ví dụ bao gồm output theo yêu cầu của lời nhắc 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 các trường không bắt buộc cho outputcontext. Người đánh giá có trách nhiệm xác thực rằng tất cả các trường bắt buộc để đánh giá đều có sẵn.

import { BaseEvalDataPoint, Score } from 'genkit/evaluator';

/**
 * Score an individual test case for delciousness.
 */
export async function deliciousnessScore<
  CustomModelOptions extends z.ZodTypeAny,
>(
  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
  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 },
  };
}

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 chính hành động của trình đánh giá.

import { BaseEvalDataPoint, EvaluatorAction } from 'genkit/evaluator';

/**
 * 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: BaseEvalDataPoint) => {
      const score = await deliciousnessScore(judge, datapoint, judgeConfig);
      return {
        testCaseId: datapoint.testCaseId,
        evaluation: score,
      };
    }
  );
}

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á dữ liệu đầu vào, ngữ cảnh hoặc kết quả 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

Giống như 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 biết về LLM của giám khảo hoặc cấu hình của LLM đó.

import { BaseEvalDataPoint, Score } from 'genkit/evaluator';

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: 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 regex ${regex.source}`
    : `Output did not match regex ${regex.source}`;
  return {
    score: matches,
    details: { reasoning },
  };
}

Xác định hành động của trình đánh giá

import { BaseEvalDataPoint, EvaluatorAction } from 'genkit/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: BaseEvalDataPoint) => {
        const score = await regexMatchScore(datapoint, regexMetric.regex);
        return fillScores(datapoint, score);
      }
    );
  });
}

Cấu hình

Tuỳ chọn trình bổ trợ

Xác định PluginOptions mà trình bổ trợ trình đánh giá tuỳ chỉnh sẽ sử dụng. Đối tượng này không có yêu cầu nghiêm ngặt và phụ thuộc vào các loại trình đánh giá được xác định.

Ít nhất, bạn cần xác định những chỉ số cần đăng ký.

export enum MyAwesomeMetric {
  WORD_COUNT = 'WORD_COUNT',
  US_PHONE_REGEX_MATCH = 'US_PHONE_REGEX_MATCH',
}

export interface PluginOptions {
  metrics?: Array<MyAwesomeMetric>;
}

Nếu trình bổ trợ mới này sử dụng LLM làm trình đánh giá và trình bổ trợ hỗ trợ việc hoán đổi LLM cần sử dụng, hãy xác định các tham số bổ sung trong đối tượng 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>;
}

Định nghĩa về trình bổ trợ

Trình bổ trợ được đăng ký với khung thông qua tệp genkit.config.ts trong dự án. Để có thể định cấu hình trình bổ trợ mới, hãy xác định một hàm xác định GenkitPlugin và định cấu hình hàm đó bằng PluginOptions được xác định ở trên.

Trong trường hợp này, chúng ta có hai trình đánh giá DELICIOUSNESSUS_PHONE_REGEX_MATCH. Đây là nơi các trình đánh giá đó được đăng ký với trình bổ trợ và với Firebase Genkit.

export function myAwesomeEval<ModelCustomOptions extends z.ZodTypeAny>(
  options: PluginOptions<ModelCustomOptions>
): PluginProvider {
  // Define the new plugin
  const plugin = (options?: MyPluginOptions<ModelCustomOptions>) => {
    return genkitPlugin(
    'myAwesomeEval',
    async (ai: Genkit) => {
      const { judge, judgeConfig, metrics } = options;
      const evaluators: EvaluatorAction[] = metrics.map((metric) => {
        switch (metric) {
          case DELICIOUSNESS:
            // This evaluator requires an LLM as judge
            return createDeliciousnessEvaluator(ai, judge, judgeConfig);
          case US_PHONE_REGEX_MATCH:
            // This evaluator does not require an LLM
            return createUSPhoneRegexEvaluator();
        }
      });
      return { evaluators };
    })
  }
  // Create the plugin with the passed options
  return plugin(options);
}
export default myAwesomeEval;

Định cấu hình Genkit

Thêm trình bổ trợ mới xác định 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 { gemini15Flash } from '@genkit-ai/googleai';

const ai = genkit({
  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
      ],
    }),
  ],
  ...
});

Thử nghiệm

Những vấn đề tương tự áp dụng cho việc đánh giá chất lượng đầu ra của một tính năng AI tạo sinh cũng áp dụng cho việc đánh giá năng lực đánh giá của một trình đánh giá dựa trên LLM.

Để biết trình đánh giá tuỳ chỉnh có hoạt động ở mức dự kiến hay không, hãy tạo một bộ các trường hợp kiểm thử có câu trả lời đúng và sai rõ ràng.

Ví dụ về độ ngon miệng, có thể trông giống như tệp 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."
  }
]

Những ví dụ này có thể do con người tạo ra hoặc bạn có thể yêu cầu LLM giúp tạo một bộ các trường hợp kiểm thử có thể được tuyển chọn. Ngoài ra, bạn cũng có thể sử dụng nhiều tập dữ liệu điểm chuẩn có sẵn.

Sau đó, hãy sử dụng Genkit CLI để chạy trình đánh giá theo các trường hợp kiểm thử này.

genkit eval:run deliciousness_dataset.json

Xem kết quả trong giao diện người dùng Genkit.

genkit start

Chuyển đến localhost:4000/evaluate.