修改替换背景节点逻辑
This commit is contained in:
-831
@@ -1,831 +0,0 @@
|
||||
{
|
||||
"id": "b6958508-1473-44fa-bd93-03897b3bb6cb",
|
||||
"revision": 0,
|
||||
"last_node_id": 87,
|
||||
"last_link_id": 166,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 78,
|
||||
"type": "ShowText|pysssss",
|
||||
"pos": [
|
||||
498,
|
||||
2633
|
||||
],
|
||||
"size": [
|
||||
492.36199951171875,
|
||||
169.55548095703125
|
||||
],
|
||||
"flags": {},
|
||||
"order": 8,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"label": "text",
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"link": 164
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "text",
|
||||
"name": "text",
|
||||
"shape": 6,
|
||||
"type": "STRING"
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ShowText|pysssss",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": []
|
||||
},
|
||||
{
|
||||
"id": 72,
|
||||
"type": "KSampler",
|
||||
"pos": [
|
||||
1780,
|
||||
1860
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
262
|
||||
],
|
||||
"flags": {},
|
||||
"order": 11,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"label": "model",
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": 142
|
||||
},
|
||||
{
|
||||
"label": "positive",
|
||||
"name": "positive",
|
||||
"type": "CONDITIONING",
|
||||
"link": 129
|
||||
},
|
||||
{
|
||||
"label": "negative",
|
||||
"name": "negative",
|
||||
"type": "CONDITIONING",
|
||||
"link": 130
|
||||
},
|
||||
{
|
||||
"label": "latent_image",
|
||||
"name": "latent_image",
|
||||
"type": "LATENT",
|
||||
"link": 145
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "LATENT",
|
||||
"name": "LATENT",
|
||||
"type": "LATENT",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
137
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "KSampler",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
479945352329433,
|
||||
"randomize",
|
||||
30,
|
||||
1,
|
||||
"euler",
|
||||
"simple",
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 75,
|
||||
"type": "CLIPTextEncode",
|
||||
"pos": [
|
||||
1510,
|
||||
1930
|
||||
],
|
||||
"size": [
|
||||
210.29940795898438,
|
||||
88
|
||||
],
|
||||
"flags": {
|
||||
"collapsed": false
|
||||
},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"label": "clip",
|
||||
"name": "clip",
|
||||
"type": "CLIP",
|
||||
"link": 138
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "CONDITIONING",
|
||||
"name": "CONDITIONING",
|
||||
"type": "CONDITIONING",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
139
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CLIPTextEncode",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 69,
|
||||
"type": "CLIPTextEncodeFlux",
|
||||
"pos": [
|
||||
1500,
|
||||
1730
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
166
|
||||
],
|
||||
"flags": {
|
||||
"collapsed": false
|
||||
},
|
||||
"order": 9,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"label": "clip",
|
||||
"name": "clip",
|
||||
"type": "CLIP",
|
||||
"link": 144
|
||||
},
|
||||
{
|
||||
"label": "t5xxl",
|
||||
"name": "t5xxl",
|
||||
"type": "STRING",
|
||||
"widget": {
|
||||
"name": "t5xxl"
|
||||
},
|
||||
"link": 165
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "CONDITIONING",
|
||||
"name": "CONDITIONING",
|
||||
"type": "CONDITIONING",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
120
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CLIPTextEncodeFlux",
|
||||
"widget_ue_connectable": {
|
||||
"t5xxl": true
|
||||
}
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
"",
|
||||
3.5
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 76,
|
||||
"type": "DifferentialDiffusion",
|
||||
"pos": [
|
||||
1500,
|
||||
1610
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
58
|
||||
],
|
||||
"flags": {},
|
||||
"order": 7,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"label": "model",
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": 141
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "MODEL",
|
||||
"name": "MODEL",
|
||||
"type": "MODEL",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
142
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "DifferentialDiffusion",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 70,
|
||||
"type": "InpaintModelConditioning",
|
||||
"pos": [
|
||||
1780,
|
||||
1600
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
138
|
||||
],
|
||||
"flags": {},
|
||||
"order": 10,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"label": "positive",
|
||||
"name": "positive",
|
||||
"type": "CONDITIONING",
|
||||
"link": 120
|
||||
},
|
||||
{
|
||||
"label": "negative",
|
||||
"name": "negative",
|
||||
"type": "CONDITIONING",
|
||||
"link": 139
|
||||
},
|
||||
{
|
||||
"label": "vae",
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"link": 122
|
||||
},
|
||||
{
|
||||
"label": "pixels",
|
||||
"name": "pixels",
|
||||
"type": "IMAGE",
|
||||
"link": 123
|
||||
},
|
||||
{
|
||||
"label": "mask",
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"link": 124
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "positive",
|
||||
"name": "positive",
|
||||
"type": "CONDITIONING",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
129
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "negative",
|
||||
"name": "negative",
|
||||
"type": "CONDITIONING",
|
||||
"slot_index": 1,
|
||||
"links": [
|
||||
130
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "latent",
|
||||
"name": "latent",
|
||||
"type": "LATENT",
|
||||
"slot_index": 2,
|
||||
"links": [
|
||||
145
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "InpaintModelConditioning",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
false
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 60,
|
||||
"type": "Note",
|
||||
"pos": [
|
||||
232,
|
||||
1464
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
140
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"properties": {
|
||||
"text": "",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
"1.上传图片后右键\n2.在遮罩编辑器中打开\n3.涂抹想要重绘的区域\n4.点击cave或者确定\n5.按住右键涂抹可以去掉涂错的地方"
|
||||
],
|
||||
"color": "#432",
|
||||
"bgcolor": "#653"
|
||||
},
|
||||
{
|
||||
"id": 30,
|
||||
"type": "LoadImage",
|
||||
"pos": [
|
||||
510,
|
||||
1504
|
||||
],
|
||||
"size": [
|
||||
470.2230224609375,
|
||||
704.8888549804688
|
||||
],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "IMAGE",
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
123
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "MASK",
|
||||
"name": "MASK",
|
||||
"type": "MASK",
|
||||
"slot_index": 1,
|
||||
"links": [
|
||||
124
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LoadImage",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
"clipspace/5c52c8440e713f6489a038f8c25e4f48e3dee18a3945147a28c7631104ea3f9c.png [input]",
|
||||
"image"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 46,
|
||||
"type": "DualCLIPLoader",
|
||||
"pos": [
|
||||
1130,
|
||||
1810
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
130
|
||||
],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "CLIP",
|
||||
"name": "CLIP",
|
||||
"type": "CLIP",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
138,
|
||||
144
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "DualCLIPLoader",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
"clip_l.safetensors",
|
||||
"t5xxl_fp8_e4m3fn.safetensors",
|
||||
"flux",
|
||||
"default"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 54,
|
||||
"type": "VAELoader",
|
||||
"pos": [
|
||||
1130,
|
||||
2050
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
58
|
||||
],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "VAE",
|
||||
"name": "VAE",
|
||||
"type": "VAE",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
79,
|
||||
122
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "VAELoader",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
"ae.sft"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 45,
|
||||
"type": "UNETLoader",
|
||||
"pos": [
|
||||
1130,
|
||||
1620
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
82
|
||||
],
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "MODEL",
|
||||
"name": "MODEL",
|
||||
"type": "MODEL",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
141
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "UNETLoader",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
"fluxFillFP8_v10.safetensors",
|
||||
"fp8_e4m3fn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 53,
|
||||
"type": "VAEDecode",
|
||||
"pos": [
|
||||
1510,
|
||||
2070
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
46
|
||||
],
|
||||
"flags": {},
|
||||
"order": 12,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"label": "samples",
|
||||
"name": "samples",
|
||||
"type": "LATENT",
|
||||
"link": 137
|
||||
},
|
||||
{
|
||||
"label": "vae",
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"link": 79
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "IMAGE",
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
166
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "VAEDecode",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": []
|
||||
},
|
||||
{
|
||||
"id": 87,
|
||||
"type": "SaveImage",
|
||||
"pos": [
|
||||
2134,
|
||||
1526
|
||||
],
|
||||
"size": [
|
||||
459.5748291015625,
|
||||
661.1332397460938
|
||||
],
|
||||
"flags": {},
|
||||
"order": 13,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"label": "images",
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 166
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "image_urls",
|
||||
"name": "image_urls",
|
||||
"type": "STRING",
|
||||
"links": null
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "SaveImage",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
"ComfyUI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 86,
|
||||
"type": "ArgosTranslateTextNode",
|
||||
"pos": [
|
||||
513,
|
||||
2359
|
||||
],
|
||||
"size": [
|
||||
469.2802429199219,
|
||||
199.02728271484375
|
||||
],
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "text",
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
164,
|
||||
165
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ArgosTranslateTextNode",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
"chinese",
|
||||
"english",
|
||||
"手镯"
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
79,
|
||||
54,
|
||||
0,
|
||||
53,
|
||||
1,
|
||||
"VAE"
|
||||
],
|
||||
[
|
||||
120,
|
||||
69,
|
||||
0,
|
||||
70,
|
||||
0,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
122,
|
||||
54,
|
||||
0,
|
||||
70,
|
||||
2,
|
||||
"VAE"
|
||||
],
|
||||
[
|
||||
123,
|
||||
30,
|
||||
0,
|
||||
70,
|
||||
3,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
124,
|
||||
30,
|
||||
1,
|
||||
70,
|
||||
4,
|
||||
"MASK"
|
||||
],
|
||||
[
|
||||
129,
|
||||
70,
|
||||
0,
|
||||
72,
|
||||
1,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
130,
|
||||
70,
|
||||
1,
|
||||
72,
|
||||
2,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
137,
|
||||
72,
|
||||
0,
|
||||
53,
|
||||
0,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
138,
|
||||
46,
|
||||
0,
|
||||
75,
|
||||
0,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
139,
|
||||
75,
|
||||
0,
|
||||
70,
|
||||
1,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
141,
|
||||
45,
|
||||
0,
|
||||
76,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
142,
|
||||
76,
|
||||
0,
|
||||
72,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
144,
|
||||
46,
|
||||
0,
|
||||
69,
|
||||
0,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
145,
|
||||
70,
|
||||
2,
|
||||
72,
|
||||
3,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
164,
|
||||
86,
|
||||
0,
|
||||
78,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
165,
|
||||
86,
|
||||
0,
|
||||
69,
|
||||
1,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
166,
|
||||
53,
|
||||
0,
|
||||
87,
|
||||
0,
|
||||
"IMAGE"
|
||||
]
|
||||
],
|
||||
"groups": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "FLUX",
|
||||
"bounding": [
|
||||
1063,
|
||||
1433,
|
||||
1577,
|
||||
796
|
||||
],
|
||||
"color": "#3f789e",
|
||||
"font_size": 24,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "上传图片并进入遮罩涂抹需要修饰的地方",
|
||||
"bounding": [
|
||||
475,
|
||||
1426,
|
||||
534,
|
||||
795
|
||||
],
|
||||
"color": "#3f789e",
|
||||
"font_size": 24,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "输入中文提示词例如:口红、花环",
|
||||
"bounding": [
|
||||
472,
|
||||
2267,
|
||||
535,
|
||||
574
|
||||
],
|
||||
"color": "#3f789e",
|
||||
"font_size": 24,
|
||||
"flags": {}
|
||||
}
|
||||
],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ue_links": [],
|
||||
"0246.VERSION": [
|
||||
0,
|
||||
0,
|
||||
4
|
||||
],
|
||||
"ds": {
|
||||
"scale": 0.6588450000000002,
|
||||
"offset": [
|
||||
460.77367154024205,
|
||||
-1317.5880656092918
|
||||
]
|
||||
},
|
||||
"frontendVersion": "1.23.0",
|
||||
"VHS_latentpreview": false,
|
||||
"VHS_latentpreviewrate": 0,
|
||||
"VHS_MetadataImage": true,
|
||||
"VHS_KeepIntermediate": true
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -0,0 +1,917 @@
|
||||
{
|
||||
"id": "ef9bb8d6-183c-41ad-a0d0-f13d4dba3839",
|
||||
"revision": 0,
|
||||
"last_node_id": 15,
|
||||
"last_link_id": 18,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "LoadImage",
|
||||
"pos": [
|
||||
40,
|
||||
420
|
||||
],
|
||||
"size": [
|
||||
270,
|
||||
314
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
1,
|
||||
2
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "MASK",
|
||||
"type": "MASK",
|
||||
"links": []
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"cnr_id": "comfy-core",
|
||||
"ver": "0.21.0",
|
||||
"Node name for S&R": "LoadImage"
|
||||
},
|
||||
"widgets_values": [
|
||||
"ChatGPT Image 2026年5月25日 18_14_30.png",
|
||||
"image"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "LoadImage",
|
||||
"pos": [
|
||||
40,
|
||||
60
|
||||
],
|
||||
"size": [
|
||||
270,
|
||||
314
|
||||
],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
3
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "MASK",
|
||||
"type": "MASK",
|
||||
"links": []
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"cnr_id": "comfy-core",
|
||||
"ver": "0.21.0",
|
||||
"Node name for S&R": "LoadImage"
|
||||
},
|
||||
"widgets_values": [
|
||||
"c580bea1ee8fcdc6b9663fada5540d6ee4a780ce9a8e309d63428a65a6a6821d.jpg",
|
||||
"image"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "RMBG",
|
||||
"pos": [
|
||||
380,
|
||||
430
|
||||
],
|
||||
"size": [
|
||||
340,
|
||||
292
|
||||
],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 1
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": []
|
||||
},
|
||||
{
|
||||
"name": "MASK",
|
||||
"type": "MASK",
|
||||
"links": [
|
||||
4
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "MASK_IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": null
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"cnr_id": "comfyui-rmbg",
|
||||
"ver": "d7402513f23f58db7d56754b02a4f51a148b4941",
|
||||
"Node name for S&R": "RMBG"
|
||||
},
|
||||
"widgets_values": [
|
||||
"RMBG-2.0",
|
||||
1,
|
||||
1024,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
"Alpha",
|
||||
"#222222"
|
||||
],
|
||||
"color": "#222e40",
|
||||
"bgcolor": "#364254"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"type": "InvertMask",
|
||||
"pos": [
|
||||
780,
|
||||
530
|
||||
],
|
||||
"size": [
|
||||
140,
|
||||
26
|
||||
],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"link": 4
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "MASK",
|
||||
"type": "MASK",
|
||||
"links": [
|
||||
5
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"cnr_id": "comfy-core",
|
||||
"ver": "0.21.0",
|
||||
"Node name for S&R": "InvertMask"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"type": "UNETLoader",
|
||||
"pos": [
|
||||
40,
|
||||
860
|
||||
],
|
||||
"size": [
|
||||
270,
|
||||
82
|
||||
],
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"label": "unet_name",
|
||||
"name": "unet_name",
|
||||
"type": "COMBO",
|
||||
"widget": {
|
||||
"name": "unet_name"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "weight_dtype",
|
||||
"name": "weight_dtype",
|
||||
"type": "COMBO",
|
||||
"widget": {
|
||||
"name": "weight_dtype"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "MODEL",
|
||||
"name": "MODEL",
|
||||
"type": "MODEL",
|
||||
"links": [
|
||||
6
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "UNETLoader",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
"flux-2-klein-9b.safetensors",
|
||||
"default"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"type": "CLIPLoader",
|
||||
"pos": [
|
||||
40,
|
||||
970
|
||||
],
|
||||
"size": [
|
||||
270,
|
||||
106
|
||||
],
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"label": "clip_name",
|
||||
"name": "clip_name",
|
||||
"type": "COMBO",
|
||||
"widget": {
|
||||
"name": "clip_name"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "type",
|
||||
"name": "type",
|
||||
"type": "COMBO",
|
||||
"widget": {
|
||||
"name": "type"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "device",
|
||||
"name": "device",
|
||||
"shape": 7,
|
||||
"type": "COMBO",
|
||||
"widget": {
|
||||
"name": "device"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "CLIP",
|
||||
"name": "CLIP",
|
||||
"type": "CLIP",
|
||||
"links": [
|
||||
9
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CLIPLoader",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
"qwen_3_8b.safetensors",
|
||||
"flux2",
|
||||
"cpu"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"type": "VAELoader",
|
||||
"pos": [
|
||||
40,
|
||||
1110
|
||||
],
|
||||
"size": [
|
||||
330,
|
||||
60
|
||||
],
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"label": "vae_name",
|
||||
"name": "vae_name",
|
||||
"type": "COMBO",
|
||||
"widget": {
|
||||
"name": "vae_name"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "VAE",
|
||||
"name": "VAE",
|
||||
"type": "VAE",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
10,
|
||||
11
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "VAELoader",
|
||||
"cnr_id": "comfy-core",
|
||||
"ver": "0.3.48",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
"flux2-vae.safetensors"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"type": "ModelSamplingAuraFlow",
|
||||
"pos": [
|
||||
380,
|
||||
860
|
||||
],
|
||||
"size": [
|
||||
246.1006317138672,
|
||||
58
|
||||
],
|
||||
"flags": {},
|
||||
"order": 7,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"label": "model",
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": 6
|
||||
},
|
||||
{
|
||||
"label": "shift",
|
||||
"name": "shift",
|
||||
"type": "FLOAT",
|
||||
"widget": {
|
||||
"name": "shift"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "MODEL",
|
||||
"name": "MODEL",
|
||||
"type": "MODEL",
|
||||
"links": [
|
||||
7
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ModelSamplingAuraFlow",
|
||||
"cnr_id": "comfy-core",
|
||||
"ver": "0.3.48",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
3
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"type": "CFGNorm",
|
||||
"pos": [
|
||||
680,
|
||||
860
|
||||
],
|
||||
"size": [
|
||||
248.726806640625,
|
||||
58
|
||||
],
|
||||
"flags": {},
|
||||
"order": 8,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"label": "model",
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": 7
|
||||
},
|
||||
{
|
||||
"label": "strength",
|
||||
"name": "strength",
|
||||
"type": "FLOAT",
|
||||
"widget": {
|
||||
"name": "strength"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "patched_model",
|
||||
"name": "patched_model",
|
||||
"type": "MODEL",
|
||||
"links": [
|
||||
8
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CFGNorm",
|
||||
"cnr_id": "comfy-core",
|
||||
"ver": "0.3.50",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"type": "LLSFlux2KleinEditTextEncode",
|
||||
"pos": [
|
||||
1040,
|
||||
240
|
||||
],
|
||||
"size": [
|
||||
400,
|
||||
260
|
||||
],
|
||||
"flags": {},
|
||||
"order": 9,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "clip",
|
||||
"type": "CLIP",
|
||||
"link": 9
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"link": 10
|
||||
},
|
||||
{
|
||||
"name": "image1",
|
||||
"type": "IMAGE",
|
||||
"link": 2
|
||||
},
|
||||
{
|
||||
"name": "image2",
|
||||
"shape": 7,
|
||||
"type": "IMAGE",
|
||||
"link": 3
|
||||
},
|
||||
{
|
||||
"name": "image3",
|
||||
"shape": 7,
|
||||
"type": "IMAGE",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "mask",
|
||||
"shape": 7,
|
||||
"type": "MASK",
|
||||
"link": 5
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "conditioning",
|
||||
"type": "CONDITIONING",
|
||||
"links": [
|
||||
12,
|
||||
13
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "latent",
|
||||
"type": "LATENT",
|
||||
"links": [
|
||||
14
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "custom_output",
|
||||
"type": "LLS_FLUX2KLEIN_OUTPUT",
|
||||
"links": null
|
||||
},
|
||||
{
|
||||
"name": "main_image",
|
||||
"type": "IMAGE",
|
||||
"links": null
|
||||
},
|
||||
{
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"links": null
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"aux_id": "Gin3601/LLS-node",
|
||||
"ver": "f6bf21e439db74bf21d96157e231dbc99b45fc88",
|
||||
"Node name for S&R": "LLSFlux2KleinEditTextEncode"
|
||||
},
|
||||
"widgets_values": [
|
||||
"Keep the product unchanged. Replace the plain background with a premium e-commerce environment that matches the product material, lighting, and usage context. Preserve the product silhouette, logo, label, and camera angle. Photorealistic, clean composition, ad-quality detail.",
|
||||
1024,
|
||||
"longest_edge",
|
||||
"use_mask"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"type": "ConditioningZeroOut",
|
||||
"pos": [
|
||||
1490,
|
||||
350
|
||||
],
|
||||
"size": [
|
||||
197.712890625,
|
||||
26
|
||||
],
|
||||
"flags": {},
|
||||
"order": 10,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"label": "conditioning",
|
||||
"name": "conditioning",
|
||||
"type": "CONDITIONING",
|
||||
"link": 13
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"label": "CONDITIONING",
|
||||
"name": "CONDITIONING",
|
||||
"type": "CONDITIONING",
|
||||
"links": [
|
||||
15
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ConditioningZeroOut",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": []
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"type": "KSampler",
|
||||
"pos": [
|
||||
1500,
|
||||
740
|
||||
],
|
||||
"size": [
|
||||
270,
|
||||
262
|
||||
],
|
||||
"flags": {},
|
||||
"order": 11,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": 8
|
||||
},
|
||||
{
|
||||
"name": "positive",
|
||||
"type": "CONDITIONING",
|
||||
"link": 12
|
||||
},
|
||||
{
|
||||
"name": "negative",
|
||||
"type": "CONDITIONING",
|
||||
"link": 15
|
||||
},
|
||||
{
|
||||
"name": "latent_image",
|
||||
"type": "LATENT",
|
||||
"link": 14
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "LATENT",
|
||||
"type": "LATENT",
|
||||
"links": [
|
||||
16
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"cnr_id": "comfy-core",
|
||||
"ver": "0.21.0",
|
||||
"Node name for S&R": "KSampler"
|
||||
},
|
||||
"widgets_values": [
|
||||
34227918990123,
|
||||
"randomize",
|
||||
20,
|
||||
4,
|
||||
"euler",
|
||||
"simple",
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"type": "VAEDecode",
|
||||
"pos": [
|
||||
1840,
|
||||
820
|
||||
],
|
||||
"size": [
|
||||
140,
|
||||
46
|
||||
],
|
||||
"flags": {},
|
||||
"order": 12,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "samples",
|
||||
"type": "LATENT",
|
||||
"link": 16
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"link": 11
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
17,
|
||||
18
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"cnr_id": "comfy-core",
|
||||
"ver": "0.21.0",
|
||||
"Node name for S&R": "VAEDecode"
|
||||
},
|
||||
"widgets_values": []
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
2050,
|
||||
720
|
||||
],
|
||||
"size": [
|
||||
296.69873046875,
|
||||
261.48797607421875
|
||||
],
|
||||
"flags": {},
|
||||
"order": 13,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 17
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"properties": {
|
||||
"cnr_id": "comfy-core",
|
||||
"ver": "0.21.0",
|
||||
"Node name for S&R": "PreviewImage"
|
||||
},
|
||||
"widgets_values": []
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"type": "SaveImage",
|
||||
"pos": [
|
||||
2050,
|
||||
1010
|
||||
],
|
||||
"size": [
|
||||
270,
|
||||
270
|
||||
],
|
||||
"flags": {},
|
||||
"order": 14,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 18
|
||||
},
|
||||
{
|
||||
"name": "filename_prefix",
|
||||
"type": "STRING",
|
||||
"widget": {
|
||||
"name": "filename_prefix"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image_urls",
|
||||
"type": "STRING"
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "SaveImage",
|
||||
"widget_ue_connectable": {}
|
||||
},
|
||||
"widgets_values": [
|
||||
"LLS-Flux2Klein-Background"
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
3,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
10,
|
||||
2,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
10,
|
||||
3,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
4,
|
||||
3,
|
||||
1,
|
||||
4,
|
||||
0,
|
||||
"MASK"
|
||||
],
|
||||
[
|
||||
5,
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
5,
|
||||
"MASK"
|
||||
],
|
||||
[
|
||||
6,
|
||||
5,
|
||||
0,
|
||||
8,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
7,
|
||||
8,
|
||||
0,
|
||||
9,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
8,
|
||||
9,
|
||||
0,
|
||||
12,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
9,
|
||||
6,
|
||||
0,
|
||||
10,
|
||||
0,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
10,
|
||||
7,
|
||||
0,
|
||||
10,
|
||||
1,
|
||||
"VAE"
|
||||
],
|
||||
[
|
||||
11,
|
||||
7,
|
||||
0,
|
||||
13,
|
||||
1,
|
||||
"VAE"
|
||||
],
|
||||
[
|
||||
12,
|
||||
10,
|
||||
0,
|
||||
12,
|
||||
1,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
13,
|
||||
10,
|
||||
0,
|
||||
11,
|
||||
0,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
14,
|
||||
10,
|
||||
1,
|
||||
12,
|
||||
3,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
15,
|
||||
11,
|
||||
0,
|
||||
12,
|
||||
2,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
16,
|
||||
12,
|
||||
0,
|
||||
13,
|
||||
0,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
17,
|
||||
13,
|
||||
0,
|
||||
14,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
18,
|
||||
13,
|
||||
0,
|
||||
15,
|
||||
0,
|
||||
"IMAGE"
|
||||
]
|
||||
],
|
||||
"groups": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "背景替换/电商详情图",
|
||||
"bounding": [
|
||||
10,
|
||||
20,
|
||||
2360,
|
||||
1280
|
||||
],
|
||||
"color": "#3f789e",
|
||||
"flags": {}
|
||||
}
|
||||
],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 0.8200000000000001,
|
||||
"offset": [
|
||||
-18,
|
||||
8
|
||||
]
|
||||
},
|
||||
"frontendVersion": "1.43.18"
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -1,669 +0,0 @@
|
||||
{
|
||||
"id": "dcac7a27-30f1-4cd1-a4a4-5b994457b3a3",
|
||||
"revision": 0,
|
||||
"last_node_id": 26,
|
||||
"last_link_id": 20,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 20,
|
||||
"type": "LoadImage",
|
||||
"pos": [
|
||||
80,
|
||||
180
|
||||
],
|
||||
"size": [
|
||||
340,
|
||||
520
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"label": "IMAGE",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "MASK",
|
||||
"type": "MASK",
|
||||
"label": "MASK",
|
||||
"slot_index": 1,
|
||||
"links": [
|
||||
2
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LoadImage"
|
||||
},
|
||||
"widgets_values": [
|
||||
"example.png",
|
||||
"image",
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"type": "LLSUniversalModelLoader",
|
||||
"pos": [
|
||||
460,
|
||||
80
|
||||
],
|
||||
"size": [
|
||||
360,
|
||||
260
|
||||
],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
3
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "text_encoder",
|
||||
"type": "CLIP",
|
||||
"slot_index": 1,
|
||||
"links": [
|
||||
4
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"slot_index": 2,
|
||||
"links": [
|
||||
5,
|
||||
6
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "model_info",
|
||||
"type": "STRING",
|
||||
"slot_index": 3,
|
||||
"links": [
|
||||
7,
|
||||
8,
|
||||
9
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LLSUniversalModelLoader"
|
||||
},
|
||||
"widgets_values": [
|
||||
"diffusion_models/flux1-fill-dev.safetensors",
|
||||
"Auto",
|
||||
"simple",
|
||||
"auto",
|
||||
"auto",
|
||||
"(auto)",
|
||||
"(auto)",
|
||||
"(auto)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"type": "LLSUniversalPromptEncode",
|
||||
"pos": [
|
||||
880,
|
||||
80
|
||||
],
|
||||
"size": [
|
||||
360,
|
||||
190
|
||||
],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "text_encoder",
|
||||
"type": "CLIP",
|
||||
"link": 4,
|
||||
"label": "text_encoder"
|
||||
},
|
||||
{
|
||||
"name": "model_info",
|
||||
"type": "STRING",
|
||||
"link": 7,
|
||||
"label": "model_info"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "positive",
|
||||
"type": "CONDITIONING",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
10
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "negative",
|
||||
"type": "CONDITIONING",
|
||||
"slot_index": 1,
|
||||
"links": [
|
||||
11
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "prompt_info",
|
||||
"type": "STRING",
|
||||
"slot_index": 2,
|
||||
"links": [
|
||||
12
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LLSUniversalPromptEncode"
|
||||
},
|
||||
"widgets_values": [
|
||||
"a small brown dog sitting in the masked area",
|
||||
"",
|
||||
-1
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"type": "LLSNativeInpaintConditioning",
|
||||
"pos": [
|
||||
880,
|
||||
300
|
||||
],
|
||||
"size": [
|
||||
400,
|
||||
230
|
||||
],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": 3,
|
||||
"label": "model"
|
||||
},
|
||||
{
|
||||
"name": "positive",
|
||||
"type": "CONDITIONING",
|
||||
"link": 10,
|
||||
"label": "positive"
|
||||
},
|
||||
{
|
||||
"name": "negative",
|
||||
"type": "CONDITIONING",
|
||||
"link": 11,
|
||||
"label": "negative"
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"link": 5,
|
||||
"label": "vae"
|
||||
},
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 1,
|
||||
"label": "image"
|
||||
},
|
||||
{
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"link": 2,
|
||||
"label": "mask"
|
||||
},
|
||||
{
|
||||
"name": "model_info",
|
||||
"type": "STRING",
|
||||
"link": 8,
|
||||
"label": "model_info"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
13
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "positive",
|
||||
"type": "CONDITIONING",
|
||||
"slot_index": 1,
|
||||
"links": [
|
||||
14
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "negative",
|
||||
"type": "CONDITIONING",
|
||||
"slot_index": 2,
|
||||
"links": [
|
||||
15
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "latent",
|
||||
"type": "LATENT",
|
||||
"slot_index": 3,
|
||||
"links": [
|
||||
16
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "inpaint_info",
|
||||
"type": "STRING",
|
||||
"slot_index": 4,
|
||||
"links": null
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LLSNativeInpaintConditioning"
|
||||
},
|
||||
"widgets_values": [
|
||||
"auto",
|
||||
1.0,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"type": "LLSSimpleKSampler",
|
||||
"pos": [
|
||||
1330,
|
||||
220
|
||||
],
|
||||
"size": [
|
||||
380,
|
||||
320
|
||||
],
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": 13,
|
||||
"label": "model"
|
||||
},
|
||||
{
|
||||
"name": "positive",
|
||||
"type": "CONDITIONING",
|
||||
"link": 14,
|
||||
"label": "positive"
|
||||
},
|
||||
{
|
||||
"name": "negative",
|
||||
"type": "CONDITIONING",
|
||||
"link": 15,
|
||||
"label": "negative"
|
||||
},
|
||||
{
|
||||
"name": "latent_image",
|
||||
"type": "LATENT",
|
||||
"link": 16,
|
||||
"label": "latent_image"
|
||||
},
|
||||
{
|
||||
"name": "repair_info",
|
||||
"type": "LLS_REPAIR_INFO",
|
||||
"link": null,
|
||||
"label": "repair_info"
|
||||
},
|
||||
{
|
||||
"name": "guidance_stack",
|
||||
"type": "LLS_GUIDANCE_STACK",
|
||||
"link": null,
|
||||
"label": "guidance_stack"
|
||||
},
|
||||
{
|
||||
"name": "model_info",
|
||||
"type": "STRING",
|
||||
"link": 9,
|
||||
"label": "model_info"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "latent",
|
||||
"type": "LATENT",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
17
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sample_info",
|
||||
"type": "STRING",
|
||||
"slot_index": 1,
|
||||
"links": [
|
||||
18
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LLSSimpleKSampler"
|
||||
},
|
||||
"widgets_values": [
|
||||
"Family Default",
|
||||
-1,
|
||||
"randomize",
|
||||
20,
|
||||
7.0,
|
||||
"euler",
|
||||
"normal",
|
||||
1.0,
|
||||
"manual",
|
||||
"auto",
|
||||
3.5,
|
||||
"Auto"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"type": "LLSSimpleVAEDecode",
|
||||
"pos": [
|
||||
1750,
|
||||
240
|
||||
],
|
||||
"size": [
|
||||
270,
|
||||
80
|
||||
],
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "samples",
|
||||
"type": "LATENT",
|
||||
"link": 17,
|
||||
"label": "samples"
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"link": 6,
|
||||
"label": "vae"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
19
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "decode_info",
|
||||
"type": "STRING",
|
||||
"slot_index": 1,
|
||||
"links": [
|
||||
20
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LLSSimpleVAEDecode"
|
||||
},
|
||||
"widgets_values": []
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"type": "LLSSaveImage",
|
||||
"pos": [
|
||||
2060,
|
||||
180
|
||||
],
|
||||
"size": [
|
||||
320,
|
||||
220
|
||||
],
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 19,
|
||||
"label": "image"
|
||||
},
|
||||
{
|
||||
"name": "prompt_info",
|
||||
"type": "STRING",
|
||||
"link": 12,
|
||||
"label": "prompt_info"
|
||||
},
|
||||
{
|
||||
"name": "latent_info",
|
||||
"type": "STRING",
|
||||
"link": null,
|
||||
"label": "latent_info"
|
||||
},
|
||||
{
|
||||
"name": "sample_info",
|
||||
"type": "STRING",
|
||||
"link": 18,
|
||||
"label": "sample_info"
|
||||
},
|
||||
{
|
||||
"name": "decode_info",
|
||||
"type": "STRING",
|
||||
"link": 20,
|
||||
"label": "decode_info"
|
||||
},
|
||||
{
|
||||
"name": "upscale_info",
|
||||
"type": "STRING",
|
||||
"link": null,
|
||||
"label": "upscale_info"
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"properties": {
|
||||
"Node name for S&R": "LLSSaveImage"
|
||||
},
|
||||
"widgets_values": [
|
||||
"LLS-Inpaint",
|
||||
"preview_only",
|
||||
true
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
1,
|
||||
20,
|
||||
0,
|
||||
23,
|
||||
4,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
2,
|
||||
20,
|
||||
1,
|
||||
23,
|
||||
5,
|
||||
"MASK"
|
||||
],
|
||||
[
|
||||
3,
|
||||
21,
|
||||
0,
|
||||
23,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
4,
|
||||
21,
|
||||
1,
|
||||
22,
|
||||
0,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
5,
|
||||
21,
|
||||
2,
|
||||
23,
|
||||
3,
|
||||
"VAE"
|
||||
],
|
||||
[
|
||||
6,
|
||||
21,
|
||||
2,
|
||||
25,
|
||||
1,
|
||||
"VAE"
|
||||
],
|
||||
[
|
||||
7,
|
||||
21,
|
||||
3,
|
||||
22,
|
||||
1,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
8,
|
||||
21,
|
||||
3,
|
||||
23,
|
||||
6,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
9,
|
||||
21,
|
||||
3,
|
||||
24,
|
||||
6,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
10,
|
||||
22,
|
||||
0,
|
||||
23,
|
||||
1,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
11,
|
||||
22,
|
||||
1,
|
||||
23,
|
||||
2,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
12,
|
||||
22,
|
||||
2,
|
||||
26,
|
||||
1,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
13,
|
||||
23,
|
||||
0,
|
||||
24,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
14,
|
||||
23,
|
||||
1,
|
||||
24,
|
||||
1,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
15,
|
||||
23,
|
||||
2,
|
||||
24,
|
||||
2,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
16,
|
||||
23,
|
||||
3,
|
||||
24,
|
||||
3,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
17,
|
||||
24,
|
||||
0,
|
||||
25,
|
||||
0,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
18,
|
||||
24,
|
||||
1,
|
||||
26,
|
||||
3,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
19,
|
||||
25,
|
||||
0,
|
||||
26,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
20,
|
||||
25,
|
||||
1,
|
||||
26,
|
||||
4,
|
||||
"STRING"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 1.0,
|
||||
"offset": [
|
||||
0.0,
|
||||
0.0
|
||||
]
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -1,553 +0,0 @@
|
||||
{
|
||||
"id": "0794c057-df8e-49ea-a3b6-8feed69f2af4",
|
||||
"revision": 0,
|
||||
"last_node_id": 15,
|
||||
"last_link_id": 15,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 10,
|
||||
"type": "LLSUniversalModelLoader",
|
||||
"pos": [
|
||||
80,
|
||||
80
|
||||
],
|
||||
"size": [
|
||||
360,
|
||||
260
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
1,
|
||||
11
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "text_encoder",
|
||||
"type": "CLIP",
|
||||
"slot_index": 1,
|
||||
"links": [
|
||||
2
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"slot_index": 2,
|
||||
"links": [
|
||||
3
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "model_info",
|
||||
"type": "STRING",
|
||||
"slot_index": 3,
|
||||
"links": [
|
||||
4,
|
||||
5
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LLSUniversalModelLoader"
|
||||
},
|
||||
"widgets_values": [
|
||||
"diffusion_models/flux1-schnell.safetensors",
|
||||
"Auto",
|
||||
"simple",
|
||||
"auto",
|
||||
"auto",
|
||||
"(auto)",
|
||||
"(auto)",
|
||||
"(auto)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"type": "LLSUniversalPromptEncode",
|
||||
"pos": [
|
||||
500,
|
||||
80
|
||||
],
|
||||
"size": [
|
||||
360,
|
||||
190
|
||||
],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "text_encoder",
|
||||
"type": "CLIP",
|
||||
"link": 2,
|
||||
"label": "text_encoder"
|
||||
},
|
||||
{
|
||||
"name": "model_info",
|
||||
"type": "STRING",
|
||||
"link": 4,
|
||||
"label": "model_info"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "positive",
|
||||
"type": "CONDITIONING",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
6
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "negative",
|
||||
"type": "CONDITIONING",
|
||||
"slot_index": 1,
|
||||
"links": [
|
||||
7
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "prompt_info",
|
||||
"type": "STRING",
|
||||
"slot_index": 2,
|
||||
"links": [
|
||||
8
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LLSUniversalPromptEncode"
|
||||
},
|
||||
"widgets_values": [
|
||||
"a small brown dog standing on the grass",
|
||||
"",
|
||||
-1
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"type": "LLSSimpleEmptyLatent",
|
||||
"pos": [
|
||||
500,
|
||||
320
|
||||
],
|
||||
"size": [
|
||||
360,
|
||||
230
|
||||
],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": 1,
|
||||
"label": "model"
|
||||
},
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": null,
|
||||
"label": "image"
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"link": null,
|
||||
"label": "vae"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "latent",
|
||||
"type": "LATENT",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
9
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "width",
|
||||
"type": "INT",
|
||||
"slot_index": 1,
|
||||
"links": null
|
||||
},
|
||||
{
|
||||
"name": "height",
|
||||
"type": "INT",
|
||||
"slot_index": 2,
|
||||
"links": null
|
||||
},
|
||||
{
|
||||
"name": "latent_info",
|
||||
"type": "STRING",
|
||||
"slot_index": 3,
|
||||
"links": [
|
||||
10
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LLSSimpleEmptyLatent"
|
||||
},
|
||||
"widgets_values": [
|
||||
"Family Default",
|
||||
1024,
|
||||
1024,
|
||||
1,
|
||||
"Auto",
|
||||
"keep_aspect"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"type": "LLSSimpleKSampler",
|
||||
"pos": [
|
||||
920,
|
||||
180
|
||||
],
|
||||
"size": [
|
||||
380,
|
||||
320
|
||||
],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": 11,
|
||||
"label": "model"
|
||||
},
|
||||
{
|
||||
"name": "positive",
|
||||
"type": "CONDITIONING",
|
||||
"link": 6,
|
||||
"label": "positive"
|
||||
},
|
||||
{
|
||||
"name": "negative",
|
||||
"type": "CONDITIONING",
|
||||
"link": 7,
|
||||
"label": "negative"
|
||||
},
|
||||
{
|
||||
"name": "latent_image",
|
||||
"type": "LATENT",
|
||||
"link": 9,
|
||||
"label": "latent_image"
|
||||
},
|
||||
{
|
||||
"name": "repair_info",
|
||||
"type": "LLS_REPAIR_INFO",
|
||||
"link": null,
|
||||
"label": "repair_info"
|
||||
},
|
||||
{
|
||||
"name": "guidance_stack",
|
||||
"type": "LLS_GUIDANCE_STACK",
|
||||
"link": null,
|
||||
"label": "guidance_stack"
|
||||
},
|
||||
{
|
||||
"name": "model_info",
|
||||
"type": "STRING",
|
||||
"link": 5,
|
||||
"label": "model_info"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "latent",
|
||||
"type": "LATENT",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
12
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sample_info",
|
||||
"type": "STRING",
|
||||
"slot_index": 1,
|
||||
"links": [
|
||||
13
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LLSSimpleKSampler"
|
||||
},
|
||||
"widgets_values": [
|
||||
"Family Default",
|
||||
-1,
|
||||
"randomize",
|
||||
20,
|
||||
7.0,
|
||||
"euler",
|
||||
"normal",
|
||||
1.0,
|
||||
"manual",
|
||||
"auto",
|
||||
3.5,
|
||||
"Auto"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"type": "LLSSimpleVAEDecode",
|
||||
"pos": [
|
||||
1330,
|
||||
200
|
||||
],
|
||||
"size": [
|
||||
270,
|
||||
80
|
||||
],
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "samples",
|
||||
"type": "LATENT",
|
||||
"link": 12,
|
||||
"label": "samples"
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"link": 3,
|
||||
"label": "vae"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"slot_index": 0,
|
||||
"links": [
|
||||
14
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "decode_info",
|
||||
"type": "STRING",
|
||||
"slot_index": 1,
|
||||
"links": [
|
||||
15
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LLSSimpleVAEDecode"
|
||||
},
|
||||
"widgets_values": []
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"type": "LLSSaveImage",
|
||||
"pos": [
|
||||
1640,
|
||||
140
|
||||
],
|
||||
"size": [
|
||||
320,
|
||||
220
|
||||
],
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 14,
|
||||
"label": "image"
|
||||
},
|
||||
{
|
||||
"name": "prompt_info",
|
||||
"type": "STRING",
|
||||
"link": 8,
|
||||
"label": "prompt_info"
|
||||
},
|
||||
{
|
||||
"name": "latent_info",
|
||||
"type": "STRING",
|
||||
"link": 10,
|
||||
"label": "latent_info"
|
||||
},
|
||||
{
|
||||
"name": "sample_info",
|
||||
"type": "STRING",
|
||||
"link": 13,
|
||||
"label": "sample_info"
|
||||
},
|
||||
{
|
||||
"name": "decode_info",
|
||||
"type": "STRING",
|
||||
"link": 15,
|
||||
"label": "decode_info"
|
||||
},
|
||||
{
|
||||
"name": "upscale_info",
|
||||
"type": "STRING",
|
||||
"link": null,
|
||||
"label": "upscale_info"
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"properties": {
|
||||
"Node name for S&R": "LLSSaveImage"
|
||||
},
|
||||
"widgets_values": [
|
||||
"LLS",
|
||||
"preview_only",
|
||||
true
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
1,
|
||||
10,
|
||||
0,
|
||||
12,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
2,
|
||||
10,
|
||||
1,
|
||||
11,
|
||||
0,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
3,
|
||||
10,
|
||||
2,
|
||||
14,
|
||||
1,
|
||||
"VAE"
|
||||
],
|
||||
[
|
||||
4,
|
||||
10,
|
||||
3,
|
||||
11,
|
||||
1,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
5,
|
||||
10,
|
||||
3,
|
||||
13,
|
||||
6,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
6,
|
||||
11,
|
||||
0,
|
||||
13,
|
||||
1,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
7,
|
||||
11,
|
||||
1,
|
||||
13,
|
||||
2,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
8,
|
||||
11,
|
||||
2,
|
||||
15,
|
||||
1,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
9,
|
||||
12,
|
||||
0,
|
||||
13,
|
||||
3,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
10,
|
||||
12,
|
||||
3,
|
||||
15,
|
||||
2,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
11,
|
||||
10,
|
||||
0,
|
||||
13,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
12,
|
||||
13,
|
||||
0,
|
||||
14,
|
||||
0,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
13,
|
||||
13,
|
||||
1,
|
||||
15,
|
||||
3,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
14,
|
||||
14,
|
||||
0,
|
||||
15,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
15,
|
||||
14,
|
||||
1,
|
||||
15,
|
||||
4,
|
||||
"STRING"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 1.0,
|
||||
"offset": [
|
||||
0.0,
|
||||
0.0
|
||||
]
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,41 @@
|
||||
# LLS Flux2Klein Background Workflow Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Add a ready-to-use ComfyUI example workflow that performs e-commerce background replacement with `LLSFlux2KleinEditTextEncode` on a fully matched Flux2/Klein model stack.
|
||||
|
||||
**Architecture:** Keep the backend node implementation as-is and add a new example workflow JSON plus a workflow regression test. The workflow must use `UNETLoader + CLIPLoader(type=flux2) + VAELoader(flux2-vae)` and derive the edit mask from `RMBG -> InvertMask` so the sampler receives a consistent Flux2/Klein edit payload.
|
||||
|
||||
**Tech Stack:** JSON workflow exports, Python `unittest`, existing ComfyUI core nodes, existing LLS custom node registration
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Lock The Workflow Contract With A Failing Test
|
||||
|
||||
**Files:**
|
||||
- Modify: `tests/test_example_workflows.py`
|
||||
|
||||
- [ ] **Step 1: Add a test that loads `LLS-Flux2Klein-电商换背景工作流.json`**
|
||||
- [ ] **Step 2: Assert the workflow includes `LLSFlux2KleinEditTextEncode`, `UNETLoader`, `CLIPLoader`, `VAELoader`, `RMBG`, `InvertMask`, `ConditioningZeroOut`, `KSampler`, and `VAEDecode`**
|
||||
- [ ] **Step 3: Assert `CLIPLoader` uses `flux2`, `VAELoader` uses `flux2-vae.safetensors`, and the LLS node uses `mask_mode = use_mask` with `resize_mode = longest_edge`**
|
||||
- [ ] **Step 4: Run the focused workflow test and confirm it fails before the workflow JSON exists**
|
||||
|
||||
### Task 2: Add The New Background-Replacement Workflow
|
||||
|
||||
**Files:**
|
||||
- Create: `LLS-Flux2Klein-电商换背景工作流.json`
|
||||
|
||||
- [ ] **Step 1: Build a compact workflow with `LoadImage` main product input feeding both `RMBG` and `LLSFlux2KleinEditTextEncode.image1`**
|
||||
- [ ] **Step 2: Add one connected scene reference image for `image2` and leave `image3` optional**
|
||||
- [ ] **Step 3: Use `RMBG -> InvertMask -> LLSFlux2KleinEditTextEncode.mask` and route `conditioning`, `ConditioningZeroOut`, `latent`, `KSampler`, and `VAEDecode` according to the edit flow contract**
|
||||
- [ ] **Step 4: Route the model through a Flux2/Klein-safe sampler chain and add `PreviewImage` plus `SaveImage` outputs**
|
||||
|
||||
### Task 3: Verify The Workflow And Summarize Constraints
|
||||
|
||||
**Files:**
|
||||
- Modify: files from earlier tasks only if verification exposes gaps
|
||||
|
||||
- [ ] **Step 1: Run `python3 -m unittest tests.test_example_workflows -v`**
|
||||
- [ ] **Step 2: Run `python3 -m json.tool 'LLS-Flux2Klein-电商换背景工作流.json' > /tmp/lls_flux2klein_background_workflow.pretty.json` to validate JSON syntax**
|
||||
- [ ] **Step 3: Re-run the targeted Flux2/Klein unit tests if the workflow change touches shared assumptions**
|
||||
- [ ] **Step 4: Summarize the new workflow file, ComfyUI search name, minimal connection path, and the remaining compatibility-vs-native Flux2 API gaps**
|
||||
@@ -32,6 +32,16 @@ except Exception as exc: # pragma: no cover - optional runtime dependency
|
||||
else: # pragma: no cover - exercised in ComfyUI runtime/tests when comfy exists
|
||||
_COMFY_UTILS_ERR = None
|
||||
|
||||
try:
|
||||
import comfy_extras.nodes_flux as native_flux_nodes
|
||||
except Exception: # pragma: no cover - optional ComfyUI runtime dependency
|
||||
native_flux_nodes = None
|
||||
|
||||
try:
|
||||
import comfy_extras.nodes_edit_model as native_edit_model_nodes
|
||||
except Exception: # pragma: no cover - optional ComfyUI runtime dependency
|
||||
native_edit_model_nodes = None
|
||||
|
||||
|
||||
RESIZE_MODE_CHOICES = ["longest_edge", "keep_original"]
|
||||
MASK_MODE_CHOICES = ["none", "use_mask", "invert_mask"]
|
||||
@@ -71,6 +81,13 @@ class _ConstantMask:
|
||||
)
|
||||
|
||||
|
||||
class _ShapeOnlyLatent:
|
||||
"""Fallback latent object for tests when torch tensors are unavailable."""
|
||||
|
||||
def __init__(self, shape):
|
||||
self.shape = tuple(shape)
|
||||
|
||||
|
||||
def _extract_latent_samples(latent):
|
||||
if isinstance(latent, dict) and "samples" in latent:
|
||||
return latent["samples"]
|
||||
@@ -87,6 +104,17 @@ def _get_image_batch_size(image) -> int:
|
||||
return batch
|
||||
|
||||
|
||||
def _extract_node_output_value(value):
|
||||
if hasattr(value, "result"):
|
||||
value = value.result
|
||||
elif hasattr(value, "args"):
|
||||
value = value.args
|
||||
|
||||
if isinstance(value, tuple) and len(value) == 1:
|
||||
return value[0]
|
||||
return value
|
||||
|
||||
|
||||
def _scale_size_by_longest_edge(width: int, height: int, target_longest_edge: int) -> tuple[int, int]:
|
||||
width = int(width)
|
||||
height = int(height)
|
||||
@@ -305,6 +333,70 @@ def _encode_reference_latent(vae, image, target_width: int, target_height: int,
|
||||
return {"samples": samples}, prepared
|
||||
|
||||
|
||||
def _encode_image_latent(vae, image, source_name: str):
|
||||
try:
|
||||
samples = vae.encode(image)
|
||||
except Exception as exc:
|
||||
raise RuntimeError(
|
||||
f"[LLS] VAE encode failed for {source_name} / {source_name} 的 VAE 编码失败: {exc}"
|
||||
) from exc
|
||||
return {"samples": samples}
|
||||
|
||||
|
||||
def _get_latent_channels(latent_samples) -> int:
|
||||
shape = tuple(getattr(latent_samples, "shape", ()))
|
||||
if len(shape) < 2:
|
||||
raise RuntimeError("[LLS] Invalid latent tensor shape. 无法识别 latent 通道数。")
|
||||
return int(shape[1])
|
||||
|
||||
|
||||
def _build_empty_like_latent(samples):
|
||||
shape = tuple(getattr(samples, "shape", ()))
|
||||
if len(shape) != 4:
|
||||
raise RuntimeError("[LLS] Invalid latent tensor shape for Empty Flux2 latent fallback.")
|
||||
|
||||
if torch is not None and isinstance(samples, torch.Tensor):
|
||||
return {"samples": torch.zeros(shape, dtype=samples.dtype, device=samples.device)}
|
||||
|
||||
try:
|
||||
return {"samples": samples.__class__(shape)}
|
||||
except Exception:
|
||||
return {"samples": _ShapeOnlyLatent(shape)}
|
||||
|
||||
|
||||
def _build_empty_flux2_latent(main_image, main_latent):
|
||||
width, height = get_image_size(main_image)
|
||||
batch_size = _get_image_batch_size(main_image)
|
||||
|
||||
execute = getattr(getattr(native_flux_nodes, "EmptyFlux2LatentImage", None), "execute", None)
|
||||
if callable(execute):
|
||||
try:
|
||||
return _extract_node_output_value(execute(width=width, height=height, batch_size=batch_size))
|
||||
except TypeError:
|
||||
return _extract_node_output_value(execute(width, height, batch_size))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return _build_empty_like_latent(_extract_latent_samples(main_latent))
|
||||
|
||||
|
||||
def _attach_reference_latents(conditioning, ref_latents):
|
||||
if not ref_latents:
|
||||
return conditioning
|
||||
|
||||
execute = getattr(getattr(native_edit_model_nodes, "ReferenceLatent", None), "execute", None)
|
||||
if callable(execute):
|
||||
updated = conditioning
|
||||
for ref_latent in ref_latents:
|
||||
try:
|
||||
updated = _extract_node_output_value(execute(updated, latent=ref_latent))
|
||||
except TypeError:
|
||||
updated = _extract_node_output_value(execute(updated, ref_latent))
|
||||
return updated
|
||||
|
||||
return _append_reference_latents(conditioning, [_extract_latent_samples(latent) for latent in ref_latents])
|
||||
|
||||
|
||||
def _build_noise_mask(mask, latent_samples):
|
||||
target_width = int(latent_samples.shape[-1])
|
||||
target_height = int(latent_samples.shape[-2])
|
||||
@@ -386,25 +478,48 @@ class LLSFlux2KleinEditTextEncode:
|
||||
conditioning, full_prompt = _encode_multivision_conditioning(clip, str(prompt), vision_images)
|
||||
|
||||
target_width, target_height = get_image_size(main_image)
|
||||
ref_latents = []
|
||||
for index, image in enumerate(images_for_edit, start=1):
|
||||
ref_latent, _prepared = _encode_reference_latent(
|
||||
vae,
|
||||
image,
|
||||
target_width,
|
||||
target_height,
|
||||
source_name=f"image{index}",
|
||||
)
|
||||
ref_latents.append(ref_latent)
|
||||
main_latent = _encode_image_latent(vae, main_image, source_name="image1")
|
||||
main_latent_channels = _get_latent_channels(_extract_latent_samples(main_latent))
|
||||
use_official_flux2_latent = main_latent_channels >= 128
|
||||
|
||||
conditioning = _append_reference_latents(
|
||||
conditioning,
|
||||
[_extract_latent_samples(latent) for latent in ref_latents],
|
||||
)
|
||||
ref_latents = [main_latent]
|
||||
if reference_image_2 is not None:
|
||||
if use_official_flux2_latent:
|
||||
ref_latents.append(_encode_image_latent(vae, reference_image_2, source_name="image2"))
|
||||
else:
|
||||
ref_latent, _prepared = _encode_reference_latent(
|
||||
vae,
|
||||
reference_image_2,
|
||||
target_width,
|
||||
target_height,
|
||||
source_name="image2",
|
||||
)
|
||||
ref_latents.append(ref_latent)
|
||||
if reference_image_3 is not None:
|
||||
if use_official_flux2_latent:
|
||||
ref_latents.append(_encode_image_latent(vae, reference_image_3, source_name="image3"))
|
||||
else:
|
||||
ref_latent, _prepared = _encode_reference_latent(
|
||||
vae,
|
||||
reference_image_3,
|
||||
target_width,
|
||||
target_height,
|
||||
source_name="image3",
|
||||
)
|
||||
ref_latents.append(ref_latent)
|
||||
|
||||
latent = {
|
||||
"samples": _extract_latent_samples(ref_latents[0]),
|
||||
}
|
||||
conditioning = _attach_reference_latents(conditioning, ref_latents)
|
||||
|
||||
if use_official_flux2_latent:
|
||||
latent = _build_empty_flux2_latent(main_image, main_latent)
|
||||
latent_mode = "empty_flux2_latent"
|
||||
conditioning_backend = "flux2klein_multivision_clip+reference_latent"
|
||||
else:
|
||||
latent = {
|
||||
"samples": _extract_latent_samples(main_latent),
|
||||
}
|
||||
latent_mode = "image1_reference_latent"
|
||||
conditioning_backend = "flux2klein_multivision_clip"
|
||||
|
||||
if mask is not None and str(mask_mode) != "none":
|
||||
latent["noise_mask"] = _build_noise_mask(output_mask, latent["samples"])
|
||||
@@ -426,13 +541,14 @@ class LLSFlux2KleinEditTextEncode:
|
||||
"main_image": "image1",
|
||||
"reference_images": reference_names,
|
||||
"num_reference_images": len(reference_names),
|
||||
"conditioning_backend": "flux2klein_multivision_clip",
|
||||
"conditioning_backend": conditioning_backend,
|
||||
"native_error": None,
|
||||
"native_wrapper": "PainterFluxImageEdit-compatible",
|
||||
"latent_mode": "image1_reference_latent",
|
||||
"native_wrapper": "official Flux2 ReferenceLatent" if use_official_flux2_latent else "PainterFluxImageEdit-compatible",
|
||||
"latent_mode": latent_mode,
|
||||
"latent_has_noise_mask": "noise_mask" in latent,
|
||||
"vision_image_count": len(vision_images),
|
||||
"reference_latent_count": len(ref_latents),
|
||||
"main_latent_channels": main_latent_channels,
|
||||
"target_size": {"width": int(target_width), "height": int(target_height)},
|
||||
"note": "image1 is main edit image; image2 and image3 are reference images; images are not concatenated",
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ from ..utils.model_info import (
|
||||
get_family_defaults,
|
||||
info_to_json,
|
||||
infer_family_from_name,
|
||||
is_flux2_family,
|
||||
is_flux_family,
|
||||
is_sdxl_family,
|
||||
tag_lls_object,
|
||||
@@ -62,6 +63,8 @@ _FLUX_T5_PATTERNS = ("t5xxl_fp8_e4m3fn.safetensors", "t5xxl_fp16.safetensors", "
|
||||
_SDXL_CLIP_L_PATTERNS = ("clip_l.safetensors", "clip_l", "clip-l")
|
||||
_SDXL_CLIP_G_PATTERNS = ("clip_g.safetensors", "clip_g", "clip-g")
|
||||
_FLUX_VAE_PATTERNS = ("ae.safetensors", "ae", "vae")
|
||||
_FLUX2_QWEN_PATTERNS = ("qwen_3_8b.safetensors", "qwen_3_8b_fp8mixed.safetensors", "qwen_3_8b")
|
||||
_FLUX2_VAE_PATTERNS = ("flux2-vae.safetensors", "flux2-vae", "flux2_vae")
|
||||
|
||||
|
||||
def _build_capability_tags(model_name: str, family: str) -> dict[str, object]:
|
||||
@@ -226,6 +229,12 @@ def _load_external_text_encoder(family: str, name1: str, name2: str | None):
|
||||
raise RuntimeError("[LLS] ComfyUI core CLIPLoader class was not found.")
|
||||
return clip_loader_cls().load_clip(name1, type="stable_diffusion")[0]
|
||||
|
||||
if is_flux2_family(family):
|
||||
clip_loader_cls = getattr(comfy_core_nodes, "CLIPLoader", None)
|
||||
if clip_loader_cls is None:
|
||||
raise RuntimeError("[LLS] ComfyUI core CLIPLoader class was not found.")
|
||||
return clip_loader_cls().load_clip(name1, type="flux2")[0]
|
||||
|
||||
dual_loader_cls = getattr(comfy_core_nodes, "DualCLIPLoader", None)
|
||||
if dual_loader_cls is None:
|
||||
raise RuntimeError("[LLS] ComfyUI core DualCLIPLoader class was not found.")
|
||||
@@ -255,6 +264,10 @@ def _resolve_external_text_encoder_names(
|
||||
return name1, None
|
||||
return (_match_file(available, _SDXL_CLIP_L_PATTERNS) or available[0] if available else None, None)
|
||||
|
||||
if is_flux2_family(family):
|
||||
resolved_1 = name1 or _match_file(available, _FLUX2_QWEN_PATTERNS)
|
||||
return resolved_1, None
|
||||
|
||||
if is_sdxl_family(family):
|
||||
resolved_1 = name1 or _match_file(available, _SDXL_CLIP_L_PATTERNS)
|
||||
resolved_2 = name2 or _match_file(available, _SDXL_CLIP_G_PATTERNS)
|
||||
@@ -269,6 +282,8 @@ def _resolve_external_vae_name(family: str, name: str | None) -> str | None:
|
||||
if name:
|
||||
return name
|
||||
available = _get_filename_list("vae")
|
||||
if is_flux2_family(family):
|
||||
return _match_file(available, _FLUX2_VAE_PATTERNS)
|
||||
if is_flux_family(family):
|
||||
return _match_file(available, _FLUX_VAE_PATTERNS)
|
||||
return available[0] if available else None
|
||||
@@ -285,6 +300,11 @@ def _missing_text_encoder_error(family: str, missing_role: str) -> RuntimeError:
|
||||
f"[LLS] Missing SDXL text encoder {filename}. "
|
||||
"Place it in ComfyUI/models/text_encoders/."
|
||||
)
|
||||
if is_flux2_family(family):
|
||||
return RuntimeError(
|
||||
"[LLS] Missing Flux2/Klein text encoder qwen_3_8b.safetensors "
|
||||
"or qwen_3_8b_fp8mixed.safetensors. Place one of them in ComfyUI/models/text_encoders/."
|
||||
)
|
||||
filename = "clip_l.safetensors" if missing_role == "clip_l" else "t5xxl_fp8_e4m3fn.safetensors"
|
||||
fallback = (
|
||||
"[LLS] Missing FLUX text encoder t5xxl_fp8_e4m3fn.safetensors or t5xxl_fp16.safetensors. "
|
||||
@@ -325,6 +345,11 @@ def _resolve_text_encoder(
|
||||
raise _missing_text_encoder_error(family, "clip")
|
||||
return _load_external_text_encoder(family, resolved_1, None), "external", resolved_1, None
|
||||
|
||||
if is_flux2_family(family):
|
||||
if not resolved_1:
|
||||
raise _missing_text_encoder_error(family, "qwen_3_8b")
|
||||
return _load_external_text_encoder(family, resolved_1, None), "external", resolved_1, None
|
||||
|
||||
required_role_1 = "clip_l"
|
||||
required_role_2 = "clip_g" if is_sdxl_family(family) else "t5xxl"
|
||||
if not resolved_1:
|
||||
@@ -367,6 +392,11 @@ def _resolve_vae(
|
||||
if resolved_vae_name:
|
||||
return _load_external_vae(resolved_vae_name), "external", resolved_vae_name
|
||||
|
||||
if is_flux2_family(family):
|
||||
raise RuntimeError(
|
||||
"[LLS] Missing Flux2/Klein VAE flux2-vae.safetensors. Place it in ComfyUI/models/vae/."
|
||||
)
|
||||
|
||||
if is_flux_family(family):
|
||||
raise RuntimeError(
|
||||
"[LLS] Missing FLUX AE/VAE ae.safetensors. Place it in ComfyUI/models/vae/."
|
||||
|
||||
@@ -16,6 +16,12 @@ class TestExampleWorkflows(unittest.TestCase):
|
||||
return node
|
||||
self.fail(f"Missing node type {node_type!r} in workflow")
|
||||
|
||||
def _find_input(self, node: dict, name: str) -> dict:
|
||||
for item in node.get("inputs", []):
|
||||
if item.get("name") == name:
|
||||
return item
|
||||
self.fail(f"Missing input {name!r} in node {node.get('type')!r}")
|
||||
|
||||
def test_universal_txt2img_ksampler_keeps_seed_control_widget(self):
|
||||
workflow = self._load("LLS-universal-txt2img-workflow.json")
|
||||
node = self._find_node(workflow, "LLSSimpleKSampler")
|
||||
@@ -36,6 +42,33 @@ class TestExampleWorkflows(unittest.TestCase):
|
||||
self.assertEqual(widgets[2], "randomize")
|
||||
self.assertEqual(widgets[3], 20)
|
||||
|
||||
def test_flux2klein_background_replace_workflow_uses_lls_edit_and_flux2_stack(self):
|
||||
workflow = self._load("LLS-Flux2Klein-电商换背景工作流.json")
|
||||
|
||||
encode = self._find_node(workflow, "LLSFlux2KleinEditTextEncode")
|
||||
unet = self._find_node(workflow, "UNETLoader")
|
||||
clip = self._find_node(workflow, "CLIPLoader")
|
||||
vae = self._find_node(workflow, "VAELoader")
|
||||
self._find_node(workflow, "RMBG")
|
||||
self._find_node(workflow, "InvertMask")
|
||||
self._find_node(workflow, "ConditioningZeroOut")
|
||||
self._find_node(workflow, "KSampler")
|
||||
self._find_node(workflow, "VAEDecode")
|
||||
|
||||
self.assertEqual(unet.get("widgets_values", [None])[0], "flux-2-klein-9b.safetensors")
|
||||
self.assertEqual(clip.get("widgets_values", [None, None])[1], "flux2")
|
||||
self.assertEqual(vae.get("widgets_values", [None])[0], "flux2-vae.safetensors")
|
||||
|
||||
widgets = encode.get("widgets_values", [])
|
||||
self.assertGreaterEqual(len(widgets), 4)
|
||||
self.assertEqual(widgets[2], "longest_edge")
|
||||
self.assertEqual(widgets[3], "use_mask")
|
||||
|
||||
self.assertIsNotNone(self._find_input(encode, "image1").get("link"))
|
||||
self.assertIsNotNone(self._find_input(encode, "image2").get("link"))
|
||||
self.assertIsNone(self._find_input(encode, "image3").get("link"))
|
||||
self.assertIsNotNone(self._find_input(encode, "mask").get("link"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -12,6 +12,8 @@ try:
|
||||
FakeMask,
|
||||
FakeVAE,
|
||||
FakeTensor,
|
||||
NativeEditModelStub,
|
||||
NativeFluxStub,
|
||||
StandardClipStub,
|
||||
import_plugin_submodule,
|
||||
load_plugin_package,
|
||||
@@ -22,6 +24,8 @@ except ImportError:
|
||||
FakeMask,
|
||||
FakeVAE,
|
||||
FakeTensor,
|
||||
NativeEditModelStub,
|
||||
NativeFluxStub,
|
||||
StandardClipStub,
|
||||
import_plugin_submodule,
|
||||
load_plugin_package,
|
||||
@@ -137,6 +141,39 @@ class TestFlux2KleinNode(unittest.TestCase):
|
||||
self.assertNotIn("noise_mask", latent)
|
||||
self.assertEqual(custom_output["latent_has_noise_mask"], False)
|
||||
|
||||
def test_flux2_official_path_uses_empty_latent_and_reference_latent_nodes(self):
|
||||
NativeFluxStub.reset()
|
||||
NativeEditModelStub.reset()
|
||||
|
||||
with mock.patch.object(self.module, "native_flux_nodes", NativeFluxStub, create=True), mock.patch.object(
|
||||
self.module,
|
||||
"native_edit_model_nodes",
|
||||
NativeEditModelStub,
|
||||
create=True,
|
||||
):
|
||||
conditioning, latent, custom_output, main_image, output_mask = self.node.encode(
|
||||
clip=StandardClipStub(),
|
||||
vae=FakeVAE(latent_channels=128, downscale_ratio=16),
|
||||
image1=FakeTensor((1, 832, 1248, 3), label="main"),
|
||||
prompt="replace background with a clean kitchen scene",
|
||||
ref_longest_edge=1248,
|
||||
resize_mode="keep_original",
|
||||
mask_mode="use_mask",
|
||||
image2=FakeTensor((1, 640, 640, 3), label="ref2"),
|
||||
image3=None,
|
||||
mask=FakeMask((1, 832, 1248), mask_bbox=(50, 40, 500, 700), mask_area_ratio=0.35, label="mask"),
|
||||
)
|
||||
|
||||
self.assertEqual(NativeFluxStub.last_empty_call, {"width": 1248, "height": 832, "batch_size": 1})
|
||||
self.assertEqual(len(NativeEditModelStub.last_calls), 2)
|
||||
self.assertEqual(latent["samples"].shape, (1, 128, 52, 78))
|
||||
self.assertEqual(latent["noise_mask"].shape, (1, 52, 78))
|
||||
self.assertEqual(custom_output["latent_mode"], "empty_flux2_latent")
|
||||
self.assertEqual(custom_output["conditioning_backend"], "flux2klein_multivision_clip+reference_latent")
|
||||
self.assertEqual(custom_output["reference_latent_count"], 2)
|
||||
self.assertEqual(main_image.shape, (1, 832, 1248, 3))
|
||||
self.assertEqual(output_mask.shape, (1, 832, 1248))
|
||||
|
||||
def test_missing_clip_backend_raises_clear_error(self):
|
||||
with self.assertRaisesRegex(RuntimeError, "vision-aware|text encoding backend"):
|
||||
self.node.encode(
|
||||
|
||||
@@ -448,6 +448,43 @@ class TestLoaderPromptRefactor(unittest.TestCase):
|
||||
self.assertEqual(payload["text_encoder_name"], "clip_l.safetensors, t5xxl_fp16.safetensors")
|
||||
self.assertEqual(payload["vae_name"], "ae.safetensors")
|
||||
|
||||
def test_universal_loader_loads_flux2_klein_with_qwen_and_flux2_vae(self):
|
||||
load_plugin_package()
|
||||
from lls_node_test_refactor.model_loader import nodes as loader_nodes
|
||||
|
||||
folder_paths = FolderPathsStub()
|
||||
folder_paths._files["diffusion_models"].append("flux-2-klein-9b.safetensors")
|
||||
folder_paths._files["text_encoders"].append("qwen_3_8b.safetensors")
|
||||
folder_paths._files["vae"].append("flux2-vae.safetensors")
|
||||
|
||||
with mock.patch.object(loader_nodes, "folder_paths", folder_paths), mock.patch.object(
|
||||
loader_nodes,
|
||||
"comfy_sd",
|
||||
ComfySDStub(),
|
||||
), mock.patch.object(loader_nodes, "comfy_core_nodes", CoreNodesStub()):
|
||||
node = loader_nodes.LLSUniversalModelLoader()
|
||||
model, text_encoder, vae, model_info = node.load(
|
||||
"diffusion_models/flux-2-klein-9b.safetensors",
|
||||
"Auto",
|
||||
"advanced",
|
||||
"external",
|
||||
"external",
|
||||
"qwen_3_8b.safetensors",
|
||||
"(auto)",
|
||||
"flux2-vae.safetensors",
|
||||
)
|
||||
|
||||
payload = json.loads(model_info)
|
||||
self.assertEqual(model.label, "MODEL::flux-2-klein-9b.safetensors")
|
||||
self.assertEqual(text_encoder.label, "CLIP::flux2::qwen_3_8b.safetensors")
|
||||
self.assertEqual(vae.label, "VAE::flux2-vae.safetensors")
|
||||
self.assertEqual(payload["model_family"], "FLUX2_KLEIN")
|
||||
self.assertEqual(payload["text_encoder_name_1"], "qwen_3_8b.safetensors")
|
||||
self.assertEqual(payload["text_encoder_name_2"], "")
|
||||
self.assertEqual(payload["text_encoder_name"], "qwen_3_8b.safetensors")
|
||||
self.assertEqual(payload["vae_name"], "flux2-vae.safetensors")
|
||||
self.assertEqual(text_encoder._lls_text_encoder_type, "flux2_qwen")
|
||||
|
||||
def test_loader_raises_clear_error_when_flux_text_encoder_is_missing(self):
|
||||
load_plugin_package()
|
||||
from lls_node_test_refactor.model_loader import nodes as loader_nodes
|
||||
|
||||
+78
-1
@@ -19,6 +19,9 @@ LEGACY_FAMILY_ALIASES: dict[str, str] = {
|
||||
"FLUX": "FLUX_DEV",
|
||||
"FLUX_SCHNELL": "FLUX_SCHNELL",
|
||||
"FLUX_DEV": "FLUX_DEV",
|
||||
"FLUX2": "FLUX2_DEV",
|
||||
"FLUX2_DEV": "FLUX2_DEV",
|
||||
"FLUX2_KLEIN": "FLUX2_KLEIN",
|
||||
}
|
||||
|
||||
MODEL_FAMILY_CHOICES: list[str] = [
|
||||
@@ -29,6 +32,8 @@ MODEL_FAMILY_CHOICES: list[str] = [
|
||||
"SDXL_TURBO",
|
||||
"FLUX_SCHNELL",
|
||||
"FLUX_DEV",
|
||||
"FLUX2_DEV",
|
||||
"FLUX2_KLEIN",
|
||||
]
|
||||
|
||||
FAMILY_DEFAULTS: dict[str, dict[str, Any]] = {
|
||||
@@ -122,6 +127,42 @@ FAMILY_DEFAULTS: dict[str, dict[str, Any]] = {
|
||||
"is_turbo": False,
|
||||
"is_flux": True,
|
||||
},
|
||||
"FLUX2_DEV": {
|
||||
"text_encoder_type": "flux2_qwen",
|
||||
"required_text_encoders": ["qwen_3_8b"],
|
||||
"required_vae": "required",
|
||||
"latent_channels": 128,
|
||||
"downscale_ratio": 16,
|
||||
"default_width": 1024,
|
||||
"default_height": 1024,
|
||||
"default_steps": 20,
|
||||
"default_cfg": 1.0,
|
||||
"default_guidance": 3.5,
|
||||
"default_sampler": "euler",
|
||||
"default_scheduler": "simple",
|
||||
"default_denoise": 1.0,
|
||||
"guidance_embed": True,
|
||||
"is_turbo": False,
|
||||
"is_flux": True,
|
||||
},
|
||||
"FLUX2_KLEIN": {
|
||||
"text_encoder_type": "flux2_qwen",
|
||||
"required_text_encoders": ["qwen_3_8b"],
|
||||
"required_vae": "required",
|
||||
"latent_channels": 128,
|
||||
"downscale_ratio": 16,
|
||||
"default_width": 1024,
|
||||
"default_height": 1024,
|
||||
"default_steps": 20,
|
||||
"default_cfg": 1.0,
|
||||
"default_guidance": 3.5,
|
||||
"default_sampler": "euler",
|
||||
"default_scheduler": "simple",
|
||||
"default_denoise": 1.0,
|
||||
"guidance_embed": True,
|
||||
"is_turbo": False,
|
||||
"is_flux": True,
|
||||
},
|
||||
}
|
||||
|
||||
SAMPLING_PRESETS: dict[str, dict[str, dict[str, float | int | None]]] = {
|
||||
@@ -190,6 +231,32 @@ SAMPLING_PRESETS: dict[str, dict[str, dict[str, float | int | None]]] = {
|
||||
"Balanced": {"steps": 20, "cfg": 1.0, "guidance": 3.5, "sampler_name": "euler", "scheduler": "simple", "denoise": 1.0},
|
||||
"High Quality": {"steps": 28, "cfg": 1.0, "guidance": 3.5, "sampler_name": "euler", "scheduler": "simple", "denoise": 1.0},
|
||||
},
|
||||
"FLUX2_DEV": {
|
||||
FAMILY_DEFAULT_PRESET: {
|
||||
"steps": 20,
|
||||
"cfg": 1.0,
|
||||
"guidance": 3.5,
|
||||
"sampler_name": "euler",
|
||||
"scheduler": "simple",
|
||||
"denoise": 1.0,
|
||||
},
|
||||
"Fast": {"steps": 12, "cfg": 1.0, "guidance": 3.5, "sampler_name": "euler", "scheduler": "simple", "denoise": 1.0},
|
||||
"Balanced": {"steps": 20, "cfg": 1.0, "guidance": 3.5, "sampler_name": "euler", "scheduler": "simple", "denoise": 1.0},
|
||||
"High Quality": {"steps": 28, "cfg": 1.0, "guidance": 3.5, "sampler_name": "euler", "scheduler": "simple", "denoise": 1.0},
|
||||
},
|
||||
"FLUX2_KLEIN": {
|
||||
FAMILY_DEFAULT_PRESET: {
|
||||
"steps": 20,
|
||||
"cfg": 1.0,
|
||||
"guidance": 3.5,
|
||||
"sampler_name": "euler",
|
||||
"scheduler": "simple",
|
||||
"denoise": 1.0,
|
||||
},
|
||||
"Fast": {"steps": 12, "cfg": 1.0, "guidance": 3.5, "sampler_name": "euler", "scheduler": "simple", "denoise": 1.0},
|
||||
"Balanced": {"steps": 20, "cfg": 1.0, "guidance": 3.5, "sampler_name": "euler", "scheduler": "simple", "denoise": 1.0},
|
||||
"High Quality": {"steps": 28, "cfg": 1.0, "guidance": 3.5, "sampler_name": "euler", "scheduler": "simple", "denoise": 1.0},
|
||||
},
|
||||
}
|
||||
|
||||
_LEGACY_MODEL_INFO_PATTERN = re.compile(r"(\w+)=([^|]+)")
|
||||
@@ -219,6 +286,10 @@ def infer_family_from_name(model_name: str | None, fallback: str = "SD1.5") -> s
|
||||
return canonicalize_family(fallback)
|
||||
|
||||
name = str(model_name).lower()
|
||||
if "flux-2" in name or "flux2" in name or "flux.2" in name:
|
||||
if "klein" in name:
|
||||
return "FLUX2_KLEIN"
|
||||
return "FLUX2_DEV"
|
||||
if "flux" in name:
|
||||
if "schnell" in name:
|
||||
return "FLUX_SCHNELL"
|
||||
@@ -231,7 +302,11 @@ def infer_family_from_name(model_name: str | None, fallback: str = "SD1.5") -> s
|
||||
|
||||
|
||||
def is_flux_family(family: str | None) -> bool:
|
||||
return canonicalize_family(family) in {"FLUX_SCHNELL", "FLUX_DEV"}
|
||||
return canonicalize_family(family) in {"FLUX_SCHNELL", "FLUX_DEV", "FLUX2_DEV", "FLUX2_KLEIN"}
|
||||
|
||||
|
||||
def is_flux2_family(family: str | None) -> bool:
|
||||
return canonicalize_family(family) in {"FLUX2_DEV", "FLUX2_KLEIN"}
|
||||
|
||||
|
||||
def is_sdxl_family(family: str | None) -> bool:
|
||||
@@ -460,6 +535,8 @@ def infer_family_from_clip(clip) -> str:
|
||||
tokens = clip.tokenize("")
|
||||
except Exception:
|
||||
return "SD1.5"
|
||||
if "qwen" in getattr(clip, "_lls_text_encoder_type", ""):
|
||||
return "FLUX2_KLEIN"
|
||||
if "t5xxl" in tokens:
|
||||
return "FLUX_DEV"
|
||||
if "g" in tokens:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+3944
-436
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user