Optimize workflows and configuration files, and standardize file naming.
Browse files- chain_injectors/__init__.py +50 -0
- chain_injectors/{boogu_edit_injector.py → boogu_image_edit_injector.py} +17 -72
- chain_injectors/{joyai_reference_injector.py → joyai_image_injector.py} +0 -0
- chain_injectors/{krea2_reference_edit_injector.py → krea2_style_reference_injector.py} +0 -0
- chain_injectors/newbie_lora_injector.py +0 -63
- chain_injectors/qwen_image_edit_injector.py +17 -74
- comfy_integration/setup.py +2 -10
- core/pipelines/sd_image_pipeline.py +4 -4
- core/pipelines/workflow_recipes/_partials/{_base_sampler_sd.yaml → _base_sampler.yaml} +27 -27
- core/pipelines/workflow_recipes/_partials/conditioning/boogu-image.yaml +67 -74
- core/pipelines/workflow_recipes/_partials/conditioning/joyai-image.yaml +2 -2
- core/pipelines/workflow_recipes/_partials/conditioning/krea-2.yaml +2 -2
- core/pipelines/workflow_recipes/_partials/conditioning/newbie-image.yaml +2 -2
- core/pipelines/workflow_recipes/_partials/conditioning/qwen-image.yaml +90 -91
- core/pipelines/workflow_recipes/{sd_unified_recipe.yaml → unified_recipe.yaml} +7 -7
- core/workflow_assembler.py +164 -178
- ui/events/change_handlers.py +10 -10
- ui/shared/ui_components.py +5 -5
- yaml/image_gen_features.yaml +199 -207
- yaml/injectors.yaml +0 -69
chain_injectors/__init__.py
CHANGED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import importlib
|
| 3 |
+
import pkgutil
|
| 4 |
+
|
| 5 |
+
def discover_injectors():
|
| 6 |
+
injectors = {}
|
| 7 |
+
package_dir = os.path.dirname(__file__)
|
| 8 |
+
|
| 9 |
+
for _, module_name, is_pkg in pkgutil.iter_modules([package_dir]):
|
| 10 |
+
if is_pkg or module_name.startswith('_'):
|
| 11 |
+
continue
|
| 12 |
+
|
| 13 |
+
full_module_name = f"chain_injectors.{module_name}"
|
| 14 |
+
try:
|
| 15 |
+
module = importlib.import_module(full_module_name)
|
| 16 |
+
if hasattr(module, 'inject') and callable(module.inject):
|
| 17 |
+
feature_name = getattr(module, 'FEATURE_NAME', None)
|
| 18 |
+
if not feature_name:
|
| 19 |
+
feature_name = module_name[:-9] if module_name.endswith('_injector') else module_name
|
| 20 |
+
|
| 21 |
+
chain_type = getattr(module, 'CHAIN_TYPE', None)
|
| 22 |
+
if not chain_type:
|
| 23 |
+
chain_type = f"dynamic_{feature_name}_chains"
|
| 24 |
+
|
| 25 |
+
injectors[chain_type] = module.inject
|
| 26 |
+
else:
|
| 27 |
+
print(f"Warning: Module '{full_module_name}' does not have a callable 'inject' function.")
|
| 28 |
+
except Exception as e:
|
| 29 |
+
print(f"Error importing injector module '{full_module_name}': {e}")
|
| 30 |
+
|
| 31 |
+
return injectors
|
| 32 |
+
|
| 33 |
+
def get_registered_features():
|
| 34 |
+
features = {}
|
| 35 |
+
package_dir = os.path.dirname(__file__)
|
| 36 |
+
|
| 37 |
+
for _, module_name, is_pkg in pkgutil.iter_modules([package_dir]):
|
| 38 |
+
if is_pkg or module_name.startswith('_'):
|
| 39 |
+
continue
|
| 40 |
+
|
| 41 |
+
feature_name = module_name[:-9] if module_name.endswith('_injector') else module_name
|
| 42 |
+
full_module_name = f"chain_injectors.{module_name}"
|
| 43 |
+
chain_type = f"dynamic_{feature_name}_chains"
|
| 44 |
+
|
| 45 |
+
features[feature_name] = {
|
| 46 |
+
'module': full_module_name,
|
| 47 |
+
'chain_type': chain_type
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
return features
|
chain_injectors/{boogu_edit_injector.py → boogu_image_edit_injector.py}
RENAMED
|
@@ -1,5 +1,3 @@
|
|
| 1 |
-
import os
|
| 2 |
-
|
| 3 |
def create_node(assembler, class_type, title):
|
| 4 |
try:
|
| 5 |
node = assembler._get_node_template(class_type)
|
|
@@ -31,64 +29,30 @@ def inject(assembler, chain_definition, chain_items):
|
|
| 31 |
|
| 32 |
valid_images = valid_images[:10]
|
| 33 |
|
| 34 |
-
|
| 35 |
-
pos_prompt_name = chain_definition.get('pos_prompt_node', 'pos_prompt')
|
| 36 |
-
neg_prompt_name = chain_definition.get('neg_prompt_node', 'neg_prompt')
|
| 37 |
-
clip_loader_name = chain_definition.get('clip_loader_node', 'clip_loader')
|
| 38 |
vae_loader_name = chain_definition.get('vae_loader_node', 'vae_loader')
|
| 39 |
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
|
|
|
| 45 |
|
| 46 |
-
if
|
| 47 |
-
print(f"Warning:
|
| 48 |
return
|
| 49 |
|
| 50 |
-
|
| 51 |
-
if
|
| 52 |
-
vae_connection = [assembler.node_map[vae_loader_name], 0]
|
| 53 |
-
else:
|
| 54 |
for node_id, node in assembler.workflow.items():
|
| 55 |
if isinstance(node, dict) and node.get('class_type') == 'VAELoader':
|
| 56 |
-
|
| 57 |
break
|
| 58 |
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
clip_connection = [assembler.node_map[clip_loader_name], 0]
|
| 62 |
-
elif pos_prompt_name in assembler.node_map:
|
| 63 |
-
pos_id = assembler.node_map[pos_prompt_name]
|
| 64 |
-
clip_connection = assembler.workflow[pos_id]['inputs'].get('clip')
|
| 65 |
-
|
| 66 |
-
pos_prompt_id = assembler.node_map.get(pos_prompt_name)
|
| 67 |
-
neg_prompt_id = assembler.node_map.get(neg_prompt_name)
|
| 68 |
-
|
| 69 |
-
pos_text = ""
|
| 70 |
-
if pos_prompt_id and pos_prompt_id in assembler.workflow:
|
| 71 |
-
pos_text = assembler.workflow[pos_prompt_id]['inputs'].get('text', '')
|
| 72 |
-
elif hasattr(assembler, 'ui_values') and isinstance(assembler.ui_values, dict):
|
| 73 |
-
pos_text = assembler.ui_values.get('positive_prompt') or assembler.ui_values.get('prompt') or ''
|
| 74 |
|
| 75 |
-
if not pos_text:
|
| 76 |
-
for node_id, node in assembler.workflow.items():
|
| 77 |
-
if isinstance(node, dict):
|
| 78 |
-
cls = node.get('class_type', '')
|
| 79 |
-
if cls in ['TextEncodeBooguEdit', 'Krea2EditGroundedEncode', 'TextEncodeQwenImageEditPlus', 'CLIPTextEncode']:
|
| 80 |
-
t = node.get('inputs', {}).get('prompt') or node.get('inputs', {}).get('text')
|
| 81 |
-
if t:
|
| 82 |
-
pos_text = t
|
| 83 |
-
break
|
| 84 |
-
|
| 85 |
-
neg_text = ""
|
| 86 |
-
if neg_prompt_id and neg_prompt_id in assembler.workflow:
|
| 87 |
-
neg_text = assembler.workflow[neg_prompt_id]['inputs'].get('text', '')
|
| 88 |
-
elif hasattr(assembler, 'ui_values') and isinstance(assembler.ui_values, dict):
|
| 89 |
-
neg_text = assembler.ui_values.get('negative_prompt') or assembler.ui_values.get('neg_prompt') or ''
|
| 90 |
-
|
| 91 |
-
scaled_image_ids = []
|
| 92 |
for i, img_filename in enumerate(valid_images):
|
| 93 |
load_id = assembler._get_unique_id()
|
| 94 |
load_node = create_node(assembler, "LoadImage", f"Load Reference Image {i+1}")
|
|
@@ -102,27 +66,8 @@ def inject(assembler, chain_definition, chain_items):
|
|
| 102 |
scale_node['inputs']['resolution_steps'] = 1
|
| 103 |
scale_node['inputs']['image'] = [load_id, 0]
|
| 104 |
assembler.workflow[scale_id] = scale_node
|
| 105 |
-
scaled_image_ids.append(scale_id)
|
| 106 |
-
|
| 107 |
-
boogu_encode_id = assembler._get_unique_id()
|
| 108 |
-
boogu_encode_node = create_node(assembler, "TextEncodeBooguEdit", "TextEncodeBooguEdit")
|
| 109 |
-
boogu_encode_node['inputs']['prompt'] = pos_text
|
| 110 |
-
boogu_encode_node['inputs']['negative_prompt'] = neg_text
|
| 111 |
-
if clip_connection:
|
| 112 |
-
boogu_encode_node['inputs']['clip'] = clip_connection
|
| 113 |
-
if vae_connection:
|
| 114 |
-
boogu_encode_node['inputs']['vae'] = vae_connection
|
| 115 |
-
for idx, s_id in enumerate(scaled_image_ids):
|
| 116 |
-
boogu_encode_node['inputs'][f"images.image_{idx+1}"] = [s_id, 0]
|
| 117 |
-
assembler.workflow[boogu_encode_id] = boogu_encode_node
|
| 118 |
-
|
| 119 |
-
assembler.workflow[ksampler_id]['inputs']['positive'] = [boogu_encode_id, 0]
|
| 120 |
-
assembler.workflow[ksampler_id]['inputs']['negative'] = [boogu_encode_id, 1]
|
| 121 |
-
|
| 122 |
-
if pos_prompt_id and pos_prompt_id in assembler.workflow:
|
| 123 |
-
del assembler.workflow[pos_prompt_id]
|
| 124 |
|
| 125 |
-
|
| 126 |
-
|
| 127 |
|
| 128 |
-
print(f"Boogu Edit injector applied with {len(valid_images)} reference image(s).
|
|
|
|
|
|
|
|
|
|
| 1 |
def create_node(assembler, class_type, title):
|
| 2 |
try:
|
| 3 |
node = assembler._get_node_template(class_type)
|
|
|
|
| 29 |
|
| 30 |
valid_images = valid_images[:10]
|
| 31 |
|
| 32 |
+
boogu_prompt_name = chain_definition.get('boogu_prompt_node', 'boogu_prompt')
|
|
|
|
|
|
|
|
|
|
| 33 |
vae_loader_name = chain_definition.get('vae_loader_node', 'vae_loader')
|
| 34 |
|
| 35 |
+
boogu_prompt_id = assembler.node_map.get(boogu_prompt_name)
|
| 36 |
+
if not boogu_prompt_id or boogu_prompt_id not in assembler.workflow:
|
| 37 |
+
for node_id, node in assembler.workflow.items():
|
| 38 |
+
if isinstance(node, dict) and node.get('class_type') == 'TextEncodeBooguEdit':
|
| 39 |
+
boogu_prompt_id = node_id
|
| 40 |
+
break
|
| 41 |
|
| 42 |
+
if not boogu_prompt_id:
|
| 43 |
+
print(f"Warning: Target node '{boogu_prompt_name}' (TextEncodeBooguEdit) for Boogu Edit chain not found. Skipping.")
|
| 44 |
return
|
| 45 |
|
| 46 |
+
vae_id = assembler.node_map.get(vae_loader_name)
|
| 47 |
+
if not vae_id:
|
|
|
|
|
|
|
| 48 |
for node_id, node in assembler.workflow.items():
|
| 49 |
if isinstance(node, dict) and node.get('class_type') == 'VAELoader':
|
| 50 |
+
vae_id = node_id
|
| 51 |
break
|
| 52 |
|
| 53 |
+
if vae_id:
|
| 54 |
+
assembler.workflow[boogu_prompt_id]['inputs']['vae'] = [vae_id, 0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
for i, img_filename in enumerate(valid_images):
|
| 57 |
load_id = assembler._get_unique_id()
|
| 58 |
load_node = create_node(assembler, "LoadImage", f"Load Reference Image {i+1}")
|
|
|
|
| 66 |
scale_node['inputs']['resolution_steps'] = 1
|
| 67 |
scale_node['inputs']['image'] = [load_id, 0]
|
| 68 |
assembler.workflow[scale_id] = scale_node
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
+
image_key = f"images.image_{i+1}"
|
| 71 |
+
assembler.workflow[boogu_prompt_id]['inputs'][image_key] = [scale_id, 0]
|
| 72 |
|
| 73 |
+
print(f"Boogu Edit injector applied with {len(valid_images)} reference image(s). Connected VAE dynamically.")
|
chain_injectors/{joyai_reference_injector.py → joyai_image_injector.py}
RENAMED
|
File without changes
|
chain_injectors/{krea2_reference_edit_injector.py → krea2_style_reference_injector.py}
RENAMED
|
File without changes
|
chain_injectors/newbie_lora_injector.py
DELETED
|
@@ -1,63 +0,0 @@
|
|
| 1 |
-
from copy import deepcopy
|
| 2 |
-
|
| 3 |
-
def inject(assembler, chain_definition, chain_items):
|
| 4 |
-
if not chain_items:
|
| 5 |
-
return
|
| 6 |
-
|
| 7 |
-
output_map = chain_definition.get('output_map', {})
|
| 8 |
-
current_connections = {}
|
| 9 |
-
for key, type_name in output_map.items():
|
| 10 |
-
if ':' in str(key):
|
| 11 |
-
node_name, idx_str = key.split(':')
|
| 12 |
-
if node_name not in assembler.node_map:
|
| 13 |
-
print(f"Warning: [NewBie LoRA Injector] Node '{node_name}' in chain's output_map not found. Skipping.")
|
| 14 |
-
continue
|
| 15 |
-
node_id = assembler.node_map[node_name]
|
| 16 |
-
start_output_idx = int(idx_str)
|
| 17 |
-
current_connections[type_name] = [node_id, start_output_idx]
|
| 18 |
-
else:
|
| 19 |
-
print(f"Warning: [NewBie LoRA Injector] output_map key '{key}' is not in 'node:index' format. Skipping this connection.")
|
| 20 |
-
|
| 21 |
-
template_name = chain_definition.get('template')
|
| 22 |
-
if not template_name:
|
| 23 |
-
print(f"Warning: [NewBie LoRA Injector] No 'template' defined for chain. Skipping.")
|
| 24 |
-
return
|
| 25 |
-
|
| 26 |
-
for item_data in chain_items:
|
| 27 |
-
template = assembler._get_node_template(template_name)
|
| 28 |
-
node_data = deepcopy(template)
|
| 29 |
-
|
| 30 |
-
node_data['inputs']['lora_name'] = item_data.get('lora_name')
|
| 31 |
-
node_data['inputs']['strength'] = item_data.get('strength_model', 1.0)
|
| 32 |
-
node_data['inputs']['enabled'] = True
|
| 33 |
-
|
| 34 |
-
if 'model' in current_connections:
|
| 35 |
-
node_data['inputs']['model'] = current_connections['model']
|
| 36 |
-
if 'clip' in current_connections:
|
| 37 |
-
node_data['inputs']['clip'] = current_connections['clip']
|
| 38 |
-
|
| 39 |
-
new_node_id = assembler._get_unique_id()
|
| 40 |
-
assembler.workflow[new_node_id] = node_data
|
| 41 |
-
|
| 42 |
-
current_connections['model'] = [new_node_id, 0]
|
| 43 |
-
current_connections['clip'] = [new_node_id, 1]
|
| 44 |
-
|
| 45 |
-
end_input_map = chain_definition.get('end_input_map', {})
|
| 46 |
-
for type_name, targets in end_input_map.items():
|
| 47 |
-
if type_name in current_connections:
|
| 48 |
-
if not isinstance(targets, list):
|
| 49 |
-
targets = [targets]
|
| 50 |
-
|
| 51 |
-
for target_str in targets:
|
| 52 |
-
try:
|
| 53 |
-
end_node_name, end_input_name = target_str.split(':')
|
| 54 |
-
if end_node_name in assembler.node_map:
|
| 55 |
-
end_node_id = assembler.node_map[end_node_name]
|
| 56 |
-
assembler.workflow[end_node_id]['inputs'][end_input_name] = current_connections[type_name]
|
| 57 |
-
else:
|
| 58 |
-
print(f"Warning: [NewBie LoRA Injector] End node '{end_node_name}' for dynamic chain not found. Skipping connection.")
|
| 59 |
-
except ValueError:
|
| 60 |
-
print(f"Warning: [NewBie LoRA Injector] Invalid target format '{target_str}' in end_input_map. Skipping.")
|
| 61 |
-
|
| 62 |
-
if chain_items:
|
| 63 |
-
print(f"NewBie LoRA injector applied. Re-routed model and clip through {len(chain_items)} LoRA(s).")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
chain_injectors/qwen_image_edit_injector.py
CHANGED
|
@@ -1,5 +1,3 @@
|
|
| 1 |
-
import os
|
| 2 |
-
|
| 3 |
def create_node(assembler, class_type, title):
|
| 4 |
try:
|
| 5 |
node = assembler._get_node_template(class_type)
|
|
@@ -34,7 +32,6 @@ def inject(assembler, chain_definition, chain_items):
|
|
| 34 |
ksampler_name = chain_definition.get('ksampler_node', 'ksampler')
|
| 35 |
pos_prompt_name = chain_definition.get('pos_prompt_node', 'pos_prompt')
|
| 36 |
neg_prompt_name = chain_definition.get('neg_prompt_node', 'neg_prompt')
|
| 37 |
-
clip_loader_name = chain_definition.get('clip_loader_node', 'clip_loader')
|
| 38 |
vae_loader_name = chain_definition.get('vae_loader_node', 'vae_loader')
|
| 39 |
model_sampler_name = chain_definition.get('model_sampler_node', 'model_sampler')
|
| 40 |
|
|
@@ -43,53 +40,24 @@ def inject(assembler, chain_definition, chain_items):
|
|
| 43 |
return
|
| 44 |
|
| 45 |
ksampler_id = assembler.node_map[ksampler_name]
|
|
|
|
|
|
|
| 46 |
|
| 47 |
-
if
|
| 48 |
-
print(
|
| 49 |
return
|
| 50 |
|
| 51 |
-
|
| 52 |
-
if
|
| 53 |
-
vae_connection = [assembler.node_map[vae_loader_name], 0]
|
| 54 |
-
else:
|
| 55 |
for node_id, node in assembler.workflow.items():
|
| 56 |
if isinstance(node, dict) and node.get('class_type') == 'VAELoader':
|
| 57 |
-
|
| 58 |
break
|
| 59 |
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
elif pos_prompt_name in assembler.node_map:
|
| 64 |
-
pos_id = assembler.node_map[pos_prompt_name]
|
| 65 |
-
clip_connection = assembler.workflow[pos_id]['inputs'].get('clip')
|
| 66 |
-
|
| 67 |
-
pos_prompt_id = assembler.node_map.get(pos_prompt_name)
|
| 68 |
-
neg_prompt_id = assembler.node_map.get(neg_prompt_name)
|
| 69 |
|
| 70 |
-
pos_text = ""
|
| 71 |
-
if pos_prompt_id and pos_prompt_id in assembler.workflow:
|
| 72 |
-
pos_text = assembler.workflow[pos_prompt_id]['inputs'].get('text', '')
|
| 73 |
-
elif hasattr(assembler, 'ui_values') and isinstance(assembler.ui_values, dict):
|
| 74 |
-
pos_text = assembler.ui_values.get('positive_prompt') or assembler.ui_values.get('prompt') or ''
|
| 75 |
-
|
| 76 |
-
if not pos_text:
|
| 77 |
-
for node_id, node in assembler.workflow.items():
|
| 78 |
-
if isinstance(node, dict):
|
| 79 |
-
cls = node.get('class_type', '')
|
| 80 |
-
if cls in ['Krea2EditGroundedEncode', 'TextEncodeQwenImageEditPlus', 'CLIPTextEncode']:
|
| 81 |
-
t = node.get('inputs', {}).get('prompt') or node.get('inputs', {}).get('text')
|
| 82 |
-
if t:
|
| 83 |
-
pos_text = t
|
| 84 |
-
break
|
| 85 |
-
|
| 86 |
-
neg_text = ""
|
| 87 |
-
if neg_prompt_id and neg_prompt_id in assembler.workflow:
|
| 88 |
-
neg_text = assembler.workflow[neg_prompt_id]['inputs'].get('text', '')
|
| 89 |
-
elif hasattr(assembler, 'ui_values') and isinstance(assembler.ui_values, dict):
|
| 90 |
-
neg_text = assembler.ui_values.get('negative_prompt') or assembler.ui_values.get('neg_prompt') or ''
|
| 91 |
-
|
| 92 |
-
scaled_image_ids = []
|
| 93 |
for i, img_filename in enumerate(valid_images):
|
| 94 |
load_id = assembler._get_unique_id()
|
| 95 |
load_node = create_node(assembler, "LoadImage", f"Load Reference Image {i+1}")
|
|
@@ -103,40 +71,21 @@ def inject(assembler, chain_definition, chain_items):
|
|
| 103 |
scale_node['inputs']['resolution_steps'] = 1
|
| 104 |
scale_node['inputs']['image'] = [load_id, 0]
|
| 105 |
assembler.workflow[scale_id] = scale_node
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
pos_encode_node['inputs']['prompt'] = pos_text
|
| 111 |
-
if clip_connection:
|
| 112 |
-
pos_encode_node['inputs']['clip'] = clip_connection
|
| 113 |
-
if vae_connection:
|
| 114 |
-
pos_encode_node['inputs']['vae'] = vae_connection
|
| 115 |
-
for idx, s_id in enumerate(scaled_image_ids):
|
| 116 |
-
pos_encode_node['inputs'][f"image{idx+1}"] = [s_id, 0]
|
| 117 |
-
assembler.workflow[pos_encode_id] = pos_encode_node
|
| 118 |
-
|
| 119 |
-
neg_encode_id = assembler._get_unique_id()
|
| 120 |
-
neg_encode_node = create_node(assembler, "TextEncodeQwenImageEditPlus", "TextEncodeQwenImageEditPlus")
|
| 121 |
-
neg_encode_node['inputs']['prompt'] = neg_text
|
| 122 |
-
if clip_connection:
|
| 123 |
-
neg_encode_node['inputs']['clip'] = clip_connection
|
| 124 |
-
if vae_connection:
|
| 125 |
-
neg_encode_node['inputs']['vae'] = vae_connection
|
| 126 |
-
for idx, s_id in enumerate(scaled_image_ids):
|
| 127 |
-
neg_encode_node['inputs'][f"image{idx+1}"] = [s_id, 0]
|
| 128 |
-
assembler.workflow[neg_encode_id] = neg_encode_node
|
| 129 |
|
| 130 |
pos_ref_id = assembler._get_unique_id()
|
| 131 |
pos_ref_node = create_node(assembler, "FluxKontextMultiReferenceLatentMethod", "Edit Model Reference Method")
|
| 132 |
pos_ref_node['inputs']['reference_latents_method'] = "index_timestep_zero"
|
| 133 |
-
pos_ref_node['inputs']['conditioning'] = [
|
| 134 |
assembler.workflow[pos_ref_id] = pos_ref_node
|
| 135 |
|
| 136 |
neg_ref_id = assembler._get_unique_id()
|
| 137 |
neg_ref_node = create_node(assembler, "FluxKontextMultiReferenceLatentMethod", "Edit Model Reference Method")
|
| 138 |
neg_ref_node['inputs']['reference_latents_method'] = "index_timestep_zero"
|
| 139 |
-
neg_ref_node['inputs']['conditioning'] = [
|
| 140 |
assembler.workflow[neg_ref_id] = neg_ref_node
|
| 141 |
|
| 142 |
assembler.workflow[ksampler_id]['inputs']['positive'] = [pos_ref_id, 0]
|
|
@@ -161,10 +110,4 @@ def inject(assembler, chain_definition, chain_items):
|
|
| 161 |
assembler.workflow[cfg_norm_id] = cfg_norm_node
|
| 162 |
assembler.workflow[ksampler_id]['inputs']['model'] = [cfg_norm_id, 0]
|
| 163 |
|
| 164 |
-
|
| 165 |
-
del assembler.workflow[pos_prompt_id]
|
| 166 |
-
|
| 167 |
-
if neg_prompt_id and neg_prompt_id in assembler.workflow:
|
| 168 |
-
del assembler.workflow[neg_prompt_id]
|
| 169 |
-
|
| 170 |
-
print(f"Qwen-Image Edit injector applied with {len(valid_images)} reference image(s). Original CLIPTextEncode nodes replaced.")
|
|
|
|
|
|
|
|
|
|
| 1 |
def create_node(assembler, class_type, title):
|
| 2 |
try:
|
| 3 |
node = assembler._get_node_template(class_type)
|
|
|
|
| 32 |
ksampler_name = chain_definition.get('ksampler_node', 'ksampler')
|
| 33 |
pos_prompt_name = chain_definition.get('pos_prompt_node', 'pos_prompt')
|
| 34 |
neg_prompt_name = chain_definition.get('neg_prompt_node', 'neg_prompt')
|
|
|
|
| 35 |
vae_loader_name = chain_definition.get('vae_loader_node', 'vae_loader')
|
| 36 |
model_sampler_name = chain_definition.get('model_sampler_node', 'model_sampler')
|
| 37 |
|
|
|
|
| 40 |
return
|
| 41 |
|
| 42 |
ksampler_id = assembler.node_map[ksampler_name]
|
| 43 |
+
pos_prompt_id = assembler.node_map.get(pos_prompt_name)
|
| 44 |
+
neg_prompt_id = assembler.node_map.get(neg_prompt_name)
|
| 45 |
|
| 46 |
+
if not pos_prompt_id or not neg_prompt_id:
|
| 47 |
+
print("Warning: Positive or negative prompt node not found for Qwen-Image Edit chain. Skipping.")
|
| 48 |
return
|
| 49 |
|
| 50 |
+
vae_id = assembler.node_map.get(vae_loader_name)
|
| 51 |
+
if not vae_id:
|
|
|
|
|
|
|
| 52 |
for node_id, node in assembler.workflow.items():
|
| 53 |
if isinstance(node, dict) and node.get('class_type') == 'VAELoader':
|
| 54 |
+
vae_id = node_id
|
| 55 |
break
|
| 56 |
|
| 57 |
+
if vae_id:
|
| 58 |
+
assembler.workflow[pos_prompt_id]['inputs']['vae'] = [vae_id, 0]
|
| 59 |
+
assembler.workflow[neg_prompt_id]['inputs']['vae'] = [vae_id, 0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
for i, img_filename in enumerate(valid_images):
|
| 62 |
load_id = assembler._get_unique_id()
|
| 63 |
load_node = create_node(assembler, "LoadImage", f"Load Reference Image {i+1}")
|
|
|
|
| 71 |
scale_node['inputs']['resolution_steps'] = 1
|
| 72 |
scale_node['inputs']['image'] = [load_id, 0]
|
| 73 |
assembler.workflow[scale_id] = scale_node
|
| 74 |
+
|
| 75 |
+
image_key = f"image{i+1}"
|
| 76 |
+
assembler.workflow[pos_prompt_id]['inputs'][image_key] = [scale_id, 0]
|
| 77 |
+
assembler.workflow[neg_prompt_id]['inputs'][image_key] = [scale_id, 0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
|
| 79 |
pos_ref_id = assembler._get_unique_id()
|
| 80 |
pos_ref_node = create_node(assembler, "FluxKontextMultiReferenceLatentMethod", "Edit Model Reference Method")
|
| 81 |
pos_ref_node['inputs']['reference_latents_method'] = "index_timestep_zero"
|
| 82 |
+
pos_ref_node['inputs']['conditioning'] = [pos_prompt_id, 0]
|
| 83 |
assembler.workflow[pos_ref_id] = pos_ref_node
|
| 84 |
|
| 85 |
neg_ref_id = assembler._get_unique_id()
|
| 86 |
neg_ref_node = create_node(assembler, "FluxKontextMultiReferenceLatentMethod", "Edit Model Reference Method")
|
| 87 |
neg_ref_node['inputs']['reference_latents_method'] = "index_timestep_zero"
|
| 88 |
+
neg_ref_node['inputs']['conditioning'] = [neg_prompt_id, 0]
|
| 89 |
assembler.workflow[neg_ref_id] = neg_ref_node
|
| 90 |
|
| 91 |
assembler.workflow[ksampler_id]['inputs']['positive'] = [pos_ref_id, 0]
|
|
|
|
| 110 |
assembler.workflow[cfg_norm_id] = cfg_norm_node
|
| 111 |
assembler.workflow[ksampler_id]['inputs']['model'] = [cfg_norm_id, 0]
|
| 112 |
|
| 113 |
+
print(f"Qwen-Image Edit injector applied with {len(valid_images)} reference image(s). Connected VAE dynamically.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
comfy_integration/setup.py
CHANGED
|
@@ -72,15 +72,7 @@ def initialize_comfyui():
|
|
| 72 |
except Exception as e:
|
| 73 |
print(f"⚠️ Warning: Could not apply PR #108 compatibility patch for ComfyUI-IPAdapter-Flux: {e}")
|
| 74 |
|
| 75 |
-
# 4.
|
| 76 |
-
newbie_nodes_path = os.path.join(APP_DIR, "custom_nodes", "ComfyUI-Newbie-Nodes")
|
| 77 |
-
if not os.path.exists(newbie_nodes_path):
|
| 78 |
-
os.system(f"git clone https://github.com/NewBieAI-Lab/ComfyUI-Newbie-Nodes.git {newbie_nodes_path}")
|
| 79 |
-
print("✅ ComfyUI-Newbie-Nodes extension cloned.")
|
| 80 |
-
else:
|
| 81 |
-
print("✅ ComfyUI-Newbie-Nodes extension already exists.")
|
| 82 |
-
|
| 83 |
-
# 5. comfyui-krea2-controlnet
|
| 84 |
krea2_controlnet_nodes_path = os.path.join(APP_DIR, "custom_nodes", "comfyui-krea2-controlnet")
|
| 85 |
if not os.path.exists(krea2_controlnet_nodes_path):
|
| 86 |
os.system(f"git clone https://github.com/facok/comfyui-krea2-controlnet.git {krea2_controlnet_nodes_path}")
|
|
@@ -88,7 +80,7 @@ def initialize_comfyui():
|
|
| 88 |
else:
|
| 89 |
print("✅ comfyui-krea2-controlnet extension already exists.")
|
| 90 |
|
| 91 |
-
#
|
| 92 |
krea2edit_nodes_path = os.path.join(APP_DIR, "custom_nodes", "comfyui-krea2edit")
|
| 93 |
if not os.path.exists(krea2edit_nodes_path):
|
| 94 |
os.system(f"git clone https://github.com/lbouaraba/comfyui-krea2edit.git {krea2edit_nodes_path}")
|
|
|
|
| 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-krea2-controlnet
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
krea2_controlnet_nodes_path = os.path.join(APP_DIR, "custom_nodes", "comfyui-krea2-controlnet")
|
| 77 |
if not os.path.exists(krea2_controlnet_nodes_path):
|
| 78 |
os.system(f"git clone https://github.com/facok/comfyui-krea2-controlnet.git {krea2_controlnet_nodes_path}")
|
|
|
|
| 80 |
else:
|
| 81 |
print("✅ comfyui-krea2-controlnet extension already exists.")
|
| 82 |
|
| 83 |
+
# 5. comfyui-krea2edit
|
| 84 |
krea2edit_nodes_path = os.path.join(APP_DIR, "custom_nodes", "comfyui-krea2edit")
|
| 85 |
if not os.path.exists(krea2edit_nodes_path):
|
| 86 |
os.system(f"git clone https://github.com/lbouaraba/comfyui-krea2edit.git {krea2edit_nodes_path}")
|
core/pipelines/sd_image_pipeline.py
CHANGED
|
@@ -151,7 +151,7 @@ class SdImagePipeline(BasePipeline):
|
|
| 151 |
'latent_generator_template': latent_generator_template
|
| 152 |
}
|
| 153 |
|
| 154 |
-
recipe_path = os.path.join(os.path.dirname(__file__), "workflow_recipes", "
|
| 155 |
assembler = WorkflowAssembler(recipe_path, dynamic_values=dynamic_values)
|
| 156 |
|
| 157 |
hidream_o1_smoothing_data = []
|
|
@@ -180,11 +180,11 @@ class SdImagePipeline(BasePipeline):
|
|
| 180 |
"conditioning_chain": active_conditioning,
|
| 181 |
"reference_latent_chain": active_reference_latents,
|
| 182 |
"hidream_o1_reference_chain": active_hidream_o1_reference,
|
| 183 |
-
"
|
| 184 |
"krea2_identity_edit_chain": active_krea2_identity_edit,
|
| 185 |
-
"
|
| 186 |
"qwen_image_edit_chain": active_qwen_image_edit,
|
| 187 |
-
"
|
| 188 |
"reference_image_chain": active_reference_images,
|
| 189 |
"vae_chain": [ui_inputs.get('vae_name')] if ui_inputs.get('vae_name') else [],
|
| 190 |
"hidream_o1_smoothing_chain": hidream_o1_smoothing_data,
|
|
|
|
| 151 |
'latent_generator_template': latent_generator_template
|
| 152 |
}
|
| 153 |
|
| 154 |
+
recipe_path = os.path.join(os.path.dirname(__file__), "workflow_recipes", "unified_recipe.yaml")
|
| 155 |
assembler = WorkflowAssembler(recipe_path, dynamic_values=dynamic_values)
|
| 156 |
|
| 157 |
hidream_o1_smoothing_data = []
|
|
|
|
| 180 |
"conditioning_chain": active_conditioning,
|
| 181 |
"reference_latent_chain": active_reference_latents,
|
| 182 |
"hidream_o1_reference_chain": active_hidream_o1_reference,
|
| 183 |
+
"joyai_image_chain": active_joyai_reference,
|
| 184 |
"krea2_identity_edit_chain": active_krea2_identity_edit,
|
| 185 |
+
"krea2_style_reference_chain": active_krea2_reference_edit,
|
| 186 |
"qwen_image_edit_chain": active_qwen_image_edit,
|
| 187 |
+
"boogu_image_edit_chain": active_boogu_edit,
|
| 188 |
"reference_image_chain": active_reference_images,
|
| 189 |
"vae_chain": [ui_inputs.get('vae_name')] if ui_inputs.get('vae_name') else [],
|
| 190 |
"hidream_o1_smoothing_chain": hidream_o1_smoothing_data,
|
core/pipelines/workflow_recipes/_partials/{_base_sampler_sd.yaml → _base_sampler.yaml}
RENAMED
|
@@ -1,28 +1,28 @@
|
|
| 1 |
-
nodes:
|
| 2 |
-
ksampler:
|
| 3 |
-
class_type: KSampler
|
| 4 |
-
title: "KSampler"
|
| 5 |
-
params:
|
| 6 |
-
denoise: 1.0
|
| 7 |
-
vae_decode:
|
| 8 |
-
class_type: VAEDecode
|
| 9 |
-
title: "VAE Decode"
|
| 10 |
-
save_image:
|
| 11 |
-
class_type: SaveImage
|
| 12 |
-
title: "Save Image"
|
| 13 |
-
params: {}
|
| 14 |
-
|
| 15 |
-
connections:
|
| 16 |
-
- from: "ksampler:0"
|
| 17 |
-
to: "vae_decode:samples"
|
| 18 |
-
- from: "vae_decode:0"
|
| 19 |
-
to: "save_image:images"
|
| 20 |
-
|
| 21 |
-
ui_map:
|
| 22 |
-
seed: "ksampler:seed"
|
| 23 |
-
steps: "ksampler:steps"
|
| 24 |
-
cfg: "ksampler:cfg"
|
| 25 |
-
sampler_name: "ksampler:sampler_name"
|
| 26 |
-
scheduler: "ksampler:scheduler"
|
| 27 |
-
denoise: "ksampler:denoise"
|
| 28 |
filename_prefix: "save_image:filename_prefix"
|
|
|
|
| 1 |
+
nodes:
|
| 2 |
+
ksampler:
|
| 3 |
+
class_type: KSampler
|
| 4 |
+
title: "KSampler"
|
| 5 |
+
params:
|
| 6 |
+
denoise: 1.0
|
| 7 |
+
vae_decode:
|
| 8 |
+
class_type: VAEDecode
|
| 9 |
+
title: "VAE Decode"
|
| 10 |
+
save_image:
|
| 11 |
+
class_type: SaveImage
|
| 12 |
+
title: "Save Image"
|
| 13 |
+
params: {}
|
| 14 |
+
|
| 15 |
+
connections:
|
| 16 |
+
- from: "ksampler:0"
|
| 17 |
+
to: "vae_decode:samples"
|
| 18 |
+
- from: "vae_decode:0"
|
| 19 |
+
to: "save_image:images"
|
| 20 |
+
|
| 21 |
+
ui_map:
|
| 22 |
+
seed: "ksampler:seed"
|
| 23 |
+
steps: "ksampler:steps"
|
| 24 |
+
cfg: "ksampler:cfg"
|
| 25 |
+
sampler_name: "ksampler:sampler_name"
|
| 26 |
+
scheduler: "ksampler:scheduler"
|
| 27 |
+
denoise: "ksampler:denoise"
|
| 28 |
filename_prefix: "save_image:filename_prefix"
|
core/pipelines/workflow_recipes/_partials/conditioning/boogu-image.yaml
CHANGED
|
@@ -1,74 +1,67 @@
|
|
| 1 |
-
nodes:
|
| 2 |
-
|
| 3 |
-
class_type:
|
| 4 |
-
title: "
|
| 5 |
-
|
| 6 |
-
class_type:
|
| 7 |
-
title: "
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
"
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
ksampler_node: "ksampler"
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
ui_map:
|
| 70 |
-
positive_prompt: "pos_prompt:text"
|
| 71 |
-
negative_prompt: "neg_prompt:text"
|
| 72 |
-
unet_name: "unet_loader:unet_name"
|
| 73 |
-
clip_name: "clip_loader:clip_name"
|
| 74 |
-
vae_name: "vae_loader:vae_name"
|
|
|
|
| 1 |
+
nodes:
|
| 2 |
+
boogu_prompt:
|
| 3 |
+
class_type: TextEncodeBooguEdit
|
| 4 |
+
title: "Text Encode Boogu Edit"
|
| 5 |
+
unet_loader:
|
| 6 |
+
class_type: UNETLoader
|
| 7 |
+
title: "Load Diffusion Model"
|
| 8 |
+
params:
|
| 9 |
+
weight_dtype: "default"
|
| 10 |
+
clip_loader:
|
| 11 |
+
class_type: CLIPLoader
|
| 12 |
+
title: "Load CLIP"
|
| 13 |
+
params:
|
| 14 |
+
type: "boogu"
|
| 15 |
+
device: "default"
|
| 16 |
+
vae_loader:
|
| 17 |
+
class_type: VAELoader
|
| 18 |
+
title: "Load VAE"
|
| 19 |
+
|
| 20 |
+
connections:
|
| 21 |
+
- from: "unet_loader:0"
|
| 22 |
+
to: "ksampler:model"
|
| 23 |
+
- from: "clip_loader:0"
|
| 24 |
+
to: "boogu_prompt:clip"
|
| 25 |
+
- from: "boogu_prompt:0"
|
| 26 |
+
to: "ksampler:positive"
|
| 27 |
+
- from: "boogu_prompt:1"
|
| 28 |
+
to: "ksampler:negative"
|
| 29 |
+
- from: "vae_loader:0"
|
| 30 |
+
to: "vae_decode:vae"
|
| 31 |
+
- from: "vae_loader:0"
|
| 32 |
+
to: "vae_encode:vae"
|
| 33 |
+
|
| 34 |
+
dynamic_lora_chains:
|
| 35 |
+
lora_chain:
|
| 36 |
+
template: "LoraLoader"
|
| 37 |
+
output_map:
|
| 38 |
+
"unet_loader:0": "model"
|
| 39 |
+
"clip_loader:0": "clip"
|
| 40 |
+
input_map:
|
| 41 |
+
"model": "model"
|
| 42 |
+
"clip": "clip"
|
| 43 |
+
end_input_map:
|
| 44 |
+
"model": ["ksampler:model"]
|
| 45 |
+
"clip": ["boogu_prompt:clip"]
|
| 46 |
+
|
| 47 |
+
dynamic_conditioning_chains:
|
| 48 |
+
conditioning_chain:
|
| 49 |
+
ksampler_node: "ksampler"
|
| 50 |
+
clip_source: "clip_loader:0"
|
| 51 |
+
|
| 52 |
+
dynamic_boogu_image_edit_chains:
|
| 53 |
+
boogu_image_edit_chain:
|
| 54 |
+
ksampler_node: "ksampler"
|
| 55 |
+
boogu_prompt_node: "boogu_prompt"
|
| 56 |
+
vae_loader_node: "vae_loader"
|
| 57 |
+
|
| 58 |
+
dynamic_pid_chains:
|
| 59 |
+
pid_chain:
|
| 60 |
+
ksampler_node: "ksampler"
|
| 61 |
+
|
| 62 |
+
ui_map:
|
| 63 |
+
positive_prompt: "boogu_prompt:prompt"
|
| 64 |
+
negative_prompt: "boogu_prompt:negative_prompt"
|
| 65 |
+
unet_name: "unet_loader:unet_name"
|
| 66 |
+
clip_name: "clip_loader:clip_name"
|
| 67 |
+
vae_name: "vae_loader:vae_name"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/pipelines/workflow_recipes/_partials/conditioning/joyai-image.yaml
CHANGED
|
@@ -71,8 +71,8 @@ dynamic_pid_chains:
|
|
| 71 |
pid_chain:
|
| 72 |
ksampler_node: "ksampler"
|
| 73 |
|
| 74 |
-
|
| 75 |
-
|
| 76 |
pos_prompt_node: "pos_prompt"
|
| 77 |
neg_prompt_node: "neg_prompt"
|
| 78 |
vae_node: "vae_loader"
|
|
|
|
| 71 |
pid_chain:
|
| 72 |
ksampler_node: "ksampler"
|
| 73 |
|
| 74 |
+
dynamic_joyai_image_chains:
|
| 75 |
+
joyai_image_chain:
|
| 76 |
pos_prompt_node: "pos_prompt"
|
| 77 |
neg_prompt_node: "neg_prompt"
|
| 78 |
vae_node: "vae_loader"
|
core/pipelines/workflow_recipes/_partials/conditioning/krea-2.yaml
CHANGED
|
@@ -62,8 +62,8 @@ dynamic_krea2_identity_edit_chains:
|
|
| 62 |
clip_loader_node: "clip_loader"
|
| 63 |
vae_loader_node: "vae_loader"
|
| 64 |
|
| 65 |
-
|
| 66 |
-
|
| 67 |
ksampler_node: "ksampler"
|
| 68 |
pos_prompt_node: "pos_prompt"
|
| 69 |
neg_prompt_node: "neg_prompt"
|
|
|
|
| 62 |
clip_loader_node: "clip_loader"
|
| 63 |
vae_loader_node: "vae_loader"
|
| 64 |
|
| 65 |
+
dynamic_krea2_style_reference_chains:
|
| 66 |
+
krea2_style_reference_chain:
|
| 67 |
ksampler_node: "ksampler"
|
| 68 |
pos_prompt_node: "pos_prompt"
|
| 69 |
neg_prompt_node: "neg_prompt"
|
core/pipelines/workflow_recipes/_partials/conditioning/newbie-image.yaml
CHANGED
|
@@ -46,9 +46,9 @@ connections:
|
|
| 46 |
- from: "vae_loader:0"
|
| 47 |
to: "vae_encode:vae"
|
| 48 |
|
| 49 |
-
|
| 50 |
lora_chain:
|
| 51 |
-
template: "
|
| 52 |
output_map:
|
| 53 |
"unet_loader:0": "model"
|
| 54 |
"clip_loader:0": "clip"
|
|
|
|
| 46 |
- from: "vae_loader:0"
|
| 47 |
to: "vae_encode:vae"
|
| 48 |
|
| 49 |
+
dynamic_lora_chains:
|
| 50 |
lora_chain:
|
| 51 |
+
template: "LoraLoader"
|
| 52 |
output_map:
|
| 53 |
"unet_loader:0": "model"
|
| 54 |
"clip_loader:0": "clip"
|
core/pipelines/workflow_recipes/_partials/conditioning/qwen-image.yaml
CHANGED
|
@@ -1,92 +1,91 @@
|
|
| 1 |
-
nodes:
|
| 2 |
-
pos_prompt:
|
| 3 |
-
class_type:
|
| 4 |
-
title: "
|
| 5 |
-
neg_prompt:
|
| 6 |
-
class_type:
|
| 7 |
-
title: "
|
| 8 |
-
unet_loader:
|
| 9 |
-
class_type: UNETLoader
|
| 10 |
-
title: "Load Qwen UNET"
|
| 11 |
-
params:
|
| 12 |
-
weight_dtype: "default"
|
| 13 |
-
vae_loader:
|
| 14 |
-
class_type: VAELoader
|
| 15 |
-
title: "Load Qwen VAE"
|
| 16 |
-
clip_loader:
|
| 17 |
-
class_type: CLIPLoader
|
| 18 |
-
title: "Load Qwen CLIP"
|
| 19 |
-
params:
|
| 20 |
-
type: "qwen_image"
|
| 21 |
-
device: "default"
|
| 22 |
-
model_sampler:
|
| 23 |
-
class_type: ModelSamplingAuraFlow
|
| 24 |
-
title: "ModelSamplingAuraFlow"
|
| 25 |
-
params:
|
| 26 |
-
shift: 3.1
|
| 27 |
-
|
| 28 |
-
connections:
|
| 29 |
-
- from: "unet_loader:0"
|
| 30 |
-
to: "model_sampler:model"
|
| 31 |
-
|
| 32 |
-
- from: "model_sampler:0"
|
| 33 |
-
to: "ksampler:model"
|
| 34 |
-
|
| 35 |
-
- from: "clip_loader:0"
|
| 36 |
-
to: "pos_prompt:clip"
|
| 37 |
-
- from: "clip_loader:0"
|
| 38 |
-
to: "neg_prompt:clip"
|
| 39 |
-
|
| 40 |
-
- from: "vae_loader:0"
|
| 41 |
-
to: "vae_decode:vae"
|
| 42 |
-
- from: "vae_loader:0"
|
| 43 |
-
to: "vae_encode:vae"
|
| 44 |
-
|
| 45 |
-
- from: "pos_prompt:0"
|
| 46 |
-
to: "ksampler:positive"
|
| 47 |
-
- from: "neg_prompt:0"
|
| 48 |
-
to: "ksampler:negative"
|
| 49 |
-
|
| 50 |
-
dynamic_lora_chains:
|
| 51 |
-
lora_chain:
|
| 52 |
-
template: "LoraLoader"
|
| 53 |
-
output_map:
|
| 54 |
-
"unet_loader:0": "model"
|
| 55 |
-
"clip_loader:0": "clip"
|
| 56 |
-
input_map:
|
| 57 |
-
"model": "model"
|
| 58 |
-
"clip": "clip"
|
| 59 |
-
end_input_map:
|
| 60 |
-
"model": ["model_sampler:model"]
|
| 61 |
-
"clip": ["pos_prompt:clip", "neg_prompt:clip"]
|
| 62 |
-
|
| 63 |
-
dynamic_controlnet_chains:
|
| 64 |
-
controlnet_chain:
|
| 65 |
-
template: "ControlNetApplyAdvanced"
|
| 66 |
-
ksampler_node: "ksampler"
|
| 67 |
-
vae_source: "vae_loader:0"
|
| 68 |
-
|
| 69 |
-
dynamic_conditioning_chains:
|
| 70 |
-
conditioning_chain:
|
| 71 |
-
ksampler_node: "ksampler"
|
| 72 |
-
clip_source: "clip_loader:0"
|
| 73 |
-
|
| 74 |
-
dynamic_qwen_image_edit_chains:
|
| 75 |
-
qwen_image_edit_chain:
|
| 76 |
-
ksampler_node: "ksampler"
|
| 77 |
-
pos_prompt_node: "pos_prompt"
|
| 78 |
-
neg_prompt_node: "neg_prompt"
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
vae_name: "vae_loader:vae_name"
|
| 92 |
clip_name: "clip_loader:clip_name"
|
|
|
|
| 1 |
+
nodes:
|
| 2 |
+
pos_prompt:
|
| 3 |
+
class_type: TextEncodeQwenImageEditPlus
|
| 4 |
+
title: "Text Encode Qwen Image Edit Plus (Positive)"
|
| 5 |
+
neg_prompt:
|
| 6 |
+
class_type: TextEncodeQwenImageEditPlus
|
| 7 |
+
title: "Text Encode Qwen Image Edit Plus (Negative)"
|
| 8 |
+
unet_loader:
|
| 9 |
+
class_type: UNETLoader
|
| 10 |
+
title: "Load Qwen UNET"
|
| 11 |
+
params:
|
| 12 |
+
weight_dtype: "default"
|
| 13 |
+
vae_loader:
|
| 14 |
+
class_type: VAELoader
|
| 15 |
+
title: "Load Qwen VAE"
|
| 16 |
+
clip_loader:
|
| 17 |
+
class_type: CLIPLoader
|
| 18 |
+
title: "Load Qwen CLIP"
|
| 19 |
+
params:
|
| 20 |
+
type: "qwen_image"
|
| 21 |
+
device: "default"
|
| 22 |
+
model_sampler:
|
| 23 |
+
class_type: ModelSamplingAuraFlow
|
| 24 |
+
title: "ModelSamplingAuraFlow"
|
| 25 |
+
params:
|
| 26 |
+
shift: 3.1
|
| 27 |
+
|
| 28 |
+
connections:
|
| 29 |
+
- from: "unet_loader:0"
|
| 30 |
+
to: "model_sampler:model"
|
| 31 |
+
|
| 32 |
+
- from: "model_sampler:0"
|
| 33 |
+
to: "ksampler:model"
|
| 34 |
+
|
| 35 |
+
- from: "clip_loader:0"
|
| 36 |
+
to: "pos_prompt:clip"
|
| 37 |
+
- from: "clip_loader:0"
|
| 38 |
+
to: "neg_prompt:clip"
|
| 39 |
+
|
| 40 |
+
- from: "vae_loader:0"
|
| 41 |
+
to: "vae_decode:vae"
|
| 42 |
+
- from: "vae_loader:0"
|
| 43 |
+
to: "vae_encode:vae"
|
| 44 |
+
|
| 45 |
+
- from: "pos_prompt:0"
|
| 46 |
+
to: "ksampler:positive"
|
| 47 |
+
- from: "neg_prompt:0"
|
| 48 |
+
to: "ksampler:negative"
|
| 49 |
+
|
| 50 |
+
dynamic_lora_chains:
|
| 51 |
+
lora_chain:
|
| 52 |
+
template: "LoraLoader"
|
| 53 |
+
output_map:
|
| 54 |
+
"unet_loader:0": "model"
|
| 55 |
+
"clip_loader:0": "clip"
|
| 56 |
+
input_map:
|
| 57 |
+
"model": "model"
|
| 58 |
+
"clip": "clip"
|
| 59 |
+
end_input_map:
|
| 60 |
+
"model": ["model_sampler:model"]
|
| 61 |
+
"clip": ["pos_prompt:clip", "neg_prompt:clip"]
|
| 62 |
+
|
| 63 |
+
dynamic_controlnet_chains:
|
| 64 |
+
controlnet_chain:
|
| 65 |
+
template: "ControlNetApplyAdvanced"
|
| 66 |
+
ksampler_node: "ksampler"
|
| 67 |
+
vae_source: "vae_loader:0"
|
| 68 |
+
|
| 69 |
+
dynamic_conditioning_chains:
|
| 70 |
+
conditioning_chain:
|
| 71 |
+
ksampler_node: "ksampler"
|
| 72 |
+
clip_source: "clip_loader:0"
|
| 73 |
+
|
| 74 |
+
dynamic_qwen_image_edit_chains:
|
| 75 |
+
qwen_image_edit_chain:
|
| 76 |
+
ksampler_node: "ksampler"
|
| 77 |
+
pos_prompt_node: "pos_prompt"
|
| 78 |
+
neg_prompt_node: "neg_prompt"
|
| 79 |
+
vae_loader_node: "vae_loader"
|
| 80 |
+
model_sampler_node: "model_sampler"
|
| 81 |
+
|
| 82 |
+
dynamic_pid_chains:
|
| 83 |
+
pid_chain:
|
| 84 |
+
ksampler_node: "ksampler"
|
| 85 |
+
|
| 86 |
+
ui_map:
|
| 87 |
+
positive_prompt: "pos_prompt:prompt"
|
| 88 |
+
negative_prompt: "neg_prompt:prompt"
|
| 89 |
+
unet_name: "unet_loader:unet_name"
|
| 90 |
+
vae_name: "vae_loader:vae_name"
|
|
|
|
| 91 |
clip_name: "clip_loader:clip_name"
|
core/pipelines/workflow_recipes/{sd_unified_recipe.yaml → unified_recipe.yaml}
RENAMED
|
@@ -1,8 +1,8 @@
|
|
| 1 |
-
imports:
|
| 2 |
-
- "_partials/
|
| 3 |
-
- "_partials/input/{{ task_type }}.yaml"
|
| 4 |
-
- "_partials/conditioning/{{ model_type }}.yaml"
|
| 5 |
-
|
| 6 |
-
connections:
|
| 7 |
-
- from: "latent_source:0"
|
| 8 |
to: "ksampler:latent_image"
|
|
|
|
| 1 |
+
imports:
|
| 2 |
+
- "_partials/_base_sampler.yaml"
|
| 3 |
+
- "_partials/input/{{ task_type }}.yaml"
|
| 4 |
+
- "_partials/conditioning/{{ model_type }}.yaml"
|
| 5 |
+
|
| 6 |
+
connections:
|
| 7 |
+
- from: "latent_source:0"
|
| 8 |
to: "ksampler:latent_image"
|
core/workflow_assembler.py
CHANGED
|
@@ -1,179 +1,165 @@
|
|
| 1 |
-
import yaml
|
| 2 |
-
import os
|
| 3 |
-
import importlib
|
| 4 |
-
from copy import deepcopy
|
| 5 |
-
from comfy_integration.nodes import NODE_CLASS_MAPPINGS
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
self.
|
| 12 |
-
self.
|
| 13 |
-
|
| 14 |
-
self.
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
merged_recipe[
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
if
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
for
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
recipe_chain_types = {key for key in self.recipe if key.startswith('dynamic_')}
|
| 166 |
-
processing_order = [key for key in self.injector_order if key in recipe_chain_types]
|
| 167 |
-
|
| 168 |
-
for chain_type in processing_order:
|
| 169 |
-
injector_func = self.global_injectors.get(chain_type)
|
| 170 |
-
if injector_func:
|
| 171 |
-
for chain_key, chain_def in self.recipe.get(chain_type, {}).items():
|
| 172 |
-
if chain_key in ui_values and ui_values[chain_key]:
|
| 173 |
-
print(f" -> Injecting '{chain_type}' for '{chain_key}'...")
|
| 174 |
-
chain_items = ui_values[chain_key]
|
| 175 |
-
injector_func(self, chain_def, chain_items)
|
| 176 |
-
|
| 177 |
-
print("--- [Assembler] Finished applying injectors ---")
|
| 178 |
-
|
| 179 |
return self.workflow
|
|
|
|
| 1 |
+
import yaml
|
| 2 |
+
import os
|
| 3 |
+
import importlib
|
| 4 |
+
from copy import deepcopy
|
| 5 |
+
from comfy_integration.nodes import NODE_CLASS_MAPPINGS
|
| 6 |
+
from chain_injectors import discover_injectors, get_registered_features
|
| 7 |
+
from core.settings import FEATURES_CONFIG
|
| 8 |
+
|
| 9 |
+
class WorkflowAssembler:
|
| 10 |
+
def __init__(self, recipe_path, dynamic_values=None):
|
| 11 |
+
self.base_path = os.path.dirname(recipe_path)
|
| 12 |
+
self.dynamic_values = dynamic_values or {}
|
| 13 |
+
self.node_counter = 0
|
| 14 |
+
self.workflow = {}
|
| 15 |
+
self.node_map = {}
|
| 16 |
+
|
| 17 |
+
model_type = self.dynamic_values.get('model_type')
|
| 18 |
+
self._load_injector_config(model_type=model_type)
|
| 19 |
+
|
| 20 |
+
self.recipe = self._load_and_merge_recipe(os.path.basename(recipe_path), self.dynamic_values)
|
| 21 |
+
|
| 22 |
+
def _load_injector_config(self, model_type=None):
|
| 23 |
+
self.global_injectors = discover_injectors()
|
| 24 |
+
registered_features = get_registered_features()
|
| 25 |
+
|
| 26 |
+
order = []
|
| 27 |
+
if model_type and model_type in FEATURES_CONFIG:
|
| 28 |
+
enabled_features = FEATURES_CONFIG[model_type].get('enabled_chains', [])
|
| 29 |
+
for feat in enabled_features:
|
| 30 |
+
if feat in registered_features:
|
| 31 |
+
chain_key = registered_features[feat]['chain_type']
|
| 32 |
+
else:
|
| 33 |
+
chain_key = f"dynamic_{feat}_chains"
|
| 34 |
+
if chain_key in self.global_injectors and chain_key not in order:
|
| 35 |
+
order.append(chain_key)
|
| 36 |
+
|
| 37 |
+
for chain_key in self.global_injectors.keys():
|
| 38 |
+
if chain_key not in order:
|
| 39 |
+
order.append(chain_key)
|
| 40 |
+
|
| 41 |
+
self.injector_order = order
|
| 42 |
+
|
| 43 |
+
def _get_unique_id(self):
|
| 44 |
+
self.node_counter += 1
|
| 45 |
+
return str(self.node_counter)
|
| 46 |
+
|
| 47 |
+
def _get_node_template(self, class_type):
|
| 48 |
+
if class_type not in NODE_CLASS_MAPPINGS:
|
| 49 |
+
raise ValueError(f"Node class '{class_type}' not found. Ensure it's correctly imported in comfy_integration/nodes.py.")
|
| 50 |
+
|
| 51 |
+
node_class = NODE_CLASS_MAPPINGS[class_type]
|
| 52 |
+
input_types = node_class.INPUT_TYPES()
|
| 53 |
+
|
| 54 |
+
template = {
|
| 55 |
+
"inputs": {},
|
| 56 |
+
"class_type": class_type,
|
| 57 |
+
"_meta": {"title": node_class.NODE_NAME if hasattr(node_class, 'NODE_NAME') else class_type}
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
all_inputs = {**input_types.get('required', {}), **input_types.get('optional', {})}
|
| 61 |
+
for name, details in all_inputs.items():
|
| 62 |
+
config = details[1] if len(details) > 1 and isinstance(details[1], dict) else {}
|
| 63 |
+
template["inputs"][name] = config.get("default")
|
| 64 |
+
|
| 65 |
+
return template
|
| 66 |
+
|
| 67 |
+
def _load_and_merge_recipe(self, recipe_filename, dynamic_values, search_context_dir=None):
|
| 68 |
+
search_path = search_context_dir or self.base_path
|
| 69 |
+
recipe_path_to_use = os.path.join(search_path, recipe_filename)
|
| 70 |
+
|
| 71 |
+
if not os.path.exists(recipe_path_to_use):
|
| 72 |
+
raise FileNotFoundError(f"Recipe file not found: {recipe_path_to_use}")
|
| 73 |
+
|
| 74 |
+
with open(recipe_path_to_use, 'r', encoding='utf-8') as f:
|
| 75 |
+
content = f.read()
|
| 76 |
+
|
| 77 |
+
for key, value in dynamic_values.items():
|
| 78 |
+
if value is not None:
|
| 79 |
+
content = content.replace(f"{{{{ {key} }}}}", str(value))
|
| 80 |
+
|
| 81 |
+
main_recipe = yaml.safe_load(content)
|
| 82 |
+
|
| 83 |
+
merged_recipe = {'nodes': {}, 'connections': [], 'ui_map': {}}
|
| 84 |
+
for key in self.injector_order:
|
| 85 |
+
if key.startswith('dynamic_'):
|
| 86 |
+
merged_recipe[key] = {}
|
| 87 |
+
|
| 88 |
+
parent_recipe_dir = os.path.dirname(recipe_path_to_use)
|
| 89 |
+
for import_path_template in main_recipe.get('imports', []):
|
| 90 |
+
import_path = import_path_template
|
| 91 |
+
for key, value in dynamic_values.items():
|
| 92 |
+
if value is not None:
|
| 93 |
+
import_path = import_path.replace(f"{{{{ {key} }}}}", str(value))
|
| 94 |
+
|
| 95 |
+
try:
|
| 96 |
+
imported_recipe = self._load_and_merge_recipe(import_path, dynamic_values, search_context_dir=parent_recipe_dir)
|
| 97 |
+
merged_recipe['nodes'].update(imported_recipe.get('nodes', {}))
|
| 98 |
+
merged_recipe['connections'].extend(imported_recipe.get('connections', []))
|
| 99 |
+
merged_recipe['ui_map'].update(imported_recipe.get('ui_map', {}))
|
| 100 |
+
for key in self.injector_order:
|
| 101 |
+
if key in imported_recipe and key.startswith('dynamic_'):
|
| 102 |
+
merged_recipe[key].update(imported_recipe.get(key, {}))
|
| 103 |
+
except FileNotFoundError:
|
| 104 |
+
print(f"Warning: Optional recipe partial '{import_path}' not found. Skipping.")
|
| 105 |
+
|
| 106 |
+
merged_recipe['nodes'].update(main_recipe.get('nodes', {}))
|
| 107 |
+
merged_recipe['connections'].extend(main_recipe.get('connections', []))
|
| 108 |
+
merged_recipe['ui_map'].update(main_recipe.get('ui_map', {}))
|
| 109 |
+
for key in self.injector_order:
|
| 110 |
+
if key in main_recipe and key.startswith('dynamic_'):
|
| 111 |
+
merged_recipe[key].update(main_recipe.get(key, {}))
|
| 112 |
+
|
| 113 |
+
return merged_recipe
|
| 114 |
+
|
| 115 |
+
def assemble(self, ui_values):
|
| 116 |
+
self.ui_values = ui_values
|
| 117 |
+
for name, details in self.recipe['nodes'].items():
|
| 118 |
+
class_type = details['class_type']
|
| 119 |
+
template = self._get_node_template(class_type)
|
| 120 |
+
node_data = deepcopy(template)
|
| 121 |
+
|
| 122 |
+
unique_id = self._get_unique_id()
|
| 123 |
+
self.node_map[name] = unique_id
|
| 124 |
+
|
| 125 |
+
if 'params' in details:
|
| 126 |
+
for param, value in details['params'].items():
|
| 127 |
+
if param in node_data['inputs']:
|
| 128 |
+
node_data['inputs'][param] = value
|
| 129 |
+
|
| 130 |
+
self.workflow[unique_id] = node_data
|
| 131 |
+
|
| 132 |
+
for ui_key, target in self.recipe.get('ui_map', {}).items():
|
| 133 |
+
if ui_key in ui_values and ui_values[ui_key] is not None:
|
| 134 |
+
target_list = target if isinstance(target, list) else [target]
|
| 135 |
+
for t in target_list:
|
| 136 |
+
target_name, target_param = t.split(':')
|
| 137 |
+
if target_name in self.node_map:
|
| 138 |
+
self.workflow[self.node_map[target_name]]['inputs'][target_param] = ui_values[ui_key]
|
| 139 |
+
|
| 140 |
+
for conn in self.recipe.get('connections', []):
|
| 141 |
+
from_name, from_output_idx = conn['from'].split(':')
|
| 142 |
+
to_name, to_input_name = conn['to'].split(':')
|
| 143 |
+
|
| 144 |
+
from_id = self.node_map.get(from_name)
|
| 145 |
+
to_id = self.node_map.get(to_name)
|
| 146 |
+
|
| 147 |
+
if from_id and to_id:
|
| 148 |
+
self.workflow[to_id]['inputs'][to_input_name] = [from_id, int(from_output_idx)]
|
| 149 |
+
|
| 150 |
+
print("--- [Assembler] Applying dynamic injectors ---")
|
| 151 |
+
recipe_chain_types = {key for key in self.recipe if key.startswith('dynamic_')}
|
| 152 |
+
processing_order = [key for key in self.injector_order if key in recipe_chain_types]
|
| 153 |
+
|
| 154 |
+
for chain_type in processing_order:
|
| 155 |
+
injector_func = self.global_injectors.get(chain_type)
|
| 156 |
+
if injector_func:
|
| 157 |
+
for chain_key, chain_def in self.recipe.get(chain_type, {}).items():
|
| 158 |
+
if chain_key in ui_values and ui_values[chain_key]:
|
| 159 |
+
print(f" -> Injecting '{chain_type}' for '{chain_key}'...")
|
| 160 |
+
chain_items = ui_values[chain_key]
|
| 161 |
+
injector_func(self, chain_def, chain_items)
|
| 162 |
+
|
| 163 |
+
print("--- [Assembler] Finished applying injectors ---")
|
| 164 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 165 |
return self.workflow
|
ui/events/change_handlers.py
CHANGED
|
@@ -52,13 +52,13 @@ def make_update_fn(m_comp, cat_comp, cs_comp, ar_comp, width_comp, height_comp,
|
|
| 52 |
architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 53 |
arch_model_type = architectures_dict.get(m_type, {}).get("model_type", m_type.lower().replace(" ", "").replace(".", ""))
|
| 54 |
|
| 55 |
-
arch_features = FEATURES_CONFIG.get(arch_model_type,
|
| 56 |
enabled_chains = arch_features.get('enabled_chains', [])
|
| 57 |
|
| 58 |
if lora_acc: updates[lora_acc] = gr.update(visible=('lora' in enabled_chains))
|
| 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=('
|
| 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))
|
|
@@ -68,11 +68,11 @@ 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 joyai_ref_acc: updates[joyai_ref_acc] = gr.update(visible=('
|
| 72 |
if krea2_identity_edit_acc: updates[krea2_identity_edit_acc] = gr.update(visible=('krea2_identity_edit' in enabled_chains))
|
| 73 |
-
if krea2_reference_edit_acc: updates[krea2_reference_edit_acc] = gr.update(visible=('
|
| 74 |
if qwen_image_edit_acc: updates[qwen_image_edit_acc] = gr.update(visible=('qwen_image_edit' in enabled_chains))
|
| 75 |
-
if boogu_edit_acc: updates[boogu_edit_acc] = gr.update(visible=('
|
| 76 |
if ref_img_acc: updates[ref_img_acc] = gr.update(visible=('reference_image' in enabled_chains))
|
| 77 |
if pid_acc: updates[pid_acc] = gr.update(visible=('pid' in enabled_chains))
|
| 78 |
if vae_acc: updates[vae_acc] = gr.update(visible=('vae' in enabled_chains))
|
|
@@ -188,13 +188,13 @@ def make_model_change_fn(cat_comp_ref, cs_comp, ar_comp, width_comp, height_comp
|
|
| 188 |
architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 189 |
arch_model_type = architectures_dict.get(m_type, {}).get("model_type", m_type.lower().replace(" ", "").replace(".", ""))
|
| 190 |
|
| 191 |
-
arch_features = FEATURES_CONFIG.get(arch_model_type,
|
| 192 |
enabled_chains = arch_features.get('enabled_chains', [])
|
| 193 |
|
| 194 |
if lora_acc: updates[lora_acc] = gr.update(visible=('lora' in enabled_chains))
|
| 195 |
if cn_acc: updates[cn_acc] = gr.update(visible=('controlnet' in enabled_chains))
|
| 196 |
if anima_cn_acc: updates[anima_cn_acc] = gr.update(visible=('anima_controlnet_lllite' in enabled_chains))
|
| 197 |
-
if diffsynth_cn_acc: updates[diffsynth_cn_acc] = gr.update(visible=('
|
| 198 |
if krea2_cn_acc: updates[krea2_cn_acc] = gr.update(visible=('krea2_controlnet' in enabled_chains))
|
| 199 |
if ipa_acc: updates[ipa_acc] = gr.update(visible=('ipadapter' in enabled_chains))
|
| 200 |
if flux1_ipa_acc: updates[flux1_ipa_acc] = gr.update(visible=('flux1_ipadapter' in enabled_chains))
|
|
@@ -204,11 +204,11 @@ def make_model_change_fn(cat_comp_ref, cs_comp, ar_comp, width_comp, height_comp
|
|
| 204 |
if cond_acc: updates[cond_acc] = gr.update(visible=('conditioning' in enabled_chains))
|
| 205 |
if ref_latent_acc: updates[ref_latent_acc] = gr.update(visible=('reference_latent' in enabled_chains))
|
| 206 |
if hidream_o1_ref_acc: updates[hidream_o1_ref_acc] = gr.update(visible=('hidream_o1_reference' in enabled_chains))
|
| 207 |
-
if joyai_ref_acc: updates[joyai_ref_acc] = gr.update(visible=('
|
| 208 |
if krea2_identity_edit_acc: updates[krea2_identity_edit_acc] = gr.update(visible=('krea2_identity_edit' in enabled_chains))
|
| 209 |
-
if krea2_reference_edit_acc: updates[krea2_reference_edit_acc] = gr.update(visible=('
|
| 210 |
if qwen_image_edit_acc: updates[qwen_image_edit_acc] = gr.update(visible=('qwen_image_edit' in enabled_chains))
|
| 211 |
-
if boogu_edit_acc: updates[boogu_edit_acc] = gr.update(visible=('
|
| 212 |
if ref_img_acc: updates[ref_img_acc] = gr.update(visible=('reference_image' in enabled_chains))
|
| 213 |
if pid_acc: updates[pid_acc] = gr.update(visible=('pid' in enabled_chains))
|
| 214 |
if vae_acc: updates[vae_acc] = gr.update(visible=('vae' in enabled_chains))
|
|
|
|
| 52 |
architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 53 |
arch_model_type = architectures_dict.get(m_type, {}).get("model_type", m_type.lower().replace(" ", "").replace(".", ""))
|
| 54 |
|
| 55 |
+
arch_features = FEATURES_CONFIG.get(arch_model_type, {})
|
| 56 |
enabled_chains = arch_features.get('enabled_chains', [])
|
| 57 |
|
| 58 |
if lora_acc: updates[lora_acc] = gr.update(visible=('lora' in enabled_chains))
|
| 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=('diffsynth_controlnet' 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))
|
|
|
|
| 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_image' in enabled_chains))
|
| 72 |
if krea2_identity_edit_acc: updates[krea2_identity_edit_acc] = gr.update(visible=('krea2_identity_edit' in enabled_chains))
|
| 73 |
+
if krea2_reference_edit_acc: updates[krea2_reference_edit_acc] = gr.update(visible=('krea2_style_reference' in enabled_chains))
|
| 74 |
if qwen_image_edit_acc: updates[qwen_image_edit_acc] = gr.update(visible=('qwen_image_edit' in enabled_chains))
|
| 75 |
+
if boogu_edit_acc: updates[boogu_edit_acc] = gr.update(visible=('boogu_image_edit' in enabled_chains))
|
| 76 |
if ref_img_acc: updates[ref_img_acc] = gr.update(visible=('reference_image' in enabled_chains))
|
| 77 |
if pid_acc: updates[pid_acc] = gr.update(visible=('pid' in enabled_chains))
|
| 78 |
if vae_acc: updates[vae_acc] = gr.update(visible=('vae' in enabled_chains))
|
|
|
|
| 188 |
architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 189 |
arch_model_type = architectures_dict.get(m_type, {}).get("model_type", m_type.lower().replace(" ", "").replace(".", ""))
|
| 190 |
|
| 191 |
+
arch_features = FEATURES_CONFIG.get(arch_model_type, {})
|
| 192 |
enabled_chains = arch_features.get('enabled_chains', [])
|
| 193 |
|
| 194 |
if lora_acc: updates[lora_acc] = gr.update(visible=('lora' in enabled_chains))
|
| 195 |
if cn_acc: updates[cn_acc] = gr.update(visible=('controlnet' in enabled_chains))
|
| 196 |
if anima_cn_acc: updates[anima_cn_acc] = gr.update(visible=('anima_controlnet_lllite' in enabled_chains))
|
| 197 |
+
if diffsynth_cn_acc: updates[diffsynth_cn_acc] = gr.update(visible=('diffsynth_controlnet' in enabled_chains))
|
| 198 |
if krea2_cn_acc: updates[krea2_cn_acc] = gr.update(visible=('krea2_controlnet' in enabled_chains))
|
| 199 |
if ipa_acc: updates[ipa_acc] = gr.update(visible=('ipadapter' in enabled_chains))
|
| 200 |
if flux1_ipa_acc: updates[flux1_ipa_acc] = gr.update(visible=('flux1_ipadapter' in enabled_chains))
|
|
|
|
| 204 |
if cond_acc: updates[cond_acc] = gr.update(visible=('conditioning' in enabled_chains))
|
| 205 |
if ref_latent_acc: updates[ref_latent_acc] = gr.update(visible=('reference_latent' in enabled_chains))
|
| 206 |
if hidream_o1_ref_acc: updates[hidream_o1_ref_acc] = gr.update(visible=('hidream_o1_reference' in enabled_chains))
|
| 207 |
+
if joyai_ref_acc: updates[joyai_ref_acc] = gr.update(visible=('joyai_image' in enabled_chains))
|
| 208 |
if krea2_identity_edit_acc: updates[krea2_identity_edit_acc] = gr.update(visible=('krea2_identity_edit' in enabled_chains))
|
| 209 |
+
if krea2_reference_edit_acc: updates[krea2_reference_edit_acc] = gr.update(visible=('krea2_style_reference' in enabled_chains))
|
| 210 |
if qwen_image_edit_acc: updates[qwen_image_edit_acc] = gr.update(visible=('qwen_image_edit' in enabled_chains))
|
| 211 |
+
if boogu_edit_acc: updates[boogu_edit_acc] = gr.update(visible=('boogu_image_edit' in enabled_chains))
|
| 212 |
if ref_img_acc: updates[ref_img_acc] = gr.update(visible=('reference_image' in enabled_chains))
|
| 213 |
if pid_acc: updates[pid_acc] = gr.update(visible=('pid' in enabled_chains))
|
| 214 |
if vae_acc: updates[vae_acc] = gr.update(visible=('vae' in enabled_chains))
|
ui/shared/ui_components.py
CHANGED
|
@@ -15,7 +15,7 @@ default_model_name = list(MODEL_MAP_CHECKPOINT.keys())[0] if MODEL_MAP_CHECKPOIN
|
|
| 15 |
default_m_type = MODEL_TYPE_MAP.get(default_model_name, "SDXL") if default_model_name else "SDXL"
|
| 16 |
default_architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 17 |
default_arch_model_type = default_architectures_dict.get(default_m_type, {}).get("model_type", default_m_type.lower().replace(" ", "").replace(".", ""))
|
| 18 |
-
default_arch_features = FEATURES_CONFIG.get(default_arch_model_type,
|
| 19 |
default_enabled_chains = default_arch_features.get('enabled_chains', [])
|
| 20 |
|
| 21 |
default_vals = MODEL_DEFAULTS_CONFIG.get('Default', {})
|
|
@@ -297,7 +297,7 @@ def create_diffsynth_controlnet_ui(prefix: str, max_units=MAX_CONTROLNETS):
|
|
| 297 |
components = {}
|
| 298 |
key = lambda name: f"{name}_{prefix}"
|
| 299 |
|
| 300 |
-
with gr.Accordion("DiffSynth ControlNet Settings", open=False, visible=('
|
| 301 |
components[key('diffsynth_controlnet_accordion')] = accordion
|
| 302 |
|
| 303 |
cn_rows, images, series, types, strengths, filepaths = [], [], [], [], [], []
|
|
@@ -700,7 +700,7 @@ 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=('
|
| 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 |
|
|
@@ -833,7 +833,7 @@ def create_krea2_reference_edit_ui(prefix: str, max_units=3):
|
|
| 833 |
components = {}
|
| 834 |
key = lambda name: f"{name}_{prefix}"
|
| 835 |
|
| 836 |
-
with gr.Accordion("Krea2 Style Reference Edit Settings", open=False, visible=('
|
| 837 |
components[key('krea2_reference_edit_accordion')] = ref_accordion
|
| 838 |
gr.Markdown("💡 **Tip:** (Krea-2-Turbo recommended) Add style reference images to perform style reference editing.")
|
| 839 |
|
|
@@ -862,7 +862,7 @@ def create_boogu_edit_ui(prefix: str, max_units=10):
|
|
| 862 |
components = {}
|
| 863 |
key = lambda name: f"{name}_{prefix}"
|
| 864 |
|
| 865 |
-
with gr.Accordion("Boogu-Image Edit Settings", open=False, visible=('
|
| 866 |
components[key('boogu_edit_accordion')] = ref_accordion
|
| 867 |
gr.Markdown("💡 **Tip:** (Boogu-Image-Edit-Turbo/Boogu-Image-Edit recommended, Boogu-Image-Edit need set ZeroGPU Duration (s) to 120 ) In txt2img mode, adding a single reference image performs an **Image Edit**, while adding multiple images performs an **Image Combine**.")
|
| 868 |
|
|
|
|
| 15 |
default_m_type = MODEL_TYPE_MAP.get(default_model_name, "SDXL") if default_model_name else "SDXL"
|
| 16 |
default_architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 17 |
default_arch_model_type = default_architectures_dict.get(default_m_type, {}).get("model_type", default_m_type.lower().replace(" ", "").replace(".", ""))
|
| 18 |
+
default_arch_features = FEATURES_CONFIG.get(default_arch_model_type, {})
|
| 19 |
default_enabled_chains = default_arch_features.get('enabled_chains', [])
|
| 20 |
|
| 21 |
default_vals = MODEL_DEFAULTS_CONFIG.get('Default', {})
|
|
|
|
| 297 |
components = {}
|
| 298 |
key = lambda name: f"{name}_{prefix}"
|
| 299 |
|
| 300 |
+
with gr.Accordion("DiffSynth ControlNet Settings", open=False, visible=('diffsynth_controlnet' in default_enabled_chains)) as accordion:
|
| 301 |
components[key('diffsynth_controlnet_accordion')] = accordion
|
| 302 |
|
| 303 |
cn_rows, images, series, types, strengths, filepaths = [], [], [], [], [], []
|
|
|
|
| 700 |
components = {}
|
| 701 |
key = lambda name: f"{name}_{prefix}"
|
| 702 |
|
| 703 |
+
with gr.Accordion("JoyAI Reference Edit Settings", open=False, visible=('joyai_image' 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 |
|
|
|
|
| 833 |
components = {}
|
| 834 |
key = lambda name: f"{name}_{prefix}"
|
| 835 |
|
| 836 |
+
with gr.Accordion("Krea2 Style Reference Edit Settings", open=False, visible=('krea2_style_reference' in default_enabled_chains)) as ref_accordion:
|
| 837 |
components[key('krea2_reference_edit_accordion')] = ref_accordion
|
| 838 |
gr.Markdown("💡 **Tip:** (Krea-2-Turbo recommended) Add style reference images to perform style reference editing.")
|
| 839 |
|
|
|
|
| 862 |
components = {}
|
| 863 |
key = lambda name: f"{name}_{prefix}"
|
| 864 |
|
| 865 |
+
with gr.Accordion("Boogu-Image Edit Settings", open=False, visible=('boogu_image_edit' in default_enabled_chains)) as ref_accordion:
|
| 866 |
components[key('boogu_edit_accordion')] = ref_accordion
|
| 867 |
gr.Markdown("💡 **Tip:** (Boogu-Image-Edit-Turbo/Boogu-Image-Edit recommended, Boogu-Image-Edit need set ZeroGPU Duration (s) to 120 ) In txt2img mode, adding a single reference image performs an **Image Edit**, while adding multiple images performs an **Image Combine**.")
|
| 868 |
|
yaml/image_gen_features.yaml
CHANGED
|
@@ -1,208 +1,200 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
-
|
| 5 |
-
-
|
| 6 |
-
-
|
| 7 |
-
-
|
| 8 |
-
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
-
|
| 31 |
-
- pid
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
enabled_chains:
|
| 35 |
-
- conditioning
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
-
|
| 50 |
-
- conditioning
|
| 51 |
-
-
|
| 52 |
-
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
-
|
| 71 |
-
-
|
| 72 |
-
-
|
| 73 |
-
- vae
|
| 74 |
-
- pid
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
enabled_chains:
|
| 78 |
-
- lora
|
| 79 |
-
-
|
| 80 |
-
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
-
|
| 99 |
-
-
|
| 100 |
-
-
|
| 101 |
-
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
-
|
| 107 |
-
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
enabled_chains:
|
| 126 |
-
- conditioning
|
| 127 |
-
- vae
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
-
|
| 142 |
-
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
-
|
| 148 |
-
-
|
| 149 |
-
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
-
|
| 162 |
-
-
|
| 163 |
-
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
-
|
| 170 |
-
- conditioning
|
| 171 |
-
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
-
|
| 178 |
-
- conditioning
|
| 179 |
-
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
-
|
| 186 |
-
-
|
| 187 |
-
-
|
| 188 |
-
-
|
| 189 |
-
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
-
|
| 196 |
-
-
|
| 197 |
-
-
|
| 198 |
-
-
|
| 199 |
-
-
|
| 200 |
-
|
| 201 |
-
sd15:
|
| 202 |
-
enabled_chains:
|
| 203 |
-
- lora
|
| 204 |
-
- controlnet
|
| 205 |
-
- ipadapter
|
| 206 |
-
- embedding
|
| 207 |
-
- conditioning
|
| 208 |
- vae
|
|
|
|
| 1 |
+
# Feature names in enabled_chains correspond 1-to-1 with chain_injectors/<name>_injector.py
|
| 2 |
+
krea-2:
|
| 3 |
+
enabled_chains:
|
| 4 |
+
- lora
|
| 5 |
+
- krea2_controlnet
|
| 6 |
+
- krea2_identity_edit
|
| 7 |
+
- krea2_style_reference
|
| 8 |
+
- pid
|
| 9 |
+
|
| 10 |
+
mage-flow:
|
| 11 |
+
enabled_chains:
|
| 12 |
+
- reference_image
|
| 13 |
+
|
| 14 |
+
joyai-image:
|
| 15 |
+
enabled_chains:
|
| 16 |
+
- joyai_image
|
| 17 |
+
|
| 18 |
+
boogu-image:
|
| 19 |
+
enabled_chains:
|
| 20 |
+
- lora
|
| 21 |
+
- boogu_image_edit
|
| 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 |
+
- reference_latent
|
| 42 |
+
- conditioning
|
| 43 |
+
- vae
|
| 44 |
+
- pid
|
| 45 |
+
|
| 46 |
+
flux2:
|
| 47 |
+
enabled_chains:
|
| 48 |
+
- lora
|
| 49 |
+
- reference_latent
|
| 50 |
+
- conditioning
|
| 51 |
+
- vae
|
| 52 |
+
- pid
|
| 53 |
+
|
| 54 |
+
ernie-image:
|
| 55 |
+
enabled_chains:
|
| 56 |
+
- conditioning
|
| 57 |
+
- pid
|
| 58 |
+
|
| 59 |
+
z-image:
|
| 60 |
+
enabled_chains:
|
| 61 |
+
- lora
|
| 62 |
+
- diffsynth_controlnet
|
| 63 |
+
- conditioning
|
| 64 |
+
- vae
|
| 65 |
+
- pid
|
| 66 |
+
|
| 67 |
+
qwen-image:
|
| 68 |
+
enabled_chains:
|
| 69 |
+
- lora
|
| 70 |
+
- conditioning
|
| 71 |
+
- controlnet
|
| 72 |
+
- qwen_image_edit
|
| 73 |
+
- vae
|
| 74 |
+
- pid
|
| 75 |
+
|
| 76 |
+
longcat-image:
|
| 77 |
+
enabled_chains:
|
| 78 |
+
- lora
|
| 79 |
+
- conditioning
|
| 80 |
+
- pid
|
| 81 |
+
|
| 82 |
+
cosmos-predict2:
|
| 83 |
+
enabled_chains:
|
| 84 |
+
- conditioning
|
| 85 |
+
- vae
|
| 86 |
+
|
| 87 |
+
anima:
|
| 88 |
+
enabled_chains:
|
| 89 |
+
- lora
|
| 90 |
+
- conditioning
|
| 91 |
+
- anima_controlnet_lllite
|
| 92 |
+
- vae
|
| 93 |
+
- pid
|
| 94 |
+
|
| 95 |
+
newbie-image:
|
| 96 |
+
enabled_chains:
|
| 97 |
+
- lora
|
| 98 |
+
- embedding
|
| 99 |
+
- conditioning
|
| 100 |
+
- vae
|
| 101 |
+
- pid
|
| 102 |
+
|
| 103 |
+
kandinsky-5:
|
| 104 |
+
enabled_chains:
|
| 105 |
+
- conditioning
|
| 106 |
+
- vae
|
| 107 |
+
- pid
|
| 108 |
+
|
| 109 |
+
ovis-image:
|
| 110 |
+
enabled_chains:
|
| 111 |
+
- conditioning
|
| 112 |
+
- vae
|
| 113 |
+
- pid
|
| 114 |
+
|
| 115 |
+
hunyuanimage:
|
| 116 |
+
enabled_chains:
|
| 117 |
+
- conditioning
|
| 118 |
+
- vae
|
| 119 |
+
|
| 120 |
+
chroma1-radiance:
|
| 121 |
+
enabled_chains:
|
| 122 |
+
- conditioning
|
| 123 |
+
|
| 124 |
+
chroma1:
|
| 125 |
+
enabled_chains:
|
| 126 |
+
- conditioning
|
| 127 |
+
- vae
|
| 128 |
+
- pid
|
| 129 |
+
|
| 130 |
+
omnigen2:
|
| 131 |
+
enabled_chains:
|
| 132 |
+
- reference_latent
|
| 133 |
+
- conditioning
|
| 134 |
+
- pid
|
| 135 |
+
|
| 136 |
+
lumina:
|
| 137 |
+
enabled_chains:
|
| 138 |
+
- lora
|
| 139 |
+
- embedding
|
| 140 |
+
- conditioning
|
| 141 |
+
- vae
|
| 142 |
+
- pid
|
| 143 |
+
|
| 144 |
+
hidream-o1:
|
| 145 |
+
enabled_chains:
|
| 146 |
+
- lora
|
| 147 |
+
- conditioning
|
| 148 |
+
- hidream_o1_smoothing
|
| 149 |
+
- hidream_o1_reference
|
| 150 |
+
|
| 151 |
+
hidream-i1:
|
| 152 |
+
enabled_chains:
|
| 153 |
+
- lora
|
| 154 |
+
- conditioning
|
| 155 |
+
- pid
|
| 156 |
+
|
| 157 |
+
flux1:
|
| 158 |
+
enabled_chains:
|
| 159 |
+
- lora
|
| 160 |
+
- flux1_ipadapter
|
| 161 |
+
- conditioning
|
| 162 |
+
- style
|
| 163 |
+
- controlnet
|
| 164 |
+
- vae
|
| 165 |
+
- pid
|
| 166 |
+
|
| 167 |
+
auraflow:
|
| 168 |
+
enabled_chains:
|
| 169 |
+
- lora
|
| 170 |
+
- conditioning
|
| 171 |
+
- vae
|
| 172 |
+
|
| 173 |
+
sd35:
|
| 174 |
+
enabled_chains:
|
| 175 |
+
- lora
|
| 176 |
+
- sd3_ipadapter
|
| 177 |
+
- embedding
|
| 178 |
+
- conditioning
|
| 179 |
+
- controlnet
|
| 180 |
+
- vae
|
| 181 |
+
- pid
|
| 182 |
+
|
| 183 |
+
sdxl:
|
| 184 |
+
enabled_chains:
|
| 185 |
+
- lora
|
| 186 |
+
- ipadapter
|
| 187 |
+
- embedding
|
| 188 |
+
- conditioning
|
| 189 |
+
- controlnet
|
| 190 |
+
- vae
|
| 191 |
+
- pid
|
| 192 |
+
|
| 193 |
+
sd15:
|
| 194 |
+
enabled_chains:
|
| 195 |
+
- lora
|
| 196 |
+
- ipadapter
|
| 197 |
+
- embedding
|
| 198 |
+
- conditioning
|
| 199 |
+
- controlnet
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 200 |
- vae
|
yaml/injectors.yaml
DELETED
|
@@ -1,69 +0,0 @@
|
|
| 1 |
-
injector_definitions:
|
| 2 |
-
dynamic_vae_chains:
|
| 3 |
-
module: "chain_injectors.vae_injector"
|
| 4 |
-
dynamic_lora_chains:
|
| 5 |
-
module: "chain_injectors.lora_injector"
|
| 6 |
-
dynamic_newbie_lora_chains:
|
| 7 |
-
module: "chain_injectors.newbie_lora_injector"
|
| 8 |
-
dynamic_controlnet_chains:
|
| 9 |
-
module: "chain_injectors.controlnet_injector"
|
| 10 |
-
dynamic_krea2_controlnet_chains:
|
| 11 |
-
module: "chain_injectors.krea2_controlnet_injector"
|
| 12 |
-
dynamic_anima_controlnet_lllite_chains:
|
| 13 |
-
module: "chain_injectors.anima_controlnet_lllite_injector"
|
| 14 |
-
dynamic_diffsynth_controlnet_chains:
|
| 15 |
-
module: "chain_injectors.diffsynth_controlnet_injector"
|
| 16 |
-
dynamic_ipadapter_chains:
|
| 17 |
-
module: "chain_injectors.ipadapter_injector"
|
| 18 |
-
dynamic_flux1_ipadapter_chains:
|
| 19 |
-
module: "chain_injectors.flux1_ipadapter_injector"
|
| 20 |
-
dynamic_sd3_ipadapter_chains:
|
| 21 |
-
module: "chain_injectors.sd3_ipadapter_injector"
|
| 22 |
-
dynamic_reference_latent_chains:
|
| 23 |
-
module: "chain_injectors.reference_latent_injector"
|
| 24 |
-
dynamic_conditioning_chains:
|
| 25 |
-
module: "chain_injectors.conditioning_injector"
|
| 26 |
-
dynamic_style_chains:
|
| 27 |
-
module: "chain_injectors.style_injector"
|
| 28 |
-
dynamic_hidream_o1_smoothing_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_krea2_identity_edit_chains:
|
| 35 |
-
module: "chain_injectors.krea2_identity_edit_injector"
|
| 36 |
-
dynamic_krea2_reference_edit_chains:
|
| 37 |
-
module: "chain_injectors.krea2_reference_edit_injector"
|
| 38 |
-
dynamic_qwen_image_edit_chains:
|
| 39 |
-
module: "chain_injectors.qwen_image_edit_injector"
|
| 40 |
-
dynamic_boogu_edit_chains:
|
| 41 |
-
module: "chain_injectors.boogu_edit_injector"
|
| 42 |
-
dynamic_reference_image_chains:
|
| 43 |
-
module: "chain_injectors.reference_image_injector"
|
| 44 |
-
dynamic_pid_chains:
|
| 45 |
-
module: "chain_injectors.pid_injector"
|
| 46 |
-
|
| 47 |
-
injector_order:
|
| 48 |
-
- dynamic_vae_chains
|
| 49 |
-
- dynamic_lora_chains
|
| 50 |
-
- dynamic_newbie_lora_chains
|
| 51 |
-
- dynamic_diffsynth_controlnet_chains
|
| 52 |
-
- dynamic_ipadapter_chains
|
| 53 |
-
- dynamic_flux1_ipadapter_chains
|
| 54 |
-
- dynamic_sd3_ipadapter_chains
|
| 55 |
-
- dynamic_reference_latent_chains
|
| 56 |
-
- dynamic_conditioning_chains
|
| 57 |
-
- dynamic_style_chains
|
| 58 |
-
- dynamic_controlnet_chains
|
| 59 |
-
- dynamic_krea2_controlnet_chains
|
| 60 |
-
- dynamic_krea2_identity_edit_chains
|
| 61 |
-
- dynamic_krea2_reference_edit_chains
|
| 62 |
-
- dynamic_qwen_image_edit_chains
|
| 63 |
-
- dynamic_boogu_edit_chains
|
| 64 |
-
- dynamic_anima_controlnet_lllite_chains
|
| 65 |
-
- dynamic_hidream_o1_smoothing_chains
|
| 66 |
-
- dynamic_hidream_o1_reference_chains
|
| 67 |
-
- dynamic_joyai_reference_chains
|
| 68 |
-
- dynamic_reference_image_chains
|
| 69 |
-
- dynamic_pid_chains
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|