RioShiina commited on
Commit
d018eec
·
verified ·
1 Parent(s): 7ab56d8

Add JoyAI-Image architecture model.

Browse files
README.md CHANGED
@@ -85,6 +85,8 @@ models:
85
  - InstantX/Qwen-Image-ControlNet-Inpainting
86
  - InstantX/Qwen-Image-ControlNet-Union
87
  - InstantX/SD3.5-Large-IP-Adapter
 
 
88
  - kandinskylab/Kandinsky-5.0-T2I-Lite
89
  - Kijai/flux-fp8
90
  - Laxhar/noob_openpose
 
85
  - InstantX/Qwen-Image-ControlNet-Inpainting
86
  - InstantX/Qwen-Image-ControlNet-Union
87
  - InstantX/SD3.5-Large-IP-Adapter
88
+ - jdopensource/JoyAI-Image-Edit-ComfyUI
89
+ - jdopensource/JoyAI-Image-Edit-Plus-ComfyUI
90
  - kandinskylab/Kandinsky-5.0-T2I-Lite
91
  - Kijai/flux-fp8
92
  - Laxhar/noob_openpose
chain_injectors/joyai_reference_injector.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ def inject(assembler, chain_definition, chain_items):
4
+ if not chain_items:
5
+ return
6
+
7
+ valid_images = []
8
+ for item in chain_items:
9
+ if not item:
10
+ continue
11
+ img_path = item
12
+ if isinstance(item, dict):
13
+ img_path = item.get('image') or item.get('filename') or item.get('path')
14
+ if img_path:
15
+ valid_images.append(img_path)
16
+
17
+ if not valid_images:
18
+ return
19
+
20
+ valid_images = valid_images[:2]
21
+
22
+ pos_prompt_name = chain_definition.get('pos_prompt_node', 'pos_prompt')
23
+ neg_prompt_name = chain_definition.get('neg_prompt_node', 'neg_prompt')
24
+ vae_node_name = chain_definition.get('vae_node', 'vae_loader')
25
+
26
+ if pos_prompt_name not in assembler.node_map:
27
+ print(f"Warning: Positive prompt node '{pos_prompt_name}' not found for JoyAI Reference chain. Skipping.")
28
+ return
29
+
30
+ if vae_node_name not in assembler.node_map:
31
+ print(f"Warning: VAE loader node '{vae_node_name}' not found for JoyAI Reference chain. Skipping.")
32
+ return
33
+
34
+ pos_prompt_id = assembler.node_map[pos_prompt_name]
35
+ neg_prompt_id = assembler.node_map.get(neg_prompt_name)
36
+ vae_node_id = assembler.node_map[vae_node_name]
37
+
38
+ assembler.workflow[pos_prompt_id]['inputs']['vae'] = [vae_node_id, 0]
39
+ if neg_prompt_id and neg_prompt_id in assembler.workflow:
40
+ assembler.workflow[neg_prompt_id]['inputs']['vae'] = [vae_node_id, 0]
41
+
42
+ for i, img_filename in enumerate(valid_images):
43
+ load_id = assembler._get_unique_id()
44
+ load_node = assembler._get_node_template("LoadImage")
45
+ load_node['inputs']['image'] = img_filename
46
+ load_node['_meta']['title'] = f"Load Reference Image {i+1}"
47
+ assembler.workflow[load_id] = load_node
48
+
49
+ scale_id = assembler._get_unique_id()
50
+ scale_node = assembler._get_node_template("ImageScaleToTotalPixels")
51
+ scale_node['inputs']['megapixels'] = 1.0
52
+ scale_node['inputs']['upscale_method'] = "nearest-exact"
53
+ scale_node['inputs']['resolution_steps'] = 1
54
+ scale_node['inputs']['image'] = [load_id, 0]
55
+ scale_node['_meta']['title'] = f"Scale Reference {i+1}"
56
+ assembler.workflow[scale_id] = scale_node
57
+
58
+ input_key = f"images.image{i}"
59
+ assembler.workflow[pos_prompt_id]['inputs'][input_key] = [scale_id, 0]
60
+ if neg_prompt_id and neg_prompt_id in assembler.workflow:
61
+ assembler.workflow[neg_prompt_id]['inputs'][input_key] = [scale_id, 0]
62
+
63
+ print(f"JoyAI Reference injector applied. Injected {len(valid_images)} reference images to JoyAI text encoding nodes.")
core/pipelines/pipeline_input_processor.py CHANGED
@@ -340,6 +340,17 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
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
@@ -378,6 +389,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
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
  }
 
340
  temp_files_to_clean.append(temp_path)
