Prompt Engineering

Controlling Output Format

Lesson 6 of 10

The content of an answer can be right and still be useless if it arrives in the wrong shape. This matters most when a program, not a person, reads the output.

State the format explicitly

List the three main causes of the outage.

Format:
- One bullet point per cause
- Each bullet at most 20 words
- Order them from most to least important
- No introduction and no closing sentence

Models tend to add a friendly opening line and a summary. If you do not want them, say so.

Control length

Be concrete. “Brief” is open to interpretation. “At most 50 words”, “exactly three bullet points” and “two paragraphs” are not.

Word limits are followed approximately, because the model works in tokens, not words. Counts of items, such as “five bullet points”, are followed more reliably.

Match the style of the prompt to the style you want

The formatting of your prompt influences the formatting of the answer. A prompt written in plain paragraphs tends to get paragraphs back. A prompt full of bullet points tends to get bullet points.

Tables

Compare the three plans in a Markdown table with these columns:
Plan | Monthly price | Users included | Best for

JSON for programs

When code will read the answer, ask for JSON and describe the exact structure.

Extract the details from the message below.

Return a JSON object with exactly these keys:
- "name": string
- "email": string, or null if not given
- "order_id": string, or null if not given
- "urgency": one of "low", "medium", "high"

Return only the JSON object, with no other text.

<message>
Hi, this is Chen Wei. My order A-10432 still hasn't arrived and I need it
by Friday for a client meeting. Please help!
</message>

Three details make this dependable:

  • The allowed values are listed.
  • The prompt says what to return when information is missing. Without that, a model may invent a value.
  • The prompt asks for the JSON alone.

Always validate

Even with a careful prompt, treat model output as untrusted input. Parse it, check it and decide what to do when it is wrong.

import json

def parse_reply(reply):
    try:
        data = json.loads(reply)
    except json.JSONDecodeError:
        return None, "not valid JSON"
    missing = {"name", "email", "order_id", "urgency"} - set(data)
    if missing:
        return None, f"missing keys: {sorted(missing)}"
    if data["urgency"] not in {"low", "medium", "high"}:
        return None, f"unexpected urgency: {data['urgency']}"
    return data, None

good = '{"name": "Chen Wei", "email": null, "order_id": "A-10432", "urgency": "high"}'
bad = '{"name": "Chen Wei", "urgency": "urgent"}'

print(parse_reply(good))
print(parse_reply(bad))
print(parse_reply("Sure! Here is the JSON you asked for..."))

When validation fails, a common approach is to send the reply back to the model with the error message and ask it to correct the output.

Structured output features

Most model providers offer a way to enforce a structure: you supply a JSON schema and the service guarantees that the reply matches it. When your provider has this feature, use it. It is more reliable than instructions alone. You still need to check that the values make sense, because a reply can match the schema and be wrong.

Give the model a way out

If every field is required, the model must produce something even when the information is absent. Allow null, an “unknown” option, or an “other” category, so that a missing value is reported as missing.

Practice

Write a prompt that extracts a date, a location and a list of attendees from a meeting invitation as JSON. Decide what each field should contain when the invitation does not mention it.