🍣

ChatGPTのプロンプトを英訳すると、どのくらいのコスト削減になるか? → トークン数は半分くらいになる?そしてコストは…

2023/08/16に公開

SREホールディングス株式会社エンジニアの木下です。
ChatGPTで日本語を処理する際のコスト削減に向けた工夫のひとつにプロンプトの英訳(英語訳/日本語を英語に翻訳)があります。本記事では、プロンプトを英訳すると、どの程度のコスト削減になりそうか、実例を用いて見てみたいと思います。

対象読者

コストを抑えたChatGPT利用を考えているかた

トークン数はtiktokenというライブラリで調べられる

トークン数はtiktokenというライブラリを用いて調べることができます。
https://github.com/openai/tiktoken

利用したいモデルで使われているエンコーダを調べて、そのエンコーダで想定文字列がエンコードされたときのトークン数を調べます。ここではGPT-4を想定して進めます。

>>> import tiktoken
>>> encoder = tiktoken.encoding_for_model('gpt-4')
>>> encoder
<Encoding 'cl100k_base'>

ただし、GPT-3.5も同じエンコーダのようです。

>>> tiktoken.encoding_for_model('gpt-3.5-turbo')
<Encoding 'cl100k_base'>

ここで、エンコーダにプロンプトで利用を想定する文字列を与えるとエンコード結果を得る事ができます。
ここでは「北海道で最も人口の多い都市はどこですか?」という質問を考えてみます。

>>> prompt = {}
>>> prompt['JA'] = '北海道で最も人口の多い都市はどこですか?'
>>> encoder.encode(prompt['JA'])
[49409,
 56235,
(中略)
 11571]

本記事ではエンコード結果そのものよりエンコード結果の長さに興味があるので、以後は長さを取っていきます。

>>> len(encoder.encode(prompt['JA']))
19

ちなみにこの文章の日本語の"文字数"は20になります。

>>> len(prompt['JA'])
20

英語にするとどうでしょうか。さきほどの日本語文を英語にしてみます。

>>> prompt['EN'] = 'What is the most populous city in Hokkaido?'

概算の単語数は8ですが、トークン数は12となりました。

>>> len(prompt['EN'].split())
8
>>> len(encoding.encode(prompt['EN']))
12

日本語のときの19と比べると半分強になっています。

※ なお、実際にOpenAIのAPIに投稿した際のプロンプトのトークン数は、tiktokenで測定した際の数字と比べて、わずかに増加するようですが、概算上はいったん無視できる範囲と想定し、以下ではtiktokenから得られる数字を元に考えてみます。(実際のトークン数はAPIのレスポンスの
'usage'>'prompt_tokens'で確認できます)

DeepLの力を借りて少し長めの文章で試してみる

もう少し長い日本語で試してみます。
ChatGPTに出してもらって質問の原案を一部修正し、127文字になりました。

>>> prompt = {}
>>> prompt['JA'] = "日本の地理的条件と気候が国の経済や文化にどのような影響を及ぼしているのか、北海道、本州、四国、九州などの主要な島と多様な地形、四季の変化、海洋性気候が交通、農業、観光産業、災害リスク、文化やライフスタイルにどのような関連があるのか、詳しく教えてください。"
>>> len(prompt['JA'])
127

英訳にはDeepL の力を借りてみます。
https://www.deepl.com/ja/translator-mobile

現在(2023年8月3日現在)のDeepLでは翻訳先言語を指定する際の"英語"に米国英語(EN-US - English (American))と英国英語(EN-GB - English (British))が見られますが、ここでは米国英語を選んでみます。

>>> import os
>>> import deepl
>>> translator = deepl.Translator(os.getenv('DEEPL_AUTH_KEY'))
>>> result = translator.translate_text(prompt['JA'], source_lang='JA', target_lang='EN-US')
>>> result.text
"Please elaborate on how Japan's geography (中略)and lifestyle."
>>> len(result.text.split())
44

