Skip to content

Twinflow-Z-Image Turbo support#13285

Open
azazeal04 wants to merge 17 commits intoComfy-Org:masterfrom
azazeal04:master
Open

Twinflow-Z-Image Turbo support#13285
azazeal04 wants to merge 17 commits intoComfy-Org:masterfrom
azazeal04:master

Conversation

@azazeal04
Copy link
Copy Markdown

Added support for the Twinflow Z-Image model

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: de2ff57f3c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 4, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a TwinFlow‑Z‑Image diffusion transformer at comfy/ldm/twinflow/model.py (functions clamp_fp16, modulate; classes JointAttention, FeedForward, TwinFlowTransformerBlock, FinalLayer, TwinFlowZImageTransformer). Registers the model and loader integration: new model class TwinFlow_Z_Image in comfy/model_base.py, registry entry in comfy/supported_models.py, detection logic in comfy/model_detection.py and comfy/sd.py, key‑mapping helper in comfy/utils.py, and LoRA support updates in comfy/lora.py and comfy/lora_convert.py.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed The description is directly related to the changeset, accurately summarizing the addition of Twinflow Z-Image model support across multiple files.
Title check ✅ Passed The title 'Twinflow-Z-Image Turbo support' accurately describes the main objective of adding support for the TwinFlow-Z-Image model across multiple files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@comfy/ldm/twinflow/model.py`:
- Around line 627-648: The pad logic extends cap_feats and cap_pos_ids but
forgets to pad cap_mask, causing length mismatches; inside the if
self.pad_tokens_multiple block (after cap_pos_ids is padded) compute pad_extra
as already done and if pad_extra > 0 extend cap_mask to match cap_feats by
concatenating a pad tensor of shape (cap_mask.shape[0], pad_extra) on the
sequence dimension using cap_mask.dtype and cap_mask.device, with the pad value
set to the same "invalid" value used by incoming masks (0/False); ensure this
updated cap_mask is what gets passed into context_refiner's layer(...) calls.
- Around line 529-537: transformer_options["target_timestep"] may be a plain
int/float, but the code assumes it's a tensor and calls .to(...) on it (see
transformer_options, target_timestep, target_t, and usage in the t embedding
block), which raises AttributeError for scalars; fix by converting
target_timestep to a tensor robustly with torch.as_tensor(target_timestep,
device=t.device, dtype=t.dtype) (then use target_t = that tensor and
expand_if_needed before using self.t_embedder_2 and combining with t_emb) so
both scalar and tensor inputs are accepted.

In `@comfy/lora_convert.py`:
- Around line 35-41: The current twinflow_z_image_lora_to_diffusers function can
silently overwrite existing "t_embedder_2.*" entries when remapping
"t_embedder.*" keys; change the move logic to first check if new_key already
exists in state_dict and if so do not overwrite it — either skip moving the
original key (preserve the existing t_embedder_2 tensor) and optionally log or
raise a descriptive warning/error; update the code path that does
state_dict[new_key] = state_dict.pop(key) to perform an existence check for
new_key and handle collisions without replacing existing tensors.

In `@comfy/lora.py`:
- Around line 331-337: The aliasing loop in comfy/lora.py for
comfy.model_base.TwinFlow_Z_Image blindly adds "t_embedder_2.*" entries from
"t_embedder.*" and can overwrite existing native "t_embedder_2" mappings; change
the loop that iterates over list(key_map.keys()) so that before assigning
key_map[key.replace("t_embedder.", "t_embedder_2.", 1)] = key_map[key] you first
check whether the replacement key already exists and only add the alias when it
does not (i.e., skip or preserve existing "t_embedder_2.*" entries), leaving all
other logic and symbol names (model, key_map, TwinFlow_Z_Image) unchanged.

In `@comfy/model_detection.py`:
- Around line 47-79: The TwinFlow_Z_Image branch returns dit_config before
applying the Z-Image allow_fp16 heuristic, so add an allow_fp16 entry to
dit_config (e.g., dit_config["allow_fp16"]=True/False) using the same heuristic
used by ZImage.__init__ (inspect the existing Z-Image logic that checks
dimensionality/axes or cap_embedder shapes to decide fp16 eligibility) and set
it right before the return in the TwinFlow_Z_Image detection block (the block
that builds dit_config for "TwinFlow_Z_Image" / "twinflow_z_image"). Ensure you
reference the same signals (dit_config["dim"], dit_config["axes_lens"] or
cap_embedder_key-derived shapes, and pad token checks) so TwinFlow_Z_Image
mirrors Z-Image's fp16 gating.

In `@comfy/utils.py`:
- Around line 821-829: The current twinflow_z_image_key_mapping function moves
tensors with keys starting "t_embedder_2." using state_dict.pop which can
overwrite existing "t_embedder." entries and deletes the original; instead
perform a non-destructive remap: for each key starting with "t_embedder_2.",
compute new_key = key.replace("t_embedder_2.", "t_embedder.", 1) and copy the
tensor (state_dict[new_key] = state_dict[key]) without popping; if new_key
already exists, leave the existing state_dict[new_key] intact and do not delete
state_dict[key] (i.e., skip overwrite), ensuring both t_embedder_2.* and
t_embedder.* remain present to preserve backward compatibility in
twinflow_z_image_key_mapping.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 18910f50-263d-4ae9-b713-c2f3f85ec166

📥 Commits

Reviewing files that changed from the base of the PR and between f21f6b2 and de2ff57.

📒 Files selected for processing (8)
  • comfy/ldm/twinflow/model.py
  • comfy/lora.py
  • comfy/lora_convert.py
  • comfy/model_base.py
  • comfy/model_detection.py
  • comfy/sd.py
  • comfy/supported_models.py
  • comfy/utils.py

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@comfy/ldm/twinflow/model.py`:
- Around line 110-113: The hot path currently does unnecessary
unsqueeze/repeat/flatten when n_rep == 1; change the condition that checks n_rep
(computed from n_local_heads and n_local_kv_heads) to only perform the
unsqueeze/repeat/flatten on xk and xv when n_rep > 1, and otherwise leave xk and
xv unchanged so no extra allocations/copies occur; update the block around
n_rep, xk, xv, n_local_heads, and n_local_kv_heads to use if n_rep > 1 and keep
downstream shape expectations intact when skipping the replication.
- Line 708: The TwinFlow adaLN input computed by _compute_twinflow_adaln
(adaln_input, which encodes t_embedder_2/target_timestep dual-timestep
conditioning) is being overwritten/rebuilt from t_emb when pooled CLIP is
enabled; preserve and propagate adaln_input instead of replacing it with a
t_emb-only reconstruction. Update the block that currently rebuilds conditioning
from t_emb (the code paths around adaln_input and t_emb handling when pooled
CLIP is active) so that pooled CLIP uses the already-computed adaln_input (and
retains t_embedder_2/target_timestep signals) rather than discarding them, and
remove the t_emb-only rebuild logic so backward-compatible dual-timestep
conditioning remains intact.
- Around line 696-703: The _forward function uses a shared mutable default
transformer_options={}, which is mutated (keys "total_blocks", "block_type",
"block_index") and can leak state across calls; change the signature default to
transformer_options=None and inside _forward create a fresh dict (e.g., opts =
dict(transformer_options or {})) then mutate and use opts instead of
transformer_options so each invocation has its own options object and avoids
concurrency/state issues.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d385ed21-a0cd-478d-81cd-9a1e3c1ec1a8

