Same text, two models
SmolLM2-135M and its instruction-tuned version read exactly the same tokens; only their training differs.
Both models read exactly this
<|im_start|>system
You are a helpful AI assistant named SmolLM, trained by Hugging Face<|im_end|>
<|im_start|>user
Give me three tips for sleeping better.<|im_end|>
<|im_start|>assistant
SmolLM2-135M (base)
Pretrained only: it learned to continue text.
Loading the recorded results
SmolLM2-135M-Instruct
The same model after fine-tuning on conversations and preference tuning.
Loading the recorded results
Challenges
0 of 3 complete
- Find the setting where the instruct model ends its reply without writing a single word. (not yet)
- With plain text, find a message that the base model answers by writing it out again. (not yet)
- Get the instruct model to answer and end its turn by itself. (not yet)
Try this
- With the chat template, compare the two columns: the instruct model answers and ends its turn; the base model does something strange with the tags.
- Switch to plain text. The base model continues your question like a page of questions, and the instruct model ends its reply at once.
Why the end-of-turn token comes after a questionPython with the standard library
from collections import Counter, defaultdict
# A toy "instruction tuning" set in the chat layout (SmolLM2-135M-Instruct
# was tuned on about 460,000 conversations; three show the idea).
pairs = [("What is the capital of France ?", "Paris ."),
("What is the capital of Italy ?", "Rome ."),
("Name a color .", "Blue .")]
def chat(user, answer=""):
return ["<|im_start|>", "user", "\n", *user.split(), "<|im_end|>", "\n",
"<|im_start|>", "assistant", "\n", *answer.split()]
# Count which token follows each token and each pair of tokens.
follows = defaultdict(Counter)
for user, answer in pairs:
seq = chat(user, answer) + ["<|im_end|>"]
for i in range(1, len(seq)):
follows[(seq[i - 1],)][seq[i]] += 1
if i > 1:
follows[(seq[i - 2], seq[i - 1])][seq[i]] += 1
def next_token(tokens):
# Use the last two tokens if that pair was seen, else the last one.
counts = follows.get(tuple(tokens[-2:])) or follows[(tokens[-1],)]
word, n = counts.most_common(1)[0]
return f"{word!r} ({n} of {sum(counts.values())})"
question = "What is the capital of Spain ?"
print("plain text ->", next_token(question.split()))
print("chat template ->", next_token(chat(question))) # the layout, not geography
print("after Blue . ->", next_token(chat("Name a color .", "Blue .")))plain text -> '<|im_end|>' (2 of 2)
chat template -> 'Paris' (1 of 3)
after Blue . -> '<|im_end|>' (1 of 1)