Few-shot examples
Showing beats telling. A few well-chosen examples of input and ideal output often control a model's format, tone, and decision boundaries more precisely than paragraphs of instructions. This lesson explains when to use examples, how to pick and format them, how to select them dynamically for each input, and the subtle ways examples can mislead a model.
Definitions
Giving the model only instructions, with no examples. Works well for common tasks that modern models already understand, such as summarisation or translation.
Including one example (one-shot) or a handful — typically 2 to 8 (few-shot) — of input → output pairs before the real input. The model infers the pattern and continues it. This is also called in-context learning, because the model learns the task from the context without any weight updates.
When examples help most
| Situation | Why examples help |
|---|---|
| A specific output format | The model copies the exact structure, punctuation, and casing. |
| A particular tone or style | Style is hard to describe in words but easy to demonstrate. |
| Subtle classification boundaries | Examples show where “mixed” ends and “negative” begins. |
| Domain-specific labels or jargon | The model learns your label set and how to apply it. |
| Transformations (rewriting, extraction) | Examples demonstrate exactly what to keep and what to drop. |
Examples help less when the task is open-ended and creative (they cause copying) or when a reasoning model is solving a hard problem (explicit instructions and a clear goal usually matter more).
Few-shot in chat format
In chat APIs, each example is a user message followed by an assistant message that you wrote. The model sees them as its own previous, correct answers.
SYSTEM = ("Extract the product and the issue from a support message. "
"Reply as: product | issue (max 6 words, lowercase).")
EXAMPLES = [
("My Vault Pro app crashes whenever I open settings.", "vault pro app | crashes when opening settings"),
("Billing charged me twice for the Team plan this month!", "team plan | charged twice this month"),
("Hi, can't log in to the web dashboard since yesterday.", "web dashboard | cannot log in"),
]
def few_shot_messages(user_input: str) -> list[dict]:
messages = [{"role": "system", "content": SYSTEM}]
for example_in, example_out in EXAMPLES:
messages.append({"role": "user", "content": example_in})
messages.append({"role": "assistant", "content": example_out})
messages.append({"role": "user", "content": user_input})
return messages
msgs = few_shot_messages("The mobile app won't sync photos over Wi-Fi.")
for m in msgs[-3:]:
print(f"{m['role']:>9}: {m['content']}")
print(len(msgs), "messages total")
For single-string prompts, the same idea works inline with clear delimiters, for example <example><input>…</input><output>…</output></example>.
Choosing good examples
- Representative: look like real inputs — same length, messiness, and language as production traffic.
- Diverse: cover different categories, phrasings, and difficulty levels, so the model learns the pattern rather than one surface feature.
- Include edge cases: an input with missing information, an ambiguous one, an off-topic one — each with the exact output you want.
- Balanced labels: if three of four examples are “positive”, the model drifts towards “positive”.
- Perfectly consistent: identical formatting in every example. Any inconsistency will be copied.
- Correct: an error in an example is taught as the rule.
Dynamic few-shot: picking examples per input
With a large pool of labelled examples, you can choose the most similar ones for each new input. Similar examples are more informative than generic ones. Production systems measure similarity with embeddings (see the RAG course); here is the idea with simple word overlap:
import re
POOL = [
("Refund my annual plan please", "billing"),
("I was charged twice", "billing"),
("Backup failed with error 504", "technical"),
("Restore is stuck at 90 percent", "technical"),
("How do I add a teammate to my account?", "account"),
("Change the email on my account", "account"),
]
def words(text: str) -> set[str]:
return set(re.findall(r"[a-z0-9]+", text.lower()))
def similarity(a: str, b: str) -> float:
wa, wb = words(a), words(b)
return len(wa & wb) / len(wa | wb) # Jaccard similarity
def select_examples(query: str, k: int = 2):
ranked = sorted(POOL, key=lambda ex: similarity(query, ex[0]), reverse=True)
return ranked[:k]
for text, label in select_examples("My backup failed again with an error"):
print(f"{label:<10} {text}")
The backup-failure example ranks first because it shares the most words with the query. The second pick is a weak match — word overlap cannot tell that “Restore is stuck” is also a technical problem, which is exactly why production systems use embeddings, which compare meaning rather than spelling. Plug the selected pairs into few_shot_messages and each request gets tailored demonstrations.
Order and bias effects
| Effect | What happens | Mitigation |
|---|---|---|
| Recency bias | The last example has the strongest influence. | Shuffle examples, or put the most typical case last. |
| Majority-label bias | The most frequent label in the examples is over-predicted. | Balance labels across examples. |
| Surface copying | The model copies wording, length, or specific facts from examples. | Vary examples; tell the model they illustrate format only. |
| Format over-fitting | Every answer becomes the same length as the examples. | Include examples of different appropriate lengths. |
Never let facts from examples leak into answers. If your example reply mentions “a 30-day refund window” and the real policy is 14 days, the model may repeat 30. Use clearly fictional or generic content in examples, or examples that are true for every case.
Few-shot with reasoning
For multi-step tasks, examples can demonstrate the reasoning as well as the answer. This is few-shot chain-of-thought: the model learns to show its steps the same way.
Q: A team of 4 uses 120 GB each. Storage costs $0.02 per GB per month. Monthly cost?
Reasoning: 4 x 120 GB = 480 GB. 480 x $0.02 = $9.60.
Answer: $9.60
Q: A team of 7 uses 50 GB each at $0.03 per GB per month. Monthly cost?
Reasoning:
How many examples?
Start with 2–3, measure, and add more only if the evaluation improves. More examples cost more tokens on every request and can crowd out instructions. If you find yourself needing dozens of examples to get consistent behaviour, that is a signal to consider fine-tuning, where those examples become training data instead of prompt tokens.
- Build a zero-shot and a 3-shot version of a sentiment classifier with labels
positive,negative,mixed. - Run both on 15 tricky reviews (sarcasm, mixed opinions, very short). Count disagreements.
- Unbalance the examples (three positive, zero negative) and observe the shift in predictions.
- Few-shot prompting teaches the task through input → output examples, without changing model weights.
- Examples are most powerful for format, tone, label boundaries, and transformations.
- Choose representative, diverse, balanced, consistent, and correct examples — including edge cases.
- Select examples dynamically by similarity to each input for the biggest gains.
- Watch for recency bias, label bias, and copied facts; start with 2–3 examples and let evals decide.