From e85c3bc465278d0900af2f1feb2f201d8ff53d8b Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Wed, 28 Aug 2024 19:54:02 +0000 Subject: [PATCH 01/20] Add FLUX VAE support to ImageToLatentsInvocation. --- invokeai/app/invocations/image_to_latents.py | 37 +++++++++++++++++++- invokeai/backend/flux/modules/autoencoder.py | 28 +++++++++++---- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/invokeai/app/invocations/image_to_latents.py b/invokeai/app/invocations/image_to_latents.py index dadd8bb3a10..e277173b70b 100644 --- a/invokeai/app/invocations/image_to_latents.py +++ b/invokeai/app/invocations/image_to_latents.py @@ -23,7 +23,9 @@ from invokeai.app.invocations.model import VAEField from invokeai.app.invocations.primitives import LatentsOutput from invokeai.app.services.shared.invocation_context import InvocationContext +from invokeai.backend.flux.modules.autoencoder import AutoEncoder from invokeai.backend.model_manager import LoadedModel +from invokeai.backend.model_manager.config import BaseModelType from invokeai.backend.stable_diffusion.diffusers_pipeline import image_resized_to_grid_as_tensor from invokeai.backend.stable_diffusion.vae_tiling import patch_vae_tiling_params @@ -52,7 +54,19 @@ class ImageToLatentsInvocation(BaseInvocation): fp32: bool = InputField(default=DEFAULT_PRECISION == torch.float32, description=FieldDescriptions.fp32) @staticmethod - def vae_encode( + def vae_encode_flux(vae_info: LoadedModel, image_tensor: torch.Tensor) -> torch.Tensor: + # TODO(ryand): Expose seed parameter at the invocation level. + # TODO(ryand): Write a util function for generating random tensors that is consistent across devices / dtypes. + # There's a starting point in get_noise(...), but it needs to be extracted and generalized. This function + # should be used for VAE encode sampling. + generator = torch.Generator().manual_seed(0) + with vae_info as vae: + assert isinstance(vae, AutoEncoder) + latents = vae.encode(image_tensor, sample=True, generator=generator) + return latents + + @staticmethod + def vae_encode_stable_diffusion( vae_info: LoadedModel, upcast: bool, tiled: bool, image_tensor: torch.Tensor, tile_size: int = 0 ) -> torch.Tensor: with vae_info as vae: @@ -107,6 +121,27 @@ def vae_encode( return latents + @staticmethod + def vae_encode( + vae_info: LoadedModel, upcast: bool, tiled: bool, image_tensor: torch.Tensor, tile_size: int = 0 + ) -> torch.Tensor: + if vae_info.config.base == BaseModelType.Flux: + if upcast: + raise NotImplementedError("FLUX VAE encode does not currently support upcast=True.") + if tiled: + raise NotImplementedError("FLUX VAE encode does not currently support tiled=True.") + return ImageToLatentsInvocation.vae_encode_flux(vae_info=vae_info, image_tensor=image_tensor) + elif vae_info.config.base in [ + BaseModelType.StableDiffusion1, + BaseModelType.StableDiffusion2, + BaseModelType.StableDiffusionXL, + ]: + return ImageToLatentsInvocation.vae_encode_stable_diffusion( + vae_info=vae_info, upcast=upcast, tiled=tiled, image_tensor=image_tensor, tile_size=tile_size + ) + else: + raise ValueError(f"Unsupported VAE base type: '{vae_info.config.base}'") + @torch.no_grad() def invoke(self, context: InvocationContext) -> LatentsOutput: image = context.images.get_pil(self.image.image_name) diff --git a/invokeai/backend/flux/modules/autoencoder.py b/invokeai/backend/flux/modules/autoencoder.py index 237769aba71..6b072a82f63 100644 --- a/invokeai/backend/flux/modules/autoencoder.py +++ b/invokeai/backend/flux/modules/autoencoder.py @@ -258,16 +258,17 @@ def forward(self, z: Tensor) -> Tensor: class DiagonalGaussian(nn.Module): - def __init__(self, sample: bool = True, chunk_dim: int = 1): + def __init__(self, chunk_dim: int = 1): super().__init__() - self.sample = sample self.chunk_dim = chunk_dim - def forward(self, z: Tensor) -> Tensor: + def forward(self, z: Tensor, sample: bool = True, generator: torch.Generator | None = None) -> Tensor: mean, logvar = torch.chunk(z, 2, dim=self.chunk_dim) - if self.sample: + if sample: std = torch.exp(0.5 * logvar) - return mean + std * torch.randn_like(mean) + # Unfortunately, torch.randn_like(...) does not accept a generator argument at the time of writing, so we + # have to use torch.randn(...) instead. + return mean + std * torch.randn(size=mean.size(), generator=generator, dtype=mean.dtype, device=mean.device) else: return mean @@ -297,8 +298,21 @@ def __init__(self, params: AutoEncoderParams): self.scale_factor = params.scale_factor self.shift_factor = params.shift_factor - def encode(self, x: Tensor) -> Tensor: - z = self.reg(self.encoder(x)) + def encode(self, x: Tensor, sample: bool = True, generator: torch.Generator | None = None) -> Tensor: + """Run VAE encoding on input tensor x. + + Args: + x (Tensor): Input image tensor. Shape: (batch_size, in_channels, height, width). + sample (bool, optional): If True, sample from the encoded distribution, else, return the distribution mean. + Defaults to True. + generator (torch.Generator | None, optional): Optional random number generator for reproducibility. + Defaults to None. + + Returns: + Tensor: Encoded latent tensor. Shape: (batch_size, z_channels, latent_height, latent_width). + """ + + z = self.reg(self.encoder(x), sample=sample, generator=generator) z = self.scale_factor * (z - self.shift_factor) return z From ffa39857d3cf8c4bf20c378784018e0f80411f59 Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Wed, 28 Aug 2024 20:30:00 +0000 Subject: [PATCH 02/20] Add FLUX VAE decoding support to LatentsToImageInvocation. --- invokeai/app/invocations/latents_to_image.py | 43 +++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/invokeai/app/invocations/latents_to_image.py b/invokeai/app/invocations/latents_to_image.py index 35b8483f2cc..90885d5c40e 100644 --- a/invokeai/app/invocations/latents_to_image.py +++ b/invokeai/app/invocations/latents_to_image.py @@ -10,6 +10,8 @@ ) from diffusers.models.autoencoders.autoencoder_kl import AutoencoderKL from diffusers.models.autoencoders.autoencoder_tiny import AutoencoderTiny +from einops import rearrange +from PIL import Image from invokeai.app.invocations.baseinvocation import BaseInvocation, invocation from invokeai.app.invocations.constants import DEFAULT_PRECISION, LATENT_SCALE_FACTOR @@ -24,6 +26,9 @@ from invokeai.app.invocations.model import VAEField from invokeai.app.invocations.primitives import ImageOutput from invokeai.app.services.shared.invocation_context import InvocationContext +from invokeai.backend.flux.modules.autoencoder import AutoEncoder +from invokeai.backend.model_manager.config import BaseModelType +from invokeai.backend.model_manager.load.load_base import LoadedModel from invokeai.backend.stable_diffusion.extensions.seamless import SeamlessExt from invokeai.backend.stable_diffusion.vae_tiling import patch_vae_tiling_params from invokeai.backend.util.devices import TorchDevice @@ -53,11 +58,7 @@ class LatentsToImageInvocation(BaseInvocation, WithMetadata, WithBoard): tile_size: int = InputField(default=0, multiple_of=8, description=FieldDescriptions.vae_tile_size) fp32: bool = InputField(default=DEFAULT_PRECISION == torch.float32, description=FieldDescriptions.fp32) - @torch.no_grad() - def invoke(self, context: InvocationContext) -> ImageOutput: - latents = context.tensors.load(self.latents.latents_name) - - vae_info = context.models.load(self.vae.vae) + def _vae_decode_stable_diffusion(self, vae_info: LoadedModel, latents: torch.Tensor) -> Image.Image: assert isinstance(vae_info.model, (AutoencoderKL, AutoencoderTiny)) with SeamlessExt.static_patch_model(vae_info.model, self.vae.seamless_axes), vae_info as vae: assert isinstance(vae, (AutoencoderKL, AutoencoderTiny)) @@ -113,6 +114,38 @@ def invoke(self, context: InvocationContext) -> ImageOutput: np_image = image.cpu().permute(0, 2, 3, 1).float().numpy() image = VaeImageProcessor.numpy_to_pil(np_image)[0] + return image + + def _vae_decode_flux(self, vae_info: LoadedModel, latents: torch.Tensor) -> Image.Image: + with vae_info as vae: + assert isinstance(vae, AutoEncoder) + latents = latents.to(dtype=TorchDevice.choose_torch_dtype()) + img = vae.decode(latents) + + img = img.clamp(-1, 1) + img = rearrange(img[0], "c h w -> h w c") # noqa: F821 + img_pil = Image.fromarray((127.5 * (img + 1.0)).byte().cpu().numpy()) + return img_pil + + @torch.no_grad() + def invoke(self, context: InvocationContext) -> ImageOutput: + latents = context.tensors.load(self.latents.latents_name) + + vae_info = context.models.load(self.vae.vae) + if vae_info.config.base == BaseModelType.Flux: + if self.fp32: + raise NotImplementedError("FLUX VAE decode does not currently support fp32=True.") + if self.tiled: + raise NotImplementedError("FLUX VAE decode does not currently support tiled=True.") + image = self._vae_decode_flux(vae_info=vae_info, latents=latents) + elif vae_info.config.base in [ + BaseModelType.StableDiffusion1, + BaseModelType.StableDiffusion2, + BaseModelType.StableDiffusionXL, + ]: + image = self._vae_decode_stable_diffusion(vae_info=vae_info, latents=latents) + else: + raise ValueError(f"Unsupported VAE base type: '{vae_info.config.base}'") TorchDevice.empty_cache() From a7a33d73f59fca040a75d13b17c57d5a4aef474f Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Thu, 29 Aug 2024 14:17:08 +0000 Subject: [PATCH 03/20] Get FLUX non-masked image-to-image working - still rough. --- .../app/invocations/flux_text_to_image.py | 41 +++++++++++++++++-- invokeai/app/invocations/image_to_latents.py | 6 ++- invokeai/backend/flux/sampling.py | 2 +- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/invokeai/app/invocations/flux_text_to_image.py b/invokeai/app/invocations/flux_text_to_image.py index 248122d8cdf..dacc2825431 100644 --- a/invokeai/app/invocations/flux_text_to_image.py +++ b/invokeai/app/invocations/flux_text_to_image.py @@ -1,3 +1,5 @@ +from typing import Optional + import torch from einops import rearrange from PIL import Image @@ -8,6 +10,7 @@ FluxConditioningField, Input, InputField, + LatentsField, WithBoard, WithMetadata, ) @@ -21,6 +24,8 @@ from invokeai.backend.stable_diffusion.diffusion.conditioning_data import FLUXConditioningInfo from invokeai.backend.util.devices import TorchDevice +EPS = 1e-6 + @invocation( "flux_text_to_image", @@ -33,6 +38,18 @@ class FluxTextToImageInvocation(BaseInvocation, WithMetadata, WithBoard): """Text-to-image generation using a FLUX model.""" + # If latents is provided, this means we are doing image-to-image. + latents: Optional[LatentsField] = InputField( + default=None, + description=FieldDescriptions.latents, + input=Input.Connection, + ) + denoising_start: float = InputField( + default=0.0, + ge=0, + le=1, + description=FieldDescriptions.denoising_start, + ) transformer: TransformerField = InputField( description=FieldDescriptions.flux_model, input=Input.Connection, @@ -78,7 +95,10 @@ def _run_diffusion( t5_embeddings = flux_conditioning.t5_embeds clip_embeddings = flux_conditioning.clip_embeds - transformer_info = context.models.load(self.transformer.transformer) + # Load the input latents, if provided. + init_latents = context.tensors.load(self.latents.latents_name) if self.latents else None + if init_latents is not None: + init_latents = init_latents.to(device=TorchDevice.choose_torch_device(), dtype=inference_dtype) # Prepare input noise. x = get_noise( @@ -90,8 +110,7 @@ def _run_diffusion( seed=self.seed, ) - x, img_ids = prepare_latent_img_patches(x) - + transformer_info = context.models.load(self.transformer.transformer) is_schnell = "schnell" in transformer_info.config.config_path timesteps = get_schedule( @@ -100,6 +119,22 @@ def _run_diffusion( shift=not is_schnell, ) + # Prepare inputs for image-to-image case. + if self.denoising_start > EPS: + if init_latents is None: + raise ValueError("latents must be provided if denoising_start > 0.") + + # Clip the timesteps schedule based on denoising_start. + # TODO(ryand): Should we apply denoising_start in timestep-space rather than timestep-index-space? + start_idx = int(self.denoising_start * len(timesteps)) + timesteps = timesteps[start_idx:] + + # Noise the orig_latents by the appropriate amount for the first timestep. + t_0 = timesteps[0] + x = t_0 * x + (1.0 - t_0) * init_latents + + x, img_ids = prepare_latent_img_patches(x) + bs, t5_seq_len, _ = t5_embeddings.shape txt_ids = torch.zeros(bs, t5_seq_len, 3, dtype=inference_dtype, device=TorchDevice.choose_torch_device()) diff --git a/invokeai/app/invocations/image_to_latents.py b/invokeai/app/invocations/image_to_latents.py index e277173b70b..8eba975898c 100644 --- a/invokeai/app/invocations/image_to_latents.py +++ b/invokeai/app/invocations/image_to_latents.py @@ -28,6 +28,7 @@ from invokeai.backend.model_manager.config import BaseModelType from invokeai.backend.stable_diffusion.diffusers_pipeline import image_resized_to_grid_as_tensor from invokeai.backend.stable_diffusion.vae_tiling import patch_vae_tiling_params +from invokeai.backend.util.devices import TorchDevice @invocation( @@ -59,9 +60,12 @@ def vae_encode_flux(vae_info: LoadedModel, image_tensor: torch.Tensor) -> torch. # TODO(ryand): Write a util function for generating random tensors that is consistent across devices / dtypes. # There's a starting point in get_noise(...), but it needs to be extracted and generalized. This function # should be used for VAE encode sampling. - generator = torch.Generator().manual_seed(0) + generator = torch.Generator(device=TorchDevice.choose_torch_device()).manual_seed(0) with vae_info as vae: assert isinstance(vae, AutoEncoder) + image_tensor = image_tensor.to( + device=TorchDevice.choose_torch_device(), dtype=TorchDevice.choose_torch_dtype() + ) latents = vae.encode(image_tensor, sample=True, generator=generator) return latents diff --git a/invokeai/backend/flux/sampling.py b/invokeai/backend/flux/sampling.py index 7a35b0aedfb..3c3103411a6 100644 --- a/invokeai/backend/flux/sampling.py +++ b/invokeai/backend/flux/sampling.py @@ -91,7 +91,7 @@ def get_schedule( # shifting the schedule to favor high timesteps for higher signal images if shift: - # eastimate mu based on linear estimation between two points + # estimate mu based on linear estimation between two points mu = get_lin_function(y1=base_shift, y2=max_shift)(image_seq_len) timesteps = time_shift(mu, 1.0, timesteps) From 0aa13c046c92d143bd0c693458c7386270bf1712 Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Thu, 29 Aug 2024 14:50:58 +0000 Subject: [PATCH 04/20] Split VAE decoding out from the FLUXTextToImageInvocation. --- .../app/invocations/flux_text_to_image.py | 33 ++++--------------- invokeai/app/invocations/latents_to_image.py | 2 +- 2 files changed, 8 insertions(+), 27 deletions(-) diff --git a/invokeai/app/invocations/flux_text_to_image.py b/invokeai/app/invocations/flux_text_to_image.py index dacc2825431..d1238864888 100644 --- a/invokeai/app/invocations/flux_text_to_image.py +++ b/invokeai/app/invocations/flux_text_to_image.py @@ -1,8 +1,6 @@ from typing import Optional import torch -from einops import rearrange -from PIL import Image from invokeai.app.invocations.baseinvocation import BaseInvocation, Classification, invocation from invokeai.app.invocations.fields import ( @@ -15,11 +13,10 @@ WithMetadata, ) from invokeai.app.invocations.model import TransformerField, VAEField -from invokeai.app.invocations.primitives import ImageOutput +from invokeai.app.invocations.primitives import LatentsOutput from invokeai.app.services.session_processor.session_processor_common import CanceledException from invokeai.app.services.shared.invocation_context import InvocationContext from invokeai.backend.flux.model import Flux -from invokeai.backend.flux.modules.autoencoder import AutoEncoder from invokeai.backend.flux.sampling import denoise, get_noise, get_schedule, prepare_latent_img_patches, unpack from invokeai.backend.stable_diffusion.diffusion.conditioning_data import FLUXConditioningInfo from invokeai.backend.util.devices import TorchDevice @@ -65,7 +62,7 @@ class FluxTextToImageInvocation(BaseInvocation, WithMetadata, WithBoard): width: int = InputField(default=1024, multiple_of=16, description="Width of the generated image.") height: int = InputField(default=1024, multiple_of=16, description="Height of the generated image.") num_steps: int = InputField( - default=4, description="Number of diffusion steps. Recommend values are schnell: 4, dev: 50." + default=4, description="Number of diffusion steps. Recommended values are schnell: 4, dev: 50." ) guidance: float = InputField( default=4.0, @@ -74,11 +71,12 @@ class FluxTextToImageInvocation(BaseInvocation, WithMetadata, WithBoard): seed: int = InputField(default=0, description="Randomness seed for reproducibility.") @torch.no_grad() - def invoke(self, context: InvocationContext) -> ImageOutput: + def invoke(self, context: InvocationContext) -> LatentsOutput: latents = self._run_diffusion(context) - image = self._run_vae_decoding(context, latents) - image_dto = context.images.save(image=image) - return ImageOutput.build(image_dto) + latents = latents.detach().to("cpu") + + name = context.tensors.save(tensor=latents) + return LatentsOutput.build(latents_name=name, latents=latents, seed=None) def _run_diffusion( self, @@ -185,20 +183,3 @@ def step_callback() -> None: x = unpack(x.float(), self.height, self.width) return x - - def _run_vae_decoding( - self, - context: InvocationContext, - latents: torch.Tensor, - ) -> Image.Image: - vae_info = context.models.load(self.vae.vae) - with vae_info as vae: - assert isinstance(vae, AutoEncoder) - latents = latents.to(dtype=TorchDevice.choose_torch_dtype()) - img = vae.decode(latents) - - img = img.clamp(-1, 1) - img = rearrange(img[0], "c h w -> h w c") - img_pil = Image.fromarray((127.5 * (img + 1.0)).byte().cpu().numpy()) - - return img_pil diff --git a/invokeai/app/invocations/latents_to_image.py b/invokeai/app/invocations/latents_to_image.py index 90885d5c40e..660e7e84d57 100644 --- a/invokeai/app/invocations/latents_to_image.py +++ b/invokeai/app/invocations/latents_to_image.py @@ -119,7 +119,7 @@ def _vae_decode_stable_diffusion(self, vae_info: LoadedModel, latents: torch.Ten def _vae_decode_flux(self, vae_info: LoadedModel, latents: torch.Tensor) -> Image.Image: with vae_info as vae: assert isinstance(vae, AutoEncoder) - latents = latents.to(dtype=TorchDevice.choose_torch_dtype()) + latents = latents.to(device=TorchDevice.choose_torch_device(), dtype=TorchDevice.choose_torch_dtype()) img = vae.decode(latents) img = img.clamp(-1, 1) From 7ebb509d05e3647982c0256175e43859a8115ba9 Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Thu, 29 Aug 2024 14:56:58 +0000 Subject: [PATCH 05/20] Bump FLUX node versions after splitting out VAE encode/decode. --- invokeai/app/invocations/flux_text_to_image.py | 2 +- invokeai/app/invocations/image_to_latents.py | 2 +- invokeai/app/invocations/latents_to_image.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/invokeai/app/invocations/flux_text_to_image.py b/invokeai/app/invocations/flux_text_to_image.py index d1238864888..906ae4cb00b 100644 --- a/invokeai/app/invocations/flux_text_to_image.py +++ b/invokeai/app/invocations/flux_text_to_image.py @@ -29,7 +29,7 @@ title="FLUX Text to Image", tags=["image", "flux"], category="image", - version="1.0.0", + version="2.0.0", classification=Classification.Prototype, ) class FluxTextToImageInvocation(BaseInvocation, WithMetadata, WithBoard): diff --git a/invokeai/app/invocations/image_to_latents.py b/invokeai/app/invocations/image_to_latents.py index 8eba975898c..99a92d98de7 100644 --- a/invokeai/app/invocations/image_to_latents.py +++ b/invokeai/app/invocations/image_to_latents.py @@ -36,7 +36,7 @@ title="Image to Latents", tags=["latents", "image", "vae", "i2l"], category="latents", - version="1.1.0", + version="1.2.0", ) class ImageToLatentsInvocation(BaseInvocation): """Encodes an image into latents.""" diff --git a/invokeai/app/invocations/latents_to_image.py b/invokeai/app/invocations/latents_to_image.py index 660e7e84d57..7c7fdf07c7e 100644 --- a/invokeai/app/invocations/latents_to_image.py +++ b/invokeai/app/invocations/latents_to_image.py @@ -39,7 +39,7 @@ title="Latents to Image", tags=["latents", "image", "vae", "l2i"], category="latents", - version="1.3.0", + version="1.4.0", ) class LatentsToImageInvocation(BaseInvocation, WithMetadata, WithBoard): """Generates an image from latents.""" From bd466661ec4efe2f24424fa37a197a129ad2c2ea Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Thu, 29 Aug 2024 15:08:11 +0000 Subject: [PATCH 06/20] Remove unused vae field from FLUXTextToImageInvocation. --- invokeai/app/invocations/flux_text_to_image.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/invokeai/app/invocations/flux_text_to_image.py b/invokeai/app/invocations/flux_text_to_image.py index 906ae4cb00b..a813243c858 100644 --- a/invokeai/app/invocations/flux_text_to_image.py +++ b/invokeai/app/invocations/flux_text_to_image.py @@ -12,7 +12,7 @@ WithBoard, WithMetadata, ) -from invokeai.app.invocations.model import TransformerField, VAEField +from invokeai.app.invocations.model import TransformerField from invokeai.app.invocations.primitives import LatentsOutput from invokeai.app.services.session_processor.session_processor_common import CanceledException from invokeai.app.services.shared.invocation_context import InvocationContext @@ -52,10 +52,6 @@ class FluxTextToImageInvocation(BaseInvocation, WithMetadata, WithBoard): input=Input.Connection, title="Transformer", ) - vae: VAEField = InputField( - description=FieldDescriptions.vae, - input=Input.Connection, - ) positive_text_conditioning: FluxConditioningField = InputField( description=FieldDescriptions.positive_cond, input=Input.Connection ) From 7ad62512eb6a905008f73fd183e84e14ef57939c Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Thu, 29 Aug 2024 17:41:06 +0000 Subject: [PATCH 07/20] Update MaskTensorToImageInvocation to support input mask tensors with or without a channel dimension. --- invokeai/app/invocations/mask.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/invokeai/app/invocations/mask.py b/invokeai/app/invocations/mask.py index 64d1b48e389..f7cbc6d832e 100644 --- a/invokeai/app/invocations/mask.py +++ b/invokeai/app/invocations/mask.py @@ -126,7 +126,7 @@ def invoke(self, context: InvocationContext) -> MaskOutput: title="Tensor Mask to Image", tags=["mask"], category="mask", - version="1.0.0", + version="1.1.0", ) class MaskTensorToImageInvocation(BaseInvocation, WithMetadata, WithBoard): """Convert a mask tensor to an image.""" @@ -135,6 +135,11 @@ class MaskTensorToImageInvocation(BaseInvocation, WithMetadata, WithBoard): def invoke(self, context: InvocationContext) -> ImageOutput: mask = context.tensors.load(self.mask.tensor_name) + + # Squeeze the channel dimension if it exists. + if mask.dim() == 3: + mask = mask.squeeze(0) + # Ensure that the mask is binary. if mask.dtype != torch.bool: mask = mask > 0.5 From 9a8aca69bff011b8b01ce487ba1965208759e635 Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Thu, 29 Aug 2024 19:05:44 +0000 Subject: [PATCH 08/20] Get a rough version of FLUX inpainting working. --- invokeai/app/invocations/denoise_latents.py | 2 +- invokeai/app/invocations/fields.py | 2 +- .../app/invocations/flux_text_to_image.py | 77 +++++++++++++-- invokeai/backend/flux/denoise.py | 55 +++++++++++ invokeai/backend/flux/inpaint.py | 15 +++ .../flux/{sampling.py => sampling_utils.py} | 96 ++++--------------- 6 files changed, 161 insertions(+), 86 deletions(-) create mode 100644 invokeai/backend/flux/denoise.py create mode 100644 invokeai/backend/flux/inpaint.py rename invokeai/backend/flux/{sampling.py => sampling_utils.py} (53%) diff --git a/invokeai/app/invocations/denoise_latents.py b/invokeai/app/invocations/denoise_latents.py index d97f92d42c0..f8028b1933d 100644 --- a/invokeai/app/invocations/denoise_latents.py +++ b/invokeai/app/invocations/denoise_latents.py @@ -185,7 +185,7 @@ class DenoiseLatentsInvocation(BaseInvocation): ) denoise_mask: Optional[DenoiseMaskField] = InputField( default=None, - description=FieldDescriptions.mask, + description=FieldDescriptions.denoise_mask, input=Input.Connection, ui_order=8, ) diff --git a/invokeai/app/invocations/fields.py b/invokeai/app/invocations/fields.py index 03654dd78db..bd841808f48 100644 --- a/invokeai/app/invocations/fields.py +++ b/invokeai/app/invocations/fields.py @@ -181,7 +181,7 @@ class FieldDescriptions: ) num_1 = "The first number" num_2 = "The second number" - mask = "The mask to use for the operation" + denoise_mask = "A mask of the region to apply the denoising process to." board = "The board to save the image to" image = "The image to process" tile_size = "Tile size" diff --git a/invokeai/app/invocations/flux_text_to_image.py b/invokeai/app/invocations/flux_text_to_image.py index a813243c858..03a09652760 100644 --- a/invokeai/app/invocations/flux_text_to_image.py +++ b/invokeai/app/invocations/flux_text_to_image.py @@ -1,9 +1,12 @@ from typing import Optional import torch +import torchvision.transforms as tv_transforms +from torchvision.transforms.functional import resize as tv_resize from invokeai.app.invocations.baseinvocation import BaseInvocation, Classification, invocation from invokeai.app.invocations.fields import ( + DenoiseMaskField, FieldDescriptions, FluxConditioningField, Input, @@ -16,8 +19,15 @@ from invokeai.app.invocations.primitives import LatentsOutput from invokeai.app.services.session_processor.session_processor_common import CanceledException from invokeai.app.services.shared.invocation_context import InvocationContext +from invokeai.backend.flux.denoise import denoise from invokeai.backend.flux.model import Flux -from invokeai.backend.flux.sampling import denoise, get_noise, get_schedule, prepare_latent_img_patches, unpack +from invokeai.backend.flux.sampling_utils import ( + generate_img_ids, + get_noise, + get_schedule, + pack, + unpack, +) from invokeai.backend.stable_diffusion.diffusion.conditioning_data import FLUXConditioningInfo from invokeai.backend.util.devices import TorchDevice @@ -41,6 +51,11 @@ class FluxTextToImageInvocation(BaseInvocation, WithMetadata, WithBoard): description=FieldDescriptions.latents, input=Input.Connection, ) + denoise_mask: Optional[DenoiseMaskField] = InputField( + default=None, + description=FieldDescriptions.denoise_mask, + input=Input.Connection, + ) denoising_start: float = InputField( default=0.0, ge=0, @@ -95,7 +110,7 @@ def _run_diffusion( init_latents = init_latents.to(device=TorchDevice.choose_torch_device(), dtype=inference_dtype) # Prepare input noise. - x = get_noise( + noise = get_noise( num_samples=1, height=self.height, width=self.width, @@ -107,14 +122,16 @@ def _run_diffusion( transformer_info = context.models.load(self.transformer.transformer) is_schnell = "schnell" in transformer_info.config.config_path + image_seq_len = noise.shape[-1] * noise.shape[-2] // 4 timesteps = get_schedule( num_steps=self.num_steps, - image_seq_len=x.shape[1], + image_seq_len=image_seq_len, shift=not is_schnell, ) - # Prepare inputs for image-to-image case. + # Prepare input latent image. if self.denoising_start > EPS: + # If denoising_start > 0, we are doing image-to-image. if init_latents is None: raise ValueError("latents must be provided if denoising_start > 0.") @@ -125,13 +142,34 @@ def _run_diffusion( # Noise the orig_latents by the appropriate amount for the first timestep. t_0 = timesteps[0] - x = t_0 * x + (1.0 - t_0) * init_latents - - x, img_ids = prepare_latent_img_patches(x) + x = t_0 * noise + (1.0 - t_0) * init_latents + else: + # We are not doing image-to-image, so we are starting from noise. + x = noise + + # Prepare inpaint mask. + inpaint_mask = self._prep_inpaint_mask(context, x) + if inpaint_mask is not None: + assert init_latents is not None + # Expand the inpaint mask to the same shape as the init_latents so that when we pack inpaint_mask it lines + # up with the init_latents. + inpaint_mask = inpaint_mask.expand_as(init_latents) + + b, _c, h, w = x.shape + img_ids = generate_img_ids(h=h, w=w, batch_size=b, device=x.device, dtype=x.dtype) bs, t5_seq_len, _ = t5_embeddings.shape txt_ids = torch.zeros(bs, t5_seq_len, 3, dtype=inference_dtype, device=TorchDevice.choose_torch_device()) + # Pack all latent tensors. + init_latents = pack(init_latents) if init_latents is not None else None + inpaint_mask = pack(inpaint_mask) if inpaint_mask is not None else None + noise = pack(noise) + x = pack(x) + + # Verify that we calculated the image_seq_len correctly. + assert image_seq_len == x.shape[1] + with transformer_info as transformer: assert isinstance(transformer, Flux) @@ -174,8 +212,33 @@ def step_callback() -> None: timesteps=timesteps, step_callback=step_callback, guidance=self.guidance, + init_latents=init_latents, + noise=noise, + inpaint_mask=inpaint_mask, ) x = unpack(x.float(), self.height, self.width) return x + + def _prep_inpaint_mask(self, context: InvocationContext, latents: torch.Tensor) -> torch.Tensor | None: + """Prepare the inpaint mask. + + Loads the mask, resizes if necessary, casts to same device/dtype as latents. + + Returns: + tuple[torch.Tensor | None, bool]: (mask, is_gradient_mask) + """ + if self.denoise_mask is None: + return None + + mask = context.tensors.load(self.denoise_mask.mask_name) + _, _, latent_height, latent_width = latents.shape + mask = tv_resize( + img=mask, + size=[latent_height, latent_width], + interpolation=tv_transforms.InterpolationMode.BILINEAR, + antialias=False, + ) + mask = mask.to(device=latents.device, dtype=latents.dtype) + return mask diff --git a/invokeai/backend/flux/denoise.py b/invokeai/backend/flux/denoise.py new file mode 100644 index 00000000000..103fcd907bc --- /dev/null +++ b/invokeai/backend/flux/denoise.py @@ -0,0 +1,55 @@ +from typing import Callable + +import torch +from tqdm import tqdm + +from invokeai.backend.flux.inpaint import merge_intermediate_latents_with_init_latents +from invokeai.backend.flux.model import Flux + + +def denoise( + model: Flux, + # model input + img: torch.Tensor, + img_ids: torch.Tensor, + txt: torch.Tensor, + txt_ids: torch.Tensor, + vec: torch.Tensor, + # sampling parameters + timesteps: list[float], + step_callback: Callable[[], None], + guidance: float, + # For inpainting: + init_latents: torch.Tensor | None, + noise: torch.Tensor, + inpaint_mask: torch.Tensor | None, +): + # guidance_vec is ignored for schnell. + guidance_vec = torch.full((img.shape[0],), guidance, device=img.device, dtype=img.dtype) + for t_curr, t_prev in tqdm(list(zip(timesteps[:-1], timesteps[1:], strict=True))): + t_vec = torch.full((img.shape[0],), t_curr, dtype=img.dtype, device=img.device) + pred = model( + img=img, + img_ids=img_ids, + txt=txt, + txt_ids=txt_ids, + y=vec, + timesteps=t_vec, + guidance=guidance_vec, + ) + + img = img + (t_prev - t_curr) * pred + + if inpaint_mask is not None: + assert init_latents is not None + img = merge_intermediate_latents_with_init_latents( + init_latents=init_latents, + intermediate_latents=img, + timestep=t_prev, + noise=noise, + inpaint_mask=inpaint_mask, + ) + + step_callback() + + return img diff --git a/invokeai/backend/flux/inpaint.py b/invokeai/backend/flux/inpaint.py new file mode 100644 index 00000000000..3bebb9c3e64 --- /dev/null +++ b/invokeai/backend/flux/inpaint.py @@ -0,0 +1,15 @@ +import torch + + +def merge_intermediate_latents_with_init_latents( + init_latents: torch.Tensor, + intermediate_latents: torch.Tensor, + timestep: float, + noise: torch.Tensor, + inpaint_mask: torch.Tensor, +) -> torch.Tensor: + # Noise the init_latents for the current timestep. + noised_init_latents = noise * timestep + (1.0 - timestep) * init_latents + + # Merge the intermediate_latents with the noised_init_latents using the inpaint_mask. + return intermediate_latents * inpaint_mask + noised_init_latents * (1.0 - inpaint_mask) diff --git a/invokeai/backend/flux/sampling.py b/invokeai/backend/flux/sampling_utils.py similarity index 53% rename from invokeai/backend/flux/sampling.py rename to invokeai/backend/flux/sampling_utils.py index 3c3103411a6..9d710015afc 100644 --- a/invokeai/backend/flux/sampling.py +++ b/invokeai/backend/flux/sampling_utils.py @@ -6,10 +6,6 @@ import torch from einops import rearrange, repeat from torch import Tensor -from tqdm import tqdm - -from invokeai.backend.flux.model import Flux -from invokeai.backend.flux.modules.conditioner import HFEncoder def get_noise( @@ -35,40 +31,6 @@ def get_noise( ).to(device=device, dtype=dtype) -def prepare(t5: HFEncoder, clip: HFEncoder, img: Tensor, prompt: str | list[str]) -> dict[str, Tensor]: - bs, c, h, w = img.shape - if bs == 1 and not isinstance(prompt, str): - bs = len(prompt) - - img = rearrange(img, "b c (h ph) (w pw) -> b (h w) (c ph pw)", ph=2, pw=2) - if img.shape[0] == 1 and bs > 1: - img = repeat(img, "1 ... -> bs ...", bs=bs) - - img_ids = torch.zeros(h // 2, w // 2, 3) - img_ids[..., 1] = img_ids[..., 1] + torch.arange(h // 2)[:, None] - img_ids[..., 2] = img_ids[..., 2] + torch.arange(w // 2)[None, :] - img_ids = repeat(img_ids, "h w c -> b (h w) c", b=bs) - - if isinstance(prompt, str): - prompt = [prompt] - txt = t5(prompt) - if txt.shape[0] == 1 and bs > 1: - txt = repeat(txt, "1 ... -> bs ...", bs=bs) - txt_ids = torch.zeros(bs, txt.shape[1], 3) - - vec = clip(prompt) - if vec.shape[0] == 1 and bs > 1: - vec = repeat(vec, "1 ... -> bs ...", bs=bs) - - return { - "img": img, - "img_ids": img_ids.to(img.device), - "txt": txt.to(img.device), - "txt_ids": txt_ids.to(img.device), - "vec": vec.to(img.device), - } - - def time_shift(mu: float, sigma: float, t: Tensor): return math.exp(mu) / (math.exp(mu) + (1 / t - 1) ** sigma) @@ -98,39 +60,6 @@ def get_schedule( return timesteps.tolist() -def denoise( - model: Flux, - # model input - img: Tensor, - img_ids: Tensor, - txt: Tensor, - txt_ids: Tensor, - vec: Tensor, - # sampling parameters - timesteps: list[float], - step_callback: Callable[[], None], - guidance: float = 4.0, -): - # guidance_vec is ignored for schnell. - guidance_vec = torch.full((img.shape[0],), guidance, device=img.device, dtype=img.dtype) - for t_curr, t_prev in tqdm(list(zip(timesteps[:-1], timesteps[1:], strict=True))): - t_vec = torch.full((img.shape[0],), t_curr, dtype=img.dtype, device=img.device) - pred = model( - img=img, - img_ids=img_ids, - txt=txt, - txt_ids=txt_ids, - y=vec, - timesteps=t_vec, - guidance=guidance_vec, - ) - - img = img + (t_prev - t_curr) * pred - step_callback() - - return img - - def unpack(x: Tensor, height: int, width: int) -> Tensor: return rearrange( x, @@ -142,21 +71,34 @@ def unpack(x: Tensor, height: int, width: int) -> Tensor: ) -def prepare_latent_img_patches(latent_img: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]: +def pack(x: Tensor) -> Tensor: + # Pixel unshuffle with a scale of 2, and flatten the height/width dimensions to get an array of patches. + return rearrange(x, "b c (h ph) (w pw) -> b (h w) (c ph pw)", ph=2, pw=2) + + +def generate_img_ids(h: int, w: int, batch_size: int, device: torch.device, dtype: torch.dtype) -> Tensor: + img_ids = torch.zeros(h // 2, w // 2, 3, device=device, dtype=dtype) + img_ids[..., 1] = img_ids[..., 1] + torch.arange(h // 2, device=device, dtype=dtype)[:, None] + img_ids[..., 2] = img_ids[..., 2] + torch.arange(w // 2, device=device, dtype=dtype)[None, :] + img_ids = repeat(img_ids, "h w c -> b (h w) c", b=batch_size) + return img_ids + + +def prepare_latent_img_patches(img: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]: """Convert an input image in latent space to patches for diffusion. This implementation was extracted from: https://github.com/black-forest-labs/flux/blob/c00d7c60b085fce8058b9df845e036090873f2ce/src/flux/sampling.py#L32 + Args: + img (torch.Tensor): Input image in latent space. + Returns: tuple[Tensor, Tensor]: (img, img_ids), as defined in the original flux repo. """ - bs, c, h, w = latent_img.shape + bs, c, h, w = img.shape - # Pixel unshuffle with a scale of 2, and flatten the height/width dimensions to get an array of patches. - img = rearrange(latent_img, "b c (h ph) (w pw) -> b (h w) (c ph pw)", ph=2, pw=2) - if img.shape[0] == 1 and bs > 1: - img = repeat(img, "1 ... -> bs ...", bs=bs) + img = pack(img) # Generate patch position ids. img_ids = torch.zeros(h // 2, w // 2, 3, device=img.device, dtype=img.dtype) From dd99ed28e0c4b7197f7692fcb3096f1f0b41b720 Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Thu, 29 Aug 2024 21:12:51 +0000 Subject: [PATCH 09/20] Split FLUX VAE encoding out into its own node from ImageToLatentsInvocation. --- invokeai/app/invocations/flux_vae_encode.py | 67 ++++++++++++++++++++ invokeai/app/invocations/image_to_latents.py | 43 +------------ 2 files changed, 69 insertions(+), 41 deletions(-) create mode 100644 invokeai/app/invocations/flux_vae_encode.py diff --git a/invokeai/app/invocations/flux_vae_encode.py b/invokeai/app/invocations/flux_vae_encode.py new file mode 100644 index 00000000000..f69b421a914 --- /dev/null +++ b/invokeai/app/invocations/flux_vae_encode.py @@ -0,0 +1,67 @@ +import einops +import torch + +from invokeai.app.invocations.baseinvocation import BaseInvocation, invocation +from invokeai.app.invocations.fields import ( + FieldDescriptions, + ImageField, + Input, + InputField, +) +from invokeai.app.invocations.model import VAEField +from invokeai.app.invocations.primitives import LatentsOutput +from invokeai.app.services.shared.invocation_context import InvocationContext +from invokeai.backend.flux.modules.autoencoder import AutoEncoder +from invokeai.backend.model_manager import LoadedModel +from invokeai.backend.stable_diffusion.diffusers_pipeline import image_resized_to_grid_as_tensor +from invokeai.backend.util.devices import TorchDevice + + +@invocation( + "flux_vae_encode", + title="FLUX VAE Encode", + tags=["latents", "image", "vae", "i2l", "flux"], + category="latents", + version="1.0.0", +) +class FluxVaeEncodeInvocation(BaseInvocation): + """Encodes an image into latents.""" + + image: ImageField = InputField( + description="The image to encode.", + ) + vae: VAEField = InputField( + description=FieldDescriptions.vae, + input=Input.Connection, + ) + + @staticmethod + def vae_encode(vae_info: LoadedModel, image_tensor: torch.Tensor) -> torch.Tensor: + # TODO(ryand): Expose seed parameter at the invocation level. + # TODO(ryand): Write a util function for generating random tensors that is consistent across devices / dtypes. + # There's a starting point in get_noise(...), but it needs to be extracted and generalized. This function + # should be used for VAE encode sampling. + generator = torch.Generator(device=TorchDevice.choose_torch_device()).manual_seed(0) + with vae_info as vae: + assert isinstance(vae, AutoEncoder) + image_tensor = image_tensor.to( + device=TorchDevice.choose_torch_device(), dtype=TorchDevice.choose_torch_dtype() + ) + latents = vae.encode(image_tensor, sample=True, generator=generator) + return latents + + @torch.no_grad() + def invoke(self, context: InvocationContext) -> LatentsOutput: + image = context.images.get_pil(self.image.image_name) + + vae_info = context.models.load(self.vae.vae) + + image_tensor = image_resized_to_grid_as_tensor(image.convert("RGB")) + if image_tensor.dim() == 3: + image_tensor = einops.rearrange(image_tensor, "c h w -> 1 c h w") + + latents = self.vae_encode(vae_info=vae_info, image_tensor=image_tensor) + + latents = latents.to("cpu") + name = context.tensors.save(tensor=latents) + return LatentsOutput.build(latents_name=name, latents=latents, seed=None) diff --git a/invokeai/app/invocations/image_to_latents.py b/invokeai/app/invocations/image_to_latents.py index 99a92d98de7..dadd8bb3a10 100644 --- a/invokeai/app/invocations/image_to_latents.py +++ b/invokeai/app/invocations/image_to_latents.py @@ -23,12 +23,9 @@ from invokeai.app.invocations.model import VAEField from invokeai.app.invocations.primitives import LatentsOutput from invokeai.app.services.shared.invocation_context import InvocationContext -from invokeai.backend.flux.modules.autoencoder import AutoEncoder from invokeai.backend.model_manager import LoadedModel -from invokeai.backend.model_manager.config import BaseModelType from invokeai.backend.stable_diffusion.diffusers_pipeline import image_resized_to_grid_as_tensor from invokeai.backend.stable_diffusion.vae_tiling import patch_vae_tiling_params -from invokeai.backend.util.devices import TorchDevice @invocation( @@ -36,7 +33,7 @@ title="Image to Latents", tags=["latents", "image", "vae", "i2l"], category="latents", - version="1.2.0", + version="1.1.0", ) class ImageToLatentsInvocation(BaseInvocation): """Encodes an image into latents.""" @@ -55,22 +52,7 @@ class ImageToLatentsInvocation(BaseInvocation): fp32: bool = InputField(default=DEFAULT_PRECISION == torch.float32, description=FieldDescriptions.fp32) @staticmethod - def vae_encode_flux(vae_info: LoadedModel, image_tensor: torch.Tensor) -> torch.Tensor: - # TODO(ryand): Expose seed parameter at the invocation level. - # TODO(ryand): Write a util function for generating random tensors that is consistent across devices / dtypes. - # There's a starting point in get_noise(...), but it needs to be extracted and generalized. This function - # should be used for VAE encode sampling. - generator = torch.Generator(device=TorchDevice.choose_torch_device()).manual_seed(0) - with vae_info as vae: - assert isinstance(vae, AutoEncoder) - image_tensor = image_tensor.to( - device=TorchDevice.choose_torch_device(), dtype=TorchDevice.choose_torch_dtype() - ) - latents = vae.encode(image_tensor, sample=True, generator=generator) - return latents - - @staticmethod - def vae_encode_stable_diffusion( + def vae_encode( vae_info: LoadedModel, upcast: bool, tiled: bool, image_tensor: torch.Tensor, tile_size: int = 0 ) -> torch.Tensor: with vae_info as vae: @@ -125,27 +107,6 @@ def vae_encode_stable_diffusion( return latents - @staticmethod - def vae_encode( - vae_info: LoadedModel, upcast: bool, tiled: bool, image_tensor: torch.Tensor, tile_size: int = 0 - ) -> torch.Tensor: - if vae_info.config.base == BaseModelType.Flux: - if upcast: - raise NotImplementedError("FLUX VAE encode does not currently support upcast=True.") - if tiled: - raise NotImplementedError("FLUX VAE encode does not currently support tiled=True.") - return ImageToLatentsInvocation.vae_encode_flux(vae_info=vae_info, image_tensor=image_tensor) - elif vae_info.config.base in [ - BaseModelType.StableDiffusion1, - BaseModelType.StableDiffusion2, - BaseModelType.StableDiffusionXL, - ]: - return ImageToLatentsInvocation.vae_encode_stable_diffusion( - vae_info=vae_info, upcast=upcast, tiled=tiled, image_tensor=image_tensor, tile_size=tile_size - ) - else: - raise ValueError(f"Unsupported VAE base type: '{vae_info.config.base}'") - @torch.no_grad() def invoke(self, context: InvocationContext) -> LatentsOutput: image = context.images.get_pil(self.image.image_name) From 278bba499e99c7045cdbfead42b1b7a930fd764e Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Thu, 29 Aug 2024 21:19:50 +0000 Subject: [PATCH 10/20] Split FLUX VAE decoding out into its own node from LatentsToImageInvocation. --- invokeai/app/invocations/flux_vae_decode.py | 60 ++++++++++++++++++++ invokeai/app/invocations/latents_to_image.py | 44 ++------------ 2 files changed, 65 insertions(+), 39 deletions(-) create mode 100644 invokeai/app/invocations/flux_vae_decode.py diff --git a/invokeai/app/invocations/flux_vae_decode.py b/invokeai/app/invocations/flux_vae_decode.py new file mode 100644 index 00000000000..54d9b57f13f --- /dev/null +++ b/invokeai/app/invocations/flux_vae_decode.py @@ -0,0 +1,60 @@ +import torch +from einops import rearrange +from PIL import Image + +from invokeai.app.invocations.baseinvocation import BaseInvocation, invocation +from invokeai.app.invocations.fields import ( + FieldDescriptions, + Input, + InputField, + LatentsField, + WithBoard, + WithMetadata, +) +from invokeai.app.invocations.model import VAEField +from invokeai.app.invocations.primitives import ImageOutput +from invokeai.app.services.shared.invocation_context import InvocationContext +from invokeai.backend.flux.modules.autoencoder import AutoEncoder +from invokeai.backend.model_manager.load.load_base import LoadedModel +from invokeai.backend.util.devices import TorchDevice + + +@invocation( + "flux_vae_decode", + title="FLUX VAE Decode", + tags=["latents", "image", "vae", "l2i", "flux"], + category="latents", + version="1.0.0", +) +class FluxVaeDecodeInvocation(BaseInvocation, WithMetadata, WithBoard): + """Generates an image from latents.""" + + latents: LatentsField = InputField( + description=FieldDescriptions.latents, + input=Input.Connection, + ) + vae: VAEField = InputField( + description=FieldDescriptions.vae, + input=Input.Connection, + ) + + def _vae_decode(self, vae_info: LoadedModel, latents: torch.Tensor) -> Image.Image: + with vae_info as vae: + assert isinstance(vae, AutoEncoder) + latents = latents.to(device=TorchDevice.choose_torch_device(), dtype=TorchDevice.choose_torch_dtype()) + img = vae.decode(latents) + + img = img.clamp(-1, 1) + img = rearrange(img[0], "c h w -> h w c") # noqa: F821 + img_pil = Image.fromarray((127.5 * (img + 1.0)).byte().cpu().numpy()) + return img_pil + + @torch.no_grad() + def invoke(self, context: InvocationContext) -> ImageOutput: + latents = context.tensors.load(self.latents.latents_name) + vae_info = context.models.load(self.vae.vae) + image = self._vae_decode(vae_info=vae_info, latents=latents) + + TorchDevice.empty_cache() + image_dto = context.images.save(image=image) + return ImageOutput.build(image_dto) diff --git a/invokeai/app/invocations/latents_to_image.py b/invokeai/app/invocations/latents_to_image.py index 7c7fdf07c7e..6d359e82fd1 100644 --- a/invokeai/app/invocations/latents_to_image.py +++ b/invokeai/app/invocations/latents_to_image.py @@ -10,8 +10,6 @@ ) from diffusers.models.autoencoders.autoencoder_kl import AutoencoderKL from diffusers.models.autoencoders.autoencoder_tiny import AutoencoderTiny -from einops import rearrange -from PIL import Image from invokeai.app.invocations.baseinvocation import BaseInvocation, invocation from invokeai.app.invocations.constants import DEFAULT_PRECISION, LATENT_SCALE_FACTOR @@ -26,9 +24,6 @@ from invokeai.app.invocations.model import VAEField from invokeai.app.invocations.primitives import ImageOutput from invokeai.app.services.shared.invocation_context import InvocationContext -from invokeai.backend.flux.modules.autoencoder import AutoEncoder -from invokeai.backend.model_manager.config import BaseModelType -from invokeai.backend.model_manager.load.load_base import LoadedModel from invokeai.backend.stable_diffusion.extensions.seamless import SeamlessExt from invokeai.backend.stable_diffusion.vae_tiling import patch_vae_tiling_params from invokeai.backend.util.devices import TorchDevice @@ -39,7 +34,7 @@ title="Latents to Image", tags=["latents", "image", "vae", "l2i"], category="latents", - version="1.4.0", + version="1.3.0", ) class LatentsToImageInvocation(BaseInvocation, WithMetadata, WithBoard): """Generates an image from latents.""" @@ -58,7 +53,10 @@ class LatentsToImageInvocation(BaseInvocation, WithMetadata, WithBoard): tile_size: int = InputField(default=0, multiple_of=8, description=FieldDescriptions.vae_tile_size) fp32: bool = InputField(default=DEFAULT_PRECISION == torch.float32, description=FieldDescriptions.fp32) - def _vae_decode_stable_diffusion(self, vae_info: LoadedModel, latents: torch.Tensor) -> Image.Image: + def invoke(self, context: InvocationContext) -> ImageOutput: + latents = context.tensors.load(self.latents.latents_name) + + vae_info = context.models.load(self.vae.vae) assert isinstance(vae_info.model, (AutoencoderKL, AutoencoderTiny)) with SeamlessExt.static_patch_model(vae_info.model, self.vae.seamless_axes), vae_info as vae: assert isinstance(vae, (AutoencoderKL, AutoencoderTiny)) @@ -114,38 +112,6 @@ def _vae_decode_stable_diffusion(self, vae_info: LoadedModel, latents: torch.Ten np_image = image.cpu().permute(0, 2, 3, 1).float().numpy() image = VaeImageProcessor.numpy_to_pil(np_image)[0] - return image - - def _vae_decode_flux(self, vae_info: LoadedModel, latents: torch.Tensor) -> Image.Image: - with vae_info as vae: - assert isinstance(vae, AutoEncoder) - latents = latents.to(device=TorchDevice.choose_torch_device(), dtype=TorchDevice.choose_torch_dtype()) - img = vae.decode(latents) - - img = img.clamp(-1, 1) - img = rearrange(img[0], "c h w -> h w c") # noqa: F821 - img_pil = Image.fromarray((127.5 * (img + 1.0)).byte().cpu().numpy()) - return img_pil - - @torch.no_grad() - def invoke(self, context: InvocationContext) -> ImageOutput: - latents = context.tensors.load(self.latents.latents_name) - - vae_info = context.models.load(self.vae.vae) - if vae_info.config.base == BaseModelType.Flux: - if self.fp32: - raise NotImplementedError("FLUX VAE decode does not currently support fp32=True.") - if self.tiled: - raise NotImplementedError("FLUX VAE decode does not currently support tiled=True.") - image = self._vae_decode_flux(vae_info=vae_info, latents=latents) - elif vae_info.config.base in [ - BaseModelType.StableDiffusion1, - BaseModelType.StableDiffusion2, - BaseModelType.StableDiffusionXL, - ]: - image = self._vae_decode_stable_diffusion(vae_info=vae_info, latents=latents) - else: - raise ValueError(f"Unsupported VAE base type: '{vae_info.config.base}'") TorchDevice.empty_cache() From 8292f6cd42829faea910ea6384ddd6edd644e59a Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Fri, 30 Aug 2024 14:46:04 +0000 Subject: [PATCH 11/20] Code cleanup and documentation around FLUX inpainting. --- .../app/invocations/flux_text_to_image.py | 116 ++++++++++-------- invokeai/backend/flux/denoise.py | 18 +-- invokeai/backend/flux/inpaint.py | 15 --- invokeai/backend/flux/inpaint_extension.py | 35 ++++++ invokeai/backend/flux/sampling_utils.py | 48 +++----- 5 files changed, 124 insertions(+), 108 deletions(-) delete mode 100644 invokeai/backend/flux/inpaint.py create mode 100644 invokeai/backend/flux/inpaint_extension.py diff --git a/invokeai/app/invocations/flux_text_to_image.py b/invokeai/app/invocations/flux_text_to_image.py index 03a09652760..68b46b11a7e 100644 --- a/invokeai/app/invocations/flux_text_to_image.py +++ b/invokeai/app/invocations/flux_text_to_image.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import Callable, Optional import torch import torchvision.transforms as tv_transforms @@ -20,6 +20,7 @@ from invokeai.app.services.session_processor.session_processor_common import CanceledException from invokeai.app.services.shared.invocation_context import InvocationContext from invokeai.backend.flux.denoise import denoise +from invokeai.backend.flux.inpaint_extension import InpaintExtension from invokeai.backend.flux.model import Flux from invokeai.backend.flux.sampling_utils import ( generate_img_ids, @@ -31,8 +32,6 @@ from invokeai.backend.stable_diffusion.diffusion.conditioning_data import FLUXConditioningInfo from invokeai.backend.util.devices import TorchDevice -EPS = 1e-6 - @invocation( "flux_text_to_image", @@ -51,6 +50,7 @@ class FluxTextToImageInvocation(BaseInvocation, WithMetadata, WithBoard): description=FieldDescriptions.latents, input=Input.Connection, ) + # denoise_mask is used for image-to-image inpainting. Only the masked region is modified. denoise_mask: Optional[DenoiseMaskField] = InputField( default=None, description=FieldDescriptions.denoise_mask, @@ -122,6 +122,7 @@ def _run_diffusion( transformer_info = context.models.load(self.transformer.transformer) is_schnell = "schnell" in transformer_info.config.config_path + # Calculate the timestep schedule. image_seq_len = noise.shape[-1] * noise.shape[-2] // 4 timesteps = get_schedule( num_steps=self.num_steps, @@ -130,7 +131,7 @@ def _run_diffusion( ) # Prepare input latent image. - if self.denoising_start > EPS: + if self.denoising_start > 1e-5: # If denoising_start > 0, we are doing image-to-image. if init_latents is None: raise ValueError("latents must be provided if denoising_start > 0.") @@ -144,16 +145,10 @@ def _run_diffusion( t_0 = timesteps[0] x = t_0 * noise + (1.0 - t_0) * init_latents else: - # We are not doing image-to-image, so we are starting from noise. + # We are not doing image-to-image, so start from noise. x = noise - # Prepare inpaint mask. inpaint_mask = self._prep_inpaint_mask(context, x) - if inpaint_mask is not None: - assert init_latents is not None - # Expand the inpaint mask to the same shape as the init_latents so that when we pack inpaint_mask it lines - # up with the init_latents. - inpaint_mask = inpaint_mask.expand_as(init_latents) b, _c, h, w = x.shape img_ids = generate_img_ids(h=h, w=w, batch_size=b, device=x.device, dtype=x.dtype) @@ -167,41 +162,22 @@ def _run_diffusion( noise = pack(noise) x = pack(x) - # Verify that we calculated the image_seq_len correctly. + # Now that we have 'packed' the latent tensors, verify that we calculated the image_seq_len correctly. assert image_seq_len == x.shape[1] + # Prepare inpaint extension. + inpaint_extension: InpaintExtension | None = None + if inpaint_mask is not None: + assert init_latents is not None + inpaint_extension = InpaintExtension( + init_latents=init_latents, + inpaint_mask=inpaint_mask, + noise=noise, + ) + with transformer_info as transformer: assert isinstance(transformer, Flux) - def step_callback() -> None: - if context.util.is_canceled(): - raise CanceledException - - # TODO: Make this look like the image before re-enabling - # latent_image = unpack(img.float(), self.height, self.width) - # latent_image = latent_image.squeeze() # Remove unnecessary dimensions - # flattened_tensor = latent_image.reshape(-1) # Flatten to shape [48*128*128] - - # # Create a new tensor of the required shape [255, 255, 3] - # latent_image = flattened_tensor[: 255 * 255 * 3].reshape(255, 255, 3) # Reshape to RGB format - - # # Convert to a NumPy array and then to a PIL Image - # image = Image.fromarray(latent_image.cpu().numpy().astype(np.uint8)) - - # (width, height) = image.size - # width *= 8 - # height *= 8 - - # dataURL = image_to_dataURL(image, image_format="JPEG") - - # # TODO: move this whole function to invocation context to properly reference these variables - # context._services.events.emit_invocation_denoise_progress( - # context._data.queue_item, - # context._data.invocation, - # state, - # ProgressImage(dataURL=dataURL, width=width, height=height), - # ) - x = denoise( model=transformer, img=x, @@ -210,29 +186,35 @@ def step_callback() -> None: txt_ids=txt_ids, vec=clip_embeddings, timesteps=timesteps, - step_callback=step_callback, + step_callback=self._build_step_callback(context), guidance=self.guidance, - init_latents=init_latents, - noise=noise, - inpaint_mask=inpaint_mask, + inpaint_extension=inpaint_extension, ) x = unpack(x.float(), self.height, self.width) - return x def _prep_inpaint_mask(self, context: InvocationContext, latents: torch.Tensor) -> torch.Tensor | None: """Prepare the inpaint mask. - Loads the mask, resizes if necessary, casts to same device/dtype as latents. + - Loads the mask + - Resizes if necessary + - Casts to same device/dtype as latents + - Expands mask to the same shape as latents so that they line up after 'packing' + + Args: + context (InvocationContext): The invocation context, for loading the inpaint mask. + latents (torch.Tensor): A latent image tensor. In 'unpacked' format. Used to determine the target shape, + device, and dtype for the inpaint mask. Returns: - tuple[torch.Tensor | None, bool]: (mask, is_gradient_mask) + torch.Tensor | None: Inpaint mask. """ if self.denoise_mask is None: return None mask = context.tensors.load(self.denoise_mask.mask_name) + _, _, latent_height, latent_width = latents.shape mask = tv_resize( img=mask, @@ -240,5 +222,41 @@ def _prep_inpaint_mask(self, context: InvocationContext, latents: torch.Tensor) interpolation=tv_transforms.InterpolationMode.BILINEAR, antialias=False, ) + mask = mask.to(device=latents.device, dtype=latents.dtype) - return mask + + # Expand the inpaint mask to the same shape as `latents` so that when we 'pack' `mask` it lines up with + # `latents`. + return mask.expand_as(latents) + + def _build_step_callback(self, context: InvocationContext) -> Callable[[], None]: + def step_callback() -> None: + if context.util.is_canceled(): + raise CanceledException + + # TODO: Make this look like the image before re-enabling + # latent_image = unpack(img.float(), self.height, self.width) + # latent_image = latent_image.squeeze() # Remove unnecessary dimensions + # flattened_tensor = latent_image.reshape(-1) # Flatten to shape [48*128*128] + + # # Create a new tensor of the required shape [255, 255, 3] + # latent_image = flattened_tensor[: 255 * 255 * 3].reshape(255, 255, 3) # Reshape to RGB format + + # # Convert to a NumPy array and then to a PIL Image + # image = Image.fromarray(latent_image.cpu().numpy().astype(np.uint8)) + + # (width, height) = image.size + # width *= 8 + # height *= 8 + + # dataURL = image_to_dataURL(image, image_format="JPEG") + + # # TODO: move this whole function to invocation context to properly reference these variables + # context._services.events.emit_invocation_denoise_progress( + # context._data.queue_item, + # context._data.invocation, + # state, + # ProgressImage(dataURL=dataURL, width=width, height=height), + # ) + + return step_callback diff --git a/invokeai/backend/flux/denoise.py b/invokeai/backend/flux/denoise.py index 103fcd907bc..4fb9a792dda 100644 --- a/invokeai/backend/flux/denoise.py +++ b/invokeai/backend/flux/denoise.py @@ -3,7 +3,7 @@ import torch from tqdm import tqdm -from invokeai.backend.flux.inpaint import merge_intermediate_latents_with_init_latents +from invokeai.backend.flux.inpaint_extension import InpaintExtension from invokeai.backend.flux.model import Flux @@ -19,10 +19,7 @@ def denoise( timesteps: list[float], step_callback: Callable[[], None], guidance: float, - # For inpainting: - init_latents: torch.Tensor | None, - noise: torch.Tensor, - inpaint_mask: torch.Tensor | None, + inpaint_extension: InpaintExtension | None, ): # guidance_vec is ignored for schnell. guidance_vec = torch.full((img.shape[0],), guidance, device=img.device, dtype=img.dtype) @@ -40,15 +37,8 @@ def denoise( img = img + (t_prev - t_curr) * pred - if inpaint_mask is not None: - assert init_latents is not None - img = merge_intermediate_latents_with_init_latents( - init_latents=init_latents, - intermediate_latents=img, - timestep=t_prev, - noise=noise, - inpaint_mask=inpaint_mask, - ) + if inpaint_extension is not None: + img = inpaint_extension.merge_intermediate_latents_with_init_latents(img, t_prev) step_callback() diff --git a/invokeai/backend/flux/inpaint.py b/invokeai/backend/flux/inpaint.py deleted file mode 100644 index 3bebb9c3e64..00000000000 --- a/invokeai/backend/flux/inpaint.py +++ /dev/null @@ -1,15 +0,0 @@ -import torch - - -def merge_intermediate_latents_with_init_latents( - init_latents: torch.Tensor, - intermediate_latents: torch.Tensor, - timestep: float, - noise: torch.Tensor, - inpaint_mask: torch.Tensor, -) -> torch.Tensor: - # Noise the init_latents for the current timestep. - noised_init_latents = noise * timestep + (1.0 - timestep) * init_latents - - # Merge the intermediate_latents with the noised_init_latents using the inpaint_mask. - return intermediate_latents * inpaint_mask + noised_init_latents * (1.0 - inpaint_mask) diff --git a/invokeai/backend/flux/inpaint_extension.py b/invokeai/backend/flux/inpaint_extension.py new file mode 100644 index 00000000000..b6c634a3b5c --- /dev/null +++ b/invokeai/backend/flux/inpaint_extension.py @@ -0,0 +1,35 @@ +import torch + + +class InpaintExtension: + """A class for managing inpainting with FLUX.""" + + def __init__(self, init_latents: torch.Tensor, inpaint_mask: torch.Tensor, noise: torch.Tensor): + """Initialize InpaintExtension. + + Args: + init_latents (torch.Tensor): The initial latents (i.e. un-noised at timestep 0). In 'packed' format. + inpaint_mask (torch.Tensor): A mask specifying which elements to inpaint. Range [0, 1]. Values of 1 will be + re-generated. Values of 0 will remain unchanged. Values between 0 and 1 can be used to blend the + inpainted region with the background. In 'packed' format. + noise (torch.Tensor): The noise tensor used to noise the init_latents. In 'packed' format. + """ + assert init_latents.shape == inpaint_mask.shape == noise.shape + self._init_latents = init_latents + self._inpaint_mask = inpaint_mask + self._noise = noise + + def merge_intermediate_latents_with_init_latents( + self, intermediate_latents: torch.Tensor, timestep: float + ) -> torch.Tensor: + """Merge the intermediate latents with the initial latents for the current timestep using the inpaint mask. I.e. + update the intermediate latents to keep the regions that are not being inpainted on the correct noise + trajectory. + + This function should be called after each denoising step. + """ + # Noise the init latents for the current timestep. + noised_init_latents = self._noise * timestep + (1.0 - timestep) * self._init_latents + + # Merge the intermediate latents with the noised_init_latents using the inpaint_mask. + return intermediate_latents * self._inpaint_mask + noised_init_latents * (1.0 - self._inpaint_mask) diff --git a/invokeai/backend/flux/sampling_utils.py b/invokeai/backend/flux/sampling_utils.py index 9d710015afc..4be15c491f5 100644 --- a/invokeai/backend/flux/sampling_utils.py +++ b/invokeai/backend/flux/sampling_utils.py @@ -5,7 +5,6 @@ import torch from einops import rearrange, repeat -from torch import Tensor def get_noise( @@ -31,7 +30,7 @@ def get_noise( ).to(device=device, dtype=dtype) -def time_shift(mu: float, sigma: float, t: Tensor): +def time_shift(mu: float, sigma: float, t: torch.Tensor) -> torch.Tensor: return math.exp(mu) / (math.exp(mu) + (1 / t - 1) ** sigma) @@ -60,7 +59,8 @@ def get_schedule( return timesteps.tolist() -def unpack(x: Tensor, height: int, width: int) -> Tensor: +def unpack(x: torch.Tensor, height: int, width: int) -> torch.Tensor: + """Unpack flat array of patch embeddings to latent image.""" return rearrange( x, "b (h w) (c ph pw) -> b c (h ph) (w pw)", @@ -71,39 +71,27 @@ def unpack(x: Tensor, height: int, width: int) -> Tensor: ) -def pack(x: Tensor) -> Tensor: +def pack(x: torch.Tensor) -> torch.Tensor: + """Pack latent image to flattented array of patch embeddings.""" # Pixel unshuffle with a scale of 2, and flatten the height/width dimensions to get an array of patches. return rearrange(x, "b c (h ph) (w pw) -> b (h w) (c ph pw)", ph=2, pw=2) -def generate_img_ids(h: int, w: int, batch_size: int, device: torch.device, dtype: torch.dtype) -> Tensor: - img_ids = torch.zeros(h // 2, w // 2, 3, device=device, dtype=dtype) - img_ids[..., 1] = img_ids[..., 1] + torch.arange(h // 2, device=device, dtype=dtype)[:, None] - img_ids[..., 2] = img_ids[..., 2] + torch.arange(w // 2, device=device, dtype=dtype)[None, :] - img_ids = repeat(img_ids, "h w c -> b (h w) c", b=batch_size) - return img_ids - - -def prepare_latent_img_patches(img: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]: - """Convert an input image in latent space to patches for diffusion. - - This implementation was extracted from: - https://github.com/black-forest-labs/flux/blob/c00d7c60b085fce8058b9df845e036090873f2ce/src/flux/sampling.py#L32 +def generate_img_ids(h: int, w: int, batch_size: int, device: torch.device, dtype: torch.dtype) -> torch.Tensor: + """Generate tensor of image position ids. Args: - img (torch.Tensor): Input image in latent space. + h (int): Height of image in latent space. + w (int): Width of image in latent space. + batch_size (int): Batch size. + device (torch.device): Device. + dtype (torch.dtype): dtype. Returns: - tuple[Tensor, Tensor]: (img, img_ids), as defined in the original flux repo. + torch.Tensor: Image position ids. """ - bs, c, h, w = img.shape - - img = pack(img) - - # Generate patch position ids. - img_ids = torch.zeros(h // 2, w // 2, 3, device=img.device, dtype=img.dtype) - img_ids[..., 1] = img_ids[..., 1] + torch.arange(h // 2, device=img.device, dtype=img.dtype)[:, None] - img_ids[..., 2] = img_ids[..., 2] + torch.arange(w // 2, device=img.device, dtype=img.dtype)[None, :] - img_ids = repeat(img_ids, "h w c -> b (h w) c", b=bs) - - return img, img_ids + img_ids = torch.zeros(h // 2, w // 2, 3, device=device, dtype=dtype) + img_ids[..., 1] = img_ids[..., 1] + torch.arange(h // 2, device=device, dtype=dtype)[:, None] + img_ids[..., 2] = img_ids[..., 2] + torch.arange(w // 2, device=device, dtype=dtype)[None, :] + img_ids = repeat(img_ids, "h w c -> b (h w) c", b=batch_size) + return img_ids From 763ef06c18f68f9f5fc7897679a42b3040a84821 Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Fri, 30 Aug 2024 15:09:55 +0000 Subject: [PATCH 12/20] Use the existence of initial latents to decide whether we are doing image-to-image in the FLUX denoising node. Previously we were using the denoising_start value, but in some cases with an inpaintin mask you may want to run image-to-image from densoising_start=0. --- invokeai/app/invocations/flux_text_to_image.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/invokeai/app/invocations/flux_text_to_image.py b/invokeai/app/invocations/flux_text_to_image.py index 68b46b11a7e..613145b5b27 100644 --- a/invokeai/app/invocations/flux_text_to_image.py +++ b/invokeai/app/invocations/flux_text_to_image.py @@ -131,10 +131,14 @@ def _run_diffusion( ) # Prepare input latent image. - if self.denoising_start > 1e-5: - # If denoising_start > 0, we are doing image-to-image. - if init_latents is None: - raise ValueError("latents must be provided if denoising_start > 0.") + if init_latents is not None: + # If init_latents is provided, we are doing image-to-image. + + if is_schnell: + context.logger.warning( + "Running image-to-image with a FLUX schnell model. This is not recommended. The results are likely " + "to be poor. Consider using a FLUX dev model instead." + ) # Clip the timesteps schedule based on denoising_start. # TODO(ryand): Should we apply denoising_start in timestep-space rather than timestep-index-space? @@ -145,7 +149,10 @@ def _run_diffusion( t_0 = timesteps[0] x = t_0 * noise + (1.0 - t_0) * init_latents else: - # We are not doing image-to-image, so start from noise. + # init_latents are not provided, so we are not doing image-to-image (i.e. we are starting from pure noise). + if self.denoising_start > 1e-5: + raise ValueError("denoising_start should be 0 when initial latents are not provided.") + x = noise inpaint_mask = self._prep_inpaint_mask(context, x) From 2e092a2313cde5e00212416750061ff9816f3ff0 Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Fri, 30 Aug 2024 15:34:56 +0000 Subject: [PATCH 13/20] Rename FluxTextToImageInvocation -> FluxDenoiseInvocation. --- invokeai/app/invocations/flux_text_to_image.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/invokeai/app/invocations/flux_text_to_image.py b/invokeai/app/invocations/flux_text_to_image.py index 613145b5b27..5312ba7fcd6 100644 --- a/invokeai/app/invocations/flux_text_to_image.py +++ b/invokeai/app/invocations/flux_text_to_image.py @@ -34,15 +34,15 @@ @invocation( - "flux_text_to_image", - title="FLUX Text to Image", + "flux_denoise", + title="FLUX Denoise", tags=["image", "flux"], category="image", - version="2.0.0", + version="1.0.0", classification=Classification.Prototype, ) -class FluxTextToImageInvocation(BaseInvocation, WithMetadata, WithBoard): - """Text-to-image generation using a FLUX model.""" +class FluxDenoiseInvocation(BaseInvocation, WithMetadata, WithBoard): + """Run denoising process with a FLUX transformer model.""" # If latents is provided, this means we are doing image-to-image. latents: Optional[LatentsField] = InputField( From 2313f326dfb88ee2442664773be2f0606ac6fcd7 Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Fri, 30 Aug 2024 19:13:20 +0000 Subject: [PATCH 14/20] Add denoise_end param to FluxDenoiseInvocation. --- .../app/invocations/flux_text_to_image.py | 15 ++++--- invokeai/backend/flux/sampling_utils.py | 38 +++++++++++++++++ tests/backend/flux/test_sampling_utils.py | 42 +++++++++++++++++++ 3 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 tests/backend/flux/test_sampling_utils.py diff --git a/invokeai/app/invocations/flux_text_to_image.py b/invokeai/app/invocations/flux_text_to_image.py index 5312ba7fcd6..2fbbc549fe4 100644 --- a/invokeai/app/invocations/flux_text_to_image.py +++ b/invokeai/app/invocations/flux_text_to_image.py @@ -23,6 +23,7 @@ from invokeai.backend.flux.inpaint_extension import InpaintExtension from invokeai.backend.flux.model import Flux from invokeai.backend.flux.sampling_utils import ( + clip_timestep_schedule, generate_img_ids, get_noise, get_schedule, @@ -62,6 +63,7 @@ class FluxDenoiseInvocation(BaseInvocation, WithMetadata, WithBoard): le=1, description=FieldDescriptions.denoising_start, ) + denoising_end: float = InputField(default=1.0, ge=0, le=1, description=FieldDescriptions.denoising_end) transformer: TransformerField = InputField( description=FieldDescriptions.flux_model, input=Input.Connection, @@ -130,6 +132,9 @@ def _run_diffusion( shift=not is_schnell, ) + # Clip the timesteps schedule based on denoising_start and denoising_end. + timesteps = clip_timestep_schedule(timesteps, self.denoising_start, self.denoising_end) + # Prepare input latent image. if init_latents is not None: # If init_latents is provided, we are doing image-to-image. @@ -140,11 +145,6 @@ def _run_diffusion( "to be poor. Consider using a FLUX dev model instead." ) - # Clip the timesteps schedule based on denoising_start. - # TODO(ryand): Should we apply denoising_start in timestep-space rather than timestep-index-space? - start_idx = int(self.denoising_start * len(timesteps)) - timesteps = timesteps[start_idx:] - # Noise the orig_latents by the appropriate amount for the first timestep. t_0 = timesteps[0] x = t_0 * noise + (1.0 - t_0) * init_latents @@ -155,6 +155,11 @@ def _run_diffusion( x = noise + # If len(timesteps) == 1, then short-circuit. We are just noising the input latents, but not taking any + # denoising steps. + if len(timesteps) <= 1: + return x + inpaint_mask = self._prep_inpaint_mask(context, x) b, _c, h, w = x.shape diff --git a/invokeai/backend/flux/sampling_utils.py b/invokeai/backend/flux/sampling_utils.py index 4be15c491f5..92c78de01eb 100644 --- a/invokeai/backend/flux/sampling_utils.py +++ b/invokeai/backend/flux/sampling_utils.py @@ -59,6 +59,44 @@ def get_schedule( return timesteps.tolist() +def _find_last_index_ge_val(timesteps: list[float], val: float, eps: float = 1e-6) -> int: + """Find the last index in timesteps that is >= val. + + We use epsilon-close equality to avoid potential floating point errors. + """ + idx = len(list(filter(lambda t: t >= (val - eps), timesteps))) - 1 + assert idx >= 0 + return idx + + +def clip_timestep_schedule(timesteps: list[float], denoising_start: float, denoising_end: float) -> list[float]: + """Clip the timestep schedule to the denoising range. + + Args: + timesteps (list[float]): The original timestep schedule: [1.0, ..., 0.0]. + denoising_start (float): A value in [0, 1] specifying the start of the denoising process. E.g. a value of 0.2 + would mean that the denoising process start at the last timestep in the schedule >= 0.8. + denoising_end (float): A value in [0, 1] specifying the end of the denoising process. E.g. a value of 0.8 would + mean that the denoising process end at the last timestep in the schedule >= 0.2. + + Returns: + list[float]: The clipped timestep schedule. + """ + assert 0.0 <= denoising_start <= 1.0 + assert 0.0 <= denoising_end <= 1.0 + assert denoising_start <= denoising_end + + t_start_val = 1.0 - denoising_start + t_end_val = 1.0 - denoising_end + + t_start_idx = _find_last_index_ge_val(timesteps, t_start_val) + t_end_idx = _find_last_index_ge_val(timesteps, t_end_val) + + clipped_timesteps = timesteps[t_start_idx : t_end_idx + 1] + + return clipped_timesteps + + def unpack(x: torch.Tensor, height: int, width: int) -> torch.Tensor: """Unpack flat array of patch embeddings to latent image.""" return rearrange( diff --git a/tests/backend/flux/test_sampling_utils.py b/tests/backend/flux/test_sampling_utils.py new file mode 100644 index 00000000000..f7264492d54 --- /dev/null +++ b/tests/backend/flux/test_sampling_utils.py @@ -0,0 +1,42 @@ +import pytest +import torch + +from invokeai.backend.flux.sampling_utils import clip_timestep_schedule + + +def float_lists_almost_equal(list1: list[float], list2: list[float], tol: float = 1e-6) -> bool: + return all(abs(a - b) < tol for a, b in zip(list1, list2, strict=True)) + + +@pytest.mark.parametrize( + ["denoising_start", "denoising_end", "expected_timesteps", "raises"], + [ + (0.0, 1.0, [1.0, 0.75, 0.5, 0.25, 0.0], False), # Default case. + (-0.1, 1.0, [], True), # Negative denoising_start should raise. + (0.0, 1.1, [], True), # denoising_end > 1 should raise. + (0.5, 0.0, [], True), # denoising_start > denoising_end should raise. + (0.0, 0.0, [1.0], False), # denoising_end == 0. + (1.0, 1.0, [0.0], False), # denoising_start == 1. + (0.2, 0.8, [1.0, 0.75, 0.5, 0.25], False), # Middle of the schedule. + # If we denoise from 0.0 to x, then from x to 1.0, it is important that denoise_end = x and denoise_start = x + # map to the same timestep. We test this first when x is equal to a timestep, then when it falls between two + # timesteps. + # x = 0.5 + (0.0, 0.5, [1.0, 0.75, 0.5], False), + (0.5, 1.0, [0.5, 0.25, 0.0], False), + # x = 0.3 + (0.0, 0.3, [1.0, 0.75], False), + (0.3, 1.0, [0.75, 0.5, 0.25, 0.0], False), + ], +) +def test_clip_timestep_schedule( + denoising_start: float, denoising_end: float, expected_timesteps: list[float], raises: bool +): + timesteps = torch.linspace(1, 0, 5).tolist() + if raises: + with pytest.raises(AssertionError): + clip_timestep_schedule(timesteps, denoising_start, denoising_end) + else: + assert float_lists_almost_equal( + clip_timestep_schedule(timesteps, denoising_start, denoising_end), expected_timesteps + ) From cfdd5a190050e4cee1d7b1c3a7b7a43f35b76e7f Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Fri, 30 Aug 2024 19:14:11 +0000 Subject: [PATCH 15/20] Rename flux_text_to_image.py -> flex_denoise.py --- .../app/invocations/{flux_text_to_image.py => flux_denoise.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename invokeai/app/invocations/{flux_text_to_image.py => flux_denoise.py} (100%) diff --git a/invokeai/app/invocations/flux_text_to_image.py b/invokeai/app/invocations/flux_denoise.py similarity index 100% rename from invokeai/app/invocations/flux_text_to_image.py rename to invokeai/app/invocations/flux_denoise.py From fb5a24fcc6224816908d13b2d18bbdafd87aae21 Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Fri, 30 Aug 2024 20:00:41 +0000 Subject: [PATCH 16/20] Update default workflows for FLUX. --- .../FLUX Image to Image.json | 397 ++++++++++++++++++ .../default_workflows/Flux Text to Image.json | 266 +++++++----- 2 files changed, 559 insertions(+), 104 deletions(-) create mode 100644 invokeai/app/services/workflow_records/default_workflows/FLUX Image to Image.json diff --git a/invokeai/app/services/workflow_records/default_workflows/FLUX Image to Image.json b/invokeai/app/services/workflow_records/default_workflows/FLUX Image to Image.json new file mode 100644 index 00000000000..20e728b469a --- /dev/null +++ b/invokeai/app/services/workflow_records/default_workflows/FLUX Image to Image.json @@ -0,0 +1,397 @@ +{ + "name": "FLUX Image to Image", + "author": "InvokeAI", + "description": "A simple image-to-image workflow using a FLUX dev model. ", + "version": "1.0.4", + "contact": "", + "tags": "image2image, flux, image-to-image", + "notes": "Prerequisite model downloads: T5 Encoder, CLIP-L Encoder, and FLUX VAE. Quantized and un-quantized versions can be found in the starter models tab within your Model Manager. We recommend using FLUX dev models for image-to-image workflows. The image-to-image performance with FLUX schnell models is poor.", + "exposedFields": [ + { + "nodeId": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", + "fieldName": "model" + }, + { + "nodeId": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", + "fieldName": "prompt" + }, + { + "nodeId": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", + "fieldName": "t5_encoder_model" + }, + { + "nodeId": "ace0258f-67d7-4eee-a218-6fff27065214", + "fieldName": "denoising_start" + }, + { + "nodeId": "ace0258f-67d7-4eee-a218-6fff27065214", + "fieldName": "num_steps" + } + ], + "meta": { + "version": "3.0.0", + "category": "default" + }, + "id": "0a91fc4c-5f93-469c-a6ad-e87bf47b68bf", + "nodes": [ + { + "id": "2981a67c-480f-4237-9384-26b68dbf912b", + "type": "invocation", + "data": { + "id": "2981a67c-480f-4237-9384-26b68dbf912b", + "type": "flux_vae_encode", + "version": "1.0.0", + "label": "", + "notes": "", + "isOpen": true, + "isIntermediate": true, + "useCache": true, + "inputs": { + "image": { + "name": "image", + "label": "" + }, + "vae": { + "name": "vae", + "label": "" + } + } + }, + "position": { + "x": 732.7680166609682, + "y": -24.37398171806909 + } + }, + { + "id": "ace0258f-67d7-4eee-a218-6fff27065214", + "type": "invocation", + "data": { + "id": "ace0258f-67d7-4eee-a218-6fff27065214", + "type": "flux_denoise", + "version": "1.0.0", + "label": "", + "notes": "", + "isOpen": true, + "isIntermediate": true, + "useCache": true, + "inputs": { + "board": { + "name": "board", + "label": "" + }, + "metadata": { + "name": "metadata", + "label": "" + }, + "latents": { + "name": "latents", + "label": "" + }, + "denoise_mask": { + "name": "denoise_mask", + "label": "" + }, + "denoising_start": { + "name": "denoising_start", + "label": "", + "value": 0.04 + }, + "denoising_end": { + "name": "denoising_end", + "label": "", + "value": 1 + }, + "transformer": { + "name": "transformer", + "label": "" + }, + "positive_text_conditioning": { + "name": "positive_text_conditioning", + "label": "" + }, + "width": { + "name": "width", + "label": "", + "value": 1024 + }, + "height": { + "name": "height", + "label": "", + "value": 1024 + }, + "num_steps": { + "name": "num_steps", + "label": "Steps (Recommend 30 for Dev, 4 for Schnell)", + "value": 30 + }, + "guidance": { + "name": "guidance", + "label": "", + "value": 4 + }, + "seed": { + "name": "seed", + "label": "", + "value": 0 + } + } + }, + "position": { + "x": 1182.8836633018684, + "y": -251.38882958913183 + } + }, + { + "id": "7e5172eb-48c1-44db-a770-8fd83e1435d1", + "type": "invocation", + "data": { + "id": "7e5172eb-48c1-44db-a770-8fd83e1435d1", + "type": "flux_vae_decode", + "version": "1.0.0", + "label": "", + "notes": "", + "isOpen": true, + "isIntermediate": false, + "useCache": true, + "inputs": { + "board": { + "name": "board", + "label": "" + }, + "metadata": { + "name": "metadata", + "label": "" + }, + "latents": { + "name": "latents", + "label": "" + }, + "vae": { + "name": "vae", + "label": "" + } + } + }, + "position": { + "x": 1575.5797431839133, + "y": -209.00150975507415 + } + }, + { + "id": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", + "type": "invocation", + "data": { + "id": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", + "type": "flux_model_loader", + "version": "1.0.4", + "label": "", + "notes": "", + "isOpen": true, + "isIntermediate": true, + "useCache": false, + "inputs": { + "model": { + "name": "model", + "label": "Model (dev variant recommended for Image-to-Image)" + }, + "t5_encoder_model": { + "name": "t5_encoder_model", + "label": "" + }, + "clip_embed_model": { + "name": "clip_embed_model", + "label": "", + "value": { + "key": "076fa0b4-6e06-413a-bfca-61ab6f8b26db", + "hash": "blake3:17c19f0ef941c3b7609a9c94a659ca5364de0be364a91d4179f0e39ba17c3b70", + "name": "clip-vit-large-patch14", + "base": "any", + "type": "clip_embed" + } + }, + "vae_model": { + "name": "vae_model", + "label": "", + "value": { + "key": "0bfe1765-2895-4a93-87e3-00277c04545d", + "hash": "blake3:ce21cb76364aa6e2421311cf4a4b5eb052a76c4f1cd207b50703d8978198a068", + "name": "FLUX.1-schnell_ae", + "base": "flux", + "type": "vae" + } + } + } + }, + "position": { + "x": 328.1809894659957, + "y": -90.2241133566946 + } + }, + { + "id": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", + "type": "invocation", + "data": { + "id": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", + "type": "flux_text_encoder", + "version": "1.0.0", + "label": "", + "notes": "", + "isOpen": true, + "isIntermediate": true, + "useCache": true, + "inputs": { + "clip": { + "name": "clip", + "label": "" + }, + "t5_encoder": { + "name": "t5_encoder", + "label": "" + }, + "t5_max_seq_len": { + "name": "t5_max_seq_len", + "label": "T5 Max Seq Len", + "value": 256 + }, + "prompt": { + "name": "prompt", + "label": "", + "value": "a cat wearing a birthday hat" + } + } + }, + "position": { + "x": 745.8823365057267, + "y": -299.60249175851914 + } + }, + { + "id": "4754c534-a5f3-4ad0-9382-7887985e668c", + "type": "invocation", + "data": { + "id": "4754c534-a5f3-4ad0-9382-7887985e668c", + "type": "rand_int", + "version": "1.0.1", + "label": "", + "notes": "", + "isOpen": true, + "isIntermediate": true, + "useCache": false, + "inputs": { + "low": { + "name": "low", + "label": "", + "value": 0 + }, + "high": { + "name": "high", + "label": "", + "value": 2147483647 + } + } + }, + "position": { + "x": 725.834098928012, + "y": 496.2710031089931 + } + } + ], + "edges": [ + { + "id": "reactflow__edge-2981a67c-480f-4237-9384-26b68dbf912bheight-ace0258f-67d7-4eee-a218-6fff27065214height", + "type": "default", + "source": "2981a67c-480f-4237-9384-26b68dbf912b", + "target": "ace0258f-67d7-4eee-a218-6fff27065214", + "sourceHandle": "height", + "targetHandle": "height" + }, + { + "id": "reactflow__edge-2981a67c-480f-4237-9384-26b68dbf912bwidth-ace0258f-67d7-4eee-a218-6fff27065214width", + "type": "default", + "source": "2981a67c-480f-4237-9384-26b68dbf912b", + "target": "ace0258f-67d7-4eee-a218-6fff27065214", + "sourceHandle": "width", + "targetHandle": "width" + }, + { + "id": "reactflow__edge-2981a67c-480f-4237-9384-26b68dbf912blatents-ace0258f-67d7-4eee-a218-6fff27065214latents", + "type": "default", + "source": "2981a67c-480f-4237-9384-26b68dbf912b", + "target": "ace0258f-67d7-4eee-a218-6fff27065214", + "sourceHandle": "latents", + "targetHandle": "latents" + }, + { + "id": "reactflow__edge-f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90vae-2981a67c-480f-4237-9384-26b68dbf912bvae", + "type": "default", + "source": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", + "target": "2981a67c-480f-4237-9384-26b68dbf912b", + "sourceHandle": "vae", + "targetHandle": "vae" + }, + { + "id": "reactflow__edge-ace0258f-67d7-4eee-a218-6fff27065214latents-7e5172eb-48c1-44db-a770-8fd83e1435d1latents", + "type": "default", + "source": "ace0258f-67d7-4eee-a218-6fff27065214", + "target": "7e5172eb-48c1-44db-a770-8fd83e1435d1", + "sourceHandle": "latents", + "targetHandle": "latents" + }, + { + "id": "reactflow__edge-4754c534-a5f3-4ad0-9382-7887985e668cvalue-ace0258f-67d7-4eee-a218-6fff27065214seed", + "type": "default", + "source": "4754c534-a5f3-4ad0-9382-7887985e668c", + "target": "ace0258f-67d7-4eee-a218-6fff27065214", + "sourceHandle": "value", + "targetHandle": "seed" + }, + { + "id": "reactflow__edge-f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90transformer-ace0258f-67d7-4eee-a218-6fff27065214transformer", + "type": "default", + "source": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", + "target": "ace0258f-67d7-4eee-a218-6fff27065214", + "sourceHandle": "transformer", + "targetHandle": "transformer" + }, + { + "id": "reactflow__edge-01f674f8-b3d1-4df1-acac-6cb8e0bfb63cconditioning-ace0258f-67d7-4eee-a218-6fff27065214positive_text_conditioning", + "type": "default", + "source": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", + "target": "ace0258f-67d7-4eee-a218-6fff27065214", + "sourceHandle": "conditioning", + "targetHandle": "positive_text_conditioning" + }, + { + "id": "reactflow__edge-f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90vae-7e5172eb-48c1-44db-a770-8fd83e1435d1vae", + "type": "default", + "source": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", + "target": "7e5172eb-48c1-44db-a770-8fd83e1435d1", + "sourceHandle": "vae", + "targetHandle": "vae" + }, + { + "id": "reactflow__edge-f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90max_seq_len-01f674f8-b3d1-4df1-acac-6cb8e0bfb63ct5_max_seq_len", + "type": "default", + "source": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", + "target": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", + "sourceHandle": "max_seq_len", + "targetHandle": "t5_max_seq_len" + }, + { + "id": "reactflow__edge-f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90t5_encoder-01f674f8-b3d1-4df1-acac-6cb8e0bfb63ct5_encoder", + "type": "default", + "source": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", + "target": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", + "sourceHandle": "t5_encoder", + "targetHandle": "t5_encoder" + }, + { + "id": "reactflow__edge-f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90clip-01f674f8-b3d1-4df1-acac-6cb8e0bfb63cclip", + "type": "default", + "source": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", + "target": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", + "sourceHandle": "clip", + "targetHandle": "clip" + } + ] +} diff --git a/invokeai/app/services/workflow_records/default_workflows/Flux Text to Image.json b/invokeai/app/services/workflow_records/default_workflows/Flux Text to Image.json index 7e392de5faa..1917fd32ed1 100644 --- a/invokeai/app/services/workflow_records/default_workflows/Flux Text to Image.json +++ b/invokeai/app/services/workflow_records/default_workflows/Flux Text to Image.json @@ -1,7 +1,7 @@ { "name": "FLUX Text to Image", "author": "InvokeAI", - "description": "A simple text-to-image workflow using FLUX dev or schnell models. Prerequisite model downloads: T5 Encoder, CLIP-L Encoder, and FLUX VAE. Quantized and un-quantized versions can be found in the starter models tab within your Model Manager. We recommend 4 steps for FLUX schnell models and 30 steps for FLUX dev models.", + "description": "A simple text-to-image workflow using FLUX dev or schnell models.", "version": "1.0.4", "contact": "", "tags": "text2image, flux", @@ -15,13 +15,13 @@ "nodeId": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", "fieldName": "prompt" }, - { - "nodeId": "159bdf1b-79e7-4174-b86e-d40e646964c8", - "fieldName": "num_steps" - }, { "nodeId": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", "fieldName": "t5_encoder_model" + }, + { + "nodeId": "4fe24f07-f906-4f55-ab2c-9beee56ef5bd", + "fieldName": "num_steps" } ], "meta": { @@ -29,6 +29,121 @@ "category": "default" }, "nodes": [ + { + "id": "4fe24f07-f906-4f55-ab2c-9beee56ef5bd", + "type": "invocation", + "data": { + "id": "4fe24f07-f906-4f55-ab2c-9beee56ef5bd", + "type": "flux_denoise", + "version": "1.0.0", + "label": "", + "notes": "", + "isOpen": true, + "isIntermediate": true, + "useCache": true, + "inputs": { + "board": { + "name": "board", + "label": "" + }, + "metadata": { + "name": "metadata", + "label": "" + }, + "latents": { + "name": "latents", + "label": "" + }, + "denoise_mask": { + "name": "denoise_mask", + "label": "" + }, + "denoising_start": { + "name": "denoising_start", + "label": "", + "value": 0 + }, + "denoising_end": { + "name": "denoising_end", + "label": "", + "value": 1 + }, + "transformer": { + "name": "transformer", + "label": "" + }, + "positive_text_conditioning": { + "name": "positive_text_conditioning", + "label": "" + }, + "width": { + "name": "width", + "label": "", + "value": 1024 + }, + "height": { + "name": "height", + "label": "", + "value": 1024 + }, + "num_steps": { + "name": "num_steps", + "label": "Steps (Recommend 30 for Dev, 4 for Schnell)", + "value": 30 + }, + "guidance": { + "name": "guidance", + "label": "", + "value": 4 + }, + "seed": { + "name": "seed", + "label": "", + "value": 0 + } + } + }, + "position": { + "x": 1186.1868226120378, + "y": -214.9459927686657 + } + }, + { + "id": "7e5172eb-48c1-44db-a770-8fd83e1435d1", + "type": "invocation", + "data": { + "id": "7e5172eb-48c1-44db-a770-8fd83e1435d1", + "type": "flux_vae_decode", + "version": "1.0.0", + "label": "", + "notes": "", + "isOpen": true, + "isIntermediate": false, + "useCache": true, + "inputs": { + "board": { + "name": "board", + "label": "" + }, + "metadata": { + "name": "metadata", + "label": "" + }, + "latents": { + "name": "latents", + "label": "" + }, + "vae": { + "name": "vae", + "label": "" + } + } + }, + "position": { + "x": 1575.5797431839133, + "y": -209.00150975507415 + } + }, { "id": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", "type": "invocation", @@ -99,8 +214,8 @@ } }, "position": { - "x": 824.1970602278849, - "y": 146.98251001061735 + "x": 778.4899149328337, + "y": -100.36469216659502 } }, { @@ -129,93 +244,60 @@ } }, "position": { - "x": 822.9899179655476, - "y": 360.9657214885052 - } - }, - { - "id": "159bdf1b-79e7-4174-b86e-d40e646964c8", - "type": "invocation", - "data": { - "id": "159bdf1b-79e7-4174-b86e-d40e646964c8", - "type": "flux_text_to_image", - "version": "1.0.0", - "label": "", - "notes": "", - "isOpen": true, - "isIntermediate": false, - "useCache": true, - "inputs": { - "board": { - "name": "board", - "label": "" - }, - "metadata": { - "name": "metadata", - "label": "" - }, - "transformer": { - "name": "transformer", - "label": "" - }, - "vae": { - "name": "vae", - "label": "" - }, - "positive_text_conditioning": { - "name": "positive_text_conditioning", - "label": "" - }, - "width": { - "name": "width", - "label": "", - "value": 1024 - }, - "height": { - "name": "height", - "label": "", - "value": 1024 - }, - "num_steps": { - "name": "num_steps", - "label": "Steps (Recommend 30 for Dev, 4 for Schnell)", - "value": 30 - }, - "guidance": { - "name": "guidance", - "label": "", - "value": 4 - }, - "seed": { - "name": "seed", - "label": "", - "value": 0 - } - } - }, - "position": { - "x": 1216.3900791301849, - "y": 5.500841807102248 + "x": 800.9667463219505, + "y": 285.8297267547506 } } ], "edges": [ { - "id": "reactflow__edge-f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90max_seq_len-01f674f8-b3d1-4df1-acac-6cb8e0bfb63ct5_max_seq_len", + "id": "reactflow__edge-f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90transformer-4fe24f07-f906-4f55-ab2c-9beee56ef5bdtransformer", "type": "default", "source": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", - "target": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", - "sourceHandle": "max_seq_len", - "targetHandle": "t5_max_seq_len" + "target": "4fe24f07-f906-4f55-ab2c-9beee56ef5bd", + "sourceHandle": "transformer", + "targetHandle": "transformer" + }, + { + "id": "reactflow__edge-01f674f8-b3d1-4df1-acac-6cb8e0bfb63cconditioning-4fe24f07-f906-4f55-ab2c-9beee56ef5bdpositive_text_conditioning", + "type": "default", + "source": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", + "target": "4fe24f07-f906-4f55-ab2c-9beee56ef5bd", + "sourceHandle": "conditioning", + "targetHandle": "positive_text_conditioning" }, { - "id": "reactflow__edge-f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90vae-159bdf1b-79e7-4174-b86e-d40e646964c8vae", + "id": "reactflow__edge-4754c534-a5f3-4ad0-9382-7887985e668cvalue-4fe24f07-f906-4f55-ab2c-9beee56ef5bdseed", + "type": "default", + "source": "4754c534-a5f3-4ad0-9382-7887985e668c", + "target": "4fe24f07-f906-4f55-ab2c-9beee56ef5bd", + "sourceHandle": "value", + "targetHandle": "seed" + }, + { + "id": "reactflow__edge-4fe24f07-f906-4f55-ab2c-9beee56ef5bdlatents-7e5172eb-48c1-44db-a770-8fd83e1435d1latents", + "type": "default", + "source": "4fe24f07-f906-4f55-ab2c-9beee56ef5bd", + "target": "7e5172eb-48c1-44db-a770-8fd83e1435d1", + "sourceHandle": "latents", + "targetHandle": "latents" + }, + { + "id": "reactflow__edge-f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90vae-7e5172eb-48c1-44db-a770-8fd83e1435d1vae", "type": "default", "source": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", - "target": "159bdf1b-79e7-4174-b86e-d40e646964c8", + "target": "7e5172eb-48c1-44db-a770-8fd83e1435d1", "sourceHandle": "vae", "targetHandle": "vae" }, + { + "id": "reactflow__edge-f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90max_seq_len-01f674f8-b3d1-4df1-acac-6cb8e0bfb63ct5_max_seq_len", + "type": "default", + "source": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", + "target": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", + "sourceHandle": "max_seq_len", + "targetHandle": "t5_max_seq_len" + }, { "id": "reactflow__edge-f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90t5_encoder-01f674f8-b3d1-4df1-acac-6cb8e0bfb63ct5_encoder", "type": "default", @@ -231,30 +313,6 @@ "target": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", "sourceHandle": "clip", "targetHandle": "clip" - }, - { - "id": "reactflow__edge-f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90transformer-159bdf1b-79e7-4174-b86e-d40e646964c8transformer", - "type": "default", - "source": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", - "target": "159bdf1b-79e7-4174-b86e-d40e646964c8", - "sourceHandle": "transformer", - "targetHandle": "transformer" - }, - { - "id": "reactflow__edge-01f674f8-b3d1-4df1-acac-6cb8e0bfb63cconditioning-159bdf1b-79e7-4174-b86e-d40e646964c8positive_text_conditioning", - "type": "default", - "source": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", - "target": "159bdf1b-79e7-4174-b86e-d40e646964c8", - "sourceHandle": "conditioning", - "targetHandle": "positive_text_conditioning" - }, - { - "id": "reactflow__edge-4754c534-a5f3-4ad0-9382-7887985e668cvalue-159bdf1b-79e7-4174-b86e-d40e646964c8seed", - "type": "default", - "source": "4754c534-a5f3-4ad0-9382-7887985e668c", - "target": "159bdf1b-79e7-4174-b86e-d40e646964c8", - "sourceHandle": "value", - "targetHandle": "seed" } ] } From 23adbd4002749d755d8db961676ca173784666b9 Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Fri, 30 Aug 2024 20:01:45 +0000 Subject: [PATCH 17/20] Update schema.ts. --- .../frontend/web/src/services/api/schema.ts | 185 ++++++++++++++---- 1 file changed, 147 insertions(+), 38 deletions(-) diff --git a/invokeai/frontend/web/src/services/api/schema.ts b/invokeai/frontend/web/src/services/api/schema.ts index c1d06392f40..31004f07217 100644 --- a/invokeai/frontend/web/src/services/api/schema.ts +++ b/invokeai/frontend/web/src/services/api/schema.ts @@ -4652,7 +4652,7 @@ export type components = { */ latents?: components["schemas"]["LatentsField"] | null; /** - * @description The mask to use for the operation + * @description A mask of the region to apply the denoising process to. * @default null */ denoise_mask?: components["schemas"]["DenoiseMaskField"] | null; @@ -5746,6 +5746,109 @@ export type components = { */ type: "flux_conditioning_output"; }; + /** + * FLUX Denoise + * @description Run denoising process with a FLUX transformer model. + */ + FluxDenoiseInvocation: { + /** + * @description The board to save the image to + * @default null + */ + board?: components["schemas"]["BoardField"] | null; + /** + * @description Optional metadata to be saved with the image + * @default null + */ + metadata?: components["schemas"]["MetadataField"] | null; + /** + * Id + * @description The id of this instance of an invocation. Must be unique among all instances of invocations. + */ + id: string; + /** + * Is Intermediate + * @description Whether or not this is an intermediate invocation. + * @default false + */ + is_intermediate?: boolean; + /** + * Use Cache + * @description Whether or not to use the cache + * @default true + */ + use_cache?: boolean; + /** + * @description Latents tensor + * @default null + */ + latents?: components["schemas"]["LatentsField"] | null; + /** + * @description A mask of the region to apply the denoising process to. + * @default null + */ + denoise_mask?: components["schemas"]["DenoiseMaskField"] | null; + /** + * Denoising Start + * @description When to start denoising, expressed a percentage of total steps + * @default 0 + */ + denoising_start?: number; + /** + * Denoising End + * @description When to stop denoising, expressed a percentage of total steps + * @default 1 + */ + denoising_end?: number; + /** + * Transformer + * @description Flux model (Transformer) to load + * @default null + */ + transformer?: components["schemas"]["TransformerField"]; + /** + * @description Positive conditioning tensor + * @default null + */ + positive_text_conditioning?: components["schemas"]["FluxConditioningField"]; + /** + * Width + * @description Width of the generated image. + * @default 1024 + */ + width?: number; + /** + * Height + * @description Height of the generated image. + * @default 1024 + */ + height?: number; + /** + * Num Steps + * @description Number of diffusion steps. Recommended values are schnell: 4, dev: 50. + * @default 4 + */ + num_steps?: number; + /** + * Guidance + * @description The guidance strength. Higher values adhere more strictly to the prompt, and will produce less diverse images. FLUX dev only, ignored for schnell. + * @default 4 + */ + guidance?: number; + /** + * Seed + * @description Randomness seed for reproducibility. + * @default 0 + */ + seed?: number; + /** + * type + * @default flux_denoise + * @constant + * @enum {string} + */ + type: "flux_denoise"; + }; /** * Flux Main Model * @description Loads a flux base model, outputting its submodels. @@ -5889,10 +5992,10 @@ export type components = { type: "flux_text_encoder"; }; /** - * FLUX Text to Image - * @description Text-to-image generation using a FLUX model. + * FLUX VAE Decode + * @description Generates an image from latents. */ - FluxTextToImageInvocation: { + FluxVaeDecodeInvocation: { /** * @description The board to save the image to * @default null @@ -5921,58 +6024,62 @@ export type components = { */ use_cache?: boolean; /** - * Transformer - * @description Flux model (Transformer) to load + * @description Latents tensor * @default null */ - transformer?: components["schemas"]["TransformerField"]; + latents?: components["schemas"]["LatentsField"]; /** * @description VAE * @default null */ vae?: components["schemas"]["VAEField"]; /** - * @description Positive conditioning tensor - * @default null + * type + * @default flux_vae_decode + * @constant + * @enum {string} */ - positive_text_conditioning?: components["schemas"]["FluxConditioningField"]; + type: "flux_vae_decode"; + }; + /** + * FLUX VAE Encode + * @description Encodes an image into latents. + */ + FluxVaeEncodeInvocation: { /** - * Width - * @description Width of the generated image. - * @default 1024 + * Id + * @description The id of this instance of an invocation. Must be unique among all instances of invocations. */ - width?: number; + id: string; /** - * Height - * @description Height of the generated image. - * @default 1024 + * Is Intermediate + * @description Whether or not this is an intermediate invocation. + * @default false */ - height?: number; + is_intermediate?: boolean; /** - * Num Steps - * @description Number of diffusion steps. Recommend values are schnell: 4, dev: 50. - * @default 4 + * Use Cache + * @description Whether or not to use the cache + * @default true */ - num_steps?: number; + use_cache?: boolean; /** - * Guidance - * @description The guidance strength. Higher values adhere more strictly to the prompt, and will produce less diverse images. FLUX dev only, ignored for schnell. - * @default 4 + * @description The image to encode. + * @default null */ - guidance?: number; + image?: components["schemas"]["ImageField"]; /** - * Seed - * @description Randomness seed for reproducibility. - * @default 0 + * @description VAE + * @default null */ - seed?: number; + vae?: components["schemas"]["VAEField"]; /** * type - * @default flux_text_to_image + * @default flux_vae_encode * @constant * @enum {string} */ - type: "flux_text_to_image"; + type: "flux_vae_encode"; }; /** FoundModel */ FoundModel: { @@ -6108,7 +6215,7 @@ export type components = { * @description The nodes in this graph */ nodes?: { - [key: string]: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["BlankImageInvocation"] | components["schemas"]["BlendLatentsInvocation"] | components["schemas"]["BooleanCollectionInvocation"] | components["schemas"]["BooleanInvocation"] | components["schemas"]["BoundingBoxInvocation"] | components["schemas"]["CLIPSkipInvocation"] | components["schemas"]["CV2InfillInvocation"] | components["schemas"]["CalculateImageTilesEvenSplitInvocation"] | components["schemas"]["CalculateImageTilesInvocation"] | components["schemas"]["CalculateImageTilesMinimumOverlapInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapImageProcessorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeImageProcessorInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DepthAnythingImageProcessorInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxTextToImageInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["ImageWatermarkInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["RandomFloatInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RectangleMaskInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["RoundInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLLoRACollectionLoader"] | components["schemas"]["SDXLLoRALoaderInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SaveImageInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["SchedulerInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringInvocation"] | components["schemas"]["StringJoinInvocation"] | components["schemas"]["StringJoinThreeInvocation"] | components["schemas"]["StringReplaceInvocation"] | components["schemas"]["StringSplitInvocation"] | components["schemas"]["StringSplitNegInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["T2IAdapterInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"]; + [key: string]: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["BlankImageInvocation"] | components["schemas"]["BlendLatentsInvocation"] | components["schemas"]["BooleanCollectionInvocation"] | components["schemas"]["BooleanInvocation"] | components["schemas"]["BoundingBoxInvocation"] | components["schemas"]["CLIPSkipInvocation"] | components["schemas"]["CV2InfillInvocation"] | components["schemas"]["CalculateImageTilesEvenSplitInvocation"] | components["schemas"]["CalculateImageTilesInvocation"] | components["schemas"]["CalculateImageTilesMinimumOverlapInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapImageProcessorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeImageProcessorInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DepthAnythingImageProcessorInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["FluxDenoiseInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxVaeDecodeInvocation"] | components["schemas"]["FluxVaeEncodeInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["ImageWatermarkInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["RandomFloatInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RectangleMaskInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["RoundInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLLoRACollectionLoader"] | components["schemas"]["SDXLLoRALoaderInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SaveImageInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["SchedulerInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringInvocation"] | components["schemas"]["StringJoinInvocation"] | components["schemas"]["StringJoinThreeInvocation"] | components["schemas"]["StringReplaceInvocation"] | components["schemas"]["StringSplitInvocation"] | components["schemas"]["StringSplitNegInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["T2IAdapterInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"]; }; /** * Edges @@ -8530,7 +8637,7 @@ export type components = { * Invocation * @description The ID of the invocation */ - invocation: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["BlankImageInvocation"] | components["schemas"]["BlendLatentsInvocation"] | components["schemas"]["BooleanCollectionInvocation"] | components["schemas"]["BooleanInvocation"] | components["schemas"]["BoundingBoxInvocation"] | components["schemas"]["CLIPSkipInvocation"] | components["schemas"]["CV2InfillInvocation"] | components["schemas"]["CalculateImageTilesEvenSplitInvocation"] | components["schemas"]["CalculateImageTilesInvocation"] | components["schemas"]["CalculateImageTilesMinimumOverlapInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapImageProcessorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeImageProcessorInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DepthAnythingImageProcessorInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxTextToImageInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["ImageWatermarkInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["RandomFloatInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RectangleMaskInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["RoundInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLLoRACollectionLoader"] | components["schemas"]["SDXLLoRALoaderInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SaveImageInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["SchedulerInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringInvocation"] | components["schemas"]["StringJoinInvocation"] | components["schemas"]["StringJoinThreeInvocation"] | components["schemas"]["StringReplaceInvocation"] | components["schemas"]["StringSplitInvocation"] | components["schemas"]["StringSplitNegInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["T2IAdapterInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"]; + invocation: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["BlankImageInvocation"] | components["schemas"]["BlendLatentsInvocation"] | components["schemas"]["BooleanCollectionInvocation"] | components["schemas"]["BooleanInvocation"] | components["schemas"]["BoundingBoxInvocation"] | components["schemas"]["CLIPSkipInvocation"] | components["schemas"]["CV2InfillInvocation"] | components["schemas"]["CalculateImageTilesEvenSplitInvocation"] | components["schemas"]["CalculateImageTilesInvocation"] | components["schemas"]["CalculateImageTilesMinimumOverlapInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapImageProcessorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeImageProcessorInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DepthAnythingImageProcessorInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["FluxDenoiseInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxVaeDecodeInvocation"] | components["schemas"]["FluxVaeEncodeInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["ImageWatermarkInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["RandomFloatInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RectangleMaskInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["RoundInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLLoRACollectionLoader"] | components["schemas"]["SDXLLoRALoaderInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SaveImageInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["SchedulerInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringInvocation"] | components["schemas"]["StringJoinInvocation"] | components["schemas"]["StringJoinThreeInvocation"] | components["schemas"]["StringReplaceInvocation"] | components["schemas"]["StringSplitInvocation"] | components["schemas"]["StringSplitNegInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["T2IAdapterInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"]; /** * Invocation Source Id * @description The ID of the prepared invocation's source node @@ -8576,7 +8683,7 @@ export type components = { * Invocation * @description The ID of the invocation */ - invocation: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["BlankImageInvocation"] | components["schemas"]["BlendLatentsInvocation"] | components["schemas"]["BooleanCollectionInvocation"] | components["schemas"]["BooleanInvocation"] | components["schemas"]["BoundingBoxInvocation"] | components["schemas"]["CLIPSkipInvocation"] | components["schemas"]["CV2InfillInvocation"] | components["schemas"]["CalculateImageTilesEvenSplitInvocation"] | components["schemas"]["CalculateImageTilesInvocation"] | components["schemas"]["CalculateImageTilesMinimumOverlapInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapImageProcessorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeImageProcessorInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DepthAnythingImageProcessorInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxTextToImageInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["ImageWatermarkInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["RandomFloatInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RectangleMaskInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["RoundInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLLoRACollectionLoader"] | components["schemas"]["SDXLLoRALoaderInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SaveImageInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["SchedulerInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringInvocation"] | components["schemas"]["StringJoinInvocation"] | components["schemas"]["StringJoinThreeInvocation"] | components["schemas"]["StringReplaceInvocation"] | components["schemas"]["StringSplitInvocation"] | components["schemas"]["StringSplitNegInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["T2IAdapterInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"]; + invocation: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["BlankImageInvocation"] | components["schemas"]["BlendLatentsInvocation"] | components["schemas"]["BooleanCollectionInvocation"] | components["schemas"]["BooleanInvocation"] | components["schemas"]["BoundingBoxInvocation"] | components["schemas"]["CLIPSkipInvocation"] | components["schemas"]["CV2InfillInvocation"] | components["schemas"]["CalculateImageTilesEvenSplitInvocation"] | components["schemas"]["CalculateImageTilesInvocation"] | components["schemas"]["CalculateImageTilesMinimumOverlapInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapImageProcessorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeImageProcessorInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DepthAnythingImageProcessorInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["FluxDenoiseInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxVaeDecodeInvocation"] | components["schemas"]["FluxVaeEncodeInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["ImageWatermarkInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["RandomFloatInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RectangleMaskInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["RoundInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLLoRACollectionLoader"] | components["schemas"]["SDXLLoRALoaderInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SaveImageInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["SchedulerInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringInvocation"] | components["schemas"]["StringJoinInvocation"] | components["schemas"]["StringJoinThreeInvocation"] | components["schemas"]["StringReplaceInvocation"] | components["schemas"]["StringSplitInvocation"] | components["schemas"]["StringSplitNegInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["T2IAdapterInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"]; /** * Invocation Source Id * @description The ID of the prepared invocation's source node @@ -8639,7 +8746,7 @@ export type components = { * Invocation * @description The ID of the invocation */ - invocation: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["BlankImageInvocation"] | components["schemas"]["BlendLatentsInvocation"] | components["schemas"]["BooleanCollectionInvocation"] | components["schemas"]["BooleanInvocation"] | components["schemas"]["BoundingBoxInvocation"] | components["schemas"]["CLIPSkipInvocation"] | components["schemas"]["CV2InfillInvocation"] | components["schemas"]["CalculateImageTilesEvenSplitInvocation"] | components["schemas"]["CalculateImageTilesInvocation"] | components["schemas"]["CalculateImageTilesMinimumOverlapInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapImageProcessorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeImageProcessorInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DepthAnythingImageProcessorInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxTextToImageInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["ImageWatermarkInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["RandomFloatInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RectangleMaskInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["RoundInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLLoRACollectionLoader"] | components["schemas"]["SDXLLoRALoaderInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SaveImageInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["SchedulerInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringInvocation"] | components["schemas"]["StringJoinInvocation"] | components["schemas"]["StringJoinThreeInvocation"] | components["schemas"]["StringReplaceInvocation"] | components["schemas"]["StringSplitInvocation"] | components["schemas"]["StringSplitNegInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["T2IAdapterInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"]; + invocation: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["BlankImageInvocation"] | components["schemas"]["BlendLatentsInvocation"] | components["schemas"]["BooleanCollectionInvocation"] | components["schemas"]["BooleanInvocation"] | components["schemas"]["BoundingBoxInvocation"] | components["schemas"]["CLIPSkipInvocation"] | components["schemas"]["CV2InfillInvocation"] | components["schemas"]["CalculateImageTilesEvenSplitInvocation"] | components["schemas"]["CalculateImageTilesInvocation"] | components["schemas"]["CalculateImageTilesMinimumOverlapInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapImageProcessorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeImageProcessorInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DepthAnythingImageProcessorInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["FluxDenoiseInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxVaeDecodeInvocation"] | components["schemas"]["FluxVaeEncodeInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["ImageWatermarkInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["RandomFloatInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RectangleMaskInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["RoundInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLLoRACollectionLoader"] | components["schemas"]["SDXLLoRALoaderInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SaveImageInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["SchedulerInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringInvocation"] | components["schemas"]["StringJoinInvocation"] | components["schemas"]["StringJoinThreeInvocation"] | components["schemas"]["StringReplaceInvocation"] | components["schemas"]["StringSplitInvocation"] | components["schemas"]["StringSplitNegInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["T2IAdapterInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"]; /** * Invocation Source Id * @description The ID of the prepared invocation's source node @@ -8714,9 +8821,11 @@ export type components = { float_math: components["schemas"]["FloatOutput"]; float_range: components["schemas"]["FloatCollectionOutput"]; float_to_int: components["schemas"]["IntegerOutput"]; + flux_denoise: components["schemas"]["LatentsOutput"]; flux_model_loader: components["schemas"]["FluxModelLoaderOutput"]; flux_text_encoder: components["schemas"]["FluxConditioningOutput"]; - flux_text_to_image: components["schemas"]["ImageOutput"]; + flux_vae_decode: components["schemas"]["ImageOutput"]; + flux_vae_encode: components["schemas"]["LatentsOutput"]; freeu: components["schemas"]["UNetOutput"]; grounding_dino: components["schemas"]["BoundingBoxCollectionOutput"]; hed_image_processor: components["schemas"]["ImageOutput"]; @@ -8857,7 +8966,7 @@ export type components = { * Invocation * @description The ID of the invocation */ - invocation: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["BlankImageInvocation"] | components["schemas"]["BlendLatentsInvocation"] | components["schemas"]["BooleanCollectionInvocation"] | components["schemas"]["BooleanInvocation"] | components["schemas"]["BoundingBoxInvocation"] | components["schemas"]["CLIPSkipInvocation"] | components["schemas"]["CV2InfillInvocation"] | components["schemas"]["CalculateImageTilesEvenSplitInvocation"] | components["schemas"]["CalculateImageTilesInvocation"] | components["schemas"]["CalculateImageTilesMinimumOverlapInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapImageProcessorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeImageProcessorInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DepthAnythingImageProcessorInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxTextToImageInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["ImageWatermarkInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["RandomFloatInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RectangleMaskInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["RoundInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLLoRACollectionLoader"] | components["schemas"]["SDXLLoRALoaderInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SaveImageInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["SchedulerInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringInvocation"] | components["schemas"]["StringJoinInvocation"] | components["schemas"]["StringJoinThreeInvocation"] | components["schemas"]["StringReplaceInvocation"] | components["schemas"]["StringSplitInvocation"] | components["schemas"]["StringSplitNegInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["T2IAdapterInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"]; + invocation: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["BlankImageInvocation"] | components["schemas"]["BlendLatentsInvocation"] | components["schemas"]["BooleanCollectionInvocation"] | components["schemas"]["BooleanInvocation"] | components["schemas"]["BoundingBoxInvocation"] | components["schemas"]["CLIPSkipInvocation"] | components["schemas"]["CV2InfillInvocation"] | components["schemas"]["CalculateImageTilesEvenSplitInvocation"] | components["schemas"]["CalculateImageTilesInvocation"] | components["schemas"]["CalculateImageTilesMinimumOverlapInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapImageProcessorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeImageProcessorInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DepthAnythingImageProcessorInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["FluxDenoiseInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxVaeDecodeInvocation"] | components["schemas"]["FluxVaeEncodeInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["ImageWatermarkInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["RandomFloatInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RectangleMaskInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["RoundInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLLoRACollectionLoader"] | components["schemas"]["SDXLLoRALoaderInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SaveImageInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["SchedulerInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringInvocation"] | components["schemas"]["StringJoinInvocation"] | components["schemas"]["StringJoinThreeInvocation"] | components["schemas"]["StringReplaceInvocation"] | components["schemas"]["StringSplitInvocation"] | components["schemas"]["StringSplitNegInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["T2IAdapterInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"]; /** * Invocation Source Id * @description The ID of the prepared invocation's source node From 4255a01c64e07eb7102671b9dab48eabad72d434 Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Fri, 30 Aug 2024 20:14:55 +0000 Subject: [PATCH 18/20] Restore line that was accidentally removed during development. --- invokeai/app/invocations/latents_to_image.py | 1 + 1 file changed, 1 insertion(+) diff --git a/invokeai/app/invocations/latents_to_image.py b/invokeai/app/invocations/latents_to_image.py index 6d359e82fd1..35b8483f2cc 100644 --- a/invokeai/app/invocations/latents_to_image.py +++ b/invokeai/app/invocations/latents_to_image.py @@ -53,6 +53,7 @@ class LatentsToImageInvocation(BaseInvocation, WithMetadata, WithBoard): tile_size: int = InputField(default=0, multiple_of=8, description=FieldDescriptions.vae_tile_size) fp32: bool = InputField(default=DEFAULT_PRECISION == torch.float32, description=FieldDescriptions.fp32) + @torch.no_grad() def invoke(self, context: InvocationContext) -> ImageOutput: latents = context.tensors.load(self.latents.latents_name) From b43da46b829ccb46e13ff67084da6170eb1b2469 Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Mon, 2 Sep 2024 09:25:45 -0400 Subject: [PATCH 19/20] Rename 'FLUX VAE Encode'/'FLUX VAE Decode' to 'FLUX Image to Latents'/'FLUX Latents to Image' --- invokeai/app/invocations/flux_vae_decode.py | 2 +- invokeai/app/invocations/flux_vae_encode.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/invokeai/app/invocations/flux_vae_decode.py b/invokeai/app/invocations/flux_vae_decode.py index 54d9b57f13f..bfe6501bddf 100644 --- a/invokeai/app/invocations/flux_vae_decode.py +++ b/invokeai/app/invocations/flux_vae_decode.py @@ -21,7 +21,7 @@ @invocation( "flux_vae_decode", - title="FLUX VAE Decode", + title="FLUX Latents to Image", tags=["latents", "image", "vae", "l2i", "flux"], category="latents", version="1.0.0", diff --git a/invokeai/app/invocations/flux_vae_encode.py b/invokeai/app/invocations/flux_vae_encode.py index f69b421a914..1fee7145f50 100644 --- a/invokeai/app/invocations/flux_vae_encode.py +++ b/invokeai/app/invocations/flux_vae_encode.py @@ -19,7 +19,7 @@ @invocation( "flux_vae_encode", - title="FLUX VAE Encode", + title="FLUX Image to Latents", tags=["latents", "image", "vae", "i2l", "flux"], category="latents", version="1.0.0", From 627b0bf644b01349e03d7ec99a77bb7a77f8118f Mon Sep 17 00:00:00 2001 From: Ryan Dick Date: Mon, 2 Sep 2024 09:37:36 -0400 Subject: [PATCH 20/20] Expose all FLUX model params in the default FLUX models. --- .../FLUX Image to Image.json | 24 +++++++++++++------ .../default_workflows/Flux Text to Image.json | 14 ++++++++--- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/invokeai/app/services/workflow_records/default_workflows/FLUX Image to Image.json b/invokeai/app/services/workflow_records/default_workflows/FLUX Image to Image.json index 20e728b469a..ba0b00ddae6 100644 --- a/invokeai/app/services/workflow_records/default_workflows/FLUX Image to Image.json +++ b/invokeai/app/services/workflow_records/default_workflows/FLUX Image to Image.json @@ -12,17 +12,25 @@ "fieldName": "model" }, { - "nodeId": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", - "fieldName": "prompt" + "nodeId": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", + "fieldName": "t5_encoder_model" }, { "nodeId": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", - "fieldName": "t5_encoder_model" + "fieldName": "clip_embed_model" + }, + { + "nodeId": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", + "fieldName": "vae_model" }, { "nodeId": "ace0258f-67d7-4eee-a218-6fff27065214", "fieldName": "denoising_start" }, + { + "nodeId": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", + "fieldName": "prompt" + }, { "nodeId": "ace0258f-67d7-4eee-a218-6fff27065214", "fieldName": "num_steps" @@ -32,7 +40,6 @@ "version": "3.0.0", "category": "default" }, - "id": "0a91fc4c-5f93-469c-a6ad-e87bf47b68bf", "nodes": [ { "id": "2981a67c-480f-4237-9384-26b68dbf912b", @@ -49,7 +56,10 @@ "inputs": { "image": { "name": "image", - "label": "" + "label": "", + "value": { + "image_name": "8a5c62aa-9335-45d2-9c71-89af9fc1f8d4.png" + } }, "vae": { "name": "vae", @@ -202,7 +212,7 @@ "name": "clip_embed_model", "label": "", "value": { - "key": "076fa0b4-6e06-413a-bfca-61ab6f8b26db", + "key": "fa23a584-b623-415d-832a-21b5098ff1a1", "hash": "blake3:17c19f0ef941c3b7609a9c94a659ca5364de0be364a91d4179f0e39ba17c3b70", "name": "clip-vit-large-patch14", "base": "any", @@ -213,7 +223,7 @@ "name": "vae_model", "label": "", "value": { - "key": "0bfe1765-2895-4a93-87e3-00277c04545d", + "key": "74fc82ba-c0a8-479d-a890-2126f82da758", "hash": "blake3:ce21cb76364aa6e2421311cf4a4b5eb052a76c4f1cd207b50703d8978198a068", "name": "FLUX.1-schnell_ae", "base": "flux", diff --git a/invokeai/app/services/workflow_records/default_workflows/Flux Text to Image.json b/invokeai/app/services/workflow_records/default_workflows/Flux Text to Image.json index 1917fd32ed1..a4bd2ce0632 100644 --- a/invokeai/app/services/workflow_records/default_workflows/Flux Text to Image.json +++ b/invokeai/app/services/workflow_records/default_workflows/Flux Text to Image.json @@ -12,12 +12,20 @@ "fieldName": "model" }, { - "nodeId": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", - "fieldName": "prompt" + "nodeId": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", + "fieldName": "t5_encoder_model" }, { "nodeId": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", - "fieldName": "t5_encoder_model" + "fieldName": "clip_embed_model" + }, + { + "nodeId": "f8d9d7c8-9ed7-4bd7-9e42-ab0e89bfac90", + "fieldName": "vae_model" + }, + { + "nodeId": "01f674f8-b3d1-4df1-acac-6cb8e0bfb63c", + "fieldName": "prompt" }, { "nodeId": "4fe24f07-f906-4f55-ab2c-9beee56ef5bd",