ComfyUI / redux_experiment_final /scripts /run_matrix_v3.py
aleph65's picture
Archive flux-redux experiment: final writeup, workflows, inputs, scripts, research, v4 outputs, comparison sheets, Claude memories
478cb8f verified
Raw
History Blame Contribute Delete
11.5 kB
#!/usr/bin/env python3
"""v3 matrix: depth-only, handwritten prompts + generic negative, portrait singles. -> outputs_v3."""
import json, os, shutil, sys, time, urllib.request
from run_sweeps import post, HOST, W, H, HW, HH, SEED
OUT_ROOT = "/workspace/outputs_v3"
COMFY_OUT = "/workspace/ComfyUI/output"
R = ["r1.jpg", "r2.jpg", "r3.jpg", "r4.jpg"]
T = ["t1.jpg", "t2.jpg", "t3.jpg", "t4.jpg", "t5.jpg", "t6.jpg"]
POS = ("A photograph of a beautiful woman posing naturally. Her body is anatomically correct, "
"with well-proportioned limbs, natural relaxed hands, and a balanced, graceful posture. "
"The image is sharp and coherent, with realistic skin texture and lighting that matches the scene.")
NEG = ("deformed anatomy, extra limbs, missing limbs, fused or extra fingers, malformed hands, "
"twisted joints, distorted face, mutated body, disfigured, blurry, lowres, jpeg artifacts, "
"watermark, text, logo, oversaturated, plastic skin")
SCENE = ("A candid photograph of a woman walking through a rain-soaked city street at night, "
"neon signs reflecting in the wet pavement, cinematic atmosphere, shallow depth of field, "
"subtle film grain.")
def core2(p, style_img, comp_img, guidance, redux=0.5):
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": POS}}
p["guid"] = {"class_type": "FluxGuidance", "inputs": {"conditioning": ["txt", 0], "guidance": guidance}}
p["neg"] = {"class_type": "CLIPTextEncode", "inputs": {"clip": ["c", 0], "text": NEG}}
p["si"] = {"class_type": "LoadImage", "inputs": {"image": style_img}}
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": redux, "strength_type": "attn_bias"}}
p["ci"] = {"class_type": "LoadImage", "inputs": {"image": comp_img}}
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 v3_style_comp(style_img, comp_img, tag):
p = {}
core2(p, style_img, comp_img, guidance=3.0)
p["savedepth"] = {"class_type": "SaveImage", "inputs": {"images": ["depth", 0],
"filename_prefix": f"v3/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"v3/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"v3/flux-v2-redux-style-composition/hires/{tag}"}}
return p
def v3_bfl(style_img, comp_img, tag):
p = {}
core2(p, style_img, comp_img, guidance=4.0)
p["lora"] = {"class_type": "LoraLoaderModelOnly", "inputs": {"model": ["u", 0],
"lora_name": "flux1-depth-dev-lora.safetensors", "strength_model": 1.0}}
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"v3/flux-v2-redux-style-composition-bfl-lora/{tag}"}}
return p
def single(style_img, tag, 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": POS, "prompt": SCENE, "schnell": ""}[kind]
p["txt"] = {"class_type": "CLIPTextEncode", "inputs": {"clip": ["c", 0], "text": text}}
p["si"] = {"class_type": "LoadImage", "inputs": {"image": style_img}}
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 = (0.5, "attn_bias") if kind == "prompt" else (1.0, "multiply")
if kind == "fal":
strength, stype = 0.6, "attn_bias" # prompt must coexist with style
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"v3/{wfname}/{tag}"}}
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 = []
for r, t in combos:
q.append(v3_style_comp(r, t, f"{r.split('.')[0]}x{t.split('.')[0]}"))
for r, t in combos:
q.append(v3_bfl(r, t, f"{r.split('.')[0]}x{t.split('.')[0]}"))
for r in R:
for kind in ["fal", "prompt", "schnell"]:
q.append(single(r, r.split(".")[0], kind))
ids = {}
for i, prompt in enumerate(q):
ids[post(prompt)] = i
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, "v3")
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] + ".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("V3 MATRIX COMPLETE", flush=True)
if __name__ == "__main__":
main()