KoeAct-JP
日本語の音声から、文字起こしを挟まずに Action JSON(Function Calling)を直接出力する小型モデルです。PC の CPU と ESP32-S3(M5Stack CoreS3)で、クラウドなしに動きます(CoreS3 は音声から Action のピースと p_act までを計算し、棄却の閾値と JSON への変換は接続した PC 側の数行の処理)。
KoeAct-JP maps Japanese speech directly to Action JSON calls for a fixed 11-tool schema, without a transcript in between. It reuses the Ralomi speech encoder (2.05M parameters, upper four blocks fine-tuned) and a 0.54M grammar-constrained decoder, and computes the Action pieces on an ESP32-S3 (the rejection threshold and JSON assembly run on the connected host).
入力音声:「顔を右に45度向けて」
出力 :[{"name":"look","arguments":{"direction":"right","degrees":45}}]
入力音声:「やっぱりライトは消さないで」
出力 :[]
ブラウザで試せるデモ(Hugging Face の Static Space。音声はブラウザの外に出ません):https://huggingface.co/spaces/ayousanz/KoeAct-JP-demo
ベンチマークの要約
比較相手は、同じデータで学習したカスケード(Ralomi の文字起こし → JapaneseTinyAgentLM-kana、B1n)。精度と誤発火は 5 seeds の平均で、このリポジトリの重み(seed 14、test を見る前に val の EM で選んだもの)の値を括弧内に示す。
- 依頼の発話はすべて合成音声で、実際の話者では検証していない。誤発火の評価だけは実録音の非依頼音(MUSAN、FSD50K)を使った(「制限」)
- 数値の根拠は
evidence/(下の「根拠のファイル」)
このリポジトリの中身
モデル
想定する使い方
- 小型ロボット(スタックチャンなど)、ゲームの NPC での、固定スキーマの音声操作(Unity/Godot への組み込みは将来の想定。現状は Python(PyTorch/ONNX)と CoreS3 のファームウェアだけ)
- オンデバイス(PC の CPU、ESP32-S3(M5Stack CoreS3))。API キーもクラウドも不要で、ダウンロードしたあとはオフラインで動く
想定しない使い方
- 自由な語彙の Function Calling(推論時にツールを足すことはできない)
- 安全に関わる機器の操作(誤発火はゼロではない。下の「制限」)
- 話者の識別や、音声の書き起こし
学習データ
- テキスト 59,935 文(train 54,500)、合成 158,783 発話(声の数を変えた 4 条件で共有)。最終モデルは 120 声の条件の発話で、品質チェックに通ったものを、そのままのコピーと増強したコピーで学習(107,964 コピー)
- 数値の一部(角度 25/37/75/105/135/165、レベルと増減量 23/47/66/85)は学習に入れず、評価だけに使う
- ReazonSpeech の音声・書き起こし・特徴量、MUSAN と DEMAND の音声、評価専用の FSD50K の音声、JESC と現行の JapaneseTinyAgentLM-Action-3M の重みに由来するものは、この公開物に含まない
- 商用 API の出力は、学習データにも正解ラベルにも使っていない
評価
合成音声(学習にない声、D01 の val 1,975 発話。evidence/e13/gate.json、evidence/b1n_e10/val_score.json)
- 負例(val 600 クリップ)での誤発火:話し声 0〜2/300、雑音と無音 0/300
- 棄却の規則は両者で違う(KoeAct は
p_act で対象外の誤発火率 ≤ 2%、B1n は JapaneseTinyAgentLM の select_gate:min_prob で val の EM の低下 0.5pt 以内)。EM(ゲートなし)は clean と増強の全コピー
- 合成音声での値なので、実際の話者・雑音・距離ではこれより下がる見込み
合成 test(学習にない声、D01 の test 3,425 文 × clean と雑音の 2 コピー。事前登録し、このモデルと比較相手では 1 回だけ評価。同じ test は M2 で別の構成の評価に一度使った)
- 数値:学習にない値だけを集めた subset の EM は 89.6% 対 63.5%。上の表の「数値の値の正解率」は、test 全体の数値の引数の値の一致
- 差(KoeAct − B1n):+9.5pt(95% 区間 +8.7〜+10.4、テキスト単位の対応 bootstrap)。差の大半は雑音のある条件と、数値・単一の Action。clean の複数動作と言い直しはほぼ同じ
- 評価の方法と基準は、評価の前に事前登録した。集計:
evidence/m3/(verdict.json、bootstrap.json、seed ごとの e13_score.json・b1n_score.json)
誤発火(FA/h:依頼でない連続音声 14.02 時間、MUSAN 1.10 時間と FSD50K の CC0/CC BY 12.93 時間。それぞれ四捨五入)
- 集計:
evidence/m3/fah_e13.json、fah_b1n.json。事前登録した基準(FA/h が B1n 以下)は満たしていない。音の種類ごとの値は事後の内訳(記述)。凍結した Ralomi に同じ 0.54M のデコーダだけを付けた構成(M2 の案A′、不採用)は 0.34 回/時と少ないが、EM は低い(evidence/m2_stage2/verdict.json)
実音声(参考値:開発者 1 名、24 文)
【録音のあとで記入。話者 1 名なので一般化はできない】
PC での処理時間(Apple M1 の CPU、1 発話ずつ、合成 val 200 発話、平均 4.75 秒)
- 発話全体を受け取ってから出力までの時間で、逐次処理ではない。Ralomi は詰めずに計算する(評価と同じ 15 秒に詰める経路では 30.5 ms 対 38.7 ms)。
evidence/pc_speed/。このリポジトリの koeact.runtime は、前処理なし(--no-clean)ならこの計測の経路と同じ計算で、合成 val の 1,975 発話で出力が全件一致する(evidence/release/verify_val_torch.json)
- 差の大半は後段:KoeAct のデコーダ(block 5〜8 を含めて 5.1 ms)と JapaneseTinyAgentLM-kana(13.7 ms)。どちらも音声の長さの 1% 以下
実機(M5Stack CoreS3、ESP32-S3)
集計:evidence/m4_redo/、evidence/m4/cascade_summary.json。事前登録した基準(遅延 P50 0.7 秒以下・P95 1.0 秒以下、内部 RAM の空き 16KB 以上、PSRAM の追加 2.0MB 以下、PC との一致 99% 以上)をすべて満たした。
- カスケードの値:1 秒区切りの公開版 Ralomi での実測は P50 1.54 秒。KoeAct と同じ 0.4 秒区切りの Ralomi はカスケード用には作れないので、KoeAct の Ralomi の最後の区切りの実測に JapaneseTinyAgentLM-kana の実測を足した見積もりが P50 1.30〜1.44 秒。この見積もりと比べると、KoeAct の遅延は約 2.5〜2.7 分の 1。別の条件のカスケードの実測は 1.57〜1.67 秒(
evidence/m4/cascade_summary.json)
- 差の大半は後段(KoeAct のデコーダ 0.24 秒、JapaneseTinyAgentLM-kana 約 1.0〜1.2 秒)
- 遅延の音声は Mac のスピーカーから流した合成音声で、実際の話者ではない。最初の計測(float32 のデコーダ、1 秒区切り)は P50 2.52 秒で中止側だった。デコーダの高速化(int16、録音中の逐次 encode)を事前登録してからやり直した
制限
- 固定のスキーマ(11 tools、2 コールまで)だけ。言い回しの外れた依頼や、知らない語彙は
[] になるか、誤った Action になる
- 依頼の発話は、学習も評価も合成音声だけ(学習の負例と誤発火の評価には、実録音の非依頼音(ReazonSpeech、SLR28、MUSAN、FSD50K)を使った)。実際の話者・マイク・部屋の響きでの精度は検証していない(開発者 1 名の録音を参考値として載せる予定だが、任意で、まだ録っていない)。実環境ではこれより下がる見込み
- 人の声で誤発火しやすい:依頼でない連続音声で約 1.6 回/時、人の話し声や歌だけなら約 4.4 回/時。テレビや会話が続く場所では、ウェイクワードやボタンと組み合わせることを勧める。棄却の閾値を上げると減るが、正しい依頼も
[] になりやすくなる
- 否定(「〜しないで」)は合成 test で 99.5%、言い直しは 91.6%(全体の 93.2% よりやや低い)。どちらも実音声では未確認
使い方
PC(Python 3.13 で確認)
hf download ayousanz/KoeAct-JP --local-dir koeact-jp && cd koeact-jp
pip install -r code/requirements.txt
# WAV → Action JSON(棄却つき、1 行に 1 つ)
PYTHONPATH=code python -m koeact.runtime --model . a.wav b.wav
# マイクに話す(Enter で録音の開始と停止、q で終了。pip install sounddevice が必要)
PYTHONPATH=code python -m koeact.runtime --model . --mic
import sys
sys.path.insert(0, "code")
from koeact.runtime import KoeAct, load_audio
model = KoeAct.from_dir(".")
r = model(load_audio("a.wav")) # 16 kHz mono に変換して渡す
print(r["output"], r["p_act"]) # p_act が閾値(0.97)未満なら output は "[]"
- v0.1.1 から、
koeact.runtime は学習と評価と同じ前処理(音量を −23 dBFS にそろえ、先頭に 0.5 秒、末尾に 0.3 秒の無音を足す)を標準でかけます。切るには --no-clean(Python では model(x, clean=False))を使います。前処理が効く理由:発話が最初のサンプルから始まると、エンコーダが最初の語を取りこぼしやすく、合成 val では前処理なしの入力が約 4.5 pt 低くなります
- 閾値は
config.json の threshold。上げると誤発火は減るが、正しい依頼も [] になりやすい(下の「制限」)
- 入力は 15 秒まで(それより長い部分は使わない)
M5Stack CoreS3(ESP32-S3)
# ESP-IDF v5.5.5 で確認
cd cores3/firmware/e05
idf.py -DRALOMI_ESPDL=$PWD/../../ralomi_e13_stream40.espdl \
-DA2_WEIGHTS=$PWD/../../a2_weights.bin build
idf.py -p <port> flash # アプリ、.espdl(model パーティション)、重み(a2 パーティション)を書き込む
# 画面をタッチすると 4 秒録音し、録音しながら 0.4 秒ずつ認識して、Action のピース ID と p_act をシリアルに出す
pip install pyserial
cd ../../.. && PYTHONPATH=code python -m koeact.runtime --model . --serial <port> # → Action JSON
- CoreS3 が出すのは Action のピース ID と
p_act まで。閾値と JSON への変換は PC 側(koeact.runtime.from_device_line)
- ファームウェアは Ralomi の CoreS3 ファームウェア(
ayousanz/ralomi の esp32s3/firmware)にデコーダ(cores3/firmware/a2、C)を足したもの。ESP-DL、ESP-DSP、M5Unified、M5GFX は ESP-IDF のコンポーネントマネージャがビルド時に取得する(dependencies.lock で版を固定)
.espdl は完成品だけを配る。作り直すには、公開されていない Ralomi の書き出しツールが要る
比較相手(カスケードの後段)
baseline/jtalm-kana-b1n/ は、JapaneseTinyAgentLM(commit e32b6c15)の 3M 構成の重み(model.safetensors、config.json の model)と、かなの SentencePiece トークナイザー。入力は Ralomi の文字起こし(かな)。評価の比較に使ったもので、KoeAct-JP の推論には要らない
根拠のファイル(evidence/)
変更履歴
- v0.1.1(2026-10-25):
koeact.runtime が評価と同じ前処理を標準でかけるようにした(--no-clean で v0.1.0 と同じ入力)。重みと、このカードの数値は v0.1.0 のまま
- v0.1.0(2026-10-25):最初の公開
謝辞と帰属
- Ralomi(ayousanz/ralomi、Apache-2.0)、JapaneseTinyAgentLM(Apache-2.0)。帰属の一覧は NOTICE