For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
メインナビゲーション
Theme

GPT-Live への移行

Realtime アプリ、テキストエージェント、または複数の処理をつないだ音声パイプラインを GPT-Live に移行します。

GPT-Live は音声の聞き取りと発話を担当します。タスクをどう進めるか、どのツールを呼び出すかはバックエンドが判断します。既存のツール実装、権限チェック、保存済みのタスク記録は引き続き使用します。移行時には、そのバックエンドを GPT-Live に接続し、各モデルにどの指示を持たせるかを決めます。

このガイドでは、空き状況を調べ、具体的な枠を示してユーザーに予約してよいか確認し、同意を得てからその枠を予約するアシスタントを例に説明します。はじめにの手順でセッションに接続し、比較用に既存のアプリケーションでの代表的な会話を保存しておきます。

移行前の準備

移行後のアプリケーションが満たすべき要件を記録します。

  • ツールと業務ルール: 既存のプロンプト、ツール、ワークフローを洗い出し、各操作を実行する条件も記録します。
  • 入力の種類: 音声、入力されたテキスト、画像をアプリケーションのどこで受け取り、どのバックエンドで必要とするかを確認します。画像と視覚情報の追加を参照してください。
  • 音声に基づく判断: 文字起こしされた言葉だけでは判断できず、元の音声が必要な場面を特定します。音声に基づく判断の維持を参照してください。
  • 発話と再生: いつ発話を開始できるか、いつ停止する必要があるか、音声の再生前にどのチェックを完了する必要があるかを明確にします。
  • 権限とガードレール: 認可、ユーザーへの確認、入出力のチェックを洗い出し、アプリケーションのどこで実施するかを記録します。ガードレールの調整を参照してください。
  • 永続化する状態: 接続が切れた後や新しいセッションでも保持する必要がある記録、タスクの進捗、保留中の操作を特定します。
  • 比較の基準となる会話: 現行アプリケーションでの代表的な会話と、その開始時の状態、想定されるツール操作、最終的なアプリケーションの状態、音声での応答を保存します。

セッションの設定にははじめにを、比較方法の検討には Cookbook の音声エージェント評価ガイドを参照してください。

委譲モードの選択

バックエンドの実行を誰が担うかを決めます。

  • Responses への委譲: ホスト型の Responses モデルがタスクの進め方を判断し、ツールを選択するように設定します。カスタム関数はアプリケーションが実行し、結果を返します。現在 Realtime モデルがこれらの関数を選択している場合は、この方式から始めると移行しやすくなります。
  • クライアントへの委譲: 既存のエージェントまたはオーケストレーターを引き続き使用します。アプリケーションが会話のコンテキストを渡し、処理を開始して、どの結果を GPT-Live に送るかを決めます。

どちらのモードも、いずれの移行経路でも使用できます。たとえば、独立したバックエンドエージェントを持つ Realtime アプリケーションは、クライアントへの委譲でそのエージェントを引き続き使用できます。詳しい比較は委譲モードの選択を参照してください。

移行経路の選択

現在の音声モデルがツールを選択している場合は、Realtime API からの移行から始めます。既存のエージェントを引き続き使用し、その音声インターフェースとして GPT-Live を追加する場合は、テキストエージェントまたは多段パイプラインからの移行から始めます。

Realtime API からの移行

まず GPT-Live プロンプトガイドを参照してください。既存のプロンプトをそのまま session.instructions にコピーせず、音声モデル用とバックエンド用に分けます。話し方や委譲の指針は音声モデルのプロンプトに残し、詳しいワークフローやツールの使い方はバックエンドに移します。

移行前: Realtime モデルが音声を処理し、check_availability や book_appointment などの関数を選択します。アプリケーションは関数を実行し、結果を返します。

移行後: GPT-Live が音声を処理し、タスクの処理を委譲します。これまでと同じ関数をバックエンドが選択し、アプリケーションが引き続き検証と実行を担います。ここでは Responses への委譲を使います。外部エージェントを引き続き使用する場合は、クライアントアダプターを使用してください。

Responses への委譲の仕組み

delegation.responses にバックエンドのモデル、指示、ツールを設定します。リクエストにバックエンドでの処理が必要だと GPT-Live が判断すると、Live サービスがその Responses モデルを呼び出し、関連する会話のコンテキストを渡します。バックエンドはタスクの進め方を判断し、ツールを選択します。カスタム関数の実行、権限チェック、結果の返却は引き続きアプリケーションが担います。

