建立以規則為準的評估

自動執行基本作業:使用程式碼找出簡單的錯誤。

現在您已瞭解要透過以規則為準的評估功能偵測哪些失敗情形,接下來請實作對應的評估工具函式:

  • evalDataFormat():檢查資料格式是否正確。包括有效的 JSON、所有鍵都存在、沒有空值、座右銘少於六個字、十六進位顏色。
  • evalContrastRatio():檢查文字與背景的顏色對比度是否符合無障礙標準。

導入以規則為準的評估

選擇評分方法

評估標準為二元,以規則為準的評估函式應產生二進位輸出內容,例如 PASSFAIL 標籤。

  • ThemeBuilder 應用程式輸出內容 (完整主題物件) → evalDataFormat()PASSFAIL 標籤。PASS資料格式是否符合所有限制。其他情況則為 FAIL
  • ThemeBuilder 應用程式輸出內容 (調色盤物件) → evalContrastRatio()PASSFAIL 標籤。如果比例大於 4.5,則為 PASS。其他情況則為 FAIL

定義評估類型

PASSFAIL 指標是布林值,但您可以選擇將其實作為字串標籤 (類別),方便閱讀。

為保持精簡,您可以對稍後實作的規則式和 LLM 評估使用相同的 TypeScript 型別。建立包裝二進位 EvalLabel 類別的 EvalResult 型別,以及供評估模型說明評分的 rationale 欄位。

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

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

導入評估工具

Zod 是很棒的結構定義驗證工具,可同時處理 JSON 結構和自訂規則。這項功能採用宣告式設計,因此驗證碼容易閱讀。定義詳細的錯誤報告,其中包含特定路徑和失敗原因,方便進行疑難排解。

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

對比度

將對比度計算等網域邏輯保留在個別公用程式函式中。

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

請參閱 evalDataFormat()evalContrastRatio()評估人員程式碼

測試以規則為準的評估

以規則為準的評估是決定性的,因此您可以實作傳統單元測試來檢查其行為。建立測試,透過評估人員執行各種輸出內容,並判斷輸出內容是否傳回預期的 PASSFAIL 標籤。

如果測試案例預期評估工具會傳回 FAIL,且評估工具確實傳回 FAIL,則測試會輸出 PASS,因為評估工具的行為符合預期。

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

立即體驗