Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4fc9bc6
Added qwen and qwen_e Arch references
Danamir Oct 4, 2025
312ded2
Added nunchaku_load_qwen_diffusion_model method
Danamir Oct 4, 2025
98da072
Added more references to Qwen
Danamir Oct 5, 2025
7c05daa
Corrected model type expected when loading qwen-image model
Danamir Oct 5, 2025
7424517
Added qwen text encoder type
Danamir Oct 5, 2025
8eae9bd
Use filename svdq quantization detection for qwen models
Danamir Oct 5, 2025
3f97aba
Use nunchaku dit loader with qwen svdq quant
Danamir Oct 5, 2025
03fac7a
Corrected Arch.qwen_e detection
Danamir Oct 5, 2025
9256066
Temporary icons for Qwen-Image and Qwen-Image-Edit models
Danamir Oct 5, 2025
5a2bc0d
Added a default case in load checkpoint
Danamir Oct 5, 2025
1d53e2f
filename variable check in Quantization.from_string
Danamir Oct 5, 2025
99fa539
Added support for Qwen-Image-Edit with TextEncodeQwenImageEdit node
Danamir Oct 5, 2025
e305386
Lint format corrections
Danamir Oct 5, 2025
329b9ee
Lint format corrections
Danamir Oct 5, 2025
0cda113
Set default Qwen-Image resolutions
Danamir Oct 5, 2025
231c239
Remove unnecessary code
Danamir Oct 5, 2025
14064f6
Added support for Qwen-Image-Edit-Plus, added Arch.qwen_e_p
Danamir Oct 5, 2025
e15de77
Allow references images to be added in Qwen-Image-Edit & Qwen-Image-E…
Danamir Oct 5, 2025
f4cc49e
Use multiple reference_latent in Arch.qwen_e_p instead of relying on …
Danamir Oct 5, 2025
9bdecda
Use auto cpu offloading in Nunchaku Qwen loader
Danamir Oct 6, 2025
0f59bcc
Refactored encode_text_prompt and apply_edit_conditioning to do the E…
Danamir Oct 6, 2025
a776ef4
Typecheck fix.
Danamir Oct 6, 2025
6c11874
Use arch.is_edit check
Danamir Oct 6, 2025
db824a0
Typecheck fix.
Danamir Oct 6, 2025
8075756
Typecheck fix.
Danamir Oct 6, 2025
028b764
Typecheck fix.
Danamir Oct 6, 2025
ce27c8a
Format fix.
Danamir Oct 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion ai_diffusion/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,11 @@ class Quantization(Enum):
svdq = 1

@staticmethod
def from_string(s: str):
def from_string(s: str, filename: str | None = None):
if s == "svdq":
return Quantization.svdq
elif filename and "qwen" in filename and "svdq" in filename:
Copy link
Owner

Choose a reason for hiding this comment

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

Why was this needed? Was there a svdq file that wasn't detected?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added some logs to find what was the quantization value, and nothing is returned in the model entity ! I had to resort to the filename trick...

I'll try some more debugging.

Copy link
Owner

Choose a reason for hiding this comment

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

Ah you're right, the quant field wasn't set by the model detection

Fixed here: Acly/comfyui-tooling-nodes@f555efb

return Quantization.svdq
else:
return Quantization.none

Expand Down Expand Up @@ -351,6 +353,7 @@ def resolve_arch(style: Style, client: Client | ClientModels | None = None):
checkpoint = style.preferred_checkpoint(models.checkpoints.keys())
if checkpoint != "not-found":
arch = models.arch_of(checkpoint)

elif style.checkpoints:
arch = style.architecture.resolve(style.checkpoints[0])

Expand Down
4 changes: 2 additions & 2 deletions ai_diffusion/comfy_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ def parse_model_info(models: dict, model_format: FileFormat):
(
filename,
Arch.from_string(info["base_model"], info.get("type", "eps"), filename),
Quantization.from_string(info.get("quant", "none")),
Quantization.from_string(info.get("quant", "none"), filename),
info.get("is_inpaint", False),
info.get("is_refiner", False),
)
Expand Down Expand Up @@ -625,7 +625,7 @@ def _find_text_encoder_models(model_list: Sequence[str]):
kind = ResourceKind.text_encoder
return {
resource_id(kind, Arch.all, te): _find_model(model_list, kind, Arch.all, te)
for te in ["clip_l", "clip_g", "t5"]
for te in ["clip_l", "clip_g", "t5", "qwen"]
}


Expand Down
41 changes: 39 additions & 2 deletions ai_diffusion/comfy_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -499,12 +499,24 @@ def load_inpaint_model(self, model_name: str):
def load_fooocus_inpaint(self, head: str, patch: str):
return self.add_cached("INPAINT_LoadFooocusInpaint", 1, head=head, patch=patch)

def nunchaku_load_diffusion_model(self, model_path: str, cache_threshold: float):
def nunchaku_load_flux_diffusion_model(self, model_path: str, cache_threshold: float):
return self.add_cached(
"NunchakuFluxDiTLoader", 1, model_path=model_path, cache_threshold=cache_threshold
)

def nunchaku_load_lora(self, model: Output, name: str, strength: float):
def nunchaku_load_qwen_diffusion_model(
self, model_name: str, cpu_offload: str, num_blocks_on_gpu: int, use_pin_memory: str
):
return self.add_cached(
"NunchakuQwenImageDiTLoader",
1,
model_name=model_name,
cpu_offload=cpu_offload,
num_blocks_on_gpu=num_blocks_on_gpu,
use_pin_memory=use_pin_memory,
)

def nunchaku_load_flux_lora(self, model: Output, name: str, strength: float):
return self.add(
"NunchakuFluxLoraLoader", 1, model=model, lora_name=name, lora_strength=strength
)
Expand Down Expand Up @@ -587,6 +599,31 @@ def instruct_pix_to_pix_conditioning(
def reference_latent(self, conditioning: Output, latent: Output):
return self.add("ReferenceLatent", 1, conditioning=conditioning, latent=latent)

def text_encode_qwen_image_edit(
self, clip: Output, vae: Output | None, image: Output, prompt: str | Output
):
return self.add(
"TextEncodeQwenImageEdit", 1, clip=clip, vae=vae, image=image, prompt=prompt
)

def text_encode_qwen_image_edit_plus(
self, clip: Output, vae: Output | None, images: list[Output], prompt: str | Output
):
image1 = images[0] if len(images) > 0 else None
image2 = images[1] if len(images) > 1 else None
image3 = images[2] if len(images) > 2 else None

return self.add(
"TextEncodeQwenImageEditPlus",
1,
clip=clip,
vae=vae,
image1=image1,
image2=image2,
image3=image3,
prompt=prompt,
)

def background_region(self, conditioning: Output):
return self.add("ETN_BackgroundRegion", 1, conditioning=conditioning)

Expand Down
2 changes: 1 addition & 1 deletion ai_diffusion/control.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ def _update_is_supported(self):
self.error_text = _("The server is missing the ClipVision model") + f" {search}"
is_supported = False

if self.mode.is_ip_adapter and models.arch is Arch.flux_k:
if self.mode.is_ip_adapter and models.arch.is_edit:
is_supported = True # Reference images are merged into the conditioning context
elif self.mode.is_ip_adapter and models.ip_adapter.find(self.mode) is None:
search_path = resources.search_path(ResourceKind.ip_adapter, models.arch, self.mode)
Expand Down
128 changes: 128 additions & 0 deletions ai_diffusion/icons/sd-version-qwen-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
128 changes: 128 additions & 0 deletions ai_diffusion/icons/sd-version-qwen-e-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading