mlx-optiq
Family guide · LFM2.5

LFM2.5 on Apple Silicon

LFM2.5 is Liquid AI's on-device series, from 230M up to an 8B sparse MoE. It is a hybrid: short convolutional blocks alternate with full-attention blocks, and only the attention blocks carry a KV cache. On the 1.2B that means six layers hold cache out of the whole stack, so memory grows slowly as context does. That is the property that makes the family interesting on a laptop or a phone, and it is why the bundled KV config is short.

As of LFM2.5-VL the family also reads images. The VL model pairs a SigLIP2 encoder with the same hybrid language tower, so it inherits the short KV cache.

The quants

Every row is a six-metric Capability Score, not a perplexity number. Sizes are the artifact on disk.

Modelbf16 sizeOptiQ sizeCompressionCapability Score
LFM2.5-230M-OptiQ-4bit443 MB180 MB2.5×24.83
LFM2.5-350M-OptiQ-4bit681 MB269 MB2.5×26.60
LFM2.5-1.2B-Instruct-OptiQ-4bit2.34 GB825 MB2.8×47.82
LFM2.5-1.2B-Thinking-OptiQ-4bit2.34 GB820 MB2.9×54.14
LFM2.5-1.2B-JP-202606-OptiQ-4bit2.34 GB838 MB2.8×47.83
LFM2.5-2.6B-OptiQ-4bit5.2 GB1.93 GB2.7×35.19
LFM2.5-VL-3B-OptiQ-4bit6.3 GB2.83 GB2.2×37.93
LFM2.5-8B-A1B-OptiQ-4bit15.8 GB5.46 GB2.9×28.69

Which one to reach for

The Thinking variant is the one to use if you can spare the tokens. It scores 64.7% on MMLU against the Instruct model's 43.3%, and 82.8% on GSM8K against 69.7%. Reasoning is doing real work at this size, not decorating the answer.

The Japanese variant is the interesting one. Its overall score lands at 47.83 against the Instruct model's 47.82, near enough to call identical, but the capability sits in different places: seven points more on MMLU, nearly ten more on HumanEval, and roughly eight less on both GSM8K and IFEval. Same total, redistributed.

Below a gigabyte the 230M and 350M are useful for classification, routing and extraction rather than open-ended chat. Both score at chance on long-context retrieval.

Vision

LFM2.5-VL-3B adds a 27-layer SigLIP2 encoder and a two-layer projector on top of the hybrid language tower. OptiQ quantizes the language path to mixed 4/8-bit and keeps the encoder and projector at bf16 in the optiq/ sidecar, so one artifact does text and images.

PropertyValue
Vision towerSigLIP2, 27 layers, hidden 1152, patch 16
Resolutionnative aspect ratio, position embeddings resampled per image
Token budget2×2 pixel unshuffle before the projector, capped at 256 image tokens
Language towermixed 4/8-bit: 88 layers at 4-bit, 78 at 8-bit
On disk1.98 GB language + 0.85 GB vision

Capability Score 37.93. It reads images well and its text scores sit mid-pack for a 3B, but it does not initiate tool calls: BFCL is 0.0% because the model works the answer out itself rather than calling the function. Asked for the area of a triangle it derives the formula, where the text-only 1.2B calls calculate_triangle_area and scores 45.0% through the same harness. It emits correct calls when told to use a tool, so the capability is there and the model simply does not reach for it. For agentic tool use at this size, take the text 1.2B or 2.6B.

The vision tower runs natively in MLX, with no PyTorch and no mlx-vlm at runtime. It was checked against the reference implementation across four patch grids and matches to bf16 round-off, so image answers are the base model's, not an approximation of them.

Hello world

hello.pypython
from mlx_lm import load, generate

model, tok = load("mlx-community/LFM2.5-1.2B-Thinking-OptiQ-4bit")
prompt = tok.apply_chat_template(
    [{"role": "user", "content": "What is 17 * 23? Think briefly then answer."}],
    tokenize=False, add_generation_prompt=True,
)
print(generate(model, tok, prompt=prompt, max_tokens=2048))
Give the Thinking model room It spends its first few hundred tokens inside the reasoning block, and that comes out of max_tokens. Set the cap too low and the entire allowance is consumed before the answer starts, so you get an empty string back rather than a short reply. 2048 is a sensible floor.

Tool calling

LFM2.5 does not emit JSON tool calls. It writes Python, between two special tokens:

tool calltext
<|tool_call_start|>[get_weather(city="Paris")]<|tool_call_end|>

Pass tools= to apply_chat_template and the catalog is rendered into the system prompt. OptiQ parses this form in both the evaluator and the agent loop, so a model that calls tools correctly scores as though it does.

Serving

Each quant ships a kv_config.json sized for its handful of attention layers. On the 1.2B that is six layers at roughly four bits.

servebash
optiq serve --model mlx-community/LFM2.5-1.2B-Thinking-OptiQ-4bit \
  --kv-config kv_config.json