d1-Omni-2B

d1-Omni-2B is a decision model for text, pictures, and audio, built on LFM3-Omni-2B. It returns calibrated answers in one forward pass, without generating tokens.

  • Native audio: clips and spoken questions go through the same pass as text and pictures, and spoken questions score within 0.5 points of written ones on unseen tasks.
  • Beyond classification: it also extracts text, numbers, and dates with their span, locates objects in pictures, and estimates quantities with an interval.
  • Millisecond decisions: 5.8 ms per decision on an NVIDIA H100 and 3.7 ms on an AMD MI325X, or 12.4 ms and 8.2 ms with a 10-second clip.

Find more information about open d1 in our release blog post.

Model details


The LFM3 family includes base, text, vision, audio, omni, and decision models. d1-Omni-2B adds audio to d1-2B.

Property Specification
Checkpoint Post-trained decision model, built on LFM3-Omni-2B
Parameters 2.17B
Architecture LFM3 backbone, 24 layers: 13 gated short convolutions, 5 sliding-window attention, 6 global attention
Context length 128K tokens
Vocabulary 128,000 tokens
Input A state (text or JSON), pictures, a video, audio clips, and any number of named questions, written or spoken
Output Typed answers with their probabilities, with no generated tokens or speech
Languages English, Arabic, Chinese, French, German, Italian, Japanese, Korean, Portuguese, Spanish, Vietnamese, Thai, Indonesian, Hindi, Russian, Polish. Speech covers the same languages except Hindi, Thai, Vietnamese, and Indonesian.
License LFM Open License v1.0

d1-Omni-2B is designed for decisions that depend on what is heard, such as call and voice-message routing and sound events, and it handles the same text and picture decisions as d1-2B. It is not a chat model and writes no transcript or speech.

Long spoken passages lose much of their accuracy, most of all outside Latin-script languages. Without audio, use d1-2B: it is stronger on text and single boxes, reports missing values more often, and is better calibrated.

Inference


d1-Omni-2B runs in Transformers with its own model code. It reads its answers from a single forward pass, so there are no sampling parameters to set.

Transformers quick start:

pip install "transformers>=5.19" torch torchvision pillow
import numpy as np
import 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)

# A recording: three short beeps over quiet noise, 16 kHz mono
rate = 16000
clip = np.random.default_rng(0).normal(0, 0.003, 4 * rate).astype(np.float32)
for start in (0.5, 1.5, 2.5):
    clip[int(start * rate):int(start * rate) + 3200] += 0.3 * np.sin(2 * np.pi * 880 * np.arange(3200) / rate)
out = model.system_one(None, {
    "beeps": {"type": "number", "instructions": "How many beeps are there?", "range": [0, 10], "step": 1},
    "speech": {"type": "noul", "instructions": "Does someone speak in the recording?"},  # yes/no: P(yes)
}, media=[{"type": "audio", "audio": clip, "sampling_rate": rate}])
a = out["answers"]
print(a["beeps"]["number"], a["speech"]["noul"] > 0.5)
# 3.0 False

A clip from a file is {"type": "audio", "path": "call.wav"} (16-bit PCM WAV, resampled to 16 kHz). A spoken question takes a clip as its instructions: {"type": "noul", "instructions": {"type": "audio", "path": "question.wav"}}.

Text questions

Several named questions over one state, answered in one pass, as with d1-2B:

questions = {
    "refund": {"type": "noul", "instructions": "Is the customer asking for a refund?"},
    "team": {"type": "choice", "instructions": "Which team should handle this?",
             "criteria": {"billing": "Charges, refunds, invoices", "shipping": "Delivery and parcels",
                          "technical": "App or site faults"}},
    "topics": {"type": "choice", "multiple": True, "instructions": "Which topics does the message raise?",
               "criteria": {"billing": "Payments and charges", "delivery": "Shipping and parcels",
                            "login": "Signing in to the account"}},
}
out = model.system_one("I was charged twice and my parcel never arrived. Please refund one charge.", questions)
a = out["answers"]
print(round(a["refund"]["noul"], 2), a["team"]["choice"], a["topics"]["choices"])
# 0.94 billing ['billing', 'delivery']
Values from a document
invoice = "ACME SA\nInvoice 2026-117\nTotal due: 1 234,50 EUR\nPay before 03/04/2026 (day/month/year)"
out = model.system_one(invoice, {
    "payee": {"type": "text", "instructions": "Who issued the invoice?"},
    "total": {"type": "number", "instructions": "How much is due?"},
    "due": {"type": "date", "instructions": "By when must it be paid?"},
    "vat": {"type": "number", "instructions": "How much VAT is charged?"},
})
a = out["answers"]
print(a["payee"]["text"], a["total"]["number"], a["due"]["date"], a["vat"]["number"])
# ACME SA 1234.5 2026-04-03 None
Pictures and boxes

Count, locate one object, or list every instance (max reads at most that many):

from transformers.image_utils import load_image

image = load_image("http://images.cocodataset.org/val2017/000000039769.jpg")  # two cats on a sofa
out = model.system_one(None, {
    "cats": {"type": "number", "instructions": "How many cats are there?", "range": [0, 10], "step": 1},
    "remote": {"type": "box", "instructions": "Where is the remote control on the left?"},
    "every_cat": {"type": "boxes", "instructions": "Every cat.", "max": 4},
}, media=[image])
a = out["answers"]
print(a["cats"]["number"], a["every_cat"]["count"], {k: round(v, 2) for k, v in a["remote"]["box"].items()})
# 2.0 2 {'top': 0.15, 'bottom': 0.24, 'left': 0.06, 'right': 0.27}
Calls
Call What it does
system_one(state, questions, media=None) Named questions over one state, in one pass. media lists audio clips ({"type": "audio", "path": ...}, or a waveform under "audio" with its "sampling_rate"), pictures (PIL images or {"type": "image", "path": ...}) and videos as their frames ({"type": "video", "video": [PIL images], "fps": 24}).
system_one_batch([(state, questions[, media]), ...]) Many requests in one call, batched.
set_size= (either call) Questions read together after the state. The default is the model's trained size (16). Larger is faster and costs some accuracy on text.

A state is a string, any JSON value, or None when the media are the whole state. Each call returns {"answers": {name: answer}, "usage": {"input_tokens": n, "output_tokens": 0}}.

