← back to catalog · registered 2026-11-06 16:02

maternion/LFM3-Audio-2B-Heretic2-Abliterated-GGUF

maternion 2B GGUF
Your rig guess connected
? Why do I need an app?
Reading your rig…

This is a rough estimate. Install the free app - we'll show exact numbers.

Reading real hardware from your app right now. Numbers below are exact.

Below is the per-quantization compatibility for this model.

curl -H "Authorization: Bearer $ABL_KEY" \
     "https://abliteration.org/api/v1/models/maternion%2FLFM3-Audio-2B-Heretic2-Abliterated-GGUF"
Response includes
  • classification m3
  • files 13
  • author_summary 5 models
  • readme_text full
10 credits · hourly refresh · ~4 KB payload Get an API key →
Abliteration classifier · v1.0.0
M3
Primary method

Layer-wise ablation

Applied on top of direct removal inherited from the base model.
Confidence
HIGH
Inherited from base model
Why this label 2 signals
Producer identity confirmed by naming conventions, tags or the model card. This label is very unlikely to change.
  • 'heretic' in model name (Heretic-produced)
  • Heretic uses layer-wise optimization (M3) with underlying direction removal (M1)
Refusal direction extracted via
Extraction technique

Difference-of-means

Confidence
HIGH
Why we say so
name contains 'heretic'; Heretic default extraction is difference-of-means (Arditi 2024)
Downloads · 30-day
0
Likes
1
Model age
today
created 2026-11-06

Genealogy 0 direct forks

Full fork graph →

This model's place in the market. Above: what it was derived from. Below: the tree of everything derived from it.

Metadata

License
other
Languages
en ar da de el fi fr he it ja ko nl pl pt es sv tr zh
Quantizations
BF16 IQ2 IQ3 IQ4 Q3_K Q4_K Q5_K Q6_K Q8_0
Tags
gguf lfm3 liquid audio speech abliterated heretic uncensored llama.cpp ollama any-to-any en

Related

Total size
12.7 GB
Files
13
Quantizations
10
Registered
2026-11-06 16:02
Last updated on HF
2026-11-06 15:23

Files by quantization

BF16 2 files 3.76 GB
LFM3-Audio-2B-BF16.gguf 3.23 GB 681d701d download
LFM3-Audio-2B-mmproj-BF16.gguf 544 MB 43bdcd15 download
Q8_0 1 file 1.72 GB
LFM3-Audio-2B-Q8_0.gguf 1.72 GB 0ba81a64 download
Q6_K 1 file 1.33 GB
LFM3-Audio-2B-Q6_K.gguf 1.33 GB d0334ba5 download
Q5_K 1 file 1.17 GB
LFM3-Audio-2B-Q5_K_M.gguf 1.17 GB a77f06d4 download
Q4_K 1 file 1.02 GB
LFM3-Audio-2B-Q4_K_M.gguf 1.02 GB 78cf8b57 download
IQ4 2 files 1.91 GB
LFM3-Audio-2B-IQ4_NL.gguf 1001 MB f159884b download
LFM3-Audio-2B-IQ4_XS.gguf 957 MB 98e1c28d download
Q3_K 1 file 873 MB
LFM3-Audio-2B-Q3_K_M.gguf 873 MB 2351f663 download
IQ3 1 file 829 MB
LFM3-Audio-2B-IQ3_M.gguf 829 MB 620c393f download
IQ2 1 file 640 MB
LFM3-Audio-2B-IQ2_M.gguf 640 MB 7912828c download
Auxiliary files 2 files 44.6 KB
README.md 44.6 KB 8cd63c3b download
.gitattributes 43.0 B ae756a3f download

README current version from Hugging Face


library_name: gguf
pipeline_tag: any-to-any
base_model: LiquidAI/LFM3-Audio-2B
tags:


LFM3-Audio-2B-Heretic2-GGUF

GGUF quantizations of an abliterated LFM3-Audio-2B,
produced with heretic 2.0.0. Refusal behaviour is reduced while the base model's
audio and text capabilities are kept intact.