トークン数を見てみると、英語版がおよそ半分になっています。(69/147=46.9%)

>>> for lang in prompt:
        print(f'{lang}: {len(encoding.encode(prompt[lang]))}')
JA: 147
EN-US: 69

日本語の質問文あと10個作成し試してみます。

>>> [f'{prompt[:15]}…' for prompt in prompts_medium['JA']]
['日本の最長川は信濃川で、この川…',
 '北海道の最大都市である札幌市は…',
 '日本の主要な火山活動地域には、…',
 '四国島は地理的にどのような特徴…',
 '九州地方の最南端に位置する都市…',
 '富士山は静岡県と山梨県にまたが…',
 '日本海と太平洋に挟まれた海は何…',
 '関東地方の最大都市である東京の…',
 '三重県にある伊勢神宮はどのよう…',
 '日本の最北端の地点はどこに位置…']

これらを同様に英語に翻訳します。

>>> import time
>>> from tqdm import tqdm
>>> target_lang = 'EN-US'
>>> prompts_medium[target_lang] = []
>>> for prompt in tqdm(prompts_medium['JA']):
    result = translator.translate_text(prompt, source_lang='JA', target_lang=target_lang)
    prompts_medium[target_lang].append(result.text)
    time.sleep(1)
>>> [f'{prompt[:25]}…' for prompt in prompts_medium['EN-US']]
['The longest river in Japa…',
 'As the largest city in Ho…',
 'There are several active …',
 'What are the geographical…',
 'What is the southernmost …',
 'Fuji straddles Shizuoka a…',
 'I would like to know what…',
 'Please explain the relati…',
 'Please tell us about the …',
 'Where is the northernmost…']

そしてトークン数を見てみると、英訳した場合がおおよそ半分程度という事が分かります。

>>> token_length = {}
>>> token_length['JA'] = []
>>> token_length[target_lang] = []
>>> for prompt, prompt_translated in zip(prompts_medium['JA'], prompts_medium[target_lang]):
    token_length['JA'].append(len(encoding.encode(prompt)))
    token_length[target_lang].append(len(encoding.encode(prompt_translated)))
>>> import pandas as pd
>>> df = pd.DataFrame({'JA': token_length['JA'], target_lang: token_length[target_lang]}, index=range(1, 11))
>>> df[f'{target_lang}/JA'] = df[f'{target_lang}']/df['JA']
>>> df
JA EN-US EN-US/JA
77 38 0.493506
65 27 0.415385
81 41 0.506173
53 22 0.415094
49 28 0.571429
60 29 0.483333
62 33 0.532258
51 26 0.509804
60 32 0.533333
68 33 0.485294

GPT-4の32K contextモデル利用時のコスト削減に期待

さて、ここまでの結果を活用して実際のコストへのインパクトにどのような事が言えそうか考えてみます。

翻訳を活用し、日本語の処理にChatGPTを利用する際のコストに関して、下記のようなコスト発生箇所が考えられます。

  1. 処理対象の日本語を(英語に)翻訳するコスト
  2. ChatGPTのプロンプトの量(トークン数)に応じたコスト
  3. ChatGPTの出力の量(トークン数)に応じたコスト
  4. (必要に応じて)ChatGPTの出力を日本語に翻訳するコスト

ここでは、翻訳しChatGPTへ入力を行うまでに関係するコスト、上記の1と2に範囲を限定して考えてみたいと思います。

そのために、まず、日本語での1文字あたりのトークン数を見てみます。
さきほども使った日本語の質問文を使ってみます。

>>> for prompt in prompts_medium['JA']:
>>>     print(f'{prompt[:15]}…')
日本の最長川は信濃川で、この川…
北海道の最大都市である札幌市は…
日本の主要な火山活動地域には、…
四国島は地理的にどのような特徴…
九州地方の最南端に位置する都市…
富士山は静岡県と山梨県にまたが…
日本海と太平洋に挟まれた海は何…
関東地方の最大都市である東京の…
三重県にある伊勢神宮はどのよう…
日本の最北端の地点はどこに位置…