予約アシスタントでは、次のように処理が進みます。

  1. ユーザーが金曜日の空き枠を尋ねると、GPT-Live がリクエストを委譲します。
  2. Responses バックエンドが check_availability の実行を要求します。
  3. アプリケーションが関数を実行して結果を返し、バックエンドの応答を続行させます。
  4. GPT-Live はバックエンドの回答をもとに、空いている枠についてユーザーと話します。

バックエンドで処理を実行している間も、GPT-Live は発話を続けられます。バックエンドのタスクと音声再生は別々に追跡します。タスクの状態はツールの結果に基づいて更新し、発話中の表示はプレーヤーの状態に合わせて更新します。設定方法とイベントの流れは委譲とツールを参照してください。

接続と音声処理のライフサイクルの変更

Realtime のセッション設定を GPT-Live の接続手順に置き換えます。使用する通信方式の開始手順と音声形式を再確認してください。WebRTC では音声をメディアトラックで、JSON イベントをデータチャネルで送受信します。メインの WebSocket 接続では JSON イベントに音声を含めます。

Realtime アプリケーションでサーバー接続を使って通話の監視やガードレールの適用を行っている場合は、GPT-Live のサイドバンド接続に合わせて変更します。会話のチェックと再生に必要な変更は、ガードレールの調整を参照してください。

Realtime での動作 GPT-Live での対応
input_audio_buffer.append で WebSocket 経由の音声を送信します。 session.input_audio.append を送信します。audio フィールドには Base64 でエンコードした生の音声データを格納します。
response.output_audio.delta の delta フィールドに含まれる音声を再生します。 session.output_audio.delta の delta フィールドに含まれる音声を順番に再生します。
ターンを手動で制御する場合、音声をコミットするか応答を作成してターンを開始します。 音声を継続的にストリーミングします。発話のタイミングは GPT-Live が判断するため、音声の手動コミットと発話ターンを開始するトリガーを削除します。
response.output_audio.done と response.done で音声生成と応答の完了を追跡します。 GPT-Live には、個々の音声応答の終了を示す対応イベントがありません。クライアントで再生状態を追跡します。
入力音声の文字起こしイベントからユーザーの字幕を表示します。 session.input_transcript.delta のテキストをユーザーの字幕に追記します。
response.output_audio_transcript.delta からアシスタントの字幕を表示します。 session.output_transcript.delta のテキストをアシスタントの字幕に追記します。

生成と再生: 発話中の表示は音声プレーヤーの状態に合わせます。サーバーで音声の生成が完了しても、プレーヤーにはまだ 1 秒分の音声が再生待ちになっていることがあります。Realtime では response.output_audio.done が生成の終了を示し、response.done で応答ストリームが終了します。中断や失敗の有無は response.status で確認します。GPT-Live には、個々の音声応答の終了を示す同等のイベントがありません。

字幕: 入力音声の文字起こしが有効な場合、Realtime は conversation.item.input_audio_transcription.delta でテキストを断片ごとに送信し、conversation.item.input_audio_transcription.completed で確定した文字起こしを送信します。GPT-Live では、各断片を通話相手またはアシスタントの字幕に追記します。両方の字幕が同時に更新されることもあります。テキストをどうまとめるかはアプリケーションで決め、再生状態は音声プレーヤーで追跡します。字幕の表示を参照してください。

委譲した Responses の処理を開始または続行するには、response.create を使用します。GPT-Live は会話を聞きながら発話のタイミングを判断します。セッションの開始、挨拶、割り込みへの対応、セッションの終了については、セッション管理を参照してください。

会話用とバックエンド用の指示の分離

Realtime アシスタントを GPT-Live に移行する際は、既存のプロンプトをもとにします。話し方と発話の順番に関する指示を Live プロンプトに移し、いつ委譲するかのルールを追加します。タスクに関する指示とツールの使用手順はバックエンドのプロンプトに残します。

テキストエージェントに音声を追加する場合は、既存のバックエンドプロンプトを再利用し、音声でのやり取りに合わせて Live プロンプトを作成します。

一貫した会話体験の維持

アシスタントの役割、対象ユーザー、目的を維持し、会話の特徴を決める次の要素を引き継ぎます。

  • 挨拶、自己紹介、口頭で伝える告知、および指定の文言や順序
  • 「英語で話してください」など、使用言語と発音に関する要件
  • 個性、親しみやすさ、共感の示し方、丁寧さ、話すペース
  • 音声での回答に求める詳しさと、意図した話し方を示す例
  • 相づちの打ち方、話を止めて相手の言葉を聞くタイミング、割り込みへの対応

短い Live プロンプトでも、音声で詳しく回答するように指示できます。

Live プロンプトの作成

