← back to Designer Wallcoverings
New-books 3-engine room compare: comparative VLM judge + auto-apply winner
76fdfd3b9cd5d53a08d91d1eec1694c42dea15e7 · 2026-07-10 09:02:18 -0700 · Steve
Files touched
A scripts/wallquest-refresh/judge-apply-newbooks.py
Diff
commit 76fdfd3b9cd5d53a08d91d1eec1694c42dea15e7
Author: Steve <steve@designerwallcoverings.com>
Date: Fri Jul 10 09:02:18 2026 -0700
New-books 3-engine room compare: comparative VLM judge + auto-apply winner
---
scripts/wallquest-refresh/judge-apply-newbooks.py | 40 +++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/scripts/wallquest-refresh/judge-apply-newbooks.py b/scripts/wallquest-refresh/judge-apply-newbooks.py
new file mode 100644
index 00000000..abfa5541
--- /dev/null
+++ b/scripts/wallquest-refresh/judge-apply-newbooks.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+# Comparative VLM judge (qwen2.5vl, $0) over the 3 room engines (patch-quilt/kontext/sdxl)
+# per SKU, then APPLY the winner: room_setting_images -> winner file, chosen_room_engine.
+# Env: TABLE, VIEW. Only judges SKUs with >=2 engine images present. Resumable.
+import base64, json, os, subprocess, urllib.request, sys
+TABLE = os.environ['TABLE']; VIEW = os.environ['VIEW']
+CONN = os.environ.get('DATABASE_URL', 'postgresql://dw_admin@127.0.0.1:5432/dw_unified')
+MODEL = 'qwen2.5vl:7b'
+def psql(sql): return subprocess.run(['psql', CONN, '-tAF|', '-c', sql], capture_output=True, text=True).stdout
+def b64(p): return base64.b64encode(open(p, 'rb').read()).decode()
+ENG = [('real','Patch-quilt (real sample)'), ('kontext','FLUX Kontext'), ('sdxl','SDXL')]
+
+def judge(swatch, cand): # cand=[(eng,path)]
+ order = ", ".join(f"image {i+2} = {lbl}" for i,(e,lbl,_) in enumerate(cand))
+ prompt = (f"You are a HARSH art director for a luxury wallcovering store. Image 1 is the product SWATCH. "
+ f"The others are candidate room-settings of the SAME product ({order}). Pick the ONE best room to sell "
+ f"this exact wallpaper. Penalize: texture not matching the swatch weave, blank/patchy walls, tiling seams, "
+ f"unrealistic artifacts. Reward exact-texture match + full even coverage + photorealism. You MUST choose one. "
+ f'Respond ONLY JSON: {{"winner":"<real|kontext|sdxl>","reason":"<=8 words"}}')
+ imgs = [b64(swatch)] + [b64(p) for _,_,p in cand]
+ body = json.dumps({"model": MODEL, "prompt": prompt, "images": imgs, "format": "json", "stream": False, "options": {"temperature": 0}}).encode()
+ r = json.load(urllib.request.urlopen(urllib.request.Request("http://localhost:11434/api/generate", body, {"Content-Type": "application/json"}), timeout=300))
+ return json.loads(r["response"])
+
+rows = [l.split('|') for l in psql(f"SELECT dw_sku, COALESCE((local_image_path::jsonb)->>0,''), COALESCE(chosen_room_engine,'') FROM {TABLE} ORDER BY dw_sku").strip().split('\n') if '|' in l]
+tally = {}; done = 0
+for sku, img, chosen in rows:
+ sw = f'{VIEW}/{img}'
+ if not img or not os.path.exists(sw): continue
+ cand = [(e, lbl, f'{VIEW}/rooms-local/{sku}-{e}.png') for e,lbl in ENG if os.path.exists(f'{VIEW}/rooms-local/{sku}-{e}.png')]
+ if len(cand) < 2: continue
+ try:
+ j = judge(sw, cand); w = j.get('winner','')
+ if w not in [e for e,_,_ in cand]: w = 'real' # fallback to patch-quilt
+ psql(f"UPDATE {TABLE} SET chosen_room_engine='{w}', room_setting_images='[\"rooms-local/{sku}-{w}.png\"]'::jsonb, updated_at=now() WHERE dw_sku='{sku}'")
+ tally[w] = tally.get(w,0)+1; done += 1
+ if done % 20 == 0: print(f' judged {done}: {tally}', flush=True)
+ except Exception as e:
+ print(f' ERR {sku}: {str(e)[:60]}', flush=True)
+print(f'{TABLE}: JUDGED {done} · winners {tally}', flush=True)
← e1e0b9dd auto-save: 2026-07-10T08:44:50 (6 files) — DW-Programming/Im
·
back to Designer Wallcoverings
·
auto-save: 2026-07-10T09:14:58 (9 files) — pending-approval/ 9200cba4 →