ブログに戻る

AI入門ガイド

AIの回答が文の途中で止まるのはなぜ?max_tokens、コンテキストウィンドウ、finish_reasonを解説

文の途中で止まるAIの回答は上限に達しています。finish_reasonを読み、max_tokensとコンテキストウィンドウの満杯を区別し、各モデルの出力上限を確認しましょう。

投稿者: CheapTokens Team公開日 更新日 読了時間 8 分

cheaptokensロゴ入りのダークなカバー:max_tokens、finish_reason、lengthの文字がボックスに入り、「Answer cut off mid-sentence?」という見出し
このページの内容
  1. 回答を打ち切る3つの上限
  2. まずfinish_reasonを読む
  3. 修正1: max_tokensを上げる
  4. 修正2: コンテキストウィンドウが満杯のとき
  5. 修正3: 長い回答を分割して得る
  6. finish_reasonがstopのとき
  7. 回答の長さでモデルを選ぶ

文の途中で止まる応答は、ほぼ必ず何らかの上限によって打ち切られています。モデルが思考の流れを失ったのではなく、リクエストに余地がなくなったのです。応答にはどの上限だったかが示されます。finish_reasonを読んでください。lengthは上限に達したことを意味します。stopはモデルが自力で終了したことを意味します。

回答の長さを決める要素は3つあります。どれに引っかかったかがわかれば、修正は1分で済みます。

回答を打ち切る3つの上限#

  • max_tokens はリクエストで設定する上限です。回答がそこに達すると、単語の途中でも生成が停止します。DeepSeekのAPIリファレンスでは、completionで生成されるトークンの最大数と定義されています。
  • モデルの出力上限 は、そのモデルが1回の回答で出せる上限です。モデルに属する値なので、max_tokensはそれ以下に保ってください。弊社モデルの数値は下の表にあります。
  • コンテキストウィンドウ は、やり取り全体のための余地です。入力と回答を合わせたものです。DeepSeekのリファレンスによれば、入力トークンと生成トークンの合計はモデルのコンテキスト長で上限が決まります。

トークンがまだ漠然とした概念であれば、まずWhat is a token in AI?をお読みください。このページはトークンとは何かを理解している前提です。

まずfinish_reasonを読む#

チャット応答の各choiceにはfinish_reasonが付きます。その隣のusageは、入力と出力に何トークン使われたかを示します。

打ち切られた回答と完了した回答の例を並べます。リクエストは「In one short sentence, what is a token?」で、まずmax_tokensを16に設定し、次に200に設定しました。

説明用の例であり、記録された応答ではありません。カウントや追加フィールドは異なります。

