Chain-of-Thought (CoT) is one of the most impactful prompting techniques. Instead of asking directly, ask the model to show its reasoning. Results are dramatically better.


Why It Works

Without CoT

Question: "I have 10 apples. I eat 3. My friend gives 5. How many now?"
Direct: "You have 12 apples"
✓ Correct but luck

Complex math:
"A train leaves A for B (200km) at 100 km/h. A car leaves B at 80 km/h.
 When do they meet?"
Direct: "After 2 hours"
✗ Wrong! (Correct: 1.1 hours)

Model didn't think—it guessed pattern.

With CoT

"...When do they meet?
 Let me think step by step."

Model:
"1. Train: 100 km/h from A
  2. Car: 80 km/h from B
  3. Combined approach: 180 km/h
  4. Time to cover 200 km: 200/180 = 1.11 hours

They meet after ~1 hour 7 minutes"
✓ Correct!

Triggering "let me think" activates reasoning pathways.

Variants

Zero-Shot CoT (Simple)

# Without
"What is the answer to X?"

# With
"What is the answer to X? Let me think step by step:"

Improvement: +5-40% accuracy depending on task
Cost: More output tokens (but worth it)

Few-Shot CoT

prompt = """
Example 1:
Question: 2+2?
Thought: 2+2 = 4
Answer: 4

Example 2:
Question: 10+15?
Thought: 10+15 = 25
Answer: 25

New Question: 123+456?
Thought: [model thinks]
Answer: [model answers]
"""

Improvement: +10-50% vs zero-shot CoT
Cost: Longer prompt

Self-Consistency Decoding

Generate CoT multiple times, vote on answer:

def self_consistent_answer(question, num_tries=5):
    answers = []
    for i in range(num_tries):
        response = llm(f"{question}\n\nLet me think:")
        answer = extract_answer(response)
        answers.append(answer)

    # Voting
    return max(set(answers), key=answers.count)

# Cost: 5× more tokens
# Quality: +5-15% accuracy
# Use only for critical decisions

Tree-of-Thought (ToT)

Explore multiple reasoning paths, not just linear:

Problem: Best chess strategy?

Thought 1: Attack king
  ├─ With knight
  └─ With pawn
    └─ Verdict: Pawn better

Thought 2: Defend
  ├─ With rook
  └─ With bishop

[LLM evaluates which path most promising]

Cost: 10-100× more tokens
Rarely used (complex).

Extended Thinking (Claude, New)

response = client.messages.create(
    model="claude-3-7-sonnet",
    max_tokens=16000,
    thinking={
        "type": "enabled",
        "budget_tokens": 10000  # internal thinking
    },
    messages=[{
        "role": "user",
        "content": "Complex math problem..."
    }]
)

# Claude thinks internally (invisible)
# Output more precise than visible CoT

vs CoT: Internal thinking often better (+5-20% quality), same cost.


When CoT Helps

Complex math:              ✅ CoT +40% improvement
Multi-step reasoning:      ✅ CoT +30%
Code writing:              ✅ CoT +25%
Logic puzzles:             ✅ CoT +50%

Simple factual QA:         ❌ CoT helps 0%, wastes tokens
Summarization:             ❌ CoT creates filler text
Classification (label):    ❌ CoT makes output longer
Sentiment analysis:        ❌ Overkill

Empirical Results

GPT-4 on Complex Tasks

Task No CoT CoT Improvement
Math (SVAMP) 67% 92% +25%
Code (MGSM) 71% 83% +12%
Commonsense 58% 81% +23%
Logic 42% 96% +54%

Cost-Benefit

Math problem (no CoT):
- Tokens: 200
- Accuracy: 65%
- Cost: €0.006

Math problem (with CoT):
- Tokens: 600
- Accuracy: 92%
- Cost: €0.018

Error cost comparison:
- Without: 35% error rate
- With: 8% error rate
- Value per error prevention: Worth it if critical!

Rule: If error is expensive (medicine, code) → use CoT always
      If error is cheap (UI text) → usually skip CoT

Best Practices

# 1. Trigger correctly
wrong = "What is the answer?"
right = "Let me think step by step:"

# 2. Combine with few-shot
prompt = """
Example 1: [with CoT thinking]
Example 2: [with CoT thinking]
New question:
Let me think step by step:"""

# 3. Don't overdo examples
too_much = """Thought: Step 1... Step 2... [50 lines]"""
good = """Thought: First A, then B, then C"""

# 4. Structure for complex tasks
prompt = """
Analyze:
1. Given:
2. Find:
3. Solution:
"""

# 5. Use self-consistency for critical decisions
if critical_decision:
    answer = self_consistent_answer(question, num_tries=5)
