Nodes/ComfyUI_Personalize_Anything/Personalize Anything Compose (fg+bg)
ComfyUI Node

Personalize Anything Compose (fg+bg)

Two reference images, one Flux frame

By smthemex·Created 2 years ago·Updated 5 days ago· 45
Personalize Anything Compose (fg+bg)
  • model
  • conditioning
  • fg_conditioning
  • bg_conditioning
  • fg_inverted_latent
  • fg_source_latent
  • bg_inverted_latent
  • bg_source_latent
  • fg_mask
  • latent
◄seed0►
◄steps28►
◄tau50►
◄eta1.00►
◄concept_processfalse►

The single-subject Personalize Anything workflow answers "put this thing in a new picture". Compose answers the harder question: "put this thing into that specific picture". Two references, so two source branches instead of one - a foreground and a background - and a batch of three rows going through Flux at every step while the subject tokens get copied in from one and the scene tokens from the other.

It's the most interesting node in the pack and also the one you'll swear at.

What it does differently

This is upstream's MultiPersonalizeAnythingAttnProcessor, ported to comfy's native Flux attention. Where the Sample node runs [source, target], this one runs [foreground, background, target]. Above tau, the foreground branch's subject tokens are copied into the target at the fg_mask positions, and the background branch's tokens land everywhere the mask isn't. No mask for the background - the complement is the mask, which is elegant and also means you can't cheat.

Still the same training-free idea: no dataset, no LoRA, no adapter weights, just tokens from inverted references replacing tokens in a fresh noise latent. The full mechanism - RF-Inversion's forward ODE, the controlled reverse ODE, why the replacement happens on q/k/v after comfy's fused projection - is on the Invert and Sample pages. Here it's doubled.

The graph, and the inputs that matter

You need two Invert nodes: one per source image, each fed its own VAEEncode. That's where four of the inputs come from - fg_inverted_latent and fg_source_latent from the foreground Invert, bg_inverted_latent and bg_source_latent from the background one. Do not mix them up; the naming is your only defence.

Then the three prompts, in batch order:

  • fg_conditioning - row 0. The foreground branch's prompt, and it must match what the foreground Invert node was given.
  • bg_conditioning - row 1. Same rule for the background.
  • conditioning - row 2, the last row. This is the prompt for the picture you actually want.

fg_mask is the only mask, and it marks the subject region of the foreground image. Everything outside it gets background tokens. Guidance still comes in through that target conditioning, so put a FluxGuidance node (3.5, flux-dev) in front of conditioning exactly as you would for a normal Flux graph.

Then seed, steps, tau, eta - same meanings as the Sample node, and the same rule applies: steps must match both Invert nodes' steps. tau at 50 and eta at 1.0 are the upstream defaults. Note there's no shift here and no mode, so you can't nudge the subject sideways and you can't switch it into inpainting duty; layout comes entirely from your mask and your background image.

Output is one latent. VAEDecode it. That's it.

Install

Same pack as the rest of it - ComfyUI Manager, search ComfyUI_Personalize_Anything, or:

cd ComfyUI/custom_nodes
git clone https://github.com/smthemex/ComfyUI_Personalize_Anything

Models are the standard Flux dev set the README lists: flux1-dev-fp8-e4m3fn.safetensors (~11 GB) into models/diffusion_models, clip_l.safetensors and t5xxl_fp8_e4m3fn.safetensors into models/clip, ae.safetensors into models/vae. The pack itself only needs torch - ignore any tutorial that starts with pip install diffusers.

The traps

Everything has to be the same size. The two inverted latents and the target noise get concatenated into one batch, so both source images must encode to the same latent dimensions as your output. Encode foreground, background and target at one resolution; Comfy's silent shape mismatch here is not a helpful error message.

Your background image is not a mood board. Its tokens are copied into the target at fixed spatial positions, so it works best when it already roughly resembles the composition you want - same subject placement, same horizon. Treat it as the plate you're dropping the subject into, not a style reference.

Masks are coarse by construction. The mask is nearest-resized to Flux's 16-pixel token grid and thresholded, so feathering is gone before the model sees it. A mask that's too tight shaves the subject; too loose and you drag background pixels in with it. Iterate on the mask, not on the prompts.

Expect it to be the slowest thing in the pack. Three rows through a 12B transformer per step, plus the node unloads and reloads CLIP/VAE around the run. On 12 GB this is the node most likely to make you drop to a smaller resolution - which is fine, and the right lever.

Console first, always. The run prints subject tokens=N | patch fired Mx. If the subject token count is zero, your mask landed nowhere useful and no amount of prompt editing will save the image.

And the one everyone hits once: if the nodes don't show up in the menu at all, you probably have an old clone whose diffusers wrapper broke on transformers>=5. git pull, restart Comfy, reinstall the workflow's JSON from the pack's example_workflows folder if in doubt.

CategoryPersonalizeAnything

Inputs (14)

NameTypeDefaultDescription
modelMODEL—
conditioningCONDITIONINGPrompt of the composed image (target branch, last row).
fg_conditioningCONDITIONINGPrompt of the foreground branch (row 0). Must match the foreground Invert node's conditioning.
bg_conditioningCONDITIONINGPrompt of the background branch (row 1). Must match the background Invert node's conditioning.
fg_inverted_latentLATENTInvert node #1 (foreground image).
fg_source_latentLATENTInvert node #1 (foreground image).
bg_inverted_latentLATENTInvert node #2 (background image).
bg_source_latentLATENTInvert node #2 (background image).
fg_maskMASKSubject region of the FOREGROUND image; the background branch fills the complement.
seedINT00–18446744073709550000—
stepsINT281–100—
tauFLOAT500–100—
etaFLOAT1.000–1—
concept_processoptBOOLEANfalse—

Outputs (1)

NameTypeDescription
latentLATENT—