diff --git a/bundled_packs/ComfyUI-ConditioningKrea2Rebalance/LICENSE b/bundled_packs/ComfyUI-ConditioningKrea2Rebalance/LICENSE
new file mode 100644
index 0000000..29f81d8
--- /dev/null
+++ b/bundled_packs/ComfyUI-ConditioningKrea2Rebalance/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/bundled_packs/ComfyUI-ConditioningKrea2Rebalance/__init__.py b/bundled_packs/ComfyUI-ConditioningKrea2Rebalance/__init__.py
new file mode 100644
index 0000000..fdb4f4b
--- /dev/null
+++ b/bundled_packs/ComfyUI-ConditioningKrea2Rebalance/__init__.py
@@ -0,0 +1,11 @@
+from .nodes import ConditioningKrea2Rebalance
+
+NODE_CLASS_MAPPINGS = {
+ "ConditioningKrea2Rebalance": ConditioningKrea2Rebalance,
+}
+
+NODE_DISPLAY_NAME_MAPPINGS = {
+ "ConditioningKrea2Rebalance": "Conditioning Krea2 Rebalance",
+}
+
+__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"]
diff --git a/bundled_packs/ComfyUI-ConditioningKrea2Rebalance/nodes.py b/bundled_packs/ComfyUI-ConditioningKrea2Rebalance/nodes.py
new file mode 100644
index 0000000..719d22b
--- /dev/null
+++ b/bundled_packs/ComfyUI-ConditioningKrea2Rebalance/nodes.py
@@ -0,0 +1,85 @@
+import torch
+
+
+def _scale_cond_tensor(t: torch.Tensor, multiplier, per_layer_weights=None):
+ """Scale a conditioning tensor, optionally with per-layer weighting.
+
+ Krea2 conditioning arrives as (B, seq, 12*2560) — the 12 Qwen3-VL taps flattened
+ into the feature dim. When per_layer_weights is given we reshape to
+ (B, seq, 12, D), apply a different gain to each tap and flatten back.
+ """
+ if per_layer_weights is None:
+ return t * multiplier
+
+ flat = t.shape[-1]
+ n_layers = len(per_layer_weights)
+ if n_layers > 1 and flat % n_layers == 0:
+ layer_dim = flat // n_layers
+ orig_dtype = t.dtype
+ t = t.float()
+ t = t.view(*t.shape[:-1], n_layers, layer_dim)
+ gains = torch.tensor(per_layer_weights, dtype=t.dtype, device=t.device)
+ t = t * gains.view(*([1] * (t.dim() - 2)), n_layers, 1)
+ t = t.view(*t.shape[:-2], flat)
+ return t.to(orig_dtype) * multiplier
+ return t * multiplier
+
+
+def _parse_per_layer(s: str):
+ """Parse a comma-separated list of floats. Returns None if empty/invalid."""
+ if not s:
+ return None
+ s = s.strip()
+ if not s:
+ return None
+ try:
+ vals = [float(x) for x in s.replace(";", ",").split(",") if x.strip() != ""]
+ except ValueError:
+ return None
+ if len(vals) < 2:
+ return None
+ return vals
+
+
+def scale_conditioning(structure, multiplier, per_layer_weights=None):
+ """leaving masks / pooled output intact."""
+ if isinstance(structure, list):
+ out = []
+ for item in structure:
+ if isinstance(item, (list, tuple)) and len(item) == 2 \
+ and isinstance(item[0], torch.Tensor) and isinstance(item[1], dict):
+ cond_t, extras = item
+ new_cond = _scale_cond_tensor(cond_t, multiplier, per_layer_weights)
+ out.append([new_cond, dict(extras)])
+ else:
+ out.append(scale_conditioning(item, multiplier, per_layer_weights))
+ return out
+ if isinstance(structure, torch.Tensor):
+ return _scale_cond_tensor(structure, multiplier, per_layer_weights)
+ if isinstance(structure, dict):
+ return {k: scale_conditioning(v, multiplier, per_layer_weights)
+ for k, v in structure.items()}
+ return structure
+
+
+class ConditioningKrea2Rebalance:
+
+ DEFAULT_WEIGHTS = "1.0,1.0,1.0,1.0,1.0,1.0,1.0,2.5,5.0,1.1,4.0,1.0"
+
+ @classmethod
+ def INPUT_TYPES(cls):
+ return {"required": {
+ "conditioning": ("CONDITIONING",),
+ "multiplier": ("FLOAT", {"default": 4.0, "min": -1000000000.0, "max": 1000000000.0, "step": 0.01}),
+ "per_layer_weights": ("STRING", {"default": cls.DEFAULT_WEIGHTS, "multiline": False}),
+ }}
+
+ RETURN_TYPES = ("CONDITIONING",)
+ RETURN_NAMES = ("conditioning",)
+ FUNCTION = "main"
+ CATEGORY = "conditioning"
+
+ def main(self, conditioning, multiplier, per_layer_weights=None):
+ plw = _parse_per_layer(per_layer_weights) if per_layer_weights else None
+ c = scale_conditioning(conditioning, multiplier, per_layer_weights=plw)
+ return (c,)
diff --git a/bundled_packs/ComfyUI-VAE-Utils/LICENSE b/bundled_packs/ComfyUI-VAE-Utils/LICENSE
new file mode 100644
index 0000000..846db00
--- /dev/null
+++ b/bundled_packs/ComfyUI-VAE-Utils/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 spacepxl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/bundled_packs/ComfyUI-VAE-Utils/__init__.py b/bundled_packs/ComfyUI-VAE-Utils/__init__.py
new file mode 100644
index 0000000..e965062
--- /dev/null
+++ b/bundled_packs/ComfyUI-VAE-Utils/__init__.py
@@ -0,0 +1,9 @@
+from .nodes import COMBINED_MAPPINGS
+
+NODE_CLASS_MAPPINGS = {}
+NODE_DISPLAY_NAME_MAPPINGS = {}
+for k, v in COMBINED_MAPPINGS.items():
+ NODE_CLASS_MAPPINGS[k] = v[0]
+ NODE_DISPLAY_NAME_MAPPINGS[k] = v[1]
+
+__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']
\ No newline at end of file
diff --git a/bundled_packs/ComfyUI-VAE-Utils/latent_upscale/latent_projector.py b/bundled_packs/ComfyUI-VAE-Utils/latent_upscale/latent_projector.py
new file mode 100644
index 0000000..17b1603
--- /dev/null
+++ b/bundled_packs/ComfyUI-VAE-Utils/latent_upscale/latent_projector.py
@@ -0,0 +1,56 @@
+import os
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+from safetensors.torch import load_file
+
+
+class CausalLatentProjector(nn.Module):
+ def __init__(
+ self,
+ in_channels = 16,
+ out_channels = 3,
+ scale_t = 4,
+ scale_s = 8,
+ num_projections = 3,
+ ):
+ super().__init__()
+ self.scale_t = scale_t
+ self.scale_s = scale_s
+
+ self.projections = nn.ModuleList([
+ nn.Linear(in_channels, out_channels * scale_s ** 2)
+ ])
+
+ for _ in range(num_projections - 1):
+ self.projections.append(
+ nn.Linear(in_channels, out_channels * scale_t * scale_s ** 2)
+ )
+
+ def forward(self, latents):
+ batch, channels, frames, height, width = latents.shape
+
+ pixels = []
+ for frame in range(frames):
+ idx = min(frame, len(self.projections) - 1)
+
+ feat = self.projections[idx](
+ latents[:, :, frame].movedim(1, -1) # BHWC
+ ).movedim(-1, 1) # BCHW
+
+ feat = F.pixel_shuffle(feat, self.scale_s).unsqueeze(2) # BCFHW
+
+ if frame == 0:
+ pixels.append(feat)
+ else:
+ feat = feat.chunk(self.scale_t, dim=1)
+ pixels.extend(list(feat))
+
+ return torch.cat(pixels, dim=2)
+
+
+def Wan21_latent_projector():
+ model = CausalLatentProjector()
+ model_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "wan21_latent_projector.safetensors")
+ model.load_state_dict(load_file(model_path))
+ return model
\ No newline at end of file
diff --git a/bundled_packs/ComfyUI-VAE-Utils/latent_upscale/model.py b/bundled_packs/ComfyUI-VAE-Utils/latent_upscale/model.py
new file mode 100644
index 0000000..55f879b
--- /dev/null
+++ b/bundled_packs/ComfyUI-VAE-Utils/latent_upscale/model.py
@@ -0,0 +1,155 @@
+import os
+import math
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+from safetensors.torch import load_file
+
+
+class LayerNorm3d(nn.LayerNorm):
+ def __init__(self, num_channels, eps=1e-6, affine=True):
+ super().__init__(num_channels, eps=eps, elementwise_affine=affine)
+
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
+ x = x.permute(0, 2, 3, 4, 1)
+ x = F.layer_norm(x, self.normalized_shape, self.weight, self.bias, self.eps)
+ x = x.permute(0, 4, 1, 2, 3)
+ return x
+
+
+class DiCoBlock3d(nn.Module):
+ def __init__(self, hidden_size, mlp_ratio=4.0, kernel_size=3):
+ super().__init__()
+
+ # self.conv1 = nn.Conv3d(hidden_size, hidden_size, kernel_size=1)
+
+ self.conv2 = nn.Conv3d(
+ hidden_size,
+ hidden_size,
+ kernel_size=(1, kernel_size, kernel_size),
+ padding=(0, kernel_size//2, kernel_size//2),
+ # groups=hidden_size,
+ padding_mode="replicate",
+ )
+
+ self.conv3 = nn.Conv3d(hidden_size, hidden_size, kernel_size=1)
+
+ self.cca = nn.Sequential(
+ nn.AdaptiveAvgPool3d(1),
+ nn.Conv3d(hidden_size, hidden_size , kernel_size=1),
+ nn.Sigmoid(),
+ )
+
+ ffn_channel = int(mlp_ratio * hidden_size)
+ self.conv4 = nn.Conv3d(hidden_size, ffn_channel, kernel_size=1)
+ self.conv5 = nn.Conv3d(ffn_channel, hidden_size, kernel_size=1)
+
+ self.norm1 = LayerNorm3d(hidden_size, affine=False)
+ self.norm2 = LayerNorm3d(hidden_size, affine=False)
+
+ def forward(self, inp):
+ x = self.norm1(inp)
+ # x = F.gelu(self.conv2(self.conv1(x)))
+ x = F.gelu(self.conv2(x))
+ x = self.conv3(x * self.cca(x))
+ x = inp + x
+
+ y = self.norm2(x)
+ y = self.conv5(F.gelu(self.conv4(y)))
+ return x + y
+
+
+class LatentModel3d(nn.Module):
+ def __init__(
+ self,
+ in_channels = 16,
+ out_channels = 16,
+ hidden_size = 128,
+ kernel_size = 3,
+ mlp_ratio = 4.0,
+ depth = 8,
+ upscale = 2,
+ ):
+ super().__init__()
+ self.upscale = int(upscale)
+
+ self.conv_in = nn.Conv3d(
+ in_channels,
+ hidden_size,
+ kernel_size=(1, 3, 3),
+ padding=(0, 1, 1),
+ padding_mode="replicate",
+ )
+
+ self.blocks = nn.ModuleList([
+ DiCoBlock3d(hidden_size, mlp_ratio, kernel_size)
+ for _ in range(depth)
+ ])
+
+ out_ch = out_channels * self.upscale ** 2
+ self.conv_out = nn.Conv3d(
+ hidden_size,
+ out_ch,
+ kernel_size=(1, 3, 3),
+ padding=(0, 1, 1),
+ padding_mode="replicate",
+ )
+
+ # self.initialize_weights()
+
+ def initialize_weights(self):
+ def _basic_init(module):
+ if isinstance(module, nn.Linear) or isinstance(module, nn.Conv3d):
+ torch.nn.init.xavier_uniform_(module.weight)
+ if module.bias is not None:
+ nn.init.constant_(module.bias, 0)
+ self.apply(_basic_init)
+
+ def forward(self, x):
+ """
+ x: (B, C, F, H, W) tensor of spatial inputs (images or latent representations of images)
+ """
+ hidden = self.conv_in(x)
+
+ for block in self.blocks:
+ hidden = block(hidden)
+
+ output = self.conv_out(hidden)
+
+ if self.upscale > 1:
+ output = F.pixel_shuffle(output.movedim(1, 2), self.upscale).movedim(2, 1)
+ x = F.interpolate(x, scale_factor=(1, self.upscale, self.upscale), mode="nearest-exact")
+ return output + x
+
+
+def Wan21_latent_upscale_2x():
+ model = LatentModel3d(
+ in_channels = 16,
+ out_channels = 16,
+ hidden_size = 128,
+ kernel_size = 3,
+ mlp_ratio = 4.0,
+ depth = 8,
+ upscale = 2,
+ )
+ model_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "wan21_latent_upscale_2x.safetensors")
+ model.load_state_dict(load_file(model_path))
+ return model
+
+
+latent_upscale_models = {
+ "Wan 2.1 latent upscale 2x": Wan21_latent_upscale_2x,
+}
+
+
+if __name__=="__main__":
+ model = LatentModel3d(upscale=2).to("cuda")
+
+ x = torch.randn(1, 16, 4, 64, 64).to("cuda")
+ out = model(x)
+ print(out.shape)
+
+ total = sum([p.numel() for p in model.parameters() if p.requires_grad])
+ print("trainable parameters: %.2f M" % (total / 1e6))
+
+ print(model)
\ No newline at end of file
diff --git a/bundled_packs/ComfyUI-VAE-Utils/latent_upscale/wan21_latent_projector.safetensors b/bundled_packs/ComfyUI-VAE-Utils/latent_upscale/wan21_latent_projector.safetensors
new file mode 100644
index 0000000..9b465e9
Binary files /dev/null and b/bundled_packs/ComfyUI-VAE-Utils/latent_upscale/wan21_latent_projector.safetensors differ
diff --git a/bundled_packs/ComfyUI-VAE-Utils/latent_upscale/wan21_latent_upscale_2x.safetensors b/bundled_packs/ComfyUI-VAE-Utils/latent_upscale/wan21_latent_upscale_2x.safetensors
new file mode 100644
index 0000000..85ad83e
Binary files /dev/null and b/bundled_packs/ComfyUI-VAE-Utils/latent_upscale/wan21_latent_upscale_2x.safetensors differ
diff --git a/bundled_packs/ComfyUI-VAE-Utils/nodes.py b/bundled_packs/ComfyUI-VAE-Utils/nodes.py
new file mode 100644
index 0000000..21757fa
--- /dev/null
+++ b/bundled_packs/ComfyUI-VAE-Utils/nodes.py
@@ -0,0 +1,450 @@
+import torch
+import torch.nn.functional as F
+import copy
+import math
+from tqdm.auto import tqdm
+
+import comfy.utils
+import comfy.model_management
+import comfy.latent_formats
+import folder_paths
+from nodes import VAELoader
+from .src.sd import CustomVAE
+from .latent_upscale.model import latent_upscale_models
+from .latent_upscale.latent_projector import Wan21_latent_projector
+
+
+class VAEUtils_CustomVAELoader(VAELoader):
+ @staticmethod
+ def vae_list():
+ return folder_paths.get_filename_list("vae")
+
+ @classmethod
+ def INPUT_TYPES(s):
+ return {
+ "required": {
+ "vae_name": (s.vae_list(), ),
+ "disable_offload": ("BOOLEAN", {"default": True}),
+ }
+ }
+
+ RETURN_TYPES = ("VAE",)
+ FUNCTION = "load_vae"
+ CATEGORY = "VAE-Utils"
+
+ def load_vae(self, vae_name, disable_offload):
+ if vae_name == "pixel_space":
+ sd = {}
+ sd["pixel_space_vae"] = torch.tensor(1.0)
+ elif vae_name in ["taesd", "taesdxl", "taesd3", "taef1"]:
+ sd = self.load_taesd(vae_name)
+ else:
+ vae_path = folder_paths.get_full_path_or_raise("vae", vae_name)
+ sd = comfy.utils.load_torch_file(vae_path)
+ vae = CustomVAE(sd=sd)
+ vae.throw_exception_if_invalid()
+ vae.disable_offload = disable_offload
+ return (vae, )
+
+
+class VAEUtils_DisableVAEOffload:
+ @classmethod
+ def INPUT_TYPES(s):
+ return {
+ "required": {
+ "vae": ("VAE", ),
+ "disable_offload": ("BOOLEAN", {"default": True}),
+ }
+ }
+
+ RETURN_TYPES = ("VAE",)
+ FUNCTION = "set_offload"
+ CATEGORY = "VAE-Utils"
+
+ def set_offload(self, vae, disable_offload):
+ vae = copy.copy(vae)
+ vae.disable_offload = disable_offload
+ return (vae, )
+
+
+class VAEUtils_VAEDecodeTiled:
+ @classmethod
+ def INPUT_TYPES(s):
+ return {
+ "required": {
+ "samples": ("LATENT", ),
+ "vae": ("VAE", ),
+ "upscale": ("INT", {"default": -1, "min": -1, "tooltip": "Post upscale factor, -1=auto"}),
+ "tile": ("BOOLEAN", {"default": False}),
+ "tile_size": ("INT", {"default": 512, "min": 64, "max": 4096, "step": 32}),
+ "overlap": ("INT", {"default": 64, "min": 0, "max": 4096, "step": 32}),
+ "temporal_size": ("INT", {"default": 4096, "min": 8, "max": 4096, "step": 4, "tooltip": "Only used for video VAEs: Amount of frames to decode at a time."}),
+ "temporal_overlap": ("INT", {"default": 64, "min": 4, "max": 4096, "step": 4, "tooltip": "Only used for video VAEs: Amount of frames to overlap."}),
+ }
+ }
+
+ RETURN_TYPES = ("IMAGE",)
+ FUNCTION = "decode"
+ CATEGORY = "VAE-Utils"
+
+ def decode(self, samples, vae, upscale, tile, tile_size, overlap, temporal_size, temporal_overlap):
+ if tile_size < overlap * 4:
+ overlap = tile_size // 4
+ if temporal_size < temporal_overlap * 2:
+ temporal_overlap = temporal_overlap // 2
+ temporal_compression = vae.temporal_compression_decode()
+ if temporal_compression is not None:
+ temporal_size = max(2, temporal_size // temporal_compression)
+ temporal_overlap = max(1, min(temporal_size // 2, temporal_overlap // temporal_compression))
+ else:
+ temporal_size = None
+ temporal_overlap = None
+
+ compression = vae.spacial_compression_decode()
+
+ if tile:
+ images = vae.decode_tiled(samples["samples"], tile_x=tile_size // compression, tile_y=tile_size // compression, overlap=overlap // compression, tile_t=temporal_size, overlap_t=temporal_overlap)
+ else:
+ images = vae.decode(samples["samples"])
+
+ if len(images.shape) == 5: #Combine batches
+ images = images.reshape(-1, images.shape[-3], images.shape[-2], images.shape[-1])
+
+ # Safety guard for ComfyUI PRs #11405 / #11406 regression:
+ # If process_output was not applied through the inherited VAE.decode() path the raw
+ # decoder output lands in [-1, 1]. Values below 0 are clamped to black by save/preview
+ # nodes, producing the dark/burned look. Detect and correct here.
+ # This guard is safe on correctly-decoded images because they are always in [0, 1]
+ # so min >= 0 and the branch never fires.
+ if images.min() < -0.1:
+ images = torch.clamp((images.float() + 1.0) / 2.0, min=0.0, max=1.0)
+
+ if upscale < 1:
+ ch = images.shape[-1]
+ if ch == 3:
+ upscale = 1
+ else:
+ if ch % 3 == 0:
+ upscale = round((ch // 3) ** 0.5)
+ else:
+ raise Exception("Couldn't determine upscale factor, try setting the value manually instead")
+
+ if upscale > 1:
+ images = F.pixel_shuffle(images.movedim(-1, 1), upscale_factor=int(upscale)).movedim(1, -1)
+
+ return (images, )
+
+
+class VAEUtils_LatentUpscale:
+ @classmethod
+ def INPUT_TYPES(s):
+ return {
+ "required": {
+ "samples": ("LATENT", ),
+ "model": (list(latent_upscale_models.keys()), ),
+ }
+ }
+
+ RETURN_TYPES = ("LATENT",)
+ FUNCTION = "upscale"
+ CATEGORY = "VAE-Utils"
+
+ def upscale(self, samples, model):
+ device = comfy.model_management.get_torch_device()
+ model = latent_upscale_models[model]().to(device)
+
+ latents = samples["samples"].to(dtype=torch.float32, device=device)
+ upscaled_latents = model(latents).to(comfy.model_management.intermediate_device())
+
+ samples = copy.deepcopy(samples)
+ samples["samples"] = upscaled_latents
+
+ return (samples, )
+
+
+class VAEUtils_WanLatentPreview:
+ @classmethod
+ def INPUT_TYPES(s):
+ return {
+ "required": {
+ "samples": ("LATENT", ),
+ }
+ }
+
+ RETURN_TYPES = ("IMAGE",)
+ FUNCTION = "upscale"
+ CATEGORY = "VAE-Utils"
+
+ def upscale(self, samples):
+ device = comfy.model_management.intermediate_device()
+ projector = Wan21_latent_projector().to(device)
+
+ latents = samples["samples"].to(dtype=torch.float32, device=device)
+ pixels = projector(latents).to(comfy.model_management.intermediate_device())
+ pixels = pixels * 0.5 + 0.5
+
+ f, h, w = pixels.shape[-3:]
+ pixels = F.interpolate(pixels, size=(f, h//8, w//8), mode="area")
+
+ pixels = [b.movedim(0, -1) for b in pixels] # CFHW -> FHWC
+ pixels = torch.cat(pixels, dim=0) # (BF)HWC
+ return (pixels, )
+
+
+def get_tiles(length, tile_size, min_overlap):
+ if length <= tile_size:
+ return [(0, length)]
+
+ max_step = tile_size - min_overlap
+ total_shiftable = length - tile_size
+
+ gaps_needed = math.ceil(total_shiftable / max_step) if total_shiftable > 0 else 0
+ num_tiles = gaps_needed + 1
+
+ if num_tiles == 1:
+ raise Exception("this shouldn't happen")
+
+ gap_base = total_shiftable // (num_tiles - 1)
+ remainder = total_shiftable % (num_tiles - 1)
+
+ starts = []
+ acc = 0
+ for i in range(num_tiles):
+ starts.append(acc)
+ if i < num_tiles - 1:
+ acc += gap_base + (1 if i < remainder else 0)
+
+ slices = [(s, s + tile_size) for s in starts]
+ return slices
+
+
+def get_1d_mask(idx, tiles, drop_first=0):
+ tile_start, tile_end = tiles[idx]
+ mask = torch.ones(tile_end - tile_start)
+
+ if idx > 0:
+ prev_end = tiles[idx - 1][1]
+ size = prev_end - tile_start - drop_first
+ ramp = (torch.arange(size) + 1) / size
+ mask[drop_first : size + drop_first] *= ramp
+ mask[:drop_first] *= 0
+
+ if idx < (len(tiles) - 1):
+ next_start = tiles[idx + 1][0]
+ size = tile_end - next_start
+ ramp = (torch.flip(torch.arange(size), [0]) + 1) / size
+ mask[-size:] *= ramp
+
+ return mask
+
+
+class VAEUtils_TileModelPatch:
+ @classmethod
+ def INPUT_TYPES(s):
+ return {
+ "required": {
+ "model": ("MODEL", ),
+ "tile_t": ("INT", {"default": 13, "min": 3, "step": 1}),
+ "tile_h": ("INT", {"default": 78, "min": 32, "step": 2}),
+ "tile_w": ("INT", {"default": 78, "min": 32, "step": 2}),
+ "min_overlap_t": ("INT", {"default": 5, "min": 1, "step": 1}),
+ "min_overlap_h": ("INT", {"default": 16, "min": 0, "step": 2}),
+ "min_overlap_w": ("INT", {"default": 16, "min": 0, "step": 2}),
+ "drop_first_t": ("INT", {"default": 2, "min": 0, "step": 1}),
+ "patch_memory_estimate": ("BOOLEAN", {"default": True}),
+ }
+ }
+
+ RETURN_TYPES = ("MODEL",)
+ FUNCTION = "patch"
+ CATEGORY = "VAE-Utils"
+
+ def patch(self, model, tile_t, tile_h, tile_w, min_overlap_t, min_overlap_h, min_overlap_w, drop_first_t, patch_memory_estimate):
+ model = model.clone()
+
+ def model_function_tile_wrapper(apply_model, args):
+ # print(args["c"]["transformer_options"]["patches"]["noise_refiner"][0].encoded_image.shape)
+
+ # collect inputs
+ x = args["input"]
+ t = args["timestep"]
+ c = args["c"]
+ c_concat = c.get("c_concat", None)
+ vace_context = c.get("vace_context", None)
+ # transformer_options = c.get("transformer_options", {})
+
+ if c_concat is not None:
+ assert c_concat.shape[2:] == x.shape[2:], f"c_concat shape {c_concat.shape} doesn't match x shape {x.shape}"
+
+ t_tiles = get_tiles(x.shape[-3], tile_t, min_overlap_t) if x.ndim == 5 else None
+ h_tiles = get_tiles(x.shape[-2], tile_h, min_overlap_h)
+ w_tiles = get_tiles(x.shape[-1], tile_w, min_overlap_w)
+
+ total_tiles = len(h_tiles) * len(w_tiles)
+ message = f"{len(h_tiles)}h {len(w_tiles)}w"
+
+ if t_tiles is not None:
+ total_tiles *= len(t_tiles)
+ message = f"{len(t_tiles)}t " + message
+
+ x_out = torch.zeros_like(x)
+ x_alpha = torch.zeros_like(x)
+ progress_bar = tqdm(range(0, total_tiles), desc=message)
+
+ for w_idx, (w_start, w_end) in enumerate(w_tiles):
+ for h_idx, (h_start, h_end) in enumerate(h_tiles):
+ if t_tiles is not None:
+ for t_idx, (t_start, t_end) in enumerate(t_tiles):
+ # slice inputs (todo: any other conditions? controlnets etc)
+ x_tile = x[..., t_start:t_end, h_start:h_end, w_start:w_end]
+ c_tile = c.copy()
+
+ if c_concat is not None:
+ c_tile["c_concat"] = c_concat[..., t_start:t_end, h_start:h_end, w_start:w_end]
+
+ if vace_context is not None:
+ c_tile["vace_context"] = vace_context[..., t_start:t_end, h_start:h_end, w_start:w_end]
+
+ tile_out = apply_model(x_tile, t, **c_tile)
+
+ # prepare mask for edge blending
+ mask_t = get_1d_mask(t_idx, t_tiles, drop_first_t).view(1, 1, -1, 1, 1)
+ mask_h = get_1d_mask(h_idx, h_tiles).view(1, 1, 1, -1, 1)
+ mask_w = get_1d_mask(w_idx, w_tiles).view(1, 1, 1, 1, -1)
+
+ mask = torch.ones_like(tile_out)
+ mask *= mask_t.to(mask)
+ mask *= mask_h.to(mask)
+ mask *= mask_w.to(mask)
+
+ # accumulate tile into full image
+ x_out[:, :, t_start:t_end, h_start:h_end, w_start:w_end] += tile_out * mask
+ x_alpha[:, :, t_start:t_end, h_start:h_end, w_start:w_end] += mask
+ progress_bar.update(1)
+
+ else:
+ x_tile = x[..., h_start:h_end, w_start:w_end]
+ c_tile = c.copy()
+
+ if c_concat is not None:
+ c_tile["c_concat"] = c_concat[..., h_start:h_end, w_start:w_end]
+
+ tile_out = apply_model(x_tile, t, **c_tile)
+
+ mask_h = get_1d_mask(h_idx, h_tiles).view(1, 1, -1, 1)
+ mask_w = get_1d_mask(w_idx, w_tiles).view(1, 1, 1, -1)
+
+ mask = torch.ones_like(tile_out)
+ mask *= mask_h.to(mask)
+ mask *= mask_w.to(mask)
+
+ x_out[:, :, h_start:h_end, w_start:w_end] += tile_out * mask
+ x_alpha[:, :, h_start:h_end, w_start:w_end] += mask
+ progress_bar.update(1)
+
+ assert x_alpha.min() > 0, "missing tile coverage"
+ x_out = x_out / x_alpha
+ return x_out
+
+ model.set_model_unet_function_wrapper(model_function_tile_wrapper)
+
+ def update_input_shape(input_shape):
+ new_input_shape = input_shape.copy()
+ if len(new_input_shape) == 5:
+ new_input_shape = new_input_shape[:2] + [tile_t, tile_h, tile_w]
+ elif len(new_input_shape) == 4:
+ new_input_shape = new_input_shape[:2] + [tile_h, tile_w]
+ return new_input_shape
+
+ original_memory_required = model.model.memory_required
+
+ def memory_required_wrapper(input_shape, cond_shapes={}):
+ new_input_shape = update_input_shape(input_shape)
+
+ for c in model.model.memory_usage_factor_conds:
+ shape = cond_shapes.get(c, None)
+ if shape is not None:
+ new_shape = update_input_shape(shape)
+ cond_shapes[c] = new_shape
+
+ return original_memory_required(new_input_shape, cond_shapes)
+
+ if patch_memory_estimate:
+ model.model.memory_required = memory_required_wrapper
+
+ return (model, )
+
+
+class VAEUtils_VisualizeTiles:
+ @classmethod
+ def INPUT_TYPES(s):
+ return {
+ "required": {
+ "length": ("INT", {"default": 21, "min": 1, "step": 1}),
+ "tile_size": ("INT", {"default": 13, "min": 1, "step": 1}),
+ "min_overlap": ("INT", {"default": 5, "min": 0, "step": 1}),
+ "drop_first": ("INT", {"default": 2, "min": 0, "step": 1}),
+ }
+ }
+
+ RETURN_TYPES = ("IMAGE",)
+ FUNCTION = "visualize"
+ CATEGORY = "VAE-Utils"
+
+ def visualize(self, length, tile_size, min_overlap, drop_first):
+ tile_slices = get_tiles(length, tile_size, min_overlap)
+
+ image = torch.zeros(1, 3, len(tile_slices), length)
+
+ for idx, (start, end) in enumerate(tile_slices):
+ print(idx, start, end)
+ mask = get_1d_mask(idx, tile_slices, drop_first)
+ image[:, :, idx, start:end] = mask
+
+ image = F.interpolate(image, scale_factor=8, mode="nearest-exact")
+ image = image.movedim(1, -1)
+
+ return (image, )
+
+
+latent_formats = {name: obj for name, obj in vars(comfy.latent_formats).items() if isinstance(obj, type)}
+del latent_formats["LatentFormat"]
+
+
+class VAEUtils_ScaleLatents:
+ @classmethod
+ def INPUT_TYPES(s):
+ return {
+ "required": {
+ "latents": ("LATENT", ),
+ "direction": (["scale", "unscale"], ),
+ "latent_type": (list(latent_formats.keys()), ),
+ }
+ }
+
+ RETURN_TYPES = ("LATENT",)
+ FUNCTION = "scale"
+ CATEGORY = "VAE-Utils"
+
+ def scale(self, latents, direction, latent_type):
+ latents = copy.deepcopy(latents)
+ latent_format = latent_formats[latent_type]()
+
+ if direction == "scale":
+ latents["samples"] = latent_format.process_in(latents["samples"])
+ else:
+ latents["samples"] = latent_format.process_out(latents["samples"])
+
+ return (latents, )
+
+
+COMBINED_MAPPINGS = {
+ "VAEUtils_CustomVAELoader": (VAEUtils_CustomVAELoader, "Load VAE (VAE Utils)"),
+ "VAEUtils_DisableVAEOffload": (VAEUtils_DisableVAEOffload, "Disable VAE Offload (VAE Utils)"),
+ "VAEUtils_VAEDecodeTiled": (VAEUtils_VAEDecodeTiled, "VAE Decode (VAE Utils)"),
+ "VAEUtils_LatentUpscale": (VAEUtils_LatentUpscale, "Latent Upscale (VAE Utils)"),
+ "VAEUtils_WanLatentPreview": (VAEUtils_WanLatentPreview, "Wan Latent Preview (VAE Utils)"),
+ "VAEUtils_TileModelPatch": (VAEUtils_TileModelPatch, "Tile Model Patch (VAE Utils)"),
+ "VAEUtils_VisualizeTiles": (VAEUtils_VisualizeTiles, "Visualize Tiles (VAE Utils)"),
+ "VAEUtils_ScaleLatents": (VAEUtils_ScaleLatents, "Scale/Unscale Latents (VAE Utils)"),
+}
\ No newline at end of file
diff --git a/bundled_packs/ComfyUI-VAE-Utils/src/sd.py b/bundled_packs/ComfyUI-VAE-Utils/src/sd.py
new file mode 100644
index 0000000..b5670a8
--- /dev/null
+++ b/bundled_packs/ComfyUI-VAE-Utils/src/sd.py
@@ -0,0 +1,420 @@
+import math
+import json
+import torch
+import logging
+
+from comfy import model_management
+from comfy.ldm.models.autoencoder import AutoencoderKL, AutoencodingEngine
+# from comfy.ldm.cascade.stage_a import StageA
+# from comfy.ldm.cascade.stage_c_coder import StageC_coder
+# from comfy.ldm.audio.autoencoder import AudioOobleckVAE
+# import comfy.ldm.genmo.vae.model
+# import comfy.ldm.lightricks.vae.causal_video_autoencoder
+# import comfy.ldm.cosmos.vae
+from .wan.vae import WanVAE
+import comfy.ldm.wan.vae2_2
+# import comfy.ldm.hunyuan3d.vae
+# import comfy.ldm.ace.vae.music_dcae_pipeline
+# import comfy.ldm.hunyuan_video.vae
+# import comfy.ldm.mmaudio.vae.autoencoder
+# import comfy.pixel_space_convert
+
+import comfy.utils
+
+import comfy.model_patcher
+import comfy.taesd.taesd
+
+from comfy.sd import VAE
+
+class CustomVAE(VAE):
+ def __init__(self, sd=None, device=None, config=None, dtype=None, metadata=None):
+ if model_management.is_amd():
+ VAE_KL_MEM_RATIO = 2.73
+ else:
+ VAE_KL_MEM_RATIO = 1.0
+
+ self.memory_used_encode = lambda shape, dtype: (1767 * shape[2] * shape[3]) * model_management.dtype_size(dtype) * VAE_KL_MEM_RATIO #These are for AutoencoderKL and need tweaking (should be lower)
+ self.memory_used_decode = lambda shape, dtype: (2178 * shape[2] * shape[3] * 64) * model_management.dtype_size(dtype) * VAE_KL_MEM_RATIO
+ self.downscale_ratio = 8
+ self.upscale_ratio = 8
+ self.latent_channels = 4
+ self.latent_dim = 2
+ self.input_channels = 3
+ self.output_channels = 3
+ self.real_output_channels = 3
+ self.pad_channel_value = None
+ self.process_input = lambda image: image * 2.0 - 1.0
+ self.process_output = lambda image: torch.clamp((image + 1.0) / 2.0, min=0.0, max=1.0)
+ self.working_dtypes = [torch.bfloat16, torch.float32]
+ self.disable_offload = False
+ self.not_video = False
+ self.size = None
+
+ self.downscale_index_formula = None
+ self.upscale_index_formula = None
+ self.extra_1d_channel = None
+ self.crop_input = True
+
+ if config is None:
+ if "decoder.mid.block_1.mix_factor" in sd:
+ encoder_config = {'double_z': True, 'z_channels': 4, 'resolution': 256, 'in_channels': 3, 'out_ch': 3, 'ch': 128, 'ch_mult': [1, 2, 4, 4], 'num_res_blocks': 2, 'attn_resolutions': [], 'dropout': 0.0}
+ decoder_config = encoder_config.copy()
+ decoder_config["video_kernel_size"] = [3, 1, 1]
+ decoder_config["alpha"] = 0.0
+ self.first_stage_model = AutoencodingEngine(regularizer_config={'target': "comfy.ldm.models.autoencoder.DiagonalGaussianRegularizer"},
+ encoder_config={'target': "comfy.ldm.modules.diffusionmodules.model.Encoder", 'params': encoder_config},
+ decoder_config={'target': "comfy.ldm.modules.temporal_ae.VideoDecoder", 'params': decoder_config})
+ elif "taesd_decoder.1.weight" in sd:
+ self.latent_channels = sd["taesd_decoder.1.weight"].shape[1]
+ self.first_stage_model = comfy.taesd.taesd.TAESD(latent_channels=self.latent_channels)
+ # elif "vquantizer.codebook.weight" in sd: #VQGan: stage a of stable cascade
+ # self.first_stage_model = StageA()
+ # self.downscale_ratio = 4
+ # self.upscale_ratio = 4
+ # self.process_input = lambda image: image
+ # self.process_output = lambda image: image
+ # elif "backbone.1.0.block.0.1.num_batches_tracked" in sd: #effnet: encoder for stage c latent of stable cascade
+ # self.first_stage_model = StageC_coder()
+ # self.downscale_ratio = 32
+ # self.latent_channels = 16
+ # new_sd = {}
+ # for k in sd:
+ # new_sd["encoder.{}".format(k)] = sd[k]
+ # sd = new_sd
+ # elif "blocks.11.num_batches_tracked" in sd: #previewer: decoder for stage c latent of stable cascade
+ # self.first_stage_model = StageC_coder()
+ # self.latent_channels = 16
+ # new_sd = {}
+ # for k in sd:
+ # new_sd["previewer.{}".format(k)] = sd[k]
+ # sd = new_sd
+ # elif "encoder.backbone.1.0.block.0.1.num_batches_tracked" in sd: #combined effnet and previewer for stable cascade
+ # self.first_stage_model = StageC_coder()
+ # self.downscale_ratio = 32
+ # self.latent_channels = 16
+ elif "decoder.conv_in.weight" in sd:
+ # if sd['decoder.conv_in.weight'].shape[1] == 64:
+ # ddconfig = {"block_out_channels": [128, 256, 512, 512, 1024, 1024], "in_channels": 3, "out_channels": 3, "num_res_blocks": 2, "ffactor_spatial": 32, "downsample_match_channel": True, "upsample_match_channel": True}
+ # self.latent_channels = ddconfig['z_channels'] = sd["decoder.conv_in.weight"].shape[1]
+ # self.downscale_ratio = 32
+ # self.upscale_ratio = 32
+ # self.working_dtypes = [torch.float16, torch.bfloat16, torch.float32]
+ # self.first_stage_model = AutoencodingEngine(regularizer_config={'target': "comfy.ldm.models.autoencoder.DiagonalGaussianRegularizer"},
+ # encoder_config={'target': "comfy.ldm.hunyuan_video.vae.Encoder", 'params': ddconfig},
+ # decoder_config={'target': "comfy.ldm.hunyuan_video.vae.Decoder", 'params': ddconfig})
+
+ # self.memory_used_encode = lambda shape, dtype: (700 * shape[2] * shape[3]) * model_management.dtype_size(dtype)
+ # self.memory_used_decode = lambda shape, dtype: (700 * shape[2] * shape[3] * 32 * 32) * model_management.dtype_size(dtype)
+ # elif sd['decoder.conv_in.weight'].shape[1] == 32:
+ # ddconfig = {"block_out_channels": [128, 256, 512, 1024, 1024], "in_channels": 3, "out_channels": 3, "num_res_blocks": 2, "ffactor_spatial": 16, "ffactor_temporal": 4, "downsample_match_channel": True, "upsample_match_channel": True, "refiner_vae": False}
+ # self.latent_channels = ddconfig['z_channels'] = sd["decoder.conv_in.weight"].shape[1]
+ # self.working_dtypes = [torch.float16, torch.bfloat16, torch.float32]
+ # self.upscale_ratio = (lambda a: max(0, a * 4 - 3), 16, 16)
+ # self.upscale_index_formula = (4, 16, 16)
+ # self.downscale_ratio = (lambda a: max(0, math.floor((a + 3) / 4)), 16, 16)
+ # self.downscale_index_formula = (4, 16, 16)
+ # self.latent_dim = 3
+ # self.not_video = True
+ # self.first_stage_model = AutoencodingEngine(regularizer_config={'target': "comfy.ldm.models.autoencoder.DiagonalGaussianRegularizer"},
+ # encoder_config={'target': "comfy.ldm.hunyuan_video.vae_refiner.Encoder", 'params': ddconfig},
+ # decoder_config={'target': "comfy.ldm.hunyuan_video.vae_refiner.Decoder", 'params': ddconfig})
+
+ # self.memory_used_encode = lambda shape, dtype: (2800 * shape[-2] * shape[-1]) * model_management.dtype_size(dtype)
+ # self.memory_used_decode = lambda shape, dtype: (2800 * shape[-3] * shape[-2] * shape[-1] * 16 * 16) * model_management.dtype_size(dtype)
+ # else:
+ #default SD1.x/SD2.x VAE parameters
+ ddconfig = {'double_z': True, 'z_channels': 4, 'resolution': 256, 'in_channels': 3, 'out_ch': 3, 'ch': 128, 'ch_mult': [1, 2, 4, 4], 'num_res_blocks': 2, 'attn_resolutions': [], 'dropout': 0.0}
+
+ if 'encoder.down.2.downsample.conv.weight' not in sd and 'decoder.up.3.upsample.conv.weight' not in sd: #Stable diffusion x4 upscaler VAE
+ ddconfig['ch_mult'] = [1, 2, 4]
+ self.downscale_ratio = 4
+ self.upscale_ratio = 4
+
+ self.latent_channels = ddconfig['z_channels'] = sd["decoder.conv_in.weight"].shape[1]
+ if 'post_quant_conv.weight' in sd:
+ self.first_stage_model = AutoencoderKL(ddconfig=ddconfig, embed_dim=sd['post_quant_conv.weight'].shape[1])
+ else:
+ self.first_stage_model = AutoencodingEngine(regularizer_config={'target': "comfy.ldm.models.autoencoder.DiagonalGaussianRegularizer"},
+ encoder_config={'target': "comfy.ldm.modules.diffusionmodules.model.Encoder", 'params': ddconfig},
+ decoder_config={'target': "comfy.ldm.modules.diffusionmodules.model.Decoder", 'params': ddconfig})
+ # elif "decoder.layers.1.layers.0.beta" in sd:
+ # self.first_stage_model = AudioOobleckVAE()
+ # self.memory_used_encode = lambda shape, dtype: (1000 * shape[2]) * model_management.dtype_size(dtype)
+ # self.memory_used_decode = lambda shape, dtype: (1000 * shape[2] * 2048) * model_management.dtype_size(dtype)
+ # self.latent_channels = 64
+ # self.output_channels = 2
+ # self.upscale_ratio = 2048
+ # self.downscale_ratio = 2048
+ # self.latent_dim = 1
+ # self.process_output = lambda audio: audio
+ # self.process_input = lambda audio: audio
+ # self.working_dtypes = [torch.float16, torch.bfloat16, torch.float32]
+ # self.disable_offload = True
+ # elif "blocks.2.blocks.3.stack.5.weight" in sd or "decoder.blocks.2.blocks.3.stack.5.weight" in sd or "layers.4.layers.1.attn_block.attn.qkv.weight" in sd or "encoder.layers.4.layers.1.attn_block.attn.qkv.weight" in sd: #genmo mochi vae
+ # if "blocks.2.blocks.3.stack.5.weight" in sd:
+ # sd = comfy.utils.state_dict_prefix_replace(sd, {"": "decoder."})
+ # if "layers.4.layers.1.attn_block.attn.qkv.weight" in sd:
+ # sd = comfy.utils.state_dict_prefix_replace(sd, {"": "encoder."})
+ # self.first_stage_model = comfy.ldm.genmo.vae.model.VideoVAE()
+ # self.latent_channels = 12
+ # self.latent_dim = 3
+ # self.memory_used_decode = lambda shape, dtype: (1000 * shape[2] * shape[3] * shape[4] * (6 * 8 * 8)) * model_management.dtype_size(dtype)
+ # self.memory_used_encode = lambda shape, dtype: (1.5 * max(shape[2], 7) * shape[3] * shape[4] * (6 * 8 * 8)) * model_management.dtype_size(dtype)
+ # self.upscale_ratio = (lambda a: max(0, a * 6 - 5), 8, 8)
+ # self.upscale_index_formula = (6, 8, 8)
+ # self.downscale_ratio = (lambda a: max(0, math.floor((a + 5) / 6)), 8, 8)
+ # self.downscale_index_formula = (6, 8, 8)
+ # self.working_dtypes = [torch.float16, torch.float32]
+ # elif "decoder.up_blocks.0.res_blocks.0.conv1.conv.weight" in sd: #lightricks ltxv
+ # tensor_conv1 = sd["decoder.up_blocks.0.res_blocks.0.conv1.conv.weight"]
+ # version = 0
+ # if tensor_conv1.shape[0] == 512:
+ # version = 0
+ # elif tensor_conv1.shape[0] == 1024:
+ # version = 1
+ # if "encoder.down_blocks.1.conv.conv.bias" in sd:
+ # version = 2
+ # vae_config = None
+ # if metadata is not None and "config" in metadata:
+ # vae_config = json.loads(metadata["config"]).get("vae", None)
+ # self.first_stage_model = comfy.ldm.lightricks.vae.causal_video_autoencoder.VideoVAE(version=version, config=vae_config)
+ # self.latent_channels = 128
+ # self.latent_dim = 3
+ # self.memory_used_decode = lambda shape, dtype: (900 * shape[2] * shape[3] * shape[4] * (8 * 8 * 8)) * model_management.dtype_size(dtype)
+ # self.memory_used_encode = lambda shape, dtype: (70 * max(shape[2], 7) * shape[3] * shape[4]) * model_management.dtype_size(dtype)
+ # self.upscale_ratio = (lambda a: max(0, a * 8 - 7), 32, 32)
+ # self.upscale_index_formula = (8, 32, 32)
+ # self.downscale_ratio = (lambda a: max(0, math.floor((a + 7) / 8)), 32, 32)
+ # self.downscale_index_formula = (8, 32, 32)
+ # self.working_dtypes = [torch.bfloat16, torch.float32]
+ # elif "decoder.conv_in.conv.weight" in sd and sd['decoder.conv_in.conv.weight'].shape[1] == 32:
+ # ddconfig = {"block_out_channels": [128, 256, 512, 1024, 1024], "in_channels": 3, "out_channels": 3, "num_res_blocks": 2, "ffactor_spatial": 16, "ffactor_temporal": 4, "downsample_match_channel": True, "upsample_match_channel": True}
+ # ddconfig['z_channels'] = sd["decoder.conv_in.conv.weight"].shape[1]
+ # self.latent_channels = 64
+ # self.upscale_ratio = (lambda a: max(0, a * 4 - 3), 16, 16)
+ # self.upscale_index_formula = (4, 16, 16)
+ # self.downscale_ratio = (lambda a: max(0, math.floor((a + 3) / 4)), 16, 16)
+ # self.downscale_index_formula = (4, 16, 16)
+ # self.latent_dim = 3
+ # self.not_video = True
+ # self.working_dtypes = [torch.float16, torch.bfloat16, torch.float32]
+ # self.first_stage_model = AutoencodingEngine(regularizer_config={'target': "comfy.ldm.models.autoencoder.EmptyRegularizer"},
+ # encoder_config={'target': "comfy.ldm.hunyuan_video.vae_refiner.Encoder", 'params': ddconfig},
+ # decoder_config={'target': "comfy.ldm.hunyuan_video.vae_refiner.Decoder", 'params': ddconfig})
+
+ # self.memory_used_encode = lambda shape, dtype: (1400 * shape[-2] * shape[-1]) * model_management.dtype_size(dtype)
+ # self.memory_used_decode = lambda shape, dtype: (1400 * shape[-3] * shape[-2] * shape[-1] * 16 * 16) * model_management.dtype_size(dtype)
+ elif "decoder.conv_in.conv.weight" in sd:
+ ddconfig = {'double_z': True, 'z_channels': 4, 'resolution': 256, 'in_channels': 3, 'out_ch': 3, 'ch': 128, 'ch_mult': [1, 2, 4, 4], 'num_res_blocks': 2, 'attn_resolutions': [], 'dropout': 0.0}
+ ddconfig["conv3d"] = True
+ ddconfig["time_compress"] = 4
+ self.upscale_ratio = (lambda a: max(0, a * 4 - 3), 8, 8)
+ self.upscale_index_formula = (4, 8, 8)
+ self.downscale_ratio = (lambda a: max(0, math.floor((a + 3) / 4)), 8, 8)
+ self.downscale_index_formula = (4, 8, 8)
+ self.latent_dim = 3
+ self.latent_channels = ddconfig['z_channels'] = sd["decoder.conv_in.conv.weight"].shape[1]
+ self.first_stage_model = AutoencoderKL(ddconfig=ddconfig, embed_dim=sd['post_quant_conv.weight'].shape[1])
+ self.memory_used_decode = lambda shape, dtype: (1500 * shape[2] * shape[3] * shape[4] * (4 * 8 * 8)) * model_management.dtype_size(dtype)
+ self.memory_used_encode = lambda shape, dtype: (900 * max(shape[2], 2) * shape[3] * shape[4]) * model_management.dtype_size(dtype)
+ self.working_dtypes = [torch.bfloat16, torch.float16, torch.float32]
+ # elif "decoder.unpatcher3d.wavelets" in sd:
+ # self.upscale_ratio = (lambda a: max(0, a * 8 - 7), 8, 8)
+ # self.upscale_index_formula = (8, 8, 8)
+ # self.downscale_ratio = (lambda a: max(0, math.floor((a + 7) / 8)), 8, 8)
+ # self.downscale_index_formula = (8, 8, 8)
+ # self.latent_dim = 3
+ # self.latent_channels = 16
+ # ddconfig = {'z_channels': 16, 'latent_channels': self.latent_channels, 'z_factor': 1, 'resolution': 1024, 'in_channels': 3, 'out_channels': 3, 'channels': 128, 'channels_mult': [2, 4, 4], 'num_res_blocks': 2, 'attn_resolutions': [32], 'dropout': 0.0, 'patch_size': 4, 'num_groups': 1, 'temporal_compression': 8, 'spacial_compression': 8}
+ # self.first_stage_model = comfy.ldm.cosmos.vae.CausalContinuousVideoTokenizer(**ddconfig)
+ # TODO: these values are a bit off because this is not a standard VAE
+ # self.memory_used_decode = lambda shape, dtype: (50 * shape[2] * shape[3] * shape[4] * (8 * 8 * 8)) * model_management.dtype_size(dtype)
+ # self.memory_used_encode = lambda shape, dtype: (50 * (round((shape[2] + 7) / 8) * 8) * shape[3] * shape[4]) * model_management.dtype_size(dtype)
+ # self.working_dtypes = [torch.bfloat16, torch.float32]
+ elif "decoder.middle.0.residual.0.gamma" in sd:
+ if "decoder.upsamples.0.upsamples.0.residual.2.weight" in sd: # Wan 2.2 VAE
+ self.upscale_ratio = (lambda a: max(0, a * 4 - 3), 16, 16)
+ self.upscale_index_formula = (4, 16, 16)
+ self.downscale_ratio = (lambda a: max(0, math.floor((a + 3) / 4)), 16, 16)
+ self.downscale_index_formula = (4, 16, 16)
+ self.latent_dim = 3
+ self.latent_channels = 48
+ ddconfig = {"dim": 160, "z_dim": self.latent_channels, "dim_mult": [1, 2, 4, 4], "num_res_blocks": 2, "attn_scales": [], "temperal_downsample": [False, True, True], "dropout": 0.0}
+ self.first_stage_model = comfy.ldm.wan.vae2_2.WanVAE(**ddconfig)
+ self.working_dtypes = [torch.bfloat16, torch.float16, torch.float32]
+ self.memory_used_encode = lambda shape, dtype: 3300 * shape[3] * shape[4] * model_management.dtype_size(dtype)
+ self.memory_used_decode = lambda shape, dtype: 8000 * shape[3] * shape[4] * (16 * 16) * model_management.dtype_size(dtype)
+ else: # Wan 2.1 VAE
+ self.upscale_ratio = (lambda a: max(0, a * 4 - 3), 8, 8)
+ self.upscale_index_formula = (4, 8, 8)
+ self.downscale_ratio = (lambda a: max(0, math.floor((a + 3) / 4)), 8, 8)
+ self.downscale_index_formula = (4, 8, 8)
+ self.input_channels = sd["encoder.conv1.weight"].shape[1]
+ # self.output_channels = sd["decoder.head.2.weight"].shape[0]
+ self.output_channels = self.input_channels
+ self.real_output_channels = sd["decoder.head.2.weight"].shape[0]
+ self.latent_dim = 3
+ self.latent_channels = 16
+ self.pad_channel_value = 1.0
+
+ ddconfig = {
+ "in_channels": self.input_channels,
+ # "out_channels": self.output_channels,
+ "out_channels": self.real_output_channels,
+ "dim": 96,
+ "z_dim": self.latent_channels,
+ "dim_mult": [1, 2, 4, 4],
+ "num_res_blocks": 2,
+ "attn_scales": [],
+ "temperal_downsample": [False, True, True],
+ "dropout": 0.0,
+ }
+ self.first_stage_model = WanVAE(**ddconfig)
+ self.working_dtypes = [torch.bfloat16, torch.float16, torch.float32]
+ self.memory_used_encode = lambda shape, dtype: 6000 * shape[3] * shape[4] * model_management.dtype_size(dtype)
+ self.memory_used_decode = lambda shape, dtype: 7000 * shape[3] * shape[4] * (8 * 8) * model_management.dtype_size(dtype)
+ # Hunyuan 3d v2 2.0 & 2.1
+ # elif "geo_decoder.cross_attn_decoder.ln_1.bias" in sd:
+ # self.latent_dim = 1
+
+ # def estimate_memory(shape, dtype, num_layers = 16, kv_cache_multiplier = 2):
+ # batch, num_tokens, hidden_dim = shape
+ # dtype_size = model_management.dtype_size(dtype)
+
+ # total_mem = batch * num_tokens * hidden_dim * dtype_size * (1 + kv_cache_multiplier * num_layers)
+ # return total_mem
+
+ # better memory estimations
+ # self.memory_used_encode = lambda shape, dtype, num_layers = 8, kv_cache_multiplier = 0:\
+ # estimate_memory(shape, dtype, num_layers, kv_cache_multiplier)
+
+ # self.memory_used_decode = lambda shape, dtype, num_layers = 16, kv_cache_multiplier = 2: \
+ # estimate_memory(shape, dtype, num_layers, kv_cache_multiplier)
+
+ # self.first_stage_model = comfy.ldm.hunyuan3d.vae.ShapeVAE()
+ # self.working_dtypes = [torch.float16, torch.bfloat16, torch.float32]
+ # elif "vocoder.backbone.channel_layers.0.0.bias" in sd: #Ace Step Audio
+ # self.first_stage_model = comfy.ldm.ace.vae.music_dcae_pipeline.MusicDCAE(source_sample_rate=44100)
+ # self.memory_used_encode = lambda shape, dtype: (shape[2] * 330) * model_management.dtype_size(dtype)
+ # self.memory_used_decode = lambda shape, dtype: (shape[2] * shape[3] * 87000) * model_management.dtype_size(dtype)
+ # self.latent_channels = 8
+ # self.output_channels = 2
+ # self.upscale_ratio = 4096
+ # self.downscale_ratio = 4096
+ # self.latent_dim = 2
+ # self.process_output = lambda audio: audio
+ # self.process_input = lambda audio: audio
+ # self.working_dtypes = [torch.bfloat16, torch.float16, torch.float32]
+ # self.disable_offload = True
+ # self.extra_1d_channel = 16
+ # elif "pixel_space_vae" in sd:
+ # self.first_stage_model = comfy.pixel_space_convert.PixelspaceConversionVAE()
+ # self.memory_used_encode = lambda shape, dtype: (1 * shape[2] * shape[3]) * model_management.dtype_size(dtype)
+ # self.memory_used_decode = lambda shape, dtype: (1 * shape[2] * shape[3]) * model_management.dtype_size(dtype)
+ # self.downscale_ratio = 1
+ # self.upscale_ratio = 1
+ # self.latent_channels = 3
+ # self.latent_dim = 2
+ # self.output_channels = 3
+ # elif "vocoder.activation_post.downsample.lowpass.filter" in sd: #MMAudio VAE
+ # sample_rate = 16000
+ # if sample_rate == 16000:
+ # mode = '16k'
+ # else:
+ # mode = '44k'
+
+ # self.first_stage_model = comfy.ldm.mmaudio.vae.autoencoder.AudioAutoencoder(mode=mode)
+ # self.memory_used_encode = lambda shape, dtype: (30 * shape[2]) * model_management.dtype_size(dtype)
+ # self.memory_used_decode = lambda shape, dtype: (90 * shape[2] * 1411.2) * model_management.dtype_size(dtype)
+ # self.latent_channels = 20
+ # self.output_channels = 2
+ # self.upscale_ratio = 512 * (44100 / sample_rate)
+ # self.downscale_ratio = 512 * (44100 / sample_rate)
+ # self.latent_dim = 1
+ # self.process_output = lambda audio: audio
+ # self.process_input = lambda audio: audio
+ # self.working_dtypes = [torch.float32]
+ # self.crop_input = False
+ else:
+ logging.warning("WARNING: No VAE weights detected, VAE not initalized.")
+ self.first_stage_model = None
+ return
+ else:
+ self.first_stage_model = AutoencoderKL(**(config['params']))
+ self.first_stage_model = self.first_stage_model.eval()
+
+ m, u = self.first_stage_model.load_state_dict(sd, strict=False)
+ if len(m) > 0:
+ logging.warning("Missing VAE keys {}".format(m))
+
+ if len(u) > 0:
+ logging.debug("Leftover VAE keys {}".format(u))
+
+ if device is None:
+ device = model_management.vae_device()
+ self.device = device
+ offload_device = model_management.vae_offload_device()
+ if dtype is None:
+ dtype = model_management.vae_dtype(self.device, self.working_dtypes)
+ self.vae_dtype = dtype
+ self.first_stage_model.to(self.vae_dtype)
+ self.output_device = model_management.intermediate_device()
+
+ self.patcher = comfy.model_patcher.ModelPatcher(self.first_stage_model, load_device=self.device, offload_device=offload_device)
+ logging.info("VAE load device: {}, offload device: {}, dtype: {}".format(self.device, offload_device, self.vae_dtype))
+
+ def decode(self, samples_in):
+ """
+ Override VAE.decode() to fix a regression introduced in ComfyUI PRs #11405 / #11406
+ (merged Dec 18 2025). Those PRs changed the 3D untiled decode path inside
+ VAE.decode() so that it no longer routes through decode_tiled_3d for subclasses;
+ it now does inline channel allocation and trimming that breaks CustomVAE because it
+ only sees self.output_channels (= input_channels = 3) and ignores
+ self.real_output_channels (the actual decoder head output count, e.g. 12 for the
+ Wan 2x upscale VAE). process_output was also no longer guaranteed to be applied
+ through that path.
+
+ For 2D VAEs (latent_dim != 3) we delegate to the parent as before.
+ For 3D VAEs (WanVAE family: Wan 2.1, Wan 2.2, Qwen-Image, Wan 2x upscale) we do
+ the model-loading bookkeeping ourselves, then call our own decode_tiled_3d which
+ already handles real_output_channels and process_output correctly.
+ """
+ if self.latent_dim != 3:
+ return super().decode(samples_in)
+
+ # Mirror the memory-management preamble from the parent's decode().
+ memory_used = self.memory_used_decode(samples_in.shape, self.vae_dtype)
+ model_management.load_models_gpu([self.patcher], memory_required=memory_used)
+
+ # decode_tiled_3d returns process_output(tiled_scale_multidim(...)) whose shape is
+ # [B, real_output_channels, T_out, H_out, W_out] (5-D for multi-frame video)
+ # or [B, real_output_channels, H_out, W_out] (4-D if tiled_scale_multidim
+ # squeezed the temporal dim)
+ images = self.decode_tiled_3d(samples_in)
+
+ # Normalise to [B*T, H, W, C] — same layout that the parent returns and that
+ # VAEUtils_VAEDecodeTiled.decode() expects (it has its own 5-D reshape guard too).
+ if images.ndim == 5:
+ B, C, T, H, W = images.shape
+ images = images.permute(0, 2, 3, 4, 1).reshape(B * T, H, W, C)
+ elif images.ndim == 4:
+ # Already [B, C, H, W] — just move channels to last dim.
+ images = images.movedim(1, -1)
+ # ndim == 3 or anything unexpected: leave as-is and let downstream handle it.
+
+ return images
+
+ def decode_tiled_3d(self, samples, tile_t=999, tile_x=32, tile_y=32, overlap=(1, 8, 8)):
+ decode_fn = lambda a: self.first_stage_model.decode(a.to(self.vae_dtype).to(self.device)).float()
+ return self.process_output(
+ comfy.utils.tiled_scale_multidim(
+ samples,
+ decode_fn,
+ tile=(tile_t, tile_x, tile_y),
+ overlap=overlap,
+ upscale_amount=self.upscale_ratio,
+ out_channels=self.real_output_channels,
+ index_formulas=self.upscale_index_formula,
+ output_device=self.output_device,
+ )
+ )
diff --git a/bundled_packs/ComfyUI-VAE-Utils/src/wan/vae.py b/bundled_packs/ComfyUI-VAE-Utils/src/wan/vae.py
new file mode 100644
index 0000000..f01fa87
--- /dev/null
+++ b/bundled_packs/ComfyUI-VAE-Utils/src/wan/vae.py
@@ -0,0 +1,521 @@
+# original version: https://github.com/Wan-Video/Wan2.1/blob/main/wan/modules/vae.py
+# Copyright 2024-2025 The Alibaba Wan Team Authors. All rights reserved.
+
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+from einops import rearrange
+from comfy.ldm.modules.diffusionmodules.model import vae_attention
+
+import comfy.ops
+ops = comfy.ops.disable_weight_init
+
+CACHE_T = 2
+
+
+class CausalConv3d(ops.Conv3d):
+ """
+ Causal 3d convolusion.
+ """
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self._padding = (self.padding[2], self.padding[2], self.padding[1],
+ self.padding[1], 2 * self.padding[0], 0)
+ self.padding = (0, 0, 0)
+
+ def forward(self, x, cache_x=None, cache_list=None, cache_idx=None):
+ if cache_list is not None:
+ cache_x = cache_list[cache_idx]
+ cache_list[cache_idx] = None
+
+ padding = list(self._padding)
+ if cache_x is not None and self._padding[4] > 0:
+ cache_x = cache_x.to(x.device)
+ x = torch.cat([cache_x, x], dim=2)
+ padding[4] -= cache_x.shape[2]
+ del cache_x
+ x = F.pad(x, padding)
+
+ return super().forward(x)
+
+
+class RMS_norm(nn.Module):
+
+ def __init__(self, dim, channel_first=True, images=True, bias=False):
+ super().__init__()
+ broadcastable_dims = (1, 1, 1) if not images else (1, 1)
+ shape = (dim, *broadcastable_dims) if channel_first else (dim,)
+
+ self.channel_first = channel_first
+ self.scale = dim**0.5
+ self.gamma = nn.Parameter(torch.ones(shape))
+ self.bias = nn.Parameter(torch.zeros(shape)) if bias else None
+
+ def forward(self, x):
+ return F.normalize(
+ x, dim=(1 if self.channel_first else -1)) * self.scale * self.gamma.to(x) + (self.bias.to(x) if self.bias is not None else 0)
+
+
+class Resample(nn.Module):
+
+ def __init__(self, dim, mode):
+ assert mode in ('none', 'upsample2d', 'upsample3d', 'downsample2d',
+ 'downsample3d')
+ super().__init__()
+ self.dim = dim
+ self.mode = mode
+
+ # layers
+ if mode == 'upsample2d':
+ self.resample = nn.Sequential(
+ nn.Upsample(scale_factor=(2., 2.), mode='nearest-exact'),
+ ops.Conv2d(dim, dim // 2, 3, padding=1))
+ elif mode == 'upsample3d':
+ self.resample = nn.Sequential(
+ nn.Upsample(scale_factor=(2., 2.), mode='nearest-exact'),
+ ops.Conv2d(dim, dim // 2, 3, padding=1))
+ self.time_conv = CausalConv3d(
+ dim, dim * 2, (3, 1, 1), padding=(1, 0, 0))
+
+ elif mode == 'downsample2d':
+ self.resample = nn.Sequential(
+ nn.ZeroPad2d((0, 1, 0, 1)),
+ ops.Conv2d(dim, dim, 3, stride=(2, 2)))
+ elif mode == 'downsample3d':
+ self.resample = nn.Sequential(
+ nn.ZeroPad2d((0, 1, 0, 1)),
+ ops.Conv2d(dim, dim, 3, stride=(2, 2)))
+ self.time_conv = CausalConv3d(
+ dim, dim, (3, 1, 1), stride=(2, 1, 1), padding=(0, 0, 0))
+
+ else:
+ self.resample = nn.Identity()
+
+ def forward(self, x, feat_cache=None, feat_idx=[0]):
+ b, c, t, h, w = x.size()
+ if self.mode == 'upsample3d':
+ if feat_cache is not None:
+ idx = feat_idx[0]
+ if feat_cache[idx] is None:
+ feat_cache[idx] = 'Rep'
+ feat_idx[0] += 1
+ else:
+
+ cache_x = x[:, :, -CACHE_T:, :, :].clone()
+ if cache_x.shape[2] < 2 and feat_cache[
+ idx] is not None and feat_cache[idx] != 'Rep':
+ # cache last frame of last two chunk
+ cache_x = torch.cat([
+ feat_cache[idx][:, :, -1, :, :].unsqueeze(2).to(
+ cache_x.device), cache_x
+ ],
+ dim=2)
+ if cache_x.shape[2] < 2 and feat_cache[
+ idx] is not None and feat_cache[idx] == 'Rep':
+ cache_x = torch.cat([
+ torch.zeros_like(cache_x).to(cache_x.device),
+ cache_x
+ ],
+ dim=2)
+ if feat_cache[idx] == 'Rep':
+ x = self.time_conv(x)
+ else:
+ x = self.time_conv(x, feat_cache[idx])
+ feat_cache[idx] = cache_x
+ feat_idx[0] += 1
+
+ x = x.reshape(b, 2, c, t, h, w)
+ x = torch.stack((x[:, 0, :, :, :, :], x[:, 1, :, :, :, :]),
+ 3)
+ x = x.reshape(b, c, t * 2, h, w)
+ t = x.shape[2]
+ x = rearrange(x, 'b c t h w -> (b t) c h w')
+ x = self.resample(x)
+ x = rearrange(x, '(b t) c h w -> b c t h w', t=t)
+
+ if self.mode == 'downsample3d':
+ if feat_cache is not None:
+ idx = feat_idx[0]
+ if feat_cache[idx] is None:
+ feat_cache[idx] = x.clone()
+ feat_idx[0] += 1
+ else:
+
+ cache_x = x[:, :, -1:, :, :].clone()
+ # if cache_x.shape[2] < 2 and feat_cache[idx] is not None and feat_cache[idx]!='Rep':
+ # # cache last frame of last two chunk
+ # cache_x = torch.cat([feat_cache[idx][:, :, -1, :, :].unsqueeze(2).to(cache_x.device), cache_x], dim=2)
+
+ x = self.time_conv(
+ torch.cat([feat_cache[idx][:, :, -1:, :, :], x], 2))
+ feat_cache[idx] = cache_x
+ feat_idx[0] += 1
+ return x
+
+
+class ResidualBlock(nn.Module):
+
+ def __init__(self, in_dim, out_dim, dropout=0.0):
+ super().__init__()
+ self.in_dim = in_dim
+ self.out_dim = out_dim
+
+ # layers
+ self.residual = nn.Sequential(
+ RMS_norm(in_dim, images=False), nn.SiLU(),
+ CausalConv3d(in_dim, out_dim, 3, padding=1),
+ RMS_norm(out_dim, images=False), nn.SiLU(), nn.Dropout(dropout),
+ CausalConv3d(out_dim, out_dim, 3, padding=1))
+ self.shortcut = CausalConv3d(in_dim, out_dim, 1) \
+ if in_dim != out_dim else nn.Identity()
+
+ def forward(self, x, feat_cache=None, feat_idx=[0]):
+ old_x = x
+ for layer in self.residual:
+ if isinstance(layer, CausalConv3d) and feat_cache is not None:
+ idx = feat_idx[0]
+ cache_x = x[:, :, -CACHE_T:, :, :].clone()
+ if cache_x.shape[2] < 2 and feat_cache[idx] is not None:
+ # cache last frame of last two chunk
+ cache_x = torch.cat([
+ feat_cache[idx][:, :, -1, :, :].unsqueeze(2).to(
+ cache_x.device), cache_x
+ ],
+ dim=2)
+ x = layer(x, cache_list=feat_cache, cache_idx=idx)
+ feat_cache[idx] = cache_x
+ feat_idx[0] += 1
+ else:
+ x = layer(x)
+ return x + self.shortcut(old_x)
+
+
+class AttentionBlock(nn.Module):
+ """
+ Causal self-attention with a single head.
+ """
+
+ def __init__(self, dim):
+ super().__init__()
+ self.dim = dim
+
+ # layers
+ self.norm = RMS_norm(dim)
+ self.to_qkv = ops.Conv2d(dim, dim * 3, 1)
+ self.proj = ops.Conv2d(dim, dim, 1)
+ self.optimized_attention = vae_attention()
+
+ def forward(self, x):
+ identity = x
+ b, c, t, h, w = x.size()
+ x = rearrange(x, 'b c t h w -> (b t) c h w')
+ x = self.norm(x)
+ # compute query, key, value
+
+ q, k, v = self.to_qkv(x).chunk(3, dim=1)
+ x = self.optimized_attention(q, k, v)
+
+ # output
+ x = self.proj(x)
+ x = rearrange(x, '(b t) c h w-> b c t h w', t=t)
+ return x + identity
+
+
+class Encoder3d(nn.Module):
+
+ def __init__(self,
+ in_channels=3,
+ dim=128,
+ z_dim=4,
+ dim_mult=[1, 2, 4, 4],
+ num_res_blocks=2,
+ attn_scales=[],
+ temperal_downsample=[True, True, False],
+ dropout=0.0):
+ super().__init__()
+ self.in_channels = in_channels
+ self.dim = dim
+ self.z_dim = z_dim
+ self.dim_mult = dim_mult
+ self.num_res_blocks = num_res_blocks
+ self.attn_scales = attn_scales
+ self.temperal_downsample = temperal_downsample
+
+ # dimensions
+ dims = [dim * u for u in [1] + dim_mult]
+ scale = 1.0
+
+ # init block
+ self.conv1 = CausalConv3d(in_channels, dims[0], 3, padding=1)
+
+ # downsample blocks
+ downsamples = []
+ for i, (in_dim, out_dim) in enumerate(zip(dims[:-1], dims[1:])):
+ # residual (+attention) blocks
+ for _ in range(num_res_blocks):
+ downsamples.append(ResidualBlock(in_dim, out_dim, dropout))
+ if scale in attn_scales:
+ downsamples.append(AttentionBlock(out_dim))
+ in_dim = out_dim
+
+ # downsample block
+ if i != len(dim_mult) - 1:
+ mode = 'downsample3d' if temperal_downsample[
+ i] else 'downsample2d'
+ downsamples.append(Resample(out_dim, mode=mode))
+ scale /= 2.0
+ self.downsamples = nn.Sequential(*downsamples)
+
+ # middle blocks
+ self.middle = nn.Sequential(
+ ResidualBlock(out_dim, out_dim, dropout), AttentionBlock(out_dim),
+ ResidualBlock(out_dim, out_dim, dropout))
+
+ # output blocks
+ self.head = nn.Sequential(
+ RMS_norm(out_dim, images=False), nn.SiLU(),
+ CausalConv3d(out_dim, z_dim, 3, padding=1))
+
+ def forward(self, x, feat_cache=None, feat_idx=[0]):
+ if feat_cache is not None:
+ idx = feat_idx[0]
+ cache_x = x[:, :, -CACHE_T:, :, :].clone()
+ if cache_x.shape[2] < 2 and feat_cache[idx] is not None:
+ # cache last frame of last two chunk
+ cache_x = torch.cat([
+ feat_cache[idx][:, :, -1, :, :].unsqueeze(2).to(
+ cache_x.device), cache_x
+ ],
+ dim=2)
+ x = self.conv1(x, feat_cache[idx])
+ feat_cache[idx] = cache_x
+ feat_idx[0] += 1
+ else:
+ x = self.conv1(x)
+
+ ## downsamples
+ for layer in self.downsamples:
+ if feat_cache is not None:
+ x = layer(x, feat_cache, feat_idx)
+ else:
+ x = layer(x)
+
+ ## middle
+ for layer in self.middle:
+ if isinstance(layer, ResidualBlock) and feat_cache is not None:
+ x = layer(x, feat_cache, feat_idx)
+ else:
+ x = layer(x)
+
+ ## head
+ for layer in self.head:
+ if isinstance(layer, CausalConv3d) and feat_cache is not None:
+ idx = feat_idx[0]
+ cache_x = x[:, :, -CACHE_T:, :, :].clone()
+ if cache_x.shape[2] < 2 and feat_cache[idx] is not None:
+ # cache last frame of last two chunk
+ cache_x = torch.cat([
+ feat_cache[idx][:, :, -1, :, :].unsqueeze(2).to(
+ cache_x.device), cache_x
+ ],
+ dim=2)
+ x = layer(x, feat_cache[idx])
+ feat_cache[idx] = cache_x
+ feat_idx[0] += 1
+ else:
+ x = layer(x)
+ return x
+
+
+class Decoder3d(nn.Module):
+
+ def __init__(self,
+ out_channels=3,
+ dim=128,
+ z_dim=4,
+ dim_mult=[1, 2, 4, 4],
+ num_res_blocks=2,
+ attn_scales=[],
+ temperal_upsample=[False, True, True],
+ dropout=0.0):
+ super().__init__()
+ self.out_channels = out_channels
+ self.dim = dim
+ self.z_dim = z_dim
+ self.dim_mult = dim_mult
+ self.num_res_blocks = num_res_blocks
+ self.attn_scales = attn_scales
+ self.temperal_upsample = temperal_upsample
+
+ # dimensions
+ dims = [dim * u for u in [dim_mult[-1]] + dim_mult[::-1]]
+ scale = 1.0 / 2**(len(dim_mult) - 2)
+
+ # init block
+ self.conv1 = CausalConv3d(z_dim, dims[0], 3, padding=1)
+
+ # middle blocks
+ self.middle = nn.Sequential(
+ ResidualBlock(dims[0], dims[0], dropout), AttentionBlock(dims[0]),
+ ResidualBlock(dims[0], dims[0], dropout))
+
+ # upsample blocks
+ upsamples = []
+ for i, (in_dim, out_dim) in enumerate(zip(dims[:-1], dims[1:])):
+ # residual (+attention) blocks
+ if i == 1 or i == 2 or i == 3:
+ in_dim = in_dim // 2
+ for _ in range(num_res_blocks + 1):
+ upsamples.append(ResidualBlock(in_dim, out_dim, dropout))
+ if scale in attn_scales:
+ upsamples.append(AttentionBlock(out_dim))
+ in_dim = out_dim
+
+ # upsample block
+ if i != len(dim_mult) - 1:
+ mode = 'upsample3d' if temperal_upsample[i] else 'upsample2d'
+ upsamples.append(Resample(out_dim, mode=mode))
+ scale *= 2.0
+ self.upsamples = nn.Sequential(*upsamples)
+
+ # output blocks
+ self.head = nn.Sequential(
+ RMS_norm(out_dim, images=False), nn.SiLU(),
+ CausalConv3d(out_dim, out_channels, 3, padding=1))
+
+ def forward(self, x, feat_cache=None, feat_idx=[0]):
+ ## conv1
+ if feat_cache is not None:
+ idx = feat_idx[0]
+ cache_x = x[:, :, -CACHE_T:, :, :].clone()
+ if cache_x.shape[2] < 2 and feat_cache[idx] is not None:
+ # cache last frame of last two chunk
+ cache_x = torch.cat([
+ feat_cache[idx][:, :, -1, :, :].unsqueeze(2).to(
+ cache_x.device), cache_x
+ ],
+ dim=2)
+ x = self.conv1(x, feat_cache[idx])
+ feat_cache[idx] = cache_x
+ feat_idx[0] += 1
+ else:
+ x = self.conv1(x)
+
+ ## middle
+ for layer in self.middle:
+ if isinstance(layer, ResidualBlock) and feat_cache is not None:
+ x = layer(x, feat_cache, feat_idx)
+ else:
+ x = layer(x)
+
+ ## upsamples
+ for layer in self.upsamples:
+ if feat_cache is not None:
+ x = layer(x, feat_cache, feat_idx)
+ else:
+ x = layer(x)
+
+ ## head
+ for layer in self.head:
+ if isinstance(layer, CausalConv3d) and feat_cache is not None:
+ idx = feat_idx[0]
+ cache_x = x[:, :, -CACHE_T:, :, :].clone()
+ if cache_x.shape[2] < 2 and feat_cache[idx] is not None:
+ # cache last frame of last two chunk
+ cache_x = torch.cat([
+ feat_cache[idx][:, :, -1, :, :].unsqueeze(2).to(
+ cache_x.device), cache_x
+ ],
+ dim=2)
+ x = layer(x, feat_cache[idx])
+ feat_cache[idx] = cache_x
+ feat_idx[0] += 1
+ else:
+ x = layer(x)
+ return x
+
+
+def count_conv3d(model):
+ count = 0
+ for m in model.modules():
+ if isinstance(m, CausalConv3d):
+ count += 1
+ return count
+
+
+class WanVAE(nn.Module):
+
+ def __init__(self,
+ in_channels=3,
+ out_channels=3,
+ dim=128,
+ z_dim=4,
+ dim_mult=[1, 2, 4, 4],
+ num_res_blocks=2,
+ attn_scales=[],
+ temperal_downsample=[True, True, False],
+ dropout=0.0):
+ super().__init__()
+ self.in_channels = in_channels
+ self.out_channels = out_channels
+ self.dim = dim
+ self.z_dim = z_dim
+ self.dim_mult = dim_mult
+ self.num_res_blocks = num_res_blocks
+ self.attn_scales = attn_scales
+ self.temperal_downsample = temperal_downsample
+ self.temperal_upsample = temperal_downsample[::-1]
+
+ # modules
+ self.encoder = Encoder3d(in_channels, dim, z_dim * 2, dim_mult, num_res_blocks,
+ attn_scales, self.temperal_downsample, dropout)
+ self.conv1 = CausalConv3d(z_dim * 2, z_dim * 2, 1)
+ self.conv2 = CausalConv3d(z_dim, z_dim, 1)
+ self.decoder = Decoder3d(out_channels, dim, z_dim, dim_mult, num_res_blocks,
+ attn_scales, self.temperal_upsample, dropout)
+
+ def encode(self, x):
+ conv_idx = [0]
+ feat_map = [None] * count_conv3d(self.decoder)
+ ## cache
+ t = x.shape[2]
+ iter_ = 1 + (t - 1) // 4
+ ## 对encode输入的x,按时间拆分为1、4、4、4....
+ for i in range(iter_):
+ conv_idx = [0]
+ if i == 0:
+ out = self.encoder(
+ x[:, :, :1, :, :],
+ feat_cache=feat_map,
+ feat_idx=conv_idx)
+ else:
+ out_ = self.encoder(
+ x[:, :, 1 + 4 * (i - 1):1 + 4 * i, :, :],
+ feat_cache=feat_map,
+ feat_idx=conv_idx)
+ out = torch.cat([out, out_], 2)
+ mu, log_var = self.conv1(out).chunk(2, dim=1)
+ return mu
+
+ def decode(self, z):
+ conv_idx = [0]
+ feat_map = [None] * count_conv3d(self.decoder)
+ # z: [b,c,t,h,w]
+
+ iter_ = z.shape[2]
+ x = self.conv2(z)
+ for i in range(iter_):
+ conv_idx = [0]
+ if i == 0:
+ out = self.decoder(
+ x[:, :, i:i + 1, :, :],
+ feat_cache=feat_map,
+ feat_idx=conv_idx)
+ else:
+ out_ = self.decoder(
+ x[:, :, i:i + 1, :, :],
+ feat_cache=feat_map,
+ feat_idx=conv_idx)
+ out = torch.cat([out, out_], 2)
+ return out
diff --git a/bundled_packs/_BUNDLED.txt b/bundled_packs/_BUNDLED.txt
index ffd3320..4c16cf0 100644
--- a/bundled_packs/_BUNDLED.txt
+++ b/bundled_packs/_BUNDLED.txt
@@ -22,6 +22,8 @@ Source provenance (owner/repo @ commit — license):
ComfyUI-SeedVR2_VideoUpscaler numz/ComfyUI-SeedVR2_VideoUpscaler @ 4490bd1f482e026674543386bb2a4d176da245b9 Apache-2.0
ComfyUI_IPAdapter_plus cubiq/ComfyUI_IPAdapter_plus @ a0f451a5 GPL-3.0
ComfyUI_UltimateSDUpscale ssitu/ComfyUI_UltimateSDUpscale @ d6b575a (patched) GPL-3.0
+ ComfyUI-ConditioningKrea2Rebalance nova452/ComfyUI-ConditioningKrea2Rebalance @ 9ab5315e6aa8 Apache-2.0
+ ComfyUI-VAE-Utils spacepxl/ComfyUI-VAE-Utils @ d69e7afaa9ed (assets/workflow imgs removed) MIT
UltimateSDUpscale local patches (in its __init__.py, both preserved on copy-out):
1. The bundled Auto1111 repositories/ submodule is shipped pre-filled, so the
diff --git a/core/install_sections.py b/core/install_sections.py
index 2a8e7a7..ea44169 100644
--- a/core/install_sections.py
+++ b/core/install_sections.py
@@ -57,6 +57,9 @@ SECTIONS: list[dict] = [
{"id": "face_detailer", "label": "Face Detailer", "size": "~6 MB",
"desc": "Region-correct face detailing",
"members": [_np("RegionalDetailer")]},
+ {"id": "krea2_highdetail", "label": "Krea 2 High Detail", "size": "~510 MB",
+ "desc": "Clean 2× decoder + conditioning rebalance for the Krea 2 High-Detail templates",
+ "members": [_np("Krea2HighDetail")]},
{"id": "controlnet", "label": "ControlNet", "size": "~5 GB SDXL · up to ~22 GB all",
"desc": "Depth / pose / canny / edge guidance (SDXL · Flux · Z-Image)",
"members": [_np("ControlNet"), _np("FluxControlNet"),
diff --git a/core/model_api.py b/core/model_api.py
index cf31a78..ec8a378 100644
--- a/core/model_api.py
+++ b/core/model_api.py
@@ -98,6 +98,16 @@ async def _api_list_models(request):
and model_settings.is_primary_model_file(m["filename"]))
or not model_settings.is_catalog_filename(m["filename"])
]
+ # The fingerprint scanner assigns architecture from header patterns; newer
+ # DiT families (e.g. krea2) have no pattern yet and read as "unknown", which
+ # drops them from the upscale picker's engine list. Their curated config
+ # (matched by filename) carries the authoritative architecture — adopt it so
+ # the right re-detail engine is offered.
+ for m in filtered:
+ if m.get("architecture") in ("", "unknown", None):
+ config = model_settings.find_config_by_filename(m["filename"])
+ if config and config.get("architecture"):
+ m["architecture"] = config["architecture"]
return web.json_response({"models": filtered})
diff --git a/core/node_install_api.py b/core/node_install_api.py
index 5b3a503..c45f27d 100644
--- a/core/node_install_api.py
+++ b/core/node_install_api.py
@@ -147,6 +147,20 @@ NODE_PACKS: dict[str, dict] = {
"dest": "ultralytics/bbox/face_yolov8n.pt"},
],
},
+ "Krea2HighDetail": {
+ "label": "Krea 2 High Detail",
+ # The High-Detail krea2 templates (t2i + i2i) need two packs: nova452's
+ # ConditioningKrea2Rebalance (a cond amplifier) and spacepxl's VAE-Utils
+ # (its VAEUtils_VAEDecodeTiled + CustomVAELoader run the clean 2x decode).
+ # Neither has pip deps. VAE-Utils ships no model downloader, so we fetch
+ # the spacepxl decoder weight into models/vae for CustomVAELoader to pick.
+ "bundle": ["ComfyUI-ConditioningKrea2Rebalance", "ComfyUI-VAE-Utils"],
+ "proof_nodes": ["ConditioningKrea2Rebalance", "VAEUtils_VAEDecodeTiled"],
+ "models": [
+ {"url": "https://huggingface.co/spacepxl/Wan2.1-VAE-upscale2x/resolve/main/Wan2.1_VAE_upscale2x_imageonly_real_v1.safetensors",
+ "dest": "vae/Wan2.1_VAE_upscale2x_imageonly_real_v1.safetensors"},
+ ],
+ },
"StyleReference": {
"label": "Style Reference",
# cubiq's IPAdapter pack is BUNDLED (bundled_packs/ComfyUI_IPAdapter_plus),
diff --git a/data/models/krea2_raw.json b/data/models/krea2_raw.json
new file mode 100644
index 0000000..5315abf
--- /dev/null
+++ b/data/models/krea2_raw.json
@@ -0,0 +1,164 @@
+{
+ "display_name": "Krea 2 - RAW",
+ "model_name": "Krea 2 RAW",
+ "version": "RAW",
+ "architecture": "krea2",
+ "family": "krea2_raw",
+ "author": "Krea AI",
+ "description": "Krea 2 RAW — the undistilled 12B base checkpoint (full-step, real cfg). Krea ships it for fine-tuning/LoRA training, but because it is NOT step-distilled it re-details cleanly at a LOW denoise — which makes it the right model for a faithful, blotch-free TILED upscale (the distilled Turbo can't: low denoise blotches, high denoise seams). Same Qwen3-VL encoder + Qwen Image VAE as Turbo.",
+ "license": "Krea 2 Community License Agreement v.1 (open weights; commercial use requires an Enterprise License once total annual revenue reaches $1M)",
+ "tags": [
+ "krea",
+ "krea2",
+ "dit",
+ "transformer",
+ "photorealistic",
+ "raw",
+ "base",
+ "undistilled"
+ ],
+ "url": "https://huggingface.co/Comfy-Org/Krea-2",
+ "release_date": "2026-06-18",
+ "tag_sources": [],
+ "tag_format": "spaces",
+ "prompt_style": "natural",
+ "trigger": "",
+ "default_prompt_id": "krea2-default",
+ "negative": "",
+ "notes": "Undistilled base: full-step sampling with a REAL cfg. Render recipe (52 steps / cfg 3.5 / er_sde+simple) is DOCUMENTED — Krea's official CLI is `--checkpoint oss_raw --steps 52 --cfg 3.5`. Negatives use the real CFG branch but efficacy on the Qwen3-VL encoder is A/B-pending (may be inert like Qwen-Image). Shift is baked into the model (no ModelSamplingAuraFlow needed; mu~1.15 at 1024). Shares qwen3vl_4b + qwen_image_vae with Turbo. ~13 GB fp8 / ~26 GB bf16. Slow (no distillation) — for UPSCALE re-detail the JS engine uses fewer steps at low denoise, this 52-step recipe is for from-scratch t2i. RESOLUTION: RAW is DOCUMENTED 'up to 1024' — keep BOTH dims <=1024 (1024x1024 is its sweet spot; long edge >1024 like 1152/1216 melts faces — confirmed). Turbo is the 1k-2k model. For bigger output, render <=1024 then upscale (RAW tiles at 1024 = exactly its trained size, why the tiled upscale is so clean). SHIFT FIX (critical): ComfyUI hardcodes flow-shift mu=1.15 (Turbo's value) for the WHOLE krea2 class, but RAW needs RESOLUTION-DYNAMIC shifting (mu~0.906 @ 1024^2, smaller below) — the over-shift compresses the detail tail and melts faces. The raw t2i/i2i templates insert a ModelSamplingFlux node (base_shift 0.5, max_shift 0.90625, width/height = render size) which REPLACES the bad baked shift (verified against ComfyUI master: supported_models.py Krea2 shift=1.15, ModelType.FLUX). SHIP RECIPE (quality-research-tuned): 52 steps / cfg 5.0 / er_sde / beta — DOCUMENTED crispest-photoreal combo; euler/simple is doubly-soft (euler smooths micro-texture, simple under-weights the detail band). cfg 5.0 ~ Krea --cfg 3.5 in ComfyUI's (1+g) convention + diffusers' native 4.5. ModelSamplingFlux width/height MUST match render size or mu over-shifts on non-square buckets (1024^2->0.906, 896x1024->0.852, 832x1024->0.825, 768x1024->0.798). Turbo needs no shift node (its real mu IS 1.15). Without the ModelSamplingFlux node a RAW render melts.",
+ "files": [
+ {
+ "label": "Diffusion Model",
+ "folder": "diffusion_models",
+ "variants": [
+ {
+ "precision": "fp8",
+ "filename": "krea2_raw_fp8_scaled.safetensors",
+ "size_bytes": 13141730784,
+ "source": {
+ "provider": "huggingface",
+ "repo": "Comfy-Org/Krea-2",
+ "path": "diffusion_models/krea2_raw_fp8_scaled.safetensors"
+ },
+ "quick_hash": null,
+ "sha256": null
+ },
+ {
+ "precision": "bf16",
+ "filename": "krea2_raw_bf16.safetensors",
+ "size_bytes": 26283332608,
+ "source": {
+ "provider": "huggingface",
+ "repo": "Comfy-Org/Krea-2",
+ "path": "diffusion_models/krea2_raw_bf16.safetensors"
+ },
+ "quick_hash": null,
+ "sha256": null
+ }
+ ]
+ },
+ {
+ "label": "Text Encoder",
+ "folder": "text_encoders",
+ "variants": [
+ {
+ "precision": "fp8",
+ "filename": "qwen3vl_4b_fp8_scaled.safetensors",
+ "size_bytes": 5242467968,
+ "source": {
+ "provider": "huggingface",
+ "repo": "Comfy-Org/Krea-2",
+ "path": "text_encoders/qwen3vl_4b_fp8_scaled.safetensors"
+ },
+ "sha256": null
+ },
+ {
+ "precision": "bf16",
+ "filename": "qwen3vl_4b_bf16.safetensors",
+ "size_bytes": 8875719384,
+ "source": {
+ "provider": "huggingface",
+ "repo": "Comfy-Org/Krea-2",
+ "path": "text_encoders/qwen3vl_4b_bf16.safetensors"
+ },
+ "sha256": null
+ }
+ ]
+ },
+ {
+ "label": "VAE",
+ "folder": "vae",
+ "filename": "qwen_image_vae.safetensors",
+ "size_bytes": 253806246,
+ "source": {
+ "provider": "huggingface",
+ "repo": "Comfy-Org/Krea-2",
+ "path": "vae/qwen_image_vae.safetensors"
+ },
+ "sha256": null
+ }
+ ],
+ "nodes": {
+ "KSampler": {
+ "steps": 52,
+ "cfg": 5.0,
+ "sampler_name": "er_sde",
+ "scheduler": "beta",
+ "steps_range": [
+ 40,
+ 60
+ ],
+ "cfg_range": [
+ 3.5,
+ 6.0
+ ],
+ "sampler_name_options": [
+ "er_sde",
+ "dpmpp_2m",
+ "euler",
+ "dpmpp_sde",
+ "euler_ancestral"
+ ],
+ "scheduler_options": [
+ "beta",
+ "simple",
+ "sgm_uniform",
+ "normal"
+ ]
+ },
+ "EmptySD3LatentImage": {
+ "width": 1024,
+ "height": 1024,
+ "_resolutions": [
+ {
+ "width": 1024,
+ "height": 1024
+ },
+ {
+ "width": 832,
+ "height": 1024
+ },
+ {
+ "width": 1024,
+ "height": 832
+ },
+ {
+ "width": 768,
+ "height": 1024
+ },
+ {
+ "width": 1024,
+ "height": 768
+ },
+ {
+ "width": 896,
+ "height": 1024
+ },
+ {
+ "width": 1024,
+ "height": 896
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/data/models/krea2_turbo.json b/data/models/krea2_turbo.json
new file mode 100644
index 0000000..c3f35a5
--- /dev/null
+++ b/data/models/krea2_turbo.json
@@ -0,0 +1,192 @@
+{
+ "display_name": "Krea 2 - Turbo",
+ "model_name": "Krea 2 Turbo",
+ "version": "Turbo",
+ "architecture": "krea2",
+ "family": "krea2_turbo",
+ "author": "Krea AI",
+ "description": "Krea 2 Turbo — a distilled 12B dense Diffusion Transformer for fast, high-quality, aesthetic-first text-to-image at native 2K. Uses a Qwen3-VL text encoder and the Qwen Image VAE. 8-step, cfg 1.0. nvfp4 variant is the fastest on Blackwell (RTX 50-series) native FP4.",
+ "license": "Krea 2 Community License Agreement v.1 (open weights; commercial use requires an Enterprise License once total annual revenue reaches $1M)",
+ "tags": [
+ "krea",
+ "krea2",
+ "dit",
+ "transformer",
+ "photorealistic",
+ "aesthetic",
+ "turbo",
+ "fast"
+ ],
+ "url": "https://huggingface.co/Comfy-Org/Krea-2",
+ "release_date": "2026-06-18",
+ "tag_sources": [],
+ "tag_format": "spaces",
+ "prompt_style": "natural",
+ "trigger": "",
+ "default_prompt_id": "krea2-default",
+ "negative": "",
+ "notes": "8 steps, cfg 1.0, euler+simple (the official Krea recipe — default; er_sde+simple is available for extra grain on photoreal skin), denoise 1.0. Distilled turbo — keep cfg at 1.0 (no real negative). Native 2K (supports 1K-2K). Reuses the Qwen Image VAE (qwen_image_vae.safetensors). Requires a ComfyUI build with the 'krea2' CLIP type (Krea 2 release, June 2026 or newer). RAW-trained Krea 2 LoRAs express on Turbo.",
+ "files": [
+ {
+ "label": "Diffusion Model",
+ "folder": "diffusion_models",
+ "variants": [
+ {
+ "precision": "fp8",
+ "filename": "krea2_turbo_fp8_scaled.safetensors",
+ "size_bytes": 13141730784,
+ "source": {
+ "provider": "huggingface",
+ "repo": "Comfy-Org/Krea-2",
+ "path": "diffusion_models/krea2_turbo_fp8_scaled.safetensors"
+ },
+ "quick_hash": null,
+ "sha256": null
+ },
+ {
+ "precision": "bf16",
+ "filename": "krea2_turbo_bf16.safetensors",
+ "size_bytes": 26283332608,
+ "source": {
+ "provider": "huggingface",
+ "repo": "Comfy-Org/Krea-2",
+ "path": "diffusion_models/krea2_turbo_bf16.safetensors"
+ },
+ "quick_hash": null,
+ "sha256": null
+ },
+ {
+ "precision": "mxfp8",
+ "filename": "krea2_turbo_mxfp8.safetensors",
+ "size_bytes": 13532318080,
+ "source": {
+ "provider": "huggingface",
+ "repo": "Comfy-Org/Krea-2",
+ "path": "diffusion_models/krea2_turbo_mxfp8.safetensors"
+ },
+ "quick_hash": null,
+ "sha256": null
+ },
+ {
+ "precision": "nvfp4",
+ "filename": "krea2_turbo_nvfp4.safetensors",
+ "size_bytes": 7673668288,
+ "source": {
+ "provider": "huggingface",
+ "repo": "Comfy-Org/Krea-2",
+ "path": "diffusion_models/krea2_turbo_nvfp4.safetensors"
+ },
+ "quick_hash": null,
+ "sha256": null
+ }
+ ]
+ },
+ {
+ "label": "Text Encoder",
+ "folder": "text_encoders",
+ "variants": [
+ {
+ "precision": "fp8",
+ "filename": "qwen3vl_4b_fp8_scaled.safetensors",
+ "size_bytes": 5242467968,
+ "source": {
+ "provider": "huggingface",
+ "repo": "Comfy-Org/Krea-2",
+ "path": "text_encoders/qwen3vl_4b_fp8_scaled.safetensors"
+ },
+ "sha256": null
+ },
+ {
+ "precision": "bf16",
+ "filename": "qwen3vl_4b_bf16.safetensors",
+ "size_bytes": 8875719384,
+ "source": {
+ "provider": "huggingface",
+ "repo": "Comfy-Org/Krea-2",
+ "path": "text_encoders/qwen3vl_4b_bf16.safetensors"
+ },
+ "sha256": null
+ }
+ ]
+ },
+ {
+ "label": "VAE",
+ "folder": "vae",
+ "filename": "qwen_image_vae.safetensors",
+ "size_bytes": 253806246,
+ "source": {
+ "provider": "huggingface",
+ "repo": "Comfy-Org/Krea-2",
+ "path": "vae/qwen_image_vae.safetensors"
+ },
+ "sha256": null
+ }
+ ],
+ "nodes": {
+ "KSampler": {
+ "steps": 8,
+ "cfg": 1.0,
+ "sampler_name": "euler",
+ "scheduler": "simple",
+ "steps_range": [
+ 6,
+ 12
+ ],
+ "cfg_range": [
+ 1.0,
+ 1.5
+ ],
+ "sampler_name_options": [
+ "er_sde",
+ "euler",
+ "res_multistep",
+ "dpmpp_2m",
+ "euler_ancestral"
+ ],
+ "scheduler_options": [
+ "simple",
+ "beta",
+ "sgm_uniform",
+ "normal"
+ ]
+ },
+ "EmptySD3LatentImage": {
+ "width": 1024,
+ "height": 1536,
+ "_resolutions": [
+ {
+ "width": 1024,
+ "height": 1536
+ },
+ {
+ "width": 1536,
+ "height": 1024
+ },
+ {
+ "width": 1024,
+ "height": 1024
+ },
+ {
+ "width": 1152,
+ "height": 1536
+ },
+ {
+ "width": 1536,
+ "height": 1152
+ },
+ {
+ "width": 1408,
+ "height": 1408
+ },
+ {
+ "width": 1152,
+ "height": 2048
+ },
+ {
+ "width": 2048,
+ "height": 1152
+ }
+ ]
+ }
+ }
+}
diff --git a/data/prompts/krea2.json b/data/prompts/krea2.json
new file mode 100644
index 0000000..33fa4f3
--- /dev/null
+++ b/data/prompts/krea2.json
@@ -0,0 +1,1315 @@
+{
+ "name": "Krea 2 Prompts",
+ "prompts": [
+ {
+ "id": "krea2-default",
+ "name": "Natural Language",
+ "category": "",
+ "text": "// Your Tags\n{cursor}",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photography",
+ "name": "Photography",
+ "category": "",
+ "text": "// Your Tags\n{cursor}\n\n// Photography\nPhotographed on 35mm film, soft natural light from a window, crisp focus with a shallow depth of field, realistic skin and fabric texture, true-to-life color.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-cinematic",
+ "name": "Cinematic",
+ "category": "",
+ "text": "// Your Tags\n{cursor}\n\n// Cinematic\nA cinematic film still, dramatic low-key lighting with deep shadows, shot on an anamorphic lens, shallow depth of field, moody teal-and-amber color grade, subtle film grain.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-portrait",
+ "name": "Portrait",
+ "category": "",
+ "text": "// Your Tags\n{cursor}\n\n// Portrait\nA close-up portrait lit by soft diffused window light, shot on an 85mm lens with a shallow depth of field and creamy background blur, sharp eyes and finely detailed skin texture.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-illustration",
+ "name": "Illustration",
+ "category": "",
+ "text": "// Your Tags\n{cursor}\n\n// Illustration\nA detailed digital illustration with clean expressive linework, a rich harmonious color palette and soft painterly shading, dynamic composition with a clear focal point.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d-render",
+ "name": "3D Render",
+ "category": "",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Render\nhigh quality 3d render, smooth skin, ray tracing with rim lighting",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-concept-art",
+ "name": "Concept Art",
+ "category": "",
+ "text": "// Your Tags\n{cursor}\n\n// Concept Art\nSweeping concept art in a painterly matte-painting style, atmospheric haze and depth, dramatic god rays through the scene, an epic cinematic composition with a strong sense of scale.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-anime",
+ "name": "Anime",
+ "category": "",
+ "text": "// Your Tags\n{cursor}\n\n// Anime\nA vibrant anime illustration with bold clean cel-shaded linework, expressive eyes, saturated color and soft gradient skies, dynamic composition.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-comic-book",
+ "name": "Comic Book",
+ "category": "",
+ "text": "// Your Tags\n{cursor}\n\n// Comic Book\nComic Book Cover titled \"Comic Book\" at top. background of a sunny beach with ocean. In the style of 90s comics",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-stained-glass",
+ "name": "Stained Glass",
+ "category": "",
+ "text": "// Your Tags\n{cursor}\n\n// Stained Glass\nSubject as an elaborate stained glass window, divided into individual pieces of translucent jewel-toned glass, each piece outlined by thick black lead came lines. Bright light rays shine through from behind, making the colored glass glow luminously and casting soft colored light. Intricate leadwork, textured cathedral glass, ornate border, radiant and vivid.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-cartoony",
+ "name": "Cartoony",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - Cartoony\nStylized 3D cartoon style with exaggerated proportions and vibrant colors. Fortnite-inspired aesthetic, chunky silhouettes for visibility. Bold saturated palette, simplified textures with realistic materials. Playful approachable game art style.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-cel_shaded_3d",
+ "name": "Cel-Shaded 3D",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - Cel-Shaded 3D\nCel-shaded 3D render with bold outlines and flat color shading. Borderlands or anime game style, stylized lighting with sharp shadow edges. Clean vector-like appearance, comic book aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-chibi_3d",
+ "name": "Chibi 3D",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - Chibi 3D\nCute chibi-style 3D character with big head and small body. Adorable proportions, soft rounded features, glossy finish. Bright colorful rendering, studio lighting. High quality 3D render.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-clay_render",
+ "name": "Clay Render",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - Clay Render\nA realistic clay figurine with accurate human proportions, sculpted from smooth matte polymer clay. The sculpture has professional realistic handmade quality, displayed in a miniature diorama setting. Macro photography with shallow depth of field.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-claymation",
+ "name": "Claymation",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - Claymation\nA handmade claymation character in stop-motion animation style, sculpted from matte plasticine with visible fingerprint marks and subtle imperfections. Charming stylized proportions with smooth rounded forms, resembling Aardman animations. Miniature set diorama with warm studio lighting, macro photography with shallow depth of field.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-funko_pop",
+ "name": "Funko Pop",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - Funko Pop\nFunko Pop vinyl figure style with oversized square head and small body. Black dot eyes, stylized simplified features. Glossy vinyl material, collectible figure aesthetic. Clean studio render.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-hologram",
+ "name": "Hologram",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - Hologram\nSubject rendered as a faint blue hologram like Princess Leia's message in Star Wars, ghostly transparent figure made of flickering light with horizontal scan-lines throughout. See-through luminous blue form against dark background, barely visible ethereal projection.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-isometric",
+ "name": "Isometric",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - Isometric\nSubject viewed from an isometric perspective at a 45-degree angle above, rendered as a miniature 3D game asset with clean geometric forms. Orthographic projection with no perspective distortion, bright cheerful colors with soft ambient shadows. Tiny diorama scene resembling a mobile game or architectural visualization, sharp detailed render.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-low_poly",
+ "name": "Low Poly",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - Low Poly\nStylized low poly 3D art with visible geometric facets. Minimalist aesthetic, flat shaded triangular surfaces. Modern indie game style, clean colors with subtle gradients. Sharp edges.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-nendoroid",
+ "name": "Nendoroid",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - Nendoroid\nNendoroid chibi figure style with oversized head and small body. Cute collectible figure aesthetic, glossy PVC material look. Clean studio lighting, display stand. High quality 3D render.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-pixar",
+ "name": "Pixar/Disney",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - Pixar/Disney\nPixar 3D animation style with expressive character design. Soft subsurface scattering skin, large expressive eyes, stylized proportions. Cinematic lighting with warm tones, soft shadows. High quality 3D render, sharp focus.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-pixel_art",
+ "name": "Pixel Art",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - Pixel Art\nDetailed pixel art style with visible pixels creating retro game aesthetic. 16-bit or 32-bit era quality, limited color palette with careful dithering. Clean crisp pixels, nostalgic video game look.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-ps1_era",
+ "name": "PS1 Era",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - PS1 Era\nPlayStation 1 era 3D graphics with low polygon count and texture warping. Affine texture mapping artifacts, vertex jitter on edges. Gouraud shading, limited color palette. 90s retro game aesthetic, nostalgic early 3D look.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-realistic",
+ "name": "Realistic",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - Realistic\n3D render in Unreal Engine 5 style. Video game character with stylized realism, subsurface scattering on skin, rim lighting. AAA game promotional art quality, highly detailed, sharp focus.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-vector_3d",
+ "name": "Vector",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - Vector\nClean vector art style with flat solid colors and crisp geometric shapes. Bold outlines, no gradients or textures. Minimalist graphic design aesthetic, scalable illustration look. Simple clean forms, limited color palette.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-voxel",
+ "name": "Voxel/Minecraft",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - Voxel/Minecraft\nVoxel art style made of 3D cubes and blocks. Minecraft aesthetic, blocky geometric forms. Bright colors, clean edges, isometric or 3D perspective. Sharp render.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-3d_styles-wireframe",
+ "name": "Wireframe",
+ "category": "3D Styles",
+ "text": "// Your Tags\n{cursor}\n\n// 3D Styles - Wireframe\nSubject rendered entirely as a 3D wireframe mesh, the figure constructed from geometric lines connecting vertices with no solid surfaces or textures. The entire form is visible as a transparent polygon grid structure, glowing white or green lines against a dark background. Technical CAD visualization style with mathematical precision.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-anime-90s_anime",
+ "name": "90s Anime",
+ "category": "Anime",
+ "text": "// Your Tags\n{cursor}\n\n// Anime - 90s Anime\n90s retro anime style with nostalgic OVA aesthetic. Bold linework, high contrast cel shading, vibrant saturated colors. Film grain, subtle chromatic aberration, VHS texture. Classic hand-drawn animation look, dynamic action poses.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-anime-bishonen",
+ "name": "Bishonen",
+ "category": "Anime",
+ "text": "// Your Tags\n{cursor}\n\n// Anime - Bishonen\nBishonen pretty boy anime style with handsome androgynous male character. Romantic shoujo aesthetic with sparkles and roses, flowing hair, delicate features. Soft lighting, dreamy atmosphere, elegant poses. Long-haired pretty boy design, emotionally expressive.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-anime-cel_shaded",
+ "name": "Cel Shaded",
+ "category": "Anime",
+ "text": "// Your Tags\n{cursor}\n\n// Anime - Cel Shaded\nAnime key visual illustration with cel shaded coloring and clean sharp linework. Vibrant colors, expressive character design, detailed background. Masterpiece quality, highly detailed, sharp focus.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-anime-chibi",
+ "name": "Chibi",
+ "category": "Anime",
+ "text": "// Your Tags\n{cursor}\n\n// Anime - Chibi\nCute chibi anime style with oversized head and small body. Adorable simplified features, big expressive eyes, rounded proportions. Bright cheerful colors, clean linework, kawaii aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-anime-donghua",
+ "name": "Donghua",
+ "category": "Anime",
+ "text": "// Your Tags\n{cursor}\n\n// Anime - Donghua\nChinese Donghua anime style with elegant flowing aesthetic. Traditional ink wash painting influences mixed with modern anime rendering. Ethereal atmosphere, intricate costume details, xianxia or wuxia influence. Delicate linework, rich color palette.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-anime-hyperrealistic",
+ "name": "Hyperrealistic",
+ "category": "Anime",
+ "text": "// Your Tags\n{cursor}\n\n// Anime - Hyperrealistic\nHyperrealistic anime style blending photorealism with anime aesthetics. Realistic skin texture with subsurface scattering, expressive anime eyes with realistic reflections. Cinematic studio lighting, detailed hair strands, depth of field. High fidelity rendering, sharp focus.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-anime-irasutoya",
+ "name": "Irasutoya Clipart",
+ "category": "Anime",
+ "text": "// Your Tags\n{cursor}\n\n// Anime - Irasutoya Clipart\nSubject rendered in Irasutoya Japanese clipart style, a simple cute illustration with flat colors and rounded features. Clean minimalist linework with friendly expressive face, manga-influenced but heavily simplified. Approachable stock illustration aesthetic like Japanese free clipart.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-anime-manga",
+ "name": "Manga",
+ "category": "Anime",
+ "text": "// Your Tags\n{cursor}\n\n// Anime - Manga\nBlack and white manga illustration with detailed ink linework. Screentone shading, dynamic panel composition, expressive speed lines. High contrast, clean precise lines, professional manga quality.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-anime-semi_realistic",
+ "name": "Semi-Realistic",
+ "category": "Anime",
+ "text": "// Your Tags\n{cursor}\n\n// Anime - Semi-Realistic\n2.5D semi-realistic anime style blending expressive anime features with realistic detail. Realistic skin texture and lighting, nuanced facial structure with expressive anime eyes. Modern rendering with soft volumetric shadows, cinematic depth of field. Detailed hair strands, masterpiece quality, sharp focus.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-anime-shonen",
+ "name": "Shonen",
+ "category": "Anime",
+ "text": "// Your Tags\n{cursor}\n\n// Anime - Shonen\nDynamic shonen anime style with action-packed energy. Bold dramatic linework, intense expressions, dynamic poses. High contrast lighting, speed lines, powerful aura effects. Dragon Ball or Naruto inspired aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-anime-studio_ghibli",
+ "name": "Studio Ghibli",
+ "category": "Anime",
+ "text": "// Your Tags\n{cursor}\n\n// Anime - Studio Ghibli\nStudio Ghibli inspired anime style with soft watercolor aesthetic. Hand-painted backgrounds, gentle color palette, whimsical atmosphere. Miyazaki-esque character design, emotional warmth, detailed environmental storytelling.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-anime-vinyl_sticker",
+ "name": "Vinyl Sticker",
+ "category": "Anime",
+ "text": "// Your Tags\n{cursor}\n\n// Anime - Vinyl Sticker\nVinyl die-cut sticker art style with bold black outlines and white border. Flat vibrant colors, clean vector-like illustration. Designed for cutout shape, simple iconic design. Laptop sticker aesthetic, bold graphic illustration with thick outline.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-artists-bacon",
+ "name": "Francis Bacon",
+ "category": "Artists",
+ "text": "// Your Tags\n{cursor}\n\n// Artists - Francis Bacon\nSubject rendered in Francis Bacon's disturbing painting style, distorted figure with smeared and blurred features suggesting movement or anguish. Isolated against a dark flat background, raw fleshy paint handling with visible brushwork. Psychological intensity and grotesque distortion, figure appearing trapped or contorted, unsettling expressionist portraiture.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-artists-davinci",
+ "name": "Da Vinci",
+ "category": "Artists",
+ "text": "// Your Tags\n{cursor}\n\n// Artists - Da Vinci\nSubject rendered in Leonardo da Vinci's painting style with soft sfumato technique, subtle smoky transitions between tones with no harsh edges. Mysterious enigmatic expression, warm earth tones and muted colors. Atmospheric perspective, Renaissance oil painting mastery with delicate glazing layers, Mona Lisa aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-artists-goya",
+ "name": "Goya",
+ "category": "Artists",
+ "text": "// Your Tags\n{cursor}\n\n// Artists - Goya\nFrancisco Goya painting style with dark romantic atmosphere and psychological intensity. Rich shadows with dramatic lighting, Spanish court portrait elegance or Black Paintings darkness. Earthy palette with deep blacks, haunting emotional depth. Old master technique with modern sensibility.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-artists-hokusai",
+ "name": "Hokusai",
+ "category": "Artists",
+ "text": "// Your Tags\n{cursor}\n\n// Artists - Hokusai\nKatsushika Hokusai Japanese ukiyo-e woodblock print style. Bold outlines with flat color areas, distinctive wave patterns. Traditional Japanese composition, Mount Fuji or nature subjects. Prussian blue and indigo palette, The Great Wave aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-artists-klimt",
+ "name": "Klimt",
+ "category": "Artists",
+ "text": "// Your Tags\n{cursor}\n\n// Artists - Klimt\nGustav Klimt Art Nouveau painting with ornate gold leaf patterns and decorative Byzantine motifs. Flat decorative backgrounds with realistic faces, intricate geometric and floral patterns. Rich gold, bronze and jewel tones. Sensual elegance, The Kiss inspired aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-artists-monet",
+ "name": "Monet",
+ "category": "Artists",
+ "text": "// Your Tags\n{cursor}\n\n// Artists - Monet\nClaude Monet impressionist painting with soft dappled brushstrokes capturing light. Broken color technique, luminous atmospheric quality. Pastel color palette, water reflections, plein air aesthetic. Gentle diffused light, dreamy garden or water lily mood.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-artists-mucha",
+ "name": "Mucha",
+ "category": "Artists",
+ "text": "// Your Tags\n{cursor}\n\n// Artists - Mucha\nAlphonse Mucha Art Nouveau poster style with elegant decorative borders and flowing organic lines. Beautiful figure with long flowing hair surrounded by floral motifs. Soft pastel colors with gold accents, ornate circular halo frame. Elegant poster art aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-artists-picasso",
+ "name": "Picasso",
+ "category": "Artists",
+ "text": "// Your Tags\n{cursor}\n\n// Artists - Picasso\nPablo Picasso cubist style with fragmented geometric forms and multiple perspectives. Bold angular shapes, distorted features showing different viewpoints simultaneously. Strong black outlines, muted earth tones or blue period palette. Abstract modernist aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-artists-rembrandt",
+ "name": "Rembrandt",
+ "category": "Artists",
+ "text": "// Your Tags\n{cursor}\n\n// Artists - Rembrandt\nRembrandt oil painting with dramatic chiaroscuro lighting. Golden brown tones emerging from deep shadows, spotlight illuminating subject. Rich impasto texture, warm earth palette. Baroque master technique, intimate psychological portrait quality.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-artists-van_gogh",
+ "name": "Van Gogh",
+ "category": "Artists",
+ "text": "// Your Tags\n{cursor}\n\n// Artists - Van Gogh\nPainting in Vincent van Gogh style with bold swirling brushstrokes and thick impasto texture.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-artists-warhol",
+ "name": "Warhol",
+ "category": "Artists",
+ "text": "// Your Tags\n{cursor}\n\n// Artists - Warhol\nAndy Warhol pop art style with bold flat colors and high contrast. Screen print aesthetic, graphic simplified forms. Vibrant neon pinks, electric blues, acid yellows. Celebrity portrait treatment, repetition and mass media influence.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-concept_art-concept_realistic",
+ "name": "Concept Realistic",
+ "category": "Concept Art",
+ "text": "// Your Tags\n{cursor}\n\n// Concept Art - Concept Realistic\nConcept art on toned paper with graphite pencil underdrawing. Subject rendered in hyperrealistic colors with visible pencil linework beneath, detailed color study. Clean background or minimal environment, professional concept art presentation. Sharp focus on subject details.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-concept_art-concept_sketch",
+ "name": "Concept Sketch",
+ "category": "Concept Art",
+ "text": "// Your Tags\n{cursor}\n\n// Concept Art - Concept Sketch\nConcept art sketch on warm toned paper. Charcoal and pencil linework with soft pastel color accents, loose expressive strokes. Visible paper texture, muted color palette with selective highlights. Professional illustration, artist sketchbook study.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-concept_art-concept_soft_watercolor",
+ "name": "Concept Soft Watercolor",
+ "category": "Concept Art",
+ "text": "// Your Tags\n{cursor}\n\n// Concept Art - Concept Soft Watercolor\nSoft concept art with loose watercolor rendering and no visible linework. Ethereal wash-based forms with gentle color bleeding and soft edges. No outlines, shapes defined by color value alone. Minimal background, dreamy painterly character study.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-concept_art-concept_watercolor",
+ "name": "Concept Watercolor",
+ "category": "Concept Art",
+ "text": "// Your Tags\n{cursor}\n\n// Concept Art - Concept Watercolor\nConcept art sketch on toned paper with pencil linework colorized in transparent watercolors. Visible graphite underdrawing with soft watercolor washes building form and color. Character study with minimal background, traditional mixed media aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-concept_art-gouache",
+ "name": "Gouache",
+ "category": "Concept Art",
+ "text": "// Your Tags\n{cursor}\n\n// Concept Art - Gouache\nConcept art painted in gouache, opaque watercolor with matte finish. Classic animation production art style, rich flat color areas with subtle gradients. Visible brushwork, warm color palette. Disney or Ghibli background art influence.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-concept_art-ink_wash",
+ "name": "Ink Wash",
+ "category": "Concept Art",
+ "text": "// Your Tags\n{cursor}\n\n// Concept Art - Ink Wash\nConcept art in ink wash style with Eastern influences. Sumi-e inspired brushwork, fluid ink gradients from dark to light. Selective watercolor accents on subject, visible brush texture. Atmospheric depth, traditional rice paper aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-concept_art-line_art",
+ "name": "Line Art",
+ "category": "Concept Art",
+ "text": "// Your Tags\n{cursor}\n\n// Concept Art - Line Art\nClean concept art linework, precise ink lines with confident strokes. Minimal to no color, focus on form and contour. Professional illustration line drawing, subtle line weight variation. Clear readable silhouette.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-concept_art-marker",
+ "name": "Marker/Copic",
+ "category": "Concept Art",
+ "text": "// Your Tags\n{cursor}\n\n// Concept Art - Marker/Copic\nSubject rendered as a Copic marker illustration on white paper, the entire figure drawn with bold confident marker strokes and smooth color gradients. Visible marker streaks and layered ink blending, bright saturated colors with clean white highlights left as bare paper. Industrial design sketch aesthetic, professional concept art rendering.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-concept_art-thumbnail",
+ "name": "Thumbnail",
+ "category": "Concept Art",
+ "text": "// Your Tags\n{cursor}\n\n// Concept Art - Thumbnail\nSubject rendered as a quick concept art thumbnail sketch, the figure captured with loose gestural brushstrokes showing only essential forms and values. Rough unfinished exploration sketch with minimal detail, focus on silhouette and composition rather than refinement. Rapid ideation style, expressive and intentionally incomplete.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-drawing-ballpoint_pen",
+ "name": "Ballpoint Pen",
+ "category": "Drawing",
+ "text": "// Your Tags\n{cursor}\n\n// Drawing - Ballpoint Pen\nSubject rendered entirely as a ballpoint pen drawing on white paper, the entire figure drawn in blue ink using layered crosshatching strokes. Monochromatic blue ballpoint illustration with no color, form built through careful pen pressure and hatching density. Hyperrealistic ballpoint art style with fine detailed linework throughout, notebook paper aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-drawing-blueprint",
+ "name": "Blueprint",
+ "category": "Drawing",
+ "text": "// Your Tags\n{cursor}\n\n// Drawing - Blueprint\nTechnical blueprint schematic drawing with white lines on deep blue background. Precise engineering diagram style, architectural drafting aesthetic. Grid lines, measurements, technical annotations. Cyanotype blueprint reproduction look, technical illustration.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-drawing-chalk",
+ "name": "Chalk",
+ "category": "Drawing",
+ "text": "// Your Tags\n{cursor}\n\n// Drawing - Chalk\nChalk drawing on dark black paper, white and colored chalk creating forms from darkness. Soft dusty texture, layered strokes building highlights. Dramatic contrast with dark background showing through. Traditional chalkboard or toned paper aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-drawing-charcoal",
+ "name": "Charcoal",
+ "category": "Drawing",
+ "text": "// Your Tags\n{cursor}\n\n// Drawing - Charcoal\nCharcoal drawing on textured paper with rich velvety blacks and soft gradations. Expressive marks from vine and compressed charcoal, dramatic chiaroscuro lighting. Smudged blending in shadows, crisp edges on highlights. Deep tonal range, atmospheric depth. Traditional fine art charcoal study.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-drawing-chinese_ink",
+ "name": "Chinese Ink",
+ "category": "Drawing",
+ "text": "// Your Tags\n{cursor}\n\n// Drawing - Chinese Ink\nChinese ink brush painting in traditional sumi-e style on rice paper. Fluid ink wash gradations from deep black to pale gray, expressive brushstrokes. Wet-on-wet technique with soft bleeding edges, empty space as compositional element. Zen aesthetic, Eastern brush painting tradition.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-drawing-colored_pencil",
+ "name": "Colored Pencil",
+ "category": "Drawing",
+ "text": "// Your Tags\n{cursor}\n\n// Drawing - Colored Pencil\nColored pencil illustration with rich layered colors and visible pencil strokes.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-drawing-conte_crayon",
+ "name": "Conte Crayon",
+ "category": "Drawing",
+ "text": "// Your Tags\n{cursor}\n\n// Drawing - Conte Crayon\nConte crayon drawing on warm toned paper in classical trois crayons technique. Sanguine red-brown and sepia tones with white chalk highlights. Soft hatching and blending, Renaissance life drawing aesthetic. Warm earth tones on buff or gray paper, classical figure study quality.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-drawing-crosshatch",
+ "name": "Crosshatch",
+ "category": "Drawing",
+ "text": "// Your Tags\n{cursor}\n\n// Drawing - Crosshatch\nDetailed crosshatching pen and ink drawing with layered parallel lines creating tonal depth. Fine technical hatching following form contours, multiple angles building shadows. High contrast black ink on white paper, engraving-like precision. Classical crosshatch illustration technique.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-drawing-davinci_sketch",
+ "name": "DaVinci Sketch",
+ "category": "Drawing",
+ "text": "// Your Tags\n{cursor}\n\n// Drawing - DaVinci Sketch\nSubject rendered as a Leonardo da Vinci anatomical study, the figure drawn in sepia ink and silverpoint on aged yellowed paper. Renaissance master sketch style with precise linework showing anatomical understanding, subtle cross-hatching for shading. Warm brown tones on antique parchment, scientific illustration meets fine art, Da Vinci codex aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-drawing-gesture",
+ "name": "Gesture",
+ "category": "Drawing",
+ "text": "// Your Tags\n{cursor}\n\n// Drawing - Gesture\nQuick gesture drawing with loose expressive lines capturing movement and energy. Fluid dynamic strokes following line of action, minimal detail maximum expression. Charcoal or graphite on newsprint, figure study aesthetic. Spontaneous confident marks, artistic shorthand for form.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-drawing-ink",
+ "name": "Ink",
+ "category": "Drawing",
+ "text": "// Your Tags\n{cursor}\n\n// Drawing - Ink\nPen and ink drawing with fine precise linework on white paper. Confident strokes with varied line weight, hatching for tonal values. High contrast black ink on clean white, crisp details. Traditional ink illustration, sharp and graphic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-drawing-pastel",
+ "name": "Pastel",
+ "category": "Drawing",
+ "text": "// Your Tags\n{cursor}\n\n// Drawing - Pastel\nSoft pastel drawing with rich velvety pigments on textured paper. Smooth blended gradients, visible paper tooth in lighter areas. Chalky matte finish with vibrant colors. Feathered strokes and soft edges, traditional pastel portrait or landscape quality.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-drawing-pencil",
+ "name": "Pencil",
+ "category": "Drawing",
+ "text": "// Your Tags\n{cursor}\n\n// Drawing - Pencil\nSubject rendered as a graphite pencil drawing on white paper, the entire figure sketched in gray pencil with visible hatching and cross-hatching strokes. No color anywhere, only shades of gray from light to dark. Traditional hand-drawn sketch with pencil texture throughout, fine linework for details and softer blending in shadows.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-drawing-stippling",
+ "name": "Stippling",
+ "category": "Drawing",
+ "text": "// Your Tags\n{cursor}\n\n// Drawing - Stippling\nStippling pointillism drawing made entirely of small dots creating form and shadow. Dense dot clusters in dark areas, sparse dots in highlights. Black ink dots on white paper, incredible patience and detail. Photorealistic stipple art, no lines only dots.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-figurine-acrylic_stand",
+ "name": "Acrylic Stand",
+ "category": "Figurine",
+ "text": "// Your Tags\n{cursor}\n\n// Figurine - Acrylic Stand\n2D anime character printed on clear acrylic standee with base. Flat printed artwork on transparent acrylic panel, vibrant CMYK colors. Clean cut edges, small pedestal base. Anime merchandise style, desk decoration collectible.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-figurine-diorama",
+ "name": "Diorama",
+ "category": "Figurine",
+ "text": "// Your Tags\n{cursor}\n\n// Figurine - Diorama\nDetailed figure diorama with scenic environmental base telling a story. Character figure integrated with themed backdrop elements, environmental props and lighting effects. Display piece with immersive scene design, collector's diorama quality.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-figurine-figure_in_box",
+ "name": "Figurine in Box",
+ "category": "Figurine",
+ "text": "// Your Tags\n{cursor}\n\n// Figurine - Figurine in Box\nSubject rendered as a 1/7 scale PVC realistic anime figurine displayed inside commercial product packaging with clear window display box. The figure has smooth matte skin finish and glossy hair, visible through plastic window. Colorful printed box art, Limited Edition collectible presentation, official merchandise product photography.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-figurine-figure_on_desk",
+ "name": "Figurine on Desk",
+ "category": "Figurine",
+ "text": "// Your Tags\n{cursor}\n\n// Figurine - Figurine on Desk\nSubject rendered as a 1/7 scale PVC realistic anime figurine displayed on wooden desk surface. The figure has smooth matte skin finish and glossy hair, seamless sculpt with precise painted details. Soft natural window lighting, shallow depth of field. Collector's display photography, lifestyle product shot.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-figurine-garage_kit",
+ "name": "Garage Kit",
+ "category": "Figurine",
+ "text": "// Your Tags\n{cursor}\n\n// Figurine - Garage Kit\nUnpainted resin garage kit figure showing raw sculpt detail. Gray or white resin material, visible panel lines and part seams. Model kit aesthetic with professional sculpting quality, hobbyist collectible. Clean studio lighting.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-figurine-marble",
+ "name": "Marble",
+ "category": "Figurine",
+ "text": "// Your Tags\n{cursor}\n\n// Figurine - Marble\nSubject rendered as a polished white marble statue, the entire figure carved from a single block of marble with smooth sculpted surfaces and fine chisel detail. Realistic marble texture with subtle grey veining and a soft translucent sheen, classical Greek and Roman sculpture style. Displayed on a stone pedestal in a museum gallery, dramatic exhibition lighting and soft shadows, photorealistic sculpture photography.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-figurine-marble_bust",
+ "name": "Marble Bust",
+ "category": "Figurine",
+ "text": "// Your Tags\n{cursor}\n\n// Figurine - Marble Bust\nSubject rendered as a classical sculptural bust carved from marble, the figure shown as a stone sculpture depicting only head, neck and upper shoulders on an elegant pedestal base. Smooth polished marble surface with subtle veining, museum lighting casting dramatic shadows. Portrait sculpture with fine carved details, neoclassical statue aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-figurine-miniature",
+ "name": "Miniature",
+ "category": "Figurine",
+ "text": "// Your Tags\n{cursor}\n\n// Figurine - Miniature\nSubject rendered as a tiny miniature figure in a tilt-shift diorama scene, appearing as a small scale model viewed from above at an angle. Extremely shallow depth of field with blur at top and bottom edges, oversaturated toy-like colors making everything look like a miniature playset. The figure appears doll-sized in a model landscape.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-figurine-pvc_figure",
+ "name": "PVC Figurine",
+ "category": "Figurine",
+ "text": "// Your Tags\n{cursor}\n\n// Figurine - PVC Figurine\n1/7 scale PVC realistic anime figurine with smooth matte skin finish and glossy hair. Seamless single-piece sculpt, precise painted details. Soft studio lighting on transparent acrylic display base. Commercial product photography, collectible figurine aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-lighting-blue_hour",
+ "name": "Blue Hour",
+ "category": "Lighting",
+ "text": "// Your Tags\n{cursor}\n\n// Lighting - Blue Hour\nBlue hour twilight lighting with cool deep blue tones. Soft diffused ambient light, no harsh shadows. Ethereal calm atmosphere, city lights beginning to glow warm against cool sky. Twilight photography aesthetic, dreamlike quality.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-lighting-candlelight",
+ "name": "Candlelight",
+ "category": "Lighting",
+ "text": "// Your Tags\n{cursor}\n\n// Lighting - Candlelight\nWarm candlelight illumination with soft flickering orange glow. Single point light source, intimate atmosphere with deep warm shadows. Romantic mood, faces softly lit from below or side. Warm color temperature around 1800K, cozy intimate setting.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-lighting-dramatic",
+ "name": "Dramatic",
+ "category": "Lighting",
+ "text": "// Your Tags\n{cursor}\n\n// Lighting - Dramatic\nDramatic cinematic lighting with strong directional light and deep shadows. High contrast with sculpted highlights, theatrical mood. Single powerful key light, minimal fill. Intense emotional atmosphere, bold light and shadow interplay.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-lighting-film_noir",
+ "name": "Film Noir",
+ "category": "Lighting",
+ "text": "// Your Tags\n{cursor}\n\n// Lighting - Film Noir\nClassic film noir lighting with dramatic high contrast chiaroscuro. Deep black shadows, stark white highlights, minimal mid-tones. Venetian blind shadows, mysterious atmospheric mood. 1940s black and white cinema aesthetic, low-key dramatic lighting.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-lighting-golden_hour",
+ "name": "Golden Hour",
+ "category": "Lighting",
+ "text": "// Your Tags\n{cursor}\n\n// Lighting - Golden Hour\nGolden hour lighting with warm sunset tones of orange, yellow, and amber. Soft diffused sunlight from low angle, long shadows, rim lighting on edges. Warm color temperature around 3000K, romantic atmospheric glow. Magic hour photography aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-lighting-high_key",
+ "name": "High Key",
+ "category": "Lighting",
+ "text": "// Your Tags\n{cursor}\n\n// Lighting - High Key\nHigh key lighting with bright airy illumination and minimal shadows. Even soft light from multiple sources, white or light backgrounds. Clean fresh aesthetic, optimistic mood. Overexposed feeling, fashion or beauty photography style.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-lighting-low_key",
+ "name": "Low Key",
+ "category": "Lighting",
+ "text": "// Your Tags\n{cursor}\n\n// Lighting - Low Key\nLow key lighting with predominantly dark tones and selective highlights. Deep shadows dominating frame, small areas of bright illumination. Moody mysterious atmosphere, dramatic sculptural light on subject. Noir-inspired, theatrical mood.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-lighting-moonlight",
+ "name": "Moonlight",
+ "category": "Lighting",
+ "text": "// Your Tags\n{cursor}\n\n// Lighting - Moonlight\nCool silvery moonlight illumination with soft blue-white tones. Gentle diffused light from above, long soft shadows. Nocturnal atmosphere, stars visible, peaceful night scene. Cool color temperature, ethereal nighttime glow.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-lighting-neon",
+ "name": "Neon",
+ "category": "Lighting",
+ "text": "// Your Tags\n{cursor}\n\n// Lighting - Neon\nNeon lighting with vibrant colorful glow in cyberpunk aesthetic. Electric pink, cyan blue, and purple neon reflections on wet surfaces. Urban night atmosphere, light bleeding and color mixing. Blade Runner inspired, rain-slicked streets reflecting neon signs.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-lighting-rim_light",
+ "name": "Rim Light",
+ "category": "Lighting",
+ "text": "// Your Tags\n{cursor}\n\n// Lighting - Rim Light\nRim lighting with bright backlit edge glow outlining subject. Light source behind subject creating glowing halo around edges. Hair and shoulders catching light, separation from dark background. Dramatic silhouette with luminous edge definition.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-lighting-studio",
+ "name": "Studio",
+ "category": "Lighting",
+ "text": "// Your Tags\n{cursor}\n\n// Lighting - Studio\nProfessional studio lighting with clean three-point setup. Key light, fill light, and backlight creating balanced illumination. Even skin tones, controlled shadows, seamless backdrop. Commercial photography quality, polished professional aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-lighting-volumetric",
+ "name": "Volumetric",
+ "category": "Lighting",
+ "text": "// Your Tags\n{cursor}\n\n// Lighting - Volumetric\nVolumetric lighting with visible light rays cutting through atmosphere. God rays streaming through windows or trees, dust particles catching light. Dramatic shafts of light in hazy air, ethereal divine atmosphere. Cinematic light beams, atmospheric depth.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-material-art_deco",
+ "name": "Art Deco",
+ "category": "Material",
+ "text": "// Your Tags\n{cursor}\n\n// Material - Art Deco\nSubject rendered in Art Deco illustration style, the figure depicted with bold geometric patterns and 1920s glamour aesthetic. Streamlined elegant forms with sunburst motifs, chevrons, and angular designs throughout. Gold, black, and jewel tone color palette with luxurious chrome and metallic accents. Gatsby era poster art sophistication.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-material-chrome",
+ "name": "Chrome",
+ "category": "Material",
+ "text": "// Your Tags\n{cursor}\n\n// Material - Chrome\nSubject rendered as a chrome metal sculpture, the entire figure constructed from highly reflective polished chrome with mirror-like surface reflecting the environment. Liquid metal aesthetic with smooth metallic curves, silver reflections and highlights throughout. Futuristic chrome robot or T-1000 style metallic form.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-material-embroidery",
+ "name": "Embroidery",
+ "category": "Material",
+ "text": "// Your Tags\n{cursor}\n\n// Material - Embroidery\nSubject rendered as an embroidered textile artwork, the entire figure created with visible thread stitches on fabric backing. Cross-stitch and crewel embroidery techniques forming the image, raised textured needlework with thread direction following the form. Base fabric weave visible in background areas, traditional needlepoint craft aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-material-fabric",
+ "name": "Fabric/Textile",
+ "category": "Material",
+ "text": "// Your Tags\n{cursor}\n\n// Material - Fabric/Textile\nSubject rendered as a woven fabric tapestry, the entire figure depicted in textile artwork with visible weave pattern and thread texture throughout. The image appears as a traditional woven cloth with rich textile colors, the form created through stitched threads on fabric. Tapestry or embroidered wall hanging aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-material-glass",
+ "name": "Glass",
+ "category": "Material",
+ "text": "// Your Tags\n{cursor}\n\n// Material - Glass\nSubject rendered as a transparent glass sculpture, the entire figure constructed from clear crystal glass with light refracting through the form. See-through translucent body with visible light caustics and prismatic reflections, delicate glass art aesthetic. Crystal figurine with smooth polished glass surface.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-material-lego",
+ "name": "LEGO",
+ "category": "Material",
+ "text": "// Your Tags\n{cursor}\n\n// Material - LEGO\nMade entirely of LEGO bricks and pieces. Blocky minifigure aesthetic with characteristic yellow skin and simple dot eyes. Plastic brick texture, studs visible on surfaces. Bright primary colors, toy photography style. Everything constructed from interlocking LEGO elements.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-material-mosaic",
+ "name": "Mosaic",
+ "category": "Material",
+ "text": "// Your Tags\n{cursor}\n\n// Material - Mosaic\nSubject rendered as a Byzantine mosaic, the entire figure constructed from small colored tesserae tiles with visible grout lines between each piece. The form is built from hundreds of tiny square stone or glass tiles arranged to create the image, gold leaf accents and rich jewel tones. Ancient Roman church wall mosaic aesthetic, every part of image must be tiny tile stone framgments.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-material-origami",
+ "name": "Origami",
+ "category": "Material",
+ "text": "// Your Tags\n{cursor}\n\n// Material - Origami\nSubject rendered as an origami paper sculpture, the entire figure constructed from crisp geometric folds and clean creases in colored paper. Angular faceted surfaces forming the shape through folded planes, visible fold lines and paper edges throughout. Japanese paper folding art style, the figure appearing as a single folded sheet.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-material-paper_cutting",
+ "name": "Paper Cutting",
+ "category": "Material",
+ "text": "// Your Tags\n{cursor}\n\n// Material - Paper Cutting\nSubject rendered as a paper cutting silhouette artwork, the entire figure depicted as an intricate cutout design in black paper on white background. The form created through delicate cut patterns and negative space, lace-like details throughout with sharp clean edges. Scherenschnitte or Chinese paper cutting aesthetic, flat two-dimensional silhouette art.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-oil_painting-alla_prima",
+ "name": "Alla Prima",
+ "category": "Oil Painting",
+ "text": "// Your Tags\n{cursor}\n\n// Oil Painting - Alla Prima\nAlla prima oil painting, wet-on-wet technique in single session. Loose confident brushstrokes, fresh spontaneous execution. Visible brush marks with soft blended edges, painterly and direct. Bold color mixing on canvas, lively immediate quality.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-oil_painting-classical_realism",
+ "name": "Classical Realism",
+ "category": "Oil Painting",
+ "text": "// Your Tags\n{cursor}\n\n// Oil Painting - Classical Realism\noil painting on canvas, rich visible brush strokes, thick impasto texture in places, layered oil paint application with subtle blending and wet-on-wet edges, realistic oil paint sheen and color depth, textured surface with visible canvas weave in thinner areas, painterly execution, museum-quality fine art reproduction, muted yet vibrant color palette with harmonious glazing, no digital smoothness, authentic traditional oil painting appearance",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-oil_painting-clean_modern",
+ "name": "Clean Modern",
+ "category": "Oil Painting",
+ "text": "// Your Tags\n{cursor}\n\n// Oil Painting - Clean Modern\nOil painting on canvas with rich visible brushstrokes. Thick impasto texture with layered paint application, wet-on-wet blending and subtle glazing. Visible canvas weave in thinner areas, realistic paint sheen and color depth. Museum-quality fine art, authentic traditional oil painting.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-oil_painting-expressionist",
+ "name": "Expressionist",
+ "category": "Oil Painting",
+ "text": "// Your Tags\n{cursor}\n\n// Oil Painting - Expressionist\nExpressionist oil painting with bold swirling brushstrokes and thick impasto texture. Intense emotional colors, Van Gogh-inspired dynamic energy. Visible paint ridges, dramatic movement in brushwork. Raw expressive power, vibrant saturated palette.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-oil_painting-impressionist",
+ "name": "Impressionist",
+ "category": "Oil Painting",
+ "text": "// Your Tags\n{cursor}\n\n// Oil Painting - Impressionist\nImpressionist oil painting with loose visible brushstrokes capturing light and atmosphere. Vibrant broken color, dappled sunlight effects, Monet-inspired palette. Soft edges, painterly texture, plein air quality. Spontaneous brushwork, luminous colors.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-oil_painting-old_masters",
+ "name": "Old Masters",
+ "category": "Oil Painting",
+ "text": "// Your Tags\n{cursor}\n\n// Oil Painting - Old Masters\nOil painting in the style of Old Masters. Dramatic chiaroscuro lighting with deep shadows and luminous highlights, Rembrandt-style golden undertones. Rich dark background, fine glazing layers for skin depth, classical composition. Baroque influence, museum-quality fine art.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-oil_painting-palette_knife",
+ "name": "Palette Knife",
+ "category": "Oil Painting",
+ "text": "// Your Tags\n{cursor}\n\n// Oil Painting - Palette Knife\nOil portrait composed entirely of thick chunky blocks of color, no smooth surfaces anywhere. Face constructed from bold rectangular strokes of paint visible as distinct shapes, features suggested only by color placement not fine detail. Heavy textured surface like a Francoise Nielly painting, every inch covered in visible palette knife marks.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photorealistic-cinematic",
+ "name": "Cinematic Dramatic",
+ "category": "Photorealistic",
+ "text": "// Your Tags\n{cursor}\n\n// Photorealistic - Cinematic Dramatic\nCinematic still from a major motion picture. Dramatic chiaroscuro lighting with deep shadows, anamorphic lens with subtle lens flare. Cinematic color grading, film grain texture. Natural skin texture, sharp focus, raw photo.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photorealistic-default",
+ "name": "Default",
+ "category": "Photorealistic",
+ "text": "// Your Tags\n{cursor}\n\n// Photorealistic - Default\nSubject in center and isolated in a dark grey studio background. Real life subject shot on Sony A7RV with 50mm f/1.4 lens, shallow depth of field, cinematic color grading. Photorealistic, natural skin pores and texture, sharp focus, raw photo.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photorealistic-documentary",
+ "name": "Documentary",
+ "category": "Photorealistic",
+ "text": "// Your Tags\n{cursor}\n\n// Photorealistic - Documentary\nNational Geographic documentary photography capturing authentic candid moment. Natural available light, environmental storytelling with rich context. Genuine unguarded expression, photojournalistic quality, sharp focus, raw photo.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photorealistic-environmental",
+ "name": "Environmental",
+ "category": "Photorealistic",
+ "text": "// Your Tags\n{cursor}\n\n// Photorealistic - Environmental\nEnvironmental portrait with rich contextual background telling a story. Dappled light filtering through natural canopy, atmospheric depth. Subject integrated with surroundings, layers of visual interest. Sharp focus, raw photo.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photorealistic-epic_landscape",
+ "name": "Epic Landscape",
+ "category": "Photorealistic",
+ "text": "// Your Tags\n{cursor}\n\n// Photorealistic - Epic Landscape\nEpic landscape photography shot on Phase One IQ4 with 24mm wide angle lens at f/11. Volumetric lighting, atmospheric perspective with depth. Tack sharp throughout, raw photo.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photorealistic-fashion_editorial",
+ "name": "Fashion Editorial",
+ "category": "Photorealistic",
+ "text": "// Your Tags\n{cursor}\n\n// Photorealistic - Fashion Editorial\nHigh-end fashion editorial photography, Vogue magazine quality. Dramatic side lighting with shadow sculpting, strong contrast. Editorial pose, runway elegance, 85mm lens with shallow depth of field. Sharp focus, raw photo.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photorealistic-film_noir",
+ "name": "Film Noir",
+ "category": "Photorealistic",
+ "text": "// Your Tags\n{cursor}\n\n// Photorealistic - Film Noir\nSubject photographed in classic film noir style, dramatic black and white cinematography with stark high contrast lighting. Hard shadows cutting across the face from a single directional light source, deep impenetrable blacks and bright highlights with minimal midtones. Moody 1940s Hollywood atmosphere with venetian blind shadows, mysterious chiaroscuro lighting. Vintage film grain texture, hardboiled detective movie aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photorealistic-golden_hour_landscape",
+ "name": "Golden Hour Landscape",
+ "category": "Photorealistic",
+ "text": "// Your Tags\n{cursor}\n\n// Photorealistic - Golden Hour Landscape\nGolden hour landscape photography with wide angle lens. Warm sunset light with pink and gold sky gradients, volumetric light rays, long shadows. Atmospheric haze and depth, cinematic color grading, sharp focus, raw photo.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photorealistic-golden_hour_portrait",
+ "name": "Golden Hour Portrait",
+ "category": "Photorealistic",
+ "text": "// Your Tags\n{cursor}\n\n// Photorealistic - Golden Hour Portrait\nGolden hour portrait photography. Warm sunset light with soft shadows, backlit rim lighting on hair and shoulders. Warm color palette, natural outdoor setting. Natural skin texture with golden glow, sharp focus, raw photo.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photorealistic-macro",
+ "name": "Macro",
+ "category": "Photorealistic",
+ "text": "// Your Tags\n{cursor}\n\n// Photorealistic - Macro\nExtreme macro photography with 100mm macro lens. Shallow depth of field with creamy bokeh, soft backlighting with subtle light rays. Hyper-detailed textures, fine surface details visible, sharp focus on subject.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photorealistic-medium_format",
+ "name": "Medium Format",
+ "category": "Photorealistic",
+ "text": "// Your Tags\n{cursor}\n\n// Photorealistic - Medium Format\nShot on Hasselblad X2D medium format camera. Incredibly sharp details with beautiful tonal range, smooth gradients. Rich 16-bit color depth, natural color reproduction. Professional studio quality, sharp focus.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photorealistic-moody_atmospheric",
+ "name": "Moody Atmospheric",
+ "category": "Photorealistic",
+ "text": "// Your Tags\n{cursor}\n\n// Photorealistic - Moody Atmospheric\nMoody atmospheric photography with dramatic weather elements. Volumetric fog, soft diffused light, cinematic color grading. Emotional depth and tension, high contrast with soft shadows. Sharp focus, raw photo.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photorealistic-product",
+ "name": "Product",
+ "category": "Photorealistic",
+ "text": "// Your Tags\n{cursor}\n\n// Photorealistic - Product\nProfessional product photography on clean white seamless background. Soft box lighting with subtle shadow and reflection, rim highlights for separation. E-commerce ready, extremely sharp details, commercial studio quality.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photorealistic-street_portrait",
+ "name": "Street Portrait",
+ "category": "Photorealistic",
+ "text": "// Your Tags\n{cursor}\n\n// Photorealistic - Street Portrait\nCandid street portrait shot on 35mm lens. Natural available light, documentary photography style. Authentic urban atmosphere, environmental context. Natural skin texture, sharp focus, raw photo.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photorealistic-studio_portrait",
+ "name": "Studio Portrait",
+ "category": "Photorealistic",
+ "text": "// Your Tags\n{cursor}\n\n// Photorealistic - Studio Portrait\nProfessional studio portrait shot on 85mm lens. Clean key light with gentle fill, soft shadows. Shallow depth of field, seamless backdrop. Natural skin texture with fine pores, sharp focus, raw photo.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-photorealistic-vintage_film",
+ "name": "Vintage Film",
+ "category": "Photorealistic",
+ "text": "// Your Tags\n{cursor}\n\n// Photorealistic - Vintage Film\nSubject photographed on 35mm film with authentic analog aesthetic, visible film grain texture throughout the image with soft halation around highlights. Natural Kodak Portra color palette with slightly lifted blacks and gently faded highlights, warm organic skin tones. Soft analog contrast without digital sharpness, the unmistakable look of real film photography.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-watercolor-botanical",
+ "name": "Botanical",
+ "category": "Watercolor",
+ "text": "// Your Tags\n{cursor}\n\n// Watercolor - Botanical\nBotanical watercolor illustration with precise delicate detail. Scientific illustration quality, accurate naturalistic rendering. Soft transparent washes building form, fine brushwork for intricate details. Visible paper texture, muted natural color palette. Traditional botanical art style, museum specimen quality.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-watercolor-impressionistic",
+ "name": "Impressionistic",
+ "category": "Watercolor",
+ "text": "// Your Tags\n{cursor}\n\n// Watercolor - Impressionistic\nImpressionistic watercolor painting capturing light and atmosphere. Loose fluid brushstrokes, Monet-inspired color palette. Soft edges with selective detail, luminous transparent layers. Dappled light effects, plein air quality. Visible paper texture, spontaneous yet controlled execution.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-watercolor-loose_expressive",
+ "name": "Loose Expressive",
+ "category": "Watercolor",
+ "text": "// Your Tags\n{cursor}\n\n// Watercolor - Loose Expressive\nAbstract watercolor painting, fluid transparent layers of vibrant watercolors on textured cold-pressed paper. Energetic action splatter and drips with soft bleeding edges, wet-on-wet blending creating organic color flows and subtle granulation. Translucent washes with visible paper texture underneath, spontaneous expressive brush marks and accidental blooms. Authentic traditional watercolor appearance, no hard digital edges.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-watercolor-portrait",
+ "name": "Portrait/Realistic",
+ "category": "Watercolor",
+ "text": "// Your Tags\n{cursor}\n\n// Watercolor - Portrait/Realistic\nTraditional watercolor portrait with controlled transparent layers. Careful wet-on-dry technique building form gradually, soft skin tones with subtle glazing. Visible paper texture in highlights, delicate color transitions. Classical watercolor portrait style, refined brushwork.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ },
+ {
+ "id": "krea2-watercolor-wet_on_wet",
+ "name": "Wet-on-Wet",
+ "category": "Watercolor",
+ "text": "// Your Tags\n{cursor}\n\n// Watercolor - Wet-on-Wet\nDreamy wet-on-wet watercolor painting with soft flowing transitions. Colors bleeding and blending organically, no hard edges. Ethereal atmospheric quality, gentle gradients. Visible paper texture, unpredictable beautiful blooms. Soft focus effect, romantic watercolor aesthetic.",
+ "scope": {
+ "type": "architecture",
+ "architecture": "krea2"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/data/tag-builder/tag-builder.db b/data/tag-builder/tag-builder.db
index be5b31e..2763880 100644
Binary files a/data/tag-builder/tag-builder.db and b/data/tag-builder/tag-builder.db differ
diff --git a/data/templates/krea2-raw-i2i-highdetail.json b/data/templates/krea2-raw-i2i-highdetail.json
new file mode 100644
index 0000000..412f5f9
--- /dev/null
+++ b/data/templates/krea2-raw-i2i-highdetail.json
@@ -0,0 +1,343 @@
+{
+ "name": "Image-to-Image (High Detail)",
+ "category": "Generation",
+ "order": 7,
+ "scope": {
+ "type": "family",
+ "architecture": "krea2",
+ "family": "krea2_raw"
+ },
+ "created_at": 1782371000,
+ "id": "krea2-raw-i2i-highdetail",
+ "nodes": [
+ {
+ "type": "CLIPTextEncode",
+ "offset": [
+ 900.0,
+ 0.0
+ ],
+ "size": [
+ 225,
+ 116
+ ],
+ "widgets_values": [
+ ""
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPTextEncode"
+ }
+ },
+ {
+ "type": "CLIPTextEncode",
+ "offset": [
+ 900.0,
+ 180.0
+ ],
+ "size": [
+ 225,
+ 116
+ ],
+ "widgets_values": [
+ ""
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPTextEncode"
+ }
+ },
+ {
+ "type": "KSampler",
+ "offset": [
+ 1740.0,
+ 160.0
+ ],
+ "size": [
+ 330,
+ 474
+ ],
+ "widgets_values": [
+ 826502184750291,
+ "randomize",
+ 40,
+ 5.0,
+ "er_sde",
+ "beta",
+ 0.6
+ ],
+ "properties": {
+ "Node name for S&R": "KSampler"
+ }
+ },
+ {
+ "type": "VAEUtils_VAEDecodeTiled",
+ "offset": [
+ 1790.0,
+ 20.0
+ ],
+ "size": [
+ 300,
+ 220
+ ],
+ "widgets_values": [
+ -1,
+ false,
+ 512,
+ 64,
+ 4096,
+ 64
+ ],
+ "properties": {
+ "Node name for S&R": "VAEUtils_VAEDecodeTiled"
+ }
+ },
+ {
+ "type": "SaveImage",
+ "offset": [
+ 2150.0,
+ -10.0
+ ],
+ "size": [
+ 276.984375,
+ 322.984375
+ ],
+ "widgets_values": [
+ "Krea2-RAW/img2img-highdetail/%date:yyyy-MM-dd_hhmmss%"
+ ],
+ "properties": {}
+ },
+ {
+ "type": "CLIPLoader",
+ "offset": [
+ 860.0,
+ 360.0
+ ],
+ "size": [
+ 346.78125,
+ 117.328125
+ ],
+ "widgets_values": [
+ "qwen3vl_4b_fp8_scaled.safetensors",
+ "krea2",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPLoader"
+ }
+ },
+ {
+ "type": "UNETLoader",
+ "offset": [
+ 1240.0,
+ 0.0
+ ],
+ "size": [
+ 371.65625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "krea2_raw_bf16.safetensors",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "UNETLoader"
+ }
+ },
+ {
+ "type": "LoadImage",
+ "offset": [
+ 1240.0,
+ 220.0
+ ],
+ "size": [
+ 270,
+ 340
+ ],
+ "widgets_values": [
+ "",
+ "image"
+ ],
+ "properties": {
+ "Node name for S&R": "LoadImage"
+ }
+ },
+ {
+ "type": "VAEUtils_CustomVAELoader",
+ "offset": [
+ 1740.0,
+ 680.0
+ ],
+ "size": [
+ 366.40625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "Wan2.1_VAE_upscale2x_imageonly_real_v1.safetensors",
+ true
+ ],
+ "properties": {
+ "Node name for S&R": "VAEUtils_CustomVAELoader"
+ }
+ },
+ {
+ "type": "ConditioningKrea2Rebalance",
+ "offset": [
+ 1180.0,
+ 0.0
+ ],
+ "size": [
+ 300,
+ 106
+ ],
+ "widgets_values": [
+ 2.0,
+ "1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.6,2.5,1.05,2.0,1.0"
+ ],
+ "properties": {
+ "Node name for S&R": "ConditioningKrea2Rebalance"
+ }
+ },
+ {
+ "type": "ModelSamplingFlux",
+ "offset": [
+ 1460.0,
+ 90.0
+ ],
+ "size": [
+ 300,
+ 130
+ ],
+ "widgets_values": [
+ 0.90625,
+ 0.5,
+ 1024,
+ 1024
+ ],
+ "properties": {
+ "Node name for S&R": "ModelSamplingFlux"
+ }
+ },
+ {
+ "type": "VAEEncode",
+ "offset": [
+ 1560.0,
+ 600.0
+ ],
+ "size": [
+ 225,
+ 72
+ ],
+ "widgets_values": [],
+ "properties": {
+ "Node name for S&R": "VAEEncode"
+ }
+ },
+ {
+ "type": "VAELoader",
+ "offset": [
+ 1180.0,
+ 600.0
+ ],
+ "size": [
+ 366.40625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "qwen_image_vae.safetensors"
+ ],
+ "properties": {
+ "Node name for S&R": "VAELoader"
+ }
+ }
+ ],
+ "connections": [
+ {
+ "from_node_idx": 0,
+ "from_slot": 0,
+ "to_node_idx": 9,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 9,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 1,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 2
+ },
+ {
+ "from_node_idx": 6,
+ "from_slot": 0,
+ "to_node_idx": 10,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 10,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 11,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 3
+ },
+ {
+ "from_node_idx": 7,
+ "from_slot": 0,
+ "to_node_idx": 11,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 12,
+ "from_slot": 0,
+ "to_node_idx": 11,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 2,
+ "from_slot": 0,
+ "to_node_idx": 3,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 8,
+ "from_slot": 0,
+ "to_node_idx": 3,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 3,
+ "from_slot": 0,
+ "to_node_idx": 4,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 5,
+ "from_slot": 0,
+ "to_node_idx": 0,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 5,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 0
+ }
+ ],
+ "anchorConnections": [
+ {
+ "from_slot": 1,
+ "to_node_idx": 0,
+ "to_slot": 1
+ },
+ {
+ "from_slot": 2,
+ "to_node_idx": 1,
+ "to_slot": 1
+ }
+ ]
+}
diff --git a/data/templates/krea2-raw-i2i.json b/data/templates/krea2-raw-i2i.json
new file mode 100644
index 0000000..dda771d
--- /dev/null
+++ b/data/templates/krea2-raw-i2i.json
@@ -0,0 +1,294 @@
+{
+ "name": "Image-to-Image (RAW base)",
+ "category": "Generation",
+ "order": 5,
+ "scope": {
+ "type": "family",
+ "architecture": "krea2",
+ "family": "krea2_raw"
+ },
+ "created_at": 1782328500,
+ "id": "krea2-raw-i2i",
+ "nodes": [
+ {
+ "type": "CLIPTextEncode",
+ "offset": [
+ 899.9999977111815,
+ 0
+ ],
+ "size": [
+ 225,
+ 116
+ ],
+ "widgets_values": [
+ ""
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPTextEncode"
+ }
+ },
+ {
+ "type": "CLIPTextEncode",
+ "offset": [
+ 899.9999977111815,
+ 180.0
+ ],
+ "size": [
+ 225,
+ 116
+ ],
+ "widgets_values": [
+ ""
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPTextEncode"
+ }
+ },
+ {
+ "type": "KSampler",
+ "offset": [
+ 1699.9999685974124,
+ 160.0
+ ],
+ "size": [
+ 330,
+ 474
+ ],
+ "widgets_values": [
+ 826502184750291,
+ "randomize",
+ 40,
+ 5.0,
+ "er_sde",
+ "beta",
+ 0.6
+ ],
+ "properties": {
+ "Node name for S&R": "KSampler"
+ }
+ },
+ {
+ "type": "VAEDecode",
+ "offset": [
+ 1750.0000429382326,
+ 20.0
+ ],
+ "size": [
+ 225,
+ 72
+ ],
+ "widgets_values": [],
+ "properties": {
+ "Node name for S&R": "VAEDecode"
+ }
+ },
+ {
+ "type": "SaveImage",
+ "offset": [
+ 2090.0000285339356,
+ -10.0
+ ],
+ "size": [
+ 276.984375,
+ 322.984375
+ ],
+ "widgets_values": [
+ "Krea2-RAW/img2img/%date:yyyy-MM-dd_hhmmss%"
+ ],
+ "properties": {}
+ },
+ {
+ "type": "CLIPLoader",
+ "offset": [
+ 860.0000519714356,
+ 340.0
+ ],
+ "size": [
+ 346.78125,
+ 117.328125
+ ],
+ "widgets_values": [
+ "qwen3vl_4b_fp8_scaled.safetensors",
+ "krea2",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPLoader"
+ }
+ },
+ {
+ "type": "UNETLoader",
+ "offset": [
+ 1239.9999069433584,
+ 0
+ ],
+ "size": [
+ 371.65625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "krea2_raw_fp8_scaled.safetensors",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "UNETLoader"
+ }
+ },
+ {
+ "type": "LoadImage",
+ "offset": [
+ 1240.0,
+ 210.0
+ ],
+ "size": [
+ 270,
+ 340
+ ],
+ "widgets_values": [
+ "",
+ "image"
+ ],
+ "properties": {
+ "Node name for S&R": "LoadImage"
+ }
+ },
+ {
+ "type": "VAELoader",
+ "offset": [
+ 1239.993419293212,
+ 590.0
+ ],
+ "size": [
+ 366.40625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "qwen_image_vae.safetensors"
+ ],
+ "properties": {
+ "Node name for S&R": "VAELoader"
+ }
+ },
+ {
+ "type": "VAEEncode",
+ "offset": [
+ 1610.0,
+ 210.0
+ ],
+ "size": [
+ 225,
+ 72
+ ],
+ "widgets_values": [],
+ "properties": {
+ "Node name for S&R": "VAEEncode"
+ }
+ },
+ {
+ "type": "ModelSamplingFlux",
+ "offset": [
+ 1450.0,
+ 90.0
+ ],
+ "size": [
+ 300,
+ 130
+ ],
+ "widgets_values": [
+ 0.90625,
+ 0.5,
+ 1024,
+ 1024
+ ],
+ "properties": {
+ "Node name for S&R": "ModelSamplingFlux"
+ }
+ }
+ ],
+ "connections": [
+ {
+ "from_node_idx": 0,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 1,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 2
+ },
+ {
+ "from_node_idx": 2,
+ "from_slot": 0,
+ "to_node_idx": 3,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 3,
+ "from_slot": 0,
+ "to_node_idx": 4,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 5,
+ "from_slot": 0,
+ "to_node_idx": 0,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 5,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 6,
+ "from_slot": 0,
+ "to_node_idx": 10,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 10,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 8,
+ "from_slot": 0,
+ "to_node_idx": 3,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 9,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 3
+ },
+ {
+ "from_node_idx": 7,
+ "from_slot": 0,
+ "to_node_idx": 9,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 8,
+ "from_slot": 0,
+ "to_node_idx": 9,
+ "to_slot": 1
+ }
+ ],
+ "anchorConnections": [
+ {
+ "from_slot": 1,
+ "to_node_idx": 0,
+ "to_slot": 1
+ },
+ {
+ "from_slot": 2,
+ "to_node_idx": 1,
+ "to_slot": 1
+ }
+ ]
+}
\ No newline at end of file
diff --git a/data/templates/krea2-raw-t2i-highdetail.json b/data/templates/krea2-raw-t2i-highdetail.json
new file mode 100644
index 0000000..967bedf
--- /dev/null
+++ b/data/templates/krea2-raw-t2i-highdetail.json
@@ -0,0 +1,300 @@
+{
+ "name": "Text-to-Image (High Detail)",
+ "category": "Generation",
+ "order": 6,
+ "scope": {
+ "type": "family",
+ "architecture": "krea2",
+ "family": "krea2_raw"
+ },
+ "created_at": 1782370000,
+ "id": "krea2-raw-t2i-highdetail",
+ "nodes": [
+ {
+ "type": "CLIPTextEncode",
+ "offset": [
+ 900.0,
+ 0.0
+ ],
+ "size": [
+ 225,
+ 116
+ ],
+ "widgets_values": [
+ ""
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPTextEncode"
+ }
+ },
+ {
+ "type": "CLIPTextEncode",
+ "offset": [
+ 900.0,
+ 180.0
+ ],
+ "size": [
+ 225,
+ 116
+ ],
+ "widgets_values": [
+ ""
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPTextEncode"
+ }
+ },
+ {
+ "type": "KSampler",
+ "offset": [
+ 1740.0,
+ 160.0
+ ],
+ "size": [
+ 330,
+ 474
+ ],
+ "widgets_values": [
+ 826502184750291,
+ "randomize",
+ 52,
+ 5.0,
+ "er_sde",
+ "beta",
+ 1
+ ],
+ "properties": {
+ "Node name for S&R": "KSampler"
+ }
+ },
+ {
+ "type": "VAEUtils_VAEDecodeTiled",
+ "offset": [
+ 1790.0,
+ 20.0
+ ],
+ "size": [
+ 300,
+ 220
+ ],
+ "widgets_values": [
+ -1,
+ false,
+ 512,
+ 64,
+ 4096,
+ 64
+ ],
+ "properties": {
+ "Node name for S&R": "VAEUtils_VAEDecodeTiled"
+ }
+ },
+ {
+ "type": "SaveImage",
+ "offset": [
+ 2150.0,
+ -10.0
+ ],
+ "size": [
+ 276.984375,
+ 322.984375
+ ],
+ "widgets_values": [
+ "Krea2-RAW/highdetail/%date:yyyy-MM-dd_hhmmss%"
+ ],
+ "properties": {}
+ },
+ {
+ "type": "CLIPLoader",
+ "offset": [
+ 860.0,
+ 360.0
+ ],
+ "size": [
+ 346.78125,
+ 117.328125
+ ],
+ "widgets_values": [
+ "qwen3vl_4b_fp8_scaled.safetensors",
+ "krea2",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPLoader"
+ }
+ },
+ {
+ "type": "UNETLoader",
+ "offset": [
+ 1240.0,
+ 0.0
+ ],
+ "size": [
+ 371.65625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "krea2_raw_bf16.safetensors",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "UNETLoader"
+ }
+ },
+ {
+ "type": "EmptySD3LatentImage",
+ "offset": [
+ 1250.0,
+ 220.0
+ ],
+ "size": [
+ 324,
+ 144
+ ],
+ "widgets_values": [
+ 1024,
+ 1024,
+ 1
+ ],
+ "properties": {
+ "Node name for S&R": "EmptySD3LatentImage"
+ }
+ },
+ {
+ "type": "VAEUtils_CustomVAELoader",
+ "offset": [
+ 1240.0,
+ 470.0
+ ],
+ "size": [
+ 366.40625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "Wan2.1_VAE_upscale2x_imageonly_real_v1.safetensors",
+ true
+ ],
+ "properties": {
+ "Node name for S&R": "VAEUtils_CustomVAELoader"
+ }
+ },
+ {
+ "type": "ConditioningKrea2Rebalance",
+ "offset": [
+ 1180.0,
+ 0.0
+ ],
+ "size": [
+ 300,
+ 106
+ ],
+ "widgets_values": [
+ 2.0,
+ "1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.6,2.5,1.05,2.0,1.0"
+ ],
+ "properties": {
+ "Node name for S&R": "ConditioningKrea2Rebalance"
+ }
+ },
+ {
+ "type": "ModelSamplingFlux",
+ "offset": [
+ 1460.0,
+ 90.0
+ ],
+ "size": [
+ 300,
+ 130
+ ],
+ "widgets_values": [
+ 0.90625,
+ 0.5,
+ 1024,
+ 1024
+ ],
+ "properties": {
+ "Node name for S&R": "ModelSamplingFlux"
+ }
+ }
+ ],
+ "connections": [
+ {
+ "from_node_idx": 0,
+ "from_slot": 0,
+ "to_node_idx": 9,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 9,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 1,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 2
+ },
+ {
+ "from_node_idx": 6,
+ "from_slot": 0,
+ "to_node_idx": 10,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 10,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 7,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 3
+ },
+ {
+ "from_node_idx": 2,
+ "from_slot": 0,
+ "to_node_idx": 3,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 8,
+ "from_slot": 0,
+ "to_node_idx": 3,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 3,
+ "from_slot": 0,
+ "to_node_idx": 4,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 5,
+ "from_slot": 0,
+ "to_node_idx": 0,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 5,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 0
+ }
+ ],
+ "anchorConnections": [
+ {
+ "from_slot": 1,
+ "to_node_idx": 0,
+ "to_slot": 1
+ },
+ {
+ "from_slot": 2,
+ "to_node_idx": 1,
+ "to_slot": 1
+ }
+ ]
+}
diff --git a/data/templates/krea2-raw-t2i.json b/data/templates/krea2-raw-t2i.json
new file mode 100644
index 0000000..68156e2
--- /dev/null
+++ b/data/templates/krea2-raw-t2i.json
@@ -0,0 +1,268 @@
+{
+ "name": "Text-to-Image (RAW base)",
+ "category": "Generation",
+ "order": 4,
+ "scope": {
+ "type": "family",
+ "architecture": "krea2",
+ "family": "krea2_raw"
+ },
+ "created_at": 1782328400,
+ "id": "c5a9e2f0-1b3d-4e6a-8c7f-9d2b4a6e1f08",
+ "nodes": [
+ {
+ "type": "CLIPTextEncode",
+ "offset": [
+ 899.9999977111815,
+ 0
+ ],
+ "size": [
+ 225,
+ 116
+ ],
+ "widgets_values": [
+ ""
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPTextEncode"
+ }
+ },
+ {
+ "type": "CLIPTextEncode",
+ "offset": [
+ 899.9999977111815,
+ 180.0
+ ],
+ "size": [
+ 225,
+ 116
+ ],
+ "widgets_values": [
+ ""
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPTextEncode"
+ }
+ },
+ {
+ "type": "KSampler",
+ "offset": [
+ 1699.9999685974124,
+ 160.0
+ ],
+ "size": [
+ 330,
+ 474
+ ],
+ "widgets_values": [
+ 826502184750291,
+ "randomize",
+ 52,
+ 5.0,
+ "er_sde",
+ "beta",
+ 1
+ ],
+ "properties": {
+ "Node name for S&R": "KSampler"
+ }
+ },
+ {
+ "type": "VAEDecode",
+ "offset": [
+ 1750.0000429382326,
+ 20.0
+ ],
+ "size": [
+ 225,
+ 72
+ ],
+ "widgets_values": [],
+ "properties": {
+ "Node name for S&R": "VAEDecode"
+ }
+ },
+ {
+ "type": "SaveImage",
+ "offset": [
+ 2090.0000285339356,
+ -10.0
+ ],
+ "size": [
+ 276.984375,
+ 322.984375
+ ],
+ "widgets_values": [
+ "Krea2-RAW/%date:yyyy-MM-dd_hhmmss%"
+ ],
+ "properties": {}
+ },
+ {
+ "type": "CLIPLoader",
+ "offset": [
+ 860.0000519714356,
+ 340.0
+ ],
+ "size": [
+ 346.78125,
+ 117.328125
+ ],
+ "widgets_values": [
+ "qwen3vl_4b_fp8_scaled.safetensors",
+ "krea2",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPLoader"
+ }
+ },
+ {
+ "type": "UNETLoader",
+ "offset": [
+ 1239.9999069433584,
+ 0
+ ],
+ "size": [
+ 371.65625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "krea2_raw_fp8_scaled.safetensors",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "UNETLoader"
+ }
+ },
+ {
+ "type": "EmptySD3LatentImage",
+ "offset": [
+ 1249.9999315600576,
+ 200.0
+ ],
+ "size": [
+ 324,
+ 144
+ ],
+ "widgets_values": [
+ 1024,
+ 1024,
+ 1
+ ],
+ "properties": {
+ "Node name for S&R": "EmptySD3LatentImage"
+ }
+ },
+ {
+ "type": "VAELoader",
+ "offset": [
+ 1239.993419293212,
+ 450.0
+ ],
+ "size": [
+ 366.40625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "qwen_image_vae.safetensors"
+ ],
+ "properties": {
+ "Node name for S&R": "VAELoader"
+ }
+ },
+ {
+ "type": "ModelSamplingFlux",
+ "offset": [
+ 1450.0,
+ 90.0
+ ],
+ "size": [
+ 300,
+ 130
+ ],
+ "widgets_values": [
+ 0.90625,
+ 0.5,
+ 1024,
+ 1024
+ ],
+ "properties": {
+ "Node name for S&R": "ModelSamplingFlux"
+ }
+ }
+ ],
+ "connections": [
+ {
+ "from_node_idx": 0,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 1,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 2
+ },
+ {
+ "from_node_idx": 2,
+ "from_slot": 0,
+ "to_node_idx": 3,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 3,
+ "from_slot": 0,
+ "to_node_idx": 4,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 5,
+ "from_slot": 0,
+ "to_node_idx": 0,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 5,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 6,
+ "from_slot": 0,
+ "to_node_idx": 9,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 9,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 7,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 3
+ },
+ {
+ "from_node_idx": 8,
+ "from_slot": 0,
+ "to_node_idx": 3,
+ "to_slot": 1
+ }
+ ],
+ "anchorConnections": [
+ {
+ "from_slot": 1,
+ "to_node_idx": 0,
+ "to_slot": 1
+ },
+ {
+ "from_slot": 2,
+ "to_node_idx": 1,
+ "to_slot": 1
+ }
+ ]
+}
\ No newline at end of file
diff --git a/data/templates/krea2-turbo-i2i-highdetail.json b/data/templates/krea2-turbo-i2i-highdetail.json
new file mode 100644
index 0000000..e0c0bb9
--- /dev/null
+++ b/data/templates/krea2-turbo-i2i-highdetail.json
@@ -0,0 +1,289 @@
+{
+ "name": "Image-to-Image (High Detail)",
+ "category": "Generation",
+ "order": 4,
+ "scope": {
+ "type": "family",
+ "architecture": "krea2",
+ "family": "krea2_turbo"
+ },
+ "created_at": 1782364000,
+ "id": "b7c3e8a1-4f2d-4a6b-9c0e-2a1f6d3b9f0a",
+ "nodes": [
+ {
+ "type": "CLIPTextEncode",
+ "offset": [
+ 820.0,
+ 20.0
+ ],
+ "size": [
+ 225,
+ 116
+ ],
+ "widgets_values": [
+ ""
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPTextEncode"
+ }
+ },
+ {
+ "type": "KSampler",
+ "offset": [
+ 1440.0,
+ 120.0
+ ],
+ "size": [
+ 330,
+ 474
+ ],
+ "widgets_values": [
+ 826502184750291,
+ "randomize",
+ 8,
+ 1,
+ "euler",
+ "simple",
+ 0.6
+ ],
+ "properties": {
+ "Node name for S&R": "KSampler"
+ }
+ },
+ {
+ "type": "VAEUtils_VAEDecodeTiled",
+ "offset": [
+ 1800.0,
+ 20.0
+ ],
+ "size": [
+ 300,
+ 220
+ ],
+ "widgets_values": [
+ -1,
+ false,
+ 512,
+ 64,
+ 4096,
+ 64
+ ],
+ "properties": {
+ "Node name for S&R": "VAEUtils_VAEDecodeTiled"
+ }
+ },
+ {
+ "type": "SaveImage",
+ "offset": [
+ 2140.0,
+ -10.0
+ ],
+ "size": [
+ 276.984375,
+ 322.984375
+ ],
+ "widgets_values": [
+ "Krea2/img2img-highdetail/%date:yyyy-MM-dd_hhmmss%"
+ ],
+ "properties": {}
+ },
+ {
+ "type": "CLIPLoader",
+ "offset": [
+ 820.0,
+ 240.0
+ ],
+ "size": [
+ 346.78125,
+ 117.328125
+ ],
+ "widgets_values": [
+ "qwen3vl_4b_fp8_scaled.safetensors",
+ "krea2",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPLoader"
+ }
+ },
+ {
+ "type": "UNETLoader",
+ "offset": [
+ 1100.0,
+ 280.0
+ ],
+ "size": [
+ 371.65625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "krea2_turbo_bf16.safetensors",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "UNETLoader"
+ }
+ },
+ {
+ "type": "LoadImage",
+ "offset": [
+ 780.0,
+ 420.0
+ ],
+ "size": [
+ 270,
+ 340
+ ],
+ "widgets_values": [
+ "",
+ "image"
+ ],
+ "properties": {
+ "Node name for S&R": "LoadImage"
+ }
+ },
+ {
+ "type": "VAEUtils_CustomVAELoader",
+ "offset": [
+ 1440.0,
+ 620.0
+ ],
+ "size": [
+ 366.40625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "Wan2.1_VAE_upscale2x_imageonly_real_v1.safetensors",
+ true
+ ],
+ "properties": {
+ "Node name for S&R": "VAEUtils_CustomVAELoader"
+ }
+ },
+ {
+ "type": "ConditioningKrea2Rebalance",
+ "offset": [
+ 1100.0,
+ 20.0
+ ],
+ "size": [
+ 300,
+ 106
+ ],
+ "widgets_values": [
+ 2.0,
+ "1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.6,2.5,1.05,2.0,1.0"
+ ],
+ "properties": {
+ "Node name for S&R": "ConditioningKrea2Rebalance"
+ }
+ },
+ {
+ "type": "VAEEncode",
+ "offset": [
+ 1130.0,
+ 500.0
+ ],
+ "size": [
+ 225,
+ 72
+ ],
+ "widgets_values": [],
+ "properties": {
+ "Node name for S&R": "VAEEncode"
+ }
+ },
+ {
+ "type": "VAELoader",
+ "offset": [
+ 780.0,
+ 790.0
+ ],
+ "size": [
+ 366.40625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "qwen_image_vae.safetensors"
+ ],
+ "properties": {
+ "Node name for S&R": "VAELoader"
+ }
+ }
+ ],
+ "connections": [
+ {
+ "from_node_idx": 0,
+ "from_slot": 0,
+ "to_node_idx": 8,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 8,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 0,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 2
+ },
+ {
+ "from_node_idx": 1,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 7,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 2,
+ "from_slot": 0,
+ "to_node_idx": 3,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 4,
+ "from_slot": 0,
+ "to_node_idx": 0,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 5,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 9,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 3
+ },
+ {
+ "from_node_idx": 6,
+ "from_slot": 0,
+ "to_node_idx": 9,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 10,
+ "from_slot": 0,
+ "to_node_idx": 9,
+ "to_slot": 1
+ }
+ ],
+ "anchorConnections": [
+ {
+ "from_slot": 1,
+ "to_node_idx": 0,
+ "to_slot": 1
+ }
+ ]
+}
\ No newline at end of file
diff --git a/data/templates/krea2-turbo-i2i.json b/data/templates/krea2-turbo-i2i.json
new file mode 100644
index 0000000..61bb882
--- /dev/null
+++ b/data/templates/krea2-turbo-i2i.json
@@ -0,0 +1,240 @@
+{
+ "name": "Image-to-Image",
+ "category": "Generation",
+ "order": 1,
+ "scope": {
+ "type": "family",
+ "architecture": "krea2",
+ "family": "krea2_turbo"
+ },
+ "created_at": 1782327800,
+ "id": "krea2-turbo-i2i",
+ "nodes": [
+ {
+ "type": "CLIPTextEncode",
+ "offset": [
+ 899.9999977111815,
+ 0
+ ],
+ "size": [
+ 225,
+ 116
+ ],
+ "widgets_values": [
+ ""
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPTextEncode"
+ }
+ },
+ {
+ "type": "KSampler",
+ "offset": [
+ 1699.9999685974124,
+ 160.0
+ ],
+ "size": [
+ 330,
+ 474
+ ],
+ "widgets_values": [
+ 826502184750291,
+ "randomize",
+ 8,
+ 1,
+ "euler",
+ "simple",
+ 0.6
+ ],
+ "properties": {
+ "Node name for S&R": "KSampler"
+ }
+ },
+ {
+ "type": "VAEDecode",
+ "offset": [
+ 1750.0000429382326,
+ 20.0
+ ],
+ "size": [
+ 225,
+ 72
+ ],
+ "widgets_values": [],
+ "properties": {
+ "Node name for S&R": "VAEDecode"
+ }
+ },
+ {
+ "type": "SaveImage",
+ "offset": [
+ 2090.0000285339356,
+ -10.0
+ ],
+ "size": [
+ 276.984375,
+ 322.984375
+ ],
+ "widgets_values": [
+ "Krea2/img2img/%date:yyyy-MM-dd_hhmmss%"
+ ],
+ "properties": {}
+ },
+ {
+ "type": "CLIPLoader",
+ "offset": [
+ 860.0000519714356,
+ 200.0
+ ],
+ "size": [
+ 346.78125,
+ 117.328125
+ ],
+ "widgets_values": [
+ "qwen3vl_4b_fp8_scaled.safetensors",
+ "krea2",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPLoader"
+ }
+ },
+ {
+ "type": "UNETLoader",
+ "offset": [
+ 1239.9999069433584,
+ 0
+ ],
+ "size": [
+ 371.65625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "krea2_turbo_fp8_scaled.safetensors",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "UNETLoader"
+ }
+ },
+ {
+ "type": "LoadImage",
+ "offset": [
+ 1240.0,
+ 210.0
+ ],
+ "size": [
+ 270,
+ 340
+ ],
+ "widgets_values": [
+ "",
+ "image"
+ ],
+ "properties": {
+ "Node name for S&R": "LoadImage"
+ }
+ },
+ {
+ "type": "VAELoader",
+ "offset": [
+ 1239.993419293212,
+ 390.0
+ ],
+ "size": [
+ 366.40625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "qwen_image_vae.safetensors"
+ ],
+ "properties": {
+ "Node name for S&R": "VAELoader"
+ }
+ },
+ {
+ "type": "VAEEncode",
+ "offset": [
+ 1610.0,
+ 210.0
+ ],
+ "size": [
+ 225,
+ 72
+ ],
+ "widgets_values": [],
+ "properties": {
+ "Node name for S&R": "VAEEncode"
+ }
+ }
+ ],
+ "connections": [
+ {
+ "from_node_idx": 0,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 0,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 2
+ },
+ {
+ "from_node_idx": 1,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 2,
+ "from_slot": 0,
+ "to_node_idx": 3,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 4,
+ "from_slot": 0,
+ "to_node_idx": 0,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 5,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 7,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 8,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 3
+ },
+ {
+ "from_node_idx": 6,
+ "from_slot": 0,
+ "to_node_idx": 8,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 7,
+ "from_slot": 0,
+ "to_node_idx": 8,
+ "to_slot": 1
+ }
+ ],
+ "anchorConnections": [
+ {
+ "from_slot": 1,
+ "to_node_idx": 0,
+ "to_slot": 1
+ }
+ ]
+}
\ No newline at end of file
diff --git a/data/templates/krea2-turbo-t2i-3d-regional.json b/data/templates/krea2-turbo-t2i-3d-regional.json
new file mode 100644
index 0000000..35681d9
--- /dev/null
+++ b/data/templates/krea2-turbo-t2i-3d-regional.json
@@ -0,0 +1,270 @@
+{
+ "name": "Text-to-Image 3D Regional",
+ "scope": {
+ "type": "family",
+ "architecture": "krea2",
+ "family": "krea2_turbo"
+ },
+ "created_at": 1781920000,
+ "nodes": [
+ {
+ "type": "PromptChain_RegionalConditioning",
+ "offset": [
+ 820,
+ 120
+ ],
+ "size": [
+ 300,
+ 170
+ ],
+ "widgets_values": [
+ 22
+ ],
+ "properties": {
+ "Node name for S&R": "PromptChain_RegionalConditioning"
+ }
+ },
+ {
+ "type": "KSampler",
+ "offset": [
+ 1830,
+ 60
+ ],
+ "size": [
+ 344.15625,
+ 565.328125
+ ],
+ "widgets_values": [
+ 674787291728667,
+ "randomize",
+ 8,
+ 1,
+ "euler",
+ "simple",
+ 1
+ ],
+ "properties": {
+ "Node name for S&R": "KSampler"
+ }
+ },
+ {
+ "type": "VAEDecode",
+ "offset": [
+ 2230,
+ 60
+ ],
+ "size": [
+ 225,
+ 72
+ ],
+ "widgets_values": [],
+ "properties": {
+ "Node name for S&R": "VAEDecode"
+ }
+ },
+ {
+ "type": "SaveImage",
+ "offset": [
+ 2230,
+ 200
+ ],
+ "size": [
+ 247.25,
+ 419.046875
+ ],
+ "widgets_values": [
+ "Krea2/%date:yyyy-MM-dd_hhmmss%"
+ ],
+ "properties": {}
+ },
+ {
+ "type": "CLIPLoader",
+ "offset": [
+ 820,
+ 320
+ ],
+ "size": [
+ 346.78125,
+ 117.328125
+ ],
+ "widgets_values": [
+ "qwen3vl_4b_fp8_scaled.safetensors",
+ "krea2",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPLoader"
+ }
+ },
+ {
+ "type": "UNETLoader",
+ "offset": [
+ 820,
+ 520
+ ],
+ "size": [
+ 304.953125,
+ 82.65625
+ ],
+ "widgets_values": [
+ "krea2_turbo_fp8_scaled.safetensors",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "UNETLoader"
+ }
+ },
+ {
+ "type": "EmptySD3LatentImage",
+ "offset": [
+ 1180,
+ 320
+ ],
+ "size": [
+ 270,
+ 144
+ ],
+ "widgets_values": [
+ 1024,
+ 1536,
+ 1
+ ],
+ "properties": {
+ "Node name for S&R": "EmptySD3LatentImage"
+ }
+ },
+ {
+ "type": "VAELoader",
+ "offset": [
+ 820,
+ 680
+ ],
+ "size": [
+ 246,
+ 83
+ ],
+ "widgets_values": [
+ "qwen_image_vae.safetensors"
+ ],
+ "properties": {
+ "Node name for S&R": "VAELoader"
+ }
+ },
+ {
+ "type": "PromptChain_PoseStudio",
+ "offset": [
+ -1350,
+ 0
+ ],
+ "size": [
+ 360,
+ 470
+ ],
+ "widgets_values": [
+ "",
+ "{\"version\":3,\"camera\":{\"position\":[-0.11421765907369465,2.2679667675054747,3.7640721683793985],\"target\":[-0.08116832790578885,0.9626632788387957,0.003294416573047413]},\"activeIndex\":1,\"figures\":[{\"uid\":4,\"body\":\"custom\",\"root\":[-0.6544460683107087,1.83557839158723e-7,-0.1296069154697062],\"rootQuat\":[0,0,0,1],\"rootScale\":[1.0847089667745293,1.0847089667745293,1.0847089667745293],\"joints\":{\"root\":[0.530589759349823,0,0,0.8476287722587585],\"shoulderL\":[-0.008142700418829918,0.012219684198498726,-0.33881765604019165,0.9407374858856201],\"elbowL\":[0.3669451177120209,0.0018381300615146756,0.0031449354719370604,0.9302355051040649],\"wristL\":[0.11023613810539246,0.41108429431915283,-0.016057291999459267,0.9047650694847107],\"shoulderR\":[-0.008142700418829918,-0.012219684198498726,0.33881765604019165,0.9407374858856201],\"elbowR\":[0.3669451177120209,-0.0018381300615146756,-0.0031449354719370604,0.9302355051040649],\"wristR\":[0.11023613810539246,-0.41108429431915283,0.016057291999459267,0.9047650694847107],\"neck\":[0.16243939101696014,0,0,0.9867185354232788],\"head\":[-0.20577044785022736,0,0,0.978600263595581],\"hipL\":[-0.9580745100975037,-0.09174012392759323,0.21390390396118164,0.16709932684898376],\"kneeL\":[0.058844611048698425,0.23217718303203583,-0.008530011400580406,0.9708544611930847],\"ankleL\":[-0.5353211164474487,-0.0010657769162207842,0.0007613753550685942,0.8446476459503174],\"hipR\":[-0.9580745100975037,0.09174012392759323,-0.21390390396118164,0.16709932684898376],\"kneeR\":[0.058844611048698425,-0.23217718303203583,0.008530011400580406,0.9708544611930847],\"ankleR\":[-0.5353211164474487,0.0010657769162207842,-0.0007613753550685942,0.8446476459503174],\"chest\":[0.008510730229318142,0,0,0.9999638199806213],\"spine\":[0.3344581127166748,0,0,0.9424106478691101],\"back\":[0,0,0,1]},\"jointPos\":{\"Root\":[0,-0.000562518835067749,6.100162863731384e-8],\"pelvis\":[0,-0.015393643795202175,0.8765072291716933],\"spine_01\":[0,0.08837844353790084,-0.0000035875321676330854],\"spine_02\":[0,0.06657692409741382,-0.0015471302564643939],\"spine_03\":[0,0.07465957864769734,-0.005422550541500943],\"spine_04\":[0,0.1554920266911116,0.008057116608445842],\"clavicle_l\":[0.022795276308897883,0.08298090375804652,0.026856951939407736],\"upperarm_l\":[-0.002402820275165144,0.14708170919523886,-0.0024412409402430058],\"lowerarm_l\":[-0.0036035171942785382,0.2335675825791744,0.007550966273508189],\"hand_l\":[-0.0022912098793312925,0.23001713307652003,0.00286084097691249],\"index_01_l\":[-0.014275551244888145,0.10155431967965949,0.00913081387989223],\"index_02_l\":[-0.00032961389198741625,0.024996880173906295,-0.00044333142189619445],\"index_03_l\":[-0.00028979239747665514,0.02228745664691208,-0.000271643739930975],\"middle_01_l\":[0.0011213888258983697,0.0983148121922568,-0.010979589074850082],\"middle_02_l\":[-0.0004448858817340806,0.032625457237979084,-0.00045865285210311413],\"middle_03_l\":[-0.0003890491255636637,0.026699312448423978,-0.00020532777125481538],\"pinky_01_l\":[0.030837264833583806,0.08091115868228371,-0.0306820534557725],\"pinky_02_l\":[-0.0004330708179622891,0.020605956754783012,-0.0003710941079286083],\"pinky_03_l\":[-0.0002436345233339428,0.015057439972830858,0.000014291528107908793],\"ring_01_l\":[0.014671692488870274,0.09115619229805816,-0.023141342176434897],\"ring_02_l\":[-0.00039252417445823095,0.028744175334092386,-0.0004921690172826243],\"ring_03_l\":[-0.00043109167184714653,0.02398470316741926,-0.0001844997920367557],\"thumb_01_l\":[-0.014337413944303988,0.037947991551694336,0.014606909942813218],\"thumb_02_l\":[0.0002165158900121842,0.029646236808427297,-0.0005050097582473731],\"thumb_03_l\":[0.0001837790356754948,0.035048878259355355,-0.0005737583730175779],\"clavicle_r\":[-0.022795276308897883,0.08298090375804652,0.026856951939407736],\"upperarm_r\":[0.002402820275165144,0.14708170919523886,-0.0024412409402430058],\"lowerarm_r\":[0.0036035171942785382,0.2335675825791744,0.007550966273508189],\"hand_r\":[0.0022912098793312925,0.23001713307652003,0.00286084097691249],\"index_01_r\":[0.014275551244888145,0.10155431967965949,0.00913081387989223],\"index_02_r\":[0.00032961389198741625,0.024996880173906295,-0.00044333142189619445],\"index_03_r\":[0.00028979239747665514,0.02228745664691208,-0.000271643739930975],\"middle_01_r\":[-0.0011213888258983697,0.0983148121922568,-0.010979589074850082],\"middle_02_r\":[0.0004448858817340806,0.032625457237979084,-0.00045865285210311413],\"middle_03_r\":[0.0003890491255636637,0.026699312448423978,-0.00020532777125481538],\"pinky_01_r\":[-0.030837264833583806,0.08091115868228371,-0.0306820534557725],\"pinky_02_r\":[0.0004330708179622891,0.020605956754783012,-0.0003710941079286083],\"pinky_03_r\":[0.0002436345233339428,0.015057439972830858,0.000014291528107908793],\"ring_01_r\":[-0.014671692488870274,0.09115619229805816,-0.023141342176434897],\"ring_02_r\":[0.00039252417445823095,0.028744175334092386,-0.0004921690172826243],\"ring_03_r\":[0.00043109167184714653,0.02398470316741926,-0.0001844997920367557],\"thumb_01_r\":[0.014337413944303988,0.037947991551694336,0.014606909942813218],\"thumb_02_r\":[-0.0002165158900121842,0.029646236808427297,-0.0005050097582473731],\"thumb_03_r\":[-0.0001837790356754948,0.035048878259355355,-0.0005737583730175779],\"neck_01\":[0,0.1554920266911116,0.008057112766740222],\"head\":[0,0.09913267713272944,-0.0024949000217020546],\"thigh_l\":[0.10406423709112762,-0.01035807409789413,-0.015486810940274154],\"calf_l\":[-0.0018221052984396628,0.38333685158674297,0.0019527052451546005],\"foot_l\":[0.0012040060549528171,0.41225113686717424,0.0060748945009739454],\"ball_l\":[-0.004144214297411963,0.1319912777786764,0.0008641794556751847],\"thigh_r\":[-0.10406423709112762,-0.01035807409789413,-0.015486810940274154],\"calf_r\":[0.0018221052984396628,0.38333685158674297,0.0019527052451546005],\"foot_r\":[-0.0012040060549528171,0.41225113686717424,0.0060748945009739454],\"ball_r\":[0.004144214297411963,0.1319912777786764,0.0008641794556751847]},\"digits\":{\"index_01_l\":[0.11009154468774796,0.47919291257858276,-0.0033358719665557146,0.8707714676856995],\"index_02_l\":[0.10867490619421005,0.0028905405197292566,0.006149682216346264,0.9940541386604309],\"index_03_l\":[0.06272030621767044,0.0006448967615142465,0.018671324476599693,0.9978562593460083],\"middle_01_l\":[0.09819573163986206,0.41311776638031006,-0.15238040685653687,0.8924525380134583],\"middle_02_l\":[0.04684380069375038,0.0005204545450396836,0.03666960448026657,0.9982287883758545],\"middle_03_l\":[0.06767940521240234,0.0009195368620567024,-0.005850149318575859,0.9976895451545715],\"pinky_01_l\":[0.04672148823738098,0.29210352897644043,-0.3033210337162018,0.9058084487915039],\"pinky_02_l\":[0.08093646168708801,0.0011062186677008867,0.024598531424999237,0.9964150786399841],\"pinky_03_l\":[-0.008727755397558212,-0.00023478623188566417,-0.01132167037576437,0.9998977780342102],\"ring_01_l\":[0.05214594677090645,0.3895569145679474,-0.2304530292749405,0.890178382396698],\"ring_02_l\":[0.059518661350011826,0.00033943928428925574,0.04314512386918068,0.9972943067550659],\"ring_03_l\":[0.05962633714079857,0.00068375637056306,-0.02453024499118328,0.9979191422462463],\"thumb_01_l\":[0.2744263708591461,0.731201171875,0.43757393956184387,0.44560524821281433],\"thumb_02_l\":[0.06898587942123413,-0.017102878540754318,-0.18289531767368317,0.9805599451065063],\"thumb_03_l\":[0.14205099642276764,-0.006924070883542299,-0.032810747623443604,0.9892911911010742],\"index_01_r\":[0.11009154468774796,-0.47919291257858276,0.0033358719665557146,0.8707714676856995],\"index_02_r\":[0.10867490619421005,-0.0028905405197292566,-0.006149682216346264,0.9940541386604309],\"index_03_r\":[0.06272030621767044,-0.0006448967615142465,-0.018671324476599693,0.9978562593460083],\"middle_01_r\":[0.09819573163986206,-0.41311776638031006,0.15238040685653687,0.8924525380134583],\"middle_02_r\":[0.04684380069375038,-0.0005204545450396836,-0.03666960448026657,0.9982287883758545],\"middle_03_r\":[0.06767940521240234,-0.0009195368620567024,0.005850149318575859,0.9976895451545715],\"pinky_01_r\":[0.04672148823738098,-0.29210352897644043,0.3033210337162018,0.9058084487915039],\"pinky_02_r\":[0.08093646168708801,-0.0011062186677008867,-0.024598531424999237,0.9964150786399841],\"pinky_03_r\":[-0.008727755397558212,0.00023478623188566417,0.01132167037576437,0.9998977780342102],\"ring_01_r\":[0.05214594677090645,-0.3895569145679474,0.2304530292749405,0.890178382396698],\"ring_02_r\":[0.059518661350011826,-0.00033943928428925574,-0.04314512386918068,0.9972943067550659],\"ring_03_r\":[0.05962633714079857,-0.00068375637056306,0.02453024499118328,0.9979191422462463],\"thumb_01_r\":[0.2744263708591461,-0.731201171875,-0.43757393956184387,0.44560524821281433],\"thumb_02_r\":[0.06898587942123413,0.017102878540754318,0.18289531767368317,0.9805599451065063],\"thumb_03_r\":[0.14205099642276764,0.006924070883542299,0.032810747623443604,0.9892911911010742],\"ball_l\":[-0.26220664381980896,0.0072789317928254604,0.029169803485274315,0.964543342590332],\"ball_r\":[-0.26220664381980896,-0.0072789317928254604,-0.029169803485274315,0.964543342590332]},\"spine\":{\"spine_01\":[0.3344581127166748,0,0,0.9424106478691101],\"spine_02\":[-0.10261907428503036,0,0,0.9947206974029541],\"spine_03\":[0.008510730229318142,0,0,0.9999638199806213],\"spine_04\":[0,0,0,1],\"neck_01\":[0.16243939101696014,0,0,0.9867185354232788],\"head\":[-0.20577044785022736,0,0,0.978600263595581]},\"morphs\":{},\"skeletalAmount\":{\"__custom\":1},\"footPins\":{},\"shoes\":false,\"sliders\":{\"gender\":0.5,\"age\":0.5,\"muscle\":0.5,\"weight\":0.5,\"height\":0.5,\"proportions\":0.5,\"african\":0.3333333333333333,\"asian\":0.3333333333333333,\"caucasian\":0.3333333333333333,\"cupsize\":0.5,\"firmness\":0.5,\"breast-trans\":0,\"breast-dist\":0,\"breast-point\":0,\"breast-volume-vert\":0,\"nipple-size\":0,\"nipple-point\":0,\"fem-apple\":0,\"fem-diamond\":0,\"fem-full-hourglass\":0,\"fem-neat-hourglass\":0,\"fem-invert-triangle\":0,\"fem-lean-column\":0,\"fem-rectangle\":0,\"fem-triangle\":0,\"fem-adrenal\":0,\"fem-liver\":0,\"fem-ovary\":0,\"fem-thyroid\":0,\"man-apple\":0,\"man-rectangle\":0,\"man-lean-column\":0,\"man-triangle\":0,\"man-invert-triangle\":0,\"man-trapezoid\":0,\"man-adrenal\":0,\"man-liver\":0,\"man-gonadal\":0,\"man-thyroid\":0,\"torso-scale-depth\":0,\"torso-scale-horiz\":0,\"torso-scale-vert\":0,\"torso-trans-horiz\":0,\"torso-trans-vert\":0,\"torso-trans-depth\":0,\"torso-vshape\":0,\"torso-dorsi\":0,\"torso-pectoral\":0,\"fingers-distance\":0,\"fingers-diameter\":0,\"fingers-length\":0,\"hand-scale\":0,\"hand-position\":0,\"hips\":0,\"glutes\":0,\"stomach\":0,\"neck-circ\":0,\"neck-height\":0,\"head-age\":0,\"head-fat\":0,\"head-angle\":0,\"head-oval\":0,\"head-round\":0,\"head-rectangular\":0,\"head-square\":0,\"head-triangular\":0,\"head-invtriangular\":0,\"head-diamond\":0,\"head-parietal\":0}},{\"uid\":5,\"body\":\"custom\",\"root\":[0.5167425402036215,1.83557839158723e-7,-0.1296069154697062],\"rootQuat\":[0,0,0,1],\"rootScale\":[1.0847089667745293,1.0847089667745293,1.0847089667745293],\"joints\":{\"root\":[0.530589759349823,0,0,0.8476287722587585],\"shoulderL\":[-0.008142700418829918,0.012219684198498726,-0.33881765604019165,0.9407374858856201],\"elbowL\":[0.3669451177120209,0.0018381300615146756,0.0031449354719370604,0.9302355051040649],\"wristL\":[0.11023613810539246,0.41108429431915283,-0.016057291999459267,0.9047650694847107],\"shoulderR\":[-0.008142700418829918,-0.012219684198498726,0.33881765604019165,0.9407374858856201],\"elbowR\":[0.3669451177120209,-0.0018381300615146756,-0.0031449354719370604,0.9302355051040649],\"wristR\":[0.11023613810539246,-0.41108429431915283,0.016057291999459267,0.9047650694847107],\"neck\":[0.16243939101696014,0,0,0.9867185354232788],\"head\":[-0.20577044785022736,0,0,0.978600263595581],\"hipL\":[-0.9580745100975037,-0.09174012392759323,0.21390390396118164,0.16709932684898376],\"kneeL\":[0.058844611048698425,0.23217718303203583,-0.008530011400580406,0.9708544611930847],\"ankleL\":[-0.5353211164474487,-0.0010657769162207842,0.0007613753550685942,0.8446476459503174],\"hipR\":[-0.9580745100975037,0.09174012392759323,-0.21390390396118164,0.16709932684898376],\"kneeR\":[0.058844611048698425,-0.23217718303203583,0.008530011400580406,0.9708544611930847],\"ankleR\":[-0.5353211164474487,0.0010657769162207842,-0.0007613753550685942,0.8446476459503174],\"chest\":[0.008510730229318142,0,0,0.9999638199806213],\"spine\":[0.3344581127166748,0,0,0.9424106478691101],\"back\":[0,0,0,1]},\"jointPos\":{\"Root\":[0,-0.000562518835067749,6.100162863731384e-8],\"pelvis\":[0,-0.015393643795202175,0.8765072291716933],\"spine_01\":[0,0.08837844353790084,-0.0000035875321676330854],\"spine_02\":[0,0.06657692409741382,-0.0015471302564643939],\"spine_03\":[0,0.07465957864769734,-0.005422550541500943],\"spine_04\":[0,0.1554920266911116,0.008057116608445842],\"clavicle_l\":[0.022795276308897883,0.08298090375804652,0.026856951939407736],\"upperarm_l\":[-0.002402820275165144,0.14708170919523886,-0.0024412409402430058],\"lowerarm_l\":[-0.0036035171942785382,0.2335675825791744,0.007550966273508189],\"hand_l\":[-0.0022912098793312925,0.23001713307652003,0.00286084097691249],\"index_01_l\":[-0.014275551244888145,0.10155431967965949,0.00913081387989223],\"index_02_l\":[-0.00032961389198741625,0.024996880173906295,-0.00044333142189619445],\"index_03_l\":[-0.00028979239747665514,0.02228745664691208,-0.000271643739930975],\"middle_01_l\":[0.0011213888258983697,0.0983148121922568,-0.010979589074850082],\"middle_02_l\":[-0.0004448858817340806,0.032625457237979084,-0.00045865285210311413],\"middle_03_l\":[-0.0003890491255636637,0.026699312448423978,-0.00020532777125481538],\"pinky_01_l\":[0.030837264833583806,0.08091115868228371,-0.0306820534557725],\"pinky_02_l\":[-0.0004330708179622891,0.020605956754783012,-0.0003710941079286083],\"pinky_03_l\":[-0.0002436345233339428,0.015057439972830858,0.000014291528107908793],\"ring_01_l\":[0.014671692488870274,0.09115619229805816,-0.023141342176434897],\"ring_02_l\":[-0.00039252417445823095,0.028744175334092386,-0.0004921690172826243],\"ring_03_l\":[-0.00043109167184714653,0.02398470316741926,-0.0001844997920367557],\"thumb_01_l\":[-0.014337413944303988,0.037947991551694336,0.014606909942813218],\"thumb_02_l\":[0.0002165158900121842,0.029646236808427297,-0.0005050097582473731],\"thumb_03_l\":[0.0001837790356754948,0.035048878259355355,-0.0005737583730175779],\"clavicle_r\":[-0.022795276308897883,0.08298090375804652,0.026856951939407736],\"upperarm_r\":[0.002402820275165144,0.14708170919523886,-0.0024412409402430058],\"lowerarm_r\":[0.0036035171942785382,0.2335675825791744,0.007550966273508189],\"hand_r\":[0.0022912098793312925,0.23001713307652003,0.00286084097691249],\"index_01_r\":[0.014275551244888145,0.10155431967965949,0.00913081387989223],\"index_02_r\":[0.00032961389198741625,0.024996880173906295,-0.00044333142189619445],\"index_03_r\":[0.00028979239747665514,0.02228745664691208,-0.000271643739930975],\"middle_01_r\":[-0.0011213888258983697,0.0983148121922568,-0.010979589074850082],\"middle_02_r\":[0.0004448858817340806,0.032625457237979084,-0.00045865285210311413],\"middle_03_r\":[0.0003890491255636637,0.026699312448423978,-0.00020532777125481538],\"pinky_01_r\":[-0.030837264833583806,0.08091115868228371,-0.0306820534557725],\"pinky_02_r\":[0.0004330708179622891,0.020605956754783012,-0.0003710941079286083],\"pinky_03_r\":[0.0002436345233339428,0.015057439972830858,0.000014291528107908793],\"ring_01_r\":[-0.014671692488870274,0.09115619229805816,-0.023141342176434897],\"ring_02_r\":[0.00039252417445823095,0.028744175334092386,-0.0004921690172826243],\"ring_03_r\":[0.00043109167184714653,0.02398470316741926,-0.0001844997920367557],\"thumb_01_r\":[0.014337413944303988,0.037947991551694336,0.014606909942813218],\"thumb_02_r\":[-0.0002165158900121842,0.029646236808427297,-0.0005050097582473731],\"thumb_03_r\":[-0.0001837790356754948,0.035048878259355355,-0.0005737583730175779],\"neck_01\":[0,0.1554920266911116,0.008057112766740222],\"head\":[0,0.09913267713272944,-0.0024949000217020546],\"thigh_l\":[0.10406423709112762,-0.01035807409789413,-0.015486810940274154],\"calf_l\":[-0.0018221052984396628,0.38333685158674297,0.0019527052451546005],\"foot_l\":[0.0012040060549528171,0.41225113686717424,0.0060748945009739454],\"ball_l\":[-0.004144214297411963,0.1319912777786764,0.0008641794556751847],\"thigh_r\":[-0.10406423709112762,-0.01035807409789413,-0.015486810940274154],\"calf_r\":[0.0018221052984396628,0.38333685158674297,0.0019527052451546005],\"foot_r\":[-0.0012040060549528171,0.41225113686717424,0.0060748945009739454],\"ball_r\":[0.004144214297411963,0.1319912777786764,0.0008641794556751847]},\"digits\":{\"index_01_l\":[0.11009154468774796,0.47919291257858276,-0.0033358719665557146,0.8707714676856995],\"index_02_l\":[0.10867490619421005,0.0028905405197292566,0.006149682216346264,0.9940541386604309],\"index_03_l\":[0.06272030621767044,0.0006448967615142465,0.018671324476599693,0.9978562593460083],\"middle_01_l\":[0.09819573163986206,0.41311776638031006,-0.15238040685653687,0.8924525380134583],\"middle_02_l\":[0.04684380069375038,0.0005204545450396836,0.03666960448026657,0.9982287883758545],\"middle_03_l\":[0.06767940521240234,0.0009195368620567024,-0.005850149318575859,0.9976895451545715],\"pinky_01_l\":[0.04672148823738098,0.29210352897644043,-0.3033210337162018,0.9058084487915039],\"pinky_02_l\":[0.08093646168708801,0.0011062186677008867,0.024598531424999237,0.9964150786399841],\"pinky_03_l\":[-0.008727755397558212,-0.00023478623188566417,-0.01132167037576437,0.9998977780342102],\"ring_01_l\":[0.05214594677090645,0.3895569145679474,-0.2304530292749405,0.890178382396698],\"ring_02_l\":[0.059518661350011826,0.00033943928428925574,0.04314512386918068,0.9972943067550659],\"ring_03_l\":[0.05962633714079857,0.00068375637056306,-0.02453024499118328,0.9979191422462463],\"thumb_01_l\":[0.2744263708591461,0.731201171875,0.43757393956184387,0.44560524821281433],\"thumb_02_l\":[0.06898587942123413,-0.017102878540754318,-0.18289531767368317,0.9805599451065063],\"thumb_03_l\":[0.14205099642276764,-0.006924070883542299,-0.032810747623443604,0.9892911911010742],\"index_01_r\":[0.11009154468774796,-0.47919291257858276,0.0033358719665557146,0.8707714676856995],\"index_02_r\":[0.10867490619421005,-0.0028905405197292566,-0.006149682216346264,0.9940541386604309],\"index_03_r\":[0.06272030621767044,-0.0006448967615142465,-0.018671324476599693,0.9978562593460083],\"middle_01_r\":[0.09819573163986206,-0.41311776638031006,0.15238040685653687,0.8924525380134583],\"middle_02_r\":[0.04684380069375038,-0.0005204545450396836,-0.03666960448026657,0.9982287883758545],\"middle_03_r\":[0.06767940521240234,-0.0009195368620567024,0.005850149318575859,0.9976895451545715],\"pinky_01_r\":[0.04672148823738098,-0.29210352897644043,0.3033210337162018,0.9058084487915039],\"pinky_02_r\":[0.08093646168708801,-0.0011062186677008867,-0.024598531424999237,0.9964150786399841],\"pinky_03_r\":[-0.008727755397558212,0.00023478623188566417,0.01132167037576437,0.9998977780342102],\"ring_01_r\":[0.05214594677090645,-0.3895569145679474,0.2304530292749405,0.890178382396698],\"ring_02_r\":[0.059518661350011826,-0.00033943928428925574,-0.04314512386918068,0.9972943067550659],\"ring_03_r\":[0.05962633714079857,-0.00068375637056306,0.02453024499118328,0.9979191422462463],\"thumb_01_r\":[0.2744263708591461,-0.731201171875,-0.43757393956184387,0.44560524821281433],\"thumb_02_r\":[0.06898587942123413,0.017102878540754318,0.18289531767368317,0.9805599451065063],\"thumb_03_r\":[0.14205099642276764,0.006924070883542299,0.032810747623443604,0.9892911911010742],\"ball_l\":[-0.26220664381980896,0.0072789317928254604,0.029169803485274315,0.964543342590332],\"ball_r\":[-0.26220664381980896,-0.0072789317928254604,-0.029169803485274315,0.964543342590332]},\"spine\":{\"spine_01\":[0.3344581127166748,0,0,0.9424106478691101],\"spine_02\":[-0.10261907428503036,0,0,0.9947206974029541],\"spine_03\":[0.008510730229318142,0,0,0.9999638199806213],\"spine_04\":[0,0,0,1],\"neck_01\":[0.16243939101696014,0,0,0.9867185354232788],\"head\":[-0.20577044785022736,0,0,0.978600263595581]},\"morphs\":{},\"skeletalAmount\":{\"__custom\":1},\"footPins\":{},\"shoes\":false,\"sliders\":{\"gender\":0.5,\"age\":0.5,\"muscle\":0.5,\"weight\":0.5,\"height\":0.5,\"proportions\":0.5,\"african\":0.3333333333333333,\"asian\":0.3333333333333333,\"caucasian\":0.3333333333333333,\"cupsize\":0.5,\"firmness\":0.5,\"breast-trans\":0,\"breast-dist\":0,\"breast-point\":0,\"breast-volume-vert\":0,\"nipple-size\":0,\"nipple-point\":0,\"fem-apple\":0,\"fem-diamond\":0,\"fem-full-hourglass\":0,\"fem-neat-hourglass\":0,\"fem-invert-triangle\":0,\"fem-lean-column\":0,\"fem-rectangle\":0,\"fem-triangle\":0,\"fem-adrenal\":0,\"fem-liver\":0,\"fem-ovary\":0,\"fem-thyroid\":0,\"man-apple\":0,\"man-rectangle\":0,\"man-lean-column\":0,\"man-triangle\":0,\"man-invert-triangle\":0,\"man-trapezoid\":0,\"man-adrenal\":0,\"man-liver\":0,\"man-gonadal\":0,\"man-thyroid\":0,\"torso-scale-depth\":0,\"torso-scale-horiz\":0,\"torso-scale-vert\":0,\"torso-trans-horiz\":0,\"torso-trans-vert\":0,\"torso-trans-depth\":0,\"torso-vshape\":0,\"torso-dorsi\":0,\"torso-pectoral\":0,\"fingers-distance\":0,\"fingers-diameter\":0,\"fingers-length\":0,\"hand-scale\":0,\"hand-position\":0,\"hips\":0,\"glutes\":0,\"stomach\":0,\"neck-circ\":0,\"neck-height\":0,\"head-age\":0,\"head-fat\":0,\"head-angle\":0,\"head-oval\":0,\"head-round\":0,\"head-rectangular\":0,\"head-square\":0,\"head-triangular\":0,\"head-invtriangular\":0,\"head-diamond\":0,\"head-parietal\":0}}],\"props\":[],\"attachments\":[],\"heads\":[{\"box\":[0.1916,0.2178,0.3413,0.3343],\"facing\":0.979},{\"box\":[0.6677,0.2175,0.817,0.3336],\"facing\":0.976}],\"regionEntities\":[{\"kind\":\"figure\",\"name\":\"mannequin1\"},{\"kind\":\"figure\",\"name\":\"mannequin2\"}]}",
+ 832,
+ 1216,
+ ""
+ ],
+ "properties": {
+ "Node name for S&R": "PromptChain_PoseStudio",
+ "pcrOutputMode": "depth",
+ "pcrTrueDepth": true
+ }
+ },
+ {
+ "type": "PreviewImage",
+ "offset": [
+ -945,
+ 0
+ ],
+ "size": [
+ 250,
+ 360
+ ],
+ "widgets_values": [],
+ "properties": {
+ "Node name for S&R": "PreviewImage"
+ }
+ }
+ ],
+ "connections": [
+ {
+ "from_node_idx": 4,
+ "from_slot": 0,
+ "to_node_idx": 0,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 8,
+ "from_slot": 2,
+ "to_node_idx": 0,
+ "to_slot": 2
+ },
+ {
+ "from_node_idx": 8,
+ "from_slot": 1,
+ "to_node_idx": 0,
+ "to_slot": 3
+ },
+ {
+ "from_node_idx": 0,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 0,
+ "from_slot": 1,
+ "to_node_idx": 1,
+ "to_slot": 2
+ },
+ {
+ "from_node_idx": 5,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 6,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 3
+ },
+ {
+ "from_node_idx": 1,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 7,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 2,
+ "from_slot": 0,
+ "to_node_idx": 3,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 8,
+ "from_slot": 0,
+ "to_node_idx": 9,
+ "to_slot": 0
+ }
+ ],
+ "anchorConnections": [
+ {
+ "from_slot": 3,
+ "to_node_idx": 0,
+ "to_slot": 1
+ }
+ ],
+ "id": "krea2-turbo-t2i-3d-regional",
+ "category": "Generation",
+ "order": 2
+}
\ No newline at end of file
diff --git a/data/templates/krea2-turbo-t2i-highdetail.json b/data/templates/krea2-turbo-t2i-highdetail.json
new file mode 100644
index 0000000..d59c50f
--- /dev/null
+++ b/data/templates/krea2-turbo-t2i-highdetail.json
@@ -0,0 +1,246 @@
+{
+ "name": "Text-to-Image (High Detail)",
+ "category": "Generation",
+ "order": 3,
+ "scope": {
+ "type": "family",
+ "architecture": "krea2",
+ "family": "krea2_turbo"
+ },
+ "created_at": 1782362000,
+ "id": "b7c3e8a1-4f2d-4a6b-9c0e-2a1f6d3b9f09",
+ "nodes": [
+ {
+ "type": "CLIPTextEncode",
+ "offset": [
+ 820.0,
+ 20.0
+ ],
+ "size": [
+ 225,
+ 116
+ ],
+ "widgets_values": [
+ ""
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPTextEncode"
+ }
+ },
+ {
+ "type": "KSampler",
+ "offset": [
+ 1440.0,
+ 120.0
+ ],
+ "size": [
+ 330,
+ 474
+ ],
+ "widgets_values": [
+ 826502184750291,
+ "randomize",
+ 8,
+ 1,
+ "euler",
+ "simple",
+ 1
+ ],
+ "properties": {
+ "Node name for S&R": "KSampler"
+ }
+ },
+ {
+ "type": "VAEUtils_VAEDecodeTiled",
+ "offset": [
+ 1800.0,
+ 20.0
+ ],
+ "size": [
+ 300,
+ 220
+ ],
+ "widgets_values": [
+ -1,
+ false,
+ 512,
+ 64,
+ 4096,
+ 64
+ ],
+ "properties": {
+ "Node name for S&R": "VAEUtils_VAEDecodeTiled"
+ }
+ },
+ {
+ "type": "SaveImage",
+ "offset": [
+ 2140.0,
+ -10.0
+ ],
+ "size": [
+ 276.984375,
+ 322.984375
+ ],
+ "widgets_values": [
+ "Krea2/highdetail/%date:yyyy-MM-dd_hhmmss%"
+ ],
+ "properties": {}
+ },
+ {
+ "type": "CLIPLoader",
+ "offset": [
+ 820.0,
+ 240.0
+ ],
+ "size": [
+ 346.78125,
+ 117.328125
+ ],
+ "widgets_values": [
+ "qwen3vl_4b_fp8_scaled.safetensors",
+ "krea2",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPLoader"
+ }
+ },
+ {
+ "type": "UNETLoader",
+ "offset": [
+ 1100.0,
+ 280.0
+ ],
+ "size": [
+ 371.65625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "krea2_turbo_bf16.safetensors",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "UNETLoader"
+ }
+ },
+ {
+ "type": "EmptySD3LatentImage",
+ "offset": [
+ 1100.0,
+ 420.0
+ ],
+ "size": [
+ 324,
+ 144
+ ],
+ "widgets_values": [
+ 1024,
+ 1536,
+ 1
+ ],
+ "properties": {
+ "Node name for S&R": "EmptySD3LatentImage"
+ }
+ },
+ {
+ "type": "VAEUtils_CustomVAELoader",
+ "offset": [
+ 1440.0,
+ 620.0
+ ],
+ "size": [
+ 366.40625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "Wan2.1_VAE_upscale2x_imageonly_real_v1.safetensors",
+ true
+ ],
+ "properties": {
+ "Node name for S&R": "VAEUtils_CustomVAELoader"
+ }
+ },
+ {
+ "type": "ConditioningKrea2Rebalance",
+ "offset": [
+ 1100.0,
+ 20.0
+ ],
+ "size": [
+ 300,
+ 106
+ ],
+ "widgets_values": [
+ 2.0,
+ "1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.6,2.5,1.05,2.0,1.0"
+ ],
+ "properties": {
+ "Node name for S&R": "ConditioningKrea2Rebalance"
+ }
+ }
+ ],
+ "connections": [
+ {
+ "from_node_idx": 0,
+ "from_slot": 0,
+ "to_node_idx": 8,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 8,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 0,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 2
+ },
+ {
+ "from_node_idx": 1,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 7,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 2,
+ "from_slot": 0,
+ "to_node_idx": 3,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 4,
+ "from_slot": 0,
+ "to_node_idx": 0,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 5,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 6,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 3
+ }
+ ],
+ "anchorConnections": [
+ {
+ "from_slot": 1,
+ "to_node_idx": 0,
+ "to_slot": 1
+ }
+ ]
+}
\ No newline at end of file
diff --git a/data/templates/krea2-turbo-t2i.json b/data/templates/krea2-turbo-t2i.json
new file mode 100644
index 0000000..8d7258f
--- /dev/null
+++ b/data/templates/krea2-turbo-t2i.json
@@ -0,0 +1,214 @@
+{
+ "name": "Text-to-Image",
+ "category": "Generation",
+ "order": 0,
+ "scope": {
+ "type": "family",
+ "architecture": "krea2",
+ "family": "krea2_turbo"
+ },
+ "created_at": 1782327800,
+ "id": "b7c3e8a1-4f2d-4a6b-9c0e-2a1f6d3b9e07",
+ "nodes": [
+ {
+ "type": "CLIPTextEncode",
+ "offset": [
+ 899.9999977111815,
+ 0
+ ],
+ "size": [
+ 225,
+ 116
+ ],
+ "widgets_values": [
+ ""
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPTextEncode"
+ }
+ },
+ {
+ "type": "KSampler",
+ "offset": [
+ 1699.9999685974124,
+ 160.0
+ ],
+ "size": [
+ 330,
+ 474
+ ],
+ "widgets_values": [
+ 826502184750291,
+ "randomize",
+ 8,
+ 1,
+ "euler",
+ "simple",
+ 1
+ ],
+ "properties": {
+ "Node name for S&R": "KSampler"
+ }
+ },
+ {
+ "type": "VAEDecode",
+ "offset": [
+ 1750.0000429382326,
+ 20.0
+ ],
+ "size": [
+ 225,
+ 72
+ ],
+ "widgets_values": [],
+ "properties": {
+ "Node name for S&R": "VAEDecode"
+ }
+ },
+ {
+ "type": "SaveImage",
+ "offset": [
+ 2090.0000285339356,
+ -10.0
+ ],
+ "size": [
+ 276.984375,
+ 322.984375
+ ],
+ "widgets_values": [
+ "Krea2/%date:yyyy-MM-dd_hhmmss%"
+ ],
+ "properties": {}
+ },
+ {
+ "type": "CLIPLoader",
+ "offset": [
+ 860.0000519714356,
+ 200.0
+ ],
+ "size": [
+ 346.78125,
+ 117.328125
+ ],
+ "widgets_values": [
+ "qwen3vl_4b_fp8_scaled.safetensors",
+ "krea2",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "CLIPLoader"
+ }
+ },
+ {
+ "type": "UNETLoader",
+ "offset": [
+ 1239.9999069433584,
+ 0
+ ],
+ "size": [
+ 371.65625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "krea2_turbo_fp8_scaled.safetensors",
+ "default"
+ ],
+ "properties": {
+ "Node name for S&R": "UNETLoader"
+ }
+ },
+ {
+ "type": "EmptySD3LatentImage",
+ "offset": [
+ 1249.9999315600576,
+ 200.0
+ ],
+ "size": [
+ 324,
+ 144
+ ],
+ "widgets_values": [
+ 1024,
+ 1536,
+ 1
+ ],
+ "properties": {
+ "Node name for S&R": "EmptySD3LatentImage"
+ }
+ },
+ {
+ "type": "VAELoader",
+ "offset": [
+ 1239.993419293212,
+ 390.0
+ ],
+ "size": [
+ 366.40625,
+ 82.65625
+ ],
+ "widgets_values": [
+ "qwen_image_vae.safetensors"
+ ],
+ "properties": {
+ "Node name for S&R": "VAELoader"
+ }
+ }
+ ],
+ "connections": [
+ {
+ "from_node_idx": 0,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 1
+ },
+ {
+ "from_node_idx": 0,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 2
+ },
+ {
+ "from_node_idx": 1,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 2,
+ "from_slot": 0,
+ "to_node_idx": 3,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 4,
+ "from_slot": 0,
+ "to_node_idx": 0,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 5,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 0
+ },
+ {
+ "from_node_idx": 6,
+ "from_slot": 0,
+ "to_node_idx": 1,
+ "to_slot": 3
+ },
+ {
+ "from_node_idx": 7,
+ "from_slot": 0,
+ "to_node_idx": 2,
+ "to_slot": 1
+ }
+ ],
+ "anchorConnections": [
+ {
+ "from_slot": 1,
+ "to_node_idx": 0,
+ "to_slot": 1
+ }
+ ]
+}
\ No newline at end of file
diff --git a/js/lib/inpaint-background.js b/js/lib/inpaint-background.js
index 143942f..38881b1 100644
--- a/js/lib/inpaint-background.js
+++ b/js/lib/inpaint-background.js
@@ -18,6 +18,7 @@ import { api } from "../../../scripts/api.js";
import { externallyTrackedPrompts, refreshEntryWorkflows, armExternalQueue, disarmExternalQueue } from "./history.js";
import { sourceSavePrefixInfo, fetchSavedUsduSettings, fetchEngineModels, engineAssetSupport, QWEN_ENHANCE_INSTRUCTION, FLUX1_TILE_GUIDANCE } from "./upscale-from-image.js";
import { resolvePre, hasPre } from "./model-settings-bridge.js";
+import { offscreenIdBase } from "./offscreen-graph.js";
function toast(severity, detail) {
app.extensionManager?.toast?.add({ severity, summary: "Inpaint", detail, life: 7000 });
@@ -182,6 +183,7 @@ function inpaintArch(entries) {
if (has("CheckpointLoaderSimple", "CheckpointLoader")) return "sdxl";
const clipType = String(entries.find((n) => n?.class_type === "CLIPLoader")?.inputs?.type || "").toLowerCase();
if (clipType === "flux2") return "flux2";
+ if (clipType === "krea2") return "krea2"; // Krea 2 DiT: UNETLoader+CLIPLoader(type krea2) — must not fall through to flux1 (would mis-wire PuLID)
if (has("DualCLIPLoader") || clipType === "flux" || has("UNETLoader", "UnetLoaderGGUF")) return "flux1";
return "other";
}
@@ -313,7 +315,11 @@ export async function prepareInpaint(entry) {
// (dual clip + flux VAE) are part of that check.
engineModels = (await fetchEngineModels()).filter((m) => m.architecture === "sdxl"
|| (m.architecture === "qwen_edit" && support.qwen)
- || (m.architecture === "flux" && support.flux1));
+ || (m.architecture === "flux" && support.flux1)
+ // Krea 2 DiT: UNETLoader + CLIPLoader(type krea2) + qwen_image VAE, all
+ // self-contained in buildKrea2InpaintPrompt — admit unless the support
+ // probe explicitly reports the krea2 assets absent.
+ || (m.architecture === "krea2" && support.krea2 !== false));
} catch { /* engine list is optional — source surgery still works */ }
if (!sourceUsable && !engineModels.length) {
// Apply would die in buildInpaintPrompt — refuse with the reason up front.
@@ -496,19 +502,34 @@ export function buildInpaintPrompt(apiPrompt, data, options, maskName) {
// VAE: whatever decodes today, else the anchor's own vae input (MaskedDetail
// and USDU carry one; a pruned inpaint graph has no VAEDecode), else the
// checkpoint's.
- const decId = idByClass("VAEDecode");
- const vaeRef = (decId && isLink(graph[decId].inputs.vae) && graph[decId].inputs.vae)
+ const decId = idByClass("VAEDecode", "VAEUtils_VAEDecodeTiled", "VAEDecodeTiled");
+ let vaeRef = (decId && isLink(graph[decId].inputs.vae) && graph[decId].inputs.vae)
|| (isLink(src.inputs.vae) && src.inputs.vae)
|| (ckptId && [ckptId, 2]);
- if (!clipRef || !vaeRef) throw new Error("couldn't trace the clip/vae lines");
+ if (!clipRef) throw new Error("couldn't trace the clip/vae lines");
- let nextId = 1 + Object.keys(graph).reduce((m, id) => Math.max(m, Number.parseInt(id, 10) || 0), 0);
+ // Grafted nodes go far above both the source graph's ids and the live canvas's,
+ // so the background run's execution images never paint onto a live node.
+ let nextId = offscreenIdBase();
const add = (class_type, inputs) => {
const id = String(nextId++);
graph[id] = { class_type, inputs };
return id;
};
+ // The traced VAE may be a decode-only/2x custom loader (the spacepxl VAEUtils
+ // decoder on High-Detail krea2 renders) that CAN'T encode — inpaint needs both
+ // encode and decode. If the trace failed or landed on that custom loader,
+ // graft a fresh stock VAELoader on the shared krea2/qwen latent (prefer
+ // qwen_image_vae, else the clean wan_2.1_vae).
+ const tracedVae = isLink(vaeRef) ? graph[String(vaeRef[0])] : null;
+ if (!vaeRef || (tracedVae && tracedVae.class_type === "VAEUtils_CustomVAELoader")) {
+ const vaeName = probeComboValue("VAELoader", "vae_name", (o) => /qwen.*image.*vae/i.test(o))
+ || probeComboValue("VAELoader", "vae_name", (o) => /wan.*2[._]?1.*vae/i.test(o) && !/upscale|2x/i.test(o));
+ if (!vaeName) throw new Error("couldn't trace the clip/vae lines");
+ vaeRef = [add("VAELoader", { vae_name: vaeName }), 0];
+ }
+
const loadId = add("LoadImage", { image: data.input_ref });
const maskId = add("LoadImageMask", { image: maskName, channel: "red" });
const pcId = add("PromptChain_PromptChain", {
@@ -583,8 +604,8 @@ export function buildInpaintPrompt(apiPrompt, data, options, maskName) {
image: [loadId, 0], mask: [maskId, 0],
positive: posRef, negative: negRef,
seed: Math.floor(Math.random() * 0xffffffffff),
- steps: lit(src.inputs.steps) ?? 20,
- cfg: lit(src.inputs.cfg) ?? 7,
+ steps: numOr(options.steps, lit(src.inputs.steps) ?? 20),
+ cfg: numOr(options.cfg, lit(src.inputs.cfg) ?? 7),
sampler_name: options.sampler || lit(src.inputs.sampler_name) || "euler",
scheduler: options.scheduler || lit(src.inputs.scheduler) || "normal",
denoise: typeof options.denoise === "number" ? options.denoise : 0.5,
@@ -626,7 +647,7 @@ export function buildInpaintEnginePrompt(data, options, maskName) {
const filename = options.engineModel?.filename;
if (!filename) throw new Error("no engine model picked");
const graph = {};
- let nextId = 1;
+ let nextId = offscreenIdBase(); // render-node ids must stay off the live canvas — else execution images paint onto a live node sharing the id (see offscreen-graph.js)
const add = (class_type, inputs) => {
const id = String(nextId++);
graph[id] = { class_type, inputs };
@@ -656,8 +677,8 @@ export function buildInpaintEnginePrompt(data, options, maskName) {
image: [loadId, 0], mask: [maskId, 0],
positive: [posId, 0], negative: [negId, 0],
seed: Math.floor(Math.random() * 0xffffffffff),
- steps: numOr(gen.steps, 25),
- cfg: numOr(gen.cfg, 5),
+ steps: numOr(options.steps, numOr(gen.steps, 25)),
+ cfg: numOr(options.cfg, numOr(gen.cfg, 5)),
sampler_name: options.sampler || gen.sampler || "dpmpp_2m",
scheduler: options.scheduler || gen.scheduler || "karras",
denoise: typeof options.denoise === "number" ? options.denoise : 0.5,
@@ -690,7 +711,7 @@ export function buildFlux1InpaintPrompt(data, options, maskName) {
if (!clipL || !t5 || !vaeFile) throw new Error("the FLUX text encoders / VAE aren't installed");
const graph = {};
- let nextId = 1;
+ let nextId = offscreenIdBase(); // render-node ids must stay off the live canvas — else execution images paint onto a live node sharing the id (see offscreen-graph.js)
const add = (class_type, inputs) => {
const id = String(nextId++);
graph[id] = { class_type, inputs };
@@ -716,7 +737,7 @@ export function buildFlux1InpaintPrompt(data, options, maskName) {
image: [loadId, 0], mask: [maskId, 0],
positive: [guidId, 0], negative: [negId, 0],
seed: Math.floor(Math.random() * 0xffffffffff),
- steps: numOr(gen.steps, 25),
+ steps: numOr(options.steps, numOr(gen.steps, 25)),
// cfg pinned, never inherited — a gen cfg would double sampling and burn.
cfg: 1.0,
sampler_name: options.sampler || gen.sampler || "euler",
@@ -730,6 +751,82 @@ export function buildFlux1InpaintPrompt(data, options, maskName) {
return { graph, detailId };
}
+// KREA 2 engine inpaint: a DiT that wires like FLUX.1 through the same
+// MaskedDetail crop path, minus FLUX's guidance regime. Shift is baked into the
+// model class (no ModelSampling) and it's cfg-native (no FluxGuidance), so the
+// UNET feeds the sampler straight and the empty negative is just the required
+// input — cfg is pinned 1.0, the same inert-negative posture as flux1/zimage.
+// Self-contained loaders (UNET + single CLIPLoader(type krea2) + qwen_image VAE)
+// mean an imported/arbitrary image needs no embedded render data. guide_size
+// 1024 / max_size 1536: krea2's native working res, matching the flux1 crop.
+export function buildKrea2InpaintPrompt(data, options, maskName) {
+ const filename = options.engineModel?.filename;
+ if (!filename) throw new Error("no engine model picked");
+ // Resolve the actual installed encoder/VAE (mirrors the flux1 builder + the krea2
+ // tile stage) so a differently-named file still binds and a missing one fails early.
+ const probe = (type, widget) => {
+ try {
+ const node = window.LiteGraph?.createNode?.(type);
+ return node?.widgets?.find((w) => w.name === widget)?.options?.values || [];
+ } catch { return []; }
+ };
+ const clipOpts = probe("CLIPLoader", "clip_name");
+ const clipFile = clipOpts.find((o) => /qwen3vl.*4b/i.test(o)) || clipOpts.find((o) => /qwen3.?vl.*4b/i.test(o));
+ const vaeFile = probe("VAELoader", "vae_name").find((o) => /qwen.*image.*vae/i.test(o));
+ if (!clipFile || !vaeFile) throw new Error("the Krea 2 text encoder / VAE aren't installed");
+
+ const graph = {};
+ let nextId = offscreenIdBase(); // render-node ids must stay off the live canvas — else execution images paint onto a live node sharing the id (see offscreen-graph.js)
+ const add = (class_type, inputs) => {
+ const id = String(nextId++);
+ graph[id] = { class_type, inputs };
+ return id;
+ };
+ const unetId = add("UNETLoader", { unet_name: filename, weight_dtype: "default" });
+ const clipId = add("CLIPLoader", { clip_name: clipFile, type: "krea2", device: "default" });
+ const vaeId = add("VAELoader", { vae_name: vaeFile });
+ const loadId = add("LoadImage", { image: data.input_ref });
+ const maskId = add("LoadImageMask", { image: maskName, channel: "red" });
+ const pcId = add("PromptChain_PromptChain", {
+ prompt: options.prompt || "", mode: "combine", switch_index: 1,
+ locked: false, disabled: false, cached_output: "", cached_neg_output: "",
+ iterate_index: 0, iterate_cycle: 1, collapsed: false,
+ wildcard_modes: "", cached_regions: "",
+ });
+ const posId = add("CLIPTextEncode", { text: [pcId, 1], clip: [clipId, 0] });
+ // Dummy negative: cfg is pinned 1.0 so it never influences sampling, but
+ // MaskedDetail requires the input — the UNET feeds the sampler straight
+ // (no ModelSampling, no FluxGuidance).
+ const negId = add("CLIPTextEncode", { text: [pcId, 2], clip: [clipId, 0] });
+ // RAW is the undistilled base: it needs full steps + a real cfg + the resolution
+ // shift, NOT Turbo's 8-step / cfg-1 / no-shift recipe (which under-resolves it and
+ // over-shifts → melted faces). The crop samples at guide_size 1024, so a static
+ // 1024 ModelSamplingFlux is correct here. Turbo keeps its pinned fast recipe.
+ const raw = /krea2_raw/i.test(filename);
+ let modelRef = [unetId, 0];
+ if (raw) {
+ const msfId = add("ModelSamplingFlux", { model: [unetId, 0], max_shift: 0.90625, base_shift: 0.5, width: 1024, height: 1024 });
+ modelRef = [msfId, 0];
+ }
+ const detailId = add("PromptChain_MaskedDetail", {
+ model: modelRef, vae: [vaeId, 0],
+ image: [loadId, 0], mask: [maskId, 0],
+ positive: [posId, 0], negative: [negId, 0],
+ seed: Math.floor(Math.random() * 0xffffffffff),
+ // Defaults are RAW/Turbo-aware but overridable from the modal (steps/cfg/sampler).
+ steps: numOr(options.steps, raw ? 30 : 8),
+ cfg: numOr(options.cfg, raw ? 3.5 : 1.0),
+ sampler_name: options.sampler || (raw ? "er_sde" : "euler"),
+ scheduler: options.scheduler || (raw ? "beta" : "simple"),
+ denoise: typeof options.denoise === "number" ? options.denoise : 0.5,
+ guide_size: 1024, max_size: 1536, crop_factor: 2.0,
+ feather: numOr(options.feather, 24), grow: numOr(options.grow, 0),
+ });
+ add("PreviewImage", { images: [detailId, 0] });
+ console.log("[PromptChain][inpaint] built krea2 engine prompt:", JSON.stringify(graph, null, 2));
+ return { graph, detailId };
+}
+
const round8 = (v) => Math.max(8, Math.round(v / 8) * 8);
// Crop window around the painted mask: bbox grown 2× (MaskedDetail's
@@ -785,7 +882,7 @@ export function buildQwenEditInpaintPrompt(data, options, maskName) {
const scaled = qwenWorkingSize(crop.w, crop.h);
const graph = {};
- let nextId = 1;
+ let nextId = offscreenIdBase(); // render-node ids must stay off the live canvas — else execution images paint onto a live node sharing the id (see offscreen-graph.js)
const add = (class_type, inputs) => {
const id = String(nextId++);
graph[id] = { class_type, inputs };
@@ -834,8 +931,8 @@ export function buildQwenEditInpaintPrompt(data, options, maskName) {
const samplerId = add("KSampler", {
model: [normId, 0], positive: [refPosId, 0], negative: [refNegId, 0], latent_image: [noisedId, 0],
seed: Math.floor(Math.random() * 0xffffffffff),
- steps: numOr(gen.steps, 40),
- cfg: numOr(gen.cfg, 4),
+ steps: numOr(options.steps, numOr(gen.steps, 40)),
+ cfg: numOr(options.cfg, numOr(gen.cfg, 4)),
sampler_name: options.sampler || gen.sampler || "euler",
scheduler: options.scheduler || gen.scheduler || "simple",
// 1.0 is structural: partial denoise blends the shifted re-render; full
@@ -912,9 +1009,11 @@ export function runInpaint(prepared, options = {}) {
? buildQwenEditInpaintPrompt(data, options, maskName)
: options.engine === "flux1-unet" && options.engineModel
? buildFlux1InpaintPrompt(data, options, maskName)
- : options.engine === "sdxl-ckpt" && options.engineModel
- ? buildInpaintEnginePrompt(data, options, maskName)
- : buildInpaintPrompt(data.prompt, data, options, maskName);
+ : options.engine === "krea2-unet" && options.engineModel
+ ? buildKrea2InpaintPrompt(data, options, maskName)
+ : options.engine === "sdxl-ckpt" && options.engineModel
+ ? buildInpaintEnginePrompt(data, options, maskName)
+ : buildInpaintPrompt(data.prompt, data, options, maskName);
} catch (e) {
console.error("[PromptChain][inpaint] build failed (rev abc3dbbd+):", e);
tracker.emit({ phase: "error", message: `build failed: ${e.message}` });
diff --git a/js/lib/krea2-shift-sync.js b/js/lib/krea2-shift-sync.js
new file mode 100644
index 0000000..dcea67d
--- /dev/null
+++ b/js/lib/krea2-shift-sync.js
@@ -0,0 +1,103 @@
+// Krea 2 RAW uses a resolution-dynamic flow-shift: the ModelSamplingFlux node's
+// width/height decide mu, and they MUST match the actual render resolution or the
+// shift is mis-applied — a 1024² shift on an 832×1024 render over-shifts mu ~10%
+// and compresses the detail tail (the same failure mode the node exists to fix,
+// milder). The model Settings resolution row mirrors this live for t2i, but that
+// misses i2i (size comes from the loaded image — there is no resolution row) and
+// any graph whose resolution was set on-canvas or loaded from disk. So re-derive
+// every krea2_raw ModelSamplingFlux's width/height from its true render size just
+// before each queue — the one chokepoint that catches all cases. Event-driven on
+// the queue (not a timer). No-op for any graph without a krea2_raw shift node.
+
+import { app } from "../../../scripts/app.js";
+import { getLink } from "./slot-utils.js";
+
+const SHIFT_TYPE = "ModelSamplingFlux";
+const LATENT_DIM_TYPES = new Set(["EmptySD3LatentImage", "EmptyLatentImage", "EmptyFlux2LatentImage"]);
+const IMAGE_TYPES = new Set(["LoadImage"]);
+
+// Nearest ancestor of `startNode` (walking input links) whose class is in `types`.
+function findUpstreamByType(startNode, types) {
+ const graph = startNode?.graph || app.graph;
+ if (!graph || !startNode) return null;
+ const visited = new Set();
+ const queue = [startNode];
+ while (queue.length) {
+ const n = queue.shift();
+ if (!n || visited.has(n.id)) continue;
+ visited.add(n.id);
+ for (const input of n.inputs || []) {
+ if (input.link == null) continue;
+ const link = getLink(graph, input.link);
+ if (!link) continue;
+ const src = graph.getNodeById(link.origin_id);
+ if (!src) continue;
+ if (types.has(src.comfyClass)) return src;
+ queue.push(src);
+ }
+ }
+ return null;
+}
+
+function widgetValue(node, name) {
+ return node?.widgets?.find((w) => w.name === name)?.value;
+}
+
+function setWidget(node, name, value) {
+ const w = node?.widgets?.find((x) => x.name === name);
+ if (!w || w.value === value) return;
+ w.value = value;
+ w.callback?.(value);
+}
+
+// The render resolution feeding a sampler: the latent node's width/height widgets
+// (t2i), or — when the latent is encoded from an input image and has no such
+// widgets (i2i) — the loaded image's natural pixel dimensions.
+function samplerResolution(samplerNode) {
+ const latent = findUpstreamByType(samplerNode, LATENT_DIM_TYPES);
+ if (latent) {
+ const w = widgetValue(latent, "width");
+ const h = widgetValue(latent, "height");
+ if (typeof w === "number" && typeof h === "number") return { width: w, height: h };
+ }
+ const img = findUpstreamByType(samplerNode, IMAGE_TYPES)?.imgs?.[0];
+ if (img?.naturalWidth) return { width: img.naturalWidth, height: img.naturalHeight };
+ return null;
+}
+
+// Scope the sync to Krea 2 RAW: only its UNET wants a resolution-tracking shift.
+// Turbo bakes a fixed mu (and carries no shift node); Flux's shift is its own
+// concern. Gating on the upstream UNET filename keeps every other arch untouched.
+function isKrea2RawShift(shiftNode) {
+ const name = widgetValue(findUpstreamByType(shiftNode, new Set(["UNETLoader"])), "unet_name");
+ return typeof name === "string" && /krea2_raw/i.test(name);
+}
+
+// Re-derive every krea2_raw ModelSamplingFlux's width/height from its render size.
+export function syncShiftNodes() {
+ const graph = app?.graph;
+ if (!graph) return;
+ for (const sampler of graph._nodes || []) {
+ const cls = sampler.comfyClass || sampler.type || "";
+ if (!cls.includes("KSampler") || cls === "KSamplerSelect") continue;
+ const shift = findUpstreamByType(sampler, new Set([SHIFT_TYPE]));
+ if (!shift || !isKrea2RawShift(shift)) continue;
+ const res = samplerResolution(sampler);
+ if (!res) continue;
+ const before = `${widgetValue(shift, "width")}×${widgetValue(shift, "height")}`;
+ setWidget(shift, "width", res.width);
+ setWidget(shift, "height", res.height);
+ const after = `${res.width}×${res.height}`;
+ if (before !== after) console.log(`[PromptChain] krea2 RAW shift synced ${before} → ${after}`);
+ }
+}
+
+// Wrap queuePrompt so the shift is corrected for the live graph before it serializes.
+export function setupShiftSync() {
+ const orig = app.queuePrompt?.bind(app);
+ if (!orig) return;
+ app.queuePrompt = async function (...args) {
+ try { syncShiftNodes(); } catch (e) { console.warn("[PromptChain] krea2 shift-sync skipped:", e); }
+ return orig(...args);
+ };
+}
diff --git a/js/lib/model-settings-bridge.js b/js/lib/model-settings-bridge.js
index c9a6368..67478f9 100644
--- a/js/lib/model-settings-bridge.js
+++ b/js/lib/model-settings-bridge.js
@@ -508,6 +508,16 @@ function findUpstreamByType(startNode, targetTypes) {
return null;
}
+// A ModelSamplingFlux belongs to a Krea 2 RAW graph when its model line traces up
+// to a krea2_raw UNET. Keeps the resolution→shift mirror scoped to RAW (Turbo bakes
+// a fixed mu; Flux owns its own shift), so only RAW's shift node is slaved.
+function isKrea2RawShift(shiftNode) {
+ const unet = findUpstreamByType(shiftNode, new Set(["UNETLoader"]));
+ if (!unet) return false;
+ const name = readWidgetValue(unet, "unet_name");
+ return typeof name === "string" && /krea2_raw/i.test(name);
+}
+
// The face-detail leg of a model-patch injectable (PuLID / Style Reference) is a
// second Apply node feeding the RegionalDetailer's couple-free model line. It's
// an implementation detail, not its own tunable — the settings panel shows one
@@ -668,6 +678,17 @@ export function detectSupportedNodes(pcNode) {
detected.push({ node: latentNode, config: LATENT_NODES[cls], type: cls });
}
+ // Krea 2 RAW's ModelSamplingFlux sets the resolution-dynamic flow-shift (mu),
+ // whose width/height MUST track the render size. Detected only so the resolution
+ // row can slave its width/height to the latent — mirrorOnly: no visible section
+ // and never written into editors, so it is never baked back into the saved
+ // config (the shift must stay dynamic). Gated to RAW (see isKrea2RawShift).
+ const shiftNode = findUpstreamByType(pivotNode, new Set(["ModelSamplingFlux"]));
+ if (shiftNode && !seenIds.has(shiftNode.id) && isKrea2RawShift(shiftNode)) {
+ seenIds.add(shiftNode.id);
+ detected.push({ node: shiftNode, config: { label: "Shift", widgets: {}, mirrorOnly: true }, type: "ModelSamplingFlux" });
+ }
+
const pulidTypes = new Set(["ApplyPulidAdvanced", "ApplyPulid", "ApplyPulidFlux", "ApplyPuLIDFlux2"]);
const pulidNode = findUpstreamByType(pivotNode, pulidTypes);
if (pulidNode && !seenIds.has(pulidNode.id)) {
@@ -746,6 +767,15 @@ function applyArchSamplerDefaults(defaults, architecture, family) {
// high-σ regime where tiles come out clean (heavier repaint is the trade).
if ("denoise" in defaults) defaults.denoise = 0.7;
}
+ } else if (arch === "krea2") {
+ // Krea 2 Turbo: distilled 8-step, guidance baked (cfg 1), euler/simple. Qwen-family
+ // is quant/prompt-sensitive, so a tile re-render wants a higher denoise floor than
+ // Z-Image-Base to avoid underbaking the few-step tail (GPU-tunable).
+ defaults.cfg = 1.0;
+ defaults.sampler_name = "euler";
+ defaults.scheduler = "simple";
+ if ("steps" in defaults) defaults.steps = 8;
+ if ("denoise" in defaults) defaults.denoise = 0.45;
}
}
@@ -1260,9 +1290,13 @@ export function injectUpscaler(pcNode, modelConfig, opts = {}) {
// exists (regional or classic), else straight off the decode.
const detailNode = downstream.find(n => n.comfyClass === "PromptChain_RegionalDetailer")
|| downstream.find(n => n.comfyClass === "FaceDetailer");
- const vaeDecodeNode = downstream.find(n => n.comfyClass === "VAEDecode");
+ const vaeDecodeNode = downstream.find(n => n.comfyClass === "VAEDecode"
+ || n.comfyClass === "VAEUtils_VAEDecodeTiled" || n.comfyClass === "VAEDecodeTiled");
const imageSource = detailNode || vaeDecodeNode;
- if (!imageSource) return false;
+ if (!imageSource) {
+ console.warn(`[PromptChain][graft] FAIL: no decode/detail image source. downstream=[${downstream.map((n) => n.comfyClass).join(",")}]`);
+ return false;
+ }
// Sampler anchor: classic KSampler graphs, or the Flux 2 split where
// SamplerCustomAdvanced samples and a guider (CFGGuider on Klein base,
@@ -1357,6 +1391,24 @@ export function injectUpscaler(pcNode, modelConfig, opts = {}) {
}
splitModelNode = ms;
splitVaeNode = findUpstreamByType(vaeDecodeNode, new Set(["VAELoader"]));
+ if (!splitVaeNode) {
+ // The source decodes through a custom/tiled VAE (e.g. the spacepxl
+ // VAEUtils decoder on High-Detail krea2 renders) whose 2x/12-ch output
+ // can't drive USDU's encode->sample->decode tiling. Graft a fresh stock
+ // VAELoader on the shared krea2/qwen latent — prefer the clean wan_2.1_vae
+ // (no grid artifact), else qwen_image_vae, else whatever is installed.
+ const freshVae = LG.createNode("VAELoader");
+ const vaeW = freshVae?.widgets?.find(w => w.name === "vae_name");
+ const vaeOpts = vaeW?.options?.values || [];
+ const pick = vaeOpts.find(o => /wan.*2[._]?1.*vae/i.test(o) && !/upscale|2x/i.test(o))
+ || vaeOpts.find(o => /qwen.*image.*vae/i.test(o)) || vaeOpts[0];
+ if (freshVae && vaeW && pick) {
+ vaeW.value = pick; vaeW.callback?.(pick);
+ freshVae.pos = [vaeDecodeNode.pos[0], vaeDecodeNode.pos[1] + 220];
+ graph.add(freshVae);
+ splitVaeNode = freshVae;
+ }
+ }
}
const loaderNode = LG.createNode("UpscaleModelLoader");
@@ -1847,7 +1899,7 @@ function injectRegional(pcNode, modelConfig) {
// $blocks cohere into ONE scene). Other DiTs (Flux/SD3/…) have no ported couple yet, so
// they fall back to ComfyUI-native masked conditioning here.
const arch = modelConfig?.architecture || "";
- const NATIVE_REGIONAL_ARCH = new Set(["flux", "flux2", "sd3", "hidream", "qwen_image", "qwen_edit"]);
+ const NATIVE_REGIONAL_ARCH = new Set(["flux", "flux2", "sd3", "hidream", "qwen_image", "qwen_edit", "krea2"]);
if (NATIVE_REGIONAL_ARCH.has(arch)) {
const rc = LG.createNode("PromptChain_RegionalConditioning");
if (!rc) return false;
@@ -2873,6 +2925,17 @@ export async function showModelModal(pcNode, modelInfo, anchorEl, { tab = null }
],
});
}
+ // Krea 2 has no published ControlNet (and ComfyUI's krea2 model class exposes
+ // no control hook), but native cond-mask regional works — PromptChain_RegionalConditioning
+ // is model-agnostic. Offer Regional only.
+ if (arch === "krea2") {
+ items.push({
+ label: "ControlNet",
+ children: [
+ { label: "Regional", value: "ControlNet:regional" },
+ ],
+ });
+ }
// Z-Image ControlNet (DiffSynth model-patch path; core nodes + aux
// preprocessors). The control model is family-specific: Turbo's is
// step-distilled, base's isn't, and they're NOT cross-compatible — so a
diff --git a/js/lib/svelte/promptchain-model-settings.js b/js/lib/svelte/promptchain-model-settings.js
index 535d3a8..1ac1bd8 100644
--- a/js/lib/svelte/promptchain-model-settings.js
+++ b/js/lib/svelte/promptchain-model-settings.js
@@ -384,14 +384,19 @@ function SettingsTab($$anchor, $$props) {
if (!get(editors)[nodeType]) get(editors)[nodeType] = {};
get(editors)[nodeType][widgetName] = val;
}
- function mirrorIdeogramScheduler(latentNode) {
- const sched = detected().find((d) => d.type === "Ideogram4Scheduler");
- if (!sched) return;
- for (const dim of ["width", "height"]) {
- const v = $$props.readWidgetValue(latentNode, dim);
- if (v !== void 0) {
- $$props.writeWidgetValue(sched.node, dim, v);
- setEditorValue("Ideogram4Scheduler", dim, v);
+ const RES_DEPENDENTS = [
+ { type: "Ideogram4Scheduler", persist: true },
+ { type: "ModelSamplingFlux", persist: false }
+ ];
+ function mirrorResolutionDependents(latentNode) {
+ for (const { type: depType, persist } of RES_DEPENDENTS) {
+ const dep = detected().find((d) => d.type === depType);
+ if (!dep) continue;
+ for (const dim of ["width", "height"]) {
+ const v = $$props.readWidgetValue(latentNode, dim);
+ if (v === void 0) continue;
+ $$props.writeWidgetValue(dep.node, dim, v);
+ if (persist) setEditorValue(depType, dim, v);
}
}
}
@@ -484,7 +489,10 @@ function SettingsTab($$anchor, $$props) {
});
}
var node_2 = sibling(node_1, 2);
- each(node_2, 17, detected, index, ($$anchor2, $$item) => {
+ each(node_2, 17, () => detected().filter((d) => {
+ var _a2;
+ return !((_a2 = d.config) == null ? void 0 : _a2.mirrorOnly);
+ }), index, ($$anchor2, $$item) => {
let node = () => get($$item).node;
let config = () => get($$item).config;
let type = () => get($$item).type;
@@ -634,7 +642,7 @@ function SettingsTab($$anchor, $$props) {
$$props.writeWidgetValue(node(), "height", get(p).height);
setEditorValue(type(), "width", get(p).width);
setEditorValue(type(), "height", get(p).height);
- mirrorIdeogramScheduler(node());
+ mirrorResolutionDependents(node());
presetMenuOpen[type()] = false;
});
delegated("click", span_2, (e) => {
@@ -702,13 +710,13 @@ function SettingsTab($$anchor, $$props) {
const v = parseInt(e.target.value) || 512;
setEditorValue(type(), "width", v);
$$props.writeWidgetValue(node(), "width", v);
- mirrorIdeogramScheduler(node());
+ mirrorResolutionDependents(node());
});
delegated("change", input_2, (e) => {
const v = parseInt(e.target.value) || 512;
setEditorValue(type(), "height", v);
$$props.writeWidgetValue(node(), "height", v);
- mirrorIdeogramScheduler(node());
+ mirrorResolutionDependents(node());
});
append($$anchor5, div_6);
};
diff --git a/js/lib/svelte/promptchain-viewer.js b/js/lib/svelte/promptchain-viewer.js
index 28f0a12..fbf0562 100644
--- a/js/lib/svelte/promptchain-viewer.js
+++ b/js/lib/svelte/promptchain-viewer.js
@@ -570,7 +570,7 @@ function SearchableSelect($$anchor, $$props) {
delegate(["click", "keydown"]);
var root_2$8 = from_html(``);
var root_3$8 = from_html(``);
-var root_5$7 = from_html(`
This image has no usable prompt metadata — a plain model upscale (ESRGAN) will be used.
`); +var root_14$6 = from_html(`No re-detail engine is available for this image — a plain model upscale (ESRGAN) will be used.
`); var root_16$5 = from_html(` `); var root_17$4 = from_html(`re-renders the whole frame at ~2MP from your instruction — composition can shift slightly; the climb model below pushes to the target size`); var root_18$4 = from_html(`deterministic enlargement with the climb model below — add a Restore step for degraded sources (webcam, jpeg, blur)`); @@ -588,16 +588,16 @@ var root_15$5 = from_html(`- This image has no usable prompt metadata — a plain model upscale (ESRGAN) will be used. + No re-detail engine is available for this image — a plain model upscale (ESRGAN) will be used.
{/if} {#if engineChoices > 1} @@ -792,6 +822,8 @@ ? "the climb model below pushes to the target, then this FLUX.1 model re-details every tile with the prompt below — low denoise holds structure without a ControlNet" : engineKind === "zimage" ? "the climb model below pushes to the target, then this Z-Image model re-details every tile with the prompt below — Base holds structure at low denoise; Turbo (distilled) needs ~0.7 or it blotches" + : engineKind === "krea2" + ? "the climb model below pushes to the target, then this Krea 2 model re-details every tile with the prompt below — distilled turbo re-detail at moderate denoise, no ControlNet" : "the climb model below pushes to the target, then this checkpoint re-details every tile (structure locked by a tile ControlNet) with the prompt below"} {:else if engineKind === "qwen"} @@ -861,7 +893,7 @@ {/if}