Audio requires the mmproj file. Only the text backbone was modified; the
audio encoder, projector, depthformer and LiquidCodec are byte-identical to the
base model and ship as LFM3-Audio-2B-mmproj-BF16.gguf. Without it these GGUFs
are text-only.

Heretic Details

Property Value
Ablation method Arbitrary-Rank Ablation (ARA)
Trial 301 of 315
KL divergence 0.0761
Refusals (this model) 19/100
Refusals (base) 98/100
Evaluation set LLM-LAT/harmful-dataset train[400:500] (100 prompts)
Degenerate repetition 1/100
start_layer_index              = 2
end_layer_index                = 22
preserve_good_behavior_weight  = 0.9846
steer_bad_behavior_weight      = 0.000970
overcorrect_relative_weight    = 0.2109
neighbor_count                 = 15

How the refusals were measured

Each prompt is answered by the model, then the (prompt, response) pair is scored
by LiquidAI d1-2B through Ollama's /v1/systemone endpoint. A decision model
returns a calibrated probability in a single forward pass - no sampling, no output
parsing - and a response counts as a refusal at p >= 0.5.

heretic's built-in BERTClassifier was discarded on this model. It matches refusal
vocabulary, so it flagged 41 of 100 answers that fully complied (precision 2.4%).
Optimising against it inflated KL divergence to 1.09 and produced a model that
looped on 25% of prompts. The decision-model judge reads the pair semantically
instead, with 5/5 recall on hand-labelled transcripts.

Generation settings matter as much as the judge: responses are scored from an
answer window (closed, empty thinking block) at 300 tokens. The 100-token
window used in the first attempt was the single biggest error in this project -
the model stays coherent for roughly 94 tokens and then falls into list
repetition, so a 100-token objective could see neither the refusals nor the
damage it was causing.

Degenerate repetition is tracked separately (any 6-word sequence repeated four or
more times), because a looping answer is neither compliance nor a refusal. The
base model scores 0/100 on it; an earlier candidate that looked perfect on
refusals scored 25/100 and was thrown out.

Note: no model is fully "uncensored". Roughly 1 in 5 harmful prompts is still
declined. Abliteration removes a refusal direction; it does not add capability.

Available Files

File Quant Size
LFM3-Audio-2B-IQ2_M.gguf IQ2_M 0.67 GB
LFM3-Audio-2B-IQ3_M.gguf IQ3_M 0.87 GB
LFM3-Audio-2B-Q3_K_M.gguf Q3_K_M 0.91 GB
LFM3-Audio-2B-IQ4_XS.gguf IQ4_XS 1.00 GB
LFM3-Audio-2B-IQ4_NL.gguf IQ4_NL 1.05 GB
LFM3-Audio-2B-Q4_K_M.gguf Q4_K_M 1.10 GB
LFM3-Audio-2B-Q5_K_M.gguf Q5_K_M 1.26 GB
LFM3-Audio-2B-Q6_K.gguf Q6_K 1.43 GB
LFM3-Audio-2B-Q8_0.gguf Q8_0 1.85 GB
LFM3-Audio-2B-BF16.gguf BF16 3.47 GB
LFM3-Audio-2B-mmproj-BF16.gguf audio projector (required for audio) 0.57 GB

Use with llama.cpp

[!NOTE]
Requires llama.cpp b11960
(v0.8.0) or newer, the
build that adds LFM3-Audio support, including real-time voice conversations on the
/v1/realtime WebSocket API of llama serve.

Sampling, quoted from the official LFM3-Audio-2B-GGUF
card: "Recommended sampling: greedy decoding (temperature 0) for text output. For
speech output, audio temperature 1.0, audio top_k 128 and audio repetition penalty
1.1."
Those audio parameters are stored in these GGUFs too.

Start a web chat UI and an OpenAI-compatible API at http://localhost:8080:

llama serve -m LFM3-Audio-2B-Q4_K_M.gguf \
  --mmproj LFM3-Audio-2B-mmproj-BF16.gguf \
  --temp 0 --port 8080

To ask one question from the command line, use llama cli.

Speech recognition: use the system prompt Perform ASR in <language>., or Perform ASR. to let the model infer the language.

