Skip to content

Image generation

gmlx makes images from a text prompt, and edits images you give it, with the Z-Image-Turbo, Qwen-Image 2.1 and Krea 2 Turbo models. You can run them from the command line, call them from an app through the OpenAI image API, or use them in ComfyUI. Image generation came with gmlx 0.5 and needs a Mac with an M3 chip or newer and 16 GB of memory or more. An M1 or M2 runs only Z-Image-Turbo, in float16, when you allow it.

Choose a model

Every model runs on 16 GB. pull downloads the quant that suits your Mac's memory, so the download is larger on a Mac with more. The image size is the one you get when you ask for none.

Model Download, 16 GB Mac Download, 24 GB Mac Image size License
z-image-turbo 8.8 GB 10.9 GB 1024x1024 Apache 2.0, any use
qwen-image-turbo 14.4 GB 17.5 GB 1024x1024 Research and evaluation only
qwen-image 14.4 GB 17.6 GB 1024x1024 Research and evaluation only
krea-2-turbo 9.8 GB 14.1 GB 512x512 on 16 GB, else 1024x1024 Free commercial use under $1M of yearly revenue

Start with Z-Image-Turbo: it is the fastest, as Benchmarks shows, and its license allows any use. Models and quants lists the steps each model runs and what it edits from.

Make your first image

Create a configuration with gmlx init if you have none, then download the model and make an image:

gmlx pull z-image-turbo
gmlx image generate z-image-turbo --prompt "a lighthouse at dusk" --seed 1 --output lighthouse.png

An image model is three files: the DiT that makes the image, the text encoder that reads the prompt, and the VAE that turns the result into pixels. pull shows what it will download and the license, then downloads the three and adds the model to your configuration. On a 16 GB Mac it prints:

