docs(examples): Workflow Sweep example on an SDXL API graph (#6)
The answer to "non standard workflow" grids: the sweep runs the user's exact exported graph per job (reference-image conditioning, ControlNet, custom nodes...), changing only the bound inputs. uscg-workflow-sweep-sdxl.json sweeps cfg x sampler x prompt (8 jobs) on an embedded SDXL graph; README section; test_examples covers it (8 jobs, 8 distinct fingerprints). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
daf3cbce49
commit
6498fdb19a
@@ -82,6 +82,16 @@ Times are approximate on an RTX 5060 Ti 16 GB, not counting the first model load
|
||||
* **Time:** TBD
|
||||
* **Notes:** SLG uses the official recipe, single block 22 for the first 0-50 % of the steps. Compare the two images to see what it does. CLIP type `moss_image`. A smaller `flux2-vae_small.safetensors` VAE also exists and can be picked in the Builder instead. The 9B text encoder is large; on a 16 GB card expect model swapping.
|
||||
|
||||
## Workflow Sweep on your own graph (`uscg-workflow-sweep-sdxl.json`)
|
||||
|
||||
| File | Folder |
|
||||
|---|---|
|
||||
| `sd_xl_base_1.0.safetensors` | `models/checkpoints/` |
|
||||
|
||||
* **What the grid tests:** one Workflow Sweep array that wraps a complete SDXL text-to-image graph (Load Checkpoint, two CLIP Text Encode, Empty Latent 1024x1024, KSampler, VAE Decode, Save Image) and sweeps three things on it: KSampler `cfg` 5 and 7 x `sampler_name` euler and dpmpp_2m x 2 positive prompts (one shared negative). **8 images**
|
||||
* **Time:** TBD
|
||||
* **Notes:** unlike the other examples, the Builder does not build the pipeline here. The sweep runs your exact exported graph once per job, changing only the inputs you bound, and collects the result into the Dashboard like any other run. This is how to grid-test a workflow the three-node grid cannot express, such as reference-image conditioning, ControlNet, multi-stage or custom-node graphs. To use your own: in ComfyUI use Export (API), open the Config Builder's **Workflow Sweep** section, load that file, pick the output image, and choose the inputs to sweep. Any API-format export works, for example the Flux.2 example in this folder could be exported and swept the same way. The embedded SDXL graph here is only a stand-in so the example runs with one checkpoint.
|
||||
|
||||
## Make your own
|
||||
|
||||
* Edit the Builder: add LoRAs or a whole LoRA folder, more samplers, schedulers, step counts, cfg values, resolutions or prompts. Every list is multiplied together.
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -29,6 +29,7 @@ EXPECTED_IMAGES = {
|
||||
"uscg-krea2-turbo.json": 2,
|
||||
"uscg-flux2-klein-9b.json": 4, # Advanced Sampling on + off (expand_configs grids both)
|
||||
"uscg-moss-image.json": 2,
|
||||
"uscg-workflow-sweep-sdxl.json": 8, # Workflow Sweep: 2 cfg x 2 samplers x 2 prompts
|
||||
}
|
||||
|
||||
# Every top-level key of the Builder's new-state object (web/conf_builder/conf-builder-main.js,
|
||||
@@ -49,6 +50,7 @@ ALLOWED_FILES = {
|
||||
"uscg-krea2-turbo.json": {"krea2_turbo_fp8_scaled.safetensors", "qwen3vl_4b_fp8_scaled.safetensors", "qwen_image_vae.safetensors"},
|
||||
"uscg-flux2-klein-9b.json": {"flux-2-klein-9b-fp8.safetensors", "qwen_3_8b_fp8mixed.safetensors", "flux2-vae.safetensors"},
|
||||
"uscg-moss-image.json": {"moss_image_sft_int8_convrot.safetensors", "qwen3.5_9b_w4a8_gptq.safetensors", "flux2-vae.safetensors"},
|
||||
"uscg-workflow-sweep-sdxl.json": {"sd_xl_base_1.0.safetensors"},
|
||||
}
|
||||
|
||||
|
||||
@@ -146,6 +148,10 @@ def test_no_local_paths_and_known_filenames(path):
|
||||
state = _state(_load(path))
|
||||
used = set()
|
||||
for a in state["config_arrays"]:
|
||||
if a.get("kind") == "workflow": # files live inside the embedded API graph
|
||||
used.update(n["inputs"]["ckpt_name"] for n in a["workflow"]["api_prompt"].values()
|
||||
if n["class_type"] == "CheckpointLoaderSimple")
|
||||
continue
|
||||
for m in a["models"]:
|
||||
used.add(m["path"] if isinstance(m, dict) else m)
|
||||
used.update(a["text_encoders"])
|
||||
@@ -183,3 +189,14 @@ def test_family_settings():
|
||||
assert moss[0]["clip_type"] == "moss_image"
|
||||
assert moss[0]["use_slg"] is True and moss[0]["slg_single_layers"] == "22"
|
||||
assert moss[1]["use_slg"] is False
|
||||
|
||||
|
||||
def test_workflow_sweep_example():
|
||||
cfg = _cfgs("uscg-workflow-sweep-sdxl.json")
|
||||
assert len(cfg) == 1 and cfg[0]["model_type"] == "workflow"
|
||||
assert cfg[0]["workflow_output"] == {"node_id": "8", "output_index": 0}
|
||||
import workflow_sweep as ws
|
||||
jobs = ws.expand_workflow_entry(cfg[0], 0, None, None)
|
||||
assert len(jobs) == 8 and len({j["wf_fingerprint"] for j in jobs}) == 8
|
||||
assert {j["wf_params"]["KSampler.cfg"] for j in jobs} == {5, 7}
|
||||
assert {j["wf_params"]["KSampler.sampler_name"] for j in jobs} == {"euler", "dpmpp_2m"}
|
||||
|
||||
Reference in New Issue
Block a user