Image Generation¶
mlxcel generates and edits images with diffusion checkpoints through the mlxcel generate-image subcommand and the OpenAI-compatible POST /v1/images/generations and POST /v1/images/edits server routes. Diffusion models produce pixels rather than tokens, so image generation is a separate surface from generate and serve -m, the same way detect is separate for boxes.
A checkpoint the loader recognizes as an image model is refused by mlxcel generate and mlxcel serve -m with a message naming generate-image, and a checkpoint the probe recognizes but this build does not implement fails with image generation family <family> is not supported by this build.
Supported Families¶
| Family | Checkpoints | Tasks | Default steps / guidance |
|---|---|---|---|
flux2 | FLUX.2 Klein 4B, 9B, base-4B, base-9B, 9b-kv, and the mlx-community 4-bit conversions | generate, edit (reference images) | distilled 4 / 1.0; base 50 / 4.0 |
z_image | Tongyi-MAI Z-Image-Turbo, Z-Image | generate, edit (img2img) | Turbo 8 / 0; base 50 / 4 |
bonsai | Prism Bonsai ternary 2-bit FLUX.2 Klein 4B | generate | 4 / 1.0 |
ernie_image | Baidu ERNIE-Image-Turbo, ERNIE-Image | generate, edit (SDEdit img2img) | Turbo 8 / 1.0 (edit 8 / 3.0); base 50 / 4.0 |
mage_flow | Mage-Flow, Mage-Flow-Base, Mage-Flow-Turbo, Mage-Flow-Edit, Mage-Flow-Edit-Base, Mage-Flow-Edit-Turbo | generate or edit, fixed by the variant | Turbo 4 / 1.0; Mage-Flow 20 / 5.0; Base and Edit 30 / 5.0 |
qwen_image | Qwen-Image-2.1 | generate, edit (one or more references, RGBA kept) | generate 30 / 1.0; edit 40 / 1.0 |
ideogram4 | ideogram-ai/ideogram-4-fp8 (license-gated) | generate | 20 / 7.0 (3.0 for the last two steps) |
ming_image | Ming-Image-0.1-Design and its MLX 8-bit and 4-bit conversions | generate (RGBA output) | 12 / 1.0 |
llada_image | LLaDA-Image-Turbo, LLaDA-Image | generate (text or VQ prior), edit (one source image) | Turbo 4 / 1.0; base 50 / 5.0 |
The family is detected from the checkpoint directory's manifest.json, model_index.json, component configs, and transformer weight map. Detection reads JSON only and never loads weights, so a wrong directory or an unported family fails before any memory is spent.
CLI¶
mlxcel generate-image -m models/flux2-klein -p "a watercolor fox"
mlxcel generate-image -m models/flux2-klein -p "a fox" --size 768x512 --seed 7 -n 2 -o fox.png
mlxcel generate-image -m models/flux2-klein --task edit --image fox.png -p "make it night"
| Flag | Default | Description |
|---|---|---|
-m, --model <PATH> | required | Checkpoint directory (Diffusers layout). |
-p, --prompt <TEXT> | required | Prompt, or the edit instruction. |
--negative-prompt <TEXT> | model default | Negative prompt. |
--task <generate\|edit> | generate | Text-to-image or reference-image editing. |
--image <PATH> | - | Reference image. Repeat for several. Required for edit, rejected for generate. |
--size <WxH> | 512x512 for generation; for editing the first reference's size, or what the family derives from it | Output size. Both sides must be multiples of the family's grid (16 for most families). |
--steps <N> | model default | Denoising steps. |
--guidance <F> | model default | Classifier-free guidance scale. |
--seed <N> | random 32-bit | Seed, always printed. |
-n <N> | 1 | Number of images (1 to 10). Image i uses seed seed + i, except FLUX.2 generation. |
-o, --output <PATH> | outputs/image-<seed>.png | Output path. The extension is forced to .png; with -n greater than one the names are <stem>-01.png, <stem>-02.png, and so on. |
--gen-kwargs <JSON> | - | Model-specific options as a JSON object, passed to the model as extra. |
The command validates the model directory, the arguments, the reference images, and the output directory before it classifies the family or loads any weight. When a model rewrites the prompt (ERNIE-Image's prompt enhancer), the CLI prints revised prompt: <text> after the line naming each saved image.
FLUX.2 generation follows upstream mlx-vlm: the n images share one noise tensor drawn from seed and come from one prompt encode, so every image reports the same seed and image i is not the image seed + i gives on its own. Edits and the other families run once per image with seed seed + i.
--gen-kwargs carries model-specific knobs. FLUX.2 and Bonsai accept max_sequence_length and tiled_vae; Z-Image, ERNIE-Image, and the other families document their own options in docs/image-generation.md.
Server¶
--image-model (also MLXCEL_IMAGE_MODEL, on both mlxcel-server and mlxcel serve) loads a side worker the way --embedding-model does: a dedicated thread owns the model, a bounded queue admits requests, and a per-request timeout frees the caller. A load failure is fatal at startup, so a command line that asked for image routes never answers 501 for them. Requests run one at a time, because a diffusion run holds the GPU for seconds; a full queue answers 503 and a timeout answers 504.
Image-only mode¶
Without -m, the image checkpoint is the served model rather than a side model:
mlxcel-server --image-model <image checkpoint> --port 8080
mlxcel serve --image-model <image checkpoint>
The served id is the first --alias entry when given, otherwise the checkpoint directory name, and /v1/models reports it with the image capability and no completion. /health follows the image worker. Chat and tokenizer routes, including /tokenize, /detokenize and /apply-template, answer the structured 501 that names --image-model and no -m. Image-only mode cannot be combined with --models-dir, --models-preset, --webui, --embedding-model, --reranker-model, --embeddings or --reranking; startup fails naming both flags. Passing -m as well keeps the two-model behavior above.
| Method | Path | Notes |
|---|---|---|
| POST | /v1/images/generations | Alias /images/generations. |
| POST | /v1/images/edits | Alias /images/edits. JSON body only. |
Without --image-model both routes answer 501 naming the flag. A request the family rejects before running is 400, and so is an InvalidImageRequest a model raises while running. Every other failure during generation is 500.
Request¶
generations accepts prompt, model, n (1 to 10), size (WxH) or width plus height, steps, seed, guidance, negative_prompt, response_format, and output_format. edits adds image, either one string or a list. Any other field is passed to the model as extra.
widthandheightcome together or not at all, and overridesize.sizedefaults to512x512for generation, and for editing to the first reference image's size or what the family derives from it.- Width and height must be multiples of the family's grid, and the error names the multiple.
response_formataccepts onlyb64_json;urlandpathare400.output_formataccepts onlypng.output_pathandoutput_dirare400, because the server never writes files on behalf of a client.model, when non-empty, must equal the served model id.- Each
imageis a data URL or a URL, read through the same limits as chat images;file://URLs stay inside--media-path. A raw filesystem path is400. Multipart upload is not served.
Response¶
{
"created": 1790000000,
"data": [
{"b64_json": "iVBORw0KGgo...", "mime_type": "image/png",
"width": 512, "height": 512, "seed": 7, "revised_prompt": null}
],
"output_format": "png",
"size": "512x512"
}
RGB and RGBA images are both encoded as they are, so an RGBA result keeps its alpha channel. revised_prompt is always present and is null unless the model rewrote the prompt.