Skip to main content

Overview

This cookbook demonstrates how to grade models that produce structured JSON output. The key idea: extract specific fields from the JSON and inject them into a custom judge prompt template. This is useful when:
  • Your model produces structured output (JSON with multiple fields)
  • You want an LLM judge to evaluate the content of specific fields semantically
  • You need to transform or format extracted fields before passing them to the judge

Example scenario

A model answers a question and produces structured output:
The grader:
  1. Parses the JSON and extracts the answer field
  2. Injects it into a judge template along with the original question
  3. Sends to an LLM judge: “Is this answer correct and well-supported?”
  4. Returns the judge’s PASS (1.0) or FAIL (0.0) score

Implementation

Define a simple Pydantic schema:

How TemplatedPromptJudgeGrader works

TemplatedPromptJudgeGrader allows you to:
  1. Parse structured output from a model
  2. Extract specific fields and transform them
  3. Inject them into a Handlebars template using {{variable}} syntax
  4. Send the rendered prompt to an LLM judge for semantic evaluation
The key mechanism is overriding extract_template_context(). This method:
  • Parses your structured JSON
  • Builds a dict of variables to inject into the template
  • Returns the dict for Handlebars rendering
When grading:
  1. extract_template_context() parses the JSON and builds context variables
  2. The user template is rendered with those variables using Handlebars
  3. The rendered prompt + judge system prompt are sent to an LLM judge
  4. The judge returns a binary decision (PASS/FAIL → 1.0/0.0)

Custom grader with extract_template_context override

Why override extract_template_context()?

The parent class provides basic context variables (thread, last_content, last_user_turn_content). But with structured output, you need to:
  1. Parse the JSON — Convert raw string to Pydantic model
  2. Extract fields — Get specific values (e.g., answer, confidence)
  3. Transform — Format them for readability (e.g., join lists with newlines)
  4. Inject into template — Provide clean variables for the judge prompt
This separation keeps the judge prompt readable and focused on semantic evaluation, not raw JSON strings.

Define judge prompts

The judge needs:
  • System prompt — Instructs the judge on evaluation criteria
  • User template — Dynamic prompt with {{variable}} placeholders filled from your parsed JSON using Handlebars syntax

Test cases

Create test inputs to validate parsing and template extraction:

Validation

We cannot run a live LLM judge in this notebook. Instead, we validate:
  1. Malformed JSON is caught and returns -1.0 during training
  2. Valid JSON is parsed correctly
  3. Template variables are extracted and injected correctly

Template extraction

Extract template context and verify that variables are available for the judge prompt:

Available template variables

When you override extract_template_context(), you have access to these default variables:
  • output_schema — JSON schema of the output model
  • turns — Full thread of all turns (system, user, assistant)
  • metadata — Custom metadata from the thread
  • context_turns — All turns including context
  • context_str — String representation of full thread
  • context_turns_without_last_user — All turns except the last user message
  • context_str_without_last_user — String without last user message
  • last_user_turn_content — Content of the last user turn
  • completion — The model’s completion
You can add custom variables by updating the context dict, as shown in the AnalysisGrader above.

Using the grader in training

To use AnalysisGrader in a real training recipe:
Note:
  • The model parameter is required and must be an InferenceModel (from a spawned judge model in your recipe)
  • The output_model must be BinaryJudgeOutput for binary grading
  • Handlebars templates render variables with {{variable}} syntax

Key takeaways

  1. Use TemplatedPromptJudgeGrader for semantic evaluation — When you need an LLM judge to evaluate extracted content, templated graders provide flexibility and control.
  2. Override extract_template_context() to parse and transform — Parse your structured JSON, extract fields, and inject them as clean variables. This keeps the judge prompt focused and readable.
  3. Handlebars templates make prompts reusable — Use {{variable}} syntax to create flexible judge prompts that work with any structured schema.
  4. Different penalties for training vs. eval — Use -1.0 for format errors during training (stronger signal) and 0.0 during evaluation.
  5. Validate early and return fast — Check for parsing errors in grade() before calling the judge, so malformed outputs don’t waste inference.
  6. The grader requires an InferenceModelTemplatedPromptJudgeGrader cannot be instantiated without a real judge model. In recipes, you’ll spawn this model and pass it to the grader constructor.