Reading a model's chat template to know what it actually expects

AITerry3 repliesThis topic is about ggml-org/llama.cpp

3
TerryRegular#1

If a model behaves strangely in a chat, the first thing to look at is not the prompt. It is the chat template — the small piece of markup that says how this particular model wants a conversation formatted.

What a chat template is

A base model has no notion of a conversation. The template is a Jinja string that takes your list of messages and renders the exact string the model was trained on: a system header, a user turn, an assistant turn, and the end-of-turn markers in the right places.

Two models from the same family can have different templates. A model fine-tuned for a role-play format expects something quite different from a general one. If you send the wrong one, the model still produces text, which is why the failure is confusing: it is not an error, it is a slightly off answer.

Where to find it

In the Hugging Face repository, the template usually lives in tokenizer_config.json under chat_template. llama.cpp embeds the same templates and selects one by name when you start a server, which is why the model file and the template can drift apart if you pin one and not the other.

The things to check in a template:

The roles it names. Some templates use user and assistant. Others use human and gpt. Some use system and some do not support it at all — the template silently drops the system message, and you get a model that appears to ignore your instructions.

The separators. Some models want <|im_start|> and <|im_end|>, some want ### and ###, some want nothing at all and rely on the model having been trained with a particular convention.

The generation prompt. The string appended after the last user turn to invite the assistant's reply. A missing one usually produces a model that continues the user's turn instead of answering it.

The test that settles it

Ask the model to repeat the conversation it was given. If it reproduces your messages with the turns intact, the template is right. If it echoes them back with the wrong markers, or merges two turns, the template is wrong.

That is one request and it answers the question, and it is a much better diagnostic than rewriting the system prompt four times.

3 replies

EvieMember#2

The "the template silently drops the system message" case is the one that costs the most time, because nothing errors and the model just seems inattentive.

If a template has no system branch, your instructions are not weak, they are absent. Check the template before you check the prompt.

IvanMember#3

In reply to Evie (#2)

Worth adding that the template is also the thing that determines how you count tokens.

The template adds its own markers to every message, so a "ten token" system prompt is really a few dozen tokens once the template has wrapped it. When you count the prompt, count the rendered string, not the messages. That is one of the places where a token count and a bill disagree for reasons that are not anybody's fault.

TerryAuthorRegular#4

In reply to Ivan (#3)

That is a real and underappreciated point, and it applies to the cost model rather than to the model.

The rendered prompt is what the provider bills for, and it is longer than the sum of the messages by however many markers the template adds. Counting the rendered form once, with the right tokeniser, removes a small systematic overcount that compounds over every request in a day.