Saya Comfy Couple
Two characters, one image — Saya Comfy Couple stops their prompts from melting together
- model_main
- main_positive
- person_1_positive
- person_2_positive
- negative
- latent
- dual_sampling_model
- support_model_1
- support_model_2
- support_model_3
- patched_model_main
- patched_dual_sampling_model
- patched_support_model_1
- patched_support_model_2
- patched_support_model_3
- positive_final
- detailer_positive
- negative
- mask_person_1
- mask_person_2
- couple_config
If you've ever prompted two girls, blue hair, pink hair and watched the model hand both hairstyles to the same character, you know the exact problem this node exists for. A diffusion model reads all of those tags as one soup - it has no idea that blue hair belongs to the left person and pink hair to the right. Saya Comfy Couple is the fix: it spatially separates your conditioning into two character regions so each half of the image only "sees" its own identity prompt.
It's a modified, expanded take on the old Comfy Couple idea, and it's aimed squarely at SDXL-family anime and illustration workflows with one or two characters. The genuinely useful twist is the prompt architecture. Instead of the usual positive_1 / positive_2 / negative, you write four things:
main_positive- the scene: what's happening, where, framing, lighting, shared action.person_1_positive- who character 1 is: hair, eyes, outfit, body.person_2_positive- who character 2 is.negative- your normal shared negative.
The node then builds region_1 = MAIN + PERSON 1 and region_2 = MAIN + PERSON 2 internally, and attaches a mask to each. Both characters get the full scene; each only gets its own identity. Keep identity traits out of MAIN unless both characters genuinely share them - that's the whole point of the separation, and it's the most common way people dilute it.
What it does under the hood
The required inputs are model_main, the four conditionings, a latent, and a handful of knobs. It derives two complementary masks from the latent's dimensions, so they always match the resolution you're actually sampling (the README talks about width/height inputs; the shipped code reads them straight off the latent - trust the node, not the doc). What you'll actually set:
orientation-horizontal(side by side, the usual) orvertical.center- where the split sits.0.5is an even split;0.4makes person 1's region smaller. Range is clamped to 0.15–0.85.transition- how soft the mask edge is.0.03default is a fairly hard split; bump it if you get a visible seam.swap_person_positions- flips which side person 1 owns. If your characters come out reversed, this (or yourcenter) is the first thing to check.use_couple_attention- the master switch. Turn it off and you get a plain concatenated prompt, which is handy as an A/B baseline.
The optional binding_mode (LEGACY default, plus experimental V0/V1/V1.1/V2 modes with attn1_strength, attn1_max_tokens, and friends) drives how strongly the regional-attention patch binds each character's tokens. Leave it on LEGACY until you understand what you're changing - this is the bleeding edge of the pack and it's still labeled experimental.
The outputs that matter
Wire it like this:
Checkpoint Loader → Saya Comfy Couple → KSampler
├── patched_model_main → model
├── positive_final → positive
└── negative → negative
positive_final is the regional couple conditioning; patched_model_main is your model with the regional-attention patch baked in. mask_person_1 / mask_person_2 are the two masks - feed them to each character's IPAdapter attn_mask so your two reference images stay on their own side of the image. detailer_positive is a character-local conditioning with the scene stripped out, made for detailer crops that shouldn't waste tokens on background prose. couple_config is the important bit for bigger builds: it's a serialized copy of every setting this node used, which the Copy and bundle nodes in this pack consume so later passes rebuild the exact same couple.
Solo generation works too - leave person_2_positive as an empty conditioning and the node auto-detects it and runs a single-region pass.
Install and honest caveats
Install is painless: ComfyUI Manager → search saya-comfy-couple-plus, or
cd ~/ComfyUI/custom_nodes
git clone https://github.com/alphaziod/saya-comfy-couple-plus.git
then restart. Dependencies are just numpy and Pillow - torch comes from ComfyUI, and there are no model files to download.
Be aware: this pack is openly work-in-progress, and the README says so. Internal ports and behavior can change between updates - keep a backup of important workflows, and if a saved workflow shows stale ports after an update, restart ComfyUI fully (delete and re-add the node if needed). And set expectations: regional prompting works best when your characters are spatially separated in the frame. Overlapping, touching characters still blend - no mask fixes that. It gives the model clean information, not magic.
Inputs (24)
| Name | Type | Default | Description |
|---|---|---|---|
| model_main | MODEL | — | |
| main_positive | CONDITIONING | — | |
| person_1_positive | CONDITIONING | — | |
| person_2_positive | CONDITIONING | — | |
| negative | CONDITIONING | — | |
| latent | LATENT | — | |
| use_couple_attention | BOOLEAN | true | — |
| orientation | COMBO | horizontal | 2 options: horizontal, vertical |
| center | FLOAT | 0.500.15–0.85 | — |
| transition | FLOAT | 0.030.01–0.2 | — |
| mask_floor | FLOAT | 0.000–0.2 | — |
| swap_person_positions | BOOLEAN | false | — |
| binding_modeopt | COMBO | LEGACY | 5 options: LEGACY, V0_PRE_SOFTMAX, V1_ATTN1, V1_1_HIRES, V2_QUERY_OWNERSHIP |
| attn1_strengthopt | FLOAT | 0.600–1.5 | — |
| attn1_max_tokensopt | INT | 1024256–16384 | — |
| attn1_ambiguous_bandopt | FLOAT | 0.150.02–0.45 | — |
| attn1_apply_lowres_onlyopt | BOOLEAN | true | — |
| attn1_hires_strengthopt | FLOAT | 0.300–0.8 | — |
| v2_ownership_strengthopt | FLOAT | 0.800–1 | — |
| v2_confidence_flooropt | FLOAT | 0.100–0.45 | — |
| dual_sampling_modelopt | MODEL | — | |
| support_model_1opt | MODEL | — | |
| support_model_2opt | MODEL | — | |
| support_model_3opt | MODEL | — |
Outputs (11)
| Name | Type | Description |
|---|---|---|
| patched_model_main | MODEL | — |
| patched_dual_sampling_model | MODEL | — |
| patched_support_model_1 | MODEL | — |
| patched_support_model_2 | MODEL | — |
| patched_support_model_3 | MODEL | — |
| positive_final | CONDITIONING | — |
| detailer_positive | CONDITIONING | — |
| negative | CONDITIONING | — |
| mask_person_1 | MASK | — |
| mask_person_2 | MASK | — |
| couple_config | SAYA_COUPLE_CONFIG | — |