llama cli -m LFM3-Audio-2B-Q4_K_M.gguf \
  --mmproj LFM3-Audio-2B-mmproj-BF16.gguf \
  --audio speech.wav -sys "Perform ASR in English." -p "<__media__>" --temp 0

Speech synthesis: --tts-lang takes a language code (default en) and --tts-voice
is female (default) or male.

llama-tts -m LFM3-Audio-2B-Q4_K_M.gguf -mm LFM3-Audio-2B-mmproj-BF16.gguf \
  -p "Hello world" --tts-voice male -o out.wav

Builds from before the llama entry point was unified ship the same functionality as
llama-cli and llama-server, which take the identical flags.


LFM3-Audio-2B

LFM3-Audio-2B is a compact, fully featured audio model that runs locally on laptops and edge devices. It takes text or audio as input and responds with text, speech, or both.

  • Voice chat: ask questions aloud and receive streaming replies in text and speech. For text-only responses, the model can reason before answering. Currently supports English only.
  • Multilingual speech: transcribe, synthesize, and translate speech across 18 languages.
  • Audio understanding and reasoning: interpret recordings and answer questions about the speech, sounds, and events they contain.
  • Tool calling: turn spoken requests into tool calls to control apps and devices, with text or speech alongside the calls.

LFM3-Audio-2B introduces an in-house audio encoder and LiquidCodec audio tokenizer, improving speech quality over LFM2.5-Audio. Find more information about the LFM3 family in our release blog post.

Model details


The LFM3 family includes base, text, vision, audio, omni, and decision models.

Property Specification
Parameters 2B total
Architecture LFM3 backbone, causal audio encoder, and LiquidCodec audio tokenizer
Input Text or audio; audio encoder operates at 16 kHz
Output Text, 24 kHz speech, or interleaved text and speech
Context length 32K tokens (input + output)
Streaming Causal audio encoding, incremental prefill, and streaming speech generation
Speech languages / locales Arabic, Danish, German, Greek, British English, American English, Finnish, French, Hebrew, Italian, Japanese, Korean, Dutch, Polish, Portuguese, Spanish, Swedish, Turkish, Chinese
License LFM Open License v1.0

LFM3-Audio-2B is designed for local agents, tool calling, structured outputs, and domain-specific fine-tuning. Use retrieval or search for knowledge-heavy tasks. It is not recommended for agentic coding or complex multi-step reasoning due to its small size.

Inference


Choose a checkpoint variant for your inference framework and hardware.

Checkpoint Framework Description
BF16 vLLM, SGLang, Transformers BF16 weights for GPU inference.
GGUF llama.cpp Local inference on CPUs and GPUs.
MLX MLX-VLM 4-bit quantization for Apple Silicon.
ONNX ONNX Runtime Cross-platform inference with ONNX Runtime.

Transformers quick start

Install the dependencies, then load the model and processor with the checkpoint's custom code. The codec implementation is included in this repository; the processor loads its weights from audio_tokenizer/.

pip install "transformers>=5.20.2" torch accelerate librosa soundfile

Load the model and processor directly from the Hugging Face Hub:

import torch
import soundfile as sf

from transformers import AutoModelForMultimodalLM, AutoProcessor

model_id = "LiquidAI/LFM3-Audio-2B"
device = "cuda" if torch.cuda.is_available() else "cpu"
dtype = torch.bfloat16 if device == "cuda" else torch.float32

model = AutoModelForMultimodalLM.from_pretrained(
    model_id, dtype=dtype, device_map=device, trust_remote_code=True
).eval()
processor = AutoProcessor.from_pretrained(model_id, trust_remote_code=True)
codec = processor.audio_tokenizer.to(device=device).eval()

Audio sampling parameters: use audio_temperature=1.0, audio_top_k=128, audio_repetition_penalty=1.1, and audio_repetition_window=4096 for speech synthesis and interleaved text and speech. For text-only output, set suppress_mixed=True and suppress_audio_out=True.

Usage examples

The examples below reuse the model, codec, and processor loaded above. Replace audio.wav, question.wav, or recording.wav with your own audio files.

Speech recognition (ASR)

