AI SWE Prep
0/10in AI/ML Engineering
AI/ML Engineering

Evaluation & Guardrails

You cannot improve what you cannot measure. Offline evals, LLM-as-judge, online signals, and safety guardrails.

~15 minLesson 42 of 60
Your progressNot started

The difference between a demo and a product is everything that happens after the model returns a plausible-looking answer. Because LLM outputs are probabilistic, you cannot ship them the way you ship a pure function — you have to measure quality, constrain behavior, and control cost and latency. This lesson is the operations layer of applied AI.

You cannot improve what you cannot measure

The first instinct — “I read a few outputs and they look good” — does not scale and does not survive a prompt change. You need evals: repeatable tests for a probabilistic system.

  • Offline evals run a fixed dataset of inputs (a “golden set”) through your system and score the outputs. Scoring can be exact-match for structured tasks, reference-based metrics, or an LLM-as-judge that rates answers against a rubric.
  • Online evals measure real traffic: thumbs up/down, task completion, escalation rate, and A/B tests between prompt or model versions.

Treat prompts and model choices like code: every change should run against your eval set before it ships. A prompt tweak that helps one case often quietly breaks three others — evals are how you catch that.

Classification threshold tunerthreshold = 0.50
≥ predict +
TP38
FP15
FN7
TN60
Precision72%
of predicted +, how many right
Recall84%
of actual +, how many caught
F178%
harmonic mean
actual positiveactual negativeRaise the threshold → precision up, recall down. There is no free lunch; pick the trade-off your product's error costs demand.

Guardrails: constraining an unreliable core

Guardrails are the checks around the model that keep bad outputs from reaching users or downstream systems:

  • Input validation — filter prompt-injection attempts and off-topic or disallowed requests before they reach the model.
  • Output validation — enforce structure (e.g. the response must be valid JSON matching a schema), and check for policy violations or leaked secrets.
  • Grounding checks — for RAG, verify the answer is actually supported by the retrieved context and isn’t a hallucination.
  • Human-in-the-loop — route low-confidence or high-stakes cases to a person.

A robust pattern is to ask the model for structured output and validate it against a schema, retrying on failure:

from pydantic import BaseModel

class Verdict(BaseModel):
    answer: str
    confidence: float
    sources: list[str]

def safe_generate(prompt, retries=2):
    for _ in range(retries + 1):
        raw = llm(prompt)
        try:
            return Verdict.model_validate_json(raw)  # reject malformed output
        except ValueError:
            continue
    raise ValueError("model failed to produce valid output")

The cost and latency triangle

Every production AI decision trades off three things: quality, latency, and cost. Pushing any one usually moves the others. Your levers:

  • Model tiering — use a small, cheap, fast model for easy requests and escalate only hard ones to a larger model. This “router” pattern often cuts cost by an order of magnitude.
  • Caching — identical or near-identical prompts can return a cached answer. Semantic caching (via embeddings) catches paraphrases too.
  • Streaming — stream tokens to the user so perceived latency drops even when total generation time doesn’t.
  • Prompt budgeting — shorter prompts and tighter max_tokens cut both cost and latency; retrieval helps by sending only the relevant context.

The senior mindset

Junior work stops when the model returns something reasonable. Senior work asks: How do I know it’s good? What happens when it’s wrong? What does this cost at a million requests a day, and how fast is it at p99? Answering those questions — with evals, guardrails, and cost controls — is the core of the role.

Pattern recognition

Variations

Worked problems

DrillEasy
  • Offline eval
  • Golden set

Build an offline eval set

You are launching a RAG assistant for internal IT policies. Design a first offline eval set that catches regressions without taking months to build.

Approach. Start small but representative. Cover common intents, high-risk policies, known failure modes, and answerability. Store expected supporting docs, not just final text.

Show solution

A strong first eval set might include 80–120 cases:

  • 40 common employee questions from search logs,
  • 20 high-risk policy questions about security, access, and reimbursements,
  • 15 unanswerable questions where the assistant should say it does not know,
  • 15 adversarial or prompt-injection attempts,
  • 10 recent policy changes.

Each row should store: question, expected answer notes, required source chunk IDs, allowed refusals, intent label, and risk slice.

from dataclasses import dataclass

@dataclass(frozen=True)
class EvalCase:
    case_id: str
    question: str
    required_sources: tuple[str, ...]
    rubric: str
    intent: str
    risk: str

Run this set on every prompt, retrieval, model, or chunking change. Add new cases from production incidents.

Complexity. O(n) model calls per eval run. The value comes from stable cases that represent real product risk.

DrillMedium
  • LLM judge
  • Rubrics

Spot LLM-as-judge pitfalls

A team uses an LLM judge with the prompt: Rate the answer from 1 to 10. Scores look high, but users still complain. Name the likely pitfalls and fix the judge setup.

Approach. A judge needs a task-specific rubric, hidden reference material, calibration against human labels, and checks for bias. Generic ratings create false confidence.

Show solution

Likely problems:

  • The rubric is vague, so the judge rewards fluent answers.
  • The judge sees no source context, so it cannot detect unsupported claims.
  • There is no calibration against human-reviewed examples.
  • The same model family may judge its own style too favorably.
  • Scores are averaged across slices, hiding failures in high-risk intents.

A better judge prompt asks for specific binary or ordinal criteria: groundedness, completeness, policy compliance, and citation correctness. It also includes the question, retrieved sources, candidate answer, and rubric.

def pass_rate(judgments):
    passed = [j for j in judgments if j["grounded"] and j["policy_ok"]]
    return len(passed) / len(judgments) if judgments else 0.0

Use the judge as a scalable signal, not the source of truth. Sample failures and passes for human review.

Complexity. O(n) over judgments to compute pass rate; O(n) model calls to produce them. The risk is metric validity, not computation.

DesignMedium
  • Online eval
  • Metrics

Choose an online metric

A customer-support assistant answers questions and can escalate to a human agent. Pick one primary online metric and two guardrail metrics for an A/B test of a new prompt.

Approach. The primary metric should reflect user value. Guardrails catch ways to game it, such as refusing too often or giving fast but wrong answers.

Show solution

Primary metric: successful self-service resolution rate — the user got an answer and did not reopen or escalate within a defined window.

Guardrails:

  1. Unsupported-claim rate from sampled citation/grounding checks.
  2. Escalation and refusal rate by intent so the new prompt cannot improve resolution by hiding hard cases or over-refusing.

Also watch p95 latency and cost per resolved conversation.

def resolution_rate(conversations):
    resolved = 0
    for c in conversations:
        if c["answered"] and not c["escalated"] and not c["reopened_within_24h"]:
            resolved += 1
    return resolved / len(conversations) if conversations else 0.0

Do not use thumbs-up alone as the primary metric. Feedback is sparse and biased toward users with strong feelings.

Complexity. O(n) over conversations. Metric design matters more than the aggregation code.

The pitfall to avoid

Your progressNot started