AI for beginnersGuide
Why does an AI answer stop mid-sentence? max_tokens, the context window and finish_reason explained
An AI answer that stops mid-sentence hit a limit. Read finish_reason, tell max_tokens from a full context window and check each model’s output limit.

On this page
A reply that stops in the middle of a sentence was almost always cut off by a limit. The model didn't lose its train of thought; the request ran out of room. The response says which limit it was: read finish_reason. length means a limit was hit. stop means the model finished on its own.
Three things decide how long an answer can be. Once you know which one bit you, the fix takes a minute.
Three limits that cut an answer#
max_tokensis a cap you set in the request. When the answer reaches it, generation stops, even mid-word. DeepSeek's API reference defines it as the maximum number of tokens generated in the completion.- The model's output limit is the ceiling for a single answer from that model. It belongs to the model, so keep
max_tokensat or below it. The numbers for our models are in the table below. - The context window is the room for the whole exchange: your input and the answer together. DeepSeek's reference says the input and generated tokens together are capped by the model's context length.
If tokens are still a fuzzy idea, start with What is a token in AI?. This page assumes you know what one is.
Read finish_reason first#
Every choice in a chat response carries a finish_reason. Next to it, usage tells you how many tokens went in and out.
Here is what a cut-off answer looks like next to a finished one. The request asked "In one short sentence, what is a token?", first with max_tokens set to 16, then with 200.
Illustrative example, not a recorded response: your counts and extra fields will differ.
{
"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 }
}{
"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 }
}In the first response completion_ is 16, exactly the cap, and the text ends in "usu". In the second the model stopped at 24 tokens, well under the cap of 200, because it was done.
To work out what happened, go through this in order:
- Look at
finish_reason. If it'sstop, the answer is complete. The model chose to end, or hit a stop sequence you set. If it'slength, a limit cut the answer off, and the next step tells you which one. Other values exist, such ascontent_filterandtool_calls; neither is a length problem. - Compare
completion_with thetokens max_tokensyou sent. If they're equal or nearly so, you hitmax_tokens. - If
completion_is well belowtokens max_tokensandprompt_tokensis large, the context window probably filled up. DeepSeek's reference useslengthfor both cases, so the field alone can't separate them; the comparison in step 2 is how you tell. Anthropic's and Z.ai's documentation name the second case separately, asmodel_. Look at the field in your own responses to see which name you get.context_ window_ exceeded
All three descriptions come from the developers' documentation, checked on 20 October 2026: DeepSeek, Anthropic and Z.ai.
Scroll the table right →
| What you see | finish_reason |
Cause | What to do |
|---|---|---|---|
Cut off, completion_ equals max_tokens |
length |
max_tokens reached |
Raise max_tokens, or ask for the answer in parts |
Cut off, completion_ far below max_tokens, long input |
length (or model_ in some APIs) |
Context window full | Shorten the input or the history, or pick a model with a larger window |
| Complete but shorter than you wanted | stop |
The model finished, or a stop sequence fired | Ask for more detail; check the stop parameter |
| No text, or a refusal | content_filter |
The response was filtered | Rephrase the request |
| No text, a tool request instead | tool_calls |
The model wants to call a tool | Run the tool and send the result back |
Fix 1: raise max_tokens#
The most common cause is also the easiest to fix. Set max_tokens yourself, so you know which cap applies. Don't count on the default.
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)This shows the shape of the call. The key goes in as YOUR_API_KEY here; keep a real one out of code you share.
Raising the number only helps up to the model's own limit. Here are the limits on CheapTokens, checked on 20 October 2026 against the CheapTokens model list:
Scroll the table right →
| Model | Model ID | Max output per answer | Context |
|---|---|---|---|
| DeepSeek-V4-Flash (0731) | deepseek- |
32,768 tokens | 380K |
| GLM-5.3-Flash | zai- |
8,192 tokens | 390K |
| MiniMax-M2.7 | MiniMaxAI/ |
8,192 tokens | 200K |
Developers publish their own limits for their own APIs. Z.ai, for example, lists up to 128K output for the GLM-5 series. Those aren't the limits of GLM-5.3-Flash on CheapTokens, which is 8,192 tokens per answer. For anything you build on CheapTokens, use the table above.
Fix 2: when the context window is full#
In a chat, the whole history goes out again with every message, so the input grows each turn. The context window has to hold that history plus the new answer. If the history alone takes nearly all of it, there's almost no room left for a reply.
These windows are large, and one short question won't fill them. Long chats and pasted documents will. What helps:
- Start a new chat for a new task instead of continuing an old one.
- Ask the model to summarise the conversation so far, and carry only the summary forward.
- Cut old messages and attachments you no longer need.
- If the input itself is huge, pick the model with the biggest window. Among ours that's GLM-5.3-Flash at 390K. Its output limit is 8,192 tokens, so ask for a long result in parts.
Fix 3: get a long answer in parts#
When the answer you want is longer than the model's output limit, no setting will fit it into one reply. Ask for it in pieces: when finish_reason is length, send the partial answer back and ask the model to continue.
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)Same caveat: an example of the pattern, not a recorded run. Read the seams between the parts. A model sometimes repeats a sentence or restarts a list at the join.
Each round re-sends everything so far as input, and every output token is billed. A long answer costs more than a short one. Here is an eight-thousand-token answer on 2,000 tokens of input, which fits every model in the table:
| Model | Input $/1M | Output $/1M | Cost | OpenRouter |
|---|---|---|---|---|
| GLM-5.3-Flash | $0.02 | $0.04 | $0.00036 | $0.00069 |
| DeepSeek-V4-Flash | $0.015 | $0.10 | $0.00083 | $0.0013 |
| MiniMax-M2.7 | $0.05 | $0.15 | $0.0013 | $0.0102 |
2,000 input and 8,000 output tokens in total. Prices per 1M tokens are current and change together with our tariffs; the OpenRouter column shows reference prices for the same workload.
When finish_reason is stop#
stop means the model ended the answer. If it ended sooner than you wanted, that isn't a limit problem and a bigger max_tokens changes nothing. Say what you want: the length, the sections, the level of detail. Also check whether the request sets a stop parameter; a stop sequence that shows up in the answer ends it on the spot.
Picking a model by answer length#
Start from the answer you need. If it fits in 8,192 tokens, MiniMax-M2.7 (MiniMaxAI/) handles it on CheapTokens. Its output is cheaper than the OpenRouter reference price, and it's billed at $0.15 (per 1M output tokens). The price is the same at any hour, there are no peak hours, and the API is OpenAI- and Anthropic-compatible.
Here is the current price list for every model:
| Model | Context | Input $/1M | Output $/1M | OpenRouter in | OpenRouter out |
|---|---|---|---|---|---|
| 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 |
Prices in USD per 1M tokens. OpenRouter figures shown for comparison and may change.
If you haven't sent a request yet, Your first API request with CheapTokens walks through it. For what a token is and why input and output are counted separately, see What is a token in AI?.
Endpoints, model ids and limits for every model are in the CheapTokens docs.



