Introduction
The same AI model can produce a brilliant answer or garbage — and the difference is usually the prompt. Prompt engineering isn't magic words; it's a *developer skill*: giving a model the context, format, and constraints it needs to do your job.
This guide covers the six techniques that matter in real applications, each with working Python code using the Mistral API from the chatbot tutorial (the same patterns work with local Ollama models).
Setup (used by every example)
import requests
def ask(messages, temperature=0.7):
response = requests.post(
"https://api.mistral.ai/v1/chat/completions",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"model": "mistral-small-latest",
"messages": messages,
"temperature": temperature},
timeout=60,
)
return response.json()["choices"][0]["message"]["content"]Every technique below is just a smarter messages list.
Technique 1: System prompts — set the role
The system message is the model's job description. Vague role, vague output:
# weak
messages = [{"role": "user", "content": "Explain recursion"}]
# strong — audience, style, and length are specified
messages = [
{"role": "system", "content":
"You are a Python tutor for teenage beginners. "
"Explain concepts using simple analogies and one short code example. "
"Never exceed 150 words."},
{"role": "user", "content": "Explain recursion"},
]Same model, completely different usefulness. Audience, format, and length — the three things a system prompt should almost always pin down.
Technique 2: Specify the output format explicitly
If your code needs to parse the answer, tell the model the exact shape:
prompt = """Analyze this review and respond with ONLY a JSON object:
{"sentiment": "positive" or "negative" or "neutral", "score": 0-10}
Review: """ + reviewWithout that instruction, you get chatty prose like "Sure! This review seems..." — unparseable. With it, json.loads() works. This single technique is what makes the AI flashcard generator possible.
Always pair format requests with a fallback — models occasionally wrap JSON in prose, so extract with a regex before parsing (the flashcard tutorial shows the pattern).
Technique 3: Few-shot examples — show, don't tell
One example of the input-output you want teaches the model more than a paragraph of rules:
prompt = """Extract the city from each message.
Message: "I'm moving to Chennai next week"
City: Chennai
Message: "Is the Bangalore office open?"
City: Bangalore
Message: "What's the weather in Jaipur like?"
City:"""The model completes the pattern. Two or three examples ("few-shot") turn a vague task into a fill-in-the-blank exercise — the most reliable trick for extraction and classification tasks.
Technique 4: Give context — the model can't read minds
# the model doesn't know your app exists
messages = [{"role": "user", "content": "Why did it crash?"}]
# feed the actual error and code
messages = [
{"role": "system", "content": "You are a Python debugging assistant."},
{"role": "user", "content":
f"This code crashes:\n{code}\n\nError:\n{error_message}\n"
"Explain the cause in one paragraph, then the fix."},
]The model has no memory of your project, your data, or yesterday's conversation — every request must carry the context it needs. In chat apps, that means sending the message history (the chatbot tutorial's core pattern). In tools like the PDF chat, it means retrieving relevant chunks first.
Technique 5: Chain of thought — ask it to think in steps
For anything involving reasoning or math, jumping straight to the answer invites errors. Ask for the steps:
prompt = """A store applies a 20% discount, then 18% tax on the discounted price.
The original price is 2000 rupees. What is the final price?
Think step by step, then give the final answer on a new line as: FINAL: amount"""The model works through discount, then tax, then total — landing on the right answer far more reliably than with a one-line prompt. The FINAL: marker also makes the answer extractable for your code while keeping the reasoning visible.
Technique 6: Temperature — the creativity dial
Temperature (0 to 1) controls randomness:
| Task | Temperature | Why |
|---|---|---|
| JSON output, classification, flashcards | 0.0–0.3 | Consistency beats creativity |
| General chat, explanations | 0.5–0.7 | Balanced |
| Brainstorming, names, stories | 0.8–1.0 | Variety wanted |
The flashcard generator uses 0.3; a story-writing app would use 0.9. Match the dial to the task.
Common Mistakes (and their fixes)
Key Concepts
What to Try Next
FAQ
Is prompt engineering a real skill or hype?
A real, learnable developer skill — the difference between a demo and a product is almost always prompt + output handling. That said, it's a skill *on top of* coding, not a replacement for it.
Do these techniques work on local Ollama models?
Yes — system prompts, few-shot, and format specification all apply. Small models need *tighter* formats and lower temperatures to stay reliable.
Why did the model ignore my format instruction?
Models drift, especially on long prompts. The professional pattern is always: specify the format and code a tolerant extractor (regex for the JSON block, fallback on failure). Never parse raw chat text and hope.