The 1bit engine runs inside Lemonade, and its
onebit recipe passes Lemonade's own LLM test suite on HRX: 29 of 29 tests run, all pass. Lemonade
is the server users talk to, with its own catalog, downloads, router and UI. For the models it
serves with 1bit, it runs the engine as a backend, the same way it runs llama-server. For a GGUF
it starts the engine's HRX llama-server directly, one HTTP hop
(#475, below); for
the other routes it starts 1bit serve (serve.md), waits for /health, and forwards
OpenAI requests to it. The engine exposes nothing but that OpenAI-compatible API.
Recovery stays Lemonade's: when a backend hangs, 1bit serve answers /health with 503 and, once
a request has had no progress for --watchdog seconds, kills its backend and exits non-zero
(serve.md, "When a backend hangs"). Lemonade's BackendWatchdog
then loads the model again.
Step 1 first went the other way. 1bit lemonade ran Lemonade v11.9.0's server
core inside the 1bit process, and this repository carried Lemonade local
recipes for the engine (onebit, mlx, zinc, the hrx_device option).
A review1 pointed out that the engine should be embedded into Lemonade, not
the reverse. So on 2026-09-23:
third_party/lemonadeand every local delta were removed. The engine no longer builds Lemonade's code or its fetched libraries.1bit servetook over what the local recipes did, for every device: NPU, Vulkan, HRX, ZINC and MLX.
One recipe in Lemonade runs the engine, onebit, in the same shape as its
llama-server recipe:
1bit serve -m <model> --port <p> [--device ...] [--ctx-size N] [--alias <name>]
Lemonade downloads and resolves GGUF checkpoints as for llamacpp, and its
backend selector picks the device (hrx or npu; unset,
the recipe sends --device auto). Replies already carry Lemonade's model name (--alias),
so requests pass through unchanged.
One hop for GGUF models (fork branch 1bit/one-hop). For a .gguf, the recipe first runs that
command with --print-backend: serve makes its load-time checks (architecture, memory, recipes)
and prints the llama-server it would start, and Lemonade starts that llama-server itself and
talks to it directly, as it does for llamacpp. A request then crosses one HTTP hop instead of
two. NPU model directories, DwarfStar, --pm and --laya still run through 1bit serve
(serve exits 5 for them), and LEMONADE_ONEBIT_ONE_HOP=0 keeps serve in the path for every model
(serve.md, "One hop from Lemonade").
The recipe lives in our Lemonade fork,
1bit-MONSTER/lemonade: upstream
Lemonade plus the onebit backend (fork PR #1). Build lemond from the fork and
put 1bit on PATH (or set $LEMONADE_ONEBIT_BIN).
The engine pins the Lemonade it is tested with: third_party/lemonade is the fork at a
fixed commit. It is never linked into the engine. scripts/build-lemonade.sh builds
lemond and the lemonade CLI from it:
scripts/build-lemonade.sh ~/.cache/lemonade-pin
LEMONADE_ONEBIT_BIN=$PWD/build/1bit ~/.cache/lemonade-pin/bin/lemond.github/workflows/bump-lemonade.yml opens a PR here when the fork's main moves (after
the upstream release sync below). Before merging, rebuild and rerun the LLM suite on Strix Halo.
On Strix Halo the recipe passes Lemonade's own LLM test suite
(test/server_llm.py --wrapped-server onebit) on HRX (the checklist below has the counts;
Vulkan passed too before RFC #213 stage 3 removed it). It is not proposed upstream yet: the plan is to embed the engine fully
in the fork first, then propose it upstream. The fork follows upstream's releases:
.github/workflows/sync-lemonade-fork.yml checks daily and merges upstream's latest
release tag (never a pre-release or main), so each engine release carries the Lemonade
release current when it was built. It
pushes only a clean merge that still registers onebit; otherwise it opens a PR
in the fork that lists the conflicts. It also keeps the fork's own copies of
upstream's workflows disabled. Lemonade asks for an RFC
before a new backend.
What "fully embedded" still needs, measured on Strix Halo. The runs use the pinned fork
(third_party/lemonade), the engine from main, and Lemonade's LLM suite
(test/server_llm.py --wrapped-server onebit --backend <device>).
| device | 2026-09-25, start | now |
|---|---|---|
| HRX | 19 / 31 | 29 / 29 run, all pass (2 skipped; release pre-check 2026-10-02, from the packaged tarballs) |
| NPU | 3 / 31 | in progress (npu.md); the suite's small test models are GGUF |
| Vulkan (removed in RFC #213 stage 3) | 19 / 31 | 29 / 29 run, all pass, before its removal |
Declare what already works.Done (fork #6). The recipe now declares tool calls,stop, async, the Responses API, slots, tokenize, embeddings and reranking.Test on the device asked for.Done (fork #6). The harness passes--backendtoonebit.Forward the rest of llama-server's API.Done (#69).1bit serveforwards/v1/responses,/tokenize,/slots,/propsand/metricson the llama-server devices.Embedding and reranking models.Done (#70, fork #6).1bit serve --embedding/--reranking, and the recipe serves those modes.Reranking on HRX.Done. jina-reranker-v1-tiny reranks on HRX (the suite's three rerank tests return the same top 3 as on Vulkan), and1bit serve --rerankruns on HRX (#281).- The NPU from Lemonade. The path works end to end: Lemonade downloads the Q4NX checkpoint
repo, the recipe hands
1bit servethe directory, and the engine runs it on the NPU (the experimental Qwen3.6-35B-A3B route builds with a closed add-on only, npu.md). Still open:- the NPU engine's kernels built from source, verified but not merged (npu.md);
: done (#73), the NPU route splits the thinking out as llama-server does;reasoning_contentmodels in our own Hugging Face repos: the 35B is1bit-MONSTER/Qwen3.6-35B-A3B-NPU(fork #8). (engine + fork)
- Beyond the LLM suite:
- the Laya router.
echo and generation parameters are skipped, because Lemonade's own llamacpp recipe
declares neither.
On Ubuntu 26.04 Lemonade installs from its PPA, and that lemond (2026.42.1~26.04) is upstream's,
with no onebit recipe. The fork's Debian 13 .deb does not install there either: it depends
on libcpp-httplib0.41, which 26.04 does not have. So on 26.04 the engine plugs into the stock
lemond through the HRX recipe it already has, llamacpp-hrx, with no patch to Lemonade:
lemondlooks for that recipe'sllama-serverinLEMONADE_HRX_HRX_BIN, then inhrx.hrx_binin itsconfig.json. A path there skips its download of its own HRX build.- The engine package's systemd drop-in,
lemonade/1bit-hrx.conf(config/lemonade/1bit-hrx.conf), setsLEMONADE_HRX_HRX_BINtolemonade-hrxin the package. lemonade-hrx(scripts/lemonade-hrx) runs the package's HRXllama-server, with our HIP kernels, on Lemonade's arguments. First it runs1bit serve --print-backend-env, which makes serve's load-time checks (architecture, memory) and prints the environment serve gives an HRX backend: strict placement (GGML_HRX_STRICT=1), TheRock's HSA runtime, CWSR placement (engine#315) and the ternary decode. It also fills in what Lemonade's arguments leave to llama-server's defaults with serve's values:-ngl 99,--cache-reuse 256, and-kvuabove--parallel 1. A variable already set inlemond's environment wins, as it does under serve.
To install:
sudo add-apt-repository ppa:lemonade-team/stable
sudo apt install lemonade-server
tar -I zstd -xf 1bit-<version>-linux-x86_64.tar.zst
sudo 1bit-<version>-linux-x86_64/install-lemonade-ppa.sh # to /opt/1bit; restarts lemondinstall-lemonade-ppa.sh (scripts/install-lemonade-ppa.sh)
copies the package to /opt/1bit (or the directory it is given, outside /home, since the
service runs with ProtectHome=yes). It writes the drop-in to
/etc/systemd/system/lemond.service.d/1bit-hrx.conf and reloads systemd. If the PPA's postinst
did not already add the lemonade user to render, the script does. HRX also needs TheRock in
/opt/rocm-therock (hrx.md).
To run lemond as yourself instead of as the service, set the same variable for it
(LEMONADE_HRX_HRX_BIN=/opt/1bit/lemonade-hrx lemond) or put the path in hrx.hrx_bin in its
config.json.
Lemonade's HRX catalog (the *-HRX models) then runs on the engine, and so does a GGUF you
register with recipe: "llamacpp-hrx". Per-model arguments go in Lemonade's hrx_args, except
the ones Lemonade sets itself (-m, --ctx-size, --device, --port, --jinja,
--metrics). NPU model directories, DwarfStar, --pm and --laya are not
llama-server, so they stay with /opt/1bit/1bit serve (serve.md), outside the stock
lemond.
scripts/check-ubuntu-2604-lemond.sh runs this whole path
in a clean ubuntu:26.04 container: PPA, package, a model registered with llamacpp-hrx, a load
and a chat completion. It passes when lemond started lemonade-hrx rather than installing its
own HRX build, and when the llama-server it ran has GGML_HRX_STRICT=1. Without --gpu it
needs no GPU: a stand-in records the llama-server command and environment, then runs Ubuntu's
CPU llama.cpp. On Strix Halo, --gpu runs the real one on HRX0:
scripts/check-ubuntu-2604-lemond.sh out/1bit-<version>-linux-x86_64.tar.zst ~/models/Qwen3-0.6B-Q4_K_M.gguf --gpuOn the GPU the engine is pure HRX with HIP kernels; no Vulkan, ROCm backend, Metal, ZINC or CUDA (RFC #213 stage 3, 2026-10-01: HRX + NPU only; the core strip, 2026-10-04: no ZINC, so no CUDA; 2026-10-12: no MLX/Metal route and no Windows package). Lemonade ships its own backends for Vulkan, ROCm, CUDA, the CPU, MLX on Apple Silicon and Windows, so a model, feature or platform the engine does not run on HRX or the NPU is Lemonade's to serve:
1bit serve --device vulkan,--device rocm,--device zincand--device mlxexit at once with that reason, as do--lean,--adaptive,--long-model,--prefill-device,--zincand--mlx-server(serve.md).- An architecture only the removed Vulkan build ran (Zyphra Zamba, Zamba2 and BlackMamba, and a
few upstream-only ones) is refused with a pointer to Lemonade's
llamacpprecipe. Qwen3.8-Flash-Next (qwen4exp) runs on HRX since llama.cpp pine57beb97.
In the pinned fork (1bit-MONSTER/lemonade,
third_party/lemonade at 80064ba72a98, fork #15 on main), the onebit backend has two entries, hrx and npu
(backend_versions.json); its vulkan and cuda entries are gone. Lemonade offers onebit
models only on machines with hrx or npu. Lemonade's other recipes (its llamacpp Vulkan, ROCm
and CUDA backends, MLX and the rest) are Lemonade's own and unchanged.
1bit serve also works without Lemonade, for any OpenAI client:
1bit serve -m ~/models/Qwen3-0.6B-Q4_K_M.gguf --port 8000 # --device auto: HRX0, else the CPU
curl http://127.0.0.1:8000/v1/chat/completions -H 'Content-Type: application/json' \
-d '{"messages": [{"role": "user", "content": "Hello"}]}'