Genkit Değerlendirme Eklentisi Yazma

Firebase Genkit, test durumu çıktılarının özel olarak değerlendirilmesini destekleyecek şekilde genişletilebilir. Bunun için LLM'yi yargılama amacıyla veya yalnızca programatik olarak kullanabilirsiniz.

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ğerlendirme (test) için iki temel yaklaşım vardır: bulgusal değerlendirme ve LLM tabanlı değerlendirme. Sezgisel yaklaşımda, geleneksel yazılım geliştirmede olduğu gibi deterministik bir işlev tanımlarsınız. LLM tabanlı bir değerlendirmede içerik bir LLM'ye geri beslenir ve LLM'den sonucu, istemde belirlenen ölçütlere göre puanlaması istenir.

LLM tabanlı Değerlendirme Araçları

LLM tabanlı bir değerlendirme uzmanı, üretken yapay zeka özelliğinizin girdisini, bağlamını veya çıktısını değerlendirmek için LLM'den yararlanır.

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

  • İstem
  • Puanlama işlevi
  • Bir değerlendirmeci işlemi

İstemi tanımlama

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

Genkit, giriş/çıkış şeması doğrulaması gibi özelliklerle istemleri tanımlamanın ve yönetmenin kolay bir yolunu sunan dotprompt içerir. Değerlendirme istemi tanımlamak için dotprompt aracını nasıl kullanabileceğiniz aşağıda açıklanmıştır.

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

Puanlama işlevini tanımlama

Şimdi, istemin gerektirdiği şekilde output öğesini içeren bir örnek alacak işlevi tanımlayıp sonucu puanlayın. Genkit test durumlarında zorunlu bir alan olarak input, output ve context için isteğe bağlı alanlar bulunur. Değerlendirme için gerekli tüm alanların mevcut olduğunu doğrulamak değerlendirmecinin sorumluluğundadır.

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

Değerlendirmeci işlemini tanımlama

Son adım, değerlendirici işleminin kendisini tanımlayan bir fonksiyon yazmaktır.

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

Sezgisel Değerlendirme Araçları

Sezgisel değerlendirme aracı, üretken yapay zeka özelliğinizin girdisini, bağlamını veya çıkışını değerlendirmek için kullanılan herhangi bir fonksiyon olabilir.

Genkit'teki bulgusal değerlendirmeciler 2 bileşenden oluşur:

  • Puanlama işlevi
  • Bir değerlendirmeci işlemi

Puanlama işlevini tanımlama

Tıpkı LLM tabanlı değerlendirme uzmanı gibi puanlama işlevini tanımlayın. Bu durumda, puanlama işlevinin jüri LLM'si veya yapılandırması hakkında bilgi sahibi olmasına gerek yoktur.

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

Değerlendirmeci işlemini tanımlama

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

Yapılandırma

Eklenti Seçenekleri

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

En azından hangi metriklerin kaydedileceğini tanımlamak gerekir.

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

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

Bu yeni eklenti, hakim 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, projedeki genkit.config.ts dosyası aracılığıyla çerçeveye kaydedilir. Yeni bir eklenti yapılandırabilmek için GenkitPlugin tanımlayan ve yukarıda tanımlanan PluginOptions ile yapılandıran bir işlev tanımlayın.

Bu örnekte DELICIOUSNESS ve US_PHONE_REGEX_MATCH adlı iki değerlendirme uzmanımız var. Bu değerlendirmeciler, eklentiye ve Firebase Genkit'e burada kayıtlıdır.

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;

Genkit'i yapılandırma

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

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

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

Test

Üretken yapay zeka özelliğinin çıktılarının kalitesini değerlendirmede geçerli olan sorunlar, LLM tabanlı bir değerlendirmecinin değerlendirme kapasitesinin değerlendirilmesi için de geçerlidir.

Özel değerlendiricinin beklenen düzeyde performans gösterip göstermediğine dair fikir edinmek için net bir doğru ve yanlış cevabı olan bir dizi test durumu oluşturun.

Lezzet konusuna örnek olarak şu json dosyasına benzer: 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."
  }
]

Bu örnekler gerçek kişiler tarafından oluşturulabilir veya LLM'den (büyük dil modeli) seçilebilecek bir test durumu grubu oluşturmaya yardımcı olmasını isteyebilirsiniz. Kullanabileceğiniz birçok karşılaştırma veri kümesi de vardır.

Ardından, değerlendiriciyi bu test durumlarında çalıştırmak için Genkit KSA'yı 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 gidiş rotasını izle.