Files
Frank e6fcf217b4 docs(comfyui): the GTT aperture is not free RAM beside frank-dragoon
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.
2026-10-21 13:35:50 -07:00

170 lines
9.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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