LatentEval

TOOL | Evaluation design

Code grader playground: score one expected and actual pair

Paste one expected answer and the model's output, pick graders, and see each score with its reason. Exact match names the first differing character. On the returns-desk example, token F1, BLEU, ROUGE-L and chrF score outside window against outside_window at 0, 0.43, 1.0 and 0.68. A near-miss probe names the step that would make a fail pass. Score a whole file on the results file grader, or build a pipeline on the normalizer builder. Your texts stay here.

With the example's pair, one difference at position 8 fails Exact match while the four scoring graders return 0, 0.43, 1.0 and 0.68.

Your texts are processed in this browser tab, and you can check by going offline after the page loads. This page never uploads them.

The reference answer for this case. Paste or type the text.

Check this value.

Expected kind

With any-of, each line is a separate acceptable answer and each grader takes the best match.

The output your model returned for this case.

Check this value.

Graders

Code-point equality with no normalization.

Run a normalization pipeline on both sides, then compare.

Does the output contain the expected text?

A regular expression tested against the output.

Read a number from each side and compare within a tolerance.

Parse the output as JSON and validate it against a schema.

Bag-of-tokens F1 between the expected and output after normalization.

Sentence BLEU-4 with 13a tokenization and exponential smoothing.

F1 over the longest common subsequence of words, without stemming.

Character n-gram F-score with beta 2, orders 1 to 6, whitespace removed.

Normalized exact match

The steps applied to both sides before comparing.

Check this value.

Contains
Match rule

Whether the output must contain any one reference or every reference.

Position

Where in the output the reference must appear.

Token F1

The steps applied to both sides before tokenizing.

Check this value.

Score at or above this value counts as pass. Leave empty for score only.

Check this value.

BLEU

Lowercase both sides before tokenization.

Score at or above this value counts as pass. Leave empty for score only.

Check this value.

ROUGE-L

Score at or above this value counts as pass. Leave empty for score only.

Check this value.

chrF

Score at or above this value counts as pass. Leave empty for score only.

Check this value.

Load a grader configuration or a normalization pipeline you exported before.

The figures below use the returns-desk example: case rd-017, expected outside_window, output outside window.

Graders run

7

Pass

0

Fail

3

Score only

4

GraderScoreResultWhy
Exact match 0.000 Fail First difference at position 8: expected _ (U+005F), output (U+0020 SPACE). Lengths: expected 14, output 14. Near miss: adding the join words with underscore step would make this pass.
Normalized exact match 0.000 Fail The texts still differ after normalization, first at position 8 of the normalized text. Near miss: adding the join words with underscore step would make this pass.
Contains 0.000 Fail The output does not contain the reference. Near miss: adding the join words with underscore step would make this pass.
Token F1 0.000 Score only Token F1 0.000 (0.00 on 0 to 100).
BLEU 0.429 Score only BLEU 0.429 (42.89 on 0 to 100).
ROUGE-L 1.000 Score only ROUGE-L 1.000 (100.00 on 0 to 100).
chrF 0.677 Score only chrF 0.677 (67.72 on 0 to 100).
Exact match

First difference at position 8: expected _ (U+005F), output (U+0020 SPACE). Lengths: expected 14, output 14.

First difference at
8
Expected character
_ U+005F
Output character
U+0020 SPACE
Expected length
14
Output length
14
Normalized exact match

The texts still differ after normalization, first at position 8 of the normalized text.

Text after each step
StepExpected after this stepOutput after this step
Originaloutside_windowoutside window
Trimoutside_windowoutside window
Lowercaseoutside_windowoutside window
First difference after normalization
8
Contains

The output does not contain the reference.

Reference
outside_window
Position
Not found
Token F1

Token F1 returned 0.000. No threshold is set, so there is no pass or fail.

Expected tokens
outsidewindow
Output tokens
outside window
Common tokens
0
Precision
0.000
Recall
0.000
F1
0.000
BLEU