else:
    answer = llm(question + "\nThinking:")

CoT is simple magic: +20-50% quality for +200-400 extra tokens. Standard best practice. Always use for reasoning tasks.


Advanced CoT Techniques

Least-to-Most Prompting (Breaking Down Hard Problems)

def least_to_most_prompt(problem):
    """Break hard problems into simpler subproblems."""

    # Step 1: Identify subproblems
    subproblem_prompt = f"""
Given this complex problem, what are the prerequisite simpler problems we need to solve first?

Problem: {problem}

Subproblems (ordered from simple to complex):"""

    subproblems = llm(subproblem_prompt)

    # Step 2: Solve each subproblem in order
    solutions = []
    for subproblem in parse_subproblems(subproblems):
        solution_prompt = f"""
Solve this step:
{subproblem}

Solution:"""
        solution = llm(solution_prompt)
        solutions.append(solution)

    # Step 3: Combine to solve original
    combine_prompt = f"""
Using these solutions to subproblems:
{chr(10).join(solutions)}

Solve the original problem:
{problem}

Answer:"""

    final_answer = llm(combine_prompt)
    return final_answer

# Example: "Build a web server from scratch"
# Subproblems:
# 1. What is TCP/IP?
# 2. How do sockets work?
# 3. How do HTTP requests work?
# 4. How to parse HTTP?
# 5. How to send responses?

Effectiveness: +30-40% for highly complex problems

Plan-and-Solve (Explicit Planning Phase)

def plan_and_solve(task):
    """Explicit planning before solving."""

    # Phase 1: Create plan
    plan_prompt = f"""
Task: {task}

Create a detailed step-by-step plan. Don't solve yet, just outline:
1. ...
2. ...
3. ..."""

    plan = llm(plan_prompt)

    # Phase 2: Execute plan
    solve_prompt = f"""
Here's the plan:
{plan}

Now execute it step-by-step:
Step 1:
Step 2:
..."""

    solution = llm(solve_prompt)
    return solution

# Improvement: +15-25% vs basic CoT
# Why: Separating planning from execution clarifies thinking

Contrastive CoT (Reasoning by Comparison)

def contrastive_cot(question):
    """Show both correct AND incorrect reasoning."""

    prompt = f"""
Question: {question}

WRONG approach (and why it fails):
[Model thinks through a common wrong method]

CORRECT approach:
[Model thinks through right method]

Answer: """

    response = llm(prompt)
    return response

# Result: +10-20% accuracy
# Helps model avoid common traps

Cost-Benefit Analysis

When CoT is Worth It

def should_use_cot(task_type, error_cost, question_frequency):
    """Determine if CoT is economically justified."""

    # Variables
    tokens_without_cot = 200
    tokens_with_cot = 600
    accuracy_without = 0.70
    accuracy_with = 0.92
    token_cost = 0.001  # €0.001 per 1000 tokens

    cost_per_question_without = tokens_without_cot * token_cost / 1000
    cost_per_question_with = tokens_with_cot * token_cost / 1000

    # Error cost
    error_rate_without = 1 - accuracy_without
    error_rate_with = 1 - accuracy_with

    annual_volume = question_frequency * 365

    # Annual cost breakdown
    cost_tokens_without = cost_per_question_without * annual_volume
    cost_tokens_with = cost_per_question_with * annual_volume

    cost_errors_without = error_rate_without * annual_volume * error_cost
    cost_errors_with = error_rate_with * annual_volume * error_cost

    total_without = cost_tokens_without + cost_errors_without
    total_with = cost_tokens_with + cost_errors_with

    savings = total_without - total_with

    print(f"Total annual cost (no CoT): €{total_without:.0f}")
    print(f"Total annual cost (with CoT): €{total_with:.0f}")
    print(f"Annual savings: €{savings:.0f}")

    return savings > 0

# Example: 100 math questions/day, €50 cost per error
should_use_cot("math", error_cost=50, question_frequency=100)
# Result: YES (saves €6,570/year)

Per-Task Recommendation Matrix

Task CoT? Reason Token Cost
Math problem ✅ YES 40% accuracy gain +400
Write code ✅ YES 25% error reduction +300
Multiple-choice ⚠️ MAYBE Only for hard questions +100
Factual QA ❌ NO Wastes tokens +200
Summary ❌ NO Adds fluff +150
Classification ❌ NO Just label needed +200
Brainstorm ✅ YES More creative +200
Translation ❌ NO Direct better +100

Prompt Structure for CoT Mastery

Structure 1: Step-by-Step Explicit

