Genkit Değerlendiricisi Yazma

Firebase Genkit, test durumu çıktısının özel değerlendirmesini desteklemek için genişletilebilir. Bu işlem, karar verici olarak bir LLM kullanılarak veya tamamen programatik olarak yapılabilir.

Değerlendirici tanımı

Değerlendiriciler, bir LLM'ye verilen ve LLM tarafından oluşturulan içeriği değerlendiren işlevlerdir. Otomatik değerlendirmeye (test) iki temel yaklaşım vardır: sezgisel değerlendirme ve LLM tabanlı değerlendirme. Heuristic yaklaşımda, geleneksel yazılım geliştirmedekilere benzer bir deterministik işlev tanımlarsınız. LLM tabanlı değerlendirmede içerik bir LLM'ye geri beslenir ve LLM'den çıkışı bir istemde belirtilen ölçütlere göre puanlaması istenir.

LLM tabanlı Değerlendiriciler

LLM tabanlı değerlendirici, üretken yapay zeka özelliğinizin girişini, bağlamını veya çıkışını değerlendirmek için LLM'den yararlanır.

Genkit'teki LLM tabanlı değerlendiriciler 3 bileşenden oluşur:

  • İstem
  • Puanlama işlevi
  • Değerlendirici işlemi

İstemi tanımlama

Bu örnekte istem, LLM'den çıktının ne kadar lezzetli olduğunu değerlendirmesini isteyecektir. Öncelikle LLM'ye bağlam bilgisi verin, ardından ne yapmasını istediğinizi açıklayın ve son olarak yanıtını temel alabileceği birkaç örnek verin.

Genkit'in definePrompt yardımcı programı, giriş ve çıkış doğrulamasıyla istemleri tanımlamanın kolay bir yolunu sunar. definePrompt ile değerlendirme istemi oluşturmak için aşağıdaki adımları uygulayın.

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:
  `
);

Puanlama işlevini tanımlama

Ardından, istemde belirtildiği gibi output içeren bir örnek alan ve sonucu puanlayan işlevi tanımlayın. Genkit test örnekleri, input için zorunlu bir alan ve output ile context için isteğe bağlı alanlar içerir. Değerlendirme için gerekli tüm alanların mevcut olduğunu doğrulamak değerlendirmecinin sorumluluğundadır.

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

Değerlendirici işlemini tanımlama

Son adım, değerlendirici işlemini tanımlayan bir işlev yazmaktır.

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

Buluşsal Yöntemlerle Değerlendirme Araçları

Heuristic evaluator, üretken yapay zeka özelliğinizin girişini, bağlamını veya çıkışını değerlendirmek için kullanılan herhangi bir işlev olabilir.

Genkit'teki sezgisel değerlendiriciler 2 bileşenden oluşur:

  • Puanlama işlevi
  • Değerlendirici işlemi

Puanlama işlevini tanımlama

LLM tabanlı değerlendiricide olduğu gibi puanlama işlevini tanımlayın. Bu durumda, puanlama işlevinin yargıç LLM'si veya yapılandırması hakkında bilgi sahibi olması gerekmez.

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

Değerlendirici işlemini tanımlama

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

Yapılandırma

Eklenti Seçenekleri

Özel değerlendirici eklentisinin kullanacağı PluginOptions öğesini tanımlayın. Bu nesnenin katı şartları yoktur ve tanımlanan değerlendirici türlerine bağlıdır.

En azından hangi metriklerin kaydedileceğinin tanımını almalıdır.

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

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

Bu yeni eklenti, karar verici olarak bir LLM kullanıyorsa ve eklenti, kullanılacak LLM'nin değiştirilmesini destekliyorsa PluginOptions nesnesinde ek parametreler tanımlayın.

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

Eklenti tanımı

Eklentiler, bir projedeki genkit.config.ts dosyası aracılığıyla çerçeveye kaydedilir. Yeni bir eklentiyi yapılandırabilmek için bir GenkitPlugin tanımlayan ve yukarıda tanımlanan PluginOptions ile yapılandıran bir işlev tanımlayın.

Bu durumda iki değerlendiricimiz (DELICIOUSNESS ve US_PHONE_REGEX_MATCH) var. Bu değerlendirmeciler, eklentiye ve Firebase Genkit'e buradan kaydedilir.

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;

Genkit'i yapılandırma

Yeni tanımlanan eklentiyi Genkit yapılandırmanıza ekleyin.

Gemini ile değerlendirme için güvenlik ayarlarını devre dışı bırakın. Böylece değerlendirici, zararlı olabilecek içerikleri kabul edebilir, algılayabilir ve puanlayabilir.

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

Test

Üretken yapay zeka özelliğinin çıktısının kalitesini değerlendirmek için geçerli olan sorunlar, LLM tabanlı bir değerlendiricinin değerlendirme kapasitesini değerlendirmek için de geçerlidir.

Özel değerlendiricinin beklenen düzeyde performans gösterip göstermediğini anlamak için doğru ve yanlış yanıtları net olan bir dizi test örneği oluşturun.

Lezzetli bir yemek örneği olarak şu JSON dosyasını deliciousness_dataset.json inceleyebilirsiniz:

[
  {
    "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."
  }
]

Bu örnekler insan tarafından oluşturulabilir veya bir LLM'den, seçilebilecek bir dizi test örneği oluşturmasına yardımcı olmasını isteyebilirsiniz. Ayrıca kullanılabilecek birçok karşılaştırma veri kümesi de vardır.

Ardından, değerlendirme aracını bu test durumlarına karşı çalıştırmak için Genkit CLI'yi kullanın.

genkit eval:run deliciousness_dataset.json

Sonuçlarınızı Genkit kullanıcı arayüzünde görüntüleyin.

genkit start

localhost:4000/evaluate adresine gidin.