これらをPythonのlenで取った数を文字数、tiktokenで取った数をトークン数として比較をしてみます。

>>> character_count = []
>>> token_count = []
>>> for prompt in prompts_medium['JA']:
>>>     character_count.append(len(prompt))
>>>     token_count.append(len(encoder.encode(prompt)))
>>> import pandas as pd
>>> df = pd.DataFrame({'character': character_count, 'token': token_count}, index=range(1, 11))
>>> df['token/character'] = df['token']/df['character']
>>> df
character token token/character
1 69 77 1.115942
2 55 65 1.181818
3 77 81 1.051948
4 46 53 1.152174
5 52 49 0.942308
6 54 60 1.111111
7 57 62 1.087719
8 51 51 1.000000
9 51 60 1.176471
10 62 68 1.096774
>>> df.mean()
character          57.400000
token              62.600000
token/character     1.091627
dtype: float64

限られた例からの結果にすぎませんが、いったん日本語の文字/トークンの比率としてこちらの数値を使ってみます。

DeepL APIは文字数単位で課金され、また料金は日本円で提示されています。2023年8月3日現在、料金は100万文字で2,500円です。(別途、基本料金が月額630円)
https://www.deepl.com/ja/pro/change-plan#developer

ここでは基本料金を無視して、単純に1文字あたり0.0025円(0.0025円/文字)と考えてみます。

ChatGPT(GPT-4)では8K contextモデルでは1000トークンあたり0.03ドル、32K contextモデルでは1000トークンあたり0.06ドルになっています(2023年8月3日現在)。
https://openai.com/pricing

これを、単純にそれぞれ1トークンあたり0.00003ドル、0.00006ドルと考えてみます。
そして、2023年8月3日の為替(ドル円)の終値 142.53円 を使って、それぞれ1トークンあたり0.0042759円、0.0085518円と考えてみます。

ドル/トークン 為替(ドル円) 円/トークン
GPT-4 8K context 0.00003 142.53 0.0042759
32K context 0.00006 142.53 0.0085518

日本語をそのままChatGPTを与えた場合を考えます。

日本語1文字あたり、翻訳コストが0円で、1文字が(文字・トークン比率)に応じてトークン化されてChatGPTに渡されると考え、文字・トークン比率に前述の数字を使い、かかってくるコストを
1.091627 * ChatGPT費用(円)
と考えてみます。(上記「ChatGPT費用」は円建てのトークンあたり費用: [円/トークン])

次に、日本語を英語に翻訳した場合を考えます。

日本語1文字あたり0.0025円の翻訳コストに、日本語の(文字・トークン比率)の半分のトークンをChatGPTに渡すと考えてみます。

>>> 1.091627/2
0.5458135

これを用いてコストを
0.0025 + 0.5458135 * ChatGPT費用(円)
と考えてみます。(同じく「ChatGPT費用」は円建てのトークンあたり費用)

日本語を英語に翻訳した方がコストが抑えられる場合を、
1.091627 * ChatGPT費用 > 0.0025 + 0.5458135 * ChatGPT費用
つまり
0.5458135 * ChatGPT費用 > 0.0025
の場合と考えてみます。

ChatGPT費用にさきほど算出した値を入れると下記のとおりとなります。

ドル/トークン 為替(ドル円) 円/トークン 0.5458…*ChatGPT費用
GPT-4 8K context 0.00003 142.53 0.0042759 0.00233384
32K context 0.00006 142.53 0.0085518 0.00466769

(0.5458…=0.5458135, ChatGPT費用=「円/トークン」列)

32K contextモデルで基準となる0.0025を超えていることがわかります。

この単純な概算では8K contextモデルでのコスト削減効果は微妙なものとなりますが、32K contextモデルではコスト削減が期待できる結果になっています。

