HEROZ Tech Blog

日本将棋連盟公認「将棋ウォーズ」や、AIを活用したシステム企画・開発を行う、AI企業HEROZの公式テックブログです。

S2S APIでどこまで作れるのか? 〜gpt-realtime 1.5 と System Prompt / Tool Callingだけで試した3つの音声アプリ

はじめに

前回の記事では、S2S(Speech-to-Speech)APIを比較し、体験品質・知能性能・レイテンシといった観点から各モデルの違いを整理しました。 またRAG編では、Tool Callingを含めた実務的な観点での選び方を扱いました。

今回は少し方向を変えて、実際にどこまで「アプリケーションとして成立するのか」を試した内容を紹介します。

S2Sはここ1年で急速に進化していますが、「実際に業務として使えるのか」という点はまだ見えづらい部分もあります。

そこで今回は、できるだけシンプルな構成に限定し、どこまで成立するのかを検証しました。

  • モデルは gpt-realtime-1.5 のみ
  • 構成は System Prompt + Tool Calling
  • いわゆる「複雑なエージェント構成」は使っていません

この条件で、以下の3つの音声アプリを試作しました。

  • App1: 電話応対
  • App2: 通訳
  • App3: AI面接官

結論から言うと、想像していたよりもかなり実用に近いところまで成立しました。

全体として見えたこと

今回の3アプリはいずれもシンプルな構成ですが、共通して次のような特徴がありました。

  • 会話の進行はほぼ System Promptだけで制御可能
  • 「確定的な出力」だけを Tool Callingで外に出すと安定する
  • モデルの知能というより、責務分離の設計で体験が大きく変わる

特に印象的だったのは、 「どこまでを会話に任せ、どこからを構造化するか」の切り分けでした。

この点を踏まえつつ、それぞれのアプリを見ていきます。

App1: 電話応対

最初に作ったのは、いわゆる一次受電の電話応対です。

役割はシンプルで、

  • 宛先
  • 名前
  • 折り返し先電話番号

を聞き出し、電話メモとして残す、というものです。

構成としては、

  • 会話進行 → System Prompt
  • メモ確定 → save_call_memo(Tool)

という分離にしています。

実際の出力イメージ

電話メモ

やっていることはかなり単純

  • 1ターン1質問
  • 必須項目が揃ったらToolを呼ぶ
  • 名前と電話番号は復唱

いわゆる新人研修レベルの電話応対ルールを、そのままプロンプトに書いています。

想像以上だった点

実際に動かしてみると、かなり自然に成立しました。

  • 相手が話した内容を踏まえて質問順を調整する
  • すでに出た情報を重複して聞かない
  • 電話番号を正確に聞き取り、復唱する

特に印象的だったのは、電話番号の扱いの安定性です。 多少聞き取りが曖昧でも、無理に補完せずに聞き直す動きが自然に出ます。

また、1回の通話コストも数円程度で、 単純な一次受電の一部は置き換え可能な感触がありました。

設計上のポイント

このアプリで重要だったのは、次の分離です。

  • 会話 → プロンプトに任せる
  • 確定出力 → Toolで外に出す

これにより、

  • 会話は柔軟に
  • 出力は安定して構造化

という状態を作れます。

App2: 通訳

次に試したのが、音声通訳です。

最初は単純な逐次通訳を想定していましたが、最終的には3セッション構成にしています。

  • Channel A: 日本語 → 対象言語
  • Channel B: キャラクター
  • Channel C: 対象言語 → 日本語

UIイメージ

3チャンネルUI

2セッションではうまくいかなかった

当初は「通訳+キャラ」の2セッションで試しましたが、

  • 入力と出力の向きが混線する
  • モデル同士が会話し始める

といった問題が発生しました。

結果として、

➡︎ 双方向通訳を1セッションに持たせない

という方針に変えています。

特に、同一セッション内で双方向の通訳を担わせると、入力と出力の向きの解釈が不安定になり、結果としてモデル同士が会話を継続してしまうような挙動が発生しやすい状態でした。

同時通訳的な体験

途中から逐次通訳ではなく、ストリーミング寄りの同時通訳にすると体験が大きく変わりました。

  • こちらが話している途中に通訳が始まる
  • それに対してキャラクターが反応する
  • その応答がまた通訳されて戻ってくる

従来の「順番に待つ」通訳ではなく、 被りながら会話が進む感覚になります。

これはかなり新鮮でした。

設計上のポイント

このアプリのポイントはシンプルです。

  • 通訳は「忠実変換」に徹する
  • 会話はキャラクター側に寄せる
  • 双方向を分離する

結果として、

➡︎ セッション分割がそのまま品質に効く

という構造になっていました。

App3: AI面接官

最後に作ったのが、AI面接官です。

これは、

  • App1のTool(構造化出力)
  • App2の複数セッション

を組み合わせた形になっています。

UIイメージ

面接フィードバック

構成

  • 面接官(AI)
  • 応募者(AI or 人間)

に加えて、

  • 求人票
  • 職務経歴書

をプロンプトに差し込んで面接を進めます。

最後に、

➡︎ submit_interview_feedback

を呼び出して評価を出します。

想像以上だった点

これもかなり驚きがありました。

  • 面接の流れを自然に進行する
  • 回答に応じて深掘りする
  • 最後に構造化された評価を出す

特に面接官側は、かなり“ちゃんとした面接官”として振る舞います。

一方で、あまりにも正確に評価してくるため、 体感としてはやや厳しめに感じる場面もありました。

AI応募者の挙動

応募者もいくつかパターンを用意しましたが、

  • 優秀な候補者
  • やや弱い候補者

の差がかなり自然に出ます。

特に「書類は通るが決め手に欠ける」ような微妙なラインも再現されており、 このあたりは実務的にも興味深い結果でした。

設計上のポイント

このアプリでは、

  • 会話(面接進行) → プロンプト
  • 評価(最終出力) → Tool

という分離に加えて、

➡︎ コンテキスト(求人票・職務経歴書)をそのまま渡す

ことが効いています。

まとめ

今回の3つの試作から見えてきたのは、

S2Sはまだ万能ではないものの、 「型のある会話業務」はかなりの精度で成立するということでした。

特に重要なのは、

  • モデルの性能そのもの
  • よりも
  • どの責務をどこに置くか

です。

整理すると、

  • 会話 → プロンプト
  • 確定出力 → Tool
  • 複雑な役割 → セッション分割

この3点で、多くのユースケースは一定の形になります。

少なくとも今回の範囲では、「複雑なエージェント構成を組まなくても、ここまでは作れる」というラインは見えたように思います。

おわりに

今回の内容はあくまで試作レベルですが、 S2Sが「デモ」から「実装」に近づいてきている感触はありました。

一方で、

  • 安定性
  • 長時間運用
  • エッジケース対応

といった点はまだ検証が必要です。

今後もこのあたりは継続的に試していきたいと思います。

S2S API比較:RAG編 〜Speech-to-SpeechでRAGを使うなら、何を選ぶべきか

はじめに

前回の記事では、S2S(Speech-to-Speech)APIを単体で比較し、体験品質・知能性能・レイテンシといった観点から各モデルの違いを整理しました。素のS2S APIとして見ると、GPT Realtime 1.5 はバランスが良く、Gemini 3.1 Flash Live は体験品質が高く、Gemini 2.5 Flash Live は知識系に強く、Nova 2 Sonic は低遅延が目立つ、という構図でした。

techblog.heroz.jp

ただ、実際のシステム開発では、単体の対話性能だけでモデルを選ぶ場面はそれほど多くありません。業務システムや社内向けアシスタントを考えると、外部知識を参照するRAG(Retrieval-Augmented Generation)を前提にした設計になることがほとんどです。すると、見るべきポイントは少し変わります。S2S単体では「自然に話せるか」「賢く答えられるか」が中心でしたが、RAGではそれに加えて「正しい文書に到達できるか」「検索結果を会話の中でうまく扱えるか」が重要になります。

さらに、RAGではモデルの素の能力だけでなく、実装のしやすさも無視できません。Tool Callingの仕様、ツール結果の返し方、イベント処理、再開制御などがモデルごとにかなり異なるため、表のスコアだけでは実務上の扱いやすさまでは見えてきません。実際に組み込んでみると、同じ「Tool Calling対応」でもかなり性格が違い、その差がそのまま開発コストや安定性に跳ね返ってきます。

本記事では、S2SでRAGを使う前提で各モデルを比較し、どのモデルがどの用途に向くのかを整理します。前回の基本編の続きとして、今回は「RAGを入れると評価軸がどう変わるか」を中心に見ていきます。

比較対象と評価設計

今回の比較対象は、前回と同じく以下の5モデルです。

  • GPT Realtime 1.5
  • GPT Realtime Mini
  • Nova 2 Sonic
  • Gemini 2.5 Flash Live
  • Gemini 3.1 Flash Live

