diff --git a/node_mappings.py b/node_mappings.py index b563251..572f1e7 100644 --- a/node_mappings.py +++ b/node_mappings.py @@ -183,7 +183,7 @@ NODE_CLASS_MAPPINGS = { "TT_GgufModelsLoaderNode": TT_Flux2GgufModelsLoaderNode, "TT_GgufModelsLoaderAdvancedNode": TT_Flux2GgufModelsLoaderAdvancedNode, "TT_Sd35GgufModelsLoaderNode": TT_Sd35GgufModelsLoaderNode, - # "TT_Sd35GgufModelsLoaderAdvancedNode": TT_Sd35GgufModelsLoaderAdvancedNode, + "TT_Sd35GgufModelsLoaderAdvancedNode": TT_Sd35GgufModelsLoaderAdvancedNode, # Postproduction "TT_ApplyLut": TT_ApplyLut, "TT_AddFilmGrain": TT_AddFilmGrain, @@ -198,9 +198,12 @@ NODE_CLASS_MAPPINGS = { "TT_KSamplerTwoStage": TT_KSamplerTwoStage, "TT_KSamplerGuided": TT_KSamplerGuided, # Samplers V3 Nodes + "TT_KSamplerNode": TT_KSamplerNode, + "TT_KSamplerAdvancedNode": TT_KSamplerAdvancedNode, + "TT_KSamplerContextNode": TT_KSamplerContextNode, + "TT_KSamplerTwoStageNode": TT_KSamplerTwoStageNode, "TT_GuidedKSamplerNode": TT_GuidedKSamplerNode, "TT_GuidedUpscaleKSamplerNode": TT_GuidedUpscaleKSamplerNode, - "TT_GuidedKSamplerWithPreviewNode": TT_GuidedKSamplerWithPreviewNode, # Text Encoder "TT_ClipTextEncodeFlux": TT_ClipTextEncodeFlux, "TT_ClipTextEncodeFluxContext": TT_ClipTextEncodeFluxContext, @@ -296,7 +299,7 @@ NODE_DISPLAY_NAME_MAPPINGS = { "TT_GgufModelsLoaderNode": "TT GGUF Models Loader", "TT_GgufModelsLoaderAdvancedNode": "TT GGUF Models Loader (Advanced)", "TT_Sd35GgufModelsLoaderNode": "TT SD3.5 GGUF Models Loader", - # "TT_Sd35ModelsLoaderAdvancedNode": "TT SD3.5 GGUF Models Loader (Advanced)", + "TT_Sd35ModelsLoaderAdvancedNode": "TT SD3.5 GGUF Models Loader (Advanced)", # Postproduction "TT_ApplyLut": "TT Apply LUT", "TT_AddFilmGrain": "TT Add Film Grain", @@ -311,9 +314,12 @@ NODE_DISPLAY_NAME_MAPPINGS = { "TT_KSamplerTwoStage": "TT KSampler (Two Stages)", "TT_KSamplerGuided": "TT KSampler (Guided)", # Samplers V3 Nodes + "TT_KSamplerNode": "TT KSampler", + "TT_KSamplerAdvancedNode": "TT KSampler (Advanced)", + "TT_KSamplerContextNode": "TT KSampler (Context)", + "TT_KSamplerTwoStageNode": "TT KSampler (Two Stage)", "TT_GuidedKSamplerNode": "TT Guided KSampler", "TT_GuidedUpscaleKSamplerNode": "TT Guided Upscale KSampler", - "TT_GuidedKSamplerWithPreviewNode": "TT Guided KSampler (With Preview)", # Text Encoder "TT_ClipTextEncodeFlux": "TT CLIP Text Encode FLUX", "TT_ClipTextEncodeFluxContext": "TT CLIP Text Encode FLUX (Context)", diff --git a/nodes/sampling/ksampler.py b/nodes/sampling/ksampler.py index 0b9402f..f656227 100644 --- a/nodes/sampling/ksampler.py +++ b/nodes/sampling/ksampler.py @@ -25,7 +25,7 @@ class TT_KSampler(): RETURN_TYPES = ("LATENT",) RETURN_NAMES = ("SAMPLES",) FUNCTION = "execute_sampling" - CATEGORY = "TenserTensor/Sampling" + CATEGORY = "TenserTensor/Deprecated/Sampling" def execute_sampling(self, **kwargs): return (sample_latents(**kwargs),) diff --git a/nodes/sampling/ksampler_advanced.py b/nodes/sampling/ksampler_advanced.py index 4c2e7c4..f31d000 100644 --- a/nodes/sampling/ksampler_advanced.py +++ b/nodes/sampling/ksampler_advanced.py @@ -30,7 +30,7 @@ class TT_KSamplerAdvanced(): RETURN_TYPES = ("LATENT",) RETURN_NAMES = ("SAMPLES",) FUNCTION = "execute_sampling" - CATEGORY = "TenserTensor/Sampling" + CATEGORY = "TenserTensor/Deprecated/Sampling" def execute_sampling(self, **kwargs): return (sample_latents(**kwargs),) diff --git a/nodes/sampling/ksampler_context.py b/nodes/sampling/ksampler_context.py index ae6a56d..648e712 100644 --- a/nodes/sampling/ksampler_context.py +++ b/nodes/sampling/ksampler_context.py @@ -15,7 +15,7 @@ class TT_KSamplerContext(): RETURN_TYPES = ("TT_CONTEXT", "LATENT",) RETURN_NAMES = ("CONTEXT", "SAMPLES",) FUNCTION = "execute_sampling" - CATEGORY = "TenserTensor/Sampling" + CATEGORY = "TenserTensor/Deprecated/Sampling" def execute_sampling(self, context): model = context.get("model", None) diff --git a/nodes/sampling/ksampler_two_stage.py b/nodes/sampling/ksampler_two_stage.py index 97b8a78..b825864 100644 --- a/nodes/sampling/ksampler_two_stage.py +++ b/nodes/sampling/ksampler_two_stage.py @@ -30,7 +30,7 @@ class TT_KSamplerTwoStage(): RETURN_TYPES = ("LATENT",) RETURN_NAMES = ("SAMPLES",) FUNCTION = "execute_sampling" - CATEGORY = "TenserTensor/Sampling" + CATEGORY = "TenserTensor/Deprecated/Sampling" def execute_sampling(self, **kwargs): draft_steps = kwargs["draft_steps"] diff --git a/nodes_loaders.py b/nodes_loaders.py index 9bc6562..df81e88 100644 --- a/nodes_loaders.py +++ b/nodes_loaders.py @@ -786,7 +786,7 @@ class LoaderNodesExtension(ComfyExtension): TT_Flux2GgufModelsLoaderNode, TT_Flux2GgufModelsLoaderAdvancedNode, TT_Sd35GgufModelsLoaderNode, - # TT_Sd35GgufModelsLoaderAdvancedNode, + TT_Sd35GgufModelsLoaderAdvancedNode, ] @@ -806,5 +806,5 @@ __all__ = [ "TT_Flux2GgufModelsLoaderNode", "TT_Flux2GgufModelsLoaderAdvancedNode", "TT_Sd35GgufModelsLoaderNode", - # "TT_Sd35GgufModelsLoaderAdvancedNode", + "TT_Sd35GgufModelsLoaderAdvancedNode", ] diff --git a/nodes_postproduction.py b/nodes_postproduction.py index 78ac677..23fbcce 100644 --- a/nodes_postproduction.py +++ b/nodes_postproduction.py @@ -2,7 +2,135 @@ from typing import override -from comfy_api.latest import ComfyExtension, IO +from comfy_api.latest import ComfyExtension, io + +CATEGORY = "TenserTensor/Postproduction" + + +class TT_AddFilmGrainNode(io.ComfyNode): + @classmethod + def define_schema(cls) -> io.Schema: + return io.Schema( + node_id="TT_AddFilmGrainNode", + display_name="TT Add Film Grain", + category=CATEGORY, + description="", + inputs=[ + + ], + outputs=[ + + ] + ) + + @classmethod + def execute(cls, **kwargs) -> io.NodeOutput: + raise NotImplementedError + + +class TT_ApplyLutNode(io.ComfyNode): + @classmethod + def define_schema(cls) -> io.Schema: + return io.Schema( + node_id="TT_ApplyLutNode", + display_name="TT Apply LUT", + category=CATEGORY, + description="", + inputs=[ + + ], + outputs=[ + + ] + ) + + @classmethod + def execute(cls, **kwargs) -> io.NodeOutput: + raise NotImplementedError + + +class TT_ImageEnhancerNode(io.ComfyNode): + @classmethod + def define_schema(cls) -> io.Schema: + return io.Schema( + node_id="TT_ImageEnhancerNode", + display_name="TT Image Enhancer", + category=CATEGORY, + description="", + inputs=[ + + ], + outputs=[ + + ] + ) + + @classmethod + def execute(cls, **kwargs) -> io.NodeOutput: + raise NotImplementedError + + +class TT_QuickImageUpscalerNode(io.ComfyNode): + @classmethod + def define_schema(cls) -> io.Schema: + return io.Schema( + node_id="TT_QuickImageUpscalerNode", + display_name="TT Quick Image Upscaler", + category=CATEGORY, + description="", + inputs=[ + + ], + outputs=[ + + ] + ) + + @classmethod + def execute(cls, **kwargs) -> io.NodeOutput: + raise NotImplementedError + + +class TT_PostproductionNode(io.ComfyNode): + @classmethod + def define_schema(cls) -> io.Schema: + return io.Schema( + node_id="TT_PostproductionNode", + display_name="TT Postproduction", + category=CATEGORY, + description="", + inputs=[ + + ], + outputs=[ + + ] + ) + + @classmethod + def execute(cls, **kwargs) -> io.NodeOutput: + raise NotImplementedError + + +class TT_PostproductionAdvancedNode(io.ComfyNode): + @classmethod + def define_schema(cls) -> io.Schema: + return io.Schema( + node_id="TT_PostproductionAdvancedNode", + display_name="TT Postproduction (Advanced)", + category=CATEGORY, + description="", + inputs=[ + + ], + outputs=[ + + ] + ) + + @classmethod + def execute(cls, **kwargs) -> io.NodeOutput: + raise NotImplementedError # ============================================================================== @@ -11,7 +139,7 @@ from comfy_api.latest import ComfyExtension, IO class PostproductionNodesExtension(ComfyExtension): @override - async def get_node_list(self) -> list[type[IO.ComfyNode]]: + async def get_node_list(self) -> list[type[io.ComfyNode]]: return [ # TT_Node, ] diff --git a/nodes_sampling.py b/nodes_sampling.py index b90b80b..bb822ba 100644 --- a/nodes_sampling.py +++ b/nodes_sampling.py @@ -2,15 +2,258 @@ from typing import override +import torch + import latent_preview -from comfy import sample, model_management +from comfy import sample, model_management, samplers from comfy_api.latest import ComfyExtension, io +from .nodes_context import Context from .nodes_latent import SCALE_FACTORS, SCALE_METHODS, scale_latent from .nodes_text_encoder import SingleCondCFGGuider CATEGORY = "TenserTensor/Sampling" +def do_sample(**kwargs): + model = kwargs.get("model", None) + if model is None: + raise ValueError("Model is required for sampling") + + latent = kwargs.get("latent", None) + if latent is None: + raise ValueError("Latent image is required for sampling") + + latent_dict = latent.copy() + samples, add_noise, seed, steps, device = ( + latent_dict["samples"], + kwargs.get("add_noise", True), + kwargs.get("seed", 0), + kwargs.get("steps", 0), + kwargs.get("device", "cpu") + ) + latent_tensor = sample.fix_empty_latent_channels(model, samples, latent.get("downscale_ratio_spacial", None)) + + if add_noise: + batch_idx = latent.get("batch_index", None) + noise = sample.prepare_noise(samples, seed, batch_idx) + else: + noise = torch.zeros(samples.size(), dtype=samples.dtype, layout=samples.layout, device="cpu") + + interim_buffer = {} + if kwargs.get("preview_latent"): + latent_preview.set_preview_method("latent2rgb") + callback = latent_preview.prepare_callback(model, steps - 1, interim_buffer) + else: + callback = None + + args = { + "model": model, + "noise": noise, + "steps": steps, + "cfg": kwargs.get("cfg"), + "sampler_name": kwargs.get("sampler_name"), + "scheduler": kwargs.get("scheduler"), + "positive": kwargs.get("positive"), + "negative": kwargs.get("negative"), + "latent_image": latent_tensor, + "denoise": kwargs.get("denoise", 1.0), + "disable_noise": not add_noise, + "start_step": kwargs.get("start_step"), + "last_step": kwargs.get("last_step"), + "force_full_denoise": kwargs.get("full_denoise", True), + "noise_mask": latent.get("noise_mask"), + "callback": callback, + "seed": seed, + } + + samples = sample.sample(**args) + sampled_latent = latent_dict.copy() + sampled_latent.pop("downscale_ratio_spacial", None) + sampled_latent["samples"] = samples + + return sampled_latent + + +class TT_KSamplerNode(io.ComfyNode): + @classmethod + def define_schema(cls) -> io.Schema: + return io.Schema( + node_id="TT_KSamplerNode", + display_name="TT KSampler", + category=CATEGORY, + description="", + inputs=[ + io.Model.Input("model"), + io.Conditioning.Input("positive"), + io.Conditioning.Input("negative"), + io.Latent.Input("latent"), + io.Int.Input("seed", default=0, min=0, max=0xffffffffffffffff), + io.Int.Input("steps", default=30, min=1, max=10_000), + io.Float.Input("cfg", default=3.0, min=0.0, max=100.0, step=0.1), + io.Combo.Input("sampler_name", options=samplers.KSampler.SAMPLERS), + io.Combo.Input("scheduler", options=samplers.KSampler.SCHEDULERS), + io.Boolean.Input("preview_latent", default=False, label_on="Show Preview", label_off="Only Sample"), + ], + outputs=[ + io.Latent.Output("LATENT"), + ] + ) + + @classmethod + def execute(cls, **kwargs) -> io.NodeOutput: + latent = do_sample(**kwargs) + + return io.NodeOutput(latent) + + +class TT_KSamplerAdvancedNode(io.ComfyNode): + @classmethod + def define_schema(cls) -> io.Schema: + return io.Schema( + node_id="TT_KSamplerAdvancedNode", + display_name="TT KSampler (Advanced)", + category=CATEGORY, + description="", + inputs=[ + io.Model.Input("model"), + io.Conditioning.Input("positive"), + io.Conditioning.Input("negative"), + io.Latent.Input("latent"), + io.Boolean.Input("add_noise", default=False, label_on="Random Noise", label_off="Zero Noise"), + io.Boolean.Input("full_denoise", default=False, label_on="Complete", label_off="Partial"), + io.Float.Input("denoise", default=1.0, min=0.0, max=1.0, step=0.01), + io.Int.Input("seed", default=0, min=0, max=0xffffffffffffffff), + io.Int.Input("steps", default=30, min=1, max=10_000), + io.Float.Input("cfg", default=3.0, min=0.0, max=100.0, step=0.1), + io.Int.Input("start_step", default=0, min=0, max=10_000), + io.Int.Input("last_step", default=10_000, min=0, max=10_000), + io.Combo.Input("sampler_name", options=samplers.KSampler.SAMPLERS), + io.Combo.Input("scheduler", options=samplers.KSampler.SCHEDULERS), + io.Boolean.Input("preview_latent", default=False, label_on="Show Preview", label_off="Only Sample"), + ], + outputs=[ + io.Latent.Output("LATENT"), + ] + ) + + @classmethod + def execute(cls, **kwargs) -> io.NodeOutput: + latent = do_sample(**kwargs) + + return io.NodeOutput(latent) + + +class TT_KSamplerContextNode(io.ComfyNode): + @classmethod + def define_schema(cls) -> io.Schema: + return io.Schema( + node_id="TT_KSamplerContextNode", + display_name="TT KSampler (Context)", + category=CATEGORY, + description="", + inputs=[ + Context.Input("context"), + io.Boolean.Input("preview_latent", default=False, label_on="Show Preview", label_off="Only Sample"), + ], + outputs=[ + Context.Output("CONTEXT"), + io.Latent.Output("LATENT"), + ] + ) + + @classmethod + def execute(cls, context) -> io.NodeOutput: + model = context.get("model") + if model is None: + raise ValueError("Model is required for sampling") + + latent = context.get("latent") + if latent is None: + raise ValueError("Latent image is required for sampling") + + config = context.get("workflow_config") + if config is None: + raise ValueError("Workflow Config is required for sampling") + + args = { + "model": model, + "positive": context.get_attr("positive"), + "negative": context.get_attr("negative"), + "latent": latent, + "seed": config.get_attr("seed"), + "steps": config.get_attr("steps"), + "cfg": config.get_attr("cfg"), + "sampler_name": config.get_attr("sampler_name"), + "scheduler": config.get_attr("scheduler"), + } + latent = do_sample(**args) + context.set_attr("latent", latent) + + return io.NodeOutput(context, latent) + + +class TT_KSamplerTwoStageNode(io.ComfyNode): + @classmethod + def define_schema(cls) -> io.Schema: + return io.Schema( + node_id="TT_KSamplerTwoStageNode", + display_name="TT KSampler (Two Stage)", + category=CATEGORY, + description="", + inputs=[ + io.Model.Input("model"), + io.Conditioning.Input("positive"), + io.Conditioning.Input("negative"), + io.Latent.Input("latent"), + io.Int.Input("seed", default=0, min=0, max=0xffffffffffffffff), + io.Float.Input("cfg", default=3.0, min=0.0, max=100.0, step=0.1), + io.Int.Input("draft_steps", default=25, min=1, max=10_000), + io.Int.Input("refiner_steps", default=25, min=1, max=10_000), + io.Combo.Input("draft_sampler_name", options=samplers.KSampler.SAMPLERS), + io.Combo.Input("draft_scheduler", options=samplers.KSampler.SCHEDULERS), + io.Combo.Input("refiner_sampler_name", options=samplers.KSampler.SAMPLERS), + io.Combo.Input("refiner_scheduler", options=samplers.KSampler.SCHEDULERS), + io.Float.Input("draft_denoise", default=1.0, min=0.0, max=1.0, step=0.01), + io.Float.Input("refiner_denoise", default=1.0, min=0.0, max=1.0, step=0.01), + io.Boolean.Input("preview_latent", default=False, label_on="Show Preview", label_off="Only Sample"), + ], + outputs=[ + io.Latent.Output("LATENT"), + ] + ) + + @classmethod + def execute(cls, **kwargs) -> io.NodeOutput: + draft_steps = kwargs["draft_steps"] + refiner_steps = kwargs["refiner_steps"] + + args = kwargs.copy() + args.update({ + "steps": draft_steps, + "start_step": 0, + "add_noise": True, + "sampler_name": kwargs["draft_sampler_name"], + "scheduler": kwargs["draft_scheduler"], + "full_denoise": False, + "denoise": kwargs["draft_denoise"], + }) + latent = do_sample(**args) + + args.update({ + "latent": latent, + "steps": draft_steps + refiner_steps, + "start_step": draft_steps, + "add_noise": True, + "sampler_name": kwargs["refiner_sampler_name"], + "scheduler": kwargs["refiner_scheduler"], + "full_denoise": True, + "denoise": kwargs["refiner_denoise"], + }) + latent = do_sample(**args) + + return io.NodeOutput(latent) + + def execute_guided_sampling(**kwargs): guider, latent, sigmas, random_noise, sampler, preview_latent = ( kwargs.get("guider"), @@ -73,6 +316,7 @@ class TT_GuidedKSamplerNode(io.ComfyNode): io.Sigmas.Input("sigmas"), io.Sampler.Input("sampler"), io.Noise.Input("random_noise"), + io.Boolean.Input("preview_latent", default=False, label_on="Show Preview", label_off="Only Sample"), ], outputs=[ io.Latent.Output("SAMPLES") @@ -103,6 +347,7 @@ class TT_GuidedUpscaleKSamplerNode(io.ComfyNode): io.Boolean.Input("scale_latent", default=False, label_on="Scale", label_off="Skip"), io.Combo.Input("scale_factor", options=SCALE_FACTORS, default="1x", advanced=True), io.Combo.Input("scale_method", options=SCALE_METHODS, default="bicubic", advanced=True), + io.Boolean.Input("preview_latent", default=False, label_on="Show Preview", label_off="Only Sample"), ], outputs=[ io.Latent.Output("SAMPLES") @@ -119,34 +364,6 @@ class TT_GuidedUpscaleKSamplerNode(io.ComfyNode): return io.NodeOutput(samples) -class TT_GuidedKSamplerWithPreviewNode(io.ComfyNode): - @classmethod - def define_schema(cls) -> io.Schema: - return io.Schema( - node_id="TT_GuidedKSamplerWithPreviewNode", - display_name="TT Guided KSampler (With Preview)", - category=CATEGORY, - description="", - inputs=[ - io.Latent.Input("latent"), - io.Guider.Input("guider"), - io.Sigmas.Input("sigmas"), - io.Sampler.Input("sampler"), - io.Noise.Input("random_noise"), - io.Boolean.Input("preview_latent", default=True, label_on="Show Peview", label_off="Only Sample"), - ], - outputs=[ - io.Latent.Output("SAMPLES") - ] - ) - - @classmethod - def execute(cls, **kwargs) -> io.NodeOutput: - samples = execute_guided_sampling(**kwargs) - - return io.NodeOutput(samples) - - # ============================================================================== # V3 entrypoint — registers context nodes with ComfyUI # ============================================================================== @@ -155,9 +372,12 @@ class SamplingNodesExtension(ComfyExtension): @override async def get_node_list(self) -> list[type[io.ComfyNode]]: return [ + TT_KSamplerNode, + TT_KSamplerAdvancedNode, + TT_KSamplerContextNode, + TT_KSamplerTwoStageNode, TT_GuidedKSamplerNode, TT_GuidedUpscaleKSamplerNode, - TT_GuidedKSamplerWithPreviewNode, ] @@ -170,7 +390,10 @@ async def comfy_entrypoint() -> SamplingNodesExtension: # ============================================================================== __all__ = [ + "TT_KSamplerNode", + "TT_KSamplerAdvancedNode", + "TT_KSamplerContextNode", + "TT_KSamplerTwoStageNode", "TT_GuidedKSamplerNode", "TT_GuidedUpscaleKSamplerNode", - "TT_GuidedKSamplerWithPreviewNode", ] diff --git a/nodes_vae.py b/nodes_vae.py index 9f46d5b..e9595e6 100644 --- a/nodes_vae.py +++ b/nodes_vae.py @@ -4,7 +4,9 @@ from typing import override import torch -from comfy_api.latest import IO, ComfyExtension +from comfy_api.latest import io, ComfyExtension + +CATEGORY="TenserTensor/VAE" TILE_SIZE, OVERLAP = 512, 64 @@ -34,6 +36,90 @@ def vae_decode(latent, vae, tile_width=TILE_SIZE, tile_height=TILE_SIZE, overlap return images +class TT_KSamplerNode(io.ComfyNode): + @classmethod + def define_schema(cls) -> io.Schema: + return io.Schema( + node_id="TT_KSamplerNode", + display_name="TT_KSampler", + category=CATEGORY, + description="", + inputs=[ + + ], + outputs=[ + + ] + ) + + @classmethod + def execute(cls, **kwargs) -> io.NodeOutput: + raise NotImplementedError + + +class TT_KSamplerAdvancedNode(io.ComfyNode): + @classmethod + def define_schema(cls) -> io.Schema: + return io.Schema( + node_id="TT_KSamplerAdvancedNode", + display_name="TT_KSampler (Advanced)", + category=CATEGORY, + description="", + inputs=[ + + ], + outputs=[ + + ] + ) + + @classmethod + def execute(cls, **kwargs) -> io.NodeOutput: + raise NotImplementedError + + +class TT_KSamplerContextNode(io.ComfyNode): + @classmethod + def define_schema(cls) -> io.Schema: + return io.Schema( + node_id="TT_KSamplerContextNode", + display_name="TT_KSampler (Context)", + category=CATEGORY, + description="", + inputs=[ + + ], + outputs=[ + + ] + ) + + @classmethod + def execute(cls, **kwargs) -> io.NodeOutput: + raise NotImplementedError + + +class TT_KSamplerTwoStageNode(io.ComfyNode): + @classmethod + def define_schema(cls) -> io.Schema: + return io.Schema( + node_id="TT_KSamplerTwoStageNode", + display_name="TT_KSampler (Two Stage)", + category=CATEGORY, + description="", + inputs=[ + + ], + outputs=[ + + ] + ) + + @classmethod + def execute(cls, **kwargs) -> io.NodeOutput: + raise NotImplementedError + + # ============================================================================== # V3 entrypoint — registers context nodes with ComfyUI # ============================================================================== diff --git a/web/docs/TT_KSamplerAdvancedNode.md b/web/docs/TT_KSamplerAdvancedNode.md new file mode 100644 index 0000000..610781b --- /dev/null +++ b/web/docs/TT_KSamplerAdvancedNode.md @@ -0,0 +1,40 @@ +## TT KSampler (Advanced) *TT_KSamplerAdvancedNode* + +*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* + +Extended KSampler with fine-grained control over noise, denoising range, and step boundaries. Useful for multi-stage workflows and img2img. + +### Inputs + +| Parameter | Type | Required | Description | +|------------------|--------------|----------|---------------------------------------------------------| +| `model` | MODEL | Yes | Diffusion model | +| `positive` | CONDITIONING | Yes | Positive conditioning | +| `negative` | CONDITIONING | Yes | Negative conditioning | +| `latent` | LATENT | Yes | Input latent tensor | +| `add_noise` | BOOLEAN | Yes | Random Noise — use random noise; Zero Noise — use zeros | +| `full_denoise` | BOOLEAN | Yes | Complete — force full denoise; Partial — stop early | +| `denoise` | FLOAT | Yes | Denoising strength, default 1.0 | +| `seed` | INT | Yes | Generation seed | +| `steps` | INT | Yes | Total number of sampling steps, default 30 | +| `cfg` | FLOAT | Yes | Guidance scale, default 3.0 | +| `start_step` | INT | No | Step to start sampling from, default 0 | +| `last_step` | INT | No | Step to stop sampling at, default 10000 | +| `sampler_name` | COMBO | Yes | Sampler algorithm | +| `scheduler` | COMBO | Yes | Noise schedule | +| `preview_latent` | BOOLEAN | No | Show step-by-step latent preview during sampling | + +### Outputs + +| Parameter | Type | Description | +|-----------|--------|-----------------------| +| `LATENT` | LATENT | Sampled latent tensor | + +### Usage + +Use `start_step` and `last_step` to run only a portion of the schedule — useful for chaining two samplers in a draft/refine workflow. Set `add_noise` +to Zero Noise when passing a pre-noised latent from a previous stage. + +--- + +[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_KSamplerContextNode.md b/web/docs/TT_KSamplerContextNode.md new file mode 100644 index 0000000..f920005 --- /dev/null +++ b/web/docs/TT_KSamplerContextNode.md @@ -0,0 +1,29 @@ +## TT KSampler (Context) *TT_KSamplerContextNode* + +*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* + +Context-based KSampler that reads all sampling parameters from a connected context object. Designed for use in context-driven pipelines where model, +latent, and workflow config are passed as a single object. + +### Inputs + +| Parameter | Type | Required | Description | +|------------------|---------|----------|----------------------------------------------------------| +| `context` | CONTEXT | Yes | Pipeline context with model, latent, and workflow config | +| `preview_latent` | BOOLEAN | No | Show step-by-step latent preview during sampling | + +### Outputs + +| Parameter | Type | Description | +|-----------|---------|-------------------------------------| +| `CONTEXT` | CONTEXT | Updated context with sampled latent | +| `LATENT` | LATENT | Sampled latent tensor | + +### Usage + +Connect a context output from a workflow settings or text encoder node. The node reads `model`, `latent`, `seed`, `steps`, `cfg`, `sampler_name`, and +`scheduler` from the context automatically. Sampled latent is written back into the context for downstream nodes. + +--- + +[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_KSamplerNode.md b/web/docs/TT_KSamplerNode.md new file mode 100644 index 0000000..b8030c5 --- /dev/null +++ b/web/docs/TT_KSamplerNode.md @@ -0,0 +1,35 @@ +## TT KSampler *TT_KSamplerNode* + +*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* + +Standard KSampler node with built-in latent preview support. Accepts model, conditioning, and latent as separate inputs. + +### Inputs + +| Parameter | Type | Required | Description | +|------------------|--------------|----------|--------------------------------------------------| +| `model` | MODEL | Yes | Diffusion model | +| `positive` | CONDITIONING | Yes | Positive conditioning | +| `negative` | CONDITIONING | Yes | Negative conditioning | +| `latent` | LATENT | Yes | Input latent tensor | +| `seed` | INT | Yes | Generation seed | +| `steps` | INT | Yes | Number of sampling steps, default 30 | +| `cfg` | FLOAT | Yes | Guidance scale, default 3.0 | +| `sampler_name` | COMBO | Yes | Sampler algorithm | +| `scheduler` | COMBO | Yes | Noise schedule | +| `preview_latent` | BOOLEAN | No | Show step-by-step latent preview during sampling | + +### Outputs + +| Parameter | Type | Description | +|-----------|--------|-----------------------| +| `LATENT` | LATENT | Sampled latent tensor | + +### Usage + +Connect `MODEL`, `CONDITIONING`, and `LATENT` outputs from loader and encoder nodes. Enable `preview_latent` to see intermediate results during +sampling. + +--- + +[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_KSamplerTwoStageNode.md b/web/docs/TT_KSamplerTwoStageNode.md new file mode 100644 index 0000000..8dd941f --- /dev/null +++ b/web/docs/TT_KSamplerTwoStageNode.md @@ -0,0 +1,41 @@ +## TT KSampler (Two Stage) *TT_KSamplerTwoStageNode* + +*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* + +Runs sampling in two sequential stages — draft and refine — in a single node. Draft stage generates a rough result, refine stage continues from where +draft stopped with different sampler settings. + +### Inputs + +| Parameter | Type | Required | Description | +|------------------------|--------------|----------|--------------------------------------------------| +| `model` | MODEL | Yes | Diffusion model | +| `positive` | CONDITIONING | Yes | Positive conditioning | +| `negative` | CONDITIONING | Yes | Negative conditioning | +| `latent` | LATENT | Yes | Input latent tensor | +| `seed` | INT | Yes | Generation seed | +| `cfg` | FLOAT | Yes | Guidance scale, default 3.0 | +| `draft_steps` | INT | Yes | Number of draft stage steps, default 25 | +| `refiner_steps` | INT | Yes | Number of refine stage steps, default 25 | +| `draft_sampler_name` | COMBO | Yes | Sampler algorithm for draft stage | +| `draft_scheduler` | COMBO | Yes | Noise schedule for draft stage | +| `refiner_sampler_name` | COMBO | Yes | Sampler algorithm for refine stage | +| `refiner_scheduler` | COMBO | Yes | Noise schedule for refine stage | +| `draft_denoise` | FLOAT | No | Denoising strength for draft stage, default 1.0 | +| `refiner_denoise` | FLOAT | No | Denoising strength for refine stage, default 1.0 | +| `preview_latent` | BOOLEAN | No | Show step-by-step latent preview during sampling | + +### Outputs + +| Parameter | Type | Description | +|-----------|--------|-----------------------| +| `LATENT` | LATENT | Sampled latent tensor | + +### Usage + +Use different samplers and schedulers for each stage — for example, `dpmpp_2m` with `karras` for draft and `euler` with `normal` for refine. Total +steps equal `draft_steps + refiner_steps`. + +--- + +[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)