Z Image LoRA Trainer
Playground
Try it on WaveSpeedAI!Z-Image-LoRA-Trainer – train custom image LoRA models from your own dataset, with zip uploads, auto-tuned defaults and fast iteration for brand, character or IP looks. Ready-to-use REST inference API, best performance, no coldstarts, affordable pricing.
Features
Z-Image LoRA Trainer is a high-performance custom model training service for the Z-Image-Turbo text-to-image generation models. It allows you to train lightweight LoRA (Low-Rank Adaptation) adapters for personalized styles, characters, and concepts, while preserving the fast and high-quality generation properties of Z-Image.
Training Architecture
The trainer is designed around Z-Image’s efficient diffusion architecture and its Turbo distilled variants, and produces one or more specialized LoRA adapters depending on your configuration:
-
Base LoRA adapter Trains on the core Z-Image representation to capture your target style, character, or object, while keeping the base model frozen and stable.
-
Turbo-aware fine-tuning (optional) When used with Z-Image-Turbo, the trainer applies Turbo-compatible optimization settings (step-aware learning rate, safe rank and scaling) to maintain high image quality even at low sampling steps.
This architecture ensures that your LoRA:
- Remains compact and easy to share
- Is plug-and-play with supported UIs and pipelines (e.g. ComfyUI / AI Toolkit)
- Preserves the speed and efficiency of Z-Image / Z-Image-Turbo
Training Process
-
Data Upload Prepare and upload a ZIP file containing your training images and, optionally, captions or prompts.
-
Automatic Preprocessing The trainer automatically:
- Validates and filters your dataset
- Resizes and normalizes images for Z-Image
- Aligns captions / prompts (or auto-generates basic captions if enabled)
- LoRA Training The system runs a tailored LoRA optimization loop for Z-Image:
- Freezes the base model weights
- Trains only the low-rank adapter layers
- Applies Turbo-safe settings when targeting Z-Image-Turbo
- Model Export After training completes, you receive:
- A LoRA adapter file compatible with Z-Image / Z-Image-Turbo
- Recommended loading settings (weight scale, steps, and sampling tips) for image generation
Price
- You pay $1.25 for every 1,000 training steps, billed proportionally to the total number of steps in your job.
Examples
| Training steps | Price (USD) |
|---|---|
| 1,000 | $1.25 |
| 2,000 | $2.50 |
| 5,000 | $6.25 |
| 10,000 | $12.50 |
Try more trainers
-
Wan 2.2 Image LoRA Trainer - High-performance LoRA trainer for the Wan 2.2 image model, ideal for custom styles and characters that integrate smoothly into the Wan video/image ecosystem.
-
Qwen Image LoRA Trainer - Built on the Qwen image model with strong multi-language prompt support and rich semantic understanding, great for text-sensitive image customization.
-
Flux Dev LoRA Trainer - LoRA trainer tailored for the Flux Dev model, focusing on high-fidelity, creative visuals and experimentation with new artistic styles.
Guidance
Authentication
For authentication details, please refer to the Authentication Guide.
API Endpoints
Submit Task & Query Result
set -euo pipefail
export WAVESPEED_API_KEY="your-api-key"
REQUEST_BODY=$(cat <<'JSON'
{
"data": "https://github.com/mdn/interactive-examples/archive/refs/heads/main.zip",
"steps": 1000,
"learning_rate": 0.0001,
"lora_rank": 16
}
JSON
)
# 1. Submit the prediction.
SUBMIT_RESPONSE=$(curl --silent --show-error --fail-with-body \
-X POST "https://api.wavespeed.ai/api/v3/wavespeed-ai/z-image-lora-trainer" \
-H "Authorization: Bearer ${WAVESPEED_API_KEY}" \
-H "Content-Type: application/json" \
-d "${REQUEST_BODY}")
TASK=$(printf '%s' "${SUBMIT_RESPONSE}" | jq 'if type == "object" and has("data") then .data else . end')
PREDICTION_ID=$(printf '%s' "${TASK}" | jq -r '.id // empty')
if [ -z "${PREDICTION_ID}" ]; then
printf 'Submission response did not contain a prediction id
' >&2
exit 1
fi
RESULT_URL=$(printf '%s' "${TASK}" | jq -r '.urls.get // empty')
if [ -z "${RESULT_URL}" ]; then RESULT_URL="https://api.wavespeed.ai/api/v3/predictions/${PREDICTION_ID}/result"; fi
# 2. Poll until the prediction finishes.
while true; do
RESPONSE=$(curl --silent --show-error --fail-with-body \
"${RESULT_URL}" \
-H "Authorization: Bearer ${WAVESPEED_API_KEY}")
RESULT=$(printf '%s' "${RESPONSE}" | jq 'if type == "object" and has("data") then .data else . end')
STATUS=$(printf '%s' "${RESULT}" | jq -r '.status // empty')
case "${STATUS}" in
completed) printf '%s\n' "${RESULT}" | jq '.outputs'; break ;;
failed|cancelled|timeout) printf '%s\n' "${RESULT}" | jq . >&2; exit 1 ;;
created|processing) sleep 2 ;;
*) printf 'Unexpected status: %s
' "${STATUS}" >&2; exit 1 ;;
esac
doneParameters
Task Submission Parameters
Request Parameters
| Parameter | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
| data | string | Yes | - | - | URL to zip archive with images. Try to use at least 4 images in general the more the better. In addition to images the archive can contain text files with captions. Each text file should have the same name as the image file it corresponds to. |
| trigger_word | string | No | - | - | Optional trigger word. If a caption file exists, it is prepended when not already present. If no caption file exists and trigger_word is non-empty, a caption containing only the trigger word is created. Leave empty to enable no-caption training. |
| steps | integer | No | 1000 | 500 ~ 10000 | Number of steps to train the LoRA on. |
| learning_rate | number | No | 0.0001 | 0 ~ 1 | - |
| lora_rank | integer | No | 16 | 1 ~ 64 | - |
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| code | integer | HTTP status code (e.g., 200 for success) |
| message | string | Status message (e.g., “success”) |
| data.id | string | Unique identifier for the prediction, Task Id |
| data.model | string | Model ID used for the prediction |
| data.outputs | array | Output values, usually URL strings; some models return text strings or structured result objects (empty when status is not completed) |
| data.urls | object | Object containing related API endpoints |
| data.urls.get | string | URL to retrieve the prediction result |
| data.status | string | Status of the task: created, processing, completed, or failed |
| data.created_at | string | ISO timestamp of when the request was created (e.g., “2023-04-01T12:34:56.789Z”) |
| data.error | string | Error message (empty if no error occurred) |
| data.timings | object | Object containing timing details |
| data.timings.inference | integer | Inference time in milliseconds |
Result Request Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| id | string | Yes | - | Task ID |
Result Response Parameters
| Parameter | Type | Description |
|---|---|---|
| code | integer | HTTP status code (e.g., 200 for success) |
| message | string | Status message (e.g., “success”) |
| data | object | The prediction data object containing all details |
| data.id | string | Unique identifier for the prediction |
| data.model | string | Model ID used for the prediction |
| data.outputs | array<string | object> | Array of generated outputs (empty when status is not completed). Items are usually URL strings, but may be text strings or structured result objects, depending on the model. |
| data.urls | object | Object containing related API endpoints |
| data.urls.get | string | URL to poll for the prediction result |
| data.status | string | Status: created, processing, completed, or failed |
| data.created_at | string | ISO timestamp of when the request was created |
| data.error | string | Error message (empty if no error occurred) |
| data.timings | object | Object containing timing details |
| data.timings.inference | integer | Inference time in milliseconds |