評価は、Tool Calling 40問、RAG 35問で実施しました。採点には Claude 4.5 Sonnet を用いた LLM as a judge を利用し、各項目を 1〜5点の5段階評価(5点満点) で採点しています。前回と同様、単に「答えられたか」だけではなく、実際の利用場面を意識して複数の観点に分解して見ています。

今回のRAG評価で主に見たのは、次の3つです。

  • 検索性能 検索精度、正答文書到達、根拠提示、multi-hop推論
  • 会話型RAG 文脈依存、曖昧質問対応、ハルシネーション耐性、結果統合
  • システム特性 レイテンシ、コスト、実装時の扱いやすさ

ここで重要なのは、RAGでは単体性能の延長で順位が決まるわけではない、という点です。S2S単体で好印象だったモデルが、RAGを入れるとそのまま有力とは限りません。逆に、基本編では不利だったモデルが、RAGでは十分候補に入ることもあります。今回はその差がかなりはっきり出ました。

結論

先に結論をまとめると、今回の位置づけは次の通りです。

  • 第一候補:Gemini 2.5 Flash Live 検索精度、根拠提示、会話型RAGのいずれも高く、RAG性能が最も高かった
  • 安定性重視:GPT Realtime 1.5 極端な弱点が少なく、実装も含めて扱いやすい
  • 速度重視:Nova 2 Sonic 基本編では厳しかったが、RAGでは実用圏まで健闘した
  • 今回の用途では弱い:GPT Realtime Mini 軽量さはあるが、RAG性能はかなり厳しい

要するに、RAGでは「最強モデル」を一つ決めるというより、何を優先するかで選び方が変わるということです。今回の比較では、知識性能なら Gemini 2.5 Flash Live、安定性なら GPT Realtime 1.5、速度なら Nova 2 Sonic という整理が最もしっくりきました。

RAG性能(検索能力)

まずは、RAGの土台になる検索性能を見ます。今回は、検索精度(基本1hop)、正答文書到達、根拠提示、multi-hop推論を中心に評価しました。

検索性能表

まず目立つのは、Gemini 2.5 Flash Live が検索性能全体で一歩抜けている点です。検索精度だけでなく、正答文書到達や根拠提示も高く、RAGで重要な指標がきれいに揃っています。単にそれらしい答えを返すのではなく、検索した文書を比較的うまく使えている、という印象です。

一方で、他モデルはそれぞれ強みと弱みがはっきり出ました。ここは表をそのまま読み上げるより、要点だけ押さえた方が分かりやすいと思います。

  • Gemini 2.5 Flash Live 検索精度、正答文書到達、根拠提示のバランスが最も良く、今回の比較では最もRAG向きでした。似た文書が複数ある状況でも比較的正しい文書に着地できており、知識アクセスを伴う用途では第一候補です。

  • GPT Realtime 1.5 検索精度と根拠提示は一定水準でしたが、正答文書到達はやや弱く、類似文書への誤参照耐性には課題が残りました。検索自体はできても、似た情報が並ぶ状況で安定して正しい文書を使えるかという点では、Gemini 2.5 Flash Live に一歩譲る結果です。

  • Gemini 3.1 Flash Live 基本編では体験品質の面で好印象だったモデルですが、RAG性能だけを見ると今回は伸び切りませんでした。Gemini系だからRAGにも強いだろうと見たくなるところですが、少なくとも今回の条件では Gemini 2.5 Flash Live の方が明確に上でした。

  • GPT Realtime Mini 軽量モデルとしての魅力はありますが、検索精度、根拠提示、multi-hop推論のいずれも低めで、RAGの検索基盤としては力不足でした。今回の用途ではかなり厳しい印象です。

  • Nova 2 Sonic 基本編の印象より健闘しました。トップではありませんが、検索性能としては十分実用圏で、少なくとも「低遅延だがRAGには弱い」と単純には言えない結果でした。

今回の結果から見えてくるのは、RAGでは単体の知能性能と検索性能が必ずしも一致しないということです。素の会話で賢く見えるモデルが、検索文書を挟んだ途端に不安定になることがありますし、その逆もあります。RAGでは「何を知っているか」よりも、「必要な知識にどう到達するか」の比重が大きくなります。

会話型RAG

ただし、RAGは検索性能だけでは決まりません。S2Sで重要なのは、検索結果を会話の中にどう統合できるかです。そこで今回は、会話型RAG(文脈依存・参照解決)、曖昧質問対応、ハルシネーション耐性、結果統合、ツール選択も合わせて見ました。

会話型RAG表

ここでも最も強かったのは Gemini 2.5 Flash Live でした。会話型RAG、曖昧質問対応、ハルシネーション耐性が全体に高く、検索結果を会話の流れの中で使う能力まで含めて強さが出ています。音声対話では、ユーザーが毎回きれいに検索語を話してくれるわけではなく、「あれ」「さっきの件」「前の資料」のような曖昧な参照が普通に出てきます。そのときに、会話履歴と検索をつなげて扱えるかどうかは、体験を大きく左右します。

各モデルの傾向を整理すると、次のようになります。

  • Gemini 2.5 Flash Live 会話型RAGでも最も強く、曖昧な問いや文脈依存の参照に比較的安定して対応できました。今回のRAG評価では、検索性能だけでなく会話としての扱いやすさまで含めてトップです。

  • GPT Realtime 1.5 突出はないものの、全体的に安定していました。曖昧質問対応や結果統合は大崩れせず、会話として破綻しにくい印象があります。ピーク性能ではなく、バランスの良さが強みです。

  • Gemini 3.1 Flash Live 基本編の体験品質ほどの強さは今回は出ませんでした。会話型RAGでは中位に収まり、素のS2Sとしての良さと、RAG込みでの強さは別物だということがよく分かる結果です。

  • GPT Realtime Mini 会話型RAG、曖昧質問対応、ハルシネーション耐性のいずれも低く、今回の用途では厳しいという評価を補強する結果でした。

  • Nova 2 Sonic 会話型RAGでも一定の健闘を見せました。トップではないものの、基本編からの印象よりはかなり実用寄りで、速度重視の選択肢としては十分に検討できます。

この結果から見えてくるのは、RAGでは単発の検索精度だけでなく、会話として扱えるかどうかがかなり重要だということです。検索で上位文書を取れても、その結果を文脈に接続できなければ、ユーザー体験としては弱いままです。S2SでRAGを使うなら、ここは外せない観点です。

レイテンシ(重要な注意点)

RAGを導入すると、レイテンシは必ず増加します。これはどのモデルでも避けられません。 ここでのレイテンシは、問い合わせから最初のトークンが返ってくるまでの時間(TTFT相当)で測定しています。RAGではこの値が、検索処理の影響を受けて増加します。

レイテンシ比較表

今回の比較では、Gemini 2.5 Flash Live は 2503.5ms から 3859.8ms、GPT Realtime 1.5 は 738.5ms から 1401.5ms、Nova 2 Sonic は 207.1ms から 740.5ms へと伸びました。増加率だけを見ると Nova 2 Sonic がかなり大きく見えますが、最終的なレイテンシ自体はまだ十分速い水準にあります。

一方で、GPT Realtime Mini は増加がほとんど見られませんでした。ただし、これは単純に強みと見るより、検索性能や会話型RAGの結果と合わせて解釈する必要があります。レイテンシが小さいこと自体は魅力ですが、RAGとして十分に機能していないのであれば評価は変わります。

ここで押さえておきたいのは、RAGでは遅くなること自体が例外ではなく前提だということです。検索処理が入る以上、S2S単体より速くなることはありません。したがって、レイテンシは「どのモデルが遅いか」を競うというより、RAG込みでどこまで許容できるかで見る方が実務的です。

RAGの流れ

S2SにRAGを組み込むと、処理の流れは概ね次のようになります。 S2S単体の対話に検索処理が追加されることで、RAGでは応答までの流れが一段増えます。

RAGシーケンス図

この図で見ておきたいのは、S2S単体の対話に検索処理が追加される、という点です。音声対話ではこの追加処理がそのまま待ち時間や応答テンポに影響するため、RAGではレイテンシが一つの注意点になります。

ただし、本記事の主眼はあくまで「どのモデルがRAGに向くか」です。レイテンシは重要ですが、それだけでモデル選定が決まるわけではありません。検索性能、会話型RAG、実装の安定性と合わせて見る必要があります。

実装してみて分かったこと(Tool Calling編)

ここからは、表の数字だけでは分かりにくい実装上の差です。前回の記事では、S2S一般の実装差、割り込みや停止、ターン制御なども扱いました。今回はそこには踏み込まず、Tool Callingを使ったRAG実装で実際に効いた差に絞って整理します。

