A transparent model-quality system

Inside the evaluation harness.

How I test a two-stage system — an interpreter that reads a photo and a natural-language edit into a measured AttributeSpec, and a generator that turns that spec into a reliable, safe, compact 3D color transform — and refuses everything outside its remit, honestly.

Interpreter → AttributeSpec Qwen2.5-VL-3B generator 64 LUT tokens · 17³ grade / clarify / refuse decoder-free v1 spine
64
discrete LUT codes
A model does not pass because its output looks plausible. It passes because the entire artifact survives a measurable chain of obligations.
01

Test the product behavior, not the training loss.

The harness starts from the client-visible contract: read a request into an AttributeSpec, route it as grade, clarify, or refuse, produce a valid transform, preserve image integrity, and decline what a global LUT cannot solve.

02

Make every failure attributable.

Boundary, syntax, decode, color direction, target fidelity, safety, and style are separate layers. A failure says what broke, not merely that a score went down.

03

Challenge the need for fine-tuning.

The SFT checkpoint must beat nulls, constants, deterministic recipes, prompt-only ablations, image ablations, and frontier prompting — otherwise the claim is narrowed.

04

Separate diagnosis from shipping.

Small slices and qualitative examples illuminate behavior. Only predeclared, adequately powered metrics can approve a release.

05

Be honest about the holdout.

The split is unit-aware, so no near-duplicate LUT straddles train and test; every held-out row is scored, not a convenient sample; and a supported row counts only with exactly 64 code positions. Where the frozen decoder is off, honesty slices use decoder-free proxies rather than pretending to measure color.

The deterministic stack

Nine lenses. One non-negotiable verdict.

Supported rows must clear every deterministic layer from L0 through L7. The L8 judge adds explanation and qualitative context, but it cannot rescue an invalid or unsafe transform. In v1 the frozen decoder stays disabled, so the decode-dependent layers (L2, L4–L7) run as decoder-free proxies or are owner-gated; the load-bearing spine is L0 boundary, L1 syntax, the routing metrics, and held-out token accuracy.

L0
Scope

Boundary & route

The interpreter's route is scored three ways. A grade must not be refused; a refuse passes only with the exact token <unsupported>, split into out_of_scope and out_of_gamut; clarify is its own class.

No partial compliance. No friendly prose.
L1
Form

Syntax

A supported output is exactly LUT-BOS, 64 valid code tokens, and LUT-EOS. Runtime constrained generation should make syntax failures implementation bugs.

Free generation measures learned discipline.
L2
Artifact

Decode & export

The 64 codes decode through the frozen VQ decoder into a finite canonical 17×17×17 residual LUT and a valid pinned .cube export.

Domain, grid, hashes, and interpolation must match.
L3
Compression

Tokenizer gate

The frozen tokenizer must satisfy reconstruction quality across the mean, difficult tail, source families, and target classes before model scores are trusted.

Bad compression cannot masquerade as bad SFT.
L4
Intent

Direction

Measured behavior_v2 must move in every requested direction — warmer, cooler, brighter, contrast toe and shoulder, matte, a global hue cast, per-tone-region hue, and per-hue saturation across seven sectors — within calibrated magnitude windows.

Intent is checked numerically, not by label matching.
L5
Similarity

Target fidelity

Depending on the row, the decoded LUT must match an exact target, one of several valid references, or a declared behavior window using image and chart ΔE00.

Underspecified requests get multiple valid answers — not a fake single truth.
L6
Integrity

LUT safety

Clip rate, out-of-range values, smoothness, foldover, neutral drift, and skin-locus behavior are tested before a transform can pass.

A pretty average cannot hide a dangerous tail.
L7
Semantics

Style recipe

Named styles must land inside recipe windows and remain discriminable from neighboring styles rather than collapsing into one generic warm filter.

Correct family, correct margin, no multi-match.
L8
Context

LLM / VLM judge

A pinned judge records perceptual and instruction-alignment commentary for review. It is evidence, not authority.

L8 cannot override L0–L7.
The decoder stays frozen and off in v1.
L2 and L4–L7 depend on decoding 64 codes into a LUT. Until the frozen decoder is owner-enabled, those layers run decoder-free proxies, and the training loop is steered by held-out, teacher-forced LUT-code token accuracy — the faithful-ish proxy that needs no decode, since the 64 codes deterministically decode to the target residual LUT.
METRIC = held-out token accuracy · direction max

The complete run, in motion

Follow one row from intent to evidence.

A release claim is the last frame, not the first. Watch the same frozen row move through generation, artifact recovery, deterministic measurement, statistical gating, and an auditable report.

Guided run ready
01 / Frozen row intake

Start with the product contract.

