A text-to-image diffusion inference engine. Tested on Strix Halo and Strix Point.
Loads one model at a time and generates images from text prompts. Available as a CLI tool, an HTTP API (with a simple web UI).
Yes, and ComfyUI will always be better than this for the advanced user. This is good for the following scenarios:
- You got a Strix Halo (congratulations!) and want to quickly start generating images
- You don't want to care about "workflows"
- You want to add an easy but powerful image generation endpoint for usage through other software
- You want something targeted at your machine. Our goal is to optimize this for Strix Halo as much as possible.
This project incorporates code from:
plus smaller snippets from other sources or transitively inherited through the above codebases.
The steps below are copy-pasteable end to end. They take you from a fresh clone to a generated image.
uv is the only prerequisite — it provides
the Python interpreter and installs every dependency:
curl -LsSf https://astral.sh/uv/install.sh | sh
source ~/.bashrcgit clone https://github.com/lemonade-sdk/thenoise.git
cd thenoisethenoise.sh creates the .venv, installs the ROCm build of PyTorch, and
installs the project in editable mode. Running it with --help does all of that
without needing any model weights yet:
./thenoise.sh --helpThis is the slow step — it downloads several GB of ROCm PyTorch wheels.
Subsequent runs skip the torch install (detected via import torch).
By default the script autodetects the GPU's architecture. Override with the
GFX_ARCH environment variable, which applies to every ./thenoise.sh
invocation. Supported targets are gfx1150, gfx1151, and gfx1152:
GFX_ARCH=gfx1151 ./thenoise.sh --helpThe download scripts need huggingface_hub, which is a scripts extra and is
not installed by thenoise.sh (it only installs runtime deps). Install it
once, then use the venv's Python (a bare system python will not work):
uv pip install -e ".[scripts]"
.venv/bin/python scripts/download_anima.py --out ./models/anima --variant turbo-v1.0Anima is the smaller of the two original supported models (~5.4 GB total), so it is the quickest way to get a first image. See Supported Models for Krea 2 (larger, higher quality) and Z-Image-Turbo (distilled 8-step).
./thenoise.sh generate \
--dit ./models/anima/split_files/diffusion_models/anima-turbo-v1.0.safetensors \
--vae ./models/anima/split_files/vae/qwen_image_vae.safetensors \
--text-encoder ./models/anima/split_files/text_encoders/qwen_3_06b_base.safetensors \
--prompt "a fox walking in the snow" --steps 8 --guidance-scale 1 \
--out fox.pngThe first generation is slow because the DiT is compiled with torch.compile —
see Performance. To serve the same model over HTTP with a web UI
instead, use serve (see CLI).
For machines without a dev toolchain, CI publishes portable bundles — one
directory with a standalone CPython, PyTorch ROCm, all dependencies, thenoise
itself, and a bundled clang (so torch.compile/Triton JIT works with no system
gcc). No installation, sudo, or Python needed on the target machine.
- Built per GPU target (
gfx1151,gfx1150,gfx1152) — see.github/workflows/build-thenoise-rocm.ymlandscripts/build_portable.sh. - The
gfx1151bundle is GPU-qualified (a real Anima generation) before release.
Download the release assets for your GPU and run:
# extract (split archives come as .partNN-of-MM.tar.gz — concatenate them first:
# cat *.part*.tar.gz | tar -xz
# single archive: tar -xzf <tag>.tar.gz
./bin/thenoise generate \
--dit ./models/anima/split_files/diffusion_models/anima-turbo-v1.0.safetensors \
--vae ./models/anima/split_files/vae/qwen_image_vae.safetensors \
--text-encoder ./models/anima/split_files/text_encoders/qwen_3_06b_base.safetensors \
--prompt "a fox walking in the snow" --steps 8 --guidance-scale 1thenoise.sh installs the runtime dependencies only. To run the test suite,
also install the dev extras:
uv pip install -e ".[dev]"
.venv/bin/python -m pytest tests/ -qTo use the model download scripts, install the scripts extra instead (or in
addition):
uv pip install -e ".[scripts]"First-run compilation: the DiT model is compiled with torch.compile on load. The first
generation will be noticeably slower while the inductor traces and compiles kernels.
You will also see some warnings on the console, these are normal.
All subsequent generations use the cached compiled code and run at full speed.
Compilation is transparent — no configuration needed.
If the first generation aborts with an InductorError wrapping a gcc failure
that references -I/usr/include/python3.13, the venv was built against a
system Python 3.13 whose development headers are not installed. Triton
JIT-compiles its HIP driver module at runtime and needs Python.h.
thenoise.sh avoids this by passing --managed-python, so uv uses its own
standalone CPython build (which always ships headers). If you have a venv
created before that fix, rebuild it:
rm -rf .venv
./thenoise.sh --helpInstalling your distro's python3.13-dev package also works, if you would
rather keep the system interpreter.
Anima, Krea 2, and Z-Image-Turbo are supported. New models will be added. PRs adding model support are welcome.
All download commands use .venv/bin/python and need the scripts extra
installed (uv pip install -e ".[scripts]"), because huggingface_hub lives
in the project venv created by Setup — a bare python will not work.
| Model | Download size | Notes |
|---|---|---|
| Anima | ~5.4 GB | 2B params; fastest to download and run |
| Krea 2 | ~35 GB | Higher quality; much larger text encoder and DiT |
| Z-Image-Turbo | ~21 GB | Distilled 8-step S3-DiT; Flux VAE + Qwen3 caption encoder |
| Z-Image | ~21 GB | Non-distilled version of Z-Image-Turob |
Download:
.venv/bin/python scripts/download_krea2.py --out ./models/krea2This fetches the bf16 Turbo DiT (~26 GB), the VAE (~0.25 GB), and the Qwen3-VL
text encoder (~8.9 GB). Add --include-raw for the non-turbo DiT (another
~26 GB).
Download — the --variant you pick becomes part of the DiT filename, so use the
same value in your --dit path:
.venv/bin/python scripts/download_anima.py --out ./models/anima --variant turbo-v1.0Available variants include turbo-v1.0 (fewest steps), aesthetic-v1.1, and
base-v1.0.
.venv/bin/python scripts/download_zimage.py --out ./models/zimageThis fetches the single-file bf16 Turbo DiT (~12 GB), the Flux VAE (ae.safetensors),
and the Qwen3-4B text encoder (qwen_3_4b.safetensors, ~8 GB).
./thenoise.sh generate \
--dit ./models/zimage/split_files/diffusion_models/z_image_turbo_bf16.safetensors \
--vae ./models/zimage/split_files/vae/ae.safetensors \
--text-encoder ./models/zimage/split_files/text_encoders/qwen_3_4b.safetensors \
--prompt "a fox walking in the snow" \
--out /tmp/zimage.pngTheNoise can be used in three ways:
- CLI — generate a single image from the command line
- HTTP server — serve a model over HTTP with a JSON API
- Web UI — a very basic browser interface served at
http://localhost:8000/when running the server
The model type is auto-detected from the DiT checkpoint — no need to specify which model you are using.
Anima (matches the model downloaded in Setup):
./thenoise.sh serve \
--dit ./models/anima/split_files/diffusion_models/anima-turbo-v1.0.safetensors \
--vae ./models/anima/split_files/vae/qwen_image_vae.safetensors \
--text-encoder ./models/anima/split_files/text_encoders/qwen_3_06b_base.safetensors \
--host 127.0.0.1 --port 8000Krea 2:
./thenoise.sh serve \
--dit ./models/krea2/diffusion_models/krea2_turbo_bf16.safetensors \
--vae ./models/krea2/vae/qwen_image_vae.safetensors \
--text-encoder ./models/krea2/text_encoders/qwen3vl_4b_bf16.safetensors \
--host 127.0.0.1 --port 8000./thenoise.sh serve \
--dit ./models/zimage/split_files/diffusion_models/z_image_turbo_bf16.safetensors \
--vae ./models/zimage/split_files/vae/ae.safetensors \
--text-encoder ./models/zimage/split_files/text_encoders/qwen_3_4b.safetensors \
--host 127.0.0.1 --port 8000Then open http://localhost:8000/ for the web UI.
./thenoise.sh generate \
--dit ./models/anima/split_files/diffusion_models/anima-turbo-v1.0.safetensors \
--vae ./models/anima/split_files/vae/qwen_image_vae.safetensors \
--text-encoder ./models/anima/split_files/text_encoders/qwen_3_06b_base.safetensors \
--prompt "a fox walking in the snow" --steps 8 --guidance-scale 1 \
--out /tmp/fox.pngPlace .safetensors LoRA files in a directory and point --lora-dir at it (both serve and generate). Then apply LoRAs per-request:
./thenoise.sh generate \
--dit ... --vae ... --text-encoder ... \
--lora-dir ./models/loras \
--prompt "a cyberpunk cityscape" \
--lora "style-cyberpunk:0.8" \
--lora "sub/detail-booster:0.5" \
--out /tmp/city.pngLoRA format is filename:weight — the .safetensors extension is appended automatically. Omit :weight to use the default of 1.0. LoRAs are switched in-memory without reloading the base model.
| Method | Path | Description |
|---|---|---|
GET |
/ |
Web UI |
GET |
/health |
Server status and loaded model |
GET |
/lora |
List available LoRA names |
GET |
/upscalers |
List available pixel upscaler names |
POST |
/text2image |
Generate an image |
All fields except prompt are optional. Omitted fields use the loaded model's defaults.
| Field | Type | Default | Description |
|---|---|---|---|
prompt |
string |
(required) | Text prompt |
negative_prompt |
string |
"" |
Negative prompt |
width |
int |
model default | Output width in pixels |
height |
int |
model default | Output height in pixels |
steps |
int |
model default | Number of denoising steps |
guidance_scale |
float |
model default | CFG scale (≤ 1.0 disables CFG) |
seed |
int |
random | Random seed (-1 for random) |
upscale |
bool |
false |
2× latent-space upscale with refine denoise |
upscale_factor |
float |
1.0 |
Upscale factor (max depends on the pixel upscaler scale) |
upscale_type |
string |
refined |
refined (latent 2x + refiner) or no-refiner (pixel upscaler only) |
pixel_upscaler |
string |
null |
Pixel upscaler name (no .safetensors suffix) from --upscaler-dir |
sampler |
string |
er_sde |
Denoising solver: euler or er_sde |
qwen_vae_enhance |
bool |
false |
Nyquist notch post-filter (removes 2px grid artifacts) |
film_grain |
float |
0.0 |
Film grain strength, 0.0–10.0 |
sharpening |
float |
0.0 |
RCAS sharpening strength, 0.0–1.0 |
lora_specs |
string[] |
null |
LoRA specs, e.g. ["style:0.8"] |
Returns a PNG image directly (Content-Type: image/png).
curl -s localhost:8000/text2image \
-H 'content-type: application/json' \
-d '{"prompt":"a fox walking in the snow","steps":8}' \
--output /tmp/fox.pngIf no model is loaded, /text2image returns HTTP 503.
| Flag | Required | Default | Description |
|---|---|---|---|
--dit |
yes | — | Path to the DiT checkpoint (.safetensors) |
--vae |
yes | — | Path to the VAE checkpoint (.safetensors) |
--text-encoder |
yes | — | Path to the text encoder checkpoint (.safetensors) |
--lora-dir |
no | — | Directory containing LoRA .safetensors files |
--device |
no | cuda |
Inference device (ROCm aliases cuda → hip) |
| Flag | Default | Description |
|---|---|---|
--host |
127.0.0.1 |
Bind host |
--port |
8000 |
Bind port |
--upscaler-dir |
— | Directory containing pixel upscaler .safetensors files (e.g. Real-ESRGAN); selected per-request via pixel_upscaler |
| Flag | Required | Default | Description |
|---|---|---|---|
--prompt |
yes | — | Text prompt |
--negative-prompt |
no | "" |
Negative prompt |
--width |
no | model default | Output width |
--height |
no | model default | Output height |
--steps |
no | model default | Denoising steps |
--guidance-scale |
no | model default | CFG scale |
--seed |
no | random | Random seed |
--out |
no | out.png |
Output file path |
--lora |
no | — | LoRA to apply (repeatable, format: file:weight) |
--pixel-upscaler |
no | — | Full path to the pixel upscaler model (one-shot; e.g. a Real-ESRGAN .safetensors) |
--upscale-type |
no | refined |
refined or no-refiner |
--upscale |
no | off | 2× latent upscale with refine denoise |
--sampler |
no | er_sde |
Solver: euler or er_sde |
--qwen-vae-enhance |
no | off | Nyquist notch post-filter |
--film-grain |
no | 0.0 |
Film grain strength (0.0–10.0) |
--sharpening |
no | 0.0 |
RCAS sharpening strength (0.0–1.0) |