CLIP Scale Dual SDXL Block
Scale each of SDXL's 44 text-encoder layers
- clip
- CLIP
SDXL runs on two text encoders - CLIP-L with 12 transformer layers, CLIP-G with 32 - and until this node, your options for messing with them were the blunt club that is CLIP skip. CLIP Scale Dual SDXL Block gives you a slider for every single layer of both encoders, plus the embeddings, the final layer norms, and CLIP-G's text projection. It's the difference between "chop off the last two layers" and "dial layer 27 down to 0.4 and see what happens."
That sounds niche until you've actually wanted it. Weakening or zeroing a specific block is how you debug which layer a LoRA or a merge is fighting you in, or how you subtly change how literally the model follows your prompt. And when you're merging two checkpoints that share an SDXL CLIP, being able to take the text encoder from each parent block-by-block is a whole different level of control than a single global ratio.
How it works
The node clones your CLIP, then reads its full state dict. The widget names in the UI use short prefixes like clip_l.encoder.layers.5, but the real keys are longer (clip_l.transformer.text_model.encoder.layers.5...), so it normalizes them internally before matching each weight against your widget values using a longest-prefix match. Weights that match a non-1.0 slider get grouped by scale and applied through add_patches - mathematically, weight × scale, done in place on a clone so your original CLIP is untouched. Two key types are explicitly skipped: .position_ids and .logit_scale. Zeroing position ids would wreck token placement, and scaling logit_scale changes raw magnitude in ways you almost never want, so the node won't let you.
The scale range runs 0.0 to 2.0 in 0.01 steps. 1.0 is "leave alone", 0.0 zeroes the layer out, and values above 1 amplify. Everything defaults to 1.0, so out of the box it's a pass-through.
The inputs that matter
There are 49 float widgets on this thing, and that's the point - but you'll rarely touch more than a handful:
- clip - the CLIP to scale (wire from a checkpoint loader or dual CLIP loader).
- clip_l.embeddings and clip_g.embeddings - the input token embeddings. Scaling these is the most drastic single change you can make; it reshapes how every token is interpreted, so go gently.
- The clip_l.encoder.layers.N and clip_g.encoder.layers.N rows - the per-layer sliders you'll actually experiment with.
- clip_g.text_projection - scales how CLIP-G's pooled output projects into the conditioning space. The one non-layer knob worth knowing.
Output is a single CLIP, which wires straight into your CLIP Text Encode nodes. Everything else in the graph downstream sees a normal CLIP - it just behaves differently.
Install and first run
From the ComfyUI Manager, search Easygoing and install the pack, or:
cd ComfyUI/custom_nodes
git clone https://github.com/easygoing0114/ComfyUI-easygoing-nodes.git
Restart ComfyUI. The pack ships no extra pip requirements, but it does need a ComfyUI build with the V3 node API - on an older build none of these nodes will register, so update ComfyUI if the menu doesn't show it.
Where people get burned
The widget names contain dots, and the frontend sometimes renders them with underscores - clip_l.encoder.layers.5 can look like clip_l_encoder_layers_5. Same thing, just cosmetic. The real trap is expecting a scaled CLIP to persist: these edits live in the graph only, so save the workflow (or, for Qwen, use the pack's CLIP Save Qwen node). For SDXL there's no save node in this pack, so if you want the scaled encoder in another project, keep the scale node in a reusable workflow. And test one layer at a time - change a single slider, generate, compare. Fifty sliders at once gives you fifty unknowns.
Inputs (50)
| Name | Type | Default | Description |
|---|---|---|---|
| clip | CLIP | — | |
| clip_l.embeddings | FLOAT | 1.000–2 | — |
| clip_l.encoder.layers.0 | FLOAT | 1.000–2 | — |
| clip_l.encoder.layers.1 | FLOAT | 1.000–2 | — |
| clip_l.encoder.layers.2 | FLOAT | 1.000–2 | — |
| clip_l.encoder.layers.3 | FLOAT | 1.000–2 | — |
| clip_l.encoder.layers.4 | FLOAT | 1.000–2 | — |
| clip_l.encoder.layers.5 | FLOAT | 1.000–2 | — |
| clip_l.encoder.layers.6 | FLOAT | 1.000–2 | — |
| clip_l.encoder.layers.7 | FLOAT | 1.000–2 | — |
| clip_l.encoder.layers.8 | FLOAT | 1.000–2 | — |
| clip_l.encoder.layers.9 | FLOAT | 1.000–2 | — |
| clip_l.encoder.layers.10 | FLOAT | 1.000–2 | — |
| clip_l.encoder.layers.11 | FLOAT | 1.000–2 | — |
| clip_l.final_layer_norm | FLOAT | 1.000–2 | — |
| clip_g.embeddings | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.0 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.1 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.2 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.3 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.4 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.5 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.6 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.7 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.8 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.9 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.10 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.11 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.12 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.13 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.14 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.15 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.16 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.17 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.18 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.19 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.20 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.21 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.22 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.23 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.24 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.25 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.26 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.27 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.28 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.29 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.30 | FLOAT | 1.000–2 | — |
| clip_g.encoder.layers.31 | FLOAT | 1.000–2 | — |
| clip_g.final_layer_norm | FLOAT | 1.000–2 | — |
| clip_g.text_projection | FLOAT | 1.000–2 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| CLIP | CLIP | — |