opncrafter

The Art of Prompt Engineering

Dec 29, 2025 • 20 min read

The model is only as smart as the instructions you give it. A mediocre prompt applied to GPT-4o will produce worse results than an excellent prompt applied to GPT-3.5. Prompt engineering isn't about magic words — it's about understanding how language models process context and exploiting that understanding to constrain model behavior toward reliable, reproducible outputs. Before spending money on fine-tuning or bigger models, exhausting your prompt engineering options almost always yields better ROI.

1. Zero-Shot vs Few-Shot: Show, Don't Tell

❌ Zero-Shot (Unreliable)
"Extract the price from this receipt text."
✅ Few-Shot (Reliable)
"Extract price as a number.
Text: paid $24.99 → Price: 24.99
Text: twenty dollars → Price: 20.00
Text: {input} → Price:"

Few-shot examples aren't just helpful hints — they define the implicit schema of your expected output. The model learns output format, content style, and handling of edge cases from 3-5 well-chosen examples. For classification tasks, include examples of all edge cases you care about. For extraction, show examples with missing values and multiple formats.

2. Chain of Thought: Force Intermediate Reasoning

# Standard prompt (often fails for multi-step problems)
"""
A store sells apples for $1.20 each. A customer buys 5 apples and pays with a $10 bill. 
How much change should they receive?
"""
# LLM might output: "$4.00" (skipping intermediate calculation)

# Chain of Thought prompt (Wei et al. 2022: 17% → 80% accuracy on reasoning benchmarks)
"""
A store sells apples for $1.20 each. A customer buys 5 apples and pays with a $10 bill.
How much change should they receive?

Let's think step by step:
"""
# LLM now outputs:
# Step 1: Calculate total cost: 5 apples × $1.20 = $6.00
# Step 2: Calculate change: $10.00 - $6.00 = $4.00
# Answer: The customer should receive $4.00 in change.

# Zero-shot CoT phrase variants that trigger reasoning:
# "Let's think step by step."
# "Let's work through this carefully."
# "Think out loud before giving your final answer."
# "First, identify what we know. Then, identify what we need. Then solve."

# For GPT-4o+ models: provide explicit reasoning structure
SYSTEM = """You are a financial analyst. For every calculation:
1. State all given information
2. Identify the formula needed
3. Show substitution with units
4. Compute the result
5. Sanity-check by alternative method if possible
Then provide your final answer after the working."""

3. The ReAct Pattern: Reasoning + Acting for Agents

# ReAct (Reason + Act) is the foundation of all agentic frameworks
# LangChain, AutoGPT, and Claude's tool use all implement ReAct under the hood

SYSTEM = """You are an intelligent assistant with access to tools.
For each user request, follow this exact pattern:

Thought: [Your reasoning about what to do next]
Action: [tool_name](argument)
Observation: [tool result - this will be filled in by the system]
... (repeat Thought/Action/Observation as needed)
Final Answer: [your final response to the user]

Available tools:
- WebSearch(query) - Search the web for current information
- Calculator(expression) - Evaluate mathematical expressions
- GetWeather(city) - Get current weather for a city"""

USER = "What's the population-normalized COVID death rate per million for Japan vs France?"

# LLM generates:
# Thought: I need current population and COVID death statistics for both countries.
# Action: WebSearch("Japan total COVID deaths 2024")  
# Observation: [system inserts tool result]
# Thought: Now I need the same for France plus population data to normalize.
# Action: WebSearch("France total COVID deaths 2024 population") 
# Observation: [system inserts tool result]
# Thought: I can now calculate deaths per million for each country.
# Action: Calculator("(Japan_deaths / Japan_population) * 1000000")
# Observation: 247.3
# Final Answer: Japan's COVID death rate is 247 per million, France's is 2,347 per million...

4. Structured Output: Engineering JSON Reliability

from openai import OpenAI
from pydantic import BaseModel
from typing import Optional
import json

client = OpenAI()

