From c5934fb6e3007795efcf9b71be6df1581f61e4cb Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Wed, 19 Jul 2023 16:26:12 +0300 Subject: [PATCH 01/23] Merge pull request #11878 from Bourne-M/patch-1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 【bug】reload altclip model error --- modules/sd_hijack.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/sd_hijack.py b/modules/sd_hijack.py index f5615967..c8fdd4f1 100644 --- a/modules/sd_hijack.py +++ b/modules/sd_hijack.py @@ -243,7 +243,7 @@ class StableDiffusionModelHijack: ldm.modules.diffusionmodules.openaimodel.UNetModel.forward = sd_unet.UNetModel_forward def undo_hijack(self, m): - if type(m.cond_stage_model) == xlmr.BertSeriesModelWithTransformation: + if type(m.cond_stage_model) == sd_hijack_xlmr.FrozenXLMREmbedderWithCustomWords: m.cond_stage_model = m.cond_stage_model.wrapped elif type(m.cond_stage_model) == sd_hijack_clip.FrozenCLIPEmbedderWithCustomWords: From 51206edb620b098f286cc33fab748ab90c5b20d4 Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Fri, 21 Jul 2023 18:00:03 +0300 Subject: [PATCH 02/23] Merge pull request #11921 from wfjsw/prepend-pythonpath prepend the pythonpath instead of overriding it --- modules/launch_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/launch_utils.py b/modules/launch_utils.py index 03552bc2..93838745 100644 --- a/modules/launch_utils.py +++ b/modules/launch_utils.py @@ -196,7 +196,7 @@ def run_extension_installer(extension_dir): try: env = os.environ.copy() - env['PYTHONPATH'] = os.path.abspath(".") + env['PYTHONPATH'] = f"{os.path.abspath('.')}{os.pathsep}{env['PYTHONPATH']}" print(run(f'"{python}" "{path_installer}"', errdesc=f"Error running install.py for extension {extension_dir}", custom_env=env)) except Exception as e: From 636ff513b0b5939f15456b82abd2e99951f6e3c1 Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Fri, 21 Jul 2023 18:01:20 +0300 Subject: [PATCH 03/23] Merge pull request #11920 from wfjsw/typo-fix-1 typo fix --- modules/launch_utils.py | 6 +++--- modules/scripts.py | 2 +- webui.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/launch_utils.py b/modules/launch_utils.py index 93838745..93c8c8ca 100644 --- a/modules/launch_utils.py +++ b/modules/launch_utils.py @@ -233,7 +233,7 @@ def run_extensions_installers(settings_file): re_requirement = re.compile(r"\s*([-_a-zA-Z0-9]+)\s*(?:==\s*([-+_.a-zA-Z0-9]+))?\s*") -def requrements_met(requirements_file): +def requirements_met(requirements_file): """ Does a simple parse of a requirements.txt file to determine if all rerqirements in it are already installed. Returns True if so, False if not installed or parsing fails. @@ -293,7 +293,7 @@ def prepare_environment(): try: # the existance of this file is a signal to webui.sh/bat that webui needs to be restarted when it stops execution os.remove(os.path.join(script_path, "tmp", "restart")) - os.environ.setdefault('SD_WEBUI_RESTARTING ', '1') + os.environ.setdefault('SD_WEBUI_RESTARTING', '1') except OSError: pass @@ -354,7 +354,7 @@ def prepare_environment(): if not os.path.isfile(requirements_file): requirements_file = os.path.join(script_path, requirements_file) - if not requrements_met(requirements_file): + if not requirements_met(requirements_file): run_pip(f"install -r \"{requirements_file}\"", "requirements") run_extensions_installers(settings_file=args.ui_settings_file) diff --git a/modules/scripts.py b/modules/scripts.py index 7d9dd59f..f34240a0 100644 --- a/modules/scripts.py +++ b/modules/scripts.py @@ -119,7 +119,7 @@ class Script: def after_extra_networks_activate(self, p, *args, **kwargs): """ - Calledafter extra networks activation, before conds calculation + Called after extra networks activation, before conds calculation allow modification of the network after extra networks activation been applied won't be call if p.disable_extra_networks diff --git a/webui.py b/webui.py index 2aafc09f..2314735f 100644 --- a/webui.py +++ b/webui.py @@ -407,7 +407,7 @@ def webui(): ssl_verify=cmd_opts.disable_tls_verify, debug=cmd_opts.gradio_debug, auth=gradio_auth_creds, - inbrowser=cmd_opts.autolaunch and os.getenv('SD_WEBUI_RESTARTING ') != '1', + inbrowser=cmd_opts.autolaunch and os.getenv('SD_WEBUI_RESTARTING') != '1', prevent_thread_lock=True, allowed_paths=cmd_opts.gradio_allowed_path, app_kwargs={ From 704628b903fc7d54ad7cb9b0f0dd4296a5913c2d Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Sat, 22 Jul 2023 07:03:21 +0300 Subject: [PATCH 04/23] Merge pull request #11923 from AnyISalIn/dev [bug] If txt2img/img2img raises an exception, finally call state.end() --- modules/api/api.py | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/modules/api/api.py b/modules/api/api.py index 2a4cd8a2..9d73083f 100644 --- a/modules/api/api.py +++ b/modules/api/api.py @@ -333,14 +333,16 @@ class Api: p.outpath_grids = opts.outdir_txt2img_grids p.outpath_samples = opts.outdir_txt2img_samples - shared.state.begin(job="scripts_txt2img") - if selectable_scripts is not None: - p.script_args = script_args - processed = scripts.scripts_txt2img.run(p, *p.script_args) # Need to pass args as list here - else: - p.script_args = tuple(script_args) # Need to pass args as tuple here - processed = process_images(p) - shared.state.end() + try: + shared.state.begin(job="scripts_txt2img") + if selectable_scripts is not None: + p.script_args = script_args + processed = scripts.scripts_txt2img.run(p, *p.script_args) # Need to pass args as list here + else: + p.script_args = tuple(script_args) # Need to pass args as tuple here + processed = process_images(p) + finally: + shared.state.end() b64images = list(map(encode_pil_to_base64, processed.images)) if send_images else [] @@ -390,14 +392,16 @@ class Api: p.outpath_grids = opts.outdir_img2img_grids p.outpath_samples = opts.outdir_img2img_samples - shared.state.begin(job="scripts_img2img") - if selectable_scripts is not None: - p.script_args = script_args - processed = scripts.scripts_img2img.run(p, *p.script_args) # Need to pass args as list here - else: - p.script_args = tuple(script_args) # Need to pass args as tuple here - processed = process_images(p) - shared.state.end() + try: + shared.state.begin(job="scripts_img2img") + if selectable_scripts is not None: + p.script_args = script_args + processed = scripts.scripts_img2img.run(p, *p.script_args) # Need to pass args as list here + else: + p.script_args = tuple(script_args) # Need to pass args as tuple here + processed = process_images(p) + finally: + shared.state.end() b64images = list(map(encode_pil_to_base64, processed.images)) if send_images else [] From cad87bf4e3e0b0a759afa94e933527c3123d59bc Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Sat, 22 Jul 2023 16:36:40 +0300 Subject: [PATCH 05/23] Merge pull request #11927 from ljleb/fix-AND Fix composable diffusion weight parsing --- modules/prompt_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/prompt_parser.py b/modules/prompt_parser.py index b29d079d..203ae1ac 100644 --- a/modules/prompt_parser.py +++ b/modules/prompt_parser.py @@ -178,7 +178,7 @@ def get_learned_conditioning(model, prompts: SdConditioning | list[str], steps): re_AND = re.compile(r"\bAND\b") -re_weight = re.compile(r"^(.*?)(?:\s*:\s*([-+]?(?:\d+\.?|\d*\.\d+)))?\s*$") +re_weight = re.compile(r"^((?:\s|.)*?)(?:\s*:\s*([-+]?(?:\d+\.?|\d*\.\d+)))?\s*$") def get_multicond_prompt_list(prompts: SdConditioning | list[str]): From 1f59be5188c0989db3bc8900f2c11b6706c07d70 Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Sat, 22 Jul 2023 16:37:03 +0300 Subject: [PATCH 06/23] Merge pull request #11926 from wfjsw/fix-env-get-1 fix 11291#issuecomment-1646547908 --- modules/launch_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/launch_utils.py b/modules/launch_utils.py index 93c8c8ca..e1c9cfbe 100644 --- a/modules/launch_utils.py +++ b/modules/launch_utils.py @@ -196,7 +196,7 @@ def run_extension_installer(extension_dir): try: env = os.environ.copy() - env['PYTHONPATH'] = f"{os.path.abspath('.')}{os.pathsep}{env['PYTHONPATH']}" + env['PYTHONPATH'] = f"{os.path.abspath('.')}{os.pathsep}{env.get('PYTHONPATH', '')}" print(run(f'"{python}" "{path_installer}"', errdesc=f"Error running install.py for extension {extension_dir}", custom_env=env)) except Exception as e: From 284822323a757a140974c11fb3e5ab72b1f3ddc8 Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Sat, 22 Jul 2023 17:14:33 +0300 Subject: [PATCH 07/23] restyle Startup profile for black users --- style.css | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/style.css b/style.css index e249cfd3..6c92d6e7 100644 --- a/style.css +++ b/style.css @@ -423,15 +423,16 @@ div#extras_scale_to_tab div.form{ } table.popup-table{ - background: white; + background: var(--body-background-fill); + color: var(--body-text-color); border-collapse: collapse; margin: 1em; - border: 4px solid white; + border: 4px solid var(--body-background-fill); } table.popup-table td{ padding: 0.4em; - border: 1px solid #ccc; + border: 1px solid rgba(128, 128, 128, 0.5); max-width: 36em; } From c251e8db8d71e649e4350f13aad1a76ed98d35c3 Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Mon, 24 Jul 2023 23:18:16 +0300 Subject: [PATCH 08/23] Merge pull request #11957 from ljleb/pp-batch-list Add postprocess_batch_list script callback --- modules/processing.py | 26 +++++++++++++++++++++++++- modules/scripts.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/modules/processing.py b/modules/processing.py index a74a5302..6dc178e1 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -717,7 +717,27 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: p.all_subseeds = [int(subseed) + x for x in range(len(p.all_prompts))] def infotext(iteration=0, position_in_batch=0, use_main_prompt=False): - return create_infotext(p, p.all_prompts, p.all_seeds, p.all_subseeds, comments, iteration, position_in_batch, use_main_prompt) + all_prompts = p.all_prompts[:] + all_negative_prompts = p.all_negative_prompts[:] + all_seeds = p.all_seeds[:] + all_subseeds = p.all_subseeds[:] + + # apply changes to generation data + all_prompts[iteration * p.batch_size:(iteration + 1) * p.batch_size] = p.prompts + all_negative_prompts[iteration * p.batch_size:(iteration + 1) * p.batch_size] = p.negative_prompts + all_seeds[iteration * p.batch_size:(iteration + 1) * p.batch_size] = p.seeds + all_subseeds[iteration * p.batch_size:(iteration + 1) * p.batch_size] = p.subseeds + + # update p.all_negative_prompts in case extensions changed the size of the batch + # create_infotext below uses it + old_negative_prompts = p.all_negative_prompts + p.all_negative_prompts = all_negative_prompts + + try: + return create_infotext(p, all_prompts, all_seeds, all_subseeds, comments, iteration, position_in_batch, use_main_prompt) + finally: + # restore p.all_negative_prompts in case extensions changed the size of the batch + p.all_negative_prompts = old_negative_prompts if os.path.exists(cmd_opts.embeddings_dir) and not p.do_not_reload_embeddings: model_hijack.embedding_db.load_textual_inversion_embeddings() @@ -806,6 +826,10 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: if p.scripts is not None: p.scripts.postprocess_batch(p, x_samples_ddim, batch_number=n) + postprocess_batch_list_args = scripts.PostprocessBatchListArgs(list(x_samples_ddim)) + p.scripts.postprocess_batch_list(p, postprocess_batch_list_args, batch_number=n) + x_samples_ddim = postprocess_batch_list_args.images + for i, x_sample in enumerate(x_samples_ddim): p.batch_index = i diff --git a/modules/scripts.py b/modules/scripts.py index f34240a0..5b4edcac 100644 --- a/modules/scripts.py +++ b/modules/scripts.py @@ -16,6 +16,11 @@ class PostprocessImageArgs: self.image = image +class PostprocessBatchListArgs: + def __init__(self, images): + self.images = images + + class Script: name = None """script's internal name derived from title""" @@ -156,6 +161,25 @@ class Script: pass + def postprocess_batch_list(self, p, pp: PostprocessBatchListArgs, *args, **kwargs): + """ + Same as postprocess_batch(), but receives batch images as a list of 3D tensors instead of a 4D tensor. + This is useful when you want to update the entire batch instead of individual images. + + You can modify the postprocessing object (pp) to update the images in the batch, remove images, add images, etc. + If the number of images is different from the batch size when returning, + then the script has the responsibility to also update the following attributes in the processing object (p): + - p.prompts + - p.negative_prompts + - p.seeds + - p.subseeds + + **kwargs will have same items as process_batch, and also: + - batch_number - index of current batch, from 0 to number of batches-1 + """ + + pass + def postprocess_image(self, p, pp: PostprocessImageArgs, *args): """ Called for every image after it has been generated. @@ -536,6 +560,14 @@ class ScriptRunner: except Exception: errors.report(f"Error running postprocess_batch: {script.filename}", exc_info=True) + def postprocess_batch_list(self, p, pp: PostprocessBatchListArgs, **kwargs): + for script in self.alwayson_scripts: + try: + script_args = p.script_args[script.args_from:script.args_to] + script.postprocess_batch_list(p, pp, *script_args, **kwargs) + except Exception: + errors.report(f"Error running postprocess_batch_list: {script.filename}", exc_info=True) + def postprocess_image(self, p, pp: PostprocessImageArgs): for script in self.alwayson_scripts: try: From ce0aab36432c655c8cb48ccc2caf23d10d77cad1 Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Tue, 25 Jul 2023 15:19:10 +0300 Subject: [PATCH 09/23] Merge pull request #11984 from AUTOMATIC1111/api-only-subpath-(root_path) api only subpath (rootpath) --- modules/api/api.py | 4 ++-- webui.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/api/api.py b/modules/api/api.py index 9d73083f..606db179 100644 --- a/modules/api/api.py +++ b/modules/api/api.py @@ -724,9 +724,9 @@ class Api: cuda = {'error': f'{err}'} return models.MemoryResponse(ram=ram, cuda=cuda) - def launch(self, server_name, port): + def launch(self, server_name, port, root_path): self.app.include_router(self.router) - uvicorn.run(self.app, host=server_name, port=port, timeout_keep_alive=shared.cmd_opts.timeout_keep_alive) + uvicorn.run(self.app, host=server_name, port=port, timeout_keep_alive=shared.cmd_opts.timeout_keep_alive, root_path=root_path) def kill_webui(self): restart.stop_program() diff --git a/webui.py b/webui.py index 2314735f..6bf06854 100644 --- a/webui.py +++ b/webui.py @@ -374,7 +374,7 @@ def api_only(): api.launch( server_name="0.0.0.0" if cmd_opts.listen else "127.0.0.1", port=cmd_opts.port if cmd_opts.port else 7861, - root_path = f"/{cmd_opts.subpath}" + root_path=f"/{cmd_opts.subpath}" if cmd_opts.subpath else "" ) From 11f996a096e43092da0c7b8cf5b9d7a19de57828 Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Tue, 25 Jul 2023 15:23:35 +0300 Subject: [PATCH 10/23] Merge pull request #11979 from AUTOMATIC1111/catch-exception-for-non-git-extensions catch exception for non git extensions --- modules/extensions.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/extensions.py b/modules/extensions.py index c561159a..09d1e550 100644 --- a/modules/extensions.py +++ b/modules/extensions.py @@ -56,9 +56,11 @@ class Extension: self.do_read_info_from_repo() return self.to_dict() - - d = cache.cached_data_for_file('extensions-git', self.name, os.path.join(self.path, ".git"), read_from_repo) - self.from_dict(d) + try: + d = cache.cached_data_for_file('extensions-git', self.name, os.path.join(self.path, ".git"), read_from_repo) + self.from_dict(d) + except FileNotFoundError: + pass self.status = 'unknown' def do_read_info_from_repo(self): From b57a816038cbe1e41dbdd505dcac81393edfc1ea Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Tue, 25 Jul 2023 16:17:41 +0300 Subject: [PATCH 11/23] Merge pull request #11963 from catboxanon/fix/lora-te Fix parsing text encoder blocks in some LoRAs --- extensions-builtin/Lora/networks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions-builtin/Lora/networks.py b/extensions-builtin/Lora/networks.py index af8188e3..3a8cfa3b 100644 --- a/extensions-builtin/Lora/networks.py +++ b/extensions-builtin/Lora/networks.py @@ -161,7 +161,7 @@ def load_network(name, network_on_disk): sd_module = shared.sd_model.network_layer_mapping.get(key, None) elif sd_module is None and "lora_te1_text_model" in key_network_without_network_parts: key = key_network_without_network_parts.replace("lora_te1_text_model", "0_transformer_text_model") - sd_module = shared.sd_model.network_layer_mapping.get(key, None) + sd_module = shared.sd_model.network_layer_mapping.get(key, None) or shared.sd_model.network_layer_mapping.get(key[2:], None) if sd_module is None: keys_failed_to_match[key_network] = key From 65b6f8d3d58ff4122162b68b6f126d63c98723ea Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Tue, 25 Jul 2023 16:18:10 +0300 Subject: [PATCH 12/23] fix for #11963 --- extensions-builtin/Lora/networks.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/extensions-builtin/Lora/networks.py b/extensions-builtin/Lora/networks.py index 3a8cfa3b..17cbe1bb 100644 --- a/extensions-builtin/Lora/networks.py +++ b/extensions-builtin/Lora/networks.py @@ -161,7 +161,12 @@ def load_network(name, network_on_disk): sd_module = shared.sd_model.network_layer_mapping.get(key, None) elif sd_module is None and "lora_te1_text_model" in key_network_without_network_parts: key = key_network_without_network_parts.replace("lora_te1_text_model", "0_transformer_text_model") - sd_module = shared.sd_model.network_layer_mapping.get(key, None) or shared.sd_model.network_layer_mapping.get(key[2:], None) + sd_module = shared.sd_model.network_layer_mapping.get(key, None) + + # some SD1 Loras also have correct compvis keys + if sd_module is None: + key = key_network_without_network_parts.replace("lora_te1_text_model", "transformer_text_model") + sd_module = shared.sd_model.network_layer_mapping.get(key, None) if sd_module is None: keys_failed_to_match[key_network] = key From 99ef3b6c5218c3b6b6ecd24be53e6e8c8b7b8384 Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Tue, 25 Jul 2023 16:31:01 +0300 Subject: [PATCH 13/23] update readme --- CHANGELOG.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63a2c7d3..511a1583 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +## 1.5.1 + +### Minor: + * support parsing text encoder blocks in some new LoRAs + +### Extensions and API: + * add postprocess_batch_list script callback + +### Bug Fixes: + * fix reload altclip model error + * prepend the pythonpath instead of overriding it + * fix typo in SD_WEBUI_RESTARTING + * if txt2img/img2img raises an exception, finally call state.end() + * fix composable diffusion weight parsing + * restyle Startup profile for black users + * fix webui not launching with --nowebui + * catch exception for non git extensions + + ## 1.5.0 ### Features: From e16eb3d0cb5a7c7a6b73afc5b6ae11831b480931 Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Wed, 26 Jul 2023 07:45:48 +0300 Subject: [PATCH 14/23] Merge pull request #12024 from AUTOMATIC1111/fix-check-for-updates-status-always-unknown- fix check for updates status always "unknown" --- modules/extensions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/extensions.py b/modules/extensions.py index 09d1e550..3ad5ed53 100644 --- a/modules/extensions.py +++ b/modules/extensions.py @@ -61,7 +61,7 @@ class Extension: self.from_dict(d) except FileNotFoundError: pass - self.status = 'unknown' + self.status = 'unknown' if self.status == '' else self.status def do_read_info_from_repo(self): repo = None From 5360ae2cc57a093a8e26d2152635a05e0329d8fe Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Wed, 26 Jul 2023 08:07:07 +0300 Subject: [PATCH 15/23] Merge pull request #12023 from AUTOMATIC1111/create_infotext_fix Create infotext fix --- modules/processing.py | 63 +++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 38 deletions(-) diff --git a/modules/processing.py b/modules/processing.py index 6dc178e1..b0992ee1 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -600,8 +600,12 @@ def program_version(): return res -def create_infotext(p, all_prompts, all_seeds, all_subseeds, comments=None, iteration=0, position_in_batch=0, use_main_prompt=False): - index = position_in_batch + iteration * p.batch_size +def create_infotext(p, all_prompts, all_seeds, all_subseeds, comments=None, iteration=0, position_in_batch=0, use_main_prompt=False, index=None, all_negative_prompts=None): + if index is None: + index = position_in_batch + iteration * p.batch_size + + if all_negative_prompts is None: + all_negative_prompts = p.all_negative_prompts clip_skip = getattr(p, 'clip_skip', opts.CLIP_stop_at_last_layers) enable_hr = getattr(p, 'enable_hr', False) @@ -617,12 +621,12 @@ def create_infotext(p, all_prompts, all_seeds, all_subseeds, comments=None, iter "Sampler": p.sampler_name, "CFG scale": p.cfg_scale, "Image CFG scale": getattr(p, 'image_cfg_scale', None), - "Seed": all_seeds[index], + "Seed": p.all_seeds[0] if use_main_prompt else all_seeds[index], "Face restoration": (opts.face_restoration_model if p.restore_faces else None), "Size": f"{p.width}x{p.height}", "Model hash": getattr(p, 'sd_model_hash', None if not opts.add_model_hash_to_info or not shared.sd_model.sd_model_hash else shared.sd_model.sd_model_hash), "Model": (None if not opts.add_model_name_to_info else shared.sd_model.sd_checkpoint_info.name_for_extra), - "Variation seed": (None if p.subseed_strength == 0 else all_subseeds[index]), + "Variation seed": (None if p.subseed_strength == 0 else (p.all_subseeds[0] if use_main_prompt else all_subseeds[index])), "Variation seed strength": (None if p.subseed_strength == 0 else p.subseed_strength), "Seed resize from": (None if p.seed_resize_from_w <= 0 or p.seed_resize_from_h <= 0 else f"{p.seed_resize_from_w}x{p.seed_resize_from_h}"), "Denoising strength": getattr(p, 'denoising_strength', None), @@ -642,7 +646,7 @@ def create_infotext(p, all_prompts, all_seeds, all_subseeds, comments=None, iter generation_params_text = ", ".join([k if k == v else f'{k}: {generation_parameters_copypaste.quote(v)}' for k, v in generation_params.items() if v is not None]) prompt_text = p.prompt if use_main_prompt else all_prompts[index] - negative_prompt_text = f"\nNegative prompt: {p.all_negative_prompts[index]}" if p.all_negative_prompts[index] else "" + negative_prompt_text = f"\nNegative prompt: {all_negative_prompts[index]}" if all_negative_prompts[index] else "" return f"{prompt_text}{negative_prompt_text}\n{generation_params_text}".strip() @@ -716,29 +720,6 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: else: p.all_subseeds = [int(subseed) + x for x in range(len(p.all_prompts))] - def infotext(iteration=0, position_in_batch=0, use_main_prompt=False): - all_prompts = p.all_prompts[:] - all_negative_prompts = p.all_negative_prompts[:] - all_seeds = p.all_seeds[:] - all_subseeds = p.all_subseeds[:] - - # apply changes to generation data - all_prompts[iteration * p.batch_size:(iteration + 1) * p.batch_size] = p.prompts - all_negative_prompts[iteration * p.batch_size:(iteration + 1) * p.batch_size] = p.negative_prompts - all_seeds[iteration * p.batch_size:(iteration + 1) * p.batch_size] = p.seeds - all_subseeds[iteration * p.batch_size:(iteration + 1) * p.batch_size] = p.subseeds - - # update p.all_negative_prompts in case extensions changed the size of the batch - # create_infotext below uses it - old_negative_prompts = p.all_negative_prompts - p.all_negative_prompts = all_negative_prompts - - try: - return create_infotext(p, all_prompts, all_seeds, all_subseeds, comments, iteration, position_in_batch, use_main_prompt) - finally: - # restore p.all_negative_prompts in case extensions changed the size of the batch - p.all_negative_prompts = old_negative_prompts - if os.path.exists(cmd_opts.embeddings_dir) and not p.do_not_reload_embeddings: model_hijack.embedding_db.load_textual_inversion_embeddings() @@ -826,9 +807,15 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: if p.scripts is not None: p.scripts.postprocess_batch(p, x_samples_ddim, batch_number=n) - postprocess_batch_list_args = scripts.PostprocessBatchListArgs(list(x_samples_ddim)) - p.scripts.postprocess_batch_list(p, postprocess_batch_list_args, batch_number=n) - x_samples_ddim = postprocess_batch_list_args.images + p.prompts = p.all_prompts[n * p.batch_size:(n + 1) * p.batch_size] + p.negative_prompts = p.all_negative_prompts[n * p.batch_size:(n + 1) * p.batch_size] + + batch_params = scripts.PostprocessBatchListArgs(list(x_samples_ddim)) + p.scripts.postprocess_batch_list(p, batch_params, batch_number=n) + x_samples_ddim = batch_params.images + + def infotext(index=0, use_main_prompt=False): + return create_infotext(p, p.prompts, p.seeds, p.subseeds, use_main_prompt=use_main_prompt, index=index, all_negative_prompts=p.negative_prompts) for i, x_sample in enumerate(x_samples_ddim): p.batch_index = i @@ -838,7 +825,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: if p.restore_faces: if opts.save and not p.do_not_save_samples and opts.save_images_before_face_restoration: - images.save_image(Image.fromarray(x_sample), p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(n, i), p=p, suffix="-before-face-restoration") + images.save_image(Image.fromarray(x_sample), p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(i), p=p, suffix="-before-face-restoration") devices.torch_gc() @@ -855,15 +842,15 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: if p.color_corrections is not None and i < len(p.color_corrections): if opts.save and not p.do_not_save_samples and opts.save_images_before_color_correction: image_without_cc = apply_overlay(image, p.paste_to, i, p.overlay_images) - images.save_image(image_without_cc, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(n, i), p=p, suffix="-before-color-correction") + images.save_image(image_without_cc, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(i), p=p, suffix="-before-color-correction") image = apply_color_correction(p.color_corrections[i], image) image = apply_overlay(image, p.paste_to, i, p.overlay_images) if opts.samples_save and not p.do_not_save_samples: - images.save_image(image, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(n, i), p=p) + images.save_image(image, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(i), p=p) - text = infotext(n, i) + text = infotext(i) infotexts.append(text) if opts.enable_pnginfo: image.info["parameters"] = text @@ -874,10 +861,10 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: image_mask_composite = Image.composite(image.convert('RGBA').convert('RGBa'), Image.new('RGBa', image.size), images.resize_image(2, p.mask_for_overlay, image.width, image.height).convert('L')).convert('RGBA') if opts.save_mask: - images.save_image(image_mask, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(n, i), p=p, suffix="-mask") + images.save_image(image_mask, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(i), p=p, suffix="-mask") if opts.save_mask_composite: - images.save_image(image_mask_composite, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(n, i), p=p, suffix="-mask-composite") + images.save_image(image_mask_composite, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(i), p=p, suffix="-mask-composite") if opts.return_mask: output_images.append(image_mask) @@ -918,7 +905,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: p, images_list=output_images, seed=p.all_seeds[0], - info=infotext(), + info=infotexts[0], comments="".join(f"{comment}\n" for comment in comments), subseed=p.all_subseeds[0], index_of_first_image=index_of_first_image, From eb6d330bb74d1b3a0455af054c8c0c1b18498791 Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Wed, 26 Jul 2023 09:19:46 +0300 Subject: [PATCH 16/23] delete scale checker script due to user demand --- javascript/badScaleChecker.js | 108 ---------------------------------- 1 file changed, 108 deletions(-) delete mode 100644 javascript/badScaleChecker.js diff --git a/javascript/badScaleChecker.js b/javascript/badScaleChecker.js deleted file mode 100644 index 625ad309..00000000 --- a/javascript/badScaleChecker.js +++ /dev/null @@ -1,108 +0,0 @@ -(function() { - var ignore = localStorage.getItem("bad-scale-ignore-it") == "ignore-it"; - - function getScale() { - var ratio = 0, - screen = window.screen, - ua = navigator.userAgent.toLowerCase(); - - if (window.devicePixelRatio !== undefined) { - ratio = window.devicePixelRatio; - } else if (~ua.indexOf('msie')) { - if (screen.deviceXDPI && screen.logicalXDPI) { - ratio = screen.deviceXDPI / screen.logicalXDPI; - } - } else if (window.outerWidth !== undefined && window.innerWidth !== undefined) { - ratio = window.outerWidth / window.innerWidth; - } - - return ratio == 0 ? 0 : Math.round(ratio * 100); - } - - var showing = false; - - var div = document.createElement("div"); - div.style.position = "fixed"; - div.style.top = "0px"; - div.style.left = "0px"; - div.style.width = "100vw"; - div.style.backgroundColor = "firebrick"; - div.style.textAlign = "center"; - div.style.zIndex = 99; - - var b = document.createElement("b"); - b.innerHTML = 'Bad Scale: ??% '; - - div.appendChild(b); - - var note1 = document.createElement("p"); - note1.innerHTML = "Change your browser or your computer settings!"; - note1.title = 'Just make sure "computer-scale" * "browser-scale" = 100% ,\n' + - "you can keep your computer-scale and only change this page's scale,\n" + - "for example: your computer-scale is 125%, just use [\"CTRL\"+\"-\"] to make your browser-scale of this page to 80%."; - div.appendChild(note1); - - var note2 = document.createElement("p"); - note2.innerHTML = " Otherwise, it will cause this page to not function properly!"; - note2.title = "When you click \"Copy image to: [inpaint sketch]\" in some img2img's tab,\n" + - "if scale<100% the canvas will be invisible,\n" + - "else if scale>100% this page will take large amount of memory and CPU performance."; - div.appendChild(note2); - - var btn = document.createElement("button"); - btn.innerHTML = "Click here to ignore"; - - div.appendChild(btn); - - function tryShowTopBar(scale) { - if (showing) return; - - b.innerHTML = 'Bad Scale: ' + scale + '% '; - - var updateScaleTimer = setInterval(function() { - var newScale = getScale(); - b.innerHTML = 'Bad Scale: ' + newScale + '% '; - if (newScale == 100) { - var p = div.parentNode; - if (p != null) p.removeChild(div); - showing = false; - clearInterval(updateScaleTimer); - check(); - } - }, 999); - - btn.onclick = function() { - clearInterval(updateScaleTimer); - var p = div.parentNode; - if (p != null) p.removeChild(div); - ignore = true; - showing = false; - localStorage.setItem("bad-scale-ignore-it", "ignore-it"); - }; - - document.body.appendChild(div); - } - - function check() { - if (!ignore) { - var timer = setInterval(function() { - var scale = getScale(); - if (scale != 100 && !ignore) { - tryShowTopBar(scale); - clearInterval(timer); - } - if (ignore) { - clearInterval(timer); - } - }, 999); - } - } - - if (document.readyState != "complete") { - document.onreadystatechange = function() { - if (document.readyState != "complete") check(); - }; - } else { - check(); - } -})(); From 6b877c35da12029106062bfa8dfefb6a565f13ff Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Wed, 26 Jul 2023 11:52:42 +0300 Subject: [PATCH 17/23] Merge pull request #12032 from AUTOMATIC1111/fix-api-get-options-sd_model_checkpoint api /sdapi/v1/options use "Any" type when default type is None --- modules/api/models.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/modules/api/models.py b/modules/api/models.py index bf97b1a3..800c9b93 100644 --- a/modules/api/models.py +++ b/modules/api/models.py @@ -208,11 +208,9 @@ class PreprocessResponse(BaseModel): fields = {} for key, metadata in opts.data_labels.items(): value = opts.data.get(key) - optType = opts.typemap.get(type(metadata.default), type(metadata.default)) + optType = opts.typemap.get(type(metadata.default), type(metadata.default)) if metadata.default else Any - if metadata.default is None: - pass - elif metadata is not None: + if metadata is not None: fields.update({key: (Optional[optType], Field(default=metadata.default, description=metadata.label))}) else: fields.update({key: (Optional[optType], Field())}) From 5c8f91b22975701af22d24f947af82e7d23264d5 Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Wed, 26 Jul 2023 13:03:52 +0300 Subject: [PATCH 18/23] fix autograd which i broke for no good reason when implementing SDXL --- modules/sd_hijack_clip.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/sd_hijack_clip.py b/modules/sd_hijack_clip.py index 5443e609..990533fe 100644 --- a/modules/sd_hijack_clip.py +++ b/modules/sd_hijack_clip.py @@ -273,9 +273,9 @@ class FrozenCLIPEmbedderWithCustomWordsBase(torch.nn.Module): # restoring original mean is likely not correct, but it seems to work well to prevent artifacts that happen otherwise batch_multipliers = torch.asarray(batch_multipliers).to(devices.device) original_mean = z.mean() - z *= batch_multipliers.reshape(batch_multipliers.shape + (1,)).expand(z.shape) + z = z * batch_multipliers.reshape(batch_multipliers.shape + (1,)).expand(z.shape) new_mean = z.mean() - z *= (original_mean / new_mean) + z = z * (original_mean / new_mean) return z From 055461ae41436e0fcbdf9f5c6b82c9441c6b5b5f Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Wed, 26 Jul 2023 15:07:56 +0300 Subject: [PATCH 19/23] repair SDXL --- modules/sd_hijack_clip.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/sd_hijack_clip.py b/modules/sd_hijack_clip.py index 990533fe..16a5500e 100644 --- a/modules/sd_hijack_clip.py +++ b/modules/sd_hijack_clip.py @@ -270,6 +270,8 @@ class FrozenCLIPEmbedderWithCustomWordsBase(torch.nn.Module): z = self.encode_with_transformers(tokens) + pooled = getattr(z, 'pooled', None) + # restoring original mean is likely not correct, but it seems to work well to prevent artifacts that happen otherwise batch_multipliers = torch.asarray(batch_multipliers).to(devices.device) original_mean = z.mean() @@ -277,6 +279,9 @@ class FrozenCLIPEmbedderWithCustomWordsBase(torch.nn.Module): new_mean = z.mean() z = z * (original_mean / new_mean) + if pooled is not None: + z.pooled = pooled + return z From 8220cf37da8130980b036535bc2fba6b89417158 Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Wed, 26 Jul 2023 15:17:37 +0300 Subject: [PATCH 20/23] Merge pull request #12020 from Littleor/dev Fix the error in rendering the name and description in the extra network UI. --- modules/ui_extra_networks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index 49612298..f2752f10 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -253,7 +253,7 @@ class ExtraNetworksPage: "prompt": item.get("prompt", None), "tabname": quote_js(tabname), "local_preview": quote_js(item["local_preview"]), - "name": item["name"], + "name": html.escape(item["name"]), "description": (item.get("description") or "" if shared.opts.extra_networks_card_show_desc else ""), "card_clicked": onclick, "save_card_preview": '"' + html.escape(f"""return saveCardPreview(event, {quote_js(tabname)}, {quote_js(item["local_preview"])})""") + '"', From 3039925b2746441b8ee2bd18c1f4cdfb9aaea65d Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Wed, 26 Jul 2023 15:19:02 +0300 Subject: [PATCH 21/23] update readme --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 511a1583..5bf4a20d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,13 @@ ### Minor: * support parsing text encoder blocks in some new LoRAs + * delete scale checker script due to user demand ### Extensions and API: * add postprocess_batch_list script callback ### Bug Fixes: + * fix TI training for SD1 * fix reload altclip model error * prepend the pythonpath instead of overriding it * fix typo in SD_WEBUI_RESTARTING @@ -15,6 +17,9 @@ * restyle Startup profile for black users * fix webui not launching with --nowebui * catch exception for non git extensions + * fix some options missing from /sdapi/v1/options + * fix for extension update status always saying "unknown" + * fix display of extra network cards that have `<>` in the name ## 1.5.0 From f82e08cf45e9eb0ea4fa15825f27313b8e78a73c Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Thu, 27 Jul 2023 09:00:47 +0300 Subject: [PATCH 22/23] update lora extension to work with python 3.8 --- extensions-builtin/Lora/network.py | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions-builtin/Lora/network.py b/extensions-builtin/Lora/network.py index 8ecfa29a..0a18d69e 100644 --- a/extensions-builtin/Lora/network.py +++ b/extensions-builtin/Lora/network.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os from collections import namedtuple import enum From 50973ec77c297edc3b3c581e871b970dde1af8ba Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Thu, 27 Jul 2023 09:02:02 +0300 Subject: [PATCH 23/23] update the changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bf4a20d..b18c6867 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ * fix some options missing from /sdapi/v1/options * fix for extension update status always saying "unknown" * fix display of extra network cards that have `<>` in the name + * update lora extension to work with python 3.8 ## 1.5.0