blog

DeNAのエンジニアが考えていることや、担当しているサービスについて情報発信しています

2026.10.20 インターンレポート

カスケード型音声対話で宿泊予約の電話応対デモを作る 〜投機的実行で待ち時間を減らす〜

by Daiki Muto

#ai #llm #spoken-dialog-system #internship

はじめに

本記事の内容

本記事では、サマーインターンシップにおいて開発した、カスケード型音声対話システムを用いた宿泊予約の電話応対デモを紹介します。 ユーザーが話し終わるのを待たずに応答に必要な処理を裏で始めておき、AI が応答するまでの待ち時間を短くする仕組みを入れたのが特徴です。

まず、カスケード型音声対話システムと、本インターンシップの課題設定を説明します。 次に、取り組みの内容として、デモのテーマ選定と、ワークフロー型からエージェント型へ作り直した経緯を含む設計・実装を紹介します。 最後に、完成したデモを動画で紹介します。

自己紹介

はじめまして。 東京科学大学 情報理工学院 情報工学系 修士課程 1 年の武藤大樹と申します。 大学ではソフトウェア工学を研究しています。 研究のかたわら、長期インターンでソフトウェア開発にも取り組んでいます。

背景

カスケード型音声対話

カスケード型音声対話は、3 つの処理を順につないで会話する方式です。 まず音声認識を担う ASR がユーザーの声を文字に起こし、次に LLM がその文字に対する応答を作り、最後に音声合成を担う TTS が応答を読み上げます。

カスケード型音声対話の構成

カスケード型の強みは、1 つのモデルで音声から音声を直接生成する End-to-End 型に比べて、構成を柔軟に変えられ、既存の仕組みとも組み合わせやすいことです。 ASR・LLM・TTS をそれぞれ自由に選べるので、声を変えたり、聞き取りを特定の言葉に強いものにしたりできます。 また、会話の途中でユーザーの発話がいったんテキストになるため、発話の内容を確認したり、テキストを扱う既存の仕組みと組み合わせたりもしやすくなります。

インターンシップにおける目標

今回のインターンシップの目標は、カスケード型音声対話システムを使い、実際の利用場面を想定したデモを作ることでした。 このシステムは、配属先のチームがさまざまなプロダクトでの活用を見据えて開発しているものです。 デモを通じて応答の柔軟性と速度の両立を示し、見た人に技術的な驚きを感じてもらうことを目指しました。

デモのテーマ選定

デモのテーマには、宿泊施設のフロントの電話応対を選びました。 いちばんの理由は、有望だと感じていたアイデアが活きる題材だったからです。 作りやすさも理由の一つです。 予約の作成・変更・キャンセルと機能を一つずつ足していけるので、3 週間という限られた期間でも形にできると判断しました。

電話で人間のフロントに空室や予約内容を尋ねると、フロントがそれらを確認するため、利用者には待ち時間が生じます。 一般的な音声対話システムでも、ユーザーが話し終えてから LLM がツールを呼び出すため、検索や照会を伴う質問には同様に待ち時間が生じます。

この待ち時間をなくせば、デモで狙う技術的な驚きを生めると考えました。 待ち時間をなくす仕組みは、ユーザーが話している間に、必要になりそうなツールを先に呼び出しておくというものです。 CPU が分岐の結果を待たずに先の命令を実行しておく投機的実行と似た考え方なので、本記事ではこの仕組みを投機的実行と呼びます。

投機的実行の有無による応答時間の比較

設計・実装

インフラ構成

デモは Google Cloud 上で動く Web アプリで、このうち今回作ったのは対話制御サーバーと予約 API の 2 つです。 図で★を付けた部分がこれにあたり、それ以外はチームの既存の基盤です。

デモのインフラ構成

