From 97e12a83f4960e208530371f33130efc2c3cf653 Mon Sep 17 00:00:00 2001 From: Gin3601 Date: Thu, 21 May 2026 14:12:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=B1=80=E9=83=A8=E9=87=8D?= =?UTF-8?q?=E7=BB=98=E7=9A=84BUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- image/nodes.py | 2 +- sampling/nodes.py | 46 +- tests/test_loader_prompt_refactor.py | 7 +- tests/test_repair_sampler.py | 48 + tests/test_sampling_frontend_compat.py | 26 + web/js/lls_ksampler_compat.js | 97 ++ 测试工作流.json | 1531 ++++++++++++++++++++++++ 7 files changed, 1751 insertions(+), 6 deletions(-) create mode 100644 tests/test_sampling_frontend_compat.py create mode 100644 web/js/lls_ksampler_compat.js create mode 100644 测试工作流.json diff --git a/image/nodes.py b/image/nodes.py index 272d40b..79b7bf8 100644 --- a/image/nodes.py +++ b/image/nodes.py @@ -145,7 +145,7 @@ class LLSSimpleVAEEncode: 编码本身复用 ComfyUI 原生 vae.encode,只在外层补尺寸处理与元信息。 """ - CATEGORY = "LLS-node" + CATEGORY = "LLS/Image" FUNCTION = "encode" RETURN_TYPES = ("LATENT", "INT", "INT", "STRING") RETURN_NAMES = ("latent", "width", "height", "latent_info") diff --git a/sampling/nodes.py b/sampling/nodes.py index cbcb933..f9ad9f8 100644 --- a/sampling/nodes.py +++ b/sampling/nodes.py @@ -116,6 +116,42 @@ def _normalize_flux_guidance(value, fallback: float | None) -> float | None: return normalized +def _normalize_ksampler_compat_values( + denoise_mode, + adapter_mode, + flux_guidance, + model_family, +): + normalized_denoise_mode = str(denoise_mode or "").strip() + normalized_flux_guidance = str(flux_guidance or "").strip() + normalized_adapter_mode = str(adapter_mode or "").strip() + normalized_model_family = str(model_family or "").strip() + + # Repair the short-lived widget-order regression so old and newly re-saved + # workflows can both be interpreted correctly. + if ( + normalized_denoise_mode not in _DENOISE_MODE_CHOICES + and normalized_flux_guidance in _DENOISE_MODE_CHOICES + and normalized_model_family.lower() in _ADAPTER_MODE_CHOICES + ): + shifted_flux_guidance = denoise_mode + denoise_mode = normalized_flux_guidance or "manual" + adapter_mode = normalized_model_family.lower() or "auto" + flux_guidance = shifted_flux_guidance + model_family = "Auto" if normalized_adapter_mode.lower() == "auto" else normalized_adapter_mode + return denoise_mode, adapter_mode, flux_guidance, model_family + + if normalized_adapter_mode.lower() in _ADAPTER_MODE_CHOICES: + adapter_mode = normalized_adapter_mode.lower() + elif normalized_adapter_mode == "Auto": + adapter_mode = "auto" + + if normalized_model_family == "auto": + model_family = "Auto" + + return denoise_mode, adapter_mode, flux_guidance, model_family + + def _common_ksampler( model, seed: int, @@ -240,13 +276,13 @@ class LLSSimpleKSampler: "sampler_name": (_get_samplers(), {"default": "euler_ancestral"}), "scheduler": (_get_schedulers(), {"default": "karras"}), "denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}), + "denoise_mode": (_DENOISE_MODE_CHOICES, {"default": "manual"}), + "adapter_mode": (_ADAPTER_MODE_CHOICES, {"default": "auto"}), "flux_guidance": ( _PRIMITIVE_NUMBER_INPUT, {"default": 3.5, "widgetType": "FLOAT", "min": 0.0, "max": 100.0, "step": 0.1, "round": 0.1}, ), "model_family": (MODEL_FAMILY_CHOICES, {"default": "Auto"}), - "denoise_mode": (_DENOISE_MODE_CHOICES, {"default": "manual"}), - "adapter_mode": (_ADAPTER_MODE_CHOICES, {"default": "auto"}), }, "optional": { "repair_info": ("LLS_REPAIR_INFO",), @@ -302,6 +338,12 @@ class LLSSimpleKSampler: repair_meta = normalize_repair_info(repair_info) if repair_info is not None else None model_meta = normalize_model_info(model_info) + denoise_mode, adapter_mode, flux_guidance, model_family = _normalize_ksampler_compat_values( + denoise_mode, + adapter_mode, + flux_guidance, + model_family, + ) family = resolve_model_family(model_family, model=model) if repair_meta is not None and repair_meta.get("model_family") not in {"UNKNOWN", "", None}: diff --git a/tests/test_loader_prompt_refactor.py b/tests/test_loader_prompt_refactor.py index f968a7f..119fd58 100644 --- a/tests/test_loader_prompt_refactor.py +++ b/tests/test_loader_prompt_refactor.py @@ -593,7 +593,7 @@ class TestLoaderPromptRefactor(unittest.TestCase): self.assertEqual(sample_data["sampler_name"], "euler") self.assertEqual(latent["samples"].shape, (1, 4, 64, 64)) - def test_ksampler_schema_appends_repair_widgets_after_legacy_widgets(self): + def test_ksampler_schema_keeps_legacy_widget_order_for_workflow_compatibility(self): plugin = load_plugin_package() node_cls = plugin.NODE_CLASS_MAPPINGS["LLSSimpleKSampler"] required = node_cls.INPUT_TYPES()["required"] @@ -612,10 +612,10 @@ class TestLoaderPromptRefactor(unittest.TestCase): "sampler_name", "scheduler", "denoise", - "flux_guidance", - "model_family", "denoise_mode", "adapter_mode", + "flux_guidance", + "model_family", ), ) self.assertEqual(required["model_family"][1]["default"], "Auto") @@ -700,6 +700,7 @@ class TestLoaderPromptRefactor(unittest.TestCase): required = node_cls.INPUT_TYPES()["required"] optional = node_cls.INPUT_TYPES()["optional"] + self.assertEqual(node_cls.CATEGORY, "LLS/Image") self.assertEqual(node_cls.RETURN_TYPES, ("LATENT", "INT", "INT", "STRING")) self.assertEqual(required["image"][0], "IMAGE") self.assertEqual(required["vae"][0], "VAE") diff --git a/tests/test_repair_sampler.py b/tests/test_repair_sampler.py index 8d7b772..a066705 100644 --- a/tests/test_repair_sampler.py +++ b/tests/test_repair_sampler.py @@ -112,6 +112,54 @@ class TestRepairSampler(unittest.TestCase): self.assertEqual(payload["repair_scope"], "region") self.assertEqual(payload["repair_kernel"], "latent_mask") + def test_sampler_recovers_shifted_values_from_broken_widget_order(self): + load_plugin_package() + from lls_node_test_repair.sampling import nodes as sampling_nodes + + node = sampling_nodes.LLSSimpleKSampler() + latent = {"samples": FakeLatentTensor((1, 4, 64, 64)), "source": "repair_prepare_region"} + with mock.patch.object(sampling_nodes, "comfy_sample", object()), mock.patch.object( + sampling_nodes, + "comfy_samplers", + types.SimpleNamespace(KSampler=types.SimpleNamespace(SAMPLERS=["euler"], SCHEDULERS=["karras"])), + ), mock.patch.object( + sampling_nodes, + "_common_ksampler", + return_value={"samples": "done"}, + ) as common: + _result_latent, sample_info = node.sample( + model=types.SimpleNamespace(_lls_family="FLUX_DEV"), + positive="positive", + negative="negative", + latent_image=latent, + quality_preset="Manual", + seed=7, + steps=20, + cfg=7.0, + sampler_name="euler", + scheduler="karras", + denoise=0.33, + denoise_mode=4.2, + adapter_mode="Auto", + flux_guidance="auto_from_repair", + model_family="auto", + repair_info={ + "repair_scope": "region", + "repair_kernel": "latent_mask", + "recommended_denoise": 0.61, + "model_family": "FLUX_DEV", + "model_role": "normal", + }, + guidance_stack=None, + model_info=None, + ) + + self.assertEqual(common.call_args.kwargs["denoise"], 0.61) + payload = json.loads(sample_info) + self.assertEqual(payload["family"], "FLUX_DEV") + self.assertEqual(payload["guidance"], 4.2) + self.assertTrue(payload["repair_mode"]) + def test_sampler_rejects_unsupported_qwen_adapter(self): load_plugin_package() from lls_node_test_repair.sampling import nodes as sampling_nodes diff --git a/tests/test_sampling_frontend_compat.py b/tests/test_sampling_frontend_compat.py new file mode 100644 index 0000000..2b38e42 --- /dev/null +++ b/tests/test_sampling_frontend_compat.py @@ -0,0 +1,26 @@ +import unittest + +try: + from .test_mask_draw_helpers import ROOT +except ImportError: + from test_mask_draw_helpers import ROOT + + +class TestSamplingFrontendCompat(unittest.TestCase): + def test_ksampler_compat_asset_exists(self): + asset = ROOT / "web" / "js" / "lls_ksampler_compat.js" + + self.assertTrue(asset.exists(), msg=f"Missing frontend asset: {asset}") + + def test_ksampler_compat_asset_targets_sampler_node(self): + asset = (ROOT / "web" / "js" / "lls_ksampler_compat.js").read_text(encoding="utf-8") + + self.assertIn("app.registerExtension", asset) + self.assertIn("LLSSimpleKSampler", asset) + self.assertIn("LLS Simple KSampler", asset) + self.assertIn("widgets_values", asset) + self.assertIn("configure", asset) + + +if __name__ == "__main__": + unittest.main() diff --git a/web/js/lls_ksampler_compat.js b/web/js/lls_ksampler_compat.js new file mode 100644 index 0000000..98dbd1a --- /dev/null +++ b/web/js/lls_ksampler_compat.js @@ -0,0 +1,97 @@ +import { app } from "../../../scripts/app.js"; + +const EXTENSION_NAME = "lls.ksampler.compat"; +const TARGET_NODE_CLASS = "LLSSimpleKSampler"; +const TARGET_NODE_DISPLAY_NAME = "LLS Simple KSampler"; +const DENOISE_MODE_INDEX = 11; +const ADAPTER_MODE_INDEX = 12; +const FLUX_GUIDANCE_INDEX = 13; +const MODEL_FAMILY_INDEX = 14; +const DENOISE_MODES = new Set(["manual", "auto_from_repair"]); +const ADAPTER_MODES = new Set(["auto", "sd_classic", "flux", "sd3", "qwen", "zimage"]); + +function normalizeText(value) { + if (typeof value === "string") { + return value.trim(); + } + if (value === null || value === undefined) { + return ""; + } + return String(value).trim(); +} + +function isNumericLike(value) { + if (typeof value === "number") { + return Number.isFinite(value); + } + const text = normalizeText(value); + if (!text) { + return false; + } + return Number.isFinite(Number(text)); +} + +function looksLikeShiftedWidgetOrder(values) { + if (!Array.isArray(values) || values.length <= MODEL_FAMILY_INDEX) { + return false; + } + + const denoiseMode = normalizeText(values[DENOISE_MODE_INDEX]); + const adapterMode = normalizeText(values[ADAPTER_MODE_INDEX]).toLowerCase(); + const fluxGuidance = normalizeText(values[FLUX_GUIDANCE_INDEX]); + const modelFamily = normalizeText(values[MODEL_FAMILY_INDEX]).toLowerCase(); + + return ( + !DENOISE_MODES.has(denoiseMode) && + DENOISE_MODES.has(fluxGuidance) && + ADAPTER_MODES.has(modelFamily) && + !ADAPTER_MODES.has(adapterMode) && + (isNumericLike(values[DENOISE_MODE_INDEX]) || denoiseMode === "") + ); +} + +function migrateWidgetValues(values) { + if (!Array.isArray(values) || values.length <= MODEL_FAMILY_INDEX) { + return values; + } + + const migrated = values.slice(); + if (looksLikeShiftedWidgetOrder(migrated)) { + const shiftedDenoiseMode = migrated[DENOISE_MODE_INDEX]; + const shiftedAdapterMode = migrated[ADAPTER_MODE_INDEX]; + const shiftedFluxGuidance = migrated[FLUX_GUIDANCE_INDEX]; + const shiftedModelFamily = migrated[MODEL_FAMILY_INDEX]; + + migrated[DENOISE_MODE_INDEX] = normalizeText(shiftedFluxGuidance) || "manual"; + migrated[ADAPTER_MODE_INDEX] = normalizeText(shiftedModelFamily).toLowerCase() || "auto"; + migrated[FLUX_GUIDANCE_INDEX] = shiftedDenoiseMode; + migrated[MODEL_FAMILY_INDEX] = + normalizeText(shiftedAdapterMode).toLowerCase() === "auto" ? "Auto" : shiftedAdapterMode; + return migrated; + } + + if (normalizeText(migrated[ADAPTER_MODE_INDEX]) === "Auto") { + migrated[ADAPTER_MODE_INDEX] = "auto"; + } + if (normalizeText(migrated[MODEL_FAMILY_INDEX]) === "auto") { + migrated[MODEL_FAMILY_INDEX] = "Auto"; + } + return migrated; +} + +app.registerExtension({ + name: EXTENSION_NAME, + async beforeRegisterNodeDef(nodeType, nodeData) { + if (nodeData.name !== TARGET_NODE_CLASS && nodeData.display_name !== TARGET_NODE_DISPLAY_NAME) { + return; + } + + const previousConfigure = nodeType.prototype.configure; + nodeType.prototype.configure = function configureLLSKSamplerCompat(info) { + if (info && Array.isArray(info.widgets_values)) { + info.widgets_values = migrateWidgetValues(info.widgets_values); + } + return previousConfigure?.apply(this, arguments); + }; + }, +}); diff --git a/测试工作流.json b/测试工作流.json new file mode 100644 index 0000000..1edd363 --- /dev/null +++ b/测试工作流.json @@ -0,0 +1,1531 @@ +{ + "id": "196d3f49-c541-4fcd-b800-ad54aecdf346", + "revision": 0, + "last_node_id": 50, + "last_link_id": 62, + "nodes": [ + { + "id": 28, + "type": "VAEDecode", + "pos": [ + 1580.7609512068045, + -386.4355276097807 + ], + "size": [ + 140, + 46 + ], + "flags": {}, + "order": 16, + "mode": 4, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 30 + }, + { + "name": "vae", + "type": "VAE", + "link": 31 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 32 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.21.0", + "Node name for S&R": "VAEDecode" + }, + "widgets_values": [] + }, + { + "id": 29, + "type": "LLSUpscaleSwitcher", + "pos": [ + 1564.4477163435238, + -280.275527609781 + ], + "size": [ + 270, + 198 + ], + "flags": {}, + "order": 18, + "mode": 4, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 32 + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 33 + ] + }, + { + "name": "upscale_info", + "type": "STRING", + "links": null + } + ], + "properties": { + "aux_id": "Gin3601/LLS-node", + "ver": "3e97537f543c74db0e91a840d698105c5f269931", + "Node name for S&R": "LLSUpscaleSwitcher" + }, + "widgets_values": [ + "interpolation", + 2, + "bilinear", + "(no upscale models found)", + 512, + 32 + ] + }, + { + "id": 10, + "type": "PreviewImage", + "pos": [ + 1879.409164205428, + -405.28809919995183 + ], + "size": [ + 258.545487837358, + 331.33331298828125 + ], + "flags": {}, + "order": 20, + "mode": 4, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 33 + } + ], + "outputs": [], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.21.0", + "Node name for S&R": "PreviewImage" + }, + "widgets_values": [] + }, + { + "id": 21, + "type": "LLSSimpleCheckpointLoader", + "pos": [ + 433.0723885292493, + -357.18940539520315 + ], + "size": [ + 303.159765625, + 286 + ], + "flags": {}, + "order": 0, + "mode": 4, + "inputs": [], + "outputs": [ + { + "name": "model", + "type": "MODEL", + "links": [ + 25, + 36 + ] + }, + { + "name": "clip", + "type": "CLIP", + "links": [ + 40 + ] + }, + { + "name": "vae", + "type": "VAE", + "links": [ + 31, + 37 + ] + }, + { + "name": "text_encoder", + "type": "CLIP", + "links": [ + 41 + ] + } + ], + "properties": { + "aux_id": "Gin3601/LLS-node", + "ver": "3e97537f543c74db0e91a840d698105c5f269931", + "Node name for S&R": "LLSSimpleCheckpointLoader" + }, + "widgets_values": [ + "flux1-schnell-fp8.safetensors", + "Auto", + "simple", + "auto", + "auto", + "(auto)", + "(auto)", + "(auto)" + ] + }, + { + "id": 31, + "type": "LLSSimpleEmptyLatent", + "pos": [ + 810.3695674177421, + -688.5215513219393 + ], + "size": [ + 270, + 238 + ], + "flags": {}, + "order": 8, + "mode": 4, + "inputs": [ + { + "name": "model", + "shape": 7, + "type": "MODEL", + "link": 36 + }, + { + "name": "image", + "shape": 7, + "type": "IMAGE", + "link": 39 + }, + { + "name": "vae", + "shape": 7, + "type": "VAE", + "link": 37 + } + ], + "outputs": [ + { + "name": "latent", + "type": "LATENT", + "links": [ + 38 + ] + }, + { + "name": "width", + "type": "INT", + "links": null + }, + { + "name": "height", + "type": "INT", + "links": null + }, + { + "name": "latent_info", + "type": "STRING", + "links": null + } + ], + "properties": { + "aux_id": "Gin3601/LLS-node", + "ver": "15fb6920931aa6c502dd40976a2bd5fb1514c27a", + "Node name for S&R": "LLSSimpleEmptyLatent" + }, + "widgets_values": [ + "Family Default", + 512, + 512, + 1, + "Auto", + "keep_aspect" + ] + }, + { + "id": 30, + "type": "LoadImage", + "pos": [ + 433.0080499616882, + -734.3942620458165 + ], + "size": [ + 270, + 314 + ], + "flags": {}, + "order": 1, + "mode": 4, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 39 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.21.0", + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "example.png", + "image" + ] + }, + { + "id": 34, + "type": "LLSQwenImageEdit", + "pos": [ + 1592.9390229661215, + 69.29028563341905 + ], + "size": [ + 400, + 534 + ], + "flags": {}, + "order": 9, + "mode": 4, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 43 + }, + { + "name": "image2", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "name": "image3", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "name": "model", + "shape": 7, + "type": "MODEL", + "link": null + }, + { + "name": "lora_stack", + "shape": 7, + "type": "LLS_QWEN_LORA_STACK", + "link": null + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 44 + ] + } + ], + "properties": { + "aux_id": "Gin3601/LLS-node", + "ver": "1d481c0dc75cac2cd1342012971f82a39792e83e", + "Node name for S&R": "LLSQwenImageEdit" + }, + "widgets_values": [ + "(no qwen image edit models found)", + "", + 20, + 661366653803666, + "randomize", + "", + 4, + "euler", + "simple", + 3.1, + 1, + "index_timestep_zero", + false, + "(auto)", + 1 + ] + }, + { + "id": 23, + "type": "LLSSimplePromptEncode", + "pos": [ + 774.4544228864921, + -326.3542439183741 + ], + "size": [ + 400, + 230 + ], + "flags": {}, + "order": 7, + "mode": 4, + "inputs": [ + { + "name": "text_encoder", + "shape": 7, + "type": "CLIP", + "link": 40 + }, + { + "name": "clip", + "shape": 7, + "type": "CLIP", + "link": 41 + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [ + 26 + ] + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 27 + ] + }, + { + "name": "prompt_info", + "type": "STRING", + "links": null + } + ], + "properties": { + "aux_id": "Gin3601/LLS-node", + "ver": "3e97537f543c74db0e91a840d698105c5f269931", + "Node name for S&R": "LLSSimplePromptEncode" + }, + "widgets_values": [ + "cat\n", + "", + -1, + "Auto" + ] + }, + { + "id": 25, + "type": "LLSSimpleKSampler", + "pos": [ + 1251.2977114607115, + -523.7621248998194 + ], + "size": [ + 270, + 446 + ], + "flags": {}, + "order": 12, + "mode": 4, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 25 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 26 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 27 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 38 + }, + { + "name": "repair_info", + "shape": 7, + "type": "LLS_REPAIR_INFO", + "link": null + }, + { + "name": "guidance_stack", + "shape": 7, + "type": "LLS_GUIDANCE_STACK", + "link": null + } + ], + "outputs": [ + { + "name": "latent", + "type": "LATENT", + "links": [ + 30 + ] + }, + { + "name": "sample_info", + "type": "STRING", + "links": null + } + ], + "properties": { + "aux_id": "Gin3601/LLS-node", + "ver": "3e97537f543c74db0e91a840d698105c5f269931", + "Node name for S&R": "LLSSimpleKSampler" + }, + "widgets_values": [ + "Family Default", + 887303760569149, + "randomize", + 20, + 7, + "euler_ancestral", + "karras", + 1, + 3.5, + "Auto", + 3.5, + "Auto", + "" + ] + }, + { + "id": 32, + "type": "LLSQwenTextToImage", + "pos": [ + 723.5861328843849, + 78.56194147786306 + ], + "size": [ + 400, + 498 + ], + "flags": {}, + "order": 10, + "mode": 4, + "inputs": [ + { + "name": "model", + "shape": 7, + "type": "MODEL", + "link": null + }, + { + "name": "lora_stack", + "shape": 7, + "type": "LLS_QWEN_LORA_STACK", + "link": 45 + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 42 + ] + } + ], + "properties": { + "aux_id": "Gin3601/LLS-node", + "ver": "1d481c0dc75cac2cd1342012971f82a39792e83e", + "Node name for S&R": "LLSQwenTextToImage" + }, + "widgets_values": [ + "qwen_image_fp8_e4m3fn.safetensors", + "CAT", + 1024, + 1024, + 20, + 236805929055807, + "randomize", + 1, + "", + 4, + "euler", + "simple", + 3.1, + false, + "(auto)", + 1 + ] + }, + { + "id": 35, + "type": "LoadImage", + "pos": [ + 1287.4303710057327, + 67.9100923991409 + ], + "size": [ + 270, + 314 + ], + "flags": {}, + "order": 2, + "mode": 4, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 43 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.21.0", + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "example.png", + "image" + ] + }, + { + "id": 36, + "type": "PreviewImage", + "pos": [ + 2013.8828021217575, + 70.5195091149048 + ], + "size": [ + 140, + 26 + ], + "flags": { + "collapsed": false + }, + "order": 13, + "mode": 4, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 44 + } + ], + "outputs": [], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.21.0", + "Node name for S&R": "PreviewImage" + }, + "widgets_values": [] + }, + { + "id": 38, + "type": "LLSQwenLoRAStack", + "pos": [ + 430.7382413862913, + 84.28211107685348 + ], + "size": [ + 270, + 82 + ], + "flags": {}, + "order": 3, + "mode": 4, + "inputs": [ + { + "name": "lora_stack", + "shape": 7, + "type": "LLS_QWEN_LORA_STACK", + "link": null + } + ], + "outputs": [ + { + "name": "lora_stack", + "type": "LLS_QWEN_LORA_STACK", + "links": [ + 45 + ] + } + ], + "properties": { + "aux_id": "Gin3601/LLS-node", + "ver": "ce6ac6b0d4efc263e1d38b64bdd11aa8629a21bf", + "Node name for S&R": "LLSQwenLoRAStack" + }, + "widgets_values": [ + "(no loras found)", + 1 + ] + }, + { + "id": 47, + "type": "VAEDecode", + "pos": [ + 1825.9733979514097, + 1053.3741446628553 + ], + "size": [ + 140, + 46 + ], + "flags": {}, + "order": 19, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 56 + }, + { + "name": "vae", + "type": "VAE", + "link": 57 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 58 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.21.0", + "Node name for S&R": "VAEDecode" + }, + "widgets_values": [] + }, + { + "id": 48, + "type": "PreviewImage", + "pos": [ + 2028.5545027912408, + 1063.1862769831923 + ], + "size": [ + 140, + 26 + ], + "flags": {}, + "order": 21, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 58 + } + ], + "outputs": [], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.21.0", + "Node name for S&R": "PreviewImage" + }, + "widgets_values": [] + }, + { + "id": 33, + "type": "PreviewImage", + "pos": [ + 1138.0580854156797, + 77.42985108631 + ], + "size": [ + 140, + 246 + ], + "flags": {}, + "order": 14, + "mode": 4, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 42 + } + ], + "outputs": [], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.21.0", + "Node name for S&R": "PreviewImage" + }, + "widgets_values": [] + }, + { + "id": 41, + "type": "LLSSimpleRepairFinish", + "pos": [ + 1834.253738230468, + 700.4561136191923 + ], + "size": [ + 298.25, + 286 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "name": "original_image", + "type": "IMAGE", + "link": null + }, + { + "name": "generated_image", + "type": "IMAGE", + "link": null + }, + { + "name": "repair_info", + "type": "LLS_REPAIR_INFO", + "link": null + }, + { + "name": "work_mask", + "shape": 7, + "type": "MASK", + "link": null + } + ], + "outputs": [ + { + "name": "final_image", + "type": "IMAGE", + "links": null + }, + { + "name": "preview_image", + "type": "IMAGE", + "links": null + } + ], + "properties": { + "aux_id": "Gin3601/LLS-node", + "ver": "3fb0ca37ca5c434470439faee80ef4248f133d92", + "Node name for S&R": "LLSSimpleRepairFinish" + }, + "widgets_values": [ + 8, + "disabled", + "enabled", + 1, + true, + "soft", + "final", + "" + ] + }, + { + "id": 42, + "type": "LoadImage", + "pos": [ + 836.8916577534524, + 694.5567621363803 + ], + "size": [ + 270, + 314 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 46 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": [ + 59 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.21.0", + "Node name for S&R": "LoadImage", + "image": "clipspace/clipspace-painted-masked-1779342854818.png [input]" + }, + "widgets_values": [ + "clipspace/clipspace-painted-masked-1779342854818.png [input]", + "image" + ] + }, + { + "id": 45, + "type": "LLSSimpleCheckpointLoader", + "pos": [ + 435.4678768213653, + 703.7324463283629 + ], + "size": [ + 303.159765625, + 286 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "model", + "type": "MODEL", + "links": [ + 52 + ] + }, + { + "name": "clip", + "type": "CLIP", + "links": [ + 47 + ] + }, + { + "name": "vae", + "type": "VAE", + "links": [ + 49, + 57 + ] + }, + { + "name": "text_encoder", + "type": "CLIP", + "links": [ + 48 + ] + } + ], + "properties": { + "aux_id": "Gin3601/LLS-node", + "ver": "3e97537f543c74db0e91a840d698105c5f269931", + "Node name for S&R": "LLSSimpleCheckpointLoader" + }, + "widgets_values": [ + "flux1-schnell-fp8.safetensors", + "Auto", + "simple", + "auto", + "auto", + "(auto)", + "(auto)", + "(auto)" + ] + }, + { + "id": 44, + "type": "LLSSimplePromptEncode", + "pos": [ + 414.4659924164017, + 1032.2056031054838 + ], + "size": [ + 400, + 230 + ], + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [ + { + "name": "text_encoder", + "shape": 7, + "type": "CLIP", + "link": 47 + }, + { + "name": "clip", + "shape": 7, + "type": "CLIP", + "link": 48 + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [ + 50 + ] + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 51 + ] + }, + { + "name": "prompt_info", + "type": "STRING", + "links": null + } + ], + "properties": { + "aux_id": "Gin3601/LLS-node", + "ver": "3e97537f543c74db0e91a840d698105c5f269931", + "Node name for S&R": "LLSSimplePromptEncode" + }, + "widgets_values": [ + "在桌子上面添加一只猫", + "", + -1, + "Auto" + ] + }, + { + "id": 40, + "type": "LLSSimpleRepairPrepare", + "pos": [ + 1146.7837663241448, + 689.6573348009558 + ], + "size": [ + 286.025390625, + 610 + ], + "flags": {}, + "order": 15, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 46 + }, + { + "name": "mask", + "type": "MASK", + "link": 59 + }, + { + "name": "vae", + "type": "VAE", + "link": 49 + }, + { + "name": "positive", + "shape": 7, + "type": "CONDITIONING", + "link": 50 + }, + { + "name": "negative", + "shape": 7, + "type": "CONDITIONING", + "link": 51 + } + ], + "outputs": [ + { + "name": "latent", + "type": "LATENT", + "links": [ + 53 + ] + }, + { + "name": "work_image", + "type": "IMAGE", + "links": null + }, + { + "name": "work_mask", + "type": "MASK", + "links": null + }, + { + "name": "repair_info", + "type": "LLS_REPAIR_INFO", + "links": [ + 60 + ] + }, + { + "name": "recommended_denoise", + "type": "FLOAT", + "links": null + }, + { + "name": "positive", + "type": "CONDITIONING", + "links": [ + 61 + ] + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 62 + ] + } + ], + "properties": { + "aux_id": "Gin3601/LLS-node", + "ver": "3fb0ca37ca5c434470439faee80ef4248f133d92", + "Node name for S&R": "LLSSimpleRepairPrepare" + }, + "widgets_values": [ + "auto", + "auto", + "auto", + 24, + 8, + 0.5, + false, + 64, + 1.5, + 256, + 1024, + "fit", + 0, + 0, + 0, + 0, + "edge", + "enabled", + "" + ] + }, + { + "id": 46, + "type": "LLSSimpleKSampler", + "pos": [ + 1501.7649997487804, + 716.6535325802862 + ], + "size": [ + 270, + 446 + ], + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 52 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 61 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 62 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 53 + }, + { + "name": "repair_info", + "shape": 7, + "type": "LLS_REPAIR_INFO", + "link": 60 + }, + { + "name": "guidance_stack", + "shape": 7, + "type": "LLS_GUIDANCE_STACK", + "link": null + } + ], + "outputs": [ + { + "name": "latent", + "type": "LATENT", + "links": [ + 56 + ] + }, + { + "name": "sample_info", + "type": "STRING", + "links": null + } + ], + "properties": { + "aux_id": "Gin3601/LLS-node", + "ver": "3e97537f543c74db0e91a840d698105c5f269931", + "Node name for S&R": "LLSSimpleKSampler" + }, + "widgets_values": [ + "Family Default", + 887303760569149, + "randomize", + 20, + 7, + "euler_ancestral", + "karras", + 1, + 3.5, + "Auto", + 3.5, + "Auto", + "" + ] + } + ], + "links": [ + [ + 25, + 21, + 0, + 25, + 0, + "MODEL" + ], + [ + 26, + 23, + 0, + 25, + 1, + "CONDITIONING" + ], + [ + 27, + 23, + 1, + 25, + 2, + "CONDITIONING" + ], + [ + 30, + 25, + 0, + 28, + 0, + "LATENT" + ], + [ + 31, + 21, + 2, + 28, + 1, + "VAE" + ], + [ + 32, + 28, + 0, + 29, + 0, + "IMAGE" + ], + [ + 33, + 29, + 0, + 10, + 0, + "IMAGE" + ], + [ + 36, + 21, + 0, + 31, + 0, + "MODEL" + ], + [ + 37, + 21, + 2, + 31, + 2, + "VAE" + ], + [ + 38, + 31, + 0, + 25, + 3, + "LATENT" + ], + [ + 39, + 30, + 0, + 31, + 1, + "IMAGE" + ], + [ + 40, + 21, + 1, + 23, + 0, + "CLIP" + ], + [ + 41, + 21, + 3, + 23, + 1, + "CLIP" + ], + [ + 42, + 32, + 0, + 33, + 0, + "IMAGE" + ], + [ + 43, + 35, + 0, + 34, + 0, + "IMAGE" + ], + [ + 44, + 34, + 0, + 36, + 0, + "IMAGE" + ], + [ + 45, + 38, + 0, + 32, + 1, + "LLS_QWEN_LORA_STACK" + ], + [ + 46, + 42, + 0, + 40, + 0, + "IMAGE" + ], + [ + 47, + 45, + 1, + 44, + 0, + "CLIP" + ], + [ + 48, + 45, + 3, + 44, + 1, + "CLIP" + ], + [ + 49, + 45, + 2, + 40, + 2, + "VAE" + ], + [ + 50, + 44, + 0, + 40, + 3, + "CONDITIONING" + ], + [ + 51, + 44, + 1, + 40, + 4, + "CONDITIONING" + ], + [ + 52, + 45, + 0, + 46, + 0, + "MODEL" + ], + [ + 53, + 40, + 0, + 46, + 3, + "LATENT" + ], + [ + 56, + 46, + 0, + 47, + 0, + "LATENT" + ], + [ + 57, + 45, + 2, + 47, + 1, + "VAE" + ], + [ + 58, + 47, + 0, + 48, + 0, + "IMAGE" + ], + [ + 59, + 42, + 1, + 40, + 1, + "MASK" + ], + [ + 60, + 40, + 3, + 46, + 4, + "LLS_REPAIR_INFO" + ], + [ + 61, + 40, + 5, + 46, + 1, + "CONDITIONING" + ], + [ + 62, + 40, + 6, + 46, + 2, + "CONDITIONING" + ] + ], + "groups": [ + { + "id": 1, + "title": "T2I+I2I", + "bounding": [ + 408.21327185361724, + -820.4548905335885, + 1767.369279174805, + 773.8946395874026 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 2, + "title": "Qwen系列", + "bounding": [ + 411.06218625162745, + -27.797312919282117, + 1766.24, + 642.9727429809573 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 3, + "title": "局部重绘", + "bounding": [ + 411.20928282019526, + 632.5416781800909, + 1766.0618691203367, + 678.9584997049681 + ], + "color": "#3f789e", + "flags": {} + } + ], + "config": {}, + "extra": { + "ds": { + "scale": 1, + "offset": [ + -271.34962416903875, + -294.342706274949 + ] + }, + "frontendVersion": "1.43.18" + }, + "version": 0.4 +} \ No newline at end of file