【アプリ開発日記4週目】リアルタイム音声会話のベストプラクティスを考える(2024/10時点、中編)
こんにちは、ちゅーりんです。
今回は複数デバイスを接続、つまり人間と複数のAIが同時に会話できるというシステムを実装した舞台裏と課題を書いていきます。
1,AIと1対1でリアルタイム会話
まずは人間:AIの1対1で対話できるようにします。
こちらは公式デモをクローンすれば、手元でもすぐ動かせました。
Reactなので、動作確認だけ行った後は新規作成したNext.jsでコードを再出力。ちなみにコードを書くときのAIはClaudeを使っています、gpt-4oやo1よりも3.5-sonnet(vercel ai sdkに関してはv0のほうがいい感じか)のほうがコーディングは手応えあったので。
ですが、欠点が「このままではパソコンのローカル環境でしか動かせない」ということ。外出先のスマホで使いたいのに、リレーサーバーに接続できないのです。(APIキーをブラウザ上で入力すれば使えますが、セキュリティと長期的な流れを考慮してリレーサーバーでの開発をすることにしました。)
ということで、自前リレーサーバーを設置していきます。
2,外出先でもローカルサーバーに繋がるようにする
わかりやすくまとめると、普段の開発では「localhost:3000」のようにPC内でサーバーを起動していることが多いかと思います。
しかし、「ローカル」という名前の通り他のパソコンやスマホからはアクセスできません。あくまでそのデバイスのなかでの環境なのです。
もちろん今回のリレーサーバーも例外ではありません。
そこで「ngrok」を使うことにしました。一言で表すと、他のデバイスからでもこのローカルサーバーにアクセスできるようにしてくれるSaaSです。
普段の使い道はローカルサーバーで立ち上げた開発中のデモ共有などで使われるイメージかもしれないですが、今回のような用途としても問題なく使えました。
ただ、これの大きな落とし穴が(少なくとも私の環境では)「有料でないと一部の処理には対応していない」という点。
今回私は、スマホでリアルタイム会話を行うにあたり3つのサーバーを立ち上げました。
WebSocket1(リレーサーバー。リアルタイム音声会話用)
WebSocket2(チャットの内容などを複数デバイスで共有。後述)
今回とは別の音声合成用(REST API)
そして、REST API(リアルタイムではなく、シンプルなリクエストとレスポンスで構成されるもの)は無料プランで問題なく外からでもアクセスできました。こちらはGPUを使うので、今回とは関係ないですがおまけで作っていたものになります(GPUサーバーを借りると高いので、、、)。
同様にリレーサーバーを含むWebSocket(リアルタイム通信)を行ったのですが、なぜかこちらがファイアウォールやウイルスソフトを全部外しても一切繋がらず。
参考記事を見ていても「無料プランでもWebSocket使えますよ」といずれも書かれていた、また私の環境でも最初の何回かは無料プランでもつながっていたので、その後に何か良くないことをしてしまったからなのかもしれません。
ngrokでWebSocketを使おうという方は一度無料プランで試しうまく行けばそれに越したことはありません。それでも私は8時間格闘の末、思い切って有料にしたところあっさりつながったということもあったので、そのことも一応書いておきます。参考程度に。。。
ということもありながら、無事外出先から1対1リアルタイム会話出来るようになりました!
3,複数デバイスでチャットを共有する
さて、今度は複数デバイスで会話できるようにしていきます。
それは別にChatGPTのAdvanced Voiceで良いのではと疑問に思う方もいらっしゃるのではないでしょうか。
ということでさっそく実験。
しかし、実際に行ってみると2つの致命的なデメリットが浮かび上がってきました。
会話が平行線になる
ユーザーが話すと2つのスマホ(GPT)が同時に返答するのでAI同士も再びユーザーが話し始めたと勘違いして黙ってしまう
1については、「AIがあくまでユーザーの質問に答える」という構成になっているためと思われます。
以前CharaChatでも同様の現象が起きていたのですが、例えばAI1が「何でも質問してくださいね、詳しくお答えしますよ」と話すと、AI2はそれに対して「もちろんです、気軽に質問してください」→AI1「ありがとうございます。質問があれば何でも言ってください」のように、新たな話題が生まれなくなってしまうのです。
上記2つを改善するため、今回のリアルタイム音声会話アプリではこれらを留意して構築していきます。
その解決策となったのが「複数デバイスでチャット履歴などを共有する」ということでした。LINEのイメージですね。
さらに、チャット履歴だけでなく「誰が親デバイスか」も共有することで、その親デバイスのみがユーザーの音声を取得、AIが同時に返答するといったことを無くしました。
さらに、以下のようなプロンプトを毎回裏で投げる(つまり、表示用のチャットと実際に裏で動いているチャット履歴の2つが存在)ことで、AIが「そうなんですよ、私は今日カフェに行ってきて……」というように能動的な会話が出来るようになりました。
下記の会話は、最初の「今日も一日お疲れ様!」以降、全てAI同士の会話になっています。途中で人間が加わることも可能。
これでスマホ同士の会話もラジオのように次々と新しい話題が生まれるようになりました。
これらの情報をデバイスで共有するために使っている技術が、前章で触れたWebSocketになります。
もちろんこれで完璧なわけもなく、内容が趣味などに偏りがちなこと、サーバーに負担をかけるとダウンすること、スマホだと処理が遅くチャットの同期がずれることがある点が気になりますね。
加えて音声に抑揚がない、ボイスの種類が少ないなどのTTSの改善点も。現時点の音声合成AIで一番気に入っているものも貼っておきます。
現時点でベストのボイス例
手元でデータを収集/学習させたものです。ぜひ1つでも聞いてみて下さい。
1、ポジティブ
2,ネガティブ
3,ポジティブ2
これが実装できればベストなのですが……
使っている技術は前回の記事を参考にして下さい。ストリームに対応していないのが欠点ですね。作りたいけど、時間的に優先度は低めか。
おわりに
今週で大体のイメージは形になってきました。ただ、まだ
AIにそれぞれの人格(話し方、好きなことなど)を入れていない
時々手動で手直ししてあげないと会話が止まってしまうことがある
もう少し話題を面白くしたい(世間話だけでなく、アイデアを自分、他の人、複数のAIでディスカッションできるようにしたい)
複数の人間がいると話者を聞き分けられるようにする
画像認識機能もつける(優先度は低め)
といった課題があります。特に建設的なディスカッションが出来るようになれば、それはAIが日常生活に入ってくる段階にシフトするのではないでしょうか。
ということで来週はそのあたりを実装していきます。
ではでは!