diff --git "a/app.py" "b/app.py" --- "a/app.py" +++ "b/app.py" @@ -1,299 +1,517 @@ import spaces import os -from argparse import ArgumentParser -from stablepy import ( - Model_Diffusers, - SCHEDULE_TYPE_OPTIONS, - SCHEDULE_PREDICTION_TYPE_OPTIONS, - check_scheduler_compatibility, - TASK_AND_PREPROCESSORS, - FACE_RESTORATION_MODELS, - PROMPT_WEIGHT_OPTIONS_PRIORITY, - scheduler_names, -) -from constants import ( - DIRECTORY_MODELS, - DIRECTORY_LORAS, - DIRECTORY_VAES, - DIRECTORY_EMBEDS, - DIRECTORY_UPSCALERS, - DOWNLOAD_MODEL, - DOWNLOAD_VAE, - DOWNLOAD_LORA, - LOAD_DIFFUSERS_FORMAT_MODEL, - DIFFUSERS_FORMAT_LORAS, - DOWNLOAD_EMBEDS, - CIVITAI_API_KEY, - HF_TOKEN, - TASK_STABLEPY, - TASK_MODEL_LIST, - UPSCALER_DICT_GUI, - UPSCALER_KEYS, - PROMPT_W_OPTIONS, - WARNING_MSG_VAE, - SDXL_TASK, - MODEL_TYPE_TASK, - POST_PROCESSING_SAMPLER, - SUBTITLE_GUI, - HELP_GUI, - EXAMPLES_GUI_HELP, - EXAMPLES_GUI, - RESOURCES, - DIFFUSERS_CONTROLNET_MODEL, - IP_MODELS, - MODE_IP_OPTIONS, - CACHE_HF_ROOT, - CACHE_HF, -) +from stablepy import Model_Diffusers from stablepy.diffusers_vanilla.style_prompt_config import STYLE_NAMES +from stablepy.diffusers_vanilla.constants import FLUX_CN_UNION_MODES import torch import re +from huggingface_hub import HfApi +from stablepy import ( + CONTROLNET_MODEL_IDS, + VALID_TASKS, + T2I_PREPROCESSOR_NAME, + FLASH_LORA, + SCHEDULER_CONFIG_MAP, + scheduler_names, + IP_ADAPTER_MODELS, + IP_ADAPTERS_SD, + IP_ADAPTERS_SDXL, + REPO_IMAGE_ENCODER, + ALL_PROMPT_WEIGHT_OPTIONS, + SD15_TASKS, + SDXL_TASKS, +) import time from PIL import ImageFile -from utils import ( - download_things, - get_model_list, - extract_parameters, - get_my_lora, - get_model_type, - extract_exif_data, - create_mask_now, - download_diffuser_repo, - get_used_storage_gb, - delete_model, - progress_step_bar, - html_template_message, - escape_html, - clear_hf_cache, -) -from image_processor import preprocessor_tab -from datetime import datetime -import gradio as gr -import logging -import diffusers -import warnings -from stablepy import logger -from diffusers import FluxPipeline # import urllib.parse -import subprocess - -IS_ZERO_GPU = bool(os.getenv("SPACES_ZERO_GPU")) -HIDE_API = bool(os.getenv("HIDE_API")) -if IS_ZERO_GPU: - subprocess.run("rm -rf /data-nvme/zerogpu-offload/*", env={}, shell=True) -IS_GPU_MODE = True if IS_ZERO_GPU else (True if torch.cuda.is_available() else False) -img_path = "./images/" -allowed_path = os.path.abspath(img_path) -delete_cache_time = (9600, 9600) if IS_ZERO_GPU else (86400, 86400) ImageFile.LOAD_TRUNCATED_IMAGES = True -torch.backends.cuda.matmul.allow_tf32 = True -# os.environ["PYTORCH_NO_CUDA_MEMORY_CACHING"] = "1" +print(os.getenv("SPACES_ZERO_GPU")) + +# - **Download SD 1.5 Models** +download_model = "https://civitai.com/api/download/models/574369, https://huggingface.co/TechnoByte/MilkyWonderland/resolve/main/milkyWonderland_v40.safetensors" +# - **Download VAEs** +download_vae = "https://huggingface.co/nubby/blessed-sdxl-vae-fp16-fix/resolve/main/sdxl_vae-fp16fix-c-1.1-b-0.5.safetensors?download=true, https://huggingface.co/nubby/blessed-sdxl-vae-fp16-fix/resolve/main/sdxl_vae-fp16fix-blessed.safetensors?download=true, https://huggingface.co/digiplay/VAE/resolve/main/vividReal_v20.safetensors?download=true, https://huggingface.co/fp16-guy/anything_kl-f8-anime2_vae-ft-mse-840000-ema-pruned_blessed_clearvae_fp16_cleaned/resolve/main/vae-ft-mse-840000-ema-pruned_fp16.safetensors?download=true" +# - **Download LoRAs** +download_lora = "https://civitai.com/api/download/models/28907, https://huggingface.co/Leopain/color/resolve/main/Coloring_book_-_LineArt.safetensors, https://civitai.com/api/download/models/135867, https://civitai.com/api/download/models/145907, https://huggingface.co/Linaqruf/anime-detailer-xl-lora/resolve/main/anime-detailer-xl.safetensors?download=true, https://huggingface.co/Linaqruf/style-enhancer-xl-lora/resolve/main/style-enhancer-xl.safetensors?download=true, https://civitai.com/api/download/models/28609, https://huggingface.co/ByteDance/Hyper-SD/resolve/main/Hyper-SD15-8steps-CFG-lora.safetensors?download=true, https://huggingface.co/ByteDance/Hyper-SD/resolve/main/Hyper-SDXL-8steps-CFG-lora.safetensors?download=true" +load_diffusers_format_model = [ + 'stabilityai/stable-diffusion-xl-base-1.0', + 'black-forest-labs/FLUX.1-dev', + 'John6666/blue-pencil-flux1-v021-fp8-flux', + 'John6666/wai-ani-flux-v10forfp8-fp8-flux', + 'John6666/xe-anime-flux-v04-fp8-flux', + 'John6666/lyh-anime-flux-v2a1-fp8-flux', + 'John6666/carnival-unchained-v10-fp8-flux', + 'cagliostrolab/animagine-xl-3.1', + 'John6666/epicrealism-xl-v8kiss-sdxl', + 'misri/epicrealismXL_v7FinalDestination', + 'misri/juggernautXL_juggernautX', + 'misri/zavychromaxl_v80', + 'SG161222/RealVisXL_V4.0', + 'SG161222/RealVisXL_V5.0', + 'misri/newrealityxlAllInOne_Newreality40', + 'eienmojiki/Anything-XL', + 'eienmojiki/Starry-XL-v5.2', + 'gsdf/CounterfeitXL', + 'KBlueLeaf/Kohaku-XL-Zeta', + 'John6666/silvermoon-mix-01xl-v11-sdxl', + 'WhiteAiZ/autismmixSDXL_autismmixConfetti_diffusers', + 'kitty7779/ponyDiffusionV6XL', + 'GraydientPlatformAPI/aniverse-pony', + 'John6666/ras-real-anime-screencap-v1-sdxl', + 'John6666/duchaiten-pony-xl-no-score-v60-sdxl', + 'John6666/mistoon-anime-ponyalpha-sdxl', + 'John6666/3x3x3mixxl-v2-sdxl', + 'John6666/3x3x3mixxl-3dv01-sdxl', + 'John6666/ebara-mfcg-pony-mix-v12-sdxl', + 'John6666/t-ponynai3-v51-sdxl', + 'John6666/t-ponynai3-v65-sdxl', + 'John6666/prefect-pony-xl-v3-sdxl', + 'John6666/mala-anime-mix-nsfw-pony-xl-v5-sdxl', + 'John6666/wai-real-mix-v11-sdxl', + 'John6666/wai-c-v6-sdxl', + 'John6666/iniverse-mix-xl-sfwnsfw-pony-guofeng-v43-sdxl', + 'John6666/photo-realistic-pony-v5-sdxl', + 'John6666/pony-realism-v21main-sdxl', + 'John6666/pony-realism-v22main-sdxl', + 'John6666/cyberrealistic-pony-v63-sdxl', + 'John6666/cyberrealistic-pony-v64-sdxl', + 'GraydientPlatformAPI/realcartoon-pony-diffusion', + 'John6666/nova-anime-xl-pony-v5-sdxl', + 'John6666/autismmix-sdxl-autismmix-pony-sdxl', + 'John6666/aimz-dream-real-pony-mix-v3-sdxl', + 'John6666/duchaiten-pony-real-v11fix-sdxl', + 'John6666/duchaiten-pony-real-v20-sdxl', + 'yodayo-ai/kivotos-xl-2.0', + 'yodayo-ai/holodayo-xl-2.1', + 'yodayo-ai/clandestine-xl-1.0', + 'digiplay/majicMIX_sombre_v2', + 'digiplay/majicMIX_realistic_v6', + 'digiplay/majicMIX_realistic_v7', + 'digiplay/DreamShaper_8', + 'digiplay/BeautifulArt_v1', + 'digiplay/DarkSushi2.5D_v1', + 'digiplay/darkphoenix3D_v1.1', + 'digiplay/BeenYouLiteL11_diffusers', + 'Yntec/RevAnimatedV2Rebirth', + 'youknownothing/cyberrealistic_v50', + 'youknownothing/deliberate-v6', + 'GraydientPlatformAPI/deliberate-cyber3', + 'GraydientPlatformAPI/picx-real', + 'GraydientPlatformAPI/perfectworld6', + 'emilianJR/epiCRealism', + 'votepurchase/counterfeitV30_v30', + 'votepurchase/ChilloutMix', + 'Meina/MeinaMix_V11', + 'Meina/MeinaUnreal_V5', + 'Meina/MeinaPastel_V7', + 'GraydientPlatformAPI/realcartoon3d-17', + 'GraydientPlatformAPI/realcartoon-pixar11', + 'GraydientPlatformAPI/realcartoon-real17', +] + +DIFFUSERS_FORMAT_LORAS = [ + "nerijs/animation2k-flux", + "XLabs-AI/flux-RealismLora", +] + +CIVITAI_API_KEY = os.environ.get("CIVITAI_API_KEY") +HF_TOKEN = os.environ.get("HF_READ_TOKEN") + +PREPROCESSOR_CONTROLNET = { + "openpose": [ + "Openpose", + "None", + ], + "scribble": [ + "HED", + "PidiNet", + "None", + ], + "softedge": [ + "PidiNet", + "HED", + "HED safe", + "PidiNet safe", + "None", + ], + "segmentation": [ + "UPerNet", + "None", + ], + "depth": [ + "DPT", + "Midas", + "None", + ], + "normalbae": [ + "NormalBae", + "None", + ], + "lineart": [ + "Lineart", + "Lineart coarse", + "Lineart (anime)", + "None", + "None (anime)", + ], + "lineart_anime": [ + "Lineart", + "Lineart coarse", + "Lineart (anime)", + "None", + "None (anime)", + ], + "shuffle": [ + "ContentShuffle", + "None", + ], + "canny": [ + "Canny", + "None", + ], + "mlsd": [ + "MLSD", + "None", + ], + "ip2p": [ + "ip2p" + ], + "recolor": [ + "Recolor luminance", + "Recolor intensity", + "None", + ], + "tile": [ + "Mild Blur", + "Moderate Blur", + "Heavy Blur", + "None", + ], + +} + +TASK_STABLEPY = { + 'txt2img': 'txt2img', + 'img2img': 'img2img', + 'inpaint': 'inpaint', + # 'canny T2I Adapter': 'sdxl_canny_t2i', # NO HAVE STEP CALLBACK PARAMETERS SO NOT WORKS WITH DIFFUSERS 0.29.0 + # 'sketch T2I Adapter': 'sdxl_sketch_t2i', + # 'lineart T2I Adapter': 'sdxl_lineart_t2i', + # 'depth-midas T2I Adapter': 'sdxl_depth-midas_t2i', + # 'openpose T2I Adapter': 'sdxl_openpose_t2i', + 'openpose ControlNet': 'openpose', + 'canny ControlNet': 'canny', + 'mlsd ControlNet': 'mlsd', + 'scribble ControlNet': 'scribble', + 'softedge ControlNet': 'softedge', + 'segmentation ControlNet': 'segmentation', + 'depth ControlNet': 'depth', + 'normalbae ControlNet': 'normalbae', + 'lineart ControlNet': 'lineart', + 'lineart_anime ControlNet': 'lineart_anime', + 'shuffle ControlNet': 'shuffle', + 'ip2p ControlNet': 'ip2p', + 'optical pattern ControlNet': 'pattern', + 'recolor ControlNet': 'recolor', + 'tile ControlNet': 'tile', +} + +TASK_MODEL_LIST = list(TASK_STABLEPY.keys()) + +UPSCALER_DICT_GUI = { + None: None, + "Lanczos": "Lanczos", + "Nearest": "Nearest", + 'Latent': 'Latent', + 'Latent (antialiased)': 'Latent (antialiased)', + 'Latent (bicubic)': 'Latent (bicubic)', + 'Latent (bicubic antialiased)': 'Latent (bicubic antialiased)', + 'Latent (nearest)': 'Latent (nearest)', + 'Latent (nearest-exact)': 'Latent (nearest-exact)', + "RealESRGAN_x4plus": "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth", + "RealESRNet_x4plus": "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.1/RealESRNet_x4plus.pth", + "RealESRGAN_x4plus_anime_6B": "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth", + "RealESRGAN_x2plus": "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.1/RealESRGAN_x2plus.pth", + "realesr-animevideov3": "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.5.0/realesr-animevideov3.pth", + "realesr-general-x4v3": "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.5.0/realesr-general-x4v3.pth", + "realesr-general-wdn-x4v3": "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.5.0/realesr-general-wdn-x4v3.pth", + "4x-UltraSharp": "https://huggingface.co/Shandypur/ESRGAN-4x-UltraSharp/resolve/main/4x-UltraSharp.pth", + "4x_foolhardy_Remacri": "https://huggingface.co/FacehugmanIII/4x_foolhardy_Remacri/resolve/main/4x_foolhardy_Remacri.pth", + "Remacri4xExtraSmoother": "https://huggingface.co/hollowstrawberry/upscalers-backup/resolve/main/ESRGAN/Remacri%204x%20ExtraSmoother.pth", + "AnimeSharp4x": "https://huggingface.co/hollowstrawberry/upscalers-backup/resolve/main/ESRGAN/AnimeSharp%204x.pth", + "lollypop": "https://huggingface.co/hollowstrawberry/upscalers-backup/resolve/main/ESRGAN/lollypop.pth", + "RealisticRescaler4x": "https://huggingface.co/hollowstrawberry/upscalers-backup/resolve/main/ESRGAN/RealisticRescaler%204x.pth", + "NickelbackFS4x": "https://huggingface.co/hollowstrawberry/upscalers-backup/resolve/main/ESRGAN/NickelbackFS%204x.pth" +} + +UPSCALER_KEYS = list(UPSCALER_DICT_GUI.keys()) + + +def download_things(directory, url, hf_token="", civitai_api_key=""): + url = url.strip() + + if "drive.google.com" in url: + original_dir = os.getcwd() + os.chdir(directory) + os.system(f"gdown --fuzzy {url}") + os.chdir(original_dir) + elif "huggingface.co" in url: + url = url.replace("?download=true", "") + # url = urllib.parse.quote(url, safe=':/') # fix encoding + if "/blob/" in url: + url = url.replace("/blob/", "/resolve/") + user_header = f'"Authorization: Bearer {hf_token}"' + if hf_token: + os.system(f"aria2c --console-log-level=error --summary-interval=10 --header={user_header} -c -x 16 -k 1M -s 16 {url} -d {directory} -o {url.split('/')[-1]}") + else: + os.system(f"aria2c --optimize-concurrent-downloads --console-log-level=error --summary-interval=10 -c -x 16 -k 1M -s 16 {url} -d {directory} -o {url.split('/')[-1]}") + elif "civitai.com" in url: + if "?" in url: + url = url.split("?")[0] + if civitai_api_key: + url = url + f"?token={civitai_api_key}" + os.system(f"aria2c --console-log-level=error --summary-interval=10 -c -x 16 -k 1M -s 16 -d {directory} {url}") + else: + print("\033[91mYou need an API key to download Civitai models.\033[0m") + else: + os.system(f"aria2c --console-log-level=error --summary-interval=10 -c -x 16 -k 1M -s 16 -d {directory} {url}") -directories = [DIRECTORY_MODELS, DIRECTORY_LORAS, DIRECTORY_VAES, DIRECTORY_EMBEDS, DIRECTORY_UPSCALERS] -for directory in directories: - os.makedirs(directory, exist_ok=True) + +def get_model_list(directory_path): + model_list = [] + valid_extensions = {'.ckpt', '.pt', '.pth', '.safetensors', '.bin'} + + for filename in os.listdir(directory_path): + if os.path.splitext(filename)[1] in valid_extensions: + # name_without_extension = os.path.splitext(filename)[0] + file_path = os.path.join(directory_path, filename) + # model_list.append((name_without_extension, file_path)) + model_list.append(file_path) + print('\033[34mFILE: ' + file_path + '\033[0m') + return model_list + + +directory_models = 'models' +os.makedirs(directory_models, exist_ok=True) +directory_loras = 'loras' +os.makedirs(directory_loras, exist_ok=True) +directory_vaes = 'vaes' +os.makedirs(directory_vaes, exist_ok=True) # Download stuffs -for url in [url.strip() for url in DOWNLOAD_MODEL.split(',')]: - download_things(DIRECTORY_MODELS, url, HF_TOKEN, CIVITAI_API_KEY) -for url in [url.strip() for url in DOWNLOAD_VAE.split(',')]: - download_things(DIRECTORY_VAES, url, HF_TOKEN, CIVITAI_API_KEY) -for url in [url.strip() for url in DOWNLOAD_LORA.split(',')]: - download_things(DIRECTORY_LORAS, url, HF_TOKEN, CIVITAI_API_KEY) +for url in [url.strip() for url in download_model.split(',')]: + if not os.path.exists(f"./models/{url.split('/')[-1]}"): + download_things(directory_models, url, HF_TOKEN, CIVITAI_API_KEY) +for url in [url.strip() for url in download_vae.split(',')]: + if not os.path.exists(f"./vaes/{url.split('/')[-1]}"): + download_things(directory_vaes, url, HF_TOKEN, CIVITAI_API_KEY) +for url in [url.strip() for url in download_lora.split(',')]: + if not os.path.exists(f"./loras/{url.split('/')[-1]}"): + download_things(directory_loras, url, HF_TOKEN, CIVITAI_API_KEY) # Download Embeddings -for url_embed in DOWNLOAD_EMBEDS: - download_things(DIRECTORY_EMBEDS, url_embed, HF_TOKEN, CIVITAI_API_KEY) +directory_embeds = 'embedings' +os.makedirs(directory_embeds, exist_ok=True) +download_embeds = [ + 'https://huggingface.co/datasets/Nerfgun3/bad_prompt/blob/main/bad_prompt_version2.pt', + 'https://huggingface.co/embed/negative/resolve/main/EasyNegativeV2.safetensors', + 'https://huggingface.co/embed/negative/resolve/main/bad-hands-5.pt', + ] + +for url_embed in download_embeds: + if not os.path.exists(f"./embedings/{url_embed.split('/')[-1]}"): + download_things(directory_embeds, url_embed, HF_TOKEN, CIVITAI_API_KEY) # Build list models -embed_list = get_model_list(DIRECTORY_EMBEDS) -embed_list = [ - (os.path.splitext(os.path.basename(emb))[0], emb) for emb in embed_list -] -single_file_model_list = get_model_list(DIRECTORY_MODELS) -model_list = LOAD_DIFFUSERS_FORMAT_MODEL + single_file_model_list -lora_model_list = get_model_list(DIRECTORY_LORAS) +embed_list = get_model_list(directory_embeds) +model_list = get_model_list(directory_models) +model_list = load_diffusers_format_model + model_list +lora_model_list = get_model_list(directory_loras) lora_model_list.insert(0, "None") lora_model_list = lora_model_list + DIFFUSERS_FORMAT_LORAS -vae_model_list = get_model_list(DIRECTORY_VAES) -vae_model_list.insert(0, "BakedVAE") +vae_model_list = get_model_list(directory_vaes) vae_model_list.insert(0, "None") print('\033[33m🏁 Download and listing of valid models completed.\033[0m') -components = None -if IS_ZERO_GPU: - flux_repo = "camenduru/FLUX.1-dev-diffusers" - flux_pipe = FluxPipeline.from_pretrained( - flux_repo, - transformer=None, - torch_dtype=torch.bfloat16, - ).to("cuda") - components = flux_pipe.components - delete_model(flux_repo) - ####################### # GUI ####################### +import gradio as gr +import logging logging.getLogger("diffusers").setLevel(logging.ERROR) +import diffusers diffusers.utils.logging.set_verbosity(40) +import warnings warnings.filterwarnings(action="ignore", category=FutureWarning, module="diffusers") warnings.filterwarnings(action="ignore", category=UserWarning, module="diffusers") warnings.filterwarnings(action="ignore", category=FutureWarning, module="transformers") +from stablepy import logger -parser = ArgumentParser(description='DiffuseCraft: Create images from text prompts.', add_help=True) -parser.add_argument("--share", action="store_true", dest="share_enabled", default=False, help="Enable sharing") -parser.add_argument('--theme', type=str, default="NoCrypt/miku", help='Set the theme (default: NoCrypt/miku)') -parser.add_argument("--ssr", action="store_true", help="Enable SSR (Server-Side Rendering)") -parser.add_argument("--log-level", type=str, default="INFO", choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], help="Set logging level (default: INFO)") -args = parser.parse_args() +logger.setLevel(logging.DEBUG) -logger.setLevel( - "INFO" if IS_ZERO_GPU else getattr(logging, args.log_level.upper()) +msg_inc_vae = ( + "Use the right VAE for your model to maintain image quality. The wrong" + " VAE can lead to poor results, like blurriness in the generated images." ) +SDXL_TASK = [k for k, v in TASK_STABLEPY.items() if v in SDXL_TASKS] +SD_TASK = [k for k, v in TASK_STABLEPY.items() if v in SD15_TASKS] +FLUX_TASK = list(TASK_STABLEPY.keys())[:3] + [k for k, v in TASK_STABLEPY.items() if v in FLUX_CN_UNION_MODES.keys()] + +MODEL_TYPE_TASK = { + "SD 1.5": SD_TASK, + "SDXL": SDXL_TASK, + "FLUX": FLUX_TASK, +} + +MODEL_TYPE_CLASS = { + "diffusers:StableDiffusionPipeline": "SD 1.5", + "diffusers:StableDiffusionXLPipeline": "SDXL", + "diffusers:FluxPipeline": "FLUX", +} + +POST_PROCESSING_SAMPLER = ["Use same sampler"] + scheduler_names[:-2] + CSS = """ .contain { display: flex; flex-direction: column; } #component-0 { height: 100%; } #gallery { flex-grow: 1; } -#load_model { height: 50px; } """ +SUBTITLE_GUI = ( + "### This demo uses [diffusers](https://github.com/huggingface/diffusers)" + " to perform different tasks in image generation." +) -def lora_chk(lora_): - if isinstance(lora_, str) and lora_.strip() not in ["", "None"]: - return lora_ - return None + +def extract_parameters(input_string): + parameters = {} + input_string = input_string.replace("\n", "") + + if "Negative prompt:" not in input_string: + if "Steps:" in input_string: + input_string = input_string.replace("Steps:", "Negative prompt: Steps:") + else: + print("Invalid metadata") + parameters["prompt"] = input_string + return parameters + + parm = input_string.split("Negative prompt:") + parameters["prompt"] = parm[0].strip() + if "Steps:" not in parm[1]: + print("Steps not detected") + parameters["neg_prompt"] = parm[1].strip() + return parameters + parm = parm[1].split("Steps:") + parameters["neg_prompt"] = parm[0].strip() + input_string = "Steps:" + parm[1] + + # Extracting Steps + steps_match = re.search(r'Steps: (\d+)', input_string) + if steps_match: + parameters['Steps'] = int(steps_match.group(1)) + + # Extracting Size + size_match = re.search(r'Size: (\d+x\d+)', input_string) + if size_match: + parameters['Size'] = size_match.group(1) + width, height = map(int, parameters['Size'].split('x')) + parameters['width'] = width + parameters['height'] = height + + # Extracting other parameters + other_parameters = re.findall(r'(\w+): (.*?)(?=, \w+|$)', input_string) + for param in other_parameters: + parameters[param[0]] = param[1].strip('"') + + return parameters + + +def get_my_lora(link_url): + for url in [url.strip() for url in link_url.split(',')]: + if not os.path.exists(f"./loras/{url.split('/')[-1]}"): + download_things(directory_loras, url, HF_TOKEN, CIVITAI_API_KEY) + new_lora_model_list = get_model_list(directory_loras) + new_lora_model_list.insert(0, "None") + new_lora_model_list = new_lora_model_list + DIFFUSERS_FORMAT_LORAS + + return gr.update( + choices=new_lora_model_list + ), gr.update( + choices=new_lora_model_list + ), gr.update( + choices=new_lora_model_list + ), gr.update( + choices=new_lora_model_list + ), gr.update( + choices=new_lora_model_list + ), + + +def info_html(json_data, title, subtitle): + return f""" +
+

