基本的な会話プログラムの作り方
独自の知識を備えたチャットBotの作り方をステップバイステップで解説していきます。まずは、知識の参照を行わない基本的な会話プログラムの作り方から始めましょう。開発言語はPython、動作環境はGoogle Colaboratoryを想定しています。
ChatGPT APIのアクセスキーを取得する
まずはOpenAIのWebサイトでアカウントを作成し、ChatGPT APIを利用するためのアクセスキーを取得します。アカウントが作成できたら、以下の手順を実行してください。
- 右上のアカウント名をクリックして開くメニューから、「View API keys」をクリック
- 「Create new secret key」をクリック
- 必要に応じてキーの名前を入力し、「Create secret key」をクリック
- 発行されたキーをコピーし、安全な場所に保管する
また、アクセスキーを使用する前に別途以下の操作が必要となります。
- 支払い情報の登録
- 上限金額の設定
本記事に掲載するコードには実行する際にAPIの利用料が発生するものがありますが、動作確認程度の使用であれば基本的には無料枠の範囲内で確認できます。もし不安がある場合は、上限金額を低めに設定しておけば、請求額がそれを超えることはなくなります。現在の使用料はUsageページより随時ご確認ください。
Google Colaboratory上に必要な環境を構築する
Google Colaboratoryはブラウザから手軽にPythonコードを実行することができるGoogleのサービスです。新しいノートブックを作成したら、まずは今回使用するOpenAIモジュールをインストールしましょう。一番上のセルに以下コードを入力し、左側の実行ボタンをクリックしてください。
!pip install openai==1.3.4
本記事では、執筆時点で最新であるVer 1.3.4を対象とします。2023年11月に正式リリースされた1系と、それ以前の0系では使用方法に差異がありますので、ローカル環境で過去のバージョンを利用している方はご注意ください。
インストールが完了したら今回使用する環境の準備は完了です。
注意
今回使用するノートブックにはOpenAIのアクセスキーを直接記載する必要があるため、不用意に漏洩することのないよう、公開範囲には充分に注意してください。
アクセスキーをセットしてクライアントを作成する
発行したアクセスキーはAPIのリクエストと共に毎回送信する必要がありますが、Pythonでopenaiモジュールを利用する場合は「OPENAI_API_KEY」という環境変数にあらかじめアクセスキーをセットしておけば自動的に送ってくれるようになります。今回はosモジュールを使用してコード内で環境変数を設定します。
先ほどのセルの下部にマウスオーバーすると表示される「+ コード」というボタンをクリックして新しいセルを追加し、以下のコードを実行して下さい。
import os from openai import OpenAI # アクセスキーを環境変数にセット os.environ['OPENAI_API_KEY'] = "<アクセスキー>" # クライアントを作成 client = OpenAI()
最後の一行でOpenAIクラスのインスタンスを作成し、clientというグローバル変数にセットしています。以降はこちらのオブジェクトを介してAPIにアクセスしていきます。
<アクセスキー> の部分には先ほど取得したご自身のアクセスキーを入力してください。
会話関数の実装
ChatGPTと会話を行う関数を以下のように定義します。
この時点ではまだ関数を定義しているだけなので、実行しても何も起こりませんが、新しいセルにペーストして実行してみてください。
# 会話履歴を保持するグローバル変数
database = []
def conversation(message_user):
# (1) システムプロンプトを作成
prompt = """あなたは優秀なアシスタントです。ユーザーからの問い合わせに適切な返答を行なってください。"""
system = {'role':'system', 'content':prompt}
# (2) 会話履歴を取得
history = database[-10:]
# (3) ユーザーメッセージを作成
user = {'role':'user', 'content':message_user}
# (4) API実行
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[system] + history + [user],
temperature=0.3
)
# (5) AIの返答を取得
message_assistant = response.choices[0].message.content
assistant = {'role':'assistant', 'content':message_assistant} # 保存用
# (6) 会話履歴を保存
database.append(user)
database.append(assistant)
# (7) AIの返答を返却
return message_assistant
以下に関数の内容を細かく解説していきます。
(1)システムプロンプトを作成
システムプロンプトという概念は、Web版のChatGPTを使用していても出会うことはないのであまり馴染みがないかもしれません。しかしWeb版ChatGPTもユーザーとの会話を行う前の段階で、運営元から何らかの指示を受けているであろうことは想像に難くないと思います。システムプロンプトとはそのような管理者からの特別な指示のことで、APIを利用する際は自由に指定できます。ユーザーとの会話をどのようなスタンスで遂行するかや、Botに守らせたいルール、または口調やキャラクターの設定をしたい場合などは、ここに指示を記述します。
ChatGPTに一連の会話内容を送信する際、それぞれの発言はroleとcontentという2つのプロパティを持つオブジェクトで表現します。contentには発言の内容、roleにはそれが誰の発言なのかを表す識別子を設定します。管理者からの指示はsystemというroleで定義し、一般的には会話の先頭に配置します。
その他のroleとcontentの内容との関係は以下の表をご覧ください。
| role | content |
|---|---|
| system | 管理者からの基盤指示 |
| user | ユーザー(人間)の発言 |
| assistant | AIの発言 |
| function | FunctionCallingで実行した関数からの戻り値(※今回は使用しません) |
(2)会話履歴を取得
ChatGPT APIは基本的に記憶を保持することができません。そのため、直近の会話内容やシステムプロンプトなど、返答を作成する上で必要となる情報は毎回こちらから送信してあげる必要があります。
会話の履歴は、Slackのように組み込み先のアプリケーションで保持している場合はそちらから取得すれば問題ありませんが、そうでない場合は別途用意したデータベース等から取得することになります。あるいは、独自のWebフロントやモバイルアプリがアクセス元の場合は、サーバーサイドには履歴を保存せず、クライアントから毎回受け取るという方法も考えられるでしょう。
今回のコードは簡易的な実装として、「database」というグローバル変数に会話履歴を保持しており、ここではその末尾10件を取得するという処理を行なっています。
(3)ユーザーメッセージを作成
引数で渡されたユーザーの発言も、先ほどのシステムメッセージと同様、roleプロパティを持つオブジェクトとして成形します。ユーザーの発言は、userというロールを設定します。
(4)API実行
先ほど作成したクライアントを使用してChatGPT APIにリクエストを送信します。client.chat.completions.create()というメソッドに必要なパラメータを渡すだけで、ChatGPTからの返答を得ることができます。
ここでは以下のパラメータを渡して実行しています。
model(必須)
使用するモデル名を指定します。今回は最も安価かつ高速なgpt-3.5-turboを指定しています。他にも、より高性能なgpt-4や、自前のデータで最適化したファインチューニングモデルなどが指定できます。
messages(必須)
最新の発言を含む会話の履歴を配列で渡します。今回はシステムプロンプト、直近10件の会話履歴、ユーザーによる最新の発言を一続きのリストに連結して渡しています。
temperature
直訳すると「温度」となりますが、こちらは返答のバラツキを表すパラメータです。必須ではありませんが、返答内容をコントロールする上で重要なパラメータであり、指定が推奨されています。
temperatureを最小の0とすると、回答のバラツキが最も少なくなります。最も性能が良く、確実性の高い返答が返ってきますが、同じ入力に対する出力は必ず同じになります。反対に最大の2とすると、同じ質問に対してもバリエーション豊かな返答を行うようになりますが、ルール違反や誤った回答を行う確率も増えてしまいます。デフォルト値は中間の1です。今回は安定性を重視して低めの0.3に設定しています。
その他のパラメータはChatGPT APIのリファレンスからご確認下さい。
(5)AIの返答を取得
APIからのレスポンスは以下のような形式で返ってきます。
{
"id": "chatcmpl-123",
"object": "chat.completion",
"created": 1677652288,
"model": "gpt-3.5-turbo-0613",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "\n\nHello there, how may I assist you today?",
},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 9,
"completion_tokens": 12,
"total_tokens": 21
}
}
送信時のパラメータによってはchoicesの中に複数の回答が入っていたり、ここにないプロパティが含まれていたりすることもありますが、基本的にはresponse.choices[0].message.contentという形で返答文が取得できます。また、usageプロパティに格納されている入出力に使ったトークン数は、ユーザー毎に使用量を制限するといったコストコントロールを行う際に役立つでしょう。
レスポンスの詳しい内容はChatGPT APIのリファレンスからご確認下さい。
(6)会話履歴を保存
2で説明した通り、AIとの会話の履歴は何らかの方法で保存しておかなければなりません。連携先で保持できない場合は、ユーザーとAIの発言をそれぞれデータベース等に保管します。発言内容やロールはもちろん、利用者のIDや、正しい順序で取得できるようにタイムスタンプまたは通し番号の登録も必要です。
今回の実装では、グローバル変数として置いたリストの末尾にユーザー、AIの順でオブジェクトを追加しています。
(7)AIの返答を返却
最後にAIの返答を戻り値として返却しています。SlackやLINEなどと連携する場合は、それぞれの仕様にしたがってレスポンスを送信します。
これで会話プログラムの核となる部分の実装は完了です。それでは、上記の関数を使用して実際にChatGPTと会話を行なってみましょう。
会話プログラムの実行
Colabに新しいセルを追加し、以下のコードを記述して実行してみてください。Python標準のinput関数を使用して、ユーザーからの入力を受け付けています。
while True:
message = input("User > ")
res = conversation(message)
print("AI > ", res)
実行すると、セルの下部にテキストの入力欄が表示されるので、そちらに質問内容を入力してEnterを押下すると、その下にChatGPTからの返答が表示されます。
変換確定のためにEnterを押しても送信されてしまうので、別の場所に書いたものをペーストする方が楽だと思います。
この時、レスポンスの速度はAIが生成する文章量が少ないほど早く、多いほど遅くなります。速度が気になる場合は、APIのパラメータに「stream=True」を追加することで、ストリーミング形式で返答を受信できます。それを利用して、Web版ChatGPTのように段階的に文章が表示されるように改修すれば、ユーザーの体感速度を向上させることが可能です。
停止の際は左側でくるくる回転している停止ボタンをクリックしてください。
以上で、ChatGPT APIを使用した最も単純な会話プログラムが実装できました。簡略化している部分があるとは言え、会話を行うだけならさほど難しい実装ではないことがわかったと思います。
しかしながら、ChatGPTは基本的に学習が行われた時点でインターネット上に一般公開されていた情報しか持っておらず、このBotも今のままでは普遍的な質問にしか答えられません。改めて、独自の情報を扱えるように改修していきましょう。