The harness binds a source image, the request, its gold route and AttributeSpec, an acceptance mode, and leakage-safe, unit-aware provenance before the model is called.

Request → AttributeSpec“Make the portrait a little warmer while keeping skin neutral.”route=grade · warmer=+1.6 · subtle_control
Freeze the row. Inputs and obligations are declared before inference.01 / 06

Interactive row walkthrough

Put one evaluation row through the harness.

Choose a representative request and generation mode. The simulation shows how the row is classified, parsed, decoded, measured, and finally accepted or rejected.

Row controls

Illustrative
“Make the portrait a little warmer while keeping skin neutral.”

This is an explanatory simulation of the real layer logic, not a live model call.

Layer-by-layer result

Ready
01Capture
02Generate
03Decode
04Measure
05Verdict
Routegrade
Acceptance modeBehavior window
Eval sliceSubtle control
Output budget64 codes
Awaiting run
Select a scenario and start the walkthrough.
·

Frozen evaluation design

One headline number, many ways to break it.

The aggregate pass rate answers “does it work?” The slices answer “where, for whom, and under what conditions does it stop working?”

usage_weighted_headline

The client-facing mix of common supported requests, reserved for the primary quality claim.

image_sensitivity

Identical text across different images where the correct LUTs must differ. Defends against a prompt-only shortcut.

hard_cli_inputs

Phone exports, screenshots, heavy JPEG compression, odd white balance, ICC variation, and size extremes.

subtle_control

Small but visible edits that expose a model that only knows exaggerated transformations.

style_discriminability

Single-style rows with neighbor-exclusion tests, recipe windows, and confusion analysis.

expert_holdout

Held-out PPR10K and FiveK expert identities absent from the SFT training set.

unseen_family

Held-out source, style, or LUT families that measure generalization beyond memorized packs.

interpreter

The interpreter's own scores: attribute-F1 against the gold AttributeSpec, three-way route accuracy, and over-refusal on valid work.

refuse_out_of_scope · out_of_gamut

Non-global edits versus global looks the frozen tokenizer cannot represent — each refusal family measured on its own.

paraphrase · named · nonce concept

Decoder-free honesty: paraphrases stay consistent, known styles map to real axes, and invented terms route to clarify or refuse instead of hallucinating.

unsupported + boundary_pairs

Local edits, geometry, generation, reference transfer, mixed traps, and contrastive near-boundary pairs.

Predeclared release criteria

A model ships on confidence bounds, not point estimates.

Every gated metric has a frozen slice, minimum sample size, direction of the bound, test family, and underpowered behavior. The current v1 headline floor is 350 rows because the reserve is approximately 382 eligible supported rows.

Supported prompt → LUT pass

Wilson lower ≥ 60%

All deterministic obligations from boundary through style.

Free-generation valid tokens

Wilson lower ≥ 85%

Valid 64-code sequence or exact refusal, measured over all rows.

Unsupported recall & precision

Each lower ≥ 80%

Catch out-of-scope work without refusing legitimate global edits.

Boundary F1 & mixed recall

Lower ≥ 80%

Includes traps that combine a supported lure with an impossible local task.

Near-boundary pair accuracy

Wilson lower ≥ 85%

Contrastive pairs differ by the smallest wording that changes supportability.

Over-refusal

Wilson upper ≤ 10%

The model cannot protect itself by saying “unsupported” to difficult valid work.

Safety failure

Wilson upper ≤ 5%

Absolute v1 gate covering clipping, foldover, neutral drift, and skin-locus risk.

Versus deterministic renderer

Paired lower ≥ +10pp

Primary headline advantage on the same frozen rows under the v1 power design.

Refusal recall by kind

Each lower ≥ 80%

Out-of-scope and out-of-gamut refusals are gated separately, so one family cannot hide behind the other.

Interpreter route accuracy

attribute-F1 + 3-way route

The interpreter's AttributeSpec must match the gold axes and pick grade, clarify, or refuse correctly.

Held-out token accuracy

direction: max

The decoder-free training metric: exact 64-code accuracy on the unit-aware holdout steers the SFT loop.

Statistics are part of the product contract.
Three final-report seeds, Wilson intervals, stratified paired bootstrap with at least 10,000 draws, paired binary tests, and Holm–Bonferroni over the ship-gate family.
min_N → evaluable, not silently pass

Results, measured honestly

Better than what?

Fine-tuning is not the default winner. This dashboard reports only what is measured today: the prompted-frontier pilot on a 5-row single-attribute grid, and this project's own measured proxies. Where an end-to-end result does not exist yet, it is marked pending — never filled with a number.