pull z-image-turbo (Z-Image-Turbo): DiT Q4_K_M, encoder Q8_0, the default for a 16 GB Mac
  dit      z-image-turbo-Q4_K_M.gguf                  4.7 GB  download
  encoder  Qwen3-4B-Q8_0.gguf                         4.0 GB  download
  vae      vae/diffusion_pytorch_model.safetensors    0.2 GB  download, packed to z-image-vae-BF16.gguf
  ...
  the three parts: 8.8 GB, which fit this Mac's 16 GB RAM
  license: Z-Image-Turbo apache-2.0 (https://huggingface.co/Tongyi-MAI/Z-Image-Turbo); encoder apache-2.0
...
registered z-image-turbo in /Users/you/.config/gmlx/gmlx.yaml (the image default)
try it: gmlx image generate z-image-turbo --prompt "a red bicycle" --output out.png

generate writes the image to the --output file. Without --output it writes gmlx-<time>-<seed>.png in the current folder. The PNG keeps the prompt, the seed and the settings it was made with. Each generate loads the model before its first step, which takes a while on every run.

gmlx image generate has the flags for size, steps, edits from an image and several images at once. When a command stops with an error, Troubleshooting has the fix.

Call it from an app

gmlx serve answers the OpenAI image routes with the image models of your configuration. Start it, and keep it running in its own terminal:

gmlx serve

A request names the model and the prompt. The answer holds the image as base64, which this command decodes into a PNG:

curl -s localhost:8080/v1/images/generations \
  -H "Content-Type: application/json" \
  -d '{"model": "z-image-turbo", "prompt": "a lighthouse at dusk"}' \
  | jq -r '.data[0].b64_json' | base64 -d > lighthouse.png

The openai Python package, which pip install openai installs, works the same way. gmlx's own fields, such as seed and steps, go in extra_body:

import base64

from openai import OpenAI

client = OpenAI(base_url="http://localhost:8080/v1", api_key="none")
result = client.images.generate(model="z-image-turbo",
                                prompt="a lighthouse at dusk",
                                extra_body={"seed": 1, "steps": 8})
with open("lighthouse.png", "wb") as f:
    f.write(base64.b64decode(result.data[0].b64_json))

Leave out size to get the model's default size, which fits your Mac. When the server has an API key, pass it as api_key, or to curl as -H "Authorization: Bearer KEY".

The model loads on its first request and shares the memory budget with the chat models. When a chat model and an image model do not fit side by side, the server unloads one to load the other, so the first request after a switch waits for the load. Image API lists every field, edits from your own images, streaming and the errors.

gmlx launch open-webui starts Open WebUI with its image generation turned on, the image button in its chat box, using the server's default image model.

Use a LoRA

A LoRA is a small file that changes a model's style or teaches it a subject. Hugging Face and Civitai host many. Take one made for the same model you run, such as a Z-Image-Turbo LoRA for z-image-turbo, as a .safetensors file:

gmlx image generate z-image-turbo --prompt "a lighthouse at dusk" \
    --adapter ~/models/loras/watercolor.safetensors:0.8 --output lighthouse.png

The number after the colon is the strength, 1 when you leave it out. Repeat --adapter to stack LoRAs. The command applies both halves of a LoRA that also trains the text encoder.

On the server, the LoRAs in the entry's adapters apply to every request, both halves. A request adds its own in adapters. Each id is a path inside a model folder, such as loras/watercolor.safetensors for ~/models/loras/watercolor.safetensors, or the file name of an entry adapter, which sets that adapter's strength for the request:

{"model": "z-image-turbo", "prompt": "a lighthouse at dusk",
 "adapters": [{"id": "loras/watercolor.safetensors", "strength": 0.8}]}

An absolute path gets 400, and so does a request LoRA with text encoder layers. List that one in the entry's adapters, where both halves apply. LoHa, LoKr, DoRA and the other kinds that are not plain LoRA pairs are refused by name, as is a LoRA of another model. ComfyUI takes LoRAs as LoRAs describes.

ComfyUI

ComfyUI builds image workflows from nodes in a browser. The gmlx node pack runs these image models in it, on the gmlx server.

Models and quants

Name Model Steps Edits Text encoder
z-image-turbo Z-Image-Turbo 8 From one image Qwen3-4B
qwen-image Qwen-Image 2.1 40 From up to 10 reference images Qwen3-VL-8B-Instruct, with its mmproj
qwen-image-turbo Qwen-Image 2.1 Turbo 8 From up to 10 reference images Qwen3-VL-8B-Instruct, with its mmproj
krea-2-turbo Krea 2 Turbo 8 From one image Qwen3-VL-4B-Instruct

pull takes the DiT at the quant for your Mac's memory, and the text encoder at Q8_0. A Mac takes the column of the largest class its memory holds. --quant and --encoder-quant pick others, and gmlx pull lists every flag.

Model 16 GB 24 GB 32 GB 64 GB or more
z-image-turbo Q4_K_M Q8_0 BF16 BF16
qwen-image Q4_K_M Q8_0 Q8_0 F16
qwen-image-turbo AD-Q4_K Q8_0 BF16 BF16
krea-2-turbo Q3_K_M Q6_K Q8_0 Q8_0

No Krea 2 quant fits a 1024x1024 image on 16 GB, so a pull of the 16 GB default sets the entry's default size to 512x512, and a pull with another --quant sets none. Of Krea 2, gmlx runs Turbo, and it refuses a Krea 2 Raw GGUF by name.

Licenses

Model License Use
Z-Image-Turbo Apache 2.0 Any, under the license's terms
Qwen-Image 2.1 Qwen Research License Research and evaluation only. Commercial use needs a license from Qwen.
Qwen-Image 2.1 Turbo Qwen Research License Research and evaluation only. Commercial use needs a license from Qwen.
Krea 2 Turbo Krea 2 Community License Free commercial use for a company, affiliates counted, under $1M of revenue in the last twelve months. A deployment must filter what it makes.
Qwen3-4B, Qwen3-VL-8B-Instruct, Qwen3-VL-4B-Instruct Apache 2.0 Any, under the license's terms

The GGUF files are quantized by unsloth, the Qwen-Image 2.1 Turbo files by AtomicChat and the Krea 2 Turbo files by Abiray, under the same licenses. The Krea 2 VAE comes from Comfy-Org's Krea 2 repository.