OpenAI Realtime APIを動かしてみた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/86e89641-f54b-044c-0dbb-8ca13e68e41f.png)

作成日：2024年10月20日(日)

## １．はじめに

私たちがこれまでに生成AIで使用してきた自然言語処理(NLP:Neuro Linguistic Programming)はChatGPTなどのチャットボットに代表されるように話者が交互にしか会話できませんでした。通信の世界ではこれを半二重通信と呼んでいます。
しかし一般的な会社の会議や人との会話では、会話に割り込んだり（カットイン）したり、同時に話したりすることが多くあります。
これは通信の世界では全二重通信と呼んでいます。
交互にしか会話できない事例としてトランシーバーなどを想像してもらうとイメージしやすいかもしれません。
同時に会話できる事例としては電話が分かりやすいですよね。
子供の頃、玩具のトランシーバーなどで遊んでいて交互にしか話せない仕組みがスパイ映画などみたいでかっこいいなんて記憶がある方もいるのではないでしょうか？
しかし、相互にしか話せないというのは普段使いすると結構なストレスとなるものです。
OpenAI Realtime APIは話者が同時に会話できるようにする画期的な技術なんです。
この技術は、ベクトルデータベースの検索や社内のRESTful APIを通じたデータレイクからの情報取得、さらにはAIによるファシリテーション機能の実現など、多様な可能性を秘めています。まさに、私たちの想像力を大きく刺激する革新的な技術と言えるでしょう。
この記事では、AIによるファシリテーションの可能性を探るため、関連情報を整理していきます。

半二重通信の図解：

```mermaid
sequenceDiagram
    participant A as デバイスA
    participant B as デバイスB
    A->>B: データ送信
    Note over A,B: Aが送信中、Bは待機
    B->>A: データ送信
    Note over A,B: Bが送信中、Aは待機
```

半二重通信では、一度に一方向のみの通信が可能です。デバイスAがデータを送信している間、デバイスBは受信のみを行い、送信することはできません。その後、役割が入れ替わり、デバイスBが送信、デバイスAが受信を行います。この方式では、同時に双方向の通信を行うことはできません。

全二重通信の図解：

```mermaid
sequenceDiagram
    participant A as デバイスA
    participant B as デバイスB
    A->>B: データ送信
    B->>A: データ送信
    Note over A,B: AとBが同時に送受信可能
```

全二重通信では、デバイスAとデバイスBが同時に双方向の通信を行うことができます。両方のデバイスが同時にデータを送信および受信することが可能で、これにより効率的で遅延の少ない通信が実現します。

## ２．OpenAI Realtime APIとは
OpenAI Realtime APIは、2024年5月13日にOpenAIが[Spting Update](https://openai.com/index/spring-update/)の中で公式に発表したAdvanced Voice Modeという新しいサービスで利用されるAPIです。この発表は、AIの世界に大きな反響を呼び、多くの開発者や企業の注目を集めました。

Spring UpdateではではAPIの公開は段階的に行われました。まず、発表から約４ヶ月後にAdvanced Voice ModeがChatGPT Plus以上の有料会員向けに少しずつ公開され、その後、2024年10月1日にベータ版のAPIが一般に公開され、開発者がリアルタイムAI機能を自社のアプリケーションに組み込むことが可能になりました。その後、2024年10月3日に正式版のAPIが一般公開され、より多くのユーザーがこの革新的な技術にアクセスできるようになりました。

OpenAIは、APIの公開と同時にGitHubでサンプルコードも公開しました。このサンプルコードは、JavaScriptやPython、Rubyなど、複数のプログラミング言語に対応しており、開発者がRealtime APIを素早く理解し、実装できるように設計されています。

技術的には、OpenAI Realtime APIはWebSocket技術を利用しています。WebSocketを使用することで、クライアントとサーバー間で双方向のリアルタイム通信が可能となり、従来のRESTful APIよりも高速で効率的な通信を実現しています。

このAPIの主な特徴は、AIモデルからの応答をストリーミング形式で受け取れることです。これにより、ユーザーは完全な応答を待つ必要がなく、生成される文章をリアルタイムで見ることができます。また、ユーザーの入力に基づいてAIの出力を動的に調整することも可能になり、より対話的で自然なAIとのやり取りが実現しました。

OpenAI Realtime APIは、チャットボット、リアルタイム翻訳、動的なコンテンツ生成など、幅広いアプリケーションに活用できる可能性を秘めており、AI技術の新たな可能性を切り開くものとして期待されています。正式版の一般公開により、これらの可能性がさらに広がることが期待されています。

[Spring Update](https://openai.com/index/spring-update/)

## ３．Realtime APIとは

OpenAI Realtime APIは従来のOpenAI APIと比較して、以下の点で大きく異なります：

| No | 比較ポイント | 説明 |
| --- | --- | --- |
| 1 | プロトコル | 従来のAPIはHTTP/RESTを使用。**Realtime APIはWebSocket**を利用し、双方向のリアルタイム通信が可能。 |
| 2 | 呼び出し方法 | 従来のAPIは単一のリクエスト/レスポンスモデル。Realtime APIは**継続的な接続**を維持し、**複数のメッセージをストリーミング形式で送受信**。 |
| 3 | レスポンス形式 | 従来のAPIは完全な応答を一度に返す。**Realtime APIは部分的な応答をリアルタイムで返し、AIの思考プロセスをリアルタイムで観察可能**。 |
| 4 | インタラクション | 従来のAPIは基本的に一問一答形式。**Realtime APIは途中で質問を変更したり、AIの回答を中断したりすることが可能。** |
| 5 | パフォーマンス | Realtime APIはWebSocketを使用し、HTTPリクエストの**オーバーヘッドが削減され、より高速な応答が可能**。 |
| 6 | 使用シナリオ | Realtime APIは、**リアルタイムチャット、ライブコーディング支援、動的なコンテンツ生成**など、より対話的で即時性の高いアプリケーションに適している。 |

これらの違いにより、OpenAI Realtime APIは従来のAPIよりも柔軟で自然な対話型AIアプリケーションの開発を可能にしています。

[Introducing the Realtime API](https://openai.com/index/introducing-the-realtime-api/)

## ４．Realtime APIの体験

| No | 手段 | 説明 |
| --- | --- | --- |
| 1 | [ChatGPT Plus/Teams/Enterprise](https://chatgpt.com/) | ChatGPTの有料版サービスで、Advanced Voice Modeを利用してリアルタイムの音声対話が可能。最も簡単に体験できる方法。 |
| 2 | [OpenAI Playground(Realtime)](https://platform.openai.com/playground/realtime) | OpenAIが提供するWebインターフェースで、コードを書かずにRealtime APIの機能をテストできる環境。開発者向けの試験的利用に適している。 |
| 3 | [openai/openai-realtime-console](https://github.com/openai/openai-realtime-console) | GitHubで公開されているオープンソースのコンソールアプリケーション。開発者がローカル環境でRealtime APIを試すのに適している。カスタマイズも可能。 |

## ５．openai-realtime-console

### 5.1 openai-realtime-consoleとは

openai-realtime-consoleは、OpenAIが提供するReact製のオープンソースアプリケーションで、Realtime APIの機能を検査、構築、デバッグするためのツールです。以下にその主な特徴を示します。

- APIレスポンスの詳細な検査が可能
- カスタムプロンプトの作成と保存機能
- APIパラメータの調整が可能
- WebSocketを使用したリアルタイム通信のデモンストレーション

| No | 特徴 | 説明 |
| --- | --- | --- |
| 1 | 対話型コンソール | Realtime APIの機能をブラウザ上でWeb UI(realtime console)で直接テストできる  <br>また、音声ストリームの送信、音声ストリームの再生、VAD(Voice Activity Detection：音声区間検出)モードを備えています。 |
| 2 | メモリー機能<br>(ツールのサンプルで実装) | 会話の中から覚えておいてほしいことを自動的にjson形式に変換してセッション中覚えておくことができます。  <br>例えば「私の誕生日は7月6日です。覚えておいてくださいね。」と発話すると右下のset_memory()エリアにjsonで記憶されます。もちろん、「私の誕生日はいつでしたっけ？」と発話すると答えます。 |
| 3 | 位置情報に基づく天気予報の取得<br>(ツールのサンプルで実装) | 通常の対話型コンソールに加えリレーサーバと対話型コンソールの分離機能にも対応し、自分で作成したアプリケーションをリレーサーバ経由で試すことができます。 |
| 4 | ツールの追加機能 | src/pages/ConsolePages.tsx内でclient.addToolを呼び出し既存の「メモリー機能」、「位置情報に基づく天気予報の取得」のほかに新たなツールを追加することも可能です。 |
| 5 | カットイン(Interrupting the model) | 再生中の音声ストリームを削除して、会話を中断できます。 |
| 6 | カスタムプロンプト | カスタムプロンプトの作成と保存機能 |
| 7 | パラメータ調整 | APIパラメータの調整が可能 |
| 8 | リアルタイム通信 | WebSocketを使用したリアルタイム通信のデモンストレーション |

このツールは、開発者がRealtime APIの動作を理解し、自身のアプリケーションに統合する際の参考として非常に有用です。GitHubリポジトリには、アプリケーションのセットアップ方法や使用方法に関する詳細な説明が含まれており、誰でも簡単に利用を開始できるようになっています。

### 5.2 環境

今回、openai/openai-realtime-consoleを実験する環境について記載します。

| No | 項目 | 説明 | 備考 |
| --- | --- | --- | --- |
| 1 | OS | Windows11 | - |
| 2 | アプリ | Git version 2.43.0.windows.1<br>TortoiseGit 2.16.0.0 | - |
| 3 | 利用言語 | Node.js v20.12.2 | - |
| 4 | ネットワーク環境 | NAPT(IP Masquerade) | かんたんに言うと良くある自宅環境<br>プロキシを使用せず、ルータでインターネットと直接通信ができる環境です |

### 5.3 導入手順
①Git Clone
![openai-realtime-console_git_clone.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/a5ccb58f-8b70-fe54-d92a-f01e7fa42477.png)

②Node.jsの依存パッケージのインストール

プロジェクトフォルダ内のpackage.jsonに基づいて、Node.jsの依存パッケージをインストールします。
私の環境では、このインストール作業に約2～3分程度かかりました。

```
Q:\OneDrive\Node.js\openai-realtime-console>npm install
npm WARN deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm WARN deprecated rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported
npm WARN deprecated abab@2.0.6: Use your platform's native atob() and btoa() methods instead
npm WARN deprecated stable@0.1.8: Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility
npm WARN deprecated rollup-plugin-terser@7.0.2: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser
npm WARN deprecated w3c-hr-time@1.0.2: Use your platform's native performance.now() and performance.timeOrigin.
npm WARN deprecated sourcemap-codec@1.4.8: Please use @jridgewell/sourcemap-codec instead
npm WARN deprecated q@1.5.1: You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.
npm WARN deprecated
npm WARN deprecated (For a CapTP with native promises, see @endo/eventual-send and @endo/captp)
npm WARN deprecated workbox-cacheable-response@6.6.0: workbox-background-sync@6.6.0
npm WARN deprecated workbox-google-analytics@6.6.0: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained
npm WARN deprecated svgo@1.3.2: This SVGO version is no longer supported. Upgrade to v2.x.x.
npm WARN deprecated @babel/plugin-proposal-private-methods@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.
npm WARN deprecated @babel/plugin-proposal-numeric-separator@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.
npm WARN deprecated @babel/plugin-proposal-class-properties@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.
npm WARN deprecated @babel/plugin-proposal-nullish-coalescing-operator@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.
npm WARN deprecated @babel/plugin-proposal-optional-chaining@7.21.0: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.
npm WARN deprecated @babel/plugin-proposal-private-property-in-object@7.21.11: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead.
npm WARN deprecated domexception@2.0.1: Use your platform's native DOMException instead
npm WARN deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
npm WARN deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
npm WARN deprecated @humanwhocodes/config-array@0.11.14: Use @eslint/config-array instead

added 1549 packages, and audited 1550 packages in 2m

263 packages are looking for funding
  run `npm fund` for details

15 vulnerabilities (1 low, 4 moderate, 10 high)

To address issues that do not require attention, run:
  npm audit fix

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
npm notice
npm notice New minor version of npm available! 10.5.0 -> 10.9.0
npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.9.0
npm notice Run npm install -g npm@10.9.0 to update!
npm notice

Q:\OneDrive\Node.js\openai-realtime-console>
```

### 5.4 実行

openai-realtime-consoleを起動するには、「npm start」コマンドを使用します。

```
Q:\OneDrive\Node.js\openai-realtime-console>npm start

> openai-realtime-console@0.0.0 start
> react-scripts start

(node:10052) [DEP_WEBPACK_DEV_SERVER_ON_AFTER_SETUP_MIDDLEWARE] DeprecationWarning: 'onAfterSetupMiddleware' option is deprecated. Please use the 'setupMiddlewares' option.
(Use `node --trace-deprecation ...` to show where the warning was created)
(node:10052) [DEP_WEBPACK_DEV_SERVER_ON_BEFORE_SETUP_MIDDLEWARE] DeprecationWarning: 'onBeforeSetupMiddleware' option is deprecated. Please use the 'setupMiddlewares' option.
Starting the development server...
Compiled successfully!

You can now view openai-realtime-console in the browser.

  Local:            http://localhost:3000
  On Your Network:  http://192.168.1.137:3000

Note that the development build is not optimized.
To create a production build, use npm run build.

LOG from ./node_modules/sass-loader/dist/cjs.js sass-loader ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[7].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[7].use[2]!./node_modules/resolve-url-loader/index.js??ruleSet[1].rules[1].oneOf[7].use[3]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[7].use[4]!./src/pages/ConsolePage.scss
<w> Deprecation Sass's behavior for declarations that appear after nested
<w> rules will be changing to match the behavior specified by CSS in an upcoming
<w> version. To keep the existing behavior, move the declaration above the nested
<w> rule. To opt into the new behavior, wrap the declaration in `& {}`.
<w>
<w> More info: https://sass-lang.com/d/mixed-decls
<w>
<w> src\pages\ConsolePage.scss 223:9  root stylesheet
<w>
<w> Deprecation Sass's behavior for declarations that appear after nested
<w> rules will be changing to match the behavior specified by CSS in an upcoming
<w> version. To keep the existing behavior, move the declaration above the nested
<w> rule. To opt into the new behavior, wrap the declaration in `& {}`.
<w>
<w> More info: https://sass-lang.com/d/mixed-decls
<w>
<w> src\pages\ConsolePage.scss 224:9  root stylesheet
<w>
<w> Deprecation Sass's behavior for declarations that appear after nested
<w> rules will be changing to match the behavior specified by CSS in an upcoming
<w> version. To keep the existing behavior, move the declaration above the nested
<w> rule. To opt into the new behavior, wrap the declaration in `& {}`.
<w>
<w> More info: https://sass-lang.com/d/mixed-decls
<w>
<w> src\pages\ConsolePage.scss 225:9  root stylesheet
<w>
<w> Deprecation Sass's behavior for declarations that appear after nested
<w> rules will be changing to match the behavior specified by CSS in an upcoming
<w> version. To keep the existing behavior, move the declaration above the nested
<w> rule. To opt into the new behavior, wrap the declaration in `& {}`.
<w>
<w> More info: https://sass-lang.com/d/mixed-decls
<w>
<w> src\pages\ConsolePage.scss 226:9  root stylesheet
<w>

webpack compiled successfully
No issues found.
```

起動すると、realtime consoleのWeb画面がhttp://localhost:3000/で開きます。
![realtime_console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/908b7685-188a-1b5d-fa2b-e320581f9b99.png)

## ６．openai-realtime-consoleの使い方
openai-realtime-consoleはWeb画面(http://localhost:3000/)から使用します。
初回の起動ではOpenAI API Keyの入力を求められます。
※OpenAI API Keyの取得方法は割愛しますのでググってください。

### 6.1 OpenAI APIキーの設定

「npm start」コマンドでopenai-realtime-consoleを起動するとOpenAI API Keyの入力を求められるので、入力します。

![request_openai_api_key.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/ac736218-0feb-1b86-e134-29f9013cb35f.png)

### 6.2 大谷翔平の功績を聞いてみた

<iframe width="560" height="315" src="https://www.youtube.com/embed/VTXSHjFw9tI?si=p72l28EADlXoc8-3" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## ７．気になる利用料金

ちょっと会話して遊んだだけで、$9.76（1ドル150円換算で1,464円）かかりました。個人で使うには、なかなか厳しい金額ですね。

OpenAIのAPIの料金は、ダッシュボードで確認できます。確認方法は以下の通りです：
[[OpenAI](https://openai.com/)] → [[API login](https://platform.openai.com/docs/overview)] → [[Dashboard](https://platform.openai.com/chat-completions)] → [[Usage](https://platform.openai.com/usage)]

![realtime_api_bulling.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/de460b3b-ac15-3eab-c3a8-e99b313b456a.png)

## ８．設定を変えてみよう
### 8.1 システムプロンプト

OpenAI APIではConversation毎にシステムプロンプトを設定できましたが、OpenAI Realtime APIではInstructionという設定を行います。

名前が違っていたので調べるのに時間が掛りました。
このInstructionはconversation_config.jsというファイルのinstructions定数で設定しています。

conversation_config.jsはConsolePage.tsxの19行目付近で読み込まれています。

openai-realtime-console\src\utils\conversation_config.js

```
export const instructions = `System settings:
Tool use: enabled.

Instructions:
- You are an artificial intelligence agent responsible for helping test realtime voice capabilities
- Please make sure to respond with a helpful voice via audio
- Be kind, helpful, and curteous
- It is okay to ask the user questions
- Use tools and functions you have available liberally, it is part of the training apparatus
- Be open to exploration and conversation
- Remember: this is just for fun and testing!

Personality:
- Be upbeat and genuine
- Try speaking quickly as if excited
`;

```

### 8.2 音声の変更

音声の変更については [README.md](http://README.md) にも記載がありますが、client.updateSession メソッドで voice パラメータに 'alloy'、'echo'、'shimmer' などの音声キャラクターを指定することで実現できそうです。

ConsolePage.tsxの以下

```
379    // Set instructions
380    client.updateSession({ instructions: instructions });
381    // Set transcription, otherwise we don't get user transcriptions back
382    client.updateSession({ input_audio_transcription: { model: 'whisper-1' } });
```

追加するコード

```
client.updateSession({ voice: 'echo' });
```

## ９．疑問点

ソースコードを調査した結果、理解できなかった点を以下に列挙します。

| No | 項目 | 疑問点 |
| --- | --- | --- |
| 1 | Instructions(システムプロンプト) | AIによるファシリテーションを実現するには、議論の誘導やサマライズが不可欠です。これらの機能を効果的に実行するには、メモリ機能や文字起こし機能と連携した包括的な指示が必要となります。<br>しかし、Instructionsにはかなりの量の指示を与える必要がありそうです。その上限や制約については、まだ確認できていません。 |
| 2 | 話者識別 | ファシリテータの役割として、発言の少ない参加者に発言を促すことが重要です。そのためには、会議参加者を認識し、発言のバランスを把握する必要があります。この点で、話者認識機能は実現可能なのでしょうか？<br>今回の検証でウィスキー１杯分は使ってしまったので、この疑問点の調査は次回に持ち越すことにします。 |
| 3 | 文字起こし | ファシリテータは最後に議論のサマリーをまとめて発表する必要があります。そのためには、会議中の発言を話者ごとに分離しつつ、正確に文字起こしする必要があります。これを実現するには、AIのメモリ機能を活用するべきでしょうか？あるいは、ツール機能を使って外部データベースに重要な決定事項を逐次記録していくのが効果的でしょうか？この点に関しては、まだ多くの課題が残されています。 |

## １０．感想

OpenAIのAdvanced Voice ModeがiPhoneのChatGPTアプリで使用できたときの感動をPC環境で体験できたことはとても喜ばしいことでした。一方、今回のサンプルプログラムはNode.jsで記述されており、Python派の私にはなかなか理解が難しいのが現状です。
また、会社には企業プロキシがあり、Websocketからみを企業プロキシに対応させたり、プロキシサーバのサーバ証明書を読ませたりととても大変です。
さらに現時点でOpenAIのRealtime APIはクラウドを利用するしかなく、私の会社ではセキュリティポリシーが厳しいため、業務情報をインターネット回線でクラウドに渡すことができそうにありません。
そのためAzure OpenAIでのRealtime APIのサポートを待つ他ありません。

## １１．参考URL

https://github.com/openai/openai-realtime-console

https://github.com/openai/openai-realtime-api-beta

https://platform.openai.com/docs/guides/realtime

https://platform.openai.com/docs/api-reference/introduction

https://platform.openai.com/playground/realtime

https://note.com/izai/n/n326ff9a1c9d9

https://zenn.dev/asap/articles/4368fd306b592a