Added nodes TT_SdxlModelsLoaderNode, TT_SdxlModelsLoaderAdvancedNode, TT_FluxModelsLoaderNode, TT_FluxModelsLoaderAdvancedNode, minor bugfixes and refactoring, added docs, changed version
This commit is contained in:
@@ -178,6 +178,8 @@ NODE_CLASS_MAPPINGS = {
|
||||
"TT_SdxlModelsLoaderAdvancedNode": TT_SdxlModelsLoaderAdvancedNode,
|
||||
"TT_FluxModelsLoaderNode": TT_FluxModelsLoaderNode,
|
||||
"TT_FluxModelsLoaderAdvancedNode": TT_FluxModelsLoaderAdvancedNode,
|
||||
"TT_GgufModelsLoaderNode": TT_GgufModelsLoaderNode,
|
||||
"TT_GgufModelsLoaderAdvancedNode": TT_GgufModelsLoaderAdvancedNode,
|
||||
# Postproduction
|
||||
"TT_ApplyLut": TT_ApplyLut,
|
||||
"TT_AddFilmGrain": TT_AddFilmGrain,
|
||||
@@ -278,6 +280,8 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"TT_SdxlModelsLoaderAdvancedNode": "TT SDXL Models Loader (Advanced)",
|
||||
"TT_FluxModelsLoaderNode": "TT FLUX Models Loader",
|
||||
"TT_FluxModelsLoaderAdvancedNode": "TT FLUX Models Loader (Advanced)",
|
||||
"TT_GgufModelsLoaderNode": "TT GGUF Models Loader",
|
||||
"TT_GgufModelsLoaderAdvancedNode": "TT GGUF Models Loader (Advanced)",
|
||||
# Postproduction
|
||||
"TT_ApplyLut": "TT Apply LUT",
|
||||
"TT_AddFilmGrain": "TT Add Film Grain",
|
||||
|
||||
@@ -28,7 +28,7 @@ class TT_Flux2GgufModelsLoader():
|
||||
RETURN_TYPES = ("MODEL", "CLIP", "VAE",)
|
||||
RETURN_NAMES = ("MODEL", "CLIP", "VAE",)
|
||||
FUNCTION = "load_models"
|
||||
CATEGORY = "TenserTensor/Loaders/FLUX2 GGUF"
|
||||
CATEGORY = "TenserTensor/Deprecated/Loaders/FLUX2 GGUF"
|
||||
|
||||
VAE_DEVICE = "cpu"
|
||||
VAE_DTYPE = "bfloat16"
|
||||
|
||||
@@ -55,7 +55,7 @@ class TT_Flux2GgufModelsLoaderAdvanced():
|
||||
RETURN_TYPES = ("MODEL", "CLIP", "VAE",)
|
||||
RETURN_NAMES = ("MODEL", "CLIP", "VAE",)
|
||||
FUNCTION = "load_models"
|
||||
CATEGORY = "TenserTensor/Loaders/FLUX2 GGUF"
|
||||
CATEGORY = "TenserTensor/Deprecated/Loaders/FLUX2 GGUF"
|
||||
|
||||
def load_models(self, **kwargs):
|
||||
model = load_unet(
|
||||
|
||||
+282
-1
@@ -1,13 +1,26 @@
|
||||
# (c) TenserTensor <tenser.tensor@proton.me> || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
# Contains slightly modified code by City96
|
||||
# (c) City96 || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
# Modified by TenserTensor
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import collections
|
||||
import inspect
|
||||
import logging
|
||||
import os
|
||||
from typing import override
|
||||
|
||||
import torch
|
||||
from torch import bfloat16, float16, float32, float8_e4m3fn, float8_e5m2, device, tensor
|
||||
|
||||
import folder_paths
|
||||
from comfy import sd, model_management, utils, model_sampling
|
||||
from comfy import sd, model_management, utils, model_sampling, model_patcher, lora, float
|
||||
from comfy_api.latest import io, ComfyExtension
|
||||
from nodes import VAELoader, MAX_RESOLUTION
|
||||
from .gguf.dequant import is_quantized, is_torch_compatible
|
||||
from .gguf.loader import gguf_sd_loader, gguf_clip_loader
|
||||
from .gguf.ops import GGMLOps, move_patch_to_device
|
||||
|
||||
CATEGORY = "TenserTensor/Loaders"
|
||||
TORCH_DEVICES = ["default", "cpu"]
|
||||
@@ -27,10 +40,22 @@ def get_diffusion_models_files():
|
||||
return folder_paths.get_filename_list("diffusion_models")
|
||||
|
||||
|
||||
def get_gguf_diffusion_models_files():
|
||||
update_folder_names_and_paths("unet_gguf", ["diffusion_models", "unet"])
|
||||
|
||||
return [f for f in folder_paths.get_filename_list("unet_gguf")]
|
||||
|
||||
|
||||
def get_text_encoder_files():
|
||||
return folder_paths.get_filename_list("text_encoders")
|
||||
|
||||
|
||||
def get_gguf_text_encoder_files():
|
||||
update_folder_names_and_paths("clip_gguf", ["text_encoders", "clip"])
|
||||
|
||||
return [x for x in folder_paths.get_filename_list("clip_gguf")]
|
||||
|
||||
|
||||
def get_vae_files():
|
||||
return VAELoader.vae_list(VAELoader)
|
||||
|
||||
@@ -380,6 +405,258 @@ class TT_FluxModelsLoaderAdvancedNode(io.ComfyNode):
|
||||
return io.NodeOutput(model, clip, vae)
|
||||
|
||||
|
||||
def update_folder_names_and_paths(key, targets=[]):
|
||||
base = folder_paths.folder_names_and_paths.get(key, ([], {}))
|
||||
base = base[0] if isinstance(base[0], (list, set, tuple)) else []
|
||||
|
||||
target = next((x for x in targets if x in folder_paths.folder_names_and_paths), targets[0])
|
||||
orig, _ = folder_paths.folder_names_and_paths.get(target, ([], {}))
|
||||
folder_paths.folder_names_and_paths[key] = (orig or base, {".gguf"})
|
||||
if base and base != orig:
|
||||
logging.warning(f"Unknown file list already present on key {key}: {base}")
|
||||
|
||||
|
||||
WeightBackup = collections.namedtuple('WeightBackup', ['weight', 'inplace_update'])
|
||||
|
||||
|
||||
class GGUFModelPatcher(model_patcher.ModelPatcher):
|
||||
patch_on_device = False
|
||||
|
||||
def patch_weight_to_device(self, key, device_to=None, inplace_update=False):
|
||||
if key not in self.patches:
|
||||
return
|
||||
|
||||
weight = utils.get_attr(self.model, key)
|
||||
|
||||
patches = self.patches[key]
|
||||
if is_quantized(weight):
|
||||
out_weight = weight.to(device_to)
|
||||
patches = move_patch_to_device(patches, self.load_device if self.patch_on_device else self.offload_device)
|
||||
# TODO: do we ever have legitimate duplicate patches? (i.e. patch on top of patched weight)
|
||||
out_weight.patches = [(patches, key)]
|
||||
else:
|
||||
inplace_update = self.weight_inplace_update or inplace_update
|
||||
if key not in self.backup:
|
||||
self.backup[key] = WeightBackup(
|
||||
weight.to(device=self.offload_device, copy=inplace_update), inplace_update
|
||||
)
|
||||
|
||||
if device_to is not None:
|
||||
temp_weight = model_management.cast_to_device(weight, device_to, torch.float32, copy=True)
|
||||
else:
|
||||
temp_weight = weight.to(torch.float32, copy=True)
|
||||
|
||||
out_weight = lora.calculate_weight(patches, temp_weight, key)
|
||||
out_weight = float.stochastic_rounding(out_weight, weight.dtype)
|
||||
|
||||
if inplace_update:
|
||||
utils.copy_to_param(self.model, key, out_weight)
|
||||
else:
|
||||
utils.set_attr_param(self.model, key, out_weight)
|
||||
|
||||
def unpatch_model(self, device_to=None, unpatch_weights=True):
|
||||
if unpatch_weights:
|
||||
for p in self.model.parameters():
|
||||
if is_torch_compatible(p):
|
||||
continue
|
||||
patches = getattr(p, "patches", [])
|
||||
if len(patches) > 0:
|
||||
p.patches = []
|
||||
# TODO: Find another way to not unload after patches
|
||||
return super().unpatch_model(device_to=device_to, unpatch_weights=unpatch_weights)
|
||||
|
||||
|
||||
def get_dtype(dtype):
|
||||
match dtype:
|
||||
case None | "default":
|
||||
return None
|
||||
case "target":
|
||||
return dtype
|
||||
case _:
|
||||
return getattr(torch, dtype)
|
||||
|
||||
|
||||
def load_clip_data(ckpt_paths):
|
||||
clip_data = []
|
||||
for path in ckpt_paths:
|
||||
if path.endswith(".gguf"):
|
||||
state_dict = gguf_clip_loader(path)
|
||||
else:
|
||||
state_dict = utils.load_torch_file(path, safe_load=True)
|
||||
# NOTE: Scaled FP8 would require different custom ops, but only one can be active
|
||||
if "scaled_fp8" in state_dict:
|
||||
raise NotImplementedError(
|
||||
f"Mixing scaled FP8 with GGUF is not supported! Use regular CLIP loader or switch model(s)\n({path})")
|
||||
|
||||
clip_data.append(state_dict)
|
||||
|
||||
return clip_data
|
||||
|
||||
|
||||
def load_clip_patcher(clip_name, type="flux2"):
|
||||
clip_path = folder_paths.get_full_path("clip_gguf", clip_name)
|
||||
clip_type = getattr(sd.CLIPType, type.upper(), sd.CLIPType.FLUX2)
|
||||
clip_data = load_clip_data([clip_path])
|
||||
|
||||
clip = sd.load_text_encoder_state_dicts(
|
||||
clip_type=clip_type,
|
||||
state_dicts=clip_data,
|
||||
model_options={
|
||||
"custom_operations": GGMLOps,
|
||||
"initial_device": model_management.text_encoder_offload_device()
|
||||
},
|
||||
embedding_directory=folder_paths.get_folder_paths("embeddings"),
|
||||
)
|
||||
clip.patcher = GGUFModelPatcher.clone(clip.patcher)
|
||||
|
||||
return clip
|
||||
|
||||
|
||||
def apply_bypass_lora_for_models(loaded_lora, model, clip, lora_name, strength):
|
||||
if loaded_lora == None:
|
||||
lora_path = folder_paths.get_full_path_or_raise("loras", lora_name)
|
||||
lora = utils.load_torch_file(lora_path, safe_load=True)
|
||||
else:
|
||||
lora = loaded_lora
|
||||
|
||||
patched_model, patched_clip = sd.load_bypass_lora_for_models(model, clip, lora, strength, strength)
|
||||
|
||||
return (patched_model, patched_clip, lora,)
|
||||
|
||||
|
||||
def load_gguf_pipeline(cls, **kwargs):
|
||||
ops = GGMLOps()
|
||||
|
||||
ops.Linear.dequant_dtype = get_dtype(kwargs.get("dequant_dtype", None))
|
||||
ops.Linear.patch_dtype = get_dtype(kwargs.get("patch_dtype", None))
|
||||
|
||||
gguf_full_path = folder_paths.get_full_path("unet_gguf", kwargs.get("diffusion_model"))
|
||||
state_dict, extra = gguf_sd_loader(gguf_full_path)
|
||||
|
||||
args = {}
|
||||
valid_params = inspect.signature(sd.load_diffusion_model_state_dict).parameters
|
||||
|
||||
if "metadata" in valid_params:
|
||||
args["metadata"] = extra.get("metadata", {})
|
||||
|
||||
model = sd.load_diffusion_model_state_dict(state_dict, model_options={"custom_operations": ops}, **args, )
|
||||
|
||||
if model is None:
|
||||
raise RuntimeError("ERROR: Could not detect model type of: {}".format(gguf_full_path))
|
||||
|
||||
model = GGUFModelPatcher.clone(model)
|
||||
model.patch_on_device = kwargs.get("patch_on_device", None)
|
||||
|
||||
apply_sampling = kwargs.get("apply_sampling")
|
||||
if apply_sampling:
|
||||
args = {
|
||||
"model": model,
|
||||
"base_sampling_shift": kwargs.get("base_sampling_shift"),
|
||||
"max_sampling_shift": kwargs.get("max_sampling_shift"),
|
||||
"sampling_width": kwargs.get("sampling_width"),
|
||||
"sampling_height": kwargs.get("sampling_height"),
|
||||
}
|
||||
model = patch_flux_sampling(**args)
|
||||
|
||||
clip = load_clip_patcher(kwargs.get("clip"), kwargs.get("clip_type", "flux2"))
|
||||
|
||||
if kwargs.get("apply_bypass_lora"):
|
||||
loras = [
|
||||
(kwargs.get("lora_name_1"), kwargs.get("strength_1"), 'loaded_lora_1'),
|
||||
(kwargs.get("lora_name_2"), kwargs.get("strength_2"), 'loaded_lora_2'),
|
||||
(kwargs.get("lora_name_3"), kwargs.get("strength_3"), 'loaded_lora_3'),
|
||||
(kwargs.get("lora_name_4"), kwargs.get("strength_4"), 'loaded_lora_4'),
|
||||
]
|
||||
|
||||
for name, strength, attr in loras:
|
||||
if name != "None" and strength != 0:
|
||||
cached = getattr(cls, attr)
|
||||
model, clip, lora = apply_bypass_lora_for_models(cached, model, clip, name, strength)
|
||||
setattr(cls, attr, lora)
|
||||
|
||||
vae = load_vae(
|
||||
kwargs.get("vae_name"),
|
||||
kwargs.get("vae_device", "default"),
|
||||
kwargs.get("vae_dtype", "bfloat16"),
|
||||
)
|
||||
|
||||
return model, clip, vae
|
||||
|
||||
|
||||
class TT_GgufModelsLoaderNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id="TT_GgufModelsLoaderNode",
|
||||
display_name="TT GGUF Models Loader",
|
||||
category=CATEGORY,
|
||||
description="",
|
||||
inputs=[
|
||||
io.Combo.Input("diffusion_model", options=get_gguf_diffusion_models_files()),
|
||||
io.Combo.Input("clip", options=get_gguf_text_encoder_files()),
|
||||
io.Combo.Input("vae_name", options=get_vae_files()),
|
||||
],
|
||||
outputs=[
|
||||
io.Model.Output("MODEL"),
|
||||
io.Clip.Output("CLIP"),
|
||||
io.Vae.Output("VAE"),
|
||||
]
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def execute(cls, **kwargs) -> io.NodeOutput:
|
||||
kwargs["apply_bypass_lora"] = False
|
||||
model, clip, vae = load_gguf_pipeline(cls, apply_loras=True, **kwargs)
|
||||
|
||||
return io.NodeOutput(model, clip, vae)
|
||||
|
||||
|
||||
class TT_GgufModelsLoaderAdvancedNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id="TT_GgufModelsLoaderAdvancedNode",
|
||||
display_name="TT GGUF Models Loader (Advanced)",
|
||||
category=CATEGORY,
|
||||
description="",
|
||||
inputs=[
|
||||
io.Combo.Input("diffusion_model", options=get_gguf_diffusion_models_files()),
|
||||
io.Combo.Input("dequant_dtype", options=list(DTYPES.keys()), default="bfloat16", advanced=True),
|
||||
io.Combo.Input("patch_dtype", options=list(DTYPES.keys()), default="bfloat16", advanced=True),
|
||||
io.Boolean.Input("apply_sampling", default=True, label_on="Flux Shift", label_off="No Shift"),
|
||||
io.Float.Input("base_sampling_shift", default=0.5, min=0.0, max=100.0, step=0.01, advanced=True),
|
||||
io.Float.Input("max_sampling_shift", default=1.15, min=0.0, max=100.0, step=0.01, advanced=True),
|
||||
io.Int.Input("sampling_width", default=1024, min=16, max=MAX_RESOLUTION, step=8, advanced=True),
|
||||
io.Int.Input("sampling_height", default=1024, min=16, max=MAX_RESOLUTION, step=8, advanced=True),
|
||||
io.Combo.Input("clip", options=get_gguf_text_encoder_files()),
|
||||
io.Combo.Input("clip_device", options=TORCH_DEVICES, default="default", advanced=True),
|
||||
io.Combo.Input("lora_name_1", options=get_lora_files()),
|
||||
io.Float.Input("strength_1", default=1.0, min=-10.0, max=10.0, step=0.1),
|
||||
io.Combo.Input("lora_name_2", options=get_lora_files()),
|
||||
io.Float.Input("strength_2", default=1.0, min=-10.0, max=10.0, step=0.1),
|
||||
io.Combo.Input("lora_name_3", options=get_lora_files()),
|
||||
io.Float.Input("strength_3", default=1.0, min=-10.0, max=10.0, step=0.1),
|
||||
io.Combo.Input("lora_name_4", options=get_lora_files()),
|
||||
io.Float.Input("strength_4", default=1.0, min=-10.0, max=10.0, step=0.1),
|
||||
io.Combo.Input("vae_name", options=get_vae_files()),
|
||||
io.Combo.Input("vae_device", options=TORCH_DEVICES, default="default", advanced=True),
|
||||
io.Combo.Input("vae_dtype", options=list(DTYPES.keys()), advanced=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Model.Output("MODEL"),
|
||||
io.Clip.Output("CLIP"),
|
||||
io.Vae.Output("VAE"),
|
||||
]
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def execute(cls, **kwargs) -> io.NodeOutput:
|
||||
kwargs["apply_bypass_lora"] = False
|
||||
model, clip, vae = load_gguf_pipeline(cls, apply_loras=True, **kwargs)
|
||||
|
||||
return io.NodeOutput(model, clip, vae)
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# V3 entrypoint — registers context nodes with ComfyUI
|
||||
# ==============================================================================
|
||||
@@ -392,6 +669,8 @@ class LoaderNodesExtension(ComfyExtension):
|
||||
TT_SdxlModelsLoaderAdvancedNode,
|
||||
TT_FluxModelsLoaderNode,
|
||||
TT_FluxModelsLoaderAdvancedNode,
|
||||
TT_GgufModelsLoaderNode,
|
||||
TT_GgufModelsLoaderAdvancedNode,
|
||||
]
|
||||
|
||||
|
||||
@@ -408,4 +687,6 @@ __all__ = [
|
||||
"TT_SdxlModelsLoaderAdvancedNode",
|
||||
"TT_FluxModelsLoaderNode",
|
||||
"TT_FluxModelsLoaderAdvancedNode",
|
||||
"TT_GgufModelsLoaderNode",
|
||||
"TT_GgufModelsLoaderAdvancedNode",
|
||||
]
|
||||
|
||||
+4
-2
@@ -11,6 +11,8 @@ from comfy.samplers import KSampler, sampler_object, Sampler
|
||||
from comfy_api.latest import io, ComfyExtension
|
||||
from nodes import MAX_RESOLUTION
|
||||
|
||||
CATEGORY = "TenserTensor/Workflow"
|
||||
|
||||
|
||||
@dataclass
|
||||
class TTWorkflowSettings():
|
||||
@@ -128,7 +130,7 @@ class TT_Flux2WorkflowSettingsNode(io.ComfyNode):
|
||||
return io.Schema(
|
||||
node_id="TT_Flux2WorkflowSettingsNode",
|
||||
display_name="TT FLUX2 Workflow Settings",
|
||||
category="TenserTensor/Workflow",
|
||||
category=CATEGORY,
|
||||
description="",
|
||||
inputs=[
|
||||
io.Int.Input("seed", default=0, min=0, max=0xffffffffffffffff),
|
||||
@@ -190,7 +192,7 @@ class TT_Flux2WorkflowSettingsAdvancedNode(io.ComfyNode):
|
||||
return io.Schema(
|
||||
node_id="TT_Flux2WorkflowSettingsAdvancedNode",
|
||||
display_name="TT FLUX2 Workflow Settings (Advanced)",
|
||||
category="TenserTensor/Workflow",
|
||||
category=CATEGORY,
|
||||
description="",
|
||||
inputs=[
|
||||
io.Int.Input("seed", default=0, min=0, max=0xffffffffffffffff),
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
## TT FLUX Models Loader (Advanced) *TT_FluxModelsLoaderAdvancedNode*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Extended FLUX pipeline loader with sampling shift control, up to 4 LoRA slots, and advanced device/dtype configuration.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|---------------------|---------|----------|--------------------------------------------------------------------------------------------------|
|
||||
| `diffusion_model` | COMBO | Yes | FLUX diffusion model checkpoint file |
|
||||
| `apply_sampling` | BOOLEAN | Yes | Enable resolution-based sampling shift ("Flux Shift" / "No Shift", default: enabled) |
|
||||
| `base_sampling_shift` | FLOAT | Yes | Base shift value for sampling schedule (0.0–100.0, default: 0.5) *(advanced)* |
|
||||
| `max_sampling_shift` | FLOAT | Yes | Maximum shift value for sampling schedule (0.0–100.0, default: 1.15) *(advanced)* |
|
||||
| `sampling_width` | INT | Yes | Reference width for shift calculation (16–MAX, step: 8, default: 1024) *(advanced)* |
|
||||
| `sampling_height` | INT | Yes | Reference height for shift calculation (16–MAX, step: 8, default: 1024) *(advanced)* |
|
||||
| `clip_l` | COMBO | Yes | CLIP-L text encoder file |
|
||||
| `t5xxl` | COMBO | Yes | T5-XXL text encoder file |
|
||||
| `clip_device` | COMBO | Yes | Device for CLIP/T5 inference (default: "default") *(advanced)* |
|
||||
| `lora_name_1` | COMBO | Yes | LoRA file for slot 1 |
|
||||
| `strength_1` | FLOAT | Yes | Strength for LoRA slot 1 (-10.0–10.0, default: 1.0) |
|
||||
| `lora_name_2` | COMBO | Yes | LoRA file for slot 2 |
|
||||
| `strength_2` | FLOAT | Yes | Strength for LoRA slot 2 (-10.0–10.0, default: 1.0) |
|
||||
| `lora_name_3` | COMBO | Yes | LoRA file for slot 3 |
|
||||
| `strength_3` | FLOAT | Yes | Strength for LoRA slot 3 (-10.0–10.0, default: 1.0) |
|
||||
| `lora_name_4` | COMBO | Yes | LoRA file for slot 4 |
|
||||
| `strength_4` | FLOAT | Yes | Strength for LoRA slot 4 (-10.0–10.0, default: 1.0) |
|
||||
| `vae_name` | COMBO | Yes | VAE model file for image encoding/decoding |
|
||||
| `vae_device` | COMBO | Yes | Device for VAE inference (default: "default") *(advanced)* |
|
||||
| `vae_dtype` | COMBO | Yes | Data type for VAE computation *(advanced)* |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|-------|----------------------------------|
|
||||
| `MODEL` | MODEL | Loaded FLUX diffusion model |
|
||||
| `CLIP` | CLIP | Loaded CLIP+T5 text encoder |
|
||||
| `VAE` | VAE | Loaded VAE |
|
||||
|
||||
### Usage
|
||||
|
||||
Advanced version of the FLUX pipeline loader with full control over all loading parameters. Supports up to
|
||||
4 simultaneous LoRAs applied at load time. Enable "Flux Shift" to apply resolution-aware sampling shift —
|
||||
adjust `base_sampling_shift`, `max_sampling_shift`, and the reference resolution to tune the shift curve.
|
||||
Use advanced device/dtype options to offload components to specific devices or reduce memory usage.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -0,0 +1,33 @@
|
||||
## TT FLUX Models Loader *TT_FluxModelsLoaderNode*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Loads all components of the FLUX pipeline (diffusion model, text encoders, and VAE) in a single node.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-------------------|-------|----------|------------------------------------------------|
|
||||
| `diffusion_model` | COMBO | Yes | FLUX diffusion model checkpoint file |
|
||||
| `clip_l` | COMBO | Yes | CLIP-L text encoder file |
|
||||
| `t5xxl` | COMBO | Yes | T5-XXL text encoder file |
|
||||
| `clip_device` | COMBO | Yes | Device for CLIP inference (default: "default") |
|
||||
| `vae_name` | COMBO | Yes | VAE model file for image encoding/decoding |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|-------|-----------------------------|
|
||||
| `MODEL` | MODEL | Loaded FLUX diffusion model |
|
||||
| `CLIP` | CLIP | Loaded CLIP+T5 text encoder |
|
||||
| `VAE` | VAE | Loaded VAE |
|
||||
|
||||
### Usage
|
||||
|
||||
Convenience node for loading the complete FLUX pipeline in one step. Select the diffusion model,
|
||||
both text encoders (CLIP-L and T5-XXL), and VAE from their respective dropdowns. Use `clip_device`
|
||||
to offload text encoders to a specific device if needed. LoRA loading is not applied at this stage.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -0,0 +1,51 @@
|
||||
## TT GGUF Models Loader (Advanced) *TT_GgufModelsLoaderAdvancedNode*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Extended GGUF pipeline loader with dequantization control, sampling shift, up to 4 LoRA slots, and advanced device/dtype configuration.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------------------|---------|----------|--------------------------------------------------------------------------------------|
|
||||
| `diffusion_model` | COMBO | Yes | GGUF-quantized diffusion model file |
|
||||
| `dequant_dtype` | COMBO | Yes | Data type for dequantization (default: "bfloat16") *(advanced)* |
|
||||
| `patch_dtype` | COMBO | Yes | Data type for model patches (default: "bfloat16") *(advanced)* |
|
||||
| `apply_sampling` | BOOLEAN | Yes | Enable resolution-based sampling shift ("Flux Shift" / "No Shift", default: enabled) |
|
||||
| `base_sampling_shift` | FLOAT | Yes | Base shift value for sampling schedule (0.0–100.0, default: 0.5) *(advanced)* |
|
||||
| `max_sampling_shift` | FLOAT | Yes | Maximum shift value for sampling schedule (0.0–100.0, default: 1.15) *(advanced)* |
|
||||
| `sampling_width` | INT | Yes | Reference width for shift calculation (16–MAX, step: 8, default: 1024) *(advanced)* |
|
||||
| `sampling_height` | INT | Yes | Reference height for shift calculation (16–MAX, step: 8, default: 1024) *(advanced)* |
|
||||
| `clip` | COMBO | Yes | GGUF-quantized text encoder file |
|
||||
| `clip_device` | COMBO | Yes | Device for CLIP inference (default: "default") *(advanced)* |
|
||||
| `lora_name_1` | COMBO | Yes | LoRA file for slot 1 |
|
||||
| `strength_1` | FLOAT | Yes | Strength for LoRA slot 1 (-10.0–10.0, default: 1.0) |
|
||||
| `lora_name_2` | COMBO | Yes | LoRA file for slot 2 |
|
||||
| `strength_2` | FLOAT | Yes | Strength for LoRA slot 2 (-10.0–10.0, default: 1.0) |
|
||||
| `lora_name_3` | COMBO | Yes | LoRA file for slot 3 |
|
||||
| `strength_3` | FLOAT | Yes | Strength for LoRA slot 3 (-10.0–10.0, default: 1.0) |
|
||||
| `lora_name_4` | COMBO | Yes | LoRA file for slot 4 |
|
||||
| `strength_4` | FLOAT | Yes | Strength for LoRA slot 4 (-10.0–10.0, default: 1.0) |
|
||||
| `vae_name` | COMBO | Yes | VAE model file for image encoding/decoding |
|
||||
| `vae_device` | COMBO | Yes | Device for VAE inference (default: "default") *(advanced)* |
|
||||
| `vae_dtype` | COMBO | Yes | Data type for VAE computation *(advanced)* |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|-------|-----------------------------|
|
||||
| `MODEL` | MODEL | Loaded GGUF diffusion model |
|
||||
| `CLIP` | CLIP | Loaded GGUF text encoder |
|
||||
| `VAE` | VAE | Loaded VAE |
|
||||
|
||||
### Usage
|
||||
|
||||
Advanced GGUF pipeline loader with full control over quantization and loading parameters. Use `dequant_dtype`
|
||||
and `patch_dtype` to balance precision and VRAM usage during dequantization. Supports up to 4 simultaneous
|
||||
LoRAs applied at load time. Enable "Flux Shift" to apply resolution-aware sampling shift — adjust
|
||||
`base_sampling_shift`, `max_sampling_shift`, and the reference resolution to tune the shift curve.
|
||||
Use advanced device options to offload components as needed.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -0,0 +1,31 @@
|
||||
## TT GGUF Models Loader *TT_GgufModelsLoaderNode*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Loads a complete GGUF-quantized pipeline (diffusion model, text encoder, and VAE) in a single node.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-------------------|-------|----------|---------------------------------------------|
|
||||
| `diffusion_model` | COMBO | Yes | GGUF-quantized diffusion model file |
|
||||
| `clip` | COMBO | Yes | GGUF-quantized text encoder file |
|
||||
| `vae_name` | COMBO | Yes | VAE model file for image encoding/decoding |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|-------|-------------------------------------|
|
||||
| `MODEL` | MODEL | Loaded GGUF diffusion model |
|
||||
| `CLIP` | CLIP | Loaded GGUF text encoder |
|
||||
| `VAE` | VAE | Loaded VAE |
|
||||
|
||||
### Usage
|
||||
|
||||
Convenience node for loading a GGUF-quantized pipeline in one step. Designed for use with quantized model
|
||||
files that reduce VRAM requirements. Select the GGUF diffusion model, GGUF text encoder, and VAE from
|
||||
their respective dropdowns. LoRA loading is supported at this stage; bypass LoRA is not applied.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
Reference in New Issue
Block a user