cozy-eval 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cozy_eval-0.1.0/.gitignore +11 -0
- cozy_eval-0.1.0/GATE.md +316 -0
- cozy_eval-0.1.0/LICENSE +21 -0
- cozy_eval-0.1.0/PKG-INFO +413 -0
- cozy_eval-0.1.0/PROVENANCE.md +260 -0
- cozy_eval-0.1.0/README.md +322 -0
- cozy_eval-0.1.0/calibration/banked-pairs.json +3224 -0
- cozy_eval-0.1.0/calibration/run_banked.py +183 -0
- cozy_eval-0.1.0/examples/bench_quickstart.py +112 -0
- cozy_eval-0.1.0/parity/analyze_h2h.py +70 -0
- cozy_eval-0.1.0/parity/h2h_results_20260727.json +427 -0
- cozy_eval-0.1.0/parity/make_fixtures.py +40 -0
- cozy_eval-0.1.0/parity/run_oracle.py +41 -0
- cozy_eval-0.1.0/pyproject.toml +72 -0
- cozy_eval-0.1.0/src/cozy_eval/__init__.py +106 -0
- cozy_eval-0.1.0/src/cozy_eval/__main__.py +3 -0
- cozy_eval-0.1.0/src/cozy_eval/_stats.py +99 -0
- cozy_eval-0.1.0/src/cozy_eval/backends/__init__.py +24 -0
- cozy_eval-0.1.0/src/cozy_eval/backends/distributional.py +95 -0
- cozy_eval-0.1.0/src/cozy_eval/backends/perceptual.py +76 -0
- cozy_eval-0.1.0/src/cozy_eval/backends/reference.py +171 -0
- cozy_eval-0.1.0/src/cozy_eval/backends/signal.py +245 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/__init__.py +120 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/catalog.py +52 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/checklists/cozy_hard_eval_v1.json +1479 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/checklists/hard_video_v1.json +235 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/checklists/magicbrush_edit_v1.json +658 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/decompose/__init__.py +76 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/decompose/engine.py +312 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/decompose/sets/compositional-v1_cases.json +1986 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/decompose/sets/compositional-v1_checklists.json +3045 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/decompose/sets/compositional-v1_prompts.json +872 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/decompose/vocab.py +75 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/device.py +29 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/errors.py +47 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/judge.py +70 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/metrics/__init__.py +25 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/metrics/adherence.py +560 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/metrics/data/niqe_pristine.npz +0 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/metrics/geneval.py +491 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/metrics/hpsv3.py +213 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/metrics/iqa.py +257 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/metrics/musiq.py +427 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/metrics/ocr.py +116 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/metrics/preference.py +262 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/metrics/similarity.py +192 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/metrics/temporal.py +177 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/metrics/vqascore.py +162 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/promptset.py +182 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/promptsets/hard_eval_v1.json +295 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/promptsets/hard_video_v1.json +185 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/registry.py +446 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/suite.py +449 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/verdict.py +216 -0
- cozy_eval-0.1.0/src/cozy_eval/bench/video.py +460 -0
- cozy_eval-0.1.0/src/cozy_eval/benchmarks.py +340 -0
- cozy_eval-0.1.0/src/cozy_eval/cli.py +121 -0
- cozy_eval-0.1.0/src/cozy_eval/control.py +164 -0
- cozy_eval-0.1.0/src/cozy_eval/frames.py +126 -0
- cozy_eval-0.1.0/src/cozy_eval/gate.py +256 -0
- cozy_eval-0.1.0/src/cozy_eval/image.py +80 -0
- cozy_eval-0.1.0/src/cozy_eval/protocol.py +248 -0
- cozy_eval-0.1.0/tests/fixtures/oracle_musiq.json +14 -0
- cozy_eval-0.1.0/tests/fixtures/oracle_niqe.json +14 -0
- cozy_eval-0.1.0/tests/fixtures/scene.png +0 -0
- cozy_eval-0.1.0/tests/fixtures/scene_blur.png +0 -0
- cozy_eval-0.1.0/tests/fixtures/scene_noise.png +0 -0
- cozy_eval-0.1.0/tests/fixtures/whitenoise.png +0 -0
- cozy_eval-0.1.0/tests/test_bench_suite.py +354 -0
- cozy_eval-0.1.0/tests/test_decompose.py +182 -0
- cozy_eval-0.1.0/tests/test_gate.py +302 -0
- cozy_eval-0.1.0/tests/test_geneval.py +284 -0
- cozy_eval-0.1.0/tests/test_hpsv3.py +120 -0
- cozy_eval-0.1.0/tests/test_iqa.py +80 -0
- cozy_eval-0.1.0/tests/test_musiq.py +80 -0
- cozy_eval-0.1.0/tests/test_public_api.py +364 -0
- cozy_eval-0.1.0/tests/test_registry_extension.py +86 -0
- cozy_eval-0.1.0/tests/test_verdict.py +141 -0
- cozy_eval-0.1.0/tests/test_video.py +363 -0
- cozy_eval-0.1.0/tests/test_vqascore.py +85 -0
- cozy_eval-0.1.0/uv.lock +3326 -0
cozy_eval-0.1.0/GATE.md
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
# The gate protocol
|
|
2
|
+
|
|
3
|
+
This is the document a producer lane follows verbatim. It defines what to render,
|
|
4
|
+
which metrics are admissible, what the thresholds are, and where those thresholds
|
|
5
|
+
came from. Deviating from it silently is how a wrong verdict ships.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Pick the lane. This is not optional.
|
|
10
|
+
|
|
11
|
+
A quality comparison between two arms is meaningful only once you have decided
|
|
12
|
+
what the change did to the **sampling trajectory**.
|
|
13
|
+
|
|
14
|
+
| The change… | Lane | Admissible metrics | Valid at |
|
|
15
|
+
|---|---|---|---|
|
|
16
|
+
| leaves the latent trajectory identical and alters only what happens after it — VAE decode dtype, decoder tiling, colour conversion, output resize, video encoder, container mux | `same-trajectory` | PSNR, SSIM, LPIPS, VMAF (reference metrics) | n = 1 |
|
|
17
|
+
| perturbs the trajectory — weight/activation quantization, weight storage cast, `torch.compile`, attention backend, scheduler, step count, guidance, LoRA attach/fuse, denoiser dtype, offload placement, hardware SKU, new weights | `population` | no-reference statistics only, over a paired prompt set | n ≥ 8 |
|
|
18
|
+
|
|
19
|
+
`classify_change()` implements the table; `require_reference_lane()` raises
|
|
20
|
+
`TrajectoryPerturbingError` rather than returning a number. One perturbing change
|
|
21
|
+
contaminates a mixed set.
|
|
22
|
+
|
|
23
|
+
### Why the refusal exists
|
|
24
|
+
|
|
25
|
+
Measured CPU-only on banked LTX-2.3 renders at 1920×1088 (`~/cozy/samples/w8a8-audit/`):
|
|
26
|
+
|
|
27
|
+
1. **The no-op consumes the whole budget.** A compile-only control — zero
|
|
28
|
+
quantization change — scores LPIPS **0.196–0.249** against a fleet fp8 budget
|
|
29
|
+
of 0.25.
|
|
30
|
+
2. **It is divergence, not drift.** The distance is already **0.29–0.41 at frame 0**
|
|
31
|
+
and flat-to-falling across the clip. Accumulating numerical error grows; a
|
|
32
|
+
different take starts far apart and stays there.
|
|
33
|
+
3. **The ranking inverts.** An fp8-storage-cast arm and an unscaled-w8a8 arm carry
|
|
34
|
+
*identical weight bytes*, but the cast arm computes its GEMMs in bf16 and is
|
|
35
|
+
therefore strictly the more accurate path. It scores **0.3875 vs 0.3052** —
|
|
36
|
+
worse. A metric that ranks a strictly-better arm below a strictly-worse one
|
|
37
|
+
cannot choose between arms.
|
|
38
|
+
|
|
39
|
+
The same logic applies to images; it is only less visible there, because one
|
|
40
|
+
1024² frame diverges less than 121 frames do.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 2. Render conditions (population lane)
|
|
45
|
+
|
|
46
|
+
Both arms MUST share all of these, and the protocol stamp MUST record them:
|
|
47
|
+
|
|
48
|
+
* **n ≥ 8 paired prompts.** Hard floor 6; below 6 the distributional benchmark is
|
|
49
|
+
not evaluated at all. At n = 1 the *shipped-clean* LTX w8a8 recipe scores an
|
|
50
|
+
imaging index of **0.934** on one prompt and **1.005** over eight. One prompt
|
|
51
|
+
measures the take.
|
|
52
|
+
* **Same seeds, same prompt set, same order.** The prompts do not need to be the
|
|
53
|
+
te#79 fixed set, but they must be fixed for the family and reused across runs.
|
|
54
|
+
* **Same pod.** Host CPU and GPU variant move these numbers on their own
|
|
55
|
+
(an H100 PCIe and an H100 SXM are not interchangeable). Cross-pod arms return
|
|
56
|
+
`INDETERMINATE`.
|
|
57
|
+
* **Same execution lane.** Both arms compiled, or both eager — never one of each.
|
|
58
|
+
Compile alone perturbs the trajectory, so a compiled-candidate-vs-eager-reference
|
|
59
|
+
comparison measures compile plus quantization and cannot attribute either.
|
|
60
|
+
**The arms must be the ones you will serve**: if production serves compiled,
|
|
61
|
+
gate compiled.
|
|
62
|
+
* **Native production resolution and step count.** A 512² proxy understates native
|
|
63
|
+
damage by roughly 2.5× on image families; there is no reason to expect video to
|
|
64
|
+
be kinder.
|
|
65
|
+
* Frames are scored **pre-encode** where possible. Pass decoded frames straight to
|
|
66
|
+
`score_clip`; the encoder is itself a `same-trajectory` change and does not
|
|
67
|
+
belong inside a quantization verdict.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 3. The three benchmarks
|
|
72
|
+
|
|
73
|
+
Each answers a question the other two cannot. Section 5 shows a degradation that
|
|
74
|
+
only one of them catches, for each of the three.
|
|
75
|
+
|
|
76
|
+
### B1 — Imaging (per-frame, no-reference)
|
|
77
|
+
|
|
78
|
+
Six per-frame statistics, split into **detail** (Laplacian variance, spectral
|
|
79
|
+
high-frequency ratio above quarter-Nyquist, local contrast) and **tone** (luma
|
|
80
|
+
standard deviation, RGB saturation, 64-bin luma histogram entropy). Each is taken
|
|
81
|
+
as a ratio to the reference arm and aggregated as the **median across prompts**,
|
|
82
|
+
so one divergent take cannot drive the verdict.
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
imaging_index = detail_retention^(2/3) · tonal_retention^(1/3)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Catches: softening, detail loss, flattening/greying, and — via the upper bound —
|
|
89
|
+
noise injection and over-sharpening.
|
|
90
|
+
|
|
91
|
+
### B2 — Temporal
|
|
92
|
+
|
|
93
|
+
* `jerk_ratio` = mean |L[t] − 2L[t−1] + L[t−2]| / mean |L[t] − L[t−1]|. Smooth
|
|
94
|
+
motion keeps this low whatever the motion magnitude; per-frame instability
|
|
95
|
+
raises it. **The tightest statistic in the suite**: per-prompt σ_log = 0.0139 on
|
|
96
|
+
the clean population.
|
|
97
|
+
* `flicker` = frame-mean luma standard deviation as a percentage of the mean.
|
|
98
|
+
* `shimmer`, `motion_energy` — advisory diagnostics, not budgets (see §6).
|
|
99
|
+
|
|
100
|
+
Catches: exposure flicker, frame-to-frame jitter, motion collapse.
|
|
101
|
+
|
|
102
|
+
### B3 — Distributional fidelity
|
|
103
|
+
|
|
104
|
+
A **paired test across the prompt set**: per-metric paired *t* on log-ratios with
|
|
105
|
+
Holm-Bonferroni correction, gated additionally on a ≥2 % practical effect, plus a
|
|
106
|
+
paired per-frame Fréchet distance on the six signal features whitened by the
|
|
107
|
+
reference population.
|
|
108
|
+
|
|
109
|
+
Catches: consistent population-level shifts too small to move any single index,
|
|
110
|
+
and — by construction — it is the only benchmark that cannot be fooled by take
|
|
111
|
+
noise, because it asks whether the shift is *consistent across prompts*.
|
|
112
|
+
|
|
113
|
+
**Why not FVD / JEDi.** A deep-feature Fréchet distance is a population statistic
|
|
114
|
+
whose estimator bias dominates at n in the single digits; published FVD uses
|
|
115
|
+
thousands of clips. A per-artifact producer gate cannot afford that. Because the
|
|
116
|
+
prompt set here is *identical between arms*, content is differenced out by
|
|
117
|
+
construction and a paired test has real power at n = 8. `[distributional]` ships
|
|
118
|
+
`frechet()` for lanes that can afford n ≥ 64, and it refuses below that.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 4. Thresholds and their provenance
|
|
123
|
+
|
|
124
|
+
Calibrated on the pairs in §5. Clean reference population throughout:
|
|
125
|
+
**LTX-2.3-distilled, w8a8-pcs compiled vs bf16 compiled, n = 8 prompts,
|
|
126
|
+
1280×704 × 121 f, 8 steps, H100-80GB-HBM3, both arms compiled, same pod.**
|
|
127
|
+
|
|
128
|
+
| Budget | Value | Clean measures | Nearest failing case |
|
|
129
|
+
|---|---|---|---|
|
|
130
|
+
| `imaging_index` | 0.92 ≤ x ≤ 1.25 | 1.005 | 0.869 (Wan 4-step per-tensor fp8, same-pod ref); 1.645 (σ=0.02 pixel noise) |
|
|
131
|
+
| `imaging_worst_prompt` | ≥ 0.85 | 0.941 (worst of 8) | 0.647 (Wan fp8 population's worst prompt) |
|
|
132
|
+
| `jerk_excess` | ≤ +0.04 | +0.013 | +0.056 (2 % per-frame gain jitter); +0.053 (animegen 4-step mush); +0.104 (pixel noise) |
|
|
133
|
+
| `flicker_ratio` | ≤ 1.25 | 1.043 | **nothing banked trips it** — see below |
|
|
134
|
+
| `significant_features` | = 0 | 0 | 1 (8 % desaturation); 3 (25 % blur blend) |
|
|
135
|
+
| `population_frechet` | ≤ 0.20 | 0.068 | 0.286 (25 % blur blend); 4.792 (pixel noise) |
|
|
136
|
+
|
|
137
|
+
**Same-trajectory lane** — anchored on a real post-latent change: x264 re-encode
|
|
138
|
+
of banked LTX clips at CRF 18/23/28/34, measuring 40.6–44.4 / 37.6–42.4 /
|
|
139
|
+
33.9–38.7 / 30.4–35.2 dB mean PSNR.
|
|
140
|
+
|
|
141
|
+
| Budget | Value | Rationale |
|
|
142
|
+
|---|---|---|
|
|
143
|
+
| `psnr_mean` | ≥ 36 dB | passes a CRF-23-class change, fails CRF-28-class |
|
|
144
|
+
| `psnr_worst` | ≥ 32 dB | worst frame at CRF 23 = 35.4 dB, at CRF 28 = 32.2 dB |
|
|
145
|
+
| `ssim_mean` | ≥ 0.97 | **provisional** — windowed SSIM barely moves on these anchors; PSNR is operative |
|
|
146
|
+
|
|
147
|
+
**`jerk_excess` is the operative temporal statistic; `flicker_ratio` is a wide
|
|
148
|
+
backstop.** The 2 % gain-jitter control raises flicker to 1.248 — inside the 1.25
|
|
149
|
+
budget — and is caught on jerk (+0.056) instead. The budget is not tightened to make
|
|
150
|
+
the control fail: `flicker`'s per-prompt spread on the clean population is
|
|
151
|
+
σ_log = 0.18, an order of magnitude looser than jerk's 0.0139, so a threshold that
|
|
152
|
+
would trip on 1.248 would be about 2σ from the clean median and start failing clean
|
|
153
|
+
arms. Flicker earns its place by catching gross exposure instability, not marginal
|
|
154
|
+
cases.
|
|
155
|
+
|
|
156
|
+
Sensitivity floors, stated honestly: the temporal axis resolves ~1.5 % frame-to-frame
|
|
157
|
+
gain noise (1 % jitter passes at jerk +0.022, 2 % fails at +0.056). The imaging axis
|
|
158
|
+
resolves roughly a 25 % blur blend. The distributional axis resolves an 8 %
|
|
159
|
+
saturation shift held consistently across 8 prompts.
|
|
160
|
+
|
|
161
|
+
`population_frechet` is fixed against **one** clean population and is the weakest
|
|
162
|
+
threshold here. Re-estimate it as more clean arms bank.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 4b. The null control — which budgets is this family allowed to be judged on?
|
|
167
|
+
|
|
168
|
+
Every threshold in §4 was fixed on ONE family at one resolution. A threshold is
|
|
169
|
+
only a threshold where the *clean* population sits comfortably inside it, and
|
|
170
|
+
that is a per-family fact. **Measure it; do not assume it.**
|
|
171
|
+
|
|
172
|
+
A **null control** is an arm with identical weights and different seeds. Zero
|
|
173
|
+
model change, so anything it trips is take spread. Declare it with
|
|
174
|
+
`ChangeKind.SEED` — the only change a control may carry — and run it through
|
|
175
|
+
`measure_null_control()`:
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
control = measure_null_control(control_pairs, control_protocol) # ChangeKind.SEED
|
|
179
|
+
report = run_population_gate(pairs, protocol, null_control=control)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The gate then reports a budget the control trips as **disregarded** — still
|
|
183
|
+
measured, still printed, never decisive — fails only on budgets the control
|
|
184
|
+
proved trustworthy, and ceilings the verdict at `INDETERMINATE` whenever
|
|
185
|
+
anything was disregarded, because a PASS on partial evidence is not a PASS.
|
|
186
|
+
|
|
187
|
+
Measured, 2026-07-27, two image families, n = 8 each, one control arm apiece:
|
|
188
|
+
|
|
189
|
+
| Budget | null controls measured | Transfers? |
|
|
190
|
+
|---|---|---|
|
|
191
|
+
| `significant_features` = 0 | 0 and 0 | **yes** — and it is what caught a real over-sharpening arm |
|
|
192
|
+
| `imaging_index` 0.92–1.25 | 1.0087 and 1.0025 | **yes**, and tight |
|
|
193
|
+
| `imaging_worst_prompt` ≥ 0.85 | 0.9182 and **0.6102** | family-dependent |
|
|
194
|
+
| `population_frechet` ≤ 0.20 | **0.4688** and **1.3275** | **no** — 2.3× and 6.6× the budget at zero model change |
|
|
195
|
+
|
|
196
|
+
Without the control, the second family reads a confident `FAIL` on two budgets
|
|
197
|
+
its own zero-change arm fails harder. That is a threshold-transfer artifact, and
|
|
198
|
+
demoting an artifact on it is exactly the class of wrong verdict this library
|
|
199
|
+
exists to refuse. **Carry a control arm on any family outside the calibrated
|
|
200
|
+
envelope of §4 — it is one extra arm on a pod you already bought** (measured:
|
|
201
|
+
$0.13 of a $0.38 pod).
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## 4c. Degenerate arms: NO SIGNAL is not a FAIL
|
|
206
|
+
|
|
207
|
+
A candidate whose frames are a constant fill — uniformly black, white or flat —
|
|
208
|
+
scores an imaging index of 0.0 and an unbounded Fréchet distance against any real
|
|
209
|
+
reference. Those numbers are arithmetic, not evidence: they invite ranking one
|
|
210
|
+
broken arm against another. Both population gates detect it up front and return
|
|
211
|
+
`DEGENERATE` with no benchmark numbers at all. A degenerate *reference* is
|
|
212
|
+
refused for the same reason — every statistic here is a ratio to it.
|
|
213
|
+
|
|
214
|
+
Real case: a Wan 2.2 per-row fp8 arm that emitted 8/8 uniformly black clips
|
|
215
|
+
previously returned `FAIL`, `imaging_index 0.0000`, `population_frechet 13001`.
|
|
216
|
+
It now returns `DEGENERATE`. Look at the render; do not rank the arm.
|
|
217
|
+
|
|
218
|
+
The same-trajectory lane is deliberately NOT covered: there, the reference render
|
|
219
|
+
is the same take, so PSNR against it measures the blackout correctly and a FAIL
|
|
220
|
+
is the right, non-misleading verdict.
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## 5. Validation table
|
|
225
|
+
|
|
226
|
+
`imaging_index` / worst-prompt / `jerk_excess` / `flicker_ratio` /
|
|
227
|
+
significant-feature count / paired Fréchet. Verdict letters are
|
|
228
|
+
imaging·temporal·distributional; `-` means not evaluated below the n ≥ 6 floor.
|
|
229
|
+
Regenerate with `python calibration/run_banked.py --samples-root …`; the evidence
|
|
230
|
+
is `calibration/banked-pairs.json`.
|
|
231
|
+
|
|
232
|
+
| Pair | Expected | IMG | wIMG | jerkX | flick | nsig | pFQD | Verdict |
|
|
233
|
+
|---|---|---|---|---|---|---|---|---|
|
|
234
|
+
| LTX 2.3 w8a8-pcs compiled vs bf16 compiled (n=8) | CLEAN | **1.005** | 0.941 | +0.013 | 1.043 | 0 | 0.068 | `PPP` |
|
|
235
|
+
| ↳ the same recipe judged on ONE prompt | CLEAN (trap) | 0.934 | 0.934 | −0.015 | 1.014 | – | – | `PP-` indeterminate |
|
|
236
|
+
| LTX compile-only control (no quant at all) | CLEAN control | 0.980 | 0.980 | +0.000 | 0.993 | – | – | `PP-` indeterminate |
|
|
237
|
+
| LTX fp8-storage cast (demoted rung) | observation | 0.957 | 0.957 | −0.011 | 1.157 | – | – | `PP-` indeterminate |
|
|
238
|
+
| Wan 2.2 4-step per-tensor fp8 (n=2) | **DEGRADED** | **0.727** | 0.647 | +0.018 | 0.899 | – | – | **`FP-`** |
|
|
239
|
+
| Wan 2.2 4-step per-tensor fp8, same-pod ref | **DEGRADED** | **0.869** | 0.869 | −0.001 | 0.786 | – | – | **`FP-`** |
|
|
240
|
+
| Wan 2.2 12-step per-tensor fp8 | CLEAN | 1.009 | 1.009 | +0.005 | 1.004 | – | – | `PP-` |
|
|
241
|
+
| animegen 4-step double-shift mush | **SEVERELY BAD** | **0.626** | 0.626 | **+0.053** | 0.706 | – | – | **`FF-`** |
|
|
242
|
+
| animegen 8-step double-shift | near-null | 1.038 | 1.038 | −0.009 | 0.881 | – | – | `PP-` |
|
|
243
|
+
| animegen 12-step double-shift | near-null | 1.038 | 1.038 | +0.008 | 0.951 | – | – | `PP-` |
|
|
244
|
+
| Wan naive timestep grid | bad, **semantic** | 0.976 | 0.976 | +0.009 | 0.837 | – | – | `PP-` **misses it — §6** |
|
|
245
|
+
| SYNTHETIC soften, 50 % blur blend (n=8) | imaging axis | **0.748** | 0.690 | −0.022 | 1.000 | 3 | 1.218 | `FPF` |
|
|
246
|
+
| SYNTHETIC soften, 25 % blur blend (n=8) | imaging axis | **0.869** | 0.841 | −0.011 | 1.000 | 3 | 0.286 | `FPF` |
|
|
247
|
+
| SYNTHETIC desaturate to 92 % (n=8) | tonal axis | 0.991 | 0.991 | +0.000 | 1.000 | **1** | 0.008 | **`PPF`** |
|
|
248
|
+
| SYNTHETIC 2 % per-frame gain jitter (n=8) | temporal axis | 0.998 | 0.996 | **+0.056** | 1.248 | 0 | 0.006 | **`PFP`** |
|
|
249
|
+
| SYNTHETIC 1 % per-frame gain jitter (n=8) | below floor | 0.999 | 0.998 | +0.022 | 1.068 | 0 | 0.001 | `PPP` |
|
|
250
|
+
| SYNTHETIC σ=0.02 per-pixel noise (n=8) | mixed | **1.645** | 1.161 | +0.104 | 0.996 | 3 | 4.790 | `FFF` |
|
|
251
|
+
|
|
252
|
+
**Separation margins.** Clean population 1.005 vs the tightest real degraded
|
|
253
|
+
observation 0.869 → the 0.92 threshold sits +9.0 % above the clean measurement and
|
|
254
|
+
−5.6 % below the nearest failure. On the temporal axis, +0.013 clean vs +0.053
|
|
255
|
+
failing, threshold +0.04: +0.027 / −0.013.
|
|
256
|
+
|
|
257
|
+
**Each benchmark catches something the others miss** — the whole reason there are
|
|
258
|
+
three:
|
|
259
|
+
|
|
260
|
+
* **imaging only** (`FP-`) — the Wan 4-step per-tensor fp8 arm. Index 0.727, jerk
|
|
261
|
+
+0.018 which is *inside* the clean band, and the population test cannot run at
|
|
262
|
+
n=2. This is the real, banked, production-relevant failure.
|
|
263
|
+
* **temporal only** (`PFP`) — 2 % per-frame gain jitter. Imaging index 0.998, zero
|
|
264
|
+
significant paired features, Fréchet 0.006 — all three pass — and `jerk_excess`
|
|
265
|
+
+0.056 fails.
|
|
266
|
+
* **distributional only** (`PPF`) — an 8 % desaturation held consistently across all
|
|
267
|
+
eight prompts. Imaging index 0.991 and jerk +0.000 both pass comfortably; the
|
|
268
|
+
paired test flags `saturation` at Holm p < 0.05 with a 2.7 % effect.
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## 6. What this gate does NOT measure
|
|
273
|
+
|
|
274
|
+
State these to anyone reading a PASS.
|
|
275
|
+
|
|
276
|
+
* **Semantic and compositional failure.** The banked Wan naive-timestep-grid pair
|
|
277
|
+
is a real bug — it produces *background-figure cloning* and a flatter grade —
|
|
278
|
+
and this gate passes it (index 0.976, every axis silent). Signal statistics
|
|
279
|
+
cannot see a duplicated subject, a dropped prompt element, or text that renders
|
|
280
|
+
as gibberish. That needs a CLIP/VLM-class scorer or a human, and it is a fourth
|
|
281
|
+
axis, deliberately out of scope here.
|
|
282
|
+
* **Absolute quality.** Every number is a ratio to a reference arm. A gate PASS
|
|
283
|
+
says "no worse than the reference", never "good".
|
|
284
|
+
* **Aesthetics and prompt adherence.**
|
|
285
|
+
* **Motion energy and shimmer** are reported but not budgeted: both are strongly
|
|
286
|
+
content-driven (motion σ_log = 0.095 per prompt on the clean population) and
|
|
287
|
+
shimmer also falls under plain softening, so neither separates its own axis.
|
|
288
|
+
They appear as advisory notes.
|
|
289
|
+
* **Audio**, for families that generate it.
|
|
290
|
+
* Thresholds are calibrated on **LTX-2.3 and Wan-2.2 class video at 720p–1080p,
|
|
291
|
+
4–12 steps**. A family far outside that (very low resolution, very long
|
|
292
|
+
clips, heavily stylised flat-shaded output) should re-derive them from its own
|
|
293
|
+
clean population before trusting a PASS.
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## 7. Producer lane checklist
|
|
298
|
+
|
|
299
|
+
1. Declare every `ChangeKind` the candidate arm introduces. Do not guess; if the
|
|
300
|
+
change is not in the enum, add it and decide its lane deliberately.
|
|
301
|
+
2. If the lane is `same-trajectory`: `run_reference_gate`, n ≥ 1, done.
|
|
302
|
+
3. Otherwise render **both arms** on one pod, same seeds, ≥ 8 prompts, both in the
|
|
303
|
+
serving execution lane, at production resolution and step count.
|
|
304
|
+
4. Outside §4's calibrated envelope — any image family, any family far from
|
|
305
|
+
LTX/Wan-class 720p–1080p video — render a **third arm on the same pod**: the
|
|
306
|
+
same checkpoint at seeds + 1, and `measure_null_control(...)` it (§4b).
|
|
307
|
+
5. `score_pairs(...)` → `run_population_gate(pairs, protocol, null_control=control)`.
|
|
308
|
+
6. Persist `report.to_dict()` next to the artifact. It contains the verdict, every
|
|
309
|
+
measured value, every budget with its provenance, which budgets were
|
|
310
|
+
disregarded and why, the control's own numbers, and the protocol stamp.
|
|
311
|
+
`ClipScore.to_dict()` / `from_dict()` persist the per-clip scores losslessly if
|
|
312
|
+
you want to re-gate without re-rendering.
|
|
313
|
+
7. `INDETERMINATE` is not a pass, and neither is `DEGENERATE`. Never promote an
|
|
314
|
+
artifact on either.
|
|
315
|
+
8. A FAIL is a **verdict**, not a fault: publish the report, keep the artifact
|
|
316
|
+
staged, do not promote it.
|
cozy_eval-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Cozy Creator and Paul Fidika
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|