アシスタントの人物設定、話し方、会話での振る舞いは、推奨されるプロンプト構成に沿って記述します。Backchannel policy と Interruption policy の項目は残し、相づちの打ち方と、アシスタントの発話に相手の声が重なったときの対応を記述します。

Live が適切に委譲するには、バックエンドで何ができるかを把握している必要があります。対応できる操作を平易な言葉で説明してください。関数名とツールのスキーマは、ツール呼び出しを担当するバックエンドに置きます。

Delegation policy の下にある次の項目を、アプリケーションに合わせて調整します。

  • Backend tools: 既存のプロンプトと同じ用語で、アプリケーションが対応する操作を列挙します。例:「予約の空き状況を調べ、折り返しの電話を予約する」
  • Delegate to the backend when: 「ユーザーが折り返しの電話の予約を求めたら委譲する」など、これらの操作をいつ使うかを明記します。進行中のタスクに関する訂正、確認、そのタスクに必要な追加情報も対象に含めます。
  • Do not delegate to the backend when: 挨拶、意図を確かめるための短い質問、会話に出た情報や今も有効なバックエンドの結果を繰り返す場合など、Live が直接対応できる場面を記述します。

進捗の伝え方、バックエンドからの次の質問をユーザーに尋ねる方法、検証済みの結果を伝える方法を Live に指示します。

アシスタントが通話を終了する場合は、終了時の挨拶と通話終了リクエストの委譲について Live に指示します。実際に通話を終了するツールと処理手順はバックエンドに置きます。たとえば、挨拶の再生が終わってから接続を切り、保留中の計算をキャンセルし、それ以降の保存を禁止する手順が必要な場合があります。Live は挨拶と委譲を担当し、残りの手順はバックエンドとアプリケーションが担当します。

バックエンドプロンプトの調整

元のプロンプトを出発点にします。引き続き適用できる文言、順序、例、構成は維持してください。主にタスクを説明するプロンプトなら、大部分をそのまま使用できます。

次の内容に関する指示はバックエンドに残します。

  • ユーザーのリクエストの解釈、訂正の反映、不足情報の収集、タスクの進捗管理
  • 業務に関する事実の活用、適用条件を満たしているかの確認、回答の根拠となる記録やサービスの参照
  • 検索、更新、確認、振り分け、転送、折り返し電話など、対応する操作の手順
  • 安全性、プライバシー、認可に関するルールの適用、失敗時の対応、転送後または通話終了後の操作制限
  • Live が伝える正確な情報、タスクの状態、次の質問の準備

声や挨拶、発話の順番、委譲のタイミングに関する指示は Live プロンプトに移します。バックエンドがユーザーに直接話すことを前提とする指示は、Live に情報を返す内容に書き換えます。各モデルの発言、質問、操作を制限する安全性とプライバシーのルールは、その制限が適用される各モデルのプロンプトに残します。

関数名、引数の要件、ツールの使用手順はバックエンドの指示に残し、ツール定義はバックエンドのツール設定に置きます。アプリケーションは現在のタスクの状態に照らして、権限、引数の妥当性、必要な確認が得られていることをチェックし、ツールを実行します。

会話に含まれるリクエスト、訂正、確認の解釈にはバックエンドモデルを使用します。正規表現、キーワードのリスト、特定の言い回しとの完全一致に基づくルールでは、以前の発言や訂正によって変わる意味を捉えきれません。たとえば「はい」は、予約枠への同意、質問を聞いたことを示す相づち、あるいはそれ以前の提案への返答かもしれません。

通話相手が話に割り込んだときや、通話が転送または終了されたときに、実行中の処理をどう扱うかというルールも維持します。発話が止まってもバックエンドの処理は続きます。通話相手がキャンセルを求めた場合、バックエンドとアプリケーションはキャンセル要求を処理し、その結果を Live に報告する必要があります。

指示の矛盾の解消

元のプロンプトと 2 つの新しいプロンプトを見比べ、矛盾する指示がないか確認します。重複する指示はまとめ、個別の条件や例外は対象のルールと一緒に記載します。権限、質問数の上限、確認の要件、通話終了後に許可される操作を確認してください。

ユーザーの希望と、すでに行われた操作は区別します。通話相手が希望日を金曜日から木曜日に変えた場合、バックエンドは最新のリクエストに従って木曜日を対象に処理します。金曜日の予約がすでに成立しているかどうかは予約記録で確認します。次にどの変更を行えるかは、既存の確認・認可ルールに従って判断します。

プロンプトを使う前に、製品の振る舞いに関わる判断は担当者と合意しておきます。たとえば、通話相手が話に割り込んだときに、一方の指示では予約処理の続行を、もう一方ではすべての処理の停止を求めている場合、アプリケーションとしてどちらを採用するかを決めます。合意した動作をプロンプトに明記し、アプリケーションのロジックにも反映します。

必要な操作がすべて実装されていることを確認します。通話を終了するには、実際に通話を切断する機能が必要です。終了の挨拶だけでは接続は切れません。必要な機能がない場合は、それを実装するか、対応可能な代替手段を採用するかをワークフローの担当チームと決めます。

両方のプロンプトの確認

両方のプロンプトを元のプロンプトと比較し、必要な動作がすべていずれかに含まれていることを確認します。

  • Live プロンプトがアシスタントの人物設定、語彙、話し方、告知、割り込みへの対応を引き継いでいること
  • バックエンドプロンプトがタスクの手順、事実、条件、例、権限、失敗時の対応を引き継いでいること
  • 新規のリクエスト、訂正、確認、会話とタスク情報の両方を含むリクエストが委譲の対象になっていること
  • 質問数の上限、操作への確認が得られたと判断するタイミング、進行中の処理、キャンセル、転送、通話終了の扱いについて、両方のプロンプトが一致していること

Live プロンプトは session.instructions に設定します。Responses への委譲ではバックエンドプロンプトを session.delegation.responses.instructions に設定し、クライアントへの委譲では既存のエージェントの設定に残します。ツール定義はバックエンド側に置きます。設定と結果の扱いについては、委譲とツールを参照してください。

例:予約アシスタントのプロンプトの分割

この予約アシスタントには、すでに check_availability と book_appointment のツールがあります。元のプロンプトには話し方と予約手順が一緒に記載されています。分割後も、挨拶、確認の要件、訂正への対応は同じです。

元のプロンプト

あなたは Northstar Repairs の予約担当アシスタント、Rowan です。
英語で、落ち着いた口調で簡潔に話してください。通話相手には次の言葉で一度だけ挨拶してください。
"Hello, this is Rowan from Northstar Repairs. How can I help?"
相手の話には短く相づちを打ってください。相手が話に割り込んだら、発話を止めてください。

通話相手の空き枠探しと予約を手伝ってください。希望日やタイムゾーンがわからない場合は、不明な項目を相手に尋ねてください。両方がそろったら check_availability を使ってください。
案内するのは、結果に含まれる空き枠だけです。予約する枠の日時を具体的に示し、その枠を予約してよいか通話相手に尋ねてください。相手がその枠の予約に同意してから、book_appointment を呼び出してください。
相手が日付、タイムゾーン、予約枠のいずれかを変更したら、それまでの同意を無効にし、空き状況を再度確認してください。
ツールの結果で予約の成功を確認してから、予約が成立したことを伝えてください。結果が不明な場合は、予約が成立したか確認できていないと伝え、自動で再試行しないでください。

Live プロンプト

あなたは Northstar Repairs の予約担当アシスタント、Rowan です。
英語で、落ち着いた口調で簡潔に話してください。通話相手には次の言葉で一度だけ挨拶してください。
"Hello, this is Rowan from Northstar Repairs. How can I help?"

Backchannel policy: 相手の話には短く相づちを打ってください。

Interruption policy: 相手が話に割り込んだら、発話を止めて相手の話を聞いてください。

Delegation policy:
Backend tools:
- 予約:空いている日時の照会と予約の登録

Delegate to the backend when:
- 通話相手が空き枠を探したい場合や、予約を希望する場合
- 相手が日付、タイムゾーン、予約枠のいずれかを伝えたり訂正したりした場合、または予約に関する質問に答えた場合(提示した枠の予約に同意した場合も含む)

Do not delegate to the backend when:
- 通話相手が挨拶した場合や、今も有効な結果をもう一度聞きたいと言った場合
- 相手の依頼内容を理解するために、ひと言聞き返す必要がある場合

バックエンドからの質問と結果を通話相手に伝えてください。案内するのは、バックエンドが返した枠だけです。
バックエンドが予約の成功を確認するまでは、予約が完了したと伝えないでください。
バックエンドから結果が不明だと報告された場合は、予約が成立したか確認できていないと伝えてください。

バックエンドプロンプト

