Skip to content

Repository files navigation

Z-Image-Turbo-Serverless

1. Introduction

This is a serverless application that uses Z-Image-Turbo (via Diffusers) to run a Text-to-Image task on Modal (recommended) or RunPod.

Serverless means that you are only charged for the time you use the application, and you don't need to pay for the idle time, which is very suitable for this kind of application that is not used frequently but needs to respond quickly.

All traffic is encrypted: prompts and result images are Fernet-encrypted between client and server.

Theoretically, this application can be called by any other application. Here we provide a simple Python client for each platform. See Usage below for more details.

Example Results:

Input Prompt: (seed: 42, 1088x1920)

A young woman sitting inside a cafe by a large window on a rainy evening. Long black hair, natural bare face, subtle skin detail, light smile, looking directly at the camera. Soft beige cropped knit top, khaki shorts. Both hands holding a single coffee cup on a bare wooden table. Raindrops on the glass, pedestrians with umbrellas passing outside, blurred street. Photograph, warm interior light, shallow depth of field, face and upper body in sharp focus, neutral warm tones, shot on 35mm film, photorealistic.

Result: (9 steps, around 12 seconds on Modal A100, measured end-to-end: from sending the encrypted request to saving the decrypted image, warm container)

Example Person

Input Prompt: (seed: 52, 1280x720)

A fluffy white cat sitting on a sunlit windowsill among potted green plants, golden hour sunlight streaming through the window, dust motes glowing in the light, cozy room with wooden bookshelves in soft-focus background, shallow depth of field, photorealistic, ultra-detailed fur, warm tones

Result: (9 steps, around 5.5 seconds on Modal A100, measured end-to-end)

Example Cat

2. Dependencies

  • Python >= 3.10, < 3.13
  • uv
  • Modal account (for Modal deployment)
  • Docker + DockerHub + RunPod accounts (for RunPod deployment)
  • Local GPU is necessary for testing but not necessary for deployment.

3. Usage

Input format (see test_input.json; only prompt is required, width/height must be multiples of 16, guidance_scale is fixed at 0.0):

{"input": {"prompt": "A fluffy white cat sitting on a sunlit windowsill", "width": 1280, "height": 720, "steps": 9, "seed": 52, "n_samples": 1}}

1. Modal (Recommended)

Models are baked into the image during build — no Docker required, one-command deploy, GPU snapshot cold starts.

  1. Set up and deploy:
# Install the deploy/client toolchain (lightweight — the GPU stack lives in the Modal image)
uv sync

# Generate an encryption key and save it to .env (required, shared by server and client)
uv run python crypto_util.py
echo "ENCRYPTION_KEY=<your-key>" > .env

# Set Modal token
uv run modal token set --token-id <id> --token-secret <secret>

# Create secrets (HF token for model download during build, encryption key for the endpoint)
uv run modal secret create huggingface-secret HF_TOKEN=<hf_token>
uv run modal secret create encryption-secret ENCRYPTION_KEY=<your-key>

# Deploy (prints the endpoint URL)
uv run modal deploy app.py

The first request after a deploy takes a few minutes (model loading + GPU snapshot creation). After that, cold starts take 20-40 seconds and warm requests a few seconds.

  1. Call the endpoint:
uv run python client_modal.py --url https://<your-endpoint>.modal.run

2. RunPod

Expand for RunPod deployment (Docker build + DockerHub push required)

1. Test on Local Machine

Requires a local GPU. Verify the worker before building and pushing the image.

# Install dependencies incl. the local GPU stack (torch, diffusers, ...)
uv sync --extra local

# Generate an encryption key and save it to .env (required, shared by server and client)
uv run python crypto_util.py
echo "ENCRYPTION_KEY=<your-key>" > .env

# Download models
uv run hf download Tongyi-MAI/Z-Image-Turbo --local-dir models/Z-Image-Turbo

# Edit (or not) config.yaml to customize your inference, e.g., change model repo, quantization, default size, etc.

# Run inference test
uv run python inference_util.py

# Run server.py local test (consumes test_input.json)
ALLOW_PLAINTEXT=1 uv run python server.py

2. Deploy on RunPod

  1. First, make sure you have installed Docker and have accounts on both DockerHub and RunPod.

  2. Then, decide a name for your Docker image, e.g., "your_username/zit:v1" and set it as runpod.docker_image in config.yaml.

  3. Run the following commands to build and push your Docker image to DockerHub.

bash scripts/build.sh
  1. Finally, deploy your application on RunPod to create Template and Endpoint. Set the Model field to the same repo as model.repo_id in config.yaml (models are loaded from RunPod's HuggingFace cache, not baked into the image), and set ENCRYPTION_KEY in the endpoint environment variables.

3. Call the Endpoint

# Set RUNPOD_API_KEY and RUNPOD_ENDPOINT_ID in .env
uv run python client_runpod.py

4. Acknowledgement

Thanks to Tongyi-MAI (Z-Image-Turbo), Hugging Face Diffusers, Modal, and RunPod.

About

Serverless Z-Image-Turbo text-to-image endpoint for Modal and RunPod, with encrypted prompts and images

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages