From b92c6ae633b64af07ae96bbe49bd8da39cec69fe Mon Sep 17 00:00:00 2001 From: Alexander Eichhorn Date: Tue, 27 Jan 2026 05:21:37 +0100 Subject: [PATCH] feat(flux2): add FLUX.2 klein model support (#8768) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * WIP: feat(flux2): add FLUX 2 Kontext model support - Add new invocation nodes for FLUX 2: - flux2_denoise: Denoising invocation for FLUX 2 - flux2_klein_model_loader: Model loader for Klein architecture - flux2_klein_text_encoder: Text encoder for Qwen3-based encoding - flux2_vae_decode: VAE decoder for FLUX 2 - Add backend support: - New flux2 module with denoise and sampling utilities - Extended model manager configs for FLUX 2 models - Updated model loaders for Klein architecture - Update frontend: - Extended graph builder for FLUX 2 support - Added FLUX 2 model types and configurations - Updated readiness checks and UI components * fix(flux2): correct VAE decode with proper BN denormalization FLUX.2 VAE uses Batch Normalization in the patchified latent space (128 channels). The decode must: 1. Patchify latents from (B, 32, H, W) to (B, 128, H/2, W/2) 2. Apply BN denormalization using running_mean/running_var 3. Unpatchify back to (B, 32, H, W) for VAE decode Also fixed image normalization from [-1, 1] to [0, 255]. This fixes washed-out colors in generated FLUX.2 Klein images. * feat(flux2): add FLUX.2 Klein model support with ComfyUI checkpoint compatibility - Add FLUX.2 transformer loader with BFL-to-diffusers weight conversion - Fix AdaLayerNorm scale-shift swap for final_layer.adaLN_modulation weights - Add VAE batch normalization handling for FLUX.2 latent normalization - Add Qwen3 text encoder loader with ComfyUI FP8 quantization support - Add frontend components for FLUX.2 Klein model selection - Update configs and schema for FLUX.2 model types * Chore Ruff * Fix Flux1 vae probing * Fix Windows Paths schema.ts * Add 4B und 9B klein to Starter Models. * feat(flux2): add non-commercial license indicator for FLUX.2 Klein 9B - Add isFlux2Klein9BMainModelConfig and isNonCommercialMainModelConfig functions - Update MainModelPicker and InitialStateMainModelPicker to show license icon - Update license tooltip text to include FLUX.2 Klein 9B * feat(flux2): add Klein/Qwen3 variant support and encoder filtering Backend: - Add klein_4b/klein_9b variants for FLUX.2 Klein models - Add qwen3_4b/qwen3_8b variants for Qwen3 encoder models - Validate encoder variant matches Klein model (4B↔4B, 9B↔8B) - Auto-detect Qwen3 variant from hidden_size during probing Frontend: - Show variant field for all model types in ModelView - Filter Qwen3 encoder dropdown to only show compatible variants - Update variant type definitions (zFlux2VariantType, zQwen3VariantType) - Remove unused exports (isFluxDevMainModelConfig, isFlux2Klein9BMainModelConfig) * Chore Ruff * feat(flux2): add Klein 9B Base (undistilled) variant support Distinguish between FLUX.2 Klein 9B (distilled) and Klein 9B Base (undistilled) models by checking guidance_embeds in diffusers config or guidance_in keys in safetensors. Klein 9B Base requires more steps but offers higher quality. * feat(flux2): improve diffusers compatibility and distilled model support Backend changes: - Update text encoder layers from [9,18,27] to (10,20,30) matching diffusers - Use apply_chat_template with system message instead of manual formatting - Change position IDs from ones to zeros to match diffusers implementation - Add get_schedule_flux2() with empirical mu computation for proper schedule shifting - Add txt_embed_scale parameter for Qwen3 embedding magnitude control - Add shift_schedule toggle for base (28+ steps) vs distilled (4 steps) models - Zero out guidance_embedder weights for Klein models without guidance_embeds UI changes: - Clear Klein VAE and Qwen3 encoder when switching away from flux2 base - Clear Qwen3 encoder when switching between different Klein model variants - Add toast notification informing user to select compatible encoder * feat(flux2): fix distilled model scheduling with proper dynamic shifting - Configure scheduler with FLUX.2 Klein parameters from scheduler_config.json (use_dynamic_shifting=True, shift=3.0, time_shift_type="exponential") - Pass mu parameter to scheduler.set_timesteps() for resolution-aware shifting - Remove manual shift_schedule parameter (scheduler handles this automatically) - Simplify get_schedule_flux2() to return linear sigmas only - Remove txt_embed_scale parameter (no longer needed) This matches the diffusers Flux2KleinPipeline behavior where the FlowMatchEulerDiscreteScheduler applies dynamic timestep shifting based on image resolution via the mu parameter. Fixes 4-step distilled Klein 9B model quality issues. * fix(ui): fix FLUX.1 graph building with posCondCollect node lookup The posCondCollect node was created with getPrefixedId() which generates a random suffix (e.g., 'pos_cond_collect:abc123'), but g.getNode() was called with the plain string 'pos_cond_collect', causing a node lookup failure. Fix by declaring posCondCollect as a module-scoped variable and referencing it directly instead of using g.getNode(). * Remove Flux2 Klein Base from Starter Models * Remove Logging * Add Default Values for Flux2 Klein and add variant as additional info to from_base * Add migrations for the z-image qwen3 encoder without a variant value * Add img2img, inpainting and outpainting support for FLUX.2 Klein - Add flux2_vae_encode invocation for encoding images to FLUX.2 latents - Integrate inpaint_extension into FLUX.2 denoise loop for proper mask handling - Apply BN normalization to init_latents and noise for consistency in inpainting - Use manual Euler stepping for img2img/inpaint to preserve exact timestep schedule - Add flux2_img2img, flux2_inpaint, flux2_outpaint generation modes - Expand starter models with FP8 variants, standalone transformers, and separate VAE/encoders - Fix outpainting to always use full denoising (0-1) since strength doesn't apply - Improve error messages in model loader with clear guidance for standalone models * Add GGUF quantized model support and Diffusers VAE loader for FLUX.2 Klein - Add Main_GGUF_Flux2_Config for GGUF-quantized FLUX.2 transformer models - Add VAE_Diffusers_Flux2_Config for FLUX.2 VAE in diffusers format - Add Flux2GGUFCheckpointModel loader with BFL-to-diffusers conversion - Add Flux2VAEDiffusersLoader for AutoencoderKLFlux2 - Add FLUX.2 Klein 4B/9B hardware requirements to documentation - Update starter model descriptions to clarify dependencies install together - Update frontend schema for new model configs * Fix FLUX.2 model detection and add FP8 weight dequantization support - Improve FLUX.2 variant detection for GGUF/checkpoint models (BFL format keys) - Fix guidance_embeds logic: distilled=False, undistilled=True - Add FP8 weight dequantization for ComfyUI-style quantized models - Prevent FLUX.2 models from being misidentified as FLUX.1 - Preserve user-editable fields (name, description, etc.) on model reidentify - Improve Qwen3Encoder detection by variant in starter models - Add defensive checks for tensor operations * Chore ruff format * Chore Typegen * Fix FLUX.2 Klein 9B model loading by detecting hidden_size from weights Previously num_attention_heads was hardcoded to 24, which is correct for Klein 4B but causes size mismatches when loading Klein 9B checkpoints. Now dynamically calculates num_attention_heads from the hidden_size dimension of context_embedder weights: - Klein 4B: hidden_size=3072 → num_attention_heads=24 - Klein 9B: hidden_size=4096 → num_attention_heads=32 Fixes both Checkpoint and GGUF loaders for FLUX.2 models. * Only clear Qwen3 encoder when FLUX.2 Klein variant changes Previously the encoder was cleared whenever switching between any Klein models, even if they had the same variant. Now compares the variant of the old and new model and only clears the encoder when switching between different variants (e.g., klein_4b to klein_9b). This allows users to switch between different Klein 9B models without having to re-select the Qwen3 encoder each time. * Add metadata recall support for FLUX.2 Klein parameters The scheduler, VAE model, and Qwen3 encoder model were not being recalled correctly for FLUX.2 Klein images. This adds dedicated metadata handlers for the Klein-specific parameters. * Fix FLUX.2 Klein denoising scaling and Z-Image VAE compatibility - Apply exponential denoising scaling (exponent 0.2) to FLUX.2 Klein, matching FLUX.1 behavior for more intuitive inpainting strength - Add isFlux1VAEModelConfig type guard to filter FLUX 1.0 VAEs only - Restrict Z-Image VAE selection to FLUX 1.0 VAEs, excluding FLUX.2 Klein 32-channel VAEs which are incompatible * chore pnpm fix * Add FLUX.2 Klein to starter bundles and documentation - Add FLUX.2 Klein hardware requirements to quick start guide - Create flux2_klein_bundle with GGUF Q4 model, VAE, and Qwen3 encoder - Add "What's New" entry announcing FLUX.2 Klein support * Add FLUX.2 Klein built-in reference image editing support FLUX.2 Klein has native multi-reference image editing without requiring a separate model (unlike FLUX.1 which needs a Kontext model). Backend changes: - Add Flux2RefImageExtension for encoding reference images with FLUX.2 VAE - Apply BN normalization to reference image latents for correct scaling - Use T-coordinate offset scale=10 like diffusers (T=10, 20, 30...) - Concatenate reference latents with generated image during denoising - Extract only generated portion in step callback for correct preview Frontend changes: - Add flux2_reference_image config type without model field - Hide model selector for FLUX.2 reference images (built-in support) - Add type guards to handle configs without model property - Update validators to skip model validation for FLUX.2 - Add 'flux2' to SUPPORTS_REF_IMAGES_BASE_MODELS * Chore windows path fix * Add reference image resizing for FLUX.2 Klein Resize large reference images to match BFL FLUX.2 sampling.py limits: - Single reference: max 2024² pixels (~4.1M) - Multiple references: max 1024² pixels (~1M) Uses same scaling approach as BFL's cap_pixels() function. --- docs/installation/quick_start.md | 8 +- docs/installation/requirements.md | 14 +- invokeai/app/api/routers/model_manager.py | 44 +- invokeai/app/invocations/fields.py | 2 +- invokeai/app/invocations/flux2_denoise.py | 499 +++ .../invocations/flux2_klein_model_loader.py | 222 + .../invocations/flux2_klein_text_encoder.py | 222 + invokeai/app/invocations/flux2_vae_decode.py | 106 + invokeai/app/invocations/flux2_vae_encode.py | 88 + invokeai/app/invocations/flux_denoise.py | 10 +- invokeai/app/invocations/flux_lora_loader.py | 2 +- invokeai/app/invocations/ideal_size.py | 7 +- invokeai/app/invocations/metadata.py | 4 + invokeai/app/invocations/model.py | 1 + .../model_records/model_records_base.py | 6 +- .../app/services/shared/invocation_context.py | 15 + .../app/services/shared/sqlite/sqlite_util.py | 2 + .../migrations/migration_25.py | 61 + invokeai/app/util/step_callback.py | 42 + invokeai/backend/flux/util.py | 36 +- invokeai/backend/flux2/__init__.py | 4 + invokeai/backend/flux2/denoise.py | 261 ++ invokeai/backend/flux2/ref_image_extension.py | 294 ++ invokeai/backend/flux2/sampling_utils.py | 209 + .../backend/model_manager/configs/factory.py | 20 +- .../backend/model_manager/configs/main.py | 377 +- .../model_manager/configs/qwen3_encoder.py | 123 +- invokeai/backend/model_manager/configs/vae.py | 80 +- .../model_manager/load/model_loaders/flux.py | 1009 ++++- .../load/model_loaders/z_image.py | 149 +- .../backend/model_manager/starter_models.py | 128 + invokeai/backend/model_manager/taxonomy.py | 35 +- .../model_manager/util/select_hf_files.py | 5 +- invokeai/frontend/web/openapi.json | 3796 ++++++++++++++++- invokeai/frontend/web/public/locales/en.json | 10 +- .../listeners/modelSelected.ts | 53 + .../components/RefImage/RefImageSettings.tsx | 33 +- .../controlLayers/hooks/addLayerHooks.ts | 11 +- .../controlLayers/store/paramsSlice.ts | 24 + .../controlLayers/store/refImagesSlice.ts | 13 +- .../src/features/controlLayers/store/types.ts | 22 +- .../src/features/controlLayers/store/util.ts | 5 + .../controlLayers/store/validators.ts | 15 +- .../web/src/features/metadata/parsing.tsx | 62 +- .../web/src/features/modelManagerV2/models.ts | 10 +- .../ModelInstallQueueItem.tsx | 9 +- .../subpanels/ModelPanel/ModelView.tsx | 2 +- .../src/features/nodes/types/common.test-d.ts | 4 + .../web/src/features/nodes/types/common.ts | 13 +- .../graph/generation/addControlAdapters.ts | 4 +- .../util/graph/generation/addImageToImage.ts | 5 +- .../nodes/util/graph/generation/addInpaint.ts | 3 +- .../util/graph/generation/addOutpaint.ts | 11 +- .../nodes/util/graph/generation/addRegions.ts | 8 +- .../util/graph/generation/addTextToImage.ts | 3 +- .../util/graph/generation/buildFLUXGraph.ts | 624 ++- .../nodes/util/graph/graphBuilderUtils.ts | 12 +- .../src/features/nodes/util/graph/types.ts | 19 +- .../Advanced/ParamFlux2KleinModelSelect.tsx | 144 + .../ParamZImageQwen3VaeModelSelect.tsx | 6 +- .../parameters/util/optimalDimension.ts | 2 + .../features/queue/hooks/useEnqueueCanvas.ts | 3 +- .../queue/hooks/useEnqueueGenerate.ts | 3 +- .../web/src/features/queue/store/readiness.ts | 49 + .../AdvancedSettingsAccordion.tsx | 21 +- .../GenerationSettingsAccordion.tsx | 17 +- .../MainModelPicker.tsx | 8 +- .../layouts/InitialStateMainModelPicker.tsx | 8 +- .../src/services/api/hooks/modelsByType.ts | 4 + .../frontend/web/src/services/api/schema.ts | 917 +++- .../frontend/web/src/services/api/types.ts | 31 +- 71 files changed, 9462 insertions(+), 607 deletions(-) create mode 100644 invokeai/app/invocations/flux2_denoise.py create mode 100644 invokeai/app/invocations/flux2_klein_model_loader.py create mode 100644 invokeai/app/invocations/flux2_klein_text_encoder.py create mode 100644 invokeai/app/invocations/flux2_vae_decode.py create mode 100644 invokeai/app/invocations/flux2_vae_encode.py create mode 100644 invokeai/app/services/shared/sqlite_migrator/migrations/migration_25.py create mode 100644 invokeai/backend/flux2/__init__.py create mode 100644 invokeai/backend/flux2/denoise.py create mode 100644 invokeai/backend/flux2/ref_image_extension.py create mode 100644 invokeai/backend/flux2/sampling_utils.py create mode 100644 invokeai/frontend/web/src/features/parameters/components/Advanced/ParamFlux2KleinModelSelect.tsx diff --git a/docs/installation/quick_start.md b/docs/installation/quick_start.md index 572289e9c1..6482374180 100644 --- a/docs/installation/quick_start.md +++ b/docs/installation/quick_start.md @@ -25,12 +25,18 @@ Hardware requirements vary significantly depending on model and image output siz - Memory: At least 16GB RAM. - Disk: 10GB for base installation plus 100GB for models. - === "FLUX - 1024×1024" + === "FLUX.1 - 1024×1024" - GPU: Nvidia 20xx series or later, 10GB+ VRAM. - Memory: At least 32GB RAM. - Disk: 10GB for base installation plus 200GB for models. + === "FLUX.2 Klein - 1024×1024" + + - GPU: Nvidia 20xx series or later, 6GB+ VRAM for GGUF Q4 quantized models, 12GB+ for full precision. + - Memory: At least 16GB RAM. + - Disk: 10GB for base installation plus 20GB for models. + === "Z-Image Turbo - 1024x1024" - GPU: Nvidia 20xx series or later, 8GB+ VRAM for the Q4_K quantized model. 16GB+ needed for the Q8 or BF16 models. - Memory: At least 16GB RAM. diff --git a/docs/installation/requirements.md b/docs/installation/requirements.md index 132ac31ed3..7fcdd14b52 100644 --- a/docs/installation/requirements.md +++ b/docs/installation/requirements.md @@ -25,12 +25,24 @@ The requirements below are rough guidelines for best performance. GPUs with less - Memory: At least 16GB RAM. - Disk: 10GB for base installation plus 100GB for models. - === "FLUX - 1024×1024" + === "FLUX.1 - 1024×1024" - GPU: Nvidia 20xx series or later, 10GB+ VRAM. - Memory: At least 32GB RAM. - Disk: 10GB for base installation plus 200GB for models. + === "FLUX.2 Klein 4B - 1024×1024" + + - GPU: Nvidia 30xx series or later, 12GB+ VRAM (e.g. RTX 3090, RTX 4070). FP8 version works with 8GB+ VRAM. + - Memory: At least 16GB RAM. + - Disk: 10GB for base installation plus 20GB for models (Diffusers format with encoder). + + === "FLUX.2 Klein 9B - 1024×1024" + + - GPU: Nvidia 40xx series, 24GB+ VRAM (e.g. RTX 4090). FP8 version works with 12GB+ VRAM. + - Memory: At least 32GB RAM. + - Disk: 10GB for base installation plus 40GB for models (Diffusers format with encoder). + === "Z-Image Turbo - 1024x1024" - GPU: Nvidia 20xx series or later, 8GB+ VRAM for the Q4_K quantized model. 16GB+ needed for the Q8 or BF16 models. - Memory: At least 16GB RAM. diff --git a/invokeai/app/api/routers/model_manager.py b/invokeai/app/api/routers/model_manager.py index 06f7dd4e66..ceca9f8f53 100644 --- a/invokeai/app/api/routers/model_manager.py +++ b/invokeai/app/api/routers/model_manager.py @@ -219,7 +219,16 @@ async def reidentify_model( result = ModelConfigFactory.from_model_on_disk(mod) if result.config is None: raise InvalidModelException("Unable to identify model format") - result.config.key = config.key # retain the same key + + # Retain user-editable fields from the original config + result.config.key = config.key + result.config.name = config.name + result.config.description = config.description + result.config.cover_image = config.cover_image + result.config.trigger_phrases = config.trigger_phrases + result.config.source = config.source + result.config.source_type = config.source_type + new_config = ApiDependencies.invoker.services.model_manager.store.replace_model(config.key, result.config) return new_config except UnknownModelException as e: @@ -905,15 +914,48 @@ class StarterModelResponse(BaseModel): def get_is_installed( starter_model: StarterModel | StarterModelWithoutDependencies, installed_models: list[AnyModelConfig] ) -> bool: + from invokeai.backend.model_manager.taxonomy import ModelType + for model in installed_models: + # Check if source matches exactly if model.source == starter_model.source: return True + # Check if name (or previous names), base and type match if ( (model.name == starter_model.name or model.name in starter_model.previous_names) and model.base == starter_model.base and model.type == starter_model.type ): return True + + # Special handling for Qwen3Encoder models - check by type and variant + # This allows renamed models to still be detected as installed + if starter_model.type == ModelType.Qwen3Encoder: + from invokeai.backend.model_manager.taxonomy import Qwen3VariantType + + # Determine expected variant from source pattern + expected_variant: Qwen3VariantType | None = None + if "klein-9B" in starter_model.source or "qwen3_8b" in starter_model.source.lower(): + expected_variant = Qwen3VariantType.Qwen3_8B + elif ( + "klein-4B" in starter_model.source + or "qwen3_4b" in starter_model.source.lower() + or "Z-Image" in starter_model.source + ): + expected_variant = Qwen3VariantType.Qwen3_4B + + if expected_variant is not None: + for model in installed_models: + if model.type == ModelType.Qwen3Encoder and hasattr(model, "variant"): + model_variant = model.variant + # Handle both enum and string values + if isinstance(model_variant, Qwen3VariantType): + if model_variant == expected_variant: + return True + elif isinstance(model_variant, str): + if model_variant == expected_variant.value: + return True + return False diff --git a/invokeai/app/invocations/fields.py b/invokeai/app/invocations/fields.py index 6137420c87..cca09a059d 100644 --- a/invokeai/app/invocations/fields.py +++ b/invokeai/app/invocations/fields.py @@ -532,7 +532,7 @@ def migrate_model_ui_type(ui_type: UIType | str, json_schema_extra: dict[str, An case UIType.VAEModel: ui_model_type = [ModelType.VAE] case UIType.FluxVAEModel: - ui_model_base = [BaseModelType.Flux] + ui_model_base = [BaseModelType.Flux, BaseModelType.Flux2] ui_model_type = [ModelType.VAE] case UIType.LoRAModel: ui_model_type = [ModelType.LoRA] diff --git a/invokeai/app/invocations/flux2_denoise.py b/invokeai/app/invocations/flux2_denoise.py new file mode 100644 index 0000000000..6a85e58f74 --- /dev/null +++ b/invokeai/app/invocations/flux2_denoise.py @@ -0,0 +1,499 @@ +"""Flux2 Klein Denoise Invocation. + +Run denoising process with a FLUX.2 Klein transformer model. +Uses Qwen3 conditioning instead of CLIP+T5. +""" + +from contextlib import ExitStack +from typing import Callable, Iterator, Optional, Tuple + +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, + FluxKontextConditioningField, + Input, + InputField, + LatentsField, +) +from invokeai.app.invocations.model import TransformerField, VAEField +from invokeai.app.invocations.primitives import LatentsOutput +from invokeai.app.services.shared.invocation_context import InvocationContext +from invokeai.backend.flux.sampling_utils import clip_timestep_schedule_fractional +from invokeai.backend.flux.schedulers import FLUX_SCHEDULER_LABELS, FLUX_SCHEDULER_MAP, FLUX_SCHEDULER_NAME_VALUES +from invokeai.backend.flux2.denoise import denoise +from invokeai.backend.flux2.ref_image_extension import Flux2RefImageExtension +from invokeai.backend.flux2.sampling_utils import ( + compute_empirical_mu, + generate_img_ids_flux2, + get_noise_flux2, + get_schedule_flux2, + pack_flux2, + unpack_flux2, +) +from invokeai.backend.model_manager.taxonomy import BaseModelType, ModelFormat, ModelType +from invokeai.backend.patches.layer_patcher import LayerPatcher +from invokeai.backend.patches.lora_conversions.flux_lora_constants import FLUX_LORA_TRANSFORMER_PREFIX +from invokeai.backend.patches.model_patch_raw import ModelPatchRaw +from invokeai.backend.rectified_flow.rectified_flow_inpaint_extension import RectifiedFlowInpaintExtension +from invokeai.backend.stable_diffusion.diffusers_pipeline import PipelineIntermediateState +from invokeai.backend.stable_diffusion.diffusion.conditioning_data import FLUXConditioningInfo +from invokeai.backend.util.devices import TorchDevice + + +@invocation( + "flux2_denoise", + title="FLUX2 Denoise", + tags=["image", "flux", "flux2", "klein", "denoise"], + category="image", + version="1.3.0", + classification=Classification.Prototype, +) +class Flux2DenoiseInvocation(BaseInvocation): + """Run denoising process with a FLUX.2 Klein transformer model. + + This node is designed for FLUX.2 Klein models which use Qwen3 as the text encoder. + It does not support ControlNet, IP-Adapters, or regional prompting. + """ + + latents: Optional[LatentsField] = InputField( + default=None, + 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, + le=1, + description=FieldDescriptions.denoising_start, + ) + denoising_end: float = InputField( + default=1.0, + ge=0, + le=1, + description=FieldDescriptions.denoising_end, + ) + add_noise: bool = InputField(default=True, description="Add noise based on denoising start.") + transformer: TransformerField = InputField( + description=FieldDescriptions.flux_model, + input=Input.Connection, + title="Transformer", + ) + positive_text_conditioning: FluxConditioningField = InputField( + description=FieldDescriptions.positive_cond, + input=Input.Connection, + ) + negative_text_conditioning: Optional[FluxConditioningField] = InputField( + default=None, + description="Negative conditioning tensor. Can be None if cfg_scale is 1.0.", + input=Input.Connection, + ) + cfg_scale: float = InputField( + default=1.0, + description=FieldDescriptions.cfg_scale, + title="CFG Scale", + ) + 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. Use 4 for distilled models, 28+ for base models.", + ) + scheduler: FLUX_SCHEDULER_NAME_VALUES = InputField( + default="euler", + description="Scheduler (sampler) for the denoising process. 'euler' is fast and standard. " + "'heun' is 2nd-order (better quality, 2x slower). 'lcm' is optimized for few steps.", + ui_choice_labels=FLUX_SCHEDULER_LABELS, + ) + seed: int = InputField(default=0, description="Randomness seed for reproducibility.") + vae: VAEField = InputField( + description="FLUX.2 VAE model (required for BN statistics).", + input=Input.Connection, + ) + kontext_conditioning: FluxKontextConditioningField | list[FluxKontextConditioningField] | None = InputField( + default=None, + description="FLUX Kontext conditioning (reference images for multi-reference image editing).", + input=Input.Connection, + title="Reference Images", + ) + + def _get_bn_stats(self, context: InvocationContext) -> Optional[Tuple[torch.Tensor, torch.Tensor]]: + """Extract BN statistics from the FLUX.2 VAE. + + The FLUX.2 VAE uses batch normalization on the patchified 128-channel representation. + IMPORTANT: BFL FLUX.2 VAE uses affine=False, so there are NO learnable weight/bias. + + BN formula (affine=False): y = (x - mean) / std + Inverse: x = y * std + mean + + Returns: + Tuple of (bn_mean, bn_std) tensors of shape (128,), or None if BN layer not found. + """ + with context.models.load(self.vae.vae).model_on_device() as (_, vae): + # Ensure VAE is in eval mode to prevent BN stats from being updated + vae.eval() + + # Try to find the BN layer - it may be at different locations depending on model format + bn_layer = None + if hasattr(vae, "bn"): + bn_layer = vae.bn + elif hasattr(vae, "batch_norm"): + bn_layer = vae.batch_norm + elif hasattr(vae, "encoder") and hasattr(vae.encoder, "bn"): + bn_layer = vae.encoder.bn + + if bn_layer is None: + return None + + # Verify running statistics are initialized + if bn_layer.running_mean is None or bn_layer.running_var is None: + return None + + # Get BN running statistics from VAE + bn_mean = bn_layer.running_mean.clone() # Shape: (128,) + bn_var = bn_layer.running_var.clone() # Shape: (128,) + bn_eps = bn_layer.eps if hasattr(bn_layer, "eps") else 1e-4 # BFL uses 1e-4 + bn_std = torch.sqrt(bn_var + bn_eps) + + return bn_mean, bn_std + + def _bn_normalize( + self, + x: torch.Tensor, + bn_mean: torch.Tensor, + bn_std: torch.Tensor, + ) -> torch.Tensor: + """Apply BN normalization to packed latents. + + BN formula (affine=False): y = (x - mean) / std + + Args: + x: Packed latents of shape (B, seq, 128). + bn_mean: BN running mean of shape (128,). + bn_std: BN running std of shape (128,). + + Returns: + Normalized latents of same shape. + """ + # x: (B, seq, 128), params: (128,) -> broadcast over batch and sequence dims + bn_mean = bn_mean.to(x.device, x.dtype) + bn_std = bn_std.to(x.device, x.dtype) + return (x - bn_mean) / bn_std + + def _bn_denormalize( + self, + x: torch.Tensor, + bn_mean: torch.Tensor, + bn_std: torch.Tensor, + ) -> torch.Tensor: + """Apply BN denormalization to packed latents (inverse of normalization). + + Inverse BN (affine=False): x = y * std + mean + + Args: + x: Packed latents of shape (B, seq, 128). + bn_mean: BN running mean of shape (128,). + bn_std: BN running std of shape (128,). + + Returns: + Denormalized latents of same shape. + """ + # x: (B, seq, 128), params: (128,) -> broadcast over batch and sequence dims + bn_mean = bn_mean.to(x.device, x.dtype) + bn_std = bn_std.to(x.device, x.dtype) + return x * bn_std + bn_mean + + @torch.no_grad() + def invoke(self, context: InvocationContext) -> LatentsOutput: + latents = self._run_diffusion(context) + 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, context: InvocationContext) -> torch.Tensor: + inference_dtype = torch.bfloat16 + device = TorchDevice.choose_torch_device() + + # Get BN statistics from VAE for latent denormalization (optional) + # BFL FLUX.2 VAE uses affine=False, so only mean/std are needed + # Some VAE formats (e.g. diffusers) may not expose BN stats directly + bn_stats = self._get_bn_stats(context) + bn_mean, bn_std = bn_stats if bn_stats is not None else (None, None) + + # 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=device, dtype=inference_dtype) + + # Prepare input noise (FLUX.2 uses 32 channels) + noise = get_noise_flux2( + num_samples=1, + height=self.height, + width=self.width, + device=device, + dtype=inference_dtype, + seed=self.seed, + ) + b, _c, latent_h, latent_w = noise.shape + packed_h = latent_h // 2 + packed_w = latent_w // 2 + + # Load the conditioning data + pos_cond_data = context.conditioning.load(self.positive_text_conditioning.conditioning_name) + assert len(pos_cond_data.conditionings) == 1 + pos_flux_conditioning = pos_cond_data.conditionings[0] + assert isinstance(pos_flux_conditioning, FLUXConditioningInfo) + pos_flux_conditioning = pos_flux_conditioning.to(dtype=inference_dtype, device=device) + + # Qwen3 stacked embeddings (stored in t5_embeds field for compatibility) + txt = pos_flux_conditioning.t5_embeds + + # Generate text position IDs (4D format for FLUX.2: T, H, W, L) + # FLUX.2 uses 4D position coordinates for its rotary position embeddings + # IMPORTANT: Position IDs must be int64 (long) dtype + # Diffusers uses: T=0, H=0, W=0, L=0..seq_len-1 + seq_len = txt.shape[1] + txt_ids = torch.zeros(1, seq_len, 4, device=device, dtype=torch.long) + txt_ids[..., 3] = torch.arange(seq_len, device=device, dtype=torch.long) # L coordinate varies + + # Load negative conditioning if provided + neg_txt = None + neg_txt_ids = None + if self.negative_text_conditioning is not None: + neg_cond_data = context.conditioning.load(self.negative_text_conditioning.conditioning_name) + assert len(neg_cond_data.conditionings) == 1 + neg_flux_conditioning = neg_cond_data.conditionings[0] + assert isinstance(neg_flux_conditioning, FLUXConditioningInfo) + neg_flux_conditioning = neg_flux_conditioning.to(dtype=inference_dtype, device=device) + neg_txt = neg_flux_conditioning.t5_embeds + # For text tokens: T=0, H=0, W=0, L=0..seq_len-1 (only L varies per token) + neg_seq_len = neg_txt.shape[1] + neg_txt_ids = torch.zeros(1, neg_seq_len, 4, device=device, dtype=torch.long) + neg_txt_ids[..., 3] = torch.arange(neg_seq_len, device=device, dtype=torch.long) + + # Validate transformer config + transformer_config = context.models.get_config(self.transformer.transformer) + assert transformer_config.base == BaseModelType.Flux2 and transformer_config.type == ModelType.Main + + # Calculate the timestep schedule using FLUX.2 specific schedule + # This matches diffusers' Flux2Pipeline implementation + # Note: Schedule shifting is handled by the scheduler via mu parameter + image_seq_len = packed_h * packed_w + timesteps = get_schedule_flux2( + num_steps=self.num_steps, + image_seq_len=image_seq_len, + ) + # Compute mu for dynamic schedule shifting (used by FlowMatchEulerDiscreteScheduler) + mu = compute_empirical_mu(image_seq_len=image_seq_len, num_steps=self.num_steps) + + # Clip the timesteps schedule based on denoising_start and denoising_end + timesteps = clip_timestep_schedule_fractional(timesteps, self.denoising_start, self.denoising_end) + + # Prepare input latent image + if init_latents is not None: + if self.add_noise: + t_0 = timesteps[0] + x = t_0 * noise + (1.0 - t_0) * init_latents + else: + x = init_latents + else: + if self.denoising_start > 1e-5: + raise ValueError("denoising_start should be 0 when initial latents are not provided.") + x = noise + + # If len(timesteps) == 1, then short-circuit + if len(timesteps) <= 1: + return x + + # Generate image position IDs (FLUX.2 uses 4D coordinates) + # Position IDs use int64 dtype like diffusers + img_ids = generate_img_ids_flux2(h=latent_h, w=latent_w, batch_size=b, device=device) + + # Prepare inpaint mask + inpaint_mask = self._prep_inpaint_mask(context, x) + + # Pack all latent tensors + init_latents_packed = pack_flux2(init_latents) if init_latents is not None else None + inpaint_mask_packed = pack_flux2(inpaint_mask) if inpaint_mask is not None else None + noise_packed = pack_flux2(noise) + x = pack_flux2(x) + + # Apply BN normalization BEFORE denoising (as per diffusers Flux2KleinPipeline) + # BN normalization: y = (x - mean) / std + # This transforms latents to normalized space for the transformer + # IMPORTANT: Also normalize init_latents and noise for inpainting to maintain consistency + if bn_mean is not None and bn_std is not None: + x = self._bn_normalize(x, bn_mean, bn_std) + if init_latents_packed is not None: + init_latents_packed = self._bn_normalize(init_latents_packed, bn_mean, bn_std) + noise_packed = self._bn_normalize(noise_packed, bn_mean, bn_std) + + # Verify packed dimensions + assert packed_h * packed_w == x.shape[1] + + # Prepare inpaint extension + inpaint_extension: Optional[RectifiedFlowInpaintExtension] = None + if inpaint_mask_packed is not None: + assert init_latents_packed is not None + inpaint_extension = RectifiedFlowInpaintExtension( + init_latents=init_latents_packed, + inpaint_mask=inpaint_mask_packed, + noise=noise_packed, + ) + + # Prepare CFG scale list + num_steps = len(timesteps) - 1 + cfg_scale_list = [self.cfg_scale] * num_steps + + # Check if we're doing inpainting (have a mask or a clipped schedule) + is_inpainting = self.denoise_mask is not None or self.denoising_start > 1e-5 + + # Create scheduler with FLUX.2 Klein configuration + # For inpainting/img2img, use manual Euler stepping to preserve the exact timestep schedule + # For txt2img, use the scheduler with dynamic shifting for optimal results + scheduler = None + if self.scheduler in FLUX_SCHEDULER_MAP and not is_inpainting: + # Only use scheduler for txt2img - use manual Euler for inpainting to preserve exact timesteps + scheduler_class = FLUX_SCHEDULER_MAP[self.scheduler] + scheduler = scheduler_class( + num_train_timesteps=1000, + shift=3.0, + use_dynamic_shifting=True, + base_shift=0.5, + max_shift=1.15, + base_image_seq_len=256, + max_image_seq_len=4096, + time_shift_type="exponential", + ) + + # Prepare reference image extension for FLUX.2 Klein built-in editing + ref_image_extension = None + if self.kontext_conditioning: + ref_image_extension = Flux2RefImageExtension( + context=context, + ref_image_conditioning=self.kontext_conditioning + if isinstance(self.kontext_conditioning, list) + else [self.kontext_conditioning], + vae_field=self.vae, + device=device, + dtype=inference_dtype, + bn_mean=bn_mean, + bn_std=bn_std, + ) + + with ExitStack() as exit_stack: + # Load the transformer model + (cached_weights, transformer) = exit_stack.enter_context( + context.models.load(self.transformer.transformer).model_on_device() + ) + config = transformer_config + + # Determine if the model is quantized + if config.format in [ModelFormat.Diffusers]: + model_is_quantized = False + elif config.format in [ + ModelFormat.BnbQuantizedLlmInt8b, + ModelFormat.BnbQuantizednf4b, + ModelFormat.GGUFQuantized, + ]: + model_is_quantized = True + else: + model_is_quantized = False + + # Apply LoRA models to the transformer + exit_stack.enter_context( + LayerPatcher.apply_smart_model_patches( + model=transformer, + patches=self._lora_iterator(context), + prefix=FLUX_LORA_TRANSFORMER_PREFIX, + dtype=inference_dtype, + cached_weights=cached_weights, + force_sidecar_patching=model_is_quantized, + ) + ) + + # Prepare reference image conditioning if provided + img_cond_seq = None + img_cond_seq_ids = None + if ref_image_extension is not None: + # Ensure batch sizes match + ref_image_extension.ensure_batch_size(x.shape[0]) + img_cond_seq, img_cond_seq_ids = ( + ref_image_extension.ref_image_latents, + ref_image_extension.ref_image_ids, + ) + + x = denoise( + model=transformer, + img=x, + img_ids=img_ids, + txt=txt, + txt_ids=txt_ids, + timesteps=timesteps, + step_callback=self._build_step_callback(context), + cfg_scale=cfg_scale_list, + neg_txt=neg_txt, + neg_txt_ids=neg_txt_ids, + scheduler=scheduler, + mu=mu, + inpaint_extension=inpaint_extension, + img_cond_seq=img_cond_seq, + img_cond_seq_ids=img_cond_seq_ids, + ) + + # Apply BN denormalization if BN stats are available + # The diffusers Flux2KleinPipeline applies: latents = latents * bn_std + bn_mean + # This transforms latents from normalized space to VAE's expected input space + if bn_mean is not None and bn_std is not None: + x = self._bn_denormalize(x, bn_mean, bn_std) + + x = unpack_flux2(x.float(), self.height, self.width) + return x + + def _prep_inpaint_mask(self, context: InvocationContext, latents: torch.Tensor) -> Optional[torch.Tensor]: + """Prepare the inpaint mask.""" + if self.denoise_mask is None: + return None + + mask = context.tensors.load(self.denoise_mask.mask_name) + mask = 1.0 - mask + + _, _, 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.expand_as(latents) + + def _lora_iterator(self, context: InvocationContext) -> Iterator[Tuple[ModelPatchRaw, float]]: + """Iterate over LoRA models to apply.""" + for lora in self.transformer.loras: + lora_info = context.models.load(lora.lora) + assert isinstance(lora_info.model, ModelPatchRaw) + yield (lora_info.model, lora.weight) + del lora_info + + def _build_step_callback(self, context: InvocationContext) -> Callable[[PipelineIntermediateState], None]: + """Build a callback for step progress updates.""" + + def step_callback(state: PipelineIntermediateState) -> None: + latents = state.latents.float() + state.latents = unpack_flux2(latents, self.height, self.width).squeeze() + context.util.flux2_step_callback(state) + + return step_callback diff --git a/invokeai/app/invocations/flux2_klein_model_loader.py b/invokeai/app/invocations/flux2_klein_model_loader.py new file mode 100644 index 0000000000..f39e7688f3 --- /dev/null +++ b/invokeai/app/invocations/flux2_klein_model_loader.py @@ -0,0 +1,222 @@ +"""Flux2 Klein Model Loader Invocation. + +Loads a Flux2 Klein model with its Qwen3 text encoder and VAE. +Unlike standard FLUX which uses CLIP+T5, Klein uses only Qwen3. +""" + +from typing import Literal, Optional + +from invokeai.app.invocations.baseinvocation import ( + BaseInvocation, + BaseInvocationOutput, + Classification, + invocation, + invocation_output, +) +from invokeai.app.invocations.fields import FieldDescriptions, Input, InputField, OutputField +from invokeai.app.invocations.model import ( + ModelIdentifierField, + Qwen3EncoderField, + TransformerField, + VAEField, +) +from invokeai.app.services.shared.invocation_context import InvocationContext +from invokeai.backend.model_manager.taxonomy import ( + BaseModelType, + Flux2VariantType, + ModelFormat, + ModelType, + Qwen3VariantType, + SubModelType, +) + + +@invocation_output("flux2_klein_model_loader_output") +class Flux2KleinModelLoaderOutput(BaseInvocationOutput): + """Flux2 Klein model loader output.""" + + transformer: TransformerField = OutputField(description=FieldDescriptions.transformer, title="Transformer") + qwen3_encoder: Qwen3EncoderField = OutputField(description=FieldDescriptions.qwen3_encoder, title="Qwen3 Encoder") + vae: VAEField = OutputField(description=FieldDescriptions.vae, title="VAE") + max_seq_len: Literal[256, 512] = OutputField( + description="The max sequence length for the Qwen3 encoder.", + title="Max Seq Length", + ) + + +@invocation( + "flux2_klein_model_loader", + title="Main Model - Flux2 Klein", + tags=["model", "flux", "klein", "qwen3"], + category="model", + version="1.0.0", + classification=Classification.Prototype, +) +class Flux2KleinModelLoaderInvocation(BaseInvocation): + """Loads a Flux2 Klein model, outputting its submodels. + + Flux2 Klein uses Qwen3 as the text encoder instead of CLIP+T5. + It uses a 32-channel VAE (AutoencoderKLFlux2) instead of the 16-channel FLUX.1 VAE. + + When using a Diffusers format model, both VAE and Qwen3 encoder are extracted + automatically from the main model. You can override with standalone models: + - Transformer: Always from Flux2 Klein main model + - VAE: From main model (Diffusers) or standalone VAE + - Qwen3 Encoder: From main model (Diffusers) or standalone Qwen3 model + """ + + model: ModelIdentifierField = InputField( + description=FieldDescriptions.flux_model, + input=Input.Direct, + ui_model_base=BaseModelType.Flux2, + ui_model_type=ModelType.Main, + title="Transformer", + ) + + vae_model: Optional[ModelIdentifierField] = InputField( + default=None, + description="Standalone VAE model. Flux2 Klein uses the same VAE as FLUX (16-channel). " + "If not provided, VAE will be loaded from the Qwen3 Source model.", + input=Input.Direct, + ui_model_base=[BaseModelType.Flux, BaseModelType.Flux2], + ui_model_type=ModelType.VAE, + title="VAE", + ) + + qwen3_encoder_model: Optional[ModelIdentifierField] = InputField( + default=None, + description="Standalone Qwen3 Encoder model. " + "If not provided, encoder will be loaded from the Qwen3 Source model.", + input=Input.Direct, + ui_model_type=ModelType.Qwen3Encoder, + title="Qwen3 Encoder", + ) + + qwen3_source_model: Optional[ModelIdentifierField] = InputField( + default=None, + description="Diffusers Flux2 Klein model to extract VAE and/or Qwen3 encoder from. " + "Use this if you don't have separate VAE/Qwen3 models. " + "Ignored if both VAE and Qwen3 Encoder are provided separately.", + input=Input.Direct, + ui_model_base=BaseModelType.Flux2, + ui_model_type=ModelType.Main, + ui_model_format=ModelFormat.Diffusers, + title="Qwen3 Source (Diffusers)", + ) + + max_seq_len: Literal[256, 512] = InputField( + default=512, + description="Max sequence length for the Qwen3 encoder.", + title="Max Seq Length", + ) + + def invoke(self, context: InvocationContext) -> Flux2KleinModelLoaderOutput: + # Transformer always comes from the main model + transformer = self.model.model_copy(update={"submodel_type": SubModelType.Transformer}) + + # Check if main model is Diffusers format (can extract VAE directly) + main_config = context.models.get_config(self.model) + main_is_diffusers = main_config.format == ModelFormat.Diffusers + + # Determine VAE source + # IMPORTANT: FLUX.2 Klein uses a 32-channel VAE (AutoencoderKLFlux2), not the 16-channel FLUX.1 VAE. + # The VAE should come from the FLUX.2 Klein Diffusers model, not a separate FLUX VAE. + if self.vae_model is not None: + # Use standalone VAE (user explicitly selected one) + vae = self.vae_model.model_copy(update={"submodel_type": SubModelType.VAE}) + elif main_is_diffusers: + # Extract VAE from main model (recommended for FLUX.2) + vae = self.model.model_copy(update={"submodel_type": SubModelType.VAE}) + elif self.qwen3_source_model is not None: + # Extract from Qwen3 source Diffusers model + self._validate_diffusers_format(context, self.qwen3_source_model, "Qwen3 Source") + vae = self.qwen3_source_model.model_copy(update={"submodel_type": SubModelType.VAE}) + else: + raise ValueError( + "No VAE source provided. Standalone safetensors/GGUF models require a separate VAE. " + "Options:\n" + " 1. Set 'VAE' to a standalone FLUX VAE model\n" + " 2. Set 'Qwen3 Source' to a Diffusers Flux2 Klein model to extract the VAE from" + ) + + # Determine Qwen3 Encoder source + if self.qwen3_encoder_model is not None: + # Use standalone Qwen3 Encoder - validate it matches the FLUX.2 Klein variant + self._validate_qwen3_encoder_variant(context, main_config) + qwen3_tokenizer = self.qwen3_encoder_model.model_copy(update={"submodel_type": SubModelType.Tokenizer}) + qwen3_encoder = self.qwen3_encoder_model.model_copy(update={"submodel_type": SubModelType.TextEncoder}) + elif main_is_diffusers: + # Extract from main model (recommended for FLUX.2 Klein) + qwen3_tokenizer = self.model.model_copy(update={"submodel_type": SubModelType.Tokenizer}) + qwen3_encoder = self.model.model_copy(update={"submodel_type": SubModelType.TextEncoder}) + elif self.qwen3_source_model is not None: + # Extract from separate Diffusers model + self._validate_diffusers_format(context, self.qwen3_source_model, "Qwen3 Source") + qwen3_tokenizer = self.qwen3_source_model.model_copy(update={"submodel_type": SubModelType.Tokenizer}) + qwen3_encoder = self.qwen3_source_model.model_copy(update={"submodel_type": SubModelType.TextEncoder}) + else: + raise ValueError( + "No Qwen3 Encoder source provided. Standalone safetensors/GGUF models require a separate text encoder. " + "Options:\n" + " 1. Set 'Qwen3 Encoder' to a standalone Qwen3 text encoder model " + "(Klein 4B needs Qwen3 4B, Klein 9B needs Qwen3 8B)\n" + " 2. Set 'Qwen3 Source' to a Diffusers Flux2 Klein model to extract the encoder from" + ) + + return Flux2KleinModelLoaderOutput( + transformer=TransformerField(transformer=transformer, loras=[]), + qwen3_encoder=Qwen3EncoderField(tokenizer=qwen3_tokenizer, text_encoder=qwen3_encoder), + vae=VAEField(vae=vae), + max_seq_len=self.max_seq_len, + ) + + def _validate_diffusers_format( + self, context: InvocationContext, model: ModelIdentifierField, model_name: str + ) -> None: + """Validate that a model is in Diffusers format.""" + config = context.models.get_config(model) + if config.format != ModelFormat.Diffusers: + raise ValueError( + f"The {model_name} model must be a Diffusers format model. " + f"The selected model '{config.name}' is in {config.format.value} format." + ) + + def _validate_qwen3_encoder_variant(self, context: InvocationContext, main_config) -> None: + """Validate that the standalone Qwen3 encoder variant matches the FLUX.2 Klein variant. + + - FLUX.2 Klein 4B requires Qwen3 4B encoder + - FLUX.2 Klein 9B requires Qwen3 8B encoder + """ + if self.qwen3_encoder_model is None: + return + + # Get the Qwen3 encoder config + qwen3_config = context.models.get_config(self.qwen3_encoder_model) + + # Check if the config has a variant field + if not hasattr(qwen3_config, "variant"): + # Can't validate, skip + return + + qwen3_variant = qwen3_config.variant + + # Get the FLUX.2 Klein variant from the main model config + if not hasattr(main_config, "variant"): + return + + flux2_variant = main_config.variant + + # Validate the variants match + # Klein4B requires Qwen3_4B, Klein9B/Klein9BBase requires Qwen3_8B + expected_qwen3_variant = None + if flux2_variant == Flux2VariantType.Klein4B: + expected_qwen3_variant = Qwen3VariantType.Qwen3_4B + elif flux2_variant in (Flux2VariantType.Klein9B, Flux2VariantType.Klein9BBase): + expected_qwen3_variant = Qwen3VariantType.Qwen3_8B + + if expected_qwen3_variant is not None and qwen3_variant != expected_qwen3_variant: + raise ValueError( + f"Qwen3 encoder variant mismatch: FLUX.2 Klein {flux2_variant.value} requires " + f"{expected_qwen3_variant.value} encoder, but {qwen3_variant.value} was selected. " + f"Please select a matching Qwen3 encoder or use a Diffusers format model which includes the correct encoder." + ) diff --git a/invokeai/app/invocations/flux2_klein_text_encoder.py b/invokeai/app/invocations/flux2_klein_text_encoder.py new file mode 100644 index 0000000000..e59d945d6d --- /dev/null +++ b/invokeai/app/invocations/flux2_klein_text_encoder.py @@ -0,0 +1,222 @@ +"""Flux2 Klein Text Encoder Invocation. + +Flux2 Klein uses Qwen3 as the text encoder instead of CLIP+T5. +The key difference is that it extracts hidden states from layers (9, 18, 27) +and stacks them together for richer text representations. + +This implementation matches the diffusers Flux2KleinPipeline exactly. +""" + +from contextlib import ExitStack +from typing import Iterator, Literal, Optional, Tuple + +import torch +from transformers import PreTrainedModel, PreTrainedTokenizerBase + +from invokeai.app.invocations.baseinvocation import BaseInvocation, Classification, invocation +from invokeai.app.invocations.fields import ( + FieldDescriptions, + FluxConditioningField, + Input, + InputField, + TensorField, + UIComponent, +) +from invokeai.app.invocations.model import Qwen3EncoderField +from invokeai.app.invocations.primitives import FluxConditioningOutput +from invokeai.app.services.shared.invocation_context import InvocationContext +from invokeai.backend.patches.layer_patcher import LayerPatcher +from invokeai.backend.patches.lora_conversions.flux_lora_constants import FLUX_LORA_T5_PREFIX +from invokeai.backend.patches.model_patch_raw import ModelPatchRaw +from invokeai.backend.stable_diffusion.diffusion.conditioning_data import ConditioningFieldData, FLUXConditioningInfo +from invokeai.backend.util.devices import TorchDevice + +# FLUX.2 Klein extracts hidden states from these specific layers +# Matching diffusers Flux2KleinPipeline: (9, 18, 27) +# hidden_states[0] is embedding layer, so layer N is at index N +KLEIN_EXTRACTION_LAYERS = (9, 18, 27) + +# Default max sequence length for Klein models +KLEIN_MAX_SEQ_LEN = 512 + + +@invocation( + "flux2_klein_text_encoder", + title="Prompt - Flux2 Klein", + tags=["prompt", "conditioning", "flux", "klein", "qwen3"], + category="conditioning", + version="1.1.0", + classification=Classification.Prototype, +) +class Flux2KleinTextEncoderInvocation(BaseInvocation): + """Encodes and preps a prompt for Flux2 Klein image generation. + + Flux2 Klein uses Qwen3 as the text encoder, extracting hidden states from + layers (9, 18, 27) and stacking them for richer text representations. + This matches the diffusers Flux2KleinPipeline implementation exactly. + """ + + prompt: str = InputField(description="Text prompt to encode.", ui_component=UIComponent.Textarea) + qwen3_encoder: Qwen3EncoderField = InputField( + title="Qwen3 Encoder", + description=FieldDescriptions.qwen3_encoder, + input=Input.Connection, + ) + max_seq_len: Literal[256, 512] = InputField( + default=512, + description="Max sequence length for the Qwen3 encoder.", + ) + mask: Optional[TensorField] = InputField( + default=None, + description="A mask defining the region that this conditioning prompt applies to.", + ) + + @torch.no_grad() + def invoke(self, context: InvocationContext) -> FluxConditioningOutput: + qwen3_embeds, pooled_embeds = self._encode_prompt(context) + + # Use FLUXConditioningInfo for compatibility with existing Flux denoiser + # t5_embeds -> qwen3 stacked embeddings + # clip_embeds -> pooled qwen3 embedding + conditioning_data = ConditioningFieldData( + conditionings=[FLUXConditioningInfo(clip_embeds=pooled_embeds, t5_embeds=qwen3_embeds)] + ) + + conditioning_name = context.conditioning.save(conditioning_data) + return FluxConditioningOutput( + conditioning=FluxConditioningField(conditioning_name=conditioning_name, mask=self.mask) + ) + + def _encode_prompt(self, context: InvocationContext) -> Tuple[torch.Tensor, torch.Tensor]: + """Encode prompt using Qwen3 text encoder with Klein-style layer extraction. + + This matches the diffusers Flux2KleinPipeline._get_qwen3_prompt_embeds() exactly. + + Returns: + Tuple of (stacked_embeddings, pooled_embedding): + - stacked_embeddings: Hidden states from layers (9, 18, 27) stacked together. + Shape: (1, seq_len, hidden_size * 3) + - pooled_embedding: Pooled representation for global conditioning. + Shape: (1, hidden_size) + """ + prompt = self.prompt + device = TorchDevice.choose_torch_device() + + text_encoder_info = context.models.load(self.qwen3_encoder.text_encoder) + tokenizer_info = context.models.load(self.qwen3_encoder.tokenizer) + + with ExitStack() as exit_stack: + (cached_weights, text_encoder) = exit_stack.enter_context(text_encoder_info.model_on_device()) + (_, tokenizer) = exit_stack.enter_context(tokenizer_info.model_on_device()) + + # Apply LoRA models to the text encoder + lora_dtype = TorchDevice.choose_bfloat16_safe_dtype(device) + exit_stack.enter_context( + LayerPatcher.apply_smart_model_patches( + model=text_encoder, + patches=self._lora_iterator(context), + prefix=FLUX_LORA_T5_PREFIX, # Reuse T5 prefix for Qwen3 LoRAs + dtype=lora_dtype, + cached_weights=cached_weights, + ) + ) + + context.util.signal_progress("Running Qwen3 text encoder (Klein)") + + if not isinstance(text_encoder, PreTrainedModel): + raise TypeError( + f"Expected PreTrainedModel for text encoder, got {type(text_encoder).__name__}. " + "The Qwen3 encoder model may be corrupted or incompatible." + ) + if not isinstance(tokenizer, PreTrainedTokenizerBase): + raise TypeError( + f"Expected PreTrainedTokenizerBase for tokenizer, got {type(tokenizer).__name__}. " + "The Qwen3 tokenizer may be corrupted or incompatible." + ) + + # Format messages exactly like diffusers Flux2KleinPipeline: + # - Only user message, NO system message + # - add_generation_prompt=True (adds assistant prefix) + # - enable_thinking=False + messages = [{"role": "user", "content": prompt}] + + # Step 1: Apply chat template to get formatted text (tokenize=False) + text: str = tokenizer.apply_chat_template( # type: ignore[assignment] + messages, + tokenize=False, + add_generation_prompt=True, # Adds assistant prefix like diffusers + enable_thinking=False, # Disable thinking mode + ) + + # Step 2: Tokenize the formatted text + inputs = tokenizer( + text, + return_tensors="pt", + padding="max_length", + truncation=True, + max_length=self.max_seq_len, + ) + + input_ids = inputs["input_ids"] + attention_mask = inputs["attention_mask"] + + # Move to device + input_ids = input_ids.to(device) + attention_mask = attention_mask.to(device) + + # Forward pass through the model - matching diffusers exactly + outputs = text_encoder( + input_ids=input_ids, + attention_mask=attention_mask, + output_hidden_states=True, + use_cache=False, + ) + + # Validate hidden_states output + if not hasattr(outputs, "hidden_states") or outputs.hidden_states is None: + raise RuntimeError( + "Text encoder did not return hidden_states. " + "Ensure output_hidden_states=True is supported by this model." + ) + + num_hidden_layers = len(outputs.hidden_states) + + # Extract and stack hidden states - EXACTLY like diffusers: + # out = torch.stack([output.hidden_states[k] for k in hidden_states_layers], dim=1) + # prompt_embeds = out.permute(0, 2, 1, 3).reshape(batch_size, seq_len, num_channels * hidden_dim) + hidden_states_list = [] + for layer_idx in KLEIN_EXTRACTION_LAYERS: + if layer_idx >= num_hidden_layers: + layer_idx = num_hidden_layers - 1 + hidden_states_list.append(outputs.hidden_states[layer_idx]) + + # Stack along dim=1, then permute and reshape - exactly like diffusers + out = torch.stack(hidden_states_list, dim=1) + out = out.to(dtype=text_encoder.dtype, device=device) + + batch_size, num_channels, seq_len, hidden_dim = out.shape + prompt_embeds = out.permute(0, 2, 1, 3).reshape(batch_size, seq_len, num_channels * hidden_dim) + + # Create pooled embedding for global conditioning + # Use mean pooling over the sequence (excluding padding) + # This serves a similar role to CLIP's pooled output in standard FLUX + last_hidden_state = outputs.hidden_states[-1] # Use last layer for pooling + # Expand mask to match hidden state dimensions + expanded_mask = attention_mask.unsqueeze(-1).expand_as(last_hidden_state).float() + sum_embeds = (last_hidden_state * expanded_mask).sum(dim=1) + num_tokens = expanded_mask.sum(dim=1).clamp(min=1) + pooled_embeds = sum_embeds / num_tokens + + return prompt_embeds, pooled_embeds + + def _lora_iterator(self, context: InvocationContext) -> Iterator[Tuple[ModelPatchRaw, float]]: + """Iterate over LoRA models to apply to the Qwen3 text encoder.""" + for lora in self.qwen3_encoder.loras: + lora_info = context.models.load(lora.lora) + if not isinstance(lora_info.model, ModelPatchRaw): + raise TypeError( + f"Expected ModelPatchRaw for LoRA '{lora.lora.key}', got {type(lora_info.model).__name__}. " + "The LoRA model may be corrupted or incompatible." + ) + yield (lora_info.model, lora.weight) + del lora_info diff --git a/invokeai/app/invocations/flux2_vae_decode.py b/invokeai/app/invocations/flux2_vae_decode.py new file mode 100644 index 0000000000..8450d1ec85 --- /dev/null +++ b/invokeai/app/invocations/flux2_vae_decode.py @@ -0,0 +1,106 @@ +"""Flux2 Klein VAE Decode Invocation. + +Decodes latents to images using the FLUX.2 32-channel VAE (AutoencoderKLFlux2). +""" + +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 ( + 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.model_manager.load.load_base import LoadedModel +from invokeai.backend.util.devices import TorchDevice + + +@invocation( + "flux2_vae_decode", + title="Latents to Image - FLUX2", + tags=["latents", "image", "vae", "l2i", "flux2", "klein"], + category="latents", + version="1.0.0", + classification=Classification.Prototype, +) +class Flux2VaeDecodeInvocation(BaseInvocation, WithMetadata, WithBoard): + """Generates an image from latents using FLUX.2 Klein's 32-channel VAE.""" + + 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: + """Decode latents to image using FLUX.2 VAE. + + Input latents should already be in the correct space after BN denormalization + was applied in the denoiser. The VAE expects (B, 32, H, W) format. + """ + with vae_info.model_on_device() as (_, vae): + vae_dtype = next(iter(vae.parameters())).dtype + device = TorchDevice.choose_torch_device() + latents = latents.to(device=device, dtype=vae_dtype) + + # Decode using diffusers API + decoded = vae.decode(latents, return_dict=False)[0] + + # Debug: Log decoded output statistics + print( + f"[FLUX.2 VAE] Decoded output: shape={decoded.shape}, " + f"min={decoded.min().item():.4f}, max={decoded.max().item():.4f}, " + f"mean={decoded.mean().item():.4f}" + ) + # Check per-channel statistics to diagnose color issues + for c in range(min(3, decoded.shape[1])): + ch = decoded[0, c] + print( + f"[FLUX.2 VAE] Channel {c}: min={ch.min().item():.4f}, " + f"max={ch.max().item():.4f}, mean={ch.mean().item():.4f}" + ) + + # Convert from [-1, 1] to [0, 1] then to [0, 255] PIL image + img = (decoded / 2 + 0.5).clamp(0, 1) + img = rearrange(img[0], "c h w -> h w c") + img_np = (img * 255).byte().cpu().numpy() + # Explicitly create RGB image (not grayscale) + img_pil = Image.fromarray(img_np, mode="RGB") + return img_pil + + @torch.no_grad() + def invoke(self, context: InvocationContext) -> ImageOutput: + latents = context.tensors.load(self.latents.latents_name) + + # Log latent statistics for debugging black image issues + context.logger.debug( + f"FLUX.2 VAE decode input: shape={latents.shape}, " + f"min={latents.min().item():.4f}, max={latents.max().item():.4f}, " + f"mean={latents.mean().item():.4f}" + ) + + # Warn if input latents are all zeros or very small (would cause black images) + if latents.abs().max() < 1e-6: + context.logger.warning( + "FLUX.2 VAE decode received near-zero latents! This will cause black images. " + "The latent cache may be corrupted - try clearing the cache." + ) + + vae_info = context.models.load(self.vae.vae) + context.util.signal_progress("Running 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/flux2_vae_encode.py b/invokeai/app/invocations/flux2_vae_encode.py new file mode 100644 index 0000000000..1b43483a40 --- /dev/null +++ b/invokeai/app/invocations/flux2_vae_encode.py @@ -0,0 +1,88 @@ +"""Flux2 Klein VAE Encode Invocation. + +Encodes images to latents using the FLUX.2 32-channel VAE (AutoencoderKLFlux2). +""" + +import einops +import torch + +from invokeai.app.invocations.baseinvocation import BaseInvocation, Classification, 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.model_manager.load.load_base import LoadedModel +from invokeai.backend.stable_diffusion.diffusers_pipeline import image_resized_to_grid_as_tensor +from invokeai.backend.util.devices import TorchDevice + + +@invocation( + "flux2_vae_encode", + title="Image to Latents - FLUX2", + tags=["latents", "image", "vae", "i2l", "flux2", "klein"], + category="latents", + version="1.0.0", + classification=Classification.Prototype, +) +class Flux2VaeEncodeInvocation(BaseInvocation): + """Encodes an image into latents using FLUX.2 Klein's 32-channel VAE.""" + + image: ImageField = InputField( + description="The image to encode.", + ) + vae: VAEField = InputField( + description=FieldDescriptions.vae, + input=Input.Connection, + ) + + def _vae_encode(self, vae_info: LoadedModel, image_tensor: torch.Tensor) -> torch.Tensor: + """Encode image to latents using FLUX.2 VAE. + + The VAE encodes to 32-channel latent space. + Output latents shape: (B, 32, H/8, W/8). + """ + with vae_info.model_on_device() as (_, vae): + vae_dtype = next(iter(vae.parameters())).dtype + device = TorchDevice.choose_torch_device() + image_tensor = image_tensor.to(device=device, dtype=vae_dtype) + + # Encode using diffusers API + # The VAE.encode() returns a DiagonalGaussianDistribution-like object + latent_dist = vae.encode(image_tensor, return_dict=False)[0] + + # Sample from the distribution (or use mode for deterministic output) + # Using mode() for deterministic encoding + if hasattr(latent_dist, "mode"): + latents = latent_dist.mode() + elif hasattr(latent_dist, "sample"): + # Fall back to sampling if mode is not available + generator = torch.Generator(device=device).manual_seed(0) + latents = latent_dist.sample(generator=generator) + else: + # Direct tensor output (some VAE implementations) + latents = latent_dist + + 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) + + # Convert image to tensor (HWC -> CHW, normalize to [-1, 1]) + 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") + + context.util.signal_progress("Running VAE Encode") + 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/flux_denoise.py b/invokeai/app/invocations/flux_denoise.py index be2c7d70fa..a8b5957b8e 100644 --- a/invokeai/app/invocations/flux_denoise.py +++ b/invokeai/app/invocations/flux_denoise.py @@ -239,8 +239,14 @@ class FluxDenoiseInvocation(BaseInvocation): ) transformer_config = context.models.get_config(self.transformer.transformer) - assert transformer_config.base is BaseModelType.Flux and transformer_config.type is ModelType.Main - is_schnell = transformer_config.variant is FluxVariantType.Schnell + assert ( + transformer_config.base in (BaseModelType.Flux, BaseModelType.Flux2) + and transformer_config.type is ModelType.Main + ) + # Schnell is only for FLUX.1, FLUX.2 Klein behaves like Dev (with guidance) + is_schnell = ( + transformer_config.base is BaseModelType.Flux and transformer_config.variant is FluxVariantType.Schnell + ) # Calculate the timestep schedule. timesteps = get_schedule( diff --git a/invokeai/app/invocations/flux_lora_loader.py b/invokeai/app/invocations/flux_lora_loader.py index f939ea2dc5..0fd96e097d 100644 --- a/invokeai/app/invocations/flux_lora_loader.py +++ b/invokeai/app/invocations/flux_lora_loader.py @@ -162,7 +162,7 @@ class FLUXLoRACollectionLoader(BaseInvocation): if not context.models.exists(lora.lora.key): raise Exception(f"Unknown lora: {lora.lora.key}!") - assert lora.lora.base is BaseModelType.Flux + assert lora.lora.base in (BaseModelType.Flux, BaseModelType.Flux2) added_loras.append(lora.lora.key) diff --git a/invokeai/app/invocations/ideal_size.py b/invokeai/app/invocations/ideal_size.py index a3f36b6049..aae3a37c8e 100644 --- a/invokeai/app/invocations/ideal_size.py +++ b/invokeai/app/invocations/ideal_size.py @@ -46,7 +46,12 @@ class IdealSizeInvocation(BaseInvocation): dimension = 512 elif unet_config.base == BaseModelType.StableDiffusion2: dimension = 768 - elif unet_config.base in (BaseModelType.StableDiffusionXL, BaseModelType.Flux, BaseModelType.StableDiffusion3): + elif unet_config.base in ( + BaseModelType.StableDiffusionXL, + BaseModelType.Flux, + BaseModelType.Flux2, + BaseModelType.StableDiffusion3, + ): dimension = 1024 else: raise ValueError(f"Unsupported model type: {unet_config.base}") diff --git a/invokeai/app/invocations/metadata.py b/invokeai/app/invocations/metadata.py index bdacec55eb..bc13b72c7b 100644 --- a/invokeai/app/invocations/metadata.py +++ b/invokeai/app/invocations/metadata.py @@ -150,6 +150,10 @@ GENERATION_MODES = Literal[ "flux_img2img", "flux_inpaint", "flux_outpaint", + "flux2_txt2img", + "flux2_img2img", + "flux2_inpaint", + "flux2_outpaint", "sd3_txt2img", "sd3_img2img", "sd3_inpaint", diff --git a/invokeai/app/invocations/model.py b/invokeai/app/invocations/model.py index 3f78f2b23d..29fbe5100c 100644 --- a/invokeai/app/invocations/model.py +++ b/invokeai/app/invocations/model.py @@ -510,6 +510,7 @@ class VAELoaderInvocation(BaseInvocation): BaseModelType.StableDiffusionXL, BaseModelType.StableDiffusion3, BaseModelType.Flux, + BaseModelType.Flux2, ], ui_model_type=ModelType.VAE, ) diff --git a/invokeai/app/services/model_records/model_records_base.py b/invokeai/app/services/model_records/model_records_base.py index 9dd69a00f5..546790cb3e 100644 --- a/invokeai/app/services/model_records/model_records_base.py +++ b/invokeai/app/services/model_records/model_records_base.py @@ -19,11 +19,13 @@ from invokeai.backend.model_manager.configs.main import MainModelDefaultSettings from invokeai.backend.model_manager.taxonomy import ( BaseModelType, ClipVariantType, + Flux2VariantType, FluxVariantType, ModelFormat, ModelSourceType, ModelType, ModelVariantType, + Qwen3VariantType, SchedulerPredictionType, ) @@ -89,8 +91,8 @@ class ModelRecordChanges(BaseModelExcludeNull): # Checkpoint-specific changes # TODO(MM2): Should we expose these? Feels footgun-y... - variant: Optional[ModelVariantType | ClipVariantType | FluxVariantType] = Field( - description="The variant of the model.", default=None + variant: Optional[ModelVariantType | ClipVariantType | FluxVariantType | Flux2VariantType | Qwen3VariantType] = ( + Field(description="The variant of the model.", default=None) ) prediction_type: Optional[SchedulerPredictionType] = Field( description="The prediction type of the model.", default=None diff --git a/invokeai/app/services/shared/invocation_context.py b/invokeai/app/services/shared/invocation_context.py index 97291230e0..4ee43b29b7 100644 --- a/invokeai/app/services/shared/invocation_context.py +++ b/invokeai/app/services/shared/invocation_context.py @@ -630,6 +630,21 @@ class UtilInterface(InvocationContextInterface): is_canceled=self.is_canceled, ) + def flux2_step_callback(self, intermediate_state: PipelineIntermediateState) -> None: + """ + The step callback for FLUX.2 Klein models (32-channel VAE). + + Args: + intermediate_state: The intermediate state of the diffusion pipeline. + """ + + diffusion_step_callback( + signal_progress=self.signal_progress, + intermediate_state=intermediate_state, + base_model=BaseModelType.Flux2, + is_canceled=self.is_canceled, + ) + def signal_progress( self, message: str, diff --git a/invokeai/app/services/shared/sqlite/sqlite_util.py b/invokeai/app/services/shared/sqlite/sqlite_util.py index df0e5fca04..f6cb70b9df 100644 --- a/invokeai/app/services/shared/sqlite/sqlite_util.py +++ b/invokeai/app/services/shared/sqlite/sqlite_util.py @@ -27,6 +27,7 @@ from invokeai.app.services.shared.sqlite_migrator.migrations.migration_21 import from invokeai.app.services.shared.sqlite_migrator.migrations.migration_22 import build_migration_22 from invokeai.app.services.shared.sqlite_migrator.migrations.migration_23 import build_migration_23 from invokeai.app.services.shared.sqlite_migrator.migrations.migration_24 import build_migration_24 +from invokeai.app.services.shared.sqlite_migrator.migrations.migration_25 import build_migration_25 from invokeai.app.services.shared.sqlite_migrator.sqlite_migrator_impl import SqliteMigrator @@ -71,6 +72,7 @@ def init_db(config: InvokeAIAppConfig, logger: Logger, image_files: ImageFileSto migrator.register_migration(build_migration_22(app_config=config, logger=logger)) migrator.register_migration(build_migration_23(app_config=config, logger=logger)) migrator.register_migration(build_migration_24(app_config=config, logger=logger)) + migrator.register_migration(build_migration_25(app_config=config, logger=logger)) migrator.run_migrations() return db diff --git a/invokeai/app/services/shared/sqlite_migrator/migrations/migration_25.py b/invokeai/app/services/shared/sqlite_migrator/migrations/migration_25.py new file mode 100644 index 0000000000..0ce8a8ff6a --- /dev/null +++ b/invokeai/app/services/shared/sqlite_migrator/migrations/migration_25.py @@ -0,0 +1,61 @@ +import json +import sqlite3 +from logging import Logger +from typing import Any + +from invokeai.app.services.config import InvokeAIAppConfig +from invokeai.app.services.shared.sqlite_migrator.sqlite_migrator_common import Migration +from invokeai.backend.model_manager.taxonomy import ModelType, Qwen3VariantType + + +class Migration25Callback: + def __init__(self, app_config: InvokeAIAppConfig, logger: Logger) -> None: + self._app_config = app_config + self._logger = logger + + def __call__(self, cursor: sqlite3.Cursor) -> None: + cursor.execute("SELECT id, config FROM models;") + rows = cursor.fetchall() + + migrated_count = 0 + + for model_id, config_json in rows: + try: + config_dict: dict[str, Any] = json.loads(config_json) + + if config_dict.get("type") != ModelType.Qwen3Encoder.value: + continue + + if "variant" in config_dict: + continue + + config_dict["variant"] = Qwen3VariantType.Qwen3_4B.value + + cursor.execute( + "UPDATE models SET config = ? WHERE id = ?;", + (json.dumps(config_dict), model_id), + ) + migrated_count += 1 + + except json.JSONDecodeError as e: + self._logger.error("Invalid config JSON for model %s: %s", model_id, e) + raise + + if migrated_count > 0: + self._logger.info(f"Migration complete: {migrated_count} Qwen3 encoder configs updated with variant field") + else: + self._logger.info("Migration complete: no Qwen3 encoder configs needed migration") + + +def build_migration_25(app_config: InvokeAIAppConfig, logger: Logger) -> Migration: + """Builds the migration object for migrating from version 24 to version 25. + + This migration adds the variant field to existing Qwen3 encoder models. + Models installed before the variant field was added will default to Qwen3_4B (for Z-Image compatibility). + """ + + return Migration( + from_version=24, + to_version=25, + callback=Migration25Callback(app_config=app_config, logger=logger), + ) diff --git a/invokeai/app/util/step_callback.py b/invokeai/app/util/step_callback.py index 90417e9a42..c1aede86ad 100644 --- a/invokeai/app/util/step_callback.py +++ b/invokeai/app/util/step_callback.py @@ -93,6 +93,46 @@ COGVIEW4_LATENT_RGB_FACTORS = [ [-0.00955853, -0.00980067, -0.00977842], ] +# FLUX.2 uses 32 latent channels. Since we don't have proper factors yet, +# we extend FLUX factors with zeros for preview approximation. +FLUX2_LATENT_RGB_FACTORS = [ + # R G B + # First 16 channels (from FLUX) + [0.0118, 0.0024, 0.0017], + [-0.0074, -0.0108, -0.0003], + [0.0056, 0.0291, 0.0768], + [0.0342, -0.0681, -0.0427], + [-0.0258, 0.0092, 0.0463], + [0.0863, 0.0784, 0.0547], + [-0.0017, 0.0402, 0.0158], + [0.0501, 0.1058, 0.1152], + [-0.0209, -0.0218, -0.0329], + [-0.0314, 0.0083, 0.0896], + [0.0851, 0.0665, -0.0472], + [-0.0534, 0.0238, -0.0024], + [0.0452, -0.0026, 0.0048], + [0.0892, 0.0831, 0.0881], + [-0.1117, -0.0304, -0.0789], + [0.0027, -0.0479, -0.0043], + # Additional 16 channels (zeros as placeholder) + [0.0, 0.0, 0.0], + [0.0, 0.0, 0.0], + [0.0, 0.0, 0.0], + [0.0, 0.0, 0.0], + [0.0, 0.0, 0.0], + [0.0, 0.0, 0.0], + [0.0, 0.0, 0.0], + [0.0, 0.0, 0.0], + [0.0, 0.0, 0.0], + [0.0, 0.0, 0.0], + [0.0, 0.0, 0.0], + [0.0, 0.0, 0.0], + [0.0, 0.0, 0.0], + [0.0, 0.0, 0.0], + [0.0, 0.0, 0.0], + [0.0, 0.0, 0.0], +] + def sample_to_lowres_estimated_image( samples: torch.Tensor, latent_rgb_factors: torch.Tensor, smooth_matrix: Optional[torch.Tensor] = None @@ -164,6 +204,8 @@ def diffusion_step_callback( latent_rgb_factors = COGVIEW4_LATENT_RGB_FACTORS elif base_model == BaseModelType.Flux: latent_rgb_factors = FLUX_LATENT_RGB_FACTORS + elif base_model == BaseModelType.Flux2: + latent_rgb_factors = FLUX2_LATENT_RGB_FACTORS elif base_model == BaseModelType.ZImage: # Z-Image uses FLUX-compatible VAE with 16 latent channels latent_rgb_factors = FLUX_LATENT_RGB_FACTORS diff --git a/invokeai/backend/flux/util.py b/invokeai/backend/flux/util.py index 2cf52b6ec1..da6590c757 100644 --- a/invokeai/backend/flux/util.py +++ b/invokeai/backend/flux/util.py @@ -5,7 +5,7 @@ from typing import Literal from invokeai.backend.flux.model import FluxParams from invokeai.backend.flux.modules.autoencoder import AutoEncoderParams -from invokeai.backend.model_manager.taxonomy import AnyVariant, FluxVariantType +from invokeai.backend.model_manager.taxonomy import AnyVariant, Flux2VariantType, FluxVariantType @dataclass @@ -46,6 +46,8 @@ _flux_max_seq_lengths: dict[AnyVariant, Literal[256, 512]] = { FluxVariantType.Dev: 512, FluxVariantType.DevFill: 512, FluxVariantType.Schnell: 256, + Flux2VariantType.Klein4B: 512, + Flux2VariantType.Klein9B: 512, } @@ -117,6 +119,38 @@ _flux_transformer_params: dict[AnyVariant, FluxParams] = { qkv_bias=True, guidance_embed=True, ), + # Flux2 Klein 4B uses Qwen3 4B text encoder with stacked embeddings from layers [9, 18, 27] + # The context_in_dim is 3 * hidden_size of Qwen3 (3 * 2560 = 7680) + Flux2VariantType.Klein4B: FluxParams( + in_channels=64, + vec_in_dim=2560, # Qwen3-4B hidden size (used for pooled output) + context_in_dim=7680, # 3 layers * 2560 = 7680 for Qwen3-4B + hidden_size=3072, + mlp_ratio=4.0, + num_heads=24, + depth=19, + depth_single_blocks=38, + axes_dim=[16, 56, 56], + theta=10_000, + qkv_bias=True, + guidance_embed=True, + ), + # Flux2 Klein 9B uses Qwen3 8B text encoder with stacked embeddings from layers [9, 18, 27] + # The context_in_dim is 3 * hidden_size of Qwen3 (3 * 4096 = 12288) + Flux2VariantType.Klein9B: FluxParams( + in_channels=64, + vec_in_dim=4096, # Qwen3-8B hidden size (used for pooled output) + context_in_dim=12288, # 3 layers * 4096 = 12288 for Qwen3-8B + hidden_size=3072, + mlp_ratio=4.0, + num_heads=24, + depth=19, + depth_single_blocks=38, + axes_dim=[16, 56, 56], + theta=10_000, + qkv_bias=True, + guidance_embed=True, + ), } diff --git a/invokeai/backend/flux2/__init__.py b/invokeai/backend/flux2/__init__.py new file mode 100644 index 0000000000..cabb51efb9 --- /dev/null +++ b/invokeai/backend/flux2/__init__.py @@ -0,0 +1,4 @@ +"""FLUX.2 backend modules. + +This package contains modules specific to FLUX.2 models (e.g., Klein). +""" diff --git a/invokeai/backend/flux2/denoise.py b/invokeai/backend/flux2/denoise.py new file mode 100644 index 0000000000..b29d1b08bf --- /dev/null +++ b/invokeai/backend/flux2/denoise.py @@ -0,0 +1,261 @@ +"""Flux2 Klein Denoising Function. + +This module provides the denoising function for FLUX.2 Klein models, +which use Qwen3 as the text encoder instead of CLIP+T5. +""" + +import math +from typing import Any, Callable + +import numpy as np +import torch +from tqdm import tqdm + +from invokeai.backend.rectified_flow.rectified_flow_inpaint_extension import RectifiedFlowInpaintExtension +from invokeai.backend.stable_diffusion.diffusers_pipeline import PipelineIntermediateState + + +def denoise( + model: torch.nn.Module, + # model input + img: torch.Tensor, + img_ids: torch.Tensor, + txt: torch.Tensor, + txt_ids: torch.Tensor, + # sampling parameters + timesteps: list[float], + step_callback: Callable[[PipelineIntermediateState], None], + cfg_scale: list[float], + # Negative conditioning for CFG + neg_txt: torch.Tensor | None = None, + neg_txt_ids: torch.Tensor | None = None, + # Scheduler for stepping (e.g., FlowMatchEulerDiscreteScheduler, FlowMatchHeunDiscreteScheduler) + scheduler: Any = None, + # Dynamic shifting parameter for FLUX.2 Klein (computed from image resolution) + mu: float | None = None, + # Inpainting extension for merging latents during denoising + inpaint_extension: RectifiedFlowInpaintExtension | None = None, + # Reference image conditioning (multi-reference image editing) + img_cond_seq: torch.Tensor | None = None, + img_cond_seq_ids: torch.Tensor | None = None, +) -> torch.Tensor: + """Denoise latents using a FLUX.2 Klein transformer model. + + This is a simplified denoise function for FLUX.2 Klein models that uses + the diffusers Flux2Transformer2DModel interface. + + Note: FLUX.2 Klein has guidance_embeds=False, so no guidance parameter is used. + CFG is applied externally using negative conditioning when cfg_scale != 1.0. + + Args: + model: The Flux2Transformer2DModel from diffusers. + img: Packed latent image tensor of shape (B, seq_len, channels). + img_ids: Image position IDs tensor. + txt: Text encoder hidden states (Qwen3 embeddings). + txt_ids: Text position IDs tensor. + timesteps: List of timesteps for denoising schedule (linear sigmas from 1.0 to 1/n). + step_callback: Callback function for progress updates. + cfg_scale: List of CFG scale values per step. + neg_txt: Negative text embeddings for CFG (optional). + neg_txt_ids: Negative text position IDs (optional). + scheduler: Optional diffusers scheduler (Euler, Heun, LCM). If None, uses manual Euler. + mu: Dynamic shifting parameter computed from image resolution. Required when scheduler + has use_dynamic_shifting=True. + + Returns: + Denoised latent tensor. + """ + total_steps = len(timesteps) - 1 + + # Store original sequence length for extracting output later (before concatenating reference images) + original_seq_len = img.shape[1] + + # Concatenate reference image conditioning if provided (multi-reference image editing) + if img_cond_seq is not None and img_cond_seq_ids is not None: + img = torch.cat([img, img_cond_seq], dim=1) + img_ids = torch.cat([img_ids, img_cond_seq_ids], dim=1) + + # Klein has guidance_embeds=False, but the transformer forward() still requires a guidance tensor + # We pass a dummy value (1.0) since it won't affect the output when guidance_embeds=False + guidance = torch.full((img.shape[0],), 1.0, device=img.device, dtype=img.dtype) + + # Use scheduler if provided + use_scheduler = scheduler is not None + if use_scheduler: + # Set up scheduler with sigmas and mu for dynamic shifting + # Convert timesteps (0-1 range) to sigmas for the scheduler + # The scheduler will apply dynamic shifting internally using mu (if enabled in scheduler config) + sigmas = np.array(timesteps[:-1], dtype=np.float32) # Exclude final 0.0 + + # Pass mu if provided - it will only be used if scheduler has use_dynamic_shifting=True + if mu is not None: + scheduler.set_timesteps(sigmas=sigmas.tolist(), mu=mu, device=img.device) + else: + scheduler.set_timesteps(sigmas=sigmas.tolist(), device=img.device) + num_scheduler_steps = len(scheduler.timesteps) + is_heun = hasattr(scheduler, "state_in_first_order") + user_step = 0 + + pbar = tqdm(total=total_steps, desc="Denoising") + for step_index in range(num_scheduler_steps): + timestep = scheduler.timesteps[step_index] + # Convert scheduler timestep (0-1000) to normalized (0-1) for the model + t_curr = timestep.item() / scheduler.config.num_train_timesteps + t_vec = torch.full((img.shape[0],), t_curr, dtype=img.dtype, device=img.device) + + # Track if we're in first or second order step (for Heun) + in_first_order = scheduler.state_in_first_order if is_heun else True + + # Run the transformer model (matching diffusers: guidance=guidance, return_dict=False) + output = model( + hidden_states=img, + encoder_hidden_states=txt, + timestep=t_vec, + img_ids=img_ids, + txt_ids=txt_ids, + guidance=guidance, + return_dict=False, + ) + + # Extract the sample from the output (return_dict=False returns tuple) + pred = output[0] if isinstance(output, tuple) else output + + step_cfg_scale = cfg_scale[min(user_step, len(cfg_scale) - 1)] + + # Apply CFG if scale is not 1.0 + if not math.isclose(step_cfg_scale, 1.0): + if neg_txt is None: + raise ValueError("Negative text conditioning is required when cfg_scale is not 1.0.") + + neg_output = model( + hidden_states=img, + encoder_hidden_states=neg_txt, + timestep=t_vec, + img_ids=img_ids, + txt_ids=neg_txt_ids if neg_txt_ids is not None else txt_ids, + guidance=guidance, + return_dict=False, + ) + + neg_pred = neg_output[0] if isinstance(neg_output, tuple) else neg_output + pred = neg_pred + step_cfg_scale * (pred - neg_pred) + + # Use scheduler.step() for the update + step_output = scheduler.step(model_output=pred, timestep=timestep, sample=img) + img = step_output.prev_sample + + # Get t_prev for inpainting (next sigma value) + if step_index + 1 < len(scheduler.sigmas): + t_prev = scheduler.sigmas[step_index + 1].item() + else: + t_prev = 0.0 + + # Apply inpainting merge at each step + if inpaint_extension is not None: + img = inpaint_extension.merge_intermediate_latents_with_init_latents(img, t_prev) + + # For Heun, only increment user step after second-order step completes + if is_heun: + if not in_first_order: + user_step += 1 + if user_step <= total_steps: + pbar.update(1) + preview_img = img - t_curr * pred + if inpaint_extension is not None: + preview_img = inpaint_extension.merge_intermediate_latents_with_init_latents( + preview_img, 0.0 + ) + step_callback( + PipelineIntermediateState( + step=user_step, + order=2, + total_steps=total_steps, + timestep=int(t_curr * 1000), + latents=preview_img, + ), + ) + else: + user_step += 1 + if user_step <= total_steps: + pbar.update(1) + preview_img = img - t_curr * pred + if inpaint_extension is not None: + preview_img = inpaint_extension.merge_intermediate_latents_with_init_latents(preview_img, 0.0) + # Extract only the generated image portion for preview (exclude reference images) + callback_latents = preview_img[:, :original_seq_len, :] if img_cond_seq is not None else preview_img + step_callback( + PipelineIntermediateState( + step=user_step, + order=1, + total_steps=total_steps, + timestep=int(t_curr * 1000), + latents=callback_latents, + ), + ) + + pbar.close() + else: + # Manual Euler stepping (original behavior) + for step_index, (t_curr, t_prev) in tqdm(list(enumerate(zip(timesteps[:-1], timesteps[1:], strict=True)))): + t_vec = torch.full((img.shape[0],), t_curr, dtype=img.dtype, device=img.device) + + # Run the transformer model (matching diffusers: guidance=guidance, return_dict=False) + output = model( + hidden_states=img, + encoder_hidden_states=txt, + timestep=t_vec, + img_ids=img_ids, + txt_ids=txt_ids, + guidance=guidance, + return_dict=False, + ) + + # Extract the sample from the output (return_dict=False returns tuple) + pred = output[0] if isinstance(output, tuple) else output + + step_cfg_scale = cfg_scale[step_index] + + # Apply CFG if scale is not 1.0 + if not math.isclose(step_cfg_scale, 1.0): + if neg_txt is None: + raise ValueError("Negative text conditioning is required when cfg_scale is not 1.0.") + + neg_output = model( + hidden_states=img, + encoder_hidden_states=neg_txt, + timestep=t_vec, + img_ids=img_ids, + txt_ids=neg_txt_ids if neg_txt_ids is not None else txt_ids, + guidance=guidance, + return_dict=False, + ) + + neg_pred = neg_output[0] if isinstance(neg_output, tuple) else neg_output + pred = neg_pred + step_cfg_scale * (pred - neg_pred) + + # Euler step + preview_img = img - t_curr * pred + img = img + (t_prev - t_curr) * pred + + # Apply inpainting merge at each step + if inpaint_extension is not None: + img = inpaint_extension.merge_intermediate_latents_with_init_latents(img, t_prev) + preview_img = inpaint_extension.merge_intermediate_latents_with_init_latents(preview_img, 0.0) + + # Extract only the generated image portion for preview (exclude reference images) + callback_latents = preview_img[:, :original_seq_len, :] if img_cond_seq is not None else preview_img + step_callback( + PipelineIntermediateState( + step=step_index + 1, + order=1, + total_steps=total_steps, + timestep=int(t_curr), + latents=callback_latents, + ), + ) + + # Extract only the generated image portion (exclude concatenated reference images) + if img_cond_seq is not None: + img = img[:, :original_seq_len, :] + + return img diff --git a/invokeai/backend/flux2/ref_image_extension.py b/invokeai/backend/flux2/ref_image_extension.py new file mode 100644 index 0000000000..9cc6240db6 --- /dev/null +++ b/invokeai/backend/flux2/ref_image_extension.py @@ -0,0 +1,294 @@ +"""FLUX.2 Klein Reference Image Extension for multi-reference image editing. + +This module provides the Flux2RefImageExtension for FLUX.2 Klein models, +which handles encoding reference images using the FLUX.2 VAE and +generating the appropriate position IDs for multi-reference image editing. + +FLUX.2 Klein has built-in support for reference image editing (unlike FLUX.1 +which requires a separate Kontext model). +""" + +import math + +import torch +import torch.nn.functional as F +import torchvision.transforms as T +from einops import repeat +from PIL import Image + +from invokeai.app.invocations.fields import FluxKontextConditioningField +from invokeai.app.invocations.model import VAEField +from invokeai.app.services.shared.invocation_context import InvocationContext +from invokeai.backend.flux2.sampling_utils import pack_flux2 +from invokeai.backend.util.devices import TorchDevice + +# Maximum pixel counts for reference images (matches BFL FLUX.2 sampling.py) +# Single reference image: 2024² pixels, Multiple: 1024² pixels +MAX_PIXELS_SINGLE_REF = 2024**2 # ~4.1M pixels +MAX_PIXELS_MULTI_REF = 1024**2 # ~1M pixels + + +def resize_image_to_max_pixels(image: Image.Image, max_pixels: int) -> Image.Image: + """Resize image to fit within max_pixels while preserving aspect ratio. + + This matches the BFL FLUX.2 sampling.py cap_pixels() behavior. + + Args: + image: PIL Image to resize. + max_pixels: Maximum total pixel count (width * height). + + Returns: + Resized PIL Image (or original if already within bounds). + """ + width, height = image.size + pixel_count = width * height + + if pixel_count <= max_pixels: + return image + + # Calculate scale factor to fit within max_pixels (BFL approach) + scale = math.sqrt(max_pixels / pixel_count) + new_width = int(width * scale) + new_height = int(height * scale) + + # Ensure dimensions are at least 1 + new_width = max(1, new_width) + new_height = max(1, new_height) + + return image.resize((new_width, new_height), Image.Resampling.LANCZOS) + + +def generate_img_ids_flux2_with_offset( + latent_height: int, + latent_width: int, + batch_size: int, + device: torch.device, + idx_offset: int = 0, + h_offset: int = 0, + w_offset: int = 0, +) -> torch.Tensor: + """Generate tensor of image position ids with optional offsets for FLUX.2. + + FLUX.2 uses 4D position coordinates (T, H, W, L) for its rotary position embeddings. + Position IDs use int64 (long) dtype. + + Args: + latent_height: Height of image in latent space (before packing). + latent_width: Width of image in latent space (before packing). + batch_size: Number of images in the batch. + device: Device to create tensors on. + idx_offset: Offset for T (time/index) coordinate - use 1 for reference images. + h_offset: Spatial offset for H coordinate in latent space. + w_offset: Spatial offset for W coordinate in latent space. + + Returns: + Image position ids with shape [batch_size, (latent_height//2 * latent_width//2), 4]. + """ + # After packing, the spatial dimensions are halved due to the 2x2 patch structure + packed_height = latent_height // 2 + packed_width = latent_width // 2 + + # Convert spatial offsets from latent space to packed space + packed_h_offset = h_offset // 2 + packed_w_offset = w_offset // 2 + + # Create base tensor for position IDs with shape [packed_height, packed_width, 4] + # The 4 channels represent: [T, H, W, L] + img_ids = torch.zeros(packed_height, packed_width, 4, device=device, dtype=torch.long) + + # Set T (time/index offset) for all positions - use 1 for reference images + img_ids[..., 0] = idx_offset + + # Set H (height/y) coordinates with offset + h_coords = torch.arange(packed_height, device=device, dtype=torch.long) + packed_h_offset + img_ids[..., 1] = h_coords[:, None] + + # Set W (width/x) coordinates with offset + w_coords = torch.arange(packed_width, device=device, dtype=torch.long) + packed_w_offset + img_ids[..., 2] = w_coords[None, :] + + # L (layer) coordinate stays 0 + + # Expand to include batch dimension: [batch_size, (packed_height * packed_width), 4] + img_ids = img_ids.reshape(1, packed_height * packed_width, 4) + img_ids = repeat(img_ids, "1 s c -> b s c", b=batch_size) + + return img_ids + + +class Flux2RefImageExtension: + """Applies FLUX.2 Klein reference image conditioning. + + This extension handles encoding reference images using the FLUX.2 VAE + and generating the appropriate 4D position IDs for multi-reference image editing. + + FLUX.2 Klein has built-in support for reference image editing, unlike FLUX.1 + which requires a separate Kontext model. + """ + + def __init__( + self, + ref_image_conditioning: list[FluxKontextConditioningField], + context: InvocationContext, + vae_field: VAEField, + device: torch.device, + dtype: torch.dtype, + bn_mean: torch.Tensor | None = None, + bn_std: torch.Tensor | None = None, + ): + """Initialize the Flux2RefImageExtension. + + Args: + ref_image_conditioning: List of reference image conditioning fields. + context: The invocation context for loading models and images. + vae_field: The FLUX.2 VAE field for encoding images. + device: Target device for tensors. + dtype: Target dtype for tensors. + bn_mean: BN running mean for normalizing latents (shape: 128). + bn_std: BN running std for normalizing latents (shape: 128). + """ + self._context = context + self._device = device + self._dtype = dtype + self._vae_field = vae_field + self._bn_mean = bn_mean + self._bn_std = bn_std + self.ref_image_conditioning = ref_image_conditioning + + # Pre-process and cache the reference image latents and ids upon initialization + self.ref_image_latents, self.ref_image_ids = self._prepare_ref_images() + + def _bn_normalize(self, x: torch.Tensor) -> torch.Tensor: + """Apply BN normalization to packed latents. + + BN formula (affine=False): y = (x - mean) / std + + Args: + x: Packed latents of shape (B, seq, 128). + + Returns: + Normalized latents of same shape. + """ + assert self._bn_mean is not None and self._bn_std is not None + bn_mean = self._bn_mean.to(x.device, x.dtype) + bn_std = self._bn_std.to(x.device, x.dtype) + return (x - bn_mean) / bn_std + + def _prepare_ref_images(self) -> tuple[torch.Tensor, torch.Tensor]: + """Encode reference images and prepare their concatenated latents and IDs with spatial tiling.""" + all_latents = [] + all_ids = [] + + # Track cumulative dimensions for spatial tiling + canvas_h = 0 + canvas_w = 0 + + vae_info = self._context.models.load(self._vae_field.vae) + + # Determine max pixels based on number of reference images (BFL FLUX.2 approach) + num_refs = len(self.ref_image_conditioning) + max_pixels = MAX_PIXELS_SINGLE_REF if num_refs == 1 else MAX_PIXELS_MULTI_REF + + for idx, ref_image_field in enumerate(self.ref_image_conditioning): + image = self._context.images.get_pil(ref_image_field.image.image_name) + image = image.convert("RGB") + + # Resize large images to max pixel count (matches BFL FLUX.2 sampling.py) + image = resize_image_to_max_pixels(image, max_pixels) + + # Convert to tensor using torchvision transforms + transformation = T.Compose([T.ToTensor()]) + image_tensor = transformation(image) + # Convert from [0, 1] to [-1, 1] range expected by VAE + image_tensor = image_tensor * 2.0 - 1.0 + image_tensor = image_tensor.unsqueeze(0) # Add batch dimension + + # Encode using FLUX.2 VAE + with vae_info.model_on_device() as (_, vae): + vae_dtype = next(iter(vae.parameters())).dtype + image_tensor = image_tensor.to(device=TorchDevice.choose_torch_device(), dtype=vae_dtype) + + # FLUX.2 VAE uses diffusers API + latent_dist = vae.encode(image_tensor, return_dict=False)[0] + + # Use mode() for deterministic encoding (no sampling) + if hasattr(latent_dist, "mode"): + ref_image_latents_unpacked = latent_dist.mode() + elif hasattr(latent_dist, "sample"): + ref_image_latents_unpacked = latent_dist.sample() + else: + ref_image_latents_unpacked = latent_dist + + TorchDevice.empty_cache() + + # Extract tensor dimensions (B, 32, H, W for FLUX.2) + batch_size, _, latent_height, latent_width = ref_image_latents_unpacked.shape + + # Pad latents to be compatible with patch_size=2 + pad_h = (2 - latent_height % 2) % 2 + pad_w = (2 - latent_width % 2) % 2 + if pad_h > 0 or pad_w > 0: + ref_image_latents_unpacked = F.pad(ref_image_latents_unpacked, (0, pad_w, 0, pad_h), mode="circular") + _, _, latent_height, latent_width = ref_image_latents_unpacked.shape + + # Pack the latents using FLUX.2 pack function (32 channels -> 128) + ref_image_latents_packed = pack_flux2(ref_image_latents_unpacked).to(self._device, self._dtype) + + # Apply BN normalization to match the input latents scale + # This is critical - the transformer expects normalized latents + if self._bn_mean is not None and self._bn_std is not None: + ref_image_latents_packed = self._bn_normalize(ref_image_latents_packed) + + # Determine spatial offsets for this reference image + h_offset = 0 + w_offset = 0 + + if idx > 0: # First image starts at (0, 0) + # Calculate potential canvas dimensions for each tiling option + potential_h_vertical = canvas_h + latent_height + potential_w_horizontal = canvas_w + latent_width + + # Choose arrangement that minimizes the maximum dimension + if potential_h_vertical > potential_w_horizontal: + # Tile horizontally (to the right) + w_offset = canvas_w + canvas_w = canvas_w + latent_width + canvas_h = max(canvas_h, latent_height) + else: + # Tile vertically (below) + h_offset = canvas_h + canvas_h = canvas_h + latent_height + canvas_w = max(canvas_w, latent_width) + else: + canvas_h = latent_height + canvas_w = latent_width + + # Generate position IDs with 4D format (T, H, W, L) + # Use T-coordinate offset with scale=10 like diffusers Flux2Pipeline: + # T = scale + scale * idx (so first ref image is T=10, second is T=20, etc.) + # The generated image uses T=0, so this clearly separates reference images + t_offset = 10 + 10 * idx # scale=10 matches diffusers + ref_image_ids = generate_img_ids_flux2_with_offset( + latent_height=latent_height, + latent_width=latent_width, + batch_size=batch_size, + device=self._device, + idx_offset=t_offset, # Reference images use T=10, 20, 30... + h_offset=h_offset, + w_offset=w_offset, + ) + + all_latents.append(ref_image_latents_packed) + all_ids.append(ref_image_ids) + + # Concatenate all latents and IDs along the sequence dimension + concatenated_latents = torch.cat(all_latents, dim=1) + concatenated_ids = torch.cat(all_ids, dim=1) + + return concatenated_latents, concatenated_ids + + def ensure_batch_size(self, target_batch_size: int) -> None: + """Ensure the reference image latents and IDs match the target batch size.""" + if self.ref_image_latents.shape[0] != target_batch_size: + self.ref_image_latents = self.ref_image_latents.repeat(target_batch_size, 1, 1) + self.ref_image_ids = self.ref_image_ids.repeat(target_batch_size, 1, 1) diff --git a/invokeai/backend/flux2/sampling_utils.py b/invokeai/backend/flux2/sampling_utils.py new file mode 100644 index 0000000000..6978d0f144 --- /dev/null +++ b/invokeai/backend/flux2/sampling_utils.py @@ -0,0 +1,209 @@ +"""FLUX.2 Klein Sampling Utilities. + +FLUX.2 Klein uses a 32-channel VAE (AutoencoderKLFlux2) instead of the 16-channel VAE +used by FLUX.1. This module provides sampling utilities adapted for FLUX.2. +""" + +import math + +import torch +from einops import rearrange + + +def get_noise_flux2( + num_samples: int, + height: int, + width: int, + device: torch.device, + dtype: torch.dtype, + seed: int, +) -> torch.Tensor: + """Generate noise for FLUX.2 Klein (32 channels). + + FLUX.2 uses a 32-channel VAE, so noise must have 32 channels. + The spatial dimensions are calculated to allow for packing. + + Args: + num_samples: Batch size. + height: Target image height in pixels. + width: Target image width in pixels. + device: Target device. + dtype: Target dtype. + seed: Random seed. + + Returns: + Noise tensor of shape (num_samples, 32, latent_h, latent_w). + """ + # We always generate noise on the same device and dtype then cast to ensure consistency. + rand_device = "cpu" + rand_dtype = torch.float16 + + # FLUX.2 uses 32 latent channels + # Latent dimensions: height/8, width/8 (from VAE downsampling) + # Must be divisible by 2 for packing (patchify step) + latent_h = 2 * math.ceil(height / 16) + latent_w = 2 * math.ceil(width / 16) + + return torch.randn( + num_samples, + 32, # FLUX.2 uses 32 latent channels (vs 16 for FLUX.1) + latent_h, + latent_w, + device=rand_device, + dtype=rand_dtype, + generator=torch.Generator(device=rand_device).manual_seed(seed), + ).to(device=device, dtype=dtype) + + +def pack_flux2(x: torch.Tensor) -> torch.Tensor: + """Pack latent image to flattened array of patch embeddings for FLUX.2. + + This performs the patchify + pack operation in one step: + 1. Patchify: Group 2x2 spatial patches into channels (C*4) + 2. Pack: Flatten spatial dimensions to sequence + + For 32-channel input: (B, 32, H, W) -> (B, H/2*W/2, 128) + + Args: + x: Latent tensor of shape (B, 32, H, W). + + Returns: + Packed tensor of shape (B, H/2*W/2, 128). + """ + # Same operation as FLUX.1 pack, but input has 32 channels -> output has 128 + return rearrange(x, "b c (h ph) (w pw) -> b (h w) (c ph pw)", ph=2, pw=2) + + +def unpack_flux2(x: torch.Tensor, height: int, width: int) -> torch.Tensor: + """Unpack flat array of patch embeddings back to latent image for FLUX.2. + + This reverses the pack_flux2 operation: + 1. Unpack: Restore spatial dimensions from sequence + 2. Unpatchify: Restore 32 channels from 128 + + Args: + x: Packed tensor of shape (B, H/2*W/2, 128). + height: Target image height in pixels. + width: Target image width in pixels. + + Returns: + Latent tensor of shape (B, 32, H, W). + """ + # Calculate latent dimensions + latent_h = 2 * math.ceil(height / 16) + latent_w = 2 * math.ceil(width / 16) + + # Packed dimensions (after patchify) + packed_h = latent_h // 2 + packed_w = latent_w // 2 + + return rearrange( + x, + "b (h w) (c ph pw) -> b c (h ph) (w pw)", + h=packed_h, + w=packed_w, + ph=2, + pw=2, + ) + + +def compute_empirical_mu(image_seq_len: int, num_steps: int) -> float: + """Compute empirical mu for FLUX.2 schedule shifting. + + This matches the diffusers Flux2Pipeline implementation. + The mu value controls how much the schedule is shifted towards higher timesteps. + + Args: + image_seq_len: Number of image tokens (packed_h * packed_w). + num_steps: Number of denoising steps. + + Returns: + The empirical mu value. + """ + a1, b1 = 8.73809524e-05, 1.89833333 + a2, b2 = 0.00016927, 0.45666666 + + if image_seq_len > 4300: + mu = a2 * image_seq_len + b2 + return float(mu) + + m_200 = a2 * image_seq_len + b2 + m_10 = a1 * image_seq_len + b1 + + a = (m_200 - m_10) / 190.0 + b = m_200 - 200.0 * a + mu = a * num_steps + b + + return float(mu) + + +def get_schedule_flux2( + num_steps: int, + image_seq_len: int, +) -> list[float]: + """Get linear timestep schedule for FLUX.2. + + Returns a linear sigma schedule from 1.0 to 1/num_steps. + The actual schedule shifting is handled by the FlowMatchEulerDiscreteScheduler + using the mu parameter and use_dynamic_shifting=True. + + Args: + num_steps: Number of denoising steps. + image_seq_len: Number of image tokens (packed_h * packed_w). Currently unused, + but kept for API compatibility. The scheduler computes shifting internally. + + Returns: + List of linear sigmas from 1.0 to 1/num_steps, plus final 0.0. + """ + import numpy as np + + # Create linear sigmas from 1.0 to 1/num_steps + # The scheduler will apply dynamic shifting using mu parameter + sigmas = np.linspace(1.0, 1 / num_steps, num_steps) + sigmas_list = [float(s) for s in sigmas] + + # Add final 0.0 for the last step (scheduler needs n+1 timesteps for n steps) + sigmas_list.append(0.0) + + return sigmas_list + + +def generate_img_ids_flux2(h: int, w: int, batch_size: int, device: torch.device) -> torch.Tensor: + """Generate tensor of image position ids for FLUX.2. + + FLUX.2 uses 4D position coordinates (T, H, W, L) for its rotary position embeddings. + This is different from FLUX.1 which uses 3D coordinates. + + IMPORTANT: Position IDs must use int64 (long) dtype like diffusers, not bfloat16. + Using floating point dtype for position IDs can cause NaN in rotary embeddings. + + Args: + h: Height of image in latent space. + w: Width of image in latent space. + batch_size: Batch size. + device: Device. + + Returns: + Image position ids tensor of shape (batch_size, h/2*w/2, 4) with int64 dtype. + """ + # After packing, spatial dims are h/2 x w/2 + packed_h = h // 2 + packed_w = w // 2 + + # Create coordinate grids - 4D: (T, H, W, L) + # T = time/batch index, H = height, W = width, L = layer/channel + # Use int64 (long) dtype like diffusers + img_ids = torch.zeros(packed_h, packed_w, 4, device=device, dtype=torch.long) + + # T (time/batch) coordinate - set to 0 (already initialized) + # H coordinates + img_ids[..., 1] = torch.arange(packed_h, device=device, dtype=torch.long)[:, None] + # W coordinates + img_ids[..., 2] = torch.arange(packed_w, device=device, dtype=torch.long)[None, :] + # L (layer) coordinate - set to 0 (already initialized) + + # Flatten and expand for batch + img_ids = img_ids.reshape(1, packed_h * packed_w, 4) + img_ids = img_ids.expand(batch_size, -1, -1) + + return img_ids diff --git a/invokeai/backend/model_manager/configs/factory.py b/invokeai/backend/model_manager/configs/factory.py index aa256e6890..021752d47b 100644 --- a/invokeai/backend/model_manager/configs/factory.py +++ b/invokeai/backend/model_manager/configs/factory.py @@ -56,6 +56,7 @@ from invokeai.backend.model_manager.configs.lora import ( ) from invokeai.backend.model_manager.configs.main import ( Main_BnBNF4_FLUX_Config, + Main_Checkpoint_Flux2_Config, Main_Checkpoint_FLUX_Config, Main_Checkpoint_SD1_Config, Main_Checkpoint_SD2_Config, @@ -63,12 +64,15 @@ from invokeai.backend.model_manager.configs.main import ( Main_Checkpoint_SDXLRefiner_Config, Main_Checkpoint_ZImage_Config, Main_Diffusers_CogView4_Config, + Main_Diffusers_Flux2_Config, + Main_Diffusers_FLUX_Config, Main_Diffusers_SD1_Config, Main_Diffusers_SD2_Config, Main_Diffusers_SD3_Config, Main_Diffusers_SDXL_Config, Main_Diffusers_SDXLRefiner_Config, Main_Diffusers_ZImage_Config, + Main_GGUF_Flux2_Config, Main_GGUF_FLUX_Config, Main_GGUF_ZImage_Config, MainModelDefaultSettings, @@ -95,10 +99,12 @@ from invokeai.backend.model_manager.configs.textual_inversion import ( ) from invokeai.backend.model_manager.configs.unknown import Unknown_Config from invokeai.backend.model_manager.configs.vae import ( + VAE_Checkpoint_Flux2_Config, VAE_Checkpoint_FLUX_Config, VAE_Checkpoint_SD1_Config, VAE_Checkpoint_SD2_Config, VAE_Checkpoint_SDXL_Config, + VAE_Diffusers_Flux2_Config, VAE_Diffusers_SD1_Config, VAE_Diffusers_SDXL_Config, ) @@ -148,17 +154,25 @@ AnyModelConfig = Annotated[ Annotated[Main_Diffusers_SDXL_Config, Main_Diffusers_SDXL_Config.get_tag()], Annotated[Main_Diffusers_SDXLRefiner_Config, Main_Diffusers_SDXLRefiner_Config.get_tag()], Annotated[Main_Diffusers_SD3_Config, Main_Diffusers_SD3_Config.get_tag()], + Annotated[Main_Diffusers_FLUX_Config, Main_Diffusers_FLUX_Config.get_tag()], + Annotated[Main_Diffusers_Flux2_Config, Main_Diffusers_Flux2_Config.get_tag()], Annotated[Main_Diffusers_CogView4_Config, Main_Diffusers_CogView4_Config.get_tag()], Annotated[Main_Diffusers_ZImage_Config, Main_Diffusers_ZImage_Config.get_tag()], # Main (Pipeline) - checkpoint format + # IMPORTANT: FLUX.2 must be checked BEFORE FLUX.1 because FLUX.2 has specific validation + # that will reject FLUX.1 models, but FLUX.1 validation may incorrectly match FLUX.2 models Annotated[Main_Checkpoint_SD1_Config, Main_Checkpoint_SD1_Config.get_tag()], Annotated[Main_Checkpoint_SD2_Config, Main_Checkpoint_SD2_Config.get_tag()], Annotated[Main_Checkpoint_SDXL_Config, Main_Checkpoint_SDXL_Config.get_tag()], Annotated[Main_Checkpoint_SDXLRefiner_Config, Main_Checkpoint_SDXLRefiner_Config.get_tag()], + Annotated[Main_Checkpoint_Flux2_Config, Main_Checkpoint_Flux2_Config.get_tag()], Annotated[Main_Checkpoint_FLUX_Config, Main_Checkpoint_FLUX_Config.get_tag()], Annotated[Main_Checkpoint_ZImage_Config, Main_Checkpoint_ZImage_Config.get_tag()], # Main (Pipeline) - quantized formats + # IMPORTANT: FLUX.2 must be checked BEFORE FLUX.1 because FLUX.2 has specific validation + # that will reject FLUX.1 models, but FLUX.1 validation may incorrectly match FLUX.2 models Annotated[Main_BnBNF4_FLUX_Config, Main_BnBNF4_FLUX_Config.get_tag()], + Annotated[Main_GGUF_Flux2_Config, Main_GGUF_Flux2_Config.get_tag()], Annotated[Main_GGUF_FLUX_Config, Main_GGUF_FLUX_Config.get_tag()], Annotated[Main_GGUF_ZImage_Config, Main_GGUF_ZImage_Config.get_tag()], # VAE - checkpoint format @@ -166,9 +180,11 @@ AnyModelConfig = Annotated[ Annotated[VAE_Checkpoint_SD2_Config, VAE_Checkpoint_SD2_Config.get_tag()], Annotated[VAE_Checkpoint_SDXL_Config, VAE_Checkpoint_SDXL_Config.get_tag()], Annotated[VAE_Checkpoint_FLUX_Config, VAE_Checkpoint_FLUX_Config.get_tag()], + Annotated[VAE_Checkpoint_Flux2_Config, VAE_Checkpoint_Flux2_Config.get_tag()], # VAE - diffusers format Annotated[VAE_Diffusers_SD1_Config, VAE_Diffusers_SD1_Config.get_tag()], Annotated[VAE_Diffusers_SDXL_Config, VAE_Diffusers_SDXL_Config.get_tag()], + Annotated[VAE_Diffusers_Flux2_Config, VAE_Diffusers_Flux2_Config.get_tag()], # ControlNet - checkpoint format Annotated[ControlNet_Checkpoint_SD1_Config, ControlNet_Checkpoint_SD1_Config.get_tag()], Annotated[ControlNet_Checkpoint_SD2_Config, ControlNet_Checkpoint_SD2_Config.get_tag()], @@ -498,7 +514,9 @@ class ModelConfigFactory: # Now do any post-processing needed for specific model types/bases/etc. match config.type: case ModelType.Main: - config.default_settings = MainModelDefaultSettings.from_base(config.base) + # Pass variant if available (e.g., for Flux2 models) + variant = getattr(config, "variant", None) + config.default_settings = MainModelDefaultSettings.from_base(config.base, variant) case ModelType.ControlNet | ModelType.T2IAdapter | ModelType.ControlLoRa: config.default_settings = ControlAdapterDefaultSettings.from_model_name(config.name) case ModelType.LoRA: diff --git a/invokeai/backend/model_manager/configs/main.py b/invokeai/backend/model_manager/configs/main.py index 39887e1b04..9f983795ea 100644 --- a/invokeai/backend/model_manager/configs/main.py +++ b/invokeai/backend/model_manager/configs/main.py @@ -23,6 +23,7 @@ from invokeai.backend.model_manager.configs.identification_utils import ( from invokeai.backend.model_manager.model_on_disk import ModelOnDisk from invokeai.backend.model_manager.taxonomy import ( BaseModelType, + Flux2VariantType, FluxVariantType, ModelFormat, ModelType, @@ -52,7 +53,11 @@ class MainModelDefaultSettings(BaseModel): model_config = ConfigDict(extra="forbid") @classmethod - def from_base(cls, base: BaseModelType) -> Self | None: + def from_base( + cls, + base: BaseModelType, + variant: Flux2VariantType | FluxVariantType | ModelVariantType | None = None, + ) -> Self | None: match base: case BaseModelType.StableDiffusion1: return cls(width=512, height=512) @@ -62,6 +67,14 @@ class MainModelDefaultSettings(BaseModel): return cls(width=1024, height=1024) case BaseModelType.ZImage: return cls(steps=9, cfg_scale=1.0, width=1024, height=1024) + case BaseModelType.Flux2: + # Different defaults based on variant + if variant == Flux2VariantType.Klein9BBase: + # Undistilled base model needs more steps + return cls(steps=28, cfg_scale=1.0, width=1024, height=1024) + else: + # Distilled models (Klein 4B, Klein 9B) use fewer steps + return cls(steps=4, cfg_scale=1.0, width=1024, height=1024) case _: # TODO(psyche): Do we want defaults for other base types? return None @@ -268,6 +281,108 @@ class Main_Checkpoint_SDXLRefiner_Config(Main_SD_Checkpoint_Config_Base, Config_ base: Literal[BaseModelType.StableDiffusionXLRefiner] = Field(default=BaseModelType.StableDiffusionXLRefiner) +def _is_flux2_model(state_dict: dict[str | int, Any]) -> bool: + """Check if state dict is a FLUX.2 model by examining context_embedder dimensions. + + FLUX.2 Klein uses Qwen3 encoder with larger context dimension: + - FLUX.1: context_in_dim = 4096 (T5) + - FLUX.2 Klein 4B: context_in_dim = 7680 (3×Qwen3-4B hidden size) + - FLUX.2 Klein 8B: context_in_dim = 12288 (3×Qwen3-8B hidden size) + + Also checks for FLUX.2-specific 32-channel latent space (in_channels=128 after packing). + """ + # Check context_embedder input dimension (most reliable) + # Weight shape: [hidden_size, context_in_dim] + for key in {"context_embedder.weight", "model.diffusion_model.context_embedder.weight"}: + if key in state_dict: + weight = state_dict[key] + if hasattr(weight, "shape") and len(weight.shape) >= 2: + context_in_dim = weight.shape[1] + # FLUX.2 has context_in_dim > 4096 (Qwen3 vs T5) + if context_in_dim > 4096: + return True + + # Also check in_channels - FLUX.2 uses 128 (32 latent channels × 4 packing) + for key in {"img_in.weight", "model.diffusion_model.img_in.weight"}: + if key in state_dict: + in_channels = state_dict[key].shape[1] + # FLUX.2 uses 128 in_channels (32 latent channels × 4) + # FLUX.1 uses 64 in_channels (16 latent channels × 4) + if in_channels == 128: + return True + + return False + + +def _get_flux2_variant(state_dict: dict[str | int, Any]) -> Flux2VariantType | None: + """Determine FLUX.2 variant from state dict. + + Distinguishes between Klein 4B and Klein 9B based on context embedding dimension: + - Klein 4B: context_in_dim = 7680 (3 × Qwen3-4B hidden_size 2560) + - Klein 9B: context_in_dim = 12288 (3 × Qwen3-8B hidden_size 4096) + + Note: Klein 9B Base (undistilled) also has context_in_dim = 12288 but is rare. + We default to Klein9B (distilled) for all 9B models since GGUF models may not + include guidance embedding keys needed to distinguish them. + + Supports both BFL format (checkpoint) and diffusers format keys: + - BFL format: txt_in.weight (context embedder) + - Diffusers format: context_embedder.weight + """ + # Context dimensions for each variant + KLEIN_4B_CONTEXT_DIM = 7680 # 3 × 2560 + KLEIN_9B_CONTEXT_DIM = 12288 # 3 × 4096 + + # Check context_embedder to determine variant + # Support both BFL format (txt_in.weight) and diffusers format (context_embedder.weight) + context_keys = { + # Diffusers format + "context_embedder.weight", + "model.diffusion_model.context_embedder.weight", + # BFL format (used by checkpoint/GGUF models) + "txt_in.weight", + "model.diffusion_model.txt_in.weight", + } + for key in context_keys: + if key in state_dict: + weight = state_dict[key] + # Handle GGUF quantized tensors which use tensor_shape instead of shape + if hasattr(weight, "tensor_shape"): + shape = weight.tensor_shape + elif hasattr(weight, "shape"): + shape = weight.shape + else: + continue + if len(shape) >= 2: + context_in_dim = shape[1] + # Determine variant based on context dimension + if context_in_dim == KLEIN_9B_CONTEXT_DIM: + # Default to Klein9B (distilled) - the official/common 9B model + return Flux2VariantType.Klein9B + elif context_in_dim == KLEIN_4B_CONTEXT_DIM: + return Flux2VariantType.Klein4B + elif context_in_dim > 4096: + # Unknown FLUX.2 variant, default to 4B + return Flux2VariantType.Klein4B + + # Check in_channels as backup - can only confirm it's FLUX.2, not which variant + for key in {"img_in.weight", "model.diffusion_model.img_in.weight"}: + if key in state_dict: + weight = state_dict[key] + # Handle GGUF quantized tensors + if hasattr(weight, "tensor_shape"): + in_channels = weight.tensor_shape[1] + elif hasattr(weight, "shape"): + in_channels = weight.shape[1] + else: + continue + if in_channels == 128: + # It's FLUX.2 but we can't determine which Klein variant, default to 4B + return Flux2VariantType.Klein4B + + return None + + def _get_flux_variant(state_dict: dict[str | int, Any]) -> FluxVariantType | None: # FLUX Model variant types are distinguished by input channels and the presence of certain keys. @@ -341,8 +456,9 @@ class Main_Checkpoint_FLUX_Config(Checkpoint_Config_Base, Main_Config_Base, Conf @classmethod def _validate_is_flux(cls, mod: ModelOnDisk) -> None: + state_dict = mod.load_state_dict() if not state_dict_has_any_keys_exact( - mod.load_state_dict(), + state_dict, { "double_blocks.0.img_attn.norm.key_norm.scale", "model.diffusion_model.double_blocks.0.img_attn.norm.key_norm.scale", @@ -350,6 +466,10 @@ class Main_Checkpoint_FLUX_Config(Checkpoint_Config_Base, Main_Config_Base, Conf ): raise NotAMatchError("state dict does not look like a FLUX checkpoint") + # Exclude FLUX.2 models - they have their own config class + if _is_flux2_model(state_dict): + raise NotAMatchError("model is a FLUX.2 model, not FLUX.1") + @classmethod def _get_variant_or_raise(cls, mod: ModelOnDisk) -> FluxVariantType: # FLUX Model variant types are distinguished by input channels and the presence of certain keys. @@ -383,6 +503,68 @@ class Main_Checkpoint_FLUX_Config(Checkpoint_Config_Base, Main_Config_Base, Conf raise NotAMatchError("state dict looks like GGUF quantized") +class Main_Checkpoint_Flux2_Config(Checkpoint_Config_Base, Main_Config_Base, Config_Base): + """Model config for FLUX.2 checkpoint models (e.g. Klein).""" + + format: Literal[ModelFormat.Checkpoint] = Field(default=ModelFormat.Checkpoint) + base: Literal[BaseModelType.Flux2] = Field(default=BaseModelType.Flux2) + + variant: Flux2VariantType = Field() + + @classmethod + def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self: + raise_if_not_file(mod) + + raise_for_override_fields(cls, override_fields) + + cls._validate_looks_like_main_model(mod) + + cls._validate_is_flux2(mod) + + cls._validate_does_not_look_like_bnb_quantized(mod) + + cls._validate_does_not_look_like_gguf_quantized(mod) + + variant = override_fields.get("variant") or cls._get_variant_or_raise(mod) + + return cls(**override_fields, variant=variant) + + @classmethod + def _validate_is_flux2(cls, mod: ModelOnDisk) -> None: + """Validate that this is a FLUX.2 model, not FLUX.1.""" + state_dict = mod.load_state_dict() + if not _is_flux2_model(state_dict): + raise NotAMatchError("state dict does not look like a FLUX.2 model") + + @classmethod + def _get_variant_or_raise(cls, mod: ModelOnDisk) -> Flux2VariantType: + state_dict = mod.load_state_dict() + variant = _get_flux2_variant(state_dict) + + if variant is None: + raise NotAMatchError("unable to determine FLUX.2 model variant from state dict") + + return variant + + @classmethod + def _validate_looks_like_main_model(cls, mod: ModelOnDisk) -> None: + has_main_model_keys = _has_main_keys(mod.load_state_dict()) + if not has_main_model_keys: + raise NotAMatchError("state dict does not look like a main model") + + @classmethod + def _validate_does_not_look_like_bnb_quantized(cls, mod: ModelOnDisk) -> None: + has_bnb_nf4_keys = _has_bnb_nf4_keys(mod.load_state_dict()) + if has_bnb_nf4_keys: + raise NotAMatchError("state dict looks like bnb quantized nf4") + + @classmethod + def _validate_does_not_look_like_gguf_quantized(cls, mod: ModelOnDisk): + has_ggml_tensors = _has_ggml_tensors(mod.load_state_dict()) + if has_ggml_tensors: + raise NotAMatchError("state dict looks like GGUF quantized") + + class Main_BnBNF4_FLUX_Config(Checkpoint_Config_Base, Main_Config_Base, Config_Base): """Model config for main checkpoint models.""" @@ -450,6 +632,8 @@ class Main_GGUF_FLUX_Config(Checkpoint_Config_Base, Main_Config_Base, Config_Bas cls._validate_looks_like_gguf_quantized(mod) + cls._validate_is_not_flux2(mod) + variant = override_fields.get("variant") or cls._get_variant_or_raise(mod) return cls(**override_fields, variant=variant) @@ -480,6 +664,195 @@ class Main_GGUF_FLUX_Config(Checkpoint_Config_Base, Main_Config_Base, Config_Bas if not has_ggml_tensors: raise NotAMatchError("state dict does not look like GGUF quantized") + @classmethod + def _validate_is_not_flux2(cls, mod: ModelOnDisk) -> None: + """Validate that this is NOT a FLUX.2 model.""" + state_dict = mod.load_state_dict() + if _is_flux2_model(state_dict): + raise NotAMatchError("model is a FLUX.2 model, not FLUX.1") + + +class Main_GGUF_Flux2_Config(Checkpoint_Config_Base, Main_Config_Base, Config_Base): + """Model config for GGUF-quantized FLUX.2 checkpoint models (e.g. Klein).""" + + base: Literal[BaseModelType.Flux2] = Field(default=BaseModelType.Flux2) + format: Literal[ModelFormat.GGUFQuantized] = Field(default=ModelFormat.GGUFQuantized) + + variant: Flux2VariantType = Field() + + @classmethod + def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self: + raise_if_not_file(mod) + + raise_for_override_fields(cls, override_fields) + + cls._validate_looks_like_main_model(mod) + + cls._validate_looks_like_gguf_quantized(mod) + + cls._validate_is_flux2(mod) + + variant = override_fields.get("variant") or cls._get_variant_or_raise(mod) + + return cls(**override_fields, variant=variant) + + @classmethod + def _validate_is_flux2(cls, mod: ModelOnDisk) -> None: + """Validate that this is a FLUX.2 model, not FLUX.1.""" + state_dict = mod.load_state_dict() + if not _is_flux2_model(state_dict): + raise NotAMatchError("state dict does not look like a FLUX.2 model") + + @classmethod + def _get_variant_or_raise(cls, mod: ModelOnDisk) -> Flux2VariantType: + state_dict = mod.load_state_dict() + variant = _get_flux2_variant(state_dict) + + if variant is None: + raise NotAMatchError("unable to determine FLUX.2 model variant from state dict") + + return variant + + @classmethod + def _validate_looks_like_main_model(cls, mod: ModelOnDisk) -> None: + has_main_model_keys = _has_main_keys(mod.load_state_dict()) + if not has_main_model_keys: + raise NotAMatchError("state dict does not look like a main model") + + @classmethod + def _validate_looks_like_gguf_quantized(cls, mod: ModelOnDisk) -> None: + has_ggml_tensors = _has_ggml_tensors(mod.load_state_dict()) + if not has_ggml_tensors: + raise NotAMatchError("state dict does not look like GGUF quantized") + + +class Main_Diffusers_FLUX_Config(Diffusers_Config_Base, Main_Config_Base, Config_Base): + """Model config for FLUX.1 models in diffusers format.""" + + base: Literal[BaseModelType.Flux] = Field(BaseModelType.Flux) + variant: FluxVariantType = Field() + + @classmethod + def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self: + raise_if_not_dir(mod) + + raise_for_override_fields(cls, override_fields) + + # Check for FLUX-specific pipeline or transformer class names + raise_for_class_name( + common_config_paths(mod.path), + { + "FluxPipeline", + "FluxFillPipeline", + "FluxTransformer2DModel", + }, + ) + + variant = override_fields.get("variant") or cls._get_variant_or_raise(mod) + + repo_variant = override_fields.get("repo_variant") or cls._get_repo_variant_or_raise(mod) + + return cls( + **override_fields, + variant=variant, + repo_variant=repo_variant, + ) + + @classmethod + def _get_variant_or_raise(cls, mod: ModelOnDisk) -> FluxVariantType: + """Determine the FLUX variant from the transformer config. + + FLUX variants are distinguished by: + - in_channels: 64 for Dev/Schnell, 384 for DevFill + - guidance_embeds: True for Dev, False for Schnell + """ + transformer_config = get_config_dict_or_raise(mod.path / "transformer" / "config.json") + + in_channels = transformer_config.get("in_channels", 64) + guidance_embeds = transformer_config.get("guidance_embeds", False) + + # DevFill has 384 input channels + if in_channels == 384: + return FluxVariantType.DevFill + + # Dev has guidance_embeds=True, Schnell has guidance_embeds=False + if guidance_embeds: + return FluxVariantType.Dev + else: + return FluxVariantType.Schnell + + +class Main_Diffusers_Flux2_Config(Diffusers_Config_Base, Main_Config_Base, Config_Base): + """Model config for FLUX.2 models in diffusers format (e.g. FLUX.2 Klein).""" + + base: Literal[BaseModelType.Flux2] = Field(BaseModelType.Flux2) + variant: Flux2VariantType = Field() + + @classmethod + def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self: + raise_if_not_dir(mod) + + raise_for_override_fields(cls, override_fields) + + # Check for FLUX.2-specific pipeline class names + raise_for_class_name( + common_config_paths(mod.path), + { + "Flux2KleinPipeline", + }, + ) + + variant = override_fields.get("variant") or cls._get_variant_or_raise(mod) + + repo_variant = override_fields.get("repo_variant") or cls._get_repo_variant_or_raise(mod) + + return cls( + **override_fields, + variant=variant, + repo_variant=repo_variant, + ) + + @classmethod + def _get_variant_or_raise(cls, mod: ModelOnDisk) -> Flux2VariantType: + """Determine the FLUX.2 variant from the transformer config. + + FLUX.2 Klein uses Qwen3 text encoder with larger joint_attention_dim: + - Klein 4B: joint_attention_dim = 7680 (3×Qwen3-4B hidden size) + - Klein 9B/9B Base: joint_attention_dim = 12288 (3×Qwen3-8B hidden size) + + To distinguish Klein 9B (distilled) from Klein 9B Base (undistilled), + we check guidance_embeds: + - Klein 9B (distilled): guidance_embeds = False (guidance is "baked in" during distillation) + - Klein 9B Base (undistilled): guidance_embeds = True (needs guidance at inference) + + Note: The official BFL Klein 9B model is the distilled version with guidance_embeds=False. + """ + KLEIN_4B_CONTEXT_DIM = 7680 # 3 × 2560 + KLEIN_9B_CONTEXT_DIM = 12288 # 3 × 4096 + + transformer_config = get_config_dict_or_raise(mod.path / "transformer" / "config.json") + + joint_attention_dim = transformer_config.get("joint_attention_dim", 4096) + guidance_embeds = transformer_config.get("guidance_embeds", False) + + # Determine variant based on joint_attention_dim + if joint_attention_dim == KLEIN_9B_CONTEXT_DIM: + # Check guidance_embeds to distinguish distilled from undistilled + # Klein 9B (distilled): guidance_embeds = False (guidance is baked in) + # Klein 9B Base (undistilled): guidance_embeds = True (needs guidance) + if guidance_embeds: + return Flux2VariantType.Klein9BBase + else: + return Flux2VariantType.Klein9B + elif joint_attention_dim == KLEIN_4B_CONTEXT_DIM: + return Flux2VariantType.Klein4B + elif joint_attention_dim > 4096: + # Unknown FLUX.2 variant, default to 4B + return Flux2VariantType.Klein4B + + # Default to 4B + return Flux2VariantType.Klein4B + class Main_SD_Diffusers_Config_Base(Diffusers_Config_Base, Main_Config_Base): prediction_type: SchedulerPredictionType = Field() diff --git a/invokeai/backend/model_manager/configs/qwen3_encoder.py b/invokeai/backend/model_manager/configs/qwen3_encoder.py index 4d78795b7d..060c6b73ac 100644 --- a/invokeai/backend/model_manager/configs/qwen3_encoder.py +++ b/invokeai/backend/model_manager/configs/qwen3_encoder.py @@ -1,4 +1,5 @@ -from typing import Any, Literal, Self +import json +from typing import Any, Literal, Optional, Self from pydantic import Field @@ -11,7 +12,7 @@ from invokeai.backend.model_manager.configs.identification_utils import ( raise_if_not_file, ) from invokeai.backend.model_manager.model_on_disk import ModelOnDisk -from invokeai.backend.model_manager.taxonomy import BaseModelType, ModelFormat, ModelType +from invokeai.backend.model_manager.taxonomy import BaseModelType, ModelFormat, ModelType, Qwen3VariantType from invokeai.backend.quantization.gguf.ggml_tensor import GGMLTensor @@ -45,12 +46,67 @@ def _has_ggml_tensors(state_dict: dict[str | int, Any]) -> bool: return any(isinstance(v, GGMLTensor) for v in state_dict.values()) +def _get_qwen3_variant_from_state_dict(state_dict: dict[str | int, Any]) -> Optional[Qwen3VariantType]: + """Determine Qwen3 variant (4B vs 8B) from state dict based on hidden_size. + + The hidden_size can be determined from the embed_tokens.weight tensor shape: + - Qwen3 4B: hidden_size = 2560 + - Qwen3 8B: hidden_size = 4096 + + For GGUF format, the key is 'token_embd.weight'. + For PyTorch format, the key is 'model.embed_tokens.weight'. + """ + # Hidden size thresholds + QWEN3_4B_HIDDEN_SIZE = 2560 + QWEN3_8B_HIDDEN_SIZE = 4096 + + # Try to find embed_tokens weight + embed_key = None + for key in state_dict.keys(): + if isinstance(key, str): + if key == "model.embed_tokens.weight" or key == "token_embd.weight": + embed_key = key + break + + if embed_key is None: + return None + + tensor = state_dict[embed_key] + + # Get hidden_size from tensor shape + # Shape is [vocab_size, hidden_size] + if isinstance(tensor, GGMLTensor): + # GGUF tensor + if hasattr(tensor, "shape") and len(tensor.shape) >= 2: + hidden_size = tensor.shape[1] + else: + return None + elif hasattr(tensor, "shape"): + # PyTorch tensor + if len(tensor.shape) >= 2: + hidden_size = tensor.shape[1] + else: + return None + else: + return None + + # Determine variant based on hidden_size + if hidden_size == QWEN3_4B_HIDDEN_SIZE: + return Qwen3VariantType.Qwen3_4B + elif hidden_size == QWEN3_8B_HIDDEN_SIZE: + return Qwen3VariantType.Qwen3_8B + else: + # Unknown size, default to 4B (more common) + return Qwen3VariantType.Qwen3_4B + + class Qwen3Encoder_Checkpoint_Config(Checkpoint_Config_Base, Config_Base): """Configuration for single-file Qwen3 Encoder models (safetensors).""" base: Literal[BaseModelType.Any] = Field(default=BaseModelType.Any) type: Literal[ModelType.Qwen3Encoder] = Field(default=ModelType.Qwen3Encoder) format: Literal[ModelFormat.Checkpoint] = Field(default=ModelFormat.Checkpoint) + variant: Qwen3VariantType = Field(description="Qwen3 model size variant (4B or 8B)") @classmethod def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self: @@ -62,7 +118,17 @@ class Qwen3Encoder_Checkpoint_Config(Checkpoint_Config_Base, Config_Base): cls._validate_does_not_look_like_gguf_quantized(mod) - return cls(**override_fields) + # Determine variant from state dict + variant = cls._get_variant_or_default(mod) + + return cls(variant=variant, **override_fields) + + @classmethod + def _get_variant_or_default(cls, mod: ModelOnDisk) -> Qwen3VariantType: + """Get variant from state dict, defaulting to 4B if unknown.""" + state_dict = mod.load_state_dict() + variant = _get_qwen3_variant_from_state_dict(state_dict) + return variant if variant is not None else Qwen3VariantType.Qwen3_4B @classmethod def _validate_looks_like_qwen3_model(cls, mod: ModelOnDisk) -> None: @@ -87,6 +153,7 @@ class Qwen3Encoder_Qwen3Encoder_Config(Config_Base): base: Literal[BaseModelType.Any] = Field(default=BaseModelType.Any) type: Literal[ModelType.Qwen3Encoder] = Field(default=ModelType.Qwen3Encoder) format: Literal[ModelFormat.Qwen3Encoder] = Field(default=ModelFormat.Qwen3Encoder) + variant: Qwen3VariantType = Field(description="Qwen3 model size variant (4B or 8B)") @classmethod def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self: @@ -94,6 +161,16 @@ class Qwen3Encoder_Qwen3Encoder_Config(Config_Base): raise_for_override_fields(cls, override_fields) + # Exclude full pipeline models - these should be matched as main models, not just Qwen3 encoders. + # Full pipelines have model_index.json at root (diffusers format) or a transformer subfolder. + model_index_path = mod.path / "model_index.json" + transformer_path = mod.path / "transformer" + if model_index_path.exists() or transformer_path.exists(): + raise NotAMatchError( + "directory looks like a full diffusers pipeline (has model_index.json or transformer folder), " + "not a standalone Qwen3 encoder" + ) + # Check for text_encoder config - support both: # 1. Full model structure: model_root/text_encoder/config.json # 2. Standalone text_encoder download: model_root/config.json (when text_encoder subfolder is downloaded separately) @@ -105,8 +182,6 @@ class Qwen3Encoder_Qwen3Encoder_Config(Config_Base): elif config_path_direct.exists(): expected_config_path = config_path_direct else: - from invokeai.backend.model_manager.configs.identification_utils import NotAMatchError - raise NotAMatchError( f"unable to load config file(s): {{PosixPath('{config_path_nested}'): 'file does not exist'}}" ) @@ -121,7 +196,30 @@ class Qwen3Encoder_Qwen3Encoder_Config(Config_Base): }, ) - return cls(**override_fields) + # Determine variant from config.json hidden_size + variant = cls._get_variant_from_config(expected_config_path) + + return cls(variant=variant, **override_fields) + + @classmethod + def _get_variant_from_config(cls, config_path) -> Qwen3VariantType: + """Get variant from config.json based on hidden_size.""" + QWEN3_4B_HIDDEN_SIZE = 2560 + QWEN3_8B_HIDDEN_SIZE = 4096 + + try: + with open(config_path, "r", encoding="utf-8") as f: + config = json.load(f) + hidden_size = config.get("hidden_size") + if hidden_size == QWEN3_8B_HIDDEN_SIZE: + return Qwen3VariantType.Qwen3_8B + elif hidden_size == QWEN3_4B_HIDDEN_SIZE: + return Qwen3VariantType.Qwen3_4B + else: + # Default to 4B for unknown sizes + return Qwen3VariantType.Qwen3_4B + except (json.JSONDecodeError, OSError): + return Qwen3VariantType.Qwen3_4B class Qwen3Encoder_GGUF_Config(Checkpoint_Config_Base, Config_Base): @@ -130,6 +228,7 @@ class Qwen3Encoder_GGUF_Config(Checkpoint_Config_Base, Config_Base): base: Literal[BaseModelType.Any] = Field(default=BaseModelType.Any) type: Literal[ModelType.Qwen3Encoder] = Field(default=ModelType.Qwen3Encoder) format: Literal[ModelFormat.GGUFQuantized] = Field(default=ModelFormat.GGUFQuantized) + variant: Qwen3VariantType = Field(description="Qwen3 model size variant (4B or 8B)") @classmethod def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self: @@ -141,7 +240,17 @@ class Qwen3Encoder_GGUF_Config(Checkpoint_Config_Base, Config_Base): cls._validate_looks_like_gguf_quantized(mod) - return cls(**override_fields) + # Determine variant from state dict + variant = cls._get_variant_or_default(mod) + + return cls(variant=variant, **override_fields) + + @classmethod + def _get_variant_or_default(cls, mod: ModelOnDisk) -> Qwen3VariantType: + """Get variant from state dict, defaulting to 4B if unknown.""" + state_dict = mod.load_state_dict() + variant = _get_qwen3_variant_from_state_dict(state_dict) + return variant if variant is not None else Qwen3VariantType.Qwen3_4B @classmethod def _validate_looks_like_qwen3_model(cls, mod: ModelOnDisk) -> None: diff --git a/invokeai/backend/model_manager/configs/vae.py b/invokeai/backend/model_manager/configs/vae.py index 2525e0a1e4..00c5783284 100644 --- a/invokeai/backend/model_manager/configs/vae.py +++ b/invokeai/backend/model_manager/configs/vae.py @@ -33,6 +33,18 @@ REGEX_TO_BASE: dict[str, BaseModelType] = { } +def _is_flux2_vae(state_dict: dict[str | int, Any]) -> bool: + """Check if state dict is a FLUX.2 VAE (AutoencoderKLFlux2). + + FLUX.2 VAE has a Batch Normalization layer (bn.running_mean, bn.running_var) + which is unique to FLUX.2 and not present in FLUX.1 VAE. + """ + # Check for BN layer which is unique to FLUX.2 VAE + # Note: We cannot use encoder.conv_out channel count because both FLUX.1 and FLUX.2 + # have 32 output channels (FLUX.1: 16 latent × 2, FLUX.2: 32 latent × 2 but patchified) + return "bn.running_mean" in state_dict or "bn.running_var" in state_dict + + class VAE_Checkpoint_Config_Base(Checkpoint_Config_Base): """Model config for standalone VAE models.""" @@ -61,8 +73,9 @@ class VAE_Checkpoint_Config_Base(Checkpoint_Config_Base): @classmethod def _validate_looks_like_vae(cls, mod: ModelOnDisk) -> None: + state_dict = mod.load_state_dict() if not state_dict_has_any_keys_starting_with( - mod.load_state_dict(), + state_dict, { "encoder.conv_in", "decoder.conv_in", @@ -70,6 +83,10 @@ class VAE_Checkpoint_Config_Base(Checkpoint_Config_Base): ): raise NotAMatchError("model does not match Checkpoint VAE heuristics") + # Exclude FLUX.2 VAEs - they have their own config class + if _is_flux2_vae(state_dict): + raise NotAMatchError("model is a FLUX.2 VAE, not a standard VAE") + @classmethod def _get_base_or_raise(cls, mod: ModelOnDisk) -> BaseModelType: # Heuristic: VAEs of all architectures have a similar structure; the best we can do is guess based on name @@ -96,6 +113,44 @@ class VAE_Checkpoint_FLUX_Config(VAE_Checkpoint_Config_Base, Config_Base): base: Literal[BaseModelType.Flux] = Field(default=BaseModelType.Flux) +class VAE_Checkpoint_Flux2_Config(Checkpoint_Config_Base, Config_Base): + """Model config for FLUX.2 VAE checkpoint models (AutoencoderKLFlux2).""" + + type: Literal[ModelType.VAE] = Field(default=ModelType.VAE) + format: Literal[ModelFormat.Checkpoint] = Field(default=ModelFormat.Checkpoint) + base: Literal[BaseModelType.Flux2] = Field(default=BaseModelType.Flux2) + + @classmethod + def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self: + raise_if_not_file(mod) + + raise_for_override_fields(cls, override_fields) + + cls._validate_looks_like_vae(mod) + + cls._validate_is_flux2_vae(mod) + + return cls(**override_fields) + + @classmethod + def _validate_looks_like_vae(cls, mod: ModelOnDisk) -> None: + if not state_dict_has_any_keys_starting_with( + mod.load_state_dict(), + { + "encoder.conv_in", + "decoder.conv_in", + }, + ): + raise NotAMatchError("model does not match Checkpoint VAE heuristics") + + @classmethod + def _validate_is_flux2_vae(cls, mod: ModelOnDisk) -> None: + """Validate that this is a FLUX.2 VAE, not FLUX.1.""" + state_dict = mod.load_state_dict() + if not _is_flux2_vae(state_dict): + raise NotAMatchError("state dict does not look like a FLUX.2 VAE") + + class VAE_Diffusers_Config_Base(Diffusers_Config_Base): """Model config for standalone VAE models (diffusers version).""" @@ -161,3 +216,26 @@ class VAE_Diffusers_SD1_Config(VAE_Diffusers_Config_Base, Config_Base): class VAE_Diffusers_SDXL_Config(VAE_Diffusers_Config_Base, Config_Base): base: Literal[BaseModelType.StableDiffusionXL] = Field(default=BaseModelType.StableDiffusionXL) + + +class VAE_Diffusers_Flux2_Config(Diffusers_Config_Base, Config_Base): + """Model config for FLUX.2 VAE models in diffusers format (AutoencoderKLFlux2).""" + + type: Literal[ModelType.VAE] = Field(default=ModelType.VAE) + format: Literal[ModelFormat.Diffusers] = Field(default=ModelFormat.Diffusers) + base: Literal[BaseModelType.Flux2] = Field(default=BaseModelType.Flux2) + + @classmethod + def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self: + raise_if_not_dir(mod) + + raise_for_override_fields(cls, override_fields) + + raise_for_class_name( + common_config_paths(mod.path), + { + "AutoencoderKLFlux2", + }, + ) + + return cls(**override_fields) diff --git a/invokeai/backend/model_manager/load/model_loaders/flux.py b/invokeai/backend/model_manager/load/model_loaders/flux.py index 4e732187a3..2de51a8aca 100644 --- a/invokeai/backend/model_manager/load/model_loaders/flux.py +++ b/invokeai/backend/model_manager/load/model_loaders/flux.py @@ -34,7 +34,7 @@ from invokeai.backend.flux.model import Flux from invokeai.backend.flux.modules.autoencoder import AutoEncoder from invokeai.backend.flux.redux.flux_redux_model import FluxReduxModel from invokeai.backend.flux.util import get_flux_ae_params, get_flux_transformers_params -from invokeai.backend.model_manager.configs.base import Checkpoint_Config_Base +from invokeai.backend.model_manager.configs.base import Checkpoint_Config_Base, Diffusers_Config_Base from invokeai.backend.model_manager.configs.clip_embed import CLIPEmbed_Diffusers_Config_Base from invokeai.backend.model_manager.configs.controlnet import ( ControlNet_Checkpoint_Config_Base, @@ -45,13 +45,16 @@ from invokeai.backend.model_manager.configs.flux_redux import FLUXRedux_Checkpoi from invokeai.backend.model_manager.configs.ip_adapter import IPAdapter_Checkpoint_Config_Base from invokeai.backend.model_manager.configs.main import ( Main_BnBNF4_FLUX_Config, + Main_Checkpoint_Flux2_Config, Main_Checkpoint_FLUX_Config, + Main_GGUF_Flux2_Config, Main_GGUF_FLUX_Config, ) from invokeai.backend.model_manager.configs.t5_encoder import T5Encoder_BnBLLMint8_Config, T5Encoder_T5Encoder_Config -from invokeai.backend.model_manager.configs.vae import VAE_Checkpoint_Config_Base +from invokeai.backend.model_manager.configs.vae import VAE_Checkpoint_Config_Base, VAE_Checkpoint_Flux2_Config from invokeai.backend.model_manager.load.load_default import ModelLoader from invokeai.backend.model_manager.load.model_loader_registry import ModelLoaderRegistry +from invokeai.backend.model_manager.load.model_loaders.generic_diffusers import GenericDiffusersLoader from invokeai.backend.model_manager.taxonomy import ( AnyModel, BaseModelType, @@ -108,6 +111,264 @@ class FluxVAELoader(ModelLoader): return model +@ModelLoaderRegistry.register(base=BaseModelType.Flux2, type=ModelType.VAE, format=ModelFormat.Diffusers) +class Flux2VAEDiffusersLoader(ModelLoader): + """Class to load FLUX.2 VAE models in diffusers format (AutoencoderKLFlux2 with 32 latent channels).""" + + def _load_model( + self, + config: AnyModelConfig, + submodel_type: Optional[SubModelType] = None, + ) -> AnyModel: + from diffusers import AutoencoderKLFlux2 + + model_path = Path(config.path) + + # VAE is broken in float16, which mps defaults to + if self._torch_dtype == torch.float16: + try: + vae_dtype = torch.tensor([1.0], dtype=torch.bfloat16, device=self._torch_device).dtype + except TypeError: + vae_dtype = torch.float32 + else: + vae_dtype = self._torch_dtype + + model = AutoencoderKLFlux2.from_pretrained( + model_path, + torch_dtype=vae_dtype, + local_files_only=True, + ) + + return model + + +@ModelLoaderRegistry.register(base=BaseModelType.Flux2, type=ModelType.VAE, format=ModelFormat.Checkpoint) +class Flux2VAELoader(ModelLoader): + """Class to load FLUX.2 VAE models (AutoencoderKLFlux2 with 32 latent channels).""" + + def _load_model( + self, + config: AnyModelConfig, + submodel_type: Optional[SubModelType] = None, + ) -> AnyModel: + if not isinstance(config, VAE_Checkpoint_Flux2_Config): + raise ValueError("Only VAE_Checkpoint_Flux2_Config models are currently supported here.") + + from diffusers import AutoencoderKLFlux2 + + model_path = Path(config.path) + + # Load state dict manually since from_single_file may not support AutoencoderKLFlux2 yet + sd = load_file(model_path) + + # Convert BFL format to diffusers format if needed + # BFL format uses: encoder.down., decoder.up., decoder.mid.block_1, decoder.mid.attn_1, decoder.norm_out + # Diffusers uses: encoder.down_blocks., decoder.up_blocks., decoder.mid_block.resnets., decoder.conv_norm_out + is_bfl_format = any( + k.startswith("encoder.down.") + or k.startswith("decoder.up.") + or k.startswith("decoder.mid.block_") + or k.startswith("decoder.mid.attn_") + or k.startswith("decoder.norm_out") + or k.startswith("encoder.mid.block_") + or k.startswith("encoder.mid.attn_") + or k.startswith("encoder.norm_out") + for k in sd.keys() + ) + if is_bfl_format: + sd = self._convert_flux2_vae_bfl_to_diffusers(sd) + + # FLUX.2 VAE configuration (32 latent channels) + # Based on the official FLUX.2 VAE architecture + # Use default config - AutoencoderKLFlux2 has built-in defaults + with SilenceWarnings(): + with accelerate.init_empty_weights(): + model = AutoencoderKLFlux2() + + # Convert to bfloat16 and load + for k in sd.keys(): + sd[k] = sd[k].to(torch.bfloat16) + + model.load_state_dict(sd, assign=True) + + # VAE is broken in float16, which mps defaults to + if self._torch_dtype == torch.float16: + try: + vae_dtype = torch.tensor([1.0], dtype=torch.bfloat16, device=self._torch_device).dtype + except TypeError: + vae_dtype = torch.float32 + else: + vae_dtype = self._torch_dtype + model.to(vae_dtype) + + return model + + def _convert_flux2_vae_bfl_to_diffusers(self, sd: dict) -> dict: + """Convert FLUX.2 VAE BFL format state dict to diffusers format. + + Key differences: + - encoder.down.X.block.Y -> encoder.down_blocks.X.resnets.Y + - encoder.down.X.downsample.conv -> encoder.down_blocks.X.downsamplers.0.conv + - encoder.mid.block_1/2 -> encoder.mid_block.resnets.0/1 + - encoder.mid.attn_1.q/k/v -> encoder.mid_block.attentions.0.to_q/k/v + - encoder.norm_out -> encoder.conv_norm_out + - encoder.quant_conv -> quant_conv (top-level) + - decoder.up.X -> decoder.up_blocks.(num_blocks-1-X) (reversed order!) + - decoder.post_quant_conv -> post_quant_conv (top-level) + - *.nin_shortcut -> *.conv_shortcut + """ + import re + + converted = {} + num_up_blocks = 4 # Standard VAE has 4 up blocks + + for old_key, tensor in sd.items(): + new_key = old_key + + # Encoder down blocks: encoder.down.X.block.Y -> encoder.down_blocks.X.resnets.Y + match = re.match(r"encoder\.down\.(\d+)\.block\.(\d+)\.(.*)", old_key) + if match: + block_idx, resnet_idx, rest = match.groups() + rest = rest.replace("nin_shortcut", "conv_shortcut") + new_key = f"encoder.down_blocks.{block_idx}.resnets.{resnet_idx}.{rest}" + converted[new_key] = tensor + continue + + # Encoder downsamplers: encoder.down.X.downsample.conv -> encoder.down_blocks.X.downsamplers.0.conv + match = re.match(r"encoder\.down\.(\d+)\.downsample\.conv\.(.*)", old_key) + if match: + block_idx, rest = match.groups() + new_key = f"encoder.down_blocks.{block_idx}.downsamplers.0.conv.{rest}" + converted[new_key] = tensor + continue + + # Encoder mid block resnets: encoder.mid.block_1/2 -> encoder.mid_block.resnets.0/1 + match = re.match(r"encoder\.mid\.block_(\d+)\.(.*)", old_key) + if match: + block_num, rest = match.groups() + resnet_idx = int(block_num) - 1 # block_1 -> resnets.0, block_2 -> resnets.1 + new_key = f"encoder.mid_block.resnets.{resnet_idx}.{rest}" + converted[new_key] = tensor + continue + + # Encoder mid block attention: encoder.mid.attn_1.* -> encoder.mid_block.attentions.0.* + match = re.match(r"encoder\.mid\.attn_1\.(.*)", old_key) + if match: + rest = match.group(1) + # Map attention keys + # BFL uses Conv2d (shape [out, in, 1, 1]), diffusers uses Linear (shape [out, in]) + # Squeeze the extra dimensions for weight tensors + if rest.startswith("q."): + new_key = f"encoder.mid_block.attentions.0.to_q.{rest[2:]}" + if rest.endswith(".weight") and tensor.dim() == 4: + tensor = tensor.squeeze(-1).squeeze(-1) + elif rest.startswith("k."): + new_key = f"encoder.mid_block.attentions.0.to_k.{rest[2:]}" + if rest.endswith(".weight") and tensor.dim() == 4: + tensor = tensor.squeeze(-1).squeeze(-1) + elif rest.startswith("v."): + new_key = f"encoder.mid_block.attentions.0.to_v.{rest[2:]}" + if rest.endswith(".weight") and tensor.dim() == 4: + tensor = tensor.squeeze(-1).squeeze(-1) + elif rest.startswith("proj_out."): + new_key = f"encoder.mid_block.attentions.0.to_out.0.{rest[9:]}" + if rest.endswith(".weight") and tensor.dim() == 4: + tensor = tensor.squeeze(-1).squeeze(-1) + elif rest.startswith("norm."): + new_key = f"encoder.mid_block.attentions.0.group_norm.{rest[5:]}" + else: + new_key = f"encoder.mid_block.attentions.0.{rest}" + converted[new_key] = tensor + continue + + # Encoder norm_out -> conv_norm_out + if old_key.startswith("encoder.norm_out."): + new_key = old_key.replace("encoder.norm_out.", "encoder.conv_norm_out.") + converted[new_key] = tensor + continue + + # Encoder quant_conv -> quant_conv (move to top level) + if old_key.startswith("encoder.quant_conv."): + new_key = old_key.replace("encoder.quant_conv.", "quant_conv.") + converted[new_key] = tensor + continue + + # Decoder up blocks (reversed order!): decoder.up.X -> decoder.up_blocks.(num_blocks-1-X) + match = re.match(r"decoder\.up\.(\d+)\.block\.(\d+)\.(.*)", old_key) + if match: + block_idx, resnet_idx, rest = match.groups() + # Reverse the block index + new_block_idx = num_up_blocks - 1 - int(block_idx) + rest = rest.replace("nin_shortcut", "conv_shortcut") + new_key = f"decoder.up_blocks.{new_block_idx}.resnets.{resnet_idx}.{rest}" + converted[new_key] = tensor + continue + + # Decoder upsamplers (reversed order!) + match = re.match(r"decoder\.up\.(\d+)\.upsample\.conv\.(.*)", old_key) + if match: + block_idx, rest = match.groups() + new_block_idx = num_up_blocks - 1 - int(block_idx) + new_key = f"decoder.up_blocks.{new_block_idx}.upsamplers.0.conv.{rest}" + converted[new_key] = tensor + continue + + # Decoder mid block resnets: decoder.mid.block_1/2 -> decoder.mid_block.resnets.0/1 + match = re.match(r"decoder\.mid\.block_(\d+)\.(.*)", old_key) + if match: + block_num, rest = match.groups() + resnet_idx = int(block_num) - 1 + new_key = f"decoder.mid_block.resnets.{resnet_idx}.{rest}" + converted[new_key] = tensor + continue + + # Decoder mid block attention: decoder.mid.attn_1.* -> decoder.mid_block.attentions.0.* + match = re.match(r"decoder\.mid\.attn_1\.(.*)", old_key) + if match: + rest = match.group(1) + # BFL uses Conv2d (shape [out, in, 1, 1]), diffusers uses Linear (shape [out, in]) + # Squeeze the extra dimensions for weight tensors + if rest.startswith("q."): + new_key = f"decoder.mid_block.attentions.0.to_q.{rest[2:]}" + if rest.endswith(".weight") and tensor.dim() == 4: + tensor = tensor.squeeze(-1).squeeze(-1) + elif rest.startswith("k."): + new_key = f"decoder.mid_block.attentions.0.to_k.{rest[2:]}" + if rest.endswith(".weight") and tensor.dim() == 4: + tensor = tensor.squeeze(-1).squeeze(-1) + elif rest.startswith("v."): + new_key = f"decoder.mid_block.attentions.0.to_v.{rest[2:]}" + if rest.endswith(".weight") and tensor.dim() == 4: + tensor = tensor.squeeze(-1).squeeze(-1) + elif rest.startswith("proj_out."): + new_key = f"decoder.mid_block.attentions.0.to_out.0.{rest[9:]}" + if rest.endswith(".weight") and tensor.dim() == 4: + tensor = tensor.squeeze(-1).squeeze(-1) + elif rest.startswith("norm."): + new_key = f"decoder.mid_block.attentions.0.group_norm.{rest[5:]}" + else: + new_key = f"decoder.mid_block.attentions.0.{rest}" + converted[new_key] = tensor + continue + + # Decoder norm_out -> conv_norm_out + if old_key.startswith("decoder.norm_out."): + new_key = old_key.replace("decoder.norm_out.", "decoder.conv_norm_out.") + converted[new_key] = tensor + continue + + # Decoder post_quant_conv -> post_quant_conv (move to top level) + if old_key.startswith("decoder.post_quant_conv."): + new_key = old_key.replace("decoder.post_quant_conv.", "post_quant_conv.") + converted[new_key] = tensor + continue + + # Keep other keys as-is (like encoder.conv_in, decoder.conv_in, decoder.conv_out, bn.*) + converted[new_key] = tensor + + return converted + + @ModelLoaderRegistry.register(base=BaseModelType.Any, type=ModelType.CLIPEmbed, format=ModelFormat.Diffusers) class CLIPDiffusersLoader(ModelLoader): """Class to load main models.""" @@ -340,6 +601,750 @@ class FluxBnbQuantizednf4bCheckpointModel(ModelLoader): return model +@ModelLoaderRegistry.register(base=BaseModelType.Flux, type=ModelType.Main, format=ModelFormat.Diffusers) +class FluxDiffusersModel(GenericDiffusersLoader): + """Class to load FLUX.1 main models in diffusers format.""" + + def _load_model( + self, + config: AnyModelConfig, + submodel_type: Optional[SubModelType] = None, + ) -> AnyModel: + if isinstance(config, Checkpoint_Config_Base): + raise NotImplementedError("CheckpointConfigBase is not implemented for FLUX diffusers models.") + + if submodel_type is None: + raise Exception("A submodel type must be provided when loading main pipelines.") + + model_path = Path(config.path) + load_class = self.get_hf_load_class(model_path, submodel_type) + repo_variant = config.repo_variant if isinstance(config, Diffusers_Config_Base) else None + variant = repo_variant.value if repo_variant else None + model_path = model_path / submodel_type.value + + # We force bfloat16 for FLUX models. This is required for correct inference. + dtype = torch.bfloat16 + try: + result: AnyModel = load_class.from_pretrained( + model_path, + torch_dtype=dtype, + variant=variant, + local_files_only=True, + ) + except OSError as e: + if variant and "no file named" in str( + e + ): # try without the variant, just in case user's preferences changed + result = load_class.from_pretrained(model_path, torch_dtype=dtype, local_files_only=True) + else: + raise e + + return result + + +@ModelLoaderRegistry.register(base=BaseModelType.Flux2, type=ModelType.Main, format=ModelFormat.Diffusers) +class Flux2DiffusersModel(GenericDiffusersLoader): + """Class to load FLUX.2 main models in diffusers format (e.g. FLUX.2 Klein).""" + + def _load_model( + self, + config: AnyModelConfig, + submodel_type: Optional[SubModelType] = None, + ) -> AnyModel: + if isinstance(config, Checkpoint_Config_Base): + raise NotImplementedError("CheckpointConfigBase is not implemented for FLUX.2 diffusers models.") + + if submodel_type is None: + raise Exception("A submodel type must be provided when loading main pipelines.") + + model_path = Path(config.path) + load_class = self.get_hf_load_class(model_path, submodel_type) + repo_variant = config.repo_variant if isinstance(config, Diffusers_Config_Base) else None + variant = repo_variant.value if repo_variant else None + model_path = model_path / submodel_type.value + + # We force bfloat16 for FLUX.2 models. This is required for correct inference. + # We use low_cpu_mem_usage=False to avoid meta tensors for weights not in checkpoint. + # FLUX.2 Klein models may have guidance_embeds=False, so the guidance_embed layers + # won't be in the checkpoint but the model class still creates them. + # We use SilenceWarnings to suppress the "guidance_embeds is not expected" warning + # from diffusers Flux2Transformer2DModel. + dtype = torch.bfloat16 + with SilenceWarnings(): + try: + result: AnyModel = load_class.from_pretrained( + model_path, + torch_dtype=dtype, + variant=variant, + local_files_only=True, + low_cpu_mem_usage=False, + ) + except OSError as e: + if variant and "no file named" in str( + e + ): # try without the variant, just in case user's preferences changed + result = load_class.from_pretrained( + model_path, + torch_dtype=dtype, + local_files_only=True, + low_cpu_mem_usage=False, + ) + else: + raise e + + # For Klein models without guidance_embeds, zero out the guidance_embedder weights + # that were randomly initialized by diffusers. This prevents noise from affecting + # the time embeddings. + if submodel_type == SubModelType.Transformer and hasattr(result, "time_guidance_embed"): + # Check if this is a Klein model without guidance (guidance_embeds=False in config) + transformer_config_path = model_path / "config.json" + if transformer_config_path.exists(): + import json + + with open(transformer_config_path, "r") as f: + transformer_config = json.load(f) + if not transformer_config.get("guidance_embeds", True): + # Zero out the guidance embedder weights + guidance_emb = result.time_guidance_embed.guidance_embedder + if hasattr(guidance_emb, "linear_1"): + guidance_emb.linear_1.weight.data.zero_() + if guidance_emb.linear_1.bias is not None: + guidance_emb.linear_1.bias.data.zero_() + if hasattr(guidance_emb, "linear_2"): + guidance_emb.linear_2.weight.data.zero_() + if guidance_emb.linear_2.bias is not None: + guidance_emb.linear_2.bias.data.zero_() + + return result + + +@ModelLoaderRegistry.register(base=BaseModelType.Flux2, type=ModelType.Main, format=ModelFormat.Checkpoint) +class Flux2CheckpointModel(ModelLoader): + """Class to load FLUX.2 transformer models from single-file checkpoints (safetensors).""" + + def _load_model( + self, + config: AnyModelConfig, + submodel_type: Optional[SubModelType] = None, + ) -> AnyModel: + if not isinstance(config, Checkpoint_Config_Base): + raise ValueError("Only CheckpointConfigBase models are currently supported here.") + + match submodel_type: + case SubModelType.Transformer: + return self._load_from_singlefile(config) + + raise ValueError( + f"Only Transformer submodels are currently supported. Received: {submodel_type.value if submodel_type else 'None'}" + ) + + def _load_from_singlefile( + self, + config: AnyModelConfig, + ) -> AnyModel: + from diffusers import Flux2Transformer2DModel + + if not isinstance(config, Main_Checkpoint_Flux2_Config): + raise TypeError( + f"Expected Main_Checkpoint_Flux2_Config, got {type(config).__name__}. " + "Model configuration type mismatch." + ) + model_path = Path(config.path) + + # Load state dict + sd = load_file(model_path) + + # Handle FP8 quantized weights (ComfyUI-style or scaled FP8) + # These store weights as: layer.weight (FP8) + layer.weight_scale (FP32 scalar) + sd = self._dequantize_fp8_weights(sd) + + # Check if keys have ComfyUI-style prefix and strip if needed + prefix_to_strip = None + for prefix in ["model.diffusion_model.", "diffusion_model."]: + if any(k.startswith(prefix) for k in sd.keys() if isinstance(k, str)): + prefix_to_strip = prefix + break + + if prefix_to_strip: + sd = { + (k[len(prefix_to_strip) :] if isinstance(k, str) and k.startswith(prefix_to_strip) else k): v + for k, v in sd.items() + } + + # Convert BFL format state dict to diffusers format + converted_sd = self._convert_flux2_bfl_to_diffusers(sd) + + # Detect architecture from checkpoint keys + double_block_indices = [ + int(k.split(".")[1]) + for k in converted_sd.keys() + if isinstance(k, str) and k.startswith("transformer_blocks.") + ] + single_block_indices = [ + int(k.split(".")[1]) + for k in converted_sd.keys() + if isinstance(k, str) and k.startswith("single_transformer_blocks.") + ] + + num_layers = max(double_block_indices) + 1 if double_block_indices else 5 + num_single_layers = max(single_block_indices) + 1 if single_block_indices else 20 + + # Get dimensions from weights + # context_embedder.weight shape: [hidden_size, joint_attention_dim] + context_embedder_weight = converted_sd.get("context_embedder.weight") + if context_embedder_weight is not None: + hidden_size = context_embedder_weight.shape[0] + joint_attention_dim = context_embedder_weight.shape[1] + else: + # Default to Klein 4B dimensions + hidden_size = 3072 + joint_attention_dim = 7680 + + x_embedder_weight = converted_sd.get("x_embedder.weight") + if x_embedder_weight is not None: + in_channels = x_embedder_weight.shape[1] + else: + in_channels = 128 + + # Calculate num_attention_heads from hidden_size + # Klein 4B: hidden_size=3072, num_attention_heads=24 (3072/128=24) + # Klein 9B: hidden_size=4096, num_attention_heads=32 (4096/128=32) + attention_head_dim = 128 + num_attention_heads = hidden_size // attention_head_dim + + # Klein models don't have guidance embeddings - check if they're in the checkpoint + has_guidance = "time_guidance_embed.guidance_embedder.linear_1.weight" in converted_sd + + # Create model with detected configuration + with SilenceWarnings(): + with accelerate.init_empty_weights(): + model = Flux2Transformer2DModel( + in_channels=in_channels, + out_channels=in_channels, + num_layers=num_layers, + num_single_layers=num_single_layers, + attention_head_dim=attention_head_dim, + num_attention_heads=num_attention_heads, + joint_attention_dim=joint_attention_dim, + patch_size=1, + ) + + # If Klein model without guidance, initialize guidance embedder with zeros + if not has_guidance: + # Get the expected dimensions from timestep embedder (they should match) + timestep_linear1 = converted_sd.get("time_guidance_embed.timestep_embedder.linear_1.weight") + if timestep_linear1 is not None: + in_features = timestep_linear1.shape[1] + out_features = timestep_linear1.shape[0] + # Initialize guidance embedder with same shape as timestep embedder + converted_sd["time_guidance_embed.guidance_embedder.linear_1.weight"] = torch.zeros( + out_features, in_features, dtype=torch.bfloat16 + ) + timestep_linear2 = converted_sd.get("time_guidance_embed.timestep_embedder.linear_2.weight") + if timestep_linear2 is not None: + in_features2 = timestep_linear2.shape[1] + out_features2 = timestep_linear2.shape[0] + converted_sd["time_guidance_embed.guidance_embedder.linear_2.weight"] = torch.zeros( + out_features2, in_features2, dtype=torch.bfloat16 + ) + + # Convert to bfloat16 and load + for k in converted_sd.keys(): + converted_sd[k] = converted_sd[k].to(torch.bfloat16) + + # Load the state dict - guidance weights were already initialized above if missing + model.load_state_dict(converted_sd, assign=True) + + return model + + def _convert_flux2_bfl_to_diffusers(self, sd: dict) -> dict: + """Convert FLUX.2 BFL format state dict to diffusers format. + + Based on diffusers convert_flux2_to_diffusers.py key mappings. + """ + converted = {} + + # Basic key renames + key_renames = { + "img_in.weight": "x_embedder.weight", + "txt_in.weight": "context_embedder.weight", + "time_in.in_layer.weight": "time_guidance_embed.timestep_embedder.linear_1.weight", + "time_in.out_layer.weight": "time_guidance_embed.timestep_embedder.linear_2.weight", + "guidance_in.in_layer.weight": "time_guidance_embed.guidance_embedder.linear_1.weight", + "guidance_in.out_layer.weight": "time_guidance_embed.guidance_embedder.linear_2.weight", + "double_stream_modulation_img.lin.weight": "double_stream_modulation_img.linear.weight", + "double_stream_modulation_txt.lin.weight": "double_stream_modulation_txt.linear.weight", + "single_stream_modulation.lin.weight": "single_stream_modulation.linear.weight", + "final_layer.linear.weight": "proj_out.weight", + "final_layer.adaLN_modulation.1.weight": "norm_out.linear.weight", + } + + for old_key, tensor in sd.items(): + new_key = old_key + + # Apply basic renames + if old_key in key_renames: + new_key = key_renames[old_key] + # Apply scale-shift swap for adaLN modulation weights + # BFL and diffusers use different parameter ordering for AdaLayerNorm + if old_key == "final_layer.adaLN_modulation.1.weight": + tensor = self._swap_scale_shift(tensor) + converted[new_key] = tensor + continue + + # Convert double_blocks.X.* to transformer_blocks.X.* + if old_key.startswith("double_blocks."): + new_key = self._convert_double_block_key(old_key, tensor, converted) + if new_key is None: + continue # Key was handled specially + # Convert single_blocks.X.* to single_transformer_blocks.X.* + elif old_key.startswith("single_blocks."): + new_key = self._convert_single_block_key(old_key, tensor, converted) + if new_key is None: + continue # Key was handled specially + + if new_key != old_key or new_key not in converted: + converted[new_key] = tensor + + return converted + + def _convert_double_block_key(self, key: str, tensor: torch.Tensor, converted: dict) -> str | None: + """Convert double_blocks key to transformer_blocks format.""" + parts = key.split(".") + block_idx = parts[1] + rest = ".".join(parts[2:]) + + prefix = f"transformer_blocks.{block_idx}" + + # Attention QKV conversion - BFL uses fused qkv, diffusers uses separate + if "img_attn.qkv.weight" in rest: + # Split fused QKV into separate Q, K, V + # Defensive check: ensure tensor has at least 1 dimension and can be split into 3 + if tensor.dim() < 1 or tensor.shape[0] % 3 != 0: + # Skip malformed tensors (might be metadata or corrupted) + return key + q, k, v = tensor.chunk(3, dim=0) + converted[f"{prefix}.attn.to_q.weight"] = q + converted[f"{prefix}.attn.to_k.weight"] = k + converted[f"{prefix}.attn.to_v.weight"] = v + return None + elif "txt_attn.qkv.weight" in rest: + # Defensive check + if tensor.dim() < 1 or tensor.shape[0] % 3 != 0: + return key + q, k, v = tensor.chunk(3, dim=0) + converted[f"{prefix}.attn.add_q_proj.weight"] = q + converted[f"{prefix}.attn.add_k_proj.weight"] = k + converted[f"{prefix}.attn.add_v_proj.weight"] = v + return None + + # Attention output projection + if "img_attn.proj.weight" in rest: + return f"{prefix}.attn.to_out.0.weight" + elif "txt_attn.proj.weight" in rest: + return f"{prefix}.attn.to_add_out.weight" + + # Attention norms + if "img_attn.norm.query_norm.scale" in rest: + return f"{prefix}.attn.norm_q.weight" + elif "img_attn.norm.key_norm.scale" in rest: + return f"{prefix}.attn.norm_k.weight" + elif "txt_attn.norm.query_norm.scale" in rest: + return f"{prefix}.attn.norm_added_q.weight" + elif "txt_attn.norm.key_norm.scale" in rest: + return f"{prefix}.attn.norm_added_k.weight" + + # MLP layers + if "img_mlp.0.weight" in rest: + return f"{prefix}.ff.linear_in.weight" + elif "img_mlp.2.weight" in rest: + return f"{prefix}.ff.linear_out.weight" + elif "txt_mlp.0.weight" in rest: + return f"{prefix}.ff_context.linear_in.weight" + elif "txt_mlp.2.weight" in rest: + return f"{prefix}.ff_context.linear_out.weight" + + return key + + def _convert_single_block_key(self, key: str, tensor: torch.Tensor, converted: dict) -> str | None: + """Convert single_blocks key to single_transformer_blocks format.""" + parts = key.split(".") + block_idx = parts[1] + rest = ".".join(parts[2:]) + + prefix = f"single_transformer_blocks.{block_idx}" + + # linear1 is the fused QKV+MLP projection + if "linear1.weight" in rest: + return f"{prefix}.attn.to_qkv_mlp_proj.weight" + elif "linear2.weight" in rest: + return f"{prefix}.attn.to_out.weight" + + # Norms + if "norm.query_norm.scale" in rest: + return f"{prefix}.attn.norm_q.weight" + elif "norm.key_norm.scale" in rest: + return f"{prefix}.attn.norm_k.weight" + + return key + + def _swap_scale_shift(self, weight: torch.Tensor) -> torch.Tensor: + """Swap scale and shift in AdaLayerNorm weights. + + BFL and diffusers use different parameter ordering for AdaLayerNorm. + This function swaps the two halves of the weight tensor. + + Args: + weight: Weight tensor of shape (out_features,) or (out_features, in_features) + + Returns: + Weight tensor with scale and shift swapped. + """ + # Defensive check: ensure tensor can be split + if weight.dim() < 1 or weight.shape[0] % 2 != 0: + return weight + # Split in half along the first dimension and swap + shift, scale = weight.chunk(2, dim=0) + return torch.cat([scale, shift], dim=0) + + def _dequantize_fp8_weights(self, sd: dict) -> dict: + """Dequantize FP8 quantized weights in the state dict. + + ComfyUI and some FLUX.2 models store quantized weights as: + - layer.weight: quantized FP8 data + - layer.weight_scale: scale factor (FP32 scalar or per-channel) + + Dequantization formula: dequantized = weight.to(float) * weight_scale + + Also handles FP8 tensors stored with float8_e4m3fn dtype by converting to float. + """ + # Check for ComfyUI-style scale factors + weight_scale_keys = [k for k in sd.keys() if isinstance(k, str) and k.endswith(".weight_scale")] + + for scale_key in weight_scale_keys: + # Get the corresponding weight key + weight_key = scale_key.replace(".weight_scale", ".weight") + if weight_key in sd: + weight = sd[weight_key] + scale = sd[scale_key] + + # Dequantize: convert FP8 to float and multiply by scale + # Note: Float8 types require .float() instead of .to(torch.float32) + weight_float = weight.float() + scale = scale.float() + + # Handle block-wise quantization where scale may have different shape + if scale.dim() > 0 and scale.shape != weight_float.shape and scale.numel() > 1: + for dim in range(len(weight_float.shape)): + if dim < len(scale.shape) and scale.shape[dim] != weight_float.shape[dim]: + block_size = weight_float.shape[dim] // scale.shape[dim] + if block_size > 1: + scale = scale.repeat_interleave(block_size, dim=dim) + + sd[weight_key] = weight_float * scale + + # Filter out scale metadata keys and other FP8 metadata + keys_to_remove = [ + k + for k in sd.keys() + if isinstance(k, str) + and (k.endswith(".weight_scale") or k.endswith(".scale_weight") or "comfy_quant" in k or k == "scaled_fp8") + ] + for k in keys_to_remove: + del sd[k] + + # Handle native FP8 tensors (float8_e4m3fn dtype) that aren't already dequantized + # Also filter out 0-dimensional tensors (scalars) which are typically metadata + keys_to_convert = [] + keys_to_remove_scalars = [] + for key in list(sd.keys()): + tensor = sd[key] + if hasattr(tensor, "dim"): + if tensor.dim() == 0: + # 0-dimensional tensor (scalar) - likely metadata, remove it + keys_to_remove_scalars.append(key) + elif hasattr(tensor, "dtype") and "float8" in str(tensor.dtype): + # Native FP8 tensor - mark for conversion + keys_to_convert.append(key) + + for k in keys_to_remove_scalars: + del sd[k] + + for key in keys_to_convert: + # Convert FP8 tensor to float32 + sd[key] = sd[key].float() + + return sd + + +@ModelLoaderRegistry.register(base=BaseModelType.Flux2, type=ModelType.Main, format=ModelFormat.GGUFQuantized) +class Flux2GGUFCheckpointModel(ModelLoader): + """Class to load GGUF-quantized FLUX.2 transformer models.""" + + def _load_model( + self, + config: AnyModelConfig, + submodel_type: Optional[SubModelType] = None, + ) -> AnyModel: + if not isinstance(config, Main_GGUF_Flux2_Config): + raise ValueError("Only Main_GGUF_Flux2_Config models are currently supported here.") + + match submodel_type: + case SubModelType.Transformer: + return self._load_from_singlefile(config) + + raise ValueError( + f"Only Transformer submodels are currently supported. Received: {submodel_type.value if submodel_type else 'None'}" + ) + + def _load_from_singlefile( + self, + config: Main_GGUF_Flux2_Config, + ) -> AnyModel: + from diffusers import Flux2Transformer2DModel + + model_path = Path(config.path) + + # Load GGUF state dict + sd = gguf_sd_loader(model_path, compute_dtype=torch.bfloat16) + + # Check if keys have ComfyUI-style prefix and strip if needed + prefix_to_strip = None + for prefix in ["model.diffusion_model.", "diffusion_model."]: + if any(k.startswith(prefix) for k in sd.keys() if isinstance(k, str)): + prefix_to_strip = prefix + break + + if prefix_to_strip: + sd = { + (k[len(prefix_to_strip) :] if isinstance(k, str) and k.startswith(prefix_to_strip) else k): v + for k, v in sd.items() + } + + # Convert BFL format state dict to diffusers format + converted_sd = self._convert_flux2_bfl_to_diffusers(sd) + + # Detect architecture from checkpoint keys + double_block_indices = [ + int(k.split(".")[1]) + for k in converted_sd.keys() + if isinstance(k, str) and k.startswith("transformer_blocks.") + ] + single_block_indices = [ + int(k.split(".")[1]) + for k in converted_sd.keys() + if isinstance(k, str) and k.startswith("single_transformer_blocks.") + ] + + num_layers = max(double_block_indices) + 1 if double_block_indices else 5 + num_single_layers = max(single_block_indices) + 1 if single_block_indices else 20 + + # Get dimensions from weights + # context_embedder.weight shape: [hidden_size, joint_attention_dim] + context_embedder_weight = converted_sd.get("context_embedder.weight") + if context_embedder_weight is not None: + if hasattr(context_embedder_weight, "tensor_shape"): + hidden_size = context_embedder_weight.tensor_shape[0] + joint_attention_dim = context_embedder_weight.tensor_shape[1] + else: + hidden_size = context_embedder_weight.shape[0] + joint_attention_dim = context_embedder_weight.shape[1] + else: + # Default to Klein 4B dimensions + hidden_size = 3072 + joint_attention_dim = 7680 + + x_embedder_weight = converted_sd.get("x_embedder.weight") + if x_embedder_weight is not None: + in_channels = ( + x_embedder_weight.tensor_shape[1] + if hasattr(x_embedder_weight, "tensor_shape") + else x_embedder_weight.shape[1] + ) + else: + in_channels = 128 + + # Calculate num_attention_heads from hidden_size + # Klein 4B: hidden_size=3072, num_attention_heads=24 (3072/128=24) + # Klein 9B: hidden_size=4096, num_attention_heads=32 (4096/128=32) + attention_head_dim = 128 + num_attention_heads = hidden_size // attention_head_dim + + # Klein models don't have guidance embeddings - check if they're in the checkpoint + has_guidance = "time_guidance_embed.guidance_embedder.linear_1.weight" in converted_sd + + # Create model with detected configuration + with SilenceWarnings(): + with accelerate.init_empty_weights(): + model = Flux2Transformer2DModel( + in_channels=in_channels, + out_channels=in_channels, + num_layers=num_layers, + num_single_layers=num_single_layers, + attention_head_dim=attention_head_dim, + num_attention_heads=num_attention_heads, + joint_attention_dim=joint_attention_dim, + patch_size=1, + ) + + # If Klein model without guidance, initialize guidance embedder with zeros + if not has_guidance: + timestep_linear1 = converted_sd.get("time_guidance_embed.timestep_embedder.linear_1.weight") + if timestep_linear1 is not None: + in_features = ( + timestep_linear1.tensor_shape[1] + if hasattr(timestep_linear1, "tensor_shape") + else timestep_linear1.shape[1] + ) + out_features = ( + timestep_linear1.tensor_shape[0] + if hasattr(timestep_linear1, "tensor_shape") + else timestep_linear1.shape[0] + ) + converted_sd["time_guidance_embed.guidance_embedder.linear_1.weight"] = torch.zeros( + out_features, in_features, dtype=torch.bfloat16 + ) + timestep_linear2 = converted_sd.get("time_guidance_embed.timestep_embedder.linear_2.weight") + if timestep_linear2 is not None: + in_features2 = ( + timestep_linear2.tensor_shape[1] + if hasattr(timestep_linear2, "tensor_shape") + else timestep_linear2.shape[1] + ) + out_features2 = ( + timestep_linear2.tensor_shape[0] + if hasattr(timestep_linear2, "tensor_shape") + else timestep_linear2.shape[0] + ) + converted_sd["time_guidance_embed.guidance_embedder.linear_2.weight"] = torch.zeros( + out_features2, in_features2, dtype=torch.bfloat16 + ) + + model.load_state_dict(converted_sd, assign=True) + return model + + def _convert_flux2_bfl_to_diffusers(self, sd: dict) -> dict: + """Convert FLUX.2 BFL format state dict to diffusers format.""" + converted = {} + + key_renames = { + "img_in.weight": "x_embedder.weight", + "txt_in.weight": "context_embedder.weight", + "time_in.in_layer.weight": "time_guidance_embed.timestep_embedder.linear_1.weight", + "time_in.out_layer.weight": "time_guidance_embed.timestep_embedder.linear_2.weight", + "guidance_in.in_layer.weight": "time_guidance_embed.guidance_embedder.linear_1.weight", + "guidance_in.out_layer.weight": "time_guidance_embed.guidance_embedder.linear_2.weight", + "double_stream_modulation_img.lin.weight": "double_stream_modulation_img.linear.weight", + "double_stream_modulation_txt.lin.weight": "double_stream_modulation_txt.linear.weight", + "single_stream_modulation.lin.weight": "single_stream_modulation.linear.weight", + "final_layer.linear.weight": "proj_out.weight", + "final_layer.adaLN_modulation.1.weight": "norm_out.linear.weight", + } + + for old_key, tensor in sd.items(): + new_key = old_key + + if old_key in key_renames: + new_key = key_renames[old_key] + if old_key == "final_layer.adaLN_modulation.1.weight": + tensor = self._swap_scale_shift(tensor) + converted[new_key] = tensor + continue + + if old_key.startswith("double_blocks."): + new_key = self._convert_double_block_key(old_key, tensor, converted) + if new_key is None: + continue + elif old_key.startswith("single_blocks."): + new_key = self._convert_single_block_key(old_key, tensor, converted) + if new_key is None: + continue + + if new_key != old_key or new_key not in converted: + converted[new_key] = tensor + + return converted + + def _convert_double_block_key(self, key: str, tensor, converted: dict) -> str | None: + parts = key.split(".") + block_idx = parts[1] + rest = ".".join(parts[2:]) + prefix = f"transformer_blocks.{block_idx}" + + if "img_attn.qkv.weight" in rest: + q, k, v = self._chunk_tensor(tensor, 3) + converted[f"{prefix}.attn.to_q.weight"] = q + converted[f"{prefix}.attn.to_k.weight"] = k + converted[f"{prefix}.attn.to_v.weight"] = v + return None + elif "txt_attn.qkv.weight" in rest: + q, k, v = self._chunk_tensor(tensor, 3) + converted[f"{prefix}.attn.add_q_proj.weight"] = q + converted[f"{prefix}.attn.add_k_proj.weight"] = k + converted[f"{prefix}.attn.add_v_proj.weight"] = v + return None + + if "img_attn.proj.weight" in rest: + return f"{prefix}.attn.to_out.0.weight" + elif "txt_attn.proj.weight" in rest: + return f"{prefix}.attn.to_add_out.weight" + + if "img_attn.norm.query_norm.scale" in rest: + return f"{prefix}.attn.norm_q.weight" + elif "img_attn.norm.key_norm.scale" in rest: + return f"{prefix}.attn.norm_k.weight" + elif "txt_attn.norm.query_norm.scale" in rest: + return f"{prefix}.attn.norm_added_q.weight" + elif "txt_attn.norm.key_norm.scale" in rest: + return f"{prefix}.attn.norm_added_k.weight" + + if "img_mlp.0.weight" in rest: + return f"{prefix}.ff.linear_in.weight" + elif "img_mlp.2.weight" in rest: + return f"{prefix}.ff.linear_out.weight" + elif "txt_mlp.0.weight" in rest: + return f"{prefix}.ff_context.linear_in.weight" + elif "txt_mlp.2.weight" in rest: + return f"{prefix}.ff_context.linear_out.weight" + + return key + + def _convert_single_block_key(self, key: str, tensor, converted: dict) -> str | None: + parts = key.split(".") + block_idx = parts[1] + rest = ".".join(parts[2:]) + prefix = f"single_transformer_blocks.{block_idx}" + + if "linear1.weight" in rest: + return f"{prefix}.attn.to_qkv_mlp_proj.weight" + elif "linear2.weight" in rest: + return f"{prefix}.attn.to_out.weight" + + if "norm.query_norm.scale" in rest: + return f"{prefix}.attn.norm_q.weight" + elif "norm.key_norm.scale" in rest: + return f"{prefix}.attn.norm_k.weight" + + return key + + def _chunk_tensor(self, tensor, chunks: int): + """Chunk a tensor, handling both regular tensors and GGUF quantized tensors.""" + if hasattr(tensor, "get_dequantized_tensor"): + # GGUF quantized tensor - dequantize first, then chunk + # This loses quantization for the split weights, but is necessary + # because diffusers uses separate Q/K/V projections + tensor = tensor.get_dequantized_tensor() + return tensor.chunk(chunks, dim=0) + + def _swap_scale_shift(self, weight) -> torch.Tensor: + """Swap scale and shift in AdaLayerNorm weights.""" + if hasattr(weight, "get_dequantized_tensor"): + # For GGUF, dequantize first + weight = weight.get_dequantized_tensor() + shift, scale = weight.chunk(2, dim=0) + return torch.cat([scale, shift], dim=0) + + @ModelLoaderRegistry.register(base=BaseModelType.Flux, type=ModelType.ControlNet, format=ModelFormat.Checkpoint) @ModelLoaderRegistry.register(base=BaseModelType.Flux, type=ModelType.ControlNet, format=ModelFormat.Diffusers) class FluxControlnetModel(ModelLoader): diff --git a/invokeai/backend/model_manager/load/model_loaders/z_image.py b/invokeai/backend/model_manager/load/model_loaders/z_image.py index fefae4d5df..aadced8f56 100644 --- a/invokeai/backend/model_manager/load/model_loaders/z_image.py +++ b/invokeai/backend/model_manager/load/model_loaders/z_image.py @@ -576,7 +576,54 @@ class Qwen3EncoderCheckpointLoader(ModelLoader): # Load the state dict from safetensors file sd = load_file(model_path) - # Determine Qwen model configuration from state dict + # Handle ComfyUI quantized checkpoints + # ComfyUI stores quantized weights with accompanying scale factors: + # - layer.weight: quantized data (FP8) + # - layer.weight_scale: scale factor (FP32 scalar) + # Dequantization formula: dequantized = weight.to(dtype) * weight_scale + # Reference: https://github.com/Comfy-Org/ComfyUI/blob/master/QUANTIZATION.md + original_key_count = len(sd) + weight_scale_keys = [k for k in sd.keys() if k.endswith(".weight_scale")] + dequantized_count = 0 + + for scale_key in weight_scale_keys: + # Get the corresponding weight key (remove "_scale" suffix) + weight_key = scale_key.replace(".weight_scale", ".weight") + if weight_key in sd: + weight = sd[weight_key] + scale = sd[scale_key] + # Dequantize: convert to float and multiply by scale + # Handle block-wise quantization (e.g., FP4 with block_size=8) + # where scale has shape [weight_dim / block_size, ...] + # Note: Float8 types (e.g., float8_e4m3fn) require .float() instead of .to(torch.float32) + # as PyTorch doesn't support direct type promotion for Float8 types + weight_float = weight.float() + scale = scale.float() + if scale.shape != weight_float.shape and scale.numel() > 1: + # Block-wise quantization: need to expand scale to match weight shape + # Find which dimension differs and repeat scale along that dimension + for dim in range(len(weight_float.shape)): + if dim < len(scale.shape) and scale.shape[dim] != weight_float.shape[dim]: + block_size = weight_float.shape[dim] // scale.shape[dim] + if block_size > 1: + # Repeat scale along this dimension to match weight shape + scale = scale.repeat_interleave(block_size, dim=dim) + sd[weight_key] = weight_float * scale + dequantized_count += 1 + + if dequantized_count > 0: + logger.info(f"Dequantized {dequantized_count} ComfyUI quantized weights") + + # Filter out ComfyUI quantization metadata keys (comfy_quant, weight_scale) + # These are no longer needed after dequantization + comfy_metadata_keys = [k for k in sd.keys() if "comfy_quant" in k or "weight_scale" in k] + for k in comfy_metadata_keys: + del sd[k] + if comfy_metadata_keys: + logger.info(f"Filtered out {len(comfy_metadata_keys)} ComfyUI quantization metadata keys") + + logger.info(f"Loaded state dict with {len(sd)} keys (originally {original_key_count})") + # Count the number of layers by looking at layer keys layer_count = 0 for key in sd.keys(): @@ -589,34 +636,63 @@ class Qwen3EncoderCheckpointLoader(ModelLoader): except ValueError: pass - # Get hidden size from embed_tokens weight shape + # Get vocab size from embed_tokens weight shape embed_weight = sd.get("model.embed_tokens.weight") if embed_weight is None: raise ValueError("Could not find model.embed_tokens.weight in state dict") - if embed_weight.ndim != 2: - raise ValueError( - f"Expected 2D embed_tokens weight tensor, got shape {embed_weight.shape}. " - "The model file may be corrupted or incompatible." - ) - hidden_size = embed_weight.shape[1] + vocab_size = embed_weight.shape[0] + embed_hidden_size = embed_weight.shape[1] - # Detect attention configuration from layer 0 weights - q_proj_weight = sd.get("model.layers.0.self_attn.q_proj.weight") - k_proj_weight = sd.get("model.layers.0.self_attn.k_proj.weight") - gate_proj_weight = sd.get("model.layers.0.mlp.gate_proj.weight") + # Detect model variant based on embed_tokens hidden size and layer count + # FLUX 2 Klein / Z-Image uses Qwen3 configurations from ComfyUI: + # Reference: https://github.com/comfyanonymous/ComfyUI/blob/master/comfy/text_encoders/llama.py + # - Qwen3-4B: hidden_size=2560, 36 layers, 32 heads, 8 KV heads, intermediate=9728 + # - Qwen3-8B: hidden_size=4096, 36 layers, 32 heads, 8 KV heads, intermediate=12288 + if embed_hidden_size == 2560 and layer_count == 36: + # Qwen3-4B variant (FLUX 2 Klein / Z-Image) + logger.info("Detected Qwen3-4B variant (FLUX 2 Klein / Z-Image)") + hidden_size = 2560 + num_attention_heads = 32 + num_kv_heads = 8 + intermediate_size = 9728 + head_dim = 128 + max_position_embeddings = 40960 + elif embed_hidden_size == 4096 and layer_count == 36: + # Qwen3-8B variant + logger.info("Detected Qwen3-8B variant") + hidden_size = 4096 + num_attention_heads = 32 + num_kv_heads = 8 + intermediate_size = 12288 + head_dim = 128 + max_position_embeddings = 40960 + else: + # Unknown variant - try to detect from weights + logger.warning( + f"Unknown Qwen3 variant: embed_hidden_size={embed_hidden_size}, layers={layer_count}. " + "Attempting to detect configuration from weights..." + ) + q_proj_weight = sd.get("model.layers.0.self_attn.q_proj.weight") + k_proj_weight = sd.get("model.layers.0.self_attn.k_proj.weight") + gate_proj_weight = sd.get("model.layers.0.mlp.gate_proj.weight") - if q_proj_weight is None or k_proj_weight is None or gate_proj_weight is None: - raise ValueError("Could not find attention/mlp weights in state dict to determine configuration") + if q_proj_weight is None or k_proj_weight is None or gate_proj_weight is None: + raise ValueError("Could not find attention/mlp weights to determine configuration") - # Calculate dimensions from actual weights - # Qwen3 uses head_dim separately from hidden_size - head_dim = 128 # Standard head dimension for Qwen3 models - num_attention_heads = q_proj_weight.shape[0] // head_dim - num_kv_heads = k_proj_weight.shape[0] // head_dim - intermediate_size = gate_proj_weight.shape[0] + hidden_size = embed_hidden_size + head_dim = 128 + num_attention_heads = q_proj_weight.shape[0] // head_dim + num_kv_heads = k_proj_weight.shape[0] // head_dim + intermediate_size = gate_proj_weight.shape[0] + max_position_embeddings = 40960 - # Create Qwen3 config - matches the diffusers text_encoder/config.json + logger.info( + f"Qwen3 config: hidden_size={hidden_size}, layers={layer_count}, " + f"heads={num_attention_heads}, kv_heads={num_kv_heads}, intermediate={intermediate_size}" + ) + + # Create Qwen3 config qwen_config = Qwen3Config( vocab_size=vocab_size, hidden_size=hidden_size, @@ -625,7 +701,7 @@ class Qwen3EncoderCheckpointLoader(ModelLoader): num_attention_heads=num_attention_heads, num_key_value_heads=num_kv_heads, head_dim=head_dim, - max_position_embeddings=40960, + max_position_embeddings=max_position_embeddings, rms_norm_eps=1e-6, tie_word_embeddings=True, rope_theta=1000000.0, @@ -771,7 +847,7 @@ class Qwen3EncoderGGUFLoader(ModelLoader): except ValueError: pass - # Get hidden size from embed_tokens weight shape + # Get vocab size from embed_tokens weight shape embed_weight = sd.get("model.embed_tokens.weight") if embed_weight is None: raise ValueError("Could not find model.embed_tokens.weight in state dict") @@ -783,13 +859,23 @@ class Qwen3EncoderGGUFLoader(ModelLoader): f"Expected 2D embed_tokens weight tensor, got shape {embed_shape}. " "The model file may be corrupted or incompatible." ) - hidden_size = embed_shape[1] vocab_size = embed_shape[0] - # Detect attention configuration from layer 0 weights - q_proj_weight = sd.get("model.layers.0.self_attn.q_proj.weight") - k_proj_weight = sd.get("model.layers.0.self_attn.k_proj.weight") - gate_proj_weight = sd.get("model.layers.0.mlp.gate_proj.weight") + # Detect attention configuration from layer weights + # IMPORTANT: Use layer 1 (not layer 0) because some models like FLUX 2 Klein have a special + # first layer with different dimensions (input projection layer) while the rest of the + # transformer layers have a different hidden_size. Using a middle layer ensures we get + # the representative hidden_size for the bulk of the model. + # Fall back to layer 0 if layer 1 doesn't exist. + q_proj_weight = sd.get("model.layers.1.self_attn.q_proj.weight") + k_proj_weight = sd.get("model.layers.1.self_attn.k_proj.weight") + gate_proj_weight = sd.get("model.layers.1.mlp.gate_proj.weight") + + # Fall back to layer 0 if layer 1 doesn't exist (single-layer model edge case) + if q_proj_weight is None: + q_proj_weight = sd.get("model.layers.0.self_attn.q_proj.weight") + k_proj_weight = sd.get("model.layers.0.self_attn.k_proj.weight") + gate_proj_weight = sd.get("model.layers.0.mlp.gate_proj.weight") if q_proj_weight is None or k_proj_weight is None or gate_proj_weight is None: raise ValueError("Could not find attention/mlp weights in state dict to determine configuration") @@ -800,7 +886,14 @@ class Qwen3EncoderGGUFLoader(ModelLoader): gate_shape = gate_proj_weight.shape if hasattr(gate_proj_weight, "shape") else gate_proj_weight.tensor_shape # Calculate dimensions from actual weights + # IMPORTANT: Use hidden_size from k_proj input dimension (not q_proj or embed_tokens). + # Some models (like FLUX 2 Klein) have unusual architectures where: + # - embed_tokens has a larger dimension (e.g., 2560) + # - q_proj may have a larger input dimension for query expansion + # - k_proj/v_proj have the actual transformer hidden_size (e.g., 1280) + # Using k_proj ensures we get the correct internal hidden_size. head_dim = 128 # Standard head dimension for Qwen3 models + hidden_size = k_shape[1] # Use k_proj input dim as the hidden_size num_attention_heads = q_shape[0] // head_dim num_kv_heads = k_shape[0] // head_dim intermediate_size = gate_shape[0] diff --git a/invokeai/backend/model_manager/starter_models.py b/invokeai/backend/model_manager/starter_models.py index 89d9666e83..ef7cd80cd2 100644 --- a/invokeai/backend/model_manager/starter_models.py +++ b/invokeai/backend/model_manager/starter_models.py @@ -690,6 +690,115 @@ flux_fill = StarterModel( ) # endregion +# region FLUX.2 Klein +flux2_vae = StarterModel( + name="FLUX.2 VAE", + base=BaseModelType.Flux2, + source="black-forest-labs/FLUX.2-klein-4B::vae", + description="FLUX.2 VAE (16-channel, same architecture as FLUX.1 VAE). ~335MB", + type=ModelType.VAE, +) + +flux2_klein_qwen3_4b_encoder = StarterModel( + name="FLUX.2 Klein Qwen3 4B Encoder", + base=BaseModelType.Any, + source="black-forest-labs/FLUX.2-klein-4B::text_encoder+tokenizer", + description="Qwen3 4B text encoder for FLUX.2 Klein 4B (also compatible with Z-Image). ~8GB", + type=ModelType.Qwen3Encoder, +) + +flux2_klein_qwen3_8b_encoder = StarterModel( + name="FLUX.2 Klein Qwen3 8B Encoder", + base=BaseModelType.Any, + source="black-forest-labs/FLUX.2-klein-9B::text_encoder+tokenizer", + description="Qwen3 8B text encoder for FLUX.2 Klein 9B models. ~16GB", + type=ModelType.Qwen3Encoder, +) + +flux2_klein_4b = StarterModel( + name="FLUX.2 Klein 4B (Diffusers)", + base=BaseModelType.Flux2, + source="black-forest-labs/FLUX.2-klein-4B", + description="FLUX.2 Klein 4B in Diffusers format - includes transformer, VAE and Qwen3 encoder. ~10GB", + type=ModelType.Main, +) + +flux2_klein_4b_single = StarterModel( + name="FLUX.2 Klein 4B", + base=BaseModelType.Flux2, + source="https://huggingface.co/black-forest-labs/FLUX.2-klein-4B/resolve/main/flux-2-klein-4b.safetensors", + description="FLUX.2 Klein 4B standalone transformer. Installs with VAE and Qwen3 4B encoder. ~8GB", + type=ModelType.Main, + dependencies=[flux2_vae, flux2_klein_qwen3_4b_encoder], +) + +flux2_klein_4b_fp8 = StarterModel( + name="FLUX.2 Klein 4B (FP8)", + base=BaseModelType.Flux2, + source="https://huggingface.co/black-forest-labs/FLUX.2-klein-4b-fp8/resolve/main/flux-2-klein-4b-fp8.safetensors", + description="FLUX.2 Klein 4B FP8 quantized - smaller and faster. Installs with VAE and Qwen3 4B encoder. ~4GB", + type=ModelType.Main, + dependencies=[flux2_vae, flux2_klein_qwen3_4b_encoder], +) + +flux2_klein_9b = StarterModel( + name="FLUX.2 Klein 9B (Diffusers)", + base=BaseModelType.Flux2, + source="black-forest-labs/FLUX.2-klein-9B", + description="FLUX.2 Klein 9B in Diffusers format - includes transformer, VAE and Qwen3 encoder. ~20GB", + type=ModelType.Main, +) + +flux2_klein_9b_fp8 = StarterModel( + name="FLUX.2 Klein 9B (FP8)", + base=BaseModelType.Flux2, + source="https://huggingface.co/black-forest-labs/FLUX.2-klein-9b-fp8/resolve/main/flux-2-klein-9b-fp8.safetensors", + description="FLUX.2 Klein 9B FP8 quantized - more efficient than full precision. Installs with VAE and Qwen3 8B encoder. ~9.5GB", + type=ModelType.Main, + dependencies=[flux2_vae, flux2_klein_qwen3_8b_encoder], +) + +flux2_klein_4b_gguf_q4 = StarterModel( + name="FLUX.2 Klein 4B (GGUF Q4)", + base=BaseModelType.Flux2, + source="https://huggingface.co/unsloth/FLUX.2-klein-4B-GGUF/resolve/main/flux-2-klein-4b-Q4_K_M.gguf", + description="FLUX.2 Klein 4B GGUF Q4_K_M quantized - runs on 6-8GB VRAM. Installs with VAE and Qwen3 4B encoder. ~2.6GB", + type=ModelType.Main, + format=ModelFormat.GGUFQuantized, + dependencies=[flux2_vae, flux2_klein_qwen3_4b_encoder], +) + +flux2_klein_4b_gguf_q8 = StarterModel( + name="FLUX.2 Klein 4B (GGUF Q8)", + base=BaseModelType.Flux2, + source="https://huggingface.co/unsloth/FLUX.2-klein-4B-GGUF/resolve/main/flux-2-klein-4b-Q8_0.gguf", + description="FLUX.2 Klein 4B GGUF Q8_0 quantized - higher quality than Q4. Installs with VAE and Qwen3 4B encoder. ~4.3GB", + type=ModelType.Main, + format=ModelFormat.GGUFQuantized, + dependencies=[flux2_vae, flux2_klein_qwen3_4b_encoder], +) + +flux2_klein_9b_gguf_q4 = StarterModel( + name="FLUX.2 Klein 9B (GGUF Q4)", + base=BaseModelType.Flux2, + source="https://huggingface.co/unsloth/FLUX.2-klein-9B-GGUF/resolve/main/flux-2-klein-9b-Q4_K_M.gguf", + description="FLUX.2 Klein 9B GGUF Q4_K_M quantized - runs on 12GB+ VRAM. Installs with VAE and Qwen3 8B encoder. ~5.8GB", + type=ModelType.Main, + format=ModelFormat.GGUFQuantized, + dependencies=[flux2_vae, flux2_klein_qwen3_8b_encoder], +) + +flux2_klein_9b_gguf_q8 = StarterModel( + name="FLUX.2 Klein 9B (GGUF Q8)", + base=BaseModelType.Flux2, + source="https://huggingface.co/unsloth/FLUX.2-klein-9B-GGUF/resolve/main/flux-2-klein-9b-Q8_0.gguf", + description="FLUX.2 Klein 9B GGUF Q8_0 quantized - higher quality than Q4. Installs with VAE and Qwen3 8B encoder. ~10GB", + type=ModelType.Main, + format=ModelFormat.GGUFQuantized, + dependencies=[flux2_vae, flux2_klein_qwen3_8b_encoder], +) +# endregion + # region Z-Image z_image_qwen3_encoder = StarterModel( name="Z-Image Qwen3 Text Encoder", @@ -826,6 +935,18 @@ STARTER_MODELS: list[StarterModel] = [ flux_redux, llava_onevision, flux_fill, + flux2_vae, + flux2_klein_4b, + flux2_klein_4b_single, + flux2_klein_4b_fp8, + flux2_klein_9b, + flux2_klein_9b_fp8, + flux2_klein_4b_gguf_q4, + flux2_klein_4b_gguf_q8, + flux2_klein_9b_gguf_q4, + flux2_klein_9b_gguf_q8, + flux2_klein_qwen3_4b_encoder, + flux2_klein_qwen3_8b_encoder, cogview4, flux_krea, flux_krea_quantized, @@ -898,10 +1019,17 @@ zimage_bundle: list[StarterModel] = [ flux_vae, ] +flux2_klein_bundle: list[StarterModel] = [ + flux2_klein_4b_gguf_q4, + flux2_vae, + flux2_klein_qwen3_4b_encoder, +] + STARTER_BUNDLES: dict[str, StarterModelBundle] = { BaseModelType.StableDiffusion1: StarterModelBundle(name="Stable Diffusion 1.5", models=sd1_bundle), BaseModelType.StableDiffusionXL: StarterModelBundle(name="SDXL", models=sdxl_bundle), BaseModelType.Flux: StarterModelBundle(name="FLUX.1 dev", models=flux_bundle), + BaseModelType.Flux2: StarterModelBundle(name="FLUX.2 Klein", models=flux2_klein_bundle), BaseModelType.ZImage: StarterModelBundle(name="Z-Image Turbo", models=zimage_bundle), } diff --git a/invokeai/backend/model_manager/taxonomy.py b/invokeai/backend/model_manager/taxonomy.py index bc7e11367a..aa0660152a 100644 --- a/invokeai/backend/model_manager/taxonomy.py +++ b/invokeai/backend/model_manager/taxonomy.py @@ -46,6 +46,8 @@ class BaseModelType(str, Enum): """Indicates the model is associated with the Stable Diffusion XL Refiner model architecture.""" Flux = "flux" """Indicates the model is associated with FLUX.1 model architecture, including FLUX Dev, Schnell and Fill.""" + Flux2 = "flux2" + """Indicates the model is associated with FLUX.2 model architecture, including FLUX2 Klein.""" CogView4 = "cogview4" """Indicates the model is associated with CogView 4 model architecture.""" ZImage = "z-image" @@ -111,11 +113,36 @@ class ModelVariantType(str, Enum): class FluxVariantType(str, Enum): + """FLUX.1 model variants.""" + Schnell = "schnell" Dev = "dev" DevFill = "dev_fill" +class Flux2VariantType(str, Enum): + """FLUX.2 model variants.""" + + Klein4B = "klein_4b" + """Flux2 Klein 4B variant using Qwen3 4B text encoder.""" + + Klein9B = "klein_9b" + """Flux2 Klein 9B variant using Qwen3 8B text encoder (distilled).""" + + Klein9BBase = "klein_9b_base" + """Flux2 Klein 9B Base variant - undistilled foundation model using Qwen3 8B text encoder.""" + + +class Qwen3VariantType(str, Enum): + """Qwen3 text encoder variants based on model size.""" + + Qwen3_4B = "qwen3_4b" + """Qwen3 4B text encoder (hidden_size=2560). Used by FLUX.2 Klein 4B and Z-Image.""" + + Qwen3_8B = "qwen3_8b" + """Qwen3 8B text encoder (hidden_size=4096). Used by FLUX.2 Klein 9B.""" + + class ModelFormat(str, Enum): """Storage format of model.""" @@ -174,7 +201,7 @@ class FluxLoRAFormat(str, Enum): XLabs = "flux.xlabs" -AnyVariant: TypeAlias = Union[ModelVariantType, ClipVariantType, FluxVariantType] -variant_type_adapter = TypeAdapter[ModelVariantType | ClipVariantType | FluxVariantType]( - ModelVariantType | ClipVariantType | FluxVariantType -) +AnyVariant: TypeAlias = Union[ModelVariantType, ClipVariantType, FluxVariantType, Flux2VariantType, Qwen3VariantType] +variant_type_adapter = TypeAdapter[ + ModelVariantType | ClipVariantType | FluxVariantType | Flux2VariantType | Qwen3VariantType +](ModelVariantType | ClipVariantType | FluxVariantType | Flux2VariantType | Qwen3VariantType) diff --git a/invokeai/backend/model_manager/util/select_hf_files.py b/invokeai/backend/model_manager/util/select_hf_files.py index 5bfb2f1f29..a8428f4edc 100644 --- a/invokeai/backend/model_manager/util/select_hf_files.py +++ b/invokeai/backend/model_manager/util/select_hf_files.py @@ -60,7 +60,7 @@ def filter_files( # Start by filtering on model file extensions, discarding images, docs, etc for file in files: - if file.name.endswith((".json", ".txt")): + if file.name.endswith((".json", ".txt", ".jinja")): # .jinja for chat templates paths.append(file) elif file.name.endswith( ( @@ -116,7 +116,8 @@ def _filter_by_variant(files: List[Path], variant: ModelRepoVariant) -> Set[Path # Note: '.model' was added to support: # https://huggingface.co/black-forest-labs/FLUX.1-schnell/blob/768d12a373ed5cc9ef9a9dea7504dc09fcc14842/tokenizer_2/spiece.model - elif path.suffix in [".json", ".txt", ".model"]: + # Note: '.jinja' was added to support chat templates for FLUX.2 Klein models + elif path.suffix in [".json", ".txt", ".model", ".jinja"]: result.add(path) elif variant in [ diff --git a/invokeai/frontend/web/openapi.json b/invokeai/frontend/web/openapi.json index 1be662f85e..7cc210b531 100644 --- a/invokeai/frontend/web/openapi.json +++ b/invokeai/frontend/web/openapi.json @@ -214,6 +214,12 @@ { "$ref": "#/components/schemas/Main_Diffusers_SD3_Config" }, + { + "$ref": "#/components/schemas/Main_Diffusers_FLUX_Config" + }, + { + "$ref": "#/components/schemas/Main_Diffusers_Flux2_Config" + }, { "$ref": "#/components/schemas/Main_Diffusers_CogView4_Config" }, @@ -235,6 +241,12 @@ { "$ref": "#/components/schemas/Main_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/Main_Checkpoint_Flux2_Config" + }, + { + "$ref": "#/components/schemas/Main_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/Main_BnBNF4_FLUX_Config" }, @@ -256,6 +268,9 @@ { "$ref": "#/components/schemas/VAE_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/VAE_Checkpoint_Flux2_Config" + }, { "$ref": "#/components/schemas/VAE_Diffusers_SD1_Config" }, @@ -274,6 +289,9 @@ { "$ref": "#/components/schemas/ControlNet_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/ControlNet_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/ControlNet_Diffusers_SD1_Config" }, @@ -334,6 +352,12 @@ { "$ref": "#/components/schemas/Qwen3Encoder_Qwen3Encoder_Config" }, + { + "$ref": "#/components/schemas/Qwen3Encoder_Checkpoint_Config" + }, + { + "$ref": "#/components/schemas/Qwen3Encoder_GGUF_Config" + }, { "$ref": "#/components/schemas/TI_File_SD1_Config" }, @@ -463,6 +487,12 @@ { "$ref": "#/components/schemas/Main_Diffusers_SD3_Config" }, + { + "$ref": "#/components/schemas/Main_Diffusers_FLUX_Config" + }, + { + "$ref": "#/components/schemas/Main_Diffusers_Flux2_Config" + }, { "$ref": "#/components/schemas/Main_Diffusers_CogView4_Config" }, @@ -484,6 +514,12 @@ { "$ref": "#/components/schemas/Main_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/Main_Checkpoint_Flux2_Config" + }, + { + "$ref": "#/components/schemas/Main_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/Main_BnBNF4_FLUX_Config" }, @@ -505,6 +541,9 @@ { "$ref": "#/components/schemas/VAE_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/VAE_Checkpoint_Flux2_Config" + }, { "$ref": "#/components/schemas/VAE_Diffusers_SD1_Config" }, @@ -523,6 +562,9 @@ { "$ref": "#/components/schemas/ControlNet_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/ControlNet_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/ControlNet_Diffusers_SD1_Config" }, @@ -583,6 +625,12 @@ { "$ref": "#/components/schemas/Qwen3Encoder_Qwen3Encoder_Config" }, + { + "$ref": "#/components/schemas/Qwen3Encoder_Checkpoint_Config" + }, + { + "$ref": "#/components/schemas/Qwen3Encoder_GGUF_Config" + }, { "$ref": "#/components/schemas/TI_File_SD1_Config" }, @@ -757,6 +805,12 @@ { "$ref": "#/components/schemas/Main_Diffusers_SD3_Config" }, + { + "$ref": "#/components/schemas/Main_Diffusers_FLUX_Config" + }, + { + "$ref": "#/components/schemas/Main_Diffusers_Flux2_Config" + }, { "$ref": "#/components/schemas/Main_Diffusers_CogView4_Config" }, @@ -778,6 +832,12 @@ { "$ref": "#/components/schemas/Main_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/Main_Checkpoint_Flux2_Config" + }, + { + "$ref": "#/components/schemas/Main_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/Main_BnBNF4_FLUX_Config" }, @@ -799,6 +859,9 @@ { "$ref": "#/components/schemas/VAE_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/VAE_Checkpoint_Flux2_Config" + }, { "$ref": "#/components/schemas/VAE_Diffusers_SD1_Config" }, @@ -817,6 +880,9 @@ { "$ref": "#/components/schemas/ControlNet_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/ControlNet_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/ControlNet_Diffusers_SD1_Config" }, @@ -877,6 +943,12 @@ { "$ref": "#/components/schemas/Qwen3Encoder_Qwen3Encoder_Config" }, + { + "$ref": "#/components/schemas/Qwen3Encoder_Checkpoint_Config" + }, + { + "$ref": "#/components/schemas/Qwen3Encoder_GGUF_Config" + }, { "$ref": "#/components/schemas/TI_File_SD1_Config" }, @@ -1070,6 +1142,12 @@ { "$ref": "#/components/schemas/Main_Diffusers_SD3_Config" }, + { + "$ref": "#/components/schemas/Main_Diffusers_FLUX_Config" + }, + { + "$ref": "#/components/schemas/Main_Diffusers_Flux2_Config" + }, { "$ref": "#/components/schemas/Main_Diffusers_CogView4_Config" }, @@ -1091,6 +1169,12 @@ { "$ref": "#/components/schemas/Main_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/Main_Checkpoint_Flux2_Config" + }, + { + "$ref": "#/components/schemas/Main_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/Main_BnBNF4_FLUX_Config" }, @@ -1112,6 +1196,9 @@ { "$ref": "#/components/schemas/VAE_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/VAE_Checkpoint_Flux2_Config" + }, { "$ref": "#/components/schemas/VAE_Diffusers_SD1_Config" }, @@ -1130,6 +1217,9 @@ { "$ref": "#/components/schemas/ControlNet_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/ControlNet_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/ControlNet_Diffusers_SD1_Config" }, @@ -1190,6 +1280,12 @@ { "$ref": "#/components/schemas/Qwen3Encoder_Qwen3Encoder_Config" }, + { + "$ref": "#/components/schemas/Qwen3Encoder_Checkpoint_Config" + }, + { + "$ref": "#/components/schemas/Qwen3Encoder_GGUF_Config" + }, { "$ref": "#/components/schemas/TI_File_SD1_Config" }, @@ -1530,6 +1626,47 @@ } } }, + "/api/v2/models/i/bulk_delete": { + "post": { + "tags": ["model_manager"], + "summary": "Bulk Delete Models", + "description": "Delete multiple model records from database.\n\nThe configuration records will be removed. The corresponding weights files will be\ndeleted as well if they reside within the InvokeAI \"models\" directory.\nReturns a list of successfully deleted keys and failed deletions with error messages.", + "operationId": "bulk_delete_models", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkDeleteModelsRequest", + "description": "List of model keys to delete" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Models deleted (possibly with some failures)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkDeleteModelsResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, "/api/v2/models/install": { "post": { "tags": ["model_manager"], @@ -1858,6 +1995,12 @@ { "$ref": "#/components/schemas/Main_Diffusers_SD3_Config" }, + { + "$ref": "#/components/schemas/Main_Diffusers_FLUX_Config" + }, + { + "$ref": "#/components/schemas/Main_Diffusers_Flux2_Config" + }, { "$ref": "#/components/schemas/Main_Diffusers_CogView4_Config" }, @@ -1879,6 +2022,12 @@ { "$ref": "#/components/schemas/Main_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/Main_Checkpoint_Flux2_Config" + }, + { + "$ref": "#/components/schemas/Main_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/Main_BnBNF4_FLUX_Config" }, @@ -1900,6 +2049,9 @@ { "$ref": "#/components/schemas/VAE_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/VAE_Checkpoint_Flux2_Config" + }, { "$ref": "#/components/schemas/VAE_Diffusers_SD1_Config" }, @@ -1918,6 +2070,9 @@ { "$ref": "#/components/schemas/ControlNet_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/ControlNet_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/ControlNet_Diffusers_SD1_Config" }, @@ -1978,6 +2133,12 @@ { "$ref": "#/components/schemas/Qwen3Encoder_Qwen3Encoder_Config" }, + { + "$ref": "#/components/schemas/Qwen3Encoder_Checkpoint_Config" + }, + { + "$ref": "#/components/schemas/Qwen3Encoder_GGUF_Config" + }, { "$ref": "#/components/schemas/TI_File_SD1_Config" }, @@ -6157,6 +6318,63 @@ } } }, + "/api/v1/workflows/tags": { + "get": { + "tags": ["workflows"], + "summary": "Get All Tags", + "description": "Gets all unique tags from workflows", + "operationId": "get_all_tags", + "parameters": [ + { + "name": "categories", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/components/schemas/WorkflowCategory" + } + }, + { + "type": "null" + } + ], + "description": "The categories to include", + "title": "Categories" + }, + "description": "The categories to include" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Response Get All Tags" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, "/api/v1/workflows/counts_by_tag": { "get": { "tags": ["workflows"], @@ -7009,6 +7227,12 @@ { "$ref": "#/components/schemas/Main_Diffusers_SD3_Config" }, + { + "$ref": "#/components/schemas/Main_Diffusers_FLUX_Config" + }, + { + "$ref": "#/components/schemas/Main_Diffusers_Flux2_Config" + }, { "$ref": "#/components/schemas/Main_Diffusers_CogView4_Config" }, @@ -7030,6 +7254,12 @@ { "$ref": "#/components/schemas/Main_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/Main_Checkpoint_Flux2_Config" + }, + { + "$ref": "#/components/schemas/Main_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/Main_BnBNF4_FLUX_Config" }, @@ -7051,6 +7281,9 @@ { "$ref": "#/components/schemas/VAE_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/VAE_Checkpoint_Flux2_Config" + }, { "$ref": "#/components/schemas/VAE_Diffusers_SD1_Config" }, @@ -7069,6 +7302,9 @@ { "$ref": "#/components/schemas/ControlNet_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/ControlNet_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/ControlNet_Diffusers_SD1_Config" }, @@ -7129,6 +7365,12 @@ { "$ref": "#/components/schemas/Qwen3Encoder_Qwen3Encoder_Config" }, + { + "$ref": "#/components/schemas/Qwen3Encoder_Checkpoint_Config" + }, + { + "$ref": "#/components/schemas/Qwen3Encoder_GGUF_Config" + }, { "$ref": "#/components/schemas/TI_File_SD1_Config" }, @@ -7474,7 +7716,19 @@ }, "BaseModelType": { "type": "string", - "enum": ["any", "sd-1", "sd-2", "sd-3", "sdxl", "sdxl-refiner", "flux", "cogview4", "z-image", "unknown"], + "enum": [ + "any", + "sd-1", + "sd-2", + "sd-3", + "sdxl", + "sdxl-refiner", + "flux", + "flux2", + "cogview4", + "z-image", + "unknown" + ], "title": "BaseModelType", "description": "An enumeration of base model architectures. For example, Stable Diffusion 1.x, Stable Diffusion 2.x, FLUX, etc.\n\nEvery model config must have a base architecture type.\n\nNot all models are associated with a base architecture. For example, CLIP models are their own thing, not related\nto any particular model architecture. To simplify internal APIs and make it easier to work with models, we use a\nfallback/null value `BaseModelType.Any` for these models, instead of making the model base optional." }, @@ -8933,6 +9187,47 @@ "title": "BoundingBoxOutput", "type": "object" }, + "BulkDeleteModelsRequest": { + "properties": { + "keys": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Keys", + "description": "List of model keys to delete" + } + }, + "type": "object", + "required": ["keys"], + "title": "BulkDeleteModelsRequest", + "description": "Request body for bulk model deletion." + }, + "BulkDeleteModelsResponse": { + "properties": { + "deleted": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Deleted", + "description": "List of successfully deleted model keys" + }, + "failed": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array", + "title": "Failed", + "description": "List of failed deletions with error messages" + } + }, + "type": "object", + "required": ["deleted", "failed"], + "title": "BulkDeleteModelsResponse", + "description": "Response body for bulk model deletion." + }, "BulkDownloadCompleteEvent": { "description": "Event model for bulk_download_complete", "properties": { @@ -13119,6 +13414,140 @@ ], "title": "ControlNet_Checkpoint_SDXL_Config" }, + "ControlNet_Checkpoint_ZImage_Config": { + "properties": { + "key": { + "type": "string", + "title": "Key", + "description": "A unique key for this model." + }, + "hash": { + "type": "string", + "title": "Hash", + "description": "The hash of the model file(s)." + }, + "path": { + "type": "string", + "title": "Path", + "description": "Path to the model on the filesystem. Relative paths are relative to the Invoke root directory." + }, + "file_size": { + "type": "integer", + "title": "File Size", + "description": "The size of the model in bytes." + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the model." + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description", + "description": "Model description" + }, + "source": { + "type": "string", + "title": "Source", + "description": "The original source of the model (path, URL or repo_id)." + }, + "source_type": { + "$ref": "#/components/schemas/ModelSourceType", + "description": "The type of source" + }, + "source_api_response": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Api Response", + "description": "The original API response from the source, as stringified JSON." + }, + "cover_image": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cover Image", + "description": "Url for image to preview model" + }, + "config_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Config Path", + "description": "Path to the config for this model, if any." + }, + "type": { + "type": "string", + "const": "controlnet", + "title": "Type", + "default": "controlnet" + }, + "format": { + "type": "string", + "const": "checkpoint", + "title": "Format", + "default": "checkpoint" + }, + "base": { + "type": "string", + "const": "z-image", + "title": "Base", + "default": "z-image" + }, + "default_settings": { + "anyOf": [ + { + "$ref": "#/components/schemas/ControlAdapterDefaultSettings" + }, + { + "type": "null" + } + ] + } + }, + "type": "object", + "required": [ + "key", + "hash", + "path", + "file_size", + "name", + "description", + "source", + "source_type", + "source_api_response", + "cover_image", + "config_path", + "type", + "format", + "base", + "default_settings" + ], + "title": "ControlNet_Checkpoint_ZImage_Config", + "description": "Model config for Z-Image Control adapter models (Safetensors checkpoint).\n\nZ-Image Control models are standalone adapters containing only the control layers\n(control_layers, control_all_x_embedder, control_noise_refiner) that extend\nthe base Z-Image transformer with spatial conditioning capabilities.\n\nSupports: Canny, HED, Depth, Pose, MLSD.\nRecommended control_context_scale: 0.65-0.80." + }, "ControlNet_Diffusers_FLUX_Config": { "properties": { "key": { @@ -13689,6 +14118,7 @@ "flux_img2img", "flux_inpaint", "flux_outpaint", + "flux2_txt2img", "sd3_txt2img", "sd3_img2img", "sd3_inpaint", @@ -14083,6 +14513,22 @@ "orig_default": null, "orig_required": false }, + "qwen3_encoder": { + "anyOf": [ + { + "$ref": "#/components/schemas/ModelIdentifierField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The Qwen3 text encoder model used for Z-Image inference", + "field_kind": "input", + "input": "any", + "orig_default": null, + "orig_required": false + }, "hrf_enabled": { "anyOf": [ { @@ -14298,7 +14744,7 @@ "tags": ["metadata"], "title": "Core Metadata", "type": "object", - "version": "2.0.0", + "version": "2.1.0", "output": { "$ref": "#/components/schemas/MetadataOutput" } @@ -18113,6 +18559,645 @@ "$ref": "#/components/schemas/IntegerOutput" } }, + "Flux2DenoiseInvocation": { + "category": "image", + "class": "invocation", + "classification": "prototype", + "description": "Run denoising process with a FLUX.2 Klein transformer model.\n\nThis node is designed for FLUX.2 Klein models which use Qwen3 as the text encoder.\nIt does not support ControlNet, IP-Adapters, or regional prompting.", + "node_pack": "invokeai", + "properties": { + "id": { + "description": "The id of this instance of an invocation. Must be unique among all instances of invocations.", + "field_kind": "node_attribute", + "title": "Id", + "type": "string" + }, + "is_intermediate": { + "default": false, + "description": "Whether or not this is an intermediate invocation.", + "field_kind": "node_attribute", + "input": "direct", + "orig_required": true, + "title": "Is Intermediate", + "type": "boolean", + "ui_hidden": false, + "ui_type": "IsIntermediate" + }, + "use_cache": { + "default": true, + "description": "Whether or not to use the cache", + "field_kind": "node_attribute", + "title": "Use Cache", + "type": "boolean" + }, + "latents": { + "anyOf": [ + { + "$ref": "#/components/schemas/LatentsField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Latents tensor", + "field_kind": "input", + "input": "connection", + "orig_default": null, + "orig_required": false + }, + "denoise_mask": { + "anyOf": [ + { + "$ref": "#/components/schemas/DenoiseMaskField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "A mask of the region to apply the denoising process to. Values of 0.0 represent the regions to be fully denoised, and 1.0 represent the regions to be preserved.", + "field_kind": "input", + "input": "connection", + "orig_default": null, + "orig_required": false + }, + "denoising_start": { + "default": 0.0, + "description": "When to start denoising, expressed a percentage of total steps", + "field_kind": "input", + "input": "any", + "maximum": 1, + "minimum": 0, + "orig_default": 0.0, + "orig_required": false, + "title": "Denoising Start", + "type": "number" + }, + "denoising_end": { + "default": 1.0, + "description": "When to stop denoising, expressed a percentage of total steps", + "field_kind": "input", + "input": "any", + "maximum": 1, + "minimum": 0, + "orig_default": 1.0, + "orig_required": false, + "title": "Denoising End", + "type": "number" + }, + "add_noise": { + "default": true, + "description": "Add noise based on denoising start.", + "field_kind": "input", + "input": "any", + "orig_default": true, + "orig_required": false, + "title": "Add Noise", + "type": "boolean" + }, + "transformer": { + "anyOf": [ + { + "$ref": "#/components/schemas/TransformerField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Flux model (Transformer) to load", + "field_kind": "input", + "input": "connection", + "orig_required": true, + "title": "Transformer" + }, + "positive_text_conditioning": { + "anyOf": [ + { + "$ref": "#/components/schemas/FluxConditioningField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Positive conditioning tensor", + "field_kind": "input", + "input": "connection", + "orig_required": true + }, + "negative_text_conditioning": { + "anyOf": [ + { + "$ref": "#/components/schemas/FluxConditioningField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Negative conditioning tensor. Can be None if cfg_scale is 1.0.", + "field_kind": "input", + "input": "connection", + "orig_default": null, + "orig_required": false + }, + "cfg_scale": { + "default": 1.0, + "description": "Classifier-Free Guidance scale", + "field_kind": "input", + "input": "any", + "orig_default": 1.0, + "orig_required": false, + "title": "CFG Scale", + "type": "number" + }, + "width": { + "default": 1024, + "description": "Width of the generated image.", + "field_kind": "input", + "input": "any", + "multipleOf": 16, + "orig_default": 1024, + "orig_required": false, + "title": "Width", + "type": "integer" + }, + "height": { + "default": 1024, + "description": "Height of the generated image.", + "field_kind": "input", + "input": "any", + "multipleOf": 16, + "orig_default": 1024, + "orig_required": false, + "title": "Height", + "type": "integer" + }, + "num_steps": { + "default": 28, + "description": "Number of diffusion steps. Recommended: 28 for Klein.", + "field_kind": "input", + "input": "any", + "orig_default": 28, + "orig_required": false, + "title": "Num Steps", + "type": "integer" + }, + "scheduler": { + "default": "euler", + "description": "Scheduler (sampler) for the denoising process. 'euler' is fast and standard. 'heun' is 2nd-order (better quality, 2x slower). 'lcm' is optimized for few steps.", + "enum": ["euler", "heun", "lcm"], + "field_kind": "input", + "input": "any", + "orig_default": "euler", + "orig_required": false, + "title": "Scheduler", + "type": "string", + "ui_choice_labels": { + "euler": "Euler", + "heun": "Heun (2nd order)", + "lcm": "LCM" + } + }, + "seed": { + "default": 0, + "description": "Randomness seed for reproducibility.", + "field_kind": "input", + "input": "any", + "orig_default": 0, + "orig_required": false, + "title": "Seed", + "type": "integer" + }, + "vae": { + "anyOf": [ + { + "$ref": "#/components/schemas/VAEField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "FLUX.2 VAE model (required for BN statistics).", + "field_kind": "input", + "input": "connection", + "orig_required": true + }, + "type": { + "const": "flux2_denoise", + "default": "flux2_denoise", + "field_kind": "node_attribute", + "title": "type", + "type": "string" + } + }, + "required": ["type", "id"], + "tags": ["image", "flux", "flux2", "klein", "denoise"], + "title": "FLUX2 Denoise", + "type": "object", + "version": "1.0.0", + "output": { + "$ref": "#/components/schemas/LatentsOutput" + } + }, + "Flux2KleinModelLoaderInvocation": { + "category": "model", + "class": "invocation", + "classification": "prototype", + "description": "Loads a Flux2 Klein model, outputting its submodels.\n\nFlux2 Klein uses Qwen3 as the text encoder instead of CLIP+T5.\nIt uses a 32-channel VAE (AutoencoderKLFlux2) instead of the 16-channel FLUX.1 VAE.\n\nWhen using a Diffusers format model, both VAE and Qwen3 encoder are extracted\nautomatically from the main model. You can override with standalone models:\n- Transformer: Always from Flux2 Klein main model\n- VAE: From main model (Diffusers) or standalone VAE\n- Qwen3 Encoder: From main model (Diffusers) or standalone Qwen3 model", + "node_pack": "invokeai", + "properties": { + "id": { + "description": "The id of this instance of an invocation. Must be unique among all instances of invocations.", + "field_kind": "node_attribute", + "title": "Id", + "type": "string" + }, + "is_intermediate": { + "default": false, + "description": "Whether or not this is an intermediate invocation.", + "field_kind": "node_attribute", + "input": "direct", + "orig_required": true, + "title": "Is Intermediate", + "type": "boolean", + "ui_hidden": false, + "ui_type": "IsIntermediate" + }, + "use_cache": { + "default": true, + "description": "Whether or not to use the cache", + "field_kind": "node_attribute", + "title": "Use Cache", + "type": "boolean" + }, + "model": { + "$ref": "#/components/schemas/ModelIdentifierField", + "description": "Flux model (Transformer) to load", + "field_kind": "input", + "input": "direct", + "orig_required": true, + "title": "Transformer", + "ui_model_base": ["flux2"], + "ui_model_type": ["main"] + }, + "vae_model": { + "anyOf": [ + { + "$ref": "#/components/schemas/ModelIdentifierField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Standalone VAE model. Flux2 Klein uses the same VAE as FLUX (16-channel). If not provided, VAE will be loaded from the Qwen3 Source model.", + "field_kind": "input", + "input": "direct", + "orig_default": null, + "orig_required": false, + "title": "VAE", + "ui_model_base": ["flux", "flux2"], + "ui_model_type": ["vae"] + }, + "qwen3_encoder_model": { + "anyOf": [ + { + "$ref": "#/components/schemas/ModelIdentifierField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Standalone Qwen3 Encoder model. If not provided, encoder will be loaded from the Qwen3 Source model.", + "field_kind": "input", + "input": "direct", + "orig_default": null, + "orig_required": false, + "title": "Qwen3 Encoder", + "ui_model_type": ["qwen3_encoder"] + }, + "qwen3_source_model": { + "anyOf": [ + { + "$ref": "#/components/schemas/ModelIdentifierField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Diffusers Flux2 Klein model to extract VAE and/or Qwen3 encoder from. Use this if you don't have separate VAE/Qwen3 models. Ignored if both VAE and Qwen3 Encoder are provided separately.", + "field_kind": "input", + "input": "direct", + "orig_default": null, + "orig_required": false, + "title": "Qwen3 Source (Diffusers)", + "ui_model_base": ["flux2"], + "ui_model_format": ["diffusers"], + "ui_model_type": ["main"] + }, + "max_seq_len": { + "default": 512, + "description": "Max sequence length for the Qwen3 encoder.", + "enum": [256, 512], + "field_kind": "input", + "input": "any", + "orig_default": 512, + "orig_required": false, + "title": "Max Seq Length", + "type": "integer" + }, + "type": { + "const": "flux2_klein_model_loader", + "default": "flux2_klein_model_loader", + "field_kind": "node_attribute", + "title": "type", + "type": "string" + } + }, + "required": ["model", "type", "id"], + "tags": ["model", "flux", "klein", "qwen3"], + "title": "Main Model - Flux2 Klein", + "type": "object", + "version": "1.0.0", + "output": { + "$ref": "#/components/schemas/Flux2KleinModelLoaderOutput" + } + }, + "Flux2KleinModelLoaderOutput": { + "class": "output", + "description": "Flux2 Klein model loader output.", + "properties": { + "transformer": { + "$ref": "#/components/schemas/TransformerField", + "description": "Transformer", + "field_kind": "output", + "title": "Transformer", + "ui_hidden": false + }, + "qwen3_encoder": { + "$ref": "#/components/schemas/Qwen3EncoderField", + "description": "Qwen3 tokenizer and text encoder", + "field_kind": "output", + "title": "Qwen3 Encoder", + "ui_hidden": false + }, + "vae": { + "$ref": "#/components/schemas/VAEField", + "description": "VAE", + "field_kind": "output", + "title": "VAE", + "ui_hidden": false + }, + "max_seq_len": { + "description": "The max sequence length for the Qwen3 encoder.", + "enum": [256, 512], + "field_kind": "output", + "title": "Max Seq Length", + "type": "integer", + "ui_hidden": false + }, + "type": { + "const": "flux2_klein_model_loader_output", + "default": "flux2_klein_model_loader_output", + "field_kind": "node_attribute", + "title": "type", + "type": "string" + } + }, + "required": ["output_meta", "transformer", "qwen3_encoder", "vae", "max_seq_len", "type", "type"], + "title": "Flux2KleinModelLoaderOutput", + "type": "object" + }, + "Flux2KleinTextEncoderInvocation": { + "category": "conditioning", + "class": "invocation", + "classification": "prototype", + "description": "Encodes and preps a prompt for Flux2 Klein image generation.\n\nFlux2 Klein uses Qwen3 as the text encoder, extracting hidden states from\nlayers [9, 18, 27] and stacking them for richer text representations.", + "node_pack": "invokeai", + "properties": { + "id": { + "description": "The id of this instance of an invocation. Must be unique among all instances of invocations.", + "field_kind": "node_attribute", + "title": "Id", + "type": "string" + }, + "is_intermediate": { + "default": false, + "description": "Whether or not this is an intermediate invocation.", + "field_kind": "node_attribute", + "input": "direct", + "orig_required": true, + "title": "Is Intermediate", + "type": "boolean", + "ui_hidden": false, + "ui_type": "IsIntermediate" + }, + "use_cache": { + "default": true, + "description": "Whether or not to use the cache", + "field_kind": "node_attribute", + "title": "Use Cache", + "type": "boolean" + }, + "prompt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Text prompt to encode.", + "field_kind": "input", + "input": "any", + "orig_required": true, + "title": "Prompt", + "ui_component": "textarea" + }, + "qwen3_encoder": { + "anyOf": [ + { + "$ref": "#/components/schemas/Qwen3EncoderField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Qwen3 tokenizer and text encoder", + "field_kind": "input", + "input": "connection", + "orig_required": true, + "title": "Qwen3 Encoder" + }, + "max_seq_len": { + "default": 512, + "description": "Max sequence length for the Qwen3 encoder.", + "enum": [256, 512], + "field_kind": "input", + "input": "any", + "orig_default": 512, + "orig_required": false, + "title": "Max Seq Len", + "type": "integer" + }, + "mask": { + "anyOf": [ + { + "$ref": "#/components/schemas/TensorField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "A mask defining the region that this conditioning prompt applies to.", + "field_kind": "input", + "input": "any", + "orig_default": null, + "orig_required": false + }, + "type": { + "const": "flux2_klein_text_encoder", + "default": "flux2_klein_text_encoder", + "field_kind": "node_attribute", + "title": "type", + "type": "string" + } + }, + "required": ["type", "id"], + "tags": ["prompt", "conditioning", "flux", "klein", "qwen3"], + "title": "Prompt - Flux2 Klein", + "type": "object", + "version": "1.0.0", + "output": { + "$ref": "#/components/schemas/FluxConditioningOutput" + } + }, + "Flux2VaeDecodeInvocation": { + "category": "latents", + "class": "invocation", + "classification": "prototype", + "description": "Generates an image from latents using FLUX.2 Klein's 32-channel VAE.", + "node_pack": "invokeai", + "properties": { + "board": { + "anyOf": [ + { + "$ref": "#/components/schemas/BoardField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The board to save the image to", + "field_kind": "internal", + "input": "direct", + "orig_required": false, + "ui_hidden": false + }, + "metadata": { + "anyOf": [ + { + "$ref": "#/components/schemas/MetadataField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional metadata to be saved with the image", + "field_kind": "internal", + "input": "connection", + "orig_required": false, + "ui_hidden": false + }, + "id": { + "description": "The id of this instance of an invocation. Must be unique among all instances of invocations.", + "field_kind": "node_attribute", + "title": "Id", + "type": "string" + }, + "is_intermediate": { + "default": false, + "description": "Whether or not this is an intermediate invocation.", + "field_kind": "node_attribute", + "input": "direct", + "orig_required": true, + "title": "Is Intermediate", + "type": "boolean", + "ui_hidden": false, + "ui_type": "IsIntermediate" + }, + "use_cache": { + "default": true, + "description": "Whether or not to use the cache", + "field_kind": "node_attribute", + "title": "Use Cache", + "type": "boolean" + }, + "latents": { + "anyOf": [ + { + "$ref": "#/components/schemas/LatentsField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Latents tensor", + "field_kind": "input", + "input": "connection", + "orig_required": true + }, + "vae": { + "anyOf": [ + { + "$ref": "#/components/schemas/VAEField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "VAE", + "field_kind": "input", + "input": "connection", + "orig_required": true + }, + "type": { + "const": "flux2_vae_decode", + "default": "flux2_vae_decode", + "field_kind": "node_attribute", + "title": "type", + "type": "string" + } + }, + "required": ["type", "id"], + "tags": ["latents", "image", "vae", "l2i", "flux2", "klein"], + "title": "Latents to Image - FLUX2", + "type": "object", + "version": "1.0.0", + "output": { + "$ref": "#/components/schemas/ImageOutput" + } + }, + "Flux2VariantType": { + "type": "string", + "enum": ["klein_4b", "klein_9b"], + "title": "Flux2VariantType", + "description": "FLUX.2 model variants." + }, "FluxConditioningCollectionOutput": { "class": "output", "description": "Base class for nodes that output a collection of conditioning tensors", @@ -18830,6 +19915,22 @@ "title": "Num Steps", "type": "integer" }, + "scheduler": { + "default": "euler", + "description": "Scheduler (sampler) for the denoising process. 'euler' is fast and standard. 'heun' is 2nd-order (better quality, 2x slower). 'lcm' is optimized for few steps.", + "enum": ["euler", "heun", "lcm"], + "field_kind": "input", + "input": "any", + "orig_default": "euler", + "orig_required": false, + "title": "Scheduler", + "type": "string", + "ui_choice_labels": { + "euler": "Euler", + "heun": "Heun (2nd order)", + "lcm": "LCM" + } + }, "guidance": { "default": 4.0, "description": "The guidance strength. Higher values adhere more strictly to the prompt, and will produce less diverse images. FLUX dev only, ignored for schnell.", @@ -18947,7 +20048,7 @@ "tags": ["image", "flux"], "title": "FLUX Denoise", "type": "object", - "version": "4.1.0", + "version": "4.2.0", "output": { "$ref": "#/components/schemas/LatentsOutput" } @@ -19254,6 +20355,22 @@ "title": "Num Steps", "type": "integer" }, + "scheduler": { + "default": "euler", + "description": "Scheduler (sampler) for the denoising process. 'euler' is fast and standard. 'heun' is 2nd-order (better quality, 2x slower). 'lcm' is optimized for few steps.", + "enum": ["euler", "heun", "lcm"], + "field_kind": "input", + "input": "any", + "orig_default": "euler", + "orig_required": false, + "title": "Scheduler", + "type": "string", + "ui_choice_labels": { + "euler": "Euler", + "heun": "Heun (2nd order)", + "lcm": "LCM" + } + }, "guidance": { "default": 4.0, "description": "The guidance strength. Higher values adhere more strictly to the prompt, and will produce less diverse images. FLUX dev only, ignored for schnell.", @@ -20671,7 +21788,8 @@ "FluxVariantType": { "type": "string", "enum": ["schnell", "dev", "dev_fill"], - "title": "FluxVariantType" + "title": "FluxVariantType", + "description": "FLUX.1 model variants." }, "FoundModel": { "properties": { @@ -21154,6 +22272,18 @@ { "$ref": "#/components/schemas/FloatToIntegerInvocation" }, + { + "$ref": "#/components/schemas/Flux2DenoiseInvocation" + }, + { + "$ref": "#/components/schemas/Flux2KleinModelLoaderInvocation" + }, + { + "$ref": "#/components/schemas/Flux2KleinTextEncoderInvocation" + }, + { + "$ref": "#/components/schemas/Flux2VaeDecodeInvocation" + }, { "$ref": "#/components/schemas/FluxControlLoRALoaderInvocation" }, @@ -21478,6 +22608,9 @@ { "$ref": "#/components/schemas/NormalMapInvocation" }, + { + "$ref": "#/components/schemas/PBRMapsInvocation" + }, { "$ref": "#/components/schemas/PairTileImageInvocation" }, @@ -21487,6 +22620,9 @@ { "$ref": "#/components/schemas/PiDiNetEdgeDetectionInvocation" }, + { + "$ref": "#/components/schemas/PromptTemplateInvocation" + }, { "$ref": "#/components/schemas/PromptsFromFileInvocation" }, @@ -21616,9 +22752,15 @@ { "$ref": "#/components/schemas/VAELoaderInvocation" }, + { + "$ref": "#/components/schemas/ZImageControlInvocation" + }, { "$ref": "#/components/schemas/ZImageDenoiseInvocation" }, + { + "$ref": "#/components/schemas/ZImageDenoiseMetaInvocation" + }, { "$ref": "#/components/schemas/ZImageImageToLatentsInvocation" }, @@ -21634,6 +22776,9 @@ { "$ref": "#/components/schemas/ZImageModelLoaderInvocation" }, + { + "$ref": "#/components/schemas/ZImageSeedVarianceEnhancerInvocation" + }, { "$ref": "#/components/schemas/ZImageTextEncoderInvocation" } @@ -21753,6 +22898,9 @@ { "$ref": "#/components/schemas/FloatOutput" }, + { + "$ref": "#/components/schemas/Flux2KleinModelLoaderOutput" + }, { "$ref": "#/components/schemas/FluxConditioningCollectionOutput" }, @@ -21864,9 +23012,15 @@ { "$ref": "#/components/schemas/NoiseOutput" }, + { + "$ref": "#/components/schemas/PBRMapsOutput" + }, { "$ref": "#/components/schemas/PairTileImageOutput" }, + { + "$ref": "#/components/schemas/PromptTemplateOutput" + }, { "$ref": "#/components/schemas/SD3ConditioningOutput" }, @@ -21918,6 +23072,9 @@ { "$ref": "#/components/schemas/ZImageConditioningOutput" }, + { + "$ref": "#/components/schemas/ZImageControlOutput" + }, { "$ref": "#/components/schemas/ZImageLoRALoaderOutput" }, @@ -22252,7 +23409,7 @@ "type": "object", "required": ["repo_id"], "title": "HFModelSource", - "description": "A HuggingFace repo_id with optional variant, sub-folder and access token.\nNote that the variant option, if not provided to the constructor, will default to fp16, which is\nwhat people (almost) always want." + "description": "A HuggingFace repo_id with optional variant, sub-folder(s) and access token.\nNote that the variant option, if not provided to the constructor, will default to fp16, which is\nwhat people (almost) always want.\n\nThe subfolder can be a single path or multiple paths joined by '+' (e.g., \"text_encoder+tokenizer\").\nWhen multiple subfolders are specified, all of them will be downloaded and combined into the model directory." }, "HFTokenStatus": { "type": "string", @@ -28066,6 +29223,18 @@ { "$ref": "#/components/schemas/FloatToIntegerInvocation" }, + { + "$ref": "#/components/schemas/Flux2DenoiseInvocation" + }, + { + "$ref": "#/components/schemas/Flux2KleinModelLoaderInvocation" + }, + { + "$ref": "#/components/schemas/Flux2KleinTextEncoderInvocation" + }, + { + "$ref": "#/components/schemas/Flux2VaeDecodeInvocation" + }, { "$ref": "#/components/schemas/FluxControlLoRALoaderInvocation" }, @@ -28390,6 +29559,9 @@ { "$ref": "#/components/schemas/NormalMapInvocation" }, + { + "$ref": "#/components/schemas/PBRMapsInvocation" + }, { "$ref": "#/components/schemas/PairTileImageInvocation" }, @@ -28399,6 +29571,9 @@ { "$ref": "#/components/schemas/PiDiNetEdgeDetectionInvocation" }, + { + "$ref": "#/components/schemas/PromptTemplateInvocation" + }, { "$ref": "#/components/schemas/PromptsFromFileInvocation" }, @@ -28528,9 +29703,15 @@ { "$ref": "#/components/schemas/VAELoaderInvocation" }, + { + "$ref": "#/components/schemas/ZImageControlInvocation" + }, { "$ref": "#/components/schemas/ZImageDenoiseInvocation" }, + { + "$ref": "#/components/schemas/ZImageDenoiseMetaInvocation" + }, { "$ref": "#/components/schemas/ZImageImageToLatentsInvocation" }, @@ -28546,6 +29727,9 @@ { "$ref": "#/components/schemas/ZImageModelLoaderInvocation" }, + { + "$ref": "#/components/schemas/ZImageSeedVarianceEnhancerInvocation" + }, { "$ref": "#/components/schemas/ZImageTextEncoderInvocation" } @@ -28623,6 +29807,9 @@ { "$ref": "#/components/schemas/FloatOutput" }, + { + "$ref": "#/components/schemas/Flux2KleinModelLoaderOutput" + }, { "$ref": "#/components/schemas/FluxConditioningCollectionOutput" }, @@ -28734,9 +29921,15 @@ { "$ref": "#/components/schemas/NoiseOutput" }, + { + "$ref": "#/components/schemas/PBRMapsOutput" + }, { "$ref": "#/components/schemas/PairTileImageOutput" }, + { + "$ref": "#/components/schemas/PromptTemplateOutput" + }, { "$ref": "#/components/schemas/SD3ConditioningOutput" }, @@ -28788,6 +29981,9 @@ { "$ref": "#/components/schemas/ZImageConditioningOutput" }, + { + "$ref": "#/components/schemas/ZImageControlOutput" + }, { "$ref": "#/components/schemas/ZImageLoRALoaderOutput" }, @@ -29041,6 +30237,18 @@ { "$ref": "#/components/schemas/FloatToIntegerInvocation" }, + { + "$ref": "#/components/schemas/Flux2DenoiseInvocation" + }, + { + "$ref": "#/components/schemas/Flux2KleinModelLoaderInvocation" + }, + { + "$ref": "#/components/schemas/Flux2KleinTextEncoderInvocation" + }, + { + "$ref": "#/components/schemas/Flux2VaeDecodeInvocation" + }, { "$ref": "#/components/schemas/FluxControlLoRALoaderInvocation" }, @@ -29365,6 +30573,9 @@ { "$ref": "#/components/schemas/NormalMapInvocation" }, + { + "$ref": "#/components/schemas/PBRMapsInvocation" + }, { "$ref": "#/components/schemas/PairTileImageInvocation" }, @@ -29374,6 +30585,9 @@ { "$ref": "#/components/schemas/PiDiNetEdgeDetectionInvocation" }, + { + "$ref": "#/components/schemas/PromptTemplateInvocation" + }, { "$ref": "#/components/schemas/PromptsFromFileInvocation" }, @@ -29503,9 +30717,15 @@ { "$ref": "#/components/schemas/VAELoaderInvocation" }, + { + "$ref": "#/components/schemas/ZImageControlInvocation" + }, { "$ref": "#/components/schemas/ZImageDenoiseInvocation" }, + { + "$ref": "#/components/schemas/ZImageDenoiseMetaInvocation" + }, { "$ref": "#/components/schemas/ZImageImageToLatentsInvocation" }, @@ -29521,6 +30741,9 @@ { "$ref": "#/components/schemas/ZImageModelLoaderInvocation" }, + { + "$ref": "#/components/schemas/ZImageSeedVarianceEnhancerInvocation" + }, { "$ref": "#/components/schemas/ZImageTextEncoderInvocation" } @@ -29727,6 +30950,18 @@ "float_to_int": { "$ref": "#/components/schemas/IntegerOutput" }, + "flux2_denoise": { + "$ref": "#/components/schemas/LatentsOutput" + }, + "flux2_klein_model_loader": { + "$ref": "#/components/schemas/Flux2KleinModelLoaderOutput" + }, + "flux2_klein_text_encoder": { + "$ref": "#/components/schemas/FluxConditioningOutput" + }, + "flux2_vae_decode": { + "$ref": "#/components/schemas/ImageOutput" + }, "flux_control_lora_loader": { "$ref": "#/components/schemas/FluxControlLoRALoaderOutput" }, @@ -30069,12 +31304,18 @@ "paste_image_into_bounding_box": { "$ref": "#/components/schemas/ImageOutput" }, + "pbr_maps": { + "$ref": "#/components/schemas/PBRMapsOutput" + }, "pidi_edge_detection": { "$ref": "#/components/schemas/ImageOutput" }, "prompt_from_file": { "$ref": "#/components/schemas/StringCollectionOutput" }, + "prompt_template": { + "$ref": "#/components/schemas/PromptTemplateOutput" + }, "rand_float": { "$ref": "#/components/schemas/FloatOutput" }, @@ -30201,9 +31442,15 @@ "vae_loader": { "$ref": "#/components/schemas/VAEOutput" }, + "z_image_control": { + "$ref": "#/components/schemas/ZImageControlOutput" + }, "z_image_denoise": { "$ref": "#/components/schemas/LatentsOutput" }, + "z_image_denoise_meta": { + "$ref": "#/components/schemas/LatentsMetaOutput" + }, "z_image_i2l": { "$ref": "#/components/schemas/LatentsOutput" }, @@ -30219,229 +31466,241 @@ "z_image_model_loader": { "$ref": "#/components/schemas/ZImageModelLoaderOutput" }, + "z_image_seed_variance_enhancer": { + "$ref": "#/components/schemas/ZImageConditioningOutput" + }, "z_image_text_encoder": { "$ref": "#/components/schemas/ZImageConditioningOutput" } }, "required": [ - "rand_int", - "metadata_to_bool_collection", - "z_image_i2l", - "lora_loader", - "img_lerp", - "lblend", - "blank_image", - "integer_collection", - "z_image_denoise", - "create_denoise_mask", - "denoise_latents_meta", - "img_channel_multiply", - "sdxl_refiner_compel_prompt", - "show_image", + "flux2_klein_model_loader", "float_to_int", - "img_hue_adjust", - "sdxl_compel_prompt", - "get_image_mask_bounding_box", - "metadata_to_lora_collection", - "denoise_latents", - "img_channel_offset", - "string_generator", - "img_conv", - "range_of_size", "cogview4_denoise", - "float", - "metadata_to_integer", - "t2i_adapter", - "invokeai_ealightness", - "float_batch", - "metadata_item", - "img_ilerp", - "face_mask_detection", - "tile_to_properties", - "conditioning", - "freeu", - "flux_kontext", - "mlsd_detection", - "sdxl_lora_collection_loader", - "invokeai_img_blend", - "img_blur", - "ideal_size", - "range", - "metadata_to_t2i_adapters", - "l2i", - "metadata_to_vae", - "lora_collection_loader", - "canvas_paste_back", - "img_paste", - "lresize", - "random_range", - "metadata_to_integer_collection", - "tensor_mask_to_image", - "alpha_mask_to_tensor", - "invokeai_img_hue_adjust_plus", - "string_split_neg", - "flux_fill", - "sd3_denoise", - "flux_controlnet", - "invokeai_img_dilate_erode", - "canvas_v2_mask_and_crop", - "lineart_edge_detection", - "merge_metadata", - "string_batch", - "mask_combine", - "color", - "float_range", - "crop_latents", - "spandrel_image_to_image", - "metadata_to_float", - "mul", - "infill_tile", - "cv_inpaint", - "calculate_image_tiles", - "img_nsfw", - "image_generator", - "flux_lora_collection_loader", - "string_join", - "seamless", - "sd3_i2l", - "flux_control_lora_loader", - "paste_image_into_bounding_box", - "clip_skip", - "conditioning_collection", - "flux_ip_adapter", - "metadata_to_ip_adapters", - "esrgan", - "invokeai_img_val_thresholds", - "face_identifier", - "metadata", - "cogview4_model_loader", - "sub", - "metadata_to_controlnets", - "z_image_text_encoder", - "string_join_three", - "unsharp_mask", - "grounding_dino", - "metadata_to_bool", - "apply_tensor_mask_to_image", - "flux_denoise_meta", - "iterate", - "image_batch", - "metadata_from_image", - "integer_math", - "metadata_to_string_collection", - "expand_mask_with_fade", - "integer_generator", - "sd3_l2i", - "boolean_collection", - "round_float", - "infill_rgba", - "z_image_l2i", - "vae_loader", - "controlnet", - "tiled_multi_diffusion_denoise_latents", - "string_split", - "cogview4_i2l", - "image_mask_to_tensor", - "heuristic_resize", - "img_watermark", - "scheduler", - "img_crop", - "sdxl_refiner_model_loader", - "segment_anything", - "color_map", - "boolean", - "hed_edge_detection", - "rectangle_mask", - "infill_lama", - "main_model_loader", - "save_image", - "calculate_image_tiles_even_split", - "image", - "flux_redux", - "noise", - "llava_onevision_vllm", - "invokeai_img_enhance", - "model_identifier", - "img_resize", - "integer_batch", - "img_noise", - "cogview4_text_encoder", - "latents_collection", - "metadata_to_loras", - "dynamic_prompt", - "metadata_item_linked", - "z_image_lora_loader", - "merge_tiles_to_image", - "img_chan", - "float_generator", - "compel", - "string", - "add", - "canny_edge_detection", - "string_collection", - "flux_denoise", - "sd3_text_encoder", - "metadata_to_scheduler", - "mask_edge", "img_scale", - "flux_vae_decode", - "latents", - "flux_lora_loader", - "float_math", - "div", - "pidi_edge_detection", - "image_panel_layout", - "lscale", - "infill_patchmatch", - "face_off", - "sdxl_lora_loader", - "i2l", - "crop_image_to_bounding_box", - "core_metadata", - "calculate_image_tiles_min_overlap", - "image_collection", - "metadata_to_model", - "infill_cv2", - "z_image_lora_collection_loader", - "mask_from_id", - "tomask", - "cogview4_l2i", - "metadata_to_sdlx_loras", - "integer", - "normal_map", - "lineart_anime_edge_detection", - "content_shuffle", - "string_replace", - "img_mul", - "flux_text_encoder", - "sdxl_model_loader", - "prompt_from_file", - "invert_tensor_mask", - "rand_float", - "flux_vae_encode", - "ip_adapter", - "lora_selector", - "spandrel_image_to_image_autoscale", + "flux_fill", + "img_channel_offset", + "metadata_to_controlnets", "sd3_model_loader", - "bounding_box", - "metadata_to_string", - "dw_openpose_detection", - "collect", - "create_gradient_mask", - "flux_kontext_image_prep", - "apply_mask_to_image", - "pair_tile_image", - "z_image_model_loader", - "flux_model_loader", - "metadata_to_sdxl_model", - "metadata_to_float_collection", + "hed_edge_detection", + "z_image_denoise_meta", + "integer_collection", + "invokeai_img_blend", + "crop_latents", + "sd3_i2l", + "sdxl_refiner_compel_prompt", + "img_chan", + "metadata_to_bool", "color_correct", - "metadata_field_extractor", - "float_collection", - "mediapipe_face_detection", + "metadata_to_ip_adapters", + "apply_mask_to_image", + "lora_collection_loader", + "color", + "crop_image_to_bounding_box", + "lscale", "depth_anything_depth_estimation", + "apply_tensor_mask_to_image", + "img_conv", + "z_image_model_loader", + "pbr_maps", + "expand_mask_with_fade", + "controlnet", + "sdxl_compel_prompt", "invokeai_img_composite", - "img_pad_crop" + "string_replace", + "canvas_v2_mask_and_crop", + "metadata_to_integer", + "cogview4_model_loader", + "flux_lora_loader", + "integer_math", + "img_paste", + "sub", + "metadata_from_image", + "flux_ip_adapter", + "compel", + "cv_inpaint", + "boolean", + "z_image_i2l", + "normal_map", + "float_collection", + "img_ilerp", + "image_batch", + "flux_vae_encode", + "mask_from_id", + "alpha_mask_to_tensor", + "seamless", + "range", + "flux_vae_decode", + "metadata_to_string_collection", + "ideal_size", + "sd3_text_encoder", + "denoise_latents", + "infill_patchmatch", + "grounding_dino", + "metadata_to_loras", + "string", + "img_nsfw", + "z_image_text_encoder", + "z_image_lora_loader", + "float_generator", + "lresize", + "lora_loader", + "unsharp_mask", + "flux2_klein_text_encoder", + "conditioning_collection", + "metadata_to_t2i_adapters", + "sdxl_model_loader", + "metadata", + "mediapipe_face_detection", + "img_blur", + "float_math", + "invokeai_img_dilate_erode", + "random_range", + "z_image_lora_collection_loader", + "flux2_vae_decode", + "calculate_image_tiles_even_split", + "cogview4_l2i", + "float", + "invokeai_ealightness", + "img_resize", + "flux_controlnet", + "sdxl_lora_loader", + "latents_collection", + "invokeai_img_enhance", + "mask_edge", + "dynamic_prompt", + "flux_kontext", + "range_of_size", + "image_mask_to_tensor", + "metadata_to_sdxl_model", + "segment_anything", + "integer_batch", + "scheduler", + "blank_image", + "invert_tensor_mask", + "z_image_denoise", + "image_panel_layout", + "metadata_to_float_collection", + "sdxl_refiner_model_loader", + "color_map", + "collect", + "metadata_to_model", + "face_identifier", + "mlsd_detection", + "string_split", + "infill_tile", + "noise", + "conditioning", + "main_model_loader", + "metadata_to_string", + "canvas_paste_back", + "face_mask_detection", + "string_join_three", + "clip_skip", + "metadata_to_scheduler", + "string_join", + "esrgan", + "prompt_from_file", + "round_float", + "boolean_collection", + "mask_combine", + "div", + "lineart_edge_detection", + "flux_denoise", + "flux_lora_collection_loader", + "string_collection", + "show_image", + "heuristic_resize", + "flux2_denoise", + "spandrel_image_to_image", + "merge_metadata", + "metadata_to_lora_collection", + "z_image_seed_variance_enhancer", + "flux_control_lora_loader", + "canny_edge_detection", + "sd3_l2i", + "lora_selector", + "mul", + "pair_tile_image", + "face_off", + "denoise_latents_meta", + "flux_redux", + "lineart_anime_edge_detection", + "img_pad_crop", + "float_range", + "spandrel_image_to_image_autoscale", + "l2i", + "pidi_edge_detection", + "sd3_denoise", + "rand_int", + "iterate", + "add", + "image", + "save_image", + "tile_to_properties", + "string_generator", + "prompt_template", + "model_identifier", + "infill_lama", + "metadata_item_linked", + "create_gradient_mask", + "img_lerp", + "bounding_box", + "flux_model_loader", + "get_image_mask_bounding_box", + "invokeai_img_hue_adjust_plus", + "img_watermark", + "t2i_adapter", + "metadata_to_float", + "dw_openpose_detection", + "calculate_image_tiles_min_overlap", + "cogview4_i2l", + "metadata_to_vae", + "integer", + "invokeai_img_val_thresholds", + "tomask", + "img_noise", + "vae_loader", + "z_image_control", + "image_collection", + "merge_tiles_to_image", + "lblend", + "rectangle_mask", + "sdxl_lora_collection_loader", + "img_crop", + "i2l", + "infill_cv2", + "integer_generator", + "metadata_to_integer_collection", + "z_image_l2i", + "cogview4_text_encoder", + "infill_rgba", + "metadata_field_extractor", + "tensor_mask_to_image", + "image_generator", + "flux_kontext_image_prep", + "core_metadata", + "flux_text_encoder", + "latents", + "content_shuffle", + "string_batch", + "ip_adapter", + "img_channel_multiply", + "metadata_to_bool_collection", + "freeu", + "calculate_image_tiles", + "flux_denoise_meta", + "img_mul", + "string_split_neg", + "create_denoise_mask", + "rand_float", + "metadata_to_sdlx_loras", + "img_hue_adjust", + "tiled_multi_diffusion_denoise_latents", + "float_batch", + "llava_onevision_vllm", + "metadata_item", + "paste_image_into_bounding_box" ] }, "InvocationProgressEvent": { @@ -30672,6 +31931,18 @@ { "$ref": "#/components/schemas/FloatToIntegerInvocation" }, + { + "$ref": "#/components/schemas/Flux2DenoiseInvocation" + }, + { + "$ref": "#/components/schemas/Flux2KleinModelLoaderInvocation" + }, + { + "$ref": "#/components/schemas/Flux2KleinTextEncoderInvocation" + }, + { + "$ref": "#/components/schemas/Flux2VaeDecodeInvocation" + }, { "$ref": "#/components/schemas/FluxControlLoRALoaderInvocation" }, @@ -30996,6 +32267,9 @@ { "$ref": "#/components/schemas/NormalMapInvocation" }, + { + "$ref": "#/components/schemas/PBRMapsInvocation" + }, { "$ref": "#/components/schemas/PairTileImageInvocation" }, @@ -31005,6 +32279,9 @@ { "$ref": "#/components/schemas/PiDiNetEdgeDetectionInvocation" }, + { + "$ref": "#/components/schemas/PromptTemplateInvocation" + }, { "$ref": "#/components/schemas/PromptsFromFileInvocation" }, @@ -31134,9 +32411,15 @@ { "$ref": "#/components/schemas/VAELoaderInvocation" }, + { + "$ref": "#/components/schemas/ZImageControlInvocation" + }, { "$ref": "#/components/schemas/ZImageDenoiseInvocation" }, + { + "$ref": "#/components/schemas/ZImageDenoiseMetaInvocation" + }, { "$ref": "#/components/schemas/ZImageImageToLatentsInvocation" }, @@ -31152,6 +32435,9 @@ { "$ref": "#/components/schemas/ZImageModelLoaderInvocation" }, + { + "$ref": "#/components/schemas/ZImageSeedVarianceEnhancerInvocation" + }, { "$ref": "#/components/schemas/ZImageTextEncoderInvocation" } @@ -31441,6 +32727,18 @@ { "$ref": "#/components/schemas/FloatToIntegerInvocation" }, + { + "$ref": "#/components/schemas/Flux2DenoiseInvocation" + }, + { + "$ref": "#/components/schemas/Flux2KleinModelLoaderInvocation" + }, + { + "$ref": "#/components/schemas/Flux2KleinTextEncoderInvocation" + }, + { + "$ref": "#/components/schemas/Flux2VaeDecodeInvocation" + }, { "$ref": "#/components/schemas/FluxControlLoRALoaderInvocation" }, @@ -31765,6 +33063,9 @@ { "$ref": "#/components/schemas/NormalMapInvocation" }, + { + "$ref": "#/components/schemas/PBRMapsInvocation" + }, { "$ref": "#/components/schemas/PairTileImageInvocation" }, @@ -31774,6 +33075,9 @@ { "$ref": "#/components/schemas/PiDiNetEdgeDetectionInvocation" }, + { + "$ref": "#/components/schemas/PromptTemplateInvocation" + }, { "$ref": "#/components/schemas/PromptsFromFileInvocation" }, @@ -31903,9 +33207,15 @@ { "$ref": "#/components/schemas/VAELoaderInvocation" }, + { + "$ref": "#/components/schemas/ZImageControlInvocation" + }, { "$ref": "#/components/schemas/ZImageDenoiseInvocation" }, + { + "$ref": "#/components/schemas/ZImageDenoiseMetaInvocation" + }, { "$ref": "#/components/schemas/ZImageImageToLatentsInvocation" }, @@ -31921,6 +33231,9 @@ { "$ref": "#/components/schemas/ZImageModelLoaderInvocation" }, + { + "$ref": "#/components/schemas/ZImageSeedVarianceEnhancerInvocation" + }, { "$ref": "#/components/schemas/ZImageTextEncoderInvocation" } @@ -32219,6 +33532,13 @@ "description": "If True, a memory snapshot will be captured before and after every model cache operation, and the result will be logged (at debug level). There is a time cost to capturing the memory snapshots, so it is recommended to only enable this feature if you are actively inspecting the model cache's behaviour.", "default": false }, + "model_cache_keep_alive_min": { + "type": "number", + "minimum": 0.0, + "title": "Model Cache Keep Alive Min", + "description": "How long to keep models in cache after last use, in minutes. A value of 0 (the default) means models are kept in cache indefinitely. If no model generations occur within the timeout period, the model cache is cleared using the same logic as the 'Clear Model Cache' button.", + "default": 0 + }, "device_working_mem_gb": { "type": "number", "title": "Device Working Mem Gb", @@ -32437,7 +33757,7 @@ "additionalProperties": false, "type": "object", "title": "InvokeAIAppConfig", - "description": "Invoke's global app configuration.\n\nTypically, you won't need to interact with this class directly. Instead, use the `get_config` function from `invokeai.app.services.config` to get a singleton config object.\n\nAttributes:\n host: IP address to bind to. Use `0.0.0.0` to serve to your local network.\n port: Port to bind to.\n allow_origins: Allowed CORS origins.\n allow_credentials: Allow CORS credentials.\n allow_methods: Methods allowed for CORS.\n allow_headers: Headers allowed for CORS.\n ssl_certfile: SSL certificate file for HTTPS. See https://www.uvicorn.org/settings/#https.\n ssl_keyfile: SSL key file for HTTPS. See https://www.uvicorn.org/settings/#https.\n log_tokenization: Enable logging of parsed prompt tokens.\n patchmatch: Enable patchmatch inpaint code.\n models_dir: Path to the models directory.\n convert_cache_dir: Path to the converted models cache directory (DEPRECATED, but do not delete because it is needed for migration from previous versions).\n download_cache_dir: Path to the directory that contains dynamically downloaded models.\n legacy_conf_dir: Path to directory of legacy checkpoint config files.\n db_dir: Path to InvokeAI databases directory.\n outputs_dir: Path to directory for outputs.\n custom_nodes_dir: Path to directory for custom nodes.\n style_presets_dir: Path to directory for style presets.\n workflow_thumbnails_dir: Path to directory for workflow thumbnails.\n log_handlers: Log handler. Valid options are \"console\", \"file=\", \"syslog=path|address:host:port\", \"http=\".\n log_format: Log format. Use \"plain\" for text-only, \"color\" for colorized output, \"legacy\" for 2.3-style logging and \"syslog\" for syslog-style.
Valid values: `plain`, `color`, `syslog`, `legacy`\n log_level: Emit logging messages at this level or higher.
Valid values: `debug`, `info`, `warning`, `error`, `critical`\n log_sql: Log SQL queries. `log_level` must be `debug` for this to do anything. Extremely verbose.\n log_level_network: Log level for network-related messages. 'info' and 'debug' are very verbose.
Valid values: `debug`, `info`, `warning`, `error`, `critical`\n use_memory_db: Use in-memory database. Useful for development.\n dev_reload: Automatically reload when Python sources are changed. Does not reload node definitions.\n profile_graphs: Enable graph profiling using `cProfile`.\n profile_prefix: An optional prefix for profile output files.\n profiles_dir: Path to profiles output directory.\n max_cache_ram_gb: The maximum amount of CPU RAM to use for model caching in GB. If unset, the limit will be configured based on the available RAM. In most cases, it is recommended to leave this unset.\n max_cache_vram_gb: The amount of VRAM to use for model caching in GB. If unset, the limit will be configured based on the available VRAM and the device_working_mem_gb. In most cases, it is recommended to leave this unset.\n log_memory_usage: If True, a memory snapshot will be captured before and after every model cache operation, and the result will be logged (at debug level). There is a time cost to capturing the memory snapshots, so it is recommended to only enable this feature if you are actively inspecting the model cache's behaviour.\n device_working_mem_gb: The amount of working memory to keep available on the compute device (in GB). Has no effect if running on CPU. If you are experiencing OOM errors, try increasing this value.\n enable_partial_loading: Enable partial loading of models. This enables models to run with reduced VRAM requirements (at the cost of slower speed) by streaming the model from RAM to VRAM as its used. In some edge cases, partial loading can cause models to run more slowly if they were previously being fully loaded into VRAM.\n keep_ram_copy_of_weights: Whether to keep a full RAM copy of a model's weights when the model is loaded in VRAM. Keeping a RAM copy increases average RAM usage, but speeds up model switching and LoRA patching (assuming there is sufficient RAM). Set this to False if RAM pressure is consistently high.\n ram: DEPRECATED: This setting is no longer used. It has been replaced by `max_cache_ram_gb`, but most users will not need to use this config since automatic cache size limits should work well in most cases. This config setting will be removed once the new model cache behavior is stable.\n vram: DEPRECATED: This setting is no longer used. It has been replaced by `max_cache_vram_gb`, but most users will not need to use this config since automatic cache size limits should work well in most cases. This config setting will be removed once the new model cache behavior is stable.\n lazy_offload: DEPRECATED: This setting is no longer used. Lazy-offloading is enabled by default. This config setting will be removed once the new model cache behavior is stable.\n pytorch_cuda_alloc_conf: Configure the Torch CUDA memory allocator. This will impact peak reserved VRAM usage and performance. Setting to \"backend:cudaMallocAsync\" works well on many systems. The optimal configuration is highly dependent on the system configuration (device type, VRAM, CUDA driver version, etc.), so must be tuned experimentally.\n device: Preferred execution device. `auto` will choose the device depending on the hardware platform and the installed torch capabilities.
Valid values: `auto`, `cpu`, `cuda`, `mps`, `cuda:N` (where N is a device number)\n precision: Floating point precision. `float16` will consume half the memory of `float32` but produce slightly lower-quality images. The `auto` setting will guess the proper precision based on your video card and operating system.
Valid values: `auto`, `float16`, `bfloat16`, `float32`\n sequential_guidance: Whether to calculate guidance in serial instead of in parallel, lowering memory requirements.\n attention_type: Attention type.
Valid values: `auto`, `normal`, `xformers`, `sliced`, `torch-sdp`\n attention_slice_size: Slice size, valid when attention_type==\"sliced\".
Valid values: `auto`, `balanced`, `max`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`\n force_tiled_decode: Whether to enable tiled VAE decode (reduces memory consumption with some performance penalty).\n pil_compress_level: The compress_level setting of PIL.Image.save(), used for PNG encoding. All settings are lossless. 0 = no compression, 1 = fastest with slightly larger filesize, 9 = slowest with smallest filesize. 1 is typically the best setting.\n max_queue_size: Maximum number of items in the session queue.\n clear_queue_on_startup: Empties session queue on startup.\n allow_nodes: List of nodes to allow. Omit to allow all.\n deny_nodes: List of nodes to deny. Omit to deny none.\n node_cache_size: How many cached nodes to keep in memory.\n hashing_algorithm: Model hashing algorthim for model installs. 'blake3_multi' is best for SSDs. 'blake3_single' is best for spinning disk HDDs. 'random' disables hashing, instead assigning a UUID to models. Useful when using a memory db to reduce model installation time, or if you don't care about storing stable hashes for models. Alternatively, any other hashlib algorithm is accepted, though these are not nearly as performant as blake3.
Valid values: `blake3_multi`, `blake3_single`, `random`, `md5`, `sha1`, `sha224`, `sha256`, `sha384`, `sha512`, `blake2b`, `blake2s`, `sha3_224`, `sha3_256`, `sha3_384`, `sha3_512`, `shake_128`, `shake_256`\n remote_api_tokens: List of regular expression and token pairs used when downloading models from URLs. The download URL is tested against the regex, and if it matches, the token is provided in as a Bearer token.\n scan_models_on_startup: Scan the models directory on startup, registering orphaned models. This is typically only used in conjunction with `use_memory_db` for testing purposes.\n unsafe_disable_picklescan: UNSAFE. Disable the picklescan security check during model installation. Recommended only for development and testing purposes. This will allow arbitrary code execution during model installation, so should never be used in production.\n allow_unknown_models: Allow installation of models that we are unable to identify. If enabled, models will be marked as `unknown` in the database, and will not have any metadata associated with them. If disabled, unknown models will be rejected during installation." + "description": "Invoke's global app configuration.\n\nTypically, you won't need to interact with this class directly. Instead, use the `get_config` function from `invokeai.app.services.config` to get a singleton config object.\n\nAttributes:\n host: IP address to bind to. Use `0.0.0.0` to serve to your local network.\n port: Port to bind to.\n allow_origins: Allowed CORS origins.\n allow_credentials: Allow CORS credentials.\n allow_methods: Methods allowed for CORS.\n allow_headers: Headers allowed for CORS.\n ssl_certfile: SSL certificate file for HTTPS. See https://www.uvicorn.org/settings/#https.\n ssl_keyfile: SSL key file for HTTPS. See https://www.uvicorn.org/settings/#https.\n log_tokenization: Enable logging of parsed prompt tokens.\n patchmatch: Enable patchmatch inpaint code.\n models_dir: Path to the models directory.\n convert_cache_dir: Path to the converted models cache directory (DEPRECATED, but do not delete because it is needed for migration from previous versions).\n download_cache_dir: Path to the directory that contains dynamically downloaded models.\n legacy_conf_dir: Path to directory of legacy checkpoint config files.\n db_dir: Path to InvokeAI databases directory.\n outputs_dir: Path to directory for outputs.\n custom_nodes_dir: Path to directory for custom nodes.\n style_presets_dir: Path to directory for style presets.\n workflow_thumbnails_dir: Path to directory for workflow thumbnails.\n log_handlers: Log handler. Valid options are \"console\", \"file=\", \"syslog=path|address:host:port\", \"http=\".\n log_format: Log format. Use \"plain\" for text-only, \"color\" for colorized output, \"legacy\" for 2.3-style logging and \"syslog\" for syslog-style.
Valid values: `plain`, `color`, `syslog`, `legacy`\n log_level: Emit logging messages at this level or higher.
Valid values: `debug`, `info`, `warning`, `error`, `critical`\n log_sql: Log SQL queries. `log_level` must be `debug` for this to do anything. Extremely verbose.\n log_level_network: Log level for network-related messages. 'info' and 'debug' are very verbose.
Valid values: `debug`, `info`, `warning`, `error`, `critical`\n use_memory_db: Use in-memory database. Useful for development.\n dev_reload: Automatically reload when Python sources are changed. Does not reload node definitions.\n profile_graphs: Enable graph profiling using `cProfile`.\n profile_prefix: An optional prefix for profile output files.\n profiles_dir: Path to profiles output directory.\n max_cache_ram_gb: The maximum amount of CPU RAM to use for model caching in GB. If unset, the limit will be configured based on the available RAM. In most cases, it is recommended to leave this unset.\n max_cache_vram_gb: The amount of VRAM to use for model caching in GB. If unset, the limit will be configured based on the available VRAM and the device_working_mem_gb. In most cases, it is recommended to leave this unset.\n log_memory_usage: If True, a memory snapshot will be captured before and after every model cache operation, and the result will be logged (at debug level). There is a time cost to capturing the memory snapshots, so it is recommended to only enable this feature if you are actively inspecting the model cache's behaviour.\n model_cache_keep_alive_min: How long to keep models in cache after last use, in minutes. A value of 0 (the default) means models are kept in cache indefinitely. If no model generations occur within the timeout period, the model cache is cleared using the same logic as the 'Clear Model Cache' button.\n device_working_mem_gb: The amount of working memory to keep available on the compute device (in GB). Has no effect if running on CPU. If you are experiencing OOM errors, try increasing this value.\n enable_partial_loading: Enable partial loading of models. This enables models to run with reduced VRAM requirements (at the cost of slower speed) by streaming the model from RAM to VRAM as its used. In some edge cases, partial loading can cause models to run more slowly if they were previously being fully loaded into VRAM.\n keep_ram_copy_of_weights: Whether to keep a full RAM copy of a model's weights when the model is loaded in VRAM. Keeping a RAM copy increases average RAM usage, but speeds up model switching and LoRA patching (assuming there is sufficient RAM). Set this to False if RAM pressure is consistently high.\n ram: DEPRECATED: This setting is no longer used. It has been replaced by `max_cache_ram_gb`, but most users will not need to use this config since automatic cache size limits should work well in most cases. This config setting will be removed once the new model cache behavior is stable.\n vram: DEPRECATED: This setting is no longer used. It has been replaced by `max_cache_vram_gb`, but most users will not need to use this config since automatic cache size limits should work well in most cases. This config setting will be removed once the new model cache behavior is stable.\n lazy_offload: DEPRECATED: This setting is no longer used. Lazy-offloading is enabled by default. This config setting will be removed once the new model cache behavior is stable.\n pytorch_cuda_alloc_conf: Configure the Torch CUDA memory allocator. This will impact peak reserved VRAM usage and performance. Setting to \"backend:cudaMallocAsync\" works well on many systems. The optimal configuration is highly dependent on the system configuration (device type, VRAM, CUDA driver version, etc.), so must be tuned experimentally.\n device: Preferred execution device. `auto` will choose the device depending on the hardware platform and the installed torch capabilities.
Valid values: `auto`, `cpu`, `cuda`, `mps`, `cuda:N` (where N is a device number)\n precision: Floating point precision. `float16` will consume half the memory of `float32` but produce slightly lower-quality images. The `auto` setting will guess the proper precision based on your video card and operating system.
Valid values: `auto`, `float16`, `bfloat16`, `float32`\n sequential_guidance: Whether to calculate guidance in serial instead of in parallel, lowering memory requirements.\n attention_type: Attention type.
Valid values: `auto`, `normal`, `xformers`, `sliced`, `torch-sdp`\n attention_slice_size: Slice size, valid when attention_type==\"sliced\".
Valid values: `auto`, `balanced`, `max`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`\n force_tiled_decode: Whether to enable tiled VAE decode (reduces memory consumption with some performance penalty).\n pil_compress_level: The compress_level setting of PIL.Image.save(), used for PNG encoding. All settings are lossless. 0 = no compression, 1 = fastest with slightly larger filesize, 9 = slowest with smallest filesize. 1 is typically the best setting.\n max_queue_size: Maximum number of items in the session queue.\n clear_queue_on_startup: Empties session queue on startup.\n allow_nodes: List of nodes to allow. Omit to allow all.\n deny_nodes: List of nodes to deny. Omit to deny none.\n node_cache_size: How many cached nodes to keep in memory.\n hashing_algorithm: Model hashing algorthim for model installs. 'blake3_multi' is best for SSDs. 'blake3_single' is best for spinning disk HDDs. 'random' disables hashing, instead assigning a UUID to models. Useful when using a memory db to reduce model installation time, or if you don't care about storing stable hashes for models. Alternatively, any other hashlib algorithm is accepted, though these are not nearly as performant as blake3.
Valid values: `blake3_multi`, `blake3_single`, `random`, `md5`, `sha1`, `sha224`, `sha256`, `sha384`, `sha512`, `blake2b`, `blake2s`, `sha3_224`, `sha3_256`, `sha3_384`, `sha3_512`, `shake_128`, `shake_256`\n remote_api_tokens: List of regular expression and token pairs used when downloading models from URLs. The download URL is tested against the regex, and if it matches, the token is provided in as a Bearer token.\n scan_models_on_startup: Scan the models directory on startup, registering orphaned models. This is typically only used in conjunction with `use_memory_db` for testing purposes.\n unsafe_disable_picklescan: UNSAFE. Disable the picklescan security check during model installation. Recommended only for development and testing purposes. This will allow arbitrary code execution during model installation, so should never be used in production.\n allow_unknown_models: Allow installation of models that we are unable to identify. If enabled, models will be marked as `unknown` in the database, and will not have any metadata associated with them. If disabled, unknown models will be rejected during installation." }, "InvokeAIAppConfigWithSetFields": { "properties": { @@ -37443,6 +38763,162 @@ "title": "Main_Checkpoint_FLUX_Config", "description": "Model config for main checkpoint models." }, + "Main_Checkpoint_Flux2_Config": { + "properties": { + "key": { + "type": "string", + "title": "Key", + "description": "A unique key for this model." + }, + "hash": { + "type": "string", + "title": "Hash", + "description": "The hash of the model file(s)." + }, + "path": { + "type": "string", + "title": "Path", + "description": "Path to the model on the filesystem. Relative paths are relative to the Invoke root directory." + }, + "file_size": { + "type": "integer", + "title": "File Size", + "description": "The size of the model in bytes." + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the model." + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description", + "description": "Model description" + }, + "source": { + "type": "string", + "title": "Source", + "description": "The original source of the model (path, URL or repo_id)." + }, + "source_type": { + "$ref": "#/components/schemas/ModelSourceType", + "description": "The type of source" + }, + "source_api_response": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Api Response", + "description": "The original API response from the source, as stringified JSON." + }, + "cover_image": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cover Image", + "description": "Url for image to preview model" + }, + "type": { + "type": "string", + "const": "main", + "title": "Type", + "default": "main" + }, + "trigger_phrases": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + { + "type": "null" + } + ], + "title": "Trigger Phrases", + "description": "Set of trigger phrases for this model" + }, + "default_settings": { + "anyOf": [ + { + "$ref": "#/components/schemas/MainModelDefaultSettings" + }, + { + "type": "null" + } + ], + "description": "Default settings for this model" + }, + "config_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Config Path", + "description": "Path to the config for this model, if any." + }, + "format": { + "type": "string", + "const": "checkpoint", + "title": "Format", + "default": "checkpoint" + }, + "base": { + "type": "string", + "const": "flux2", + "title": "Base", + "default": "flux2" + }, + "variant": { + "$ref": "#/components/schemas/Flux2VariantType" + } + }, + "type": "object", + "required": [ + "key", + "hash", + "path", + "file_size", + "name", + "description", + "source", + "source_type", + "source_api_response", + "cover_image", + "type", + "trigger_phrases", + "default_settings", + "config_path", + "format", + "base", + "variant" + ], + "title": "Main_Checkpoint_Flux2_Config", + "description": "Model config for FLUX.2 checkpoint models (e.g. Klein)." + }, "Main_Checkpoint_SD1_Config": { "properties": { "key": { @@ -38079,6 +39555,158 @@ ], "title": "Main_Checkpoint_SDXL_Config" }, + "Main_Checkpoint_ZImage_Config": { + "properties": { + "key": { + "type": "string", + "title": "Key", + "description": "A unique key for this model." + }, + "hash": { + "type": "string", + "title": "Hash", + "description": "The hash of the model file(s)." + }, + "path": { + "type": "string", + "title": "Path", + "description": "Path to the model on the filesystem. Relative paths are relative to the Invoke root directory." + }, + "file_size": { + "type": "integer", + "title": "File Size", + "description": "The size of the model in bytes." + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the model." + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description", + "description": "Model description" + }, + "source": { + "type": "string", + "title": "Source", + "description": "The original source of the model (path, URL or repo_id)." + }, + "source_type": { + "$ref": "#/components/schemas/ModelSourceType", + "description": "The type of source" + }, + "source_api_response": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Api Response", + "description": "The original API response from the source, as stringified JSON." + }, + "cover_image": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cover Image", + "description": "Url for image to preview model" + }, + "type": { + "type": "string", + "const": "main", + "title": "Type", + "default": "main" + }, + "trigger_phrases": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + { + "type": "null" + } + ], + "title": "Trigger Phrases", + "description": "Set of trigger phrases for this model" + }, + "default_settings": { + "anyOf": [ + { + "$ref": "#/components/schemas/MainModelDefaultSettings" + }, + { + "type": "null" + } + ], + "description": "Default settings for this model" + }, + "config_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Config Path", + "description": "Path to the config for this model, if any." + }, + "base": { + "type": "string", + "const": "z-image", + "title": "Base", + "default": "z-image" + }, + "format": { + "type": "string", + "const": "checkpoint", + "title": "Format", + "default": "checkpoint" + } + }, + "type": "object", + "required": [ + "key", + "hash", + "path", + "file_size", + "name", + "description", + "source", + "source_type", + "source_api_response", + "cover_image", + "type", + "trigger_phrases", + "default_settings", + "config_path", + "base", + "format" + ], + "title": "Main_Checkpoint_ZImage_Config", + "description": "Model config for Z-Image single-file checkpoint models (safetensors, etc)." + }, "Main_Diffusers_CogView4_Config": { "properties": { "key": { @@ -38222,6 +39850,302 @@ ], "title": "Main_Diffusers_CogView4_Config" }, + "Main_Diffusers_FLUX_Config": { + "properties": { + "key": { + "type": "string", + "title": "Key", + "description": "A unique key for this model." + }, + "hash": { + "type": "string", + "title": "Hash", + "description": "The hash of the model file(s)." + }, + "path": { + "type": "string", + "title": "Path", + "description": "Path to the model on the filesystem. Relative paths are relative to the Invoke root directory." + }, + "file_size": { + "type": "integer", + "title": "File Size", + "description": "The size of the model in bytes." + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the model." + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description", + "description": "Model description" + }, + "source": { + "type": "string", + "title": "Source", + "description": "The original source of the model (path, URL or repo_id)." + }, + "source_type": { + "$ref": "#/components/schemas/ModelSourceType", + "description": "The type of source" + }, + "source_api_response": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Api Response", + "description": "The original API response from the source, as stringified JSON." + }, + "cover_image": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cover Image", + "description": "Url for image to preview model" + }, + "type": { + "type": "string", + "const": "main", + "title": "Type", + "default": "main" + }, + "trigger_phrases": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + { + "type": "null" + } + ], + "title": "Trigger Phrases", + "description": "Set of trigger phrases for this model" + }, + "default_settings": { + "anyOf": [ + { + "$ref": "#/components/schemas/MainModelDefaultSettings" + }, + { + "type": "null" + } + ], + "description": "Default settings for this model" + }, + "format": { + "type": "string", + "const": "diffusers", + "title": "Format", + "default": "diffusers" + }, + "repo_variant": { + "$ref": "#/components/schemas/ModelRepoVariant", + "default": "" + }, + "base": { + "type": "string", + "const": "flux", + "title": "Base", + "default": "flux" + }, + "variant": { + "$ref": "#/components/schemas/FluxVariantType" + } + }, + "type": "object", + "required": [ + "key", + "hash", + "path", + "file_size", + "name", + "description", + "source", + "source_type", + "source_api_response", + "cover_image", + "type", + "trigger_phrases", + "default_settings", + "format", + "repo_variant", + "base", + "variant" + ], + "title": "Main_Diffusers_FLUX_Config", + "description": "Model config for FLUX.1 models in diffusers format." + }, + "Main_Diffusers_Flux2_Config": { + "properties": { + "key": { + "type": "string", + "title": "Key", + "description": "A unique key for this model." + }, + "hash": { + "type": "string", + "title": "Hash", + "description": "The hash of the model file(s)." + }, + "path": { + "type": "string", + "title": "Path", + "description": "Path to the model on the filesystem. Relative paths are relative to the Invoke root directory." + }, + "file_size": { + "type": "integer", + "title": "File Size", + "description": "The size of the model in bytes." + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the model." + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description", + "description": "Model description" + }, + "source": { + "type": "string", + "title": "Source", + "description": "The original source of the model (path, URL or repo_id)." + }, + "source_type": { + "$ref": "#/components/schemas/ModelSourceType", + "description": "The type of source" + }, + "source_api_response": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Api Response", + "description": "The original API response from the source, as stringified JSON." + }, + "cover_image": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cover Image", + "description": "Url for image to preview model" + }, + "type": { + "type": "string", + "const": "main", + "title": "Type", + "default": "main" + }, + "trigger_phrases": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + { + "type": "null" + } + ], + "title": "Trigger Phrases", + "description": "Set of trigger phrases for this model" + }, + "default_settings": { + "anyOf": [ + { + "$ref": "#/components/schemas/MainModelDefaultSettings" + }, + { + "type": "null" + } + ], + "description": "Default settings for this model" + }, + "format": { + "type": "string", + "const": "diffusers", + "title": "Format", + "default": "diffusers" + }, + "repo_variant": { + "$ref": "#/components/schemas/ModelRepoVariant", + "default": "" + }, + "base": { + "type": "string", + "const": "flux2", + "title": "Base", + "default": "flux2" + }, + "variant": { + "$ref": "#/components/schemas/Flux2VariantType" + } + }, + "type": "object", + "required": [ + "key", + "hash", + "path", + "file_size", + "name", + "description", + "source", + "source_type", + "source_api_response", + "cover_image", + "type", + "trigger_phrases", + "default_settings", + "format", + "repo_variant", + "base", + "variant" + ], + "title": "Main_Diffusers_Flux2_Config", + "description": "Model config for FLUX.2 models in diffusers format (e.g. FLUX.2 Klein)." + }, "Main_Diffusers_SD1_Config": { "properties": { "key": { @@ -43198,6 +45122,12 @@ { "$ref": "#/components/schemas/Main_Diffusers_SD3_Config" }, + { + "$ref": "#/components/schemas/Main_Diffusers_FLUX_Config" + }, + { + "$ref": "#/components/schemas/Main_Diffusers_Flux2_Config" + }, { "$ref": "#/components/schemas/Main_Diffusers_CogView4_Config" }, @@ -43219,6 +45149,12 @@ { "$ref": "#/components/schemas/Main_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/Main_Checkpoint_Flux2_Config" + }, + { + "$ref": "#/components/schemas/Main_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/Main_BnBNF4_FLUX_Config" }, @@ -43240,6 +45176,9 @@ { "$ref": "#/components/schemas/VAE_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/VAE_Checkpoint_Flux2_Config" + }, { "$ref": "#/components/schemas/VAE_Diffusers_SD1_Config" }, @@ -43258,6 +45197,9 @@ { "$ref": "#/components/schemas/ControlNet_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/ControlNet_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/ControlNet_Diffusers_SD1_Config" }, @@ -43318,6 +45260,12 @@ { "$ref": "#/components/schemas/Qwen3Encoder_Qwen3Encoder_Config" }, + { + "$ref": "#/components/schemas/Qwen3Encoder_Checkpoint_Config" + }, + { + "$ref": "#/components/schemas/Qwen3Encoder_GGUF_Config" + }, { "$ref": "#/components/schemas/TI_File_SD1_Config" }, @@ -43682,6 +45630,12 @@ { "$ref": "#/components/schemas/Main_Diffusers_SD3_Config" }, + { + "$ref": "#/components/schemas/Main_Diffusers_FLUX_Config" + }, + { + "$ref": "#/components/schemas/Main_Diffusers_Flux2_Config" + }, { "$ref": "#/components/schemas/Main_Diffusers_CogView4_Config" }, @@ -43703,6 +45657,12 @@ { "$ref": "#/components/schemas/Main_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/Main_Checkpoint_Flux2_Config" + }, + { + "$ref": "#/components/schemas/Main_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/Main_BnBNF4_FLUX_Config" }, @@ -43724,6 +45684,9 @@ { "$ref": "#/components/schemas/VAE_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/VAE_Checkpoint_Flux2_Config" + }, { "$ref": "#/components/schemas/VAE_Diffusers_SD1_Config" }, @@ -43742,6 +45705,9 @@ { "$ref": "#/components/schemas/ControlNet_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/ControlNet_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/ControlNet_Diffusers_SD1_Config" }, @@ -43802,6 +45768,12 @@ { "$ref": "#/components/schemas/Qwen3Encoder_Qwen3Encoder_Config" }, + { + "$ref": "#/components/schemas/Qwen3Encoder_Checkpoint_Config" + }, + { + "$ref": "#/components/schemas/Qwen3Encoder_GGUF_Config" + }, { "$ref": "#/components/schemas/TI_File_SD1_Config" }, @@ -44059,6 +46031,12 @@ { "$ref": "#/components/schemas/Main_Diffusers_SD3_Config" }, + { + "$ref": "#/components/schemas/Main_Diffusers_FLUX_Config" + }, + { + "$ref": "#/components/schemas/Main_Diffusers_Flux2_Config" + }, { "$ref": "#/components/schemas/Main_Diffusers_CogView4_Config" }, @@ -44080,6 +46058,12 @@ { "$ref": "#/components/schemas/Main_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/Main_Checkpoint_Flux2_Config" + }, + { + "$ref": "#/components/schemas/Main_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/Main_BnBNF4_FLUX_Config" }, @@ -44101,6 +46085,9 @@ { "$ref": "#/components/schemas/VAE_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/VAE_Checkpoint_Flux2_Config" + }, { "$ref": "#/components/schemas/VAE_Diffusers_SD1_Config" }, @@ -44119,6 +46106,9 @@ { "$ref": "#/components/schemas/ControlNet_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/ControlNet_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/ControlNet_Diffusers_SD1_Config" }, @@ -44179,6 +46169,12 @@ { "$ref": "#/components/schemas/Qwen3Encoder_Qwen3Encoder_Config" }, + { + "$ref": "#/components/schemas/Qwen3Encoder_Checkpoint_Config" + }, + { + "$ref": "#/components/schemas/Qwen3Encoder_GGUF_Config" + }, { "$ref": "#/components/schemas/TI_File_SD1_Config" }, @@ -44294,6 +46290,12 @@ { "$ref": "#/components/schemas/Main_Diffusers_SD3_Config" }, + { + "$ref": "#/components/schemas/Main_Diffusers_FLUX_Config" + }, + { + "$ref": "#/components/schemas/Main_Diffusers_Flux2_Config" + }, { "$ref": "#/components/schemas/Main_Diffusers_CogView4_Config" }, @@ -44315,6 +46317,12 @@ { "$ref": "#/components/schemas/Main_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/Main_Checkpoint_Flux2_Config" + }, + { + "$ref": "#/components/schemas/Main_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/Main_BnBNF4_FLUX_Config" }, @@ -44336,6 +46344,9 @@ { "$ref": "#/components/schemas/VAE_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/VAE_Checkpoint_Flux2_Config" + }, { "$ref": "#/components/schemas/VAE_Diffusers_SD1_Config" }, @@ -44354,6 +46365,9 @@ { "$ref": "#/components/schemas/ControlNet_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/ControlNet_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/ControlNet_Diffusers_SD1_Config" }, @@ -44414,6 +46428,12 @@ { "$ref": "#/components/schemas/Qwen3Encoder_Qwen3Encoder_Config" }, + { + "$ref": "#/components/schemas/Qwen3Encoder_Checkpoint_Config" + }, + { + "$ref": "#/components/schemas/Qwen3Encoder_GGUF_Config" + }, { "$ref": "#/components/schemas/TI_File_SD1_Config" }, @@ -44728,6 +46748,12 @@ { "$ref": "#/components/schemas/FluxVariantType" }, + { + "$ref": "#/components/schemas/Flux2VariantType" + }, + { + "$ref": "#/components/schemas/Qwen3VariantType" + }, { "type": "null" } @@ -44895,6 +46921,12 @@ { "$ref": "#/components/schemas/Main_Diffusers_SD3_Config" }, + { + "$ref": "#/components/schemas/Main_Diffusers_FLUX_Config" + }, + { + "$ref": "#/components/schemas/Main_Diffusers_Flux2_Config" + }, { "$ref": "#/components/schemas/Main_Diffusers_CogView4_Config" }, @@ -44916,6 +46948,12 @@ { "$ref": "#/components/schemas/Main_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/Main_Checkpoint_Flux2_Config" + }, + { + "$ref": "#/components/schemas/Main_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/Main_BnBNF4_FLUX_Config" }, @@ -44937,6 +46975,9 @@ { "$ref": "#/components/schemas/VAE_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/VAE_Checkpoint_Flux2_Config" + }, { "$ref": "#/components/schemas/VAE_Diffusers_SD1_Config" }, @@ -44955,6 +46996,9 @@ { "$ref": "#/components/schemas/ControlNet_Checkpoint_FLUX_Config" }, + { + "$ref": "#/components/schemas/ControlNet_Checkpoint_ZImage_Config" + }, { "$ref": "#/components/schemas/ControlNet_Diffusers_SD1_Config" }, @@ -45015,6 +47059,12 @@ { "$ref": "#/components/schemas/Qwen3Encoder_Qwen3Encoder_Config" }, + { + "$ref": "#/components/schemas/Qwen3Encoder_Checkpoint_Config" + }, + { + "$ref": "#/components/schemas/Qwen3Encoder_GGUF_Config" + }, { "$ref": "#/components/schemas/TI_File_SD1_Config" }, @@ -45522,6 +47572,158 @@ "title": "OutputFieldJSONSchemaExtra", "type": "object" }, + "PBRMapsInvocation": { + "category": "image", + "class": "invocation", + "classification": "stable", + "description": "Generate Normal, Displacement and Roughness Map from a given image", + "node_pack": "invokeai", + "properties": { + "board": { + "anyOf": [ + { + "$ref": "#/components/schemas/BoardField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The board to save the image to", + "field_kind": "internal", + "input": "direct", + "orig_required": false, + "ui_hidden": false + }, + "metadata": { + "anyOf": [ + { + "$ref": "#/components/schemas/MetadataField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional metadata to be saved with the image", + "field_kind": "internal", + "input": "connection", + "orig_required": false, + "ui_hidden": false + }, + "id": { + "description": "The id of this instance of an invocation. Must be unique among all instances of invocations.", + "field_kind": "node_attribute", + "title": "Id", + "type": "string" + }, + "is_intermediate": { + "default": false, + "description": "Whether or not this is an intermediate invocation.", + "field_kind": "node_attribute", + "input": "direct", + "orig_required": true, + "title": "Is Intermediate", + "type": "boolean", + "ui_hidden": false, + "ui_type": "IsIntermediate" + }, + "use_cache": { + "default": true, + "description": "Whether or not to use the cache", + "field_kind": "node_attribute", + "title": "Use Cache", + "type": "boolean" + }, + "image": { + "anyOf": [ + { + "$ref": "#/components/schemas/ImageField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Input image", + "field_kind": "input", + "input": "any", + "orig_required": true + }, + "tile_size": { + "default": 512, + "description": "Tile size", + "field_kind": "input", + "input": "any", + "orig_default": 512, + "orig_required": false, + "title": "Tile Size", + "type": "integer" + }, + "border_mode": { + "default": "none", + "description": "Border mode to apply to eliminate any artifacts or seams", + "enum": ["none", "seamless", "mirror", "replicate"], + "field_kind": "input", + "input": "any", + "orig_default": "none", + "orig_required": false, + "title": "Border Mode", + "type": "string" + }, + "type": { + "const": "pbr_maps", + "default": "pbr_maps", + "field_kind": "node_attribute", + "title": "type", + "type": "string" + } + }, + "required": ["type", "id"], + "tags": ["image", "material"], + "title": "PBR Maps", + "type": "object", + "version": "1.0.0", + "output": { + "$ref": "#/components/schemas/PBRMapsOutput" + } + }, + "PBRMapsOutput": { + "class": "output", + "properties": { + "normal_map": { + "$ref": "#/components/schemas/ImageField", + "default": null, + "description": "The generated normal map", + "field_kind": "output", + "ui_hidden": false + }, + "roughness_map": { + "$ref": "#/components/schemas/ImageField", + "default": null, + "description": "The generated roughness map", + "field_kind": "output", + "ui_hidden": false + }, + "displacement_map": { + "$ref": "#/components/schemas/ImageField", + "default": null, + "description": "The generated displacement map", + "field_kind": "output", + "ui_hidden": false + }, + "type": { + "const": "pbr_maps-output", + "default": "pbr_maps-output", + "field_kind": "node_attribute", + "title": "type", + "type": "string" + } + }, + "required": ["output_meta", "normal_map", "roughness_map", "displacement_map", "type", "type"], + "title": "PBRMapsOutput", + "type": "object" + }, "PaginatedResults_WorkflowRecordListItemWithThumbnailDTO_": { "properties": { "page": { @@ -45944,6 +48146,121 @@ "title": "ProgressImage", "type": "object" }, + "PromptTemplateInvocation": { + "category": "prompt", + "class": "invocation", + "classification": "stable", + "description": "Applies a Style Preset template to positive and negative prompts.\n\nSelect a Style Preset and provide positive/negative prompts. The node replaces\n{prompt} placeholders in the template with your input prompts.", + "node_pack": "invokeai", + "properties": { + "id": { + "description": "The id of this instance of an invocation. Must be unique among all instances of invocations.", + "field_kind": "node_attribute", + "title": "Id", + "type": "string" + }, + "is_intermediate": { + "default": false, + "description": "Whether or not this is an intermediate invocation.", + "field_kind": "node_attribute", + "input": "direct", + "orig_required": true, + "title": "Is Intermediate", + "type": "boolean", + "ui_hidden": false, + "ui_type": "IsIntermediate" + }, + "use_cache": { + "default": true, + "description": "Whether or not to use the cache", + "field_kind": "node_attribute", + "title": "Use Cache", + "type": "boolean" + }, + "style_preset": { + "anyOf": [ + { + "$ref": "#/components/schemas/StylePresetField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The Style Preset to use as a template", + "field_kind": "input", + "input": "any", + "orig_required": true + }, + "positive_prompt": { + "default": "", + "description": "The positive prompt to insert into the template's {prompt} placeholder", + "field_kind": "input", + "input": "any", + "orig_default": "", + "orig_required": false, + "title": "Positive Prompt", + "type": "string", + "ui_component": "textarea" + }, + "negative_prompt": { + "default": "", + "description": "The negative prompt to insert into the template's {prompt} placeholder", + "field_kind": "input", + "input": "any", + "orig_default": "", + "orig_required": false, + "title": "Negative Prompt", + "type": "string", + "ui_component": "textarea" + }, + "type": { + "const": "prompt_template", + "default": "prompt_template", + "field_kind": "node_attribute", + "title": "type", + "type": "string" + } + }, + "required": ["type", "id"], + "tags": ["prompt", "template", "style", "preset"], + "title": "Prompt Template", + "type": "object", + "version": "1.0.0", + "output": { + "$ref": "#/components/schemas/PromptTemplateOutput" + } + }, + "PromptTemplateOutput": { + "class": "output", + "description": "Output for the Prompt Template node", + "properties": { + "positive_prompt": { + "description": "The positive prompt with the template applied", + "field_kind": "output", + "title": "Positive Prompt", + "type": "string", + "ui_hidden": false + }, + "negative_prompt": { + "description": "The negative prompt with the template applied", + "field_kind": "output", + "title": "Negative Prompt", + "type": "string", + "ui_hidden": false + }, + "type": { + "const": "prompt_template_output", + "default": "prompt_template_output", + "field_kind": "node_attribute", + "title": "type", + "type": "string" + } + }, + "required": ["output_meta", "positive_prompt", "negative_prompt", "type", "type"], + "title": "PromptTemplateOutput", + "type": "object" + }, "PromptsFromFileInvocation": { "category": "prompt", "class": "invocation", @@ -46313,6 +48630,262 @@ "title": "Qwen3EncoderField", "type": "object" }, + "Qwen3Encoder_Checkpoint_Config": { + "properties": { + "key": { + "type": "string", + "title": "Key", + "description": "A unique key for this model." + }, + "hash": { + "type": "string", + "title": "Hash", + "description": "The hash of the model file(s)." + }, + "path": { + "type": "string", + "title": "Path", + "description": "Path to the model on the filesystem. Relative paths are relative to the Invoke root directory." + }, + "file_size": { + "type": "integer", + "title": "File Size", + "description": "The size of the model in bytes." + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the model." + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description", + "description": "Model description" + }, + "source": { + "type": "string", + "title": "Source", + "description": "The original source of the model (path, URL or repo_id)." + }, + "source_type": { + "$ref": "#/components/schemas/ModelSourceType", + "description": "The type of source" + }, + "source_api_response": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Api Response", + "description": "The original API response from the source, as stringified JSON." + }, + "cover_image": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cover Image", + "description": "Url for image to preview model" + }, + "config_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Config Path", + "description": "Path to the config for this model, if any." + }, + "base": { + "type": "string", + "const": "any", + "title": "Base", + "default": "any" + }, + "type": { + "type": "string", + "const": "qwen3_encoder", + "title": "Type", + "default": "qwen3_encoder" + }, + "format": { + "type": "string", + "const": "checkpoint", + "title": "Format", + "default": "checkpoint" + }, + "variant": { + "$ref": "#/components/schemas/Qwen3VariantType", + "description": "Qwen3 model size variant (4B or 8B)" + } + }, + "type": "object", + "required": [ + "key", + "hash", + "path", + "file_size", + "name", + "description", + "source", + "source_type", + "source_api_response", + "cover_image", + "config_path", + "base", + "type", + "format", + "variant" + ], + "title": "Qwen3Encoder_Checkpoint_Config", + "description": "Configuration for single-file Qwen3 Encoder models (safetensors)." + }, + "Qwen3Encoder_GGUF_Config": { + "properties": { + "key": { + "type": "string", + "title": "Key", + "description": "A unique key for this model." + }, + "hash": { + "type": "string", + "title": "Hash", + "description": "The hash of the model file(s)." + }, + "path": { + "type": "string", + "title": "Path", + "description": "Path to the model on the filesystem. Relative paths are relative to the Invoke root directory." + }, + "file_size": { + "type": "integer", + "title": "File Size", + "description": "The size of the model in bytes." + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the model." + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description", + "description": "Model description" + }, + "source": { + "type": "string", + "title": "Source", + "description": "The original source of the model (path, URL or repo_id)." + }, + "source_type": { + "$ref": "#/components/schemas/ModelSourceType", + "description": "The type of source" + }, + "source_api_response": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Api Response", + "description": "The original API response from the source, as stringified JSON." + }, + "cover_image": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cover Image", + "description": "Url for image to preview model" + }, + "config_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Config Path", + "description": "Path to the config for this model, if any." + }, + "base": { + "type": "string", + "const": "any", + "title": "Base", + "default": "any" + }, + "type": { + "type": "string", + "const": "qwen3_encoder", + "title": "Type", + "default": "qwen3_encoder" + }, + "format": { + "type": "string", + "const": "gguf_quantized", + "title": "Format", + "default": "gguf_quantized" + }, + "variant": { + "$ref": "#/components/schemas/Qwen3VariantType", + "description": "Qwen3 model size variant (4B or 8B)" + } + }, + "type": "object", + "required": [ + "key", + "hash", + "path", + "file_size", + "name", + "description", + "source", + "source_type", + "source_api_response", + "cover_image", + "config_path", + "base", + "type", + "format", + "variant" + ], + "title": "Qwen3Encoder_GGUF_Config", + "description": "Configuration for GGUF-quantized Qwen3 Encoder models." + }, "Qwen3Encoder_Qwen3Encoder_Config": { "properties": { "key": { @@ -46402,6 +48975,10 @@ "const": "qwen3_encoder", "title": "Format", "default": "qwen3_encoder" + }, + "variant": { + "$ref": "#/components/schemas/Qwen3VariantType", + "description": "Qwen3 model size variant (4B or 8B)" } }, "type": "object", @@ -46418,11 +48995,18 @@ "cover_image", "base", "type", - "format" + "format", + "variant" ], "title": "Qwen3Encoder_Qwen3Encoder_Config", "description": "Configuration for Qwen3 Encoder models in a diffusers-like format.\n\nThe model weights are expected to be in a folder called text_encoder inside the model directory,\ncompatible with Qwen2VLForConditionalGeneration or similar architectures used by Z-Image." }, + "Qwen3VariantType": { + "type": "string", + "enum": ["qwen3_4b", "qwen3_8b"], + "title": "Qwen3VariantType", + "description": "Qwen3 text encoder variants based on model size." + }, "RandomFloatInvocation": { "category": "math", "class": "invocation", @@ -51440,6 +54024,19 @@ "$ref": "#/components/schemas/StringPosNegOutput" } }, + "StylePresetField": { + "description": "A style preset primitive field", + "properties": { + "style_preset_id": { + "description": "The id of the style preset", + "title": "Style Preset Id", + "type": "string" + } + }, + "required": ["style_preset_id"], + "title": "StylePresetField", + "type": "object" + }, "StylePresetRecordWithImage": { "properties": { "name": { @@ -51517,6 +54114,12 @@ { "$ref": "#/components/schemas/FluxVariantType" }, + { + "$ref": "#/components/schemas/Flux2VariantType" + }, + { + "$ref": "#/components/schemas/Qwen3VariantType" + }, { "type": "null" } @@ -54142,7 +56745,7 @@ "input": "any", "orig_required": true, "title": "VAE", - "ui_model_base": ["sd-1", "sd-2", "sdxl", "sd-3", "flux"], + "ui_model_base": ["sd-1", "sd-2", "sdxl", "sd-3", "flux", "flux2"], "ui_model_type": ["vae"] }, "type": { @@ -54307,6 +56910,129 @@ ], "title": "VAE_Checkpoint_FLUX_Config" }, + "VAE_Checkpoint_Flux2_Config": { + "properties": { + "key": { + "type": "string", + "title": "Key", + "description": "A unique key for this model." + }, + "hash": { + "type": "string", + "title": "Hash", + "description": "The hash of the model file(s)." + }, + "path": { + "type": "string", + "title": "Path", + "description": "Path to the model on the filesystem. Relative paths are relative to the Invoke root directory." + }, + "file_size": { + "type": "integer", + "title": "File Size", + "description": "The size of the model in bytes." + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the model." + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description", + "description": "Model description" + }, + "source": { + "type": "string", + "title": "Source", + "description": "The original source of the model (path, URL or repo_id)." + }, + "source_type": { + "$ref": "#/components/schemas/ModelSourceType", + "description": "The type of source" + }, + "source_api_response": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Api Response", + "description": "The original API response from the source, as stringified JSON." + }, + "cover_image": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cover Image", + "description": "Url for image to preview model" + }, + "config_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Config Path", + "description": "Path to the config for this model, if any." + }, + "type": { + "type": "string", + "const": "vae", + "title": "Type", + "default": "vae" + }, + "format": { + "type": "string", + "const": "checkpoint", + "title": "Format", + "default": "checkpoint" + }, + "base": { + "type": "string", + "const": "flux2", + "title": "Base", + "default": "flux2" + } + }, + "type": "object", + "required": [ + "key", + "hash", + "path", + "file_size", + "name", + "description", + "source", + "source_type", + "source_api_response", + "cover_image", + "config_path", + "type", + "format", + "base" + ], + "title": "VAE_Checkpoint_Flux2_Config", + "description": "Model config for FLUX.2 VAE checkpoint models (AutoencoderKLFlux2)." + }, "VAE_Checkpoint_SD1_Config": { "properties": { "key": { @@ -55470,6 +58196,186 @@ "title": "ZImageConditioningOutput", "type": "object" }, + "ZImageControlField": { + "description": "A Z-Image control conditioning field for spatial control (Canny, HED, Depth, Pose, MLSD).", + "properties": { + "image_name": { + "description": "The name of the preprocessed control image", + "title": "Image Name", + "type": "string" + }, + "control_model": { + "$ref": "#/components/schemas/ModelIdentifierField", + "description": "The Z-Image ControlNet adapter model" + }, + "control_context_scale": { + "default": 0.75, + "description": "The strength of the control signal. Recommended range: 0.65-0.80.", + "maximum": 2.0, + "minimum": 0.0, + "title": "Control Context Scale", + "type": "number" + }, + "begin_step_percent": { + "default": 0.0, + "description": "When the control is first applied (% of total steps)", + "maximum": 1.0, + "minimum": 0.0, + "title": "Begin Step Percent", + "type": "number" + }, + "end_step_percent": { + "default": 1.0, + "description": "When the control is last applied (% of total steps)", + "maximum": 1.0, + "minimum": 0.0, + "title": "End Step Percent", + "type": "number" + } + }, + "required": ["image_name", "control_model"], + "title": "ZImageControlField", + "type": "object" + }, + "ZImageControlInvocation": { + "category": "control", + "class": "invocation", + "classification": "prototype", + "description": "Configure Z-Image ControlNet for spatial conditioning.\n\nTakes a preprocessed control image (e.g., Canny edges, depth map, pose)\nand a Z-Image ControlNet adapter model to enable spatial control.\n\nSupports 5 control modes: Canny, HED, Depth, Pose, MLSD.\nRecommended control_context_scale: 0.65-0.80.", + "node_pack": "invokeai", + "properties": { + "id": { + "description": "The id of this instance of an invocation. Must be unique among all instances of invocations.", + "field_kind": "node_attribute", + "title": "Id", + "type": "string" + }, + "is_intermediate": { + "default": false, + "description": "Whether or not this is an intermediate invocation.", + "field_kind": "node_attribute", + "input": "direct", + "orig_required": true, + "title": "Is Intermediate", + "type": "boolean", + "ui_hidden": false, + "ui_type": "IsIntermediate" + }, + "use_cache": { + "default": true, + "description": "Whether or not to use the cache", + "field_kind": "node_attribute", + "title": "Use Cache", + "type": "boolean" + }, + "image": { + "anyOf": [ + { + "$ref": "#/components/schemas/ImageField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The preprocessed control image (Canny, HED, Depth, Pose, or MLSD)", + "field_kind": "input", + "input": "any", + "orig_required": true + }, + "control_model": { + "anyOf": [ + { + "$ref": "#/components/schemas/ModelIdentifierField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "ControlNet model to load", + "field_kind": "input", + "input": "any", + "orig_required": true, + "title": "Control Model", + "ui_model_base": ["z-image"], + "ui_model_type": ["controlnet"] + }, + "control_context_scale": { + "default": 0.75, + "description": "Strength of the control signal. Recommended range: 0.65-0.80.", + "field_kind": "input", + "input": "any", + "maximum": 2.0, + "minimum": 0.0, + "orig_default": 0.75, + "orig_required": false, + "title": "Control Scale", + "type": "number" + }, + "begin_step_percent": { + "default": 0.0, + "description": "When the control is first applied (% of total steps)", + "field_kind": "input", + "input": "any", + "maximum": 1.0, + "minimum": 0.0, + "orig_default": 0.0, + "orig_required": false, + "title": "Begin Step Percent", + "type": "number" + }, + "end_step_percent": { + "default": 1.0, + "description": "When the control is last applied (% of total steps)", + "field_kind": "input", + "input": "any", + "maximum": 1.0, + "minimum": 0.0, + "orig_default": 1.0, + "orig_required": false, + "title": "End Step Percent", + "type": "number" + }, + "type": { + "const": "z_image_control", + "default": "z_image_control", + "field_kind": "node_attribute", + "title": "type", + "type": "string" + } + }, + "required": ["type", "id"], + "tags": ["image", "z-image", "control", "controlnet"], + "title": "Z-Image ControlNet", + "type": "object", + "version": "1.1.0", + "output": { + "$ref": "#/components/schemas/ZImageControlOutput" + } + }, + "ZImageControlOutput": { + "class": "output", + "description": "Z-Image Control output containing control configuration.", + "properties": { + "control": { + "$ref": "#/components/schemas/ZImageControlField", + "description": "Z-Image control conditioning", + "field_kind": "output", + "ui_hidden": false + }, + "type": { + "const": "z_image_control_output", + "default": "z_image_control_output", + "field_kind": "node_attribute", + "title": "type", + "type": "string" + } + }, + "required": ["output_meta", "control", "type", "type"], + "title": "ZImageControlOutput", + "type": "object" + }, "ZImageDenoiseInvocation": { "category": "image", "class": "invocation", @@ -55477,22 +58383,283 @@ "description": "Run the denoising process with a Z-Image model.\n\nSupports regional prompting by connecting multiple conditioning inputs with masks.", "node_pack": "invokeai", "properties": { - "board": { + "id": { + "description": "The id of this instance of an invocation. Must be unique among all instances of invocations.", + "field_kind": "node_attribute", + "title": "Id", + "type": "string" + }, + "is_intermediate": { + "default": false, + "description": "Whether or not this is an intermediate invocation.", + "field_kind": "node_attribute", + "input": "direct", + "orig_required": true, + "title": "Is Intermediate", + "type": "boolean", + "ui_hidden": false, + "ui_type": "IsIntermediate" + }, + "use_cache": { + "default": true, + "description": "Whether or not to use the cache", + "field_kind": "node_attribute", + "title": "Use Cache", + "type": "boolean" + }, + "latents": { "anyOf": [ { - "$ref": "#/components/schemas/BoardField" + "$ref": "#/components/schemas/LatentsField" }, { "type": "null" } ], "default": null, - "description": "The board to save the image to", - "field_kind": "internal", - "input": "direct", - "orig_required": false, - "ui_hidden": false + "description": "Latents tensor", + "field_kind": "input", + "input": "connection", + "orig_default": null, + "orig_required": false }, + "denoise_mask": { + "anyOf": [ + { + "$ref": "#/components/schemas/DenoiseMaskField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "A mask of the region to apply the denoising process to. Values of 0.0 represent the regions to be fully denoised, and 1.0 represent the regions to be preserved.", + "field_kind": "input", + "input": "connection", + "orig_default": null, + "orig_required": false + }, + "denoising_start": { + "default": 0.0, + "description": "When to start denoising, expressed a percentage of total steps", + "field_kind": "input", + "input": "any", + "maximum": 1, + "minimum": 0, + "orig_default": 0.0, + "orig_required": false, + "title": "Denoising Start", + "type": "number" + }, + "denoising_end": { + "default": 1.0, + "description": "When to stop denoising, expressed a percentage of total steps", + "field_kind": "input", + "input": "any", + "maximum": 1, + "minimum": 0, + "orig_default": 1.0, + "orig_required": false, + "title": "Denoising End", + "type": "number" + }, + "add_noise": { + "default": true, + "description": "Add noise based on denoising start.", + "field_kind": "input", + "input": "any", + "orig_default": true, + "orig_required": false, + "title": "Add Noise", + "type": "boolean" + }, + "transformer": { + "anyOf": [ + { + "$ref": "#/components/schemas/TransformerField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Z-Image model (Transformer) to load", + "field_kind": "input", + "input": "connection", + "orig_required": true, + "title": "Transformer" + }, + "positive_conditioning": { + "anyOf": [ + { + "$ref": "#/components/schemas/ZImageConditioningField" + }, + { + "items": { + "$ref": "#/components/schemas/ZImageConditioningField" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Positive conditioning tensor", + "field_kind": "input", + "input": "connection", + "orig_required": true, + "title": "Positive Conditioning" + }, + "negative_conditioning": { + "anyOf": [ + { + "$ref": "#/components/schemas/ZImageConditioningField" + }, + { + "items": { + "$ref": "#/components/schemas/ZImageConditioningField" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Negative conditioning tensor", + "field_kind": "input", + "input": "connection", + "orig_default": null, + "orig_required": false, + "title": "Negative Conditioning" + }, + "guidance_scale": { + "default": 1.0, + "description": "Guidance scale for classifier-free guidance. 1.0 = no CFG (recommended for Z-Image-Turbo). Values > 1.0 amplify guidance.", + "field_kind": "input", + "input": "any", + "minimum": 1.0, + "orig_default": 1.0, + "orig_required": false, + "title": "Guidance Scale", + "type": "number" + }, + "width": { + "default": 1024, + "description": "Width of the generated image.", + "field_kind": "input", + "input": "any", + "multipleOf": 16, + "orig_default": 1024, + "orig_required": false, + "title": "Width", + "type": "integer" + }, + "height": { + "default": 1024, + "description": "Height of the generated image.", + "field_kind": "input", + "input": "any", + "multipleOf": 16, + "orig_default": 1024, + "orig_required": false, + "title": "Height", + "type": "integer" + }, + "steps": { + "default": 8, + "description": "Number of denoising steps. 8 recommended for Z-Image-Turbo.", + "exclusiveMinimum": 0, + "field_kind": "input", + "input": "any", + "orig_default": 8, + "orig_required": false, + "title": "Steps", + "type": "integer" + }, + "seed": { + "default": 0, + "description": "Randomness seed for reproducibility.", + "field_kind": "input", + "input": "any", + "orig_default": 0, + "orig_required": false, + "title": "Seed", + "type": "integer" + }, + "control": { + "anyOf": [ + { + "$ref": "#/components/schemas/ZImageControlField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Z-Image control conditioning for spatial control (Canny, HED, Depth, Pose, MLSD).", + "field_kind": "input", + "input": "connection", + "orig_default": null, + "orig_required": false + }, + "vae": { + "anyOf": [ + { + "$ref": "#/components/schemas/VAEField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "VAE Required for control conditioning.", + "field_kind": "input", + "input": "connection", + "orig_default": null, + "orig_required": false + }, + "scheduler": { + "default": "euler", + "description": "Scheduler (sampler) for the denoising process. Euler is the default and recommended for Z-Image-Turbo. Heun is 2nd-order (better quality, 2x slower). LCM is optimized for few steps.", + "enum": ["euler", "heun", "lcm"], + "field_kind": "input", + "input": "any", + "orig_default": "euler", + "orig_required": false, + "title": "Scheduler", + "type": "string", + "ui_choice_labels": { + "euler": "Euler", + "heun": "Heun (2nd order)", + "lcm": "LCM" + } + }, + "type": { + "const": "z_image_denoise", + "default": "z_image_denoise", + "field_kind": "node_attribute", + "title": "type", + "type": "string" + } + }, + "required": ["type", "id"], + "tags": ["image", "z-image"], + "title": "Denoise - Z-Image", + "type": "object", + "version": "1.4.0", + "output": { + "$ref": "#/components/schemas/LatentsOutput" + } + }, + "ZImageDenoiseMetaInvocation": { + "category": "latents", + "class": "invocation", + "classification": "stable", + "description": "Run denoising process with a Z-Image transformer model + metadata.", + "node_pack": "invokeai", + "properties": { "metadata": { "anyOf": [ { @@ -55589,6 +58756,16 @@ "title": "Denoising End", "type": "number" }, + "add_noise": { + "default": true, + "description": "Add noise based on denoising start.", + "field_kind": "input", + "input": "any", + "orig_default": true, + "orig_required": false, + "title": "Add Noise", + "type": "boolean" + }, "transformer": { "anyOf": [ { @@ -55651,12 +58828,12 @@ "title": "Negative Conditioning" }, "guidance_scale": { - "default": 0.0, - "description": "Guidance scale for classifier-free guidance. Use 0.0 for Z-Image-Turbo.", + "default": 1.0, + "description": "Guidance scale for classifier-free guidance. 1.0 = no CFG (recommended for Z-Image-Turbo). Values > 1.0 amplify guidance.", "field_kind": "input", "input": "any", - "minimum": 0.0, - "orig_default": 0.0, + "minimum": 1.0, + "orig_default": 1.0, "orig_required": false, "title": "Guidance Scale", "type": "number" @@ -55704,21 +58881,69 @@ "title": "Seed", "type": "integer" }, + "control": { + "anyOf": [ + { + "$ref": "#/components/schemas/ZImageControlField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Z-Image control conditioning for spatial control (Canny, HED, Depth, Pose, MLSD).", + "field_kind": "input", + "input": "connection", + "orig_default": null, + "orig_required": false + }, + "vae": { + "anyOf": [ + { + "$ref": "#/components/schemas/VAEField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "VAE Required for control conditioning.", + "field_kind": "input", + "input": "connection", + "orig_default": null, + "orig_required": false + }, + "scheduler": { + "default": "euler", + "description": "Scheduler (sampler) for the denoising process. Euler is the default and recommended for Z-Image-Turbo. Heun is 2nd-order (better quality, 2x slower). LCM is optimized for few steps.", + "enum": ["euler", "heun", "lcm"], + "field_kind": "input", + "input": "any", + "orig_default": "euler", + "orig_required": false, + "title": "Scheduler", + "type": "string", + "ui_choice_labels": { + "euler": "Euler", + "heun": "Heun (2nd order)", + "lcm": "LCM" + } + }, "type": { - "const": "z_image_denoise", - "default": "z_image_denoise", + "const": "z_image_denoise_meta", + "default": "z_image_denoise_meta", "field_kind": "node_attribute", "title": "type", "type": "string" } }, "required": ["type", "id"], - "tags": ["image", "z-image"], - "title": "Denoise - Z-Image", + "tags": ["z-image", "latents", "denoise", "txt2img", "t2i", "t2l", "img2img", "i2i", "l2l"], + "title": "Denoise - Z-Image + Metadata", "type": "object", - "version": "1.2.0", + "version": "1.0.0", "output": { - "$ref": "#/components/schemas/LatentsOutput" + "$ref": "#/components/schemas/LatentsMetaOutput" } }, "ZImageImageToLatentsInvocation": { @@ -56354,6 +59579,105 @@ "title": "ZImageModelLoaderOutput", "type": "object" }, + "ZImageSeedVarianceEnhancerInvocation": { + "category": "conditioning", + "class": "invocation", + "classification": "prototype", + "description": "Adds seed-based noise to Z-Image conditioning to increase variance between seeds.\n\nZ-Image-Turbo can produce relatively similar images with different seeds,\nmaking it harder to explore variations of a prompt. This node implements\nreproducible, seed-based noise injection into text embeddings to increase\nvisual variation while maintaining reproducibility.\n\nThe noise strength is auto-calibrated relative to the embedding's standard\ndeviation, ensuring consistent results across different prompts.", + "node_pack": "invokeai", + "properties": { + "id": { + "description": "The id of this instance of an invocation. Must be unique among all instances of invocations.", + "field_kind": "node_attribute", + "title": "Id", + "type": "string" + }, + "is_intermediate": { + "default": false, + "description": "Whether or not this is an intermediate invocation.", + "field_kind": "node_attribute", + "input": "direct", + "orig_required": true, + "title": "Is Intermediate", + "type": "boolean", + "ui_hidden": false, + "ui_type": "IsIntermediate" + }, + "use_cache": { + "default": true, + "description": "Whether or not to use the cache", + "field_kind": "node_attribute", + "title": "Use Cache", + "type": "boolean" + }, + "conditioning": { + "anyOf": [ + { + "$ref": "#/components/schemas/ZImageConditioningField" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Conditioning tensor", + "field_kind": "input", + "input": "connection", + "orig_required": true, + "title": "Conditioning" + }, + "seed": { + "default": 0, + "description": "Seed for reproducible noise generation. Different seeds produce different noise patterns.", + "field_kind": "input", + "input": "any", + "minimum": 0, + "orig_default": 0, + "orig_required": false, + "title": "Seed", + "type": "integer" + }, + "strength": { + "default": 0.1, + "description": "Noise strength as multiplier of embedding std. 0=off, 0.1=subtle, 0.5=strong.", + "field_kind": "input", + "input": "any", + "maximum": 2.0, + "minimum": 0.0, + "orig_default": 0.1, + "orig_required": false, + "title": "Strength", + "type": "number" + }, + "randomize_percent": { + "default": 50.0, + "description": "Percentage of embedding values to add noise to (1-100). Lower values create more selective noise patterns.", + "field_kind": "input", + "input": "any", + "maximum": 100.0, + "minimum": 1.0, + "orig_default": 50.0, + "orig_required": false, + "title": "Randomize Percent", + "type": "number" + }, + "type": { + "const": "z_image_seed_variance_enhancer", + "default": "z_image_seed_variance_enhancer", + "field_kind": "node_attribute", + "title": "type", + "type": "string" + } + }, + "required": ["type", "id"], + "tags": ["conditioning", "z-image", "variance", "seed"], + "title": "Seed Variance Enhancer - Z-Image", + "type": "object", + "version": "1.0.0", + "output": { + "$ref": "#/components/schemas/ZImageConditioningOutput" + } + }, "ZImageTextEncoderInvocation": { "category": "conditioning", "class": "invocation", diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index 5bdd7ba08e..ed825c1076 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -1057,6 +1057,10 @@ "zImageQwen3EncoderPlaceholder": "From Qwen3 source model", "zImageQwen3Source": "Qwen3 & VAE Source Model", "zImageQwen3SourcePlaceholder": "Required if VAE/Encoder empty", + "flux2KleinVae": "VAE (optional)", + "flux2KleinVaePlaceholder": "From main model", + "flux2KleinQwen3Encoder": "Qwen3 Encoder (optional)", + "flux2KleinQwen3EncoderPlaceholder": "From main model", "upcastAttention": "Upcast Attention", "uploadImage": "Upload Image", "urlOrLocalPath": "URL or Local Path", @@ -1338,6 +1342,7 @@ "noT5EncoderModelSelected": "No T5 Encoder model selected for FLUX generation", "noFLUXVAEModelSelected": "No VAE model selected for FLUX generation", "noCLIPEmbedModelSelected": "No CLIP Embed model selected for FLUX generation", + "noQwen3EncoderModelSelected": "No Qwen3 Encoder model selected for FLUX2 Klein generation", "noZImageVaeSourceSelected": "No VAE source: Select VAE (FLUX) or Qwen3 Source model", "noZImageQwen3EncoderSourceSelected": "No Qwen3 Encoder source: Select Qwen3 Encoder or Qwen3 Source model", "fluxModelIncompatibleBboxWidth": "$t(parameters.invoke.fluxRequiresDimensionsToBeMultipleOf16), bbox width is {{width}}", @@ -1486,6 +1491,8 @@ "baseModelChanged": "Base Model Changed", "baseModelChangedCleared_one": "Updated, cleared or disabled {{count}} incompatible submodel", "baseModelChangedCleared_other": "Updated, cleared or disabled {{count}} incompatible submodels", + "kleinEncoderCleared": "Qwen3 Encoder Cleared", + "kleinEncoderClearedDescription": "Please select a compatible Qwen3 encoder for the new Klein model variant", "canceled": "Processing Canceled", "connected": "Connected to Server", "imageCopied": "Image Copied", @@ -1989,7 +1996,7 @@ "fluxDevLicense": { "heading": "Non-Commercial License", "paragraphs": [ - "FLUX.1 [dev] models are licensed under the FLUX [dev] non-commercial license. To use this model type for commercial purposes in Invoke, visit our website to learn more." + "This model is licensed for non-commercial use only. FLUX.1 [dev] models use the FLUX.1 [dev] Non-Commercial License, and FLUX.2 Klein 9B uses the FLUX.2 Non-Commercial License." ] }, "optimizedDenoising": { @@ -2858,6 +2865,7 @@ "whatsNew": { "whatsNewInInvoke": "What's New in Invoke", "items": [ + "FLUX.2 Klein Support: InvokeAI now supports the new FLUX.2 Klein models (4B and 9B variants) with GGUF, FP8, and Diffusers formats. Features include txt2img, img2img, inpainting, and outpainting. See 'Starter Models' to get started.", "Support for Z-Image-Turbo: InvokeAI now supports the fast and accurate Z-Image-Turbo model. See 'Starter Models' to get started.", "Hotkeys: Add and edit keyboard shortcuts for any of Invoke's major functions.", "Model Manager: The Model Manager user interface now supports bulk tagging and deletion." diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts index 69745ed1d4..cdafc2e8d9 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts @@ -4,6 +4,8 @@ import { bboxSyncedToOptimalDimension, rgRefImageModelChanged } from 'features/c import { buildSelectIsStaging, selectCanvasSessionId } from 'features/controlLayers/store/canvasStagingAreaSlice'; import { loraIsEnabledChanged } from 'features/controlLayers/store/lorasSlice'; import { + kleinQwen3EncoderModelSelected, + kleinVaeModelSelected, modelChanged, syncedToOptimalDimension, vaeSelected, @@ -23,6 +25,7 @@ import { modelSelected } from 'features/parameters/store/actions'; import { zParameterModel } from 'features/parameters/types/parameterSchemas'; import { toast } from 'features/toast/toast'; import { t } from 'i18next'; +import { modelConfigsAdapterSelectors, selectModelConfigsQuery } from 'services/api/endpoints/models'; import { selectFluxVAEModels, selectGlobalRefImageModels, @@ -140,6 +143,19 @@ export const addModelSelectedListener = (startAppListening: AppStartListening) = } } + // handle incompatible FLUX.2 Klein models - clear if switching away from flux2 + const { kleinVaeModel, kleinQwen3EncoderModel } = state.params; + if (newBase !== 'flux2') { + if (kleinVaeModel) { + dispatch(kleinVaeModelSelected(null)); + modelsUpdatedDisabledOrCleared += 1; + } + if (kleinQwen3EncoderModel) { + dispatch(kleinQwen3EncoderModelSelected(null)); + modelsUpdatedDisabledOrCleared += 1; + } + } + if (SUPPORTS_REF_IMAGES_BASE_MODELS.includes(newModel.base)) { // Handle incompatible reference image models - switch to first compatible model, with some smart logic // to choose the best available model based on the new main model. @@ -168,6 +184,11 @@ export const addModelSelectedListener = (startAppListening: AppStartListening) = // All ref image entities are updated to use the same new model const refImageEntities = selectReferenceImageEntities(state); for (const entity of refImageEntities) { + // Skip FLUX.2 reference images - they don't have a model field (built-in support) + if (!('model' in entity.config)) { + continue; + } + const shouldUpdateModel = (entity.config.model && entity.config.model.base !== newBase) || (!entity.config.model && newGlobalRefImageModel); @@ -222,6 +243,38 @@ export const addModelSelectedListener = (startAppListening: AppStartListening) = } } + // Handle FLUX.2 Klein model changes within the same base (different variants need different encoders) + // Clear the Qwen3 encoder only when switching between different Klein variants + // (e.g., klein_4b needs qwen3_4b, klein_9b needs qwen3_8b) + if (newBase === 'flux2' && state.params.model?.base === 'flux2' && newModel.key !== state.params.model?.key) { + const { kleinQwen3EncoderModel } = state.params; + if (kleinQwen3EncoderModel) { + // Get model configs to compare variants + const modelConfigsResult = selectModelConfigsQuery(state); + if (modelConfigsResult.data) { + const oldModelConfig = modelConfigsAdapterSelectors.selectById( + modelConfigsResult.data, + state.params.model.key + ); + const newModelConfig = modelConfigsAdapterSelectors.selectById(modelConfigsResult.data, newModel.key); + + // Extract variants (only clear if variants are different) + const oldVariant = oldModelConfig && 'variant' in oldModelConfig ? oldModelConfig.variant : null; + const newVariant = newModelConfig && 'variant' in newModelConfig ? newModelConfig.variant : null; + + if (oldVariant !== newVariant) { + dispatch(kleinQwen3EncoderModelSelected(null)); + toast({ + id: 'KLEIN_ENCODER_CLEARED', + title: t('toast.kleinEncoderCleared'), + description: t('toast.kleinEncoderClearedDescription'), + status: 'info', + }); + } + } + } + } + dispatch(modelChanged({ model: newModel, previousModel: state.params.model })); const modelBase = selectBboxModelBase(state); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RefImage/RefImageSettings.tsx b/invokeai/frontend/web/src/features/controlLayers/components/RefImage/RefImageSettings.tsx index 0c9153f16f..babfd79968 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/RefImage/RefImageSettings.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/RefImage/RefImageSettings.tsx @@ -34,7 +34,7 @@ import type { FLUXReduxImageInfluence as FLUXReduxImageInfluenceType, IPMethodV2, } from 'features/controlLayers/store/types'; -import { isFLUXReduxConfig, isIPAdapterConfig } from 'features/controlLayers/store/types'; +import { isFlux2ReferenceImageConfig, isFLUXReduxConfig, isIPAdapterConfig } from 'features/controlLayers/store/types'; import type { SetGlobalReferenceImageDndTargetData } from 'features/dnd/dnd'; import { setGlobalReferenceImageDndTarget } from 'features/dnd/dnd'; import { selectActiveTab } from 'features/ui/store/uiSelectors'; @@ -121,19 +121,34 @@ const RefImageSettingsContent = memo(() => { const isFLUX = useAppSelector(selectIsFLUX); + // FLUX.2 Klein has built-in reference image support - no model selector needed + const showModelSelector = !isFlux2ReferenceImageConfig(config); + return ( - - - {isIPAdapterConfig(config) && ( - - )} - {tab === 'canvas' && ( + {showModelSelector && ( + + + {isIPAdapterConfig(config) && ( + + )} + {tab === 'canvas' && ( + + + + )} + + )} + {!showModelSelector && tab === 'canvas' && ( + - )} - + + )} {isIPAdapterConfig(config) && ( diff --git a/invokeai/frontend/web/src/features/controlLayers/hooks/addLayerHooks.ts b/invokeai/frontend/web/src/features/controlLayers/hooks/addLayerHooks.ts index fe23ec9d90..038af19603 100644 --- a/invokeai/frontend/web/src/features/controlLayers/hooks/addLayerHooks.ts +++ b/invokeai/frontend/web/src/features/controlLayers/hooks/addLayerHooks.ts @@ -26,6 +26,7 @@ import type { CanvasRegionalGuidanceState, ControlLoRAConfig, ControlNetConfig, + Flux2ReferenceImageConfig, FluxKontextReferenceImageConfig, IPAdapterConfig, RegionalGuidanceIPAdapterConfig, @@ -33,6 +34,7 @@ import type { } from 'features/controlLayers/store/types'; import { initialControlNet, + initialFlux2ReferenceImage, initialFluxKontextReferenceImage, initialIPAdapter, initialRegionalGuidanceIPAdapter, @@ -74,7 +76,9 @@ export const selectDefaultControlAdapter = createSelector( } ); -export const getDefaultRefImageConfig = (getState: AppGetState): IPAdapterConfig | FluxKontextReferenceImageConfig => { +export const getDefaultRefImageConfig = ( + getState: AppGetState +): IPAdapterConfig | FluxKontextReferenceImageConfig | Flux2ReferenceImageConfig => { const state = getState(); const mainModelConfig = selectMainModelConfig(state); @@ -82,6 +86,11 @@ export const getDefaultRefImageConfig = (getState: AppGetState): IPAdapterConfig const base = mainModelConfig?.base; + // FLUX.2 Klein has built-in reference image support - no model needed + if (base === 'flux2') { + return deepClone(initialFlux2ReferenceImage); + } + if (base === 'flux' && mainModelConfig?.name?.toLowerCase().includes('kontext')) { const config = deepClone(initialFluxKontextReferenceImage); config.model = zModelIdentifierField.parse(mainModelConfig); diff --git a/invokeai/frontend/web/src/features/controlLayers/store/paramsSlice.ts b/invokeai/frontend/web/src/features/controlLayers/store/paramsSlice.ts index 0190aba602..7a9d08360d 100644 --- a/invokeai/frontend/web/src/features/controlLayers/store/paramsSlice.ts +++ b/invokeai/frontend/web/src/features/controlLayers/store/paramsSlice.ts @@ -200,6 +200,23 @@ const slice = createSlice({ } state.zImageQwen3SourceModel = result.data; }, + kleinVaeModelSelected: (state, action: PayloadAction) => { + const result = zParamsState.shape.kleinVaeModel.safeParse(action.payload); + if (!result.success) { + return; + } + state.kleinVaeModel = result.data; + }, + kleinQwen3EncoderModelSelected: ( + state, + action: PayloadAction<{ key: string; name: string; base: string } | null> + ) => { + const result = zParamsState.shape.kleinQwen3EncoderModel.safeParse(action.payload); + if (!result.success) { + return; + } + state.kleinQwen3EncoderModel = result.data; + }, vaePrecisionChanged: (state, action: PayloadAction) => { state.vaePrecision = action.payload; }, @@ -446,6 +463,8 @@ const resetState = (state: ParamsState): ParamsState => { newState.zImageVaeModel = oldState.zImageVaeModel; newState.zImageQwen3EncoderModel = oldState.zImageQwen3EncoderModel; newState.zImageQwen3SourceModel = oldState.zImageQwen3SourceModel; + newState.kleinVaeModel = oldState.kleinVaeModel; + newState.kleinQwen3EncoderModel = oldState.kleinQwen3EncoderModel; return newState; }; @@ -487,6 +506,8 @@ export const { zImageVaeModelSelected, zImageQwen3EncoderModelSelected, zImageQwen3SourceModelSelected, + kleinVaeModelSelected, + kleinQwen3EncoderModelSelected, setClipSkip, shouldUseCpuNoiseChanged, setColorCompensation, @@ -552,6 +573,7 @@ export const selectIsFLUX = createParamsSelector((params) => params.model?.base export const selectIsSD3 = createParamsSelector((params) => params.model?.base === 'sd-3'); export const selectIsCogView4 = createParamsSelector((params) => params.model?.base === 'cogview4'); export const selectIsZImage = createParamsSelector((params) => params.model?.base === 'z-image'); +export const selectIsFlux2 = createParamsSelector((params) => params.model?.base === 'flux2'); export const selectIsFluxKontext = createParamsSelector((params) => { if (params.model?.base === 'flux' && params.model?.name.toLowerCase().includes('kontext')) { return true; @@ -572,6 +594,8 @@ export const selectCLIPGEmbedModel = createParamsSelector((params) => params.cli export const selectZImageVaeModel = createParamsSelector((params) => params.zImageVaeModel); export const selectZImageQwen3EncoderModel = createParamsSelector((params) => params.zImageQwen3EncoderModel); export const selectZImageQwen3SourceModel = createParamsSelector((params) => params.zImageQwen3SourceModel); +export const selectKleinVaeModel = createParamsSelector((params) => params.kleinVaeModel); +export const selectKleinQwen3EncoderModel = createParamsSelector((params) => params.kleinQwen3EncoderModel); export const selectCFGScale = createParamsSelector((params) => params.cfgScale); export const selectGuidance = createParamsSelector((params) => params.guidance); diff --git a/invokeai/frontend/web/src/features/controlLayers/store/refImagesSlice.ts b/invokeai/frontend/web/src/features/controlLayers/store/refImagesSlice.ts index e0896c0fb9..2554cacc61 100644 --- a/invokeai/frontend/web/src/features/controlLayers/store/refImagesSlice.ts +++ b/invokeai/frontend/web/src/features/controlLayers/store/refImagesSlice.ts @@ -17,7 +17,13 @@ import { assert } from 'tsafe'; import type { PartialDeep } from 'type-fest'; import type { CLIPVisionModelV2, IPMethodV2, RefImageState } from './types'; -import { getInitialRefImagesState, isFLUXReduxConfig, isIPAdapterConfig, zRefImagesState } from './types'; +import { + getInitialRefImagesState, + isFlux2ReferenceImageConfig, + isFLUXReduxConfig, + isIPAdapterConfig, + zRefImagesState, +} from './types'; import { getReferenceImageState, initialFluxKontextReferenceImage, initialFLUXRedux, initialIPAdapter } from './util'; type PayloadActionWithId = T extends void @@ -100,6 +106,11 @@ const slice = createSlice({ return; } + // FLUX.2 reference images don't have a model field - they use built-in support + if (isFlux2ReferenceImageConfig(entity.config)) { + return; + } + const oldModel = entity.config.model; // First set the new model diff --git a/invokeai/frontend/web/src/features/controlLayers/store/types.ts b/invokeai/frontend/web/src/features/controlLayers/store/types.ts index fbd3d415b7..779e6cb29e 100644 --- a/invokeai/frontend/web/src/features/controlLayers/store/types.ts +++ b/invokeai/frontend/web/src/features/controlLayers/store/types.ts @@ -322,6 +322,13 @@ const zFluxKontextReferenceImageConfig = z.object({ }); export type FluxKontextReferenceImageConfig = z.infer; +// FLUX.2 Klein has built-in reference image support - no separate model needed +const zFlux2ReferenceImageConfig = z.object({ + type: z.literal('flux2_reference_image'), + image: zCroppableImageWithDims.nullable(), +}); +export type Flux2ReferenceImageConfig = z.infer; + const zCanvasEntityBase = z.object({ id: zId, name: zName, @@ -332,7 +339,12 @@ const zCanvasEntityBase = z.object({ export const zRefImageState = z.object({ id: zId, isEnabled: z.boolean().default(true), - config: z.discriminatedUnion('type', [zIPAdapterConfig, zFLUXReduxConfig, zFluxKontextReferenceImageConfig]), + config: z.discriminatedUnion('type', [ + zIPAdapterConfig, + zFLUXReduxConfig, + zFluxKontextReferenceImageConfig, + zFlux2ReferenceImageConfig, + ]), }); export type RefImageState = z.infer; @@ -346,6 +358,9 @@ export const isFluxKontextReferenceImageConfig = ( config: RefImageState['config'] ): config is FluxKontextReferenceImageConfig => config.type === 'flux_kontext_reference_image'; +export const isFlux2ReferenceImageConfig = (config: RefImageState['config']): config is Flux2ReferenceImageConfig => + config.type === 'flux2_reference_image'; + const zFillStyle = z.enum(['solid', 'grid', 'crosshatch', 'diagonal', 'horizontal', 'vertical']); export type FillStyle = z.infer; export const isFillStyle = (v: unknown): v is FillStyle => zFillStyle.safeParse(v).success; @@ -633,6 +648,9 @@ export const zParamsState = z.object({ zImageVaeModel: zParameterVAEModel.nullable(), // Optional: Separate FLUX VAE zImageQwen3EncoderModel: zModelIdentifierField.nullable(), // Optional: Separate Qwen3 Encoder zImageQwen3SourceModel: zParameterModel.nullable(), // Diffusers Z-Image model (fallback for VAE/Encoder) + // Flux2 Klein model components - uses Qwen3 instead of CLIP+T5 + kleinVaeModel: zParameterVAEModel.nullable(), // Optional: Separate FLUX.2 VAE for Klein + kleinQwen3EncoderModel: zModelIdentifierField.nullable(), // Optional: Separate Qwen3 Encoder for Klein // Z-Image Seed Variance Enhancer settings zImageSeedVarianceEnabled: z.boolean(), zImageSeedVarianceStrength: z.number().min(0).max(2), @@ -692,6 +710,8 @@ export const getInitialParamsState = (): ParamsState => ({ zImageVaeModel: null, zImageQwen3EncoderModel: null, zImageQwen3SourceModel: null, + kleinVaeModel: null, + kleinQwen3EncoderModel: null, zImageSeedVarianceEnabled: false, zImageSeedVarianceStrength: 0.1, zImageSeedVarianceRandomizePercent: 50, diff --git a/invokeai/frontend/web/src/features/controlLayers/store/util.ts b/invokeai/frontend/web/src/features/controlLayers/store/util.ts index 62c5a978ad..f14af4feee 100644 --- a/invokeai/frontend/web/src/features/controlLayers/store/util.ts +++ b/invokeai/frontend/web/src/features/controlLayers/store/util.ts @@ -10,6 +10,7 @@ import type { ControlLoRAConfig, ControlNetConfig, CroppableImageWithDims, + Flux2ReferenceImageConfig, FluxKontextReferenceImageConfig, FLUXReduxConfig, ImageWithDims, @@ -112,6 +113,10 @@ export const initialFluxKontextReferenceImage: FluxKontextReferenceImageConfig = image: null, model: null, }; +export const initialFlux2ReferenceImage: Flux2ReferenceImageConfig = { + type: 'flux2_reference_image', + image: null, +}; export const initialT2IAdapter: T2IAdapterConfig = { type: 't2i_adapter', model: null, diff --git a/invokeai/frontend/web/src/features/controlLayers/store/validators.ts b/invokeai/frontend/web/src/features/controlLayers/store/validators.ts index 5706f77bb2..3406e9e7ee 100644 --- a/invokeai/frontend/web/src/features/controlLayers/store/validators.ts +++ b/invokeai/frontend/web/src/features/controlLayers/store/validators.ts @@ -125,12 +125,15 @@ export const getGlobalReferenceImageWarnings = ( const { config } = entity; - if (!config.model) { - // No model selected - warnings.push(WARNINGS.IP_ADAPTER_NO_MODEL_SELECTED); - } else if (!areBasesCompatibleForRefImage(config.model, model)) { - // Supported model architecture but doesn't match - warnings.push(WARNINGS.IP_ADAPTER_INCOMPATIBLE_BASE_MODEL); + // FLUX.2 reference images don't require a model - it's built-in + if (config.type !== 'flux2_reference_image') { + if (!('model' in config) || !config.model) { + // No model selected + warnings.push(WARNINGS.IP_ADAPTER_NO_MODEL_SELECTED); + } else if (!areBasesCompatibleForRefImage(config.model, model)) { + // Supported model architecture but doesn't match + warnings.push(WARNINGS.IP_ADAPTER_INCOMPATIBLE_BASE_MODEL); + } } if (!entity.config.image) { diff --git a/invokeai/frontend/web/src/features/metadata/parsing.tsx b/invokeai/frontend/web/src/features/metadata/parsing.tsx index d9201f15ff..42c2c433a3 100644 --- a/invokeai/frontend/web/src/features/metadata/parsing.tsx +++ b/invokeai/frontend/web/src/features/metadata/parsing.tsx @@ -9,6 +9,8 @@ import { bboxHeightChanged, bboxWidthChanged, canvasMetadataRecalled } from 'fea import { loraAllDeleted, loraRecalled } from 'features/controlLayers/store/lorasSlice'; import { heightChanged, + kleinQwen3EncoderModelSelected, + kleinVaeModelSelected, negativePromptChanged, positivePromptChanged, refinerModelChanged, @@ -380,8 +382,8 @@ const Scheduler: SingleMetadataHandler = { recall: (value, store) => { // Dispatch to the appropriate scheduler based on the current model base const base = selectBase(store.getState()); - if (base === 'flux') { - // Flux only supports euler, heun, lcm + if (base === 'flux' || base === 'flux2') { + // Flux and Flux2 (Klein) only support euler, heun, lcm if (value === 'euler' || value === 'heun' || value === 'lcm') { store.dispatch(setFluxScheduler(value)); } @@ -847,6 +849,54 @@ const ZImageQwen3SourceModel: SingleMetadataHandler = { }; //#endregion ZImageQwen3SourceModel +//#region KleinVAEModel +const KleinVAEModel: SingleMetadataHandler = { + [SingleMetadataKey]: true, + type: 'KleinVAEModel', + parse: async (metadata, store) => { + const raw = getProperty(metadata, 'vae'); + const parsed = await parseModelIdentifier(raw, store, 'vae'); + assert(parsed.type === 'vae'); + // Only recall if the current main model is FLUX.2 Klein + const base = selectBase(store.getState()); + assert(base === 'flux2', 'KleinVAEModel handler only works with FLUX.2 Klein models'); + return Promise.resolve(parsed); + }, + recall: (value, store) => { + store.dispatch(kleinVaeModelSelected(value)); + }, + i18nKey: 'metadata.vae', + LabelComponent: MetadataLabel, + ValueComponent: ({ value }: SingleMetadataValueProps) => ( + + ), +}; +//#endregion KleinVAEModel + +//#region KleinQwen3EncoderModel +const KleinQwen3EncoderModel: SingleMetadataHandler = { + [SingleMetadataKey]: true, + type: 'KleinQwen3EncoderModel', + parse: async (metadata, store) => { + const raw = getProperty(metadata, 'qwen3_encoder'); + const parsed = await parseModelIdentifier(raw, store, 'qwen3_encoder'); + assert(parsed.type === 'qwen3_encoder'); + // Only recall if the current main model is FLUX.2 Klein + const base = selectBase(store.getState()); + assert(base === 'flux2', 'KleinQwen3EncoderModel handler only works with FLUX.2 Klein models'); + return Promise.resolve(parsed); + }, + recall: (value, store) => { + store.dispatch(kleinQwen3EncoderModelSelected(value)); + }, + i18nKey: 'metadata.qwen3Encoder', + LabelComponent: MetadataLabel, + ValueComponent: ({ value }: SingleMetadataValueProps) => ( + + ), +}; +//#endregion KleinQwen3EncoderModel + //#region LoRAs const LoRAs: CollectionMetadataHandler = { [CollectionMetadataKey]: true, @@ -1029,7 +1079,8 @@ const RefImages: CollectionMetadataHandler = { if (refImage.config.image) { await throwIfImageDoesNotExist(refImage.config.image.original.image.image_name, store); } - if (refImage.config.model) { + // FLUX.2 reference images don't have a model field (built-in support) + if ('model' in refImage.config && refImage.config.model) { await throwIfModelDoesNotExist(refImage.config.model.key, store); } } @@ -1047,7 +1098,8 @@ const RefImages: CollectionMetadataHandler = { i18nKey: 'controlLayers.referenceImage', LabelComponent: MetadataLabel, ValueComponent: ({ value }: CollectionMetadataValueProps) => { - if (value.config.model) { + // FLUX.2 reference images don't have a model field (built-in support) + if ('model' in value.config && value.config.model) { return ; } return ; @@ -1085,6 +1137,8 @@ export const ImageMetadataHandlers = { Qwen3EncoderModel, ZImageVAEModel, ZImageQwen3SourceModel, + KleinVAEModel, + KleinQwen3EncoderModel, ZImageSeedVarianceEnabled, ZImageSeedVarianceStrength, ZImageSeedVarianceRandomizePercent, diff --git a/invokeai/frontend/web/src/features/modelManagerV2/models.ts b/invokeai/frontend/web/src/features/modelManagerV2/models.ts index e07e7f0632..cd83315d48 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/models.ts +++ b/invokeai/frontend/web/src/features/modelManagerV2/models.ts @@ -140,6 +140,7 @@ export const MODEL_BASE_TO_COLOR: Record = { sdxl: 'invokeBlue', 'sdxl-refiner': 'invokeBlue', flux: 'gold', + flux2: 'gold', cogview4: 'red', 'z-image': 'cyan', unknown: 'red', @@ -180,6 +181,7 @@ export const MODEL_BASE_TO_LONG_NAME: Record = { sdxl: 'Stable Diffusion XL', 'sdxl-refiner': 'Stable Diffusion XL Refiner', flux: 'FLUX', + flux2: 'FLUX.2', cogview4: 'CogView4', 'z-image': 'Z-Image', unknown: 'Unknown', @@ -196,6 +198,7 @@ export const MODEL_BASE_TO_SHORT_NAME: Record = { sdxl: 'SDXL', 'sdxl-refiner': 'SDXLR', flux: 'FLUX', + flux2: 'FLUX.2', cogview4: 'CogView4', 'z-image': 'Z-Image', unknown: 'Unknown', @@ -208,8 +211,13 @@ export const MODEL_VARIANT_TO_LONG_NAME: Record = { dev: 'FLUX Dev', dev_fill: 'FLUX Dev - Fill', schnell: 'FLUX Schnell', + klein_4b: 'FLUX.2 Klein 4B', + klein_9b: 'FLUX.2 Klein 9B', + klein_9b_base: 'FLUX.2 Klein 9B Base', large: 'CLIP L', gigantic: 'CLIP G', + qwen3_4b: 'Qwen3 4B', + qwen3_8b: 'Qwen3 8B', }; export const MODEL_FORMAT_TO_LONG_NAME: Record = { @@ -232,7 +240,7 @@ export const MODEL_FORMAT_TO_LONG_NAME: Record = { export const SUPPORTS_OPTIMIZED_DENOISING_BASE_MODELS: BaseModelType[] = ['flux', 'sd-3', 'z-image']; -export const SUPPORTS_REF_IMAGES_BASE_MODELS: BaseModelType[] = ['sd-1', 'sdxl', 'flux']; +export const SUPPORTS_REF_IMAGES_BASE_MODELS: BaseModelType[] = ['sd-1', 'sdxl', 'flux', 'flux2']; export const SUPPORTS_NEGATIVE_PROMPT_BASE_MODELS: BaseModelType[] = [ 'sd-1', diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/ModelInstallQueue/ModelInstallQueueItem.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/ModelInstallQueue/ModelInstallQueueItem.tsx index 5706702180..bfe81713d0 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/ModelInstallQueue/ModelInstallQueueItem.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/ModelInstallQueue/ModelInstallQueueItem.tsx @@ -66,8 +66,13 @@ export const ModelInstallQueueItem = memo((props: ModelListItemProps) => { const modelName = useMemo(() => { switch (installJob.source.type) { - case 'hf': - return installJob.source.repo_id; + case 'hf': { + const { repo_id, subfolder } = installJob.source; + if (subfolder) { + return `${repo_id}::${subfolder}`; + } + return repo_id; + } case 'url': return installJob.source.url.split('/').slice(-1)[0] ?? t('common.unknown'); case 'local': diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelView.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelView.tsx index 20b8fd6c13..2650d20cee 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelView.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelView.tsx @@ -66,7 +66,7 @@ export const ModelView = memo(({ modelConfig }: Props) => { - {modelConfig.type === 'main' && 'variant' in modelConfig && ( + {'variant' in modelConfig && modelConfig.variant && ( )} {modelConfig.type === 'main' && modelConfig.format === 'diffusers' && modelConfig.repo_variant && ( diff --git a/invokeai/frontend/web/src/features/nodes/types/common.test-d.ts b/invokeai/frontend/web/src/features/nodes/types/common.test-d.ts index c223747b93..25ba48c293 100644 --- a/invokeai/frontend/web/src/features/nodes/types/common.test-d.ts +++ b/invokeai/frontend/web/src/features/nodes/types/common.test-d.ts @@ -12,9 +12,11 @@ import type { T2IAdapterField, zBaseModelType, zClipVariantType, + zFlux2VariantType, zFluxVariantType, zModelFormat, zModelVariantType, + zQwen3VariantType, zSubModelType, } from 'features/nodes/types/common'; import type { Invocation, S } from 'services/api/types'; @@ -47,6 +49,8 @@ describe('Common types', () => { test('ClipVariantType', () => assert, S['ClipVariantType']>>()); test('ModelVariantType', () => assert, S['ModelVariantType']>>()); test('FluxVariantType', () => assert, S['FluxVariantType']>>()); + test('Flux2VariantType', () => assert, S['Flux2VariantType']>>()); + test('Qwen3VariantType', () => assert, S['Qwen3VariantType']>>()); test('ModelFormat', () => assert, S['ModelFormat']>>()); // Misc types diff --git a/invokeai/frontend/web/src/features/nodes/types/common.ts b/invokeai/frontend/web/src/features/nodes/types/common.ts index 994d909143..389903b9c9 100644 --- a/invokeai/frontend/web/src/features/nodes/types/common.ts +++ b/invokeai/frontend/web/src/features/nodes/types/common.ts @@ -81,12 +81,13 @@ export const zBaseModelType = z.enum([ 'sdxl', 'sdxl-refiner', 'flux', + 'flux2', 'cogview4', 'z-image', 'unknown', ]); export type BaseModelType = z.infer; -export const zMainModelBase = z.enum(['sd-1', 'sd-2', 'sd-3', 'sdxl', 'flux', 'cogview4', 'z-image']); +export const zMainModelBase = z.enum(['sd-1', 'sd-2', 'sd-3', 'sdxl', 'flux', 'flux2', 'cogview4', 'z-image']); type MainModelBase = z.infer; export const isMainModelBase = (base: unknown): base is MainModelBase => zMainModelBase.safeParse(base).success; export const zModelType = z.enum([ @@ -129,7 +130,15 @@ export const zSubModelType = z.enum([ export const zClipVariantType = z.enum(['large', 'gigantic']); export const zModelVariantType = z.enum(['normal', 'inpaint', 'depth']); export const zFluxVariantType = z.enum(['dev', 'dev_fill', 'schnell']); -export const zAnyModelVariant = z.union([zModelVariantType, zClipVariantType, zFluxVariantType]); +export const zFlux2VariantType = z.enum(['klein_4b', 'klein_9b', 'klein_9b_base']); +export const zQwen3VariantType = z.enum(['qwen3_4b', 'qwen3_8b']); +export const zAnyModelVariant = z.union([ + zModelVariantType, + zClipVariantType, + zFluxVariantType, + zFlux2VariantType, + zQwen3VariantType, +]); export type AnyModelVariant = z.infer; export const zModelFormat = z.enum([ 'omi', diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/generation/addControlAdapters.ts b/invokeai/frontend/web/src/features/nodes/util/graph/generation/addControlAdapters.ts index 73a070c46d..f867ff5c41 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/generation/addControlAdapters.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/generation/addControlAdapters.ts @@ -5,7 +5,7 @@ import type { CanvasControlLayerState, Rect } from 'features/controlLayers/store import { getControlLayerWarnings } from 'features/controlLayers/store/validators'; import type { Graph } from 'features/nodes/util/graph/generation/Graph'; import { serializeError } from 'serialize-error'; -import type { FLUXModelConfig, ImageDTO, Invocation, MainModelConfig } from 'services/api/types'; +import type { AnyFLUXModelConfig, ImageDTO, Invocation, MainModelConfig } from 'services/api/types'; import { assert } from 'tsafe'; const log = logger('system'); @@ -113,7 +113,7 @@ type AddControlLoRAArg = { entities: CanvasControlLayerState[]; g: Graph; rect: Rect; - model: FLUXModelConfig; + model: AnyFLUXModelConfig; denoise: Invocation<'flux_denoise'>; }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/generation/addImageToImage.ts b/invokeai/frontend/web/src/features/nodes/util/graph/generation/addImageToImage.ts index 7b944a6946..4273077499 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/generation/addImageToImage.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/generation/addImageToImage.ts @@ -21,7 +21,7 @@ type AddImageToImageArg = { state: RootState; manager: CanvasManager; l2i: Invocation; - i2l: Invocation<'i2l' | 'flux_vae_encode' | 'sd3_i2l' | 'cogview4_i2l' | 'z_image_i2l'>; + i2l: Invocation<'i2l' | 'flux_vae_encode' | 'flux2_vae_encode' | 'sd3_i2l' | 'cogview4_i2l' | 'z_image_i2l'>; noise?: Invocation<'noise'>; denoise: Invocation; vaeSource: Invocation; @@ -37,7 +37,7 @@ export const addImageToImage = async ({ denoise, vaeSource, }: AddImageToImageArg): Promise< - Invocation<'img_resize' | 'l2i' | 'flux_vae_decode' | 'sd3_l2i' | 'cogview4_l2i' | 'z_image_l2i'> + Invocation<'img_resize' | 'l2i' | 'flux_vae_decode' | 'flux2_vae_decode' | 'sd3_l2i' | 'cogview4_l2i' | 'z_image_l2i'> > => { const { denoising_start, denoising_end } = getDenoisingStartAndEnd(state); denoise.denoising_start = denoising_start; @@ -48,6 +48,7 @@ export const addImageToImage = async ({ if ( denoise.type === 'cogview4_denoise' || denoise.type === 'flux_denoise' || + denoise.type === 'flux2_denoise' || denoise.type === 'sd3_denoise' || denoise.type === 'z_image_denoise' ) { diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/generation/addInpaint.ts b/invokeai/frontend/web/src/features/nodes/util/graph/generation/addInpaint.ts index 39b548576c..837e7f09ea 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/generation/addInpaint.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/generation/addInpaint.ts @@ -24,7 +24,7 @@ type AddInpaintArg = { state: RootState; manager: CanvasManager; l2i: Invocation; - i2l: Invocation<'i2l' | 'flux_vae_encode' | 'sd3_i2l' | 'cogview4_i2l' | 'z_image_i2l'>; + i2l: Invocation<'i2l' | 'flux_vae_encode' | 'flux2_vae_encode' | 'sd3_i2l' | 'cogview4_i2l' | 'z_image_i2l'>; noise?: Invocation<'noise'>; denoise: Invocation; vaeSource: Invocation; @@ -56,6 +56,7 @@ export const addInpaint = async ({ if ( denoise.type === 'cogview4_denoise' || denoise.type === 'flux_denoise' || + denoise.type === 'flux2_denoise' || denoise.type === 'sd3_denoise' || denoise.type === 'z_image_denoise' ) { diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/generation/addOutpaint.ts b/invokeai/frontend/web/src/features/nodes/util/graph/generation/addOutpaint.ts index 995b319a59..d745f80fe6 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/generation/addOutpaint.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/generation/addOutpaint.ts @@ -6,7 +6,6 @@ import { selectCanvasSettingsSlice } from 'features/controlLayers/store/canvasSe import { selectParamsSlice } from 'features/controlLayers/store/paramsSlice'; import type { Graph } from 'features/nodes/util/graph/generation/Graph'; import { - getDenoisingStartAndEnd, getInfill, getOriginalAndScaledSizesForOtherModes, isMainModelWithoutUnet, @@ -46,9 +45,12 @@ export const addOutpaint = async ({ modelLoader, seed, }: AddOutpaintArg): Promise> => { - const { denoising_start, denoising_end } = getDenoisingStartAndEnd(state); - denoise.denoising_start = denoising_start; - denoise.denoising_end = denoising_end; + // For outpainting, always use full denoising (from pure noise) because: + // - New areas should be fully generated + // - Existing areas are preserved by the inpaint mask + // The strength setting doesn't make sense for outpainting. + denoise.denoising_start = 0; + denoise.denoising_end = 1; const params = selectParamsSlice(state); const canvasSettings = selectCanvasSettingsSlice(state); @@ -58,6 +60,7 @@ export const addOutpaint = async ({ if ( denoise.type === 'cogview4_denoise' || denoise.type === 'flux_denoise' || + denoise.type === 'flux2_denoise' || denoise.type === 'sd3_denoise' || denoise.type === 'z_image_denoise' ) { diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/generation/addRegions.ts b/invokeai/frontend/web/src/features/nodes/util/graph/generation/addRegions.ts index 3337a094f5..22973983a9 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/generation/addRegions.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/generation/addRegions.ts @@ -32,8 +32,12 @@ type AddRegionsArg = { g: Graph; bbox: Rect; model: MainModelConfig; - posCond: Invocation<'compel' | 'sdxl_compel_prompt' | 'flux_text_encoder' | 'z_image_text_encoder'>; - negCond: Invocation<'compel' | 'sdxl_compel_prompt' | 'flux_text_encoder' | 'z_image_text_encoder'> | null; + posCond: Invocation< + 'compel' | 'sdxl_compel_prompt' | 'flux_text_encoder' | 'flux2_klein_text_encoder' | 'z_image_text_encoder' + >; + negCond: Invocation< + 'compel' | 'sdxl_compel_prompt' | 'flux_text_encoder' | 'flux2_klein_text_encoder' | 'z_image_text_encoder' + > | null; posCondCollect: Invocation<'collect'>; negCondCollect: Invocation<'collect'> | null; ipAdapterCollect: Invocation<'collect'>; diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/generation/addTextToImage.ts b/invokeai/frontend/web/src/features/nodes/util/graph/generation/addTextToImage.ts index bb1130f71a..d70457ac63 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/generation/addTextToImage.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/generation/addTextToImage.ts @@ -22,7 +22,7 @@ export const addTextToImage = ({ denoise, l2i, }: AddTextToImageArg): Invocation< - 'img_resize' | 'l2i' | 'flux_vae_decode' | 'sd3_l2i' | 'cogview4_l2i' | 'z_image_l2i' + 'img_resize' | 'l2i' | 'flux_vae_decode' | 'flux2_vae_decode' | 'sd3_l2i' | 'cogview4_l2i' | 'z_image_l2i' > => { denoise.denoising_start = 0; denoise.denoising_end = 1; @@ -32,6 +32,7 @@ export const addTextToImage = ({ if ( denoise.type === 'cogview4_denoise' || denoise.type === 'flux_denoise' || + denoise.type === 'flux2_denoise' || denoise.type === 'sd3_denoise' || denoise.type === 'z_image_denoise' ) { diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/generation/buildFLUXGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/generation/buildFLUXGraph.ts index d54697cf55..0837a701a5 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/generation/buildFLUXGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/generation/buildFLUXGraph.ts @@ -1,9 +1,14 @@ import { logger } from 'app/logging/logger'; import { getPrefixedId } from 'features/controlLayers/konva/util'; -import { selectMainModelConfig, selectParamsSlice } from 'features/controlLayers/store/paramsSlice'; +import { + selectKleinQwen3EncoderModel, + selectKleinVaeModel, + selectMainModelConfig, + selectParamsSlice, +} from 'features/controlLayers/store/paramsSlice'; import { selectRefImagesSlice } from 'features/controlLayers/store/refImagesSlice'; import { selectCanvasMetadata, selectCanvasSlice } from 'features/controlLayers/store/selectors'; -import { isFluxKontextReferenceImageConfig } from 'features/controlLayers/store/types'; +import { isFlux2ReferenceImageConfig, isFluxKontextReferenceImageConfig } from 'features/controlLayers/store/types'; import { getGlobalReferenceImageWarnings } from 'features/controlLayers/store/validators'; import { zImageField } from 'features/nodes/types/common'; import { addFLUXFill } from 'features/nodes/util/graph/generation/addFLUXFill'; @@ -37,7 +42,7 @@ export const buildFLUXGraph = async (arg: GraphBuilderArg): Promise | Invocation<'flux2_klein_model_loader'>; + let posCond: Invocation<'flux_text_encoder'> | Invocation<'flux2_klein_text_encoder'>; + let denoise: Invocation<'flux_denoise'> | Invocation<'flux2_denoise'>; + let posCondCollect: Invocation<'collect'> | null = null; const positivePrompt = g.addNode({ id: getPrefixedId('positive_prompt'), type: 'string', }); - const posCond = g.addNode({ - type: 'flux_text_encoder', - id: getPrefixedId('flux_text_encoder'), - }); - const posCondCollect = g.addNode({ - type: 'collect', - id: getPrefixedId('pos_cond_collect'), - }); const seed = g.addNode({ id: getPrefixedId('seed'), type: 'integer', }); - const denoise = g.addNode({ - type: 'flux_denoise', - id: getPrefixedId('flux_denoise'), - guidance, - num_steps: steps, - scheduler: fluxScheduler, - }); - const l2i = g.addNode({ - type: 'flux_vae_decode', - id: getPrefixedId('flux_vae_decode'), - }); + // Use appropriate VAE decode node based on model type + // FLUX.2 Klein uses a 32-channel VAE (AutoencoderKLFlux2) + let l2i: Invocation<'flux_vae_decode'> | Invocation<'flux2_vae_decode'>; + if (isFlux2) { + l2i = g.addNode({ + type: 'flux2_vae_decode', + id: getPrefixedId('flux2_vae_decode'), + }); + } else { + l2i = g.addNode({ + type: 'flux_vae_decode', + id: getPrefixedId('flux_vae_decode'), + }); + } - g.addEdge(modelLoader, 'transformer', denoise, 'transformer'); - g.addEdge(modelLoader, 'vae', denoise, 'controlnet_vae'); - g.addEdge(modelLoader, 'vae', l2i, 'vae'); + if (isFlux2) { + // Flux2 Klein: Use Qwen3-based model loader, text encoder, and dedicated denoise node + // VAE and Qwen3 encoder can be extracted from the main Diffusers model or selected separately + modelLoader = g.addNode({ + type: 'flux2_klein_model_loader', + id: getPrefixedId('flux2_klein_model_loader'), + model, + // Optional: Use separately selected VAE and Qwen3 encoder models + vae_model: kleinVaeModel ?? undefined, + qwen3_encoder_model: kleinQwen3EncoderModel ?? undefined, + }); - g.addEdge(modelLoader, 'clip', posCond, 'clip'); - g.addEdge(modelLoader, 't5_encoder', posCond, 't5_encoder'); - g.addEdge(modelLoader, 'max_seq_len', posCond, 't5_max_seq_len'); + posCond = g.addNode({ + type: 'flux2_klein_text_encoder', + id: getPrefixedId('flux2_klein_text_encoder'), + }); - g.addEdge(positivePrompt, 'value', posCond, 'prompt'); - g.addEdge(posCond, 'conditioning', posCondCollect, 'item'); - g.addEdge(posCondCollect, 'collection', denoise, 'positive_text_conditioning'); + denoise = g.addNode({ + type: 'flux2_denoise', + id: getPrefixedId('flux2_denoise'), + num_steps: steps, + scheduler: fluxScheduler, + }); + + // Klein: Connect Qwen3 encoder outputs + const kleinLoader = modelLoader as Invocation<'flux2_klein_model_loader'>; + const kleinCond = posCond as Invocation<'flux2_klein_text_encoder'>; + g.addEdge(kleinLoader, 'qwen3_encoder', kleinCond, 'qwen3_encoder'); + g.addEdge(kleinLoader, 'max_seq_len', kleinCond, 'max_seq_len'); + g.addEdge(kleinLoader, 'transformer', denoise, 'transformer'); + g.addEdge(kleinLoader, 'vae', denoise, 'vae'); // VAE needed for BN statistics + g.addEdge(kleinLoader, 'vae', l2i, 'vae'); + g.addEdge(positivePrompt, 'value', kleinCond, 'prompt'); + g.addEdge(kleinCond, 'conditioning', denoise, 'positive_text_conditioning'); + } else { + // Standard FLUX: Use CLIP+T5 model loader and text encoder + modelLoader = g.addNode({ + type: 'flux_model_loader', + id: getPrefixedId('flux_model_loader'), + model, + t5_encoder_model: t5EncoderModel!, + clip_embed_model: clipEmbedModel!, + vae_model: fluxVAE, + }); + + posCond = g.addNode({ + type: 'flux_text_encoder', + id: getPrefixedId('flux_text_encoder'), + }); + + denoise = g.addNode({ + type: 'flux_denoise', + id: getPrefixedId('flux_denoise'), + guidance, + num_steps: steps, + scheduler: fluxScheduler, + }); + + posCondCollect = g.addNode({ + type: 'collect', + id: getPrefixedId('pos_cond_collect'), + }); + + // Standard FLUX: Connect CLIP and T5 encoder outputs + const fluxLoader = modelLoader as Invocation<'flux_model_loader'>; + const fluxCond = posCond as Invocation<'flux_text_encoder'>; + g.addEdge(fluxLoader, 'clip', fluxCond, 'clip'); + g.addEdge(fluxLoader, 't5_encoder', fluxCond, 't5_encoder'); + g.addEdge(fluxLoader, 'max_seq_len', fluxCond, 't5_max_seq_len'); + g.addEdge(fluxLoader, 'transformer', denoise, 'transformer'); + g.addEdge(fluxLoader, 'vae', denoise, 'controlnet_vae'); + g.addEdge(fluxLoader, 'vae', l2i, 'vae'); + g.addEdge(positivePrompt, 'value', fluxCond, 'prompt'); + g.addEdge(fluxCond, 'conditioning', posCondCollect, 'item'); + g.addEdge(posCondCollect, 'collection', denoise, 'positive_text_conditioning'); + } g.addEdge(seed, 'value', denoise, 'seed'); g.addEdge(denoise, 'latents', l2i, 'latents'); - addFLUXLoRAs(state, g, denoise, modelLoader, posCond); - - g.upsertMetadata({ - guidance, - model: Graph.getModelMetadataField(model), - steps, - scheduler: fluxScheduler, - vae: fluxVAE, - t5_encoder: t5EncoderModel, - clip_embed_model: clipEmbedModel, - }); + // Metadata + if (isFlux2) { + // VAE and Qwen3 encoder can come from the main model or be selected separately + const flux2Metadata: Record = { + model: Graph.getModelMetadataField(model), + steps, + scheduler: fluxScheduler, + }; + if (kleinVaeModel) { + flux2Metadata.vae = kleinVaeModel; + } + if (kleinQwen3EncoderModel) { + flux2Metadata.qwen3_encoder = kleinQwen3EncoderModel; + } + g.upsertMetadata(flux2Metadata); + } else { + g.upsertMetadata({ + guidance, + model: Graph.getModelMetadataField(model), + steps, + scheduler: fluxScheduler, + vae: fluxVAE, + t5_encoder: t5EncoderModel, + clip_embed_model: clipEmbedModel, + }); + } g.addEdgeToMetadata(seed, 'value', 'seed'); g.addEdgeToMetadata(positivePrompt, 'value', 'positive_prompt'); - if (isFluxKontextDev) { - const validFLUXKontextConfigs = selectRefImagesSlice(state) + let canvasOutput: Invocation = l2i; + + // Flux2 Klein path + if (isFlux2) { + const flux2Denoise = denoise as Invocation<'flux2_denoise'>; + const flux2ModelLoader = modelLoader as Invocation<'flux2_klein_model_loader'>; + const flux2L2i = l2i as Invocation<'flux2_vae_decode'>; + + // FLUX.2 Klein has built-in multi-reference image editing - no separate model needed + const validFlux2RefImageConfigs = selectRefImagesSlice(state) .entities.filter((entity) => entity.isEnabled) - .filter((entity) => isFluxKontextReferenceImageConfig(entity.config)) + .filter((entity) => isFlux2ReferenceImageConfig(entity.config)) .filter((entity) => getGlobalReferenceImageWarnings(entity, model).length === 0); - if (validFLUXKontextConfigs.length > 0) { - const fluxKontextCollect = g.addNode({ + if (validFlux2RefImageConfigs.length > 0) { + const flux2KontextCollect = g.addNode({ type: 'collect', - id: getPrefixedId('flux_kontext_collect'), + id: getPrefixedId('flux2_kontext_collect'), }); - for (const { config } of validFLUXKontextConfigs) { - const kontextImagePrep = g.addNode({ - id: getPrefixedId('flux_kontext_image_prep'), - type: 'flux_kontext_image_prep', - images: [zImageField.parse(config.image?.crop?.image ?? config.image?.original.image)], - }); + for (const { config } of validFlux2RefImageConfigs) { + // FLUX.2 uses the same flux_kontext node - it just packages the image const kontextConditioning = g.addNode({ type: 'flux_kontext', id: getPrefixedId('flux_kontext'), + image: zImageField.parse(config.image?.crop?.image ?? config.image?.original.image), }); - g.addEdge(kontextImagePrep, 'image', kontextConditioning, 'image'); - g.addEdge(kontextConditioning, 'kontext_cond', fluxKontextCollect, 'item'); + g.addEdge(kontextConditioning, 'kontext_cond', flux2KontextCollect, 'item'); } - g.addEdge(fluxKontextCollect, 'collection', denoise, 'kontext_conditioning'); + g.addEdge(flux2KontextCollect, 'collection', flux2Denoise, 'kontext_conditioning'); - g.upsertMetadata({ ref_images: [validFLUXKontextConfigs] }, 'merge'); + g.upsertMetadata({ ref_images: [validFlux2RefImageConfigs] }, 'merge'); } - } - let canvasOutput: Invocation = l2i; - - if (isFLUXFill && (generationMode === 'inpaint' || generationMode === 'outpaint')) { - assert(manager !== null); - canvasOutput = await addFLUXFill({ - g, - state, - manager, - l2i, - denoise, - }); - } else if (generationMode === 'txt2img') { - canvasOutput = addTextToImage({ - g, - state, - denoise, - l2i, - }); - g.upsertMetadata({ generation_mode: 'flux_txt2img' }); - } else if (generationMode === 'img2img') { - assert(manager !== null); - const i2l = g.addNode({ - type: 'flux_vae_encode', - id: getPrefixedId('flux_vae_encode'), - }); - canvasOutput = await addImageToImage({ - g, - state, - manager, - l2i, - i2l, - denoise, - vaeSource: modelLoader, - }); - g.upsertMetadata({ generation_mode: 'flux_img2img' }); - } else if (generationMode === 'inpaint') { - assert(manager !== null); - const i2l = g.addNode({ - type: 'flux_vae_encode', - id: getPrefixedId('flux_vae_encode'), - }); - canvasOutput = await addInpaint({ - g, - state, - manager, - l2i, - i2l, - denoise, - vaeSource: modelLoader, - modelLoader, - seed, - }); - g.upsertMetadata({ generation_mode: 'flux_inpaint' }); - } else if (generationMode === 'outpaint') { - assert(manager !== null); - const i2l = g.addNode({ - type: 'flux_vae_encode', - id: getPrefixedId('flux_vae_encode'), - }); - canvasOutput = await addOutpaint({ - g, - state, - manager, - l2i, - i2l, - denoise, - vaeSource: modelLoader, - modelLoader, - seed, - }); - g.upsertMetadata({ generation_mode: 'flux_outpaint' }); - } else { - assert>(false); - } - - if (manager !== null) { - const controlNetCollector = g.addNode({ - type: 'collect', - id: getPrefixedId('control_net_collector'), - }); - const controlNetResult = await addControlNets({ - manager, - entities: canvas.controlLayers.entities, - g, - rect: canvas.bbox.rect, - collector: controlNetCollector, - model, - }); - if (controlNetResult.addedControlNets > 0) { - g.addEdge(controlNetCollector, 'collection', denoise, 'control'); + if (generationMode === 'txt2img') { + canvasOutput = addTextToImage({ + g, + state, + denoise: flux2Denoise, + l2i: flux2L2i, + }); + g.upsertMetadata({ generation_mode: 'flux2_txt2img' }); + } else if (generationMode === 'img2img') { + assert(manager !== null); + const i2l = g.addNode({ + type: 'flux2_vae_encode', + id: getPrefixedId('flux2_vae_encode'), + }); + canvasOutput = await addImageToImage({ + g, + state, + manager, + l2i: flux2L2i, + i2l, + denoise: flux2Denoise, + vaeSource: flux2ModelLoader, + }); + g.upsertMetadata({ generation_mode: 'flux2_img2img' }); + } else if (generationMode === 'inpaint') { + assert(manager !== null); + const i2l = g.addNode({ + type: 'flux2_vae_encode', + id: getPrefixedId('flux2_vae_encode'), + }); + canvasOutput = await addInpaint({ + g, + state, + manager, + l2i: flux2L2i, + i2l, + denoise: flux2Denoise, + vaeSource: flux2ModelLoader, + modelLoader: flux2ModelLoader, + seed, + }); + g.upsertMetadata({ generation_mode: 'flux2_inpaint' }); + } else if (generationMode === 'outpaint') { + assert(manager !== null); + const i2l = g.addNode({ + type: 'flux2_vae_encode', + id: getPrefixedId('flux2_vae_encode'), + }); + canvasOutput = await addOutpaint({ + g, + state, + manager, + l2i: flux2L2i, + i2l, + denoise: flux2Denoise, + vaeSource: flux2ModelLoader, + modelLoader: flux2ModelLoader, + seed, + }); + g.upsertMetadata({ generation_mode: 'flux2_outpaint' }); } else { - g.deleteNode(controlNetCollector.id); + assert>(false); + } + } else { + // Standard FLUX path with all features + const fluxDenoise = denoise as Invocation<'flux_denoise'>; + const fluxModelLoader = modelLoader as Invocation<'flux_model_loader'>; + const fluxPosCond = posCond as Invocation<'flux_text_encoder'>; + const fluxL2i = l2i as Invocation<'flux_vae_decode'>; + + // Only add FLUX LoRAs for non-Klein models + addFLUXLoRAs(state, g, fluxDenoise, fluxModelLoader, fluxPosCond); + + if (isFluxKontextDev) { + const validFLUXKontextConfigs = selectRefImagesSlice(state) + .entities.filter((entity) => entity.isEnabled) + .filter((entity) => isFluxKontextReferenceImageConfig(entity.config)) + .filter((entity) => getGlobalReferenceImageWarnings(entity, model).length === 0); + + if (validFLUXKontextConfigs.length > 0) { + const fluxKontextCollect = g.addNode({ + type: 'collect', + id: getPrefixedId('flux_kontext_collect'), + }); + for (const { config } of validFLUXKontextConfigs) { + const kontextImagePrep = g.addNode({ + id: getPrefixedId('flux_kontext_image_prep'), + type: 'flux_kontext_image_prep', + images: [zImageField.parse(config.image?.crop?.image ?? config.image?.original.image)], + }); + const kontextConditioning = g.addNode({ + type: 'flux_kontext', + id: getPrefixedId('flux_kontext'), + }); + g.addEdge(kontextImagePrep, 'image', kontextConditioning, 'image'); + g.addEdge(kontextConditioning, 'kontext_cond', fluxKontextCollect, 'item'); + } + g.addEdge(fluxKontextCollect, 'collection', fluxDenoise, 'kontext_conditioning'); + + g.upsertMetadata({ ref_images: [validFLUXKontextConfigs] }, 'merge'); + } } - await addControlLoRA({ - manager, - entities: canvas.controlLayers.entities, + if (isFLUXFill && (generationMode === 'inpaint' || generationMode === 'outpaint')) { + assert(manager !== null); + canvasOutput = await addFLUXFill({ + g, + state, + manager, + l2i: fluxL2i, + denoise: fluxDenoise, + }); + } else if (generationMode === 'txt2img') { + canvasOutput = addTextToImage({ + g, + state, + denoise: fluxDenoise, + l2i: fluxL2i, + }); + g.upsertMetadata({ generation_mode: 'flux_txt2img' }); + } else if (generationMode === 'img2img') { + assert(manager !== null); + const i2l = g.addNode({ + type: 'flux_vae_encode', + id: getPrefixedId('flux_vae_encode'), + }); + canvasOutput = await addImageToImage({ + g, + state, + manager, + l2i: fluxL2i, + i2l, + denoise: fluxDenoise, + vaeSource: fluxModelLoader, + }); + g.upsertMetadata({ generation_mode: 'flux_img2img' }); + } else if (generationMode === 'inpaint') { + assert(manager !== null); + const i2l = g.addNode({ + type: 'flux_vae_encode', + id: getPrefixedId('flux_vae_encode'), + }); + canvasOutput = await addInpaint({ + g, + state, + manager, + l2i: fluxL2i, + i2l, + denoise: fluxDenoise, + vaeSource: fluxModelLoader, + modelLoader: fluxModelLoader, + seed, + }); + g.upsertMetadata({ generation_mode: 'flux_inpaint' }); + } else if (generationMode === 'outpaint') { + assert(manager !== null); + const i2l = g.addNode({ + type: 'flux_vae_encode', + id: getPrefixedId('flux_vae_encode'), + }); + canvasOutput = await addOutpaint({ + g, + state, + manager, + l2i: fluxL2i, + i2l, + denoise: fluxDenoise, + vaeSource: fluxModelLoader, + modelLoader: fluxModelLoader, + seed, + }); + g.upsertMetadata({ generation_mode: 'flux_outpaint' }); + } else { + assert>(false); + } + + if (manager !== null) { + const controlNetCollector = g.addNode({ + type: 'collect', + id: getPrefixedId('control_net_collector'), + }); + const controlNetResult = await addControlNets({ + manager, + entities: canvas.controlLayers.entities, + g, + rect: canvas.bbox.rect, + collector: controlNetCollector, + model, + }); + if (controlNetResult.addedControlNets > 0) { + g.addEdge(controlNetCollector, 'collection', fluxDenoise, 'control'); + } else { + g.deleteNode(controlNetCollector.id); + } + + await addControlLoRA({ + manager, + entities: canvas.controlLayers.entities, + g, + rect: canvas.bbox.rect, + denoise: fluxDenoise, + model, + }); + } + + const ipAdapterCollect = g.addNode({ + type: 'collect', + id: getPrefixedId('ip_adapter_collector'), + }); + const ipAdapterResult = addIPAdapters({ + entities: refImages.entities, g, - rect: canvas.bbox.rect, - denoise, + collector: ipAdapterCollect, model, }); - } - const ipAdapterCollect = g.addNode({ - type: 'collect', - id: getPrefixedId('ip_adapter_collector'), - }); - const ipAdapterResult = addIPAdapters({ - entities: refImages.entities, - g, - collector: ipAdapterCollect, - model, - }); + let totalIPAdaptersAdded = ipAdapterResult.addedIPAdapters; - let totalIPAdaptersAdded = ipAdapterResult.addedIPAdapters; - - const fluxReduxCollect = g.addNode({ - type: 'collect', - id: getPrefixedId('ip_adapter_collector'), - }); - const fluxReduxResult = addFLUXReduxes({ - entities: refImages.entities, - g, - collector: fluxReduxCollect, - model, - }); - let totalReduxesAdded = fluxReduxResult.addedFLUXReduxes; - - if (manager !== null) { - const regionsResult = await addRegions({ - manager, - regions: canvas.regionalGuidance.entities, - g, - bbox: canvas.bbox.rect, - model, - posCond, - negCond: null, - posCondCollect, - negCondCollect: null, - ipAdapterCollect, - fluxReduxCollect, + const fluxReduxCollect = g.addNode({ + type: 'collect', + id: getPrefixedId('flux_redux_collector'), }); + const fluxReduxResult = addFLUXReduxes({ + entities: refImages.entities, + g, + collector: fluxReduxCollect, + model, + }); + let totalReduxesAdded = fluxReduxResult.addedFLUXReduxes; - totalIPAdaptersAdded += regionsResult.reduce((acc, r) => acc + r.addedIPAdapters, 0); - totalReduxesAdded += regionsResult.reduce((acc, r) => acc + r.addedFLUXReduxes, 0); - } + // Use posCondCollect from the else block (only exists for standard FLUX, not FLUX.2 Klein) + if (manager !== null && posCondCollect !== null) { + const regionsResult = await addRegions({ + manager, + regions: canvas.regionalGuidance.entities, + g, + bbox: canvas.bbox.rect, + model, + posCond: fluxPosCond, + negCond: null, + posCondCollect: posCondCollect, + negCondCollect: null, + ipAdapterCollect, + fluxReduxCollect, + }); - if (totalIPAdaptersAdded > 0) { - g.addEdge(ipAdapterCollect, 'collection', denoise, 'ip_adapter'); - } else { - g.deleteNode(ipAdapterCollect.id); - } + totalIPAdaptersAdded += regionsResult.reduce((acc, r) => acc + r.addedIPAdapters, 0); + totalReduxesAdded += regionsResult.reduce((acc, r) => acc + r.addedFLUXReduxes, 0); + } - if (totalReduxesAdded > 0) { - g.addEdge(fluxReduxCollect, 'collection', denoise, 'redux_conditioning'); - } else { - g.deleteNode(fluxReduxCollect.id); + if (totalIPAdaptersAdded > 0) { + g.addEdge(ipAdapterCollect, 'collection', fluxDenoise, 'ip_adapter'); + } else { + g.deleteNode(ipAdapterCollect.id); + } + + if (totalReduxesAdded > 0) { + g.addEdge(fluxReduxCollect, 'collection', fluxDenoise, 'redux_conditioning'); + } else { + g.deleteNode(fluxReduxCollect.id); + } } // TODO: Add FLUX Reduxes to denoise node like we do for ipa diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/graphBuilderUtils.ts b/invokeai/frontend/web/src/features/nodes/util/graph/graphBuilderUtils.ts index 0ab1690089..0424f17506 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/graphBuilderUtils.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/graphBuilderUtils.ts @@ -210,6 +210,7 @@ const CANVAS_OUTPUT_PREFIX = 'canvas_output'; export const isMainModelWithoutUnet = (modelLoader: Invocation) => { return ( modelLoader.type === 'flux_model_loader' || + modelLoader.type === 'flux2_klein_model_loader' || modelLoader.type === 'sd3_model_loader' || modelLoader.type === 'cogview4_model_loader' || modelLoader.type === 'z_image_model_loader' @@ -236,17 +237,18 @@ export const getDenoisingStartAndEnd = (state: RootState): { denoising_start: nu denoising_end: 1, }; } - case 'flux': { - if (model.variant === 'dev_fill') { + case 'flux': + case 'flux2': { + if (model.base === 'flux' && model.variant === 'dev_fill') { // This is a FLUX Fill model - we always denoise fully return { denoising_start: 0, denoising_end: 1, }; } else { - // We rescale the img2imgStrength (with exponent 0.2) to effectively use the entire range [0, 1] and make the scale - // more user-friendly for SD3.5. Without this, most of the 'change' is concentrated in the high denoise strength - // range (>0.9). + // FLUX.1 and FLUX.2 Klein: We rescale the img2imgStrength (with exponent 0.2) to effectively use the entire + // range [0, 1] and make the scale more user-friendly. Without this, most of the 'change' is concentrated in + // the high denoise strength range (>0.9). const exponent = optimizedDenoisingEnabled ? 0.2 : 1; return { denoising_start: 1 - denoisingStrength ** exponent, diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/types.ts b/invokeai/frontend/web/src/features/nodes/util/graph/types.ts index fc5a054ebb..334f7449c4 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/types.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/types.ts @@ -12,17 +12,31 @@ export type ImageOutputNodes = | 'invokeai_img_blend' | 'apply_mask_to_image' | 'flux_vae_decode' + | 'flux2_vae_decode' | 'sd3_l2i' | 'cogview4_l2i' | 'z_image_l2i'; -export type LatentToImageNodes = 'l2i' | 'flux_vae_decode' | 'sd3_l2i' | 'cogview4_l2i' | 'z_image_l2i'; +export type LatentToImageNodes = + | 'l2i' + | 'flux_vae_decode' + | 'flux2_vae_decode' + | 'sd3_l2i' + | 'cogview4_l2i' + | 'z_image_l2i'; -export type ImageToLatentsNodes = 'i2l' | 'flux_vae_encode' | 'sd3_i2l' | 'cogview4_i2l' | 'z_image_i2l'; +export type ImageToLatentsNodes = + | 'i2l' + | 'flux_vae_encode' + | 'flux2_vae_encode' + | 'sd3_i2l' + | 'cogview4_i2l' + | 'z_image_i2l'; export type DenoiseLatentsNodes = | 'denoise_latents' | 'flux_denoise' + | 'flux2_denoise' | 'sd3_denoise' | 'cogview4_denoise' | 'z_image_denoise'; @@ -31,6 +45,7 @@ export type MainModelLoaderNodes = | 'main_model_loader' | 'sdxl_model_loader' | 'flux_model_loader' + | 'flux2_klein_model_loader' | 'sd3_model_loader' | 'cogview4_model_loader' | 'z_image_model_loader'; diff --git a/invokeai/frontend/web/src/features/parameters/components/Advanced/ParamFlux2KleinModelSelect.tsx b/invokeai/frontend/web/src/features/parameters/components/Advanced/ParamFlux2KleinModelSelect.tsx new file mode 100644 index 0000000000..1d652a1645 --- /dev/null +++ b/invokeai/frontend/web/src/features/parameters/components/Advanced/ParamFlux2KleinModelSelect.tsx @@ -0,0 +1,144 @@ +import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import { useModelCombobox } from 'common/hooks/useModelCombobox'; +import { + kleinQwen3EncoderModelSelected, + kleinVaeModelSelected, + selectKleinQwen3EncoderModel, + selectKleinVaeModel, + selectMainModelConfig, +} from 'features/controlLayers/store/paramsSlice'; +import { zModelIdentifierField } from 'features/nodes/types/common'; +import { memo, useCallback, useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useFlux2VAEModels, useQwen3EncoderModels } from 'services/api/hooks/modelsByType'; +import type { Qwen3EncoderModelConfig, VAEModelConfig } from 'services/api/types'; + +/** + * FLUX.2 Klein VAE Model Select + * Selects a FLUX.2 VAE model (32-channel AutoencoderKLFlux2) + */ +const ParamFlux2KleinVaeModelSelect = memo(() => { + const dispatch = useAppDispatch(); + const { t } = useTranslation(); + const kleinVaeModel = useAppSelector(selectKleinVaeModel); + const [modelConfigs, { isLoading }] = useFlux2VAEModels(); + + const _onChange = useCallback( + (model: VAEModelConfig | null) => { + if (model) { + dispatch(kleinVaeModelSelected(zModelIdentifierField.parse(model))); + } else { + dispatch(kleinVaeModelSelected(null)); + } + }, + [dispatch] + ); + + const { options, value, onChange, noOptionsMessage } = useModelCombobox({ + modelConfigs, + onChange: _onChange, + selectedModel: kleinVaeModel, + isLoading, + }); + + return ( + + {t('modelManager.flux2KleinVae')} + + + ); +}); + +ParamFlux2KleinVaeModelSelect.displayName = 'ParamFlux2KleinVaeModelSelect'; + +/** + * Maps FLUX.2 Klein variants to compatible Qwen3 encoder variants + */ +const KLEIN_TO_QWEN3_VARIANT_MAP: Record = { + klein_4b: 'qwen3_4b', + klein_9b: 'qwen3_8b', + klein_9b_base: 'qwen3_8b', +}; + +/** + * FLUX.2 Klein Qwen3 Encoder Model Select + * Selects a Qwen3 text encoder model for FLUX.2 Klein + * Only shows encoders compatible with the selected Klein model variant + */ +const ParamFlux2KleinQwen3EncoderModelSelect = memo(() => { + const dispatch = useAppDispatch(); + const { t } = useTranslation(); + const kleinQwen3EncoderModel = useAppSelector(selectKleinQwen3EncoderModel); + const mainModelConfig = useAppSelector(selectMainModelConfig); + const [allModelConfigs, { isLoading }] = useQwen3EncoderModels(); + + // Filter Qwen3 encoders based on the main model's variant + const modelConfigs = useMemo(() => { + if (!mainModelConfig || !('variant' in mainModelConfig) || !mainModelConfig.variant) { + return allModelConfigs; + } + + const requiredQwen3Variant = KLEIN_TO_QWEN3_VARIANT_MAP[mainModelConfig.variant]; + if (!requiredQwen3Variant) { + return allModelConfigs; + } + + return allModelConfigs.filter((config) => config.variant === requiredQwen3Variant); + }, [allModelConfigs, mainModelConfig]); + + const _onChange = useCallback( + (model: Qwen3EncoderModelConfig | null) => { + if (model) { + dispatch(kleinQwen3EncoderModelSelected(zModelIdentifierField.parse(model))); + } else { + dispatch(kleinQwen3EncoderModelSelected(null)); + } + }, + [dispatch] + ); + + const { options, value, onChange, noOptionsMessage } = useModelCombobox({ + modelConfigs, + onChange: _onChange, + selectedModel: kleinQwen3EncoderModel, + isLoading, + }); + + return ( + + {t('modelManager.flux2KleinQwen3Encoder')} + + + ); +}); + +ParamFlux2KleinQwen3EncoderModelSelect.displayName = 'ParamFlux2KleinQwen3EncoderModelSelect'; + +/** + * Combined component for FLUX.2 Klein model selection + */ +const ParamFlux2KleinModelSelects = () => { + return ( + <> + + + + ); +}; + +export default memo(ParamFlux2KleinModelSelects); diff --git a/invokeai/frontend/web/src/features/parameters/components/Advanced/ParamZImageQwen3VaeModelSelect.tsx b/invokeai/frontend/web/src/features/parameters/components/Advanced/ParamZImageQwen3VaeModelSelect.tsx index b4449012f8..fff7698979 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Advanced/ParamZImageQwen3VaeModelSelect.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Advanced/ParamZImageQwen3VaeModelSelect.tsx @@ -12,18 +12,18 @@ import { import { zModelIdentifierField } from 'features/nodes/types/common'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { useFluxVAEModels, useQwen3EncoderModels, useZImageDiffusersModels } from 'services/api/hooks/modelsByType'; +import { useFlux1VAEModels, useQwen3EncoderModels, useZImageDiffusersModels } from 'services/api/hooks/modelsByType'; import type { MainModelConfig, Qwen3EncoderModelConfig, VAEModelConfig } from 'services/api/types'; /** - * Z-Image VAE Model Select - uses FLUX VAE models + * Z-Image VAE Model Select - uses FLUX 1.0 VAE models only (not FLUX.2 Klein VAEs) * Selecting this will clear Qwen3 Source (mutually exclusive) */ const ParamZImageVaeModelSelect = memo(() => { const dispatch = useAppDispatch(); const { t } = useTranslation(); const zImageVaeModel = useAppSelector(selectZImageVaeModel); - const [modelConfigs, { isLoading }] = useFluxVAEModels(); + const [modelConfigs, { isLoading }] = useFlux1VAEModels(); const _onChange = useCallback( (model: VAEModelConfig | null) => { diff --git a/invokeai/frontend/web/src/features/parameters/util/optimalDimension.ts b/invokeai/frontend/web/src/features/parameters/util/optimalDimension.ts index 7157ba8493..fd0d7a240d 100644 --- a/invokeai/frontend/web/src/features/parameters/util/optimalDimension.ts +++ b/invokeai/frontend/web/src/features/parameters/util/optimalDimension.ts @@ -15,6 +15,7 @@ export const getOptimalDimension = (base?: BaseModelType | null): number => { return 512; case 'sdxl': case 'flux': + case 'flux2': case 'sd-3': case 'cogview4': case 'z-image': @@ -71,6 +72,7 @@ export const getGridSize = (base?: BaseModelType | null): number => { case 'cogview4': return 32; case 'flux': + case 'flux2': case 'sd-3': case 'z-image': return 16; diff --git a/invokeai/frontend/web/src/features/queue/hooks/useEnqueueCanvas.ts b/invokeai/frontend/web/src/features/queue/hooks/useEnqueueCanvas.ts index cfdd792737..652cf4c5b2 100644 --- a/invokeai/frontend/web/src/features/queue/hooks/useEnqueueCanvas.ts +++ b/invokeai/frontend/web/src/features/queue/hooks/useEnqueueCanvas.ts @@ -52,7 +52,8 @@ const enqueueCanvas = async (store: AppStore, canvasManager: CanvasManager, prep return await buildSD1Graph(graphBuilderArg); case `sd-3`: return await buildSD3Graph(graphBuilderArg); - case `flux`: + case 'flux': + case 'flux2': return await buildFLUXGraph(graphBuilderArg); case 'cogview4': return await buildCogView4Graph(graphBuilderArg); diff --git a/invokeai/frontend/web/src/features/queue/hooks/useEnqueueGenerate.ts b/invokeai/frontend/web/src/features/queue/hooks/useEnqueueGenerate.ts index 215f35d035..cf00a12ee5 100644 --- a/invokeai/frontend/web/src/features/queue/hooks/useEnqueueGenerate.ts +++ b/invokeai/frontend/web/src/features/queue/hooks/useEnqueueGenerate.ts @@ -45,7 +45,8 @@ const enqueueGenerate = async (store: AppStore, prepend: boolean) => { return await buildSD1Graph(graphBuilderArg); case `sd-3`: return await buildSD3Graph(graphBuilderArg); - case `flux`: + case 'flux': + case 'flux2': return await buildFLUXGraph(graphBuilderArg); case 'cogview4': return await buildCogView4Graph(graphBuilderArg); diff --git a/invokeai/frontend/web/src/features/queue/store/readiness.ts b/invokeai/frontend/web/src/features/queue/store/readiness.ts index 4da65c511d..8fa97eff4a 100644 --- a/invokeai/frontend/web/src/features/queue/store/readiness.ts +++ b/invokeai/frontend/web/src/features/queue/store/readiness.ts @@ -255,6 +255,8 @@ const getReasonsWhyCannotEnqueueGenerateTab = (arg: { } } + // FLUX.2 (Klein) extracts Qwen3 encoder and VAE from main model - no separate selections needed + if (model?.base === 'z-image') { // Check if VAE source is available (either separate VAE or Qwen3 Source) const hasVaeSource = params.zImageVaeModel !== null || params.zImageQwen3SourceModel !== null; @@ -541,6 +543,53 @@ const getReasonsWhyCannotEnqueueCanvasTab = (arg: { } } + if (model?.base === 'flux2') { + // FLUX.2 (Klein) extracts Qwen3 encoder and VAE from main model - no separate selections needed + + const { bbox } = canvas; + const gridSize = getGridSize('flux'); // FLUX.2 uses same grid size as FLUX.1 + + if (bbox.scaleMethod === 'none') { + if (bbox.rect.width % gridSize !== 0) { + reasons.push({ + content: i18n.t('parameters.invoke.modelIncompatibleBboxWidth', { + model: 'FLUX.2', + width: bbox.rect.width, + multiple: gridSize, + }), + }); + } + if (bbox.rect.height % gridSize !== 0) { + reasons.push({ + content: i18n.t('parameters.invoke.modelIncompatibleBboxHeight', { + model: 'FLUX.2', + height: bbox.rect.height, + multiple: gridSize, + }), + }); + } + } else { + if (bbox.scaledSize.width % gridSize !== 0) { + reasons.push({ + content: i18n.t('parameters.invoke.modelIncompatibleScaledBboxWidth', { + model: 'FLUX.2', + width: bbox.scaledSize.width, + multiple: gridSize, + }), + }); + } + if (bbox.scaledSize.height % gridSize !== 0) { + reasons.push({ + content: i18n.t('parameters.invoke.modelIncompatibleScaledBboxHeight', { + model: 'FLUX.2', + height: bbox.scaledSize.height, + multiple: gridSize, + }), + }); + } + } + } + if (model?.base === 'cogview4') { const { bbox } = canvas; const gridSize = getGridSize('cogview4'); diff --git a/invokeai/frontend/web/src/features/settingsAccordions/components/AdvancedSettingsAccordion/AdvancedSettingsAccordion.tsx b/invokeai/frontend/web/src/features/settingsAccordions/components/AdvancedSettingsAccordion/AdvancedSettingsAccordion.tsx index e52d3ad40d..eddf82e922 100644 --- a/invokeai/frontend/web/src/features/settingsAccordions/components/AdvancedSettingsAccordion/AdvancedSettingsAccordion.tsx +++ b/invokeai/frontend/web/src/features/settingsAccordions/components/AdvancedSettingsAccordion/AdvancedSettingsAccordion.tsx @@ -5,6 +5,7 @@ import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; import { useAppSelector } from 'app/store/storeHooks'; import { selectIsFLUX, + selectIsFlux2, selectIsSD3, selectIsZImage, selectParamsSlice, @@ -15,6 +16,7 @@ import ParamCLIPEmbedModelSelect from 'features/parameters/components/Advanced/P import ParamCLIPGEmbedModelSelect from 'features/parameters/components/Advanced/ParamCLIPGEmbedModelSelect'; import ParamCLIPLEmbedModelSelect from 'features/parameters/components/Advanced/ParamCLIPLEmbedModelSelect'; import ParamClipSkip from 'features/parameters/components/Advanced/ParamClipSkip'; +import ParamFlux2KleinModelSelect from 'features/parameters/components/Advanced/ParamFlux2KleinModelSelect'; import ParamT5EncoderModelSelect from 'features/parameters/components/Advanced/ParamT5EncoderModelSelect'; import ParamZImageQwen3VaeModelSelect from 'features/parameters/components/Advanced/ParamZImageQwen3VaeModelSelect'; import ParamSeamlessXAxis from 'features/parameters/components/Seamless/ParamSeamlessXAxis'; @@ -40,14 +42,16 @@ export const AdvancedSettingsAccordion = memo(() => { const vaeKey = useAppSelector(selectVAEKey); const { currentData: vaeConfig } = useGetModelConfigQuery(vaeKey ?? skipToken); const isFLUX = useAppSelector(selectIsFLUX); + const isFlux2 = useAppSelector(selectIsFlux2); const isSD3 = useAppSelector(selectIsSD3); const isZImage = useAppSelector(selectIsZImage); const selectBadges = useMemo( () => - createMemoizedSelector([selectParamsSlice, selectIsFLUX], (params, isFLUX) => { + createMemoizedSelector([selectParamsSlice, selectIsFLUX, selectIsFlux2], (params, isFLUX, isFlux2) => { const badges: (string | number)[] = []; - if (isFLUX) { + // FLUX.2 has VAE built into main model - no badge needed + if (isFLUX && !isFlux2) { if (vaeConfig) { let vaeBadge = vaeConfig.name; if (params.vaePrecision === 'fp16') { @@ -55,7 +59,7 @@ export const AdvancedSettingsAccordion = memo(() => { } badges.push(vaeBadge); } - } else { + } else if (!isFlux2) { if (vaeConfig) { let vaeBadge = vaeConfig.name; if (params.vaePrecision === 'fp16') { @@ -90,13 +94,13 @@ export const AdvancedSettingsAccordion = memo(() => { return ( - {!isZImage && ( + {!isZImage && !isFlux2 && ( {isFLUX ? : } {!isFLUX && !isSD3 && } )} - {!isFLUX && !isSD3 && !isZImage && ( + {!isFLUX && !isFlux2 && !isSD3 && !isZImage && ( <> @@ -115,12 +119,17 @@ export const AdvancedSettingsAccordion = memo(() => { )} - {isFLUX && ( + {isFLUX && !isFlux2 && ( )} + {isFlux2 && ( + + + + )} {isSD3 && ( diff --git a/invokeai/frontend/web/src/features/settingsAccordions/components/GenerationSettingsAccordion/GenerationSettingsAccordion.tsx b/invokeai/frontend/web/src/features/settingsAccordions/components/GenerationSettingsAccordion/GenerationSettingsAccordion.tsx index 90ad40c7cf..814a942a08 100644 --- a/invokeai/frontend/web/src/features/settingsAccordions/components/GenerationSettingsAccordion/GenerationSettingsAccordion.tsx +++ b/invokeai/frontend/web/src/features/settingsAccordions/components/GenerationSettingsAccordion/GenerationSettingsAccordion.tsx @@ -4,7 +4,13 @@ import { EMPTY_ARRAY } from 'app/store/constants'; import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; import { useAppSelector } from 'app/store/storeHooks'; import { selectLoRAsSlice } from 'features/controlLayers/store/lorasSlice'; -import { selectIsCogView4, selectIsFLUX, selectIsSD3, selectIsZImage } from 'features/controlLayers/store/paramsSlice'; +import { + selectIsCogView4, + selectIsFLUX, + selectIsFlux2, + selectIsSD3, + selectIsZImage, +} from 'features/controlLayers/store/paramsSlice'; import { LoRAList } from 'features/lora/components/LoRAList'; import LoRASelect from 'features/lora/components/LoRASelect'; import ParamCFGScale from 'features/parameters/components/Core/ParamCFGScale'; @@ -30,6 +36,7 @@ export const GenerationSettingsAccordion = memo(() => { const { t } = useTranslation(); const modelConfig = useSelectedModelConfig(); const isFLUX = useAppSelector(selectIsFLUX); + const isFlux2 = useAppSelector(selectIsFlux2); const isSD3 = useAppSelector(selectIsSD3); const isCogView4 = useAppSelector(selectIsCogView4); const isZImage = useAppSelector(selectIsZImage); @@ -70,12 +77,12 @@ export const GenerationSettingsAccordion = memo(() => { - {!isFLUX && !isSD3 && !isCogView4 && !isZImage && } - {isFLUX && } + {!isFLUX && !isFlux2 && !isSD3 && !isCogView4 && !isZImage && } + {(isFLUX || isFlux2) && } {isZImage && } - {isFLUX && modelConfig && !isFluxFillMainModelModelConfig(modelConfig) && } - {!isFLUX && } + {(isFLUX || isFlux2) && modelConfig && !isFluxFillMainModelModelConfig(modelConfig) && } + {!isFLUX && !isFlux2 && } {isZImage && } diff --git a/invokeai/frontend/web/src/features/settingsAccordions/components/GenerationSettingsAccordion/MainModelPicker.tsx b/invokeai/frontend/web/src/features/settingsAccordions/components/GenerationSettingsAccordion/MainModelPicker.tsx index 312ea2dd1e..773b67e39b 100644 --- a/invokeai/frontend/web/src/features/settingsAccordions/components/GenerationSettingsAccordion/MainModelPicker.tsx +++ b/invokeai/frontend/web/src/features/settingsAccordions/components/GenerationSettingsAccordion/MainModelPicker.tsx @@ -9,7 +9,7 @@ import { useTranslation } from 'react-i18next'; import { MdMoneyOff } from 'react-icons/md'; import { useMainModels } from 'services/api/hooks/modelsByType'; import { useSelectedModelConfig } from 'services/api/hooks/useSelectedModelConfig'; -import { type AnyModelConfig, isFluxDevMainModelConfig } from 'services/api/types'; +import { type AnyModelConfig, isNonCommercialMainModelConfig } from 'services/api/types'; export const MainModelPicker = memo(() => { const { t } = useTranslation(); @@ -23,8 +23,8 @@ export const MainModelPicker = memo(() => { [dispatch] ); - const isFluxDevSelected = useMemo( - () => selectedModelConfig && isFluxDevMainModelConfig(selectedModelConfig), + const isNonCommercialSelected = useMemo( + () => selectedModelConfig && isNonCommercialMainModelConfig(selectedModelConfig), [selectedModelConfig] ); @@ -33,7 +33,7 @@ export const MainModelPicker = memo(() => { {t('modelManager.model')} - {isFluxDevSelected && ( + {isNonCommercialSelected && ( diff --git a/invokeai/frontend/web/src/features/ui/layouts/InitialStateMainModelPicker.tsx b/invokeai/frontend/web/src/features/ui/layouts/InitialStateMainModelPicker.tsx index 89dc612c9a..0d71b62173 100644 --- a/invokeai/frontend/web/src/features/ui/layouts/InitialStateMainModelPicker.tsx +++ b/invokeai/frontend/web/src/features/ui/layouts/InitialStateMainModelPicker.tsx @@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next'; import { MdMoneyOff } from 'react-icons/md'; import { useMainModels } from 'services/api/hooks/modelsByType'; import { useSelectedModelConfig } from 'services/api/hooks/useSelectedModelConfig'; -import { type AnyModelConfig, isFluxDevMainModelConfig } from 'services/api/types'; +import { type AnyModelConfig, isNonCommercialMainModelConfig } from 'services/api/types'; export const InitialStateMainModelPicker = memo(() => { const { t } = useTranslation(); @@ -22,8 +22,8 @@ export const InitialStateMainModelPicker = memo(() => { [dispatch] ); - const isFluxDevSelected = useMemo( - () => selectedModelConfig && isFluxDevMainModelConfig(selectedModelConfig), + const isNonCommercialSelected = useMemo( + () => selectedModelConfig && isNonCommercialMainModelConfig(selectedModelConfig), [selectedModelConfig] ); @@ -31,7 +31,7 @@ export const InitialStateMainModelPicker = memo(() => { {t('common.selectYourModel')}{' '} - {isFluxDevSelected && ( + {isNonCommercialSelected && ( diff --git a/invokeai/frontend/web/src/services/api/hooks/modelsByType.ts b/invokeai/frontend/web/src/services/api/hooks/modelsByType.ts index 56cf9a9665..b771dd7840 100644 --- a/invokeai/frontend/web/src/services/api/hooks/modelsByType.ts +++ b/invokeai/frontend/web/src/services/api/hooks/modelsByType.ts @@ -12,6 +12,8 @@ import { isCLIPEmbedModelConfigOrSubmodel, isControlLayerModelConfig, isControlNetModelConfig, + isFlux1VAEModelConfig, + isFlux2VAEModelConfig, isFluxKontextModelConfig, isFluxReduxModelConfig, isFluxVAEModelConfig, @@ -55,6 +57,8 @@ export const useSpandrelImageToImageModels = buildModelsHook(isSpandrelImageToIm export const useEmbeddingModels = buildModelsHook(isTIModelConfig); export const useVAEModels = () => buildModelsHook(isVAEModelConfigOrSubmodel)(); export const useFluxVAEModels = () => buildModelsHook(isFluxVAEModelConfig)(); +export const useFlux1VAEModels = () => buildModelsHook(isFlux1VAEModelConfig)(); +export const useFlux2VAEModels = () => buildModelsHook(isFlux2VAEModelConfig)(); export const useZImageDiffusersModels = () => buildModelsHook(isZImageDiffusersMainModelConfig)(); export const useQwen3EncoderModels = () => buildModelsHook(isQwen3EncoderModelConfig)(); export const useGlobalReferenceImageModels = buildModelsHook( diff --git a/invokeai/frontend/web/src/services/api/schema.ts b/invokeai/frontend/web/src/services/api/schema.ts index 829c5d435c..ccb5854a23 100644 --- a/invokeai/frontend/web/src/services/api/schema.ts +++ b/invokeai/frontend/web/src/services/api/schema.ts @@ -2056,7 +2056,7 @@ export type components = { */ type: "alpha_mask_to_tensor"; }; - AnyModelConfig: components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; + AnyModelConfig: components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_FLUX_Config"] | components["schemas"]["Main_Diffusers_Flux2_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_Flux2_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_Flux2_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Checkpoint_Flux2_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["VAE_Diffusers_Flux2_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; /** * AppVersion * @description App Version Response @@ -2208,7 +2208,7 @@ export type components = { * fallback/null value `BaseModelType.Any` for these models, instead of making the model base optional. * @enum {string} */ - BaseModelType: "any" | "sd-1" | "sd-2" | "sd-3" | "sdxl" | "sdxl-refiner" | "flux" | "cogview4" | "z-image" | "unknown"; + BaseModelType: "any" | "sd-1" | "sd-2" | "sd-3" | "sdxl" | "sdxl-refiner" | "flux" | "flux2" | "cogview4" | "z-image" | "unknown"; /** Batch */ Batch: { /** @@ -5802,7 +5802,7 @@ export type components = { * @description The generation mode that output this image * @default null */ - generation_mode?: ("txt2img" | "img2img" | "inpaint" | "outpaint" | "sdxl_txt2img" | "sdxl_img2img" | "sdxl_inpaint" | "sdxl_outpaint" | "flux_txt2img" | "flux_img2img" | "flux_inpaint" | "flux_outpaint" | "sd3_txt2img" | "sd3_img2img" | "sd3_inpaint" | "sd3_outpaint" | "cogview4_txt2img" | "cogview4_img2img" | "cogview4_inpaint" | "cogview4_outpaint" | "z_image_txt2img" | "z_image_img2img" | "z_image_inpaint" | "z_image_outpaint") | null; + generation_mode?: ("txt2img" | "img2img" | "inpaint" | "outpaint" | "sdxl_txt2img" | "sdxl_img2img" | "sdxl_inpaint" | "sdxl_outpaint" | "flux_txt2img" | "flux_img2img" | "flux_inpaint" | "flux_outpaint" | "flux2_txt2img" | "flux2_img2img" | "flux2_inpaint" | "flux2_outpaint" | "sd3_txt2img" | "sd3_img2img" | "sd3_inpaint" | "sd3_outpaint" | "cogview4_txt2img" | "cogview4_img2img" | "cogview4_inpaint" | "cogview4_outpaint" | "z_image_txt2img" | "z_image_img2img" | "z_image_inpaint" | "z_image_outpaint") | null; /** * Positive Prompt * @description The positive prompt parameter @@ -7969,6 +7969,382 @@ export type components = { */ type: "float_to_int"; }; + /** + * FLUX2 Denoise + * @description Run denoising process with a FLUX.2 Klein transformer model. + * + * This node is designed for FLUX.2 Klein models which use Qwen3 as the text encoder. + * It does not support ControlNet, IP-Adapters, or regional prompting. + */ + Flux2DenoiseInvocation: { + /** + * 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. Values of 0.0 represent the regions to be fully denoised, and 1.0 represent the regions to be preserved. + * @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; + /** + * Add Noise + * @description Add noise based on denoising start. + * @default true + */ + add_noise?: boolean; + /** + * Transformer + * @description Flux model (Transformer) to load + * @default null + */ + transformer?: components["schemas"]["TransformerField"] | null; + /** + * @description Positive conditioning tensor + * @default null + */ + positive_text_conditioning?: components["schemas"]["FluxConditioningField"] | null; + /** + * @description Negative conditioning tensor. Can be None if cfg_scale is 1.0. + * @default null + */ + negative_text_conditioning?: components["schemas"]["FluxConditioningField"] | null; + /** + * CFG Scale + * @description Classifier-Free Guidance scale + * @default 1 + */ + cfg_scale?: number; + /** + * 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. Use 4 for distilled models, 28+ for base models. + * @default 4 + */ + num_steps?: number; + /** + * Scheduler + * @description Scheduler (sampler) for the denoising process. 'euler' is fast and standard. 'heun' is 2nd-order (better quality, 2x slower). 'lcm' is optimized for few steps. + * @default euler + * @enum {string} + */ + scheduler?: "euler" | "heun" | "lcm"; + /** + * Seed + * @description Randomness seed for reproducibility. + * @default 0 + */ + seed?: number; + /** + * @description FLUX.2 VAE model (required for BN statistics). + * @default null + */ + vae?: components["schemas"]["VAEField"] | null; + /** + * Reference Images + * @description FLUX Kontext conditioning (reference images for multi-reference image editing). + * @default null + */ + kontext_conditioning?: components["schemas"]["FluxKontextConditioningField"] | components["schemas"]["FluxKontextConditioningField"][] | null; + /** + * type + * @default flux2_denoise + * @constant + */ + type: "flux2_denoise"; + }; + /** + * Main Model - Flux2 Klein + * @description Loads a Flux2 Klein model, outputting its submodels. + * + * Flux2 Klein uses Qwen3 as the text encoder instead of CLIP+T5. + * It uses a 32-channel VAE (AutoencoderKLFlux2) instead of the 16-channel FLUX.1 VAE. + * + * When using a Diffusers format model, both VAE and Qwen3 encoder are extracted + * automatically from the main model. You can override with standalone models: + * - Transformer: Always from Flux2 Klein main model + * - VAE: From main model (Diffusers) or standalone VAE + * - Qwen3 Encoder: From main model (Diffusers) or standalone Qwen3 model + */ + Flux2KleinModelLoaderInvocation: { + /** + * 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; + /** + * Transformer + * @description Flux model (Transformer) to load + */ + model: components["schemas"]["ModelIdentifierField"]; + /** + * VAE + * @description Standalone VAE model. Flux2 Klein uses the same VAE as FLUX (16-channel). If not provided, VAE will be loaded from the Qwen3 Source model. + * @default null + */ + vae_model?: components["schemas"]["ModelIdentifierField"] | null; + /** + * Qwen3 Encoder + * @description Standalone Qwen3 Encoder model. If not provided, encoder will be loaded from the Qwen3 Source model. + * @default null + */ + qwen3_encoder_model?: components["schemas"]["ModelIdentifierField"] | null; + /** + * Qwen3 Source (Diffusers) + * @description Diffusers Flux2 Klein model to extract VAE and/or Qwen3 encoder from. Use this if you don't have separate VAE/Qwen3 models. Ignored if both VAE and Qwen3 Encoder are provided separately. + * @default null + */ + qwen3_source_model?: components["schemas"]["ModelIdentifierField"] | null; + /** + * Max Seq Length + * @description Max sequence length for the Qwen3 encoder. + * @default 512 + * @enum {integer} + */ + max_seq_len?: 256 | 512; + /** + * type + * @default flux2_klein_model_loader + * @constant + */ + type: "flux2_klein_model_loader"; + }; + /** + * Flux2KleinModelLoaderOutput + * @description Flux2 Klein model loader output. + */ + Flux2KleinModelLoaderOutput: { + /** + * Transformer + * @description Transformer + */ + transformer: components["schemas"]["TransformerField"]; + /** + * Qwen3 Encoder + * @description Qwen3 tokenizer and text encoder + */ + qwen3_encoder: components["schemas"]["Qwen3EncoderField"]; + /** + * VAE + * @description VAE + */ + vae: components["schemas"]["VAEField"]; + /** + * Max Seq Length + * @description The max sequence length for the Qwen3 encoder. + * @enum {integer} + */ + max_seq_len: 256 | 512; + /** + * type + * @default flux2_klein_model_loader_output + * @constant + */ + type: "flux2_klein_model_loader_output"; + }; + /** + * Prompt - Flux2 Klein + * @description Encodes and preps a prompt for Flux2 Klein image generation. + * + * Flux2 Klein uses Qwen3 as the text encoder, extracting hidden states from + * layers (9, 18, 27) and stacking them for richer text representations. + * This matches the diffusers Flux2KleinPipeline implementation exactly. + */ + Flux2KleinTextEncoderInvocation: { + /** + * 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; + /** + * Prompt + * @description Text prompt to encode. + * @default null + */ + prompt?: string | null; + /** + * Qwen3 Encoder + * @description Qwen3 tokenizer and text encoder + * @default null + */ + qwen3_encoder?: components["schemas"]["Qwen3EncoderField"] | null; + /** + * Max Seq Len + * @description Max sequence length for the Qwen3 encoder. + * @default 512 + * @enum {integer} + */ + max_seq_len?: 256 | 512; + /** + * @description A mask defining the region that this conditioning prompt applies to. + * @default null + */ + mask?: components["schemas"]["TensorField"] | null; + /** + * type + * @default flux2_klein_text_encoder + * @constant + */ + type: "flux2_klein_text_encoder"; + }; + /** + * Latents to Image - FLUX2 + * @description Generates an image from latents using FLUX.2 Klein's 32-channel VAE. + */ + Flux2VaeDecodeInvocation: { + /** + * @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 VAE + * @default null + */ + vae?: components["schemas"]["VAEField"] | null; + /** + * type + * @default flux2_vae_decode + * @constant + */ + type: "flux2_vae_decode"; + }; + /** + * Image to Latents - FLUX2 + * @description Encodes an image into latents using FLUX.2 Klein's 32-channel VAE. + */ + Flux2VaeEncodeInvocation: { + /** + * 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 The image to encode. + * @default null + */ + image?: components["schemas"]["ImageField"] | null; + /** + * @description VAE + * @default null + */ + vae?: components["schemas"]["VAEField"] | null; + /** + * type + * @default flux2_vae_encode + * @constant + */ + type: "flux2_vae_encode"; + }; + /** + * Flux2VariantType + * @description FLUX.2 model variants. + * @enum {string} + */ + Flux2VariantType: "klein_4b" | "klein_9b" | "klein_9b_base"; /** * FluxConditioningCollectionOutput * @description Base class for nodes that output a collection of conditioning tensors @@ -9205,6 +9581,7 @@ export type components = { }; /** * FluxVariantType + * @description FLUX.1 model variants. * @enum {string} */ FluxVariantType: "schnell" | "dev" | "dev_fill"; @@ -9397,7 +9774,7 @@ export type components = { * @description The nodes in this graph */ nodes?: { - [key: string]: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["ApplyMaskTensorToImageInvocation"] | components["schemas"]["ApplyMaskToImageInvocation"] | 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"]["CannyEdgeDetectionInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CanvasV2MaskAndCropInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CogView4DenoiseInvocation"] | components["schemas"]["CogView4ImageToLatentsInvocation"] | components["schemas"]["CogView4LatentsToImageInvocation"] | components["schemas"]["CogView4ModelLoaderInvocation"] | components["schemas"]["CogView4TextEncoderInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropImageToBoundingBoxInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeDetectionInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DenoiseLatentsMetaInvocation"] | components["schemas"]["DepthAnythingDepthEstimationInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["ExpandMaskWithFadeInvocation"] | components["schemas"]["FLUXLoRACollectionLoader"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatBatchInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatGenerator"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["FluxControlLoRALoaderInvocation"] | components["schemas"]["FluxControlNetInvocation"] | components["schemas"]["FluxDenoiseInvocation"] | components["schemas"]["FluxDenoiseLatentsMetaInvocation"] | components["schemas"]["FluxFillInvocation"] | components["schemas"]["FluxIPAdapterInvocation"] | components["schemas"]["FluxKontextConcatenateImagesInvocation"] | components["schemas"]["FluxKontextInvocation"] | components["schemas"]["FluxLoRALoaderInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxReduxInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxVaeDecodeInvocation"] | components["schemas"]["FluxVaeEncodeInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GetMaskBoundingBoxInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HEDEdgeDetectionInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBatchInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageGenerator"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImageNoiseInvocation"] | components["schemas"]["ImagePanelLayoutInvocation"] | 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"]["IntegerBatchInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerGenerator"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["InvokeAdjustImageHuePlusInvocation"] | components["schemas"]["InvokeEquivalentAchromaticLightnessInvocation"] | components["schemas"]["InvokeImageBlendInvocation"] | components["schemas"]["InvokeImageCompositorInvocation"] | components["schemas"]["InvokeImageDilateOrErodeInvocation"] | components["schemas"]["InvokeImageEnhanceInvocation"] | components["schemas"]["InvokeImageValueThresholdsInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LineartAnimeEdgeDetectionInvocation"] | components["schemas"]["LineartEdgeDetectionInvocation"] | components["schemas"]["LlavaOnevisionVllmInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MLSDDetectionInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediaPipeFaceDetectionInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataFieldExtractorInvocation"] | components["schemas"]["MetadataFromImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MetadataItemLinkedInvocation"] | components["schemas"]["MetadataToBoolCollectionInvocation"] | components["schemas"]["MetadataToBoolInvocation"] | components["schemas"]["MetadataToControlnetsInvocation"] | components["schemas"]["MetadataToFloatCollectionInvocation"] | components["schemas"]["MetadataToFloatInvocation"] | components["schemas"]["MetadataToIPAdaptersInvocation"] | components["schemas"]["MetadataToIntegerCollectionInvocation"] | components["schemas"]["MetadataToIntegerInvocation"] | components["schemas"]["MetadataToLorasCollectionInvocation"] | components["schemas"]["MetadataToLorasInvocation"] | components["schemas"]["MetadataToModelInvocation"] | components["schemas"]["MetadataToSDXLLorasInvocation"] | components["schemas"]["MetadataToSDXLModelInvocation"] | components["schemas"]["MetadataToSchedulerInvocation"] | components["schemas"]["MetadataToStringCollectionInvocation"] | components["schemas"]["MetadataToStringInvocation"] | components["schemas"]["MetadataToT2IAdaptersInvocation"] | components["schemas"]["MetadataToVAEInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalMapInvocation"] | components["schemas"]["PBRMapsInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PasteImageIntoBoundingBoxInvocation"] | components["schemas"]["PiDiNetEdgeDetectionInvocation"] | components["schemas"]["PromptTemplateInvocation"] | 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"]["SD3DenoiseInvocation"] | components["schemas"]["SD3ImageToLatentsInvocation"] | components["schemas"]["SD3LatentsToImageInvocation"] | 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"]["Sd3ModelLoaderInvocation"] | components["schemas"]["Sd3TextEncoderInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StringBatchInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringGenerator"] | 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"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZImageControlInvocation"] | components["schemas"]["ZImageDenoiseInvocation"] | components["schemas"]["ZImageDenoiseMetaInvocation"] | components["schemas"]["ZImageImageToLatentsInvocation"] | components["schemas"]["ZImageLatentsToImageInvocation"] | components["schemas"]["ZImageLoRACollectionLoader"] | components["schemas"]["ZImageLoRALoaderInvocation"] | components["schemas"]["ZImageModelLoaderInvocation"] | components["schemas"]["ZImageSeedVarianceEnhancerInvocation"] | components["schemas"]["ZImageTextEncoderInvocation"]; + [key: string]: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["ApplyMaskTensorToImageInvocation"] | components["schemas"]["ApplyMaskToImageInvocation"] | 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"]["CannyEdgeDetectionInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CanvasV2MaskAndCropInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CogView4DenoiseInvocation"] | components["schemas"]["CogView4ImageToLatentsInvocation"] | components["schemas"]["CogView4LatentsToImageInvocation"] | components["schemas"]["CogView4ModelLoaderInvocation"] | components["schemas"]["CogView4TextEncoderInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropImageToBoundingBoxInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeDetectionInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DenoiseLatentsMetaInvocation"] | components["schemas"]["DepthAnythingDepthEstimationInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["ExpandMaskWithFadeInvocation"] | components["schemas"]["FLUXLoRACollectionLoader"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatBatchInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatGenerator"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["Flux2DenoiseInvocation"] | components["schemas"]["Flux2KleinModelLoaderInvocation"] | components["schemas"]["Flux2KleinTextEncoderInvocation"] | components["schemas"]["Flux2VaeDecodeInvocation"] | components["schemas"]["Flux2VaeEncodeInvocation"] | components["schemas"]["FluxControlLoRALoaderInvocation"] | components["schemas"]["FluxControlNetInvocation"] | components["schemas"]["FluxDenoiseInvocation"] | components["schemas"]["FluxDenoiseLatentsMetaInvocation"] | components["schemas"]["FluxFillInvocation"] | components["schemas"]["FluxIPAdapterInvocation"] | components["schemas"]["FluxKontextConcatenateImagesInvocation"] | components["schemas"]["FluxKontextInvocation"] | components["schemas"]["FluxLoRALoaderInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxReduxInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxVaeDecodeInvocation"] | components["schemas"]["FluxVaeEncodeInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GetMaskBoundingBoxInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HEDEdgeDetectionInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBatchInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageGenerator"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImageNoiseInvocation"] | components["schemas"]["ImagePanelLayoutInvocation"] | 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"]["IntegerBatchInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerGenerator"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["InvokeAdjustImageHuePlusInvocation"] | components["schemas"]["InvokeEquivalentAchromaticLightnessInvocation"] | components["schemas"]["InvokeImageBlendInvocation"] | components["schemas"]["InvokeImageCompositorInvocation"] | components["schemas"]["InvokeImageDilateOrErodeInvocation"] | components["schemas"]["InvokeImageEnhanceInvocation"] | components["schemas"]["InvokeImageValueThresholdsInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LineartAnimeEdgeDetectionInvocation"] | components["schemas"]["LineartEdgeDetectionInvocation"] | components["schemas"]["LlavaOnevisionVllmInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MLSDDetectionInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediaPipeFaceDetectionInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataFieldExtractorInvocation"] | components["schemas"]["MetadataFromImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MetadataItemLinkedInvocation"] | components["schemas"]["MetadataToBoolCollectionInvocation"] | components["schemas"]["MetadataToBoolInvocation"] | components["schemas"]["MetadataToControlnetsInvocation"] | components["schemas"]["MetadataToFloatCollectionInvocation"] | components["schemas"]["MetadataToFloatInvocation"] | components["schemas"]["MetadataToIPAdaptersInvocation"] | components["schemas"]["MetadataToIntegerCollectionInvocation"] | components["schemas"]["MetadataToIntegerInvocation"] | components["schemas"]["MetadataToLorasCollectionInvocation"] | components["schemas"]["MetadataToLorasInvocation"] | components["schemas"]["MetadataToModelInvocation"] | components["schemas"]["MetadataToSDXLLorasInvocation"] | components["schemas"]["MetadataToSDXLModelInvocation"] | components["schemas"]["MetadataToSchedulerInvocation"] | components["schemas"]["MetadataToStringCollectionInvocation"] | components["schemas"]["MetadataToStringInvocation"] | components["schemas"]["MetadataToT2IAdaptersInvocation"] | components["schemas"]["MetadataToVAEInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalMapInvocation"] | components["schemas"]["PBRMapsInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PasteImageIntoBoundingBoxInvocation"] | components["schemas"]["PiDiNetEdgeDetectionInvocation"] | components["schemas"]["PromptTemplateInvocation"] | 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"]["SD3DenoiseInvocation"] | components["schemas"]["SD3ImageToLatentsInvocation"] | components["schemas"]["SD3LatentsToImageInvocation"] | 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"]["Sd3ModelLoaderInvocation"] | components["schemas"]["Sd3TextEncoderInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StringBatchInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringGenerator"] | 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"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZImageControlInvocation"] | components["schemas"]["ZImageDenoiseInvocation"] | components["schemas"]["ZImageDenoiseMetaInvocation"] | components["schemas"]["ZImageImageToLatentsInvocation"] | components["schemas"]["ZImageLatentsToImageInvocation"] | components["schemas"]["ZImageLoRACollectionLoader"] | components["schemas"]["ZImageLoRALoaderInvocation"] | components["schemas"]["ZImageModelLoaderInvocation"] | components["schemas"]["ZImageSeedVarianceEnhancerInvocation"] | components["schemas"]["ZImageTextEncoderInvocation"]; }; /** * Edges @@ -9434,7 +9811,7 @@ export type components = { * @description The results of node executions */ results: { - [key: string]: components["schemas"]["BooleanCollectionOutput"] | components["schemas"]["BooleanOutput"] | components["schemas"]["BoundingBoxCollectionOutput"] | components["schemas"]["BoundingBoxOutput"] | components["schemas"]["CLIPOutput"] | components["schemas"]["CLIPSkipInvocationOutput"] | components["schemas"]["CalculateImageTilesOutput"] | components["schemas"]["CogView4ConditioningOutput"] | components["schemas"]["CogView4ModelLoaderOutput"] | components["schemas"]["CollectInvocationOutput"] | components["schemas"]["ColorCollectionOutput"] | components["schemas"]["ColorOutput"] | components["schemas"]["ConditioningCollectionOutput"] | components["schemas"]["ConditioningOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["DenoiseMaskOutput"] | components["schemas"]["FaceMaskOutput"] | components["schemas"]["FaceOffOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["FloatGeneratorOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["FluxConditioningCollectionOutput"] | components["schemas"]["FluxConditioningOutput"] | components["schemas"]["FluxControlLoRALoaderOutput"] | components["schemas"]["FluxControlNetOutput"] | components["schemas"]["FluxFillOutput"] | components["schemas"]["FluxKontextOutput"] | components["schemas"]["FluxLoRALoaderOutput"] | components["schemas"]["FluxModelLoaderOutput"] | components["schemas"]["FluxReduxOutput"] | components["schemas"]["GradientMaskOutput"] | components["schemas"]["IPAdapterOutput"] | components["schemas"]["IdealSizeOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["ImageGeneratorOutput"] | components["schemas"]["ImageOutput"] | components["schemas"]["ImagePanelCoordinateOutput"] | components["schemas"]["IntegerCollectionOutput"] | components["schemas"]["IntegerGeneratorOutput"] | components["schemas"]["IntegerOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["LatentsCollectionOutput"] | components["schemas"]["LatentsMetaOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["LoRALoaderOutput"] | components["schemas"]["LoRASelectorOutput"] | components["schemas"]["MDControlListOutput"] | components["schemas"]["MDIPAdapterListOutput"] | components["schemas"]["MDT2IAdapterListOutput"] | components["schemas"]["MaskOutput"] | components["schemas"]["MetadataItemOutput"] | components["schemas"]["MetadataOutput"] | components["schemas"]["MetadataToLorasCollectionOutput"] | components["schemas"]["MetadataToModelOutput"] | components["schemas"]["MetadataToSDXLModelOutput"] | components["schemas"]["ModelIdentifierOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["PBRMapsOutput"] | components["schemas"]["PairTileImageOutput"] | components["schemas"]["PromptTemplateOutput"] | components["schemas"]["SD3ConditioningOutput"] | components["schemas"]["SDXLLoRALoaderOutput"] | components["schemas"]["SDXLModelLoaderOutput"] | components["schemas"]["SDXLRefinerModelLoaderOutput"] | components["schemas"]["SchedulerOutput"] | components["schemas"]["Sd3ModelLoaderOutput"] | components["schemas"]["SeamlessModeOutput"] | components["schemas"]["String2Output"] | components["schemas"]["StringCollectionOutput"] | components["schemas"]["StringGeneratorOutput"] | components["schemas"]["StringOutput"] | components["schemas"]["StringPosNegOutput"] | components["schemas"]["T2IAdapterOutput"] | components["schemas"]["TileToPropertiesOutput"] | components["schemas"]["UNetOutput"] | components["schemas"]["VAEOutput"] | components["schemas"]["ZImageConditioningOutput"] | components["schemas"]["ZImageControlOutput"] | components["schemas"]["ZImageLoRALoaderOutput"] | components["schemas"]["ZImageModelLoaderOutput"]; + [key: string]: components["schemas"]["BooleanCollectionOutput"] | components["schemas"]["BooleanOutput"] | components["schemas"]["BoundingBoxCollectionOutput"] | components["schemas"]["BoundingBoxOutput"] | components["schemas"]["CLIPOutput"] | components["schemas"]["CLIPSkipInvocationOutput"] | components["schemas"]["CalculateImageTilesOutput"] | components["schemas"]["CogView4ConditioningOutput"] | components["schemas"]["CogView4ModelLoaderOutput"] | components["schemas"]["CollectInvocationOutput"] | components["schemas"]["ColorCollectionOutput"] | components["schemas"]["ColorOutput"] | components["schemas"]["ConditioningCollectionOutput"] | components["schemas"]["ConditioningOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["DenoiseMaskOutput"] | components["schemas"]["FaceMaskOutput"] | components["schemas"]["FaceOffOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["FloatGeneratorOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["Flux2KleinModelLoaderOutput"] | components["schemas"]["FluxConditioningCollectionOutput"] | components["schemas"]["FluxConditioningOutput"] | components["schemas"]["FluxControlLoRALoaderOutput"] | components["schemas"]["FluxControlNetOutput"] | components["schemas"]["FluxFillOutput"] | components["schemas"]["FluxKontextOutput"] | components["schemas"]["FluxLoRALoaderOutput"] | components["schemas"]["FluxModelLoaderOutput"] | components["schemas"]["FluxReduxOutput"] | components["schemas"]["GradientMaskOutput"] | components["schemas"]["IPAdapterOutput"] | components["schemas"]["IdealSizeOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["ImageGeneratorOutput"] | components["schemas"]["ImageOutput"] | components["schemas"]["ImagePanelCoordinateOutput"] | components["schemas"]["IntegerCollectionOutput"] | components["schemas"]["IntegerGeneratorOutput"] | components["schemas"]["IntegerOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["LatentsCollectionOutput"] | components["schemas"]["LatentsMetaOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["LoRALoaderOutput"] | components["schemas"]["LoRASelectorOutput"] | components["schemas"]["MDControlListOutput"] | components["schemas"]["MDIPAdapterListOutput"] | components["schemas"]["MDT2IAdapterListOutput"] | components["schemas"]["MaskOutput"] | components["schemas"]["MetadataItemOutput"] | components["schemas"]["MetadataOutput"] | components["schemas"]["MetadataToLorasCollectionOutput"] | components["schemas"]["MetadataToModelOutput"] | components["schemas"]["MetadataToSDXLModelOutput"] | components["schemas"]["ModelIdentifierOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["PBRMapsOutput"] | components["schemas"]["PairTileImageOutput"] | components["schemas"]["PromptTemplateOutput"] | components["schemas"]["SD3ConditioningOutput"] | components["schemas"]["SDXLLoRALoaderOutput"] | components["schemas"]["SDXLModelLoaderOutput"] | components["schemas"]["SDXLRefinerModelLoaderOutput"] | components["schemas"]["SchedulerOutput"] | components["schemas"]["Sd3ModelLoaderOutput"] | components["schemas"]["SeamlessModeOutput"] | components["schemas"]["String2Output"] | components["schemas"]["StringCollectionOutput"] | components["schemas"]["StringGeneratorOutput"] | components["schemas"]["StringOutput"] | components["schemas"]["StringPosNegOutput"] | components["schemas"]["T2IAdapterOutput"] | components["schemas"]["TileToPropertiesOutput"] | components["schemas"]["UNetOutput"] | components["schemas"]["VAEOutput"] | components["schemas"]["ZImageConditioningOutput"] | components["schemas"]["ZImageControlOutput"] | components["schemas"]["ZImageLoRALoaderOutput"] | components["schemas"]["ZImageModelLoaderOutput"]; }; /** * Errors @@ -12571,7 +12948,7 @@ export type components = { * Invocation * @description The ID of the invocation */ - invocation: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["ApplyMaskTensorToImageInvocation"] | components["schemas"]["ApplyMaskToImageInvocation"] | 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"]["CannyEdgeDetectionInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CanvasV2MaskAndCropInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CogView4DenoiseInvocation"] | components["schemas"]["CogView4ImageToLatentsInvocation"] | components["schemas"]["CogView4LatentsToImageInvocation"] | components["schemas"]["CogView4ModelLoaderInvocation"] | components["schemas"]["CogView4TextEncoderInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropImageToBoundingBoxInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeDetectionInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DenoiseLatentsMetaInvocation"] | components["schemas"]["DepthAnythingDepthEstimationInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["ExpandMaskWithFadeInvocation"] | components["schemas"]["FLUXLoRACollectionLoader"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatBatchInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatGenerator"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["FluxControlLoRALoaderInvocation"] | components["schemas"]["FluxControlNetInvocation"] | components["schemas"]["FluxDenoiseInvocation"] | components["schemas"]["FluxDenoiseLatentsMetaInvocation"] | components["schemas"]["FluxFillInvocation"] | components["schemas"]["FluxIPAdapterInvocation"] | components["schemas"]["FluxKontextConcatenateImagesInvocation"] | components["schemas"]["FluxKontextInvocation"] | components["schemas"]["FluxLoRALoaderInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxReduxInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxVaeDecodeInvocation"] | components["schemas"]["FluxVaeEncodeInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GetMaskBoundingBoxInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HEDEdgeDetectionInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBatchInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageGenerator"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImageNoiseInvocation"] | components["schemas"]["ImagePanelLayoutInvocation"] | 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"]["IntegerBatchInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerGenerator"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["InvokeAdjustImageHuePlusInvocation"] | components["schemas"]["InvokeEquivalentAchromaticLightnessInvocation"] | components["schemas"]["InvokeImageBlendInvocation"] | components["schemas"]["InvokeImageCompositorInvocation"] | components["schemas"]["InvokeImageDilateOrErodeInvocation"] | components["schemas"]["InvokeImageEnhanceInvocation"] | components["schemas"]["InvokeImageValueThresholdsInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LineartAnimeEdgeDetectionInvocation"] | components["schemas"]["LineartEdgeDetectionInvocation"] | components["schemas"]["LlavaOnevisionVllmInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MLSDDetectionInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediaPipeFaceDetectionInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataFieldExtractorInvocation"] | components["schemas"]["MetadataFromImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MetadataItemLinkedInvocation"] | components["schemas"]["MetadataToBoolCollectionInvocation"] | components["schemas"]["MetadataToBoolInvocation"] | components["schemas"]["MetadataToControlnetsInvocation"] | components["schemas"]["MetadataToFloatCollectionInvocation"] | components["schemas"]["MetadataToFloatInvocation"] | components["schemas"]["MetadataToIPAdaptersInvocation"] | components["schemas"]["MetadataToIntegerCollectionInvocation"] | components["schemas"]["MetadataToIntegerInvocation"] | components["schemas"]["MetadataToLorasCollectionInvocation"] | components["schemas"]["MetadataToLorasInvocation"] | components["schemas"]["MetadataToModelInvocation"] | components["schemas"]["MetadataToSDXLLorasInvocation"] | components["schemas"]["MetadataToSDXLModelInvocation"] | components["schemas"]["MetadataToSchedulerInvocation"] | components["schemas"]["MetadataToStringCollectionInvocation"] | components["schemas"]["MetadataToStringInvocation"] | components["schemas"]["MetadataToT2IAdaptersInvocation"] | components["schemas"]["MetadataToVAEInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalMapInvocation"] | components["schemas"]["PBRMapsInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PasteImageIntoBoundingBoxInvocation"] | components["schemas"]["PiDiNetEdgeDetectionInvocation"] | components["schemas"]["PromptTemplateInvocation"] | 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"]["SD3DenoiseInvocation"] | components["schemas"]["SD3ImageToLatentsInvocation"] | components["schemas"]["SD3LatentsToImageInvocation"] | 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"]["Sd3ModelLoaderInvocation"] | components["schemas"]["Sd3TextEncoderInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StringBatchInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringGenerator"] | 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"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZImageControlInvocation"] | components["schemas"]["ZImageDenoiseInvocation"] | components["schemas"]["ZImageDenoiseMetaInvocation"] | components["schemas"]["ZImageImageToLatentsInvocation"] | components["schemas"]["ZImageLatentsToImageInvocation"] | components["schemas"]["ZImageLoRACollectionLoader"] | components["schemas"]["ZImageLoRALoaderInvocation"] | components["schemas"]["ZImageModelLoaderInvocation"] | components["schemas"]["ZImageSeedVarianceEnhancerInvocation"] | components["schemas"]["ZImageTextEncoderInvocation"]; + invocation: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["ApplyMaskTensorToImageInvocation"] | components["schemas"]["ApplyMaskToImageInvocation"] | 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"]["CannyEdgeDetectionInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CanvasV2MaskAndCropInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CogView4DenoiseInvocation"] | components["schemas"]["CogView4ImageToLatentsInvocation"] | components["schemas"]["CogView4LatentsToImageInvocation"] | components["schemas"]["CogView4ModelLoaderInvocation"] | components["schemas"]["CogView4TextEncoderInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropImageToBoundingBoxInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeDetectionInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DenoiseLatentsMetaInvocation"] | components["schemas"]["DepthAnythingDepthEstimationInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["ExpandMaskWithFadeInvocation"] | components["schemas"]["FLUXLoRACollectionLoader"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatBatchInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatGenerator"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["Flux2DenoiseInvocation"] | components["schemas"]["Flux2KleinModelLoaderInvocation"] | components["schemas"]["Flux2KleinTextEncoderInvocation"] | components["schemas"]["Flux2VaeDecodeInvocation"] | components["schemas"]["Flux2VaeEncodeInvocation"] | components["schemas"]["FluxControlLoRALoaderInvocation"] | components["schemas"]["FluxControlNetInvocation"] | components["schemas"]["FluxDenoiseInvocation"] | components["schemas"]["FluxDenoiseLatentsMetaInvocation"] | components["schemas"]["FluxFillInvocation"] | components["schemas"]["FluxIPAdapterInvocation"] | components["schemas"]["FluxKontextConcatenateImagesInvocation"] | components["schemas"]["FluxKontextInvocation"] | components["schemas"]["FluxLoRALoaderInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxReduxInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxVaeDecodeInvocation"] | components["schemas"]["FluxVaeEncodeInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GetMaskBoundingBoxInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HEDEdgeDetectionInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBatchInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageGenerator"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImageNoiseInvocation"] | components["schemas"]["ImagePanelLayoutInvocation"] | 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"]["IntegerBatchInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerGenerator"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["InvokeAdjustImageHuePlusInvocation"] | components["schemas"]["InvokeEquivalentAchromaticLightnessInvocation"] | components["schemas"]["InvokeImageBlendInvocation"] | components["schemas"]["InvokeImageCompositorInvocation"] | components["schemas"]["InvokeImageDilateOrErodeInvocation"] | components["schemas"]["InvokeImageEnhanceInvocation"] | components["schemas"]["InvokeImageValueThresholdsInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LineartAnimeEdgeDetectionInvocation"] | components["schemas"]["LineartEdgeDetectionInvocation"] | components["schemas"]["LlavaOnevisionVllmInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MLSDDetectionInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediaPipeFaceDetectionInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataFieldExtractorInvocation"] | components["schemas"]["MetadataFromImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MetadataItemLinkedInvocation"] | components["schemas"]["MetadataToBoolCollectionInvocation"] | components["schemas"]["MetadataToBoolInvocation"] | components["schemas"]["MetadataToControlnetsInvocation"] | components["schemas"]["MetadataToFloatCollectionInvocation"] | components["schemas"]["MetadataToFloatInvocation"] | components["schemas"]["MetadataToIPAdaptersInvocation"] | components["schemas"]["MetadataToIntegerCollectionInvocation"] | components["schemas"]["MetadataToIntegerInvocation"] | components["schemas"]["MetadataToLorasCollectionInvocation"] | components["schemas"]["MetadataToLorasInvocation"] | components["schemas"]["MetadataToModelInvocation"] | components["schemas"]["MetadataToSDXLLorasInvocation"] | components["schemas"]["MetadataToSDXLModelInvocation"] | components["schemas"]["MetadataToSchedulerInvocation"] | components["schemas"]["MetadataToStringCollectionInvocation"] | components["schemas"]["MetadataToStringInvocation"] | components["schemas"]["MetadataToT2IAdaptersInvocation"] | components["schemas"]["MetadataToVAEInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalMapInvocation"] | components["schemas"]["PBRMapsInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PasteImageIntoBoundingBoxInvocation"] | components["schemas"]["PiDiNetEdgeDetectionInvocation"] | components["schemas"]["PromptTemplateInvocation"] | 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"]["SD3DenoiseInvocation"] | components["schemas"]["SD3ImageToLatentsInvocation"] | components["schemas"]["SD3LatentsToImageInvocation"] | 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"]["Sd3ModelLoaderInvocation"] | components["schemas"]["Sd3TextEncoderInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StringBatchInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringGenerator"] | 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"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZImageControlInvocation"] | components["schemas"]["ZImageDenoiseInvocation"] | components["schemas"]["ZImageDenoiseMetaInvocation"] | components["schemas"]["ZImageImageToLatentsInvocation"] | components["schemas"]["ZImageLatentsToImageInvocation"] | components["schemas"]["ZImageLoRACollectionLoader"] | components["schemas"]["ZImageLoRALoaderInvocation"] | components["schemas"]["ZImageModelLoaderInvocation"] | components["schemas"]["ZImageSeedVarianceEnhancerInvocation"] | components["schemas"]["ZImageTextEncoderInvocation"]; /** * Invocation Source Id * @description The ID of the prepared invocation's source node @@ -12581,7 +12958,7 @@ export type components = { * Result * @description The result of the invocation */ - result: components["schemas"]["BooleanCollectionOutput"] | components["schemas"]["BooleanOutput"] | components["schemas"]["BoundingBoxCollectionOutput"] | components["schemas"]["BoundingBoxOutput"] | components["schemas"]["CLIPOutput"] | components["schemas"]["CLIPSkipInvocationOutput"] | components["schemas"]["CalculateImageTilesOutput"] | components["schemas"]["CogView4ConditioningOutput"] | components["schemas"]["CogView4ModelLoaderOutput"] | components["schemas"]["CollectInvocationOutput"] | components["schemas"]["ColorCollectionOutput"] | components["schemas"]["ColorOutput"] | components["schemas"]["ConditioningCollectionOutput"] | components["schemas"]["ConditioningOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["DenoiseMaskOutput"] | components["schemas"]["FaceMaskOutput"] | components["schemas"]["FaceOffOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["FloatGeneratorOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["FluxConditioningCollectionOutput"] | components["schemas"]["FluxConditioningOutput"] | components["schemas"]["FluxControlLoRALoaderOutput"] | components["schemas"]["FluxControlNetOutput"] | components["schemas"]["FluxFillOutput"] | components["schemas"]["FluxKontextOutput"] | components["schemas"]["FluxLoRALoaderOutput"] | components["schemas"]["FluxModelLoaderOutput"] | components["schemas"]["FluxReduxOutput"] | components["schemas"]["GradientMaskOutput"] | components["schemas"]["IPAdapterOutput"] | components["schemas"]["IdealSizeOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["ImageGeneratorOutput"] | components["schemas"]["ImageOutput"] | components["schemas"]["ImagePanelCoordinateOutput"] | components["schemas"]["IntegerCollectionOutput"] | components["schemas"]["IntegerGeneratorOutput"] | components["schemas"]["IntegerOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["LatentsCollectionOutput"] | components["schemas"]["LatentsMetaOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["LoRALoaderOutput"] | components["schemas"]["LoRASelectorOutput"] | components["schemas"]["MDControlListOutput"] | components["schemas"]["MDIPAdapterListOutput"] | components["schemas"]["MDT2IAdapterListOutput"] | components["schemas"]["MaskOutput"] | components["schemas"]["MetadataItemOutput"] | components["schemas"]["MetadataOutput"] | components["schemas"]["MetadataToLorasCollectionOutput"] | components["schemas"]["MetadataToModelOutput"] | components["schemas"]["MetadataToSDXLModelOutput"] | components["schemas"]["ModelIdentifierOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["PBRMapsOutput"] | components["schemas"]["PairTileImageOutput"] | components["schemas"]["PromptTemplateOutput"] | components["schemas"]["SD3ConditioningOutput"] | components["schemas"]["SDXLLoRALoaderOutput"] | components["schemas"]["SDXLModelLoaderOutput"] | components["schemas"]["SDXLRefinerModelLoaderOutput"] | components["schemas"]["SchedulerOutput"] | components["schemas"]["Sd3ModelLoaderOutput"] | components["schemas"]["SeamlessModeOutput"] | components["schemas"]["String2Output"] | components["schemas"]["StringCollectionOutput"] | components["schemas"]["StringGeneratorOutput"] | components["schemas"]["StringOutput"] | components["schemas"]["StringPosNegOutput"] | components["schemas"]["T2IAdapterOutput"] | components["schemas"]["TileToPropertiesOutput"] | components["schemas"]["UNetOutput"] | components["schemas"]["VAEOutput"] | components["schemas"]["ZImageConditioningOutput"] | components["schemas"]["ZImageControlOutput"] | components["schemas"]["ZImageLoRALoaderOutput"] | components["schemas"]["ZImageModelLoaderOutput"]; + result: components["schemas"]["BooleanCollectionOutput"] | components["schemas"]["BooleanOutput"] | components["schemas"]["BoundingBoxCollectionOutput"] | components["schemas"]["BoundingBoxOutput"] | components["schemas"]["CLIPOutput"] | components["schemas"]["CLIPSkipInvocationOutput"] | components["schemas"]["CalculateImageTilesOutput"] | components["schemas"]["CogView4ConditioningOutput"] | components["schemas"]["CogView4ModelLoaderOutput"] | components["schemas"]["CollectInvocationOutput"] | components["schemas"]["ColorCollectionOutput"] | components["schemas"]["ColorOutput"] | components["schemas"]["ConditioningCollectionOutput"] | components["schemas"]["ConditioningOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["DenoiseMaskOutput"] | components["schemas"]["FaceMaskOutput"] | components["schemas"]["FaceOffOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["FloatGeneratorOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["Flux2KleinModelLoaderOutput"] | components["schemas"]["FluxConditioningCollectionOutput"] | components["schemas"]["FluxConditioningOutput"] | components["schemas"]["FluxControlLoRALoaderOutput"] | components["schemas"]["FluxControlNetOutput"] | components["schemas"]["FluxFillOutput"] | components["schemas"]["FluxKontextOutput"] | components["schemas"]["FluxLoRALoaderOutput"] | components["schemas"]["FluxModelLoaderOutput"] | components["schemas"]["FluxReduxOutput"] | components["schemas"]["GradientMaskOutput"] | components["schemas"]["IPAdapterOutput"] | components["schemas"]["IdealSizeOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["ImageGeneratorOutput"] | components["schemas"]["ImageOutput"] | components["schemas"]["ImagePanelCoordinateOutput"] | components["schemas"]["IntegerCollectionOutput"] | components["schemas"]["IntegerGeneratorOutput"] | components["schemas"]["IntegerOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["LatentsCollectionOutput"] | components["schemas"]["LatentsMetaOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["LoRALoaderOutput"] | components["schemas"]["LoRASelectorOutput"] | components["schemas"]["MDControlListOutput"] | components["schemas"]["MDIPAdapterListOutput"] | components["schemas"]["MDT2IAdapterListOutput"] | components["schemas"]["MaskOutput"] | components["schemas"]["MetadataItemOutput"] | components["schemas"]["MetadataOutput"] | components["schemas"]["MetadataToLorasCollectionOutput"] | components["schemas"]["MetadataToModelOutput"] | components["schemas"]["MetadataToSDXLModelOutput"] | components["schemas"]["ModelIdentifierOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["PBRMapsOutput"] | components["schemas"]["PairTileImageOutput"] | components["schemas"]["PromptTemplateOutput"] | components["schemas"]["SD3ConditioningOutput"] | components["schemas"]["SDXLLoRALoaderOutput"] | components["schemas"]["SDXLModelLoaderOutput"] | components["schemas"]["SDXLRefinerModelLoaderOutput"] | components["schemas"]["SchedulerOutput"] | components["schemas"]["Sd3ModelLoaderOutput"] | components["schemas"]["SeamlessModeOutput"] | components["schemas"]["String2Output"] | components["schemas"]["StringCollectionOutput"] | components["schemas"]["StringGeneratorOutput"] | components["schemas"]["StringOutput"] | components["schemas"]["StringPosNegOutput"] | components["schemas"]["T2IAdapterOutput"] | components["schemas"]["TileToPropertiesOutput"] | components["schemas"]["UNetOutput"] | components["schemas"]["VAEOutput"] | components["schemas"]["ZImageConditioningOutput"] | components["schemas"]["ZImageControlOutput"] | components["schemas"]["ZImageLoRALoaderOutput"] | components["schemas"]["ZImageModelLoaderOutput"]; }; /** * InvocationErrorEvent @@ -12629,7 +13006,7 @@ export type components = { * Invocation * @description The ID of the invocation */ - invocation: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["ApplyMaskTensorToImageInvocation"] | components["schemas"]["ApplyMaskToImageInvocation"] | 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"]["CannyEdgeDetectionInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CanvasV2MaskAndCropInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CogView4DenoiseInvocation"] | components["schemas"]["CogView4ImageToLatentsInvocation"] | components["schemas"]["CogView4LatentsToImageInvocation"] | components["schemas"]["CogView4ModelLoaderInvocation"] | components["schemas"]["CogView4TextEncoderInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropImageToBoundingBoxInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeDetectionInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DenoiseLatentsMetaInvocation"] | components["schemas"]["DepthAnythingDepthEstimationInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["ExpandMaskWithFadeInvocation"] | components["schemas"]["FLUXLoRACollectionLoader"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatBatchInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatGenerator"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["FluxControlLoRALoaderInvocation"] | components["schemas"]["FluxControlNetInvocation"] | components["schemas"]["FluxDenoiseInvocation"] | components["schemas"]["FluxDenoiseLatentsMetaInvocation"] | components["schemas"]["FluxFillInvocation"] | components["schemas"]["FluxIPAdapterInvocation"] | components["schemas"]["FluxKontextConcatenateImagesInvocation"] | components["schemas"]["FluxKontextInvocation"] | components["schemas"]["FluxLoRALoaderInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxReduxInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxVaeDecodeInvocation"] | components["schemas"]["FluxVaeEncodeInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GetMaskBoundingBoxInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HEDEdgeDetectionInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBatchInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageGenerator"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImageNoiseInvocation"] | components["schemas"]["ImagePanelLayoutInvocation"] | 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"]["IntegerBatchInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerGenerator"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["InvokeAdjustImageHuePlusInvocation"] | components["schemas"]["InvokeEquivalentAchromaticLightnessInvocation"] | components["schemas"]["InvokeImageBlendInvocation"] | components["schemas"]["InvokeImageCompositorInvocation"] | components["schemas"]["InvokeImageDilateOrErodeInvocation"] | components["schemas"]["InvokeImageEnhanceInvocation"] | components["schemas"]["InvokeImageValueThresholdsInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LineartAnimeEdgeDetectionInvocation"] | components["schemas"]["LineartEdgeDetectionInvocation"] | components["schemas"]["LlavaOnevisionVllmInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MLSDDetectionInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediaPipeFaceDetectionInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataFieldExtractorInvocation"] | components["schemas"]["MetadataFromImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MetadataItemLinkedInvocation"] | components["schemas"]["MetadataToBoolCollectionInvocation"] | components["schemas"]["MetadataToBoolInvocation"] | components["schemas"]["MetadataToControlnetsInvocation"] | components["schemas"]["MetadataToFloatCollectionInvocation"] | components["schemas"]["MetadataToFloatInvocation"] | components["schemas"]["MetadataToIPAdaptersInvocation"] | components["schemas"]["MetadataToIntegerCollectionInvocation"] | components["schemas"]["MetadataToIntegerInvocation"] | components["schemas"]["MetadataToLorasCollectionInvocation"] | components["schemas"]["MetadataToLorasInvocation"] | components["schemas"]["MetadataToModelInvocation"] | components["schemas"]["MetadataToSDXLLorasInvocation"] | components["schemas"]["MetadataToSDXLModelInvocation"] | components["schemas"]["MetadataToSchedulerInvocation"] | components["schemas"]["MetadataToStringCollectionInvocation"] | components["schemas"]["MetadataToStringInvocation"] | components["schemas"]["MetadataToT2IAdaptersInvocation"] | components["schemas"]["MetadataToVAEInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalMapInvocation"] | components["schemas"]["PBRMapsInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PasteImageIntoBoundingBoxInvocation"] | components["schemas"]["PiDiNetEdgeDetectionInvocation"] | components["schemas"]["PromptTemplateInvocation"] | 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"]["SD3DenoiseInvocation"] | components["schemas"]["SD3ImageToLatentsInvocation"] | components["schemas"]["SD3LatentsToImageInvocation"] | 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"]["Sd3ModelLoaderInvocation"] | components["schemas"]["Sd3TextEncoderInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StringBatchInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringGenerator"] | 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"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZImageControlInvocation"] | components["schemas"]["ZImageDenoiseInvocation"] | components["schemas"]["ZImageDenoiseMetaInvocation"] | components["schemas"]["ZImageImageToLatentsInvocation"] | components["schemas"]["ZImageLatentsToImageInvocation"] | components["schemas"]["ZImageLoRACollectionLoader"] | components["schemas"]["ZImageLoRALoaderInvocation"] | components["schemas"]["ZImageModelLoaderInvocation"] | components["schemas"]["ZImageSeedVarianceEnhancerInvocation"] | components["schemas"]["ZImageTextEncoderInvocation"]; + invocation: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["ApplyMaskTensorToImageInvocation"] | components["schemas"]["ApplyMaskToImageInvocation"] | 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"]["CannyEdgeDetectionInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CanvasV2MaskAndCropInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CogView4DenoiseInvocation"] | components["schemas"]["CogView4ImageToLatentsInvocation"] | components["schemas"]["CogView4LatentsToImageInvocation"] | components["schemas"]["CogView4ModelLoaderInvocation"] | components["schemas"]["CogView4TextEncoderInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropImageToBoundingBoxInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeDetectionInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DenoiseLatentsMetaInvocation"] | components["schemas"]["DepthAnythingDepthEstimationInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["ExpandMaskWithFadeInvocation"] | components["schemas"]["FLUXLoRACollectionLoader"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatBatchInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatGenerator"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["Flux2DenoiseInvocation"] | components["schemas"]["Flux2KleinModelLoaderInvocation"] | components["schemas"]["Flux2KleinTextEncoderInvocation"] | components["schemas"]["Flux2VaeDecodeInvocation"] | components["schemas"]["Flux2VaeEncodeInvocation"] | components["schemas"]["FluxControlLoRALoaderInvocation"] | components["schemas"]["FluxControlNetInvocation"] | components["schemas"]["FluxDenoiseInvocation"] | components["schemas"]["FluxDenoiseLatentsMetaInvocation"] | components["schemas"]["FluxFillInvocation"] | components["schemas"]["FluxIPAdapterInvocation"] | components["schemas"]["FluxKontextConcatenateImagesInvocation"] | components["schemas"]["FluxKontextInvocation"] | components["schemas"]["FluxLoRALoaderInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxReduxInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxVaeDecodeInvocation"] | components["schemas"]["FluxVaeEncodeInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GetMaskBoundingBoxInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HEDEdgeDetectionInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBatchInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageGenerator"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImageNoiseInvocation"] | components["schemas"]["ImagePanelLayoutInvocation"] | 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"]["IntegerBatchInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerGenerator"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["InvokeAdjustImageHuePlusInvocation"] | components["schemas"]["InvokeEquivalentAchromaticLightnessInvocation"] | components["schemas"]["InvokeImageBlendInvocation"] | components["schemas"]["InvokeImageCompositorInvocation"] | components["schemas"]["InvokeImageDilateOrErodeInvocation"] | components["schemas"]["InvokeImageEnhanceInvocation"] | components["schemas"]["InvokeImageValueThresholdsInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LineartAnimeEdgeDetectionInvocation"] | components["schemas"]["LineartEdgeDetectionInvocation"] | components["schemas"]["LlavaOnevisionVllmInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MLSDDetectionInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediaPipeFaceDetectionInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataFieldExtractorInvocation"] | components["schemas"]["MetadataFromImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MetadataItemLinkedInvocation"] | components["schemas"]["MetadataToBoolCollectionInvocation"] | components["schemas"]["MetadataToBoolInvocation"] | components["schemas"]["MetadataToControlnetsInvocation"] | components["schemas"]["MetadataToFloatCollectionInvocation"] | components["schemas"]["MetadataToFloatInvocation"] | components["schemas"]["MetadataToIPAdaptersInvocation"] | components["schemas"]["MetadataToIntegerCollectionInvocation"] | components["schemas"]["MetadataToIntegerInvocation"] | components["schemas"]["MetadataToLorasCollectionInvocation"] | components["schemas"]["MetadataToLorasInvocation"] | components["schemas"]["MetadataToModelInvocation"] | components["schemas"]["MetadataToSDXLLorasInvocation"] | components["schemas"]["MetadataToSDXLModelInvocation"] | components["schemas"]["MetadataToSchedulerInvocation"] | components["schemas"]["MetadataToStringCollectionInvocation"] | components["schemas"]["MetadataToStringInvocation"] | components["schemas"]["MetadataToT2IAdaptersInvocation"] | components["schemas"]["MetadataToVAEInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalMapInvocation"] | components["schemas"]["PBRMapsInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PasteImageIntoBoundingBoxInvocation"] | components["schemas"]["PiDiNetEdgeDetectionInvocation"] | components["schemas"]["PromptTemplateInvocation"] | 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"]["SD3DenoiseInvocation"] | components["schemas"]["SD3ImageToLatentsInvocation"] | components["schemas"]["SD3LatentsToImageInvocation"] | 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"]["Sd3ModelLoaderInvocation"] | components["schemas"]["Sd3TextEncoderInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StringBatchInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringGenerator"] | 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"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZImageControlInvocation"] | components["schemas"]["ZImageDenoiseInvocation"] | components["schemas"]["ZImageDenoiseMetaInvocation"] | components["schemas"]["ZImageImageToLatentsInvocation"] | components["schemas"]["ZImageLatentsToImageInvocation"] | components["schemas"]["ZImageLoRACollectionLoader"] | components["schemas"]["ZImageLoRALoaderInvocation"] | components["schemas"]["ZImageModelLoaderInvocation"] | components["schemas"]["ZImageSeedVarianceEnhancerInvocation"] | components["schemas"]["ZImageTextEncoderInvocation"]; /** * Invocation Source Id * @description The ID of the prepared invocation's source node @@ -12705,6 +13082,11 @@ export type components = { float_math: components["schemas"]["FloatOutput"]; float_range: components["schemas"]["FloatCollectionOutput"]; float_to_int: components["schemas"]["IntegerOutput"]; + flux2_denoise: components["schemas"]["LatentsOutput"]; + flux2_klein_model_loader: components["schemas"]["Flux2KleinModelLoaderOutput"]; + flux2_klein_text_encoder: components["schemas"]["FluxConditioningOutput"]; + flux2_vae_decode: components["schemas"]["ImageOutput"]; + flux2_vae_encode: components["schemas"]["LatentsOutput"]; flux_control_lora_loader: components["schemas"]["FluxControlLoRALoaderOutput"]; flux_controlnet: components["schemas"]["FluxControlNetOutput"]; flux_denoise: components["schemas"]["LatentsOutput"]; @@ -12922,7 +13304,7 @@ export type components = { * Invocation * @description The ID of the invocation */ - invocation: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["ApplyMaskTensorToImageInvocation"] | components["schemas"]["ApplyMaskToImageInvocation"] | 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"]["CannyEdgeDetectionInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CanvasV2MaskAndCropInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CogView4DenoiseInvocation"] | components["schemas"]["CogView4ImageToLatentsInvocation"] | components["schemas"]["CogView4LatentsToImageInvocation"] | components["schemas"]["CogView4ModelLoaderInvocation"] | components["schemas"]["CogView4TextEncoderInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropImageToBoundingBoxInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeDetectionInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DenoiseLatentsMetaInvocation"] | components["schemas"]["DepthAnythingDepthEstimationInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["ExpandMaskWithFadeInvocation"] | components["schemas"]["FLUXLoRACollectionLoader"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatBatchInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatGenerator"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["FluxControlLoRALoaderInvocation"] | components["schemas"]["FluxControlNetInvocation"] | components["schemas"]["FluxDenoiseInvocation"] | components["schemas"]["FluxDenoiseLatentsMetaInvocation"] | components["schemas"]["FluxFillInvocation"] | components["schemas"]["FluxIPAdapterInvocation"] | components["schemas"]["FluxKontextConcatenateImagesInvocation"] | components["schemas"]["FluxKontextInvocation"] | components["schemas"]["FluxLoRALoaderInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxReduxInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxVaeDecodeInvocation"] | components["schemas"]["FluxVaeEncodeInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GetMaskBoundingBoxInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HEDEdgeDetectionInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBatchInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageGenerator"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImageNoiseInvocation"] | components["schemas"]["ImagePanelLayoutInvocation"] | 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"]["IntegerBatchInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerGenerator"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["InvokeAdjustImageHuePlusInvocation"] | components["schemas"]["InvokeEquivalentAchromaticLightnessInvocation"] | components["schemas"]["InvokeImageBlendInvocation"] | components["schemas"]["InvokeImageCompositorInvocation"] | components["schemas"]["InvokeImageDilateOrErodeInvocation"] | components["schemas"]["InvokeImageEnhanceInvocation"] | components["schemas"]["InvokeImageValueThresholdsInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LineartAnimeEdgeDetectionInvocation"] | components["schemas"]["LineartEdgeDetectionInvocation"] | components["schemas"]["LlavaOnevisionVllmInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MLSDDetectionInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediaPipeFaceDetectionInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataFieldExtractorInvocation"] | components["schemas"]["MetadataFromImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MetadataItemLinkedInvocation"] | components["schemas"]["MetadataToBoolCollectionInvocation"] | components["schemas"]["MetadataToBoolInvocation"] | components["schemas"]["MetadataToControlnetsInvocation"] | components["schemas"]["MetadataToFloatCollectionInvocation"] | components["schemas"]["MetadataToFloatInvocation"] | components["schemas"]["MetadataToIPAdaptersInvocation"] | components["schemas"]["MetadataToIntegerCollectionInvocation"] | components["schemas"]["MetadataToIntegerInvocation"] | components["schemas"]["MetadataToLorasCollectionInvocation"] | components["schemas"]["MetadataToLorasInvocation"] | components["schemas"]["MetadataToModelInvocation"] | components["schemas"]["MetadataToSDXLLorasInvocation"] | components["schemas"]["MetadataToSDXLModelInvocation"] | components["schemas"]["MetadataToSchedulerInvocation"] | components["schemas"]["MetadataToStringCollectionInvocation"] | components["schemas"]["MetadataToStringInvocation"] | components["schemas"]["MetadataToT2IAdaptersInvocation"] | components["schemas"]["MetadataToVAEInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalMapInvocation"] | components["schemas"]["PBRMapsInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PasteImageIntoBoundingBoxInvocation"] | components["schemas"]["PiDiNetEdgeDetectionInvocation"] | components["schemas"]["PromptTemplateInvocation"] | 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"]["SD3DenoiseInvocation"] | components["schemas"]["SD3ImageToLatentsInvocation"] | components["schemas"]["SD3LatentsToImageInvocation"] | 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"]["Sd3ModelLoaderInvocation"] | components["schemas"]["Sd3TextEncoderInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StringBatchInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringGenerator"] | 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"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZImageControlInvocation"] | components["schemas"]["ZImageDenoiseInvocation"] | components["schemas"]["ZImageDenoiseMetaInvocation"] | components["schemas"]["ZImageImageToLatentsInvocation"] | components["schemas"]["ZImageLatentsToImageInvocation"] | components["schemas"]["ZImageLoRACollectionLoader"] | components["schemas"]["ZImageLoRALoaderInvocation"] | components["schemas"]["ZImageModelLoaderInvocation"] | components["schemas"]["ZImageSeedVarianceEnhancerInvocation"] | components["schemas"]["ZImageTextEncoderInvocation"]; + invocation: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["ApplyMaskTensorToImageInvocation"] | components["schemas"]["ApplyMaskToImageInvocation"] | 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"]["CannyEdgeDetectionInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CanvasV2MaskAndCropInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CogView4DenoiseInvocation"] | components["schemas"]["CogView4ImageToLatentsInvocation"] | components["schemas"]["CogView4LatentsToImageInvocation"] | components["schemas"]["CogView4ModelLoaderInvocation"] | components["schemas"]["CogView4TextEncoderInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropImageToBoundingBoxInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeDetectionInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DenoiseLatentsMetaInvocation"] | components["schemas"]["DepthAnythingDepthEstimationInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["ExpandMaskWithFadeInvocation"] | components["schemas"]["FLUXLoRACollectionLoader"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatBatchInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatGenerator"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["Flux2DenoiseInvocation"] | components["schemas"]["Flux2KleinModelLoaderInvocation"] | components["schemas"]["Flux2KleinTextEncoderInvocation"] | components["schemas"]["Flux2VaeDecodeInvocation"] | components["schemas"]["Flux2VaeEncodeInvocation"] | components["schemas"]["FluxControlLoRALoaderInvocation"] | components["schemas"]["FluxControlNetInvocation"] | components["schemas"]["FluxDenoiseInvocation"] | components["schemas"]["FluxDenoiseLatentsMetaInvocation"] | components["schemas"]["FluxFillInvocation"] | components["schemas"]["FluxIPAdapterInvocation"] | components["schemas"]["FluxKontextConcatenateImagesInvocation"] | components["schemas"]["FluxKontextInvocation"] | components["schemas"]["FluxLoRALoaderInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxReduxInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxVaeDecodeInvocation"] | components["schemas"]["FluxVaeEncodeInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GetMaskBoundingBoxInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HEDEdgeDetectionInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBatchInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageGenerator"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImageNoiseInvocation"] | components["schemas"]["ImagePanelLayoutInvocation"] | 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"]["IntegerBatchInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerGenerator"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["InvokeAdjustImageHuePlusInvocation"] | components["schemas"]["InvokeEquivalentAchromaticLightnessInvocation"] | components["schemas"]["InvokeImageBlendInvocation"] | components["schemas"]["InvokeImageCompositorInvocation"] | components["schemas"]["InvokeImageDilateOrErodeInvocation"] | components["schemas"]["InvokeImageEnhanceInvocation"] | components["schemas"]["InvokeImageValueThresholdsInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LineartAnimeEdgeDetectionInvocation"] | components["schemas"]["LineartEdgeDetectionInvocation"] | components["schemas"]["LlavaOnevisionVllmInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MLSDDetectionInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediaPipeFaceDetectionInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataFieldExtractorInvocation"] | components["schemas"]["MetadataFromImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MetadataItemLinkedInvocation"] | components["schemas"]["MetadataToBoolCollectionInvocation"] | components["schemas"]["MetadataToBoolInvocation"] | components["schemas"]["MetadataToControlnetsInvocation"] | components["schemas"]["MetadataToFloatCollectionInvocation"] | components["schemas"]["MetadataToFloatInvocation"] | components["schemas"]["MetadataToIPAdaptersInvocation"] | components["schemas"]["MetadataToIntegerCollectionInvocation"] | components["schemas"]["MetadataToIntegerInvocation"] | components["schemas"]["MetadataToLorasCollectionInvocation"] | components["schemas"]["MetadataToLorasInvocation"] | components["schemas"]["MetadataToModelInvocation"] | components["schemas"]["MetadataToSDXLLorasInvocation"] | components["schemas"]["MetadataToSDXLModelInvocation"] | components["schemas"]["MetadataToSchedulerInvocation"] | components["schemas"]["MetadataToStringCollectionInvocation"] | components["schemas"]["MetadataToStringInvocation"] | components["schemas"]["MetadataToT2IAdaptersInvocation"] | components["schemas"]["MetadataToVAEInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalMapInvocation"] | components["schemas"]["PBRMapsInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PasteImageIntoBoundingBoxInvocation"] | components["schemas"]["PiDiNetEdgeDetectionInvocation"] | components["schemas"]["PromptTemplateInvocation"] | 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"]["SD3DenoiseInvocation"] | components["schemas"]["SD3ImageToLatentsInvocation"] | components["schemas"]["SD3LatentsToImageInvocation"] | 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"]["Sd3ModelLoaderInvocation"] | components["schemas"]["Sd3TextEncoderInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StringBatchInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringGenerator"] | 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"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZImageControlInvocation"] | components["schemas"]["ZImageDenoiseInvocation"] | components["schemas"]["ZImageDenoiseMetaInvocation"] | components["schemas"]["ZImageImageToLatentsInvocation"] | components["schemas"]["ZImageLatentsToImageInvocation"] | components["schemas"]["ZImageLoRACollectionLoader"] | components["schemas"]["ZImageLoRALoaderInvocation"] | components["schemas"]["ZImageModelLoaderInvocation"] | components["schemas"]["ZImageSeedVarianceEnhancerInvocation"] | components["schemas"]["ZImageTextEncoderInvocation"]; /** * Invocation Source Id * @description The ID of the prepared invocation's source node @@ -12991,7 +13373,7 @@ export type components = { * Invocation * @description The ID of the invocation */ - invocation: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["ApplyMaskTensorToImageInvocation"] | components["schemas"]["ApplyMaskToImageInvocation"] | 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"]["CannyEdgeDetectionInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CanvasV2MaskAndCropInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CogView4DenoiseInvocation"] | components["schemas"]["CogView4ImageToLatentsInvocation"] | components["schemas"]["CogView4LatentsToImageInvocation"] | components["schemas"]["CogView4ModelLoaderInvocation"] | components["schemas"]["CogView4TextEncoderInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropImageToBoundingBoxInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeDetectionInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DenoiseLatentsMetaInvocation"] | components["schemas"]["DepthAnythingDepthEstimationInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["ExpandMaskWithFadeInvocation"] | components["schemas"]["FLUXLoRACollectionLoader"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatBatchInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatGenerator"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["FluxControlLoRALoaderInvocation"] | components["schemas"]["FluxControlNetInvocation"] | components["schemas"]["FluxDenoiseInvocation"] | components["schemas"]["FluxDenoiseLatentsMetaInvocation"] | components["schemas"]["FluxFillInvocation"] | components["schemas"]["FluxIPAdapterInvocation"] | components["schemas"]["FluxKontextConcatenateImagesInvocation"] | components["schemas"]["FluxKontextInvocation"] | components["schemas"]["FluxLoRALoaderInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxReduxInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxVaeDecodeInvocation"] | components["schemas"]["FluxVaeEncodeInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GetMaskBoundingBoxInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HEDEdgeDetectionInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBatchInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageGenerator"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImageNoiseInvocation"] | components["schemas"]["ImagePanelLayoutInvocation"] | 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"]["IntegerBatchInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerGenerator"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["InvokeAdjustImageHuePlusInvocation"] | components["schemas"]["InvokeEquivalentAchromaticLightnessInvocation"] | components["schemas"]["InvokeImageBlendInvocation"] | components["schemas"]["InvokeImageCompositorInvocation"] | components["schemas"]["InvokeImageDilateOrErodeInvocation"] | components["schemas"]["InvokeImageEnhanceInvocation"] | components["schemas"]["InvokeImageValueThresholdsInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LineartAnimeEdgeDetectionInvocation"] | components["schemas"]["LineartEdgeDetectionInvocation"] | components["schemas"]["LlavaOnevisionVllmInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MLSDDetectionInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediaPipeFaceDetectionInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataFieldExtractorInvocation"] | components["schemas"]["MetadataFromImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MetadataItemLinkedInvocation"] | components["schemas"]["MetadataToBoolCollectionInvocation"] | components["schemas"]["MetadataToBoolInvocation"] | components["schemas"]["MetadataToControlnetsInvocation"] | components["schemas"]["MetadataToFloatCollectionInvocation"] | components["schemas"]["MetadataToFloatInvocation"] | components["schemas"]["MetadataToIPAdaptersInvocation"] | components["schemas"]["MetadataToIntegerCollectionInvocation"] | components["schemas"]["MetadataToIntegerInvocation"] | components["schemas"]["MetadataToLorasCollectionInvocation"] | components["schemas"]["MetadataToLorasInvocation"] | components["schemas"]["MetadataToModelInvocation"] | components["schemas"]["MetadataToSDXLLorasInvocation"] | components["schemas"]["MetadataToSDXLModelInvocation"] | components["schemas"]["MetadataToSchedulerInvocation"] | components["schemas"]["MetadataToStringCollectionInvocation"] | components["schemas"]["MetadataToStringInvocation"] | components["schemas"]["MetadataToT2IAdaptersInvocation"] | components["schemas"]["MetadataToVAEInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalMapInvocation"] | components["schemas"]["PBRMapsInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PasteImageIntoBoundingBoxInvocation"] | components["schemas"]["PiDiNetEdgeDetectionInvocation"] | components["schemas"]["PromptTemplateInvocation"] | 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"]["SD3DenoiseInvocation"] | components["schemas"]["SD3ImageToLatentsInvocation"] | components["schemas"]["SD3LatentsToImageInvocation"] | 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"]["Sd3ModelLoaderInvocation"] | components["schemas"]["Sd3TextEncoderInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StringBatchInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringGenerator"] | 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"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZImageControlInvocation"] | components["schemas"]["ZImageDenoiseInvocation"] | components["schemas"]["ZImageDenoiseMetaInvocation"] | components["schemas"]["ZImageImageToLatentsInvocation"] | components["schemas"]["ZImageLatentsToImageInvocation"] | components["schemas"]["ZImageLoRACollectionLoader"] | components["schemas"]["ZImageLoRALoaderInvocation"] | components["schemas"]["ZImageModelLoaderInvocation"] | components["schemas"]["ZImageSeedVarianceEnhancerInvocation"] | components["schemas"]["ZImageTextEncoderInvocation"]; + invocation: components["schemas"]["AddInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["ApplyMaskTensorToImageInvocation"] | components["schemas"]["ApplyMaskToImageInvocation"] | 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"]["CannyEdgeDetectionInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["CanvasV2MaskAndCropInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["CogView4DenoiseInvocation"] | components["schemas"]["CogView4ImageToLatentsInvocation"] | components["schemas"]["CogView4LatentsToImageInvocation"] | components["schemas"]["CogView4ModelLoaderInvocation"] | components["schemas"]["CogView4TextEncoderInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ColorMapInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["ContentShuffleInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["CropImageToBoundingBoxInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["DWOpenposeDetectionInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["DenoiseLatentsMetaInvocation"] | components["schemas"]["DepthAnythingDepthEstimationInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["ExpandMaskWithFadeInvocation"] | components["schemas"]["FLUXLoRACollectionLoader"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["FloatBatchInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["FloatGenerator"] | components["schemas"]["FloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["Flux2DenoiseInvocation"] | components["schemas"]["Flux2KleinModelLoaderInvocation"] | components["schemas"]["Flux2KleinTextEncoderInvocation"] | components["schemas"]["Flux2VaeDecodeInvocation"] | components["schemas"]["Flux2VaeEncodeInvocation"] | components["schemas"]["FluxControlLoRALoaderInvocation"] | components["schemas"]["FluxControlNetInvocation"] | components["schemas"]["FluxDenoiseInvocation"] | components["schemas"]["FluxDenoiseLatentsMetaInvocation"] | components["schemas"]["FluxFillInvocation"] | components["schemas"]["FluxIPAdapterInvocation"] | components["schemas"]["FluxKontextConcatenateImagesInvocation"] | components["schemas"]["FluxKontextInvocation"] | components["schemas"]["FluxLoRALoaderInvocation"] | components["schemas"]["FluxModelLoaderInvocation"] | components["schemas"]["FluxReduxInvocation"] | components["schemas"]["FluxTextEncoderInvocation"] | components["schemas"]["FluxVaeDecodeInvocation"] | components["schemas"]["FluxVaeEncodeInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["GetMaskBoundingBoxInvocation"] | components["schemas"]["GroundingDinoInvocation"] | components["schemas"]["HEDEdgeDetectionInvocation"] | components["schemas"]["HeuristicResizeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["ImageBatchInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageGenerator"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageMaskToTensorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["ImageNoiseInvocation"] | components["schemas"]["ImagePanelLayoutInvocation"] | 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"]["IntegerBatchInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["IntegerGenerator"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InvertTensorMaskInvocation"] | components["schemas"]["InvokeAdjustImageHuePlusInvocation"] | components["schemas"]["InvokeEquivalentAchromaticLightnessInvocation"] | components["schemas"]["InvokeImageBlendInvocation"] | components["schemas"]["InvokeImageCompositorInvocation"] | components["schemas"]["InvokeImageDilateOrErodeInvocation"] | components["schemas"]["InvokeImageEnhanceInvocation"] | components["schemas"]["InvokeImageValueThresholdsInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["LineartAnimeEdgeDetectionInvocation"] | components["schemas"]["LineartEdgeDetectionInvocation"] | components["schemas"]["LlavaOnevisionVllmInvocation"] | components["schemas"]["LoRACollectionLoader"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["LoRASelectorInvocation"] | components["schemas"]["MLSDDetectionInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["MaskTensorToImageInvocation"] | components["schemas"]["MediaPipeFaceDetectionInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["MetadataFieldExtractorInvocation"] | components["schemas"]["MetadataFromImageInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["MetadataItemLinkedInvocation"] | components["schemas"]["MetadataToBoolCollectionInvocation"] | components["schemas"]["MetadataToBoolInvocation"] | components["schemas"]["MetadataToControlnetsInvocation"] | components["schemas"]["MetadataToFloatCollectionInvocation"] | components["schemas"]["MetadataToFloatInvocation"] | components["schemas"]["MetadataToIPAdaptersInvocation"] | components["schemas"]["MetadataToIntegerCollectionInvocation"] | components["schemas"]["MetadataToIntegerInvocation"] | components["schemas"]["MetadataToLorasCollectionInvocation"] | components["schemas"]["MetadataToLorasInvocation"] | components["schemas"]["MetadataToModelInvocation"] | components["schemas"]["MetadataToSDXLLorasInvocation"] | components["schemas"]["MetadataToSDXLModelInvocation"] | components["schemas"]["MetadataToSchedulerInvocation"] | components["schemas"]["MetadataToStringCollectionInvocation"] | components["schemas"]["MetadataToStringInvocation"] | components["schemas"]["MetadataToT2IAdaptersInvocation"] | components["schemas"]["MetadataToVAEInvocation"] | components["schemas"]["ModelIdentifierInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["NormalMapInvocation"] | components["schemas"]["PBRMapsInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["PasteImageIntoBoundingBoxInvocation"] | components["schemas"]["PiDiNetEdgeDetectionInvocation"] | components["schemas"]["PromptTemplateInvocation"] | 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"]["SD3DenoiseInvocation"] | components["schemas"]["SD3ImageToLatentsInvocation"] | components["schemas"]["SD3LatentsToImageInvocation"] | 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"]["Sd3ModelLoaderInvocation"] | components["schemas"]["Sd3TextEncoderInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["SegmentAnythingInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["SpandrelImageToImageAutoscaleInvocation"] | components["schemas"]["SpandrelImageToImageInvocation"] | components["schemas"]["StringBatchInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["StringGenerator"] | 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"]["TileToPropertiesInvocation"] | components["schemas"]["TiledMultiDiffusionDenoiseLatents"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["ZImageControlInvocation"] | components["schemas"]["ZImageDenoiseInvocation"] | components["schemas"]["ZImageDenoiseMetaInvocation"] | components["schemas"]["ZImageImageToLatentsInvocation"] | components["schemas"]["ZImageLatentsToImageInvocation"] | components["schemas"]["ZImageLoRACollectionLoader"] | components["schemas"]["ZImageLoRALoaderInvocation"] | components["schemas"]["ZImageModelLoaderInvocation"] | components["schemas"]["ZImageSeedVarianceEnhancerInvocation"] | components["schemas"]["ZImageTextEncoderInvocation"]; /** * Invocation Source Id * @description The ID of the prepared invocation's source node @@ -16010,6 +16392,90 @@ export type components = { base: "flux"; variant: components["schemas"]["FluxVariantType"]; }; + /** + * Main_Checkpoint_Flux2_Config + * @description Model config for FLUX.2 checkpoint models (e.g. Klein). + */ + Main_Checkpoint_Flux2_Config: { + /** + * Key + * @description A unique key for this model. + */ + key: string; + /** + * Hash + * @description The hash of the model file(s). + */ + hash: string; + /** + * Path + * @description Path to the model on the filesystem. Relative paths are relative to the Invoke root directory. + */ + path: string; + /** + * File Size + * @description The size of the model in bytes. + */ + file_size: number; + /** + * Name + * @description Name of the model. + */ + name: string; + /** + * Description + * @description Model description + */ + description: string | null; + /** + * Source + * @description The original source of the model (path, URL or repo_id). + */ + source: string; + /** @description The type of source */ + source_type: components["schemas"]["ModelSourceType"]; + /** + * Source Api Response + * @description The original API response from the source, as stringified JSON. + */ + source_api_response: string | null; + /** + * Cover Image + * @description Url for image to preview model + */ + cover_image: string | null; + /** + * Type + * @default main + * @constant + */ + type: "main"; + /** + * Trigger Phrases + * @description Set of trigger phrases for this model + */ + trigger_phrases: string[] | null; + /** @description Default settings for this model */ + default_settings: components["schemas"]["MainModelDefaultSettings"] | null; + /** + * Config Path + * @description Path to the config for this model, if any. + */ + config_path: string | null; + /** + * Format + * @default checkpoint + * @constant + */ + format: "checkpoint"; + /** + * Base + * @default flux2 + * @constant + */ + base: "flux2"; + variant: components["schemas"]["Flux2VariantType"]; + }; /** Main_Checkpoint_SD1_Config */ Main_Checkpoint_SD1_Config: { /** @@ -16498,6 +16964,168 @@ export type components = { */ base: "cogview4"; }; + /** + * Main_Diffusers_FLUX_Config + * @description Model config for FLUX.1 models in diffusers format. + */ + Main_Diffusers_FLUX_Config: { + /** + * Key + * @description A unique key for this model. + */ + key: string; + /** + * Hash + * @description The hash of the model file(s). + */ + hash: string; + /** + * Path + * @description Path to the model on the filesystem. Relative paths are relative to the Invoke root directory. + */ + path: string; + /** + * File Size + * @description The size of the model in bytes. + */ + file_size: number; + /** + * Name + * @description Name of the model. + */ + name: string; + /** + * Description + * @description Model description + */ + description: string | null; + /** + * Source + * @description The original source of the model (path, URL or repo_id). + */ + source: string; + /** @description The type of source */ + source_type: components["schemas"]["ModelSourceType"]; + /** + * Source Api Response + * @description The original API response from the source, as stringified JSON. + */ + source_api_response: string | null; + /** + * Cover Image + * @description Url for image to preview model + */ + cover_image: string | null; + /** + * Type + * @default main + * @constant + */ + type: "main"; + /** + * Trigger Phrases + * @description Set of trigger phrases for this model + */ + trigger_phrases: string[] | null; + /** @description Default settings for this model */ + default_settings: components["schemas"]["MainModelDefaultSettings"] | null; + /** + * Format + * @default diffusers + * @constant + */ + format: "diffusers"; + /** @default */ + repo_variant: components["schemas"]["ModelRepoVariant"]; + /** + * Base + * @default flux + * @constant + */ + base: "flux"; + variant: components["schemas"]["FluxVariantType"]; + }; + /** + * Main_Diffusers_Flux2_Config + * @description Model config for FLUX.2 models in diffusers format (e.g. FLUX.2 Klein). + */ + Main_Diffusers_Flux2_Config: { + /** + * Key + * @description A unique key for this model. + */ + key: string; + /** + * Hash + * @description The hash of the model file(s). + */ + hash: string; + /** + * Path + * @description Path to the model on the filesystem. Relative paths are relative to the Invoke root directory. + */ + path: string; + /** + * File Size + * @description The size of the model in bytes. + */ + file_size: number; + /** + * Name + * @description Name of the model. + */ + name: string; + /** + * Description + * @description Model description + */ + description: string | null; + /** + * Source + * @description The original source of the model (path, URL or repo_id). + */ + source: string; + /** @description The type of source */ + source_type: components["schemas"]["ModelSourceType"]; + /** + * Source Api Response + * @description The original API response from the source, as stringified JSON. + */ + source_api_response: string | null; + /** + * Cover Image + * @description Url for image to preview model + */ + cover_image: string | null; + /** + * Type + * @default main + * @constant + */ + type: "main"; + /** + * Trigger Phrases + * @description Set of trigger phrases for this model + */ + trigger_phrases: string[] | null; + /** @description Default settings for this model */ + default_settings: components["schemas"]["MainModelDefaultSettings"] | null; + /** + * Format + * @default diffusers + * @constant + */ + format: "diffusers"; + /** @default */ + repo_variant: components["schemas"]["ModelRepoVariant"]; + /** + * Base + * @default flux2 + * @constant + */ + base: "flux2"; + variant: components["schemas"]["Flux2VariantType"]; + }; /** Main_Diffusers_SD1_Config */ Main_Diffusers_SD1_Config: { /** @@ -17062,6 +17690,90 @@ export type components = { format: "gguf_quantized"; variant: components["schemas"]["FluxVariantType"]; }; + /** + * Main_GGUF_Flux2_Config + * @description Model config for GGUF-quantized FLUX.2 checkpoint models (e.g. Klein). + */ + Main_GGUF_Flux2_Config: { + /** + * Key + * @description A unique key for this model. + */ + key: string; + /** + * Hash + * @description The hash of the model file(s). + */ + hash: string; + /** + * Path + * @description Path to the model on the filesystem. Relative paths are relative to the Invoke root directory. + */ + path: string; + /** + * File Size + * @description The size of the model in bytes. + */ + file_size: number; + /** + * Name + * @description Name of the model. + */ + name: string; + /** + * Description + * @description Model description + */ + description: string | null; + /** + * Source + * @description The original source of the model (path, URL or repo_id). + */ + source: string; + /** @description The type of source */ + source_type: components["schemas"]["ModelSourceType"]; + /** + * Source Api Response + * @description The original API response from the source, as stringified JSON. + */ + source_api_response: string | null; + /** + * Cover Image + * @description Url for image to preview model + */ + cover_image: string | null; + /** + * Type + * @default main + * @constant + */ + type: "main"; + /** + * Trigger Phrases + * @description Set of trigger phrases for this model + */ + trigger_phrases: string[] | null; + /** @description Default settings for this model */ + default_settings: components["schemas"]["MainModelDefaultSettings"] | null; + /** + * Config Path + * @description Path to the config for this model, if any. + */ + config_path: string | null; + /** + * Base + * @default flux2 + * @constant + */ + base: "flux2"; + /** + * Format + * @default gguf_quantized + * @constant + */ + format: "gguf_quantized"; + variant: components["schemas"]["Flux2VariantType"]; + }; /** * Main_GGUF_ZImage_Config * @description Model config for GGUF-quantized Z-Image transformer models. @@ -18973,7 +19685,7 @@ export type components = { * Config * @description The installed model's config */ - config: components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; + config: components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_FLUX_Config"] | components["schemas"]["Main_Diffusers_Flux2_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_Flux2_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_Flux2_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Checkpoint_Flux2_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["VAE_Diffusers_Flux2_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; }; /** * ModelInstallDownloadProgressEvent @@ -19139,7 +19851,7 @@ export type components = { * Config Out * @description After successful installation, this will hold the configuration object. */ - config_out?: (components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]) | null; + config_out?: (components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_FLUX_Config"] | components["schemas"]["Main_Diffusers_Flux2_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_Flux2_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_Flux2_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Checkpoint_Flux2_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["VAE_Diffusers_Flux2_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]) | null; /** * Inplace * @description Leave model in its current location; otherwise install under models directory @@ -19225,7 +19937,7 @@ export type components = { * Config * @description The model's config */ - config: components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; + config: components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_FLUX_Config"] | components["schemas"]["Main_Diffusers_Flux2_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_Flux2_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_Flux2_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Checkpoint_Flux2_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["VAE_Diffusers_Flux2_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; /** * @description The submodel type, if any * @default null @@ -19246,7 +19958,7 @@ export type components = { * Config * @description The model's config */ - config: components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; + config: components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_FLUX_Config"] | components["schemas"]["Main_Diffusers_Flux2_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_Flux2_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_Flux2_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Checkpoint_Flux2_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["VAE_Diffusers_Flux2_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; /** * @description The submodel type, if any * @default null @@ -19350,7 +20062,7 @@ export type components = { * Variant * @description The variant of the model. */ - variant?: components["schemas"]["ModelVariantType"] | components["schemas"]["ClipVariantType"] | components["schemas"]["FluxVariantType"] | null; + variant?: components["schemas"]["ModelVariantType"] | components["schemas"]["ClipVariantType"] | components["schemas"]["FluxVariantType"] | components["schemas"]["Flux2VariantType"] | components["schemas"]["Qwen3VariantType"] | null; /** @description The prediction type of the model. */ prediction_type?: components["schemas"]["SchedulerPredictionType"] | null; /** @@ -19415,7 +20127,7 @@ export type components = { */ ModelsList: { /** Models */ - models: (components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"])[]; + models: (components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_FLUX_Config"] | components["schemas"]["Main_Diffusers_Flux2_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_Flux2_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_Flux2_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Checkpoint_Flux2_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["VAE_Diffusers_Flux2_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"])[]; }; /** * Multiply Integers @@ -20334,6 +21046,8 @@ export type components = { * @constant */ format: "checkpoint"; + /** @description Qwen3 model size variant (4B or 8B) */ + variant: components["schemas"]["Qwen3VariantType"]; }; /** * Qwen3Encoder_GGUF_Config @@ -20410,6 +21124,8 @@ export type components = { * @constant */ format: "gguf_quantized"; + /** @description Qwen3 model size variant (4B or 8B) */ + variant: components["schemas"]["Qwen3VariantType"]; }; /** * Qwen3Encoder_Qwen3Encoder_Config @@ -20484,7 +21200,15 @@ export type components = { * @constant */ format: "qwen3_encoder"; + /** @description Qwen3 model size variant (4B or 8B) */ + variant: components["schemas"]["Qwen3VariantType"]; }; + /** + * Qwen3VariantType + * @description Qwen3 text encoder variants based on model size. + * @enum {string} + */ + Qwen3VariantType: "qwen3_4b" | "qwen3_8b"; /** * Random Float * @description Outputs a single random float @@ -23179,7 +23903,7 @@ export type components = { path_or_prefix: string; model_type: components["schemas"]["ModelType"]; /** Variant */ - variant?: components["schemas"]["ModelVariantType"] | components["schemas"]["ClipVariantType"] | components["schemas"]["FluxVariantType"] | null; + variant?: components["schemas"]["ModelVariantType"] | components["schemas"]["ClipVariantType"] | components["schemas"]["FluxVariantType"] | components["schemas"]["Flux2VariantType"] | components["schemas"]["Qwen3VariantType"] | null; }; /** * Subtract Integers @@ -24754,6 +25478,82 @@ export type components = { */ base: "flux"; }; + /** + * VAE_Checkpoint_Flux2_Config + * @description Model config for FLUX.2 VAE checkpoint models (AutoencoderKLFlux2). + */ + VAE_Checkpoint_Flux2_Config: { + /** + * Key + * @description A unique key for this model. + */ + key: string; + /** + * Hash + * @description The hash of the model file(s). + */ + hash: string; + /** + * Path + * @description Path to the model on the filesystem. Relative paths are relative to the Invoke root directory. + */ + path: string; + /** + * File Size + * @description The size of the model in bytes. + */ + file_size: number; + /** + * Name + * @description Name of the model. + */ + name: string; + /** + * Description + * @description Model description + */ + description: string | null; + /** + * Source + * @description The original source of the model (path, URL or repo_id). + */ + source: string; + /** @description The type of source */ + source_type: components["schemas"]["ModelSourceType"]; + /** + * Source Api Response + * @description The original API response from the source, as stringified JSON. + */ + source_api_response: string | null; + /** + * Cover Image + * @description Url for image to preview model + */ + cover_image: string | null; + /** + * Config Path + * @description Path to the config for this model, if any. + */ + config_path: string | null; + /** + * Type + * @default vae + * @constant + */ + type: "vae"; + /** + * Format + * @default checkpoint + * @constant + */ + format: "checkpoint"; + /** + * Base + * @default flux2 + * @constant + */ + base: "flux2"; + }; /** VAE_Checkpoint_SD1_Config */ VAE_Checkpoint_SD1_Config: { /** @@ -24973,6 +25773,79 @@ export type components = { */ base: "sdxl"; }; + /** + * VAE_Diffusers_Flux2_Config + * @description Model config for FLUX.2 VAE models in diffusers format (AutoencoderKLFlux2). + */ + VAE_Diffusers_Flux2_Config: { + /** + * Key + * @description A unique key for this model. + */ + key: string; + /** + * Hash + * @description The hash of the model file(s). + */ + hash: string; + /** + * Path + * @description Path to the model on the filesystem. Relative paths are relative to the Invoke root directory. + */ + path: string; + /** + * File Size + * @description The size of the model in bytes. + */ + file_size: number; + /** + * Name + * @description Name of the model. + */ + name: string; + /** + * Description + * @description Model description + */ + description: string | null; + /** + * Source + * @description The original source of the model (path, URL or repo_id). + */ + source: string; + /** @description The type of source */ + source_type: components["schemas"]["ModelSourceType"]; + /** + * Source Api Response + * @description The original API response from the source, as stringified JSON. + */ + source_api_response: string | null; + /** + * Cover Image + * @description Url for image to preview model + */ + cover_image: string | null; + /** + * Format + * @default diffusers + * @constant + */ + format: "diffusers"; + /** @default */ + repo_variant: components["schemas"]["ModelRepoVariant"]; + /** + * Type + * @default vae + * @constant + */ + type: "vae"; + /** + * Base + * @default flux2 + * @constant + */ + base: "flux2"; + }; /** VAE_Diffusers_SD1_Config */ VAE_Diffusers_SD1_Config: { /** @@ -26310,7 +27183,7 @@ export interface operations { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; + "application/json": components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_FLUX_Config"] | components["schemas"]["Main_Diffusers_Flux2_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_Flux2_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_Flux2_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Checkpoint_Flux2_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["VAE_Diffusers_Flux2_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; }; }; /** @description Validation Error */ @@ -26360,7 +27233,7 @@ export interface operations { * "repo_variant": "fp16", * "upcast_attention": false * } */ - "application/json": components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; + "application/json": components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_FLUX_Config"] | components["schemas"]["Main_Diffusers_Flux2_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_Flux2_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_Flux2_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Checkpoint_Flux2_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["VAE_Diffusers_Flux2_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; }; }; /** @description Bad request */ @@ -26465,7 +27338,7 @@ export interface operations { * "repo_variant": "fp16", * "upcast_attention": false * } */ - "application/json": components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; + "application/json": components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_FLUX_Config"] | components["schemas"]["Main_Diffusers_Flux2_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_Flux2_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_Flux2_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Checkpoint_Flux2_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["VAE_Diffusers_Flux2_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; }; }; /** @description Bad request */ @@ -26536,7 +27409,7 @@ export interface operations { * "repo_variant": "fp16", * "upcast_attention": false * } */ - "application/json": components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; + "application/json": components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_FLUX_Config"] | components["schemas"]["Main_Diffusers_Flux2_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_Flux2_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_Flux2_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Checkpoint_Flux2_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["VAE_Diffusers_Flux2_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; }; }; /** @description Bad request */ @@ -27076,7 +27949,7 @@ export interface operations { * "repo_variant": "fp16", * "upcast_attention": false * } */ - "application/json": components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; + "application/json": components["schemas"]["Main_Diffusers_SD1_Config"] | components["schemas"]["Main_Diffusers_SD2_Config"] | components["schemas"]["Main_Diffusers_SDXL_Config"] | components["schemas"]["Main_Diffusers_SDXLRefiner_Config"] | components["schemas"]["Main_Diffusers_SD3_Config"] | components["schemas"]["Main_Diffusers_FLUX_Config"] | components["schemas"]["Main_Diffusers_Flux2_Config"] | components["schemas"]["Main_Diffusers_CogView4_Config"] | components["schemas"]["Main_Diffusers_ZImage_Config"] | components["schemas"]["Main_Checkpoint_SD1_Config"] | components["schemas"]["Main_Checkpoint_SD2_Config"] | components["schemas"]["Main_Checkpoint_SDXL_Config"] | components["schemas"]["Main_Checkpoint_SDXLRefiner_Config"] | components["schemas"]["Main_Checkpoint_Flux2_Config"] | components["schemas"]["Main_Checkpoint_FLUX_Config"] | components["schemas"]["Main_Checkpoint_ZImage_Config"] | components["schemas"]["Main_BnBNF4_FLUX_Config"] | components["schemas"]["Main_GGUF_Flux2_Config"] | components["schemas"]["Main_GGUF_FLUX_Config"] | components["schemas"]["Main_GGUF_ZImage_Config"] | components["schemas"]["VAE_Checkpoint_SD1_Config"] | components["schemas"]["VAE_Checkpoint_SD2_Config"] | components["schemas"]["VAE_Checkpoint_SDXL_Config"] | components["schemas"]["VAE_Checkpoint_FLUX_Config"] | components["schemas"]["VAE_Checkpoint_Flux2_Config"] | components["schemas"]["VAE_Diffusers_SD1_Config"] | components["schemas"]["VAE_Diffusers_SDXL_Config"] | components["schemas"]["VAE_Diffusers_Flux2_Config"] | components["schemas"]["ControlNet_Checkpoint_SD1_Config"] | components["schemas"]["ControlNet_Checkpoint_SD2_Config"] | components["schemas"]["ControlNet_Checkpoint_SDXL_Config"] | components["schemas"]["ControlNet_Checkpoint_FLUX_Config"] | components["schemas"]["ControlNet_Checkpoint_ZImage_Config"] | components["schemas"]["ControlNet_Diffusers_SD1_Config"] | components["schemas"]["ControlNet_Diffusers_SD2_Config"] | components["schemas"]["ControlNet_Diffusers_SDXL_Config"] | components["schemas"]["ControlNet_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_SD1_Config"] | components["schemas"]["LoRA_LyCORIS_SD2_Config"] | components["schemas"]["LoRA_LyCORIS_SDXL_Config"] | components["schemas"]["LoRA_LyCORIS_FLUX_Config"] | components["schemas"]["LoRA_LyCORIS_ZImage_Config"] | components["schemas"]["LoRA_OMI_SDXL_Config"] | components["schemas"]["LoRA_OMI_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_SD1_Config"] | components["schemas"]["LoRA_Diffusers_SD2_Config"] | components["schemas"]["LoRA_Diffusers_SDXL_Config"] | components["schemas"]["LoRA_Diffusers_FLUX_Config"] | components["schemas"]["LoRA_Diffusers_ZImage_Config"] | components["schemas"]["ControlLoRA_LyCORIS_FLUX_Config"] | components["schemas"]["T5Encoder_T5Encoder_Config"] | components["schemas"]["T5Encoder_BnBLLMint8_Config"] | components["schemas"]["Qwen3Encoder_Qwen3Encoder_Config"] | components["schemas"]["Qwen3Encoder_Checkpoint_Config"] | components["schemas"]["Qwen3Encoder_GGUF_Config"] | components["schemas"]["TI_File_SD1_Config"] | components["schemas"]["TI_File_SD2_Config"] | components["schemas"]["TI_File_SDXL_Config"] | components["schemas"]["TI_Folder_SD1_Config"] | components["schemas"]["TI_Folder_SD2_Config"] | components["schemas"]["TI_Folder_SDXL_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD1_Config"] | components["schemas"]["IPAdapter_InvokeAI_SD2_Config"] | components["schemas"]["IPAdapter_InvokeAI_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD1_Config"] | components["schemas"]["IPAdapter_Checkpoint_SD2_Config"] | components["schemas"]["IPAdapter_Checkpoint_SDXL_Config"] | components["schemas"]["IPAdapter_Checkpoint_FLUX_Config"] | components["schemas"]["T2IAdapter_Diffusers_SD1_Config"] | components["schemas"]["T2IAdapter_Diffusers_SDXL_Config"] | components["schemas"]["Spandrel_Checkpoint_Config"] | components["schemas"]["CLIPEmbed_Diffusers_G_Config"] | components["schemas"]["CLIPEmbed_Diffusers_L_Config"] | components["schemas"]["CLIPVision_Diffusers_Config"] | components["schemas"]["SigLIP_Diffusers_Config"] | components["schemas"]["FLUXRedux_Checkpoint_Config"] | components["schemas"]["LlavaOnevision_Diffusers_Config"] | components["schemas"]["Unknown_Config"]; }; }; /** @description Bad request */ diff --git a/invokeai/frontend/web/src/services/api/types.ts b/invokeai/frontend/web/src/services/api/types.ts index 7ca815ea86..39dba976d3 100644 --- a/invokeai/frontend/web/src/services/api/types.ts +++ b/invokeai/frontend/web/src/services/api/types.ts @@ -79,7 +79,9 @@ export type OffsetPaginatedResults_ImageDTO_ = S['OffsetPaginatedResults_ImageDT // Model Configs export type AnyModelConfig = S['AnyModelConfig']; export type MainModelConfig = Extract; -export type FLUXModelConfig = Extract; +type FLUXModelConfig = Extract; +type FLUX2ModelConfig = Extract; +export type AnyFLUXModelConfig = FLUXModelConfig | FLUX2ModelConfig; export type ControlLoRAModelConfig = Extract; export type LoRAModelConfig = Extract; export type VAEModelConfig = Extract; @@ -168,17 +170,32 @@ export const isNonFluxVAEModelConfig = ( ): config is VAEModelConfig => { return ( (config.type === 'vae' || (!excludeSubmodels && config.type === 'main' && checkSubmodels(['vae'], config))) && - config.base !== 'flux' + config.base !== 'flux' && + config.base !== 'flux2' ); }; export const isFluxVAEModelConfig = (config: AnyModelConfig, excludeSubmodels?: boolean): config is VAEModelConfig => { + return ( + (config.type === 'vae' || (!excludeSubmodels && config.type === 'main' && checkSubmodels(['vae'], config))) && + (config.base === 'flux' || config.base === 'flux2') + ); +}; + +export const isFlux1VAEModelConfig = (config: AnyModelConfig, excludeSubmodels?: boolean): config is VAEModelConfig => { return ( (config.type === 'vae' || (!excludeSubmodels && config.type === 'main' && checkSubmodels(['vae'], config))) && config.base === 'flux' ); }; +export const isFlux2VAEModelConfig = (config: AnyModelConfig, excludeSubmodels?: boolean): config is VAEModelConfig => { + return ( + (config.type === 'vae' || (!excludeSubmodels && config.type === 'main' && checkSubmodels(['vae'], config))) && + config.base === 'flux2' + ); +}; + export const isControlNetModelConfig = (config: AnyModelConfig): config is ControlNetModelConfig => { return config.type === 'controlnet'; }; @@ -289,10 +306,18 @@ export const isRefinerMainModelModelConfig = (config: AnyModelConfig): config is return config.type === 'main' && config.base === 'sdxl-refiner'; }; -export const isFluxDevMainModelConfig = (config: AnyModelConfig): config is MainModelConfig => { +const isFluxDevMainModelConfig = (config: AnyModelConfig): config is MainModelConfig => { return config.type === 'main' && config.base === 'flux' && config.variant === 'dev'; }; +const isFlux2Klein9BMainModelConfig = (config: AnyModelConfig): config is MainModelConfig => { + return config.type === 'main' && config.base === 'flux2' && config.name.toLowerCase().includes('9b'); +}; + +export const isNonCommercialMainModelConfig = (config: AnyModelConfig): config is MainModelConfig => { + return isFluxDevMainModelConfig(config) || isFlux2Klein9BMainModelConfig(config); +}; + export const isFluxFillMainModelModelConfig = (config: AnyModelConfig): config is MainModelConfig => { return config.type === 'main' && config.base === 'flux' && config.variant === 'dev_fill'; };