BLEU returned 0.429. No threshold is set, so there is no pass or fail.

Expected tokens
outside _ window
Output tokens
outside window
Per-order matches and precision
1: 2/2 = 1.000
2: 0/1 = 0.500
3: 0/0
4: 0/0
Smoothed orders
2
Effective order
2
Output length (c)
2
Closest reference length (r)
3
Brevity penalty
0.607
Score
0.429
Score (0 to 100)
42.89
ROUGE-L

ROUGE-L returned 1.000. No threshold is set, so there is no pass or fail.

Expected tokens
outside window
Output tokens
outside window
LCS tokens
2
LCS tokens highlighted
outside window
Precision
1.000
Recall
1.000
F1
1.000
chrF

chrF returned 0.677. No threshold is set, so there is no pass or fail.

Per-order matches
OrderOutput n-gramsExpected n-gramsPer-order matches
1131413
2121311
311129
410117
59105
6893
Mean precision
0.728
Mean recall
0.666
Beta
2
F-score
0.677

This page scores one pair under each grader you selected: exact match fails on any changed character, token F1 credits partial word overlap, and a schema check tests the output's structure and values without the expected answer.

To score a whole file with these graders, use the results file grader. To build and export the normalization pipeline your harness applies, use the normalizer builder.

Export

Saves each grader and its settings, without your expected and output texts.

Each grader runs independently on the same expected and output pair.How?

How this is calculated

Exact match compares the two texts as sequences of Unicode code points with no normalization. A single differing code point, including invisible characters such as a no-break space or a byte order mark, makes the pair fail. The explanation names the first differing position, both characters with their Unicode code, and flags a leading or trailing whitespace difference, a case-only difference, or an NFC- or NFKC-only difference.