通話相手が Northstar Repairs の空き枠を探し、予約できるように手伝ってください。
希望日やタイムゾーンがわからない場合は、不明な項目を相手に尋ねてください。両方がそろったら check_availability を使ってください。案内するのは、結果に含まれる空き枠だけです。
予約する枠の日時を具体的に示し、その枠を予約してよいか通話相手に尋ねてください。相手がその枠の予約に同意してから、book_appointment を呼び出してください。
相手が日付、タイムゾーン、予約枠のいずれかを変更したら、それまでの同意を無効にし、空き状況を再度確認してください。
ツールの結果で予約の成功を確認してから、予約が成立したことを報告してください。結果が不明な場合は、予約が成立したか確認できていないと報告し、自動で再試行しないでください。

音声アシスタントが相手に伝えられるよう、空き枠、予約の結果、または次の質問を返してください。相手の最新の回答や訂正は、これまでの会話と現在のタスクの状態を踏まえて解釈してください。

関数ハンドラーの変更

check_availability と book_appointment の実装は引き続き使用します。関数定義は Realtime の session.tools または response.tools から delegation.responses.tools に移し、Responses の関数スキーマに合わせます。ツール選択の設定は delegation.responses.tool_choice と delegation.responses.parallel_tool_calls に移します。Responses への委譲の設定を参照してください。

関数はこれまでどおり、呼び出し時の call_id に対応する結果を返します。変わるのは、ハンドラーがどのイベントから呼び出しを受け取り、どのイベントで結果を送信するかです。

手順 Realtime API Responses への委譲を使う GPT-Live
関数呼び出しの内容が確定したら受け取ります。 response.output_item.done を読み取ります。 response.event を展開し、内部の response.output_item.done を読み取ります。
操作を特定して実行します。 項目の name、arguments、call_id を読み取り、実行が許可されたハンドラーを呼び出します。 既存のハンドラーとチェックを引き続き使用します。外側のイベントの delegation_id とバックエンドの応答 ID をアプリケーションに保持します。
各関数の結果を返します。 conversation.item.create を送信します。 response.item.create を送信します。
必要な結果をすべて返したら処理を続行します。 response.create を送信します。 response.create を送信してバックエンドの処理を続行します。

たとえば、check_availability から空きが確認できた枠が返ったら、接続中のセッションで次のイベントを送信します。call_availability は受け取った呼び出し ID に置き換えてください。

移行前:Realtime での結果の返却

{
  "type": "conversation.item.create",
  "item": {
    "type": "function_call_output",
    "call_id": "call_availability",
    "output": "{\"available\":true,\"slot_id\":\"slot_friday_14\",\"booked\":false}"
  }
}

移行後:GPT-Live での結果の返却

export function sendUpdate(connection) {
  connection.send({
    type: "response.item.create",
    event_id: "availability_result_1",
    item: {
      type: "function_call_output",
      call_id: "call_availability",
      output: '{"available":true,"slot_id":"slot_friday_14","booked":false}',
    },
  });
}

必要な関数の結果をすべて送信してから、バックエンドの処理を続行します。

export function sendUpdate(connection) {
  connection.send({
    type: "response.create",
    event_id: "continue_availability_1",
  });
}

移行の初期段階では、parallel_tool_calls を false に設定し、ツール呼び出しを 1 件ずつ処理します。内部の response.output_item.done イベントから各関数呼び出しを取得し、関数名、引数、call_id を保持します。後続の完了イベントに output: [] が含まれていても、この記録は保持してください。引数の完了イベントだけでは関数名と call_id がわからないため、関数呼び出しの項目全体が確定してからハンドラーを実行します。呼び出しの収集、結果の送信、エラー処理の詳細は、関数の結果を返す手順に従ってください。

コンテキストの保持と訂正の反映

Responses への委譲では、関連する音声会話のコンテキストがバックエンドに渡されます。予約状態の正本はアプリケーション側に保持します。選択された枠、ユーザーが予約に同意した枠、権限、実行中の操作、その結果を記録してください。Live の会話履歴は圧縮されることがあるため、予約記録としては使用できません。

ユーザーが「やっぱり金曜日にしてください」と言った場合は、金曜日を現在の希望日として記録し、木曜日の枠について得ていた同意を無効にします。タスクにリビジョン 2 などの新しいバージョン番号を付け、以前のリクエストに対する結果をアプリケーションが識別できるようにします。

予約前に、日付、枠、ユーザーが同意した内容が現在のリクエストと一致していることを確認します。ユーザーがリクエストを変更したために保留中の関数呼び出しを実行しない場合は、スキップしたのかキャンセルしたのか、実際に行った処理を結果として返します。バックエンドの処理を続行する前に、結果が必要なすべての呼び出しに対して結果を送信してください。

木曜日の予約がすでに成立している場合は、現在の予約状況を確認し、希望された変更に対応してから次の予約を試みます。

