একটি জেনকিট মূল্যায়নকারী লেখা

আপনি কাস্টম মূল্যায়ন সমর্থন করার জন্য ফায়ারবেস জেনকিট প্রসারিত করতে পারেন, হয় একজন বিচারক হিসাবে LLM ব্যবহার করে, অথবা প্রোগ্রামেটিক (হিউরিস্টিক) মূল্যায়নের মাধ্যমে।

মূল্যায়নকারীর সংজ্ঞা

মূল্যায়নকারীরা এমন ফাংশন যা একটি LLM এর প্রতিক্রিয়া মূল্যায়ন করে। স্বয়ংক্রিয় মূল্যায়নের দুটি প্রধান পদ্ধতি রয়েছে: হিউরিস্টিক মূল্যায়ন এবং এলএলএম-ভিত্তিক মূল্যায়ন। হিউরিস্টিক পদ্ধতিতে, আপনি একটি নির্ধারক ফাংশন সংজ্ঞায়িত করেন। বিপরীতে, একটি LLM-ভিত্তিক মূল্যায়নে, বিষয়বস্তু একটি LLM-এ ফেরত দেওয়া হয়, এবং LLM-কে প্রম্পটে সেট করা মানদণ্ড অনুযায়ী আউটপুট স্কোর করতে বলা হয়।

ai.defineEvaluator পদ্ধতি, যা আপনি Genkit-এ একটি মূল্যায়নকারী ক্রিয়া সংজ্ঞায়িত করতে ব্যবহার করেন, উভয় পদ্ধতিকে সমর্থন করে। এই নথিটি হিউরিস্টিক এবং এলএলএম-ভিত্তিক মূল্যায়নের জন্য এই পদ্ধতিটি কীভাবে ব্যবহার করতে হয় তার কয়েকটি উদাহরণ অন্বেষণ করে।

এলএলএম-ভিত্তিক মূল্যায়নকারী

একটি LLM-ভিত্তিক মূল্যায়নকারী আপনার জেনারেটিভ AI বৈশিষ্ট্যের input , context এবং output মূল্যায়ন করার জন্য একটি LLM-এর ব্যবহার করে।

জেনকিটে এলএলএম-ভিত্তিক মূল্যায়নকারীরা 3টি উপাদান নিয়ে গঠিত:

  • একটি প্রম্পট
  • একটি স্কোরিং ফাংশন
  • একটি মূল্যায়নকারী কর্ম

প্রম্পট সংজ্ঞায়িত করুন

এই উদাহরণের জন্য, একটি খাদ্য ( output ) সুস্বাদু কিনা তা নির্ধারণ করতে মূল্যায়নকারী একটি এলএলএম ব্যবহার করে। প্রথমে, এলএলএম-এর প্রসঙ্গ প্রদান করুন, তারপর আপনি এটি কী করতে চান তা বর্ণনা করুন এবং অবশেষে, এর প্রতিক্রিয়ার উপর ভিত্তি করে কয়েকটি উদাহরণ দিন।