341
  active_hidream_o1_reference.append(os.path.basename(temp_path))
342
 
343
+ joyai_reference_data = ui_inputs.get('joyai_reference_data', [])
344
+ active_joyai_reference = []
345
+ if joyai_reference_data:
346
+ for img in joyai_reference_data:
347
+ if img:
348
+ if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
349
+ temp_path = os.path.join(INPUT_DIR, f"temp_joyai_ref_{random.randint(1000, 9999)}.png")
350
+ img.save(temp_path, "PNG")
351
+ temp_files_to_clean.append(temp_path)
352
+ active_joyai_reference.append(os.path.basename(temp_path))
353
+
354
  vae_source = ui_inputs.get('vae_source')
355
  vae_id = ui_inputs.get('vae_id')
356
  vae_name_override = None
 
389
  "active_styles": active_styles,
390
  "active_reference_latents": active_reference_latents,
391
  "active_hidream_o1_reference": active_hidream_o1_reference,
392
+ "active_joyai_reference": active_joyai_reference,
393
  "active_conditioning": active_conditioning,
394
  "temp_files_to_clean": temp_files_to_clean
395
  }
core/pipelines/sd_image_pipeline.py CHANGED
@@ -116,6 +116,7 @@ class SdImagePipeline(BasePipeline):
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 ""
@@ -172,6 +173,7 @@ class SdImagePipeline(BasePipeline):
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 [],
 
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_joyai_reference = processed.get("active_joyai_reference", [])
120
  active_conditioning = processed["active_conditioning"]
121
 
122
  loras_string = f"LoRAs: [{', '.join(active_loras_for_meta)}]" if active_loras_for_meta else ""
 
173
  "conditioning_chain": active_conditioning,
174
  "reference_latent_chain": active_reference_latents,
175
  "hidream_o1_reference_chain": active_hidream_o1_reference,
176
+ "joyai_reference_chain": active_joyai_reference,
177
  "vae_chain": [ui_inputs.get('vae_name')] if ui_inputs.get('vae_name') else [],
178
  "hidream_o1_smoothing_chain": hidream_o1_smoothing_data,
179
  "pid_chain": [ui_inputs.get('pid_settings', 'OFF')] if is_pid_enabled else [],
core/pipelines/workflow_recipes/_partials/conditioning/joyai-image.yaml ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ nodes:
2
+ unet_loader:
3
+ class_type: UNETLoader
4
+ title: "Load Diffusion Model"
5
+ params:
6
+ weight_dtype: "default"
7
+ vae_loader:
8
+ class_type: VAELoader
9
+ title: "Load VAE"
10
+ clip_loader:
11
+ class_type: CLIPLoader
12
+ title: "Load CLIP"
13
+ params:
14
+ type: "joyimage"
15
+ device: "default"
16
+
17
+ pos_prompt:
18
+ class_type: TextEncodeJoyImageEdit
19
+ title: "TextEncodeJoyImageEdit (Positive)"
20
+ neg_prompt:
21
+ class_type: TextEncodeJoyImageEdit
22
+ title: "TextEncodeJoyImageEdit (Negative)"
23
+
24
+ cfg_norm:
25
+ class_type: CFGNorm
26
+ title: "CFGNorm"
27
+ params:
28
+ strength: 1.0
29
+ pre_cfg: true
30
+
31
+ connections:
32
+ - from: "unet_loader:0"
33
+ to: "cfg_norm:model"
34
+ - from: "cfg_norm:0"
35
+ to: "ksampler:model"
36
+
37
+ - from: "clip_loader:0"
38
+ to: "pos_prompt:clip"
39
+ - from: "clip_loader:0"
40
+ to: "neg_prompt:clip"
41
+
42
+ - from: "pos_prompt:0"
43
+ to: "ksampler:positive"
44
+ - from: "neg_prompt:0"
45
+ to: "ksampler:negative"
46
+
47
+ - from: "vae_loader:0"
48
+ to: "vae_decode:vae"
49
+ - from: "vae_loader:0"
50
+ to: "vae_encode:vae"
51
+
52
+ dynamic_lora_chains:
53
+ lora_chain:
54
+ template: "LoraLoader"
55
+ output_map:
56
+ "unet_loader:0": "model"
57
+ "clip_loader:0": "clip"
58
+ input_map:
59
+ "model": "model"
60
+ "clip": "clip"
61
+ end_input_map:
62
+ "model": ["cfg_norm:model"]
63
+ "clip": ["pos_prompt:clip", "neg_prompt:clip"]
64
+
65
+ dynamic_conditioning_chains:
66
+ conditioning_chain:
67
+ ksampler_node: "ksampler"
68
+ clip_source: "clip_loader:0"
69
+
70
+ dynamic_pid_chains:
71
+ pid_chain:
72
+ ksampler_node: "ksampler"
73
+
74
+ dynamic_joyai_reference_chains:
75
+ joyai_reference_chain:
76
+ pos_prompt_node: "pos_prompt"
77
+ neg_prompt_node: "neg_prompt"
78
+ vae_node: "vae_loader"
79
+
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
+ positive_prompt: "pos_prompt:prompt"
85
+ negative_prompt: "neg_prompt:prompt"
86
+
requirements.txt CHANGED
@@ -1,5 +1,5 @@
1
  comfyui-frontend-package==1.47.10