GPT Realtime 1.5

GPT Realtime 1.5 は、Tool Calling自体は比較的素直でした。function calling の流れは追いやすく、イベント構造も理解しやすいため、今回の5モデルの中では最も見通しが立てやすい部類です。

特に重要だったのは次の点です。

  • tool実行後に明示的な再開処理が必要だった GPT Realtime 1.5 では、tool call を受けて検索を実行し、function_call_output を返しただけでは、そのまま最終回答が生成されないケースがありました。ここで response.create を送って会話を再開しないと、ツールは呼ばれたのに最終応答が返らない状態になります。 これは実装してみるまで見落としやすく、評価系でもかなり影響が大きいポイントでした。tool call 前後の response.done を区別せずに処理すると、「無応答だった」と誤判定しやすくなります。Specでも、OpenAI Realtime は function_call_output 投入後に追加の response.create が必要だったことが明記されています。

このモデルは、実装上の癖がまったくないわけではありませんが、癖の出方が比較的分かりやすく、修正方針も立てやすいのが強みでした。RAG性能そのものでは Gemini 2.5 Flash Live に譲る場面があっても、実務で「まず崩れにくいものを選びたい」ときにはかなり有力です。

GPT Realtime Mini

GPT Realtime Mini も系統としては GPT Realtime 1.5 に近く、Tool Callingの考え方も大きくは変わりません。ただし、今回のRAG用途では肝心の性能面が伸びませんでした。

実装面で特別大きな落とし穴があるというより、ちゃんと実装しても、RAGとしての見返りが小さいというのが率直な印象です。軽量モデルとしての魅力はありますが、S2SでRAGをしっかり使いたいという前提では、選びにくい結果でした。

Gemini 2.5 Flash Live / Gemini 3.1 Flash Live

Gemini系は、性能面では特に Gemini 2.5 Flash Live が強かった一方で、Tool Calling実装では最も気を使う部分が多いグループでした。OpenAI互換の実装をそのまま持ち込めず、Gemini向けに合わせ直す必要があります。

特に効いたのは次の点です。

  • OpenAI互換のschemaをそのまま受け付けなかった Gemini 2.5 Flash Live / Gemini 3.1 Flash Live では、OpenAI向けの tool schema をそのまま渡しても受理されず、Gemini向けに変換する必要がありました。たとえば additionalProperties などを落とさないと通らず、共通のツール定義をそのまま各モデルに流す設計では破綻しやすいです。 Tool Callingをマルチプロバイダで共通化したい場合、この差分吸収レイヤはほぼ必須でした。Specでも、Gemini向け schema への変換が必要だったことが明記されています。

  • FunctionResponseにtool callのidが必要だった Gemini系では、nameresponse だけ返せばよいわけではなく、対応する tool call の id を明示的に返す必要がありました。ここが欠けると、見た目上は正しいレスポンスを返していても受理されません。 OpenAI系と同じ感覚で実装するとハマりやすい点で、Tool Callingのレスポンス形式そのものが微妙に違うことを意識する必要があります。

  • tool call と他イベントが同居し、取りこぼしやすかった Gemini 3.1 Flash Live では、usage_metadatatool_call が同一 response に同居するケースがあり、usageを先に処理すると tool call 自体を取りこぼして無応答に見えることがありました。 また、Gemini系は全体としてイベント粒度がやや扱いづらく、Tool Callingだけを独立して雑に処理すると不安定になりやすい印象があります。イベントを逐次1件ずつ単純に返す設計ではなく、どの情報を優先して拾うかを考えて受信ループを組む必要がありました。

Gemini系は、RAG性能だけ見れば今回かなり有力です。ただし、Tool Calling実装まで含めると、強いモデルであるほど丁寧な受け側が必要になる、という印象でした。特に Gemini 2.5 Flash Live を使うなら、schema変換とレスポンス整形は最初から前提にしておいた方がよさそうです。

Nova 2 Sonic

Nova 2 Sonic は、Tool Callingまわりの仕様が最も厳格でした。自由に設計するというより、仕様に正確に合わせること自体が実装になります。

特に重要だったのは次の点です。

  • tool schemaの渡し方がかなり特殊だった Nova 2 Sonic では、inputSchema.json を JSON文字列で渡す必要があり、一般的なJSONオブジェクトとしてそのまま載せる実装だと通りませんでした。また、toolUseOutputConfiguration も必要で、ツール利用時の周辺設定まで含めて揃えないと動きません。 ぱっと見では小さな差に見えますが、共通実装を組もうとするとここが大きな分岐になります。OpenAI系やGemini系と同じ前提では作れません。

  • tool resultの返却形式が専用で、少しでもずれると落ちた Nova 2 Sonic では、tool result を単純なテキスト応答として返すのではなく、contentStart(type=TOOL) -> toolResult -> contentEnd のような専用構造で返す必要がありました。これを単発イベントで返したり、誤って textInput 的に返すと受理されません。 しかもエラーは必ずしも親切ではなく、ValidationExceptionModelStreamErrorException のような抽象的な形で返るため、原因の切り分けに時間がかかりました。Specでも、Nova 2 Sonic は tool use まわりが最も癖が強かったと整理されています。

Nova 2 Sonic は、性能評価だけ見ると今回かなり健闘しています。ただし、その裏側では「仕様に正確に合わせる」実装負荷が相応にあります。速度を優先して選ぶ価値はありますが、Tool Calling部分は雑に共通化せず、専用分岐を用意した方が安定します。

まとめ

今回の比較で見えてきたのは、S2SでRAGを使うと評価軸がかなり変わるということです。基本編では、体験品質や素の知能性能、低遅延性が前面に出ていましたが、RAGを入れると「正しい文書に到達できるか」「その結果を会話の中で扱えるか」がより重要になります。

今回の結論をあらためて整理すると、次の通りです。

  • 知識性能を重視するなら Gemini 2.5 Flash Live
  • 安定性を重視するなら GPT Realtime 1.5
  • 速度を重視するなら Nova 2 Sonic

逆に、GPT Realtime Mini は今回の用途ではかなり厳しいというのが率直な印象でした。

RAGでは、単純なランキングよりも、何を優先するかで選ぶ方が実務的です。知識性能、安定性、速度のどれを取りにいくかで、最適なモデルは変わります。今回の比較が、S2SでRAGを組み込む際のモデル選定の参考になればありがたいです。

モデル別の使い分け(まとめ)

モデル 総合評価 強み 弱み 向いている用途
Gemini 2.5 Flash Live ★★★★☆ RAG性能が最も高い 実装がやや複雑 知識検索・RAG中心の対話
GPT Realtime 1.5 ★★★☆☆ 安定性が高い RAG精度は中程度 安定重視の音声対話
Nova 2 Sonic ★★★☆☆ 低レイテンシ Tool周りが厳格 速度重視のRAG
GPT Realtime Mini ★★☆☆☆ 軽量・低コスト RAG性能が低い 非RAG・軽量用途

S2S APIを比較して分かった実務的な選び方

はじめに

音声AIの実装では、これまで「音声 → テキスト → LLM → 音声」というパイプライン構成が一般的でした。 これに対して、音声入力から音声出力までを一気通貫で扱う S2S(Speech-to-Speech)API が登場し、リアルタイムな会話体験の実現が現実的になってきています。

一方で、各社のS2S APIはまだ新しい領域にあり、単純な性能比較だけでは整理しづらい状況です。応答の正確さだけでなく、会話の自然さ、レイテンシ、コスト、さらには実装時の扱いやすさまで含めて見ないと、実務的な判断は難しいと感じています。

そこで本記事では、主要なS2Sモデルを同一条件で比較し、まずは基本性能に絞って整理しました。RAGやTool Callingについては別記事で扱い、本記事では「素のS2S APIとしての違い」にフォーカスします。

比較対象

今回の比較対象は以下のモデルです。

  • GPT Realtime 1.5 (gpt-realtime-1.5)
  • GPT Realtime Mini (gpt-realtime-mini)
  • Nova 2 Sonic (amazon.nova-2-sonic-v1:0)
  • Gemini 2.5 Flash Live (gemini-2.5-flash-native-audio-preview-12-2025)
  • Gemini 3.1 Flash Live (gemini-3.1-flash-live-preview)

なお、Gemini 3.1 Flash Live は比較的新しいモデルであり、検証時点では Vertex AI 未対応で、Gemini API 経由での利用となりました。また、output token usage が取得できないケースがあり、コストの扱いには制約があります。

実験設計

今回の評価では、体験品質と知能性能を分けて評価しています。 S2Sでは「正しい答えを出すか」だけでなく、「会話として自然か」が重要になるため、この2軸を分離しました。

