Nodes/ComfyUI-ContextualRepulsion/Contextual Repulsion (Diversity)
ComfyUI Node

Contextual Repulsion (Diversity)

Same prompt, six identical pictures? This node pushes the batch apart.

By Hyun-Puer·Created 5 months ago·Updated 5 months ago· 0
Contextual Repulsion (Diversity)
  • model
  • MODEL
repulsion_scale0.10
timestep_cutoff0.35
gradient_steps3

Set batch_size to 4 in EmptyLatentImage, run the same prompt, and most models hand you four cousins instead of four takes: same pose, same composition, same everything except a slightly different face. That collapse is typicality bias, baked into how diffusion samples - every image drifts toward the most probable version of your prompt. ContextualRepulsion is a model patch that fights it at the source: it pushes the text-conditioning embeddings of each image in the batch apart during denoising, so one prompt actually produces different compositions and styles.

It lives under model_patches. MODEL in, MODEL out, wired between your model loader and the sampler. And it's one of the first pieces of community tooling aimed squarely at the Anima DiT line - the README says Anima DiT (the animayume series) is the only architecture fully validated so far, with SD3/SD3.5 and Flux marked "coming soon" and any other DiT using c_crossattn treated as experimental. If you're batch-generating on an SDXL checkpoint, this node isn't really aimed at you yet.

How it actually works

The node clones your model and installs a function wrapper around its forward pass - the standard set_model_unet_function_wrapper trick, so nothing about your checkpoint is permanently modified. Before each denoising step it intercepts the c_crossattn text embeddings for the whole batch and:

  • builds a cosine-similarity kernel across all the samples,
  • computes a Vendi Score diversity loss - the negative von Neumann entropy of that normalized kernel,
  • runs gradient_steps of gradient descent pushing the embeddings apart, normalized per-sample so the scale stays interpretable.

Two design choices matter. First, only the conditional (positive-prompt) embeddings get pushed; the unconditional half of the batch is left untouched so CFG keeps behaving. Second, repulsion only runs during the early part of denoising, up to timestep_cutoff - because that's where global composition gets decided. Once the sampler is polishing details, the node has already checked out, which is why it doesn't wreck quality at sensible settings.

The inputs that matter

  • repulsion_scale (default 0.1) - how hard the push is. Per the tooltip it's roughly the fraction of embedding magnitude shifted per gradient step, which is why 0.1 is a sane start. 0.05–0.2 for subtle variation, 0.3–1.0 for "maximum diversity."
  • timestep_cutoff (default 0.35) - fraction of the step range where repulsion is active.
  • gradient_steps (default 3) - gradient-descent iterations per step. 1–3 is usually plenty; more is stronger but slower.

Output is a single MODEL, straight into your KSampler. And EmptyLatentImage needs batch ≥ 2 - the code requires at least two conditional samples and silently passes through below that. That's the #1 "nothing happened" trap: check your batch size before you blame the node.

Installing and a reality check

No hidden dependencies - just PyTorch, which ComfyUI already ships. ComfyUI Manager, search ComfyUI-ContextualRepulsion, or:

cd ComfyUI/custom_nodes
git clone https://github.com/Hyun-Puer/ComfyUI-ContextualRepulsion

Restart and it appears under model_patches. The "zero overhead" claim at repulsion_scale=0 is genuinely true: the code returns the model untouched, no wrapper installed at all. But when it's on, it isn't free - real float32 autograd per early step, and the cost compounds with batch size.

Seeing artifacts? Drop repulsion_scale first, then timestep_cutoff. And set expectations: at the time of writing this is a brand-new node with zero community footprint - no reddit reports, no battle-tested settings beyond the README's quick guide. It's a serious idea lifted from an actual SIGGRAPH paper (arXiv:2603.28762), and on anything other than Anima you're effectively the beta tester. That's fine - that's how the good ComfyUI nodes start.

Categorymodel_patches

Inputs (4)

NameTypeDefaultDescription
modelMODEL
repulsion_scaleFLOAT0.100–5Repulsion strength. 0.1 = shift embeddings by ~10% of their magnitude per gradient step. Start with 0.05-0.2, increase for more diversity.
timestep_cutoffFLOAT0.350–1Fraction of early denoising steps to apply repulsion. 0.35 = first 35% of steps.
gradient_stepsINT31–10Number of iterative gradient steps per model call. More steps = stronger effect.

Outputs (1)

NameTypeDescription
MODELMODEL