Skip to content
AI360XpertBeta

In-Context Learning

Show a model a few worked examples inside the prompt and its next answer follows their pattern. No training run, no weight change, nothing remembered afterward.

Three sentiment examples in the prompt steer the next answer to positive while the model weights stay exactly the same
Three sentiment examples in the prompt steer the next answer to positive while the model weights stay exactly the same

Why Does This Exist?

Changing what a model does used to mean changing its weights. You gathered data, ran a training loop, and shipped new numbers. That machinery is heavy: data to clean, gradients to compute, checkpoints to judge. When a behavior has to last, it's still the right tool, which is why when to fine-tune gets its own page.

But models trained at scale turned out to have a second gear. Paste three worked examples into the prompt and the very next answer follows their pattern. No optimizer runs. No weight moves. Delete the examples and the behavior vanishes like it was never there. That's startling if your whole picture of learning is gradient descent, because here one frozen function acts like a different machine depending on what you show it.

One idea first, since everything below leans on it. A language model trains on a single job: given some text, guess the next token, check, adjust. Repeat that across enough text and the weights soak up grammar, facts, and styles along the way. The full version lives in next-token prediction. In-context learning is what that same next-token machinery does at test time, when the text sitting before it happens to contain examples.

This page covers that test-time behavior: what varies, why it works, and where it breaks. The hands-on version, writing prompts that show instead of tell, is few-shot prompting. The permanent version, actually rewriting the weights, is instruction tuning.

Think of It Like This

A session musician handed a setlist

A session guitarist knows hundreds of songs cold. Hand her a setlist with three country titles, then the opening bars of a fourth song she has never played. She needs no lessons. She reads the pattern, stays in genre, and plays the fourth song country-style on first sight. The setlist taught her nothing about guitar. It only told her which of her existing skills tonight calls for.

Where it stops: hand her a setlist for an instrument she never learned and you get silence. Examples steer abilities the model already built in pretraining. They cannot install one it never had. When the skill is missing, no arrangement of examples puts it there. That is when you train.

How It Actually Works

Conditioning, not training

Write the model's behavior as Pθ(y∣x)P_\theta(y \mid x). In plain words: PP is the probability distribution the model computes over possible outputs, θ\theta (theta) is its weights, yy is the output tokens you have not seen yet, xx is the prompt tokens you supplied, and ∣\mid means "given". Zero-shot prompting asks for Pθ(y∣x)P_\theta(y \mid x) with an instruction alone. Few-shot prompting asks for Pθ(y∣E,x)P_\theta(y \mid E, x), where EE is a few demonstration pairs placed before the query. Only the right side of the bar changed. θ\theta sits outside everything that moves.

All of it runs through the ordinary forward pass described in how LLMs work: embed the tokens, run the transformer blocks, sample the next token. There's no second mode. The weights answering a prompt with five examples are bit-for-bit the weights answering a prompt with none, so nothing persists. The next request starts from the same θ\theta with a different xx.

Zero-shot, one-shot, few-shot

The names just count examples. Zero-shot shows none and leans on the instruction alone (zero-shot prompting). One-shot shows a single pair. Few-shot shows a handful, usually two to five. The model never changes between these. Only the length and content of xx changes.

More examples usually pin down the pattern better, but each one spends context. A context window is finite, and every example token is one your actual task cannot use. Past a point you are paying rent on every request for examples that stopped adding signal several examples back.

Why examples steer at all

Pretraining text is full of pattern-then-continuation: glossaries, phrasebooks, worked exercises, tables. A model that predicts next tokens well across that diet has to get good at spotting "a pattern is being demonstrated" and continuing it, because finishing those passages demands exactly that. Few-shot prompting works because it hands the model the kind of passage it spent training learning to finish.

That is also the assumption the whole trick rests on: the examples select among patterns the model already knows. Break it and steering fails. Ask for a notation the model never saw, with three neat examples, and you'll often get something fluent and wrong, continuing the surface shape while missing the rule. Fluency is not comprehension, and examples cannot fix a missing capability.

Worked example: counting the prompt

Take sentiment classification with three examples and one query, the same prompt the diagram draws:

"happy" -> positive"awful" -> negative"fine" -> neutral"thrilled" ->

Count the words on each line. "happy" -> positive is three words. So is each of the next two lines. The query line, "thrilled" ->, is two. Total: 3+3+3+2=113 + 3 + 3 + 2 = 11 words, against 2 words for the zero-shot version. Nine extra words buy the behavior shift.

Those nine words are re-sent, re-processed, and re-paid on every single request. Nothing is amortized, because nothing is stored. That is the trade in one line: instant adaptation at per-request rent, versus instruction tuning, which pays once during training and then charges nothing per request.

Code

The point of this snippet is the boundary it draws: the only object the code builds is a longer string. No model, no weights, and no optimizer appear anywhere in it.

def build_prompt(examples: list[tuple[str, str]], query: str) -> str:    lines = [f'"{text}" -> {label}' for text, label in examples]    lines.append(f'"{query}" ->')    return "\n".join(lines)

examples: list[tuple[str, str]] = [    ("happy", "positive"),    ("awful", "negative"),    ("fine", "neutral"),]zero_shot = build_prompt([], "thrilled")few_shot = build_prompt(examples, "thrilled")
print(zero_shot)# -> "thrilled" ->print(len(zero_shot.split()), len(few_shot.split()))# -> 2 11

Two words versus eleven: the same numbers as the worked example and the diagram. Whatever behavior gap you observe between those two strings comes from the forward pass reading a longer xx, because there is nothing else here that could cause it.

Watch Out For

Expecting the examples to stick around

The symptom shows up after testing goes well: your few-shot prompt behaves in the harness, then users report the raw behavior back. The examples lived in your test script, never in the app's request template, so production prompts never contained them. Each request starts from the same weights holding whatever that request's prompt holds.

The fix is to treat the examples as code. Freeze one exact template, examples included, and send it on every request. If the pattern must hold without per-request rent, bake it in with instruction tuning instead. Never rely on memory across sessions. There's none.

Shuffling examples and watching the answer flip

Same examples, different order, different answer. Or a formatting tweak, an arrow versus a colon, moves results more than adding two examples did. That brittleness surprises people who think of examples as training data, where order mostly washes out. Here order is part of the input, so it is part of the prediction.

Pin the order and the format exactly, then test the pinned template on a small fixed set before shipping. When results swing with order, keep the arrangement that is most consistent, not the one that reads nicest, and keep the count small enough that position effects stay visible during review.

The Quick Version

  • In-context learning changes what a model does without touching its weights: examples in the prompt steer the next output, then vanish.
  • It runs through the ordinary forward pass. There is no separate learning mode, and nothing persists between requests.
  • Zero-shot shows no examples and few-shot shows a handful, both on identical weights.
  • It works because next-token pretraining rewards continuing demonstrated patterns, so a prompt shaped like a pattern gets continued.
  • Examples rent context on every request and order effects are real, so freeze one template and test it before shipping.
  • When the behavior must persist across sessions or the model lacks the underlying skill, examples are the wrong tool: retrieve or fine-tune instead.