Special tokens are reserved IDs in the vocabulary that have structural rather than lexical meaning. They are not part of the input text the user wrote — they tell the model how to interpret the rest of the sequence.
| Token | Role | Used by |
|---|---|---|
| [CLS] | Classification — last-layer hidden state at this position represents the whole input | BERT |
| [SEP] | Boundary between two segments (question / context) | BERT |
| [PAD] | Padding to align variable-length inputs in a batch | Almost every encoder |
| [MASK] | Placeholder for masked-LM training | BERT |
| <|endoftext|> | Document boundary | GPT-2/3/4 |
| <s> / </s> | Beginning / end of sequence | Llama, T5 |
| <|im_start|> / <|im_end|> | Chat message role boundaries (system, user, assistant) | OpenAI Harmony, Llama chat |
Why this matters for you
Modern chat models use chat templates made out of special tokens. When you call tokenizer.apply_chat_template(messages) the library inserts the right special tokens around each role. Bypassing the template — concatenating "User: ..." and "Assistant: ..." manually — is a top-three source of "the model is acting weird" bugs. The model trained on tokens like <|im_start|>user, not on the literal string "User:".