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.
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 targets gfx1151 (Strix Halo). Override with the
GFX_ARCH environment variable, which applies to every ./thenoise.sh
invocation:
GFX_ARCH=gfx1150 ./thenoise.sh --helpUse the venv's Python — the download scripts need huggingface_hub, which is
installed inside .venv, not on your system Python:
.venv/bin/python scripts/download_anima.py --out ./models/anima --variant turbo-v1.0Anima is the smaller of the two supported models (~5.4 GB total), so it is the quickest way to get a first image. See Supported Models for Krea 2, which is larger (~35 GB) but higher quality.
./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).
thenoise.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/ -qFirst-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.
At the moment, only Krea 2 and Anima are supported. New models will be added. PRs adding model support are welcome.
All download commands use .venv/bin/python, 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 |
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. Downloading --variant aesthetic-v1.1 produces
anima-aesthetic-v1.1.safetensors, not anima-turbo-v1.0.safetensors.
TheNoise 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 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 |
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 |
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 |
| 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) |
--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) |