🦔

ChatGPTを使ってChatアプリを作る

2023/09/13に公開

はじめに

ChatGPTのAPI※1を使った簡単なサンプルを作ってみたくなったのでやってみました。
※1 ・・・ 正確にはOpenAI社のChat completions APIと言います。

方針

基本的にChatGPTの出したコードで実行します。
書き直しはChatGPTに依頼します。

ChatGPTとのやりとりは最後に載せておきます。

環境

コーディング環境:ChatGPT 4
実行環境:VS Code

※無料版のChatGPT3.5だと厳しいです。動かないコードを出してくる事や、意図したコードを提示してくれなかったり、修正のためのやりとりが数倍発生します。

完成版


アプリケーションの動作イメージ

完成版のコードを載せておきます。

openai_chat_app.py

import tkinter as tk
from tkinter import scrolledtext, ttk
import os
import openai

# 環境変数からAPIキーを取得
api_key = os.environ.get('OPENAI_API_KEY')

# APIキーが設定されているか確認
if not api_key:
    raise ValueError("OPENAI_API_KEY environment variable not set")

openai.api_key = api_key

messages = [
    {"role": "system", "content": "You are a helpful assistant."}
]


def send_message():
    user_message = user_input.get()
    chat_area.insert(tk.END, f"You: {user_message}\n")
    user_input.delete(0, tk.END)

    messages.append({"role": "user", "content": user_message})

    selected_model = model_combobox.get()
    max_tokens_val = int(max_tokens_input.get())

    # OpenAI APIを呼び出して回答を取得
    response = openai.ChatCompletion.create(
        model=selected_model,
        messages=messages,
        max_tokens=max_tokens_val
    )

    ai_message = response['choices'][0]['message']['content']
    chat_area.insert(tk.END, f"AI: {ai_message}\n")
    messages.append({"role": "assistant", "content": ai_message})


# GUIの設定
root = tk.Tk()
root.title("OpenAI Chat")
root.geometry("500x600")

chat_area = scrolledtext.ScrolledText(root, wrap=tk.WORD)
chat_area.pack(pady=15)

model_label = tk.Label(root, text="Select Model:")
model_label.pack(pady=5)
available_models = ["gpt-4", "gpt-4-0613", "gpt-4-32k", "gpt-4-32k-0613",
                    "gpt-3.5-turbo", "gpt-3.5-turbo-0613", "gpt-3.5-turbo-16k", "gpt-3.5-turbo-16k-0613"]
model_combobox = ttk.Combobox(root, values=available_models, state="readonly")
model_combobox.set("gpt-3.5-turbo")
model_combobox.pack(pady=5)

max_tokens_label = tk.Label(root, text="Max Tokens:")
max_tokens_label.pack(pady=5)
max_tokens_var = tk.StringVar()
max_tokens_var.set("1000")
max_tokens_input = tk.Spinbox(
    root, from_=1, to=1500, width=7, textvariable=max_tokens_var)
max_tokens_input.pack(pady=5)

user_input = tk.Entry(root, width=50)
user_input.pack(pady=10)

send_button = tk.Button(root, text="Send", command=send_message)
send_button.pack(pady=20)

root.mainloop()

セットアップ・実行

# gitクローン
git clone https://github.com/KaT0819/openai-chat-sample.git

# venv環境設定
cd openai-chat-sample
python -m venv openai_chat_env

source openai_chat_env/bin/activate

# 環境変数にOpenAIのAPIキーを設定
export OPENAI_API_KEY=your_api_key

# 必要なパッケージをインストール
pip install -r requirement.txt

# 実行
python openai_chat_app.py

上記でほぼ全量ですが、セットアップ手順含めたソースのリポジトリです。
https://github.com/KaT0819/openai-chat-sample

ChatGPTとのやりとり

上記のコードになるまでのChatGPTとのやりとりを示します。
途中、解説的なものは下記の注釈で示します。

[私] 導入

open aiのAPIを用いたチャットツールをデスクトップアプリケーションで作りたいのでコードを書いて

[GPT]

OpenAIのAPIを使用して、デスクトップアプリケーションのチャットツールを作成するためのシンプルなコード例を提供します。ここではPythonを使用し、TkinterをGUIライブラリとして使用します。

まず、必要なライブラリをインストールします:

pip install openai tkinter

次に、以下のPythonコードを使用してデスクトップアプリケーションを作成します:

import tkinter as tk
from tkinter import scrolledtext
import openai

