Add model card (M16.9)
Browse files
README.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
language:
|
| 4 |
+
- en
|
| 5 |
+
- zh
|
| 6 |
+
- ja
|
| 7 |
+
library_name: onnx
|
| 8 |
+
tags:
|
| 9 |
+
- text-to-speech
|
| 10 |
+
- tts
|
| 11 |
+
- onnx
|
| 12 |
+
- quantized
|
| 13 |
+
- fp16
|
| 14 |
+
- mobile
|
| 15 |
+
- on-device
|
| 16 |
+
- audio-tokenizer
|
| 17 |
+
- moss
|
| 18 |
+
base_model: OpenMOSS-Team/MOSS-TTS-Nano-100M-ONNX
|
| 19 |
+
pipeline_tag: text-to-speech
|
| 20 |
+
---
|
| 21 |
+
|
| 22 |
+
# MOSS-TTS-Nano-100M — FP16 (shared external data)
|
| 23 |
+
|
| 24 |
+
Half-precision-quantized version of
|
| 25 |
+
[OpenMOSS-Team/MOSS-TTS-Nano-100M-ONNX](https://huggingface.co/OpenMOSS-Team/MOSS-TTS-Nano-100M-ONNX),
|
| 26 |
+
re-exported with shared external weight data so **prefill** and **decode_step**
|
| 27 |
+
mmap the same 220 MB blob instead of duplicating weights. Tuned for ARM CPUs
|
| 28 |
+
with native fp16 SIMD (Snapdragon 8 Gen 2/3, Apple A14+, etc).
|
| 29 |
+
|
| 30 |
+
**Audio codec is unchanged from upstream.** Use this repo for the language
|
| 31 |
+
model graphs and pull the codec from
|
| 32 |
+
[OpenMOSS-Team/MOSS-Audio-Tokenizer-Nano-ONNX](https://huggingface.co/OpenMOSS-Team/MOSS-Audio-Tokenizer-Nano-ONNX).
|
| 33 |
+
|
| 34 |
+
## What's here
|
| 35 |
+
|
| 36 |
+
| File | Size | Purpose |
|
| 37 |
+
|---|---:|---|
|
| 38 |
+
| `moss_tts_prefill.onnx` | 476 KB | global LM, full-context prefill |
|
| 39 |
+
| `moss_tts_decode_step.onnx` | 503 KB | global LM, autoregressive single step (KV cache) |
|
| 40 |
+
| `moss_tts_local_fixed_sampled_frame.onnx` | 819 KB | local LM with baked-in sampling |
|
| 41 |
+
| `moss_tts_global_shared_fp16.data` | **220 MB** | fp16 weights shared by prefill + decode_step |
|
| 42 |
+
| `moss_tts_local_fixed_sampled_frame_fp16.data` | 113 MB | fp16 weights for the local sampler |
|
| 43 |
+
| `tokenizer.model` | 471 KB | SentencePiece (unchanged from upstream) |
|
| 44 |
+
| `browser_poc_manifest.json` | 503 KB | prompt templates + 18 builtin voices |
|
| 45 |
+
| `tts_browser_onnx_meta.json` | 4 KB | I/O metadata |
|
| 46 |
+
| **Total** | **~336 MB** | (vs 640 MB upstream fp32 LM, 196 MB int8) |
|
| 47 |
+
|
| 48 |
+
## Variant comparison (this repo's role)
|
| 49 |
+
|
| 50 |
+
| Variant | LM size | Quality vs FP32 | Use when |
|
| 51 |
+
|---|---:|---|---|
|
| 52 |
+
| FP32 (upstream) | 640 MB | reference | offline rendering, high-end devices |
|
| 53 |
+
| **FP16 (this repo)** | **336 MB** | **indistinguishable from FP32** | **mobile devices with native fp16** |
|
| 54 |
+
| INT8 ([sister repo](https://huggingface.co/REALBITS/MOSS-TTS-Nano-100M-ONNX-int8)) | 196 MB | ~3 dB envelope shift, slightly more monotone delivery | size-constrained, fastest |
|
| 55 |
+
|
| 56 |
+
Triple A/B objective analysis (Adam voice, same long demo, seed=42):
|
| 57 |
+
|
| 58 |
+
| Metric | FP32 | FP16 | INT8 |
|
| 59 |
+
|---|---:|---:|---:|
|
| 60 |
+
| RMS dBFS | -20.79 | -20.49 | -20.18 |
|
| 61 |
+
| F0 mean (Hz) | 110.0 | 110.7 | 114.0 |
|
| 62 |
+
| **F0 std (Hz)** | **32.7** | **35.1** | **21.9** ← more monotone |
|
| 63 |
+
| Voice-band envelope MAE vs FP32 | 0 dB | 9.7 dB ← content-length variance | 13.4 dB |
|
| 64 |
+
| Silent-region noise floor RMS | 0.0014 | 0.0016 | 0.0017 |
|
| 65 |
+
|
| 66 |
+
## Notes on fp16 numerics
|
| 67 |
+
|
| 68 |
+
The conversion uses
|
| 69 |
+
`onnxruntime.transformers.float16.convert_float_to_float16(keep_io_types=True)`
|
| 70 |
+
with these ops kept at fp32 (precision-sensitive):
|
| 71 |
+
- `LayerNormalization`
|
| 72 |
+
- `GroupNormalization`
|
| 73 |
+
- `Softmax`
|
| 74 |
+
- `Cast`
|
| 75 |
+
|
| 76 |
+
This preserves the standard "fp16 forward pass with fp32 norm/softmax" recipe
|
| 77 |
+
that's robust across most transformer architectures. The audio output is
|
| 78 |
+
visually indistinguishable from fp32 in spectral envelope (within the noise
|
| 79 |
+
floor of run-to-run sampling variance — the model has stochastic decoding).
|
| 80 |
+
|
| 81 |
+
## Speed expectations
|
| 82 |
+
|
| 83 |
+
| Hardware | FP16 RTF | Notes |
|
| 84 |
+
|---|---:|---|
|
| 85 |
+
| x86 desktop CPU (no AVX-512 BF16) | **~0.75** (slower than fp32 0.38) | ORT-CPU has no fp16 GEMM; expands to fp32 + downconverts |
|
| 86 |
+
| Snapdragon 8 Gen 2/3 ARM cores | TBD | Native fp16 SIMD; expect close to int8 |
|
| 87 |
+
| Apple A14+ | TBD | Native fp16 SIMD |
|
| 88 |
+
| ARM Cortex-X1 / older | varies | Less native support |
|
| 89 |
+
|
| 90 |
+
If you're targeting x86 CPU, **use the int8 variant instead** — fp16 is a loss there.
|
| 91 |
+
|
| 92 |
+
## Quick test (Python ORT)
|
| 93 |
+
|
| 94 |
+
```python
|
| 95 |
+
from onnxruntime import InferenceSession, SessionOptions
|
| 96 |
+
from huggingface_hub import snapshot_download
|
| 97 |
+
|
| 98 |
+
lm_dir = snapshot_download("REALBITS/MOSS-TTS-Nano-100M-ONNX-fp16")
|
| 99 |
+
codec_dir = snapshot_download(
|
| 100 |
+
"OpenMOSS-Team/MOSS-Audio-Tokenizer-Nano-ONNX",
|
| 101 |
+
allow_patterns=["moss_audio_tokenizer_decode_*", "*.json"],
|
| 102 |
+
)
|
| 103 |
+
# Drive prefill → loop {sampler → decode_step} → codec.decode_full
|
| 104 |
+
# (or codec.decode_step for streaming) per upstream onnx_tts_runtime.py.
|
| 105 |
+
```
|
| 106 |
+
|
| 107 |
+
## On-device example
|
| 108 |
+
|
| 109 |
+
This repo is a v2 candidate for the
|
| 110 |
+
[Fictures MOSS-TTS-Nano Android prototype](https://github.com/dev-realbits/Fictures/tree/main/mobile/moss-tts-nano-prototype).
|
| 111 |
+
Switch to it via:
|
| 112 |
+
|
| 113 |
+
```bash
|
| 114 |
+
adb shell setprop debug.mosstts.variant FP16
|
| 115 |
+
```
|
| 116 |
+
|
| 117 |
+
then restart the app and tap Download.
|
| 118 |
+
|
| 119 |
+
## How it was quantized
|
| 120 |
+
|
| 121 |
+
Repro: see
|
| 122 |
+
[`_dryrun/13_quantize_fp16.py`](https://github.com/dev-realbits/Fictures/blob/main/mobile/moss-tts-nano-prototype/_dryrun/13_quantize_fp16.py).
|
| 123 |
+
Three steps:
|
| 124 |
+
1. `onnx.load(load_external_data=True)` for each LM graph
|
| 125 |
+
2. `convert_float_to_float16(keep_io_types=True, op_block_list=[LayerNorm, GroupNorm, Softmax, Cast])`
|
| 126 |
+
3. Save with `save_as_external_data=True`; hash the resulting `.data` files;
|
| 127 |
+
collapse byte-identical pairs (prefill + decode_step share the underlying
|
| 128 |
+
transformer weights) into one shared `moss_tts_global_shared_fp16.data`
|
| 129 |
+
and rewire both graphs' external_data location attributes.
|
| 130 |
+
|
| 131 |
+
## License + attribution
|
| 132 |
+
|
| 133 |
+
Apache 2.0, inherited from upstream
|
| 134 |
+
[OpenMOSS/MOSS-TTS-Nano](https://github.com/OpenMOSS/MOSS-TTS-Nano).
|
| 135 |
+
|
| 136 |
+
## Known limitations
|
| 137 |
+
|
| 138 |
+
Same as the upstream and int8 variant: English / Chinese / Japanese only;
|
| 139 |
+
no microphone voice cloning out of the box (use the 18 builtin voices in
|
| 140 |
+
`browser_poc_manifest.json`); codec stays fp32.
|