#!/usr/bin/env python3 """v4 final matrix: per-combo handwritten prompts, multiply 0.35, bfl spec. -> outputs_v4.""" import json, os, shutil, sys, time, urllib.request from run_sweeps import post, HOST, W, H, HW, HH, SEED from prompts_v4 import combo_prompt, FAL_PROMPTS, SCENE_PROMPTS OUT_ROOT = "/workspace/outputs_v4" COMFY_OUT = "/workspace/ComfyUI/output" R = ["r1", "r2", "r3", "r4"] T = ["t1", "t2", "t3", "t4", "t5", "t6"] IMG = {k: f"{k}.jpg" for k in R + T} def core4(p, style_key, target_key, guidance): p["u"] = {"class_type": "UNETLoader", "inputs": {"unet_name": "flux1-dev.safetensors", "weight_dtype": "default"}} p["c"] = {"class_type": "DualCLIPLoader", "inputs": {"clip_name1": "t5xxl_fp16.safetensors", "clip_name2": "clip_l.safetensors", "type": "flux", "device": "default"}} p["v"] = {"class_type": "VAELoader", "inputs": {"vae_name": "ae.safetensors"}} p["txt"] = {"class_type": "CLIPTextEncode", "inputs": {"clip": ["c", 0], "text": combo_prompt(style_key, target_key)}} p["guid"] = {"class_type": "FluxGuidance", "inputs": {"conditioning": ["txt", 0], "guidance": guidance}} p["neg"] = {"class_type": "ConditioningZeroOut", "inputs": {"conditioning": ["guid", 0]}} p["si"] = {"class_type": "LoadImage", "inputs": {"image": IMG[style_key]}} p["cvl"] = {"class_type": "CLIPVisionLoader", "inputs": {"clip_name": "sigclip_vision_patch14_384.safetensors"}} p["cve"] = {"class_type": "CLIPVisionEncode", "inputs": {"clip_vision": ["cvl", 0], "image": ["si", 0], "crop": "center"}} p["sml"] = {"class_type": "StyleModelLoader", "inputs": {"style_model_name": "flux1-redux-dev.safetensors"}} p["sma"] = {"class_type": "StyleModelApply", "inputs": {"conditioning": ["guid", 0], "style_model": ["sml", 0], "clip_vision_output": ["cve", 0], "strength": 0.35, "strength_type": "multiply"}} p["ci"] = {"class_type": "LoadImage", "inputs": {"image": IMG[target_key]}} p["rs"] = {"class_type": "ImageResize+", "inputs": {"image": ["ci", 0], "width": W, "height": H, "interpolation": "lanczos", "method": "fill / crop", "condition": "always", "multiple_of": 0}} p["depth"] = {"class_type": "DepthAnythingV2Preprocessor", "inputs": { "image": ["rs", 0], "ckpt_name": "depth_anything_v2_vitl.pth", "resolution": W}} def v4_style_comp(style_key, target_key): tag = f"{style_key}x{target_key}" p = {} core4(p, style_key, target_key, 3.0) p["savedepth"] = {"class_type": "SaveImage", "inputs": {"images": ["depth", 0], "filename_prefix": f"v4/flux-v2-redux-style-composition/inputs/{tag}-depth"}} p["cnl"] = {"class_type": "ControlNetLoader", "inputs": {"control_net_name": "FLUX.1-dev-ControlNet-Union-Pro-2.0.safetensors"}} p["cn"] = {"class_type": "ControlNetApplySD3", "inputs": {"positive": ["sma", 0], "negative": ["neg", 0], "control_net": ["cnl", 0], "vae": ["v", 0], "image": ["depth", 0], "strength": 0.7, "start_percent": 0.0, "end_percent": 0.8}} p["msf"] = {"class_type": "ModelSamplingFlux", "inputs": {"model": ["u", 0], "max_shift": 1.15, "base_shift": 0.5, "width": W, "height": H}} p["lat"] = {"class_type": "EmptySD3LatentImage", "inputs": {"width": W, "height": H, "batch_size": 1}} p["ks"] = {"class_type": "KSampler", "inputs": {"model": ["msf", 0], "positive": ["cn", 0], "negative": ["cn", 1], "latent_image": ["lat", 0], "seed": SEED, "steps": 32, "cfg": 1.0, "sampler_name": "euler", "scheduler": "simple", "denoise": 1.0}} p["dec"] = {"class_type": "VAEDecode", "inputs": {"samples": ["ks", 0], "vae": ["v", 0]}} p["save"] = {"class_type": "SaveImage", "inputs": {"images": ["dec", 0], "filename_prefix": f"v4/flux-v2-redux-style-composition/{tag}"}} p["up"] = {"class_type": "LatentUpscaleBy", "inputs": {"samples": ["ks", 0], "upscale_method": "bislerp", "scale_by": 1.5}} p["msf2"] = {"class_type": "ModelSamplingFlux", "inputs": {"model": ["u", 0], "max_shift": 1.15, "base_shift": 0.5, "width": HW, "height": HH}} p["ks2"] = {"class_type": "KSampler", "inputs": {"model": ["msf2", 0], "positive": ["sma", 0], "negative": ["neg", 0], "latent_image": ["up", 0], "seed": SEED, "steps": 32, "cfg": 1.0, "sampler_name": "euler", "scheduler": "simple", "denoise": 0.30}} p["dec2"] = {"class_type": "VAEDecode", "inputs": {"samples": ["ks2", 0], "vae": ["v", 0]}} p["save2"] = {"class_type": "SaveImage", "inputs": {"images": ["dec2", 0], "filename_prefix": f"v4/flux-v2-redux-style-composition/hires/{tag}"}} return p def v4_bfl(style_key, target_key): tag = f"{style_key}x{target_key}" p = {} core4(p, style_key, target_key, 10.0) p["lora"] = {"class_type": "LoraLoaderModelOnly", "inputs": {"model": ["u", 0], "lora_name": "flux1-depth-dev-lora.safetensors", "strength_model": 0.85}} p["ip2p"] = {"class_type": "InstructPixToPixConditioning", "inputs": {"positive": ["sma", 0], "negative": ["neg", 0], "vae": ["v", 0], "pixels": ["depth", 0]}} p["msf"] = {"class_type": "ModelSamplingFlux", "inputs": {"model": ["lora", 0], "max_shift": 1.15, "base_shift": 0.5, "width": W, "height": H}} p["ks"] = {"class_type": "KSampler", "inputs": {"model": ["msf", 0], "positive": ["ip2p", 0], "negative": ["ip2p", 1], "latent_image": ["ip2p", 2], "seed": SEED, "steps": 32, "cfg": 1.0, "sampler_name": "euler", "scheduler": "simple", "denoise": 1.0}} p["dec"] = {"class_type": "VAEDecode", "inputs": {"samples": ["ks", 0], "vae": ["v", 0]}} p["save"] = {"class_type": "SaveImage", "inputs": {"images": ["dec", 0], "filename_prefix": f"v4/flux-v2-redux-style-composition-bfl-lora/{tag}"}} return p def single(style_key, kind): p = {} unet = "flux1-schnell.safetensors" if kind == "schnell" else "flux1-dev.safetensors" p["u"] = {"class_type": "UNETLoader", "inputs": {"unet_name": unet, "weight_dtype": "default"}} p["c"] = {"class_type": "DualCLIPLoader", "inputs": {"clip_name1": "t5xxl_fp16.safetensors", "clip_name2": "clip_l.safetensors", "type": "flux", "device": "default"}} p["v"] = {"class_type": "VAELoader", "inputs": {"vae_name": "ae.safetensors"}} text = {"fal": FAL_PROMPTS[style_key], "prompt": SCENE_PROMPTS[style_key], "schnell": ""}[kind] p["txt"] = {"class_type": "CLIPTextEncode", "inputs": {"clip": ["c", 0], "text": text}} p["si"] = {"class_type": "LoadImage", "inputs": {"image": IMG[style_key]}} p["cvl"] = {"class_type": "CLIPVisionLoader", "inputs": {"clip_name": "sigclip_vision_patch14_384.safetensors"}} p["cve"] = {"class_type": "CLIPVisionEncode", "inputs": {"clip_vision": ["cvl", 0], "image": ["si", 0], "crop": "center"}} p["sml"] = {"class_type": "StyleModelLoader", "inputs": {"style_model_name": "flux1-redux-dev.safetensors"}} cond = ["txt", 0] if kind != "schnell": p["guid"] = {"class_type": "FluxGuidance", "inputs": {"conditioning": ["txt", 0], "guidance": 3.5}} cond = ["guid", 0] strength, stype = {"fal": (0.6, "attn_bias"), "prompt": (0.5, "attn_bias"), "schnell": (1.0, "multiply")}[kind] p["sma"] = {"class_type": "StyleModelApply", "inputs": {"conditioning": cond, "style_model": ["sml", 0], "clip_vision_output": ["cve", 0], "strength": strength, "strength_type": stype}} w, h = (768, 1024) if kind == "fal" else (W, H) if kind != "schnell": p["msf"] = {"class_type": "ModelSamplingFlux", "inputs": {"model": ["u", 0], "max_shift": 1.15, "base_shift": 0.5, "width": w, "height": h}} model = ["msf", 0] else: model = ["u", 0] p["noise"] = {"class_type": "RandomNoise", "inputs": {"noise_seed": SEED}} p["guider"] = {"class_type": "BasicGuider", "inputs": {"model": model, "conditioning": ["sma", 0]}} p["samp"] = {"class_type": "KSamplerSelect", "inputs": {"sampler_name": "euler"}} p["sched"] = {"class_type": "BasicScheduler", "inputs": {"model": model, "scheduler": "simple", "steps": 4 if kind == "schnell" else 28, "denoise": 1.0}} p["lat"] = {"class_type": "EmptySD3LatentImage", "inputs": {"width": w, "height": h, "batch_size": 1}} p["sca"] = {"class_type": "SamplerCustomAdvanced", "inputs": {"noise": ["noise", 0], "guider": ["guider", 0], "sampler": ["samp", 0], "sigmas": ["sched", 0], "latent_image": ["lat", 0]}} p["dec"] = {"class_type": "VAEDecode", "inputs": {"samples": ["sca", 0], "vae": ["v", 0]}} wfname = {"fal": "flux-redux-fal-dev", "prompt": "flux-redux-prompt", "schnell": "flux-redux-schnell"}[kind] p["save"] = {"class_type": "SaveImage", "inputs": {"images": ["dec", 0], "filename_prefix": f"v4/{wfname}/{style_key}"}} return p def main(): combos = [(r, t) for r in R for t in T] + [(a, b) for a in R for b in R if a != b] q = [v4_style_comp(r, t) for r, t in combos] + [v4_bfl(r, t) for r, t in combos] q += [single(r, k) for r in R for k in ["fal", "prompt", "schnell"]] ids = {post(p): i for i, p in enumerate(q)} print(f"queued {len(q)}", flush=True) pending, errors = set(ids), [] while pending: time.sleep(15) for pid in list(pending): try: with urllib.request.urlopen(f"{HOST}/history/{pid}") as r: h = json.loads(r.read()) except Exception: continue if pid not in h: continue st = h[pid].get("status", {}) if st.get("completed"): pending.discard(pid) if (len(ids) - len(pending)) % 10 == 0: print(f"progress {len(ids)-len(pending)}/{len(ids)}", flush=True) elif st.get("status_str") == "error": pending.discard(pid); errors.append(pid) msgs = [m for m in st.get("messages", []) if m[0] == "execution_error"] print(f"ERROR: {(msgs[-1][1].get('exception_message','?') if msgs else '?')[:300]}", flush=True) src = os.path.join(COMFY_OUT, "v4") for root, _, files in os.walk(src): rel = os.path.relpath(root, src) dst = os.path.join(OUT_ROOT, rel) os.makedirs(dst, exist_ok=True) for f in files: shutil.copy(os.path.join(root, f), os.path.join(dst, f.split("_0")[0] + ".png")) print("COLLECTED", flush=True) for root, dirs, files in os.walk(OUT_ROOT): if files: print(f" {os.path.relpath(root, OUT_ROOT)}: {len(files)}", flush=True) if errors: print("ERRORS:", len(errors)); sys.exit(1) print("V4 MATRIX COMPLETE", flush=True) if __name__ == "__main__": main()