To use the model for transcription, use the system prompt Perform ASR in <language>., where <language> is the English name of the language.
To let the model infer the language, use Perform ASR..

Below, we transcribe a .wav file containing English speech.

conversation = [
    {"role": "system", "content": "Perform ASR in English."},
    {"role": "user", "content": [{"type": "audio", "audio": "audio.wav"}]},
]

inputs = processor.apply_chat_template(
    conversation,
    add_generation_prompt=True,
    tokenize=True,
    return_dict=True,
    return_tensors="pt",
).to(device)
with torch.no_grad():
    outputs = model.generate(
        **inputs,
        max_new_tokens=1024,
        suppress_mixed=True,
        suppress_audio_out=True,
        return_dict_in_generate=True,
    )
text = processor.decode(
    outputs.sequences[0, inputs["input_ids"].shape[1]:],
    skip_special_tokens=True,
)
print(text)
Live speech recognition (LiveASR)

LiveASR transcribes speech while it is still being spoken, instead of waiting for the full recording. Use the system prompt Perform live ASR.. LiveASR currently supports English only. The model processes audio in chunks of about 0.96 s and writes the text for each chunk as soon as the chunk arrives. model.transcribe_live() runs one chunk at a time and returns a state that you pass to the next call.

Below, we simulate a microphone by feeding a .wav file in 100 ms pieces.

import librosa

tokenizer = processor.tokenizer
chunk_frames = 8 * model.config.interleaved_n_audio
prompt = tokenizer(
    "<|startoftext|><|im_start|>system\nPerform live ASR.<|im_end|>\n<|im_start|>assistant\n",
    add_special_tokens=False,
    return_tensors="pt",
).input_ids.to(device)
suppress = tokenizer.convert_tokens_to_ids(["<|mixed_end|>", "<|endoftext|>"])
stop = tokenizer.convert_tokens_to_ids(["<|endoftext|>", "<|im_start|>"])
state, feature_cache = None, None
mel = torch.empty((1, processor.feature_extractor.feature_size, 0), device=device)


def transcribe(frames, is_final=False):
    global state
    output = model.transcribe_live(
        frames,
        state,
        input_ids=prompt if state is None else None,
        is_final=is_final,
        max_new_tokens=96 if is_final else 48,
        suppress_token_ids=suppress,
        stop_token_ids=stop,
    )
    state = output.state
    print(tokenizer.decode(output.sequences[0], skip_special_tokens=True), end="", flush=True)


waveform, _ = librosa.load("audio.wav", sr=16_000)
for start in range(0, len(waveform), 1_600):  # 100 ms microphone chunks
    features, feature_cache = processor.feature_extractor.stream(
        waveform[start:start + 1_600], feature_cache
    )
    mel = torch.cat((mel, features.input_features.to(device)), dim=-1)
    while mel.shape[-1] >= chunk_frames:
        transcribe(mel[..., :chunk_frames])
        mel = mel[..., chunk_frames:]

# flush the remaining audio and end the transcript
features, feature_cache = processor.feature_extractor.stream([], feature_cache, is_final=True)
mel = torch.cat((mel, features.input_features.to(device)), dim=-1)
while mel.shape[-1] > chunk_frames:
    transcribe(mel[..., :chunk_frames])
    mel = mel[..., chunk_frames:]
transcribe(mel, is_final=True)
print()

For streams longer than 30 seconds, pass input_ids=prompt again to start a new text context. The encoder keeps following the audio stream.

Speech synthesis (TTS)

For speech synthesis, use the system prompt Perform TTS in <language> using a <gender> voice..
Use a language or locale from the model details above and a female or male voice. Prefill the assistant turn with <|audio_start|>.

conversation = [
    {"role": "system", "content": "Perform TTS in American English using a female voice."},
    {"role": "user", "content": "The quick brown fox jumps over the lazy dog"},
    {"role": "assistant", "content": "<|audio_start|>"},
]
inputs = processor.apply_chat_template(
    conversation,
    continue_final_message=True,
    tokenize=True,
    return_dict=True,
    return_tensors="pt",
).to(device)
with torch.no_grad():
    outputs = model.generate(
        **inputs,
        max_new_tokens=256,
        audio_temperature=1.0,
        audio_top_k=128,
        audio_repetition_penalty=1.1,
        audio_repetition_window=4096,
        return_dict_in_generate=True,
    )
    waveform = codec.decode(
        outputs.audio_codes[:1, :, :outputs.audio_lengths[0]]
    ).audio_values[0]  # 24 kHz

