課題
ここ最近言語生成AIが盛り上がっており、様々なアプリケーションの登場が期待されます。しかし、Azure OpenAI Serviceをはじめとしたサービスはインターネット上で処理が実行され、特に長文を生成する場合にはレスポンスが返ってくるまでに何秒かかかることも多く、リアルタイムコミュニケーションが難しいように感じられます。
それに対して、REST APIや各種SDKではストリーミング処理でレスポンスを受け取るための機能が備わっており、チャンクに分割された回答を少しずつ受け取ることができます。これは本家ChatGPTやAzure OpenAI Serviceのプレイグラウンドで質問をした際に少しずつ回答が生成されるのと同じ仕組みだと思われますが、原理的に可能であることは分かります。
ここで、一つの課題として、直接それらのサービス(以降、今回実装に使用したAzure OpenAI Serviceとします)を叩くのではなく、バックエンド経由で叩く場合にフロントエンドにそのレスポンスを表示するのに手間がかかることがあります。特にセキュリティの都合やプロンプトエンジニアリングをユーザーから秘匿したい場合などにフロントエンドに直接処理を記載せずバックエンドを挟むことが考えられます。バックエンドでレスポンスをストリーミングで受け取った際に、それをフロントエンドに返す際にリレーするような形になってしまい、実装上大きな制約となり場合によってはクラス設計やアーキテクチャが歪む可能性もあります。また、長時間の接続となり途中で接続が切れる懸念もあります。
解決法
2つの仕組みを導入します。
- バックエンドはフロントエンドからリクエストを受けたらAzure OpenAI Serviceにリクエストを送信するプロセスを立ち上げ、先にレスポンスを返す
- 別プロセスでAzure OpenAI Serviceへリクエストを送信し、レスポンスのストリームをWebSocketでサーバに送信する
基本的な考え方として、長時間のセッションを避け、別の経路でレスポンスをフロントエンドに返します。そこで、リアルタイムコミュニケーションが可能なWebSocketを使用します。
この形式にすることで、デモの様にフロントエンド画面上に少しずつ結果を表示できます
デモ
画面右のバックエンドアプリケーションがAIサービスにリクエストをすると、その結果を裏側でWebSocketとして送信し、画面左のブラウザアプリケーションにリアルタイムに表示します(簡易的な実装の為、バックエンドアプリケーションをフロントエンドではなくコマンドラインで直接起動しています…)。
Azure構成のイメージ
折角なのでAzureで実現する際のイメージも貼っておきます。
終わりに
折角なので、ちょっとしたアプリでも作ってみたいですね。特にエージェントとの音声会話みたいな用途では難しいみたいな風潮もあるので、こういった構成でリアルタイム性が確保されて実現されるシステムがあれば嬉しいです。