📥 Commits

Reviewing files that changed from the base of the PR and between de2ff57 and 5f041f4.

📒 Files selected for processing (1)
  • comfy/ldm/twinflow/model.py

Ensure new key is added only if it doesn't exist.
Prevent overwriting existing keys when mapping t_embedder_2 keys to t_embedder.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@comfy/ldm/twinflow/model.py`:
- Around line 679-684: The code in patchify_and_embed clears the caption mask by
setting mask = None which breaks variable-length caption handling for the joint
transformer; instead construct and return a combined attention mask (preserving
cap_mask) that covers caption tokens and image patches so self.layers and
self.context_refiner see the correct masking. Update the return from
patchify_and_embed to compute mask from cap_mask (and any patch masks if
applicable), account for pad_tokens_multiple padding and batch sizes, and return
that mask alongside padded_full_embed, img_sizes, l_effective_cap_len, freqs_cis
so downstream callers (e.g., self.layers and self.context_refiner) receive the
proper attention_mask.
- Around line 525-527: The pad token parameters x_pad_token and cap_pad_token
are created with torch.empty(), leaving them uninitialized if a checkpoint
conversion doesn't populate both; change their initialization to a deterministic
fallback (e.g., zero-filled tensor) when pad_tokens_multiple is not None so
downstream runs don't read garbage. Locate the branch that checks
pad_tokens_multiple and replace the torch.empty-based init of nn.Parameter for
x_pad_token and cap_pad_token with a zero-initialized tensor (use torch.zeros
with the same shape, device, and dtype) so loaded weights can still overwrite
them safely.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5f48ee12-d276-4b23-be3e-774efd853ec5

📥 Commits

Reviewing files that changed from the base of the PR and between 479536e and 6965b83.

📒 Files selected for processing (1)
  • comfy/ldm/twinflow/model.py

@azazeal04 azazeal04 changed the title Twinflow-Z-Image support Twinflow-Z-Image Turbo support Apr 4, 2026
@azazeal04
Copy link
Copy Markdown
Author

Model used: https://huggingface.co/azazeal2/TwinFlow-Z-Image-Turbo-repacked/tree/main/ComfyUI
TwinFlow KSampler from node pack https://github.com/mengqin/ComfyUI-TwinFlow used, don't need the model patcher.
ComfyUI_temp_atjdj_00001_

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant