Lab 3 — Prompt Engineering¶
⏱️ ~25 min
Turn a vague prompt into a reliable one: zero-shot → few-shot → structured output.
In [ ]:
Copied!
import os, getpass
PROVIDER = "openai" # or "anthropic"
if PROVIDER == "openai":
!pip install -q openai
if not os.environ.get("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API key: ")
else:
!pip install -q anthropic
if not os.environ.get("ANTHROPIC_API_KEY"):
os.environ["ANTHROPIC_API_KEY"] = getpass.getpass("Anthropic API key: ")
def chat(messages, temperature=0.7, model=None):
if PROVIDER == "openai":
from openai import OpenAI
client = OpenAI()
resp = client.chat.completions.create(
model=model or "gpt-4o-mini", messages=messages, temperature=temperature)
return resp.choices[0].message.content
else:
from anthropic import Anthropic
client = Anthropic()
system = "".join(m["content"] for m in messages if m["role"] == "system")
turns = [m for m in messages if m["role"] != "system"]
resp = client.messages.create(
model=model or "claude-3-5-haiku-20241022", max_tokens=1024,
temperature=temperature, system=system or None, messages=turns)
return resp.content[0].text
import os, getpass
PROVIDER = "openai" # or "anthropic"
if PROVIDER == "openai":
!pip install -q openai
if not os.environ.get("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API key: ")
else:
!pip install -q anthropic
if not os.environ.get("ANTHROPIC_API_KEY"):
os.environ["ANTHROPIC_API_KEY"] = getpass.getpass("Anthropic API key: ")
def chat(messages, temperature=0.7, model=None):
if PROVIDER == "openai":
from openai import OpenAI
client = OpenAI()
resp = client.chat.completions.create(
model=model or "gpt-4o-mini", messages=messages, temperature=temperature)
return resp.choices[0].message.content
else:
from anthropic import Anthropic
client = Anthropic()
system = "".join(m["content"] for m in messages if m["role"] == "system")
turns = [m for m in messages if m["role"] != "system"]
resp = client.messages.create(
model=model or "claude-3-5-haiku-20241022", max_tokens=1024,
temperature=temperature, system=system or None, messages=turns)
return resp.content[0].text
1. The vague prompt (bad)¶
In [ ]:
Copied!
review = "the app keeps crashing when I upload a big file and im on wifi"
print(chat([{"role": "user", "content": f"Classify this: {review}"}]))
review = "the app keeps crashing when I upload a big file and im on wifi"
print(chat([{"role": "user", "content": f"Classify this: {review}"}]))
2. Add a system prompt + clear task (better)¶
In [ ]:
Copied!
system = {"role": "system", "content":
"You are a support-ticket triager. Classify the ticket's category and severity."}
print(chat([system, {"role": "user", "content": review}]))
system = {"role": "system", "content":
"You are a support-ticket triager. Classify the ticket's category and severity."}
print(chat([system, {"role": "user", "content": review}]))
3. Few-shot — show the exact shape you want¶
In [ ]:
Copied!
few_shot = [
{"role": "system", "content": "Classify support tickets. Reply exactly like the examples."},
{"role": "user", "content": "login button does nothing on safari"},
{"role": "assistant", "content": "category=auth; severity=high"},
{"role": "user", "content": "the font on the about page looks a bit small"},
{"role": "assistant", "content": "category=ui; severity=low"},
{"role": "user", "content": review},
]
print(chat(few_shot, temperature=0))
few_shot = [
{"role": "system", "content": "Classify support tickets. Reply exactly like the examples."},
{"role": "user", "content": "login button does nothing on safari"},
{"role": "assistant", "content": "category=auth; severity=high"},
{"role": "user", "content": "the font on the about page looks a bit small"},
{"role": "assistant", "content": "category=ui; severity=low"},
{"role": "user", "content": review},
]
print(chat(few_shot, temperature=0))
4. Structured output — JSON your code can parse¶
In [ ]:
Copied!
import json
json_prompt = [
{"role": "system", "content":
'Return ONLY valid JSON: {"category": str, "severity": "low|medium|high"}. No prose.'},
{"role": "user", "content": review},
]
raw = chat(json_prompt, temperature=0)
print(raw)
print("Parsed:", json.loads(raw))
import json
json_prompt = [
{"role": "system", "content":
'Return ONLY valid JSON: {"category": str, "severity": "low|medium|high"}. No prose.'},
{"role": "user", "content": review},
]
raw = chat(json_prompt, temperature=0)
print(raw)
print("Parsed:", json.loads(raw))
Takeaway: each step removed ambiguity. Few-shot + structured output makes the model's response safe to feed into code.
✅ Did it work?¶
- The few-shot step produced the exact
category=...; severity=...shape from the examples. - The final JSON step printed valid JSON and
json.loadsparsed it into a dict with no error.