Regelbasierte Bewertungen erstellen

Automatisieren Sie die Grundlagen: Verwenden Sie Code, um einfache Fehler zu erkennen.

Nachdem Sie nun wissen, welche Fehler Sie mit regelbasierten Auswertungen erkennen möchten, können Sie die entsprechenden Auswertungsfunktionen implementieren:

  • evalDataFormat(): Prüft, ob das Datenformat korrekt ist. Dazu gehören gültiges JSON, alle Schlüssel vorhanden, keine leeren Werte, Motto unter sechs Wörtern, hexadezimale Farben.
  • evalContrastRatio(): Prüft, ob das Kontrastverhältnis zwischen Text und Hintergrundfarbe zugänglich ist.

Regelbasierte Auswertungen implementieren

Bewertungsmethode auswählen

Die Bewertungskriterien sind binär. Ihre regelbasierten Auswertungsfunktionen sollten eine binäre Ausgabe erzeugen, z. B. ein PASS- oder FAIL-Label.

  • Ausgabe der ThemeBuilder-App (vollständiges Designobjekt) → evalDataFormat()PASS- oder FAIL-Label. PASS, wenn das Datenformat alle Einschränkungen erfüllt. Andernfalls FAIL.
  • Ausgabe der ThemeBuilder-App (Farbpalettenobjekt) → evalContrastRatio()PASS- oder FAIL-Label .PASS, wenn das Verhältnis > 4,5 ist. Andernfalls FAIL.

Auswertungstyp definieren

Der Messwert PASS oder FAIL ist ein boolescher Wert. Sie können ihn aber zur besseren Lesbarkeit als String-Label (Kategorie) implementieren.

Um die Dinge einfach zu halten, können Sie denselben TypeScript-Typ für Ihre regelbasierten Auswertungen und die LLM-Auswertungen verwenden, die Sie später implementieren. Erstellen Sie einen EvalResult-Typ, der eine binäre EvalLabel-Kategorie und ein rationale-Feld für das Auswertungsmodell enthält, um die Bewertung zu erklären.

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

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

Auswerter implementieren

Zod ist ein hervorragendes Tool für die Schemavalidierung, da es sowohl die JSON-Struktur als auch benutzerdefinierte Regeln verarbeitet. Es ist deklarativ, wodurch der Validierungscode lesbar ist. Definieren Sie detaillierte Fehlerberichte mit spezifischen Pfaden und Gründen für Fehler, um die Fehlerbehebung zu erleichtern.

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

Kontrastverhältnis

Bewahren Sie die Domainlogik, z. B. die Berechnungen des Kontrastverhältnisses, in separaten Hilfsfunktionen auf.

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

Sehen Sie sich unseren Auswertungscode für evalDataFormat() und evalContrastRatio() an.

Regelbasierte Auswertungen testen

Regelbasierte Auswertungen sind deterministisch. Sie können also klassische Einheitentests implementieren, um ihr Verhalten zu prüfen. Erstellen Sie Tests, um verschiedene Ausgaben durch die Auswerter zu senden und zu prüfen, ob sie das erwartete PASS- oder FAIL-Label zurückgeben.

Wenn ein Testfall erwartet, dass der Auswerter ein FAIL zurückgibt, und dies geschieht, gibt der Test ein PASS aus, da sich der Auswerter wie vorgesehen verhalten hat.

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

Jetzt ausprobieren