Measured 2026-10-21 with frank-dragoon live: MemAvailable 15.3 GiB, iGPU busy 1.75 GiB. The Qwen-Image weight sets (13.3-14.2 GB) do not fit that budget, and the page's 122 GB /system_stats figure is the aperture, not headroom. Adds the fit table and the stop-mask-render-verify procedure (the 3090 bench law, applied to the APU); ComfyUI.md gotcha links it.
170 lines
9.2 KiB
Markdown
170 lines
9.2 KiB
Markdown
---
|
||
type: howto
|
||
description: "Proven Qwen-Image text-to-image workflows on Dankclaw: the recipes, the API call shape, and which models to add next."
|
||
tags:
|
||
- dankclaw
|
||
- comfyui
|
||
- qwen-image
|
||
timestamp: 2026-10-05
|
||
---
|
||
|
||
# ComfyUI Qwen-Image Workflows
|
||
|
||
Two ready-to-load text-to-image workflows for the Qwen-Image 2.1 payload
|
||
already on Dankclaw, both proven end-to-end on 2026-10-05 by POSTing to the
|
||
live API on port 8188 and verifying the rendered PNG (the renders are still on
|
||
disk: `qwen21-art_00001_.png` 22:41 and `qwen21-text_00001_.png` 22:44,
|
||
`ls -l /home/dank/comfyui-data/output/` 2026-10-18). The repo copies are the
|
||
source of truth; the host copies under `/home/dank/comfyui-data/workflows/`
|
||
are for convenience and are byte-identical today (`md5sum` matches both files,
|
||
2026-10-18).
|
||
|
||
## What is on disk
|
||
|
||
Sizes are GiB, measured `ls -l` on the host 2026-10-18 (all files dated
|
||
2026-09-21).
|
||
|
||
| Path (under `/home/dank/comfyui-data/models/`) | Size | Role |
|
||
|---|---|---|
|
||
| `diffusion_models/qwen_image_2.1_int8_convrot.safetensors` | 6.8 GB (7,256,783,064 B) | **The one the workflows use** — int8-convrot quant, ComfyUI-core native |
|
||
| `diffusion_models/qwen_image_2.1_bf16.safetensors` | 13.3 GB (14,230,280,616 B) | Full-precision fallback |
|
||
| `diffusion_models/qwen-image-2.1-Q8_0.gguf` (+ `-arch`) | 7.1 GB each (7,591,551,648 / 7,591,551,680 B) | GGUF alternative (needs ComfyUI-GGUF custom node, present in `custom_nodes/`) |
|
||
| `text_encoders/qwen3vl_8b_w4a8.safetensors` | 5.9 GB (6,312,105,364 B) | **The one the workflows use** — 4-bit-weights/8-bit-act Qwen3-VL 8B encoder |
|
||
| `text_encoders/qwen3vl_8b_int8_convrot.safetensors` | 8.7 GB (9,350,798,360 B) | Mid quant |
|
||
| `text_encoders/qwen3vl_8b_bf16.safetensors` | 16.3 GB (17,534,334,616 B) | Full precision |
|
||
| `vae/qwen_image_2.1_vae_bf16.safetensors` | 645 MB (675,509,688 B) | 2.1 VAE (used) |
|
||
| `vae/qwen_image_vae.safetensors` | 243 MB (253,806,246 B) | Smaller VAE |
|
||
|
||
No LoRAs are on disk yet, and `models/lora/` / `models/controlnet/` do not
|
||
exist — see [Recommended additions](#recommended-additions).
|
||
|
||
## The workflows
|
||
|
||
Both are API-format JSON (ComfyUI 0.37 loads them via the UI's **Load** dialog
|
||
too): `dankclaw/comfyui/workflows/` in the repo,
|
||
`/home/dank/comfyui-data/workflows/` on the host. Node chain in both:
|
||
|
||
```
|
||
UNETLoader (int8_convrot) ──┐
|
||
CLIPLoader (qwen_image, w4a8) ─┤ CLIPTextEncode pos/neg
|
||
VAELoader (2.1 bf16) ────────┤
|
||
EmptySD3LatentImage ─────────┴─ KSampler ─ VAEDecode ─ SaveImage
|
||
```
|
||
|
||
**Common sampler settings:** `cfg 1.0` (Qwen-Image 2.1 expects CFG-free
|
||
sampling), `sampler_name: euler`, `scheduler: simple`, `denoise: 1.0`, seed
|
||
fixed in the file (`1930` in the art workflow, `2026` in the text one) —
|
||
read from `dankclaw/comfyui/workflows/*.json` node `9`.
|
||
|
||
Node `class_type`s in both files: `CLIPTextEncode` ×2, `UNETLoader`
|
||
`CLIPLoader`, `VAELoader`, `EmptySD3LatentImage`, `KSampler`, `VAEDecode`
|
||
`SaveImage` (ids 3–11).
|
||
|
||
| Workflow | File | Shape | Steps | Made for |
|
||
|---|---|---|---|---|
|
||
| Art | `qwen-image-2.1-t2i-art.json` | 1024×1024 | 20 | General illustration/prose prompts |
|
||
| Legible text | `qwen-image-2.1-t2i-legible-text.json` | 832×1216 | 25 | Posters, captions, any in-image text |
|
||
|
||
### Legible-text prompt recipe
|
||
|
||
Qwen-Image 2.1 is one of the best open-weight text renderers, but only if the
|
||
prompt is written for it:
|
||
|
||
1. **Quote the exact strings**: `large bold white text reading "SOLIDARITY OF
|
||
THE SOVIET COMPUTER SYSTEMS"` — quoted text is rendered literally.
|
||
2. **Describe layout, not vibes**: say *centered / below it / large vs small*,
|
||
the typeface family (sans-serif), and the color.
|
||
3. **Say what NOT to draw**: end with `no other words, no watermark`.
|
||
4. Keep the negative side on `misspelled, warped letters, extra text` (already
|
||
in the workflow).
|
||
5. More steps help text: the text workflow uses 25 vs 20.
|
||
|
||
Verified render: `SOLIDARITY OF THE SOVIET COMPUTER SYSTEMS` + `DANKCLAW
|
||
DANKSERVER EST 2026` came back crisp and correctly spelled at 832×1216
|
||
(`qwen21-text_00001_.png`, 953,254 B — still on disk, `ls -l
|
||
/home/dank/comfyui-data/output/` 2026-10-18). One caveat from the same render:
|
||
a shorter secondary line is where misspellings creep in — proofread the first
|
||
render before shipping.
|
||
|
||
## Driving it from the API
|
||
|
||
ComfyUI 0.37 **requires the graph wrapped in a `prompt` key** — a bare
|
||
`{node-id: node}` body gets `{"error": {"type": "no_prompt"}}` (verified
|
||
2026-10-05):
|
||
|
||
```bash
|
||
curl -s -X POST http://127.0.0.1:8188/prompt -H 'Content-Type: application/json' \
|
||
-d "$(python3 -c 'import json;print(json.dumps({"prompt": json.load(open("dankclaw/comfyui/workflows/qwen-image-2.1-t2i-art.json"))}))')"
|
||
# -> {"prompt_id": "...", ...}
|
||
curl -s http://127.0.0.1:8188/history/<prompt_id> # status.status_str == "success"
|
||
```
|
||
|
||
Outputs land in `/home/dank/comfyui-data/output/`. The queue is FIFO — the
|
||
two workflows above ran back-to-back unattended.
|
||
|
||
**Note:** the container's UI-saved workflows live in the ephemeral
|
||
`/opt/ComfyUI/user` layer and do NOT survive an image rebuild — the unit mounts
|
||
only `models`, `input`, `output`, `custom_nodes` and the healthcheck file
|
||
(`podman inspect comfyui` 2026-10-18; `dankclaw/comfyui/quadlet/comfyui.container:48-52`)
|
||
— hence the host-side `workflows/` dir and the repo copy.
|
||
|
||
## Recommended additions
|
||
|
||
Quantized preferred. The iGPU's GTT aperture is not free RAM beside
|
||
frank-dragoon — size every pick against *What actually fits beside
|
||
frank-dragoon* below (the RTX 3090 is frank-zealot's). All repos verified 2026-10-05 and
|
||
all four still resolve today (`huggingface.co/lightx2v/Qwen-Image-Lightning`
|
||
`huggingface.co/unsloth/Qwen-Image-Edit-2511-GGUF`
|
||
`huggingface.co/Comfy-Org/Qwen-Image-DiffSynth-ControlNets`
|
||
`huggingface.co/QuantStack/Wan2.2-TI2V-5B-GGUF`, 2026-10-18). None are on disk
|
||
yet: `models/` holds no lora/, controlnet/ or Wan/Edit file (`ls -R` 2026-10-18).
|
||
|
||
| # | What | Repo | Grab | Size | Why |
|
||
|---|---|---|---|---|---|
|
||
| 1 | **Lightning 8-step LoRA** (T2I speed) | `lightx2v/Qwen-Image-Lightning` | `qwen_image_lightning_8steps_*.safetensors` (LoRA) | ~1–2 GB | 20 steps → 8 with a `LoraLoader` node; 2–3× faster renders on the iGPU, negligible quality loss |
|
||
| 2 | **Qwen-Image-Edit-2511 GGUF** (image editing) | `unsloth/Qwen-Image-Edit-2511-GGUF` | Q4_K_M (~13.2 GB) or Q4_0 (~11.9 GB) | ~12–13 GB | Unlocks img2img "edit this photo" workflows — a capability class the fleet has zero of; Q4 keeps it iGPU-friendly |
|
||
| 3 | **DiffSynth ControlNets** (structure control) | `Comfy-Org/Qwen-Image-DiffSynth-ControlNets` | `split_files/model_patches/` canny + depth | ~2–3 GB each | Pose/edge/depth-guided layouts — pairs with the legible-text workflow for exact poster composition. The `QwenImageDiffsynthControlnet` node is already in the running ComfyUI (`GET http://127.0.0.1:8188/object_info/QwenImageDiffsynthControlnet` → 200, 2026-10-18) |
|
||
| 4 | **Wan 2.2 TI2V-5B GGUF** (first video model) | `QuantStack/Wan2.2-TI2V-5B-GGUF` | Q4/Q5 GGUF (~6–8 GB) | ~6–8 GB | T2V+I2V in one dense 5B model; the gentlest on-ramp into video generation, runs in ComfyUI core (`wan` is in this build's `CLIPLoader` type enum — `GET http://127.0.0.1:8188/object_info/CLIPLoader` 2026-10-18) |
|
||
|
||
Placement: #1 → `models/lora/` (create it), #2 → `models/diffusion_models/`
|
||
#3 → `models/controlnet/` (create it), #4 → `models/diffusion_models/`.
|
||
Fetch with `scripts/download-frank-*.sh` discipline (`-f` + byte-count +
|
||
sha256 checks) or a plain `hf download` with the token in the environment —
|
||
never on the command line.
|
||
|
||
Skip list: the original `city96/Qwen-Image-gguf` conversions (superseded by
|
||
the 2.1 files already on disk), and any BF16 of #2/#4 — they double the disk
|
||
bill, and see *What actually fits beside frank-dragoon* for why raw GTT size
|
||
is not the real budget.
|
||
|
||
## What actually fits beside frank-dragoon
|
||
|
||
The 122 GB `/system_stats` figure is the GTT **aperture**, not free memory: on
|
||
an APU the aperture and `MemAvailable` are the same physical RAM, and
|
||
frank-dragoon pins tens of GiB of it. Measured 2026-10-21 with frank-dragoon
|
||
live: `MemAvailable` 15.3 GiB, iGPU busy 1.75 GiB — ComfyUI itself idles at
|
||
~10 MB, so the budget for a generation run is roughly what `free` says.
|
||
|
||
Weights must land inside that budget with slack for compute buffers and
|
||
activations (the mmproj-class lesson: price a model at ~1.5× its file set):
|
||
|
||
| Pipeline (weights) | Fits beside frank-dragoon? |
|
||
|---|---|
|
||
| Qwen-Image 2.1 int8_convrot + w4a8 + bf16 VAE (~14.2 GB) — the two proven workflows | **No** — thrash-or-fail; do not queue it while the endpoint serves |
|
||
| GGUF Q8_0 + w4a8 + small VAE (~13.3 GB) | No, same reason |
|
||
| Any BF16 combination | No |
|
||
| SDXL-Turbo / SD 1.5-class (~2–7 GB) | Yes, with real headroom |
|
||
|
||
**The law: one process owns the memory — same rule as the 3090 bench law.**
|
||
For a Qwen-Image render: stop and mask frank-dragoon
|
||
(`sudo systemctl stop frank-dragoon` + `mask` — the mask stops
|
||
`Restart=always` from firing mid-render), generate, unmask, verify
|
||
`curl 192.168.0.143:7770/health`. The proven workflows above then run with
|
||
the whole machine. Do not treat `/system_stats`'s 122 GB as an invitation.
|
||
|
||
## See Also
|
||
|
||
- [[ComfyUI]] — the service itself (image, unit, GPU access)
|
||
- [[ComfyUI ROCm and Vulkan]] — the live-verified GPU path
|
||
- [[Dankclaw Stack]] — the host
|