Skip to content

Chat Template Renderer

Render a message list into the single string a model is actually given, with every space and newline made visible — and parse a rendered string back into messages.

Rendered length
216 characters

≈ 54 estimated tokens, of which the markers are a fixed overhead you pay on every turn.

Messages rendered
4
Role markers emitted
5
Characters spent on markers
141
Ends with the generation prompt
yes
Worth looking at:
  • A assistant message was opened but its closing marker never appeared — the string is truncated, or the suffix is wrong.
  • The string ends with the generation prompt, so the last message is the model's turn to speak rather than a completed one.
What this assumes: the presets are named for the SHAPE of a well-known template, not for any particular model — a model's real template ships in its tokenizer config and changes between releases, so treat these as starting points and check yours. Every field is editable for that reason. Token figures are characters ÷ 4 and do not know that <|im_start|> is usually a single token rather than twelve characters' worth. Everything on this page runs in your browser. Nothing you paste is uploaded, logged or sent anywhere.

A chat model does not receive a list of messages. It receives one string, assembled from your messages by a template, and everything the model knows about who said what comes from the special tokens that template inserted. When a good model suddenly behaves like a bad one, the string is the first place to look: a doubled newline, a missing end-of-turn marker, or a system message rendered into a slot the model was never trained to read.

Why the whitespace toggle exists

The difference between a template that works and one that does not is frequently a single trailing space, and a trailing space is invisible. Turning on the reveal shows every one of them, along with the double newlines that appear when a suffix ends with \n and the next prefix begins with one. This also matters for caching: a prefix that differs by one character is a different prefix, and the cache hit you were counting on silently becomes a miss.

The round trip is the test

Rendering messages into a string is easy. Parsing that string back into messages is what proves the markers are unambiguous — if the parser cannot tell where a user turn ended, neither can anything else that reads your logs. Paste a real prompt string from your own stack into the other direction and see whether it decomposes cleanly; if leftover text shows up in the unattributed list, your template and your assumed template are not the same template.

Chat Template Renderer · Multigrid