この記事は、面白法人グループ Advent Calendar 2022 の13日目の記事です。
カヤックボンドでエンジニアをやっております中野です。
今回はChatGPTで使用されているGPT-3.5系のモデル「text-davinci-003」のAPIを
Unity上から実行してデータを取得するお話をします。
ChatGPTとは
2022年11月30日に発表されたOpenAIが開発するGPT-3.5系の言語モデルを用いたチャットアプリです。
対話形式で、UnityのコードからDB設計まで様々なこと出力してくれます。
かなり賢い。
ChatGPTの使い方について下記が詳しくまとまっております。 qiita.com
最初に
どうやら有志の方が作成したUnity用のAPIライブラリがすでにありました。
確認したところ、2022/12/10現在 最新の「text-davinci-003」は対応されていなかった。。。
https://beta.openai.com/docs/libraries/python-bindings
GitHub - hexthedev/OpenAi-Api-Unity: Integration for the OpenAi Api in Unity
ということで「text-davinci-003」を対応したシンプルなものを作ろう!
事前準備
OpenAIの公式ページよりアカウント発行とAPIのKEYの発行を行います。
アカウント発行
https://auth0.openai.com/u/login/
API KEYの取得
下記ページ内の「Create new secret key」ボタンを押してKEYを発行します。
https://beta.openai.com/account/api-keys
※KEYはアカウント内で再度表示されないため、ご注意ください。
KEYがわからなくなった場合は同ページ内で再発行する必要があります。
検証環境
名前 | 備考 |
---|---|
Windows10 | |
Unity 2021.3.14 | https://unity.com/ja/download |
UniTask Ver.2.3.3 | https://github.com/Cysharp/UniTask/releases |
Newtonsoft.Json | APIリクエスト/レスポンスのシリアライズ・デシリアライズに使用。 下記を参考にさせていただきました。 Unity2020でNewtonsoft.Jsonを入れる - Qiita |
実装
検証スクリプト
using UnityEngine; using UnityEngine.UI; using UnityEngine.Networking; using Newtonsoft.Json; using System; using System.Linq; using Cysharp.Threading.Tasks; public class SendChatGPT: MonoBehaviour { /// <summary> /// APIエンドポイント /// </summary> const string API_END_POINT = "https://api.openai.com/v1/completions"; /// <summary> /// API KEY /// </summary> const string API_KEY = "USER_API_KEY"; /// <summary> /// 入力欄 /// </summary> [SerializeField] private InputField Input; [SerializeField] private Text Output; [SerializeField] private Button ExecButton; [SerializeField] private Button QuitButton; private void Start() { // API実行ボタン ExecButton.onClick.AddListener(async () => { //入力取得 string prompt = Input.text; if (!string.IsNullOrEmpty(prompt)) { //レスポンス取得 var response = await GetAPIResponse(prompt) ; //レスポンスからテキスト取得 string outputText = response.Choices.FirstOrDefault().Text; Output.text = outputText.TrimStart('\n'); Debug.Log(outputText); } }); // 終了ボタン QuitButton.onClick.AddListener(() => { Application.Quit(); }); } /// <summary> /// APIからレスポンス取得 /// </summary> /// <param name="prompt"></param> /// <returns></returns> /// <exception cref="ArgumentOutOfRangeException"></exception> public async UniTask<APIResponseData> GetAPIResponse(string prompt) { APIRequestData requestData = new() { Prompt = prompt, MaxTokens = 300 //レスポンスのテキストが途切れる場合、こちらを変更する }; string requestJson = JsonConvert.SerializeObject(requestData, Formatting.Indented); Debug.Log(requestJson); // POSTするデータ byte[] data = System.Text.Encoding.UTF8.GetBytes(requestJson); string jsonString = null; // POSTリクエストを送信 using (UnityWebRequest request = UnityWebRequest.Post(API_END_POINT, "POST")) { request.uploadHandler = new UploadHandlerRaw(data); request.downloadHandler = new DownloadHandlerBuffer(); request.SetRequestHeader("Content-Type", "application/json"); request.SetRequestHeader("Authorization", "Bearer " + API_KEY); await request.SendWebRequest(); switch (request.result) { case UnityWebRequest.Result.InProgress: Debug.Log("リクエスト中"); break; case UnityWebRequest.Result.Success: Debug.Log("リクエスト成功"); jsonString = request.downloadHandler.text; // レスポンスデータを表示 Debug.Log(jsonString); break; default: throw new ArgumentOutOfRangeException(); } } // デシリアライズ APIResponseData jsonObject = JsonConvert.DeserializeObject<APIResponseData>(jsonString); return jsonObject; } }
APIリクエスト/レスポンス スクリプト
using Newtonsoft.Json; /// <summary> /// APIリクエスト /// /// https://beta.openai.com/docs/api-reference/authentication /// </summary> [JsonObject] public class APIRequestData { [JsonProperty("model")] public string Model { get; set; } = "text-davinci-003"; [JsonProperty("prompt")] public string Prompt { get; set; } = ""; [JsonProperty("temperature")] public int Temperature { get; set; } = 0; [JsonProperty("max_tokens")] public int MaxTokens { get; set; } = 100; } /// <summary> /// APIレスポンス /// /// https://beta.openai.com/docs/api-reference/authentication /// </summary> [JsonObject] public class APIResponseData { [JsonProperty("id")] public string Id { get; set; } [JsonProperty("object")] public string Object { get; set; } [JsonProperty("model")] public string Model { get; set; } [JsonProperty("created")] public int Created { get; set; } [JsonProperty("choices")] public ChoiceData[] Choices { get; set; } [JsonProperty("usage")] public UsageData Usage { get; set; } } [JsonObject] public class UsageData { [JsonProperty("prompt_tokens")] public int PromptTokens { get; set; } [JsonProperty("completion_tokens")] public int CompletionTokens { get; set; } [JsonProperty("total_tokens")] public int TotalTokens { get; set; } } [JsonObject] public class ChoiceData { [JsonProperty("text")] public string Text { get; set; } [JsonProperty("index")] public int Index { get; set; } [JsonProperty("logprobs")] public string Logprobs { get; set; } [JsonProperty("finish_reason")] public string FinishReason { get; set; } }
動作確認
1. Unityについて質問してみる。
入力 : Unityとは何ですか?
2. おすすめ観光地について聞いてみる。
入力 : 日本のおすすめ観光地はどこですか?
うまく取得できているみたいですね! APIより取得できたテキストが途切れる場合は、 リクエストの「max_tokens 」を大きな値に調整する必要があります。
最後に
今回の記事では、UnityからChatGPTのAPI実行についてお話しました。
最後までお読みいただきありがとうございました!!