『Python数値計算ノート』ではアフィリエイトプログラムを利用して商品を紹介しています。

ChatGPTをPythonで実装する方法

巷で話題になっている人工知能チャットボット ChatGPT (Chat Generative Pre-trained Transformer) に私もはまっています。ChatGPT は、OpenAI という企業が開発した人工知能です。自然言語処理という技術を使って人が話す言葉を理解でき、いろいろなトピックに関する知識を持っているので、ユーザーが聞きたいことについて答えることができます。それだけでなく、大まかな指示を伝えると、なんとプログラミングのコードまで書いてくれます(私の仕事がなくなったらどうしよう)。

ChatGPTのAPIについて調べます

こんな便利な ChatGPT を Python で実装できたら面白そうですよね。ChatGPT を組み込んだアプリも開発できそうです。というわけで、Google 検索を使わずに、ChatGPt にあれこれ質問しながら Python で使える API について調べてみました。ChatGPT との対話で有用な情報を得るための参考にしてみてください。準備として、

pip install openai

で、openai ライブラリをインストールしておいてください。
 
以下、[K] は記事本文 (KOBATO の頭文字)、[Q] は ChatGPT への質問、[ChatGPT] は ChatGPT からの返答です。
 
[Q] ChatGPT とは何ですか?
 
[ChatGPT] ChatGPT は、OpenAI が開発した大規模言語モデルの一つで、GPT-3.5 アーキテクチャを基盤としています。ChatGPT は、自然言語処理タスクを実行するために訓練された AI エージェントであり、自然な対話を通じてユーザーとコミュニケーションを行うことができます。ChatGPT は、一般的な知識から特定の分野の専門知識まで、幅広いトピックに関する情報を提供することができます。

[Q] PythonでChatGPTのAPIを使う方法を教えてください。ただし、あなたと同じ受け答えをするバージョンを使うようにしてください。
 
[ChatGPT] ChatGPTのAPIを使用するには、以下の手順に従ってください。
 
1. OpenAI に登録してください。OpenAI の登録は https://beta.openai.com/signup/ で可能です。登録が完了したら、OpenAI ダッシュボードから API キーを取得します。
 
2. Python の requests ライブラリを使用して API にリクエストを送信します。
 
3. リクエストの形式は以下のようになります。

# In[1]

import openai
import json

openai.api_key = "YOUR_API_KEY"

def ask(question):
    prompt = f"I am a large language model trained by OpenAI. Ask me anything!\nQ: {question}\nA:"
    response = openai.Completion.create(
        engine="text-davinci-002",
        prompt=prompt,
        max_tokens=1024,
        n=1,
        stop=None,
        temperature=0.7,
    )

    answer = response.choices[0].text.strip()
    return answer

4. 上記のコードを使用して、API から返された回答を表示できます。以下は、Python コンソールでの使用例です。

# In[2]

ask("What is the meaning of life?")
# 著作権侵害の可能性があるので実行結果は省略

このように、上記のコードを使用することで、ChatGPT の API を簡単に使うことができます。ただし、OpenAI の API は有料であるため、使用にはコストがかかります。

[K] いきなり、コードを全部書いてくれました。すごいですね。ちなみに、ChatGPTのもっている情報はちょっと古いので注意が必要です。それについても尋ねてみましょう。
 
[Q] あなたの持っている情報はいつのものですか?
 
[ChatGPT] 私が持っている情報は、2021年9月時点でのものです。私はその時点でトレーニングされた GPT-3.5 アーキテクチャに基づく大規模言語モデルであり、それ以降に更新された情報にはアクセスできません。最新の情報を取得するには、OpenAIの公式ウェブサイトやドキュメンテーションを参照することをお勧めします。
 
[K] つまり、ChatGPT は 2022 年のワールドカップの優勝国を知りません。つい最近盛り上がった WBC の結果も知りません。Python についても、最新情報は得られないので要注意です。
 
(ちなみに、In[2] の実行結果を Google 検索してみると、同じ文章が掲載された Web サイトがあったので、この記事での掲載は見送りました。ChatGPT は色々な Web サイトなどから大量にデータを学習している可能性があるので、出力を扱う際には著作権に注意する必要があります)
 
Google Colab に、上のコードをそのまま貼り付けて試してみると、一応動きましたが、なんかおかしいです。たとえば、ChatGPT の公式サイトで「Pythonの開発者は誰ですか?」と尋ねると、次のように詳細な答えを返してくれます。

[Q] Python の開発者は誰ですか?
 
[ChatGPT] Pythonの 開発者は、Guido van Rossum(グイド・ヴァン・ロッサム)氏です。彼は 1989 年に Python を開発し、1991 年に最初の公式リリースが行われました。Python は、Guido van Rossum 氏が率いる Python 開発者コミュニティによって開発・維持されています。Guido van Rossum 氏は、Python の開発においてリーダーシップを発揮し、Python のデザイン思想の大部分を担当しました。彼は Python の開発において多大な貢献をし、Python の成功に大きく貢献しています。Guido van Rossum 氏は、2018年 に Python 開発者コミュニティから退職しましたが、Python の開発者コミュニティは彼の遺産を引き継いで、Python の発展を続けています。
 
[K] しかし、以下のコードを実行すると …

# In[3]

ask("Pythonの開発者は誰ですか?")
# 'Guido van Rossum'

こんな素っ気ない答えしか返してくれません(ちなみに、このモデルは、こちらが日本語で質問しているにもかかわらず英語で答えることがありますが、質問に「日本語で答えてください」と付け加えておくと、日本語で応じてくれます)。なにか、おかしいですね。以下の質問で、engine に最新のモデルが指定されているかを確認しました。

[Q] openai.Completion.create() 関数で engine で指定できる種類には何がありますか?
 
[ChatGPT] OpenAI APIのCompletion エンドポイントでは、以下のようなエンジンが利用可能です。
 
text-davinci-002: OpenAIが提供する最も高度な自然言語生成モデルで、様々な自然言語タスクにおいて高いパフォーマンスを発揮します。
 
text-curie-001: text-davinci-002よりも小さいが、それでも高いパフォーマンスを持つ自然言語生成モデルです。
 
text-babbage-001: text-curie-001よりも小さいが、それでも高いパフォーマンスを持つ自然言語生成モデルです。
 
text-ada-001: 最も小さい自然言語生成モデルで、迅速な推論が必要な場合に最適です。
 
これらのエンジンは、それぞれ異なるサイズとパフォーマンスを持ち、使用する目的に応じて選択することができます。ただし、text-davinci-002 が最も高度なモデルであるため、一般的には最も推奨されます。

[K] text-davinci-002 が最新となっています。ただし、先ほども言ったように、これは 2021 年 9 月以前の情報なので、おそらく、より高度な engine が存在しているはずです。最新の ChatGPT API を使用する方法を知っておられる方は、コメント欄で教えていただけるとありがたいです。
 
[Q] openai.Completion.create() 関数で指定できる引数の種類を教えてください。
 
[ChatGPT] OpenAI APIのCompletionエンドポイントで使用可能な引数は以下の通りです。
 
engine: 使用するGPTモデルを指定するための文字列。使用可能な値は、先程の回答で示したように、”text-davinci-002″、”text-curie-001″、”text-babbage-001″、”text-ada-001″などがあります。
 
prompt: モデルに入力するテキストのプロンプトを指定するための文字列。この文字列には、モデルが回答を生成するために必要な情報が含まれている必要があります。
 
temperature: 生成されたテキストのランダム性を制御するための浮動小数点数。値が高いほど、より多様なテキストが生成されます。
 
max_tokens: モデルが生成するテキストの最大トークン数を指定するための整数。これを指定することで、生成されるテキストの長さを制御することができます。
 
n: モデルが生成するテキストの数を指定するための整数。デフォルト値は1で、1回のリクエストで1つのテキストが生成されます。
 