文字起こしの各断片は受け取ったとおりに保持し、話者、start_ms、end_ms も一緒に記録します。この情報を使って、通話相手またはアシスタントの該当する字幕やチャットの吹き出しを更新します。断片が遅れて届いた場合や、両者が同時に話した場合も同様です。メッセージの区切りはアプリケーションで決め、音声の再生状態はプレーヤーで追跡します。文字起こしのタイムスタンプから各単語の正確な再生時刻を特定することはできません。意図が不明確な場合は、重要な日付、名前、数値を聞き返します。文字起こしとコンテキストの扱いについては、セッション管理を参照してください。

画像と画面のコンテキスト: Realtime アプリケーションが画像を受け付ける場合は、画像を処理できるバックエンドに送り、関連する情報をテキストで GPT-Live に返します。この方式は、クライアントへの委譲でも Responses への委譲でも使用できます。画像と視覚情報の追加を参照してください。

音声に基づく判断の維持

留守番電話の録音開始音を検出する場合や、音声のタイミングから録音済みの応答メッセージを識別する場合など、音そのものが必要な判断もあります。GPT-Live は通話の音声を聞き取りますが、委譲時に音声が自動でバックエンドに送られることはありません。クライアントモードでは session.delegation.created に ID とタイミング情報が含まれます。リクエストのコンテキストとバックエンドが必要とする音声は、アプリケーションから渡します。

留守番電話を検出するには、受信音声を音声処理に対応した検出器に明示的に送ります。検討できる構成の一例として、アプリケーション側で、通話の一部の区間だけ GPT-Live と並行して別の Realtime セッションを実行する方法があります。

  1. 受信した通話音声を複製し、両方のセッションに送ります。
  2. 検出器から構造化された関数呼び出しで判定結果を報告させます。各結果をスキーマに照らして検証し、古い結果は破棄します。判断材料が足りない場合は「不明」の状態を維持し、後から得た情報で判定を更新できるようにします。
  3. 関連する信頼できるコンテキストを GPT-Live に送り、相手に聞かせる音声の再生にはアプリケーションのポリシーを適用します。

通話相手が人か機械か、そして相手側でメッセージを録音できる状態かという 2 つの判断を別々に追跡します。応答メッセージの再生中に、検出器が留守番電話と判定する場合があります。相手に聞かせる音声の再生は、アプリケーションが必要とする判断材料がそろうまで待ちます。コンテキスト更新への確認応答が示すのは、更新が受理されたことです。再生の可否は引き続きアプリケーションが判断します。ガードレールの調整と再生制御を参照し、アプリケーションが制御する音声経路にこの判断を反映してください。

短い「もしもし」に続いて留守番電話の応答メッセージが流れる場合、着信スクリーニングの音声案内が流れる場合、留守番電話の応答中に人が電話に出る場合をテストします。通話終了前に検出器を停止する予定なら、停止後に人が電話に出た場合の動作もテストしてください。テスト結果と検出器の追加コストをもとに、どのくらいの時間動作させるかを決めます。最初は「人」と判定しても、その後に届いた音声で判定が変わるケースも含めます。

テキストエージェントまたは多段パイプラインからの移行

移行前: テキストエージェントは文章でリクエストを受け取り、ツールと保存済みの状態を使って処理します。複数の処理をつないだ音声パイプライン(カスケード型パイプライン)では、エージェントの前段に音声認識、後段に音声合成を追加します。

移行後: GPT-Live が音声インターフェースを提供し、既存のエージェントにタスクの処理を委譲します。多段パイプラインでは、これまで別々に実行していた音声認識と音声合成を GPT-Live が担います。既存のモデル、指示、ツール、ワークフロー、永続化した状態は、引き続きタスクに適しているものをバックエンドに残します。

既存のエージェントとの接続

delegation を {"type":"client"} に設定して、セッションをセットアップします。アプリケーションは次のような通知を受け取ります。

{
  "type": "session.delegation.created",
  "offset_ms": 1000,
  "delegation": {
    "id": "item_appointment_1",
    "type": "delegation",
    "target": "client"
  }
}

この通知を受けたら、アプリケーションの委譲ハンドラーを起動します。結果を同じリクエストに関連付けられるように、delegation.id を保持してください。ハンドラーは、通話相手とアシスタントの文字起こしにアプリケーションが保持するタスク記録を組み合わせて、エージェントへの入力を準備します。通知自体にはリクエストの本文もツールの引数も含まれません。

たとえば、予約エージェントには次の情報を渡せます。

通話相手:「やっぱり金曜日にしてください」

現在のリクエスト:通話相手のタイムゾーンで金曜日の空き枠を探す。

