【優しいキャラは高くつく】ChatGPT APIの課金体系と節約方法

# はじめに
ChatGPTのAPIを使い始めました。有料のAPIですので、どう課金されていくのか、節約して使うにはどうすれば良いのか知りたいと思い、調査・まとめをしました。

# 課金体系
まずサブスクリプションではなく、従量課金です。使った分だけ請求されます。後述しますが高額な利用料ではないものの、青天井ではあるので、何かの拍子に無限ループでAPIを実行しまくってしまったりすると悲劇が起こります。対策も含めて書いていきます。

初回登録時に無料クレジット18ドル（3ヶ月有効）がもらえるようです。

:::note warn
ちなみに私は無料クレジットをもらうことができず、いきなりの課金となりました。同じアカウントでChatGPT PlusにUpgradeしていたことが関係あるのかと一瞬思いましたが別途クレジットカードの登録はAPI用に必要だったので現時点では詳細は分かりません（なぜそうなったのかは問い合わせ中です。回答が来たら記事を更新します）。
:::

## 基本の課金体系
Pricingのページを見ていきましょう。

https://openai.com/pricing

`gpt-3.5-turbo`というモデルを使うことになりますが、`$0.002 / 1K tokens`と記載があります。
1000トークンにつき、0.27円（2023年4月10日時点）かかるということですね。

### トークン
入力したり出力される単語が増えるほど課金されるんだろうなと思いますが、トークンとは何なのか、厳密にはわかりませんので説明を探してみました。


https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them

>Tokens can be thought of as pieces of words. 
>[訳]トークンは単語の断片と考えることができます

>Here are some helpful rules of thumb for understanding tokens in terms of lengths:
>[訳]トークンの長さを理解するのに役立つ、おおまかな目安です。
>1 token ~= 4 chars in English
1 token ~= ¾ words
100 tokens ~= 75 words
Or 
1-2 sentence ~= 30 tokens
1 paragraph ~= 100 tokens
1,500 words ~= 2048 tokens

1単語1トークンというわけでもなく、厳密な説明はありませんでした。英語であれば大体750単語で0.27円になるということですね。

:::note
Tokenizerというトークン数がわかるツールもありました。
https://platform.openai.com/tokenizer
:::


APIを実行すると、トークン数もレスポンスに含まれるので自分でもどんなもんか試してみます。
試しに単に`Hello`とだけ聞いてみます。
```sh
curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <Your Token>" \
  -d '{
    "model": "gpt-3.5-turbo",
    "messages": [
      {
        "role": "user",
        "content": "Hello"
      }
    ]
  }'
```
**レスポンス**
```json
{
	"id": "chatcmpl-73fk3U9kDX1PPJuyjxnkmKkeo0BIG",
	"object": "chat.completion",
	"created": 1681109795,
	"model": "gpt-3.5-turbo-0301",
	"usage": {
		"prompt_tokens": 9,
		"completion_tokens": 9,
		"total_tokens": 18
	},
	"choices": [
		{
			"message": {
				"role": "assistant",
				"content": "Hello! How can I assist you today?"
			},
			"finish_reason": "stop",
			"index": 0
		}
	]
}
```

`Hello! How can I assist you today?`と返事がありました。
`usage`を確認します。
```json
"usage": {
    "prompt_tokens": 9,
    "completion_tokens": 9,
    "total_tokens": 18
},
```

`prompt_tokens`が入力のトークン、`completion_tokens`が出力のトークンですがそれぞれ9となりました。
`Hello`が9で、`Hello! How can I assist you today?`も9というのが納得行きませんが結果は結果なのでそのまま参考情報として載せておきます。

今度は日本語で`こんにちは`と聞いてみます。
```json
{
	"id": "chatcmpl-73fmN3yyCpDxh7z2u1GO1wZ60DEt0",
	"object": "chat.completion",
	"created": 1681109939,
	"model": "gpt-3.5-turbo-0301",
	"usage": {
		"prompt_tokens": 9,
		"completion_tokens": 41,
		"total_tokens": 50
	},
	"choices": [
		{
			"message": {
				"role": "assistant",
				"content": "こんにちは！私はAIのアシスタントです。何かお力になれることがあれば遠慮なくお尋ねください。"
			},
			"finish_reason": "stop",
			"index": 0
		}
	]
}
```

