How to run FLUX 2, Z-Image and OmniSVG locally on Windows with ComfyUI
17 min readWritten by: Jonathan Reis on
A useful local image setup separates three jobs: FLUX 2 for raster direction, Z-Image-Turbo for short readable text, and OmniSVG for native vectors. This guide covers the AMD Windows runtime, each model graph, and a local web control panel instead of MCP.
Updated:

Running an image model locally is straightforward until the workflow stops being one model on one computer. The useful setup here had a Windows machine with an AMD GPU doing inference, a second computer used for development, FLUX 2 for fast raster exploration, Z-Image-Turbo for short readable headlines, and a requirement for actual SVG output rather than a PNG passed through an image tracer.
Those requirements change the architecture. FLUX is good at composition, lighting, materials, and rapid prompt iteration, but its own model card warns that text can be inaccurate or distorted. In this setup, Z-Image-Turbo produced a legible short headline in the first direct test, but it is still a raster model. OmniSVG emits SVG-oriented tokens, but uses a different model stack and is slower by design. Trying to make one model impersonate all three is where most of the wasted time went.
This guide describes a local-only pattern that worked on Windows 11 with a recent AMD Radeon card and 16 GB of VRAM. Replace machine names, paths, and LAN addresses with your own values. Do not publish the ComfyUI API to the Internet.
Start with a ComfyUI runtime that supports both model families
The first attempt used the AMD portable bundle. It ran FLUX successfully, detected the Radeon through ROCm, and reported it through ComfyUI’s API. It could not load OmniSVG.
The failure was not an ordinary missing Python package. OmniSVG’s Qwen 2.5 VL integration imports PyTorch distributed components. The portable build in that test did not include torch._C._distributed_c10d. Installing accelerate, changing a Transformers version, or adding another Python package cannot create a C++ extension that was omitted from the installed PyTorch wheel.
Check this before downloading OmniSVG weights or installing its custom node:
python -c "import torch; import torch.distributed; print(torch.__version__); print(torch.distributed.is_available()); print(torch.cuda.get_device_name(0))"
Continue only if the command completes and torch.distributed.is_available() prints True. On an AMD ROCm installation, the device can still be labelled cuda:0; read the full device name before assuming a NVIDIA runtime is involved.
In the tested setup, a fresh Comfy Desktop installation provided a newer ROCm-backed PyTorch build with distributed support. That left the existing portable installation untouched and gave FLUX and OmniSVG one compatible environment.
This is the practical rule: create an isolated ComfyUI instance when a new model family requires a different runtime. Do not replace the PyTorch wheel inside the installation that already generates images just to satisfy one custom node.
Put FLUX 2 Klein files in the model folders ComfyUI scans
The official FLUX 2 Klein workflow separates the diffusion model, text encoder, and VAE. The base model used here requires these three files:
| File | Folder |
|---|---|
flux-2-klein-base-4b.safetensors |
models/diffusion_models/ |
qwen_3_4b.safetensors |
models/text_encoders/ |
flux2-vae.safetensors |
models/vae/ |
The names matter because the workflow references them directly. Do not put the FLUX diffusion weight under checkpoints and expect a generic checkpoint loader to find it.
Comfy Desktop can index a shared model library outside its application directory. If you want all large weights under one folder you can delete later, make that folder the source of truth and point Comfy Desktop’s shared models folder to it with a directory junction. Test the index after restarting ComfyUI before deleting the old tree. The important part is not the exact path: one physical copy of every weight must remain under the model folders ComfyUI scans.
The current official workflow is also not the old KSampler graph many examples still show. Its relevant sequence is:
UNETLoader
-> CFGGuider
KSamplerSelect + Flux2Scheduler
-> SamplerCustomAdvanced
-> VAEDecode
-> SaveImage
Flux2Scheduler owns the step count. If a ComfyUI template collapses this graph into a subworkflow, double-click the subworkflow to find that node. Looking for a visible KSampler.steps field will not work because there is no KSampler in this graph.
Measure a warm FLUX run before judging speed
FLUX 2 Klein Base is an undistilled model. A 16 GB card can run it, but ComfyUI may move the text encoder, transformer, and VAE between RAM and VRAM. The first generation therefore measures model loading, allocation, and sampling together. It is not a useful prompt-performance benchmark.
In this setup, a cold 1024 by 1024 generation at 20 steps took a little over seven minutes end to end. After the model remained resident, the same resolution at eight steps sampled in about 15 seconds and completed in about 20 seconds. Those numbers are evidence from one machine, not a promise for every AMD card, driver, or prompt.
Use a two-stage workflow instead:
- Explore composition at 640 or 768 pixels with 8 steps.
- Keep a seed when comparing prompt edits.
- Generate a final candidate at 1024 pixels and 12 to 16 steps only after the composition is right.
Lower resolution reduces the number of pixels processed per diffusion step. It is the fastest lever for exploration. Reducing steps lowers time too, but it changes refinement and can hide whether a bad result comes from the prompt or insufficient denoising.
FLUX remains a raster workflow. It can make a convincing glossy game icon, but it is not the final tool for a Sudoku grid with exact cell values, selected fonts, or editable paths. Generate the visual direction with FLUX, then add deterministic typography and UI geometry in a design tool or in SVG code.
Add Z-Image-Turbo when the image needs a short readable headline
Z-Image-Turbo is a 6B distilled raster model. Its maintainers specifically claim accurate English and Chinese text rendering, and the official ComfyUI template targets consumer cards with 16 GB of VRAM. That makes it a practical second raster workflow when a post image needs one short phrase, rather than a reason to replace FLUX everywhere.
It uses a different graph and file set:
| File | Folder | Role |
|---|---|---|
z_image_turbo_bf16.safetensors |
models/diffusion_models/ |
Z-Image diffusion model |
qwen_3_4b.safetensors |
models/text_encoders/ |
shared weight file, loaded as lumina2 for Z-Image |
ae.safetensors |
models/vae/ |
Z-Image VAE |
The filename qwen_3_4b.safetensors can be shared with the FLUX installation, but the loader type cannot. FLUX uses flux2; Z-Image uses lumina2. Reusing the filename is not evidence that their graphs are interchangeable.
The official Z-Image graph is also deliberately different from the FLUX graph:
UNETLoader -> ModelSamplingAuraFlow
CLIPTextEncode -> ConditioningZeroOut
EmptySD3LatentImage -> KSampler -> VAEDecode -> SaveImage
Use eight steps, res_multistep, the simple scheduler, and CFG 1.0. The Turbo template passes an empty negative conditioning through ConditioningZeroOut; it does not expose a useful negative prompt. Put exclusions into the main prompt instead: ask for one exact quoted phrase, then state “no other words”, “no logos”, or “no UI panels”.
On the tested 16 GB AMD system, the first 1024-square Z-Image run took 57.5 seconds end to end because it loaded the text encoder, diffusion model, and VAE. The eight sampling steps themselves took about 17 seconds. That is one ROCm measurement, not a hardware promise, but it is enough to distinguish model loading from generation time.
There is one template-specific trap. ComfyUI exposes the Z-Image text-to-image workflow as a subgraph blueprint. Its root graph must contain only that subgraph node. Dragging a Preview Image or Save Image node next to it can make ComfyUI reject a save with “The root graph of a subgraph blueprint must consist of only a single subgraph node.” Use the complete template with its output node, or edit inside the subgraph instead of decorating its root canvas.
Install OmniSVG for native SVG output
OmniSVG is not a raster tracer. Its model produces a vector representation directly, then the ComfyUI node renders a preview. That makes it useful for icons and simple illustrations where editable paths matter.
The community ComfyUI OmniSVG node loads two model components:
| Component | Purpose |
|---|---|
OmniSVG1.1_4B.bin |
SVG-specialized decoder weights |
Qwen2.5-VL-3B-Instruct |
the compatible vision-language base model, tokenizer, and processor |
The Qwen 2.5 VL model is not interchangeable with a newer chat model called “Qwen 3” or “Qwen 3.8”. OmniSVG’s decoder was trained against Qwen 2.5 VL shapes, layers, tokenizer IDs, and configuration. A better unrelated model cannot replace the base checkpoint.
Download pytorch_model.bin from the OmniSVG 1.1 4B release, rename it to OmniSVG1.1_4B.bin, and place it under models/diffusion_models/. Download the complete Qwen 2.5 VL 3B repository, including both safetensor shards, the index, tokenizer files, processor config, and model config. Point the OmniSVG loader at that local Qwen folder.
Verify local Qwen loading instead of silently downloading again
If the loader is configured with a Hub name such as Qwen/Qwen2.5-VL-3B-Instruct, Transformers treats it as a remote repository. The ComfyUI log will show Hugging Face requests and Fetching 2 files. That can look like a frozen 0% generation while it starts downloading multiple gigabytes into a cache.
Use an explicit local directory path in the loader. A correct run reaches Loading weights without HTTP requests to the model repository. This is also why downloading every file in the Qwen repository matters: a local folder with only the weights is not a complete Transformers model.
The custom node may expose dependency gaps not listed clearly in its installation guide. In this setup, the runtime needed packages for configuration, OpenCV, SVG rendering, model loading, notebook display helpers, and geometry operations. Install missing modules one at a time in the Python environment owned by the new ComfyUI instance. Do not run an unreviewed requirements file if it can replace the ROCm PyTorch wheel that just passed the distributed check.
Use OmniSVG for the part it can reliably do
The first successful icon generation used subtype: icon, one candidate, and a short generation limit. It produced a valid candidate with nine paths in about 20 seconds after model loading. The full initial job took longer because it also loaded Qwen and OmniSVG weights.
That is a useful outcome, but it does not mean OmniSVG is a general-purpose SVG code generator. It is less reliable when a prompt requires all of these at once:
- glossy 3D rendering;
- a complex scene;
- exact colors and a strict element budget;
- five particular digits in fixed grid cells;
- semantic group IDs and SVG 1.1 policy constraints;
- a specific pencil geometry with several materials.
When no candidate passes validation, the node can return a blank preview. Treat the svg_path output and the terminal log as the source of truth, not the white preview alone.
For a Sudoku-style app icon, split the work deliberately:
OmniSVG -> card, pencil, simple shapes, icon silhouette
SVG code or a design tool -> 3x3 grid, exact digits, positions, colors, labels
Start with an English visual prompt, subtype: icon, max_length between 256 and 384, one candidate, and no text. Add complexity only after the simple SVG renders. This is not a compromise caused by local models; exact typography and UI geometry are deterministic design tasks and should not depend on a stochastic generator.
Keep FLUX, Z-Image, and OmniSVG as separate workflows
All three models can live in one ComfyUI installation, but they should not share an active workflow on a 16 GB GPU. FLUX needs its diffusion transformer, text encoder, and VAE. Z-Image needs another diffusion model and VAE. OmniSVG needs Qwen VL and its own decoder. Loading more than one family at a time creates unnecessary offloading and makes every result harder to diagnose.
Use separate saved workflows or separate canvases:
FLUX 2 Klein
-> fast raster reference, composition, material exploration
Z-Image-Turbo
-> short readable headline inside a raster image
OmniSVG
-> native SVG icon or simple illustration
SVG editor or code
-> exact type, grid, layout, and final product constraints
The speed difference is expected. FLUX processes a small number of diffusion steps with highly parallel GPU operations. OmniSVG generates vector tokens autoregressively: each new token depends on the preceding sequence, then the node validates and renders the output. A fast warmed-up FLUX run can therefore beat OmniSVG even when both models are nominally “4B”. Parameter count does not describe the generation algorithm or the surrounding pipeline.
Expose ComfyUI only on a trusted LAN
ComfyUI’s API is useful from another computer, but it is not an Internet-facing application. It should not be port-forwarded or wrapped in a public tunnel without an authentication and authorization layer you operate deliberately.
For a private LAN, stop the Comfy Desktop instance and start its own Python environment with a network listener:
& "<comfy-python>" -s "<comfy-root>\main.py" --listen 0.0.0.0 --disable-api-nodes
Replace placeholders with the paths from your Comfy Desktop instance. The important parts are --listen 0.0.0.0 and --disable-api-nodes.
Create a Windows Firewall inbound rule restricted to the private network and, ideally, the IP address of the development computer. Then verify from that computer:
curl --fail --max-time 10 http://<windows-lan-ip>:8188/system_stats
The response should be JSON that reports the selected GPU. It is a better connectivity test than opening the web interface because it proves the endpoint used by automation is reachable.
Do not use 0.0.0.0 as a public address, do not forward port 8188 through a router, and do not confuse a trusted home LAN with an access-control system. If the second computer is outside the LAN, keep ComfyUI on loopback and use a private tunnel with explicit authentication instead.
Control the Windows GPU from a small local web app
MCP is useful when an agent needs to discover tools and decide how to use them. It is unnecessary overhead for one known image workflow. A small local web app can submit the exact FLUX graph, follow the ComfyUI WebSocket progress stream, relay the final PNG, and keep the interface in a browser instead of a terminal.
The browser should not call the Windows ComfyUI endpoint directly. Cross-origin restrictions can block it, and exposing the Windows endpoint broadly to make CORS easier is the wrong fix. Run the web UI on the development computer and let its local Python process act as a narrow proxy:
Browser -> local UI and proxy -> private LAN ComfyUI -> Windows GPU
The proxy owns a fixed allowlist of inputs: model choice, positive prompt, negative prompt where supported, width, height, steps, CFG, seed, and output prefix. It constructs either the Flux2Scheduler/SamplerCustomAdvanced graph or the Z-Image ModelSamplingAuraFlow/KSampler graph itself. It also writes the returned PNG to a local generated/ directory and serves that local file back to the browser.
That boundary solves three problems at once:
- no browser CORS configuration against the Windows host;
- no need for an MCP server or a remote LLM for repeatable generations;
- a local archive whose names retain the ComfyUI prefix and generation sequence.
Keep the local control panel bound to 127.0.0.1 by default. It is a personal interface, not another network service.
Complete workflow
1. Install a separate Comfy Desktop instance with ROCm PyTorch.
2. Verify torch.distributed before adding OmniSVG.
3. Place FLUX 2 Klein model, text encoder, and VAE in their model folders.
4. Generate a manual FLUX image with the official scheduler-based workflow.
5. Add Z-Image-Turbo with its own diffusion model and VAE; reuse the Qwen file only with the `lumina2` loader type.
6. Use Z-Image for a short headline test before relying on it for a post image.
7. Measure cold and warm runs separately.
8. Install OmniSVG and point it to a complete local Qwen 2.5 VL folder.
9. Generate a simple SVG icon before attempting detailed illustration or text.
10. Keep model families in separate workflows on a 16 GB GPU.
11. Bind ComfyUI to a restricted LAN only when another computer needs it.
12. Verify /system_stats from that computer.
13. Use a local browser proxy for fixed generation jobs and progress feedback.
14. Add long text, grids, and exact product geometry with deterministic tools after the generative step.
Checklist
-
torch.distributed.is_available()isTruebefore OmniSVG is installed. - FLUX 2 Klein files are in
diffusion_models,text_encoders, andvae. - The FLUX graph uses
Flux2SchedulerandSamplerCustomAdvanced. - Z-Image uses
ModelSamplingAuraFlow,ConditioningZeroOut, and CFG1.0. - Z-Image is used for a short text test, not as a guarantee for dense page layout.
- Cold and warm generations were measured separately.
- OmniSVG points to a complete local Qwen 2.5 VL directory.
- OmniSVG was first tested as a short single-candidate icon generation.
- SVG preview output is checked alongside the actual saved SVG path.
- FLUX, Z-Image, and OmniSVG are not intentionally loaded together on a 16 GB card.
- The ComfyUI API is accessible only on loopback or a restricted private LAN.
- No router port forwarding or public tunnel exposes ComfyUI.
- The browser UI is local and proxies only the generation operations it needs.
- Final UI text and exact vector geometry are added deterministically after generation.
The result is not one magic “local AI” button. It is a small pipeline with clear boundaries: FLUX for fast image direction, OmniSVG for native vector candidates, deterministic tools for product detail, and a private browser control surface for the Windows GPU. That separation is what makes the setup maintainable when a model, driver, or prompt inevitably fails.
Related postHow to audit OpenCode AI gateways for model identity, silent fallbacks, and real cost11 min readWritten by: Jonathan Reis on