Haas-ja-v1.0 OneCompression ONNX
Haas-ja-v1.0 を GPU なし・CPU だけで動くようにした版です。OneCompression で 4 bit にした ONNX(ほかに 8 bit / fp32)。
hf download kizuna-intelligence/Haas-ja-v1.0-OneCompression-ONNX --local-dir haas-ja-onnx
cd haas-ja-onnx
pip install -r requirements.txt
python example.py audio.wav
普通の ONNX 変換との違い
- そのままでは ONNX にできないモデルです。 元のモデルは GPU 専用の計算(KDA の高速カーネル)を使っていて、通常の書き出しでは変換できません。その部分を普通の計算(1 歩ずつの再帰)に書き直し、元のモデルと 1 歩ごとに差を確かめてから ONNX にしました。
- 4 bit はただ丸めただけではありません。 OneCompression(GPTQ+QEP)で、音声を流して誤差が小さくなるように 4 bit の値を決めています。ただ丸めた 4 bit(誤り率 3.98%)より良く、fp32(4.05%)と比べても精度を保ったまま、大きさは約 6.5 分の 1(380 MB)です。
- PyTorch も NeMo も要りません。 音の特徴量の計算から文字への変換まで、ONNX Runtime と NumPy だけで動きます。
日本語
既定は int4-onecomp、CPU 4スレッドです。Python 3.12 で動作確認しています。
大きさ・精度・速さ
| 形式 | 大きさ (MB) | JSUT CER strict | FLEURS CER strict | 全体 CER strict | 話す速さの何倍 (RTFx) |
|---|---|---|---|---|---|
| 元の GPU 版 (NeMo bf16) | 1232.38 | 4.38% | 3.94% | 4.04% | 未測定 |
| fp32 | 2472.91 | 4.38% | 3.95% | 4.05% | 23.10倍 |
| int8 | 663.87 | 4.29% | 4.06% | 4.11% | 41.57倍 |
| int4-onecomp | 380.31 | 4.22% | 3.74% | 3.85% | 30.15倍 |
数値は手元で測った値です。1 MB = 10⁶ bytes。各ONNX形式の大きさは共通ファイル込みで、全形式をまとめた容量ではありません。 CER は文字誤り率で、小さいほど良好です。JSUT と FLEURS を各200発話、計400発話で評価し、全体は音声時間で重み付けしています。 速さは Core i7-12700F、Pコア固定の4スレッド、30秒音声、ONNX Runtime 1.31.1 / CPUExecutionProvider で測定しました。 ウォームアップ1回後の5回の中央値です。RTFx は音声の長さ ÷ 処理時間で、モデルの読み込み時間は含みません。速さはパソコンや音声によって変わります。
使い方
ダウンロードしたフォルダで実行します。GPU・CUDA・PyTorch・NeMo は不要です。
hf download kizuna-intelligence/Haas-ja-v1.0-OneCompression-ONNX --local-dir haas-ja-onnx
cd haas-ja-onnx
pip install -r requirements.txt
python example.py audio.wav
python example.py audio.wav --format int8 または --format fp32 で形式を選べます。
Python からは同じフォルダで次の3行を使います。
from haas_cpu.pipeline import Transcriber
from haas_cpu.external.audio_io import read_audio
print(Transcriber().transcribe_long(read_audio("audio.wav")).text)
モデルへの入力は16 kHzのモノラル音声です。read_audio と example.py はそれ以外のサンプルレートを自動変換し、複数チャンネルは平均します。
例えば44.1 kHzの音声も python example.py audio_44100.wav でそのまま使えます。変換には同梱の依存関係 SciPy を使います。
長い音声は約28秒ごとの静かな箇所で自動分割し、各区間の文字列を連結します。
音声ファイルはローカルで処理します。
モデルの場所は Transcriber(models_dir=...)、環境変数 HAAS_CPU_MODELS、この配布フォルダの順で決まります。
別の作業ディレクトリから python /path/to/hf_release/example.py audio.wav を実行しても、環境変数がなければスクリプトと同じフォルダのモデルを使います。
example.py だけを持っている場合は、--repo を付けるとモデルを取得してから文字起こしします。
python example.py audio.wav --repo kizuna-intelligence/Haas-ja-v1.0-OneCompression-ONNX
既定の実行ではダウンロードしません。
取得済みの snapshot フォルダは Transcriber(models_dir=snapshot_path) に直接渡せます。
中身と注意点
元のモデルのGPU専用部分を普通の計算に書き直してONNXへ変換しました。
4 bit の重みは OneCompression(GPTQ+QEP、group size 128)で決め、ONNX Runtime の MatMulNBits に格納しています。
ONNX Runtime で動かす前提です。MatMulNBits は ONNX Runtime 独自の命令です。
形式名はエンコーダの形式を示し、特徴量計算・TDTデコード・文字列への変換は haas_cpu/、共通のモデルと設定は common/ に含みます。
4 bit では読み間違いが出ることがあります。早口言葉の例(2倍速)では「屏風」が「寮部」になりました。 400発話での平均CERが低くても、個々の音声で元のモデルと一致するとは限りません。 無音付近で分割する長音声でも、区間の境界では文脈が途切れます。
manifest.json は配布ファイルの大きさとSHA256を記録しています(manifest自身を除く)。全ファイルの照合は次のコマンドで行えます。
python -c 'from haas_cpu.external.bundle import Bundle; Bundle.open(verify=True); print("SHA256 OK")'
ライセンス
Apache-2.0。元のモデル third-intelligence/Haas-ja-v1.0 のライセンスに従います。
全文は LICENSE、元のモデルと OneCompression(MIT、Fujitsu)の表示は NOTICE にあります。
English
An ONNX version of Haas-ja-v1.0 for CPU-only Japanese speech recognition, with 4-bit, 8-bit and fp32 encoders.
The default is int4-onecomp with four CPU threads. Tested with Python 3.12.
How this differs from a plain ONNX export
- The original model cannot be exported as-is. It relies on GPU-only kernels (fast KDA kernels). We rewrote that part as ordinary step-by-step recurrence, checked it against the original model step by step, and then exported to ONNX.
- The 4-bit model is not simple rounding. OneCompression (GPTQ + QEP) chooses the 4-bit values using real audio to minimize error. It beats plain rounding (CER 3.98%) and keeps accuracy versus fp32 (4.05%) at about 1/6.5 of the size (380 MB).
- No PyTorch or NeMo. Everything from feature extraction to text runs on ONNX Runtime and NumPy.
Size, accuracy and speed
| Format | Size (MB) | JSUT strict CER | FLEURS strict CER | Overall strict CER | Real-time factor (RTFx) |
|---|---|---|---|---|---|
| Original GPU model (NeMo bf16) | 1232.38 | 4.38% | 3.94% | 4.04% | Not measured |
| fp32 | 2472.91 | 4.38% | 3.95% | 4.05% | 23.10× |
| int8 | 663.87 | 4.29% | 4.06% | 4.11% | 41.57× |
| int4-onecomp | 380.31 | 4.22% | 3.74% | 3.85% | 30.15× |
Values were measured locally. One MB is 10⁶ bytes; each ONNX size includes the shared files, not all three encoders. CER is character error rate (lower is better). Evaluation uses 200 JSUT and 200 FLEURS utterances; the overall value is weighted by audio duration. Speed was measured on a Core i7-12700F with four threads pinned to performance cores, a 30-second clip and ONNX Runtime 1.31.1 CPUExecutionProvider. The reported value is the median of five runs after one warm-up. RTFx is audio duration divided by processing time, excluding model loading. Speed varies with hardware and audio.
Usage
Download, then run inside the folder:
hf download kizuna-intelligence/Haas-ja-v1.0-OneCompression-ONNX --local-dir haas-ja-onnx
cd haas-ja-onnx
pip install -r requirements.txt
python example.py audio.wav
Choose --format int8 or --format fp32 to change the encoder. No GPU, CUDA, PyTorch or NeMo is needed.
From Python in the same folder:
from haas_cpu.pipeline import Transcriber
from haas_cpu.external.audio_io import read_audio
print(Transcriber().transcribe_long(read_audio("audio.wav")).text)
The model accepts 16 kHz mono audio. read_audio and example.py automatically resample other rates using SciPy and average multiple channels.
For example, python example.py audio_44100.wav handles 44.1 kHz input directly.
Long recordings are split near quiet points roughly every 28 seconds; resulting text is concatenated. Audio is processed locally.
Model lookup uses an explicit models_dir, then HAAS_CPU_MODELS, then this distribution folder, independently of the working directory.
python example.py audio.wav --repo kizuna-intelligence/Haas-ja-v1.0-OneCompression-ONNX downloads the model with huggingface_hub.snapshot_download before transcribing.
Normal local execution does not download anything. An existing snapshot path can be passed directly to Transcriber(models_dir=snapshot_path).
Implementation and limitations
GPU-specific operations were rewritten as ordinary operations for ONNX export.
The 4-bit encoder uses OneCompression GPTQ + QEP (group size 128), packed into ONNX Runtime MatMulNBits.
ONNX Runtime is required: MatMulNBits is an ONNX Runtime-specific operator.
The format names refer to the encoder; shared models and configuration are in common/. Feature extraction, TDT decoding and text conversion are in haas_cpu/.
Quantization can change individual transcriptions. In a tongue-twister example played at twice the original speed, the 4-bit model transcribed 「屏風」 as 「寮部」. A lower average CER on these 400 utterances does not guarantee identical or better output on every recording. Chunk boundaries can interrupt context in long recordings.
manifest.json records byte sizes and SHA256 hashes for every distribution file except itself. Verify all files with:
python -c 'from haas_cpu.external.bundle import Bundle; Bundle.open(verify=True); print("SHA256 OK")'
License
Apache-2.0, following the license of third-intelligence/Haas-ja-v1.0.
See LICENSE for the full text and NOTICE for the original-model notice and OneCompression (MIT, Fujitsu) notice.
Model tree for kizuna-intelligence/Haas-ja-v1.0-OneCompression-ONNX
Base model
third-intelligence/Haas-ja-v1.0