Generative AI
By the end of this lesson
Describe what generative models produce and how that differs from classification.
A spam filter decides. A model that writes produces. That sentence is the distinction, and the engineering consequences of it run through everything else in this course.
A classifier picks from a set of options you defined. Four categories in, one of four categories out. A generative model produces new content one piece at a time, and the set of things it could produce is effectively unlimited. You cannot enumerate the possible outputs, which means you cannot test them all, and you cannot assume the shape of what comes back.
The same expense claim, handled two ways:
| Classification | Generation | |
|---|---|---|
| Question it answers | Which of these four categories is this? | Write the employee an explanation of why it was rejected |
| Output space | Closed — one of a fixed list | Open — any text |
| Checking it in code | Compare against the expected label | No single correct answer to compare against |
| Typical failure | The wrong label, and you can count how often | Fluent text that is subtly wrong, and counting is harder |
| Cost per call | Usually tiny, often running on your own hardware | Paid per piece of text in and out |
CATEGORIES = ["travel", "meals", "software", "equipment"]
def categorise(description: str) -> str:
"""Closed output. The return value is always one of four strings."""
return classifier.predict([description])[0]
def draft_rejection_note(claim: dict, reason: str) -> str:
"""Open output. The return value is text that did not exist before."""
response = client.chat.completions.create(
model="gpt-4.1-mini",
messages=[
{
"role": "system",
"content": (
"You write short, plain, courteous notes to employees about "
"expense claims. Two sentences. State the reason given. "
"Do not invent policy."
),
},
{"role": "user", "content": f"Claim: {claim['description']}. Reason: {reason}"},
],
)
return response.choices[0].message.content- categorise has a return type you can reason about. Four values are possible, so a test can cover the behaviour and a bug is visible as the wrong label.
- draft_rejection_note returns a string, and that is all its type tells you. It might be two sentences as asked. It might be five. It might contain a policy detail nobody supplied.
- The system message is where you constrain a generative call — length, tone, and an explicit instruction not to invent policy. Constraints in words are guidance, not enforcement, which is why later lessons validate the result in code.
- The full mechanics of this call — the client, the key, timeouts, retries — come in "Your First Model Integration". For now, notice only the shape: instructions plus data in, free text out.
Where generation earns its cost in the internal knowledge assistant:
- Answering a policy question in a sentence, using document extracts you supply
- Summarising a long handbook section down to what the person asked about
- Rewriting a dense paragraph of finance wording into plain English
- Turning a messy claim description into structured fields
- Drafting a reply that a human reads before it is sent
Summary
- Classification chooses from a fixed set of options; generation produces new content piece by piece
- A generative model's output space is open, so you cannot enumerate, test or assume the shape of what comes back
- Prefer a classifier for closed decisions — cheaper, faster, and closed by construction
- When you do generate, constrain the request in words and validate the result in code
Practice
Attempt each one before opening the solution. Getting it wrong first is how the idea sticks.
Think about it
Classify, generate, or neither
Decide which approach fits each of these, and say why: routing an incoming email to the right team; writing the first draft of a reply to that email; extracting the invoice number from the email body; deciding whether the email is urgent.
Show solution
Routing to a team is classification. The set of teams is fixed and you have years of routed email as examples.
Drafting a reply is generation. There is no correct answer to compare against, so a human should read it before it goes out.
Extracting an invoice number is neither, if the format is reliable — a pattern match is exact, free and instant. If invoice numbers arrive in a dozen inconsistent shapes across suppliers, generation with validation becomes reasonable, because you can check the extracted value against your records.
Urgency is classification, but pause on who defines it. Unless someone has labelled what urgent means in your organisation, you do not have a target to learn. This is the common case where the data problem is the real problem.
Saved in this browser only.