前回の結果:木曜日の午後 2 時の枠を案内済み。

確認状況:金曜日のどの枠についても、予約への同意はまだ得られていない。

タスクのリビジョン:2

発言全体の文字起こしが終わる前に通知が届くことがあります。十分なコンテキストがそろうまで通知を保持するか、操作を実行する前に通話相手に意図を確認します。

テキストアプリケーションでは、ユーザーの最新メッセージをそのままエージェントに渡す場合があります。GPT-Live では、必要なコンテキストを渡して簡潔な検証済みの結果を返すアダプターを追加します。

アダプターを呼び出す前に委譲 ID を記録し、その ID に対して処理を開始するハンドラーを 1 つに限定します。リクエストが不明確な場合は、コンテキストがそろった時点でアダプターを再度呼び出します。

認可、ユーザーへの確認、操作 ID、再試行は引き続きバックエンドが管理します。予約を変更する前に、タスクの現在のリビジョンを確認してください。その後にアダプターが行うリビジョンチェックで防げるのは、古い結果を読み上げることだけです。すでに成立した予約を元に戻すことはできません。

クライアントへの委譲とエージェントの接続
async function handleDelegation(event, app) {
  if (
    event.type !== "session.delegation.created" ||
    event.delegation?.target !== "client"
  )
    return;

  const context = app.readContext();
  if (!context) return; // Retain the notice; resolve the request before acting.

  const summary = await app.runAgent({
    revision: context.revision,
    recentConversation: context.recentConversation,
    task: context.task,
  });

  if (app.currentRevision() !== context.revision) return;

  app.send({
    type: "session.commentary.append",
    event_id: crypto.randomUUID(),
    delegation_id: event.delegation.id,
    content: summary,
  });
}

コンテキスト取得用とエージェント実行用のコールバックをアプリケーションに実装します。コンテキスト取得用のコールバックは、直近の会話と現在のタスクを返します。リクエストがまだ不明確な間は値を返しません。エージェント実行用のコールバックは既存のバックエンドを実行し、検証済みの要約を 500 トークン以内で返します。JavaScript では、アプリケーションが用意する send コールバックで Live 接続に JSON イベントを送信します。Python では、アダプターが SDK の connection を通じて直接更新を送信します。

予約アシスタントのコンテキストには、希望日とタイムゾーン、すでに案内した枠、通話相手が予約に同意した枠、最新の訂正を含め、それぞれを明確にします。空き状況の照会結果には、該当の枠が空いており、まだ予約していないことを明記します。予約の確定を伝える結果は、予約が成功した後にだけ返してください。設定から結果の返却までの流れは、クライアントへの委譲を参照してください。

更新と訂正の送信

構造化されたツール出力とワークフローの詳細はバックエンドに保持します。GPT-Live には、事実に基づく短い更新を返します。

  • 照会がまだ実行中であることなど、バックグラウンド処理の進捗には session.thinking.append を使用します。
  • ユーザーに音声で伝えるべき検証済みの結果には session.commentary.append を使用します。
  • アプリケーション側で作成した振る舞いに関する指示には session.instructions.append を使用します。

いずれも content に 500 トークン以内のプレーンな文字列を指定し、delegation_id が必須です。関連する処理には元のクライアント委譲 ID を使用し、セッション全般のコンテキストには null を指定します。client_event_id を使い、各確認応答を送信したコマンドと照合します。これで更新が受理されたことを確認できます。生成された発話はアシスタントの文字起こしイベントで確認し、再生はプレーヤーの状態で追跡します。用途に合った更新の送信を参照してください。

ユーザーが「やっぱり金曜日にしてください」と言った場合は、金曜日を現在の希望日として保存し、リクエストのバージョン番号を進め、木曜日の枠について得ていた同意を無効にします。その訂正を既存のエージェントに送ります。木曜日の照会については、キャンセルを要求するか、照会内容を変更するか、完了まで待って結果を破棄するかを決めます。

キャンセル済みと報告する前に、照会の状態を追跡して確認します。ユーザーの割り込みでアシスタントの発話がすでに止まっていても、バックエンドでは照会をどう扱うか判断し、必要な処理を行います。

バックエンドの処理は音声セッションが終了した後も続くことがあります。その状態をアプリケーションで永続化します。後で音声でのやり取りを再開する際には、保存したコンテキストのうち関連する情報を使って新しいセッションを開始します。セッション管理を参照してください。

テキスト入力とエージェントの接続の維持