2
- comfyui-workflow-templates==0.11.15
3
  comfyui-embedded-docs==0.5.8
4
  torch
5
  torchsde
 
1
  comfyui-frontend-package==1.47.10
2
+ comfyui-workflow-templates==0.11.17
3
  comfyui-embedded-docs==0.5.8
4
  torch
5
  torchsde
ui/events/chain_handlers.py CHANGED
@@ -715,6 +715,39 @@ def create_hidream_o1_reference_event_handlers(prefix, ui_components):
715
  del_button.click(fn=del_ref_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
716
 
717
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
718
  def create_embedding_event_handlers(prefix, ui_components):
719
  rows = ui_components.get(f'embedding_rows_{prefix}')
720
  if not rows: return
 
715
  del_button.click(fn=del_ref_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
716
 
717
 
718
+ def create_joyai_reference_event_handlers(prefix, ui_components):
719
+ ref_rows = ui_components.get(f'joyai_reference_rows_{prefix}')
720
+ if not ref_rows: return
721
+ count_state = ui_components[f'joyai_reference_count_state_{prefix}']
722
+ add_button = ui_components[f'add_joyai_reference_button_{prefix}']
723
+ del_button = ui_components[f'delete_joyai_reference_button_{prefix}']
724
+ images = ui_components[f'joyai_reference_images_{prefix}']
725
+
726
+ def add_ref_row(c):
727
+ c += 1
728
+ return {
729
+ count_state: c,
730
+ ref_rows[c - 1]: gr.update(visible=True),
731
+ add_button: gr.update(visible=c < 2),
732
+ del_button: gr.update(visible=True),
733
+ }
734
+
735
+ def del_ref_row(c):
736
+ c -= 1
737
+ return {
738
+ count_state: c,
739
+ ref_rows[c]: gr.update(visible=False),
740
+ images[c]: None,
741
+ add_button: gr.update(visible=True),
742
+ del_button: gr.update(visible=c > 0),
743
+ }
744
+
745
+ add_outputs = [count_state, add_button, del_button] + ref_rows
746
+ del_outputs = [count_state, add_button, del_button] + ref_rows + images
747
+ add_button.click(fn=add_ref_row, inputs=[count_state], outputs=add_outputs, show_progress=False)
748
+ del_button.click(fn=del_ref_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
749
+
750
+
751
  def create_embedding_event_handlers(prefix, ui_components):
752
  rows = ui_components.get(f'embedding_rows_{prefix}')
753
  if not rows: return
ui/events/change_handlers.py CHANGED
@@ -17,7 +17,7 @@ from .config_loaders import (
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]
@@ -68,6 +68,7 @@ def make_update_fn(m_comp, cat_comp, cs_comp, ar_comp, width_comp, height_comp,
68
  if cond_acc: updates[cond_acc] = gr.update(visible=('conditioning' 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
 
@@ -142,7 +143,7 @@ def make_update_fn(m_comp, cat_comp, cs_comp, ar_comp, width_comp, height_comp,
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
@@ -198,8 +199,10 @@ def make_model_change_fn(cat_comp_ref, cs_comp, ar_comp, width_comp, height_comp
198
  if cond_acc: updates[cond_acc] = gr.update(visible=('conditioning' 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"))
 
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, joyai_ref_acc=None):
21
  def update_fn(*args):
22
  arch = args[0]
23
  category = args[1]
 
68
  if cond_acc: updates[cond_acc] = gr.update(visible=('conditioning' 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 joyai_ref_acc: updates[joyai_ref_acc] = gr.update(visible=('joyai_reference' in enabled_chains))
72
  if pid_acc: updates[pid_acc] = gr.update(visible=('pid' in enabled_chains))
73
  if vae_acc: updates[vae_acc] = gr.update(visible=('vae' in enabled_chains))
74
 
 
143
  return update_fn
144
 
145
 
146
+ 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, joyai_ref_acc=None):
147
  def change_fn(*args):
148
  model_name = args[0]
149
  idx = 1
 
199
  if cond_acc: updates[cond_acc] = gr.update(visible=('conditioning' in enabled_chains))
200
  if ref_latent_acc: updates[ref_latent_acc] = gr.update(visible=('reference_latent' in enabled_chains))
201
  if hidream_o1_ref_acc: updates[hidream_o1_ref_acc] = gr.update(visible=('hidream_o1_reference' in enabled_chains))
202
+ if joyai_ref_acc: updates[joyai_ref_acc] = gr.update(visible=('joyai_reference' in enabled_chains))
203
  if pid_acc: updates[pid_acc] = gr.update(visible=('pid' in enabled_chains))
204
  if vae_acc: updates[vae_acc] = gr.update(visible=('vae' in enabled_chains))
205
+ if vae_acc: updates[vae_acc] = gr.update(visible=('vae' in enabled_chains))
206
 
207
  if cs_comp:
208
  updates[cs_comp] = gr.update(visible=(arch_model_type == "sd15"))
ui/events/main.py CHANGED
@@ -12,7 +12,8 @@ from .chain_handlers import (
12
  create_sd3_ipadapter_event_handlers,
13
  create_style_event_handlers,
14
  create_reference_latent_event_handlers,
15
- create_hidream_o1_reference_event_handlers
 
16
  )
17
  from .change_handlers import (
18
  make_update_fn,
@@ -66,6 +67,7 @@ def attach_event_handlers(ui_components, demo):
66
  conditioning_accordion = ui_components.get(f'conditioning_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
 
@@ -103,6 +105,7 @@ def attach_event_handlers(ui_components, demo):
103
  if conditioning_accordion: outputs.append(conditioning_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)
@@ -117,7 +120,7 @@ def attach_event_handlers(ui_components, demo):
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:
@@ -149,6 +152,7 @@ def attach_event_handlers(ui_components, demo):
149
  if conditioning_accordion: outputs2.append(conditioning_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)
@@ -168,7 +172,7 @@ def attach_event_handlers(ui_components, demo):
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
 
@@ -185,6 +189,7 @@ def attach_event_handlers(ui_components, demo):
185
  create_style_event_handlers(prefix, ui_components)
186
  create_reference_latent_event_handlers(prefix, ui_components)
187
  create_hidream_o1_reference_event_handlers(prefix, ui_components)
 
188
  create_run_event(prefix, task_type, ui_components)
189
 
190
  if 'view_mode_inpaint' in ui_components:
 
12
  create_sd3_ipadapter_event_handlers,
13
  create_style_event_handlers,
14
  create_reference_latent_event_handlers,
15
+ create_hidream_o1_reference_event_handlers,
16
+ create_joyai_reference_event_handlers
17
  )
18
  from .change_handlers import (
19
  make_update_fn,
 
67
  conditioning_accordion = ui_components.get(f'conditioning_accordion_{prefix}')
68
  ref_latent_accordion = ui_components.get(f'reference_latent_accordion_{prefix}')
69
  hidream_o1_ref_accordion = ui_components.get(f'hidream_o1_reference_accordion_{prefix}')
70
+ joyai_ref_accordion = ui_components.get(f'joyai_reference_accordion_{prefix}')
71
  pid_accordion = ui_components.get(f'pid_accordion_{prefix}')
72
  vae_accordion = ui_components.get(f'vae_accordion_{prefix}')
73
 
 
105
  if conditioning_accordion: outputs.append(conditioning_accordion)
106
  if ref_latent_accordion: outputs.append(ref_latent_accordion)
107
  if hidream_o1_ref_accordion: outputs.append(hidream_o1_ref_accordion)
108
+ if joyai_ref_accordion: outputs.append(joyai_ref_accordion)
109
  if pid_accordion: outputs.append(pid_accordion)
110
  if vae_accordion: outputs.append(vae_accordion)
111
  if ipa_preset_list: outputs.append(ipa_preset_list)
 
120
  krea2_cn_types_list, krea2_cn_series_list, krea2_cn_filepaths_list,
121
  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,
122
  ref_latent_accordion, hidream_o1_ref_accordion, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp,
123
+ pid_acc=pid_accordion, vae_acc=vae_accordion, joyai_ref_acc=joyai_ref_accordion
124
  )
125
  inputs = [arch_comp, cat_comp]
126
  if aspect_ratio_comp:
 
152
  if conditioning_accordion: outputs2.append(conditioning_accordion)
153
  if ref_latent_accordion: outputs2.append(ref_latent_accordion)
154
  if hidream_o1_ref_accordion: outputs2.append(hidream_o1_ref_accordion)
155
+ if joyai_ref_accordion: outputs2.append(joyai_ref_accordion)
156
  if pid_accordion: outputs2.append(pid_accordion)
157
  if vae_accordion: outputs2.append(vae_accordion)
158
  if ipa_preset_list: outputs2.append(ipa_preset_list)
 
172
  krea2_cn_types_list, krea2_cn_series_list, krea2_cn_filepaths_list,
173
  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,
174
  ref_latent_accordion, hidream_o1_ref_accordion, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp,
175
+ pid_acc=pid_accordion, vae_acc=vae_accordion, joyai_ref_acc=joyai_ref_accordion
176
  )
177
  model_comp.change(fn=change_fn, inputs=inputs2, outputs=outputs2)
178
 
 
189
  create_style_event_handlers(prefix, ui_components)
190
  create_reference_latent_event_handlers(prefix, ui_components)
191
  create_hidream_o1_reference_event_handlers(prefix, ui_components)
192
+ create_joyai_reference_event_handlers(prefix, ui_components)
193
  create_run_event(prefix, task_type, ui_components)
194
 
195
  if 'view_mode_inpaint' in ui_components:
ui/events/run_handlers.py CHANGED
@@ -52,6 +52,7 @@ def create_run_event(prefix: str, task_type: str, ui_components: dict):
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}')
@@ -62,7 +63,7 @@ def create_run_event(prefix: str, task_type: str, ui_components: dict):
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:
@@ -92,6 +93,7 @@ def create_run_event(prefix: str, task_type: str, ui_components: dict):
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
 
 
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
+ joyai_reference_data_components = ui_components.get(f'all_joyai_reference_components_flat_{prefix}', [])
56
 
57
  run_inputs_map['vae_source'] = ui_components.get(f'vae_source_{prefix}')
58
  run_inputs_map['vae_id'] = ui_components.get(f'vae_id_{prefix}')
 
63
  all_chains = [
64
  lora_data_components, controlnet_data_components, anima_controlnet_lllite_data_components, diffsynth_controlnet_data_components, krea2_controlnet_data_components, ipadapter_data_components,
65
  sd3_ipadapter_data_components, flux1_ipadapter_data_components, style_data_components,
66
+ embedding_data_components, conditioning_data_components, reference_latent_data_components, hidream_o1_reference_data_components, joyai_reference_data_components
67
  ]
68
  for chain in all_chains:
69
  if chain:
 
93
  assign_chain_data('conditioning_data', conditioning_data_components)
94
  assign_chain_data('reference_latent_data', reference_latent_data_components)
95
  assign_chain_data('hidream_o1_reference_data', hidream_o1_reference_data_components)
96
+ assign_chain_data('joyai_reference_data', joyai_reference_data_components)
97
 
98
  return ui_dict
99
 
ui/shared/hires_fix_ui.py CHANGED
@@ -7,7 +7,7 @@ from .ui_components import (
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', {})
@@ -101,6 +101,7 @@ def create_ui():
101
  components.update(create_conditioning_ui(prefix))
102
  components.update(create_reference_latent_ui(prefix))
103
  components.update(create_hidream_o1_reference_ui(prefix))
 
104
  components.update(create_vae_override_ui(prefix))
105
 
106
  return components
 
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, create_joyai_reference_ui
11
  )
12
 
13
  default_vals = MODEL_DEFAULTS_CONFIG.get('Default', {})
 
101
  components.update(create_conditioning_ui(prefix))
102
  components.update(create_reference_latent_ui(prefix))
103
  components.update(create_hidream_o1_reference_ui(prefix))
104
+ components.update(create_joyai_reference_ui(prefix))
105
  components.update(create_vae_override_ui(prefix))
106
 
107
  return components
ui/shared/img2img_ui.py CHANGED
@@ -7,7 +7,7 @@ from .ui_components import (
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', {})
@@ -82,6 +82,7 @@ def create_ui():
82
  components.update(create_conditioning_ui(prefix))
83
  components.update(create_reference_latent_ui(prefix))
84
  components.update(create_hidream_o1_reference_ui(prefix))
 
85
  components.update(create_vae_override_ui(prefix))
86
 
87
  return components
 
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, create_joyai_reference_ui
11
  )
12
 
13
  default_vals = MODEL_DEFAULTS_CONFIG.get('Default', {})
 
82
  components.update(create_conditioning_ui(prefix))
83
  components.update(create_reference_latent_ui(prefix))
84
  components.update(create_hidream_o1_reference_ui(prefix))
85
+ components.update(create_joyai_reference_ui(prefix))
86
  components.update(create_vae_override_ui(prefix))
87
 
88
  return components
ui/shared/inpaint_ui.py CHANGED
@@ -6,7 +6,7 @@ from .ui_components import (
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', {})
@@ -114,6 +114,7 @@ def create_ui():
114
  components.update(create_conditioning_ui(prefix))
115
  components.update(create_reference_latent_ui(prefix))
116
  components.update(create_hidream_o1_reference_ui(prefix))
 
117
  components.update(create_vae_override_ui(prefix))
118
  components[f'accordion_wrapper_{prefix}'] = accordion_wrapper
119
 
 
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, create_joyai_reference_ui
10
  )
11
 
12
  default_vals = MODEL_DEFAULTS_CONFIG.get('Default', {})
 
114
  components.update(create_conditioning_ui(prefix))
115
  components.update(create_reference_latent_ui(prefix))
116
  components.update(create_hidream_o1_reference_ui(prefix))
117
+ components.update(create_joyai_reference_ui(prefix))
118
  components.update(create_vae_override_ui(prefix))
119
  components[f'accordion_wrapper_{prefix}'] = accordion_wrapper
120
 
ui/shared/outpaint_ui.py CHANGED
@@ -7,7 +7,7 @@ from .ui_components import (
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', {})
@@ -97,6 +97,7 @@ def create_ui():
97
  components.update(create_conditioning_ui(prefix))
98
  components.update(create_reference_latent_ui(prefix))
99
  components.update(create_hidream_o1_reference_ui(prefix))
 
100
  components.update(create_vae_override_ui(prefix))
101
 
102
  return components
 
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, create_joyai_reference_ui
11
  )
12
 
13
  default_vals = MODEL_DEFAULTS_CONFIG.get('Default', {})
 
97
  components.update(create_conditioning_ui(prefix))
98
  components.update(create_reference_latent_ui(prefix))
99
  components.update(create_hidream_o1_reference_ui(prefix))
100
+ components.update(create_joyai_reference_ui(prefix))
101
  components.update(create_vae_override_ui(prefix))
102
 
103
  return components
ui/shared/txt2img_ui.py CHANGED
@@ -6,7 +6,7 @@ from .ui_components import (
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
  create_pid_ui
11
  )
12
 
@@ -54,6 +54,7 @@ def create_ui():
54
  components.update(create_conditioning_ui(prefix))
55
  components.update(create_reference_latent_ui(prefix))
56
  components.update(create_hidream_o1_reference_ui(prefix))
 
57
  components.update(create_vae_override_ui(prefix))
58
  components.update(create_pid_ui(prefix))
59
 
 
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, create_joyai_reference_ui,
10
  create_pid_ui
11
  )
12
 
 
54
  components.update(create_conditioning_ui(prefix))
55
  components.update(create_reference_latent_ui(prefix))
56
  components.update(create_hidream_o1_reference_ui(prefix))
57
+ components.update(create_joyai_reference_ui(prefix))
58
  components.update(create_vae_override_ui(prefix))
59
  components.update(create_pid_ui(prefix))
60
 
ui/shared/ui_components.py CHANGED
@@ -696,6 +696,35 @@ def create_hidream_o1_reference_ui(prefix: str, max_units=10):
696
 
697
  return components
698
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
699
  def create_pid_ui(prefix: str):
700
  components = {}
701
  key = lambda name: f"{name}_{prefix}"
 
696
 
697
  return components
698
 
699
+ def create_joyai_reference_ui(prefix: str, max_units=2):
700
+ components = {}
701
+ key = lambda name: f"{name}_{prefix}"
702
+
703
+ with gr.Accordion("JoyAI Reference Edit Settings", open=False, visible=('joyai_reference' in default_enabled_chains)) as ref_accordion:
704
+ components[key('joyai_reference_accordion')] = ref_accordion
705
+ gr.Markdown("💡 **Tip:** For multimodal models, this feature enables powerful editing and combining capabilities. In txt2img mode, adding a single reference image performs an **Image Edit** (JoyAI-Image-Edit recommended), while adding multiple images performs an **Image Combine** (JoyAI-Image-Edit-Plus recommended with ZeroGPU Duration (s) set to 120).")
706
+
707
+ ref_image_groups = []
708
+ ref_image_inputs = []
709
+ with gr.Row():
710
+ for i in range(max_units):
711
+ with gr.Column(visible=(i < 1), min_width=160) as img_col:
712
+ img_comp = gr.Image(type="pil", label=f"Ref. {i+1}", sources=["upload"], height=150)
713
+ ref_image_groups.append(img_col)
714
+ ref_image_inputs.append(img_comp)
715
+
716
+ components[key('joyai_reference_rows')] = ref_image_groups
717
+ components[key('joyai_reference_images')] = ref_image_inputs
718
+
719
+ with gr.Row():
720
+ components[key('add_joyai_reference_button')] = gr.Button("✚ Add Reference Image")
721
+ components[key('delete_joyai_reference_button')] = gr.Button("➖ Delete Reference Image", visible=False)
722
+ components[key('joyai_reference_count_state')] = gr.State(1)
723
+
724
+ components[key('all_joyai_reference_components_flat')] = ref_image_inputs
725
+
726
+ return components
727
+
728
  def create_pid_ui(prefix: str):
729
  components = {}
730
  key = lambda name: f"{name}_{prefix}"
yaml/constants.yaml CHANGED
@@ -15,6 +15,14 @@ RESOLUTION_MAP:
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]
@@ -233,6 +241,7 @@ RESOLUTION_MAP:
233
  "2:3 (Portrait)": [512, 768]
234
 
235
  MULTIPLIERS_MAP:
 
236
  krea-2: 1
237
  boogu-image: 1
238
  pixeldit: 1
 
15
  "3:4 (Classic Portrait)": [896, 1152]
16
  "3:2 (Photography)": [1216, 832]
17
  "2:3 (Photography Portrait)": [832, 1216]
18
+ joyai-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
  boogu-image:
27
  "1:1 (Square)": [1024, 1024]
28
  "16:9 (Landscape)": [1344, 768]
 
241
  "2:3 (Portrait)": [512, 768]
242
 
243
  MULTIPLIERS_MAP:
244
+ joyai-image: 1
245
  krea-2: 1
246
  boogu-image: 1
247
  pixeldit: 1
yaml/file_list.yaml CHANGED
@@ -405,6 +405,15 @@ file:
405
  source: "hf"
406
  repo_id: "Comfy-Org/Krea-2"
407
  repository_file_path: "diffusion_models/krea2_raw_fp8_scaled.safetensors"
 
 
 
 
 
 
 
 
 
408
  # Boogu-Image
409
  - filename: "boogu_image_base_nvfp4.safetensors"
410
  source: "hf"
@@ -778,6 +787,15 @@ file:
778
  source: "hf"
779
  repo_id: "Comfy-Org/Krea-2"
780
  repository_file_path: "text_encoders/qwen3vl_4b_fp8_scaled.safetensors"
 
 
 
 
 
 
 
 
 
781
  # Cosmos-Predict2
782
  - filename: "oldt5_xxl_fp8_e4m3fn_scaled.safetensors"
783
  source: "hf"
 
405
  source: "hf"
406
  repo_id: "Comfy-Org/Krea-2"
407
  repository_file_path: "diffusion_models/krea2_raw_fp8_scaled.safetensors"
408
+ # JoyAI-Image
409
+ - filename: "joyai_image_edit_int8_convrot.safetensors"
410
+ source: "hf"
411
+ repo_id: "jdopensource/JoyAI-Image-Edit-ComfyUI"
412
+ repository_file_path: "diffusion_models/joyai_image_edit_int8_convrot.safetensors"
413
+ - filename: "joyai_image_edit_plus_int8_convrot.safetensors"
414
+ source: "hf"
415
+ repo_id: "jdopensource/JoyAI-Image-Edit-Plus-ComfyUI"
416
+ repository_file_path: "diffusion_models/joyai_image_edit_plus_int8_convrot.safetensors"
417
  # Boogu-Image
418
  - filename: "boogu_image_base_nvfp4.safetensors"
419
  source: "hf"
 
787
  source: "hf"
788
  repo_id: "Comfy-Org/Krea-2"
789
  repository_file_path: "text_encoders/qwen3vl_4b_fp8_scaled.safetensors"
790
+ # JoyAI-Image
791
+ - filename: "qwen3vl_8b_joyimage_edit_int8_convrot.safetensors"
792
+ source: "hf"
793
+ repo_id: "jdopensource/JoyAI-Image-Edit-ComfyUI"
794
+ repository_file_path: "text_encoders/qwen3vl_8b_joyimage_edit_int8_convrot.safetensors"
795
+ - filename: "qwen3vl_8b_joyimage_edit_plus_int8_convrot.safetensors"
796
+ source: "hf"
797
+ repo_id: "jdopensource/JoyAI-Image-Edit-Plus-ComfyUI"
798
+ repository_file_path: "text_encoders/qwen3vl_8b_joyimage_edit_plus_int8_convrot.safetensors"
799
  # Cosmos-Predict2
800
  - filename: "oldt5_xxl_fp8_e4m3fn_scaled.safetensors"
801
  source: "hf"
yaml/image_gen_features.yaml CHANGED
@@ -8,6 +8,10 @@ default:
8
  - conditioning
9
  - vae
10
 
 
 
 
 
11
  krea-2:
12
  enabled_chains:
13
  - lora
 
8
  - conditioning
9
  - vae
10
 
11
+ joyai-image:
12
+ enabled_chains:
13
+ - joyai_reference
14
+
15
  krea-2:
16
  enabled_chains:
17
  - lora
yaml/injectors.yaml CHANGED
@@ -29,6 +29,8 @@ injector_definitions:
29
  module: "chain_injectors.hidream_o1_smoothing_injector"
30
  dynamic_hidream_o1_reference_chains:
31
  module: "chain_injectors.hidream_o1_reference_injector"
 
 
32
  dynamic_pid_chains:
33
  module: "chain_injectors.pid_injector"
34
 
@@ -48,4 +50,5 @@ injector_order:
48
  - dynamic_anima_controlnet_lllite_chains
49
  - dynamic_hidream_o1_smoothing_chains
50
  - dynamic_hidream_o1_reference_chains
 
51
  - dynamic_pid_chains
 
29
  module: "chain_injectors.hidream_o1_smoothing_injector"
30
  dynamic_hidream_o1_reference_chains:
31
  module: "chain_injectors.hidream_o1_reference_injector"
32
+ dynamic_joyai_reference_chains:
33
+ module: "chain_injectors.joyai_reference_injector"
34
  dynamic_pid_chains:
35
  module: "chain_injectors.pid_injector"
36
 
 
50
  - dynamic_anima_controlnet_lllite_chains
51
  - dynamic_hidream_o1_smoothing_chains
52
  - dynamic_hidream_o1_reference_chains
53
+ - dynamic_joyai_reference_chains
54
  - dynamic_pid_chains
yaml/model_architectures.yaml CHANGED
@@ -1,5 +1,6 @@
1
  architecture_order:
2
  - "Krea-2"
 
3
  - "Boogu-Image"
4
  - "PixelDiT"
5
  - "Ideogram-4"
@@ -31,6 +32,8 @@ architecture_order:
31
  architectures:
32
  Krea-2:
33
  model_type: "krea-2"
 
 
34
  "Boogu-Image":
35
  model_type: "boogu-image"
36
  "PixelDiT":
 
1
  architecture_order:
2
  - "Krea-2"
3
+ - "JoyAI-Image"
4
  - "Boogu-Image"
5
  - "PixelDiT"
6
  - "Ideogram-4"
 
32
  architectures:
33
  Krea-2:
34
  model_type: "krea-2"
35
+ "JoyAI-Image":
36
+ model_type: "joyai-image"
37
  "Boogu-Image":
38
  model_type: "boogu-image"
39
  "PixelDiT":
yaml/model_defaults.yaml CHANGED
@@ -18,6 +18,16 @@ Krea-2:
18
  sampler_name: "euler"
19
  scheduler: "simple"
20
 
 
 
 
 
 
 
 
 
 
 
21
  Boogu-Image:
22
  _defaults:
23
  steps: 25
 
18
  sampler_name: "euler"
19
  scheduler: "simple"
20
 
21
+ JoyAI-Image:
22
+ _defaults:
23
+ steps: 40
24
+ cfg: 4.0
25
+ sampler_name: "euler"
26
+ scheduler: "normal"
27
+ "JoyAI-Image-Edit-Plus":
28
+ steps: 30
29
+ cfg: 4.0
30
+
31
  Boogu-Image:
32
  _defaults:
33
  steps: 25
yaml/model_list.yaml CHANGED
@@ -12,6 +12,19 @@ Checkpoint:
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:
 
12
  unet: "krea2_raw_fp8_scaled.safetensors"
13
  clip: "qwen3vl_4b_fp8_scaled.safetensors"
14
  vae: "qwen_image_vae.safetensors"
15
+ JoyAI-Image:
16
+ latent_type: sd3_latent
17
+ models:
18
+ - display_name: "JoyAI-Image-Edit"
19
+ components:
20
+ unet: "joyai_image_edit_int8_convrot.safetensors"
21
+ clip: "qwen3vl_8b_joyimage_edit_int8_convrot.safetensors"
22
+ vae: "wan_2.1_vae.safetensors"
23
+ - display_name: "JoyAI-Image-Edit-Plus"
24
+ components:
25
+ unet: "joyai_image_edit_plus_int8_convrot.safetensors"
26
+ clip: "qwen3vl_8b_joyimage_edit_plus_int8_convrot.safetensors"
27
+ vae: "wan_2.1_vae.safetensors"
28
  Boogu-Image:
29
  latent_type: latent
30
  models: