If you came here hoping to run LiquidAI d1-Omni-2B locally as a small voice assistant, I'll save you the download first: it can't talk back, and it can't write back either. It listens to audio and returns typed answers with probabilities attached, and that's all you get out of it.
Hugging Face files d1-Omni-2B under audio-text-to-text, and that label sets the wrong expectations. Liquid calls it a "decision model". You give it a state (text, JSON, an image, a video, or an audio clip) and a set of named questions, and it answers all of them in one forward pass with zero generated tokens. The card says plainly that it "writes no transcript or speech", and the docs say it is not a chat model.
I think that's a good design, for reasons I'll get to below. But it changes what "running it locally" means, so here's what the 2B adds over the 600M, how much RAM it needs, and what works today in transformers, llama.cpp, Ollama, MLX and ONNX (as of late October 2026). All benchmark and speed numbers below are Liquid's own. I haven't run it myself.
What d1-Omni-2B actually does
You ask typed questions and get typed answers:
noul: yes/no, returns P(yes)choice: one of several named options, with probabilitiesscore: an ordinal scale of 2 to 10 levels ("Agitated", "Neutral", "Calm")- in transformers, not yet in llama.cpp: multiple choice, extraction of text/number/date spans, number estimates with intervals, and bounding boxes
That fits call routing ("billing, technical or fraud?"), voicemail triage, sound event detection, or a cheap check at the front of a pipeline before a bigger model gets involved. Questions can even be spoken: the instructions field takes an audio clip. For text- or image-only work, Liquid's card itself tells you to use d1-2B instead, which beats the Omni on most rows.
d1-Omni-2B vs d1-omni-600M: what 3x the parameters buys you
The 600M came out with the Open d1 release on October 7, 2026, billed as Liquid's "first experimental checkpoint". According to OrcaRouter's repo write-up, the 2B repo was created on October 24. The 2B sits on a different base model, so treat it as a separate model rather than a bigger 600M:
| | d1-omni-600M | d1-Omni-2B |
|---|---|---|
| Parameters | 587M | 2.17B |
| Base | LFM2.5-Encoder-350M | LFM3-Omni-2B |
| Context | 16,384 tokens | 128K tokens |
| Audio input | one 16 kHz mono clip, up to 30 s | clips + spoken questions |
| Images + audio in one request | no (ValueError) | yes |
| Speech languages | trained on English requests | 12 (the 16 text languages minus Hindi, Thai, Vietnamese, Indonesian) |
| Decision Index v0.3 | 18.3 | 49.0 |
| Average (public decision + image benchmarks) | 42.8 | 67.7 |
| Min transformers | 5.15 | 5.19 |
The jump is large. Liquid says the 2B beats the 600M on every benchmark it reports, and beats d1-3B on the decision board and on 16 of 18 image benchmarks with about 70% of the parameters. VisualWebBench goes from 14.9 to 88.6. The 600M card reports no audio benchmarks at all, so there's no audio comparison to make between the two.
Audio scores: written vs. spoken input
The 2B card does publish audio scores, and they're worth a careful look. Each task is scored twice, once with the input written as text and once with the same input read aloud. The gap between the two columns is what the speech path costs you:
| Test | Written | Heard |
|---|---|---|
| SLURP (assistant commands, real speakers) | 87.4 | 81.7 |
| Speech-MASSIVE (12 languages) | 85.2 | 63.4 |
| FLEURS (spoken language ID, 43 languages) | 92.4 | 92.5 |
| ESC-50 (sound events) | n/a | 84.5 |
| Spoken short states | 42.0 | 22.8 |
| Belebele (passages, 8 languages) | 83.6 | 41.8 |
Short English commands and sound classification hold up. Long passages and non-English speech fall apart: Belebele loses half its score once you speak it. The card admits that "long spoken passages lose much of their accuracy, most of all outside Latin-script languages." If you're building multilingual voicemail triage, run your own eval before you trust it.
How much RAM and VRAM d1-Omni-2B needs
Liquid publishes no memory requirements, so here's the arithmetic plus the file sizes they do publish. At 2 bytes per parameter, 2.17B is about 4.3 GB of weights, which matches the single 4.33 GB BF16 safetensors file. Being a hybrid (13 short-convolution layers, 5 sliding-window, only 6 global attention), it should keep a smaller KV cache than a pure transformer at long context. And since it never decodes, you only pay for the prefill.
| Build | Size on disk | Where it runs |
|---|---|---|
| Safetensors BF16 | 4.33 GB | transformers (CUDA, MPS, CPU in fp32) |
| GGUF BF16 / F16 | 3.47 GB | llama.cpp |
| GGUF Q8_0 | 1.85 GB | llama.cpp |
| MLX 8-bit | 2.71 GB | Apple Silicon |
| ONNX q4 | 2.45 GB | CPU |
| ONNX q4f16 | 2.20 GB | GPU / WebGPU |
| ONNX fp32 | 8.32 GB | reference |
Watch the CPU path in transformers: the sample code loads in float32 on CPU, so budget for roughly double the BF16 footprint, around 8.7 GB by my math. The GGUF sizes are the language model only; llama.cpp also pulls an mmproj file for audio and images (0.33 GB at Q8_0, 0.61 GB at BF16). On an 8 GB laptop, use the Q8_0 GGUF or ONNX q4.
Runtime status: transformers, llama.cpp, Ollama, MLX
transformers
Full support, including every question type. It needs remote code:
pip install "transformers>=5.19" torch torchvision pillowimport torch
from transformers import AutoModel
device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
dtype = torch.float32 if device == "cpu" else torch.bfloat16
model = AutoModel.from_pretrained("LiquidAI/d1-Omni-2B", trust_remote_code=True, dtype=dtype).to(device)Then call model.system_one(state, questions, media=...). WAV files need to be 16-bit PCM and get resampled to 16 kHz.
llama.cpp
It works from build b11960 (v0.8.0) using the official GGUF, but only for noul, choice and score. Extraction, estimates, boxes and multi-select aren't supported there yet. On a laptop, this is what I'd run:
llama-server -hf LiquidAI/d1-Omni-2B-GGUF:Q8_0 -b 8192 -ub 8192Don't drop the batch flags. Each question's full state and media has to fit in a single batch. An image can use at most half of -ub, so 8192 gives it the full 4096-token budget. Then POST audio to the custom endpoint (this is the card's audio example):
curl -sL -o jfk.wav https://github.com/ggml-org/whisper.cpp/raw/master/samples/jfk.wav
curl http://127.0.0.1:8080/v1/systemone -H "Content-Type: application/json" -d @- <<JSON
{
"state": "Recording from a public event.",
"files": ["data:audio/wav;base64,$(base64 < jfk.wav | tr -d '\n')"],
"questions": {
"kind": {"type": "choice", "instructions": "What kind of utterance is this?",
"criteria": {"request": "A request to do something",
"question": "A question asking for information",
"speech": "A speech to an audience"}},
"calm": {"type": "score", "instructions": "How calm is the speaker?",
"criteria": ["Agitated", "Neutral", "Calm"]}
}
}
JSONSpoken questions work here too: put an input_audio part in a question's instructions.
Ollama
There's an official d1-omni library entry with a 2b tag at 4.4 GB. That's roughly the BF16 checkpoint, so don't expect a small quant. It serves the same /v1/systemone endpoint on port 11434, and the CLI gets an --ask flag. The page's own example:
curl http://localhost:11434/v1/systemone \
-H "Content-Type: application/json" \
-d '{
"model": "d1-omni:2b",
"state": "Hello World",
"questions": {
"says_hello": {
"type": "noul",
"instructions": "Does the state text contain a greeting?",
"criteria": {
"true": "The state text contains a greeting.",
"false": "The state text does not contain a greeting."
}
}
}
}'There's a catch. When I checked, the readme on that page still described the 600M (587M parameters, English speech only, 30-second clips, no audio and images together), and Liquid's d1-Omni-2B docs page only covers transformers and llama.cpp. Compare the 2B tag against transformers on a few of your own clips before you rely on it.
MLX
Official builds exist (fp16, 8-bit) and run through mlx_vlm, but the card itself says "Support for d1 in MLX-VLM is in progress". The examples may need an mlx-vlm release that doesn't exist yet. On a Mac I'd stick with transformers on MPS for now.
ONNX
The ONNX repo is the one I'd keep an eye on. It has CPU q4/q8 bundles and a WebGPU path via onnxruntime-web/webgpu, so routing audio in the browser looks doable.
Speed: fast on GPUs, and no CPU numbers yet
Liquid's bf16 numbers after model.compile(), for a 10-second audio clip: 12.4 ms on an H100 PCIe, 8.2 ms on an MI325X, 33.3 ms on an Apple M5 Pro. A single question on the M5 Pro takes 21.1 ms. Nothing gets decoded, which is why the numbers are that low.
Liquid doesn't publish any CPU or Raspberry Pi number for this model. I'd ignore any headline that says it "runs on CPU" until someone posts timings. It will run, since the ONNX CPU builds exist, but nobody has said how fast.
License: free until you hit $10M revenue
The weights ship under the LFM Open License v1.0. Commercial use is free under $10 million USD annual revenue, counted across your whole corporate group. Above that, you need a separate license. The threshold also applies to your downstream customers, and violating any term terminates the license immediately. That's fine for hobby projects and startups. If you ship it in an enterprise product, talk to a lawyer before it goes out. The Open d1 blog's "without restrictions" line is more generous than the actual license text.
My take
Skipping generation is the right call for this job. When I'm routing a call I want {"team": "billing", "confidence": 0.94} back in 20 ms, with a probability I can put a threshold on; a 300-token explanation is just latency. The 600M was a research preview. The 2B is the first d1-Omni I'd consider putting in a real pipeline, as long as the audio is short, mostly English, and you've calibrated thresholds on your own recordings, which the card also tells you to do.
Is 2B the sweet spot for an on-device voice model, or would you rather run the 600M on a Pi and accept the accuracy hit? And if you've run d1-omni:2b in Ollama, do its probabilities match what transformers gives you for the same clip? Tell me in the comments.
