OpenAIが大規模で低遅延音声AIを提供する方法
著者: Yi Zhang、William McDonald(Technical Staff メンバー)
はじめに
音声AIが自然に感じられるのは、会話が音声の速度で進むときだけです。ネットワークが邪魔になると、ユーザーはすぐに不自然な沈黙、途切れた割り込み、または遅延したバージイン(割り込み)として認識します。これはChatGPT音声、Realtime APIで構築する開発者、インタラクティブワークフローで動作するエージェント、およびユーザーがまだ話している間に音声を処理する必要があるモデルにとって重要です。
OpenAIの規模では、これは3つの具体的な要件に変わります:
- グローバルリーチ: 9億人以上の週間アクティブユーザーに対応
- 高速接続セットアップ: ユーザーがセッション開始直後に話し始められるように
- 低く安定したメディアラウンドトリップ時間: ジッターとパケット損失が低いため、ターンテイキングが鮮明に感じられる
リアルタイムAIインタラクションを担当するOpenAIのチームは、最近WebRTCスタックを再構築しました。これは大規模で衝突し始めた3つの制約に対処するためです:
- セッションごとの1ポートメディア終端がOpenAIインフラストラクチャに適さない
- ステートフルなICE(Interactive Connectivity Establishment)およびDTLS(Datagram Transport Layer Security)セッションは安定した所有権が必要
- グローバルルーティングはファーストホップレイテンシを低く保つ必要がある
この投稿では、クライアントの標準WebRTC動作を保持しながら、OpenAIのインフラストラクチャ内でパケットをルーティングする方法を変更するために構築した、スプリットリレープラストランシーバーアーキテクチャについて説明します。
WebRTCがリアルタイムAI製品を可能にする理由
WebRTCは、ブラウザ、モバイルアプリ、サーバー間で低遅延の音声、ビデオ、データを送信するためのオープン標準です。ピアツーピア通話に関連付けられることが多いですが、クライアント・ツー・サーバーのリアルタイムシステムの実用的な基盤でもあります。これは、インタラクティブメディアの難しい部分を標準化するためです:
- ICE: 接続確立とNAT(Network Address Translation)トラバーサル
- DTLS と SRTP: 暗号化されたトランスポート(Secure Real-time Transport Protocol)
- コーデックネゴシエーション: 音声の圧縮と復号化
- RTCP: 品質制御(Real-time Transport Control Protocol)
- クライアント側機能: エコーキャンセレーションとジッターバッファリング
この標準化はAI製品にとって重要です。WebRTCがなければ、すべてのクライアントはNAT間の接続確立、メディア暗号化、コーデック(送信と復号化用に選択されたコーダーデコーダー)ネゴシエーション、および変化するネットワーク条件への適応方法について異なる答えが必要になります。WebRTCを使用すると、ブラウザとモバイルプラットフォーム全体で既に実装されているプロトコルスタック上に構築でき、リアルタイムメディアをモデルに接続するインフラストラクチャに独自の作業を集中できます。
また、WebRTCエコシステム自体の上に構築します。これには、成熟したオープンソース実装と、ブラウザ、モバイルアプリ、サーバーの相互運用性を保つ標準作業が含まれます。WebRTCの元の建築家の1人であるJustin Ubertiと、Pionの作成者兼メンテナーであるSean DuBoisによる基礎的な作業により、低レベルのトランスポート、暗号化、輻輳制御動作を再発明するのではなく、実戦で試されたメディアインフラストラクチャ上に構築することが可能になりました。JustinとSeanの両方がOpenAIの同僚であり、WebRTCとリアルタイムAIをどのように近づけるかをガイドしているのは幸運です。
AIにとって最も重要な特性は、音声が連続ストリームとして到着することです。話されたエージェントは、完全なアップロードを待つのではなく、ユーザーがまだ話している間に、転写、推論、ツール呼び出し、または音声生成を開始できます。これは、会話的に感じるシステムと、プッシュツートークのように感じるシステムの違いです。
メディアアーキテクチャの選択
WebRTCを選択した後、次の質問は、どこでそれを終端するか(WebRTC接続を受け入れて所有する場所、例えばエッジで)、およびそれらのセッションを推論バックエンドに接続する方法でした。終端は、リアルタイムセッション状態、メディアトランスポート、ルーティング、レイテンシ、および障害分離をどのように処理するかを決定するため、重要です。
SFU(Selective Forwarding Unit)
SFUは、各参加者から1つのWebRTCストリームを受け取り、他の参加者にストリームを選択的に転送するメディアサーバーです。このモデルでは、SFUは参加者ごとに個別のWebRTC接続を終端し、AIはセッション内の別の参加者として参加します。これは、グループ通話、教室、または協調的なミーティングなど、本質的にマルチパーティである製品に適している場合があります。音声コーデック、RTCPメッセージ、データチャネル、記録、およびストリームごとのポリシーを1つの場所に保ちます。
クライアント・ツー・AI製品でも、SFUは多くの場合、デフォルトの出発点です。これにより、チームはシグナリング、メディアルーティング、記録、可観測性、および人間へのハンドオフやより多くの参加者の追加などの将来の拡張機能に対して、1つの実証済みシステムを再利用できます。
トランシーバーモデル
当社のワークロードは異なります。ほとんどのセッションは1対1です。1人のユーザーが1つのモデルと話すか、1つのアプリケーションが1つのリアルタイムエージェントと話します。すべてのターンでレイテンシに敏感です。このトラフィック形状に対して、トランシーバーモデルを選択しました:WebRTCエッジサービスはクライアント接続を終端し、メディアとイベントをモデル推論、転写、音声生成、ツール使用、およびオーケストレーション用のより単純な内部プロトコルに変換します。
この設計では、トランシーバーはWebRTCセッション状態を所有する唯一のサービスです。これには、ICE接続チェック、DTLSハンドシェイク、SRTP暗号化キー、およびセッションライフサイクルが含まれます。「終端」とは、トランシーバーがこれらのハンドシェイクを完了し、メディアを暗号化または復号化するエンドポイントであることを意味します。その状態を1つの場所に保つことで、セッション所有権の推論が容易になり、バックエンドサービスがWebRTCピア自体として機能する代わりに、通常のサービスのようにスケーリングできるようになりました。
コア展開の問題:WebRTCがKubernetesに出会う
トランシーバーモデルを選択した後、最初の実装は、シグナリングとメディア終端の両方を処理するPionに基づいて構築された単一のGoサービスでした。これはChatGPT音声、Realtime APIのWebRTCエンドポイント、および多くの研究プロジェクトを強化します。
運用上、トランシーバーサービスは2つのジョブを実行します:
- シグナリング: SDP交渉、コーデック選択、ICE認証情報、およびセッションセットアップ
- メディア: ダウンストリームWebRTC接続を終端し、推論とオーケストレーション用のバックエンドサービスへのアップストリーム接続を維持
サービスをインフラストラクチャの残りの部分のように実行したかったです:Kubernetes上で、ワークロードはスケールアップおよびスケールダウンでき、需要が変わるにつれてホスト間を移動できます。しかし、従来のセッションごとの1ポートWebRTCモデルは、その環境に適していません。これは、ポッドが追加、削除、または再スケジュールされるときに、公開するのが難しく、保護し、保持するのが難しい大きなパブリックUDPポート範囲に依存しているためです。
ポート枯渇
最初の問題は、セッションごとの1ポートモデル自体でした。高い同時実行では、これは非常に大きなUDPポート範囲を公開および管理することを意味します。クラウドロードバランサーとKubernetesサービスは、サービスごとに数万のパブリックUDPポートを中心に設計されていません。追加の範囲ごとに、ロードバランサー設定、ヘルスチェック、ファイアウォールポリシー、およびロールアウト安全性の運用上の複雑さが増します。
大きなUDPポート範囲は、外部に到達可能な表面積を拡大し、ネットワークポリシーの監査を難しくするため、保護するのが難しいです。また、自動スケーリングに適していません。ポッドはKubernetesで常に追加、削除、および再スケジュールされます。各ポッドが大きな安定したポート範囲を予約および通知する必要があることは、その弾力性を脆くします。
これが、多くのWebRTCシステムが単一のUDPポートごとのサーバーに向かう理由です。そのポートの背後にあるアプリケーションレベルの多重分離があります。
状態スティッキー
シングルポートごとのサーバー設計はポート数を解決しますが、2番目の問題を導入します:フリート全体でセッションの所有権を保持します。ICEとDTLSはステートフルプロトコルです。セッションを作成したプロセスは、そのセッションのパケットを受け取り続ける必要があります。これにより、接続チェックを検証し、DTLSハンドシェイクを完了し、SRTPを復号化し、ICE再起動などの後のセッション変更を処理できます。同じセッションのパケットが別のプロセスに到達した場合、セットアップが失敗するか、メディアが破損する可能性があります。
これにより、特定のターゲットが得られました:パブリックインターネットに小さな固定UDPサーフェスを公開しながら、対応するWebRTCセッションを所有するトランシーバーにすべてのパケットをルーティングします。
WebRTCメディアアーキテクチャの比較
複数の方法を評価しました。これには、TURN(Traversal Using Relays around NAT)が含まれます。ここで、エッジリレーはクライアント割り当てを終端し、その代わりにトラフィックを転送します。
| アプローチ | 利点 | 欠点 |
|---|
| セッションごとの一意のIP:ポート(ネイティブダイレクトUDPとも呼ばれる) | クライアント・ツー・サーバーの直接メディアパス、データパスに転送層がない | セッションごとに1つのパブリックUDPポートが必要、大きなポート範囲は公開および保護が難しい、Kubernetesおよびクラウドロードバランサーに適さない |
| サーバーごとの一意のIP:ポート | セッションごとの公開UDPフットプリントよりもはるかに小さい、1つの共有ソケットごとのサーバーは多くのセッションを多重分離できる | 単一ホストでは正常に機能しますが、共有ロードバランサーフリート全体では機能しません。セッションごとの多重分離は、パケットがそのホストに到達した後にのみ役立ちます。ロードバランサーフリート全体では、最初のパケットは依然として間違ったインスタンスに到達する可能性があるため、各セッションをそれを所有するプロセスに導く決定論的な方法が必要です |
| TURNリレー(プロトコル終端) | クライアントはTURNリレーアドレスとポートにのみ到達する必要があります、ポリシーをエッジで一元化できます | TURN割り当てはセットアップラウンドトリップを追加します、TURNサーバー全体で割り当てを移動または復旧するのはまだ難しいです |
| ステートレスフォワーダー+ステートフル終端(OpenAIのリレー+トランシーバー) | 小さなパブリックUDPフットプリント、トランシーバーは完全なWebRTCセッションを所有します | メディアが所有するトランシーバーに到達する前に、1つの転送ホップを追加します |
アーキテクチャ概要:リレー+トランシーバー
当社が出荷したアーキテクチャは、パケットルーティングをプロトコル終端から分割します。シグナリングはセッションセットアップのためにトランシーバーに到達し続けますが、メディアは最初にリレーを通じて入ります。リレーは小さなパブリックフットプリントを持つ軽量UDPフォワーディングレイヤーであり、トランシーバーはその背後にあるステートフルWebRTCエンドポイントです。
リレーはメディアを復号化したり、ICE状態マシンを実行したり、コーデックネゴシエーションに参加したりしません。宛先を選択するのに十分なパケットメタデータを読み取り、パケットをセッションを所有するトランシーバーに転送します。トランシーバーは依然として通常のWebRTCフローを見て、すべてのプロトコル状態を所有しています。クライアントの観点からは、WebRTCセッションについて何も変わりません。
ICE認証情報でのルーティング
ファーストパケットルーティングはこのセットアップの重要なステップです。リレーは、外部ルックアップサービスで一時停止するのではなく、パケットパス自体にセッションが存在する前に、クライアントからの最初のパケットをルーティングする必要があります。すべてのWebRTCセッションには、プロトコルネイティブルーティングフックが既に含まれています:ICEユーザー名フラグメント、またはufrag。これは、セッションセットアップ中に交換され、STUN接続チェックでエコーバックされる短い識別子です。
サーバー側のufragを生成して、リレーが宛先クラスタと所有するトランシーバーを推測するのに十分なルーティングメタデータが含まれるようにします。シグナリング中に、トランシーバーはセッション状態を割り当て、SDP応答で共有リレーVIPとUDPポートを返します。VIPは、リレーフリートの前面にある仮想IPアドレスです。ポートと組み合わせると、多くのリレーインスタンスがその背後にあっても、クライアントに203.0.113.10:3478などの単一の安定した宛先を提供します。
クライアントの最初のメディアパスパケットは通常、STUN(Session Traversal Utilities for NAT)バインディング要求です。これはICEが、アドバタイズされたアドレスにパケットが到達できることを確認するために使用します。リレーは、その最初のSTUNパケットの十分な部分を解析して、サーバーufragを読み取り、ルーティングヒントをデコードし、パケットを所有するトランシーバーに転送します。
各トランシーバーは共有UDPソケットでリッスンします。つまり、セッションごとに1つのソケットではなく、内部IP:ポートにバインドされた1つのオペレーティングシステムエンドポイントです。リレーがクライアントのソース IP:ポートからそのトランシーバー宛先への接続を作成した後、後続のパケットはそのマッピングに従います。