対話制御サーバーは、ユーザーとの対話を進めるサーバーで、チームの既存の対話サーバーをもとに作りました。 ユーザーの声はブラウザから WebSocket でこのサーバーに届き、応答の音声も同じ経路で返ります。 音声認識と音声合成にはチームが GPU 上で動かしているものをそのまま使い、LLM は Vertex AI(Gemini Enterprise Agent Platform の一部)から呼び出しています。 会話履歴は Cloud SQL に保存しています。

予約 API は、デモのために自作した宿泊予約の API です。 部屋・プラン・予約のデータを Cloud SQL に持ち、空室の検索や予約の作成はすべてこの API を通して行います。

ワークフロー型で作る

まずワークフロー型での実装から始めました。 宿泊予約は条件の確認、プランの選択、個人情報の入力、最終確認と手順がはっきりしていて、ワークフローに落とし込みやすく、エージェント型より実装しやすいと判断したためです。 予約の作成から始めて、変更やキャンセルも同じ方式で広げていく計画でした。

ところが、予約の作成までを動かしてみると、会話が噛み合わない場面がありました。 次の画像はその一例です。 ユーザーは「他にプランはないの?」と尋ねていますが、システムはプランの内容を復唱するだけで、他のプランには答えていません。 チームの方々にデモを触ってもらった際にも、返答の柔軟性が足りないというフィードバックをいただきました。

ワークフローで想定していない発話をした対話の例

この柔軟性の不足は、ワークフロー型のまま改善を重ねても解消しきれないと考えました。 この例だけなら他のプランを示す行動を足せば対応できますが、こうした改善を積み重ねるとワークフローはどんどん複雑になってしまいます。 また、ユーザーがどんな発話をするか事前に網羅しておくこと自体が現実的ではありません。

そこで、柔軟性を上げるため、発話への応じ方を LLM がその場で選ぶエージェント型で作り直すことにしました。

エージェント型で作り直す

ここからは、エージェント型で作り直した最終的なデモアプリの設計を説明します。 構成は次の図のとおりです。 背景で紹介したカスケード型の構成がもとになっています。

エージェント型の構成

応答生成は、LLM にツールを持たせて予約 API を操作できるようにしたエージェントが担っています。 通常のカスケード型と同じく、発話が確定してから同期的に実行されます。

これとは別に、投機的実行のエージェントが応答生成とは非同期に動いています。

投機的実行の仕組み

投機的実行のエージェントは、音声認識が発話の途中で逐次返す文字起こし(以下、途中結果)をプロンプトに受け取り、プラン・部屋・空室のうち必要な検索を実行します。 このエージェントに持たせているのは読み取りのツールだけです。 なぜなら、投機的実行は推測が外れても結果を捨てれば済む操作でなければ成り立ちませんが、予約の確定やキャンセルは実行した時点で予約の状態を変えてしまうためです。 投機的実行のエージェントに与えるシステムプロンプトは、応答生成のものに投機的実行用の指示を加えたものです。 加えた指示では、投機が当たる可能性を高めるために、読み取れた条件で積極的にツールを実行するように求めています。

このエージェントは、途中結果が更新されるたびに動かしています。 途中結果は音声認識から発話の内容を受け取れる最も細かい単位なので、更新のたびに動かせば最も早く調べ始められます。 ただし、同時に動かすのは 1 本だけにしています。 実行中に届いた途中結果は最新の 1 件だけを残しておき、動作が終了してから再度エージェントを動かします。

発話が確定するとそれまでに完了したツールの呼び出しとその結果のペアを、ユーザー発話の直後に置く形で応答生成エージェントの履歴に含めます。 応答生成のエージェントから見ると、自分がすでにツールを呼び出して結果を受け取った状態から応答を始めることになります。 通常のツール呼び出しでは、LLM がツールの呼び出しを返し、その実行結果を送り返してもう一度応答を求めるため、LLM へのリクエストが 2 回かかります。 履歴に含めた検索結果が当たっていれば、1 回目のリクエストから検索結果を使った応答を始められ、リクエストは 1 回で済みます。 検索結果が外れていたり足りなかったりすれば、応答生成のエージェントが自分でツールを呼びます。

体感速度を上げる工夫

最初の声が早く聞こえるように、システムプロンプトで話し方を 2 つ指示しました。 音声対話でユーザーが感じる速さは、最初の声が聞こえるまでの時間に大きく左右されるからです。

1 つ目は、一度の応答を一息で言える長さにとどめさせ、最初の 1 文を早く読み上げられるようにする指示です。 チームの基盤は、LLM が生成した文章を句点で区切り、1 文ずつ音声合成に回します。 応答が短ければ最初の 1 文も短くなり、LLM がそれを書き終えた時点ですぐに読み上げを始められます。

2 つ目は、検索の前に「少々お待ちください」のようなひと言を言わせる指示です。 投機的実行が外れると、応答生成のエージェントが自分で検索するため、結果が返るまで沈黙が生まれます。 このひと言を挟むことで、その間を自然につなげられます。

完成したデモ

完成したデモの動作を2つの動画で紹介します。

次の動画は、投機的実行が活きている例です。 ユーザーが「来月の土曜日」と言った後、まだ話し終えていない動画開始から7〜8秒ほどの時点で、画面右側の「先読みした情報」欄に10月の空室と料金の検索結果が現れます。 この表示は投機的実行が行われたことを示しています。 ユーザーが話し終えると、AI はこの検索結果を前提として、10月の土曜日の空室を5日分挙げています。 このように投機的実行が当たると、ユーザーの待ち時間を減らすことができます。

次の動画は、ワークフロー型と比較して高い柔軟性を発揮している例です。 ユーザーが「一番安い日の一番安いプランを紹介して、それにしてほしい」と頼むと、AI は10月の土曜日はどの日も同じ料金で、素泊まりプランの1泊9千円が最も安いと答えています。 そのうえで、どの日にするかは決めずに、部屋のタイプとチェックイン日を聞き返しています。 このようにエージェント型では、想定していない要望にも柔軟に応じられます。

まとめ

本記事では、サマーインターンシップで開発した、カスケード型音声対話システムを用いた宿泊予約の電話応対デモを紹介しました。

本インターンシップでは、応答の柔軟性と速度の両立を示すデモを作ることを目指しました。

速度の面では、投機的実行によって、検索を伴う質問への待ち時間を短くしました。

柔軟性の面では、ワークフロー型からエージェント型に作り直し、想定していない要望にも応じられるようにしました。

完成したデモの 2 つの動画は、これらの効果をそれぞれ示しています。

今後の課題としては、柔軟性を保ったまま速度を改善することです。 具体的には、最初の音声の読み上げまでの時間を短くするために音声合成の境界を「、」にすることや、今回使用したGemini 3.8 Flash以外のモデルを試すことなどが挙げられます。

おわりに

アプリケーションのテーマの策定から、設計・実装、フィードバックを受けての改善と、開発においてのさまざまなプロセスを経験でき、充実した3週間でした。 どのようなアプリを作るのかを考えることは、今までの実務ではあまり経験してこなかったことであり、とても良いチャレンジができたと感じています。

また、社員の方々との交流の場を多くセッティングしていただき、よりDeNAについて知ることができました。 入社して半年ほどでエンジニアからプロダクトオーナーに職種を変えられている方がいるなど、挑戦者を歓迎しやりたいことを後押しする会社だと改めて感じました。

メンターの佐藤さん1をはじめ、音声対話チーム、事業部、HR の皆さまにお礼申し上げます。 3 週間という短い期間でデモを形にできたのは、多くの方に支えていただいたおかげです。

最後までお読みいただき、ありがとうございました。

最後まで読んでいただき、ありがとうございます!
この記事をシェアしていただける方はこちらからお願いします。

recruit

DeNAでは、失敗を恐れず常に挑戦し続けるエンジニアを募集しています。