Chroma (this project) Frontier model Refused / truncated measured by construction pending
100%
valid 17³ .cube by construction — 64 codes → frozen decoder always yields a canonical LUT
9/9
completed frontier LUTs that were direction-correct and safe. Color intent is never the failure — completion is.
64 codes
to encode a full LUT, vs ~100,000 raw floats for a 4,913-row .cube
$1.4–2.4
frontier cost per usable LUT (8–17 min). Chroma target: ~$0, sub-second, local.

Completion reliability — valid full 17³ .cube

Prompted-frontier pilot, 5 single-attribute rows (warmer · cooler · more magenta · more green · brighter). Frontier failures are truncation or refusal, not wrong color.

Chroma (ours)100% by construction
Opus 4.880% 4/5
Sonnet 4.660% 3/5
GPT-5.5 xhigh40% 2/5
GPT-5.5 medium0% refused
Gemini 3.1 Pro0% token-capped
Source: docs/frontier_baseline_results.md (main grid). Gemini 3.1 Pro is structurally blocked — its route hard-caps output at ~65K tokens (~2,000 rows), so a full ~100K-token LUT is impossible regardless of prompt. Ours is 100% valid by construction (grammar-constrained 64-code decode), which is a structural guarantee, not the same measurement.

Cost & latency — full 5-row grid

Provider list prices; wall-clock per grid. Grand total ≈ $30.22 across all frontier configs.

Opus 4.8$9.76 51m
GPT-5.5 xhigh$9.05 16m
Sonnet 4.6$7.71 70m
Gemini 3.1 Pro$3.22 29m · 0 valid
GPT-5.5 medium$0.48 3m · 0 valid
Chroma (ours)~$0 <1s · target
Source: docs/frontier_baseline_results.md. Bars scaled to Opus ($9.76). Chroma cost/latency is a design target (local single-T4 / deterministic), not a benchmarked figure.

Output budget — the tractability story

A frontier model must emit every LUT row as text; Chroma emits 64 VQ codes a frozen decoder expands into the 4,913-row grid.

64
VQ codes (256-entry codebook) — Chroma
~100K
raw float tokens — frontier full .cube (4,913 rows)
≈ 1,500× smaller
Source: docs/model_architecture.md; docs/frontier_baseline_results.md. The compact budget is why a small local model can finish where frontier prompting truncates.

Chroma — measured proxies measured

These are the real numbers we have today. They are component measurements and decoder-free proxies — not an end-to-end harness pass rate, which does not exist yet.

Frozen tokenizer reconstruction

382-LUT dev holdout · CIEDE2000 (lower is better)

mean ΔE00 1.31
p95 ΔE00 3.34
PSNR 37.0 dB
gold gate ≤ 2.5

Interpreter / router

Qwen2.5-0.5B · holdout n=684 · ships as router only

route accuracy 0.884
refuse recall 1.00
clarify recall 1.00
over-refusal 0.132

Generator behavioral fidelity

P6 adapter · spec-conditioned · ruler ceiling ≈ 0.89

teacher-forced 0.708
best-of-N (deployable) 0.42
free-running greedy 0.159
greedy collapse 94%
Sources: tokenizer/final/manifest.json · docs/interpreter_results.md · docs/collapse_fix/README.md. Free-running greedy collapses (exposure bias, not a broken seam); best-of-N sample+rerank is the deployable mitigation. GRPO is planned, not shipped.

Configurations compared

ModelId$ in / out (1M)EffortCompletion
Chroma (ours)local · Qwen2.5-VL-3B + adapter~$0 · localdeterministic100% valid by construction
Opus 4.8claude-group/claude-opus-4-8$5 / $25medium4/5
Sonnet 4.6claude-group/claude-sonnet-4-6$3 / $15medium3/5
GPT-5.5openai-group/gpt-5.5$5 / $30xhigh / med2/5 · 0/5
Gemini 3.1 Progemini-group/gemini-3.1-pro$2 / $12—0/5 (token cap)
Source: docs/frontier_baseline_results.md §Configurations. Prices are provider list prices.

What this dashboard does and does not claim

✓ True today
  • Every output is a valid, safe-domain 17³ LUT by construction (grammar-constrained 64-code decode).
  • Deterministic, local, and cheap: fixed-seed greedy decode on a single T4, scale-to-zero.
  • Frozen tokenizer reconstructs held-out LUTs at mean ΔE00 1.31 / ~37 dB.
  • Router is production-ready: route accuracy 0.884, refuse & clarify recall 1.0.
◌ Not yet proven
  • No end-to-end supported_prompt_to_lut_pass_rate exists — the decode-dependent layers (L2, L4–L7) are still decoder-free proxies in the v1 spine.
  • Free-running greedy generation collapses (behavioral fidelity 0.159); best-of-N recovers to ≈0.42 against a 0.708 teacher-forced ceiling.
  • No headline quality gate has been met at scale, and no GRPO result is shipped.