json
{
  "choices": [
    {
      "message": { "role": "assistant", "content": "A token is a small piece of text that a model reads and writes, usu" },
      "finish_reason": "length"
    }
  ],
  "usage": { "prompt_tokens": 21, "completion_tokens": 16, "total_tokens": 37 }
}
json
{
  "choices": [
    {
      "message": { "role": "assistant", "content": "A token is a small piece of text that a model reads and writes, usually a word or part of a word." },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 21, "completion_tokens": 24, "total_tokens": 45 }
}

最初の応答ではcompletion_tokensが16で、まさに上限ぴったりであり、テキストは「usu」で終わっています。2番目ではモデルは24トークンで停止しており、上限200を大きく下回っています。完了したからです。

何が起きたかを判断するには、次の順に確認します。

  1. finish_reasonを見る。 stopなら回答は完了しています。モデルが終了を選んだか、設定した停止シーケンスに達したのです。lengthなら上限が回答を打ち切っており、次のステップでどれかを特定します。content_filterやtool_callsなど他の値もあり、どちらも長さの問題ではありません。
  2. completion_tokensを送信したmax_tokensと比較する。 等しいかほぼ等しければ、max_tokensに達しています。
  3. completion_tokensがmax_tokensを大きく下回り、かつprompt_tokensが大きい場合、 コンテキストウィンドウが埋まった可能性が高いです。DeepSeekのリファレンスは両方のケースでlengthを使うため、このフィールドだけでは区別できません。ステップ2の比較で見分けます。AnthropicとZ.aiのドキュメントは2番目のケースをmodel_context_window_exceededとして別に名付けています。自分の応答でこのフィールドを見て、どちらの名前が返るか確認してください。

3つの説明はすべて開発者のドキュメントに基づき、2026年10月20日に確認したものです: DeepSeek、Anthropic、Z.ai。

見えるもの finish_reason 原因 対処
打ち切り、completion_tokensがmax_tokensと等しい length max_tokensに達した max_tokensを上げる、または回答を分割して求める
打ち切り、completion_tokensがmax_tokensを大きく下回る、入力が長い length(一部のAPIではmodel_context_window_exceeded) コンテキストウィンドウが満杯 入力や履歴を短くする、またはより大きなウィンドウのモデルを選ぶ
完了したが希望より短い stop モデルが終了した、または停止シーケンスが発動した より詳しく求める。stopパラメータを確認する
テキストがない、または拒否 content_filter 応答がフィルタリングされた リクエストを言い換える
テキストがなく、代わりにツールリクエスト tool_calls モデルがツールを呼び出したい ツールを実行して結果を返す

修正1: max_tokensを上げる#

最もよくある原因は、最も簡単に直せます。max_tokensを自分で設定し、どの上限が適用されるかを把握してください。デフォルトに頼らないでください。

python
from openai import OpenAI

client = OpenAI(base_url="https://api.cheaptokens.dev/v1", api_key="YOUR_API_KEY")

resp = client.chat.completions.create(
    model="deepseek-ai/DeepSeek-V4-Flash-0731",
    messages=[{"role": "user", "content": "Write a detailed guide to setting up a home network."}],
    max_tokens=16000,  # example value: stay at or below the model's output limit
)

choice = resp.choices[0]
print(choice.finish_reason, resp.usage.completion_tokens)

これは呼び出しの形を示しています。ここではキーをYOUR_API_KEYとして入れています。実際のキーは共有するコードに入れないでください。

数値を上げても、モデル自身の上限までしか効果はありません。以下はCheapTokensの上限で、2026年10月20日にCheapTokensのモデル一覧で確認したものです:

モデル モデルID 回答あたりの最大出力 コンテキスト
DeepSeek-V4-Flash (0731) deepseek-ai/DeepSeek-V4-Flash-0731 32,768トークン 380K
GLM-5.3-Flash zai-org/GLM-5.3-Flash 8,192トークン 390K
MiniMax-M2.7 MiniMaxAI/MiniMax-M2.7 8,192トークン 200K

開発者は自社API向けに独自の上限を公開しています。例えばZ.aiはGLM-5シリーズで最大128K出力と記載しています。それはCheapTokens上のGLM-5.3-Flashの上限ではなく、こちらは回答あたり8,192トークンです。CheapTokens上で何かを作る場合は、上の表を使ってください。

修正2: コンテキストウィンドウが満杯のとき#

チャットでは、メッセージごとに履歴全体が再送されるため、ターンごとに入力が増えます。コンテキストウィンドウはその履歴と新しい回答を保持しなければなりません。履歴だけでほぼ埋まってしまえば、返答の余地はほとんど残りません。

これらのウィンドウは大きく、短い質問1つでは埋まりません。長いチャットや貼り付けたドキュメントなら埋まります。有効な対策:

  • 古いチャットを続けるのではなく、新しいタスクには新しいチャットを始める。
  • モデルにここまでの会話を要約させ、要約だけを引き継ぐ。
  • 不要になった古いメッセージや添付を削除する。
  • 入力自体が巨大なら、最も大きなウィンドウのモデルを選ぶ。弊社の中ではGLM-5.3-Flashの390Kです。出力上限は8,192トークンなので、長い結果は分割して求めてください。

修正3: 長い回答を分割して得る#

欲しい回答がモデルの出力上限より長い場合、どの設定でも1回の返答には収まりません。分割して求めてください。finish_reasonがlengthのとき、部分的な回答を送り返し、モデルに続きを求めます。

python
messages = [{"role": "user", "content": "Write a detailed guide to setting up a home network."}]
parts = []

for _ in range(4):  # example limit: at most 4 rounds
    resp = client.chat.completions.create(
        model="zai-org/GLM-5.3-Flash",
        messages=messages,
        max_tokens=8000,  # example value: below this model's output limit
    )
    choice = resp.choices[0]
    parts.append(choice.message.content)
    if choice.finish_reason != "length":
        break
    messages.append({"role": "assistant", "content": choice.message.content})
    messages.append({"role": "user", "content": "Continue exactly where you stopped. Don't repeat anything."})

text = "".join(parts)

同じ注意: パターンの例であり、記録された実行ではありません。各部分のつなぎ目を読んでください。モデルは継ぎ目で文を繰り返したり、リストをやり直したりすることがあります。

各ラウンドではここまでのすべてが入力として再送され、出力トークンはすべて課金されます。長い回答は短いものよりコストがかかります。以下は入力2,000トークンに対する8,000トークンの回答で、表のすべてのモデルに収まります:

モデル コスト OpenRouter
GLM-5.3-Flash $0.00036 $0.00069
DeepSeek-V4-Flash $0.00083 $0.0013
MiniMax-M2.7 $0.0013 $0.0102

合計 2,000 入力トークンと 8,000 出力トークン。100万トークンあたりの価格は現行のもので、当社の料金体系に合わせて変動します。OpenRouter 列は同じワークロードの参考価格を示しています。

finish_reasonがstopのとき#

stopはモデルが回答を終えたことを意味します。希望より早く終わったとしても、それは上限の問題ではなく、max_tokensを大きくしても変わりません。欲しいものを伝えてください。長さ、セクション、詳細度などです。また、リクエストがstopパラメータを設定していないか確認してください。回答に現れる停止シーケンスは、その場で回答を終わらせます。

回答の長さでモデルを選ぶ#

必要な回答から始めます。8,192トークンに収まるなら、CheapTokensではMiniMax-M2.7(MiniMaxAI/MiniMax-M2.7)が対応します。その出力はOpenRouterの参考価格より安く、$0.15(出力100万トークンあたり)で課金されます。価格は時間帯にかかわらず同じで、ピーク時間はなく、APIはOpenAIおよびAnthropicと互換です。

以下は全モデルの現在の価格表です:

モデル コンテキスト 入力 $/1M 出力 $/1M OpenRouter 入力 OpenRouter 出力
GLM-5.3-Flash reasoning 390K $0.02 $0.04 $0.0413 $0.0758
DeepSeek-V4-Flash 380K $0.015 $0.10 $0.0475 $0.1568
MiniMax-M2.7 180K $0.05 $0.15 $0.30 $1.20

価格は100万トークンあたりのUSD表記です。OpenRouterの数値は比較用であり、変更される可能性があります。

まだリクエストを送っていないなら、Your first API request with CheapTokensが手順を説明します。トークンとは何か、なぜ入力と出力が別々に数えられるかについては、What is a token in AI?をご覧ください。

全モデルのエンドポイント、モデルID、上限はCheapTokens docsにあります。