体験品質は人手評価で、会話自然度や感情表現、発話や割り込みといった観点を中心に3段階で評価しています。

一方で知能性能は自動評価とし、基本QA、指示追従、会話メモリ、言語混在耐性、構造制御などを対象に5段階で評価しました。評価には Claude 4.5 Sonnet を用いた LLM as a judge を利用しています。

総合スコアは単純平均ではなく、評価件数(体験30問、知能120問)を考慮して統合しています。

今回の評価に使用した対話テーマは、以下のような実務寄りのシナリオを中心に構成しています。

  • 一般的なQA(知識質問・業務FAQ)
  • 指示追従(条件付き回答、フォーマット指定)
  • 複数ターン会話(文脈保持・言い換え)
  • 言語混在(日本語+英語)

特定ドメインに強く依存しないように設計しつつ、実際の業務利用を想定したケースを中心に評価しています。

➡︎ 体験と知能を分離した上で統合することで、S2Sの特性をより正確に評価しています。

実験結果

今回の比較では、単純な精度や応答品質だけでなく、実際の利用シーンを想定した複数の観点から評価を行いました。

具体的には、以下の3つの軸で整理しています。

  • 体験品質(人手評価): 会話の自然さ、感情表現、発話品質、割り込みや停止の扱いやすさなど、実際に使った際の体験を評価しています。

  • 知能性能(自動評価): 基本QA、指示追従、会話メモリ、言語混在耐性、構造制御など、モデルとしての能力を評価しています。こちらは Claude 4.5 Sonnet を用いた LLM as a judge により採点しています。

  • システム特性: レイテンシやコストといった、実運用に直結する指標を評価しています。

これらを統合した総合スコアに加えて、各観点ごとの結果も併せて見ることで、モデルごとの特性をより立体的に把握できるようにしています。

➡︎ 本記事では「どのモデルが優れているか」ではなく、「どの観点で強みがあるか」に注目して比較しています。

総合比較

総合比較テーブル

総合スコアでは GPT Realtime 1.5 が最も高くなりました。 体験品質・知能性能ともに大きな弱点がありません。

個別項目で突出しているわけではありませんが、どの観点でも安定しており、実運用で扱いやすいバランスに収まっています。

Gemini 3.1 Flash Live は僅差で続き、特に体験スコアの高さが目立ちました。会話の自然さや感情表現といった部分では強さがあり、ユーザー体験という観点では魅力的です。

一方で、挙動の安定性や実装面では注意が必要な場面もあり、スコアだけでは評価しきれない側面があります。

Gemini 2.5 Flash Live は知能面では依然として高水準ですが、レイテンシの影響で総合スコアはやや下がっています。

GPT Realtime Mini は軽量モデルとしてバランスが良く、コストを抑えたい場合の現実的な選択肢です。 Nova 2 Sonic は総合スコアでは低めですが、低遅延という別軸の強みがあります。

整理すると、各モデルの位置づけは次の通りです。

  • GPT Realtime 1.5:バランス型で実運用向け
  • Gemini 3.1 Flash Live:体験品質が高い最新モデル
  • Gemini 2.5 Flash Live:知識系に強いがレイテンシ重め
  • GPT Realtime Mini:コスパ重視の軽量モデル
  • Nova 2 Sonic:低遅延特化

➡︎ 総合順位よりも「どの特性を持つか」で見るべき結果です。

体験品質と知能性能の関係

散布図

図を見ると、体験品質と知能性能は2軸上で右上に集中しており、いずれのモデルも一定以上の品質を持っていることが分かります。

そのため、この図は優劣を比較するというよりも、各モデルの「性格の違い」を見るものになります。

GPT Realtime 1.5 は体験・知能ともにバランスが良く、実用域の中心に位置しています。 特定の強みよりも、安定性が際立つモデルです。

Gemini 2.5 Flash Live および Gemini 3.1 Flash Live はやや知能寄りに分布しており、QAや会話メモリといった観点での強さが影響しています。

GPT Realtime Mini はその中間に位置し、軽量モデルとして性能とコストのバランスを取っています。

Nova 2 Sonic は他モデルより下側に位置しますが、これは今回の評価軸によるものであり、低遅延という特性はこの図には含まれていません。

整理すると、各モデルの関係は以下のようになります。

  • GPT Realtime 1.5:バランス型
  • Gemini系:知能寄り
  • GPT Realtime Mini:中間
  • Nova 2 Sonic:低遅延特化

➡︎ 性能差よりも「モデルの性格差」が支配的です。

能力分解(知能)

能力分解テーブル

知能性能を分解すると、各モデルの得意分野がより明確になります。

Gemini 2.5 Flash Live は基本QAのスコアが高く、知識を引き出して回答する能力が際立っています。

Gemini 3.1 Flash Live は会話メモリが強く、複数ターンにわたる文脈保持に優れています。

一方で GPT Realtime 1.5 は構造制御の安定性が高く、形式に沿った出力や応答の整理といった点で優位です。 実務で扱う際に破綻しにくいという特徴は、この結果とも一致します。

GPT Realtime Mini は指示追従は比較的良好ですが、メモリや構造制御は控えめです。

Nova 2 Sonic はQA力自体は一定水準にあるものの、言語耐性が低く、言語混在への対応では弱さが見られました。

整理すると、モデルの特徴は次の通りです。

  • Gemini系:内容の強さ(QA・メモリ)
  • GPT Realtime系:出力の安定性
  • Nova 2 Sonic:知能面はやや弱い

➡︎ 「何を出すか」と「どう出すか」で強みが分かれています。

レイテンシとコスト

レイテンシ・コスト表

レイテンシでは Nova 2 Sonic が突出しており、約200msという値は体感的にも非常に軽快でした。 リアルタイム性を重視する用途では、この差は明確に効いてきます。

GPT Realtime 1.5 と GPT Realtime Mini はいずれも700ms台で、リアルタイム会話として十分成立する水準です。

特に GPT Realtime Mini はコストも抑えられており、速度と価格のバランスが良いモデルです。

Gemini 2.5 Flash Live はレイテンシが重く、応答開始までの待ち時間が長くなります。 Gemini 3.1 Flash Live は改善されているものの、依然としてGPT系より遅く、さらに output token usage が安定しないため、コスト見積もりには注意が必要です。

整理すると、次のような関係になります。

  • Nova 2 Sonic:最速(低遅延)
  • GPT Realtime系:バランス型
  • Gemini系:低コストだが遅い

➡︎ レイテンシとコストは明確なトレードオフです。

実装してみて分かったこと

実際にS2S APIを実装してみると、単純な性能比較では見えない差がはっきりと出てきます。 特に大きかったのは、音声対話における「ターン制御」の扱いです。

音声UIでは、「いつ話し終わったか」「途中で止めるか」「割り込んだ場合どうするか」といった制御が不可欠になります。これらは単なるAPI呼び出しでは解決できず、イベント処理・再生制御・状態管理が密接に絡みます。

➡︎ 精度より先に、ターン制御で実装が分かれます。

途中停止と割り込みの設計

途中停止(Stop / cancel)

音声UIでは、アシスタントの発話を途中で止められることが前提になります。ただし実装してみると、「止める」という処理は2つのレイヤーに分かれます。

  • モデル側の生成を止める
  • クライアント側の再生を止める

この違いを整理しないと、設計が破綻します。

GPT Realtime 1.5 / Mini では、response.cancelconversation.item.truncate により、生成そのものを停止できます。そのため、

  1. APIに停止イベントを送る
  2. 以降のトークン生成が止まる
  3. 再生も停止する

という一貫した制御が可能です。

一方で Nova 2 Sonic や Gemini Flash Live では、少なくとも今回の検証範囲では生成停止を前提としたAPI設計にはなっていません。そのため実装としては、

  1. 音声再生を停止する
  2. 受信済みのバッファを破棄する
  3. 以降の出力は無視する

という「聞き捨てる」設計になります。

この差は責任分担の違いとして整理できます。

  • GPT:停止制御をAPI側に委ねられる
  • Gemini / Nova:停止制御をクライアント側で持つ

➡︎ 途中停止は「止める」か「聞き捨てる」かで設計が分かれます。

割り込み(Barge-in)

割り込みは、ユーザーがアシスタント発話中に話し始めた際の挙動です。音声UIの自然さはここで決まります。

今回の実装ではローカルVADは使わず、API側の検知に委ねています。各モデルの挙動は以下の通りです。

  • GPT Realtime:server VAD による検知
  • Nova 2 Sonic:Bedrock側の turn detection / barge-in
  • Gemini Flash Live:activity detection

重要なのは、割り込みは単なる停止ではないという点です。実際には以下のような状態遷移になります(「話している → 止める → 次に切り替える」という流れ)。

  1. ユーザー発話を検知
  2. 現在の音声再生を停止
  3. 未処理の音声バッファを破棄
  4. 新しい入力として次ターンに遷移

