Problem
layout-8 / LayerAwareObjectInsertion (and its peers in the layer-aware-edit
family) declare nima_score as a primary/reported metric upstream, but the
native BaseBenchmark.evaluate() method does not produce nima_score for
these benchmarks. The benchmark's native metric set is identity-preservation
(clip_identity, dino_identity, dreamsim_distance, lpips, hpsv3, …).
The nima_score values we report upstream for layout-8 (e.g. 4.5225 for
claude-sonnet-4-20250514 in outputs/parity_claude_code.rescored.json) are
produced via a separate post-hoc rescoring pass over the output PNGs using
pyiqa's NIMA model (see nima_real_rescore.json / scripts/merge_parity_results.py
flow).
This creates an asymmetry:
- A fresh upstream run that calls
bench.evaluate() (e.g. via
run_benchmarks.py) returns NaN / absent nima_score for layout-8.
- Only after the rescoring side-pass do the "canonical" parity numbers appear.
Any external harness (Harbor adapter, other evaluators, or a clean re-run) that
consumes evaluate() output directly will see nima_score = NaN for layout-8
and peers, and produce a 0-reward or skip the benchmark entirely.
Expected behavior
LayerAwareObjectInsertion.evaluate() (and any other layer-aware benchmark that
ships nima_score as part of its reported metric set) should natively compute
nima_score via pyiqa.create_metric("nima", …) on the generated image, so
downstream consumers don't need a separate rescoring pipeline.
Proposed fix
Add a _compute_nima helper to BaseBenchmark (or a mixin) that:
- Loads
pyiqa.create_metric("nima", device=…) once per process (cached).
- Runs it on each sample's generated image.
- Populates
scores["nima_score"] in evaluate() output.
Then gate it on a benchmark-class flag such as REPORTS_NIMA = True to avoid
paying the model-load cost for benchmarks that don't report it.
Workaround used downstream
For the Harbor GDB adapter, we ship a post-hoc fallback in the Harbor verifier
(evaluate.py) that mirrors the upstream rescoring pass: when the primary
metric is nima_score and bench.evaluate() does not return it, we compute it
ourselves with pyiqa.create_metric("nima", device="cpu") against
/workspace/output.png. This keeps parity numbers comparable across harnesses,
but it's a shim — the clean fix is upstream in this repo.
Repro
bench = LayerAwareObjectInsertion(...)
result = bench.evaluate(samples)
assert "nima_score" in result.scores # fails today
Problem
layout-8/LayerAwareObjectInsertion(and its peers in the layer-aware-editfamily) declare
nima_scoreas a primary/reported metric upstream, but thenative
BaseBenchmark.evaluate()method does not producenima_scoreforthese benchmarks. The benchmark's native metric set is identity-preservation
(
clip_identity,dino_identity,dreamsim_distance,lpips,hpsv3, …).The
nima_scorevalues we report upstream forlayout-8(e.g.4.5225forclaude-sonnet-4-20250514inoutputs/parity_claude_code.rescored.json) areproduced via a separate post-hoc rescoring pass over the output PNGs using
pyiqa's NIMA model (seenima_real_rescore.json/scripts/merge_parity_results.pyflow).
This creates an asymmetry:
bench.evaluate()(e.g. viarun_benchmarks.py) returns NaN / absentnima_scoreforlayout-8.Any external harness (Harbor adapter, other evaluators, or a clean re-run) that
consumes
evaluate()output directly will seenima_score = NaNforlayout-8and peers, and produce a 0-reward or skip the benchmark entirely.
Expected behavior
LayerAwareObjectInsertion.evaluate()(and any other layer-aware benchmark thatships
nima_scoreas part of its reported metric set) should natively computenima_scoreviapyiqa.create_metric("nima", …)on the generated image, sodownstream consumers don't need a separate rescoring pipeline.
Proposed fix
Add a
_compute_nimahelper toBaseBenchmark(or a mixin) that:pyiqa.create_metric("nima", device=…)once per process (cached).scores["nima_score"]inevaluate()output.Then gate it on a benchmark-class flag such as
REPORTS_NIMA = Trueto avoidpaying the model-load cost for benchmarks that don't report it.
Workaround used downstream
For the Harbor GDB adapter, we ship a post-hoc fallback in the Harbor verifier
(
evaluate.py) that mirrors the upstream rescoring pass: when the primarymetric is
nima_scoreandbench.evaluate()does not return it, we compute itourselves with
pyiqa.create_metric("nima", device="cpu")against/workspace/output.png. This keeps parity numbers comparable across harnesses,but it's a shim — the clean fix is upstream in this repo.
Repro