stop: テキスト生成を終了するためのトークンのリスト。これを指定することで、モデルが生成するテキストを制御することができます。
 
presence_penalty: テキストの重複を避けるための浮動小数点数。値が高いほど、テキストの重複を避けるために選択されたトークンの重みが低くなります。
 
frequency_penalty: テキストの重複を避けるための浮動小数点数。値が高いほど、より多様なトークンが選択されます。
 
これらの引数を適切に設定することで、OpenAI APIを使用して高品質なテキスト生成を行うことができます。
 
ChatGPT API については、こちらの書籍で詳しく扱われています。

ChatGPT API 生成AIプログラミング入門

新品価格
¥3,740から
(2023/6/8 09:31時点)


 
GPT-3 モデルを使用してトレーニングされた言語モデル text-davinci-003 の API が使用できるようです。In[1] のコードで text-davinci-002 の部分を text-davinci-003 に変えるだけで実装できます。

【補足】最新 API (gpt-3.5-turbo-0613) の実装方法

このまま、ChatGPT と会話を続けても、最新モデルを実装できそうにないので、個人的に最新モデル “gpt-3.5-turbo-0613” を実装する方法を調べておきました。0613 版は 2023 年 6 月 27 日にアップデートされた最新バージョンです。以下のコードで実装できるはずなので、ぜひお試しください。

# ChatGPT(gpt-3.5-turbo-0613モデル)

openai.api_key = "YOUR_API_KEY"

def askChatGPT(question):
    res = openai.ChatCompletion.create(
          model = "gpt-3.5-turbo-0613",
          messages = [{'role':'user', 'content':question}],
          max_tokens  = 1024
          )
    return res.choices[0].message.content

askChatGPT("あなたは何者ですか? 詳しく教えてください")

'''私はオープンAIの開発した言語処理AIで、GPT-3というモデルをベースにしています。私は自然言語でのコミュニケーションを通じて、ユーザーの質問や要求に対する応答を提供することができます。さまざまなトピックや文脈に関しての情報を持っており、翻訳、要約、質問応答などのタスクをこなすことが可能です。ただし、私はあくまでAIであるため、感情や意識は持ちません。'''

ChatGPTにPythonでプログラミングしてもらいます

 ChatGPT の Python のコーディング・スキルを見極めてみましょう。まずは、ウォーミングアップとして (AI にウォーミングアップは要らないと思うけど) 簡単な問題から。
 
[Q] Python で等比級数を近似計算する関数を書いてください。ただし、外部ライブラリは使用しないものとします。また、級数を任意の項で打ち切ることができるようにしてください。
 
[ChatGPT] 以下は、Pythonで等比級数を近似計算する関数の例です。この関数は級数を打ち切るための項数 n も引数として受け取ります。

# In[1]

def geometric_sum_approximation(a, r, n):
    """
    等比級数 a + ar + ar^2 + ar^3 + ... の近似値を計算する関数
    
    Parameters
    ----------
    a : float
        等比級数の初項
    r : float
        等比級数の公比
    n : int
        級数を打ち切る項数
    
    Returns
    -------
    approx_sum : float
        等比級数の近似値
    """
    approx_sum = 0
    for i in range(n):
        approx_sum += a * (r ** i)
    return approx_sum

この関数では、等比級数の初項 a、公比 r、級数を打ち切る項数 n を引数として受け取り、級数の近似値を計算して返します。級数の近似値は、初項 a に各項の重み r^i をかけたものをすべて足し合わせたものになります。range(n) を使って i の値を0から n-1 まで変化させ、それぞれの i について a * (r ** i) を計算して、approx_sum に加算します。最終的に、計算された approx_sum を返します。
 
[K] 丁寧に関数の説明文までつけてくれました。私も見習いたいぐらいの丁寧さです。実行例もつけてくれると完璧でしたが、せっかくなので、それもお願いしてみましょう。

[Q] geometric_sum_approximation() 関数の使用例をお願いします。
 
