Skip to content

Recipes

m4bwav edited this page Oct 22, 2026 · 1 revision

Whole tasks with aw.py, each run as shown. A batch judged end to end, with the verdict read back by a calling plugin, is on the Verdict contract page.

Call aw.py from Python

Every command prints one JSON object, so a caller runs it and parses stdout. Check the exit code too: 1 means "ok": false somewhere in the answer, and 2 means a usage mistake with nothing on stdout (Errors and edge cases).

import json
import subprocess
import sys


def aw(*args):
    r = subprocess.run([sys.executable, "aw.py", *args], capture_output=True, text=True, encoding="utf-8")
    return r.returncode, json.loads(r.stdout)


code, info = aw("info", "dusk.png", "missing.png")
print("exit", code)
for item in info["items"]:
    if item["ok"]:
        print(item["file"], item["size"], item["tokens"]["standard"]["tokens"], "tokens")
    else:
        print(item["file"], "error:", item["error"])

prints:

exit 1
dusk.png [2000, 1200] 1500 tokens
missing.png error: no such file: missing.png

Replace "aw.py" with the script's full path when the caller runs from another folder.

What a folder of images costs to read

for f in renders/*.png; do
  python aw.py info "$f" | python -c "import json,sys; i=json.load(sys.stdin)['items'][0]; print(i['file'], i['tokens']['standard']['tokens'])"
done

prints:

renders/render_01.png 25
renders/render_01_copy.png 25
renders/render_02.png 25
renders/render_03.png 25
renders/render_04.png 25
renders/render_05.png 25
renders/render_06.png 25

info takes many files at once, so for one JSON answer pass them all: python aw.py info renders. Seven reads of 25 tokens each are cheap; the habit matters for photographs, where one 2000 x 1200 image is 1500 tokens on the standard tier and a 1024 px copy is 814.

Did the grid fixer help?

The pixel skill keeps a fix only when the numbers improve and a blind comparison prefers it. Run pixel on the sprite before and after the fixer, with the same budget. Before (the resampled sprite):

python aw.py pixel sprite_ai.png --budget 16

ends:

   "clean_pixel_art": false,
   "problems": [
    "off-grid pixels (lattice alignment 66.7%)",
    "blocks not uniform (66.0%)",
    "transitional (blend) pixels 2.95%",
    "145 semi-transparent pixels"
   ]

After (the clean sprite stands in for the fixer's output here):

python aw.py pixel sprite.png --budget 16 --preview sprite_x4.png

ends:

   "clean_pixel_art": true,
   "problems": []

Then judge the two with compare prepare and compare record in both orders, blind, before keeping the fix.

Test pairs with a known answer

To see whether a judge prefers the right image, pair an image with a damaged copy of itself. degrade is deterministic, so the same command makes the same pair on any run:

for k in saturate crush crop; do python aw.py degrade dusk.png -o dusk_$k.png --kind $k --seed 7; done

prints:

{
 "out": "dusk_saturate.png",
 "kind": "saturate",
 "seed": 7,
 "size": [
  2000,
  1200
 ],
 "ok": true
}
{
 "out": "dusk_crush.png",
 "kind": "crush",
 "seed": 7,
 "size": [
  2000,
  1200
 ],
 "ok": true
}
{
 "out": "dusk_crop.png",
 "kind": "crop",
 "seed": 7,
 "size": [
  2000,
  1200
 ],
 "ok": true
}

Each dusk.png against dusk_<kind>.png pair has an expected winner. Record the person's pick with cache label and compare with the judge using cache agreement (How images are judged).

Find near-copies before judging

A batch often holds the same render twice, re-encoded. dedupe groups them by difference hash, and keep is the list to judge:

python aw.py dedupe renders

prints:

{
 "groups": [
  [
   "renders/render_01.png",
   "renders/render_01_copy.png"
  ]
 ],
 "pairs": [
  {
   "a": "renders/render_01.png",
   "b": "renders/render_01_copy.png",
   "distance": 0
  }
 ],
 "keep": [
  "renders/render_01.png",
  "renders/render_02.png",
  "renders/render_03.png",
  "renders/render_04.png",
  "renders/render_05.png",
  "renders/render_06.png"
 ],
 "threshold": {
  "algo": "dhash",
  "version": 1,
  "max_distance": 6
 },
 "ok": true
}

render_01_copy.png was render_01.png through degrade --kind jpeg: a different file (another SHA-256) with the same 64-bit hashes, distance 0.

Look at a detail without paying for the whole image

Crop at full resolution rather than reading the whole image larger. A 300 x 150 box around the fox in the 2000 x 1200 scene:

python aw.py fit dusk.png -o fox_crop.png --crop 1100,850,300,150

prints:

{
 "out": "fox_crop.png",
 "size": [
  300,
  150
 ],
 "tokens": {
  "standard": {
   "tokens": 66,
   "read_at": [
    300,
    150
   ]
  },
  "high": {
   "tokens": 66,
   "read_at": [
    300,
    150
   ]
  }
 },
 "ok": true
}

66 tokens, against 1500 for the whole image on the standard tier.

Clone this wiki locally