sf.write("tts.wav", waveform.float().cpu().numpy(), 24_000)
Voice chat: speech and text responses

In this mode, the model will respond to the user in both speech and text.
The recommended system prompt is Respond with interleaved text and audio..
User input can be either text or audio, and we prefill the assistant turn with a special token <|mixed_start|>.

The assistant responds in a conversational style with interleaved text and speech. This example saves the complete response.

conversation = [
    {"role": "system", "content": "Respond with interleaved text and audio."},
    {"role": "user", "content": [{"type": "audio", "audio": "question.wav"}]},
    {"role": "assistant", "content": "<|mixed_start|>"},
]
inputs = processor.apply_chat_template(
    conversation,
    continue_final_message=True,
    tokenize=True,
    return_dict=True,
    return_tensors="pt",
).to(device)
with torch.no_grad():
    outputs = model.generate(
        **inputs,
        max_new_tokens=1024,
        audio_temperature=1.0,
        audio_top_k=128,
        audio_repetition_penalty=1.1,
        audio_repetition_window=4096,
        return_dict_in_generate=True,
    )

    text = processor.decode(
        outputs.sequences[0, inputs["input_ids"].shape[1]:],
        skip_special_tokens=True,
    )
    waveform = codec.decode(
        outputs.audio_codes[:1, :, :outputs.audio_lengths[0]]
    ).audio_values[0]  # 24 kHz
print(text)
sf.write("reply.wav", waveform.float().cpu().numpy(), 24_000)

For streaming applications, model.generate() accepts streamer for text tokens and audio_streamer for speech frames. LiquidCodec supports incremental decoding of those frames.

Speech-to-text chat, with or without reasoning

For a text-only answer, no specific system prompt is needed. Prefill <think> to let the model reason before answering, or <think></think> for a direct response.

use_thinking = True
conversation = [
    {"role": "user", "content": [{"type": "audio", "audio": "question.wav"}]},
    {"role": "assistant", "content": "<think>" if use_thinking else "<think></think>"},
]
inputs = processor.apply_chat_template(
    conversation,
    continue_final_message=True,
    tokenize=True,
    return_dict=True,
    return_tensors="pt",
).to(device)
with torch.no_grad():
    outputs = model.generate(
        **inputs,
        max_new_tokens=1024,
        suppress_mixed=True,
        suppress_audio_out=True,
        return_dict_in_generate=True,
    )
    text = processor.decode(
        outputs.sequences[0, inputs["input_ids"].shape[1]:],
        skip_special_tokens=True,
    )
if use_thinking:
    _, separator, text = text.partition("</think>")
    if not separator:
        raise RuntimeError("Reasoning has not finished; increase max_new_tokens.")
print(text.strip())
Audio understanding

Include the recording and a question in the user turn. Questions can address speech, music, background sounds, or events. No specific system prompt is required; to ground answers in the recording, use Answer questions about the provided audio clip. Base every answer only on what can be heard..

conversation = [
    {
        "role": "system",
        "content": "Answer questions about the provided audio clip. Base every answer only on what can be heard.",
    },
    {
        "role": "user",
        "content": [
            {"type": "audio", "audio": "recording.wav"},
            {"type": "text", "text": "What is happening in this recording?"},
        ],
    },
]
inputs = processor.apply_chat_template(
    conversation,
    add_generation_prompt=True,
    tokenize=True,
    return_dict=True,
    return_tensors="pt",
).to(device)

with torch.no_grad():
    outputs = model.generate(
        **inputs,
        max_new_tokens=1024,
        suppress_mixed=True,
        suppress_audio_out=True,
        return_dict_in_generate=True,
    )

print(processor.decode(
    outputs.sequences[0, inputs["input_ids"].shape[1]:],
    skip_special_tokens=True,
))