{title}

+
+ Details +

{subtitle}

+
+
+ """ + + +def get_model_type(repo_id: str): + api = HfApi(token=os.environ.get("HF_TOKEN")) # if use private or gated model + default = "SD 1.5" + try: + model = api.model_info(repo_id=repo_id, timeout=5.0) + tags = model.tags + for tag in tags: + if tag in MODEL_TYPE_CLASS.keys(): return MODEL_TYPE_CLASS.get(tag, default) + except Exception: + return default + return default class GuiSD: def __init__(self, stream=True): self.model = None - self.status_loading = False - self.sleep_loading = 4 - self.last_load = datetime.now() - self.inventory = [] - - def update_storage_models(self, storage_floor_gb=30, required_inventory_for_purge=3): - while get_used_storage_gb() > storage_floor_gb: - if len(self.inventory) < required_inventory_for_purge: - break - removal_candidate = self.inventory.pop(0) - delete_model(removal_candidate) - - # Cleanup after 60 seconds of inactivity - lowPrioCleanup = max((datetime.now() - self.last_load).total_seconds(), 0) > 60 - if lowPrioCleanup and (len(self.inventory) >= required_inventory_for_purge - 1) and not self.status_loading and get_used_storage_gb(CACHE_HF_ROOT) > (storage_floor_gb * 2): - print("Cleaning up Hugging Face cache...") - clear_hf_cache() - self.inventory = [ - m for m in self.inventory if os.path.exists(m) - ] - - def update_inventory(self, model_name): - if model_name not in single_file_model_list: - self.inventory = [ - m for m in self.inventory if m != model_name - ] + [model_name] - print(self.inventory) - - def load_new_model(self, model_name, vae_model, task, controlnet_model, progress=gr.Progress(track_tqdm=True)): - - # download link model > model_name - if model_name.startswith("http"): - yield f"Downloading model: {model_name}" - model_name = download_things(DIRECTORY_MODELS, model_name, HF_TOKEN, CIVITAI_API_KEY) - if not model_name: - raise ValueError("Error retrieving model information from URL") - - if IS_ZERO_GPU: - self.update_storage_models() - - vae_model = vae_model if vae_model != "None" else None - model_type = get_model_type(model_name) - dtype_model = torch.bfloat16 if model_type == "FLUX" else torch.float16 - - if not os.path.exists(model_name): - logger.debug(f"model_name={model_name}, vae_model={vae_model}, task={task}, controlnet_model={controlnet_model}") - _ = download_diffuser_repo( - repo_name=model_name, - model_type=model_type, - revision="main", - token=True, - ) - - self.update_inventory(model_name) - for i in range(68): - if not self.status_loading: - self.status_loading = True - if i > 0: - time.sleep(self.sleep_loading) - print("Previous model ops...") - break - time.sleep(0.5) - print(f"Waiting queue {i}") - yield "Waiting queue" + print("Loading model...") + self.model = Model_Diffusers( + base_model_id="Lykon/dreamshaper-8", + task_name="txt2img", + vae_model=None, + type_model_precision=torch.float16, + retain_task_model_in_cache=False, + device="cpu", + ) + self.model.load_beta_styles() - self.status_loading = True + def load_new_model(self, model_name, vae_model, task, progress=gr.Progress(track_tqdm=True)): yield f"Loading model: {model_name}" - if vae_model == "BakedVAE": - vae_model = model_name - elif vae_model: + vae_model = vae_model if vae_model != "None" else None + model_type = get_model_type(model_name) + + if vae_model: vae_type = "SDXL" if "sdxl" in vae_model.lower() else "SD 1.5" if model_type != vae_type: - gr.Warning(WARNING_MSG_VAE) - - print("Loading model...") - - try: - start_time = time.time() - - if self.model is None: - self.model = Model_Diffusers( - base_model_id=model_name, - task_name=TASK_STABLEPY[task], - vae_model=vae_model, - type_model_precision=dtype_model, - retain_task_model_in_cache=False, - controlnet_model=controlnet_model, - device="cpu" if IS_ZERO_GPU else None, - env_components=components, - ) - self.model.advanced_params(image_preprocessor_cuda_active=IS_GPU_MODE) - else: - if self.model.base_model_id != model_name: - load_now_time = datetime.now() - elapsed_time = max((load_now_time - self.last_load).total_seconds(), 0) - - if elapsed_time <= 9: - print("Waiting for the previous model's time ops...") - time.sleep(9 - elapsed_time) - - if IS_ZERO_GPU: - self.model.device = torch.device("cpu") - self.model.load_pipe( - model_name, - task_name=TASK_STABLEPY[task], - vae_model=vae_model, - type_model_precision=dtype_model, - retain_task_model_in_cache=False, - controlnet_model=controlnet_model, - ) + gr.Warning(msg_inc_vae) - end_time = time.time() - self.sleep_loading = max(min(int(end_time - start_time), 10), 4) - except Exception as e: - self.last_load = datetime.now() - self.status_loading = False - self.sleep_loading = 4 - raise e + self.model.device = torch.device("cpu") + dtype_model = torch.bfloat16 if model_type == "FLUX" else torch.float16 - self.last_load = datetime.now() - self.status_loading = False + self.model.load_pipe( + model_name, + task_name=TASK_STABLEPY[task], + vae_model=vae_model, + type_model_precision=dtype_model, + retain_task_model_in_cache=False, + ) yield f"Model loaded: {model_name}" @@ -318,13 +536,7 @@ class GuiSD: lora_scale4, lora5, lora_scale5, - lora6, - lora_scale6, - lora7, - lora_scale7, sampler, - schedule_type, - schedule_prediction_type, img_height, img_width, model_name, @@ -342,8 +554,6 @@ class GuiSD: high_threshold, value_threshold, distance_threshold, - recolor_gamma_correction, - tile_blur_sigma, controlnet_output_scaling_in_unet, controlnet_start_threshold, controlnet_stop_threshold, @@ -351,8 +561,8 @@ class GuiSD: syntax_weights, upscaler_model_path, upscaler_increases_size, - upscaler_tile_size, - upscaler_tile_overlap, + esrgan_tile, + esrgan_tile_overlap, hires_steps, hires_denoising_strength, hires_sampler, @@ -360,16 +570,12 @@ class GuiSD: hires_negative_prompt, hires_before_adetailer, hires_after_adetailer, - hires_schedule_type, - hires_guidance_scale, - controlnet_model, loop_generation, leave_progress_bar, disable_progress_bar, image_previews, display_images, save_generated_images, - filename_pattern, image_storage_location, retain_compel_previous_load, retain_detailfix_model_previous_load, @@ -377,7 +583,7 @@ class GuiSD: t2i_adapter_preprocessor, t2i_adapter_conditioning_scale, t2i_adapter_conditioning_factor, - enable_live_preview, + xformers_memory_efficient_attention, freeu, generator_in_cpu, adetailer_inpaint_only, @@ -404,7 +610,6 @@ class GuiSD: mask_blur_b, mask_padding_b, retain_task_cache_gui, - guidance_rescale, image_ip1, mask_ip1, model_ip1, @@ -416,19 +621,14 @@ class GuiSD: mode_ip2, scale_ip2, pag_scale, - face_restoration_model, - face_restoration_visibility, - face_restoration_weight, ): - info_state = html_template_message("Navigating latent space...") - yield info_state, gr.update(), gr.update() vae_model = vae_model if vae_model != "None" else None - loras_list = [lora1, lora2, lora3, lora4, lora5, lora6, lora7] + loras_list = [lora1, lora2, lora3, lora4, lora5] vae_msg = f"VAE: {vae_model}" if vae_model else "" msg_lora = "" - logger.debug(f"Config model: {model_name}, {vae_model}, {loras_list}") + print("Config model:", model_name, vae_model, loras_list) task = TASK_STABLEPY[task] @@ -443,34 +643,35 @@ class GuiSD: (image_ip2, mask_ip2, model_ip2, mode_ip2, scale_ip2), ] - if not hasattr(self.model.pipe, "transformer"): - for imgip, mskip, modelip, modeip, scaleip in all_adapters: - if imgip: - params_ip_img.append(imgip) - if mskip: - params_ip_msk.append(mskip) - params_ip_model.append(modelip) - params_ip_mode.append(modeip) - params_ip_scale.append(scaleip) + for imgip, mskip, modelip, modeip, scaleip in all_adapters: + if imgip: + params_ip_img.append(imgip) + if mskip: + params_ip_msk.append(mskip) + params_ip_model.append(modelip) + params_ip_mode.append(modeip) + params_ip_scale.append(scaleip) - concurrency = 5 - self.model.stream_config(concurrency=concurrency, latent_resize_by=1, vae_decoding=False) + self.model.stream_config(concurrency=5, latent_resize_by=1, vae_decoding=False) if task != "txt2img" and not image_control: - raise ValueError("Reference image is required. Please upload one in 'Image ControlNet/Inpaint/Img2img'.") + raise ValueError("No control image found: To use this function, you have to upload an image in 'Image ControlNet/Inpaint/Img2img'") - if task in ["inpaint", "repaint"] and not image_mask: - raise ValueError("Mask image not found. Upload one in 'Image Mask' to proceed.") + if task == "inpaint" and not image_mask: + raise ValueError("No mask image found: Specify one in 'Image Mask'") - if "https://" not in str(UPSCALER_DICT_GUI[upscaler_model_path]): + if upscaler_model_path in UPSCALER_KEYS[:9]: upscaler_model = upscaler_model_path else: + directory_upscalers = 'upscalers' + os.makedirs(directory_upscalers, exist_ok=True) + url_upscaler = UPSCALER_DICT_GUI[upscaler_model_path] - if not os.path.exists(f"./{DIRECTORY_UPSCALERS}/{url_upscaler.split('/')[-1]}"): - download_things(DIRECTORY_UPSCALERS, url_upscaler, HF_TOKEN) + if not os.path.exists(f"./upscalers/{url_upscaler.split('/')[-1]}"): + download_things(directory_upscalers, url_upscaler, HF_TOKEN) - upscaler_model = f"./{DIRECTORY_UPSCALERS}/{url_upscaler.split('/')[-1]}" + upscaler_model = f"./upscalers/{url_upscaler.split('/')[-1]}" logging.getLogger("ultralytics").setLevel(logging.INFO if adetailer_verbose else logging.ERROR) @@ -524,28 +725,20 @@ class GuiSD: "high_threshold": high_threshold, "value_threshold": value_threshold, "distance_threshold": distance_threshold, - "recolor_gamma_correction": float(recolor_gamma_correction), - "tile_blur_sigma": int(tile_blur_sigma), - "lora_A": lora_chk(lora1), + "lora_A": lora1 if lora1 != "None" else None, "lora_scale_A": lora_scale1, - "lora_B": lora_chk(lora2), + "lora_B": lora2 if lora2 != "None" else None, "lora_scale_B": lora_scale2, - "lora_C": lora_chk(lora3), + "lora_C": lora3 if lora3 != "None" else None, "lora_scale_C": lora_scale3, - "lora_D": lora_chk(lora4), + "lora_D": lora4 if lora4 != "None" else None, "lora_scale_D": lora_scale4, - "lora_E": lora_chk(lora5), + "lora_E": lora5 if lora5 != "None" else None, "lora_scale_E": lora_scale5, - "lora_F": lora_chk(lora6), - "lora_scale_F": lora_scale6, - "lora_G": lora_chk(lora7), - "lora_scale_G": lora_scale7, - "textual_inversion": embed_list if textual_inversion else [], + "textual_inversion": embed_list if textual_inversion and self.model.class_name != "StableDiffusionXLPipeline" else [], "syntax_weights": syntax_weights, # "Classic" "sampler": sampler, - "schedule_type": schedule_type, - "schedule_prediction_type": schedule_prediction_type, - "xformers_memory_efficient_attention": False, + "xformers_memory_efficient_attention": xformers_memory_efficient_attention, "gui_active": True, "loop_generation": loop_generation, "controlnet_conditioning_scale": float(controlnet_output_scaling_in_unet), @@ -560,9 +753,8 @@ class GuiSD: "leave_progress_bar": leave_progress_bar, "disable_progress_bar": disable_progress_bar, "image_previews": image_previews, - "display_images": False, + "display_images": display_images, "save_generated_images": save_generated_images, - "filename_pattern": filename_pattern, "image_storage_location": image_storage_location, "retain_compel_previous_load": retain_compel_previous_load, "retain_detailfix_model_previous_load": retain_detailfix_model_previous_load, @@ -572,8 +764,8 @@ class GuiSD: "t2i_adapter_conditioning_factor": float(t2i_adapter_conditioning_factor), "upscaler_model_path": upscaler_model, "upscaler_increases_size": upscaler_increases_size, - "upscaler_tile_size": upscaler_tile_size, - "upscaler_tile_overlap": upscaler_tile_overlap, + "esrgan_tile": esrgan_tile, + "esrgan_tile_overlap": esrgan_tile_overlap, "hires_steps": hires_steps, "hires_denoising_strength": hires_denoising_strength, "hires_prompt": hires_prompt, @@ -581,41 +773,25 @@ class GuiSD: "hires_sampler": hires_sampler, "hires_before_adetailer": hires_before_adetailer, "hires_after_adetailer": hires_after_adetailer, - "hires_schedule_type": hires_schedule_type, - "hires_guidance_scale": hires_guidance_scale, "ip_adapter_image": params_ip_img, "ip_adapter_mask": params_ip_msk, "ip_adapter_model": params_ip_model, "ip_adapter_mode": params_ip_mode, "ip_adapter_scale": params_ip_scale, - "face_restoration_model": face_restoration_model, - "face_restoration_visibility": face_restoration_visibility, - "face_restoration_weight": face_restoration_weight, } - # kwargs for diffusers pipeline - if guidance_rescale: - pipe_params["guidance_rescale"] = guidance_rescale - if IS_ZERO_GPU: - self.model.device = torch.device("cuda:0") - if hasattr(self.model.pipe, "transformer") and loras_list != ["None"] * self.model.num_loras: - self.model.pipe.transformer.to(self.model.device) - logger.debug("transformer to cuda") - - actual_progress = 0 - info_images = gr.update() - for img, [seed, image_path, metadata] in self.model(**pipe_params): - info_state = progress_step_bar(actual_progress, steps) - actual_progress += concurrency + self.model.device = torch.device("cuda:0") + if hasattr(self.model.pipe, "transformer") and loras_list != ["None"] * 5: + self.model.pipe.transformer.to(self.model.device) + print("transformer to cuda") + + info_state = "PROCESSING " + for img, seed, image_path, metadata in self.model(**pipe_params): + info_state += ">" if image_path: - info_images = f"Seeds: {str(seed)}" + info_state = f"COMPLETE. Seeds: {str(seed)}" if vae_msg: - info_images = info_images + "
" + vae_msg - - if "Cannot copy out of meta tensor; no data!" in self.model.last_lora_error: - msg_ram = "Unable to process the LoRAs due to high RAM usage; please try again later." - print(msg_ram) - msg_lora += f"
{msg_ram}" + info_state = info_state + "
" + vae_msg for status, lora in zip(self.model.lora_status, self.model.lora_memory): if status: @@ -624,32 +800,33 @@ class GuiSD: msg_lora += f"
Error with: {lora}" if msg_lora: - info_images += msg_lora + info_state += msg_lora - info_images = info_images + "
" + "GENERATION DATA:
" + escape_html(metadata[-1]) + "
-------
" + info_state = info_state + "
" + "GENERATION DATA:
" + metadata[0].replace("\n", "
") + "
-------
" download_links = "
".join( [ - f'Download Image {i + 1}' + f'Download Image {i + 1}' for i, path in enumerate(image_path) ] ) if save_generated_images: - info_images += f"
{download_links}" + info_state += f"
{download_links}" + + yield img, info_state - if not display_images: - img = gr.update() - info_state = "COMPLETE" - elif not enable_live_preview: - img = gr.update() +def update_task_options(model_name, task_name): + new_choices = MODEL_TYPE_TASK[get_model_type(model_name)] - yield info_state, img, info_images + if task_name not in new_choices: + task_name = "txt2img" + + return gr.update(value=task_name, choices=new_choices) def dynamic_gpu_duration(func, duration, *args): - # @torch.inference_mode() @spaces.GPU(duration=duration) def wrapped_func(): yield from func(*args) @@ -663,44 +840,35 @@ def dummy_gpu(): def sd_gen_generate_pipeline(*args): + gpu_duration_arg = int(args[-1]) if args[-1] else 59 verbose_arg = int(args[-2]) load_lora_cpu = args[-3] generation_args = args[:-3] lora_list = [ None if item == "None" else item - for item in [args[7], args[9], args[11], args[13], args[15], args[17], args[19]] + for item in [args[7], args[9], args[11], args[13], args[15]] ] - lora_status = [None] * sd_gen.model.num_loras + lora_status = [None] * 5 msg_load_lora = "Updating LoRAs in GPU..." if load_lora_cpu: - msg_load_lora = "Updating LoRAs in CPU..." + msg_load_lora = "Updating LoRAs in CPU (Slow but saves GPU usage)..." - if lora_list != sd_gen.model.lora_memory and lora_list != [None] * sd_gen.model.num_loras: - yield msg_load_lora, gr.update(), gr.update() + if lora_list != sd_gen.model.lora_memory and lora_list != [None] * 5: + yield None, msg_load_lora # Load lora in CPU if load_lora_cpu: - lora_status = sd_gen.model.load_lora_on_the_fly( + lora_status = sd_gen.model.lora_merge( lora_A=lora_list[0], lora_scale_A=args[8], lora_B=lora_list[1], lora_scale_B=args[10], lora_C=lora_list[2], lora_scale_C=args[12], lora_D=lora_list[3], lora_scale_D=args[14], lora_E=lora_list[4], lora_scale_E=args[16], - lora_F=lora_list[5], lora_scale_F=args[18], - lora_G=lora_list[6], lora_scale_G=args[20], ) print(lora_status) - sampler_name = args[21] - schedule_type_name = args[22] - _, _, msg_sampler = check_scheduler_compatibility( - sd_gen.model.class_name, sampler_name, schedule_type_name - ) - if msg_sampler: - gr.Warning(msg_sampler) - if verbose_arg: for status, lora in zip(lora_status, lora_list): if status: @@ -708,21 +876,20 @@ def sd_gen_generate_pipeline(*args): elif status is not None: gr.Warning(f"Failed to load LoRA: {lora}") - if lora_status == [None] * sd_gen.model.num_loras and sd_gen.model.lora_memory != [None] * sd_gen.model.num_loras and load_lora_cpu: + if lora_status == [None] * 5 and sd_gen.model.lora_memory != [None] * 5 and load_lora_cpu: lora_cache_msg = ", ".join( str(x) for x in sd_gen.model.lora_memory if x is not None ) gr.Info(f"LoRAs in cache: {lora_cache_msg}") - msg_request = f"Requesting {gpu_duration_arg}s. of GPU time.\nModel: {sd_gen.model.base_model_id}" - if verbose_arg: + msg_request = f"Requesting {gpu_duration_arg}s. of GPU time" gr.Info(msg_request) print(msg_request) - yield msg_request.replace("\n", "
"), gr.update(), gr.update() + + # yield from sd_gen.generate_pipeline(*generation_args) start_time = time.time() - # yield from sd_gen.generate_pipeline(*generation_args) yield from dynamic_gpu_duration( sd_gen.generate_pipeline, gpu_duration_arg, @@ -730,52 +897,60 @@ def sd_gen_generate_pipeline(*args): ) end_time = time.time() - execution_time = end_time - start_time - msg_task_complete = ( - f"GPU task complete in: {int(round(execution_time, 0) + 1)} seconds" - ) if verbose_arg: + execution_time = end_time - start_time + msg_task_complete = ( + f"GPU task complete in: {round(execution_time, 0) + 1} seconds" + ) gr.Info(msg_task_complete) print(msg_task_complete) - yield msg_task_complete, gr.update(), gr.update() +def extract_exif_data(image): + if image is None: return "" -@spaces.GPU(duration=15) -def process_upscale(image, upscaler_name, upscaler_size): - if image is None: - return None + try: + metadata_keys = ['parameters', 'metadata', 'prompt', 'Comment'] - from stablepy.diffusers_vanilla.utils import save_pil_image_with_metadata - from stablepy import load_upscaler_model + for key in metadata_keys: + if key in image.info: + return image.info[key] - image = image.convert("RGB") - exif_image = extract_exif_data(image) + return str(image.info) + + except Exception as e: + return f"Error extracting metadata: {str(e)}" - name_upscaler = UPSCALER_DICT_GUI[upscaler_name] - if "https://" in str(name_upscaler): +@spaces.GPU(duration=20) +def esrgan_upscale(image, upscaler_name, upscaler_size): + if image is None: return None - if not os.path.exists(f"./{DIRECTORY_UPSCALERS}/{name_upscaler.split('/')[-1]}"): - download_things(DIRECTORY_UPSCALERS, name_upscaler, HF_TOKEN) + from stablepy.diffusers_vanilla.utils import save_pil_image_with_metadata + from stablepy import UpscalerESRGAN + + exif_image = extract_exif_data(image) - name_upscaler = f"./{DIRECTORY_UPSCALERS}/{name_upscaler.split('/')[-1]}" + url_upscaler = UPSCALER_DICT_GUI[upscaler_name] + directory_upscalers = 'upscalers' + os.makedirs(directory_upscalers, exist_ok=True) + if not os.path.exists(f"./upscalers/{url_upscaler.split('/')[-1]}"): + download_things(directory_upscalers, url_upscaler, HF_TOKEN) - scaler_beta = load_upscaler_model(model=name_upscaler, tile=(0 if IS_ZERO_GPU else 192), tile_overlap=8, device=("cuda" if IS_GPU_MODE else "cpu"), half=IS_GPU_MODE) - image_up = scaler_beta.upscale(image, upscaler_size, True) + scaler_beta = UpscalerESRGAN(0, 0) + image_up = scaler_beta.upscale(image, upscaler_size, f"./upscalers/{url_upscaler.split('/')[-1]}") image_path = save_pil_image_with_metadata(image_up, f'{os.getcwd()}/up_images', exif_image) return image_path -# https://huggingface.co/spaces/BestWishYsh/ConsisID-preview-Space/discussions/1#674969a022b99c122af5d407 -# dynamic_gpu_duration.zerogpu = True -# sd_gen_generate_pipeline.zerogpu = True +dynamic_gpu_duration.zerogpu = True +sd_gen_generate_pipeline.zerogpu = True sd_gen = GuiSD() -with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as app: +with gr.Blocks(theme="NoCrypt/miku", css=CSS) as app: gr.Markdown("# 🧩 DiffuseCraft") gr.Markdown(SUBTITLE_GUI) with gr.Tab("Generation"): @@ -783,22 +958,10 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as with gr.Column(scale=2): - def update_task_options(model_name, task_name): - new_choices = MODEL_TYPE_TASK[get_model_type(model_name)] - - if task_name not in new_choices: - task_name = "txt2img" - - return gr.update(value=task_name, choices=new_choices) - - with gr.Accordion("Model and Task", open=True, visible=True): - task_gui = gr.Dropdown(label="Task", choices=SDXL_TASK, value=TASK_MODEL_LIST[0]) - model_name_gui = gr.Dropdown(label="Model", choices=model_list, value=model_list[0], allow_custom_value=True) + task_gui = gr.Dropdown(label="Task", choices=SDXL_TASK, value=TASK_MODEL_LIST[0]) + model_name_gui = gr.Dropdown(label="Model", choices=model_list, value=model_list[0], allow_custom_value=True) prompt_gui = gr.Textbox(lines=5, placeholder="Enter prompt", label="Prompt") - - with gr.Accordion("Negative prompt", open=False, visible=True): - neg_prompt_gui = gr.Textbox(lines=3, placeholder="Enter Neg prompt", label="Negative prompt", value="bad anatomy, ((many hands, bad hands, missing fingers)), anatomical nonsense, ugly, deformed, bad proportions, bad shadow, extra limbs, missing limbs, floating limbs, disconnected limbs, malformed hands, poorly drawn, mutation, mutated hands and fingers, extra legs, interlocked fingers, extra arms, disfigured face, long neck, asymmetrical eyes, lowres, extra digit, fewer digits, cropped, jpeg artifacts, signature, watermark, username, blurry, duplicate, bad composition, text, worst quality, normal quality, low quality, very displeasing, monochrome, grayscale, black and white, desaturated, low contrast, muted tones, washed out, unfinished, incomplete, draft, logo, backlighting") - + neg_prompt_gui = gr.Textbox(lines=3, placeholder="Enter Neg prompt", label="Negative prompt") with gr.Row(equal_height=False): set_params_gui = gr.Button(value="↙️", variant="secondary", size="sm") clear_prompt_gui = gr.Button(value="🗑️", variant="secondary", size="sm") @@ -811,7 +974,7 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as [task_gui], ) - load_model_gui = gr.HTML(elem_id="load_model", elem_classes="contain") + load_model_gui = gr.HTML() result_images = gr.Gallery( label="Generated images", @@ -828,197 +991,138 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as actual_task_info = gr.HTML() - with gr.Row(equal_height=False, variant="default", visible=IS_ZERO_GPU): + with gr.Row(equal_height=False, variant="default"): gpu_duration_gui = gr.Number(minimum=5, maximum=240, value=59, show_label=False, container=False, info="GPU time duration (seconds)") with gr.Column(): verbose_info_gui = gr.Checkbox(value=False, container=False, label="Status info") - load_lora_cpu_gui = gr.Checkbox(value=False, container=False, label="Load LoRAs on CPU") + load_lora_cpu_gui = gr.Checkbox(value=False, container=False, label="Load LoRAs on CPU (Save GPU time)") with gr.Column(scale=1): - with gr.Accordion("Generation settings", open=True, visible=True): - steps_gui = gr.Slider(minimum=1, maximum=100, step=1, value=30, label="Steps") - cfg_gui = gr.Slider(minimum=0, maximum=30, step=0.5, value=7., label="CFG") - sampler_gui = gr.Dropdown(label="Sampler", choices=scheduler_names, value="Euler") - schedule_type_gui = gr.Dropdown(label="Schedule type", choices=SCHEDULE_TYPE_OPTIONS, value=SCHEDULE_TYPE_OPTIONS[0]) - img_width_gui = gr.Slider(minimum=64, maximum=4096, step=8, value=832, label="Img Width") - img_height_gui = gr.Slider(minimum=64, maximum=4096, step=8, value=1216, label="Img Height") - seed_gui = gr.Number(minimum=-1, maximum=9999999999, value=-1, label="Seed") - pag_scale_gui = gr.Slider(minimum=0.0, maximum=10.0, step=0.1, value=0.0, label="PAG Scale") - with gr.Row(): - clip_skip_gui = gr.Checkbox(value=True, label="Layer 2 Clip Skip") - free_u_gui = gr.Checkbox(value=True, label="FreeU") - - with gr.Row(equal_height=False): - num_images_gui = gr.Slider(minimum=1, maximum=(16 if IS_ZERO_GPU else 20), step=1, value=1, label="Images") - prompt_syntax_gui = gr.Dropdown(label="Prompt Syntax", choices=PROMPT_W_OPTIONS, value=PROMPT_W_OPTIONS[2][1]) - vae_model_gui = gr.Dropdown(label="VAE Model", choices=vae_model_list, value=vae_model_list[0]) - - - def run_set_params_gui(base_prompt, name_model): - valid_receptors = { # default values - "prompt": gr.update(value=base_prompt), - "neg_prompt": gr.update(value=""), - "Steps": gr.update(value=30), - "width": gr.update(value=1024), - "height": gr.update(value=1024), - "Seed": gr.update(value=-1), - "Sampler": gr.update(value="Euler"), - "CFG scale": gr.update(value=7.), # cfg - "Clip skip": gr.update(value=True), - "Model": gr.update(value=name_model), - "Schedule type": gr.update(value="Automatic"), - "PAG": gr.update(value=.0), - "FreeU": gr.update(value=False), - "Hires upscaler": gr.update(), - "Hires upscale": gr.update(), - "Hires steps": gr.update(), - "Hires denoising strength": gr.update(), - "Hires CFG": gr.update(), - "Hires sampler": gr.update(), - "Hires schedule type": gr.update(), - "Image resolution": gr.update(value=1024), - "Strength": gr.update(), - "Prompt emphasis": gr.update(), - } - - # Generate up to 7 LoRAs - for i in range(1, 8): - valid_receptors[f"Lora_{i}"] = gr.update() - valid_receptors[f"Lora_scale_{i}"] = gr.update() - - valid_keys = list(valid_receptors.keys()) - - parameters = extract_parameters(base_prompt) - # print(parameters) - - if "Sampler" in parameters: - value_sampler = parameters["Sampler"] - for s_type in SCHEDULE_TYPE_OPTIONS: - if s_type in value_sampler: - value_sampler = value_sampler.replace(s_type, "").strip() - parameters["Sampler"] = value_sampler - parameters["Schedule type"] = s_type - - params_lora = [] - if ">" in parameters["prompt"] and "<" in parameters["prompt"]: - params_lora = re.findall(r']+>', parameters["prompt"]) - if "Loras" in parameters: - params_lora += re.findall(r']+>', parameters["Loras"]) - - if params_lora: - parsed_params = [] - for tag_l in params_lora: - try: - inner = tag_l.strip("<>") # remove < > - _, data_l = inner.split(":", 1) # remove the "lora:" part - parts_l = data_l.split(":") - - name_l = parts_l[0] - weight_l = float(parts_l[1]) if len(parts_l) > 1 else 1.0 # default weight = 1.0 - - parsed_params.append((name_l, weight_l)) - except Exception as e: - print(f"Error parsing LoRA tag {tag_l}: {e}") - - new_lora_model_list = get_model_list(DIRECTORY_LORAS) - new_lora_model_list.insert(0, "None") - - num_lora = 1 - for parsed_l, parsed_s in parsed_params: - filtered_loras = [m for m in new_lora_model_list if parsed_l in m] - if filtered_loras: - parameters[f"Lora_{num_lora}"] = filtered_loras[0] - parameters[f"Lora_scale_{num_lora}"] = parsed_s - num_lora += 1 - - # continue = discard new value - for key, val in parameters.items(): - # print(val) - if key in valid_keys: - try: - if key == "Sampler": - if val not in scheduler_names: - continue - if key in ["Schedule type", "Hires schedule type"]: - if val not in SCHEDULE_TYPE_OPTIONS: - continue - if key == "Hires sampler": - if val not in POST_PROCESSING_SAMPLER: - continue - if key == "Prompt emphasis": - if val not in PROMPT_WEIGHT_OPTIONS_PRIORITY: - continue - elif key == "Clip skip": - if "," in str(val): - val = val.replace(",", "") - if int(val) >= 2: - val = True - if key == "prompt": - if ">" in val and "<" in val: - val = re.sub(r'<[^>]+>', '', val) # Delete html and loras - print("Removed LoRA written in the prompt") - if key in ["prompt", "neg_prompt"]: - val = re.sub(r'\s+', ' ', re.sub(r',+', ',', val)).strip() - if key in ["Steps", "width", "height", "Seed", "Hires steps", "Image resolution"]: - val = int(val) - if key == "FreeU": - val = True - if key in ["CFG scale", "PAG", "Hires upscale", "Hires denoising strength", "Hires CFG", "Strength"]: - val = float(val) - if key == "Model": - filtered_models = [m for m in model_list if val in m] - if filtered_models: - val = filtered_models[0] - else: - val = name_model - if key == "Hires upscaler": - if val not in UPSCALER_KEYS: + steps_gui = gr.Slider(minimum=1, maximum=100, step=1, value=30, label="Steps") + cfg_gui = gr.Slider(minimum=0, maximum=30, step=0.5, value=7., label="CFG") + sampler_gui = gr.Dropdown(label="Sampler", choices=scheduler_names, value="Euler a") + img_width_gui = gr.Slider(minimum=64, maximum=4096, step=8, value=1024, label="Img Width") + img_height_gui = gr.Slider(minimum=64, maximum=4096, step=8, value=1024, label="Img Height") + seed_gui = gr.Number(minimum=-1, maximum=9999999999, value=-1, label="Seed") + pag_scale_gui = gr.Slider(minimum=0.0, maximum=10.0, step=0.1, value=0.0, label="PAG Scale") + with gr.Row(): + clip_skip_gui = gr.Checkbox(value=True, label="Layer 2 Clip Skip") + free_u_gui = gr.Checkbox(value=False, label="FreeU") + + with gr.Row(equal_height=False): + + def run_set_params_gui(base_prompt, name_model): + valid_receptors = { # default values + "prompt": gr.update(value=base_prompt), + "neg_prompt": gr.update(value=""), + "Steps": gr.update(value=30), + "width": gr.update(value=1024), + "height": gr.update(value=1024), + "Seed": gr.update(value=-1), + "Sampler": gr.update(value="Euler a"), + "scale": gr.update(value=7.), # cfg + "skip": gr.update(value=True), + "Model": gr.update(value=name_model), + } + valid_keys = list(valid_receptors.keys()) + + parameters = extract_parameters(base_prompt) + + for key, val in parameters.items(): + # print(val) + if key in valid_keys: + try: + if key == "Sampler": + if val not in scheduler_names: + continue + elif key == "skip": + if "," in str(val): + val = val.replace(",", "") + if int(val) >= 2: + val = True + if key == "prompt": + if ">" in val and "<" in val: + val = re.sub(r'<[^>]+>', '', val) + print("Removed LoRA written in the prompt") + if key in ["prompt", "neg_prompt"]: + val = re.sub(r'\s+', ' ', re.sub(r',+', ',', val)).strip() + if key in ["Steps", "width", "height", "Seed"]: + val = int(val) + if key == "scale": + val = float(val) + if key == "Model": + filtered_models = [m for m in model_list if val in m] + if filtered_models: + val = filtered_models[0] + else: + val = name_model + if key == "Seed": continue - if key == "Seed": - continue - - valid_receptors[key] = gr.update(value=val) - # print(val, type(val)) - # print(valid_receptors) - except Exception as e: - print(str(e)) - return [value for value in valid_receptors.values()] - - def run_clear_prompt_gui(): - return gr.update(value=""), gr.update(value="") - clear_prompt_gui.click( - run_clear_prompt_gui, [], [prompt_gui, neg_prompt_gui] - ) + valid_receptors[key] = gr.update(value=val) + # print(val, type(val)) + # print(valid_receptors) + except Exception as e: + print(str(e)) + return [value for value in valid_receptors.values()] + + set_params_gui.click( + run_set_params_gui, [prompt_gui, model_name_gui], [ + prompt_gui, + neg_prompt_gui, + steps_gui, + img_width_gui, + img_height_gui, + seed_gui, + sampler_gui, + cfg_gui, + clip_skip_gui, + model_name_gui, + ], + ) - def run_set_random_seed(): - return -1 - set_random_seed.click( - run_set_random_seed, [], seed_gui - ) + def run_clear_prompt_gui(): + return gr.update(value=""), gr.update(value="") + clear_prompt_gui.click( + run_clear_prompt_gui, [], [prompt_gui, neg_prompt_gui] + ) + + def run_set_random_seed(): + return -1 + set_random_seed.click( + run_set_random_seed, [], seed_gui + ) + + num_images_gui = gr.Slider(minimum=1, maximum=5, step=1, value=1, label="Images") + prompt_s_options = [ + ("Compel format: (word)weight", "Compel"), + ("Classic format: (word:weight)", "Classic"), + ("Classic-original format: (word:weight)", "Classic-original"), + ("Classic-no_norm format: (word:weight)", "Classic-no_norm"), + ("Classic-ignore", "Classic-ignore"), + ("None", "None"), + ] + prompt_syntax_gui = gr.Dropdown(label="Prompt Syntax", choices=prompt_s_options, value=prompt_s_options[1][1]) + vae_model_gui = gr.Dropdown(label="VAE Model", choices=vae_model_list, value=vae_model_list[0]) with gr.Accordion("Hires fix", open=False, visible=True): upscaler_model_path_gui = gr.Dropdown(label="Upscaler", choices=UPSCALER_KEYS, value=UPSCALER_KEYS[0]) upscaler_increases_size_gui = gr.Slider(minimum=1.1, maximum=4., step=0.1, value=1.2, label="Upscale by") - upscaler_tile_size_gui = gr.Slider(minimum=0, maximum=512, step=16, value=(0 if IS_ZERO_GPU else 192), label="Upscaler Tile Size", info="0 = no tiling") - upscaler_tile_overlap_gui = gr.Slider(minimum=0, maximum=48, step=1, value=8, label="Upscaler Tile Overlap") + esrgan_tile_gui = gr.Slider(minimum=0, value=0, maximum=500, step=1, label="ESRGAN Tile") + esrgan_tile_overlap_gui = gr.Slider(minimum=1, maximum=200, step=1, value=8, label="ESRGAN Tile Overlap") hires_steps_gui = gr.Slider(minimum=0, value=30, maximum=100, step=1, label="Hires Steps") hires_denoising_strength_gui = gr.Slider(minimum=0.1, maximum=1.0, step=0.01, value=0.55, label="Hires Denoising Strength") hires_sampler_gui = gr.Dropdown(label="Hires Sampler", choices=POST_PROCESSING_SAMPLER, value=POST_PROCESSING_SAMPLER[0]) - hires_schedule_list = ["Use same schedule type"] + SCHEDULE_TYPE_OPTIONS - hires_schedule_type_gui = gr.Dropdown(label="Hires Schedule type", choices=hires_schedule_list, value=hires_schedule_list[0]) - hires_guidance_scale_gui = gr.Slider(minimum=-1., maximum=30., step=0.5, value=-1., label="Hires CFG", info="If the value is -1, the main CFG will be used") hires_prompt_gui = gr.Textbox(label="Hires Prompt", placeholder="Main prompt will be use", lines=3) hires_negative_prompt_gui = gr.Textbox(label="Hires Negative Prompt", placeholder="Main negative prompt will be use", lines=3) with gr.Accordion("LoRA", open=False, visible=True): - def lora_dropdown(label, visible=True): - return gr.Dropdown(label=label, choices=lora_model_list, value="None", allow_custom_value=True, visible=visible) + def lora_dropdown(label): + return gr.Dropdown(label=label, choices=lora_model_list, value="None", allow_custom_value=True) - def lora_scale_slider(label, visible=True): - val_lora = 8 if IS_ZERO_GPU else 10 - return gr.Slider(minimum=-val_lora, maximum=val_lora, step=0.01, value=0.33, label=label, visible=visible) + def lora_scale_slider(label): + return gr.Slider(minimum=-2, maximum=2, step=0.01, value=0.33, label=label) lora1_gui = lora_dropdown("Lora1") lora_scale_1_gui = lora_scale_slider("Lora Scale 1") @@ -1030,37 +1134,21 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as lora_scale_4_gui = lora_scale_slider("Lora Scale 4") lora5_gui = lora_dropdown("Lora5") lora_scale_5_gui = lora_scale_slider("Lora Scale 5") - lora6_gui = lora_dropdown("Lora6") - lora_scale_6_gui = lora_scale_slider("Lora Scale 6") - lora7_gui = lora_dropdown("Lora7") - lora_scale_7_gui = lora_scale_slider("Lora Scale 7") with gr.Accordion("From URL", open=False, visible=True): - text_lora = gr.Textbox( - label="LoRA's download URL", - placeholder="https://civitai.com/api/download/models/28907", - lines=1, - info="It has to be .safetensors files, and you can also download them from Hugging Face.", - ) - romanize_text = gr.Checkbox(value=False, label="Transliterate name", visible=(not IS_ZERO_GPU)) - button_lora = gr.Button("Get and Refresh the LoRA Lists") - new_lora_status = gr.HTML() + text_lora = gr.Textbox(label="LoRA URL", placeholder="https://civitai.com/api/download/models/28907", lines=1) + button_lora = gr.Button("Get and update lists of LoRAs") button_lora.click( get_my_lora, - [text_lora, romanize_text], - [lora1_gui, lora2_gui, lora3_gui, lora4_gui, lora5_gui, lora6_gui, lora7_gui, new_lora_status] + [text_lora], + [lora1_gui, lora2_gui, lora3_gui, lora4_gui, lora5_gui] ) - with gr.Accordion("Face restoration", open=False, visible=True): - - face_rest_options = [None] + FACE_RESTORATION_MODELS - - face_restoration_model_gui = gr.Dropdown(label="Face restoration model", choices=face_rest_options, value=face_rest_options[0]) - face_restoration_visibility_gui = gr.Slider(minimum=0., maximum=1., step=0.001, value=1., label="Visibility") - face_restoration_weight_gui = gr.Slider(minimum=0., maximum=1., step=0.001, value=.5, label="Weight", info="(0 = maximum effect, 1 = minimum effect)") - with gr.Accordion("IP-Adapter", open=False, visible=True): + IP_MODELS = sorted(list(set(IP_ADAPTERS_SD + IP_ADAPTERS_SDXL))) + MODE_IP_OPTIONS = ["original", "style", "layout", "style+layout"] + with gr.Accordion("IP-Adapter 1", open=False, visible=True): image_ip1 = gr.Image(label="IP Image", type="filepath") mask_ip1 = gr.Image(label="IP Mask", type="filepath") @@ -1079,38 +1167,32 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as image_mask_gui = gr.Image(label="Image Mask", type="filepath") strength_gui = gr.Slider( minimum=0.01, maximum=1.0, step=0.01, value=0.55, label="Strength", - info="This option adjusts the level of changes for img2img, repaint and inpaint." - ) - image_resolution_gui = gr.Slider( - minimum=64, maximum=2048, step=64, value=1024, label="Image Resolution", - info="The maximum proportional size of the generated image based on the uploaded image." + info="This option adjusts the level of changes for img2img and inpainting." ) - controlnet_model_gui = gr.Dropdown(label="ControlNet model", choices=DIFFUSERS_CONTROLNET_MODEL, value=DIFFUSERS_CONTROLNET_MODEL[0], allow_custom_value=True) - control_net_output_scaling_gui = gr.Slider(minimum=0, maximum=5.0, step=0.1, value=1, label="ControlNet Output Scaling in UNet") - control_net_start_threshold_gui = gr.Slider(minimum=0, maximum=1, step=0.01, value=0, label="ControlNet Start Threshold (%)") - control_net_stop_threshold_gui = gr.Slider(minimum=0, maximum=1, step=0.01, value=1, label="ControlNet Stop Threshold (%)") - preprocessor_name_gui = gr.Dropdown(label="Preprocessor Name", choices=TASK_AND_PREPROCESSORS["canny"]) + image_resolution_gui = gr.Slider(minimum=64, maximum=2048, step=64, value=1024, label="Image Resolution") + preprocessor_name_gui = gr.Dropdown(label="Preprocessor Name", choices=PREPROCESSOR_CONTROLNET["canny"]) def change_preprocessor_choices(task): task = TASK_STABLEPY[task] - if task in TASK_AND_PREPROCESSORS.keys(): - choices_task = TASK_AND_PREPROCESSORS[task] + if task in PREPROCESSOR_CONTROLNET.keys(): + choices_task = PREPROCESSOR_CONTROLNET[task] else: - choices_task = TASK_AND_PREPROCESSORS["canny"] + choices_task = PREPROCESSOR_CONTROLNET["canny"] return gr.update(choices=choices_task, value=choices_task[0]) + task_gui.change( change_preprocessor_choices, [task_gui], [preprocessor_name_gui], ) - - preprocess_resolution_gui = gr.Slider(minimum=64, maximum=2048, step=64, value=512, label="Preprocessor Resolution") - low_threshold_gui = gr.Slider(minimum=1, maximum=255, step=1, value=100, label="'CANNY' low threshold") - high_threshold_gui = gr.Slider(minimum=1, maximum=255, step=1, value=200, label="'CANNY' high threshold") - value_threshold_gui = gr.Slider(minimum=0.0, maximum=2.0, step=0.01, value=0.1, label="'MLSD' Hough value threshold") - distance_threshold_gui = gr.Slider(minimum=0.0, maximum=20.0, step=0.01, value=0.1, label="'MLSD' Hough distance threshold") - recolor_gamma_correction_gui = gr.Number(minimum=0., maximum=25., value=1., step=0.001, label="'RECOLOR' gamma correction") - tile_blur_sigma_gui = gr.Number(minimum=0, maximum=100, value=9, step=1, label="'TILE' blur sigma") + preprocess_resolution_gui = gr.Slider(minimum=64, maximum=2048, step=64, value=512, label="Preprocess Resolution") + low_threshold_gui = gr.Slider(minimum=1, maximum=255, step=1, value=100, label="Canny low threshold") + high_threshold_gui = gr.Slider(minimum=1, maximum=255, step=1, value=200, label="Canny high threshold") + value_threshold_gui = gr.Slider(minimum=1, maximum=2.0, step=0.01, value=0.1, label="Hough value threshold (MLSD)") + distance_threshold_gui = gr.Slider(minimum=1, maximum=20.0, step=0.01, value=0.1, label="Hough distance threshold (MLSD)") + control_net_output_scaling_gui = gr.Slider(minimum=0, maximum=5.0, step=0.1, value=1, label="ControlNet Output Scaling in UNet") + control_net_start_threshold_gui = gr.Slider(minimum=0, maximum=1, step=0.01, value=0, label="ControlNet Start Threshold (%)") + control_net_stop_threshold_gui = gr.Slider(minimum=0, maximum=1, step=0.01, value=1, label="ControlNet Stop Threshold (%)") with gr.Accordion("T2I adapter", open=False, visible=False): t2i_adapter_preprocessor_gui = gr.Checkbox(value=True, label="T2i Adapter Preprocessor") @@ -1143,7 +1225,7 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as gr.Info(f"{len(sd_gen.model.STYLE_NAMES)} styles loaded") return gr.update(value=None, choices=sd_gen.model.STYLE_NAMES) - style_button.click(load_json_style_file, [style_json_gui], [style_prompt_gui]) + style_button.click(load_json_style_file, [style_json_gui], [style_prompt_gui]) with gr.Accordion("Textual inversion", open=False, visible=False): active_textual_inversion_gui = gr.Checkbox(value=False, label="Active Textual Inversion in prompt") @@ -1166,7 +1248,7 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as negative_prompt_ad_a_gui = gr.Textbox(label="Negative prompt", placeholder="Main negative prompt will be use", lines=3) strength_ad_a_gui = gr.Number(label="Strength:", value=0.35, step=0.01, minimum=0.01, maximum=1.0) face_detector_ad_a_gui = gr.Checkbox(label="Face detector", value=True) - person_detector_ad_a_gui = gr.Checkbox(label="Person detector", value=False) + person_detector_ad_a_gui = gr.Checkbox(label="Person detector", value=True) hand_detector_ad_a_gui = gr.Checkbox(label="Hand detector", value=False) mask_dilation_a_gui = gr.Number(label="Mask dilation:", value=4, minimum=1) mask_blur_a_gui = gr.Number(label="Mask blur:", value=4, minimum=1) @@ -1178,7 +1260,7 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as prompt_ad_b_gui = gr.Textbox(label="Main prompt", placeholder="Main prompt will be use", lines=3) negative_prompt_ad_b_gui = gr.Textbox(label="Negative prompt", placeholder="Main negative prompt will be use", lines=3) strength_ad_b_gui = gr.Number(label="Strength:", value=0.35, step=0.01, minimum=0.01, maximum=1.0) - face_detector_ad_b_gui = gr.Checkbox(label="Face detector", value=False) + face_detector_ad_b_gui = gr.Checkbox(label="Face detector", value=True) person_detector_ad_b_gui = gr.Checkbox(label="Person detector", value=True) hand_detector_ad_b_gui = gr.Checkbox(label="Hand detector", value=False) mask_dilation_b_gui = gr.Number(label="Mask dilation:", value=4, minimum=1) @@ -1186,76 +1268,191 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as mask_padding_b_gui = gr.Number(label="Mask padding:", value=32, minimum=1) with gr.Accordion("Other settings", open=False, visible=True): - schedule_prediction_type_gui = gr.Dropdown(label="Discrete Sampling Type", choices=SCHEDULE_PREDICTION_TYPE_OPTIONS, value=SCHEDULE_PREDICTION_TYPE_OPTIONS[0]) - guidance_rescale_gui = gr.Number(label="CFG rescale:", value=0., step=0.01, minimum=0., maximum=1.5) save_generated_images_gui = gr.Checkbox(value=True, label="Create a download link for the images") - enable_live_preview_gui = gr.Checkbox(value=True, label="Enable live previews") - display_images_gui = gr.Checkbox(value=True, label="Show final results") - filename_pattern_gui = gr.Textbox(label="Filename pattern", value="model,seed", placeholder="model,seed,sampler,schedule_type,img_width,img_height,guidance_scale,num_steps,vae,prompt_section,neg_prompt_section", lines=1) hires_before_adetailer_gui = gr.Checkbox(value=False, label="Hires Before Adetailer") hires_after_adetailer_gui = gr.Checkbox(value=True, label="Hires After Adetailer") generator_in_cpu_gui = gr.Checkbox(value=False, label="Generator in CPU") - with gr.Column(visible=(not IS_ZERO_GPU)): - image_storage_location_gui = gr.Textbox(value=img_path, label="Image Storage Location") - disable_progress_bar_gui = gr.Checkbox(value=False, label="Disable Progress Bar") - leave_progress_bar_gui = gr.Checkbox(value=True, label="Leave Progress Bar") with gr.Accordion("More settings", open=False, visible=False): loop_generation_gui = gr.Slider(minimum=1, value=1, label="Loop Generation") retain_task_cache_gui = gr.Checkbox(value=False, label="Retain task model in cache") - - image_previews_gui = gr.Checkbox(value=True, label="Image Previews (alt)") + leave_progress_bar_gui = gr.Checkbox(value=True, label="Leave Progress Bar") + disable_progress_bar_gui = gr.Checkbox(value=False, label="Disable Progress Bar") + display_images_gui = gr.Checkbox(value=True, label="Display Images") + image_previews_gui = gr.Checkbox(value=True, label="Image Previews") + image_storage_location_gui = gr.Textbox(value="./images", label="Image Storage Location") retain_compel_previous_load_gui = gr.Checkbox(value=False, label="Retain Compel Previous Load") retain_detailfix_model_previous_load_gui = gr.Checkbox(value=False, label="Retain Detailfix Model Previous Load") retain_hires_model_previous_load_gui = gr.Checkbox(value=False, label="Retain Hires Model Previous Load") - - set_params_gui.click( - run_set_params_gui, [prompt_gui, model_name_gui], [ - prompt_gui, - neg_prompt_gui, - steps_gui, - img_width_gui, - img_height_gui, - seed_gui, - sampler_gui, - cfg_gui, - clip_skip_gui, - model_name_gui, - schedule_type_gui, - pag_scale_gui, - free_u_gui, - upscaler_model_path_gui, - upscaler_increases_size_gui, - hires_steps_gui, - hires_denoising_strength_gui, - hires_guidance_scale_gui, - hires_sampler_gui, - hires_schedule_type_gui, - image_resolution_gui, - strength_gui, - prompt_syntax_gui, - lora1_gui, - lora_scale_1_gui, - lora2_gui, - lora_scale_2_gui, - lora3_gui, - lora_scale_3_gui, - lora4_gui, - lora_scale_4_gui, - lora5_gui, - lora_scale_5_gui, - lora6_gui, - lora_scale_6_gui, - lora7_gui, - lora_scale_7_gui, - ], - ) + xformers_memory_efficient_attention_gui = gr.Checkbox(value=False, label="Xformers Memory Efficient Attention") with gr.Accordion("Examples and help", open=False, visible=True): - gr.Markdown(HELP_GUI) - gr.Markdown(EXAMPLES_GUI_HELP) + gr.Markdown( + """### Help: + - The current space runs on a ZERO GPU which is assigned for approximately 60 seconds; Therefore, if you submit expensive tasks, the operation may be canceled upon reaching the maximum allowed time with 'GPU TASK ABORTED'. + - Distorted or strange images often result from high prompt weights, so it's best to use low weights and scales, and consider using Classic variants like 'Classic-original'. + - For better results with Pony Diffusion, try using sampler DPM++ 1s or DPM2 with Compel or Classic prompt weights. + """ + ) + gr.Markdown( + """### The following examples perform specific tasks: + 1. Generation with SDXL and upscale + 2. Generation with FLUX dev + 3. ControlNet Canny SDXL + 4. Optical pattern (Optical illusion) SDXL + 5. Convert an image to a coloring drawing + 6. ControlNet OpenPose SD 1.5 and Latent upscale + + - Different tasks can be performed, such as img2img or using the IP adapter, to preserve a person's appearance or a specific style based on an image. + """ + ) gr.Examples( - examples=EXAMPLES_GUI, + examples=[ + [ + "1girl, souryuu asuka langley, neon genesis evangelion, rebuild of evangelion, lance of longinus, cat hat, plugsuit, pilot suit, red bodysuit, sitting, crossed legs, black eye patch, throne, looking down, from bottom, looking at viewer, outdoors, (masterpiece), (best quality), (ultra-detailed), very aesthetic, illustration, disheveled hair, perfect composition, moist skin, intricate details", + "nfsw, lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, unfinished, very displeasing, oldest, early, chromatic aberration, artistic error, scan, abstract", + 28, + 7.0, + -1, + "None", + 0.33, + "Euler a", + 1152, + 896, + "cagliostrolab/animagine-xl-3.1", + "txt2img", + "image.webp", # img conttol + 1024, # img resolution + 0.35, # strength + 1.0, # cn scale + 0.0, # cn start + 1.0, # cn end + "Classic", + "Nearest", + 45, + False, + ], + [ + "a digital illustration of a movie poster titled 'Finding Emo', finding nemo parody poster, featuring a depressed cartoon clownfish with black emo hair, eyeliner, and piercings, bored expression, swimming in a dark underwater scene, in the background, movie title in a dripping, grungy font, moody blue and purple color palette", + "", + 24, + 3.5, + -1, + "None", + 0.33, + "Euler a", + 1152, + 896, + "black-forest-labs/FLUX.1-dev", + "txt2img", + None, # img conttol + 1024, # img resolution + 0.35, # strength + 1.0, # cn scale + 0.0, # cn start + 1.0, # cn end + "Classic", + None, + 70, + True, + ], + [ + "((masterpiece)), best quality, blonde disco girl, detailed face, realistic face, realistic hair, dynamic pose, pink pvc, intergalactic disco background, pastel lights, dynamic contrast, airbrush, fine detail, 70s vibe, midriff", + "(worst quality:1.2), (bad quality:1.2), (poor quality:1.2), (missing fingers:1.2), bad-artist-anime, bad-artist, bad-picture-chill-75v", + 48, + 3.5, + -1, + "None", + 0.33, + "DPM++ 2M SDE Lu", + 1024, + 1024, + "misri/epicrealismXL_v7FinalDestination", + "canny ControlNet", + "image.webp", # img conttol + 1024, # img resolution + 0.35, # strength + 1.0, # cn scale + 0.0, # cn start + 1.0, # cn end + "Classic", + None, + 44, + False, + ], + [ + "cinematic scenery old city ruins", + "(worst quality, low quality, illustration, 3d, 2d, painting, cartoons, sketch), (illustration, 3d, 2d, painting, cartoons, sketch, blurry, film grain, noise), (low quality, worst quality:1.2)", + 50, + 4.0, + -1, + "None", + 0.33, + "Euler a", + 1024, + 1024, + "misri/juggernautXL_juggernautX", + "optical pattern ControlNet", + "spiral_no_transparent.png", # img conttol + 1024, # img resolution + 0.35, # strength + 1.0, # cn scale + 0.05, # cn start + 0.75, # cn end + "Classic", + None, + 35, + False, + ], + [ + "black and white, line art, coloring drawing, clean line art, black strokes, no background, white, black, free lines, black scribbles, on paper, A blend of comic book art and lineart full of black and white color, masterpiece, high-resolution, trending on Pixiv fan box, palette knife, brush strokes, two-dimensional, planar vector, T-shirt design, stickers, and T-shirt design, vector art, fantasy art, Adobe Illustrator, hand-painted, digital painting, low polygon, soft lighting, aerial view, isometric style, retro aesthetics, 8K resolution, black sketch lines, monochrome, invert color", + "color, red, green, yellow, colored, duplicate, blurry, abstract, disfigured, deformed, animated, toy, figure, framed, 3d, bad art, poorly drawn, extra limbs, close up, b&w, weird colors, blurry, watermark, blur haze, 2 heads, long neck, watermark, elongated body, cropped image, out of frame, draft, deformed hands, twisted fingers, double image, malformed hands, multiple heads, extra limb, ugly, poorly drawn hands, missing limb, cut-off, over satured, grain, lowères, bad anatomy, poorly drawn face, mutation, mutated, floating limbs, disconnected limbs, out of focus, long body, disgusting, extra fingers, groos proportions, missing arms, mutated hands, cloned face, missing legs, ugly, tiling, poorly drawn hands, poorly drawn feet, poorly drawn face, out of frame, extra limbs, disfigured, deformed, body out of frame, blurry, bad anatomy, blurred, watermark, grainy, signature, cut off, draft, deformed, blurry, bad anatomy, disfigured, poorly drawn face, mutation, bluelish, blue", + 20, + 4.0, + -1, + "loras/Coloring_book_-_LineArt.safetensors", + 1.0, + "DPM++ 2M SDE Karras", + 1024, + 1024, + "cagliostrolab/animagine-xl-3.1", + "lineart ControlNet", + "color_image.png", # img conttol + 896, # img resolution + 0.35, # strength + 1.0, # cn scale + 0.0, # cn start + 1.0, # cn end + "Compel", + None, + 35, + False, + ], + [ + "1girl,face,curly hair,red hair,white background,", + "(worst quality:2),(low quality:2),(normal quality:2),lowres,watermark,", + 38, + 5.0, + -1, + "None", + 0.33, + "DPM++ 2M SDE Karras", + 512, + 512, + "digiplay/majicMIX_realistic_v7", + "openpose ControlNet", + "image.webp", # img conttol + 1024, # img resolution + 0.35, # strength + 1.0, # cn scale + 0.0, # cn start + 0.9, # cn end + "Compel", + "Latent (antialiased)", + 46, + False, + ], + ], fn=sd_gen.generate_pipeline, inputs=[ prompt_gui, @@ -1281,13 +1478,45 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as gpu_duration_gui, load_lora_cpu_gui, ], - outputs=[load_model_gui, result_images, actual_task_info], + outputs=[result_images, actual_task_info], cache_examples=False, ) - gr.Markdown(RESOURCES) + gr.Markdown( + """### Resources + - John6666's space has some great features you might find helpful [link](https://huggingface.co/spaces/John6666/DiffuseCraftMod). + - You can also try the image generator in Colab’s free tier, which provides free GPU [link](https://github.com/R3gm/SD_diffusers_interactive). + """ + ) with gr.Tab("Inpaint mask maker", render=True): + def create_mask_now(img, invert): + import numpy as np + import time + + time.sleep(0.5) + + transparent_image = img["layers"][0] + + # Extract the alpha channel + alpha_channel = np.array(transparent_image)[:, :, 3] + + # Create a binary mask by thresholding the alpha channel + binary_mask = alpha_channel > 1 + + if invert: + print("Invert") + # Invert the binary mask so that the drawn shape is white and the rest is black + binary_mask = np.invert(binary_mask) + + # Convert the binary mask to a 3-channel RGB mask + rgb_mask = np.stack((binary_mask,) * 3, axis=-1) + + # Convert the mask to uint8 + rgb_mask = rgb_mask.astype(np.uint8) * 255 + + return img["background"], rgb_mask + with gr.Row(): with gr.Column(scale=2): image_base = gr.ImageEditor( @@ -1296,31 +1525,20 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as # enable crop (or disable it) # transforms=["crop"], brush=gr.Brush( - default_size="16", # or leave it as 'auto' - color_mode="fixed", # 'fixed' hides the user swatches and colorpicker, 'defaults' shows it - # default_color="black", # html names are supported - colors=[ - "rgba(0, 0, 0, 1)", # rgb(a) - "rgba(0, 0, 0, 0.1)", - "rgba(255, 255, 255, 0.1)", - # "hsl(360, 120, 120)" # in fact any valid colorstring - ] + default_size="16", # or leave it as 'auto' + color_mode="fixed", # 'fixed' hides the user swatches and colorpicker, 'defaults' shows it + # default_color="black", # html names are supported + colors=[ + "rgba(0, 0, 0, 1)", # rgb(a) + "rgba(0, 0, 0, 0.1)", + "rgba(255, 255, 255, 0.1)", + # "hsl(360, 120, 120)" # in fact any valid colorstring + ] ), - eraser=gr.Eraser(default_size="16"), - render=True, - visible=False, - interactive=False, + eraser=gr.Eraser(default_size="16") ) - - show_canvas = gr.Button("SHOW INPAINT CANVAS") - - def change_visibility_canvas(): - return gr.update(visible=True, interactive=True), gr.update(visible=False) - show_canvas.click(change_visibility_canvas, [], [image_base, show_canvas]) - invert_mask = gr.Checkbox(value=False, label="Invert mask") btn = gr.Button("Create mask") - with gr.Column(scale=1): img_source = gr.Image(interactive=False) img_result = gr.Image(label="Mask image", show_label=True, interactive=False) @@ -1351,11 +1569,8 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as with gr.Row(): with gr.Column(): - - USCALER_TAB_KEYS = [name for name in UPSCALER_KEYS[9:]] - image_up_tab = gr.Image(label="Image", type="pil", sources=["upload"]) - upscaler_tab = gr.Dropdown(label="Upscaler", choices=USCALER_TAB_KEYS, value=USCALER_TAB_KEYS[5]) + upscaler_tab = gr.Dropdown(label="Upscaler", choices=UPSCALER_KEYS[9:], value=UPSCALER_KEYS[11]) upscaler_size_tab = gr.Slider(minimum=1., maximum=4., step=0.1, value=1.1, label="Upscale by") generate_button_up_tab = gr.Button(value="START UPSCALE", variant="primary") @@ -1363,26 +1578,21 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as result_up_tab = gr.Image(label="Result", type="pil", interactive=False, format="png") generate_button_up_tab.click( - fn=process_upscale, + fn=esrgan_upscale, inputs=[image_up_tab, upscaler_tab, upscaler_size_tab], outputs=[result_up_tab], ) - with gr.Tab("Preprocessor", render=True): - preprocessor_tab() - generate_button.click( fn=sd_gen.load_new_model, inputs=[ model_name_gui, vae_model_gui, - task_gui, - controlnet_model_gui, + task_gui ], outputs=[load_model_gui], queue=True, show_progress="minimal", - api_name=(False if HIDE_API else None), ).success( fn=sd_gen_generate_pipeline, # fn=sd_gen.generate_pipeline, inputs=[ @@ -1403,13 +1613,7 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as lora_scale_4_gui, lora5_gui, lora_scale_5_gui, - lora6_gui, - lora_scale_6_gui, - lora7_gui, - lora_scale_7_gui, sampler_gui, - schedule_type_gui, - schedule_prediction_type_gui, img_height_gui, img_width_gui, model_name_gui, @@ -1427,8 +1631,6 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as high_threshold_gui, value_threshold_gui, distance_threshold_gui, - recolor_gamma_correction_gui, - tile_blur_sigma_gui, control_net_output_scaling_gui, control_net_start_threshold_gui, control_net_stop_threshold_gui, @@ -1436,8 +1638,8 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as prompt_syntax_gui, upscaler_model_path_gui, upscaler_increases_size_gui, - upscaler_tile_size_gui, - upscaler_tile_overlap_gui, + esrgan_tile_gui, + esrgan_tile_overlap_gui, hires_steps_gui, hires_denoising_strength_gui, hires_sampler_gui, @@ -1445,16 +1647,12 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as hires_negative_prompt_gui, hires_before_adetailer_gui, hires_after_adetailer_gui, - hires_schedule_type_gui, - hires_guidance_scale_gui, - controlnet_model_gui, loop_generation_gui, leave_progress_bar_gui, disable_progress_bar_gui, image_previews_gui, display_images_gui, save_generated_images_gui, - filename_pattern_gui, image_storage_location_gui, retain_compel_previous_load_gui, retain_detailfix_model_previous_load_gui, @@ -1462,7 +1660,7 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as t2i_adapter_preprocessor_gui, adapter_conditioning_scale_gui, adapter_conditioning_factor_gui, - enable_live_preview_gui, + xformers_memory_efficient_attention_gui, free_u_gui, generator_in_cpu_gui, adetailer_inpaint_only_gui, @@ -1489,7 +1687,6 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as mask_blur_b_gui, mask_padding_b_gui, retain_task_cache_gui, - guidance_rescale_gui, image_ip1, mask_ip1, model_ip1, @@ -1501,26 +1698,19 @@ with gr.Blocks(theme=args.theme, css=CSS, fill_width=True, fill_height=False) as mode_ip2, scale_ip2, pag_scale_gui, - face_restoration_model_gui, - face_restoration_visibility_gui, - face_restoration_weight_gui, load_lora_cpu_gui, verbose_info_gui, gpu_duration_gui, ], - outputs=[load_model_gui, result_images, actual_task_info], + outputs=[result_images, actual_task_info], queue=True, show_progress="minimal", - # api_name=(False if HIDE_API else None), ) -if __name__ == "__main__": - app.queue() - app.launch( - show_error=True, - share=args.share_enabled, - debug=True, - ssr_mode=args.ssr, - allowed_paths=[allowed_path], - show_api=(not HIDE_API), - ) \ No newline at end of file +app.queue() + +app.launch( + show_error=True, + debug=True, + allowed_paths=["./images/"], +) \ No newline at end of file