ai-assisted programming · lecture
The slides in Microsoft's web viewer, with every slide's text below. Download the PowerPoint to present it with its animations.
View slidesDownload PowerPoint
No slides above? Use View slides, or Download PowerPoint.
All 53 slides.
how you ask, and what the model can see
PROMPT · A
write a function to parse a date string
PROMPT · B
Write a Python function parse_date(s: str) -> date.
Accept "2026-08-12" and "12/08/2026" (day first). Raise ValueError on anything else. No external libraries.
A prompt is not a request. It is a specification. Everything you leave unspecified, the model decides for you: silently, and from whatever was most common in its training data.
// part 1: how you ask
// part 2: what the model can see
// part 1 · section 1 of 3
What the model actually reads, and a checklist for prompts that leave nothing to guess
Prompting is writing the instructions and information you give an AI model so that it produces the result you want.
[Picture: Real token splits from OpenAI's o200k_base tokenizer: def calculate_median(numbers): is 6 tokens (def | calculate | _m | edian | (numbers | ):); the date 12/08/2026 is 6 tokens (12 | / | 08 | / | 202 | 6); KeyError: 'unit_price' is 7 tokens (Key | Error | : | ' | unit | _price | ')]
[Chart: tokens per 100 words, by kind of text. Tokens per 100 words (English prose: 125.2, JSON: 158.1, Python source: 191.3, Python traceback: 267.7)]
// source: counted with OpenAI's o200k_base tokenizer on samples of each kind
// OpenAI's rule of thumb: 1 token ≈ 4 characters ≈ ¾ of an English word
// the context window: everything the model sees on one request
System prompt
Written by the assistant's makers
Standing instructions
AGENTS.md, read on every request
Conversation so far
Grows every turn, dead ends included
Pasted + tool results
Your pastes, files the agent read, web searches
free
Space left
outside
Your repo, ticket, intent
Invisible unless something puts it in
| Letter | Example | |
|---|---|---|
| S | Specific goal | "Parse a date string into a date" |
| P | Programming language / file | "Python 3.12, in utils/dates.py" |
| E | Example, input to output | "2026-08-12" → date(2026, 8, 12) |
| C | Constraints | "No external libraries. Raise on bad input" |
// any checklist works; what matters is covering all four, every time
PROMPT · B
Write a Python function parse_date(s: str) -> date.
Accept "2026-08-12" and "12/08/2026" (day first). Raise ValueError on anything else. No external libraries.
Is
12/08/2026in August or December? Prompt A leaves the model to guess. B is better because it makes that decision, not because it is longer.
// tested Sept 2026: given prompt A, three current models read it as 8 December (month first), and none asked
Python 3.12no new dependenciesunder 200msno eval()No database schema changes
No error handling yet
Do not reformat the rest of the file
Assistants often change more than you asked. Bugs hide in those extra changes, because nobody expected them, so nobody checked them
PROMPT
here's my file, fix the bug in calculate_total
1
Just the one-line fix
2
The fix, plus changes you did not ask for
3
The whole file, reformatted, with type hints and error handling
Answer: none of them reliably. It depends on the model, and on the run
Tested Sept 2026: the same prompt changed 1 line with one model, 3 with another, and 11 then 4 with a third
[Chart: lines each model changed to fix a one-line bug: two runs of the vague prompt and one of the narrow prompt. vague prompt, run 1 (GLM-5.3: 1, Gemini 3.6 Flash: 3, Gemini 2.5 Flash: 11); vague prompt, run 2 (GLM-5.3: 1, Gemini 3.6 Flash: 3, Gemini 2.5 Flash: 4); narrow prompt (next slide) (GLM-5.3: 1, Gemini 3.6 Flash: 1, Gemini 2.5 Flash: 1)]
// source: tested Sept 2026 through each vendor's API, no system prompt; every reply fixed the bug
PROMPT
Fix only the off-by-one in calculate_total.
Change nothing else: no formatting, no type hints, no error handling.
Show me a diff, not the file.
You will read a one-line change carefully, but only skim a whole file. Asking for just the fix, as a diff, is what makes a real review possible.
// tested Sept 2026: a one-line diff from all three models
// part 1 · section 2 of 3
Three well-known techniques, what the evidence says about each, and when to use which
| Technique | What it changes | Reach for it when |
|---|---|---|
Persona "You are a security reviewer" |
Tone, audience, what the model focuses on | You want a lens: security, performance, a beginner |
Chain-of-thought "Think step by step first" |
Shows the steps, not just the answer | You need to check the reasoning, not only the result |
Few-shot Two examples, then yours |
A “shot” is one worked example: an input and its exact output. Give 2 or 3 | The output format must be exact |
// each technique fixes one kind of problem; use it only for that problem
Use a persona to set the viewpoint ("review this as a security auditor"), not to make answers more correct
[Chart: percentage points of accuracy gained by asking for step-by-step reasoning, 2022 models against 2025 reasoning models. Accuracy gained by asking for step-by-step reasoning (PaLM 540B 2022, maths: 39.0, text-davinci-002 2022, maths: 30.3, o3-mini 2025, science: 2.9, o4-mini 2025, science: 3.1, Gemini 2.5 Flash 2025, science: -3.3)]
// source: Wei et al. 2022 and Kojima et al. 2022 (GSM8K); Meincke et al., Wharton, 2025 (GPQA Diamond)
You need a report as CSV: fixed header, fixed column order, no commentary. The model keeps adding a sentence of explanation above the data.
PROMPT
One CSV line per bug report. Header: severity,component,summary.
"Login 500 when the password has an emoji" → high,auth,500 on emoji password
"Typo on the about page, and in the footer" → low,web,"typo on about page, footer"
Now: "Checkout total wrong when a coupon is applied twice"
REPLY
high,checkout,coupon applied twice miscounts total
// if code will read the output, use the API's structured-output option (a JSON schema) instead
// part 1 · section 3 of 3
When rewording stops helping, the model is usually missing information
What no wording can do: give the model a fact it was never shown
e.g. no rewording of “fix it” tells the model your data uses the key price, not unit_price
THEN · 2023
Tiny wording changes swung the results
Swapping a colon, a newline or capital letters moved one model's score by up to 76 points out of 100
So people hunted for magic phrasings
NOW
Models understand sloppy requests
Rewording the same request changes little
Polishing the wording is no longer where the gains are
So when an answer is wrong, first ask: what does the model not know?
| Prompt engineering | Context engineering | |
|---|---|---|
| You ask | How do I phrase this? | What does the model need to see? |
| You work on | Wording, structure, examples | Files, errors, examples, history |
| Fails when | The request is ambiguous | The model lacks a fact it can't guess |
| Covers | One message | Everything in the window, every turn |
// Anthropic: "the smallest possible set of high-signal tokens" for the task
Context engineering is choosing what the model gets to see: which files, errors, examples and past messages go into its window, and which stay out.
SCENARIO
You asked the model to fix a bug, then rewrote the request three times, each clearer than the last. The answer is still wrong in the same way.
1
The model is not good enough: switch to a bigger one
2
Keep rewording until you find the magic phrasing
3
The model is missing a fact it cannot guess
4
Turn up the randomness for a different answer
Answer: 3. The model is missing a fact it cannot guess
If clearer wording changes nothing, wording was not the problem. Rewording adds no new facts, and a bigger model or more randomness has the same gap.
Fix: give the model what it is missing, e.g. the file, the error message or the failing test.
Wrong because I asked badly, or because the model doesn't know something?
You asked badly
HOW YOU CAN TELL
WHAT TO DO
Rewrite the prompt: fill the SPEC gaps
The model lacks a fact
HOW YOU CAN TELL
WHAT TO DO
Paste in the error, file, schema or failing test
Rule of thumb: if you can name the fact the model is missing, paste it in. If not, it's the wording.
PROMPT
Before writing any code, ask me up to five questions about anything you would otherwise have to guess. Then stop and wait for my answers.
// then send your answers back: together with the request, they are a complete SPEC
// a good prompt directs what the model can already do; it cannot add knowledge or ability
Part 2 answers: when you leave a gap, how does it get filled, and what, exactly, is in front of the model when it answers?
// part 2 · section 1 of 4
Where the model's guesses come from, and what is actually in the window when it answers
A vague prompt's guesses look reasonable, so the wrong ones are hard to spot. The fix: write the answer down once.
# AGENTS.md
- Python 3.12; run the tests with `pytest -q`
- Dates are day first: 12/08/2026 is 12 August
- Money is Decimal, never float
- Never add a dependency without asking
What it is
Plain text in your project. The assistant reads it with every request.
What goes in it
Rules you keep retyping: commands, formats, limits, things to avoid.
What it is called
It depends on the tool:
AGENTS.md
CLAUDE.md
.github/copilot-instructions.md
Keep it short and current.
The model follows an outdated rule just as strictly as a correct one.
Your editor's assistant. A project of forty files. You ask about a function in a file you have not opened.
// if the model "doesn't know" something, that thing was not in the window
// part 2 · section 2 of 4
The same error twice: first on its own, then with the code it came from
FAILED tests/test_orders.py::test_total - KeyError: 'unit_price'
PROMPT
my test fails with KeyError: 'unit_price', fix it
.get() with a default value, so the missing key stops raisingREPLY · Gemini 2.5 Flash, Sept 2026, excerpt
Use dict.get() with a default value (Recommended). This is the most Pythonic and safest way to access dictionary keys that might not exist.
assert 0 == 10.0
def order_total(order: dict) -> float:
return sum(item["unit_price"] * item["qty"] for item in order["items"])
def test_total():
order = {"items": [{"price": 2.50, "qty": 4}]}
assert order_total(order) == 10.0
price, but the function expects unit_price. Each is fine alone; they just don't match| Put in | Leave out |
|---|---|
| The error, verbatim: never your paraphrase of it | The rest of the file |
| The function that raised | Files that are not on the path to the error |
| The input that triggered it: the fixture, the request | Your guess at the cause: give the model the evidence and let it find the cause |
| The test, the schema, the config it depends on | The forty-minute conversation you had about it |
// paste the real code and error, not a summary; include everything relevant and nothing else
// part 2 · section 3 of 4
Leaving things out on purpose, and starting fresh when a conversation goes in circles
[Chart: accuracy at finding one fact as the input grows from 1K to 128K tokens. GPT-4o (1K: 98.1, 4K: 95.7, 8K: 89.2, 16K: 81.6, 32K: 69.7, 128K: 56.0); GPT-4.1 (1K: 95.6, 4K: 91.7, 8K: 87.5, 16K: 84.9, 32K: 79.8, 128K: 64.7)]
// source: NoLiMa, Adobe Research, ICML 2025 (GPT-4.1 from its repository)
// in 2023 models often missed facts in the middle of long input; that is less true now, but longer input still gives worse answers
// a long conversation slowly fills up with old attempts you no longer want the model to use
Forty minutes in, and each answer is a variation on the last one.
PROMPT
New conversation. Here are order_total, its test, and the fixture it uses.
A default value was already tried and is wrong: the test then fails as 0 == 10.0.
Propose the minimal fix, and state which key name you treat as canonical.
def test_parse_date_day_first():
assert parse_date("12/08/2026") == date(2026, 8, 12)
// a test written after the code only checks what the code already does, bugs included
| The gap | What it looks like | The fix |
|---|---|---|
| Under-specified | Code that looks fine but is full of choices you never made | Make the decision yourself: add one line to the prompt |
| Under-informed | Sounds right but is wrong for your code; rewording does not help | Put the file, the error, the test in the window |
| Over-loaded | Generic, vague, or fixated on the wrong part | Remove what is not needed |
Asking "bad wording or missing information?" tells the first two apart. The third, pasting too much, is rarely suspected because it feels like being thorough.
// part 2 · section 4 of 4
How prompting changed since 2022, and why it still matters when agents work for hours
// source: METR, task length agents complete half the time, measured in human working time, 2025–2026
Your job moved from choosing the right words to deciding what gets built, and checking it
An agent that works for hours still starts from a prompt. It is just longer: a written plan, plus the standing instructions it reads every time.
Is it wrong because I asked badly, or because the model doesn't know something? No amount of rewording adds information.