Question types
type Question Answer
noul Yes or no noul: P(yes)
choice One of the options criteria names ({name: description}) choice, confidence, probabilities
choice with multiple: true Any of the options criteria names choices, probabilities (each option's own P(yes))
score One of 2 to 10 ordered levels, with criteria listing them lowest first score (the median level), confidence, probabilities, legend
text, number, date A value to read from the state The field of its type (a number with its unit, a date in ISO 8601), span, found
number with range An estimate, step apart number (the median), interval (p10, p90)
box, boxes One object, or every instance (16 at most, or max), in the one picture box (top, bottom, left, right as fractions of the picture), found, confidence, or boxes and count

A value or a box is missing when found is under 0.5, and it is then None. Calibrate any decision threshold on data from your own use.

Performance


Benchmarks

d1-Omni-2B scores above d1-omni-600M on every benchmark, and above d1-3B on our decision board and on 16 of 18 image benchmarks, with 70% of its parameters. d1-2B, which has no audio input, stays ahead on most rows.

Benchmark d1-Omni
2B
d1-omni
600M
d1
2B
d1
3B
Decisions
Decision Index public suite (v0.3) 49.0 18.3 51.1 49.0
DecisionBench (Hanno Labs) v1 76.4 58.7 77.1 73.1
Decision Bench (decisionbench.ai) v4 84.7 57.9 85.2 83.6
Fast Decisions 56.8 – 58.8 59.3
JevBench v1.4.1 75.3 58.0 77.9 76.2
ImajevBench v2.0-lite 72.3 21.7 75.5 64.0
WorkflowEvals 77.1 48.8 81.6 74.4
Typed Decisions 63.1 57.5 61.3 65.0
Our board (over a hundred public and private benchmarks) 61.8 – 63.2 58.8
Vision
AI2D 71.5 37.1 76.7 79.9
BLINK 63.5 37.7 66.2 59.2
CountQA 45.4 26.8 51.4 42.6
CV-Bench 84.0 40.8 86.1 82.1
ERQA 42.5 27.3 45.8 39.8
HallusionBench 67.5 52.6 72.1 65.3
MMBench 85.2 54.2 87.9 84.9
MME 83.9 61.0 85.4 82.1
MMMU-Pro 24.1 11.9 26.4 18.5
MMRB2 52.6 48.3 54.2 49.5
MMStar 61.3 31.9 67.5 59.9
MMVP 81.3 54.0 82.7 77.0
NaturalBench 80.0 58.8 81.5 79.8
POPE 89.9 82.7 88.7 88.6
V* 76.4 35.6 76.4 73.8
VisualPuzzles 26.9 26.2 29.9 29.5
VisualWebBench 88.6 14.9 96.2 71.4
VL-RewardBench 68.8 48.1 69.3 65.0
Average67.742.870.265.4
Evaluation details

All four models are scored on the same items with the same scoring, so a few of d1-3B's and d1-omni-600M's numbers differ slightly from their own cards. d1-omni-600M has no Fast Decisions or board score. Average is the unweighted mean of the public benchmarks that all four models have, so it leaves out Fast Decisions and our board. Image benchmarks are read as decisions over each benchmark's options, on at most 1,000 rows each. Three of them are saturated: POPE, MME, and VisualWebBench.

Audio

Each audio row is scored heard and written, on clips and voices that no training row has. Scores are effective accuracy, where 0 is chance and 100 is every answer right. In the second group, synthetic voices read the question and short state of 1,284 test rows aloud, in each row's language.

Test Written Heard
Held-out audio
Spoken questions, on tasks absent from training 45.2 44.7
Spoken short states 42.0 22.8
Assistant commands, real speakers (SLURP intents) 87.4 81.7
Assistant commands in 12 languages (Speech-MASSIVE intents) 85.2 63.4
Spoken language, 43 languages (FLEURS) 92.4 92.5
Sound events (ESC-50) – 84.5
Decision suites read aloud
DecisionBench (Hanno Labs) v1, routing and triage 83.4 78.2
JevBench v1.4.1, the rows a voice can say 87.6 89.0
Abstention: none of the options applies (our set) 78.5 75.8
Typed Decisions, customer service 50.5 48.0
Belebele, passages in 8 languages 83.6 41.8

Speed

Warm calls after model.compile() in bf16, median of 20 calls, and best of three runs on the H100 and the M5 Pro. Compiling takes about a minute on the first calls.

Hardware One question 3 questions 5K-token state 384 px picture 10 s audio clip 64 states in one call
NVIDIA H100 PCIe 5.8 ms 7.7 ms 52 ms 12.1 ms 12.4 ms 1,154 / s
AMD MI325X 3.7 ms 5.6 ms 43 ms 8.6 ms 8.2 ms 1,697 / s
Apple M5 Pro (mps) 21.1 ms 28.9 ms 694 ms 40.2 ms 33.3 ms 110 / s

Citation


@article{liquidAI2026opend1,
  author  = {Liquid AI},
  title   = {Open d1: Edge decision models for text, vision, and audio},
  journal = {Liquid AI Blog},
  year    = {2026},
  note    = {https://www.liquid.ai/blog/open-d1},
}
@article{liquidAI2026LFM3,
  author  = {Liquid AI},
  title   = {Introducing LFM3: Every Modality for Specialized Intelligence},
  journal = {Liquid AI Blog},
  year    = {2026},
  note    = {https://www.liquid.ai/blog/lfm3},
}

For questions and feedback, join Discord. For custom deployment and fine-tuning support, contact Liquid AI.

Downloads last month
36
Safetensors
Model size
2B params
Tensor type
BF16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for LiquidAI/d1-Omni-2B

Quantizations
3 models

Space using LiquidAI/d1-Omni-2B 1

Collection including LiquidAI/d1-Omni-2B

Article mentioning LiquidAI/d1-Omni-2B