コードから Naia モデルを利用するための開発者ガイド。 4.4 Naia モデルダウンロードに従ってモデルを実行した後、ローカルで提供される OpenAI 互換 API (ゲートウェイなし、キューなし)をそのまま利用します。あらゆる OpenAI SDK やツールで、baseURL を向けるだけです。
naia-os / シェル専用ではありません — OpenAI Realtime/Chat/Audio/Embeddings を話すあらゆるコードがそのまま接続でき、 このモデルの上に新しいアプリケーションを構築して実行できます。
1. 接続・認証
- REST ベース:
http://<host>:8892/v1(同じ PC では127.0.0.1) - Realtime(WS):
ws://<host>:8892/v1/realtime(裸のws://<host>:8892も動作 — パス/v1/realtime+ デフォルトモデルが自動適用) - 接続: ローカル(
127.0.0.1)/ Tailscale では認証は不要です — コンテナがライセンスを自己検証します。キーフィールドを必要とするクライアント(OpenAI SDK など)は任意の値(naia)を渡せます。リモートに公開する場合は、前段に §4.4 の Tailscale/VPN を置いてください。
🔑 キーは 1 つ — 購読キー
- 購読キー — ポータルから取得する購読キー。コンテナの実行時(有効化)にのみ使用します(
-e NAIA_ACCOUNT_TOKEN=<subscription-key>)。購読を確認し、期限付きライセンス(証明書)を取得します。 - 別途の接続キーはありません。 一度有効化されると、コンテナは証明書でローカルに自己検証するため、クライアント(naia-os、OpenAI SDK)は URL で接続するだけで済みます — 同じ PC では
127.0.0.1、別の端末からは Tailscale/VPN(§4.4)。接続ごとにゲートウェイを呼び出すことはありません。 - 以下の例の
api_keyはプレースホルダーです(OpenAI SDK がフィールドを要求するため)— オフラインコンテナはこれをチェックしないので、"naia"のような任意の値で動作します。
2. エンドポイント(OpenAI 互換)
| エンドポイント | 用途 | バックエンド |
|---|---|---|
GET /health | 準備状態 {"ready":true,"services":{tts,stt,llm},"vad":true}(認証なし) | — |
GET /v1/models | モデル一覧 | — |
WS /v1/realtime | リアルタイム音声セッション(VAD、バージイン、感情) | cascade |
POST /v1/chat/completions | チャット(ストリーミング) | gemma4-e4b |
POST /v1/audio/speech | テキスト読み上げ(TTS) | VoxCPM2 |
POST /v1/audio/transcriptions | 音声認識(STT) | Whisper |
POST /v1/embeddings | 埋め込み | bge-m3 |
Chat(curl):
curl -s http://127.0.0.1:8892/v1/chat/completions \
-H "Authorization: Bearer naia" -H "Content-Type: application/json" \
-d '{"model":"naia-0.9-omni-24g","messages":[{"role":"user","content":"hi"}],"stream":false}'
OpenAI SDK(Python)— baseURL を差し替えるだけ:
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8892/v1", api_key="naia")
print(client.chat.completions.create(
model="naia-0.9-omni-24g",
messages=[{"role": "user", "content": "hi"}],
).choices[0].message.content)
文字起こし(STT):
curl -s http://127.0.0.1:8892/v1/audio/transcriptions \
-H "Authorization: Bearer naia" \
-F file=@sample.wav -F model=naia-0.9-omni-24g
3. リアルタイム音声 — 接続フロー(WS)
4.3 ライブデモと同じフローです。(オフラインはゲートウェイのキュー / 割り当てがなく、すぐに開始します。)
-
接続 —
ws://<host>:8892を開きます。 -
最初のフレーム(認証・言語) — ブラウザの WebSocket はヘッダーを送れないため、最初のメッセージとして送信します:
{ "setup": { "apiKey": "naia", "locale": "en" } } -
サーバーが
session.createdを送ってきたら、session.updateでセッションを設定します:{ "type": "session.update", "session": { "modalities": ["text", "audio"], "input_audio_format": "pcm16", "output_audio_format": "pcm16", "instructions": "<persona instructions>", "turn_detection": { "type": "server_vad" }, "input_audio_transcription": { "language": "en" }, "ref_audio_url": "<URL of a voice sample to mimic (optional)>" } } -
やり取り
クライアント → サーバー 音声入力 {"type":"input_audio_buffer.append","audio":"<base64 PCM16 24kHz>"}(サーバー VAD が発話の終わりを検出)テキスト入力 conversation.item.createの後にresponse.createバージイン response.cancelサーバー → クライアント response.audio.deltabase64 PCM16 24kHz の音声チャンク response.audio_transcript.delta/response.text.delta回答テキスト(ストリーミング) conversation.item.input_audio_transcription.completedあなたの発話の文字起こし emotion.updated感情 / プロソディタグ(§5) response.done1 ターンの終了
4. 言語 — 30 言語(デフォルト = 自動 / グローバル)
モデルは 30 言語に対応します(アラビア語、ビルマ語、中国語、デンマーク語、オランダ語、英語、フィンランド語、フランス語、 ドイツ語、ギリシャ語、ヘブライ語、ヒンディー語、インドネシア語、イタリア語、日本語、クメール語、韓国語、ラオ語、マレー語、ノルウェー語、 ポーランド語、ポルトガル語、ロシア語、スペイン語、スワヒリ語、スウェーデン語、タガログ語、タイ語、トルコ語、ベトナム語)。
- デフォルト(未設定)= グローバル / 自動 — あなたが話した言語を検出し、その言語で返答します(ターンごと)。
- 特定の言語に固定するには、
setup.localeまたはsession.updateのinput_audio_transcription.languageに ISO-639-1 コード(例:ko/en/ja)を指定します。
5. 出力フォーマット(感情・プロソディタグ)
音声会話向けに出力フォーマットが調整されています — クライアントがこれを理解していれば、より豊かに表現できます。
- プロソディタグ: 回答テキストには、感情が変化する箇所に
[laughing]、[sigh]、[breath]、[pause]、[hesitation]のような小文字の英語ブラケットタグが混在します(音声プロソディのため)。モデルは[웃음]のような韓国語タグ、(smiling)のような括弧付きのト書き、*smiles*のようなアスタリスクを使わないよう 指示されています。既知の語彙:laughing/laugh/laughter/chuckle/giggle · sigh/exhale · breath/inhale · pause · hesitation · gasp/cough/sneeze/yawn/sniff/hum · cry/sob/moan/whisper/shout/cheer(その他のタグはそのまま通過します)。 - 各タグについて、サーバーは 1:1 の
emotion.updatedイベントを送ります(state== タグ名、小文字):{ "type": "emotion.updated", "state": "laughing", "tag": "[laughing]", "known": true } - TTS パスはタグを保持し、音声プロソディのために合成に渡しますが、chat の
text.deltaはタグを取り除いたクリーンなテキストを送ります。(出力には絵文字、マークダウン、括弧付きの自己ナレーションはありません。) - クライアントのマッピング(naia-os リファレンス):
emotion.updated.state(プロソディタグ)をアバターの表情にマッピングします —laughing/chuckle/giggle/cheer → happy、sigh/exhale/cry/sob → sad、gasp → surprised、shout → angry、hesitation → think。breath・pauseのような感情を伴わないプロソディは表情を変えません (直前のものを維持 — 呼吸のたびにニュートラルに点滅しないように)。 - 堅牢な処理を推奨: LLM の出力は常に正確とは限りません。
emotion.updatedを優先しつつ、それが 欠けている場合は、文字起こしそのものの中のタグ(大文字の[HAPPY]/ 小文字のプロソディタグ)や 漏れたト書き((smiles)・*sigh*)を自動検出して表情に反映します。手がかりがなければ、 現在の表情を維持します(cf. naia-osshell/src/lib/vrm/expression.tsのextractExpression)。
6. 関連情報
- リファレンス実装 / サンプルコード(オープンソース): naia-os の音声クライアント
shell/src/lib/voice/(Apache 2.0)— この API と通信する実際のクライアント(naia-omni.ts)と、感情 / プロソディの処理 (emotion-tags.ts; 表情マッピングと堅牢な抽出はvrm/expression.ts)が含まれています。 新しいモデルのテストや Tauri アプリ構築の出発点として利用してください。4.3 ライブデモでライブにお試しいただけます。 - ラインアップと価格: 4.1 モデル価格
- クラウド(予定): 4.6 オンライン