Table of Contents
- ScriptableConditioning Node
- Overview
- What is Conditioning?
- Inputs
- Outputs
- Default Script
- How the Default Script Works
- Available Variables
- Understanding Conditioning Structure
- Example: Pass-Through with Logging
- Example: Combine Multiple Conditionings
- Example: Filter Conditioning Entries
- Example: Modify Conditioning Strength
- Example: Add Random Perturbation
- Example: Conditional Logic Based on Content
- Example: Empty Conditioning
- Example: Create Dummy Conditioning
- Common Patterns
- Pattern 1: Debugging Conditioning Flow
- Pattern 2: Safe Modification
- Pattern 3: Conditional Pass-Through
- Limitations
- Error Handling
- Security Considerations
- Related Nodes
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 existselse []: 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 parametertorch: The PyTorch librarynp: The NumPy library
If enable_io_helpers is True, you also get:
get_output_dir(): Returns ComfyUI's output directory pathget_input_dir(): Returns ComfyUI's input directory pathget_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.
Related Nodes
- 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