Roadmap · not done yet

Next step: GRPO.

Planned · needs more A100 time + compute · no shipped result

The dashboard above is honest about the gap: free-running greedy generation collapses to ≈0.16 behavioral fidelity (~94% collapse), while sample-and-rerank best-of-N already reaches ≈0.42. The next step is GRPO — on-policy RL to bake that covered-but-unselected quality into a single deterministic greedy pass. It is not run yet; it needs GPU time and may need knob tuning. Here is why the bet is worth making — and where it could fail.

◆ The strongest evidence — from our own data

Why it should work

Coverage already exists 0.42oracle@320.42best-of-N
The good trajectories are already in the policy's sampling distribution — greedy just doesn't pick them. GRPO only has to shift mass toward behavior the model already produces, not discover new capability. That is the easy case for policy gradient.
High within-prompt variance = strong learning signal Sample-t0.7 mean fidelity is only ~0.09, but the best of 32 is ~0.42. That heavy right tail gives each group of rollouts a wide reward spread — exactly what group-relative advantage exploits (it pushes toward the top of each group). Low mean + high max is the favorable signature, not a red flag.
The capability is there Teacher-forced fidelity is 0.708 — given a good prefix the model renders the spec fine. The failure is purely free-running collapse (the GRPO run initializes right here: greedy ≈0.16, collapse >90%). On-policy RL trains on the model's own rollouts — the textbook fix for exactly this exposure-bias mismatch.
Our own gate points here The oracle_at_n rule: ≥0.6 → distill · 0.3–0.6 → capped · ≤0.3 → escalate. At 0.42 we're in the capped band — best-of-N ships today, distillation alone is capped, so RL/GRPO is the escalation of record.

◇ The honest counter-case

Where it could fall short

RL sharpens more than it invents The realistic target is greedy climbing toward ~0.42 — best-of-N parity, but in one deterministic pass — not blowing past it. Reaching 0.42 is the win; 0.7 is not expected.
Reward hacking is real The reward only scores requested axes, so the policy can game them (dominant-code collapse, ΔE drift). That is why the collapse penalty + guard panel + KL-to-P6 exist. If it hacks, ΔE/collapse rise — and BEST won't promote it.
Movement may be weak or slow 3B QLoRA, lr 5e-6, μ=1 — a conservative REINFORCE+KL. It might need more than 500 steps, or knob tuning.
Literature prior GRPO/RLHF in the pass@k ≫ pass@1 regime (DeepSeekMath / R1 and the broader RLHF literature) reliably raises greedy/pass@1 toward pass@k by sharpening onto high-reward modes already sampled — precisely greedy 0.16 vs oracle 0.42.

Why the bet is cheap

BEST only promotes a guard-clean fidelity improvement. Worst case, GRPO doesn't help and BEST stays at the ~0.16 init — you've spent GPU time, not shipped a regression. You cannot end up worse than P6.

init P6 two-stage 3B QLoRA (r16) grpo_lr 5e-6 μ 1 group 8 KL β 0.05 steps 500 reward: free-running behavioral + collapse penalty promote BEST, not latest

Auditability

Every claim leaves an evidence trail.

The harness produces enough structure to reproduce a run, inspect individual failures, and distinguish model defects from parser, tokenizer, data, or evaluation defects.

ID

Frozen identity

Rows, split units, interpreter and generator artifacts, the AttributeSpec version, tokenizer hashes, canonical domain, parser/FSM versions, safety thresholds, and config versions are recorded.

  • version_manifest.json
  • config_resolved.yaml
  • row-level provenance, route, and split_unit_id
ΔE

Measured behavior

Per-row layer results preserve the facts behind the aggregate: direction deltas, image/chart ΔE00, safety flags, style margins, and refusal classifications.

  • metrics_by_row.parquet
  • attribute, target, style, safety tables
  • representative failure row IDs
CI

Decision record

Overall results, paired deltas, seed summaries, adjusted gate outcomes, and qualitative artifacts are written together as the release packet.

  • overall.csv + gates.csv
  • baseline_delta.csv
  • summary.md + qualitative outputs
eval_runs / checkpoint_sft_042 /

The goal is not a model that usually looks right.

It is a system whose scope, artifact validity, color behavior, safety, generalization, and comparative advantage are legible before anyone depends on it.

Primary outcomesupported_prompt_to_lut_pass_rate
Runtime pathinterpreter → spec → generator → 64 codes → decode
Unsupported pathroute → exact <unsupported>
Training metricheld-out token accuracy (max)
Release principlepredeclare → measure → audit