From 4518cfb3b10001b06c6af8bfbf8a42768a36125c Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Thu, 21 Sep 2023 13:19:55 -0400 Subject: [PATCH] refactor schedulers first part --- modules/generation_parameters_copypaste.py | 5 ++- modules/hashes.py | 4 +-- modules/processing.py | 2 +- modules/processing_diffusers.py | 8 ++--- modules/sd_models.py | 2 +- modules/sd_samplers.py | 12 +++---- modules/sd_samplers_compvis.py | 2 +- modules/sd_samplers_kdiffusion.py | 14 ++++---- modules/sd_vae.py | 10 +++--- modules/sd_vae_approx.py | 2 +- modules/shared.py | 38 +++++++++++----------- modules/taesd/sd_vae_taesd.py | 4 +-- 12 files changed, 50 insertions(+), 53 deletions(-) diff --git a/modules/generation_parameters_copypaste.py b/modules/generation_parameters_copypaste.py index ff86801fb..f59e5c3dd 100644 --- a/modules/generation_parameters_copypaste.py +++ b/modules/generation_parameters_copypaste.py @@ -270,10 +270,9 @@ infotext_to_setting_name_mapping = [ ('Parser', 'prompt_attention'), ('ENSD', 'eta_noise_seed_delta'), ('Noise multiplier', 'initial_noise_multiplier'), - ('Eta', 'eta_ancestral'), - ('Eta DDIM', 'eta_ddim'), + ('Eta', 'scheduler_eta'), ('LoRA method', 'diffusers_lora_loader'), - ('Discard penultimate sigma', 'always_discard_next_to_last_sigma'), + ('Discard penultimate sigma', 'discard_next_to_last_sigma'), ('UniPC variant', 'uni_pc_variant'), ('UniPC skip type', 'uni_pc_skip_type'), ('UniPC order', 'schedulers_solver_order'), diff --git a/modules/hashes.py b/modules/hashes.py index 4bbc80850..1470f6685 100644 --- a/modules/hashes.py +++ b/modules/hashes.py @@ -25,7 +25,7 @@ def calculate_sha256(filename, quiet=False): hash_sha256 = hashlib.sha256() blksize = 1024 * 1024 if not quiet: - with progress.open(filename, 'rb', description=f'Calculating hash: [cyan]{filename}', auto_refresh=True, console=shared.console) as f: + with progress.open(filename, 'rb', description=f'[cyan]Calculating hash: [yellow]{filename}', auto_refresh=True, console=shared.console) as f: for chunk in iter(lambda: f.read(blksize), b""): hash_sha256.update(chunk) else: @@ -58,7 +58,7 @@ def sha256(filename, title, use_addnet_hash=False): return None shared.state.begin("hashing") if use_addnet_hash: - with progress.open(filename, 'rb', description=f'Calculating hash: [cyan]{filename}', auto_refresh=True, console=shared.console) as f: + with progress.open(filename, 'rb', description=f'[cyan]Calculating hash: [yellow]{filename}', auto_refresh=True, console=shared.console) as f: sha256_value = addnet_hash_safetensors(f) else: sha256_value = calculate_sha256(filename) diff --git a/modules/processing.py b/modules/processing.py index f1fda1941..5ebf06835 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -1045,7 +1045,7 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): else: image_conditioning = self.txt2img_image_conditioning(samples.to(dtype=devices.dtype_vae)) if self.latent_sampler == "PLMS": - self.latent_sampler = 'UniPC' + self.latent_sampler = 'UniPC' if self.hr_force or latent_scale_mode is not None: if self.denoising_strength > 0: self.ops.append('hires') diff --git a/modules/processing_diffusers.py b/modules/processing_diffusers.py index 56444d4ec..eff57d80e 100644 --- a/modules/processing_diffusers.py +++ b/modules/processing_diffusers.py @@ -343,7 +343,7 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro prompts_2=[p.refiner_prompt] if len(p.refiner_prompt) > 0 else prompts, negative_prompts_2=[p.refiner_negative] if len(p.refiner_negative) > 0 else negative_prompts, num_inference_steps=calculate_base_steps(), - eta=shared.opts.eta_ddim, + eta=shared.opts.scheduler_eta, guidance_rescale=p.diffusers_guidance_rescale, denoising_start=0 if use_refiner_start else p.refiner_start if use_denoise_start else None, denoising_end=p.refiner_start if use_refiner_start else 1 if use_denoise_start else None, @@ -353,7 +353,7 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro **task_specific_kwargs ) p.extra_generation_params['CFG rescale'] = p.diffusers_guidance_rescale - p.extra_generation_params["Eta DDIM"] = shared.opts.eta_ddim if shared.opts.eta_ddim is not None and shared.opts.eta_ddim > 0 else None + p.extra_generation_params["Eta"] = shared.opts.scheduler_eta if shared.opts.scheduler_eta is not None and shared.opts.scheduler_eta > 0 else None try: output = shared.sd_model(**base_args) # pylint: disable=not-callable except AssertionError as e: @@ -395,7 +395,7 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro prompts_2=[p.refiner_prompt] if len(p.refiner_prompt) > 0 else prompts, negative_prompts_2=[p.refiner_negative] if len(p.refiner_negative) > 0 else negative_prompts, num_inference_steps=int(p.hr_second_pass_steps // p.denoising_strength + 1), - eta=shared.opts.eta_ddim, + eta=shared.opts.scheduler_eta, guidance_scale=p.image_cfg_scale if p.image_cfg_scale is not None else p.cfg_scale, guidance_rescale=p.diffusers_guidance_rescale, output_type='latent' if hasattr(shared.sd_model, 'vae') else 'np', @@ -448,7 +448,7 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro prompts=[p.refiner_prompt] if len(p.refiner_prompt) > 0 else prompts[i], negative_prompts=[p.refiner_negative] if len(p.refiner_negative) > 0 else negative_prompts[i], num_inference_steps=int(p.refiner_steps // (1 - p.refiner_start)) if p.refiner_start > 0 and p.refiner_start < 1 and refiner_is_sdxl else int(p.refiner_steps // p.denoising_strength + 1) if refiner_is_sdxl else p.refiner_steps, - eta=shared.opts.eta_ddim, + eta=shared.opts.scheduler_eta, strength=p.denoising_strength, guidance_scale=p.image_cfg_scale if p.image_cfg_scale is not None else p.cfg_scale, guidance_rescale=p.diffusers_guidance_rescale, diff --git a/modules/sd_models.py b/modules/sd_models.py index 69106650c..5e88d84a0 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -617,7 +617,7 @@ def detect_pipeline(f: str, op: str = 'model'): guess = 'Unknown' shared.log.error(f'Model autodetect failed, set diffuser pipeline manually: {f}') return None, None - shared.log.debug(f'Model autodetect {op}: {f} pipeline={guess} size={size} GB') + shared.log.debug(f'Model autodetect: {op}="{f}" pipeline="{guess}" size={size} GB') except Exception as e: shared.log.error(f'Error detecting diffusers pipeline: model={f} {e}') return None, None diff --git a/modules/sd_samplers.py b/modules/sd_samplers.py index 61a56c82a..7f8cebaba 100644 --- a/modules/sd_samplers.py +++ b/modules/sd_samplers.py @@ -61,14 +61,10 @@ def create_sampler(name, model): def set_samplers(): - global samplers, samplers_for_img2img # pylint: disable=global-statement - shown = shared.opts.show_samplers - if type(shown) is not list or len(shown) == 0: - shown = ['UniPC'] - shown_img2img = set(shown) - shown = set(shown + ['PLMS']) - samplers = [x for x in all_samplers if x.name in shown] - samplers_for_img2img = [x for x in all_samplers if x.name in shown_img2img] + global samplers # pylint: disable=global-statement + global samplers_for_img2img # pylint: disable=global-statement + samplers = [x for x in all_samplers if x.name in shared.opts.show_samplers] if len(shared.opts.show_samplers) > 0 else all_samplers + samplers_for_img2img = [x for x in samplers if x.name != "PLMS"] samplers_map.clear() for sampler in all_samplers: samplers_map[sampler.name.lower()] = sampler.name diff --git a/modules/sd_samplers_compvis.py b/modules/sd_samplers_compvis.py index f0053e76c..8dc1e000d 100644 --- a/modules/sd_samplers_compvis.py +++ b/modules/sd_samplers_compvis.py @@ -132,7 +132,7 @@ class VanillaStableDiffusionSampler: def initialize(self, p): if self.is_ddim: - self.eta = p.eta if p.eta is not None else shared.opts.eta_ddim + self.eta = p.eta if p.eta is not None else shared.opts.scheduler_eta else: self.eta = 0.0 if self.eta != 0.0: diff --git a/modules/sd_samplers_kdiffusion.py b/modules/sd_samplers_kdiffusion.py index e39f6ab19..396b5707a 100644 --- a/modules/sd_samplers_kdiffusion.py +++ b/modules/sd_samplers_kdiffusion.py @@ -282,7 +282,7 @@ class KDiffusionSampler: self.model_wrap_cfg.nmask = p.nmask if hasattr(p, 'nmask') else None self.model_wrap_cfg.step = 0 self.model_wrap_cfg.image_cfg_scale = getattr(p, 'image_cfg_scale', None) - self.eta = p.eta if p.eta is not None else opts.eta_ancestral + self.eta = p.eta if p.eta is not None else opts.scheduler_eta self.s_min_uncond = getattr(p, 's_min_uncond', 0.0) k_diffusion.sampling.torch = TorchHijack(self.sampler_noises if self.sampler_noises is not None else []) @@ -301,13 +301,15 @@ class KDiffusionSampler: return extra_params_kwargs def get_sigmas(self, p, steps): - discard_next_to_last_sigma = self.config is not None and self.config.options.get('discard_next_to_last_sigma', False) - if opts.always_discard_next_to_last_sigma: + if opts.discard_next_to_last_sigma == 'always': discard_next_to_last_sigma = True - p.extra_generation_params["Discard penultimate sigma"] = True - if opts.never_discard_next_to_last_sigma: + p.extra_generation_params["Discard penultimate sigma"] = 'always' + elif opts.discard_next_to_last_sigma == 'never': discard_next_to_last_sigma = False - p.extra_generation_params["Discard penultimate sigma"] = False + p.extra_generation_params["Discard penultimate sigma"] = 'never' + else: + discard_next_to_last_sigma = self.config is not None and self.config.options.get('discard_next_to_last_sigma', False) + steps += 1 if discard_next_to_last_sigma else 0 if p.sampler_noise_scheduler_override: diff --git a/modules/sd_vae.py b/modules/sd_vae.py index 173f54337..52216d852 100644 --- a/modules/sd_vae.py +++ b/modules/sd_vae.py @@ -147,12 +147,12 @@ def load_vae(model, vae_file=None, vae_source="unknown-source"): if vae_file: if cache_enabled and vae_file in checkpoints_loaded: # use vae checkpoint cache - shared.log.info(f"Loading VAE weights: {get_filename(vae_file)} source={vae_source} cached=True") + shared.log.info(f"Loading VAE: model={get_filename(vae_file)} source={vae_source} cached=True") store_base_vae(model) _load_vae_dict(model, checkpoints_loaded[vae_file]) else: if not os.path.isfile(vae_file): - shared.log.error(f"VAE doesn't exist: {vae_file} source={vae_source}") + shared.log.error(f"VAE not found: model={vae_file} source={vae_source}") return store_base_vae(model) vae_dict_1 = load_vae_dict(vae_file) @@ -178,9 +178,9 @@ def load_vae_diffusers(model_file, vae_file=None, vae_source="unknown-source"): if vae_file is None: return None if not os.path.exists(vae_file): - shared.log.error(f'VAE not found: {vae_file}') + shared.log.error(f'VAE not found: model{vae_file}') return None - shared.log.info(f"Loading diffusers VAE: {vae_file} source={vae_source}") + shared.log.info(f"Loading VAE: model={vae_file} source={vae_source}") diffusers_load_config = { "low_cpu_mem_usage": False, "torch_dtype": devices.dtype_vae, @@ -210,7 +210,7 @@ def load_vae_diffusers(model_file, vae_file=None, vae_source="unknown-source"): # shared.log.debug(f'Diffusers VAE config: {vae.config}') return vae except Exception as e: - shared.log.error(f"Loading diffusers VAE failed: {vae_file} {e}") + shared.log.error(f"Loading VAE failed: model={vae_file} {e}") return None diff --git a/modules/sd_vae_approx.py b/modules/sd_vae_approx.py index 213926cdc..78fd0f106 100644 --- a/modules/sd_vae_approx.py +++ b/modules/sd_vae_approx.py @@ -44,7 +44,7 @@ def model(): sd_vae_approx_model.load_state_dict(torch.load(model_path, map_location='cpu' if devices.device.type != 'cuda' else None)) sd_vae_approx_model.eval() sd_vae_approx_model.to(devices.device, devices.dtype) - log.info(f"Loaded VAE-approx model: {model_path}") + log.info(f"Loaded VAE-approx: model={model_path}") return sd_vae_approx_model diff --git a/modules/shared.py b/modules/shared.py index 8de276203..e9d2931ea 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -563,33 +563,33 @@ options_templates.update(options_section(('live-preview', "Live Previews"), { })) options_templates.update(options_section(('sampler-params', "Sampler Settings"), { - "show_samplers": OptionInfo(["Default", "Euler a", "UniPC", "DEIS", "DDIM", "DPM 1S", "DPM 2M", "DPM SDE", "DPM++ 2M SDE", "DPM++ 2M SDE Karras", "DPM2 Karras", "DPM++ 2M Karras"], "Show samplers in user interface", gr.CheckboxGroup, lambda: {"choices": [x.name for x in list_samplers() if x.name != "PLMS"]}), + "show_samplers": OptionInfo([], "Show samplers in user interface", gr.CheckboxGroup, lambda: {"choices": [x.name for x in list_samplers()]}), 'uni_pc_variant': OptionInfo("bh1", "UniPC variant", gr.Radio, {"choices": ["bh1", "bh2", "vary_coeff"]}), 'uni_pc_skip_type': OptionInfo("time_uniform", "UniPC skip type", gr.Radio, {"choices": ["time_uniform", "time_quadratic", "logSNR"]}), 'eta_noise_seed_delta': OptionInfo(0, "Noise seed delta (eta)", gr.Number, {"precision": 0}), - "eta_ddim": OptionInfo(0.0, "Noise multiplier for DDIM (eta)", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}), - "schedulers_solver_order": OptionInfo(2, "Samplers solver order where applicable", gr.Slider, {"minimum": 1, "maximum": 5, "step": 1}), + "scheduler_eta": OptionInfo(1.0, "Noise multiplier (eta)", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}), + "schedulers_solver_order": OptionInfo(2, "Solver order (where applicable)", gr.Slider, {"minimum": 1, "maximum": 5, "step": 1}), "schedulers_sep_diffusers": OptionInfo("

