# Kromoss + DMD2 8-step text-to-image This service turns a text prompt into a 1024x1024 PNG. It runs lodestones/Kromoss (a full fine-tune of MOSS-Image-Base, Apache-2.0) with the author's 8-step DMD2 turbo LoRA, through diffusers on one GPU. The text encoder is Qwen3.5-9B, so long, detailed prompts work well. Generation settings are fixed: 1024x1024, 8 steps, guidance (CFG) 1 with no negative prompt, flow-matching shift 5. You send a prompt and, optionally, a seed. Base URL: `{{BASE_URL}}` ## Routes ### `POST /v1/images/generations` OpenAI-style image generation. Returns one image as base64 PNG. ```bash curl -s {{BASE_URL}}/v1/images/generations {{AUTH}} \ -H "Content-Type: application/json" \ -d '{"prompt": "a tabby cat holding a sign that says MOSS", "seed": 42}' \ | python3 -c 'import sys,json,base64; d=json.load(sys.stdin); open("out.png","wb").write(base64.b64decode(d["data"][0]["b64_json"])); print(d["seed"], d["params_used"])' ``` Request fields: - `prompt` (string, required): what to draw. English works best. - `seed` (integer >= 0, optional): the random seed. The same prompt and seed give the same image, byte for byte. Leave it out for a random one; the response's top-level `seed` field says which seed was used, so you can reproduce a result you liked. Also accepted, for stock OpenAI clients: `model` (any string), `n` (must be 1), `response_format` (must be `"b64_json"`), `size` (must be `"1024x1024"`), `user`. Any other field, or a different value for a fixed one (for example `"num_inference_steps": 50` or `"negative_prompt": "..."`), is rejected with `400`. Response: ```json {"created": 1761530000, "model": "kromoss-dmd2", "seed": 42, "elapsed_seconds": 19.0, "data": [{"b64_json": ""}], "params_used": {"size": "1024x1024", "num_inference_steps": 8, "guidance_scale": 1.0, "shift": 5.0, "lora": "8-steps-dmd2-lora"}} ``` The OpenAI Python SDK works too: ```python from openai import OpenAI client = OpenAI(base_url="{{BASE_URL}}/v1", api_key="unused") r = client.images.generate(model="kromoss-dmd2", prompt="a lighthouse at sunset", response_format="b64_json", extra_body={"seed": 7}) ``` ### `GET /v1/config` The fixed settings and the request fields this service accepts. ```bash curl -s {{BASE_URL}}/v1/config {{AUTH}} ``` ### `GET /status` Where the service is in its start-up: `phase` is one of `building`, `downloading`, `starting`, `loading`, `warming`, `ready`, `error`, with `eta_seconds` and, while starting, a `wait_hint`. ```bash curl -s {{BASE_URL}}/status {{AUTH}} ``` ## Timings and concurrency - First start: builds a container image and downloads about 30 GB of weights. After that, loading and a warm-up take a few minutes (budgeted at 420 s). - Each image takes about 19 s on a DGX Spark (GB10). - Requests run one at a time; extra requests wait in line. Send them one by one, or a few in parallel at most, and allow at least 120 s per request in your client timeout. ## Errors - `503` with `Retry-After` while the service is still starting: wait that many seconds and retry. `GET /status` shows progress. - `400`: a field was rejected; the body's `error` says which and why. - `422`: a request field has the wrong type (for example `prompt` missing or empty, `seed` negative). - `5xx` otherwise: retry once, then check `GET /status`.