第2回:JSONフィールド順序で翻訳表示が2倍速に

前回の記事で、「Intent-First Translation」という音声翻訳のアプローチをご紹介しました。話し始めてから約500ミリ秒で意図を表示し、会話のテンポを維持するというものです。

今回は、この速度を実現するために必要だった技術的な設計について、少し詳しくお伝えします。エンジニアの方にはもちろん、技術に関心のあるビジネスの方にも、「なぜ速いのか」のエッセンスが伝わればと思います。


3つのレイヤーで「段階的に」情報を届ける

Intent-First Translationは、単一の翻訳処理ではありません。速度の異なる3つのレイヤーを重ねて、段階的に情報を提供する構造になっています。

Layer 1: キーワード予測     → 約0ms   (LLM不要)
Layer 2: 意図ラベル(Intent)→ 約500ms (LLMストリーミング)
Layer 3: 完全翻訳            → 約500-800ms(LLMストリーミング続き)

Layer 1:キーワード予測(遅延ほぼゼロ)

音声認識から届く断片的なテキストに対して、LLMを使わず辞書ベースで即座にトピックを予測します。

“meeting” → 「会議」、“budget” → 「予算」、“Tuesday” → 「火曜日」

これだけでも、聞き手は「会議と予算と火曜日の話だな」と瞬時に把握できます。LLMの応答を待つ必要がないため、ほぼゼロ遅延で表示されます。

Layer 2 & 3:LLMによる意図推定と翻訳

音声認識(Deepgram)のPartial結果——話している途中のまだ確定していないテキスト——が更新されるたびに、LLMへJSON形式で意図推定と翻訳を依頼します。

ポイントはストリーミング出力です。LLMがJSONを上から1文字ずつ生成するのを、リアルタイムでパースして、生成され次第フロントエンドへ送信しています。


JSONのフィールド順序が、速度を決めていました

ここが今回最もお伝えしたい点です。

LLMのストリーミング出力は、JSONを上から順番に生成します。つまり、最初に定義されたフィールドが最初に生成され、最後のフィールドは最後に生成されます。

これは、フィールドの配置順序によって、各情報がユーザーに届くタイミングが変わることを意味します。

意図と翻訳を先に配置した場合

{
  "dialogue_act": "PROPOSAL",
  "intent_label": "日程調整の提案",      すぐ表示される
  "slots": {"when": "Tuesday"},
  "full_translation": "火曜に...",        翻訳も早めに届く
  "confidence": 0.85,
  "is_meaning_stable": true
}

翻訳を最後に配置した場合

{
  "dialogue_act": "PROPOSAL",
  "slots": {"when": "Tuesday"},
  "key_terms": ["meeting", "reschedule"],
  "confidence": 0.85,
  "is_meaning_stable": true,
  "intent_label": "日程調整の提案",
  "full_translation": "火曜に..." すべての生成を待つ必要がある
}

後者の場合、翻訳が表示されるまでに全フィールドの生成を待つことになり、体感で約2倍の遅延が発生しました。

JSONのフィールド順序を入れ替える——たったこれだけの変更で、翻訳の表示速度がほぼ2倍に向上しました。LLMの「上から順に生成する」という性質を理解したことで見つかった最適化です。


進行中と確定時で、プロンプトを切り替える

音声認識の結果には2種類あります。

  • Partial(進行中): 話している最中の不完全なテキスト(例: “I think we should…”)
  • Final(確定): 発話が完了した確定テキスト(例: “I think we should reschedule the meeting to Tuesday.”)

この2つに対して、同じプロンプトを使うのは非効率だと気づきました。

状態目的プロンプトの方針
Partial(進行中)速く意図を表示する速度重視:意図 → 翻訳 を先に生成
Final(確定)正確な翻訳を提供する品質重視:文脈分析を先に行い、翻訳の精度を上げる

話している最中はスピード優先で大まかな意図と翻訳を先行表示し、話し終わった時点で品質優先の正確な翻訳に差し替えます。

これは、人間の同時通訳者が行っていることと同じ構造です。まず大意を伝え、確定したら正確に訂正する。


6つのLLMモデルを実際に比較しました

このシステムでは、用途や環境に応じてLLMを切り替えられるようにしています。同じ入力で比較した結果は以下の通りです。

モデル翻訳表示速度品質5時間あたりのコスト
Groq / Llama 4 Maverick413ms$3.43(約515円)
Groq / Llama 3.3 70B480ms
Groq / Llama 3.1 8B377ms
Groq / GPT-OSS 120B662ms
Gemini 2.5 Flash Lite954ms$1.17(約175円)
OpenAI GPT-4o-mini1,976ms$1.74(約261円)

Groq + Llama 4 Maverickは推論速度が800+ tokens/secと非常に速く、リアルタイム翻訳に最も適していました。一方、コストを重視する場合はGemini 2.5 Flash Liteが5時間で約175円と経済的です。

フロントエンドからワンクリックでモデルを切り替えられるUIを用意し、用途に応じた使い分けができるようにしています。


システム全体のデータフロー

技術的な全体像を示します。

[ブラウザ]               [バックエンド(FastAPI)]          [外部API]
   |                          |                           |
   |-- 音声バイナリ --------->|                           |
   |                          |-- 音声データ ------------>| Deepgram
   |                          |<-- Partial/Final text ----|
   |                          |                           |
   |                          |-- テキスト -------------->| LLM (Gemini/Groq)
   |                          |<-- ストリーミングJSON ----|
   |                          |                           |
   |<-- intent_partial -------|  (意図ラベルを即送信)     |
   |<-- translation_partial --|  (翻訳を即送信)          |
   |<-- intent (complete) ----|  (完全な結果)            |

重要なのは、LLMの出力を最後まで待ってからまとめて送るのではなく、JSONの各フィールドが生成されるたびに個別のWebSocketメッセージとして即座にフロントエンドへ送信している点です。


LLMの無駄遣いを防ぐための工夫

Deepgramは非常に高速にPartial結果を返すため、何も対策しないとLLMへのリクエストが毎秒数十回に達してしまいます。これを防ぐために、いくつかの最適化を施しています。

  1. デバウンス処理(300ms): テキスト更新後300ms待ち、その間に新しいテキストが来なければLLMを呼ぶ
  2. 短文スキップ(5単語未満): “I” や “I think” のような短すぎるPartialはスキップ
  3. 重複チェック: 同じテキストを二重に処理しない
  4. 非同期パイプライン: LLMの応答待ちの間も、音声認識のデータは受信し続ける

推測翻訳(Speculative Translation)の実験

実験的な機能として、「推測翻訳」も実装しました。

対話行為(例:提案)と意図ラベル(例:日程調整)の2つの情報だけから、文の内容を推測して翻訳を先行表示するものです。正確さは確定翻訳に劣りますが、「何について話しているか」が確定翻訳より約500ms〜1秒早く伝わります。


この開発で得られた知見

このシステムの開発を通じて最も実感したのは、LLMの出力を「結果」としてではなく「ストリーム」として扱うことの重要性です。

  1. JSONのフィールド順序を最適化し、重要な情報を先に生成させる
  2. 生成途中のJSONを部分的にパースして即座に送信する
  3. Partial/Finalの状態に応じてプロンプトを動的に切り替える

いずれも、LLMの「上から順に生成する」という基本的な性質を理解し、それを活かした設計です。

次回は、ローカルLLMへの挑戦の記録と、このシステムの今後の展望についてお伝えします。


第1回:音声翻訳の本当の課題は精度ではなかった 第3回:自宅GPUでリアルタイム翻訳は動くのか