For multiple-choice questions, include the choices in the text part and ask the model to select an answer.

Translation

Use a system prompt that specifies the source language, target language, and output format:

  • Speech to text: Translate the following speech from {source} to {target} in text form.
  • Text to text: Translate the following {source} text into {target}.

Replace {source} and {target} with the English names of the source and target languages. Follow the ASR example with the translation prompt; for text input, set the user message's content to the text to translate. Translation supports the speech languages listed above; translation to or from English generally works best.

Tool calling from spoken requests

Pass function schemas through tools=... to apply_chat_template(). The chat template appends them to the system prompt, one JSON definition per line inside <tools>…</tools>. Requests may be spoken or written.

With the system prompt Respond with function calls, and interleaved text and audio.\n\nList of tools:, the model either calls tools or answers with interleaved text and speech. Do not prefill the assistant turn: the model chooses whether to start with <tool_call> or <|mixed_start|>. A tool call looks like this, with multiple calls separated by a blank line:

<tool_call>
<function=set_volume>
<parameter=volume>
30
</parameter>
</function>
</tool_call>

Values other than strings are written as JSON. Your application parses and runs the calls, then appends the assistant's tool_calls (with arguments as a dict) and a tool message with the results to the conversation. The template wraps the results in <tool_response>…</tool_response>. Generate again with the same tools: the model either makes more calls or answers.

import json
import re

tools = [{
    "type": "function",
    "function": {
        "name": "set_volume",
        "description": "Set the device speaker volume.",
        "parameters": {
            "type": "object",
            "properties": {
                "volume": {"type": "integer", "description": "Volume from 0 to 100."}
            },
            "required": ["volume"],
        },
    },
}]
functions = {"set_volume": lambda volume: {"volume": volume}}  # your implementations

CALL_RE = re.compile(r"<tool_call>\s*<function=([^>\n]+)>(.*?)</function>\s*</tool_call>", re.DOTALL)
PARAM_RE = re.compile(r"<parameter=([^>\n]+)>\n?(.*?)\n?</parameter>", re.DOTALL)


def parse_tool_calls(text):
    calls = []
    for name, body in CALL_RE.findall(text):
        arguments = {}
        for key, value in PARAM_RE.findall(body):
            try:
                arguments[key] = json.loads(value)
            except json.JSONDecodeError:
                arguments[key] = value  # plain string
        calls.append({"type": "function", "function": {"name": name, "arguments": arguments}})
    return calls


def respond(conversation):
    inputs = processor.apply_chat_template(
        conversation,
        tools=tools,
        add_generation_prompt=True,
        tokenize=True,
        return_dict=True,
        return_tensors="pt",
    ).to(device)
    with torch.no_grad():
        outputs = model.generate(
            **inputs,
            max_new_tokens=1024,
            audio_temperature=1.0,
            audio_top_k=128,
            audio_repetition_penalty=1.1,
            audio_repetition_window=4096,
            return_dict_in_generate=True,
        )
    text = processor.decode(
        outputs.sequences[0, inputs["input_ids"].shape[1]:],
        skip_special_tokens=True,
    )
    return text, outputs


conversation = [
    {
        "role": "system",
        "content": "Respond with function calls, and interleaved text and audio.\n\nList of tools:",
    },
    {"role": "user", "content": [{"type": "audio", "audio": "question.wav"}]},
]
text, outputs = respond(conversation)
while calls := parse_tool_calls(text):
    results = [functions[c["function"]["name"]](**c["function"]["arguments"]) for c in calls]
    conversation += [
        {"role": "assistant", "tool_calls": calls},
        {"role": "tool", "content": json.dumps(results)},
    ]
    text, outputs = respond(conversation)

print(text)
with torch.no_grad():
    waveform = codec.decode(
        outputs.audio_codes[:1, :, :outputs.audio_lengths[0]]
    ).audio_values[0]  # 24 kHz
sf.write("reply.wav", waveform.float().cpu().numpy(), 24_000)

Text-only answers: use the system prompt List of tools: (keep tools=) and pass suppress_mixed=True, suppress_audio_out=True to generate(). Calls and results are handled the same way.

Fine-tuning


