Nodes/Mecha Merge Node Pack/Perpendicular Component
ComfyUI Node

Perpendicular Component

Remove the part of B that points along A, and merge what's actually new

By ljleb·Created 2 years ago·Updated 30 days ago· 101
Perpendicular Component
  • a (delta|param|weight)
  • b (delta|param|weight)
  • recipe
merge_checkpointingfalse

Perpendicular Component (class Perpendicular Component Mecha Recipe) is the geometry node of the merge toolkit. Give it two vectors - it treats each tensor of model b as a vector - and it returns the component of b that's orthogonal to a: everything in b minus its projection onto a. It's the "give me what B contributes that A doesn't already cover" operation.

Why would you want that? Model merges are full of overlapping directions. If you're combining two deltas that both push in similar ways, a plain add double-counts the shared part. Taking the perpendicular component of one relative to the other strips away the overlap, so what you add to a is only the genuinely new information from b. It's a de-redundancy filter, and it's the heart of the pack's Add Perpendicular method (which subtracts a common base from two models, takes the perpendicular component, and adds it back).

How it works

Per tensor, the math is the standard vector projection removal:

res = b − a · (a / ‖a‖) · (b / ‖a‖)

i.e. subtract from b its projection onto the direction of a. If the result comes out NaN - which happens when a is (near) zero and the projection is undefined - the node returns a zero tensor for that key instead of crashing the merge.

The inputs that matter:

  • a, b (both MECHA_RECIPE, required) - a defines the direction to remove; b is what gets orthogonalized. The output is a modified b.
  • recipe (output, weight space) - the orthogonal component of b. Wire it into an Add Difference/Add Perpendicular step or combine it into a larger recipe.

A couple of framing notes so the math lands. This works on weight-space tensors and is generally used in delta-composition flows: you subtract a base from two fine-tunes, orthogonalize one delta against the other, then combine. It's also the operation that makes some "debias" merges work - removing what's shared with a reference direction leaves only what's unique to the model you care about.

Install

It's part of the Mecha Merge Node Pack (ljleb/comfy-mecha):

  • ComfyUI Manager → Install Custom Nodes → search "mecha" → Mecha Merge Node Pack, or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/ljleb/comfy-mecha.git
pip install -r comfy-mecha/requirements.txt

Restart, find it under mecha. The pack's only dependency is sd-mecha==1.1.7; no model downloads.

Common issues

  • Zero tensors in a produce zeroed output. That's the designed NaN fallback, and it means "nothing to remove here." Usually harmless, occasionally worth knowing about when the whole output looks suspiciously empty.
  • Input order flips the meaning. Orthogonalizing b against a is not the same as orthogonalizing a against b. If your merge suddenly has less of the model you wanted, check which direction you wired.
  • It's weight-space math. If you feed it deltas expecting a delta out, you'll get whatever the tensor math produces - keep this node in the weight-space part of your graph unless you know exactly what you're doing.

Perpendicular Component is not a daily driver. It's the tool you reach for when two models are too similar and a plain add just smears them together - the one that turns "these two deltas overlap" from a problem into something you can actually subtract away.

Categorymecha

Inputs (3)

NameTypeDefaultDescription
a (delta|param|weight)MECHA_RECIPE
b (delta|param|weight)MECHA_RECIPE
merge_checkpointingoptBOOLEANfalseSpeeds up an entire branch of a merge graph that does not change often in exchange of memory. - true: store the first output of this recipe node on cpu memory in fp16. On subsequent workflow executions, as long as the inputs do not change, the cached keys are returned after being cast to the original device and dtype. - false: do not store the output. The recipe and its inputs will re-execute on subsequent workflow executions. Note that the memory used to checkpoint the output is distinct from the cache feature. In general, you probably want to either use this *or* a cache unit, but not both at the same time because the memory adds up. The difference between merge checkpointing and cache is that merge checkpointing completely re-merges from scratch if any input changes. Merge checkpointing is also generally much faster than cache in the fast path.

Outputs (1)

NameTypeDescription
recipeMECHA_RECIPE