1 nodes-scriptable-conditioning
Balazs Horvath edited this page 2026-04-18 10:52:19 +02:00

ScriptableConditioning Node

Overview

The ScriptableConditioning node allows you to write Python scripts that modify or generate conditioning for diffusion models. Conditioning is the text prompt representation that guides the diffusion model to generate specific images.

What is Conditioning?

In diffusion models, conditioning is the encoded representation of the text prompt. When you type a prompt like "a beautiful sunset over mountains", the text encoder converts this into a numerical representation (conditioning) that the diffusion model uses to guide the image generation process.

Conditioning in ComfyUI is typically a list of dictionaries, where each dictionary contains:

  • The encoded text embeddings
  • Optional attention masks
  • Other metadata

Inputs

Parameter Type Default Range Description
conditioning_in CONDITIONING - - Optional input conditioning to modify
seed INT 0 0-4294967295 Random seed for reproducibility
enable_io_helpers BOOLEAN False - Enable file I/O helper functions
script STRING (see below) - Python script to execute

Outputs

  • conditioning: A list of conditioning dictionaries

Default Script

# Scriptable Conditioning: set 'output_conditioning' (list of conditioning dicts).
# Injected: conditioning_in, seed, torch, np.
# Example - pass through:
#   output_conditioning = conditioning_in if conditioning_in else []

output_conditioning = conditioning_in if conditioning_in else []

How the Default Script Works

output_conditioning = conditioning_in if conditioning_in else []
  • conditioning_in: The input conditioning (if connected)
  • if conditioning_in: Checks if input exists
  • else []: Returns empty list if no input
  • This is a pass-through: it returns the input unchanged

This default behavior allows the node to be used as a no-op or placeholder when you want to add conditioning manipulation later.

Available Variables

Your script has access to:

  • conditioning_in: The input conditioning (list of dicts, or None)
  • seed (int): The seed parameter
  • torch: The PyTorch library
  • np: The NumPy library

If enable_io_helpers is True, you also get:

  • get_output_dir(): Returns ComfyUI's output directory path
  • get_input_dir(): Returns ComfyUI's input directory path
  • get_temp_dir(): Returns ComfyUI's temporary directory path

Understanding Conditioning Structure

Conditioning in ComfyUI is a list of dictionaries. A typical structure:

[
    {
        'cond': tensor,  # The actual conditioning embeddings [batch, seq_len, dim]
        'cross_attn': tensor,  # Cross-attention conditioning
        # ... other optional fields
    }
]

The exact structure depends on the model and text encoder being used.

Example: Pass-Through with Logging

# Log information about the conditioning
if conditioning_in:
    print(f"Received {len(conditioning_in)} conditioning entries")
    for i, cond in enumerate(conditioning_in):
        print(f"Entry {i}: {list(cond.keys())}")
else:
    print("No input conditioning received")

# Pass through unchanged
output_conditioning = conditioning_in if conditioning_in else []

Explanation:

  • Checks if conditioning exists
  • Logs the number of entries and their keys
  • Passes through unchanged
  • Useful for debugging conditioning flow

Example: Combine Multiple Conditionings

# This example assumes you have multiple conditioning inputs
# In practice, you'd need to connect multiple inputs or use a different node structure

# For now, this is a placeholder showing the concept
if conditioning_in:
    # Duplicate the conditioning (simple example)
    output_conditioning = conditioning_in + conditioning_in
else:
    output_conditioning = []

Explanation:

  • Duplicates the conditioning list
  • This would effectively apply the same prompt twice
  • In practice, you'd want more sophisticated combination logic

Example: Filter Conditioning Entries

# Filter conditioning based on some criteria
if conditioning_in:
    # Keep only the first entry
    output_conditioning = [conditioning_in[0]]
else:
    output_conditioning = []

Explanation:

  • Keeps only the first conditioning entry
  • Useful when you have multiple prompts but only want to use one
  • Could be extended with more sophisticated filtering logic

Example: Modify Conditioning Strength

# This is a conceptual example
# Actual implementation depends on the conditioning structure

if conditioning_in:
    modified_conditioning = []
    for cond in conditioning_in:
        # Create a modified copy
        new_cond = cond.copy()
        
        # Scale the conditioning (if it has a 'cond' field)
        if 'cond' in new_cond:
            new_cond['cond'] = new_cond['cond'] * 0.8  # Reduce strength by 20%
        
        modified_conditioning.append(new_cond)
    
    output_conditioning = modified_conditioning
else:
    output_conditioning = []

Explanation:

  • Iterates through each conditioning entry
  • Creates a copy to avoid modifying the original
  • Scales the conditioning embeddings by 0.8
  • This would reduce the prompt's influence on generation
  • Actual implementation depends on the specific structure

Example: Add Random Perturbation

import torch

