File size: 7,697 Bytes
21447f6 2d5931f 21447f6 f2679c4 21447f6 2d5931f 21447f6 f2679c4 21447f6 61ab477 f2679c4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | ---
license: other
license_name: lfm1.0
license_link: LICENSE
base_model: LiquidAI/LFM3-Audio-2B
library_name: fluidaudio
pipeline_tag: automatic-speech-recognition
tags:
- coreml
- apple-silicon
- asr
- tts
- text-to-speech
- streaming
- on-device
---
# LFM3-Audio-2B for Core ML
[LiquidAI/LFM3-Audio-2B](https://huggingface.co/LiquidAI/LFM3-Audio-2B) converted to Core ML for Apple devices
(macOS 15 / iOS 18 and newer): offline speech recognition (long-form included), LiveASR (streaming English
transcription in 0.96 s chunks) and text-to-speech, all from one 2B audio language model. Run it with
[FluidAudio](https://github.com/FluidInference/FluidAudio) (`LFM3AudioManager`).
This is a modified version of the original model: the weights were converted to Core ML and the language model was
quantized to int8 (block size 32). See [Quantization and parity](#quantization-and-parity).
Core AI builds of the language model and the depth decoder (macOS 27 / iOS 27; faster ASR and TTS) are in
[FluidInference/lfm3-audio-2b-coreai](https://huggingface.co/FluidInference/lfm3-audio-2b-coreai); that backend uses the
encoder, codec and tables from this repo.
## Files
| Part | File | Precision | Compute unit (default) |
|---|---|---|---|
| LM backbone, layers 0-11 / 12-23 (stateful; functions `decode_q1`, `prefill_q256/64/16/13`) | `coreml/LFM3-A-C4160-int8b32.mlmodelc`, `coreml/LFM3-B-C4160-int8b32.mlmodelc` | int8 weights (block 32), fp16 compute | GPU |
| LM head (128k vocab, per-chunk top-64) | `coreml/LFM3-Head-int8b32.mlmodelc` | int8 | GPU |
| Causal audio encoder (functions `n12` / `n96` / `n375`, tokens per call) | `coreml/AudioEncoder-fp16.mlmodelc` | fp16 | GPU (offline), ANE (LiveASR `n12`) |
| MaskGIT depth decoder (`depth_in`, `depth_pass`) | `coreml/DepthDecoder-fp16.mlmodelc` | fp16 (+ host fp32 sampling) | GPU |
| LiquidCodec decoder (`f1` / `f4` / `f25`, frames per call) | `coreml/CodecDecoder-fp16.mlmodelc` | fp16 | ANE |
| Pack contract, tokenizer | `assets/config.json`, `assets/tokenizer.json` | | |
| Host tables: token embeddings, speech-frame embeddings, depth code embeddings, codec synthesis head | `assets/embed_tokens.f16.bin`, `assets/codebook_embedding.f16.bin`, `assets/depth_tables.f16.bin`, `assets/codec_head.f32.bin` | fp16 / fp32 | CPU |
ASR and LiveASR need about 2.5 GB of files; TTS adds the depth decoder, codec and tables (~0.4 GB). Context: 4096
positions. `ane/` holds an experimental Neural Engine build of the LM that FluidAudio does not download; see
[Experimental: Neural Engine LM](#experimental-neural-engine-lm-ane).
## Use (Swift)
```swift
import FluidAudio
let manager = try await LFM3AudioManager.downloadAndLoad() // .coreML; includeSpeech: true
// Offline ASR (16 kHz mono); language: "English", "French", ... or nil to infer
let result = try await manager.transcribe(samples)
print(result.text)
// LiveASR (English)
try await manager.startLiveTranscription()
let partial = try await manager.appendLiveAudio(microphoneChunk)
let final = try await manager.finishLiveTranscription()
// TTS (24 kHz), streamed as it is decoded
let speech = try await manager.synthesize(
"Hello from LFM3 Audio.", voice: .female, language: "American English",
onAudio: { chunk in /* play */ })
```
CLI: `fluidaudiocli lfm3-audio transcribe|live|tts|benchmark`.
## Speed and accuracy
Apple M5 Pro (24 GB), macOS 27.0, FluidAudio release build, Core ML backend. Wall time includes model warm-up (the
first calls after load), audio decoding excluded.
| Task | Data | Result |
|---|---|---|
| Offline ASR | LibriSpeech test-clean, first 100 utterances (901 s) | WER 1.32%, RTFx 18.4; transcripts 100/100 identical to the original model (HF fp32 on MPS, greedy) |
| LiveASR (160 ms pieces) | LibriSpeech test-clean, first 20 utterances (157 s) | WER 1.46%, RTFx 10.4 |
| TTS | 20 phrases (72 s of speech, female voice) | RTFx 4.3-4.5 across runs, first audio after 37 ms (median); Parakeet TDT v3 round-trip WER 2.5% |
Per speech frame (80 ms): LM 9.4 ms + depth decoder 4.9 ms on the GPU; the codec decodes on the ANE in parallel.
Peak memory footprint for ASR: 1.9 GB.
## Quantization and parity
- LM: int8 per-block-32 weights. Teacher-forced TTS hidden states match fp32 at cosine 0.9999; offline ASR transcripts
are identical to the original model on the 100 utterances above. (An int4 build failed the speech-frame check.)
- Audio encoder, depth decoder and codec: fp16. Depth decoder codes are 99.6% identical to the original on 319 golden
frames (sampling noise injected); codec waveform SNR 43-49 dB vs fp32.
- Host log-mel matches the original feature extractor to 8.3e-5.
## Experimental: Neural Engine LM (`ane/`)
An all-ANE build of the language model (backbone + head), for testing. FluidAudio does not download or load it yet.
On the M5 Pro it is slower than the GPU pack above. It is here for iPhone-class testing, where the ANE should match
GPU latency at lower power; that has not been measured yet.
| Part | File | Weights | ANE placement | ms per call (M5 Pro) |
|---|---|---|---|---|
| Layers 0-11 | `ane/LFM3-L0-12-q1-S1024-lut8g8.mlmodelc` | LUT8, group 8 | 100% | 5.77 |
| Layers 12-23 + final norm | `ane/LFM3-L12-24-q1-S1024-lut8g8.mlmodelc` | LUT8, group 8 | 100% | 6.01 |
| Head (4 x 32,000 logits) | `ane/LFM3-Head-lut8g8.mlmodelc` | LUT8, group 8 | 100% | 2.08 |
- **Speed:** one text token takes 14.43 ms (GPU pack ~10.8 ms), and one speech frame (backbone only) 12.03 ms
(9.07 ms).
- **Calls:** decode only, one row per call, positions up to 1024. Input `x` is fp16 [1, 1, 2048], and the output `h`
feeds the next part. The host supplies the RoPE tables (`cos_g` / `sin_g`, `cos_s` / `sin_s`) and the additive
masks (`mask_g`, `mask_s`).
- **State:** the K/V caches and conv states are MLState. Full-attention layers write at the position given by the
`onehot` input. `ane/config.json` lists each part's inputs and states.
- **Head:** returns raw logits in four 32,000-row slices. Argmax, top-k and token suppression run on the host.
- **Parity vs fp32,** measured with the same driver for both builds (GPU pack in parentheses):
- ASR: 19/20 golden clips token-identical (20/20)
- TTS teacher-forced hidden cosine: min 0.99969 (0.99983)
- Depth codes: 97.15% identical (97.39%)
- **ANE numerics:**
- Weight rows are pre-scaled by a power of two, and the scale is undone after each linear. This avoids fp16 underflow.
- Sigmoid is computed as 0.5 + 0.5·tanh(x/2).
- **Loading:** the first load compiles for the ANE in about 5 s per part; cached loads take 35-60 ms.
## License
[LFM Open License v1.0](LICENSE) (Liquid AI). Commercial use by organizations with annual revenue of USD 10 million or
more requires a separate license from Liquid AI; see the license for the full terms.
## Changelog
| Date | Files | Change | Issue | FluidAudio PR | HF commit |
|---|---|---|---|---|---|
| 2026-10-29 | all | Initial release: Core ML LM pack (int8 b32), audio encoder, depth decoder (per-pass functions), codec, host tables | [FluidAudio #49](https://github.com/FluidInference/FluidAudio/issues/49#issuecomment-6501658263) | [#1076](https://github.com/FluidInference/FluidAudio/pull/1076) | [21447f69](https://huggingface.co/FluidInference/lfm3-audio-2b-coreml/commit/21447f69cc14197e302d755ecc1aaeb416e24e55) |
| 2026-10-30 | `ane/*` | Experimental all-ANE LM (LUT8 group 8, decode q=1, span 1024); not loaded by FluidAudio | [FluidAudio #49](https://github.com/FluidInference/FluidAudio/issues/49#issuecomment-6501658263) | none | [e5259314](https://huggingface.co/FluidInference/lfm3-audio-2b-coreml/commit/e5259314f4efec09e4fc1011ac92795c26bceb1f) |
|