8.1 KiB
ComfyUI-QwenImageLoraLoader側のZ-Image-Turbo ControlNet対応修正の詳細解説
追加修正が必要になった原因
非公式Z-Image-Turboローダー側(ComfyUI-nunchaku-unofficial-z-image-turbo-loader)でNunchakuZImageTransformer2DModel.forwardをモンキーパッチし、transformer_optionsとcontrolパラメータを受け付けるようにした。
しかし、ComfyUI-QwenImageLoraLoader側のComfyZImageTurboWrapperクラスが、これらのパラメータを下位のNunchakuZImageTransformer2DModel.forwardに正しく伝達していなかった。
ComfyZImageTurboWrapperはLoRA合成とフォワードパスを分離するラッパーで、forwardメソッドで受け取った引数を_execute_modelメソッド経由でNunchakuZImageTransformer2DModel.forwardに渡す。この伝達経路にtransformer_optionsとcontrolを追加する必要があった。
修正したファイル
ComfyUI-QwenImageLoraLoader/wrappers/zimageturbo.py
修正内容
修正1: forwardメソッドのシグネチャ(76行目から85行目)
修正前
def forward(
self,
x,
timestep,
context=None,
y=None,
guidance=None,
**kwargs,
):
修正後
def forward(
self,
x,
timestep,
context=None,
y=None,
guidance=None,
control=None,
transformer_options={},
**kwargs,
):
意味の説明
forwardメソッドのシグネチャにcontrolとtransformer_optionsを追加。ComfyUIのModelPatcherからこれらを受け取れるようにした。
修正2: forwardメソッド内のtransformer_optionsマージ処理(93行目から100行目)
修正内容
# Remove guidance, transformer_options, and attention_mask from kwargs
if "guidance" in kwargs:
kwargs.pop("guidance")
if "transformer_options" in kwargs:
if isinstance(transformer_options, dict) and isinstance(kwargs["transformer_options"], dict):
transformer_options = {**transformer_options, **kwargs.pop("transformer_options")}
else:
kwargs.pop("transformer_options")
if "attention_mask" in kwargs:
kwargs.pop("attention_mask")
意味の説明
kwargsにtransformer_optionsが含まれている場合、明示的なパラメータとマージ。明示的なパラメータが優先。
修正3: _execute_modelメソッドへの引数伝達(219行目、221行目)
修正内容
forwardメソッド内で_execute_modelを呼び出す際に、controlとtransformer_optionsを渡すように変更:
with cache_context(self._cache_context):
out = self._execute_model(x, timestep, context, y, guidance, control, transformer_options, **kwargs)
else:
out = self._execute_model(x, timestep, context, y, guidance, control, transformer_options, **kwargs)
意味の説明
_execute_modelにcontrolとtransformer_optionsを渡すことで、下位のNunchakuZImageTransformer2DModel.forwardまで伝達できるようにした。
修正4: _execute_modelメソッドのシグネチャ(239行目)
修正前
def _execute_model(self, x, timestep, context, y, guidance, **kwargs):
修正後
def _execute_model(self, x, timestep, context, y, guidance, control, transformer_options, **kwargs):
意味の説明
_execute_modelのシグネチャにcontrolとtransformer_optionsを追加。
修正5: customized_forward使用時の伝達(282行目から300行目)
修正内容
customized_forwardが設定されている場合(非公式ZITローダー側のカスタムフォワードを使用する場合)の処理:
if self.customized_forward:
with torch.inference_mode():
forward_kwargs_cleaned = {k: v for k, v in self.forward_kwargs.items() if k not in ("guidance", "ref_latents", "transformer_options", "attention_mask")}
transformer_options_cleaned = dict(transformer_options) if transformer_options else {}
transformer_options_cleaned.pop("guidance", None)
transformer_options_cleaned.pop("ref_latents", None)
return self.customized_forward(
self.model,
hidden_states=x,
encoder_hidden_states=context,
timestep=timestep,
guidance=guidance if self.config.get("guidance_embed", False) else None,
ref_latents=ref_latents_value,
control=control,
transformer_options=transformer_options_cleaned,
**forward_kwargs_cleaned,
**kwargs,
)
意味の説明
customized_forward呼び出し時にcontrolとtransformer_optionsを渡す。transformer_optionsからguidanceとref_latentsを除去(重複を避けるため)。
修正6: 直接forward呼び出し時の伝達(389行目から409行目)
修正内容
customized_forwardが設定されていない場合(直接NunchakuZImageTransformer2DModel.forwardを呼び出す場合)の処理:
# Call Z-Image-Turbo forward with correct signature
# Pass control and transformer_options to allow Model Patcher (double_block patches) to work
# Check if the model's forward method accepts control parameter
import inspect
forward_sig = inspect.signature(self.model.forward)
forward_params = set(forward_sig.parameters.keys())
zimage_kwargs_clean = {k: v for k, v in zimage_kwargs.items() if k not in ('control', 'transformer_options')}
# Build kwargs based on what the forward method accepts
forward_kwargs = zimage_kwargs_clean.copy()
if 'control' in forward_params:
forward_kwargs['control'] = control
if 'transformer_options' in forward_params:
forward_kwargs['transformer_options'] = transformer_options
model_output = self.model(
x_list,
t_zimage,
cap_feats=cap_feats,
**forward_kwargs
)
意味の説明
inspect.signatureでself.model.forwardのシグネチャを確認controlとtransformer_optionsが受け付けられる場合のみ、それらをforward_kwargsに追加- これにより、非公式ZITローダー側の
_patched_forward(モンキーパッチされたforwardメソッド)が正しくtransformer_optionsとcontrolを受け取れる
重要な設計判断
inspect.signatureによる動的パラメータチェック
inspect.signatureを使って、forwardメソッドがcontrolとtransformer_optionsを受け付けるかどうかを動的に確認する。これにより:
- 後方互換性が保たれる(これらのパラメータを受け付けない旧バージョンでもエラーにならない)
- 非公式ZITローダー側のモンキーパッチが適用されているかどうかに関係なく、適切に動作する
- 将来的な拡張に対応しやすい
非公式ZITローダー側との連携
この修正により、以下の連携フローが実現される:
- ComfyUIのModelPatcherが
transformer_optionsとcontrolをComfyZImageTurboWrapper.forwardに渡す ComfyZImageTurboWrapper.forwardがこれらを_execute_modelに渡す_execute_modelがinspect.signatureで確認してからNunchakuZImageTransformer2DModel.forwardに渡す- 非公式ZITローダー側の
_patched_forward(モンキーパッチされたforward)がtransformer_optionsとcontrolを受け取り、double_blockパッチを適用する
まとめ
ComfyUI-QwenImageLoraLoader側のComfyZImageTurboWrapperクラスを修正し、controlとtransformer_optionsパラメータを正しく伝達するようにした。
主な変更点は:
forwardメソッドのシグネチャにcontrolとtransformer_optionsを追加_execute_modelメソッドのシグネチャにcontrolとtransformer_optionsを追加inspect.signatureを使って、下位のforwardメソッドがこれらのパラメータを受け付ける場合のみ渡すように実装
これにより、非公式ZITローダー側で追加したControlNet対応のモンキーパッチが正しく動作し、ControlNetとLoRAの両立が実現される。