[ChatGPT] 前回の回答で作成した geometric_sum_approximation() 関数を使用する例を以下に示します。例えば、初項が1で公比が2の等比級数の10項目までの和を求める場合は、以下のように呼び出せます。

# In[2]

approx_sum = geometric_sum_approximation(1, 2, 10)
print(approx_sum)

#1023.0

[K] でも、等比級数は簡単すぎる問題でしたね。Pythonista であれば目をつぶっても書けるようなコードです。もう少し難しい問題を出してみましょう。

[Q] Pythonを使って、双子素数 を10組求めてください。
 
[ChatGPT] 以下は、Python を使って双子素数を10組求めるコードです。

# In[3]

def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(n**0.5)+1):
        if n % i == 0:
            return False
    return True

twin_primes = []
count = 0
n = 2

while count < 10:
    if is_prime(n) and is_prime(n+2):
        twin_primes.append((n, n+2))
        count += 1
    n += 1

print("10 pairs of twin primes are:")
for i in range(10):
    print(twin_primes[i])

'''
10 pairs of twin primes are:
(3, 5)
(5, 7)
(11, 13)
(17, 19)
(29, 31)
(41, 43)
(59, 61)
(71, 73)
(101, 103)
(107, 109)
'''

[K] おお! なかなかやりますね。では、次の問題。

[Q] SymPy を使って、ピタゴラス方程式 x^2 + y^2 = z^2 を解いてください。
 
[ChatGPT] 以下は、SymPy を使ってピタゴラス方程式 x^2 + y^2 = z^2 を解く Python コードです。

# In[4]

from sympy import symbols, Eq, solve

# x, y, z をシンボルとして定義する
x, y, z = symbols('x y z')

# x^2 + y^2 = z^2 を表す方程式を定義する
eq = Eq(x**2 + y**2, z**2)

# x, y, z に関する方程式を解く
sol = solve(eq, (x, y, z))

# 解を表示する
print(sol)

[K] ... ちょっと質問が難しすぎましたかね。ひと目で間違いだとわかるコードを、なぜか自信満々に書きました。次の問題は当サイトの機械学習で扱った内容です。

[Q] f(x) = x cos(2x) の [0, 2π] の範囲における最小値を 最急降下法 で求める Python のコードを書いてください。
 
[ChatGPT] 以下は、Pythonで最急降下法を使用して、f(x) = x cos(2x) の [0, 2π] 範囲における最小値を求めるコードです。

# In[5]

import numpy as np

def f(x):
    return x * np.cos(2 * x)

def grad_f(x):
    return np.cos(2 * x) - 2 * x * np.sin(2 * x)

def gradient_descent(f, grad_f, x_init, eta, epsilon):
    x = x_init
    while True:
        grad = grad_f(x)
        x_new = x - eta * grad
        if abs(f(x_new) - f(x)) < epsilon:
            return x_new
        x = x_new

x_init = np.pi / 4  # initial guess for x
eta = 0.01          # learning rate
epsilon = 1e-6      # tolerance for convergence

x_min = gradient_descent(f, grad_f, x_init, eta, epsilon)

print("The minimum value of f(x) is {} at x = {}".format(f(x_min), x_min))
# The minimum value of f(x) is -1.6441806555371843 at x = 1.711664424133624

[K] いちおう、最急降下法のアルゴリズムは知ってるみたいだけど ... 間違ってます。指定範囲内に 2 つある極小値のうち、大きい値を選択しています(ちゃんと質問で [0, 2π] 範囲という条件を付けたのに、そこは完全無視?)。一変数関数の極小値探索は機械学習の入門レベルの問題なので、これができないとなると ... やはりまだ本格的なコーディングは任せられないですね。とはいえ、ChatGPT もバージョンアップするたびにどんどん賢くなると思うので、いずれは本当に私の仕事もなくなるかもしれませんね(転職を考えようかな ... 他に何もできないけど)。
 
姉妹サイト「Excel VBA 数学教室」でも ChatGPT に数学の問題を解いてもらう記事を掲載しています。
 

コメント