Normalized exact match runs the selected pipeline on both sides and then applies code-point equality. The default pipeline trims leading and trailing whitespace (the 29 characters Python's str.strip() removes) and lowercases both sides. SQuAD answer normalization lowercases, removes ASCII punctuation, removes English articles (a, an, the), collapses runs of whitespace to one space, and trims.

Contains checks whether the output contains each expected reference (any one or all of them) with no normalization. The match can be required anywhere or at the start.

Regex compiles the pattern as a JavaScript regular expression with the u flag always on. Anywhere finds the first match in the output. At the start pins the match to index 0. Whole text requires the entire output to match: the pattern is wrapped so that alternatives can backtrack to cover the full string. Expected text is not used. A Python-syntax pattern is refused with a hint naming the JavaScript equivalent.

Numeric reads one number from each side. Whole text requires the entire trimmed string to be a number. First number and last number find the first or last ASCII numeral sequence that does not follow a letter, digit, underscore, period or comma, and does not run into a digit or into a period or comma plus a digit, so v2.0 scored 0.83 reads 0.83 and The refund is $42.00. reads 42. Commas count only as exact three-digit separators. A leading sign counts only at the start of the text, after whitespace or after (. 50% is not read as 0.5. The pair passes when the absolute difference is within the larger of the absolute tolerance and the relative tolerance times the size of the expected value. When the expected text is not a number, the grader returns not judged.

JSON Schema parses the output as JSON after any selected pre-parse step and validates it with the schema evaluator. A schema keyword outside the supported set makes the result not judged. A parse failure shows the browser's own error message. A fail names each violation by JSON Pointer path, keyword and message.

Token F1 applies SQuAD answer normalization by default, splits on runs of Python's 29 whitespace characters, and computes bag-of-tokens precision, recall and F1. When both sides are empty after normalization (for example the against a), F1 is 1 by the SQuAD convention; one side empty gives 0. With multiple references, the grader takes the maximum F1.

BLEU computes sentence-level BLEU-4 with uniform weights, 13a tokenization (which splits off most punctuation, including _, and keeps a hyphen between letters, so refund-status stays one token), clipped n-gram counts and effective order: an order with no output n-grams is dropped. Exponential smoothing fills orders with no matches: the first such order gets a precision of 1 divided by twice its n-gram count, the next 1 divided by four times its count, and so on. This is method 3 in Chen and Cherry, "A systematic comparison of smoothing techniques for sentence-level BLEU" (WMT 2014). When the output is shorter than the closest reference, the brevity penalty is exp(1 minus the reference length divided by the output length); a tie in closeness takes the shorter reference. The score is 0 when no n-gram matches at any order. Post, "A call for clarity in reporting BLEU scores" (WMT 2018), found that BLEU on the same test set differs by up to 1.8 points on the 0 to 100 scale across common configurations, mostly through tokenization and normalization, so this page states its settings.

ROUGE-L tokenizes by lowercasing and splitting on every run of characters that are not Unicode letters or numbers. The longest common subsequence is found by dynamic programming. Precision is LCS divided by the output token count, recall is LCS divided by the expected token count, and F1 uses beta 1 (Lin, "ROUGE: a package for automatic evaluation of summaries," 2004, defines ROUGE-L with beta set very high for recall; this page computes F1 and states it). When one side is empty the score is 0. Pairs whose token counts multiply to over 25,000,000 are not computed.

chrF removes all whitespace from both sides and counts character n-gram matches for orders 1 through 6 over Unicode code points, with clipped counts against the best reference. Precision and recall are their means over orders where both sides have n-grams. The F-score uses beta 2, which gives recall twice the weight of precision: F = (1 + 4) times precision times recall, divided by 4 times precision plus recall, where 4 is beta squared. Beta 2 was the most promising setting across several values in Popovic, "chrF deconstructed: beta parameters and n-gram weights" (WMT 2016).

A near-miss probe runs on every fail. For exact match, normalized match and contains, the probe tries each formatting step on its own, in a fixed order (trim, lowercase, NFKC, collapse whitespace, strip trailing period or exclamation mark, join words with underscore, strip quotes) and names every step that turns the fail into a pass. If no single step passes, the probe runs all seven together; a pass then reads "several formatting differences." For regex, the probe tests with the i flag added. For JSON Schema, the probe tries stripping a code fence, then trimming. For numeric, the probe tries the other read modes. For continuous graders with a threshold, the probe flags a score within 0.1 below the threshold.

These overlap graders follow the settings stated above and have not been compared against a reference library.

Formula: Each grader runs independently on the same expected and output pair.

Worked example

Case rd-017: expected outside_window, output outside window. Exact match fails at position 8, where the expected text has _ (U+005F) and the output has a space (U+0020); both texts are 14 characters. Normalized exact match also fails, because trim and lowercase change neither side, and both near misses name the "Join words with underscore" step. Token F1 is 0: SQuAD normalization deletes the underscore, so the expected side becomes outsidewindow and shares no token with outside and window. BLEU is 0.428882: 13a tokenization gives three expected tokens and two output tokens, one-token matches are 2 of 2, the single two-token n-gram does not match and is smoothed to 0.5, orders 3 and 4 are dropped, and the brevity penalty is 0.606531. ROUGE-L is 1, because both sides split into outside and window. chrF is 0.677248, from a mean precision of 0.727567 and a mean recall of 0.665737 over orders 1 to 6.

Questions

Why does an answer that looks correct score 0 on exact match?

Exact match compares code points with no normalization at all. A single underscore versus a space, a trailing period, or a capital letter where the reference has lowercase is enough to fail. The explanation pane names the first difference and its Unicode codes. The near-miss probe shows which formatting step would close the gap. If the differences are consistent across your file, you can build a normalization pipeline on the normalizer page and export it for your harness.

Why do token F1 and ROUGE-L disagree on "outside window" against "outside_window"?

Token F1 with SQuAD normalization removes the underscore as punctuation, leaving one token outsidewindow on the expected side and two tokens outside, window on the output side, so the bags share nothing and F1 is 0. ROUGE-L splits on non-letter non-digit runs, which splits the underscore, so both sides become outside, window and the LCS covers both, giving F1 of 1. The difference is that SQuAD strips punctuation before splitting, while ROUGE-L splits on it.

Why does a completely wrong label score BLEU 0.275?

BLEU works on tokens. With 13a tokenization, outside_window and return_eligible each become three tokens, with _ in the middle. The shared _ gives a one-token precision of 1 of 3. The two-token and three-token orders have no matches and are smoothed to 0.25 each, the four-token order has no output n-grams and is dropped, and both sides have three tokens, so there is no brevity penalty. The geometric mean of 1/3, 0.25 and 0.25 is 0.275. The match comes from a shared delimiter token.

What is the difference between sentence BLEU and corpus BLEU, and why do the settings matter?

Sentence BLEU scores one pair. Corpus BLEU pools n-gram counts across all pairs in a file and computes one score; the results file grader shows both. Sentence BLEU gives each pair its own brevity penalty, smoothing and effective order, while corpus BLEU applies one brevity penalty to the pooled counts and no effective order. Post (WMT 2018) found that BLEU on the same test set moves by up to 1.8 points on the 0 to 100 scale across common configurations, mostly through tokenization and normalization. A BLEU number without its settings is not comparable.

Which ROUGE-L does this page compute?

This page computes ROUGE-L as an F1 measure with beta 1 (equal weight to precision and recall). Lin's original paper (2004) sets beta to a very large value, making the score recall-dominated. This page does not apply stemming and does not use summary-level union LCS. Both choices are stated so you can compare: a harness using recall-weighted ROUGE-L or stemming can give a different number on the same pair.

Which chrF does this page compute?

This page computes chrF with beta 2, character orders 1 through 6, and all whitespace removed before counting. This is not chrF++ (which adds word n-grams). Beta 2 gives recall twice the weight of precision. The score is computed over Unicode code points, and case is preserved.

Can I paste a Python regex pattern?

JavaScript's regular expressions differ from Python's in a few constructs. The u flag is always on, which makes some Python escapes invalid (for example \- and \_). Named groups use (?<name>...). End-of-string \Z becomes $. Inline flags like (?i) are set with the toggle instead. The page shows a hint when a Python pattern is detected.

How does the numeric grader read a number from text?

In whole-text mode, the trimmed text must be one number with an optional sign, so 50% is not a number. In first-number and last-number mode, a number must not follow a letter, digit, underscore, period or comma, and must not run into a digit or into a period or comma plus a digit; there 50% reads 50. Commas count only as three-digit separators. A sign counts only at the start, after whitespace or after (, so x=-5 reads 5. Arabic-Indic digits are not read, though Python's float() accepts them.

Will my harness give the same score as this page?

Only if the settings match. This page states every setting it uses: the tokenizer, the smoothing method, whether effective order is used, the beta value and the normalization steps. Its BLEU, ROUGE-L and chrF follow those settings and have not been compared against a reference library, so a library run with the same settings can still give a different number. For normalization, the normalizer builder checks a pipeline against your harness's verdicts row by row.

Sources

  1. chrF deconstructed: beta parameters and n-gram weightsPopovic, WMT 2016 (doi:10.18653/v1/W16-2341)
  2. ROUGE: a package for automatic evaluation of summariesLin, Text Summarization Branches Out, 2004
  3. BLEU: a method for automatic evaluation of machine translationPapineni et al., ACL 2002 (doi:10.3115/1073083.1073135)
  4. A call for clarity in reporting BLEU scoresPost, WMT 2018 (doi:10.18653/v1/W18-6319)
  5. A systematic comparison of smoothing techniques for sentence-level BLEUChen and Cherry, WMT 2014 (doi:10.3115/v1/W14-3346)