art_pipe: always seed generation, and record what made each image (#842) #844

Closed
opened 2026-07-25 20:21:54 +00:00 by spikerj · 1 comment
Owner

The actual fix. All three concept backends now build the torch.Generator unconditionally, so an effective seed always exists and is always reported.

New stdlib-only artpipe.generation_params (sibling to result_contract for the same reason: a contract that crosses a boundary lives in one place). Seeds are 0..2**32-1 — the A1111/ComfyUI/Civitai convention, so a recorded seed is portable; out-of-range wraps rather than being rejected, which closes the round trip.

Random materialisation is limited to paths that were ALREADY nondeterministic. Backends with a hardcoded seed (triposg/trellis/hymotion 42, unirig 12345, tex_seed 42) pass it as default= so their output stays byte-identical.

Images carry their own provenance: an artpipe_generation_params PNG chunk plus a parameters chunk in A1111 format (readable by ComfyUI/Civitai/exiftool) and a .artpipe.json sidecar for non-PNG outputs.

DEPLOY NOTE: only SDXL Lightning is reachable in prod (baked into the prodstages monolith). model-env-images.yml has no case for sdxlturbo or fluxschnell, so those two backends' changes are dormant until an image exists. The backend logs a Warning when a concept stage completes with no params — that is the only signal an image is stale.

The actual fix. All three concept backends now build the `torch.Generator` unconditionally, so an effective seed always exists and is always reported. New stdlib-only `artpipe.generation_params` (sibling to `result_contract` for the same reason: a contract that crosses a boundary lives in one place). Seeds are 0..2**32-1 — the A1111/ComfyUI/Civitai convention, so a recorded seed is portable; out-of-range wraps rather than being rejected, which closes the round trip. Random materialisation is limited to paths that were ALREADY nondeterministic. Backends with a hardcoded seed (triposg/trellis/hymotion 42, unirig 12345, tex_seed 42) pass it as `default=` so their output stays byte-identical. Images carry their own provenance: an `artpipe_generation_params` PNG chunk plus a `parameters` chunk in A1111 format (readable by ComfyUI/Civitai/exiftool) and a `.artpipe.json` sidecar for non-PNG outputs. DEPLOY NOTE: only SDXL Lightning is reachable in prod (baked into the prodstages monolith). `model-env-images.yml` has no case for `sdxlturbo` or `fluxschnell`, so those two backends' changes are dormant until an image exists. The backend logs a Warning when a concept stage completes with no params — that is the only signal an image is stale.
Author
Owner

Resolved in spikersoft-artpipe PR #39 (merged to main). Verified against origin/main:

  • New stdlib-only src/artpipe/generation_params.py: resolve_seed(raw, *, default=None) (:60) with SEED_MIN/SEED_MAX = 0..2**32-1 (:38/:43), build_generation_params (:150), attach (:244), write_sidecar (:261, emitting <output>.artpipe.json), a1111_parameters_line (:277), and png_info (:306) writing both the artpipe_generation_params chunk and the A1111-compatible parameters text chunk (:317-318).
  • Seeding is now unconditional, which was the core ask: sdxl_lightning.py:146 resolves the seed and :380 sets run_params["generator"] = torch.Generator(...).manual_seed(seed), with an explicit "Unconditional, unlike before" comment. Sidecar + PNG info at :490/:496, attach at :395/:458.
  • Same shape in the other two concept backends: sdxl_turbo.py:85,97,135,140,146 and flux_schnell.py:182,200,158,163,236 (plus the second path at :259,289,305,327). qr_monster.py:174 adopted it later.
  • Backend persistence exists on spikersoft-backend origin/master: ArtStudioController.cs:1586 BuildGenerationParams, with ArtAssetGenerationParams covered by ArtAssetLegacyDocumentTests.cs:363-414.

Observation, not a gap: the mesh/motion backends still don't call resolve_seed/build_generation_paramstrellis.py:125,201, trellis_mac.py:121, hymotion.py:127 (params.get("seed", 42)), unirig.py:155 (12345), triposg.py:122 (hardcoded 42). This ticket is scoped to images and PR #39 correctly touched only the concept backends. If you want deterministic mesh generation too, that's worth its own ticket.

Closing.

Resolved in spikersoft-artpipe PR #39 (merged to `main`). Verified against `origin/main`: - New stdlib-only `src/artpipe/generation_params.py`: `resolve_seed(raw, *, default=None)` (`:60`) with `SEED_MIN`/`SEED_MAX` = `0..2**32-1` (`:38`/`:43`), `build_generation_params` (`:150`), `attach` (`:244`), `write_sidecar` (`:261`, emitting `<output>.artpipe.json`), `a1111_parameters_line` (`:277`), and `png_info` (`:306`) writing both the `artpipe_generation_params` chunk and the A1111-compatible `parameters` text chunk (`:317-318`). - **Seeding is now unconditional**, which was the core ask: `sdxl_lightning.py:146` resolves the seed and `:380` sets `run_params["generator"] = torch.Generator(...).manual_seed(seed)`, with an explicit "Unconditional, unlike before" comment. Sidecar + PNG info at `:490`/`:496`, attach at `:395`/`:458`. - Same shape in the other two concept backends: `sdxl_turbo.py:85,97,135,140,146` and `flux_schnell.py:182,200,158,163,236` (plus the second path at `:259,289,305,327`). `qr_monster.py:174` adopted it later. - Backend persistence exists on `spikersoft-backend` `origin/master`: `ArtStudioController.cs:1586` `BuildGenerationParams`, with `ArtAssetGenerationParams` covered by `ArtAssetLegacyDocumentTests.cs:363-414`. Observation, not a gap: the mesh/motion backends still don't call `resolve_seed`/`build_generation_params` — `trellis.py:125,201`, `trellis_mac.py:121`, `hymotion.py:127` (`params.get("seed", 42)`), `unirig.py:155` (12345), `triposg.py:122` (hardcoded 42). This ticket is scoped to images and PR #39 correctly touched only the concept backends. If you want deterministic mesh generation too, that's worth its own ticket. Closing.
Sign in to join this conversation.