- Python 99.5%
- JavaScript 0.5%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
- Implement complete Bevy 0.18.1 WASM vendor directory - Add strawberry-themed pink background with 3D white text effects - Create user-editable text configuration system - Add comprehensive Python pytest suite (18 tests passing) - Add Rust test framework for core functionality - Fix all Bevy 0.18.1 API compatibility issues - Implement cosmic text effects (Plasma, Nebula, Quantum, Stellar) - Add particle systems and 3D projection effects - Create JavaScript bridge for ComfyUI communication - Add automated WASM build pipeline with wasm-bindgen - Include web interface with interactive configuration panel Features: - Pink strawberry theme with animated glow effects - 3D white text with cosmic particle systems - Real-time user-editable configuration - WebGL2 rendering with WASM optimization - Comprehensive test coverage - Modular effect system architecture |
||
| build | ||
| docs | ||
| nodes | ||
| scripts | ||
| vendor/bevy | ||
| web | ||
| .gitignore | ||
| __init__.py | ||
| CHANGELOG.md | ||
| config.yaml | ||
| EULER_ANCESTRAL_WOLF.md | ||
| package-lock.json | ||
| package.json | ||
| pytest.ini | ||
| README.md | ||
| README_STREAMSCRIPTABLE.md | ||
| requirements.txt | ||
| SAMPLER_EVALUATOR.md | ||
| SIGMA_EVALUATOR.md | ||
| SIMPLE_SAMPLER_EVALUATOR.md | ||
| test_bevy_wasm_standalone.py | ||
| wolf_sigmas.py | ||
ComfyUI Wolf Sigmas
⚠️ Security Warning: Remote Code Execution ⚠️
This custom node pack includes nodes that can execute arbitrary Python code provided by the user or embedded within imported workflows/scripts. Specifically, the following nodes pose a risk if you load untrusted content:
Wolf Sigma Script Evaluator (🐺)Wolf Sampler Script Evaluator (🐺)Wolf Simple Sampler Script (🐺)Scriptable Empty Latent (🐺)Wolf Simple Sampler Script (🐺)
Executing scripts from untrusted sources can lead to security vulnerabilities, including remote code execution on your machine.
Please exercise extreme caution:
- NEVER load or run workflows, scripts, or JSON files containing these nodes from sources you do not fully trust.
- Always review any Python code within these nodes before execution if you are unsure of its origin or purpose.
The authors of this node pack are not responsible for any damage or security incidents that may occur from the misuse of these script evaluation features.
Configuration
Edit config.yaml in this folder (or set env vars) to change behavior:
- disable_scriptable_nodes (default:
false): Iftrue, all nodes that execute user Python (scriptable nodes and script evaluators) are not registered. Use in locked-down environments to disable remote code execution. - Env override:
COMFYUI_WOLFSIGMAS_DISABLE_SCRIPTABLE_NODES=1forces scriptable nodes off.
This custom node pack for ComfyUI provides a suite of tools for generating and manipulating sigma schedules for diffusion models. These nodes are particularly useful for fine-tuning the sampling process, experimenting with different step counts, and adapting schedules for specific models.
Node overview
flowchart TB
subgraph sigma_utils [Sigma utilities]
Get[Get Sigmas]
Set[Set from JSON]
ToJSON[To JSON]
end
subgraph transforms [Sigma transforms]
Power[Power Transform]
ClampT0[Clamp T0]
ShiftScale[Shift and Scale]
Normalize[Normalize Range]
Quantize[Quantize]
RespaceLogCos[Respace Log-Cosine]
Clip[Clip Values]
Reverse[Reverse]
ReverseRescale[Reverse and Rescale]
Slice[Slice]
Insert[Insert Value]
AddNoise[Add Noise]
end
subgraph generators [Sigma generators]
Geometric[Geometric Progression]
Polynomial[Polynomial]
Tanh[Tanh Generator]
end
subgraph script_eval [Script evaluators]
SigmaScript[Sigma Script Evaluator]
SamplerScript[Sampler Script Evaluator]
SimpleSampler[Simple Sampler Script]
end
subgraph scriptable [Scriptable nodes]
EmptyLatent[Scriptable Empty Latent]
ScriptableImage[Scriptable Image]
ScriptableMask[Scriptable Mask]
ScriptableLatent[Scriptable Latent]
ScriptableLatentFlux2[Scriptable Latent Flux2]
FractalImage[Fractal Image]
TextProj[Text Projection 3D]
ScriptText[Scriptable Text]
MdText[Markdown Text]
end
subgraph inspection [Model inspection]
Structure[Structure Explorer]
Activation[Activation Inspector]
Depatchify[Depatchify]
end
sigma_utils --> transforms
sigma_utils --> generators
script_eval --> SIGMAS[SIGMAS]
script_eval --> SAMPLER[SAMPLER]
ScriptableImage --> SHADER_GALLERY[Shader gallery]
FractalImage --> SHADER_GALLERY
Scriptable Image (🐺) has a dedicated Scriptable Image API and Shader Gallery with copy-paste scripts for: underwater, water caustics, fire/heat, smoke/fog, vignette, film grain, chromatic aberration, lens distortion, scanlines, and simple bloom.
For deeper math-heavy implementations, see Advanced PyTorch Shaders (refraction-density caustics, flow-band caustics, multi-light torch shading, chromatic refraction, edge-aware bloom, filmic split-tone).
Advanced image ops for edit models and IP-Adapter: Edge and structure, Style and color, Composition and layout, Lighting and depth — each doc has math and runnable Scriptable Image scripts.
Text Projection (3D, Mask) (🐺) renders 2D/3D-style text onto an image and outputs a mask for inpainting/guidance. See Text Projection (IMAGE_OPS_TEXT_PROJECTION.md) for styles, parameters, and the optional draggable position UI (WolfBypass).
Table of Contents
- ComfyUI Wolf Sigmas
- ⚠️ Security Warning: Remote Code Execution ⚠️
- Table of Contents
- Advanced
- General Sigma Utilities
- Sigma Transformation
- Wolf Sigma Power Transform
- Wolf Sigma Transform (Clamp T0)
- Wolf Sigma Transform (Shift & Scale)
- Wolf Sigma Transform (Normalize Range)
- Wolf Sigma Transform (Quantize)
- Wolf Sigma Transform (Respace Log-Cosine)
- Sigma Clip Values (🐺)
- Sigma Schedule Reverser (🐺)
- Wolf Sigma Reverse and Rescale
- Sigma Slice (🐺)
- Sigma Insert Value (🐺)
- Sigma Add Noise (🐺)
- General Purpose Sigma Generators
- Flux2 / Flux2-Klein image and latent nodes
Advanced
Scriptable Sigma Generator
For advanced users who need maximum flexibility, the Wolf Sigma Script Evaluator (🐺) node allows for the creation of custom sigma schedules by executing a user-provided Python script. This provides a powerful way to define complex or experimental schedules.
For detailed information on how to use the script evaluator, its inputs, outputs, scripting capabilities, and example scripts, please see the Wolf Sigma Script Evaluator Documentation.
Scriptable Sampler Generator
Similarly, for users wishing to implement entirely custom sampling algorithms, the Wolf Sampler Script Evaluator (🐺) node enables the definition of new samplers through Python scripts. This node integrates with ComfyUI's KSampler system, allowing custom samplers to be used like any built-in sampler.
For detailed information on how to use the sampler script evaluator, its scripting requirements, parameters, and example sampler implementations (like Euler and Euler Ancestral), please see the Wolf Sampler Script Evaluator Documentation.
Simple Scriptable Sampler
The Wolf Simple Sampler Script (🐺) node offers a streamlined way to define custom sampling logic by executing a user-provided Python script for the core denoising loop. This is simpler than implementing a full KSampler-compatible class and is well-suited for direct experimentation with sampling algorithms. The provided script is given access to necessary variables like the model, initial latents, and the sigma schedule, and is expected to return the final denoised latents.
- Class:
WolfSimpleSamplerScriptEvaluator - Display Name:
Wolf Simple Sampler Script (🐺) - Category:
sampling/ksampler_wolf - Description: Executes a user-provided Python script that defines the core sampling loop. The script receives variables like the model, initial latents (
x_initial), and the sigma schedule (sigmas_schedule), and must assign the final denoised latents to a variable namedlatents. A default script implementing a basic Euler sampler is provided as a template. - Inputs:
script:STRING(multiline, default: Python script for basic Euler sampling) - The Python script implementing the sampling loop.
- Outputs:
SAMPLER:SAMPLER- A ComfyUI compatible sampler object that can be directly used with KSampler nodes.
For detailed information on the scripting environment, available variables, requirements, and example scripts, please refer to the Wolf Simple Sampler Script Evaluator Documentation.
Flux2 / Flux2-Klein image and latent nodes
The pack includes scriptable image and latent nodes that work with Flux2 and Flux2-Klein (128-channel latent, H/16×W/16):
- Scriptable Image (🐺) — Run Python on IMAGE with Pillow, OpenCV, numpy; set
output_image. API and Shader Gallery (underwater, caustics, fire, smoke, vignette, grain, chromatic aberration, lens distortion, scanlines, bloom). - Scriptable Latent (🐺) — Model-aware scriptable latent (SDXL/FLUX/Flux2); set
output_latent_samples. - Scriptable Latent Flux2 (🐺) — Flux2/Flux2-Klein only: 128ch, optional reference latent and Klein helpers (channel mask, spatial fade).
- Image Expression (🐺) — Single expression on IMAGE (e.g.
torch.clamp(image * a + b, 0, 1)). - Flux2 Latent Batch Ops (🐺) — Concat, slice, blend, or mask Flux2 latents without scripting.
For detailed documentation, injected variables, and copy-paste example scripts for Flux2 and Flux2-Klein edit/diffusion workflows, see Flux2-Klein nodes documentation (docs/FLUX2_KLEIN_NODES.md). The Scriptable Image node can optionally output a MASK (set output_mask in the script); see the same doc for simple and advanced mask-operation examples. Scriptable Latent Flux2 (🐺) has a detailed guide (Flux2-Klein latent format, channel layout, Klein helpers, and many effects: half-and-half ref, radial blend, channel bands, invert, tile, edge-only ref, low-freq, per-quadrant, gradient strength) in docs/SCRIPTABLE_LATENT_FLUX2.md. Scriptable Conditioning (🐺) has full documentation (contract, meta keys, beginner/intermediate/advanced examples, Flux2-Klein reference latents) in docs/SCRIPTABLE_CONDITIONING.md. A plan for additional scriptable nodes (Scriptable Mask, Scriptable String, Scriptable Conditioning, Comfy I/O utilities) is in docs/SCRIPTABLE_NODES_AND_IO_PLAN.md.
Text Projection (3D, Mask) (🐺)
- Class:
WolfTextProjection - Display Name:
Text Projection (3D, Mask) (🐺) - Category:
image/text - Description: Renders text onto an input image with optional 3D-like styles (flat, shadow, bevel, perspective, extrude, outline, glow, emboss, sticker) and outputs the composited IMAGE and a MASK (text + effects alpha) for inpainting or control.
Styles: Flat, Shadow, Bevel, Perspective, Extrude (fake depth), Outline (stroke), Glow (soft halo), Emboss (light/dark edge), Sticker (border + drop shadow). Optional parameters per style: shadow offset/blur, depth steps/offset (Extrude), outline width/color (Outline/Sticker), glow radius/intensity (Glow), bevel strength (Bevel/Emboss).
UI (ComfyUI WolfBypass): If the WolfBypass extension is installed, the node gets an extra widget: a small preview with draggable anchors for text position (x, y) and shadow offset (shadow_dx, shadow_dy), and style-specific sliders that show/hide based on the selected style.
See docs/IMAGE_OPS_TEXT_PROJECTION.md for data flow and usage.
Text 3D Projection (Blender) (🐺)
- Class:
WolfText3DProjection - Display Name:
Text 3D Projection (Blender) (🐺) - Category:
image/text - Description: Renders 3D text to IMAGE and MASK via Blender (headless subprocess). Full TrueType/OpenType support, extrude, bevel, Cycles or Eevee, GPU-accelerated. No EGL/GLX/Node.js; works in Docker with
apt install blender.
Inputs: text (optional STRING, CodeMirror via PYTHON_SCRIPT when WolfBypass is installed; connect any STRING to override), width/height, font (Built-in or system fonts), size_scale, extrude, bevel_depth, bevel_resolution, color, camera/samples/render_engine, optional background image to composite onto.
Font list: "Built-in" (Blender default) or system fonts from fontconfig (Linux), Windows Fonts, or macOS font directories; path is passed to Blender.
Blender script: scripts/blender_render_text.py is invoked as blender -b -P blender_render_text.py -- params.json out.png. The node writes params JSON and reads the rendered PNG (RGBA to image + mask).
Docker: The ComfyUI Dockerfile includes blender (apt). No Node.js or npm is required for this node. For custom fonts, mount a directory (e.g. -v /host/fonts:/fonts) and use a font path like /fonts/MyFont.ttf (or select a system font discovered from that path).
Scriptable Empty Latent (🐺)
The WolfScriptableEmptyLatent node provides a highly flexible way to generate initial latent noise for the diffusion process. It allows users to define the generation logic using a Python script, enabling complex noise patterns, structured noise, or any custom initialization beyond simple Gaussian noise or zeros. The default script implements a sophisticated "Calibrated Structured Noise" combining Perlin and Gaussian noise, scaled by the initial sigma of a provided schedule and the VAE's scaling factor.
- Class:
WolfScriptableEmptyLatent - Display Name:
Scriptable Empty Latent (🐺) - Category:
latent/noise(or your preferred category likeWolf Custom Nodes/Latent) - Description: Executes a user-provided Python script to generate an initial latent tensor. The script has access to various parameters like dimensions, seed, the VAE model, a sigma schedule, and Perlin noise configuration. It must produce a latent tensor of the correct NCHW shape.
⚠️ Security Warning
This node executes arbitrary Python code. Only use scripts from trusted sources. Review any script before execution if you are unsure of its origin.
Inputs
model:MODEL- The main diffusion model, used primarily to access VAE properties likelatent_format.scale_factor.width:INT(default: 1024, min: 64, step: 8) - Target width of the image (latent width will bewidth // 8).height:INT(default: 1024, min: 64, step: 8) - Target height of the image (latent height will beheight // 8).batch_size:INT(default: 1, min: 1, max: 64) - Number of latent images to generate in the batch.seed:INT(default: 0,control_after_generate: True) - Seed for random number generation within the script.sigmas:SIGMAS- An input sigma schedule (tensor). The default script uses the first sigma (sigmas[0]) for calibration.perlin_blend_factor:FLOAT(default: 0.5, min: 0.0, max: 1.0) - Blend factor between Gaussian and Perlin noise in the default script. 0.0 for pure Gaussian, 1.0 for pure Perlin.perlin_res_factor_h:INT(default: 8, min: 1, max: 128) - Resolution factor for Perlin noise height. Higher values mean lower frequency / larger features. Latent height is divided by this.perlin_res_factor_w:INT(default: 8, min: 1, max: 128) - Resolution factor for Perlin noise width.perlin_frequency_factor:FLOAT(default: 2.0, min: 1.01, max: 4.0) - Frequency multiplier for each Perlin octave.perlin_octaves:INT(default: 4, min: 1, max: 10) - Number of Perlin noise octaves to sum.perlin_persistence:FLOAT(default: 0.5, min: 0.01, max: 1.0) - Amplitude persistence factor between Perlin octaves.perlin_contrast_scale:FLOAT(default: 1.0, min: 0.1, max: 20.0, step: 0.1, tooltip: "Scales Perlin noise before normalization to enhance its features.") - Multiplies the raw Perlin noise before it's normalized, to amplify its structural features.script:STRING(multiline, default: Python script for calibrated structured noise) - The Python script to execute for latent generation.
Outputs
LATENT:LATENT- A dictionary containing the generated latent tensor under the key"samples".
Scripting Environment
The Python script executed by this node has access to the following:
Local Variables:
width,height,batch_size,seed: Integers as provided to the node.sigmas: Atorch.Tensorof sigma values, moved to the executiondevice.model: TheMODELobject passed to the node.device: A string representing the torch device for execution (e.g.,"cuda:0","cpu").perlin_params: A dictionary containing allperlin_*input values:{'blend_factor', 'res_factor_h', 'res_factor_w', 'frequency_factor', 'octaves', 'persistence', 'perlin_contrast_scale'}.output_latent_samples: InitiallyNone. The script must assign the final generated latent tensor (NCHW float32 tensor ondevice) to this variable.
Global Helper Modules & Functions:
torch: The PyTorch module.math: The Python math module.F:torch.nn.functional.rand_perlin_2d_octaves_fn(shape, res, octaves, persistence, frequency_factor, device): Function to generate multi-octave 2D Perlin noise.deviceargument should be the string fromscript_locals.rand_perlin_2d_fn(shape, res, fade_func, device): Function to generate single-octave 2D Perlin noise._fade_fn(t): The quintic fade function6t^5 - 15t^4 + 10t^3used in Perlin noise.
Default Script: Calibrated Structured Noise Mathematics
The default script generates initial noise by blending Perlin noise with Gaussian noise and then calibrates its magnitude using the provided sigmas and VAE properties.
-
Parameter Setup:
- Latent dimensions:
H_L = \text{height} // 8,W_L = \text{width} // 8. (Note: For FLUX models, the script usesH_L = \text{height} // 8, W_L = \text{width} // 8as well, but with 16 channels). - Target sigma
\sigma_{target}is taken as the first value from the inputsigmastensor. - VAE scaling factor
s_{VAE}is determined based on the model type (e.g., 0.18215 for typical SDXL, 1.0 for FLUX). This value is logged for informational purposes. - The effective sigma for scaling the final
\mathcal{N}(0, 1)noise is:$$ \sigma_{eff} = \sigma_{target
This means the standard deviation of the final output noise tensor is intended to match the
target_sigmafrom the input schedule. - Latent dimensions:
-
Gaussian Noise Generation (
G):- Standard Gaussian noise is generated for each element in the latent tensor
(B, C, H_L, W_L), whereBis batch size andC=4channels. G_{b,c,h,w} \sim \mathcal{N}(0, 1)
- Standard Gaussian noise is generated for each element in the latent tensor
-
Perlin Noise Generation (
P):- Generated independently for each batch item and channel, using
rand_perlin_2d_octaves_fn. - Base Perlin Noise (
rand_perlin_2d_fn):- A grid of random 2D gradient vectors is created. For a point
(x,y)in the latent space, its position within a grid cell(u,v)(whereu,v \in [0,1]) is determined. - Dot products are computed between the gradient vectors at the cell's four corners (
g_{00}, g_{10}, g_{01}, g_{11}) and the displacement vectors from the point to these corners.dp_{00} = g_{00} \cdot (u, v)dp_{10} = g_{10} \cdot (u-1, v)dp_{01} = g_{01} \cdot (u, v-1)dp_{11} = g_{11} \cdot (u-1, v-1)
- These dot products are interpolated using a fade function
\text{fade}(t) = 6t^5 - 15t^4 + 10t^3to ensure smooth transitions. Lett_u = \text{fade}(u)andt_v = \text{fade}(v). - Lerp (Linear Interpolation):
\text{lerp}(a, b, w) = a + w(b-a).v_0 = \text{lerp}(dp_{00}, dp_{10}, t_u)v_1 = \text{lerp}(dp_{01}, dp_{11}, t_u)
- The final Perlin value for that point is
\text{lerp}(v_0, v_1, t_v), typically scaled by\sqrt{2}.
- A grid of random 2D gradient vectors is created. For a point
- Octaves: Multiple layers (octaves) of Perlin noise are summed. For each octave
i:- Frequency
f_i = \text{frequency\_factor}^i. The resolutionresforrand_perlin_2d_fnis scaled byf_i. - Amplitude
A_i = \text{persistence}^i. - The total Perlin noise is
P_{raw} = \sum_{i=0}^{\text{octaves}-1} A_i \times \text{Perlin}_i(\text{shape}, \text{res} \times f_i).
- Frequency
- The base resolution for Perlin noise is determined by
perlin_res_factor_handperlin_res_factor_w:\text{res}_h = \max(1, H_L // \text{perlin\_res\_factor\_h})\text{res}_w = \max(1, W_L // \text{perlin\_res\_factor\_w})
- Generated independently for each batch item and channel, using
-
Perlin Contrast Scaling:
- Let
c_{scale}be theperlin_contrast_scaleinput parameter. - The raw Perlin noise
P_{raw}(generated in step 3) is multiplied byc_{scale}to enhance its features before normalization:$$ P_{scaled} = P_{raw} \times c_{scale
- Let
-
Normalization:
- Both the Gaussian noise
Gand the contrast-scaled Perlin noiseP_{scaled}are independently normalized to have zero mean and unit standard deviation across their spatial dimensions (height and width) for each channel and batch item. For any noise tensorX(hereXwould beGorP_{scaled}):
where$$ X_{norm} = \frac{X - \mu_X}{\sigma_X + \epsilon\mu_Xis the mean ofX,\sigma_Xis its standard deviation, and\epsilonis a small constant (e.g.,10^{-5}) to prevent division by zero. So, we getG_{norm}fromG, andP_{norm}fromP_{scaled}.
- Both the Gaussian noise
-
Blending:
- The normalized Gaussian noise
G_{norm}and normalized (contrast-enhanced) Perlin noiseP_{norm}are blended using theperlin_blend_factor(\alpha_{blend}):
This is equivalent to$$ N_{blend} = (1 - \alpha_{blend}) \cdot G_{norm} + \alpha_{blend} \cdot P_{normtorch.lerp(G_norm, P_norm, perlin_blend_factor).
- The normalized Gaussian noise
-
Re-Normalization of Blended Noise:
- The blended noise
N_{blend}is normalized again to ensure it has zero mean and unit standard deviation:$$ N_{blend, norm} = \frac{N_{blend} - \mu_{N_{blend}}}{\sigma_{N_{blend}} + \epsilon
- The blended noise
-
Final Scaling:
- The re-normalized blended noise
N_{blend, norm}(which is\mathcal{N}(0, 1)) is scaled by theeffective_sigma(which is\sigma_{target}) calculated in step 1:$$ \text{Output Latent} = N_{blend, norm} \times \sigma_{eff
This ensures the initial latent noise has a standard deviation equal to
\sigma_{target}, which is typically expected by samplers using schedules like Karras. - The re-normalized blended noise
Simple Scriptable Empty Latent (🐺)
The WolfSimpleScriptableEmptyLatent node provides a straightforward way to generate initial latent noise using a Python script. It is simpler than the Scriptable Empty Latent (🐺) node and is well-suited for basic latent generation or when custom logic is needed for channel count or initial values, especially with models like FLUX. The default script generates a zero-filled latent tensor, automatically adjusting the number of channels based on the connected model.
- Class:
WolfSimpleScriptableEmptyLatent - Display Name:
Simple Scriptable Empty Latent (🐺) - Category:
latent/noise - Description: Executes a user-provided Python script to generate an initial latent tensor. The script has access to parameters like dimensions and an optional model connection. It must produce a latent tensor of the correct NCHW shape.
⚠️ Simple Security Warning
This node executes arbitrary Python code. Only use scripts from trusted sources. Review any script before execution if you are unsure of its origin.
Simple Inputs
width:INT(default: 1024, min: 64, step: 8) - Target width of the image (latent width will bewidth // 8).height:INT(default: 1024, min: 64, step: 8) - Target height of the image (latent height will beheight // 8).batch_size:INT(default: 1, min: 1, max: 64) - Number of latent images to generate in the batch.device_selection:COMBO["AUTO", "CPU", "GPU"](default: "AUTO") - Specifies the target device for the script execution and the final latent tensor. "AUTO" attempts to use the model's device or falls back to an intermediate device.script:STRING(multiline, default: Python script for model-aware zero latent) - The Python script to execute for latent generation.model:MODEL(optional) - An optional model input. The default script uses this to determine if the model is FLUX-based to set the latent channel count to 16 (otherwise 4).
Simple Outputs
LATENT:LATENT- A dictionary containing the generated latent tensor under the key"samples".
Simple Scripting Environment
The Python script executed by this node has access to the following:
Local Variables:
width,height,batch_size: Integers as provided to the node.model: TheMODELobject passed to the node (can beNone).device: A string representing the torch device for execution (e.g.,"cuda:0","cpu"), determined by thedevice_selectioninput and available hardware/model.output_latent_samples: InitiallyNone. The script must assign the final generated latent tensor (NCHW float32 tensor ondevice) to this variable.
Global Helper Modules & Functions:
torch: The PyTorch module.math: The Python math module.
Default Script: Model-Aware Zero Latent
The default script generates a zero-filled latent tensor with dimensions appropriate for the specified width, height, and batch_size.
-
Channel Determination:
- It inspects the connected
model(if any). - If the model is identified as a FLUX model (by checking
model.model_typeor class name),num_latent_channelsis set to 16. - Otherwise,
num_latent_channelsdefaults to 4 (standard for SD, SDXL, etc.). - If no model is connected, it defaults to 4 channels.
- Prints the detected model type and chosen channel count.
- It inspects the connected
-
Latent Dimensions:
- Latent height:
H_L = \text{height} // 8. - Latent width:
W_L = \text{width} // 8.
- Latent height:
-
Tensor Generation:
- The target shape is
(B, C, H_L, W_L), whereBisbatch_sizeandCis the determinednum_latent_channels. - A
torch.zerostensor of thisshapeis created withdtype=torch.float32on the specifieddevice. - This tensor is assigned to
output_latent_samples. - Prints the generation parameters and target shape.
- The target shape is
This provides a basic, flexible starting point for latent generation, particularly useful for ensuring compatibility with models requiring different latent channel depths.
General Sigma Utilities
Get Sigmas (🐺)
- Class:
WolfSigmasGet - Display Name:
Get Sigmas (🐺) - Category:
sampling/sigmas_wolf - Description: Retrieves the sigma schedule from a given model based on the specified sampler settings (steps, denoise, scheduler type). This is a utility to extract the sigmas that ComfyUI would normally calculate internally.
- Inputs:
model:MODEL- The diffusion model.steps:INT(default: 20, min: 1, max: 10000) - The total number of sampling steps.denoise:FLOAT(default: 1.0, min: 0.0, max: 1.0, step: 0.01) - The denoising strength. A value of 1.0 uses all steps, while a smaller value uses a fraction of the steps from the end of the schedule.scheduler:COMBO[comfy.samplers.KSampler.SCHEDULERS]- The ComfyUI native scheduler type to use for sigma calculation.
- Outputs:
SIGMAS:SIGMAS- The calculated sigma tensor.sigmas_json:STRING- A JSON string representation of the sigmas list.
Set Sigmas from JSON (🐺)
- Class:
WolfSigmasSet - Display Name:
Set Sigmas from JSON (🐺) - Category:
sampling/sigmas_wolf - Description: Converts a JSON string representing a list of sigma values into a SIGMAS tensor that can be used by samplers. Useful for manually defining or importing custom sigma schedules.
- Inputs:
sigmas_json:STRING(multiline, default:"[14.61, ..., 0.0]") - A JSON string representing a list of numbers (e.g.,[14.615, 8.0, 0.029, 0.0]).
- Outputs:
SIGMAS:SIGMAS- The sigma tensor created from the JSON input.
Wolf Sigmas to JSON
- Class:
WolfSigmasToJSON - Display Name:
Wolf Sigmas to JSON - Category:
sampling/sigmas_wolf/util - Description: Converts an input SIGMAS object to its JSON string representation. Useful for debugging or exporting sigma schedules.
- Inputs:
sigmas:SIGMAS- The input SIGMAS object.
- Outputs:
sigmas_json:STRING- A JSON string representation of the sigmas list.
Sigma Transformation
Formulas (reference):
- Power:
s_{\mathrm{norm}} = (s - s_{\min})/(s_{\max} - s_{\min}),s_{\mathrm{new}} = s_{\min} + s_{\mathrm{norm}}^{\mathrm{power}}(s_{\max} - s_{\min}). - Shift & scale:
\sigma_{\mathrm{new}} = (\sigma + \mathrm{shift}) \cdot \mathrm{scale}(final 0 unchanged). - Respace log-cosine:
t \in [0,1],\mathrm{cos\_t} = 0.5(1 - \cos(\pi t)),\log\sigma = \log\sigma_{\min} + (1 - \mathrm{cos\_t})(\log\sigma_{\max} - \log\sigma_{\min}),\sigma = \exp(\log\sigma). - Geometric:
\sigma_0 = \sigma_{\mathrm{start}},\sigma_{i+1} = \sigma_i \cdot r(clamped by\sigma_{\min}), last step 0. - Polynomial:
t_{\mathrm{norm}} = i/(n-1),\sigma_i = \sigma_{\min} + (\sigma_{\max} - \sigma_{\min})(1 - t_{\mathrm{norm}}^p); last sigma 0. - Tanh:
tfrom scale to-\mathrm{scale},\mathrm{tanh\_vals} = \tanh(t)normalized to [0,1], linearly mapped to[\sigma_{\min}, \sigma_{\max}]; last sigma 0.
Example sigma chain: Get Sigmas → Power Transform → Respace Log-Cosine → use in KSampler (or Set from JSON if you need to round-trip).
flowchart LR
Model[MODEL] --> Get[Get Sigmas]
Get --> Power[Power Transform]
Power --> Respace[Respace Log-Cosine]
Respace --> KSampler[KSampler]
Wolf Sigma Power Transform
- Class:
WolfSigmaPowerTransform - Display Name:
Wolf Sigma Power Transform - Category:
sampling/sigmas_wolf/transform - Description: Applies a power transformation to an existing sigma schedule.
The active sigmas (excluding a potential final 0.0) are normalized to the range
[0,1]. Letsbe an active sigma,s_{min}ands_{max}be the min/max of the active range. Normalized sigma:s_{norm} = (s - s_{min}) / (s_{max} - s_{min}). Powered sigma:s_{powered} = s_{norm}^{\text{power}}. Denormalized sigma:s_{new} = s_{min} + s_{powered} \times (s_{max} - s_{min}).power > 1.0: concentrates steps towards the minimum of the schedule range (smaller steps later).power < 1.0: concentrates steps towards the maximum of the schedule range (smaller steps earlier). - Inputs:
sigmas_in:SIGMAS- The input sigma schedule.power:FLOAT(default: 1.0, min: 0.1, max: 10.0) - The power exponent.override_input_min:FLOAT(default: -1.0) - If >= 0, overrides auto-detected min sigma for normalization.override_input_max:FLOAT(default: -1.0) - If >= 0, overrides auto-detected max sigma for normalization.
- Outputs:
SIGMAS:SIGMAS- The transformed sigma schedule.
Wolf Sigma Transform (Clamp T0)
- Class:
WolfSigmaClampT0 - Display Name:
Wolf Sigma Transform (Clamp T0) - Category:
sampling/sigmas_wolf/transform - Description: Clamps the first sigma (t0) of an incoming schedule to a specified value. Other sigmas are adjusted proportionally if they would exceed t0 or become non-monotonic. The final 0.0 sigma, if present, remains unchanged.
- Inputs:
sigmas_in:SIGMAS- The input sigma schedule.target_t0:FLOAT(default: 1.0, min: 0.0001, max: 1000.0, step: 0.001) - The target value for the first sigma.min_epsilon_spacing:FLOAT(default: 1e-7, min: 1e-9, max: 0.1, step: 1e-7) - Minimum spacing to maintain between sigmas if adjustments are needed.
- Outputs:
SIGMAS:SIGMAS- The transformed sigma schedule with t0 clamped.
Wolf Sigma Transform (Shift & Scale)
- Class:
WolfSigmaShiftAndScale - Display Name:
Wolf Sigma Transform (Shift & Scale) - Category:
sampling/sigmas_wolf/transform - Description: Applies a global shift and scale to all sigmas in a schedule:
Sigmas = (Sigmas + shift) * scale. The final 0.0 sigma, if present, remains unchanged. Monotonicity (decreasing order) and non-negativity are enforced. - Inputs:
sigmas_in:SIGMAS- The input sigma schedule.shift:FLOAT(default: 0.0, min: -100.0, max: 100.0, step: 0.01) - Value to add to each sigma before scaling.scale:FLOAT(default: 1.0, min: 0.01, max: 100.0, step: 0.01) - Value to multiply each shifted sigma by.min_epsilon_spacing:FLOAT(default: 1e-7, min: 1e-9, max: 0.1, step: 1e-7) - Minimum spacing for monotonicity enforcement.
- Outputs:
SIGMAS:SIGMAS- The transformed sigma schedule.
Wolf Sigma Transform (Normalize Range)
- Class:
WolfSigmaNormalizeRange - Display Name:
Wolf Sigma Transform (Normalize Range) - Category:
sampling/sigmas_wolf/transform - Description: Normalizes an existing sigma schedule to a new min/max range. The relative spacing of sigmas is preserved as much as possible. The final 0.0 sigma, if present, remains 0.0.
- Inputs:
sigmas_in:SIGMAS- The input sigma schedule.new_max:FLOAT(default: 1.0, min: 0.0001, max: 1000.0, step: 0.001) - The target maximum sigma value (first sigma).new_min_positive:FLOAT(default: 0.002, min: 0.0001, max: 100.0, step: 0.0001) - The target minimum positive sigma value (last active sigma).min_epsilon_spacing:FLOAT(default: 1e-7, min: 1e-9, max: 0.1, step: 1e-7) - Minimum spacing for monotonicity enforcement.
- Outputs:
SIGMAS:SIGMAS- The normalized sigma schedule.
Wolf Sigma Transform (Quantize)
- Class:
WolfSigmaQuantize - Display Name:
Wolf Sigma Transform (Quantize) - Category:
sampling/sigmas_wolf/transform - Description: Quantizes sigmas in a schedule to a specific number of decimal places or to the nearest multiple of a quantization step. The final 0.0 sigma, if present, remains unchanged.
- Inputs:
sigmas_in:SIGMAS- The input sigma schedule.quantization_method:COMBO["decimal_places", "step_multiple"](default: "decimal_places") - Method for quantization.decimal_places:INT(default: 3, min: 0, max: 10) - Number of decimal places if method isdecimal_places.quantization_step:FLOAT(default: 0.001, min: 1e-7, max: 10.0, step: 0.0001) - Step multiple if method isstep_multiple.rounding_mode:COMBO["round", "floor", "ceil"](default: "round") - Rounding method to use.min_epsilon_spacing:FLOAT(default: 1e-7, min: 1e-9, max: 0.1, step: 1e-7) - Minimum spacing for post-quantization monotonicity enforcement.
- Outputs:
SIGMAS:SIGMAS- The quantized sigma schedule.
Wolf Sigma Transform (Respace Log-Cosine)
- Class:
WolfSigmaRespaceLogCosine - Display Name:
Wolf Sigma Transform (Respace Log-Cosine) - Category:
sampling/sigmas_wolf/transform - Description: Respaces an existing N-step sigma schedule (N+1 sigmas) to have its active points (sigma_max to sigma_min_positive) follow a cosine curve in the log-sigma domain. The number of steps in the output matches the input. The final 0.0 sigma, if present, remains unchanged.
- Inputs:
sigmas_in:SIGMAS- The input sigma schedule.override_sigma_max:FLOAT(default: -1.0) - If >= 0, overrides auto-detected max sigma for spacing. -1 uses max fromsigmas_in.override_sigma_min_positive:FLOAT(default: -1.0) - If >= 0, overrides auto-detected min positive sigma. -1 uses min fromsigmas_in.min_epsilon_spacing:FLOAT(default: 1e-7, min: 1e-9, max: 0.1, step: 1e-7) - Minimum spacing for monotonicity enforcement.
- Outputs:
SIGMAS:SIGMAS- The respaced sigma schedule.
Sigma Clip Values (🐺)
- Class:
WolfSigmaClipValues - Display Name:
Sigma Clip Values (🐺) - Category:
sampling/sigmas_wolf/transformations - Description: Clips individual active sigma values in a schedule to a specified minimum and maximum. The final 0.0 sigma, if present, remains unchanged. Optionally re-ensures strictly decreasing order after clipping.
- Inputs:
sigmas:SIGMAS- The input sigma schedule.min_clip_value:FLOAT(default: 0.001, min: 0.0, max: 1000.0, step: 0.001) - Minimum value to clip sigmas to.max_clip_value:FLOAT(default: 150.0, min: 0.0, max: 1000.0, step: 0.01) - Maximum value to clip sigmas to.ensure_strictly_decreasing:BOOLEAN(default: True) - Whether to enforce strictly decreasing order after clipping.min_epsilon_spacing:FLOAT(default: 1e-5, min: 1e-7, max: 1e-2, step: 1e-7) - Minimum spacing if order is re-enforced.
- Outputs:
SIGMAS:SIGMAS- The sigma schedule with values clipped.
Sigma Schedule Reverser (🐺)
- Class:
WolfSigmaReverse - Display Name:
Sigma Schedule Reverser (🐺) - Category:
sampling/sigmas_wolf/transformations - Description: Reverses the order of active sigmas in a schedule. The final 0.0 sigma, if present, remains unchanged.
- Inputs:
sigmas:SIGMAS- The input sigma schedule.
- Outputs:
SIGMAS:SIGMAS- The reversed sigma schedule.
Wolf Sigma Reverse and Rescale
- Class:
WolfSigmaReverseAndRescale - Display Name:
Wolf Sigma Reverse and Rescale - Category:
sampling/sigmas_wolf/transformations - Description: Takes an existing SIGMAS tensor, reverses the order of its active steps, and then rescales them to a new target sigma_max and sigma_min_positive. The last sigma (0.0) remains in place.
- Inputs:
sigmas:SIGMAS- The input sigma schedule.new_sigma_max:FLOAT(default: 1.0, min: 0.01, max: 1000.0, step: 0.1) - The target maximum sigma for the reversed and rescaled schedule.new_sigma_min_positive:FLOAT(default: 0.002, min: 0.0001, max: 10.0, step: 0.0001) - The target minimum positive sigma.min_epsilon_spacing:FLOAT(default: 1e-5, min: 1e-7, max: 1e-2, step: 1e-7) - Minimum spacing for monotonicity enforcement.
- Outputs:
SIGMAS:SIGMAS- The reversed and rescaled sigma schedule.
Sigma Slice (🐺)
- Class:
WolfSigmaSlice - Display Name:
Sigma Slice (🐺) - Category:
sampling/sigmas_wolf/transformations - Description: Slices an existing sigma schedule, selecting a sub-sequence of active sigmas. The final 0.0 sigma, if present, is re-appended. Optionally re-ensures strictly decreasing order after slicing.
- Inputs:
sigmas:SIGMAS- The input sigma schedule.start_index:INT(default: 0, min: 0, max: 10000) - Start index for slicing active sigmas.end_index:INT(default: -1, min: -1, max: 10000) - End index for slicing active sigmas (-1 means to the end).step_size:INT(default: 1, min: 1, max: 1000) - Step size for slicing.ensure_strictly_decreasing:BOOLEAN(default: True) - Whether to enforce strictly decreasing order after slicing.min_epsilon_spacing:FLOAT(default: 1e-5, min: 1e-7, max: 1e-2, step: 1e-7) - Minimum spacing if order is re-enforced.
- Outputs:
SIGMAS:SIGMAS- The sliced sigma schedule.
Sigma Insert Value (🐺)
- Class:
WolfSigmaInsertValue - Display Name:
Sigma Insert Value (🐺) - Category:
sampling/sigmas_wolf/transformations - Description: Inserts a custom sigma value into an existing schedule at a specified index. Optionally re-sorts the schedule afterwards to maintain strictly decreasing order and ensures the final 0.0 sigma (if present) remains last.
- Inputs:
sigmas:SIGMAS- The input sigma schedule.sigma_value:FLOAT(default: 1.0, min: 0.0001, max: 1000.0, step: 0.01) - The sigma value to insert.index:INT(default: 0, min: 0, max: 1000) - Index in the active sigmas list where the value should be inserted.sort_after_insert:BOOLEAN(default: True) - Whether to sort the schedule (descending) after insertion.min_epsilon_spacing:FLOAT(default: 1e-5, min: 1e-7, max: 1e-2, step: 1e-7) - Minimum spacing if sorted.
- Outputs:
SIGMAS:SIGMAS- The sigma schedule with the value inserted.
Sigma Add Noise (🐺)
- Class:
WolfSigmaAddNoise - Display Name:
Sigma Add Noise (🐺) - Category:
sampling/sigmas_wolf/transformations - Description: Adds random noise to an existing sigma schedule. Ensures sigmas remain positive and optionally re-sorts them. The final 0.0 sigma (if present) remains unchanged by noise.
- Inputs:
sigmas:SIGMAS- The input sigma schedule.noise_strength:FLOAT(default: 0.1, min: 0.0, max: 10.0, step: 0.01) - Strength of the noise to add.noise_type:COMBO["gaussian", "uniform"](default: "gaussian") - Type of noise distribution.seed:INT(default: 0, min: 0, max: 0xFFFFFFFFFFFFFFFF) - Seed for the random noise generation.ensure_strictly_decreasing:BOOLEAN(default: True) - Whether to sort the schedule (descending) and enforce spacing after adding noise.min_epsilon_spacing:FLOAT(default: 1e-5, min: 1e-7, max: 1e-2, step: 1e-7) - Minimum spacing if sorted.
- Outputs:
SIGMAS:SIGMAS- The sigma schedule with noise added.
General Purpose Sigma Generators
These nodes provide flexible ways to generate sigma schedules based on mathematical functions.
Wolf Sigma Geometric Progression
- Class:
WolfSigmaGeometricProgression - Display Name:
Wolf Sigma Geometric Progression - Category:
sampling/sigmas_wolf/transformations(Note: Category in code istransformations, seems more like a generator. Using code value.) - Description: Generates N_steps + 1 sigmas forming a geometric progression. Each active sigma is the previous one multiplied by a
common_ratio. Sigmas are bounded bysigma_start(max) andsigma_min_positive. Last sigma is 0.0. - Inputs:
num_steps:INT(default: 12, min: 1, max: 1000) - Number of active sigmas to generate.sigma_start:FLOAT(default: 1.0, min: 0.01, max: 1000.0, step: 0.1) - Starting sigma value (sigma_max).sigma_min_positive:FLOAT(default: 0.002, min: 0.0001, max: 10.0, step: 0.0001) - Smallest positive sigma allowed.common_ratio:FLOAT(default: 0.75, min: 0.01, max: 2.0, step: 0.01) - Multiplier for each step. <1 for decreasing sigmas.min_epsilon_spacing:FLOAT(default: 1e-5, min: 1e-7, max: 1e-2, step: 1e-7) - Minimum spacing.
- Outputs:
SIGMAS:SIGMAS- Tensor with N+1 geometrically spaced sigmas.
Wolf Sigma Polynomial
- Class:
WolfSigmaPolynomial - Display Name:
Wolf Sigma Polynomial - Category:
sampling/sigmas_wolf/transformations(Note: Category in code istransformations, seems more like a generator. Using code value.) - Description: Generates N_steps + 1 sigmas based on a polynomial function of normalized time:
sigma = sigma_min_positive + (sigma_max - sigma_min_positive) * (1 - t_norm^power). Last sigma is 0.0. - Inputs:
num_steps:INT(default: 12, min: 1, max: 1000) - Number of active sigmas.sigma_max:FLOAT(default: 1.0, min: 0.01, max: 1000.0, step: 0.1) - Maximum sigma.sigma_min_positive:FLOAT(default: 0.002, min: 0.0001, max: 10.0, step: 0.0001) - Smallest positive sigma.power:FLOAT(default: 1.0, min: 0.1, max: 10.0, step: 0.05) - Power for the polynomial. 1.0=linear, >1.0 denser near sigma_max, <1.0 denser near sigma_min_positive.min_epsilon_spacing:FLOAT(default: 1e-5, min: 1e-7, max: 1e-2, step: 1e-7) - Minimum spacing.
- Outputs:
SIGMAS:SIGMAS- Tensor with N+1 polynomially spaced sigmas.
Sigma Tanh Generator (🐺)
- Class:
WolfSigmaTanhGenerator - Display Name:
Sigma Tanh Generator (🐺) - Category:
sampling/sigmas_wolf/generate - Description: Generates N_steps + 1 sigmas based on a scaled and shifted tanh function of normalized time. Sigmas range from
sigma_maxtosigma_min_positive. The tanh function provides an S-shaped curve. Last sigma is 0.0. - Inputs:
num_steps:INT(default: 12, min: 1, max: 1000) - Number of active sigmas.sigma_max:FLOAT(default: 1.0, min: 0.01, max: 1000.0, step: 0.1) - Maximum sigma.sigma_min_positive:FLOAT(default: 0.002, min: 0.0001, max: 10.0, step: 0.0001) - Smallest positive sigma.tanh_scale:FLOAT(default: 3.0, min: 0.1, max: 10.0, step: 0.1) - Scales the input to tanh, controlling steepness. Higher values = steeper.min_epsilon_spacing:FLOAT(default: 1e-5, min: 1e-7, max: 1e-2, step: 1e-7) - Minimum spacing.
- Outputs:
SIGMAS:SIGMAS- Tensor with N+1 tanh-spaced sigmas.
Model Inspection API and Usage (WolfSigmas)
This section documents the model inspection nodes provided in this package, how to use them, expected inputs/outputs, and troubleshooting steps for common failure modes (missing forward, dict outputs from hooks, black images). It also includes small mermaid workflow diagrams illustrating common setups.
Nodes covered
Wolf Model Structure Explorer(helper): enumerate module paths, types, parameters; use to copy exactlayer_namefor hooks.Wolf Model Activation Inspector(🐺): attach hooks, capture activations, convert to a ComfyUIIMAGE.Wolf Model Depatchify(🐺): dedicated node to convert patch/token activations into pixel-like images (tiles, upsampling, projection).Wolf Model Key Inspector: lists state_dict keys and parameter shapes for debugging parameter-based inspection.
Important quick notes
- Always pass the same MODEL output from ComfyUI to the Structure Explorer and Inspector nodes to ensure path resolution is consistent.
- Use the Structure Explorer first to obtain exact module names for
layer_name. The inspector acceptsendswithfallback but the exact path is more reliable. Activation Inspectorreturns two outputs:IMAGE: torch tensor [1, H, W, 3], dtype float32, values in range [0,1].STRING(JSON): diagnostic metadata including which executor was used, captured key, activation shape and basic statistics (min, max, mean, std), and method used for depatchifying/visualizing.
- If the JSON
activation_infocontains"error", use itsavailable_methods_sampleandavailable_attrs_samplefields (if present) to guide which executor to try next.
Execution/Executor strategies (inspector executor input)
auto(default): prefer wrapperapply_modelif present (this integrates with ComfyUI patcher), then falls back tomodel.model.apply_model,traversal.apply_model, then direct forward-like calls on the traversal module (forward,_forward,forward_orig, etc.).apply_model: force explicit use ofapply_modelon the wrapper/inner wrapper. Use when your MODEL exposesapply_model(ComfyUI models often do).direct_forward: attempt to call forward-like methods on the traversal module directly. Use only when you know the inner module exposes standard forward entrypoints.
What the inspector collects (activation_info keys)
executor: which executor path was used (e.g."apply_model","traversal.apply_model","forward", etc.)captured_key: the module name resolved in the traversal where activation was capturedorig_shape: original activation shape (tuple)activation_stats: object withmin,max,mean,std,nan_count,inf_count,dtype— helps diagnose black/constant imagesmethod: which conversion was used (e.g.,tokens_to_grid,spatial_direct_project,heatmap_fallback)token_grid/patch_grid/patch_size_used: details used for depatchification if applicableerror: present when something failed; may includeavailable_methods_sampleandavailable_attrs_samplefor the traversal module
Typical workflows
- Inspect a block activation and visualize as image (recommended)
- Connect MODEL ->
Wolf Model Structure Explorerto locate the exact module path (copy it) - Connect MODEL,
layer_name(copied path), andinput_latent(LATENT) ->Wolf Model Activation Inspector(executor:autoorapply_model) - Inspect
activation_infoJSON; if stats indicate near-zero range (min == max), choose per-channel visualization or try a different layer.
```mermaid` flowchart TD A[ComfyUI MODEL output] --> B[Wolf Model Structure Explorer] B --> C{Copy exact module path} A --> D[Wolf Model Activation Inspector] D -->|layer_name| C D --> E[Activation Image (IMAGE)] D --> F[Activation Info (STRING JSON)] click B "#" click D "#"
2) Capture tokens and depatchify to pixels
- If a captured activation is token-shaped `(B, L, C)`, the `depatchify` logic will:
- Attempt to reshape tokens into a grid `(B, gh, gw, C)` (prefer square or nearest factorization).
- Project channels to RGB using `model.latent_rgb_factors` if present, otherwise PCA-lite or channel selection.
- Upsample patches by detected `patch_size` (or `1` as fallback) to produce pixel-sized image.
- If reshape fails (e.g., token count not factorizable), the inspector will fall back to a heatmap matrix visualization and include `tokens_error` in `activation_info`.
```mermaid
flowchart LR
A[Captured Activation] --> B{Shape check}
B --> |B,L,C tokens| C[Token -> Grid reshape]
C --> D[Project channels -> RGB]
D --> E[Upsample patches by patch_size]
E --> F[IMAGE out]
B --> |B,C,H,W spatial| G[Spatial channel projection]
G --> F
B --> |Other| H[Heatmap fallback]
H --> F
Practical tips for diagnosing the two errors you reported
- Error: {"error": "Error inspecting activations: Module [Flux2] is missing the required "forward" function"}
- Diagnosis:
- The traversal module returned by
get_traversal_module(model)may be a Flux2 wrapper that doesn't implement a typical.forwardbut expectsapply_modelon the outer wrapper.
- The traversal module returned by
- Fix:
- Use
Wolf Model Structure Exploreron the same MODEL object to confirm the wrapper exposesapply_model. If it does, set inspectorexecutortoapply_model. - If
apply_modelis not present on the object you passed, pass the outer wrapper (the actual ComfyUI MODEL output) rather than the inner module. The inspector'sautomode should preferapply_modelwhen the wrapper is passed. - If you still see missing-forward diagnostics, paste the
activation_infoJSONavailable_methods_sampleandavailable_attrs_sampleand I will recommend a precise executor path or add a small special-case call.
- Use
- Diagnosis:
- Error: {"error": "Error depatchifying: 'dict' object has no attribute 'ndim'"} (or "'dict' object has no attribute 'ndim'"/black image)
- Root cause:
- Some modules return a dict-like output rather than a raw Tensor. Earlier hook implementations could store the raw dict into
collector.activations, and downstream depatchify/visualization code attempted to treat it as a Tensor.
- Some modules return a dict-like output rather than a raw Tensor. Earlier hook implementations could store the raw dict into
- Fix (already implemented in utilities):
- HookCollector now attempts to extract the best tensor candidate from dict/list/tuple outputs (
sample,samples,out,hidden_states,x, etc.) before storing activations. - If no tensor is found, the hook stores a lightweight diagnostic (a dict of shapes/types) and the inspector returns an informative error JSON rather than crashing.
- HookCollector now attempts to extract the best tensor candidate from dict/list/tuple outputs (
- How to use:
- Re-run the inspector (after selecting exact
layer_namefrom the Structure Explorer). Checkactivation_info— if you see a dict diagnostic, inspect its keys to know which element actually contains tensors and updatelayer_nameaccordingly (or provide aslice_exprto target a field if your node supports parameter attribute capture).
- Re-run the inspector (after selecting exact
- Root cause:
Examples (copy-and-run patterns)
-
Exact module activation visualization (recommended)
- Use
Wolf Model Structure Explorer-> copydiffusion_model.double_blocks.3.img_norm1 - Plugin into inspector:
layer_name:diffusion_model.double_blocks.3.img_norm1(or the exact path shown)executor:auto(if the MODEL wrapper exposesapply_model) elsedirect_forwardonly if you know the inner traversal exposesforward.input_latent: connect a latent (from VAE or initial seed)
- Inspect
activation_info. Ifactivation_info.activation_stats.max - activation_info.activation_stats.min < 1e-8then the visualization will be essentially constant/black — try another layer or enable per-channel visualization (future feature) or increase instrumentation.
- Use
-
Parameter/weight visualization
- Provide
layer_namepointing to a parameter path (e.g.,diffusion_model.xxx.proj.weight[0:64,0:64]). - The inspector will coerce the parameter to a tensor, optionally apply the
slice_expr, and visualize the slice as a matrix image with statistics inactivation_info.
- Provide
Advanced notes (for maintainers)
- Use
Wolf Model Structure Exploreroutput to build stable UI elements (dropdowns) if you want to makelayer_nameselection easier in the ComfyUI interface. - The utilities provide
safe_as_tensorwhich aggressively coerces numpy-object arrays, nested lists, and lazy parameter placeholders into Tensor objects — prefer using that when handling arbitrary framework outputs.
Appendix: Example activation_info (informative)
{
"executor": "apply_model",
"captured_key": "diffusion_model.double_blocks.3.img_norm1",
"orig_shape": [1, 512, 64, 64],
"activation_stats": {"min": -0.0023, "max": 0.003, "mean": -2.1e-05, "std": 0.0009, "nan_count": 0, "inf_count": 0, "dtype": "float32"},
"method": "spatial_direct_project",
"img_stats": {"min": 0.0, "max": 1.0, "mean": 0.45, "std": 0.12}
}
If you want me to proceed
- Option A (recommended): Run
Wolf Model Structure Exploreron the exact MODEL used in the failing flow and paste the top ~40 lines of its JSON output (module names and types) here. I'll:- Pick the exact
layer_nameto hook, - Recommend the precise
executoroption, - If necessary, add a tiny special-case call for Flux2 wrappers so hooks always fire.
- Pick the exact
- Option B: Re-run the Inspector with
executor="apply_model"and attach the returnedactivation_infoJSON — I'll interpret it and suggest next debugging steps.
Closing summary
- I added this Model Inspection API and usage guide to the README describing node inputs/outputs, executor strategies, diagnostics to expect in
activation_info, and mermaid workflow diagrams to clarify typical flows. - Next steps I can take for you: pick Option A or B above and I'll continue debugging the Flux2 forward/apply integration and the depatchify fallbacks.