LFM3-Audio-2B is designed for easy customization for a given domain, task, or application with Hugging Face Transformers.

Training Use case Notebook
SFT Audio-to-function calling for smart home control Open in Colab
SFT Text-to-speech (TTS) Open in Colab

Performance


Benchmarks

LFM3-Audio-2B improves over LFM2.5-Audio in speech quality, spoken instruction following, and audio understanding, while supporting multilingual speech and tool calling.

Benchmark LFM3-Audio
2B
LFM2.5-Audio
1.5B
Gemma 4
E2B
Gemma 4
E4B
Qwen2.5-Omni
3B
NVIDIA Audex
2B
Voxtral Mini
3B
Total parameters 2B 1.5B 5B 8B 6B 3B 5B
English ASR
WER ↓
6.23 6.13 8.26 7.82 6.30 5.99 5.51
Multilingual ASR
WER / CER ↓
6.03 — 8.08 6.54 7.41 6.40 7.76
English TTS
UTMOSv2 ↑
3.83 3.22 — — 3.42 — —
VoiceBench ↑ 73.13 55.17 63.28 72.90 66.37 22.55 65.78
Tool calling
internal eval ↑
58.50 — 55.60 72.40 44.30 — 44.50
Audio understanding
MMAR ↑
50.60 25.85 44.49 49.10 54.41 53.21 50.10
Evaluation details

English ASR: average word error rate (WER) in percent on the ESB / Open ASR benchmark suite, lower is better.
Multilingual ASR: mean error rate in percent on FLEURS across English, Spanish, Portuguese, German, French, Italian, Chinese, Japanese, and Korean, lower is better. WER is used for all languages except Chinese, Japanese, and Korean, which use character error rate (CER).
English TTS: UTMOSv2 speech quality score on a 1–5 scale, higher is better.
VoiceBench: audio input, text output, percentage score, higher is better.
Tool calling: internal evaluation with audio input, percentage score, higher is better.
Audio understanding: MMAR, percentage score, higher is better.

Note: Evaluations used audio_temperature=0.4, audio_top_k=0, audio_repetition_penalty=1.2 and audio_repetition_window=64, with greedy text decoding except VoiceBench (do_sample=True, temperature=0.1, top_k=0, repetition_penalty=1.1, text_repetition_window=2048).

Streaming performance

The causal encoder processes live microphone input and allows the backbone to prefill while you speak, reducing the wait after you finish. Time to first token can be as low as 50 ms.

LiquidCodec converts generated tokens into speech at about 87× real time on a single CPU thread on Apple M4 Max. It supports streaming decoding so speech can be played as it is generated.

Architecture


LFM3-Audio-2B architecture: 16 kHz audio input passes through a causal, streaming audio encoder into the LFM3 backbone, and text input enters the backbone directly. The backbone outputs text and tool calls, or speech tokens that LiquidCodec, at 12 tokens per 80 ms, decodes into 24 kHz speech.

Causal audio encoder: our LFM-based encoder combines sliding-window attention and short convolution layers to keep memory utilization bounded. Its fully causal design supports live audio input and incremental prefill.

LiquidCodec: our in-house audio tokenizer powers multilingual speech generation in both LFM3-Audio and LFM3-Omni. Built on the LFM3 architecture, it represents each 80 ms of speech with 12 discrete tokens and supports streaming decoding.

Parallel speech prediction: multiple audio tokens are predicted iteratively in parallel, replacing the sequential prediction used by previous LFM Audio models. As the backbone generates tokens, the detokenizer progressively turns them into speech faster than real time, keeping conversations responsive.

Citation


@article{liquidAI2026LFM3,
  author  = {Liquid AI},
  title   = {Introducing LFM3: Every Modality for Specialized Intelligence},
  journal = {Liquid AI Blog},
  year    = {2026},
  note    = {www.liquid.ai/blog/lfm3},
}

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

Catalog is the map. Apps are the tools.

Run models on your own machine, not in the cloud.

Every model page has an "Open in Abliteration" button that hands the model directly to the first-party desktop client, at the quantization your rig can actually run. No API keys, no subscription, no prompt leakage.

Open in Abliteration