Ontwikkel op regels gebaseerde evaluaties

Automatiseer de basis: gebruik code om simpele fouten op te vangen.

Nu je weet welke fouten je wilt opvangen met op regels gebaseerde evaluaties, is het tijd om de bijbehorende evaluatiefuncties te implementeren:

  • evalDataFormat() : Controleert of het gegevensformaat correct is. Dit omvat geldige JSON, alle sleutels aanwezig, geen lege waarden, motto mag niet meer dan zes woorden bevatten, hexadecimale kleuren.
  • evalContrastRatio() : Controleert of de contrastverhouding tussen tekst en achtergrondkleur beschikbaar is.

Implementeer op regels gebaseerde evaluaties.

Kies een scoringsmethode

De evaluatiecriteria zijn binair. Uw op regels gebaseerde evaluatiefuncties moeten een binaire uitvoer produceren, zoals een label PASS of FAIL .

  • Uitvoer van de ThemeBuilder-app (volledig thema-object) → evalDataFormat() → label PASS of FAIL . PASS als het gegevensformaat aan alle beperkingen voldoet. FAIL anders.
  • Uitvoer van de ThemeBuilder-app (kleurpaletobject) → evalContrastRatio() → label PASS of FAIL . PASS als de verhouding > 4,5 is. FAIL anders.

Definieer een evaluatietype

De PASS of FAIL indicator is een booleaanse waarde, maar je kunt ervoor kiezen om deze voor de leesbaarheid als een tekenreekslabel (categorie) te implementeren.

Om het overzichtelijk te houden, kun je hetzelfde TypeScript-type gebruiken voor zowel je op regels gebaseerde evaluaties als de LLM-beoordelingsevaluaties die je later implementeert. Maak een EvalResult -type aan dat een binaire EvalLabel -categorie en een rationale veld voor het beoordelingsmodel om de score toe te lichten omvat.

enum EvalLabel {
    PASS = "PASS",
    FAIL = "FAIL"
}

interface EvalResult {
    label: EvalLabel;
    rationale?: string;
}

Implementeer evaluatoren

Zod is een uitstekend hulpmiddel voor schemavalidatie, omdat het zowel de JSON-structuur als aangepaste regels verwerkt. Het is declaratief, waardoor de validatiecode leesbaar is. Definieer gedetailleerde foutrapporten met specifieke paden en redenen voor fouten, voor eenvoudigere probleemoplossing.

import { z } from 'zod';
import { MAX_WORD_COUNT } from './app.config';

const hexColorRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;

// Reusable schema for hex colors
const HexColor = z.string().regex(hexColorRegex, { message: "Invalid hex color code" });

// zod schema definition for AppOutput
export const AppOutputSchema = z.object({
  motto: z.string().min(1, { message: "Motto is missing or empty" }).refine((val) => {
    const words = val.replace(/[^\w\s]|_/g, "").trim();
    const count = words ? words.split(/\s+/).length : 0;
    return count > 0 && count <= MAX_WORD_COUNT;
  }, { message: `Motto must be between 1 and ${MAX_WORD_COUNT} words` }),
  colorPalette: z.object({
    textColor: HexColor,
    backgroundColor: HexColor,
    primary: HexColor,
    secondary: HexColor
  }).catchall(HexColor)
});

Contrastverhouding

Houd domeinlogica, zoals de berekeningen van de contrastverhouding, in aparte hulpprogramma's.

/*
 * Input: ColorPalette {"textColor":"#333333","backgroundColor":"#000000", ...}
 * Output: EvalResult {"status":"FAIL","rationale":"Contrast ratio is 1.66:1 (must be >= 4.5:1)."}
 * minContrastRatio is an app config variable, MIN_CONTRAST_RATIO = 4.5
*/
export function evalContrastRatio(colorPalette: ColorPalette, minContrastRatio: number): EvalResult {
  if (!colorPalette || !colorPalette.textColor || !colorPalette.backgroundColor) {
    return { status: EvalLabel.FAIL, rationale: "Missing textColor or backgroundColor." };
  }
  try {
    const ratio = getContrastRatio(colorPalette.textColor, colorPalette.backgroundColor);
    const rationale = `Contrast ratio is ${ratio.toFixed(2)}:1 (must be >= ${minContrastRatio}:1).`;
    if (ratio < minContrastRatio) {
      return { status: EvalLabel.FAIL, rationale };
    }
    return { status: EvalLabel.PASS, rationale };
  } catch (e) {
    return { status: EvalLabel.FAIL, rationale: "Could not calculate contrast ratio (invalid hex?)." };
  }
}

Bekijk onze evaluatiecode voor evalDataFormat() en evalContrastRatio() .

Test regelgebaseerde evaluaties

Op regels gebaseerde evaluaties zijn deterministisch, dus je kunt klassieke unit tests implementeren om hun gedrag te controleren. Bouw je tests zo dat ze verschillende outputs door de evaluatoren laten lopen en controleer of ze het verwachte PASS of FAIL label retourneren.

Als een testcase verwacht dat de evaluator een FAIL retourneert en dat ook doet, dan geeft de test een PASS als uitvoer, omdat de evaluator zich naar behoren heeft gedragen.

import { MIN_CONTRAST_RATIO } from '../src/app.config'; // 4.5

const testCases = [
  {
  // ...
      appOutput: {
        motto: "Test motto",
        colorPalette: {
          textColor: "#333333",
          backgroundColor: "#000000",
          primary: "#FF0000",
          secondary: "#333333"
        }
      },
    expected: {
      // Dark grey on black (low contrast): FAIL
      contrast: EvalLabel.FAIL
    }
  }
  // ... more test cases
];

testCases.forEach((testCase) => {
  const result = evalContrastRatio(
    testCase.appOutput.colorPalette as any, MIN_CONTRAST_RATIO
  );
  const actualEvalLabel = result.label;
  const expectedEvalLabel = testCase.expected.contrast;
  const isSuccess = actualEvalLabel === expectedEvalLabel;
 // ...
});

Probeer het eens.