Diffusers specific config

", "", gr.HTML), - "schedulers_prediction_type": OptionInfo("default", "Samplers override model prediction type", gr.Radio, lambda: {"choices": ['default', 'epsilon', 'sample', 'v-prediction']}), - "schedulers_use_karras": OptionInfo(True, "Samplers use Karras sigmas where applicable"), - "schedulers_use_loworder": OptionInfo(True, "Samplers use simplified solvers in final steps where applicable"), - "schedulers_use_thresholding": OptionInfo(False, "Samplers use dynamic thresholding where applicable"), - "schedulers_dpm_solver": OptionInfo("sde-dpmsolver++", "Samplers DPM solver algorithm", gr.Radio, lambda: {"choices": ['dpmsolver', 'dpmsolver++', 'sde-dpmsolver', 'sde-dpmsolver++']}), - "schedulers_beta_schedule": OptionInfo("default", "Samplers override beta schedule", gr.Radio, lambda: {"choices": ['default', 'linear', 'scaled_linear', 'squaredcos_cap_v2']}), - 'schedulers_beta_start': OptionInfo(0, "Samplers override beta start", gr.Number, {}), - 'schedulers_beta_end': OptionInfo(0, "Samplers override beta end", gr.Number, {}), + "schedulers_prediction_type": OptionInfo("default", "Override model prediction type", gr.Radio, lambda: {"choices": ['default', 'epsilon', 'sample', 'v-prediction']}), + "schedulers_use_karras": OptionInfo(True, "Use Karras sigmas (where applicable)"), + "schedulers_use_loworder": OptionInfo(True, "Use simplified solvers in final steps (where applicable)"), + "schedulers_use_thresholding": OptionInfo(False, "Use dynamic thresholding (where applicable)"), + "schedulers_dpm_solver": OptionInfo("sde-dpmsolver++", "DPM solver algorithm", gr.Radio, lambda: {"choices": ['dpmsolver', 'dpmsolver++', 'sde-dpmsolver', 'sde-dpmsolver++']}), + "schedulers_beta_schedule": OptionInfo("default", "Override beta schedule", gr.Radio, lambda: {"choices": ['default', 'linear', 'scaled_linear', 'squaredcos_cap_v2']}), + 'schedulers_beta_start': OptionInfo(0, "Override beta start", gr.Number, {}), + 'schedulers_beta_end': OptionInfo(0, "Override beta end", gr.Number, {}), "schedulers_sep_kdiffusers": OptionInfo("

K-Diffusion specific config

", "", gr.HTML), "always_batch_cond_uncond": OptionInfo(False, "Disable conditional batching enabled on low memory systems"), - "enable_quantization": OptionInfo(True, "Enable samplers quantization for sharper and cleaner results"), - "eta_ancestral": OptionInfo(1.0, "Noise multiplier for ancestral samplers (eta)", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}), - 's_churn': OptionInfo(0.0, "sigma churn", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}), - 's_min_uncond': OptionInfo(0.0, "sigma negative guidance minimum ", gr.Slider, {"minimum": 0.0, "maximum": 4.0, "step": 0.01}), - 's_tmin': OptionInfo(0.0, "sigma tmin", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}), - 's_noise': OptionInfo(1.0, "sigma noise", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}), - 'always_discard_next_to_last_sigma': OptionInfo(False, "Always discard next-to-last sigma"), - 'never_discard_next_to_last_sigma': OptionInfo(False, "Never discard next-to-last sigma"), + "enable_quantization": OptionInfo(True, "Enable quantization for sharper and cleaner results"), + 's_churn': OptionInfo(0.0, "Sigma churn", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}), + 's_min_uncond': OptionInfo(0.0, "Sigma negative guidance minimum ", gr.Slider, {"minimum": 0.0, "maximum": 4.0, "step": 0.01}), + 's_tmin': OptionInfo(0.0, "Sigma tmin", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}), + 's_noise': OptionInfo(1.0, "Sigma noise", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}), + 'discard_next_to_last_sigma': OptionInfo("default", "Discard penultimate sigma", gr.Radio, lambda: {"choices": ['default', 'always', 'never']}), + # 'always_discard_next_to_last_sigma': OptionInfo(False, "Always discard next-to-last sigma"), + # 'never_discard_next_to_last_sigma': OptionInfo(False, "Never discard next-to-last sigma"), "schedulers_sep_compvis": OptionInfo("

CompVis specific config

", "", gr.HTML), "ddim_discretize": OptionInfo('uniform', "DDIM discretize img2img", gr.Radio, {"choices": ['uniform', 'quad']}), diff --git a/modules/taesd/sd_vae_taesd.py b/modules/taesd/sd_vae_taesd.py index d50f533c3..35d71a776 100644 --- a/modules/taesd/sd_vae_taesd.py +++ b/modules/taesd/sd_vae_taesd.py @@ -33,9 +33,9 @@ def model(model_class = 'sd', model_type = 'decoder'): vae = taesd_models[f'{model_class}-{model_type}'] vae.eval() vae.to(devices.device, devices.dtype_vae) - log.info(f"Loaded VAE-approx model: {model_path}") + log.info(f"Loaded VAE-TAESD: model={model_path}") else: - raise FileNotFoundError('TAESD model not found') + raise FileNotFoundError(f'TAESD model not found: {model_path}') if vae is None: return None else: