HTTPプロトコルは、代表的なステートレスなプロトコルになるので、HTTP APIのデータ送受信もステートレスになります。つまり、HTTP APIを呼ぶ出す場合、サーバー側でレスポンスの生成が全て完了してクライアントに返すという1回のやり取りだけでセッションが完了します。しかし、サーバー送信イベント(SSE)という技術を使うことで、APIからのレスポンスをリアルタイムに返す事ができるようになります。
本文では、ChatGPT APIを呼び出すと、サーバー送信イベントという技術を用いて、そのレスポンスをストリーミングする方法を皆さんに紹介します。
サーバー送信イベントとは
サーバー送信イベント(Server-Sent Events、SSE)とは、Webブラウザーとサーバー間の一方向の非同期通信方法のことです。この通信方法では、サーバーがブラウザーに対してイベントをプッシュ送信でき、ブラウザーはサーバーから送信されたイベントを受信して処理できます。SSEはHTTPプロトコルに基づいているため、サーバーとブラウザー間は長時間接続を維持でき、テキスト形式でデータ送受信を行います。長時間接続でもリソース消費が少ないため、リアルタイムな通信に向いているのが特徴です。
ChatGPT APIのstreamオプション
上記のサーバー送信イベントという技術が普及されると共に、サーバー送信イベントをChatGPT APIのstream オプションと一緒に使用すると、ChatGPT APIとリアルタイムで対話を行うことができ、ChatGPTのレスポンスをストリーム表示にする事ができます。
ChatGPT APIのStreamオプションをオンにして、サーバー送信イベントを利用してChatGPTのレスポンスをストリーミングするには、APIリクエストのBodyメッセージにstream=true
を追加して渡すだけで良いのです。
ChatGPT APIのレスポンスのストリーム表示を実現
それでは、どのようにChatGPT APIレスポンスのストリーム表示を実現しますか?まずは、ChatGPTを利用するために、いくつかのものを事前に用意する必要があります。
ChatGPT APIキー
ChatGTPT APIを利用するために、事前にOpenAIに登録して、認証用のAPIキーを取得する必要がありす。
ステップ⒈OpenAIのAPI Keysページにアクセスして、自分のアカウントでログインします。(アカウントが無ければ新規登録)
ステップ⒉「Create new secret key」ボタンをクリックして、新しいAPIキーを生成します。
APIキーを生成すると、APIキーはすぐ画面に表示されます。当該APIキーは再度と表示する事ができないので、APIキーを記録して別の保存に保管する事がお勧めです。
ChatGPT APIのプロジェクト
ChatGPTのAPIを利用するために、エンドポイント、APIドキュメントなどの情報を取得する必要もあります。ここでApidogというツールをみんさんに紹介します。Apdiogが提供しているAPI Hubサービスを利用することで、ChatGPT APIの全てのエンドポイントを見つけることもできますし、APIを直接に呼び出す事もできます。
上記のものを用意した上、Node.js、PHP、Pythonなどのフレームワークを利用して、ChatGPT APIにリクエストを送信して、レスポンスをストリーミングする事ができます。
ApidogでChatGPT APIレスポンスのストリーム表示を実現
Apidogは、サーバー送信イベントに対応できるAPIクライアントです。Apidogを使うことで、非常に直感的な操作で、サーバー送信イベントを実装する事ができます。コードを書かずにサーバー送信イベントを実装したい場合は、Apidogは一番適切なソリューションになると思います。
それでは、次は、ApidogのSSE機能を利用して、ChatGPT APIレスポンスをストリーミングする方法を皆さんに紹介します。
ChatGPTのAPIを自分のプロジェクトにクローン
Apidogを開き、左側のメニューで「API Hub」をクリックして、OpenAI API(ChatGPT)を検索します。OpenAI API(ChatGPT)を開くと、「複製」ボタンをクリックして、自分のプロジェクトにクローンする事ができます。そして、ApidogからOpenAI API(ChatGPT)を直接に利用する事ができます。
SSE 接続の開始
SSE 接続を開始するには、HTTP プロジェクトで新しい API を作成します。リクエストの送信後、レスポンスの Content-Type
に text/event-stream
が含まれている場合、Apidog は自動的に返されたデータを SSE イベントとして解析し、新しいタイムラインビューでレスポンスの内容をリアルタイムに更新します。
後処理でメッセージ内容の抽出
現在のAPIの後処理でカスタムスクリプトを追加して、各 SSE イベントから特定のフィールド値を抽出し、完全な文字列に連結します。
上記の図に示した APIを例に取ると、この APIで返されるメッセージには JSONデータが含まれています。 answer
フィールドからパラメーターの内容を抽出して、完全なテキストに連結します。
カスタム スクリプトに以下の例のコードを記述します。
// レスポンス テキストを取得
const text = pm.response.text()
// テキストを行に分割
var lines = text.split('\n');
// "content"パラメータを格納する空の配列を作成
var contents = [];
// 各行を反復処理
for (var i = 0; i < lines.length; i++) {
const line = lines[i];
// "data:"で始まらない行はスキップ
if (!line.startsWith('data:')) {
continue;
}
// JSON データを解析
try {
var data = JSON.parse(line.substring(5).trim()); // 先頭の "data: " を削除
// "choices" 配列から "content" パラメーターを取得し、配列に追加
contents.push(data.choices[0].delta.content);
} catch (e) {
// 有効なJSONデータでない場合は現在の行を無視
}
}
// "content" パラメーターを join() メソッドを使用して連結
var result = contents.join('');
// 結果を本文の "Visualize" タブに表示
pm.visualizer.set(result);
// 結果をコンソールに出力
console.log(result);
リクエストの送信後、連結されたテキストは「コンソール」で確認できます。