LoginSignup
0
0

ChatGPT APIのトークン上限に合わせたテキストファイル分割

Posted at

はじめに

ChatGPT APIのトークン上限に合わせたテキストファイル分割に関しての備忘録です。
初心者です😅
間違えてる部分が多々あると思います。
もし見つけた場合、ツッコミいただけると助かります🙇

🦁結論🦁

翻訳などをする際にChatGPT APIはレスポンスのトークン数の上限は4096(2024年2月時点)のため翻訳などを行う際にテキストデータを送付して行う場合には、ChatGPTのレスポンストークンの上限の数値に合わせてテキストデータを分割した後、リクエストして回答を得るようにする必要がある。

押さえておくべき点

  • 英語と日本語ではトークン数は同じではない(日本語の方が多くなる)
  • 翻訳の内容によってもトークン数は左右される。
  • テキストデータ上限は「余裕を持ったトークン数」を設定すると良い。
  • ChatGPTのレスポンスがちゃんと返ってくるかを事前にChatGPTのチャットにて作成した命令文(リクエストにあるmessage)を送ってみて確認する

sample.py
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トークナイザーにてトークンをカウント

sample.py
    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の方が多い)


トークンの分割定義

sample.py
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を追加

sample.py
if block:
    blocks.append(block)

完成したblock(上限に達した)は「blocks」に格納される。
そのことから最後に余った部分が「block」入ってる。
もしそれがあった場合は「blocks」に格納。
要は最後の部分を追加する。


まとめ😺

トークン、エンコーディングはまだまだ奥が深い…
勉強あるのみ。


参考にしたサイト📗

OpenAIのAPIを利用する際のトークン数を見積もる


OpenAI GPTにおいて、モデルごとにトークン量が変動するのはなぜ?

0
0
0

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
  3. You can use dark theme
What you can do with signing up
0
0