生成AI入門 2026.06.24

APIトークン上限エラーの完全解決ガイド【Claude・ChatGPT 2026年版】長文入力の3つの分割戦略

タグ:Claude API / ChatGPT API / エラー対処 / 長文入力 / コンテキストウィンドウ

コンテキストウィンドウの比較(2026年版)

モデルコンテキスト約何文字(日本語)
GPT-4o mini128K約9万字
GPT-5128K約9万字
Claude Haiku/Sonnet/Opus200K約15万字

長文処理が多い場合はClaude(200K)への移行が根本解決になる場合が多いです。

Step 1: まずトークン数を計測する

# count_tokens.py
# 送信前にトークン数を確認する

import anthropic
import os

client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

def count_claude_tokens(text: str, model: str = "claude-sonnet-4-5") -> int:
    """Claudeでトークン数を無料でカウントする(APIコストなし)"""
    response = client.messages.count_tokens(
        model=model,
        messages=[{"role": "user", "content": text}]
    )
    return response.input_tokens

# 使用例
long_text = "..." * 10000  # 長いテキスト

token_count = count_claude_tokens(long_text)
CLAUDE_MAX = 200_000

print(f"トークン数: {token_count:,}")
print(f"Claudeの上限: {CLAUDE_MAX:,}")
if token_count > CLAUDE_MAX:
    print("⚠️ 上限超過 → チャンク分割が必要")
elif token_count > CLAUDE_MAX * 0.8:
    print("⚠️ 上限に近い → 余裕を持たせた分割を推奨")
else:
    print("✅ 上限内 → そのまま送信可能")

Step 2: チャンク分割で長文を処理する

# chunk_processor.py
# 長い文書を分割してClaudeで処理する

import anthropic
import os

client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

def process_long_document(document: str, task: str, chunk_chars: int = 60000) -> str:
    """長い文書をチャンクに分割して処理し結果を統合する"""
    
    # 文書を分割(日本語は約3文字/トークン)
    chunks = []
    for i in range(0, len(document), chunk_chars):
        chunks.append(document[i:i + chunk_chars])
    
    print(f"文書: {len(document):,}文字 → {len(chunks)}チャンクに分割")
    
    # 各チャンクを処理
    results = []
    for i, chunk in enumerate(chunks):
        response = client.messages.create(
            model="claude-haiku-4-5-20251001",   # 大量処理はHaikuでコスト削減
            max_tokens=1024,
            messages=[{"role": "user", "content": f"""
{task}

※ これは文書の{i + 1}番目の部分(全{len(chunks)}部分)です。

文書内容:
{chunk}
"""}]
        )
        results.append(response.content[0].text)
        print(f"  チャンク {i + 1}/{len(chunks)} 処理完了")
    
    # 結果を統合
    if len(results) == 1:
        return results[0]
    
    combined = "\n\n---\n\n".join(f"[Part {i+1}]\n{r}" for i, r in enumerate(results))
    
    final = client.messages.create(
        model="claude-sonnet-4-5",              # 統合はSonnetで品質向上
        max_tokens=2048,
        messages=[{"role": "user", "content": f"""
以下の{len(results)}つのパートの結果を統合して、一つの一貫した回答にまとめてください。

{combined}
"""}]
    )
    return final.content[0].text

# 使用例
with open("long_contract.txt") as f:
    contract = f.read()

summary = process_long_document(contract, "この契約書の重要なリスク事項を箇条書きで挙げてください")
print(summary)

Step 3: 途中で切れたレスポンスを続けさせる

# continue_response.py
# max_tokensに達して途中で切れた回答を続けさせる

def ask_with_continuation(prompt: str, max_continuation_attempts: int = 3) -> str:
    """必要に応じて回答を続けさせる"""
    
    full_response = ""
    messages = [{"role": "user", "content": prompt}]
    
    for attempt in range(max_continuation_attempts):
        response = client.messages.create(
            model="claude-sonnet-4-5",
            max_tokens=2048,
            messages=messages
        )
        
        chunk = response.content[0].text
        full_response += chunk
        
        # 終了理由が「stop_sequence」または「end_turn」なら完了
        if response.stop_reason in ("end_turn", "stop_sequence"):
            break
        
        # 「max_tokens」で止まった場合は続きを要求
        if response.stop_reason == "max_tokens":
            messages.append({"role": "assistant", "content": chunk})
            messages.append({"role": "user", "content": "続きをお願いします。前の文の続きから再開してください。"})
        else:
            break
    
    return full_response

result = ask_with_continuation("Pythonの設計パターンを10個詳しく説明してください")
print(result)

あわせて読みたい

参考ソース