`こんにちは！私はAIのアシスタントです。何かお力になれることがあれば遠慮なくお尋ねください。`と回答がありました。
```json
"usage": {
    "prompt_tokens": 9,
    "completion_tokens": 41,
    "total_tokens": 50
}
```
`completion_tokens`の方が文字数以上に増えている感じがします。
以上、目安の情報になれば幸いです。


まとめると料金としては、
`単価($0.002)` * `total_tokens`ということですね。


# 節約方法

まずは節約云々の前に制限をかけましょう。
## 使用制限の設定

`Usage Limites`から設定していきます。

![Screenshot 2023-04-10 at 16.07.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556201/50ff2343-123e-64e4-2d41-6a26a78c8794.png)

:::note
無料のクレジットがある方は画像の"Pay as you go"の部分が"Free trial"になっているはずです。
:::

こちらの画面で`Soft Limit（この金額に達するとメールが来る）`と`Hard Limit（この金額に達するとリクエストできなくなる）`を設定して青天井を回避しましょう。
![Screenshot 2023-04-10 at 16.08.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556201/474a6ae7-b36c-3140-7de0-12934a205341.png)

### リクエスト時の制限
[max_tokens](https://platform.openai.com/docs/api-reference/chat/create#chat/create-max_tokens)というパラメータをリクエストボディに含めることができるので必要に応じてこれを設定しましょう。

## 節約方法を考えてみる

### 1. 文字数を減らす
自分の質問の文字数を減らすということと、ChatGPTの返答内容が短くなるように工夫する、ということを指しています。
例えば`パソコンでできることは何でしょうか`と`パソコンでできること`、このどちらで入力しても返答内容は同じような内容になりますが入力時のトークンを減らせます。

ChatGPTからの返答も工夫次第で短くできます。
末尾に`〇〇文字以下で答えて`、`〇個の箇条書きで答えて`などと付けると返答の文字数が減らせます。

:::note
余談ですが、「すごく優しくて丁寧で気配りがすごい人」みたいなロール設定にしたら、丁寧すぎて言葉数が多く、トークン消費が激増しました。雑なキャラにした方がお財布に優しいです。優しさはコストです。

「それは大変でしたね。お体に気をつけてお過ごしください。何かあればお気兼ねなくご相談ください。」→ 66 tokens
「ウィ」→ 2 tokens

by [Tokenizer](https://platform.openai.com/tokenizer)
:::

### 2. 英語にする
日本語は消費が激しいので、英語に翻訳してリクエストした方がトークン数は減らせます。
質問は日本語でするしかない、という場合でもロール設定などを英語で済ますだけでも全て日本語よりマシです。
ちょっとした文章なら翻訳してる方が手間かもしれませんが基本として知っておきたい事項です。

### 3. リクエストに含める会話履歴に制限をつける
ブラウザ版とAPI版の大きな違いといえば文脈を理解しているかどうか、かと思います。ブラウザ版と違いAPI版は過去の会話履歴をユーザー側で保持・管理する必要があります（コンテキストのIDなどがあるわけではないです）。過去の会話に基づいた回答をChatGPTに期待する時はリクエストする時に、質問+過去の会話をボディに含めてリクエストする必要があります。

つまり、過去の会話を含めるほど1回のリクエストでのトークン数がどんどん増えていってしまうことになります。
自分で管理するデータの話なので好きなようにすれば良い話ですが過去2、3回のやり取りだけ含めるなど、制限をつけた実装にした方が安全だと思います。


# まとめ
いかに少ない言葉でこちらの期待通りの結果を短く出させるか、の勝負になります。これは特にリモートワーク時に言えることですが、対人でも有効な話ですので、節約とコミュ力向上の両方を狙えるなと思いました。

日本語が上手だけど第一言語が英語のリモートで働いている部下だと思い込んでプロンプトを考えていこうと思います。

# おまけ

ChatGPTのデータの取り扱いについての記事も書いてみました。ご興味がある方はどうぞ。

https://qiita.com/ysv/items/cb39ae4d96c1c8a73f59