Unity で OpenAI 社の ChatGPT API とやり取りするメモ

Unity で OpenAI 社の ChatGPT API とやり取りするメモです。
Unity に Cube を準備
2023/09 現在の情報で進めます。
Unity に Cube を準備します。ほか EventSystem やカメラに Physics Raycaster を仕込んでいる状態で、クリックすれば動作する状態です。
Cube に CubeEvent.cs を割り当て
Cube に CubeEvent.cs を割り当てます。
using UnityEngine;
using UnityEngine.EventSystems;
using System.Collections; // IEnumerator のための参照
using UnityEngine.Networking; // UnityWebRequest のための参照
using System; // Serializable のための参照
using System.Text; // Encoding のための参照
using System.Collections.Generic;
public class CubeEvent : MonoBehaviour, IPointerClickHandler
{
// 受信した JSON データを Unity で扱うデータにする ResponseData ベースクラス
// API仕様 : https://platform.openai.com/docs/api-reference/completions/object
[Serializable]
public class ResponseData
{
public string id;
public string @object; // object は予約語なので @ を使ってエスケープしています
public int created;
public List<ResponseDataChoice> choices;
public ResponseDataUsage usage;
}
[Serializable]
public class ResponseDataUsage
{
public int prompt_tokens;
public int completion_tokens;
public int total_tokens;
}
[Serializable]
public class ResponseDataChoice
{
public int index;
public RequestDataMessages message;
public string finish_reason;
}
// 送信する Unity データを JSON データ化する RequestData ベースクラス
[Serializable]
public class RequestData
{
public string model;
public List<RequestDataMessages> messages;
}
[Serializable]
public class RequestDataMessages
{
public string role;
public string content;
}
public void OnPointerClick(PointerEventData eventData)
{
// HTTP リクエストを非同期処理を待つためコルーチンとして呼び出す
StartCoroutine("PostChatGPT");
}
// ChatGPT の API キーを入力
string tokenCHatGPT = "tokenCHatGPT";
// リクエストする本体
IEnumerator PostChatGPT()
{
// HTTP リクエストする(POST メソッド) UnityWebRequest を呼び出し
// リクエスト仕様 : https://platform.openai.com/docs/guides/gpt/chat-completions-api
// API仕様 : https://platform.openai.com/docs/api-reference/completions/object
UnityWebRequest request = new UnityWebRequest("https://api.openai.com/v1/chat/completions", "POST");
RequestData requestData = new RequestData();
// データを設定
requestData.model = "gpt-3.5-turbo-0613";
RequestDataMessages currentMessage = new RequestDataMessages();
// ロールは user
currentMessage.role = "user";
// 実際の質問
currentMessage.content = "こんにちは!";
List<RequestDataMessages> currentMessages = new List<RequestDataMessages>();
currentMessages.Add(currentMessage);
requestData.messages = currentMessages;
Debug.Log($"currentMessages[0].content : {currentMessages[0].content}");
// 送信データを JsonUtility.ToJson で JSON 文字列を作成
// RequestData, RequestDataMessages の構造に基づいて変換してくれる
string strJSON = JsonUtility.ToJson(requestData);
Debug.Log($"strJSON : {strJSON}");
// 送信データを Encoding.UTF8.GetBytes で byte データ化
byte[] bodyRaw = Encoding.UTF8.GetBytes(strJSON);
// アップロード(Unity→サーバ)のハンドラを作成
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
// ダウンロード(サーバ→Unity)のハンドラを作成
request.downloadHandler = new DownloadHandlerBuffer();
// JSON で送ると HTTP ヘッダーで宣言する
request.SetRequestHeader("Content-Type", "application/json");
// ChatGPT 用の認証を伝える設定
request.SetRequestHeader("Authorization", $"Bearer {tokenCHatGPT}");
// リクエスト開始
yield return request.SendWebRequest();
Debug.Log("リクエスト...");
// 結果によって分岐
switch (request.result)
{
case UnityWebRequest.Result.InProgress:
Debug.Log("リクエスト中");
break;
case UnityWebRequest.Result.ProtocolError:
Debug.Log("ProtocolError");
Debug.Log(request.responseCode);
Debug.Log(request.error);
break;
case UnityWebRequest.Result.ConnectionError:
Debug.Log("ConnectionError");
break;
case UnityWebRequest.Result.Success:
Debug.Log("リクエスト成功");
// コンソールに表示
Debug.Log($"responseData: {request.downloadHandler.text}");
ResponseData resultResponse = JsonUtility.FromJson<ResponseData>(request.downloadHandler.text);
// 返答
Debug.Log($"resultResponse.choices[0].message : {resultResponse.choices[0].message.content}");
break;
}
}
}
送信する Unity データを JSON データ化する仕組み
送信する Unity データを JSON データ化する RequestData ベースクラスは、以下の通りです。
// 送信する Unity データを JSON データ化する RequestData ベースクラス
[Serializable]
public class RequestData
{
public string model;
public List<RequestDataMessages> messages;
}
[Serializable]
public class RequestDataMessages
{
public string role;
public string content;
}
The completion object API Reference にあるとおり、
{
"id": "cmpl-uqkvlQyYK7bGYrRHQ0eXlWi7",
"object": "text_completion",
"created": 1589478378,
"model": "gpt-3.5-turbo",
"choices": [
{
"text": "\n\nThis is indeed a test",
"index": 0,
"logprobs": null,
"finish_reason": "length"
}
],
"usage": {
"prompt_tokens": 5,
"completion_tokens": 7,
"total_tokens": 12
}
}
のようなデータ作成するために、データ構造を定義しています。
受信した JSON データを Unity で扱う仕組み
受信した JSON データを Unity で扱うデータにする ResponseData ベースクラスは、以下の通りです。
// 受信した JSON データを Unity で扱うデータにする ResponseData ベースクラス
// API仕様 : https://platform.openai.com/docs/api-reference/completions/object
[Serializable]
public class ResponseData
{
public string id;
public string @object; // object は予約語なので @ を使ってエスケープしています
public int created;
public List<ResponseDataChoice> choices;
public ResponseDataUsage usage;
}
[Serializable]
public class ResponseDataUsage
{
public int prompt_tokens;
public int completion_tokens;
public int total_tokens;
}
[Serializable]
public class ResponseDataChoice
{
public int index;
public RequestDataMessages message;
public string finish_reason;
}
Create completio API Reference にあるとおり
{
"id": "cmpl-uqkvlQyYK7bGYrRHQ0eXlWi7",
"object": "text_completion",
"created": 1589478378,
"model": "gpt-3.5-turbo-instruct",
"choices": [
{
"text": "\n\nThis is indeed a test",
"index": 0,
"logprobs": null,
"finish_reason": "length"
}
],
"usage": {
"prompt_tokens": 5,
"completion_tokens": 7,
"total_tokens": 12
}
}
のようなデータを受け取るために JSON 構造を定義しています。object は予約語なので @ を使ってエスケープしているところが、いろいろ確認してがんばりました。
APIのやり取りする部分
APIのやり取りする部分はこちらです。ResonseData クラスをもとに JSON データを作っていて currentMessage.content = "こんにちは!";
のところで、ChatGPT への質問を作っています。データを受け取ったら ResponseData クラスで受け止めて resultResponse.choices[0].message.content
で回答を取り出しています。
// リクエストする本体
IEnumerator PostChatGPT()
{
// HTTP リクエストする(POST メソッド) UnityWebRequest を呼び出し
// リクエスト仕様 : https://platform.openai.com/docs/guides/gpt/chat-completions-api
// API仕様 : https://platform.openai.com/docs/api-reference/completions/object
UnityWebRequest request = new UnityWebRequest("https://api.openai.com/v1/chat/completions", "POST");
RequestData requestData = new RequestData();
// データを設定
requestData.model = "gpt-3.5-turbo-0613";
RequestDataMessages currentMessage = new RequestDataMessages();
// ロールは user
currentMessage.role = "user";
// 実際の質問
currentMessage.content = "こんにちは!";
List<RequestDataMessages> currentMessages = new List<RequestDataMessages>();
currentMessages.Add(currentMessage);
requestData.messages = currentMessages;
Debug.Log($"currentMessages[0].content : {currentMessages[0].content}");
// 送信データを JsonUtility.ToJson で JSON 文字列を作成
// RequestData, RequestDataMessages の構造に基づいて変換してくれる
string strJSON = JsonUtility.ToJson(requestData);
Debug.Log($"strJSON : {strJSON}");
// 送信データを Encoding.UTF8.GetBytes で byte データ化
byte[] bodyRaw = Encoding.UTF8.GetBytes(strJSON);
// アップロード(Unity→サーバ)のハンドラを作成
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
// ダウンロード(サーバ→Unity)のハンドラを作成
request.downloadHandler = new DownloadHandlerBuffer();
// JSON で送ると HTTP ヘッダーで宣言する
request.SetRequestHeader("Content-Type", "application/json");
// ChatGPT 用の認証を伝える設定
request.SetRequestHeader("Authorization", $"Bearer {tokenCHatGPT}");
// リクエスト開始
yield return request.SendWebRequest();
Debug.Log("リクエスト...");
// 結果によって分岐
switch (request.result)
{
case UnityWebRequest.Result.InProgress:
Debug.Log("リクエスト中");
break;
case UnityWebRequest.Result.ProtocolError:
Debug.Log("ProtocolError");
Debug.Log(request.responseCode);
Debug.Log(request.error);
break;
case UnityWebRequest.Result.ConnectionError:
Debug.Log("ConnectionError");
break;
case UnityWebRequest.Result.Success:
Debug.Log("リクエスト成功");
// コンソールに表示
Debug.Log($"responseData: {request.downloadHandler.text}");
ResponseData resultResponse = JsonUtility.FromJson<ResponseData>(request.downloadHandler.text);
// 返答
Debug.Log($"resultResponse.choices[0].message : {resultResponse.choices[0].message.content}");
break;
}
}
}
ChatGPT の API キーを設定
Cube に CubeEvent.cs 設定できたら、以下の対応をします。
// ChatGPT の API キーを入力
string tokenCHatGPT = "tokenCHatGPT";
こちらで ChatGPT の API キーを設定します。
動かしてみる
ここまで設定できたら、Play ボタンを押して動かしてみます。
Cube をクリックしてみます。
API とやり取りが行われ「こんにちは!」という内容に、「こんにちは!ご用件ありますか?」と ChatGPT が回答した結果が表示されます。