S116 · Prompting — Zero-Shot, Few-Shot, Chain-of-Thought, ReAct
The four prompting patterns that actually move the needle — with the failure modes, decision rules, and Anthropic/OpenAI-recommended templates for each.
🎯 Pick the right prompting pattern (zero-shot / few-shot / CoT / ReAct) for a new task in under 30 seconds and template it correctly.
Why this session exists
"Prompt engineering" got laughed at in 2024 and quietly became mandatory in 2026. The gap between a bad prompt and a good prompt is often bigger than the gap between GPT-3.5 and GPT-4. This session teaches you the four canonical patterns that actually earn their weight in production (zero-shot, few-shot, chain-of-thought, ReAct), the empirical evidence for each, and the templates the frontier labs actually recommend.
- Explain the difference between zero-shot, few-shot, CoT, and ReAct in one sentence each.
- Pick the right pattern for a new problem — extraction / reasoning / tool use — in under 30 seconds.
- Write a prompt with structured output, system prompt, and constraints that survives production drift.
- Diagnose 'the model won't follow my format' bugs by category (missing role, temperature too high, ambiguous instructions).
- Explain why CoT helps math + logic tasks but hurts extraction and can trigger safety issues.
Prerequisites
- S112 · BERT/GPT/T5 — you need the decoder-only mental model to reason about in-context learning.
- S113 · LLM Sampling — decoding parameters interact with every prompting pattern here.
(a) Intuition · 5 min
You hired an intern who is smart, has read the internet, but has no idea what your company does. You have four levers:
1. Just ask ("summarise this contract"). 2. Show 2–3 examples of the desired output. 3. Ask them to think out loud before answering. 4. Give them access to tools (a calculator, a search bar, a database) and tell them how to use each.
The trick is knowing which lever the task actually needs. Show-examples for a subjective classification. Think-out-loud for math. Give-tools for anything that requires external knowledge or precise computation.
LLM prompting is exactly the same four levers with fancy names: zero-shot = just ask. Few-shot = show examples. Chain-of-thought = "let's think step by step". ReAct = tool use with an explicit Thought → Action → Observation loop.
Modern LLMs are trained to respond well to these patterns because their instruction-tuning datasets contain thousands of each. Reaching for the right one is a 30-second decision that often gets you an entire benchmark point.
- Zero-shot — just ask. Works surprisingly well on frontier models for extraction, classification, summarisation. Try this FIRST always.
- Few-shot (in-context learning) — 2–5 examples in the prompt. Best when the output format is unusual or the task is subjective (tone, style, taxonomy).
- Chain-of-thought (CoT) — 'let's think step by step' or explicit reasoning trace. 20–40 point gains on multi-step math/logic. Zero help on extraction.
- ReAct — Thought → Action → Observation loop with tools. The default pattern for LLM agents; every function-calling API is a variant of this.
The rise of the four patterns
- 2020GPT-3 + in-context learningBrown et al. show that a 175B decoder can 'learn' a new task from a few examples in the prompt. Kicks off prompt engineering as a discipline.
- 2022Chain-of-Thought · Wei et al.Adding 'let's think step by step' or example reasoning traces gives huge gains on GSM8K and BBH benchmarks.
- 2022ReAct · Yao et al.Combining Reasoning + Action traces enables LLMs to use tools coherently. Foundation for every 2024+ agent framework.
- 2023Self-consistency · Wang et al.Sample N CoT traces at T=0.7, majority-vote the final answers. Another 10-point gain on math tasks, at 5-20× cost.
- 2024Structured output APIsOpenAI JSON mode, Anthropic tool_use, Gemini function calling. Prompting becomes 'give a schema, get a schema-conforming answer'.
- 2025Reasoning models (o1, Claude thinking)CoT gets baked into the model. External CoT prompts become less necessary — but the mental model still applies.
(b) Visual walkthrough · 15 min
The decision tree
The four patterns side by side
Just ask. Cheap. Try first.
- 1 API call, no examples
- Best for: extraction, classification, summarisation on well-known tasks
- Fails on: unusual formats, niche domains, subjective judgments
- Cost baseline
Show 2–5 examples in-context
- 1 API call, longer prompt
- Best for: unusual output formats, tone matching, custom taxonomies
- Fails on: reasoning-heavy tasks (examples don't teach reasoning)
- Cost 1.5–3× baseline
Reason step by step first
- 1 API call, longer generation
- Best for: math, logic, planning, multi-hop reasoning
- Fails on: extraction (overthinks), can be verbose
- Cost 3–10× baseline
Thought → Action → Observation loop
- N API calls (one per step)
- Best for: tool use, search, code exec, database queries
- Fails on: purely-linguistic tasks (overkill)
- Cost 5–50× baseline; latency multiplies
The anatomy of a well-structured prompt
What every good prompt has (Anthropic-style)
CoT visualised
For trivial arithmetic both get it right. Move to a 3-step word problem and CoT is often 30 points higher. Move to extraction ('what is the customer's name?') and CoT hurts because there's nothing to reason about.
The ReAct loop
"Chain-of-thought works because the model reasons step by step. So the reasoning text it produces is an explanation of how it got the answer."
The generated reasoning is a computation substrate, not necessarily a faithful account. It helps because each emitted token is another forward pass conditioned on everything before — the model buys itself serial compute it otherwise could not have, and it puts intermediate results into the context where later steps can attend to them. But models demonstrably produce correct answers with unfaithful stated reasoning, and can be steered by cues they never mention.
Because the output looks exactly like human reasoning, and we have no other prior for text of that shape. The stronger reason it sticks: it makes an accurate prediction — CoT does improve multi-step accuracy — so the mechanism story is never falsified in daily use. The falsification only shows up when you plant a biasing cue in the prompt and watch the model change its answer while its stated reasoning stays the same.
A faithfulness probe you can run on any model:
# 1. Ask a multiple-choice question with CoT. Record answer + reasoning.
# 2. Re-ask identically, but add a biasing cue:
# 'I think the answer is (C), but check my work.'
# 3. Compare.
#
# If the answer moves toward (C) while the stated reasoning never
# mentions your suggestion, the reasoning is not the cause of the
# answer. Run over ~50 questions and report the flip rate.The practical consequence: never treat a model's stated rationale as an audit trail. It is generated text subject to the same pressures as any other output.
Why does "think step by step" improve accuracy at all? The model's weights do not change, and it already had the same information.
- 1A transformer applies a fixed number of layers per token. The compute available to produce one token is bounded and constant, regardless of how hard the question is.forced by · depth is fixed at architecture time; there is no loop
- 2So any problem requiring more sequential steps than the model has layers cannot be solved within a single token's forward pass.forced by · each layer can perform roughly one step of composition; you cannot fit k sequential steps into fewer than ~k layers
- 3But generation is autoregressive: every token emitted is appended to the context and the whole stack runs again. Emitting n tokens gives you n × depth sequential compute.forced by · the model re-reads its own output, so the context is a working memory that persists across passes
- 4Crucially, that working memory is written in tokens, so it must be explicit. An intermediate result the model does not write down is lost when the next forward pass begins — nothing else carries state between tokens except the KV cache of what was actually emitted.forced by · there is no hidden scratchpad; the context is the only state
- 5Therefore prompting for explicit intermediate steps converts a depth-bounded problem into a length-bounded one, and length is the cheap resource.forced by · you can always generate more tokens; you cannot add layers at inference
Therefore CoT is a compute-allocation technique: it trades output tokens for serial depth. That reframing explains the whole family at once.
And note what this predicts: (1) CoT should help most on problems with genuine sequential structure — arithmetic, multi-hop lookup, constraint satisfaction — and help little or not at all on single-step recall or sentiment, which is exactly the observed pattern; (2) even meaningless filler tokens should provide some benefit if they buy passes, which has been observed; (3) the natural extension is to spend far more tokens deliberately at inference. That prediction is precisely what reasoning models do, and why they are priced per reasoning token.
You are not persuading an agent. You are conditioning a distribution and allocating compute. The prompt sets the region of the distribution the model samples from; the tokens it generates are the only working memory it has, and each one buys another full pass through the network.
So a prompt has two independent jobs: constrain the space of acceptable outputs, and allocate enough tokens for the computation the task actually requires.
- Show, do not describe. A single well-chosen example constrains format more precisely than a paragraph of instruction, because format is a pattern the model can copy.
- Put the instruction where attention will reach it. Very long contexts show position sensitivity — the middle is the weakest place for a critical constraint.
- Decompose rather than elaborate. Two calls with clear single jobs beat one call with a complicated prompt, because each call gets its own full compute budget and its own clean context.
- A stated rationale is output, not explanation. Never use it as an audit trail or a safety control.
Fire this model the moment you see: a prompt being made longer to fix a failure · a model getting arithmetic wrong · inconsistent output format · someone citing the model's explanation as evidence · a task that a human would need scratch paper for.
Your zero-shot prompt is at 80% accuracy and you need 95%. Add few-shot examples, add chain-of-thought, or fine-tune?
Diagnose before you reach. Sample twenty failures and classify them: format errors want examples, reasoning errors want decomposition, knowledge gaps want retrieval, and only "the model understands but will not consistently comply" wants fine-tuning. Most teams fine-tune when they had a format problem, and most reach for a longer prompt when they had a compute problem.
The cost asymmetry also matters and is often ignored: few-shot tokens are paid on every request in perpetuity, while fine-tuning is paid once. At sustained volume the crossover arrives fast — but only after the prompt has stopped improving, because fine-tuning a task you have not yet specified precisely just bakes in your confusion.
(c) Hands-on · 25 min
Compare the four patterns on the same benchmark of math + extraction problems. This is the fastest way to build intuition for when each wins.
"""prompt_patterns.py — measure zero/few/CoT/ReAct on a small task set.
Requires: openai or anthropic sdk + API key. Change MODEL/CLIENT to match.
"""
from __future__ import annotations
import json
import os
import re
import time
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
MODEL = "gpt-4o-mini" # cheap, fast, plenty smart enough for the demo
def ask(system: str, user: str, temperature: float = 0.0) -> str:
r = client.chat.completions.create(
model=MODEL,
messages=[{"role": "system", "content": system},
{"role": "user", "content": user}],
temperature=temperature,
)
return r.choices[0].message.content.strip()
# ---------- The evaluation set: a math word problem + an extraction ----------
MATH_Q = (
"Alice has 3 more apples than Bob. Bob has twice as many as Charlie. "
"Together they have 33 apples. How many does Charlie have?"
)
MATH_A = "6"
EXTRACT_Q = (
"Customer email: 'Hi, my name is Priya Sharma. My order #A-4821 arrived "
"damaged. Please refund $89.99 to my card ending 4242. Thanks!'"
)
EXTRACT_SCHEMA = ("Extract as JSON: {name, order_id, amount, "
"issue_category (damage/late/wrong/other)}")
# ---------- 1. Zero-shot ----------
def zero_shot(q: str) -> str:
return ask("You are a helpful assistant. Answer concisely.", q)
# ---------- 2. Few-shot ----------
FEW_SHOT_MATH = """Solve each problem. Give only the final integer answer.
Q: There are 5 pens. I buy 2 boxes of 4. How many pens total?
A: 13
Q: A train leaves at 3 and arrives at 7. How many hours?
A: 4
Q: {q}
A:"""
def few_shot(q: str) -> str:
return ask("You are a helpful assistant.", FEW_SHOT_MATH.format(q=q))
# ---------- 3. Chain-of-thought ----------
COT = "Let's think step by step. Show your reasoning, then on the last line write 'ANSWER: <value>'."
def cot(q: str) -> str:
out = ask("You are a helpful assistant.", f"{q}\n\n{COT}")
m = re.search(r"ANSWER:\s*(.+)", out)
return m.group(1).strip() if m else out.splitlines()[-1]
# ---------- 4. ReAct (tool-using) — mini implementation ----------
def get_apples(person: str) -> int: # a fake 'database'
return {"charlie": 6, "bob": 12, "alice": 15}.get(person.lower(), -1)
TOOLS_DESC = ("You have one tool: get_apples(person). "
"Respond in the form:\n"
"Thought: ...\nAction: get_apples('name')\n"
"or\nThought: ...\nFinal Answer: <value>")
def react(q: str, max_steps: int = 5) -> str:
convo = f"Question: {q}\n"
for _ in range(max_steps):
out = ask(TOOLS_DESC, convo)
convo += out + "\n"
if "Final Answer:" in out:
return out.split("Final Answer:")[-1].strip()
m = re.search(r"Action:\s*get_apples\(['\"]?(\w+)['\"]?\)", out)
if m:
obs = get_apples(m.group(1))
convo += f"Observation: {obs}\n"
else:
break
return "(no final answer)"
# ---------- Run all four on the MATH problem ----------
print(f"MATH problem: {MATH_Q}")
print(f"Correct answer: {MATH_A}\n")
for name, fn in [("zero_shot", zero_shot),
("few_shot", few_shot),
("cot", cot),
("react", react)]:
t0 = time.time()
ans = fn(MATH_Q)
print(f" {name:<10} → {ans[:60]:<60} ({time.time()-t0:.1f}s)")
# ---------- Run zero-shot vs few-shot on EXTRACTION ----------
print(f"\nEXTRACTION problem: {EXTRACT_Q}")
zs = ask("You are a data extractor. Respond with ONLY valid JSON.",
f"{EXTRACT_Q}\n\n{EXTRACT_SCHEMA}")
print(f" zero-shot JSON → {zs[:120]}")What each block does
Anatomy of the four patterns
Add:
from collections import Counter
def self_consistent(q: str, k: int = 5) -> str:
answers = []
for _ in range(k):
out = ask("You are a helpful assistant.",
f"{q}\n\n{COT}", temperature=0.7)
m = re.search(r"ANSWER:\s*(.+)", out)
if m:
answers.append(m.group(1).strip())
return Counter(answers).most_common(1)[0][0]
print("self_consistent →", self_consistent(MATH_Q))Run 5–10× and see how much more stable it is than single-shot CoT.
(d) Production reality · 15 min
Early API users kept complaining that GPT-3 was 'bad at math'. Simple word problems it fluffed constantly. Papers on 'why LLMs can't reason' proliferated.
Wei et al. (Google) showed that adding 'Let's think step by step' or a few worked examples with reasoning steps produced 30+ point gains on GSM8K (grade-school math). The model could reason all along — it just needed permission to.
Customers reported Claude 'refuses to follow the format' — asked for JSON, got prose. Asked for one word, got a paragraph.
Anthropic's official recommendation: use XML tags to delimit input/output sections, put the format spec at the end of the prompt (recency bias), and provide a partial 'assistant' turn that starts with the desired opening (e.g. pre-fill an opening brace for JSON output).
The pre-fill trick alone fixed 80% of format-compliance issues before official 'JSON mode' shipped.
Pre-ReAct, LLMs given tools would either hallucinate tool call arguments or forget to use tools at all. Naive prompting like 'you have a search tool, use it' failed.
ReAct: explicitly interleave Thought (reasoning about state) and Action (tool call) in the same generation, then feed the Observation back into the next generation. The Thoughts anchor the model in the plan, the Actions provide grounded facts, the Observations correct any drift.
Every agent framework since 2023 (LangChain, LlamaIndex, Autogen, CrewAI) is a ReAct variant. Function-calling APIs are ReAct with the parsing done by the platform.
Where this shows up next
(e) Recall + stretch · 10 min
Explain-out-loud test
- What is in-context learning and why doesn't BERT do it?
- When does CoT help, and when does it hurt?
- What is the ReAct loop and why does 'Thought' matter?
What comes next
Hub: The 6-Month Learning Plan
Part of a 130-session evergreen learning series. Session structure: intuition → visual → hands-on → production war stories → recall. Duration: 90 minutes.