Z-Image Loader & Patcher (LyCORIS/LoHA)
Load Z-Image and patch LoHA/LoKR/LoRA in one node
- lora_stack
- RAW_MODEL
- RAW_CLIP
This is the centerpiece of the Zlycoris pack, and it's where the "Z-Image" in every node name earns its keep. ZImageLoaderAndPatcher loads a Z-Image transformer and its Qwen text encoder as raw state dicts, then applies a LyCORIS-style adapter - LoRA, LoHA, LoKR, the works - directly onto the weights, all in one node. The output is RAW_MODEL and RAW_CLIP, the pack's internal raw type, which is the whole philosophy here: everything stays raw state dicts until you explicitly inject them into ComfyUI.
Why the raw pipeline exists
Z-Image LoRA handling is genuinely awkward with stock nodes. The standard trainer is Ostris's AI Toolkit, which saves adapters with lora_te and lora_unet key conventions that stock Load LoRA chokes on, and the community's other big finding is that stacking more than one plain LoRA tends to collapse quality - while LoKR stacks three at max strength happily. This node exists to patch all of that by hand: it understands the low-level layouts (lora_A/lora_B, lora_up/lora_down, hada_w1_a/w1_b/w2_a/w2_b for LoHA, lokr_w1/lokr_w2 for LoKR, plus alpha) and rebuilds the weight deltas itself.
The inputs that matter
transformer_name- frommodels/diffusion_models/(the Z-Image checkpoint, usually a safetensors).text_encoder_name- frommodels/text_encoders/(the Qwen3-4B TE).lora_name- frommodels/loras/.strength_model/strength_clip- default 1.0, and the range goes to ±100. On Z-Image, base-trained LoRAs often genuinely want 2.0+, so don't be shy.lora_stack(LYCORIS_STACK, optional) - chain multiple adapters viaZImageLycorisStacker. The stack applies in order, then the singlelora_nameon top.
Outputs are RAW_MODEL and RAW_CLIP. To actually sample, send them through ZImageComfyInjector to get a real MODEL/CLIP. That two-step dance (load raw → inject) is the pack's core workflow, and it's what enables the raw merging and saving nodes in between.
How it patches
The patcher loads the LoRA, groups its keys, and for each module tries a stack of candidate target key names - lora_unet_/lora_te_ prefixes stripped, then transformer./diffusion_model./model.diffusion_model. variants, including a blocks↔layers swap for architectures that renamed their blocks. It only writes a patch when the shapes line up, and it logs how many layers it patched. That log line is your single most useful debugging tool.
Install
ComfyUI Manager (search ComfyUI-Zlycoris) or:
cd ComfyUI/custom_nodes
git clone https://github.com/TripleHeadedMonkey/ComfyUI-Zlycoris.git
Restart ComfyUI. The dependency list is heavy - transformers, diffusers, optimum, lycoris, sentencepiece among others - so budget for a long first install.
Where people get burned
- "0 layers patched" in the console means a key mismatch. If your LoRA's keys don't match any candidate target, the patch silently no-ops. AITK-format and DiffSynth-format LoRAs have dedicated loaders in this pack (
ZImageAITKLoRALoader,ZImageDiffSynthLoader) - use those instead of fighting this one. - Huge strength range is a trap as much as a feature. The ±100 slider exists because Z-Image LoRAs run hot, but an accidental 50.0 will destroy the model. Start at 1.0, verify with one render, then adjust.
- Strengths of 0 skip the patch entirely - that's the code's way of letting you disable a stack member without deleting it.
- Nothing here is a
MODELyou can sample directly. If you wireRAW_MODELinto a KSampler, ComfyUI will stare at you. Inject first.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| transformer_name | COMBO | 1 options: None | |
| text_encoder_name | COMBO | 1 options: None | |
| lora_name | COMBO | 1 options: None | |
| strength_model | FLOAT | 1.00-100–100 | — |
| strength_clip | FLOAT | 1.00-100–100 | — |
| lora_stackopt | LYCORIS_STACK | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| RAW_MODEL | RAW_MODEL | — |
| RAW_CLIP | RAW_CLIP | — |