diff --git a/extensions-builtin/Lora/extra_networks_lora.py b/extensions-builtin/Lora/extra_networks_lora.py index f900f98a1..1d319d0b6 100644 --- a/extensions-builtin/Lora/extra_networks_lora.py +++ b/extensions-builtin/Lora/extra_networks_lora.py @@ -61,7 +61,7 @@ class ExtraNetworkLora(extra_networks.ExtraNetwork): loaded.tags = loaded.tags[:shared.opts.lora_apply_tags] all_tags.extend(loaded.tags) if len(all_tags) > 0: - shared.log.debug(f"Load network: type=LoRA max={shared.opts.lora_apply_tags} tags={all_tags} apply") + shared.log.debug(f"Load network: type=LoRA tags={all_tags} max={shared.opts.lora_apply_tags} apply") all_tags = ', '.join(all_tags) p.extra_generation_params["LoRA tags"] = all_tags if p.all_prompts is not None: diff --git a/extensions-builtin/Lora/networks.py b/extensions-builtin/Lora/networks.py index 516956684..dca0a9835 100644 --- a/extensions-builtin/Lora/networks.py +++ b/extensions-builtin/Lora/networks.py @@ -248,7 +248,7 @@ def load_networks(names, te_multipliers=None, unet_multipliers=None, dyn_dims=No continue if net is None: failed_to_load_networks.append(name) - shared.log.error(f'Load network: type=LoRA name="{name}" detected={network_on_disk.sd_version} failed') + shared.log.error(f'Load network: type=LoRA name="{name}" detected={network_on_disk.sd_version if network_on_disk is not None else None} failed') continue if shared.native: shared.sd_model.embedding_db.load_diffusers_embedding(None, net.bundle_embeddings) diff --git a/javascript/sdnext.css b/javascript/sdnext.css index 58407c9b6..0ce893e2f 100644 --- a/javascript/sdnext.css +++ b/javascript/sdnext.css @@ -19,7 +19,7 @@ button { font-size: var(--text-lg) !important; } input[type='color'] { width: 64px; height: 32px; } /* gradio elements */ -.block .padded:not(.gradio-accordion) { padding: 0 !important; margin-right: 0; min-width: 90px !important; } +.block .padded:not(.gradio-accordion) { padding: 4px 0 0 0 !important; margin-right: 0; min-width: 90px !important; } .compact { gap: 1em 0.2em; background: transparent !important; padding: 0 !important; } .flex-break { flex-basis: 100% !important; } .form { border-width: 0; box-shadow: none; background: transparent; overflow: visible; gap: 0.5em 1em; flex-grow: 1 !important; } diff --git a/modules/infotext.py b/modules/infotext.py index b16c3769e..485bcf523 100644 --- a/modules/infotext.py +++ b/modules/infotext.py @@ -86,31 +86,22 @@ mapping = [ ('Parser', 'prompt_attention'), ('Color correction', 'img2img_color_correction'), # Samplers - ('Sampler Eta', 'scheduler_eta'), - ('Sampler ENSD', 'eta_noise_seed_delta'), + ('Sampler eta delta', 'eta_noise_seed_delta'), + ('Sampler eta multiplier', 'initial_noise_multiplier'), + ('Sampler timesteps', 'schedulers_timesteps'), + ('Sampler spacing', 'schedulers_timestep_spacing'), + ('Sampler sigma', 'schedulers_sigma'), ('Sampler order', 'schedulers_solver_order'), - # Samplers diffusers + ('Sampler type', 'schedulers_prediction_type'), ('Sampler beta schedule', 'schedulers_beta_schedule'), + ('Sampler low order', 'schedulers_use_loworder'), + ('Sampler dynamic', 'schedulers_use_thresholding'), + ('Sampler rescale', 'schedulers_rescale_betas'), ('Sampler beta start', 'schedulers_beta_start'), ('Sampler beta end', 'schedulers_beta_end'), - ('Sampler DPM solver', 'schedulers_dpm_solver'), - # Samplers original - ('Sampler brownian', 'schedulers_brownian_noise'), - ('Sampler discard', 'schedulers_discard_penultimate'), - ('Sampler dyn threshold', 'schedulers_use_thresholding'), - ('Sampler karras', 'schedulers_use_karras'), - ('Sampler low order', 'schedulers_use_loworder'), - ('Sampler quantization', 'enable_quantization'), - ('Sampler sigma', 'schedulers_sigma'), - ('Sampler sigma min', 's_min'), - ('Sampler sigma max', 's_max'), - ('Sampler sigma churn', 's_churn'), - ('Sampler sigma uncond', 's_min_uncond'), - ('Sampler sigma noise', 's_noise'), - ('Sampler sigma tmin', 's_tmin'), - ('Sampler ENSM', 'initial_noise_multiplier'), # img2img only - ('UniPC skip type', 'uni_pc_skip_type'), - ('UniPC variant', 'uni_pc_variant'), + ('Sampler range', 'schedulers_timesteps_range'), + ('Sampler shift', 'schedulers_shift'), + ('Sampler dynamic shift', 'schedulers_dynamic_shift'), # Token Merging ('Mask weight', 'inpainting_mask_weight'), ('ToMe', 'tome_ratio'), diff --git a/modules/processing_helpers.py b/modules/processing_helpers.py index 2e0d748e3..6da4511f5 100644 --- a/modules/processing_helpers.py +++ b/modules/processing_helpers.py @@ -559,31 +559,14 @@ def update_sampler(p, sd_model, second_pass=False): if sampler is None: shared.log.warning(f'Sampler: sampler="{sampler_selection}" not found') sampler = sd_samplers.all_samplers_map.get("UniPC") - if len(getattr(p, 'timesteps', [])) > 0: - if 'schedulers_use_karras' in shared.opts.data: - shared.opts.data['schedulers_use_karras'] = False - else: - shared.opts.schedulers_use_karras = False sampler = sd_samplers.create_sampler(sampler.name, sd_model) if sampler is None or sampler_selection == 'Default': return sampler_options = [] - if sampler.config.get('use_karras_sigmas', False): - sampler_options.append('karras') - if sampler.config.get('rescale_betas_zero_snr', False): - sampler_options.append('rescale beta') - if sampler.config.get('thresholding', False): - sampler_options.append('dynamic thresholding') - if 'algorithm_type' in sampler.config: - sampler_options.append(sampler.config['algorithm_type']) - if shared.opts.schedulers_prediction_type != 'default': - sampler_options.append(shared.opts.schedulers_prediction_type) - if shared.opts.schedulers_beta_schedule != 'default': - sampler_options.append(shared.opts.schedulers_beta_schedule) - if 'beta_start' in sampler.config and (shared.opts.schedulers_beta_start > 0 or shared.opts.schedulers_beta_end > 0): - sampler_options.append(f'beta {shared.opts.schedulers_beta_start}-{shared.opts.schedulers_beta_end}') - if 'solver_order' in sampler.config: - sampler_options.append(f'order {shared.opts.schedulers_solver_order}') - if 'lower_order_final' in sampler.config: + if sampler.config.get('rescale_betas_zero_snr', False) and shared.opts.schedulers_rescale_beta != shared.opts.data_labels.get('schedulers_rescale_beta').default: + sampler_options.append('rescale') + if sampler.config.get('thresholding', False) and shared.opts.schedulers_use_thresholding != shared.opts.data_labels.get('schedulers_use_thresholding').default: + sampler_options.append('dynamic') + if 'lower_order_final' in sampler.config and shared.opts.schedulers_use_loworder != shared.opts.data_labels.get('schedulers_use_loworder').default: sampler_options.append('low order') p.extra_generation_params['Sampler options'] = '/'.join(sampler_options) diff --git a/modules/processing_info.py b/modules/processing_info.py index bd146daa6..ad0a455fa 100644 --- a/modules/processing_info.py +++ b/modules/processing_info.py @@ -131,28 +131,23 @@ def create_infotext(p: StableDiffusionProcessing, all_prompts=None, all_seeds=No if sd_hijack is not None and hasattr(sd_hijack.model_hijack, 'embedding_db') and len(sd_hijack.model_hijack.embedding_db.embeddings_used) > 0: # this is for original hijaacked models only, diffusers are handled separately args["Embeddings"] = ', '.join(sd_hijack.model_hijack.embedding_db.embeddings_used) # samplers - args["Sampler ENSD"] = shared.opts.eta_noise_seed_delta if shared.opts.eta_noise_seed_delta != 0 and sd_samplers_common.is_sampler_using_eta_noise_seed_delta(p) else None - args["Sampler ENSM"] = p.initial_noise_multiplier if getattr(p, 'initial_noise_multiplier', 1.0) != 1.0 else None - args['Sampler order'] = shared.opts.schedulers_solver_order if shared.opts.schedulers_solver_order != shared.opts.data_labels.get('schedulers_solver_order').default else None - if shared.native: + if getattr(p, 'sampler_name', None) is not None: + args["Sampler eta delta"] = shared.opts.eta_noise_seed_delta if shared.opts.eta_noise_seed_delta != 0 and sd_samplers_common.is_sampler_using_eta_noise_seed_delta(p) else None + args["Sampler eta multiplier"] = p.initial_noise_multiplier if getattr(p, 'initial_noise_multiplier', 1.0) != 1.0 else None + args['Sampler timesteps'] = shared.opts.schedulers_timesteps if shared.opts.schedulers_timesteps != shared.opts.data_labels.get('schedulers_timesteps').default else None + args['Sampler spacing'] = shared.opts.schedulers_timestep_spacing if shared.opts.schedulers_timestep_spacing != shared.opts.data_labels.get('schedulers_timestep_spacing').default else None + args['Sampler sigma'] = shared.opts.schedulers_sigma if shared.opts.schedulers_sigma != shared.opts.data_labels.get('schedulers_sigma').default else None + args['Sampler order'] = shared.opts.schedulers_solver_order if shared.opts.schedulers_solver_order != shared.opts.data_labels.get('schedulers_solver_order').default else None + args['Sampler type'] = shared.opts.schedulers_prediction_type if shared.opts.schedulers_prediction_type != shared.opts.data_labels.get('schedulers_prediction_type').default else None args['Sampler beta schedule'] = shared.opts.schedulers_beta_schedule if shared.opts.schedulers_beta_schedule != shared.opts.data_labels.get('schedulers_beta_schedule').default else None + args['Sampler low order'] = shared.opts.schedulers_use_loworder if shared.opts.schedulers_use_loworder != shared.opts.data_labels.get('schedulers_use_loworder').default else None + args['Sampler dynamic'] = shared.opts.schedulers_use_thresholding if shared.opts.schedulers_use_thresholding != shared.opts.data_labels.get('schedulers_use_thresholding').default else None + args['Sampler rescale'] = shared.opts.schedulers_rescale_betas if shared.opts.schedulers_rescale_betas != shared.opts.data_labels.get('schedulers_rescale_betas').default else None args['Sampler beta start'] = shared.opts.schedulers_beta_start if shared.opts.schedulers_beta_start != shared.opts.data_labels.get('schedulers_beta_start').default else None args['Sampler beta end'] = shared.opts.schedulers_beta_end if shared.opts.schedulers_beta_end != shared.opts.data_labels.get('schedulers_beta_end').default else None - args['Sampler DPM solver'] = shared.opts.schedulers_dpm_solver if shared.opts.schedulers_dpm_solver != shared.opts.data_labels.get('schedulers_dpm_solver').default else None - if not shared.native: - args['Sampler brownian'] = shared.opts.schedulers_brownian_noise if shared.opts.schedulers_brownian_noise != shared.opts.data_labels.get('schedulers_brownian_noise').default else None - args['Sampler discard'] = shared.opts.schedulers_discard_penultimate if shared.opts.schedulers_discard_penultimate != shared.opts.data_labels.get('schedulers_discard_penultimate').default else None - args['Sampler dyn threshold'] = shared.opts.schedulers_use_thresholding if shared.opts.schedulers_use_thresholding != shared.opts.data_labels.get('schedulers_use_thresholding').default else None - args['Sampler karras'] = shared.opts.schedulers_use_karras if shared.opts.schedulers_use_karras != shared.opts.data_labels.get('schedulers_use_karras').default else None - args['Sampler low order'] = shared.opts.schedulers_use_loworder if shared.opts.schedulers_use_loworder != shared.opts.data_labels.get('schedulers_use_loworder').default else None - args['Sampler quantization'] = shared.opts.enable_quantization if shared.opts.enable_quantization != shared.opts.data_labels.get('enable_quantization').default else None - args['Sampler sigma'] = shared.opts.schedulers_sigma if shared.opts.schedulers_sigma != shared.opts.data_labels.get('schedulers_sigma').default else None - args['Sampler sigma min'] = shared.opts.s_min if shared.opts.s_min != shared.opts.data_labels.get('s_min').default else None - args['Sampler sigma max'] = shared.opts.s_max if shared.opts.s_max != shared.opts.data_labels.get('s_max').default else None - args['Sampler sigma churn'] = shared.opts.s_churn if shared.opts.s_churn != shared.opts.data_labels.get('s_churn').default else None - args['Sampler sigma uncond'] = shared.opts.s_churn if shared.opts.s_churn != shared.opts.data_labels.get('s_churn').default else None - args['Sampler sigma noise'] = shared.opts.s_noise if shared.opts.s_noise != shared.opts.data_labels.get('s_noise').default else None - args['Sampler sigma tmin'] = shared.opts.s_tmin if shared.opts.s_tmin != shared.opts.data_labels.get('s_tmin').default else None + args['Sampler range'] = shared.opts.schedulers_timesteps_range if shared.opts.schedulers_timesteps_range != shared.opts.data_labels.get('schedulers_timesteps_range').default else None + args['Sampler shift'] = shared.opts.schedulers_shift if shared.opts.schedulers_shift != shared.opts.data_labels.get('schedulers_shift').default else None + args['Sampler dynamic shift'] = shared.opts.schedulers_dynamic_shift if shared.opts.schedulers_dynamic_shift != shared.opts.data_labels.get('schedulers_dynamic_shift').default else None # tome/todo if shared.opts.token_merging_method == 'ToMe': args['ToMe'] = shared.opts.tome_ratio if shared.opts.tome_ratio != 0 else None diff --git a/modules/processing_original.py b/modules/processing_original.py index f96b65dfd..bd6a8b466 100644 --- a/modules/processing_original.py +++ b/modules/processing_original.py @@ -64,7 +64,7 @@ def sample_txt2img(p: processing.StableDiffusionProcessingTxt2Img, conditioning, p.hr_force = False # no need to force anything if p.enable_hr and (latent_scale_mode is None or p.hr_force): if len([x for x in shared.sd_upscalers if x.name == p.hr_upscaler]) == 0: - shared.log.warning(f"Cannot find upscaler for hires: {p.hr_upscaler}") + shared.log.warning(f"HiRes: upscaler={p.hr_upscaler} unknown") p.enable_hr = False p.ops.append('txt2img') diff --git a/modules/sd_models.py b/modules/sd_models.py index a5f60ba53..0c62d00c2 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -850,9 +850,6 @@ def apply_balanced_offload(sd_model): if hasattr(sd_model, "decoder_pipe"): apply_balanced_offload_to_module(sd_model.decoder_pipe) sd_model.has_accelerate = True - if not shared.opts.lora_force_diffusers: - shared.log.warning('Balanced offload: Forcing Diffusers Lora loading method') - shared.opts.lora_force_diffusers = True return sd_model diff --git a/modules/sd_samplers.py b/modules/sd_samplers.py index 6a19d90cc..cf72301e4 100644 --- a/modules/sd_samplers.py +++ b/modules/sd_samplers.py @@ -83,7 +83,7 @@ def create_sampler(name, model): if hasattr(model, "prior_pipe") and hasattr(model.prior_pipe, "scheduler"): model.prior_pipe.scheduler = sampler.sampler model.prior_pipe.scheduler.config.clip_sample = False - shared.log.debug(f'Sampler: sampler="{sampler.name}" config={sampler.config}') + shared.log.debug(f'Sampler: sampler="{sampler.name}" class="{model.scheduler.__class__.__name__} config={sampler.config}') return sampler.sampler else: return None diff --git a/modules/sd_samplers_diffusers.py b/modules/sd_samplers_diffusers.py index 4de463b07..273841239 100644 --- a/modules/sd_samplers_diffusers.py +++ b/modules/sd_samplers_diffusers.py @@ -5,7 +5,7 @@ import inspect from modules import shared, errors from modules import sd_samplers_common from modules.tcd import TCDScheduler -from modules.dcsolver import DCSolverMultistepScheduler #https://github.com/wl-zhao/DC-Solver +from modules.dcsolver import DCSolverMultistepScheduler from modules.vdm import VDMScheduler debug = shared.log.trace if os.environ.get('SD_SAMPLER_DEBUG', None) is not None else lambda *args, **kwargs: None @@ -14,27 +14,34 @@ debug('Trace: SAMPLER') try: from diffusers import ( CMStochasticIterativeScheduler, - DDIMScheduler, - DDPMScheduler, UniPCMultistepScheduler, - DEISMultistepScheduler, - DPMSolverMultistepScheduler, - DPMSolverSinglestepScheduler, - DPMSolverSDEScheduler, - EDMDPMSolverMultistepScheduler, - EDMEulerScheduler, - EulerAncestralDiscreteScheduler, + DDIMScheduler, + EulerDiscreteScheduler, + EulerAncestralDiscreteScheduler, + EDMEulerScheduler, + FlowMatchEulerDiscreteScheduler, + + DEISMultistepScheduler, + SASolverScheduler, + + DPMSolverSinglestepScheduler, + DPMSolverMultistepScheduler, + EDMDPMSolverMultistepScheduler, + CosineDPMSolverMultistepScheduler, + DPMSolverSDEScheduler, + HeunDiscreteScheduler, + FlowMatchHeunDiscreteScheduler, + + LCMScheduler, + + PNDMScheduler, IPNDMScheduler, + DDPMScheduler, + LMSDiscreteScheduler, KDPM2DiscreteScheduler, KDPM2AncestralDiscreteScheduler, - LCMScheduler, - LMSDiscreteScheduler, - PNDMScheduler, - SASolverScheduler, - FlowMatchEulerDiscreteScheduler, - FlowMatchHeunDiscreteScheduler, ) except Exception as e: import diffusers @@ -46,68 +53,83 @@ config = { # beta_start, beta_end are typically per-scheduler, but we don't want them as they should be taken from the model itself as those are values model was trained on # prediction_type is ideally set in model as well, but it maybe needed that we do auto-detect of model type in the future 'All': { 'num_train_timesteps': 1000, 'beta_start': 0.0001, 'beta_end': 0.02, 'beta_schedule': 'linear', 'prediction_type': 'epsilon' }, - 'DDIM': { 'clip_sample': False, 'set_alpha_to_one': True, 'steps_offset': 0, 'clip_sample_range': 1.0, 'sample_max_value': 1.0, 'timestep_spacing': 'linspace', 'rescale_betas_zero_snr': False }, - 'UniPC': { 'solver_order': 2, 'thresholding': False, 'sample_max_value': 1.0, 'predict_x0': 'bh2', 'lower_order_final': True, 'timestep_spacing': 'linspace' }, - 'DEIS': { 'solver_order': 2, 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "deis", 'solver_type': "logrho", 'lower_order_final': True, 'timestep_spacing': 'linspace' }, + + 'UniPC': { 'predict_x0': True, 'sample_max_value': 1.0, 'solver_order': 2, 'solver_type': 'bh2', 'thresholding': False, 'use_beta_sigmas': False, 'use_exponential_sigmas': False, 'use_karras_sigmas': False, 'lower_order_final': True, 'timestep_spacing': 'linspace', 'final_sigmas_type': 'zero', 'rescale_betas_zero_snr': False }, + 'DDIM': { 'clip_sample': False, 'set_alpha_to_one': True, 'steps_offset': 0, 'clip_sample_range': 1.0, 'sample_max_value': 1.0, 'timestep_spacing': 'leading', 'rescale_betas_zero_snr': False, 'thresholding': False }, + + 'Euler': { 'steps_offset': 0, 'interpolation_type': "linear", 'rescale_betas_zero_snr': False, 'final_sigmas_type': 'zero', 'timestep_spacing': 'linspace', 'use_beta_sigmas': False, 'use_exponential_sigmas': False, 'use_karras_sigmas': False }, + 'Euler a': { 'steps_offset': 0, 'rescale_betas_zero_snr': False, 'timestep_spacing': 'linspace' }, + 'Euler SGM': { 'steps_offset': 0, 'interpolation_type': "linear", 'rescale_betas_zero_snr': False, 'final_sigmas_type': 'zero', 'timestep_spacing': 'trailing', 'use_beta_sigmas': False, 'use_exponential_sigmas': False, 'use_karras_sigmas': False, 'prediction_type': "sample" }, + 'Euler EDM': { 'sigma_schedule': "karras" }, + 'Euler FlowMatch': { 'timestep_spacing': "linspace", 'shift': 1, 'use_dynamic_shifting': False }, + 'DPM++': { 'solver_order': 2, 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "dpmsolver++", 'solver_type': "midpoint", 'lower_order_final': True, 'use_karras_sigmas': False, 'final_sigmas_type': 'sigma_min' }, 'DPM++ 1S': { 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "dpmsolver++", 'solver_type': "midpoint", 'lower_order_final': True, 'use_karras_sigmas': False, 'final_sigmas_type': 'zero', 'timestep_spacing': 'linspace', 'solver_order': 1 }, 'DPM++ 2M': { 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "dpmsolver++", 'solver_type': "midpoint", 'lower_order_final': True, 'use_karras_sigmas': False, 'final_sigmas_type': 'zero', 'timestep_spacing': 'linspace', 'solver_order': 2 }, 'DPM++ 3M': { 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "dpmsolver++", 'solver_type': "midpoint", 'lower_order_final': True, 'use_karras_sigmas': False, 'final_sigmas_type': 'zero', 'timestep_spacing': 'linspace', 'solver_order': 3 }, + 'DPM++ 2M SDE': { 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "sde-dpmsolver++", 'solver_type': "midpoint", 'lower_order_final': True, 'use_karras_sigmas': False, 'final_sigmas_type': 'zero', 'timestep_spacing': 'linspace', 'solver_order': 2 }, + 'DPM++ 2M EDM': { 'solver_order': 2, 'solver_type': 'midpoint', 'final_sigmas_type': 'zero', 'algorithm_type': 'dpmsolver++' }, + 'DPM++ Cosine': { 'solver_order': 2, 'sigma_schedule': "exponential", 'prediction_type': "v-prediction" }, 'DPM SDE': { 'use_karras_sigmas': False, 'noise_sampler_seed': None, 'timestep_spacing': 'linspace', 'steps_offset': 0 }, - 'Euler': { 'steps_offset': 0, 'interpolation_type': "linear", 'use_karras_sigmas': False, 'rescale_betas_zero_snr': False, 'final_sigmas_type': 'zero', 'timestep_spacing': 'linspace' }, - 'Euler a': { 'steps_offset': 0, 'rescale_betas_zero_snr': False, 'timestep_spacing': 'linspace' }, - 'Euler SGM': { 'timestep_spacing': "trailing", 'prediction_type': "sample" }, - 'Heun': { 'use_karras_sigmas': False, 'timestep_spacing': 'linspace' }, - 'DDPM': { 'variance_type': "fixed_small", 'clip_sample': False, 'thresholding': False, 'clip_sample_range': 1.0, 'sample_max_value': 1.0, 'timestep_spacing': 'linspace', 'rescale_betas_zero_snr': False }, - 'KDPM2': { 'steps_offset': 0, 'timestep_spacing': 'linspace' }, - 'KDPM2 a': { 'steps_offset': 0, 'timestep_spacing': 'linspace' }, - 'LMSD': { 'use_karras_sigmas': False, 'timestep_spacing': 'linspace', 'steps_offset': 0 }, - 'PNDM': { 'skip_prk_steps': False, 'set_alpha_to_one': False, 'steps_offset': 0, 'timestep_spacing': 'linspace' }, + + 'Heun': { 'use_beta_sigmas': False, 'use_karras_sigmas': False, 'timestep_spacing': 'linspace' }, + 'Heun FlowMatch': { 'timestep_spacing': "linspace", 'shift': 1 }, + + 'DEIS': { 'solver_order': 2, 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "deis", 'solver_type': "logrho", 'lower_order_final': True, 'timestep_spacing': 'linspace' }, 'SA Solver': {'predictor_order': 2, 'corrector_order': 2, 'thresholding': False, 'lower_order_final': True, 'use_karras_sigmas': False, 'timestep_spacing': 'linspace'}, 'DC Solver': { 'beta_start': 0.0001, 'beta_end': 0.02, 'solver_order': 2, 'prediction_type': "epsilon", 'thresholding': False, 'solver_type': 'bh2', 'lower_order_final': True, 'dc_order': 2, 'disable_corrector': [0] }, + 'VDM Solver': { 'clip_sample_range': 2.0, }, + 'LCM': { 'beta_start': 0.00085, 'beta_end': 0.012, 'beta_schedule': "scaled_linear", 'set_alpha_to_one': True, 'rescale_betas_zero_snr': False, 'thresholding': False, 'timestep_spacing': 'linspace' }, 'TCD': { 'set_alpha_to_one': True, 'rescale_betas_zero_snr': False, 'beta_schedule': 'scaled_linear' }, - 'Euler EDM': { }, - 'Variational VDM': { 'clip_sample_range': 2.0, }, - 'DPM++ 2M EDM': { 'solver_order': 2, 'solver_type': 'midpoint', 'final_sigmas_type': 'zero', 'algorithm_type': 'dpmsolver++' }, - 'CMSI': { }, #{ 'sigma_min': 0.002, 'sigma_max': 80.0, 'sigma_data': 0.5, 's_noise': 1.0, 'rho': 7.0, 'clip_denoised': True }, - 'Euler FlowMatch': { 'timestep_spacing': "linspace", 'shift': 1, 'use_dynamic_shifting': False }, - 'Heun FlowMatch': { 'timestep_spacing': "linspace", 'shift': 1 }, + + 'PNDM': { 'skip_prk_steps': False, 'set_alpha_to_one': False, 'steps_offset': 0, 'timestep_spacing': 'linspace' }, 'IPNDM': { }, + 'DDPM': { 'variance_type': "fixed_small", 'clip_sample': False, 'thresholding': False, 'clip_sample_range': 1.0, 'sample_max_value': 1.0, 'timestep_spacing': 'linspace', 'rescale_betas_zero_snr': False }, + 'LMSD': { 'use_karras_sigmas': False, 'timestep_spacing': 'linspace', 'steps_offset': 0 }, + 'KDPM2': { 'steps_offset': 0, 'timestep_spacing': 'linspace' }, + 'KDPM2 a': { 'steps_offset': 0, 'timestep_spacing': 'linspace' }, + 'CMSI': { }, #{ 'sigma_min': 0.002, 'sigma_max': 80.0, 'sigma_data': 0.5, 's_noise': 1.0, 'rho': 7.0, 'clip_denoised': True }, } samplers_data_diffusers = [ sd_samplers_common.SamplerData('Default', None, [], {}), sd_samplers_common.SamplerData('UniPC', lambda model: DiffusionSampler('UniPC', UniPCMultistepScheduler, model), [], {}), - sd_samplers_common.SamplerData('DEIS', lambda model: DiffusionSampler('DEIS', DEISMultistepScheduler, model), [], {}), - sd_samplers_common.SamplerData('SA Solver', lambda model: DiffusionSampler('SA Solver', SASolverScheduler, model), [], {}), - sd_samplers_common.SamplerData('DC Solver', lambda model: DiffusionSampler('DC Solver', DCSolverMultistepScheduler, model), [], {}), sd_samplers_common.SamplerData('DDIM', lambda model: DiffusionSampler('DDIM', DDIMScheduler, model), [], {}), - sd_samplers_common.SamplerData('Heun', lambda model: DiffusionSampler('Heun', HeunDiscreteScheduler, model), [], {}), sd_samplers_common.SamplerData('Euler', lambda model: DiffusionSampler('Euler', EulerDiscreteScheduler, model), [], {}), sd_samplers_common.SamplerData('Euler a', lambda model: DiffusionSampler('Euler a', EulerAncestralDiscreteScheduler, model), [], {}), sd_samplers_common.SamplerData('Euler SGM', lambda model: DiffusionSampler('Euler SGM', EulerDiscreteScheduler, model), [], {}), + sd_samplers_common.SamplerData('Euler EDM', lambda model: DiffusionSampler('Euler EDM', EDMEulerScheduler, model), [], {}), + sd_samplers_common.SamplerData('Euler FlowMatch', lambda model: DiffusionSampler('Euler FlowMatch', FlowMatchEulerDiscreteScheduler, model), [], {}), + sd_samplers_common.SamplerData('DPM++', lambda model: DiffusionSampler('DPM++', DPMSolverSinglestepScheduler, model), [], {}), sd_samplers_common.SamplerData('DPM++ 1S', lambda model: DiffusionSampler('DPM++ 1S', DPMSolverMultistepScheduler, model), [], {}), sd_samplers_common.SamplerData('DPM++ 2M', lambda model: DiffusionSampler('DPM++ 2M', DPMSolverMultistepScheduler, model), [], {}), sd_samplers_common.SamplerData('DPM++ 3M', lambda model: DiffusionSampler('DPM++ 3M', DPMSolverMultistepScheduler, model), [], {}), + sd_samplers_common.SamplerData('DPM++ 2M SDE', lambda model: DiffusionSampler('DPM++ 2M SDE', DPMSolverMultistepScheduler, model), [], {}), + sd_samplers_common.SamplerData('DPM++ 2M EDM', lambda model: DiffusionSampler('DPM++ 2M EDM', EDMDPMSolverMultistepScheduler, model), [], {}), + sd_samplers_common.SamplerData('DPM++ Cosine', lambda model: DiffusionSampler('DPM++ 2M EDM', CosineDPMSolverMultistepScheduler, model), [], {}), sd_samplers_common.SamplerData('DPM SDE', lambda model: DiffusionSampler('DPM SDE', DPMSolverSDEScheduler, model), [], {}), + sd_samplers_common.SamplerData('Heun', lambda model: DiffusionSampler('Heun', HeunDiscreteScheduler, model), [], {}), + sd_samplers_common.SamplerData('Heun FlowMatch', lambda model: DiffusionSampler('Heun FlowMatch', FlowMatchHeunDiscreteScheduler, model), [], {}), + + sd_samplers_common.SamplerData('DEIS', lambda model: DiffusionSampler('DEIS', DEISMultistepScheduler, model), [], {}), + sd_samplers_common.SamplerData('SA Solver', lambda model: DiffusionSampler('SA Solver', SASolverScheduler, model), [], {}), + sd_samplers_common.SamplerData('DC Solver', lambda model: DiffusionSampler('DC Solver', DCSolverMultistepScheduler, model), [], {}), + sd_samplers_common.SamplerData('VDM Solver', lambda model: DiffusionSampler('VDM Solver', VDMScheduler, model), [], {}), + sd_samplers_common.SamplerData('PNDM', lambda model: DiffusionSampler('PNDM', PNDMScheduler, model), [], {}), sd_samplers_common.SamplerData('IPNDM', lambda model: DiffusionSampler('IPNDM', IPNDMScheduler, model), [], {}), sd_samplers_common.SamplerData('DDPM', lambda model: DiffusionSampler('DDPM', DDPMScheduler, model), [], {}), sd_samplers_common.SamplerData('LMSD', lambda model: DiffusionSampler('LMSD', LMSDiscreteScheduler, model), [], {}), sd_samplers_common.SamplerData('KDPM2', lambda model: DiffusionSampler('KDPM2', KDPM2DiscreteScheduler, model), [], {}), sd_samplers_common.SamplerData('KDPM2 a', lambda model: DiffusionSampler('KDPM2 a', KDPM2AncestralDiscreteScheduler, model), [], {}), - sd_samplers_common.SamplerData('DPM++ 2M EDM', lambda model: DiffusionSampler('DPM++ 2M EDM', EDMDPMSolverMultistepScheduler, model), [], {}), - sd_samplers_common.SamplerData('Euler EDM', lambda model: DiffusionSampler('Euler EDM', EDMEulerScheduler, model), [], {}), + sd_samplers_common.SamplerData('CMSI', lambda model: DiffusionSampler('CMSI', CMStochasticIterativeScheduler, model), [], {}), + sd_samplers_common.SamplerData('LCM', lambda model: DiffusionSampler('LCM', LCMScheduler, model), [], {}), sd_samplers_common.SamplerData('TCD', lambda model: DiffusionSampler('TCD', TCDScheduler, model), [], {}), - sd_samplers_common.SamplerData('CMSI', lambda model: DiffusionSampler('CMSI', CMStochasticIterativeScheduler, model), [], {}), - sd_samplers_common.SamplerData('Variational VDM', lambda model: DiffusionSampler('Variational VDM', VDMScheduler, model), [], {}), - sd_samplers_common.SamplerData('Euler FlowMatch', lambda model: DiffusionSampler('Euler FlowMatch', FlowMatchEulerDiscreteScheduler, model), [], {}), - sd_samplers_common.SamplerData('Heun FlowMatch', lambda model: DiffusionSampler('Heun FlowMatch', FlowMatchHeunDiscreteScheduler, model), [], {}), sd_samplers_common.SamplerData('Same as primary', None, [], {}), ] @@ -145,19 +167,34 @@ class DiffusionSampler: if shared.opts.schedulers_prediction_type != 'default': self.config['prediction_type'] = shared.opts.schedulers_prediction_type if shared.opts.schedulers_beta_schedule != 'default': - self.config['beta_schedule'] = shared.opts.schedulers_beta_schedule - if 'use_karras_sigmas' in self.config: - timesteps = re.split(',| ', shared.opts.schedulers_timesteps) - timesteps = [int(x) for x in timesteps if x.isdigit()] - self.config['use_karras_sigmas'] = shared.opts.schedulers_use_karras if len(timesteps) == 0 else False + if shared.opts.schedulers_beta_schedule == 'linear': + self.config['beta_schedule'] = 'linear' + elif shared.opts.schedulers_beta_schedule == 'scaled': + self.config['beta_schedule'] = 'scaled_linear' + elif shared.opts.schedulers_beta_schedule == 'cosine': + self.config['beta_schedule'] = 'squaredcos_cap_v2' + print('HERE', shared.opts.schedulers_beta_schedule, self.config['beta_schedule']) + + timesteps = re.split(',| ', shared.opts.schedulers_timesteps) + timesteps = [int(x) for x in timesteps if x.isdigit()] + if len(timesteps) == 0: + if 'use_beta_sigmas' in self.config: + self.config['use_beta_sigmas'] = shared.opts.schedulers_sigma == 'beta' + if 'use_karras_sigmas' in self.config: + self.config['use_karras_sigmas'] = shared.opts.schedulers_sigma == 'karras' + if 'use_exponential_sigmas' in self.config: + self.config['use_exponential_sigmas'] = shared.opts.schedulers_sigma == 'exponential' + else: + pass # timesteps are set using set_timesteps in set_pipeline_args + if 'thresholding' in self.config: self.config['thresholding'] = shared.opts.schedulers_use_thresholding if 'lower_order_final' in self.config: self.config['lower_order_final'] = shared.opts.schedulers_use_loworder - if 'solver_order' in self.config and 'DPM' not in name: + if 'solver_order' in self.config and shared.opts.schedulers_solver_order > 0: self.config['solver_order'] = shared.opts.schedulers_solver_order if 'predict_x0' in self.config: - self.config['predict_x0'] = shared.opts.uni_pc_variant + self.config['solver_type'] = shared.opts.uni_pc_variant if 'beta_start' in self.config and shared.opts.schedulers_beta_start > 0: self.config['beta_start'] = shared.opts.schedulers_beta_start if 'beta_end' in self.config and shared.opts.schedulers_beta_end > 0: @@ -172,15 +209,11 @@ class DiffusionSampler: self.config['timestep_spacing'] = shared.opts.schedulers_timestep_spacing if 'num_train_timesteps' in self.config: self.config['num_train_timesteps'] = shared.opts.schedulers_timesteps_range - if name in {'DPM++ 2M', 'DPM++ 2M EDM'}: - self.config['algorithm_type'] = shared.opts.schedulers_dpm_solver - if name == 'DEIS': - self.config['algorithm_type'] = 'deis' if 'EDM' in name: del self.config['beta_start'] del self.config['beta_end'] del self.config['beta_schedule'] - if name in {'IPNDM', 'CMSI', 'Variational VDM'}: + if name in {'IPNDM', 'CMSI', 'VDM Solver'}: del self.config['beta_start'] del self.config['beta_end'] del self.config['beta_schedule'] diff --git a/modules/shared.py b/modules/shared.py index 6e377be57..d4afea85a 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -615,7 +615,7 @@ options_templates.update(options_section(('saving-images', "Image Options"), { "samples_save": OptionInfo(True, "Save all generated images"), "samples_format": OptionInfo('jpg', 'File format', gr.Dropdown, {"choices": ["jpg", "png", "webp", "tiff", "jp2"]}), "jpeg_quality": OptionInfo(90, "Image quality", gr.Slider, {"minimum": 1, "maximum": 100, "step": 1}), - "img_max_size_mp": OptionInfo(500, "Maximum image size (MP)", gr.Slider, {"minimum": 100, "maximum": 2000, "step": 1}), + "img_max_size_mp": OptionInfo(1000, "Maximum image size (MP)", gr.Slider, {"minimum": 100, "maximum": 2000, "step": 1}), "webp_lossless": OptionInfo(False, "WebP lossless compression"), "save_selected_only": OptionInfo(True, "Save only saves selected image"), "include_mask": OptionInfo(False, "Include mask in outputs"), @@ -728,44 +728,42 @@ options_templates.update(options_section(('sampler-params', "Sampler Settings"), "show_samplers": OptionInfo([], "Show samplers in user interface", gr.CheckboxGroup, lambda: {"choices": [x.name for x in list_samplers()]}), 'eta_noise_seed_delta': OptionInfo(0, "Noise seed delta (eta)", gr.Number, {"precision": 0}), "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_solver_order": OptionInfo(0, "Solver order (where", gr.Slider, {"minimum": 0, "maximum": 5, "step": 1, "visible": False}), # managed from ui.py for backend original "schedulers_brownian_noise": OptionInfo(True, "Use Brownian noise", gr.Checkbox, {"visible": False}), "schedulers_discard_penultimate": OptionInfo(True, "Discard penultimate sigma", gr.Checkbox, {"visible": False}), - "schedulers_sigma": OptionInfo("default", "Sigma algorithm", gr.Radio, {"choices": ['default', 'karras', 'exponential', 'polyexponential'], "visible": False}), "schedulers_use_karras": OptionInfo(True, "Use Karras sigmas", gr.Checkbox, {"visible": False}), - "schedulers_use_thresholding": OptionInfo(False, "Use dynamic thresholding", gr.Checkbox, {"visible": False}), + "schedulers_use_loworder": OptionInfo(True, "Use simplified solvers in final steps", gr.Checkbox, {"visible": False}), - "schedulers_prediction_type": OptionInfo("default", "Override model prediction type", gr.Radio, {"choices": ['default', 'epsilon', 'sample', 'v_prediction']}), + "schedulers_prediction_type": OptionInfo("default", "Override model prediction type", gr.Radio, {"choices": ['default', 'epsilon', 'sample', 'v_prediction'], "visible": False}), + "schedulers_sigma": OptionInfo("default", "Sigma algorithm", gr.Radio, {"choices": ['default', 'karras', 'exponential', 'polyexponential'], "visible": False}), # managed from ui.py for backend diffusers - "schedulers_sep_diffusers": OptionInfo("