Add FLUX.1, FLUX.2-KV, SD3.5 & additional base model architecture recipes
Browse files- app.py +14 -137
- comfy_integration/nodes.py +5 -0
- comfy_integration/setup.py +36 -13
- core/generation_logic.py +0 -15
- core/model_manager.py +6 -19
- core/pipelines/controlnet_preprocessor.py +0 -143
- core/pipelines/sd_image_pipeline.py +224 -59
- core/pipelines/workflow_recipes/_partials/{_base_sampler.yaml → _base_sampler_sd.yaml} +15 -2
- core/pipelines/workflow_recipes/_partials/conditioning/flux1.yaml +64 -0
- core/pipelines/workflow_recipes/_partials/conditioning/flux2-kv.yaml +104 -0
- core/pipelines/workflow_recipes/_partials/conditioning/flux2.yaml +33 -6
- core/pipelines/workflow_recipes/_partials/conditioning/sd35.yaml +58 -0
- core/pipelines/workflow_recipes/_partials/input/hires_fix.yaml +4 -3
- core/pipelines/workflow_recipes/_partials/input/img2img.yaml +3 -2
- core/pipelines/workflow_recipes/_partials/input/inpaint.yaml +6 -8
- core/pipelines/workflow_recipes/_partials/input/outpaint.yaml +14 -11
- core/pipelines/workflow_recipes/_partials/input/txt2img.yaml +2 -8
- core/pipelines/workflow_recipes/_partials/input/txt2img_chroma_radiance_latent.yaml +11 -0
- core/pipelines/workflow_recipes/_partials/input/txt2img_flux2_latent.yaml +11 -0
- core/pipelines/workflow_recipes/_partials/input/txt2img_hunyuan_latent.yaml +11 -0
- core/pipelines/workflow_recipes/_partials/input/txt2img_latent.yaml +11 -0
- core/pipelines/workflow_recipes/_partials/input/txt2img_sd3_latent.yaml +11 -0
- core/pipelines/workflow_recipes/sd_unified_recipe.yaml +2 -2
- core/settings.py +111 -31
- requirements.txt +10 -9
- ui/events.py +1044 -286
- ui/layout.py +16 -62
- ui/shared/hires_fix_ui.py +27 -17
- ui/shared/img2img_ui.py +27 -18
- ui/shared/inpaint_ui.py +38 -20
- ui/shared/outpaint_ui.py +35 -22
- ui/shared/txt2img_ui.py +26 -11
- ui/shared/ui_components.py +368 -57
- utils/app_utils.py +203 -99
- yaml/constants.yaml +138 -1
- yaml/file_list.yaml +626 -6
- yaml/image_gen_features.yaml +117 -0
- yaml/injectors.yaml +26 -2
- yaml/model_architectures.yaml +65 -1
- yaml/model_defaults.yaml +206 -22
- yaml/model_list.yaml +5 -16
- yaml/private_file_list.yaml +0 -12
app.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
| 1 |
import spaces
|
| 2 |
import os
|
| 3 |
import sys
|
| 4 |
-
import requests
|
| 5 |
import site
|
| 6 |
|
| 7 |
APP_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
@@ -45,106 +44,14 @@ def dummy_gpu_for_startup():
|
|
| 45 |
print("--- [GPU Startup] Startup check passed. ---")
|
| 46 |
return "Startup check passed."
|
| 47 |
|
| 48 |
-
def handle_private_downloads():
|
| 49 |
-
"""
|
| 50 |
-
Checks for a private_file_list.yaml, downloads required models using HF_TOKEN,
|
| 51 |
-
and then clears the token from the environment.
|
| 52 |
-
"""
|
| 53 |
-
import yaml
|
| 54 |
-
from huggingface_hub import hf_hub_download
|
| 55 |
-
from core.settings import (
|
| 56 |
-
DIFFUSION_MODELS_DIR, TEXT_ENCODERS_DIR, VAE_DIR, CHECKPOINT_DIR,
|
| 57 |
-
LORA_DIR, CONTROLNET_DIR, MODEL_PATCHES_DIR, EMBEDDING_DIR
|
| 58 |
-
)
|
| 59 |
-
|
| 60 |
-
print("--- [Startup] Checking for private models to download... ---")
|
| 61 |
-
private_list_path = os.path.join(APP_DIR, 'yaml', 'private_file_list.yaml')
|
| 62 |
-
|
| 63 |
-
if not os.path.exists(private_list_path):
|
| 64 |
-
print("--- [Startup] No private model list found. Skipping. ---")
|
| 65 |
-
if 'HF_TOKEN' in os.environ:
|
| 66 |
-
del os.environ['HF_TOKEN']
|
| 67 |
-
print("--- [Startup] Cleared HF_TOKEN environment variable as it is no longer needed. ---")
|
| 68 |
-
print(f"--- [Startup] Verifying HF_TOKEN after clearing: {os.environ.get('HF_TOKEN')}")
|
| 69 |
-
return
|
| 70 |
-
|
| 71 |
-
try:
|
| 72 |
-
with open(private_list_path, 'r', encoding='utf-8') as f:
|
| 73 |
-
private_files_config = yaml.safe_load(f)
|
| 74 |
-
|
| 75 |
-
if not private_files_config or 'file' not in private_files_config:
|
| 76 |
-
print("--- [Startup] Private model list is empty or malformed. Skipping. ---")
|
| 77 |
-
return
|
| 78 |
-
|
| 79 |
-
category_to_dir_map = {
|
| 80 |
-
"diffusion_models": DIFFUSION_MODELS_DIR,
|
| 81 |
-
"text_encoders": TEXT_ENCODERS_DIR,
|
| 82 |
-
"vae": VAE_DIR,
|
| 83 |
-
"checkpoints": CHECKPOINT_DIR,
|
| 84 |
-
"loras": LORA_DIR,
|
| 85 |
-
"controlnet": CONTROLNET_DIR,
|
| 86 |
-
"model_patches": MODEL_PATCHES_DIR,
|
| 87 |
-
"embeddings": EMBEDDING_DIR,
|
| 88 |
-
}
|
| 89 |
-
|
| 90 |
-
files_to_download = []
|
| 91 |
-
for category, files in private_files_config.get('file', {}).items():
|
| 92 |
-
dest_dir = category_to_dir_map.get(category)
|
| 93 |
-
if not dest_dir:
|
| 94 |
-
print(f"--- [Startup] ⚠️ Unknown category '{category}' in private_file_list.yaml. Skipping. ---")
|
| 95 |
-
continue
|
| 96 |
-
|
| 97 |
-
if isinstance(files, list):
|
| 98 |
-
for file_info in files:
|
| 99 |
-
files_to_download.append((file_info, dest_dir))
|
| 100 |
-
|
| 101 |
-
if not files_to_download:
|
| 102 |
-
print("--- [Startup] No private models configured for download. ---")
|
| 103 |
-
return
|
| 104 |
-
|
| 105 |
-
print(f"--- [Startup] Found {len(files_to_download)} private model(s) to download. Using HF_TOKEN if available. ---")
|
| 106 |
-
|
| 107 |
-
for file_info, dest_dir in files_to_download:
|
| 108 |
-
filename = file_info.get("filename")
|
| 109 |
-
repo_id = file_info.get("repo_id")
|
| 110 |
-
repo_path = file_info.get("repository_file_path", filename)
|
| 111 |
-
|
| 112 |
-
if not all([filename, repo_id]):
|
| 113 |
-
print(f"--- [Startup] ⚠️ Skipping malformed entry in private_file_list.yaml: {file_info} ---")
|
| 114 |
-
continue
|
| 115 |
-
|
| 116 |
-
dest_path = os.path.join(dest_dir, filename)
|
| 117 |
-
if os.path.lexists(dest_path):
|
| 118 |
-
print(f"--- [Startup] ✅ Model '{filename}' already exists. Skipping download. ---")
|
| 119 |
-
continue
|
| 120 |
-
|
| 121 |
-
print(f"--- [Startup] ⏳ Downloading '{filename}' from repo '{repo_id}'... ---")
|
| 122 |
-
try:
|
| 123 |
-
cached_path = hf_hub_download(repo_id=repo_id, filename=repo_path)
|
| 124 |
-
os.makedirs(dest_dir, exist_ok=True)
|
| 125 |
-
os.symlink(cached_path, dest_path)
|
| 126 |
-
print(f"--- [Startup] ✅ Successfully downloaded and linked '{filename}'. ---")
|
| 127 |
-
except Exception as e:
|
| 128 |
-
print(f"--- [Startup] ❌ ERROR: Failed to download '{filename}': {e}")
|
| 129 |
-
print("--- [Startup] ❌ Please ensure your HF_TOKEN is set correctly and has access to the repository. ---")
|
| 130 |
-
|
| 131 |
-
finally:
|
| 132 |
-
if 'HF_TOKEN' in os.environ:
|
| 133 |
-
del os.environ['HF_TOKEN']
|
| 134 |
-
print("--- [Startup] ✅ Cleared HF_TOKEN environment variable. ---")
|
| 135 |
-
print(f"--- [Startup] Verifying HF_TOKEN after clearing: {os.environ.get('HF_TOKEN')}")
|
| 136 |
-
else:
|
| 137 |
-
print("--- [Startup] Note: HF_TOKEN environment variable was not set. Private downloads may fail without it. ---")
|
| 138 |
|
| 139 |
def main():
|
| 140 |
from utils.app_utils import print_welcome_message
|
| 141 |
from scripts import build_sage_attention
|
|
|
|
| 142 |
|
| 143 |
print_welcome_message()
|
| 144 |
|
| 145 |
-
# Handle downloads that require authentication first.
|
| 146 |
-
handle_private_downloads()
|
| 147 |
-
|
| 148 |
print("--- [Setup] Attempting to build and install SageAttention... ---")
|
| 149 |
try:
|
| 150 |
build_sage_attention.install_sage_attention()
|
|
@@ -152,7 +59,9 @@ def main():
|
|
| 152 |
except Exception as e:
|
| 153 |
print(f"--- [Setup] ❌ SageAttention installation failed: {e}. Continuing with default attention. ---")
|
| 154 |
|
| 155 |
-
|
|
|
|
|
|
|
| 156 |
print("--- [Setup] Reloading site-packages to detect newly installed packages... ---")
|
| 157 |
try:
|
| 158 |
site.main()
|
|
@@ -160,52 +69,20 @@ def main():
|
|
| 160 |
except Exception as e:
|
| 161 |
print(f"--- [Setup] ⚠️ Warning: Could not fully reload site-packages: {e} ---")
|
| 162 |
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
from
|
| 170 |
-
|
| 171 |
-
def check_all_model_urls_on_startup():
|
| 172 |
-
print("--- [Setup] Checking all model URL validity (one-time check) ---")
|
| 173 |
-
for display_name, model_info in ALL_MODEL_MAP.items():
|
| 174 |
-
_, components, _, _ = model_info
|
| 175 |
-
if not components: continue
|
| 176 |
-
|
| 177 |
-
for filename in components.values():
|
| 178 |
-
download_info = ALL_FILE_DOWNLOAD_MAP.get(filename, {})
|
| 179 |
-
repo_id = download_info.get('repo_id')
|
| 180 |
-
if not repo_id: continue
|
| 181 |
-
|
| 182 |
-
repo_file_path = download_info.get('repository_file_path', filename)
|
| 183 |
-
url = f"https://huggingface.co/{repo_id}/resolve/main/{repo_file_path}"
|
| 184 |
-
|
| 185 |
-
try:
|
| 186 |
-
response = requests.head(url, timeout=5, allow_redirects=True)
|
| 187 |
-
if response.status_code >= 400:
|
| 188 |
-
print(f"❌ Invalid URL for '{display_name}' component '{filename}': {url} (Status: {response.status_code})")
|
| 189 |
-
shared_state.INVALID_MODEL_URLS[display_name] = True
|
| 190 |
-
break
|
| 191 |
-
except requests.RequestException as e:
|
| 192 |
-
print(f"❌ URL check failed for '{display_name}' component '{filename}': {e}")
|
| 193 |
-
shared_state.INVALID_MODEL_URLS[display_name] = True
|
| 194 |
-
break
|
| 195 |
-
print("--- [Setup] ✅ Finished checking model URLs. ---")
|
| 196 |
|
| 197 |
print("--- Starting Application Setup ---")
|
| 198 |
|
| 199 |
-
|
|
|
|
|
|
|
| 200 |
|
| 201 |
-
check_all_model_urls_on_startup()
|
| 202 |
-
|
| 203 |
-
print("--- Building ControlNet preprocessor maps ---")
|
| 204 |
-
from core.generation_logic import build_reverse_map
|
| 205 |
-
build_reverse_map()
|
| 206 |
-
build_preprocessor_model_map()
|
| 207 |
-
build_preprocessor_parameter_map()
|
| 208 |
-
print("--- ✅ ControlNet preprocessor setup complete. ---")
|
| 209 |
|
| 210 |
print("--- Environment configured. Proceeding with module imports. ---")
|
| 211 |
from ui.layout import build_ui
|
|
|
|
| 1 |
import spaces
|
| 2 |
import os
|
| 3 |
import sys
|
|
|
|
| 4 |
import site
|
| 5 |
|
| 6 |
APP_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
| 44 |
print("--- [GPU Startup] Startup check passed. ---")
|
| 45 |
return "Startup check passed."
|
| 46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
|
| 48 |
def main():
|
| 49 |
from utils.app_utils import print_welcome_message
|
| 50 |
from scripts import build_sage_attention
|
| 51 |
+
from comfy_integration import setup as setup_comfyui
|
| 52 |
|
| 53 |
print_welcome_message()
|
| 54 |
|
|
|
|
|
|
|
|
|
|
| 55 |
print("--- [Setup] Attempting to build and install SageAttention... ---")
|
| 56 |
try:
|
| 57 |
build_sage_attention.install_sage_attention()
|
|
|
|
| 59 |
except Exception as e:
|
| 60 |
print(f"--- [Setup] ❌ SageAttention installation failed: {e}. Continuing with default attention. ---")
|
| 61 |
|
| 62 |
+
print("--- [Setup] Starting ComfyUI initialization ---")
|
| 63 |
+
setup_comfyui.initialize_comfyui()
|
| 64 |
+
|
| 65 |
print("--- [Setup] Reloading site-packages to detect newly installed packages... ---")
|
| 66 |
try:
|
| 67 |
site.main()
|
|
|
|
| 69 |
except Exception as e:
|
| 70 |
print(f"--- [Setup] ⚠️ Warning: Could not fully reload site-packages: {e} ---")
|
| 71 |
|
| 72 |
+
print("--- Initiating GPU Startup Check & SageAttention Patch ---")
|
| 73 |
+
try:
|
| 74 |
+
dummy_gpu_for_startup()
|
| 75 |
+
except Exception as e:
|
| 76 |
+
print(f"--- [GPU Startup] ⚠️ Warning: Startup check failed: {e} ---")
|
| 77 |
+
|
| 78 |
+
from utils.app_utils import load_ipadapter_presets
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
|
| 80 |
print("--- Starting Application Setup ---")
|
| 81 |
|
| 82 |
+
print("--- Loading IPAdapter presets ---")
|
| 83 |
+
load_ipadapter_presets()
|
| 84 |
+
print("--- ✅ IPAdapter setup complete. ---")
|
| 85 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
|
| 87 |
print("--- Environment configured. Proceeding with module imports. ---")
|
| 88 |
from ui.layout import build_ui
|
comfy_integration/nodes.py
CHANGED
|
@@ -23,6 +23,11 @@ CLIPTextEncodeSDXL = NODE_CLASS_MAPPINGS['CLIPTextEncodeSDXL']
|
|
| 23 |
LoraLoader = NODE_CLASS_MAPPINGS['LoraLoader']
|
| 24 |
CLIPSetLastLayer = NODE_CLASS_MAPPINGS['CLIPSetLastLayer']
|
| 25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
try:
|
| 27 |
KSamplerNode = NODE_CLASS_MAPPINGS['KSampler']
|
| 28 |
SAMPLER_CHOICES = KSamplerNode.INPUT_TYPES()["required"]["sampler_name"][0]
|
|
|
|
| 23 |
LoraLoader = NODE_CLASS_MAPPINGS['LoraLoader']
|
| 24 |
CLIPSetLastLayer = NODE_CLASS_MAPPINGS['CLIPSetLastLayer']
|
| 25 |
|
| 26 |
+
if 'EmptyHunyuanImageLatent' in NODE_CLASS_MAPPINGS:
|
| 27 |
+
EmptyHunyuanImageLatent = NODE_CLASS_MAPPINGS['EmptyHunyuanImageLatent']
|
| 28 |
+
else:
|
| 29 |
+
print("⚠️ Warning: 'EmptyHunyuanImageLatent' not found in NODE_CLASS_MAPPINGS. HunyuanImage txt2img may fail if this node is required.")
|
| 30 |
+
|
| 31 |
try:
|
| 32 |
KSamplerNode = NODE_CLASS_MAPPINGS['KSampler']
|
| 33 |
SAMPLER_CHOICES = KSamplerNode.INPUT_TYPES()["required"]["sampler_name"][0]
|
comfy_integration/setup.py
CHANGED
|
@@ -39,14 +39,40 @@ def initialize_comfyui():
|
|
| 39 |
except OSError as e:
|
| 40 |
print(f"⚠️ Could not remove temporary directory '{COMFYUI_TEMP_DIR}': {e}")
|
| 41 |
|
|
|
|
| 42 |
print("--- Cloning third-party extensions for ComfyUI ---")
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
|
|
|
|
|
|
| 47 |
else:
|
| 48 |
-
print("✅
|
| 49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
|
| 51 |
print(f"✅ Current working directory is: {os.getcwd()}")
|
| 52 |
|
|
@@ -55,13 +81,10 @@ def initialize_comfyui():
|
|
| 55 |
|
| 56 |
print("✅ ComfyUI initialized with default attention mechanism.")
|
| 57 |
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
os.makedirs(os.path.join(APP_DIR, CONTROLNET_DIR), exist_ok=True)
|
| 62 |
-
os.makedirs(os.path.join(APP_DIR, MODEL_PATCHES_DIR), exist_ok=True)
|
| 63 |
-
os.makedirs(os.path.join(APP_DIR, DIFFUSION_MODELS_DIR), exist_ok=True)
|
| 64 |
-
os.makedirs(os.path.join(APP_DIR, VAE_DIR), exist_ok=True)
|
| 65 |
-
os.makedirs(os.path.join(APP_DIR, TEXT_ENCODERS_DIR), exist_ok=True)
|
| 66 |
os.makedirs(os.path.join(APP_DIR, INPUT_DIR), exist_ok=True)
|
|
|
|
|
|
|
| 67 |
print("✅ All required model directories are present.")
|
|
|
|
| 39 |
except OSError as e:
|
| 40 |
print(f"⚠️ Could not remove temporary directory '{COMFYUI_TEMP_DIR}': {e}")
|
| 41 |
|
| 42 |
+
|
| 43 |
print("--- Cloning third-party extensions for ComfyUI ---")
|
| 44 |
+
|
| 45 |
+
# 1. ComfyUI_IPAdapter_plus
|
| 46 |
+
ipadapter_plus_path = os.path.join(APP_DIR, "custom_nodes", "ComfyUI_IPAdapter_plus")
|
| 47 |
+
if not os.path.exists(ipadapter_plus_path):
|
| 48 |
+
os.system(f"git clone https://github.com/cubiq/ComfyUI_IPAdapter_plus.git {ipadapter_plus_path}")
|
| 49 |
+
print("✅ ComfyUI_IPAdapter_plus extension cloned.")
|
| 50 |
else:
|
| 51 |
+
print("✅ ComfyUI_IPAdapter_plus extension already exists.")
|
| 52 |
|
| 53 |
+
# 2. ComfyUI-InstantX-IPAdapter-SD3
|
| 54 |
+
ipadapter_plus_path = os.path.join(APP_DIR, "custom_nodes", "ComfyUI-InstantX-IPAdapter-SD3")
|
| 55 |
+
if not os.path.exists(ipadapter_plus_path):
|
| 56 |
+
os.system(f"git clone https://github.com/Slickytail/ComfyUI-InstantX-IPAdapter-SD3.git {ipadapter_plus_path}")
|
| 57 |
+
print("✅ ComfyUI-InstantX-IPAdapter-SD3 extension cloned.")
|
| 58 |
+
else:
|
| 59 |
+
print("✅ ComfyUI-InstantX-IPAdapter-SD3 extension already exists.")
|
| 60 |
+
|
| 61 |
+
# 3. ComfyUI-IPAdapter-Flux
|
| 62 |
+
ipadapter_flux_path = os.path.join(APP_DIR, "custom_nodes", "ComfyUI-IPAdapter-Flux")
|
| 63 |
+
if not os.path.exists(ipadapter_flux_path):
|
| 64 |
+
os.system(f"git clone https://github.com/Shakker-Labs/ComfyUI-IPAdapter-Flux.git {ipadapter_flux_path}")
|
| 65 |
+
print("✅ ComfyUI-IPAdapter-Flux extension cloned.")
|
| 66 |
+
else:
|
| 67 |
+
print("✅ ComfyUI-IPAdapter-Flux extension already exists.")
|
| 68 |
+
|
| 69 |
+
# 4. ComfyUI-Newbie-Nodes
|
| 70 |
+
newbie_nodes_path = os.path.join(APP_DIR, "custom_nodes", "ComfyUI-Newbie-Nodes")
|
| 71 |
+
if not os.path.exists(newbie_nodes_path):
|
| 72 |
+
os.system(f"git clone https://github.com/NewBieAI-Lab/ComfyUI-Newbie-Nodes.git {newbie_nodes_path}")
|
| 73 |
+
print("✅ ComfyUI-Newbie-Nodes extension cloned.")
|
| 74 |
+
else:
|
| 75 |
+
print("✅ ComfyUI-Newbie-Nodes extension already exists.")
|
| 76 |
|
| 77 |
print(f"✅ Current working directory is: {os.getcwd()}")
|
| 78 |
|
|
|
|
| 81 |
|
| 82 |
print("✅ ComfyUI initialized with default attention mechanism.")
|
| 83 |
|
| 84 |
+
for dir_path in CATEGORY_TO_DIR_MAP.values():
|
| 85 |
+
os.makedirs(os.path.join(APP_DIR, dir_path), exist_ok=True)
|
| 86 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
os.makedirs(os.path.join(APP_DIR, INPUT_DIR), exist_ok=True)
|
| 88 |
+
os.makedirs(os.path.join(APP_DIR, OUTPUT_DIR), exist_ok=True)
|
| 89 |
+
|
| 90 |
print("✅ All required model directories are present.")
|
core/generation_logic.py
CHANGED
|
@@ -1,25 +1,10 @@
|
|
| 1 |
from typing import Any, Dict
|
| 2 |
import gradio as gr
|
| 3 |
|
| 4 |
-
from core.pipelines.controlnet_preprocessor import ControlNetPreprocessorPipeline
|
| 5 |
from core.pipelines.sd_image_pipeline import SdImagePipeline
|
| 6 |
|
| 7 |
-
controlnet_preprocessor_pipeline = ControlNetPreprocessorPipeline()
|
| 8 |
sd_image_pipeline = SdImagePipeline()
|
| 9 |
|
| 10 |
|
| 11 |
-
def build_reverse_map():
|
| 12 |
-
from nodes import NODE_DISPLAY_NAME_MAPPINGS
|
| 13 |
-
import core.pipelines.controlnet_preprocessor as cn_module
|
| 14 |
-
|
| 15 |
-
if cn_module.REVERSE_DISPLAY_NAME_MAP is None:
|
| 16 |
-
cn_module.REVERSE_DISPLAY_NAME_MAP = {v: k for k, v in NODE_DISPLAY_NAME_MAPPINGS.items()}
|
| 17 |
-
if "Semantic Segmentor (legacy, alias for UniFormer)" not in cn_module.REVERSE_DISPLAY_NAME_MAP:
|
| 18 |
-
cn_module.REVERSE_DISPLAY_NAME_MAP["Semantic Segmentor (legacy, alias for UniFormer)"] = "SemSegPreprocessor"
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
def run_cn_preprocessor_entry(*args, **kwargs):
|
| 22 |
-
return controlnet_preprocessor_pipeline.run(*args, **kwargs)
|
| 23 |
-
|
| 24 |
def generate_image_wrapper(ui_inputs: dict, progress=gr.Progress(track_tqdm=True)):
|
| 25 |
return sd_image_pipeline.run(ui_inputs=ui_inputs, progress=progress)
|
|
|
|
| 1 |
from typing import Any, Dict
|
| 2 |
import gradio as gr
|
| 3 |
|
|
|
|
| 4 |
from core.pipelines.sd_image_pipeline import SdImagePipeline
|
| 5 |
|
|
|
|
| 6 |
sd_image_pipeline = SdImagePipeline()
|
| 7 |
|
| 8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
def generate_image_wrapper(ui_inputs: dict, progress=gr.Progress(track_tqdm=True)):
|
| 10 |
return sd_image_pipeline.run(ui_inputs=ui_inputs, progress=progress)
|
core/model_manager.py
CHANGED
|
@@ -1,9 +1,8 @@
|
|
| 1 |
import gc
|
| 2 |
from typing import List
|
| 3 |
import gradio as gr
|
| 4 |
-
|
| 5 |
-
from core.settings import ALL_MODEL_MAP
|
| 6 |
from utils.app_utils import _ensure_model_downloaded
|
|
|
|
| 7 |
|
| 8 |
class ModelManager:
|
| 9 |
_instance = None
|
|
@@ -21,25 +20,13 @@ class ModelManager:
|
|
| 21 |
|
| 22 |
def ensure_models_downloaded(self, required_models: List[str], progress):
|
| 23 |
print(f"--- [ModelManager] Ensuring models are downloaded: {required_models} ---")
|
| 24 |
-
|
| 25 |
-
files_to_download = set()
|
| 26 |
-
for display_name in required_models:
|
| 27 |
-
if display_name in ALL_MODEL_MAP:
|
| 28 |
-
_, components, _, _ = ALL_MODEL_MAP[display_name]
|
| 29 |
-
for component_file in components.values():
|
| 30 |
-
files_to_download.add(component_file)
|
| 31 |
-
|
| 32 |
-
files_to_download = list(files_to_download)
|
| 33 |
-
total_files = len(files_to_download)
|
| 34 |
-
|
| 35 |
-
for i, filename in enumerate(files_to_download):
|
| 36 |
if progress and hasattr(progress, '__call__'):
|
| 37 |
-
progress(i /
|
| 38 |
try:
|
| 39 |
-
_ensure_model_downloaded(
|
| 40 |
except Exception as e:
|
| 41 |
-
raise gr.Error(f"Failed to download model
|
| 42 |
-
|
| 43 |
print(f"--- [ModelManager] ✅ All required models are present on disk. ---")
|
| 44 |
-
|
| 45 |
model_manager = ModelManager()
|
|
|
|
| 1 |
import gc
|
| 2 |
from typing import List
|
| 3 |
import gradio as gr
|
|
|
|
|
|
|
| 4 |
from utils.app_utils import _ensure_model_downloaded
|
| 5 |
+
from core.settings import ALL_MODEL_MAP
|
| 6 |
|
| 7 |
class ModelManager:
|
| 8 |
_instance = None
|
|
|
|
| 20 |
|
| 21 |
def ensure_models_downloaded(self, required_models: List[str], progress):
|
| 22 |
print(f"--- [ModelManager] Ensuring models are downloaded: {required_models} ---")
|
| 23 |
+
for i, display_name in enumerate(required_models):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
if progress and hasattr(progress, '__call__'):
|
| 25 |
+
progress(i / max(len(required_models), 1), desc=f"Checking file: {display_name}")
|
| 26 |
try:
|
| 27 |
+
_ensure_model_downloaded(display_name, progress)
|
| 28 |
except Exception as e:
|
| 29 |
+
raise gr.Error(f"Failed to download model '{display_name}'. Reason: {e}")
|
|
|
|
| 30 |
print(f"--- [ModelManager] ✅ All required models are present on disk. ---")
|
| 31 |
+
|
| 32 |
model_manager = ModelManager()
|
core/pipelines/controlnet_preprocessor.py
DELETED
|
@@ -1,143 +0,0 @@
|
|
| 1 |
-
from typing import Dict, Any, List
|
| 2 |
-
import imageio
|
| 3 |
-
import tempfile
|
| 4 |
-
import numpy as np
|
| 5 |
-
import torch
|
| 6 |
-
import gradio as gr
|
| 7 |
-
from PIL import Image
|
| 8 |
-
import spaces
|
| 9 |
-
|
| 10 |
-
from .base_pipeline import BasePipeline
|
| 11 |
-
from comfy_integration.nodes import NODE_CLASS_MAPPINGS
|
| 12 |
-
from nodes import NODE_DISPLAY_NAME_MAPPINGS
|
| 13 |
-
from utils.app_utils import get_value_at_index
|
| 14 |
-
|
| 15 |
-
REVERSE_DISPLAY_NAME_MAP = None
|
| 16 |
-
CPU_ONLY_PREPROCESSORS = {
|
| 17 |
-
"Binary Lines", "Canny Edge", "Color Pallete", "Fake Scribble Lines (aka scribble_hed)",
|
| 18 |
-
"Image Intensity", "Image Luminance", "Inpaint Preprocessor", "PyraCanny", "Scribble Lines",
|
| 19 |
-
"Scribble XDoG Lines", "Standard Lineart", "Content Shuffle", "Tile"
|
| 20 |
-
}
|
| 21 |
-
|
| 22 |
-
def run_node_by_function_name(node_instance: Any, **kwargs) -> Any:
|
| 23 |
-
node_class = type(node_instance)
|
| 24 |
-
function_name = getattr(node_class, 'FUNCTION', None)
|
| 25 |
-
if not function_name:
|
| 26 |
-
raise AttributeError(f"Node class '{node_class.__name__}' is missing the required 'FUNCTION' attribute.")
|
| 27 |
-
execution_method = getattr(node_instance, function_name, None)
|
| 28 |
-
if not callable(execution_method):
|
| 29 |
-
raise AttributeError(f"Method '{function_name}' not found or not callable on node '{node_class.__name__}'.")
|
| 30 |
-
return execution_method(**kwargs)
|
| 31 |
-
|
| 32 |
-
class ControlNetPreprocessorPipeline(BasePipeline):
|
| 33 |
-
def get_required_models(self, **kwargs) -> List[str]:
|
| 34 |
-
return []
|
| 35 |
-
|
| 36 |
-
def _gpu_logic(
|
| 37 |
-
self, pil_images: List[Image.Image], preprocessor_name: str, model_name: str,
|
| 38 |
-
params: Dict[str, Any], progress=gr.Progress(track_tqdm=True)
|
| 39 |
-
) -> List[Image.Image]:
|
| 40 |
-
global REVERSE_DISPLAY_NAME_MAP
|
| 41 |
-
if REVERSE_DISPLAY_NAME_MAP is None:
|
| 42 |
-
raise RuntimeError("REVERSE_DISPLAY_NAME_MAP has not been initialized. `build_reverse_map` must be called on startup.")
|
| 43 |
-
|
| 44 |
-
class_name = REVERSE_DISPLAY_NAME_MAP.get(preprocessor_name)
|
| 45 |
-
if not class_name or class_name not in NODE_CLASS_MAPPINGS:
|
| 46 |
-
raise ValueError(f"Preprocessor '{preprocessor_name}' not found.")
|
| 47 |
-
|
| 48 |
-
preprocessor_instance = NODE_CLASS_MAPPINGS[class_name]()
|
| 49 |
-
call_args = {**params, 'ckpt_name': model_name}
|
| 50 |
-
|
| 51 |
-
processed_pil_images = []
|
| 52 |
-
total_frames = len(pil_images)
|
| 53 |
-
|
| 54 |
-
for i, frame_pil in enumerate(pil_images):
|
| 55 |
-
progress(i / total_frames, desc=f"Processing frame {i+1}/{total_frames} with {preprocessor_name}...")
|
| 56 |
-
|
| 57 |
-
frame_tensor = torch.from_numpy(np.array(frame_pil).astype(np.float32) / 255.0).unsqueeze(0)
|
| 58 |
-
|
| 59 |
-
resolution_arg = {'resolution': max(frame_tensor.shape[2], frame_tensor.shape[3])}
|
| 60 |
-
|
| 61 |
-
result_tuple = run_node_by_function_name(
|
| 62 |
-
preprocessor_instance,
|
| 63 |
-
image=frame_tensor,
|
| 64 |
-
**resolution_arg,
|
| 65 |
-
**call_args
|
| 66 |
-
)
|
| 67 |
-
|
| 68 |
-
processed_tensor = get_value_at_index(result_tuple, 0)
|
| 69 |
-
processed_np = (processed_tensor.squeeze(0).cpu().numpy().clip(0, 1) * 255.0).astype(np.uint8)
|
| 70 |
-
processed_pil_images.append(Image.fromarray(processed_np))
|
| 71 |
-
|
| 72 |
-
return processed_pil_images
|
| 73 |
-
|
| 74 |
-
def run(self, input_type, image_input, video_input, preprocessor_name, model_name, zero_gpu_duration, *args, progress=gr.Progress(track_tqdm=True)):
|
| 75 |
-
from utils import app_utils
|
| 76 |
-
pil_images, is_video, fps = [], False, 30
|
| 77 |
-
|
| 78 |
-
progress(0, desc="Reading input file...")
|
| 79 |
-
if input_type == "Image":
|
| 80 |
-
if image_input is None: raise gr.Error("Please provide an input image.")
|
| 81 |
-
pil_images = [image_input]
|
| 82 |
-
elif input_type == "Video":
|
| 83 |
-
if video_input is None: raise gr.Error("Please provide an input video.")
|
| 84 |
-
try:
|
| 85 |
-
video_reader = imageio.get_reader(video_input)
|
| 86 |
-
meta = video_reader.get_meta_data()
|
| 87 |
-
fps = meta.get('fps', 30)
|
| 88 |
-
pil_images = [Image.fromarray(frame) for frame in video_reader]
|
| 89 |
-
is_video = True
|
| 90 |
-
video_reader.close()
|
| 91 |
-
except Exception as e: raise gr.Error(f"Failed to read video file: {e}")
|
| 92 |
-
else:
|
| 93 |
-
raise gr.Error("Invalid input type selected.")
|
| 94 |
-
|
| 95 |
-
if not pil_images: raise gr.Error("Could not extract any frames from the input.")
|
| 96 |
-
|
| 97 |
-
if app_utils.PREPROCESSOR_PARAMETER_MAP is None:
|
| 98 |
-
raise RuntimeError("Preprocessor parameter map is not built. Check startup logs.")
|
| 99 |
-
|
| 100 |
-
params_config = app_utils.PREPROCESSOR_PARAMETER_MAP.get(preprocessor_name, [])
|
| 101 |
-
sliders_params = [p for p in params_config if p['type'] in ["INT", "FLOAT"]]
|
| 102 |
-
dropdown_params = [p for p in params_config if isinstance(p['type'], list)]
|
| 103 |
-
checkbox_params = [p for p in params_config if p['type'] == "BOOLEAN"]
|
| 104 |
-
ordered_params_config = sliders_params + dropdown_params + checkbox_params
|
| 105 |
-
param_names = [p['name'] for p in ordered_params_config]
|
| 106 |
-
provided_params = {param_names[i]: args[i] for i in range(len(param_names))}
|
| 107 |
-
|
| 108 |
-
if preprocessor_name not in CPU_ONLY_PREPROCESSORS:
|
| 109 |
-
print(f"--- '{preprocessor_name}' requires GPU, requesting ZeroGPU. ---")
|
| 110 |
-
try:
|
| 111 |
-
processed_pil_images = self._execute_gpu_logic(
|
| 112 |
-
self._gpu_logic,
|
| 113 |
-
duration=zero_gpu_duration,
|
| 114 |
-
default_duration=60,
|
| 115 |
-
task_name=f"Preprocessor '{preprocessor_name}'",
|
| 116 |
-
pil_images=pil_images,
|
| 117 |
-
preprocessor_name=preprocessor_name,
|
| 118 |
-
model_name=model_name,
|
| 119 |
-
params=provided_params,
|
| 120 |
-
progress=progress
|
| 121 |
-
)
|
| 122 |
-
except Exception as e:
|
| 123 |
-
import traceback; traceback.print_exc()
|
| 124 |
-
raise gr.Error(f"Failed to run preprocessor '{preprocessor_name}' on GPU: {e}")
|
| 125 |
-
else:
|
| 126 |
-
print(f"--- Running '{preprocessor_name}' on CPU, no ZeroGPU requested. ---")
|
| 127 |
-
try:
|
| 128 |
-
processed_pil_images = self._gpu_logic(pil_images, preprocessor_name, model_name, provided_params, progress=progress)
|
| 129 |
-
except Exception as e:
|
| 130 |
-
import traceback; traceback.print_exc()
|
| 131 |
-
raise gr.Error(f"Failed to run preprocessor '{preprocessor_name}' on CPU: {e}")
|
| 132 |
-
|
| 133 |
-
if not processed_pil_images: raise gr.Error("Processing returned no frames.")
|
| 134 |
-
|
| 135 |
-
progress(0.9, desc="Finalizing output...")
|
| 136 |
-
if is_video:
|
| 137 |
-
frames_np = [np.array(img) for img in processed_pil_images]
|
| 138 |
-
frames_tensor = torch.from_numpy(np.stack(frames_np)).to(torch.float32) / 255.0
|
| 139 |
-
video_path = self._encode_video_from_frames(frames_tensor, fps, progress)
|
| 140 |
-
return [video_path]
|
| 141 |
-
else:
|
| 142 |
-
progress(1.0, desc="Done!")
|
| 143 |
-
return processed_pil_images
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/pipelines/sd_image_pipeline.py
CHANGED
|
@@ -11,12 +11,20 @@ import numpy as np
|
|
| 11 |
from .base_pipeline import BasePipeline
|
| 12 |
from core.settings import *
|
| 13 |
from comfy_integration.nodes import *
|
| 14 |
-
from utils.app_utils import get_value_at_index, sanitize_prompt, get_lora_path, get_embedding_path, ensure_controlnet_model_downloaded, sanitize_filename
|
| 15 |
from core.workflow_assembler import WorkflowAssembler
|
| 16 |
|
| 17 |
class SdImagePipeline(BasePipeline):
|
| 18 |
def get_required_models(self, model_display_name: str, **kwargs) -> List[str]:
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
def _topological_sort(self, workflow: Dict[str, Any]) -> List[str]:
|
| 22 |
graph = defaultdict(list)
|
|
@@ -47,7 +55,6 @@ class SdImagePipeline(BasePipeline):
|
|
| 47 |
|
| 48 |
return sorted_nodes
|
| 49 |
|
| 50 |
-
|
| 51 |
def _execute_workflow(self, workflow: Dict[str, Any], initial_objects: Dict[str, Any]):
|
| 52 |
with torch.no_grad():
|
| 53 |
computed_outputs = initial_objects
|
|
@@ -119,7 +126,7 @@ class SdImagePipeline(BasePipeline):
|
|
| 119 |
progress(0.4, desc="Executing workflow...")
|
| 120 |
|
| 121 |
initial_objects = {}
|
| 122 |
-
|
| 123 |
decoded_images_tensor = self._execute_workflow(workflow, initial_objects=initial_objects)
|
| 124 |
|
| 125 |
output_images = []
|
|
@@ -135,6 +142,7 @@ class SdImagePipeline(BasePipeline):
|
|
| 135 |
params_string = f"{ui_inputs['positive_prompt']}\nNegative prompt: {ui_inputs['negative_prompt']}\n"
|
| 136 |
params_string += f"Steps: {ui_inputs['num_inference_steps']}, Sampler: {ui_inputs['sampler']}, Scheduler: {ui_inputs['scheduler']}, CFG scale: {ui_inputs['guidance_scale']}, Seed: {current_seed}, Size: {width_for_meta}x{height_for_meta}, Base Model: {model_display_name}"
|
| 137 |
if ui_inputs['task_type'] != 'txt2img': params_string += f", Denoise: {ui_inputs['denoise']}"
|
|
|
|
| 138 |
if loras_string: params_string += f", {loras_string}"
|
| 139 |
|
| 140 |
pil_image.info = {'parameters': params_string.strip()}
|
|
@@ -146,39 +154,46 @@ class SdImagePipeline(BasePipeline):
|
|
| 146 |
progress(0, desc="Preparing models...")
|
| 147 |
|
| 148 |
task_type = ui_inputs['task_type']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
|
| 150 |
ui_inputs['positive_prompt'] = sanitize_prompt(ui_inputs.get('positive_prompt', ''))
|
| 151 |
ui_inputs['negative_prompt'] = sanitize_prompt(ui_inputs.get('negative_prompt', ''))
|
| 152 |
|
| 153 |
-
|
| 154 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
self.model_manager.ensure_models_downloaded(required_models, progress=progress)
|
| 156 |
|
| 157 |
lora_data = ui_inputs.get('lora_data', [])
|
| 158 |
active_loras_for_gpu, active_loras_for_meta = [], []
|
| 159 |
if lora_data:
|
| 160 |
sources, ids, scales, files = lora_data[0::4], lora_data[1::4], lora_data[2::4], lora_data[3::4]
|
| 161 |
-
|
| 162 |
for i, (source, lora_id, scale, _) in enumerate(zip(sources, ids, scales, files)):
|
| 163 |
if scale > 0 and lora_id and lora_id.strip():
|
| 164 |
lora_filename = None
|
| 165 |
if source == "File":
|
| 166 |
lora_filename = sanitize_filename(lora_id)
|
| 167 |
elif source == "Civitai":
|
| 168 |
-
local_path, status = get_lora_path(source, lora_id,
|
| 169 |
if local_path: lora_filename = os.path.basename(local_path)
|
| 170 |
else: raise gr.Error(f"Failed to prepare LoRA {lora_id}: {status}")
|
| 171 |
|
| 172 |
if lora_filename:
|
| 173 |
active_loras_for_gpu.append({"lora_name": lora_filename, "strength_model": scale, "strength_clip": scale})
|
| 174 |
active_loras_for_meta.append(f"{source} {lora_id}:{scale}")
|
| 175 |
-
|
| 176 |
ui_inputs['denoise'] = 1.0
|
| 177 |
if task_type == 'img2img': ui_inputs['denoise'] = ui_inputs.get('img2img_denoise', 0.7)
|
| 178 |
elif task_type == 'hires_fix': ui_inputs['denoise'] = ui_inputs.get('hires_denoise', 0.55)
|
| 179 |
|
| 180 |
temp_files_to_clean = []
|
| 181 |
-
|
| 182 |
if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
|
| 183 |
|
| 184 |
if task_type == 'img2img':
|
|
@@ -197,7 +212,6 @@ class SdImagePipeline(BasePipeline):
|
|
| 197 |
raise gr.Error("Inpainting requires an input image and a drawn mask.")
|
| 198 |
|
| 199 |
background_img = inpaint_dict['background'].convert("RGBA")
|
| 200 |
-
|
| 201 |
composite_mask_pil = Image.new('L', background_img.size, 0)
|
| 202 |
for layer in inpaint_dict['layers']:
|
| 203 |
if layer:
|
|
@@ -211,7 +225,7 @@ class SdImagePipeline(BasePipeline):
|
|
| 211 |
temp_file_path = os.path.join(INPUT_DIR, f"temp_inpaint_composite_{random.randint(1000, 9999)}.png")
|
| 212 |
composite_image_with_mask.save(temp_file_path, "PNG")
|
| 213 |
|
| 214 |
-
ui_inputs['
|
| 215 |
temp_files_to_clean.append(temp_file_path)
|
| 216 |
ui_inputs.pop('inpaint_mask', None)
|
| 217 |
|
|
@@ -222,6 +236,9 @@ class SdImagePipeline(BasePipeline):
|
|
| 222 |
input_image_pil.save(temp_file_path, "PNG")
|
| 223 |
ui_inputs['input_image'] = os.path.basename(temp_file_path)
|
| 224 |
temp_files_to_clean.append(temp_file_path)
|
|
|
|
|
|
|
|
|
|
| 225 |
|
| 226 |
elif task_type == 'hires_fix':
|
| 227 |
input_image_pil = ui_inputs.get('hires_image')
|
|
@@ -241,7 +258,7 @@ class SdImagePipeline(BasePipeline):
|
|
| 241 |
if source == "File":
|
| 242 |
emb_filename = sanitize_filename(emb_id)
|
| 243 |
elif source == "Civitai":
|
| 244 |
-
local_path, status = get_embedding_path(source, emb_id,
|
| 245 |
if local_path: emb_filename = os.path.basename(local_path)
|
| 246 |
else: raise gr.Error(f"Failed to prepare Embedding {emb_id}: {status}")
|
| 247 |
|
|
@@ -255,20 +272,162 @@ class SdImagePipeline(BasePipeline):
|
|
| 255 |
else:
|
| 256 |
ui_inputs['positive_prompt'] = embedding_prompt_text
|
| 257 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
from utils.app_utils import get_vae_path
|
| 259 |
vae_source = ui_inputs.get('vae_source')
|
| 260 |
vae_id = ui_inputs.get('vae_id')
|
| 261 |
-
vae_file = ui_inputs.get('vae_file')
|
| 262 |
vae_name_override = None
|
| 263 |
-
|
| 264 |
if vae_source and vae_source != "None":
|
| 265 |
if vae_source == "File":
|
| 266 |
vae_name_override = sanitize_filename(vae_id)
|
| 267 |
elif vae_source == "Civitai" and vae_id and vae_id.strip():
|
| 268 |
-
local_path, status = get_vae_path(vae_source, vae_id,
|
| 269 |
if local_path: vae_name_override = os.path.basename(local_path)
|
| 270 |
else: raise gr.Error(f"Failed to prepare VAE {vae_id}: {status}")
|
| 271 |
-
|
| 272 |
if vae_name_override:
|
| 273 |
ui_inputs['vae_name'] = vae_name_override
|
| 274 |
|
|
@@ -276,78 +435,84 @@ class SdImagePipeline(BasePipeline):
|
|
| 276 |
active_conditioning = []
|
| 277 |
if conditioning_data:
|
| 278 |
num_units = len(conditioning_data) // 6
|
| 279 |
-
prompts
|
| 280 |
-
widths = conditioning_data[1*num_units : 2*num_units]
|
| 281 |
-
heights = conditioning_data[2*num_units : 3*num_units]
|
| 282 |
-
xs = conditioning_data[3*num_units : 4*num_units]
|
| 283 |
-
ys = conditioning_data[4*num_units : 5*num_units]
|
| 284 |
-
strengths = conditioning_data[5*num_units : 6*num_units]
|
| 285 |
-
|
| 286 |
for i in range(num_units):
|
| 287 |
if prompts[i] and prompts[i].strip():
|
| 288 |
active_conditioning.append({
|
| 289 |
-
"prompt": prompts[i],
|
| 290 |
-
"
|
| 291 |
-
"height": int(heights[i]),
|
| 292 |
-
"x": int(xs[i]),
|
| 293 |
-
"y": int(ys[i]),
|
| 294 |
-
"strength": float(strengths[i])
|
| 295 |
})
|
| 296 |
|
| 297 |
-
reference_latent_data = ui_inputs.get('reference_latent_data', [])
|
| 298 |
-
active_reference_latents = []
|
| 299 |
-
if reference_latent_data:
|
| 300 |
-
for img_pil in reference_latent_data:
|
| 301 |
-
if img_pil is not None:
|
| 302 |
-
temp_file_path = os.path.join(INPUT_DIR, f"temp_ref_{random.randint(1000, 9999)}.png")
|
| 303 |
-
img_pil.save(temp_file_path, "PNG")
|
| 304 |
-
active_reference_latents.append(os.path.basename(temp_file_path))
|
| 305 |
-
temp_files_to_clean.append(temp_file_path)
|
| 306 |
-
|
| 307 |
loras_string = f"LoRAs: [{', '.join(active_loras_for_meta)}]" if active_loras_for_meta else ""
|
| 308 |
|
| 309 |
progress(0.8, desc="Assembling workflow...")
|
| 310 |
|
| 311 |
if ui_inputs.get('seed') == -1:
|
| 312 |
ui_inputs['seed'] = random.randint(0, 2**32 - 1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 313 |
|
| 314 |
-
dynamic_values = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 315 |
|
| 316 |
recipe_path = os.path.join(os.path.dirname(__file__), "workflow_recipes", "sd_unified_recipe.yaml")
|
| 317 |
assembler = WorkflowAssembler(recipe_path, dynamic_values=dynamic_values)
|
| 318 |
|
| 319 |
-
model_display_name = ui_inputs['model_display_name']
|
| 320 |
-
if model_display_name not in ALL_MODEL_MAP:
|
| 321 |
-
raise gr.Error(f"Model '{model_display_name}' is not configured in model_list.yaml.")
|
| 322 |
-
|
| 323 |
-
_, components, _, _ = ALL_MODEL_MAP[model_display_name]
|
| 324 |
-
|
| 325 |
workflow_inputs = {
|
|
|
|
| 326 |
"positive_prompt": ui_inputs['positive_prompt'], "negative_prompt": ui_inputs['negative_prompt'],
|
| 327 |
"seed": ui_inputs['seed'], "steps": ui_inputs['num_inference_steps'], "cfg": ui_inputs['guidance_scale'],
|
| 328 |
"sampler_name": ui_inputs['sampler'], "scheduler": ui_inputs['scheduler'],
|
| 329 |
"batch_size": ui_inputs['batch_size'],
|
| 330 |
-
"
|
| 331 |
-
"
|
| 332 |
-
"
|
| 333 |
-
"
|
| 334 |
-
"left": ui_inputs.get('outpaint_left'), "top": ui_inputs.get('outpaint_top'),
|
| 335 |
-
"right": ui_inputs.get('outpaint_right'), "bottom": ui_inputs.get('outpaint_bottom'),
|
| 336 |
-
"hires_upscaler": ui_inputs.get('hires_upscaler'), "hires_scale_by": ui_inputs.get('hires_scale_by'),
|
| 337 |
-
"unet_name": components['unet'],
|
| 338 |
-
"clip_name": components['clip'],
|
| 339 |
-
"vae_name": ui_inputs.get('vae_name', components['vae']),
|
| 340 |
"lora_chain": active_loras_for_gpu,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 341 |
"conditioning_chain": active_conditioning,
|
| 342 |
"reference_latent_chain": active_reference_latents,
|
|
|
|
| 343 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 344 |
|
| 345 |
if task_type == 'txt2img':
|
| 346 |
workflow_inputs['width'] = ui_inputs['width']
|
| 347 |
workflow_inputs['height'] = ui_inputs['height']
|
| 348 |
|
| 349 |
workflow = assembler.assemble(workflow_inputs)
|
| 350 |
-
|
| 351 |
progress(1.0, desc="All models ready. Requesting GPU for generation...")
|
| 352 |
|
| 353 |
try:
|
|
@@ -362,7 +527,7 @@ class SdImagePipeline(BasePipeline):
|
|
| 362 |
assembler=assembler,
|
| 363 |
progress=progress
|
| 364 |
)
|
| 365 |
-
|
| 366 |
import json
|
| 367 |
import glob
|
| 368 |
from PIL import PngImagePlugin
|
|
|
|
| 11 |
from .base_pipeline import BasePipeline
|
| 12 |
from core.settings import *
|
| 13 |
from comfy_integration.nodes import *
|
| 14 |
+
from utils.app_utils import get_value_at_index, sanitize_prompt, get_lora_path, get_embedding_path, ensure_controlnet_model_downloaded, ensure_ipadapter_models_downloaded, sanitize_filename
|
| 15 |
from core.workflow_assembler import WorkflowAssembler
|
| 16 |
|
| 17 |
class SdImagePipeline(BasePipeline):
|
| 18 |
def get_required_models(self, model_display_name: str, **kwargs) -> List[str]:
|
| 19 |
+
model_info = ALL_MODEL_MAP.get(model_display_name)
|
| 20 |
+
if not model_info:
|
| 21 |
+
return [model_display_name]
|
| 22 |
+
|
| 23 |
+
path_or_components = model_info[1]
|
| 24 |
+
if isinstance(path_or_components, dict):
|
| 25 |
+
return [v for v in path_or_components.values() if v and v != "pixel_space"]
|
| 26 |
+
else:
|
| 27 |
+
return [model_display_name]
|
| 28 |
|
| 29 |
def _topological_sort(self, workflow: Dict[str, Any]) -> List[str]:
|
| 30 |
graph = defaultdict(list)
|
|
|
|
| 55 |
|
| 56 |
return sorted_nodes
|
| 57 |
|
|
|
|
| 58 |
def _execute_workflow(self, workflow: Dict[str, Any], initial_objects: Dict[str, Any]):
|
| 59 |
with torch.no_grad():
|
| 60 |
computed_outputs = initial_objects
|
|
|
|
| 126 |
progress(0.4, desc="Executing workflow...")
|
| 127 |
|
| 128 |
initial_objects = {}
|
| 129 |
+
|
| 130 |
decoded_images_tensor = self._execute_workflow(workflow, initial_objects=initial_objects)
|
| 131 |
|
| 132 |
output_images = []
|
|
|
|
| 142 |
params_string = f"{ui_inputs['positive_prompt']}\nNegative prompt: {ui_inputs['negative_prompt']}\n"
|
| 143 |
params_string += f"Steps: {ui_inputs['num_inference_steps']}, Sampler: {ui_inputs['sampler']}, Scheduler: {ui_inputs['scheduler']}, CFG scale: {ui_inputs['guidance_scale']}, Seed: {current_seed}, Size: {width_for_meta}x{height_for_meta}, Base Model: {model_display_name}"
|
| 144 |
if ui_inputs['task_type'] != 'txt2img': params_string += f", Denoise: {ui_inputs['denoise']}"
|
| 145 |
+
if ui_inputs.get('clip_skip') and ui_inputs['clip_skip'] != 1: params_string += f", Clip skip: {abs(ui_inputs['clip_skip'])}"
|
| 146 |
if loras_string: params_string += f", {loras_string}"
|
| 147 |
|
| 148 |
pil_image.info = {'parameters': params_string.strip()}
|
|
|
|
| 154 |
progress(0, desc="Preparing models...")
|
| 155 |
|
| 156 |
task_type = ui_inputs['task_type']
|
| 157 |
+
model_display_name = ui_inputs['model_display_name']
|
| 158 |
+
model_type = MODEL_TYPE_MAP.get(model_display_name, 'sdxl')
|
| 159 |
+
|
| 160 |
+
architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 161 |
+
workflow_model_type = architectures_dict.get(model_type, {}).get("model_type", "sdxl")
|
| 162 |
|
| 163 |
ui_inputs['positive_prompt'] = sanitize_prompt(ui_inputs.get('positive_prompt', ''))
|
| 164 |
ui_inputs['negative_prompt'] = sanitize_prompt(ui_inputs.get('negative_prompt', ''))
|
| 165 |
|
| 166 |
+
if 'clip_skip' in ui_inputs and ui_inputs['clip_skip'] is not None:
|
| 167 |
+
ui_inputs['clip_skip'] = -int(ui_inputs['clip_skip'])
|
| 168 |
+
else:
|
| 169 |
+
ui_inputs['clip_skip'] = -1
|
| 170 |
+
|
| 171 |
+
required_models = self.get_required_models(model_display_name=model_display_name)
|
| 172 |
self.model_manager.ensure_models_downloaded(required_models, progress=progress)
|
| 173 |
|
| 174 |
lora_data = ui_inputs.get('lora_data', [])
|
| 175 |
active_loras_for_gpu, active_loras_for_meta = [], []
|
| 176 |
if lora_data:
|
| 177 |
sources, ids, scales, files = lora_data[0::4], lora_data[1::4], lora_data[2::4], lora_data[3::4]
|
|
|
|
| 178 |
for i, (source, lora_id, scale, _) in enumerate(zip(sources, ids, scales, files)):
|
| 179 |
if scale > 0 and lora_id and lora_id.strip():
|
| 180 |
lora_filename = None
|
| 181 |
if source == "File":
|
| 182 |
lora_filename = sanitize_filename(lora_id)
|
| 183 |
elif source == "Civitai":
|
| 184 |
+
local_path, status = get_lora_path(source, lora_id, os.environ.get("CIVITAI_API_KEY", ""), progress)
|
| 185 |
if local_path: lora_filename = os.path.basename(local_path)
|
| 186 |
else: raise gr.Error(f"Failed to prepare LoRA {lora_id}: {status}")
|
| 187 |
|
| 188 |
if lora_filename:
|
| 189 |
active_loras_for_gpu.append({"lora_name": lora_filename, "strength_model": scale, "strength_clip": scale})
|
| 190 |
active_loras_for_meta.append(f"{source} {lora_id}:{scale}")
|
| 191 |
+
|
| 192 |
ui_inputs['denoise'] = 1.0
|
| 193 |
if task_type == 'img2img': ui_inputs['denoise'] = ui_inputs.get('img2img_denoise', 0.7)
|
| 194 |
elif task_type == 'hires_fix': ui_inputs['denoise'] = ui_inputs.get('hires_denoise', 0.55)
|
| 195 |
|
| 196 |
temp_files_to_clean = []
|
|
|
|
| 197 |
if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
|
| 198 |
|
| 199 |
if task_type == 'img2img':
|
|
|
|
| 212 |
raise gr.Error("Inpainting requires an input image and a drawn mask.")
|
| 213 |
|
| 214 |
background_img = inpaint_dict['background'].convert("RGBA")
|
|
|
|
| 215 |
composite_mask_pil = Image.new('L', background_img.size, 0)
|
| 216 |
for layer in inpaint_dict['layers']:
|
| 217 |
if layer:
|
|
|
|
| 225 |
temp_file_path = os.path.join(INPUT_DIR, f"temp_inpaint_composite_{random.randint(1000, 9999)}.png")
|
| 226 |
composite_image_with_mask.save(temp_file_path, "PNG")
|
| 227 |
|
| 228 |
+
ui_inputs['input_image'] = os.path.basename(temp_file_path)
|
| 229 |
temp_files_to_clean.append(temp_file_path)
|
| 230 |
ui_inputs.pop('inpaint_mask', None)
|
| 231 |
|
|
|
|
| 236 |
input_image_pil.save(temp_file_path, "PNG")
|
| 237 |
ui_inputs['input_image'] = os.path.basename(temp_file_path)
|
| 238 |
temp_files_to_clean.append(temp_file_path)
|
| 239 |
+
|
| 240 |
+
ui_inputs['megapixels'] = 0.25
|
| 241 |
+
ui_inputs['grow_mask_by'] = ui_inputs.get('feathering', 10)
|
| 242 |
|
| 243 |
elif task_type == 'hires_fix':
|
| 244 |
input_image_pil = ui_inputs.get('hires_image')
|
|
|
|
| 258 |
if source == "File":
|
| 259 |
emb_filename = sanitize_filename(emb_id)
|
| 260 |
elif source == "Civitai":
|
| 261 |
+
local_path, status = get_embedding_path(source, emb_id, os.environ.get("CIVITAI_API_KEY", ""), progress)
|
| 262 |
if local_path: emb_filename = os.path.basename(local_path)
|
| 263 |
else: raise gr.Error(f"Failed to prepare Embedding {emb_id}: {status}")
|
| 264 |
|
|
|
|
| 272 |
else:
|
| 273 |
ui_inputs['positive_prompt'] = embedding_prompt_text
|
| 274 |
|
| 275 |
+
controlnet_data = ui_inputs.get('controlnet_data', [])
|
| 276 |
+
active_controlnets = []
|
| 277 |
+
if controlnet_data:
|
| 278 |
+
(cn_images, _, _, cn_strengths, cn_filepaths) = [controlnet_data[i::5] for i in range(5)]
|
| 279 |
+
for i in range(len(cn_images)):
|
| 280 |
+
if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
|
| 281 |
+
ensure_controlnet_model_downloaded(cn_filepaths[i], progress)
|
| 282 |
+
if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
|
| 283 |
+
cn_temp_path = os.path.join(INPUT_DIR, f"temp_cn_{i}_{random.randint(1000, 9999)}.png")
|
| 284 |
+
cn_images[i].save(cn_temp_path, "PNG")
|
| 285 |
+
temp_files_to_clean.append(cn_temp_path)
|
| 286 |
+
active_controlnets.append({
|
| 287 |
+
"image": os.path.basename(cn_temp_path), "strength": cn_strengths[i],
|
| 288 |
+
"start_percent": 0.0, "end_percent": 1.0, "control_net_name": cn_filepaths[i]
|
| 289 |
+
})
|
| 290 |
+
|
| 291 |
+
diffsynth_controlnet_data = ui_inputs.get('diffsynth_controlnet_data', [])
|
| 292 |
+
active_diffsynth_controlnets = []
|
| 293 |
+
if diffsynth_controlnet_data:
|
| 294 |
+
(cn_images, _, _, cn_strengths, cn_filepaths) = [diffsynth_controlnet_data[i::5] for i in range(5)]
|
| 295 |
+
for i in range(len(cn_images)):
|
| 296 |
+
if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
|
| 297 |
+
ensure_controlnet_model_downloaded(cn_filepaths[i], progress)
|
| 298 |
+
|
| 299 |
+
if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
|
| 300 |
+
cn_temp_path = os.path.join(INPUT_DIR, f"temp_diffsynth_cn_{i}_{random.randint(1000, 9999)}.png")
|
| 301 |
+
cn_images[i].save(cn_temp_path, "PNG")
|
| 302 |
+
temp_files_to_clean.append(cn_temp_path)
|
| 303 |
+
active_diffsynth_controlnets.append({
|
| 304 |
+
"image": os.path.basename(cn_temp_path), "strength": cn_strengths[i],
|
| 305 |
+
"control_net_name": cn_filepaths[i]
|
| 306 |
+
})
|
| 307 |
+
|
| 308 |
+
ipadapter_data = ui_inputs.get('ipadapter_data', [])
|
| 309 |
+
active_ipadapters = []
|
| 310 |
+
if ipadapter_data:
|
| 311 |
+
num_ipa_units = (len(ipadapter_data) - 5) // 3
|
| 312 |
+
final_preset, final_weight, final_lora_strength, final_embeds_scaling, final_combine_method = ipadapter_data[-5:]
|
| 313 |
+
ipa_images, ipa_weights, ipa_lora_strengths = [ipadapter_data[i*num_ipa_units:(i+1)*num_ipa_units] for i in range(3)]
|
| 314 |
+
all_presets_to_download = set()
|
| 315 |
+
for i in range(num_ipa_units):
|
| 316 |
+
if ipa_images[i] and ipa_weights[i] > 0 and final_preset:
|
| 317 |
+
all_presets_to_download.add(final_preset)
|
| 318 |
+
if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
|
| 319 |
+
ipa_temp_path = os.path.join(INPUT_DIR, f"temp_ipa_{i}_{random.randint(1000, 9999)}.png")
|
| 320 |
+
ipa_images[i].save(ipa_temp_path, "PNG")
|
| 321 |
+
temp_files_to_clean.append(ipa_temp_path)
|
| 322 |
+
active_ipadapters.append({
|
| 323 |
+
"image": os.path.basename(ipa_temp_path), "preset": final_preset,
|
| 324 |
+
"weight": ipa_weights[i], "lora_strength": ipa_lora_strengths[i]
|
| 325 |
+
})
|
| 326 |
+
if active_ipadapters and final_preset:
|
| 327 |
+
all_presets_to_download.add(final_preset)
|
| 328 |
+
for preset in all_presets_to_download:
|
| 329 |
+
ensure_ipadapter_models_downloaded(preset, progress)
|
| 330 |
+
|
| 331 |
+
model_type_key = 'sd15' if workflow_model_type == 'sd15' else 'sdxl'
|
| 332 |
+
if active_ipadapters:
|
| 333 |
+
active_ipadapters.append({
|
| 334 |
+
'is_final_settings': True, 'model_type': model_type_key, 'final_preset': final_preset,
|
| 335 |
+
'final_weight': final_weight, 'final_lora_strength': final_lora_strength,
|
| 336 |
+
'final_embeds_scaling': final_embeds_scaling, 'final_combine_method': final_combine_method
|
| 337 |
+
})
|
| 338 |
+
|
| 339 |
+
flux1_ipadapter_data = ui_inputs.get('flux1_ipadapter_data', [])
|
| 340 |
+
active_flux1_ipadapters = []
|
| 341 |
+
if flux1_ipadapter_data:
|
| 342 |
+
num_units = len(flux1_ipadapter_data) // 4
|
| 343 |
+
f_images = flux1_ipadapter_data[0*num_units : 1*num_units]
|
| 344 |
+
f_weights = flux1_ipadapter_data[1*num_units : 2*num_units]
|
| 345 |
+
f_starts = flux1_ipadapter_data[2*num_units : 3*num_units]
|
| 346 |
+
f_ends = flux1_ipadapter_data[3*num_units : 4*num_units]
|
| 347 |
+
for i in range(len(f_images)):
|
| 348 |
+
if f_images[i] and f_weights[i] > 0:
|
| 349 |
+
from utils.app_utils import _ensure_model_downloaded
|
| 350 |
+
for filename in ["ip-adapter.bin"]:
|
| 351 |
+
_ensure_model_downloaded(filename, progress)
|
| 352 |
+
|
| 353 |
+
from huggingface_hub import snapshot_download
|
| 354 |
+
progress(0.5, desc="Caching HF SigLIP model...")
|
| 355 |
+
snapshot_download(
|
| 356 |
+
repo_id="google/siglip-so400m-patch14-384",
|
| 357 |
+
allow_patterns=["*.json", "*.safetensors", "*.txt"],
|
| 358 |
+
ignore_patterns=["*.msgpack", "*.h5", "*.bin"]
|
| 359 |
+
)
|
| 360 |
+
|
| 361 |
+
temp_path = os.path.join(INPUT_DIR, f"temp_fipa_{i}_{random.randint(1000, 9999)}.png")
|
| 362 |
+
f_images[i].save(temp_path, "PNG")
|
| 363 |
+
temp_files_to_clean.append(temp_path)
|
| 364 |
+
active_flux1_ipadapters.append({
|
| 365 |
+
"image": os.path.basename(temp_path),
|
| 366 |
+
"weight": f_weights[i], "start_percent": f_starts[i], "end_percent": f_ends[i]
|
| 367 |
+
})
|
| 368 |
+
|
| 369 |
+
sd3_ipadapter_data = ui_inputs.get('sd3_ipadapter_chain', [])
|
| 370 |
+
active_sd3_ipadapters = []
|
| 371 |
+
if sd3_ipadapter_data:
|
| 372 |
+
num_units = len(sd3_ipadapter_data) // 4
|
| 373 |
+
s_images = sd3_ipadapter_data[0*num_units : 1*num_units]
|
| 374 |
+
s_weights = sd3_ipadapter_data[1*num_units : 2*num_units]
|
| 375 |
+
s_starts = sd3_ipadapter_data[2*num_units : 3*num_units]
|
| 376 |
+
s_ends = sd3_ipadapter_data[3*num_units : 4*num_units]
|
| 377 |
+
sd3_ipa_downloaded = False
|
| 378 |
+
for i in range(len(s_images)):
|
| 379 |
+
if s_images[i] and s_weights[i] > 0:
|
| 380 |
+
if not sd3_ipa_downloaded:
|
| 381 |
+
from utils.app_utils import ensure_sd3_ipadapter_models_downloaded
|
| 382 |
+
ensure_sd3_ipadapter_models_downloaded(progress)
|
| 383 |
+
sd3_ipa_downloaded = True
|
| 384 |
+
temp_path = os.path.join(INPUT_DIR, f"temp_s3ipa_{i}_{random.randint(1000, 9999)}.png")
|
| 385 |
+
s_images[i].save(temp_path, "PNG")
|
| 386 |
+
temp_files_to_clean.append(temp_path)
|
| 387 |
+
active_sd3_ipadapters.append({
|
| 388 |
+
"image": os.path.basename(temp_path),
|
| 389 |
+
"weight": s_weights[i], "start_percent": s_starts[i], "end_percent": s_ends[i]
|
| 390 |
+
})
|
| 391 |
+
|
| 392 |
+
style_data = ui_inputs.get('style_data', [])
|
| 393 |
+
active_styles = []
|
| 394 |
+
if style_data:
|
| 395 |
+
num_units = len(style_data) // 2
|
| 396 |
+
st_images = style_data[0*num_units : 1*num_units]
|
| 397 |
+
st_strengths = style_data[1*num_units : 2*num_units]
|
| 398 |
+
for i in range(len(st_images)):
|
| 399 |
+
if st_images[i] and st_strengths[i] > 0:
|
| 400 |
+
from utils.app_utils import _ensure_model_downloaded
|
| 401 |
+
_ensure_model_downloaded("sigclip_vision_patch14_384.safetensors", progress)
|
| 402 |
+
temp_path = os.path.join(INPUT_DIR, f"temp_style_{i}_{random.randint(1000, 9999)}.png")
|
| 403 |
+
st_images[i].save(temp_path, "PNG")
|
| 404 |
+
temp_files_to_clean.append(temp_path)
|
| 405 |
+
active_styles.append({
|
| 406 |
+
"image": os.path.basename(temp_path), "strength": st_strengths[i]
|
| 407 |
+
})
|
| 408 |
+
|
| 409 |
+
reference_latent_data = ui_inputs.get('reference_latent_data', [])
|
| 410 |
+
active_reference_latents = []
|
| 411 |
+
if reference_latent_data:
|
| 412 |
+
for img in reference_latent_data:
|
| 413 |
+
if img:
|
| 414 |
+
if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
|
| 415 |
+
temp_path = os.path.join(INPUT_DIR, f"temp_ref_{random.randint(1000, 9999)}.png")
|
| 416 |
+
img.save(temp_path, "PNG")
|
| 417 |
+
temp_files_to_clean.append(temp_path)
|
| 418 |
+
active_reference_latents.append(os.path.basename(temp_path))
|
| 419 |
+
|
| 420 |
from utils.app_utils import get_vae_path
|
| 421 |
vae_source = ui_inputs.get('vae_source')
|
| 422 |
vae_id = ui_inputs.get('vae_id')
|
|
|
|
| 423 |
vae_name_override = None
|
|
|
|
| 424 |
if vae_source and vae_source != "None":
|
| 425 |
if vae_source == "File":
|
| 426 |
vae_name_override = sanitize_filename(vae_id)
|
| 427 |
elif vae_source == "Civitai" and vae_id and vae_id.strip():
|
| 428 |
+
local_path, status = get_vae_path(vae_source, vae_id, os.environ.get("CIVITAI_API_KEY", ""), progress)
|
| 429 |
if local_path: vae_name_override = os.path.basename(local_path)
|
| 430 |
else: raise gr.Error(f"Failed to prepare VAE {vae_id}: {status}")
|
|
|
|
| 431 |
if vae_name_override:
|
| 432 |
ui_inputs['vae_name'] = vae_name_override
|
| 433 |
|
|
|
|
| 435 |
active_conditioning = []
|
| 436 |
if conditioning_data:
|
| 437 |
num_units = len(conditioning_data) // 6
|
| 438 |
+
prompts, widths, heights, xs, ys, strengths = [conditioning_data[i*num_units : (i+1)*num_units] for i in range(6)]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 439 |
for i in range(num_units):
|
| 440 |
if prompts[i] and prompts[i].strip():
|
| 441 |
active_conditioning.append({
|
| 442 |
+
"prompt": prompts[i], "width": int(widths[i]), "height": int(heights[i]),
|
| 443 |
+
"x": int(xs[i]), "y": int(ys[i]), "strength": float(strengths[i])
|
|
|
|
|
|
|
|
|
|
|
|
|
| 444 |
})
|
| 445 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 446 |
loras_string = f"LoRAs: [{', '.join(active_loras_for_meta)}]" if active_loras_for_meta else ""
|
| 447 |
|
| 448 |
progress(0.8, desc="Assembling workflow...")
|
| 449 |
|
| 450 |
if ui_inputs.get('seed') == -1:
|
| 451 |
ui_inputs['seed'] = random.randint(0, 2**32 - 1)
|
| 452 |
+
|
| 453 |
+
model_info = ALL_MODEL_MAP[model_display_name]
|
| 454 |
+
path_or_components = model_info[1]
|
| 455 |
+
latent_type = model_info[3] if len(model_info) > 3 and model_info[3] else 'latent'
|
| 456 |
+
latent_generator_template = "EmptyLatentImage"
|
| 457 |
+
if latent_type == 'sd3_latent':
|
| 458 |
+
latent_generator_template = "EmptySD3LatentImage"
|
| 459 |
+
elif latent_type == 'chroma_radiance_latent':
|
| 460 |
+
latent_generator_template = "EmptyChromaRadianceLatentImage"
|
| 461 |
+
elif latent_type == 'hunyuan_latent':
|
| 462 |
+
latent_generator_template = "EmptyHunyuanImageLatent"
|
| 463 |
|
| 464 |
+
dynamic_values = {
|
| 465 |
+
'task_type': ui_inputs['task_type'],
|
| 466 |
+
'model_type': workflow_model_type,
|
| 467 |
+
'latent_type': latent_type,
|
| 468 |
+
'latent_generator_template': latent_generator_template
|
| 469 |
+
}
|
| 470 |
|
| 471 |
recipe_path = os.path.join(os.path.dirname(__file__), "workflow_recipes", "sd_unified_recipe.yaml")
|
| 472 |
assembler = WorkflowAssembler(recipe_path, dynamic_values=dynamic_values)
|
| 473 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 474 |
workflow_inputs = {
|
| 475 |
+
**ui_inputs,
|
| 476 |
"positive_prompt": ui_inputs['positive_prompt'], "negative_prompt": ui_inputs['negative_prompt'],
|
| 477 |
"seed": ui_inputs['seed'], "steps": ui_inputs['num_inference_steps'], "cfg": ui_inputs['guidance_scale'],
|
| 478 |
"sampler_name": ui_inputs['sampler'], "scheduler": ui_inputs['scheduler'],
|
| 479 |
"batch_size": ui_inputs['batch_size'],
|
| 480 |
+
"clip_skip": ui_inputs['clip_skip'],
|
| 481 |
+
"denoise": ui_inputs['denoise'],
|
| 482 |
+
"vae_name": ui_inputs.get('vae_name'),
|
| 483 |
+
"guidance": ui_inputs.get('guidance', 3.5),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 484 |
"lora_chain": active_loras_for_gpu,
|
| 485 |
+
"controlnet_chain": active_controlnets,
|
| 486 |
+
"diffsynth_controlnet_chain": active_diffsynth_controlnets,
|
| 487 |
+
"ipadapter_chain": active_ipadapters,
|
| 488 |
+
"flux1_ipadapter_chain": active_flux1_ipadapters,
|
| 489 |
+
"sd3_ipadapter_chain": active_sd3_ipadapters,
|
| 490 |
+
"style_chain": active_styles,
|
| 491 |
"conditioning_chain": active_conditioning,
|
| 492 |
"reference_latent_chain": active_reference_latents,
|
| 493 |
+
"vae_chain": [ui_inputs.get('vae_name')] if ui_inputs.get('vae_name') else [],
|
| 494 |
}
|
| 495 |
+
|
| 496 |
+
if isinstance(path_or_components, dict):
|
| 497 |
+
workflow_inputs.update({
|
| 498 |
+
'unet_name': path_or_components.get('unet'),
|
| 499 |
+
'vae_name': ui_inputs.get('vae_name') or path_or_components.get('vae'),
|
| 500 |
+
'clip_name': path_or_components.get('clip'),
|
| 501 |
+
'clip1_name': path_or_components.get('clip1'),
|
| 502 |
+
'clip2_name': path_or_components.get('clip2'),
|
| 503 |
+
'clip3_name': path_or_components.get('clip3'),
|
| 504 |
+
'clip4_name': path_or_components.get('clip4'),
|
| 505 |
+
'lora_name': path_or_components.get('lora'),
|
| 506 |
+
})
|
| 507 |
+
else:
|
| 508 |
+
workflow_inputs['model_name'] = path_or_components
|
| 509 |
|
| 510 |
if task_type == 'txt2img':
|
| 511 |
workflow_inputs['width'] = ui_inputs['width']
|
| 512 |
workflow_inputs['height'] = ui_inputs['height']
|
| 513 |
|
| 514 |
workflow = assembler.assemble(workflow_inputs)
|
| 515 |
+
|
| 516 |
progress(1.0, desc="All models ready. Requesting GPU for generation...")
|
| 517 |
|
| 518 |
try:
|
|
|
|
| 527 |
assembler=assembler,
|
| 528 |
progress=progress
|
| 529 |
)
|
| 530 |
+
|
| 531 |
import json
|
| 532 |
import glob
|
| 533 |
from PIL import PngImagePlugin
|
core/pipelines/workflow_recipes/_partials/{_base_sampler.yaml → _base_sampler_sd.yaml}
RENAMED
|
@@ -1,11 +1,21 @@
|
|
| 1 |
nodes:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
ksampler:
|
| 3 |
class_type: KSampler
|
| 4 |
-
|
|
|
|
|
|
|
| 5 |
vae_decode:
|
| 6 |
class_type: VAEDecode
|
|
|
|
| 7 |
save_image:
|
| 8 |
class_type: SaveImage
|
|
|
|
| 9 |
params: {}
|
| 10 |
|
| 11 |
connections:
|
|
@@ -15,9 +25,12 @@ connections:
|
|
| 15 |
to: "save_image:images"
|
| 16 |
|
| 17 |
ui_map:
|
|
|
|
|
|
|
| 18 |
seed: "ksampler:seed"
|
| 19 |
steps: "ksampler:steps"
|
| 20 |
cfg: "ksampler:cfg"
|
| 21 |
sampler_name: "ksampler:sampler_name"
|
| 22 |
scheduler: "ksampler:scheduler"
|
| 23 |
-
denoise: "ksampler:denoise"
|
|
|
|
|
|
| 1 |
nodes:
|
| 2 |
+
pos_prompt:
|
| 3 |
+
class_type: CLIPTextEncode
|
| 4 |
+
title: "CLIP Text Encode (Positive)"
|
| 5 |
+
neg_prompt:
|
| 6 |
+
class_type: CLIPTextEncode
|
| 7 |
+
title: "CLIP Text Encode (Negative)"
|
| 8 |
ksampler:
|
| 9 |
class_type: KSampler
|
| 10 |
+
title: "KSampler"
|
| 11 |
+
params:
|
| 12 |
+
denoise: 1.0
|
| 13 |
vae_decode:
|
| 14 |
class_type: VAEDecode
|
| 15 |
+
title: "VAE Decode"
|
| 16 |
save_image:
|
| 17 |
class_type: SaveImage
|
| 18 |
+
title: "Save Image"
|
| 19 |
params: {}
|
| 20 |
|
| 21 |
connections:
|
|
|
|
| 25 |
to: "save_image:images"
|
| 26 |
|
| 27 |
ui_map:
|
| 28 |
+
positive_prompt: "pos_prompt:text"
|
| 29 |
+
negative_prompt: "neg_prompt:text"
|
| 30 |
seed: "ksampler:seed"
|
| 31 |
steps: "ksampler:steps"
|
| 32 |
cfg: "ksampler:cfg"
|
| 33 |
sampler_name: "ksampler:sampler_name"
|
| 34 |
scheduler: "ksampler:scheduler"
|
| 35 |
+
denoise: "ksampler:denoise"
|
| 36 |
+
filename_prefix: "save_image:filename_prefix"
|
core/pipelines/workflow_recipes/_partials/conditioning/flux1.yaml
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
nodes:
|
| 2 |
+
unet_loader:
|
| 3 |
+
class_type: UNETLoader
|
| 4 |
+
title: "Load FLUX UNET"
|
| 5 |
+
params:
|
| 6 |
+
weight_dtype: "default"
|
| 7 |
+
vae_loader:
|
| 8 |
+
class_type: VAELoader
|
| 9 |
+
title: "Load FLUX VAE"
|
| 10 |
+
clip_loader:
|
| 11 |
+
class_type: DualCLIPLoader
|
| 12 |
+
title: "Load FLUX Dual CLIP"
|
| 13 |
+
params:
|
| 14 |
+
type: "flux"
|
| 15 |
+
device: "default"
|
| 16 |
+
flux_guidance:
|
| 17 |
+
class_type: FluxGuidance
|
| 18 |
+
title: "FluxGuidance"
|
| 19 |
+
|
| 20 |
+
connections:
|
| 21 |
+
- from: "unet_loader:0"
|
| 22 |
+
to: "ksampler:model"
|
| 23 |
+
- from: "clip_loader:0"
|
| 24 |
+
to: "pos_prompt:clip"
|
| 25 |
+
- from: "clip_loader:0"
|
| 26 |
+
to: "neg_prompt:clip"
|
| 27 |
+
- from: "vae_loader:0"
|
| 28 |
+
to: "vae_decode:vae"
|
| 29 |
+
- from: "vae_loader:0"
|
| 30 |
+
to: "vae_encode:vae"
|
| 31 |
+
- from: "pos_prompt:0"
|
| 32 |
+
to: "flux_guidance:conditioning"
|
| 33 |
+
- from: "flux_guidance:0"
|
| 34 |
+
to: "ksampler:positive"
|
| 35 |
+
- from: "neg_prompt:0"
|
| 36 |
+
to: "ksampler:negative"
|
| 37 |
+
|
| 38 |
+
dynamic_controlnet_chains:
|
| 39 |
+
controlnet_chain:
|
| 40 |
+
template: "ControlNetApplyAdvanced"
|
| 41 |
+
ksampler_node: "ksampler"
|
| 42 |
+
vae_source: "vae_loader:0"
|
| 43 |
+
|
| 44 |
+
dynamic_flux1_ipadapter_chains:
|
| 45 |
+
flux1_ipadapter_chain:
|
| 46 |
+
ksampler_node: "ksampler"
|
| 47 |
+
|
| 48 |
+
dynamic_style_chains:
|
| 49 |
+
style_chain:
|
| 50 |
+
flux_guidance_node: "flux_guidance"
|
| 51 |
+
ksampler_node: "ksampler"
|
| 52 |
+
|
| 53 |
+
dynamic_conditioning_chains:
|
| 54 |
+
conditioning_chain:
|
| 55 |
+
flux_guidance_node: "flux_guidance"
|
| 56 |
+
ksampler_node: "ksampler"
|
| 57 |
+
clip_source: "clip_loader:0"
|
| 58 |
+
|
| 59 |
+
ui_map:
|
| 60 |
+
unet_name: "unet_loader:unet_name"
|
| 61 |
+
vae_name: "vae_loader:vae_name"
|
| 62 |
+
clip1_name: "clip_loader:clip_name1"
|
| 63 |
+
clip2_name: "clip_loader:clip_name2"
|
| 64 |
+
guidance: "flux_guidance:guidance"
|
core/pipelines/workflow_recipes/_partials/conditioning/flux2-kv.yaml
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
nodes:
|
| 2 |
+
unet_loader:
|
| 3 |
+
class_type: UNETLoader
|
| 4 |
+
title: "Load Diffusion Model"
|
| 5 |
+
params:
|
| 6 |
+
weight_dtype: "default"
|
| 7 |
+
clip_loader:
|
| 8 |
+
class_type: CLIPLoader
|
| 9 |
+
title: "Load CLIP"
|
| 10 |
+
params:
|
| 11 |
+
type: "flux2"
|
| 12 |
+
device: "default"
|
| 13 |
+
vae_loader:
|
| 14 |
+
class_type: VAELoader
|
| 15 |
+
title: "Load VAE"
|
| 16 |
+
|
| 17 |
+
flux_kv_cache:
|
| 18 |
+
class_type: FluxKVCache
|
| 19 |
+
title: "Flux KV Cache"
|
| 20 |
+
|
| 21 |
+
pos_prompt:
|
| 22 |
+
class_type: CLIPTextEncode
|
| 23 |
+
title: "CLIP Text Encode (Positive)"
|
| 24 |
+
neg_prompt:
|
| 25 |
+
class_type: CLIPTextEncode
|
| 26 |
+
title: "CLIP Text Encode (Negative)"
|
| 27 |
+
|
| 28 |
+
ksampler:
|
| 29 |
+
class_type: KSampler
|
| 30 |
+
title: "KSampler"
|
| 31 |
+
params:
|
| 32 |
+
denoise: 1.0
|
| 33 |
+
|
| 34 |
+
vae_decode:
|
| 35 |
+
class_type: VAEDecode
|
| 36 |
+
title: "VAE Decode"
|
| 37 |
+
|
| 38 |
+
save_image:
|
| 39 |
+
class_type: SaveImage
|
| 40 |
+
title: "Save Image"
|
| 41 |
+
|
| 42 |
+
connections:
|
| 43 |
+
- from: "unet_loader:0"
|
| 44 |
+
to: "flux_kv_cache:model"
|
| 45 |
+
- from: "flux_kv_cache:0"
|
| 46 |
+
to: "ksampler:model"
|
| 47 |
+
|
| 48 |
+
- from: "clip_loader:0"
|
| 49 |
+
to: "pos_prompt:clip"
|
| 50 |
+
- from: "clip_loader:0"
|
| 51 |
+
to: "neg_prompt:clip"
|
| 52 |
+
|
| 53 |
+
- from: "vae_loader:0"
|
| 54 |
+
to: "vae_decode:vae"
|
| 55 |
+
- from: "vae_loader:0"
|
| 56 |
+
to: "vae_encode:vae"
|
| 57 |
+
|
| 58 |
+
- from: "pos_prompt:0"
|
| 59 |
+
to: "ksampler:positive"
|
| 60 |
+
- from: "neg_prompt:0"
|
| 61 |
+
to: "ksampler:negative"
|
| 62 |
+
|
| 63 |
+
- from: "latent_source:0"
|
| 64 |
+
to: "ksampler:latent_image"
|
| 65 |
+
|
| 66 |
+
- from: "ksampler:0"
|
| 67 |
+
to: "vae_decode:samples"
|
| 68 |
+
- from: "vae_decode:0"
|
| 69 |
+
to: "save_image:images"
|
| 70 |
+
|
| 71 |
+
dynamic_lora_chains:
|
| 72 |
+
lora_chain:
|
| 73 |
+
template: "LoraLoader"
|
| 74 |
+
output_map:
|
| 75 |
+
"unet_loader:0": "model"
|
| 76 |
+
"clip_loader:0": "clip"
|
| 77 |
+
input_map:
|
| 78 |
+
"model": "model"
|
| 79 |
+
"clip": "clip"
|
| 80 |
+
end_input_map:
|
| 81 |
+
"model": ["flux_kv_cache:model"]
|
| 82 |
+
"clip": ["pos_prompt:clip", "neg_prompt:clip"]
|
| 83 |
+
|
| 84 |
+
dynamic_reference_latent_chains:
|
| 85 |
+
reference_latent_chain:
|
| 86 |
+
ksampler_node: "ksampler"
|
| 87 |
+
vae_node: "vae_loader"
|
| 88 |
+
|
| 89 |
+
ui_map:
|
| 90 |
+
unet_name: "unet_loader:unet_name"
|
| 91 |
+
clip_name: "clip_loader:clip_name"
|
| 92 |
+
vae_name: "vae_loader:vae_name"
|
| 93 |
+
|
| 94 |
+
positive_prompt: "pos_prompt:text"
|
| 95 |
+
negative_prompt: "neg_prompt:text"
|
| 96 |
+
|
| 97 |
+
seed: "ksampler:seed"
|
| 98 |
+
steps: "ksampler:steps"
|
| 99 |
+
cfg: "ksampler:cfg"
|
| 100 |
+
sampler_name: "ksampler:sampler_name"
|
| 101 |
+
scheduler: "ksampler:scheduler"
|
| 102 |
+
denoise: "ksampler:denoise"
|
| 103 |
+
|
| 104 |
+
filename_prefix: "save_image:filename_prefix"
|
core/pipelines/workflow_recipes/_partials/conditioning/flux2.yaml
CHANGED
|
@@ -20,6 +20,20 @@ nodes:
|
|
| 20 |
neg_prompt:
|
| 21 |
class_type: CLIPTextEncode
|
| 22 |
title: "CLIP Text Encode (Negative)"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
connections:
|
| 25 |
- from: "unet_loader:0"
|
|
@@ -37,6 +51,14 @@ connections:
|
|
| 37 |
to: "ksampler:positive"
|
| 38 |
- from: "neg_prompt:0"
|
| 39 |
to: "ksampler:negative"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
|
| 41 |
dynamic_lora_chains:
|
| 42 |
lora_chain:
|
|
@@ -51,11 +73,6 @@ dynamic_lora_chains:
|
|
| 51 |
"model": ["ksampler:model"]
|
| 52 |
"clip": ["pos_prompt:clip", "neg_prompt:clip"]
|
| 53 |
|
| 54 |
-
dynamic_conditioning_chains:
|
| 55 |
-
conditioning_chain:
|
| 56 |
-
ksampler_node: "ksampler"
|
| 57 |
-
clip_source: "clip_loader:0"
|
| 58 |
-
|
| 59 |
dynamic_reference_latent_chains:
|
| 60 |
reference_latent_chain:
|
| 61 |
ksampler_node: "ksampler"
|
|
@@ -65,5 +82,15 @@ ui_map:
|
|
| 65 |
unet_name: "unet_loader:unet_name"
|
| 66 |
clip_name: "clip_loader:clip_name"
|
| 67 |
vae_name: "vae_loader:vae_name"
|
|
|
|
| 68 |
positive_prompt: "pos_prompt:text"
|
| 69 |
-
negative_prompt: "neg_prompt:text"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
neg_prompt:
|
| 21 |
class_type: CLIPTextEncode
|
| 22 |
title: "CLIP Text Encode (Negative)"
|
| 23 |
+
|
| 24 |
+
ksampler:
|
| 25 |
+
class_type: KSampler
|
| 26 |
+
title: "KSampler"
|
| 27 |
+
params:
|
| 28 |
+
denoise: 1.0
|
| 29 |
+
|
| 30 |
+
vae_decode:
|
| 31 |
+
class_type: VAEDecode
|
| 32 |
+
title: "VAE Decode"
|
| 33 |
+
|
| 34 |
+
save_image:
|
| 35 |
+
class_type: SaveImage
|
| 36 |
+
title: "Save Image"
|
| 37 |
|
| 38 |
connections:
|
| 39 |
- from: "unet_loader:0"
|
|
|
|
| 51 |
to: "ksampler:positive"
|
| 52 |
- from: "neg_prompt:0"
|
| 53 |
to: "ksampler:negative"
|
| 54 |
+
|
| 55 |
+
- from: "latent_source:0"
|
| 56 |
+
to: "ksampler:latent_image"
|
| 57 |
+
|
| 58 |
+
- from: "ksampler:0"
|
| 59 |
+
to: "vae_decode:samples"
|
| 60 |
+
- from: "vae_decode:0"
|
| 61 |
+
to: "save_image:images"
|
| 62 |
|
| 63 |
dynamic_lora_chains:
|
| 64 |
lora_chain:
|
|
|
|
| 73 |
"model": ["ksampler:model"]
|
| 74 |
"clip": ["pos_prompt:clip", "neg_prompt:clip"]
|
| 75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
dynamic_reference_latent_chains:
|
| 77 |
reference_latent_chain:
|
| 78 |
ksampler_node: "ksampler"
|
|
|
|
| 82 |
unet_name: "unet_loader:unet_name"
|
| 83 |
clip_name: "clip_loader:clip_name"
|
| 84 |
vae_name: "vae_loader:vae_name"
|
| 85 |
+
|
| 86 |
positive_prompt: "pos_prompt:text"
|
| 87 |
+
negative_prompt: "neg_prompt:text"
|
| 88 |
+
|
| 89 |
+
seed: "ksampler:seed"
|
| 90 |
+
steps: "ksampler:steps"
|
| 91 |
+
cfg: "ksampler:cfg"
|
| 92 |
+
sampler_name: "ksampler:sampler_name"
|
| 93 |
+
scheduler: "ksampler:scheduler"
|
| 94 |
+
denoise: "ksampler:denoise"
|
| 95 |
+
|
| 96 |
+
filename_prefix: "save_image:filename_prefix"
|
core/pipelines/workflow_recipes/_partials/conditioning/sd35.yaml
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
nodes:
|
| 2 |
+
ckpt_loader:
|
| 3 |
+
class_type: CheckpointLoaderSimple
|
| 4 |
+
title: "Load Checkpoint"
|
| 5 |
+
|
| 6 |
+
connections:
|
| 7 |
+
- from: "ckpt_loader:0"
|
| 8 |
+
to: "ksampler:model"
|
| 9 |
+
- from: "ckpt_loader:1"
|
| 10 |
+
to: "pos_prompt:clip"
|
| 11 |
+
- from: "ckpt_loader:1"
|
| 12 |
+
to: "neg_prompt:clip"
|
| 13 |
+
- from: "pos_prompt:0"
|
| 14 |
+
to: "ksampler:positive"
|
| 15 |
+
- from: "neg_prompt:0"
|
| 16 |
+
to: "ksampler:negative"
|
| 17 |
+
- from: "ckpt_loader:2"
|
| 18 |
+
to: "vae_decode:vae"
|
| 19 |
+
- from: "ckpt_loader:2"
|
| 20 |
+
to: "vae_encode:vae"
|
| 21 |
+
|
| 22 |
+
dynamic_vae_chains:
|
| 23 |
+
vae_chain:
|
| 24 |
+
targets:
|
| 25 |
+
- "vae_decode:vae"
|
| 26 |
+
- "vae_encode:vae"
|
| 27 |
+
|
| 28 |
+
dynamic_lora_chains:
|
| 29 |
+
lora_chain:
|
| 30 |
+
template: "LoraLoader"
|
| 31 |
+
start: "ckpt_loader"
|
| 32 |
+
output_map:
|
| 33 |
+
"0": "model"
|
| 34 |
+
"1": "clip"
|
| 35 |
+
input_map:
|
| 36 |
+
"model": "model"
|
| 37 |
+
"clip": "clip"
|
| 38 |
+
end_input_map:
|
| 39 |
+
"model": ["ksampler:model"]
|
| 40 |
+
"clip": ["pos_prompt:clip", "neg_prompt:clip"]
|
| 41 |
+
|
| 42 |
+
dynamic_controlnet_chains:
|
| 43 |
+
controlnet_chain:
|
| 44 |
+
template: "ControlNetApplyAdvanced"
|
| 45 |
+
ksampler_node: "ksampler"
|
| 46 |
+
vae_source: "ckpt_loader:2"
|
| 47 |
+
|
| 48 |
+
dynamic_sd3_ipadapter_chains:
|
| 49 |
+
sd3_ipadapter_chain:
|
| 50 |
+
ksampler_node: "ksampler"
|
| 51 |
+
|
| 52 |
+
dynamic_conditioning_chains:
|
| 53 |
+
conditioning_chain:
|
| 54 |
+
ksampler_node: "ksampler"
|
| 55 |
+
clip_source: "ckpt_loader:1"
|
| 56 |
+
|
| 57 |
+
ui_map:
|
| 58 |
+
model_name: "ckpt_loader:ckpt_name"
|
core/pipelines/workflow_recipes/_partials/input/hires_fix.yaml
CHANGED
|
@@ -1,15 +1,16 @@
|
|
| 1 |
nodes:
|
| 2 |
input_image_loader:
|
| 3 |
class_type: LoadImage
|
| 4 |
-
|
| 5 |
vae_encode:
|
| 6 |
class_type: VAEEncode
|
| 7 |
-
|
| 8 |
latent_upscaler:
|
| 9 |
class_type: LatentUpscaleBy
|
| 10 |
-
|
| 11 |
latent_source:
|
| 12 |
class_type: RepeatLatentBatch
|
|
|
|
| 13 |
|
| 14 |
connections:
|
| 15 |
- from: "input_image_loader:0"
|
|
|
|
| 1 |
nodes:
|
| 2 |
input_image_loader:
|
| 3 |
class_type: LoadImage
|
| 4 |
+
title: "Load Input Image"
|
| 5 |
vae_encode:
|
| 6 |
class_type: VAEEncode
|
| 7 |
+
title: "VAE Encode (Hires Pre-step)"
|
| 8 |
latent_upscaler:
|
| 9 |
class_type: LatentUpscaleBy
|
| 10 |
+
title: "Upscale Latent By"
|
| 11 |
latent_source:
|
| 12 |
class_type: RepeatLatentBatch
|
| 13 |
+
title: "Repeat Latent Batch for Hires"
|
| 14 |
|
| 15 |
connections:
|
| 16 |
- from: "input_image_loader:0"
|
core/pipelines/workflow_recipes/_partials/input/img2img.yaml
CHANGED
|
@@ -1,12 +1,13 @@
|
|
| 1 |
nodes:
|
| 2 |
input_image_loader:
|
| 3 |
class_type: LoadImage
|
| 4 |
-
|
| 5 |
vae_encode:
|
| 6 |
class_type: VAEEncode
|
| 7 |
-
|
| 8 |
latent_source:
|
| 9 |
class_type: RepeatLatentBatch
|
|
|
|
| 10 |
|
| 11 |
connections:
|
| 12 |
- from: "input_image_loader:0"
|
|
|
|
| 1 |
nodes:
|
| 2 |
input_image_loader:
|
| 3 |
class_type: LoadImage
|
| 4 |
+
title: "Load Input Image"
|
| 5 |
vae_encode:
|
| 6 |
class_type: VAEEncode
|
| 7 |
+
title: "VAE Encode (Img2Img)"
|
| 8 |
latent_source:
|
| 9 |
class_type: RepeatLatentBatch
|
| 10 |
+
title: "Repeat Latent Batch"
|
| 11 |
|
| 12 |
connections:
|
| 13 |
- from: "input_image_loader:0"
|
core/pipelines/workflow_recipes/_partials/input/inpaint.yaml
CHANGED
|
@@ -2,24 +2,22 @@ nodes:
|
|
| 2 |
inpaint_loader:
|
| 3 |
class_type: LoadImage
|
| 4 |
title: "Load Inpaint Image+Mask"
|
| 5 |
-
|
| 6 |
vae_encode:
|
| 7 |
class_type: VAEEncodeForInpaint
|
| 8 |
-
|
| 9 |
-
grow_mask_by: 6
|
| 10 |
-
|
| 11 |
latent_source:
|
| 12 |
class_type: RepeatLatentBatch
|
| 13 |
-
|
|
|
|
| 14 |
connections:
|
| 15 |
- from: "inpaint_loader:0"
|
| 16 |
to: "vae_encode:pixels"
|
| 17 |
- from: "inpaint_loader:1"
|
| 18 |
to: "vae_encode:mask"
|
| 19 |
-
|
| 20 |
- from: "vae_encode:0"
|
| 21 |
to: "latent_source:samples"
|
| 22 |
|
| 23 |
ui_map:
|
| 24 |
-
|
| 25 |
-
batch_size: "latent_source:amount"
|
|
|
|
|
|
| 2 |
inpaint_loader:
|
| 3 |
class_type: LoadImage
|
| 4 |
title: "Load Inpaint Image+Mask"
|
|
|
|
| 5 |
vae_encode:
|
| 6 |
class_type: VAEEncodeForInpaint
|
| 7 |
+
title: "VAE Encode (for Inpainting)"
|
|
|
|
|
|
|
| 8 |
latent_source:
|
| 9 |
class_type: RepeatLatentBatch
|
| 10 |
+
title: "Repeat Latent Batch"
|
| 11 |
+
|
| 12 |
connections:
|
| 13 |
- from: "inpaint_loader:0"
|
| 14 |
to: "vae_encode:pixels"
|
| 15 |
- from: "inpaint_loader:1"
|
| 16 |
to: "vae_encode:mask"
|
|
|
|
| 17 |
- from: "vae_encode:0"
|
| 18 |
to: "latent_source:samples"
|
| 19 |
|
| 20 |
ui_map:
|
| 21 |
+
input_image: "inpaint_loader:image"
|
| 22 |
+
batch_size: "latent_source:amount"
|
| 23 |
+
grow_mask_by: "vae_encode:grow_mask_by"
|
core/pipelines/workflow_recipes/_partials/input/outpaint.yaml
CHANGED
|
@@ -1,38 +1,41 @@
|
|
| 1 |
nodes:
|
| 2 |
input_image_loader:
|
| 3 |
class_type: LoadImage
|
| 4 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
pad_image:
|
| 6 |
class_type: ImagePadForOutpaint
|
| 7 |
-
|
| 8 |
-
feathering: 10
|
| 9 |
-
|
| 10 |
vae_encode:
|
| 11 |
class_type: VAEEncodeForInpaint
|
| 12 |
-
|
| 13 |
-
grow_mask_by: 6
|
| 14 |
-
|
| 15 |
latent_source:
|
| 16 |
class_type: RepeatLatentBatch
|
|
|
|
| 17 |
|
| 18 |
connections:
|
| 19 |
- from: "input_image_loader:0"
|
|
|
|
|
|
|
| 20 |
to: "pad_image:image"
|
| 21 |
-
|
| 22 |
- from: "pad_image:0"
|
| 23 |
to: "vae_encode:pixels"
|
| 24 |
- from: "pad_image:1"
|
| 25 |
to: "vae_encode:mask"
|
| 26 |
-
|
| 27 |
- from: "vae_encode:0"
|
| 28 |
to: "latent_source:samples"
|
| 29 |
|
| 30 |
ui_map:
|
| 31 |
input_image: "input_image_loader:image"
|
| 32 |
-
|
| 33 |
left: "pad_image:left"
|
| 34 |
top: "pad_image:top"
|
| 35 |
right: "pad_image:right"
|
| 36 |
bottom: "pad_image:bottom"
|
| 37 |
-
|
|
|
|
| 38 |
batch_size: "latent_source:amount"
|
|
|
|
| 1 |
nodes:
|
| 2 |
input_image_loader:
|
| 3 |
class_type: LoadImage
|
| 4 |
+
title: "Load Image for Outpaint"
|
| 5 |
+
scale_image:
|
| 6 |
+
class_type: ImageScaleToTotalPixels
|
| 7 |
+
title: "Scale Image to Total Pixels"
|
| 8 |
+
params:
|
| 9 |
+
upscale_method: "nearest-exact"
|
| 10 |
pad_image:
|
| 11 |
class_type: ImagePadForOutpaint
|
| 12 |
+
title: "Pad Image for Outpainting"
|
|
|
|
|
|
|
| 13 |
vae_encode:
|
| 14 |
class_type: VAEEncodeForInpaint
|
| 15 |
+
title: "VAE Encode (for Inpainting)"
|
|
|
|
|
|
|
| 16 |
latent_source:
|
| 17 |
class_type: RepeatLatentBatch
|
| 18 |
+
title: "Repeat Latent Batch"
|
| 19 |
|
| 20 |
connections:
|
| 21 |
- from: "input_image_loader:0"
|
| 22 |
+
to: "scale_image:image"
|
| 23 |
+
- from: "scale_image:0"
|
| 24 |
to: "pad_image:image"
|
|
|
|
| 25 |
- from: "pad_image:0"
|
| 26 |
to: "vae_encode:pixels"
|
| 27 |
- from: "pad_image:1"
|
| 28 |
to: "vae_encode:mask"
|
|
|
|
| 29 |
- from: "vae_encode:0"
|
| 30 |
to: "latent_source:samples"
|
| 31 |
|
| 32 |
ui_map:
|
| 33 |
input_image: "input_image_loader:image"
|
| 34 |
+
megapixels: "scale_image:megapixels"
|
| 35 |
left: "pad_image:left"
|
| 36 |
top: "pad_image:top"
|
| 37 |
right: "pad_image:right"
|
| 38 |
bottom: "pad_image:bottom"
|
| 39 |
+
feathering: "pad_image:feathering"
|
| 40 |
+
grow_mask_by: "vae_encode:grow_mask_by"
|
| 41 |
batch_size: "latent_source:amount"
|
core/pipelines/workflow_recipes/_partials/input/txt2img.yaml
CHANGED
|
@@ -1,8 +1,2 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
class_type: EmptyFlux2LatentImage
|
| 4 |
-
|
| 5 |
-
ui_map:
|
| 6 |
-
width: "latent_source:width"
|
| 7 |
-
height: "latent_source:height"
|
| 8 |
-
batch_size: "latent_source:batch_size"
|
|
|
|
| 1 |
+
imports:
|
| 2 |
+
- "txt2img_{{ latent_type }}.yaml"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/pipelines/workflow_recipes/_partials/input/txt2img_chroma_radiance_latent.yaml
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
nodes:
|
| 2 |
+
latent_source:
|
| 3 |
+
class_type: "EmptyChromaRadianceLatentImage"
|
| 4 |
+
title: "EmptyChromaRadianceLatentImage"
|
| 5 |
+
|
| 6 |
+
connections: []
|
| 7 |
+
|
| 8 |
+
ui_map:
|
| 9 |
+
width: "latent_source:width"
|
| 10 |
+
height: "latent_source:height"
|
| 11 |
+
batch_size: "latent_source:batch_size"
|
core/pipelines/workflow_recipes/_partials/input/txt2img_flux2_latent.yaml
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
nodes:
|
| 2 |
+
latent_source:
|
| 3 |
+
class_type: "EmptyFlux2LatentImage"
|
| 4 |
+
title: "Empty Flux 2 Latent"
|
| 5 |
+
|
| 6 |
+
connections: []
|
| 7 |
+
|
| 8 |
+
ui_map:
|
| 9 |
+
width: "latent_source:width"
|
| 10 |
+
height: "latent_source:height"
|
| 11 |
+
batch_size: "latent_source:batch_size"
|
core/pipelines/workflow_recipes/_partials/input/txt2img_hunyuan_latent.yaml
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
nodes:
|
| 2 |
+
latent_source:
|
| 3 |
+
class_type: "EmptyHunyuanImageLatent"
|
| 4 |
+
title: "EmptyHunyuanImageLatent"
|
| 5 |
+
|
| 6 |
+
connections: []
|
| 7 |
+
|
| 8 |
+
ui_map:
|
| 9 |
+
width: "latent_source:width"
|
| 10 |
+
height: "latent_source:height"
|
| 11 |
+
batch_size: "latent_source:batch_size"
|
core/pipelines/workflow_recipes/_partials/input/txt2img_latent.yaml
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
nodes:
|
| 2 |
+
latent_source:
|
| 3 |
+
class_type: "{{ latent_generator_template }}"
|
| 4 |
+
title: "Empty Latent Image"
|
| 5 |
+
|
| 6 |
+
connections: []
|
| 7 |
+
|
| 8 |
+
ui_map:
|
| 9 |
+
width: "latent_source:width"
|
| 10 |
+
height: "latent_source:height"
|
| 11 |
+
batch_size: "latent_source:batch_size"
|
core/pipelines/workflow_recipes/_partials/input/txt2img_sd3_latent.yaml
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
nodes:
|
| 2 |
+
latent_source:
|
| 3 |
+
class_type: "EmptySD3LatentImage"
|
| 4 |
+
title: "EmptySD3LatentImage"
|
| 5 |
+
|
| 6 |
+
connections: []
|
| 7 |
+
|
| 8 |
+
ui_map:
|
| 9 |
+
width: "latent_source:width"
|
| 10 |
+
height: "latent_source:height"
|
| 11 |
+
batch_size: "latent_source:batch_size"
|
core/pipelines/workflow_recipes/sd_unified_recipe.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
imports:
|
| 2 |
-
- "_partials/
|
| 3 |
- "_partials/input/{{ task_type }}.yaml"
|
| 4 |
-
- "_partials/conditioning/
|
| 5 |
|
| 6 |
connections:
|
| 7 |
- from: "latent_source:0"
|
|
|
|
| 1 |
imports:
|
| 2 |
+
- "_partials/_base_sampler_sd.yaml"
|
| 3 |
- "_partials/input/{{ task_type }}.yaml"
|
| 4 |
+
- "_partials/conditioning/{{ model_type }}.yaml"
|
| 5 |
|
| 6 |
connections:
|
| 7 |
- from: "latent_source:0"
|
core/settings.py
CHANGED
|
@@ -10,16 +10,37 @@ MODEL_PATCHES_DIR = "models/model_patches"
|
|
| 10 |
DIFFUSION_MODELS_DIR = "models/diffusion_models"
|
| 11 |
VAE_DIR = "models/vae"
|
| 12 |
TEXT_ENCODERS_DIR = "models/text_encoders"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
INPUT_DIR = "input"
|
| 14 |
OUTPUT_DIR = "output"
|
| 15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
_PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 17 |
_MODEL_LIST_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'model_list.yaml')
|
| 18 |
_FILE_LIST_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'file_list.yaml')
|
|
|
|
| 19 |
_CONSTANTS_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'constants.yaml')
|
|
|
|
|
|
|
| 20 |
_MODEL_DEFAULTS_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'model_defaults.yaml')
|
| 21 |
|
| 22 |
-
|
| 23 |
def load_constants_from_yaml(filepath=_CONSTANTS_PATH):
|
| 24 |
if not os.path.exists(filepath):
|
| 25 |
print(f"Warning: Constants file not found at {filepath}. Using fallback values.")
|
|
@@ -27,6 +48,27 @@ def load_constants_from_yaml(filepath=_CONSTANTS_PATH):
|
|
| 27 |
with open(filepath, 'r', encoding='utf-8') as f:
|
| 28 |
return yaml.safe_load(f)
|
| 29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
def load_file_download_map(filepath=_FILE_LIST_PATH):
|
| 31 |
if not os.path.exists(filepath):
|
| 32 |
raise FileNotFoundError(f"The file list (for downloads) was not found at: {filepath}")
|
|
@@ -59,50 +101,86 @@ def load_models_from_yaml(model_list_filepath=_MODEL_LIST_PATH, download_map=Non
|
|
| 59 |
}
|
| 60 |
category_map_names = {
|
| 61 |
"Checkpoint": "MODEL_MAP_CHECKPOINT",
|
|
|
|
| 62 |
}
|
| 63 |
|
| 64 |
-
for category,
|
| 65 |
if category in category_map_names:
|
| 66 |
map_name = category_map_names[category]
|
| 67 |
-
if not isinstance(
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
|
| 81 |
return model_maps
|
| 82 |
|
| 83 |
-
def load_model_defaults(filepath=_MODEL_DEFAULTS_PATH):
|
| 84 |
-
if not os.path.exists(filepath):
|
| 85 |
-
print(f"Warning: Model defaults file not found at {filepath}. Using empty defaults.")
|
| 86 |
-
return {}
|
| 87 |
-
with open(filepath, 'r', encoding='utf-8') as f:
|
| 88 |
-
return yaml.safe_load(f)
|
| 89 |
-
|
| 90 |
try:
|
| 91 |
ALL_FILE_DOWNLOAD_MAP = load_file_download_map()
|
| 92 |
loaded_maps = load_models_from_yaml(download_map=ALL_FILE_DOWNLOAD_MAP)
|
| 93 |
MODEL_MAP_CHECKPOINT = loaded_maps["MODEL_MAP_CHECKPOINT"]
|
| 94 |
ALL_MODEL_MAP = loaded_maps["ALL_MODEL_MAP"]
|
| 95 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
MODEL_TYPE_MAP = {k: v[2] for k, v in ALL_MODEL_MAP.items()}
|
| 97 |
-
|
| 98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
|
| 100 |
except Exception as e:
|
| 101 |
print(f"FATAL: Could not load model configuration from YAML. Error: {e}")
|
| 102 |
ALL_FILE_DOWNLOAD_MAP = {}
|
| 103 |
MODEL_MAP_CHECKPOINT, ALL_MODEL_MAP = {}, {}
|
| 104 |
MODEL_TYPE_MAP = {}
|
| 105 |
-
|
| 106 |
|
| 107 |
|
| 108 |
try:
|
|
@@ -111,15 +189,17 @@ try:
|
|
| 111 |
MAX_EMBEDDINGS = _constants.get('MAX_EMBEDDINGS', 5)
|
| 112 |
MAX_CONDITIONINGS = _constants.get('MAX_CONDITIONINGS', 10)
|
| 113 |
MAX_CONTROLNETS = _constants.get('MAX_CONTROLNETS', 5)
|
| 114 |
-
|
| 115 |
LORA_SOURCE_CHOICES = _constants.get('LORA_SOURCE_CHOICES', ["Civitai", "File"])
|
| 116 |
RESOLUTION_MAP = _constants.get('RESOLUTION_MAP', {})
|
|
|
|
|
|
|
|
|
|
| 117 |
except Exception as e:
|
| 118 |
print(f"FATAL: Could not load constants from YAML. Error: {e}")
|
| 119 |
-
MAX_LORAS, MAX_EMBEDDINGS, MAX_CONDITIONINGS, MAX_CONTROLNETS = 5, 5, 10, 5
|
| 120 |
-
MAX_REFERENCE_LATENTS = 10
|
| 121 |
LORA_SOURCE_CHOICES = ["Civitai", "File"]
|
| 122 |
RESOLUTION_MAP = {}
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
|
|
|
| 10 |
DIFFUSION_MODELS_DIR = "models/diffusion_models"
|
| 11 |
VAE_DIR = "models/vae"
|
| 12 |
TEXT_ENCODERS_DIR = "models/text_encoders"
|
| 13 |
+
STYLE_MODELS_DIR = "models/style_models"
|
| 14 |
+
CLIP_VISION_DIR = "models/clip_vision"
|
| 15 |
+
IPADAPTER_DIR = "models/ipadapter"
|
| 16 |
+
IPADAPTER_FLUX_DIR = "models/ipadapter-flux"
|
| 17 |
INPUT_DIR = "input"
|
| 18 |
OUTPUT_DIR = "output"
|
| 19 |
|
| 20 |
+
CATEGORY_TO_DIR_MAP = {
|
| 21 |
+
"diffusion_models": DIFFUSION_MODELS_DIR,
|
| 22 |
+
"text_encoders": TEXT_ENCODERS_DIR,
|
| 23 |
+
"vae": VAE_DIR,
|
| 24 |
+
"checkpoints": CHECKPOINT_DIR,
|
| 25 |
+
"loras": LORA_DIR,
|
| 26 |
+
"controlnet": CONTROLNET_DIR,
|
| 27 |
+
"model_patches": MODEL_PATCHES_DIR,
|
| 28 |
+
"embeddings": EMBEDDING_DIR,
|
| 29 |
+
"style_models": STYLE_MODELS_DIR,
|
| 30 |
+
"clip_vision": CLIP_VISION_DIR,
|
| 31 |
+
"ipadapter": IPADAPTER_DIR,
|
| 32 |
+
"ipadapter-flux": IPADAPTER_FLUX_DIR
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
_PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 36 |
_MODEL_LIST_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'model_list.yaml')
|
| 37 |
_FILE_LIST_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'file_list.yaml')
|
| 38 |
+
_IPADAPTER_LIST_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'ipadapter.yaml')
|
| 39 |
_CONSTANTS_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'constants.yaml')
|
| 40 |
+
_MODEL_ARCHITECTURES_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'model_architectures.yaml')
|
| 41 |
+
_IMAGE_GEN_FEATURES_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'image_gen_features.yaml')
|
| 42 |
_MODEL_DEFAULTS_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'model_defaults.yaml')
|
| 43 |
|
|
|
|
| 44 |
def load_constants_from_yaml(filepath=_CONSTANTS_PATH):
|
| 45 |
if not os.path.exists(filepath):
|
| 46 |
print(f"Warning: Constants file not found at {filepath}. Using fallback values.")
|
|
|
|
| 48 |
with open(filepath, 'r', encoding='utf-8') as f:
|
| 49 |
return yaml.safe_load(f)
|
| 50 |
|
| 51 |
+
def load_architectures_config(filepath=_MODEL_ARCHITECTURES_PATH):
|
| 52 |
+
if not os.path.exists(filepath):
|
| 53 |
+
print(f"Warning: Architectures file not found at {filepath}.")
|
| 54 |
+
return {}
|
| 55 |
+
with open(filepath, 'r', encoding='utf-8') as f:
|
| 56 |
+
return yaml.safe_load(f)
|
| 57 |
+
|
| 58 |
+
def load_features_config(filepath=_IMAGE_GEN_FEATURES_PATH):
|
| 59 |
+
if not os.path.exists(filepath):
|
| 60 |
+
print(f"Warning: Features file not found at {filepath}.")
|
| 61 |
+
return {}
|
| 62 |
+
with open(filepath, 'r', encoding='utf-8') as f:
|
| 63 |
+
return yaml.safe_load(f)
|
| 64 |
+
|
| 65 |
+
def load_model_defaults(filepath=_MODEL_DEFAULTS_PATH):
|
| 66 |
+
if not os.path.exists(filepath):
|
| 67 |
+
print(f"Warning: Model defaults file not found at {filepath}.")
|
| 68 |
+
return {}
|
| 69 |
+
with open(filepath, 'r', encoding='utf-8') as f:
|
| 70 |
+
return yaml.safe_load(f)
|
| 71 |
+
|
| 72 |
def load_file_download_map(filepath=_FILE_LIST_PATH):
|
| 73 |
if not os.path.exists(filepath):
|
| 74 |
raise FileNotFoundError(f"The file list (for downloads) was not found at: {filepath}")
|
|
|
|
| 101 |
}
|
| 102 |
category_map_names = {
|
| 103 |
"Checkpoint": "MODEL_MAP_CHECKPOINT",
|
| 104 |
+
"Checkpoints": "MODEL_MAP_CHECKPOINT"
|
| 105 |
}
|
| 106 |
|
| 107 |
+
for category, architectures in model_data.items():
|
| 108 |
if category in category_map_names:
|
| 109 |
map_name = category_map_names[category]
|
| 110 |
+
if not isinstance(architectures, dict): continue
|
| 111 |
+
|
| 112 |
+
for arch, arch_data in architectures.items():
|
| 113 |
+
if not isinstance(arch_data, dict): continue
|
| 114 |
+
|
| 115 |
+
latent_type = arch_data.get('latent_type', 'latent')
|
| 116 |
+
models = arch_data.get('models', [])
|
| 117 |
+
if not isinstance(models, list): continue
|
| 118 |
+
|
| 119 |
+
for model in models:
|
| 120 |
+
display_name = model['display_name']
|
| 121 |
+
path_or_components = model.get('path') or model.get('components')
|
| 122 |
+
mod_category = model.get('category', None)
|
| 123 |
+
|
| 124 |
+
repo_id = ''
|
| 125 |
+
if isinstance(path_or_components, str):
|
| 126 |
+
download_info = download_map.get(path_or_components, {})
|
| 127 |
+
repo_id = download_info.get('repo_id', '')
|
| 128 |
+
|
| 129 |
+
model_tuple = (
|
| 130 |
+
repo_id,
|
| 131 |
+
path_or_components,
|
| 132 |
+
arch,
|
| 133 |
+
latent_type,
|
| 134 |
+
mod_category
|
| 135 |
+
)
|
| 136 |
+
model_maps[map_name][display_name] = model_tuple
|
| 137 |
+
model_maps["ALL_MODEL_MAP"][display_name] = model_tuple
|
| 138 |
|
| 139 |
return model_maps
|
| 140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
try:
|
| 142 |
ALL_FILE_DOWNLOAD_MAP = load_file_download_map()
|
| 143 |
loaded_maps = load_models_from_yaml(download_map=ALL_FILE_DOWNLOAD_MAP)
|
| 144 |
MODEL_MAP_CHECKPOINT = loaded_maps["MODEL_MAP_CHECKPOINT"]
|
| 145 |
ALL_MODEL_MAP = loaded_maps["ALL_MODEL_MAP"]
|
| 146 |
|
| 147 |
+
category_to_model_type = {
|
| 148 |
+
"diffusion_models": "UNET",
|
| 149 |
+
"text_encoders": "TEXT_ENCODER",
|
| 150 |
+
"vae": "VAE",
|
| 151 |
+
"checkpoints": "SDXL",
|
| 152 |
+
"loras": "LORA",
|
| 153 |
+
"controlnet": "CONTROLNET",
|
| 154 |
+
"model_patches": "MODEL_PATCH",
|
| 155 |
+
"style_models": "STYLE",
|
| 156 |
+
"clip_vision": "CLIP_VISION",
|
| 157 |
+
"ipadapter": "IPADAPTER",
|
| 158 |
+
"ipadapter-flux": "IPADAPTER_FLUX"
|
| 159 |
+
}
|
| 160 |
+
for filename, file_info in ALL_FILE_DOWNLOAD_MAP.items():
|
| 161 |
+
if filename not in ALL_MODEL_MAP:
|
| 162 |
+
category = file_info.get('category')
|
| 163 |
+
model_type = category_to_model_type.get(category, 'UNKNOWN')
|
| 164 |
+
repo_id = file_info.get('repo_id', '')
|
| 165 |
+
ALL_MODEL_MAP[filename] = (repo_id, filename, model_type, None, None)
|
| 166 |
+
|
| 167 |
MODEL_TYPE_MAP = {k: v[2] for k, v in ALL_MODEL_MAP.items()}
|
| 168 |
+
|
| 169 |
+
ARCH_CATEGORIES_MAP = {}
|
| 170 |
+
for display_name, info in MODEL_MAP_CHECKPOINT.items():
|
| 171 |
+
arch = info[2]
|
| 172 |
+
cat = info[4] if len(info) > 4 else None
|
| 173 |
+
if arch not in ARCH_CATEGORIES_MAP:
|
| 174 |
+
ARCH_CATEGORIES_MAP[arch] = []
|
| 175 |
+
if cat and cat not in ARCH_CATEGORIES_MAP[arch]:
|
| 176 |
+
ARCH_CATEGORIES_MAP[arch].append(cat)
|
| 177 |
|
| 178 |
except Exception as e:
|
| 179 |
print(f"FATAL: Could not load model configuration from YAML. Error: {e}")
|
| 180 |
ALL_FILE_DOWNLOAD_MAP = {}
|
| 181 |
MODEL_MAP_CHECKPOINT, ALL_MODEL_MAP = {}, {}
|
| 182 |
MODEL_TYPE_MAP = {}
|
| 183 |
+
ARCH_CATEGORIES_MAP = {}
|
| 184 |
|
| 185 |
|
| 186 |
try:
|
|
|
|
| 189 |
MAX_EMBEDDINGS = _constants.get('MAX_EMBEDDINGS', 5)
|
| 190 |
MAX_CONDITIONINGS = _constants.get('MAX_CONDITIONINGS', 10)
|
| 191 |
MAX_CONTROLNETS = _constants.get('MAX_CONTROLNETS', 5)
|
| 192 |
+
MAX_IPADAPTERS = _constants.get('MAX_IPADAPTERS', 5)
|
| 193 |
LORA_SOURCE_CHOICES = _constants.get('LORA_SOURCE_CHOICES', ["Civitai", "File"])
|
| 194 |
RESOLUTION_MAP = _constants.get('RESOLUTION_MAP', {})
|
| 195 |
+
ARCHITECTURES_CONFIG = load_architectures_config()
|
| 196 |
+
FEATURES_CONFIG = load_features_config()
|
| 197 |
+
MODEL_DEFAULTS_CONFIG = load_model_defaults()
|
| 198 |
except Exception as e:
|
| 199 |
print(f"FATAL: Could not load constants from YAML. Error: {e}")
|
| 200 |
+
MAX_LORAS, MAX_EMBEDDINGS, MAX_CONDITIONINGS, MAX_CONTROLNETS, MAX_IPADAPTERS = 5, 5, 10, 5, 5
|
|
|
|
| 201 |
LORA_SOURCE_CHOICES = ["Civitai", "File"]
|
| 202 |
RESOLUTION_MAP = {}
|
| 203 |
+
ARCHITECTURES_CONFIG = {}
|
| 204 |
+
FEATURES_CONFIG = {}
|
| 205 |
+
MODEL_DEFAULTS_CONFIG = {}
|
requirements.txt
CHANGED
|
@@ -1,10 +1,10 @@
|
|
| 1 |
-
comfyui-frontend-package==1.42.
|
| 2 |
-
comfyui-workflow-templates==0.9.
|
| 3 |
-
comfyui-embedded-docs==0.4.
|
| 4 |
-
torch
|
| 5 |
torchsde
|
| 6 |
-
torchvision
|
| 7 |
-
torchaudio
|
| 8 |
numpy>=1.25.0
|
| 9 |
einops
|
| 10 |
transformers>=4.50.3
|
|
@@ -19,11 +19,11 @@ scipy
|
|
| 19 |
tqdm
|
| 20 |
psutil
|
| 21 |
alembic
|
| 22 |
-
SQLAlchemy
|
| 23 |
filelock
|
| 24 |
av>=14.2.0
|
| 25 |
comfy-kitchen>=0.2.8
|
| 26 |
-
comfy-aimdo
|
| 27 |
requests
|
| 28 |
simpleeval>=1.0.0
|
| 29 |
blake3
|
|
@@ -58,4 +58,5 @@ svglib
|
|
| 58 |
trimesh[easy]
|
| 59 |
yacs
|
| 60 |
yapf
|
| 61 |
-
onnxruntime-gpu
|
|
|
|
|
|
| 1 |
+
comfyui-frontend-package==1.42.15
|
| 2 |
+
comfyui-workflow-templates==0.9.66
|
| 3 |
+
comfyui-embedded-docs==0.4.4
|
| 4 |
+
torch==2.10.0
|
| 5 |
torchsde
|
| 6 |
+
torchvision==0.25.0
|
| 7 |
+
torchaudio==2.10.0
|
| 8 |
numpy>=1.25.0
|
| 9 |
einops
|
| 10 |
transformers>=4.50.3
|
|
|
|
| 19 |
tqdm
|
| 20 |
psutil
|
| 21 |
alembic
|
| 22 |
+
SQLAlchemy>=2.0.0
|
| 23 |
filelock
|
| 24 |
av>=14.2.0
|
| 25 |
comfy-kitchen>=0.2.8
|
| 26 |
+
comfy-aimdo==0.3.0
|
| 27 |
requests
|
| 28 |
simpleeval>=1.0.0
|
| 29 |
blake3
|
|
|
|
| 58 |
trimesh[easy]
|
| 59 |
yacs
|
| 60 |
yapf
|
| 61 |
+
onnxruntime-gpu
|
| 62 |
+
diffusers
|
ui/events.py
CHANGED
|
@@ -8,150 +8,193 @@ from utils.app_utils import *
|
|
| 8 |
from core.generation_logic import *
|
| 9 |
from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
|
| 10 |
|
| 11 |
-
from
|
| 12 |
-
from
|
| 13 |
-
from ui.shared.ui_components import RESOLUTION_MAP, MAX_CONTROLNETS, MAX_EMBEDDINGS, MAX_CONDITIONINGS, MAX_LORAS, MAX_REFERENCE_LATENTS
|
| 14 |
|
| 15 |
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
if model_display_name in models_in_category:
|
| 29 |
-
if '_defaults' in models_in_category:
|
| 30 |
-
defaults.update(models_in_category['_defaults'])
|
| 31 |
-
defaults.update(models_in_category[model_display_name])
|
| 32 |
-
model_found = True
|
| 33 |
-
break
|
| 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 |
-
s_idx, d_idx, c_idx = 0, 0, 0
|
| 70 |
-
|
| 71 |
-
for param in params:
|
| 72 |
-
if s_idx + d_idx + c_idx >= MAX_DYNAMIC_CONTROLS: break
|
| 73 |
-
|
| 74 |
-
name = param["name"]
|
| 75 |
-
ptype = param["type"]
|
| 76 |
-
config = param["config"]
|
| 77 |
-
label = name.replace('_', ' ').title()
|
| 78 |
-
|
| 79 |
-
if ptype == "INT" or ptype == "FLOAT":
|
| 80 |
-
if s_idx < MAX_DYNAMIC_CONTROLS:
|
| 81 |
-
slider_updates.append(gr.update(
|
| 82 |
-
label=label,
|
| 83 |
-
minimum=config.get('min', 0),
|
| 84 |
-
maximum=config.get('max', 255),
|
| 85 |
-
step=config.get('step', 0.1 if ptype == "FLOAT" else 1),
|
| 86 |
-
value=config.get('default', 0),
|
| 87 |
-
visible=True
|
| 88 |
-
))
|
| 89 |
-
s_idx += 1
|
| 90 |
-
elif isinstance(ptype, list):
|
| 91 |
-
if d_idx < MAX_DYNAMIC_CONTROLS:
|
| 92 |
-
dropdown_updates.append(gr.update(
|
| 93 |
-
label=label,
|
| 94 |
-
choices=ptype,
|
| 95 |
-
value=config.get('default', ptype[0] if ptype else None),
|
| 96 |
-
visible=True
|
| 97 |
-
))
|
| 98 |
-
d_idx += 1
|
| 99 |
-
elif ptype == "BOOLEAN":
|
| 100 |
-
if c_idx < MAX_DYNAMIC_CONTROLS:
|
| 101 |
-
checkbox_updates.append(gr.update(
|
| 102 |
-
label=label,
|
| 103 |
-
value=config.get('default', False),
|
| 104 |
-
visible=True
|
| 105 |
-
))
|
| 106 |
-
c_idx += 1
|
| 107 |
-
|
| 108 |
-
for _ in range(s_idx, MAX_DYNAMIC_CONTROLS): slider_updates.append(gr.update(visible=False))
|
| 109 |
-
for _ in range(d_idx, MAX_DYNAMIC_CONTROLS): dropdown_updates.append(gr.update(visible=False))
|
| 110 |
-
for _ in range(c_idx, MAX_DYNAMIC_CONTROLS): checkbox_updates.append(gr.update(visible=False))
|
| 111 |
-
|
| 112 |
-
return slider_updates + dropdown_updates + checkbox_updates
|
| 113 |
-
|
| 114 |
-
def update_run_button_for_cpu(preprocessor_name):
|
| 115 |
-
if preprocessor_name in CPU_ONLY_PREPROCESSORS:
|
| 116 |
-
return gr.update(value="Run Preprocessor CPU Only", variant="primary"), gr.update(visible=False)
|
| 117 |
else:
|
| 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 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 153 |
def create_lora_event_handlers(prefix):
|
| 154 |
-
lora_rows = ui_components
|
|
|
|
| 155 |
lora_ids = ui_components[f'lora_ids_{prefix}']
|
| 156 |
lora_scales = ui_components[f'lora_scales_{prefix}']
|
| 157 |
lora_uploads = ui_components[f'lora_uploads_{prefix}']
|
|
@@ -190,8 +233,362 @@ def attach_event_handlers(ui_components, demo):
|
|
| 190 |
add_button.click(add_lora_row, [count_state], add_outputs, show_progress=False)
|
| 191 |
del_button.click(del_lora_row, [count_state], del_outputs, show_progress=False)
|
| 192 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
def create_embedding_event_handlers(prefix):
|
| 194 |
-
rows = ui_components
|
|
|
|
| 195 |
ids = ui_components[f'embeddings_ids_{prefix}']
|
| 196 |
files = ui_components[f'embeddings_files_{prefix}']
|
| 197 |
count_state = ui_components[f'embedding_count_state_{prefix}']
|
|
@@ -224,7 +621,8 @@ def attach_event_handlers(ui_components, demo):
|
|
| 224 |
del_button.click(fn=del_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
|
| 225 |
|
| 226 |
def create_conditioning_event_handlers(prefix):
|
| 227 |
-
rows = ui_components
|
|
|
|
| 228 |
prompts = ui_components[f'conditioning_prompts_{prefix}']
|
| 229 |
count_state = ui_components[f'conditioning_count_state_{prefix}']
|
| 230 |
add_button = ui_components[f'add_conditioning_button_{prefix}']
|
|
@@ -253,37 +651,6 @@ def attach_event_handlers(ui_components, demo):
|
|
| 253 |
del_outputs = [count_state, add_button, del_button] + rows + prompts
|
| 254 |
add_button.click(fn=add_row, inputs=[count_state], outputs=add_outputs, show_progress=False)
|
| 255 |
del_button.click(fn=del_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
|
| 256 |
-
|
| 257 |
-
def create_reference_latent_event_handlers(prefix):
|
| 258 |
-
rows = ui_components[f'reference_latent_rows_{prefix}']
|
| 259 |
-
images = ui_components[f'reference_latent_images_{prefix}']
|
| 260 |
-
count_state = ui_components[f'reference_latent_count_state_{prefix}']
|
| 261 |
-
add_button = ui_components[f'add_reference_latent_button_{prefix}']
|
| 262 |
-
del_button = ui_components[f'delete_reference_latent_button_{prefix}']
|
| 263 |
-
|
| 264 |
-
def add_row(c):
|
| 265 |
-
c += 1
|
| 266 |
-
return {
|
| 267 |
-
count_state: c,
|
| 268 |
-
rows[c - 1]: gr.update(visible=True),
|
| 269 |
-
add_button: gr.update(visible=c < MAX_REFERENCE_LATENTS),
|
| 270 |
-
del_button: gr.update(visible=True),
|
| 271 |
-
}
|
| 272 |
-
|
| 273 |
-
def del_row(c):
|
| 274 |
-
c -= 1
|
| 275 |
-
return {
|
| 276 |
-
count_state: c,
|
| 277 |
-
rows[c]: gr.update(visible=False),
|
| 278 |
-
images[c]: None,
|
| 279 |
-
add_button: gr.update(visible=True),
|
| 280 |
-
del_button: gr.update(visible=c > 0),
|
| 281 |
-
}
|
| 282 |
-
|
| 283 |
-
add_outputs = [count_state, add_button, del_button] + rows
|
| 284 |
-
del_outputs = [count_state, add_button, del_button] + rows + images
|
| 285 |
-
add_button.click(fn=add_row, inputs=[count_state], outputs=add_outputs, show_progress=False)
|
| 286 |
-
del_button.click(fn=del_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
|
| 287 |
|
| 288 |
def on_vae_upload(file_obj):
|
| 289 |
if not file_obj:
|
|
@@ -310,37 +677,48 @@ def attach_event_handlers(ui_components, demo):
|
|
| 310 |
def create_run_event(prefix: str, task_type: str):
|
| 311 |
run_inputs_map = {
|
| 312 |
'model_display_name': ui_components[f'base_model_{prefix}'],
|
| 313 |
-
'positive_prompt': ui_components
|
| 314 |
-
'negative_prompt': ui_components
|
| 315 |
-
'seed': ui_components
|
| 316 |
-
'batch_size': ui_components
|
| 317 |
-
'guidance_scale': ui_components
|
| 318 |
-
'num_inference_steps': ui_components
|
| 319 |
-
'sampler': ui_components
|
| 320 |
-
'scheduler': ui_components
|
| 321 |
-
'zero_gpu_duration': ui_components
|
| 322 |
-
|
| 323 |
-
'clip_skip': ui_components
|
|
|
|
| 324 |
'task_type': gr.State(task_type)
|
| 325 |
}
|
| 326 |
|
| 327 |
if task_type not in ['img2img', 'inpaint']:
|
| 328 |
-
run_inputs_map.update({
|
|
|
|
|
|
|
|
|
|
| 329 |
|
| 330 |
task_specific_map = {
|
| 331 |
'img2img': {'img2img_image': f'input_image_{prefix}', 'img2img_denoise': f'denoise_{prefix}'},
|
| 332 |
-
'inpaint': {'inpaint_image_dict': f'input_image_dict_{prefix}'},
|
| 333 |
-
'outpaint': {'outpaint_image': f'input_image_{prefix}', '
|
| 334 |
'hires_fix': {'hires_image': f'input_image_{prefix}', 'hires_upscaler': f'hires_upscaler_{prefix}', 'hires_scale_by': f'hires_scale_by_{prefix}', 'hires_denoise': f'denoise_{prefix}'}
|
| 335 |
}
|
| 336 |
if task_type in task_specific_map:
|
| 337 |
for key, comp_name in task_specific_map[task_type].items():
|
| 338 |
-
|
|
|
|
| 339 |
|
| 340 |
lora_data_components = ui_components.get(f'all_lora_components_flat_{prefix}', [])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 341 |
embedding_data_components = ui_components.get(f'all_embedding_components_flat_{prefix}', [])
|
| 342 |
conditioning_data_components = ui_components.get(f'all_conditioning_components_flat_{prefix}', [])
|
| 343 |
-
|
| 344 |
|
| 345 |
run_inputs_map['vae_source'] = ui_components.get(f'vae_source_{prefix}')
|
| 346 |
run_inputs_map['vae_id'] = ui_components.get(f'vae_id_{prefix}')
|
|
@@ -348,153 +726,533 @@ def attach_event_handlers(ui_components, demo):
|
|
| 348 |
|
| 349 |
input_keys = list(run_inputs_map.keys())
|
| 350 |
input_list_flat = [v for v in run_inputs_map.values() if v is not None]
|
| 351 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 352 |
|
| 353 |
def create_ui_inputs_dict(*args):
|
| 354 |
valid_keys = [k for k in input_keys if run_inputs_map[k] is not None]
|
| 355 |
ui_dict = dict(zip(valid_keys, args[:len(valid_keys)]))
|
| 356 |
arg_idx = len(valid_keys)
|
| 357 |
-
|
| 358 |
-
ui_dict['lora_data'] = list(args[arg_idx : arg_idx + len(lora_data_components)])
|
| 359 |
-
arg_idx += len(lora_data_components)
|
| 360 |
-
ui_dict['embedding_data'] = list(args[arg_idx : arg_idx + len(embedding_data_components)])
|
| 361 |
-
arg_idx += len(embedding_data_components)
|
| 362 |
-
ui_dict['conditioning_data'] = list(args[arg_idx : arg_idx + len(conditioning_data_components)])
|
| 363 |
-
arg_idx += len(conditioning_data_components)
|
| 364 |
-
ui_dict['reference_latent_data'] = list(args[arg_idx : arg_idx + len(reference_latent_components)])
|
| 365 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 366 |
|
| 367 |
return ui_dict
|
| 368 |
|
| 369 |
-
ui_components
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 374 |
|
| 375 |
|
| 376 |
for prefix, task_type in [
|
| 377 |
("txt2img", "txt2img"), ("img2img", "img2img"), ("inpaint", "inpaint"),
|
| 378 |
("outpaint", "outpaint"), ("hires_fix", "hires_fix"),
|
| 379 |
]:
|
| 380 |
-
model_dropdown = ui_components.get(f'base_model_{prefix}')
|
| 381 |
-
steps_slider = ui_components.get(f'steps_{prefix}')
|
| 382 |
-
cfg_slider = ui_components.get(f'cfg_{prefix}')
|
| 383 |
-
if all([model_dropdown, steps_slider, cfg_slider]):
|
| 384 |
-
model_dropdown.change(
|
| 385 |
-
fn=on_model_change,
|
| 386 |
-
inputs=[model_dropdown],
|
| 387 |
-
outputs=[steps_slider, cfg_slider],
|
| 388 |
-
show_progress=False
|
| 389 |
-
)
|
| 390 |
|
| 391 |
-
|
| 392 |
-
|
| 393 |
-
|
| 394 |
-
|
| 395 |
-
|
| 396 |
-
|
| 397 |
-
|
| 398 |
-
|
| 399 |
-
|
| 400 |
-
|
| 401 |
-
|
| 402 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 403 |
|
| 404 |
-
if
|
| 405 |
-
|
| 406 |
-
if
|
| 407 |
-
|
| 408 |
-
|
| 409 |
-
|
| 410 |
-
|
| 411 |
-
|
| 412 |
-
|
| 413 |
-
|
| 414 |
-
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
|
| 422 |
-
if
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
|
| 430 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 431 |
)
|
|
|
|
| 432 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 433 |
create_run_event(prefix, task_type)
|
| 434 |
|
| 435 |
-
def on_aspect_ratio_change(ratio_key, model_display_name):
|
| 436 |
-
model_type = MODEL_TYPE_MAP.get(model_display_name, 'sdxl').lower()
|
| 437 |
-
res_map = RESOLUTION_MAP.get(model_type, RESOLUTION_MAP.get("sdxl", {}))
|
| 438 |
-
w, h = res_map.get(ratio_key, (1024, 1024))
|
| 439 |
-
return w, h
|
| 440 |
|
| 441 |
-
for prefix in ["txt2img", "img2img", "inpaint", "outpaint", "hires_fix"]:
|
| 442 |
-
if f'aspect_ratio_{prefix}' in ui_components:
|
| 443 |
-
aspect_ratio_dropdown = ui_components[f'aspect_ratio_{prefix}']
|
| 444 |
-
width_component = ui_components[f'width_{prefix}']
|
| 445 |
-
height_component = ui_components[f'height_{prefix}']
|
| 446 |
-
model_dropdown = ui_components[f'base_model_{prefix}']
|
| 447 |
-
aspect_ratio_dropdown.change(fn=on_aspect_ratio_change, inputs=[aspect_ratio_dropdown, model_dropdown], outputs=[width_component, height_component], show_progress=False)
|
| 448 |
-
|
| 449 |
if 'view_mode_inpaint' in ui_components:
|
| 450 |
def toggle_inpaint_fullscreen_view(view_mode):
|
| 451 |
is_fullscreen = (view_mode == "Fullscreen View")
|
| 452 |
other_elements_visible = not is_fullscreen
|
| 453 |
editor_height = 800 if is_fullscreen else 272
|
| 454 |
-
|
| 455 |
-
|
| 456 |
ui_components['prompts_column_inpaint']: gr.update(visible=other_elements_visible),
|
| 457 |
ui_components['params_and_gallery_row_inpaint']: gr.update(visible=other_elements_visible),
|
| 458 |
ui_components['accordion_wrapper_inpaint']: gr.update(visible=other_elements_visible),
|
| 459 |
ui_components['input_image_dict_inpaint']: gr.update(height=editor_height),
|
| 460 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 461 |
|
| 462 |
-
output_components
|
| 463 |
-
ui_components['
|
| 464 |
-
ui_components['params_and_gallery_row_inpaint'],
|
|
|
|
| 465 |
ui_components['input_image_dict_inpaint']
|
| 466 |
-
]
|
| 467 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 468 |
|
| 469 |
-
def
|
| 470 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 471 |
|
| 472 |
-
|
| 473 |
-
|
| 474 |
-
all_updates[ui_components["preprocessor_model_cn"]] = model_update
|
| 475 |
|
| 476 |
-
|
| 477 |
-
|
| 478 |
-
|
| 479 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 480 |
|
| 481 |
-
|
| 482 |
-
|
| 483 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 484 |
|
| 485 |
return all_updates
|
| 486 |
|
| 487 |
-
all_load_outputs = [
|
| 488 |
-
|
| 489 |
-
|
| 490 |
-
|
| 491 |
-
|
| 492 |
-
|
| 493 |
-
ui_components
|
| 494 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 495 |
|
| 496 |
if all_load_outputs:
|
| 497 |
demo.load(
|
| 498 |
fn=run_on_load,
|
| 499 |
outputs=all_load_outputs
|
| 500 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
from core.generation_logic import *
|
| 9 |
from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
|
| 10 |
|
| 11 |
+
from utils.app_utils import save_uploaded_file_with_hash
|
| 12 |
+
from ui.shared.ui_components import RESOLUTION_MAP, MAX_CONTROLNETS, MAX_IPADAPTERS, MAX_EMBEDDINGS, MAX_CONDITIONINGS, MAX_LORAS
|
|
|
|
| 13 |
|
| 14 |
|
| 15 |
+
@lru_cache(maxsize=1)
|
| 16 |
+
def load_controlnet_config():
|
| 17 |
+
_PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 18 |
+
_CN_MODEL_LIST_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'controlnet_models.yaml')
|
| 19 |
+
try:
|
| 20 |
+
print("--- Loading controlnet_models.yaml ---")
|
| 21 |
+
with open(_CN_MODEL_LIST_PATH, 'r', encoding='utf-8') as f:
|
| 22 |
+
config = yaml.safe_load(f)
|
| 23 |
+
print("--- ✅ controlnet_models.yaml loaded successfully ---")
|
| 24 |
+
return config.get("ControlNet", {})
|
| 25 |
+
except Exception as e:
|
| 26 |
+
print(f"Error loading controlnet_models.yaml: {e}")
|
| 27 |
+
return {}
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def get_cn_defaults(arch_val):
|
| 31 |
+
cn_full_config = load_controlnet_config()
|
| 32 |
+
cn_config = cn_full_config.get(arch_val, [])
|
| 33 |
|
| 34 |
+
if not cn_config:
|
| 35 |
+
return [], None, [], None, "None"
|
| 36 |
+
|
| 37 |
+
all_types = sorted(list(set(t for model in cn_config for t in model.get("Type", []))))
|
| 38 |
+
default_type = all_types[0] if all_types else None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
|
| 40 |
+
series_choices = []
|
| 41 |
+
if default_type:
|
| 42 |
+
series_choices = sorted(list(set(model.get("Series", "Default") for model in cn_config if default_type in model.get("Type", []))))
|
| 43 |
+
default_series = series_choices[0] if series_choices else None
|
| 44 |
+
|
| 45 |
+
filepath = "None"
|
| 46 |
+
if default_series and default_type:
|
| 47 |
+
for model in cn_config:
|
| 48 |
+
if model.get("Series") == default_series and default_type in model.get("Type", []):
|
| 49 |
+
filepath = model.get("Filepath")
|
| 50 |
+
break
|
| 51 |
+
|
| 52 |
+
return all_types, default_type, series_choices, default_series, filepath
|
| 53 |
+
|
| 54 |
+
@lru_cache(maxsize=1)
|
| 55 |
+
def load_diffsynth_controlnet_config():
|
| 56 |
+
_PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 57 |
+
_CN_MODEL_LIST_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'diffsynth_controlnet_models.yaml')
|
| 58 |
+
try:
|
| 59 |
+
print("--- Loading diffsynth_controlnet_models.yaml ---")
|
| 60 |
+
with open(_CN_MODEL_LIST_PATH, 'r', encoding='utf-8') as f:
|
| 61 |
+
config = yaml.safe_load(f)
|
| 62 |
+
print("--- ✅ diffsynth_controlnet_models.yaml loaded successfully ---")
|
| 63 |
+
return config.get("DiffSynth_ControlNet", {})
|
| 64 |
+
except Exception as e:
|
| 65 |
+
print(f"Error loading diffsynth_controlnet_models.yaml: {e}")
|
| 66 |
+
return {}
|
| 67 |
|
| 68 |
+
def get_diffsynth_cn_defaults(arch_val):
|
| 69 |
+
cn_full_config = load_diffsynth_controlnet_config()
|
| 70 |
+
cn_config = cn_full_config.get(arch_val, [])
|
| 71 |
|
| 72 |
+
if not cn_config:
|
| 73 |
+
return [], None, [], None, "None"
|
| 74 |
+
|
| 75 |
+
all_types = sorted(list(set(t for model in cn_config for t in model.get("Type", []))))
|
| 76 |
+
default_type = all_types[0] if all_types else None
|
| 77 |
+
|
| 78 |
+
series_choices = []
|
| 79 |
+
if default_type:
|
| 80 |
+
series_choices = sorted(list(set(model.get("Series", "Default") for model in cn_config if default_type in model.get("Type", []))))
|
| 81 |
+
default_series = series_choices[0] if series_choices else None
|
| 82 |
+
|
| 83 |
+
filepath = "None"
|
| 84 |
+
if default_series and default_type:
|
| 85 |
+
for model in cn_config:
|
| 86 |
+
if model.get("Series") == default_series and default_type in model.get("Type", []):
|
| 87 |
+
filepath = model.get("Filepath")
|
| 88 |
+
break
|
| 89 |
+
|
| 90 |
+
return all_types, default_type, series_choices, default_series, filepath
|
| 91 |
|
| 92 |
+
|
| 93 |
+
@lru_cache(maxsize=1)
|
| 94 |
+
def load_ipadapter_config():
|
| 95 |
+
_PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 96 |
+
_IPA_MODEL_LIST_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'ipadapter.yaml')
|
| 97 |
+
try:
|
| 98 |
+
print("--- Loading ipadapter.yaml ---")
|
| 99 |
+
with open(_IPA_MODEL_LIST_PATH, 'r', encoding='utf-8') as f:
|
| 100 |
+
config = yaml.safe_load(f)
|
| 101 |
+
print("--- ✅ ipadapter.yaml loaded successfully ---")
|
| 102 |
+
return config
|
| 103 |
+
except Exception as e:
|
| 104 |
+
print(f"Error loading ipadapter.yaml: {e}")
|
| 105 |
+
return {}
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def apply_data_to_ui(data, prefix, ui_components):
|
| 109 |
+
final_sampler = data.get('sampler') if data.get('sampler') in SAMPLER_CHOICES else SAMPLER_CHOICES[0]
|
| 110 |
+
default_scheduler = 'normal' if 'normal' in SCHEDULER_CHOICES else SCHEDULER_CHOICES[0]
|
| 111 |
+
final_scheduler = data.get('scheduler') if data.get('scheduler') in SCHEDULER_CHOICES else default_scheduler
|
| 112 |
+
|
| 113 |
+
updates = {}
|
| 114 |
+
base_model_name = data.get('base_model')
|
| 115 |
|
| 116 |
+
model_map = MODEL_MAP_CHECKPOINT
|
| 117 |
+
|
| 118 |
+
if f'base_model_{prefix}' in ui_components:
|
| 119 |
+
model_dropdown_component = ui_components[f'base_model_{prefix}']
|
| 120 |
+
if base_model_name and base_model_name in model_map:
|
| 121 |
+
updates[model_dropdown_component] = base_model_name
|
| 122 |
+
if f'model_arch_{prefix}' in ui_components:
|
| 123 |
+
m_type = MODEL_TYPE_MAP.get(base_model_name, "SDXL")
|
| 124 |
+
updates[ui_components[f'model_arch_{prefix}']] = m_type
|
| 125 |
+
if f'model_cat_{prefix}' in ui_components:
|
| 126 |
+
m_info = model_map.get(base_model_name)
|
| 127 |
+
m_cat = m_info[4] if m_info and len(m_info) > 4 else None
|
| 128 |
+
updates[ui_components[f'model_cat_{prefix}']] = m_cat if m_cat else "ALL"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
else:
|
| 130 |
+
updates[model_dropdown_component] = gr.update()
|
| 131 |
+
|
| 132 |
+
common_params = {
|
| 133 |
+
f'prompt_{prefix}': data.get('prompt', ''),
|
| 134 |
+
f'neg_prompt_{prefix}': data.get('negative_prompt', ''),
|
| 135 |
+
f'seed_{prefix}': data.get('seed', -1),
|
| 136 |
+
f'cfg_{prefix}': data.get('cfg_scale', 7.5),
|
| 137 |
+
f'steps_{prefix}': data.get('steps', 28),
|
| 138 |
+
f'sampler_{prefix}': final_sampler,
|
| 139 |
+
f'scheduler_{prefix}': final_scheduler,
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
for comp_name, value in common_params.items():
|
| 143 |
+
if comp_name in ui_components:
|
| 144 |
+
updates[ui_components[comp_name]] = value
|
| 145 |
+
|
| 146 |
+
if prefix == 'txt2img':
|
| 147 |
+
if f'width_{prefix}' in ui_components:
|
| 148 |
+
updates[ui_components[f'width_{prefix}']] = data.get('width', 1024)
|
| 149 |
+
if f'height_{prefix}' in ui_components:
|
| 150 |
+
updates[ui_components[f'height_{prefix}']] = data.get('height', 1024)
|
| 151 |
+
|
| 152 |
+
tab_indices = {"txt2img": 0, "img2img": 1, "inpaint": 2, "outpaint": 3, "hires_fix": 4}
|
| 153 |
+
tab_index = tab_indices.get(prefix, 0)
|
| 154 |
+
|
| 155 |
+
updates[ui_components['tabs']] = gr.Tabs(selected=tab_index)
|
| 156 |
+
|
| 157 |
+
return updates
|
| 158 |
+
|
| 159 |
+
|
| 160 |
+
def send_info_to_tab(image, prefix, ui_components):
|
| 161 |
+
if not image or not image.info.get('parameters', ''):
|
| 162 |
+
all_comps = [comp for comp_or_list in ui_components.values() for comp in (comp_or_list if isinstance(comp_or_list, list) else [comp_or_list])]
|
| 163 |
+
return {comp: gr.update() for comp in all_comps}
|
| 164 |
+
|
| 165 |
+
data = parse_parameters(image.info['parameters'])
|
| 166 |
+
|
| 167 |
+
image_input_map = {
|
| 168 |
+
"img2img": 'input_image_img2img',
|
| 169 |
+
"inpaint": 'input_image_dict_inpaint',
|
| 170 |
+
"outpaint": 'input_image_outpaint',
|
| 171 |
+
"hires_fix": 'input_image_hires_fix'
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
updates = apply_data_to_ui(data, prefix, ui_components)
|
| 175 |
+
|
| 176 |
+
if prefix in image_input_map and image_input_map[prefix] in ui_components:
|
| 177 |
+
component_key = image_input_map[prefix]
|
| 178 |
+
updates[ui_components[component_key]] = gr.update(value=image)
|
| 179 |
+
|
| 180 |
+
return updates
|
| 181 |
+
|
| 182 |
|
| 183 |
+
def send_info_by_hash(image, ui_components):
|
| 184 |
+
if not image or not image.info.get('parameters', ''):
|
| 185 |
+
all_comps = [comp for comp_or_list in ui_components.values() for comp in (comp_or_list if isinstance(comp_or_list, list) else [comp_or_list])]
|
| 186 |
+
return {comp: gr.update() for comp in all_comps}
|
| 187 |
+
|
| 188 |
+
data = parse_parameters(image.info['parameters'])
|
| 189 |
+
|
| 190 |
+
return apply_data_to_ui(data, "txt2img", ui_components)
|
| 191 |
+
|
| 192 |
+
|
| 193 |
+
def attach_event_handlers(ui_components, demo):
|
| 194 |
+
|
| 195 |
def create_lora_event_handlers(prefix):
|
| 196 |
+
lora_rows = ui_components.get(f'lora_rows_{prefix}')
|
| 197 |
+
if not lora_rows: return
|
| 198 |
lora_ids = ui_components[f'lora_ids_{prefix}']
|
| 199 |
lora_scales = ui_components[f'lora_scales_{prefix}']
|
| 200 |
lora_uploads = ui_components[f'lora_uploads_{prefix}']
|
|
|
|
| 233 |
add_button.click(add_lora_row, [count_state], add_outputs, show_progress=False)
|
| 234 |
del_button.click(del_lora_row, [count_state], del_outputs, show_progress=False)
|
| 235 |
|
| 236 |
+
def create_controlnet_event_handlers(prefix):
|
| 237 |
+
cn_rows = ui_components.get(f'controlnet_rows_{prefix}')
|
| 238 |
+
if not cn_rows: return
|
| 239 |
+
cn_types = ui_components[f'controlnet_types_{prefix}']
|
| 240 |
+
cn_series = ui_components[f'controlnet_series_{prefix}']
|
| 241 |
+
cn_filepaths = ui_components[f'controlnet_filepaths_{prefix}']
|
| 242 |
+
cn_images = ui_components[f'controlnet_images_{prefix}']
|
| 243 |
+
cn_strengths = ui_components[f'controlnet_strengths_{prefix}']
|
| 244 |
+
|
| 245 |
+
count_state = ui_components[f'controlnet_count_state_{prefix}']
|
| 246 |
+
add_button = ui_components[f'add_controlnet_button_{prefix}']
|
| 247 |
+
del_button = ui_components[f'delete_controlnet_button_{prefix}']
|
| 248 |
+
accordion = ui_components[f'controlnet_accordion_{prefix}']
|
| 249 |
+
|
| 250 |
+
arch_comp = ui_components.get(f'model_arch_{prefix}')
|
| 251 |
+
actual_arch_comp = arch_comp if arch_comp else gr.State("SDXL")
|
| 252 |
+
|
| 253 |
+
def add_cn_row(c):
|
| 254 |
+
c += 1
|
| 255 |
+
updates = {
|
| 256 |
+
count_state: c,
|
| 257 |
+
cn_rows[c-1]: gr.update(visible=True),
|
| 258 |
+
add_button: gr.update(visible=c < MAX_CONTROLNETS),
|
| 259 |
+
del_button: gr.update(visible=True)
|
| 260 |
+
}
|
| 261 |
+
return updates
|
| 262 |
+
|
| 263 |
+
def del_cn_row(c):
|
| 264 |
+
c -= 1
|
| 265 |
+
updates = {
|
| 266 |
+
count_state: c,
|
| 267 |
+
cn_rows[c]: gr.update(visible=False),
|
| 268 |
+
cn_images[c]: None,
|
| 269 |
+
cn_strengths[c]: 1.0,
|
| 270 |
+
add_button: gr.update(visible=True),
|
| 271 |
+
del_button: gr.update(visible=c > 0)
|
| 272 |
+
}
|
| 273 |
+
return updates
|
| 274 |
+
|
| 275 |
+
add_outputs = [count_state, add_button, del_button] + cn_rows
|
| 276 |
+
del_outputs = [count_state, add_button, del_button] + cn_rows + cn_images + cn_strengths
|
| 277 |
+
add_button.click(fn=add_cn_row, inputs=[count_state], outputs=add_outputs, show_progress=False)
|
| 278 |
+
del_button.click(fn=del_cn_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
|
| 279 |
+
|
| 280 |
+
def on_cn_type_change(selected_type, arch_val):
|
| 281 |
+
cn_full_config = load_controlnet_config()
|
| 282 |
+
|
| 283 |
+
architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 284 |
+
controlnet_key = architectures_dict.get(arch_val, {}).get("controlnet_key", arch_val)
|
| 285 |
+
|
| 286 |
+
cn_config = cn_full_config.get(controlnet_key, [])
|
| 287 |
+
series_choices = []
|
| 288 |
+
if selected_type:
|
| 289 |
+
series_choices = sorted(list(set(
|
| 290 |
+
model.get("Series", "Default") for model in cn_config
|
| 291 |
+
if selected_type in model.get("Type", [])
|
| 292 |
+
)))
|
| 293 |
+
default_series = series_choices[0] if series_choices else None
|
| 294 |
+
filepath = "None"
|
| 295 |
+
if default_series:
|
| 296 |
+
for model in cn_config:
|
| 297 |
+
if model.get("Series") == default_series and selected_type in model.get("Type", []):
|
| 298 |
+
filepath = model.get("Filepath")
|
| 299 |
+
break
|
| 300 |
+
return gr.update(choices=series_choices, value=default_series), filepath
|
| 301 |
+
|
| 302 |
+
def on_cn_series_change(selected_series, selected_type, arch_val):
|
| 303 |
+
cn_full_config = load_controlnet_config()
|
| 304 |
+
|
| 305 |
+
architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 306 |
+
controlnet_key = architectures_dict.get(arch_val, {}).get("controlnet_key", arch_val)
|
| 307 |
+
|
| 308 |
+
cn_config = cn_full_config.get(controlnet_key, [])
|
| 309 |
+
filepath = "None"
|
| 310 |
+
if selected_series and selected_type:
|
| 311 |
+
for model in cn_config:
|
| 312 |
+
if model.get("Series") == selected_series and selected_type in model.get("Type", []):
|
| 313 |
+
filepath = model.get("Filepath")
|
| 314 |
+
break
|
| 315 |
+
return filepath
|
| 316 |
+
|
| 317 |
+
for i in range(MAX_CONTROLNETS):
|
| 318 |
+
cn_types[i].change(
|
| 319 |
+
fn=on_cn_type_change,
|
| 320 |
+
inputs=[cn_types[i], actual_arch_comp],
|
| 321 |
+
outputs=[cn_series[i], cn_filepaths[i]],
|
| 322 |
+
show_progress=False
|
| 323 |
+
)
|
| 324 |
+
cn_series[i].change(
|
| 325 |
+
fn=on_cn_series_change,
|
| 326 |
+
inputs=[cn_series[i], cn_types[i], actual_arch_comp],
|
| 327 |
+
outputs=[cn_filepaths[i]],
|
| 328 |
+
show_progress=False
|
| 329 |
+
)
|
| 330 |
+
|
| 331 |
+
def on_accordion_expand(*images):
|
| 332 |
+
return [gr.update() for _ in images]
|
| 333 |
+
|
| 334 |
+
accordion.expand(
|
| 335 |
+
fn=on_accordion_expand,
|
| 336 |
+
inputs=cn_images,
|
| 337 |
+
outputs=cn_images,
|
| 338 |
+
show_progress=False
|
| 339 |
+
)
|
| 340 |
+
|
| 341 |
+
def create_diffsynth_controlnet_event_handlers(prefix):
|
| 342 |
+
cn_rows = ui_components.get(f'diffsynth_controlnet_rows_{prefix}')
|
| 343 |
+
if not cn_rows: return
|
| 344 |
+
cn_types = ui_components[f'diffsynth_controlnet_types_{prefix}']
|
| 345 |
+
cn_series = ui_components[f'diffsynth_controlnet_series_{prefix}']
|
| 346 |
+
cn_filepaths = ui_components[f'diffsynth_controlnet_filepaths_{prefix}']
|
| 347 |
+
cn_images = ui_components[f'diffsynth_controlnet_images_{prefix}']
|
| 348 |
+
cn_strengths = ui_components[f'diffsynth_controlnet_strengths_{prefix}']
|
| 349 |
+
|
| 350 |
+
count_state = ui_components[f'diffsynth_controlnet_count_state_{prefix}']
|
| 351 |
+
add_button = ui_components[f'add_diffsynth_controlnet_button_{prefix}']
|
| 352 |
+
del_button = ui_components[f'delete_diffsynth_controlnet_button_{prefix}']
|
| 353 |
+
accordion = ui_components[f'diffsynth_controlnet_accordion_{prefix}']
|
| 354 |
+
|
| 355 |
+
arch_comp = ui_components.get(f'model_arch_{prefix}')
|
| 356 |
+
actual_arch_comp = arch_comp if arch_comp else gr.State("Z-Image")
|
| 357 |
+
|
| 358 |
+
def add_cn_row(c):
|
| 359 |
+
c += 1
|
| 360 |
+
updates = {
|
| 361 |
+
count_state: c,
|
| 362 |
+
cn_rows[c-1]: gr.update(visible=True),
|
| 363 |
+
add_button: gr.update(visible=c < MAX_CONTROLNETS),
|
| 364 |
+
del_button: gr.update(visible=True)
|
| 365 |
+
}
|
| 366 |
+
return updates
|
| 367 |
+
|
| 368 |
+
def del_cn_row(c):
|
| 369 |
+
c -= 1
|
| 370 |
+
updates = {
|
| 371 |
+
count_state: c,
|
| 372 |
+
cn_rows[c]: gr.update(visible=False),
|
| 373 |
+
cn_images[c]: None,
|
| 374 |
+
cn_strengths[c]: 1.0,
|
| 375 |
+
add_button: gr.update(visible=True),
|
| 376 |
+
del_button: gr.update(visible=c > 0)
|
| 377 |
+
}
|
| 378 |
+
return updates
|
| 379 |
+
|
| 380 |
+
add_outputs = [count_state, add_button, del_button] + cn_rows
|
| 381 |
+
del_outputs = [count_state, add_button, del_button] + cn_rows + cn_images + cn_strengths
|
| 382 |
+
add_button.click(fn=add_cn_row, inputs=[count_state], outputs=add_outputs, show_progress=False)
|
| 383 |
+
del_button.click(fn=del_cn_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
|
| 384 |
+
|
| 385 |
+
def on_cn_type_change(selected_type, arch_val):
|
| 386 |
+
cn_full_config = load_diffsynth_controlnet_config()
|
| 387 |
+
|
| 388 |
+
architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 389 |
+
controlnet_key = architectures_dict.get(arch_val, {}).get("controlnet_key", arch_val)
|
| 390 |
+
|
| 391 |
+
cn_config = cn_full_config.get(controlnet_key, [])
|
| 392 |
+
series_choices = []
|
| 393 |
+
if selected_type:
|
| 394 |
+
series_choices = sorted(list(set(
|
| 395 |
+
model.get("Series", "Default") for model in cn_config
|
| 396 |
+
if selected_type in model.get("Type", [])
|
| 397 |
+
)))
|
| 398 |
+
default_series = series_choices[0] if series_choices else None
|
| 399 |
+
filepath = "None"
|
| 400 |
+
if default_series:
|
| 401 |
+
for model in cn_config:
|
| 402 |
+
if model.get("Series") == default_series and selected_type in model.get("Type", []):
|
| 403 |
+
filepath = model.get("Filepath")
|
| 404 |
+
break
|
| 405 |
+
return gr.update(choices=series_choices, value=default_series), filepath
|
| 406 |
+
|
| 407 |
+
def on_cn_series_change(selected_series, selected_type, arch_val):
|
| 408 |
+
cn_full_config = load_diffsynth_controlnet_config()
|
| 409 |
+
|
| 410 |
+
architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 411 |
+
controlnet_key = architectures_dict.get(arch_val, {}).get("controlnet_key", arch_val)
|
| 412 |
+
|
| 413 |
+
cn_config = cn_full_config.get(controlnet_key, [])
|
| 414 |
+
filepath = "None"
|
| 415 |
+
if selected_series and selected_type:
|
| 416 |
+
for model in cn_config:
|
| 417 |
+
if model.get("Series") == selected_series and selected_type in model.get("Type", []):
|
| 418 |
+
filepath = model.get("Filepath")
|
| 419 |
+
break
|
| 420 |
+
return filepath
|
| 421 |
+
|
| 422 |
+
for i in range(MAX_CONTROLNETS):
|
| 423 |
+
cn_types[i].change(
|
| 424 |
+
fn=on_cn_type_change,
|
| 425 |
+
inputs=[cn_types[i], actual_arch_comp],
|
| 426 |
+
outputs=[cn_series[i], cn_filepaths[i]],
|
| 427 |
+
show_progress=False
|
| 428 |
+
)
|
| 429 |
+
cn_series[i].change(
|
| 430 |
+
fn=on_cn_series_change,
|
| 431 |
+
inputs=[cn_series[i], cn_types[i], actual_arch_comp],
|
| 432 |
+
outputs=[cn_filepaths[i]],
|
| 433 |
+
show_progress=False
|
| 434 |
+
)
|
| 435 |
+
|
| 436 |
+
def on_accordion_expand(*images):
|
| 437 |
+
return [gr.update() for _ in images]
|
| 438 |
+
|
| 439 |
+
accordion.expand(
|
| 440 |
+
fn=on_accordion_expand,
|
| 441 |
+
inputs=cn_images,
|
| 442 |
+
outputs=cn_images,
|
| 443 |
+
show_progress=False
|
| 444 |
+
)
|
| 445 |
+
|
| 446 |
+
def create_flux1_ipadapter_event_handlers(prefix):
|
| 447 |
+
fipa_rows = ui_components.get(f'flux1_ipadapter_rows_{prefix}')
|
| 448 |
+
if not fipa_rows: return
|
| 449 |
+
count_state = ui_components[f'flux1_ipadapter_count_state_{prefix}']
|
| 450 |
+
add_button = ui_components[f'add_flux1_ipadapter_button_{prefix}']
|
| 451 |
+
del_button = ui_components[f'delete_flux1_ipadapter_button_{prefix}']
|
| 452 |
+
|
| 453 |
+
def add_fipa_row(c):
|
| 454 |
+
c += 1
|
| 455 |
+
return {
|
| 456 |
+
count_state: c,
|
| 457 |
+
fipa_rows[c - 1]: gr.update(visible=True),
|
| 458 |
+
add_button: gr.update(visible=c < MAX_IPADAPTERS),
|
| 459 |
+
del_button: gr.update(visible=True),
|
| 460 |
+
}
|
| 461 |
+
|
| 462 |
+
def del_fipa_row(c):
|
| 463 |
+
c -= 1
|
| 464 |
+
return {
|
| 465 |
+
count_state: c,
|
| 466 |
+
fipa_rows[c]: gr.update(visible=False),
|
| 467 |
+
add_button: gr.update(visible=True),
|
| 468 |
+
del_button: gr.update(visible=c > 0),
|
| 469 |
+
}
|
| 470 |
+
|
| 471 |
+
add_outputs = [count_state, add_button, del_button] + fipa_rows
|
| 472 |
+
del_outputs = [count_state, add_button, del_button] + fipa_rows
|
| 473 |
+
add_button.click(fn=add_fipa_row, inputs=[count_state], outputs=add_outputs, show_progress=False)
|
| 474 |
+
del_button.click(fn=del_fipa_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
|
| 475 |
+
|
| 476 |
+
def create_style_event_handlers(prefix):
|
| 477 |
+
style_rows = ui_components.get(f'style_rows_{prefix}')
|
| 478 |
+
if not style_rows: return
|
| 479 |
+
count_state = ui_components[f'style_count_state_{prefix}']
|
| 480 |
+
add_button = ui_components[f'add_style_button_{prefix}']
|
| 481 |
+
del_button = ui_components[f'delete_style_button_{prefix}']
|
| 482 |
+
|
| 483 |
+
def add_style_row(c):
|
| 484 |
+
c += 1
|
| 485 |
+
return {
|
| 486 |
+
count_state: c,
|
| 487 |
+
style_rows[c - 1]: gr.update(visible=True),
|
| 488 |
+
add_button: gr.update(visible=c < 5),
|
| 489 |
+
del_button: gr.update(visible=True),
|
| 490 |
+
}
|
| 491 |
+
|
| 492 |
+
def del_style_row(c):
|
| 493 |
+
c -= 1
|
| 494 |
+
return {
|
| 495 |
+
count_state: c,
|
| 496 |
+
style_rows[c]: gr.update(visible=False),
|
| 497 |
+
add_button: gr.update(visible=True),
|
| 498 |
+
del_button: gr.update(visible=c > 0),
|
| 499 |
+
}
|
| 500 |
+
|
| 501 |
+
add_outputs = [count_state, add_button, del_button] + style_rows
|
| 502 |
+
del_outputs = [count_state, add_button, del_button] + style_rows
|
| 503 |
+
add_button.click(fn=add_style_row, inputs=[count_state], outputs=add_outputs, show_progress=False)
|
| 504 |
+
del_button.click(fn=del_style_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
|
| 505 |
+
|
| 506 |
+
def create_ipadapter_event_handlers(prefix):
|
| 507 |
+
ipa_rows = ui_components.get(f'ipadapter_rows_{prefix}')
|
| 508 |
+
if not ipa_rows: return
|
| 509 |
+
ipa_lora_strengths = ui_components[f'ipadapter_lora_strengths_{prefix}']
|
| 510 |
+
ipa_final_preset = ui_components[f'ipadapter_final_preset_{prefix}']
|
| 511 |
+
ipa_final_lora_strength = ui_components[f'ipadapter_final_lora_strength_{prefix}']
|
| 512 |
+
count_state = ui_components[f'ipadapter_count_state_{prefix}']
|
| 513 |
+
add_button = ui_components[f'add_ipadapter_button_{prefix}']
|
| 514 |
+
del_button = ui_components[f'delete_ipadapter_button_{prefix}']
|
| 515 |
+
accordion = ui_components[f'ipadapter_accordion_{prefix}']
|
| 516 |
+
|
| 517 |
+
def add_ipa_row(c):
|
| 518 |
+
c += 1
|
| 519 |
+
return {
|
| 520 |
+
count_state: c,
|
| 521 |
+
ipa_rows[c - 1]: gr.update(visible=True),
|
| 522 |
+
add_button: gr.update(visible=c < MAX_IPADAPTERS),
|
| 523 |
+
del_button: gr.update(visible=True),
|
| 524 |
+
}
|
| 525 |
+
|
| 526 |
+
def del_ipa_row(c):
|
| 527 |
+
c -= 1
|
| 528 |
+
return {
|
| 529 |
+
count_state: c,
|
| 530 |
+
ipa_rows[c]: gr.update(visible=False),
|
| 531 |
+
add_button: gr.update(visible=True),
|
| 532 |
+
del_button: gr.update(visible=c > 0),
|
| 533 |
+
}
|
| 534 |
+
|
| 535 |
+
add_outputs = [count_state, add_button, del_button] + ipa_rows
|
| 536 |
+
del_outputs = [count_state, add_button, del_button] + ipa_rows
|
| 537 |
+
add_button.click(fn=add_ipa_row, inputs=[count_state], outputs=add_outputs, show_progress=False)
|
| 538 |
+
del_button.click(fn=del_ipa_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
|
| 539 |
+
|
| 540 |
+
def on_preset_change(preset_value):
|
| 541 |
+
config = load_ipadapter_config()
|
| 542 |
+
faceid_presets = []
|
| 543 |
+
if config:
|
| 544 |
+
faceid_presets.extend(config.get("IPAdapter_FaceID_presets", {}).get("SDXL", []))
|
| 545 |
+
faceid_presets.extend(config.get("IPAdapter_FaceID_presets", {}).get("SD1.5", []))
|
| 546 |
+
|
| 547 |
+
is_visible = preset_value in faceid_presets
|
| 548 |
+
updates = [gr.update(visible=is_visible)] * (MAX_IPADAPTERS + 1)
|
| 549 |
+
return updates
|
| 550 |
+
|
| 551 |
+
all_lora_strength_sliders = [ipa_final_lora_strength] + ipa_lora_strengths
|
| 552 |
+
ipa_final_preset.change(fn=on_preset_change, inputs=[ipa_final_preset], outputs=all_lora_strength_sliders, show_progress=False)
|
| 553 |
+
|
| 554 |
+
accordion.expand(fn=lambda *imgs: [gr.update() for _ in imgs], inputs=ui_components[f'ipadapter_images_{prefix}'], outputs=ui_components[f'ipadapter_images_{prefix}'], show_progress=False)
|
| 555 |
+
|
| 556 |
+
def create_reference_latent_event_handlers(prefix):
|
| 557 |
+
ref_rows = ui_components.get(f'reference_latent_rows_{prefix}')
|
| 558 |
+
if not ref_rows: return
|
| 559 |
+
count_state = ui_components[f'reference_latent_count_state_{prefix}']
|
| 560 |
+
add_button = ui_components[f'add_reference_latent_button_{prefix}']
|
| 561 |
+
del_button = ui_components[f'delete_reference_latent_button_{prefix}']
|
| 562 |
+
images = ui_components[f'reference_latent_images_{prefix}']
|
| 563 |
+
|
| 564 |
+
def add_ref_row(c):
|
| 565 |
+
c += 1
|
| 566 |
+
return {
|
| 567 |
+
count_state: c,
|
| 568 |
+
ref_rows[c - 1]: gr.update(visible=True),
|
| 569 |
+
add_button: gr.update(visible=c < 10),
|
| 570 |
+
del_button: gr.update(visible=True),
|
| 571 |
+
}
|
| 572 |
+
|
| 573 |
+
def del_ref_row(c):
|
| 574 |
+
c -= 1
|
| 575 |
+
return {
|
| 576 |
+
count_state: c,
|
| 577 |
+
ref_rows[c]: gr.update(visible=False),
|
| 578 |
+
images[c]: None,
|
| 579 |
+
add_button: gr.update(visible=True),
|
| 580 |
+
del_button: gr.update(visible=c > 0),
|
| 581 |
+
}
|
| 582 |
+
|
| 583 |
+
add_outputs = [count_state, add_button, del_button] + ref_rows
|
| 584 |
+
del_outputs = [count_state, add_button, del_button] + ref_rows + images
|
| 585 |
+
add_button.click(fn=add_ref_row, inputs=[count_state], outputs=add_outputs, show_progress=False)
|
| 586 |
+
del_button.click(fn=del_ref_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
|
| 587 |
+
|
| 588 |
+
|
| 589 |
def create_embedding_event_handlers(prefix):
|
| 590 |
+
rows = ui_components.get(f'embedding_rows_{prefix}')
|
| 591 |
+
if not rows: return
|
| 592 |
ids = ui_components[f'embeddings_ids_{prefix}']
|
| 593 |
files = ui_components[f'embeddings_files_{prefix}']
|
| 594 |
count_state = ui_components[f'embedding_count_state_{prefix}']
|
|
|
|
| 621 |
del_button.click(fn=del_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
|
| 622 |
|
| 623 |
def create_conditioning_event_handlers(prefix):
|
| 624 |
+
rows = ui_components.get(f'conditioning_rows_{prefix}')
|
| 625 |
+
if not rows: return
|
| 626 |
prompts = ui_components[f'conditioning_prompts_{prefix}']
|
| 627 |
count_state = ui_components[f'conditioning_count_state_{prefix}']
|
| 628 |
add_button = ui_components[f'add_conditioning_button_{prefix}']
|
|
|
|
| 651 |
del_outputs = [count_state, add_button, del_button] + rows + prompts
|
| 652 |
add_button.click(fn=add_row, inputs=[count_state], outputs=add_outputs, show_progress=False)
|
| 653 |
del_button.click(fn=del_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 654 |
|
| 655 |
def on_vae_upload(file_obj):
|
| 656 |
if not file_obj:
|
|
|
|
| 677 |
def create_run_event(prefix: str, task_type: str):
|
| 678 |
run_inputs_map = {
|
| 679 |
'model_display_name': ui_components[f'base_model_{prefix}'],
|
| 680 |
+
'positive_prompt': ui_components.get(f'prompt_{prefix}') or ui_components.get(f'{prefix}_positive_prompt'),
|
| 681 |
+
'negative_prompt': ui_components.get(f'neg_prompt_{prefix}') or ui_components.get(f'{prefix}_negative_prompt'),
|
| 682 |
+
'seed': ui_components.get(f'seed_{prefix}') or ui_components.get(f'{prefix}_seed'),
|
| 683 |
+
'batch_size': ui_components.get(f'batch_size_{prefix}') or ui_components.get(f'{prefix}_batch_size'),
|
| 684 |
+
'guidance_scale': ui_components.get(f'cfg_{prefix}') or ui_components.get(f'{prefix}_cfg'),
|
| 685 |
+
'num_inference_steps': ui_components.get(f'steps_{prefix}') or ui_components.get(f'{prefix}_steps'),
|
| 686 |
+
'sampler': ui_components.get(f'sampler_{prefix}') or ui_components.get(f'{prefix}_sampler_name'),
|
| 687 |
+
'scheduler': ui_components.get(f'scheduler_{prefix}') or ui_components.get(f'{prefix}_scheduler'),
|
| 688 |
+
'zero_gpu_duration': ui_components.get(f'zero_gpu_{prefix}'),
|
| 689 |
+
|
| 690 |
+
'clip_skip': ui_components.get(f'clip_skip_{prefix}'),
|
| 691 |
+
'guidance': ui_components.get(f'guidance_{prefix}'),
|
| 692 |
'task_type': gr.State(task_type)
|
| 693 |
}
|
| 694 |
|
| 695 |
if task_type not in ['img2img', 'inpaint']:
|
| 696 |
+
run_inputs_map.update({
|
| 697 |
+
'width': ui_components.get(f'width_{prefix}') or ui_components.get(f'{prefix}_width'),
|
| 698 |
+
'height': ui_components.get(f'height_{prefix}') or ui_components.get(f'{prefix}_height')
|
| 699 |
+
})
|
| 700 |
|
| 701 |
task_specific_map = {
|
| 702 |
'img2img': {'img2img_image': f'input_image_{prefix}', 'img2img_denoise': f'denoise_{prefix}'},
|
| 703 |
+
'inpaint': {'inpaint_image_dict': f'input_image_dict_{prefix}', 'grow_mask_by': f'grow_mask_by_{prefix}'},
|
| 704 |
+
'outpaint': {'outpaint_image': f'input_image_{prefix}', 'left': f'left_{prefix}', 'top': f'top_{prefix}', 'right': f'right_{prefix}', 'bottom': f'bottom_{prefix}', 'feathering': f'feathering_{prefix}'},
|
| 705 |
'hires_fix': {'hires_image': f'input_image_{prefix}', 'hires_upscaler': f'hires_upscaler_{prefix}', 'hires_scale_by': f'hires_scale_by_{prefix}', 'hires_denoise': f'denoise_{prefix}'}
|
| 706 |
}
|
| 707 |
if task_type in task_specific_map:
|
| 708 |
for key, comp_name in task_specific_map[task_type].items():
|
| 709 |
+
if comp_name in ui_components:
|
| 710 |
+
run_inputs_map[key] = ui_components[comp_name]
|
| 711 |
|
| 712 |
lora_data_components = ui_components.get(f'all_lora_components_flat_{prefix}', [])
|
| 713 |
+
controlnet_data_components = ui_components.get(f'all_controlnet_components_flat_{prefix}', [])
|
| 714 |
+
diffsynth_controlnet_data_components = ui_components.get(f'all_diffsynth_controlnet_components_flat_{prefix}', [])
|
| 715 |
+
ipadapter_data_components = ui_components.get(f'all_ipadapter_components_flat_{prefix}', [])
|
| 716 |
+
sd3_ipadapter_data_components = ui_components.get(f'all_sd3_ipadapter_components_flat_{prefix}', [])
|
| 717 |
+
flux1_ipadapter_data_components = ui_components.get(f'all_flux1_ipadapter_components_flat_{prefix}', [])
|
| 718 |
+
style_data_components = ui_components.get(f'all_style_components_flat_{prefix}', [])
|
| 719 |
embedding_data_components = ui_components.get(f'all_embedding_components_flat_{prefix}', [])
|
| 720 |
conditioning_data_components = ui_components.get(f'all_conditioning_components_flat_{prefix}', [])
|
| 721 |
+
reference_latent_data_components = ui_components.get(f'all_reference_latent_components_flat_{prefix}', [])
|
| 722 |
|
| 723 |
run_inputs_map['vae_source'] = ui_components.get(f'vae_source_{prefix}')
|
| 724 |
run_inputs_map['vae_id'] = ui_components.get(f'vae_id_{prefix}')
|
|
|
|
| 726 |
|
| 727 |
input_keys = list(run_inputs_map.keys())
|
| 728 |
input_list_flat = [v for v in run_inputs_map.values() if v is not None]
|
| 729 |
+
all_chains = [
|
| 730 |
+
lora_data_components, controlnet_data_components, diffsynth_controlnet_data_components, ipadapter_data_components,
|
| 731 |
+
sd3_ipadapter_data_components, flux1_ipadapter_data_components, style_data_components,
|
| 732 |
+
embedding_data_components, conditioning_data_components, reference_latent_data_components
|
| 733 |
+
]
|
| 734 |
+
for chain in all_chains:
|
| 735 |
+
if chain:
|
| 736 |
+
input_list_flat.extend(chain)
|
| 737 |
|
| 738 |
def create_ui_inputs_dict(*args):
|
| 739 |
valid_keys = [k for k in input_keys if run_inputs_map[k] is not None]
|
| 740 |
ui_dict = dict(zip(valid_keys, args[:len(valid_keys)]))
|
| 741 |
arg_idx = len(valid_keys)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 742 |
|
| 743 |
+
def assign_chain_data(chain_key, components_list):
|
| 744 |
+
nonlocal arg_idx
|
| 745 |
+
if components_list:
|
| 746 |
+
ui_dict[chain_key] = list(args[arg_idx : arg_idx + len(components_list)])
|
| 747 |
+
arg_idx += len(components_list)
|
| 748 |
+
|
| 749 |
+
assign_chain_data('lora_data', lora_data_components)
|
| 750 |
+
assign_chain_data('controlnet_data', controlnet_data_components)
|
| 751 |
+
assign_chain_data('diffsynth_controlnet_data', diffsynth_controlnet_data_components)
|
| 752 |
+
assign_chain_data('ipadapter_data', ipadapter_data_components)
|
| 753 |
+
assign_chain_data('sd3_ipadapter_chain', sd3_ipadapter_data_components)
|
| 754 |
+
assign_chain_data('flux1_ipadapter_data', flux1_ipadapter_data_components)
|
| 755 |
+
assign_chain_data('style_data', style_data_components)
|
| 756 |
+
assign_chain_data('embedding_data', embedding_data_components)
|
| 757 |
+
assign_chain_data('conditioning_data', conditioning_data_components)
|
| 758 |
+
assign_chain_data('reference_latent_data', reference_latent_data_components)
|
| 759 |
|
| 760 |
return ui_dict
|
| 761 |
|
| 762 |
+
run_btn = ui_components.get(f'run_{prefix}') or ui_components.get(f'{prefix}_run_button')
|
| 763 |
+
res_gal = ui_components.get(f'result_{prefix}') or ui_components.get(f'{prefix}_output_gallery')
|
| 764 |
+
if run_btn and res_gal:
|
| 765 |
+
run_btn.click(
|
| 766 |
+
fn=lambda *args, progress=gr.Progress(track_tqdm=True): generate_image_wrapper(create_ui_inputs_dict(*args), progress),
|
| 767 |
+
inputs=input_list_flat,
|
| 768 |
+
outputs=[res_gal]
|
| 769 |
+
)
|
| 770 |
+
|
| 771 |
+
def make_update_fn(m_comp, cat_comp, cs_comp, ar_comp, width_comp, height_comp, cn_types, cn_series, cn_filepaths, diffsynth_cn_types, diffsynth_cn_series, diffsynth_cn_filepaths, ipa_preset, lora_acc, cn_acc, diffsynth_cn_acc, ipa_acc, sd3_ipa_acc, flux1_ipa_acc, style_acc, embed_acc, cond_acc, ref_latent_acc, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp):
|
| 772 |
+
def update_fn(*args):
|
| 773 |
+
arch = args[0]
|
| 774 |
+
category = args[1]
|
| 775 |
+
current_ar = args[2] if len(args) > 2 else None
|
| 776 |
+
from core.settings import MODEL_TYPE_MAP, MODEL_MAP_CHECKPOINT, FEATURES_CONFIG, ARCHITECTURES_CONFIG, MODEL_DEFAULTS_CONFIG, ARCH_CATEGORIES_MAP
|
| 777 |
+
from utils.app_utils import get_model_generation_defaults
|
| 778 |
+
|
| 779 |
+
if arch == "ALL":
|
| 780 |
+
valid_cats = list(set(cat for cats in ARCH_CATEGORIES_MAP.values() for cat in cats))
|
| 781 |
+
else:
|
| 782 |
+
valid_cats = ARCH_CATEGORIES_MAP.get(arch, [])
|
| 783 |
+
|
| 784 |
+
cat_choices = ["ALL"] + sorted(valid_cats)
|
| 785 |
+
new_category = category if category in cat_choices else "ALL"
|
| 786 |
+
|
| 787 |
+
choices = []
|
| 788 |
+
for name, info in MODEL_MAP_CHECKPOINT.items():
|
| 789 |
+
m_arch = info[2]
|
| 790 |
+
m_cat = info[4] if len(info) > 4 else None
|
| 791 |
+
arch_match = (arch == "ALL" or m_arch == arch)
|
| 792 |
+
cat_match = (new_category == "ALL" or m_cat == new_category)
|
| 793 |
+
if arch_match and cat_match:
|
| 794 |
+
choices.append(name)
|
| 795 |
+
|
| 796 |
+
val = choices[0] if choices else None
|
| 797 |
+
|
| 798 |
+
updates = {
|
| 799 |
+
m_comp: gr.update(choices=choices, value=val),
|
| 800 |
+
cat_comp: gr.update(choices=cat_choices, value=new_category)
|
| 801 |
+
}
|
| 802 |
+
|
| 803 |
+
m_type = MODEL_TYPE_MAP.get(val, "SDXL") if val else "SDXL"
|
| 804 |
+
|
| 805 |
+
architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 806 |
+
arch_model_type = architectures_dict.get(m_type, {}).get("model_type", m_type.lower().replace(" ", "").replace(".", ""))
|
| 807 |
+
|
| 808 |
+
arch_features = FEATURES_CONFIG.get(arch_model_type, FEATURES_CONFIG.get('default', {}))
|
| 809 |
+
enabled_chains = arch_features.get('enabled_chains', [])
|
| 810 |
+
|
| 811 |
+
if lora_acc: updates[lora_acc] = gr.update(visible=('lora' in enabled_chains))
|
| 812 |
+
if cn_acc: updates[cn_acc] = gr.update(visible=('controlnet' in enabled_chains))
|
| 813 |
+
if diffsynth_cn_acc: updates[diffsynth_cn_acc] = gr.update(visible=('controlnet_model_patch' in enabled_chains))
|
| 814 |
+
if ipa_acc: updates[ipa_acc] = gr.update(visible=('ipadapter' in enabled_chains))
|
| 815 |
+
if flux1_ipa_acc: updates[flux1_ipa_acc] = gr.update(visible=('flux1_ipadapter' in enabled_chains))
|
| 816 |
+
if sd3_ipa_acc: updates[sd3_ipa_acc] = gr.update(visible=('sd3_ipadapter' in enabled_chains))
|
| 817 |
+
if style_acc: updates[style_acc] = gr.update(visible=('style' in enabled_chains))
|
| 818 |
+
if embed_acc: updates[embed_acc] = gr.update(visible=('embedding' in enabled_chains))
|
| 819 |
+
if cond_acc: updates[cond_acc] = gr.update(visible=('conditioning' in enabled_chains))
|
| 820 |
+
if ref_latent_acc: updates[ref_latent_acc] = gr.update(visible=('reference_latent' in enabled_chains))
|
| 821 |
+
|
| 822 |
+
if cs_comp:
|
| 823 |
+
updates[cs_comp] = gr.update(visible=(arch_model_type == "sd15"))
|
| 824 |
+
if guidance_comp:
|
| 825 |
+
updates[guidance_comp] = gr.update(visible=(arch_model_type == "flux1"))
|
| 826 |
+
|
| 827 |
+
if ar_comp:
|
| 828 |
+
res_key = arch_model_type
|
| 829 |
+
if res_key not in RESOLUTION_MAP:
|
| 830 |
+
res_key = 'sdxl'
|
| 831 |
+
res_map = RESOLUTION_MAP.get(res_key, {})
|
| 832 |
+
target_ar = current_ar if current_ar in res_map else (list(res_map.keys())[0] if res_map else "1:1 (Square)")
|
| 833 |
+
updates[ar_comp] = gr.update(choices=list(res_map.keys()), value=target_ar)
|
| 834 |
+
if width_comp and height_comp and target_ar in res_map:
|
| 835 |
+
updates[width_comp] = gr.update(value=res_map[target_ar][0])
|
| 836 |
+
updates[height_comp] = gr.update(value=res_map[target_ar][1])
|
| 837 |
+
|
| 838 |
+
controlnet_key = architectures_dict.get(m_type, {}).get("controlnet_key", m_type)
|
| 839 |
+
|
| 840 |
+
all_types, default_type, series_choices, default_series, filepath = get_cn_defaults(controlnet_key)
|
| 841 |
+
for t_comp in cn_types:
|
| 842 |
+
updates[t_comp] = gr.update(choices=all_types, value=default_type)
|
| 843 |
+
for s_comp in cn_series:
|
| 844 |
+
updates[s_comp] = gr.update(choices=series_choices, value=default_series)
|
| 845 |
+
for f_comp in cn_filepaths:
|
| 846 |
+
updates[f_comp] = filepath
|
| 847 |
+
|
| 848 |
+
diffsynth_all_types, diffsynth_default_type, diffsynth_series_choices, diffsynth_default_series, diffsynth_filepath = get_diffsynth_cn_defaults(controlnet_key)
|
| 849 |
+
for t_comp in diffsynth_cn_types:
|
| 850 |
+
updates[t_comp] = gr.update(choices=diffsynth_all_types, value=diffsynth_default_type)
|
| 851 |
+
for s_comp in diffsynth_cn_series:
|
| 852 |
+
updates[s_comp] = gr.update(choices=diffsynth_series_choices, value=diffsynth_default_series)
|
| 853 |
+
for f_comp in diffsynth_cn_filepaths:
|
| 854 |
+
updates[f_comp] = diffsynth_filepath
|
| 855 |
+
|
| 856 |
+
if ipa_preset and (arch_model_type in ["sdxl", "sd15", "sd35"]):
|
| 857 |
+
config = load_ipadapter_config()
|
| 858 |
+
ipa_arch_key = "SDXL" if arch_model_type in ["sdxl", "sd35"] else "SD1.5"
|
| 859 |
+
std_presets = config.get("IPAdapter_presets", {}).get(ipa_arch_key, [])
|
| 860 |
+
face_presets = config.get("IPAdapter_FaceID_presets", {}).get(ipa_arch_key, [])
|
| 861 |
+
all_ipa_presets = std_presets + face_presets
|
| 862 |
+
default_ipa = all_ipa_presets[0] if all_ipa_presets else None
|
| 863 |
+
updates[ipa_preset] = gr.update(choices=all_ipa_presets, value=default_ipa)
|
| 864 |
+
|
| 865 |
+
defaults = get_model_generation_defaults(val, arch_model_type, MODEL_DEFAULTS_CONFIG)
|
| 866 |
+
if steps_comp: updates[steps_comp] = gr.update(value=defaults.get('steps'))
|
| 867 |
+
if cfg_comp: updates[cfg_comp] = gr.update(value=defaults.get('cfg'))
|
| 868 |
+
if sampler_comp: updates[sampler_comp] = gr.update(value=defaults.get('sampler_name'))
|
| 869 |
+
if scheduler_comp: updates[scheduler_comp] = gr.update(value=defaults.get('scheduler'))
|
| 870 |
+
if prompt_comp: updates[prompt_comp] = gr.update(value=defaults.get('positive_prompt'))
|
| 871 |
+
if neg_prompt_comp: updates[neg_prompt_comp] = gr.update(value=defaults.get('negative_prompt'))
|
| 872 |
+
|
| 873 |
+
return updates
|
| 874 |
+
return update_fn
|
| 875 |
+
|
| 876 |
+
def make_model_change_fn(cat_comp_ref, cs_comp, ar_comp, width_comp, height_comp, cn_types, cn_series, cn_filepaths, diffsynth_cn_types, diffsynth_cn_series, diffsynth_cn_filepaths, arch_comp_ref, ipa_preset, lora_acc, cn_acc, diffsynth_cn_acc, ipa_acc, sd3_ipa_acc, flux1_ipa_acc, style_acc, embed_acc, cond_acc, ref_latent_acc, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp):
|
| 877 |
+
def change_fn(*args):
|
| 878 |
+
model_name = args[0]
|
| 879 |
+
idx = 1
|
| 880 |
+
current_arch = args[idx] if arch_comp_ref and idx < len(args) else None
|
| 881 |
+
if arch_comp_ref: idx += 1
|
| 882 |
+
current_cat = args[idx] if cat_comp_ref and idx < len(args) else None
|
| 883 |
+
if cat_comp_ref: idx += 1
|
| 884 |
+
current_ar = args[idx] if idx < len(args) else None
|
| 885 |
+
from core.settings import MODEL_TYPE_MAP, FEATURES_CONFIG, ARCHITECTURES_CONFIG, MODEL_DEFAULTS_CONFIG, ARCH_CATEGORIES_MAP, MODEL_MAP_CHECKPOINT
|
| 886 |
+
from utils.app_utils import get_model_generation_defaults
|
| 887 |
+
m_type = MODEL_TYPE_MAP.get(model_name, "SDXL")
|
| 888 |
+
|
| 889 |
+
m_info = MODEL_MAP_CHECKPOINT.get(model_name)
|
| 890 |
+
m_cat = m_info[4] if m_info and len(m_info) > 4 else None
|
| 891 |
+
if not m_cat: m_cat = "ALL"
|
| 892 |
+
|
| 893 |
+
updates = {}
|
| 894 |
+
target_arch = m_type
|
| 895 |
+
if arch_comp_ref:
|
| 896 |
+
if current_arch == "ALL":
|
| 897 |
+
updates[arch_comp_ref] = gr.update()
|
| 898 |
+
target_arch = "ALL"
|
| 899 |
+
else:
|
| 900 |
+
updates[arch_comp_ref] = m_type
|
| 901 |
+
|
| 902 |
+
if cat_comp_ref:
|
| 903 |
+
if target_arch == "ALL":
|
| 904 |
+
valid_cats = list(set(cat for cats in ARCH_CATEGORIES_MAP.values() for cat in cats))
|
| 905 |
+
else:
|
| 906 |
+
valid_cats = ARCH_CATEGORIES_MAP.get(target_arch, [])
|
| 907 |
+
cat_choices = ["ALL"] + sorted(valid_cats)
|
| 908 |
+
|
| 909 |
+
if current_cat == "ALL":
|
| 910 |
+
updates[cat_comp_ref] = gr.update(choices=cat_choices)
|
| 911 |
+
else:
|
| 912 |
+
updates[cat_comp_ref] = gr.update(choices=cat_choices, value=m_cat)
|
| 913 |
+
|
| 914 |
+
architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 915 |
+
arch_model_type = architectures_dict.get(m_type, {}).get("model_type", m_type.lower().replace(" ", "").replace(".", ""))
|
| 916 |
+
|
| 917 |
+
arch_features = FEATURES_CONFIG.get(arch_model_type, FEATURES_CONFIG.get('default', {}))
|
| 918 |
+
enabled_chains = arch_features.get('enabled_chains', [])
|
| 919 |
+
|
| 920 |
+
if lora_acc: updates[lora_acc] = gr.update(visible=('lora' in enabled_chains))
|
| 921 |
+
if cn_acc: updates[cn_acc] = gr.update(visible=('controlnet' in enabled_chains))
|
| 922 |
+
if diffsynth_cn_acc: updates[diffsynth_cn_acc] = gr.update(visible=('controlnet_model_patch' in enabled_chains))
|
| 923 |
+
if ipa_acc: updates[ipa_acc] = gr.update(visible=('ipadapter' in enabled_chains))
|
| 924 |
+
if flux1_ipa_acc: updates[flux1_ipa_acc] = gr.update(visible=('flux1_ipadapter' in enabled_chains))
|
| 925 |
+
if sd3_ipa_acc: updates[sd3_ipa_acc] = gr.update(visible=('sd3_ipadapter' in enabled_chains))
|
| 926 |
+
if style_acc: updates[style_acc] = gr.update(visible=('style' in enabled_chains))
|
| 927 |
+
if embed_acc: updates[embed_acc] = gr.update(visible=('embedding' in enabled_chains))
|
| 928 |
+
if cond_acc: updates[cond_acc] = gr.update(visible=('conditioning' in enabled_chains))
|
| 929 |
+
if ref_latent_acc: updates[ref_latent_acc] = gr.update(visible=('reference_latent' in enabled_chains))
|
| 930 |
+
|
| 931 |
+
if cs_comp:
|
| 932 |
+
updates[cs_comp] = gr.update(visible=(arch_model_type == "sd15"))
|
| 933 |
+
if guidance_comp:
|
| 934 |
+
updates[guidance_comp] = gr.update(visible=(arch_model_type == "flux1"))
|
| 935 |
+
|
| 936 |
+
if ar_comp:
|
| 937 |
+
res_key = arch_model_type
|
| 938 |
+
if res_key not in RESOLUTION_MAP:
|
| 939 |
+
res_key = 'sdxl'
|
| 940 |
+
res_map = RESOLUTION_MAP.get(res_key, {})
|
| 941 |
+
target_ar = current_ar if current_ar in res_map else (list(res_map.keys())[0] if res_map else "1:1 (Square)")
|
| 942 |
+
updates[ar_comp] = gr.update(choices=list(res_map.keys()), value=target_ar)
|
| 943 |
+
if width_comp and height_comp and target_ar in res_map:
|
| 944 |
+
updates[width_comp] = gr.update(value=res_map[target_ar][0])
|
| 945 |
+
updates[height_comp] = gr.update(value=res_map[target_ar][1])
|
| 946 |
+
|
| 947 |
+
controlnet_key = architectures_dict.get(m_type, {}).get("controlnet_key", m_type)
|
| 948 |
+
|
| 949 |
+
all_types, default_type, series_choices, default_series, filepath = get_cn_defaults(controlnet_key)
|
| 950 |
+
for t_comp in cn_types:
|
| 951 |
+
updates[t_comp] = gr.update(choices=all_types, value=default_type)
|
| 952 |
+
for s_comp in cn_series:
|
| 953 |
+
updates[s_comp] = gr.update(choices=series_choices, value=default_series)
|
| 954 |
+
for f_comp in cn_filepaths:
|
| 955 |
+
updates[f_comp] = filepath
|
| 956 |
+
|
| 957 |
+
diffsynth_all_types, diffsynth_default_type, diffsynth_series_choices, diffsynth_default_series, diffsynth_filepath = get_diffsynth_cn_defaults(controlnet_key)
|
| 958 |
+
for t_comp in diffsynth_cn_types:
|
| 959 |
+
updates[t_comp] = gr.update(choices=diffsynth_all_types, value=diffsynth_default_type)
|
| 960 |
+
for s_comp in diffsynth_cn_series:
|
| 961 |
+
updates[s_comp] = gr.update(choices=diffsynth_series_choices, value=diffsynth_default_series)
|
| 962 |
+
for f_comp in diffsynth_cn_filepaths:
|
| 963 |
+
updates[f_comp] = diffsynth_filepath
|
| 964 |
+
|
| 965 |
+
if ipa_preset and (arch_model_type in ["sdxl", "sd15", "sd35"]):
|
| 966 |
+
config = load_ipadapter_config()
|
| 967 |
+
ipa_arch_key = "SDXL" if arch_model_type in ["sdxl", "sd35"] else "SD1.5"
|
| 968 |
+
std_presets = config.get("IPAdapter_presets", {}).get(ipa_arch_key, [])
|
| 969 |
+
face_presets = config.get("IPAdapter_FaceID_presets", {}).get(ipa_arch_key, [])
|
| 970 |
+
all_ipa_presets = std_presets + face_presets
|
| 971 |
+
default_ipa = all_ipa_presets[0] if all_ipa_presets else None
|
| 972 |
+
updates[ipa_preset] = gr.update(choices=all_ipa_presets, value=default_ipa)
|
| 973 |
+
|
| 974 |
+
defaults = get_model_generation_defaults(model_name, arch_model_type, MODEL_DEFAULTS_CONFIG)
|
| 975 |
+
if steps_comp: updates[steps_comp] = gr.update(value=defaults.get('steps'))
|
| 976 |
+
if cfg_comp: updates[cfg_comp] = gr.update(value=defaults.get('cfg'))
|
| 977 |
+
if sampler_comp: updates[sampler_comp] = gr.update(value=defaults.get('sampler_name'))
|
| 978 |
+
if scheduler_comp: updates[scheduler_comp] = gr.update(value=defaults.get('scheduler'))
|
| 979 |
+
if prompt_comp: updates[prompt_comp] = gr.update(value=defaults.get('positive_prompt'))
|
| 980 |
+
if neg_prompt_comp: updates[neg_prompt_comp] = gr.update(value=defaults.get('negative_prompt'))
|
| 981 |
+
|
| 982 |
+
return updates
|
| 983 |
+
return change_fn
|
| 984 |
|
| 985 |
|
| 986 |
for prefix, task_type in [
|
| 987 |
("txt2img", "txt2img"), ("img2img", "img2img"), ("inpaint", "inpaint"),
|
| 988 |
("outpaint", "outpaint"), ("hires_fix", "hires_fix"),
|
| 989 |
]:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 990 |
|
| 991 |
+
arch_comp = ui_components.get(f'model_arch_{prefix}')
|
| 992 |
+
cat_comp = ui_components.get(f'model_cat_{prefix}')
|
| 993 |
+
model_comp = ui_components.get(f'base_model_{prefix}')
|
| 994 |
+
clip_skip_comp = ui_components.get(f'clip_skip_{prefix}') or ui_components.get(f'{prefix}_clip_skip')
|
| 995 |
+
guidance_comp = ui_components.get(f'guidance_{prefix}') or ui_components.get(f'{prefix}_guidance')
|
| 996 |
+
aspect_ratio_comp = ui_components.get(f'aspect_ratio_{prefix}') or ui_components.get(f'{prefix}_aspect_ratio_dropdown')
|
| 997 |
+
width_comp = ui_components.get(f'width_{prefix}') or ui_components.get(f'{prefix}_width')
|
| 998 |
+
height_comp = ui_components.get(f'height_{prefix}') or ui_components.get(f'{prefix}_height')
|
| 999 |
+
|
| 1000 |
+
cn_types_list = ui_components.get(f'controlnet_types_{prefix}', [])
|
| 1001 |
+
cn_series_list = ui_components.get(f'controlnet_series_{prefix}', [])
|
| 1002 |
+
cn_filepaths_list = ui_components.get(f'controlnet_filepaths_{prefix}', [])
|
| 1003 |
+
|
| 1004 |
+
diffsynth_cn_types_list = ui_components.get(f'diffsynth_controlnet_types_{prefix}', [])
|
| 1005 |
+
diffsynth_cn_series_list = ui_components.get(f'diffsynth_controlnet_series_{prefix}', [])
|
| 1006 |
+
diffsynth_cn_filepaths_list = ui_components.get(f'diffsynth_controlnet_filepaths_{prefix}', [])
|
| 1007 |
+
|
| 1008 |
+
lora_accordion = ui_components.get(f'lora_accordion_{prefix}')
|
| 1009 |
+
cn_accordion = ui_components.get(f'controlnet_accordion_{prefix}')
|
| 1010 |
+
diffsynth_cn_accordion = ui_components.get(f'diffsynth_controlnet_accordion_{prefix}')
|
| 1011 |
+
ipa_accordion = ui_components.get(f'ipadapter_accordion_{prefix}')
|
| 1012 |
+
sd3_ipa_accordion = ui_components.get(f'sd3_ipadapter_accordion_{prefix}')
|
| 1013 |
+
flux1_ipa_accordion = ui_components.get(f'flux1_ipadapter_accordion_{prefix}')
|
| 1014 |
+
style_accordion = ui_components.get(f'style_accordion_{prefix}')
|
| 1015 |
+
embedding_accordion = ui_components.get(f'embedding_accordion_{prefix}')
|
| 1016 |
+
conditioning_accordion = ui_components.get(f'conditioning_accordion_{prefix}')
|
| 1017 |
+
ref_latent_accordion = ui_components.get(f'reference_latent_accordion_{prefix}')
|
| 1018 |
+
|
| 1019 |
+
ipa_preset_list = ui_components.get(f'ipadapter_final_preset_{prefix}')
|
| 1020 |
+
|
| 1021 |
+
prompt_comp = ui_components.get(f'prompt_{prefix}') or ui_components.get(f'{prefix}_positive_prompt')
|
| 1022 |
+
neg_prompt_comp = ui_components.get(f'neg_prompt_{prefix}') or ui_components.get(f'{prefix}_negative_prompt')
|
| 1023 |
+
steps_comp = ui_components.get(f'steps_{prefix}') or ui_components.get(f'{prefix}_steps')
|
| 1024 |
+
cfg_comp = ui_components.get(f'cfg_{prefix}') or ui_components.get(f'{prefix}_cfg')
|
| 1025 |
+
sampler_comp = ui_components.get(f'sampler_{prefix}') or ui_components.get(f'{prefix}_sampler_name')
|
| 1026 |
+
scheduler_comp = ui_components.get(f'scheduler_{prefix}') or ui_components.get(f'{prefix}_scheduler')
|
| 1027 |
+
|
| 1028 |
+
extra_comps = [prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp, width_comp, height_comp]
|
| 1029 |
+
valid_extra_comps = [c for c in extra_comps if c is not None]
|
| 1030 |
+
|
| 1031 |
+
if arch_comp and cat_comp and model_comp:
|
| 1032 |
+
outputs = [model_comp, cat_comp]
|
| 1033 |
+
if clip_skip_comp: outputs.append(clip_skip_comp)
|
| 1034 |
+
if guidance_comp: outputs.append(guidance_comp)
|
| 1035 |
+
if aspect_ratio_comp: outputs.append(aspect_ratio_comp)
|
| 1036 |
+
outputs.extend(cn_types_list + cn_series_list + cn_filepaths_list)
|
| 1037 |
+
outputs.extend(diffsynth_cn_types_list + diffsynth_cn_series_list + diffsynth_cn_filepaths_list)
|
| 1038 |
+
if lora_accordion: outputs.append(lora_accordion)
|
| 1039 |
+
if cn_accordion: outputs.append(cn_accordion)
|
| 1040 |
+
if diffsynth_cn_accordion: outputs.append(diffsynth_cn_accordion)
|
| 1041 |
+
if ipa_accordion: outputs.append(ipa_accordion)
|
| 1042 |
+
if sd3_ipa_accordion: outputs.append(sd3_ipa_accordion)
|
| 1043 |
+
if flux1_ipa_accordion: outputs.append(flux1_ipa_accordion)
|
| 1044 |
+
if style_accordion: outputs.append(style_accordion)
|
| 1045 |
+
if embedding_accordion: outputs.append(embedding_accordion)
|
| 1046 |
+
if conditioning_accordion: outputs.append(conditioning_accordion)
|
| 1047 |
+
if ref_latent_accordion: outputs.append(ref_latent_accordion)
|
| 1048 |
+
if ipa_preset_list: outputs.append(ipa_preset_list)
|
| 1049 |
+
|
| 1050 |
+
outputs.extend(valid_extra_comps)
|
| 1051 |
+
|
| 1052 |
+
update_fn = make_update_fn(
|
| 1053 |
+
model_comp, cat_comp, clip_skip_comp, aspect_ratio_comp, width_comp, height_comp,
|
| 1054 |
+
cn_types_list, cn_series_list, cn_filepaths_list,
|
| 1055 |
+
diffsynth_cn_types_list, diffsynth_cn_series_list, diffsynth_cn_filepaths_list,
|
| 1056 |
+
ipa_preset_list, lora_accordion, cn_accordion, diffsynth_cn_accordion, ipa_accordion, sd3_ipa_accordion, flux1_ipa_accordion, style_accordion, embedding_accordion, conditioning_accordion,
|
| 1057 |
+
ref_latent_accordion, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp
|
| 1058 |
+
)
|
| 1059 |
+
inputs = [arch_comp, cat_comp]
|
| 1060 |
+
if aspect_ratio_comp:
|
| 1061 |
+
inputs.append(aspect_ratio_comp)
|
| 1062 |
+
arch_comp.change(fn=update_fn, inputs=inputs, outputs=outputs)
|
| 1063 |
+
cat_comp.change(fn=update_fn, inputs=inputs, outputs=outputs)
|
| 1064 |
|
| 1065 |
+
if model_comp:
|
| 1066 |
+
outputs2 = []
|
| 1067 |
+
if arch_comp: outputs2.append(arch_comp)
|
| 1068 |
+
if cat_comp: outputs2.append(cat_comp)
|
| 1069 |
+
if clip_skip_comp: outputs2.append(clip_skip_comp)
|
| 1070 |
+
if guidance_comp: outputs2.append(guidance_comp)
|
| 1071 |
+
if aspect_ratio_comp: outputs2.append(aspect_ratio_comp)
|
| 1072 |
+
outputs2.extend(cn_types_list + cn_series_list + cn_filepaths_list)
|
| 1073 |
+
outputs2.extend(diffsynth_cn_types_list + diffsynth_cn_series_list + diffsynth_cn_filepaths_list)
|
| 1074 |
+
if lora_accordion: outputs2.append(lora_accordion)
|
| 1075 |
+
if cn_accordion: outputs2.append(cn_accordion)
|
| 1076 |
+
if diffsynth_cn_accordion: outputs2.append(diffsynth_cn_accordion)
|
| 1077 |
+
if ipa_accordion: outputs2.append(ipa_accordion)
|
| 1078 |
+
if sd3_ipa_accordion: outputs2.append(sd3_ipa_accordion)
|
| 1079 |
+
if flux1_ipa_accordion: outputs2.append(flux1_ipa_accordion)
|
| 1080 |
+
if style_accordion: outputs2.append(style_accordion)
|
| 1081 |
+
if embedding_accordion: outputs2.append(embedding_accordion)
|
| 1082 |
+
if conditioning_accordion: outputs2.append(conditioning_accordion)
|
| 1083 |
+
if ref_latent_accordion: outputs2.append(ref_latent_accordion)
|
| 1084 |
+
if ipa_preset_list: outputs2.append(ipa_preset_list)
|
| 1085 |
+
|
| 1086 |
+
outputs2.extend(valid_extra_comps)
|
| 1087 |
+
|
| 1088 |
+
if outputs2:
|
| 1089 |
+
inputs2 = [model_comp]
|
| 1090 |
+
if arch_comp: inputs2.append(arch_comp)
|
| 1091 |
+
if cat_comp: inputs2.append(cat_comp)
|
| 1092 |
+
if aspect_ratio_comp: inputs2.append(aspect_ratio_comp)
|
| 1093 |
+
change_fn = make_model_change_fn(
|
| 1094 |
+
cat_comp, clip_skip_comp, aspect_ratio_comp, width_comp, height_comp,
|
| 1095 |
+
cn_types_list, cn_series_list, cn_filepaths_list,
|
| 1096 |
+
diffsynth_cn_types_list, diffsynth_cn_series_list, diffsynth_cn_filepaths_list,
|
| 1097 |
+
arch_comp, ipa_preset_list, lora_accordion, cn_accordion, diffsynth_cn_accordion, ipa_accordion, sd3_ipa_accordion, flux1_ipa_accordion, style_accordion, embedding_accordion, conditioning_accordion,
|
| 1098 |
+
ref_latent_accordion, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp
|
| 1099 |
)
|
| 1100 |
+
model_comp.change(fn=change_fn, inputs=inputs2, outputs=outputs2)
|
| 1101 |
|
| 1102 |
+
create_lora_event_handlers(prefix)
|
| 1103 |
+
create_controlnet_event_handlers(prefix)
|
| 1104 |
+
create_diffsynth_controlnet_event_handlers(prefix)
|
| 1105 |
+
create_ipadapter_event_handlers(prefix)
|
| 1106 |
+
create_embedding_event_handlers(prefix)
|
| 1107 |
+
create_conditioning_event_handlers(prefix)
|
| 1108 |
+
create_flux1_ipadapter_event_handlers(prefix)
|
| 1109 |
+
create_style_event_handlers(prefix)
|
| 1110 |
+
create_reference_latent_event_handlers(prefix)
|
| 1111 |
create_run_event(prefix, task_type)
|
| 1112 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1113 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1114 |
if 'view_mode_inpaint' in ui_components:
|
| 1115 |
def toggle_inpaint_fullscreen_view(view_mode):
|
| 1116 |
is_fullscreen = (view_mode == "Fullscreen View")
|
| 1117 |
other_elements_visible = not is_fullscreen
|
| 1118 |
editor_height = 800 if is_fullscreen else 272
|
| 1119 |
+
|
| 1120 |
+
updates = {
|
| 1121 |
ui_components['prompts_column_inpaint']: gr.update(visible=other_elements_visible),
|
| 1122 |
ui_components['params_and_gallery_row_inpaint']: gr.update(visible=other_elements_visible),
|
| 1123 |
ui_components['accordion_wrapper_inpaint']: gr.update(visible=other_elements_visible),
|
| 1124 |
ui_components['input_image_dict_inpaint']: gr.update(height=editor_height),
|
| 1125 |
}
|
| 1126 |
+
|
| 1127 |
+
model_and_run_rows = ui_components.get('model_and_run_row_inpaint', [])
|
| 1128 |
+
for row in model_and_run_rows:
|
| 1129 |
+
updates[row] = gr.update(visible=other_elements_visible)
|
| 1130 |
+
|
| 1131 |
+
return updates
|
| 1132 |
+
|
| 1133 |
+
output_components = []
|
| 1134 |
+
model_and_run_rows = ui_components.get('model_and_run_row_inpaint', [])
|
| 1135 |
+
if isinstance(model_and_run_rows, list):
|
| 1136 |
+
output_components.extend(model_and_run_rows)
|
| 1137 |
+
else:
|
| 1138 |
+
output_components.append(model_and_run_rows)
|
| 1139 |
|
| 1140 |
+
output_components.extend([
|
| 1141 |
+
ui_components['prompts_column_inpaint'],
|
| 1142 |
+
ui_components['params_and_gallery_row_inpaint'],
|
| 1143 |
+
ui_components['accordion_wrapper_inpaint'],
|
| 1144 |
ui_components['input_image_dict_inpaint']
|
| 1145 |
+
])
|
| 1146 |
+
|
| 1147 |
+
ui_components['view_mode_inpaint'].change(
|
| 1148 |
+
fn=toggle_inpaint_fullscreen_view,
|
| 1149 |
+
inputs=[ui_components['view_mode_inpaint']],
|
| 1150 |
+
outputs=output_components,
|
| 1151 |
+
show_progress=False
|
| 1152 |
+
)
|
| 1153 |
|
| 1154 |
+
def initialize_all_cn_dropdowns():
|
| 1155 |
+
from core.settings import MODEL_TYPE_MAP, MODEL_MAP_CHECKPOINT, ARCHITECTURES_CONFIG
|
| 1156 |
+
default_model_name = list(MODEL_MAP_CHECKPOINT.keys())[0] if MODEL_MAP_CHECKPOINT else None
|
| 1157 |
+
default_m_type = MODEL_TYPE_MAP.get(default_model_name, "SDXL") if default_model_name else "SDXL"
|
| 1158 |
+
architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 1159 |
+
controlnet_key = architectures_dict.get(default_m_type, {}).get("controlnet_key", default_m_type)
|
| 1160 |
|
| 1161 |
+
all_types, default_type, series_choices, default_series, filepath = get_cn_defaults(controlnet_key)
|
| 1162 |
+
diffsynth_all_types, diffsynth_default_type, diffsynth_series_choices, diffsynth_default_series, diffsynth_filepath = get_diffsynth_cn_defaults(controlnet_key)
|
|
|
|
| 1163 |
|
| 1164 |
+
updates = {}
|
| 1165 |
+
for prefix in ["txt2img", "img2img", "inpaint", "outpaint", "hires_fix"]:
|
| 1166 |
+
if f'controlnet_types_{prefix}' in ui_components:
|
| 1167 |
+
for type_dd in ui_components[f'controlnet_types_{prefix}']:
|
| 1168 |
+
updates[type_dd] = gr.update(choices=all_types, value=default_type)
|
| 1169 |
+
for series_dd in ui_components[f'controlnet_series_{prefix}']:
|
| 1170 |
+
updates[series_dd] = gr.update(choices=series_choices, value=default_series)
|
| 1171 |
+
for filepath_state in ui_components[f'controlnet_filepaths_{prefix}']:
|
| 1172 |
+
updates[filepath_state] = filepath
|
| 1173 |
+
|
| 1174 |
+
if f'diffsynth_controlnet_types_{prefix}' in ui_components:
|
| 1175 |
+
for type_dd in ui_components[f'diffsynth_controlnet_types_{prefix}']:
|
| 1176 |
+
updates[type_dd] = gr.update(choices=diffsynth_all_types, value=diffsynth_default_type)
|
| 1177 |
+
for series_dd in ui_components[f'diffsynth_controlnet_series_{prefix}']:
|
| 1178 |
+
updates[series_dd] = gr.update(choices=diffsynth_series_choices, value=diffsynth_default_series)
|
| 1179 |
+
for filepath_state in ui_components[f'diffsynth_controlnet_filepaths_{prefix}']:
|
| 1180 |
+
updates[filepath_state] = diffsynth_filepath
|
| 1181 |
+
|
| 1182 |
+
return updates
|
| 1183 |
|
| 1184 |
+
def initialize_all_ipa_dropdowns():
|
| 1185 |
+
config = load_ipadapter_config()
|
| 1186 |
+
if not config: return {}
|
| 1187 |
+
|
| 1188 |
+
from core.settings import MODEL_TYPE_MAP, MODEL_MAP_CHECKPOINT, ARCHITECTURES_CONFIG
|
| 1189 |
+
default_model_name = list(MODEL_MAP_CHECKPOINT.keys())[0] if MODEL_MAP_CHECKPOINT else None
|
| 1190 |
+
default_m_type = MODEL_TYPE_MAP.get(default_model_name, "SDXL") if default_model_name else "SDXL"
|
| 1191 |
+
architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 1192 |
+
arch_model_type = architectures_dict.get(default_m_type, {}).get("model_type", default_m_type.lower().replace(" ", "").replace(".", ""))
|
| 1193 |
+
ipa_arch_key = "SDXL" if arch_model_type in ["sdxl", "sd35"] else "SD1.5"
|
| 1194 |
+
|
| 1195 |
+
unified_presets = config.get("IPAdapter_presets", {}).get(ipa_arch_key, [])
|
| 1196 |
+
faceid_presets = config.get("IPAdapter_FaceID_presets", {}).get(ipa_arch_key, [])
|
| 1197 |
+
|
| 1198 |
+
all_presets = unified_presets + faceid_presets
|
| 1199 |
+
default_preset = all_presets[0] if all_presets else None
|
| 1200 |
+
is_faceid_default = default_preset in faceid_presets
|
| 1201 |
+
|
| 1202 |
+
lora_strength_update = gr.update(visible=is_faceid_default)
|
| 1203 |
+
|
| 1204 |
+
updates = {}
|
| 1205 |
+
for prefix in ["txt2img", "img2img", "inpaint", "outpaint", "hires_fix"]:
|
| 1206 |
+
if f'ipadapter_final_preset_{prefix}' in ui_components:
|
| 1207 |
+
for lora_strength_slider in ui_components[f'ipadapter_lora_strengths_{prefix}']:
|
| 1208 |
+
updates[lora_strength_slider] = lora_strength_update
|
| 1209 |
+
updates[ui_components[f'ipadapter_final_preset_{prefix}']] = gr.update(choices=all_presets, value=default_preset)
|
| 1210 |
+
updates[ui_components[f'ipadapter_final_lora_strength_{prefix}']] = lora_strength_update
|
| 1211 |
+
return updates
|
| 1212 |
+
|
| 1213 |
+
def run_on_load():
|
| 1214 |
+
cn_updates = initialize_all_cn_dropdowns()
|
| 1215 |
+
ipa_updates = initialize_all_ipa_dropdowns()
|
| 1216 |
+
|
| 1217 |
+
all_updates = {**cn_updates, **ipa_updates}
|
| 1218 |
|
| 1219 |
return all_updates
|
| 1220 |
|
| 1221 |
+
all_load_outputs = []
|
| 1222 |
+
for prefix in ["txt2img", "img2img", "inpaint", "outpaint", "hires_fix"]:
|
| 1223 |
+
if f'controlnet_types_{prefix}' in ui_components:
|
| 1224 |
+
all_load_outputs.extend(ui_components[f'controlnet_types_{prefix}'])
|
| 1225 |
+
all_load_outputs.extend(ui_components[f'controlnet_series_{prefix}'])
|
| 1226 |
+
all_load_outputs.extend(ui_components[f'controlnet_filepaths_{prefix}'])
|
| 1227 |
+
if f'diffsynth_controlnet_types_{prefix}' in ui_components:
|
| 1228 |
+
all_load_outputs.extend(ui_components[f'diffsynth_controlnet_types_{prefix}'])
|
| 1229 |
+
all_load_outputs.extend(ui_components[f'diffsynth_controlnet_series_{prefix}'])
|
| 1230 |
+
all_load_outputs.extend(ui_components[f'diffsynth_controlnet_filepaths_{prefix}'])
|
| 1231 |
+
if f'ipadapter_final_preset_{prefix}' in ui_components:
|
| 1232 |
+
all_load_outputs.extend(ui_components[f'ipadapter_lora_strengths_{prefix}'])
|
| 1233 |
+
all_load_outputs.append(ui_components[f'ipadapter_final_preset_{prefix}'])
|
| 1234 |
+
all_load_outputs.append(ui_components[f'ipadapter_final_lora_strength_{prefix}'])
|
| 1235 |
|
| 1236 |
if all_load_outputs:
|
| 1237 |
demo.load(
|
| 1238 |
fn=run_on_load,
|
| 1239 |
outputs=all_load_outputs
|
| 1240 |
+
)
|
| 1241 |
+
|
| 1242 |
+
def on_aspect_ratio_change(ratio_key, model_display_name):
|
| 1243 |
+
from core.settings import MODEL_TYPE_MAP, ARCHITECTURES_CONFIG
|
| 1244 |
+
m_type = MODEL_TYPE_MAP.get(model_display_name, 'SDXL')
|
| 1245 |
+
architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 1246 |
+
arch_model_type = architectures_dict.get(m_type, {}).get("model_type", m_type.lower().replace(" ", "").replace(".", ""))
|
| 1247 |
+
|
| 1248 |
+
res_map = RESOLUTION_MAP.get(arch_model_type, RESOLUTION_MAP.get("sdxl", {}))
|
| 1249 |
+
w, h = res_map.get(ratio_key, (1024, 1024))
|
| 1250 |
+
return w, h
|
| 1251 |
+
|
| 1252 |
+
for prefix in ["txt2img", "img2img", "inpaint", "outpaint", "hires_fix"]:
|
| 1253 |
+
aspect_ratio_dropdown = ui_components.get(f'aspect_ratio_{prefix}') or ui_components.get(f'{prefix}_aspect_ratio_dropdown')
|
| 1254 |
+
width_component = ui_components.get(f'width_{prefix}') or ui_components.get(f'{prefix}_width')
|
| 1255 |
+
height_component = ui_components.get(f'height_{prefix}') or ui_components.get(f'{prefix}_height')
|
| 1256 |
+
model_dropdown = ui_components.get(f'base_model_{prefix}')
|
| 1257 |
+
if aspect_ratio_dropdown and width_component and height_component and model_dropdown:
|
| 1258 |
+
aspect_ratio_dropdown.change(fn=on_aspect_ratio_change, inputs=[aspect_ratio_dropdown, model_dropdown], outputs=[width_component, height_component], show_progress=False)
|
ui/layout.py
CHANGED
|
@@ -6,83 +6,37 @@ from .shared import txt2img_ui, img2img_ui, inpaint_ui, outpaint_ui, hires_fix_u
|
|
| 6 |
|
| 7 |
MAX_DYNAMIC_CONTROLS = 10
|
| 8 |
|
| 9 |
-
def get_preprocessor_choices():
|
| 10 |
-
from nodes import NODE_DISPLAY_NAME_MAPPINGS
|
| 11 |
-
|
| 12 |
-
preprocessor_names = [
|
| 13 |
-
display_name for class_name, display_name in NODE_DISPLAY_NAME_MAPPINGS.items()
|
| 14 |
-
if "Preprocessor" in class_name or "Segmentor" in class_name or
|
| 15 |
-
"Estimator" in class_name or "Detector" in class_name
|
| 16 |
-
]
|
| 17 |
-
return sorted(list(set(preprocessor_names)))
|
| 18 |
-
|
| 19 |
-
|
| 20 |
def build_ui(event_handler_function):
|
| 21 |
ui_components = {}
|
| 22 |
|
| 23 |
with gr.Blocks() as demo:
|
| 24 |
-
gr.Markdown("# ImageGen - FLUX.2")
|
| 25 |
gr.Markdown(
|
| 26 |
-
"This demo is a streamlined version of the [Comfy web UI](https://github.com/RioShiina47/comfy-webui)'s
|
| 27 |
"Other versions are also available: "
|
| 28 |
-
"[Z-Image](https://huggingface.co/spaces/RioShiina/ImageGen-Z-Image), "
|
| 29 |
-
"[Qwen-Image](https://huggingface.co/spaces/RioShiina/ImageGen-Qwen-Image), "
|
| 30 |
"[Anima](https://huggingface.co/spaces/RioShiina/ImageGen-Anima), "
|
| 31 |
-
"[
|
| 32 |
"[NoobAI](https://huggingface.co/spaces/RioShiina/ImageGen-NoobAI), "
|
| 33 |
-
"[Pony](https://huggingface.co/spaces/RioShiina/ImageGen-
|
| 34 |
-
"[SDXL](https://huggingface.co/spaces/RioShiina/ImageGen-SDXL)"
|
| 35 |
)
|
| 36 |
with gr.Tabs(elem_id="tabs_container") as tabs:
|
| 37 |
-
with gr.TabItem("
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
with gr.TabItem("Img2Img", id=1):
|
| 43 |
-
ui_components.update(img2img_ui.create_ui())
|
| 44 |
|
| 45 |
-
|
| 46 |
-
|
| 47 |
|
| 48 |
-
|
| 49 |
-
|
| 50 |
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
ui_components['image_gen_tabs'] = image_gen_tabs
|
| 55 |
|
| 56 |
-
with gr.TabItem("Controlnet Preprocessors", id=1):
|
| 57 |
-
gr.Markdown("## ControlNet Auxiliary Preprocessors")
|
| 58 |
-
gr.Markdown("Powered by [Fannovel16/comfyui_controlnet_aux](https://github.com/Fannovel16/comfyui_controlnet_aux).")
|
| 59 |
-
gr.Markdown("Upload an image or video to process it with a ControlNet preprocessor.")
|
| 60 |
-
with gr.Row():
|
| 61 |
-
with gr.Column(scale=1):
|
| 62 |
-
cn_input_type = gr.Radio(["Image", "Video"], label="Input Type", value="Image")
|
| 63 |
-
cn_image_input = gr.Image(type="pil", label="Input Image", visible=True, height=384)
|
| 64 |
-
cn_video_input = gr.Video(label="Input Video", visible=False)
|
| 65 |
-
preprocessor_cn = gr.Dropdown(label="Preprocessor", choices=get_preprocessor_choices(), value="Canny Edge")
|
| 66 |
-
preprocessor_model_cn = gr.Dropdown(label="Preprocessor Model", choices=[], value=None, visible=False)
|
| 67 |
-
with gr.Column() as preprocessor_settings_ui:
|
| 68 |
-
cn_sliders, cn_dropdowns, cn_checkboxes = [], [], []
|
| 69 |
-
for i in range(MAX_DYNAMIC_CONTROLS):
|
| 70 |
-
cn_sliders.append(gr.Slider(visible=False, label=f"dyn_slider_{i}"))
|
| 71 |
-
cn_dropdowns.append(gr.Dropdown(visible=False, label=f"dyn_dropdown_{i}"))
|
| 72 |
-
cn_checkboxes.append(gr.Checkbox(visible=False, label=f"dyn_checkbox_{i}"))
|
| 73 |
-
run_cn = gr.Button("Run Preprocessor", variant="primary")
|
| 74 |
-
with gr.Column(scale=1):
|
| 75 |
-
output_gallery_cn = gr.Gallery(label="Output", show_label=False, object_fit="contain", height=512)
|
| 76 |
-
zero_gpu_cn = gr.Number(label="ZeroGPU Duration (s)", value=None, placeholder="Default: 60, Max: 120", info="Optional")
|
| 77 |
-
ui_components.update({
|
| 78 |
-
"cn_input_type": cn_input_type, "cn_image_input": cn_image_input, "cn_video_input": cn_video_input,
|
| 79 |
-
"preprocessor_cn": preprocessor_cn, "preprocessor_model_cn": preprocessor_model_cn, "run_cn": run_cn,
|
| 80 |
-
"zero_gpu_cn": zero_gpu_cn, "output_gallery_cn": output_gallery_cn,
|
| 81 |
-
"preprocessor_settings_ui": preprocessor_settings_ui, "cn_sliders": cn_sliders,
|
| 82 |
-
"cn_dropdowns": cn_dropdowns, "cn_checkboxes": cn_checkboxes
|
| 83 |
-
})
|
| 84 |
-
|
| 85 |
ui_components["tabs"] = tabs
|
|
|
|
| 86 |
|
| 87 |
gr.Markdown("<div style='text-align: center; margin-top: 20px;'>Made by RioShiina with ❤️<br><a href='https://github.com/RioShiina47' target='_blank'>GitHub</a> | <a href='https://huggingface.co/RioShiina' target='_blank'>Hugging Face</a> | <a href='https://civitai.com/user/RioShiina' target='_blank'>Civitai</a></div>")
|
| 88 |
|
|
|
|
| 6 |
|
| 7 |
MAX_DYNAMIC_CONTROLS = 10
|
| 8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
def build_ui(event_handler_function):
|
| 10 |
ui_components = {}
|
| 11 |
|
| 12 |
with gr.Blocks() as demo:
|
| 13 |
+
gr.Markdown("# ImageGen - FLUX.2-KV")
|
| 14 |
gr.Markdown(
|
| 15 |
+
"This demo is a streamlined version of the [Comfy web UI](https://github.com/RioShiina47/comfy-webui)'s [ImageGen](https://huggingface.co/spaces/RioShiina/ImageGen) functionality. "
|
| 16 |
"Other versions are also available: "
|
|
|
|
|
|
|
| 17 |
"[Anima](https://huggingface.co/spaces/RioShiina/ImageGen-Anima), "
|
| 18 |
+
"[Illustrious](https://huggingface.co/spaces/RioShiina/ImageGen-Illustrious), "
|
| 19 |
"[NoobAI](https://huggingface.co/spaces/RioShiina/ImageGen-NoobAI), "
|
| 20 |
+
"[Pony](https://huggingface.co/spaces/RioShiina/ImageGen-Pony)"
|
|
|
|
| 21 |
)
|
| 22 |
with gr.Tabs(elem_id="tabs_container") as tabs:
|
| 23 |
+
with gr.TabItem("Txt2Img", id=0):
|
| 24 |
+
ui_components.update(txt2img_ui.create_ui())
|
| 25 |
+
|
| 26 |
+
with gr.TabItem("Img2Img", id=1):
|
| 27 |
+
ui_components.update(img2img_ui.create_ui())
|
|
|
|
|
|
|
| 28 |
|
| 29 |
+
with gr.TabItem("Inpaint", id=2):
|
| 30 |
+
ui_components.update(inpaint_ui.create_ui())
|
| 31 |
|
| 32 |
+
with gr.TabItem("Outpaint", id=3):
|
| 33 |
+
ui_components.update(outpaint_ui.create_ui())
|
| 34 |
|
| 35 |
+
with gr.TabItem("Hires. Fix", id=4):
|
| 36 |
+
ui_components.update(hires_fix_ui.create_ui())
|
|
|
|
|
|
|
| 37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
ui_components["tabs"] = tabs
|
| 39 |
+
ui_components["image_gen_tabs"] = tabs
|
| 40 |
|
| 41 |
gr.Markdown("<div style='text-align: center; margin-top: 20px;'>Made by RioShiina with ❤️<br><a href='https://github.com/RioShiina47' target='_blank'>GitHub</a> | <a href='https://huggingface.co/RioShiina' target='_blank'>Hugging Face</a> | <a href='https://civitai.com/user/RioShiina' target='_blank'>Civitai</a></div>")
|
| 42 |
|
ui/shared/hires_fix_ui.py
CHANGED
|
@@ -3,8 +3,10 @@ from core.settings import MODEL_MAP_CHECKPOINT
|
|
| 3 |
from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
|
| 4 |
from .ui_components import (
|
| 5 |
create_lora_settings_ui,
|
| 6 |
-
create_embedding_ui,
|
| 7 |
-
create_conditioning_ui, create_vae_override_ui,
|
|
|
|
|
|
|
| 8 |
create_reference_latent_ui
|
| 9 |
)
|
| 10 |
|
|
@@ -13,12 +15,16 @@ def create_ui():
|
|
| 13 |
components = {}
|
| 14 |
|
| 15 |
with gr.Column():
|
|
|
|
|
|
|
| 16 |
with gr.Row():
|
|
|
|
| 17 |
components[f'base_model_{prefix}'] = gr.Dropdown(
|
| 18 |
label="Base Model",
|
| 19 |
choices=list(MODEL_MAP_CHECKPOINT.keys()),
|
| 20 |
value=list(MODEL_MAP_CHECKPOINT.keys())[0],
|
| 21 |
-
scale=3
|
|
|
|
| 22 |
)
|
| 23 |
with gr.Column(scale=1):
|
| 24 |
components[f'run_{prefix}'] = gr.Button("Run Hires. Fix", variant="primary")
|
|
@@ -27,8 +33,8 @@ def create_ui():
|
|
| 27 |
with gr.Column(scale=1):
|
| 28 |
components[f'input_image_{prefix}'] = gr.Image(type="pil", label="Input Image", height=255)
|
| 29 |
with gr.Column(scale=2):
|
| 30 |
-
components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3
|
| 31 |
-
components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3
|
| 32 |
|
| 33 |
with gr.Row():
|
| 34 |
with gr.Column(scale=1):
|
|
@@ -46,31 +52,35 @@ def create_ui():
|
|
| 46 |
components[f'denoise_{prefix}'] = gr.Slider(label="Denoise Strength", minimum=0.0, maximum=1.0, step=0.01, value=0.55)
|
| 47 |
|
| 48 |
with gr.Row():
|
| 49 |
-
components[f'sampler_{prefix}'] = gr.Dropdown(label="Sampler", choices=SAMPLER_CHOICES, value=
|
| 50 |
-
components[f'scheduler_{prefix}'] = gr.Dropdown(label="Scheduler", choices=SCHEDULER_CHOICES, value=
|
| 51 |
with gr.Row():
|
| 52 |
-
components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=
|
| 53 |
-
components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=
|
| 54 |
with gr.Row():
|
| 55 |
components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
|
| 56 |
components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
|
| 57 |
with gr.Row():
|
| 58 |
-
components[f'
|
|
|
|
|
|
|
| 59 |
|
| 60 |
-
components[f'clip_skip_{prefix}'] = gr.State(value=1)
|
| 61 |
components[f'width_{prefix}'] = gr.State(value=512)
|
| 62 |
components[f'height_{prefix}'] = gr.State(value=512)
|
| 63 |
|
| 64 |
with gr.Column(scale=1):
|
| 65 |
components[f'result_{prefix}'] = gr.Gallery(label="Result", show_label=False, columns=1, object_fit="contain", height=610)
|
| 66 |
|
| 67 |
-
|
| 68 |
components.update(create_lora_settings_ui(prefix))
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
components.update(
|
|
|
|
|
|
|
| 73 |
components.update(create_conditioning_ui(prefix))
|
| 74 |
-
|
|
|
|
| 75 |
|
| 76 |
return components
|
|
|
|
| 3 |
from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
|
| 4 |
from .ui_components import (
|
| 5 |
create_lora_settings_ui,
|
| 6 |
+
create_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
|
| 7 |
+
create_conditioning_ui, create_vae_override_ui,
|
| 8 |
+
create_model_architecture_filter_ui, create_category_filter_ui,
|
| 9 |
+
create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
|
| 10 |
create_reference_latent_ui
|
| 11 |
)
|
| 12 |
|
|
|
|
| 15 |
components = {}
|
| 16 |
|
| 17 |
with gr.Column():
|
| 18 |
+
components.update(create_model_architecture_filter_ui(prefix))
|
| 19 |
+
|
| 20 |
with gr.Row():
|
| 21 |
+
components.update(create_category_filter_ui(prefix))
|
| 22 |
components[f'base_model_{prefix}'] = gr.Dropdown(
|
| 23 |
label="Base Model",
|
| 24 |
choices=list(MODEL_MAP_CHECKPOINT.keys()),
|
| 25 |
value=list(MODEL_MAP_CHECKPOINT.keys())[0],
|
| 26 |
+
scale=3,
|
| 27 |
+
allow_custom_value=True
|
| 28 |
)
|
| 29 |
with gr.Column(scale=1):
|
| 30 |
components[f'run_{prefix}'] = gr.Button("Run Hires. Fix", variant="primary")
|
|
|
|
| 33 |
with gr.Column(scale=1):
|
| 34 |
components[f'input_image_{prefix}'] = gr.Image(type="pil", label="Input Image", height=255)
|
| 35 |
with gr.Column(scale=2):
|
| 36 |
+
components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3)
|
| 37 |
+
components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3)
|
| 38 |
|
| 39 |
with gr.Row():
|
| 40 |
with gr.Column(scale=1):
|
|
|
|
| 52 |
components[f'denoise_{prefix}'] = gr.Slider(label="Denoise Strength", minimum=0.0, maximum=1.0, step=0.01, value=0.55)
|
| 53 |
|
| 54 |
with gr.Row():
|
| 55 |
+
components[f'sampler_{prefix}'] = gr.Dropdown(label="Sampler", choices=SAMPLER_CHOICES, value=SAMPLER_CHOICES[0])
|
| 56 |
+
components[f'scheduler_{prefix}'] = gr.Dropdown(label="Scheduler", choices=SCHEDULER_CHOICES, value='normal' if 'normal' in SCHEDULER_CHOICES else SCHEDULER_CHOICES[0])
|
| 57 |
with gr.Row():
|
| 58 |
+
components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=28)
|
| 59 |
+
components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=7.5)
|
| 60 |
with gr.Row():
|
| 61 |
components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
|
| 62 |
components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
|
| 63 |
with gr.Row():
|
| 64 |
+
components[f'clip_skip_{prefix}'] = gr.Slider(label="Clip Skip", minimum=1, maximum=2, step=1, value=1, visible=False, interactive=True)
|
| 65 |
+
components[f'guidance_{prefix}'] = gr.Slider(label="Guidance (FLUX)", minimum=1.0, maximum=10.0, step=0.1, value=3.5, visible=False, interactive=True)
|
| 66 |
+
components[f'zero_gpu_{prefix}'] = gr.Number(label="ZeroGPU Duration (s)", value=None, placeholder="Default: 60s, Max: 120s", info="Optional: Set how long to reserve the GPU.")
|
| 67 |
|
|
|
|
| 68 |
components[f'width_{prefix}'] = gr.State(value=512)
|
| 69 |
components[f'height_{prefix}'] = gr.State(value=512)
|
| 70 |
|
| 71 |
with gr.Column(scale=1):
|
| 72 |
components[f'result_{prefix}'] = gr.Gallery(label="Result", show_label=False, columns=1, object_fit="contain", height=610)
|
| 73 |
|
| 74 |
+
|
| 75 |
components.update(create_lora_settings_ui(prefix))
|
| 76 |
+
components.update(create_controlnet_ui(prefix))
|
| 77 |
+
components.update(create_ipadapter_ui(prefix))
|
| 78 |
+
components.update(create_flux1_ipadapter_ui(prefix))
|
| 79 |
+
components.update(create_sd3_ipadapter_ui(prefix))
|
| 80 |
+
components.update(create_style_ui(prefix))
|
| 81 |
+
components.update(create_embedding_ui(prefix))
|
| 82 |
components.update(create_conditioning_ui(prefix))
|
| 83 |
+
components.update(create_reference_latent_ui(prefix))
|
| 84 |
+
components.update(create_vae_override_ui(prefix))
|
| 85 |
|
| 86 |
return components
|
ui/shared/img2img_ui.py
CHANGED
|
@@ -3,8 +3,10 @@ from core.settings import MODEL_MAP_CHECKPOINT
|
|
| 3 |
from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
|
| 4 |
from .ui_components import (
|
| 5 |
create_lora_settings_ui,
|
| 6 |
-
create_embedding_ui,
|
| 7 |
-
create_conditioning_ui, create_vae_override_ui,
|
|
|
|
|
|
|
| 8 |
create_reference_latent_ui
|
| 9 |
)
|
| 10 |
|
|
@@ -13,8 +15,11 @@ def create_ui():
|
|
| 13 |
components = {}
|
| 14 |
|
| 15 |
with gr.Column():
|
|
|
|
|
|
|
| 16 |
with gr.Row():
|
| 17 |
-
components
|
|
|
|
| 18 |
with gr.Column(scale=1):
|
| 19 |
components[f'run_{prefix}'] = gr.Button("Run", variant="primary")
|
| 20 |
|
|
@@ -23,37 +28,41 @@ def create_ui():
|
|
| 23 |
components[f'input_image_{prefix}'] = gr.Image(type="pil", label="Input Image", height=255)
|
| 24 |
|
| 25 |
with gr.Column(scale=2):
|
| 26 |
-
components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3
|
| 27 |
-
components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3
|
| 28 |
|
| 29 |
with gr.Row():
|
| 30 |
with gr.Column(scale=1):
|
| 31 |
components[f'denoise_{prefix}'] = gr.Slider(label="Denoise Strength", minimum=0.0, maximum=1.0, step=0.01, value=0.7)
|
| 32 |
|
| 33 |
with gr.Row():
|
| 34 |
-
components[f'sampler_{prefix}'] = gr.Dropdown(label="Sampler", choices=SAMPLER_CHOICES, value=
|
| 35 |
-
components[f'scheduler_{prefix}'] = gr.Dropdown(label="Scheduler", choices=SCHEDULER_CHOICES, value=
|
| 36 |
with gr.Row():
|
| 37 |
-
components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=
|
| 38 |
-
components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=
|
| 39 |
with gr.Row():
|
| 40 |
components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
|
| 41 |
components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
|
| 42 |
with gr.Row():
|
| 43 |
-
components[f'
|
| 44 |
-
|
| 45 |
-
|
| 46 |
|
| 47 |
with gr.Column(scale=1):
|
| 48 |
components[f'result_{prefix}'] = gr.Gallery(label="Result", show_label=False, columns=1, object_fit="contain", height=505)
|
| 49 |
|
| 50 |
-
|
| 51 |
components.update(create_lora_settings_ui(prefix))
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
components.update(
|
|
|
|
|
|
|
|
|
|
| 56 |
components.update(create_conditioning_ui(prefix))
|
| 57 |
-
|
|
|
|
| 58 |
|
| 59 |
return components
|
|
|
|
| 3 |
from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
|
| 4 |
from .ui_components import (
|
| 5 |
create_lora_settings_ui,
|
| 6 |
+
create_controlnet_ui, create_diffsynth_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
|
| 7 |
+
create_conditioning_ui, create_vae_override_ui,
|
| 8 |
+
create_model_architecture_filter_ui, create_category_filter_ui,
|
| 9 |
+
create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
|
| 10 |
create_reference_latent_ui
|
| 11 |
)
|
| 12 |
|
|
|
|
| 15 |
components = {}
|
| 16 |
|
| 17 |
with gr.Column():
|
| 18 |
+
components.update(create_model_architecture_filter_ui(prefix))
|
| 19 |
+
|
| 20 |
with gr.Row():
|
| 21 |
+
components.update(create_category_filter_ui(prefix))
|
| 22 |
+
components[f'base_model_{prefix}'] = gr.Dropdown(label="Base Model", choices=list(MODEL_MAP_CHECKPOINT.keys()), value=list(MODEL_MAP_CHECKPOINT.keys())[0], scale=3, allow_custom_value=True)
|
| 23 |
with gr.Column(scale=1):
|
| 24 |
components[f'run_{prefix}'] = gr.Button("Run", variant="primary")
|
| 25 |
|
|
|
|
| 28 |
components[f'input_image_{prefix}'] = gr.Image(type="pil", label="Input Image", height=255)
|
| 29 |
|
| 30 |
with gr.Column(scale=2):
|
| 31 |
+
components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3)
|
| 32 |
+
components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3)
|
| 33 |
|
| 34 |
with gr.Row():
|
| 35 |
with gr.Column(scale=1):
|
| 36 |
components[f'denoise_{prefix}'] = gr.Slider(label="Denoise Strength", minimum=0.0, maximum=1.0, step=0.01, value=0.7)
|
| 37 |
|
| 38 |
with gr.Row():
|
| 39 |
+
components[f'sampler_{prefix}'] = gr.Dropdown(label="Sampler", choices=SAMPLER_CHOICES, value=SAMPLER_CHOICES[0])
|
| 40 |
+
components[f'scheduler_{prefix}'] = gr.Dropdown(label="Scheduler", choices=SCHEDULER_CHOICES, value='normal' if 'normal' in SCHEDULER_CHOICES else SCHEDULER_CHOICES[0])
|
| 41 |
with gr.Row():
|
| 42 |
+
components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=28)
|
| 43 |
+
components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=7.5)
|
| 44 |
with gr.Row():
|
| 45 |
components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
|
| 46 |
components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
|
| 47 |
with gr.Row():
|
| 48 |
+
components[f'clip_skip_{prefix}'] = gr.Slider(label="Clip Skip", minimum=1, maximum=2, step=1, value=1, visible=False, interactive=True)
|
| 49 |
+
components[f'guidance_{prefix}'] = gr.Slider(label="Guidance (FLUX)", minimum=1.0, maximum=10.0, step=0.1, value=3.5, visible=False, interactive=True)
|
| 50 |
+
components[f'zero_gpu_{prefix}'] = gr.Number(label="ZeroGPU Duration (s)", value=None, placeholder="Default: 60s, Max: 120s", info="Optional: Set how long to reserve the GPU. Longer jobs may need more time.")
|
| 51 |
|
| 52 |
with gr.Column(scale=1):
|
| 53 |
components[f'result_{prefix}'] = gr.Gallery(label="Result", show_label=False, columns=1, object_fit="contain", height=505)
|
| 54 |
|
| 55 |
+
|
| 56 |
components.update(create_lora_settings_ui(prefix))
|
| 57 |
+
components.update(create_controlnet_ui(prefix))
|
| 58 |
+
components.update(create_diffsynth_controlnet_ui(prefix))
|
| 59 |
+
components.update(create_ipadapter_ui(prefix))
|
| 60 |
+
components.update(create_flux1_ipadapter_ui(prefix))
|
| 61 |
+
components.update(create_sd3_ipadapter_ui(prefix))
|
| 62 |
+
components.update(create_embedding_ui(prefix))
|
| 63 |
+
components.update(create_style_ui(prefix))
|
| 64 |
components.update(create_conditioning_ui(prefix))
|
| 65 |
+
components.update(create_reference_latent_ui(prefix))
|
| 66 |
+
components.update(create_vae_override_ui(prefix))
|
| 67 |
|
| 68 |
return components
|
ui/shared/inpaint_ui.py
CHANGED
|
@@ -2,8 +2,10 @@ import gradio as gr
|
|
| 2 |
from core.settings import MODEL_MAP_CHECKPOINT
|
| 3 |
from .ui_components import (
|
| 4 |
create_base_parameter_ui, create_lora_settings_ui,
|
| 5 |
-
create_embedding_ui,
|
| 6 |
-
create_conditioning_ui, create_vae_override_ui,
|
|
|
|
|
|
|
| 7 |
create_reference_latent_ui
|
| 8 |
)
|
| 9 |
|
|
@@ -12,17 +14,22 @@ def create_ui():
|
|
| 12 |
components = {}
|
| 13 |
|
| 14 |
with gr.Column():
|
|
|
|
|
|
|
|
|
|
| 15 |
with gr.Row() as model_and_run_row:
|
|
|
|
| 16 |
components[f'base_model_{prefix}'] = gr.Dropdown(
|
| 17 |
label="Base Model",
|
| 18 |
choices=list(MODEL_MAP_CHECKPOINT.keys()),
|
| 19 |
value=list(MODEL_MAP_CHECKPOINT.keys())[0],
|
| 20 |
-
scale=3
|
|
|
|
| 21 |
)
|
| 22 |
with gr.Column(scale=1):
|
| 23 |
components[f'run_{prefix}'] = gr.Button("Run Inpaint", variant="primary")
|
| 24 |
|
| 25 |
-
components[f'model_and_run_row_{prefix}'] = model_and_run_row
|
| 26 |
|
| 27 |
with gr.Row() as main_content_row:
|
| 28 |
with gr.Column(scale=1) as editor_column:
|
|
@@ -40,44 +47,55 @@ def create_ui():
|
|
| 40 |
components[f'editor_column_{prefix}'] = editor_column
|
| 41 |
|
| 42 |
with gr.Column(scale=2) as prompts_column:
|
| 43 |
-
components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=6
|
| 44 |
-
components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=6
|
| 45 |
components[f'prompts_column_{prefix}'] = prompts_column
|
| 46 |
|
| 47 |
with gr.Row() as params_and_gallery_row:
|
| 48 |
with gr.Column(scale=1):
|
| 49 |
-
param_defaults = {'w': 1024, 'h': 1024, 'cs_vis': False, 'cs_val': 1}
|
| 50 |
from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
|
| 51 |
with gr.Row():
|
| 52 |
-
components[f'
|
| 53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
with gr.Row():
|
| 55 |
-
components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=
|
| 56 |
-
components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=
|
| 57 |
with gr.Row():
|
| 58 |
components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
|
| 59 |
components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
|
| 60 |
with gr.Row():
|
| 61 |
-
components[f'
|
|
|
|
|
|
|
| 62 |
|
| 63 |
-
components[f'clip_skip_{prefix}'] = gr.State(value=1)
|
| 64 |
components[f'width_{prefix}'] = gr.State(value=512)
|
| 65 |
components[f'height_{prefix}'] = gr.State(value=512)
|
| 66 |
|
| 67 |
with gr.Column(scale=1):
|
| 68 |
-
components[f'result_{prefix}'] = gr.Gallery(label="Result", show_label=False, columns=1, object_fit="contain", height=
|
| 69 |
|
| 70 |
components[f'params_and_gallery_row_{prefix}'] = params_and_gallery_row
|
| 71 |
|
| 72 |
with gr.Column() as accordion_wrapper:
|
| 73 |
-
|
| 74 |
components.update(create_lora_settings_ui(prefix))
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
components.update(
|
|
|
|
|
|
|
|
|
|
| 79 |
components.update(create_conditioning_ui(prefix))
|
| 80 |
-
|
|
|
|
| 81 |
components[f'accordion_wrapper_{prefix}'] = accordion_wrapper
|
| 82 |
|
| 83 |
return components
|
|
|
|
| 2 |
from core.settings import MODEL_MAP_CHECKPOINT
|
| 3 |
from .ui_components import (
|
| 4 |
create_base_parameter_ui, create_lora_settings_ui,
|
| 5 |
+
create_controlnet_ui, create_diffsynth_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
|
| 6 |
+
create_conditioning_ui, create_vae_override_ui,
|
| 7 |
+
create_model_architecture_filter_ui, create_category_filter_ui,
|
| 8 |
+
create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
|
| 9 |
create_reference_latent_ui
|
| 10 |
)
|
| 11 |
|
|
|
|
| 14 |
components = {}
|
| 15 |
|
| 16 |
with gr.Column():
|
| 17 |
+
with gr.Row() as arch_row:
|
| 18 |
+
components.update(create_model_architecture_filter_ui(prefix))
|
| 19 |
+
|
| 20 |
with gr.Row() as model_and_run_row:
|
| 21 |
+
components.update(create_category_filter_ui(prefix))
|
| 22 |
components[f'base_model_{prefix}'] = gr.Dropdown(
|
| 23 |
label="Base Model",
|
| 24 |
choices=list(MODEL_MAP_CHECKPOINT.keys()),
|
| 25 |
value=list(MODEL_MAP_CHECKPOINT.keys())[0],
|
| 26 |
+
scale=3,
|
| 27 |
+
allow_custom_value=True
|
| 28 |
)
|
| 29 |
with gr.Column(scale=1):
|
| 30 |
components[f'run_{prefix}'] = gr.Button("Run Inpaint", variant="primary")
|
| 31 |
|
| 32 |
+
components[f'model_and_run_row_{prefix}'] = [arch_row, model_and_run_row]
|
| 33 |
|
| 34 |
with gr.Row() as main_content_row:
|
| 35 |
with gr.Column(scale=1) as editor_column:
|
|
|
|
| 47 |
components[f'editor_column_{prefix}'] = editor_column
|
| 48 |
|
| 49 |
with gr.Column(scale=2) as prompts_column:
|
| 50 |
+
components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=6)
|
| 51 |
+
components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=6)
|
| 52 |
components[f'prompts_column_{prefix}'] = prompts_column
|
| 53 |
|
| 54 |
with gr.Row() as params_and_gallery_row:
|
| 55 |
with gr.Column(scale=1):
|
|
|
|
| 56 |
from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
|
| 57 |
with gr.Row():
|
| 58 |
+
components[f'denoise_{prefix}'] = gr.Slider(
|
| 59 |
+
label="Denoise", minimum=0.0, maximum=1.0, step=0.05, value=1.0
|
| 60 |
+
)
|
| 61 |
+
components[f'grow_mask_by_{prefix}'] = gr.Slider(
|
| 62 |
+
label="Grow Mask By", minimum=0, maximum=64, step=1, value=6
|
| 63 |
+
)
|
| 64 |
+
with gr.Row():
|
| 65 |
+
components[f'sampler_{prefix}'] = gr.Dropdown(label="Sampler", choices=SAMPLER_CHOICES, value=SAMPLER_CHOICES[0])
|
| 66 |
+
components[f'scheduler_{prefix}'] = gr.Dropdown(label="Scheduler", choices=SCHEDULER_CHOICES, value='normal' if 'normal' in SCHEDULER_CHOICES else SCHEDULER_CHOICES[0])
|
| 67 |
with gr.Row():
|
| 68 |
+
components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=28)
|
| 69 |
+
components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=7.5)
|
| 70 |
with gr.Row():
|
| 71 |
components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
|
| 72 |
components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
|
| 73 |
with gr.Row():
|
| 74 |
+
components[f'clip_skip_{prefix}'] = gr.Slider(label="Clip Skip", minimum=1, maximum=2, step=1, value=1, visible=False, interactive=True)
|
| 75 |
+
components[f'guidance_{prefix}'] = gr.Slider(label="Guidance (FLUX)", minimum=1.0, maximum=10.0, step=0.1, value=3.5, visible=False, interactive=True)
|
| 76 |
+
components[f'zero_gpu_{prefix}'] = gr.Number(label="ZeroGPU Duration (s)", value=None, placeholder="Default: 60s, Max: 120s", info="Optional: Set how long to reserve the GPU.")
|
| 77 |
|
|
|
|
| 78 |
components[f'width_{prefix}'] = gr.State(value=512)
|
| 79 |
components[f'height_{prefix}'] = gr.State(value=512)
|
| 80 |
|
| 81 |
with gr.Column(scale=1):
|
| 82 |
+
components[f'result_{prefix}'] = gr.Gallery(label="Result", show_label=False, columns=1, object_fit="contain", height=510)
|
| 83 |
|
| 84 |
components[f'params_and_gallery_row_{prefix}'] = params_and_gallery_row
|
| 85 |
|
| 86 |
with gr.Column() as accordion_wrapper:
|
| 87 |
+
|
| 88 |
components.update(create_lora_settings_ui(prefix))
|
| 89 |
+
components.update(create_controlnet_ui(prefix))
|
| 90 |
+
components.update(create_diffsynth_controlnet_ui(prefix))
|
| 91 |
+
components.update(create_ipadapter_ui(prefix))
|
| 92 |
+
components.update(create_flux1_ipadapter_ui(prefix))
|
| 93 |
+
components.update(create_sd3_ipadapter_ui(prefix))
|
| 94 |
+
components.update(create_style_ui(prefix))
|
| 95 |
+
components.update(create_embedding_ui(prefix))
|
| 96 |
components.update(create_conditioning_ui(prefix))
|
| 97 |
+
components.update(create_reference_latent_ui(prefix))
|
| 98 |
+
components.update(create_vae_override_ui(prefix))
|
| 99 |
components[f'accordion_wrapper_{prefix}'] = accordion_wrapper
|
| 100 |
|
| 101 |
return components
|
ui/shared/outpaint_ui.py
CHANGED
|
@@ -3,8 +3,10 @@ from core.settings import MODEL_MAP_CHECKPOINT
|
|
| 3 |
from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
|
| 4 |
from .ui_components import (
|
| 5 |
create_lora_settings_ui,
|
| 6 |
-
create_embedding_ui,
|
| 7 |
-
create_conditioning_ui, create_vae_override_ui,
|
|
|
|
|
|
|
| 8 |
create_reference_latent_ui
|
| 9 |
)
|
| 10 |
|
|
@@ -13,12 +15,16 @@ def create_ui():
|
|
| 13 |
components = {}
|
| 14 |
|
| 15 |
with gr.Column():
|
|
|
|
|
|
|
| 16 |
with gr.Row():
|
|
|
|
| 17 |
components[f'base_model_{prefix}'] = gr.Dropdown(
|
| 18 |
label="Base Model",
|
| 19 |
choices=list(MODEL_MAP_CHECKPOINT.keys()),
|
| 20 |
value=list(MODEL_MAP_CHECKPOINT.keys())[0],
|
| 21 |
-
scale=3
|
|
|
|
| 22 |
)
|
| 23 |
with gr.Column(scale=1):
|
| 24 |
components[f'run_{prefix}'] = gr.Button("Run Outpaint", variant="primary")
|
|
@@ -27,44 +33,51 @@ def create_ui():
|
|
| 27 |
with gr.Column(scale=1):
|
| 28 |
components[f'input_image_{prefix}'] = gr.Image(type="pil", label="Input Image", height=255)
|
| 29 |
with gr.Column(scale=2):
|
| 30 |
-
components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3
|
| 31 |
-
components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3
|
| 32 |
|
| 33 |
with gr.Row():
|
| 34 |
with gr.Column(scale=1):
|
| 35 |
with gr.Row():
|
| 36 |
-
components[f'
|
| 37 |
-
components[f'
|
| 38 |
with gr.Row():
|
| 39 |
-
components[f'
|
| 40 |
-
components[f'
|
|
|
|
|
|
|
| 41 |
|
| 42 |
with gr.Row():
|
| 43 |
-
components[f'sampler_{prefix}'] = gr.Dropdown(label="Sampler", choices=SAMPLER_CHOICES, value=
|
| 44 |
-
components[f'scheduler_{prefix}'] = gr.Dropdown(label="Scheduler", choices=SCHEDULER_CHOICES, value=
|
| 45 |
with gr.Row():
|
| 46 |
-
components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=
|
| 47 |
-
components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=
|
| 48 |
with gr.Row():
|
| 49 |
components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
|
| 50 |
components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
|
| 51 |
with gr.Row():
|
| 52 |
-
components[f'
|
|
|
|
|
|
|
| 53 |
|
| 54 |
-
components[f'clip_skip_{prefix}'] = gr.State(value=1)
|
| 55 |
components[f'width_{prefix}'] = gr.State(value=512)
|
| 56 |
components[f'height_{prefix}'] = gr.State(value=512)
|
| 57 |
|
| 58 |
with gr.Column(scale=1):
|
| 59 |
-
components[f'result_{prefix}'] = gr.Gallery(label="Result", show_label=False, columns=1, object_fit="contain", height=
|
| 60 |
|
| 61 |
-
|
| 62 |
components.update(create_lora_settings_ui(prefix))
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
components.update(
|
|
|
|
|
|
|
|
|
|
| 67 |
components.update(create_conditioning_ui(prefix))
|
| 68 |
-
|
|
|
|
| 69 |
|
| 70 |
return components
|
|
|
|
| 3 |
from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
|
| 4 |
from .ui_components import (
|
| 5 |
create_lora_settings_ui,
|
| 6 |
+
create_controlnet_ui, create_diffsynth_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
|
| 7 |
+
create_conditioning_ui, create_vae_override_ui,
|
| 8 |
+
create_model_architecture_filter_ui, create_category_filter_ui,
|
| 9 |
+
create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
|
| 10 |
create_reference_latent_ui
|
| 11 |
)
|
| 12 |
|
|
|
|
| 15 |
components = {}
|
| 16 |
|
| 17 |
with gr.Column():
|
| 18 |
+
components.update(create_model_architecture_filter_ui(prefix))
|
| 19 |
+
|
| 20 |
with gr.Row():
|
| 21 |
+
components.update(create_category_filter_ui(prefix))
|
| 22 |
components[f'base_model_{prefix}'] = gr.Dropdown(
|
| 23 |
label="Base Model",
|
| 24 |
choices=list(MODEL_MAP_CHECKPOINT.keys()),
|
| 25 |
value=list(MODEL_MAP_CHECKPOINT.keys())[0],
|
| 26 |
+
scale=3,
|
| 27 |
+
allow_custom_value=True
|
| 28 |
)
|
| 29 |
with gr.Column(scale=1):
|
| 30 |
components[f'run_{prefix}'] = gr.Button("Run Outpaint", variant="primary")
|
|
|
|
| 33 |
with gr.Column(scale=1):
|
| 34 |
components[f'input_image_{prefix}'] = gr.Image(type="pil", label="Input Image", height=255)
|
| 35 |
with gr.Column(scale=2):
|
| 36 |
+
components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3)
|
| 37 |
+
components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3)
|
| 38 |
|
| 39 |
with gr.Row():
|
| 40 |
with gr.Column(scale=1):
|
| 41 |
with gr.Row():
|
| 42 |
+
components[f'left_{prefix}'] = gr.Slider(label="Pad Left", minimum=0, maximum=512, step=64, value=64)
|
| 43 |
+
components[f'right_{prefix}'] = gr.Slider(label="Pad Right", minimum=0, maximum=512, step=64, value=64)
|
| 44 |
with gr.Row():
|
| 45 |
+
components[f'top_{prefix}'] = gr.Slider(label="Pad Top", minimum=0, maximum=512, step=64, value=64)
|
| 46 |
+
components[f'bottom_{prefix}'] = gr.Slider(label="Pad Bottom", minimum=0, maximum=512, step=64, value=64)
|
| 47 |
+
|
| 48 |
+
components[f'feathering_{prefix}'] = gr.Slider(label="Feathering / Grow Mask", minimum=0, maximum=100, step=1, value=10)
|
| 49 |
|
| 50 |
with gr.Row():
|
| 51 |
+
components[f'sampler_{prefix}'] = gr.Dropdown(label="Sampler", choices=SAMPLER_CHOICES, value=SAMPLER_CHOICES[0])
|
| 52 |
+
components[f'scheduler_{prefix}'] = gr.Dropdown(label="Scheduler", choices=SCHEDULER_CHOICES, value='normal' if 'normal' in SCHEDULER_CHOICES else SCHEDULER_CHOICES[0])
|
| 53 |
with gr.Row():
|
| 54 |
+
components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=28)
|
| 55 |
+
components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=7.5)
|
| 56 |
with gr.Row():
|
| 57 |
components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
|
| 58 |
components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
|
| 59 |
with gr.Row():
|
| 60 |
+
components[f'clip_skip_{prefix}'] = gr.Slider(label="Clip Skip", minimum=1, maximum=2, step=1, value=1, visible=False, interactive=True)
|
| 61 |
+
components[f'guidance_{prefix}'] = gr.Slider(label="Guidance (FLUX)", minimum=1.0, maximum=10.0, step=0.1, value=3.5, visible=False, interactive=True)
|
| 62 |
+
components[f'zero_gpu_{prefix}'] = gr.Number(label="ZeroGPU Duration (s)", value=None, placeholder="Default: 60s, Max: 120s", info="Optional: Set how long to reserve the GPU.")
|
| 63 |
|
|
|
|
| 64 |
components[f'width_{prefix}'] = gr.State(value=512)
|
| 65 |
components[f'height_{prefix}'] = gr.State(value=512)
|
| 66 |
|
| 67 |
with gr.Column(scale=1):
|
| 68 |
+
components[f'result_{prefix}'] = gr.Gallery(label="Result", show_label=False, columns=1, object_fit="contain", height=685)
|
| 69 |
|
| 70 |
+
|
| 71 |
components.update(create_lora_settings_ui(prefix))
|
| 72 |
+
components.update(create_controlnet_ui(prefix))
|
| 73 |
+
components.update(create_diffsynth_controlnet_ui(prefix))
|
| 74 |
+
components.update(create_ipadapter_ui(prefix))
|
| 75 |
+
components.update(create_flux1_ipadapter_ui(prefix))
|
| 76 |
+
components.update(create_sd3_ipadapter_ui(prefix))
|
| 77 |
+
components.update(create_style_ui(prefix))
|
| 78 |
+
components.update(create_embedding_ui(prefix))
|
| 79 |
components.update(create_conditioning_ui(prefix))
|
| 80 |
+
components.update(create_reference_latent_ui(prefix))
|
| 81 |
+
components.update(create_vae_override_ui(prefix))
|
| 82 |
|
| 83 |
return components
|
ui/shared/txt2img_ui.py
CHANGED
|
@@ -2,8 +2,10 @@ import gradio as gr
|
|
| 2 |
from core.settings import MODEL_MAP_CHECKPOINT
|
| 3 |
from .ui_components import (
|
| 4 |
create_base_parameter_ui, create_lora_settings_ui,
|
| 5 |
-
create_embedding_ui,
|
| 6 |
-
create_conditioning_ui, create_vae_override_ui,
|
|
|
|
|
|
|
| 7 |
create_reference_latent_ui
|
| 8 |
)
|
| 9 |
|
|
@@ -13,13 +15,22 @@ def create_ui():
|
|
| 13 |
components = {}
|
| 14 |
|
| 15 |
with gr.Column():
|
|
|
|
|
|
|
| 16 |
with gr.Row():
|
| 17 |
-
components
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
with gr.Column(scale=1):
|
| 19 |
components[f'run_{prefix}'] = gr.Button("Run", variant="primary")
|
| 20 |
|
| 21 |
-
components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3
|
| 22 |
-
components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3
|
| 23 |
|
| 24 |
with gr.Row():
|
| 25 |
with gr.Column(scale=1):
|
|
@@ -28,13 +39,17 @@ def create_ui():
|
|
| 28 |
with gr.Column(scale=1):
|
| 29 |
components[f'result_{prefix}'] = gr.Gallery(label="Result", show_label=False, columns=2, object_fit="contain", height=627)
|
| 30 |
|
| 31 |
-
|
| 32 |
components.update(create_lora_settings_ui(prefix))
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
components.update(
|
|
|
|
|
|
|
|
|
|
| 37 |
components.update(create_conditioning_ui(prefix))
|
| 38 |
-
|
|
|
|
| 39 |
|
| 40 |
return components
|
|
|
|
| 2 |
from core.settings import MODEL_MAP_CHECKPOINT
|
| 3 |
from .ui_components import (
|
| 4 |
create_base_parameter_ui, create_lora_settings_ui,
|
| 5 |
+
create_controlnet_ui, create_diffsynth_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
|
| 6 |
+
create_conditioning_ui, create_vae_override_ui,
|
| 7 |
+
create_model_architecture_filter_ui, create_category_filter_ui,
|
| 8 |
+
create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
|
| 9 |
create_reference_latent_ui
|
| 10 |
)
|
| 11 |
|
|
|
|
| 15 |
components = {}
|
| 16 |
|
| 17 |
with gr.Column():
|
| 18 |
+
components.update(create_model_architecture_filter_ui(prefix))
|
| 19 |
+
|
| 20 |
with gr.Row():
|
| 21 |
+
components.update(create_category_filter_ui(prefix))
|
| 22 |
+
components[f'base_model_{prefix}'] = gr.Dropdown(
|
| 23 |
+
label="Base Model",
|
| 24 |
+
choices=list(MODEL_MAP_CHECKPOINT.keys()),
|
| 25 |
+
value=list(MODEL_MAP_CHECKPOINT.keys())[0],
|
| 26 |
+
scale=3,
|
| 27 |
+
allow_custom_value=True
|
| 28 |
+
)
|
| 29 |
with gr.Column(scale=1):
|
| 30 |
components[f'run_{prefix}'] = gr.Button("Run", variant="primary")
|
| 31 |
|
| 32 |
+
components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3)
|
| 33 |
+
components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3)
|
| 34 |
|
| 35 |
with gr.Row():
|
| 36 |
with gr.Column(scale=1):
|
|
|
|
| 39 |
with gr.Column(scale=1):
|
| 40 |
components[f'result_{prefix}'] = gr.Gallery(label="Result", show_label=False, columns=2, object_fit="contain", height=627)
|
| 41 |
|
| 42 |
+
|
| 43 |
components.update(create_lora_settings_ui(prefix))
|
| 44 |
+
components.update(create_controlnet_ui(prefix))
|
| 45 |
+
components.update(create_diffsynth_controlnet_ui(prefix))
|
| 46 |
+
components.update(create_ipadapter_ui(prefix))
|
| 47 |
+
components.update(create_flux1_ipadapter_ui(prefix))
|
| 48 |
+
components.update(create_sd3_ipadapter_ui(prefix))
|
| 49 |
+
components.update(create_embedding_ui(prefix))
|
| 50 |
+
components.update(create_style_ui(prefix))
|
| 51 |
components.update(create_conditioning_ui(prefix))
|
| 52 |
+
components.update(create_reference_latent_ui(prefix))
|
| 53 |
+
components.update(create_vae_override_ui(prefix))
|
| 54 |
|
| 55 |
return components
|
ui/shared/ui_components.py
CHANGED
|
@@ -2,12 +2,74 @@ import gradio as gr
|
|
| 2 |
from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
|
| 3 |
from core.settings import (
|
| 4 |
MAX_LORAS, LORA_SOURCE_CHOICES, MAX_EMBEDDINGS, MAX_CONDITIONINGS,
|
| 5 |
-
MAX_CONTROLNETS, RESOLUTION_MAP,
|
|
|
|
| 6 |
)
|
| 7 |
import yaml
|
| 8 |
import os
|
| 9 |
from functools import lru_cache
|
| 10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
def create_base_parameter_ui(prefix, defaults=None):
|
| 12 |
if defaults is None:
|
| 13 |
defaults = {}
|
|
@@ -17,50 +79,37 @@ def create_base_parameter_ui(prefix, defaults=None):
|
|
| 17 |
with gr.Row():
|
| 18 |
components[f'aspect_ratio_{prefix}'] = gr.Dropdown(
|
| 19 |
label="Aspect Ratio",
|
| 20 |
-
choices=list(RESOLUTION_MAP
|
| 21 |
value="1:1 (Square)",
|
| 22 |
-
interactive=True
|
|
|
|
| 23 |
)
|
| 24 |
with gr.Row():
|
| 25 |
components[f'width_{prefix}'] = gr.Number(label="Width", value=defaults.get('w', 1024), interactive=True)
|
| 26 |
components[f'height_{prefix}'] = gr.Number(label="Height", value=defaults.get('h', 1024), interactive=True)
|
| 27 |
with gr.Row():
|
| 28 |
-
components[f'sampler_{prefix}'] = gr.Dropdown(label="Sampler", choices=SAMPLER_CHOICES, value=
|
| 29 |
-
components[f'scheduler_{prefix}'] = gr.Dropdown(label="Scheduler", choices=SCHEDULER_CHOICES, value=
|
| 30 |
with gr.Row():
|
| 31 |
-
components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=
|
| 32 |
-
components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=
|
| 33 |
with gr.Row():
|
| 34 |
components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
|
| 35 |
components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
|
| 36 |
with gr.Row():
|
| 37 |
-
components[f'
|
| 38 |
-
|
| 39 |
-
|
| 40 |
|
| 41 |
return components
|
| 42 |
|
| 43 |
|
| 44 |
-
def create_api_key_ui(prefix: str):
|
| 45 |
-
components = {}
|
| 46 |
-
with gr.Accordion("API Key Settings", open=False) as api_key_accordion:
|
| 47 |
-
components[f'api_key_accordion_{prefix}'] = api_key_accordion
|
| 48 |
-
gr.Markdown("💡 **Tip:** Enter API key (optional). An API key is required for resources that need a login to download. The key will be used for all Civitai downloads on this tab. You can also manually upload the corresponding files to avoid API Key leakage caused by potential vulnerabilities.")
|
| 49 |
-
with gr.Row():
|
| 50 |
-
components[f'civitai_api_key_{prefix}'] = gr.Textbox(
|
| 51 |
-
label="Civitai API Key",
|
| 52 |
-
type="password",
|
| 53 |
-
placeholder="Enter your Civitai API key here (optional)"
|
| 54 |
-
)
|
| 55 |
-
return components
|
| 56 |
-
|
| 57 |
-
|
| 58 |
def create_lora_settings_ui(prefix: str):
|
| 59 |
components = {}
|
| 60 |
|
| 61 |
lora_rows, lora_sources, lora_ids, lora_scales, lora_uploads = [], [], [], [], []
|
| 62 |
|
| 63 |
-
with gr.Accordion("LoRA Settings", open=False) as lora_accordion:
|
| 64 |
components[f'lora_accordion_{prefix}'] = lora_accordion
|
| 65 |
gr.Markdown("💡 **Tip:** When downloading from Civitai, please use the **Version ID**, not the Model ID. You can find the Version ID in the URL (e.g., `civitai.com/models/123?modelVersionId=456`) or under the model's download button.")
|
| 66 |
components[f'lora_count_state_{prefix}'] = gr.State(1)
|
|
@@ -69,7 +118,7 @@ def create_lora_settings_ui(prefix: str):
|
|
| 69 |
with gr.Row(visible=i==0) as row:
|
| 70 |
source = gr.Dropdown(label=f"LoRA Source {i+1}", choices=LORA_SOURCE_CHOICES, value=LORA_SOURCE_CHOICES[0], scale=1)
|
| 71 |
lora_id = gr.Textbox(label=f"Civitai Version ID / File", placeholder="Civitai Version ID or Filename", scale=2, type="text")
|
| 72 |
-
scale = gr.Slider(label=f"Scale", minimum=
|
| 73 |
upload = gr.UploadButton(label="Upload", file_types=[".safetensors"], scale=1)
|
| 74 |
|
| 75 |
lora_rows.append(row)
|
|
@@ -95,11 +144,273 @@ def create_lora_settings_ui(prefix: str):
|
|
| 95 |
|
| 96 |
return components
|
| 97 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
def create_embedding_ui(prefix: str):
|
| 99 |
components = {}
|
| 100 |
key = lambda name: f"{name}_{prefix}"
|
| 101 |
|
| 102 |
-
with gr.Accordion("Embedding Settings", open=False, visible=
|
| 103 |
components[key('embedding_accordion')] = accordion
|
| 104 |
gr.Markdown("💡 **Tip:** Embeddings are automatically added to your prompt using `embedding:filename` syntax. When downloading from Civitai, please use the **Version ID**, not the Model ID. You can find the Version ID in the URL (e.g., `civitai.com/models/123?modelVersionId=456`) or under the model's download button. For instance, using the Version ID `456` from the example above would automatically append `embedding:civitai_456` to your positive prompt.")
|
| 105 |
|
|
@@ -137,7 +448,7 @@ def create_conditioning_ui(prefix: str):
|
|
| 137 |
components = {}
|
| 138 |
key = lambda name: f"{name}_{prefix}"
|
| 139 |
|
| 140 |
-
with gr.Accordion("Conditioning Settings", open=False) as accordion:
|
| 141 |
components[key('conditioning_accordion')] = accordion
|
| 142 |
gr.Markdown("💡 **Tip:** Define rectangular areas and assign specific prompts to them. Coordinates (X, Y) start from the top-left corner.")
|
| 143 |
|
|
@@ -173,35 +484,6 @@ def create_conditioning_ui(prefix: str):
|
|
| 173 |
|
| 174 |
return components
|
| 175 |
|
| 176 |
-
def create_reference_latent_ui(prefix: str):
|
| 177 |
-
components = {}
|
| 178 |
-
key = lambda name: f"{name}_{prefix}"
|
| 179 |
-
|
| 180 |
-
with gr.Accordion("Reference Edit", open=False) as accordion:
|
| 181 |
-
components[key('reference_latent_accordion')] = accordion
|
| 182 |
-
gr.Markdown("💡 **Tip:** For multimodal models (like FLUX.2), this feature enables powerful editing and combining capabilities. In txt2img mode, adding a single reference image performs an **Image Edit**, while adding multiple images performs an **Image Combine**.")
|
| 183 |
-
|
| 184 |
-
ref_rows, ref_images = [], []
|
| 185 |
-
components.update({
|
| 186 |
-
key('reference_latent_rows'): ref_rows,
|
| 187 |
-
key('reference_latent_images'): ref_images,
|
| 188 |
-
})
|
| 189 |
-
|
| 190 |
-
with gr.Row():
|
| 191 |
-
for i in range(MAX_REFERENCE_LATENTS):
|
| 192 |
-
with gr.Column(visible=(i < 1), min_width=160) as row_wrapper:
|
| 193 |
-
ref_images.append(gr.Image(type="pil", label=f"Reference {i+1}", sources=["upload"], height=150))
|
| 194 |
-
ref_rows.append(row_wrapper)
|
| 195 |
-
|
| 196 |
-
with gr.Row():
|
| 197 |
-
components[key('add_reference_latent_button')] = gr.Button("✚ Add Reference Image")
|
| 198 |
-
components[key('delete_reference_latent_button')] = gr.Button("➖ Delete Reference Image", visible=False)
|
| 199 |
-
components[key('reference_latent_count_state')] = gr.State(1)
|
| 200 |
-
|
| 201 |
-
components[key('all_reference_latent_components_flat')] = ref_images
|
| 202 |
-
|
| 203 |
-
return components
|
| 204 |
-
|
| 205 |
def create_vae_override_ui(prefix: str):
|
| 206 |
components = {}
|
| 207 |
key = lambda name: f"{name}_{prefix}"
|
|
@@ -233,4 +515,33 @@ def create_vae_override_ui(prefix: str):
|
|
| 233 |
components[key('vae_upload_button')] = upload_btn
|
| 234 |
components[key('vae_file')] = gr.State(None)
|
| 235 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 236 |
return components
|
|
|
|
| 2 |
from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
|
| 3 |
from core.settings import (
|
| 4 |
MAX_LORAS, LORA_SOURCE_CHOICES, MAX_EMBEDDINGS, MAX_CONDITIONINGS,
|
| 5 |
+
MAX_CONTROLNETS, MAX_IPADAPTERS, RESOLUTION_MAP, ARCHITECTURES_CONFIG,
|
| 6 |
+
MODEL_MAP_CHECKPOINT, MODEL_TYPE_MAP, FEATURES_CONFIG, ARCH_CATEGORIES_MAP
|
| 7 |
)
|
| 8 |
import yaml
|
| 9 |
import os
|
| 10 |
from functools import lru_cache
|
| 11 |
|
| 12 |
+
default_model_name = list(MODEL_MAP_CHECKPOINT.keys())[0] if MODEL_MAP_CHECKPOINT else None
|
| 13 |
+
default_m_type = MODEL_TYPE_MAP.get(default_model_name, "SDXL") if default_model_name else "SDXL"
|
| 14 |
+
default_architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
|
| 15 |
+
default_arch_model_type = default_architectures_dict.get(default_m_type, {}).get("model_type", default_m_type.lower().replace(" ", "").replace(".", ""))
|
| 16 |
+
default_arch_features = FEATURES_CONFIG.get(default_arch_model_type, FEATURES_CONFIG.get('default', {}))
|
| 17 |
+
default_enabled_chains = default_arch_features.get('enabled_chains', [])
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
@lru_cache(maxsize=1)
|
| 21 |
+
def get_ipadapter_config_from_yaml():
|
| 22 |
+
try:
|
| 23 |
+
_PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
| 24 |
+
_IPADAPTER_LIST_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'ipadapter.yaml')
|
| 25 |
+
with open(_IPADAPTER_LIST_PATH, 'r', encoding='utf-8') as f:
|
| 26 |
+
config = yaml.safe_load(f)
|
| 27 |
+
return config
|
| 28 |
+
except Exception as e:
|
| 29 |
+
print(f"Warning: Could not load ipadapter.yaml for UI components: {e}")
|
| 30 |
+
return {}
|
| 31 |
+
|
| 32 |
+
def get_ipadapter_presets(arch="SDXL"):
|
| 33 |
+
config = get_ipadapter_config_from_yaml()
|
| 34 |
+
presets = []
|
| 35 |
+
if config:
|
| 36 |
+
std_presets = config.get("IPAdapter_presets", {}).get(arch, [])
|
| 37 |
+
face_presets = config.get("IPAdapter_FaceID_presets", {}).get(arch, [])
|
| 38 |
+
if std_presets:
|
| 39 |
+
presets.extend(std_presets)
|
| 40 |
+
if face_presets:
|
| 41 |
+
presets.extend(face_presets)
|
| 42 |
+
return presets if presets else ["STANDARD (medium strength)"]
|
| 43 |
+
|
| 44 |
+
def create_model_architecture_filter_ui(prefix):
|
| 45 |
+
components = {}
|
| 46 |
+
ordered_architectures = ARCHITECTURES_CONFIG.get("architecture_order", [])
|
| 47 |
+
choices = ["ALL"] + ordered_architectures
|
| 48 |
+
|
| 49 |
+
components[f'model_arch_{prefix}'] = gr.Radio(
|
| 50 |
+
label="Model Architecture",
|
| 51 |
+
choices=choices,
|
| 52 |
+
value="ALL",
|
| 53 |
+
interactive=True,
|
| 54 |
+
visible=False
|
| 55 |
+
)
|
| 56 |
+
return components
|
| 57 |
+
|
| 58 |
+
def create_category_filter_ui(prefix):
|
| 59 |
+
valid_cats = list(set(cat for cats in ARCH_CATEGORIES_MAP.values() for cat in cats))
|
| 60 |
+
cat_choices = ["ALL"] + sorted(valid_cats)
|
| 61 |
+
|
| 62 |
+
components = {}
|
| 63 |
+
components[f'model_cat_{prefix}'] = gr.Dropdown(
|
| 64 |
+
label="Filter Models",
|
| 65 |
+
choices=cat_choices,
|
| 66 |
+
value="ALL",
|
| 67 |
+
interactive=True,
|
| 68 |
+
scale=1,
|
| 69 |
+
allow_custom_value=True
|
| 70 |
+
)
|
| 71 |
+
return components
|
| 72 |
+
|
| 73 |
def create_base_parameter_ui(prefix, defaults=None):
|
| 74 |
if defaults is None:
|
| 75 |
defaults = {}
|
|
|
|
| 79 |
with gr.Row():
|
| 80 |
components[f'aspect_ratio_{prefix}'] = gr.Dropdown(
|
| 81 |
label="Aspect Ratio",
|
| 82 |
+
choices=list(RESOLUTION_MAP.get('sdxl', {}).keys()),
|
| 83 |
value="1:1 (Square)",
|
| 84 |
+
interactive=True,
|
| 85 |
+
allow_custom_value=True
|
| 86 |
)
|
| 87 |
with gr.Row():
|
| 88 |
components[f'width_{prefix}'] = gr.Number(label="Width", value=defaults.get('w', 1024), interactive=True)
|
| 89 |
components[f'height_{prefix}'] = gr.Number(label="Height", value=defaults.get('h', 1024), interactive=True)
|
| 90 |
with gr.Row():
|
| 91 |
+
components[f'sampler_{prefix}'] = gr.Dropdown(label="Sampler", choices=SAMPLER_CHOICES, value=SAMPLER_CHOICES[0])
|
| 92 |
+
components[f'scheduler_{prefix}'] = gr.Dropdown(label="Scheduler", choices=SCHEDULER_CHOICES, value='normal' if 'normal' in SCHEDULER_CHOICES else SCHEDULER_CHOICES[0])
|
| 93 |
with gr.Row():
|
| 94 |
+
components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=28)
|
| 95 |
+
components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=7.5)
|
| 96 |
with gr.Row():
|
| 97 |
components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
|
| 98 |
components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
|
| 99 |
with gr.Row():
|
| 100 |
+
components[f'clip_skip_{prefix}'] = gr.Slider(label="Clip Skip", minimum=1, maximum=2, step=1, value=1, visible=False, interactive=True)
|
| 101 |
+
components[f'guidance_{prefix}'] = gr.Slider(label="Guidance (FLUX)", minimum=1.0, maximum=10.0, step=0.1, value=3.5, visible=False, interactive=True)
|
| 102 |
+
components[f'zero_gpu_{prefix}'] = gr.Number(label="ZeroGPU Duration (s)", value=None, placeholder="Default: 60s, Max: 120s", info="Optional: Set how long to reserve the GPU.")
|
| 103 |
|
| 104 |
return components
|
| 105 |
|
| 106 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
def create_lora_settings_ui(prefix: str):
|
| 108 |
components = {}
|
| 109 |
|
| 110 |
lora_rows, lora_sources, lora_ids, lora_scales, lora_uploads = [], [], [], [], []
|
| 111 |
|
| 112 |
+
with gr.Accordion("LoRA Settings", open=False, visible=('lora' in default_enabled_chains)) as lora_accordion:
|
| 113 |
components[f'lora_accordion_{prefix}'] = lora_accordion
|
| 114 |
gr.Markdown("💡 **Tip:** When downloading from Civitai, please use the **Version ID**, not the Model ID. You can find the Version ID in the URL (e.g., `civitai.com/models/123?modelVersionId=456`) or under the model's download button.")
|
| 115 |
components[f'lora_count_state_{prefix}'] = gr.State(1)
|
|
|
|
| 118 |
with gr.Row(visible=i==0) as row:
|
| 119 |
source = gr.Dropdown(label=f"LoRA Source {i+1}", choices=LORA_SOURCE_CHOICES, value=LORA_SOURCE_CHOICES[0], scale=1)
|
| 120 |
lora_id = gr.Textbox(label=f"Civitai Version ID / File", placeholder="Civitai Version ID or Filename", scale=2, type="text")
|
| 121 |
+
scale = gr.Slider(label=f"Scale", minimum=0.0, maximum=2.0, step=0.05, value=0.8, scale=1)
|
| 122 |
upload = gr.UploadButton(label="Upload", file_types=[".safetensors"], scale=1)
|
| 123 |
|
| 124 |
lora_rows.append(row)
|
|
|
|
| 144 |
|
| 145 |
return components
|
| 146 |
|
| 147 |
+
def create_controlnet_ui(prefix: str, max_units=MAX_CONTROLNETS):
|
| 148 |
+
components = {}
|
| 149 |
+
key = lambda name: f"{name}_{prefix}"
|
| 150 |
+
|
| 151 |
+
with gr.Accordion("ControlNet Settings", open=False, visible=('controlnet' in default_enabled_chains)) as accordion:
|
| 152 |
+
components[key('controlnet_accordion')] = accordion
|
| 153 |
+
|
| 154 |
+
cn_rows, images, series, types, strengths, filepaths = [], [], [], [], [], []
|
| 155 |
+
components.update({
|
| 156 |
+
key('controlnet_rows'): cn_rows,
|
| 157 |
+
key('controlnet_images'): images,
|
| 158 |
+
key('controlnet_series'): series,
|
| 159 |
+
key('controlnet_types'): types,
|
| 160 |
+
key('controlnet_strengths'): strengths,
|
| 161 |
+
key('controlnet_filepaths'): filepaths
|
| 162 |
+
})
|
| 163 |
+
|
| 164 |
+
for i in range(max_units):
|
| 165 |
+
with gr.Row(visible=(i < 1)) as row:
|
| 166 |
+
with gr.Column(scale=1):
|
| 167 |
+
images.append(gr.Image(label=f"Control Image {i+1}", type="pil", sources=["upload"], height=256))
|
| 168 |
+
with gr.Column(scale=2):
|
| 169 |
+
types.append(gr.Dropdown(label="Type", choices=[], interactive=True, allow_custom_value=True))
|
| 170 |
+
series.append(gr.Dropdown(label="Series", choices=[], interactive=True, allow_custom_value=True))
|
| 171 |
+
strengths.append(gr.Slider(label="Strength", minimum=0.0, maximum=2.0, step=0.05, value=1.0, interactive=True))
|
| 172 |
+
filepaths.append(gr.State(None))
|
| 173 |
+
cn_rows.append(row)
|
| 174 |
+
|
| 175 |
+
with gr.Row():
|
| 176 |
+
components[key('add_controlnet_button')] = gr.Button("✚ Add ControlNet")
|
| 177 |
+
components[key('delete_controlnet_button')] = gr.Button("➖ Delete ControlNet", visible=False)
|
| 178 |
+
components[key('controlnet_count_state')] = gr.State(1)
|
| 179 |
+
|
| 180 |
+
all_cn_components_flat = []
|
| 181 |
+
for i in range(max_units):
|
| 182 |
+
all_cn_components_flat.extend([
|
| 183 |
+
images[i], types[i], series[i], strengths[i], filepaths[i]
|
| 184 |
+
])
|
| 185 |
+
components[key('all_controlnet_components_flat')] = all_cn_components_flat
|
| 186 |
+
|
| 187 |
+
return components
|
| 188 |
+
|
| 189 |
+
def create_diffsynth_controlnet_ui(prefix: str, max_units=MAX_CONTROLNETS):
|
| 190 |
+
components = {}
|
| 191 |
+
key = lambda name: f"{name}_{prefix}"
|
| 192 |
+
|
| 193 |
+
with gr.Accordion("DiffSynth ControlNet Settings", open=False, visible=('controlnet_model_patch' in default_enabled_chains)) as accordion:
|
| 194 |
+
components[key('diffsynth_controlnet_accordion')] = accordion
|
| 195 |
+
|
| 196 |
+
cn_rows, images, series, types, strengths, filepaths = [], [], [], [], [], []
|
| 197 |
+
components.update({
|
| 198 |
+
key('diffsynth_controlnet_rows'): cn_rows,
|
| 199 |
+
key('diffsynth_controlnet_images'): images,
|
| 200 |
+
key('diffsynth_controlnet_series'): series,
|
| 201 |
+
key('diffsynth_controlnet_types'): types,
|
| 202 |
+
key('diffsynth_controlnet_strengths'): strengths,
|
| 203 |
+
key('diffsynth_controlnet_filepaths'): filepaths
|
| 204 |
+
})
|
| 205 |
+
|
| 206 |
+
for i in range(max_units):
|
| 207 |
+
with gr.Row(visible=(i < 1)) as row:
|
| 208 |
+
with gr.Column(scale=1):
|
| 209 |
+
images.append(gr.Image(label=f"Control Image {i+1}", type="pil", sources=["upload"], height=256))
|
| 210 |
+
with gr.Column(scale=2):
|
| 211 |
+
types.append(gr.Dropdown(label="Type", choices=[], interactive=True, allow_custom_value=True))
|
| 212 |
+
series.append(gr.Dropdown(label="Series", choices=[], interactive=True, allow_custom_value=True))
|
| 213 |
+
strengths.append(gr.Slider(label="Strength", minimum=0.0, maximum=2.0, step=0.05, value=1.0, interactive=True))
|
| 214 |
+
filepaths.append(gr.State(None))
|
| 215 |
+
cn_rows.append(row)
|
| 216 |
+
|
| 217 |
+
with gr.Row():
|
| 218 |
+
components[key('add_diffsynth_controlnet_button')] = gr.Button("✚ Add DiffSynth ControlNet")
|
| 219 |
+
components[key('delete_diffsynth_controlnet_button')] = gr.Button("➖ Delete DiffSynth ControlNet", visible=False)
|
| 220 |
+
components[key('diffsynth_controlnet_count_state')] = gr.State(1)
|
| 221 |
+
|
| 222 |
+
all_cn_components_flat = []
|
| 223 |
+
for i in range(max_units):
|
| 224 |
+
all_cn_components_flat.extend([
|
| 225 |
+
images[i], types[i], series[i], strengths[i], filepaths[i]
|
| 226 |
+
])
|
| 227 |
+
components[key('all_diffsynth_controlnet_components_flat')] = all_cn_components_flat
|
| 228 |
+
|
| 229 |
+
return components
|
| 230 |
+
|
| 231 |
+
def create_ipadapter_ui(prefix: str, max_units=MAX_IPADAPTERS):
|
| 232 |
+
components = {}
|
| 233 |
+
key = lambda name: f"{name}_{prefix}"
|
| 234 |
+
|
| 235 |
+
sdxl_presets = get_ipadapter_presets("SDXL")
|
| 236 |
+
default_preset = sdxl_presets[0] if sdxl_presets else None
|
| 237 |
+
|
| 238 |
+
with gr.Accordion("IPAdapter Settings", open=False, visible=('ipadapter' in default_enabled_chains)) as accordion:
|
| 239 |
+
components[key('ipadapter_accordion')] = accordion
|
| 240 |
+
gr.Markdown("Powered by [cubiq/ComfyUI_IPAdapter_plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus).")
|
| 241 |
+
|
| 242 |
+
with gr.Row():
|
| 243 |
+
components[key('ipadapter_final_preset')] = gr.Dropdown(
|
| 244 |
+
label="Preset (for all images)",
|
| 245 |
+
choices=sdxl_presets,
|
| 246 |
+
value=default_preset,
|
| 247 |
+
interactive=True,
|
| 248 |
+
allow_custom_value=True
|
| 249 |
+
)
|
| 250 |
+
components[key('ipadapter_embeds_scaling')] = gr.Dropdown(
|
| 251 |
+
label="Embeds Scaling",
|
| 252 |
+
choices=['V only', 'K+V', 'K+V w/ C penalty', 'K+mean(V) w/ C penalty'],
|
| 253 |
+
value='V only',
|
| 254 |
+
interactive=True
|
| 255 |
+
)
|
| 256 |
+
|
| 257 |
+
with gr.Row():
|
| 258 |
+
components[key('ipadapter_combine_method')] = gr.Dropdown(
|
| 259 |
+
label="Combine Method",
|
| 260 |
+
choices=["concat", "add", "subtract", "average", "norm average", "max", "min"],
|
| 261 |
+
value="concat",
|
| 262 |
+
interactive=True
|
| 263 |
+
)
|
| 264 |
+
components[key('ipadapter_final_weight')] = gr.Slider(label="Final Weight", minimum=0.0, maximum=2.0, step=0.05, value=1.0, interactive=True)
|
| 265 |
+
components[key('ipadapter_final_lora_strength')] = gr.Slider(label="Final LoRA Strength", minimum=0.0, maximum=2.0, step=0.05, value=0.6, interactive=True, visible=False)
|
| 266 |
+
|
| 267 |
+
gr.Markdown("---")
|
| 268 |
+
|
| 269 |
+
ipa_rows, images, weights, lora_strengths = [], [], [], []
|
| 270 |
+
components.update({
|
| 271 |
+
key('ipadapter_rows'): ipa_rows,
|
| 272 |
+
key('ipadapter_images'): images,
|
| 273 |
+
key('ipadapter_weights'): weights,
|
| 274 |
+
key('ipadapter_lora_strengths'): lora_strengths
|
| 275 |
+
})
|
| 276 |
+
|
| 277 |
+
for i in range(max_units):
|
| 278 |
+
with gr.Row(visible=(i < 1)) as row:
|
| 279 |
+
with gr.Column(scale=1):
|
| 280 |
+
images.append(gr.Image(label=f"IPAdapter Image {i+1}", type="pil", sources=["upload"], height=256))
|
| 281 |
+
with gr.Column(scale=2):
|
| 282 |
+
weights.append(gr.Slider(label="Weight", minimum=0.0, maximum=2.0, step=0.05, value=1.0, interactive=True))
|
| 283 |
+
lora_strengths.append(gr.Slider(label="LoRA Strength", minimum=0.0, maximum=2.0, step=0.05, value=0.6, interactive=True, visible=False))
|
| 284 |
+
ipa_rows.append(row)
|
| 285 |
+
|
| 286 |
+
with gr.Row():
|
| 287 |
+
components[key('add_ipadapter_button')] = gr.Button("✚ Add IPAdapter")
|
| 288 |
+
components[key('delete_ipadapter_button')] = gr.Button("➖ Delete IPAdapter", visible=False)
|
| 289 |
+
components[key('ipadapter_count_state')] = gr.State(1)
|
| 290 |
+
|
| 291 |
+
all_ipa_components_flat = images + weights + lora_strengths
|
| 292 |
+
all_ipa_components_flat += [
|
| 293 |
+
components[key('ipadapter_final_preset')],
|
| 294 |
+
components[key('ipadapter_final_weight')],
|
| 295 |
+
components[key('ipadapter_final_lora_strength')],
|
| 296 |
+
components[key('ipadapter_embeds_scaling')],
|
| 297 |
+
components[key('ipadapter_combine_method')],
|
| 298 |
+
]
|
| 299 |
+
components[key('all_ipadapter_components_flat')] = all_ipa_components_flat
|
| 300 |
+
|
| 301 |
+
return components
|
| 302 |
+
|
| 303 |
+
def create_flux1_ipadapter_ui(prefix: str, max_units=MAX_IPADAPTERS):
|
| 304 |
+
components = {}
|
| 305 |
+
key = lambda name: f"{name}_{prefix}"
|
| 306 |
+
|
| 307 |
+
with gr.Accordion("IPAdapter Settings (FLUX.1)", open=False, visible=('flux1_ipadapter' in default_enabled_chains)) as accordion:
|
| 308 |
+
components[key('flux1_ipadapter_accordion')] = accordion
|
| 309 |
+
|
| 310 |
+
ipa_rows, images, weights, start_percents, end_percents = [], [], [], [], []
|
| 311 |
+
components.update({
|
| 312 |
+
key('flux1_ipadapter_rows'): ipa_rows,
|
| 313 |
+
key('flux1_ipadapter_images'): images,
|
| 314 |
+
key('flux1_ipadapter_weights'): weights,
|
| 315 |
+
key('flux1_ipadapter_start_percents'): start_percents,
|
| 316 |
+
key('flux1_ipadapter_end_percents'): end_percents,
|
| 317 |
+
})
|
| 318 |
+
|
| 319 |
+
for i in range(max_units):
|
| 320 |
+
with gr.Row(visible=(i < 1)) as row:
|
| 321 |
+
with gr.Column(scale=1):
|
| 322 |
+
images.append(gr.Image(label=f"IPAdapter Image {i+1}", type="pil", sources=["upload"], height=256))
|
| 323 |
+
with gr.Column(scale=2):
|
| 324 |
+
weights.append(gr.Slider(label="Weight", minimum=0.0, maximum=2.0, step=0.05, value=0.6, interactive=True))
|
| 325 |
+
with gr.Row():
|
| 326 |
+
start_percents.append(gr.Slider(label="Start At", minimum=0.0, maximum=1.0, step=0.01, value=0.0, interactive=True))
|
| 327 |
+
end_percents.append(gr.Slider(label="End At", minimum=0.0, maximum=1.0, step=0.01, value=0.6, interactive=True))
|
| 328 |
+
ipa_rows.append(row)
|
| 329 |
+
|
| 330 |
+
with gr.Row():
|
| 331 |
+
components[key('add_flux1_ipadapter_button')] = gr.Button("✚ Add IPAdapter (FLUX)")
|
| 332 |
+
components[key('delete_flux1_ipadapter_button')] = gr.Button("➖ Delete IPAdapter (FLUX)", visible=False)
|
| 333 |
+
components[key('flux1_ipadapter_count_state')] = gr.State(1)
|
| 334 |
+
|
| 335 |
+
all_flux1_ipa_components_flat = images + weights + start_percents + end_percents
|
| 336 |
+
components[key('all_flux1_ipadapter_components_flat')] = all_flux1_ipa_components_flat
|
| 337 |
+
|
| 338 |
+
return components
|
| 339 |
+
|
| 340 |
+
def create_sd3_ipadapter_ui(prefix: str, max_units=MAX_IPADAPTERS):
|
| 341 |
+
components = {}
|
| 342 |
+
key = lambda name: f"{name}_{prefix}"
|
| 343 |
+
|
| 344 |
+
with gr.Accordion("IPAdapter Settings (SD3)", open=False, visible=('sd3_ipadapter' in default_enabled_chains)) as accordion:
|
| 345 |
+
components[key('sd3_ipadapter_accordion')] = accordion
|
| 346 |
+
|
| 347 |
+
ipa_rows, images, weights, start_percents, end_percents = [], [], [], [], []
|
| 348 |
+
components.update({
|
| 349 |
+
key('sd3_ipadapter_rows'): ipa_rows,
|
| 350 |
+
key('sd3_ipadapter_images'): images,
|
| 351 |
+
key('sd3_ipadapter_weights'): weights,
|
| 352 |
+
key('sd3_ipadapter_start_percents'): start_percents,
|
| 353 |
+
key('sd3_ipadapter_end_percents'): end_percents,
|
| 354 |
+
})
|
| 355 |
+
|
| 356 |
+
for i in range(max_units):
|
| 357 |
+
with gr.Row(visible=(i < 1)) as row:
|
| 358 |
+
with gr.Column(scale=1):
|
| 359 |
+
images.append(gr.Image(label=f"IPAdapter Image {i+1}", type="pil", sources=["upload"], height=256))
|
| 360 |
+
with gr.Column(scale=2):
|
| 361 |
+
weights.append(gr.Slider(label="Weight", minimum=0.0, maximum=2.0, step=0.05, value=0.5, interactive=True))
|
| 362 |
+
with gr.Row():
|
| 363 |
+
start_percents.append(gr.Slider(label="Start At", minimum=0.0, maximum=1.0, step=0.01, value=0.0, interactive=True))
|
| 364 |
+
end_percents.append(gr.Slider(label="End At", minimum=0.0, maximum=1.0, step=0.01, value=1.0, interactive=True))
|
| 365 |
+
ipa_rows.append(row)
|
| 366 |
+
|
| 367 |
+
with gr.Row():
|
| 368 |
+
components[key('add_sd3_ipadapter_button')] = gr.Button("✚ Add IPAdapter (SD3)")
|
| 369 |
+
components[key('delete_sd3_ipadapter_button')] = gr.Button("➖ Delete IPAdapter (SD3)", visible=False)
|
| 370 |
+
components[key('sd3_ipadapter_count_state')] = gr.State(1)
|
| 371 |
+
|
| 372 |
+
all_sd3_ipa_components_flat = images + weights + start_percents + end_percents
|
| 373 |
+
components[key('all_sd3_ipadapter_components_flat')] = all_sd3_ipa_components_flat
|
| 374 |
+
|
| 375 |
+
return components
|
| 376 |
+
|
| 377 |
+
def create_style_ui(prefix: str):
|
| 378 |
+
components = {}
|
| 379 |
+
key = lambda name: f"{name}_{prefix}"
|
| 380 |
+
|
| 381 |
+
with gr.Accordion("Style Settings (FLUX.1)", open=False, visible=('style' in default_enabled_chains)) as accordion:
|
| 382 |
+
components[key('style_accordion')] = accordion
|
| 383 |
+
|
| 384 |
+
style_rows, images, strengths = [], [], []
|
| 385 |
+
components.update({
|
| 386 |
+
key('style_rows'): style_rows,
|
| 387 |
+
key('style_images'): images,
|
| 388 |
+
key('style_strengths'): strengths
|
| 389 |
+
})
|
| 390 |
+
|
| 391 |
+
for i in range(5):
|
| 392 |
+
with gr.Row(visible=(i < 1)) as row:
|
| 393 |
+
with gr.Column(scale=1):
|
| 394 |
+
images.append(gr.Image(label=f"Style Image {i+1}", type="pil", sources=["upload"], height=256))
|
| 395 |
+
with gr.Column(scale=2):
|
| 396 |
+
strengths.append(gr.Slider(label="Strength", minimum=0.0, maximum=2.0, step=0.05, value=1.0, interactive=True))
|
| 397 |
+
style_rows.append(row)
|
| 398 |
+
|
| 399 |
+
with gr.Row():
|
| 400 |
+
components[key('add_style_button')] = gr.Button("✚ Add Style (FLUX)")
|
| 401 |
+
components[key('delete_style_button')] = gr.Button("➖ Delete Style (FLUX)", visible=False)
|
| 402 |
+
components[key('style_count_state')] = gr.State(1)
|
| 403 |
+
|
| 404 |
+
all_style_components_flat = images + strengths
|
| 405 |
+
components[key('all_style_components_flat')] = all_style_components_flat
|
| 406 |
+
|
| 407 |
+
return components
|
| 408 |
+
|
| 409 |
def create_embedding_ui(prefix: str):
|
| 410 |
components = {}
|
| 411 |
key = lambda name: f"{name}_{prefix}"
|
| 412 |
|
| 413 |
+
with gr.Accordion("Embedding Settings", open=False, visible=('embedding' in default_enabled_chains)) as accordion:
|
| 414 |
components[key('embedding_accordion')] = accordion
|
| 415 |
gr.Markdown("💡 **Tip:** Embeddings are automatically added to your prompt using `embedding:filename` syntax. When downloading from Civitai, please use the **Version ID**, not the Model ID. You can find the Version ID in the URL (e.g., `civitai.com/models/123?modelVersionId=456`) or under the model's download button. For instance, using the Version ID `456` from the example above would automatically append `embedding:civitai_456` to your positive prompt.")
|
| 416 |
|
|
|
|
| 448 |
components = {}
|
| 449 |
key = lambda name: f"{name}_{prefix}"
|
| 450 |
|
| 451 |
+
with gr.Accordion("Conditioning Settings", open=False, visible=('conditioning' in default_enabled_chains)) as accordion:
|
| 452 |
components[key('conditioning_accordion')] = accordion
|
| 453 |
gr.Markdown("💡 **Tip:** Define rectangular areas and assign specific prompts to them. Coordinates (X, Y) start from the top-left corner.")
|
| 454 |
|
|
|
|
| 484 |
|
| 485 |
return components
|
| 486 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 487 |
def create_vae_override_ui(prefix: str):
|
| 488 |
components = {}
|
| 489 |
key = lambda name: f"{name}_{prefix}"
|
|
|
|
| 515 |
components[key('vae_upload_button')] = upload_btn
|
| 516 |
components[key('vae_file')] = gr.State(None)
|
| 517 |
|
| 518 |
+
return components
|
| 519 |
+
|
| 520 |
+
def create_reference_latent_ui(prefix: str, max_units=10):
|
| 521 |
+
components = {}
|
| 522 |
+
key = lambda name: f"{name}_{prefix}"
|
| 523 |
+
|
| 524 |
+
with gr.Accordion("Reference Edit Settings", open=False, visible=('reference_latent' in default_enabled_chains)) as ref_accordion:
|
| 525 |
+
components[key('reference_latent_accordion')] = ref_accordion
|
| 526 |
+
gr.Markdown("💡 **Tip:** For multimodal models (like FLUX.2 or OmniGen), this feature enables powerful editing and combining capabilities. In txt2img mode, adding a single reference image performs an **Image Edit**, while adding multiple images performs an **Image Combine**.")
|
| 527 |
+
|
| 528 |
+
ref_image_groups = []
|
| 529 |
+
ref_image_inputs = []
|
| 530 |
+
with gr.Row():
|
| 531 |
+
for i in range(max_units):
|
| 532 |
+
with gr.Column(visible=(i < 1), min_width=160) as img_col:
|
| 533 |
+
img_comp = gr.Image(type="pil", label=f"Ref. {i+1}", sources=["upload"], height=150)
|
| 534 |
+
ref_image_groups.append(img_col)
|
| 535 |
+
ref_image_inputs.append(img_comp)
|
| 536 |
+
|
| 537 |
+
components[key('reference_latent_rows')] = ref_image_groups
|
| 538 |
+
components[key('reference_latent_images')] = ref_image_inputs
|
| 539 |
+
|
| 540 |
+
with gr.Row():
|
| 541 |
+
components[key('add_reference_latent_button')] = gr.Button("✚ Add Reference Image")
|
| 542 |
+
components[key('delete_reference_latent_button')] = gr.Button("➖ Delete Reference Image", visible=False)
|
| 543 |
+
components[key('reference_latent_count_state')] = gr.State(1)
|
| 544 |
+
|
| 545 |
+
components[key('all_reference_latent_components_flat')] = ref_image_inputs
|
| 546 |
+
|
| 547 |
return components
|
utils/app_utils.py
CHANGED
|
@@ -11,16 +11,38 @@ from huggingface_hub import hf_hub_download, constants as hf_constants
|
|
| 11 |
import torch
|
| 12 |
import numpy as np
|
| 13 |
from PIL import Image, ImageChops
|
| 14 |
-
|
| 15 |
|
| 16 |
from core.settings import *
|
| 17 |
|
| 18 |
DISK_LIMIT_GB = 120
|
| 19 |
MODELS_ROOT_DIR = "ComfyUI/models"
|
| 20 |
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
def save_uploaded_file_with_hash(file_obj: gr.File, target_dir: str) -> str:
|
| 26 |
if not file_obj:
|
|
@@ -48,7 +70,6 @@ def save_uploaded_file_with_hash(file_obj: gr.File, target_dir: str) -> str:
|
|
| 48 |
|
| 49 |
return hashed_filename
|
| 50 |
|
| 51 |
-
|
| 52 |
def bytes_to_gb(byte_size: int) -> float:
|
| 53 |
if byte_size is None or byte_size == 0:
|
| 54 |
return 0.0
|
|
@@ -116,7 +137,6 @@ def enforce_disk_limit():
|
|
| 116 |
except Exception as e:
|
| 117 |
print(f"--- [Storage Manager] An unexpected error occurred: {e} ---")
|
| 118 |
|
| 119 |
-
|
| 120 |
def get_value_at_index(obj: Union[Sequence, Mapping], index: int) -> Any:
|
| 121 |
try:
|
| 122 |
return obj[index]
|
|
@@ -151,7 +171,6 @@ def sanitize_filename(filename: str) -> str:
|
|
| 151 |
sanitized = re.sub(r'[^\w\.\-]', '_', sanitized)
|
| 152 |
return sanitized.lstrip('/\\')
|
| 153 |
|
| 154 |
-
|
| 155 |
def get_civitai_file_info(version_id: str) -> dict | None:
|
| 156 |
api_url = f"https://civitai.com/api/v1/model-versions/{version_id}"
|
| 157 |
try:
|
|
@@ -168,7 +187,6 @@ def get_civitai_file_info(version_id: str) -> dict | None:
|
|
| 168 |
except Exception:
|
| 169 |
return None
|
| 170 |
|
| 171 |
-
|
| 172 |
def download_file(url: str, save_path: str, api_key: str = None, progress=None, desc: str = "") -> str:
|
| 173 |
enforce_disk_limit()
|
| 174 |
|
|
@@ -197,7 +215,6 @@ def download_file(url: str, save_path: str, api_key: str = None, progress=None,
|
|
| 197 |
os.remove(save_path)
|
| 198 |
return f"Download failed for {os.path.basename(save_path)}: {e}"
|
| 199 |
|
| 200 |
-
|
| 201 |
def get_lora_path(source: str, id_or_url: str, civitai_key: str, progress) -> tuple[str | None, str]:
|
| 202 |
if not id_or_url or not id_or_url.strip():
|
| 203 |
return None, "No ID/URL provided."
|
|
@@ -301,47 +318,44 @@ def get_vae_path(source: str, id_or_url: str, civitai_key: str, progress) -> tup
|
|
| 301 |
return (local_path, status) if "Successfully" in status else (None, status)
|
| 302 |
|
| 303 |
|
| 304 |
-
def _ensure_model_downloaded(
|
| 305 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 306 |
if not download_info:
|
| 307 |
-
raise gr.Error(f"Model
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
"text_encoders": TEXT_ENCODERS_DIR,
|
| 312 |
-
"vae": VAE_DIR,
|
| 313 |
-
"checkpoints": CHECKPOINT_DIR,
|
| 314 |
-
"loras": LORA_DIR,
|
| 315 |
-
"controlnet": CONTROLNET_DIR,
|
| 316 |
-
"model_patches": MODEL_PATCHES_DIR,
|
| 317 |
-
"clip_vision": os.path.join(os.path.dirname(LORA_DIR), "clip_vision")
|
| 318 |
-
}
|
| 319 |
|
| 320 |
-
category = download_info.get('category')
|
| 321 |
-
dest_dir = category_to_dir_map.get(category)
|
| 322 |
if not dest_dir:
|
| 323 |
-
raise ValueError(f"Unknown
|
| 324 |
|
| 325 |
-
dest_path = os.path.join(dest_dir,
|
| 326 |
|
| 327 |
if os.path.lexists(dest_path):
|
| 328 |
if not os.path.exists(dest_path):
|
| 329 |
print(f"⚠️ Found and removed broken symlink: {dest_path}")
|
| 330 |
os.remove(dest_path)
|
| 331 |
else:
|
| 332 |
-
return
|
| 333 |
|
| 334 |
source = download_info.get("source")
|
| 335 |
try:
|
| 336 |
-
progress(0, desc=f"Downloading: {
|
| 337 |
|
| 338 |
if source == "hf":
|
| 339 |
repo_id = download_info.get("repo_id")
|
| 340 |
-
hf_filename = download_info.get("repository_file_path",
|
| 341 |
if not repo_id:
|
| 342 |
-
raise ValueError(f"repo_id is missing for HF model '{
|
| 343 |
|
| 344 |
-
cached_path = hf_hub_download(repo_id=repo_id, filename=hf_filename)
|
| 345 |
os.makedirs(dest_dir, exist_ok=True)
|
| 346 |
os.symlink(cached_path, dest_path)
|
| 347 |
print(f"✅ Symlinked '{cached_path}' to '{dest_path}'")
|
|
@@ -349,98 +363,168 @@ def _ensure_model_downloaded(filename: str, progress=gr.Progress()):
|
|
| 349 |
elif source == "civitai":
|
| 350 |
model_version_id = download_info.get("model_version_id")
|
| 351 |
if not model_version_id:
|
| 352 |
-
raise ValueError(f"model_version_id is missing for Civitai model '{
|
| 353 |
|
| 354 |
file_info = get_civitai_file_info(model_version_id)
|
| 355 |
if not file_info or not file_info.get('downloadUrl'):
|
| 356 |
raise ConnectionError(f"Could not get download URL for Civitai model version ID {model_version_id}")
|
| 357 |
|
| 358 |
status = download_file(
|
| 359 |
-
file_info['downloadUrl'], dest_path, progress=progress, desc=f"Downloading: {
|
| 360 |
)
|
| 361 |
if "Failed" in status:
|
| 362 |
raise ConnectionError(status)
|
| 363 |
else:
|
| 364 |
-
raise NotImplementedError(f"Download source '{source}' is not implemented for '{
|
| 365 |
|
| 366 |
-
progress(1.0, desc=f"Downloaded: {
|
| 367 |
|
| 368 |
except Exception as e:
|
| 369 |
if os.path.lexists(dest_path):
|
| 370 |
try:
|
| 371 |
os.remove(dest_path)
|
| 372 |
except OSError: pass
|
| 373 |
-
raise gr.Error(f"Failed to download and link '{
|
| 374 |
|
| 375 |
-
return
|
| 376 |
|
| 377 |
def ensure_controlnet_model_downloaded(filename: str, progress):
|
| 378 |
if not filename or filename == "None":
|
| 379 |
return
|
| 380 |
-
_ensure_model_downloaded(filename, progress)
|
| 381 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 382 |
|
| 383 |
-
def build_preprocessor_model_map():
|
| 384 |
-
global PREPROCESSOR_MODEL_MAP
|
| 385 |
-
if PREPROCESSOR_MODEL_MAP is not None: return PREPROCESSOR_MODEL_MAP
|
| 386 |
-
print("--- Building ControlNet Preprocessor model map ---")
|
| 387 |
-
manual_map = {
|
| 388 |
-
"dwpose": [("yzd-v/DWPose", "yolox_l.onnx"), ("yzd-v/DWPose", "dw-ll_ucoco_384.onnx"), ("hr16/UnJIT-DWPose", "dw-ll_ucoco.onnx"), ("hr16/DWPose-TorchScript-BatchSize5", "dw-ll_ucoco_384_bs5.torchscript.pt"), ("hr16/DWPose-TorchScript-BatchSize5", "rtmpose-m_ap10k_256_bs5.torchscript.pt"), ("hr16/yolo-nas-fp16", "yolo_nas_l_fp16.onnx"), ("hr16/yolo-nas-fp16", "yolo_nas_m_fp16.onnx"), ("hr16/yolo-nas-fp16", "yolo_nas_s_fp16.onnx")],
|
| 389 |
-
"densepose": [("LayerNorm/DensePose-TorchScript-with-hint-image", "densepose_r50_fpn_dl.torchscript"), ("LayerNorm/DensePose-TorchScript-with-hint-image", "densepose_r101_fpn_dl.torchscript")]
|
| 390 |
-
}
|
| 391 |
-
temp_map = {}
|
| 392 |
-
from nodes import NODE_DISPLAY_NAME_MAPPINGS
|
| 393 |
-
wrappers_dir = Path("./custom_nodes/comfyui_controlnet_aux/node_wrappers/")
|
| 394 |
-
if not wrappers_dir.exists():
|
| 395 |
-
print("⚠️ ControlNet AUX wrappers directory not found. Cannot build model map.")
|
| 396 |
-
PREPROCESSOR_MODEL_MAP = {}; return PREPROCESSOR_MODEL_MAP
|
| 397 |
-
for wrapper_file in wrappers_dir.glob("*.py"):
|
| 398 |
-
if wrapper_file.name == "__init__.py": continue
|
| 399 |
-
with open(wrapper_file, 'r', encoding='utf-8') as f:
|
| 400 |
-
content = f.read()
|
| 401 |
-
display_name_matches = re.findall(r'NODE_DISPLAY_NAME_MAPPINGS\s*=\s*{(?:.|\n)*?["\'](.*?)["\']\s*:\s*["\'](.*?)["\']', content)
|
| 402 |
-
for _, display_name in display_name_matches:
|
| 403 |
-
if display_name not in temp_map: temp_map[display_name] = []
|
| 404 |
-
manual_key = wrapper_file.stem
|
| 405 |
-
if manual_key in manual_map: temp_map[display_name].extend(manual_map[manual_key])
|
| 406 |
-
matches = re.findall(r"from_pretrained\s*\(\s*(?:filename=)?\s*f?[\"']([^\"']+)[\"']", content)
|
| 407 |
-
for model_filename in matches:
|
| 408 |
-
repo_id = "lllyasviel/Annotators"
|
| 409 |
-
if "depth_anything" in model_filename and "v2" in model_filename: repo_id = "LiheYoung/Depth-Anything-V2"
|
| 410 |
-
elif "depth_anything" in model_filename: repo_id = "LiheYoung/Depth-Anything"
|
| 411 |
-
elif "diffusion_edge" in model_filename: repo_id = "hr16/Diffusion-Edge"
|
| 412 |
-
temp_map[display_name].append((repo_id, model_filename))
|
| 413 |
-
final_map = {name: sorted(list(set(models))) for name, models in temp_map.items() if models}
|
| 414 |
-
PREPROCESSOR_MODEL_MAP = final_map
|
| 415 |
-
print("✅ ControlNet Preprocessor model map built."); return PREPROCESSOR_MODEL_MAP
|
| 416 |
-
|
| 417 |
-
def build_preprocessor_parameter_map():
|
| 418 |
-
global PREPROCESSOR_PARAMETER_MAP
|
| 419 |
-
if PREPROCESSOR_PARAMETER_MAP is not None: return
|
| 420 |
-
print("--- Building ControlNet Preprocessor parameter map ---")
|
| 421 |
-
param_map = {}
|
| 422 |
-
from nodes import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS
|
| 423 |
-
for class_name, node_class in NODE_CLASS_MAPPINGS.items():
|
| 424 |
-
if not hasattr(node_class, "INPUT_TYPES"): continue
|
| 425 |
-
if hasattr(node_class, '__module__') and 'comfyui_controlnet_aux.node_wrappers' not in node_class.__module__: continue
|
| 426 |
-
display_name = NODE_DISPLAY_NAME_MAPPINGS.get(class_name)
|
| 427 |
-
if not display_name: continue
|
| 428 |
try:
|
| 429 |
-
|
| 430 |
-
all_inputs = {**input_types.get('required', {}), **input_types.get('optional', {})}
|
| 431 |
-
params = []
|
| 432 |
-
for name, details in all_inputs.items():
|
| 433 |
-
if name in ['image', 'resolution', 'pose_kps']: continue
|
| 434 |
-
if not isinstance(details, (list, tuple)) or not details: continue
|
| 435 |
-
param_type = details[0]
|
| 436 |
-
param_config = details[1] if len(details) > 1 and isinstance(details[1], dict) else {}
|
| 437 |
-
param_info = {"name": name, "type": param_type, "config": param_config}
|
| 438 |
-
params.append(param_info)
|
| 439 |
-
if params: param_map[display_name] = params
|
| 440 |
except Exception as e:
|
| 441 |
-
print(f"
|
| 442 |
-
|
| 443 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 444 |
|
| 445 |
def print_welcome_message():
|
| 446 |
author_name = "RioShiina"
|
|
@@ -459,4 +543,24 @@ def print_welcome_message():
|
|
| 459 |
f"{border}\n"
|
| 460 |
)
|
| 461 |
|
| 462 |
-
print(message)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
import torch
|
| 12 |
import numpy as np
|
| 13 |
from PIL import Image, ImageChops
|
| 14 |
+
import yaml
|
| 15 |
|
| 16 |
from core.settings import *
|
| 17 |
|
| 18 |
DISK_LIMIT_GB = 120
|
| 19 |
MODELS_ROOT_DIR = "ComfyUI/models"
|
| 20 |
|
| 21 |
+
IPADAPTER_PRESETS = None
|
| 22 |
+
|
| 23 |
+
class UniqueKeyLoader(yaml.SafeLoader):
|
| 24 |
+
"""
|
| 25 |
+
A custom YAML loader that handles duplicate keys by grouping their values into a list.
|
| 26 |
+
"""
|
| 27 |
+
def construct_mapping(self, node, deep=False):
|
| 28 |
+
mapping = []
|
| 29 |
+
for key_node, value_node in node.value:
|
| 30 |
+
key = self.construct_object(key_node, deep=deep)
|
| 31 |
+
value = self.construct_object(value_node, deep=deep)
|
| 32 |
+
mapping.append((key, value))
|
| 33 |
+
|
| 34 |
+
result = {}
|
| 35 |
+
for k, v in mapping:
|
| 36 |
+
if k in result:
|
| 37 |
+
if isinstance(result[k], list):
|
| 38 |
+
result[k].append(v)
|
| 39 |
+
else:
|
| 40 |
+
result[k] = [result[k], v]
|
| 41 |
+
else:
|
| 42 |
+
result[k] = v
|
| 43 |
+
return result
|
| 44 |
+
|
| 45 |
+
UniqueKeyLoader.add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, UniqueKeyLoader.construct_mapping)
|
| 46 |
|
| 47 |
def save_uploaded_file_with_hash(file_obj: gr.File, target_dir: str) -> str:
|
| 48 |
if not file_obj:
|
|
|
|
| 70 |
|
| 71 |
return hashed_filename
|
| 72 |
|
|
|
|
| 73 |
def bytes_to_gb(byte_size: int) -> float:
|
| 74 |
if byte_size is None or byte_size == 0:
|
| 75 |
return 0.0
|
|
|
|
| 137 |
except Exception as e:
|
| 138 |
print(f"--- [Storage Manager] An unexpected error occurred: {e} ---")
|
| 139 |
|
|
|
|
| 140 |
def get_value_at_index(obj: Union[Sequence, Mapping], index: int) -> Any:
|
| 141 |
try:
|
| 142 |
return obj[index]
|
|
|
|
| 171 |
sanitized = re.sub(r'[^\w\.\-]', '_', sanitized)
|
| 172 |
return sanitized.lstrip('/\\')
|
| 173 |
|
|
|
|
| 174 |
def get_civitai_file_info(version_id: str) -> dict | None:
|
| 175 |
api_url = f"https://civitai.com/api/v1/model-versions/{version_id}"
|
| 176 |
try:
|
|
|
|
| 187 |
except Exception:
|
| 188 |
return None
|
| 189 |
|
|
|
|
| 190 |
def download_file(url: str, save_path: str, api_key: str = None, progress=None, desc: str = "") -> str:
|
| 191 |
enforce_disk_limit()
|
| 192 |
|
|
|
|
| 215 |
os.remove(save_path)
|
| 216 |
return f"Download failed for {os.path.basename(save_path)}: {e}"
|
| 217 |
|
|
|
|
| 218 |
def get_lora_path(source: str, id_or_url: str, civitai_key: str, progress) -> tuple[str | None, str]:
|
| 219 |
if not id_or_url or not id_or_url.strip():
|
| 220 |
return None, "No ID/URL provided."
|
|
|
|
| 318 |
return (local_path, status) if "Successfully" in status else (None, status)
|
| 319 |
|
| 320 |
|
| 321 |
+
def _ensure_model_downloaded(display_name: str, progress=gr.Progress()):
|
| 322 |
+
if display_name not in ALL_MODEL_MAP:
|
| 323 |
+
raise ValueError(f"Model '{display_name}' not found in configuration.")
|
| 324 |
+
|
| 325 |
+
model_info = ALL_MODEL_MAP[display_name]
|
| 326 |
+
repo_filename = model_info[1]
|
| 327 |
+
base_filename = os.path.basename(repo_filename)
|
| 328 |
+
|
| 329 |
+
download_info = ALL_FILE_DOWNLOAD_MAP.get(base_filename)
|
| 330 |
if not download_info:
|
| 331 |
+
raise gr.Error(f"Model '{base_filename}' not found in file_list.yaml. Cannot download.")
|
| 332 |
+
|
| 333 |
+
category = download_info.get("category")
|
| 334 |
+
dest_dir = CATEGORY_TO_DIR_MAP.get(category)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 335 |
|
|
|
|
|
|
|
| 336 |
if not dest_dir:
|
| 337 |
+
raise ValueError(f"Unknown YAML category '{category}' for '{base_filename}'.")
|
| 338 |
|
| 339 |
+
dest_path = os.path.join(dest_dir, base_filename)
|
| 340 |
|
| 341 |
if os.path.lexists(dest_path):
|
| 342 |
if not os.path.exists(dest_path):
|
| 343 |
print(f"⚠️ Found and removed broken symlink: {dest_path}")
|
| 344 |
os.remove(dest_path)
|
| 345 |
else:
|
| 346 |
+
return base_filename
|
| 347 |
|
| 348 |
source = download_info.get("source")
|
| 349 |
try:
|
| 350 |
+
progress(0, desc=f"Downloading: {base_filename}")
|
| 351 |
|
| 352 |
if source == "hf":
|
| 353 |
repo_id = download_info.get("repo_id")
|
| 354 |
+
hf_filename = download_info.get("repository_file_path", base_filename)
|
| 355 |
if not repo_id:
|
| 356 |
+
raise ValueError(f"repo_id is missing for HF model '{base_filename}'")
|
| 357 |
|
| 358 |
+
cached_path = hf_hub_download(repo_id=repo_id, filename=hf_filename, token=os.environ.get("HF_TOKEN"))
|
| 359 |
os.makedirs(dest_dir, exist_ok=True)
|
| 360 |
os.symlink(cached_path, dest_path)
|
| 361 |
print(f"✅ Symlinked '{cached_path}' to '{dest_path}'")
|
|
|
|
| 363 |
elif source == "civitai":
|
| 364 |
model_version_id = download_info.get("model_version_id")
|
| 365 |
if not model_version_id:
|
| 366 |
+
raise ValueError(f"model_version_id is missing for Civitai model '{base_filename}'")
|
| 367 |
|
| 368 |
file_info = get_civitai_file_info(model_version_id)
|
| 369 |
if not file_info or not file_info.get('downloadUrl'):
|
| 370 |
raise ConnectionError(f"Could not get download URL for Civitai model version ID {model_version_id}")
|
| 371 |
|
| 372 |
status = download_file(
|
| 373 |
+
file_info['downloadUrl'], dest_path, api_key=os.environ.get("CIVITAI_API_KEY", ""), progress=progress, desc=f"Downloading: {base_filename}"
|
| 374 |
)
|
| 375 |
if "Failed" in status:
|
| 376 |
raise ConnectionError(status)
|
| 377 |
else:
|
| 378 |
+
raise NotImplementedError(f"Download source '{source}' is not implemented for '{base_filename}'")
|
| 379 |
|
| 380 |
+
progress(1.0, desc=f"Downloaded: {base_filename}")
|
| 381 |
|
| 382 |
except Exception as e:
|
| 383 |
if os.path.lexists(dest_path):
|
| 384 |
try:
|
| 385 |
os.remove(dest_path)
|
| 386 |
except OSError: pass
|
| 387 |
+
raise gr.Error(f"Failed to download and link '{display_name}': {e}")
|
| 388 |
|
| 389 |
+
return base_filename
|
| 390 |
|
| 391 |
def ensure_controlnet_model_downloaded(filename: str, progress):
|
| 392 |
if not filename or filename == "None":
|
| 393 |
return
|
|
|
|
| 394 |
|
| 395 |
+
download_info = ALL_FILE_DOWNLOAD_MAP.get(filename)
|
| 396 |
+
if not download_info:
|
| 397 |
+
raise gr.Error(f"ControlNet model '{filename}' not found in configuration (file_list.yaml). Cannot download.")
|
| 398 |
+
|
| 399 |
+
category = download_info.get("category", "controlnet")
|
| 400 |
+
dest_dir = CATEGORY_TO_DIR_MAP.get(category, CONTROLNET_DIR)
|
| 401 |
+
dest_path = os.path.join(dest_dir, filename)
|
| 402 |
+
|
| 403 |
+
if os.path.lexists(dest_path):
|
| 404 |
+
if not os.path.exists(dest_path):
|
| 405 |
+
print(f"⚠️ Found and removed broken symlink: {dest_path}")
|
| 406 |
+
os.remove(dest_path)
|
| 407 |
+
else:
|
| 408 |
+
return
|
| 409 |
+
|
| 410 |
+
source = download_info.get("source")
|
| 411 |
+
|
| 412 |
+
try:
|
| 413 |
+
if source == "hf":
|
| 414 |
+
repo_id = download_info.get("repo_id")
|
| 415 |
+
repo_filename = download_info.get("repository_file_path", filename)
|
| 416 |
+
if not repo_id:
|
| 417 |
+
raise ValueError("repo_id is missing for Hugging Face download.")
|
| 418 |
+
|
| 419 |
+
progress(0, desc=f"Downloading CN: {filename}")
|
| 420 |
+
cached_path = hf_hub_download(repo_id=repo_id, filename=repo_filename, token=os.environ.get("HF_TOKEN"))
|
| 421 |
+
os.makedirs(dest_dir, exist_ok=True)
|
| 422 |
+
os.symlink(cached_path, dest_path)
|
| 423 |
+
print(f"✅ Symlinked ControlNet '{cached_path}' to '{dest_path}'")
|
| 424 |
+
progress(1.0, desc=f"Downloaded CN: {filename}")
|
| 425 |
+
|
| 426 |
+
elif source == "civitai":
|
| 427 |
+
model_version_id = download_info.get("model_version_id")
|
| 428 |
+
if not model_version_id:
|
| 429 |
+
raise ValueError("model_version_id is missing for Civitai download.")
|
| 430 |
+
|
| 431 |
+
file_info = get_civitai_file_info(model_version_id)
|
| 432 |
+
if not file_info or not file_info.get('downloadUrl'):
|
| 433 |
+
raise ConnectionError(f"Could not get download URL for Civitai model version ID {model_version_id}")
|
| 434 |
+
|
| 435 |
+
status = download_file(
|
| 436 |
+
file_info['downloadUrl'],
|
| 437 |
+
dest_path,
|
| 438 |
+
api_key=os.environ.get("CIVITAI_API_KEY", ""),
|
| 439 |
+
progress=progress,
|
| 440 |
+
desc=f"Downloading CN: {filename}"
|
| 441 |
+
)
|
| 442 |
+
if "Failed" in status:
|
| 443 |
+
raise ConnectionError(status)
|
| 444 |
+
else:
|
| 445 |
+
raise NotImplementedError(f"Download source '{source}' is not implemented for ControlNets.")
|
| 446 |
+
|
| 447 |
+
except Exception as e:
|
| 448 |
+
if os.path.lexists(dest_path):
|
| 449 |
+
try:
|
| 450 |
+
os.remove(dest_path)
|
| 451 |
+
except OSError:
|
| 452 |
+
pass
|
| 453 |
+
raise gr.Error(f"Failed to download ControlNet model '{filename}': {e}")
|
| 454 |
+
|
| 455 |
+
def load_ipadapter_presets():
|
| 456 |
+
global IPADAPTER_PRESETS
|
| 457 |
+
if IPADAPTER_PRESETS is not None:
|
| 458 |
+
return
|
| 459 |
+
|
| 460 |
+
_PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 461 |
+
_IPADAPTER_MODELS_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'ipadapter_models.yaml')
|
| 462 |
+
|
| 463 |
+
try:
|
| 464 |
+
with open(_IPADAPTER_MODELS_PATH, 'r', encoding='utf-8') as f:
|
| 465 |
+
presets_list = yaml.load(f, Loader=UniqueKeyLoader)
|
| 466 |
+
|
| 467 |
+
IPADAPTER_PRESETS = {item['preset_name']: item for item in presets_list}
|
| 468 |
+
print("✅ IPAdapter presets loaded successfully.")
|
| 469 |
+
except Exception as e:
|
| 470 |
+
print(f"❌ FATAL: Could not load or parse ipadapter_models.yaml. IPAdapter will not work. Error: {e}")
|
| 471 |
+
IPADAPTER_PRESETS = {}
|
| 472 |
+
|
| 473 |
+
def ensure_ipadapter_models_downloaded(preset_name: str, progress):
|
| 474 |
+
if not preset_name:
|
| 475 |
+
return
|
| 476 |
+
|
| 477 |
+
if IPADAPTER_PRESETS is None:
|
| 478 |
+
raise RuntimeError("IPAdapter presets have not been loaded. `load_ipadapter_presets` must be called on startup.")
|
| 479 |
+
|
| 480 |
+
preset_info = IPADAPTER_PRESETS.get(preset_name)
|
| 481 |
+
if not preset_info:
|
| 482 |
+
print(f"⚠️ Warning: IPAdapter preset '{preset_name}' not found in configuration. Skipping download.")
|
| 483 |
+
return
|
| 484 |
+
|
| 485 |
+
model_files_to_check = []
|
| 486 |
+
|
| 487 |
+
def add_files(value, type_name):
|
| 488 |
+
if not value: return
|
| 489 |
+
if isinstance(value, list):
|
| 490 |
+
for v in value:
|
| 491 |
+
model_files_to_check.append((v, type_name))
|
| 492 |
+
else:
|
| 493 |
+
model_files_to_check.append((value, type_name))
|
| 494 |
+
|
| 495 |
+
add_files(preset_info.get('clip_vision'), 'CLIP_VISION')
|
| 496 |
+
add_files(preset_info.get('ipadapter'), 'IPADAPTER')
|
| 497 |
+
add_files(preset_info.get('loras'), 'LORA')
|
| 498 |
+
|
| 499 |
+
for filename, model_type in model_files_to_check:
|
| 500 |
+
if not filename:
|
| 501 |
+
continue
|
| 502 |
+
|
| 503 |
+
temp_display_name = f"ipadapter_asset_{filename}"
|
| 504 |
+
|
| 505 |
+
if temp_display_name not in ALL_MODEL_MAP:
|
| 506 |
+
ALL_MODEL_MAP[temp_display_name] = (None, filename, model_type, None, None)
|
| 507 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 508 |
try:
|
| 509 |
+
_ensure_model_downloaded(temp_display_name, progress)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 510 |
except Exception as e:
|
| 511 |
+
print(f"❌ Error ensuring download for IPAdapter asset '{filename}': {e}")
|
| 512 |
+
|
| 513 |
+
|
| 514 |
+
def ensure_sd3_ipadapter_models_downloaded(progress):
|
| 515 |
+
_PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 516 |
+
yaml_path = os.path.join(_PROJECT_ROOT, 'yaml', 'ipadapter_sd3_models.yaml')
|
| 517 |
+
try:
|
| 518 |
+
with open(yaml_path, 'r', encoding='utf-8') as f:
|
| 519 |
+
sd3_models = yaml.safe_load(f)
|
| 520 |
+
if sd3_models:
|
| 521 |
+
if 'ipadapter' in sd3_models:
|
| 522 |
+
_ensure_model_downloaded(sd3_models['ipadapter'], progress)
|
| 523 |
+
if 'clip_vision' in sd3_models:
|
| 524 |
+
_ensure_model_downloaded(sd3_models['clip_vision'], progress)
|
| 525 |
+
except Exception as e:
|
| 526 |
+
print(f"Warning: Failed to load or download sd3 ipadapter models: {e}")
|
| 527 |
+
|
| 528 |
|
| 529 |
def print_welcome_message():
|
| 530 |
author_name = "RioShiina"
|
|
|
|
| 543 |
f"{border}\n"
|
| 544 |
)
|
| 545 |
|
| 546 |
+
print(message)
|
| 547 |
+
|
| 548 |
+
def get_model_generation_defaults(model_display_name: str, model_type: str, defaults_config: dict):
|
| 549 |
+
final_defaults = {
|
| 550 |
+
'steps': 25, 'cfg': 7.0, 'sampler_name': 'euler', 'scheduler': 'simple',
|
| 551 |
+
'positive_prompt': '', 'negative_prompt': ''
|
| 552 |
+
}
|
| 553 |
+
|
| 554 |
+
if 'Default' in defaults_config:
|
| 555 |
+
final_defaults.update(defaults_config['Default'])
|
| 556 |
+
|
| 557 |
+
model_type_key = next((key for key in defaults_config if key.lower().replace(" ", "-").replace(".", "") == model_type.lower()), None)
|
| 558 |
+
if model_type_key:
|
| 559 |
+
model_type_config = defaults_config[model_type_key]
|
| 560 |
+
if '_defaults' in model_type_config:
|
| 561 |
+
final_defaults.update(model_type_config['_defaults'])
|
| 562 |
+
|
| 563 |
+
if model_display_name in model_type_config:
|
| 564 |
+
final_defaults.update(model_type_config[model_display_name])
|
| 565 |
+
|
| 566 |
+
return final_defaults
|
yaml/constants.yaml
CHANGED
|
@@ -1,11 +1,116 @@
|
|
| 1 |
MAX_LORAS: 5
|
| 2 |
MAX_CONTROLNETS: 5
|
|
|
|
| 3 |
MAX_EMBEDDINGS: 5
|
| 4 |
MAX_CONDITIONINGS: 10
|
| 5 |
MAX_REFERENCE_LATENTS: 10
|
| 6 |
LORA_SOURCE_CHOICES: ["Civitai", "File"]
|
| 7 |
|
| 8 |
RESOLUTION_MAP:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
sdxl:
|
| 10 |
"1:1 (Square)": [1024, 1024]
|
| 11 |
"16:9 (Landscape)": [1344, 768]
|
|
@@ -13,4 +118,36 @@ RESOLUTION_MAP:
|
|
| 13 |
"4:3 (Classic)": [1152, 896]
|
| 14 |
"3:4 (Classic Portrait)": [896, 1152]
|
| 15 |
"3:2 (Photography)": [1216, 832]
|
| 16 |
-
"2:3 (Photography Portrait)": [832, 1216]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
MAX_LORAS: 5
|
| 2 |
MAX_CONTROLNETS: 5
|
| 3 |
+
MAX_IPADAPTERS: 5
|
| 4 |
MAX_EMBEDDINGS: 5
|
| 5 |
MAX_CONDITIONINGS: 10
|
| 6 |
MAX_REFERENCE_LATENTS: 10
|
| 7 |
LORA_SOURCE_CHOICES: ["Civitai", "File"]
|
| 8 |
|
| 9 |
RESOLUTION_MAP:
|
| 10 |
+
ernie-image:
|
| 11 |
+
"1:1 (Square)": [1024, 1024]
|
| 12 |
+
"16:9 (Landscape)": [1344, 768]
|
| 13 |
+
"9:16 (Portrait)": [768, 1344]
|
| 14 |
+
"4:3 (Classic)": [1152, 896]
|
| 15 |
+
"3:4 (Classic Portrait)": [896, 1152]
|
| 16 |
+
"3:2 (Photography)": [1216, 832]
|
| 17 |
+
"2:3 (Photography Portrait)": [832, 1216]
|
| 18 |
+
flux2:
|
| 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 |
+
flux2-kv:
|
| 27 |
+
"1:1 (Square)": [1024, 1024]
|
| 28 |
+
"16:9 (Landscape)": [1344, 768]
|
| 29 |
+
"9:16 (Portrait)": [768, 1344]
|
| 30 |
+
"4:3 (Classic)": [1152, 896]
|
| 31 |
+
"3:4 (Classic Portrait)": [896, 1152]
|
| 32 |
+
"3:2 (Photography)": [1216, 832]
|
| 33 |
+
"2:3 (Photography Portrait)": [832, 1216]
|
| 34 |
+
qwen-image:
|
| 35 |
+
"1:1 (Square)": [1328, 1328]
|
| 36 |
+
"16:9 (Landscape)": [1664, 928]
|
| 37 |
+
"9:16 (Portrait)": [928, 1664]
|
| 38 |
+
"4:3 (Classic)": [1472, 1104]
|
| 39 |
+
"3:4 (Classic Portrait)": [1104, 1472]
|
| 40 |
+
"3:2 (Photography)": [1536, 1024]
|
| 41 |
+
"2:3 (Photography Portrait)": [1024, 1536]
|
| 42 |
+
longcat-image:
|
| 43 |
+
"1:1 (Square)": [1024, 1024]
|
| 44 |
+
"16:9 (Landscape)": [1344, 768]
|
| 45 |
+
"9:16 (Portrait)": [768, 1344]
|
| 46 |
+
"4:3 (Classic)": [1152, 896]
|
| 47 |
+
"3:4 (Classic Portrait)": [896, 1152]
|
| 48 |
+
"3:2 (Photography)": [1216, 832]
|
| 49 |
+
"2:3 (Photography Portrait)": [832, 1216]
|
| 50 |
+
anima:
|
| 51 |
+
"1:1 (Square)": [1024, 1024]
|
| 52 |
+
"16:9 (Landscape)": [1344, 768]
|
| 53 |
+
"9:16 (Portrait)": [768, 1344]
|
| 54 |
+
"4:3 (Classic)": [1152, 896]
|
| 55 |
+
"3:4 (Classic Portrait)": [896, 1152]
|
| 56 |
+
"3:2 (Photography)": [1216, 832]
|
| 57 |
+
"2:3 (Photography Portrait)": [832, 1216]
|
| 58 |
+
newbie-image:
|
| 59 |
+
"1:1 (Square)": [1024, 1024]
|
| 60 |
+
"16:9 (Landscape)": [1344, 768]
|
| 61 |
+
"9:16 (Portrait)": [768, 1344]
|
| 62 |
+
"4:3 (Classic)": [1152, 896]
|
| 63 |
+
"3:4 (Classic Portrait)": [896, 1152]
|
| 64 |
+
"3:2 (Photography)": [1216, 832]
|
| 65 |
+
"2:3 (Photography Portrait)": [832, 1216]
|
| 66 |
+
omnigen2:
|
| 67 |
+
"1:1 (Square)": [1024, 1024]
|
| 68 |
+
"16:9 (Landscape)": [1344, 768]
|
| 69 |
+
"9:16 (Portrait)": [768, 1344]
|
| 70 |
+
"4:3 (Classic)": [1152, 896]
|
| 71 |
+
"3:4 (Classic Portrait)": [896, 1152]
|
| 72 |
+
"3:2 (Photography)": [1216, 832]
|
| 73 |
+
"2:3 (Photography Portrait)": [832, 1216]
|
| 74 |
+
lumina:
|
| 75 |
+
"1:1 (Square)": [1024, 1024]
|
| 76 |
+
"16:9 (Landscape)": [1344, 768]
|
| 77 |
+
"9:16 (Portrait)": [768, 1344]
|
| 78 |
+
"4:3 (Classic)": [1152, 896]
|
| 79 |
+
"3:4 (Classic Portrait)": [896, 1152]
|
| 80 |
+
"3:2 (Photography)": [1216, 832]
|
| 81 |
+
"2:3 (Photography Portrait)": [832, 1216]
|
| 82 |
+
ovis-image:
|
| 83 |
+
"1:1 (Square)": [1024, 1024]
|
| 84 |
+
"16:9 (Landscape)": [1344, 768]
|
| 85 |
+
"9:16 (Portrait)": [768, 1344]
|
| 86 |
+
"4:3 (Classic)": [1152, 896]
|
| 87 |
+
"3:4 (Classic Portrait)": [896, 1152]
|
| 88 |
+
"3:2 (Photography)": [1216, 832]
|
| 89 |
+
"2:3 (Photography Portrait)": [832, 1216]
|
| 90 |
+
flux1:
|
| 91 |
+
"1:1 (Square)": [1024, 1024]
|
| 92 |
+
"16:9 (Landscape)": [1344, 768]
|
| 93 |
+
"9:16 (Portrait)": [768, 1344]
|
| 94 |
+
"4:3 (Classic)": [1152, 896]
|
| 95 |
+
"3:4 (Classic Portrait)": [896, 1152]
|
| 96 |
+
"3:2 (Photography)": [1216, 832]
|
| 97 |
+
"2:3 (Photography Portrait)": [832, 1216]
|
| 98 |
+
hidream:
|
| 99 |
+
"1:1 (Square)": [1024, 1024]
|
| 100 |
+
"16:9 (Landscape)": [1344, 768]
|
| 101 |
+
"9:16 (Portrait)": [768, 1344]
|
| 102 |
+
"4:3 (Classic)": [1152, 896]
|
| 103 |
+
"3:4 (Classic Portrait)": [896, 1152]
|
| 104 |
+
"3:2 (Photography)": [1216, 832]
|
| 105 |
+
"2:3 (Photography Portrait)": [832, 1216]
|
| 106 |
+
sd35:
|
| 107 |
+
"1:1 (Square)": [1024, 1024]
|
| 108 |
+
"16:9 (Landscape)": [1344, 768]
|
| 109 |
+
"9:16 (Portrait)": [768, 1344]
|
| 110 |
+
"4:3 (Classic)": [1152, 896]
|
| 111 |
+
"3:4 (Classic Portrait)": [896, 1152]
|
| 112 |
+
"3:2 (Photography)": [1216, 832]
|
| 113 |
+
"2:3 (Photography Portrait)": [832, 1216]
|
| 114 |
sdxl:
|
| 115 |
"1:1 (Square)": [1024, 1024]
|
| 116 |
"16:9 (Landscape)": [1344, 768]
|
|
|
|
| 118 |
"4:3 (Classic)": [1152, 896]
|
| 119 |
"3:4 (Classic Portrait)": [896, 1152]
|
| 120 |
"3:2 (Photography)": [1216, 832]
|
| 121 |
+
"2:3 (Photography Portrait)": [832, 1216]
|
| 122 |
+
sd15:
|
| 123 |
+
"1:1 (Square)": [512, 512]
|
| 124 |
+
"16:9 (Landscape)": [896, 512]
|
| 125 |
+
"9:16 (Portrait)": [512, 896]
|
| 126 |
+
"4:3 (Classic Landscape)": [683, 512]
|
| 127 |
+
"3:4 (Classic Portrait)": [512, 683]
|
| 128 |
+
"3:2 (Landscape)": [768, 512]
|
| 129 |
+
"2:3 (Portrait)": [512, 768]
|
| 130 |
+
chroma1-radiance:
|
| 131 |
+
"1:1 (Square)": [1024, 1024]
|
| 132 |
+
"16:9 (Landscape)": [1344, 768]
|
| 133 |
+
"9:16 (Portrait)": [768, 1344]
|
| 134 |
+
"4:3 (Classic)": [1152, 896]
|
| 135 |
+
"3:4 (Classic Portrait)": [896, 1152]
|
| 136 |
+
"3:2 (Photography)": [1216, 832]
|
| 137 |
+
"2:3 (Photography Portrait)": [832, 1216]
|
| 138 |
+
chroma1:
|
| 139 |
+
"1:1 (Square)": [1024, 1024]
|
| 140 |
+
"16:9 (Landscape)": [1344, 768]
|
| 141 |
+
"9:16 (Portrait)": [768, 1344]
|
| 142 |
+
"4:3 (Classic)": [1152, 896]
|
| 143 |
+
"3:4 (Classic Portrait)": [896, 1152]
|
| 144 |
+
"3:2 (Photography)": [1216, 832]
|
| 145 |
+
"2:3 (Photography Portrait)": [832, 1216]
|
| 146 |
+
hunyuanimage:
|
| 147 |
+
"1:1 (Square)": [2048, 2048]
|
| 148 |
+
"16:9 (Landscape)": [2728, 1536]
|
| 149 |
+
"9:16 (Portrait)": [1536, 2728]
|
| 150 |
+
"4:3 (Classic)": [2368, 1776]
|
| 151 |
+
"3:4 (Classic Portrait)": [1776, 2368]
|
| 152 |
+
"3:2 (Photography)": [2504, 1672]
|
| 153 |
+
"2:3 (Photography Portrait)": [1672, 2504]
|
yaml/file_list.yaml
CHANGED
|
@@ -1,25 +1,645 @@
|
|
| 1 |
-
file:
|
| 2 |
-
checkpoints:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
- filename: "sd_xl_base_1.0.safetensors"
|
| 4 |
source: "hf"
|
| 5 |
repo_id: "stabilityai/stable-diffusion-xl-base-1.0"
|
| 6 |
repository_file_path: "sd_xl_base_1.0.safetensors"
|
|
|
|
| 7 |
- filename: "v1-5-pruned-emaonly.safetensors"
|
| 8 |
source: "hf"
|
| 9 |
repo_id: "stable-diffusion-v1-5/stable-diffusion-v1-5"
|
| 10 |
repository_file_path: "v1-5-pruned-emaonly.safetensors"
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
- filename: "flux2_dev_fp8mixed.safetensors"
|
| 13 |
source: "hf"
|
| 14 |
repo_id: "Comfy-Org/flux2-dev"
|
| 15 |
repository_file_path: "split_files/diffusion_models/flux2_dev_fp8mixed.safetensors"
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
- filename: "mistral_3_small_flux2_fp8.safetensors"
|
| 18 |
source: "hf"
|
| 19 |
repo_id: "Comfy-Org/flux2-dev"
|
| 20 |
repository_file_path: "split_files/text_encoders/mistral_3_small_flux2_fp8.safetensors"
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
- filename: "flux2-vae.safetensors"
|
| 23 |
source: "hf"
|
| 24 |
repo_id: "Comfy-Org/flux2-dev"
|
| 25 |
-
repository_file_path: "split_files/vae/flux2-vae.safetensors"
|
|
|
|
| 1 |
+
file:
|
| 2 |
+
checkpoints:
|
| 3 |
+
# Lumina
|
| 4 |
+
- filename: "lumina_2.safetensors"
|
| 5 |
+
source: "hf"
|
| 6 |
+
repo_id: "Comfy-Org/Lumina_Image_2.0_Repackaged"
|
| 7 |
+
repository_file_path: "all_in_one/lumina_2.safetensors"
|
| 8 |
+
# SD3.5
|
| 9 |
+
- filename: "sd3.5_large_fp8_scaled.safetensors"
|
| 10 |
+
source: "hf"
|
| 11 |
+
repo_id: "Comfy-Org/stable-diffusion-3.5-fp8"
|
| 12 |
+
repository_file_path: "sd3.5_large_fp8_scaled.safetensors"
|
| 13 |
+
- filename: "sd3.5_medium_incl_clips_t5xxlfp8scaled.safetensors"
|
| 14 |
+
source: "hf"
|
| 15 |
+
repo_id: "Comfy-Org/stable-diffusion-3.5-fp8"
|
| 16 |
+
repository_file_path: "sd3.5_medium_incl_clips_t5xxlfp8scaled.safetensors"
|
| 17 |
+
# SDXL-NoobAI
|
| 18 |
+
- filename: "NoobAI-XL-Vpred-v1.0.safetensors"
|
| 19 |
+
source: hf
|
| 20 |
+
repo_id: "Laxhar/noobai-XL-Vpred-1.0"
|
| 21 |
+
repository_file_path: "NoobAI-XL-Vpred-v1.0.safetensors"
|
| 22 |
+
- filename: "NoobAI-XL-v1.1.safetensors"
|
| 23 |
+
source: hf
|
| 24 |
+
repo_id: "Laxhar/noobai-XL-1.1"
|
| 25 |
+
repository_file_path: "NoobAI-XL-v1.1.safetensors"
|
| 26 |
+
- filename: "noob_v_pencil-XL-v3.0.0.safetensors"
|
| 27 |
+
source: hf
|
| 28 |
+
repo_id: "bluepen5805/noob_v_pencil-XL"
|
| 29 |
+
repository_file_path: "noob_v_pencil-XL-v3.0.0.safetensors"
|
| 30 |
+
- filename: "Hikari_Noob_v-pred_1.2.4.safetensors"
|
| 31 |
+
source: hf
|
| 32 |
+
repo_id: "RedRayz/hikari_noob_v-pred_1.2.4"
|
| 33 |
+
repository_file_path: "Hikari_Noob_v-pred_1.2.4.safetensors"
|
| 34 |
+
- filename: "ChenkinNoob-XL-V0.5.safetensors"
|
| 35 |
+
source: hf
|
| 36 |
+
repo_id: "ChenkinNoob/ChenkinNoob-XL-V0.5"
|
| 37 |
+
repository_file_path: "ChenkinNoob-XL-V0.5.safetensors"
|
| 38 |
+
# SDXL-Illustrious
|
| 39 |
+
- filename: "waiIllustriousSDXL_v170.safetensors"
|
| 40 |
+
source: hf
|
| 41 |
+
repo_id: "zhenshipo/waiIllustriousSDXL_v170"
|
| 42 |
+
repository_file_path: "waiIllustriousSDXL_v170.safetensors"
|
| 43 |
+
- filename: "mellow_pencil-XL-v1.0.0.safetensors"
|
| 44 |
+
source: hf
|
| 45 |
+
repo_id: "bluepen5805/mellow_pencil-XL"
|
| 46 |
+
repository_file_path: "mellow_pencil-XL-v1.0.0.safetensors"
|
| 47 |
+
- filename: "illustrious_pencil-XL-v5.0.0.safetensors"
|
| 48 |
+
source: hf
|
| 49 |
+
repo_id: "bluepen5805/illustrious_pencil-XL"
|
| 50 |
+
repository_file_path: "illustrious_pencil-XL-v5.0.0.safetensors"
|
| 51 |
+
- filename: "hassakuXLIllustrious_v34.safetensors"
|
| 52 |
+
source: hf
|
| 53 |
+
repo_id: "oldhag88/hassakuXLIllustrious_v34.safetensors"
|
| 54 |
+
repository_file_path: "hassakuXLIllustrious_v34.safetensors"
|
| 55 |
+
- filename: "novaAnimeXL_ilV160.safetensors"
|
| 56 |
+
source: hf
|
| 57 |
+
repo_id: "Yevrey921/novaAnimeXL_ilV160"
|
| 58 |
+
repository_file_path: "novaAnimeXL_ilV160.safetensors"
|
| 59 |
+
- filename: "Illustrious-XL-v2.0.safetensors"
|
| 60 |
+
source: hf
|
| 61 |
+
repo_id: "OnomaAIResearch/Illustrious-XL-v2.0"
|
| 62 |
+
- filename: "Illustrious-XL-v2.0.safetensors"
|
| 63 |
+
source: hf
|
| 64 |
+
repo_id: "OnomaAIResearch/Illustrious-XL-v2.0"
|
| 65 |
+
repository_file_path: "Illustrious-XL-v2.0.safetensors"
|
| 66 |
+
- filename: "Illustrious-XL-v1.1.safetensors"
|
| 67 |
+
source: hf
|
| 68 |
+
repo_id: "OnomaAIResearch/Illustrious-XL-v1.1"
|
| 69 |
+
repository_file_path: "Illustrious-XL-v1.1.safetensors"
|
| 70 |
+
- filename: "Illustrious-XL-v1.0.safetensors"
|
| 71 |
+
source: hf
|
| 72 |
+
repo_id: "OnomaAIResearch/Illustrious-XL-v1.0"
|
| 73 |
+
repository_file_path: "Illustrious-XL-v1.0.safetensors"
|
| 74 |
+
- filename: "illustriousXL_v01.safetensors"
|
| 75 |
+
source: hf
|
| 76 |
+
repo_id: "AiAF/Illustrious-XL-v0.1.safetensors"
|
| 77 |
+
repository_file_path: "illustriousXL_v01.safetensors"
|
| 78 |
+
# SDXL-Animate
|
| 79 |
+
- filename: "animagine-xl-4.0.safetensors"
|
| 80 |
+
source: hf
|
| 81 |
+
repo_id: "cagliostrolab/animagine-xl-4.0"
|
| 82 |
+
repository_file_path: "animagine-xl-4.0.safetensors"
|
| 83 |
+
- filename: "animagine-xl-3.1.safetensors"
|
| 84 |
+
source: hf
|
| 85 |
+
repo_id: "cagliostrolab/animagine-xl-3.1"
|
| 86 |
+
repository_file_path: "animagine-xl-3.1.safetensors"
|
| 87 |
+
- filename: "4nima_pencil-XL-v1.0.1.safetensors"
|
| 88 |
+
source: hf
|
| 89 |
+
repo_id: "bluepen5805/4nima_pencil-XL"
|
| 90 |
+
repository_file_path: "4nima_pencil-XL-v1.0.1.safetensors"
|
| 91 |
+
- filename: "anima_pencil-XL-v5.0.0.safetensors"
|
| 92 |
+
source: hf
|
| 93 |
+
repo_id: "bluepen5805/anima_pencil-XL"
|
| 94 |
+
repository_file_path: "anima_pencil-XL-v5.0.0.safetensors"
|
| 95 |
+
- filename: "blue_pencil-XL-v7.0.0.safetensors"
|
| 96 |
+
source: hf
|
| 97 |
+
repo_id: "bluepen5805/blue_pencil-XL"
|
| 98 |
+
repository_file_path: "blue_pencil-XL-v7.0.0.safetensors"
|
| 99 |
+
# SDXL-Pony
|
| 100 |
+
- filename: "ponyDiffusionV6XL_v6StartWithThisOne.safetensors"
|
| 101 |
+
source: hf
|
| 102 |
+
repo_id: "LyliaEngine/Pony_Diffusion_V6_XL"
|
| 103 |
+
repository_file_path: "ponyDiffusionV6XL_v6StartWithThisOne.safetensors"
|
| 104 |
+
- filename: "pony_pencil-XL-v2.0.0.safetensors"
|
| 105 |
+
source: hf
|
| 106 |
+
repo_id: "bluepen5805/pony_pencil-XL"
|
| 107 |
+
repository_file_path: "pony_pencil-XL-v2.0.0.safetensors"
|
| 108 |
+
- filename: "CyberRealisticPony_V14.0.safetensors"
|
| 109 |
+
source: hf
|
| 110 |
+
repo_id: "cyberdelia/CyberRealisticPony"
|
| 111 |
+
repository_file_path: "CyberRealisticPony_V14.0.safetensors"
|
| 112 |
+
# SDXL-Base
|
| 113 |
- filename: "sd_xl_base_1.0.safetensors"
|
| 114 |
source: "hf"
|
| 115 |
repo_id: "stabilityai/stable-diffusion-xl-base-1.0"
|
| 116 |
repository_file_path: "sd_xl_base_1.0.safetensors"
|
| 117 |
+
# SD1.5
|
| 118 |
- filename: "v1-5-pruned-emaonly.safetensors"
|
| 119 |
source: "hf"
|
| 120 |
repo_id: "stable-diffusion-v1-5/stable-diffusion-v1-5"
|
| 121 |
repository_file_path: "v1-5-pruned-emaonly.safetensors"
|
| 122 |
+
clip_vision:
|
| 123 |
+
# style_injector
|
| 124 |
+
- filename: "sigclip_vision_patch14_384.safetensors"
|
| 125 |
+
source: "hf"
|
| 126 |
+
repo_id: "Comfy-Org/sigclip_vision_384"
|
| 127 |
+
repository_file_path: "sigclip_vision_patch14_384.safetensors"
|
| 128 |
+
# IPAdapter
|
| 129 |
+
- filename: "CLIP-ViT-H-14-laion2B-s32B-b79K.safetensors"
|
| 130 |
+
source: "hf"
|
| 131 |
+
repo_id: "h94/IP-Adapter"
|
| 132 |
+
repository_file_path: "models/image_encoder/model.safetensors"
|
| 133 |
+
- filename: "CLIP-ViT-bigG-14-laion2B-39B-b160k.safetensors"
|
| 134 |
+
source: "hf"
|
| 135 |
+
repo_id: "h94/IP-Adapter"
|
| 136 |
+
repository_file_path: "sdxl_models/image_encoder/model.safetensors"
|
| 137 |
+
# IPAdapter-SD3
|
| 138 |
+
- filename: "sigclip_vision_patch14_384.safetensors"
|
| 139 |
+
source: "hf"
|
| 140 |
+
repo_id: "Comfy-Org/sigclip_vision_384"
|
| 141 |
+
repository_file_path: "sigclip_vision_patch14_384.safetensors"
|
| 142 |
+
controlnet:
|
| 143 |
+
# SD3.5
|
| 144 |
+
- filename: "sd3.5_large_controlnet_blur.safetensors"
|
| 145 |
+
source: "hf"
|
| 146 |
+
repo_id: "stabilityai/stable-diffusion-3.5-controlnets"
|
| 147 |
+
repository_file_path: "sd3.5_large_controlnet_blur.safetensors"
|
| 148 |
+
- filename: "sd3.5_large_controlnet_canny.safetensors"
|
| 149 |
+
source: "hf"
|
| 150 |
+
repo_id: "stabilityai/stable-diffusion-3.5-controlnets"
|
| 151 |
+
repository_file_path: "sd3.5_large_controlnet_canny.safetensors"
|
| 152 |
+
- filename: "sd3.5_large_controlnet_depth.safetensors"
|
| 153 |
+
source: "hf"
|
| 154 |
+
repo_id: "stabilityai/stable-diffusion-3.5-controlnets"
|
| 155 |
+
repository_file_path: "sd3.5_large_controlnet_depth.safetensors"
|
| 156 |
+
# Qwen-Image
|
| 157 |
+
- filename: "Qwen-Image-InstantX-ControlNet-Union.safetensors"
|
| 158 |
+
source: "hf"
|
| 159 |
+
repo_id: "InstantX/Qwen-Image-ControlNet-Union"
|
| 160 |
+
repository_file_path: "diffusion_pytorch_model.safetensors"
|
| 161 |
+
- filename: "Qwen-Image-InstantX-ControlNet-Inpainting.safetensors"
|
| 162 |
+
source: "hf"
|
| 163 |
+
repo_id: "InstantX/Qwen-Image-ControlNet-Inpainting"
|
| 164 |
+
repository_file_path: "diffusion_pytorch_model.safetensors"
|
| 165 |
+
# FLUX.1
|
| 166 |
+
- filename: "FLUX.1-dev-ControlNet-Union-Pro-2.0.safetensors"
|
| 167 |
+
source: "hf"
|
| 168 |
+
repo_id: "Shakker-Labs/FLUX.1-dev-ControlNet-Union-Pro-2.0"
|
| 169 |
+
repository_file_path: "diffusion_pytorch_model.safetensors"
|
| 170 |
+
- filename: "flux-canny-controlnet-v3.safetensors"
|
| 171 |
+
source: "hf"
|
| 172 |
+
repo_id: "XLabs-AI/flux-controlnet-collections"
|
| 173 |
+
repository_file_path: "flux-canny-controlnet-v3.safetensors"
|
| 174 |
+
- filename: "flux-depth-controlnet-v3.safetensors"
|
| 175 |
+
source: "hf"
|
| 176 |
+
repo_id: "XLabs-AI/flux-controlnet-collections"
|
| 177 |
+
repository_file_path: "flux-depth-controlnet-v3.safetensors"
|
| 178 |
+
- filename: "flux-hed-controlnet-v3.safetensors"
|
| 179 |
+
source: "hf"
|
| 180 |
+
repo_id: "XLabs-AI/flux-controlnet-collections"
|
| 181 |
+
repository_file_path: "flux-hed-controlnet-v3.safetensors"
|
| 182 |
+
# SDXL
|
| 183 |
+
- filename: "controlnet-union-sdxl-1.0_promax.safetensors"
|
| 184 |
+
source: "hf"
|
| 185 |
+
repo_id: "xinsir/controlnet-union-sdxl-1.0"
|
| 186 |
+
repository_file_path: "diffusion_pytorch_model_promax.safetensors"
|
| 187 |
+
- filename: "controlnet-tile-sdxl-1.0.safetensors"
|
| 188 |
+
source: "hf"
|
| 189 |
+
repo_id: "xinsir/controlnet-tile-sdxl-1.0"
|
| 190 |
+
repository_file_path: "diffusion_pytorch_model.safetensors"
|
| 191 |
+
- filename: "controlnet-canny-sdxl-1.0_V2.safetensors"
|
| 192 |
+
source: "hf"
|
| 193 |
+
repo_id: "xinsir/controlnet-canny-sdxl-1.0"
|
| 194 |
+
repository_file_path: "diffusion_pytorch_model_V2.safetensors"
|
| 195 |
+
- filename: "controlnet-openpose-sdxl-1.0.safetensors"
|
| 196 |
+
source: "hf"
|
| 197 |
+
repo_id: "xinsir/controlnet-openpose-sdxl-1.0"
|
| 198 |
+
repository_file_path: "diffusion_pytorch_model.safetensors"
|
| 199 |
+
- filename: "controlnet-depth-sdxl-1.0.safetensors"
|
| 200 |
+
source: "hf"
|
| 201 |
+
repo_id: "xinsir/controlnet-depth-sdxl-1.0"
|
| 202 |
+
repository_file_path: "diffusion_pytorch_model.safetensors"
|
| 203 |
+
- filename: "controlnet-scribble-sdxl-1.0.safetensors"
|
| 204 |
+
source: "hf"
|
| 205 |
+
repo_id: "xinsir/controlnet-scribble-sdxl-1.0"
|
| 206 |
+
repository_file_path: "diffusion_pytorch_model.safetensors"
|
| 207 |
+
- filename: "anime-painter.safetensors"
|
| 208 |
+
source: "hf"
|
| 209 |
+
repo_id: "xinsir/anime-painter"
|
| 210 |
+
repository_file_path: "diffusion_pytorch_model.safetensors"
|
| 211 |
+
# SD1.5
|
| 212 |
+
- filename: "control_v11e_sd15_ip2p_fp16.safetensors"
|
| 213 |
+
source: "hf"
|
| 214 |
+
repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
|
| 215 |
+
repository_file_path: "control_v11e_sd15_ip2p_fp16.safetensors"
|
| 216 |
+
- filename: "control_v11e_sd15_shuffle_fp16.safetensors"
|
| 217 |
+
source: "hf"
|
| 218 |
+
repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
|
| 219 |
+
repository_file_path: "control_v11e_sd15_shuffle_fp16.safetensors"
|
| 220 |
+
- filename: "control_v11f1e_sd15_tile_fp16.safetensors"
|
| 221 |
+
source: "hf"
|
| 222 |
+
repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
|
| 223 |
+
repository_file_path: "control_v11f1e_sd15_tile_fp16.safetensors"
|
| 224 |
+
- filename: "control_v11f1p_sd15_depth_fp16.safetensors"
|
| 225 |
+
source: "hf"
|
| 226 |
+
repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
|
| 227 |
+
repository_file_path: "control_v11f1p_sd15_depth_fp16.safetensors"
|
| 228 |
+
- filename: "control_v11p_sd15_canny_fp16.safetensors"
|
| 229 |
+
source: "hf"
|
| 230 |
+
repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
|
| 231 |
+
repository_file_path: "control_v11p_sd15_canny_fp16.safetensors"
|
| 232 |
+
- filename: "control_v11p_sd15_inpaint_fp16.safetensors"
|
| 233 |
+
source: "hf"
|
| 234 |
+
repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
|
| 235 |
+
repository_file_path: "control_v11p_sd15_inpaint_fp16.safetensors"
|
| 236 |
+
- filename: "control_v11p_sd15_lineart_fp16.safetensors"
|
| 237 |
+
source: "hf"
|
| 238 |
+
repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
|
| 239 |
+
repository_file_path: "control_v11p_sd15_lineart_fp16.safetensors"
|
| 240 |
+
- filename: "control_v11p_sd15_mlsd_fp16.safetensors"
|
| 241 |
+
source: "hf"
|
| 242 |
+
repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
|
| 243 |
+
repository_file_path: "control_v11p_sd15_mlsd_fp16.safetensors"
|
| 244 |
+
- filename: "control_v11p_sd15_normalbae_fp16.safetensors"
|
| 245 |
+
source: "hf"
|
| 246 |
+
repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
|
| 247 |
+
repository_file_path: "control_v11p_sd15_normalbae_fp16.safetensors"
|
| 248 |
+
- filename: "control_v11p_sd15_openpose_fp16.safetensors"
|
| 249 |
+
source: "hf"
|
| 250 |
+
repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
|
| 251 |
+
repository_file_path: "control_v11p_sd15_openpose_fp16.safetensors"
|
| 252 |
+
- filename: "control_v11p_sd15_scribble_fp16.safetensors"
|
| 253 |
+
source: "hf"
|
| 254 |
+
repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
|
| 255 |
+
repository_file_path: "control_v11p_sd15_scribble_fp16.safetensors"
|
| 256 |
+
- filename: "control_v11p_sd15_seg_fp16.safetensors"
|
| 257 |
+
source: "hf"
|
| 258 |
+
repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
|
| 259 |
+
repository_file_path: "control_v11p_sd15_seg_fp16.safetensors"
|
| 260 |
+
- filename: "control_v11p_sd15_softedge_fp16.safetensors"
|
| 261 |
+
source: "hf"
|
| 262 |
+
repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
|
| 263 |
+
repository_file_path: "control_v11p_sd15_softedge_fp16.safetensors"
|
| 264 |
+
- filename: "control_v11p_sd15s2_lineart_anime_fp16.safetensors"
|
| 265 |
+
source: "hf"
|
| 266 |
+
repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
|
| 267 |
+
repository_file_path: "control_v11p_sd15s2_lineart_anime_fp16.safetensors"
|
| 268 |
+
- filename: "control_v11u_sd15_tile_fp16.safetensors"
|
| 269 |
+
source: "hf"
|
| 270 |
+
repo_id: "comfyanonymous/ControlNet-v1-1_fp16_safetensors"
|
| 271 |
+
repository_file_path: "control_v11u_sd15_tile_fp16.safetensors"
|
| 272 |
+
diffusion_models:
|
| 273 |
+
# FLUX.2-klein-9B
|
| 274 |
+
- filename: "flux-2-klein-9b-fp8.safetensors"
|
| 275 |
+
source: "hf"
|
| 276 |
+
repo_id: "black-forest-labs/FLUX.2-klein-9b-fp8"
|
| 277 |
+
repository_file_path: "flux-2-klein-9b-fp8.safetensors"
|
| 278 |
+
# FLUX.2-klein-base-9B
|
| 279 |
+
- filename: "flux-2-klein-base-9b-fp8.safetensors"
|
| 280 |
+
source: "hf"
|
| 281 |
+
repo_id: "black-forest-labs/FLUX.2-klein-base-9b-fp8"
|
| 282 |
+
repository_file_path: "flux-2-klein-base-9b-fp8.safetensors"
|
| 283 |
+
# Anima
|
| 284 |
+
- filename: "anima-preview3-base.safetensors"
|
| 285 |
+
source: "hf"
|
| 286 |
+
repo_id: "circlestone-labs/Anima"
|
| 287 |
+
repository_file_path: "split_files/diffusion_models/anima-preview3-base.safetensors"
|
| 288 |
+
- filename: "AnimaYume_tuned_v04.safetensors"
|
| 289 |
+
source: "hf"
|
| 290 |
+
repo_id: "duongve/AnimaYume"
|
| 291 |
+
repository_file_path: "split_files/diffusion_models/AnimaYume_tuned_v04.safetensors"
|
| 292 |
+
# NewBie-Image
|
| 293 |
+
- filename: "NewBie-Image-Exp0.1-bf16.safetensors"
|
| 294 |
+
source: "hf"
|
| 295 |
+
repo_id: "Comfy-Org/NewBie-image-Exp0.1_repackaged"
|
| 296 |
+
repository_file_path: "split_files/diffusion_models/NewBie-Image-Exp0.1-bf16.safetensors"
|
| 297 |
+
# ERNIE-Image
|
| 298 |
+
- filename: "ernie-image.safetensors"
|
| 299 |
+
source: "hf"
|
| 300 |
+
repo_id: "Comfy-Org/ERNIE-Image"
|
| 301 |
+
repository_file_path: "diffusion_models/ernie-image.safetensors"
|
| 302 |
+
- filename: "ernie-image-turbo.safetensors"
|
| 303 |
+
source: "hf"
|
| 304 |
+
repo_id: "Comfy-Org/ERNIE-Image"
|
| 305 |
+
repository_file_path: "diffusion_models/ernie-image-turbo.safetensors"
|
| 306 |
+
# FLUX.2-klein-9B-KV
|
| 307 |
+
- filename: "flux-2-klein-9b-kv-fp8.safetensors"
|
| 308 |
+
source: "hf"
|
| 309 |
+
repo_id: "black-forest-labs/FLUX.2-klein-9b-kv-fp8"
|
| 310 |
+
repository_file_path: "flux-2-klein-9b-kv-fp8.safetensors"
|
| 311 |
+
# FLUX.2-klein-4B
|
| 312 |
+
- filename: "flux-2-klein-4b-fp8.safetensors"
|
| 313 |
+
source: "hf"
|
| 314 |
+
repo_id: "black-forest-labs/FLUX.2-klein-4b-fp8"
|
| 315 |
+
repository_file_path: "flux-2-klein-4b-fp8.safetensors"
|
| 316 |
+
# FLUX.2-klein-base-4B
|
| 317 |
+
- filename: "flux-2-klein-base-4b-fp8.safetensors"
|
| 318 |
+
source: "hf"
|
| 319 |
+
repo_id: "black-forest-labs/FLUX.2-klein-base-4b-fp8"
|
| 320 |
+
repository_file_path: "flux-2-klein-base-4b-fp8.safetensors"
|
| 321 |
+
# FLUX.2-klein-9B
|
| 322 |
+
- filename: "flux-2-klein-9b-fp8.safetensors"
|
| 323 |
+
source: "hf"
|
| 324 |
+
repo_id: "black-forest-labs/FLUX.2-klein-9b-fp8"
|
| 325 |
+
repository_file_path: "flux-2-klein-9b-fp8.safetensors"
|
| 326 |
+
# FLUX.2-klein-base-9B
|
| 327 |
+
- filename: "flux-2-klein-base-9b-fp8.safetensors"
|
| 328 |
+
source: "hf"
|
| 329 |
+
repo_id: "black-forest-labs/FLUX.2-klein-base-9b-fp8"
|
| 330 |
+
repository_file_path: "flux-2-klein-base-9b-fp8.safetensors"
|
| 331 |
+
# FLUX.2-dev
|
| 332 |
- filename: "flux2_dev_fp8mixed.safetensors"
|
| 333 |
source: "hf"
|
| 334 |
repo_id: "Comfy-Org/flux2-dev"
|
| 335 |
repository_file_path: "split_files/diffusion_models/flux2_dev_fp8mixed.safetensors"
|
| 336 |
+
# LongCat-Image
|
| 337 |
+
- filename: "longcat_image_bf16.safetensors"
|
| 338 |
+
source: "hf"
|
| 339 |
+
repo_id: "Comfy-Org/LongCat-Image"
|
| 340 |
+
repository_file_path: "split_files/diffusion_models/longcat_image_bf16.safetensors"
|
| 341 |
+
# Ovis-Image
|
| 342 |
+
- filename: "ovis_image_bf16.safetensors"
|
| 343 |
+
source: "hf"
|
| 344 |
+
repo_id: "Comfy-Org/Ovis-Image"
|
| 345 |
+
repository_file_path: "split_files/diffusion_models/ovis_image_bf16.safetensors"
|
| 346 |
+
# Z-Image
|
| 347 |
+
- filename: "z_image_turbo_bf16.safetensors"
|
| 348 |
+
source: "hf"
|
| 349 |
+
repo_id: "Comfy-Org/z_image_turbo"
|
| 350 |
+
repository_file_path: "split_files/diffusion_models/z_image_turbo_bf16.safetensors"
|
| 351 |
+
- filename: "z_image_bf16.safetensors"
|
| 352 |
+
source: "hf"
|
| 353 |
+
repo_id: "Comfy-Org/z_image"
|
| 354 |
+
repository_file_path: "split_files/diffusion_models/z_image_bf16.safetensors"
|
| 355 |
+
# Qwen-Image
|
| 356 |
+
- filename: "qwen_image_2512_fp8_e4m3fn.safetensors"
|
| 357 |
+
source: "hf"
|
| 358 |
+
repo_id: "Comfy-Org/Qwen-Image_ComfyUI"
|
| 359 |
+
repository_file_path: "split_files/diffusion_models/qwen_image_2512_fp8_e4m3fn.safetensors"
|
| 360 |
+
- filename: "qwen_image_fp8_e4m3fn.safetensors"
|
| 361 |
+
source: "hf"
|
| 362 |
+
repo_id: "Comfy-Org/Qwen-Image_ComfyUI"
|
| 363 |
+
repository_file_path: "split_files/diffusion_models/qwen_image_fp8_e4m3fn.safetensors"
|
| 364 |
+
# Flux.1
|
| 365 |
+
- filename: "flux1-dev-fp8-e4m3fn.safetensors"
|
| 366 |
+
source: "hf"
|
| 367 |
+
repo_id: "Kijai/flux-fp8"
|
| 368 |
+
repository_file_path: "flux1-dev-fp8-e4m3fn.safetensors"
|
| 369 |
+
- filename: "flux1-schnell-fp8-e4m3fn.safetensors"
|
| 370 |
+
source: "hf"
|
| 371 |
+
repo_id: "Kijai/flux-fp8"
|
| 372 |
+
repository_file_path: "flux1-schnell-fp8-e4m3fn.safetensors"
|
| 373 |
+
- filename: "flux1-dev-kontext_fp8_scaled.safetensors"
|
| 374 |
+
source: "hf"
|
| 375 |
+
repo_id: "Comfy-Org/flux1-kontext-dev_ComfyUI"
|
| 376 |
+
repository_file_path: "split_files/diffusion_models/flux1-dev-kontext_fp8_scaled.safetensors"
|
| 377 |
+
- filename: "flux1-krea-dev_fp8_scaled.safetensors"
|
| 378 |
+
source: "hf"
|
| 379 |
+
repo_id: "Comfy-Org/FLUX.1-Krea-dev_ComfyUI"
|
| 380 |
+
repository_file_path: "split_files/diffusion_models/flux1-krea-dev_fp8_scaled.safetensors"
|
| 381 |
+
# HiDream
|
| 382 |
+
- filename: "hidream_i1_dev_fp8.safetensors"
|
| 383 |
+
source: "hf"
|
| 384 |
+
repo_id: "Comfy-Org/HiDream-I1_ComfyUI"
|
| 385 |
+
repository_file_path: "split_files/diffusion_models/hidream_i1_dev_fp8.safetensors"
|
| 386 |
+
- filename: "hidream_i1_fast_fp8.safetensors"
|
| 387 |
+
source: "hf"
|
| 388 |
+
repo_id: "Comfy-Org/HiDream-I1_ComfyUI"
|
| 389 |
+
repository_file_path: "split_files/diffusion_models/hidream_i1_fast_fp8.safetensors"
|
| 390 |
+
- filename: "hidream_i1_full_fp8.safetensors"
|
| 391 |
+
source: "hf"
|
| 392 |
+
repo_id: "Comfy-Org/HiDream-I1_ComfyUI"
|
| 393 |
+
repository_file_path: "split_files/diffusion_models/hidream_i1_full_fp8.safetensors"
|
| 394 |
+
- filename: "hunyuanimage2.1_fp8_e4m3fn.safetensors"
|
| 395 |
+
source: "hf"
|
| 396 |
+
repo_id: "Comfy-Org/HunyuanImage_2.1_ComfyUI"
|
| 397 |
+
repository_file_path: "split_files/diffusion_models/hunyuanimage2.1_fp8_e4m3fn.safetensors"
|
| 398 |
+
- filename: "hunyuanimage2.1_distilled_fp8_e4m3fn.safetensors"
|
| 399 |
+
source: "hf"
|
| 400 |
+
repo_id: "Comfy-Org/HunyuanImage_2.1_ComfyUI"
|
| 401 |
+
repository_file_path: "split_files/diffusion_models/hunyuanimage2.1_distilled_fp8_e4m3fn.safetensors"
|
| 402 |
+
- filename: "hunyuanimage2.1_refiner_fp8_e4m3fn.safetensors"
|
| 403 |
+
source: "hf"
|
| 404 |
+
repo_id: "Comfy-Org/HunyuanImage_2.1_ComfyUI"
|
| 405 |
+
repository_file_path: "split_files/diffusion_models/hunyuanimage2.1_refiner_fp8_e4m3fn.safetensors"
|
| 406 |
+
# Chroma1-Radiance
|
| 407 |
+
- filename: "Chroma1-Radiance-x0-fp8mixed_fullmm-20260104.safetensors"
|
| 408 |
+
source: "hf"
|
| 409 |
+
repo_id: "silveroxides/Chroma1-Radiance-fp8-scaled"
|
| 410 |
+
repository_file_path: "Chroma1-Radiance-x0-fp8mixed_fullmm-20260104.safetensors"
|
| 411 |
+
# Chroma1
|
| 412 |
+
- filename: "Chroma1-HD-Flash_float8_e4m3fn_scaled_learned_topk8_svd.safetensors"
|
| 413 |
+
source: "hf"
|
| 414 |
+
repo_id: "Clybius/Chroma-fp8-scaled"
|
| 415 |
+
repository_file_path: "Chroma1-HD/Chroma1-HD-Flash_float8_e4m3fn_scaled_learned_topk8_svd.safetensors"
|
| 416 |
+
- filename: "Chroma1-HD_float8_e4m3fn_scaled_learned_topk8_svd.safetensors"
|
| 417 |
+
source: "hf"
|
| 418 |
+
repo_id: "Clybius/Chroma-fp8-scaled"
|
| 419 |
+
repository_file_path: "Chroma1-HD/Chroma1-HD_float8_e4m3fn_scaled_learned_topk8_svd.safetensors"
|
| 420 |
+
- filename: "omnigen2_fp16.safetensors"
|
| 421 |
+
source: "hf"
|
| 422 |
+
repo_id: "Comfy-Org/Omnigen2_ComfyUI_repackaged"
|
| 423 |
+
repository_file_path: "split_files/diffusion_models/omnigen2_fp16.safetensors"
|
| 424 |
+
ipadapter:
|
| 425 |
+
# SD3.5
|
| 426 |
+
- filename: "ip-adapter_sd35l_instantx.bin"
|
| 427 |
+
source: "hf"
|
| 428 |
+
repo_id: "InstantX/SD3.5-Large-IP-Adapter"
|
| 429 |
+
repository_file_path: "ip-adapter.bin"
|
| 430 |
+
# SD1.5
|
| 431 |
+
- filename: "ip-adapter_sd15.safetensors"
|
| 432 |
+
source: "hf"
|
| 433 |
+
repo_id: "h94/IP-Adapter"
|
| 434 |
+
repository_file_path: "models/ip-adapter_sd15.safetensors"
|
| 435 |
+
- filename: "ip-adapter_sd15_light_v11.bin"
|
| 436 |
+
source: "hf"
|
| 437 |
+
repo_id: "h94/IP-Adapter"
|
| 438 |
+
repository_file_path: "models/ip-adapter_sd15_light_v11.bin"
|
| 439 |
+
- filename: "ip-adapter-plus_sd15.safetensors"
|
| 440 |
+
source: "hf"
|
| 441 |
+
repo_id: "h94/IP-Adapter"
|
| 442 |
+
repository_file_path: "models/ip-adapter-plus_sd15.safetensors"
|
| 443 |
+
- filename: "ip-adapter-plus-face_sd15.safetensors"
|
| 444 |
+
source: "hf"
|
| 445 |
+
repo_id: "h94/IP-Adapter"
|
| 446 |
+
repository_file_path: "models/ip-adapter-plus-face_sd15.safetensors"
|
| 447 |
+
- filename: "ip-adapter-full-face_sd15.safetensors"
|
| 448 |
+
source: "hf"
|
| 449 |
+
repo_id: "h94/IP-Adapter"
|
| 450 |
+
repository_file_path: "models/ip-adapter-full-face_sd15.safetensors"
|
| 451 |
+
- filename: "ip-adapter_sd15_vit-G.safetensors"
|
| 452 |
+
source: "hf"
|
| 453 |
+
repo_id: "h94/IP-Adapter"
|
| 454 |
+
repository_file_path: "models/ip-adapter_sd15_vit-G.safetensors"
|
| 455 |
+
# SDXL
|
| 456 |
+
- filename: "ip-adapter_sdxl_vit-h.safetensors"
|
| 457 |
+
source: "hf"
|
| 458 |
+
repo_id: "h94/IP-Adapter"
|
| 459 |
+
repository_file_path: "sdxl_models/ip-adapter_sdxl_vit-h.safetensors"
|
| 460 |
+
- filename: "ip-adapter-plus_sdxl_vit-h.safetensors"
|
| 461 |
+
source: "hf"
|
| 462 |
+
repo_id: "h94/IP-Adapter"
|
| 463 |
+
repository_file_path: "sdxl_models/ip-adapter-plus_sdxl_vit-h.safetensors"
|
| 464 |
+
- filename: "ip-adapter-plus-face_sdxl_vit-h.safetensors"
|
| 465 |
+
source: "hf"
|
| 466 |
+
repo_id: "h94/IP-Adapter"
|
| 467 |
+
repository_file_path: "sdxl_models/ip-adapter-plus-face_sdxl_vit-h.safetensors"
|
| 468 |
+
- filename: "ip-adapter_sdxl.safetensors"
|
| 469 |
+
source: "hf"
|
| 470 |
+
repo_id: "h94/IP-Adapter"
|
| 471 |
+
repository_file_path: "sdxl_models/ip-adapter_sdxl.safetensors"
|
| 472 |
+
- filename: "ip-adapter-faceid_sd15.bin"
|
| 473 |
+
source: "hf"
|
| 474 |
+
repo_id: "h94/IP-Adapter-FaceID"
|
| 475 |
+
repository_file_path: "ip-adapter-faceid_sd15.bin"
|
| 476 |
+
- filename: "ip-adapter-faceid-plusv2_sd15.bin"
|
| 477 |
+
source: "hf"
|
| 478 |
+
repo_id: "h94/IP-Adapter-FaceID"
|
| 479 |
+
repository_file_path: "ip-adapter-faceid-plusv2_sd15.bin"
|
| 480 |
+
- filename: "ip-adapter-faceid-portrait-v11_sd15.bin"
|
| 481 |
+
source: "hf"
|
| 482 |
+
repo_id: "h94/IP-Adapter-FaceID"
|
| 483 |
+
repository_file_path: "ip-adapter-faceid-portrait-v11_sd15.bin"
|
| 484 |
+
- filename: "ip-adapter-faceid_sdxl.bin"
|
| 485 |
+
source: "hf"
|
| 486 |
+
repo_id: "h94/IP-Adapter-FaceID"
|
| 487 |
+
repository_file_path: "ip-adapter-faceid_sdxl.bin"
|
| 488 |
+
- filename: "ip-adapter-faceid-plusv2_sdxl.bin"
|
| 489 |
+
source: "hf"
|
| 490 |
+
repo_id: "h94/IP-Adapter-FaceID"
|
| 491 |
+
repository_file_path: "ip-adapter-faceid-plusv2_sdxl.bin"
|
| 492 |
+
- filename: "ip-adapter-faceid-portrait_sdxl.bin"
|
| 493 |
+
source: "hf"
|
| 494 |
+
repo_id: "h94/IP-Adapter-FaceID"
|
| 495 |
+
repository_file_path: "ip-adapter-faceid-portrait_sdxl.bin"
|
| 496 |
+
- filename: "ip-adapter-faceid-portrait_sdxl_unnorm.bin"
|
| 497 |
+
source: "hf"
|
| 498 |
+
repo_id: "h94/IP-Adapter-FaceID"
|
| 499 |
+
repository_file_path: "ip-adapter-faceid-portrait_sdxl_unnorm.bin"
|
| 500 |
+
ipadapter-flux:
|
| 501 |
+
- filename: "ip-adapter.bin"
|
| 502 |
+
source: "hf"
|
| 503 |
+
repo_id: "InstantX/FLUX.1-dev-IP-Adapter"
|
| 504 |
+
repository_file_path: "ip-adapter.bin"
|
| 505 |
+
style_models:
|
| 506 |
+
# FLUX.1-Redux-dev
|
| 507 |
+
- filename: "flux1-redux-dev.safetensors"
|
| 508 |
+
source: "hf"
|
| 509 |
+
repo_id: "black-forest-labs/FLUX.1-Redux-dev"
|
| 510 |
+
repository_file_path: "flux1-redux-dev.safetensors"
|
| 511 |
+
loras:
|
| 512 |
+
# Qwen-Image
|
| 513 |
+
- filename: "Qwen-Image-2512-Lightning-4steps-V1.0-bf16.safetensors"
|
| 514 |
+
source: "hf"
|
| 515 |
+
repo_id: "lightx2v/Qwen-Image-2512-Lightning"
|
| 516 |
+
repository_file_path: "Qwen-Image-2512-Lightning-4steps-V1.0-bf16.safetensors"
|
| 517 |
+
- filename: "Qwen-Image-fp8-e4m3fn-Lightning-4steps-V1.0-bf16.safetensors"
|
| 518 |
+
source: "hf"
|
| 519 |
+
repo_id: "lightx2v/Qwen-Image-Lightning"
|
| 520 |
+
repository_file_path: "Qwen-Image-fp8-e4m3fn-Lightning-4steps-V1.0-bf16.safetensors"
|
| 521 |
+
# SD1.5 FaceID
|
| 522 |
+
- filename: "ip-adapter-faceid_sd15_lora.safetensors"
|
| 523 |
+
source: "hf"
|
| 524 |
+
repo_id: "h94/IP-Adapter-FaceID"
|
| 525 |
+
repository_file_path: "ip-adapter-faceid_sd15_lora.safetensors"
|
| 526 |
+
- filename: "ip-adapter-faceid-plusv2_sd15_lora.safetensors"
|
| 527 |
+
source: "hf"
|
| 528 |
+
repo_id: "h94/IP-Adapter-FaceID"
|
| 529 |
+
repository_file_path: "ip-adapter-faceid-plusv2_sd15_lora.safetensors"
|
| 530 |
+
- filename: "ip-adapter-faceid_sdxl_lora.safetensors"
|
| 531 |
+
source: "hf"
|
| 532 |
+
repo_id: "h94/IP-Adapter-FaceID"
|
| 533 |
+
repository_file_path: "ip-adapter-faceid_sdxl_lora.safetensors"
|
| 534 |
+
- filename: "ip-adapter-faceid-plusv2_sdxl_lora.safetensors"
|
| 535 |
+
source: "hf"
|
| 536 |
+
repo_id: "h94/IP-Adapter-FaceID"
|
| 537 |
+
repository_file_path: "ip-adapter-faceid-plusv2_sdxl_lora.safetensors"
|
| 538 |
+
model_patches:
|
| 539 |
+
# Z-Image
|
| 540 |
+
- filename: "Z-Image-Turbo-Fun-Controlnet-Union-2.1-8steps.safetensors"
|
| 541 |
+
source: "hf"
|
| 542 |
+
repo_id: "alibaba-pai/Z-Image-Turbo-Fun-Controlnet-Union-2.1"
|
| 543 |
+
repository_file_path: "Z-Image-Turbo-Fun-Controlnet-Union-2.1-8steps.safetensors"
|
| 544 |
+
- filename: "Z-Image-Turbo-Fun-Controlnet-Tile-2.1-8steps.safetensors"
|
| 545 |
+
source: "hf"
|
| 546 |
+
repo_id: "alibaba-pai/Z-Image-Turbo-Fun-Controlnet-Union-2.1"
|
| 547 |
+
repository_file_path: "Z-Image-Turbo-Fun-Controlnet-Tile-2.1-8steps.safetensors"
|
| 548 |
+
text_encoders:
|
| 549 |
+
# Anima
|
| 550 |
+
- filename: "qwen_3_06b_base.safetensors"
|
| 551 |
+
source: "hf"
|
| 552 |
+
repo_id: "circlestone-labs/Anima"
|
| 553 |
+
repository_file_path: "split_files/text_encoders/qwen_3_06b_base.safetensors"
|
| 554 |
+
# NewBie-Image
|
| 555 |
+
- filename: "gemma_3_4b_it_bf16.safetensors"
|
| 556 |
+
source: "hf"
|
| 557 |
+
repo_id: "Comfy-Org/NewBie-image-Exp0.1_repackaged"
|
| 558 |
+
repository_file_path: "split_files/text_encoders/gemma_3_4b_it_bf16.safetensors"
|
| 559 |
+
- filename: "jina_clip_v2_bf16.safetensors"
|
| 560 |
+
source: "hf"
|
| 561 |
+
repo_id: "Comfy-Org/NewBie-image-Exp0.1_repackaged"
|
| 562 |
+
repository_file_path: "split_files/text_encoders/jina_clip_v2_bf16.safetensors"
|
| 563 |
+
# ERNIE-Image
|
| 564 |
+
- filename: "ministral-3-3b.safetensors"
|
| 565 |
+
source: "hf"
|
| 566 |
+
repo_id: "Comfy-Org/ERNIE-Image"
|
| 567 |
+
repository_file_path: "text_encoders/ministral-3-3b.safetensors"
|
| 568 |
+
# FLUX.2-klein-4B & base
|
| 569 |
+
- filename: "qwen_3_4b.safetensors"
|
| 570 |
+
source: "hf"
|
| 571 |
+
repo_id: "Comfy-Org/vae-text-encorder-for-flux-klein-4b"
|
| 572 |
+
repository_file_path: "split_files/text_encoders/qwen_3_4b.safetensors"
|
| 573 |
+
# FLUX.2-klein-9B & base
|
| 574 |
+
- filename: "qwen_3_8b_fp8mixed.safetensors"
|
| 575 |
+
source: "hf"
|
| 576 |
+
repo_id: "Comfy-Org/vae-text-encorder-for-flux-klein-9b"
|
| 577 |
+
repository_file_path: "split_files/text_encoders/qwen_3_8b_fp8mixed.safetensors"
|
| 578 |
+
# FLUX.2-dev
|
| 579 |
- filename: "mistral_3_small_flux2_fp8.safetensors"
|
| 580 |
source: "hf"
|
| 581 |
repo_id: "Comfy-Org/flux2-dev"
|
| 582 |
repository_file_path: "split_files/text_encoders/mistral_3_small_flux2_fp8.safetensors"
|
| 583 |
+
# Ovis-Image
|
| 584 |
+
- filename: "ovis_2.5.safetensors"
|
| 585 |
+
source: "hf"
|
| 586 |
+
repo_id: "Comfy-Org/Ovis-Image"
|
| 587 |
+
repository_file_path: "split_files/text_encoders/ovis_2.5.safetensors"
|
| 588 |
+
# Z-Image
|
| 589 |
+
- filename: "qwen_3_4b_fp8_mixed.safetensors"
|
| 590 |
+
source: "hf"
|
| 591 |
+
repo_id: "Comfy-Org/z_image_turbo"
|
| 592 |
+
repository_file_path: "split_files/text_encoders/qwen_3_4b_fp8_mixed.safetensors"
|
| 593 |
+
- filename: "clip_l.safetensors"
|
| 594 |
+
source: "hf"
|
| 595 |
+
repo_id: "comfyanonymous/flux_text_encoders"
|
| 596 |
+
repository_file_path: "clip_l.safetensors"
|
| 597 |
+
- filename: "t5xxl_fp8_e4m3fn_scaled.safetensors"
|
| 598 |
+
source: "hf"
|
| 599 |
+
repo_id: "comfyanonymous/flux_text_encoders"
|
| 600 |
+
repository_file_path: "t5xxl_fp8_e4m3fn_scaled.safetensors"
|
| 601 |
+
- filename: "clip_l_hidream.safetensors"
|
| 602 |
+
source: "hf"
|
| 603 |
+
repo_id: "Comfy-Org/HiDream-I1_ComfyUI"
|
| 604 |
+
repository_file_path: "split_files/text_encoders/clip_l_hidream.safetensors"
|
| 605 |
+
- filename: "clip_g_hidream.safetensors"
|
| 606 |
+
source: "hf"
|
| 607 |
+
repo_id: "Comfy-Org/HiDream-I1_ComfyUI"
|
| 608 |
+
repository_file_path: "split_files/text_encoders/clip_g_hidream.safetensors"
|
| 609 |
+
- filename: "llama_3.1_8b_instruct_fp8_scaled.safetensors"
|
| 610 |
+
source: "hf"
|
| 611 |
+
repo_id: "Comfy-Org/HiDream-I1_ComfyUI"
|
| 612 |
+
repository_file_path: "split_files/text_encoders/llama_3.1_8b_instruct_fp8_scaled.safetensors"
|
| 613 |
+
- filename: "qwen_2.5_vl_7b_fp8_scaled.safetensors"
|
| 614 |
+
source: "hf"
|
| 615 |
+
repo_id: "Comfy-Org/Qwen-Image_ComfyUI"
|
| 616 |
+
repository_file_path: "split_files/text_encoders/qwen_2.5_vl_7b_fp8_scaled.safetensors"
|
| 617 |
+
- filename: "byt5_small_glyphxl_fp16.safetensors"
|
| 618 |
+
source: "hf"
|
| 619 |
+
repo_id: "Comfy-Org/HunyuanImage_2.1_ComfyUI"
|
| 620 |
+
repository_file_path: "split_files/text_encoders/byt5_small_glyphxl_fp16.safetensors"
|
| 621 |
+
- filename: "qwen_2.5_vl_fp16.safetensors"
|
| 622 |
+
source: "hf"
|
| 623 |
+
repo_id: "Comfy-Org/Omnigen2_ComfyUI_repackaged"
|
| 624 |
+
repository_file_path: "split_files/text_encoders/qwen_2.5_vl_fp16.safetensors"
|
| 625 |
+
vae:
|
| 626 |
+
- filename: "qwen_image_vae.safetensors"
|
| 627 |
+
source: "hf"
|
| 628 |
+
repo_id: "Comfy-Org/Qwen-Image_ComfyUI"
|
| 629 |
+
repository_file_path: "split_files/vae/qwen_image_vae.safetensors"
|
| 630 |
+
- filename: "hunyuan_image_2.1_vae_fp16.safetensors"
|
| 631 |
+
source: "hf"
|
| 632 |
+
repo_id: "Comfy-Org/HunyuanImage_2.1_ComfyUI"
|
| 633 |
+
repository_file_path: "split_files/vae/hunyuan_image_2.1_vae_fp16.safetensors"
|
| 634 |
+
- filename: "hunyuan_image_refiner_vae_fp16.safetensors"
|
| 635 |
+
source: "hf"
|
| 636 |
+
repo_id: "Comfy-Org/HunyuanImage_2.1_ComfyUI"
|
| 637 |
+
repository_file_path: "split_files/vae/hunyuan_image_refiner_vae_fp16.safetensors"
|
| 638 |
+
- filename: "ae.safetensors"
|
| 639 |
+
source: "hf"
|
| 640 |
+
repo_id: "Comfy-Org/Lumina_Image_2.0_Repackaged"
|
| 641 |
+
repository_file_path: "split_files/vae/ae.safetensors"
|
| 642 |
- filename: "flux2-vae.safetensors"
|
| 643 |
source: "hf"
|
| 644 |
repo_id: "Comfy-Org/flux2-dev"
|
| 645 |
+
repository_file_path: "split_files/vae/flux2-vae.safetensors"
|
yaml/image_gen_features.yaml
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
default:
|
| 2 |
+
enabled_chains:
|
| 3 |
+
- lora
|
| 4 |
+
- controlnet
|
| 5 |
+
- ipadapter
|
| 6 |
+
- embedding
|
| 7 |
+
- style
|
| 8 |
+
- conditioning
|
| 9 |
+
|
| 10 |
+
ernie-image:
|
| 11 |
+
enabled_chains:
|
| 12 |
+
- lora
|
| 13 |
+
- conditioning
|
| 14 |
+
|
| 15 |
+
flux2:
|
| 16 |
+
enabled_chains:
|
| 17 |
+
- lora
|
| 18 |
+
- conditioning
|
| 19 |
+
- reference_latent
|
| 20 |
+
|
| 21 |
+
flux2-kv:
|
| 22 |
+
enabled_chains:
|
| 23 |
+
- lora
|
| 24 |
+
- conditioning
|
| 25 |
+
- reference_latent
|
| 26 |
+
|
| 27 |
+
z-image:
|
| 28 |
+
enabled_chains:
|
| 29 |
+
- lora
|
| 30 |
+
- conditioning
|
| 31 |
+
- controlnet_model_patch
|
| 32 |
+
|
| 33 |
+
qwen-image:
|
| 34 |
+
enabled_chains:
|
| 35 |
+
- lora
|
| 36 |
+
- controlnet
|
| 37 |
+
- conditioning
|
| 38 |
+
|
| 39 |
+
longcat-image:
|
| 40 |
+
enabled_chains:
|
| 41 |
+
- lora
|
| 42 |
+
- conditioning
|
| 43 |
+
|
| 44 |
+
anima:
|
| 45 |
+
enabled_chains:
|
| 46 |
+
- lora
|
| 47 |
+
- conditioning
|
| 48 |
+
|
| 49 |
+
newbie-image:
|
| 50 |
+
enabled_chains:
|
| 51 |
+
- lora
|
| 52 |
+
- embedding
|
| 53 |
+
- conditioning
|
| 54 |
+
|
| 55 |
+
omnigen2:
|
| 56 |
+
enabled_chains:
|
| 57 |
+
- conditioning
|
| 58 |
+
- reference_latent
|
| 59 |
+
|
| 60 |
+
lumina:
|
| 61 |
+
enabled_chains:
|
| 62 |
+
- lora
|
| 63 |
+
- embedding
|
| 64 |
+
- conditioning
|
| 65 |
+
|
| 66 |
+
ovis-image:
|
| 67 |
+
enabled_chains:
|
| 68 |
+
- conditioning
|
| 69 |
+
|
| 70 |
+
sd35:
|
| 71 |
+
enabled_chains:
|
| 72 |
+
- lora
|
| 73 |
+
- controlnet
|
| 74 |
+
- embedding
|
| 75 |
+
- conditioning
|
| 76 |
+
- sd3_ipadapter
|
| 77 |
+
|
| 78 |
+
sdxl:
|
| 79 |
+
enabled_chains:
|
| 80 |
+
- lora
|
| 81 |
+
- controlnet
|
| 82 |
+
- ipadapter
|
| 83 |
+
- embedding
|
| 84 |
+
- conditioning
|
| 85 |
+
|
| 86 |
+
sd15:
|
| 87 |
+
enabled_chains:
|
| 88 |
+
- lora
|
| 89 |
+
- controlnet
|
| 90 |
+
- ipadapter
|
| 91 |
+
- embedding
|
| 92 |
+
- conditioning
|
| 93 |
+
|
| 94 |
+
flux1:
|
| 95 |
+
enabled_chains:
|
| 96 |
+
- lora
|
| 97 |
+
- controlnet
|
| 98 |
+
- style
|
| 99 |
+
- conditioning
|
| 100 |
+
- flux1_ipadapter
|
| 101 |
+
|
| 102 |
+
hidream:
|
| 103 |
+
enabled_chains:
|
| 104 |
+
- lora
|
| 105 |
+
- conditioning
|
| 106 |
+
|
| 107 |
+
chroma1:
|
| 108 |
+
enabled_chains:
|
| 109 |
+
- conditioning
|
| 110 |
+
|
| 111 |
+
chroma1-radiance:
|
| 112 |
+
enabled_chains:
|
| 113 |
+
- conditioning
|
| 114 |
+
|
| 115 |
+
hunyuanimage:
|
| 116 |
+
enabled_chains:
|
| 117 |
+
- conditioning
|
yaml/injectors.yaml
CHANGED
|
@@ -1,12 +1,36 @@
|
|
| 1 |
injector_definitions:
|
| 2 |
-
|
|
|
|
|
|
|
| 3 |
module: "chain_injectors.lora_injector"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
dynamic_conditioning_chains:
|
| 5 |
module: "chain_injectors.conditioning_injector"
|
| 6 |
dynamic_reference_latent_chains:
|
| 7 |
module: "chain_injectors.reference_latent_injector"
|
| 8 |
|
| 9 |
injector_order:
|
|
|
|
| 10 |
- dynamic_lora_chains
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
- dynamic_reference_latent_chains
|
| 12 |
-
-
|
|
|
|
| 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_diffsynth_controlnet_chains:
|
| 11 |
+
module: "chain_injectors.diffsynth_controlnet_injector"
|
| 12 |
+
dynamic_ipadapter_chains:
|
| 13 |
+
module: "chain_injectors.ipadapter_injector"
|
| 14 |
+
dynamic_flux1_ipadapter_chains:
|
| 15 |
+
module: "chain_injectors.flux1_ipadapter_injector"
|
| 16 |
+
dynamic_sd3_ipadapter_chains:
|
| 17 |
+
module: "chain_injectors.sd3_ipadapter_injector"
|
| 18 |
+
dynamic_style_chains:
|
| 19 |
+
module: "chain_injectors.style_injector"
|
| 20 |
dynamic_conditioning_chains:
|
| 21 |
module: "chain_injectors.conditioning_injector"
|
| 22 |
dynamic_reference_latent_chains:
|
| 23 |
module: "chain_injectors.reference_latent_injector"
|
| 24 |
|
| 25 |
injector_order:
|
| 26 |
+
- dynamic_vae_chains
|
| 27 |
- dynamic_lora_chains
|
| 28 |
+
- dynamic_newbie_lora_chains
|
| 29 |
+
- dynamic_diffsynth_controlnet_chains
|
| 30 |
+
- dynamic_ipadapter_chains
|
| 31 |
+
- dynamic_flux1_ipadapter_chains
|
| 32 |
+
- dynamic_sd3_ipadapter_chains
|
| 33 |
+
- dynamic_style_chains
|
| 34 |
+
- dynamic_conditioning_chains
|
| 35 |
- dynamic_reference_latent_chains
|
| 36 |
+
- dynamic_controlnet_chains
|
yaml/model_architectures.yaml
CHANGED
|
@@ -1,15 +1,79 @@
|
|
| 1 |
architecture_order:
|
|
|
|
| 2 |
- "FLUX.2"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
- "SDXL"
|
| 4 |
- "SD1.5"
|
| 5 |
|
| 6 |
architectures:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
"FLUX.2":
|
| 8 |
model_type: "flux2"
|
| 9 |
controlnet_key: "FLUX.2"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
"SDXL":
|
| 11 |
model_type: "sdxl"
|
| 12 |
controlnet_key: "SDXL"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
"SD1.5":
|
| 14 |
model_type: "sd15"
|
| 15 |
-
controlnet_key: "SD1.5"
|
|
|
|
| 1 |
architecture_order:
|
| 2 |
+
- "FLUX.2-KV"
|
| 3 |
- "FLUX.2"
|
| 4 |
+
- "ERNIE-Image"
|
| 5 |
+
- "Z-Image"
|
| 6 |
+
- "Qwen-Image"
|
| 7 |
+
- "LongCat-Image"
|
| 8 |
+
- "Anima"
|
| 9 |
+
- "NewBie-Image"
|
| 10 |
+
- "Ovis-Image"
|
| 11 |
+
- "HunyuanImage"
|
| 12 |
+
- "Chroma1-Radiance"
|
| 13 |
+
- "Chroma1"
|
| 14 |
+
- "OmniGen2"
|
| 15 |
+
- "Lumina"
|
| 16 |
+
- "HiDream"
|
| 17 |
+
- "FLUX.1"
|
| 18 |
+
- "SD3.5"
|
| 19 |
- "SDXL"
|
| 20 |
- "SD1.5"
|
| 21 |
|
| 22 |
architectures:
|
| 23 |
+
"ERNIE-Image":
|
| 24 |
+
model_type: "ernie-image"
|
| 25 |
+
controlnet_key: "ERNIE-Image"
|
| 26 |
+
"FLUX.2-KV":
|
| 27 |
+
model_type: "flux2-kv"
|
| 28 |
+
controlnet_key: "FLUX.2"
|
| 29 |
"FLUX.2":
|
| 30 |
model_type: "flux2"
|
| 31 |
controlnet_key: "FLUX.2"
|
| 32 |
+
"Z-Image":
|
| 33 |
+
model_type: "z-image"
|
| 34 |
+
controlnet_key: "Z-Image"
|
| 35 |
+
"Qwen-Image":
|
| 36 |
+
model_type: "qwen-image"
|
| 37 |
+
controlnet_key: "Qwen-Image"
|
| 38 |
+
"LongCat-Image":
|
| 39 |
+
model_type: "longcat-image"
|
| 40 |
+
controlnet_key: "LongCat-Image"
|
| 41 |
+
"Anima":
|
| 42 |
+
model_type: "anima"
|
| 43 |
+
controlnet_key: "Anima"
|
| 44 |
+
"Chroma1-Radiance":
|
| 45 |
+
model_type: "chroma1-radiance"
|
| 46 |
+
controlnet_key: "Chroma1-Radiance"
|
| 47 |
+
"Chroma1":
|
| 48 |
+
model_type: "chroma1"
|
| 49 |
+
controlnet_key: "Chroma1"
|
| 50 |
+
"OmniGen2":
|
| 51 |
+
model_type: "omnigen2"
|
| 52 |
+
controlnet_key: "OmniGen2"
|
| 53 |
+
"Lumina":
|
| 54 |
+
model_type: "lumina"
|
| 55 |
+
controlnet_key: "Lumina"
|
| 56 |
+
"Ovis-Image":
|
| 57 |
+
model_type: "ovis-image"
|
| 58 |
+
controlnet_key: "Ovis-Image"
|
| 59 |
+
"HunyuanImage":
|
| 60 |
+
model_type: "hunyuanimage"
|
| 61 |
+
controlnet_key: "HunyuanImage"
|
| 62 |
+
"NewBie-Image":
|
| 63 |
+
model_type: "newbie-image"
|
| 64 |
+
controlnet_key: "NewBie-Image"
|
| 65 |
+
"FLUX.1":
|
| 66 |
+
model_type: "flux1"
|
| 67 |
+
controlnet_key: "FLUX.1"
|
| 68 |
"SDXL":
|
| 69 |
model_type: "sdxl"
|
| 70 |
controlnet_key: "SDXL"
|
| 71 |
+
"SD3.5":
|
| 72 |
+
model_type: "sd35"
|
| 73 |
+
controlnet_key: "SD3.5"
|
| 74 |
+
"HiDream":
|
| 75 |
+
model_type: "hidream"
|
| 76 |
+
controlnet_key: "HiDream"
|
| 77 |
"SD1.5":
|
| 78 |
model_type: "sd15"
|
| 79 |
+
controlnet_key: "SD1.5"
|
yaml/model_defaults.yaml
CHANGED
|
@@ -1,22 +1,206 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Default:
|
| 2 |
+
steps: 25
|
| 3 |
+
cfg: 7.0
|
| 4 |
+
sampler_name: "euler"
|
| 5 |
+
scheduler: "simple"
|
| 6 |
+
total_pixels: 1048576
|
| 7 |
+
positive_prompt: ""
|
| 8 |
+
negative_prompt: ""
|
| 9 |
+
|
| 10 |
+
ERNIE-Image:
|
| 11 |
+
_defaults:
|
| 12 |
+
steps: 20
|
| 13 |
+
cfg: 4.0
|
| 14 |
+
sampler_name: "euler"
|
| 15 |
+
scheduler: "simple"
|
| 16 |
+
total_pixels: 1048576
|
| 17 |
+
"baidu/ERNIE-Image-Turbo":
|
| 18 |
+
steps: 8
|
| 19 |
+
cfg: 1.0
|
| 20 |
+
sampler_name: "euler"
|
| 21 |
+
scheduler: "simple"
|
| 22 |
+
total_pixels: 1048576
|
| 23 |
+
|
| 24 |
+
FLUX.2:
|
| 25 |
+
_defaults:
|
| 26 |
+
steps: 20
|
| 27 |
+
cfg: 4.0
|
| 28 |
+
sampler_name: "euler"
|
| 29 |
+
scheduler: "simple"
|
| 30 |
+
total_pixels: 1048576
|
| 31 |
+
"black-forest-labs/FLUX.2-klein-4B":
|
| 32 |
+
steps: 4
|
| 33 |
+
cfg: 1.0
|
| 34 |
+
"black-forest-labs/FLUX.2-klein-9B":
|
| 35 |
+
steps: 4
|
| 36 |
+
cfg: 1.0
|
| 37 |
+
|
| 38 |
+
FLUX.2-KV:
|
| 39 |
+
_defaults:
|
| 40 |
+
steps: 20
|
| 41 |
+
cfg: 4.0
|
| 42 |
+
sampler_name: "euler"
|
| 43 |
+
scheduler: "simple"
|
| 44 |
+
total_pixels: 1048576
|
| 45 |
+
"black-forest-labs/FLUX.2-klein-9B-KV":
|
| 46 |
+
steps: 4
|
| 47 |
+
cfg: 1.0
|
| 48 |
+
|
| 49 |
+
Z-Image:
|
| 50 |
+
_defaults:
|
| 51 |
+
steps: 25
|
| 52 |
+
cfg: 4.0
|
| 53 |
+
sampler_name: "euler"
|
| 54 |
+
scheduler: "simple"
|
| 55 |
+
total_pixels: 1048576
|
| 56 |
+
"Tongyi-MAI/Z Image Turbo":
|
| 57 |
+
steps: 9
|
| 58 |
+
cfg: 1.0
|
| 59 |
+
sampler_name: "euler"
|
| 60 |
+
scheduler: "simple"
|
| 61 |
+
total_pixels: 1048576
|
| 62 |
+
|
| 63 |
+
Qwen-Image:
|
| 64 |
+
_defaults:
|
| 65 |
+
steps: 4
|
| 66 |
+
cfg: 1.0
|
| 67 |
+
sampler_name: "euler"
|
| 68 |
+
scheduler: "simple"
|
| 69 |
+
total_pixels: 1763584
|
| 70 |
+
|
| 71 |
+
LongCat-Image:
|
| 72 |
+
_defaults:
|
| 73 |
+
steps: 20
|
| 74 |
+
cfg: 4.0
|
| 75 |
+
guidance: 4.0
|
| 76 |
+
sampler_name: "euler"
|
| 77 |
+
scheduler: "simple"
|
| 78 |
+
total_pixels: 1048576
|
| 79 |
+
|
| 80 |
+
Anima:
|
| 81 |
+
_defaults:
|
| 82 |
+
steps: 30
|
| 83 |
+
cfg: 4.0
|
| 84 |
+
sampler_name: "er_sde"
|
| 85 |
+
scheduler: "simple"
|
| 86 |
+
total_pixels: 1048576
|
| 87 |
+
positive_prompt: "masterpiece, best quality, score_7, safe. "
|
| 88 |
+
negative_prompt: "worst quality, low quality, score_1, score_2, score_3, blurry, jpeg artifacts, sepia"
|
| 89 |
+
|
| 90 |
+
NewBie-Image:
|
| 91 |
+
_defaults:
|
| 92 |
+
steps: 20
|
| 93 |
+
cfg: 5.5
|
| 94 |
+
sampler_name: "res_multistep"
|
| 95 |
+
scheduler: "simple"
|
| 96 |
+
positive_prompt: "You are an assistant designed to generate high-quality anime images with the highest degree of image-text alignment based on xml format textual prompts. <Prompt Start>"
|
| 97 |
+
negative_prompt: "You are an assistant designed to generate low-quality images based on textual prompts. <Prompt Start>"
|
| 98 |
+
|
| 99 |
+
Ovis-Image:
|
| 100 |
+
_defaults:
|
| 101 |
+
steps: 20
|
| 102 |
+
cfg: 5.0
|
| 103 |
+
sampler_name: "euler"
|
| 104 |
+
scheduler: "simple"
|
| 105 |
+
total_pixels: 1048576
|
| 106 |
+
|
| 107 |
+
OmniGen2:
|
| 108 |
+
_defaults:
|
| 109 |
+
steps: 20
|
| 110 |
+
cfg: 5.0
|
| 111 |
+
sampler_name: "euler"
|
| 112 |
+
scheduler: "simple"
|
| 113 |
+
total_pixels: 1048576
|
| 114 |
+
positive_prompt: ""
|
| 115 |
+
negative_prompt: ""
|
| 116 |
+
|
| 117 |
+
Chroma1:
|
| 118 |
+
_defaults:
|
| 119 |
+
steps: 30
|
| 120 |
+
cfg: 4.0
|
| 121 |
+
sampler_name: "euler"
|
| 122 |
+
scheduler: "simple"
|
| 123 |
+
total_pixels: 1048576
|
| 124 |
+
negative_prompt: "low quality, bad anatomy, extra digits, missing digits, extra limbs, missing limbs"
|
| 125 |
+
"lodestones/Chroma1-HD-Flash":
|
| 126 |
+
steps: 8
|
| 127 |
+
cfg: 1.0
|
| 128 |
+
scheduler: "beta"
|
| 129 |
+
|
| 130 |
+
Chroma1-Radiance:
|
| 131 |
+
_defaults:
|
| 132 |
+
steps: 30
|
| 133 |
+
cfg: 4.0
|
| 134 |
+
sampler_name: "euler"
|
| 135 |
+
scheduler: "simple"
|
| 136 |
+
total_pixels: 1048576
|
| 137 |
+
negative_prompt: "low quality, bad anatomy, extra digits, missing digits, extra limbs, missing limbs, hands, fingers"
|
| 138 |
+
|
| 139 |
+
SD3.5:
|
| 140 |
+
_defaults:
|
| 141 |
+
steps: 20
|
| 142 |
+
cfg: 4.0
|
| 143 |
+
sampler_name: "euler"
|
| 144 |
+
scheduler: "sgm_uniform"
|
| 145 |
+
total_pixels: 1048576
|
| 146 |
+
|
| 147 |
+
SDXL:
|
| 148 |
+
_defaults:
|
| 149 |
+
steps: 25
|
| 150 |
+
cfg: 7.0
|
| 151 |
+
sampler_name: "euler"
|
| 152 |
+
scheduler: "simple"
|
| 153 |
+
total_pixels: 1048576
|
| 154 |
+
positive_prompt: ""
|
| 155 |
+
negative_prompt: ""
|
| 156 |
+
|
| 157 |
+
SD1.5:
|
| 158 |
+
_defaults:
|
| 159 |
+
steps: 47
|
| 160 |
+
cfg: 7.0
|
| 161 |
+
sampler_name: "euler_ancestral"
|
| 162 |
+
scheduler: "simple"
|
| 163 |
+
total_pixels: 393216
|
| 164 |
+
|
| 165 |
+
FLUX.1:
|
| 166 |
+
_defaults:
|
| 167 |
+
steps: 20
|
| 168 |
+
cfg: 1.0
|
| 169 |
+
sampler_name: "euler"
|
| 170 |
+
scheduler: "simple"
|
| 171 |
+
total_pixels: 1048576
|
| 172 |
+
"flux1-schnell":
|
| 173 |
+
steps: 4
|
| 174 |
+
cfg: 1.0
|
| 175 |
+
sampler_name: "euler"
|
| 176 |
+
scheduler: "simple"
|
| 177 |
+
|
| 178 |
+
HiDream:
|
| 179 |
+
_defaults:
|
| 180 |
+
steps: 50
|
| 181 |
+
cfg: 3.0
|
| 182 |
+
sampler_name: "uni_pc"
|
| 183 |
+
scheduler: "simple"
|
| 184 |
+
total_pixels: 1048576
|
| 185 |
+
negative_prompt: "bad ugly jpeg artifacts"
|
| 186 |
+
"HiDream_i1_Dev":
|
| 187 |
+
steps: 28
|
| 188 |
+
cfg: 1.0
|
| 189 |
+
sampler_name: "lcm"
|
| 190 |
+
scheduler: "normal"
|
| 191 |
+
"HiDream_i1_Fast":
|
| 192 |
+
steps: 16
|
| 193 |
+
cfg: 1.0
|
| 194 |
+
sampler_name: "lcm"
|
| 195 |
+
scheduler: "normal"
|
| 196 |
+
|
| 197 |
+
HunyuanImage:
|
| 198 |
+
_defaults:
|
| 199 |
+
steps: 20
|
| 200 |
+
cfg: 3.5
|
| 201 |
+
sampler_name: "euler"
|
| 202 |
+
scheduler: "simple"
|
| 203 |
+
total_pixels: 4194304
|
| 204 |
+
"HunyuanImage-2.1-Distilled":
|
| 205 |
+
steps: 8
|
| 206 |
+
cfg: 1.0
|
yaml/model_list.yaml
CHANGED
|
@@ -1,20 +1,9 @@
|
|
| 1 |
Checkpoint:
|
| 2 |
-
FLUX.2:
|
| 3 |
latent_type: flux2_latent
|
| 4 |
models:
|
| 5 |
-
- display_name: "
|
| 6 |
components:
|
| 7 |
-
unet: "
|
| 8 |
-
clip: "
|
| 9 |
-
vae: "flux2-vae.safetensors"
|
| 10 |
-
SDXL:
|
| 11 |
-
latent_type: latent
|
| 12 |
-
models:
|
| 13 |
-
- display_name: "stabilityai/SDXL-Base-1.0"
|
| 14 |
-
path: "sd_xl_base_1.0.safetensors"
|
| 15 |
-
category: "Base"
|
| 16 |
-
SD1.5:
|
| 17 |
-
latent_type: latent
|
| 18 |
-
models:
|
| 19 |
-
- display_name: "stable-diffusion-v1-5/stable-diffusion-v1-5"
|
| 20 |
-
path: "v1-5-pruned-emaonly.safetensors"
|
|
|
|
| 1 |
Checkpoint:
|
| 2 |
+
FLUX.2-KV:
|
| 3 |
latent_type: flux2_latent
|
| 4 |
models:
|
| 5 |
+
- display_name: "black-forest-labs/FLUX.2-klein-9B-KV"
|
| 6 |
components:
|
| 7 |
+
unet: "flux-2-klein-9b-kv-fp8.safetensors"
|
| 8 |
+
clip: "qwen_3_8b_fp8mixed.safetensors"
|
| 9 |
+
vae: "flux2-vae.safetensors"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
yaml/private_file_list.yaml
DELETED
|
@@ -1,12 +0,0 @@
|
|
| 1 |
-
file:
|
| 2 |
-
diffusion_models:
|
| 3 |
-
# FLUX.2-klein-9B
|
| 4 |
-
- filename: "flux-2-klein-9b-fp8.safetensors"
|
| 5 |
-
source: "hf"
|
| 6 |
-
repo_id: "black-forest-labs/FLUX.2-klein-9b-fp8"
|
| 7 |
-
repository_file_path: "flux-2-klein-9b-fp8.safetensors"
|
| 8 |
-
# FLUX.2-klein-base-9B
|
| 9 |
-
- filename: "flux-2-klein-base-9b-fp8.safetensors"
|
| 10 |
-
source: "hf"
|
| 11 |
-
repo_id: "black-forest-labs/FLUX.2-klein-base-9b-fp8"
|
| 12 |
-
repository_file_path: "flux-2-klein-base-9b-fp8.safetensors"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|