この「再生停止 + 状態リセット + 次ターン移行」が一体となって初めて自然な挙動になります。

➡︎ 割り込みは停止ではなく「ターンの切り替え」です。

モデル別の実装特性

ここまでの挙動を踏まえると、各モデルの実装体験には明確な違いがあります。細かい仕様差に入る前に、直感的には以下のように整理できます。

  • GPT Realtime 1.5 / Mini:素直で完結している
  • Gemini Flash Live:柔軟だがイベント依存が強い
  • Nova 2 Sonic:仕様が厳格で入力にシビア

これは単なる使いやすさではなく、「どこに制御責任があるか」の違いです。

➡︎ モデルごとに「実装責任の置き場所」が異なります。

GPT Realtime 1.5 / Mini

GPT Realtime 系は、イベントの流れが明確で、ターン制御がAPI側で完結します。

  • server VAD によるターン検知
  • cancel / truncate による生成停止
  • 一貫したイベント構造(開始 → 生成 → 完了の流れが明確)

これにより、

  • いつ終了したか
  • いつ止めるか
  • いつ次に進むか

をすべてAPIで判断できます。

クライアント側は「イベントに従う」だけで成立するため、状態管理がシンプルです。結果として、Stop・割り込み・ターン制御を一貫した設計で扱えます。

Gemini Flash Live

Gemini Flash Live は柔軟ですが、その分イベント解釈の責任がクライアント側に寄ります。

特に注意が必要だったのは以下です。

  • activity detection に依存したターン確定
  • response.done のタイミングが一定でない
  • transcript / audio のイベント粒度の違い
  • usage情報が安定しないケース

例えば、response.done を終了判定に使うと、実際の音声出力より先に終了扱いになるケースがありました。このため、終了判定は複数イベントを組み合わせて判断する必要があります。

➡︎ イベントをどう解釈するかが実装の本質になります。

Nova 2 Sonic

Nova 2 Sonic は仕様が厳格で、入力フォーマットへの依存が強いモデルでした。

主な特徴は以下です。

  • promptの先頭がSYSTEMである必要がある
  • イベント構造が固定されている
  • フォーマット不備でValidationExceptionが発生しやすい
  • cancel前提ではなくturn detectionベース

このため、「自由に設計する」というよりも「仕様に正確に合わせる」実装が求められます。柔軟性は低いですが、その分動作は一貫しています。

➡︎ 仕様適合性がそのまま実装難易度になります。

まとめ

今回の比較から見えてきたのは、S2S APIは単純なランキングで選べるものではないという点です。

GPT Realtime 1.5 は体験品質・知能性能・レイテンシのバランスが良く、さらに実装も素直であるため、最も扱いやすいモデルでした。 汎用的なリアルタイム対話基盤としては第一候補になります。

Gemini 2.5 Flash Live と Gemini 3.1 Flash Live は知能面での強さがあり、特に知識系やRAG用途では有力です。ただしレイテンシや実装上の癖には注意が必要です。

GPT Realtime Mini はコストと性能のバランスが良く、軽量な選択肢として実用的です。 Nova 2 Sonic は低遅延という明確な強みがあり、速度が重要な場面では有効です。

整理すると、用途別の選択は以下の通りです。

  • 汎用用途:GPT Realtime 1.5
  • 知識・RAG用途:Gemini系
  • コスト重視:GPT Realtime Mini
  • 低遅延重視:Nova 2 Sonic

➡︎ 「どれが最強か」ではなく「どの用途に合うか」で選ぶのが重要です。

Agentic RAGの前に整えるべきもの:実務RAGの入口を設計する Router RAG

はじめに

前回の記事では、Agentic RAGの有効性について、社内実験と最新研究の両面から検証しました。

その結果、Agentic RAGは確かに強力なアプローチである一方、エンタープライズ検索のようなユースケースでは、必ずしも複雑化に見合う効果が得られるとは限らない、ということが分かりました。

では、なぜ期待したほどの改善が得られないのでしょうか。

この問いをシステム全体で分解していくと、次のような気づきに至ります。

💡 結論

問題は後段(検索・生成)ではなく、
前段(問い合わせ処理)にある

実際の業務システムでは、ユーザは必ずしも検索に適した形で質問してくれるわけではありません。

  • 「こんにちは」
  • 「売上を集計して」
  • 「この機種のエラー原因は?」
  • 「操作方法を教えて」

これらはすべて“質問”ですが、必要な処理はまったく異なります。

しかし従来のRAGでは、これらを十分に区別せず、そのまま検索に流してしまう構造になりがちです。

本記事で扱うのは、機器ごとに分かれたマニュアルや社内ドキュメントを対象とする検索システムです。

このような文書群では、似た説明が複数の機種やカテゴリにまたがって存在するため、単純な検索では別機種の情報が混ざりやすくなります。そのため、機種名やカテゴリーといった分類情報を前提とした設計が重要になります。

前回のAgentic RAG検証から見えてきたこと

前回の記事では、高難度な質問への対応として、Agentic RAGのようなより高度な構成を検証しました。

techblog.heroz.jp

Agentic RAGは柔軟で強力な一方で、

  • 挙動が不安定になりやすい
  • コストやレイテンシが増えやすい

という特徴もあります。

そのため、すべての問い合わせに対していきなりAgenticな構成を適用するよりも、

まずは問い合わせを整理し、適切な処理に振り分ける

という前段の設計の方が重要になります。

実際、複雑な質問に対しては、検索戦略の動的制御やツール利用が有効に働くケースもあります。

一方で、エンタープライズ検索では、すべての質問に対してそのような複雑な処理が必要なわけではありませんでした。 コストやレイテンシが増える一方で、効果が限定的なケースも少なくありませんでした。

そこで後段については、よりシンプルな構成、具体的には ReRanking を中心とした Enhanced RAG に整理しました。

しかし、ここでより重要な問題に気づきます。

そもそも、すべての質問を同じ検索フローに流してよいのか?

実際の入力を見てみると、

  • 雑談
  • 計算依頼
  • 条件不足の質問
  • 単純に答えられる質問
  • 丁寧な検索が必要な質問

が混在しています。

この状態で後段だけを高度化しても、入力が整理されていなければ、期待した効果は出ません。

つまり、Agentic RAGの前に、問い合わせを正しく振り分ける仕組みが必要だった

この気づきから設計したのが、今回の Router RAG です。

実務で起きていた問題

雑談が検索に流れ、事故的な回答が出る

⚠️ 問題: 関係ないチャンクを拾い、“それっぽい誤回答”を生成することがある

単純な挨拶であっても、検索に流してしまうと、偶然ヒットしたチャンクをもとに文脈と無関係な“それっぽい回答”が生成されることがあります。

場合によっては、まったく関係ない業務情報を返してしまうなど、事故に近い挙動になることもあります。

metadata不足による誤検索

マニュアル検索では、似た説明が複数の機種にまたがって存在します。

このとき、機種などの条件が曖昧なまま検索すると、

  • A機種の質問に対してB機種の情報が混ざる

といったことが起きます。

これは単なるノイズではなく、誤情報そのものになります。

検索ではなく計算を求められる

ユーザは普通にこう言います。

  • 「売上を集計して」
  • 「平均を出して」

これは検索ではなく計算です。

RAGに流すと、断片的な情報を組み合わせてもっともらしい答えを返す危険があります。

ユーザは「無駄には待ちたくない」が「間違いは避けたい」

ユーザはできるだけ早く答えがほしい一方で、間違うくらいなら少し待ってもいいという期待も持っています。

つまり、

  • 簡単な質問はすぐ答える
  • 難しい質問は丁寧に扱う

という切り分けが必要になります。

検索に流してはいけない入力が混ざっている

つまり、RAGの問題は検索精度ではなく、 「入力の整理不足」にあると言えます。

Router RAGという考え方

こうした問題に対して導入したのが、Router RAGです。

ここでのポイントは、RAGを改善するのではなく、

「そもそも検索に流すべきか」を先に判断する

という設計に変えたことです。

図1:まず何をすべきかを決めてから、必要な処理に進む

Before / After

Before(従来のRAG)

すべての質問を検索に流してしまう

After(Router RAG)

質問に応じて処理を分離する

この違いは、構造として見るとより分かりやすくなります。

図2:すべて検索に流す構造から、適切に処理を分離する構造へ

PreRetrieveは「判断材料を集める」ためにある

Router RAGでは、質問を受けると最初に少量の検索を行います(top_k=4)。

これは最終回答のための検索ではなく、次に何をすべきかを判断するための材料集めです。

