はじめに
ChatGPT APIのトークン上限に合わせたテキストファイル分割に関しての備忘録です。
初心者です😅
間違えてる部分が多々あると思います。
もし見つけた場合、ツッコミいただけると助かります🙇
🦁結論🦁
翻訳などをする際にChatGPT APIはレスポンスのトークン数の上限は4096(2024年2月時点)のため翻訳などを行う際にテキストデータを送付して行う場合には、ChatGPTのレスポンストークンの上限の数値に合わせてテキストデータを分割した後、リクエストして回答を得るようにする必要がある。
押さえておくべき点
- 英語と日本語ではトークン数は同じではない(日本語の方が多くなる)
- 翻訳の内容によってもトークン数は左右される。
- テキストデータ上限は「余裕を持ったトークン数」を設定すると良い。
- ChatGPTのレスポンスがちゃんと返ってくるかを事前にChatGPTのチャットにて作成した命令文(リクエストにあるmessage)を送ってみて確認する
from transformers import GPT2Tokenizer
def chatgpt_text_split_save():
file_path = "分割したいファイルパス"
block_size = 3000 # トークン上限を設定
separat_part = '\n' # 文章の区切りになる部分
output_dir = "分割したテキストデータを入れるディレクトリ"
# GPT2トークナイザー
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
with open(file_path, 'r', encoding='utf-8') as f:
text = f.read()
# テキストをトークン化し、トークン数をカウント
all_tokens = tokenizer.encode(text, add_special_tokens=True)
count = len(all_tokens)
# 全テキストのトークン数
print(f"Token count: {count}")
# 一つ一つを区切ってるパーツによって分解
lines = text.split(separat_part)
# 各ボックスの初期化
blocks = []
block = ''
token_count = 0
for line in lines:
# lineにあるトークンをカウント
t = len(tokenizer.encode(line))
# トークンカウントが0以上(初期ではない)かつblock_sizeを超えてしまったら新しくリストに追加する
if token_count > 0 and block_size < (token_count + t):
blocks.append(block)
token_count = 0
block = ''
# トークンカウントを追加
token_count += t
# ブロックに区切れた部分を追加する(区切られたもの自体も追加)
block += line + separat_part
# 最後のblock_sizeに達してないものも追加(ここまでのものは全てblocksに追加されてるためない)
if block:
blocks.append(block)
if not os.path.exists(output_dir):
os.makedirs(output_dir)
for i, block in enumerate(blocks):
output_text = os.path.join(output_dir, f'text_block_{i+1}.txt')
with open(output_text, 'w', encoding='utf-8') as output_file:
output_file.write(block)
print(f"{output_text} 保存完了")
GPT-2トークナイザーにてトークンをカウント
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
with open(file_path, 'r', encoding='utf-8') as f:
text = f.read()
# テキストをトークン化し、トークン数をカウント
all_tokens = tokenizer.encode(text, add_special_tokens=True)
count = len(all_tokens)
# 全テキストのトークン数
print(f"Token count: {count}")
トークナイザーとはトークンをカウントしてくれる。
トークナイザーは様々あり、ChatGPTによるトークン数を測るなら、GPT-2トークナイザーが正確性が高いみたい。(tiktokenと比較した際に200ぐらいの誤差がありました→GPT-2の方が多い)
トークンの分割定義
if token_count > 0 and block_size < (token_count + t):
blocks.append(block)
token_count = 0
block = ''
if token_count > 0 and block_size < (token_count + t):
block_sizeを超えた場合にblocksに格納して「token_count」と「block」を初期化してlineのtoken_count(t)とblockにblock_size = 3000に達するまで格納。
(separat_partによって区切られた文章が格納される)
※3000トークンのバーを超えたら次の箱が用意されるイメージ。
余ったblockを追加
if block:
blocks.append(block)
完成したblock(上限に達した)は「blocks」に格納される。
そのことから最後に余った部分が「block」入ってる。
もしそれがあった場合は「blocks」に格納。
要は最後の部分を追加する。
まとめ😺
トークン、エンコーディングはまだまだ奥が深い…
勉強あるのみ。