入力されたテキストは引き続き既存のバックエンドに渡します。テキストによる訂正は同じタスクへの更新として扱い、関連する検証済みのコンテキストを音声セッションに送ります。テキスト入力の受け付けと正確で役立つ更新の送信を参照してください。

テキストと音声の安全対策の調整

テキストエージェントや多段パイプラインでは、応答全体を検証してから表示したり読み上げたりできます。GPT-Live では、会話とバックエンドの処理が同時に進みます。すべての音声応答をユーザーが聞く前にチェックする必要がある場合は、アプリケーションが制御する音声の再生経路にチェックを組み込んでください。バックエンドの結果の送信を保留するだけでは、すべての発話を一時停止することはできません。

ガードレールの調整に従い、既存のチェックを維持しながら、発話が継続する仕組みに対応してください。

ガードレールの調整

どちらの構成から移行する場合も、既存のアプリケーションの入出力に対する安全対策を維持します。バックエンドの処理やポリシーチェックの実行中も GPT-Live は発話を続けられるため、会話とバックエンドが実行する操作の両方をチェックします。

サーバーからブラウザの WebRTC セッションを監視または制御する必要がある場合は、サイドバンド WebSocket を接続し、文字起こしの受信と修正指示の送信に使用します。音声は引き続き WebRTC で送受信します。サーバーがすでにメインの WebSocket 接続で音声をストリーミングしている場合は、その接続のイベントストリームをチェックに使用します。Responses への委譲を選んだことだけを理由に、サイドバンド接続が必要になるわけではありません。

  1. ユーザーとアシスタントの文字起こしイベントを監視し、会話と並行してチェックを実行します。
  2. 対象のツールと外部操作はアプリケーションコードでブロックします。アプリケーションが管理する関連処理は、キャンセルに対応していればキャンセルします。遅れて結果が届いても、ブロックしたリクエストの処理が続行されないようにします。
  3. session.instructions.append を送信してアシスタントの対応を修正し、その判断をアプリケーションに記録します。

たとえば、通話相手が権限を持たずに他人の予約を変更するよう予約アシスタントに求めた場合は、予約の変更操作を実行前にブロックします。そのうえで、変更できないことを説明するようアシスタントに指示します。予約記録が変わっていないことと、音声での応答の両方を確認してください。口頭で拒否するだけでは、権限のない操作の実行は防げません。

すでに相手が聞いた音声は、修正指示を送っても取り消せません。再生前にアシスタントの発話をチェックする必要がある場合は、再生前の発話チェックに従って、バッファリング、承認、中断、復旧を処理します。操作の制御と修正指示の例は、会話へのガードレールの適用を参照してください。冒頭で所定の文言を伝える必要がある場合は、告知の読み上げを参照してください。

移行結果の検証

現行アプリケーションでの代表的な会話を使って、移行後のアシスタントの動作を比較します。シナリオ、バックエンドのツール、成功基準をそろえて各シナリオを繰り返し、意図した動作変更とリグレッションを区別して記録します。

  • 操作と音声での確認: 空き状況を調べ、具体的な枠を予約してよいかユーザーに尋ね、同意が得られた枠だけを予約します。バックエンドでの処理結果、音声での回答、クライアントでの再生を別々に検証します。
  • 訂正と重複防止: リクエストの処理中に希望日を木曜日から金曜日に変更します。古い結果を破棄し、再試行しても予約が重複しないことを確認します。
  • 権限: 権限のない操作と、ユーザーの同意を得ていない予約を試します。アプリケーションのポリシーによって実行がブロックされることを確認します。
  • ガードレールによる介入: 発話中やツールの実行中にチェックを発動させます。アシスタントが修正指示を受け取ること、ツールの結果が遅れて届いても対象の操作がブロックされたままであること、再生が意図どおりに再開することを検証します。実行中だった操作が実際に停止したかも確認します。チェックに時間がかかる場合や誤検知もテストに含めてください。
  • 割り込み: アシスタントの発話中や処理中に話しかけます。会話、音声再生、バックエンドのタスク状態をそれぞれ検証します。
  • 障害と再接続: ツールのエラー、結果の消失、接続の切断をテストします。予約リクエストの応答を受け取れなかった場合は、再試行する前に予約が成立したかどうかを確認します。保存済みのタスクのコンテキストを使って次の音声セッションを開始し、確認済みの処理結果を引き継いで会話を続けられることを検証します。

バックエンドのレイテンシの削減を参考に、移行後のバックエンドを調整します。Cookbook の音声エージェント評価ガイドを使い、ユーザーにとって有用な音声応答が返るまでの時間とタスクの成否を比較します。使用量とコストの比較にはコストの最適化を参照してください。