Download redux_experiment_final/scripts/build_workflows.py from aleph65/ComfyUI: direct link, hf CLI and curl.
- Browser
- Download file 25.1 kB
-
https://huggingface.co/aleph65/ComfyUI/resolve/main/redux_experiment_final/scripts/build_workflows.py
- Command line
-
hf download hf://aleph65/ComfyUI/redux_experiment_final/scripts/build_workflows.py
-
curl -L -o build_workflows.py https://huggingface.co/aleph65/ComfyUI/resolve/main/redux_experiment_final/scripts/build_workflows.py
25.1 kB
| #!/usr/bin/env python3 | |
| """Generate the flux-redux workflow JSON drafts (ComfyUI graph format 0.4).""" | |
| import json, os | |
| OUT = "/workspace/workflows/wip" | |
| os.makedirs(OUT, exist_ok=True) | |
| CORE = {"cnr_id": "comfy-core", "ver": "0.27.0"} | |
| AUX = {"cnr_id": "comfyui_controlnet_aux"} | |
| REFLUX = {"aux_id": "kaibioinfo/ComfyUI_AdvancedRefluxControl"} | |
| # node type -> (link_inputs [(name,TYPE)...], outputs [(name,TYPE)...], pack_props, default_size) | |
| DEFS = { | |
| "MarkdownNote": ([], [], CORE, [520, 460]), | |
| "UNETLoader": ([], [("MODEL", "MODEL")], CORE, [340, 82]), | |
| "DualCLIPLoader": ([], [("CLIP", "CLIP")], CORE, [340, 130]), | |
| "VAELoader": ([], [("VAE", "VAE")], CORE, [340, 58]), | |
| "CLIPVisionLoader": ([], [("CLIP_VISION", "CLIP_VISION")], CORE, [340, 58]), | |
| "LoadImage": ([], [("IMAGE", "IMAGE"), ("MASK", "MASK")], CORE, [274, 314]), | |
| "CLIPVisionEncode": ([("clip_vision", "CLIP_VISION"), ("image", "IMAGE")], | |
| [("CLIP_VISION_OUTPUT", "CLIP_VISION_OUTPUT")], CORE, [290, 78]), | |
| "StyleModelLoader": ([], [("STYLE_MODEL", "STYLE_MODEL")], CORE, [340, 58]), | |
| "StyleModelApply": ([("conditioning", "CONDITIONING"), ("style_model", "STYLE_MODEL"), | |
| ("clip_vision_output", "CLIP_VISION_OUTPUT")], | |
| [("CONDITIONING", "CONDITIONING")], CORE, [320, 102]), | |
| "ReduxAdvanced": ([("conditioning", "CONDITIONING"), ("style_model", "STYLE_MODEL"), | |
| ("clip_vision", "CLIP_VISION"), ("image", "IMAGE"), ("mask", "MASK")], | |
| [("CONDITIONING", "CONDITIONING"), ("IMAGE", "IMAGE"), ("MASK", "MASK")], | |
| REFLUX, [320, 190]), | |
| "CLIPTextEncode": ([("clip", "CLIP")], [("CONDITIONING", "CONDITIONING")], CORE, [400, 160]), | |
| "FluxGuidance": ([("conditioning", "CONDITIONING")], [("CONDITIONING", "CONDITIONING")], CORE, [290, 58]), | |
| "ConditioningZeroOut": ([("conditioning", "CONDITIONING")], [("CONDITIONING", "CONDITIONING")], CORE, [290, 48]), | |
| "ControlNetLoader": ([], [("CONTROL_NET", "CONTROL_NET")], CORE, [380, 58]), | |
| "ControlNetApplySD3": ([("positive", "CONDITIONING"), ("negative", "CONDITIONING"), | |
| ("control_net", "CONTROL_NET"), ("vae", "VAE"), ("image", "IMAGE")], | |
| [("positive", "CONDITIONING"), ("negative", "CONDITIONING")], CORE, [320, 166]), | |
| "Canny": ([("image", "IMAGE")], [("IMAGE", "IMAGE")], CORE, [290, 82]), | |
| "DepthAnythingV2Preprocessor": ([("image", "IMAGE")], [("IMAGE", "IMAGE")], AUX, [330, 82]), | |
| "EmptySD3LatentImage": ([], [("LATENT", "LATENT")], CORE, [290, 106]), | |
| "ModelSamplingFlux": ([("model", "MODEL")], [("MODEL", "MODEL")], CORE, [300, 130]), | |
| "LoraLoaderModelOnly": ([("model", "MODEL")], [("MODEL", "MODEL")], CORE, [340, 82]), | |
| "KSampler": ([("model", "MODEL"), ("positive", "CONDITIONING"), ("negative", "CONDITIONING"), | |
| ("latent_image", "LATENT")], [("LATENT", "LATENT")], CORE, [300, 262]), | |
| "RandomNoise": ([], [("NOISE", "NOISE")], CORE, [290, 82]), | |
| "KSamplerSelect": ([], [("SAMPLER", "SAMPLER")], CORE, [290, 58]), | |
| "BasicScheduler": ([("model", "MODEL")], [("SIGMAS", "SIGMAS")], CORE, [290, 106]), | |
| "BasicGuider": ([("model", "MODEL"), ("conditioning", "CONDITIONING")], | |
| [("GUIDER", "GUIDER")], CORE, [240, 66]), | |
| "SamplerCustomAdvanced": ([("noise", "NOISE"), ("guider", "GUIDER"), ("sampler", "SAMPLER"), | |
| ("sigmas", "SIGMAS"), ("latent_image", "LATENT")], | |
| [("output", "LATENT"), ("denoised_output", "LATENT")], CORE, [270, 126]), | |
| "InstructPixToPixConditioning": ([("positive", "CONDITIONING"), ("negative", "CONDITIONING"), | |
| ("vae", "VAE"), ("pixels", "IMAGE")], | |
| [("positive", "CONDITIONING"), ("negative", "CONDITIONING"), | |
| ("latent", "LATENT")], CORE, [300, 106]), | |
| "VAEDecode": ([("samples", "LATENT"), ("vae", "VAE")], [("IMAGE", "IMAGE")], CORE, [210, 66]), | |
| "SaveImage": ([("images", "IMAGE")], [], CORE, [400, 400]), | |
| "PreviewImage": ([("images", "IMAGE")], [], CORE, [300, 300]), | |
| } | |
| BYPASS = 4 | |
| class G: | |
| def __init__(self): | |
| self.nodes, self.links, self.groups = [], [], [] | |
| self.nid, self.lid = 0, 0 | |
| def add(self, type_, widgets=None, inputs=None, pos=(0, 0), size=None, mode=0, title=None): | |
| """inputs: {slot_name: (src_node_dict, src_slot_index)}""" | |
| link_ins, outs, pack, dsize = DEFS[type_] | |
| self.nid += 1 | |
| node = { | |
| "id": self.nid, "type": type_, "pos": list(pos), | |
| "size": list(size or dsize), "flags": {}, "order": len(self.nodes), | |
| "mode": mode, | |
| "inputs": [], "outputs": [], | |
| "properties": {"Node name for S&R": type_, **pack}, | |
| } | |
| if title: | |
| node["title"] = title | |
| if widgets is not None: | |
| node["widgets_values"] = list(widgets) | |
| for name, typ in link_ins: | |
| entry = {"name": name, "type": typ, "link": None} | |
| src = (inputs or {}).get(name) | |
| if src is not None: | |
| src_node, src_slot = src | |
| self.lid += 1 | |
| entry["link"] = self.lid | |
| self.links.append([self.lid, src_node["id"], src_slot, self.nid, | |
| len(node["inputs"]), typ]) | |
| src_node["outputs"][src_slot].setdefault("links", []).append(self.lid) | |
| node["inputs"].append(entry) | |
| for i, (name, typ) in enumerate(outs): | |
| node["outputs"].append({"name": name, "type": typ, "links": [], "slot_index": i}) | |
| self.nodes.append(node) | |
| return node | |
| def group(self, title, x, y, w, h, color="#3f789e"): | |
| self.groups.append({"id": len(self.groups) + 1, "title": title, | |
| "bounding": [x, y, w, h], "color": color, | |
| "font_size": 24, "flags": {}}) | |
| def dump(self, path): | |
| doc = {"id": "00000000-0000-0000-0000-000000000000", "revision": 0, | |
| "last_node_id": self.nid, "last_link_id": self.lid, | |
| "nodes": self.nodes, "links": self.links, "groups": self.groups, | |
| "config": {}, "extra": {}, "version": 0.4} | |
| with open(path, "w") as f: | |
| json.dump(doc, f, indent=2) | |
| print("wrote", path, f"({len(self.nodes)} nodes, {len(self.links)} links)") | |
| def flux_loaders(g, unet="flux1-dev.safetensors", x=-720): | |
| unet_n = g.add("UNETLoader", [unet, "default"], pos=(x, -80)) | |
| clip = g.add("DualCLIPLoader", ["t5xxl_fp16.safetensors", "clip_l.safetensors", "flux", "default"], pos=(x, 60)) | |
| vae = g.add("VAELoader", ["ae.safetensors"], pos=(x, 250)) | |
| return unet_n, clip, vae | |
| def redux_branch(g, x, y, img_name="style_ref.png"): | |
| img = g.add("LoadImage", [img_name, "image"], pos=(x, y), title="Style reference (Image A)") | |
| cv_loader = g.add("CLIPVisionLoader", ["sigclip_vision_patch14_384.safetensors"], pos=(x, y + 360)) | |
| enc = g.add("CLIPVisionEncode", ["center"], inputs={"clip_vision": (cv_loader, 0), "image": (img, 0)}, | |
| pos=(x + 380, y + 60)) | |
| sm = g.add("StyleModelLoader", ["flux1-redux-dev.safetensors"], pos=(x, y + 450)) | |
| return img, cv_loader, enc, sm | |
| # ---------------------------------------------------------------- #1 priority | |
| def build_style_composition(): | |
| g = G() | |
| g.add("MarkdownNote", ["""## FLUX Redux + ControlNet β style + composition (v1 draft) | |
| **Image A (style)** supplies aesthetic/palette/lighting via **FLUX.1 Redux**; **Image B | |
| (composition)** supplies layout via **Depth** (Shakker-Labs ControlNet **Union-Pro-2.0** β mode | |
| inferred from the control image, do NOT add SetUnionControlNetType). Optional text prompt. | |
| **Models** (HF `aleph65/ComfyUI`): | |
| - `diffusion_models/flux1-dev.safetensors` (bf16) Β· `text_encoders/t5xxl_fp16.safetensors` + | |
| `clip_l.safetensors` Β· `vae/ae.safetensors` | |
| - `style_models/flux1-redux-dev.safetensors` Β· `clip_vision/sigclip_vision_patch14_384.safetensors` | |
| - `controlnet/FLUX.1-dev-ControlNet-Union-Pro-2.0.safetensors` | |
| - bypassed extras: `loras/flux1-turbo-alpha.safetensors` | |
| - `depth_anything_v2_vitl.pth` auto-downloads into `custom_nodes/comfyui_controlnet_aux/ckpts/` | |
| **Knobs** | |
| - *Apply Style Model* `strength` = Redux influence, `attn_bias` mode: 0.3β0.7 (start 0.5). | |
| Raise if style too weak; lower (or use the ReduxAdvanced group) if Image A's layout leaks. | |
| - *Depth ControlNet* strength 0.6β0.8, end_percent 0.8 (official 2.0 rec: 0.8/0.8). | |
| - **Canny group (bypassed)**: enable to stack hard contour lock at LOW strength 0.25β0.4, or | |
| use instead of depth (rewire). Union-Pro-2.0 handles both from the same loader. | |
| - **ReduxAdvanced group (bypassed)**: alternative style isolation via token downsampling | |
| (factor 3). To use: connect its CONDITIONING output to the depth Apply ControlNet `positive` | |
| (replacing Apply Style Model) and enable the node. | |
| - **Turbo group (bypassed)**: enable turbo-alpha LoRA + set steps to 8 for fast previews. | |
| - Sampler: euler / simple / 28 steps / CFG 1.0 / FluxGuidance 3.5 / denoise 1.0. | |
| Prompt may be empty; a short scene description usually helps. Match latent aspect to Image B. | |
| """], pos=(-1340, -120), size=[580, 700]) | |
| unet, clip, vae = flux_loaders(g) | |
| # style branch | |
| s_img, cv_loader, cv_enc, sm_loader = redux_branch(g, -720, 420) | |
| # text branch | |
| txt = g.add("CLIPTextEncode", [""], inputs={"clip": (clip, 0)}, pos=(-300, 60), | |
| title="Prompt (optional β may stay empty)") | |
| guid = g.add("FluxGuidance", [3.5], inputs={"conditioning": (txt, 0)}, pos=(140, 60)) | |
| neg = g.add("ConditioningZeroOut", inputs={"conditioning": (guid, 0)}, pos=(140, 170)) | |
| apply_style = g.add("StyleModelApply", [0.5, "attn_bias"], | |
| inputs={"conditioning": (guid, 0), "style_model": (sm_loader, 0), | |
| "clip_vision_output": (cv_enc, 0)}, pos=(140, 300)) | |
| # ALT: ReduxAdvanced (bypassed, output unconnected) | |
| radv = g.add("ReduxAdvanced", [3, "area", "center crop (square)", 1.0, 0.1], | |
| inputs={"conditioning": (guid, 0), "style_model": (sm_loader, 0), | |
| "clip_vision": (cv_loader, 0), "image": (s_img, 0)}, | |
| pos=(140, 520), mode=BYPASS, title="ALT: ReduxAdvanced (rewire to use)") | |
| # composition branch | |
| c_img = g.add("LoadImage", ["composition_ref.png", "image"], pos=(-720, 1000), | |
| title="Composition reference (Image B)") | |
| depth = g.add("DepthAnythingV2Preprocessor", ["depth_anything_v2_vitl.pth", 1024], | |
| inputs={"image": (c_img, 0)}, pos=(-300, 1030)) | |
| depth_prev = g.add("PreviewImage", inputs={"images": (depth, 0)}, pos=(-300, 1180), | |
| title="Depth map preview") | |
| canny = g.add("Canny", [0.2, 0.5], inputs={"image": (c_img, 0)}, pos=(-300, 1540), | |
| mode=BYPASS, title="OPTIONAL: canny edges") | |
| cn_loader = g.add("ControlNetLoader", ["FLUX.1-dev-ControlNet-Union-Pro-2.0.safetensors"], | |
| pos=(140, 950)) | |
| cn_depth = g.add("ControlNetApplySD3", [0.7, 0.0, 0.8], | |
| inputs={"positive": (apply_style, 0), "negative": (neg, 0), | |
| "control_net": (cn_loader, 0), "vae": (vae, 0), "image": (depth, 0)}, | |
| pos=(560, 300), title="Apply ControlNet β DEPTH") | |
| cn_canny = g.add("ControlNetApplySD3", [0.35, 0.0, 0.6], | |
| inputs={"positive": (cn_depth, 0), "negative": (cn_depth, 1), | |
| "control_net": (cn_loader, 0), "vae": (vae, 0), "image": (canny, 0)}, | |
| pos=(560, 560), mode=BYPASS, title="OPTIONAL: Apply ControlNet β CANNY (stack)") | |
| # model chain + sampling | |
| turbo = g.add("LoraLoaderModelOnly", ["flux1-turbo-alpha.safetensors", 1.0], | |
| inputs={"model": (unet, 0)}, pos=(-300, -160), mode=BYPASS, | |
| title="FAST PREVIEW: turbo LoRA (set steps 8)") | |
| msf = g.add("ModelSamplingFlux", [1.15, 0.5, 1024, 1024], inputs={"model": (turbo, 0)}, | |
| pos=(140, -160)) | |
| latent = g.add("EmptySD3LatentImage", [1024, 1024, 1], pos=(560, 950)) | |
| ks = g.add("KSampler", [0, "randomize", 28, 1.0, "euler", "simple", 1.0], | |
| inputs={"model": (msf, 0), "positive": (cn_canny, 0), "negative": (cn_canny, 1), | |
| "latent_image": (latent, 0)}, pos=(980, 300)) | |
| dec = g.add("VAEDecode", inputs={"samples": (ks, 0), "vae": (vae, 0)}, pos=(1320, 300)) | |
| g.add("SaveImage", ["flux-redux/style-comp"], inputs={"images": (dec, 0)}, pos=(1320, 420)) | |
| g.group("STYLE REFERENCE β Redux", -740, 340, 1220, 700, "#3f789e") | |
| g.group("COMPOSITION REFERENCE β Union-Pro-2.0", -740, 900, 1220, 800, "#8f5b34") | |
| g.group("SAMPLING", 940, 200, 800, 700, "#444") | |
| g.dump(f"{OUT}/flux-redux-style-composition.json") | |
| # ---------------------------------------------------------------- #2 fal replica | |
| def build_fal_dev(): | |
| g = G() | |
| g.add("MarkdownNote", ["""## FLUX Redux β fal `flux/dev/redux` replica (v1 draft) | |
| Official ComfyUI Redux example graph with fal's exact defaults. One image in β variations out. | |
| No safety checker (unlike fal). Doubles as the plain single-image Redux workflow. | |
| **Models** (HF `aleph65/ComfyUI`): `diffusion_models/flux1-dev.safetensors` (bf16, dtype | |
| `default`) Β· `text_encoders/t5xxl_fp16.safetensors` + `clip_l.safetensors` Β· `vae/ae.safetensors` | |
| Β· `style_models/flux1-redux-dev.safetensors` Β· `clip_vision/sigclip_vision_patch14_384.safetensors` | |
| **fal parity settings** β prompt empty (fal dev endpoint passes none), FluxGuidance 3.5 | |
| (= guidance_scale), euler / simple / 28 steps / denoise 1.0, 768x1024 (= portrait_4_3), | |
| Apply Style Model strength 1.0 / multiply. Seeds do NOT transfer from fal. | |
| **Extras fal doesn't expose**: type a prompt; lower strength (or switch to `attn_bias`) to let | |
| the prompt steer; chain a second Apply Style Model to blend two references. | |
| """], pos=(-1300, -80), size=[540, 460]) | |
| unet, clip, vae = flux_loaders(g) | |
| s_img, cv_loader, cv_enc, sm_loader = redux_branch(g, -720, 420) | |
| txt = g.add("CLIPTextEncode", [""], inputs={"clip": (clip, 0)}, pos=(-300, 60), | |
| title="Prompt (empty = fal parity)") | |
| guid = g.add("FluxGuidance", [3.5], inputs={"conditioning": (txt, 0)}, pos=(140, 60)) | |
| apply_style = g.add("StyleModelApply", [1.0, "multiply"], | |
| inputs={"conditioning": (guid, 0), "style_model": (sm_loader, 0), | |
| "clip_vision_output": (cv_enc, 0)}, pos=(140, 200)) | |
| msf = g.add("ModelSamplingFlux", [1.15, 0.5, 768, 1024], inputs={"model": (unet, 0)}, | |
| pos=(140, -160)) | |
| noise = g.add("RandomNoise", [0, "randomize"], pos=(560, -160)) | |
| guider = g.add("BasicGuider", inputs={"model": (msf, 0), "conditioning": (apply_style, 0)}, | |
| pos=(560, 20)) | |
| sampler = g.add("KSamplerSelect", ["euler"], pos=(560, 140)) | |
| sched = g.add("BasicScheduler", ["simple", 28, 1.0], inputs={"model": (msf, 0)}, pos=(560, 250)) | |
| latent = g.add("EmptySD3LatentImage", [768, 1024, 1], pos=(560, 420)) | |
| samp = g.add("SamplerCustomAdvanced", | |
| inputs={"noise": (noise, 0), "guider": (guider, 0), "sampler": (sampler, 0), | |
| "sigmas": (sched, 0), "latent_image": (latent, 0)}, pos=(980, 60)) | |
| dec = g.add("VAEDecode", inputs={"samples": (samp, 0), "vae": (vae, 0)}, pos=(1240, 60)) | |
| g.add("SaveImage", ["flux-redux/fal-dev"], inputs={"images": (dec, 0)}, pos=(1240, 180)) | |
| g.group("STYLE REFERENCE β Redux", -740, 340, 940, 700, "#3f789e") | |
| g.group("SAMPLING (fal defaults)", 540, -220, 1100, 760, "#444") | |
| g.dump(f"{OUT}/flux-redux-fal-dev.json") | |
| # ---------------------------------------------------------------- #3 image + prompt | |
| def build_prompt(): | |
| g = G() | |
| g.add("MarkdownNote", ["""## FLUX Redux + text prompt (v1 draft) | |
| One style image + a text prompt that keeps authority. Same graph as the fal replica, but Redux | |
| is restrained with **attn_bias 0.5** so the prompt actually steers content β at 1.0/multiply | |
| Redux drowns the prompt (that's the known Redux failure mode). | |
| **Models**: same as `flux-redux-fal-dev.json`. Optional fast preview: enable the bypassed | |
| turbo LoRA group (`loras/flux1-turbo-alpha.safetensors`) and set steps 28 β 8. | |
| **Knobs**: strength 0.3β0.7 attn_bias (higher = more style, more subject leakage from the | |
| reference); FluxGuidance 3.5; euler / simple / 28 steps; 1024x1024 (any flux-legal size). | |
| If the reference's composition/subjects still leak: lower strength, or install | |
| `ComfyUI_AdvancedRefluxControl` and swap in ReduxAdvanced (downsampling 3) β see the | |
| style-composition workflow for the wiring. | |
| """], pos=(-1300, -80), size=[540, 420]) | |
| unet, clip, vae = flux_loaders(g) | |
| s_img, cv_loader, cv_enc, sm_loader = redux_branch(g, -720, 420) | |
| txt = g.add("CLIPTextEncode", ["describe the scene you want, in the reference's style"], | |
| inputs={"clip": (clip, 0)}, pos=(-300, 60), title="Prompt") | |
| guid = g.add("FluxGuidance", [3.5], inputs={"conditioning": (txt, 0)}, pos=(140, 60)) | |
| apply_style = g.add("StyleModelApply", [0.5, "attn_bias"], | |
| inputs={"conditioning": (guid, 0), "style_model": (sm_loader, 0), | |
| "clip_vision_output": (cv_enc, 0)}, pos=(140, 200)) | |
| turbo = g.add("LoraLoaderModelOnly", ["flux1-turbo-alpha.safetensors", 1.0], | |
| inputs={"model": (unet, 0)}, pos=(-300, -160), mode=BYPASS, | |
| title="FAST PREVIEW: turbo LoRA (set steps 8)") | |
| msf = g.add("ModelSamplingFlux", [1.15, 0.5, 1024, 1024], inputs={"model": (turbo, 0)}, | |
| pos=(140, -160)) | |
| noise = g.add("RandomNoise", [0, "randomize"], pos=(560, -160)) | |
| guider = g.add("BasicGuider", inputs={"model": (msf, 0), "conditioning": (apply_style, 0)}, | |
| pos=(560, 20)) | |
| sampler = g.add("KSamplerSelect", ["euler"], pos=(560, 140)) | |
| sched = g.add("BasicScheduler", ["simple", 28, 1.0], inputs={"model": (msf, 0)}, pos=(560, 250)) | |
| latent = g.add("EmptySD3LatentImage", [1024, 1024, 1], pos=(560, 420)) | |
| samp = g.add("SamplerCustomAdvanced", | |
| inputs={"noise": (noise, 0), "guider": (guider, 0), "sampler": (sampler, 0), | |
| "sigmas": (sched, 0), "latent_image": (latent, 0)}, pos=(980, 60)) | |
| dec = g.add("VAEDecode", inputs={"samples": (samp, 0), "vae": (vae, 0)}, pos=(1240, 60)) | |
| g.add("SaveImage", ["flux-redux/prompt"], inputs={"images": (dec, 0)}, pos=(1240, 180)) | |
| g.group("STYLE REFERENCE β Redux", -740, 340, 940, 700, "#3f789e") | |
| g.group("SAMPLING", 540, -220, 1100, 760, "#444") | |
| g.dump(f"{OUT}/flux-redux-prompt.json") | |
| # ---------------------------------------------------------------- #4 replicate schnell | |
| def build_schnell(): | |
| g = G() | |
| g.add("MarkdownNote", ["""## FLUX Redux schnell β Replicate `flux-redux-schnell` replica (v1 draft) | |
| Parity with Replicate's `black-forest-labs/flux-redux-schnell` endpoint: image variations in | |
| **4 steps**, no prompt (their `redux_image` replaces it), no guidance (schnell ignores it β the | |
| endpoint schema has none, hence no FluxGuidance node), no safety checker locally. | |
| **Models** (HF `aleph65/ComfyUI`): `diffusion_models/flux1-schnell.safetensors` (bf16, | |
| Apache-2.0, HF repo not gated) Β· `text_encoders/t5xxl_fp16.safetensors` + `clip_l.safetensors` | |
| Β· `vae/ae.safetensors` Β· `style_models/flux1-redux-dev.safetensors` Β· | |
| `clip_vision/sigclip_vision_patch14_384.safetensors` | |
| **Endpoint mapping** β aspect_ratio @ ~1MP β EmptySD3LatentImage size (default 1:1 = | |
| 1024x1024); num_outputs 1β4 β batch_size; num_inference_steps (max 4) β steps; seed β noise | |
| seed (values do NOT reproduce Replicate's outputs). euler / simple / denoise 1.0 / | |
| Apply Style Model 1.0 multiply. Lower steps = faster + worse, exactly like the endpoint. | |
| """], pos=(-1300, -80), size=[540, 440]) | |
| unet, clip, vae = flux_loaders(g, unet="flux1-schnell.safetensors") | |
| s_img, cv_loader, cv_enc, sm_loader = redux_branch(g, -720, 420) | |
| txt = g.add("CLIPTextEncode", [""], inputs={"clip": (clip, 0)}, pos=(-300, 60), | |
| title="Prompt (endpoint has none β leave empty)") | |
| apply_style = g.add("StyleModelApply", [1.0, "multiply"], | |
| inputs={"conditioning": (txt, 0), "style_model": (sm_loader, 0), | |
| "clip_vision_output": (cv_enc, 0)}, pos=(140, 100)) | |
| noise = g.add("RandomNoise", [0, "randomize"], pos=(560, -160)) | |
| guider = g.add("BasicGuider", inputs={"model": (unet, 0), "conditioning": (apply_style, 0)}, | |
| pos=(560, 20)) | |
| sampler = g.add("KSamplerSelect", ["euler"], pos=(560, 140)) | |
| sched = g.add("BasicScheduler", ["simple", 4, 1.0], inputs={"model": (unet, 0)}, pos=(560, 250)) | |
| latent = g.add("EmptySD3LatentImage", [1024, 1024, 1], pos=(560, 420), | |
| title="size = aspect_ratio @ 1MP Β· batch = num_outputs") | |
| samp = g.add("SamplerCustomAdvanced", | |
| inputs={"noise": (noise, 0), "guider": (guider, 0), "sampler": (sampler, 0), | |
| "sigmas": (sched, 0), "latent_image": (latent, 0)}, pos=(980, 60)) | |
| dec = g.add("VAEDecode", inputs={"samples": (samp, 0), "vae": (vae, 0)}, pos=(1240, 60)) | |
| g.add("SaveImage", ["flux-redux/schnell"], inputs={"images": (dec, 0)}, pos=(1240, 180)) | |
| g.group("STYLE REFERENCE β Redux", -740, 340, 940, 700, "#3f789e") | |
| g.group("SAMPLING (Replicate defaults, 4 steps)", 540, -220, 1100, 760, "#444") | |
| g.dump(f"{OUT}/flux-redux-schnell.json") | |
| # ---------------------------------------------------------------- #5 BFL depth lora A/B | |
| def build_bfl_lora(): | |
| g = G() | |
| g.add("MarkdownNote", ["""## FLUX Redux + official BFL Depth LoRA (v1 draft β A/B variant) | |
| Alternative to the Union-Pro-2.0 workflow for maximum structural adherence: BFL's | |
| `flux1-depth-dev-lora` on stock flux1-dev, control image fed via latent-concat | |
| (**InstructPixToPixConditioning**), Redux on the conditioning as usual. | |
| **Models**: dev base + Redux files as in the other workflows, plus | |
| `loras/flux1-depth-dev-lora.safetensors` (HF `black-forest-labs/FLUX.1-Depth-dev-lora`, gated). | |
| **Differences vs the ControlNet version** β structure control has NO strength/start/end; | |
| weaken it via the LoRA strength (1.0 = full adherence, ~0.7 looser). No canny stacking. | |
| **FluxGuidance 10** (BFL's depth rec β NOT 3.5). Redux attn_bias 0.5 as usual. | |
| Latent size comes from InstructPixToPixConditioning (= control image size) β feed a | |
| flux-legal resolution composition image (~1MP). | |
| """], pos=(-1300, -80), size=[540, 420]) | |
| unet, clip, vae = flux_loaders(g) | |
| s_img, cv_loader, cv_enc, sm_loader = redux_branch(g, -720, 420) | |
| txt = g.add("CLIPTextEncode", [""], inputs={"clip": (clip, 0)}, pos=(-300, 60), | |
| title="Prompt (optional)") | |
| guid = g.add("FluxGuidance", [10.0], inputs={"conditioning": (txt, 0)}, pos=(140, 60)) | |
| neg = g.add("ConditioningZeroOut", inputs={"conditioning": (guid, 0)}, pos=(140, 170)) | |
| apply_style = g.add("StyleModelApply", [0.5, "attn_bias"], | |
| inputs={"conditioning": (guid, 0), "style_model": (sm_loader, 0), | |
| "clip_vision_output": (cv_enc, 0)}, pos=(140, 300)) | |
| c_img = g.add("LoadImage", ["composition_ref.png", "image"], pos=(-720, 1000), | |
| title="Composition reference (Image B)") | |
| depth = g.add("DepthAnythingV2Preprocessor", ["depth_anything_v2_vitl.pth", 1024], | |
| inputs={"image": (c_img, 0)}, pos=(-300, 1030)) | |
| g.add("PreviewImage", inputs={"images": (depth, 0)}, pos=(-300, 1180), title="Depth map preview") | |
| ip2p = g.add("InstructPixToPixConditioning", | |
| inputs={"positive": (apply_style, 0), "negative": (neg, 0), "vae": (vae, 0), | |
| "pixels": (depth, 0)}, pos=(560, 300)) | |
| dlora = g.add("LoraLoaderModelOnly", ["flux1-depth-dev-lora.safetensors", 1.0], | |
| inputs={"model": (unet, 0)}, pos=(-300, -160), title="BFL Depth LoRA") | |
| msf = g.add("ModelSamplingFlux", [1.15, 0.5, 1024, 1024], inputs={"model": (dlora, 0)}, | |
| pos=(140, -160)) | |
| ks = g.add("KSampler", [0, "randomize", 28, 1.0, "euler", "simple", 1.0], | |
| inputs={"model": (msf, 0), "positive": (ip2p, 0), "negative": (ip2p, 1), | |
| "latent_image": (ip2p, 2)}, pos=(980, 300)) | |
| dec = g.add("VAEDecode", inputs={"samples": (ks, 0), "vae": (vae, 0)}, pos=(1320, 300)) | |
| g.add("SaveImage", ["flux-redux/style-comp-bfl"], inputs={"images": (dec, 0)}, pos=(1320, 420)) | |
| g.group("STYLE REFERENCE β Redux", -740, 340, 940, 700, "#3f789e") | |
| g.group("COMPOSITION β BFL Depth LoRA", -740, 900, 1220, 500, "#8f5b34") | |
| g.dump(f"{OUT}/flux-redux-style-composition-bfl-lora.json") | |
| build_style_composition() | |
| build_fal_dev() | |
| build_prompt() | |
| build_schnell() | |
| build_bfl_lora() | |