For AI agents: the complete documentation index is available at https://viteval.dev/llms.txt, the full documentation bundle is available at https://viteval.dev/llms-full.txt, and this page is available as Markdown at https://viteval.dev/guide/custom-scorers.md.
V1 release candidate available.Migration guide →
GitHub

Write a custom scorer

Use createScorer() when a built-in check does not express your application's requirements. This example compares order IDs after trimming and normalizing case.

Prerequisites

  • Complete Getting started and keep its Vitest configuration.
  • Use string outputs and expected values for this example. No API key is needed.

Steps

1

Define the check

Create src/normalized-order-id.ts:

import { createScorer } from 'viteval';

export const normalizedOrderId = createScorer<string>({
  name: 'normalized-order-id',
  score: ({ output, expected }) => ({
    score: output.trim().toUpperCase() === expected ? 1 : 0,
    metadata: { normalized: output.trim().toUpperCase() },
  }),
});

The callback can be synchronous or asynchronous. Return a finite score and any metadata that will help explain the result. Viteval attaches the configured name.

2

Use the scorer in an evaluation

Replace src/viteval.eval.ts with:

import { evaluate } from 'viteval';
import { normalizedOrderId } from './normalized-order-id';

evaluate('Order extraction', {
  data: [
    { input: 'Please cancel ord-2087.', expected: 'ORD-2087' },
    { input: 'How do I update my address?', expected: '' },
  ],
  task: ({ input }) => input.match(/\bORD-\d+\b/i)?.[0] ?? '',
  scorers: [normalizedOrderId],
  threshold: 1,
});

Verification

pnpm exec viteval run

Both cases pass because the scorer normalizes the extracted ID. Remove .toUpperCase() from the scorer and run again. The lowercase case now fails. Restore normalization after the check.

Troubleshooting

The case fails without a numeric score

Save a JSON report to inspect the score and metadata in the dashboard. Return score: null when your scorer cannot produce a measurement. Null contributes zero to aggregation, while throwing an error fails the case regardless of its threshold. Inspect the score metadata or execution errors in a saved report.

References