search
LoginSignup
60

More than 1 year has passed since last update.

posted at

updated at

Organization

GPT-3 & OpenAI Codexの使用方法。文章からプログラムを自動生成する方法

本記事ではOpenAIのGPT-3およびCodexの使用方法と、文章自動生成、文章からプログラムの自動生成、プログラムから文章を自動生成する方法を紹介します。

また最後にGPT-3での素数生成の再現も試みます。

本記事の内容

  1. GPT-3、Codex、Copilotの違いとは
  2. GPT-3、Codex、Copilotを使用するための申請方法
  3. GPT-3の使用例:広告文書の作成
  4. Codexの使用例:Pythonのコードからコードのコメント文を生成
  5. Codexの使用例:Pythonのコードからdocstringを生成
  6. Codexの使用例:文章からPythonプログラムの生成
  7. GPT-3で素数を生成してみる
  8. さいごに

1. GPT-3、Codex、Copilotの違いとは

GPT-3、Codex(コーデックス)、Copilot(コパイロット)の違いについて説明します。

初め、私にはCodexとCopilotの違いが分かりづらかったです。

GPT-3

GPT-3 [link]の正式名称は「Generative Pretrained Transformer version3」です。

その名の通り、BERTなどでも使用されるTransformerを使用した言語モデルとなります。

GPT-3では入力に文章を与え、何らかを出力させます。

基本的には、文章を出力させることが多く、言語生成モデルとなります。

Codex

Codex [link]の正式名称は「code extension model」です(だと思われます)。

当初のGPT-3の発表ではGPT-3に文章を入力し、プログラムコードを生成させるデモなどがありました。

CodexはGPT-3の、入力もしくは出力がプログラミングコードである部分を取り出したものです(code extension model)。

おそらく、OpenAIがAPIを開放する際の整理のために、

自然言語を出力するものは「GPT-3 API」にして、プログラミングコードが関係するAPI機能は「Codex」に整理したのだと思います。

Copilot

Copilot[link]の正式名称は「GitHub Copilot」です。

Copilotは普通の英単語で、飛行機などの副操縦士を意味します。

CopilotはCodexを使用し、GitHubの(おそらく利用権限に問題がない)各種コードを学習させた「VS Code」の拡張機能です。

コーディングを支援してくれるAI機能になります。

正式名称にGiHubが含まれており、使用プラットフォームが「VS Code」であることから分かるように、Copilotを管轄しているのはOpenAIではなく、GitHub(Microsoft)です。

2. GPT-3、Codex、Copilotを使用するための申請方法

GPT-3、Codex

GPT-3とCodexはOpenAIのAPIページの申請フォーム(APIページの右上のJOIN)から申請します。

o1.JPG

申請するとwait listに追加され、時期が来ると「使用できるようになりましたー」というメールが届きます。

上記の図の通り、GPT-3(language models)とCodex(code models)を両方同時に(Both)申請することができます。

ただし、「使用できるようになりましたー」メールは別々のタイミングで届きます。

私の場合、GPT-3が1日後、Codexが2日後くらいでした。

申請フォームには、「What is your GitHub profile?」とGitHubのURLを記入する部分、

そして、「If you have an idea you want to use the API for, what is it?」と、どんな風に使用しますか?というのを記入する部分があります。

そのため、育っているGitHubアカウントを持ち、良い感じにアイデアを書いておくと、申請が通るのが早くなるかもしれません。

Copilot

Copilotは、GPT-3とCodexとは違い、OpenAIではなく、GitHubのページ こちら から申請します。

ページ中央にある「Sign UP」ボタンをクリックします。

私もまだCopilotはwaiting listのままで、使用できる状態にありません。

Copilotが使用できるようになったら、また報告したいと思います。

3. GPT-3の使用例:広告文書の作成

GPT-3およびCodexの使用例を紹介します。

まずは広告文書の作成例です。

OpenAIのAPIページにログインすると、各種exampleが用意されています(約60個)。

o2.JPG