# OpenAIのAPIキーを設定
openai.api_key = 'YOUR_OPENAI_API_KEY'

def send_message():
    user_message = user_input.get()
    chat_area.insert(tk.END, f"You: {user_message}\n")
    user_input.delete(0, tk.END)

    # OpenAI APIを呼び出して回答を取得
    response = openai.Completion.create(
        engine="davinci",
        prompt=f"{user_message}\nAI:",
        max_tokens=150
    )

    ai_message = response.choices[0].text.strip()
    chat_area.insert(tk.END, f"AI: {ai_message}\n")

# GUIの設定
root = tk.Tk()
root.title("OpenAI Chat")
root.geometry("400x500")

chat_area = scrolledtext.ScrolledText(root, wrap=tk.WORD)
chat_area.pack(pady=15)

user_input = tk.Entry(root, width=50)
user_input.pack(pady=20)

send_button = tk.Button(root, text="Send", command=send_message)
send_button.pack(pady=20)

root.mainloop()

このコードを保存して実行すると、Tkinterのウィンドウが表示され、ユーザーはメッセージを入力してOpenAIのAPIに問い合わせることができます。

注意点:

  • この例は基本的なものであり、エラーハンドリングなどの多くの側面がカバーされていません。
  • 実際に本番環境で使用する場合、APIキーをコード内にハードコードしないようにしてください。安全な方法でキーを管理する必要があります。
  • また、APIコールのコストに注意してください。大量のメッセージや高頻度での使用はコストがかかります。

このコードをベースに、さらなる機能やカスタマイズを追加することができます。

[私] 仮想環境化の依頼

先にvenvで仮想環境を定義したいです。

[GPT]

了解しました。Pythonのvenvを使用して仮想環境を設定し、その上で先程のデスクトップアプリケーションを作成する手順を示します。

  1. まず、仮想環境を作成します。
python -m venv openai_chat_env
  1. 作成した仮想環境をアクティベートします。
  • Linux/macOSの場合:
source openai_chat_env/bin/activate
  • Windowsの場合:
openai_chat_env\Scripts\activate
  1. アクティベートされた仮想環境上で必要なライブラリをインストールします。
pip install openai tkinter
  1. 以前提供したPythonコードを保存します。例として、openai_chat_app.pyという名前で保存しましょう。

  2. 保存したコードを実行します。

python openai_chat_app.py

これで、venvでの仮想環境上でOpenAI APIを使用したデスクトップアプリケーションが動作します。

作業が終了したら、仮想環境をデアクティベートするには以下のコマンドを実行します。

deactivate

注意: 仮想環境を使うことで、グローバルなPython環境を汚染せずに必要なライブラリや依存関係をインストールすることができます。

[私] エラーの解決を依頼

tkinterのインストールで
以下のエラーが出ました。原因と対策を書いて

pip install openai tkinter
Collecting openai
  Downloading openai-0.28.0-py3-none-any.whl (76 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 76.5/76.5 kB 2.7 MB/s eta 0:00:00
ERROR: Could not find a version that satisfies the requirement tkinter (from versions: none)
ERROR: No matching distribution found for tkinter

[notice] A new release of pip is available: 23.1.2 -> 23.2.1
[notice] To update, run: pip install --upgrade pip

[GPT]

tkinterはPythonの標準ライブラリの一部であり、通常はPythonとともに自動的にインストールされます。そのため、pipを使用して外部からインストールすることはできません。上記のエラーメッセージは、piptkinterを公式のPython Package Index (PyPI) で見つけられなかったことを示しています。

対策:

  1. まず、tkinterが既にインストールされているかどうかを確認します。Pythonインタープリタで以下のコードを実行してみてください。
import tkinter
print(tkinter.TkVersion)

エラーが発生しなければ、tkinterは正しくインストールされています。

  1. もし1のステップでエラーが発生する場合、Pythonを再インストールすることを考慮してください。再インストール時にtkinterが含まれるようにするために、正しいインストールオプションを選択する必要があります。これは、使用しているOSやPythonのディストリビューションによって異なる場合があります。

  2. 仮想環境に問題がある場合、新しい仮想環境を作成して再試行することも考慮してください。

また、pipのアップデートに関する通知が表示されていますので、以下のコマンドを実行してpipをアップデートすることをおすすめします。

pip install --upgrade pip

しかし、tkinterの問題とは無関係ですので、まずtkinterの問題を解決してからpipのアップデートを行っても構いません。

[私] 秘密情報の秘匿化を依頼

openai.api_keyは環境変数から受け取るように書き換えて

[GPT]

もちろん、Pythonで環境変数を読み取るには、osモジュールを使用します。以下はopenai.api_keyを環境変数から受け取る方法です。

  1. 最初に、osモジュールをインポートします。

  2. os.environを使用して環境変数を読み取ります。ここでは、環境変数の名前としてOPENAI_API_KEYを使用しますが、お好みに合わせて名前を変更することができます。

以下は具体的なコードです:

import os
import openai

# 環境変数からAPIキーを取得
api_key = os.environ.get('OPENAI_API_KEY')

# APIキーが設定されているか確認
if not api_key:
    raise ValueError("OPENAI_API_KEY environment variable not set")

openai.api_key = api_key

# 以降、OpenAIのAPIを使用するコード

このコードを使用する前に、環境変数OPENAI_API_KEYを設定しておく必要があります。

コマンドラインから環境変数を設定する場合の例:

export OPENAI_API_KEY=your_openai_api_key_here

上記のコードはUNIX系のシステム(LinuxやMac)での例です。Windowsの場合は、環境変数の設定方法が異なる場合があります。

[私] 賢いモデルに変更を依頼

もっと賢いモデルに書き換えて

[GPT]

あなたのコードをもっと高性能なモデル、例えば "gpt-3.5-turbo" でアップグレードすることは賢い選択です。また、新しいChat APIエンドポイントを使用して、継続的な会話をより効果的に行うことができます。以下のように変更してください:

import tkinter as tk
from tkinter import scrolledtext
import os
import openai

# 環境変数からAPIキーを取得
api_key = os.environ.get('OPENAI_API_KEY')

# APIキーが設定されているか確認
if not api_key:
    raise ValueError("OPENAI_API_KEY environment variable not set")

openai.api_key = api_key

messages = [
    {"role": "system", "content": "You are a helpful assistant."}
]

def send_message():
    user_message = user_input.get()
    chat_area.insert(tk.END, f"You: {user_message}\n")
    user_input.delete(0, tk.END)

    messages.append({"role": "user", "content": user_message})

    # OpenAI APIを呼び出して回答を取得
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=messages
    )

    ai_message = response['choices'][0]['message']['content']
    chat_area.insert(tk.END, f"AI: {ai_message}\n")
    messages.append({"role": "assistant", "content": ai_message})


# GUIの設定
root = tk.Tk()
root.title("OpenAI Chat")
root.geometry("400x500")

chat_area = scrolledtext.ScrolledText(root, wrap=tk.WORD)
chat_area.pack(pady=15)

user_input = tk.Entry(root, width=50)
user_input.pack(pady=20)

send_button = tk.Button(root, text="Send", command=send_message)
send_button.pack(pady=20)

root.mainloop()

この変更で行ったこと:

  1. グローバル変数messagesを作成して、会話のコンテキストを格納し、これをAPIリクエスト時に利用しています。
  2. openai.Completion.createメソッドをopenai.ChatCompletion.createに変更し、モデルを "gpt-3.5-turbo" に設定しています。
  3. ユーザーとアシスタントのメッセージを適切にmessagesリストに追加しています。
  4. APIからの応答を処理する方法を変更しています。

これで、アプリケーションは前回のメッセージを記憶し、前のコンテキストを利用してより自然な会話を行うことが可能になります。

[私] 最新情報の取得について

gpt4を使う形に書き換えて

[GPT]

2023年8月の時点での情報に基づくと、GPT-4の詳細や実装に関する公式情報はOpenAIから公開されていません。したがって、具体的なAPIのエンドポイントやモデル名などの情報は提供できません。しかし、もしGPT-4が公開され、それに関するAPIエンドポイントやモデル名が提供されている場合、以下のようにコードを変更することで利用することができるでしょう。

import tkinter as tk
from tkinter import scrolledtext
import os
import openai

# 環境変数からAPIキーを取得
api_key = os.environ.get('OPENAI_API_KEY')

# APIキーが設定されているか確認
if not api_key:
    raise ValueError("OPENAI_API_KEY environment variable not set")

openai.api_key = api_key

messages = [
    {"role": "system", "content": "You are a helpful assistant."}
]