ここで得られたチャンクは、主に次の用途に使われます。

  • 🔍 ナレッジに関係するかの判定
  • ❓ 情報が足りているかの判定
  • ✏️ クエリ書き換えのヒント

つまり、PreRetrieveは「検索の前段」ではなく、Routerのための観測ステップです。

Classifierは「次の動き」を決める

PreRetrieveの結果をもとに、Classifierが次の処理を決めます。

ここで重要なのは、Classifierは回答を作らないことです。 やるのは一つだけで、次にどの経路に進めるかを決めることです。

Classifierの役割:次にどの処理に進むかを決める

  • 挨拶 → 雑談として処理
  • 意味が不足 → 確認質問
  • 集計・計算 → Code Interpreter
  • 条件不足(metadata) → 追加質問
  • すぐ答えられる → 即答
  • それ以外 → 詳細検索

(具体的なプロンプト設計については、本記事では詳細には触れませんが、 事前取得したチャンクやスコアを含めて一度に判断させる形にしています)

metadataとRouter Query Engine

ここで少しだけ、検索の前提となる仕組みを説明します。

今回のシステムでは、文書ごとに

  • 機種名
  • カテゴリー
  • 種類

といった分類情報をLLMで自動付与し、metadataとして保存しています。

検索時には、質問文からこれらの値を推定し、フィルタとして使います。

ここで重要なのが、必須の項目(required metadata)です。

例えば機種が必須の場合:

  • 「エラー原因は?」 → 機種が不明
  • → そのまま検索すると危険
  • → 先に聞き返す

この処理を担当しているのが Router Query Engine です。

fast と slow の分離

今回の設計では、処理を2つに分けています。

fast

  • PreRetrieveの結果を使って即答
  • 低レイテンシ

slow

  • クエリ変換
  • 再検索
  • ReRanking

重要なのは、これは単なる最適化ではなく、

ユーザの期待に合わせた分離

であることです。

  • 簡単な質問 → 待たせない
  • 難しい質問 → 無理に急がない

ノード構成

全体の処理の流れをまとめると、次のようになります。

図3:Router RAGの全体構成

なお、確認質問に対するユーザの応答は、次のターンで会話履歴(history)として再度 Router 側に渡します。Router Query Engine はその履歴を見て、前のターンで不足していた項目が埋まったかを再評価します。

たとえば「どの機種ですか?」という確認質問に対して、次のターンで「A-120です」と返ってきた場合、その応答単体を新しい質問として扱うのではなく、直前の確認質問と合わせて metadata を補完する入力として解釈します。

設計上の知見

実装を進める中で感じたのは、

細かく調整するより、大まかに分けた方が安定する

という点です。

  • fast / slow の境界
  • rewriteの有無
  • rerankの強さ

こういった要素は、個別にチューニングすると全体のバランスが崩れやすくなります。

そのため今回は、

  • 雑談
  • 確認質問
  • 計算
  • 即答
  • 詳細検索

といった大きな分類を先に決める方針にしました。

おわりに

前回のAgentic RAGの検証を通じて見えてきたのは、

後段を強くする前に、前段を整える必要がある

ということでした。つまり、RAGを高度化する前に、

「入力を整える」

ことが重要だった、というのが今回の結論です。

Router RAGは、そのための仕組みです。

雑談は雑談として扱い、計算は計算に回し、条件が足りなければ確認し、必要なときだけ検索する。

こうした分離を行うことで、RAGは単なる検索付き生成から、実務で使えるシステムへと近づきます。

PDFの図表はRAGで扱えるのか?6つの方法で検証して分かった“現実的な最適解”

はじめに

PDFの資料をRAGで検索・要約できるようにしたい、というニーズは多くの現場で見られます。 しかし実際にやってみると、「図や表の情報がうまく扱えない」という壁にぶつかることが少なくありません。 実際に社内外のユースケースでも、この課題に直面するケースが増えてきました。

テキスト中心のRAGでは、図解やレイアウトに依存した情報はうまく検索できず、結果として不正確な回答や見当違いの要約が返ってくることがあります。 では、最近話題のマルチモーダルRAGや画像対応のEmbeddingを使えば、この問題は解決するのでしょうか?

実は筆者も約2年前、マルチモーダルRAGの黎明期に同様の検証を行っています。 techblog.heroz.jp

当時は画像・表・テキストを分離して扱い、それぞれを要約・構造化する必要があり、実装・精度の両面で課題が残る状態でした。 しかし現在では、マルチモーダルEmbeddingの進化により、ページ全体をそのままベクトル化できるようになり、アプローチ自体が大きく変わりつつあります。

本記事では、PDFに含まれる図表を対象に、6つの方法(テキスト抽出、OCR、マルチモーダルEmbeddingなど)を比較し、精度・コスト・処理時間の観点から検証を行いました。 その結果、必ずしも最新の手法が最適とは限らず、用途によってはより現実的な選択肢が見えてきました。

PDFの図表をRAGで扱いたいと考えている方に向けて、本記事ではその「実務的な最適解」を整理して紹介します。

マルチモーダルRAGの基本構成

マルチモーダルRAGとは、テキストだけでなく、画像や図表といった複数の形式(モダリティ)の情報を扱うRAGの仕組みです。

従来のRAGはテキストを前提としているため、PDFに含まれる図や表の情報をそのまま扱うことが難しいという課題がありました。 この課題に対して、マルチモーダルRAGではいくつかの設計パターンが提案されています。

マルチモーダルRAGのオプション

代表的には以下の3つに分類されます。

  • Option1:画像をそのまま扱う(マルチモーダルEmbedding)
  • Option2:画像をテキストに変換して扱う(OCR・要約)
  • Option3:画像とテキストを併用する(融合型)

今回のmode2はOption2、mode4系(mode4v / mode4c / mode4g)はOption1、mode3はOption3に対応する構成となっています。 本記事では、この分類に対応する形で6つの手法を比較します。

実験概要

目的

PDFに含まれる図表を含めて、RAGの検索および回答生成がどの程度可能かを検証する。 特に、マルチモーダルEmbeddingの実用性を確認する。

手法(6つのモード)

  • mode1:テキスト抽出のみ(テキストのみ・図表なし) → PDFからテキストのみ抽出し、図表は扱わない

  • mode2:LLMによるOCR(OCRテキスト化) → 各ページを画像として処理し、LLMでテキスト化して検索に利用する

  • mode3:OCR+画像併用(テキスト+画像) → OCRでテキスト化しつつ、回答生成時には画像も参照する

  • mode4v:画像Embedding(Voyage) → ページ全体を画像としてベクトル化し、そのまま検索に利用する

  • mode4c:画像Embedding(Cohere) → ページ全体を画像としてベクトル化し、そのまま検索に利用する

  • mode4g:画像Embedding(Gemini) → ページ全体を画像としてベクトル化し、そのまま検索に利用する

※ mode4v / mode4c / mode4gはそれぞれ異なるマルチモーダルEmbeddingモデル(Voyage / Cohere / Gemini Embedding 2)を使用しており、モデル間の差異も含めて比較している

データセット

本検証では、以下の3種類のデータセットを用いて評価を行いました。

  • データセットA: 某北欧家具メーカーの組み立てマニュアル(24問) 図解のみで構成されており、警告表示以外にテキストがほとんど含まれない資料です。 視覚情報のみから理解する必要があり、マルチモーダル性能を評価するための難易度の高いケースとなります。

  • データセットB: JDocQA(30問) チラシやパンフレットを中心とした、日本語のマルチモーダルQAデータセットです。 テキストと図表が混在する、実務に近い構成となっています。

  • データセットC: 家電製品のマニュアル資料(20問) 図とテキストが併記された一般的なマニュアル形式のデータです。 図の難易度は比較的低く、テキスト情報による補助が期待できるケースです。

評価指標

  • 精度:LLM(Claude 4.5 Sonnet)による5段階評価(1〜5の5点満点)
  • コスト:日本円によるAPI利用料金
  • 処理時間:平均応答時間(ミリ秒)

結果

データセットAにおける精度比較(図解のみのため難易度が高い)

データセットBにおける精度比較(テキストと図表が混在)

データセットCにおける精度比較(テキストによる補助があるケース)

各モデルにおけるmode別の平均精度

本記事で最も重要な結果は、コストと精度の関係として以下のように整理できます。

コストと精度の関係(モデル別)

図より、mode2は多くのケースで比較的低コストに一定の精度を確保できる、コストパフォーマンスの高い選択肢であることが分かります。 一方で、mode4系は高精度を狙える一方、モデルによってはコスト負担が大きくなる傾向があります。

また、mode3は全体としては中間的な位置づけですが、GPT-5.2のようにコストを抑えつつ精度を伸ばせているケースも見られ、モデルやデータセットによって有効性が変わる手法と考えられます。

結果のまとめ

