← All courses ← Course home

Lesson 07 of 08

Evaluate generations

Look at the pictures before you score them. Open-code what is missing (write what you see in plain words), group the failures into axial buckets (a few shared groups), then automate only a yes-or-no check those groups support.

Agent brief (llms.md)

Why this matters when the model runs on a phone

A personalized generator can miss the subject, drift off the style you wrote down, smear artifacts, or ignore the prompt while still looking visually polished. Those failures do not show up in one hand-picked seed. If you put the model on a phone, collect a small golden set. Generate it on the Mac preview, after merge, and on the device. Then read the images before anyone invents a score.

This lesson does not relax merge-then-export. You still bake the LoRA into the base (merge the LoRA into the base and export one model file) and ship the merged .aimodel folder. Evaluation judges that baked resource. It does not attach an adapter at runtime.

Look before you score. First read real examples of what the model makes. Then build simple checks for the problems you see most often. Open-code first (plain notes on each image), then axial buckets (shared groups), then a yes-or-no check. The intro this lesson follows is Hamel Husain and Shreya Shankar, Evals for AI systems. Cite that talk once in this course.

The steps, one box at a time

GoldenFixed prompts and seeds
GoldenFixed prompts and seeds
GeneratePre, merge, device
GoldenFixed prompts and seeds
GeneratePre, merge, device
Open codeNotes on each image
GoldenFixed prompts and seeds
GeneratePre, merge, device
Open codeNotes on each image
AxialSubject, style, artifact, ignore
GoldenFixed prompts and seeds
GeneratePre, merge, device
Open codeNotes on each image
AxialSubject, style, artifact, ignore
AutomateBinary rubric, CLIP second

Environment setup

Use the same Mac uv project. MPS or CPU. No CUDA. Keep the device app from lesson 05 so the third generation pass is the baked resource, not a notebook preview.

cd diffusion-lora-coreai
uv run python -c "import torch; print(torch.__version__); print('MPS:', torch.backends.mps.is_available())"
mkdir -p evals/golden evals/pre evals/merged evals/device evals/open-codes
uv run python generate_eval_grid.py --stage pre --out evals/pre
uv run python generate_eval_grid.py --stage merged --out evals/merged

Build a golden set

Write eight to twenty contracts you can pass or fail. Each row is a prompt, a seed, and one success sentence from lesson 02. Include subject shots, style shots, a negative (the subject must not appear), and one prompt the model liked to ignore during training.

{
  "id": "mug-window-04",
  "prompt": "the blue enamel mug on a sunlit windowsill, product photo",
  "seed": 1042,
  "stage": "device",
  "success": "The mug is recognizable as the training subject. The sill is secondary.",
  "runtime_lora_swap": false
}

Generate the grid three times: base or pre-merge preview, merged Mac export, and on-device pipeline. Same prompt. Same seed. If merge looks right and the device looks like the base, the resource folder or tokenizer is the first suspect.

Open-code the pictures

Sit with the grid. Open-code means you write what failed in plain language before you name a category.

{
  "id": "mug-window-04",
  "stage": "device",
  "open_codes": [
    "handle is missing",
    "enamel color is close",
    "extra mug in the background"
  ]
}

Axial buckets and one taste owner

Axial means you group those notes into a few shared buckets. Four buckets cover this course:

Pick one person who knows the product well to decide what good and bad look like. Reviewers can challenge a bucket. They should not each invent their own list. If two people cannot put the same image in the same bucket, the definition is still too fuzzy.

Yes-or-no checks. CLIP is second.

Turn each bucket into a yes-or-no. "Is the training mug present?" is a rubric. "Quality 1-5" is not. Code can catch some artifacts (empty file, tiny dimensions, near-duplicate of the base). Subject and style still need a human or a yes-or-no judge aligned to that human.

RUBRIC = """
Answer PASS or FAIL only for this one question:
Does the image show the contracted subject from the success sentence?

Success sentence: {success}
Prompt: {prompt}
If the subject is absent, swapped, or unrecognizable, FAIL.
"""

CLIP similarity to a reference photo can be a secondary alarm. It is not the eval. A high CLIP score can still miss the style contract. A low score can flag a crop or a color shift that a person would still accept. Use it to sort the queue, then read the pictures.

Instruments stays separate

Elapsed time, the extra time to get the model ready, and memory belong to the on-device pipeline lesson and to Xcode Instruments. Do not mix speed into the quality check. A fast wrong image is still a fail. A slow correct image is a performance bug, not a LoRA miss.

When this goes wrong

Done when

Keep learning

The same error-analysis path on writing style is Evaluate the writing style. On labels it is Evaluate the clothing classifier.

PyTorch to Core AI in Xcode · From the metal to the model · Core AI models, typed · Model architectures in plain English · LLM LoRA for your writing style

Key concepts

  • Look before you score: open-code, then axial buckets, then yes or no checks.
  • Build a golden set of fixed prompt, seed, and success-sentence contracts.
  • Generate three grids: pre-merge, merged Mac, and on-device.
  • CLIP is a secondary alarm. Speed belongs in Instruments, not in quality eval.

Takeaways

  • One taste owner decides the buckets. Do not average 1-5 scores.
  • Judge the baked device resource, not the adapter.
  • If the device grid looks like the base, check the resource folder first.