Source code for dgenerate.renderloopconfig

# Copyright (c) 2023, Teriks
#
# dgenerate is distributed under the following BSD 3-Clause License
#
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived
#    from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import collections.abc
import random
import typing

import dgenerate.hfhub as _hfhub
import dgenerate.image as _image
import dgenerate.mediainput as _mediainput
import dgenerate.mediaoutput as _mediaoutput
import dgenerate.pipelinewrapper as _pipelinewrapper
import dgenerate.pipelinewrapper.util as _pipelinewrapper_util
import dgenerate.prompt as _prompt
import dgenerate.promptupscalers as _promptupscalers
import dgenerate.promptweighters as _promptweighters
import dgenerate.textprocessing as _textprocessing
import dgenerate.torchutil as _torchutil
import dgenerate.types as _types

IMAGE_PROCESSOR_SEP = '+'
"""
The character that is used to separate image processor chains
when specifying processors for individual images in a group
of input images. This is also used for latents processors.
"""


def _iterate_diffusion_args(**kwargs) -> collections.abc.Iterator[_pipelinewrapper.DiffusionArguments]:
    def _list_or_list_of_none(val: typing.Any) -> typing.List[typing.Any]:
        return val if val else [None]

    yield from _types.iterate_attribute_combinations(
        [(arg_name, _list_or_list_of_none(value)) for arg_name, value in kwargs.items()],
        _pipelinewrapper.DiffusionArguments)


