From ab07788ab5bbd5556ad310482ede102582a86f59 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Mon, 16 Dec 2024 11:30:15 -0500 Subject: [PATCH] add sana Signed-off-by: Vladimir Mandic --- CHANGELOG.md | 13 ++- html/reference.json | 13 +++ installer.py | 2 +- ...rge-Model--Sana_1600M_1024px_diffusers.jpg | Bin 0 -> 53061 bytes modules/model_flux.py | 6 +- modules/model_omnigen.py | 3 +- modules/model_sana.py | 25 ++++ modules/model_te.py | 3 +- modules/modeldata.py | 83 +++++++------ modules/pag/__init__.py | 7 +- modules/processing_vae.py | 3 +- modules/schedulers/scheduler_dpm_flowmatch.py | 3 +- modules/sd_detect.py | 2 + modules/sd_models.py | 3 + modules/sd_samplers.py | 9 +- modules/sd_samplers_common.py | 1 + modules/sd_samplers_diffusers.py | 109 +++++++++--------- modules/shared_items.py | 21 ++-- modules/ui_sections.py | 4 +- 19 files changed, 188 insertions(+), 122 deletions(-) create mode 100644 models/Reference/Efficient-Large-Model--Sana_1600M_1024px_diffusers.jpg create mode 100644 modules/model_sana.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 35d3fcbe9..3a07f154c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,19 @@ # Change Log for SD.Next -## Update for 2024-12-15 +## Update for 2024-12-16 + +- Sana: both 1.6B and 0.6B +- ControlNet: better Union results, support for ProMax and Tile +- FreeScale: run optimized iterative generation of images at different scales +- Samplers: UniPC, DEIS, SA, DPM-Multistep: add FlowMatch sigma method and prediction type ### New models and integrations +- [NVLabs Sana](https://huggingface.co/Efficient-Large-Model/Sana_1600M_1024px) + **Sana** can synthesize high-resolution images with strong text-image alignment by using **Gemma2** as text-encoder + support for both 1.6B and 0.6B models + to use, select from *networks -> models -> reference* and models will be auto-downloaded on first use + *reference values*: sampler: default, width/height: 1024, guidance scale: 4.5, attention guidance: 3.0, adaptive scaling: 0.0 - [Flux Tools](https://blackforestlabs.ai/flux-1-tools/) **Redux** is actually a tool, **Fill** is inpaint/outpaint optimized version of *Flux-dev* **Canny** & **Depth** are optimized versions of *Flux-dev* for their respective tasks: they are *not* ControlNets that work on top of a model @@ -98,6 +108,7 @@ - **IPEX**: update to IPEX 2.5.10+xpu - **OpenVINO**: update to 2024.5.0 - **Sampler** improvements + - UniPC, DEIS, SA, DPM-Multistep: allow FlowMatch method - Euler FlowMatch: add sigma methods (*karras/exponential/betas*) - Euler FlowMatch: allow using timestep presets to set sigmas - DPM FlowMatch: update all and add sigma methods diff --git a/html/reference.json b/html/reference.json index 4a549586f..8a0965697 100644 --- a/html/reference.json +++ b/html/reference.json @@ -180,6 +180,19 @@ "extras": "sampler: Default, cfg_scale: 3.5" }, + "NVLabs Sana 1.6B": { + "path": "Efficient-Large-Model/Sana_1600M_1024px_diffusers", + "desc": "Sana is a text-to-image framework that can efficiently generate images up to 4096 × 4096 resolution. Sana can synthesize high-resolution, high-quality images with strong text-image alignment at a remarkably fast speed, deployable on laptop GPU.", + "preview": "Efficient-Large-Model--Sana_1600M_1024px_diffusers.jpg", + "skip": true + }, + "NVLabs Sana 0.6B": { + "path": "Efficient-Large-Model/Sana_600M_1024px_diffusers", + "desc": "Sana is a text-to-image framework that can efficiently generate images up to 4096 × 4096 resolution. Sana can synthesize high-resolution, high-quality images with strong text-image alignment at a remarkably fast speed, deployable on laptop GPU.", + "preview": "Efficient-Large-Model--Sana_1600M_1024px_diffusers.jpg", + "skip": true + }, + "VectorSpaceLab OmniGen v1": { "path": "Shitao/OmniGen-v1", "desc": "OmniGen is a unified image generation model that can generate a wide range of images from multi-modal prompts. It is designed to be simple, flexible and easy to use.", diff --git a/installer.py b/installer.py index 18a8ad1f1..a12b09d4d 100644 --- a/installer.py +++ b/installer.py @@ -459,7 +459,7 @@ def check_python(supported_minors=[9, 10, 11, 12], reason=None): def check_diffusers(): if args.skip_all or args.skip_requirements: return - sha = '63243406ba5510c10d5cac931882918ceba926f9' # diffusers commit hash + sha = '5fb3a985173efaae7ff381b9040c386751d643da' # diffusers commit hash pkg = pkg_resources.working_set.by_key.get('diffusers', None) minor = int(pkg.version.split('.')[1] if pkg is not None else 0) cur = opts.get('diffusers_version', '') if minor > 0 else '' diff --git a/models/Reference/Efficient-Large-Model--Sana_1600M_1024px_diffusers.jpg b/models/Reference/Efficient-Large-Model--Sana_1600M_1024px_diffusers.jpg new file mode 100644 index 0000000000000000000000000000000000000000..654f854034544bc8fafa5a0de21b54c4b3862709 GIT binary patch literal 53061 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 literal 0 HcmV?d00001 diff --git a/modules/model_flux.py b/modules/model_flux.py index ce2c55f70..8d6a02ef6 100644 --- a/modules/model_flux.py +++ b/modules/model_flux.py @@ -34,7 +34,8 @@ def load_flux_quanto(checkpoint_info): with torch.device("meta"): transformer = diffusers.FluxTransformer2DModel.from_config(os.path.join(repo_path, "transformer", "config.json")).to(dtype=dtype) quanto.requantize(transformer, state_dict, quantization_map, device=torch.device("cpu")) - transformer.eval() + if shared.opts.diffusers_eval: + transformer.eval() if transformer.dtype != devices.dtype: try: transformer = transformer.to(dtype=devices.dtype) @@ -61,7 +62,8 @@ def load_flux_quanto(checkpoint_info): with torch.device("meta"): text_encoder_2 = transformers.T5EncoderModel(t5_config).to(dtype=dtype) quanto.requantize(text_encoder_2, state_dict, quantization_map, device=torch.device("cpu")) - text_encoder_2.eval() + if shared.opts.diffusers_eval: + text_encoder_2.eval() if text_encoder_2.dtype != devices.dtype: try: text_encoder_2 = text_encoder_2.to(dtype=devices.dtype) diff --git a/modules/model_omnigen.py b/modules/model_omnigen.py index 64c99ddd7..a08ad4ed5 100644 --- a/modules/model_omnigen.py +++ b/modules/model_omnigen.py @@ -17,7 +17,8 @@ def load_omnigen(checkpoint_info, diffusers_load_config={}): # pylint: disable=u pipe.separate_cfg_infer = True pipe.use_kv_cache = False pipe.model.to(device=devices.device, dtype=devices.dtype) - pipe.model.eval() + if shared.opts.diffusers_eval: + pipe.model.eval() pipe.vae.to(devices.device, dtype=devices.dtype) devices.torch_gc() diff --git a/modules/model_sana.py b/modules/model_sana.py new file mode 100644 index 000000000..06e6fe981 --- /dev/null +++ b/modules/model_sana.py @@ -0,0 +1,25 @@ +import diffusers + + +def load_sana(checkpoint_info, diffusers_load_config={}): + from modules import shared, sd_models, devices, modelloader, model_quant + modelloader.hf_login() + + repo_id = checkpoint_info if isinstance(checkpoint_info, str) else checkpoint_info.path + repo_id = sd_models.path_to_repo(repo_id) + + diffusers_load_config['variant'] = 'fp16' + diffusers_load_config['torch_dtype'] = devices.dtype + diffusers_load_config = model_quant.create_bnb_config(diffusers_load_config) + pipe = diffusers.SanaPAGPipeline.from_pretrained( + repo_id, + # pag_applied_layers=["transformer_blocks.8"], + cache_dir = shared.opts.diffusers_dir, + **diffusers_load_config, + ).to(devices.dtype) + if shared.opts.diffusers_eval: + pipe.text_encoder.eval() + pipe.transformer.eval() + + devices.torch_gc() + return pipe diff --git a/modules/model_te.py b/modules/model_te.py index 606cdb86d..8227ba3e8 100644 --- a/modules/model_te.py +++ b/modules/model_te.py @@ -52,7 +52,8 @@ def load_t5(name=None, cache_dir=None): if torch.is_floating_point(param) and not is_param_float8_e4m3fn: param = param.to(devices.dtype) set_module_tensor_to_device(t5, param_name, device=0, value=param) - t5.eval() + if shared.opts.diffusers_eval: + t5.eval() if t5.dtype != devices.dtype: try: t5 = t5.to(dtype=devices.dtype) diff --git a/modules/modeldata.py b/modules/modeldata.py index 604ff4623..4b7ec1776 100644 --- a/modules/modeldata.py +++ b/modules/modeldata.py @@ -3,6 +3,45 @@ import threading from modules import shared, errors +def get_model_type(pipe): + name = pipe.__class__.__name__ + if not shared.native: + model_type = 'ldm' + elif "StableDiffusion3" in name: + model_type = 'sd3' + elif "StableDiffusionXL" in name: + model_type = 'sdxl' + elif "StableDiffusion" in name: + model_type = 'sd' + elif "LatentConsistencyModel" in name: + model_type = 'sd' # lcm is compatible with sd + elif "InstaFlowPipeline" in name: + model_type = 'sd' # instaflow is compatible with sd + elif "AnimateDiffPipeline" in name: + model_type = 'sd' # animatediff is compatible with sd + elif "Kandinsky" in name: + model_type = 'kandinsky' + elif "HunyuanDiT" in name: + model_type = 'hunyuandit' + elif "Cascade" in name: + model_type = 'sc' + elif "AuraFlow" in name: + model_type = 'auraflow' + elif "Flux" in name: + model_type = 'f1' + elif "Lumina" in name: + model_type = 'lumina' + elif "OmniGen" in name: + model_type = 'omnigen' + elif "CogVideo" in name: + model_type = 'cogvideox' + elif "Sana" in name: + model_type = 'sana' + else: + model_type = name + return model_type + + class ModelData: def __init__(self): self.sd_model = None @@ -82,36 +121,7 @@ class Shared(sys.modules[__name__].__class__): if modules.sd_models.model_data.sd_model is None: model_type = 'none' return model_type - if not shared.native: - model_type = 'ldm' - elif "StableDiffusion3" in self.sd_model.__class__.__name__: - model_type = 'sd3' - elif "StableDiffusionXL" in self.sd_model.__class__.__name__: - model_type = 'sdxl' - elif "StableDiffusion" in self.sd_model.__class__.__name__: - model_type = 'sd' - elif "LatentConsistencyModel" in self.sd_model.__class__.__name__: - model_type = 'sd' # lcm is compatible with sd - elif "InstaFlowPipeline" in self.sd_model.__class__.__name__: - model_type = 'sd' # instaflow is compatible with sd - elif "AnimateDiffPipeline" in self.sd_model.__class__.__name__: - model_type = 'sd' # animatediff is compatible with sd - elif "Kandinsky" in self.sd_model.__class__.__name__: - model_type = 'kandinsky' - elif "HunyuanDiT" in self.sd_model.__class__.__name__: - model_type = 'hunyuandit' - elif "Cascade" in self.sd_model.__class__.__name__: - model_type = 'sc' - elif "AuraFlow" in self.sd_model.__class__.__name__: - model_type = 'auraflow' - elif "Flux" in self.sd_model.__class__.__name__: - model_type = 'f1' - elif "OmniGen" in self.sd_model.__class__.__name__: - model_type = 'omnigen' - elif "CogVideo" in self.sd_model.__class__.__name__: - model_type = 'cogvideox' - else: - model_type = self.sd_model.__class__.__name__ + model_type = get_model_type(self.sd_model) except Exception: model_type = 'unknown' return model_type @@ -123,18 +133,7 @@ class Shared(sys.modules[__name__].__class__): if modules.sd_models.model_data.sd_refiner is None: model_type = 'none' return model_type - if not shared.native: - model_type = 'ldm' - elif "StableDiffusion3" in self.sd_refiner.__class__.__name__: - model_type = 'sd3' - elif "StableDiffusionXL" in self.sd_refiner.__class__.__name__: - model_type = 'sdxl' - elif "StableDiffusion" in self.sd_refiner.__class__.__name__: - model_type = 'sd' - elif "Kandinsky" in self.sd_refiner.__class__.__name__: - model_type = 'kandinsky' - else: - model_type = self.sd_refiner.__class__.__name__ + model_type = get_model_type(self.sd_refiner) except Exception: model_type = 'unknown' return model_type diff --git a/modules/pag/__init__.py b/modules/pag/__init__.py index 29cdee8ca..8fe54c198 100644 --- a/modules/pag/__init__.py +++ b/modules/pag/__init__.py @@ -20,7 +20,9 @@ def apply(p: processing.StableDiffusionProcessing): # pylint: disable=arguments- if sd_models.get_diffusers_task(shared.sd_model) != sd_models.DiffusersTaskType.TEXT_2_IMAGE: shared.log.warning(f'PAG: pipeline={c} not implemented') return None - if detect.is_sd15(c): + if 'PAG' in shared.sd_model.__class__.__name__: + pass + elif detect.is_sd15(c): orig_pipeline = shared.sd_model shared.sd_model = sd_models.switch_pipe(StableDiffusionPAGPipeline, shared.sd_model) elif detect.is_sdxl(c): @@ -32,13 +34,14 @@ def apply(p: processing.StableDiffusionProcessing): # pylint: disable=arguments- p.task_args['pag_scale'] = p.pag_scale p.task_args['pag_adaptive_scaling'] = p.pag_adaptive + p.task_args['pag_adaptive_scale'] = p.pag_adaptive pag_applied_layers = shared.opts.pag_apply_layers pag_applied_layers_index = pag_applied_layers.split() if len(pag_applied_layers) > 0 else [] pag_applied_layers_index = [p.strip() for p in pag_applied_layers_index] p.task_args['pag_applied_layers_index'] = pag_applied_layers_index if len(pag_applied_layers_index) > 0 else ['m0'] # Available layers: d[0-5], m[0], u[0-8] p.extra_generation_params["PAG scale"] = p.pag_scale p.extra_generation_params["PAG adaptive"] = p.pag_adaptive - shared.log.debug(f'{c}: args={p.task_args}') + # shared.log.debug(f'{c}: args={p.task_args}') def unapply(): diff --git a/modules/processing_vae.py b/modules/processing_vae.py index 77a89c512..772a48adc 100644 --- a/modules/processing_vae.py +++ b/modules/processing_vae.py @@ -114,10 +114,11 @@ def full_vae_decode(latents, model): else: # manual upcast and we restore it later model.vae.orig_dtype = model.vae.dtype model.vae = model.vae.to(dtype=torch.float32) - latents = latents.to(torch.float32) latents = latents.to(devices.device) if getattr(model.vae, "post_quant_conv", None) is not None: latents = latents.to(next(iter(model.vae.post_quant_conv.parameters())).dtype) + else: + latents = latents.to(model.vae.dtype) # normalize latents latents_mean = model.vae.config.get("latents_mean", None) diff --git a/modules/schedulers/scheduler_dpm_flowmatch.py b/modules/schedulers/scheduler_dpm_flowmatch.py index 1afe54498..69452aca9 100644 --- a/modules/schedulers/scheduler_dpm_flowmatch.py +++ b/modules/schedulers/scheduler_dpm_flowmatch.py @@ -22,7 +22,8 @@ class BatchedBrownianTree: t0, t1, self.sign = self.sort(t0, t1) w0 = kwargs.get("w0", torch.zeros_like(x)) if seed is None: - seed = torch.randint(0, 2**63 - 1, []).item() + seed = [torch.randint(0, 2**63 - 1, []).item()] + seed = [s.initial_seed() if isinstance(s, torch.Generator) else s for s in seed] self.batched = True try: assert len(seed) == x.shape[0] diff --git a/modules/sd_detect.py b/modules/sd_detect.py index 071a83d7e..1931b9077 100644 --- a/modules/sd_detect.py +++ b/modules/sd_detect.py @@ -71,6 +71,8 @@ def detect_pipeline(f: str, op: str = 'model', warning=True, quiet=False): guess = 'Stable Cascade' if 'pixart-sigma' in f.lower(): guess = 'PixArt-Sigma' + if 'sana' in f.lower(): + guess = 'Sana' if 'lumina-next' in f.lower(): guess = 'Lumina-Next' if 'kolors' in f.lower(): diff --git a/modules/sd_models.py b/modules/sd_models.py index 5d42e314b..661559ae9 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -705,6 +705,9 @@ def load_diffuser_force(model_type, checkpoint_info, diffusers_load_config, op=' elif model_type in ['PixArt-Sigma']: # forced pipeline from modules.model_pixart import load_pixart sd_model = load_pixart(checkpoint_info, diffusers_load_config) + elif model_type in ['Sana']: # forced pipeline + from modules.model_sana import load_sana + sd_model = load_sana(checkpoint_info, diffusers_load_config) elif model_type in ['Lumina-Next']: # forced pipeline from modules.model_lumina import load_lumina sd_model = load_lumina(checkpoint_info, diffusers_load_config) diff --git a/modules/sd_samplers.py b/modules/sd_samplers.py index d8416e5d9..1b1be2d1a 100644 --- a/modules/sd_samplers.py +++ b/modules/sd_samplers.py @@ -3,6 +3,7 @@ import copy from modules import shared from modules.sd_samplers_common import samples_to_image_grid, sample_to_image # pylint: disable=unused-import + debug = shared.log.trace if os.environ.get('SD_SAMPLER_DEBUG', None) is not None else lambda *args, **kwargs: None debug('Trace: SAMPLER') all_samplers = [] @@ -75,15 +76,15 @@ def create_sampler(name, model): shared.log.debug(f'Sampler: sampler="{name}" config={config.options}') return sampler elif shared.native: - FlowModels = ['Flux', 'StableDiffusion3', 'Lumina', 'AuraFlow'] + FlowModels = ['Flux', 'StableDiffusion3', 'Lumina', 'AuraFlow', 'Sana'] if 'KDiffusion' in model.__class__.__name__: return None - if any(x in model.__class__.__name__ for x in FlowModels) and 'FlowMatch' not in name: - shared.log.warning(f'Sampler: default={current} target="{name}" class={model.__class__.__name__} linear scheduler unsupported') - return None if not any(x in model.__class__.__name__ for x in FlowModels) and 'FlowMatch' in name: shared.log.warning(f'Sampler: default={current} target="{name}" class={model.__class__.__name__} flow-match scheduler unsupported') return None + # if any(x in model.__class__.__name__ for x in FlowModels) and 'FlowMatch' not in name: + # shared.log.warning(f'Sampler: default={current} target="{name}" class={model.__class__.__name__} linear scheduler unsupported') + # return None sampler = config.constructor(model) if sampler is None: sampler = config.constructor(model) diff --git a/modules/sd_samplers_common.py b/modules/sd_samplers_common.py index 723f7b181..5297d0bcd 100644 --- a/modules/sd_samplers_common.py +++ b/modules/sd_samplers_common.py @@ -9,6 +9,7 @@ from modules import shared, devices, processing, images, sd_vae_approx, sd_vae_t SamplerData = namedtuple('SamplerData', ['name', 'constructor', 'aliases', 'options']) approximation_indexes = { "Simple": 0, "Approximate": 1, "TAESD": 2, "Full VAE": 3 } +flow_models = ['f1', 'sd3', 'lumina', 'auraflow', 'sana'] warned = False queue_lock = threading.Lock() diff --git a/modules/sd_samplers_diffusers.py b/modules/sd_samplers_diffusers.py index 7c23d4342..c95ae0858 100644 --- a/modules/sd_samplers_diffusers.py +++ b/modules/sd_samplers_diffusers.py @@ -4,13 +4,12 @@ import copy import inspect import diffusers from modules import shared, errors -from modules import sd_samplers_common +from modules.sd_samplers_common import SamplerData, flow_models debug = shared.log.trace if os.environ.get('SD_SAMPLER_DEBUG', None) is not None else lambda *args, **kwargs: None debug('Trace: SAMPLER') - try: from diffusers import ( CMStochasticIterativeScheduler, @@ -63,7 +62,7 @@ config = { # 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' }, - '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 }, + '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_flow_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 }, @@ -72,11 +71,11 @@ config = { 'Euler EDM': { 'sigma_schedule': "karras" }, 'Euler FlowMatch': { 'timestep_spacing': "linspace", 'shift': 1, 'use_dynamic_shifting': False, 'use_karras_sigmas': False, 'use_exponential_sigmas': False, 'use_beta_sigmas': 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, 'use_exponential_sigmas': False, 'use_beta_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, 'use_exponential_sigmas': False, 'use_beta_sigmas': False, 'use_lu_lambdas': 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, 'use_exponential_sigmas': False, 'use_beta_sigmas': False, 'use_lu_lambdas': 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, 'use_exponential_sigmas': False, 'use_beta_sigmas': False, 'use_lu_lambdas': 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, 'use_exponential_sigmas': False, 'use_beta_sigmas': False, 'use_lu_lambdas': False, 'final_sigmas_type': 'zero', 'timestep_spacing': 'linspace', 'solver_order': 2 }, + '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, 'use_exponential_sigmas': False, 'use_flow_sigmas': False, 'use_beta_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, 'use_exponential_sigmas': False, 'use_flow_sigmas': False, 'use_beta_sigmas': False, 'use_lu_lambdas': 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, 'use_exponential_sigmas': False, 'use_flow_sigmas': False, 'use_beta_sigmas': False, 'use_lu_lambdas': 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, 'use_exponential_sigmas': False, 'use_flow_sigmas': False, 'use_beta_sigmas': False, 'use_lu_lambdas': 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, 'use_exponential_sigmas': False, 'use_flow_sigmas': False, 'use_beta_sigmas': False, 'use_lu_lambdas': 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, 'use_exponential_sigmas': False, 'use_beta_sigmas': False, 'noise_sampler_seed': None, 'timestep_spacing': 'linspace', 'steps_offset': 0, }, @@ -92,8 +91,8 @@ config = { 'Heun': { 'use_beta_sigmas': False, 'use_karras_sigmas': False, 'use_exponential_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', 'use_karras_sigmas': False, 'use_exponential_sigmas': False, 'use_beta_sigmas': False }, - 'SA Solver': {'predictor_order': 2, 'corrector_order': 2, 'thresholding': False, 'lower_order_final': True, 'use_karras_sigmas': False, 'use_exponential_sigmas': False, 'use_beta_sigmas': False, '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', 'use_karras_sigmas': False, 'use_exponential_sigmas': False, 'use_flow_sigmas': False, 'use_beta_sigmas': False }, + 'SA Solver': {'predictor_order': 2, 'corrector_order': 2, 'thresholding': False, 'lower_order_final': True, 'use_karras_sigmas': False, 'use_flow_sigmas': False, 'use_exponential_sigmas': False, 'use_beta_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' }, @@ -110,54 +109,54 @@ config = { } samplers_data_diffusers = [ - sd_samplers_common.SamplerData('Default', None, [], {}), + SamplerData('Default', None, [], {}), - sd_samplers_common.SamplerData('UniPC', lambda model: DiffusionSampler('UniPC', UniPCMultistepScheduler, model), [], {}), - sd_samplers_common.SamplerData('DDIM', lambda model: DiffusionSampler('DDIM', DDIMScheduler, 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), [], {}), + SamplerData('UniPC', lambda model: DiffusionSampler('UniPC', UniPCMultistepScheduler, model), [], {}), + SamplerData('DDIM', lambda model: DiffusionSampler('DDIM', DDIMScheduler, model), [], {}), + SamplerData('Euler', lambda model: DiffusionSampler('Euler', EulerDiscreteScheduler, model), [], {}), + SamplerData('Euler a', lambda model: DiffusionSampler('Euler a', EulerAncestralDiscreteScheduler, model), [], {}), + SamplerData('Euler SGM', lambda model: DiffusionSampler('Euler SGM', EulerDiscreteScheduler, model), [], {}), + SamplerData('Euler EDM', lambda model: DiffusionSampler('Euler EDM', EDMEulerScheduler, model), [], {}), + 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), [], {}), + SamplerData('DPM++', lambda model: DiffusionSampler('DPM++', DPMSolverSinglestepScheduler, model), [], {}), + SamplerData('DPM++ 1S', lambda model: DiffusionSampler('DPM++ 1S', DPMSolverMultistepScheduler, model), [], {}), + SamplerData('DPM++ 2M', lambda model: DiffusionSampler('DPM++ 2M', DPMSolverMultistepScheduler, model), [], {}), + SamplerData('DPM++ 3M', lambda model: DiffusionSampler('DPM++ 3M', DPMSolverMultistepScheduler, model), [], {}), + SamplerData('DPM++ 2M SDE', lambda model: DiffusionSampler('DPM++ 2M SDE', DPMSolverMultistepScheduler, model), [], {}), + SamplerData('DPM++ 2M EDM', lambda model: DiffusionSampler('DPM++ 2M EDM', EDMDPMSolverMultistepScheduler, model), [], {}), + SamplerData('DPM++ Cosine', lambda model: DiffusionSampler('DPM++ 2M EDM', CosineDPMSolverMultistepScheduler, model), [], {}), + SamplerData('DPM SDE', lambda model: DiffusionSampler('DPM SDE', DPMSolverSDEScheduler, model), [], {}), - sd_samplers_common.SamplerData('DPM2 FlowMatch', lambda model: DiffusionSampler('DPM2 FlowMatch', FlowMatchDPMSolverMultistepScheduler, model), [], {}), - sd_samplers_common.SamplerData('DPM2a FlowMatch', lambda model: DiffusionSampler('DPM2a FlowMatch', FlowMatchDPMSolverMultistepScheduler, model), [], {}), - sd_samplers_common.SamplerData('DPM2++ 2M FlowMatch', lambda model: DiffusionSampler('DPM2++ 2M FlowMatch', FlowMatchDPMSolverMultistepScheduler, model), [], {}), - sd_samplers_common.SamplerData('DPM2++ 2S FlowMatch', lambda model: DiffusionSampler('DPM2++ 2S FlowMatch', FlowMatchDPMSolverMultistepScheduler, model), [], {}), - sd_samplers_common.SamplerData('DPM2++ SDE FlowMatch', lambda model: DiffusionSampler('DPM2++ SDE FlowMatch', FlowMatchDPMSolverMultistepScheduler, model), [], {}), - sd_samplers_common.SamplerData('DPM2++ 2M SDE FlowMatch', lambda model: DiffusionSampler('DPM2++ 2M SDE FlowMatch', FlowMatchDPMSolverMultistepScheduler, model), [], {}), - sd_samplers_common.SamplerData('DPM2++ 3M SDE FlowMatch', lambda model: DiffusionSampler('DPM2++ 3M SDE FlowMatch', FlowMatchDPMSolverMultistepScheduler, model), [], {}), + SamplerData('DPM2 FlowMatch', lambda model: DiffusionSampler('DPM2 FlowMatch', FlowMatchDPMSolverMultistepScheduler, model), [], {}), + SamplerData('DPM2a FlowMatch', lambda model: DiffusionSampler('DPM2a FlowMatch', FlowMatchDPMSolverMultistepScheduler, model), [], {}), + SamplerData('DPM2++ 2M FlowMatch', lambda model: DiffusionSampler('DPM2++ 2M FlowMatch', FlowMatchDPMSolverMultistepScheduler, model), [], {}), + SamplerData('DPM2++ 2S FlowMatch', lambda model: DiffusionSampler('DPM2++ 2S FlowMatch', FlowMatchDPMSolverMultistepScheduler, model), [], {}), + SamplerData('DPM2++ SDE FlowMatch', lambda model: DiffusionSampler('DPM2++ SDE FlowMatch', FlowMatchDPMSolverMultistepScheduler, model), [], {}), + SamplerData('DPM2++ 2M SDE FlowMatch', lambda model: DiffusionSampler('DPM2++ 2M SDE FlowMatch', FlowMatchDPMSolverMultistepScheduler, model), [], {}), + SamplerData('DPM2++ 3M SDE FlowMatch', lambda model: DiffusionSampler('DPM2++ 3M SDE FlowMatch', FlowMatchDPMSolverMultistepScheduler, 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), [], {}), + SamplerData('Heun', lambda model: DiffusionSampler('Heun', HeunDiscreteScheduler, model), [], {}), + 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('BDIA DDIM', lambda model: DiffusionSampler('BDIA DDIM g=0', BDIA_DDIMScheduler, model), [], {}), + SamplerData('DEIS', lambda model: DiffusionSampler('DEIS', DEISMultistepScheduler, model), [], {}), + SamplerData('SA Solver', lambda model: DiffusionSampler('SA Solver', SASolverScheduler, model), [], {}), + SamplerData('DC Solver', lambda model: DiffusionSampler('DC Solver', DCSolverMultistepScheduler, model), [], {}), + SamplerData('VDM Solver', lambda model: DiffusionSampler('VDM Solver', VDMScheduler, model), [], {}), + SamplerData('BDIA DDIM', lambda model: DiffusionSampler('BDIA DDIM g=0', BDIA_DDIMScheduler, 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('CMSI', lambda model: DiffusionSampler('CMSI', CMStochasticIterativeScheduler, model), [], {}), + SamplerData('PNDM', lambda model: DiffusionSampler('PNDM', PNDMScheduler, model), [], {}), + SamplerData('IPNDM', lambda model: DiffusionSampler('IPNDM', IPNDMScheduler, model), [], {}), + SamplerData('DDPM', lambda model: DiffusionSampler('DDPM', DDPMScheduler, model), [], {}), + SamplerData('LMSD', lambda model: DiffusionSampler('LMSD', LMSDiscreteScheduler, model), [], {}), + SamplerData('KDPM2', lambda model: DiffusionSampler('KDPM2', KDPM2DiscreteScheduler, model), [], {}), + SamplerData('KDPM2 a', lambda model: DiffusionSampler('KDPM2 a', KDPM2AncestralDiscreteScheduler, model), [], {}), + 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), [], {}), + SamplerData('LCM', lambda model: DiffusionSampler('LCM', LCMScheduler, model), [], {}), + SamplerData('TCD', lambda model: DiffusionSampler('TCD', TCDScheduler, model), [], {}), - sd_samplers_common.SamplerData('Same as primary', None, [], {}), + SamplerData('Same as primary', None, [], {}), ] @@ -178,14 +177,14 @@ class DiffusionSampler: orig_config = model.default_scheduler.scheduler_config else: orig_config = model.default_scheduler.config - for key, value in config.get(name, {}).items(): # apply diffusers per-scheduler defaults - self.config[key] = value debug(f'Sampler: diffusers="{self.config}"') debug(f'Sampler: original="{orig_config}"') for key, value in orig_config.items(): # apply model defaults if key in self.config: self.config[key] = value debug(f'Sampler: default="{self.config}"') + for key, value in config.get(name, {}).items(): # apply diffusers per-scheduler defaults + self.config[key] = value for key, value in kwargs.items(): # apply user args, if any if key in self.config: self.config[key] = value @@ -205,10 +204,14 @@ class DiffusionSampler: if len(timesteps) == 0: if 'sigma_schedule' in self.config: self.config['sigma_schedule'] = shared.opts.schedulers_sigma if shared.opts.schedulers_sigma != 'default' else None - if shared.opts.schedulers_sigma == 'betas' and 'use_beta_sigmas' in self.config: + if shared.opts.schedulers_sigma == 'default' and shared.sd_model_type in flow_models and 'use_flow_sigmas' in self.config: + self.config['use_flow_sigmas'] = True + elif shared.opts.schedulers_sigma == 'betas' and 'use_beta_sigmas' in self.config: self.config['use_beta_sigmas'] = True elif shared.opts.schedulers_sigma == 'karras' and 'use_karras_sigmas' in self.config: self.config['use_karras_sigmas'] = True + elif shared.opts.schedulers_sigma == 'flowmatch' and 'use_flow_sigmas' in self.config: + self.config['use_flow_sigmas'] = True elif shared.opts.schedulers_sigma == 'exponential' and 'use_exponential_sigmas' in self.config: self.config['use_exponential_sigmas'] = True elif shared.opts.schedulers_sigma == 'lambdas' and 'use_lu_lambdas' in self.config: diff --git a/modules/shared_items.py b/modules/shared_items.py index 4d9b325c8..9abb64718 100644 --- a/modules/shared_items.py +++ b/modules/shared_items.py @@ -86,6 +86,14 @@ def get_pipelines(): 'Kolors': getattr(diffusers, 'KolorsPipeline', None), 'AuraFlow': getattr(diffusers, 'AuraFlowPipeline', None), 'CogView': getattr(diffusers, 'CogView3PlusPipeline', None), + 'Stable Cascade': getattr(diffusers, 'StableCascadeCombinedPipeline', None), + 'PixArt-Sigma': getattr(diffusers, 'PixArtSigmaPipeline', None), + 'HunyuanDiT': getattr(diffusers, 'HunyuanDiTPipeline', None), + 'Stable Diffusion 3': getattr(diffusers, 'StableDiffusion3Pipeline', None), + 'Stable Diffusion 3 Img2Img': getattr(diffusers, 'StableDiffusion3Img2ImgPipeline', None), + 'Lumina-Next': getattr(diffusers, 'LuminaText2ImgPipeline', None), + 'FLUX': getattr(diffusers, 'FluxPipeline', None), + 'Sana': getattr(diffusers, 'SanaPAGPipeline', None), } if hasattr(diffusers, 'OnnxStableDiffusionPipeline'): onnx_pipelines = { @@ -103,19 +111,10 @@ def get_pipelines(): pipelines.update(onnx_pipelines) # items that may rely on diffusers dev version - if hasattr(diffusers, 'StableCascadeCombinedPipeline'): - pipelines['Stable Cascade'] = getattr(diffusers, 'StableCascadeCombinedPipeline', None) - if hasattr(diffusers, 'PixArtSigmaPipeline'): - pipelines['PixArt-Sigma'] = getattr(diffusers, 'PixArtSigmaPipeline', None) - if hasattr(diffusers, 'HunyuanDiTPipeline'): - pipelines['HunyuanDiT'] = getattr(diffusers, 'HunyuanDiTPipeline', None) - if hasattr(diffusers, 'StableDiffusion3Pipeline'): - pipelines['Stable Diffusion 3'] = getattr(diffusers, 'StableDiffusion3Pipeline', None) - pipelines['Stable Diffusion 3 Img2Img'] = getattr(diffusers, 'StableDiffusion3Img2ImgPipeline', None) - if hasattr(diffusers, 'LuminaText2ImgPipeline'): - pipelines['Lumina-Next'] = getattr(diffusers, 'LuminaText2ImgPipeline', None) + """ if hasattr(diffusers, 'FluxPipeline'): pipelines['FLUX'] = getattr(diffusers, 'FluxPipeline', None) + """ for k, v in pipelines.items(): if k != 'Autodetect' and v is None: diff --git a/modules/ui_sections.py b/modules/ui_sections.py index f15edb4bd..fcf53cf70 100644 --- a/modules/ui_sections.py +++ b/modules/ui_sections.py @@ -276,11 +276,11 @@ def create_sampler_options(tabname): else: # shared.native with gr.Row(elem_classes=['flex-break']): - sampler_sigma = gr.Dropdown(label='Sigma method', elem_id=f"{tabname}_sampler_sigma", choices=['default', 'karras', 'betas', 'exponential', 'lambdas'], value=shared.opts.schedulers_sigma, type='value') + sampler_sigma = gr.Dropdown(label='Sigma method', elem_id=f"{tabname}_sampler_sigma", choices=['default', 'karras', 'betas', 'exponential', 'lambdas', 'flowmatch'], value=shared.opts.schedulers_sigma, type='value') sampler_spacing = gr.Dropdown(label='Timestep spacing', elem_id=f"{tabname}_sampler_spacing", choices=['default', 'linspace', 'leading', 'trailing'], value=shared.opts.schedulers_timestep_spacing, type='value') with gr.Row(elem_classes=['flex-break']): sampler_beta = gr.Dropdown(label='Beta schedule', elem_id=f"{tabname}_sampler_beta", choices=['default', 'linear', 'scaled', 'cosine'], value=shared.opts.schedulers_beta_schedule, type='value') - sampler_prediction = gr.Dropdown(label='Prediction method', elem_id=f"{tabname}_sampler_prediction", choices=['default', 'epsilon', 'sample', 'v_prediction'], value=shared.opts.schedulers_prediction_type, type='value') + sampler_prediction = gr.Dropdown(label='Prediction method', elem_id=f"{tabname}_sampler_prediction", choices=['default', 'epsilon', 'sample', 'v_prediction', 'flow_prediction'], value=shared.opts.schedulers_prediction_type, type='value') with gr.Row(elem_classes=['flex-break']): sampler_presets = gr.Dropdown(label='Timesteps presets', elem_id=f"{tabname}_sampler_presets", choices=['None', 'AYS SD15', 'AYS SDXL'], value='None', type='value') sampler_timesteps = gr.Textbox(label='Timesteps override', elem_id=f"{tabname}_sampler_timesteps", value=shared.opts.schedulers_timesteps)