- Python 78.7%
- Shell 16.3%
- Dockerfile 5%
|
All checks were successful
Auto Deploy tti-provider / Check podman State (push) Successful in 0s
Auto Deploy tti-provider / tti-provider-git-prep (push) Successful in 0s
Auto Deploy tti-provider / bld-tti-provider (push) Successful in 4s
Auto Deploy tti-provider / dpy-tti-provider (push) Successful in 17s
|
||
|---|---|---|
| .forgejo/workflows | ||
| tti-db | ||
| tti-provider | ||
| .gitignore | ||
| deploy.sh | ||
| docker-compose.yaml | ||
| LICENSE | ||
| README.md | ||
tti-provider
Text-to-Image Provider
Creates images from a text prompt (optionally with a style, a negative prompt, a size, ...). Requests are queued in a database and
worked off one at a time by a cron runner; the result is picked up by polling /task_details/{id} or sent to a callback URL.
| Model | What it is | Steps | Negative prompt | Memory | Download | License |
|---|---|---|---|---|---|---|
zimage (default) |
Z-Image-Turbo (Tongyi-MAI, 6B) - strong prompt following, text in images | 9 | no (trained without) | ~30 GB | ~33 GB | Apache-2.0 |
juggernaut |
Juggernaut XI v11 (SDXL, RunDiffusion) - photorealistic | 30 | yes | ~14 GB | ~7 GB | CC BY-NC-ND 4.0 (non-commercial) |
juggernautz |
Juggernaut Z (fine-tune of Z-Image Base, RunDiffusion) - Z-Image prompt following and text with the cinematic Juggernaut look (lighting, skin, anatomy) | 35 (CFG 6) | yes | ~30 GB | ~13 GB (+ text encoder of zimage) |
CC BY-NC 4.0 (non-commercial) |
Juggernaut XI v11 is the newest SDXL Juggernaut with open weights on Hugging Face (checked in October 2026). Juggernaut Z is the Z-Image based successor:
it has the same architecture as Z-Image-Turbo, but is not step-distilled, so it needs 35 steps with CFG (two transformer passes per step) instead of 9 -
expect roughly 8-9 times the time of zimage per image. Its text encoder is identical to the one of Z-Image-Turbo and is shared (downloading
juggernautz fetches only that folder of Z-Image-Turbo, ~8 GB, not the whole model).
Weights are downloaded once on the first task of a model (pinned revisions) into the models volume. Only one model is kept in RAM,
switching models reloads (takes a few minutes).
Structure
- A database container to store the pending/ongoing/completed tasks.
- A container with the web API (accepts tasks, shows their state, serves the images) and the cron runner that generates the images.
Setup
Make sure Docker and Docker-Compose are installed.
docker-compose up -d app database --build
Once the containers have started, you can visit http://your-ip:8889/docs to view the documentation.
docker-compose.yaml is meant for development (fixed example passwords, mounts the model cache as a volume); the server uses deploy.sh.
Quick test (curl)
Replace HOST with the server (default port 8889). The request returns the task_id right away:
HOST=http://localhost:8889
# models, sizes, styles
curl -s "$HOST/models"
curl -s "$HOST/styles" | head -c 400
# queue a task -> {"status":200,"result":"Task added to queue. ...","task_id":1}
curl -s -X POST "$HOST/generate/" -H 'Content-Type: application/json' \
-d '{"initial_prompt":"a lighthouse in a storm, oil painting","model":"zimage","image_dimensions":"Widescreen","file_name":"curl test"}'
# same with juggernaut, 2 images, a style, a negative prompt and a fixed seed
curl -s -X POST "$HOST/generate/" -H 'Content-Type: application/json' \
-d '{"initial_prompt":"portrait of an old fisherman","model":"juggernaut","itterations":2,"image_style":"Cinematic","negative_prompt":"hat","seed":42,"image_dimensions":"Portrait"}'
# juggernautz: long prompts and text like zimage, negative prompt like juggernaut
curl -s -X POST "$HOST/generate/" -H 'Content-Type: application/json' \
-d '{"initial_prompt":"a fisherman at dawn holding a wooden sign that reads \"FRESH FISH\", cinematic lighting","model":"juggernautz","negative_prompt":"blurry, plastic skin","seed":42,"image_dimensions":"Portrait"}'
# poll the result (replace 1 with the task_id): done when pit_processing_finished is set, images in download_urls
# (the cron runner picks up tasks within a minute; the first task of a model also downloads its weights)
curl -s "$HOST/task_details/1"
# queue overview
curl -s "$HOST/list_tasks"
| Field | Default | |
|---|---|---|
initial_prompt |
required | |
model |
zimage |
zimage | juggernaut | juggernautz (see /models) |
itterations |
1 |
number of images (1-4); they use the seeds seed, seed+1, ... |
seed |
random | the used seed is returned by /task_details |
image_dimensions |
Square |
Square 1024x1024, Widescreen 1344x768, Portrait 896x1152, Photo 1152x896, or <width>x<height> (256-1536, multiples of 16) |
image_style |
none | one name of /styles (extends the prompt, the style's negative prompt is used by juggernaut and juggernautz) |
negative_prompt |
none | only juggernaut and juggernautz |
callback |
none | URL that receives {"task_id", "download_url", "download_urls", "seed"} via POST, or {"task_id", "error"} |
file_name |
display name |
Invalid values (unknown model/style, bad size, ...) are rejected right away with HTTP 400 and a message. A failed task has error_encountered: 1 and the reason in error_message.
Images that are already finished stay available when a later one of the same task fails.
Notes
Generating on a CPU is slow: expect minutes per image (Z-Image-Turbo: 9 steps with a 6B model, Juggernaut: 30 steps, Juggernaut Z: 35 steps with CFG on the 6B model, the slowest by far). Tasks run strictly one after another; if the runner is killed (out of memory, restart) the task it was working on is marked as failed and the queue continues.