まずは、ここのGPT-3の権限だけで実行できる「Ad from product description」(商品説明からの広告文生成)を紹介します。

image.png

実行方法は複数あります。

一番簡単なのは上図の右上にある「Open in Playground」をクリックして、Webページ上で体験する方法です。

その他にも、上図の下側のようにAPIを各種言語から叩いてresponseとして取得することもできます。

OpenAIとしては公式にはCurlで叩けるものと、Python SDKしか提供していませんが、各種言語でのラッパーが用意されており(C#.net、Java、Javascript、GO、Rubyなどなど)、公式ページで以下のようにリンクが案内されています。

o3.JPG

「Playground」での使用の様子は以下の通りです。

はじめに入力文を与えておき、そして「Submit」ボタンをクリックします。

すると、広告文が生成されます。

GPT3-ad_text_generation.gif

上記の例の場合、

入力は以下です。

Write a creative ad for the following product to run on Facebook:
""""""
Airee is a line of skin-care products for young women with delicate skin. The ingredients are all-natural.
""""""
This is the ad I wrote for Facebook aimed at teenage girls:
""""""

商品説明の文章が

最初に目的として、「Facebook用の広告として、以下の製品のad文章を生成せよ」と指令しています。

商品説明は、

「Aireeは、デリケートな肌を持つ若い女性のためのスキンケア製品ラインです。成分はすべて天然のものを使用しています。」

です。

そして、「10代の女性向けにFacebook広告としては以下となります」。

と記入して、入力が終了します。

あとは、GPT-3の出力です。

出力は、以下のような感じです(上記の図とは少し異なります。毎回異なる生成になるので)

Airee is a line of skin-care products for young women with delicate skin.
The ingredients are all-natural.
You need to be gentle with your skin. It's important to take care of it.
Airee is perfect for you. It's gentle and

Aireeは、デリケートな肌を持つ若い女性のためのスキンケア製品ラインです。
成分はすべて天然のものを使用しています。
自分の肌に優しくすることが必要です。ケアすることが大切なのです。
Aireeはあなたにぴったりです。穏やかで

生成するたびに変わるので、

You know how it's always hard to find a moisturizer that won't make your skin break out?
Well, Airee is the answer to your prayers. 
With all-natural ingredients and a light, moisturizing formula, 
Airee will keep your skin looking and feeling great.

肌が荒れない保湿クリームを見つけるのはいつも大変なんですよね。
Aireeはそんなあなたの願いを叶えてくれます。
すべての天然成分と、軽い保湿剤を使用しています。
Aireeは、あなたの肌の見た目と感触を保ちます。

です。


APIを叩くこともでき、Pythonで上記を実現する場合は以下の通りです。

import os
import openai

openai.api_key = os.getenv("OPENAI_API_KEY")

response = openai.Completion.create(
  engine="davinci-instruct-beta",
  prompt="Write a creative ad for the following product to run on Facebook:\n\"\"\"\"\"\"\nAiree is a line of skin-care products for young women with delicate skin. The ingredients are all-natural.\n\"\"\"\"\"\"\nThis is the ad I wrote for Facebook aimed at teenage girls:\n\"\"\"\"\"\"",
  temperature=0.5,
  max_tokens=60,
  top_p=1.0,
  frequency_penalty=0.0,
  presence_penalty=0.0,
  stop=["\"\"\"\"\"\""]
)

事前にpip install でopenaiをインストールしておきます(openai gymとは違うので注意)。

responseは以下のような感じになっており、textに生成された文が入っています。

<OpenAIObject text_completion id=cmpl-3utxvRERchBUwZCIAPbzilXmUJFE4 at 0x7ff061f40d10> JSON: {
  "choices": [
    {
      "finish_reason": "length",
      "index": 0,
      "logprobs": null,
      "text": "\nAiree is a line of skin-care products for young women with delicate skin. The ingredients are all-natural.\n\nYou need to be gentle with your skin. It's important to take care of it.\n\nAiree is perfect for you. It's gentle and"
    }
  ],
  "created": 1634690511,
  "id": "cmpl-3utxvRERchBUwZCIAPbzilXmUJFE4",
  "model": "if-davinci-v2",
  "object": "text_completion"
}

重要点

OpenAIのAPIを使ううえで重要な点は以下の6つかと思います。

  1. 現在の対応は英語のみで、日本語での入力はできません

  2. アカウントには事前に18ドルくらい?の使用料金が付与されていますが、それを超えると払う必要あります

  3. 料金は入力する文字数(正確には分かち書きしたトークン数)で決まります

  4. さらに料金は使用するパラメータengine(上記の例ではdavinci-instruct-beta)でも変わります。
    賢さ(モデルサイズや事前訓練の量)がエンジンによって異なっており、Davinci、Curie、Babbage、Adaの順番で賢いが処理が遅くなります。

  5. させたいタスクはengineでモデル名のあとにつなげます。Base series、Instruct series、Codex series、Content filterの4種類があります。多くは、instructにして、入力文にさせたいタスクを実際に入力することになります(上記のad文章の生成の入力のように)

  6. 上記のCodex seriesがCodexを使用するための設定ですが、Codexの権限許可が下りるまでは実行できません

4. Codexの使用例:Pythonのコードからコードのコメント文を生成

続いて、Exampleの「Python to natural language」を試します。

以下のような入力を与え、エンジンにdavinci-codexを使用すると、以下の図のような動作をします。

以下の関数は、
「変数ws_prefixTrueなら、変数xの接頭語prefixを空白スペースに変換する」
という内容です。

# Python 3 
def remove_common_prefix(x, prefix, ws_prefix): 
    x["completion"] = x["completion"].str[len(prefix) :] 
    if ws_prefix: 
        # keep the single whitespace as prefix 
        x["completion"] = " " + x["completion"] 
return x 

# Explanation of what the code does

#

GPT3_Pythontonatural language.gif

出力は

The code above is a function that takes three arguments:

と、
「上記の関数は3つの引数をとります」でした。

ちょっと、使い物にならないですね。。。

Playgroudの右端での設定が問題です。

Stop sequencesに、"#"が設定されているのを除去して、2文以上のコメント文を生成できるようにします。

さらにResponse lengthが64では短文しか作れないので、256に増やしてあげます。

これで実行すると以下の通りです。

GPT3_Pythontonatural language2.gif

出力結果は以下の通りです。

最初に各引数を説明しているのですが、きちんと各引数が関数の動作の説明となる正確な文章です。
とくにxdataframeであることを説明しており、かつ、ws_prefixがフラグとなっていて、しかもスペースに接頭語を置換する点まで説明してくれています。

# The code above is a function that takes three arguments:
# 
# * `x`: a row of the dataframe
# * `prefix`: the prefix to remove
# * `ws_prefix`: whether or not to keep the single whitespace character that was added to the prefix
# 
# The function returns a modified version of the row, where the `completion` column has the prefix removed.
# 
# The function is then passed to the `apply` method of the dataframe, which applies the function to each row.
# 
# The `apply` method is a very powerful method of dataframes, and there are many use cases.
# 
# For more information, see the [documentation](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.apply.html).

# The code above is a little verbose, and it can be simplified using a lambda function.
# 
# A lambda function is a function without a name.
# 
# The code below is equivalent to the code above, but uses a lambda function instead.


入力した関数は型ヒントがないのですが、xがdictなどでは、x["completion"].str[が実行できないので、xはdataframe型である必要があります。

その点まで説明し、さらにリファレンスとして、
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.apply.html

を書き出し、dataframeに対する関数のひっかけかた(ここでは、.str[])の説明のURLまで提示してくれました。

5. Codexの使用例:Pythonのコードからdocstringを生成

続いて、Exampleの「Write a Python docstring」を試します。

入力は以下の通りです。engineはdavinci-codexです。

フォルダ名とファイル名を引数に、訓練とテストのdataframeを分割し、それぞれをJSONにして保存しています。

# Python 3.7

def randomly_split_dataset(folder, filename, split_ratio=[0.8, 0.2]):
    df = pd.read_json(folder + filename, lines=True)
    train_name, test_name = "train.jsonl", "test.jsonl"
    df_train, df_test = train_test_split(df, test_size=split_ratio[1], random_state=42)
    df_train.to_json(folder + train_name, orient='records', lines=True)
    df_test.to_json(folder + test_name, orient='records', lines=True)
randomly_split_dataset('finetune_data/', 'dataset.jsonl')

# An elaborate, high quality docstring for the above function:
"""

動作は以下の通りです。

GPT3_Write_a_Python_docstring.gif

出力は

Randomly splits a dataset into train and test sets.

:param folder: The folder where the dataset is located.
:param filename: The name of the dataset file.
:param split_ratio: The ratio of train to test samples.
:return: None

きちんとした関数と引数の説明、そして返り値がないことまで説明してくれています。

上記はreStructuredTextのstyleのdocstringであって、次はNumpy styleにしたいとします。

次は、「先ほどコメント文を生成させた接頭語をスペースに変換する関数」を入力、そしてdocstringはNumpy Styleにしたいと思います。

GPT-3 Codexへの入力は次の通りです。

# Python 3.7

def remove_common_prefix(x, prefix, ws_prefix): 
    x["completion"] = x["completion"].str[len(prefix) :] 
    if ws_prefix: 
        # keep the single whitespace as prefix 
        x["completion"] = " " + x["completion"] 
    return x 

# An elaborate, high quality docstring for the above function in Numpy style:
"""

さきほどは

# An elaborate, high quality docstring for the above function:

であった部分の最後に、in Numpy styleと足してあげます。

動作は次の通りです。

GPT3_Write_a_Python_docstring2.gif

出力は

Remove a common prefix from a column in a dataframe.

Parameters
----------
x : pandas.DataFrame
    The dataframe containing the column to be modified.
prefix : str
    The prefix to be removed.
ws_prefix : bool
    Whether to keep the single whitespace character after the prefix.

Returns
-------
x : pandas.DataFrame
    The modified dataframe.

Numpy Styleで説明、引数、返り値を記述するとともに、ws_prefixが接頭語を空白スペースに変換するかのフラグである点の説明など、各変数の内容についてもきちんと説明してくれています。

6. Codexの使用例:文章からPythonプログラムの生成

最後に文章からプログラムを生成します。

Exampleの「Natural language to Stripe API」をしてみます。

Stripeは決済サービスのプラットフォームでいろいろな言語のSDKが用意されています。

今回はExample通りではなく、Pythonのコードを生成させてみましょう。

まず「Natural language to Stripe API」のPlaygroundを開きます。

右側のResponse lengthを200にして、長い文章を生成できるように設定します。

入力する内容は元の、

"""
Util exposes the following:

util.stripe() -> authenticates & returns the stripe module; usable as stripe.Charge.create etc
"""
import util
"""
Create a Stripe token using the users credit card: 5555-4444-3333-2222, expiration date 12 / 28, cvc 521
"""

ではなく、

"""
Create a Stripe token using the users credit card: 5555-4444-3333-2222, expiration date 12 / 28, cvc 521 in python sdk
"""

に変更します。

動作は次の通りです。

GPT3_Write_a_Python_code.gif

出力は

import stripe

stripe.api_key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"

token = stripe.Token.create(
    card={
        "number": "5555-4444-3333-2222",
        "exp_month": 12,
        "exp_year": 2020,
        "cvc": "521",
    },
)

print(token)

となりました。

私はStripeのPython SDKを使用したことがないので、正しいか確認してみます。

stripe.JPG

リンクはこちら

importするライブラリはstripeで合っています。

また使用する関数がstripe.Token.createで、これも合っています。

生成されたAPI Tokenが誰かがGitHubに誤って公開したものだと恐ろしかったのですが、Stripeの公式ページの見本と一致しており、見本例をきちんと引っ張ってきてくれたのだと分かりました。

続いて、私は、stripe.Token.create関数のパラメータ名をもちろん知らないのですが、"number"や"exp_month"を正しく使用してくれています。

そして"exp_month"には、入力文章で「expiration date 12 / 28」と与えた通り、きちんと12月が与えられています。

よって、私の知らないPython SDKでのコードを文章からうまく自動生成できたと判断します。

「本例は、1関数だけで構成される、SDK Documentsに見本がある簡単なレベルの内容ではありますが、文章を入力すればプログラムが生成されるという凄い世界になったものです」


最後に、API keyも指定して、コードを自動生成させましょう。

入力は以下です。

"""
Create a Stripe token using the users credit card: 5555-4444-3333-2222, expiration date 12 / 28, cvc 521 in python sdk.
My api key is sk_test_yutaroogawa.
"""

動作は以下の通りです。

GPT3_Write_a_Python_code2.gif

出力は

import stripe

stripe.api_key = "sk_test_yutaroogawa"

token = stripe.Token.create(
    card={
        "number": "5555-4444-3333-2222",
        "exp_month": 12,
        "exp_year": 2020,
        "cvc": "521",
    },
)

print(token)

となり、api_keysk_test_yutaroogawaを代入してくれました。

これで完全に、自然言語から、プログラムの自動生成が完了できました。

7. GPT-3で素数を生成してみる

最後に、GPT-3で素数を生成してみます。

以下の記事にて、松尾先生がGPT-3の素数生成能力の話をしています。

さらに、GPT-3には素数が列挙できるという特徴もある。最初の12個ぐらいの素数を「2、3、5、7、11……」と列挙すると、その後の数字を続け始めるというのだ。

もしかしたら、インターネット上にはたくさんのデータがあるため、「素数を列挙したページから丸覚えしたのではないか?」と思われるかもしれない。しかし、GPT-3は誤って「3693」など素数ではない数字もはじき出しているという。

松尾豊さんは「間違えているということは、計算をちゃんとしているということです。つまり、たくさんのデータを入力して学習させるだけで、(GPT-3には)素数を計算するようなアルゴリズムが学習されています」と解説する。

GPT-3はビジネスの世界も変え得る。松尾豊さんは「非常に多くのタスクが今後、GPT-3によって実現される可能性があります。法務、人事、調達などなどはもちろん、ヘルスケアの分野でも、たくさんテキストを使う仕事があります。こういったものを次々と自動化していく可能性があると思います」と話した。

上記の松尾先生の見解は、Aravind Srinivas(OpenAI所属)のTwitterに由来します。

確かに、129のような素数でない数字も生成しているのですが、ほとんどが素数で、たまに素数を飛ばしてしまったりもしています(263など)。

ただ、Aravind Srinivasのこの結果を再現する方法がどこにもないので、本当か?と疑問があります。

ここで試してみましょう。


入力するのは、109までの素数とし、その続きを生成させることにします(109までにしたのは、100以下の素数を羅列したサイトは多いため、それを引用する可能性を考慮)。

2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109,

engineには一番賢いDavinci、そして2番目のCurieの2つを使用して比べてみます。

まずCurieでの生成の様子を以下に示します。Response lengthは70に設定しています。

GPT3_seq_q.gif

出力は

113, 127, 131, 137, 139, 149, 151, 157, 161, 163, 167, 173, 179, 181, 187, 191, 193, 197, 199, 211, 223, 227, 229, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255,

となりました。

113から233のうち、ほとんど(22個)は素数ですが、161(7×23)と187(11×17)のみ素数ではありません。

233からその先は単純に2ずつ増えていて素数生成になっていません。

凄いのは、与えた数字が109までの素数なので、入力した数値の最大値の2倍である233あたりまでは素数をきちんと出力していることです。そして松尾先生の指摘通り、素数表を引用しているわけではなさそうで、161と187という素数でない誤った数字も出力しています。

松尾豊さんは「間違えているということは、計算をちゃんとしているということです。つまり、たくさんのデータを入力して学習させるだけで、(GPT-3には)素数を計算するようなアルゴリズムが学習されています」と解説する。

が再現できました。


それでは続いて、engineを最高レベルのDavinciで試してみましょう。

先ほどと同じく入力するのは、109までの素数とし、その続きを生成させることにします。

2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109,

Davinciでの生成の様子を以下に示します。

GPT3_seq_davinch.gif

出力は

113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311,

となりました。

これは全て完全に素数です。誤りもなく、抜けもなく、きちんと生成されています。

Curieと違って、Davinciは入力した数列から、素数の数列であることを把握し、続きの素数をどこかから引用して羅列している可能性があります・・・

109までの入力で素数と判断しているなら、それはそれで凄いのですが、その場合、続きの生成はCurieとは違い、GPT-3にとくにアルゴリズムはなく素数表の引用になります。


上記仮説が本当かどうかを検証するために、当人であるGPT-3のDavinciCurieに聞いてみることにします。

入力は以下の通りです。上記の数列は何ですか?と尋ねてみます。

2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109,
Q: What are these sequential numbers?

Response lengthは20にします。

まずはDavinciを試します。

動作は以下の通りです。
今回は一度20 lengthの文章を生成したあと、再度もう一度続きを生成してみました。

GPT3_seq_davinch2.gif

出力は1回目が、

A: They are the prime numbers.
Q: What are the prime numbers?
A:

続きが、

A: They are the numbers that can only be divided by themselves and 1.
Q: What are the

であり、入力が素数(prime numbers)であると把握していることが分かります。

また、丁寧に素数の説明もしてくれました。

よって、GPT-3 Davinciは入力を素数と判断していることが確定し、数字生成は素数表をどこかから引用しているだけと思われます。

では、同じ質問をGPT-3 Curieに尋ねるとどうでしょうか?

以下が動作の様子です。

GPT3_seq_qq2.gif

出力は

A: They are the numbers that are used to identify the different parts of the sequence.

(これらはシーケンスの異なる部分を特定するために使用される数字です。)

となり、GPT-3 Curieの場合は素数であることを把握できていません。

Curieの方がDavinciよりもモデルサイズが小さく、性能が低いため、入力を素数と把握できなかったのでしょう。


よってGPT-3の、engineDavinciは「素数を列挙したページから丸覚え」(入力を素数の数列と判定できていることも凄いですが)、そしてengineCurieは松尾先生が指摘した通り

「間違えているということは、計算をちゃんとしているということです。つまり、たくさんのデータを入力して学習させるだけで、(GPT-3には)素数を計算するようなアルゴリズムが学習されています」

と考えられます。

いったい、もう、どうなっているのだろう。。。
GPT-3Curieの、ちょっと間違うこともあるけど、ほぼほぼきちんと素数を生成できる能力に驚きです。

GPT-3Curieが備え持つ素数算出アルゴリズムの凄さにも驚きがあり、一方でDavinciが「入力された数列は素数の数列」と判断しており、それを踏まえて、続きの数列を生成していたという、自身の出力に対する説明性も驚くべきものだと感じています。

長くなりましたが、以上、GPT-3での素数生成の再現実験でした。

8. さいごに

以上、OpenAIのGPT-3およびCodexの使用方法と、GPT-3およびCodexを使用した文章生成、プログラムから文章を生成する方法、文章からプログラム生成、そして最後に素数生成を紹介しました。

長文をご一読いただき、ありがとうございました。


【記事執筆者】
電通国際情報サービス(ISID)AIトランスフォーメーションセンター 製品開発Gr
小川 雄太郎
主書「つくりながら学ぶ! PyTorchによる発展ディープラーニング」
自己紹介(詳細はこちら)

【情報発信】
Twitterアカウント小川雄太郎@ISID_AI_team

IT・AIやビジネス・経営系情報で、面白いと感じた記事やサイトを、Twitterで発信しています。

【免責】
本記事の内容そのものは執筆者の意見/発信であり、執筆者が属する企業等の公式見解ではございません


Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
60