PDFに質問しよう4 ~ 読み取ったテキストを適切に分割しよう | SkillhubAI(スキルハブエーアイ)

PDFに質問しよう4 ~ 読み取ったテキストを適切に分割しよう

ステップ3: 読み取ったテキストを適切に分割しよう

さて、PDFからテキストを抜き出すことができました。でも、100ページもあるPDFのテキストをそのままChatGPTに渡すわけにはいきません。なぜかというと:

  1. コストの問題: OpenAI APIは文字数(正確にはトークン数)で課金されます
  2. 精度の問題: 長すぎるテキストだと、関連する部分を見つけるのが難しくなります
  3. 制限の問題: APIには一度に送れる文字数の制限があります

そこで、長いテキストを適切な長さの「チャンク」に分割します。ちょうど、長い本を章ごとに分けて読むような感じですね。

tiktokenを使った正確な分割

ここで重要なのは、ただ文字数で切るんじゃなくて、「トークン数」で切ることです。トークンというのはAIが文章を理解する際の単位で、だいたい日本語だと1文字が1〜2トークン、英語だと1単語が1〜2トークンくらいです。

import tiktoken

def split_text_by_tokens(text, chunk_size=500, chunk_overlap=50):
    """
    テキストをトークン数ベースでチャンクに分割する関数

    chunk_size: 1チャンクの最大トークン数
    chunk_overlap: チャンク間の重複トークン数(文脈を保つため)
    """
    # GPT-4のトークナイザーを使用
    encoding = tiktoken.encoding_for_model("gpt-4")

    # テキストをトークンに変換
    tokens = encoding.encode(text)

    chunks = []
    start = 0

    while start < len(tokens):
        # チャンクの終了位置を計算
        end = min(start + chunk_size, len(tokens))

        # トークンのチャンクを取得
        chunk_tokens = tokens[start:end]

        # トークンをテキストに戻す
        chunk_text = encoding.decode(chunk_tokens)
        chunks.append(chunk_text)

        # 次の開始位置(オーバーラップを考慮)
        start = end - chunk_overlap if end < len(tokens) else end

    return chunks

chunk_sizeの選び方のコツを教えますね:

  • 250-500トークン: 一般的な質問応答に最適。今回はこれを使います
  • 500-1000トークン: 詳細な説明が必要な技術文書など
  • 100-250トークン: FAQ的な短い質問応答

チャンクが小さすぎると文脈が失われ、大きすぎると検索精度が落ちる。このバランスが大事なんです。