def send_message():
    user_message = user_input.get()
    chat_area.insert(tk.END, f"You: {user_message}\n")
    user_input.delete(0, tk.END)

    messages.append({"role": "user", "content": user_message})

    # OpenAI APIを呼び出して回答を取得
    response = openai.ChatCompletion.create(
        model="gpt-4.0-turbo",  # GPT-4の適切なモデル名に変更する
        messages=messages
    )

    ai_message = response['choices'][0]['message']['content']
    chat_area.insert(tk.END, f"AI: {ai_message}\n")
    messages.append({"role": "assistant", "content": ai_message})


# GUIの設定
root = tk.Tk()
root.title("OpenAI Chat with GPT-4")
root.geometry("400x500")

chat_area = scrolledtext.ScrolledText(root, wrap=tk.WORD)
chat_area.pack(pady=15)

user_input = tk.Entry(root, width=50)
user_input.pack(pady=20)

send_button = tk.Button(root, text="Send", command=send_message)
send_button.pack(pady=20)

root.mainloop()

変更点:

  1. modelの値を "gpt-4.0-turbo"(想定されるGPT-4のモデル名)に変更しました。
  2. ウィンドウのタイトルを "OpenAI Chat with GPT-4" に変更しました。

これは仮のコードであり、実際のGPT-4のAPI仕様に基づいて適切な変更を行う必要があります。公式のドキュメントやリリースノートを確認して、正確な情報を元にコードを変更してください。

[私] アプリの機能拡張を依頼

他のモデルを選択したり、APIの他のパラメータを画面から指定できるように書き換えて

[GPT]

了解しました。以下のコードでは、モデルの選択およびAPIの他のパラメータ(例えば、max_tokens)を指定できるように画面を拡張しています。

import tkinter as tk
from tkinter import scrolledtext, ttk
import os
import openai

# 環境変数からAPIキーを取得
api_key = os.environ.get('OPENAI_API_KEY')

# APIキーが設定されているか確認
if not api_key:
    raise ValueError("OPENAI_API_KEY environment variable not set")

openai.api_key = api_key

messages = [
    {"role": "system", "content": "You are a helpful assistant."}
]

def send_message():
    user_message = user_input.get()
    chat_area.insert(tk.END, f"You: {user_message}\n")
    user_input.delete(0, tk.END)

    messages.append({"role": "user", "content": user_message})

    selected_model = model_combobox.get()
    max_tokens_val = int(max_tokens_input.get())

    # OpenAI APIを呼び出して回答を取得
    response = openai.ChatCompletion.create(
        model=selected_model,
        messages=messages,
        max_tokens=max_tokens_val
    )

    ai_message = response['choices'][0]['message']['content']
    chat_area.insert(tk.END, f"AI: {ai_message}\n")
    messages.append({"role": "assistant", "content": ai_message})

# GUIの設定
root = tk.Tk()
root.title("OpenAI Chat")
root.geometry("500x600")

chat_area = scrolledtext.ScrolledText(root, wrap=tk.WORD)
chat_area.pack(pady=15)

model_label = tk.Label(root, text="Select Model:")
model_label.pack(pady=5)
available_models = ["gpt-3.5-turbo", "davinci", "curie", "babbage", "ada"]
model_combobox = ttk.Combobox(root, values=available_models, state="readonly")
model_combobox.set("gpt-3.5-turbo")
model_combobox.pack(pady=5)

max_tokens_label = tk.Label(root, text="Max Tokens:")
max_tokens_label.pack(pady=5)
max_tokens_input = tk.Spinbox(root, from_=1, to=1500, width=7)
max_tokens_input.pack(pady=5)

user_input = tk.Entry(root, width=50)
user_input.pack(pady=10)

send_button = tk.Button(root, text="Send", command=send_message)
send_button.pack(pady=20)

root.mainloop()

このコードでは、ttk.Comboboxを使用して利用可能なモデルを選択するUIを提供します。さらに、max_tokensを指定するためのtk.Spinboxも追加されています。ユーザーはこれらのオプションを使ってAPIの呼び出しをカスタマイズできます。

終わりに

Pythonのライブラリが充実しているのでかなり簡単な実装でOpenAIのAPIを使うことができました。
最初に出力されたdavinci版でのチャットでは正直使い物にならないと感じましたが、
GPT3.5との違いは学習に用いたパラメータ数だけという話もあるので、モデルの違いによっての進化の過程を垣間見ることができました。
ファインチューニングも興味あるので近いうちに試したいと思います。

ちなみに、第3代内閣総理大臣は山縣 有朋でした。

レスキューナウテックブログ

Discussion