|
Download API_SPEC.md from mando2222/moss-image: direct link, hf CLI and curl.
- Browser
- Download file 7.82 kB
-
https://huggingface.co/mando2222/moss-image/resolve/cccfdf730b310c2d7745840e04e0930bae987f73/API_SPEC.md
- Command line
-
hf download hf://mando2222/moss-image@cccfdf730b310c2d7745840e04e0930bae987f73/API_SPEC.md
-
curl -L -o API_SPEC.md https://huggingface.co/mando2222/moss-image/resolve/cccfdf730b310c2d7745840e04e0930bae987f73/API_SPEC.md
7.82 kB
| # MOSS-Image API spec (node4) | |
| HTTP image-generation API for the MOSS-Image TTNN bundle. Diffusion model β **no tokens, no | |
| KV cache, no streaming**; requests are image jobs. | |
| ## Base URL | |
| - From node4 itself: `http://127.0.0.1:8000` | |
| - From other boxes on the LAN: `http://192.168.50.97:8000` (node4), or `http://node4:8000` if | |
| your `/etc/hosts`/DNS resolves it. | |
| - The server binds `0.0.0.0:$PORT` (default **8000**). Open that port in any firewall between | |
| boxes. No auth (intended for a trusted LAN); put it behind a proxy if you need auth. | |
| > Status note: the API shape below is identical whether it is served by the device bundle | |
| > (TTNN on the Blackhole card) or the CPU reference β same endpoints, same schemas. Only speed | |
| > differs. | |
| ## Endpoints | |
| ### `GET /health` | |
| Liveness + which model/mesh is loaded, and the capability contract. | |
| ```json | |
| { "status": "ok", "model": "OpenMOSS-Team/MOSS-Image-Base", | |
| "mesh": "P150", "mesh_shape": "1x1", "vae_device": true, | |
| "pipeline_loaded": true, "kind": "tt-dit-server", | |
| "progress_reporting": true, "job_persistence": true, | |
| "private_ephemeral_jobs": true, "private_result_ttl_s": 900 } | |
| ``` | |
| - `vae_device` β `true` when the VAE decodes on the device (pure `ttnn`, the default; | |
| validated vs host fp32 to PCC β₯0.9999 at all resolutions). Force host with `MOSS_VAE_DEVICE=0`. | |
| - `mesh_shape` β DiT topology (`MOSS_MESH`): `1x1` single-chip (default), `1x2`/`1x4` mesh. | |
| - `private_ephemeral_jobs` / `private_result_ttl_s` β see **Private jobs** below. | |
| ### Private jobs (default for new `POST /generate`) | |
| Send an `X-Moss-Job-Token` header on `POST /generate` (or let the server mint one and return it | |
| as `job_token`). The job is then token-scoped: **not** listed in `GET /jobs`, **never** written | |
| to disk (result held in memory only), and reaped after a **900 s** TTL. The same token is | |
| required on `GET /jobs/{id}`, `GET /images/{id}.png`, and `DELETE /jobs/{id}`; a missing/wrong | |
| token returns **404**. Limits: max 8 private jobs, 64 MiB encoded result each. Legacy disk-backed | |
| jobs (created without a token) remain listable and survive restarts. | |
| ### `GET /v1/models` | |
| OpenAI-style model list. | |
| ```json | |
| { "object": "list", "data": [ | |
| { "id": "OpenMOSS-Team/MOSS-Image-Base", "object": "model", "owned_by": "openmoss" } ] } | |
| ``` | |
| ### `POST /generate` β submit an async job (recommended) | |
| Request body (JSON): | |
| | field | type | default | notes | | |
| | --- | --- | --- | --- | | |
| | `prompt` | string | β | **required** | | |
| | `height` | int | 1024 | 256β2048, multiple of 16 | | |
| | `width` | int | 1024 | 256β2048, multiple of 16 | | |
| | `num_inference_steps` | int | 50 | 1β200; β₯28 for quality | | |
| | `guidance_scale` | float | 3.0 | 0β20; CFG scale (1.0 disables CFG) | | |
| | `negative_prompt` | string | `""` | used when `guidance_scale != 1` | | |
| | `seed` | int\|null | null | reproducibility (CPU RNG) | | |
| | `max_sequence_length` | int | 4096 | 1β4096; max prompt tokens | | |
| | `shift` | float\|null | nullβ5.0 | 1β10; flow-match scheduler shift | | |
| | `uncond_skip_layers` | list[int] | `[22]` | DiT layers skipped on the CFG negative branch; `[]` disables | | |
| | `slg_layers` | list[int]\|null | null | skip-layer-guidance layers; null/`[]` disables the extra forward | | |
| | `slg_scale` | float | 0.0 | 0β20; `prediction += slg_scale*(cond β cond_skipped)` | | |
| | `slg_start` | float | 0.0 | 0β1; SLG/skip window start (fraction of steps) | | |
| | `slg_stop` | float | 1.0 | 0β1; SLG/skip window stop (fraction of steps) | | |
| The advanced knobs mirror `reference/pipeline_moss_image.py __call__`. Call **`GET /v1/parameters`** | |
| (alias `GET /config`) for this schema with ranges at runtime. | |
| Response (every new job is private by default β keep the `job_token`): | |
| ```json | |
| { "job_id": "ff70ee2b28e4", "status": "queued", "poll": "/jobs/ff70ee2b28e4", | |
| "job_token": "<43β128 url-safe chars>", "storage": "memory", "private": true, "result_ttl_s": 900 } | |
| ``` | |
| Jobs are serialized through one worker (one model / one device); submitting many just queues them. | |
| ### `GET /jobs/{job_id}` β poll status | |
| ```json | |
| { "job_id": "ff70ee2b28e4", "status": "done", | |
| "request": { ... }, "image_url": "/images/ff70ee2b28e4.png" } | |
| ``` | |
| `status` β `queued` | `running` | `done` | `error`. On `error`, an `error` field carries the message. | |
| ### `GET /images/{job_id}.png` β fetch the result | |
| Returns `image/png` once the job is `done` (404 until then). Finished images are | |
| saved to disk (`$MOSS_OUTPUT_DIR`, default `./moss_outputs`) and freed from memory, so | |
| this is served from the saved file after the job completes. | |
| ### `GET /jobs` β list jobs | |
| ```json | |
| { "jobs": [ { "job_id": "ff70ee2b28e4", "status": "done", | |
| "file_path": "/.../moss_outputs/ff70ee2b28e4.png", "prompt": "a red fox in snow" } ] } | |
| ``` | |
| ### `DELETE /jobs/{job_id}` β delete a job + its saved image | |
| Drops the job from memory and removes its PNG from disk. | |
| ```json | |
| { "deleted": true, "job_id": "ff70ee2b28e4", "file_removed": true } | |
| ``` | |
| ### `POST /generate/sync` β blocking, returns PNG directly | |
| Same body as `/generate`; responds with `image/png`. Convenient but holds the connection for the | |
| full generation (minutes at 1024Β²/50) β prefer the async flow for anything non-trivial. | |
| ### `POST /v1/images/generations` β OpenAI-compatible (blocking) | |
| Request (superset of the OpenAI schema β the full control set is accepted here too): | |
| ```json | |
| { "prompt": "a red fox in snow", "n": 1, "size": "1024x1024", "seed": 42, | |
| "width": 1024, "height": 1024, "num_inference_steps": 50, "guidance_scale": 3.0, | |
| "negative_prompt": "", "shift": 5.0, "slg_layers": [24], "slg_scale": 3.0 } | |
| ``` | |
| `size` is `WIDTHxHEIGHT`; explicit `width`+`height` override it. All `/generate` advanced knobs | |
| (`max_sequence_length`, `shift`, `uncond_skip_layers`, `slg_*`) are accepted. Response (base64 | |
| PNGs, OpenAI Images shape): | |
| ```json | |
| { "created": 1760000000, "data": [ { "b64_json": "<base64 png>" } ] } | |
| ``` | |
| ### `GET /v1/parameters` (alias `GET /config`) β controllable-parameter schema | |
| A UI reads this to render generation controls. Each entry has `name`, `type`, `default`, and | |
| `min`/`max`/`multiple_of`/`max_length` where applicable. | |
| ```json | |
| { "model": "OpenMOSS-Team/MOSS-Image-Base", | |
| "endpoints": ["/generate", "/v1/images/generations"], | |
| "parameters": [ | |
| { "name": "num_inference_steps", "type": "int", "default": 50, "min": 1, "max": 200 }, | |
| { "name": "guidance_scale", "type": "float", "default": 3.0, "min": 0.0, "max": 20.0 }, | |
| { "name": "shift", "type": "float|null", "default": 5.0, "min": 1.0, "max": 10.0 }, | |
| { "name": "width", "type": "int", "default": 1024, "min": 256, "max": 2048, "multiple_of": 16 } | |
| /* β¦height, seed, negative_prompt, max_sequence_length, uncond_skip_layers, slg_* β¦ */ | |
| ] } | |
| ``` | |
| ## Example (async) | |
| ```bash | |
| HOST=http://192.168.50.97:8000 | |
| JID=$(curl -s -X POST $HOST/generate -H 'content-type: application/json' \ | |
| -d '{"prompt":"a cozy bookshop, warm light, a cat asleep on a chair","height":1024,"width":1024,"num_inference_steps":50,"seed":7}' \ | |
| | python3 -c 'import sys,json;print(json.load(sys.stdin)["job_id"])') | |
| until curl -s $HOST/jobs/$JID | grep -q '"status":"done"'; do sleep 5; done | |
| curl -s $HOST/images/$JID.png -o out.png | |
| ``` | |
| ## Notes for client/agent builders | |
| - **Latency** (single p150, device backend): ~12β25 s for 256Β²/4-step warm; ~235 s for | |
| 1024Β²/50-step. Set generous client timeouts; prefer `/generate` + poll over `/generate/sync`. | |
| - **Concurrency:** requests queue (single device). Don't fan out expecting parallelism. | |
| - **Resolution:** `height`/`width` must be multiples of 16. | |
| - **Determinism:** pass `seed` for reproducible images. | |
| - **Errors:** poll `/jobs/{id}` and check `status == "error"` + the `error` string; HTTP 4xx for | |
| bad input (e.g. malformed `size`), 404 for an unknown job or an image not yet ready. | |