RioShiina commited on
Commit
dd0ca3b
·
verified ·
1 Parent(s): 7b16551

Add Krea-2 architecture and Krea-2 ControlNet injector

Browse files
.gitattributes CHANGED
@@ -1,35 +1,4 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ /web/assets/** linguist-generated
2
+ /web/** linguist-vendored
3
+ comfy_api_nodes/apis/__init__.py linguist-generated
4
+ comfy/text_encoders/t5_pile_tokenizer/tokenizer.model filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
chain_injectors/krea2_controlnet_injector.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def inject(assembler, chain_definition, chain_items):
2
+ if not chain_items:
3
+ return
4
+
5
+ ksampler_name = chain_definition.get('ksampler_node', 'ksampler')
6
+ if ksampler_name not in assembler.node_map:
7
+ print(f"Warning: Target node '{ksampler_name}' for Krea2 ControlNet chain not found. Skipping.")
8
+ return
9
+
10
+ ksampler_id = assembler.node_map[ksampler_name]
11
+
12
+ if 'model' not in assembler.workflow[ksampler_id]['inputs']:
13
+ print(f"Warning: KSampler node '{ksampler_name}' is missing 'model' input. Skipping.")
14
+ return
15
+
16
+ vae_source_str = chain_definition.get('vae_source')
17
+ vae_connection = None
18
+ if vae_source_str:
19
+ vae_node_name, vae_idx_str = vae_source_str.split(':')
20
+ if vae_node_name in assembler.node_map:
21
+ vae_connection = [assembler.node_map[vae_node_name], int(vae_idx_str)]
22
+
23
+ latent_connection = assembler.workflow[ksampler_id]['inputs'].get('latent_image')
24
+ if not latent_connection:
25
+ print(f"Warning: KSampler node '{ksampler_name}' is missing 'latent_image' input. Krea2 ControlNet requires it. Skipping.")
26
+ return
27
+
28
+ current_model_connection = assembler.workflow[ksampler_id]['inputs']['model']
29
+
30
+ for item_data in chain_items:
31
+ image_loader_id = assembler._get_unique_id()
32
+ image_loader_node = assembler._get_node_template("LoadImage")
33
+ image_loader_node['inputs']['image'] = item_data['image']
34
+ assembler.workflow[image_loader_id] = image_loader_node
35
+
36
+ image_scaler_id = assembler._get_unique_id()
37
+ image_scaler_node = assembler._get_node_template("ImageScaleToTotalPixels")
38
+ image_scaler_node['inputs']['image'] = [image_loader_id, 0]
39
+ image_scaler_node['inputs']['upscale_method'] = 'nearest-exact'
40
+ image_scaler_node['inputs']['megapixels'] = 1.0
41
+ image_scaler_node['inputs']['resolution_steps'] = 1
42
+ assembler.workflow[image_scaler_id] = image_scaler_node
43
+
44
+ lora_loader_id = assembler._get_unique_id()
45
+ lora_loader_node = assembler._get_node_template("Krea2ControlLoRALoader")
46
+ lora_loader_node['inputs']['lora_name'] = item_data['control_net_name']
47
+ lora_loader_node['inputs']['strength'] = item_data.get('strength', 1.0)
48
+ lora_loader_node['inputs']['model'] = current_model_connection
49
+ assembler.workflow[lora_loader_id] = lora_loader_node
50
+
51
+ img_encode_id = assembler._get_unique_id()
52
+ img_encode_node = assembler._get_node_template("Krea2ControlImageEncode")
53
+ img_encode_node['inputs']['resize'] = "match_latent_size"
54
+ img_encode_node['inputs']['upscale_method'] = "lanczos"
55
+ img_encode_node['inputs']['crop'] = "center"
56
+ img_encode_node['inputs']['channel_mode'] = "rgb"
57
+ img_encode_node['inputs']['normalize'] = "none"
58
+ img_encode_node['inputs']['invert'] = False
59
+ img_encode_node['inputs']['batch_mode'] = "independent_images"
60
+ img_encode_node['inputs']['control_image'] = [image_scaler_id, 0]
61
+ if vae_connection:
62
+ img_encode_node['inputs']['vae'] = vae_connection
63
+ if latent_connection:
64
+ img_encode_node['inputs']['latent'] = latent_connection
65
+ assembler.workflow[img_encode_id] = img_encode_node
66
+
67
+ apply_cn_id = assembler._get_unique_id()
68
+ apply_cn_node = assembler._get_node_template("Krea2ControlApply")
69
+ apply_cn_node['inputs']['model'] = [lora_loader_id, 0]
70
+ apply_cn_node['inputs']['control_latent'] = [img_encode_id, 0]
71
+
72
+ assembler.workflow[apply_cn_id] = apply_cn_node
73
+
74
+ current_model_connection = [apply_cn_id, 0]
75
+
76
+ assembler.workflow[ksampler_id]['inputs']['model'] = current_model_connection
77
+
78
+ print(f"Krea2 ControlNet injector applied. KSampler model input redirected through {len(chain_items)} Krea2 ControlNet nodes.")
comfy_integration/setup.py CHANGED
@@ -65,6 +65,12 @@ def initialize_comfyui():
65
  print("✅ ComfyUI-IPAdapter-Flux extension cloned.")
66
  else:
67
  print("✅ ComfyUI-IPAdapter-Flux extension already exists.")
 
 
 
 
 
 
68
 
69
  # 4. ComfyUI-Newbie-Nodes
70
  newbie_nodes_path = os.path.join(APP_DIR, "custom_nodes", "ComfyUI-Newbie-Nodes")
@@ -82,6 +88,14 @@ def initialize_comfyui():
82
  else:
83
  print("✅ ComfyUI-Anima-LLLite extension already exists.")
84
 
 
 
 
 
 
 
 
 
85
  print(f"✅ Current working directory is: {os.getcwd()}")
86
 
87
  import comfy.model_management
 
65
  print("✅ ComfyUI-IPAdapter-Flux extension cloned.")
66
  else:
67
  print("✅ ComfyUI-IPAdapter-Flux extension already exists.")
68
+ try:
69
+ print("--- [Setup] Applying PR #108 compatibility patch for ComfyUI-IPAdapter-Flux ---")
70
+ os.system(f"git -C {ipadapter_flux_path} fetch origin pull/108/head && git -C {ipadapter_flux_path} checkout -f FETCH_HEAD")
71
+ print("✅ Successfully applied PR #108 compatibility patch.")
72
+ except Exception as e:
73
+ print(f"⚠️ Warning: Could not apply PR #108 compatibility patch for ComfyUI-IPAdapter-Flux: {e}")
74
 
75
  # 4. ComfyUI-Newbie-Nodes
76
  newbie_nodes_path = os.path.join(APP_DIR, "custom_nodes", "ComfyUI-Newbie-Nodes")
 
88
  else:
89
  print("✅ ComfyUI-Anima-LLLite extension already exists.")
90
 
91
+ # 6. comfyui-krea2-controlnet
92
+ krea2_controlnet_nodes_path = os.path.join(APP_DIR, "custom_nodes", "comfyui-krea2-controlnet")
93
+ if not os.path.exists(krea2_controlnet_nodes_path):
94
+ os.system(f"git clone https://github.com/facok/comfyui-krea2-controlnet.git {krea2_controlnet_nodes_path}")
95
+ print("✅ comfyui-krea2-controlnet extension cloned.")
96
+ else:
97
+ print("✅ comfyui-krea2-controlnet extension already exists.")
98
+
99
  print(f"✅ Current working directory is: {os.getcwd()}")
100
 
101
  import comfy.model_management
core/pipelines/pipeline_input_processor.py CHANGED
@@ -1,334 +1,383 @@
1
- import os
2
- import random
3
- import numpy as np
4
- import gradio as gr
5
- from PIL import Image, ImageChops
6
- from typing import Dict, Any, List
7
-
8
- from core.settings import INPUT_DIR
9
- from utils.app_utils import (
10
- sanitize_filename,
11
- get_lora_path,
12
- get_embedding_path,
13
- ensure_controlnet_model_downloaded,
14
- ensure_ipadapter_models_downloaded,
15
- _ensure_model_downloaded,
16
- ensure_sd3_ipadapter_models_downloaded,
17
- get_vae_path,
18
- )
19
-
20
- def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, workflow_model_type: str) -> Dict[str, Any]:
21
- task_type = ui_inputs['task_type']
22
- temp_files_to_clean = []
23
-
24
- lora_data = ui_inputs.get('lora_data', [])
25
- active_loras_for_gpu, active_loras_for_meta = [], []
26
- if lora_data:
27
- sources, ids, scales, files = lora_data[0::4], lora_data[1::4], lora_data[2::4], lora_data[3::4]
28
- for i, (source, lora_id, scale, _) in enumerate(zip(sources, ids, scales, files)):
29
- if scale > 0 and lora_id and lora_id.strip():
30
- lora_filename = None
31
- if source == "File":
32
- lora_filename = sanitize_filename(lora_id)
33
- elif source == "Civitai":
34
- local_path, status = get_lora_path(source, lora_id, os.environ.get("CIVITAI_API_KEY", ""), progress)
35
- if local_path: lora_filename = os.path.basename(local_path)
36
- else: raise gr.Error(f"Failed to prepare LoRA {lora_id}: {status}")
37
-
38
- if lora_filename:
39
- active_loras_for_gpu.append({"lora_name": lora_filename, "strength_model": scale, "strength_clip": scale})
40
- active_loras_for_meta.append(f"{source} {lora_id}:{scale}")
41
-
42
- ui_inputs['denoise'] = 1.0
43
- if task_type == 'img2img': ui_inputs['denoise'] = ui_inputs.get('img2img_denoise', 0.7)
44
- elif task_type == 'hires_fix': ui_inputs['denoise'] = ui_inputs.get('hires_denoise', 0.55)
45
-
46
- if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
47
-
48
- if task_type == 'img2img':
49
- input_image_pil = ui_inputs.get('img2img_image')
50
- if not input_image_pil:
51
- raise gr.Error("Please upload an image for Image-to-Image.")
52
- temp_file_path = os.path.join(INPUT_DIR, f"temp_input_{random.randint(1000, 9999)}.png")
53
- input_image_pil.save(temp_file_path, "PNG")
54
- ui_inputs['input_image'] = os.path.basename(temp_file_path)
55
- temp_files_to_clean.append(temp_file_path)
56
- ui_inputs['width'] = input_image_pil.width
57
- ui_inputs['height'] = input_image_pil.height
58
-
59
- elif task_type == 'inpaint':
60
- inpaint_dict = ui_inputs.get('inpaint_image_dict')
61
- if not inpaint_dict or not inpaint_dict.get('background') or not inpaint_dict.get('layers'):
62
- raise gr.Error("Inpainting requires an input image and a drawn mask.")
63
-
64
- background_img = inpaint_dict['background'].convert("RGBA")
65
- composite_mask_pil = Image.new('L', background_img.size, 0)
66
- for layer in inpaint_dict['layers']:
67
- if layer:
68
- layer_alpha = layer.split()[-1]
69
- composite_mask_pil = ImageChops.lighter(composite_mask_pil, layer_alpha)
70
-
71
- inverted_mask_alpha = Image.fromarray(255 - np.array(composite_mask_pil), mode='L')
72
- r, g, b, _ = background_img.split()
73
- composite_image_with_mask = Image.merge('RGBA', [r, g, b, inverted_mask_alpha])
74
-
75
- temp_file_path = os.path.join(INPUT_DIR, f"temp_inpaint_composite_{random.randint(1000, 9999)}.png")
76
- composite_image_with_mask.save(temp_file_path, "PNG")
77
-
78
- ui_inputs['input_image'] = os.path.basename(temp_file_path)
79
- temp_files_to_clean.append(temp_file_path)
80
- ui_inputs.pop('inpaint_mask', None)
81
-
82
- elif task_type == 'outpaint':
83
- input_image_pil = ui_inputs.get('outpaint_image')
84
- if not input_image_pil:
85
- raise gr.Error("Please upload an image for Outpainting.")
86
- temp_file_path = os.path.join(INPUT_DIR, f"temp_input_{random.randint(1000, 9999)}.png")
87
- input_image_pil.save(temp_file_path, "PNG")
88
- ui_inputs['input_image'] = os.path.basename(temp_file_path)
89
- temp_files_to_clean.append(temp_file_path)
90
-
91
- ui_inputs['megapixels'] = 0.25
92
- ui_inputs['grow_mask_by'] = ui_inputs.get('feathering', 10)
93
-
94
- elif task_type == 'hires_fix':
95
- input_image_pil = ui_inputs.get('hires_image')
96
- if not input_image_pil:
97
- raise gr.Error("Please upload an image for Hires Fix.")
98
- temp_file_path = os.path.join(INPUT_DIR, f"temp_input_{random.randint(1000, 9999)}.png")
99
- input_image_pil.save(temp_file_path, "PNG")
100
- ui_inputs['input_image'] = os.path.basename(temp_file_path)
101
- temp_files_to_clean.append(temp_file_path)
102
-
103
- embedding_data = ui_inputs.get('embedding_data', [])
104
- embedding_filenames = []
105
- if embedding_data:
106
- emb_sources, emb_ids, emb_files = embedding_data[0::3], embedding_data[1::3], embedding_data[2::3]
107
- for i, (source, emb_id, _) in enumerate(zip(emb_sources, emb_ids, emb_files)):
108
- if emb_id and emb_id.strip():
109
- emb_filename = None
110
- if source == "File":
111
- emb_filename = sanitize_filename(emb_id)
112
- elif source == "Civitai":
113
- local_path, status = get_embedding_path(source, emb_id, os.environ.get("CIVITAI_API_KEY", ""), progress)
114
- if local_path: emb_filename = os.path.basename(local_path)
115
- else: raise gr.Error(f"Failed to prepare Embedding {emb_id}: {status}")
116
-
117
- if emb_filename:
118
- embedding_filenames.append(emb_filename)
119
-
120
- if embedding_filenames:
121
- embedding_prompt_text = " ".join([f"embedding:{f}" for f in embedding_filenames])
122
- if ui_inputs['positive_prompt']:
123
- ui_inputs['positive_prompt'] = f"{ui_inputs['positive_prompt']}, {embedding_prompt_text}"
124
- else:
125
- ui_inputs['positive_prompt'] = embedding_prompt_text
126
-
127
- controlnet_data = ui_inputs.get('controlnet_data', [])
128
- active_controlnets = []
129
- if controlnet_data:
130
- (cn_images, _, _, cn_strengths, cn_filepaths) = [controlnet_data[i::5] for i in range(5)]
131
- for i in range(len(cn_images)):
132
- if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
133
- ensure_controlnet_model_downloaded(cn_filepaths[i], progress)
134
- if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
135
- cn_temp_path = os.path.join(INPUT_DIR, f"temp_cn_{i}_{random.randint(1000, 9999)}.png")
136
- cn_images[i].save(cn_temp_path, "PNG")
137
- temp_files_to_clean.append(cn_temp_path)
138
- active_controlnets.append({
139
- "image": os.path.basename(cn_temp_path), "strength": cn_strengths[i],
140
- "start_percent": 0.0, "end_percent": 1.0, "control_net_name": cn_filepaths[i]
141
- })
142
-
143
- anima_controlnet_lllite_data = ui_inputs.get('anima_controlnet_lllite_data', [])
144
- active_anima_controlnets = []
145
- if anima_controlnet_lllite_data:
146
- (cn_images, _, _, cn_strengths, cn_filepaths, cn_starts, cn_ends) = [anima_controlnet_lllite_data[i::7] for i in range(7)]
147
- for i in range(len(cn_images)):
148
- if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
149
- _ensure_model_downloaded(cn_filepaths[i], progress)
150
- if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
151
- cn_temp_path = os.path.join(INPUT_DIR, f"temp_anima_cn_{i}_{random.randint(1000, 9999)}.png")
152
- cn_images[i].save(cn_temp_path, "PNG")
153
- temp_files_to_clean.append(cn_temp_path)
154
- active_anima_controlnets.append({
155
- "image": os.path.basename(cn_temp_path), "strength": cn_strengths[i],
156
- "start_percent": cn_starts[i], "end_percent": cn_ends[i], "control_net_name": cn_filepaths[i]
157
- })
158
-
159
- diffsynth_controlnet_data = ui_inputs.get('diffsynth_controlnet_data', [])
160
- active_diffsynth_controlnets = []
161
- if diffsynth_controlnet_data:
162
- (cn_images, _, _, cn_strengths, cn_filepaths) = [diffsynth_controlnet_data[i::5] for i in range(5)]
163
- for i in range(len(cn_images)):
164
- if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
165
- ensure_controlnet_model_downloaded(cn_filepaths[i], progress)
166
- if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
167
- cn_temp_path = os.path.join(INPUT_DIR, f"temp_diffsynth_cn_{i}_{random.randint(1000, 9999)}.png")
168
- cn_images[i].save(cn_temp_path, "PNG")
169
- temp_files_to_clean.append(cn_temp_path)
170
- active_diffsynth_controlnets.append({
171
- "image": os.path.basename(cn_temp_path), "strength": cn_strengths[i],
172
- "control_net_name": cn_filepaths[i]
173
- })
174
-
175
- ipadapter_data = ui_inputs.get('ipadapter_data', [])
176
- active_ipadapters = []
177
- if ipadapter_data:
178
- num_ipa_units = (len(ipadapter_data) - 5) // 3
179
- final_preset, final_weight, final_lora_strength, final_embeds_scaling, final_combine_method = ipadapter_data[-5:]
180
- ipa_images, ipa_weights, ipa_lora_strengths = [ipadapter_data[i*num_ipa_units:(i+1)*num_ipa_units] for i in range(3)]
181
- all_presets_to_download = set()
182
- for i in range(num_ipa_units):
183
- if ipa_images[i] and ipa_weights[i] > 0 and final_preset:
184
- all_presets_to_download.add(final_preset)
185
- if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
186
- ipa_temp_path = os.path.join(INPUT_DIR, f"temp_ipa_{i}_{random.randint(1000, 9999)}.png")
187
- ipa_images[i].save(ipa_temp_path, "PNG")
188
- temp_files_to_clean.append(ipa_temp_path)
189
- active_ipadapters.append({
190
- "image": os.path.basename(ipa_temp_path), "preset": final_preset,
191
- "weight": ipa_weights[i], "lora_strength": ipa_lora_strengths[i]
192
- })
193
- if active_ipadapters and final_preset:
194
- all_presets_to_download.add(final_preset)
195
- for preset in all_presets_to_download:
196
- ensure_ipadapter_models_downloaded(preset, progress)
197
-
198
- model_type_key = 'sd15' if workflow_model_type == 'sd15' else 'sdxl'
199
- if active_ipadapters:
200
- active_ipadapters.append({
201
- 'is_final_settings': True, 'model_type': model_type_key, 'final_preset': final_preset,
202
- 'final_weight': final_weight, 'final_lora_strength': final_lora_strength,
203
- 'final_embeds_scaling': final_embeds_scaling, 'final_combine_method': final_combine_method
204
- })
205
-
206
- flux1_ipadapter_data = ui_inputs.get('flux1_ipadapter_data', [])
207
- active_flux1_ipadapters = []
208
- if flux1_ipadapter_data:
209
- num_units = len(flux1_ipadapter_data) // 4
210
- f_images = flux1_ipadapter_data[0*num_units : 1*num_units]
211
- f_weights = flux1_ipadapter_data[1*num_units : 2*num_units]
212
- f_starts = flux1_ipadapter_data[2*num_units : 3*num_units]
213
- f_ends = flux1_ipadapter_data[3*num_units : 4*num_units]
214
- for i in range(len(f_images)):
215
- if f_images[i] and f_weights[i] > 0:
216
- for filename in ["ip-adapter.bin"]:
217
- _ensure_model_downloaded(filename, progress)
218
-
219
- from huggingface_hub import snapshot_download
220
- progress(0.5, desc="Caching HF SigLIP model...")
221
- snapshot_download(
222
- repo_id="google/siglip-so400m-patch14-384",
223
- allow_patterns=["*.json", "*.safetensors", "*.txt"],
224
- ignore_patterns=["*.msgpack", "*.h5", "*.bin"]
225
- )
226
-
227
- temp_path = os.path.join(INPUT_DIR, f"temp_fipa_{i}_{random.randint(1000, 9999)}.png")
228
- f_images[i].save(temp_path, "PNG")
229
- temp_files_to_clean.append(temp_path)
230
- active_flux1_ipadapters.append({
231
- "image": os.path.basename(temp_path),
232
- "weight": f_weights[i], "start_percent": f_starts[i], "end_percent": f_ends[i]
233
- })
234
-
235
- sd3_ipadapter_data = ui_inputs.get('sd3_ipadapter_chain', [])
236
- active_sd3_ipadapters = []
237
- if sd3_ipadapter_data:
238
- num_units = len(sd3_ipadapter_data) // 4
239
- s_images = sd3_ipadapter_data[0*num_units : 1*num_units]
240
- s_weights = sd3_ipadapter_data[1*num_units : 2*num_units]
241
- s_starts = sd3_ipadapter_data[2*num_units : 3*num_units]
242
- s_ends = sd3_ipadapter_data[3*num_units : 4*num_units]
243
- sd3_ipa_downloaded = False
244
- for i in range(len(s_images)):
245
- if s_images[i] and s_weights[i] > 0:
246
- if not sd3_ipa_downloaded:
247
- ensure_sd3_ipadapter_models_downloaded(progress)
248
- sd3_ipa_downloaded = True
249
- temp_path = os.path.join(INPUT_DIR, f"temp_s3ipa_{i}_{random.randint(1000, 9999)}.png")
250
- s_images[i].save(temp_path, "PNG")
251
- temp_files_to_clean.append(temp_path)
252
- active_sd3_ipadapters.append({
253
- "image": os.path.basename(temp_path),
254
- "weight": s_weights[i], "start_percent": s_starts[i], "end_percent": s_ends[i]
255
- })
256
-
257
- style_data = ui_inputs.get('style_data', [])
258
- active_styles = []
259
- if style_data:
260
- num_units = len(style_data) // 2
261
- st_images = style_data[0*num_units : 1*num_units]
262
- st_strengths = style_data[1*num_units : 2*num_units]
263
- for i in range(len(st_images)):
264
- if st_images[i] and st_strengths[i] > 0:
265
- _ensure_model_downloaded("sigclip_vision_patch14_384.safetensors", progress)
266
- temp_path = os.path.join(INPUT_DIR, f"temp_style_{i}_{random.randint(1000, 9999)}.png")
267
- st_images[i].save(temp_path, "PNG")
268
- temp_files_to_clean.append(temp_path)
269
- active_styles.append({
270
- "image": os.path.basename(temp_path), "strength": st_strengths[i]
271
- })
272
-
273
- reference_latent_data = ui_inputs.get('reference_latent_data', [])
274
- active_reference_latents = []
275
- if reference_latent_data:
276
- for img in reference_latent_data:
277
- if img:
278
- if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
279
- temp_path = os.path.join(INPUT_DIR, f"temp_ref_{random.randint(1000, 9999)}.png")
280
- img.save(temp_path, "PNG")
281
- temp_files_to_clean.append(temp_path)
282
- active_reference_latents.append(os.path.basename(temp_path))
283
-
284
- hidream_o1_reference_data = ui_inputs.get('hidream_o1_reference_data', [])
285
- active_hidream_o1_reference = []
286
- if hidream_o1_reference_data:
287
- for img in hidream_o1_reference_data:
288
- if img:
289
- if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
290
- temp_path = os.path.join(INPUT_DIR, f"temp_ho1_ref_{random.randint(1000, 9999)}.png")
291
- img.save(temp_path, "PNG")
292
- temp_files_to_clean.append(temp_path)
293
- active_hidream_o1_reference.append(os.path.basename(temp_path))
294
-
295
- vae_source = ui_inputs.get('vae_source')
296
- vae_id = ui_inputs.get('vae_id')
297
- vae_name_override = None
298
- if vae_source and vae_source != "None":
299
- if vae_source == "File":
300
- vae_name_override = sanitize_filename(vae_id)
301
- elif vae_source == "Civitai" and vae_id and vae_id.strip():
302
- local_path, status = get_vae_path(vae_source, vae_id, os.environ.get("CIVITAI_API_KEY", ""), progress)
303
- if local_path: vae_name_override = os.path.basename(local_path)
304
- else: raise gr.Error(f"Failed to prepare VAE {vae_id}: {status}")
305
- if vae_name_override:
306
- ui_inputs['vae_name'] = vae_name_override
307
-
308
- conditioning_data = ui_inputs.get('conditioning_data', [])
309
- active_conditioning = []
310
- if conditioning_data:
311
- num_units = len(conditioning_data) // 6
312
- prompts, widths, heights, xs, ys, strengths = [conditioning_data[i*num_units : (i+1)*num_units] for i in range(6)]
313
- for i in range(num_units):
314
- if prompts[i] and prompts[i].strip():
315
- active_conditioning.append({
316
- "prompt": prompts[i], "width": int(widths[i]), "height": int(heights[i]),
317
- "x": int(xs[i]), "y": int(ys[i]), "strength": float(strengths[i])
318
- })
319
-
320
- return {
321
- "active_loras_for_gpu": active_loras_for_gpu,
322
- "active_loras_for_meta": active_loras_for_meta,
323
- "active_controlnets": active_controlnets,
324
- "active_anima_controlnets": active_anima_controlnets,
325
- "active_diffsynth_controlnets": active_diffsynth_controlnets,
326
- "active_ipadapters": active_ipadapters,
327
- "active_flux1_ipadapters": active_flux1_ipadapters,
328
- "active_sd3_ipadapters": active_sd3_ipadapters,
329
- "active_styles": active_styles,
330
- "active_reference_latents": active_reference_latents,
331
- "active_hidream_o1_reference": active_hidream_o1_reference,
332
- "active_conditioning": active_conditioning,
333
- "temp_files_to_clean": temp_files_to_clean
334
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import random
3
+ import numpy as np
4
+ import gradio as gr
5
+ from PIL import Image, ImageChops
6
+ from typing import Dict, Any, List
7
+
8
+ from core.settings import INPUT_DIR, MULTIPLIERS_MAP
9
+ from utils.app_utils import (
10
+ sanitize_filename,
11
+ get_lora_path,
12
+ get_embedding_path,
13
+ ensure_controlnet_model_downloaded,
14
+ ensure_ipadapter_models_downloaded,
15
+ _ensure_model_downloaded,
16
+ ensure_sd3_ipadapter_models_downloaded,
17
+ get_vae_path,
18
+ )
19
+
20
+ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, workflow_model_type: str) -> Dict[str, Any]:
21
+ task_type = ui_inputs['task_type']
22
+ temp_files_to_clean = []
23
+
24
+ multiplier = MULTIPLIERS_MAP.get(workflow_model_type, 8)
25
+ img_w, img_h = 0, 0
26
+ if task_type == 'txt2img':
27
+ img_w = int(ui_inputs.get('width', 0))
28
+ img_h = int(ui_inputs.get('height', 0))
29
+ elif task_type == 'img2img':
30
+ input_image_pil = ui_inputs.get('img2img_image')
31
+ if input_image_pil:
32
+ img_w, img_h = input_image_pil.width, input_image_pil.height
33
+ elif task_type == 'inpaint':
34
+ inpaint_dict = ui_inputs.get('inpaint_image_dict')
35
+ if inpaint_dict and inpaint_dict.get('background'):
36
+ img_w, img_h = inpaint_dict['background'].width, inpaint_dict['background'].height
37
+ elif task_type == 'outpaint':
38
+ input_image_pil = ui_inputs.get('outpaint_image')
39
+ if input_image_pil:
40
+ img_w, img_h = input_image_pil.width, input_image_pil.height
41
+ elif task_type == 'hires_fix':
42
+ input_image_pil = ui_inputs.get('hires_image')
43
+ if input_image_pil:
44
+ img_w, img_h = input_image_pil.width, input_image_pil.height
45
+
46
+ if img_w > 0 and img_h > 0:
47
+ if (img_w % multiplier != 0) or (img_h % multiplier != 0):
48
+ warning_msg = f"Width and height must be multiples of {multiplier} for this model."
49
+ raise gr.Error(warning_msg)
50
+
51
+ lora_data = ui_inputs.get('lora_data', [])
52
+ active_loras_for_gpu, active_loras_for_meta = [], []
53
+ if lora_data:
54
+ sources, ids, scales, files = lora_data[0::4], lora_data[1::4], lora_data[2::4], lora_data[3::4]
55
+ for i, (source, lora_id, scale, _) in enumerate(zip(sources, ids, scales, files)):
56
+ if scale > 0 and lora_id and lora_id.strip():
57
+ lora_filename = None
58
+ if source == "File":
59
+ lora_filename = sanitize_filename(lora_id)
60
+ elif source in ("Civitai", "Hugging Face"):
61
+ local_path, status = get_lora_path(source, lora_id, os.environ.get("CIVITAI_API_KEY", ""), progress)
62
+ if local_path: lora_filename = os.path.basename(local_path)
63
+ else: raise gr.Error(f"Failed to prepare LoRA {lora_id}: {status}")
64
+
65
+ if lora_filename:
66
+ active_loras_for_gpu.append({"lora_name": lora_filename, "strength_model": scale, "strength_clip": scale})
67
+ active_loras_for_meta.append(f"{source} {lora_id}:{scale}")
68
+
69
+ ui_inputs['denoise'] = 1.0
70
+ if task_type == 'img2img': ui_inputs['denoise'] = ui_inputs.get('img2img_denoise', 0.7)
71
+ elif task_type == 'hires_fix': ui_inputs['denoise'] = ui_inputs.get('hires_denoise', 0.55)
72
+ elif task_type == 'inpaint': ui_inputs['denoise'] = ui_inputs.get('inpaint_denoise', 1.0)
73
+
74
+ if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
75
+
76
+ if task_type == 'img2img':
77
+ input_image_pil = ui_inputs.get('img2img_image')
78
+ if not input_image_pil:
79
+ raise gr.Error("Please upload an image for Image-to-Image.")
80
+ temp_file_path = os.path.join(INPUT_DIR, f"temp_input_{random.randint(1000, 9999)}.png")
81
+ input_image_pil.save(temp_file_path, "PNG")
82
+ ui_inputs['input_image'] = os.path.basename(temp_file_path)
83
+ temp_files_to_clean.append(temp_file_path)
84
+ ui_inputs['width'] = input_image_pil.width
85
+ ui_inputs['height'] = input_image_pil.height
86
+
87
+ elif task_type == 'inpaint':
88
+ inpaint_dict = ui_inputs.get('inpaint_image_dict')
89
+ if not inpaint_dict or not inpaint_dict.get('background') or not inpaint_dict.get('layers'):
90
+ raise gr.Error("Inpainting requires an input image and a drawn mask.")
91
+
92
+ background_img = inpaint_dict['background'].convert("RGBA")
93
+ composite_mask_pil = Image.new('L', background_img.size, 0)
94
+ for layer in inpaint_dict['layers']:
95
+ if layer:
96
+ layer_alpha = layer.split()[-1]
97
+ composite_mask_pil = ImageChops.lighter(composite_mask_pil, layer_alpha)
98
+
99
+ inverted_mask_alpha = Image.fromarray(255 - np.array(composite_mask_pil), mode='L')
100
+ r, g, b, _ = background_img.split()
101
+ composite_image_with_mask = Image.merge('RGBA', [r, g, b, inverted_mask_alpha])
102
+
103
+ temp_file_path = os.path.join(INPUT_DIR, f"temp_inpaint_composite_{random.randint(1000, 9999)}.png")
104
+ composite_image_with_mask.save(temp_file_path, "PNG")
105
+
106
+ ui_inputs['input_image'] = os.path.basename(temp_file_path)
107
+ temp_files_to_clean.append(temp_file_path)
108
+ ui_inputs.pop('inpaint_mask', None)
109
+
110
+ elif task_type == 'outpaint':
111
+ input_image_pil = ui_inputs.get('outpaint_image')
112
+ if not input_image_pil:
113
+ raise gr.Error("Please upload an image for Outpainting.")
114
+ temp_file_path = os.path.join(INPUT_DIR, f"temp_input_{random.randint(1000, 9999)}.png")
115
+ input_image_pil.save(temp_file_path, "PNG")
116
+ ui_inputs['input_image'] = os.path.basename(temp_file_path)
117
+ temp_files_to_clean.append(temp_file_path)
118
+
119
+ ui_inputs['megapixels'] = 0.25
120
+ ui_inputs['grow_mask_by'] = ui_inputs.get('feathering', 10)
121
+
122
+ elif task_type == 'hires_fix':
123
+ input_image_pil = ui_inputs.get('hires_image')
124
+ if not input_image_pil:
125
+ raise gr.Error("Please upload an image for Hires Fix.")
126
+ temp_file_path = os.path.join(INPUT_DIR, f"temp_input_{random.randint(1000, 9999)}.png")
127
+ input_image_pil.save(temp_file_path, "PNG")
128
+ ui_inputs['input_image'] = os.path.basename(temp_file_path)
129
+ temp_files_to_clean.append(temp_file_path)
130
+
131
+ embedding_data = ui_inputs.get('embedding_data', [])
132
+ embedding_filenames = []
133
+ if embedding_data:
134
+ emb_sources, emb_ids, emb_files = embedding_data[0::3], embedding_data[1::3], embedding_data[2::3]
135
+ for i, (source, emb_id, _) in enumerate(zip(emb_sources, emb_ids, emb_files)):
136
+ if emb_id and emb_id.strip():
137
+ emb_filename = None
138
+ if source == "File":
139
+ emb_filename = sanitize_filename(emb_id)
140
+ elif source in ("Civitai", "Hugging Face"):
141
+ local_path, status = get_embedding_path(source, emb_id, os.environ.get("CIVITAI_API_KEY", ""), progress)
142
+ if local_path: emb_filename = os.path.basename(local_path)
143
+ else: raise gr.Error(f"Failed to prepare Embedding {emb_id}: {status}")
144
+
145
+ if emb_filename:
146
+ embedding_filenames.append(emb_filename)
147
+
148
+ if embedding_filenames:
149
+ embedding_prompt_text = " ".join([f"embedding:{f}" for f in embedding_filenames])
150
+ if ui_inputs['positive_prompt']:
151
+ ui_inputs['positive_prompt'] = f"{ui_inputs['positive_prompt']}, {embedding_prompt_text}"
152
+ else:
153
+ ui_inputs['positive_prompt'] = embedding_prompt_text
154
+
155
+ controlnet_data = ui_inputs.get('controlnet_data', [])
156
+ active_controlnets = []
157
+ if controlnet_data:
158
+ (cn_images, _, _, cn_strengths, cn_filepaths) = [controlnet_data[i::5] for i in range(5)]
159
+ for i in range(len(cn_images)):
160
+ if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
161
+ ensure_controlnet_model_downloaded(cn_filepaths[i], progress)
162
+ if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
163
+ cn_temp_path = os.path.join(INPUT_DIR, f"temp_cn_{i}_{random.randint(1000, 9999)}.png")
164
+ cn_images[i].save(cn_temp_path, "PNG")
165
+ temp_files_to_clean.append(cn_temp_path)
166
+ active_controlnets.append({
167
+ "image": os.path.basename(cn_temp_path), "strength": cn_strengths[i],
168
+ "start_percent": 0.0, "end_percent": 1.0, "control_net_name": cn_filepaths[i]
169
+ })
170
+
171
+ anima_controlnet_lllite_data = ui_inputs.get('anima_controlnet_lllite_data', [])
172
+ active_anima_controlnets = []
173
+ if anima_controlnet_lllite_data:
174
+ (cn_images, _, _, cn_strengths, cn_filepaths, cn_starts, cn_ends) = [anima_controlnet_lllite_data[i::7] for i in range(7)]
175
+ for i in range(len(cn_images)):
176
+ if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
177
+ _ensure_model_downloaded(cn_filepaths[i], progress)
178
+ if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
179
+ cn_temp_path = os.path.join(INPUT_DIR, f"temp_anima_cn_{i}_{random.randint(1000, 9999)}.png")
180
+ cn_images[i].save(cn_temp_path, "PNG")
181
+ temp_files_to_clean.append(cn_temp_path)
182
+ active_anima_controlnets.append({
183
+ "image": os.path.basename(cn_temp_path), "strength": cn_strengths[i],
184
+ "start_percent": cn_starts[i], "end_percent": cn_ends[i], "control_net_name": cn_filepaths[i]
185
+ })
186
+
187
+ diffsynth_controlnet_data = ui_inputs.get('diffsynth_controlnet_data', [])
188
+ active_diffsynth_controlnets = []
189
+ if diffsynth_controlnet_data:
190
+ (cn_images, _, _, cn_strengths, cn_filepaths) = [diffsynth_controlnet_data[i::5] for i in range(5)]
191
+ for i in range(len(cn_images)):
192
+ if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
193
+ ensure_controlnet_model_downloaded(cn_filepaths[i], progress)
194
+ if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
195
+ cn_temp_path = os.path.join(INPUT_DIR, f"temp_diffsynth_cn_{i}_{random.randint(1000, 9999)}.png")
196
+ cn_images[i].save(cn_temp_path, "PNG")
197
+ temp_files_to_clean.append(cn_temp_path)
198
+ active_diffsynth_controlnets.append({
199
+ "image": os.path.basename(cn_temp_path), "strength": cn_strengths[i],
200
+ "control_net_name": cn_filepaths[i]
201
+ })
202
+
203
+ krea2_controlnet_data = ui_inputs.get('krea2_controlnet_data', [])
204
+ active_krea2_controlnets = []
205
+ if krea2_controlnet_data:
206
+ (cn_images, _, _, cn_strengths, cn_filepaths) = [krea2_controlnet_data[i::5] for i in range(5)]
207
+ for i in range(len(cn_images)):
208
+ if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
209
+ ensure_controlnet_model_downloaded(cn_filepaths[i], progress)
210
+ if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
211
+ cn_temp_path = os.path.join(INPUT_DIR, f"temp_krea2_cn_{i}_{random.randint(1000, 9999)}.png")
212
+ cn_images[i].save(cn_temp_path, "PNG")
213
+ temp_files_to_clean.append(cn_temp_path)
214
+ active_krea2_controlnets.append({
215
+ "image": os.path.basename(cn_temp_path), "strength": cn_strengths[i],
216
+ "control_net_name": cn_filepaths[i]
217
+ })
218
+
219
+ ipadapter_data = ui_inputs.get('ipadapter_data', [])
220
+ active_ipadapters = []
221
+ if ipadapter_data:
222
+ num_ipa_units = (len(ipadapter_data) - 5) // 3
223
+ final_preset, final_weight, final_lora_strength, final_embeds_scaling, final_combine_method = ipadapter_data[-5:]
224
+ ipa_images, ipa_weights, ipa_lora_strengths = [ipadapter_data[i*num_ipa_units:(i+1)*num_ipa_units] for i in range(3)]
225
+ all_presets_to_download = set()
226
+ for i in range(num_ipa_units):
227
+ if ipa_images[i] and ipa_weights[i] > 0 and final_preset:
228
+ all_presets_to_download.add(final_preset)
229
+ if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
230
+ ipa_temp_path = os.path.join(INPUT_DIR, f"temp_ipa_{i}_{random.randint(1000, 9999)}.png")
231
+ ipa_images[i].save(ipa_temp_path, "PNG")
232
+ temp_files_to_clean.append(ipa_temp_path)
233
+ active_ipadapters.append({
234
+ "image": os.path.basename(ipa_temp_path), "preset": final_preset,
235
+ "weight": ipa_weights[i], "lora_strength": ipa_lora_strengths[i]
236
+ })
237
+ if active_ipadapters and final_preset:
238
+ all_presets_to_download.add(final_preset)
239
+ for preset in all_presets_to_download:
240
+ ensure_ipadapter_models_downloaded(preset, progress)
241
+
242
+ model_type_key = 'sd15' if workflow_model_type == 'sd15' else 'sdxl'
243
+ if active_ipadapters:
244
+ active_ipadapters.append({
245
+ 'is_final_settings': True, 'model_type': model_type_key, 'final_preset': final_preset,
246
+ 'final_weight': final_weight, 'final_lora_strength': final_lora_strength,
247
+ 'final_embeds_scaling': final_embeds_scaling, 'final_combine_method': final_combine_method
248
+ })
249
+
250
+ flux1_ipadapter_data = ui_inputs.get('flux1_ipadapter_data', [])
251
+ active_flux1_ipadapters = []
252
+ if flux1_ipadapter_data:
253
+ num_units = len(flux1_ipadapter_data) // 4
254
+ f_images = flux1_ipadapter_data[0*num_units : 1*num_units]
255
+ f_weights = flux1_ipadapter_data[1*num_units : 2*num_units]
256
+ f_starts = flux1_ipadapter_data[2*num_units : 3*num_units]
257
+ f_ends = flux1_ipadapter_data[3*num_units : 4*num_units]
258
+ for i in range(len(f_images)):
259
+ if f_images[i] and f_weights[i] > 0:
260
+ for filename in ["ip-adapter.bin"]:
261
+ _ensure_model_downloaded(filename, progress)
262
+
263
+ from huggingface_hub import snapshot_download
264
+ progress(0.5, desc="Caching HF SigLIP model...")
265
+ snapshot_download(
266
+ repo_id="google/siglip-so400m-patch14-384",
267
+ allow_patterns=["*.json", "*.safetensors", "*.txt"],
268
+ ignore_patterns=["*.msgpack", "*.h5", "*.bin"]
269
+ )
270
+
271
+ temp_path = os.path.join(INPUT_DIR, f"temp_fipa_{i}_{random.randint(1000, 9999)}.png")
272
+ f_images[i].save(temp_path, "PNG")
273
+ temp_files_to_clean.append(temp_path)
274
+ active_flux1_ipadapters.append({
275
+ "image": os.path.basename(temp_path),
276
+ "weight": f_weights[i], "start_percent": f_starts[i], "end_percent": f_ends[i]
277
+ })
278
+
279
+ sd3_ipadapter_data = ui_inputs.get('sd3_ipadapter_chain', [])
280
+ active_sd3_ipadapters = []
281
+ if sd3_ipadapter_data:
282
+ num_units = len(sd3_ipadapter_data) // 4
283
+ s_images = sd3_ipadapter_data[0*num_units : 1*num_units]
284
+ s_weights = sd3_ipadapter_data[1*num_units : 2*num_units]
285
+ s_starts = sd3_ipadapter_data[2*num_units : 3*num_units]
286
+ s_ends = sd3_ipadapter_data[3*num_units : 4*num_units]
287
+ sd3_ipa_downloaded = False
288
+ for i in range(len(s_images)):
289
+ if s_images[i] and s_weights[i] > 0:
290
+ if not sd3_ipa_downloaded:
291
+ ensure_sd3_ipadapter_models_downloaded(progress)
292
+ sd3_ipa_downloaded = True
293
+ temp_path = os.path.join(INPUT_DIR, f"temp_s3ipa_{i}_{random.randint(1000, 9999)}.png")
294
+ s_images[i].save(temp_path, "PNG")
295
+ temp_files_to_clean.append(temp_path)
296
+ active_sd3_ipadapters.append({
297
+ "image": os.path.basename(temp_path),
298
+ "weight": s_weights[i], "start_percent": s_starts[i], "end_percent": s_ends[i]
299
+ })
300
+
301
+ style_data = ui_inputs.get('style_data', [])
302
+ active_styles = []
303
+ if style_data:
304
+ num_units = len(style_data) // 2
305
+ st_images = style_data[0*num_units : 1*num_units]
306
+ st_strengths = style_data[1*num_units : 2*num_units]
307
+ style_models_downloaded = False
308
+ for i in range(len(st_images)):
309
+ if st_images[i] and st_strengths[i] > 0:
310
+ if not style_models_downloaded:
311
+ _ensure_model_downloaded("sigclip_vision_patch14_384.safetensors", progress)
312
+ _ensure_model_downloaded("flux1-redux-dev.safetensors", progress)
313
+ style_models_downloaded = True
314
+ temp_path = os.path.join(INPUT_DIR, f"temp_style_{i}_{random.randint(1000, 9999)}.png")
315
+ st_images[i].save(temp_path, "PNG")
316
+ temp_files_to_clean.append(temp_path)
317
+ active_styles.append({
318
+ "image": os.path.basename(temp_path), "strength": st_strengths[i]
319
+ })
320
+
321
+ reference_latent_data = ui_inputs.get('reference_latent_data', [])
322
+ active_reference_latents = []
323
+ if reference_latent_data:
324
+ for img in reference_latent_data:
325
+ if img:
326
+ if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
327
+ temp_path = os.path.join(INPUT_DIR, f"temp_ref_{random.randint(1000, 9999)}.png")
328
+ img.save(temp_path, "PNG")
329
+ temp_files_to_clean.append(temp_path)
330
+ active_reference_latents.append(os.path.basename(temp_path))
331
+
332
+ hidream_o1_reference_data = ui_inputs.get('hidream_o1_reference_data', [])
333
+ active_hidream_o1_reference = []
334
+ if hidream_o1_reference_data:
335
+ for img in hidream_o1_reference_data:
336
+ if img:
337
+ if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
338
+ temp_path = os.path.join(INPUT_DIR, f"temp_ho1_ref_{random.randint(1000, 9999)}.png")
339
+ img.save(temp_path, "PNG")
340
+ temp_files_to_clean.append(temp_path)
341
+ active_hidream_o1_reference.append(os.path.basename(temp_path))
342
+
343
+ vae_source = ui_inputs.get('vae_source')
344
+ vae_id = ui_inputs.get('vae_id')
345
+ vae_name_override = None
346
+ if vae_source and vae_source != "None":
347
+ if vae_source == "File":
348
+ vae_name_override = sanitize_filename(vae_id)
349
+ elif vae_source in ("Civitai", "Hugging Face") and vae_id and vae_id.strip():
350
+ local_path, status = get_vae_path(vae_source, vae_id, os.environ.get("CIVITAI_API_KEY", ""), progress)
351
+ if local_path: vae_name_override = os.path.basename(local_path)
352
+ else: raise gr.Error(f"Failed to prepare VAE {vae_id}: {status}")
353
+ if vae_name_override:
354
+ ui_inputs['vae_name'] = vae_name_override
355
+
356
+ conditioning_data = ui_inputs.get('conditioning_data', [])
357
+ active_conditioning = []
358
+ if conditioning_data:
359
+ num_units = len(conditioning_data) // 6
360
+ prompts, widths, heights, xs, ys, strengths = [conditioning_data[i*num_units : (i+1)*num_units] for i in range(6)]
361
+ for i in range(num_units):
362
+ if prompts[i] and prompts[i].strip():
363
+ active_conditioning.append({
364
+ "prompt": prompts[i], "width": int(widths[i]), "height": int(heights[i]),
365
+ "x": int(xs[i]), "y": int(ys[i]), "strength": float(strengths[i])
366
+ })
367
+
368
+ return {
369
+ "active_loras_for_gpu": active_loras_for_gpu,
370
+ "active_loras_for_meta": active_loras_for_meta,
371
+ "active_controlnets": active_controlnets,
372
+ "active_anima_controlnets": active_anima_controlnets,
373
+ "active_diffsynth_controlnets": active_diffsynth_controlnets,
374
+ "active_krea2_controlnets": active_krea2_controlnets,
375
+ "active_ipadapters": active_ipadapters,
376
+ "active_flux1_ipadapters": active_flux1_ipadapters,
377
+ "active_sd3_ipadapters": active_sd3_ipadapters,
378
+ "active_styles": active_styles,
379
+ "active_reference_latents": active_reference_latents,
380
+ "active_hidream_o1_reference": active_hidream_o1_reference,
381
+ "active_conditioning": active_conditioning,
382
+ "temp_files_to_clean": temp_files_to_clean
383
+ }
core/pipelines/sd_image_pipeline.py CHANGED
@@ -1,254 +1,259 @@
1
- import os
2
- import random
3
- import shutil
4
- import torch
5
- import gradio as gr
6
- from PIL import Image
7
- from typing import List, Dict, Any
8
-
9
- from .base_pipeline import BasePipeline
10
- from core.settings import *
11
- from utils.app_utils import sanitize_prompt
12
- from core.workflow_assembler import WorkflowAssembler
13
- from .workflow_executor import WorkflowExecutor
14
- from .pipeline_input_processor import process_pipeline_inputs
15
-
16
- class SdImagePipeline(BasePipeline):
17
- def get_required_models(self, model_display_name: str, **kwargs) -> List[str]:
18
- model_info = ALL_MODEL_MAP.get(model_display_name)
19
- if not model_info:
20
- return [model_display_name]
21
-
22
- path_or_components = model_info[1]
23
- if isinstance(path_or_components, dict):
24
- return [v for v in path_or_components.values() if v and v != "pixel_space"]
25
- else:
26
- return [model_display_name]
27
-
28
- def _gpu_logic(self, ui_inputs: Dict, loras_string: str, workflow: Dict[str, Any], assembler: WorkflowAssembler, progress=gr.Progress(track_tqdm=True)):
29
- model_display_name = ui_inputs['model_display_name']
30
-
31
- progress(0.4, desc="Executing workflow...")
32
-
33
- initial_objects = {}
34
-
35
- decoded_images_tensor = WorkflowExecutor.execute_workflow(workflow, initial_objects=initial_objects)
36
-
37
- output_images = []
38
- start_seed = ui_inputs['seed'] if ui_inputs['seed'] != -1 else random.randint(0, 2**64 - 1)
39
- for i in range(decoded_images_tensor.shape[0]):
40
- img_tensor = decoded_images_tensor[i]
41
- pil_image = Image.fromarray((img_tensor.cpu().numpy() * 255.0).astype("uint8"))
42
- current_seed = start_seed + i
43
-
44
- width_for_meta = ui_inputs.get('width', 'N/A')
45
- height_for_meta = ui_inputs.get('height', 'N/A')
46
-
47
- params_string = f"{ui_inputs['positive_prompt']}\nNegative prompt: {ui_inputs['negative_prompt']}\n"
48
- params_string += f"Steps: {ui_inputs['num_inference_steps']}, Sampler: {ui_inputs['sampler']}, Scheduler: {ui_inputs['scheduler']}, CFG scale: {ui_inputs['guidance_scale']}, Seed: {current_seed}, Size: {width_for_meta}x{height_for_meta}, Base Model: {model_display_name}"
49
- if ui_inputs['task_type'] != 'txt2img': params_string += f", Denoise: {ui_inputs['denoise']}"
50
- if ui_inputs.get('clip_skip') and ui_inputs['clip_skip'] != 1: params_string += f", Clip skip: {abs(ui_inputs['clip_skip'])}"
51
- if loras_string: params_string += f", {loras_string}"
52
-
53
- pil_image.info = {'parameters': params_string.strip()}
54
- output_images.append(pil_image)
55
-
56
- return output_images
57
-
58
- def run(self, ui_inputs: Dict, progress):
59
- progress(0, desc="Preparing models...")
60
-
61
- task_type = ui_inputs['task_type']
62
- model_display_name = ui_inputs['model_display_name']
63
- model_type = MODEL_TYPE_MAP.get(model_display_name, 'sdxl')
64
-
65
- architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
66
- workflow_model_type = architectures_dict.get(model_type, {}).get("model_type", model_type.lower().replace(" ", "").replace(".", ""))
67
-
68
- ui_inputs['positive_prompt'] = sanitize_prompt(ui_inputs.get('positive_prompt', ''))
69
- ui_inputs['negative_prompt'] = sanitize_prompt(ui_inputs.get('negative_prompt', ''))
70
-
71
- if 'clip_skip' in ui_inputs and ui_inputs['clip_skip'] is not None:
72
- ui_inputs['clip_skip'] = -int(ui_inputs['clip_skip'])
73
- else:
74
- ui_inputs['clip_skip'] = -1
75
-
76
- required_models = self.get_required_models(model_display_name=model_display_name)
77
-
78
- is_pid_enabled = (ui_inputs.get('pid_settings', 'OFF') == 'ON' and task_type == 'txt2img')
79
- if is_pid_enabled:
80
- import yaml
81
- pid_config_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'yaml', 'pid.yaml')
82
- pid_unet_name = "pid_flux1_1024_to_4096_4step_mxfp8.safetensors"
83
- try:
84
- with open(pid_config_path, 'r', encoding='utf-8') as f:
85
- pid_config = yaml.safe_load(f) or {}
86
- pid_items = pid_config.get("PiD", [])
87
- for item in pid_items:
88
- archs = item.get("architectures", [])
89
- if workflow_model_type in archs:
90
- pid_unet_name = item.get("filepath")
91
- break
92
- except Exception as e:
93
- print(f"Error loading PiD config for download: {e}")
94
-
95
- if pid_unet_name not in required_models:
96
- required_models.append(pid_unet_name)
97
- if "gemma_2_2b_it_elm_fp8_scaled.safetensors" not in required_models:
98
- required_models.append("gemma_2_2b_it_elm_fp8_scaled.safetensors")
99
-
100
- self.model_manager.ensure_models_downloaded(required_models, progress=progress)
101
-
102
- temp_files_to_clean = []
103
- try:
104
- processed = process_pipeline_inputs(ui_inputs, progress, workflow_model_type)
105
- temp_files_to_clean.extend(processed["temp_files_to_clean"])
106
-
107
- active_loras_for_gpu = processed["active_loras_for_gpu"]
108
- active_loras_for_meta = processed["active_loras_for_meta"]
109
- active_controlnets = processed["active_controlnets"]
110
- active_anima_controlnets = processed["active_anima_controlnets"]
111
- active_diffsynth_controlnets = processed["active_diffsynth_controlnets"]
112
- active_ipadapters = processed["active_ipadapters"]
113
- active_flux1_ipadapters = processed["active_flux1_ipadapters"]
114
- active_sd3_ipadapters = processed["active_sd3_ipadapters"]
115
- active_styles = processed["active_styles"]
116
- active_reference_latents = processed["active_reference_latents"]
117
- active_hidream_o1_reference = processed["active_hidream_o1_reference"]
118
- active_conditioning = processed["active_conditioning"]
119
-
120
- loras_string = f"LoRAs: [{', '.join(active_loras_for_meta)}]" if active_loras_for_meta else ""
121
-
122
- progress(0.8, desc="Assembling workflow...")
123
-
124
- if ui_inputs.get('seed') == -1:
125
- ui_inputs['seed'] = random.randint(0, 2**32 - 1)
126
-
127
- model_info = ALL_MODEL_MAP[model_display_name]
128
- path_or_components = model_info[1]
129
- latent_type = model_info[3] if len(model_info) > 3 and model_info[3] else 'latent'
130
- latent_generator_template = "EmptyLatentImage"
131
- if latent_type == 'sd3_latent':
132
- latent_generator_template = "EmptySD3LatentImage"
133
- elif latent_type == 'chroma_radiance_latent':
134
- latent_generator_template = "EmptyChromaRadianceLatentImage"
135
- elif latent_type == 'hunyuan_latent':
136
- latent_generator_template = "EmptyHunyuanImageLatent"
137
-
138
- dynamic_values = {
139
- 'task_type': ui_inputs['task_type'],
140
- 'model_type': workflow_model_type,
141
- 'latent_type': latent_type,
142
- 'latent_generator_template': latent_generator_template
143
- }
144
-
145
- recipe_path = os.path.join(os.path.dirname(__file__), "workflow_recipes", "sd_unified_recipe.yaml")
146
- assembler = WorkflowAssembler(recipe_path, dynamic_values=dynamic_values)
147
-
148
- hidream_o1_smoothing_data = []
149
- if workflow_model_type == 'hidream-o1' and model_display_name == "HiDream-O1-Image":
150
- hidream_o1_smoothing_data.append({})
151
-
152
- workflow_inputs = {
153
- **ui_inputs,
154
- "positive_prompt": ui_inputs['positive_prompt'], "negative_prompt": ui_inputs['negative_prompt'],
155
- "seed": ui_inputs['seed'], "steps": ui_inputs['num_inference_steps'], "cfg": ui_inputs['guidance_scale'],
156
- "sampler_name": ui_inputs['sampler'], "scheduler": ui_inputs['scheduler'],
157
- "batch_size": ui_inputs['batch_size'],
158
- "clip_skip": ui_inputs['clip_skip'],
159
- "denoise": ui_inputs['denoise'],
160
- "vae_name": ui_inputs.get('vae_name'),
161
- "guidance": ui_inputs.get('guidance', 3.5),
162
- "lora_chain": active_loras_for_gpu,
163
- "controlnet_chain": active_controlnets if not active_anima_controlnets else [],
164
- "anima_controlnet_lllite_chain": active_anima_controlnets,
165
- "diffsynth_controlnet_chain": active_diffsynth_controlnets,
166
- "ipadapter_chain": active_ipadapters,
167
- "flux1_ipadapter_chain": active_flux1_ipadapters,
168
- "sd3_ipadapter_chain": active_sd3_ipadapters,
169
- "style_chain": active_styles,
170
- "conditioning_chain": active_conditioning,
171
- "reference_latent_chain": active_reference_latents,
172
- "hidream_o1_reference_chain": active_hidream_o1_reference,
173
- "vae_chain": [ui_inputs.get('vae_name')] if ui_inputs.get('vae_name') else [],
174
- "hidream_o1_smoothing_chain": hidream_o1_smoothing_data,
175
- "pid_chain": [ui_inputs.get('pid_settings', 'OFF')] if is_pid_enabled else [],
176
- }
177
-
178
- if isinstance(path_or_components, dict):
179
- workflow_inputs.update({
180
- 'unet_name': path_or_components.get('unet'),
181
- 'vae_name': ui_inputs.get('vae_name') or path_or_components.get('vae'),
182
- 'clip_name': path_or_components.get('clip'),
183
- 'clip1_name': path_or_components.get('clip1'),
184
- 'clip2_name': path_or_components.get('clip2'),
185
- 'clip3_name': path_or_components.get('clip3'),
186
- 'clip4_name': path_or_components.get('clip4'),
187
- 'lora_name': path_or_components.get('lora'),
188
- })
189
- else:
190
- workflow_inputs['model_name'] = path_or_components
191
-
192
- if task_type == 'txt2img':
193
- workflow_inputs['width'] = ui_inputs['width']
194
- workflow_inputs['height'] = ui_inputs['height']
195
-
196
- workflow = assembler.assemble(workflow_inputs)
197
-
198
- progress(1.0, desc="All models ready. Requesting GPU for generation...")
199
-
200
- results = self._execute_gpu_logic(
201
- self._gpu_logic,
202
- duration=ui_inputs['zero_gpu_duration'],
203
- default_duration=60,
204
- task_name=f"ImageGen ({task_type})",
205
- ui_inputs=ui_inputs,
206
- loras_string=loras_string,
207
- workflow=workflow,
208
- assembler=assembler,
209
- progress=progress
210
- )
211
-
212
- import json
213
- import glob
214
- from PIL import PngImagePlugin
215
-
216
- prompt_json = json.dumps(workflow)
217
-
218
- out_dir = os.path.abspath(OUTPUT_DIR)
219
- os.makedirs(out_dir, exist_ok=True)
220
-
221
- try:
222
- existing_files = glob.glob(os.path.join(out_dir, "gen_*.png"))
223
- existing_files.sort(key=os.path.getmtime)
224
- while len(existing_files) > 50:
225
- os.remove(existing_files.pop(0))
226
- except Exception as e:
227
- print(f"Warning: Failed to cleanup output dir: {e}")
228
-
229
- final_results = []
230
- for img in results:
231
- if not isinstance(img, Image.Image):
232
- final_results.append(img)
233
- continue
234
-
235
- metadata = PngImagePlugin.PngInfo()
236
- params_string = img.info.get("parameters", "")
237
- if params_string:
238
- metadata.add_text("parameters", params_string)
239
- metadata.add_text("prompt", prompt_json)
240
-
241
- filename = f"gen_{random.randint(1000000, 9999999)}.png"
242
- filepath = os.path.join(out_dir, filename)
243
- img.save(filepath, "PNG", pnginfo=metadata)
244
- final_results.append(filepath)
245
-
246
- results = final_results
247
-
248
- finally:
249
- for temp_file in temp_files_to_clean:
250
- if temp_file and os.path.exists(temp_file):
251
- os.remove(temp_file)
252
- print(f"✅ Cleaned up temp file: {temp_file}")
253
-
 
 
 
 
 
254
  return results
 
1
+ import os
2
+ import random
3
+ import shutil
4
+ import torch
5
+ import gradio as gr
6
+ from PIL import Image
7
+ from typing import List, Dict, Any
8
+
9
+ from .base_pipeline import BasePipeline
10
+ from core.settings import *
11
+ from utils.app_utils import sanitize_prompt
12
+ from core.workflow_assembler import WorkflowAssembler
13
+ from .workflow_executor import WorkflowExecutor
14
+ from .pipeline_input_processor import process_pipeline_inputs
15
+
16
+ class SdImagePipeline(BasePipeline):
17
+ def get_required_models(self, model_display_name: str, **kwargs) -> List[str]:
18
+ model_info = ALL_MODEL_MAP.get(model_display_name)
19
+ if not model_info:
20
+ return [model_display_name]
21
+
22
+ path_or_components = model_info[1]
23
+ if isinstance(path_or_components, dict):
24
+ return [v for v in path_or_components.values() if v and v != "pixel_space"]
25
+ else:
26
+ return [model_display_name]
27
+
28
+ def _gpu_logic(self, ui_inputs: Dict, loras_string: str, workflow: Dict[str, Any], assembler: WorkflowAssembler, progress=gr.Progress(track_tqdm=True)):
29
+ model_display_name = ui_inputs['model_display_name']
30
+
31
+ progress(0.4, desc="Executing workflow...")
32
+
33
+ initial_objects = {}
34
+
35
+ decoded_images_tensor = WorkflowExecutor.execute_workflow(workflow, initial_objects=initial_objects)
36
+
37
+ output_images = []
38
+ start_seed = ui_inputs['seed'] if ui_inputs['seed'] != -1 else random.randint(0, 2**64 - 1)
39
+ for i in range(decoded_images_tensor.shape[0]):
40
+ img_tensor = decoded_images_tensor[i]
41
+ pil_image = Image.fromarray((img_tensor.cpu().numpy() * 255.0).astype("uint8"))
42
+ current_seed = start_seed + i
43
+
44
+ width_for_meta = ui_inputs.get('width', 'N/A')
45
+ height_for_meta = ui_inputs.get('height', 'N/A')
46
+
47
+ params_string = f"{ui_inputs['positive_prompt']}\nNegative prompt: {ui_inputs['negative_prompt']}\n"
48
+ params_string += f"Steps: {ui_inputs['num_inference_steps']}, Sampler: {ui_inputs['sampler']}, Scheduler: {ui_inputs['scheduler']}, CFG scale: {ui_inputs['guidance_scale']}, Seed: {current_seed}, Size: {width_for_meta}x{height_for_meta}, Base Model: {model_display_name}"
49
+ if ui_inputs['task_type'] != 'txt2img': params_string += f", Denoise: {ui_inputs['denoise']}"
50
+ if ui_inputs.get('clip_skip') and ui_inputs['clip_skip'] != 1: params_string += f", Clip skip: {abs(ui_inputs['clip_skip'])}"
51
+ if loras_string: params_string += f", {loras_string}"
52
+
53
+ pil_image.info = {'parameters': params_string.strip()}
54
+ output_images.append(pil_image)
55
+
56
+ return output_images
57
+
58
+ def run(self, ui_inputs: Dict, progress):
59
+ progress(0, desc="Preparing models...")
60
+
61
+ task_type = ui_inputs['task_type']
62
+ model_display_name = ui_inputs['model_display_name']
63
+ model_type = MODEL_TYPE_MAP.get(model_display_name, 'sdxl')
64
+
65
+ architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
66
+ workflow_model_type = architectures_dict.get(model_type, {}).get("model_type", model_type.lower().replace(" ", "").replace(".", ""))
67
+
68
+ ui_inputs['positive_prompt'] = sanitize_prompt(ui_inputs.get('positive_prompt', ''))
69
+ ui_inputs['negative_prompt'] = sanitize_prompt(ui_inputs.get('negative_prompt', ''))
70
+
71
+ if 'clip_skip' in ui_inputs and ui_inputs['clip_skip'] is not None:
72
+ ui_inputs['clip_skip'] = -int(ui_inputs['clip_skip'])
73
+ else:
74
+ ui_inputs['clip_skip'] = -1
75
+
76
+ required_models = self.get_required_models(model_display_name=model_display_name)
77
+
78
+ is_pid_enabled = (ui_inputs.get('pid_settings', 'OFF') == 'ON' and task_type == 'txt2img')
79
+ if is_pid_enabled:
80
+ import yaml
81
+ pid_config_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'yaml', 'pid.yaml')
82
+ pid_unet_name = "pid_flux1_1024_to_4096_4step_mxfp8.safetensors"
83
+ try:
84
+ with open(pid_config_path, 'r', encoding='utf-8') as f:
85
+ pid_config = yaml.safe_load(f) or {}
86
+ pid_items = pid_config.get("PiD", [])
87
+ for item in pid_items:
88
+ archs = item.get("architectures", [])
89
+ if workflow_model_type in archs:
90
+ pid_unet_name = item.get("filepath")
91
+ break
92
+ except Exception as e:
93
+ print(f"Error loading PiD config for download: {e}")
94
+
95
+ if pid_unet_name not in required_models:
96
+ required_models.append(pid_unet_name)
97
+ if "gemma_2_2b_it_elm_fp8_scaled.safetensors" not in required_models:
98
+ required_models.append("gemma_2_2b_it_elm_fp8_scaled.safetensors")
99
+
100
+ self.model_manager.ensure_models_downloaded(required_models, progress=progress)
101
+
102
+ temp_files_to_clean = []
103
+ try:
104
+ processed = process_pipeline_inputs(ui_inputs, progress, workflow_model_type)
105
+ temp_files_to_clean.extend(processed["temp_files_to_clean"])
106
+
107
+ active_loras_for_gpu = processed["active_loras_for_gpu"]
108
+ active_loras_for_meta = processed["active_loras_for_meta"]
109
+ active_controlnets = processed["active_controlnets"]
110
+ active_anima_controlnets = processed["active_anima_controlnets"]
111
+ active_diffsynth_controlnets = processed["active_diffsynth_controlnets"]
112
+ active_krea2_controlnets = processed.get("active_krea2_controlnets", [])
113
+ active_ipadapters = processed["active_ipadapters"]
114
+ active_flux1_ipadapters = processed["active_flux1_ipadapters"]
115
+ active_sd3_ipadapters = processed["active_sd3_ipadapters"]
116
+ active_styles = processed["active_styles"]
117
+ active_reference_latents = processed["active_reference_latents"]
118
+ active_hidream_o1_reference = processed["active_hidream_o1_reference"]
119
+ active_conditioning = processed["active_conditioning"]
120
+
121
+ loras_string = f"LoRAs: [{', '.join(active_loras_for_meta)}]" if active_loras_for_meta else ""
122
+
123
+ progress(0.8, desc="Assembling workflow...")
124
+
125
+ if ui_inputs.get('seed') == -1:
126
+ ui_inputs['seed'] = random.randint(0, 2**32 - 1)
127
+
128
+ model_info = ALL_MODEL_MAP[model_display_name]
129
+ path_or_components = model_info[1]
130
+ latent_type = model_info[3] if len(model_info) > 3 and model_info[3] else 'latent'
131
+ latent_generator_template = "EmptyLatentImage"
132
+ if latent_type == 'sd3_latent':
133
+ latent_generator_template = "EmptySD3LatentImage"
134
+ elif latent_type == 'chroma_radiance_latent':
135
+ latent_generator_template = "EmptyChromaRadianceLatentImage"
136
+ elif latent_type == 'hunyuan_latent':
137
+ latent_generator_template = "EmptyHunyuanImageLatent"
138
+
139
+ dynamic_values = {
140
+ 'task_type': ui_inputs['task_type'],
141
+ 'model_type': workflow_model_type,
142
+ 'latent_type': latent_type,
143
+ 'latent_generator_template': latent_generator_template
144
+ }
145
+
146
+ recipe_path = os.path.join(os.path.dirname(__file__), "workflow_recipes", "sd_unified_recipe.yaml")
147
+ assembler = WorkflowAssembler(recipe_path, dynamic_values=dynamic_values)
148
+
149
+ hidream_o1_smoothing_data = []
150
+ if workflow_model_type == 'hidream-o1' and model_display_name == "HiDream-O1-Image":
151
+ hidream_o1_smoothing_data.append({})
152
+
153
+ workflow_inputs = {
154
+ **ui_inputs,
155
+ "positive_prompt": ui_inputs['positive_prompt'], "negative_prompt": ui_inputs['negative_prompt'],
156
+ "seed": ui_inputs['seed'], "steps": ui_inputs['num_inference_steps'], "cfg": ui_inputs['guidance_scale'],
157
+ "sampler_name": ui_inputs['sampler'], "scheduler": ui_inputs['scheduler'],
158
+ "batch_size": ui_inputs['batch_size'],
159
+ "clip_skip": ui_inputs['clip_skip'],
160
+ "denoise": ui_inputs['denoise'],
161
+ "vae_name": ui_inputs.get('vae_name'),
162
+ "guidance": ui_inputs.get('guidance', 3.5),
163
+ "lora_chain": active_loras_for_gpu,
164
+ "controlnet_chain": active_controlnets if not active_anima_controlnets else [],
165
+ "anima_controlnet_lllite_chain": active_anima_controlnets,
166
+ "diffsynth_controlnet_chain": active_diffsynth_controlnets,
167
+ "krea2_controlnet_chain": active_krea2_controlnets,
168
+ "ipadapter_chain": active_ipadapters,
169
+ "flux1_ipadapter_chain": active_flux1_ipadapters,
170
+ "sd3_ipadapter_chain": active_sd3_ipadapters,
171
+ "style_chain": active_styles,
172
+ "conditioning_chain": active_conditioning,
173
+ "reference_latent_chain": active_reference_latents,
174
+ "hidream_o1_reference_chain": active_hidream_o1_reference,
175
+ "vae_chain": [ui_inputs.get('vae_name')] if ui_inputs.get('vae_name') else [],
176
+ "hidream_o1_smoothing_chain": hidream_o1_smoothing_data,
177
+ "pid_chain": [ui_inputs.get('pid_settings', 'OFF')] if is_pid_enabled else [],
178
+ "scheduler_width": ui_inputs.get('width', 1024),
179
+ "scheduler_height": ui_inputs.get('height', 1024),
180
+ }
181
+
182
+ if isinstance(path_or_components, dict):
183
+ workflow_inputs.update({
184
+ 'unet_name': path_or_components.get('unet'),
185
+ 'unet_uncond_name': path_or_components.get('unet_uncond'),
186
+ 'vae_name': ui_inputs.get('vae_name') or path_or_components.get('vae'),
187
+ 'clip_name': path_or_components.get('clip'),
188
+ 'clip1_name': path_or_components.get('clip1'),
189
+ 'clip2_name': path_or_components.get('clip2'),
190
+ 'clip3_name': path_or_components.get('clip3'),
191
+ 'clip4_name': path_or_components.get('clip4'),
192
+ 'lora_name': path_or_components.get('lora'),
193
+ })
194
+ else:
195
+ workflow_inputs['model_name'] = path_or_components
196
+
197
+ if task_type == 'txt2img':
198
+ workflow_inputs['width'] = ui_inputs['width']
199
+ workflow_inputs['height'] = ui_inputs['height']
200
+
201
+ workflow = assembler.assemble(workflow_inputs)
202
+
203
+ progress(1.0, desc="All models ready. Requesting GPU for generation...")
204
+
205
+ results = self._execute_gpu_logic(
206
+ self._gpu_logic,
207
+ duration=ui_inputs['zero_gpu_duration'],
208
+ default_duration=60,
209
+ task_name=f"ImageGen ({task_type})",
210
+ ui_inputs=ui_inputs,
211
+ loras_string=loras_string,
212
+ workflow=workflow,
213
+ assembler=assembler,
214
+ progress=progress
215
+ )
216
+
217
+ import json
218
+ import glob
219
+ from PIL import PngImagePlugin
220
+
221
+ prompt_json = json.dumps(workflow)
222
+
223
+ out_dir = os.path.abspath(OUTPUT_DIR)
224
+ os.makedirs(out_dir, exist_ok=True)
225
+
226
+ try:
227
+ existing_files = glob.glob(os.path.join(out_dir, "gen_*.png"))
228
+ existing_files.sort(key=os.path.getmtime)
229
+ while len(existing_files) > 50:
230
+ os.remove(existing_files.pop(0))
231
+ except Exception as e:
232
+ print(f"Warning: Failed to cleanup output dir: {e}")
233
+
234
+ final_results = []
235
+ for img in results:
236
+ if not isinstance(img, Image.Image):
237
+ final_results.append(img)
238
+ continue
239
+
240
+ metadata = PngImagePlugin.PngInfo()
241
+ params_string = img.info.get("parameters", "")
242
+ if params_string:
243
+ metadata.add_text("parameters", params_string)
244
+ metadata.add_text("prompt", prompt_json)
245
+
246
+ filename = f"gen_{random.randint(1000000, 9999999)}.png"
247
+ filepath = os.path.join(out_dir, filename)
248
+ img.save(filepath, "PNG", pnginfo=metadata)
249
+ final_results.append(filepath)
250
+
251
+ results = final_results
252
+
253
+ finally:
254
+ for temp_file in temp_files_to_clean:
255
+ if temp_file and os.path.exists(temp_file):
256
+ os.remove(temp_file)
257
+ print(f"✅ Cleaned up temp file: {temp_file}")
258
+
259
  return results
core/pipelines/workflow_recipes/_partials/conditioning/krea-2.yaml ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ nodes:
2
+ unet_loader:
3
+ class_type: UNETLoader
4
+ title: "Load Diffusion Model"
5
+ params:
6
+ weight_dtype: "default"
7
+ clip_loader:
8
+ class_type: CLIPLoader
9
+ title: "Load CLIP"
10
+ params:
11
+ type: "krea2"
12
+ device: "default"
13
+ vae_loader:
14
+ class_type: VAELoader
15
+ title: "Load VAE"
16
+
17
+ connections:
18
+ - from: "unet_loader:0"
19
+ to: "ksampler:model"
20
+ - from: "clip_loader:0"
21
+ to: "pos_prompt:clip"
22
+ - from: "clip_loader:0"
23
+ to: "neg_prompt:clip"
24
+ - from: "pos_prompt:0"
25
+ to: "ksampler:positive"
26
+ - from: "neg_prompt:0"
27
+ to: "ksampler:negative"
28
+ - from: "vae_loader:0"
29
+ to: "vae_decode:vae"
30
+ - from: "vae_loader:0"
31
+ to: "vae_encode:vae"
32
+
33
+ dynamic_lora_chains:
34
+ lora_chain:
35
+ template: "LoraLoader"
36
+ output_map:
37
+ "unet_loader:0": "model"
38
+ "clip_loader:0": "clip"
39
+ input_map:
40
+ "model": "model"
41
+ "clip": "clip"
42
+ end_input_map:
43
+ "model": ["ksampler:model"]
44
+ "clip": ["pos_prompt:clip", "neg_prompt:clip"]
45
+
46
+ dynamic_krea2_controlnet_chains:
47
+ krea2_controlnet_chain:
48
+ ksampler_node: "ksampler"
49
+ vae_source: "vae_loader:0"
50
+
51
+ dynamic_conditioning_chains:
52
+ conditioning_chain:
53
+ ksampler_node: "ksampler"
54
+ clip_source: "clip_loader:0"
55
+
56
+ dynamic_pid_chains:
57
+ pid_chain:
58
+ ksampler_node: "ksampler"
59
+
60
+ ui_map:
61
+ unet_name: "unet_loader:unet_name"
62
+ clip_name: "clip_loader:clip_name"
63
+ vae_name: "vae_loader:vae_name"
core/pipelines/workflow_recipes/_partials/conditioning/qwen-image.yaml CHANGED
@@ -13,12 +13,6 @@ nodes:
13
  params:
14
  type: "qwen_image"
15
  device: "default"
16
-
17
- lora_loader:
18
- class_type: LoraLoaderModelOnly
19
- title: "Load Qwen Lightning LoRA"
20
- params:
21
- strength_model: 1.0
22
  model_sampler:
23
  class_type: ModelSamplingAuraFlow
24
  title: "ModelSamplingAuraFlow"
@@ -27,8 +21,6 @@ nodes:
27
 
28
  connections:
29
  - from: "unet_loader:0"
30
- to: "lora_loader:model"
31
- - from: "lora_loader:0"
32
  to: "model_sampler:model"
33
 
34
  - from: "model_sampler:0"
@@ -53,7 +45,7 @@ dynamic_lora_chains:
53
  lora_chain:
54
  template: "LoraLoader"
55
  output_map:
56
- "lora_loader:0": "model"
57
  "clip_loader:0": "clip"
58
  input_map:
59
  "model": "model"
@@ -80,5 +72,4 @@ dynamic_pid_chains:
80
  ui_map:
81
  unet_name: "unet_loader:unet_name"
82
  vae_name: "vae_loader:vae_name"
83
- clip_name: "clip_loader:clip_name"
84
- lora_name: "lora_loader:lora_name"
 
13
  params:
14
  type: "qwen_image"
15
  device: "default"
 
 
 
 
 
 
16
  model_sampler:
17
  class_type: ModelSamplingAuraFlow
18
  title: "ModelSamplingAuraFlow"
 
21
 
22
  connections:
23
  - from: "unet_loader:0"
 
 
24
  to: "model_sampler:model"
25
 
26
  - from: "model_sampler:0"
 
45
  lora_chain:
46
  template: "LoraLoader"
47
  output_map:
48
+ "unet_loader:0": "model"
49
  "clip_loader:0": "clip"
50
  input_map:
51
  "model": "model"
 
72
  ui_map:
73
  unet_name: "unet_loader:unet_name"
74
  vae_name: "vae_loader:vae_name"
75
+ clip_name: "clip_loader:clip_name"
 
core/settings.py CHANGED
@@ -192,6 +192,7 @@ try:
192
  MAX_IPADAPTERS = _constants.get('MAX_IPADAPTERS', 5)
193
  LORA_SOURCE_CHOICES = _constants.get('LORA_SOURCE_CHOICES', ["Civitai", "File"])
194
  RESOLUTION_MAP = _constants.get('RESOLUTION_MAP', {})
 
195
  ARCHITECTURES_CONFIG = load_architectures_config()
196
  FEATURES_CONFIG = load_features_config()
197
  MODEL_DEFAULTS_CONFIG = load_model_defaults()
@@ -200,6 +201,7 @@ except Exception as e:
200
  MAX_LORAS, MAX_EMBEDDINGS, MAX_CONDITIONINGS, MAX_CONTROLNETS, MAX_IPADAPTERS = 5, 5, 10, 5, 5
201
  LORA_SOURCE_CHOICES = ["Civitai", "File"]
202
  RESOLUTION_MAP = {}
 
203
  ARCHITECTURES_CONFIG = {}
204
  FEATURES_CONFIG = {}
205
  MODEL_DEFAULTS_CONFIG = {}
 
192
  MAX_IPADAPTERS = _constants.get('MAX_IPADAPTERS', 5)
193
  LORA_SOURCE_CHOICES = _constants.get('LORA_SOURCE_CHOICES', ["Civitai", "File"])
194
  RESOLUTION_MAP = _constants.get('RESOLUTION_MAP', {})
195
+ MULTIPLIERS_MAP = _constants.get('MULTIPLIERS_MAP', {})
196
  ARCHITECTURES_CONFIG = load_architectures_config()
197
  FEATURES_CONFIG = load_features_config()
198
  MODEL_DEFAULTS_CONFIG = load_model_defaults()
 
201
  MAX_LORAS, MAX_EMBEDDINGS, MAX_CONDITIONINGS, MAX_CONTROLNETS, MAX_IPADAPTERS = 5, 5, 10, 5, 5
202
  LORA_SOURCE_CHOICES = ["Civitai", "File"]
203
  RESOLUTION_MAP = {}
204
+ MULTIPLIERS_MAP = {}
205
  ARCHITECTURES_CONFIG = {}
206
  FEATURES_CONFIG = {}
207
  MODEL_DEFAULTS_CONFIG = {}
core/workflow_assembler.py CHANGED
@@ -36,7 +36,6 @@ class WorkflowAssembler:
36
  module = importlib.import_module(module_path)
37
  if hasattr(module, 'inject'):
38
  self.global_injectors[chain_type] = module.inject
39
- print(f"✅ Successfully registered global injector: {chain_type} from {module_path}")
40
  else:
41
  print(f"⚠️ Warning: Module '{module_path}' for injector '{chain_type}' does not have an 'inject' function.")
42
  except ImportError as e:
 
36
  module = importlib.import_module(module_path)
37
  if hasattr(module, 'inject'):
38
  self.global_injectors[chain_type] = module.inject
 
39
  else:
40
  print(f"⚠️ Warning: Module '{module_path}' for injector '{chain_type}' does not have an 'inject' function.")
41
  except ImportError as e:
requirements.txt CHANGED
@@ -1,6 +1,6 @@
1
- comfyui-frontend-package==1.45.15
2
- comfyui-workflow-templates==0.9.98
3
- comfyui-embedded-docs==0.5.2
4
  torch
5
  torchsde
6
  torchvision
@@ -22,8 +22,8 @@ alembic
22
  SQLAlchemy>=2.0.0
23
  filelock
24
  av>=16.0.0
25
- comfy-kitchen==0.2.10
26
- comfy-aimdo==0.4.8
27
  requests
28
  simpleeval>=1.0.0
29
  blake3
@@ -33,12 +33,13 @@ kornia>=0.7.1
33
  spandrel
34
  pydantic~=2.0
35
  pydantic-settings~=2.0
36
- PyOpenGL
37
- glfw
38
 
39
 
40
  diffusers
41
  protobuf
 
42
  huggingface-hub
43
  imageio
44
  spaces
 
1
+ comfyui-frontend-package==1.45.21
2
+ comfyui-workflow-templates==0.11.9
3
+ comfyui-embedded-docs==0.5.8
4
  torch
5
  torchsde
6
  torchvision
 
22
  SQLAlchemy>=2.0.0
23
  filelock
24
  av>=16.0.0
25
+ comfy-kitchen==0.2.20
26
+ comfy-aimdo==0.4.10
27
  requests
28
  simpleeval>=1.0.0
29
  blake3
 
33
  spandrel
34
  pydantic~=2.0
35
  pydantic-settings~=2.0
36
+ PyOpenGL>=3.1.8
37
+ comfy-angle
38
 
39
 
40
  diffusers
41
  protobuf
42
+ insightface
43
  huggingface-hub
44
  imageio
45
  spaces
ui/events/__init__.py CHANGED
@@ -6,5 +6,7 @@ from .config_loaders import (
6
  get_anima_cn_defaults,
7
  load_diffsynth_controlnet_config,
8
  get_diffsynth_cn_defaults,
 
 
9
  load_ipadapter_config
10
  )
 
6
  get_anima_cn_defaults,
7
  load_diffsynth_controlnet_config,
8
  get_diffsynth_cn_defaults,
9
+ load_krea2_controlnet_config,
10
+ get_krea2_cn_defaults,
11
  load_ipadapter_config
12
  )
ui/events/chain_handlers.py CHANGED
@@ -12,6 +12,7 @@ from .config_loaders import (
12
  load_controlnet_config,
13
  load_anima_controlnet_lllite_config,
14
  load_diffsynth_controlnet_config,
 
15
  load_ipadapter_config
16
  )
17
 
@@ -191,6 +192,99 @@ def create_controlnet_event_handlers(prefix, ui_components):
191
  )
192
 
193
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  def create_anima_controlnet_lllite_event_handlers(prefix, ui_components):
195
  cn_rows = ui_components.get(f'anima_controlnet_lllite_rows_{prefix}')
196
  if not cn_rows: return
@@ -677,4 +771,4 @@ def create_conditioning_event_handlers(prefix, ui_components):
677
  add_outputs = [count_state, add_button, del_button] + rows
678
  del_outputs = [count_state, add_button, del_button] + rows + prompts
679
  add_button.click(fn=add_row, inputs=[count_state], outputs=add_outputs, show_progress=False)
680
- del_button.click(fn=del_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
 
12
  load_controlnet_config,
13
  load_anima_controlnet_lllite_config,
14
  load_diffsynth_controlnet_config,
15
+ load_krea2_controlnet_config,
16
  load_ipadapter_config
17
  )
18
 
 
192
  )
193
 
194
 
195
+ def create_krea2_controlnet_event_handlers(prefix, ui_components):
196
+ cn_rows = ui_components.get(f'krea2_controlnet_rows_{prefix}')
197
+ if not cn_rows: return
198
+ cn_types = ui_components[f'krea2_controlnet_types_{prefix}']
199
+ cn_series = ui_components[f'krea2_controlnet_series_{prefix}']
200
+ cn_filepaths = ui_components[f'krea2_controlnet_filepaths_{prefix}']
201
+ cn_images = ui_components[f'krea2_controlnet_images_{prefix}']
202
+ cn_strengths = ui_components[f'krea2_controlnet_strengths_{prefix}']
203
+
204
+ count_state = ui_components[f'krea2_controlnet_count_state_{prefix}']
205
+ add_button = ui_components[f'add_krea2_controlnet_button_{prefix}']
206
+ del_button = ui_components[f'delete_krea2_controlnet_button_{prefix}']
207
+ accordion = ui_components[f'krea2_controlnet_accordion_{prefix}']
208
+
209
+ def add_cn_row(c):
210
+ c += 1
211
+ updates = {
212
+ count_state: c,
213
+ cn_rows[c-1]: gr.update(visible=True),
214
+ add_button: gr.update(visible=c < MAX_CONTROLNETS),
215
+ del_button: gr.update(visible=True)
216
+ }
217
+ return updates
218
+
219
+ def del_cn_row(c):
220
+ c -= 1
221
+ updates = {
222
+ count_state: c,
223
+ cn_rows[c]: gr.update(visible=False),
224
+ cn_images[c]: None,
225
+ cn_strengths[c]: 1.0,
226
+ add_button: gr.update(visible=True),
227
+ del_button: gr.update(visible=c > 0)
228
+ }
229
+ return updates
230
+
231
+ add_outputs = [count_state, add_button, del_button] + cn_rows
232
+ del_outputs = [count_state, add_button, del_button] + cn_rows + cn_images + cn_strengths
233
+ add_button.click(fn=add_cn_row, inputs=[count_state], outputs=add_outputs, show_progress=False)
234
+ del_button.click(fn=del_cn_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
235
+
236
+ def on_cn_type_change(selected_type):
237
+ cn_config = load_krea2_controlnet_config()
238
+ series_choices = []
239
+ if selected_type:
240
+ series_choices = sorted(list(set(
241
+ model.get("Series", "Default") for model in cn_config
242
+ if selected_type in model.get("Type", [])
243
+ )))
244
+ default_series = series_choices[0] if series_choices else None
245
+ filepath = "None"
246
+ if default_series:
247
+ for model in cn_config:
248
+ if model.get("Series") == default_series and selected_type in model.get("Type", []):
249
+ filepath = model.get("Filepath")
250
+ break
251
+ return gr.update(choices=series_choices, value=default_series), filepath
252
+
253
+ def on_cn_series_change(selected_series, selected_type):
254
+ cn_config = load_krea2_controlnet_config()
255
+ filepath = "None"
256
+ if selected_series and selected_type:
257
+ for model in cn_config:
258
+ if model.get("Series") == selected_series and selected_type in model.get("Type", []):
259
+ filepath = model.get("Filepath")
260
+ break
261
+ return filepath
262
+
263
+ for i in range(MAX_CONTROLNETS):
264
+ cn_types[i].change(
265
+ fn=on_cn_type_change,
266
+ inputs=[cn_types[i]],
267
+ outputs=[cn_series[i], cn_filepaths[i]],
268
+ show_progress=False
269
+ )
270
+ cn_series[i].change(
271
+ fn=on_cn_series_change,
272
+ inputs=[cn_series[i], cn_types[i]],
273
+ outputs=[cn_filepaths[i]],
274
+ show_progress=False
275
+ )
276
+
277
+ def on_accordion_expand(*images):
278
+ return [gr.update() for _ in images]
279
+
280
+ accordion.expand(
281
+ fn=on_accordion_expand,
282
+ inputs=cn_images,
283
+ outputs=cn_images,
284
+ show_progress=False
285
+ )
286
+
287
+
288
  def create_anima_controlnet_lllite_event_handlers(prefix, ui_components):
289
  cn_rows = ui_components.get(f'anima_controlnet_lllite_rows_{prefix}')
290
  if not cn_rows: return
 
771
  add_outputs = [count_state, add_button, del_button] + rows
772
  del_outputs = [count_state, add_button, del_button] + rows + prompts
773
  add_button.click(fn=add_row, inputs=[count_state], outputs=add_outputs, show_progress=False)
774
+ del_button.click(fn=del_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
ui/events/change_handlers.py CHANGED
@@ -13,10 +13,11 @@ from .config_loaders import (
13
  get_cn_defaults,
14
  get_anima_cn_defaults,
15
  get_diffsynth_cn_defaults,
 
16
  load_ipadapter_config
17
  )
18
 
19
- def make_update_fn(m_comp, cat_comp, cs_comp, ar_comp, width_comp, height_comp, cn_types, cn_series, cn_filepaths, anima_cn_types, anima_cn_series, anima_cn_filepaths, diffsynth_cn_types, diffsynth_cn_series, diffsynth_cn_filepaths, ipa_preset, lora_acc, cn_acc, anima_cn_acc, diffsynth_cn_acc, ipa_acc, sd3_ipa_acc, flux1_ipa_acc, style_acc, embed_acc, cond_acc, ref_latent_acc, hidream_o1_ref_acc, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp, pid_acc=None):
20
  def update_fn(*args):
21
  arch = args[0]
22
  category = args[1]
@@ -58,6 +59,7 @@ def make_update_fn(m_comp, cat_comp, cs_comp, ar_comp, width_comp, height_comp,
58
  if cn_acc: updates[cn_acc] = gr.update(visible=('controlnet' in enabled_chains))
59
  if anima_cn_acc: updates[anima_cn_acc] = gr.update(visible=('anima_controlnet_lllite' in enabled_chains))
60
  if diffsynth_cn_acc: updates[diffsynth_cn_acc] = gr.update(visible=('controlnet_model_patch' in enabled_chains))
 
61
  if ipa_acc: updates[ipa_acc] = gr.update(visible=('ipadapter' in enabled_chains))
62
  if flux1_ipa_acc: updates[flux1_ipa_acc] = gr.update(visible=('flux1_ipadapter' in enabled_chains))
63
  if sd3_ipa_acc: updates[sd3_ipa_acc] = gr.update(visible=('sd3_ipadapter' in enabled_chains))
@@ -67,6 +69,7 @@ def make_update_fn(m_comp, cat_comp, cs_comp, ar_comp, width_comp, height_comp,
67
  if ref_latent_acc: updates[ref_latent_acc] = gr.update(visible=('reference_latent' in enabled_chains))
68
  if hidream_o1_ref_acc: updates[hidream_o1_ref_acc] = gr.update(visible=('hidream_o1_reference' in enabled_chains))
69
  if pid_acc: updates[pid_acc] = gr.update(visible=('pid' in enabled_chains))
 
70
 
71
  if cs_comp:
72
  updates[cs_comp] = gr.update(visible=(arch_model_type == "sd15"))
@@ -109,6 +112,14 @@ def make_update_fn(m_comp, cat_comp, cs_comp, ar_comp, width_comp, height_comp,
109
  updates[s_comp] = gr.update(choices=diffsynth_series_choices, value=diffsynth_default_series)
110
  for f_comp in diffsynth_cn_filepaths:
111
  updates[f_comp] = diffsynth_filepath
 
 
 
 
 
 
 
 
112
 
113
  if ipa_preset and (arch_model_type in ["sdxl", "sd15", "sd35"]):
114
  config = load_ipadapter_config()
@@ -131,7 +142,7 @@ def make_update_fn(m_comp, cat_comp, cs_comp, ar_comp, width_comp, height_comp,
131
  return update_fn
132
 
133
 
134
- def make_model_change_fn(cat_comp_ref, cs_comp, ar_comp, width_comp, height_comp, cn_types, cn_series, cn_filepaths, anima_cn_types, anima_cn_series, anima_cn_filepaths, diffsynth_cn_types, diffsynth_cn_series, diffsynth_cn_filepaths, arch_comp_ref, ipa_preset, lora_acc, cn_acc, anima_cn_acc, diffsynth_cn_acc, ipa_acc, sd3_ipa_acc, flux1_ipa_acc, style_acc, embed_acc, cond_acc, ref_latent_acc, hidream_o1_ref_acc, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp, pid_acc=None):
135
  def change_fn(*args):
136
  model_name = args[0]
137
  idx = 1
@@ -178,6 +189,7 @@ def make_model_change_fn(cat_comp_ref, cs_comp, ar_comp, width_comp, height_comp
178
  if cn_acc: updates[cn_acc] = gr.update(visible=('controlnet' in enabled_chains))
179
  if anima_cn_acc: updates[anima_cn_acc] = gr.update(visible=('anima_controlnet_lllite' in enabled_chains))
180
  if diffsynth_cn_acc: updates[diffsynth_cn_acc] = gr.update(visible=('controlnet_model_patch' in enabled_chains))
 
181
  if ipa_acc: updates[ipa_acc] = gr.update(visible=('ipadapter' in enabled_chains))
182
  if flux1_ipa_acc: updates[flux1_ipa_acc] = gr.update(visible=('flux1_ipadapter' in enabled_chains))
183
  if sd3_ipa_acc: updates[sd3_ipa_acc] = gr.update(visible=('sd3_ipadapter' in enabled_chains))
@@ -187,6 +199,7 @@ def make_model_change_fn(cat_comp_ref, cs_comp, ar_comp, width_comp, height_comp
187
  if ref_latent_acc: updates[ref_latent_acc] = gr.update(visible=('reference_latent' in enabled_chains))
188
  if hidream_o1_ref_acc: updates[hidream_o1_ref_acc] = gr.update(visible=('hidream_o1_reference' in enabled_chains))
189
  if pid_acc: updates[pid_acc] = gr.update(visible=('pid' in enabled_chains))
 
190
 
191
  if cs_comp:
192
  updates[cs_comp] = gr.update(visible=(arch_model_type == "sd15"))
@@ -229,6 +242,14 @@ def make_model_change_fn(cat_comp_ref, cs_comp, ar_comp, width_comp, height_comp
229
  updates[s_comp] = gr.update(choices=diffsynth_series_choices, value=diffsynth_default_series)
230
  for f_comp in diffsynth_cn_filepaths:
231
  updates[f_comp] = diffsynth_filepath
 
 
 
 
 
 
 
 
232
 
233
  if ipa_preset and (arch_model_type in ["sdxl", "sd15", "sd35"]):
234
  config = load_ipadapter_config()
@@ -260,6 +281,7 @@ def initialize_all_cn_dropdowns(ui_components):
260
  all_types, default_type, series_choices, default_series, filepath = get_cn_defaults(controlnet_key)
261
  anima_all_types, anima_default_type, anima_series_choices, anima_default_series, anima_filepath = get_anima_cn_defaults()
262
  diffsynth_all_types, diffsynth_default_type, diffsynth_series_choices, diffsynth_default_series, diffsynth_filepath = get_diffsynth_cn_defaults(controlnet_key)
 
263
 
264
  updates = {}
265
  for prefix in ["txt2img", "img2img", "inpaint", "outpaint", "hires_fix"]:
@@ -286,6 +308,14 @@ def initialize_all_cn_dropdowns(ui_components):
286
  updates[series_dd] = gr.update(choices=diffsynth_series_choices, value=default_series)
287
  for filepath_state in ui_components[f'diffsynth_controlnet_filepaths_{prefix}']:
288
  updates[filepath_state] = diffsynth_filepath
 
 
 
 
 
 
 
 
289
 
290
  return updates
291
 
 
13
  get_cn_defaults,
14
  get_anima_cn_defaults,
15
  get_diffsynth_cn_defaults,
16
+ get_krea2_cn_defaults,
17
  load_ipadapter_config
18
  )
19
 
20
+ def make_update_fn(m_comp, cat_comp, cs_comp, ar_comp, width_comp, height_comp, cn_types, cn_series, cn_filepaths, anima_cn_types, anima_cn_series, anima_cn_filepaths, diffsynth_cn_types, diffsynth_cn_series, diffsynth_cn_filepaths, krea2_cn_types, krea2_cn_series, krea2_cn_filepaths, ipa_preset, lora_acc, cn_acc, anima_cn_acc, diffsynth_cn_acc, krea2_cn_acc, ipa_acc, sd3_ipa_acc, flux1_ipa_acc, style_acc, embed_acc, cond_acc, ref_latent_acc, hidream_o1_ref_acc, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp, pid_acc=None, vae_acc=None):
21
  def update_fn(*args):
22
  arch = args[0]
23
  category = args[1]
 
59
  if cn_acc: updates[cn_acc] = gr.update(visible=('controlnet' in enabled_chains))
60
  if anima_cn_acc: updates[anima_cn_acc] = gr.update(visible=('anima_controlnet_lllite' in enabled_chains))
61
  if diffsynth_cn_acc: updates[diffsynth_cn_acc] = gr.update(visible=('controlnet_model_patch' in enabled_chains))
62
+ if krea2_cn_acc: updates[krea2_cn_acc] = gr.update(visible=('krea2_controlnet' in enabled_chains))
63
  if ipa_acc: updates[ipa_acc] = gr.update(visible=('ipadapter' in enabled_chains))
64
  if flux1_ipa_acc: updates[flux1_ipa_acc] = gr.update(visible=('flux1_ipadapter' in enabled_chains))
65
  if sd3_ipa_acc: updates[sd3_ipa_acc] = gr.update(visible=('sd3_ipadapter' in enabled_chains))
 
69
  if ref_latent_acc: updates[ref_latent_acc] = gr.update(visible=('reference_latent' in enabled_chains))
70
  if hidream_o1_ref_acc: updates[hidream_o1_ref_acc] = gr.update(visible=('hidream_o1_reference' in enabled_chains))
71
  if pid_acc: updates[pid_acc] = gr.update(visible=('pid' in enabled_chains))
72
+ if vae_acc: updates[vae_acc] = gr.update(visible=('vae' in enabled_chains))
73
 
74
  if cs_comp:
75
  updates[cs_comp] = gr.update(visible=(arch_model_type == "sd15"))
 
112
  updates[s_comp] = gr.update(choices=diffsynth_series_choices, value=diffsynth_default_series)
113
  for f_comp in diffsynth_cn_filepaths:
114
  updates[f_comp] = diffsynth_filepath
115
+
116
+ krea2_all_types, krea2_default_type, krea2_series_choices, krea2_default_series, krea2_filepath = get_krea2_cn_defaults()
117
+ for t_comp in krea2_cn_types:
118
+ updates[t_comp] = gr.update(choices=krea2_all_types, value=krea2_default_type)
119
+ for s_comp in krea2_cn_series:
120
+ updates[s_comp] = gr.update(choices=krea2_series_choices, value=krea2_default_series)
121
+ for f_comp in krea2_cn_filepaths:
122
+ updates[f_comp] = krea2_filepath
123
 
124
  if ipa_preset and (arch_model_type in ["sdxl", "sd15", "sd35"]):
125
  config = load_ipadapter_config()
 
142
  return update_fn
143
 
144
 
145
+ def make_model_change_fn(cat_comp_ref, cs_comp, ar_comp, width_comp, height_comp, cn_types, cn_series, cn_filepaths, anima_cn_types, anima_cn_series, anima_cn_filepaths, diffsynth_cn_types, diffsynth_cn_series, diffsynth_cn_filepaths, krea2_cn_types, krea2_cn_series, krea2_cn_filepaths, arch_comp_ref, ipa_preset, lora_acc, cn_acc, anima_cn_acc, diffsynth_cn_acc, krea2_cn_acc, ipa_acc, sd3_ipa_acc, flux1_ipa_acc, style_acc, embed_acc, cond_acc, ref_latent_acc, hidream_o1_ref_acc, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp, pid_acc=None, vae_acc=None):
146
  def change_fn(*args):
147
  model_name = args[0]
148
  idx = 1
 
189
  if cn_acc: updates[cn_acc] = gr.update(visible=('controlnet' in enabled_chains))
190
  if anima_cn_acc: updates[anima_cn_acc] = gr.update(visible=('anima_controlnet_lllite' in enabled_chains))
191
  if diffsynth_cn_acc: updates[diffsynth_cn_acc] = gr.update(visible=('controlnet_model_patch' in enabled_chains))
192
+ if krea2_cn_acc: updates[krea2_cn_acc] = gr.update(visible=('krea2_controlnet' in enabled_chains))
193
  if ipa_acc: updates[ipa_acc] = gr.update(visible=('ipadapter' in enabled_chains))
194
  if flux1_ipa_acc: updates[flux1_ipa_acc] = gr.update(visible=('flux1_ipadapter' in enabled_chains))
195
  if sd3_ipa_acc: updates[sd3_ipa_acc] = gr.update(visible=('sd3_ipadapter' in enabled_chains))
 
199
  if ref_latent_acc: updates[ref_latent_acc] = gr.update(visible=('reference_latent' in enabled_chains))
200
  if hidream_o1_ref_acc: updates[hidream_o1_ref_acc] = gr.update(visible=('hidream_o1_reference' in enabled_chains))
201
  if pid_acc: updates[pid_acc] = gr.update(visible=('pid' in enabled_chains))
202
+ if vae_acc: updates[vae_acc] = gr.update(visible=('vae' in enabled_chains))
203
 
204
  if cs_comp:
205
  updates[cs_comp] = gr.update(visible=(arch_model_type == "sd15"))
 
242
  updates[s_comp] = gr.update(choices=diffsynth_series_choices, value=diffsynth_default_series)
243
  for f_comp in diffsynth_cn_filepaths:
244
  updates[f_comp] = diffsynth_filepath
245
+
246
+ krea2_all_types, krea2_default_type, krea2_series_choices, krea2_default_series, krea2_filepath = get_krea2_cn_defaults()
247
+ for t_comp in krea2_cn_types:
248
+ updates[t_comp] = gr.update(choices=krea2_all_types, value=krea2_default_type)
249
+ for s_comp in krea2_cn_series:
250
+ updates[s_comp] = gr.update(choices=krea2_series_choices, value=krea2_default_series)
251
+ for f_comp in krea2_cn_filepaths:
252
+ updates[f_comp] = krea2_filepath
253
 
254
  if ipa_preset and (arch_model_type in ["sdxl", "sd15", "sd35"]):
255
  config = load_ipadapter_config()
 
281
  all_types, default_type, series_choices, default_series, filepath = get_cn_defaults(controlnet_key)
282
  anima_all_types, anima_default_type, anima_series_choices, anima_default_series, anima_filepath = get_anima_cn_defaults()
283
  diffsynth_all_types, diffsynth_default_type, diffsynth_series_choices, diffsynth_default_series, diffsynth_filepath = get_diffsynth_cn_defaults(controlnet_key)
284
+ krea2_all_types, krea2_default_type, krea2_series_choices, krea2_default_series, krea2_filepath = get_krea2_cn_defaults()
285
 
286
  updates = {}
287
  for prefix in ["txt2img", "img2img", "inpaint", "outpaint", "hires_fix"]:
 
308
  updates[series_dd] = gr.update(choices=diffsynth_series_choices, value=default_series)
309
  for filepath_state in ui_components[f'diffsynth_controlnet_filepaths_{prefix}']:
310
  updates[filepath_state] = diffsynth_filepath
311
+
312
+ if f'krea2_controlnet_types_{prefix}' in ui_components:
313
+ for type_dd in ui_components[f'krea2_controlnet_types_{prefix}']:
314
+ updates[type_dd] = gr.update(choices=krea2_all_types, value=krea2_default_type)
315
+ for series_dd in ui_components[f'krea2_controlnet_series_{prefix}']:
316
+ updates[series_dd] = gr.update(choices=krea2_series_choices, value=krea2_default_series)
317
+ for filepath_state in ui_components[f'krea2_controlnet_filepaths_{prefix}']:
318
+ updates[filepath_state] = krea2_filepath
319
 
320
  return updates
321
 
ui/events/config_loaders.py CHANGED
@@ -116,6 +116,43 @@ def get_diffsynth_cn_defaults(arch_val):
116
  return all_types, default_type, series_choices, default_series, filepath
117
 
118
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  @lru_cache(maxsize=1)
120
  def load_ipadapter_config():
121
  _PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
@@ -128,4 +165,4 @@ def load_ipadapter_config():
128
  return config
129
  except Exception as e:
130
  print(f"Error loading ipadapter.yaml: {e}")
131
- return {}
 
116
  return all_types, default_type, series_choices, default_series, filepath
117
 
118
 
119
+ @lru_cache(maxsize=1)
120
+ def load_krea2_controlnet_config():
121
+ _PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
122
+ _CN_MODEL_LIST_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'krea2_controlnet_models.yaml')
123
+ try:
124
+ print("--- Loading krea2_controlnet_models.yaml ---")
125
+ with open(_CN_MODEL_LIST_PATH, 'r', encoding='utf-8') as f:
126
+ config = yaml.safe_load(f)
127
+ print("--- ✅ krea2_controlnet_models.yaml loaded successfully ---")
128
+ return config.get("Krea2_ControlNet", [])
129
+ except Exception as e:
130
+ print(f"Error loading krea2_controlnet_models.yaml: {e}")
131
+ return []
132
+
133
+ def get_krea2_cn_defaults():
134
+ cn_config = load_krea2_controlnet_config()
135
+ if not cn_config:
136
+ return [], None, [], None, "None"
137
+
138
+ all_types = sorted(list(set(t for model in cn_config for t in model.get("Type", []))))
139
+ default_type = all_types[0] if all_types else None
140
+
141
+ series_choices = []
142
+ if default_type:
143
+ series_choices = sorted(list(set(model.get("Series", "Default") for model in cn_config if default_type in model.get("Type", []))))
144
+ default_series = series_choices[0] if series_choices else None
145
+
146
+ filepath = "None"
147
+ if default_series and default_type:
148
+ for model in cn_config:
149
+ if model.get("Series") == default_series and default_type in model.get("Type", []):
150
+ filepath = model.get("Filepath")
151
+ break
152
+
153
+ return all_types, default_type, series_choices, default_series, filepath
154
+
155
+
156
  @lru_cache(maxsize=1)
157
  def load_ipadapter_config():
158
  _PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
165
  return config
166
  except Exception as e:
167
  print(f"Error loading ipadapter.yaml: {e}")
168
+ return {}
ui/events/main.py CHANGED
@@ -4,6 +4,7 @@ from .chain_handlers import (
4
  create_controlnet_event_handlers,
5
  create_anima_controlnet_lllite_event_handlers,
6
  create_diffsynth_controlnet_event_handlers,
 
7
  create_ipadapter_event_handlers,
8
  create_embedding_event_handlers,
9
  create_conditioning_event_handlers,
@@ -47,11 +48,16 @@ def attach_event_handlers(ui_components, demo):
47
  diffsynth_cn_types_list = ui_components.get(f'diffsynth_controlnet_types_{prefix}', [])
48
  diffsynth_cn_series_list = ui_components.get(f'diffsynth_controlnet_series_{prefix}', [])
49
  diffsynth_cn_filepaths_list = ui_components.get(f'diffsynth_controlnet_filepaths_{prefix}', [])
 
 
 
 
50
 
51
  lora_accordion = ui_components.get(f'lora_accordion_{prefix}')
52
  cn_accordion = ui_components.get(f'controlnet_accordion_{prefix}')
53
  anima_cn_accordion = ui_components.get(f'anima_controlnet_lllite_accordion_{prefix}')
54
  diffsynth_cn_accordion = ui_components.get(f'diffsynth_controlnet_accordion_{prefix}')
 
55
  ipa_accordion = ui_components.get(f'ipadapter_accordion_{prefix}')
56
  sd3_ipa_accordion = ui_components.get(f'sd3_ipadapter_accordion_{prefix}')
57
  flux1_ipa_accordion = ui_components.get(f'flux1_ipadapter_accordion_{prefix}')
@@ -61,6 +67,7 @@ def attach_event_handlers(ui_components, demo):
61
  ref_latent_accordion = ui_components.get(f'reference_latent_accordion_{prefix}')
62
  hidream_o1_ref_accordion = ui_components.get(f'hidream_o1_reference_accordion_{prefix}')
63
  pid_accordion = ui_components.get(f'pid_accordion_{prefix}')
 
64
 
65
  ipa_preset_list = ui_components.get(f'ipadapter_final_preset_{prefix}')
66
 
@@ -82,10 +89,12 @@ def attach_event_handlers(ui_components, demo):
82
  outputs.extend(cn_types_list + cn_series_list + cn_filepaths_list)
83
  outputs.extend(anima_cn_types_list + anima_cn_series_list + anima_cn_filepaths_list)
84
  outputs.extend(diffsynth_cn_types_list + diffsynth_cn_series_list + diffsynth_cn_filepaths_list)
 
85
  if lora_accordion: outputs.append(lora_accordion)
86
  if cn_accordion: outputs.append(cn_accordion)
87
  if anima_cn_accordion: outputs.append(anima_cn_accordion)
88
  if diffsynth_cn_accordion: outputs.append(diffsynth_cn_accordion)
 
89
  if ipa_accordion: outputs.append(ipa_accordion)
90
  if sd3_ipa_accordion: outputs.append(sd3_ipa_accordion)
91
  if flux1_ipa_accordion: outputs.append(flux1_ipa_accordion)
@@ -95,6 +104,7 @@ def attach_event_handlers(ui_components, demo):
95
  if ref_latent_accordion: outputs.append(ref_latent_accordion)
96
  if hidream_o1_ref_accordion: outputs.append(hidream_o1_ref_accordion)
97
  if pid_accordion: outputs.append(pid_accordion)
 
98
  if ipa_preset_list: outputs.append(ipa_preset_list)
99
 
100
  outputs.extend(valid_extra_comps)
@@ -104,9 +114,10 @@ def attach_event_handlers(ui_components, demo):
104
  cn_types_list, cn_series_list, cn_filepaths_list,
105
  anima_cn_types_list, anima_cn_series_list, anima_cn_filepaths_list,
106
  diffsynth_cn_types_list, diffsynth_cn_series_list, diffsynth_cn_filepaths_list,
107
- ipa_preset_list, lora_accordion, cn_accordion, anima_cn_accordion, diffsynth_cn_accordion, ipa_accordion, sd3_ipa_accordion, flux1_ipa_accordion, style_accordion, embedding_accordion, conditioning_accordion,
 
108
  ref_latent_accordion, hidream_o1_ref_accordion, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp,
109
- pid_acc=pid_accordion
110
  )
111
  inputs = [arch_comp, cat_comp]
112
  if aspect_ratio_comp:
@@ -124,10 +135,12 @@ def attach_event_handlers(ui_components, demo):
124
  outputs2.extend(cn_types_list + cn_series_list + cn_filepaths_list)
125
  outputs2.extend(anima_cn_types_list + anima_cn_series_list + anima_cn_filepaths_list)
126
  outputs2.extend(diffsynth_cn_types_list + diffsynth_cn_series_list + diffsynth_cn_filepaths_list)
 
127
  if lora_accordion: outputs2.append(lora_accordion)
128
  if cn_accordion: outputs2.append(cn_accordion)
129
  if anima_cn_accordion: outputs2.append(anima_cn_accordion)
130
  if diffsynth_cn_accordion: outputs2.append(diffsynth_cn_accordion)
 
131
  if ipa_accordion: outputs2.append(ipa_accordion)
132
  if sd3_ipa_accordion: outputs2.append(sd3_ipa_accordion)
133
  if flux1_ipa_accordion: outputs2.append(flux1_ipa_accordion)
@@ -137,6 +150,7 @@ def attach_event_handlers(ui_components, demo):
137
  if ref_latent_accordion: outputs2.append(ref_latent_accordion)
138
  if hidream_o1_ref_accordion: outputs2.append(hidream_o1_ref_accordion)
139
  if pid_accordion: outputs2.append(pid_accordion)
 
140
  if ipa_preset_list: outputs2.append(ipa_preset_list)
141
 
142
  outputs2.extend(valid_extra_comps)
@@ -151,9 +165,10 @@ def attach_event_handlers(ui_components, demo):
151
  cn_types_list, cn_series_list, cn_filepaths_list,
152
  anima_cn_types_list, anima_cn_series_list, anima_cn_filepaths_list,
153
  diffsynth_cn_types_list, diffsynth_cn_series_list, diffsynth_cn_filepaths_list,
154
- arch_comp, ipa_preset_list, lora_accordion, cn_accordion, anima_cn_accordion, diffsynth_cn_accordion, ipa_accordion, sd3_ipa_accordion, flux1_ipa_accordion, style_accordion, embedding_accordion, conditioning_accordion,
 
155
  ref_latent_accordion, hidream_o1_ref_accordion, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp,
156
- pid_acc=pid_accordion
157
  )
158
  model_comp.change(fn=change_fn, inputs=inputs2, outputs=outputs2)
159
 
@@ -161,6 +176,7 @@ def attach_event_handlers(ui_components, demo):
161
  create_controlnet_event_handlers(prefix, ui_components)
162
  create_anima_controlnet_lllite_event_handlers(prefix, ui_components)
163
  create_diffsynth_controlnet_event_handlers(prefix, ui_components)
 
164
  create_ipadapter_event_handlers(prefix, ui_components)
165
  create_embedding_event_handlers(prefix, ui_components)
166
  create_conditioning_event_handlers(prefix, ui_components)
@@ -225,6 +241,10 @@ def attach_event_handlers(ui_components, demo):
225
  all_load_outputs.extend(ui_components[f'diffsynth_controlnet_types_{prefix}'])
226
  all_load_outputs.extend(ui_components[f'diffsynth_controlnet_series_{prefix}'])
227
  all_load_outputs.extend(ui_components[f'diffsynth_controlnet_filepaths_{prefix}'])
 
 
 
 
228
  if f'ipadapter_final_preset_{prefix}' in ui_components:
229
  all_load_outputs.extend(ui_components[f'ipadapter_lora_strengths_{prefix}'])
230
  all_load_outputs.append(ui_components[f'ipadapter_final_preset_{prefix}'])
 
4
  create_controlnet_event_handlers,
5
  create_anima_controlnet_lllite_event_handlers,
6
  create_diffsynth_controlnet_event_handlers,
7
+ create_krea2_controlnet_event_handlers,
8
  create_ipadapter_event_handlers,
9
  create_embedding_event_handlers,
10
  create_conditioning_event_handlers,
 
48
  diffsynth_cn_types_list = ui_components.get(f'diffsynth_controlnet_types_{prefix}', [])
49
  diffsynth_cn_series_list = ui_components.get(f'diffsynth_controlnet_series_{prefix}', [])
50
  diffsynth_cn_filepaths_list = ui_components.get(f'diffsynth_controlnet_filepaths_{prefix}', [])
51
+
52
+ krea2_cn_types_list = ui_components.get(f'krea2_controlnet_types_{prefix}', [])
53
+ krea2_cn_series_list = ui_components.get(f'krea2_controlnet_series_{prefix}', [])
54
+ krea2_cn_filepaths_list = ui_components.get(f'krea2_controlnet_filepaths_{prefix}', [])
55
 
56
  lora_accordion = ui_components.get(f'lora_accordion_{prefix}')
57
  cn_accordion = ui_components.get(f'controlnet_accordion_{prefix}')
58
  anima_cn_accordion = ui_components.get(f'anima_controlnet_lllite_accordion_{prefix}')
59
  diffsynth_cn_accordion = ui_components.get(f'diffsynth_controlnet_accordion_{prefix}')
60
+ krea2_cn_accordion = ui_components.get(f'krea2_controlnet_accordion_{prefix}')
61
  ipa_accordion = ui_components.get(f'ipadapter_accordion_{prefix}')
62
  sd3_ipa_accordion = ui_components.get(f'sd3_ipadapter_accordion_{prefix}')
63
  flux1_ipa_accordion = ui_components.get(f'flux1_ipadapter_accordion_{prefix}')
 
67
  ref_latent_accordion = ui_components.get(f'reference_latent_accordion_{prefix}')
68
  hidream_o1_ref_accordion = ui_components.get(f'hidream_o1_reference_accordion_{prefix}')
69
  pid_accordion = ui_components.get(f'pid_accordion_{prefix}')
70
+ vae_accordion = ui_components.get(f'vae_accordion_{prefix}')
71
 
72
  ipa_preset_list = ui_components.get(f'ipadapter_final_preset_{prefix}')
73
 
 
89
  outputs.extend(cn_types_list + cn_series_list + cn_filepaths_list)
90
  outputs.extend(anima_cn_types_list + anima_cn_series_list + anima_cn_filepaths_list)
91
  outputs.extend(diffsynth_cn_types_list + diffsynth_cn_series_list + diffsynth_cn_filepaths_list)
92
+ outputs.extend(krea2_cn_types_list + krea2_cn_series_list + krea2_cn_filepaths_list)
93
  if lora_accordion: outputs.append(lora_accordion)
94
  if cn_accordion: outputs.append(cn_accordion)
95
  if anima_cn_accordion: outputs.append(anima_cn_accordion)
96
  if diffsynth_cn_accordion: outputs.append(diffsynth_cn_accordion)
97
+ if krea2_cn_accordion: outputs.append(krea2_cn_accordion)
98
  if ipa_accordion: outputs.append(ipa_accordion)
99
  if sd3_ipa_accordion: outputs.append(sd3_ipa_accordion)
100
  if flux1_ipa_accordion: outputs.append(flux1_ipa_accordion)
 
104
  if ref_latent_accordion: outputs.append(ref_latent_accordion)
105
  if hidream_o1_ref_accordion: outputs.append(hidream_o1_ref_accordion)
106
  if pid_accordion: outputs.append(pid_accordion)
107
+ if vae_accordion: outputs.append(vae_accordion)
108
  if ipa_preset_list: outputs.append(ipa_preset_list)
109
 
110
  outputs.extend(valid_extra_comps)
 
114
  cn_types_list, cn_series_list, cn_filepaths_list,
115
  anima_cn_types_list, anima_cn_series_list, anima_cn_filepaths_list,
116
  diffsynth_cn_types_list, diffsynth_cn_series_list, diffsynth_cn_filepaths_list,
117
+ krea2_cn_types_list, krea2_cn_series_list, krea2_cn_filepaths_list,
118
+ ipa_preset_list, lora_accordion, cn_accordion, anima_cn_accordion, diffsynth_cn_accordion, krea2_cn_accordion, ipa_accordion, sd3_ipa_accordion, flux1_ipa_accordion, style_accordion, embedding_accordion, conditioning_accordion,
119
  ref_latent_accordion, hidream_o1_ref_accordion, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp,
120
+ pid_acc=pid_accordion, vae_acc=vae_accordion
121
  )
122
  inputs = [arch_comp, cat_comp]
123
  if aspect_ratio_comp:
 
135
  outputs2.extend(cn_types_list + cn_series_list + cn_filepaths_list)
136
  outputs2.extend(anima_cn_types_list + anima_cn_series_list + anima_cn_filepaths_list)
137
  outputs2.extend(diffsynth_cn_types_list + diffsynth_cn_series_list + diffsynth_cn_filepaths_list)
138
+ outputs2.extend(krea2_cn_types_list + krea2_cn_series_list + krea2_cn_filepaths_list)
139
  if lora_accordion: outputs2.append(lora_accordion)
140
  if cn_accordion: outputs2.append(cn_accordion)
141
  if anima_cn_accordion: outputs2.append(anima_cn_accordion)
142
  if diffsynth_cn_accordion: outputs2.append(diffsynth_cn_accordion)
143
+ if krea2_cn_accordion: outputs2.append(krea2_cn_accordion)
144
  if ipa_accordion: outputs2.append(ipa_accordion)
145
  if sd3_ipa_accordion: outputs2.append(sd3_ipa_accordion)
146
  if flux1_ipa_accordion: outputs2.append(flux1_ipa_accordion)
 
150
  if ref_latent_accordion: outputs2.append(ref_latent_accordion)
151
  if hidream_o1_ref_accordion: outputs2.append(hidream_o1_ref_accordion)
152
  if pid_accordion: outputs2.append(pid_accordion)
153
+ if vae_accordion: outputs2.append(vae_accordion)
154
  if ipa_preset_list: outputs2.append(ipa_preset_list)
155
 
156
  outputs2.extend(valid_extra_comps)
 
165
  cn_types_list, cn_series_list, cn_filepaths_list,
166
  anima_cn_types_list, anima_cn_series_list, anima_cn_filepaths_list,
167
  diffsynth_cn_types_list, diffsynth_cn_series_list, diffsynth_cn_filepaths_list,
168
+ krea2_cn_types_list, krea2_cn_series_list, krea2_cn_filepaths_list,
169
+ arch_comp, ipa_preset_list, lora_accordion, cn_accordion, anima_cn_accordion, diffsynth_cn_accordion, krea2_cn_accordion, ipa_accordion, sd3_ipa_accordion, flux1_ipa_accordion, style_accordion, embedding_accordion, conditioning_accordion,
170
  ref_latent_accordion, hidream_o1_ref_accordion, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp,
171
+ pid_acc=pid_accordion, vae_acc=vae_accordion
172
  )
173
  model_comp.change(fn=change_fn, inputs=inputs2, outputs=outputs2)
174
 
 
176
  create_controlnet_event_handlers(prefix, ui_components)
177
  create_anima_controlnet_lllite_event_handlers(prefix, ui_components)
178
  create_diffsynth_controlnet_event_handlers(prefix, ui_components)
179
+ create_krea2_controlnet_event_handlers(prefix, ui_components)
180
  create_ipadapter_event_handlers(prefix, ui_components)
181
  create_embedding_event_handlers(prefix, ui_components)
182
  create_conditioning_event_handlers(prefix, ui_components)
 
241
  all_load_outputs.extend(ui_components[f'diffsynth_controlnet_types_{prefix}'])
242
  all_load_outputs.extend(ui_components[f'diffsynth_controlnet_series_{prefix}'])
243
  all_load_outputs.extend(ui_components[f'diffsynth_controlnet_filepaths_{prefix}'])
244
+ if f'krea2_controlnet_types_{prefix}' in ui_components:
245
+ all_load_outputs.extend(ui_components[f'krea2_controlnet_types_{prefix}'])
246
+ all_load_outputs.extend(ui_components[f'krea2_controlnet_series_{prefix}'])
247
+ all_load_outputs.extend(ui_components[f'krea2_controlnet_filepaths_{prefix}'])
248
  if f'ipadapter_final_preset_{prefix}' in ui_components:
249
  all_load_outputs.extend(ui_components[f'ipadapter_lora_strengths_{prefix}'])
250
  all_load_outputs.append(ui_components[f'ipadapter_final_preset_{prefix}'])
ui/events/run_handlers.py CHANGED
@@ -1,103 +1,105 @@
1
- import gradio as gr
2
- from core.generation_logic import generate_image_wrapper
3
-
4
- def create_run_event(prefix: str, task_type: str, ui_components: dict):
5
- run_inputs_map = {
6
- 'model_display_name': ui_components[f'base_model_{prefix}'],
7
- 'positive_prompt': ui_components.get(f'prompt_{prefix}') or ui_components.get(f'{prefix}_positive_prompt'),
8
- 'negative_prompt': ui_components.get(f'neg_prompt_{prefix}') or ui_components.get(f'{prefix}_negative_prompt'),
9
- 'seed': ui_components.get(f'seed_{prefix}') or ui_components.get(f'{prefix}_seed'),
10
- 'batch_size': ui_components.get(f'batch_size_{prefix}') or ui_components.get(f'{prefix}_batch_size'),
11
- 'guidance_scale': ui_components.get(f'cfg_{prefix}') or ui_components.get(f'{prefix}_cfg'),
12
- 'num_inference_steps': ui_components.get(f'steps_{prefix}') or ui_components.get(f'{prefix}_steps'),
13
- 'sampler': ui_components.get(f'sampler_{prefix}') or ui_components.get(f'{prefix}_sampler_name'),
14
- 'scheduler': ui_components.get(f'scheduler_{prefix}') or ui_components.get(f'{prefix}_scheduler'),
15
- 'zero_gpu_duration': ui_components.get(f'zero_gpu_{prefix}'),
16
-
17
- 'clip_skip': ui_components.get(f'clip_skip_{prefix}'),
18
- 'guidance': ui_components.get(f'guidance_{prefix}'),
19
- 'task_type': gr.State(task_type)
20
- }
21
-
22
- if ui_components.get(f'pid_settings_{prefix}'):
23
- run_inputs_map['pid_settings'] = ui_components[f'pid_settings_{prefix}']
24
-
25
- if task_type not in ['img2img', 'inpaint']:
26
- run_inputs_map.update({
27
- 'width': ui_components.get(f'width_{prefix}') or ui_components.get(f'{prefix}_width'),
28
- 'height': ui_components.get(f'height_{prefix}') or ui_components.get(f'{prefix}_height')
29
- })
30
-
31
- task_specific_map = {
32
- 'img2img': {'img2img_image': f'input_image_{prefix}', 'img2img_denoise': f'denoise_{prefix}'},
33
- 'inpaint': {'inpaint_image_dict': f'input_image_dict_{prefix}', 'grow_mask_by': f'grow_mask_by_{prefix}'},
34
- 'outpaint': {'outpaint_image': f'input_image_{prefix}', 'left': f'left_{prefix}', 'top': f'top_{prefix}', 'right': f'right_{prefix}', 'bottom': f'bottom_{prefix}', 'feathering': f'feathering_{prefix}'},
35
- 'hires_fix': {'hires_image': f'input_image_{prefix}', 'hires_upscaler': f'hires_upscaler_{prefix}', 'hires_scale_by': f'hires_scale_by_{prefix}', 'hires_denoise': f'denoise_{prefix}'}
36
- }
37
- if task_type in task_specific_map:
38
- for key, comp_name in task_specific_map[task_type].items():
39
- if comp_name in ui_components:
40
- run_inputs_map[key] = ui_components[comp_name]
41
-
42
- lora_data_components = ui_components.get(f'all_lora_components_flat_{prefix}', [])
43
- controlnet_data_components = ui_components.get(f'all_controlnet_components_flat_{prefix}', [])
44
- anima_controlnet_lllite_data_components = ui_components.get(f'all_anima_controlnet_lllite_components_flat_{prefix}', [])
45
- diffsynth_controlnet_data_components = ui_components.get(f'all_diffsynth_controlnet_components_flat_{prefix}', [])
46
- ipadapter_data_components = ui_components.get(f'all_ipadapter_components_flat_{prefix}', [])
47
- sd3_ipadapter_data_components = ui_components.get(f'all_sd3_ipadapter_components_flat_{prefix}', [])
48
- flux1_ipadapter_data_components = ui_components.get(f'all_flux1_ipadapter_components_flat_{prefix}', [])
49
- style_data_components = ui_components.get(f'all_style_components_flat_{prefix}', [])
50
- embedding_data_components = ui_components.get(f'all_embedding_components_flat_{prefix}', [])
51
- conditioning_data_components = ui_components.get(f'all_conditioning_components_flat_{prefix}', [])
52
- reference_latent_data_components = ui_components.get(f'all_reference_latent_components_flat_{prefix}', [])
53
- hidream_o1_reference_data_components = ui_components.get(f'all_hidream_o1_reference_components_flat_{prefix}', [])
54
-
55
- run_inputs_map['vae_source'] = ui_components.get(f'vae_source_{prefix}')
56
- run_inputs_map['vae_id'] = ui_components.get(f'vae_id_{prefix}')
57
- run_inputs_map['vae_file'] = ui_components.get(f'vae_file_{prefix}')
58
-
59
- input_keys = list(run_inputs_map.keys())
60
- input_list_flat = [v for v in run_inputs_map.values() if v is not None]
61
- all_chains = [
62
- lora_data_components, controlnet_data_components, anima_controlnet_lllite_data_components, diffsynth_controlnet_data_components, ipadapter_data_components,
63
- sd3_ipadapter_data_components, flux1_ipadapter_data_components, style_data_components,
64
- embedding_data_components, conditioning_data_components, reference_latent_data_components, hidream_o1_reference_data_components
65
- ]
66
- for chain in all_chains:
67
- if chain:
68
- input_list_flat.extend(chain)
69
-
70
- def create_ui_inputs_dict(*args):
71
- valid_keys = [k for k in input_keys if run_inputs_map[k] is not None]
72
- ui_dict = dict(zip(valid_keys, args[:len(valid_keys)]))
73
- arg_idx = len(valid_keys)
74
-
75
- def assign_chain_data(chain_key, components_list):
76
- nonlocal arg_idx
77
- if components_list:
78
- ui_dict[chain_key] = list(args[arg_idx : arg_idx + len(components_list)])
79
- arg_idx += len(components_list)
80
-
81
- assign_chain_data('lora_data', lora_data_components)
82
- assign_chain_data('controlnet_data', controlnet_data_components)
83
- assign_chain_data('anima_controlnet_lllite_data', anima_controlnet_lllite_data_components)
84
- assign_chain_data('diffsynth_controlnet_data', diffsynth_controlnet_data_components)
85
- assign_chain_data('ipadapter_data', ipadapter_data_components)
86
- assign_chain_data('sd3_ipadapter_chain', sd3_ipadapter_data_components)
87
- assign_chain_data('flux1_ipadapter_data', flux1_ipadapter_data_components)
88
- assign_chain_data('style_data', style_data_components)
89
- assign_chain_data('embedding_data', embedding_data_components)
90
- assign_chain_data('conditioning_data', conditioning_data_components)
91
- assign_chain_data('reference_latent_data', reference_latent_data_components)
92
- assign_chain_data('hidream_o1_reference_data', hidream_o1_reference_data_components)
93
-
94
- return ui_dict
95
-
96
- run_btn = ui_components.get(f'run_{prefix}') or ui_components.get(f'{prefix}_run_button')
97
- res_gal = ui_components.get(f'result_{prefix}') or ui_components.get(f'{prefix}_output_gallery')
98
- if run_btn and res_gal:
99
- run_btn.click(
100
- fn=lambda *args, progress=gr.Progress(track_tqdm=True): generate_image_wrapper(create_ui_inputs_dict(*args), progress),
101
- inputs=input_list_flat,
102
- outputs=[res_gal]
 
 
103
  )
 
1
+ import gradio as gr
2
+ from core.generation_logic import generate_image_wrapper
3
+
4
+ def create_run_event(prefix: str, task_type: str, ui_components: dict):
5
+ run_inputs_map = {
6
+ 'model_display_name': ui_components[f'base_model_{prefix}'],
7
+ 'positive_prompt': ui_components.get(f'prompt_{prefix}') or ui_components.get(f'{prefix}_positive_prompt'),
8
+ 'negative_prompt': ui_components.get(f'neg_prompt_{prefix}') or ui_components.get(f'{prefix}_negative_prompt'),
9
+ 'seed': ui_components.get(f'seed_{prefix}') or ui_components.get(f'{prefix}_seed'),
10
+ 'batch_size': ui_components.get(f'batch_size_{prefix}') or ui_components.get(f'{prefix}_batch_size'),
11
+ 'guidance_scale': ui_components.get(f'cfg_{prefix}') or ui_components.get(f'{prefix}_cfg'),
12
+ 'num_inference_steps': ui_components.get(f'steps_{prefix}') or ui_components.get(f'{prefix}_steps'),
13
+ 'sampler': ui_components.get(f'sampler_{prefix}') or ui_components.get(f'{prefix}_sampler_name'),
14
+ 'scheduler': ui_components.get(f'scheduler_{prefix}') or ui_components.get(f'{prefix}_scheduler'),
15
+ 'zero_gpu_duration': ui_components.get(f'zero_gpu_{prefix}'),
16
+
17
+ 'clip_skip': ui_components.get(f'clip_skip_{prefix}'),
18
+ 'guidance': ui_components.get(f'guidance_{prefix}'),
19
+ 'task_type': gr.State(task_type)
20
+ }
21
+
22
+ if ui_components.get(f'pid_settings_{prefix}'):
23
+ run_inputs_map['pid_settings'] = ui_components[f'pid_settings_{prefix}']
24
+
25
+ if task_type not in ['img2img', 'inpaint']:
26
+ run_inputs_map.update({
27
+ 'width': ui_components.get(f'width_{prefix}') or ui_components.get(f'{prefix}_width'),
28
+ 'height': ui_components.get(f'height_{prefix}') or ui_components.get(f'{prefix}_height')
29
+ })
30
+
31
+ task_specific_map = {
32
+ 'img2img': {'img2img_image': f'input_image_{prefix}', 'img2img_denoise': f'denoise_{prefix}'},
33
+ 'inpaint': {'inpaint_image_dict': f'input_image_dict_{prefix}', 'grow_mask_by': f'grow_mask_by_{prefix}', 'inpaint_denoise': f'denoise_{prefix}'},
34
+ 'outpaint': {'outpaint_image': f'input_image_{prefix}', 'left': f'left_{prefix}', 'top': f'top_{prefix}', 'right': f'right_{prefix}', 'bottom': f'bottom_{prefix}', 'feathering': f'feathering_{prefix}'},
35
+ 'hires_fix': {'hires_image': f'input_image_{prefix}', 'hires_upscaler': f'hires_upscaler_{prefix}', 'hires_scale_by': f'hires_scale_by_{prefix}', 'hires_denoise': f'denoise_{prefix}'}
36
+ }
37
+ if task_type in task_specific_map:
38
+ for key, comp_name in task_specific_map[task_type].items():
39
+ if comp_name in ui_components:
40
+ run_inputs_map[key] = ui_components[comp_name]
41
+
42
+ lora_data_components = ui_components.get(f'all_lora_components_flat_{prefix}', [])
43
+ controlnet_data_components = ui_components.get(f'all_controlnet_components_flat_{prefix}', [])
44
+ anima_controlnet_lllite_data_components = ui_components.get(f'all_anima_controlnet_lllite_components_flat_{prefix}', [])
45
+ diffsynth_controlnet_data_components = ui_components.get(f'all_diffsynth_controlnet_components_flat_{prefix}', [])
46
+ krea2_controlnet_data_components = ui_components.get(f'all_krea2_controlnet_components_flat_{prefix}', [])
47
+ ipadapter_data_components = ui_components.get(f'all_ipadapter_components_flat_{prefix}', [])
48
+ sd3_ipadapter_data_components = ui_components.get(f'all_sd3_ipadapter_components_flat_{prefix}', [])
49
+ flux1_ipadapter_data_components = ui_components.get(f'all_flux1_ipadapter_components_flat_{prefix}', [])
50
+ style_data_components = ui_components.get(f'all_style_components_flat_{prefix}', [])
51
+ embedding_data_components = ui_components.get(f'all_embedding_components_flat_{prefix}', [])
52
+ conditioning_data_components = ui_components.get(f'all_conditioning_components_flat_{prefix}', [])
53
+ reference_latent_data_components = ui_components.get(f'all_reference_latent_components_flat_{prefix}', [])
54
+ hidream_o1_reference_data_components = ui_components.get(f'all_hidream_o1_reference_components_flat_{prefix}', [])
55
+
56
+ run_inputs_map['vae_source'] = ui_components.get(f'vae_source_{prefix}')
57
+ run_inputs_map['vae_id'] = ui_components.get(f'vae_id_{prefix}')
58
+ run_inputs_map['vae_file'] = ui_components.get(f'vae_file_{prefix}')
59
+
60
+ input_keys = list(run_inputs_map.keys())
61
+ input_list_flat = [v for v in run_inputs_map.values() if v is not None]
62
+ all_chains = [
63
+ lora_data_components, controlnet_data_components, anima_controlnet_lllite_data_components, diffsynth_controlnet_data_components, krea2_controlnet_data_components, ipadapter_data_components,
64
+ sd3_ipadapter_data_components, flux1_ipadapter_data_components, style_data_components,
65
+ embedding_data_components, conditioning_data_components, reference_latent_data_components, hidream_o1_reference_data_components
66
+ ]
67
+ for chain in all_chains:
68
+ if chain:
69
+ input_list_flat.extend(chain)
70
+
71
+ def create_ui_inputs_dict(*args):
72
+ valid_keys = [k for k in input_keys if run_inputs_map[k] is not None]
73
+ ui_dict = dict(zip(valid_keys, args[:len(valid_keys)]))
74
+ arg_idx = len(valid_keys)
75
+
76
+ def assign_chain_data(chain_key, components_list):
77
+ nonlocal arg_idx
78
+ if components_list:
79
+ ui_dict[chain_key] = list(args[arg_idx : arg_idx + len(components_list)])
80
+ arg_idx += len(components_list)
81
+
82
+ assign_chain_data('lora_data', lora_data_components)
83
+ assign_chain_data('controlnet_data', controlnet_data_components)
84
+ assign_chain_data('anima_controlnet_lllite_data', anima_controlnet_lllite_data_components)
85
+ assign_chain_data('diffsynth_controlnet_data', diffsynth_controlnet_data_components)
86
+ assign_chain_data('krea2_controlnet_data', krea2_controlnet_data_components)
87
+ assign_chain_data('ipadapter_data', ipadapter_data_components)
88
+ assign_chain_data('sd3_ipadapter_chain', sd3_ipadapter_data_components)
89
+ assign_chain_data('flux1_ipadapter_data', flux1_ipadapter_data_components)
90
+ assign_chain_data('style_data', style_data_components)
91
+ assign_chain_data('embedding_data', embedding_data_components)
92
+ assign_chain_data('conditioning_data', conditioning_data_components)
93
+ assign_chain_data('reference_latent_data', reference_latent_data_components)
94
+ assign_chain_data('hidream_o1_reference_data', hidream_o1_reference_data_components)
95
+
96
+ return ui_dict
97
+
98
+ run_btn = ui_components.get(f'run_{prefix}') or ui_components.get(f'{prefix}_run_button')
99
+ res_gal = ui_components.get(f'result_{prefix}') or ui_components.get(f'{prefix}_output_gallery')
100
+ if run_btn and res_gal:
101
+ run_btn.click(
102
+ fn=lambda *args, progress=gr.Progress(track_tqdm=True): generate_image_wrapper(create_ui_inputs_dict(*args), progress),
103
+ inputs=input_list_flat,
104
+ outputs=[res_gal]
105
  )
ui/shared/hires_fix_ui.py CHANGED
@@ -1,15 +1,23 @@
1
  import gradio as gr
2
- from core.settings import MODEL_MAP_CHECKPOINT
3
  from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
4
  from .ui_components import (
5
  create_lora_settings_ui,
6
- create_controlnet_ui, create_anima_controlnet_lllite_ui, create_ipadapter_ui, create_embedding_ui,
7
  create_conditioning_ui, create_vae_override_ui,
8
  create_model_architecture_filter_ui, create_category_filter_ui,
9
  create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
10
  create_reference_latent_ui, create_hidream_o1_reference_ui
11
  )
12
 
 
 
 
 
 
 
 
 
13
  def create_ui():
14
  prefix = "hires_fix"
15
  components = {}
@@ -33,8 +41,8 @@ def create_ui():
33
  with gr.Column(scale=1):
34
  components[f'input_image_{prefix}'] = gr.Image(type="pil", label="Input Image", height=255)
35
  with gr.Column(scale=2):
36
- components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3)
37
- components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3)
38
 
39
  with gr.Row():
40
  with gr.Column(scale=1):
@@ -52,11 +60,19 @@ def create_ui():
52
  components[f'denoise_{prefix}'] = gr.Slider(label="Denoise Strength", minimum=0.0, maximum=1.0, step=0.01, value=0.55)
53
 
54
  with gr.Row():
55
- components[f'sampler_{prefix}'] = gr.Dropdown(label="Sampler", choices=SAMPLER_CHOICES, value='er_sde' if 'er_sde' in SAMPLER_CHOICES else SAMPLER_CHOICES[0])
56
- components[f'scheduler_{prefix}'] = gr.Dropdown(label="Scheduler", choices=SCHEDULER_CHOICES, value='simple' if 'simple' in SCHEDULER_CHOICES else SCHEDULER_CHOICES[0])
 
 
 
 
 
 
 
 
57
  with gr.Row():
58
- components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=30)
59
- components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=4.0)
60
  with gr.Row():
61
  components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
62
  components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
@@ -75,6 +91,8 @@ def create_ui():
75
  components.update(create_lora_settings_ui(prefix))
76
  components.update(create_controlnet_ui(prefix))
77
  components.update(create_anima_controlnet_lllite_ui(prefix))
 
 
78
  components.update(create_ipadapter_ui(prefix))
79
  components.update(create_flux1_ipadapter_ui(prefix))
80
  components.update(create_sd3_ipadapter_ui(prefix))
 
1
  import gradio as gr
2
+ from core.settings import MODEL_MAP_CHECKPOINT, MODEL_DEFAULTS_CONFIG
3
  from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
4
  from .ui_components import (
5
  create_lora_settings_ui,
6
+ create_controlnet_ui, create_anima_controlnet_lllite_ui, create_diffsynth_controlnet_ui, create_krea2_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
7
  create_conditioning_ui, create_vae_override_ui,
8
  create_model_architecture_filter_ui, create_category_filter_ui,
9
  create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
10
  create_reference_latent_ui, create_hidream_o1_reference_ui
11
  )
12
 
13
+ default_vals = MODEL_DEFAULTS_CONFIG.get('Default', {})
14
+ DEFAULT_STEPS = default_vals.get('steps', 20)
15
+ DEFAULT_CFG = default_vals.get('cfg', 5.0)
16
+ DEFAULT_SAMPLER = default_vals.get('sampler_name', 'euler')
17
+ DEFAULT_SCHEDULER = default_vals.get('scheduler', 'simple')
18
+ DEFAULT_POS_PROMPT = default_vals.get('positive_prompt', '')
19
+ DEFAULT_NEG_PROMPT = default_vals.get('negative_prompt', '')
20
+
21
  def create_ui():
22
  prefix = "hires_fix"
23
  components = {}
 
41
  with gr.Column(scale=1):
42
  components[f'input_image_{prefix}'] = gr.Image(type="pil", label="Input Image", height=255)
43
  with gr.Column(scale=2):
44
+ components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3, value=DEFAULT_POS_PROMPT)
45
+ components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3, value=DEFAULT_NEG_PROMPT)
46
 
47
  with gr.Row():
48
  with gr.Column(scale=1):
 
60
  components[f'denoise_{prefix}'] = gr.Slider(label="Denoise Strength", minimum=0.0, maximum=1.0, step=0.01, value=0.55)
61
 
62
  with gr.Row():
63
+ components[f'sampler_{prefix}'] = gr.Dropdown(
64
+ label="Sampler",
65
+ choices=SAMPLER_CHOICES,
66
+ value=DEFAULT_SAMPLER if DEFAULT_SAMPLER in SAMPLER_CHOICES else (SAMPLER_CHOICES[0] if SAMPLER_CHOICES else 'euler')
67
+ )
68
+ components[f'scheduler_{prefix}'] = gr.Dropdown(
69
+ label="Scheduler",
70
+ choices=SCHEDULER_CHOICES,
71
+ value=DEFAULT_SCHEDULER if DEFAULT_SCHEDULER in SCHEDULER_CHOICES else (SCHEDULER_CHOICES[0] if SCHEDULER_CHOICES else 'simple')
72
+ )
73
  with gr.Row():
74
+ components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=DEFAULT_STEPS)
75
+ components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=DEFAULT_CFG)
76
  with gr.Row():
77
  components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
78
  components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
 
91
  components.update(create_lora_settings_ui(prefix))
92
  components.update(create_controlnet_ui(prefix))
93
  components.update(create_anima_controlnet_lllite_ui(prefix))
94
+ components.update(create_diffsynth_controlnet_ui(prefix))
95
+ components.update(create_krea2_controlnet_ui(prefix))
96
  components.update(create_ipadapter_ui(prefix))
97
  components.update(create_flux1_ipadapter_ui(prefix))
98
  components.update(create_sd3_ipadapter_ui(prefix))
ui/shared/img2img_ui.py CHANGED
@@ -1,15 +1,23 @@
1
  import gradio as gr
2
- from core.settings import MODEL_MAP_CHECKPOINT
3
  from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
4
  from .ui_components import (
5
  create_lora_settings_ui,
6
- create_controlnet_ui, create_anima_controlnet_lllite_ui, create_diffsynth_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
7
  create_conditioning_ui, create_vae_override_ui,
8
  create_model_architecture_filter_ui, create_category_filter_ui,
9
  create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
10
  create_reference_latent_ui, create_hidream_o1_reference_ui
11
  )
12
 
 
 
 
 
 
 
 
 
13
  def create_ui():
14
  prefix = "img2img"
15
  components = {}
@@ -28,19 +36,27 @@ def create_ui():
28
  components[f'input_image_{prefix}'] = gr.Image(type="pil", label="Input Image", height=255)
29
 
30
  with gr.Column(scale=2):
31
- components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3)
32
- components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3)
33
 
34
  with gr.Row():
35
  with gr.Column(scale=1):
36
  components[f'denoise_{prefix}'] = gr.Slider(label="Denoise Strength", minimum=0.0, maximum=1.0, step=0.01, value=0.7)
37
 
38
  with gr.Row():
39
- components[f'sampler_{prefix}'] = gr.Dropdown(label="Sampler", choices=SAMPLER_CHOICES, value='er_sde' if 'er_sde' in SAMPLER_CHOICES else SAMPLER_CHOICES[0])
40
- components[f'scheduler_{prefix}'] = gr.Dropdown(label="Scheduler", choices=SCHEDULER_CHOICES, value='simple' if 'simple' in SCHEDULER_CHOICES else SCHEDULER_CHOICES[0])
 
 
 
 
 
 
 
 
41
  with gr.Row():
42
- components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=30)
43
- components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=4.0)
44
  with gr.Row():
45
  components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
46
  components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
@@ -57,6 +73,7 @@ def create_ui():
57
  components.update(create_controlnet_ui(prefix))
58
  components.update(create_anima_controlnet_lllite_ui(prefix))
59
  components.update(create_diffsynth_controlnet_ui(prefix))
 
60
  components.update(create_ipadapter_ui(prefix))
61
  components.update(create_flux1_ipadapter_ui(prefix))
62
  components.update(create_sd3_ipadapter_ui(prefix))
 
1
  import gradio as gr
2
+ from core.settings import MODEL_MAP_CHECKPOINT, MODEL_DEFAULTS_CONFIG
3
  from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
4
  from .ui_components import (
5
  create_lora_settings_ui,
6
+ create_controlnet_ui, create_anima_controlnet_lllite_ui, create_diffsynth_controlnet_ui, create_krea2_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
7
  create_conditioning_ui, create_vae_override_ui,
8
  create_model_architecture_filter_ui, create_category_filter_ui,
9
  create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
10
  create_reference_latent_ui, create_hidream_o1_reference_ui
11
  )
12
 
13
+ default_vals = MODEL_DEFAULTS_CONFIG.get('Default', {})
14
+ DEFAULT_STEPS = default_vals.get('steps', 20)
15
+ DEFAULT_CFG = default_vals.get('cfg', 5.0)
16
+ DEFAULT_SAMPLER = default_vals.get('sampler_name', 'euler')
17
+ DEFAULT_SCHEDULER = default_vals.get('scheduler', 'simple')
18
+ DEFAULT_POS_PROMPT = default_vals.get('positive_prompt', '')
19
+ DEFAULT_NEG_PROMPT = default_vals.get('negative_prompt', '')
20
+
21
  def create_ui():
22
  prefix = "img2img"
23
  components = {}
 
36
  components[f'input_image_{prefix}'] = gr.Image(type="pil", label="Input Image", height=255)
37
 
38
  with gr.Column(scale=2):
39
+ components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3, value=DEFAULT_POS_PROMPT)
40
+ components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3, value=DEFAULT_NEG_PROMPT)
41
 
42
  with gr.Row():
43
  with gr.Column(scale=1):
44
  components[f'denoise_{prefix}'] = gr.Slider(label="Denoise Strength", minimum=0.0, maximum=1.0, step=0.01, value=0.7)
45
 
46
  with gr.Row():
47
+ components[f'sampler_{prefix}'] = gr.Dropdown(
48
+ label="Sampler",
49
+ choices=SAMPLER_CHOICES,
50
+ value=DEFAULT_SAMPLER if DEFAULT_SAMPLER in SAMPLER_CHOICES else (SAMPLER_CHOICES[0] if SAMPLER_CHOICES else 'euler')
51
+ )
52
+ components[f'scheduler_{prefix}'] = gr.Dropdown(
53
+ label="Scheduler",
54
+ choices=SCHEDULER_CHOICES,
55
+ value=DEFAULT_SCHEDULER if DEFAULT_SCHEDULER in SCHEDULER_CHOICES else (SCHEDULER_CHOICES[0] if SCHEDULER_CHOICES else 'simple')
56
+ )
57
  with gr.Row():
58
+ components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=DEFAULT_STEPS)
59
+ components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=DEFAULT_CFG)
60
  with gr.Row():
61
  components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
62
  components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
 
73
  components.update(create_controlnet_ui(prefix))
74
  components.update(create_anima_controlnet_lllite_ui(prefix))
75
  components.update(create_diffsynth_controlnet_ui(prefix))
76
+ components.update(create_krea2_controlnet_ui(prefix))
77
  components.update(create_ipadapter_ui(prefix))
78
  components.update(create_flux1_ipadapter_ui(prefix))
79
  components.update(create_sd3_ipadapter_ui(prefix))
ui/shared/inpaint_ui.py CHANGED
@@ -1,14 +1,22 @@
1
  import gradio as gr
2
- from core.settings import MODEL_MAP_CHECKPOINT
3
  from .ui_components import (
4
  create_base_parameter_ui, create_lora_settings_ui,
5
- create_controlnet_ui, create_anima_controlnet_lllite_ui, create_diffsynth_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
6
  create_conditioning_ui, create_vae_override_ui,
7
  create_model_architecture_filter_ui, create_category_filter_ui,
8
  create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
9
  create_reference_latent_ui, create_hidream_o1_reference_ui
10
  )
11
 
 
 
 
 
 
 
 
 
12
  def create_ui():
13
  prefix = "inpaint"
14
  components = {}
@@ -47,8 +55,8 @@ def create_ui():
47
  components[f'editor_column_{prefix}'] = editor_column
48
 
49
  with gr.Column(scale=2) as prompts_column:
50
- components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=6)
51
- components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=6)
52
  components[f'prompts_column_{prefix}'] = prompts_column
53
 
54
  with gr.Row() as params_and_gallery_row:
@@ -62,11 +70,19 @@ def create_ui():
62
  label="Grow Mask By", minimum=0, maximum=64, step=1, value=6
63
  )
64
  with gr.Row():
65
- components[f'sampler_{prefix}'] = gr.Dropdown(label="Sampler", choices=SAMPLER_CHOICES, value='er_sde' if 'er_sde' in SAMPLER_CHOICES else SAMPLER_CHOICES[0])
66
- components[f'scheduler_{prefix}'] = gr.Dropdown(label="Scheduler", choices=SCHEDULER_CHOICES, value='simple' if 'simple' in SCHEDULER_CHOICES else SCHEDULER_CHOICES[0])
 
 
 
 
 
 
 
 
67
  with gr.Row():
68
- components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=30)
69
- components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=4.0)
70
  with gr.Row():
71
  components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
72
  components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
@@ -89,6 +105,7 @@ def create_ui():
89
  components.update(create_controlnet_ui(prefix))
90
  components.update(create_anima_controlnet_lllite_ui(prefix))
91
  components.update(create_diffsynth_controlnet_ui(prefix))
 
92
  components.update(create_ipadapter_ui(prefix))
93
  components.update(create_flux1_ipadapter_ui(prefix))
94
  components.update(create_sd3_ipadapter_ui(prefix))
 
1
  import gradio as gr
2
+ from core.settings import MODEL_MAP_CHECKPOINT, MODEL_DEFAULTS_CONFIG
3
  from .ui_components import (
4
  create_base_parameter_ui, create_lora_settings_ui,
5
+ create_controlnet_ui, create_anima_controlnet_lllite_ui, create_diffsynth_controlnet_ui, create_krea2_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
6
  create_conditioning_ui, create_vae_override_ui,
7
  create_model_architecture_filter_ui, create_category_filter_ui,
8
  create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
9
  create_reference_latent_ui, create_hidream_o1_reference_ui
10
  )
11
 
12
+ default_vals = MODEL_DEFAULTS_CONFIG.get('Default', {})
13
+ DEFAULT_STEPS = default_vals.get('steps', 20)
14
+ DEFAULT_CFG = default_vals.get('cfg', 5.0)
15
+ DEFAULT_SAMPLER = default_vals.get('sampler_name', 'euler')
16
+ DEFAULT_SCHEDULER = default_vals.get('scheduler', 'simple')
17
+ DEFAULT_POS_PROMPT = default_vals.get('positive_prompt', '')
18
+ DEFAULT_NEG_PROMPT = default_vals.get('negative_prompt', '')
19
+
20
  def create_ui():
21
  prefix = "inpaint"
22
  components = {}
 
55
  components[f'editor_column_{prefix}'] = editor_column
56
 
57
  with gr.Column(scale=2) as prompts_column:
58
+ components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=6, value=DEFAULT_POS_PROMPT)
59
+ components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=6, value=DEFAULT_NEG_PROMPT)
60
  components[f'prompts_column_{prefix}'] = prompts_column
61
 
62
  with gr.Row() as params_and_gallery_row:
 
70
  label="Grow Mask By", minimum=0, maximum=64, step=1, value=6
71
  )
72
  with gr.Row():
73
+ components[f'sampler_{prefix}'] = gr.Dropdown(
74
+ label="Sampler",
75
+ choices=SAMPLER_CHOICES,
76
+ value=DEFAULT_SAMPLER if DEFAULT_SAMPLER in SAMPLER_CHOICES else (SAMPLER_CHOICES[0] if SAMPLER_CHOICES else 'euler')
77
+ )
78
+ components[f'scheduler_{prefix}'] = gr.Dropdown(
79
+ label="Scheduler",
80
+ choices=SCHEDULER_CHOICES,
81
+ value=DEFAULT_SCHEDULER if DEFAULT_SCHEDULER in SCHEDULER_CHOICES else (SCHEDULER_CHOICES[0] if SCHEDULER_CHOICES else 'simple')
82
+ )
83
  with gr.Row():
84
+ components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=DEFAULT_STEPS)
85
+ components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=DEFAULT_CFG)
86
  with gr.Row():
87
  components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
88
  components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
 
105
  components.update(create_controlnet_ui(prefix))
106
  components.update(create_anima_controlnet_lllite_ui(prefix))
107
  components.update(create_diffsynth_controlnet_ui(prefix))
108
+ components.update(create_krea2_controlnet_ui(prefix))
109
  components.update(create_ipadapter_ui(prefix))
110
  components.update(create_flux1_ipadapter_ui(prefix))
111
  components.update(create_sd3_ipadapter_ui(prefix))
ui/shared/outpaint_ui.py CHANGED
@@ -1,15 +1,23 @@
1
  import gradio as gr
2
- from core.settings import MODEL_MAP_CHECKPOINT
3
  from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
4
  from .ui_components import (
5
  create_lora_settings_ui,
6
- create_controlnet_ui, create_anima_controlnet_lllite_ui, create_diffsynth_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
7
  create_conditioning_ui, create_vae_override_ui,
8
  create_model_architecture_filter_ui, create_category_filter_ui,
9
  create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
10
  create_reference_latent_ui, create_hidream_o1_reference_ui
11
  )
12
 
 
 
 
 
 
 
 
 
13
  def create_ui():
14
  prefix = "outpaint"
15
  components = {}
@@ -33,8 +41,8 @@ def create_ui():
33
  with gr.Column(scale=1):
34
  components[f'input_image_{prefix}'] = gr.Image(type="pil", label="Input Image", height=255)
35
  with gr.Column(scale=2):
36
- components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3)
37
- components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3)
38
 
39
  with gr.Row():
40
  with gr.Column(scale=1):
@@ -48,11 +56,19 @@ def create_ui():
48
  components[f'feathering_{prefix}'] = gr.Slider(label="Feathering / Grow Mask", minimum=0, maximum=100, step=1, value=10)
49
 
50
  with gr.Row():
51
- components[f'sampler_{prefix}'] = gr.Dropdown(label="Sampler", choices=SAMPLER_CHOICES, value='er_sde' if 'er_sde' in SAMPLER_CHOICES else SAMPLER_CHOICES[0])
52
- components[f'scheduler_{prefix}'] = gr.Dropdown(label="Scheduler", choices=SCHEDULER_CHOICES, value='simple' if 'simple' in SCHEDULER_CHOICES else SCHEDULER_CHOICES[0])
 
 
 
 
 
 
 
 
53
  with gr.Row():
54
- components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=30)
55
- components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=4.0)
56
  with gr.Row():
57
  components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
58
  components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
@@ -72,6 +88,7 @@ def create_ui():
72
  components.update(create_controlnet_ui(prefix))
73
  components.update(create_anima_controlnet_lllite_ui(prefix))
74
  components.update(create_diffsynth_controlnet_ui(prefix))
 
75
  components.update(create_ipadapter_ui(prefix))
76
  components.update(create_flux1_ipadapter_ui(prefix))
77
  components.update(create_sd3_ipadapter_ui(prefix))
 
1
  import gradio as gr
2
+ from core.settings import MODEL_MAP_CHECKPOINT, MODEL_DEFAULTS_CONFIG
3
  from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
4
  from .ui_components import (
5
  create_lora_settings_ui,
6
+ create_controlnet_ui, create_anima_controlnet_lllite_ui, create_diffsynth_controlnet_ui, create_krea2_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
7
  create_conditioning_ui, create_vae_override_ui,
8
  create_model_architecture_filter_ui, create_category_filter_ui,
9
  create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
10
  create_reference_latent_ui, create_hidream_o1_reference_ui
11
  )
12
 
13
+ default_vals = MODEL_DEFAULTS_CONFIG.get('Default', {})
14
+ DEFAULT_STEPS = default_vals.get('steps', 20)
15
+ DEFAULT_CFG = default_vals.get('cfg', 5.0)
16
+ DEFAULT_SAMPLER = default_vals.get('sampler_name', 'euler')
17
+ DEFAULT_SCHEDULER = default_vals.get('scheduler', 'simple')
18
+ DEFAULT_POS_PROMPT = default_vals.get('positive_prompt', '')
19
+ DEFAULT_NEG_PROMPT = default_vals.get('negative_prompt', '')
20
+
21
  def create_ui():
22
  prefix = "outpaint"
23
  components = {}
 
41
  with gr.Column(scale=1):
42
  components[f'input_image_{prefix}'] = gr.Image(type="pil", label="Input Image", height=255)
43
  with gr.Column(scale=2):
44
+ components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3, value=DEFAULT_POS_PROMPT)
45
+ components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3, value=DEFAULT_NEG_PROMPT)
46
 
47
  with gr.Row():
48
  with gr.Column(scale=1):
 
56
  components[f'feathering_{prefix}'] = gr.Slider(label="Feathering / Grow Mask", minimum=0, maximum=100, step=1, value=10)
57
 
58
  with gr.Row():
59
+ components[f'sampler_{prefix}'] = gr.Dropdown(
60
+ label="Sampler",
61
+ choices=SAMPLER_CHOICES,
62
+ value=DEFAULT_SAMPLER if DEFAULT_SAMPLER in SAMPLER_CHOICES else (SAMPLER_CHOICES[0] if SAMPLER_CHOICES else 'euler')
63
+ )
64
+ components[f'scheduler_{prefix}'] = gr.Dropdown(
65
+ label="Scheduler",
66
+ choices=SCHEDULER_CHOICES,
67
+ value=DEFAULT_SCHEDULER if DEFAULT_SCHEDULER in SCHEDULER_CHOICES else (SCHEDULER_CHOICES[0] if SCHEDULER_CHOICES else 'simple')
68
+ )
69
  with gr.Row():
70
+ components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=DEFAULT_STEPS)
71
+ components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=DEFAULT_CFG)
72
  with gr.Row():
73
  components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
74
  components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
 
88
  components.update(create_controlnet_ui(prefix))
89
  components.update(create_anima_controlnet_lllite_ui(prefix))
90
  components.update(create_diffsynth_controlnet_ui(prefix))
91
+ components.update(create_krea2_controlnet_ui(prefix))
92
  components.update(create_ipadapter_ui(prefix))
93
  components.update(create_flux1_ipadapter_ui(prefix))
94
  components.update(create_sd3_ipadapter_ui(prefix))
ui/shared/txt2img_ui.py CHANGED
@@ -2,7 +2,7 @@ import gradio as gr
2
  from core.settings import MODEL_MAP_CHECKPOINT
3
  from .ui_components import (
4
  create_base_parameter_ui, create_lora_settings_ui,
5
- create_controlnet_ui, create_anima_controlnet_lllite_ui, create_diffsynth_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
6
  create_conditioning_ui, create_vae_override_ui,
7
  create_model_architecture_filter_ui, create_category_filter_ui,
8
  create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
@@ -45,6 +45,7 @@ def create_ui():
45
  components.update(create_controlnet_ui(prefix))
46
  components.update(create_anima_controlnet_lllite_ui(prefix))
47
  components.update(create_diffsynth_controlnet_ui(prefix))
 
48
  components.update(create_ipadapter_ui(prefix))
49
  components.update(create_flux1_ipadapter_ui(prefix))
50
  components.update(create_sd3_ipadapter_ui(prefix))
 
2
  from core.settings import MODEL_MAP_CHECKPOINT
3
  from .ui_components import (
4
  create_base_parameter_ui, create_lora_settings_ui,
5
+ create_controlnet_ui, create_anima_controlnet_lllite_ui, create_diffsynth_controlnet_ui, create_krea2_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
6
  create_conditioning_ui, create_vae_override_ui,
7
  create_model_architecture_filter_ui, create_category_filter_ui,
8
  create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
 
45
  components.update(create_controlnet_ui(prefix))
46
  components.update(create_anima_controlnet_lllite_ui(prefix))
47
  components.update(create_diffsynth_controlnet_ui(prefix))
48
+ components.update(create_krea2_controlnet_ui(prefix))
49
  components.update(create_ipadapter_ui(prefix))
50
  components.update(create_flux1_ipadapter_ui(prefix))
51
  components.update(create_sd3_ipadapter_ui(prefix))
ui/shared/ui_components.py CHANGED
@@ -4,7 +4,7 @@ from core.settings import (
4
  MAX_LORAS, LORA_SOURCE_CHOICES, MAX_EMBEDDINGS, MAX_CONDITIONINGS,
5
  MAX_CONTROLNETS, MAX_IPADAPTERS, RESOLUTION_MAP, ARCHITECTURES_CONFIG,
6
  MODEL_MAP_CHECKPOINT, MODEL_TYPE_MAP, FEATURES_CONFIG, ARCH_CATEGORIES_MAP,
7
- VAE_DIR
8
  )
9
  import yaml
10
  import os
@@ -18,6 +18,13 @@ default_arch_model_type = default_architectures_dict.get(default_m_type, {}).get
18
  default_arch_features = FEATURES_CONFIG.get(default_arch_model_type, FEATURES_CONFIG.get('default', {}))
19
  default_enabled_chains = default_arch_features.get('enabled_chains', [])
20
 
 
 
 
 
 
 
 
21
 
22
  @lru_cache(maxsize=1)
23
  def get_ipadapter_config_from_yaml():
@@ -90,11 +97,19 @@ def create_base_parameter_ui(prefix, defaults=None):
90
  components[f'width_{prefix}'] = gr.Number(label="Width", value=defaults.get('w', 1024), interactive=True)
91
  components[f'height_{prefix}'] = gr.Number(label="Height", value=defaults.get('h', 1024), interactive=True)
92
  with gr.Row():
93
- components[f'sampler_{prefix}'] = gr.Dropdown(label="Sampler", choices=SAMPLER_CHOICES, value='er_sde' if 'er_sde' in SAMPLER_CHOICES else SAMPLER_CHOICES[0])
94
- components[f'scheduler_{prefix}'] = gr.Dropdown(label="Scheduler", choices=SCHEDULER_CHOICES, value='simple' if 'simple' in SCHEDULER_CHOICES else SCHEDULER_CHOICES[0])
 
 
 
 
 
 
 
 
95
  with gr.Row():
96
- components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=30)
97
- components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=4.0)
98
  with gr.Row():
99
  components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
100
  components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
@@ -113,14 +128,14 @@ def create_lora_settings_ui(prefix: str):
113
 
114
  with gr.Accordion("LoRA Settings", open=False, visible=('lora' in default_enabled_chains)) as lora_accordion:
115
  components[f'lora_accordion_{prefix}'] = lora_accordion
116
- gr.Markdown("💡 **Tip:** When downloading from Civitai, please use the **Version ID**, not the Model ID. You can find the Version ID in the URL (e.g., `civitai.com/models/123?modelVersionId=456`) or under the model's download button.")
117
  components[f'lora_count_state_{prefix}'] = gr.State(1)
118
 
119
  for i in range(MAX_LORAS):
120
  with gr.Row(visible=i==0) as row:
121
  source = gr.Dropdown(label=f"LoRA Source {i+1}", choices=LORA_SOURCE_CHOICES, value=LORA_SOURCE_CHOICES[0], scale=1)
122
- lora_id = gr.Textbox(label=f"Civitai Version ID / File", placeholder="Civitai Version ID or Filename", scale=2, type="text")
123
- scale = gr.Slider(label=f"Scale", minimum=0.0, maximum=2.0, step=0.05, value=0.8, scale=1)
124
  upload = gr.UploadButton(label="Upload", file_types=[".safetensors"], scale=1)
125
 
126
  lora_rows.append(row)
@@ -188,6 +203,49 @@ def create_controlnet_ui(prefix: str, max_units=MAX_CONTROLNETS):
188
 
189
  return components
190
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  def create_anima_controlnet_lllite_ui(prefix: str, max_units=MAX_CONTROLNETS):
192
  components = {}
193
  key = lambda name: f"{name}_{prefix}"
@@ -464,7 +522,7 @@ def create_embedding_ui(prefix: str):
464
 
465
  with gr.Accordion("Embedding Settings", open=False, visible=('embedding' in default_enabled_chains)) as accordion:
466
  components[key('embedding_accordion')] = accordion
467
- gr.Markdown("💡 **Tip:** Embeddings are automatically added to your prompt using `embedding:filename` syntax. When downloading from Civitai, please use the **Version ID**, not the Model ID. You can find the Version ID in the URL (e.g., `civitai.com/models/123?modelVersionId=456`) or under the model's download button. For instance, using the Version ID `456` from the example above would automatically append `embedding:civitai_456` to your positive prompt.")
468
 
469
  embedding_rows, sources, ids, files, upload_buttons = [], [], [], [], []
470
  components.update({
@@ -478,7 +536,7 @@ def create_embedding_ui(prefix: str):
478
  for i in range(MAX_EMBEDDINGS):
479
  with gr.Row(visible=(i < 1)) as row:
480
  sources.append(gr.Dropdown(label=f"Embedding Source {i+1}", choices=LORA_SOURCE_CHOICES, value="Civitai", scale=1, interactive=True))
481
- ids.append(gr.Textbox(label="Civitai Version ID / File", placeholder="Civitai Version ID or Filename", scale=3, interactive=True, type="text"))
482
  upload_btn = gr.UploadButton("Upload", file_types=[".safetensors"], scale=1)
483
  files.append(gr.State(None))
484
  upload_buttons.append(upload_btn)
@@ -548,9 +606,9 @@ def create_vae_override_ui(prefix: str):
548
  key = lambda name: f"{name}_{prefix}"
549
  source_choices = ["None"] + LORA_SOURCE_CHOICES
550
 
551
- with gr.Accordion("VAE Settings (Override)", open=False) as vae_accordion:
552
  components[key('vae_accordion')] = vae_accordion
553
- gr.Markdown("💡 **Tip:** When downloading from Civitai, please use the **Version ID**, not the Model ID. You can find the Version ID in the URL (e.g., `civitai.com/models/123?modelVersionId=456`) or under the model's download button.")
554
  with gr.Row():
555
  components[key('vae_source')] = gr.Dropdown(
556
  label="VAE Source",
@@ -560,8 +618,7 @@ def create_vae_override_ui(prefix: str):
560
  interactive=True
561
  )
562
  components[key('vae_id')] = gr.Textbox(
563
- label="Civitai Version ID / File",
564
- placeholder="Civitai Version ID or Filename",
565
  scale=3,
566
  interactive=True,
567
  type="text"
 
4
  MAX_LORAS, LORA_SOURCE_CHOICES, MAX_EMBEDDINGS, MAX_CONDITIONINGS,
5
  MAX_CONTROLNETS, MAX_IPADAPTERS, RESOLUTION_MAP, ARCHITECTURES_CONFIG,
6
  MODEL_MAP_CHECKPOINT, MODEL_TYPE_MAP, FEATURES_CONFIG, ARCH_CATEGORIES_MAP,
7
+ VAE_DIR, MODEL_DEFAULTS_CONFIG
8
  )
9
  import yaml
10
  import os
 
18
  default_arch_features = FEATURES_CONFIG.get(default_arch_model_type, FEATURES_CONFIG.get('default', {}))
19
  default_enabled_chains = default_arch_features.get('enabled_chains', [])
20
 
21
+ default_vals = MODEL_DEFAULTS_CONFIG.get('Default', {})
22
+ DEFAULT_STEPS = default_vals.get('steps', 20)
23
+ DEFAULT_CFG = default_vals.get('cfg', 5.0)
24
+ DEFAULT_SAMPLER = default_vals.get('sampler_name', 'euler')
25
+ DEFAULT_SCHEDULER = default_vals.get('scheduler', 'simple')
26
+ DEFAULT_POS_PROMPT = default_vals.get('positive_prompt', '')
27
+ DEFAULT_NEG_PROMPT = default_vals.get('negative_prompt', '')
28
 
29
  @lru_cache(maxsize=1)
30
  def get_ipadapter_config_from_yaml():
 
97
  components[f'width_{prefix}'] = gr.Number(label="Width", value=defaults.get('w', 1024), interactive=True)
98
  components[f'height_{prefix}'] = gr.Number(label="Height", value=defaults.get('h', 1024), interactive=True)
99
  with gr.Row():
100
+ components[f'sampler_{prefix}'] = gr.Dropdown(
101
+ label="Sampler",
102
+ choices=SAMPLER_CHOICES,
103
+ value=DEFAULT_SAMPLER if DEFAULT_SAMPLER in SAMPLER_CHOICES else (SAMPLER_CHOICES[0] if SAMPLER_CHOICES else 'euler')
104
+ )
105
+ components[f'scheduler_{prefix}'] = gr.Dropdown(
106
+ label="Scheduler",
107
+ choices=SCHEDULER_CHOICES,
108
+ value=DEFAULT_SCHEDULER if DEFAULT_SCHEDULER in SCHEDULER_CHOICES else (SCHEDULER_CHOICES[0] if SCHEDULER_CHOICES else 'simple')
109
+ )
110
  with gr.Row():
111
+ components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=DEFAULT_STEPS)
112
+ components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=DEFAULT_CFG)
113
  with gr.Row():
114
  components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
115
  components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
 
128
 
129
  with gr.Accordion("LoRA Settings", open=False, visible=('lora' in default_enabled_chains)) as lora_accordion:
130
  components[f'lora_accordion_{prefix}'] = lora_accordion
131
+ gr.Markdown("💡 **Tip:** When downloading from Civitai, please use the **Version ID**, not the Model ID. You can find the Version ID in the URL (e.g., `civitai.com/models/123?modelVersionId=456`) or under the model's download button. When downloading from Hugging Face, please use the format: `repo_id/filename.extension` or `repo_id/folder_path/filename.extension` (e.g., `lightx2v/Qwen-Image-Lightning/Qwen-Image-Lightning-4steps-V2.0-bf16.safetensors`).")
132
  components[f'lora_count_state_{prefix}'] = gr.State(1)
133
 
134
  for i in range(MAX_LORAS):
135
  with gr.Row(visible=i==0) as row:
136
  source = gr.Dropdown(label=f"LoRA Source {i+1}", choices=LORA_SOURCE_CHOICES, value=LORA_SOURCE_CHOICES[0], scale=1)
137
+ lora_id = gr.Textbox(label="Civitai Version ID / HF file / Upload File", scale=2, type="text")
138
+ scale = gr.Slider(label=f"Scale", minimum=0.0, maximum=2.0, step=0.05, value=1.0, scale=1)
139
  upload = gr.UploadButton(label="Upload", file_types=[".safetensors"], scale=1)
140
 
141
  lora_rows.append(row)
 
203
 
204
  return components
205
 
206
+ def create_krea2_controlnet_ui(prefix: str, max_units=MAX_CONTROLNETS):
207
+ components = {}
208
+ key = lambda name: f"{name}_{prefix}"
209
+
210
+ with gr.Accordion("Krea2 ControlNet Settings", open=False, visible=('krea2_controlnet' in default_enabled_chains)) as accordion:
211
+ components[key('krea2_controlnet_accordion')] = accordion
212
+ gr.Markdown("💡 **Tip:** Processed using the [facok/comfyui-krea2-controlnet](https://github.com/facok/comfyui-krea2-controlnet) node.")
213
+
214
+ cn_rows, images, series, types, strengths, filepaths = [], [], [], [], [], []
215
+ components.update({
216
+ key('krea2_controlnet_rows'): cn_rows,
217
+ key('krea2_controlnet_images'): images,
218
+ key('krea2_controlnet_series'): series,
219
+ key('krea2_controlnet_types'): types,
220
+ key('krea2_controlnet_strengths'): strengths,
221
+ key('krea2_controlnet_filepaths'): filepaths
222
+ })
223
+
224
+ for i in range(max_units):
225
+ with gr.Row(visible=(i < 1)) as row:
226
+ with gr.Column(scale=1):
227
+ images.append(gr.Image(label=f"Control Image {i+1}", type="pil", sources=["upload"], height=256))
228
+ with gr.Column(scale=2):
229
+ types.append(gr.Dropdown(label="Type", choices=[], interactive=True, allow_custom_value=True))
230
+ series.append(gr.Dropdown(label="Series", choices=[], interactive=True, allow_custom_value=True))
231
+ strengths.append(gr.Slider(label="Strength", minimum=0.0, maximum=2.0, step=0.05, value=1.0, interactive=True))
232
+ filepaths.append(gr.State(None))
233
+ cn_rows.append(row)
234
+
235
+ with gr.Row():
236
+ components[key('add_krea2_controlnet_button')] = gr.Button("✚ Add Krea2 ControlNet")
237
+ components[key('delete_krea2_controlnet_button')] = gr.Button("➖ Delete Krea2 ControlNet", visible=False)
238
+ components[key('krea2_controlnet_count_state')] = gr.State(1)
239
+
240
+ all_cn_components_flat = []
241
+ for i in range(max_units):
242
+ all_cn_components_flat.extend([
243
+ images[i], types[i], series[i], strengths[i], filepaths[i]
244
+ ])
245
+ components[key('all_krea2_controlnet_components_flat')] = all_cn_components_flat
246
+
247
+ return components
248
+
249
  def create_anima_controlnet_lllite_ui(prefix: str, max_units=MAX_CONTROLNETS):
250
  components = {}
251
  key = lambda name: f"{name}_{prefix}"
 
522
 
523
  with gr.Accordion("Embedding Settings", open=False, visible=('embedding' in default_enabled_chains)) as accordion:
524
  components[key('embedding_accordion')] = accordion
525
+ gr.Markdown("💡 **Tip:** When downloading from Civitai, please use the **Version ID**, not the Model ID. You can find the Version ID in the URL (e.g., `civitai.com/models/123?modelVersionId=456`) or under the model's download button. For example, entering the Version ID 456 will automatically save the file as \"civitai_456.safetensors\", and you will need to manually enter `embedding:civitai_456` in either your prompt or negative prompt to activate it.When downloading from Hugging Face, please use the format: repo_id/filename.extension or repo_id/folder_path/filename.extension (e.g., ilikebigturtles/lazypos/lazypos.safetensors or ilikebigturtles/lazyneg/lazyneg.safetensors). For Hugging Face files, you will need to enter embedding:filename (e.g., entering embedding:lazypos in your positive prompt, or embedding:lazyneg in your negative prompt) to activate it.")
526
 
527
  embedding_rows, sources, ids, files, upload_buttons = [], [], [], [], []
528
  components.update({
 
536
  for i in range(MAX_EMBEDDINGS):
537
  with gr.Row(visible=(i < 1)) as row:
538
  sources.append(gr.Dropdown(label=f"Embedding Source {i+1}", choices=LORA_SOURCE_CHOICES, value="Civitai", scale=1, interactive=True))
539
+ ids.append(gr.Textbox(label="Civitai Version ID / HF file / Upload File", scale=3, interactive=True, type="text"))
540
  upload_btn = gr.UploadButton("Upload", file_types=[".safetensors"], scale=1)
541
  files.append(gr.State(None))
542
  upload_buttons.append(upload_btn)
 
606
  key = lambda name: f"{name}_{prefix}"
607
  source_choices = ["None"] + LORA_SOURCE_CHOICES
608
 
609
+ with gr.Accordion("VAE Settings (Override)", open=False, visible=('vae' in default_enabled_chains)) as vae_accordion:
610
  components[key('vae_accordion')] = vae_accordion
611
+ gr.Markdown("💡 **Tip:** When downloading from Civitai, please use the **Version ID**, not the Model ID. You can find the Version ID in the URL (e.g., `civitai.com/models/123?modelVersionId=456`) or under the model's download button. When downloading from Hugging Face, please use the format: `repo_id/filename.extension` or `repo_id/folder_path/filename.extension` (e.g., `madebyollin/sdxl-vae-fp16-fix/sdxl_vae.safetensors`).")
612
  with gr.Row():
613
  components[key('vae_source')] = gr.Dropdown(
614
  label="VAE Source",
 
618
  interactive=True
619
  )
620
  components[key('vae_id')] = gr.Textbox(
621
+ label="Civitai Version ID / HF file / Upload File",
 
622
  scale=3,
623
  interactive=True,
624
  type="text"
utils/app_utils.py CHANGED
@@ -105,6 +105,14 @@ def sanitize_prompt(prompt: str) -> str:
105
  def sanitize_id(input_id: str) -> str:
106
  if not isinstance(input_id, str):
107
  return ""
 
 
 
 
 
 
 
 
108
  return re.sub(r'[^0-9]', '', input_id)
109
 
110
  def sanitize_url(url: str) -> str:
@@ -129,12 +137,20 @@ def get_civitai_file_info(version_id: str) -> dict | None:
129
  response.raise_for_status()
130
  data = response.json()
131
 
 
 
 
132
  for file_data in data.get('files', []):
133
  if file_data.get('type') == 'Model' and file_data['name'].endswith(('.safetensors', '.pt', '.bin')):
134
- return file_data
 
135
 
136
- if data.get('files'):
137
- return data['files'][0]
 
 
 
 
138
  except Exception:
139
  return None
140
 
@@ -173,99 +189,180 @@ def get_lora_path(source: str, id_or_url: str, civitai_key: str, progress) -> tu
173
  version_id = sanitize_id(id_or_url)
174
  if not version_id:
175
  return None, "Invalid Civitai ID provided. Must be numeric."
 
 
 
 
 
 
 
176
  filename = sanitize_filename(f"civitai_{version_id}.safetensors")
177
  local_path = os.path.join(LORA_DIR, filename)
178
- file_info = get_civitai_file_info(version_id)
179
  api_key_to_use = civitai_key
180
  source_name = f"Civitai ID {version_id}"
 
 
 
 
 
 
 
 
 
 
181
  else:
182
  return None, "Invalid source."
183
 
184
  except ValueError as e:
185
  return None, f"Input validation failed: {e}"
186
 
187
- if os.path.exists(local_path):
188
- return local_path, "File already exists."
 
 
 
189
 
190
- if not file_info or not file_info.get('downloadUrl'):
191
- return None, f"Could not get download link for {source_name}."
 
192
 
193
- status = download_file(file_info['downloadUrl'], local_path, api_key_to_use, progress=progress, desc=f"Downloading {source_name}")
194
-
195
- return (local_path, status) if "Successfully" in status else (None, status)
 
 
 
 
 
 
 
 
 
196
 
197
  def get_embedding_path(source: str, id_or_url: str, civitai_key: str, progress) -> tuple[str | None, str]:
198
  if not id_or_url or not id_or_url.strip():
199
  return None, "No ID/URL provided."
200
 
201
  try:
202
- file_ext = ".safetensors"
203
-
204
  if source == "Civitai":
205
  version_id = sanitize_id(id_or_url)
206
  if not version_id:
207
  return None, "Invalid Civitai ID. Must be numeric."
208
 
209
  file_info = get_civitai_file_info(version_id)
210
- if file_info and file_info['name'].lower().endswith(('.pt', '.bin')):
 
 
 
 
 
 
211
  file_ext = os.path.splitext(file_info['name'])[1]
212
 
213
  filename = sanitize_filename(f"civitai_{version_id}{file_ext}")
214
  local_path = os.path.join(EMBEDDING_DIR, filename)
215
  api_key_to_use = civitai_key
216
  source_name = f"Embedding Civitai ID {version_id}"
 
 
 
 
 
 
 
 
 
217
  else:
218
  return None, "Invalid source."
219
 
220
  except ValueError as e:
221
  return None, f"Input validation failed: {e}"
222
 
223
- if os.path.exists(local_path):
224
- return local_path, "File already exists."
 
 
 
225
 
226
- if not file_info or not file_info.get('downloadUrl'):
227
- return None, f"Could not get download link for {source_name}."
 
228
 
229
- status = download_file(file_info['downloadUrl'], local_path, api_key_to_use, progress=progress, desc=f"Downloading {source_name}")
230
-
231
- return (local_path, status) if "Successfully" in status else (None, status)
 
 
 
 
 
 
 
 
 
232
 
233
  def get_vae_path(source: str, id_or_url: str, civitai_key: str, progress) -> tuple[str | None, str]:
234
  if not id_or_url or not id_or_url.strip():
235
  return None, "No ID/URL provided."
236
 
237
  try:
238
- file_ext = ".safetensors"
239
-
240
  if source == "Civitai":
241
  version_id = sanitize_id(id_or_url)
242
  if not version_id:
243
  return None, "Invalid Civitai ID. Must be numeric."
244
 
245
  file_info = get_civitai_file_info(version_id)
246
- if file_info and file_info['name'].lower().endswith(('.pt', '.bin')):
 
 
 
 
 
 
247
  file_ext = os.path.splitext(file_info['name'])[1]
248
 
249
  filename = sanitize_filename(f"civitai_{version_id}{file_ext}")
250
  local_path = os.path.join(VAE_DIR, filename)
251
  api_key_to_use = civitai_key
252
  source_name = f"VAE Civitai ID {version_id}"
 
 
 
 
 
 
 
 
 
 
253
  else:
254
  return None, "Invalid source."
255
 
256
  except ValueError as e:
257
  return None, f"Input validation failed: {e}"
258
 
259
- if os.path.exists(local_path):
260
- return local_path, "File already exists."
261
-
262
- if not file_info or not file_info.get('downloadUrl'):
263
- return None, f"Could not get download link for {source_name}."
264
 
265
- status = download_file(file_info['downloadUrl'], local_path, api_key_to_use, progress=progress, desc=f"Downloading {source_name}")
266
-
267
- return (local_path, status) if "Successfully" in status else (None, status)
268
 
 
 
 
 
 
 
 
 
 
 
 
 
269
 
270
  def _ensure_model_downloaded(display_name: str, progress=gr.Progress()):
271
  if display_name not in ALL_MODEL_MAP:
@@ -459,7 +556,6 @@ def ensure_ipadapter_models_downloaded(preset_name: str, progress):
459
  except Exception as e:
460
  print(f"❌ Error ensuring download for IPAdapter asset '{filename}': {e}")
461
 
462
-
463
  def ensure_sd3_ipadapter_models_downloaded(progress):
464
  _PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
465
  yaml_path = os.path.join(_PROJECT_ROOT, 'yaml', 'ipadapter_sd3_models.yaml')
@@ -474,8 +570,6 @@ def ensure_sd3_ipadapter_models_downloaded(progress):
474
  except Exception as e:
475
  print(f"Warning: Failed to load or download sd3 ipadapter models: {e}")
476
 
477
-
478
-
479
  def get_model_generation_defaults(model_display_name: str, model_type: str, defaults_config: dict):
480
  final_defaults = {
481
  'steps': 25, 'cfg': 7.0, 'sampler_name': 'euler', 'scheduler': 'simple',
 
105
  def sanitize_id(input_id: str) -> str:
106
  if not isinstance(input_id, str):
107
  return ""
108
+ input_id = input_id.strip()
109
+ if "civitai" in input_id.lower():
110
+ version_match = re.search(r'modelVersionId=(\d+)', input_id)
111
+ if version_match:
112
+ return version_match.group(1)
113
+ model_match = re.search(r'/models/(\d+)', input_id)
114
+ if model_match:
115
+ return model_match.group(1)
116
  return re.sub(r'[^0-9]', '', input_id)
117
 
118
  def sanitize_url(url: str) -> str:
 
137
  response.raise_for_status()
138
  data = response.json()
139
 
140
+ model_type = data.get('model', {}).get('type')
141
+
142
+ result_file = None
143
  for file_data in data.get('files', []):
144
  if file_data.get('type') == 'Model' and file_data['name'].endswith(('.safetensors', '.pt', '.bin')):
145
+ result_file = file_data.copy()
146
+ break
147
 
148
+ if not result_file and data.get('files'):
149
+ result_file = data['files'][0].copy()
150
+
151
+ if result_file:
152
+ result_file['model_type'] = model_type
153
+ return result_file
154
  except Exception:
155
  return None
156
 
 
189
  version_id = sanitize_id(id_or_url)
190
  if not version_id:
191
  return None, "Invalid Civitai ID provided. Must be numeric."
192
+
193
+ file_info = get_civitai_file_info(version_id)
194
+ if file_info:
195
+ model_type = file_info.get('model_type')
196
+ if model_type and model_type.lower() == 'checkpoint':
197
+ return None, f"Invalid Civitai model type '{model_type}' for LoRA. Checkpoint models are not allowed."
198
+
199
  filename = sanitize_filename(f"civitai_{version_id}.safetensors")
200
  local_path = os.path.join(LORA_DIR, filename)
 
201
  api_key_to_use = civitai_key
202
  source_name = f"Civitai ID {version_id}"
203
+ elif source == "Hugging Face":
204
+ parts = id_or_url.strip().split('/')
205
+ if len(parts) < 3:
206
+ return None, "Invalid Hugging Face path. Format: repo_owner/repo_name/filename"
207
+ repo_id = f"{parts[0]}/{parts[1]}"
208
+ repo_file_path = "/".join(parts[2:])
209
+ unique_name = id_or_url.strip().replace('/', '_')
210
+ filename = sanitize_filename(unique_name)
211
+ local_path = os.path.join(LORA_DIR, filename)
212
+ source_name = f"HF {repo_file_path}"
213
  else:
214
  return None, "Invalid source."
215
 
216
  except ValueError as e:
217
  return None, f"Input validation failed: {e}"
218
 
219
+ if os.path.lexists(local_path):
220
+ if not os.path.exists(local_path):
221
+ os.remove(local_path)
222
+ else:
223
+ return local_path, "File already exists."
224
 
225
+ if source == "Civitai":
226
+ if not file_info or not file_info.get('downloadUrl'):
227
+ return None, f"Could not get download link for {source_name}."
228
 
229
+ status = download_file(file_info['downloadUrl'], local_path, api_key_to_use, progress=progress, desc=f"Downloading {source_name}")
230
+ return (local_path, status) if "Successfully" in status else (None, status)
231
+ elif source == "Hugging Face":
232
+ try:
233
+ if progress: progress(0, desc=f"Downloading {source_name}")
234
+ cached_path = hf_hub_download(repo_id=repo_id, filename=repo_file_path, token=os.environ.get("HF_TOKEN"))
235
+ os.makedirs(LORA_DIR, exist_ok=True)
236
+ os.symlink(cached_path, local_path)
237
+ if progress: progress(1.0, desc=f"Downloaded {source_name}")
238
+ return local_path, f"Successfully downloaded: {filename}"
239
+ except Exception as e:
240
+ return None, f"Hugging Face download failed: {e}"
241
 
242
  def get_embedding_path(source: str, id_or_url: str, civitai_key: str, progress) -> tuple[str | None, str]:
243
  if not id_or_url or not id_or_url.strip():
244
  return None, "No ID/URL provided."
245
 
246
  try:
 
 
247
  if source == "Civitai":
248
  version_id = sanitize_id(id_or_url)
249
  if not version_id:
250
  return None, "Invalid Civitai ID. Must be numeric."
251
 
252
  file_info = get_civitai_file_info(version_id)
253
+ if file_info:
254
+ model_type = file_info.get('model_type')
255
+ if model_type and model_type.lower() == 'checkpoint':
256
+ return None, f"Invalid Civitai model type '{model_type}' for Embedding. Checkpoint models are not allowed."
257
+
258
+ file_ext = ".safetensors"
259
+ if file_info and file_info.get('name') and file_info['name'].lower().endswith(('.pt', '.bin')):
260
  file_ext = os.path.splitext(file_info['name'])[1]
261
 
262
  filename = sanitize_filename(f"civitai_{version_id}{file_ext}")
263
  local_path = os.path.join(EMBEDDING_DIR, filename)
264
  api_key_to_use = civitai_key
265
  source_name = f"Embedding Civitai ID {version_id}"
266
+ elif source == "Hugging Face":
267
+ parts = id_or_url.strip().split('/')
268
+ if len(parts) < 3:
269
+ return None, "Invalid Hugging Face path. Format: repo_owner/repo_name/filename"
270
+ repo_id = f"{parts[0]}/{parts[1]}"
271
+ repo_file_path = "/".join(parts[2:])
272
+ filename = sanitize_filename(parts[-1])
273
+ local_path = os.path.join(EMBEDDING_DIR, filename)
274
+ source_name = f"Embedding HF {repo_file_path}"
275
  else:
276
  return None, "Invalid source."
277
 
278
  except ValueError as e:
279
  return None, f"Input validation failed: {e}"
280
 
281
+ if os.path.lexists(local_path):
282
+ if not os.path.exists(local_path):
283
+ os.remove(local_path)
284
+ else:
285
+ return local_path, "File already exists."
286
 
287
+ if source == "Civitai":
288
+ if not file_info or not file_info.get('downloadUrl'):
289
+ return None, f"Could not get download link for {source_name}."
290
 
291
+ status = download_file(file_info['downloadUrl'], local_path, api_key_to_use, progress=progress, desc=f"Downloading {source_name}")
292
+ return (local_path, status) if "Successfully" in status else (None, status)
293
+ elif source == "Hugging Face":
294
+ try:
295
+ if progress: progress(0, desc=f"Downloading {source_name}")
296
+ cached_path = hf_hub_download(repo_id=repo_id, filename=repo_file_path, token=os.environ.get("HF_TOKEN"))
297
+ os.makedirs(EMBEDDING_DIR, exist_ok=True)
298
+ os.symlink(cached_path, local_path)
299
+ if progress: progress(1.0, desc=f"Downloaded {source_name}")
300
+ return local_path, f"Successfully downloaded: {filename}"
301
+ except Exception as e:
302
+ return None, f"Hugging Face download failed: {e}"
303
 
304
  def get_vae_path(source: str, id_or_url: str, civitai_key: str, progress) -> tuple[str | None, str]:
305
  if not id_or_url or not id_or_url.strip():
306
  return None, "No ID/URL provided."
307
 
308
  try:
 
 
309
  if source == "Civitai":
310
  version_id = sanitize_id(id_or_url)
311
  if not version_id:
312
  return None, "Invalid Civitai ID. Must be numeric."
313
 
314
  file_info = get_civitai_file_info(version_id)
315
+ if file_info:
316
+ model_type = file_info.get('model_type')
317
+ if model_type and model_type.lower() == 'checkpoint':
318
+ return None, f"Invalid Civitai model type '{model_type}' for VAE. Checkpoint models are not allowed."
319
+
320
+ file_ext = ".safetensors"
321
+ if file_info and file_info.get('name') and file_info['name'].lower().endswith(('.pt', '.bin')):
322
  file_ext = os.path.splitext(file_info['name'])[1]
323
 
324
  filename = sanitize_filename(f"civitai_{version_id}{file_ext}")
325
  local_path = os.path.join(VAE_DIR, filename)
326
  api_key_to_use = civitai_key
327
  source_name = f"VAE Civitai ID {version_id}"
328
+ elif source == "Hugging Face":
329
+ parts = id_or_url.strip().split('/')
330
+ if len(parts) < 3:
331
+ return None, "Invalid Hugging Face path. Format: repo_owner/repo_name/filename"
332
+ repo_id = f"{parts[0]}/{parts[1]}"
333
+ repo_file_path = "/".join(parts[2:])
334
+ unique_name = id_or_url.strip().replace('/', '_')
335
+ filename = sanitize_filename(unique_name)
336
+ local_path = os.path.join(VAE_DIR, filename)
337
+ source_name = f"VAE HF {repo_file_path}"
338
  else:
339
  return None, "Invalid source."
340
 
341
  except ValueError as e:
342
  return None, f"Input validation failed: {e}"
343
 
344
+ if os.path.lexists(local_path):
345
+ if not os.path.exists(local_path):
346
+ os.remove(local_path)
347
+ else:
348
+ return local_path, "File already exists."
349
 
350
+ if source == "Civitai":
351
+ if not file_info or not file_info.get('downloadUrl'):
352
+ return None, f"Could not get download link for {source_name}."
353
 
354
+ status = download_file(file_info['downloadUrl'], local_path, api_key_to_use, progress=progress, desc=f"Downloading {source_name}")
355
+ return (local_path, status) if "Successfully" in status else (None, status)
356
+ elif source == "Hugging Face":
357
+ try:
358
+ if progress: progress(0, desc=f"Downloading {source_name}")
359
+ cached_path = hf_hub_download(repo_id=repo_id, filename=repo_file_path, token=os.environ.get("HF_TOKEN"))
360
+ os.makedirs(VAE_DIR, exist_ok=True)
361
+ os.symlink(cached_path, local_path)
362
+ if progress: progress(1.0, desc=f"Downloaded {source_name}")
363
+ return local_path, f"Successfully downloaded: {filename}"
364
+ except Exception as e:
365
+ return None, f"Hugging Face download failed: {e}"
366
 
367
  def _ensure_model_downloaded(display_name: str, progress=gr.Progress()):
368
  if display_name not in ALL_MODEL_MAP:
 
556
  except Exception as e:
557
  print(f"❌ Error ensuring download for IPAdapter asset '{filename}': {e}")
558
 
 
559
  def ensure_sd3_ipadapter_models_downloaded(progress):
560
  _PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
561
  yaml_path = os.path.join(_PROJECT_ROOT, 'yaml', 'ipadapter_sd3_models.yaml')
 
570
  except Exception as e:
571
  print(f"Warning: Failed to load or download sd3 ipadapter models: {e}")
572
 
 
 
573
  def get_model_generation_defaults(model_display_name: str, model_type: str, defaults_config: dict):
574
  final_defaults = {
575
  'steps': 25, 'cfg': 7.0, 'sampler_name': 'euler', 'scheduler': 'simple',
yaml/constants.yaml CHANGED
@@ -4,9 +4,25 @@ MAX_IPADAPTERS: 5
4
  MAX_EMBEDDINGS: 5
5
  MAX_CONDITIONINGS: 10
6
  MAX_REFERENCE_LATENTS: 10
7
- LORA_SOURCE_CHOICES: ["Civitai", "File"]
8
 
9
  RESOLUTION_MAP:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  pixeldit:
11
  "1:1 (Square)": [1024, 1024]
12
  "16:9 (Landscape)": [1344, 768]
@@ -15,6 +31,14 @@ RESOLUTION_MAP:
15
  "3:4 (Classic Portrait)": [896, 1152]
16
  "3:2 (Photography)": [1216, 832]
17
  "2:3 (Photography Portrait)": [832, 1216]
 
 
 
 
 
 
 
 
18
  lens:
19
  "1:1 (Square)": [1024, 1024]
20
  "16:9 (Landscape)": [1344, 768]
@@ -23,7 +47,7 @@ RESOLUTION_MAP:
23
  "3:4 (Classic Portrait)": [896, 1152]
24
  "3:2 (Photography)": [1216, 832]
25
  "2:3 (Photography Portrait)": [832, 1216]
26
- ernie-image:
27
  "1:1 (Square)": [1024, 1024]
28
  "16:9 (Landscape)": [1344, 768]
29
  "9:16 (Portrait)": [768, 1344]
@@ -39,7 +63,15 @@ RESOLUTION_MAP:
39
  "3:4 (Classic Portrait)": [896, 1152]
40
  "3:2 (Photography)": [1216, 832]
41
  "2:3 (Photography Portrait)": [832, 1216]
42
- flux2-kv:
 
 
 
 
 
 
 
 
43
  "1:1 (Square)": [1024, 1024]
44
  "16:9 (Landscape)": [1344, 768]
45
  "9:16 (Portrait)": [768, 1344]
@@ -63,6 +95,14 @@ RESOLUTION_MAP:
63
  "3:4 (Classic Portrait)": [896, 1152]
64
  "3:2 (Photography)": [1216, 832]
65
  "2:3 (Photography Portrait)": [832, 1216]
 
 
 
 
 
 
 
 
66
  anima:
67
  "1:1 (Square)": [1024, 1024]
68
  "16:9 (Landscape)": [1344, 768]
@@ -79,7 +119,7 @@ RESOLUTION_MAP:
79
  "3:4 (Classic Portrait)": [896, 1152]
80
  "3:2 (Photography)": [1216, 832]
81
  "2:3 (Photography Portrait)": [832, 1216]
82
- omnigen2:
83
  "1:1 (Square)": [1024, 1024]
84
  "16:9 (Landscape)": [1344, 768]
85
  "9:16 (Portrait)": [768, 1344]
@@ -87,7 +127,7 @@ RESOLUTION_MAP:
87
  "3:4 (Classic Portrait)": [896, 1152]
88
  "3:2 (Photography)": [1216, 832]
89
  "2:3 (Photography Portrait)": [832, 1216]
90
- lumina:
91
  "1:1 (Square)": [1024, 1024]
92
  "16:9 (Landscape)": [1344, 768]
93
  "9:16 (Portrait)": [768, 1344]
@@ -95,7 +135,15 @@ RESOLUTION_MAP:
95
  "3:4 (Classic Portrait)": [896, 1152]
96
  "3:2 (Photography)": [1216, 832]
97
  "2:3 (Photography Portrait)": [832, 1216]
98
- ovis-image:
 
 
 
 
 
 
 
 
99
  "1:1 (Square)": [1024, 1024]
100
  "16:9 (Landscape)": [1344, 768]
101
  "9:16 (Portrait)": [768, 1344]
@@ -103,7 +151,7 @@ RESOLUTION_MAP:
103
  "3:4 (Classic Portrait)": [896, 1152]
104
  "3:2 (Photography)": [1216, 832]
105
  "2:3 (Photography Portrait)": [832, 1216]
106
- flux1:
107
  "1:1 (Square)": [1024, 1024]
108
  "16:9 (Landscape)": [1344, 768]
109
  "9:16 (Portrait)": [768, 1344]
@@ -111,7 +159,7 @@ RESOLUTION_MAP:
111
  "3:4 (Classic Portrait)": [896, 1152]
112
  "3:2 (Photography)": [1216, 832]
113
  "2:3 (Photography Portrait)": [832, 1216]
114
- hidream-o1:
115
  "1:1 (Square)": [1024, 1024]
116
  "16:9 (Landscape)": [1344, 768]
117
  "9:16 (Portrait)": [768, 1344]
@@ -119,7 +167,7 @@ RESOLUTION_MAP:
119
  "3:4 (Classic Portrait)": [896, 1152]
120
  "3:2 (Photography)": [1216, 832]
121
  "2:3 (Photography Portrait)": [832, 1216]
122
- hidream-i1:
123
  "1:1 (Square)": [1024, 1024]
124
  "16:9 (Landscape)": [1344, 768]
125
  "9:16 (Portrait)": [768, 1344]
@@ -127,7 +175,7 @@ RESOLUTION_MAP:
127
  "3:4 (Classic Portrait)": [896, 1152]
128
  "3:2 (Photography)": [1216, 832]
129
  "2:3 (Photography Portrait)": [832, 1216]
130
- sd35:
131
  "1:1 (Square)": [1024, 1024]
132
  "16:9 (Landscape)": [1344, 768]
133
  "9:16 (Portrait)": [768, 1344]
@@ -135,7 +183,7 @@ RESOLUTION_MAP:
135
  "3:4 (Classic Portrait)": [896, 1152]
136
  "3:2 (Photography)": [1216, 832]
137
  "2:3 (Photography Portrait)": [832, 1216]
138
- sdxl:
139
  "1:1 (Square)": [1024, 1024]
140
  "16:9 (Landscape)": [1344, 768]
141
  "9:16 (Portrait)": [768, 1344]
@@ -143,15 +191,7 @@ RESOLUTION_MAP:
143
  "3:4 (Classic Portrait)": [896, 1152]
144
  "3:2 (Photography)": [1216, 832]
145
  "2:3 (Photography Portrait)": [832, 1216]
146
- sd15:
147
- "1:1 (Square)": [512, 512]
148
- "16:9 (Landscape)": [896, 512]
149
- "9:16 (Portrait)": [512, 896]
150
- "4:3 (Classic Landscape)": [683, 512]
151
- "3:4 (Classic Portrait)": [512, 683]
152
- "3:2 (Landscape)": [768, 512]
153
- "2:3 (Portrait)": [512, 768]
154
- chroma1-radiance:
155
  "1:1 (Square)": [1024, 1024]
156
  "16:9 (Landscape)": [1344, 768]
157
  "9:16 (Portrait)": [768, 1344]
@@ -159,7 +199,7 @@ RESOLUTION_MAP:
159
  "3:4 (Classic Portrait)": [896, 1152]
160
  "3:2 (Photography)": [1216, 832]
161
  "2:3 (Photography Portrait)": [832, 1216]
162
- chroma1:
163
  "1:1 (Square)": [1024, 1024]
164
  "16:9 (Landscape)": [1344, 768]
165
  "9:16 (Portrait)": [768, 1344]
@@ -167,11 +207,48 @@ RESOLUTION_MAP:
167
  "3:4 (Classic Portrait)": [896, 1152]
168
  "3:2 (Photography)": [1216, 832]
169
  "2:3 (Photography Portrait)": [832, 1216]
170
- hunyuanimage:
171
- "1:1 (Square)": [2048, 2048]
172
- "16:9 (Landscape)": [2728, 1536]
173
- "9:16 (Portrait)": [1536, 2728]
174
- "4:3 (Classic)": [2368, 1776]
175
- "3:4 (Classic Portrait)": [1776, 2368]
176
- "3:2 (Photography)": [2504, 1672]
177
- "2:3 (Photography Portrait)": [1672, 2504]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  MAX_EMBEDDINGS: 5
5
  MAX_CONDITIONINGS: 10
6
  MAX_REFERENCE_LATENTS: 10
7
+ LORA_SOURCE_CHOICES: ["Civitai", "Hugging Face", "File"]
8
 
9
  RESOLUTION_MAP:
10
+ krea-2:
11
+ "1:1 (Square)": [1024, 1024]
12
+ "16:9 (Landscape)": [1344, 768]
13
+ "9:16 (Portrait)": [768, 1344]
14
+ "4:3 (Classic)": [1152, 896]
15
+ "3:4 (Classic Portrait)": [896, 1152]
16
+ "3:2 (Photography)": [1216, 832]
17
+ "2:3 (Photography Portrait)": [832, 1216]
18
+ boogu-image:
19
+ "1:1 (Square)": [1024, 1024]
20
+ "16:9 (Landscape)": [1344, 768]
21
+ "9:16 (Portrait)": [768, 1344]
22
+ "4:3 (Classic)": [1152, 896]
23
+ "3:4 (Classic Portrait)": [896, 1152]
24
+ "3:2 (Photography)": [1216, 832]
25
+ "2:3 (Photography Portrait)": [832, 1216]
26
  pixeldit:
27
  "1:1 (Square)": [1024, 1024]
28
  "16:9 (Landscape)": [1344, 768]
 
31
  "3:4 (Classic Portrait)": [896, 1152]
32
  "3:2 (Photography)": [1216, 832]
33
  "2:3 (Photography Portrait)": [832, 1216]
34
+ ideogram-4:
35
+ "1:1 (Square)": [1024, 1024]
36
+ "16:9 (Landscape)": [1344, 768]
37
+ "9:16 (Portrait)": [768, 1344]
38
+ "4:3 (Classic)": [1152, 896]
39
+ "3:4 (Classic Portrait)": [896, 1152]
40
+ "3:2 (Photography)": [1216, 832]
41
+ "2:3 (Photography Portrait)": [832, 1216]
42
  lens:
43
  "1:1 (Square)": [1024, 1024]
44
  "16:9 (Landscape)": [1344, 768]
 
47
  "3:4 (Classic Portrait)": [896, 1152]
48
  "3:2 (Photography)": [1216, 832]
49
  "2:3 (Photography Portrait)": [832, 1216]
50
+ flux2-kv:
51
  "1:1 (Square)": [1024, 1024]
52
  "16:9 (Landscape)": [1344, 768]
53
  "9:16 (Portrait)": [768, 1344]
 
63
  "3:4 (Classic Portrait)": [896, 1152]
64
  "3:2 (Photography)": [1216, 832]
65
  "2:3 (Photography Portrait)": [832, 1216]
66
+ ernie-image:
67
+ "1:1 (Square)": [1024, 1024]
68
+ "16:9 (Landscape)": [1344, 768]
69
+ "9:16 (Portrait)": [768, 1344]
70
+ "4:3 (Classic)": [1152, 896]
71
+ "3:4 (Classic Portrait)": [896, 1152]
72
+ "3:2 (Photography)": [1216, 832]
73
+ "2:3 (Photography Portrait)": [832, 1216]
74
+ z-image:
75
  "1:1 (Square)": [1024, 1024]
76
  "16:9 (Landscape)": [1344, 768]
77
  "9:16 (Portrait)": [768, 1344]
 
95
  "3:4 (Classic Portrait)": [896, 1152]
96
  "3:2 (Photography)": [1216, 832]
97
  "2:3 (Photography Portrait)": [832, 1216]
98
+ cosmos-predict2:
99
+ "1:1 (Square)": [1024, 1024]
100
+ "16:9 (Landscape)": [1344, 768]
101
+ "9:16 (Portrait)": [768, 1344]
102
+ "4:3 (Classic)": [1152, 896]
103
+ "3:4 (Classic Portrait)": [896, 1152]
104
+ "3:2 (Photography)": [1216, 832]
105
+ "2:3 (Photography Portrait)": [832, 1216]
106
  anima:
107
  "1:1 (Square)": [1024, 1024]
108
  "16:9 (Landscape)": [1344, 768]
 
119
  "3:4 (Classic Portrait)": [896, 1152]
120
  "3:2 (Photography)": [1216, 832]
121
  "2:3 (Photography Portrait)": [832, 1216]
122
+ kandinsky-5:
123
  "1:1 (Square)": [1024, 1024]
124
  "16:9 (Landscape)": [1344, 768]
125
  "9:16 (Portrait)": [768, 1344]
 
127
  "3:4 (Classic Portrait)": [896, 1152]
128
  "3:2 (Photography)": [1216, 832]
129
  "2:3 (Photography Portrait)": [832, 1216]
130
+ ovis-image:
131
  "1:1 (Square)": [1024, 1024]
132
  "16:9 (Landscape)": [1344, 768]
133
  "9:16 (Portrait)": [768, 1344]
 
135
  "3:4 (Classic Portrait)": [896, 1152]
136
  "3:2 (Photography)": [1216, 832]
137
  "2:3 (Photography Portrait)": [832, 1216]
138
+ hunyuanimage:
139
+ "1:1 (Square)": [2048, 2048]
140
+ "16:9 (Landscape)": [2728, 1536]
141
+ "9:16 (Portrait)": [1536, 2728]
142
+ "4:3 (Classic)": [2368, 1776]
143
+ "3:4 (Classic Portrait)": [1776, 2368]
144
+ "3:2 (Photography)": [2504, 1672]
145
+ "2:3 (Photography Portrait)": [1672, 2504]
146
+ chroma1-radiance:
147
  "1:1 (Square)": [1024, 1024]
148
  "16:9 (Landscape)": [1344, 768]
149
  "9:16 (Portrait)": [768, 1344]
 
151
  "3:4 (Classic Portrait)": [896, 1152]
152
  "3:2 (Photography)": [1216, 832]
153
  "2:3 (Photography Portrait)": [832, 1216]
154
+ chroma1:
155
  "1:1 (Square)": [1024, 1024]
156
  "16:9 (Landscape)": [1344, 768]
157
  "9:16 (Portrait)": [768, 1344]
 
159
  "3:4 (Classic Portrait)": [896, 1152]
160
  "3:2 (Photography)": [1216, 832]
161
  "2:3 (Photography Portrait)": [832, 1216]
162
+ omnigen2:
163
  "1:1 (Square)": [1024, 1024]
164
  "16:9 (Landscape)": [1344, 768]
165
  "9:16 (Portrait)": [768, 1344]
 
167
  "3:4 (Classic Portrait)": [896, 1152]
168
  "3:2 (Photography)": [1216, 832]
169
  "2:3 (Photography Portrait)": [832, 1216]
170
+ lumina:
171
  "1:1 (Square)": [1024, 1024]
172
  "16:9 (Landscape)": [1344, 768]
173
  "9:16 (Portrait)": [768, 1344]
 
175
  "3:4 (Classic Portrait)": [896, 1152]
176
  "3:2 (Photography)": [1216, 832]
177
  "2:3 (Photography Portrait)": [832, 1216]
178
+ hidream-o1:
179
  "1:1 (Square)": [1024, 1024]
180
  "16:9 (Landscape)": [1344, 768]
181
  "9:16 (Portrait)": [768, 1344]
 
183
  "3:4 (Classic Portrait)": [896, 1152]
184
  "3:2 (Photography)": [1216, 832]
185
  "2:3 (Photography Portrait)": [832, 1216]
186
+ hidream-i1:
187
  "1:1 (Square)": [1024, 1024]
188
  "16:9 (Landscape)": [1344, 768]
189
  "9:16 (Portrait)": [768, 1344]
 
191
  "3:4 (Classic Portrait)": [896, 1152]
192
  "3:2 (Photography)": [1216, 832]
193
  "2:3 (Photography Portrait)": [832, 1216]
194
+ flux1:
 
 
 
 
 
 
 
 
195
  "1:1 (Square)": [1024, 1024]
196
  "16:9 (Landscape)": [1344, 768]
197
  "9:16 (Portrait)": [768, 1344]
 
199
  "3:4 (Classic Portrait)": [896, 1152]
200
  "3:2 (Photography)": [1216, 832]
201
  "2:3 (Photography Portrait)": [832, 1216]
202
+ sd35:
203
  "1:1 (Square)": [1024, 1024]
204
  "16:9 (Landscape)": [1344, 768]
205
  "9:16 (Portrait)": [768, 1344]
 
207
  "3:4 (Classic Portrait)": [896, 1152]
208
  "3:2 (Photography)": [1216, 832]
209
  "2:3 (Photography Portrait)": [832, 1216]
210
+ sdxl:
211
+ "1:1 (Square)": [1024, 1024]
212
+ "16:9 (Landscape)": [1344, 768]
213
+ "9:16 (Portrait)": [768, 1344]
214
+ "4:3 (Classic)": [1152, 896]
215
+ "3:4 (Classic Portrait)": [896, 1152]
216
+ "3:2 (Photography)": [1216, 832]
217
+ "2:3 (Photography Portrait)": [832, 1216]
218
+ sd15:
219
+ "1:1 (Square)": [512, 512]
220
+ "16:9 (Landscape)": [896, 512]
221
+ "9:16 (Portrait)": [512, 896]
222
+ "4:3 (Classic Landscape)": [683, 512]
223
+ "3:4 (Classic Portrait)": [512, 683]
224
+ "3:2 (Landscape)": [768, 512]
225
+ "2:3 (Portrait)": [512, 768]
226
+
227
+ MULTIPLIERS_MAP:
228
+ krea-2: 1
229
+ boogu-image: 1
230
+ pixeldit: 1
231
+ ideogram-4: 1
232
+ lens: 1
233
+ flux2-kv: 1
234
+ flux2: 1
235
+ ernie-image: 1
236
+ z-image: 1
237
+ qwen-image: 1
238
+ longcat-image: 1
239
+ cosmos-predict2: 1
240
+ anima: 1
241
+ newbie-image: 1
242
+ kandinsky-5: 32
243
+ ovis-image: 1
244
+ hunyuanimage: 1
245
+ chroma1-radiance: 64
246
+ chroma1: 1
247
+ omnigen2: 1
248
+ lumina: 1
249
+ hidream-o1: 32
250
+ hidream-i1: 1
251
+ flux1: 1
252
+ sd35: 1
253
+ sdxl: 1
254
+ sd15: 1
yaml/file_list.yaml CHANGED
@@ -403,6 +403,33 @@ file:
403
  repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
404
  repository_file_path: "control_v11u_sd15_tile_fp16.safetensors"
405
  diffusion_models:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
  # PixelDiT
407
  - filename: "pixeldit_1300m_1024px_mxfp8.safetensors"
408
  source: "hf"
@@ -417,18 +444,18 @@ file:
417
  source: "hf"
418
  repo_id: "Comfy-Org/PixelDiT"
419
  repository_file_path: "diffusion_models/pid_sd3_1024_to_4096_4step_bf16.safetensors"
420
- - filename: "pid_flux1_1024_to_4096_4step_mxfp8.safetensors"
421
  source: "hf"
422
  repo_id: "Comfy-Org/PixelDiT"
423
- repository_file_path: "diffusion_models/pid_flux1_1024_to_4096_4step_mxfp8.safetensors"
424
- - filename: "pid_qwenimage_1024_to_4096_4step_bf16.safetensors"
425
  source: "hf"
426
  repo_id: "Comfy-Org/PixelDiT"
427
- repository_file_path: "diffusion_models/pid_qwenimage_1024_to_4096_4step_bf16.safetensors"
428
- - filename: "pid_flux2_1024_to_4096_4step_mxfp8.safetensors"
429
  source: "hf"
430
  repo_id: "Comfy-Org/PixelDiT"
431
- repository_file_path: "diffusion_models/pid_flux2_1024_to_4096_4step_mxfp8.safetensors"
432
  # Lens
433
  - filename: "lens_mxfp8.safetensors"
434
  source: "hf"
@@ -438,23 +465,48 @@ file:
438
  source: "hf"
439
  repo_id: "Comfy-Org/Lens"
440
  repository_file_path: "diffusion_models/lens_turbo_mxfp8.safetensors"
 
 
 
 
 
 
 
 
 
441
  # Anima
442
- - filename: "waiANIMA_v10.safetensors"
443
  source: "hf"
444
- repo_id: "diffusionmodels1254ani/waiANIMA"
445
- repository_file_path: "waiANIMA_v10.safetensors"
 
 
 
 
446
  - filename: "anima-base-v1.0.safetensors"
447
  source: "hf"
448
  repo_id: "circlestone-labs/Anima"
449
  repository_file_path: "split_files/diffusion_models/anima-base-v1.0.safetensors"
450
- - filename: "AnimaYume_tuned_v05.safetensors"
 
 
 
 
451
  source: "hf"
452
  repo_id: "duongve/AnimaYume"
453
- repository_file_path: "split_files/diffusion_models/AnimaYume_tuned_v05.safetensors"
454
- - filename: "anima_pencil-v1.0.0.safetensors"
 
 
 
 
 
 
 
 
455
  source: "hf"
456
  repo_id: "bluepen5805/anima-models"
457
- repository_file_path: "anima_pencil-v1.0.0.safetensors"
458
  # NewBie-Image
459
  - filename: "NewBie-Image-Exp0.1-bf16.safetensors"
460
  source: "hf"
@@ -523,23 +575,24 @@ file:
523
  source: "hf"
524
  repo_id: "Comfy-Org/Qwen-Image_ComfyUI"
525
  repository_file_path: "split_files/diffusion_models/qwen_image_2512_fp8_e4m3fn.safetensors"
526
- - filename: "qwen_image_fp8_e4m3fn.safetensors"
527
  source: "hf"
528
  repo_id: "Comfy-Org/Qwen-Image_ComfyUI"
529
- repository_file_path: "split_files/diffusion_models/qwen_image_fp8_e4m3fn.safetensors"
 
 
 
 
 
530
  # Flux.1
531
- - filename: "flux1-dev-fp8-e4m3fn.safetensors"
532
  source: "hf"
533
- repo_id: "Kijai/flux-fp8"
534
- repository_file_path: "flux1-dev-fp8-e4m3fn.safetensors"
535
  - filename: "flux1-schnell-fp8-e4m3fn.safetensors"
536
  source: "hf"
537
  repo_id: "Kijai/flux-fp8"
538
  repository_file_path: "flux1-schnell-fp8-e4m3fn.safetensors"
539
- - filename: "flux1-dev-kontext_fp8_scaled.safetensors"
540
- source: "hf"
541
- repo_id: "Comfy-Org/flux1-kontext-dev_ComfyUI"
542
- repository_file_path: "split_files/diffusion_models/flux1-dev-kontext_fp8_scaled.safetensors"
543
  - filename: "flux1-krea-dev_fp8_scaled.safetensors"
544
  source: "hf"
545
  repo_id: "Comfy-Org/FLUX.1-Krea-dev_ComfyUI"
@@ -557,6 +610,7 @@ file:
557
  source: "hf"
558
  repo_id: "Comfy-Org/HiDream-I1_ComfyUI"
559
  repository_file_path: "split_files/diffusion_models/hidream_i1_full_fp8.safetensors"
 
560
  - filename: "hunyuanimage2.1_fp8_e4m3fn.safetensors"
561
  source: "hf"
562
  repo_id: "Comfy-Org/HunyuanImage_2.1_ComfyUI"
@@ -579,6 +633,7 @@ file:
579
  source: "hf"
580
  repo_id: "Clybius/Chroma-fp8-scaled"
581
  repository_file_path: "Chroma1-HD/Chroma1-HD_float8_e4m3fn_scaled_learned_topk8_svd.safetensors"
 
582
  - filename: "omnigen2_fp16.safetensors"
583
  source: "hf"
584
  repo_id: "Comfy-Org/Omnigen2_ComfyUI_repackaged"
@@ -671,15 +726,11 @@ file:
671
  repo_id: "black-forest-labs/FLUX.1-Redux-dev"
672
  repository_file_path: "flux1-redux-dev.safetensors"
673
  loras:
674
- # Qwen-Image
675
- - filename: "Qwen-Image-2512-Lightning-4steps-V1.0-bf16.safetensors"
676
- source: "hf"
677
- repo_id: "lightx2v/Qwen-Image-2512-Lightning"
678
- repository_file_path: "Qwen-Image-2512-Lightning-4steps-V1.0-bf16.safetensors"
679
- - filename: "Qwen-Image-fp8-e4m3fn-Lightning-4steps-V1.0-bf16.safetensors"
680
  source: "hf"
681
- repo_id: "lightx2v/Qwen-Image-Lightning"
682
- repository_file_path: "Qwen-Image-fp8-e4m3fn-Lightning-4steps-V1.0-bf16.safetensors"
683
  # SD1.5 FaceID
684
  - filename: "ip-adapter-faceid_sd15_lora.safetensors"
685
  source: "hf"
@@ -708,6 +759,21 @@ file:
708
  repo_id: "alibaba-pai/Z-Image-Turbo-Fun-Controlnet-Union-2.1"
709
  repository_file_path: "Z-Image-Turbo-Fun-Controlnet-Tile-2.1-8steps.safetensors"
710
  text_encoders:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
711
  # PixelDiT
712
  - filename: "gemma_2_2b_it_elm_fp8_scaled.safetensors"
713
  source: "hf"
@@ -782,10 +848,10 @@ file:
782
  source: "hf"
783
  repo_id: "Comfy-Org/HiDream-I1_ComfyUI"
784
  repository_file_path: "split_files/text_encoders/llama_3.1_8b_instruct_fp8_scaled.safetensors"
785
- - filename: "qwen_2.5_vl_7b_fp8_scaled.safetensors"
786
  source: "hf"
787
  repo_id: "Comfy-Org/Qwen-Image_ComfyUI"
788
- repository_file_path: "split_files/text_encoders/qwen_2.5_vl_7b_fp8_scaled.safetensors"
789
  - filename: "byt5_small_glyphxl_fp16.safetensors"
790
  source: "hf"
791
  repo_id: "Comfy-Org/HunyuanImage_2.1_ComfyUI"
@@ -795,6 +861,10 @@ file:
795
  repo_id: "Comfy-Org/Omnigen2_ComfyUI_repackaged"
796
  repository_file_path: "split_files/text_encoders/qwen_2.5_vl_fp16.safetensors"
797
  vae:
 
 
 
 
798
  - filename: "qwen_image_vae.safetensors"
799
  source: "hf"
800
  repo_id: "Comfy-Org/Qwen-Image_ComfyUI"
 
403
  repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
404
  repository_file_path: "control_v11u_sd15_tile_fp16.safetensors"
405
  diffusion_models:
406
+ # Krea-2
407
+ - filename: "krea2_turbo_nvfp4.safetensors"
408
+ source: "hf"
409
+ repo_id: "Comfy-Org/Krea-2"
410
+ repository_file_path: "diffusion_models/krea2_turbo_nvfp4.safetensors"
411
+ - filename: "krea2_raw_fp8_scaled.safetensors"
412
+ source: "hf"
413
+ repo_id: "Comfy-Org/Krea-2"
414
+ repository_file_path: "diffusion_models/krea2_raw_fp8_scaled.safetensors"
415
+ # Boogu-Image
416
+ - filename: "boogu_image_base_nvfp4.safetensors"
417
+ source: "hf"
418
+ repo_id: "Comfy-Org/Boogu-Image"
419
+ repository_file_path: "diffusion_models/boogu_image_base_nvfp4.safetensors"
420
+ - filename: "boogu_image_turbo_hotfix_nvfp4.safetensors"
421
+ source: "hf"
422
+ repo_id: "Comfy-Org/Boogu-Image"
423
+ repository_file_path: "diffusion_models/boogu_image_turbo_hotfix_nvfp4.safetensors"
424
+ # Ideogram-4
425
+ - filename: "ideogram4_nvfp4_mixed.safetensors"
426
+ source: "hf"
427
+ repo_id: "Comfy-Org/Ideogram-4"
428
+ repository_file_path: "diffusion_models/ideogram4_nvfp4_mixed.safetensors"
429
+ - filename: "ideogram4_unconditional_nvfp4_mixed.safetensors"
430
+ source: "hf"
431
+ repo_id: "Comfy-Org/Ideogram-4"
432
+ repository_file_path: "diffusion_models/ideogram4_unconditional_nvfp4_mixed.safetensors"
433
  # PixelDiT
434
  - filename: "pixeldit_1300m_1024px_mxfp8.safetensors"
435
  source: "hf"
 
444
  source: "hf"
445
  repo_id: "Comfy-Org/PixelDiT"
446
  repository_file_path: "diffusion_models/pid_sd3_1024_to_4096_4step_bf16.safetensors"
447
+ - filename: "pid_1.5_flux1_1024_to_4096_4step_int8_convrot.safetensors"
448
  source: "hf"
449
  repo_id: "Comfy-Org/PixelDiT"
450
+ repository_file_path: "diffusion_models/pid_1.5_flux1_1024_to_4096_4step_int8_convrot.safetensors"
451
+ - filename: "pid_1.5_qwenimage_1024_to_4096_4step_int8_convrot.safetensors"
452
  source: "hf"
453
  repo_id: "Comfy-Org/PixelDiT"
454
+ repository_file_path: "diffusion_models/pid_1.5_qwenimage_1024_to_4096_4step_int8_convrot.safetensors"
455
+ - filename: "pid_1.5_flux2_1024_to_4096_4step_int8_convrot.safetensors"
456
  source: "hf"
457
  repo_id: "Comfy-Org/PixelDiT"
458
+ repository_file_path: "diffusion_models/pid_1.5_flux2_1024_to_4096_4step_int8_convrot.safetensors"
459
  # Lens
460
  - filename: "lens_mxfp8.safetensors"
461
  source: "hf"
 
465
  source: "hf"
466
  repo_id: "Comfy-Org/Lens"
467
  repository_file_path: "diffusion_models/lens_turbo_mxfp8.safetensors"
468
+ # Cosmos-Predict2
469
+ - filename: "cosmos_predict2_2B_t2i.pt"
470
+ source: "hf"
471
+ repo_id: "nvidia/Cosmos-Predict2-2B-Text2Image"
472
+ repository_file_path: "model.pt"
473
+ - filename: "cosmos_predict2_14B_t2i.pt"
474
+ source: "hf"
475
+ repo_id: "nvidia/Cosmos-Predict2-14B-Text2Image"
476
+ repository_file_path: "model.pt"
477
  # Anima
478
+ - filename: "anima-turbo-v1.0.safetensors"
479
  source: "hf"
480
+ repo_id: "circlestone-labs/Anima"
481
+ repository_file_path: "split_files/diffusion_models/anima-turbo-v1.0.safetensors"
482
+ - filename: "anima-aesthetic-v1.1.safetensors"
483
+ source: "hf"
484
+ repo_id: "circlestone-labs/Anima"
485
+ repository_file_path: "split_files/diffusion_models/anima-aesthetic-v1.1.safetensors"
486
  - filename: "anima-base-v1.0.safetensors"
487
  source: "hf"
488
  repo_id: "circlestone-labs/Anima"
489
  repository_file_path: "split_files/diffusion_models/anima-base-v1.0.safetensors"
490
+ - filename: "waiANIMA_v10Base10.safetensors"
491
+ source: "hf"
492
+ repo_id: "diffusionmodels1254ani/waiANIMA"
493
+ repository_file_path: "waiANIMA_v10Base10.safetensors"
494
+ - filename: "AnimaYume_v10_final_base.safetensors"
495
  source: "hf"
496
  repo_id: "duongve/AnimaYume"
497
+ repository_file_path: "split_files/diffusion_models/AnimaYume_v10_final_base.safetensors"
498
+ - filename: "hassakuAnima_v1Style.safetensors"
499
+ source: "hf"
500
+ repo_id: "diffusionmodels1254ani/hassakuAnima"
501
+ repository_file_path: "hassakuAnima_v1Style.safetensors"
502
+ - filename: "kirazuriAnima_v30AnimaBase1.safetensors"
503
+ source: "hf"
504
+ repo_id: "diffusionmodels1254ani/kirazuriAnima_v30AnimaBase1"
505
+ repository_file_path: "kirazuriAnima_v30AnimaBase1.safetensors"
506
+ - filename: "anima_pencil-v2.1.0.safetensors"
507
  source: "hf"
508
  repo_id: "bluepen5805/anima-models"
509
+ repository_file_path: "anima_pencil-v2.1.0.safetensors"
510
  # NewBie-Image
511
  - filename: "NewBie-Image-Exp0.1-bf16.safetensors"
512
  source: "hf"
 
575
  source: "hf"
576
  repo_id: "Comfy-Org/Qwen-Image_ComfyUI"
577
  repository_file_path: "split_files/diffusion_models/qwen_image_2512_fp8_e4m3fn.safetensors"
578
+ - filename: "qwen_image_nvfp4.safetensors"
579
  source: "hf"
580
  repo_id: "Comfy-Org/Qwen-Image_ComfyUI"
581
+ repository_file_path: "split_files/diffusion_models/qwen_image_nvfp4.safetensors"
582
+ # Kandinsky-5
583
+ - filename: "kandinsky5lite_t2i.safetensors"
584
+ source: "hf"
585
+ repo_id: "kandinskylab/Kandinsky-5.0-T2I-Lite"
586
+ repository_file_path: "model/kandinsky5lite_t2i.safetensors"
587
  # Flux.1
588
+ - filename: "flux1-dev-nvfp4.safetensors"
589
  source: "hf"
590
+ repo_id: "black-forest-labs/FLUX.1-dev-NVFP4"
591
+ repository_file_path: "flux1-dev-nvfp4.safetensors"
592
  - filename: "flux1-schnell-fp8-e4m3fn.safetensors"
593
  source: "hf"
594
  repo_id: "Kijai/flux-fp8"
595
  repository_file_path: "flux1-schnell-fp8-e4m3fn.safetensors"
 
 
 
 
596
  - filename: "flux1-krea-dev_fp8_scaled.safetensors"
597
  source: "hf"
598
  repo_id: "Comfy-Org/FLUX.1-Krea-dev_ComfyUI"
 
610
  source: "hf"
611
  repo_id: "Comfy-Org/HiDream-I1_ComfyUI"
612
  repository_file_path: "split_files/diffusion_models/hidream_i1_full_fp8.safetensors"
613
+ # HunyuanImage-2.1
614
  - filename: "hunyuanimage2.1_fp8_e4m3fn.safetensors"
615
  source: "hf"
616
  repo_id: "Comfy-Org/HunyuanImage_2.1_ComfyUI"
 
633
  source: "hf"
634
  repo_id: "Clybius/Chroma-fp8-scaled"
635
  repository_file_path: "Chroma1-HD/Chroma1-HD_float8_e4m3fn_scaled_learned_topk8_svd.safetensors"
636
+ # Omnigen2
637
  - filename: "omnigen2_fp16.safetensors"
638
  source: "hf"
639
  repo_id: "Comfy-Org/Omnigen2_ComfyUI_repackaged"
 
726
  repo_id: "black-forest-labs/FLUX.1-Redux-dev"
727
  repository_file_path: "flux1-redux-dev.safetensors"
728
  loras:
729
+ # Krea2 ControlNet
730
+ - filename: "depth-control-lora.safetensors"
 
 
 
 
731
  source: "hf"
732
+ repo_id: "Patil/Krea-2-depth-controlnet"
733
+ repository_file_path: "depth-control-lora.safetensors"
734
  # SD1.5 FaceID
735
  - filename: "ip-adapter-faceid_sd15_lora.safetensors"
736
  source: "hf"
 
759
  repo_id: "alibaba-pai/Z-Image-Turbo-Fun-Controlnet-Union-2.1"
760
  repository_file_path: "Z-Image-Turbo-Fun-Controlnet-Tile-2.1-8steps.safetensors"
761
  text_encoders:
762
+ # Krea-2
763
+ - filename: "qwen3vl_4b_fp8_scaled.safetensors"
764
+ source: "hf"
765
+ repo_id: "Comfy-Org/Krea-2"
766
+ repository_file_path: "text_encoders/qwen3vl_4b_fp8_scaled.safetensors"
767
+ # Cosmos-Predict2
768
+ - filename: "oldt5_xxl_fp8_e4m3fn_scaled.safetensors"
769
+ source: "hf"
770
+ repo_id: "comfyanonymous/cosmos_1.0_text_encoder_and_VAE_ComfyUI"
771
+ repository_file_path: "text_encoders/oldt5_xxl_fp8_e4m3fn_scaled.safetensors"
772
+ # Ideogram-4 & Boogu-Image
773
+ - filename: "qwen3vl_8b_nvfp4.safetensors"
774
+ source: "hf"
775
+ repo_id: "Comfy-Org/Ideogram-4"
776
+ repository_file_path: "text_encoders/qwen3vl_8b_nvfp4.safetensors"
777
  # PixelDiT
778
  - filename: "gemma_2_2b_it_elm_fp8_scaled.safetensors"
779
  source: "hf"
 
848
  source: "hf"
849
  repo_id: "Comfy-Org/HiDream-I1_ComfyUI"
850
  repository_file_path: "split_files/text_encoders/llama_3.1_8b_instruct_fp8_scaled.safetensors"
851
+ - filename: "qwen_2.5_vl_7b_nvfp4.safetensors"
852
  source: "hf"
853
  repo_id: "Comfy-Org/Qwen-Image_ComfyUI"
854
+ repository_file_path: "split_files/text_encoders/qwen_2.5_vl_7b_nvfp4.safetensors"
855
  - filename: "byt5_small_glyphxl_fp16.safetensors"
856
  source: "hf"
857
  repo_id: "Comfy-Org/HunyuanImage_2.1_ComfyUI"
 
861
  repo_id: "Comfy-Org/Omnigen2_ComfyUI_repackaged"
862
  repository_file_path: "split_files/text_encoders/qwen_2.5_vl_fp16.safetensors"
863
  vae:
864
+ - filename: "wan_2.1_vae.safetensors"
865
+ source: "hf"
866
+ repo_id: "Comfy-Org/Wan_2.1_ComfyUI_repackaged"
867
+ repository_file_path: "split_files/vae/wan_2.1_vae.safetensors"
868
  - filename: "qwen_image_vae.safetensors"
869
  source: "hf"
870
  repo_id: "Comfy-Org/Qwen-Image_ComfyUI"
yaml/image_gen_features.yaml CHANGED
@@ -8,38 +8,54 @@ default:
8
  - conditioning
9
  - vae
10
 
11
- pixeldit:
 
 
 
 
 
 
 
12
  enabled_chains:
 
13
  - conditioning
 
14
 
15
- lens:
16
  enabled_chains:
17
  - conditioning
 
 
 
 
18
  - pid
19
 
20
- ernie-image:
21
  enabled_chains:
22
  - conditioning
23
  - pid
24
- anima:
 
25
  enabled_chains:
26
  - lora
27
- - anima_controlnet_lllite
28
  - conditioning
 
29
  - vae
30
  - pid
31
- longcat-image:
 
32
  enabled_chains:
33
  - lora
34
  - conditioning
 
 
35
  - pid
36
- newbie-image:
 
37
  enabled_chains:
38
- - lora
39
- - embedding
40
  - conditioning
41
- - vae
42
  - pid
 
43
  z-image:
44
  enabled_chains:
45
  - lora
@@ -47,97 +63,130 @@ z-image:
47
  - controlnet_model_patch
48
  - vae
49
  - pid
50
- lumina:
 
51
  enabled_chains:
52
  - lora
53
- - embedding
54
  - conditioning
55
  - vae
56
  - pid
57
- sd35:
 
58
  enabled_chains:
59
  - lora
60
- - controlnet
61
- - embedding
62
  - conditioning
63
- - sd3_ipadapter
64
- - vae
65
  - pid
66
- sdxl:
 
 
 
 
 
 
67
  enabled_chains:
68
  - lora
69
- - controlnet
70
- - ipadapter
71
- - embedding
72
  - conditioning
73
  - vae
74
  - pid
75
- sd15:
 
76
  enabled_chains:
77
  - lora
78
- - controlnet
79
- - ipadapter
80
  - embedding
81
  - conditioning
82
  - vae
83
- flux2:
 
 
84
  enabled_chains:
85
- - lora
86
  - conditioning
87
- - reference_latent
88
  - vae
89
  - pid
90
- flux2-kv:
 
91
  enabled_chains:
92
- - lora
93
  - conditioning
94
- - reference_latent
95
  - vae
96
  - pid
97
- flux1:
 
 
 
 
 
 
 
 
 
 
98
  enabled_chains:
99
- - lora
100
- - controlnet
101
- - style
102
  - conditioning
103
- - flux1_ipadapter
104
  - vae
105
  - pid
 
106
  omnigen2:
107
  enabled_chains:
108
  - conditioning
109
  - reference_latent
110
  - pid
111
- qwen-image:
 
112
  enabled_chains:
113
  - lora
114
- - controlnet
115
  - conditioning
116
  - vae
117
  - pid
 
118
  hidream-o1:
119
  enabled_chains:
120
  - lora
121
  - conditioning
122
  - hidream_o1_reference
 
123
  hidream-i1:
124
  enabled_chains:
125
  - lora
126
  - conditioning
127
  - pid
128
- hunyuanimage:
 
129
  enabled_chains:
 
 
 
130
  - conditioning
 
131
  - vae
 
132
 
133
- ovis-image:
134
  enabled_chains:
 
 
 
135
  - conditioning
 
136
  - vae
137
  - pid
138
 
139
- chroma1:
140
  enabled_chains:
 
 
 
 
141
  - conditioning
142
  - vae
143
- - pid
 
 
 
 
 
 
 
 
 
 
8
  - conditioning
9
  - vae
10
 
11
+ krea-2:
12
+ enabled_chains:
13
+ - lora
14
+ - krea2_controlnet
15
+ - conditioning
16
+ - pid
17
+
18
+ boogu-image:
19
  enabled_chains:
20
+ - lora
21
  - conditioning
22
+ - pid
23
 
24
+ pixeldit:
25
  enabled_chains:
26
  - conditioning
27
+
28
+ ideogram-4:
29
+ enabled_chains:
30
+ - vae
31
  - pid
32
 
33
+ lens:
34
  enabled_chains:
35
  - conditioning
36
  - pid
37
+
38
+ flux2-kv:
39
  enabled_chains:
40
  - lora
 
41
  - conditioning
42
+ - reference_latent
43
  - vae
44
  - pid
45
+
46
+ flux2:
47
  enabled_chains:
48
  - lora
49
  - conditioning
50
+ - reference_latent
51
+ - vae
52
  - pid
53
+
54
+ ernie-image:
55
  enabled_chains:
 
 
56
  - conditioning
 
57
  - pid
58
+
59
  z-image:
60
  enabled_chains:
61
  - lora
 
63
  - controlnet_model_patch
64
  - vae
65
  - pid
66
+
67
+ qwen-image:
68
  enabled_chains:
69
  - lora
70
+ - controlnet
71
  - conditioning
72
  - vae
73
  - pid
74
+
75
+ longcat-image:
76
  enabled_chains:
77
  - lora
 
 
78
  - conditioning
 
 
79
  - pid
80
+
81
+ cosmos-predict2:
82
+ enabled_chains:
83
+ - conditioning
84
+ - vae
85
+
86
+ anima:
87
  enabled_chains:
88
  - lora
89
+ - anima_controlnet_lllite
 
 
90
  - conditioning
91
  - vae
92
  - pid
93
+
94
+ newbie-image:
95
  enabled_chains:
96
  - lora
 
 
97
  - embedding
98
  - conditioning
99
  - vae
100
+ - pid
101
+
102
+ kandinsky-5:
103
  enabled_chains:
 
104
  - conditioning
 
105
  - vae
106
  - pid
107
+
108
+ ovis-image:
109
  enabled_chains:
 
110
  - conditioning
 
111
  - vae
112
  - pid
113
+
114
+ hunyuanimage:
115
+ enabled_chains:
116
+ - conditioning
117
+ - vae
118
+
119
+ chroma1-radiance:
120
+ enabled_chains:
121
+ - conditioning
122
+
123
+ chroma1:
124
  enabled_chains:
 
 
 
125
  - conditioning
 
126
  - vae
127
  - pid
128
+
129
  omnigen2:
130
  enabled_chains:
131
  - conditioning
132
  - reference_latent
133
  - pid
134
+
135
+ lumina:
136
  enabled_chains:
137
  - lora
138
+ - embedding
139
  - conditioning
140
  - vae
141
  - pid
142
+
143
  hidream-o1:
144
  enabled_chains:
145
  - lora
146
  - conditioning
147
  - hidream_o1_reference
148
+
149
  hidream-i1:
150
  enabled_chains:
151
  - lora
152
  - conditioning
153
  - pid
154
+
155
+ flux1:
156
  enabled_chains:
157
+ - lora
158
+ - controlnet
159
+ - style
160
  - conditioning
161
+ - flux1_ipadapter
162
  - vae
163
+ - pid
164
 
165
+ sd35:
166
  enabled_chains:
167
+ - lora
168
+ - controlnet
169
+ - embedding
170
  - conditioning
171
+ - sd3_ipadapter
172
  - vae
173
  - pid
174
 
175
+ sdxl:
176
  enabled_chains:
177
+ - lora
178
+ - controlnet
179
+ - ipadapter
180
+ - embedding
181
  - conditioning
182
  - vae
183
+ - pid
184
+
185
+ sd15:
186
+ enabled_chains:
187
+ - lora
188
+ - controlnet
189
+ - ipadapter
190
+ - embedding
191
+ - conditioning
192
+ - vae
yaml/krea2_controlnet_models.yaml ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ Krea2_ControlNet:
2
+ - Filepath: "depth-control-lora.safetensors"
3
+ Series: "Patil"
4
+ Type: ["Depth"]
yaml/model_architectures.yaml CHANGED
@@ -1,5 +1,8 @@
1
  architecture_order:
 
 
2
  - "PixelDiT"
 
3
  - "Lens"
4
  - "FLUX.2-KV"
5
  - "FLUX.2"
@@ -7,8 +10,10 @@ architecture_order:
7
  - "Z-Image"
8
  - "Qwen-Image"
9
  - "LongCat-Image"
 
10
  - "Anima"
11
  - "NewBie-Image"
 
12
  - "Ovis-Image"
13
  - "HunyuanImage"
14
  - "Chroma1-Radiance"
@@ -23,15 +28,18 @@ architecture_order:
23
  - "SD1.5"
24
 
25
  architectures:
 
 
 
 
26
  "PixelDiT":
27
  model_type: "pixeldit"
28
- controlnet_key: "PixelDiT"
 
29
  "Lens":
30
  model_type: "lens"
31
- controlnet_key: "Lens"
32
  "ERNIE-Image":
33
  model_type: "ernie-image"
34
- controlnet_key: "ERNIE-Image"
35
  "FLUX.2-KV":
36
  model_type: "flux2-kv"
37
  controlnet_key: "FLUX.2"
@@ -47,6 +55,9 @@ architectures:
47
  "LongCat-Image":
48
  model_type: "longcat-image"
49
  controlnet_key: "LongCat-Image"
 
 
 
50
  "Anima":
51
  model_type: "anima"
52
  controlnet_key: "Anima"
@@ -62,6 +73,9 @@ architectures:
62
  "Lumina":
63
  model_type: "lumina"
64
  controlnet_key: "Lumina"
 
 
 
65
  "Ovis-Image":
66
  model_type: "ovis-image"
67
  controlnet_key: "Ovis-Image"
 
1
  architecture_order:
2
+ - "Krea-2"
3
+ - "Boogu-Image"
4
  - "PixelDiT"
5
+ - "Ideogram-4"
6
  - "Lens"
7
  - "FLUX.2-KV"
8
  - "FLUX.2"
 
10
  - "Z-Image"
11
  - "Qwen-Image"
12
  - "LongCat-Image"
13
+ - "Cosmos-Predict2"
14
  - "Anima"
15
  - "NewBie-Image"
16
+ - "Kandinsky-5"
17
  - "Ovis-Image"
18
  - "HunyuanImage"
19
  - "Chroma1-Radiance"
 
28
  - "SD1.5"
29
 
30
  architectures:
31
+ Krea-2:
32
+ model_type: "krea-2"
33
+ "Boogu-Image":
34
+ model_type: "boogu-image"
35
  "PixelDiT":
36
  model_type: "pixeldit"
37
+ "Ideogram-4":
38
+ model_type: "ideogram-4"
39
  "Lens":
40
  model_type: "lens"
 
41
  "ERNIE-Image":
42
  model_type: "ernie-image"
 
43
  "FLUX.2-KV":
44
  model_type: "flux2-kv"
45
  controlnet_key: "FLUX.2"
 
55
  "LongCat-Image":
56
  model_type: "longcat-image"
57
  controlnet_key: "LongCat-Image"
58
+ "Cosmos-Predict2":
59
+ model_type: "cosmos-predict2"
60
+ controlnet_key: "Cosmos-Predict2"
61
  "Anima":
62
  model_type: "anima"
63
  controlnet_key: "Anima"
 
73
  "Lumina":
74
  model_type: "lumina"
75
  controlnet_key: "Lumina"
76
+ "Kandinsky-5":
77
+ model_type: "kandinsky-5"
78
+ controlnet_key: "Kandinsky-5"
79
  "Ovis-Image":
80
  model_type: "ovis-image"
81
  controlnet_key: "Ovis-Image"
yaml/model_defaults.yaml CHANGED
@@ -1,17 +1,50 @@
1
  Default:
2
- steps: 20
3
- cfg: 5.0
4
  sampler_name: "euler"
5
  scheduler: "simple"
6
  positive_prompt: ""
7
  negative_prompt: ""
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  PixelDiT:
10
  _defaults:
11
  steps: 30
12
  cfg: 4.0
13
  sampler_name: "er_sde"
14
  scheduler: "simple"
 
 
 
 
 
 
 
 
 
15
 
16
  Lens:
17
  _defaults:
@@ -23,14 +56,9 @@ Lens:
23
  steps: 4
24
  cfg: 1.0
25
 
26
- ERNIE-Image:
27
  _defaults:
28
- steps: 20
29
- cfg: 4.0
30
- sampler_name: "euler"
31
- scheduler: "simple"
32
- "baidu/ERNIE-Image-Turbo":
33
- steps: 8
34
  cfg: 1.0
35
  sampler_name: "euler"
36
  scheduler: "simple"
@@ -48,14 +76,14 @@ FLUX.2:
48
  steps: 4
49
  cfg: 1.0
50
 
51
- FLUX.2-KV:
52
  _defaults:
53
  steps: 20
54
  cfg: 4.0
55
  sampler_name: "euler"
56
  scheduler: "simple"
57
- "black-forest-labs/FLUX.2-klein-9B-KV":
58
- steps: 4
59
  cfg: 1.0
60
 
61
  Z-Image:
@@ -67,13 +95,11 @@ Z-Image:
67
  "Tongyi-MAI/Z Image Turbo":
68
  steps: 9
69
  cfg: 1.0
70
- sampler_name: "euler"
71
- scheduler: "simple"
72
 
73
  Qwen-Image:
74
  _defaults:
75
- steps: 4
76
- cfg: 1.0
77
  sampler_name: "euler"
78
  scheduler: "simple"
79
 
@@ -85,6 +111,13 @@ LongCat-Image:
85
  sampler_name: "euler"
86
  scheduler: "simple"
87
 
 
 
 
 
 
 
 
88
  Anima:
89
  _defaults:
90
  steps: 30
@@ -93,6 +126,9 @@ Anima:
93
  scheduler: "simple"
94
  positive_prompt: "masterpiece, best quality, score_7, safe. "
95
  negative_prompt: "worst quality, low quality, score_1, score_2, score_3, blurry, jpeg artifacts, sepia"
 
 
 
96
 
97
  NewBie-Image:
98
  _defaults:
@@ -103,33 +139,29 @@ NewBie-Image:
103
  positive_prompt: "You are an assistant designed to generate high-quality anime images with the highest degree of image-text alignment based on xml format textual prompts. <Prompt Start>"
104
  negative_prompt: "You are an assistant designed to generate low-quality images based on textual prompts. <Prompt Start>"
105
 
106
- Ovis-Image:
107
  _defaults:
108
- steps: 20
109
- cfg: 5.0
110
  sampler_name: "euler"
111
  scheduler: "simple"
112
 
113
- OmniGen2:
114
  _defaults:
115
  steps: 20
116
  cfg: 5.0
117
  sampler_name: "euler"
118
  scheduler: "simple"
119
- positive_prompt: ""
120
- negative_prompt: ""
121
 
122
- Chroma1:
123
  _defaults:
124
- steps: 30
125
- cfg: 4.0
126
  sampler_name: "euler"
127
  scheduler: "simple"
128
- negative_prompt: "low quality, bad anatomy, extra digits, missing digits, extra limbs, missing limbs"
129
- "lodestones/Chroma1-HD-Flash":
130
  steps: 8
131
  cfg: 1.0
132
- scheduler: "beta"
133
 
134
  Chroma1-Radiance:
135
  _defaults:
@@ -139,40 +171,35 @@ Chroma1-Radiance:
139
  scheduler: "simple"
140
  negative_prompt: "low quality, bad anatomy, extra digits, missing digits, extra limbs, missing limbs, hands, fingers"
141
 
142
- SD3.5:
143
  _defaults:
144
- steps: 20
145
  cfg: 4.0
146
  sampler_name: "euler"
147
- scheduler: "sgm_uniform"
 
 
 
 
 
148
 
149
- SDXL:
150
  _defaults:
151
- steps: 25
152
- cfg: 7.0
153
  sampler_name: "euler"
154
  scheduler: "simple"
155
  positive_prompt: ""
156
  negative_prompt: ""
157
 
158
- SD1.5:
159
- _defaults:
160
- steps: 47
161
- cfg: 7.0
162
- sampler_name: "euler_ancestral"
163
- scheduler: "simple"
164
-
165
- FLUX.1:
166
  _defaults:
167
  steps: 20
168
- cfg: 1.0
169
- sampler_name: "euler"
170
- scheduler: "simple"
171
- "flux1-schnell":
172
- steps: 4
173
- cfg: 1.0
174
- sampler_name: "euler"
175
  scheduler: "simple"
 
 
176
 
177
  HiDream-O1:
178
  _defaults:
@@ -204,12 +231,37 @@ HiDream-I1:
204
  sampler_name: "lcm"
205
  scheduler: "normal"
206
 
207
- HunyuanImage:
208
  _defaults:
209
  steps: 20
210
- cfg: 3.5
211
  sampler_name: "euler"
212
  scheduler: "simple"
213
- "HunyuanImage-2.1-Distilled":
214
- steps: 8
215
- cfg: 1.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  Default:
2
+ steps: 8
3
+ cfg: 1.0
4
  sampler_name: "euler"
5
  scheduler: "simple"
6
  positive_prompt: ""
7
  negative_prompt: ""
8
 
9
+ Krea-2:
10
+ _defaults:
11
+ steps: 52
12
+ cfg: 3.5
13
+ sampler_name: "euler"
14
+ scheduler: "simple"
15
+ "Krea-2-Turbo":
16
+ steps: 8
17
+ cfg: 1.0
18
+ sampler_name: "euler"
19
+ scheduler: "simple"
20
+
21
+ Boogu-Image:
22
+ _defaults:
23
+ steps: 25
24
+ cfg: 3.5
25
+ sampler_name: "dpmpp_2m"
26
+ scheduler: "simple"
27
+ "Boogu-Image-Turbo":
28
+ steps: 4
29
+ cfg: 1.0
30
+ sampler_name: "lcm"
31
+ scheduler: "sgm_uniform"
32
+
33
  PixelDiT:
34
  _defaults:
35
  steps: 30
36
  cfg: 4.0
37
  sampler_name: "er_sde"
38
  scheduler: "simple"
39
+ negative_prompt: "low quality, worst quality, over-saturated, blurry, deformed, watermark"
40
+
41
+ Ideogram-4:
42
+ _defaults:
43
+ steps: 20
44
+ cfg: 7.0
45
+ sampler_name: "res_multistep"
46
+ scheduler: "simple"
47
+ positive_prompt: "NOTE: If you see \"Image blocked by safety filter\" it is because of safety training in the model itself, ImageGen does not have any safety filter."
48
 
49
  Lens:
50
  _defaults:
 
56
  steps: 4
57
  cfg: 1.0
58
 
59
+ FLUX.2-KV:
60
  _defaults:
61
+ steps: 4
 
 
 
 
 
62
  cfg: 1.0
63
  sampler_name: "euler"
64
  scheduler: "simple"
 
76
  steps: 4
77
  cfg: 1.0
78
 
79
+ ERNIE-Image:
80
  _defaults:
81
  steps: 20
82
  cfg: 4.0
83
  sampler_name: "euler"
84
  scheduler: "simple"
85
+ "baidu/ERNIE-Image-Turbo":
86
+ steps: 8
87
  cfg: 1.0
88
 
89
  Z-Image:
 
95
  "Tongyi-MAI/Z Image Turbo":
96
  steps: 9
97
  cfg: 1.0
 
 
98
 
99
  Qwen-Image:
100
  _defaults:
101
+ steps: 20
102
+ cfg: 4.0
103
  sampler_name: "euler"
104
  scheduler: "simple"
105
 
 
111
  sampler_name: "euler"
112
  scheduler: "simple"
113
 
114
+ Cosmos-Predict2:
115
+ _defaults:
116
+ steps: 35
117
+ cfg: 4.0
118
+ sampler_name: "euler"
119
+ scheduler: "karras"
120
+
121
  Anima:
122
  _defaults:
123
  steps: 30
 
126
  scheduler: "simple"
127
  positive_prompt: "masterpiece, best quality, score_7, safe. "
128
  negative_prompt: "worst quality, low quality, score_1, score_2, score_3, blurry, jpeg artifacts, sepia"
129
+ "circlestone-labs/Anima-Turbo-v1.0":
130
+ steps: 10
131
+ cfg: 1.0
132
 
133
  NewBie-Image:
134
  _defaults:
 
139
  positive_prompt: "You are an assistant designed to generate high-quality anime images with the highest degree of image-text alignment based on xml format textual prompts. <Prompt Start>"
140
  negative_prompt: "You are an assistant designed to generate low-quality images based on textual prompts. <Prompt Start>"
141
 
142
+ Kandinsky-5:
143
  _defaults:
144
+ steps: 50
145
+ cfg: 3.5
146
  sampler_name: "euler"
147
  scheduler: "simple"
148
 
149
+ Ovis-Image:
150
  _defaults:
151
  steps: 20
152
  cfg: 5.0
153
  sampler_name: "euler"
154
  scheduler: "simple"
 
 
155
 
156
+ HunyuanImage:
157
  _defaults:
158
+ steps: 20
159
+ cfg: 3.5
160
  sampler_name: "euler"
161
  scheduler: "simple"
162
+ "HunyuanImage-2.1-Distilled":
 
163
  steps: 8
164
  cfg: 1.0
 
165
 
166
  Chroma1-Radiance:
167
  _defaults:
 
171
  scheduler: "simple"
172
  negative_prompt: "low quality, bad anatomy, extra digits, missing digits, extra limbs, missing limbs, hands, fingers"
173
 
174
+ Chroma1:
175
  _defaults:
176
+ steps: 30
177
  cfg: 4.0
178
  sampler_name: "euler"
179
+ scheduler: "simple"
180
+ negative_prompt: "low quality, bad anatomy, extra digits, missing digits, extra limbs, missing limbs"
181
+ "lodestones/Chroma1-HD-Flash":
182
+ steps: 8
183
+ cfg: 1.0
184
+ scheduler: "beta"
185
 
186
+ OmniGen2:
187
  _defaults:
188
+ steps: 20
189
+ cfg: 5.0
190
  sampler_name: "euler"
191
  scheduler: "simple"
192
  positive_prompt: ""
193
  negative_prompt: ""
194
 
195
+ Lumina:
 
 
 
 
 
 
 
196
  _defaults:
197
  steps: 20
198
+ cfg: 4.0
199
+ sampler_name: "res_multistep"
 
 
 
 
 
200
  scheduler: "simple"
201
+ positive_prompt: ""
202
+ negative_prompt: ""
203
 
204
  HiDream-O1:
205
  _defaults:
 
231
  sampler_name: "lcm"
232
  scheduler: "normal"
233
 
234
+ FLUX.1:
235
  _defaults:
236
  steps: 20
237
+ cfg: 1.0
238
  sampler_name: "euler"
239
  scheduler: "simple"
240
+ "flux1-schnell":
241
+ steps: 4
242
+ cfg: 1.0
243
+ sampler_name: "euler"
244
+ scheduler: "simple"
245
+
246
+ SD3.5:
247
+ _defaults:
248
+ steps: 20
249
+ cfg: 4.0
250
+ sampler_name: "euler"
251
+ scheduler: "sgm_uniform"
252
+
253
+ SDXL:
254
+ _defaults:
255
+ steps: 25
256
+ cfg: 7.0
257
+ sampler_name: "euler"
258
+ scheduler: "simple"
259
+ positive_prompt: ""
260
+ negative_prompt: ""
261
+
262
+ SD1.5:
263
+ _defaults:
264
+ steps: 47
265
+ cfg: 7.0
266
+ sampler_name: "euler_ancestral"
267
+ scheduler: "simple"
yaml/model_list.yaml CHANGED
@@ -1,4 +1,30 @@
1
  Checkpoint:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  PixelDiT:
3
  latent_type: chroma_radiance_latent
4
  models:
@@ -7,6 +33,15 @@ Checkpoint:
7
  unet: "pixeldit_1300m_1024px_mxfp8.safetensors"
8
  clip: "gemma_2_2b_it_elm_fp8_scaled.safetensors"
9
  vae: "pixel_space"
 
 
 
 
 
 
 
 
 
10
  Lens:
11
  latent_type: flux2_latent
12
  models:
@@ -85,18 +120,16 @@ Checkpoint:
85
  Qwen-Image:
86
  latent_type: sd3_latent
87
  models:
88
- - display_name: "Qwen/Qwen-Image-2512 + Lightning-4steps-V1.0 LoRA"
89
  components:
90
  unet: "qwen_image_2512_fp8_e4m3fn.safetensors"
91
  vae: "qwen_image_vae.safetensors"
92
- clip: "qwen_2.5_vl_7b_fp8_scaled.safetensors"
93
- lora: "Qwen-Image-2512-Lightning-4steps-V1.0-bf16.safetensors"
94
- - display_name: "Qwen/Qwen-Image + Lightning-4steps-V1.0 LoRA"
95
  components:
96
- unet: "qwen_image_fp8_e4m3fn.safetensors"
97
  vae: "qwen_image_vae.safetensors"
98
- clip: "qwen_2.5_vl_7b_fp8_scaled.safetensors"
99
- lora: "Qwen-Image-fp8-e4m3fn-Lightning-4steps-V1.0-bf16.safetensors"
100
  LongCat-Image:
101
  latent_type: sd3_latent
102
  models:
@@ -104,28 +137,61 @@ Checkpoint:
104
  components:
105
  unet: "longcat_image_bf16.safetensors"
106
  vae: "ae.safetensors"
107
- clip: "qwen_2.5_vl_7b_fp8_scaled.safetensors"
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  Anima:
109
  latent_type: latent
110
  models:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  - display_name: "WAI0731/waiANIMA-v1.0"
112
  components:
113
- unet: "waiANIMA_v10.safetensors"
114
  vae: "qwen_image_vae.safetensors"
115
  clip: "qwen_3_06b_base.safetensors"
116
- - display_name: "duongve/AnimaYume-v0.5"
117
  components:
118
- unet: "AnimaYume_tuned_v05.safetensors"
119
  vae: "qwen_image_vae.safetensors"
120
  clip: "qwen_3_06b_base.safetensors"
121
- - display_name: "bluepen5805/Anima-pencil-v1.0"
122
  components:
123
- unet: "anima_pencil-v1.0.0.safetensors"
124
  vae: "qwen_image_vae.safetensors"
125
  clip: "qwen_3_06b_base.safetensors"
126
- - display_name: "circlestone-labs/Anima-base-v1.0"
127
  components:
128
- unet: "anima-base-v1.0.safetensors"
 
 
 
 
 
129
  vae: "qwen_image_vae.safetensors"
130
  clip: "qwen_3_06b_base.safetensors"
131
  NewBie-Image:
@@ -137,6 +203,15 @@ Checkpoint:
137
  vae: "ae.safetensors"
138
  clip1: "gemma_3_4b_it_bf16.safetensors"
139
  clip2: "jina_clip_v2_bf16.safetensors"
 
 
 
 
 
 
 
 
 
140
  Ovis-Image:
141
  latent_type: sd3_latent
142
  models:
@@ -152,13 +227,13 @@ Checkpoint:
152
  components:
153
  unet: "hunyuanimage2.1_fp8_e4m3fn.safetensors"
154
  vae: "hunyuan_image_2.1_vae_fp16.safetensors"
155
- clip1: "qwen_2.5_vl_7b_fp8_scaled.safetensors"
156
  clip2: "byt5_small_glyphxl_fp16.safetensors"
157
  - display_name: "HunyuanImage-2.1-Distilled"
158
  components:
159
  unet: "hunyuanimage2.1_distilled_fp8_e4m3fn.safetensors"
160
  vae: "hunyuan_image_2.1_vae_fp16.safetensors"
161
- clip1: "qwen_2.5_vl_7b_fp8_scaled.safetensors"
162
  clip2: "byt5_small_glyphxl_fp16.safetensors"
163
  Chroma1-Radiance:
164
  latent_type: chroma_radiance_latent
@@ -233,7 +308,7 @@ Checkpoint:
233
  models:
234
  - display_name: "flux1-dev"
235
  components:
236
- unet: "flux1-dev-fp8-e4m3fn.safetensors"
237
  vae: "ae.safetensors"
238
  clip1: "clip_l.safetensors"
239
  clip2: "t5xxl_fp8_e4m3fn_scaled.safetensors"
 
1
  Checkpoint:
2
+ Krea-2:
3
+ latent_type: latent
4
+ models:
5
+ - display_name: "Krea-2-Turbo"
6
+ components:
7
+ unet: "krea2_turbo_nvfp4.safetensors"
8
+ clip: "qwen3vl_4b_fp8_scaled.safetensors"
9
+ vae: "qwen_image_vae.safetensors"
10
+ - display_name: "Krea-2-Raw"
11
+ components:
12
+ unet: "krea2_raw_fp8_scaled.safetensors"
13
+ clip: "qwen3vl_4b_fp8_scaled.safetensors"
14
+ vae: "qwen_image_vae.safetensors"
15
+ Boogu-Image:
16
+ latent_type: latent
17
+ models:
18
+ - display_name: "Boogu-Image-Turbo"
19
+ components:
20
+ unet: "boogu_image_turbo_hotfix_nvfp4.safetensors"
21
+ clip: "qwen3vl_8b_nvfp4.safetensors"
22
+ vae: "ae.safetensors"
23
+ - display_name: "Boogu-Image-Base"
24
+ components:
25
+ unet: "boogu_image_base_nvfp4.safetensors"
26
+ clip: "qwen3vl_8b_nvfp4.safetensors"
27
+ vae: "ae.safetensors"
28
  PixelDiT:
29
  latent_type: chroma_radiance_latent
30
  models:
 
33
  unet: "pixeldit_1300m_1024px_mxfp8.safetensors"
34
  clip: "gemma_2_2b_it_elm_fp8_scaled.safetensors"
35
  vae: "pixel_space"
36
+ Ideogram-4:
37
+ latent_type: flux2_latent
38
+ models:
39
+ - display_name: "ideogram-ai/ideogram-4"
40
+ components:
41
+ unet: "ideogram4_nvfp4_mixed.safetensors"
42
+ unet_uncond: "ideogram4_unconditional_nvfp4_mixed.safetensors"
43
+ clip: "qwen3vl_8b_nvfp4.safetensors"
44
+ vae: "flux2-vae.safetensors"
45
  Lens:
46
  latent_type: flux2_latent
47
  models:
 
120
  Qwen-Image:
121
  latent_type: sd3_latent
122
  models:
123
+ - display_name: "Qwen-Image-2512"
124
  components:
125
  unet: "qwen_image_2512_fp8_e4m3fn.safetensors"
126
  vae: "qwen_image_vae.safetensors"
127
+ clip: "qwen_2.5_vl_7b_nvfp4.safetensors"
128
+ - display_name: "Qwen-Image"
 
129
  components:
130
+ unet: "qwen_image_nvfp4.safetensors"
131
  vae: "qwen_image_vae.safetensors"
132
+ clip: "qwen_2.5_vl_7b_nvfp4.safetensors"
 
133
  LongCat-Image:
134
  latent_type: sd3_latent
135
  models:
 
137
  components:
138
  unet: "longcat_image_bf16.safetensors"
139
  vae: "ae.safetensors"
140
+ clip: "qwen_2.5_vl_7b_nvfp4.safetensors"
141
+ Cosmos-Predict2:
142
+ latent_type: sd3_latent
143
+ models:
144
+ - display_name: "Cosmos-Predict2-2B-T2I"
145
+ components:
146
+ unet: "cosmos_predict2_2B_t2i.pt"
147
+ clip: "oldt5_xxl_fp8_e4m3fn_scaled.safetensors"
148
+ vae: "wan_2.1_vae.safetensors"
149
+ - display_name: "Cosmos-Predict2-14B-T2I"
150
+ components:
151
+ unet: "cosmos_predict2_14B_t2i.pt"
152
+ clip: "oldt5_xxl_fp8_e4m3fn_scaled.safetensors"
153
+ vae: "wan_2.1_vae.safetensors"
154
  Anima:
155
  latent_type: latent
156
  models:
157
+ - display_name: "circlestone-labs/Anima-Turbo-v1.0"
158
+ components:
159
+ unet: "anima-turbo-v1.0.safetensors"
160
+ vae: "qwen_image_vae.safetensors"
161
+ clip: "qwen_3_06b_base.safetensors"
162
+ - display_name: "circlestone-labs/Anima-Aesthetic-v1.1"
163
+ components:
164
+ unet: "anima-aesthetic-v1.1.safetensors"
165
+ vae: "qwen_image_vae.safetensors"
166
+ clip: "qwen_3_06b_base.safetensors"
167
+ - display_name: "circlestone-labs/Anima-Base-v1.0"
168
+ components:
169
+ unet: "anima-base-v1.0.safetensors"
170
+ vae: "qwen_image_vae.safetensors"
171
+ clip: "qwen_3_06b_base.safetensors"
172
  - display_name: "WAI0731/waiANIMA-v1.0"
173
  components:
174
+ unet: "waiANIMA_v10Base10.safetensors"
175
  vae: "qwen_image_vae.safetensors"
176
  clip: "qwen_3_06b_base.safetensors"
177
+ - display_name: "duongve/AnimaYume-v1.0"
178
  components:
179
+ unet: "AnimaYume_v10_final_base.safetensors"
180
  vae: "qwen_image_vae.safetensors"
181
  clip: "qwen_3_06b_base.safetensors"
182
+ - display_name: "bluepen5805/Anima-pencil-v2.1"
183
  components:
184
+ unet: "anima_pencil-v2.1.0.safetensors"
185
  vae: "qwen_image_vae.safetensors"
186
  clip: "qwen_3_06b_base.safetensors"
187
+ - display_name: "Ikena/Hassaku-Anima-v1-Style"
188
  components:
189
+ unet: "hassakuAnima_v1Style.safetensors"
190
+ vae: "qwen_image_vae.safetensors"
191
+ clip: "qwen_3_06b_base.safetensors"
192
+ - display_name: "motimalu/Kirazuri (Anima)-v3.0"
193
+ components:
194
+ unet: "hassakuAnima_v1Style.safetensors"
195
  vae: "qwen_image_vae.safetensors"
196
  clip: "qwen_3_06b_base.safetensors"
197
  NewBie-Image:
 
203
  vae: "ae.safetensors"
204
  clip1: "gemma_3_4b_it_bf16.safetensors"
205
  clip2: "jina_clip_v2_bf16.safetensors"
206
+ Kandinsky-5:
207
+ latent_type: latent
208
+ models:
209
+ - display_name: "Kandinsky-5.0-T2I-Lite"
210
+ components:
211
+ unet: "kandinsky5lite_t2i.safetensors"
212
+ vae: "ae.safetensors"
213
+ clip1: "qwen_2.5_vl_7b_nvfp4.safetensors"
214
+ clip2: "clip_l.safetensors"
215
  Ovis-Image:
216
  latent_type: sd3_latent
217
  models:
 
227
  components:
228
  unet: "hunyuanimage2.1_fp8_e4m3fn.safetensors"
229
  vae: "hunyuan_image_2.1_vae_fp16.safetensors"
230
+ clip1: "qwen_2.5_vl_7b_nvfp4.safetensors"
231
  clip2: "byt5_small_glyphxl_fp16.safetensors"
232
  - display_name: "HunyuanImage-2.1-Distilled"
233
  components:
234
  unet: "hunyuanimage2.1_distilled_fp8_e4m3fn.safetensors"
235
  vae: "hunyuan_image_2.1_vae_fp16.safetensors"
236
+ clip1: "qwen_2.5_vl_7b_nvfp4.safetensors"
237
  clip2: "byt5_small_glyphxl_fp16.safetensors"
238
  Chroma1-Radiance:
239
  latent_type: chroma_radiance_latent
 
308
  models:
309
  - display_name: "flux1-dev"
310
  components:
311
+ unet: "flux1-dev-nvfp4.safetensors"
312
  vae: "ae.safetensors"
313
  clip1: "clip_l.safetensors"
314
  clip2: "t5xxl_fp8_e4m3fn_scaled.safetensors"