diff --git a/CHANGELOG.md b/CHANGELOG.md index 23e8e7a45..833b3601b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,41 @@ ## Update for 2023-12-30 -- Fixes: - - img2img interrogate +- **Fixes**: + - img2img clip and blip interrogate + - guard against invalid sampler index + - reset default cfg scale to 6.0 ## Update for 2023-12-29 +To wrap up this amazing year, we're releasing a new version of [SD.Next](https://github.com/vladmandic/automatic), this one is absolutely massive! + +### Highlights + +- Brand new Control module for *text, image, batch and video* processing + Native implementation of all control methods for both *SD15* and *SD-XL* + ▹ **ControlNet | ControlNet XS | Control LLLite | T2I Adapters | IP Adapters** + For details, see [Wiki](https://github.com/vladmandic/automatic/wiki/Control) documentation: +- Support for new models types out-of-the-box + This brings number of supported t2i/i2i model families to 13! + ▹ **Stable Diffusion 1.5/2.1 | SD-XL | LCM | Segmind | Kandinsky | Pixart-α | Würstchen | aMUSEd | DeepFloyd IF | UniDiffusion | SD-Distilled | BLiP Diffusion | etc.** +- New video capabilities: + ▹ **AnimateDiff | SVD | ModelScope | ZeroScope** +- Enhanced platform support + ▹ **Windows | Linux | MacOS** with **nVidia | AMD | IntelArc | DirectML | OpenVINO | ONNX+Olive** backends +- Better onboarding experience (first install) + with all model types available for single click download & load (networks -> reference) +- Performance optimizations! + For comparisment of different processing options and compile backends, see [Wiki](https://github.com/vladmandic/automatic/wiki/Benchmark) + As a highlight, we're reaching **~100 it/s** (no tricks, this is with full features enabled and end-to-end on a standard nVidia RTX4090) +- New [custom pipelines](https://github.com/vladmandic/automatic/blob/dev/scripts/example.py) framework for quickly porting any new pipeline + +And others improvements in areas such as: Upscaling (up to 8x now with 40+ available upscalers), Inpainting (better quality), Prompt scheduling, new Sampler options, new LoRA types, additional UI themes, better HDR processing, built-in Video interpolation, parallel Batch processing, etc. + +Plus some nifty new modules such as **FaceID** automatic face guidance using embeds during generation and **Depth 3D** image to 3D scene + +### Full changelog + - **Control** - native implementation of all image control methods: **ControlNet**, **ControlNet XS**, **Control LLLite**, **T2I Adapters** and **IP Adapters** diff --git a/modules/control/run.py b/modules/control/run.py index e4dc60dfe..7e499e956 100644 --- a/modules/control/run.py +++ b/modules/control/run.py @@ -15,7 +15,7 @@ from modules.control.units import lite # Kohya ControlLLLite from modules.control.units import t2iadapter # TencentARC T2I-Adapter from modules.control.units import reference # ControlNet-Reference from modules.control.units import ipadapter # IP-Adapter -from modules import devices, shared, errors, processing, images, sd_models, sd_samplers +from modules import devices, shared, errors, processing, images, sd_models debug = shared.log.trace if os.environ.get('SD_CONTROL_DEBUG', None) is not None else lambda *args, **kwargs: None @@ -90,8 +90,8 @@ def control_run(units: List[unit.Unit], inputs, inits, unit_type: str, is_genera negative_prompt = negative, styles = styles, steps = steps, - sampler_name = sd_samplers.samplers[sampler_index].name, - latent_sampler = sd_samplers.samplers[sampler_index].name, + sampler_name = processing.get_sampler_name(sampler_index), + latent_sampler = processing.get_sampler_name(sampler_index), seed = seed, subseed = subseed, subseed_strength = subseed_strength, diff --git a/modules/hypernetworks/hypernetwork.py b/modules/hypernetworks/hypernetwork.py index 8ad9fc822..f5d192b05 100644 --- a/modules/hypernetworks/hypernetwork.py +++ b/modules/hypernetworks/hypernetwork.py @@ -11,7 +11,7 @@ from torch import einsum from torch.nn.init import normal_, xavier_normal_, xavier_uniform_, kaiming_normal_, kaiming_uniform_, zeros_ from einops import rearrange, repeat from ldm.util import default -from modules import devices, processing, sd_models, shared, sd_samplers, hashes, sd_hijack_checkpoint, errors +from modules import devices, processing, sd_models, shared, hashes, sd_hijack_checkpoint, errors import modules.textual_inversion.dataset from modules.textual_inversion import textual_inversion, ti_logging from modules.textual_inversion.learn_schedule import LearnRateScheduler @@ -445,7 +445,7 @@ def create_hypernetwork(name, enable_sizes, overwrite_old, layer_structure=None, return name -def train_hypernetwork(id_task, hypernetwork_name, learn_rate, batch_size, gradient_step, data_root, log_directory, training_width, training_height, varsize, steps, clip_grad_mode, clip_grad_value, shuffle_tags, tag_drop_out, latent_sampling_method, use_weight, create_image_every, save_hypernetwork_every, template_filename, preview_from_txt2img, preview_prompt, preview_negative_prompt, preview_steps, preview_sampler_index, preview_cfg_scale, preview_seed, preview_width, preview_height): +def train_hypernetwork(id_task, hypernetwork_name, learn_rate, batch_size, gradient_step, data_root, log_directory, training_width, training_height, varsize, steps, clip_grad_mode, clip_grad_value, shuffle_tags, tag_drop_out, latent_sampling_method, use_weight, create_image_every, save_hypernetwork_every, template_filename, preview_from_txt2img, preview_prompt, preview_negative_prompt, preview_steps, preview_sampler_index, preview_cfg_scale, preview_seed, preview_width, preview_height): # pylint: disable=unused-argument # images allows training previews to have infotext. Importing it at the top causes a circular import problem. from modules import images @@ -672,7 +672,7 @@ def train_hypernetwork(id_task, hypernetwork_name, learn_rate, batch_size, gradi p.prompt = preview_prompt p.negative_prompt = preview_negative_prompt p.steps = preview_steps - p.sampler_name = sd_samplers.samplers[preview_sampler_index].name + p.sampler_name = processing.get_sampler_name(preview_sampler_index) p.cfg_scale = preview_cfg_scale p.seed = preview_seed p.width = preview_width diff --git a/modules/img2img.py b/modules/img2img.py index 4c0ce910b..66cb8d6f6 100644 --- a/modules/img2img.py +++ b/modules/img2img.py @@ -3,7 +3,7 @@ import itertools # SBM Batch frames import numpy as np from PIL import Image, ImageOps, ImageFilter, ImageEnhance, ImageChops, UnidentifiedImageError import modules.scripts -from modules import sd_samplers, shared, processing, images +from modules import shared, processing, images from modules.generation_parameters_copypaste import create_override_settings_dict from modules.ui import plaintext_to_html from modules.memstats import memory_stats @@ -212,8 +212,8 @@ def img2img(id_task: str, mode: int, seed_resize_from_h=seed_resize_from_h, seed_resize_from_w=seed_resize_from_w, seed_enable_extras=True, - sampler_name=sd_samplers.samplers_for_img2img[sampler_index].name, - latent_sampler=sd_samplers.samplers[latent_index].name, + sampler_name = processing.get_sampler_name(sampler_index, img=True), + latent_sampler = processing.get_sampler_name(latent_index, img=True), batch_size=batch_size, n_iter=n_iter, steps=steps, diff --git a/modules/processing.py b/modules/processing.py index e749eb59c..b57f1cfba 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -120,6 +120,16 @@ def txt2img_image_conditioning(sd_model, x, width, height): return x.new_zeros(x.shape[0], 5, 1, 1, dtype=x.dtype, device=x.device) +def get_sampler_name(sampler_index: int, img: bool = False) -> str: + samplers = modules.sd_samplers.samplers if not img else modules.sd_samplers.samplers_for_img2img + if len(samplers) > sampler_index: + sampler_name = samplers[sampler_index].name + else: + sampler_name = "UniPC" + shared.log.warning(f'Sampler not found: index={sampler_index} available={[s.name for s in samplers]} fallback={sampler_name}') + return sampler_name + + @dataclass(repr=False) class StableDiffusionProcessing: """ diff --git a/modules/processing_diffusers.py b/modules/processing_diffusers.py index 54cab61bc..f8d0e635a 100644 --- a/modules/processing_diffusers.py +++ b/modules/processing_diffusers.py @@ -350,7 +350,6 @@ def process_diffusers(p: StableDiffusionProcessing): def update_sampler(sd_model, second_pass=False): sampler_selection = p.latent_sampler if second_pass else p.sampler_name - # is_karras_compatible = sd_model.__class__.__init__.__annotations__.get("scheduler", None) == diffusers.schedulers.scheduling_utils.KarrasDiffusionSchedulers if sd_model.__class__.__name__ in ['AmusedPipeline']: return # models with their own schedulers if hasattr(sd_model, 'scheduler') and sampler_selection != 'Default': diff --git a/modules/textual_inversion/textual_inversion.py b/modules/textual_inversion/textual_inversion.py index 53b27cf47..0688e37be 100644 --- a/modules/textual_inversion/textual_inversion.py +++ b/modules/textual_inversion/textual_inversion.py @@ -9,7 +9,7 @@ import safetensors.torch import numpy as np from PIL import Image, PngImagePlugin from torch.utils.tensorboard import SummaryWriter -from modules import shared, devices, sd_hijack, processing, sd_models, images, sd_samplers, sd_hijack_checkpoint, errors +from modules import shared, devices, sd_hijack, processing, sd_models, images, sd_hijack_checkpoint, errors import modules.textual_inversion.dataset from modules.textual_inversion.learn_schedule import LearnRateScheduler from modules.textual_inversion.image_embedding import embedding_to_b64, embedding_from_b64, insert_image_data_embed, extract_image_data_embed, caption_image_overlay @@ -599,7 +599,7 @@ def train_embedding(id_task, embedding_name, learn_rate, batch_size, gradient_st p.prompt = preview_prompt p.negative_prompt = preview_negative_prompt p.steps = preview_steps - p.sampler_name = sd_samplers.samplers[preview_sampler_index].name + p.sampler_name = processing.get_sampler_name(preview_sampler_index) p.cfg_scale = preview_cfg_scale p.seed = preview_seed p.width = preview_width diff --git a/modules/txt2img.py b/modules/txt2img.py index deb87caba..98004c492 100644 --- a/modules/txt2img.py +++ b/modules/txt2img.py @@ -1,6 +1,6 @@ import os import modules.scripts -from modules import sd_samplers, shared, processing +from modules import shared, processing from modules.generation_parameters_copypaste import create_override_settings_dict from modules.ui import plaintext_to_html @@ -50,8 +50,8 @@ def txt2img(id_task, seed_resize_from_h=seed_resize_from_h, seed_resize_from_w=seed_resize_from_w, seed_enable_extras=True, - sampler_name=sd_samplers.samplers[sampler_index].name, - latent_sampler=sd_samplers.samplers[latent_index].name, + sampler_name = processing.get_sampler_name(sampler_index), + latent_sampler = processing.get_sampler_name(latent_index), batch_size=batch_size, n_iter=n_iter, steps=steps, diff --git a/modules/ui.py b/modules/ui.py index a1c76ff1f..90b1f6a0d 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -183,10 +183,10 @@ def create_advanced_inputs(tab): with gr.Accordion(open=False, label="Advanced", elem_id=f"{tab}_advanced", elem_classes=["small-accordion"]): with gr.Group(): with FormRow(): - cfg_scale = gr.Slider(minimum=0.0, maximum=30.0, step=0.1, label='CFG scale', value=4.0, elem_id=f"{tab}_cfg_scale") + cfg_scale = gr.Slider(minimum=0.0, maximum=30.0, step=0.1, label='CFG scale', value=6.0, elem_id=f"{tab}_cfg_scale") clip_skip = gr.Slider(label='CLIP skip', value=1, minimum=1, maximum=14, step=1, elem_id=f"{tab}_clip_skip", interactive=True) with FormRow(): - image_cfg_scale = gr.Slider(minimum=0.0, maximum=30.0, step=0.1, label='Secondary CFG scale', value=4.0, elem_id=f"{tab}_image_cfg_scale") + image_cfg_scale = gr.Slider(minimum=0.0, maximum=30.0, step=0.1, label='Secondary CFG scale', value=6.0, elem_id=f"{tab}_image_cfg_scale") diffusers_guidance_rescale = gr.Slider(minimum=0.0, maximum=1.0, step=0.05, label='Guidance rescale', value=0.7, elem_id=f"{tab}_image_cfg_rescale", visible=shared.backend == shared.Backend.DIFFUSERS) with gr.Group(): with FormRow():