Self-hosted Llama 3 chat returns fluent-looking nonsense. You check and the prompt was tokenized with cl100k_base. What went wrong?
Same topic, related formats. Practice these next.
Same topic, related formats. Practice these next.
Click any words you think contain an error. Click again to unmark.
cl100k_base is GPT-4's tokenizer; Llama 3 uses its own 128K BPE with its own special tokens. Wrong tokenizer plus wrong chat template produces fluent-looking garbage. Use AutoTokenizer plus apply_chat_template.
Imagine two phone books, both 128,000 entries long, both alphabetical. They look identical from the outside. But entry 14,082 in one belongs to a different person than entry 14,082 in the other. If you dial the number from book A while pretending you are using book B, you reach a stranger every time. That is what happens when you tokenize a Llama 3 prompt with the GPT-4 tokenizer. Each id you produce points to a different word in Llama's brain than you meant. The model still answers, because answering is what it does, but the words coming out of it have nothing to do with what you asked. The fix is to use Llama 3's own phone book and Llama 3's own greeting format, not a borrowed one from a different model.
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example.
Everything important, quickly.
Open with the framing that the tokenizer is part of the model. Diagnose the two bugs: cl100k_base ids indexing into the Llama 3 embedding matrix as garbage, then the wrong chat-template markers missing <|begin_of_text|>, <|start_header_id|>, <|end_header_id|>, <|eot_id|>. Walk the fix with AutoTokenizer plus apply_chat_template. Close on the startup-time assertion that catches this class of mistake permanently.
# Wrong: cl100k_base ids fed into Llama 3 embeddings
import tiktoken
enc = tiktoken.get_encoding('cl100k_base')
prompt = f'<|begin_of_text|>system\n{sys}\nuser\n{msg}\nassistant\n'
ids = enc.encode(prompt, allowed_special='all')
out = llama3_model.generate(ids) # fluent nonsense
# Right: Llama 3 tokenizer plus apply_chat_template
from transformers import AutoTokenizer
tok = AutoTokenizer.from_pretrained('meta-llama/Meta-Llama-3-8B-Instruct')
messages = [
{'role': 'system', 'content': sys},
{'role': 'user', 'content': msg},
]
input_ids = tok.apply_chat_template(
messages, add_generation_prompt=True, return_tensors='pt'
)
out = llama3_model.generate(input_ids)
# Startup-time guard
assert tok.vocab_size == llama3_model.config.vocab_size
assert tok.bos_token_id == llama3_model.config.bos_token_idReal products, models, and research that use this idea.
What an interviewer would ask next. Try answering before peeking at the approach.
Red flags and common mistakes that signal junior thinking. Click to expand.
Assuming two tiktoken-style BPEs with similar vocab size are interchangeable, when their merge tables and special tokens are completely independent.
The night-before-the-interview bullets. Scan these on the way to the call.
Primary sources. Skim if you want the original framing.