Run the templates on FLUX, and name the loaded style
The root templates ran on SDXL base, where every gallery style washed out. A full compiled style is ~480 tokens and SDXL's CLIP attends to ~77 per chunk, so the style was truncated before the sampler saw it. No checkpoint swap fixes that, Juggernaut included: it is an SDXL finetune with the same encoder. Root set now runs FLUX.1 dev (Comfy-Org fp8 all-in-one, since BFL's own file is UNET-only and CheckpointLoaderSimple cannot load it), compiled from the flux target, whose T5 encoder takes the whole prompt. FluxGuidance 3.5, CFG 1.0, and ConditioningZeroOut on the negative input: FLUX is guidance distilled and has no negative channel, exactly like Z-Image. Uses EmptySD3LatentImage because FLUX works in a 16-channel latent space. The two sets load different gallery styles on purpose. How well a style demos is a property of the style and the model together: Z-Image reproduces painterly technique and keeps the Renaissance style, FLUX is strongest at light and tonality and takes a noir one. Also: - Adds the reference-images template the root set was missing, and renumbers Facets to 05, so both sets are 01-05 with matching names. Both sets are now pinned by test against a shared story list. - Model download metadata moves to each node's properties.models, where ComfyUI reads it, so a missing checkpoint offers a download instead of being silently substituted. - The Load node names the style its slug resolves to, on a read-only row under style_ref, via a new /styleref/resolve route. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
70fcf9ef00
commit
cd36fae865
+234
-59
@@ -54,6 +54,7 @@ OUTPUTS = {
|
||||
"StyleRefReferenceImages": [("images", "IMAGE"), ("count", "INT")],
|
||||
"StyleRefLogin": [("status", "STRING")],
|
||||
"CheckpointLoaderSimple": [("MODEL", "MODEL"), ("CLIP", "CLIP"), ("VAE", "VAE")],
|
||||
"FluxGuidance": [("CONDITIONING", "CONDITIONING")],
|
||||
"UNETLoader": [("MODEL", "MODEL")],
|
||||
"CLIPLoader": [("CLIP", "CLIP")],
|
||||
"VAELoader": [("VAE", "VAE")],
|
||||
@@ -76,6 +77,7 @@ INPUTS = {
|
||||
"StyleRefReferenceImages": [("style", "STYLEREF_STYLE")],
|
||||
"CLIPTextEncode": [("clip", "CLIP"), ("text", "STRING")],
|
||||
"ConditioningZeroOut": [("conditioning", "CONDITIONING")],
|
||||
"FluxGuidance": [("conditioning", "CONDITIONING")],
|
||||
"KSampler": [
|
||||
("model", "MODEL"),
|
||||
("positive", "CONDITIONING"),
|
||||
@@ -109,15 +111,30 @@ MULTILINE_WIDGETS = {
|
||||
# Node titles longer than this truncate in both frontends.
|
||||
MAX_TITLE = 28
|
||||
|
||||
# The gallery style every ready-to-run template loads. Picked for how legible
|
||||
# its effect is on the first queue: it compiles to tempera-on-panel technique
|
||||
# and a muted Renaissance palette, so the render is obviously not what the base
|
||||
# checkpoint would have produced alone. Two styles that read well on the
|
||||
# gallery make poor demos here — a naturalistic photography style lands close
|
||||
# to what SDXL does unprompted (the node looks like it did nothing), and a
|
||||
# typography-led graphic style asks the sampler for headline text it renders as
|
||||
# gibberish. This one carries no type at all and constrains no subject.
|
||||
GALLERY_STYLE_REF = "sbdlwwly-66ae1a89efdc" # Renaissance Mythic Classicism
|
||||
# The gallery style each set loads. Deliberately different per model, because
|
||||
# "which style demos well" is a property of the pair, not of the style.
|
||||
#
|
||||
# Z-Image renders a painterly style faithfully — panel texture, contour-led
|
||||
# figures, a muted Renaissance palette — so it gets the painterly one.
|
||||
#
|
||||
# FLUX does not. It has a strong photoreal house look and reverts to it,
|
||||
# and it is specifically weak at reproducing painterly technique; the usual
|
||||
# remedy in the ecosystem is a style LoRA, which is far too much apparatus for
|
||||
# a first-run demo. Rather than ship a demo that quietly under-delivers, the
|
||||
# FLUX set uses a style whose identity is *light and tonality* — hard key,
|
||||
# crushed blacks, monochrome. That is what FLUX is genuinely good at, and
|
||||
# monochrome high-contrast output is unmistakably styled: nobody has to wonder
|
||||
# whether the node did anything.
|
||||
#
|
||||
# Both are subject-agnostic (the consistency grid needs that) and both carry
|
||||
# inspiration images (the reference-images template needs that).
|
||||
#
|
||||
# Two styles that read well on the gallery still demo badly anywhere here: a
|
||||
# naturalistic photography style lands close to what a base model does
|
||||
# unprompted, and a typography-led graphic style asks the sampler for headline
|
||||
# text. Neither of these does either.
|
||||
FLUX_STYLE_REF = "72e1zdae-e2d54a18d090" # Noir Low-Key Portrait
|
||||
ZIMAGE_STYLE_REF = "sbdlwwly-66ae1a89efdc" # Renaissance Mythic Classicism
|
||||
|
||||
# Placeholder ref for the "your own style" templates. Refs are opaque ids now
|
||||
# (no name lookup), so the templates ship an obvious placeholder the user swaps
|
||||
@@ -130,7 +147,8 @@ OWN_STYLE_REF = "<your style id>"
|
||||
# words of their own, so anything stylistic in the render came from StyleRef.
|
||||
GRID_SUBJECTS = [
|
||||
"two friends flipping through crates of vinyl in a record shop",
|
||||
"a lone surfer walking back along the beach at dusk",
|
||||
"A lone surfer strolled back along the beach at dusk, carrying her large "
|
||||
"surfing board.",
|
||||
"a roadside diner at night seen from the parking lot",
|
||||
]
|
||||
|
||||
@@ -140,9 +158,24 @@ DEMO_SUBJECT = GRID_SUBJECTS[0]
|
||||
|
||||
# Frontend model-download metadata: a missing checkpoint becomes a guided
|
||||
# download instead of a red error.
|
||||
MODEL_SDXL = {
|
||||
"name": "sd_xl_base_1.0.safetensors",
|
||||
"url": "https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/sd_xl_base_1.0.safetensors",
|
||||
#
|
||||
# The Comfy-Org all-in-one fp8 repack — UNET + CLIP/T5 + VAE in one file, so
|
||||
# CheckpointLoaderSimple can load it. BFL's own flux1-dev.safetensors is
|
||||
# UNET-only and cannot.
|
||||
#
|
||||
# Why FLUX rather than SDXL, which more people have installed: StyleRef
|
||||
# compiles a long style spec (~480 tokens for a full style), and SDXL's CLIP
|
||||
# attends to ~77 tokens per chunk — the style is mostly truncated before it
|
||||
# reaches the sampler, whatever the checkpoint. FLUX reads the prompt with T5,
|
||||
# which takes the whole thing. This is the first model where the compiled
|
||||
# style and the text encoder actually fit each other.
|
||||
#
|
||||
# `flux1-schnell-fp8.safetensors` (Comfy-Org/flux1-schnell) is a drop-in swap:
|
||||
# Apache-2.0 instead of dev's non-commercial licence, and ~4 steps instead of
|
||||
# 20, at some cost in fidelity.
|
||||
MODEL_FLUX = {
|
||||
"name": "flux1-dev-fp8.safetensors",
|
||||
"url": "https://huggingface.co/Comfy-Org/flux1-dev/resolve/main/flux1-dev-fp8.safetensors",
|
||||
"directory": "checkpoints",
|
||||
}
|
||||
|
||||
@@ -217,6 +250,7 @@ class Graph:
|
||||
widgets: list[Any] | None = None,
|
||||
title: str | None = None,
|
||||
height: int | None = None,
|
||||
models: list[dict[str, str]] | None = None,
|
||||
) -> int:
|
||||
if title is not None and len(title) > MAX_TITLE:
|
||||
raise ValueError(f"title longer than {MAX_TITLE} chars truncates: {title!r}")
|
||||
@@ -249,6 +283,12 @@ class Graph:
|
||||
"properties": {"Node name for S&R": node_type},
|
||||
"widgets_values": widgets,
|
||||
}
|
||||
if models:
|
||||
# ComfyUI reads download metadata from the *node's* properties —
|
||||
# this is what turns a missing file into a download offer instead
|
||||
# of a silently-substituted combo value. The workflow-level
|
||||
# "models" key alone does not drive that prompt.
|
||||
node["properties"]["models"] = models
|
||||
if title:
|
||||
node["title"] = title
|
||||
self.nodes.append(node)
|
||||
@@ -303,28 +343,72 @@ def apply_widgets(subject: str, target: str) -> list[Any]:
|
||||
return [subject, target, "", False, "", True]
|
||||
|
||||
|
||||
def sampler_widgets(cfg: float) -> list[Any]:
|
||||
# Seeds randomize: a fixed seed makes the second queue a silent
|
||||
# cache no-op — deadly in a demo.
|
||||
return [0, "randomize", 25, cfg, "euler", "normal", 1.0]
|
||||
def _flux_checkpoint(graph: Graph) -> int:
|
||||
"""
|
||||
Place the FLUX checkpoint loader with its download metadata attached.
|
||||
|
||||
A helper rather than a bare `place()` call for the same reason
|
||||
`_zimage_loaders` is one: the metadata has to travel with the node. When
|
||||
declaring the download was a separate step, every template placed the
|
||||
loader correctly and none of them offered the download.
|
||||
"""
|
||||
return graph.place(
|
||||
"CheckpointLoaderSimple", 0, [MODEL_FLUX["name"]], models=[MODEL_FLUX]
|
||||
)
|
||||
|
||||
|
||||
def _sdxl_tail(graph: Graph, apply_node: int, checkpoint: int, col: int) -> None:
|
||||
"""Apply → two CLIP encoders → KSampler → VAEDecode → SaveImage."""
|
||||
def flux_sampler_widgets() -> list[Any]:
|
||||
"""
|
||||
FLUX dev defaults: 20 steps, CFG 1.0, euler/simple.
|
||||
|
||||
CFG stays at 1.0 for the same reason it does on Z-Image — FLUX is guidance
|
||||
distilled, and prompt strength is set with FluxGuidance instead. Raising CFG
|
||||
here does not sharpen the style, it just doubles the work and burns the
|
||||
image.
|
||||
"""
|
||||
# Seeds randomize: a fixed seed makes the second queue a silent cache
|
||||
# no-op — deadly in a demo.
|
||||
return [0, "randomize", 20, 1.0, "euler", "simple", 1.0]
|
||||
|
||||
|
||||
def _flux_tail(graph: Graph, apply_node: int, checkpoint: int, col: int) -> None:
|
||||
"""
|
||||
Apply → CLIP encoder → FluxGuidance → KSampler → VAEDecode → SaveImage.
|
||||
|
||||
**No negative encoder**, the same story as `_zimage_tail`: at CFG 1.0 the
|
||||
negative branch is multiplied out entirely, so a second encoder would be
|
||||
dead weight. The sampler's negative input takes a zeroed conditioning.
|
||||
Apply's `negative` output stays wired to its Preview Any so the compiled
|
||||
exclusions remain readable; fold anything you need from them into `subject`
|
||||
as a positive phrase.
|
||||
|
||||
The latent is `EmptySD3LatentImage`, not `EmptyLatentImage`: FLUX works in a
|
||||
16-channel latent space and the plain node emits 4 channels. This graph
|
||||
previously shipped with the 4-channel node — it is the kind of mistake that
|
||||
surfaces as a shape error or noise at sample time, never at build time.
|
||||
"""
|
||||
positive = graph.place("CLIPTextEncode", col, [""], title="Positive (from StyleRef)")
|
||||
negative = graph.place("CLIPTextEncode", col, [""], title="Negative (from StyleRef)")
|
||||
latent = graph.place("EmptyLatentImage", col, [1024, 1024, 1])
|
||||
sampler = graph.place("KSampler", col + 1, sampler_widgets(cfg=7.0))
|
||||
# FLUX's own default. It briefly shipped at 5.0 here, to force a painterly
|
||||
# style that FLUX was never going to reproduce; with a style the model is
|
||||
# actually good at, that compensation stops helping and starts costing the
|
||||
# subject. This style asks for crushed blacks and no fill, and guidance is
|
||||
# a blunt "obey harder" dial — over-driven, the frame goes to pure black and
|
||||
# the subject dissolves into it. Style adherence is the pairing's job, not
|
||||
# this number's.
|
||||
guidance = graph.place("FluxGuidance", col, [3.5], title="Flux guidance")
|
||||
zero_out = graph.place("ConditioningZeroOut", col, [], title="FLUX has no negative")
|
||||
latent = graph.place("EmptySD3LatentImage", col, [1024, 1024, 1])
|
||||
sampler = graph.place("KSampler", col + 1, flux_sampler_widgets())
|
||||
decode = graph.place("VAEDecode", col + 2)
|
||||
save = graph.place("SaveImage", col + 2, ["StyleRef"])
|
||||
|
||||
graph.link(apply_node, 0, positive, 1)
|
||||
graph.link(apply_node, 1, negative, 1)
|
||||
graph.link(checkpoint, 1, positive, 0)
|
||||
graph.link(checkpoint, 1, negative, 0)
|
||||
graph.link(positive, 0, guidance, 0)
|
||||
graph.link(positive, 0, zero_out, 0)
|
||||
graph.link(checkpoint, 0, sampler, 0)
|
||||
graph.link(positive, 0, sampler, 1)
|
||||
graph.link(negative, 0, sampler, 2)
|
||||
graph.link(guidance, 0, sampler, 1)
|
||||
graph.link(zero_out, 0, sampler, 2)
|
||||
graph.link(latent, 0, sampler, 3)
|
||||
graph.link(sampler, 0, decode, 0)
|
||||
graph.link(checkpoint, 2, decode, 1)
|
||||
@@ -373,18 +457,34 @@ def zimage_sampler_widgets() -> list[Any]:
|
||||
CFG stays at 1.0 because Z-Image has no negative channel to activate (see
|
||||
`_zimage_tail`) — raising it only oversaturates and slows the sample down.
|
||||
"""
|
||||
# Seeds randomize: a fixed seed makes the second queue a silent cache
|
||||
# no-op — deadly in a demo.
|
||||
return [0, "randomize", 8, 1.0, "euler", "simple", 1.0]
|
||||
|
||||
|
||||
def _zimage_loaders(graph: Graph) -> tuple[int, int, int]:
|
||||
"""Place the Z-Image UNET + CLIP + VAE loaders. Returns their node ids."""
|
||||
unet = graph.place(
|
||||
"UNETLoader", 0, [MODEL_ZIMAGE_UNET["name"], "default"], title="Z-Image UNET"
|
||||
"UNETLoader",
|
||||
0,
|
||||
[MODEL_ZIMAGE_UNET["name"], "default"],
|
||||
title="Z-Image UNET",
|
||||
models=[MODEL_ZIMAGE_UNET],
|
||||
)
|
||||
clip = graph.place(
|
||||
"CLIPLoader", 0, [MODEL_ZIMAGE_CLIP["name"], "lumina2", "default"], title="Qwen text encoder"
|
||||
"CLIPLoader",
|
||||
0,
|
||||
[MODEL_ZIMAGE_CLIP["name"], "lumina2", "default"],
|
||||
title="Qwen text encoder",
|
||||
models=[MODEL_ZIMAGE_CLIP],
|
||||
)
|
||||
vae = graph.place(
|
||||
"VAELoader",
|
||||
0,
|
||||
[MODEL_ZIMAGE_VAE["name"]],
|
||||
title="Z-Image VAE",
|
||||
models=[MODEL_ZIMAGE_VAE],
|
||||
)
|
||||
vae = graph.place("VAELoader", 0, [MODEL_ZIMAGE_VAE["name"]], title="Z-Image VAE")
|
||||
return unet, clip, vae
|
||||
|
||||
|
||||
@@ -439,6 +539,44 @@ _ZIMAGE_SETUP_NOTE = (
|
||||
)
|
||||
|
||||
|
||||
_FLUX_STYLE_TIP = (
|
||||
"Style not coming through strongly enough?\n"
|
||||
"FLUX has a confident house look and will drift back to it. Two dials, in "
|
||||
"the order worth trying:\n"
|
||||
"1. `Flux guidance` (3.5 here, FLUX's default) is the blunt dial. 4–5 makes "
|
||||
"the style bite harder; past that the subject starts losing to it, and a "
|
||||
"dark style can go to pure black.\n"
|
||||
"2. Narrow `sections` on StyleRef Apply to the parts that define this "
|
||||
"style. For a period or painterly style that is usually "
|
||||
"`artistic_mediums,references,surface_material,colors` — the sections "
|
||||
"naming the medium, the era and the finish. Leaving it empty sends every "
|
||||
"section, and the identity-carrying ones render last, so a long style can "
|
||||
"read as generic.\n"
|
||||
"Which sections matter depends on the style: for a geometric or layout-led "
|
||||
"style keep `shape_language` and `spatial_hierarchy` instead. Queue the "
|
||||
"Facets template to see what a style actually carries."
|
||||
)
|
||||
|
||||
|
||||
_FLUX_SETUP_NOTE = (
|
||||
"FLUX.1 dev (fp8 all-in-one). The checkpoint downloads on first use "
|
||||
"into checkpoints/ — one ~16 GB file containing the UNET, the T5 text "
|
||||
"encoder and the VAE.\n"
|
||||
"Sampler defaults: 20 steps, CFG 1.0, euler/simple. Prompt strength is "
|
||||
"the FluxGuidance node (3.5), not CFG.\n"
|
||||
"FLUX takes no negative prompt. It is guidance distilled and runs at "
|
||||
"CFG 1.0, so there is no negative encoder on this canvas — the sampler's "
|
||||
"negative input gets a zeroed conditioning. StyleRef still compiles the "
|
||||
"negative and previews it; put anything you need from it into `subject` "
|
||||
"on Apply as a positive phrase (\"fully clothed\", \"no text or "
|
||||
"watermark\"). Raising CFG does not bring the negative back.\n"
|
||||
"Style prompts use the `flux` target — FLUX reads prose with T5, so the "
|
||||
"whole style fits instead of being truncated at ~77 tokens the way an "
|
||||
"SDXL CLIP encoder would.\n\n"
|
||||
+ _FLUX_STYLE_TIP
|
||||
)
|
||||
|
||||
|
||||
def workflow_zimage_01_quickstart() -> dict[str, Any]:
|
||||
"""Z-Image quickstart: Load a gallery style → Apply → generate."""
|
||||
g = Graph()
|
||||
@@ -451,7 +589,7 @@ def workflow_zimage_01_quickstart() -> dict[str, Any]:
|
||||
title="Z-Image quickstart",
|
||||
)
|
||||
load = g.place(
|
||||
"StyleRefLoad", 0, load_widgets(GALLERY_STYLE_REF), title="Load — swap this slug"
|
||||
"StyleRefLoad", 0, load_widgets(ZIMAGE_STYLE_REF), title="Load — swap this slug"
|
||||
)
|
||||
unet, clip, vae = _zimage_loaders(g)
|
||||
apply_node = g.place(
|
||||
@@ -475,7 +613,7 @@ def workflow_zimage_02_consistency() -> dict[str, Any]:
|
||||
"many subjects, a coherent set within this model.\n\n" + _ZIMAGE_SETUP_NOTE,
|
||||
title="Z-Image consistency",
|
||||
)
|
||||
load = g.place("StyleRefLoad", 0, load_widgets(GALLERY_STYLE_REF))
|
||||
load = g.place("StyleRefLoad", 0, load_widgets(ZIMAGE_STYLE_REF))
|
||||
unet, clip, vae = _zimage_loaders(g)
|
||||
|
||||
subjects = GRID_SUBJECTS
|
||||
@@ -535,7 +673,7 @@ def workflow_zimage_04_reference_images() -> dict[str, Any]:
|
||||
title="Z-Image + references",
|
||||
)
|
||||
load = g.place(
|
||||
"StyleRefLoad", 0, load_widgets(GALLERY_STYLE_REF), title="Load — a gallery slug"
|
||||
"StyleRefLoad", 0, load_widgets(ZIMAGE_STYLE_REF), title="Load — a gallery slug"
|
||||
)
|
||||
unet, clip, vae = _zimage_loaders(g)
|
||||
|
||||
@@ -560,28 +698,29 @@ def workflow_01_quickstart() -> dict[str, Any]:
|
||||
g.note(
|
||||
0,
|
||||
"Quickstart — no account needed.\n"
|
||||
"1. Set your SDXL checkpoint below (a missing model offers a download).\n"
|
||||
"2. Queue. Seeds randomize, so every queue is a fresh image.\n"
|
||||
"1. Queue — the FLUX checkpoint downloads on first run.\n"
|
||||
"2. Seeds randomize, so every queue is a fresh image.\n"
|
||||
"3. Change `subject` on StyleRef Apply and queue again.\n"
|
||||
"Swap `style_ref` on StyleRef Load for any slug from "
|
||||
"https://styleref.io/gallery — or use the Search styles… button.",
|
||||
"https://styleref.io/gallery — or use the Search styles… button.\n\n"
|
||||
+ _FLUX_SETUP_NOTE,
|
||||
title="Quickstart",
|
||||
)
|
||||
load = g.place(
|
||||
"StyleRefLoad",
|
||||
0,
|
||||
load_widgets(GALLERY_STYLE_REF),
|
||||
load_widgets(FLUX_STYLE_REF),
|
||||
title="Load — swap this slug",
|
||||
)
|
||||
checkpoint = g.place("CheckpointLoaderSimple", 0, [MODEL_SDXL["name"]])
|
||||
checkpoint = _flux_checkpoint(g)
|
||||
apply_node = g.place(
|
||||
"StyleRefApply", 1, apply_widgets(DEMO_SUBJECT, "diffusion")
|
||||
"StyleRefApply", 1, apply_widgets(DEMO_SUBJECT, "flux")
|
||||
)
|
||||
_preview(g, apply_node, 1)
|
||||
g.link(load, 0, apply_node, 0)
|
||||
_sdxl_tail(g, apply_node, checkpoint, col=2)
|
||||
_flux_tail(g, apply_node, checkpoint, col=2)
|
||||
|
||||
return g.to_json(models=[MODEL_SDXL])
|
||||
return g.to_json(models=[MODEL_FLUX])
|
||||
|
||||
|
||||
def workflow_02_consistency() -> dict[str, Any]:
|
||||
@@ -602,19 +741,19 @@ def workflow_02_consistency() -> dict[str, Any]:
|
||||
"Change any subject, or swap the style on StyleRef Load, and queue again.",
|
||||
title="Consistency grid",
|
||||
)
|
||||
load = g.place("StyleRefLoad", 0, load_widgets(GALLERY_STYLE_REF))
|
||||
checkpoint = g.place("CheckpointLoaderSimple", 0, [MODEL_SDXL["name"]])
|
||||
load = g.place("StyleRefLoad", 0, load_widgets(FLUX_STYLE_REF))
|
||||
checkpoint = _flux_checkpoint(g)
|
||||
|
||||
subjects = GRID_SUBJECTS
|
||||
for index, subject in enumerate(subjects):
|
||||
apply_node = g.place(
|
||||
"StyleRefApply", 1, apply_widgets(subject, "diffusion"), title=f"Subject {index + 1}"
|
||||
"StyleRefApply", 1, apply_widgets(subject, "flux"), title=f"Subject {index + 1}"
|
||||
)
|
||||
g.link(load, 0, apply_node, 0)
|
||||
_preview(g, apply_node, 1, suffix=f" {index + 1}")
|
||||
_sdxl_tail(g, apply_node, checkpoint, col=2)
|
||||
_flux_tail(g, apply_node, checkpoint, col=2)
|
||||
|
||||
return g.to_json(models=[MODEL_SDXL])
|
||||
return g.to_json(models=[MODEL_FLUX])
|
||||
|
||||
|
||||
def workflow_03_your_own_style() -> dict[str, Any]:
|
||||
@@ -630,7 +769,7 @@ def workflow_03_your_own_style() -> dict[str, Any]:
|
||||
"set action to `sign in` and queue again.\n"
|
||||
"2. Put your style's id in `style_ref` on StyleRef Load, or pick it\n"
|
||||
" with the Search styles… button.\n"
|
||||
"3. Set your SDXL checkpoint and queue.",
|
||||
"3. Queue.\n\n" + _FLUX_SETUP_NOTE,
|
||||
title="Your own style",
|
||||
)
|
||||
login = g.place("StyleRefLogin", 0, [], title="Login — check status")
|
||||
@@ -641,15 +780,15 @@ def workflow_03_your_own_style() -> dict[str, Any]:
|
||||
load_widgets(OWN_STYLE_REF),
|
||||
title="Load — your own style",
|
||||
)
|
||||
checkpoint = g.place("CheckpointLoaderSimple", 0, [MODEL_SDXL["name"]])
|
||||
checkpoint = _flux_checkpoint(g)
|
||||
apply_node = g.place(
|
||||
"StyleRefApply", 1, apply_widgets(DEMO_SUBJECT, "diffusion")
|
||||
"StyleRefApply", 1, apply_widgets(DEMO_SUBJECT, "flux")
|
||||
)
|
||||
g.link(load, 0, apply_node, 0)
|
||||
_preview(g, apply_node, 1)
|
||||
_sdxl_tail(g, apply_node, checkpoint, col=2)
|
||||
_flux_tail(g, apply_node, checkpoint, col=2)
|
||||
|
||||
return g.to_json(models=[MODEL_SDXL])
|
||||
return g.to_json(models=[MODEL_FLUX])
|
||||
|
||||
|
||||
_FACETS_NOTE = (
|
||||
@@ -668,28 +807,63 @@ _FACETS_NOTE = (
|
||||
)
|
||||
|
||||
|
||||
def workflow_04_facets() -> dict[str, Any]:
|
||||
def workflow_04_reference_images() -> dict[str, Any]:
|
||||
"""FLUX render + the style's inspiration images side by side."""
|
||||
g = Graph()
|
||||
g.note(
|
||||
0,
|
||||
"Style prompt and reference images together.\n"
|
||||
"StyleRef Apply drives the sampler with the style's prompt; StyleRef "
|
||||
"Reference Images pulls the style's inspiration images out as a batch, "
|
||||
"previewed alongside. The prompt says how the style reads; the images "
|
||||
"show how it looks — wire the images into IPAdapter or a "
|
||||
"reference-only ControlNet to combine both.\n"
|
||||
"Use a gallery style that has inspiration images.\n"
|
||||
"\n" + _FLUX_SETUP_NOTE,
|
||||
title="FLUX + references",
|
||||
)
|
||||
load = g.place(
|
||||
"StyleRefLoad", 0, load_widgets(FLUX_STYLE_REF), title="Load — a gallery slug"
|
||||
)
|
||||
checkpoint = _flux_checkpoint(g)
|
||||
|
||||
refs = g.place("StyleRefReferenceImages", 1, [12], title="Reference images")
|
||||
ref_preview = g.place("PreviewImage", 1, [], title="Inspiration images")
|
||||
g.link(load, 0, refs, 0)
|
||||
g.link(refs, 0, ref_preview, 0)
|
||||
|
||||
apply_node = g.place(
|
||||
"StyleRefApply", 1, apply_widgets(DEMO_SUBJECT, "flux")
|
||||
)
|
||||
g.link(load, 0, apply_node, 0)
|
||||
_preview(g, apply_node, 1)
|
||||
_flux_tail(g, apply_node, checkpoint, col=2)
|
||||
|
||||
return g.to_json(models=[MODEL_FLUX])
|
||||
|
||||
|
||||
def workflow_05_facets() -> dict[str, Any]:
|
||||
"""Every section of a style, exposed and readable, next to a normal render."""
|
||||
g = Graph()
|
||||
g.note(0, _FACETS_NOTE, title="Facets")
|
||||
load = g.place(
|
||||
"StyleRefLoad",
|
||||
0,
|
||||
load_widgets(GALLERY_STYLE_REF),
|
||||
load_widgets(FLUX_STYLE_REF),
|
||||
title="Load — swap this slug",
|
||||
)
|
||||
checkpoint = g.place("CheckpointLoaderSimple", 0, [MODEL_SDXL["name"]])
|
||||
checkpoint = _flux_checkpoint(g)
|
||||
|
||||
_facet_board(g, load, col=1)
|
||||
|
||||
apply_node = g.place(
|
||||
"StyleRefApply", 3, apply_widgets(DEMO_SUBJECT, "diffusion")
|
||||
"StyleRefApply", 3, apply_widgets(DEMO_SUBJECT, "flux")
|
||||
)
|
||||
g.link(load, 0, apply_node, 0)
|
||||
_preview(g, apply_node, 3)
|
||||
_sdxl_tail(g, apply_node, checkpoint, col=4)
|
||||
_flux_tail(g, apply_node, checkpoint, col=4)
|
||||
|
||||
return g.to_json(models=[MODEL_SDXL])
|
||||
return g.to_json(models=[MODEL_FLUX])
|
||||
|
||||
|
||||
def workflow_zimage_05_facets() -> dict[str, Any]:
|
||||
@@ -699,7 +873,7 @@ def workflow_zimage_05_facets() -> dict[str, Any]:
|
||||
load = g.place(
|
||||
"StyleRefLoad",
|
||||
0,
|
||||
load_widgets(GALLERY_STYLE_REF),
|
||||
load_widgets(ZIMAGE_STYLE_REF),
|
||||
title="Load — swap this slug",
|
||||
)
|
||||
unet, clip, vae = _zimage_loaders(g)
|
||||
@@ -716,13 +890,14 @@ def workflow_zimage_05_facets() -> dict[str, Any]:
|
||||
return g.to_json(models=MODELS_ZIMAGE)
|
||||
|
||||
|
||||
# Keyed by path relative to workflows/. The SDXL set lives at the root; the
|
||||
# Keyed by path relative to workflows/. The FLUX set lives at the root; the
|
||||
# Z-Image set lives in workflows/z-image/.
|
||||
WORKFLOWS = {
|
||||
"01-quickstart.json": workflow_01_quickstart,
|
||||
"02-consistency-grid.json": workflow_02_consistency,
|
||||
"03-your-own-style.json": workflow_03_your_own_style,
|
||||
"04-facets.json": workflow_04_facets,
|
||||
"04-reference-images.json": workflow_04_reference_images,
|
||||
"05-facets.json": workflow_05_facets,
|
||||
"z-image/01-quickstart.json": workflow_zimage_01_quickstart,
|
||||
"z-image/02-consistency-grid.json": workflow_zimage_02_consistency,
|
||||
"z-image/03-your-own-style.json": workflow_zimage_03_your_own_style,
|
||||
|
||||
Reference in New Issue
Block a user