Genkit এর definePrompt ইউটিলিটি ইনপুট এবং আউটপুট বৈধতা সহ প্রম্পট সংজ্ঞায়িত করার একটি সহজ উপায় প্রদান করে। নিম্নলিখিত কোডটি 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:
      `
  });
}

স্কোরিং ফাংশন সংজ্ঞায়িত করুন

একটি ফাংশন সংজ্ঞায়িত করুন যা একটি উদাহরণ নেয় যা প্রম্পটের প্রয়োজনীয় output অন্তর্ভুক্ত করে এবং ফলাফল স্কোর করে। Genkit testcases একটি প্রয়োজনীয় ক্ষেত্র হিসাবে input অন্তর্ভুক্ত, output এবং ঐচ্ছিক ক্ষেত্র হিসাবে context সহ। মূল্যায়নের জন্য প্রয়োজনীয় সমস্ত ক্ষেত্র উপস্থিত রয়েছে তা যাচাই করা মূল্যায়নকারীর দায়িত্ব।

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

মূল্যায়নকারী কর্ম সংজ্ঞায়িত করুন

চূড়ান্ত ধাপ হল একটি ফাংশন লিখতে যা 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,
      };
    }
  );
}

defineEvaluator পদ্ধতিটি অন্যান্য জেনকিট কনস্ট্রাক্টর যেমন defineFlow এবং defineRetriever মত। এই পদ্ধতিতে একটি EvaluatorFn একটি কলব্যাক হিসাবে প্রদান করা প্রয়োজন৷ EvaluatorFn পদ্ধতি একটি BaseEvalDataPoint অবজেক্ট গ্রহণ করে, যা নির্দিষ্ট করা থাকলে একটি ঐচ্ছিক কাস্টম-অপশন প্যারামিটার সহ মূল্যায়নের অধীনে একটি ডেটাসেটে একটি একক এন্ট্রির সাথে মিলে যায়। ফাংশন ডেটাপয়েন্ট প্রক্রিয়া করে এবং একটি EvalResponse অবজেক্ট প্রদান করে।

BaseEvalDataPoint এবং EvalResponse জন্য Zod স্কিমগুলি নিম্নরূপ।

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

defineEvaluator অবজেক্ট ব্যবহারকারীকে একটি নাম, একটি ব্যবহারকারী-পাঠযোগ্য প্রদর্শন নাম এবং মূল্যায়নকারীর জন্য একটি সংজ্ঞা প্রদান করতে দেয়। ডিসপ্লে নাম এবং ডেফিনিটন ডিভ UI-তে মূল্যায়ন ফলাফলের সাথে প্রদর্শিত হয়। এটিতে একটি ঐচ্ছিক isBilled ক্ষেত্র রয়েছে যা চিহ্নিত করে যে এই মূল্যায়নকারীর ফলে বিলিং হতে পারে কিনা (যেমন, এটি একটি বিল করা LLM বা API ব্যবহার করে)। যদি একজন মূল্যায়নকারীকে বিল দেওয়া হয়, UI ব্যবহারকারীকে একটি মূল্যায়ন চালানোর অনুমতি দেওয়ার আগে CLI-তে একটি নিশ্চিতকরণের জন্য অনুরোধ করে। এই পদক্ষেপটি অনিচ্ছাকৃত খরচ থেকে রক্ষা করতে সাহায্য করে।

হিউরিস্টিক মূল্যায়নকারী

একটি হিউরিস্টিক মূল্যায়নকারী আপনার জেনারেটিভ এআই বৈশিষ্ট্যের input , context বা output মূল্যায়ন করতে ব্যবহৃত যে কোনও ফাংশন হতে পারে।

জেনকিটে হিউরিস্টিক মূল্যায়নকারী 2টি উপাদান নিয়ে গঠিত:

  • একটি স্কোরিং ফাংশন
  • একটি মূল্যায়নকারী কর্ম

স্কোরিং ফাংশন সংজ্ঞায়িত করুন

এলএলএম-ভিত্তিক মূল্যায়নকারীর মতো, স্কোরিং ফাংশনটি সংজ্ঞায়িত করুন। এই ক্ষেত্রে, স্কোরিং ফাংশনের জন্য একজন বিচারক এলএলএম প্রয়োজন নেই।

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

মূল্যায়নকারী কর্ম সংজ্ঞায়িত করুন

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

এটা একসাথে নির্বাণ

প্লাগইন সংজ্ঞা

Genkit শুরু করার সময় প্লাগইনগুলি ইনস্টল করে ফ্রেমওয়ার্কের সাথে নিবন্ধিত হয়। একটি নতুন প্লাগইন সংজ্ঞায়িত করতে, প্লাগইন প্রসঙ্গে সমস্ত জেনকিট অ্যাকশনগুলিকে ইনস্ট্যান্টিয়েট করতে genkitPlugin সহায়ক পদ্ধতি ব্যবহার করুন।

এই কোড নমুনা দুটি মূল্যায়নকারীকে দেখায়: এলএলএম-ভিত্তিক সুস্বাদু মূল্যায়নকারী এবং রেজেক্স-ভিত্তিক মার্কিন ফোন নম্বর মূল্যায়নকারী। প্লাগইন প্রেক্ষাপটের মধ্যে এই মূল্যায়নকারীদের সূচনা করা তাদের প্লাগইনের সাথে নিবন্ধিত করে।

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;

Genkit কনফিগার করুন

আপনার Genkit কনফিগারেশনে myCustomEvals প্লাগইন যোগ করুন।

মিথুনের সাথে মূল্যায়নের জন্য, নিরাপত্তা সেটিংস অক্ষম করুন যাতে মূল্যায়নকারী সম্ভাব্য ক্ষতিকারক সামগ্রী গ্রহণ করতে, সনাক্ত করতে এবং স্কোর করতে পারে৷

import { gemini15Pro } from '@genkit-ai/googleai';

const ai = genkit({
  plugins: [
    vertexAI(),
    ...
    myCustomEvals({
      judge: gemini15Pro,
    }),
  ],
  ...
});

আপনার কাস্টম মূল্যায়নকারীদের ব্যবহার করে

একবার আপনি আপনার কাস্টম মূল্যায়নকারীদের জেনকিট অ্যাপের প্রেক্ষাপটে (হয় একটি প্লাগইনের মাধ্যমে বা সরাসরি) ইনস্ট্যান্টিয়েট করলে, তারা ব্যবহারের জন্য প্রস্তুত। নিচের উদাহরণটি ব্যাখ্যা করে যে কিভাবে সুস্বাদু মূল্যায়নকারীকে কয়েকটি নমুনা ইনপুট এবং আউটপুট দিয়ে চেষ্টা করতে হয়।

  • 1. নিম্নলিখিত বিষয়বস্তু সহ একটি 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."
  }
]
  • 2. এই পরীক্ষার ক্ষেত্রে মূল্যায়নকারী চালানোর জন্য Genkit CLI ব্যবহার করুন।
# Start your genkit runtime
genkit start -- <command to start your app>
genkit eval:run deliciousness_dataset.json --evaluators=myCustomEvals/deliciousnessEvaluator
  • 3. Genkit UI-তে আপনার ফলাফল দেখতে `localhost:4000/evaluate`-এ নেভিগেট করুন।

এটা মনে রাখা গুরুত্বপূর্ণ যে কাস্টম মূল্যায়নকারীদের প্রতি আস্থা বৃদ্ধি পায় যখন আপনি তাদের মানক ডেটাসেট বা পদ্ধতির সাথে বেঞ্চমার্ক করেন। আপনার মূল্যায়নকারীদের কর্মক্ষমতা উন্নত করতে এই ধরনের বেঞ্চমার্কের ফলাফলের উপর পুনরাবৃত্তি করুন যতক্ষণ না এটি মানের লক্ষ্যযুক্ত স্তরে পৌঁছায়।