From 65e8f01586fb6930f48533faabd1ef8ab42e4048 Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Tue, 10 Nov 2026 09:26:30 +0100 Subject: [PATCH] docs(tools): local ComfyUI, how to start it, and the checkpoint pair it actually has Tools/README.md now covers the generative tools next to each other: - comfyui_generate.py drives the LOCAL ComfyUI at 127.0.0.1:8188, which this repository does not start. A new subsection says so and says what to do: start Stability Matrix, launch ComfyUI, re-run. It points at /home/zwitschi/StabilityMatrix/Data/README.md for the package version, the launch arguments and the shared 80 GB model library, and notes that THIRD_PARTY_NOTICES.md must carry the model and licence before a generated texture ships. - generate_facade_textures.py and generate_character_textures.py are listed as the deterministic procedural path: no model, no network, byte-identical on every run. - The tool's own docstring carries the same Stability Matrix instruction. The default second checkpoint was sd_xl_base_1.0.safetensors, which is NOT installed; it is now epicrealismXL_pureFix.safetensors, verified against the running server. The pair was smoke-tested end to end at 512 px: both checkpoints rendered, both scored, juggernautXL won at 20.37 against 12.93, and the winner landed on --out with the loser kept beside it. --- Tools/README.md | 11 +++++++++++ Tools/comfyui_generate.py | 12 +++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Tools/README.md b/Tools/README.md index b7da761..877b97d 100644 --- a/Tools/README.md +++ b/Tools/README.md @@ -85,9 +85,20 @@ Geographic tools live in [`Geo/tools/`](../Geo/README.md) and the Blender-side b | Tool | Purpose | | --- | --- | +| `comfyui_generate.py` | Drives the **local** ComfyUI at `http://127.0.0.1:8188` (Stability Matrix install): `models` lists checkpoints, `txt2img` renders through the HTTP API and writes a provenance sidecar (model, prompt, seed, full graph). Two checkpoints by default — same prompt and seed, both scored by high-frequency detail, the winner takes `--out`, the loser is kept as `__.png`. `--alt-model ""` for a single run. Local and human-triggered; no credential. | +| `generate_facade_textures.py` | Procedural, deterministic facade texture maps (ashlar base colour + roughness, stucco, asphalt, concrete) written with a pure-zlib PNG encoder — no model, no network, byte-identical on every run. | +| `generate_character_textures.py` | Procedural character texture maps, same deterministic approach as the facade set. | | `facade_detail_concepts.py` | Generates **frontal building plates** (whole elevation, entrance in its facade, or building with neighbours) from a local reference photograph with an image model (OpenRouter); close-up detail crops are deliberately not requested because they cannot be measured for proportion. `--list` is free and shows which studies have their reference present; `--all`/`--only ` generates. Never overwrites (writes `-v2`, `-v3`), writes a `.refgen.json` sidecar per image (model, prompt, source photo, SHA-256), and puts everything under `Art/reference/facade-details/` — gitignored, local-only, never shipped. Costs money per image, so it is never automatic. | | `judge_screenshot.py` | (see Visual review) | +### Local image generation: start Stability Matrix first + +`comfyui_generate.py` talks to ComfyUI on `http://127.0.0.1:8188`. That server is **not** started by this repository — it lives in a [Stability Matrix](https://lykos.ai) install and must already be running. + +**If the tool reports a connection error, start Stability Matrix and launch ComfyUI**, then re-run. The install is documented in [`/home/zwitschi/StabilityMatrix/Data/README.md`](/home/zwitschi/StabilityMatrix/Data/README.md): package version, launch arguments, and the shared model library (`Models/`, ~80 GB, mapped in through `extra_model_paths.yaml`). Reading that file before writing a prompt is the cheap way to see which checkpoints actually exist — `python3 Tools/comfyui_generate.py models` asks the running server the same question, and it is the authoritative list — the default pair is `juggernautXL_ragnarok.safetensors` and `epicrealismXL_pureFix.safetensors`, both verified installed. + +Checkpoints are **not** committed. A generated texture ships only after its model and licence are recorded in [`THIRD_PARTY_NOTICES.md`](../THIRD_PARTY_NOTICES.md); the sidecar carries what that needs. + ## Input injection | Tool | Purpose | diff --git a/Tools/comfyui_generate.py b/Tools/comfyui_generate.py index 34d770b..eca274b 100644 --- a/Tools/comfyui_generate.py +++ b/Tools/comfyui_generate.py @@ -21,6 +21,10 @@ Outputs land in the given path and a JSON sidecar records the exact prompt, mode seed and workflow, so an asset can be regenerated or rejected later without guessing how it was made. +The server is a **Stability Matrix** install and nothing here starts it: if the tool cannot reach +`127.0.0.1:8188`, start Stability Matrix, launch ComfyUI, and re-run. The install, its launch arguments and +its model library are documented in `/home/zwitschi/StabilityMatrix/Data/README.md`. + Licence: the output is a generated image from a locally hosted model. `THIRD_PARTY NOTICES.md` must record the model and its licence before the texture ships; the sidecar carries what is needed to do that. @@ -42,7 +46,7 @@ HOST = os.environ.get("COMFYUI_HOST", "http://127.0.0.1:8188") DEFAULT_MODEL = "juggernautXL_ragnarok.safetensors" # A second checkpoint by default: one model's texture is a lottery ticket, two is a comparison. Both are # generated from the identical prompt and seed, then scored, and only the winner takes the output path. -DEFAULT_ALT_MODEL = "sd_xl_base_1.0.safetensors" +DEFAULT_ALT_MODEL = "epicrealismXL_pureFix.safetensors" def score_image(path): @@ -183,13 +187,15 @@ def generate_pair(args) -> int: candidate is kept for inspection instead of thrown away. The winner is chosen by `score_image()`; when Pillow is missing or the scores tie, the primary model keeps the output and the run says so. """ - import dataclasses + import copy stem, ext = os.path.splitext(args.out) candidates = [] for label, model in (("primary", args.model), ("alternate", args.alt_model)): out = f"{stem}__{model.replace('/', '_')[:40]}{ext}" - sub_args = dataclasses.replace(args, model=model, out=out) + sub_args = copy.copy(args) + sub_args.model = model + sub_args.out = out if generate(sub_args) != 0: print(f"{label} model {model} failed; continuing with what worked") continue