# Add small random noise to conditioning for variation
if conditioning_in:
    torch.manual_seed(seed)
    modified_conditioning = []
    
    for cond in conditioning_in:
        new_cond = cond.copy()
        
        # Add small noise if 'cond' field exists
        if 'cond' in new_cond:
            noise = torch.randn_like(new_cond['cond']) * 0.01  # Small noise
            new_cond['cond'] = new_cond['cond'] + noise
        
        modified_conditioning.append(new_cond)
    
    output_conditioning = modified_conditioning
else:
    output_conditioning = []

Explanation:

  • Adds small random noise to conditioning embeddings
  • Uses seed for reproducibility
  • Noise magnitude is 0.01 (small to avoid breaking the conditioning)
  • Creates variation while preserving the original prompt meaning

Example: Conditional Logic Based on Content

# Modify conditioning based on its content
if conditioning_in:
    modified_conditioning = []
    
    for cond in conditioning_in:
        new_cond = cond.copy()
        
        # Example: Check if conditioning has certain characteristics
        if 'cond' in new_cond:
            # Check the shape or values
            cond_tensor = new_cond['cond']
            
            # Modify based on some condition
            if cond_tensor.shape[-1] > 768:  # Large embedding dimension
                # Do something for large embeddings
                pass
            else:
                # Do something for small embeddings
                pass
        
        modified_conditioning.append(new_cond)
    
    output_conditioning = modified_conditioning
else:
    output_conditioning = []

Explanation:

  • Shows how to apply conditional logic
  • Checks properties of the conditioning
  • Applies different modifications based on those properties
  • Actual logic depends on your specific use case

Example: Empty Conditioning

# Return empty conditioning (no prompt influence)
output_conditioning = []

Explanation:

  • Returns an empty list
  • This effectively removes any prompt guidance
  • The model will generate based purely on noise and any other inputs
  • Useful for unconditional generation or testing

Example: Create Dummy Conditioning

import torch

# Create a dummy conditioning for testing
# This is NOT recommended for production use

# Create a simple tensor
dummy_cond = torch.zeros(1, 77, 768)  # Typical CLIP embedding shape

output_conditioning = [{'cond': dummy_cond}]

Explanation:

  • Creates a dummy conditioning tensor
  • Shape: [1, 77, 768] is typical for CLIP text encoder
  • All zeros means no actual prompt information
  • This is only for testing - real prompts should come from a text encoder

Common Patterns

Pattern 1: Debugging Conditioning Flow

# Log everything to understand the structure
if conditioning_in:
    print(f"Conditioning type: {type(conditioning_in)}")
    print(f"Conditioning length: {len(conditioning_in)}")
    
    for i, cond in enumerate(conditioning_in):
        print(f"\nEntry {i}:")
        print(f"  Type: {type(cond)}")
        print(f"  Keys: {list(cond.keys())}")
        
        for key, value in cond.items():
            if isinstance(value, torch.Tensor):
                print(f"  {key}: tensor shape {value.shape}")
            else:
                print(f"  {key}: {type(value)}")

output_conditioning = conditioning_in if conditioning_in else []

Pattern 2: Safe Modification

# Always check if fields exist before modifying
if conditioning_in:
    modified_conditioning = []
    
    for cond in conditioning_in:
        new_cond = cond.copy()  # Always copy to avoid side effects
        
        # Safely modify
        if 'cond' in new_cond and isinstance(new_cond['cond'], torch.Tensor):
            # Safe to modify
            new_cond['cond'] = new_cond['cond'] * 0.9
        
        modified_conditioning.append(new_cond)
    
    output_conditioning = modified_conditioning
else:
    output_conditioning = []

Pattern 3: Conditional Pass-Through

# Only modify under certain conditions
should_modify = True  # Set based on your logic

if conditioning_in and should_modify:
    # Apply modification
    modified_conditioning = [cond.copy() for cond in conditioning_in]
    # ... modification logic ...
    output_conditioning = modified_conditioning
else:
    # Pass through unchanged
    output_conditioning = conditioning_in if conditioning_in else []

Limitations

The ScriptableConditioning node has some limitations:

  • It doesn't have built-in text encoding capabilities
  • You need to understand the specific conditioning structure for your model
  • Modifications can break the conditioning if done incorrectly
  • It's primarily useful for:
    • Debugging conditioning flow
    • Simple modifications like scaling
    • Filtering or selecting between conditionings
    • Adding small perturbations

For more complex text manipulation, use ComfyUI's text encoding nodes (CLIP Text Encode, etc.).

Error Handling

The node includes error handling:

  • Script execution errors return the input conditioning unchanged
  • Invalid output types fall back to input conditioning
  • Errors are logged for debugging

Security Considerations

This node uses exec() to run your script. This is intentionally powerful for local development but should not be used in production or exposed to untrusted users.

  • CLIP Text Encode: For encoding text prompts into conditioning
  • Conditioning Combine / Conditioning Set Area: For combining conditionings
  • Conditioning (Set Area): For applying conditioning to specific regions