Running Models YourselfLesson 32 of 82

Contents

Running Models Yourself

Lesson 32 of 82. Sign in to keep your place.

Module 4 · Getting it running

Chat templates: the most common silent failure

10 min read

Four ways a template fails without raising an errorA borrowed templateA community quant packaged with another family’smarkersA doubled beginning-of-sequence tokenThe template emits one and the tokeniser addsanotherA system role the model never hadYour system prompt is folded into the user turn, ordroppedThe end marker missing from the stop listIt answers, then invents the next user turn andanswers thatThe model receives one formatted string, never a list of messages. Print the string before concludinganything about the weights: every failure here is visible in it, none of them raises an error, andtogether they account for a large share of reports that a model is stupid.
The model receives one formatted string, never a list of messages. Print the string before concluding anything about the weights: every failure here is visible in it, none of them raises an error, and together they account for a large share of reports that a model is stupid.

Figure

The model never sees your messages

A chat model does not receive a list of messages. It receives one string of tokens. Something has to convert [{"role": "user", "content": "hello"}] into that string, and the conversion has to match the format the model was fine-tuned on, exactly.

That conversion is the chat template. When it is wrong, the model is being addressed in a dialect it does not recognise. It still answers, models are robust, but noticeably worse: ignoring the system prompt, failing to stop, drifting out of character, or producing rambling text. This accounts for a large share of “this model is stupid” reports, and it is invisible unless you look.

What the string looks like

A typical modern format:

Text
<|im_start|>system
You are a careful assistant.<|im_end|>
<|im_start|>user
What is the boiling point of water?<|im_end|>
<|im_start|>assistant

The markers are single tokens in the model’s vocabulary, learned during fine-tuning. The trailing <|im_start|>assistant is the cue to begin answering. Different families use different markers, and the differences are not cosmetic: a model trained on one set has no idea what another’s means.

Applying it correctly

The template is stored with the model, so let the tokeniser apply it:

Python
from transformers import AutoTokenizer
tok = AutoTokenizer.from_pretrained("Qwen/Qwen3-8B")

msgs = [{"role": "system", "content": "You are terse."},
        {"role": "user", "content": "Why is the sky blue?"}]

print(tok.apply_chat_template(msgs, tokenize=False,
                              add_generation_prompt=True))

Print it. Reading the actual string once teaches you more than any explanation, and it is the fastest diagnostic when something is off.

add_generation_prompt=True appends the assistant cue. Omit it and the model has not been told it is its turn, and will often continue the user’s message instead: a bug that looks like the model misunderstanding the question.

The three failures worth recognising

Double BOS. Many templates already emit a beginning-of-sequence token. If the tokeniser then adds another, the model starts with a sequence it has never seen. Symptoms are subtle: slightly worse quality, occasionally much worse. When calling a tokeniser directly, add_special_tokens=False on already-templated text is the fix.

A borrowed template. A community quant packaged with a template copied from a different model family. The markers are wrong, and the model is being spoken to in a foreign dialect. Dump the metadata and compare against the original repository’s tokenizer_config.json.

A system role the model does not have. Some models were trained without a system role. Passing one gets it silently folded into the first user message, or dropped. If your system prompt seems to have no effect, check whether the template actually places it anywhere.

Seeing what your server sends

If you use an OpenAI-compatible endpoint, the server applies the template for you and you never see the result. Two ways to look:

Bash
# llama-server logs the formatted prompt at higher verbosity
llama-server -m model.gguf --verbose

# or bypass chat entirely and send the raw string yourself
curl http://localhost:8080/v1/completions -H 'Content-Type: application/json' \
  -d '{"prompt":"<|im_start|>user\nhello<|im_end|>\n<|im_start|>assistant\n",
       "max_tokens":64}'

The second is the diagnostic that settles it. If the raw call behaves correctly and the chat call does not, the template is your problem.

Overriding a template

When the packaged template is wrong, replace it rather than working around it:

Bash
llama-server -m model.gguf --chat-template chatml
# or supply a Jinja file
llama-server -m model.gguf --chat-template-file ./correct.jinja

In Ollama the template lives in the Modelfile, and ollama show <model> --modelfile prints it. Copy it, correct it, and rebuild the model with ollama create.

Stop tokens

The other half of the same problem. The template’s end marker must be in the server’s stop list, or generation runs past the end of the answer and the model begins writing the next turn of the conversation itself: inventing a user question and answering it. If your model will not shut up, this is why, and the fix is a stop sequence rather than a shorter max_tokens.

Good engines read the stop tokens from the model’s metadata. When a model is new, or a quant was packaged carelessly, they are missing and you must supply them:

JSON
{"stop": ["<|im_end|>", "<|endoftext|>"]}

Check this on the first run of any new model. It takes one prompt and it saves a long, confused investigation.

Every lesson here is open. Your progress is recorded once you pass the Open Model Ecosystem exam.

Check your understanding

A model answers a question correctly, then writes a plausible follow-up question from the user and answers that too, continuing until it hits the token limit. What is the mechanism?

Pick the one you would defend. Your answer stays private.

Next lesson · 9 minContext settings that truncate in silence

Stuck on something?Ask Tri, your AI tutor

How to cite: Addaly (2026) ‘Chat templates: the most common silent failure’, in Running Models Yourself. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/running-models-yourself/chat-templates (Accessed: 13 October 2026).