[docs] def gen_seeds(n: int) -> list[int]: """ Generate a list of N random seed integers :param n: number of seeds to generate :return: list of integer seeds """ return [random.randint(0, 99999999999999) for _ in range(0, n)]
[docs] class RenderLoopConfigError(Exception): """ Raised by :py:meth:`.RenderLoopConfig.check` on configuration errors. """ pass
[docs] class RenderLoopConfig(_types.SetFromMixin): """ This object represents configuration for :py:class:`RenderLoop`. It nearly directly maps to dgenerate's command line arguments. See subclass :py:class:`dgenerate.arguments.DgenerateArguments` """ model_path: _types.OptionalPath = None """ Primary diffusion model path, ``model_path`` argument of dgenerate command line tool. """ subfolder: _types.OptionalPath = None """ Primary model subfolder argument, ``--subfolder`` argument of dgenerate command line tool. """ original_config: _types.OptionalPath = None """ This option can be used to supply an original LDM config .yaml file that was provided with a single file checkpoint. """ second_model_original_config: _types.OptionalPath = None """ This option can be used to supply an original LDM config .yaml file that was provided with a single file checkpoint for the secondary model, i.e. the SDXL Refiner or Stable Cascade Decoder. """ sdxl_refiner_uri: _types.OptionalUri = None """ SDXL Refiner model URI, ``--sdxl-refiner`` argument of dgenerate command line tool. """ sdxl_refiner_edit: _types.OptionalBoolean = None """ Force the SDXL refiner to operate in edit mode instead of cooperative denoising mode. """ batch_size: _types.OptionalInteger = None """ Image generation batch size, ``--batch-size`` argument of dgenerate command line tool. """ batch_grid_size: _types.OptionalSize = None """ Optional image grid size specification for when **batch_size** is greater than one. This is the ``--batch-grid-size`` argument of the dgenerate command line tool. """ prompt_weighter_uri: _types.OptionalUri = None """ The URI of a prompt-weighter implementation supported by dgenerate. This corresponds to the ``--prompt-weighter`` argument of the dgenerate command line tool. """ second_model_prompt_weighter_uri: _types.OptionalUri = None """ The URI of a prompt-weighter implementation supported by dgenerate to use with the SDXL refiner or Stable Cascade decoder. Defaults to :py:attr:`RenderLoopConfig.prompt_weighter_uri` if not specified. This corresponds to the ``--second-model-prompt-weighter`` argument of the dgenerate command line tool. """ prompt_upscaler_uri: _types.OptionalUriOrUris = None """ The URI of a prompt-upscaler implementation supported by dgenerate. This may also be a list of URIs, the prompt upscalers will be chained together sequentially. This corresponds to the ``--prompt-upscaler`` argument of the dgenerate command line tool. """ second_model_prompt_upscaler_uri: _types.OptionalUriOrUris = None """ The URI of a prompt-upscaler implementation supported by dgenerate to use with the SDXL refiner or Stable Cascade decoder. Defaults to :py:attr:`RenderLoopConfig.prompt_upscaler_uri` if not specified. This may also be a list of URIs, the prompt upscalers will be chained together sequentially. This corresponds to the ``--second-model-prompt-upscaler`` argument of the dgenerate command line tool. """ second_prompt_upscaler_uri: _types.OptionalUriOrUris = None """ The URI of a prompt-upscaler implementation supported by dgenerate that applies to :py:attr:`RenderLoopConfig.second_prompts` Defaults to :py:attr:`RenderLoopConfig.prompt_upscaler_uri` if not specified. This may also be a list of URIs, the prompt upscalers will be chained together sequentially. This corresponds to the ``--second-prompt-upscaler`` argument of the dgenerate command line tool. """ second_model_second_prompt_upscaler_uri: _types.OptionalUriOrUris = None """ The URI of a prompt-upscaler implementation supported by dgenerate to use with the SDXL refiner ``--second-prompts`` value. Or rather :py:attr:`RenderLoopConfig.second_model_second_prompts` Defaults to :py:attr:`RenderLoopConfig.prompt_upscaler_uri` if not specified. This may also be a list of URIs, the prompt upscalers will be chained together sequentially. This corresponds to the ``--second-model-second-prompt-upscaler`` argument of the dgenerate command line tool. """ third_prompt_upscaler_uri: _types.OptionalUriOrUris = None """ The URI of a prompt-upscaler implementation supported by dgenerate that applies to :py:attr:`RenderLoopConfig.third_prompts` Defaults to :py:attr:`RenderLoopConfig.prompt_upscaler_uri` if not specified. This may also be a list of URIs, the prompt upscalers will be chained together sequentially. This corresponds to the ``--third-prompt-upscaler`` argument of the dgenerate command line tool. """ prompts: _prompt.Prompts """ List of prompt objects, this corresponds to the ``--prompts`` argument of the dgenerate command line tool. """ max_sequence_length: _types.OptionalInteger = None """ Max number of prompt tokens that the T5EncoderModel (text encoder 3) of Stable Diffusion 3 or Flux can handle. This defaults to 256 for SD3 when not specified, and 512 for Flux. The maximum value is 512 and the minimum value is 1. High values result in more resource usage and processing time. """ second_prompts: _prompt.OptionalPrompts = None """ Optional list of SD3 / Flux secondary prompts, this corresponds to the ``--second-prompts`` argument of the dgenerate command line tool. """ third_prompts: _prompt.OptionalPrompts = None """ Optional list of SD3 tertiary prompts, this corresponds to the ``--third-prompts`` argument of the dgenerate command line tool. Flux does not support this argument. """ sdxl_t2i_adapter_factors: _types.OptionalFloats = None """ Optional list of SDXL specific T2I adapter factors to try, this controls the amount of time-steps for which a T2I adapter applies guidance to an image, this is a value between 0.0 and 1.0. A value of 0.5 for example indicates that the T2I adapter is only active for half the amount of time-steps it takes to completely render an image. """ second_model_prompts: _prompt.OptionalPrompts = None """ Optional list of SDXL refiner or Stable Cascade decoder prompt overrides, this corresponds to the ``--second-model-prompts`` argument of the dgenerate command line tool. """ second_model_second_prompts: _prompt.OptionalPrompts = None """ Optional list of SDXL refiner secondary prompt overrides, this corresponds to the ``--second-model-second-prompts`` argument of the dgenerate command line tool. The Stable Cascade Decoder does not support this argument. """ seeds: _types.Integers """ List of integer seeds, this corresponds to the ``--seeds`` argument of the dgenerate command line tool. """ seeds_to_images: bool = False """ Should :py:attr:`RenderLoopConfig.seeds` be interpreted as seeds for each image input instead of combinatorial? this includes control images. """ guidance_scales: _types.Floats """ List of floating point guidance scales, this corresponds to the ``--guidance-scales`` argument of the dgenerate command line tool. """ sigmas: typing.Optional[collections.abc.Sequence[collections.abc.Sequence[float] | str]] = None """ One or more lists of sigma values to try. This is supported when using a :py:attr:`RenderLoopConfig.scheduler_uri` that supports setting sigmas. Or: string expressions involving sigmas from the selected scheduler such as ``sigmas * 0.95``, sigmas will be represented as a numpy array, numpy is available through the namespace ``np``, this uses ``asteval``. Lists of floats and strings representing expressions can be intermixed. Sigma values control the noise schedule in the diffusion process, allowing for fine-grained control over how noise is added and removed during image generation. This corresponds to the ``--sigmas`` command line argument, which accepts multiple comma-separated lists of floating point values, or singular values, or expressions denoted with: ``expr: ...``. You do not need to specify ``expr:`` when passing this value in the library, simply pass a string instead of a list of floats. Example: ``[[1.0,2.0,3.0], 'sigmas * 0.95']`` """ inference_steps: _types.Integers """ List of inference steps values, this corresponds to the ``--inference-steps`` argument of the dgenerate command line tool. """ clip_skips: _types.OptionalIntegers = None """ List of clip skip values. Clip skip is the number of layers to be skipped from CLIP while computing the prompt embeddings. A value of 1 means that the output of the pre-final layer will be used for computing the prompt embeddings. Only supported for ``model_type`` values ``sd`` and ``sdxl``, including with ``controlnet_uris`` defined. """ sdxl_refiner_clip_skips: _types.OptionalIntegers = None """ Clip skip override values for the SDXL refiner, which normally defaults to the clip skip value for the main model when it is defined. """ image_seeds: _types.OptionalUris = None """ List of ``--image-seeds`` URI strings. """ parsed_image_seeds: _mediainput.OptionalParsedImageSeeds = None """ The results of parsing URIs mentioned in :py:attr:`.RenderLoopConfig.image_seeds`, will only be available if :py:meth:`.RenderLoopConfig.check` has been called. """ image_seed_strengths: _types.OptionalFloats = None """ Optional list of floating point image seed strengths, this corresponds to the ``--image-seed-strengths`` argument of the dgenerate command line tool. """ upscaler_noise_levels: _types.OptionalIntegers = None """ Optional list of integer upscaler noise levels, this corresponds to the ``--upscaler-noise-levels`` argument of the dgenerate command line tool that is used for the :py:attr:`dgenerate.pipelinewrapper.ModelType.UPSCALER_X4` model type only. """ guidance_rescales: _types.OptionalFloats = None """ List of floating point guidance rescale values which are supported by some pipelines, (there will be an error if it is unsupported upon running), this corresponds to the ``--guidance-rescales`` argument of the dgenerate command line tool. """ image_guidance_scales: _types.OptionalFloats = None """ Optional list of floating point image guidance scales, used for pix2pix model types, this corresponds to the ``--image-guidance-scales`` argument of the dgenerate command line tool. """ s_cascade_decoder_uri: _types.OptionalUri = None """ Stable Cascade model URI, ``--s-cascade-decoder`` argument of dgenerate command line tool. """ sdxl_high_noise_fractions: _types.OptionalFloats = None """ Optional list of SDXL refiner high noise fractions (floats), this value is the fraction of inference steps that the base model handles, the inverse proportion of the provided fraction is handled by the refiner model. This corresponds to the ``--sdxl-high-noise-fractions`` argument of the dgenerate command line tool. """ second_model_inference_steps: _types.OptionalIntegers = None """ Optional list of inference steps value overrides for the SDXL refiner, this corresponds to the ``--second-model-inference-steps`` argument of the dgenerate command line tool. """ second_model_guidance_scales: _types.OptionalFloats = None """ Optional list of guidance scale value overrides for the SDXL refiner or Stable Cascade decoder, this corresponds to the ``--second-model-guidance-scales`` argument of the dgenerate command line tool. """ sdxl_refiner_sigmas: typing.Optional[collections.abc.Sequence[collections.abc.Sequence[float] | str]] = None """ One or more lists of sigma values to try with the SDXL refiner. This is supported when using a :py:attr:`RenderLoopConfig.second_model_scheduler_uri` that supports setting sigmas. Or: string expressions involving sigmas from the selected scheduler such as ``sigmas * 0.95``, sigmas will be represented as a numpy array, numpy is available through the namespace ``np``, this uses ``asteval``. Lists of floats and strings representing expressions can be intermixed. Sigma values control the noise schedule in the diffusion process, allowing for fine-grained control over how noise is added and removed during image generation. This corresponds to the ``--sdxl-refiner-sigmas`` command line argument, which accepts multiple comma-separated lists of floating point values, or singular values, or expressions denoted with: ``expr: ...``. You do not need to specify ``expr:`` when passing this value in the library, simply pass a string instead of a list of floats. Example: ``[[1.0,2.0,3.0], 'sigmas * 0.95']`` """ sdxl_refiner_guidance_rescales: _types.OptionalFloats = None """ Optional list of guidance rescale value overrides for the SDXL refiner or Stable Cascade decoder, this corresponds to the ``--sdxl-refiner-guidance-rescales`` argument of the dgenerate command line tool. """ sdxl_aesthetic_scores: _types.OptionalFloats = None """ Optional list of SDXL aesthetic-score conditioning values, this corresponds to the ``--sdxl-aesthetic-scores`` argument of the dgenerate command line tool. """ sdxl_original_sizes: _types.OptionalSizes = None """ Optional list of SDXL original-size micro-conditioning parameters, this corresponds to the ``--sdxl-original-sizes`` argument of the dgenerate command line tool. """ sdxl_target_sizes: _types.OptionalSizes = None """ Optional list of SDXL target-size micro-conditioning parameters, this corresponds to the ``--sdxl-target-sizes`` argument of the dgenerate command line tool. """ sdxl_crops_coords_top_left: _types.OptionalCoordinates = None """ Optional list of SDXL top-left-crop-coords micro-conditioning parameters, this corresponds to the ``--sdxl-crops-coords-top-left`` argument of the dgenerate command line tool. """ sdxl_negative_aesthetic_scores: _types.OptionalFloats = None """ Optional list of negative influence SDXL aesthetic-score conditioning values, this corresponds to the ``--sdxl-negative-aesthetic-scores`` argument of the dgenerate command line tool. """ sdxl_negative_original_sizes: _types.OptionalSizes = None """ Optional list of negative influence SDXL original-size micro-conditioning parameters, this corresponds to the ``--sdxl-negative-original-sizes`` argument of the dgenerate command line tool. """ sdxl_negative_target_sizes: _types.OptionalSizes = None """ Optional list of negative influence SDXL target-size micro-conditioning parameters, this corresponds to the ``--sdxl-negative-target-sizes`` argument of the dgenerate command line tool. """ sdxl_negative_crops_coords_top_left: _types.OptionalCoordinates = None """ Optional list of negative influence SDXL top-left crop coords micro-conditioning parameters, this corresponds to the ``--sdxl-negative-crops-coords-top-left`` argument of the dgenerate command line tool. """ sdxl_refiner_aesthetic_scores: _types.OptionalFloats = None """ Optional list of SDXL-refiner override aesthetic-score conditioning values, this corresponds to the ``--sdxl-refiner-aesthetic-scores`` argument of the dgenerate command line tool. """ sdxl_refiner_original_sizes: _types.OptionalSizes = None """ Optional list of SDXL-refiner override original-size micro-conditioning parameters, this corresponds to the ``--sdxl-refiner-original-sizes`` argument of the dgenerate command line tool. """ sdxl_refiner_target_sizes: _types.OptionalSizes = None """ Optional list of SDXL-refiner override target-size micro-conditioning parameters, this corresponds to the ``--sdxl-refiner-target-sizes`` argument of the dgenerate command line tool. """ sdxl_refiner_crops_coords_top_left: _types.OptionalCoordinates = None """ Optional list of SDXL-refiner override top-left-crop-coords micro-conditioning parameters, this corresponds to the ``--sdxl-refiner-crops-coords-top-left`` argument of the dgenerate command line tool. """ sdxl_refiner_negative_aesthetic_scores: _types.OptionalFloats = None """ Optional list of negative influence SDXL-refiner override aesthetic-score conditioning values, this corresponds to the ``--sdxl-refiner-negative-aesthetic-scores`` argument of the dgenerate command line tool. """ sdxl_refiner_negative_original_sizes: _types.OptionalSizes = None """ Optional list of negative influence SDXL-refiner override original-size micro-conditioning parameters, this corresponds to the ``--sdxl-refiner-negative-original-sizes`` argument of the dgenerate command line tool. """ sdxl_refiner_negative_target_sizes: _types.OptionalSizes = None """ Optional list of negative influence SDXL-refiner override target-size micro-conditioning parameters, this corresponds to the ``--sdxl-refiner-negative-target-sizes`` argument of the dgenerate command line tool. """ sdxl_refiner_negative_crops_coords_top_left: _types.OptionalCoordinates = None """ Optional list of negative influence SDXL-refiner top-left crop coords micro-conditioning parameters, this corresponds to the ``--sdxl-refiner-negative-crops-coords-top-left`` argument of the dgenerate command line tool. """ unet_uri: _types.OptionalUri = None """ Optional user specified UNet URI, this corresponds to the ``--unet`` argument of the dgenerate command line tool. """ second_model_unet_uri: _types.OptionalUri = None """ Optional user specified second UNet URI, this corresponds to the ``--second-model-unet`` argument of the dgenerate command line tool. This UNet uri will be used for the SDXL refiner or Stable Cascade decoder model. """ transformer_uri: _types.OptionalUri = None """ Optional user specified Transformer URI, this corresponds to the ``--transformer`` argument of the dgenerate command line tool. This is currently only supported for Stable Diffusion 3 and Flux models. """ vae_uri: _types.OptionalUri = None """ Optional user specified VAE URI, this corresponds to the ``--vae`` argument of the dgenerate command line tool. """ vae_tiling: bool = False """ Enable VAE tiling? ``--vae-tiling`` """ vae_slicing: bool = False """ Enable VAE slicing? ``--vae-slicing`` """ lora_uris: _types.OptionalUris = None """ Optional user specified LoRA URIs, this corresponds to the ``--loras`` argument of the dgenerate command line tool. """ lora_fuse_scale: _types.OptionalFloat = None """ Optional global LoRA fuse scale, this corresponds to the ``--lora-fuse-scale`` argument of the dgenerate command line tool. LoRA weights are merged into the main model at this scale. When specifying multiple LoRA models, they are fused together into one set of weights using their individual scale values, after which they are fused into the main model at this scale value. The default value when ``None`` is specified is ``1.0``. """ image_encoder_uri: _types.OptionalUri = None """ Optional user specified Image Encoder URI when using IP Adapter models or Stable Cascade. This corresponds to the ``--image-encoder`` argument of the dgenerate command line tool. If none of your specified ``--ip-adapters`` URIs point to a model which contains an Image Encoder model, you will need to specify one manually using this argument. """ ip_adapter_uris: _types.OptionalUris = None """ Optional user specified IP Adapter URIs, this corresponds to the ``--ip-adapters`` argument of the dgenerate command line tool. """ textual_inversion_uris: _types.OptionalUris = None """ Optional user specified Textual Inversion URIs, this corresponds to the ``--textual-inversions`` argument of the dgenerate command line tool. """ text_encoder_uris: _types.OptionalUris = None """ Optional user specified Text Encoder URIs, this corresponds to the ``--text-encoders`` argument of the dgenerate command line tool. """ second_model_text_encoder_uris: _types.OptionalUris = None """ Optional user specified Text Encoder URIs, this corresponds to the ``--second-model-text-encoders`` argument of the dgenerate command line tool. This specifies text encoders for the SDXL refiner or Stable Cascade decoder. """ controlnet_uris: _types.OptionalUris = None """ Optional user specified ControlNet URIs, this corresponds to the ``--control-nets`` argument of the dgenerate command line tool. """ t2i_adapter_uris: _types.OptionalUris = None """ Optional user specified T2IAdapter URIs, this corresponds to the ``--t2i-adapters`` argument of the dgenerate command line tool. """ quantizer_uri: _types.OptionalUri = None """ Global quantizer URI for main pipline, this corresponds to the ``--quantizer`` argument of the dgenerate command line tool. The quantization backend and settings specified by this URI will be used globally on the the most appropriate models associated with the main diffusion pipeline. """ quantizer_map: _types.OptionalStrings = None """ Collection of pipeline submodule names to which quantization should be applied when :py:attr`RenderLoopConfig.quantizer_uri` is provided. Valid values include: ``unet``, ``transformer``, ``text_encoder``, ``text_encoder_2``, ``text_encoder_3``. If ``None``, all supported modules will be quantized. """ second_model_quantizer_uri: _types.OptionalUri = None """ Global quantizer URI for secondary pipeline (SDXL Refiner or Stable Cascade decoder), this corresponds to the ``--second-model-quantizer`` argument of the dgenerate command line tool. The quantization backend and settings specified by this URI will be used globally on the the most appropriate models associated with the secondary diffusion pipeline (SDXL Refiner, Stable Cascade Decoder). """ second_model_quantizer_map: _types.OptionalStrings = None """ Collection of secondary pipeline submodule names to which quantization should be applied when :py:attr`RenderLoopConfig.second_model_quantizer_uri` is provided. Valid values include: ``unet``, ``transformer``, ``text_encoder``, ``text_encoder_2``, ``text_encoder_3``. If ``None``, all supported modules will be quantized. """ scheduler_uri: _types.OptionalUriOrUris = None """ Optional primary model scheduler/sampler class name specification, this corresponds to the ``--scheduler`` argument of the dgenerate command line tool. Setting this to 'help' will yield a help message to stdout describing scheduler names compatible with the current configuration upon running. Passing 'helpargs' will yield a help message with a list of overridable arguments for each scheduler and their typical defaults. This may be a list of schedulers, indicating to try each scheduler in turn. """ freeu_params: typing.Optional[collections.abc.Sequence[tuple[float, float, float, float]]] = None """ FreeU is a technique for improving image quality by re-balancing the contributions from the UNet's skip connections and backbone feature maps. This can be used with no cost to performance, to potentially improve image quality. This argument can be used to specify The FreeU parameters: s1, s2, b1, and b2 in that order. You can specify the FreeU parameters as a list / sequence of tuples that will be tried in turn for generation. This argument only applies to models that utilize a UNet: SD1.5/2, SDXL, and Kolors See: https://huggingface.co/docs/diffusers/main/en/using-diffusers/freeu And: https://github.com/ChenyangSi/FreeU """ sdxl_refiner_freeu_params: typing.Optional[collections.abc.Sequence[tuple[float, float, float, float]]] = None """ List / sequence of FreeU parameters to try for the SDXL refiner. See: :py:attr:`RenderLoopConfig.freeu_params` for clarification. """ hi_diffusion: bool = False """ Activate HiDiffusion for the primary model? This can increase the resolution at which the model can output images while retaining quality with no overhead, and possibly improved performance. See: https://github.com/megvii-research/HiDiffusion This is supported for: ``--model-type sd, sdxl, and kolors``. """ hi_diffusion_no_win_attn: _types.OptionalBoolean = None """ Disable window attention when using HiDiffusion for the primary model? This disables the MSW-MSA (Multi-Scale Window Multi-Head Self-Attention) component of HiDiffusion. See: https://github.com/megvii-research/HiDiffusion This is supported for: ``--model-type sd, sdxl, and kolors``. """ hi_diffusion_no_raunet: _types.OptionalBoolean = None """ Disable RAU-Net when using HiDiffusion for the primary model? This disables the Resolution-Aware U-Net component of HiDiffusion. See: https://github.com/megvii-research/HiDiffusion This is supported for: ``--model-type sd, sdxl, and kolors``. """ sada: bool = False """ Enable SADA (Stability-guided Adaptive Diffusion Acceleration) with default parameters for the primary model. Specifying this alone is equivalent to setting all SADA parameters to their model-specific default values: - SD/SD2: ``sada_max_downsamples=1``, ``sada_sxs=3``, ``sada_sys=3``, ``sada_lagrange_terms=4``, ``sada_lagrange_ints=4``, ``sada_lagrange_steps=24``, ``sada_max_fixes=5120`` - SDXL/Kolors: ``sada_max_downsamples=2``, ``sada_sxs=3``, ``sada_sys=3``, ``sada_lagrange_terms=4``, ``sada_lagrange_ints=4``, ``sada_lagrange_steps=24``, ``sada_max_fixes=10240`` - Flux: ``sada_max_downsamples=0``, ``sada_lagrange_terms=3``, ``sada_lagrange_ints=4``, ``sada_lagrange_steps=20``, ``sada_max_fixes=0`` SADA is not compatible with HiDiffusion, DeepCache, or TeaCache. """ sada_max_downsamples: _types.OptionalIntegers = None """ SADA maximum downsample factor for the primary model. Controls the maximum downsample factor in the SADA algorithm. Lower values can improve quality but may reduce speedup. Model-specific defaults: - SD/SD2: 1 - SDXL/Kolors: 2 - Flux: 0 See: https://github.com/Ting-Justin-Jiang/sada-icml Supplying any SADA parameter implies that SADA is enabled. This is supported for: ``--model-type sd, sdxl, kolors, flux*``. Each value supplied will be tried in turn. """ sada_sxs: _types.OptionalIntegers = None """ SADA spatial downsample factor X for the primary model. Controls the spatial downsample factor in the X dimension. Higher values can increase speedup but may affect quality. Model-specific defaults: - SD/SD2: 3 - SDXL/Kolors: 3 - Flux: 0 (not used) See: https://github.com/Ting-Justin-Jiang/sada-icml Supplying any SADA parameter implies that SADA is enabled. This is supported for: ``--model-type sd, sdxl, kolors, flux*``. Each value supplied will be tried in turn. """ sada_sys: _types.OptionalIntegers = None """ SADA spatial downsample factor Y for the primary model. Controls the spatial downsample factor in the Y dimension. Higher values can increase speedup but may affect quality. Model-specific defaults: - SD/SD2: 3 - SDXL/Kolors: 3 - Flux: 0 (not used) See: https://github.com/Ting-Justin-Jiang/sada-icml Supplying any SADA parameter implies that SADA is enabled. This is supported for: ``--model-type sd, sdxl, kolors, flux*``. Each value supplied will be tried in turn. """ sada_acc_ranges: _types.OptionalRanges = None """ SADA acceleration range start / end steps for the primary model. Defines the starting / ending step for SADA acceleration. Starting step must be at least 3 as SADA leverages third-order dynamics. Defaults to [[10,47]]. See: https://github.com/Ting-Justin-Jiang/sada-icml Supplying any SADA parameter implies that SADA is enabled. This is supported for: ``--model-type sd, sdxl, kolors, flux*``. Each value supplied will be tried in turn. """ sada_lagrange_terms: _types.OptionalIntegers = None """ SADA Lagrangian interpolation terms for the primary model. Number of terms to use in Lagrangian interpolation. Set to 0 to disable Lagrangian interpolation. Model-specific defaults: - SD/SD2: 4 - SDXL/Kolors: 4 - Flux: 3 See: https://github.com/Ting-Justin-Jiang/sada-icml Supplying any SADA parameter implies that SADA is enabled. This is supported for: ``--model-type sd, sdxl, kolors, flux*``. Each value supplied will be tried in turn. """ sada_lagrange_ints: _types.OptionalIntegers = None """ SADA Lagrangian interpolation interval for the primary model. Interval for Lagrangian interpolation. Must be compatible with sada_lagrange_step (lagrange_step % lagrange_int == 0). Model-specific defaults: - SD/SD2: 4 - SDXL/Kolors: 4 - Flux: 4 See: https://github.com/Ting-Justin-Jiang/sada-icml Supplying any SADA parameter implies that SADA is enabled. This is supported for: ``--model-type sd, sdxl, kolors, flux*``. Each value supplied will be tried in turn. """ sada_lagrange_steps: _types.OptionalIntegers = None """ SADA Lagrangian interpolation step for the primary model. Step value for Lagrangian interpolation. Must be compatible with sada_lagrange_int (lagrange_step % lagrange_int == 0). Model-specific defaults: - SD/SD2: 24 - SDXL/Kolors: 24 - Flux: 20 See: https://github.com/Ting-Justin-Jiang/sada-icml Supplying any SADA parameter implies that SADA is enabled. This is supported for: ``--model-type sd, sdxl, kolors, flux*``. Each value supplied will be tried in turn. """ sada_max_fixes: _types.OptionalIntegers = None """ SADA maximum fixed memory for the primary model. Maximum amount of fixed memory to use in SADA optimization. Model-specific defaults: - SD/SD2: 5120 (5 * 1024) - SDXL/Kolors: 10240 (10 * 1024) - Flux: 0 See: https://github.com/Ting-Justin-Jiang/sada-icml Supplying any SADA parameter implies that SADA is enabled. This is supported for: ``--model-type sd, sdxl, kolors, flux*``. Each value supplied will be tried in turn. """ sada_max_intervals: _types.OptionalIntegers = None """ SADA maximum interval for optimization for the primary model. Maximum interval between optimizations in the SADA algorithm. Defaults to 4. See: https://github.com/Ting-Justin-Jiang/sada-icml Supplying any SADA parameter implies that SADA is enabled. This is supported for: ``--model-type sd, sdxl, kolors, flux*``. Each value supplied will be tried in turn. """ tea_cache: bool = False """ Activate TeaCache for the primary model? This is supported for Flux, teacache uses a novel caching mechanism in the forward pass of the flux transformer to reduce the amount of computation needed to generate an image, this can speed up inference with small amounts of quality loss. See: https://github.com/ali-vilab/TeaCache Also see: :py:attr:`RenderLoopConfig.tea_cache_rel_l1_thresholds` This is supported for: ``--model-type flux*``. """ tea_cache_rel_l1_thresholds: _types.OptionalFloats = None """ TeaCache relative L1 thresholds to try when :py:attr:`RenderLoopConfig.tea_cache` is enabled. This should be one or more float values between 0.0 and 1.0, each value will be tried in turn. Higher values mean more speedup. Defaults to 0.6 (2.0x speedup). 0.25 for 1.5x speedup, 0.4 for 1.8x speedup, 0.6 for 2.0x speedup, 0.8 for 2.25x speedup See: https://github.com/ali-vilab/TeaCache Supplying any value implies that :py:attr:`RenderLoopConfig.tea_cache` is enabled. This is supported for: ``--model-type flux*``. """ deep_cache: bool = False """ Activate DeepCache for the main model? DeepCache caches intermediate attention layer outputs to speed up the diffusion process. This is beneficial for higher inference steps. See: https://github.com/horseee/DeepCache This is supported for Stable Diffusion, Stable Diffusion XL, Stable Diffusion Upscaler X4, Kolors, and Pix2Pix variants. """ deep_cache_intervals: _types.OptionalIntegers = None """ Cache intervals to try for DeepCache for the main model. Controls how frequently the attention layers are cached during the diffusion process. Lower values cache more frequently, potentially resulting in more speedup but using more memory. This value must be greater than zero. Each value supplied will be tried in turn. This is supported for Stable Diffusion, Stable Diffusion XL, Stable Diffusion Upscaler X4, Kolors, and Pix2Pix variants. Supplying any value implies that :py:attr:`RenderLoopConfig.deep_cache` is enabled. (default: 5) """ deep_cache_branch_ids: _types.OptionalIntegers = None """ Branch IDs to try for DeepCache for the main model. Controls which branches of the UNet attention blocks the caching is applied to. Advanced usage only. This value must be greater than or equal to 0. Each value supplied will be tried in turn. This is supported for Stable Diffusion, Stable Diffusion XL, Stable Diffusion Upscaler X4, Kolors, and Pix2Pix variants. Supplying any value implies that :py:attr:`RenderLoopConfig.deep_cache` is enabled. (default: 1) """ sdxl_refiner_deep_cache: _types.OptionalBoolean = None """ Activate DeepCache for the SDXL Refiner? See: :py:attr:`RenderLoopConfig.deep_cache` This is supported for Stable Diffusion XL and Kolors based models. """ sdxl_refiner_deep_cache_intervals: _types.OptionalIntegers = None """ Cache intervals to try for DeepCache for the SDXL Refiner. Controls how frequently the attention layers are cached during the diffusion process. Lower values cache more frequently, potentially resulting in more speedup but using more memory. This value must be greater than zero. Each value supplied will be tried in turn. This is supported for Stable Diffusion XL and Kolors based models. Supplying any value implies that :py:attr:`RenderLoopConfig.sdxl_refiner_deep_cache` is enabled. (default: 5) """ sdxl_refiner_deep_cache_branch_ids: _types.OptionalIntegers = None """ Branch IDs to try for DeepCache for the SDXL Refiner. Controls which branches of the UNet attention blocks the caching is applied to. Advanced usage only. This value must be greater than or equal to 0. Each value supplied will be tried in turn. This is supported for Stable Diffusion XL and Kolors based models. Supplying any value implies that :py:attr:`RenderLoopConfig.sdxl_refiner_deep_cache` is enabled. (default: 1) """ ras: bool = False """ Activate RAS (Region-Adaptive Sampling) for the primary model? This can increase inference speed with SD3. See: https://github.com/microsoft/ras This is supported for: ``--model-type sd3``. """ ras_index_fusion: _types.OptionalBoolean = None """ Enable index fusion in RAS (Region-Adaptive Sampling) for the primary model? This can improve attention computation in RAS for SD3. See: https://github.com/microsoft/ras Setting to ``True`` implies that :py:attr:`RenderLoopConfig.ras` is enabled. This is supported for: ``--model-type sd3``, (but not for SD3.5 models) """ ras_sample_ratios: _types.OptionalFloats = None """ Sample ratios to try for RAS (Region-Adaptive Sampling). For instance, setting this to 0.5 on a sequence of 4096 tokens will result in the noise of averagely 2048 tokens to be updated during each RAS step. Must be between 0 and 1. Each value will be tried in turn. Supplying any values implies that :py:attr:`RenderLoopConfig.ras` is enabled. This is supported for: ``--model-type sd3``. """ ras_high_ratios: _types.OptionalFloats = None """ High ratios to try for RAS (Region-Adaptive Sampling). Based on the metric selected, the ratio of the high value chosen to be cached. Default value is 1.0, but can be set between 0 and 1 to balance the sample ratio between the main subject and the background. Each value will be tried in turn. Supplying any values implies that :py:attr:`RenderLoopConfig.ras` is enabled. This is supported for: ``--model-type sd3``. """ ras_starvation_scales: _types.OptionalFloats = None """ Starvation scales to try for RAS (Region-Adaptive Sampling). RAS tracks how often a token is dropped and incorporates this count as a scaling factor in the metric for selecting tokens. This scale factor prevents excessive blurring or noise in the final generated image. Larger scaling factor will result in more uniform sampling. Usually set between 0.0 and 1.0. Each value will be tried in turn. Supplying any values implies that :py:attr:`RenderLoopConfig.ras` is enabled. This is supported for: ``--model-type sd3``. """ ras_metrics: _types.OptionalStrings = None """ One or more RAS metrics to try. This controls how RAS measures the importance of tokens for caching. Valid values are "std" (standard deviation) or "l2norm" (L2 norm). Defaults to "std". Each value will be tried in turn. Supplying any values implies that :py:attr:`RenderLoopConfig.ras` is enabled. This is supported for: ``--model-type sd3``. """ ras_error_reset_steps: typing.Optional[collections.abc.Sequence[_types.Integers]] = None """ Error reset step patterns to try for RAS (Region-Adaptive Sampling). The dense sampling steps inserted between the RAS steps to reset the accumulated error. Should be a list of lists of step numbers, e.g. [[12, 22], ...]. Each list will be tried in turn. Supplying any values implies that :py:attr:`RenderLoopConfig.ras` is enabled. This is supported for: ``--model-type sd3``. """ ras_start_steps: _types.OptionalIntegers = None """ Starting steps to try for RAS (Region-Adaptive Sampling). This controls when RAS begins applying its sampling strategy. Must be greater than or equal to 1. Defaults to 4 if not specified. Each value will be tried in turn. Supplying any values implies that :py:attr:`RenderLoopConfig.ras` is enabled. This is supported for: ``--model-type sd3``. """ ras_end_steps: _types.OptionalIntegers = None """ Ending steps to try for RAS (Region-Adaptive Sampling). This controls when RAS stops applying its sampling strategy. Must be greater than or equal to 1. Defaults to the number of inference steps if not specified. Each value will be tried in turn. Supplying any values implies that :py:attr:`RenderLoopConfig.ras` is enabled. This is supported for: ``--model-type sd3``. """ ras_skip_num_steps: _types.OptionalIntegers = None """ Skip steps to try for RAS (Region-Adaptive Sampling). This controls the number of steps to skip between RAS steps. The actual number of tokens skipped will be rounded down to the nearest multiple of 64. This ensures efficient memory access patterns for the attention computation. When used with :py:attr:`RenderLoopConfig.ras_skip_num_step_lengths` > 0, this value determines how much to increase/decrease the number of skipped tokens over time. A positive value will increase the number of skipped tokens, while a negative value will decrease it. Each value will be tried in turn. Supplying any value implies that :py:attr:`RenderLoopConfig.ras` is enabled. This is supported for: ``--model-type sd3``. (default: 0) """ ras_skip_num_step_lengths: _types.OptionalIntegers = None """ Skip step lengths to try for RAS (Region-Adaptive Sampling). This controls the length of steps to skip between RAS steps. Must be greater than or equal to 0. When set to 0, static dropping is used where the same number of tokens are skipped at each step (except for error reset steps and steps before :py:attr:`RenderLoopConfig.ras_start_steps`). When greater than 0, dynamic dropping is used where the number of skipped tokens varies over time based on :py:attr:`RenderLoopConfig.ras_skip_num_steps`. The pattern repeats every :py:attr:`RenderLoopConfig.ras_skip_num_step_lengths` steps. Each value will be tried in turn. Supplying any value implies that :py:attr:`RenderLoopConfig.ras` is enabled. This is supported for: ``--model-type sd3``. (default: 0) """ pag: bool = False """ Use perturbed attention guidance? """ pag_scales: _types.OptionalFloats = None """ List of floating point perturbed attention guidance scales, this corresponds to the ``--pag-scales`` argument of the dgenerate command line tool. """ pag_adaptive_scales: _types.OptionalFloats = None """ List of floating point adaptive perturbed attention guidance scales, this corresponds to the ``--pag-adaptive-scales`` argument of the dgenerate command line tool. """ sdxl_refiner_pag: _types.OptionalBoolean = None """ Use perturbed attention guidance in the SDXL refiner? """ sdxl_refiner_pag_scales: _types.OptionalFloats = None """ List of floating point perturbed attention guidance scales to try with the SDXL refiner, this corresponds to the ``--sdxl-refiner-pag-scales`` argument of the dgenerate command line tool. """ sdxl_refiner_pag_adaptive_scales: _types.OptionalFloats = None """ List of floating point adaptive perturbed attention guidance scales to try with the SDXL refiner, this corresponds to the ``--sdxl-refiner-pag-adaptive-scales`` argument of the dgenerate command line tool. """ second_model_scheduler_uri: _types.OptionalUriOrUris = None """ Optional SDXL Refiner / Stable Cascade Decoder model scheduler/sampler class name specification, this corresponds to the ``--second-model-scheduler`` argument of the dgenerate command line tool. Setting this to 'help' will yield a help message to stdout describing scheduler names compatible with the current configuration upon running. Passing 'helpargs' will yield a help message with a list of overridable arguments for each scheduler and their typical defaults. This may be a list of schedulers, indicating to try each scheduler in turn. """ safety_checker: bool = False """ Enable safety checker? ``--safety-checker`` """ model_type: _pipelinewrapper.ModelType = _pipelinewrapper.ModelType.SD """ Corresponds to the ``--model-type`` argument of the dgenerate command line tool. """ device: _types.Name = _torchutil.default_device() """ Processing device specification, for example "cuda" or "cuda:N" where N is an alternate GPU id as reported by nvidia-smi if you want to specify a specific GPU. This corresponds to the ``--device`` argument of the dgenerate command line tool. The default device on MacOS is "mps". "xpu" is an option for intel GPUs, for which device indices are also supported. """ dtype: _pipelinewrapper.DataType = _pipelinewrapper.DataType.AUTO """ Primary model data type specification, IE: integer precision. Default is auto selection. Lower precision datatypes result in less GPU memory usage. This corresponds to the ``--dtype`` argument of the dgenerate command line tool. """ revision: _types.Name = 'main' """ Repo revision selector for the main model when loading from a huggingface repository. This corresponds to the ``--revision`` argument of the dgenerate command line tool. """ variant: _types.OptionalName = None """ Primary model weights variant string. This corresponds to the ``--variant`` argument of the dgenerate command line tool. """ output_size: _types.OptionalSize = None """ Desired output size, sizes not aligned by 8 pixels will result in an error message. This corresponds to the ``--output-size`` argument of the dgenerate command line tool. """ no_aspect: bool = False """ Should Seed, Mask, and Control guidance images specified in :py:attr:`.RenderLoopConfig.image_seeds` definitions (``--image-seeds``) have their aspect ratio ignored when being resized to :py:attr:`.RenderLoopConfig.output_size` (``--output-size``) ? """ output_path: _types.Path = 'output' """ Render loop write folder, where images and animations will be written. This corresponds to the ``--output-path`` argument of the dgenerate command line tool. """ output_prefix: _types.OptionalString = None """ Output filename prefix, add an optional prefix string to all written files. This corresponds to the ``--output-prefix`` argument of the dgenerate command line tool. """ output_overwrite: bool = False """ Allow overwrites of files? or avoid this with a file suffix in a multiprocess safe manner? This corresponds to the ``--output-overwrite`` argument of the dgenerate command line tool. """ output_configs: bool = False """ Output a config text file next to every generated image or animation? this file will contain configuration that is pipeable to dgenerate stdin, which will reproduce said file. This corresponds to the ``--output-configs`` argument of the dgenerate command line tool. """ output_metadata: bool = False """ Write config text to the metadata of all written images? this data is not written to animated files, only PNGs and JPEGs. This corresponds to the ``--output-metadata`` argument of the dgenerate command line tool. """ output_auto1111_metadata: bool = False """ Write Automatic1111 compatible metadata to the metadata of all written images? this data is not written to animated files, only PNGs and JPEGs. This corresponds to the ``--output-metadata`` argument of the dgenerate command line tool. """ animation_format: _types.Name = 'mp4' """ Format for any rendered animations, see: :py:func:`dgenerate.mediaoutput.supported_animation_writer_formats()`. This value may also be set to 'frames' to indicate that only individual frames should be output and no animation file coalesced. This corresponds to the ``--animation-format`` argument of the dgenerate command line tool. """ image_format: _types.Name = 'png' """ Format for any images that are written including animation frames. Anything other than "png", "jpg", or "jpeg" is not compatible with ``output_metadata=True`` and a :py:exc:`.RenderLoopConfigError` will be raised upon running the render loop if ``output_metadata=True`` and this value is not one of those mentioned formats. """ no_frames: bool = False """ Should individual frames not be output when rendering an animation? defaults to False. This corresponds to the ``--no-frames`` argument of the dgenerate command line tool. Using this option when :py:attr:`RenderLoopConfig.animation_format` is equal to ``"frames"`` will cause a :py:exc:`RenderLoopConfigError` be raised. """ frame_start: _types.Integer = 0 """ Start frame inclusive frame slice for any rendered animations. This corresponds to the ``--frame-start`` argument of the dgenerate command line tool. """ frame_end: _types.OptionalInteger = None """ Optional end frame inclusive frame slice for any rendered animations. This corresponds to the ``--frame-end`` argument of the dgenerate command line tool. """ auth_token: _types.OptionalString = None """ Optional huggingface API token which will allow the download of restricted repositories that your huggingface account has been granted access to. This corresponds to the ``--auth-token`` argument of the dgenerate command line tool. """ seed_image_processors: _types.OptionalUris = None """ Corresponds to the ``--seed-image-processors`` argument of the dgenerate command line tool verbatim. """ mask_image_processors: _types.OptionalUris = None """ Corresponds to the ``--mask-image-processors`` argument of the dgenerate command line tool verbatim. """ control_image_processors: _types.OptionalUris = None """ Corresponds to the ``--control-image-processors`` argument of the dgenerate command line tool verbatim, including the grouping syntax using the "+" symbol, the plus symbol should be used as its own list element, IE: it is a token. """ post_processors: _types.OptionalUris = None """ Corresponds to the ``--post-processors`` argument of the dgenerate command line tool verbatim. """ offline_mode: bool = False """ Avoid ever connecting to the internet to download anything? this can be used if all your models / media are cached or if you are only ever using resources that exist on disk already. Corresponds to the ``--offline-mode`` argument of the dgenerate command line tool. """ model_cpu_offload: bool = False """ Force model cpu offloading for the main pipeline, this may reduce memory consumption and allow large models to run when they would otherwise not fit in your GPUs VRAM. Inference will be slower. Mutually exclusive with :py:attr:`RenderLoopConfig.model_sequential_offload` """ model_sequential_offload: bool = False """ Force sequential model offloading for the main pipeline, this may drastically reduce memory consumption and allow large models to run when they would otherwise not fit in your GPUs VRAM. Inference will be much slower. Mutually exclusive with :py:attr:`RenderLoopConfig.model_cpu_offload` """ second_model_cpu_offload: _types.OptionalBoolean = None """ Force model cpu offloading for the SDXL refiner or Stable Cascade decoder pipeline, this may reduce memory consumption and allow large models to run when they would otherwise not fit in your GPUs VRAM. Inference will be slower. Mutually exclusive with :py:attr:`RenderLoopConfig.second_model_sequential_offload` """ second_model_sequential_offload: _types.OptionalBoolean = None """ Force sequential model offloading for the SDXL refiner or Stable Cascade decoder pipeline, this may drastically reduce memory consumption and allow large models to run when they would otherwise not fit in your GPUs VRAM. Inference will be much slower. Mutually exclusive with :py:attr:`RenderLoopConfig.second_model_cpu_offload` """ adetailer_class_filter: _types.OptionalIntegersAndStringsBag = None """ A collection of class IDs and/or class names that indicates what YOLO detection classes to keep. This filter is applied before index-filter. Detections that don't match any of the specified classes will be ignored. Integers are treated as ID's, strings are treated as names. """ adetailer_index_filter: _types.OptionalIntegersBag = None """ A list index values that indicates what YOLO detection indices to keep, the index values start at zero. Detections are sorted by their top left bounding box coordinate from left to right, top to bottom, by (confidence descending). The order of detections in the image is identical to the reading order of words on a page (english). Inpainting will only be performed on the specified detection indices, if no indices are specified, then inpainting will be performed on all detections. This filter is applied after class-filter. """ adetailer_detector_uris: _types.OptionalUris = None """ One or more adetailer YOLO detector model URIs. Corresponds directly to --adetailer-detectors. Specification of this argument enables the adetailer inpainting algorithm and requires the use of :py:attr:`.RenderLoopConfig.image_seeds` """ adetailer_model_masks: _types.OptionalBoolean = None """ Indicates that masks generated by the model itself should be preferred over masks generated from the detection bounding box. If this is ``True``, and the model itself returns mask data, :py:attr:`.RenderLoopConfig.adetailer_mask_shape`, :py:attr:`.RenderLoopConfig.adetailer_mask_padding`, and :py:attr:`.RenderLoopConfig.adetailer_detector_padding` will all be ignored. """ adetailer_mask_shapes: _types.OptionalNames = None """ One or more adetailer mask shapes to try. This indicates what mask shape adetailer should attempt to draw around a detected feature, the default value is "rectangle". You may also specify "circle" to generate an ellipsoid shaped mask, which might be helpful for achieving better blending. Valid values are: ("r", "rect", "rectangle"), or ("c", "circle", "ellipse") """ adetailer_detector_paddings: _types.OptionalPaddings = None """ One or more adetailer detector padding values. This value specifies the amount of padding that will be added to the detection rectangle which is used to generate a masked area. The default is 0, you can make the mask area around the detected feature larger with positive padding and smaller with negative padding. Example: 32 (32px Uniform, all sides) (10, 20) (10px Horizontal, 20px Vertical) (10, 20, 30, 40) (10px Left, 20px Top, 30px Right, 40px Bottom) Defaults to [0]. """ adetailer_mask_paddings: _types.OptionalPaddings = None """ One or more adetailer mask padding values. This value indicates how much padding to place around the masked area when cropping out the image to be inpainted, this value must be large enough to accommodate any feathering on the edge of the mask caused by :py:attr:`.RenderLoopConfig.adetailer_mask_blurs` or :py:attr:`.RenderLoopConfig.adetailer_mask_dilations` for the best result. Example: 32 (32px Uniform, all sides) (10, 20) (10px Horizontal, 20px Vertical) (10, 20, 30, 40) (10px Left, 20px Top, 30px Right, 40px Bottom) Defaults to [32]. """ adetailer_mask_blurs: _types.OptionalIntegers = None """ Indicates the level of gaussian blur to apply to the inpaint mask generated by adetailer, which can help with smooth blending of the inpainted feature. Defaults to [4]. """ adetailer_mask_dilations: _types.OptionalIntegers = None """ Indicates the amount of dilation applied to the generated adetailer inpaint mask, see: cv2.dilate. Defaults to [4]. """ adetailer_sizes: _types.OptionalIntegers = None """ One or more target sizes for processing detected areas. When specified, detected areas will always be scaled to this target size (with aspect ratio preserved) for processing, then scaled back to the original size for compositing. This can significantly improve detail quality for small detected features like faces or hands, or reduce processing time for overly large detected areas. The scaling is based on the larger dimension (width or height) of the detected area. The optimal resampling method is automatically selected for both upscaling and downscaling. Each value must be an integer greater than 1. Defaults to none (process at native resolution). """ adetailer_crop_control_image: _types.OptionalBoolean = None """ Should adetailer crop any control image the same way that it crops the mask? This is only relevant when using adetailer with ControlNet models. When enabled, control images will be cropped to match the detected region before being passed to the inpainting pipeline. This can help ensure that the control guidance is properly aligned with the area being inpainted. When disabled (default), control images will be resized to match the cropped region size without cropping. This corresponds to the ``--adetailer-crop-control-image`` argument of the dgenerate command line tool. """ inpaint_crop: bool = False """ Enable cropping to mask bounds for inpainting. When enabled, input images will be automatically cropped to the bounds of their masks (plus any padding) before processing, then the generated result will be pasted back onto the original uncropped image. This allows inpainting at higher effective resolutions for better quality results. Note: Inpaint crop cannot be used with multiple input images. Each image/mask pair must be processed individually for optimal cropping, as different masks may have different bounds. However, ``batch_size`` > 1 is supported for generating multiple variations of a single crop. This corresponds to the ``--inpaint-crop`` argument of the dgenerate command line tool. """ inpaint_crop_paddings: _types.OptionalPaddings = None """ One or more padding values to use around mask bounds for inpaint cropping. Each value will be tried in turn (combinatorial). Specifying this automatically enables :py:attr:`RenderLoopConfig.inpaint_crop`. Padding can be specified as: - A single integer (e.g., 32) for uniform padding on all sides - "WIDTHxHEIGHT" format (e.g., "10x20") for horizontal and vertical padding - "LEFTxTOPxRIGHTxBOTTOM" format (e.g., "5x10x5x15") for specific side padding This corresponds to the ``--inpaint-crop-paddings`` argument of the dgenerate command line tool. """ inpaint_crop_masked: bool = False """ Use the mask when pasting the generated result back onto the original image for inpaint cropping. Specifying this automatically enables :py:attr:`RenderLoopConfig.inpaint_crop`. This means only the masked areas will be replaced. Cannot be used together with :py:attr:`RenderLoopConfig.inpaint_crop_feathers`. This corresponds to the ``--inpaint-crop-masked`` argument of the dgenerate command line tool. """ inpaint_crop_feathers: _types.OptionalIntegers = None """ One or more feather values to use when pasting the generated result back onto the original image for inpaint cropping. Specifying this automatically enables :py:attr:`RenderLoopConfig.inpaint_crop`. Each value will be tried in turn (combinatorial). Feathering creates smooth transitions from opaque to transparent. Cannot be used together with :py:attr:`RenderLoopConfig.inpaint_crop_masked`. This corresponds to the ``--inpaint-crop-feathers`` argument of the dgenerate command line tool. """ latents: _types.OptionalTensors = None """ Optional list of tensors containing noisy latents to use as starting points for diffusion. These latents can be generated by using --denoising-end with --image-format pt/pth/safetensors to save intermediate noisy latents from a previous generation. This allows for advanced workflows where you can pass partially denoised latents between different models or generation stages. """ latents_processors: _types.OptionalUris = None """ One or more latents processor URI strings for processing raw input latents before pipeline execution. These processors are applied to latents provided through the :py:attr:`RenderLoopConfig.latents` argument (raw latents used as noise initialization). The processors are applied in sequence before the latents are passed to the diffusion pipeline. This corresponds to the ``--latents-processors`` argument of the dgenerate command line tool. """ latents_post_processors: _types.OptionalUris = None """ One or more latents processor URI strings for processing output latents when outputting to latents. These processors are applied to latents when :py:attr:`RenderLoopConfig.image_format` is set to a tensor format (pt, pth, safetensors). The processors are applied in sequence after the diffusion pipeline generates the latents but before they are returned in the result. This corresponds to the ``--latents-post-processors`` argument of the dgenerate command line tool. """ img2img_latents_processors: _types.OptionalUris = None """ One or more latents processor URI strings for processing img2img latents before pipeline execution. These processors are applied to latent tensors provided through the :py:attr:`RenderLoopConfig.image_seeds` argument when doing img2img with tensor inputs. The processors are applied in sequence and may occur before VAE decoding (for models that decode img2img latents) or before direct pipeline usage. This corresponds to the ``--img2img-latents-processors`` argument of the dgenerate command line tool. """ denoising_start: _types.OptionalFloat = None """ Denoising should start at this fraction of total timesteps (0.0 to 1.0). This is useful continuing denoising on noisy latents generated with :py:attr:`RenderLoopConfig.denoising_end` Scheduler Compatibility: * SD 1.5 models: Only stateless schedulers are supported (``EulerDiscreteScheduler``, ``LMSDiscreteScheduler``, ``EDMEulerScheduler``, ``DPMSolverMultistepScheduler``, ``DDIMScheduler``, ``DDPMScheduler``, ``PNDMScheduler``) * SDXL models: All schedulers supported via native denoising_start/denoising_end * SD3/Flux models: FlowMatchEulerDiscreteScheduler and standard schedulers supported This corresponds to the ``--denoising-start`` argument of the dgenerate command line tool. """ denoising_end: _types.OptionalFloat = None """ Denoising should end at this fraction of total timesteps (0.0 to 1.0). This is useful for generating noisy latents that can be saved and passed to other models. Scheduler Compatibility: * SD 1.5 models: Only stateless schedulers are supported (``EulerDiscreteScheduler``, ``LMSDiscreteScheduler``, ``EDMEulerScheduler``, ``DPMSolverMultistepScheduler``, ``DDIMScheduler``, ``DDPMScheduler``, ``PNDMScheduler``) * SDXL models: All schedulers supported via native denoising_start/denoising_end * SD3/Flux models: FlowMatchEulerDiscreteScheduler and standard schedulers supported This corresponds to the ``--denoising-end`` argument of the dgenerate command line tool. """
[docs] def __init__(self): self.guidance_scales = [_pipelinewrapper.constants.DEFAULT_GUIDANCE_SCALE] self.inference_steps = [_pipelinewrapper.constants.DEFAULT_INFERENCE_STEPS] self.prompts = [_prompt.Prompt()] self.seeds = gen_seeds(1)
def _check(self, attribute_namer: typing.Optional[typing.Callable[[str], str]] = None): """ Check the configuration for type and logical usage errors, set defaults for certain values when needed and not specified. This may modify the configuration. :param attribute_namer: Callable for naming attributes mentioned in exception messages """ # Create attribute namer function for consistent error reporting a_namer = self._create_attribute_namer(attribute_namer) # Validate basic type constraints self._validate_type_constraints(a_namer) # Setup help mode and validate help-related arguments help_mode = self._check_help_arguments(a_namer) # Check model-specific optimization features self._check_optimization_features(a_namer) # Check second model arguments compatibility self._check_second_model_compatibility(a_namer) # Check configuration files compatibility self._check_configuration_files_compatibility(a_namer) # Check adetailer compatibility self._check_adetailer_compatibility(a_namer) # Check inpaint crop compatibility self._check_inpaint_crop_compatibility(a_namer) # Check image seeds requirements for certain model types self._check_image_seeds_requirements(a_namer, help_mode) # Check output-related arguments self._check_output_arguments(a_namer) # Configure PAG defaults if needed self._configure_pag_defaults() # Check prompt weighters self._check_prompt_weighters(a_namer) # Check other general compatibility issues self._check_general_compatibility(a_namer) # Check model-specific requirements and restrictions self._check_model_specific_requirements(a_namer) # Process image seeds if present self._process_image_seeds(a_namer, help_mode) def _create_attribute_namer(self, attribute_namer: typing.Optional[typing.Callable[[str], str]]) -> typing.Callable[ [str], str]: """Create a function to standardize attribute naming in error messages.""" def a_namer(attr_name: str) -> str: if attribute_namer: return attribute_namer(attr_name) return f'{self.__class__.__name__}.{attr_name}' return a_namer def _validate_type_constraints(self, a_namer: typing.Callable[[str], str]): """Validate type constraints on configuration attributes.""" try: _types.type_check_struct(self, a_namer) except ValueError as e: raise RenderLoopConfigError(e) from e def _check_help_arguments(self, a_namer: typing.Callable[[str], str]) -> bool: """Check help-related arguments for validity.""" schedulers = [self.scheduler_uri] if \ isinstance(self.scheduler_uri, (_types.Uri, type(None))) else self.scheduler_uri scheduler_help = any(_pipelinewrapper.scheduler_is_help(s) for s in schedulers) second_model_schedulers = [self.second_model_scheduler_uri] if \ isinstance(self.second_model_scheduler_uri, (_types.Uri, type(None))) else self.second_model_scheduler_uri second_model_scheduler_help = any(_pipelinewrapper.scheduler_is_help(s) for s in second_model_schedulers) text_encoder_help = _pipelinewrapper.text_encoder_is_help(self.text_encoder_uris) second_model_text_encoder_help = _pipelinewrapper.text_encoder_is_help(self.second_model_text_encoder_uris) help_mode = scheduler_help or \ second_model_scheduler_help or \ text_encoder_help or \ second_model_text_encoder_help if scheduler_help and len(schedulers) > 1: raise RenderLoopConfigError( f'You cannot specify "help" or "helpargs" to {a_namer("scheduler")} ' f'with multiple values involved.' ) if second_model_scheduler_help and len(second_model_schedulers) > 1: raise RenderLoopConfigError( f'You cannot specify "help" or "helpargs" to {a_namer("second_model_scheduler_uri")} ' f'with multiple values involved.' ) if text_encoder_help and len(self.text_encoder_uris) > 1: raise RenderLoopConfigError( f'You cannot specify "help" or "helpargs" to {a_namer("text_encoder_uris")} ' f'with multiple values involved.' ) if second_model_text_encoder_help and len(self.second_model_text_encoder_uris) > 1: raise RenderLoopConfigError( f'You cannot specify "help" or "helpargs" to {a_namer("second_model_text_encoder_uris")} ' f'with multiple values involved.' ) return help_mode def _check_optimization_features(self, a_namer: typing.Callable[[str], str]): """Check optimization features compatibility with the selected model type.""" if self.quantizer_map and not self.quantizer_uri: raise RenderLoopConfigError( f'{a_namer("quantizer_map")} cannot be used without {a_namer("quantizer_uri")}' ) if self.second_model_quantizer_map and not self.second_model_quantizer_uri: raise RenderLoopConfigError( f'{a_namer("second_model_quantizer_map")} cannot be ' f'used without {a_namer("second_model_quantizer_uri")}' ) # Check TeaCache compatibility tea_cache_enabled = (self.tea_cache or any(self._non_null_attr_that_start_with('tea_cache_'))) if tea_cache_enabled and not _pipelinewrapper.model_type_is_flux(self.model_type): raise RenderLoopConfigError( f'{a_namer("tea_cache")} and related arguments are only ' f'compatible with {a_namer("model_type")} flux*' ) if tea_cache_enabled and self.model_cpu_offload: raise RenderLoopConfigError( f'{a_namer("model_cpu_offload")} is not compatible ' f'with {a_namer("tea_cache")} and related arguments.' ) # Check RAS compatibility ras_enabled = (self.ras or any(self._non_null_attr_that_start_with('ras_'))) if ras_enabled and not _pipelinewrapper.model_type_is_sd3(self.model_type): raise RenderLoopConfigError( f'{a_namer("ras")} and related arguments are only ' f'compatible with {a_namer("model_type")} sd3' ) if ras_enabled and self.model_cpu_offload: raise RenderLoopConfigError( f'{a_namer("model_cpu_offload")} is not compatible ' f'with {a_namer("ras")} and related arguments.' ) if self.ras_index_fusion and self.model_sequential_offload: raise RenderLoopConfigError( f'{a_namer("ras_index_fusion")} is not compatible ' f'with {a_namer("model_sequential_offload")}.' ) if self.ras_index_fusion and ( self.quantizer_uri or (self.unet_uri and _pipelinewrapper.UNetUri.parse(self.unet_uri).quantizer) ): raise RenderLoopConfigError( f'{a_namer("ras_index_fusion")} is not supported for RAS when UNet quantization is enabled, ' f'quantize the text encoders individually using {a_namer("text_encoder_uris")}') if self.hi_diffusion: if not ( self.model_type == _pipelinewrapper.ModelType.SDXL or self.model_type == _pipelinewrapper.ModelType.KOLORS or self.model_type == _pipelinewrapper.ModelType.SD): raise RenderLoopConfigError( f'{a_namer("hi_diffusion")} is only supported for ' f'Stable Diffusion, Stable Diffusion XL, and Kolors' ) if self.t2i_adapter_uris: raise RenderLoopConfigError( f'{a_namer("hi_diffusion")} is not supported with {a_namer("t2i_adapter_uris")}' ) else: if self.hi_diffusion_no_win_attn is not None: raise RenderLoopConfigError( f'{a_namer("hi_diffusion_no_win_attn")} is only supported when {a_namer("hi_diffusion")} is enabled.' ) if self.hi_diffusion_no_raunet is not None: raise RenderLoopConfigError( f'{a_namer("hi_diffusion_no_raunet")} is only supported when {a_namer("hi_diffusion")} is enabled.' ) # Check DeepCache compatibility first (needed for SADA validation) deep_cache_enabled = (self.deep_cache or any(self._non_null_attr_that_start_with('deep_cache_'))) # Check SADA compatibility sada_enabled = (self.sada or any(self._non_null_attr_that_start_with('sada_'))) if sada_enabled and not ( self.model_type == _pipelinewrapper.ModelType.SD or self.model_type == _pipelinewrapper.ModelType.SDXL or self.model_type == _pipelinewrapper.ModelType.KOLORS or _pipelinewrapper.model_type_is_flux(self.model_type)): raise RenderLoopConfigError( f'SADA arguments are only supported for ' f'--model-type sd, sdxl, kolors, and flux*' ) if sada_enabled and tea_cache_enabled: raise RenderLoopConfigError( f'SADA cannot be used simultaneously with {a_namer("tea_cache")} and related arguments.' ) if sada_enabled and deep_cache_enabled: raise RenderLoopConfigError( f'SADA cannot be used simultaneously with {a_namer("deep_cache")} and related arguments.' ) if sada_enabled and self.hi_diffusion: raise RenderLoopConfigError( f'SADA cannot be used simultaneously with {a_namer("hi_diffusion")}' ) # Validate SADA Lagrangian interpolation parameters if sada_enabled and self.sada_lagrange_terms and any(term != 0 for term in self.sada_lagrange_terms): if not self.sada_lagrange_ints or not self.sada_lagrange_steps: raise RenderLoopConfigError( f'When using SADA Lagrangian interpolation ({a_namer("sada_lagrange_terms")} != 0), ' f'both {a_namer("sada_lagrange_ints")} and {a_namer("sada_lagrange_steps")} must be specified' ) # Check compatibility for each combination for lagrange_int in self.sada_lagrange_ints or []: for lagrange_step in self.sada_lagrange_steps or []: if lagrange_step % lagrange_int != 0: raise RenderLoopConfigError( f'SADA {a_namer("sada_lagrange_steps")} ({lagrange_step}) must be ' f'divisible by {a_namer("sada_lagrange_ints")} ({lagrange_int})' ) # Set up SADA defaults when any SADA argument is used if sada_enabled: # Get model-specific defaults sada_defaults = _pipelinewrapper_util.get_sada_model_defaults(self.model_type) if self.sada_max_downsamples is None: self.sada_max_downsamples = [sada_defaults['max_downsample']] if self.sada_sxs is None: self.sada_sxs = [sada_defaults['sx']] if self.sada_sys is None: self.sada_sys = [sada_defaults['sy']] if self.sada_acc_ranges is None: self.sada_acc_ranges = [sada_defaults['acc_range']] if self.sada_lagrange_terms is None: self.sada_lagrange_terms = [sada_defaults['lagrange_term']] if self.sada_lagrange_ints is None: self.sada_lagrange_ints = [sada_defaults['lagrange_int']] if self.sada_lagrange_steps is None: self.sada_lagrange_steps = [sada_defaults['lagrange_step']] if self.sada_max_fixes is None: self.sada_max_fixes = [sada_defaults['max_fix']] if self.sada_max_intervals is None: self.sada_max_intervals = [sada_defaults['max_interval']] if deep_cache_enabled and not ( self.model_type == _pipelinewrapper.ModelType.SDXL or self.model_type == _pipelinewrapper.ModelType.SDXL_PIX2PIX or self.model_type == _pipelinewrapper.ModelType.KOLORS or self.model_type == _pipelinewrapper.ModelType.SD or self.model_type == _pipelinewrapper.ModelType.PIX2PIX or self.model_type == _pipelinewrapper.ModelType.UPSCALER_X4): raise RenderLoopConfigError( f'{a_namer("deep_cache")} and related arguments are only ' f'supported with Stable Diffusion, Stable Diffusion XL, ' f'Stable Diffusion Upscaler X4, Kolors, and Pix2Pix variants.' ) # Check FreeU compatibility if self.freeu_params is not None: freeu_model_types = { _pipelinewrapper.ModelType.SD, _pipelinewrapper.ModelType.SDXL, _pipelinewrapper.ModelType.KOLORS, _pipelinewrapper.ModelType.PIX2PIX, _pipelinewrapper.ModelType.SDXL_PIX2PIX, _pipelinewrapper.ModelType.UPSCALER_X2, _pipelinewrapper.ModelType.UPSCALER_X4 } if self.model_type not in freeu_model_types: raise RenderLoopConfigError( f'{a_namer("freeu_params")} not supported with ' f'{a_namer("model_type")} {_pipelinewrapper.get_model_type_string(self.model_type)}.' ) def _check_second_model_compatibility(self, a_namer: typing.Callable[[str], str]): """Check compatibility of second model arguments with the primary model type.""" # Check if second model arguments are valid for the primary model type if not (_pipelinewrapper.model_type_is_sdxl(self.model_type) or _pipelinewrapper.model_type_is_kolors(self.model_type) or _pipelinewrapper.model_type_is_s_cascade(self.model_type)): errors = [] for arg in self._non_null_second_model_arguments(): errors.append( f'Cannot use {a_namer(arg)} with ' f'{a_namer("model_type")} ' f'{_pipelinewrapper.get_model_type_string(self.model_type)}' ) if errors: raise RenderLoopConfigError('\n'.join(errors)) # Check if second model scheduler and text encoder are valid if not self.sdxl_refiner_uri and not self.s_cascade_decoder_uri: if self.second_model_scheduler_uri: raise RenderLoopConfigError( f'Cannot use {a_namer("second_model_scheduler_uri")} if {a_namer("sdxl_refiner_uri")} ' f'or {a_namer("s_cascade_decoder_uri")} is not specified.') if self.second_model_text_encoder_uris: raise RenderLoopConfigError( f'Cannot use {a_namer("second_model_text_encoder_uris")} if {a_namer("sdxl_refiner_uri")} ' f'or {a_namer("s_cascade_decoder_uri")} is not specified.') def _check_configuration_files_compatibility(self, a_namer: typing.Callable[[str], str]): """Check compatibility of configuration files with model types.""" # Check original config compatibility if not _hfhub.is_single_file_model_load(self.model_path): if self.original_config: raise RenderLoopConfigError( f'You cannot specify {a_namer("original_config")} when the main ' f'model is not a a single file checkpoint.' ) # Check second model original config compatibility if self.second_model_original_config: if not self.sdxl_refiner_uri and not self.s_cascade_decoder_uri: raise RenderLoopConfigError( f'You cannot specify {a_namer("second_model_original_config")} ' f'without {a_namer("sdxl_refiner_uri")} or {a_namer("s_cascade_decoder_uri")}.' ) if self.sdxl_refiner_uri and \ not _hfhub.is_single_file_model_load( _pipelinewrapper.uris.SDXLRefinerUri.parse(self.sdxl_refiner_uri).model): raise RenderLoopConfigError( f'You cannot specify {a_namer("second_model_original_config")} ' f'when the {a_namer("sdxl_refiner_uri")} model is not a ' f'single file checkpoint.' ) if self.s_cascade_decoder_uri and \ not _hfhub.is_single_file_model_load( _pipelinewrapper.uris.SCascadeDecoderUri.parse(self.s_cascade_decoder_uri).model): raise RenderLoopConfigError( f'You cannot specify {a_namer("second_model_original_config")} ' f'when the {a_namer("s_cascade_decoder_uri")} model is not a ' f'single file checkpoint.' ) def _check_adetailer_compatibility(self, a_namer: typing.Callable[[str], str]): """Check compatibility of ADetailer-related arguments.""" adetailer_args_used = list(self._non_null_attr_that_start_with('adetailer')) if not self.adetailer_detector_uris and adetailer_args_used: bad_adetailer_args = _textprocessing.oxford_comma( [a_namer(a) for a in adetailer_args_used if a != "adetailer_detector_uris"], "or") raise RenderLoopConfigError( f'May not use {bad_adetailer_args} without {a_namer("adetailer_detector_uris")}.') if self.adetailer_detector_uris and self.model_type not in { _pipelinewrapper.ModelType.SD, _pipelinewrapper.ModelType.SDXL, _pipelinewrapper.ModelType.KOLORS, _pipelinewrapper.ModelType.SD3, _pipelinewrapper.ModelType.FLUX, _pipelinewrapper.ModelType.FLUX_FILL }: raise RenderLoopConfigError( f'{a_namer("adetailer_detector_uris")} is only compatible with ' f'{a_namer("model_type")} sd, sdxl, kolors, sd3, and flux') if self.adetailer_detector_uris and self.is_output_latents(): raise RenderLoopConfigError( f'Outputting latents with {a_namer("image_format")} {self.image_format} ' f'is not supported with {a_namer("adetailer_detector_uris")}' ) if self.adetailer_mask_shapes: for shape in self.adetailer_mask_shapes: try: parsed_shape = _textprocessing.parse_basic_mask_shape(shape) except ValueError: parsed_shape = None if parsed_shape is None or parsed_shape not in { _textprocessing.BasicMaskShape.RECTANGLE, _textprocessing.BasicMaskShape.ELLIPSE }: raise RenderLoopConfigError( f'Unknown {"adetailer_mask_shapes"} value: {shape}') def _check_inpaint_crop_compatibility(self, a_namer: typing.Callable[[str], str]): """Check compatibility of inpaint crop arguments.""" # Automatically enable inpaint crop if padding, feathering, or masking is specified if not self.inpaint_crop and ( self.inpaint_crop_paddings or self.inpaint_crop_feathers or self.inpaint_crop_masked): self.inpaint_crop = True if self.inpaint_crop and self.no_aspect: raise RenderLoopConfigError( f'{a_namer("inpaint_crop")} is not compatible with {a_namer("no_aspect")}' ) # Check if inpaint crop is used without mask inputs if self.inpaint_crop and not self.image_seeds: raise RenderLoopConfigError( f'{a_namer("inpaint_crop")} requires {a_namer("image_seeds")} to be specified ' f'with mask images for inpainting.') # Check mutual exclusivity of masked and feathered modes if self.inpaint_crop_masked and self.inpaint_crop_feathers: raise RenderLoopConfigError( f'{a_namer("inpaint_crop_masked")} and {a_namer("inpaint_crop_feathers")} ' f'are mutually exclusive options.') # Check compatibility with latent output if self.inpaint_crop and self.is_output_latents(): raise RenderLoopConfigError( f'Outputting latents with {a_namer("image_format")} {self.image_format} ' f'is not supported with {a_namer("inpaint_crop")}') # Set default padding when inpaint crop is enabled but no padding/feathering specified if self.inpaint_crop and not self.inpaint_crop_paddings and not self.inpaint_crop_feathers: self.inpaint_crop_paddings = [_pipelinewrapper.constants.DEFAULT_INPAINT_CROP_PADDING] def _check_image_seeds_requirements(self, a_namer: typing.Callable[[str], str], help_mode: bool): """Verify requirements for image seeds based on model type.""" if not self.image_seeds: args_help = help_mode # Check if model type requires image seeds if _pipelinewrapper.model_type_is_floyd_ifs(self.model_type) and not args_help: raise RenderLoopConfigError( f'you cannot specify Deep Floyd IF super-resolution ' f'({a_namer("model_type")} "{self.model_type})" without {a_namer("image_seeds")}' ) if _pipelinewrapper.model_type_is_upscaler(self.model_type) and not args_help: raise RenderLoopConfigError( f'you cannot specify an upscaler model ' f'({a_namer("model_type")} "{self.model_type})" without {a_namer("image_seeds")}.' ) if _pipelinewrapper.model_type_is_pix2pix(self.model_type) and not args_help: raise RenderLoopConfigError( f'you cannot specify a pix2pix model ' f'({a_namer("model_type")} "{self.model_type})" without {a_namer("image_seeds")}.' ) if self.model_type == _pipelinewrapper.ModelType.FLUX_FILL: raise RenderLoopConfigError( f'you cannot use {a_namer("model_type")} ' f'flux-fill without {a_namer("image_seeds")}.' ) # Check arguments that require image seeds if self.adetailer_detector_uris: raise RenderLoopConfigError( f'You cannot specify {a_namer("adetailer_detector_uris")} ' f'without {a_namer("image_seeds")}.' ) if self.image_seed_strengths: raise RenderLoopConfigError( f'you cannot specify {a_namer("image_seed_strengths")} ' f'without {a_namer("image_seeds")}.') if self.seeds_to_images: raise RenderLoopConfigError( f'{a_namer("seeds_to_images")} cannot be specified ' f'without {a_namer("image_seeds")}.') if self.controlnet_uris: raise RenderLoopConfigError( f'you cannot specify {a_namer("controlnet_uris")} ' f'without {a_namer("image_seeds")}.') if self.t2i_adapter_uris: raise RenderLoopConfigError( f'you cannot specify {a_namer("t2i_adapter_uris")} ' f'without {a_namer("image_seeds")}.') if self.ip_adapter_uris: raise RenderLoopConfigError( f'you cannot specify {a_namer("ip_adapter_uris")} ' f'without {a_namer("image_seeds")}.') # Check image processor arguments without image seeds invalid_self = [] for processor_self in self._non_null_attr_that_end_with('image_processors'): invalid_self.append( f'you cannot specify {a_namer(processor_self)} ' f'without {a_namer("image_seeds")}.') # check for latents processors without any possible latents input for processor_self in self._non_null_attr_that_end_with('latents_processors'): invalid_self.append( f'you cannot specify {a_namer(processor_self)} ' f'without {a_namer("image_seeds")}.') if invalid_self: raise RenderLoopConfigError('\n'.join(invalid_self)) # Check pipeline class compatibility try: _pipelinewrapper.get_pipeline_class( model_type=self.model_type, pipeline_type=_pipelinewrapper.PipelineType.TXT2IMG, unet_uri=self.unet_uri, transformer_uri=self.transformer_uri, vae_uri=self.vae_uri, lora_uris=self.lora_uris, image_encoder_uri=self.image_encoder_uri, ip_adapter_uris=self.ip_adapter_uris, textual_inversion_uris=self.textual_inversion_uris, controlnet_uris=self.controlnet_uris, t2i_adapter_uris=self.t2i_adapter_uris, pag=self.pag, help_mode=help_mode ) except _pipelinewrapper.UnsupportedPipelineConfigError as e: raise RenderLoopConfigError(str(e)) from e def _check_output_arguments(self, a_namer: typing.Callable[[str], str]): """Check output-related arguments for compatibility.""" # Check output prefix if self.output_prefix: if '/' in self.output_prefix or '\\' in self.output_prefix: raise RenderLoopConfigError( f'{a_namer("output_prefix")} value may not contain slash characters.') # Check frame start/end if self.frame_end is not None and self.frame_start > self.frame_end: raise RenderLoopConfigError( f'{a_namer("frame_start")} must be less than or equal to {a_namer("frame_end")}') # Clean and validate animation and image formats self.animation_format = self.animation_format.strip().lower() self.image_format = self.image_format.strip().lower() if self.animation_format not in _mediaoutput.get_supported_animation_writer_formats() + ['frames']: raise RenderLoopConfigError( f'Unsupported {a_namer("animation_format")} value "{self.animation_format}". Must be one of ' f'{_textprocessing.oxford_comma(_mediaoutput.get_supported_animation_writer_formats(), "or")}') # Check if it's a supported image format or tensor format supported_image_formats = _mediaoutput.get_supported_static_image_formats() supported_tensor_formats = _mediaoutput.get_supported_tensor_formats() all_supported_formats = supported_image_formats + supported_tensor_formats if self.image_format not in all_supported_formats: raise RenderLoopConfigError( f'Unsupported {a_namer("image_format")} value "{self.image_format}". Must be one of ' f'{_textprocessing.oxford_comma(all_supported_formats, "or")}') if self.output_metadata and self.output_auto1111_metadata: raise RenderLoopConfigError( f'{a_namer("output_metadata")} and {a_namer("output_auto1111_metadata")} ' f'are mutually exclusive and cannot be used simultaneously.') # Only check metadata compatibility for actual image formats, not tensor formats if not self.is_output_latents(): if self.latents_post_processors: raise RenderLoopConfigError( f'Cannot specify {a_namer("latents_post_processors")} when {a_namer("image_format")} is not a ' f'tensor format such as: ' f'{_textprocessing.oxford_comma(_mediainput.get_supported_tensor_formats(), "or")}' ) if self.image_format not in {"png", "jpg", "jpeg"}: if self.output_metadata or self.output_auto1111_metadata: prop_name = 'output_metadata' if self.output_metadata else 'output_auto1111_metadata' raise RenderLoopConfigError( f'{a_namer("image_format")} value "{self.image_format}" is ' f'unsupported when {a_namer(prop_name)} is enabled. ' f'Only "png", "jpg", and "jpeg" formats are supported with {a_namer(prop_name)}.') # Tensor formats don't support metadata if self.is_output_latents() and (self.output_metadata or self.output_auto1111_metadata): prop_name = 'output_metadata' if self.output_metadata else 'output_auto1111_metadata' raise RenderLoopConfigError( f'{a_namer(prop_name)} is not supported when outputting latents. ' f'Tensor formats ({", ".join(_mediaoutput.get_supported_tensor_formats())}) do not support metadata.') if self.animation_format == 'frames' and self.no_frames: raise RenderLoopConfigError( f'Cannot specify {a_namer("no_frames")} when {a_namer("animation_format")} is set to "frames"') def _configure_pag_defaults(self): """Configure PAG default values if needed.""" if self.pag: if not (self.pag_scales or self.pag_adaptive_scales): self.pag_scales = [_pipelinewrapper.constants.DEFAULT_PAG_SCALE] self.pag_adaptive_scales = [_pipelinewrapper.constants.DEFAULT_PAG_ADAPTIVE_SCALE] if self.sdxl_refiner_pag and self.sdxl_refiner_uri: if not (self.sdxl_refiner_pag_scales or self.sdxl_refiner_pag_adaptive_scales): self.sdxl_refiner_pag_scales = [_pipelinewrapper.constants.DEFAULT_SDXL_REFINER_PAG_SCALE] self.sdxl_refiner_pag_adaptive_scales = [ _pipelinewrapper.constants.DEFAULT_SDXL_REFINER_PAG_ADAPTIVE_SCALE] def _check_prompt_weighters(self, a_namer: typing.Callable[[str], str]): """Check prompt weighter compatibility.""" if self.prompt_weighter_uri is not None \ and not _promptweighters.prompt_weighter_exists(self.prompt_weighter_uri): raise RenderLoopConfigError( f'Unknown prompt weighter implementation: {_promptweighters.prompt_weighter_name_from_uri(self.prompt_weighter_uri)}, ' f'must be one of: {_textprocessing.oxford_comma(_promptweighters.prompt_weighter_names(), "or")}') if self.second_model_prompt_weighter_uri is not None \ and not _promptweighters.prompt_weighter_exists(self.second_model_prompt_weighter_uri): raise RenderLoopConfigError( f'Unknown prompt weighter implementation for secondary model: ' f'{_promptweighters.prompt_weighter_name_from_uri(self.prompt_weighter_uri)}, ' f'must be one of: {_textprocessing.oxford_comma(_promptweighters.prompt_weighter_names(), "or")}') def _check_general_compatibility(self, a_namer: typing.Callable[[str], str]): """Check general configuration compatibility.""" # Check T2I adapter factors if self.sdxl_t2i_adapter_factors and not self.t2i_adapter_uris: raise RenderLoopConfigError( f'You may not specify {a_namer("sdxl_t2i_adapter_factors")} ' f'without {a_namer("t2i_adapter_uris")}.') # Check data type supported_dtypes = _pipelinewrapper.supported_data_type_strings() if self.dtype not in _pipelinewrapper.supported_data_type_enums(): raise RenderLoopConfigError( f'{a_namer("dtype")} must be {_textprocessing.oxford_comma(supported_dtypes, "or")}') # Check batch size if self.batch_size is not None and self.batch_size < 1: raise RenderLoopConfigError( f'{a_namer("batch_size")} must be greater than or equal to 1.') # Check model type if self.model_type not in _pipelinewrapper.supported_model_type_enums(): supported_model_types = _textprocessing.oxford_comma(_pipelinewrapper.supported_model_type_strings(), "or") raise RenderLoopConfigError( f'{a_namer("model_type")} must be one of: {supported_model_types}') # Check device if not _torchutil.is_valid_device_string(self.device): raise RenderLoopConfigError( f'{a_namer("device")} {_torchutil.invalid_device_message(self.device, cap=False)}') # Check model offload options if self.model_cpu_offload and self.model_sequential_offload: raise RenderLoopConfigError( f'{a_namer("model_cpu_offload")} and {a_namer("model_sequential_offload")} ' f'may not be enabled simultaneously.') if self.second_model_cpu_offload and self.second_model_sequential_offload: raise RenderLoopConfigError( f'{a_namer("second_model_cpu_offload")} and {a_namer("second_model_sequential_offload")} ' f'may not be enabled simultaneously.') # Check model path is specified if self.model_path is None: raise RenderLoopConfigError( f'{a_namer("model_path")} must be specified') # Check clip skip compatibility if self.clip_skips: if ( self.model_type != _pipelinewrapper.ModelType.SD and self.model_type != _pipelinewrapper.ModelType.SDXL and self.model_type != _pipelinewrapper.ModelType.SD3 and self.model_type != _pipelinewrapper.ModelType.SD3_PIX2PIX and self.prompt_weighter_uri is None ): # prompt weighter may be able to handle clip skips # when the pipeline cannot, such is the case for StableCascade raise RenderLoopConfigError( f'you cannot specify {a_namer("clip_skips")} for ' f'{a_namer("model_type")} values other than ' f'"sd", "sdxl", or "sd3" when a ' f'{a_namer("prompt_weighter_uri")} is not specified.') # Check tensor output compatibility with batch grid if self.batch_grid_size is not None and self.is_output_latents(): raise RenderLoopConfigError( f'{a_namer("batch_grid_size")} cannot be used with latents output formats ' f'(pt, pth, safetensors). Image grids can only be created from decoded images, ' f'not raw latents tensors. Use a standard image format such as "png" or "jpg" instead.') def _check_model_specific_requirements(self, a_namer: typing.Callable[[str], str]): """Check specific requirements for different model types.""" self._check_stable_cascade_requirements(a_namer) self._check_upscaler_requirements(a_namer) self._check_pix2pix_requirements(a_namer) self._check_transformer_compatibility(a_namer) self._check_flux_model_requirements(a_namer) self._check_sd3_model_requirements(a_namer) self._check_sdxl_model_requirements(a_namer) self._check_floyd_requirements(a_namer) def _check_floyd_requirements(self, a_namer: typing.Callable[[str], str]): """Check Floyd model specific requirements.""" if _pipelinewrapper.model_type_is_floyd(self.model_type): if self.is_output_latents(): raise RenderLoopConfigError( f'Outputting latents with {a_namer("image_format")} {self.image_format} ' f'is not supported with Deep Floyd model types.' ) def _check_stable_cascade_requirements(self, a_namer: typing.Callable[[str], str]): """Check Stable Cascade specific requirements.""" if self.model_type == _pipelinewrapper.ModelType.S_CASCADE_DECODER: raise RenderLoopConfigError( f'Stable Cascade decoder {a_namer("model_type")} may not be used as the primary model.') if self.model_type == _pipelinewrapper.ModelType.S_CASCADE: if self.hi_diffusion: raise RenderLoopConfigError( f'{a_namer("hi_diffusion")} is not supported with Stable Cascade.' ) if not self.second_model_guidance_scales: self.second_model_guidance_scales = [ _pipelinewrapper.constants.DEFAULT_S_CASCADE_DECODER_GUIDANCE_SCALE] if not self.second_model_inference_steps: self.second_model_inference_steps = [ _pipelinewrapper.constants.DEFAULT_S_CASCADE_DECODER_INFERENCE_STEPS] if self.output_size is not None and not _image.is_aligned(self.output_size, 128): raise RenderLoopConfigError( f'Stable Cascade requires {a_namer("output_size")} to be aligned by 128.') elif self.s_cascade_decoder_uri: raise RenderLoopConfigError( f'{a_namer("s_cascade_decoder_uri")} may only be used with "s-cascade"') def _check_upscaler_requirements(self, a_namer: typing.Callable[[str], str]) -> bool: """ Check upscaler model specific requirements. Returns: Whether upscaler noise levels default was set """ upscaler_noise_levels_default_set = False if not _pipelinewrapper.model_type_is_upscaler(self.model_type) \ and not _pipelinewrapper.model_type_is_floyd_ifs(self.model_type): if self.upscaler_noise_levels: raise RenderLoopConfigError( f'you cannot specify {a_namer("upscaler_noise_levels")} for a ' f'non upscaler model type, see: {a_namer("model_type")}.') elif self.upscaler_noise_levels is None: if self.model_type == _pipelinewrapper.ModelType.UPSCALER_X4: upscaler_noise_levels_default_set = True self.upscaler_noise_levels = [_pipelinewrapper.constants.DEFAULT_X4_UPSCALER_NOISE_LEVEL] elif self.model_type != _pipelinewrapper.ModelType.UPSCALER_X4 and \ not _pipelinewrapper.model_type_is_floyd_ifs(self.model_type): raise RenderLoopConfigError( f'you cannot specify {a_namer("upscaler_noise_levels")} for an upscaler ' f'model type that is not "upscaler-x4" or "ifs-*", ' f'see: {a_namer("model_type")}.') return upscaler_noise_levels_default_set def _check_pix2pix_requirements(self, a_namer: typing.Callable[[str], str]): """Check pix2pix model specific requirements.""" if not _pipelinewrapper.model_type_is_pix2pix(self.model_type): if self.image_guidance_scales: raise RenderLoopConfigError( f'argument {a_namer("image_guidance_scales")} only valid with ' f'pix2pix models, see: {a_namer("model_type")}.') elif not self.image_guidance_scales: self.image_guidance_scales = [_pipelinewrapper.constants.DEFAULT_IMAGE_GUIDANCE_SCALE] def _check_transformer_compatibility(self, a_namer: typing.Callable[[str], str]): """Check transformer compatibility with the model type.""" if self.transformer_uri: if not _pipelinewrapper.model_type_is_sd3(self.model_type) \ and not _pipelinewrapper.model_type_is_flux(self.model_type): raise _pipelinewrapper.UnsupportedPipelineConfigError( f'{a_namer("transformer_uri")} is only supported for ' f'{a_namer("model_type")} sd3 and flux.') def _check_flux_model_requirements(self, a_namer: typing.Callable[[str], str]): """Check Flux model specific requirements.""" if not _pipelinewrapper.model_type_is_flux(self.model_type): invalid_self = [] for flux_self in self._non_null_attr_that_start_with('flux'): invalid_self.append(f'you cannot specify {a_namer(flux_self)} ' f'for a non Flux model type, see: {a_namer("model_type")}.') if invalid_self: raise RenderLoopConfigError('\n'.join(invalid_self)) else: if self.hi_diffusion: raise RenderLoopConfigError( f'{a_namer("hi_diffusion")} is not supported with Flux.' ) if self.max_sequence_length is not None: if self.max_sequence_length < 1 or self.max_sequence_length > 512: raise RenderLoopConfigError( f'{a_namer("max_sequence_length")} must be greater than or equal ' f'to 1 and less than or equal to 512.' ) def _check_sd3_model_requirements(self, a_namer: typing.Callable[[str], str]): """Check SD3 model specific requirements.""" if not _pipelinewrapper.model_type_is_sd3(self.model_type): invalid_self = [] for sd3_self in self._non_null_attr_that_start_with('sd3'): invalid_self.append(f'you cannot specify {a_namer(sd3_self)} ' f'for a non SD3 model type, see: {a_namer("model_type")}.') if invalid_self: raise RenderLoopConfigError('\n'.join(invalid_self)) else: if self.hi_diffusion: raise RenderLoopConfigError( f'{a_namer("hi_diffusion")} is not supported with Stable Diffusion 3.' ) if self.max_sequence_length is not None: if self.controlnet_uris: raise RenderLoopConfigError( f'{a_namer("max_sequence_length")} is not supported when ' f'{a_namer("controlnet_uris")} is specified.') if self.max_sequence_length < 1 or self.max_sequence_length > 512: raise RenderLoopConfigError( f'{a_namer("max_sequence_length")} must be greater than or equal ' f'to 1 and less than or equal to 512.' ) if self.output_size is not None: if not _image.is_aligned(self.output_size, 16): raise RenderLoopConfigError( f'Stable Diffusion 3 requires {a_namer("output_size")} to be aligned to 16.') if self.unet_uri or self.second_model_unet_uri: raise RenderLoopConfigError( f'Stable Diffusion 3 does not support the ' f'use of {a_namer("unet_uri")}/{a_namer("second_model_unet_uri")}.') def _check_sdxl_model_requirements(self, a_namer: typing.Callable[[str], str]): """Check SDXL model specific requirements.""" # Check if we're using an SDXL or Kolors model is_sdxl_model = (_pipelinewrapper.model_type_is_sdxl(self.model_type) or _pipelinewrapper.model_type_is_kolors(self.model_type)) if not is_sdxl_model: # Not an SDXL model, check for incompatible arguments invalid_self = [] for sdxl_self in self._non_null_attr_that_start_with('sdxl'): invalid_self.append(f'you cannot specify {a_namer(sdxl_self)} ' f'for a non SDXL model type, see: {a_namer("model_type")}.') if invalid_self: raise RenderLoopConfigError('\n'.join(invalid_self)) # Clear high noise fractions since it's not applicable self.sdxl_high_noise_fractions = None return # We have an SDXL or Kolors model, check refiner compatibility if not self.sdxl_refiner_uri: # No refiner specified, check for incompatible refiner-specific arguments invalid_self = [] for sdxl_self in self._non_null_second_model_arguments('sdxl_refiner'): invalid_self.append( f'you cannot specify {a_namer(sdxl_self)} ' f'without {a_namer("sdxl_refiner_uri")}.') # High noise fractions require a refiner if self.sdxl_high_noise_fractions is not None: invalid_self.append( f'you cannot specify {a_namer("sdxl_high_noise_fractions")} ' f'without {a_namer("sdxl_refiner_uri")}.') if invalid_self: raise RenderLoopConfigError('\n'.join(invalid_self)) else: # Refiner is specified, set default high noise fraction if needed if self.sdxl_high_noise_fractions is None: self.sdxl_high_noise_fractions = [_pipelinewrapper.constants.DEFAULT_SDXL_HIGH_NOISE_FRACTION] def _process_image_seeds(self, a_namer: typing.Callable[[str], str], help_mode: bool): """Process image seeds and verify compatibility.""" if not self.image_seeds: return # Check if model type supports image seed strength no_seed_strength = (_pipelinewrapper.model_type_is_upscaler(self.model_type) or _pipelinewrapper.model_type_is_pix2pix(self.model_type) or _pipelinewrapper.model_type_is_s_cascade(self.model_type) or self.model_type == _pipelinewrapper.ModelType.FLUX_FILL or self.model_type == _pipelinewrapper.ModelType.FLUX_KONTEXT) # Set default image seed strength if needed image_seed_strengths_default_set = False user_provided_image_seed_strengths = False if self.image_seed_strengths is None: if not no_seed_strength: image_seed_strengths_default_set = True self.image_seed_strengths = [_pipelinewrapper.constants.DEFAULT_IMAGE_SEED_STRENGTH] else: if no_seed_strength: raise RenderLoopConfigError( f'{a_namer("image_seed_strengths")} ' f'cannot be used with pix2pix, upscaler, stablecascade, flux-fill, or flux-kontext models.') user_provided_image_seed_strengths = True # Check upscaler noise level default setting upscaler_noise_levels_default_set = self._check_upscaler_requirements(a_namer) # Parse and validate each image seed URI parsed_image_seeds = [] for uri in self.image_seeds: parsed_image_seeds.append( self._check_image_seed_uri( uri=uri, attribute_namer=a_namer, image_seed_strengths_default_set=image_seed_strengths_default_set, upscaler_noise_levels_default_set=upscaler_noise_levels_default_set)) # Verify pipeline compatibility self._verify_pipeline_compatibility( parsed_image_seeds=parsed_image_seeds, help_mode=help_mode, a_namer=a_namer ) # Check for additional compatibility issues self._check_adetailer_mask_compatibility( parsed_image_seeds=parsed_image_seeds, a_namer=a_namer ) self._check_image_input_compatibility( parsed_image_seeds=parsed_image_seeds, image_seed_strengths_default_set=image_seed_strengths_default_set, user_provided_image_seed_strengths=user_provided_image_seed_strengths, a_namer=a_namer ) # Store parsed image seeds self.parsed_image_seeds = parsed_image_seeds def _verify_pipeline_compatibility(self, parsed_image_seeds: typing.List[_mediainput.ImageSeedParseResult], help_mode: bool, a_namer: typing.Callable[[str], str]): """Verify that a pipeline can be built for the given configuration.""" try: for image_seed in parsed_image_seeds: is_control_guidance_spec = \ (self.controlnet_uris or self.t2i_adapter_uris) and image_seed.is_single_spec if image_seed.images and (self.adetailer_detector_uris or image_seed.mask_images): pipeline_type = _pipelinewrapper.PipelineType.INPAINT elif image_seed.images and not is_control_guidance_spec: pipeline_type = _pipelinewrapper.PipelineType.IMG2IMG else: pipeline_type = _pipelinewrapper.PipelineType.TXT2IMG # Check if a class can handle the operation _pipelinewrapper.get_pipeline_class( model_type=self.model_type, pipeline_type=pipeline_type, unet_uri=self.unet_uri, transformer_uri=self.transformer_uri, vae_uri=self.vae_uri, lora_uris=self.lora_uris, image_encoder_uri=self.image_encoder_uri, ip_adapter_uris=self.ip_adapter_uris, textual_inversion_uris=self.textual_inversion_uris, controlnet_uris=self.controlnet_uris, t2i_adapter_uris=self.t2i_adapter_uris, pag=self.pag, help_mode=help_mode ) except _pipelinewrapper.UnsupportedPipelineConfigError as e: raise RenderLoopConfigError(str(e)) from e def _check_adetailer_mask_compatibility(self, parsed_image_seeds: typing.List[_mediainput.ImageSeedParseResult], a_namer: typing.Callable[[str], str]): """Check that adetailer is not used with manual inpaint masks.""" if self.adetailer_detector_uris and any(p.mask_images is not None for p in parsed_image_seeds): raise RenderLoopConfigError( f'Cannot specify inpaint masks when using {a_namer("adetailer_detector_uris")}, inpaint masks ' f'are generated automatically with this option.' ) def _check_image_input_compatibility(self, parsed_image_seeds: typing.List[_mediainput.ImageSeedParseResult], image_seed_strengths_default_set: bool, user_provided_image_seed_strengths: bool, a_namer: typing.Callable[[str], str]): """Check compatibility of image inputs with model type and settings.""" # Check if no images are provided for img2img if all(p.images is None for p in parsed_image_seeds): if image_seed_strengths_default_set: self.image_seed_strengths = None elif self.image_seed_strengths: raise RenderLoopConfigError( f'{a_namer("image_seed_strengths")} ' f'cannot be used unless an img2img operation exists ' f'in at least one {a_namer("image_seeds")} definition.') # Check flux-fill compatibility if not all(p.mask_images is not None for p in parsed_image_seeds): if self.model_type == _pipelinewrapper.ModelType.FLUX_FILL \ and not self.adetailer_detector_uris: raise RenderLoopConfigError( f'Only inpainting {a_namer("image_seeds")} ' f'definitions can be used with {a_namer("model_type")} flux-fill.') # Check non-inpainting mode compatibility if all(p.mask_images is None for p in parsed_image_seeds): if self.model_type == _pipelinewrapper.ModelType.IFS: self.image_seed_strengths = None if user_provided_image_seed_strengths: raise RenderLoopConfigError( f'{a_namer("image_seed_strengths")} ' f'cannot be used with {a_namer("model_type")} ifs ' f'when no inpainting is taking place in any image seed ' f'specification.') if self.inpaint_crop: raise RenderLoopConfigError( f'All image seeds must be inpainting ' f'definitions when {a_namer("inpaint_crop")} or related arguments are used.' ) # Check batching compatibility if self.inpaint_crop: for image_seed in parsed_image_seeds: if ((image_seed.images is not None and len(list(image_seed.images)) > 1) or (image_seed.mask_images is not None and len(list(image_seed.mask_images)) > 1)): raise RenderLoopConfigError( f'Inpaint batching via {a_namer("image_seeds")} batching syntax is ' f'not supported with {a_namer("inpaint_crop")}, but you may ' f'use {a_namer("batch_size")}') def _check_image_seed_uri(self, uri: str, attribute_namer: typing.Callable[[str], str], image_seed_strengths_default_set: bool, upscaler_noise_levels_default_set: bool) -> _mediainput.ImageSeedParseResult: """ Check image seed URI for compatibility with the current configuration. :param uri: The URI to check :param attribute_namer: Function to name attributes in error messages :param image_seed_strengths_default_set: Whether check() has set an image_seed_strengths default value :param upscaler_noise_levels_default_set: Whether check() has set an upscaler_noise_levels default value :return: Parsed image seed result """ a_namer = attribute_namer try: parsed = _mediainput.parse_image_seed_uri(uri) except _mediainput.ImageSeedError as e: raise RenderLoopConfigError(e) from e mask_part = 'mask=my-mask.png;' if parsed.mask_images else '' # ^ Used for nice messages about image seed keyword argument misuse # Check model-specific image seed requirements self._check_model_specific_image_seed_requirements( parsed=parsed, uri=uri, a_namer=a_namer ) # Check adapter image compatibility self._check_adapter_image_compatibility( parsed=parsed, uri=uri, a_namer=a_namer ) # Check image processor compatibility self._check_image_processor_compatibility( parsed=parsed, uri=uri, a_namer=a_namer ) # Check latents processor compatibility self._check_latents_processor_compatibility( parsed=parsed, uri=uri, a_namer=a_namer ) # Check adapter compatibility self._check_adapter_compatibility( parsed=parsed, uri=uri, a_namer=a_namer ) # Check control guidance compatibility self._check_control_guidance_compatibility( parsed=parsed, uri=uri, a_namer=a_namer, image_seed_strengths_default_set=image_seed_strengths_default_set, upscaler_noise_levels_default_set=upscaler_noise_levels_default_set ) # Check deep floyd compatibility self._check_floyd_compatibility( parsed=parsed, uri=uri, a_namer=a_namer, mask_part=mask_part ) return parsed def _check_model_specific_image_seed_requirements(self, parsed: _mediainput.ImageSeedParseResult, uri: str, a_namer: typing.Callable[[str], str]): """Check model-specific requirements for image seeds.""" if _pipelinewrapper.model_type_is_s_cascade(self.model_type): if not parsed.is_single_spec: raise RenderLoopConfigError( f'{a_namer("image_seeds")} configurations other than plain ' f'img2img are not supported for Stable Cascade.') if _pipelinewrapper.model_type_is_upscaler(self.model_type): if not parsed.is_single_spec: raise RenderLoopConfigError( f'{a_namer("image_seeds")} configurations other than plain ' f'img2img are not supported for Stable Diffusion upscaler models.') if _pipelinewrapper.model_type_is_sdxl(self.model_type): if self.denoising_start is not None and self.denoising_start != 0.0: if not parsed.images: raise RenderLoopConfigError( f'{a_namer("denoising_start")} may not be used with SDXL and an ' f'{a_namer("image_seeds")} URI that does not contain an img2img image source, ' f'if you are trying to refine latents, pass them in as a normal img2img definition.') def _check_adapter_image_compatibility(self, parsed: _mediainput.ImageSeedParseResult, uri: str, a_namer: typing.Callable[[str], str]): """Check compatibility of adapter images with IP adapters.""" if parsed.adapter_images: if not self.ip_adapter_uris: raise RenderLoopConfigError( f'You may not use IP Adapter images in your {a_namer("image_seeds")} specification ' f'without specifying {a_namer("ip_adapter_uris")}.') number_of_ip_adapter_image_groups = len(parsed.adapter_images) number_of_ip_adapter_uris = len(self.ip_adapter_uris) if len(parsed.adapter_images) != number_of_ip_adapter_uris: raise RenderLoopConfigError( f'The amount of IP Adapter image groups in your {a_namer("image_seeds")} specification "{uri}" ' f'must equal the number of {a_namer("ip_adapter_uris")} supplied. You have supplied ' f'{number_of_ip_adapter_image_groups} IP Adapter image groups for {number_of_ip_adapter_uris} IP ' f'Adapter models.') def _check_latents_processor_compatibility(self, parsed: _mediainput.ImageSeedParseResult, uri: str, a_namer: typing.Callable[[str], str]): if self.img2img_latents_processors: if not any(_mediainput.is_tensor_file(i) for i in parsed.images): raise RenderLoopConfigError( f'Your {a_namer("image_seeds")} specification "{uri}" does not ' f'contain any tensor file (latents) img2img inputs, therefore ' f'{a_namer("img2img_latents_processors")} cannot be used.' ) num_img2img_latents = len(parsed.images) if parsed.images is not None else 0 latents_processor_chain_count = \ (sum(1 for p in self.img2img_latents_processors if p == _pipelinewrapper.constants.LATENTS_PROCESSOR_SEP) + 1) if latents_processor_chain_count > num_img2img_latents: raise RenderLoopConfigError( f'Your {a_namer("image_seeds")} specification "{uri}" defines {num_img2img_latents} ' f'tensor file (latents) img2img image sources, and you have specified {latents_processor_chain_count} ' f'{a_namer("img2img_latents_processors")} actions / action chains. The amount of processors ' f'must not exceed the amount of inputs.' ) if self.latents_processors: if not parsed.latents: raise RenderLoopConfigError( f'Your {a_namer("image_seeds")} specification "{uri}" does not ' f'contain any raw latents tensor file inputs, therefore ' f'{a_namer("img2img_latents_processors")} cannot be used.' ) num_latents = len(parsed.latents) if parsed.latents is not None else 0 latents_processor_chain_count = \ (sum(1 for p in self.latents_processors if p == _pipelinewrapper.constants.LATENTS_PROCESSOR_SEP) + 1) if latents_processor_chain_count > num_latents: raise RenderLoopConfigError( f'Your {a_namer("image_seeds")} specification "{uri}" defines {num_latents} ' f'tensor file (raw latents) inputs, and you have specified {latents_processor_chain_count} ' f'{a_namer("latents_processors")} actions / action chains. The amount of processors ' f'must not exceed the amount of inputs.' ) def _check_image_processor_compatibility(self, parsed: _mediainput.ImageSeedParseResult, uri: str, a_namer: typing.Callable[[str], str]): """Check compatibility of image processors with available images.""" if self.seed_image_processors: num_img2img_images = len(parsed.images) if parsed.images is not None else 0 seed_processor_chain_count = \ (sum(1 for p in self.seed_image_processors if p == IMAGE_PROCESSOR_SEP) + 1) if seed_processor_chain_count > num_img2img_images: raise RenderLoopConfigError( f'Your {a_namer("image_seeds")} specification "{uri}" defines {num_img2img_images} ' f'img2img image sources, and you have specified {seed_processor_chain_count} ' f'{a_namer("seed_image_processors")} actions / action chains. The amount of processors ' f'must not exceed the amount of img2img images.' ) if self.mask_image_processors: num_mask_images = len(parsed.mask_images) if parsed.mask_images is not None else 0 mask_processor_chain_count = \ (sum(1 for p in self.mask_image_processors if p == IMAGE_PROCESSOR_SEP) + 1) if mask_processor_chain_count > num_mask_images: raise RenderLoopConfigError( f'Your {a_namer("image_seeds")} specification "{uri}" defines {num_mask_images} ' f'inpaint mask image sources, and you have specified {mask_processor_chain_count} ' f'{a_namer("mask_image_processors")} actions / action chains. The amount of processors ' f'must not exceed the amount of inpaint mask images.' ) def _check_adapter_compatibility(self, parsed: _mediainput.ImageSeedParseResult, uri: str, a_namer: typing.Callable[[str], str]): """Check T2I adapter or ControlNet compatibility with the image seeds.""" control_image_paths = parsed.get_control_image_paths() num_control_images = len(control_image_paths) if control_image_paths is not None else 0 if self.t2i_adapter_uris: if not parsed.is_single_spec: raise RenderLoopConfigError( f'You may not use img2img or inpainting in your {a_namer("image_seeds")} specification ' f'when using {a_namer("t2i_adapter_uris")} as it is not supported.') if num_control_images != len(self.t2i_adapter_uris): raise RenderLoopConfigError( f'Your {a_namer("image_seeds")} specification "{uri}" defines {num_control_images} ' f'control guidance image sources, and you have specified {len(self.t2i_adapter_uris)} ' f'{a_namer("t2i_adapter_uris")} URIs. The amount of guidance image sources and the ' f'amount of T2I Adapter models must be equal.' ) elif self.controlnet_uris: if not parsed.is_single_spec and parsed.control_images is None: images_str = ', '.join(parsed.images) raise RenderLoopConfigError( f'You must specify a control image with the control argument ' f'IE: "my-seed.png;control=my-control.png" in your ' f'{a_namer("image_seeds")} "{uri}" when using {a_namer("controlnet_uris")} ' f'in order to use inpainting. If you want to use the control image alone ' f'without a mask, use {a_namer("image_seeds")} "{images_str}".') if control_image_paths is None: raise RenderLoopConfigError( f'You must specify controlnet guidance images in your {a_namer("image_seeds")} ' f'specification "{uri}" (for example: "img2img;mask=my-mask.png;control=control1.png, control2.png") ' f'when using {a_namer("controlnet_uris")}' ) if num_control_images != len(self.controlnet_uris): raise RenderLoopConfigError( f'Your {a_namer("image_seeds")} specification "{uri}" defines {num_control_images} ' f'control guidance image sources, and you have specified {len(self.controlnet_uris)} ' f'{a_namer("controlnet_uris")} URIs. The amount of guidance image sources and the ' f'amount of ControlNet models must be equal.' ) if self.control_image_processors: control_processor_chain_count = \ (sum(1 for p in self.control_image_processors if p == IMAGE_PROCESSOR_SEP) + 1) if control_processor_chain_count > num_control_images: raise RenderLoopConfigError( f'Your {a_namer("image_seeds")} specification "{uri}" defines {num_control_images} ' f'control guidance image sources, and you have specified {control_processor_chain_count} ' f'{a_namer("control_image_processors")} actions / action chains. The amount of processors ' f'must not exceed the amount of control guidance images.' ) def _check_control_guidance_compatibility(self, parsed: _mediainput.ImageSeedParseResult, uri: str, a_namer: typing.Callable[[str], str], image_seed_strengths_default_set: bool, upscaler_noise_levels_default_set: bool): """Check control guidance compatibility.""" is_control_guidance_spec = (self.controlnet_uris or self.t2i_adapter_uris) and parsed.is_single_spec has_additional_control = parsed.control_images and not parsed.is_single_spec if has_additional_control and not self.controlnet_uris: raise RenderLoopConfigError( f'Cannot use the "control" argument in an image seed without ' f'specifying {a_namer("controlnet_uris")}.' ) if is_control_guidance_spec and self.image_seed_strengths: if image_seed_strengths_default_set: # check() set this default that isn't valid # upon further parsing self.image_seed_strengths = None else: # user set this raise RenderLoopConfigError( f'Cannot use {a_namer("image_seed_strengths")} with a control guidance image ' f'specification "{uri}". IE: when {a_namer("controlnet_uris")} is specified and ' f'your {a_namer("image_seeds")} specification has a single source or comma ' f'separated list of sources.') if is_control_guidance_spec and self.upscaler_noise_levels: # upscaler noise level should already be handled but handle it again just incase if upscaler_noise_levels_default_set: # check() set this default that isn't valid # upon further parsing self.upscaler_noise_levels = None else: # user set this raise RenderLoopConfigError( f'Cannot use {a_namer("upscaler_noise_levels")} with a control guidance image ' f'specification "{uri}". IE: when {a_namer("controlnet_uris")} is specified and ' f'your {a_namer("image_seeds")} specification has a single source or comma ' f'separated list of sources.') def _check_floyd_compatibility(self, parsed: _mediainput.ImageSeedParseResult, uri: str, a_namer: typing.Callable[[str], str], mask_part: str): """Check compatibility with Deep Floyd IF models.""" if self.model_type == _pipelinewrapper.ModelType.IFS_IMG2IMG or \ (parsed.mask_images and _pipelinewrapper.model_type_is_floyd_ifs(self.model_type)): if not parsed.floyd_image: raise RenderLoopConfigError( f'You must specify a floyd image with the floyd argument ' f'IE: "my-seed.png;{mask_part}floyd=previous-stage-image.png" ' f'in your {a_namer("image_seeds")} "{uri}" to disambiguate this ' f'usage of Deep Floyd IF super-resolution.') def _normalized_schedulers(self) -> typing.Tuple[ typing.List[typing.Optional[_types.Uri]], typing.List[typing.Optional[_types.Uri]]]: """ Return normalized lists of schedulers and second model schedulers. Returns: A tuple containing two lists: (schedulers, second_model_schedulers) """ schedulers = self.scheduler_uri second_model_schedulers = self.second_model_scheduler_uri if isinstance(schedulers, (_types.Uri, type(None))): schedulers = [schedulers] if isinstance(second_model_schedulers, (_types.Uri, type(None))): second_model_schedulers = [second_model_schedulers] return schedulers, second_model_schedulers
[docs] def check(self, attribute_namer: typing.Optional[typing.Callable[[str], str]] = None): """ Check the configuration for type and logical usage errors, set defaults for certain values when needed and not specified. This may modify the configuration. :param attribute_namer: Callable for naming attributes mentioned in exception messages """ try: self._check(attribute_namer) except (_pipelinewrapper.InvalidModelUriError, _mediainput.ImageSeedParseError) as e: raise RenderLoopConfigError(e) from e
[docs] def calculate_generation_steps(self) -> int: """ Calculate the number of generation steps that this configuration results in. This factors in diffusion parameter combinations as well as scheduler combinations. :return: int """ optional_factors = [ self.second_model_prompts, self.second_model_second_prompts, self.second_prompts, self.third_prompts, self.image_guidance_scales, self.image_seeds, self.image_seed_strengths, self.sdxl_t2i_adapter_factors, self.clip_skips, self.sdxl_refiner_clip_skips, self.upscaler_noise_levels, self.guidance_rescales, self.freeu_params, self.sdxl_refiner_freeu_params, self.sdxl_high_noise_fractions, self.sdxl_aesthetic_scores, self.sdxl_original_sizes, self.sdxl_target_sizes, self.sdxl_crops_coords_top_left, self.sdxl_negative_aesthetic_scores, self.sdxl_negative_original_sizes, self.sdxl_negative_target_sizes, self.sdxl_negative_crops_coords_top_left, self.sdxl_refiner_aesthetic_scores, self.sdxl_refiner_original_sizes, self.sdxl_refiner_target_sizes, self.sdxl_refiner_crops_coords_top_left, self.sdxl_refiner_negative_aesthetic_scores, self.sdxl_refiner_negative_original_sizes, self.sdxl_refiner_negative_target_sizes, self.sdxl_refiner_negative_crops_coords_top_left, self.pag_scales, self.pag_adaptive_scales, self.sdxl_refiner_pag_scales, self.sdxl_refiner_pag_adaptive_scales, self.second_model_inference_steps, self.second_model_guidance_scales, self.sdxl_refiner_guidance_rescales, self.adetailer_mask_shapes, self.adetailer_detector_paddings, self.adetailer_mask_paddings, self.adetailer_mask_blurs, self.adetailer_mask_dilations, self.adetailer_sizes, self.tea_cache_rel_l1_thresholds, self.ras_error_reset_steps, self.ras_high_ratios, self.ras_sample_ratios, self.ras_starvation_scales, self.ras_metrics, self.ras_start_steps, self.ras_end_steps, self.ras_skip_num_steps, self.ras_skip_num_step_lengths, self.deep_cache_intervals, self.deep_cache_branch_ids, self.sdxl_refiner_deep_cache_intervals, self.sdxl_refiner_deep_cache_branch_ids, self.sigmas, self.sdxl_refiner_sigmas, self.sada_max_downsamples, self.sada_sxs, self.sada_sys, self.sada_acc_ranges, self.sada_lagrange_terms, self.sada_lagrange_ints, self.sada_lagrange_steps, self.sada_max_fixes, self.sada_max_intervals ] schedulers, second_model_schedulers = self._normalized_schedulers() product = 1 for lst in optional_factors: product *= max(0 if lst is None else len(lst), 1) return (product * len(self.prompts) * (len(self.seeds) if not self.seeds_to_images else 1) * len(self.guidance_scales) * len(self.inference_steps) * len(schedulers) * len(second_model_schedulers))
[docs] def copy(self) -> 'RenderLoopConfig': """ Create a deep copy of this :py:class:`RenderLoopConfig` instance. :return: :py:class:`RenderLoopConfig` instance that is a deep copy of this instance. """ new_config = RenderLoopConfig() for attr_name, attr_value in self.__dict__.items(): if isinstance(attr_value, (list, tuple, dict, set)): new_config.__dict__[attr_name] = _types.partial_deep_copy_container(attr_value) elif hasattr(attr_value, 'copy') and callable(getattr(attr_value, 'copy')): new_config.__dict__[attr_name] = attr_value.copy() else: new_config.__dict__[attr_name] = attr_value return new_config
[docs] def apply_prompt_upscalers(self): """ Apply requested prompt upscaling operations to all prompts in the configuration. This potentially modifies the configuration in place, specifically the prompt arguments. :raises dgenerate.promptupscalers.PromptUpscalerNotFoundError: :raises dgenerate.promptupscalers.PromptUpscalerArgumentError: :raises dgenerate.promptupscalers.PromptUpscalerProcessingError: """ def upscale_prompts(prompts, default_upscaler_uri): return _promptupscalers.upscale_prompts( prompts=prompts, default_upscaler_uri=default_upscaler_uri, device=self.device, local_files_only=self.offline_mode ) self.prompts = upscale_prompts(self.prompts, self.prompt_upscaler_uri) if self.second_prompts: self.second_prompts = upscale_prompts( self.second_prompts, _types.default( self.second_prompt_upscaler_uri, self.prompt_upscaler_uri)) if self.third_prompts: self.third_prompts = upscale_prompts( self.third_prompts, _types.default( self.third_prompt_upscaler_uri, self.prompt_upscaler_uri)) if self.second_model_prompts: self.second_model_prompts = upscale_prompts( self.second_model_prompts, _types.default( self.second_model_prompt_upscaler_uri, self.prompt_upscaler_uri)) if self.second_model_second_prompts: self.second_model_second_prompts = upscale_prompts( self.second_model_second_prompts, _types.default( self.second_model_second_prompt_upscaler_uri, self.prompt_upscaler_uri))
[docs] def iterate_diffusion_args(self, **overrides) -> collections.abc.Iterator[_pipelinewrapper.DiffusionArguments]: """ Iterate over :py:class:`dgenerate.pipelinewrapper.DiffusionArguments` argument objects using every combination of argument values provided for that object by this configuration. :param overrides: use key word arguments to override specific attributes of this object with a new list value. :return: an iterator over :py:class:`dgenerate.pipelinewrapper.DiffusionArguments` """ def ov(n: str, v: typing.Any) -> typing.Optional[typing.List[typing.Any]]: if not hasattr(_pipelinewrapper.DiffusionArguments, n): # fat-fingered an argument name too many times :) raise AssertionError( f'dgenerate.pipelinewrapper.DiffusionArguments lacks property: {n}') if not ( _pipelinewrapper.model_type_is_sdxl(self.model_type) or _pipelinewrapper.model_type_is_kolors(self.model_type)): if n.startswith('sdxl_'): return None else: if n.startswith('sdxl_refiner_') and not self.sdxl_refiner_uri: return None if not _pipelinewrapper.model_type_is_sd3(self.model_type): if n.startswith('sd3_'): return None if not _pipelinewrapper.model_type_is_flux(self.model_type): if n.startswith('flux_'): return None if not self.adetailer_detector_uris: if n.startswith('adetailer_'): return None if n in overrides: return overrides[n] return v schedulers = [self.scheduler_uri] if \ isinstance(self.scheduler_uri, (str, type(None))) else \ self.scheduler_uri second_model_schedulers = [self.second_model_scheduler_uri] if \ isinstance(self.second_model_scheduler_uri, (str, type(None))) else \ self.second_model_scheduler_uri for arg in _iterate_diffusion_args( prompt=ov('prompt', self.prompts), prompt_weighter_uri=ov('prompt_weighter_uri', [self.prompt_weighter_uri]), vae_tiling=ov('vae_tiling', [self.vae_tiling]), vae_slicing=ov('vae_slicing', [self.vae_slicing]), scheduler_uri=ov('scheduler_uri', schedulers), second_model_scheduler_uri= ov('second_model_scheduler_uri', second_model_schedulers), second_model_prompt_weighter_uri= ov('second_model_prompt_weighter_uri', [self.second_model_prompt_weighter_uri]), second_prompt=ov('second_prompt', self.second_prompts), third_prompt=ov('third_prompt', self.third_prompts), second_model_prompt=ov('second_model_prompt', self.second_model_prompts), second_model_second_prompt=ov('second_model_second_prompt', self.second_model_second_prompts), max_sequence_length=ov('max_sequence_length', [self.max_sequence_length]), seed=ov('seed', self.seeds), clip_skip=ov('clip_skip', self.clip_skips), sdxl_refiner_clip_skip=ov('sdxl_refiner_clip_skip', self.sdxl_refiner_clip_skips), sdxl_t2i_adapter_factor=ov('sdxl_t2i_adapter_factor', self.sdxl_t2i_adapter_factors), image_seed_strength=ov('image_seed_strength', self.image_seed_strengths), guidance_scale=ov('guidance_scale', self.guidance_scales), freeu_params=ov('freeu_params', self.freeu_params), hi_diffusion=ov('hi_diffusion', [self.hi_diffusion]), hi_diffusion_no_win_attn=ov( 'hi_diffusion_no_win_attn', [self.hi_diffusion_no_win_attn]), hi_diffusion_no_raunet=ov( 'hi_diffusion_no_raunet', [self.hi_diffusion_no_raunet]), sada=ov('sada', [self.sada]), sada_max_downsample=ov('sada_max_downsample', self.sada_max_downsamples), sada_sx=ov('sada_sx', self.sada_sxs), sada_sy=ov('sada_sy', self.sada_sys), sada_acc_range=ov('sada_acc_range', self.sada_acc_ranges), sada_lagrange_term=ov('sada_lagrange_term', self.sada_lagrange_terms), sada_lagrange_int=ov('sada_lagrange_int', self.sada_lagrange_ints), sada_lagrange_step=ov('sada_lagrange_step', self.sada_lagrange_steps), sada_max_fix=ov('sada_max_fix', self.sada_max_fixes), sada_max_interval=ov('sada_max_interval', self.sada_max_intervals), tea_cache=ov('tea_cache', [self.tea_cache]), tea_cache_rel_l1_threshold=ov('tea_cache_rel_l1_threshold', self.tea_cache_rel_l1_thresholds), ras=ov('ras', [self.ras]), ras_index_fusion=ov('ras_index_fusion', [self.ras_index_fusion]), ras_sample_ratio=ov('ras_sample_ratio', self.ras_sample_ratios), ras_high_ratio=ov('ras_high_ratio', self.ras_high_ratios), ras_starvation_scale=ov('ras_starvation_scale', self.ras_starvation_scales), ras_error_reset_steps=ov('ras_error_reset_steps', self.ras_error_reset_steps), ras_metric=ov('ras_metric', self.ras_metrics), ras_start_step=ov('ras_start_step', self.ras_start_steps), ras_end_step=ov('ras_end_step', self.ras_end_steps), ras_skip_num_step=ov('ras_skip_num_step', self.ras_skip_num_steps), ras_skip_num_step_length=ov('ras_skip_num_step_length', self.ras_skip_num_step_lengths), deep_cache=ov('deep_cache', [self.deep_cache]), deep_cache_interval=ov('deep_cache_interval', self.deep_cache_intervals), deep_cache_branch_id=ov('deep_cache_branch_id', self.deep_cache_branch_ids), sdxl_refiner_deep_cache=ov('sdxl_refiner_deep_cache', [self.sdxl_refiner_deep_cache]), sdxl_refiner_deep_cache_interval=ov('sdxl_refiner_deep_cache_interval', self.sdxl_refiner_deep_cache_intervals), sdxl_refiner_deep_cache_branch_id=ov('sdxl_refiner_deep_cache_branch_id', self.sdxl_refiner_deep_cache_branch_ids), pag_scale=ov('pag_scale', self.pag_scales), pag_adaptive_scale=ov('pag_adaptive_scale', self.pag_adaptive_scales), image_guidance_scale=ov('image_guidance_scale', self.image_guidance_scales), guidance_rescale=ov('guidance_rescale', self.guidance_rescales), sigmas=ov('sigmas', self.sigmas), inference_steps=ov('inference_steps', self.inference_steps), sdxl_high_noise_fraction=ov('sdxl_high_noise_fraction', self.sdxl_high_noise_fractions), second_model_inference_steps=ov('second_model_inference_steps', self.second_model_inference_steps), second_model_guidance_scale=ov('second_model_guidance_scale', self.second_model_guidance_scales), sdxl_refiner_sigmas=ov('sdxl_refiner_sigmas', self.sdxl_refiner_sigmas), sdxl_refiner_freeu_params=ov('sdxl_refiner_freeu_params', self.sdxl_refiner_freeu_params), sdxl_refiner_pag_scale=ov('sdxl_refiner_pag_scale', self.sdxl_refiner_pag_scales), sdxl_refiner_pag_adaptive_scale=ov('sdxl_refiner_pag_adaptive_scale', self.sdxl_refiner_pag_adaptive_scales), sdxl_refiner_guidance_rescale=ov('sdxl_refiner_guidance_rescale', self.sdxl_refiner_guidance_rescales), upscaler_noise_level=ov('upscaler_noise_level', self.upscaler_noise_levels), sdxl_aesthetic_score=ov('sdxl_aesthetic_score', self.sdxl_aesthetic_scores), sdxl_original_size=ov('sdxl_original_size', self.sdxl_original_sizes), sdxl_target_size=ov('sdxl_target_size', self.sdxl_target_sizes), sdxl_crops_coords_top_left=ov('sdxl_crops_coords_top_left', self.sdxl_crops_coords_top_left), sdxl_negative_aesthetic_score=ov('sdxl_negative_aesthetic_score', self.sdxl_negative_aesthetic_scores), sdxl_negative_original_size=ov('sdxl_negative_original_size', self.sdxl_negative_original_sizes), sdxl_negative_target_size=ov('sdxl_negative_target_size', self.sdxl_negative_target_sizes), sdxl_negative_crops_coords_top_left=ov('sdxl_negative_crops_coords_top_left', self.sdxl_negative_crops_coords_top_left), sdxl_refiner_aesthetic_score=ov('sdxl_refiner_aesthetic_score', self.sdxl_refiner_aesthetic_scores), sdxl_refiner_original_size=ov('sdxl_refiner_original_size', self.sdxl_refiner_original_sizes), sdxl_refiner_target_size=ov('sdxl_refiner_target_size', self.sdxl_refiner_target_sizes), sdxl_refiner_crops_coords_top_left=ov('sdxl_refiner_crops_coords_top_left', self.sdxl_refiner_crops_coords_top_left), sdxl_refiner_negative_aesthetic_score=ov('sdxl_refiner_negative_aesthetic_score', self.sdxl_refiner_negative_aesthetic_scores), sdxl_refiner_negative_original_size=ov('sdxl_refiner_negative_original_size', self.sdxl_refiner_negative_original_sizes), sdxl_refiner_negative_target_size=ov('sdxl_refiner_negative_target_size', self.sdxl_refiner_negative_target_sizes), sdxl_refiner_negative_crops_coords_top_left=ov('sdxl_refiner_negative_crops_coords_top_left', self.sdxl_refiner_negative_crops_coords_top_left), adetailer_class_filter=ov('adetailer_class_filter', [self.adetailer_class_filter]), adetailer_index_filter=ov('adetailer_index_filter', [self.adetailer_index_filter]), adetailer_mask_shape=ov('adetailer_mask_shape', self.adetailer_mask_shapes), adetailer_detector_padding=ov('adetailer_detector_padding', self.adetailer_detector_paddings), adetailer_mask_padding=ov('adetailer_mask_padding', self.adetailer_mask_paddings), adetailer_mask_blur=ov('adetailer_mask_blur', self.adetailer_mask_blurs), adetailer_mask_dilation=ov('adetailer_mask_dilation', self.adetailer_mask_dilations), adetailer_size=ov('adetailer_size', self.adetailer_sizes), adetailer_model_masks=ov('adetailer_model_masks', [self.adetailer_model_masks]), output_latents=ov('output_latents', [self.is_output_latents()]), denoising_start=ov('denoising_start', [self.denoising_start]), denoising_end=ov('denoising_end', [self.denoising_end]), latents=ov('latents', [self.latents]), latents_processors=ov('latents_processors', [self.latents_processors]), latents_post_processors=ov('latents_post_processors', [self.latents_post_processors]), img2img_latents_processors=ov( 'img2img_latents_processors', [self.img2img_latents_processors] ), inpaint_crop=ov('inpaint_crop', [self.inpaint_crop]), inpaint_crop_padding=ov('inpaint_crop_padding', self.inpaint_crop_paddings), inpaint_crop_masked=ov('inpaint_crop_masked', [self.inpaint_crop_masked]), inpaint_crop_feather=ov('inpaint_crop_feather', self.inpaint_crop_feathers) ): if self.output_size is not None: arg.width = self.output_size[0] arg.height = self.output_size[1] arg.aspect_correct = not self.no_aspect arg.prompt.set_embedded_args_on( on_object=arg, forbidden_checker=_pipelinewrapper.DiffusionArguments.prompt_embedded_arg_checker) yield arg
def _non_null_attr_that_start_with(self, s: typing.Union[str, typing.List[str]]) -> typing.Iterator[str]: """ Return an iterator of attribute names that start with the given prefix(es) and have non-None values. Args: s: A string prefix or list of string prefixes Returns: Iterator of attribute names that match the prefix(es) and have non-None values """ if not isinstance(s, list): s = [s] return (a for a in dir(self) if any(a.startswith(k) for k in s) and getattr(self, a) is not None) def _non_null_attr_that_end_with(self, s: str) -> typing.Iterator[str]: """ Return an iterator of attribute names that end with the given suffix and have non-None values. Args: s: A string suffix Returns: Iterator of attribute names that match the suffix and have non-None values """ return (a for a in dir(self) if a.endswith(s) and getattr(self, a) is not None) def _non_null_second_model_arguments(self, prefix: typing.Optional[str] = None) -> typing.Iterator[str]: """ Return an iterator of attribute names related to second models that have non-None values. Args: prefix: An optional prefix to further filter attributes Returns: Iterator of attribute names related to second models that have non-None values """ def check(a: str) -> bool: if prefix and a.startswith(prefix): return True if a.startswith('second_model'): # short circuit and include # second model prompt arguments return True if a.startswith('second') and not \ (a.endswith('prompts') or a.endswith('prompt_upscaler_uri')): # reject primary model 'second_prompts' and `second_prompt_upscaler_uri` # and include everything else return True return False return (a for a in dir(self) if check(a) and getattr(self, a) is not None)
[docs] def is_output_latents(self) -> bool: """ Check if the current image_format results in outputting latents. :return: ``True`` if the image output format indicates to output latents. """ return self.image_format in _mediaoutput.get_supported_tensor_formats()