Skip to content

Add Z-Image (Lumina2/NextDiT) support #64

Open
scottmudge wants to merge 3 commits into
ChenDarYen:mainfrom
scottmudge:lumina2_support
Open

Add Z-Image (Lumina2/NextDiT) support #64
scottmudge wants to merge 3 commits into
ChenDarYen:mainfrom
scottmudge:lumina2_support

Conversation

@scottmudge
Copy link
Copy Markdown

@scottmudge scottmudge commented Nov 30, 2025

Adds support for NextDiT (Lumina2/Z-Image), following existing design patterns.

Seems to work as expected. Increasing nag_scale above 3 or so seems to cause distortions, but it has the desired effect with:

  • nag_scale = ~1.5-2.3
  • nag_tau = ~2.5
  • nag_alpha = ~0.25
  • nag_sigma_end = ~0.7-0.9

Notably the nag_sigma_end should be increased from the default 0.0, as applying NAG to the final few steps of inference seems to reduce quality, and probably isn't needed.

Example:

image

Note: I mis-captioned the text in the image. Alpha should read 0.25, not 2.5.


NOTE: if you are encountering issues with nodes not loading, you need to also apply this PR (#59) to your local repo clone, OR use my fork (https://github.com/scottmudge/ComfyUI-NAG/tree/main, which includes this Z-Image support PR and that compatibility PR).

This repo has not been updated in a while, and PR 59 fixes some compatibility issues with more recent versions of ComfyUI.

@scottmudge
Copy link
Copy Markdown
Author

For anyone who wants to use this now, use my fork:

https://github.com/scottmudge/ComfyUI-NAG/tree/main

It's been merged into main, along with some other fixes to support recent ComfyUI versions.

@NulliferBones
Copy link
Copy Markdown

Causes me to OOM

@scottmudge
Copy link
Copy Markdown
Author

scottmudge commented Nov 30, 2025

Yes it uses more VRAM because it's basically doubling the context processing and requires additional buffers for computing for negative guidance.

No easy way around that. The turbo model on CFG 1.0 normally just completely discards the negative conditioning, which saves memory.

You'll probably have to free up VRAM at some other step/location. Reduce resolution, etc. I do notice ComfyUI is using 90% of my VRAM on first run, and then drops back down to 70% for all subsequent runs. At least with Z-Image. Not sure if they have a memory management bug or something.

You can try disabling NAG for the first run and then re-enabling it.

@NulliferBones
Copy link
Copy Markdown

I have to even restart comfyui for it to stop throwing oom after using it. (This makes me think something is definitely off)

I can use this nag node fine with things that are way heavier like chroma at resolutions beyond 720x1280.

@scottmudge
Copy link
Copy Markdown
Author

Hmm can you post your workflow?

@NulliferBones
Copy link
Copy Markdown

It's just the default workflow for z-image-turbo but with the nag swapped in. Nothing special.

I tried it with the current official release comfy, as well as the one you can pull that is more up to date and it's the same thing.

@scottmudge
Copy link
Copy Markdown
Author

I mean are you using the NAGGuider/NAGCFGGuider or "KSampler with NAG" node?

@NulliferBones
Copy link
Copy Markdown

NulliferBones commented Nov 30, 2025

I mean are you using the NAGGuider/NAGCFGGuider or "KSampler with NAG" node?

i tried both, here is the error

!!! Exception during processing !!! Allocation on device 
Traceback (most recent call last):
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/execution.py", line 510, in execute
    output_data, output_ui, has_subgraph, has_pending_tasks = await get_output_data(prompt_id, unique_id, obj, input_data_all, execution_block_cb=execution_block_cb, pre_execute_cb=pre_execute_cb, hidden_inputs=hidden_inputs)
                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/execution.py", line 324, in get_output_data
    return_values = await _async_map_node_over_list(prompt_id, unique_id, obj, input_data_all, obj.FUNCTION, allow_interrupt=True, execution_block_cb=execution_block_cb, pre_execute_cb=pre_execute_cb, hidden_inputs=hidden_inputs)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/custom_nodes/comfyui-lora-manager/py/metadata_collector/metadata_hook.py", line 165, in async_map_node_over_list_with_metadata
    results = await original_map_node_over_list(
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/execution.py", line 298, in _async_map_node_over_list
    await process_inputs(input_dict, i)
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/execution.py", line 286, in process_inputs
    result = f(**inputs)
             ^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/custom_nodes/ComfyUI-NAG/node.py", line 166, in sample
    return common_ksampler_with_nag(model, seed, steps, cfg, nag_scale, nag_tau, nag_alpha, nag_sigma_end,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/custom_nodes/ComfyUI-NAG/node.py", line 28, in common_ksampler_with_nag
    samples = sample_with_nag(
              ^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/custom_nodes/ComfyUI-NAG/sample.py", line 10, in sample_with_nag
    samples = sampler.sample(
              ^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/custom_nodes/ComfyUI-NAG/samplers.py", line 255, in sample
    return sample_with_nag(
           ^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/custom_nodes/ComfyUI-NAG/samplers.py", line 66, in sample_with_nag
    return guider.sample(
           ^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/custom_nodes/ComfyUI-NAG/samplers.py", line 197, in sample
    output = executor.execute(
             ^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/patcher_extension.py", line 112, in execute
    return self.original(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/samplers.py", line 997, in outer_sample
    output = self.inner_sample(noise, latent_image, device, sampler, sigmas, denoise_mask, callback, disable_pbar, seed, latent_shapes=latent_shapes)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/custom_nodes/ComfyUI-NAG/samplers.py", line 122, in inner_sample
    samples = executor.execute(
              ^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/patcher_extension.py", line 112, in execute
    return self.original(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/samplers.py", line 752, in sample
    samples = self.sampler_function(model_k, noise, sigmas, extra_args=extra_args, callback=k_callback, disable=disable_pbar, **self.extra_options)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/venv/lib/python3.12/site-packages/torch/utils/_contextlib.py", line 116, in decorate_context
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/k_diffusion/sampling.py", line 199, in sample_euler
    denoised = model(x, sigma_hat * s_in, **extra_args)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/samplers.py", line 401, in __call__
    out = self.inner_model(x, sigma, model_options=model_options, seed=seed)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/custom_nodes/ComfyUI-NAG/samplers.py", line 105, in __call__
    return self.predict_noise(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/samplers.py", line 963, in predict_noise
    return sampling_function(self.inner_model, x, timestep, self.conds.get("negative", None), self.conds.get("positive", None), self.cfg, model_options=model_options, seed=seed)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/samplers.py", line 381, in sampling_function
    out = calc_cond_batch(model, conds, x, timestep, model_options)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/samplers.py", line 206, in calc_cond_batch
    return _calc_cond_batch_outer(model, conds, x_in, timestep, model_options)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/samplers.py", line 214, in _calc_cond_batch_outer
    return executor.execute(model, conds, x_in, timestep, model_options)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/patcher_extension.py", line 112, in execute
    return self.original(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/samplers.py", line 326, in _calc_cond_batch
    output = model.apply_model(input_x, timestep_, **c).chunk(batch_chunks)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/model_base.py", line 161, in apply_model
    return comfy.patcher_extension.WrapperExecutor.new_class_executor(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/patcher_extension.py", line 112, in execute
    return self.original(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/model_base.py", line 203, in _apply_model
    model_output = self.diffusion_model(xc, t, context=context, control=control, transformer_options=transformer_options, **extra_conds)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/venv/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1751, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/venv/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1762, in _call_impl
    return forward_call(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/custom_nodes/ComfyUI-NAG/lumina2/model.py", line 55, in forward
    output = comfy.patcher_extension.WrapperExecutor.new_class_executor(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/patcher_extension.py", line 112, in execute
    return self.original(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/ldm/lumina/model.py", line 574, in _forward
    x, mask, img_size, cap_size, freqs_cis = self.patchify_and_embed(x, cap_feats, cap_mask, t, num_tokens, transformer_options=transformer_options)
                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/ldm/lumina/model.py", line 539, in patchify_and_embed
    x = layer(x, padded_img_mask, freqs_cis[:, cap_pos_ids.shape[1]:], t, transformer_options=transformer_options)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/venv/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1751, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/venv/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1762, in _call_impl
    return forward_call(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/ldm/lumina/model.py", line 284, in forward
    self.feed_forward(
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/venv/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1751, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/venv/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1762, in _call_impl
    return forward_call(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/ldm/lumina/model.py", line 175, in forward
    return self.w2(self._forward_silu_gating(self.w1(x), self.w3(x)))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/nullifer/Documents/AI/Comfy2/ComfyUI/comfy/ldm/lumina/model.py", line 172, in _forward_silu_gating
    return F.silu(x1) * x3
           ~~~~~~~~~~~^~~~
torch.OutOfMemoryError: Allocation on device 

Got an OOM, unloading all loaded models.
Prompt executed in 2.41 seconds



@scottmudge
Copy link
Copy Markdown
Author

Thanks I'll take a look when I get home later today

@scottmudge
Copy link
Copy Markdown
Author

scottmudge commented Nov 30, 2025

Yeah I've re-reviewed the memory allocations, and even explicitly deleting all buffers after they're used (even though torch gc should be cleaning these up automatically), I only see ~3% more VRAM (~700 MB at 1440p generation) used compared to the stock K Sampler. So if you're running on thin margins where you don't have 700 MB free, then you might run into OOM.

But there's no way around that, as the context needs to be doubled to handle negative attention.

One thing I did notice is more of a bug with ComfyUI itself. The default workflow (same one you mentioned), without the NAG nodes, does not offload the Qwen3 4B CLIP model to CPU before inference with K Sampler when the text prompt is changed. This causes 5GB of VRAM to be consumed unnecessarily. It only seems to offload it to CPU after the entire prompt has finished. If the text prompt doesn't change, then subsequent runs will use far less VRAM, since it doesn't need to load Qwen3 back into VRAM.

I did fix the issue with NAG not being properly reverted/unpatched on the model when it's turned off. I'll be pushing those changes soon. But the OOM'ing/high VRAM usage seems to happen with the normal/non-NAG sampler for me. The only thing that seems to avoid high VRAM usage is using the CPU for Qwen3 4B, effectively bypassing the issue where it's only offloaded to CPU after the entire prompt finishes.

@NulliferBones
Copy link
Copy Markdown

I will test it now, however this high vram usage thing you're mentioning I did not notice. Even with my limited vram without nag I can generate at even 4k.

@NulliferBones
Copy link
Copy Markdown

Tested, and it's still happening.
Something like this was happening in older versions for chroma.

…n, since transformer_options seems to be getting reset by ComfyUI base.
@scottmudge
Copy link
Copy Markdown
Author

Pushed some minor fixes. Though @NulliferBones your VRAM issues are likely still due to the way ComfyUI handles offloading the Qwen model. They might have improved it in recent updates to their master branch.

After additional testing, it looks like some good parameter values are:

  • nag_scale = ~1.5-2.3
  • nag_tau = ~2.5
  • nag_alpha = ~0.25
  • nag_sigma_end = ~0.7-0.9

Notably the nag_sigma_end should be increased from 0.0, as applying NAG to the final few steps of inference seems to reduce quality, and probably isn't needed.

@NulliferBones
Copy link
Copy Markdown

Pushed some minor fixes. Though @NulliferBones your VRAM issues are likely still due to the way ComfyUI handles offloading the Qwen model. They might have improved it in recent updates to their master branch.

After additional testing, it looks like some good parameter values are:

* `nag_scale = ~1.5-2.3`

* `nag_tau = ~2.5`

* `nag_alpha = ~0.25`

* `nag_sigma_end = ~0.7-0.9`

Notably the nag_sigma_end should be increased from 0.0, as applying NAG to the final few steps of inference seems to reduce quality, and probably isn't needed.

Whatever you've changed has allowed me to generate at 768x1024 now instead of 512x768
Much better, but still lower than what I can do with the heavier Chroma model. (Chroma I can do 720x1280 before oom, with z-image my target is 1088x1440)

So odd, the model is small, runs quick. The new comfyui vram management almost nullifies oom issues in general, so it's weird nag would cause OOM issues. Especially at a low resolution, when without i can generate at nearly 4k. (With z-image)

@rktvr
Copy link
Copy Markdown

rktvr commented Dec 4, 2025

does this also fix it working with chroma? the latest comfy update discards all layers, or something like that so it has zero effect at all

@bghira
Copy link
Copy Markdown

bghira commented Dec 14, 2025

  1. L72-73: The _nag_img_token_len cleanup only happens for the last mod in the loop, not all of them
  2. the nag_forward_wrapper closure captures self (the Switch) which holds references to _nag_negative_context and original_attributes
  3. original_attributes dict stores references by id(module) but never fully cleared

if these help solve the memory concern, it's all i could see in a short review.

@scottmudge
Copy link
Copy Markdown
Author

@bghira

Thanks, I'll work on addressing those

@deniaud
Copy link
Copy Markdown

deniaud commented Dec 21, 2025

Nice work. Qwen Image / Edit version?

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.

5 participants