File size: 8,822 Bytes
478cb8f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/env python3
"""Full v2 matrix on inputs_v2, seed 777, baked defaults. Outputs -> /workspace/outputs_v2/."""
import json, os, shutil, sys, time, urllib.request
from run_sweeps import post, core, save, bfl_wf, HOST, W, H, HW, HH, SEED

OUT_ROOT = "/workspace/outputs_v2"
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"]

def v2_style_comp(style_img, comp_img, tag):
    p = {}
    core(p, style_img, comp_img, guidance=3.0, redux=0.5)
    p["savecrop"] = {"class_type": "SaveImage", "inputs": {"images": ["rs", 0],
        "filename_prefix": f"flux-v2-redux-style-composition/inputs/{tag}-crop"}}
    p["savedepth"] = {"class_type": "SaveImage", "inputs": {"images": ["depth", 0],
        "filename_prefix": f"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}}
    save(p, ["ks", 0], f"flux-v2-redux-style-composition/{tag}")
    # hires pass (enabled for the matrix: both resolutions saved)
    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"flux-v2-redux-style-composition/hires/{tag}"}}
    return p

def v2_bfl(style_img, comp_img, tag):
    p = bfl_wf(style_img, comp_img, "tmp", 4.0)
    p["ks"]["inputs"]["steps"] = 32
    p["savecrop"] = {"class_type": "SaveImage", "inputs": {"images": ["rs", 0],
        "filename_prefix": f"flux-v2-redux-style-composition-bfl-lora/inputs/{tag}-crop"}}
    p["save"]["inputs"]["filename_prefix"] = f"flux-v2-redux-style-composition-bfl-lora/{tag}"
    return p

def single(style_img, tag, kind):
    p = {}
    if kind == "schnell":
        p["u"] = {"class_type": "UNETLoader", "inputs": {"unet_name": "flux1-schnell.safetensors", "weight_dtype": "default"}}
    else:
        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"}}
    text = "a person walking through a rainy city street at night, cinematic lighting" if kind == "prompt" else ""
    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")
    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 (1024, 1024)
    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"}}
    steps = 4 if kind == "schnell" else 28
    p["sched"] = {"class_type": "BasicScheduler", "inputs": {"model": model, "scheduler": "simple", "steps": steps, "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"{wfname}-v2in/{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:
        tag = f"{r.split('.')[0]}x{t.split('.')[0]}"
        q.append(v2_style_comp(r, t, tag))
    for r, t in combos:
        tag = f"{r.split('.')[0]}x{t.split('.')[0]}"
        q.append(v2_bfl(r, t, tag))
    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 {i+1}/{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 run {ids[pid]}: {(msgs[-1][1].get('exception_message','?') if msgs else '?')[:300]}", flush=True)

    # collect: comfy output dirs -> /workspace/outputs_v2/<wf>/...
    for wf in ["flux-v2-redux-style-composition", "flux-v2-redux-style-composition-bfl-lora",
               "flux-redux-fal-dev-v2in", "flux-redux-prompt-v2in", "flux-redux-schnell-v2in"]:
        src = os.path.join(COMFY_OUT, wf)
        if not os.path.isdir(src): continue
        for root, _, files in os.walk(src):
            rel = os.path.relpath(root, COMFY_OUT)
            dst = os.path.join(OUT_ROOT, rel)
            os.makedirs(dst, exist_ok=True)
            for f in files:
                clean = f.split("_")[0] + ".png" if "_" in f else f
                shutil.copy(os.path.join(root, f), os.path.join(dst, clean))
    print("COLLECTED", flush=True)
    for root, dirs, files in os.walk(OUT_ROOT):
        if files and "sweeps" not in root:
            print(f"  {os.path.relpath(root, OUT_ROOT)}: {len(files)}", flush=True)
    if errors:
        print("ERRORS:", len(errors)); sys.exit(1)
    print("V2 MATRIX COMPLETE", flush=True)

if __name__ == "__main__":
    main()