# Method 1: JSON Mode (GPT-4o / GPT-4-turbo)
# Guarantees valid JSON but doesn't enforce specific schema
response = client.chat.completions.create(
    model="gpt-4o",
    response_format={"type": "json_object"},  # Enables JSON Mode
    messages=[{
        "role": "system",
        "content": """Extract order details from the user message.
        Return JSON with this exact structure:
        {
            "item": string,
            "quantity": integer,
            "price": float | null,
            "currency": "USD" | "EUR" | "GBP",
            "date_mentioned": string | null
        }"""
    }, {
        "role": "user",
        "content": "I bought 3 books for twenty dollars yesterday"
    }],
)
order = json.loads(response.choices[0].message.content)

# Method 2: Structured Outputs with Pydantic (GPT-4o-2024-08-06+)
# Guarantees EXACT schema adherence — no extra/missing fields
class OrderDetails(BaseModel):
    item: str
    quantity: int
    price: Optional[float]
    currency: str = "USD"
    date_mentioned: Optional[str]

response = client.beta.chat.completions.parse(
    model="gpt-4o-2024-08-06",
    messages=[
        {"role": "system", "content": "Extract order details from the user message."},
        {"role": "user", "content": "I bought 3 books for twenty dollars yesterday"},
    ],
    response_format=OrderDetails,  # Pydantic model enforces schema
)

order: OrderDetails = response.choices[0].message.parsed
print(order.quantity)  # 3 (typed integer, not string!)
print(order.price)     # 20.0 (typed float)

5. Meta-Prompting: Generating Better Prompts

# Meta-prompting: Use Claude/GPT-4o to improve your own prompts

META_PROMPT = """You are an expert prompt engineer specializing in GPT-4o and Claude.
I'll give you a task description. Your job is to write the optimal system prompt for it.

Requirements for the system prompt you write:
1. Specify the persona/role clearly
2. Define exact output format with examples
3. List all edge cases and how to handle them
4. Include validation instructions
5. Be specific about what NOT to do

Task: {task_description}

Write the optimal system prompt:"""

# Example: meta-prompt generates a complete system prompt for customer support
task = "A customer support bot for a SaaS product that extracts bug reports from user emails"
# The meta-prompt will generate a 500-word system prompt covering: classification criteria,
# severity levels, required fields to extract, escalation conditions, tone guidelines

Frequently Asked Questions

How many few-shot examples are optimal?

For most tasks, 3-5 examples covers the distribution of cases models need to understand. Diminishing returns set in quickly: 5 examples often outperforms 20 because the model overfits to the specific examples rather than inferring the underlying pattern. Quality beats quantity — one example demonstrating a tricky edge case is worth more than five normal examples. Exception: for complex extraction with many possible formats (5+ distinct input formats), more examples improve robustness.

When does Chain of Thought NOT help?

CoT helps primarily for tasks requiring multi-step reasoning or decomposition. It doesn't help (and can hurt) for: simple factual retrieval (adding CoT creates more opportunity for hallucinated reasoning), classification tasks (direct classification is often more accurate), and reasoning models like o1/R1 (they already do extensive internal CoT — adding explicit CoT instructions degrades performance by interfering with their internal process).

Conclusion

Prompt engineering is a discipline with measurable impact: few-shot examples dramatically improve consistency, Chain of Thought unlocks reasoning accuracy for complex tasks, ReAct enables reliable tool-using agents, and structured output schemas make LLM responses directly parseable by downstream systems. Before considering fine-tuning, exhaust the prompt engineering toolkit — most production reliability issues are instruction failures, not model capability gaps.

Continue Reading

👨‍💻
Written by

Vivek

AI Engineer

Full-stack AI engineer with 4+ years building LLM-powered products, autonomous agents, and RAG pipelines. I've shipped AI features to production for startups and worked hands-on with GPT-4o, LangChain, LlamaIndex, and the Vercel AI SDK. I started OpnCrafter to share everything I wish I had when learning — no fluff, just working code and real-world context.

GPT-4oLangChainNext.jsVector DBsRAGVercel AI SDK