OpenAIのAPIとUnityで音声会話チャットボットを作る ~ チャット機能編 ~
はじめに
この記事は Panda株式会社 Advent Calendar 2023 4日目の記事です。
Panda株式会社として初めてのAdvent Calendarとなります。
Panda株式会社は東京大学松尾研究室・香川高専発のスタートアップで、AR技術とAI技術を駆使したシステム開発と研究に取り組んでいます。
このアドベントカレンダーでは、スタートアップとしての知見、AI・AR技術、バックエンドなど、さまざまな領域の記事を公開していきます。
自己紹介
皆さんこんにちは、Panda株式会社代表取締役の田貝奈央です。AR技術が好きで、X(旧:Twitter)でARに関する投稿の巡回をしています。また、私はコーヒー好きで、この記事を執筆するときもPCの隣にはコーヒーを置いています。執筆活動を支援してくれたコーヒーに感謝を。
背景
2023年に4回ほどにわけて「ChatGPT×Unityハンズオン」を小規模に開催しました。2024年にはこのイベントを広く公開しようと考えています。そのため、このタイミングでハンズオンの内容を文書化することに決めました。
2022年11月にOpenAIのChatGPTが公開されてからというもの、多くの人々がチャットボットへの関心を高めています。そんな中、「バーチャル空間でチャットボットを実装してみたいけど、やり方がわからない」という相談をUnity初心者の方から受けることがありました。世の中にはチャットボットを実現するための機能が多く存在しますが、その使用方法や実装手順が明確になっていないため、Unity初心者がチャットボットを作るのは大変です。そこで、「ChatGPT×Unityハンズオン」はUnity初心者でもチャットボットを作れるようなスキルアップイベントとして開催されました。
このハンズオンは、Unityを使用してチャットボットを構築する手順を分かりやすく、実践的に学べる4回のセッションで構成されています。これにより、参加者は音声でのやり取りが可能なチャットボットをUnityで開発することができるようになります。ユーザーが音声で質問すると、「ユニティちゃん」が音声で応答するチャットボットを実装することができます。
本記事では、ハンズオンで取り扱った内容をチュートリアル形式で紹介します。実際に1時間かけて行ったハンズオンを詳細に記事化しているため、内容が豊富になっておりますが、最後までお付き合いいただけると幸いです。
環境
- Unity 2021.3.9f1以降
システム構成
このシステムでは、ユーザーが音声で質問すると、Unity Technologies Japanが開発者のために提供しているオリジナルキャラクター「ユニティちゃん」が音声で応答するチャットボットを作成します。ユーザーの音声での入力はマイクを使用して録音され、その音声データはテキストに書き起こされます。次に、この書き起こされたテキストをOpenAIのchat completions APIに送信し、ユーザーの質問に対する適切な応答を生成します。chat completions APIに送信するテキストには、ユニティちゃんの喋り方を指定するプロンプトと感情分析を含めることで、返却された応答から「ユニティちゃん」の表情を操作します。さらに、生成された応答はGoogle Cloud Platform(GCP)のText-to-Speechサービスを使用して音声データに変換されます。そして、この音声データをUnity内で再生することで、アバターが音声で応答することを実現します。
それぞれの機能を実現するために本記事を含めて以下の4つの記事に分けて実装について説明します。アドベントカレンダーで公開される記事になっているため、投稿日現在(2023/12/04)、アクセスできない記事が含まれています。
- (本記事)OpenAIのAPIとUnityで音声会話チャットボットを作る ~ チャット機能編 ~
- OpenAIのAPIとUnityで音声会話チャットボットを作る ~ 音声入力編 ~
- OpenAIのAPIとUnityで音声会話チャットボットを作る ~ 音声生成編 ~
- OpenAIのAPIとUnityで音声会話チャットボットを作る ~ 喜怒哀楽編 ~
チャット用のUIを準備する
チャット機能を実現するには、ユーザがインタラクションできるUIが必要です。このセクションでは、ユーザがメッセージを入力、送信し、応答を受け取れるようなUIを構築する方法について説明します。チャット機能に必要となる主なUI要素は、入力用のテキストボックス、送信ボタン、応答が表示されるメッセージエリアの3つです。
1. テキストボックスを作成
ユーザがチャットボットにメッセージを入力するためのテキストボックスを準備します。Unityでユーザがテキストを入力できるUI要素を作る際は「Input Field」を使います。
ヒエラルキーを右クリックし、UI → Legacy → Input Field
の順で選択し、Input Field
をシーンに追加します。
追加後、Input Field
の位置を調整し、Canvas
要素の下部に移動します。
2. 送信ボタンを作成
ユーザが入力したメッセージを送信できるようにするボタンを作成します。Unityでクリックイベントを発火させるUI要素を作る際は「Button」を使います。
ヒエラルキーを右クリックし、UI → Legacy → Button
の順で選択し、Button
をシーンに追加します。
追加後、Button
の位置を調整し、先ほど配置したInput Field
の下に配置します。
このボタンがテキストを送信するためのボタンであることがわかりやすいようにラベルを変更します。ヒエラルキーからButton
の子要素のText
要素を選択し、インスペクターのText
を書き換えます。
これにより、Button
のラベルを変更することができます。
3. 応答が表示されるテキストエリアを作成
LINEのように送信者と応答者のコメントがわかりやすいUIを作成します。本プロジェクトでは、各メッセージは吹き出し形式で表示されます。また、送信者と応答者のコメントがわかりやすいようにメッセージの色を区別します。送信者のメッセージは右側に、応答者のメッセージは左側に表示します。
まず、メッセージの履歴が多くなってもスクロールして閲覧できるように、Scroll Viewを使用してテキストボックスを表示する領域を作成します。
ヒエラルキーを右クリックし、UI → Scroll View
の順で選択し、Scroll View
をシーンに追加します。Scroll View
のサイズや位置をインスペクターから変更します。
Scroll View
はViewport
・Scrollbar Horizontal
・Scrollbar Vertical
の三つの要素で構成されています。Viewport
はScroll View
内の表示領域を定義します。Viewport
の子要素にあるオブジェクトがViewport
の領域をはみ出ると、Unity上では表示されなくなります。Scrollbar Horizontal
は水平方向のスクロールバー、Scrollbar Vertical
は垂直方向のスクロールバーを表しています。
このプロジェクトでは、LINEのように縦方向にメッセージの履歴を表示するために、垂直方向のスクロールバーであるScrollbar Vertical
のみを使用します。そのため、Scrollbar Horizontal
を削除します。
次にScroll View
のインスペクターでScroll Rect
のHorizontal
のチェックマークを外し、Horizontal Scrollbar
で選択している要素をNone
に設定します。これにより、Scroll View
は水平方向のスクロールバーを使用しないように設定されます。
Viewport
の中にあるContent
の子要素にメッセージボックスを並べることで送信者と応答者のメッセージの履歴を表示することができます。LINEのように下の方が最新の投稿で、上に行くほど過去の投稿になるようにするために、Content
の子要素の並べ方を変更します。Content
のインスペクターを開きAdd Component
をクリックしVertical Layout Group
を追加します。
メッセージが追加されるたびにContentのサイズを広げる必要があるため、UI要素のサイズを子要素のサイズに合わせて自動で調整することができるContentSizeFitter
を追加します。Content
のインスペクターを開きAdd Component
をクリックしContentSizeFitter
を追加します。
下から積み上げるように表示するために、Content
のRect Transform
のアンカーを変更します。アンカーとは子要素のUI要素を配置するための基準となる場所のことです。インスペクターのRect Transform
の左の四角をクリックすることでアンカーを変更することができます。
本プロジェクトでは、縦方向にサイズを調整する必要があるためVertical Fit
というプロパティをPreferred Size
にします。これにより、Content
の垂直方向のサイズを子要素の推奨サイズに合わせることができます。
そして、送信者と応答者のメッセージを表示する吹き出しをコンポーネントとして作成します。送信者と投稿者のメッセージを区別するために、吹き出しの色を変更する必要があるため、Panelを作成します。
ヒエラルキーを右クリックし、UI → Panel
の順に選択し、Panel
をシーンに追加します。
メッセージを表示するためにText
要素をPanel
の子要素として追加します。
先ほど作成したPanel
を選択した状態でヒエラルキーを右クリックし、UI → Legacy → Text
を選択し、Text
を追加します。
Panel
のImage
の色を緑色に変更します。
メッセージを表示するテキストが複数行になった時にメッセージを表示する吹き出しを縦方向に拡大するために、Text
にUI要素のサイズを子要素のサイズに合わせて自動で調整することができるContentSizeFitter
を追加します。Text
のインスペクターを開きAdd Component
をクリックしContentSizeFitter
を追加します。縦方向にサイズを調整する必要があるためVertical Fit
というプロパティをPreferred Size
にします。
Text
コンポーネントが複数行に渡る場合、親要素であるPanel
のサイズを拡張する必要があります。これを効率的に行うために、UI要素のサイズをその子要素のサイズに合わせて自動的に調整するContentSizeFitter
コンポーネントの使用が推奨されます。Panel
のサイズを動的に管理するには、まずPanel
のインスペクターを開きます。その後、Add Component
ボタンをクリックし、ドロップダウンからContentSizeFitter
を選択して追加します。
さらに、メッセージの背景サイズをText
の大きさに適応させるためには、Vertical Layout Group
コンポーネントの追加が効果的です。Vertical Layout Group
を追加することで、子要素を垂直方向に整列させ、適切なPadding
を設定することが可能になります。これは、Text
コンポーネントのインスペクターを開き、Add Component
ボタンをクリックしてからVertical Layout Group
を選択し追加することで実現できます。
このオブジェクトをプレハブ化することで、後ほどメッセージの送受信をするときにスクリプトからオブジェクトを作成できるようにします。
OpenAI chat completions APIとの連携
ユーザが入力したメッセージに対して適切な返答をするチャットボットを実現するために、OpenAIが提供するGPT-3(Generative Pre-trained Transformer 3)などの大規模言語モデルを利用して、与えられたメッセージに対する応答を生成します。このモデルは、自然言語・コードなどを理解できるようにトレーニングされており、入力されたテキスト(プロンプトと呼ばれます)に基づいて適切なテキストを出力します。プロンプトを変更することで大規模言語モデルへの指示をカスタマイズすることが可能です。
今回は「gpt-3.5-turbo」を利用します。このモデルを利用するには、入力とAPIキーを含むリクエストをOpenAIのAPIに送信し、モデルからの出力を受け取る必要があります。Unityからモデルを利用するには、UnityWebRequestを使ってAPIにリクエストを送信します。
1. OpenAIのAPIキーを作成
まず、OpenAIのウェブサイトにアクセスし、アカウントを作成します。アカウントがない場合は新規登録が必要です。登録したアカウントでログインできたら、OpenAIの開発者クイックスタートのアカウントの設定を参考にOpenAIのAPIキーを作成します。このキーはAPIリクエストを送信する際に必要になります。
2. APIに対するリクエストの送受信
UnityWebRequestを用いて、APIにリクエストを送るコードを作成します。リクエストにはユーザの入力メッセージとプロンプト、APIキーを含める必要があります。
APIを呼び出すために必要なリクエストと返却される形式についてはOpenAIのchat completions APIのドキュメントから確認することができます。
「 https://api.openai.com/v1/chat/completions 」にメッセージを入れたJSONをPostすることでリクエストを送ることができます。
UnityWebRequestでPostするにはPostをリクエストを作成する必要があります。
以下は、UnityからAPIリクエストを送信・受信するためのスクリプトです。このサイトを参考に送受信に必要なクラスを構築します。
ChatGPTConnection.csの全体
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
namespace OpenAIGPT{
// OpenAI GPTとの接続を管理するクラス
[Serializable]
public class ChatGPTConnection
{
// OpenAI APIキー
private readonly string _apiKey;
// メッセージ履歴を保持するリスト
private readonly List<ChatGPTMessageModel> _messageList = new();
// コンストラクタ:APIキーを設定し、初期メッセージを追加
public ChatGPTConnection(string apikey)
{
_apiKey = apikey;
_messageList.Add(
new ChatGPTMessageModel() {role = "system", content = "あなたは猫です。猫語で対話をしてください。"});
}
// メッセージモデル
[Serializable]
public class ChatGPTMessageModel
{
// メッセージの送信者の役割(ユーザーまたはシステム)
public string role;
// メッセージの内容
public string content;
}
// ユーザーメッセージに対するOpenAI GPT APIリクエストを送信する非同期メソッド
public async UniTask<ChatGPTResponseModel> RequestAsync(string userMessage)
{
// OpenAI GPT APIのエンドポイント
var apiUrl = "https://api.openai.com/v1/chat/completions";
// ユーザーメッセージをリストに追加
_messageList.Add(new ChatGPTMessageModel {role = "user", content = userMessage});
// OpenAI APIリクエストに必要なヘッダー情報
var headers = new Dictionary<string, string>
{
{"Authorization", "Bearer " + _apiKey},
{"Content-type", "application/json"}
};
// APIリクエストのオプション(モデルとメッセージリスト)
var options = new ChatGPTCompletionRequestModel()
{
model = "gpt-3.5-turbo",
messages = _messageList
};
var jsonOptions = JsonUtility.ToJson(options);
// UnityWebRequestを使用してOpenAI GPT APIにリクエストを送信
using var request = new UnityWebRequest(apiUrl, "POST")
{
uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(jsonOptions)),
downloadHandler = new DownloadHandlerBuffer()
};
// リクエストヘッダーを設定
foreach (var header in headers)
{
request.SetRequestHeader(header.Key, header.Value);
}
// リクエストを送信し、応答を待機
await request.SendWebRequest();
// リクエストの結果を処理
if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError)
{
Debug.LogError(request.error);
throw new Exception();
}
else
{
var responseString = request.downloadHandler.text;
var responseObject = JsonUtility.FromJson<ChatGPTResponseModel>(responseString);
_messageList.Add(responseObject.choices[0].message);
return responseObject;
}
}
// OpenAI GPT APIリクエストのJSONモデル
[Serializable]
public class ChatGPTCompletionRequestModel
{
public string model; // 使用するモデル名
public List<ChatGPTMessageModel> messages; // メッセージリスト
}
// OpenAI chat completions APIの応答モデル
[System.Serializable]
public class ChatGPTResponseModel
{
public string id; // 応答のID
public string @object; // オブジェクトタイプ
public int created; // 作成タイムスタンプ
public Choice[] choices; // 応答選択肢
public Usage usage; // 使用量情報
[System.Serializable]
public class Choice
{
public int index; // 選択肢のインデックス
public ChatGPTMessageModel message; // メッセージ内容
public string finish_reason; // 終了理由
}
[System.Serializable]
public class Usage
{
public int prompt_tokens; // プロンプトに使用されたトークン数
public int completion_tokens; // 完成に使用されたトークン数
public int total_tokens; // 合計使用トークン数
}
}
}
}
全体のコードを元に、OpenAI chat completions APIにリクエストを送る方法を紹介します。
UnityでJSON形式のPOSTリクエストを送るには、JSONに変換したいクラスを定義し、そのクラスのインスタンスをJsonUtility.ToJson
メソッドを利用してJSON形式のオブジェクトに変換する必要があります。
以下の部分で、OpenAI chat completions APIにリクエストを行うためのJSONモデルを定義しています。OpenAIのchat completions API referenceのリクエストボディの欄を確認すると、以下の二つが必須項目であることがわかります。
-
messages array:
- これまでの会話を構成する一連のメッセージのリスト
- 例えば、ユーザからの質問とそれに対するボットの応答などを記述する
- システムプロンプトを含めることができる
-
model string:
- 使用するモデルのID
- 利用するモデルを指定する
この二つを持つクラスをChatGPTCompletionRequestModel
と定義し、[Serializable]
属性をつけます。これにより、APIサーバにポストリクエストをJSON形式で送るために、クラスのインスタンスをJsonUtility.ToJson
を用いてシリアライゼーションできるようになります。
// OpenAI chat completions APIリクエストのJSONモデル
[Serializable]
public class ChatGPTCompletionRequestModel
{
public string model; // 使用するモデル名
public List<ChatGPTMessageModel> messages; // メッセージリスト
}
messages
で指定できるメッセージオブジェクトの属性は複数あります。今回、チャットボットを実現する上で使うのは次の二つです。
- システムメッセージ
- プロンプトを設定できます
- content string or null: システムメッセージの内容
- role string: メッセージ送信者の役割「system」
- ユーザーメッセージ
- ユーザーが送信したメッセージを記入できる
- content string or null: ユーザメッセージの内容
-
role string: メッセージの送信者の役割「user」
どちらもcontent
とrole
が必要なため、以下のようなメッセージモデルを表すクラスChatGPTMessageModel
を定義します。送信時にJSONにシリアライズする必要があるため、[Serializable]
属性をつけます。
// メッセージモデル
[Serializable]
public class ChatGPTMessageModel
{
// メッセージの送信者の役割(ユーザーまたはシステム)
public string role;
// メッセージの内容
public string content;
}
以下の部分でメッセージモデルのリストを作成し、APIの送信するメッセージの履歴を保持するリストを作成します。
// メッセージ履歴を保持するリスト
private readonly List<ChatGPTMessageModel> _messageList = new();
先ほど作った_messageList
に対して、プロンプトを加えます。本プロジェクトでは猫語で応答が返却されるようにしたいため、「あなたは猫です。猫語で対話してください。」というテキストをシステムメッセージに登録することで、プロンプトを指定しています。
_messageList.Add(
new ChatGPTMessageModel() {role = "system", content = "あなたは猫です。猫語で対話をしてください。"});
ユーザーの入力を_messageList
に追加するには、以下のコードでユーザーメッセージを追加します。
// ユーザーメッセージをリストに追加
_messageList.Add(new ChatGPTMessageModel {role = "user", content = userMessage});
このようにして作成したメッセージのリストを以下のコードでJSON形式に変換し、APIに送信できる形にします。modelにはgpt-3.5-turbo
を指定したリクエストモデルをインスタンス化し、JsonUtility.ToJson
でJSON形式のテキストに変換します。
// APIリクエストのオプション(モデルとメッセージリスト)
var options = new ChatGPTCompletionRequestModel()
{
model = "gpt-3.5-turbo",
messages = _messageList
};
var jsonOptions = JsonUtility.ToJson(options);
以下にOpenAI chat completions APIにPOSTリクエストを送るためのコードを記述します。まずUnityWebRequest
オブジェクトを作成し、APIのエンドポイントとHTTPメソッドであるPOST
を指定します。リクエストボディ(uploadHandler
で指定できます)には先ほど作成したjsonOptions
をUnityWebRequest
オブジェクトを設定します。downloadHandler
にAPIからのレスポンスを受け取るためのバッファを設定します。
// UnityWebRequestを使用してOpenAI GPT APIにリクエストを送信
using var request = new UnityWebRequest(apiUrl, "POST")
{
uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(jsonOptions)),
downloadHandler = new DownloadHandlerBuffer()
};
OpenAI APIは認証にAPIキーを使用するため、すべてのAPIリクエストのヘッダーに以下のようにAPIキーを含める必要があります。
// OpenAI APIリクエストに必要なヘッダー情報
var headers = new Dictionary<string, string>
{
{"Authorization", "Bearer " + _apiKey},
{"Content-type", "application/json"}
};
・・・
// リクエストヘッダーを設定
foreach (var header in headers)
{
request.SetRequestHeader(header.Key, header.Value);
}
ここまでで作成したリクエストを送信し、応答が返却されるまで待機します。
// リクエストを送信し、応答を待機
await request.SendWebRequest();
リクエストが返却されたら、その結果を処理します。リクエストがうまくいかなかった場合はエラー処理し、うまくいった場合は、レスポンスをクラスに変換し、Unity側から扱えるようにします。JsonUtility.FromJson
を用いることで、JSON形式のテキストをclassオブジェクトにシリアライズすることができます。これにより得られたOpenAI chat completions APIで生成された応答をメッセージとして記録するために、_messageList.Add(responseObject.choices[0].message);
を用いて会話履歴に登録します。
// リクエストの結果を処理
if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError)
{
Debug.LogError(request.error);
throw new Exception();
}
else
{
var responseString = request.downloadHandler.text;
var responseObject = JsonUtility.FromJson<ChatGPTResponseModel>(responseString);
_messageList.Add(responseObject.choices[0].message);
return responseObject;
}
OpenAI chat completions APIから返却されるレスポンスは次のようになっています。
- id string: 一意の識別子
-
object string: 今回は常に
chat.completion
- created integer: 返答が作成されたUnixタイムスタンプ
-
choices object: 生成されたメッセージの選択肢のリスト。今回は生成数を指定していないので1つだけ返却される
- index integer: 生成されたメッセージの選択肢のインデックス
- message object: モデルによって生成されたメッセージ
-
finish_reason string: モデルがトークンの生成を停止した理由(
stop
: 自然なところで止まったlenght
: 最大トークン数に到達した etc)
-
usage object: 生成結果の統計情報
- prompt_tokens integer: 生成されたメッセージのトークン数
- completion_tokens integer: プロンプトのトークン数
- total_tokens integer: リクエストで使用されたトークン数の合計(プロンプト+生成されたメッセージ)
この要素を持つクラスをChatGPTResponseModel
として定義します。以下のように[System.Serializable]
属性を指定し、JSON形式のテキストをシリアライズできるようにします。
// OpenAI chat completions APIの応答モデル
[System.Serializable]
public class ChatGPTResponseModel
{
public string id; // 応答のID
public string @object; // オブジェクトタイプ
public int created; // 作成タイムスタンプ
public Choice[] choices; // 応答選択肢
public Usage usage; // 使用量情報
[System.Serializable]
public class Choice
{
public int index; // 選択肢のインデックス
public ChatGPTMessageModel message; // メッセージ内容
public string finish_reason; // 終了理由
}
[System.Serializable]
public class Usage
{
public int prompt_tokens; // プロンプトに使用されたトークン数
public int completion_tokens; // 完成に使用されたトークン数
public int total_tokens; // 合計使用トークン数
}
}
OpenAI chat completions APIにリクエストの送受信を実現するスクリプトの解説は以上です。
次に、実際にチャットを送信するためのスクリプトを以下に示します。
SendChat.csの全体
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using OpenAIGPT;
using UnityEngine.UI;
public class SendChat : MonoBehaviour
{
// OpenAI APIキー
[SerializeField]
private string openAIApiKey;
// ユーザーの入力を受け取るためのInputField
[SerializeField]
private InputField inputField;
// チャットメッセージを表示するコンテンツエリア
[SerializeField]
private GameObject content_obj;
// チャットメッセージのプレハブオブジェクト
[SerializeField]
private GameObject chat_obj;
// 送信ボタンが押されたときに呼び出されるメソッド
public void OnClick()
{
// InputFieldからテキストを取得
var text = inputField.GetComponent<InputField>().text;
// メッセージを送信
sendmessage(text);
// InputFieldをクリア
inputField.GetComponent<InputField>().text = "";
}
// メッセージを送信し、応答を取得する非同期メソッド
private async void sendmessage(string text)
{
// OpenAI GPTとの接続を初期化
var chatGPTConnection = new ChatGPTConnection(openAIApiKey);
// ユーザーのメッセージを表示するオブジェクトを生成
var sendObj = Instantiate(chat_obj, this.transform.position, Quaternion.identity);
sendObj.GetComponent<Image>().color = new Color(0.6f, 1.0f, 0.1f, 0.3f);
GameObject Child = sendObj.transform.GetChild(0).gameObject;
Child.GetComponent<Text>().text = text;
// 生成したオブジェクトをコンテンツエリアの子要素として追加
sendObj.transform.SetParent(content_obj.transform, false);
// OpenAI GPTにリクエストを送信し、応答を待つ
var response = await chatGPTConnection.RequestAsync(text);
// 応答があれば処理を行う
if (response.choices != null && response.choices.Length > 0)
{
var choice = response.choices[0];
Debug.Log("ChatGPT Response: " + choice.message.content);
// GPTの応答を表示するオブジェクトを生成
var responseObj = Instantiate(chat_obj, this.transform.position, Quaternion.identity);
responseObj.GetComponent<Image>().color = new Color(1.0f, 1.0f, 1.0f, 0.3f);
GameObject Child_responce = responseObj.transform.GetChild(0).gameObject;
Child_responce.GetComponent<Text>().text = choice.message.content;
// 応答オブジェクトをコンテンツエリアの子要素として追加
responseObj.transform.SetParent(content_obj.transform, false);
}
}
}
SendChat.cs
スクリプトを記述し、送信ボタンのオブジェクトにアタッチします。
インスペクターからOpenAIApiKeyに先ほど取得したOpenAIのAPIキーを記述し、InputField、Content_obj、Chat_objにそれぞれのオブジェクトをアタッチします。
3. メッセージをAPIに送信する
以下は送信ボタンが押された時に入力されているInputField
のテキスト内容をOpenAIのAPIに送信するスクリプトです。送信後にInputFieldを空にします。
// 送信ボタンが押されたときに呼び出されるメソッド
public void OnClick()
{
// InputFieldからテキストを取得
var text = inputField.GetComponent<InputField>().text;
// メッセージを送信
sendmessage(text);
// InputFieldをクリア
inputField.GetComponent<InputField>().text = "";
}
このスクリプトをButton
のOnClick()
イベントにアタッチすることで、ボタンのクリックイベントに対応させます。これにより、ボタンがクリックされたときに指定した処理が実行されます。
スクリプトは、InputField
コンポーネントからユーザが入力したテキストを取得し、sendmessage
メソッドを通じてそのテキストをOpenAI APIに送信します。メッセージの送信後、InputField
のテキストをクリアすることで、ユーザーは新しいメッセージを入力できるようになります。
4. APIリクエストの送信と応答の待機
以下は、OpenAIのAPIにリクエストを送信し応答を待つコードです。chatGPTConnection
オブジェクトのRequestAsync
メソッドを呼び出して、ユーザーからの入力されたテキストをOpenAI GPT-3 APIに送信します。await
キーワードは非同期処理を示し、APIからの応答を待ちます。
// OpenAI GPTにリクエストを送信し、応答を待つ
var response = await chatGPTConnection.RequestAsync(text);
5. 応答の確認と処理
以下は、APIからの応答がnull
でなく、少なくとも一つの選択肢が含まれているかを確認します。条件を満たす場合、最初の応答選択肢(response.choices[0]
)を取得し、その内容をデバッグログに出力します。
// 応答があれば処理を行う
if (response.choices != null && response.choices.Length > 0)
{
var choice = response.choices[0];
Debug.Log("ChatGPT Response: " + choice.message.content);
...
}
6. 応答を表示する
APIからの応答を受け取ったら、その内容(生成されたテキスト)を応答としてメッセージに表示します。これによりユーザは自身が送信したメッセージに対して応答が来るようなチャットボットを実現することができます。以下は、応答を表示するためにUnityのシーン内に新しいオブジェクトを生成し配置するコードです。
まず、応答を表示するための新しいオブジェクト(responseObj
)を生成し配置します。chat_obj
プレハブからresponseObj
をインスタンス化する際に現在のオブジェクトの位置や回転を引数として与えることで、現在のオブジェクトの位置に配置することができます。
// GPTの応答を表示するオブジェクトを生成
var responseObj = Instantiate(chat_obj, this.transform.position, Quaternion.identity);
次に、responseObj
の色を灰色に指定し、LINEのような見た目の応答表示を実現します。
responseObj.GetComponent<Image>().color = new Color(1.0f, 1.0f, 1.0f, 0.3f);
そして、応答テキストをresponseObj
の子オブジェクトにあるText
コンポーネントに設定します。これによりメッセージの応答をUnityのシーン上に表示することができます。
GameObject Child_responce = responseObj.transform.GetChild(0).gameObject;
Child_responce.GetComponent<Text>().text = choice.message.content;
最後に、content_obj
オブジェクトの子要素として追加します。これにより、テキストエリアの領域にメッセージを積み上げるように表示することができます。
// 応答オブジェクトをコンテンツエリアの子要素として追加
responseObj.transform.SetParent(content_obj.transform, false);
これにより、ユーザのメッセージに対する応答が視覚的に表示されるようなチャットボットを実現することができます。
おわりに
今回は「OpenAIのAPIとUnityで音声会話チャットボットを作る ~ チャット機能編 ~」というテーマでPanda株式会社 Advent Calendar 2023 4日目を執筆させていただきました。
本記事では、UnityでOpenAIのAPIを使ってテキストベースのチャットボットを実装する方法を紹介しました。
OpenAIのAPIキーを用意し、リクエストを作成し送信することで簡単にAPIと通信ができることがわかりましたね。Unityで何かしら自然な応答が必要な時などに使ってみてください。
明日の記事も私、Panda株式会社代表取締役の田貝奈央による「OpenAIのAPIとUnityで音声会話チャットボットを作る ~ 音声入力編 ~」です。この記事を読めば音声入力ができるチャットボットをUnityで作成できるようになります。明日の記事をお楽しみに!
Discussion