prompt = """
Problem: [problem]

Let me solve this step by step:
Step 1 - [specific action]:
Step 2 - [specific action]:
Step 3 - [specific action]:

Therefore, the answer is:"""

Structure 2: Show Your Work

prompt = """
Problem: [problem]

First, I'll identify what we know:
- [fact 1]
- [fact 2]

Next, I'll apply the relevant principle:
[principle]

Calculating:
[calculation shown]

Answer: [final answer]"""

Structure 3: Compare Approaches

prompt = """
Problem: [problem]

Approach 1 (Method A):
[reasoning]
Result: [answer]

Approach 2 (Method B):
[reasoning]
Result: [answer]

The better approach is [Method X] because [reason].
Final answer: [answer]"""

Pitfalls & Solutions

Pitfall 1: CoT Makes Model Verbose Without Improving Accuracy

# WRONG: Just asking for reasoning
prompt = "Solve: What's 15 × 8?"

# Result: "Let me think step by step. 15 × 8 equals... let me see... 15 times 8... [rambling]"
# May get wrong answer AFTER long explanation

# RIGHT: Structure the CoT
prompt = """
Calculate 15 × 8

Breaking it down:
15 × 8 = (10 + 5) × 8 = 80 + 40 = 120

Answer: 120"""

Pitfall 2: Too Much Reasoning Path Exploration

# WRONG: Exploring every possible path
prompt = "Solve this logic puzzle. Consider all possibilities."

# Result: Model explores 50 branches, gets lost

# RIGHT: Bounded reasoning
prompt = """
Solve this logic puzzle.
Evaluate the top 3 most likely approaches.
Pick the best one.

Answer:"""

Pitfall 3: CoT with Trained Models

# Models trained SPECIFICALLY for CoT (e.g., o1) sometimes perform worse
# when explicitly asked for CoT (they already do it internally)

# For extended thinking models:
# USE: Let them think internally
response = client.messages.create(
    model="o1",  # Already does deep reasoning
    max_tokens=10000,
    messages=[{"role": "user", "content": "Hard problem..."}]
)

# DON'T: Ask for explicit CoT (redundant)
# response = client.messages.create(
#     model="o1",
#     messages=[{"role": "user", "content": "Hard problem...\n\nThink step by step..."}]
# )

CoT in Production

class CoTProcessor:
    def __init__(self, client, model="claude-3-5-sonnet"):
        self.client = client
        self.model = model
        self.reasoning_tasks = [
            "math", "logic", "code_analysis", "multi-step"
        ]

    def should_use_cot(self, task_type):
        return task_type in self.reasoning_tasks

    def process(self, question, task_type):
        if self.should_use_cot(task_type):
            prompt = f"{question}\n\nLet me think step by step:"
        else:
            prompt = question

        response = self.client.messages.create(
            model=self.model,
            max_tokens=2000,
            messages=[{"role": "user", "content": prompt}]
        )

        return {
            "answer": response.content[0].text,
            "used_cot": self.should_use_cot(task_type),
            "tokens": response.usage.output_tokens
        }

# Usage
processor = CoTProcessor(client)

result = processor.process(
    "If A > B and B > C, is A > C?",
    task_type="logic"
)

Combining CoT with Other Techniques

CoT + Few-Shot + Self-Consistency (Maximum Quality)

def premium_reasoning(question, critical=True):
    """Maximum quality reasoning for critical decisions."""

    base_prompt = """
Example 1:
Q: 5 + 3 × 2?
Thought: PEMDAS — multiply first. 5 + (3 × 2) = 5 + 6 = 11
A: 11

Example 2:
Q: (5 + 3) × 2?
Thought: Parentheses first. (5 + 3) = 8. Then 8 × 2 = 16
A: 16

Q: {question}
Thought: """

    if critical:
        # Use self-consistency
        answers = []
        for i in range(3):
            response = llm(base_prompt.format(question=question))
            answer = extract_final_answer(response)
            answers.append(answer)

        final_answer = max(set(answers), key=answers.count)
        confidence = answers.count(final_answer) / len(answers)
    else:
        response = llm(base_prompt.format(question=question))
        final_answer = extract_final_answer(response)
        confidence = 1.0

    return {
        "answer": final_answer,
        "confidence": confidence,
        "uses_cot": True,
        "uses_fewshot": True,
        "uses_consistency": critical
    }

Cost vs Benefit:

  • Basic CoT: +3× tokens, +30% quality
  • CoT + Few-shot: +5× tokens, +50% quality
  • CoT + Few-shot + Consistency: +9× tokens, +60% quality (critical only)

Use premium reasoning when:

  • Decision affects people's lives (medicine, finance)
  • Irreversible consequences
  • High monetary value
  • Legal/compliance critical