モード 精度 コスト 特徴
mode1 (テキストのみ・図表なし) 図表は扱えない
mode2 (OCRテキスト化) 多くのケースでコスパが良い
mode3 (テキスト+画像) 中〜高 中〜高 モデルによって評価が分かれる
mode4系 (画像Embedding) 高精度だがコスト増

本検証の特徴は、精度だけでなくコストも含めて比較している点にあり、実務における意思決定に直接つながる結果となっています。 以降では、この観点も踏まえながら結果を考察します。

考察

精度は段階的に向上するが、頭打ちになる

結果として、全体傾向としては mode1 < mode2 < mode3 < mode4系 という関係が確認されました。 ただし、mode3は全体としては中間的な位置づけであり、モデルによっては有効なケースも見られました。

これは、必要な情報の取得(retrieval)はすでに十分に行われており、その後の回答生成(generation)が性能を支配している可能性を示唆しています。

この傾向は近年の研究とも一致しています。 例えば、VisRAG(ICLR 2025)では、PDFを画像のまま扱うRAGが従来手法より高い性能を示すことが報告されています。 https://openreview.net/forum?id=zG459X3Xge

マルチモーダルEmbedding間の差は小さい

マルチモーダルEmbedding間で大きな差は見られませんでした。

UniDoc-Bench(2025)でも、Embedding単体では性能差が出にくく、一定以上では改善幅が小さくなる傾向が見られました。 https://huggingface.co/papers/2510.03663

OCRベースの手法も依然として有効

mode2(OCR)でも一定の精度が出ている点は重要です。 文書理解においては、テキスト化による情報の正規化が依然として有効であることが分かります。

LLMの性能が最終的な精度を決める

画像を扱う手法では、最終的な精度は回答生成LLMの性能に強く依存しました。 特に図解中心のタスクではモデル間の差が顕著に現れました。

実務的な最適解

今回の結果から、用途別に以下のような選択が現実的な指針となります。

  • コスト重視:mode2(OCR)
  • 精度重視:mode4系(マルチモーダルEmbedding)
  • mode3(融合型):モデルやデータセットによって有効だが、コストやレイテンシも含めて個別に評価する必要がある

実務においては、まずmode2をベースラインとし、精度要件が高い場合にmode4系を検討するのが現実的な選択となります。

おわりに

本記事では、PDFに含まれる図表を対象に、RAGの6つの手法を比較し、その精度・コスト・処理時間について検証を行いました。

その結果、マルチモーダルEmbeddingはすでに実用レベルに達している一方で、必ずしも単体で最適解となるわけではなく、テキスト化(OCR)や画像の活用方法を含めた設計全体が重要であることが分かりました。

特に、最新の研究においてもテキストと画像を組み合わせた手法が有効であることが示されており、本検証の結果はそうした傾向とも一致しています。 一方で、実務においてはコストや処理時間の制約も無視できず、用途に応じたトレードオフ設計が求められます。

PDFの図表を含む情報活用は、今後ますます重要になる領域です。 マルチモーダルRAGは急速に進化を続けており、今後のモデル・アーキテクチャの発展によって、さらに実用性が高まっていくと考えられます。

引き続き、こうした技術動向を追いながら、実務で使える形に落とし込んでいきたいと思います。

Agentic RAGは本当に必要なのか? 〜RAGの社内実験と最新研究から考える

はじめに

2025年頃から「AIエージェント」というキーワードが急速に広まり、2026年に入ってからはその応用の一つである Agentic RAG も注目を集めています。

RAG (Retrieval-Augmented Generation) は、検索によって取得した文書を元にLLMが回答を生成するアーキテクチャで、エンタープライズ検索や社内ナレッジ検索などで広く利用されています。近年は、単純な検索+生成の構成から、ReRankingやSelf-RAGなど様々な改良手法が提案されており、RAGの設計も進化を続けています。

その延長線上にあるのが、LLMが検索やツール利用を動的に制御する Agentic RAG です。

従来のRAGは検索→回答生成という比較的シンプルなパイプラインですが、Agentic RAGではLLMが状況に応じて検索や推論を繰り返しながら回答を構築します。

RAGの種類

このような構造により、より複雑な問題に対応できる可能性がある一方で、

  • 本当に精度は向上するのか
  • 追加されるコストや複雑さに見合うのか

といった疑問もあります。

そこで今回は、社内でいくつかのRAG手法を比較する簡単な実験を行いました。また、2026年に発表された最新の研究論文も合わせて紹介し、Agentic RAGの現状を整理してみたいと思います。

Agentic RAGを試してみた

実験設定

まず、複数のRAGアーキテクチャを比較する簡単な実験を行いました。

実験は社内の実験プラットフォーム上に構築したRAG環境を用いて実施しました。評価には 弊社製品の関連文書から構成されたQA評価セット を使用しています。内容としては、製品ドキュメントを対象とした典型的なエンタープライズ検索に近いタスクです。

評価方法は LLM-as-judge による自動評価を採用しました。回答生成および評価には Claude 4.5 Sonnet を使用しています。

今回比較した手法は以下の5種類です。

Naive RAG

最もシンプルなRAGです。

検索で取得したチャンクをそのままコンテキストとしてLLMに渡し、回答を生成します。今回は検索結果の上位4チャンクを使用しました。

RAGのベースラインとして広く使われている構成です。

RAG + ReRanking

検索で取得したチャンクを 再ランキング (ReRanking) によって選別する構成です。

今回は

  1. 検索で10チャンク取得
  2. ReRankerで重要度を評価
  3. 上位4チャンクをLLMへ入力

という手順を採用しました。

RAGの精度改善手法として比較的よく使われる構成です。

ReAct

ReAct (Reasoning and Acting) は、LLMが推論とツール利用を交互に行うエージェント型のアプローチです。

RAGをツールとしてLLMに与え、必要に応じて検索を行いながら回答を生成します。

論文 https://arxiv.org/abs/2210.03629

Adaptive RAG

Adaptive RAGは、回答の信頼性を高めるために 複数段階の検索や検証を行うRAG構成です。

検索結果の確認や再検索を行いながら回答を生成するため、より複雑なワークフローになります。Agentic RAGの代表的な構成の一つとして研究されています。

論文 https://arxiv.org/abs/2403.14403

LangGraphの実装例 https://docs.langchain.com/oss/python/langgraph/agentic-rag

Deep Agent

LangChainで公開されている Deep Agent も比較対象として評価しました。ツールを利用しながら複数ステップの推論を行う、より汎用的なエージェント型アーキテクチャです。

https://github.com/langchain-ai/deepagents

実験結果

各手法の評価結果をまとめたものが次の表です。

Agentic RAGの実験結果

結果を見ると、評価スコアには大きな差は見られませんでした

一方で、Agentic RAGに分類される手法では

  • LLM呼び出し回数
  • トークン消費量
  • レイテンシ

が増加する傾向が見られました。

今回の設定では、Naive RAGやReRanking付きRAGでも十分に高い性能が得られるという結果になりました。

もちろんこの結果だけで一般的な結論を出すことはできませんが、少なくとも今回のようなエンタープライズ検索に近いタスクでは、Agentic RAGの明確な優位性は確認できませんでした。

論文紹介①

Is Agentic RAG worth it?

ちょうど実験を行っていたタイミングで、興味深い論文が公開されました。

Is Agentic RAG worth it? https://arxiv.org/abs/2601.07711

この論文では、従来のRAGとAgentic RAGを複数のタスクで比較し、その費用対効果を分析しています。

論文の主な結論は次の通りです。

  • Agentic RAGは推論能力自体は高い
  • しかし精度改善は限定的
  • 一方で 計算コストとレイテンシは増加する

その結果、実運用の観点では Enhanced RAG(ReRankingなどを組み合わせたRAG)でも十分な場合が多いと述べられています。

今回の社内実験の結果も、少なくとも方向性としてはこの論文の結果と一致するものでした。

論文紹介②

A-RAG: Scaling Agentic Retrieval-Augmented Generation via Hierarchical Retrieval Interfaces

一方で、Agentic RAGの可能性を示す研究も発表されています。

A-RAG: Scaling Agentic Retrieval-Augmented Generation via Hierarchical Retrieval Interfaces https://arxiv.org/abs/2602.03442

この研究では、Agentic RAGが十分に性能を発揮できない原因の一つとして、検索インターフェースの設計を指摘しています。

従来のRAGでは、

  • 一度の検索で固定数のチャンクを取得する
  • その結果をそのままLLMに渡す

という比較的単純な構造になっています。

A-RAGではこれを拡張し、

  • キーワード検索
  • セマンティック検索
  • 文書単位の取得
  • チャンク単位の取得

といった複数の検索インターフェースをLLMに提供します。

