smcleod commited on
Commit
2b6be93
·
verified ·
1 Parent(s): 430d002

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +123 -3
README.md CHANGED
@@ -1,3 +1,123 @@
1
- ---
2
- license: apache-2.0
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ base_model: ibm-granite/granite-speech-4.1-2b-nar
4
+ base_model_relation: quantized
5
+ library_name: transformers
6
+ pipeline_tag: automatic-speech-recognition
7
+ tags:
8
+ - onnx
9
+ - onnxruntime
10
+ - speech
11
+ - asr
12
+ - automatic-speech-recognition
13
+ - granite
14
+ - ibm
15
+ - quantized
16
+ - int8
17
+ - non-autoregressive
18
+ - nar
19
+ language:
20
+ - en
21
+ ---
22
+
23
+ # IBM Granite Speech 4.1 2b NAR - ONNX export
24
+
25
+ ONNX export of [`ibm-granite/granite-speech-4.1-2b-nar`](https://huggingface.co/ibm-granite/granite-speech-4.1-2b-nar) produced by Sam McLeod
26
+ (<https://smcleod.net>). Repository: `smcleod/ibm-granite-speech-4.1-2b-nar-onnx`. Both FP32 and INT8 weight-only
27
+ graphs are included. The graphs target opset 20, IR 10, `ai.onnx` operators
28
+ only - no `com.microsoft` ops - so they load under the `ort` 2.0-rc.x Rust
29
+ crate as well as standard `onnxruntime` 1.17 - 1.25.
30
+
31
+ > **Additional precision tiers in progress.** A statically-calibrated INT8 variant (better quality vs the dynamic INT8 already in this repo) and a half-precision encoder are in active development. The repo will be updated when those graphs pass the multi-clip parity gate.
32
+
33
+ Two graphs: `encoder.onnx` runs the conformer + CTC heads + BPE-collapsing projector and emits `bpe_logits_dense` plus pooled audio embeddings. `editor.onnx` runs the bidirectional NLE editor over a packed prompt (`<|audio|>` placeholders are replaced with the projector output) and emits per-position vocab logits. Decoding is a single argmax pass; no KV cache, no autoregression.
34
+
35
+ ## Files
36
+
37
+ - `encoder.onnx` + `encoder.onnx_data` (FP32) and `encoder_int8.onnx` + `encoder_int8.onnx_data` (INT8 weight-only quantisation)
38
+ - `editor.onnx` + `editor.onnx_data` (FP32) and `editor_int8.onnx` + `editor_int8.onnx_data` (INT8 weight-only quantisation)
39
+ - Tokeniser / processor: `tokenizer.json`, `tokenizer_config.json`, `special_tokens_map.json`, `preprocessor_config.json`
40
+ - Export scripts: `export_nar_encoder.py`, `export_nar_editor.py`, `quantise.py`
41
+ - `granite_export_metadata.json` (graph IO, parity numbers, toolchain)
42
+ - `LICENSE` (Apache 2.0)
43
+
44
+ ## Parity
45
+
46
+ Parity is taken against the upstream PyTorch reference on a single LibriSpeech
47
+ clip (`10226_10111_000000.wav`, 8.43 seconds, 844 mel frames). FP32 graphs
48
+ match the reference within numeric tolerance; INT8 graphs are validated in
49
+ argmax-only mode (logit values shift but token argmax is preserved, so the
50
+ decoded transcript is unchanged).
51
+
52
+ | graph | precision | max-abs-err | argmax mismatches | transcript match |
53
+ | --- | --- | --- | --- | --- |
54
+ | encoder (bpe_logits_dense) | FP32 | 0.00204 | 0/211 | n/a |
55
+ | encoder (bpe_logits_dense) | INT8 | 1.84 | 0/211 | n/a |
56
+ | editor | FP32 | 0.00147 | 0/257 | Y |
57
+ | editor | INT8 | 94.5 | 15/257 | Y |
58
+
59
+ INT8 note: the encoder graph emits two CTC heads. `bpe_logits_dense` (used downstream) holds argmax-stable through quantisation; `char_logits` (unused downstream) drifts noticeably and is not part of the inference path. The editor INT8 graph reproduces the reference transcript despite logit max-abs delta, because argmax decoding is invariant to the residual quant error.
60
+
61
+ ### Multi-clip transcript parity
62
+
63
+ Three additional 16 kHz mono clips covering longer utterances (39 to 94 seconds), single and two-speaker conversational content. Word error rate (WER) and Levenshtein edit distance computed against the upstream PyTorch reference. Numbers measured end-to-end through the full ONNX pipeline (no PyTorch encoder fallback).
64
+
65
+ | Clip | Duration | FP32 byte-exact vs PT | INT8 byte-exact vs PT | INT8 WER vs PT | INT8 vs FP32 Lev |
66
+ | --- | ---: | :---: | :---: | ---: | ---: |
67
+ | is-it-more-wood | 46.9 s | Y | N | 3.6% | 13 |
68
+ | two-speakers-1 | 93.8 s | N | N | 3.5% | 26 |
69
+ | two-speakers-2 | 38.8 s | Y | N | 2.0% | 10 |
70
+
71
+ Raw multi-clip data including full transcripts: see `granite_export_metadata.json` `multi_clip_parity` block.
72
+
73
+ Reference transcript:
74
+
75
+ > after his nap timothy lazily stretched first one gray velvet foot then another strolled indolently to his plate turning over the food carefully selecting choice bits nosing out that which he scorned upon the clean hearth
76
+
77
+ Both FP32 and INT8 paths reproduce this transcript exactly on the test clip.
78
+
79
+ ## Toolchain
80
+
81
+ - transformers 5.8.0
82
+ - torch 2.11.0
83
+ - onnx 1.21.0
84
+ - onnxruntime 1.25.1
85
+ - exporter: torch.onnx.export TorchScript path (dynamo=False)
86
+ - opset: 20 (`ai.onnx` only)
87
+ - IR version: 10
88
+ - external data layout: single `<stem>.onnx_data` sidecar per graph
89
+
90
+ ## Compatibility
91
+
92
+ Targeted at the [`ort`](https://crates.io/crates/ort) 2.0-rc.x Rust crate.
93
+ Compatible with `onnxruntime` Python 1.17 through 1.25. No `com.microsoft`
94
+ ops are used. Graphs were emitted via the TorchScript path
95
+ (`torch.onnx.export(..., dynamo=False)`); the dynamo exporter was deliberately
96
+ avoided because it injects `aten::*` ops `ort` does not understand.
97
+
98
+ ## Reproducing the export
99
+
100
+ The included scripts and `quantise.py` regenerate every artefact in this
101
+ bundle. From a checkout of <https://github.com/sammcj/granite-speech-4.1-onnx>:
102
+
103
+ ```bash
104
+ python export_nar_encoder.py \
105
+ --model-dir <path-to-ibm-granite/granite-speech-4.1-2b-nar> \
106
+ --out-dir exports/granite-speech-4.1-2b-nar
107
+ python export_nar_editor.py \
108
+ --model-dir <path-to-ibm-granite/granite-speech-4.1-2b-nar> \
109
+ --out-dir exports/granite-speech-4.1-2b-nar
110
+ python quantise.py --input exports/granite-speech-4.1-2b-nar/encoder.onnx --output exports/granite-speech-4.1-2b-nar/encoder_int8.onnx
111
+ python quantise.py --input exports/granite-speech-4.1-2b-nar/editor.onnx --output exports/granite-speech-4.1-2b-nar/editor_int8.onnx
112
+ ```
113
+
114
+ Sandboxed environments may need:
115
+
116
+ ```bash
117
+ HF_HOME=$TMPDIR/hf_home HF_MODULES_CACHE=$TMPDIR/hf_modules <command above>
118
+ ```
119
+
120
+ ## Licence
121
+
122
+ Apache 2.0 for both the upstream IBM model and this ONNX export. See
123
+ [`LICENSE`](LICENSE) for the full text.