From f8a7c2718f38354d4ff34c856c6e57cd48e924b1 Mon Sep 17 00:00:00 2001 From: chrmc40 Date: Sat, 27 Jun 2026 16:45:33 -0700 Subject: [PATCH] Krea 2 Realism: restore the author's ClownsharKSampler_Beta recipe (t2i/i2i templates + i2i modal); declare RES4LYF as a required prerequisite (install via ComfyUI Manager) rather than substituting a built-in sampler. --- core/install_sections.py | 2 +- core/node_install_api.py | 19 ++++++----- data/templates/krea2-turbo-realism-i2i.json | 9 +++--- data/templates/krea2-turbo-realism-t2i.json | 9 +++--- js/lib/i2i-background.js | 35 +++++++++++++-------- js/lib/svelte/promptchain-viewer.js | 6 ++-- svelte-src/components/I2IModal.svelte | 7 +++-- 7 files changed, 53 insertions(+), 34 deletions(-) diff --git a/core/install_sections.py b/core/install_sections.py index 1632d03..8e77549 100644 --- a/core/install_sections.py +++ b/core/install_sections.py @@ -61,7 +61,7 @@ SECTIONS: list[dict] = [ "desc": "Clean 2× decoder + conditioning rebalance for the Krea 2 High-Detail templates", "members": [_np("Krea2HighDetail")]}, {"id": "krea2_realism", "label": "Krea 2 Realism", "size": "~5.7 GB", - "desc": "Abliterated encoder + realism & filter-bypass LoRAs for the Krea 2 Turbo Realism mode (uncensored)", + "desc": "Abliterated encoder + realism & filter-bypass LoRAs for Krea 2 Turbo Realism (uncensored). t2i/i2i also need the RES4LYF node pack — install it via ComfyUI Manager.", "members": [_np("Krea2Realism")]}, {"id": "controlnet", "label": "ControlNet", "size": "~5 GB SDXL · up to ~22 GB all", "desc": "Depth / pose / canny / edge guidance (SDXL · Flux · Z-Image)", diff --git a/core/node_install_api.py b/core/node_install_api.py index b08f098..58c3ad1 100644 --- a/core/node_install_api.py +++ b/core/node_install_api.py @@ -163,14 +163,17 @@ NODE_PACKS: dict[str, dict] = { }, "Krea2Realism": { "label": "Krea 2 Realism", - # Models-only (no custom node). The Realism mode — the krea2_turbo Realism - # templates + the editor inpaint/i2i/upscale toggle — swaps in the - # abliterated Qwen3-VL encoder (uncensored at encode), a realism LoRA, and - # the projector-scale "filter bypass" LoRA. RES4LYF's ClownsharKSampler is - # deliberately NOT bundled (its scipy/kornia deps can't be pip-installed at - # runtime); the recipe uses the built-in res_multistep sampler instead. The - # 268-byte projector LoRA has no upstream URL — it ships in this repo - # (data/loras/) and is copied straight into models/loras/ on install. + # Models-only pack. The Realism mode (krea2_turbo Realism templates + the + # editor i2i toggle) swaps in the abliterated Qwen3-VL encoder (uncensored + # at encode), a realism LoRA, and the projector-scale "filter bypass" LoRA. + # The t2i/i2i recipe re-renders full-frame with the author's + # ClownsharKSampler_Beta — that's RES4LYF, a REQUIRED PREREQUISITE the user + # installs via ComfyUI Manager. We don't bundle RES4LYF: its license forbids + # commercial use (incompatible with PromptChain's AGPL), and the user + # obtaining it directly from the author avoids any redistribution. The + # inpaint/upscale realism paths use their built-in sampler and need only + # these model files. The 268-byte projector LoRA has no upstream URL — it + # ships in this repo (data/loras/) and is copied into models/loras/. "proof_nodes": [], "models": [ {"url": "https://huggingface.co/ahmed22xa/Huihui-Qwen3-VL-4B-Instruct-abliterated-comfy/resolve/main/Huihui-Qwen3-VL-4B-Instruct-abliterated-fp8_scaled.safetensors", diff --git a/data/templates/krea2-turbo-realism-i2i.json b/data/templates/krea2-turbo-realism-i2i.json index 9ea7e04..b8b7357 100644 --- a/data/templates/krea2-turbo-realism-i2i.json +++ b/data/templates/krea2-turbo-realism-i2i.json @@ -29,12 +29,13 @@ } }, { - "type": "KSampler", + "type": "ClownsharKSampler_Beta", "offset": [1700, 160], - "size": [330, 474], - "widgets_values": [1033759726676101, "randomize", 8, 1, "res_multistep", "beta", 0.6], + "size": [373.90625, 756], + "widgets_values": [0.5, "exponential/ddim", "beta57", 8, -1, 0.6, 1, 1033759726676101, "randomize", "standard", false], "properties": { - "Node name for S&R": "KSampler" + "Node name for S&R": "ClownsharKSampler_Beta", + "aux_id": "tashiscool/RES4LYF" } }, { diff --git a/data/templates/krea2-turbo-realism-t2i.json b/data/templates/krea2-turbo-realism-t2i.json index 879f1c1..d4b1d8a 100644 --- a/data/templates/krea2-turbo-realism-t2i.json +++ b/data/templates/krea2-turbo-realism-t2i.json @@ -29,12 +29,13 @@ } }, { - "type": "KSampler", + "type": "ClownsharKSampler_Beta", "offset": [1700, 160], - "size": [330, 474], - "widgets_values": [1033759726676101, "randomize", 8, 1, "res_multistep", "beta", 1], + "size": [373.90625, 756], + "widgets_values": [0.5, "exponential/ddim", "beta57", 8, -1, 1, 1, 1033759726676101, "randomize", "standard", false], "properties": { - "Node name for S&R": "KSampler" + "Node name for S&R": "ClownsharKSampler_Beta", + "aux_id": "tashiscool/RES4LYF" } }, { diff --git a/js/lib/i2i-background.js b/js/lib/i2i-background.js index 03549cb..2346a63 100644 --- a/js/lib/i2i-background.js +++ b/js/lib/i2i-background.js @@ -125,7 +125,7 @@ function makeAdder(graph) { // Shared clean tail: encode the loaded image, partially denoise it, decode, // preview. `modelRef`/`clipRef`/`vaeRef` are [id, slot] links into `graph`. -function attachI2ITail(graph, add, { inputRef, modelRef, clipRef, vaeRef, options, guidance, steps, cfg, sampler, scheduler }) { +function attachI2ITail(graph, add, { inputRef, modelRef, clipRef, vaeRef, options, guidance, steps, cfg, sampler, scheduler, clown }) { const loadId = add("LoadImage", { image: inputRef }); const encId = add("VAEEncode", { pixels: [loadId, 0], vae: vaeRef }); const pc = PC_NODE(); pc.prompt = options.prompt || ""; @@ -135,12 +135,22 @@ function attachI2ITail(graph, add, { inputRef, modelRef, clipRef, vaeRef, option if (typeof guidance === "number") { posRef = [add("FluxGuidance", { conditioning: posRef, guidance }), 0]; } - const ksId = add("KSampler", { - model: modelRef, positive: posRef, negative: negRef, latent_image: [encId, 0], - seed: Math.floor(Math.random() * 0xffffffffff), - steps, cfg, sampler_name: sampler, scheduler, - denoise: typeof options.denoise === "number" ? options.denoise : 0.55, - }); + const denoise = typeof options.denoise === "number" ? options.denoise : 0.55; + // Realism full-frame i2i uses the author's ClownsharKSampler_Beta (RES4LYF) — + // the same node the realism t2i/i2i templates use. Full-frame (not a composited + // patch), so a sampler NODE is allowed here. cfg pinned 1 like Turbo. + const ksId = clown + ? add("ClownsharKSampler_Beta", { + model: modelRef, positive: posRef, negative: negRef, latent_image: [encId, 0], + eta: 0.5, sampler_name: "exponential/ddim", scheduler: "beta57", + steps: steps ?? 8, steps_to_run: -1, denoise, cfg: cfg ?? 1.0, + seed: Math.floor(Math.random() * 0xffffffffff), sampler_mode: "standard", bongmath: false, + }) + : add("KSampler", { + model: modelRef, positive: posRef, negative: negRef, latent_image: [encId, 0], + seed: Math.floor(Math.random() * 0xffffffffff), + steps, cfg, sampler_name: sampler, scheduler, denoise, + }); const decId = add("VAEDecode", { samples: [ksId, 0], vae: vaeRef }); const previewId = add("PreviewImage", { images: [decId, 0] }); return { ksId, previewId }; @@ -200,8 +210,8 @@ export function buildI2IEngineKrea2(data, options) { const filename = options.engineModel?.filename; if (!filename) throw new Error("no engine model picked"); // Realism mode (krea2_turbo): abliterated Qwen3-VL encoder + wan_2.1 VAE + - // projector/realism LoRAs + res_multistep/beta sampling. i2i is full-frame (a - // whole new layer, not a composited patch), so the wan VAE is safe here. + // projector/realism LoRAs + the author's ClownsharKSampler_Beta tail. i2i is + // full-frame (a whole new layer, not a composited patch), so wan VAE is safe. const realism = !!options.realism; const clipOpts = probeCombo("CLIPLoader", "clip_name"); const loraOpts = probeCombo("LoraLoaderModelOnly", "lora_name"); @@ -243,12 +253,11 @@ export function buildI2IEngineKrea2(data, options) { } const { ksId } = attachI2ITail(graph, add, { inputRef: data.input_ref, modelRef, clipRef: [clipId, 0], vaeRef: [vaeId, 0], options, + clown: realism, steps: numOr(options.steps, raw ? 40 : 8), cfg: numOr(options.cfg, raw ? 3.5 : 1.0), - // Realism uses res_multistep/beta (a portable built-in close to the t2i - // template's recipe); RES4LYF's ClownsharKSampler isn't bundleable. - sampler: options.sampler || (realism ? "res_multistep" : raw ? "er_sde" : "euler"), - scheduler: options.scheduler || (realism ? "beta" : raw ? "beta" : "simple"), + sampler: options.sampler || (raw ? "er_sde" : "euler"), + scheduler: options.scheduler || (raw ? "beta" : "simple"), }); return { graph, detailId: ksId }; } diff --git a/js/lib/svelte/promptchain-viewer.js b/js/lib/svelte/promptchain-viewer.js index d0d65b4..fccd124 100644 --- a/js/lib/svelte/promptchain-viewer.js +++ b/js/lib/svelte/promptchain-viewer.js @@ -4441,12 +4441,14 @@ function I2IModal($$anchor, $$props) { let engineKind = user_derived(() => get(engineEntry) ? get(engineEntry).architecture === "flux" ? "flux1" : get(engineEntry).architecture === "krea2" ? "krea2" : "sdxl" : "source"); let realism = state(false); const realismAssetsInstalled = (() => { - var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j; + var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k; try { const LG = window.LiteGraph; const clip = ((_e = (_d = (_c = (_b = (_a = LG == null ? void 0 : LG.createNode) == null ? void 0 : _a.call(LG, "CLIPLoader")) == null ? void 0 : _b.widgets) == null ? void 0 : _c.find((w) => w.name === "clip_name")) == null ? void 0 : _d.options) == null ? void 0 : _e.values) || []; const loras = ((_j = (_i = (_h = (_g = (_f = LG == null ? void 0 : LG.createNode) == null ? void 0 : _f.call(LG, "LoraLoaderModelOnly")) == null ? void 0 : _g.widgets) == null ? void 0 : _h.find((w) => w.name === "lora_name")) == null ? void 0 : _i.options) == null ? void 0 : _j.values) || []; - return clip.some((o) => /qwen3.?vl.*4b.*abliterated/i.test(o)) && loras.some((o) => /krea2-realism/i.test(o)) && loras.some((o) => /krea2_turbo_projector_scale/i.test(o)); + return clip.some((o) => /qwen3.?vl.*4b.*abliterated/i.test(o)) && loras.some((o) => /krea2-realism/i.test(o)) && loras.some((o) => /krea2_turbo_projector_scale/i.test(o)) && // i2i realism re-renders full-frame with the author's ClownsharKSampler_Beta + // (RES4LYF) — gate on the node being registered too. + !!((_k = LG == null ? void 0 : LG.registered_node_types) == null ? void 0 : _k["ClownsharKSampler_Beta"]); } catch { return false; } diff --git a/svelte-src/components/I2IModal.svelte b/svelte-src/components/I2IModal.svelte index 95a8ac2..4a2bcca 100644 --- a/svelte-src/components/I2IModal.svelte +++ b/svelte-src/components/I2IModal.svelte @@ -52,7 +52,7 @@ ? (engineEntry.architecture === "flux" ? "flux1" : engineEntry.architecture === "krea2" ? "krea2" : "sdxl") : "source"); // Realism mode: a krea2_turbo-only recipe (abliterated encoder + wan_2.1 VAE + - // realism/bypass LoRAs + res_multistep sampling — full-frame i2i). + // realism/bypass LoRAs + ClownsharKSampler_Beta — full-frame i2i). let realism = $state(false); // Realism assets present? (abliterated encoder + realism + projector LoRAs). // Computed once — installed lists don't change without a restart. Hides the @@ -64,7 +64,10 @@ const loras = LG?.createNode?.("LoraLoaderModelOnly")?.widgets?.find((w) => w.name === "lora_name")?.options?.values || []; return clip.some((o) => /qwen3.?vl.*4b.*abliterated/i.test(o)) && loras.some((o) => /krea2-realism/i.test(o)) - && loras.some((o) => /krea2_turbo_projector_scale/i.test(o)); + && loras.some((o) => /krea2_turbo_projector_scale/i.test(o)) + // i2i realism re-renders full-frame with the author's ClownsharKSampler_Beta + // (RES4LYF) — gate on the node being registered too. + && !!LG?.registered_node_types?.["ClownsharKSampler_Beta"]; } catch { return false; } })(); let realismAvailable = $derived(engineKind === "krea2" && /turbo/i.test(engineEntry?.filename || "") && realismAssetsInstalled);