また、実際のユースケースではプロンプトの一部を流用することで、毎回プロンプト全体を翻訳する必要がないケースなど様々なケースが考えられますので、8K contextモデルでも英語への翻訳を用いたコスト削減の可能性は残されていそうです。

この単純なコスト概算では以下のような要素を考えました。

  • 日本語と日本語を翻訳した英語のトークンの量の比率
  • 日本語の文字・トークンの比率
  • 翻訳ツールの料金体系
  • ChatGPTの料金体系
  • 為替(翻訳ツールの料金の表示通貨とChatGPTの料金の表示通貨が違う場合)

料金体系など今後の改定も見込めますので、英訳を用いたChatGPT活用に有利な状況にあるか、定期的に確認していく必要がありそうです。

また、日本語以外の言語の処理を考え、翻訳を活用することによるコスト的なメリットの大きい言語を探してみるのも面白そうです。

付録: 日本語を英語以外の言語に翻訳した場合のトークン数

日本語を英語以外の言語に翻訳した場合のトークン数を調べてみました。

>>> prompt['JA']
'日本の地理的条件と気候が国の経済や文化にどのような影響を及ぼしているのか、北海道、本州、四国、九州などの主要な島と多様な地形、四季の変化、海洋性気候が交通、農業、観光産業、災害リスク、文化やライフスタイルにどのような関連があるのか、詳しく教えてください。'
>>> token_count = {}
for code in tqdm(codes):
    result = translator.translate_text(prompt['JA'], source_lang='JA', target_lang=code)
    token_count[code] = len(encoding.encode(result.text))
    time.sleep(1)
>>> token_count['JA'] = len(encoding.encode(prompt['JA']))
>>> df = pd.DataFrame({'token_count': token_count.values()}, index=token_count.keys())
>>> df.loc['EN-US']['token_count']
69.0
>>> df['EN-US'] = df.loc['EN-US']['token_count']
>>> df['ratio'] = df['token_count'] / df['EN-US']
>>> df
token_count EN-US ratio
BG 176 69 2.550725
CS 157 69 2.275362
DA 101 69 1.463768
DE 110 69 1.594203
EL 332 69 4.811594
EN-GB 66 69 0.956522
EN-US 69 69 1.000000
ES 105 69 1.521739
ET 122 69 1.768116
FI 133 69 1.927536
FR 108 69 1.565217
HU 161 69 2.333333
ID 107 69 1.550725
IT 120 69 1.739130
KO 167 69 2.420290
LT 148 69 2.144928
LV 141 69 2.043478
NB 97 69 1.405797
NL 104 69 1.507246
PL 119 69 1.724638
PT-BR 97 69 1.405797
PT-PT 110 69 1.594203
RO 119 69 1.724638
RU 179 69 2.594203
SK 154 69 2.231884
SL 129 69 1.869565
SV 99 69 1.434783
TR 125 69 1.811594
UK 206 69 2.985507
ZH 105 69 1.521739
JA 147 69 2.130435

翻訳先言語としては英語が無難そうです。

付録: 「日本語で答えてください」

ChatGPTに"日本語で答えてください"と問うと日本語で答えてくれます。

"What is the most populous city in Hokkaido?"
"As of my last update in September 2021, the most (以下略)"
"What is the most populous city in Hokkaido? Please answer in Japanese."
"北海道で最も人口の(以下略)"

まとめ

プロンプトを英訳することで、トークン数をおよそ半分に出来そうな事が分かりました。
翻訳の品質、翻訳コストという考慮すべき事柄もありますが、コストを抑えてのChatGPT活用について、英訳は積極的に検討したい工夫と考えることができそうです。
利用予定の範囲で、翻訳品質に比較的課題が出にくい一部の領域にのみ活用するなどの利用方法も良さそうです。

SRE Holdings 株式会社

Discussion