「Unity/ChatGPT」の版間の差分
提供: 初心者エンジニアの簡易メモ
(→サンプルを動作させる) |
(→エラーについて) |
||
| (同じ利用者による、間の12版が非表示) | |||
| 行3: | 行3: | ||
#https://beta.openai.com/ でアカウントを作成 | #https://beta.openai.com/ でアカウントを作成 | ||
#"create new secret key"を押してAPIキーを作成する | #"create new secret key"を押してAPIキーを作成する | ||
| + | |||
| + | ==参考== | ||
| + | https://techblog.kayac.com/2022-group-calendar-unity-openapi | ||
| + | |||
| + | ==料金確認== | ||
| + | https://platform.openai.com/account/usage | ||
| + | |||
| + | ==リクエスト制限== | ||
| + | https://platform.openai.com/docs/guides/rate-limits/overview | ||
| + | |||
| + | 無料ユーザは、20リクエスト/分まで | ||
| + | 従量ユーザは、60~3000リクエスト/分まで | ||
==unityサンプル== | ==unityサンプル== | ||
| − | + | Main.cs | |
| + | <pre> | ||
| + | using System.Collections; | ||
| + | using System.Collections.Generic; | ||
| + | using UnityEngine; | ||
| − | == | + | public class Main : MonoBehaviour |
| − | + | { | |
| + | [SerializeField] GptView gptView; | ||
| + | GptUseCase gptUseCase = null; | ||
| + | void Awake() | ||
| + | { | ||
| + | if (ReferenceEquals(gptUseCase, null)) | ||
| + | { | ||
| + | GptRepository gptRepository = new GptRepository(); | ||
| + | GptPresenter gptPresenter = new GptPresenter(gptView); | ||
| + | gptUseCase = new GptUseCase( | ||
| + | gptPresenter, | ||
| + | gptRepository | ||
| + | ); | ||
| + | gptUseCase.Begin(); | ||
| + | } | ||
| + | } | ||
| + | void OnDestroy() | ||
| + | { | ||
| + | if (!ReferenceEquals(gptUseCase, null)) | ||
| + | { | ||
| + | gptUseCase.Finish(); | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | </pre> | ||
| + | GptUseCase.cs | ||
<pre> | <pre> | ||
| + | using UnityEngine; | ||
| + | using System.Linq; | ||
| + | using Cysharp.Threading.Tasks; | ||
| + | using TMPro; | ||
| + | using UniRx; | ||
| + | |||
| + | public class GptUseCase | ||
{ | { | ||
| − | + | GptPresenter gptPresenter; | |
| + | GptRepository gptRepository; | ||
| + | CompositeDisposable disposable = null; | ||
| + | public GptUseCase( | ||
| + | GptPresenter gptPresenter, | ||
| + | GptRepository gptRepository | ||
| + | ) | ||
| + | { | ||
| + | this.gptPresenter = gptPresenter; | ||
| + | this.gptRepository = gptRepository; | ||
| + | } | ||
| + | /// <summary> 初回処理 </summary> | ||
| + | public void Begin() | ||
| + | { | ||
| + | disposable = new CompositeDisposable(); | ||
| + | gptPresenter.Bind(); | ||
| + | gptPresenter.ExecOnClickAsObservable | ||
| + | .Subscribe(async _ => { | ||
| + | TMP_InputField input = gptPresenter.GptView.Input; | ||
| + | string prompt = input.text; | ||
| + | if (!string.IsNullOrEmpty(prompt)) | ||
| + | { | ||
| + | var response = await gptRepository.GetAPIResponse(prompt); | ||
| + | string outputText = response.Choices.FirstOrDefault().Text; | ||
| + | string outputText = prompt; | ||
| + | outputText = outputText.TrimStart('\n'); | ||
| + | } | ||
| + | }) | ||
| + | .AddTo(disposable); | ||
| + | } | ||
| + | /// <summary> 終了処理 </summary> | ||
| + | public void Finish() | ||
| + | { | ||
| + | disposable.Dispose(); | ||
| + | disposable = null; | ||
| + | } | ||
} | } | ||
</pre> | </pre> | ||
| − | "< | + | GptDefine.cs |
| + | <pre> | ||
| + | public class GptDefine | ||
| + | { | ||
| + | /// <summary> | ||
| + | /// APIエンドポイント | ||
| + | /// </summary> | ||
| + | public const string API_END_POINT = "https://api.openai.com/v1/completions"; | ||
| + | /// <summary> | ||
| + | /// API KEY | ||
| + | /// </summary> | ||
| + | public const string API_KEY = "API_KEY"; | ||
| + | /// <summary> | ||
| + | } | ||
| + | </pre> | ||
| + | GptPresenter.cs | ||
| + | <pre> | ||
| + | using UniRx; | ||
| + | using System; | ||
| − | + | public class GptPresenter | |
| + | { | ||
| + | GptView gptView = null; | ||
| + | public GptView GptView { get => gptView; set => value = gptView; } | ||
| + | /// <summary> 実行Observable </summary> | ||
| + | IObservable<Unit> execOnClickAsObservable = null; | ||
| + | public IObservable<Unit> ExecOnClickAsObservable { get => execOnClickAsObservable; } | ||
| + | public GptPresenter(GptView gptView) | ||
| + | { | ||
| + | this.gptView = gptView; | ||
| + | } | ||
| + | public void Bind() | ||
| + | { | ||
| + | execOnClickAsObservable = gptView.ExecButton.OnClickAsObservable(); | ||
| + | } | ||
| + | } | ||
| + | </pre> | ||
| + | GptRepository.cs | ||
| + | <pre> | ||
| + | using UnityEngine.Networking; | ||
| + | using Newtonsoft.Json; | ||
| + | using System; | ||
| + | using Cysharp.Threading.Tasks; | ||
| − | == | + | public class GptRepository |
| − | + | { | |
| + | /// <summary> | ||
| + | /// APIからレスポンス取得 | ||
| + | /// </summary> | ||
| + | /// <param name="prompt"></param> | ||
| + | /// <returns></returns> | ||
| + | /// <exception cref="ArgumentOutOfRangeException"></exception> | ||
| + | public async UniTask<GptAPIResponseEntity> GetAPIResponse(string prompt) | ||
| + | { | ||
| + | GptAPIRequestEntity requestEntity = new() | ||
| + | { | ||
| + | Prompt = prompt, | ||
| + | MaxTokens = 200 | ||
| + | }; | ||
| + | string requestJson = JsonConvert.SerializeObject(requestEntity, Formatting.Indented); | ||
| + | byte[] data = System.Text.Encoding.UTF8.GetBytes(requestJson); | ||
| + | string jsonString = null; | ||
| + | using (UnityWebRequest request = UnityWebRequest.Post(GptDefine.API_END_POINT, "POST")) | ||
| + | { | ||
| + | request.uploadHandler = new UploadHandlerRaw(data); | ||
| + | request.downloadHandler = new DownloadHandlerBuffer(); | ||
| + | request.SetRequestHeader("Content-Type", "application/json"); | ||
| + | request.SetRequestHeader("Authorization", "Bearer " + GptDefine.API_KEY); | ||
| + | await request.SendWebRequest(); | ||
| + | switch (request.result) | ||
| + | { | ||
| + | case UnityWebRequest.Result.InProgress: | ||
| + | break; | ||
| + | case UnityWebRequest.Result.Success: | ||
| + | jsonString = request.downloadHandler.text; | ||
| + | break; | ||
| + | default: | ||
| + | throw new ArgumentOutOfRangeException(); | ||
| + | } | ||
| + | } | ||
| + | return JsonConvert.DeserializeObject<GptAPIResponseEntity>(jsonString); | ||
| + | } | ||
| + | } | ||
| + | </pre> | ||
| + | GptView.cs | ||
| + | <pre> | ||
| + | using UnityEngine; | ||
| + | using UnityEngine.UI; | ||
| + | using TMPro; | ||
| + | |||
| + | public class GptView : MonoBehaviour | ||
| + | { | ||
| + | /// 入力欄 | ||
| + | [SerializeField] | ||
| + | private TMP_InputField input; | ||
| + | public TMP_InputField Input { get => input; } | ||
| + | /// 出力欄 | ||
| + | [SerializeField] | ||
| + | private TextMeshProUGUI output; | ||
| + | public TextMeshProUGUI Output { get => output; } | ||
| + | /// 実行ボタン | ||
| + | [SerializeField] | ||
| + | private Button execButton; | ||
| + | public Button ExecButton { get => execButton; } | ||
| + | } | ||
| + | </pre> | ||
| + | ==エラーについて== | ||
| + | ===429エラーレスポンス=== | ||
| + | |||
| + | リクエストの処理中にサーバーでエラーが発生しました。と返ってくるので、多分サーバーに負荷がかかってる状態なのかも。 | ||
| + | |||
| + | <pre> | ||
| + | UnityWebRequestException: HTTP/1.1 429 Too Many Requests | ||
| + | { | ||
| + | "error": { | ||
| + | "message": "The server had an error while processing your request. Sorry about that!", | ||
| + | "type": "server_error", | ||
| + | "param": null, | ||
| + | "code": null | ||
| + | } | ||
| + | } | ||
| + | Cysharp.Threading.Tasks.UnityAsyncExtensions+UnityWebRequestAsyncOperationAwaiter.GetResult () [0x00000] in <00000000000000000000000000000000>:0 | ||
| + | --- End of stack trace from previous location where exception was thrown --- | ||
| + | </pre> | ||
| + | |||
| + | ===You exceeded your current quota, please check your plan and billing details.=== | ||
| + | 現在の割り当てを超えています。とのことで、無料割当分が、なくなったとか、で使えなくなってる状態。https://platform.openai.com/account/billing/overview からクレジットで、払えば使えるようになる。 | ||
2023年7月24日 (月) 11:41時点における最新版
目次
apiを取得する
- https://beta.openai.com/ でアカウントを作成
- "create new secret key"を押してAPIキーを作成する
参考
https://techblog.kayac.com/2022-group-calendar-unity-openapi
料金確認
https://platform.openai.com/account/usage
リクエスト制限
https://platform.openai.com/docs/guides/rate-limits/overview
無料ユーザは、20リクエスト/分まで 従量ユーザは、60~3000リクエスト/分まで
unityサンプル
Main.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Main : MonoBehaviour
{
[SerializeField] GptView gptView;
GptUseCase gptUseCase = null;
void Awake()
{
if (ReferenceEquals(gptUseCase, null))
{
GptRepository gptRepository = new GptRepository();
GptPresenter gptPresenter = new GptPresenter(gptView);
gptUseCase = new GptUseCase(
gptPresenter,
gptRepository
);
gptUseCase.Begin();
}
}
void OnDestroy()
{
if (!ReferenceEquals(gptUseCase, null))
{
gptUseCase.Finish();
}
}
}
GptUseCase.cs
using UnityEngine;
using System.Linq;
using Cysharp.Threading.Tasks;
using TMPro;
using UniRx;
public class GptUseCase
{
GptPresenter gptPresenter;
GptRepository gptRepository;
CompositeDisposable disposable = null;
public GptUseCase(
GptPresenter gptPresenter,
GptRepository gptRepository
)
{
this.gptPresenter = gptPresenter;
this.gptRepository = gptRepository;
}
/// <summary> 初回処理 </summary>
public void Begin()
{
disposable = new CompositeDisposable();
gptPresenter.Bind();
gptPresenter.ExecOnClickAsObservable
.Subscribe(async _ => {
TMP_InputField input = gptPresenter.GptView.Input;
string prompt = input.text;
if (!string.IsNullOrEmpty(prompt))
{
var response = await gptRepository.GetAPIResponse(prompt);
string outputText = response.Choices.FirstOrDefault().Text;
string outputText = prompt;
outputText = outputText.TrimStart('\n');
}
})
.AddTo(disposable);
}
/// <summary> 終了処理 </summary>
public void Finish()
{
disposable.Dispose();
disposable = null;
}
}
GptDefine.cs
public class GptDefine
{
/// <summary>
/// APIエンドポイント
/// </summary>
public const string API_END_POINT = "https://api.openai.com/v1/completions";
/// <summary>
/// API KEY
/// </summary>
public const string API_KEY = "API_KEY";
/// <summary>
}
GptPresenter.cs
using UniRx;
using System;
public class GptPresenter
{
GptView gptView = null;
public GptView GptView { get => gptView; set => value = gptView; }
/// <summary> 実行Observable </summary>
IObservable<Unit> execOnClickAsObservable = null;
public IObservable<Unit> ExecOnClickAsObservable { get => execOnClickAsObservable; }
public GptPresenter(GptView gptView)
{
this.gptView = gptView;
}
public void Bind()
{
execOnClickAsObservable = gptView.ExecButton.OnClickAsObservable();
}
}
GptRepository.cs
using UnityEngine.Networking;
using Newtonsoft.Json;
using System;
using Cysharp.Threading.Tasks;
public class GptRepository
{
/// <summary>
/// APIからレスポンス取得
/// </summary>
/// <param name="prompt"></param>
/// <returns></returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public async UniTask<GptAPIResponseEntity> GetAPIResponse(string prompt)
{
GptAPIRequestEntity requestEntity = new()
{
Prompt = prompt,
MaxTokens = 200
};
string requestJson = JsonConvert.SerializeObject(requestEntity, Formatting.Indented);
byte[] data = System.Text.Encoding.UTF8.GetBytes(requestJson);
string jsonString = null;
using (UnityWebRequest request = UnityWebRequest.Post(GptDefine.API_END_POINT, "POST"))
{
request.uploadHandler = new UploadHandlerRaw(data);
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");
request.SetRequestHeader("Authorization", "Bearer " + GptDefine.API_KEY);
await request.SendWebRequest();
switch (request.result)
{
case UnityWebRequest.Result.InProgress:
break;
case UnityWebRequest.Result.Success:
jsonString = request.downloadHandler.text;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
return JsonConvert.DeserializeObject<GptAPIResponseEntity>(jsonString);
}
}
GptView.cs
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class GptView : MonoBehaviour
{
/// 入力欄
[SerializeField]
private TMP_InputField input;
public TMP_InputField Input { get => input; }
/// 出力欄
[SerializeField]
private TextMeshProUGUI output;
public TextMeshProUGUI Output { get => output; }
/// 実行ボタン
[SerializeField]
private Button execButton;
public Button ExecButton { get => execButton; }
}
エラーについて
429エラーレスポンス
リクエストの処理中にサーバーでエラーが発生しました。と返ってくるので、多分サーバーに負荷がかかってる状態なのかも。
UnityWebRequestException: HTTP/1.1 429 Too Many Requests
{
"error": {
"message": "The server had an error while processing your request. Sorry about that!",
"type": "server_error",
"param": null,
"code": null
}
}
Cysharp.Threading.Tasks.UnityAsyncExtensions+UnityWebRequestAsyncOperationAwaiter.GetResult () [0x00000] in <00000000000000000000000000000000>:0
--- End of stack trace from previous location where exception was thrown ---
You exceeded your current quota, please check your plan and billing details.
現在の割り当てを超えています。とのことで、無料割当分が、なくなったとか、で使えなくなってる状態。https://platform.openai.com/account/billing/overview からクレジットで、払えば使えるようになる。
