diff --git a/TODO.md b/TODO.md index 0a5b0e99d..503154a59 100644 --- a/TODO.md +++ b/TODO.md @@ -11,13 +11,14 @@ Stuff to be fixed... Stuff to be added... -- Update README +- Update `README.md` - Add Gradio theme maker - Transformers version - Create new GitHub hooks/actions for CI/CD - Redo Extensions tab: see - Stream-load models as option for slow storage - Auto-test `torch.layer_norm` for FP16 +- Monitor file changes by misbehaving extensions ## Investigate diff --git a/modules/cmd_args.py b/modules/cmd_args.py index fdc9ab240..0d1da94ef 100644 --- a/modules/cmd_args.py +++ b/modules/cmd_args.py @@ -1,81 +1,82 @@ import argparse import os -from modules.paths_internal import data_path, sd_default_config, sd_model_file +from modules.paths_internal import data_path -parser = argparse.ArgumentParser(description="Stable Diffusion", conflict_handler='resolve', formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=55, indent_increment=2, width=200)) +parser = argparse.ArgumentParser(description="SD.Next", conflict_handler='resolve', epilog='For other options see UI Settings page', prog='', add_help=True, formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=55, indent_increment=2, width=200)) +parser._optionals = parser.add_argument_group('Other options') # pylint: disable=protected-access +group = parser.add_argument_group('Server options') +# group.add_argument("--config", type=str, default=sd_default_config, help=argparse.SUPPRESS) -parser.add_argument("-f", action='store_true', help=argparse.SUPPRESS) # allows running as root; implemented outside of webui -parser.add_argument("--ui-settings-file", type=str, help=argparse.SUPPRESS, default=os.path.join(data_path, 'config.json')) -parser.add_argument("--ui-config-file", type=str, help=argparse.SUPPRESS, default=os.path.join(data_path, 'ui-config.json')) -parser.add_argument("--config", type=str, default=sd_default_config, help=argparse.SUPPRESS) -parser.add_argument("--theme", type=str, help=argparse.SUPPRESS, default=None) +group.add_argument("-f", action='store_true', help=argparse.SUPPRESS) # allows running as root; implemented outside of webui +group.add_argument("--ui-settings-file", type=str, help=argparse.SUPPRESS, default=os.path.join(data_path, 'config.json')) +group.add_argument("--ui-config-file", type=str, help=argparse.SUPPRESS, default=os.path.join(data_path, 'ui-config.json')) +group.add_argument("--hide-ui-dir-config", action='store_true', help=argparse.SUPPRESS, default=False) +group.add_argument("--theme", type=str, help=argparse.SUPPRESS, default=None) +group.add_argument("--disable-console-progressbars", action='store_true', help=argparse.SUPPRESS, default=True) +group.add_argument("--disable-safe-unpickle", action='store_true', help=argparse.SUPPRESS, default=True) +group.add_argument("--lowram", action='store_true', help=argparse.SUPPRESS) -parser.add_argument("--medvram", action='store_true', help="Enable model optimizations for sacrificing a little speed for low memory usage") -parser.add_argument("--lowvram", action='store_true', help="Enable model optimizations for sacrificing a lot of speed for lowest memory usage") -parser.add_argument("--lowram", action='store_true', help="Load checkpoint weights to VRAM instead of RAM") - -parser.add_argument("--ckpt", type=str, default=sd_model_file, help="Path to checkpoint of stable diffusion model to load immediately",) -parser.add_argument('--vae', type=str, help='Path to checkpoint of stable diffusion VAE model to load immediately', default=None) -parser.add_argument("--data-dir", type=str, default=os.path.dirname(os.path.dirname(os.path.realpath(__file__))), help="Base path where all user data is stored") -parser.add_argument("--models-dir", type=str, default="models", help="Nase path where all models are stored",) - -parser.add_argument("--allow-code", action='store_true', help="Allow custom script execution") -parser.add_argument("--share", action='store_true', help="Enable to make the UI accessible through Gradio site") -parser.add_argument("--enable-insecure", action='store_true', help="Enable extensions tab regardless of other options") -parser.add_argument("--use-cpu", nargs='+', help="Force use CPU for specified modules", default=[], type=str.lower) -parser.add_argument("--use-ipex", action='store_true', help="Force use Intel OneAPI XPU backend") -parser.add_argument("--listen", action='store_true', help="Launch web server using public IP address") -parser.add_argument("--port", type=int, help="Launch web server with given server port", default=None) -parser.add_argument("--hide-ui-dir-config", action='store_true', help="Hide directory configuration from UI", default=False) -parser.add_argument("--freeze-settings", action='store_true', help="Disable editing settings", default=False) -parser.add_argument("--gradio-auth", type=str, help='Set Gradio authentication like "username:password,username:password""', default=None) -parser.add_argument("--gradio-auth-path", type=str, help='Set Gradio authentication using file', default=None) -parser.add_argument("--autolaunch", action='store_true', help="Open the UI URL in the system's default browser upon launch", default=False) -parser.add_argument("--disable-console-progressbars", action='store_true', help="Do not output progressbars to console", default=True) -parser.add_argument("--disable-safe-unpickle", action='store_true', help="Disable checking models for malicious code", default=True) -parser.add_argument("--api-auth", type=str, help='Set API authentication', default=None) -parser.add_argument("--api-log", action='store_true', help="Enable logging of all API requests") -parser.add_argument("--device-id", type=str, help="Select the default CUDA device to use", default=None) -parser.add_argument("--cors-origins", type=str, help="Allowed CORS origin(s) in the form of a comma-separated list", default=None) -parser.add_argument("--cors-regex", type=str, help="Allowed CORS origin(s) in the form of a single regular expression", default=None) -parser.add_argument("--tls-keyfile", type=str, help="Partially enables TLS, requires --tls-certfile to fully function", default=None) -parser.add_argument("--tls-certfile", type=str, help="Partially enables TLS, requires --tls-keyfile to fully function", default=None) -parser.add_argument("--server-name", type=str, help="Sets hostname of server", default=None) -parser.add_argument("--no-hashing", action='store_true', help="Disable sha256 hashing of checkpoints", default=False) -parser.add_argument("--no-download-sd-model", action='store_true', help="Disable download of default model even if no model is found", default=False) -parser.add_argument("--profile", action='store_true', help="Run profiler, default: %(default)s") -parser.add_argument("--disable-queue", action='store_true', help="Disable Gradio queues and force use of HTTP instead of WebSockets, default: %(default)s") +group.add_argument("--config", type=str, default=os.path.join(data_path, 'config.json'), help="Use specific configuration file, default: %(default)s") +group.add_argument("--medvram", action='store_true', help="Split model stages and keep only active part in VRAM, default: %(default)s") +group.add_argument("--lowvram", action='store_true', help="Split model components and keep only active part in VRAM, default: %(default)s") +group.add_argument("--ckpt", type=str, default=None, help="Path to model checkpoint to load immediately, default: %(default)s") +group.add_argument('--vae', type=str, default=None, help='Path to VAE checkpoint to load immediately, default: %(default)s') +group.add_argument("--data-dir", type=str, default=os.path.dirname(os.path.dirname(os.path.realpath(__file__))), help="Base path where all user data is stored, default: %(default)s") +group.add_argument("--models-dir", type=str, default="models", help="Base path where all models are stored, default: %(default)s",) +group.add_argument("--allow-code", action='store_true', help="Allow custom script execution, default: %(default)s") +group.add_argument("--share", action='store_true', help="Enable UI accessible through Gradio site, default: %(default)s") +group.add_argument("--insecure", action='store_true', help="Enable extensions tab regardless of other options, default: %(default)s") +group.add_argument("--use-cpu", nargs='+', default=[], type=str.lower, help="Force use CPU for specified modules, default: %(default)s") +group.add_argument("--use-ipex", action='store_true', help="Force use Intel OneAPI XPU backend, default: %(default)s", default=False) +group.add_argument("--listen", action='store_true', help="Launch web server using public IP address, default: %(default)s") +group.add_argument("--port", type=int, default=7860, help="Launch web server with given server port, default: %(default)s") +group.add_argument("--freeze", action='store_true', help="Disable editing settings", default=False) +group.add_argument("--auth", type=str, help='Set access authentication like "user:pwd,user:pwd""', default=None) +group.add_argument("--authfile", type=str, help='Set access authentication using file, default: %(default)s', default=None) +group.add_argument("--autolaunch", action='store_true', help="Open the UI URL in the system's default browser upon launch", default=False) +group.add_argument("--api-auth", type=str, help='Set API authentication, default: %(default)s', default=None) +group.add_argument("--api-log", default=False, action='store_true', help="Enable logging of all API requests, default: %(default)s") +group.add_argument("--device-id", type=str, help="Select the default CUDA device to use, default: %(default)s", default=None) +group.add_argument("--cors-origins", type=str, help="Allowed CORS origins as comma-separated list, default: %(default)s", default=None) +group.add_argument("--cors-regex", type=str, help="Allowed CORS origins as regular expression, default: %(default)s", default=None) +group.add_argument("--tls-keyfile", type=str, help="Enable TLS and specify key file, default: %(default)s", default=None) +group.add_argument("--tls-certfile", type=str, help="Enable TLS and specify cert file, default: %(default)s", default=None) +group.add_argument("--server-name", type=str, help="Sets hostname of server, default: %(default)s", default=None) +group.add_argument("--no-hashing", action='store_true', help="Disable hashing of checkpoints, default: %(default)s", default=False) +group.add_argument("--no-download", action='store_true', help="Disable download of default model, default: %(default)s", default=False) +group.add_argument("--profile", action='store_true', help="Run profiler, default: %(default)s") +group.add_argument("--disable-queue", action='store_true', help="Disable queues, default: %(default)s") def compatibility_args(opts, args): - parser.add_argument("--ckpt-dir", type=str, help=argparse.SUPPRESS, default=opts.ckpt_dir) - parser.add_argument("--vae-dir", type=str, help=argparse.SUPPRESS, default=opts.vae_dir) - parser.add_argument("--embeddings-dir", type=str, help=argparse.SUPPRESS, default=opts.embeddings_dir) - parser.add_argument("--embeddings-templates-dir", type=str, help=argparse.SUPPRESS, default=opts.embeddings_templates_dir) - parser.add_argument("--hypernetwork-dir", type=str, help=argparse.SUPPRESS, default=opts.hypernetwork_dir) - parser.add_argument("--codeformer-models-path", type=str, help=argparse.SUPPRESS, default=opts.codeformer_models_path) - parser.add_argument("--gfpgan-models-path", type=str, help=argparse.SUPPRESS, default=opts.gfpgan_models_path) - parser.add_argument("--esrgan-models-path", type=str, help=argparse.SUPPRESS, default=opts.esrgan_models_path) - parser.add_argument("--bsrgan-models-path", type=str, help=argparse.SUPPRESS, default=opts.bsrgan_models_path) - parser.add_argument("--realesrgan-models-path", type=str, help=argparse.SUPPRESS, default=opts.realesrgan_models_path) - parser.add_argument("--scunet-models-path", help=argparse.SUPPRESS, default=opts.scunet_models_path) - parser.add_argument("--swinir-models-path", help=argparse.SUPPRESS, default=opts.swinir_models_path) - parser.add_argument("--ldsr-models-path", help=argparse.SUPPRESS, default=opts.ldsr_models_path) - parser.add_argument("--clip-models-path", type=str, help=argparse.SUPPRESS, default=opts.clip_models_path) - parser.add_argument("--disable-extension-access", default = False, action='store_true', help=argparse.SUPPRESS) - parser.add_argument("--opt-channelslast", help=argparse.SUPPRESS, default=opts.opt_channelslast) - parser.add_argument("--xformers", default = (opts.cross_attention_optimization == "xFormers"), action='store_true', help=argparse.SUPPRESS) - parser.add_argument("--disable-nan-check", help=argparse.SUPPRESS, default=opts.disable_nan_check) - parser.add_argument("--token-merging", help=argparse.SUPPRESS, default=opts.token_merging) - parser.add_argument("--rollback-vae", help=argparse.SUPPRESS, default=opts.rollback_vae) - parser.add_argument("--no-half", help=argparse.SUPPRESS, default=opts.no_half) - parser.add_argument("--no-half-vae", help=argparse.SUPPRESS, default=opts.no_half_vae) - parser.add_argument("--precision", help=argparse.SUPPRESS, default=opts.precision) - parser.add_argument("--api", help=argparse.SUPPRESS, default=True) - parser.add_argument("--sub-quad-q-chunk-size", help=argparse.SUPPRESS, default=opts.sub_quad_q_chunk_size) - parser.add_argument("--sub-quad-kv-chunk-size", help=argparse.SUPPRESS, default=opts.sub_quad_kv_chunk_size) - parser.add_argument("--sub-quad-chunk-threshold", help=argparse.SUPPRESS, default=opts.sub_quad_chunk_threshold) - parser.add_argument('--debug', default = False, action='store_true', help = "Run installer with debug logging, default: %(default)s") + group.add_argument("--ckpt-dir", type=str, help=argparse.SUPPRESS, default=opts.ckpt_dir) + group.add_argument("--vae-dir", type=str, help=argparse.SUPPRESS, default=opts.vae_dir) + group.add_argument("--embeddings-dir", type=str, help=argparse.SUPPRESS, default=opts.embeddings_dir) + group.add_argument("--embeddings-templates-dir", type=str, help=argparse.SUPPRESS, default=opts.embeddings_templates_dir) + group.add_argument("--hypernetwork-dir", type=str, help=argparse.SUPPRESS, default=opts.hypernetwork_dir) + group.add_argument("--codeformer-models-path", type=str, help=argparse.SUPPRESS, default=opts.codeformer_models_path) + group.add_argument("--gfpgan-models-path", type=str, help=argparse.SUPPRESS, default=opts.gfpgan_models_path) + group.add_argument("--esrgan-models-path", type=str, help=argparse.SUPPRESS, default=opts.esrgan_models_path) + group.add_argument("--bsrgan-models-path", type=str, help=argparse.SUPPRESS, default=opts.bsrgan_models_path) + group.add_argument("--realesrgan-models-path", type=str, help=argparse.SUPPRESS, default=opts.realesrgan_models_path) + group.add_argument("--scunet-models-path", help=argparse.SUPPRESS, default=opts.scunet_models_path) + group.add_argument("--swinir-models-path", help=argparse.SUPPRESS, default=opts.swinir_models_path) + group.add_argument("--ldsr-models-path", help=argparse.SUPPRESS, default=opts.ldsr_models_path) + group.add_argument("--clip-models-path", type=str, help=argparse.SUPPRESS, default=opts.clip_models_path) + group.add_argument("--disable-extension-access", default = False, action='store_true', help=argparse.SUPPRESS) + group.add_argument("--opt-channelslast", help=argparse.SUPPRESS, default=opts.opt_channelslast) + group.add_argument("--xformers", default = (opts.cross_attention_optimization == "xFormers"), action='store_true', help=argparse.SUPPRESS) + group.add_argument("--disable-nan-check", help=argparse.SUPPRESS, default=opts.disable_nan_check) + group.add_argument("--token-merging", help=argparse.SUPPRESS, default=opts.token_merging) + group.add_argument("--rollback-vae", help=argparse.SUPPRESS, default=opts.rollback_vae) + group.add_argument("--no-half", help=argparse.SUPPRESS, default=opts.no_half) + group.add_argument("--no-half-vae", help=argparse.SUPPRESS, default=opts.no_half_vae) + group.add_argument("--precision", help=argparse.SUPPRESS, default=opts.precision) + group.add_argument("--api", help=argparse.SUPPRESS, default=True) + group.add_argument("--sub-quad-q-chunk-size", help=argparse.SUPPRESS, default=opts.sub_quad_q_chunk_size) + group.add_argument("--sub-quad-kv-chunk-size", help=argparse.SUPPRESS, default=opts.sub_quad_kv_chunk_size) + group.add_argument("--sub-quad-chunk-threshold", help=argparse.SUPPRESS, default=opts.sub_quad_chunk_threshold) + group.add_argument('--debug', default = False, action='store_true', help = "Run installer with debug logging, default: %(default)s") opts.use_old_emphasis_implementation = False opts.use_old_karras_scheduler_sigmas = False @@ -94,7 +95,7 @@ def compatibility_args(opts, args): opts.print_hypernet_extra = False opts.dimensions_and_batch_together = True - parser.add_argument("--lora-dir", help=argparse.SUPPRESS, default=opts.lora_dir) + group.add_argument("--lora-dir", help=argparse.SUPPRESS, default=opts.lora_dir) args = parser.parse_args() if 'lyco_dir' in args: args.lyco_dir = opts.lyco_dir diff --git a/modules/generation_parameters_copypaste.py b/modules/generation_parameters_copypaste.py index 964432d72..b6609e224 100644 --- a/modules/generation_parameters_copypaste.py +++ b/modules/generation_parameters_copypaste.py @@ -316,7 +316,7 @@ infotext_to_setting_name_mapping = [ ('Token merging merge attention', 'token_merging_merge_attention'), ('Token merging merge cross attention', 'token_merging_merge_cross_attention'), ('Token merging merge mlp', 'token_merging_merge_mlp'), - ('Token merging maximum downsampling', 'token_merging_maximum_downsampling'), + ('Token merging maximum downsampling', 'token_merging_maximum_down_sampling'), ('Token merging stride x', 'token_merging_stride_x'), ('Token merging stride y', 'token_merging_stride_y') ] diff --git a/modules/sd_hijack.py b/modules/sd_hijack.py index 6d2bb3b0f..49acdf3dd 100644 --- a/modules/sd_hijack.py +++ b/modules/sd_hijack.py @@ -96,12 +96,12 @@ def undo_optimizations(): def fix_checkpoint(): """checkpoints are now added and removed in embedding/hypernet code, since torch doesn't want checkpoints to be added when not training (there's a warning)""" - pass + pass # pylint: disable=unnecessary-pass def weighted_loss(sd_model, pred, target, mean=True): #Calculate the weight normally, but ignore the mean - loss = sd_model._old_get_loss(pred, target, mean=False) + loss = sd_model._old_get_loss(pred, target, mean=False) # pylint: disable=protected-access #Check if we have weights available weight = getattr(sd_model, '_custom_loss_weight', None) @@ -114,12 +114,12 @@ def weighted_loss(sd_model, pred, target, mean=True): def weighted_forward(sd_model, x, c, w, *args, **kwargs): try: #Temporarily append weights to a place accessible during loss calc - sd_model._custom_loss_weight = w + sd_model._custom_loss_weight = w # pylint: disable=protected-access #Replace 'get_loss' with a weight-aware one. Otherwise we need to reimplement 'forward' completely #Keep 'get_loss', but don't overwrite the previous old_get_loss if it's already set if not hasattr(sd_model, '_old_get_loss'): - sd_model._old_get_loss = sd_model.get_loss + sd_model._old_get_loss = sd_model.get_loss # pylint: disable=protected-access sd_model.get_loss = MethodType(weighted_loss, sd_model) #Run the standard forward function, but with the patched 'get_loss' @@ -133,7 +133,7 @@ def weighted_forward(sd_model, x, c, w, *args, **kwargs): #If we have an old loss function, reset the loss function to the original one if hasattr(sd_model, '_old_get_loss'): - sd_model.get_loss = sd_model._old_get_loss + sd_model.get_loss = sd_model._old_get_loss # pylint: disable=protected-access del sd_model._old_get_loss def apply_weighted_forward(sd_model): @@ -182,8 +182,13 @@ class StableDiffusionModelHijack: if opts.cuda_compile and opts.cuda_compile_mode != 'none': try: import torch._dynamo as dynamo # pylint: disable=unused-import - torch._dynamo.config.verbose = True # pylint: disable=protected-access + torch._dynamo.config.verbose = opts.cuda_compile_verbose # pylint: disable=protected-access + torch._dynamo.config.suppress_errors = opts.cuda_compile_errors # pylint: disable=protected-access torch.backends.cudnn.benchmark = True + if opts.cuda_compile_mode == 'hidet': + import hidet + hidet.torch.dynamo_config.use_tensor_core(True) + hidet.torch.dynamo_config.search_space(2) m.model = torch.compile(m.model, mode="default", backend=opts.cuda_compile_mode, fullgraph=False, dynamic=False) print("Model compile enabled:", opts.cuda_compile_mode) except Exception as err: diff --git a/modules/sd_models.py b/modules/sd_models.py index 2e2b5f0a2..a7a9adeb9 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -122,7 +122,7 @@ def list_models(): checkpoint_info.register() print(f'Available models: {shared.opts.ckpt_dir} {len(checkpoints_list)}') if len(checkpoints_list) == 0: - if not shared.cmd_opts.no_download_sd_model: + if not shared.cmd_opts.no_download: key = input('Download the default model? (y/N) ') if key.lower().startswith('y'): model_url = "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.safetensors" diff --git a/modules/shared.py b/modules/shared.py index 12cb05b05..11177d0ac 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -49,7 +49,7 @@ ui_reorder_categories = [ "scripts", ] -cmd_opts.disable_extension_access = (cmd_opts.share or cmd_opts.listen or cmd_opts.server_name) and not cmd_opts.enable_insecure +cmd_opts.disable_extension_access = (cmd_opts.share or cmd_opts.listen or cmd_opts.server_name) and not cmd_opts.insecure devices.device, devices.device_interrogate, devices.device_gfpgan, devices.device_esrgan, devices.device_codeformer = (devices.cpu if any(y in cmd_opts.use_cpu for y in [x, 'all']) else devices.get_optimal_device() for x in ['sd', 'interrogate', 'gfpgan', 'esrgan', 'codeformer']) device = devices.device is_device_dml = False @@ -59,7 +59,7 @@ clip_model = None if device.type == 'privateuseone': - import modules.dml + import modules.dml # pylint: disable=ungrouped-imports is_device_dml = True @@ -252,8 +252,6 @@ options_templates.update(options_section(('system-paths', "System Paths"), { "ckpt_dir": OptionInfo(os.path.join(paths.models_path, 'Stable-diffusion'), "Path to directory with stable diffusion checkpoints"), "vae_dir": OptionInfo(os.path.join(paths.models_path, 'VAE'), "Path to directory with VAE files"), "embeddings_dir": OptionInfo(os.path.join(paths.models_path, 'embeddings'), "Embeddings directory for textual inversion"), - "embeddings_templates_dir": OptionInfo(os.path.join(paths.script_path, 'train/templates'), "Embeddings train templates directory"), - "embeddings_train_log": OptionInfo(os.path.join(paths.script_path, 'train.csv'), "Embeddings train log file"), "hypernetwork_dir": OptionInfo(os.path.join(paths.models_path, 'hypernetworks'), "Hypernetwork directory"), "codeformer_models_path": OptionInfo(os.path.join(paths.models_path, 'Codeformer'), "Path to directory with codeformer model file(s)."), "gfpgan_models_path": OptionInfo(os.path.join(paths.models_path, 'GFPGAN'), "Path to directory with GFPGAN model file(s)"), @@ -326,7 +324,9 @@ options_templates.update(options_section(('cuda', "CUDA Settings"), { "cuda_allow_tf32": OptionInfo(True, "Allow TF32 math ops"), "cuda_allow_tf16_reduced": OptionInfo(True, "Allow TF16 reduced precision math ops"), "cuda_compile": OptionInfo(False, "Enable model compile (experimental)"), - "cuda_compile_mode": OptionInfo("none", "Model compile mode (experimental)", gr.Radio, lambda: {"choices": ['none', 'inductor', 'cudagraphs', 'aot_ts_nvfuser']}), + "cuda_compile_mode": OptionInfo("none", "Model compile mode (experimental)", gr.Radio, lambda: {"choices": ['none', 'inductor', 'cudagraphs', 'aot_ts_nvfuser', 'hidet']}), + "cuda_compile_verbose": OptionInfo(True, "Model compile verbose mode"), + "cuda_compile_errors": OptionInfo(True, "Model compile suppress errors"), })) options_templates.update(options_section(('upscaling', "Upscaling"), { @@ -351,6 +351,8 @@ options_templates.update(options_section(('training', "Training"), { "save_training_settings_to_txt": OptionInfo(True, "Save textual inversion and hypernet settings to a text file whenever training starts."), "dataset_filename_word_regex": OptionInfo("", "Filename word regex"), "dataset_filename_join_string": OptionInfo(" ", "Filename join string"), + "embeddings_templates_dir": OptionInfo(os.path.join(paths.script_path, 'train', 'templates'), "Embeddings train templates directory"), + "embeddings_train_log": OptionInfo(os.path.join(paths.script_path, 'train', 'log', 'train.csv'), "Embeddings train log file"), "training_image_repeats_per_epoch": OptionInfo(1, "Number of repeats for a single input image per epoch; used only for displaying epoch number", gr.Number, {"precision": 0}), "training_write_csv_every": OptionInfo(0, "Save an csv containing the loss to log directory every N steps, 0 to disable"), "training_enable_tensorboard": OptionInfo(False, "Enable tensorboard logging."), @@ -428,14 +430,14 @@ options_templates.update(options_section(('sampler-params', "Sampler parameters" options_templates.update(options_section(('token_merging', 'Token Merging'), { "token_merging": OptionInfo(False, "Enable redundant token merging via tomesd. This can provide significant speed and memory improvements.", gr.Checkbox), - "token_merging_ratio": OptionInfo(0.5, "Merging Ratio", gr.Slider, {"minimum": 0, "maximum": 0.9, "step": 0.1}), + "token_merging_ratio": OptionInfo(0.5, "Merging Ratio. Higher merging ratio = faster generation, smaller VRAM usage, lower quality.", gr.Slider, {"minimum": 0, "maximum": 0.9, "step": 0.1}), "token_merging_hr_only": OptionInfo(True, "Apply only to high-res fix pass. Disabling can yield a ~20-35% speedup on contemporary resolutions.", gr.Checkbox), "token_merging_ratio_hr": OptionInfo(0.5, "Merging Ratio (high-res pass) - If 'Apply only to high-res' is enabled, this will always be the ratio used.", gr.Slider, {"minimum": 0, "maximum": 0.9, "step": 0.1}), "token_merging_random": OptionInfo(False, "Use random perturbations - Can improve outputs for certain samplers. For others, it may cause visual artifacting.", gr.Checkbox), - "token_merging_merge_attention": OptionInfo(True, "Merge attention", gr.Checkbox), - "token_merging_merge_cross_attention": OptionInfo(False, "Merge cross attention", gr.Checkbox), - "token_merging_merge_mlp": OptionInfo(False, "Merge mlp", gr.Checkbox), - "token_merging_maximum_down_sampling": OptionInfo(1, "Maximum down sampling", gr.Dropdown, lambda: {"choices": ["1", "2", "4", "8"]}), + "token_merging_merge_attention": OptionInfo(True, "Merge attention (Recommend on)", gr.Checkbox), + "token_merging_merge_cross_attention": OptionInfo(False, "Merge cross attention (Recommend off)", gr.Checkbox), + "token_merging_merge_mlp": OptionInfo(False, "Merge mlp (Strongly recommend off)", gr.Checkbox), + "token_merging_maximum_down_sampling": OptionInfo(1, "Maximum down sampling", gr.Radio, lambda: {"choices": [1, 2, 4, 8]}), "token_merging_stride_x": OptionInfo(2, "Stride - X", gr.Slider, {"minimum": 2, "maximum": 8, "step": 2}), "token_merging_stride_y": OptionInfo(2, "Stride - Y", gr.Slider, {"minimum": 2, "maximum": 8, "step": 2}) })) @@ -466,7 +468,7 @@ class Options: def __setattr__(self, key, value): if self.data is not None: if key in self.data or key in self.data_labels: - if cmd_opts.freeze_settings: + if cmd_opts.freeze: print(f'Settings are frozen: {key}') return if cmd_opts.hide_ui_dir_config and key in restricted_opts: @@ -512,7 +514,7 @@ class Options: return data_label.default def save(self, filename): - assert not cmd_opts.freeze_settings, "saving settings is disabled" + assert not cmd_opts.freeze, "saving settings is disabled" with open(filename, "w", encoding="utf8") as file: json.dump(self.data, file, indent=4) @@ -585,7 +587,7 @@ opts = Options() batch_cond_uncond = opts.always_batch_cond_uncond or not (cmd_opts.lowvram or cmd_opts.medvram) parallel_processing_allowed = not cmd_opts.lowvram and not cmd_opts.medvram xformers_available = False -config_filename = cmd_opts.ui_settings_file +config_filename = cmd_opts.config os.makedirs(opts.hypernetwork_dir, exist_ok=True) hypernetworks = {} loaded_hypernetworks = [] diff --git a/modules/textual_inversion/logging.py b/modules/textual_inversion/logging.py index edef48433..d0e52beb7 100644 --- a/modules/textual_inversion/logging.py +++ b/modules/textual_inversion/logging.py @@ -2,7 +2,7 @@ import datetime import json import os -saved_params_shared = {"model_name", "model_hash", "initial_step", "num_of_dataset_images", "learn_rate", "batch_size", "clip_grad_mode", "clip_grad_value", "gradient_step", "data_root", "log_directory", "training_width", "training_height", "steps", "create_image_every", "template_file", "gradient_step", "latent_sampling_method"} +saved_params_shared = {"model_name", "model_hash", "initial_step", "num_of_dataset_images", "learn_rate", "batch_size", "clip_grad_mode", "clip_grad_value", "gradient_step", "data_root", "log_directory", "training_width", "training_height", "steps", "create_image_every", "template_file", "latent_sampling_method"} saved_params_ti = {"embedding_name", "num_vectors_per_token", "save_embedding_every", "save_image_with_stored_embedding"} saved_params_hypernet = {"hypernetwork_name", "layer_structure", "activation_func", "weight_init", "add_layer_norm", "use_dropout", "save_hypernetwork_every"} saved_params_all = saved_params_shared | saved_params_ti | saved_params_hypernet @@ -12,13 +12,12 @@ saved_params_previews = {"preview_prompt", "preview_negative_prompt", "preview_s def save_settings_to_file(log_directory, all_params): now = datetime.datetime.now() params = {"datetime": now.strftime("%Y-%m-%d %H:%M:%S")} - keys = saved_params_all if all_params.get('preview_from_txt2img'): keys = keys | saved_params_previews - params.update({k: v for k, v in all_params.items() if k in keys}) - - filename = f'settings.json' - with open(os.path.join(log_directory, filename), "w") as file: + filename = 'settings.json' + fn = os.path.join(log_directory, filename) + with open(os.path.join(log_directory, filename), "w", encoding='utf-8') as file: + print(f'Training settings file: {fn}') json.dump(params, file, indent=2) diff --git a/modules/textual_inversion/textual_inversion.py b/modules/textual_inversion/textual_inversion.py index 377b577f0..ab412f458 100644 --- a/modules/textual_inversion/textual_inversion.py +++ b/modules/textual_inversion/textual_inversion.py @@ -178,7 +178,7 @@ class EmbeddingDatabase: if len(emb.shape) == 1: emb = emb.unsqueeze(0) else: - raise Exception(f"Couldn't identify {filename} as neither textual inversion embedding nor diffuser concept.") + raise RuntimeError(f"Couldn't identify {filename} as neither textual inversion embedding nor diffuser concept.") vec = emb.detach().to(devices.device, dtype=torch.float32) embedding = Embedding(vec, name) @@ -351,7 +351,8 @@ def validate_train_inputs(model_name, learn_rate, batch_size, gradient_step, dat assert log_directory, "Log directory is empty" -def train_embedding(id_task, embedding_name, learn_rate, batch_size, gradient_step, data_root, log_directory, training_width, training_height, varsize, steps, clip_grad_mode, clip_grad_value, shuffle_tags, tag_drop_out, latent_sampling_method, use_weight, create_image_every, save_embedding_every, template_filename, save_image_with_stored_embedding, preview_from_txt2img, preview_prompt, preview_negative_prompt, preview_steps, preview_sampler_index, preview_cfg_scale, preview_seed, preview_width, preview_height): +def train_embedding(id_task, embedding_name, learn_rate, batch_size, gradient_step, data_root, log_directory, training_width, training_height, varsize, steps, clip_grad_mode, clip_grad_value, shuffle_tags, tag_drop_out, latent_sampling_method, use_weight, create_image_every, save_embedding_every, template_filename, save_image_with_stored_embedding, preview_from_txt2img, preview_prompt, preview_negative_prompt, preview_steps, preview_sampler_index, preview_cfg_scale, preview_seed, preview_width, preview_height): # pylint: disable=unused_argument + save_embedding_every = save_embedding_every or 0 create_image_every = create_image_every or 0 template_file = textual_inversion_templates.get(template_filename, None) diff --git a/modules/ui.py b/modules/ui.py index 12e888308..e9d6c6efc 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -254,7 +254,7 @@ def setup_progressbar(*args, **kwargs): # pylint: disable=unused-argument def apply_setting(key, value): if value is None: return gr.update() - if shared.cmd_opts.freeze_settings: + if shared.cmd_opts.freeze: return gr.update() # dont allow model to be swapped when model hash exists in prompt if key == "sd_model_checkpoint" and opts.disable_weights_auto_swap: @@ -1292,7 +1292,7 @@ def create_ui(): current_row = gr.Column(variant='compact') current_row.__enter__() previous_section = item.section - if k in quicksettings_names and not shared.cmd_opts.freeze_settings: + if k in quicksettings_names and not shared.cmd_opts.freeze: quicksettings_list.append((i, k, item)) components.append(dummy_component) elif section_must_be_skipped: diff --git a/scripts/xyz_grid.py b/scripts/xyz_grid.py index 700cc599e..d216d2fef 100644 --- a/scripts/xyz_grid.py +++ b/scripts/xyz_grid.py @@ -145,6 +145,15 @@ def apply_face_restore(p, opt, x): p.restore_faces = is_active +def apply_token_merging_ratio_hr(p, x, xs): + opts.data["token_merging_ratio_hr"] = x + +def apply_token_merging_ratio(p, x, xs): + opts.data["token_merging_ratio"] = x + +def apply_token_merging_random(p, x, xs): + is_active = x.lower() in ('true', 'yes', 'y', '1') + opts.data["token_merging_random"] = is_active def format_value_add_label(p, opt, x): if type(x) == float: @@ -226,6 +235,9 @@ axis_options = [ AxisOption("Styles", str, apply_styles, choices=lambda: list(shared.prompt_styles.styles)), AxisOption("UniPC Order", int, apply_uni_pc_order, cost=0.5), AxisOption("Face restore", str, apply_face_restore, format_value=format_value), + AxisOption("ToMe ratio",float,apply_token_merging_ratio), + AxisOption("ToMe ratio for Hires fix",float,apply_token_merging_ratio_hr), + AxisOption("ToMe random pertubations",str,apply_token_merging_random, choices = lambda: ["Yes","No"]) ] @@ -342,11 +354,16 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend class SharedSettingsStackHelper(object): def __enter__(self): + #Save overridden settings so they can be restored later. self.CLIP_stop_at_last_layers = opts.CLIP_stop_at_last_layers self.vae = opts.sd_vae self.uni_pc_order = opts.uni_pc_order + self.token_merging_ratio_hr = opts.token_merging_ratio_hr + self.token_merging_ratio = opts.token_merging_ratio + self.token_merging_random = opts.token_merging_random def __exit__(self, exc_type, exc_value, tb): + #Restore overriden settings after plot generation. opts.data["sd_vae"] = self.vae opts.data["uni_pc_order"] = self.uni_pc_order sd_models.reload_model_weights() @@ -354,6 +371,9 @@ class SharedSettingsStackHelper(object): opts.data["CLIP_stop_at_last_layers"] = self.CLIP_stop_at_last_layers + opts.data["token_merging_ratio_hr"] = self.token_merging_ratio_hr + opts.data["token_merging_ratio"] = self.token_merging_ratio + opts.data["token_merging_random"] = self.token_merging_random re_range = re.compile(r"\s*([+-]?\s*\d+)\s*-\s*([+-]?\s*\d+)(?:\s*\(([+-]\d+)\s*\))?\s*") re_range_float = re.compile(r"\s*([+-]?\s*\d+(?:.\d*)?)\s*-\s*([+-]?\s*\d+(?:.\d*)?)(?:\s*\(([+-]\d+(?:.\d*)?)\s*\))?\s*") diff --git a/setup.py b/setup.py index 59c200161..393663088 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ class Dot(dict): # dot notation access to dictionary attributes log = logging.getLogger("sd") -args = Dot({ 'debug': False, 'upgrade': False, 'noupdate': False, 'nodirectml': False, 'skip-extensions': False, 'skip-requirements': False, 'reset': False }) +args = Dot({ 'debug': False, 'upgrade': False, 'skip_update': False, 'no_directml': False, 'skip_extensions': False, 'skip_requirements': False, 'reset': False }) quick_allowed = True errors = 0 opts = {} @@ -175,7 +175,6 @@ def clone(url, folder, commithash=None): # check python version def check_python(): - import platform supported_minors = [9, 10] if args.experimental: supported_minors.append(11) @@ -211,7 +210,7 @@ def check_torch(): xformers_package = os.environ.get('XFORMERS_PACKAGE', 'none') else: machine = platform.machine() - if 'arm' not in machine and 'aarch' not in machine and not args.nodirectml: # torch-directml is available on AMD64 + if 'arm' not in machine and 'aarch' not in machine and not args.no_directml: # torch-directml is available on AMD64 log.info('Using DirectML Backend') torch_command = os.environ.get('TORCH_COMMAND', 'torch==2.0.0 torchvision torch-directml') xformers_package = os.environ.get('XFORMERS_PACKAGE', 'none') @@ -239,7 +238,7 @@ def check_torch(): log.info(f'Torch detected GPU: {torch.cuda.get_device_name(device)} VRAM {round(torch.cuda.get_device_properties(device).total_memory / 1024 / 1024)} Arch {torch.cuda.get_device_capability(device)} Cores {torch.cuda.get_device_properties(device).multi_processor_count}') else: try: - import torch_directml + import torch_directml # pylint: disable=import-error import pkg_resources version = pkg_resources.get_distribution("torch-directml") log.info(f'Torch backend: DirectML ({version})') @@ -261,6 +260,8 @@ def check_torch(): install(tensorflow_package, 'tensorflow', ignore=True) except Exception as e: log.debug(f'Cannot install tensorflow package: {e}') + if opts.get('cuda_compile_mode', '') == 'hidet': + install('hidet', 'hidet') # install required packages @@ -338,7 +339,7 @@ def install_extensions(): extensions = list_extensions(folder) log.info(f'Extensions enabled: {extensions}') for ext in extensions: - if not args.noupdate: + if not args.skip_update: try: update(os.path.join(folder, ext)) except: @@ -362,7 +363,7 @@ def install_submodules(): git('checkout master') log.info('Continuing setup') txt = git('submodule --quiet update --init --recursive') - if not args.noupdate: + if not args.skip_update: log.info('Updating submodules') submodules = git('submodule').splitlines() for submodule in submodules: @@ -477,7 +478,7 @@ def check_version(): def update_wiki(): - if not args.noupdate: + if not args.skip_update: log.info('Updating Wiki') try: update(os.path.join(os.path.dirname(__file__), "wiki")) @@ -519,16 +520,17 @@ def check_timestamp(): def add_args(): - parser.add_argument('--debug', default = False, action='store_true', help = "Run installer with debug logging, default: %(default)s") - parser.add_argument('--reset', default = False, action='store_true', help = "Reset main repository to latest version, default: %(default)s") - parser.add_argument('--upgrade', default = False, action='store_true', help = "Upgrade main repository to latest version, default: %(default)s") - parser.add_argument('--noupdate', default = False, action='store_true', help = "Skip update of extensions and submodules, default: %(default)s") - parser.add_argument('--nodirectml', default = False, action='store_true', help = "Although nVidia and AMD toolkit aren't detected, use CPU not DirectML, default: %(default)s") - parser.add_argument('--skip-requirements', default = False, action='store_true', help = "Skips checking and installing requirements, default: %(default)s") - parser.add_argument('--skip-extensions', default = False, action='store_true', help = "Skips running individual extension installers, default: %(default)s") - parser.add_argument('--skip-git', default = False, action='store_true', help = "Skips running all GIT operations, default: %(default)s") - parser.add_argument('--experimental', default = False, action='store_true', help = "Allow unsupported versions of libraries, default: %(default)s") - parser.add_argument('--test', default = False, action='store_true', help = "Run test only, default: %(default)s") + group = parser.add_argument_group('Setup options') + group.add_argument('--debug', default = False, action='store_true', help = "Run installer with debug logging, default: %(default)s") + group.add_argument('--reset', default = False, action='store_true', help = "Reset main repository to latest version, default: %(default)s") + group.add_argument('--upgrade', default = False, action='store_true', help = "Upgrade main repository to latest version, default: %(default)s") + group.add_argument('--no-directml', default = False, action='store_true', help = "Use CPU instead of DirectML if no compatible GPU is detected, default: %(default)s") + group.add_argument('--skip-update', default = False, action='store_true', help = "Skip update of extensions and submodules, default: %(default)s") + group.add_argument('--skip-requirements', default = False, action='store_true', help = "Skips checking and installing requirements, default: %(default)s") + group.add_argument('--skip-extensions', default = False, action='store_true', help = "Skips running individual extension installers, default: %(default)s") + group.add_argument('--skip-git', default = False, action='store_true', help = "Skips running all GIT operations, default: %(default)s") + group.add_argument('--experimental', default = False, action='store_true', help = "Allow unsupported versions of libraries, default: %(default)s") + group.add_argument('--test', default = False, action='store_true', help = "Run test only, default: %(default)s") def parse_args(): @@ -566,8 +568,8 @@ def git_reset(): def read_options(): global opts # pylint: disable=global-statement - if os.path.isfile(args.ui_settings_file): - with open(args.ui_settings_file, "r", encoding="utf8") as file: + if os.path.isfile(args.config): + with open(args.config, "r", encoding="utf8") as file: opts = json.load(file) diff --git a/webui.py b/webui.py index e9ec96c6d..707585ca7 100644 --- a/webui.py +++ b/webui.py @@ -202,10 +202,10 @@ def start_ui(): shared.demo.queue(16) gradio_auth_creds = [] - if cmd_opts.gradio_auth: - gradio_auth_creds += [x.strip() for x in cmd_opts.gradio_auth.strip('"').replace('\n', '').split(',') if x.strip()] - if cmd_opts.gradio_auth_path: - with open(cmd_opts.gradio_auth_path, 'r', encoding="utf8") as file: + if cmd_opts.auth: + gradio_auth_creds += [x.strip() for x in cmd_opts.auth.strip('"').replace('\n', '').split(',') if x.strip()] + if cmd_opts.authfile: + with open(cmd_opts.authfile, 'r', encoding="utf8") as file: for line in file.readlines(): gradio_auth_creds += [x.strip() for x in line.split(',') if x.strip()]