ChatGPTのAPIの使い方

# １．はじめに
### この記事の目的
本記事では、ChatGPTのAPIをPythonで使う場合の基本や注意点をPython初心者に向けて説明していきます。また、GoogleのColabratoryを用います。

記事を書くのは初めてなので、気になる点があれば、ご指摘くださると助かります（内容のみならず記事のデザインなど全体も含め）。

### この記事のターゲット
本記事は、初めてPythonからChatGPTを動かす方向けの記事になります。また、使い方の説明だけを行うので、API料金や良いプロンプトの書き方、関数呼び出しなどについての説明はしません。この記事を役立てていただける方がいるとしたら、以下のような方々です。

   - ChatGPTのAPIキーを取得したが、使い方がわからない方
   - Pythonをあまり使ったことないがChatGPTを動かしてみたい方
   - プロンプトの入力や出力結果の見方がわからない方

一方でこの記事を全く読む必要がない、あるいは別の記事を読むべき方々は以下のようになります。

- APIキーの取得の仕方がわからない方：[公式ページを参照](https://platform.openai.com/account/api-keys)
- すでにChatGPTのAPIをスムーズに使えて、より高度なことを関数呼び出しを用いてやりたい方
- API使用料金の詳細が知りたい方
- 良いプロンプトの作り方を知りたい方

# ２．ChatGPTで応答を生成（利用例）
PythonでGPTを使うには、まず「openai」ライブラリをインストールしてからインポートする必要があります。

```python
!pip install openai
import openai
```

インポートができたら、api_keyメソッドで取得したAPIキーをstring型（クォーテーションで囲む）で入力します。これにより、PythonからChatGPTが操作できます。具体的には、ChatCompletion.createメソッドを使って応答を生成することになります。

詳細を説明する前に一度例を示します。

```python
# APIキーの設定
openai.api_key = "APIキー" 

# GPTによる応答生成
prompt = "以下の条件の下でおいしい食べ物を教えてください。\n条件1:和食\n条件2:甘い"
response = openai.ChatCompletion.create(
                    model = "gpt-3.5-turbo-16k-0613",
                    messages = [
                        {"role": "system", "content": "You are a helpful assistant."},
                        {"role": "user", "content": prompt}
                    ],
                    temperature=0
                )

# 応答の表示
text = response['choices'][0]['message']['content']
print(text)
```

以上を実行すると、次のような応答が得られました。

```
Out[1]:
条件1と条件2を満たすおいしい食べ物は、和菓子です。
和菓子は、伝統的な日本の甘いお菓子であり、和食の一部としても楽しまれています。
代表的な和菓子には、あんこや抹茶を使用したものがあります。
和菓子は、見た目も美しく、季節感を感じることができるため、特別な日やお茶の時間にぴったりです。
是非、和菓子を試してみてください。
```

これで、PythonからChatGPTを操作できるようになりました。この中身を詳しく見ていきます。


# ３．関数の引数
PythonからChatGPTを操作する場合は、「openai」ライブラリのChatCompletion.createメソッドを使います。引数としては様々なものがありますが、ここでは数種類のみを紹介します。

### **model：str, 必須**

　ChatGPTの出力の際に使用するモデルをstring型で指定する引数です。16kトークンまで入力が可能なモデル（gpt-3.5-turbo-16k）や関数呼び出しに対応しているモデル（gpt-3.5-turbo-0613）など様々なモデルがあります。また、有料版であれば、GPT4を使うこともできます。本記事では最新のgpt-3.5-turbo-16k-0613モデルの使い方を説明します。
[詳細は公式ページへ](https://platform.openai.com/docs/models/continuous-model-upgrades)

### **messages：list[dict], 必須**

　ChatGPTのプロンプトを入力する引数で、ここが本記事のメインになります。具体的には、辞書を要素とするリストを入力します。辞書とは、キーとバリューをペアとして格納するデータ型です。以下にmessagesで用いる辞書のキーとバリューのペアを示します。ただし、関数呼び出しについては説明を省略しています。

| key(str) | value(str) | 備考 |
| --- | --- | --- |
| role | system | 対話のシステムや設定の指示 |
|  | user | ユーザの入力（プロンプト） |
|  | assistant | 質問に対する応答を入力することで、コンテクストを与えることができる |
| content | 各役割に対応する指示 | roleで指定した役割に対応する内容を入力 |

以下にmessagesの入力の例を示します。assistantを設定することで、コンテクストを与えることができます。

```python
messages=[
  {"role":"system",    "content":"You are a helpful assistant."},
  {"role":"user",      "content": "2002年4月2日は何曜日ですか"},
  {"role":"assistant", "content": "2002年4月2日は火曜日です。"},
  {"role":"user",      "content": "その日に起きた出来事を1つ教えてください"},
]
```

### temperature：number, デフォルト1

出力の多様性を制御することができます。0~2の値から選択し、0にすると、出力は一意に固定されます。

### n：int, デフォルト1

出力の数を指定します

### max_tokens：int, デフォルト1

生成に用いる最大のトークン数を指定します。

### その他

他にも、単語の出力頻度を制御する引数など様々な引数があります。
[詳細は公式ページへ](https://platform.openai.com/docs/api-reference/chat/create)

# ４．可読性の高い入力（プロンプト）
ChatGPTにおいてプロンプトは極めて重要です。しかし、本記事では良いプロンプトの作り方ではなく、プロンプトの可読性についての便利な方法を紹介します。

Pythonでは、string型をシングルクォーテーションで表記します。しかし、この表記で改行をするには「\n」を用いる必要があり、長いプロンプトや箇条書きなどを行う場合の可読性が著しく低下してしまいます。

```python
# 普通の文字列（可読性が低い）
str_exam1 = "以下の条件の下でおいしい食べ物を教えてください。\n条件1:和食\n条件2:甘い"

# 無理やり改行するとstring型ではなくなってしまう
str_exam2 = "以下の条件の下でおいしい食べ物を教えてください。\n
条件1:和食\n
条件2:甘い
"
```

その解決策として、三重クォーテーションを用いるというものがあります。

```python
# 三重クォーテーション
str_exam3 = """
以下の条件の下でおいしい食べ物を教えてください。
条件1:和食
条件2:甘い
"""
```

このようにすることで、可読性の高いプロンプトを作成することができます。また、このような表記でも、普通のstring型と同様にf-stringsを用いることが可能で、これを用いることでより読みやすく、変更しやすいプロンプトを作成することができます。

```python
# f-strings
add_str   = "おいしい食べ物"
str_short = f"以下の条件の下で{add_str}を教えてください。\n条件1:和食\n条件2:甘い"
str_long  = f"""
以下の条件の下で{add_str}を教えてください。
条件1:和食
条件2:甘い
"""
print(str_short)
print(str_long)
```

```
Out[2]:
以下の条件の下でおいしい食べ物を教えてください。
条件1:和食
条件2:甘い

Out[3]:
以下の条件の下でおいしい食べ物を教えてください。
条件1:和食
条件2:甘い
```

# ５．出力の見方
ChatCompletion.createメソッドにおける出力はJSON形式で与えられ、ChatGPTによる応答のみならず、プロンプトのトークン数や生成時に利用したトークン数など様々な情報が記載されています。以下が実際の出力の結果です。

```json
{
  "id": "chatcmpl-7jqaSJHuMTdBHyPSj8HuuhEqyoD4I",
  "object": "chat.completion",
  "created": 1691161260,
  "model": "gpt-3.5-turbo-16k-0613",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "2002\u5e744\u67082\u65e5\u306f\u706b\u66dc\u65e5\u3067\u3059\u3002"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 31,
    "completion_tokens": 14,
    "total_tokens": 45
  }
}
```
この出力の詳細は以下になります。
| key | value |
| --- | --- |
| id | APIリクエストに割り当てられるID |
| object | オブジェクトの種類 |
| created | レスポンス生成のUNIXタイムスタンプ |
| model | 使用したモデル |
| choices | index：生成したモデルのインデックス |
|  | message：応答の結果 |
|  | finish_reason：生成の終了の理由 |
| usage | prompt_tokens：プロンプトのトークン数 |
|  | completion_tokens：応答のトークン数 |
|  | total_tokens：総トークン数 |

最後にChatGPTの出力を取得する方法と総トークン数を取得する方法を以下に示します。

```python
# ChatGPTによる出力
gpt_output = response["choices"][0]["message"]["content"]

# 総トークン数
total_tokens = response["usatotal_tokens = response["usage"]["total_tokens"]
```

# ６．おわりに
PythonでChatGPTを使用すること自体は極めて容易であることが分かったと思います。今回はそのなかでも、Pythonに慣れていない方がつまずきがちなstring型や辞書型のデータ型の使い方についても少し詳しく解説しました。

# ７． 参考文献
* 【公式】APIキーの取得について
    https://platform.openai.com/account/api-keys
* 【公式】ChatGPTのモデルについて
    https://platform.openai.com/docs/models/continuous-model-upgrades
* ChatGPTのAPIをPythonから使う
    https://fuji-pocketbook.net/chatgpt-api-python/