diff --git "a/app.py" "b/app.py" --- "a/app.py" +++ "b/app.py" @@ -1,1799 +1,1799 @@ -import spaces -import os -from stablepy import ( - Model_Diffusers, - SCHEDULE_TYPE_OPTIONS, - SCHEDULE_PREDICTION_TYPE_OPTIONS, - check_scheduler_compatibility, - TASK_AND_PREPROCESSORS, - FACE_RESTORATION_MODELS, - scheduler_names, -) -from constants import ( - DIRECTORY_UPSCALERS, - TASK_STABLEPY, - TASK_MODEL_LIST, - UPSCALER_DICT_GUI, - UPSCALER_KEYS, - PROMPT_W_OPTIONS, - WARNING_MSG_VAE, - SDXL_TASK, - MODEL_TYPE_TASK, - POST_PROCESSING_SAMPLER, - DIFFUSERS_CONTROLNET_MODEL, - IP_MODELS, - MODE_IP_OPTIONS, -) -from stablepy.diffusers_vanilla.style_prompt_config import STYLE_NAMES -import torch -import re -import time -from PIL import ImageFile -from utils import ( - get_model_list, - extract_parameters, - 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, -) -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 - -# 导入翻译模块 -import translate_ui -from translate_ui import monkey_patch_gradio -import translate_helper as th - -# 应用猴子补丁,使所有新创建的Gradio组件自动翻译 -monkey_patch_gradio() - -subprocess.run("rm -rf /data-nvme/zerogpu-offload/*", env={}, shell=True) - -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")) - -## BEGIN MOD -from modutils import (list_uniq, download_private_repo, get_model_id_list, get_tupled_embed_list, - get_lora_model_list, get_all_lora_tupled_list, update_loras, apply_lora_prompt, set_prompt_loras, - get_my_lora, upload_file_lora, move_file_lora, search_civitai_lora, select_civitai_lora, - update_civitai_selection, get_civitai_tag, CIVITAI_SORT, CIVITAI_PERIOD, CIVITAI_BASEMODEL, - set_textual_inversion_prompt, get_model_pipeline, change_interface_mode, get_t2i_model_info, download_link_model, - get_tupled_model_list, save_gallery_images, save_gallery_history, set_optimization, set_sampler_settings, - set_quick_presets, process_style_prompt, optimization_list, save_images, download_things, valid_model_name, - preset_styles, preset_quality, preset_sampler_setting, translate_to_en, EXAMPLES_GUI, RESOURCES) -from env import (HF_TOKEN, CIVITAI_API_KEY, HF_LORA_ESSENTIAL_PRIVATE_REPO, HF_VAE_PRIVATE_REPO, - HF_SDXL_EMBEDS_NEGATIVE_PRIVATE_REPO, HF_SDXL_EMBEDS_POSITIVE_PRIVATE_REPO, - DIRECTORY_MODELS, DIRECTORY_LORAS, DIRECTORY_VAES, DIRECTORY_EMBEDS, DIRECTORY_EMBEDS_SDXL, - DIRECTORY_EMBEDS_POSITIVE_SDXL, LOAD_DIFFUSERS_FORMAT_MODEL, - DOWNLOAD_MODEL_LIST, DOWNLOAD_LORA_LIST, DOWNLOAD_VAE_LIST, DOWNLOAD_EMBEDS) - -download_private_repo(HF_LORA_ESSENTIAL_PRIVATE_REPO, DIRECTORY_LORAS, True) -download_private_repo(HF_VAE_PRIVATE_REPO, DIRECTORY_VAES, False) -## END MOD - -directories = [DIRECTORY_MODELS, DIRECTORY_LORAS, DIRECTORY_VAES, DIRECTORY_EMBEDS, DIRECTORY_UPSCALERS] -for directory in directories: - os.makedirs(directory, exist_ok=True) - -# - **Download Models** -DOWNLOAD_MODEL = ", ".join(DOWNLOAD_MODEL_LIST) -# - **Download VAEs** -DOWNLOAD_VAE = ", ".join(DOWNLOAD_VAE_LIST) -# - **Download LoRAs** -DOWNLOAD_LORA = ", ".join(DOWNLOAD_LORA_LIST) - -# Download stuffs -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: - 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) -lora_model_list = get_lora_model_list() -vae_model_list = get_model_list(DIRECTORY_VAES) -vae_model_list.insert(0, "BakedVAE") -vae_model_list.insert(0, "None") - -## BEGIN MOD -single_file_model_list = get_model_list(DIRECTORY_MODELS) -model_list = list_uniq(get_model_id_list() + LOAD_DIFFUSERS_FORMAT_MODEL + single_file_model_list) -download_private_repo(HF_SDXL_EMBEDS_NEGATIVE_PRIVATE_REPO, DIRECTORY_EMBEDS_SDXL, False) -download_private_repo(HF_SDXL_EMBEDS_POSITIVE_PRIVATE_REPO, DIRECTORY_EMBEDS_POSITIVE_SDXL, False) -embed_sdxl_list = get_model_list(DIRECTORY_EMBEDS_SDXL) + get_model_list(DIRECTORY_EMBEDS_POSITIVE_SDXL) - -def get_embed_list(pipeline_name): - return get_tupled_embed_list(embed_sdxl_list if pipeline_name == "StableDiffusionXLPipeline" else embed_list) -## END MOD - -print('\033[33m🏁 Download and listing of valid models completed.\033[0m') - -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 -components.pop("transformer", None) -components.pop("scheduler", None) -delete_model(flux_repo) -# components = None - -####################### -# GUI -####################### -logging.getLogger("diffusers").setLevel(logging.ERROR) -diffusers.utils.logging.set_verbosity(40) -warnings.filterwarnings(action="ignore", category=FutureWarning, module="diffusers") -warnings.filterwarnings(action="ignore", category=UserWarning, module="diffusers") -warnings.filterwarnings(action="ignore", category=FutureWarning, module="transformers") -## BEGIN MOD -#logger.setLevel(logging.CRITICAL) -logger.setLevel(logging.DEBUG) - -from tagger.v2 import V2_ALL_MODELS, v2_random_prompt, v2_upsampling_prompt -from tagger.utils import (gradio_copy_text, COPY_ACTION_JS, gradio_copy_prompt, - V2_ASPECT_RATIO_OPTIONS, V2_RATING_OPTIONS, V2_LENGTH_OPTIONS, V2_IDENTITY_OPTIONS) -from tagger.tagger import (predict_tags_wd, convert_danbooru_to_e621_prompt, - remove_specific_prompt, insert_recom_prompt, insert_model_recom_prompt, - compose_prompt_to_copy, translate_prompt, select_random_character) -def description_ui(): - gr.Markdown( - th.t(""" -## Danbooru Tags Transformer V2 Demo with WD Tagger -(Image =>) Prompt => Upsampled longer prompt -- Mod of p1atdev's [Danbooru Tags Transformer V2 Demo](https://huggingface.co/spaces/p1atdev/danbooru-tags-transformer-v2) and [WD Tagger with 🤗 transformers](https://huggingface.co/spaces/p1atdev/wd-tagger-transformers). -- Models: p1atdev's [wd-swinv2-tagger-v3-hf](https://huggingface.co/p1atdev/wd-swinv2-tagger-v3-hf), [dart-v2-moe-sft](https://huggingface.co/p1atdev/dart-v2-moe-sft) -""") - ) -## END MOD - -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=24, 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) - - 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 "http" in model_name: # - model_name, model_type = download_link_model(model_name, DIRECTORY_MODELS) # - is_link_model = True # - else: is_link_model = False # - - self.update_storage_models() - - vae_model = vae_model if vae_model != "None" else None - model_type = get_model_type(model_name) if not is_link_model else model_type # - dtype_model = torch.bfloat16 if model_type == "FLUX" else torch.float16 - - if not os.path.exists(model_name): - _ = 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" - - self.status_loading = True - - yield f"Loading model: {model_name}" - - if vae_model == "BakedVAE": - vae_model = model_name - elif 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", - env_components=components, - ) - self.model.advanced_params(image_preprocessor_cuda_active=True) - 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) - - 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, - ) - - 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.last_load = datetime.now() - self.status_loading = False - - yield f"Model loaded: {model_name}" - - #@spaces.GPU - @torch.inference_mode() - def generate_pipeline( - self, - prompt, - neg_prompt, - num_images, - steps, - cfg, - clip_skip, - seed, - lora1, - lora_scale1, - lora2, - lora_scale2, - lora3, - lora_scale3, - lora4, - lora_scale4, - lora5, - lora_scale5, - lora6, - lora_scale6, - lora7, - lora_scale7, - sampler, - schedule_type, - schedule_prediction_type, - img_height, - img_width, - model_name, - vae_model, - task, - image_control, - preprocessor_name, - preprocess_resolution, - image_resolution, - style_prompt, # list [] - style_json_file, - image_mask, - strength, - low_threshold, - high_threshold, - value_threshold, - distance_threshold, - recolor_gamma_correction, - tile_blur_sigma, - controlnet_output_scaling_in_unet, - controlnet_start_threshold, - controlnet_stop_threshold, - textual_inversion, - syntax_weights, - upscaler_model_path, - upscaler_increases_size, - upscaler_tile_size, - upscaler_tile_overlap, - hires_steps, - hires_denoising_strength, - hires_sampler, - hires_prompt, - 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, - retain_hires_model_previous_load, - t2i_adapter_preprocessor, - t2i_adapter_conditioning_scale, - t2i_adapter_conditioning_factor, - xformers_memory_efficient_attention, - freeu, - generator_in_cpu, - adetailer_inpaint_only, - adetailer_verbose, - adetailer_sampler, - adetailer_active_a, - prompt_ad_a, - negative_prompt_ad_a, - strength_ad_a, - face_detector_ad_a, - person_detector_ad_a, - hand_detector_ad_a, - mask_dilation_a, - mask_blur_a, - mask_padding_a, - adetailer_active_b, - prompt_ad_b, - negative_prompt_ad_b, - strength_ad_b, - face_detector_ad_b, - person_detector_ad_b, - hand_detector_ad_b, - mask_dilation_b, - mask_blur_b, - mask_padding_b, - retain_task_cache_gui, - guidance_rescale, - image_ip1, - mask_ip1, - model_ip1, - mode_ip1, - scale_ip1, - image_ip2, - mask_ip2, - model_ip2, - 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] - vae_msg = f"VAE: {vae_model}" if vae_model else "" - msg_lora = "" - -## BEGIN MOD - loras_list = [s if s else "None" for s in loras_list] - global lora_model_list - lora_model_list = get_lora_model_list() - lora1, lora_scale1, lora2, lora_scale2, lora3, lora_scale3, lora4, lora_scale4, lora5, lora_scale5, lora6, lora_scale6, lora7, lora_scale7 = \ - set_prompt_loras(prompt, syntax_weights, model_name, lora1, lora_scale1, lora2, lora_scale2, lora3, - lora_scale3, lora4, lora_scale4, lora5, lora_scale5, lora6, lora_scale6, lora7, lora_scale7) -## END MOD - - print("Config model:", model_name, vae_model, loras_list) - - task = TASK_STABLEPY[task] - - params_ip_img = [] - params_ip_msk = [] - params_ip_model = [] - params_ip_mode = [] - params_ip_scale = [] - - all_adapters = [ - (image_ip1, mask_ip1, model_ip1, mode_ip1, scale_ip1), - (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) - - concurrency = 5 - self.model.stream_config(concurrency=concurrency, 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'.") - - if task in ["inpaint", "repaint"] and not image_mask: - raise ValueError("Mask image not found. Upload one in 'Image Mask' to proceed.") - - if "https://" not in str(UPSCALER_DICT_GUI[upscaler_model_path]): - upscaler_model = upscaler_model_path - else: - 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) - - upscaler_model = f"./{DIRECTORY_UPSCALERS}/{url_upscaler.split('/')[-1]}" - - logging.getLogger("ultralytics").setLevel(logging.INFO if adetailer_verbose else logging.ERROR) - - adetailer_params_A = { - "face_detector_ad": face_detector_ad_a, - "person_detector_ad": person_detector_ad_a, - "hand_detector_ad": hand_detector_ad_a, - "prompt": prompt_ad_a, - "negative_prompt": negative_prompt_ad_a, - "strength": strength_ad_a, - # "image_list_task" : None, - "mask_dilation": mask_dilation_a, - "mask_blur": mask_blur_a, - "mask_padding": mask_padding_a, - "inpaint_only": adetailer_inpaint_only, - "sampler": adetailer_sampler, - } - - adetailer_params_B = { - "face_detector_ad": face_detector_ad_b, - "person_detector_ad": person_detector_ad_b, - "hand_detector_ad": hand_detector_ad_b, - "prompt": prompt_ad_b, - "negative_prompt": negative_prompt_ad_b, - "strength": strength_ad_b, - # "image_list_task" : None, - "mask_dilation": mask_dilation_b, - "mask_blur": mask_blur_b, - "mask_padding": mask_padding_b, - } - pipe_params = { - "prompt": prompt, - "negative_prompt": neg_prompt, - "img_height": img_height, - "img_width": img_width, - "num_images": num_images, - "num_steps": steps, - "guidance_scale": cfg, - "clip_skip": clip_skip, - "pag_scale": float(pag_scale), - "seed": seed, - "image": image_control, - "preprocessor_name": preprocessor_name, - "preprocess_resolution": preprocess_resolution, - "image_resolution": image_resolution, - "style_prompt": style_prompt if style_prompt else "", - "style_json_file": "", - "image_mask": image_mask, # only for Inpaint - "strength": strength, # only for Inpaint or ... - "low_threshold": low_threshold, - "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": lora1 if lora1 != "None" else None, - "lora_scale_A": lora_scale1, - "lora_B": lora2 if lora2 != "None" else None, - "lora_scale_B": lora_scale2, - "lora_C": lora3 if lora3 != "None" else None, - "lora_scale_C": lora_scale3, - "lora_D": lora4 if lora4 != "None" else None, - "lora_scale_D": lora_scale4, - "lora_E": lora5 if lora5 != "None" else None, - "lora_scale_E": lora_scale5, - "lora_F": lora6 if lora6 != "None" else None, - "lora_scale_F": lora_scale6, - "lora_G": lora7 if lora7 != "None" else None, - "lora_scale_G": lora_scale7, -## BEGIN MOD - "textual_inversion": get_embed_list(self.model.class_name) if textual_inversion else [], -## END MOD - "syntax_weights": syntax_weights, # "Classic" - "sampler": sampler, - "schedule_type": schedule_type, - "schedule_prediction_type": schedule_prediction_type, - "xformers_memory_efficient_attention": xformers_memory_efficient_attention, - "gui_active": True, - "loop_generation": loop_generation, - "controlnet_conditioning_scale": float(controlnet_output_scaling_in_unet), - "control_guidance_start": float(controlnet_start_threshold), - "control_guidance_end": float(controlnet_stop_threshold), - "generator_in_cpu": generator_in_cpu, - "FreeU": freeu, - "adetailer_A": adetailer_active_a, - "adetailer_A_params": adetailer_params_A, - "adetailer_B": adetailer_active_b, - "adetailer_B_params": adetailer_params_B, - "leave_progress_bar": leave_progress_bar, - "disable_progress_bar": disable_progress_bar, - "image_previews": image_previews, - "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, - "retain_hires_model_previous_load": retain_hires_model_previous_load, - "t2i_adapter_preprocessor": t2i_adapter_preprocessor, - "t2i_adapter_conditioning_scale": float(t2i_adapter_conditioning_scale), - "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, - "hires_steps": hires_steps, - "hires_denoising_strength": hires_denoising_strength, - "hires_prompt": hires_prompt, - "hires_negative_prompt": hires_negative_prompt, - "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 - - 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) - print("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 - if image_path: - info_images = f"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}" - - for status, lora in zip(self.model.lora_status, self.model.lora_memory): - if status: - msg_lora += f"
Loaded: {lora}" - elif status is not None: - msg_lora += f"
Error with: {lora}" - - if msg_lora: - info_images += msg_lora - - info_images = info_images + "
" + "GENERATION DATA:
" + escape_html(metadata[-1]) + "
-------
" - - download_links = "
".join( - [ - f'Download Image {i + 1}' - for i, path in enumerate(image_path) - ] - ) - if save_generated_images: - info_images += f"
{download_links}" - -## BEGIN MOD - img = save_images(img, metadata) -## END MOD - - info_state = "COMPLETE" - - yield info_state, img, info_images - - -def dynamic_gpu_duration(func, duration, *args): - - @spaces.GPU(duration=duration) - def wrapped_func(): - yield from func(*args) - - return wrapped_func() - - -@spaces.GPU -def dummy_gpu(): - return None - - -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" or item == "" else item # MOD - for item in [args[7], args[9], args[11], args[13], args[15], args[17], args[19]] - ] - lora_status = [None] * sd_gen.model.num_loras - - msg_load_lora = "Updating LoRAs in GPU..." - if load_lora_cpu: - msg_load_lora = "Updating LoRAs in CPU..." - - 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() - - # Load lora in CPU - if load_lora_cpu: - lora_status = sd_gen.model.load_lora_on_the_fly( - 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: - gr.Info(f"LoRA loaded in CPU: {lora}") - 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: - 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: - gr.Info(msg_request) - print(msg_request) - yield msg_request.replace("\n", "
"), gr.update(), gr.update() - - start_time = time.time() - - # yield from sd_gen.generate_pipeline(*generation_args) - yield from dynamic_gpu_duration( - sd_gen.generate_pipeline, - gpu_duration_arg, - *generation_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: - gr.Info(msg_task_complete) - print(msg_task_complete) - - yield msg_task_complete, gr.update(), gr.update() - - -@spaces.GPU(duration=15) -def process_upscale(image, upscaler_name, upscaler_size): - if image is None: return None - - from stablepy.diffusers_vanilla.utils import save_pil_image_with_metadata - from stablepy import load_upscaler_model - - image = image.convert("RGB") - exif_image = extract_exif_data(image) - - name_upscaler = UPSCALER_DICT_GUI[upscaler_name] - - if "https://" in str(name_upscaler): - - if not os.path.exists(f"./{DIRECTORY_UPSCALERS}/{name_upscaler.split('/')[-1]}"): - download_things(DIRECTORY_UPSCALERS, name_upscaler, HF_TOKEN) - - name_upscaler = f"./{DIRECTORY_UPSCALERS}/{name_upscaler.split('/')[-1]}" - - scaler_beta = load_upscaler_model(model=name_upscaler, tile=0, tile_overlap=8, device="cuda", half=True) - image_up = scaler_beta.upscale(image, upscaler_size, True) - - 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 -sd_gen = GuiSD() - - -## BEGIN MOD -CSS =""" -.gradio-container, #main { width:100%; height:100%; max-width:100%; padding-left:0; padding-right:0; margin-left:0; margin-right:0; } -.contain { display:flex; flex-direction:column; } -#component-0 { width:100%; height:100%; } -#gallery { flex-grow:1; } -#load_model { height: 50px; } -.lora { min-width:480px; } -#model-info { text-align:center; } -.title { font-size: 3em; align-items: center; text-align: center; } -.info { align-items: center; text-align: center; } -.desc [src$='#float'] { float: right; margin: 20px; } -""" - -with gr.Blocks(theme='NoCrypt/miku@>=1.2.2', elem_id="main", fill_width=True, css=CSS, delete_cache=(60, 3600)) as app: - title, description = th.translate_app_title() - gr.Markdown(title, elem_classes="title") - gr.Markdown(description, elem_classes="info") - with gr.Column(): - with gr.Tab(th.t("Generation")): - with gr.Row(): - with gr.Column(scale=1): - - def update_task_options(model_name, task_name): - new_choices = MODEL_TYPE_TASK[get_model_type(valid_model_name(model_name))] - - if task_name not in new_choices: - task_name = "txt2img" - - return gr.update(value=task_name, choices=new_choices) - - interface_mode_gui = gr.Radio(label="Quick settings", choices=["Simple", "Standard", "Fast", "LoRA"], value="Standard") - with gr.Accordion("Model and Task", open=False) as menu_model: - task_gui = gr.Dropdown(label="Task", choices=SDXL_TASK, value=TASK_MODEL_LIST[0]) - with gr.Group(): - model_name_gui = gr.Dropdown(label="Model", info="You can enter a huggingface model repo_id to want to use.", choices=get_tupled_model_list(model_list), value="votepurchase/animagine-xl-3.1", allow_custom_value=True) - model_info_gui = gr.Markdown(elem_classes="info") - with gr.Row(): - quick_model_type_gui = gr.Radio(label="Model Type", choices=["None", "Auto", "Animagine", "Pony"], value="Auto", interactive=True) - quick_genre_gui = gr.Radio(label="Genre", choices=["Anime", "Photo"], value="Anime", interactive=True) - quick_speed_gui = gr.Radio(label="Speed", choices=["Fast", "Standard", "Heavy"], value="Standard", interactive=True) - quick_aspect_gui = gr.Radio(label="Aspect Ratio", choices=["1:1", "3:4"], value="1:1", interactive=True) - with gr.Row(): - quality_selector_gui = gr.Dropdown(label="Quality Tags Presets", interactive=True, choices=list(preset_quality.keys()), value="None") - style_selector_gui = gr.Dropdown(label="Style Preset", interactive=True, choices=list(preset_styles.keys()), value="None") - sampler_selector_gui = gr.Dropdown(label="Sampler Quick Settings", interactive=True, choices=list(preset_sampler_setting.keys()), value="None") - optimization_gui = gr.Dropdown(label="Optimization for SDXL", choices=list(optimization_list.keys()), value="None", interactive=True) - with gr.Group(): - with gr.Accordion("Prompt from Image", open=False) as menu_from_image: - input_image_gui = gr.Image(label="Input image", type="pil", sources=["upload", "clipboard"], height=256) - with gr.Accordion(label="Advanced options", open=False): - with gr.Row(): - general_threshold_gui = gr.Slider(label="Threshold", minimum=0.0, maximum=1.0, value=0.3, step=0.01, interactive=True) - character_threshold_gui = gr.Slider(label="Character threshold", minimum=0.0, maximum=1.0, value=0.8, step=0.01, interactive=True) - with gr.Row(): - tag_type_gui = gr.Radio(label="Convert tags to", info="danbooru for Animagine, e621 for Pony.", choices=["danbooru", "e621"], value="danbooru") - recom_prompt_gui = gr.Radio(label="Insert reccomended prompt", choices=["None", "Animagine", "Pony"], value="None", interactive=True) - keep_tags_gui = gr.Radio(label="Remove tags leaving only the following", choices=["body", "dress", "all"], value="all") - image_algorithms = gr.CheckboxGroup(["Use WD Tagger"], label="Algorithms", value=["Use WD Tagger"], visible=False) - generate_from_image_btn_gui = gr.Button(value="GENERATE TAGS FROM IMAGE") - prompt_gui = gr.Textbox(lines=6, placeholder="1girl, solo, ...", label="Prompt", show_copy_button=True) - with gr.Accordion("Negative prompt, etc.", open=False) as menu_negative: - neg_prompt_gui = gr.Textbox(lines=3, placeholder="Enter Neg prompt", label="Negative prompt", value="lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer digits, worst quality, low quality, very displeasing, (bad)", show_copy_button=True) - translate_prompt_button = gr.Button(value="Translate prompt to English", size="sm", variant="secondary") - with gr.Row(): - insert_prompt_gui = gr.Radio(label="Insert reccomended positive / negative prompt", choices=["None", "Auto", "Animagine", "Pony"], value="Auto", interactive=True) - prompt_type_gui = gr.Radio(label="Convert tags to", choices=["danbooru", "e621"], value="e621", visible=False) - prompt_type_button = gr.Button(value="Convert prompt to Pony e621 style", size="sm", variant="secondary") - with gr.Row(): - character_dbt = gr.Textbox(lines=1, placeholder="kafuu chino, ...", label="Character names") - series_dbt = gr.Textbox(lines=1, placeholder="Is the order a rabbit?, ...", label="Series names") - random_character_gui = gr.Button(value="Random character 🎲", size="sm", variant="secondary") - model_name_dbt = gr.Dropdown(label="Model", choices=list(V2_ALL_MODELS.keys()), value=list(V2_ALL_MODELS.keys())[0], visible=False) - aspect_ratio_dbt = gr.Radio(label="Aspect ratio", choices=list(V2_ASPECT_RATIO_OPTIONS), value="square", visible=False) - length_dbt = gr.Radio(label="Length", choices=list(V2_LENGTH_OPTIONS), value="very_long", visible=False) - identity_dbt = gr.Radio(label="Keep identity", choices=list(V2_IDENTITY_OPTIONS), value="lax", visible=False) - ban_tags_dbt = gr.Textbox(label="Ban tags", placeholder="alternate costumen, ...", value="futanari, censored, furry, furrification", visible=False) - copy_button_dbt = gr.Button(value="Copy to clipboard", visible=False) - rating_dbt = gr.Radio(label="Rating", choices=list(V2_RATING_OPTIONS), value="sfw") - generate_db_random_button = gr.Button(value="EXTEND PROMPT 🎲") - with gr.Row(): - translate_prompt_gui = gr.Button(value="Translate Prompt 📝", variant="secondary", size="sm") - set_random_seed = gr.Button(value="Seed 🎲", variant="secondary", size="sm") - set_params_gui = gr.Button(value="Params ↙️", variant="secondary", size="sm") - clear_prompt_gui = gr.Button(value="Clear 🗑️", variant="secondary", size="sm") - - generate_button = gr.Button(value="GENERATE IMAGE", size="lg", variant="primary") - - model_name_gui.change( - update_task_options, - [model_name_gui, task_gui], - [task_gui], - ) - - load_model_gui = gr.HTML(elem_id="load_model", elem_classes="contain") - - result_images = gr.Gallery( - label="Generated images", - show_label=False, - elem_id="gallery", - #columns=[2], - columns=[1], - #rows=[2], - rows=[1], - object_fit="contain", - # height="auto", - interactive=False, - preview=False, - show_share_button=False, - show_download_button=True, - selected_index=50, - format="png", - ) - - result_images_files = gr.Files(interactive=False, visible=False) - - actual_task_info = gr.HTML() - - with gr.Accordion("History", open=False): - history_files = gr.Files(interactive=False, visible=False) - history_gallery = gr.Gallery(label="History", columns=6, object_fit="contain", format="png", interactive=False, show_share_button=False, show_download_button=True) - history_clear_button = gr.Button(value="Clear History", variant="secondary") - history_clear_button.click(lambda: ([], []), None, [history_gallery, history_files], queue=False, show_api=False) - - 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") - - with gr.Column(scale=1): - with gr.Accordion("Generation settings", open=False, visible=True) as menu_gen: - with gr.Row(): - 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") - steps_gui = gr.Slider(minimum=1, maximum=100, step=1, value=28, label="Steps") - cfg_gui = gr.Slider(minimum=0, maximum=30, step=0.5, value=7.0, label="CFG") - guidance_rescale_gui = gr.Slider(label="CFG rescale:", value=0., step=0.01, minimum=0., maximum=1.5) - with gr.Row(): - seed_gui = gr.Number(minimum=-1, maximum=2**32-1, value=-1, label="Seed") - pag_scale_gui = gr.Slider(minimum=0.0, maximum=10.0, step=0.1, value=0.0, label="PAG Scale") - num_images_gui = gr.Slider(minimum=1, maximum=5, step=1, value=1, label="Images") - clip_skip_gui = gr.Checkbox(value=False, label="Layer 2 Clip Skip") - free_u_gui = gr.Checkbox(value=False, label="FreeU") - with gr.Row(): - 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]) - schedule_prediction_type_gui = gr.Dropdown(label="Discrete Sampling Type", choices=SCHEDULE_PREDICTION_TYPE_OPTIONS, value=SCHEDULE_PREDICTION_TYPE_OPTIONS[0]) - vae_model_gui = gr.Dropdown(label="VAE Model", choices=vae_model_list, value=vae_model_list[0]) - prompt_syntax_gui = gr.Dropdown(label="Prompt Syntax", choices=PROMPT_W_OPTIONS, value=PROMPT_W_OPTIONS[1][1]) - - 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"), - "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), - } - 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 - - 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 == "Schedule type": - if val not in SCHEDULE_TYPE_OPTIONS: - val = "Automatic" - 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) - 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 == "FreeU": - val = True - if key in ["CFG scale", "PAG"]: - 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 - 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, - schedule_type_gui, - pag_scale_gui, - free_u_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 - ) - - with gr.Accordion("LoRA", open=False, visible=True) as menu_lora: - def lora_dropdown(label, visible=True): - return gr.Dropdown(label=label, choices=get_all_lora_tupled_list(), value="", allow_custom_value=True, elem_classes="lora", min_width=320, visible=visible) - - def lora_scale_slider(label, visible=True): - return gr.Slider(minimum=-2, maximum=2, step=0.01, value=1.00, label=label, visible=visible) - - def lora_textbox(label): - return gr.Textbox(label=label, info="Example of prompt:", value="None", show_copy_button=True, interactive=False, visible=False) - - with gr.Row(): - with gr.Column(): - lora1_gui = lora_dropdown("LoRA1") - lora_scale_1_gui = lora_scale_slider("LoRA Scale 1") - with gr.Row(): - with gr.Group(): - lora1_info_gui = lora_textbox("LoRA1 prompts") - lora1_copy_gui = gr.Button(value="Copy example to prompt", visible=False) - lora1_desc_gui = gr.Markdown(value="", visible=False) - with gr.Column(): - lora2_gui = lora_dropdown("LoRA2") - lora_scale_2_gui = lora_scale_slider("LoRA Scale 2") - with gr.Row(): - with gr.Group(): - lora2_info_gui = lora_textbox("LoRA2 prompts") - lora2_copy_gui = gr.Button(value="Copy example to prompt", visible=False) - lora2_desc_gui = gr.Markdown(value="", visible=False) - with gr.Column(): - lora3_gui = lora_dropdown("LoRA3") - lora_scale_3_gui = lora_scale_slider("LoRA Scale 3") - with gr.Row(): - with gr.Group(): - lora3_info_gui = lora_textbox("LoRA3 prompts") - lora3_copy_gui = gr.Button(value="Copy example to prompt", visible=False) - lora3_desc_gui = gr.Markdown(value="", visible=False) - with gr.Column(): - lora4_gui = lora_dropdown("LoRA4") - lora_scale_4_gui = lora_scale_slider("LoRA Scale 4") - with gr.Row(): - with gr.Group(): - lora4_info_gui = lora_textbox("LoRA4 prompts") - lora4_copy_gui = gr.Button(value="Copy example to prompt", visible=False) - lora4_desc_gui = gr.Markdown(value="", visible=False) - with gr.Column(): - lora5_gui = lora_dropdown("LoRA5") - lora_scale_5_gui = lora_scale_slider("LoRA Scale 5") - with gr.Row(): - with gr.Group(): - lora5_info_gui = lora_textbox("LoRA5 prompts") - lora5_copy_gui = gr.Button(value="Copy example to prompt", visible=False) - lora5_desc_gui = gr.Markdown(value="", visible=False) - with gr.Column(): - lora6_gui = lora_dropdown("LoRA6", visible=False) - lora_scale_6_gui = lora_scale_slider("LoRA Scale 6", visible=False) - with gr.Row(): - with gr.Group(): - lora6_info_gui = lora_textbox("LoRA6 prompts") - lora6_copy_gui = gr.Button(value="Copy example to prompt", visible=False) - lora6_desc_gui = gr.Markdown(value="", visible=False) - with gr.Column(): - lora7_gui = lora_dropdown("LoRA7", visible=False) - lora_scale_7_gui = lora_scale_slider("LoRA Scale 7", visible=False) - with gr.Row(): - with gr.Group(): - lora7_info_gui = lora_textbox("LoRA7 prompts") - lora7_copy_gui = gr.Button(value="Copy example to prompt", visible=False) - lora7_desc_gui = gr.Markdown(value="", visible=False) - with gr.Accordion("From URL", open=True, visible=True): - with gr.Row(): - search_civitai_basemodel_lora = gr.CheckboxGroup(label="Search LoRA for", choices=CIVITAI_BASEMODEL, value=["Pony", "Illustrious", "SDXL 1.0"]) - search_civitai_sort_lora = gr.Radio(label="Sort", choices=CIVITAI_SORT, value="Highest Rated") - search_civitai_period_lora = gr.Radio(label="Period", choices=CIVITAI_PERIOD, value="AllTime") - with gr.Row(): - search_civitai_query_lora = gr.Textbox(label="Query", placeholder="oomuro sakurako...", lines=1) - search_civitai_tag_lora = gr.Dropdown(label="Tag", choices=get_civitai_tag(), value=get_civitai_tag()[0], allow_custom_value=True) - search_civitai_user_lora = gr.Textbox(label="Username", lines=1) - search_civitai_button_lora = gr.Button("Search on Civitai") - search_civitai_desc_lora = gr.Markdown(value="", visible=False, elem_classes="desc") - with gr.Accordion("Select from Gallery", open=False): - search_civitai_gallery_lora = gr.Gallery([], label="Results", allow_preview=False, columns=5, show_share_button=False, interactive=False) - search_civitai_result_lora = gr.Dropdown(label="Search Results", choices=[("", "")], value="", allow_custom_value=True, visible=False) - with gr.Row(): - text_lora = gr.Textbox(label="LoRA's download URL", placeholder="https://civitai.com/api/download/models/28907", info="It has to be .safetensors files, and you can also download them from Hugging Face.", lines=1, scale=4) - romanize_text = gr.Checkbox(value=False, label="Transliterate name", scale=1, visible=False) - button_lora = gr.Button("Get and Refresh the LoRA Lists") - new_lora_status = gr.HTML() - with gr.Accordion("From Local", open=True, visible=True): - file_output_lora = gr.File(label="Uploaded LoRA", file_types=['.ckpt', '.pt', '.pth', '.safetensors', '.bin'], file_count="multiple", interactive=False, visible=False) - upload_button_lora = gr.UploadButton(label="Upload LoRA from your disk (very slow)", file_types=['.ckpt', '.pt', '.pth', '.safetensors', '.bin'], file_count="multiple") - - with gr.Column() as menu_advanced: - with gr.Accordion("Hires fix", open=False, visible=True) as menu_hires: - upscaler_model_path_gui = gr.Dropdown(label="Upscaler", choices=UPSCALER_KEYS, value=UPSCALER_KEYS[0]) - with gr.Row(): - upscaler_increases_size_gui = gr.Slider(minimum=1.1, maximum=6., step=0.1, value=1.0, label="Upscale by") - upscaler_tile_size_gui = gr.Slider(minimum=0, maximum=512, step=16, value=0, 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") - with gr.Row(): - 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("Detailfix", open=False, visible=True) as menu_detail: - with gr.Row(): - - # Adetailer Inpaint Only - adetailer_inpaint_only_gui = gr.Checkbox(label="Inpaint only", value=True) - - # Adetailer Verbose - adetailer_verbose_gui = gr.Checkbox(label="Verbose", value=False) - - # Adetailer Sampler - adetailer_sampler_gui = gr.Dropdown(label="Adetailer sampler:", choices=POST_PROCESSING_SAMPLER, value=POST_PROCESSING_SAMPLER[0]) - - with gr.Accordion("Detailfix A", open=True, visible=True): - # Adetailer A - adetailer_active_a_gui = gr.Checkbox(label="Enable Adetailer A", value=False) - prompt_ad_a_gui = gr.Textbox(label="Main prompt", placeholder="Main prompt will be use", lines=3) - negative_prompt_ad_a_gui = gr.Textbox(label="Negative prompt", placeholder="Main negative prompt will be use", lines=3) - with gr.Row(): - 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=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) - with gr.Row(): - 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) - mask_padding_a_gui = gr.Number(label="Mask padding:", value=32, minimum=1) - - with gr.Accordion("Detailfix B", open=True, visible=True): - # Adetailer B - adetailer_active_b_gui = gr.Checkbox(label="Enable Adetailer B", value=False) - 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) - with gr.Row(): - 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) - person_detector_ad_b_gui = gr.Checkbox(label="Person detector", value=True) - hand_detector_ad_b_gui = gr.Checkbox(label="Hand detector", value=False) - with gr.Row(): - mask_dilation_b_gui = gr.Number(label="Mask dilation:", value=4, minimum=1) - mask_blur_b_gui = gr.Number(label="Mask blur:", value=4, minimum=1) - mask_padding_b_gui = gr.Number(label="Mask padding:", value=32, minimum=1) - - 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]) - with gr.Row(): - 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("Textual inversion", open=False, visible=True) as menu_ti: - active_textual_inversion_gui = gr.Checkbox(value=False, label="Active Textual Inversion in prompt") - use_textual_inversion_gui = gr.CheckboxGroup(choices=get_embed_list(get_model_pipeline(model_name_gui.value)) if active_textual_inversion_gui.value else [], value=None, label="Use Textual Invertion in prompt") - def update_textual_inversion_gui(active_textual_inversion_gui, model_name_gui): - return gr.update(choices=get_embed_list(get_model_pipeline(model_name_gui)) if active_textual_inversion_gui else []) - active_textual_inversion_gui.change(update_textual_inversion_gui, [active_textual_inversion_gui, model_name_gui], [use_textual_inversion_gui]) - model_name_gui.change(update_textual_inversion_gui, [active_textual_inversion_gui, model_name_gui], [use_textual_inversion_gui]) - - with gr.Accordion("ControlNet / Img2img / Inpaint", open=False, visible=True) as menu_i2i: - with gr.Row(): - image_control = gr.Image(label="Image ControlNet/Inpaint/Img2img", type="filepath") - image_mask_gui = gr.Image(label="Image Mask", type="filepath") - with gr.Row(): - 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." - ) - with gr.Row(): - 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 (%)") - with gr.Row(): - preprocessor_name_gui = gr.Dropdown(label="Preprocessor Name", choices=TASK_AND_PREPROCESSORS["canny"]) - 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") - - def change_preprocessor_choices(task): - task = TASK_STABLEPY[task] - if task in TASK_AND_PREPROCESSORS.keys(): - choices_task = TASK_AND_PREPROCESSORS[task] - else: - choices_task = TASK_AND_PREPROCESSORS["canny"] - return gr.update(choices=choices_task, value=choices_task[0]) - - task_gui.change( - change_preprocessor_choices, - [task_gui], - [preprocessor_name_gui], - ) - - with gr.Row(): - value_threshold_gui = gr.Slider(minimum=1, maximum=2.0, step=0.01, value=0.1, label="'MLSD' Hough value threshold") - distance_threshold_gui = gr.Slider(minimum=1, 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") - - with gr.Accordion("IP-Adapter", open=False, visible=True) as menu_ipa: - - with gr.Accordion("IP-Adapter 1", open=True, visible=True): - with gr.Row(): - image_ip1 = gr.Image(label="IP Image", type="filepath") - mask_ip1 = gr.Image(label="IP Mask", type="filepath") - with gr.Row(): - model_ip1 = gr.Dropdown(value="plus_face", label="Model", choices=IP_MODELS) - mode_ip1 = gr.Dropdown(value="original", label="Mode", choices=MODE_IP_OPTIONS) - scale_ip1 = gr.Slider(minimum=0., maximum=2., step=0.01, value=0.7, label="Scale") - with gr.Accordion("IP-Adapter 2", open=True, visible=True): - with gr.Row(): - image_ip2 = gr.Image(label="IP Image", type="filepath") - mask_ip2 = gr.Image(label="IP Mask (optional)", type="filepath") - with gr.Row(): - model_ip2 = gr.Dropdown(value="base", label="Model", choices=IP_MODELS) - mode_ip2 = gr.Dropdown(value="style", label="Mode", choices=MODE_IP_OPTIONS) - scale_ip2 = gr.Slider(minimum=0., maximum=2., step=0.01, value=0.7, label="Scale") - - with gr.Accordion("T2I adapter", open=False, visible=False) as menu_t2i: - t2i_adapter_preprocessor_gui = gr.Checkbox(value=True, label="T2i Adapter Preprocessor") - with gr.Row(): - adapter_conditioning_scale_gui = gr.Slider(minimum=0, maximum=5., step=0.1, value=1, label="Adapter Conditioning Scale") - adapter_conditioning_factor_gui = gr.Slider(minimum=0, maximum=1., step=0.01, value=0.55, label="Adapter Conditioning Factor (%)") - - with gr.Accordion("Styles", open=False, visible=True) as menu_styles: - - try: - style_names_found = sd_gen.model.STYLE_NAMES - except Exception: - style_names_found = STYLE_NAMES - - style_prompt_gui = gr.Dropdown( - style_names_found, - multiselect=True, - value=None, - label="Style Prompt", - interactive=True, - ) - style_json_gui = gr.File(label="Style JSON File") - style_button = gr.Button("Load styles") - - def load_json_style_file(json): - if not sd_gen.model: - gr.Info("First load the model") - return gr.update(value=None, choices=STYLE_NAMES) - - sd_gen.model.load_style_file(json) - 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]) - - with gr.Accordion("Other settings", open=False, visible=True) as menu_other: - with gr.Row(): - save_generated_images_gui = gr.Checkbox(value=False, label="Save Generated Images") - 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) - with gr.Row(): - 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.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=True, label="Retain task model in cache") - 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=False, 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") - xformers_memory_efficient_attention_gui = gr.Checkbox(value=False, label="Xformers Memory Efficient Attention") - - with gr.Accordion("Examples and help", open=True, visible=True) as menu_example: - gr.Examples( - examples=EXAMPLES_GUI, - fn=sd_gen.generate_pipeline, - inputs=[ - prompt_gui, - neg_prompt_gui, - num_images_gui, - steps_gui, - cfg_gui, - clip_skip_gui, - seed_gui, - sampler_gui, - img_height_gui, - img_width_gui, - model_name_gui, - ], - outputs=[load_model_gui, result_images, actual_task_info], - cache_examples=False, - #elem_id="examples", - ) - - gr.Markdown(RESOURCES) -## END MOD - - with gr.Tab(th.t("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(label="Base image", show_label=True, brush=gr.Brush(colors=["#000000"])) - image_base = gr.ImageEditor( - sources=["upload", "clipboard"], - # crop_size="1:1", - # 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 - ] - ), - eraser=gr.Eraser(default_size="16") - ) - 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) - btn_send = gr.Button("Send to the first tab") - - btn.click(create_mask_now, [image_base, invert_mask], [img_source, img_result]) - - def send_img(img_source, img_result): - return img_source, img_result - btn_send.click(send_img, [img_source, img_result], [image_control, image_mask_gui]) - - with gr.Tab(th.t("PNG Info")): - with gr.Row(): - with gr.Column(): - image_metadata = gr.Image(label="Image with metadata", type="pil", sources=["upload"]) - - with gr.Column(): - result_metadata = gr.Textbox(label="Metadata", show_label=True, show_copy_button=True, interactive=False, container=True, max_lines=99) - - image_metadata.change( - fn=extract_exif_data, - inputs=[image_metadata], - outputs=[result_metadata], - ) - - with gr.Tab(th.t("Upscaler")): - 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_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") - - with gr.Column(): - result_up_tab = gr.Image(label="Result", type="pil", interactive=False, format="png") - - generate_button_up_tab.click( - fn=process_upscale, - inputs=[image_up_tab, upscaler_tab, upscaler_size_tab], - outputs=[result_up_tab], - ) - - with gr.Tab(th.t("Preprocessor"), render=True): - preprocessor_tab() - -## BEGIN MOD - interface_mode_gui.change( - change_interface_mode, - [interface_mode_gui], - [menu_model, menu_from_image, menu_negative, menu_gen, menu_hires, menu_lora, menu_advanced, - menu_example, task_gui, quick_speed_gui], - queue=False, - ) - model_name_gui.change(get_t2i_model_info, [model_name_gui], [model_info_gui], queue=False) - translate_prompt_gui.click(translate_to_en, [prompt_gui], [prompt_gui], queue=False)\ - .then(translate_to_en, [neg_prompt_gui], [neg_prompt_gui], queue=False) - - gr.on( - triggers=[quick_model_type_gui.change, quick_genre_gui.change, quick_speed_gui.change, quick_aspect_gui.change], - fn=set_quick_presets, - inputs=[quick_genre_gui, quick_model_type_gui, quick_speed_gui, quick_aspect_gui], - outputs=[quality_selector_gui, style_selector_gui, sampler_selector_gui, optimization_gui, insert_prompt_gui], - queue=False, - trigger_mode="once", - ) - gr.on( - triggers=[quality_selector_gui.change, style_selector_gui.change, insert_prompt_gui.change], - fn=process_style_prompt, - inputs=[prompt_gui, neg_prompt_gui, style_selector_gui, quality_selector_gui, insert_prompt_gui], - outputs=[prompt_gui, neg_prompt_gui, quick_model_type_gui], - queue=False, - trigger_mode="once", - ) - sampler_selector_gui.change(set_sampler_settings, [sampler_selector_gui], [sampler_gui, steps_gui, cfg_gui, clip_skip_gui, img_width_gui, img_height_gui, optimization_gui], queue=False) - optimization_gui.change(set_optimization, [optimization_gui, steps_gui, cfg_gui, sampler_gui, clip_skip_gui, lora5_gui, lora_scale_5_gui], [steps_gui, cfg_gui, sampler_gui, clip_skip_gui, lora5_gui, lora_scale_5_gui], queue=False) - - gr.on( - triggers=[lora1_gui.change, lora_scale_1_gui.change, lora2_gui.change, lora_scale_2_gui.change, - lora3_gui.change, lora_scale_3_gui.change, lora4_gui.change, lora_scale_4_gui.change, - lora5_gui.change, lora_scale_5_gui.change, lora6_gui.change, lora_scale_6_gui.change, - lora7_gui.change, lora_scale_7_gui.change, prompt_syntax_gui.change], - fn=update_loras, - inputs=[prompt_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], - outputs=[prompt_gui, lora1_gui, lora_scale_1_gui, lora1_info_gui, lora1_copy_gui, lora1_desc_gui, - lora2_gui, lora_scale_2_gui, lora2_info_gui, lora2_copy_gui, lora2_desc_gui, - lora3_gui, lora_scale_3_gui, lora3_info_gui, lora3_copy_gui, lora3_desc_gui, - lora4_gui, lora_scale_4_gui, lora4_info_gui, lora4_copy_gui, lora4_desc_gui, - lora5_gui, lora_scale_5_gui, lora5_info_gui, lora5_copy_gui, lora5_desc_gui, - lora6_gui, lora_scale_6_gui, lora6_info_gui, lora6_copy_gui, lora6_desc_gui, - lora7_gui, lora_scale_7_gui, lora7_info_gui, lora7_copy_gui, lora7_desc_gui], - queue=False, - trigger_mode="once", - ) - lora1_copy_gui.click(apply_lora_prompt, [prompt_gui, lora1_info_gui], [prompt_gui], queue=False) - lora2_copy_gui.click(apply_lora_prompt, [prompt_gui, lora2_info_gui], [prompt_gui], queue=False) - lora3_copy_gui.click(apply_lora_prompt, [prompt_gui, lora3_info_gui], [prompt_gui], queue=False) - lora4_copy_gui.click(apply_lora_prompt, [prompt_gui, lora4_info_gui], [prompt_gui], queue=False) - lora5_copy_gui.click(apply_lora_prompt, [prompt_gui, lora5_info_gui], [prompt_gui], queue=False) - lora6_copy_gui.click(apply_lora_prompt, [prompt_gui, lora6_info_gui], [prompt_gui], queue=False) - lora7_copy_gui.click(apply_lora_prompt, [prompt_gui, lora7_info_gui], [prompt_gui], queue=False) - gr.on( - triggers=[search_civitai_button_lora.click, search_civitai_query_lora.submit], - fn=search_civitai_lora, - inputs=[search_civitai_query_lora, search_civitai_basemodel_lora, search_civitai_sort_lora, search_civitai_period_lora, - search_civitai_tag_lora, search_civitai_user_lora, search_civitai_gallery_lora], - outputs=[search_civitai_result_lora, search_civitai_desc_lora, search_civitai_button_lora, search_civitai_query_lora, search_civitai_gallery_lora], - queue=True, - scroll_to_output=True, - ) - search_civitai_result_lora.change(select_civitai_lora, [search_civitai_result_lora], [text_lora, search_civitai_desc_lora], queue=False, scroll_to_output=True) - search_civitai_gallery_lora.select(update_civitai_selection, None, [search_civitai_result_lora], queue=False, show_api=False) - 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], scroll_to_output=True) - upload_button_lora.upload(upload_file_lora, [upload_button_lora], [file_output_lora, upload_button_lora]).success( - move_file_lora, [file_output_lora], [lora1_gui, lora2_gui, lora3_gui, lora4_gui, lora5_gui, lora6_gui, lora7_gui], scroll_to_output=True) - - use_textual_inversion_gui.change(set_textual_inversion_prompt, [use_textual_inversion_gui, prompt_gui, neg_prompt_gui, prompt_syntax_gui], [prompt_gui, neg_prompt_gui]) - - generate_from_image_btn_gui.click( - lambda: ("", "", ""), None, [series_dbt, character_dbt, prompt_gui], queue=False, - ).success( - predict_tags_wd, - [input_image_gui, prompt_gui, image_algorithms, general_threshold_gui, character_threshold_gui], - [series_dbt, character_dbt, prompt_gui, copy_button_dbt], - ).success( - compose_prompt_to_copy, [character_dbt, series_dbt, prompt_gui], [prompt_gui], queue=False, - ).success( - remove_specific_prompt, [prompt_gui, keep_tags_gui], [prompt_gui], queue=False, - ).success( - convert_danbooru_to_e621_prompt, [prompt_gui, tag_type_gui], [prompt_gui], queue=False, - ).success( - insert_recom_prompt, [prompt_gui, neg_prompt_gui, recom_prompt_gui], [prompt_gui, neg_prompt_gui], queue=False, - ) - - prompt_type_button.click(convert_danbooru_to_e621_prompt, [prompt_gui, prompt_type_gui], [prompt_gui], queue=False) - random_character_gui.click(select_random_character, [series_dbt, character_dbt], [series_dbt, character_dbt], queue=False) - generate_db_random_button.click( - v2_random_prompt, - [prompt_gui, series_dbt, character_dbt, - rating_dbt, aspect_ratio_dbt, length_dbt, identity_dbt, ban_tags_dbt, model_name_dbt], - [prompt_gui, series_dbt, character_dbt], - ).success( - convert_danbooru_to_e621_prompt, [prompt_gui, tag_type_gui], [prompt_gui], queue=False, - ) - - translate_prompt_button.click(translate_prompt, [prompt_gui], [prompt_gui], queue=False) - translate_prompt_button.click(translate_prompt, [character_dbt], [character_dbt], queue=False) - translate_prompt_button.click(translate_prompt, [series_dbt], [series_dbt], queue=False) - - generate_button.click( - fn=insert_model_recom_prompt, - inputs=[prompt_gui, neg_prompt_gui, model_name_gui, recom_prompt_gui], - outputs=[prompt_gui, neg_prompt_gui], - queue=False, - ).success( - fn=sd_gen.load_new_model, - inputs=[ - model_name_gui, - vae_model_gui, - task_gui, - controlnet_model_gui, - ], - outputs=[load_model_gui], - queue=True, - show_progress="minimal", - ).success( - fn=sd_gen_generate_pipeline, - inputs=[ - prompt_gui, - neg_prompt_gui, - num_images_gui, - steps_gui, - cfg_gui, - clip_skip_gui, - seed_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, - sampler_gui, - schedule_type_gui, - schedule_prediction_type_gui, - img_height_gui, - img_width_gui, - model_name_gui, - vae_model_gui, - task_gui, - image_control, - preprocessor_name_gui, - preprocess_resolution_gui, - image_resolution_gui, - style_prompt_gui, - style_json_gui, - image_mask_gui, - strength_gui, - low_threshold_gui, - 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, - active_textual_inversion_gui, - prompt_syntax_gui, - upscaler_model_path_gui, - upscaler_increases_size_gui, - upscaler_tile_size_gui, - upscaler_tile_overlap_gui, - hires_steps_gui, - hires_denoising_strength_gui, - hires_sampler_gui, - hires_prompt_gui, - 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, - retain_hires_model_previous_load_gui, - t2i_adapter_preprocessor_gui, - adapter_conditioning_scale_gui, - adapter_conditioning_factor_gui, - xformers_memory_efficient_attention_gui, - free_u_gui, - generator_in_cpu_gui, - adetailer_inpaint_only_gui, - adetailer_verbose_gui, - adetailer_sampler_gui, - adetailer_active_a_gui, - prompt_ad_a_gui, - negative_prompt_ad_a_gui, - strength_ad_a_gui, - face_detector_ad_a_gui, - person_detector_ad_a_gui, - hand_detector_ad_a_gui, - mask_dilation_a_gui, - mask_blur_a_gui, - mask_padding_a_gui, - adetailer_active_b_gui, - prompt_ad_b_gui, - negative_prompt_ad_b_gui, - strength_ad_b_gui, - face_detector_ad_b_gui, - person_detector_ad_b_gui, - hand_detector_ad_b_gui, - mask_dilation_b_gui, - mask_blur_b_gui, - mask_padding_b_gui, - retain_task_cache_gui, - guidance_rescale_gui, - image_ip1, - mask_ip1, - model_ip1, - mode_ip1, - scale_ip1, - image_ip2, - mask_ip2, - model_ip2, - 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], - queue=True, - show_progress="full", - ).success(save_gallery_images, [result_images, model_name_gui], [result_images, result_images_files], queue=False, show_api=False)\ - .success(save_gallery_history, [result_images, result_images_files, history_gallery, history_files], [history_gallery, history_files], queue=False, show_api=False) - - with gr.Tab(th.t("Danbooru Tags Transformer with WD Tagger"), render=True): - with gr.Column(scale=2): - with gr.Group(): - input_image = gr.Image(label="Input image", type="pil", sources=["upload", "clipboard"], height=256) - with gr.Accordion(label="Advanced options", open=False): - general_threshold = gr.Slider(label="Threshold", minimum=0.0, maximum=1.0, value=0.3, step=0.01, interactive=True) - character_threshold = gr.Slider(label="Character threshold", minimum=0.0, maximum=1.0, value=0.8, step=0.01, interactive=True) - input_tag_type = gr.Radio(label="Convert tags to", info="danbooru for Animagine, e621 for Pony.", choices=["danbooru", "e621"], value="danbooru") - recom_prompt = gr.Radio(label="Insert reccomended prompt", choices=["None", "Animagine", "Pony"], value="None", interactive=True) - image_algorithms = gr.CheckboxGroup(["Use WD Tagger"], label="Algorithms", value=["Use WD Tagger"], visible=False) - keep_tags = gr.Radio(label="Remove tags leaving only the following", choices=["body", "dress", "all"], value="all") - generate_from_image_btn = gr.Button(value="GENERATE TAGS FROM IMAGE", size="lg", variant="primary") - with gr.Group(): - with gr.Row(): - input_character = gr.Textbox(label="Character tags", placeholder="hatsune miku") - input_copyright = gr.Textbox(label="Copyright tags", placeholder="vocaloid") - pick_random_character = gr.Button(value="Random character 🎲", size="sm") - input_general = gr.TextArea(label="General tags", lines=4, placeholder="1girl, ...", value="") - input_tags_to_copy = gr.Textbox(value="", visible=False) - with gr.Row(): - copy_input_btn = gr.Button(value="Copy to clipboard", size="sm", interactive=False) - copy_prompt_btn_input = gr.Button(value="Copy to primary prompt", size="sm", interactive=False) - translate_input_prompt_button = gr.Button(value="Translate prompt to English", size="sm", variant="secondary") - tag_type = gr.Radio(label="Output tag conversion", info="danbooru for Animagine, e621 for Pony.", choices=["danbooru", "e621"], value="e621", visible=False) - input_rating = gr.Radio(label="Rating", choices=list(V2_RATING_OPTIONS), value="explicit") - with gr.Accordion(label="Advanced options", open=False): - input_aspect_ratio = gr.Radio(label="Aspect ratio", info="The aspect ratio of the image.", choices=list(V2_ASPECT_RATIO_OPTIONS), value="square") - input_length = gr.Radio(label="Length", info="The total length of the tags.", choices=list(V2_LENGTH_OPTIONS), value="very_long") - input_identity = gr.Radio(label="Keep identity", info="How strictly to keep the identity of the character or subject. If you specify the detail of subject in the prompt, you should choose `strict`. Otherwise, choose `none` or `lax`. `none` is very creative but sometimes ignores the input prompt.", choices=list(V2_IDENTITY_OPTIONS), value="lax") - input_ban_tags = gr.Textbox(label="Ban tags", info="Tags to ban from the output.", placeholder="alternate costumen, ...", value="censored") - model_name = gr.Dropdown(label="Model", choices=list(V2_ALL_MODELS.keys()), value=list(V2_ALL_MODELS.keys())[0]) - dummy_np = gr.Textbox(label="Negative prompt", value="", visible=False) - recom_animagine = gr.Textbox(label="Animagine reccomended prompt", value="Animagine", visible=False) - recom_pony = gr.Textbox(label="Pony reccomended prompt", value="Pony", visible=False) - generate_btn = gr.Button(value="GENERATE TAGS", size="lg", variant="primary") - with gr.Row(): - with gr.Group(): - output_text = gr.TextArea(label="Output tags", interactive=False, show_copy_button=True) - with gr.Row(): - copy_btn = gr.Button(value="Copy to clipboard", size="sm", interactive=False) - copy_prompt_btn = gr.Button(value="Copy to primary prompt", size="sm", interactive=False) - with gr.Group(): - output_text_pony = gr.TextArea(label="Output tags (Pony e621 style)", interactive=False, show_copy_button=True) - with gr.Row(): - copy_btn_pony = gr.Button(value="Copy to clipboard", size="sm", interactive=False) - copy_prompt_btn_pony = gr.Button(value="Copy to primary prompt", size="sm", interactive=False) - description_ui() - - translate_input_prompt_button.click(translate_prompt, inputs=[input_general], outputs=[input_general], queue=False) - translate_input_prompt_button.click(translate_prompt, inputs=[input_character], outputs=[input_character], queue=False) - translate_input_prompt_button.click(translate_prompt, inputs=[input_copyright], outputs=[input_copyright], queue=False) - - generate_from_image_btn.click( - lambda: ("", "", ""), None, [input_copyright, input_character, input_general], queue=False, - ).success( - predict_tags_wd, - [input_image, input_general, image_algorithms, general_threshold, character_threshold], - [input_copyright, input_character, input_general, copy_input_btn], - ).success( - remove_specific_prompt, inputs=[input_general, keep_tags], outputs=[input_general], queue=False, - ).success( - convert_danbooru_to_e621_prompt, inputs=[input_general, input_tag_type], outputs=[input_general], queue=False, - ).success( - insert_recom_prompt, inputs=[input_general, dummy_np, recom_prompt], outputs=[input_general, dummy_np], queue=False, - ).success(lambda: gr.update(interactive=True), None, [copy_prompt_btn_input], queue=False) - copy_input_btn.click(compose_prompt_to_copy, inputs=[input_character, input_copyright, input_general], outputs=[input_tags_to_copy])\ - .success(gradio_copy_text, inputs=[input_tags_to_copy], js=COPY_ACTION_JS) - copy_prompt_btn_input.click(compose_prompt_to_copy, inputs=[input_character, input_copyright, input_general], outputs=[input_tags_to_copy])\ - .success(gradio_copy_prompt, inputs=[input_tags_to_copy], outputs=[prompt_gui]) - - pick_random_character.click(select_random_character, [input_copyright, input_character], [input_copyright, input_character]) - - generate_btn.click( - v2_upsampling_prompt, - [model_name, input_copyright, input_character, input_general, - input_rating, input_aspect_ratio, input_length, input_identity, input_ban_tags], - [output_text], - ).success( - convert_danbooru_to_e621_prompt, inputs=[output_text, tag_type], outputs=[output_text_pony], queue=False, - ).success( - insert_recom_prompt, inputs=[output_text, dummy_np, recom_animagine], outputs=[output_text, dummy_np], queue=False, - ).success( - insert_recom_prompt, inputs=[output_text_pony, dummy_np, recom_pony], outputs=[output_text_pony, dummy_np], queue=False, - ).success(lambda: (gr.update(interactive=True), gr.update(interactive=True), gr.update(interactive=True), gr.update(interactive=True)), - None, [copy_btn, copy_btn_pony, copy_prompt_btn, copy_prompt_btn_pony], queue=False) - copy_btn.click(gradio_copy_text, inputs=[output_text], js=COPY_ACTION_JS) - copy_btn_pony.click(gradio_copy_text, inputs=[output_text_pony], js=COPY_ACTION_JS) - copy_prompt_btn.click(gradio_copy_prompt, inputs=[output_text], outputs=[prompt_gui]) - copy_prompt_btn_pony.click(gradio_copy_prompt, inputs=[output_text_pony], outputs=[prompt_gui]) - - gr.LoginButton() - gr.DuplicateButton(value="Duplicate Space for private use (This demo does not work on CPU. Requires GPU Space)") - -app.queue() -th.translate_civitai_constants(app) -app.launch(show_error=True, debug=True) # allowed_paths=["./images/"], show_error=True, debug=True -## END MOD - -# 自定义一些额外的翻译 -def custom_translate(text): - """自定义翻译函数,以处理特殊情况""" - return translate_ui.translate_text(text) +import spaces +import os +from stablepy import ( + Model_Diffusers, + SCHEDULE_TYPE_OPTIONS, + SCHEDULE_PREDICTION_TYPE_OPTIONS, + check_scheduler_compatibility, + TASK_AND_PREPROCESSORS, + FACE_RESTORATION_MODELS, + scheduler_names, +) +from constants import ( + DIRECTORY_UPSCALERS, + TASK_STABLEPY, + TASK_MODEL_LIST, + UPSCALER_DICT_GUI, + UPSCALER_KEYS, + PROMPT_W_OPTIONS, + WARNING_MSG_VAE, + SDXL_TASK, + MODEL_TYPE_TASK, + POST_PROCESSING_SAMPLER, + DIFFUSERS_CONTROLNET_MODEL, + IP_MODELS, + MODE_IP_OPTIONS, +) +from stablepy.diffusers_vanilla.style_prompt_config import STYLE_NAMES +import torch +import re +import time +from PIL import ImageFile +from utils import ( + get_model_list, + extract_parameters, + 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, +) +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 + +# 导入翻译模块 +import translate_ui +from translate_ui import monkey_patch_gradio +import translate_helper as th + +# 应用猴子补丁,使所有新创建的Gradio组件自动翻译 +monkey_patch_gradio() + +subprocess.run("rm -rf /data-nvme/zerogpu-offload/*", env={}, shell=True) + +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")) + +## BEGIN MOD +from modutils import (list_uniq, download_private_repo, get_model_id_list, get_tupled_embed_list, + get_lora_model_list, get_all_lora_tupled_list, update_loras, apply_lora_prompt, set_prompt_loras, + get_my_lora, upload_file_lora, move_file_lora, search_civitai_lora, select_civitai_lora, + update_civitai_selection, get_civitai_tag, CIVITAI_SORT, CIVITAI_PERIOD, CIVITAI_BASEMODEL, + set_textual_inversion_prompt, get_model_pipeline, change_interface_mode, get_t2i_model_info, download_link_model, + get_tupled_model_list, save_gallery_images, save_gallery_history, set_optimization, set_sampler_settings, + set_quick_presets, process_style_prompt, optimization_list, save_images, download_things, valid_model_name, + preset_styles, preset_quality, preset_sampler_setting, translate_to_en, EXAMPLES_GUI, RESOURCES) +from env import (HF_TOKEN, CIVITAI_API_KEY, HF_LORA_ESSENTIAL_PRIVATE_REPO, HF_VAE_PRIVATE_REPO, + HF_SDXL_EMBEDS_NEGATIVE_PRIVATE_REPO, HF_SDXL_EMBEDS_POSITIVE_PRIVATE_REPO, + DIRECTORY_MODELS, DIRECTORY_LORAS, DIRECTORY_VAES, DIRECTORY_EMBEDS, DIRECTORY_EMBEDS_SDXL, + DIRECTORY_EMBEDS_POSITIVE_SDXL, LOAD_DIFFUSERS_FORMAT_MODEL, + DOWNLOAD_MODEL_LIST, DOWNLOAD_LORA_LIST, DOWNLOAD_VAE_LIST, DOWNLOAD_EMBEDS) + +download_private_repo(HF_LORA_ESSENTIAL_PRIVATE_REPO, DIRECTORY_LORAS, True) +download_private_repo(HF_VAE_PRIVATE_REPO, DIRECTORY_VAES, False) +## END MOD + +directories = [DIRECTORY_MODELS, DIRECTORY_LORAS, DIRECTORY_VAES, DIRECTORY_EMBEDS, DIRECTORY_UPSCALERS] +for directory in directories: + os.makedirs(directory, exist_ok=True) + +# - **Download Models** +DOWNLOAD_MODEL = ", ".join(DOWNLOAD_MODEL_LIST) +# - **Download VAEs** +DOWNLOAD_VAE = ", ".join(DOWNLOAD_VAE_LIST) +# - **Download LoRAs** +DOWNLOAD_LORA = ", ".join(DOWNLOAD_LORA_LIST) + +# Download stuffs +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: + 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) +lora_model_list = get_lora_model_list() +vae_model_list = get_model_list(DIRECTORY_VAES) +vae_model_list.insert(0, "BakedVAE") +vae_model_list.insert(0, "None") + +## BEGIN MOD +single_file_model_list = get_model_list(DIRECTORY_MODELS) +model_list = list_uniq(get_model_id_list() + LOAD_DIFFUSERS_FORMAT_MODEL + single_file_model_list) +download_private_repo(HF_SDXL_EMBEDS_NEGATIVE_PRIVATE_REPO, DIRECTORY_EMBEDS_SDXL, False) +download_private_repo(HF_SDXL_EMBEDS_POSITIVE_PRIVATE_REPO, DIRECTORY_EMBEDS_POSITIVE_SDXL, False) +embed_sdxl_list = get_model_list(DIRECTORY_EMBEDS_SDXL) + get_model_list(DIRECTORY_EMBEDS_POSITIVE_SDXL) + +def get_embed_list(pipeline_name): + return get_tupled_embed_list(embed_sdxl_list if pipeline_name == "StableDiffusionXLPipeline" else embed_list) +## END MOD + +print('\033[33m🏁 Download and listing of valid models completed.\033[0m') + +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 +components.pop("transformer", None) +components.pop("scheduler", None) +delete_model(flux_repo) +# components = None + +####################### +# GUI +####################### +logging.getLogger("diffusers").setLevel(logging.ERROR) +diffusers.utils.logging.set_verbosity(40) +warnings.filterwarnings(action="ignore", category=FutureWarning, module="diffusers") +warnings.filterwarnings(action="ignore", category=UserWarning, module="diffusers") +warnings.filterwarnings(action="ignore", category=FutureWarning, module="transformers") +## BEGIN MOD +#logger.setLevel(logging.CRITICAL) +logger.setLevel(logging.DEBUG) + +from tagger.v2 import V2_ALL_MODELS, v2_random_prompt, v2_upsampling_prompt +from tagger.utils import (gradio_copy_text, COPY_ACTION_JS, gradio_copy_prompt, + V2_ASPECT_RATIO_OPTIONS, V2_RATING_OPTIONS, V2_LENGTH_OPTIONS, V2_IDENTITY_OPTIONS) +from tagger.tagger import (predict_tags_wd, convert_danbooru_to_e621_prompt, + remove_specific_prompt, insert_recom_prompt, insert_model_recom_prompt, + compose_prompt_to_copy, translate_prompt, select_random_character) +def description_ui(): + gr.Markdown( + th.t(""" +## Danbooru Tags Transformer V2 Demo with WD Tagger +(Image =>) Prompt => Upsampled longer prompt +- Mod of p1atdev's [Danbooru Tags Transformer V2 Demo](https://huggingface.co/spaces/p1atdev/danbooru-tags-transformer-v2) and [WD Tagger with 🤗 transformers](https://huggingface.co/spaces/p1atdev/wd-tagger-transformers). +- Models: p1atdev's [wd-swinv2-tagger-v3-hf](https://huggingface.co/p1atdev/wd-swinv2-tagger-v3-hf), [dart-v2-moe-sft](https://huggingface.co/p1atdev/dart-v2-moe-sft) +""") + ) +## END MOD + +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=24, 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) + + 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 "http" in model_name: # + model_name, model_type = download_link_model(model_name, DIRECTORY_MODELS) # + is_link_model = True # + else: is_link_model = False # + + self.update_storage_models() + + vae_model = vae_model if vae_model != "None" else None + model_type = get_model_type(model_name) if not is_link_model else model_type # + dtype_model = torch.bfloat16 if model_type == "FLUX" else torch.float16 + + if not os.path.exists(model_name): + _ = 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" + + self.status_loading = True + + yield f"Loading model: {model_name}" + + if vae_model == "BakedVAE": + vae_model = model_name + elif 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", + env_components=components, + ) + self.model.advanced_params(image_preprocessor_cuda_active=True) + 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) + + 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, + ) + + 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.last_load = datetime.now() + self.status_loading = False + + yield f"Model loaded: {model_name}" + + #@spaces.GPU + @torch.inference_mode() + def generate_pipeline( + self, + prompt, + neg_prompt, + num_images, + steps, + cfg, + clip_skip, + seed, + lora1, + lora_scale1, + lora2, + lora_scale2, + lora3, + lora_scale3, + lora4, + lora_scale4, + lora5, + lora_scale5, + lora6, + lora_scale6, + lora7, + lora_scale7, + sampler, + schedule_type, + schedule_prediction_type, + img_height, + img_width, + model_name, + vae_model, + task, + image_control, + preprocessor_name, + preprocess_resolution, + image_resolution, + style_prompt, # list [] + style_json_file, + image_mask, + strength, + low_threshold, + high_threshold, + value_threshold, + distance_threshold, + recolor_gamma_correction, + tile_blur_sigma, + controlnet_output_scaling_in_unet, + controlnet_start_threshold, + controlnet_stop_threshold, + textual_inversion, + syntax_weights, + upscaler_model_path, + upscaler_increases_size, + upscaler_tile_size, + upscaler_tile_overlap, + hires_steps, + hires_denoising_strength, + hires_sampler, + hires_prompt, + 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, + retain_hires_model_previous_load, + t2i_adapter_preprocessor, + t2i_adapter_conditioning_scale, + t2i_adapter_conditioning_factor, + xformers_memory_efficient_attention, + freeu, + generator_in_cpu, + adetailer_inpaint_only, + adetailer_verbose, + adetailer_sampler, + adetailer_active_a, + prompt_ad_a, + negative_prompt_ad_a, + strength_ad_a, + face_detector_ad_a, + person_detector_ad_a, + hand_detector_ad_a, + mask_dilation_a, + mask_blur_a, + mask_padding_a, + adetailer_active_b, + prompt_ad_b, + negative_prompt_ad_b, + strength_ad_b, + face_detector_ad_b, + person_detector_ad_b, + hand_detector_ad_b, + mask_dilation_b, + mask_blur_b, + mask_padding_b, + retain_task_cache_gui, + guidance_rescale, + image_ip1, + mask_ip1, + model_ip1, + mode_ip1, + scale_ip1, + image_ip2, + mask_ip2, + model_ip2, + 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] + vae_msg = f"VAE: {vae_model}" if vae_model else "" + msg_lora = "" + +## BEGIN MOD + loras_list = [s if s else "None" for s in loras_list] + global lora_model_list + lora_model_list = get_lora_model_list() + lora1, lora_scale1, lora2, lora_scale2, lora3, lora_scale3, lora4, lora_scale4, lora5, lora_scale5, lora6, lora_scale6, lora7, lora_scale7 = \ + set_prompt_loras(prompt, syntax_weights, model_name, lora1, lora_scale1, lora2, lora_scale2, lora3, + lora_scale3, lora4, lora_scale4, lora5, lora_scale5, lora6, lora_scale6, lora7, lora_scale7) +## END MOD + + print("Config model:", model_name, vae_model, loras_list) + + task = TASK_STABLEPY[task] + + params_ip_img = [] + params_ip_msk = [] + params_ip_model = [] + params_ip_mode = [] + params_ip_scale = [] + + all_adapters = [ + (image_ip1, mask_ip1, model_ip1, mode_ip1, scale_ip1), + (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) + + concurrency = 5 + self.model.stream_config(concurrency=concurrency, 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'.") + + if task in ["inpaint", "repaint"] and not image_mask: + raise ValueError("Mask image not found. Upload one in 'Image Mask' to proceed.") + + if "https://" not in str(UPSCALER_DICT_GUI[upscaler_model_path]): + upscaler_model = upscaler_model_path + else: + 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) + + upscaler_model = f"./{DIRECTORY_UPSCALERS}/{url_upscaler.split('/')[-1]}" + + logging.getLogger("ultralytics").setLevel(logging.INFO if adetailer_verbose else logging.ERROR) + + adetailer_params_A = { + "face_detector_ad": face_detector_ad_a, + "person_detector_ad": person_detector_ad_a, + "hand_detector_ad": hand_detector_ad_a, + "prompt": prompt_ad_a, + "negative_prompt": negative_prompt_ad_a, + "strength": strength_ad_a, + # "image_list_task" : None, + "mask_dilation": mask_dilation_a, + "mask_blur": mask_blur_a, + "mask_padding": mask_padding_a, + "inpaint_only": adetailer_inpaint_only, + "sampler": adetailer_sampler, + } + + adetailer_params_B = { + "face_detector_ad": face_detector_ad_b, + "person_detector_ad": person_detector_ad_b, + "hand_detector_ad": hand_detector_ad_b, + "prompt": prompt_ad_b, + "negative_prompt": negative_prompt_ad_b, + "strength": strength_ad_b, + # "image_list_task" : None, + "mask_dilation": mask_dilation_b, + "mask_blur": mask_blur_b, + "mask_padding": mask_padding_b, + } + pipe_params = { + "prompt": prompt, + "negative_prompt": neg_prompt, + "img_height": img_height, + "img_width": img_width, + "num_images": num_images, + "num_steps": steps, + "guidance_scale": cfg, + "clip_skip": clip_skip, + "pag_scale": float(pag_scale), + "seed": seed, + "image": image_control, + "preprocessor_name": preprocessor_name, + "preprocess_resolution": preprocess_resolution, + "image_resolution": image_resolution, + "style_prompt": style_prompt if style_prompt else "", + "style_json_file": "", + "image_mask": image_mask, # only for Inpaint + "strength": strength, # only for Inpaint or ... + "low_threshold": low_threshold, + "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": lora1 if lora1 != "None" else None, + "lora_scale_A": lora_scale1, + "lora_B": lora2 if lora2 != "None" else None, + "lora_scale_B": lora_scale2, + "lora_C": lora3 if lora3 != "None" else None, + "lora_scale_C": lora_scale3, + "lora_D": lora4 if lora4 != "None" else None, + "lora_scale_D": lora_scale4, + "lora_E": lora5 if lora5 != "None" else None, + "lora_scale_E": lora_scale5, + "lora_F": lora6 if lora6 != "None" else None, + "lora_scale_F": lora_scale6, + "lora_G": lora7 if lora7 != "None" else None, + "lora_scale_G": lora_scale7, +## BEGIN MOD + "textual_inversion": get_embed_list(self.model.class_name) if textual_inversion else [], +## END MOD + "syntax_weights": syntax_weights, # "Classic" + "sampler": sampler, + "schedule_type": schedule_type, + "schedule_prediction_type": schedule_prediction_type, + "xformers_memory_efficient_attention": xformers_memory_efficient_attention, + "gui_active": True, + "loop_generation": loop_generation, + "controlnet_conditioning_scale": float(controlnet_output_scaling_in_unet), + "control_guidance_start": float(controlnet_start_threshold), + "control_guidance_end": float(controlnet_stop_threshold), + "generator_in_cpu": generator_in_cpu, + "FreeU": freeu, + "adetailer_A": adetailer_active_a, + "adetailer_A_params": adetailer_params_A, + "adetailer_B": adetailer_active_b, + "adetailer_B_params": adetailer_params_B, + "leave_progress_bar": leave_progress_bar, + "disable_progress_bar": disable_progress_bar, + "image_previews": image_previews, + "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, + "retain_hires_model_previous_load": retain_hires_model_previous_load, + "t2i_adapter_preprocessor": t2i_adapter_preprocessor, + "t2i_adapter_conditioning_scale": float(t2i_adapter_conditioning_scale), + "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, + "hires_steps": hires_steps, + "hires_denoising_strength": hires_denoising_strength, + "hires_prompt": hires_prompt, + "hires_negative_prompt": hires_negative_prompt, + "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 + + 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) + print("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 + if image_path: + info_images = f"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}" + + for status, lora in zip(self.model.lora_status, self.model.lora_memory): + if status: + msg_lora += f"
Loaded: {lora}" + elif status is not None: + msg_lora += f"
Error with: {lora}" + + if msg_lora: + info_images += msg_lora + + info_images = info_images + "
" + "GENERATION DATA:
" + escape_html(metadata[-1]) + "
-------
" + + download_links = "
".join( + [ + f'Download Image {i + 1}' + for i, path in enumerate(image_path) + ] + ) + if save_generated_images: + info_images += f"
{download_links}" + +## BEGIN MOD + img = save_images(img, metadata) +## END MOD + + info_state = "COMPLETE" + + yield info_state, img, info_images + + +def dynamic_gpu_duration(func, duration, *args): + + @spaces.GPU(duration=duration) + def wrapped_func(): + yield from func(*args) + + return wrapped_func() + + +@spaces.GPU +def dummy_gpu(): + return None + + +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" or item == "" else item # MOD + for item in [args[7], args[9], args[11], args[13], args[15], args[17], args[19]] + ] + lora_status = [None] * sd_gen.model.num_loras + + msg_load_lora = "Updating LoRAs in GPU..." + if load_lora_cpu: + msg_load_lora = "Updating LoRAs in CPU..." + + 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() + + # Load lora in CPU + if load_lora_cpu: + lora_status = sd_gen.model.load_lora_on_the_fly( + 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: + gr.Info(f"LoRA loaded in CPU: {lora}") + 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: + 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: + gr.Info(msg_request) + print(msg_request) + yield msg_request.replace("\n", "
"), gr.update(), gr.update() + + start_time = time.time() + + # yield from sd_gen.generate_pipeline(*generation_args) + yield from dynamic_gpu_duration( + sd_gen.generate_pipeline, + gpu_duration_arg, + *generation_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: + gr.Info(msg_task_complete) + print(msg_task_complete) + + yield msg_task_complete, gr.update(), gr.update() + + +@spaces.GPU(duration=15) +def process_upscale(image, upscaler_name, upscaler_size): + if image is None: return None + + from stablepy.diffusers_vanilla.utils import save_pil_image_with_metadata + from stablepy import load_upscaler_model + + image = image.convert("RGB") + exif_image = extract_exif_data(image) + + name_upscaler = UPSCALER_DICT_GUI[upscaler_name] + + if "https://" in str(name_upscaler): + + if not os.path.exists(f"./{DIRECTORY_UPSCALERS}/{name_upscaler.split('/')[-1]}"): + download_things(DIRECTORY_UPSCALERS, name_upscaler, HF_TOKEN) + + name_upscaler = f"./{DIRECTORY_UPSCALERS}/{name_upscaler.split('/')[-1]}" + + scaler_beta = load_upscaler_model(model=name_upscaler, tile=0, tile_overlap=8, device="cuda", half=True) + image_up = scaler_beta.upscale(image, upscaler_size, True) + + 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 +sd_gen = GuiSD() + + +## BEGIN MOD +CSS =""" +.gradio-container, #main { width:100%; height:100%; max-width:100%; padding-left:0; padding-right:0; margin-left:0; margin-right:0; } +.contain { display:flex; flex-direction:column; } +#component-0 { width:100%; height:100%; } +#gallery { flex-grow:1; } +#load_model { height: 50px; } +.lora { min-width:480px; } +#model-info { text-align:center; } +.title { font-size: 3em; align-items: center; text-align: center; } +.info { align-items: center; text-align: center; } +.desc [src$='#float'] { float: right; margin: 20px; } +""" + +with gr.Blocks(theme='NoCrypt/miku@>=1.2.2', elem_id="main", fill_width=True, css=CSS, delete_cache=(60, 3600)) as app: + title, description = th.translate_app_title() + gr.Markdown(title, elem_classes="title") + gr.Markdown(description, elem_classes="info") + with gr.Column(): + with gr.Tab(th.t("Generation")): + with gr.Row(): + with gr.Column(scale=1): + + def update_task_options(model_name, task_name): + new_choices = MODEL_TYPE_TASK[get_model_type(valid_model_name(model_name))] + + if task_name not in new_choices: + task_name = "txt2img" + + return gr.update(value=task_name, choices=new_choices) + + interface_mode_gui = gr.Radio(label="Quick settings", choices=["Simple", "Standard", "Fast", "LoRA"], value="Standard") + with gr.Accordion("Model and Task", open=False) as menu_model: + task_gui = gr.Dropdown(label="Task", choices=SDXL_TASK, value=TASK_MODEL_LIST[0]) + with gr.Group(): + model_name_gui = gr.Dropdown(label="Model", info="You can enter a huggingface model repo_id to want to use.", choices=get_tupled_model_list(model_list), value="votepurchase/animagine-xl-3.1", allow_custom_value=True) + model_info_gui = gr.Markdown(elem_classes="info") + with gr.Row(): + quick_model_type_gui = gr.Radio(label="Model Type", choices=["None", "Auto", "Animagine", "Pony"], value="Auto", interactive=True) + quick_genre_gui = gr.Radio(label="Genre", choices=["Anime", "Photo"], value="Anime", interactive=True) + quick_speed_gui = gr.Radio(label="Speed", choices=["Fast", "Standard", "Heavy"], value="标准", interactive=True) + quick_aspect_gui = gr.Radio(label="Aspect Ratio", choices=["1:1", "3:4"], value="1:1", interactive=True) + with gr.Row(): + quality_selector_gui = gr.Dropdown(label="Quality Tags Presets", interactive=True, choices=list(preset_quality.keys()), value="None") + style_selector_gui = gr.Dropdown(label="Style Preset", interactive=True, choices=list(preset_styles.keys()), value="None") + sampler_selector_gui = gr.Dropdown(label="Sampler Quick Settings", interactive=True, choices=list(preset_sampler_setting.keys()), value="None") + optimization_gui = gr.Dropdown(label="Optimization for SDXL", choices=list(optimization_list.keys()), value="None", interactive=True) + with gr.Group(): + with gr.Accordion("Prompt from Image", open=False) as menu_from_image: + input_image_gui = gr.Image(label="Input image", type="pil", sources=["upload", "clipboard"], height=256) + with gr.Accordion(label="Advanced options", open=False): + with gr.Row(): + general_threshold_gui = gr.Slider(label="Threshold", minimum=0.0, maximum=1.0, value=0.3, step=0.01, interactive=True) + character_threshold_gui = gr.Slider(label="Character threshold", minimum=0.0, maximum=1.0, value=0.8, step=0.01, interactive=True) + with gr.Row(): + tag_type_gui = gr.Radio(label="Convert tags to", info="danbooru for Animagine, e621 for Pony.", choices=["danbooru", "e621"], value="danbooru") + recom_prompt_gui = gr.Radio(label="Insert reccomended prompt", choices=["None", "Animagine", "Pony"], value="None", interactive=True) + keep_tags_gui = gr.Radio(label="Remove tags leaving only the following", choices=["body", "dress", "all"], value="all") + image_algorithms = gr.CheckboxGroup(["Use WD Tagger"], label="Algorithms", value=["Use WD Tagger"], visible=False) + generate_from_image_btn_gui = gr.Button(value="GENERATE TAGS FROM IMAGE") + prompt_gui = gr.Textbox(lines=6, placeholder="1girl, solo, ...", label="Prompt", show_copy_button=True) + with gr.Accordion("Negative prompt, etc.", open=False) as menu_negative: + neg_prompt_gui = gr.Textbox(lines=3, placeholder="Enter Neg prompt", label="Negative prompt", value="lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer digits, worst quality, low quality, very displeasing, (bad)", show_copy_button=True) + translate_prompt_button = gr.Button(value="Translate prompt to English", size="sm", variant="secondary") + with gr.Row(): + insert_prompt_gui = gr.Radio(label="Insert reccomended positive / negative prompt", choices=["None", "Auto", "Animagine", "Pony"], value="Auto", interactive=True) + prompt_type_gui = gr.Radio(label="Convert tags to", choices=["danbooru", "e621"], value="e621", visible=False) + prompt_type_button = gr.Button(value="Convert prompt to Pony e621 style", size="sm", variant="secondary") + with gr.Row(): + character_dbt = gr.Textbox(lines=1, placeholder="kafuu chino, ...", label="Character names") + series_dbt = gr.Textbox(lines=1, placeholder="Is the order a rabbit?, ...", label="Series names") + random_character_gui = gr.Button(value="Random character 🎲", size="sm", variant="secondary") + model_name_dbt = gr.Dropdown(label="Model", choices=list(V2_ALL_MODELS.keys()), value=list(V2_ALL_MODELS.keys())[0], visible=False) + aspect_ratio_dbt = gr.Radio(label="Aspect ratio", choices=list(V2_ASPECT_RATIO_OPTIONS), value="square", visible=False) + length_dbt = gr.Radio(label="Length", choices=list(V2_LENGTH_OPTIONS), value="very_long", visible=False) + identity_dbt = gr.Radio(label="Keep identity", choices=list(V2_IDENTITY_OPTIONS), value="lax", visible=False) + ban_tags_dbt = gr.Textbox(label="Ban tags", placeholder="alternate costumen, ...", value="futanari, censored, furry, furrification", visible=False) + copy_button_dbt = gr.Button(value="Copy to clipboard", visible=False) + rating_dbt = gr.Radio(label="Rating", choices=list(V2_RATING_OPTIONS), value="sfw") + generate_db_random_button = gr.Button(value="EXTEND PROMPT 🎲") + with gr.Row(): + translate_prompt_gui = gr.Button(value="Translate Prompt 📝", variant="secondary", size="sm") + set_random_seed = gr.Button(value="Seed 🎲", variant="secondary", size="sm") + set_params_gui = gr.Button(value="Params ↙️", variant="secondary", size="sm") + clear_prompt_gui = gr.Button(value="Clear 🗑️", variant="secondary", size="sm") + + generate_button = gr.Button(value="GENERATE IMAGE", size="lg", variant="primary") + + model_name_gui.change( + update_task_options, + [model_name_gui, task_gui], + [task_gui], + ) + + load_model_gui = gr.HTML(elem_id="load_model", elem_classes="contain") + + result_images = gr.Gallery( + label="Generated images", + show_label=False, + elem_id="gallery", + #columns=[2], + columns=[1], + #rows=[2], + rows=[1], + object_fit="contain", + # height="auto", + interactive=False, + preview=False, + show_share_button=False, + show_download_button=True, + selected_index=50, + format="png", + ) + + result_images_files = gr.Files(interactive=False, visible=False) + + actual_task_info = gr.HTML() + + with gr.Accordion("History", open=False): + history_files = gr.Files(interactive=False, visible=False) + history_gallery = gr.Gallery(label="History", columns=6, object_fit="contain", format="png", interactive=False, show_share_button=False, show_download_button=True) + history_clear_button = gr.Button(value="Clear History", variant="secondary") + history_clear_button.click(lambda: ([], []), None, [history_gallery, history_files], queue=False, show_api=False) + + 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") + + with gr.Column(scale=1): + with gr.Accordion("Generation settings", open=False, visible=True) as menu_gen: + with gr.Row(): + 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") + steps_gui = gr.Slider(minimum=1, maximum=100, step=1, value=28, label="Steps") + cfg_gui = gr.Slider(minimum=0, maximum=30, step=0.5, value=7.0, label="CFG") + guidance_rescale_gui = gr.Slider(label="CFG rescale:", value=0., step=0.01, minimum=0., maximum=1.5) + with gr.Row(): + seed_gui = gr.Number(minimum=-1, maximum=2**32-1, value=-1, label="Seed") + pag_scale_gui = gr.Slider(minimum=0.0, maximum=10.0, step=0.1, value=0.0, label="PAG Scale") + num_images_gui = gr.Slider(minimum=1, maximum=5, step=1, value=1, label="Images") + clip_skip_gui = gr.Checkbox(value=False, label="Layer 2 Clip Skip") + free_u_gui = gr.Checkbox(value=False, label="FreeU") + with gr.Row(): + 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]) + schedule_prediction_type_gui = gr.Dropdown(label="Discrete Sampling Type", choices=SCHEDULE_PREDICTION_TYPE_OPTIONS, value=SCHEDULE_PREDICTION_TYPE_OPTIONS[0]) + vae_model_gui = gr.Dropdown(label="VAE Model", choices=vae_model_list, value=vae_model_list[0]) + prompt_syntax_gui = gr.Dropdown(label="Prompt Syntax", choices=PROMPT_W_OPTIONS, value=PROMPT_W_OPTIONS[1][1]) + + 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"), + "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), + } + 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 + + 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 == "Schedule type": + if val not in SCHEDULE_TYPE_OPTIONS: + val = "Automatic" + 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) + 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 == "FreeU": + val = True + if key in ["CFG scale", "PAG"]: + 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 + 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, + schedule_type_gui, + pag_scale_gui, + free_u_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 + ) + + with gr.Accordion("LoRA", open=False, visible=True) as menu_lora: + def lora_dropdown(label, visible=True): + return gr.Dropdown(label=label, choices=get_all_lora_tupled_list(), value="", allow_custom_value=True, elem_classes="lora", min_width=320, visible=visible) + + def lora_scale_slider(label, visible=True): + return gr.Slider(minimum=-2, maximum=2, step=0.01, value=1.00, label=label, visible=visible) + + def lora_textbox(label): + return gr.Textbox(label=label, info="Example of prompt:", value="None", show_copy_button=True, interactive=False, visible=False) + + with gr.Row(): + with gr.Column(): + lora1_gui = lora_dropdown("LoRA1") + lora_scale_1_gui = lora_scale_slider("LoRA Scale 1") + with gr.Row(): + with gr.Group(): + lora1_info_gui = lora_textbox("LoRA1 prompts") + lora1_copy_gui = gr.Button(value="Copy example to prompt", visible=False) + lora1_desc_gui = gr.Markdown(value="", visible=False) + with gr.Column(): + lora2_gui = lora_dropdown("LoRA2") + lora_scale_2_gui = lora_scale_slider("LoRA Scale 2") + with gr.Row(): + with gr.Group(): + lora2_info_gui = lora_textbox("LoRA2 prompts") + lora2_copy_gui = gr.Button(value="Copy example to prompt", visible=False) + lora2_desc_gui = gr.Markdown(value="", visible=False) + with gr.Column(): + lora3_gui = lora_dropdown("LoRA3") + lora_scale_3_gui = lora_scale_slider("LoRA Scale 3") + with gr.Row(): + with gr.Group(): + lora3_info_gui = lora_textbox("LoRA3 prompts") + lora3_copy_gui = gr.Button(value="Copy example to prompt", visible=False) + lora3_desc_gui = gr.Markdown(value="", visible=False) + with gr.Column(): + lora4_gui = lora_dropdown("LoRA4") + lora_scale_4_gui = lora_scale_slider("LoRA Scale 4") + with gr.Row(): + with gr.Group(): + lora4_info_gui = lora_textbox("LoRA4 prompts") + lora4_copy_gui = gr.Button(value="Copy example to prompt", visible=False) + lora4_desc_gui = gr.Markdown(value="", visible=False) + with gr.Column(): + lora5_gui = lora_dropdown("LoRA5") + lora_scale_5_gui = lora_scale_slider("LoRA Scale 5") + with gr.Row(): + with gr.Group(): + lora5_info_gui = lora_textbox("LoRA5 prompts") + lora5_copy_gui = gr.Button(value="Copy example to prompt", visible=False) + lora5_desc_gui = gr.Markdown(value="", visible=False) + with gr.Column(): + lora6_gui = lora_dropdown("LoRA6", visible=False) + lora_scale_6_gui = lora_scale_slider("LoRA Scale 6", visible=False) + with gr.Row(): + with gr.Group(): + lora6_info_gui = lora_textbox("LoRA6 prompts") + lora6_copy_gui = gr.Button(value="Copy example to prompt", visible=False) + lora6_desc_gui = gr.Markdown(value="", visible=False) + with gr.Column(): + lora7_gui = lora_dropdown("LoRA7", visible=False) + lora_scale_7_gui = lora_scale_slider("LoRA Scale 7", visible=False) + with gr.Row(): + with gr.Group(): + lora7_info_gui = lora_textbox("LoRA7 prompts") + lora7_copy_gui = gr.Button(value="Copy example to prompt", visible=False) + lora7_desc_gui = gr.Markdown(value="", visible=False) + with gr.Accordion("From URL", open=True, visible=True): + with gr.Row(): + search_civitai_basemodel_lora = gr.CheckboxGroup(label="Search LoRA for", choices=CIVITAI_BASEMODEL, value=["Pony", "Illustrious", "SDXL 1.0"]) + search_civitai_sort_lora = gr.Radio(label="Sort", choices=CIVITAI_SORT, value="Highest Rated") + search_civitai_period_lora = gr.Radio(label="Period", choices=CIVITAI_PERIOD, value="AllTime") + with gr.Row(): + search_civitai_query_lora = gr.Textbox(label="Query", placeholder="oomuro sakurako...", lines=1) + search_civitai_tag_lora = gr.Dropdown(label="Tag", choices=get_civitai_tag(), value=get_civitai_tag()[0], allow_custom_value=True) + search_civitai_user_lora = gr.Textbox(label="Username", lines=1) + search_civitai_button_lora = gr.Button("Search on Civitai") + search_civitai_desc_lora = gr.Markdown(value="", visible=False, elem_classes="desc") + with gr.Accordion("Select from Gallery", open=False): + search_civitai_gallery_lora = gr.Gallery([], label="Results", allow_preview=False, columns=5, show_share_button=False, interactive=False) + search_civitai_result_lora = gr.Dropdown(label="Search Results", choices=[("", "")], value="", allow_custom_value=True, visible=False) + with gr.Row(): + text_lora = gr.Textbox(label="LoRA's download URL", placeholder="https://civitai.com/api/download/models/28907", info="It has to be .safetensors files, and you can also download them from Hugging Face.", lines=1, scale=4) + romanize_text = gr.Checkbox(value=False, label="Transliterate name", scale=1, visible=False) + button_lora = gr.Button("Get and Refresh the LoRA Lists") + new_lora_status = gr.HTML() + with gr.Accordion("From Local", open=True, visible=True): + file_output_lora = gr.File(label="Uploaded LoRA", file_types=['.ckpt', '.pt', '.pth', '.safetensors', '.bin'], file_count="multiple", interactive=False, visible=False) + upload_button_lora = gr.UploadButton(label="Upload LoRA from your disk (very slow)", file_types=['.ckpt', '.pt', '.pth', '.safetensors', '.bin'], file_count="multiple") + + with gr.Column() as menu_advanced: + with gr.Accordion("Hires fix", open=False, visible=True) as menu_hires: + upscaler_model_path_gui = gr.Dropdown(label="Upscaler", choices=UPSCALER_KEYS, value=UPSCALER_KEYS[0]) + with gr.Row(): + upscaler_increases_size_gui = gr.Slider(minimum=1.1, maximum=6., step=0.1, value=1.0, label="Upscale by") + upscaler_tile_size_gui = gr.Slider(minimum=0, maximum=512, step=16, value=0, 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") + with gr.Row(): + 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("Detailfix", open=False, visible=True) as menu_detail: + with gr.Row(): + + # Adetailer Inpaint Only + adetailer_inpaint_only_gui = gr.Checkbox(label="Inpaint only", value=True) + + # Adetailer Verbose + adetailer_verbose_gui = gr.Checkbox(label="Verbose", value=False) + + # Adetailer Sampler + adetailer_sampler_gui = gr.Dropdown(label="Adetailer sampler:", choices=POST_PROCESSING_SAMPLER, value=POST_PROCESSING_SAMPLER[0]) + + with gr.Accordion("Detailfix A", open=True, visible=True): + # Adetailer A + adetailer_active_a_gui = gr.Checkbox(label="Enable Adetailer A", value=False) + prompt_ad_a_gui = gr.Textbox(label="Main prompt", placeholder="Main prompt will be use", lines=3) + negative_prompt_ad_a_gui = gr.Textbox(label="Negative prompt", placeholder="Main negative prompt will be use", lines=3) + with gr.Row(): + 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=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) + with gr.Row(): + 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) + mask_padding_a_gui = gr.Number(label="Mask padding:", value=32, minimum=1) + + with gr.Accordion("Detailfix B", open=True, visible=True): + # Adetailer B + adetailer_active_b_gui = gr.Checkbox(label="Enable Adetailer B", value=False) + 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) + with gr.Row(): + 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) + person_detector_ad_b_gui = gr.Checkbox(label="Person detector", value=True) + hand_detector_ad_b_gui = gr.Checkbox(label="Hand detector", value=False) + with gr.Row(): + mask_dilation_b_gui = gr.Number(label="Mask dilation:", value=4, minimum=1) + mask_blur_b_gui = gr.Number(label="Mask blur:", value=4, minimum=1) + mask_padding_b_gui = gr.Number(label="Mask padding:", value=32, minimum=1) + + 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]) + with gr.Row(): + 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("Textual inversion", open=False, visible=True) as menu_ti: + active_textual_inversion_gui = gr.Checkbox(value=False, label="Active Textual Inversion in prompt") + use_textual_inversion_gui = gr.CheckboxGroup(choices=get_embed_list(get_model_pipeline(model_name_gui.value)) if active_textual_inversion_gui.value else [], value=None, label="Use Textual Invertion in prompt") + def update_textual_inversion_gui(active_textual_inversion_gui, model_name_gui): + return gr.update(choices=get_embed_list(get_model_pipeline(model_name_gui)) if active_textual_inversion_gui else []) + active_textual_inversion_gui.change(update_textual_inversion_gui, [active_textual_inversion_gui, model_name_gui], [use_textual_inversion_gui]) + model_name_gui.change(update_textual_inversion_gui, [active_textual_inversion_gui, model_name_gui], [use_textual_inversion_gui]) + + with gr.Accordion("ControlNet / Img2img / Inpaint", open=False, visible=True) as menu_i2i: + with gr.Row(): + image_control = gr.Image(label="Image ControlNet/Inpaint/Img2img", type="filepath") + image_mask_gui = gr.Image(label="Image Mask", type="filepath") + with gr.Row(): + 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." + ) + with gr.Row(): + 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 (%)") + with gr.Row(): + preprocessor_name_gui = gr.Dropdown(label="Preprocessor Name", choices=TASK_AND_PREPROCESSORS["canny"]) + 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") + + def change_preprocessor_choices(task): + task = TASK_STABLEPY[task] + if task in TASK_AND_PREPROCESSORS.keys(): + choices_task = TASK_AND_PREPROCESSORS[task] + else: + choices_task = TASK_AND_PREPROCESSORS["canny"] + return gr.update(choices=choices_task, value=choices_task[0]) + + task_gui.change( + change_preprocessor_choices, + [task_gui], + [preprocessor_name_gui], + ) + + with gr.Row(): + value_threshold_gui = gr.Slider(minimum=1, maximum=2.0, step=0.01, value=0.1, label="'MLSD' Hough value threshold") + distance_threshold_gui = gr.Slider(minimum=1, 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") + + with gr.Accordion("IP-Adapter", open=False, visible=True) as menu_ipa: + + with gr.Accordion("IP-Adapter 1", open=True, visible=True): + with gr.Row(): + image_ip1 = gr.Image(label="IP Image", type="filepath") + mask_ip1 = gr.Image(label="IP Mask", type="filepath") + with gr.Row(): + model_ip1 = gr.Dropdown(value="plus_face", label="Model", choices=IP_MODELS) + mode_ip1 = gr.Dropdown(value="original", label="Mode", choices=MODE_IP_OPTIONS) + scale_ip1 = gr.Slider(minimum=0., maximum=2., step=0.01, value=0.7, label="Scale") + with gr.Accordion("IP-Adapter 2", open=True, visible=True): + with gr.Row(): + image_ip2 = gr.Image(label="IP Image", type="filepath") + mask_ip2 = gr.Image(label="IP Mask (optional)", type="filepath") + with gr.Row(): + model_ip2 = gr.Dropdown(value="base", label="Model", choices=IP_MODELS) + mode_ip2 = gr.Dropdown(value="style", label="Mode", choices=MODE_IP_OPTIONS) + scale_ip2 = gr.Slider(minimum=0., maximum=2., step=0.01, value=0.7, label="Scale") + + with gr.Accordion("T2I adapter", open=False, visible=False) as menu_t2i: + t2i_adapter_preprocessor_gui = gr.Checkbox(value=True, label="T2i Adapter Preprocessor") + with gr.Row(): + adapter_conditioning_scale_gui = gr.Slider(minimum=0, maximum=5., step=0.1, value=1, label="Adapter Conditioning Scale") + adapter_conditioning_factor_gui = gr.Slider(minimum=0, maximum=1., step=0.01, value=0.55, label="Adapter Conditioning Factor (%)") + + with gr.Accordion("Styles", open=False, visible=True) as menu_styles: + + try: + style_names_found = sd_gen.model.STYLE_NAMES + except Exception: + style_names_found = STYLE_NAMES + + style_prompt_gui = gr.Dropdown( + style_names_found, + multiselect=True, + value=None, + label="Style Prompt", + interactive=True, + ) + style_json_gui = gr.File(label="Style JSON File") + style_button = gr.Button("Load styles") + + def load_json_style_file(json): + if not sd_gen.model: + gr.Info("First load the model") + return gr.update(value=None, choices=STYLE_NAMES) + + sd_gen.model.load_style_file(json) + 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]) + + with gr.Accordion("Other settings", open=False, visible=True) as menu_other: + with gr.Row(): + save_generated_images_gui = gr.Checkbox(value=False, label="Save Generated Images") + 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) + with gr.Row(): + 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.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=True, label="Retain task model in cache") + 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=False, 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") + xformers_memory_efficient_attention_gui = gr.Checkbox(value=False, label="Xformers Memory Efficient Attention") + + with gr.Accordion("Examples and help", open=True, visible=True) as menu_example: + gr.Examples( + examples=EXAMPLES_GUI, + fn=sd_gen.generate_pipeline, + inputs=[ + prompt_gui, + neg_prompt_gui, + num_images_gui, + steps_gui, + cfg_gui, + clip_skip_gui, + seed_gui, + sampler_gui, + img_height_gui, + img_width_gui, + model_name_gui, + ], + outputs=[load_model_gui, result_images, actual_task_info], + cache_examples=False, + #elem_id="examples", + ) + + gr.Markdown(RESOURCES) +## END MOD + + with gr.Tab(th.t("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(label="Base image", show_label=True, brush=gr.Brush(colors=["#000000"])) + image_base = gr.ImageEditor( + sources=["upload", "clipboard"], + # crop_size="1:1", + # 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 + ] + ), + eraser=gr.Eraser(default_size="16") + ) + 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) + btn_send = gr.Button("Send to the first tab") + + btn.click(create_mask_now, [image_base, invert_mask], [img_source, img_result]) + + def send_img(img_source, img_result): + return img_source, img_result + btn_send.click(send_img, [img_source, img_result], [image_control, image_mask_gui]) + + with gr.Tab(th.t("PNG Info")): + with gr.Row(): + with gr.Column(): + image_metadata = gr.Image(label="Image with metadata", type="pil", sources=["upload"]) + + with gr.Column(): + result_metadata = gr.Textbox(label="Metadata", show_label=True, show_copy_button=True, interactive=False, container=True, max_lines=99) + + image_metadata.change( + fn=extract_exif_data, + inputs=[image_metadata], + outputs=[result_metadata], + ) + + with gr.Tab(th.t("Upscaler")): + 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_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") + + with gr.Column(): + result_up_tab = gr.Image(label="Result", type="pil", interactive=False, format="png") + + generate_button_up_tab.click( + fn=process_upscale, + inputs=[image_up_tab, upscaler_tab, upscaler_size_tab], + outputs=[result_up_tab], + ) + + with gr.Tab(th.t("Preprocessor"), render=True): + preprocessor_tab() + +## BEGIN MOD + interface_mode_gui.change( + change_interface_mode, + [interface_mode_gui], + [menu_model, menu_from_image, menu_negative, menu_gen, menu_hires, menu_lora, menu_advanced, + menu_example, task_gui, quick_speed_gui], + queue=False, + ) + model_name_gui.change(get_t2i_model_info, [model_name_gui], [model_info_gui], queue=False) + translate_prompt_gui.click(translate_to_en, [prompt_gui], [prompt_gui], queue=False)\ + .then(translate_to_en, [neg_prompt_gui], [neg_prompt_gui], queue=False) + + gr.on( + triggers=[quick_model_type_gui.change, quick_genre_gui.change, quick_speed_gui.change, quick_aspect_gui.change], + fn=set_quick_presets, + inputs=[quick_genre_gui, quick_model_type_gui, quick_speed_gui, quick_aspect_gui], + outputs=[quality_selector_gui, style_selector_gui, sampler_selector_gui, optimization_gui, insert_prompt_gui], + queue=False, + trigger_mode="once", + ) + gr.on( + triggers=[quality_selector_gui.change, style_selector_gui.change, insert_prompt_gui.change], + fn=process_style_prompt, + inputs=[prompt_gui, neg_prompt_gui, style_selector_gui, quality_selector_gui, insert_prompt_gui], + outputs=[prompt_gui, neg_prompt_gui, quick_model_type_gui], + queue=False, + trigger_mode="once", + ) + sampler_selector_gui.change(set_sampler_settings, [sampler_selector_gui], [sampler_gui, steps_gui, cfg_gui, clip_skip_gui, img_width_gui, img_height_gui, optimization_gui], queue=False) + optimization_gui.change(set_optimization, [optimization_gui, steps_gui, cfg_gui, sampler_gui, clip_skip_gui, lora5_gui, lora_scale_5_gui], [steps_gui, cfg_gui, sampler_gui, clip_skip_gui, lora5_gui, lora_scale_5_gui], queue=False) + + gr.on( + triggers=[lora1_gui.change, lora_scale_1_gui.change, lora2_gui.change, lora_scale_2_gui.change, + lora3_gui.change, lora_scale_3_gui.change, lora4_gui.change, lora_scale_4_gui.change, + lora5_gui.change, lora_scale_5_gui.change, lora6_gui.change, lora_scale_6_gui.change, + lora7_gui.change, lora_scale_7_gui.change, prompt_syntax_gui.change], + fn=update_loras, + inputs=[prompt_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], + outputs=[prompt_gui, lora1_gui, lora_scale_1_gui, lora1_info_gui, lora1_copy_gui, lora1_desc_gui, + lora2_gui, lora_scale_2_gui, lora2_info_gui, lora2_copy_gui, lora2_desc_gui, + lora3_gui, lora_scale_3_gui, lora3_info_gui, lora3_copy_gui, lora3_desc_gui, + lora4_gui, lora_scale_4_gui, lora4_info_gui, lora4_copy_gui, lora4_desc_gui, + lora5_gui, lora_scale_5_gui, lora5_info_gui, lora5_copy_gui, lora5_desc_gui, + lora6_gui, lora_scale_6_gui, lora6_info_gui, lora6_copy_gui, lora6_desc_gui, + lora7_gui, lora_scale_7_gui, lora7_info_gui, lora7_copy_gui, lora7_desc_gui], + queue=False, + trigger_mode="once", + ) + lora1_copy_gui.click(apply_lora_prompt, [prompt_gui, lora1_info_gui], [prompt_gui], queue=False) + lora2_copy_gui.click(apply_lora_prompt, [prompt_gui, lora2_info_gui], [prompt_gui], queue=False) + lora3_copy_gui.click(apply_lora_prompt, [prompt_gui, lora3_info_gui], [prompt_gui], queue=False) + lora4_copy_gui.click(apply_lora_prompt, [prompt_gui, lora4_info_gui], [prompt_gui], queue=False) + lora5_copy_gui.click(apply_lora_prompt, [prompt_gui, lora5_info_gui], [prompt_gui], queue=False) + lora6_copy_gui.click(apply_lora_prompt, [prompt_gui, lora6_info_gui], [prompt_gui], queue=False) + lora7_copy_gui.click(apply_lora_prompt, [prompt_gui, lora7_info_gui], [prompt_gui], queue=False) + gr.on( + triggers=[search_civitai_button_lora.click, search_civitai_query_lora.submit], + fn=search_civitai_lora, + inputs=[search_civitai_query_lora, search_civitai_basemodel_lora, search_civitai_sort_lora, search_civitai_period_lora, + search_civitai_tag_lora, search_civitai_user_lora, search_civitai_gallery_lora], + outputs=[search_civitai_result_lora, search_civitai_desc_lora, search_civitai_button_lora, search_civitai_query_lora, search_civitai_gallery_lora], + queue=True, + scroll_to_output=True, + ) + search_civitai_result_lora.change(select_civitai_lora, [search_civitai_result_lora], [text_lora, search_civitai_desc_lora], queue=False, scroll_to_output=True) + search_civitai_gallery_lora.select(update_civitai_selection, None, [search_civitai_result_lora], queue=False, show_api=False) + 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], scroll_to_output=True) + upload_button_lora.upload(upload_file_lora, [upload_button_lora], [file_output_lora, upload_button_lora]).success( + move_file_lora, [file_output_lora], [lora1_gui, lora2_gui, lora3_gui, lora4_gui, lora5_gui, lora6_gui, lora7_gui], scroll_to_output=True) + + use_textual_inversion_gui.change(set_textual_inversion_prompt, [use_textual_inversion_gui, prompt_gui, neg_prompt_gui, prompt_syntax_gui], [prompt_gui, neg_prompt_gui]) + + generate_from_image_btn_gui.click( + lambda: ("", "", ""), None, [series_dbt, character_dbt, prompt_gui], queue=False, + ).success( + predict_tags_wd, + [input_image_gui, prompt_gui, image_algorithms, general_threshold_gui, character_threshold_gui], + [series_dbt, character_dbt, prompt_gui, copy_button_dbt], + ).success( + compose_prompt_to_copy, [character_dbt, series_dbt, prompt_gui], [prompt_gui], queue=False, + ).success( + remove_specific_prompt, [prompt_gui, keep_tags_gui], [prompt_gui], queue=False, + ).success( + convert_danbooru_to_e621_prompt, [prompt_gui, tag_type_gui], [prompt_gui], queue=False, + ).success( + insert_recom_prompt, [prompt_gui, neg_prompt_gui, recom_prompt_gui], [prompt_gui, neg_prompt_gui], queue=False, + ) + + prompt_type_button.click(convert_danbooru_to_e621_prompt, [prompt_gui, prompt_type_gui], [prompt_gui], queue=False) + random_character_gui.click(select_random_character, [series_dbt, character_dbt], [series_dbt, character_dbt], queue=False) + generate_db_random_button.click( + v2_random_prompt, + [prompt_gui, series_dbt, character_dbt, + rating_dbt, aspect_ratio_dbt, length_dbt, identity_dbt, ban_tags_dbt, model_name_dbt], + [prompt_gui, series_dbt, character_dbt], + ).success( + convert_danbooru_to_e621_prompt, [prompt_gui, tag_type_gui], [prompt_gui], queue=False, + ) + + translate_prompt_button.click(translate_prompt, [prompt_gui], [prompt_gui], queue=False) + translate_prompt_button.click(translate_prompt, [character_dbt], [character_dbt], queue=False) + translate_prompt_button.click(translate_prompt, [series_dbt], [series_dbt], queue=False) + + generate_button.click( + fn=insert_model_recom_prompt, + inputs=[prompt_gui, neg_prompt_gui, model_name_gui, recom_prompt_gui], + outputs=[prompt_gui, neg_prompt_gui], + queue=False, + ).success( + fn=sd_gen.load_new_model, + inputs=[ + model_name_gui, + vae_model_gui, + task_gui, + controlnet_model_gui, + ], + outputs=[load_model_gui], + queue=True, + show_progress="minimal", + ).success( + fn=sd_gen_generate_pipeline, + inputs=[ + prompt_gui, + neg_prompt_gui, + num_images_gui, + steps_gui, + cfg_gui, + clip_skip_gui, + seed_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, + sampler_gui, + schedule_type_gui, + schedule_prediction_type_gui, + img_height_gui, + img_width_gui, + model_name_gui, + vae_model_gui, + task_gui, + image_control, + preprocessor_name_gui, + preprocess_resolution_gui, + image_resolution_gui, + style_prompt_gui, + style_json_gui, + image_mask_gui, + strength_gui, + low_threshold_gui, + 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, + active_textual_inversion_gui, + prompt_syntax_gui, + upscaler_model_path_gui, + upscaler_increases_size_gui, + upscaler_tile_size_gui, + upscaler_tile_overlap_gui, + hires_steps_gui, + hires_denoising_strength_gui, + hires_sampler_gui, + hires_prompt_gui, + 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, + retain_hires_model_previous_load_gui, + t2i_adapter_preprocessor_gui, + adapter_conditioning_scale_gui, + adapter_conditioning_factor_gui, + xformers_memory_efficient_attention_gui, + free_u_gui, + generator_in_cpu_gui, + adetailer_inpaint_only_gui, + adetailer_verbose_gui, + adetailer_sampler_gui, + adetailer_active_a_gui, + prompt_ad_a_gui, + negative_prompt_ad_a_gui, + strength_ad_a_gui, + face_detector_ad_a_gui, + person_detector_ad_a_gui, + hand_detector_ad_a_gui, + mask_dilation_a_gui, + mask_blur_a_gui, + mask_padding_a_gui, + adetailer_active_b_gui, + prompt_ad_b_gui, + negative_prompt_ad_b_gui, + strength_ad_b_gui, + face_detector_ad_b_gui, + person_detector_ad_b_gui, + hand_detector_ad_b_gui, + mask_dilation_b_gui, + mask_blur_b_gui, + mask_padding_b_gui, + retain_task_cache_gui, + guidance_rescale_gui, + image_ip1, + mask_ip1, + model_ip1, + mode_ip1, + scale_ip1, + image_ip2, + mask_ip2, + model_ip2, + 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], + queue=True, + show_progress="full", + ).success(save_gallery_images, [result_images, model_name_gui], [result_images, result_images_files], queue=False, show_api=False)\ + .success(save_gallery_history, [result_images, result_images_files, history_gallery, history_files], [history_gallery, history_files], queue=False, show_api=False) + + with gr.Tab(th.t("Danbooru Tags Transformer with WD Tagger"), render=True): + with gr.Column(scale=2): + with gr.Group(): + input_image = gr.Image(label="Input image", type="pil", sources=["upload", "clipboard"], height=256) + with gr.Accordion(label="Advanced options", open=False): + general_threshold = gr.Slider(label="Threshold", minimum=0.0, maximum=1.0, value=0.3, step=0.01, interactive=True) + character_threshold = gr.Slider(label="Character threshold", minimum=0.0, maximum=1.0, value=0.8, step=0.01, interactive=True) + input_tag_type = gr.Radio(label="Convert tags to", info="danbooru for Animagine, e621 for Pony.", choices=["danbooru", "e621"], value="danbooru") + recom_prompt = gr.Radio(label="Insert reccomended prompt", choices=["None", "Animagine", "Pony"], value="None", interactive=True) + image_algorithms = gr.CheckboxGroup(["Use WD Tagger"], label="Algorithms", value=["Use WD Tagger"], visible=False) + keep_tags = gr.Radio(label="Remove tags leaving only the following", choices=["body", "dress", "all"], value="all") + generate_from_image_btn = gr.Button(value="GENERATE TAGS FROM IMAGE", size="lg", variant="primary") + with gr.Group(): + with gr.Row(): + input_character = gr.Textbox(label="Character tags", placeholder="hatsune miku") + input_copyright = gr.Textbox(label="Copyright tags", placeholder="vocaloid") + pick_random_character = gr.Button(value="Random character 🎲", size="sm") + input_general = gr.TextArea(label="General tags", lines=4, placeholder="1girl, ...", value="") + input_tags_to_copy = gr.Textbox(value="", visible=False) + with gr.Row(): + copy_input_btn = gr.Button(value="Copy to clipboard", size="sm", interactive=False) + copy_prompt_btn_input = gr.Button(value="Copy to primary prompt", size="sm", interactive=False) + translate_input_prompt_button = gr.Button(value="Translate prompt to English", size="sm", variant="secondary") + tag_type = gr.Radio(label="Output tag conversion", info="danbooru for Animagine, e621 for Pony.", choices=["danbooru", "e621"], value="e621", visible=False) + input_rating = gr.Radio(label="Rating", choices=list(V2_RATING_OPTIONS), value="explicit") + with gr.Accordion(label="Advanced options", open=False): + input_aspect_ratio = gr.Radio(label="Aspect ratio", info="The aspect ratio of the image.", choices=list(V2_ASPECT_RATIO_OPTIONS), value="square") + input_length = gr.Radio(label="Length", info="The total length of the tags.", choices=list(V2_LENGTH_OPTIONS), value="very_long") + input_identity = gr.Radio(label="Keep identity", info="How strictly to keep the identity of the character or subject. If you specify the detail of subject in the prompt, you should choose `strict`. Otherwise, choose `none` or `lax`. `none` is very creative but sometimes ignores the input prompt.", choices=list(V2_IDENTITY_OPTIONS), value="lax") + input_ban_tags = gr.Textbox(label="Ban tags", info="Tags to ban from the output.", placeholder="alternate costumen, ...", value="censored") + model_name = gr.Dropdown(label="Model", choices=list(V2_ALL_MODELS.keys()), value=list(V2_ALL_MODELS.keys())[0]) + dummy_np = gr.Textbox(label="Negative prompt", value="", visible=False) + recom_animagine = gr.Textbox(label="Animagine reccomended prompt", value="Animagine", visible=False) + recom_pony = gr.Textbox(label="Pony reccomended prompt", value="Pony", visible=False) + generate_btn = gr.Button(value="GENERATE TAGS", size="lg", variant="primary") + with gr.Row(): + with gr.Group(): + output_text = gr.TextArea(label="Output tags", interactive=False, show_copy_button=True) + with gr.Row(): + copy_btn = gr.Button(value="Copy to clipboard", size="sm", interactive=False) + copy_prompt_btn = gr.Button(value="Copy to primary prompt", size="sm", interactive=False) + with gr.Group(): + output_text_pony = gr.TextArea(label="Output tags (Pony e621 style)", interactive=False, show_copy_button=True) + with gr.Row(): + copy_btn_pony = gr.Button(value="Copy to clipboard", size="sm", interactive=False) + copy_prompt_btn_pony = gr.Button(value="Copy to primary prompt", size="sm", interactive=False) + description_ui() + + translate_input_prompt_button.click(translate_prompt, inputs=[input_general], outputs=[input_general], queue=False) + translate_input_prompt_button.click(translate_prompt, inputs=[input_character], outputs=[input_character], queue=False) + translate_input_prompt_button.click(translate_prompt, inputs=[input_copyright], outputs=[input_copyright], queue=False) + + generate_from_image_btn.click( + lambda: ("", "", ""), None, [input_copyright, input_character, input_general], queue=False, + ).success( + predict_tags_wd, + [input_image, input_general, image_algorithms, general_threshold, character_threshold], + [input_copyright, input_character, input_general, copy_input_btn], + ).success( + remove_specific_prompt, inputs=[input_general, keep_tags], outputs=[input_general], queue=False, + ).success( + convert_danbooru_to_e621_prompt, inputs=[input_general, input_tag_type], outputs=[input_general], queue=False, + ).success( + insert_recom_prompt, inputs=[input_general, dummy_np, recom_prompt], outputs=[input_general, dummy_np], queue=False, + ).success(lambda: gr.update(interactive=True), None, [copy_prompt_btn_input], queue=False) + copy_input_btn.click(compose_prompt_to_copy, inputs=[input_character, input_copyright, input_general], outputs=[input_tags_to_copy])\ + .success(gradio_copy_text, inputs=[input_tags_to_copy], js=COPY_ACTION_JS) + copy_prompt_btn_input.click(compose_prompt_to_copy, inputs=[input_character, input_copyright, input_general], outputs=[input_tags_to_copy])\ + .success(gradio_copy_prompt, inputs=[input_tags_to_copy], outputs=[prompt_gui]) + + pick_random_character.click(select_random_character, [input_copyright, input_character], [input_copyright, input_character]) + + generate_btn.click( + v2_upsampling_prompt, + [model_name, input_copyright, input_character, input_general, + input_rating, input_aspect_ratio, input_length, input_identity, input_ban_tags], + [output_text], + ).success( + convert_danbooru_to_e621_prompt, inputs=[output_text, tag_type], outputs=[output_text_pony], queue=False, + ).success( + insert_recom_prompt, inputs=[output_text, dummy_np, recom_animagine], outputs=[output_text, dummy_np], queue=False, + ).success( + insert_recom_prompt, inputs=[output_text_pony, dummy_np, recom_pony], outputs=[output_text_pony, dummy_np], queue=False, + ).success(lambda: (gr.update(interactive=True), gr.update(interactive=True), gr.update(interactive=True), gr.update(interactive=True)), + None, [copy_btn, copy_btn_pony, copy_prompt_btn, copy_prompt_btn_pony], queue=False) + copy_btn.click(gradio_copy_text, inputs=[output_text], js=COPY_ACTION_JS) + copy_btn_pony.click(gradio_copy_text, inputs=[output_text_pony], js=COPY_ACTION_JS) + copy_prompt_btn.click(gradio_copy_prompt, inputs=[output_text], outputs=[prompt_gui]) + copy_prompt_btn_pony.click(gradio_copy_prompt, inputs=[output_text_pony], outputs=[prompt_gui]) + + gr.LoginButton() + gr.DuplicateButton(value="Duplicate Space for private use (This demo does not work on CPU. Requires GPU Space)") + +app.queue() +th.translate_civitai_constants(app) +app.launch(show_error=True, debug=True) # allowed_paths=["./images/"], show_error=True, debug=True +## END MOD + +# 自定义一些额外的翻译 +def custom_translate(text): + """自定义翻译函数,以处理特殊情况""" + return translate_ui.translate_text(text)