Skip to main content

Grader description

This example shows how to build a custom grader to train on classification accuracy against a groundtruth label. It is common to require a JSON formatted output from an LLM, where one or more of the keys in the output are a predicted label from a set of possible labels. An example of this, if we asked an LLM to analyze a call transcript and extract information: Example prompt:
Example output:
The grader we will build compares the values predicted for sentiment and escalation against groundtruth stored in each sample’s metadata. This same grader would work for any number of labels in the output, and any expected JSON format.

Pseudocode

This is the pseudocode for our grader:
  • Validate a text completion in JSON format against a pydantic model
  • If completion does not comply with expected format, return -1.0 reward
  • Compare predicted category against ground truth label
    • Returns binary scores (1.0 for correct, 0.0 for incorrect)

Implementation

How label matching works

The grader uses the same key (label_key) to extract labels from two places:
  1. From the Pydantic output: Uses getattr(prediction, label_key) to get the predicted label
  2. From sample metadata: Uses sample.metadata.get(label_key) to get the ground truth
Example with label_key="sentiment":
  • Predicted: prediction.sentiment"angry"
  • Ground truth: sample.metadata["sentiment"]"angry"
  • Score: 1.0 (match!)
This design keeps the grader simple and ensures the field names are consistent across your Pydantic schema and dataset metadata.

Why -1.0 for malformed outputs in training?

During training with RL, we use -1.0 for malformed outputs instead of 0.0 because:
  1. Stronger penalty signal: -1.0 tells the RL algorithm that malformed output is worse than just getting the wrong category. This encourages the model to always produce valid JSON.
  2. Distinguishes failure modes:
    • -1.0 = “You broke the format”
    • 0.0 = “You followed the format but chose the wrong category”
    • 1.0 = “Perfect!”
  3. Faster convergence: The stronger signal helps the model learn to produce structured output early in training, before fine-tuning category predictions.
During evaluation, we use 0.0 because we only care about binary correctness (right or wrong), not degrees of failure.

Test cases

We create 3 simple test cases:
  • correct completion: right format and labels
  • incorrect completion: right format, wrong labels
  • malformed completion: label values are not supported, likely a hallucination; could also be incorrect JSON, like a missing curly brace

Validation

Run tests on the mock samples

Key takeaways

  1. Always validate structured output - Use Pydantic schemas and handle parse errors gracefully with pydantic parse
  2. Different penalties for training vs. eval - Penalize format errors more heavily during training
  3. Log scores for tracking - Use self.add_log() to send metrics to training loggers
  4. Include reasoning in grades - Helps debug model behavior during development