これにより、LLMが状況に応じて検索戦略を選択できるようになり、より複雑な情報探索や multi-hop reasoning が可能になるとしています。

つまり、

  • 現在のAgentic RAGがうまく機能しないのは
  • アーキテクチャがまだ発展途上である可能性がある

という立場の研究と言えます。

おわりに

今回は、社内で行った簡単な比較実験と、2026年に公開された2本の論文を紹介しました。

今回の実験では、少なくともエンタープライズ検索に近いタスクにおいては、Agentic RAGの明確な優位性は確認できませんでした。一方で、研究コミュニティではAgentic RAGの改良に関する研究も活発に進んでいます。

Agentic RAGについては、研究や実装の方向性によって評価が変わる可能性もあり、まだ議論の続いているテーマと言えそうです。

今後の研究や実装の動向も追いながら、引き続き最良のサービスを提供できるよう、今後の研究や実装の動向も追っていきます。

クロスプラットフォーム開発の現在地:なぜ私はReact NativeからFlutterへ移行するのか (2025年版)

はじめに

こんにちは。クロスプラットフォーム開発の選定に頭を悩ませているエンジニアです。 「一度書けばどこでも動く(Write Once, Run Anywhere)」——これは我々エンジニアにとって永遠の夢ですが、現実はそれほど甘くありません。

今回、「Webアプリの資産を活かしたネイティブアプリ開発」を目指してReact Nativeに取り組みましたが、特にデスクトップ(Windows)対応において想像以上の「茨の道」を経験しました。その結果、Flutterへの移行を決断するに至った経緯と、その技術的な裏付けを共有したいと思います。

クロスプラットフォームフレームワークの概況

まず、現在利用可能な主要なクロスプラットフォーム技術を整理します。モバイルだけでなくデスクトップ(Windows/macOS)も視野に入れると、選択肢は以下のように絞られます。

フレームワーク 言語 主幹企業 特徴 今回の評価
React Native JS / TS Meta / Microsoft Web技術(React)を使用。OS標準のUIを描画。 Web資産流用は魅力的だが、デスクトップ対応に難あり。
Flutter Dart Google 独自の描画エンジン(Skia/Impeller)を使用。全OSで均一なUI。 今回の採用候補。安定性とパフォーマンスが高い。
.NET MAUI C# Microsoft Xamarinの後継。Windowsとの親和性は最強だが、モバイル開発体験は好みが分かれる。 Windows特化ならありだが、モバイル含めると学習コスト高。
Electron JS / TS OpenJS Fdn. Web技術そのもの(Chromium)で動作。 デスクトップ専用のため、モバイル対応不可。
Unity C# Unity ゲームエンジン ゲーム専用。一般的なUIアプリには不向き。

当初、Web(React)の知見を最大限活かせる React Native が最適解だと考え、プロジェクトをスタートしました。

(余談)Expo vs React Native CLI の落とし穴

開始当初、私は「Expoは開発用で、最終的に純粋なネイティブコードにはならない」という古い認識を持っていました。そのため、あえて難易度の高い React Native CLI を選択しました。 しかし、調査を進めると現在の Expo は prebuild 機能により、完全にネイティブなプロジェクトを生成できることが判明しました。CLIを選んでしまったことで、Windowsのビルド環境(Visual Studioのソリューションファイル)を自力で管理する羽目になり、これが後の苦戦の伏線となりました。

React Native での挑戦と「構造的限界」

React Nativeでの開発を始めてすぐに、「Webのように書けるが、Webではない」 という現実に直面しました。特にWindows対応において、以下の構造的な壁にぶつかりました。

エコシステムの分断

React Nativeは「一枚岩」ではありません。

  • React: Webの本家ライブラリ(npmでインストール)。
  • React Native (Core): モバイル(iOS/Android)向け。主幹は Meta
  • React Native for Windows / macOS: デスクトップ向け。主幹は Microsoft
    • ここがポイント: コア(Meta)とは別リポジトリで開発されており、コアの最新版への追従が遅れがちです。
  • React Native CLI: 開発ツール。主幹は コミュニティ(Callstack社など)
  • Expo: 開発ツールチェーン。主幹は 650 Industries (Expo)

この開発主体の違いにより、Coreの最新機能にWindows版が追従できていない「周回遅れ」の状態が頻発します。

Windows対応の辛すぎる現実

特に苦戦したのがWindows版です。「React Native for Windows」導入時に以下の問題が多発しました。

  1. UWPの制約と署名のコスト: Windows版は歴史的にUWP(サンドボックス環境)ベースです。このため、プロトタイプを社内に配ろうとしても、UWPはデジタル署名が必須となります。有償の証明書(年間数万円〜)を購入しないとインストールすらままならない現実は、プロトタイプ開発において大きな足枷でした。また、UWPゆえにファイルアクセス権限やWin32 APIへのアクセスが非常に制限されていて、回避策の検討にも苦労します。
  2. ライブラリ品質のばらつき: react-native-* 系のライブラリは、iOS/Androidには対応していても、Windowsは未対応かビルド不能であることが多々あります。
  3. Hermesエンジンのクラッシュ: Windows版のJSエンジン「Hermes」が、国際化機能(Intl)を呼ぶだけでクラッシュするバグに遭遇しました。プラットフォーム固有の地雷を踏むたびに開発がストップしました。
  4. アーキテクチャの過渡期: React Nativeは現在、旧アーキテクチャ(Bridge)から新アーキテクチャFabric / TurboModules)への移行期です。しかし、Windows版はこの対応が完了しておらず、ライブラリによっては「モバイルは新アーキテクチャ必須だが、Windowsは未対応」という板挟み状態になります。

結果として、「Reactのコードは共通化できても、ネイティブ周りのトラブルシューティング工数が倍増する」 という本末転倒な状態に陥りました。

なぜ Flutter なのか? 技術的な優位性

「純粋なクロスプラットフォームアプリ」を作るという目的に立ち返ったとき、Flutterアーキテクチャが持つ合理性が際立ちます。

インタープリター」vs「ネイティブコード」

性能面で決定的な違いがあります。

  • React Native: リリースビルドであっても、JavaScriptコードはバイトコード化され、アプリ内のJSエンジン(VM)上で実行されます。つまり、ネイティブコードとの間には常に変換のオーバーヘッドが存在します。
  • Flutter: リリースモードでは AOT (Ahead-Of-Time) コンパイル され、そのプラットフォームの完全なネイティブ機械語(マシンコード) になります。C++で書いたアプリと同等にCPUが直接実行するため、起動速度も処理速度も圧倒的です。

配布の容易さ(.exe vs MSIX)

FlutterのWindows版は、標準的なWin32アプリ(.exe)としてビルドされます。署名なしでも(警告は出ますが)zipで固めて配布し、ダブルクリックで即起動できます。この「普通のWindowsアプリ」が作れる手軽さは、React Native (UWP/MSIX) との大きな差です。

FFI による高速な連携と安定性

React Nativeが複雑なブリッジを介するのに対し、Flutter (Dart) は FFI を使って C/C++ (Win32 API) を直接呼び出せます。OS機能へのアクセスが高速で、かつGoogleが公式プラグインを整備しているため、「Windowsだけ動かない」という事態が起きにくい構造になっています。

Googleによる中央集権的な品質管理

Flutterは言語(Dart)もフレームワーク本体も Google が主幹です。 さらに、ファイルシステム、HTTP通信、画像選択といった主要なプラグインGoogle(またはFlutterチーム)が公式にメンテナンスしています。 「Windowsだけ動かない」という事態が構造的に起きにくく、Windows版もStable(安定版)として本体に含まれています。

AI時代における「言語の壁」の崩壊

移行に際して唯一の懸念は「Dart」という馴染みのない言語でした。しかし、実際に触れてみると2つの発見がありました。

  1. AIコーディングとの相性: Dartは静的型付け言語です。AIにコードを書かせた際、型定義が間違っていればコンパイルエラーになるため、JavaScriptよりも「AIの嘘」に気づきやすいです。
  2. 「書く」のはAI、「読む」のは人間: 新しい言語をゼロから「書く」のは大変です。しかし、AIに生成させたコードを「読んでレビューする」のは、JavaやTypeScriptに近いDartなら難しくありません。

「AIに書いてもらい、人間は型安全な環境でレビューする」 ——このスタイルが確立できる今、言語のマイナーさはもはや障壁ではなくなりました。

おわりに

Web資産の流用やOS標準UIへのこだわりがあるなら React Native も選択肢ですが、デスクトップを含む真のクロスプラットフォーム展開と、ネイティブアプリとしての純粋な性能・配布のしやすさを求めるなら、2025年現在は Flutter が最適解であると判断しました。
今後は今回の知見を活かして、Flutterでクロスプラットフォームのネイティブアプリを量産できるようにしていきたいと思います。