Fill In the Sampling and Decode Loop of an LLM Inference Notebook
AnthropicMachine Learning Engineer · OnsiteLast updated
Anthropic Fellows final-round practice: complete temperature/top-k/top-p sampling and a batched KV-cache decode loop in a Colab notebook so greedy output matches model.generate.
Context
One candidate account of the Anthropic Fellows final round describes a 55-minute live exercise in Google Colab. The notebook held 20–30 lines of skeleton Python with two incomplete functions that finish an LLM inference step. Using an LLM was explicitly not allowed. Candidates were told to check the notebook environment and GPU beforehand. The skeleton below is a practice reconstruction of that shape; the real notebook's functions were not published.
Notebook Skeleton
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
tok = AutoTokenizer.from_pretrained("gpt2", padding_side="left")
tok.pad_token = tok.eos_token
model = AutoModelForCausalLM.from_pretrained("gpt2").to("cuda").eval()
def sample_next_token(logits, temperature=1.0, top_k=0, top_p=1.0, generator=None):
"""logits: (batch, vocab) for the last position.
temperature == 0 -> greedy. top_k == 0 / top_p == 1.0 -> disabled.
Returns (batch,) int64 token ids."""
# TODO
@torch.no_grad()
def generate(model, input_ids, attention_mask, max_new_tokens, eos_token_id, pad_token_id, **sampling):
"""input_ids / attention_mask: (batch, seq), LEFT-padded.
Run the prompt once, then decode one token at a time reusing past_key_values.
Sequences that emit EOS keep emitting pad_token_id. Stop early when all are done.
Returns (batch, seq + generated) token ids."""
# TODO
batch = tok(["The capital of France is", "def fibonacci(n):"], return_tensors="pt", padding=True).to("cuda")
ids = generate(model, batch.input_ids, batch.attention_mask, 20, tok.eos_token_id, tok.pad_token_id, temperature=0)
print(tok.batch_decode(ids, skip_special_tokens=True))
Requirements
- With
temperature=0, the output must matchmodel.generate(..., do_sample=False)exactly, for a left-padded batch of different-length prompts. top_k=1must behave like greedy at any temperature.- Sampling must be reproducible with a seeded
torch.Generator. - The prompt is processed once. Each later step feeds only the newest token plus
past_key_values. - Be ready to explain what changes for a batch where one sequence finishes early.
Hints
Hint 1
Special-case temperature 0, and mask removed tokens with -inf rather than 0.
Hint 2
For top-p, compare the probability mass before each sorted token with p, always keep the top token, and scatter back to vocabulary order.
Hint 3
With left padding, derive position_ids from the attention mask and extend the mask by one column every step.
Follow-up questions
- Why should temperature be applied before top-p filtering?
- How would you support stop strings that span several tokens?
- How would you turn this loop into continuous batching where requests join mid-decode?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.