OCS Expressions
August 9, 2025 · View on GitHub
See Filters for places where expressions apply.
Expressions
OCS implements a simple expression language.
Supported math operators: +, -, *, /, // (integer division), ** (power)
Supported logic operators: ||, &&, ==, !=, >, <, >=, <=
Operator precedence should generally work the way you'd expect.
You may surround a function name with backticks to turn it into a binary operator (only for functions that take two arguments).
Functions are called via name(param1, param2). Keyword arguments may be passed using the :> operator. Example:
name(param1, key :> 123, key2 :> otherfunction(10)).
Symbols (simple string type) are defined using 'symbol_name - note the solitary single quote. They may not contain spaces.
; can be used to sequence operations. I.E. exp1 ; exp2 evaluates exp1, then exp2 and then result of the expression is whatever exp2 returned.
:= is used to assign to a temporary variable (see set_var below).
The expression language supports a C/JavaScript style ternary operator: condition ? true_branch : false_branch is the equivalent of if(condition, true_branch, false_branch).
Like Python, a parenthesized expression with a trailing comma can be used to create an empty tuple. Example: (1,)
Filter Variables
Indexes like step are zero-based: 0 will be the first step.
Basic Variables
default: Context specific default value. i.e. if used in aninputexpression this would bex, if used foroutputthis would be the current result.step: Current step.substep: Current substep.dt:sigma_next - sigmasigma_idx: Index of the current sigma. Note that when using restarts this will be based on the restart sigma chunks, not full sigma list.sigma: The current sigma.sigma_next: The next sigma.sigma_down: The down sigma in ancestral sampling.sigma_up: The up sigma in ancestral sampling.sigma_prev: The previous sigma (may beNone).hist_len: Current available history length. "Now" counts as one.sigma_min: The minimum sigma (based on the full list).sigma_max: The maximum sigma (based on the full list).step_pct: Percentage for the current step (based on total steps).total_steps: Total steps to be sampled.
Extended Variables
denoised: From the current step or substep. May not be available in modelinputor grouppre_filter.cond: From the current step or substep. May not be available in modelinputor grouppre_filter.uncond: From the current step or substep. May not be available in modelinputor grouppre_filter.denoised_prev: Only available when model history exists.cond_prev: Only available when model history exists.cond_prev: Only available when model history exists.
Model Filter Variables
model_call: Only applicable tomodelfilters, will be the model call index. I.E. if the sampler calls the model three times, the filter would be called with model call indexes0,1and2.
Available in model filters, with the exception of the input filter.
denoised_currcond_curruncond_curr
Basic Expression Functions
| Name | Input | Output | ||||
|---|---|---|---|---|---|---|
| ⬤ | all | B* | B | |||
| Evaluates to true if all its arguments evaluate to true. Example: all(x > 1, y < 1) | ||||||
| ⬤ | any | B* | B | |||
| Evaluates to true if any of its arguments evaluate to true. Example: any(x > 1, y < 1) | ||||||
| ⬤ | between | value:N, from:N, to:N | B | |||
| Boolean range checking. Example: between(value, low, high) | ||||||
| ⬤ | comment | * | null | |||
Ignores any arguments passed to it (they won't be evaluated at all but must parse as a valid expression) and returns None | ||||||
| ⬤ | dict | ** | dict | |||
| Constructs a dictionary from its keyword arguments. Note: You may not pass positional arguments. Example: dict(key1 :> value1, keyN :> valueN) | ||||||
| ⬤ | get | name:SY, fallback:* | * | |||
| Returns a variable if set, otherwise the fallback. Example: get('somevar, 123) | ||||||
| ⬤ | if | condition:B, then:*, else:* | * | |||
| Conditional expressions. Example: if(condition, true_expression, false_expression) | ||||||
| ⬤ | index | index:IDX, value:S | T | * | |||
| Index function. | ||||||
| ⬤ | is_set | name:SY | B | |||
| Tests whether a variable is set. | ||||||
| ⬤ | max | values:SN | N | |||
| Maximum operation. Note: Takes one sequence argument. Example: min((1, 2, 3)) | ||||||
| ⬤ | min | values: SN | N | |||
| Minimum operation. Note: Takes one sequence argument. Example: max((1, 2, 3)) | ||||||
| ⬤ | mod | lhs:N, rhs:N | N | |||
| Modulus operation: Example: mod(5, 2) | ||||||
| ⬤ | neg | N | N | |||
| Negation. Example: neg(2) | ||||||
| ⬤ | not | B | B | |||
| Boolean negation | ||||||
| ⬤ | s_ | start:I(null), end:I(null), step:I(null) | slice | |||
Creates a slice object from the start, end, step values. See Numpy s_ | ||||||
| ⬤ | set_var | SY, * | * | |||
Sets a temporary variable to the specified value and returns the value. Alias for the := assignment operator. Example: test1 := 2; set_var('test2, 10); test1 * test2 | ||||||
| ⬤ | unsafe_call | callable, ** | * | |||
| Allows calling an arbitrary callable. Example: unsafe_call(some_callable, arg1, arg2, kwarg1 :> 123) | ||||||
Legend: B=boolean, N=numeric, NS=scalar numeric, I=integer, F=float, T=tensor, S=sequence, SN=numeric sequence, SY=symbol, *=any -- parenthized values indicate argument defaults. * following the type indicates variable length arguments. For functions that take keyword arguments, the type will be written like "name: TYPE(default_value)".
Tensor Expression Functions
Tensor dimensions hint: Most tensors you'll be dealing with are laid out as batch, channels, height, width. Negative indexes start from the end, so dimension -1 would mean width just the same as 3.
| Name | Input | Output | ||||
|---|---|---|---|---|---|---|
| ⬤ | t_bleh_enhance | tensor:T, mode:SY, scale:N(1.0) | T | |||
| Available if you have the ComfyUI-bleh node pack installed. See Filtering. Example: bleh_enhance(some_tensor, 'bandpass, 0.5) | ||||||
| ⬤ | t_blend | tensor1:T, tensor2:T, scale:N(0.5), mode:SY(lerp) | T | |||
| Tensor blend operation. Example: t_blend(t1, t2, 0.75, 'lerp) | ||||||
| ⬤ | t_contrast_adaptive_sharpening | tensor:T, scale:N(0.5) | T | |||
Contrast adaptive sharpening. Note: Not recommended to call on noisy tensors (so denoised but probably not x). Example: t_contrast_adaptive_sharpening(some_tensor, 0.1) | ||||||
| ⬤ | t_flip | tensor:T, dim:NS, mirror:B(false) | T | |||
| Flips a tensor on the specified dimension. If the third argument is true, it will be mirrored around the center in that dimension. Example: t_flip(some_tensor, -1, true) | ||||||
| ⬤ | t_mean | tensor:T, dim:SN(-3, -2, -1) | T | |||
| Tensor mean, second argument is dimensions. Example: t_mean(some_tensor, (-2, -1)) | ||||||
| ⬤ | t_noise | tensor:T, type:SY(gaussian) | T | |||
Generates un-normalized noise (use t_norm if you want to normalize it). If you have ComfyUI-sonar you can use any noise type that supports, otherwise only gaussian. The generated noise will have the same shape as the supplied tensor (hopefully, may not be true for every exotic noise type but at least should be broadcastable to the tensor). Example: t_noise(some_tensor, 'pyramid) | ||||||
| ⬤ | t_norm | tensor:T, factor:N(1.0), dim:SN(-3, -2, -1) | T | |||
| Tensor normalization (subtracts mean, divides by std). Example: t_norm(some_tensor, 1.0, (-2, -1)) | ||||||
| ⬤ | t_sonar_power_filter | tensor:T, filter:dict | T | |||
| Available if you have ComfyUI-sonar installed. See Filtering. Constructs a power filter from a dictionary argument. Note: May be slow as the filter is reconstructed on every evaluation. Example: t_sonar_power_filter(some_tensor, dict(alpha :> 0.1, min_freq :> 0.2, max_freq :> 0.6)) | ||||||
| ⬤ | t_roll | tensor:T, amount:NS(0.5), dim:SN((-2,)) | T | |||
| Rolls a tensor along the specified dimensions. If amount is >= -1.0 and < 1.0 this will be interpreted as a percentage. Example: t_roll(some_tensor, 10, (-2,)) | ||||||
| ⬤ | t_scale | tensor:T, scale:SN | NS, mode:SY(bicubic), absolute_scale:B(false) | T | |||
Scales a tensor. If scale is a tuple, it will be interpreted as (height, width). When absolute_scale is not set, the scales will be interpreted as percentages otherwise absolute values will be used. Example: t_scale(some_tensor, (0.75, 0.5), 'bilinear) | ||||||
| ⬤ | t_scale_nnlatentupscale | tensor:T, mode:SY(sd1), scale:SN(2.0) | T | |||
Available if you have ComfyUi_NNLatentUpscale installed. mode must be one of sd1 or sdxl. scale should be between 1.0 and 2.0 (may or may not work out of that range).Example: t_scale_nnlatentupscale(some_tensor, 'sdxl, 1.5) | ||||||
| ⬤ | t_shape | tensor:T | SN | |||
| Returns a tensor's shape as a tuple. Example: shp := t_shape(some_tensor); width := shp[-1]; height := shp[-2] | ||||||
| ⬤ | t_std | tensor:T, dim:SN(-3, -2, -1) | T | |||
| Tensor std, second argument is dimensions. Example: t_std(some_tensor, (-2, -1)) | ||||||
| ⬤ | t_taesd_decode | tensor:T, mode:SY(sd15) | T | |||
Decodes a latent tensor used TAESD. Mode must be one of sd15, sdxl. Only works if the appropriate models are in vae_approx Example: t_taesd_decode(some_tensor, 'sd15) | ||||||
| ⬤ | unsafe_tensor_method | T, SY, ** | * | |||
| Unsafe tensor method call. See note below. Example: unsafe_tensor_method(some_tensor, 'mul, 10) | ||||||
| ⬤ | unsafe_torch | path:SY | * | |||
| Unsafe Torch module attribute access. See note below. Example: unsafe_torch('nn.functional.interpolate) | ||||||
Note on unsafe_tensor_method and unsafe_torch: These functions are disabled by default. If the environment variable COMFYUI_OCS_ALLOW_UNSAFE_EXPRESSIONS is set to anything then you can use unsafe_tensor_method with a whitelisted set of methods (best effort to avoid anything actually unsafe). If the environment variable COMFYUI_OCS_ALLOW_ALL_UNSAFE is set to anything then unsafe_torch is enabled and unsafe_tensor_method will allow calling any method. WARNING: Allowing all unsafe with workflows you don't trust is not recommended and a malicious workflow will likely have access to anything ComfyUI can access. It is effectively the same as letting the workflow run an arbitrary script on your system.
Documentation TBD (check the source if you want to use them now): t_copysign, t_gaussianblur2d, t_rgb_latent, t_snf_guidance
Image Expression Functions
IMG used here to donate the type for functions that take an image. This may actually be an image batch rather than a single image.
| Name | Input | Output | ||||
|---|---|---|---|---|---|---|
| ⬤ | img_pil_resize | image:IMG, size:SN | NS, resample_mode:SY(bicubic), absolute_scale:B(false) | IMG | |||
Scales an image batch using Pillow's Image.resize function (follow link for information about resample modes, etc). If scale is a tuple, it will be interpreted as (height, width). When absolute_scale is not set, the scales will be interpreted as percentages otherwise absolute values will be used. Example: img_pil_resize(image_batch, (0.75, 0.5), 'lanczos) | ||||||
| ⬤ | img_shape | image:IMG | SN | |||
| Returns an image's shape as a tuple. Will fail if all the images in the batch aren't the same size. Example: shp := img_shape(image_batch); width := shp[-1]; height := shp[-2] | ||||||
| ⬤ | img_taesd_encode | image:IMG, reference_latent: T, mode:SY(sd15) | T | |||
Encodes an image batch into a latent tensor. The reference latent is only used to determine what device and type the output should be. Mode must be one of sd15, sdxl. Only works if the appropriate models are in vae_approx. Example: img_taesd_encode(image_batch, some_tensor, 'sd15) | ||||||