重新设计模型加载节点
This commit is contained in:
@@ -0,0 +1,668 @@
|
||||
{
|
||||
"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,
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,552 @@
|
||||
{
|
||||
"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,
|
||||
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
|
||||
}
|
||||
@@ -13,6 +13,7 @@ from ..utils.model_info import (
|
||||
info_to_json,
|
||||
is_flux_family,
|
||||
is_sdxl_family,
|
||||
parse_jsonish_info,
|
||||
resolve_model_family,
|
||||
)
|
||||
|
||||
@@ -221,10 +222,112 @@ class LLSSimplePromptEncode:
|
||||
return (positive, negative, prompt_info)
|
||||
|
||||
|
||||
class LLSUniversalPromptEncode:
|
||||
"""
|
||||
统一文本编码节点。
|
||||
- 只公开一个 `text_encoder` 输入
|
||||
- SDXL / FLUX 的双编码器在 Loader 内部组装,对下游透明
|
||||
- 可选 `model_info` 用于明确 family / checkpoint / encoder metadata
|
||||
"""
|
||||
|
||||
CATEGORY = "LLS/Conditioning"
|
||||
FUNCTION = "encode"
|
||||
RETURN_TYPES = ("CONDITIONING", "CONDITIONING", "STRING")
|
||||
RETURN_NAMES = ("positive", "negative", "prompt_info")
|
||||
DESCRIPTION = (
|
||||
"Encode prompts using one text_encoder input across SD1.5, SDXL, and FLUX families."
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"text_encoder": ("CLIP",),
|
||||
"positive_prompt": ("STRING", {"default": "", "multiline": True}),
|
||||
"negative_prompt": ("STRING", {"default": "", "multiline": True}),
|
||||
"clip_skip": (_CLIP_SKIP_CHOICES, {"default": -1}),
|
||||
},
|
||||
"optional": {
|
||||
"model_info": ("STRING",),
|
||||
},
|
||||
}
|
||||
|
||||
def encode(
|
||||
self,
|
||||
text_encoder,
|
||||
positive_prompt: str = "",
|
||||
negative_prompt: str = "",
|
||||
clip_skip=-1,
|
||||
model_info=None,
|
||||
):
|
||||
info = parse_jsonish_info(model_info)
|
||||
family_hint = str(info.get("model_family") or info.get("family") or "Auto")
|
||||
family = resolve_model_family(family_hint, clip=text_encoder)
|
||||
defaults = get_family_defaults(family)
|
||||
clip_skip = _normalize_clip_skip(clip_skip)
|
||||
encoder = text_encoder
|
||||
if is_flux_family(family):
|
||||
clip_skip = -1
|
||||
|
||||
if clip_skip != -1:
|
||||
try:
|
||||
encoder = encoder.clone()
|
||||
encoder.clip_layer(clip_skip)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
negative_mode = "standard"
|
||||
negative_for_encode = negative_prompt
|
||||
|
||||
if family == "SDXL_TURBO" and negative_prompt.strip():
|
||||
negative_for_encode = ""
|
||||
negative_mode = "weakened_for_turbo"
|
||||
|
||||
try:
|
||||
if is_flux_family(family):
|
||||
guidance = defaults.get("default_guidance")
|
||||
positive = _encode_flux_prompt(encoder, positive_prompt, guidance)
|
||||
negative = _encode_flux_prompt(encoder, "", guidance)
|
||||
negative_mode = "ignored_for_flux"
|
||||
elif is_sdxl_family(family):
|
||||
width = int(defaults.get("default_width", 1024))
|
||||
height = int(defaults.get("default_height", 1024))
|
||||
positive = _encode_sdxl_prompt(encoder, positive_prompt, width, height)
|
||||
negative = _encode_sdxl_prompt(encoder, negative_for_encode, width, height)
|
||||
else:
|
||||
positive = _encode_standard_prompt(encoder, positive_prompt)
|
||||
negative = _encode_standard_prompt(encoder, negative_for_encode)
|
||||
except Exception as exc:
|
||||
raise RuntimeError(f"[LLS] Failed to encode prompts for family {family}: {exc}") from exc
|
||||
|
||||
prompt_mode = "flux" if is_flux_family(family) else "sdxl" if is_sdxl_family(family) else "clip"
|
||||
prompt_info = info_to_json(
|
||||
{
|
||||
"model_family": family,
|
||||
"checkpoint_name": info.get("checkpoint_name") or info.get("model_name") or "",
|
||||
"text_encoder_type": info.get("text_encoder_type") or defaults.get("text_encoder_type", "clip"),
|
||||
"text_encoder_name": info.get("text_encoder_name") or "",
|
||||
"text_encoder_name_1": info.get("text_encoder_name_1") or "",
|
||||
"text_encoder_name_2": info.get("text_encoder_name_2") or "",
|
||||
"positive_prompt": positive_prompt,
|
||||
"negative_prompt": negative_prompt,
|
||||
"prompt_mode": prompt_mode,
|
||||
"positive_prompt_length": len(positive_prompt),
|
||||
"negative_prompt_length": len(negative_prompt),
|
||||
"clip_skip": clip_skip,
|
||||
"negative_mode": negative_mode,
|
||||
"guidance": defaults.get("default_guidance") if is_flux_family(family) else None,
|
||||
}
|
||||
)
|
||||
return (positive, negative, prompt_info)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS: dict[str, type] = {
|
||||
"LLSSimplePromptEncode": LLSSimplePromptEncode,
|
||||
"LLSUniversalPromptEncode": LLSUniversalPromptEncode,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS: dict[str, str] = {
|
||||
"LLSSimplePromptEncode": "LLS Simple Prompt Encode",
|
||||
"LLSUniversalPromptEncode": "LLS Universal Prompt Encode",
|
||||
}
|
||||
|
||||
+175
-73
@@ -39,6 +39,7 @@ from ..utils.model_info import (
|
||||
MODEL_FAMILY_CHOICES,
|
||||
canonicalize_family,
|
||||
get_family_defaults,
|
||||
info_to_json,
|
||||
infer_family_from_name,
|
||||
is_flux_family,
|
||||
is_sdxl_family,
|
||||
@@ -53,6 +54,8 @@ NO_TEXT_ENCODER_PLACEHOLDER = "(no text encoders found)"
|
||||
LOAD_MODE_CHOICES = ["simple", "advanced"]
|
||||
VAE_SOURCE_CHOICES = ["auto", "embedded", "external", "none"]
|
||||
TEXT_ENCODER_SOURCE_CHOICES = ["auto", "embedded", "external", "manual"]
|
||||
UNIVERSAL_VAE_SOURCE_CHOICES = ["auto", "embedded", "external"]
|
||||
UNIVERSAL_TEXT_ENCODER_SOURCE_CHOICES = ["auto", "embedded", "external"]
|
||||
|
||||
_FLUX_CLIP_L_PATTERNS = ("clip_l.safetensors", "clip_l", "clip-l")
|
||||
_FLUX_T5_PATTERNS = ("t5xxl_fp8_e4m3fn.safetensors", "t5xxl_fp16.safetensors", "t5xxl", "t5")
|
||||
@@ -371,6 +374,120 @@ def _resolve_vae(
|
||||
return None, "none", None
|
||||
|
||||
|
||||
def _resolve_loader_family(model_name: str, model_family: str) -> str:
|
||||
if model_family == "Auto":
|
||||
return infer_family_from_name(model_name, "SD1.5")
|
||||
return canonicalize_family(model_family)
|
||||
|
||||
|
||||
def _load_tagged_resources(
|
||||
*,
|
||||
model_name: str,
|
||||
model_family: str,
|
||||
load_mode: str,
|
||||
vae_source: str,
|
||||
text_encoder_source: str,
|
||||
vae_name: str,
|
||||
text_encoder_name_1: str,
|
||||
text_encoder_name_2: str,
|
||||
):
|
||||
if folder_paths is None:
|
||||
raise RuntimeError(
|
||||
"[LLS] folder_paths is not available. Make sure this node runs inside ComfyUI."
|
||||
) from _FOLDER_PATHS_ERR
|
||||
if comfy_sd is None:
|
||||
raise RuntimeError(
|
||||
"[LLS] comfy.sd is not available. Make sure this node runs inside ComfyUI."
|
||||
) from _COMFY_SD_ERR
|
||||
|
||||
family = _resolve_loader_family(model_name, model_family)
|
||||
model_source, model_path = _resolve_model_path(model_name, family)
|
||||
model, embedded_text_encoder, embedded_vae = _load_model(model_source, model_path)
|
||||
if model is None:
|
||||
raise RuntimeError(f"[LLS] The selected model '{model_name}' did not produce a valid diffusion model.")
|
||||
|
||||
external_vae_name = _normalize_choice(vae_name, NO_VAE_PLACEHOLDER)
|
||||
external_text_encoder_1 = _normalize_choice(text_encoder_name_1, NO_TEXT_ENCODER_PLACEHOLDER)
|
||||
external_text_encoder_2 = _normalize_choice(text_encoder_name_2, NO_TEXT_ENCODER_PLACEHOLDER)
|
||||
|
||||
text_encoder, resolved_text_encoder_source, resolved_te_1, resolved_te_2 = _resolve_text_encoder(
|
||||
family=family,
|
||||
source=text_encoder_source,
|
||||
embedded_text_encoder=embedded_text_encoder,
|
||||
external_name_1=external_text_encoder_1,
|
||||
external_name_2=external_text_encoder_2,
|
||||
)
|
||||
vae, resolved_vae_source, resolved_vae_name = _resolve_vae(
|
||||
family=family,
|
||||
source=vae_source,
|
||||
embedded_vae=embedded_vae,
|
||||
external_vae_name=external_vae_name,
|
||||
)
|
||||
|
||||
defaults = get_family_defaults(family)
|
||||
capability_tags = _build_capability_tags(model_name, family)
|
||||
resolved_text_encoder_name = resolved_te_1 or ("embedded" if text_encoder is not None else None)
|
||||
resolved_text_encoder_name_1 = resolved_te_1 or ("embedded" if text_encoder is not None and not resolved_te_2 else None)
|
||||
resolved_text_encoder_name_2 = resolved_te_2
|
||||
if resolved_te_1 and resolved_te_2:
|
||||
resolved_text_encoder_name = ", ".join([resolved_te_1, resolved_te_2])
|
||||
resolved_vae_label = resolved_vae_name or ("embedded" if vae is not None else None)
|
||||
|
||||
tag_lls_object(
|
||||
model,
|
||||
family=family,
|
||||
model_name=model_name,
|
||||
checkpoint_name=model_name,
|
||||
load_mode=load_mode,
|
||||
**capability_tags,
|
||||
)
|
||||
tag_lls_object(
|
||||
text_encoder,
|
||||
family=family,
|
||||
model_name=model_name,
|
||||
checkpoint_name=model_name,
|
||||
text_encoder_type=defaults["text_encoder_type"],
|
||||
text_encoder_source=resolved_text_encoder_source,
|
||||
text_encoder_name=resolved_text_encoder_name,
|
||||
text_encoder_name_1=resolved_text_encoder_name_1,
|
||||
text_encoder_name_2=resolved_text_encoder_name_2,
|
||||
**capability_tags,
|
||||
)
|
||||
tag_lls_object(
|
||||
vae,
|
||||
family=family,
|
||||
model_name=model_name,
|
||||
checkpoint_name=model_name,
|
||||
vae_name=resolved_vae_label,
|
||||
vae_source=resolved_vae_source,
|
||||
**capability_tags,
|
||||
)
|
||||
|
||||
model_info = {
|
||||
"model_family": family,
|
||||
"checkpoint_name": model_name,
|
||||
"model_name": model_name,
|
||||
"load_mode": load_mode,
|
||||
"model_source": model_source,
|
||||
"profile_id": capability_tags["profile_id"],
|
||||
"backend_type": capability_tags["backend_type"],
|
||||
"sampler_strategy": capability_tags["sampler_strategy"],
|
||||
"loader_strategy": capability_tags["loader_strategy"],
|
||||
"model_role": capability_tags["model_role"],
|
||||
"supports_inpaint_native": capability_tags["supports_inpaint_native"],
|
||||
"supports_image_edit_native": capability_tags["supports_image_edit_native"],
|
||||
"preferred_edit_backend": capability_tags["preferred_edit_backend"],
|
||||
"text_encoder_type": defaults["text_encoder_type"],
|
||||
"text_encoder_source": resolved_text_encoder_source,
|
||||
"text_encoder_name": resolved_text_encoder_name or "",
|
||||
"text_encoder_name_1": resolved_text_encoder_name_1 or "",
|
||||
"text_encoder_name_2": resolved_text_encoder_name_2 or "",
|
||||
"vae_name": resolved_vae_label or "",
|
||||
"vae_source": resolved_vae_source,
|
||||
}
|
||||
return model, text_encoder, vae, model_info
|
||||
|
||||
|
||||
class LLSSimpleCheckpointLoader:
|
||||
"""
|
||||
统一封装的基础模型加载器。
|
||||
@@ -418,89 +535,74 @@ class LLSSimpleCheckpointLoader:
|
||||
external_text_encoder_1: str,
|
||||
external_text_encoder_2: str,
|
||||
):
|
||||
if folder_paths is None:
|
||||
raise RuntimeError(
|
||||
"[LLS] folder_paths is not available. Make sure this node runs inside ComfyUI."
|
||||
) from _FOLDER_PATHS_ERR
|
||||
if comfy_sd is None:
|
||||
raise RuntimeError(
|
||||
"[LLS] comfy.sd is not available. Make sure this node runs inside ComfyUI."
|
||||
) from _COMFY_SD_ERR
|
||||
|
||||
if model_family == "Auto":
|
||||
family = infer_family_from_name(ckpt_name, "SD1.5")
|
||||
else:
|
||||
family = canonicalize_family(model_family)
|
||||
|
||||
model_source, model_path = _resolve_model_path(ckpt_name, family)
|
||||
model, embedded_text_encoder, embedded_vae = _load_model(model_source, model_path)
|
||||
if model is None:
|
||||
raise RuntimeError(f"[LLS] The selected model '{ckpt_name}' did not produce a valid diffusion model.")
|
||||
|
||||
external_vae_name = _normalize_choice(external_vae_name, NO_VAE_PLACEHOLDER)
|
||||
external_text_encoder_1 = _normalize_choice(external_text_encoder_1, NO_TEXT_ENCODER_PLACEHOLDER)
|
||||
external_text_encoder_2 = _normalize_choice(external_text_encoder_2, NO_TEXT_ENCODER_PLACEHOLDER)
|
||||
|
||||
text_encoder, resolved_text_encoder_source, resolved_te_1, resolved_te_2 = _resolve_text_encoder(
|
||||
family=family,
|
||||
source=text_encoder_source,
|
||||
embedded_text_encoder=embedded_text_encoder,
|
||||
external_name_1=external_text_encoder_1,
|
||||
external_name_2=external_text_encoder_2,
|
||||
)
|
||||
vae, resolved_vae_source, resolved_vae_name = _resolve_vae(
|
||||
family=family,
|
||||
source=vae_source,
|
||||
embedded_vae=embedded_vae,
|
||||
external_vae_name=external_vae_name,
|
||||
)
|
||||
|
||||
defaults = get_family_defaults(family)
|
||||
capability_tags = _build_capability_tags(ckpt_name, family)
|
||||
resolved_text_encoder_name = resolved_te_1 or ("embedded" if text_encoder is not None else None)
|
||||
resolved_text_encoder_name_1 = resolved_te_1 or ("embedded" if text_encoder is not None and not resolved_te_2 else None)
|
||||
resolved_text_encoder_name_2 = resolved_te_2
|
||||
if resolved_te_1 and resolved_te_2:
|
||||
resolved_text_encoder_name = ", ".join([resolved_te_1, resolved_te_2])
|
||||
resolved_vae_label = resolved_vae_name or ("embedded" if vae is not None else None)
|
||||
|
||||
tag_lls_object(
|
||||
model,
|
||||
family=family,
|
||||
model, text_encoder, vae, _model_info = _load_tagged_resources(
|
||||
model_name=ckpt_name,
|
||||
checkpoint_name=ckpt_name,
|
||||
model_family=model_family,
|
||||
load_mode=load_mode,
|
||||
**capability_tags,
|
||||
vae_source=vae_source,
|
||||
text_encoder_source=text_encoder_source,
|
||||
vae_name=external_vae_name,
|
||||
text_encoder_name_1=external_text_encoder_1,
|
||||
text_encoder_name_2=external_text_encoder_2,
|
||||
)
|
||||
tag_lls_object(
|
||||
text_encoder,
|
||||
family=family,
|
||||
model_name=ckpt_name,
|
||||
checkpoint_name=ckpt_name,
|
||||
text_encoder_type=defaults["text_encoder_type"],
|
||||
text_encoder_source=resolved_text_encoder_source,
|
||||
text_encoder_name=resolved_text_encoder_name,
|
||||
text_encoder_name_1=resolved_text_encoder_name_1,
|
||||
text_encoder_name_2=resolved_text_encoder_name_2,
|
||||
**capability_tags,
|
||||
)
|
||||
tag_lls_object(
|
||||
vae,
|
||||
family=family,
|
||||
model_name=ckpt_name,
|
||||
checkpoint_name=ckpt_name,
|
||||
vae_name=resolved_vae_label,
|
||||
vae_source=resolved_vae_source,
|
||||
**capability_tags,
|
||||
)
|
||||
|
||||
return (model, text_encoder, vae, text_encoder)
|
||||
|
||||
|
||||
class LLSUniversalModelLoader:
|
||||
CATEGORY = "LLS/Model Loader"
|
||||
FUNCTION = "load"
|
||||
RETURN_TYPES = ("MODEL", "CLIP", "VAE", "STRING")
|
||||
RETURN_NAMES = ("model", "text_encoder", "vae", "model_info")
|
||||
DESCRIPTION = (
|
||||
"Unified model loader for SD1.5, SDXL, and FLUX families. "
|
||||
"Internally resolves single or dual text encoders but always exposes one text_encoder output."
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"model_name": (_get_model_name_choices(),),
|
||||
"model_family": (MODEL_FAMILY_CHOICES, {"default": "Auto"}),
|
||||
"load_mode": (LOAD_MODE_CHOICES, {"default": "simple"}),
|
||||
"vae_source": (UNIVERSAL_VAE_SOURCE_CHOICES, {"default": "auto"}),
|
||||
"text_encoder_source": (UNIVERSAL_TEXT_ENCODER_SOURCE_CHOICES, {"default": "auto"}),
|
||||
"text_encoder_1": (_get_text_encoder_choices(), {"default": AUTO_PLACEHOLDER}),
|
||||
"text_encoder_2": (_get_text_encoder_choices(), {"default": AUTO_PLACEHOLDER}),
|
||||
"vae_name": (_get_vae_choices(), {"default": AUTO_PLACEHOLDER}),
|
||||
},
|
||||
}
|
||||
|
||||
def load(
|
||||
self,
|
||||
model_name: str,
|
||||
model_family: str,
|
||||
load_mode: str,
|
||||
vae_source: str,
|
||||
text_encoder_source: str,
|
||||
text_encoder_1: str,
|
||||
text_encoder_2: str,
|
||||
vae_name: str,
|
||||
):
|
||||
model, text_encoder, vae, model_info = _load_tagged_resources(
|
||||
model_name=model_name,
|
||||
model_family=model_family,
|
||||
load_mode=load_mode,
|
||||
vae_source=vae_source,
|
||||
text_encoder_source=text_encoder_source,
|
||||
vae_name=vae_name,
|
||||
text_encoder_name_1=text_encoder_1,
|
||||
text_encoder_name_2=text_encoder_2,
|
||||
)
|
||||
return model, text_encoder, vae, info_to_json(model_info)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS: dict[str, type] = {
|
||||
"LLSSimpleCheckpointLoader": LLSSimpleCheckpointLoader,
|
||||
"LLSUniversalModelLoader": LLSUniversalModelLoader,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS: dict[str, str] = {
|
||||
"LLSSimpleCheckpointLoader": "LLS Simple Checkpoint Loader",
|
||||
"LLSUniversalModelLoader": "LLS Universal Model Loader",
|
||||
}
|
||||
|
||||
@@ -297,6 +297,35 @@ class TestLoaderPromptRefactor(unittest.TestCase):
|
||||
)
|
||||
self.assertNotIn("optional", node_cls.INPUT_TYPES())
|
||||
|
||||
def test_universal_loader_schema_exposes_single_text_encoder_output(self):
|
||||
plugin = load_plugin_package()
|
||||
node_cls = plugin.NODE_CLASS_MAPPINGS["LLSUniversalModelLoader"]
|
||||
required = node_cls.INPUT_TYPES()["required"]
|
||||
|
||||
self.assertEqual(
|
||||
node_cls.RETURN_TYPES,
|
||||
("MODEL", "CLIP", "VAE", "STRING"),
|
||||
)
|
||||
self.assertEqual(
|
||||
node_cls.RETURN_NAMES,
|
||||
("model", "text_encoder", "vae", "model_info"),
|
||||
)
|
||||
self.assertEqual(
|
||||
tuple(required.keys()),
|
||||
(
|
||||
"model_name",
|
||||
"model_family",
|
||||
"load_mode",
|
||||
"vae_source",
|
||||
"text_encoder_source",
|
||||
"text_encoder_1",
|
||||
"text_encoder_2",
|
||||
"vae_name",
|
||||
),
|
||||
)
|
||||
self.assertEqual(required["model_family"][1]["default"], "Auto")
|
||||
self.assertEqual(required["text_encoder_source"][1]["default"], "auto")
|
||||
|
||||
def test_loader_tags_sd15_resources_without_context_output(self):
|
||||
load_plugin_package()
|
||||
from lls_node_test_refactor.model_loader import nodes as loader_nodes
|
||||
@@ -328,6 +357,36 @@ class TestLoaderPromptRefactor(unittest.TestCase):
|
||||
self.assertEqual(clip._lls_text_encoder_type, "clip")
|
||||
self.assertEqual(vae._lls_family, "SD1.5")
|
||||
|
||||
def test_universal_loader_loads_sd15_into_single_text_encoder_port(self):
|
||||
load_plugin_package()
|
||||
from lls_node_test_refactor.model_loader import nodes as loader_nodes
|
||||
|
||||
with mock.patch.object(loader_nodes, "folder_paths", FolderPathsStub()), 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(
|
||||
"sd15.safetensors",
|
||||
"SD1.5",
|
||||
"simple",
|
||||
"auto",
|
||||
"auto",
|
||||
"(auto)",
|
||||
"(auto)",
|
||||
"(auto)",
|
||||
)
|
||||
|
||||
payload = json.loads(model_info)
|
||||
self.assertEqual(model.label, "MODEL::SD15")
|
||||
self.assertEqual(text_encoder.label, "CLIP::SD15")
|
||||
self.assertEqual(vae.label, "VAE::SD15")
|
||||
self.assertEqual(payload["model_family"], "SD1.5")
|
||||
self.assertEqual(payload["checkpoint_name"], "sd15.safetensors")
|
||||
self.assertEqual(payload["text_encoder_source"], "embedded")
|
||||
self.assertEqual(payload["vae_source"], "embedded")
|
||||
|
||||
def test_loader_tags_flux_resources_and_keeps_standard_text_encoder_alias(self):
|
||||
load_plugin_package()
|
||||
from lls_node_test_refactor.model_loader import nodes as loader_nodes
|
||||
@@ -358,6 +417,37 @@ class TestLoaderPromptRefactor(unittest.TestCase):
|
||||
self.assertEqual(clip._lls_model_name, "diffusion_models/flux1-schnell.safetensors")
|
||||
self.assertEqual(vae._lls_vae_name, "ae.safetensors")
|
||||
|
||||
def test_universal_loader_loads_flux_dual_encoders_into_single_text_encoder_port(self):
|
||||
load_plugin_package()
|
||||
from lls_node_test_refactor.model_loader import nodes as loader_nodes
|
||||
|
||||
with mock.patch.object(loader_nodes, "folder_paths", FolderPathsStub()), 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/flux1-schnell.safetensors",
|
||||
"FLUX_SCHNELL",
|
||||
"advanced",
|
||||
"external",
|
||||
"external",
|
||||
"clip_l.safetensors",
|
||||
"t5xxl_fp16.safetensors",
|
||||
"ae.safetensors",
|
||||
)
|
||||
|
||||
payload = json.loads(model_info)
|
||||
self.assertEqual(model.label, "MODEL::flux1-schnell.safetensors")
|
||||
self.assertEqual(text_encoder.label, "CLIP::flux::clip_l.safetensors+t5xxl_fp16.safetensors")
|
||||
self.assertEqual(vae.label, "VAE::ae.safetensors")
|
||||
self.assertEqual(payload["model_family"], "FLUX_SCHNELL")
|
||||
self.assertEqual(payload["text_encoder_name_1"], "clip_l.safetensors")
|
||||
self.assertEqual(payload["text_encoder_name_2"], "t5xxl_fp16.safetensors")
|
||||
self.assertEqual(payload["text_encoder_name"], "clip_l.safetensors, t5xxl_fp16.safetensors")
|
||||
self.assertEqual(payload["vae_name"], "ae.safetensors")
|
||||
|
||||
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
|
||||
@@ -394,6 +484,18 @@ class TestLoaderPromptRefactor(unittest.TestCase):
|
||||
self.assertEqual(optional["clip"][0], "CLIP")
|
||||
self.assertNotIn("task_context", optional)
|
||||
|
||||
def test_universal_prompt_encode_schema_requires_single_text_encoder_input(self):
|
||||
plugin = load_plugin_package()
|
||||
node_cls = plugin.NODE_CLASS_MAPPINGS["LLSUniversalPromptEncode"]
|
||||
required = node_cls.INPUT_TYPES()["required"]
|
||||
optional = node_cls.INPUT_TYPES()["optional"]
|
||||
|
||||
self.assertEqual(node_cls.RETURN_TYPES, ("CONDITIONING", "CONDITIONING", "STRING"))
|
||||
self.assertEqual(required["text_encoder"][0], "CLIP")
|
||||
self.assertEqual(required["clip_skip"][1]["default"], -1)
|
||||
self.assertNotIn("clip", required)
|
||||
self.assertEqual(optional["model_info"][0], "STRING")
|
||||
|
||||
def test_prompt_encode_dispatches_sdxl_using_inferred_family_defaults(self):
|
||||
plugin = load_plugin_package()
|
||||
node_cls = plugin.NODE_CLASS_MAPPINGS["LLSSimplePromptEncode"]
|
||||
@@ -451,6 +553,60 @@ class TestLoaderPromptRefactor(unittest.TestCase):
|
||||
self.assertEqual(positive[0][0], "cond::a robot in a forest")
|
||||
self.assertEqual(negative[0][0], "cond::")
|
||||
|
||||
def test_universal_prompt_encode_dispatches_sdxl_from_model_info(self):
|
||||
plugin = load_plugin_package()
|
||||
node_cls = plugin.NODE_CLASS_MAPPINGS["LLSUniversalPromptEncode"]
|
||||
node = node_cls()
|
||||
clip = RecordingClip(("g", "l"))
|
||||
|
||||
positive, negative, prompt_info = node.encode(
|
||||
text_encoder=clip,
|
||||
positive_prompt="a castle",
|
||||
negative_prompt="low quality",
|
||||
clip_skip=-1,
|
||||
model_info=json.dumps({"model_family": "SDXL", "checkpoint_name": "sdxl_turbo.safetensors"}),
|
||||
)
|
||||
|
||||
self.assertEqual(len(clip.calls), 2)
|
||||
self.assertEqual(clip.calls[0]["add_dict"]["width"], 1024)
|
||||
payload = json.loads(prompt_info)
|
||||
self.assertEqual(payload["model_family"], "SDXL")
|
||||
self.assertEqual(payload["prompt_mode"], "sdxl")
|
||||
self.assertEqual(payload["checkpoint_name"], "sdxl_turbo.safetensors")
|
||||
self.assertEqual(positive[0][0], "cond::a castle")
|
||||
self.assertEqual(negative[0][0], "cond::low quality")
|
||||
|
||||
def test_universal_prompt_encode_dispatches_flux_from_model_info(self):
|
||||
plugin = load_plugin_package()
|
||||
node_cls = plugin.NODE_CLASS_MAPPINGS["LLSUniversalPromptEncode"]
|
||||
node = node_cls()
|
||||
clip = RecordingClip(("t5xxl",))
|
||||
|
||||
positive, negative, prompt_info = node.encode(
|
||||
text_encoder=clip,
|
||||
positive_prompt="a robot in a forest",
|
||||
negative_prompt="ugly, blurry",
|
||||
clip_skip=-1,
|
||||
model_info=json.dumps(
|
||||
{
|
||||
"model_family": "FLUX_DEV",
|
||||
"checkpoint_name": "diffusion_models/flux1-schnell.safetensors",
|
||||
"text_encoder_name": "clip_l.safetensors, t5xxl_fp16.safetensors",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
self.assertEqual(len(clip.calls), 2)
|
||||
self.assertEqual(clip.calls[0]["add_dict"]["guidance"], 3.5)
|
||||
self.assertEqual(clip.calls[1]["tokens"]["text"], "")
|
||||
payload = json.loads(prompt_info)
|
||||
self.assertEqual(payload["model_family"], "FLUX_DEV")
|
||||
self.assertEqual(payload["prompt_mode"], "flux")
|
||||
self.assertEqual(payload["checkpoint_name"], "diffusion_models/flux1-schnell.safetensors")
|
||||
self.assertEqual(payload["text_encoder_name"], "clip_l.safetensors, t5xxl_fp16.safetensors")
|
||||
self.assertEqual(positive[0][0], "cond::a robot in a forest")
|
||||
self.assertEqual(negative[0][0], "cond::")
|
||||
|
||||
def test_empty_latent_uses_model_family_inference_for_flux_shape(self):
|
||||
load_plugin_package()
|
||||
from lls_node_test_refactor.latent import nodes as latent_nodes
|
||||
|
||||
Reference in New Issue
Block a user