Automatic Speech Recognition
ONNX
Transformers.js
onnxruntime
onnxruntime-web
asr
speech-recognition
robust-asr
quantized
int4
int8
matmulnbits
gptq
on-device
browser
web
qwen3
qwen3-asr
mega-asr
Instructions to use VidraAI/mega-asr-onnx with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers.js
How to use VidraAI/mega-asr-onnx with Transformers.js:
// npm i @huggingface/transformers import { pipeline } from '@huggingface/transformers'; // Allocate pipeline const pipe = await pipeline('automatic-speech-recognition', 'VidraAI/mega-asr-onnx');
Upload README.md with huggingface_hub
Browse files
README.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
language:
|
| 4 |
+
- en
|
| 5 |
+
- zh
|
| 6 |
+
- ja
|
| 7 |
+
- ko
|
| 8 |
+
- multilingual
|
| 9 |
+
library_name: onnxruntime
|
| 10 |
+
tags:
|
| 11 |
+
- onnx
|
| 12 |
+
- onnxruntime
|
| 13 |
+
- onnxruntime-web
|
| 14 |
+
- automatic-speech-recognition
|
| 15 |
+
- asr
|
| 16 |
+
- speech-recognition
|
| 17 |
+
- robust-asr
|
| 18 |
+
- quantized
|
| 19 |
+
- int4
|
| 20 |
+
- int8
|
| 21 |
+
- matmulnbits
|
| 22 |
+
- gptq
|
| 23 |
+
- on-device
|
| 24 |
+
- browser
|
| 25 |
+
- web
|
| 26 |
+
- qwen3
|
| 27 |
+
- qwen3-asr
|
| 28 |
+
- mega-asr
|
| 29 |
+
- transformers.js
|
| 30 |
+
pipeline_tag: automatic-speech-recognition
|
| 31 |
+
base_model: zhifeixie/Mega-ASR
|
| 32 |
+
base_model_relation: quantized
|
| 33 |
+
---
|
| 34 |
+
|
| 35 |
+
# Mega-ASR β INT4 ONNX (GPTQ-calibrated)
|
| 36 |
+
|
| 37 |
+
INT4 ONNX export of [zhifeixie/Mega-ASR](https://huggingface.co/zhifeixie/Mega-ASR),
|
| 38 |
+
a 1.7B-parameter multilingual ASR foundation model built on Qwen3-ASR-1.7B with
|
| 39 |
+
2.6M training samples covering noise, far-field speech, obstruction, recording
|
| 40 |
+
artifacts, echo, dropout, and transmission dropout.
|
| 41 |
+
|
| 42 |
+
The model is split into three ONNX files (Whisper-style: audio encoder + LLM
|
| 43 |
+
decoder prefill + LLM decoder step) so it can be loaded **directly in the
|
| 44 |
+
browser** via [`onnxruntime-web`](https://onnxruntime.ai/docs/api/javascript/) or as
|
| 45 |
+
a CPU/GPU service via `onnxruntime`. INT4 weight quantization (MatMulNBits, 4-bit
|
| 46 |
+
block-32 asymmetric) compresses the model from ~7.5 GB fp16 down to **~2 GB**
|
| 47 |
+
total β small enough for a one-time browser cache.
|
| 48 |
+
|
| 49 |
+
**Both decoder halves are GPTQ-calibrated** on 168 / 63 English Voices-in-the-Wild
|
| 50 |
+
samples (prefill / step respectively). The step model uses past-KV-cache-aware
|
| 51 |
+
calibration: prefill output is piped into step, so the calibration captures the
|
| 52 |
+
realistic activation distribution of autoregressive decode.
|
| 53 |
+
|
| 54 |
+
## What's in this repo
|
| 55 |
+
|
| 56 |
+
| File | Size | Role |
|
| 57 |
+
| --- | ---: | --- |
|
| 58 |
+
| `onnx/audio_encoder_int4.onnx` (+ `.data`) | **214 MB** | mel features β audio embeddings (24-layer Whisper-style encoder) |
|
| 59 |
+
| `onnx/decoder_prefill_int4.onnx` (+ `.data`) | **968 MB** | Qwen3 1.7B decoder, full-length prefill (no KV cache, **GPTQ-calibrated**) |
|
| 60 |
+
| `onnx/decoder_step_int4.onnx` (+ `.data`) | **968 MB** | Qwen3 1.7B decoder, single-token step (with KV cache, **GPTQ-calibrated**) |
|
| 61 |
+
| `examples/*.wav` | ~3 MB | 8 noisy benchmark clips from [Voices-in-the-Wild-Bench](https://github.com/xzf-thu/Voices-in-the-Wild-Bench) |
|
| 62 |
+
| `tokenizer_config.json` / `vocab.json` / `merges.txt` | β | Qwen3 BPE tokenizer assets |
|
| 63 |
+
| `preprocessor_config.json` | β | Whisper-style mel feature extractor config |
|
| 64 |
+
| `inference.py` | β | Standalone Python ASR pipeline using these ONNX files |
|
| 65 |
+
|
| 66 |
+
## Compression vs original
|
| 67 |
+
|
| 68 |
+
| Component | Original (fp16 PT) | This (INT4 ONNX) | Savings |
|
| 69 |
+
| --- | ---: | ---: | ---: |
|
| 70 |
+
| Audio encoder | ~635 MB | **214 MB** | 3.0Γ |
|
| 71 |
+
| LLM decoder | ~3.4 GB Γ 2 (prefill + step) | **968 MB Γ 2** | 3.5Γ |
|
| 72 |
+
| **Total deploy** | **~7.5 GB** | **~2.0 GB** | **3.7Γ smaller** |
|
| 73 |
+
|
| 74 |
+
The decoder is ~95% MatMul ops so MatMulNBits 4-bit quantization works well.
|
| 75 |
+
The audio encoder is mostly Conv2d / Linear in transformer layers β MatMulNBits
|
| 76 |
+
quantizes the transformer Linear ops (most of the weight) but leaves the small
|
| 77 |
+
Conv2d front-end at fp16.
|
| 78 |
+
|
| 79 |
+
## Quality
|
| 80 |
+
|
| 81 |
+
Benchmarked on the 8 [Voices-in-the-Wild-Bench](https://github.com/xzf-thu/Voices-in-the-Wild-Bench)
|
| 82 |
+
example clips (real-world noisy conditions, all English), word-level
|
| 83 |
+
agreement (1 β WER), prompt forced to `language English`:
|
| 84 |
+
|
| 85 |
+
| Variant | Encoder | Decoder | Avg agreement | 100% samples | Total size |
|
| 86 |
+
| --- | --- | --- | ---: | ---: | ---: |
|
| 87 |
+
| PT bf16 (original) | fp16 | fp16 | 95.1% | 6 / 8 | 7.5 GB |
|
| 88 |
+
| ONNX fp16 (ref) | fp32 | fp16 | **96.7%** | 7 / 8 | 8.2 GB |
|
| 89 |
+
| **ONNX recommended (GPTQ)** | **INT8** | **INT4 GPTQ** | **92.7%** | **6 / 8** | **2.3 GB** |
|
| 90 |
+
| ONNX RTN (previous ship) | INT8 | INT4 RTN | 91.9% | 6 / 8 | 2.3 GB |
|
| 91 |
+
| ONNX small | INT4 | INT4 RTN | 87.8% | 6 / 8 | 2.0 GB |
|
| 92 |
+
|
| 93 |
+
The recommended config (INT8 audio encoder + GPTQ-INT4 LLM decoder) is the
|
| 94 |
+
size/quality sweet spot for browser deployment. Forcing the language
|
| 95 |
+
(rather than auto-detecting) recovers most of the quantization drift.
|
| 96 |
+
|
| 97 |
+
GPTQ calibration on both prefill and step yields **+0.8% over plain RTN** at
|
| 98 |
+
the same model size, most visibly on the `echo` sample where the
|
| 99 |
+
RTN-quantized decoder previously hallucinated *"the size was fine standing
|
| 100 |
+
up at the terrible white wall"* β the GPTQ-quantized decoder produces
|
| 101 |
+
*"the size feels fine standing up against terrible white walls"*, recovering
|
| 102 |
+
the leading clause exactly.
|
| 103 |
+
|
| 104 |
+
**Note**: fp16 ONNX actually beats PT bf16 (96.7 vs 95.1) because forcing
|
| 105 |
+
language skips the model's audio-quality-router language detection,
|
| 106 |
+
which is where the PT model loses points on `echo` and `recording`
|
| 107 |
+
(truncated).
|
| 108 |
+
|
| 109 |
+
## Inference (Python)
|
| 110 |
+
|
| 111 |
+
```bash
|
| 112 |
+
pip install onnxruntime numpy soundfile transformers qwen-asr
|
| 113 |
+
git clone https://huggingface.co/Reza2kn/mega-asr-onnx
|
| 114 |
+
cd mega-asr-onnx
|
| 115 |
+
python inference.py --audio examples/noise.wav
|
| 116 |
+
```
|
| 117 |
+
|
| 118 |
+
## Inference (browser)
|
| 119 |
+
|
| 120 |
+
A live browser demo (loads these ONNX models directly via `onnxruntime-web`
|
| 121 |
+
and WebGPU) is at
|
| 122 |
+
[Reza2kn/mega-asr-bench](https://huggingface.co/spaces/Reza2kn/mega-asr-bench).
|
| 123 |
+
The first visit downloads ~2 GB of model weights, cached by the browser for
|
| 124 |
+
subsequent runs.
|
| 125 |
+
|
| 126 |
+
## Performance
|
| 127 |
+
|
| 128 |
+
| Hardware | Cold (model load) | Warm (3-4 s audio) |
|
| 129 |
+
| --- | ---: | ---: |
|
| 130 |
+
| RTX 5080 (CUDAExecutionProvider) | ~5 s | ~1.5 s |
|
| 131 |
+
| M-series Mac (CPUExecutionProvider) | ~12 s | ~6 s |
|
| 132 |
+
| Browser, WebGPU (RTX 5080) | ~10 s + ~1 GB download (cached) | ~3 s |
|
| 133 |
+
| Browser, WASM CPU | ~10 s + download | ~30 s |
|
| 134 |
+
|
| 135 |
+
## Conversion details
|
| 136 |
+
|
| 137 |
+
- Exported via `torch.onnx.export(..., dynamo=True)` from PyTorch 2.12.
|
| 138 |
+
- Audio encoder rewrites: replaced packed-sequence flash-attention with
|
| 139 |
+
standard batched attention + chunked Conv2d (parity cos β 0.998 vs original).
|
| 140 |
+
- Decoder uses a single `DecoderForExport` wrapper that accepts a flat tuple
|
| 141 |
+
of KV cache tensors; prefill and step are two specialisations of the same
|
| 142 |
+
Python wrapper exported separately.
|
| 143 |
+
- Quantization: `onnxruntime.quantization.matmul_nbits_quantizer.MatMulNBitsQuantizer`
|
| 144 |
+
with `block_size=32`, `is_symmetric=False`, `bits=4`, `algo=GPTQ`.
|
| 145 |
+
Non-MatMul ops (LayerNorm, RMSNorm, residuals, RoPE, the audio-encoder
|
| 146 |
+
Conv2d front-end) stay at fp16.
|
| 147 |
+
- KV cache: dynamic past-length axis (`Dim("T_past")`) via dynamo's
|
| 148 |
+
`dynamic_shapes` API.
|
| 149 |
+
|
| 150 |
+
### GPTQ calibration
|
| 151 |
+
|
| 152 |
+
The default ORT GPTQ implementation in
|
| 153 |
+
`onnxruntime.quantization.neural_compressor.weight_only` is CPU-only (numpy
|
| 154 |
+
matmul + `np.linalg.cholesky` for the Hessian inverse), and runs at ~90 min
|
| 155 |
+
for a 1.7B model on a workstation CPU. For this release we ported the
|
| 156 |
+
GPTQ inner loop + Hessian accumulation to `torch.cuda` and added a
|
| 157 |
+
diagonal-jitter retry on the Cholesky factorisation (fp32 is stricter
|
| 158 |
+
than LAPACK on barely-singular Hessians). On an RTX 5080 Laptop the
|
| 159 |
+
prefill GPTQ runs at ~99% GPU util and finishes in **~35 min**; the step
|
| 160 |
+
GPTQ takes **~3 min** (fewer unique MatMul input names because of GQA
|
| 161 |
+
sharing).
|
| 162 |
+
|
| 163 |
+
- **Prefill calibration**: 168 samples (24 per noise/far_field/obstructed/
|
| 164 |
+
distortion/recording/echo/dropout split), English-only filter on the
|
| 165 |
+
`text` field, audio decoded via `soundfile` (`Audio(decode=False)`)
|
| 166 |
+
to avoid the `torchcodec` import on streaming `cast_column`.
|
| 167 |
+
- **Step calibration**: 63 samples from the same English-only set; each
|
| 168 |
+
sample's calibration feed is built by running the fp16 prefill ONNX,
|
| 169 |
+
capturing all 56 `present.{0..27}.{key,value}` tensors, embedding the
|
| 170 |
+
greedy first predicted token, and pairing it with `attention_mask` of
|
| 171 |
+
length `L + 1` and `position_ids = L`. This gives the step's GPTQ Hessian
|
| 172 |
+
exactly the autoregressive-decode activation distribution it sees at
|
| 173 |
+
inference.
|
| 174 |
+
|
| 175 |
+
## Credits
|
| 176 |
+
|
| 177 |
+
- Original model: [zhifeixie/Mega-ASR](https://huggingface.co/zhifeixie/Mega-ASR) (1.7B params, Apache-2.0)
|
| 178 |
+
- ONNX export + GPTQ quantization: this repo
|
| 179 |
+
- Benchmark: [Voices-in-the-Wild-Bench](https://github.com/xzf-thu/Voices-in-the-Wild-Bench)
|
| 180 |
+
- Live demo: [Reza2kn/mega-asr-bench](https://huggingface.co/spaces/Reza2kn/mega-asr-bench)
|