PHASE 01 · FOUNDATIONS

Talk to an LLM

Goal: Make your first API call and develop intuition for how LLMs respond.

What this is

An LLM is just an HTTP API. You send a list of messages (a system message describing who the assistant is, plus user/assistant turns) and you get back a generated message. That's the whole thing.

The same model can produce wildly different outputs depending on the system prompt (its instructions), temperature (how random the sampling is), and max tokens (how long the reply can be). Before you build anything fancy, you need a gut feel for how these knobs change behavior.

You'll also learn that different models have very different tradeoffs. A small, cheap model (Claude Haiku, GPT-4o-mini) is fast but less capable. A frontier model (Claude Sonnet/Opus, GPT-4o) is smarter but slower and ~30× more expensive. Picking the right one is a real engineering decision.

The plan

  1. Sign up for an API account (Anthropic or OpenAI). Generate a key. Store it in a .env file — never commit it.
  2. Install the SDK: pip install anthropic or pip install openai.
  3. Write a ~20-line Python script: read a prompt from sys.argv, send it to the API, print the response.
  4. Add a --model flag. Run the same prompt against a small model and a frontier model. Note: response quality, latency, tokens used, dollar cost.
  5. Add --system and --temperature flags. See how a sharp system prompt ("You are a terse senior engineer") completely changes the output.

Ask your coding assistant

  • What's the messages format for the Anthropic / OpenAI SDK? Show me a minimal example.
  • How do I load API keys safely with python-dotenv?
  • What does temperature actually do — explain in one paragraph.
  • Help me count input and output tokens before sending so I can predict cost.
  • What's a system prompt and why does it matter?

What you'll have when you're done

  • You can call any LLM from the terminal in under a minute.
  • You've felt the speed/quality/cost triangle in real numbers.
  • You understand what a system prompt is and why it changes everything.
  • You have a reusable llm_chat.py you'll build on for the next 10 phases.

Deliverable

llm_chat.py — A CLI that takes a prompt, optional model and system message, and returns a response.

Concepts unlocked: API keys · messages format · model selection · token counting

Intuition

Forget the hype for a minute. You've already used a tiny language model today — your phone's keyboard. You type a few words and it guesses the next one:

That's the whole trick — just small. Your keyboard learned from the texts you've typed: a few years of messages, maybe a million words if you're chatty. Now scale that up — and "scale" here isn't an adjective, it's a number. Stack the three sizes next to each other:

  • Every message you've ever typed — roughly a million words. That's your keyboard's entire education.
  • All of English Wikipedia — about 4½ billion words. Thousands of times more than your texts.
  • A frontier LLM's training datatrillions of words: millions of books, huge slices of the public web, mountains of code. To this thing, all of Wikipedia is a rounding error — and it's read roughly a million times more text than every message you've ever typed. Reading a book a day, you'd need tens of thousands of lifetimes to catch up.

To predict the next word well across all of that — legal contracts, Python code, love poems, physics forums — the guesser can't get by on habits like your keyboard does. It has to soak up grammar, facts, reasoning patterns, coding style, the shape of an argument. Not because anyone taught it those things — because they're the only way to keep winning the guessing game at that scale.

Push it far enough and something strange happens: "just guess the next word" becomes good enough to write an essay, fix a bug in your code, or explain quantum tunneling — because for each of those, producing the right next word, over and over, is the task.

The one-line intuition. An LLM is autocomplete that read the internet — a next-word guesser scaled up until the guessing turned into something that feels like intelligence. Not a database, not a search engine, not a mind.

Two things to hold onto

1. It's a tool, not a being. It has no memory of you between requests, no goals, no awareness. Each time, it's text in, text out, in isolation — the "conversation" is an illusion you create by re-sending the history every time. That's why it can't "remember" yesterday unless you remind it.

2. It predicts what's likely, not what's true. It completes text the way the internet would, not the way reality is. Usually those line up; when they don't, you get a fluent, confident, wrong answer — a hallucination. Fixing that is the whole point of Phase 2.

Keep "autocomplete that read the internet" in your head. Everything else in this course — prompts, tools, memory, agents — is just clever ways to use that one trick.

What is an LLM?

We've got the gut feel — now let's be exact about what it is. An LLM is a math function: the f(x) kind from school, where you put something in and get something out, and the same input always gives the same output. Here's the whole thing, start to finish:

Read it left to right. Computers only do math, so your words are turned into numbers first. Those numbers run through the function — and here's the important part: the function is billions of numbers it learned by reading text, not rules a human wrote. Out come more numbers — a score for every possible next word — and the top one is turned back into text.

Notice it never "looks up" Paris in a database. It learned that across everything it read, Paris is overwhelmingly the most likely word after that phrase. To an LLM, knowledge is just very confident prediction — which is also why shaky knowledge comes out as a confident-sounding guess.

The whole thing. An LLM is a math function with billions of learned numbers inside. Words in → numbers → function → numbers → a word out. Everything in this course is built on that one pass.

That trained function has a name: a model. It's the word you'll see all over this course ("which model?", "Claude is a model") — and now you know exactly what it means: a big math function full of numbers learned from text.

One thing to file away: the function part is perfectly repeatable — the same words in give the same scores out, every time. Any randomness you see happens afterward, in a separate step that picks which of the high-scoring words to actually use.

But notice what this picture produces: exactly one word. A chatbot writes whole paragraphs. The gap between "one word out" and "an essay out" is closed by a single, almost embarrassingly simple trick — and that's the next section.

The prediction loop

We just watched one prediction — one word out. To get a whole sentence, you do the obvious thing: append that word and ask again. Predict, append, predict, append — a loop, with the model reading its own growing text each time.

In picture form, the whole engine is three boxes — and one arrow that bends back on itself. That bent arrow is the entire idea: the output gets glued onto the input, and the model reads its own last word as part of the next question:

This is autoregressive generationauto because it feeds on its own output, regressive because each step looks back at everything so far. The model never plans the whole sentence — it just keeps answering "what's next?" one piece at a time. It stops when it predicts a special end-of-text token (or you cap the length).

Word vs token. The loop actually runs on tokens, not words. A token is a chunk of text — often ~4 characters or a word-piece. cat is one token; windowsill might be two. When people talk about cost and context limits, they're counting tokens.

How does it choose among the likely words? Always grab the single most likely one and you get safe, predictable text; allow a little randomness and you get creativity. That dial is called temperature — we'll get to it soon.

What is a prompt?

We just saw the model only ever continues text. So here's a simple way to think about a prompt: it's just the text you hand the model to continue. You set up the start so the most likely continuation is the answer you want.

Type The capital of France is and the likeliest continuation is Paris. Type Write a haiku about autumn: and the likeliest continuation is a haiku. You're not commanding the model — you're steering its prediction by choosing the setup.

In practice a prompt has two layers. The system prompt sets persona and rules for the whole conversation ("You are a terse senior engineer"); the user message is the specific ask. Both are just text placed in front of the model's prediction. (If you're wondering whether the system prompt "sticks" between messages — good instinct; the next section shows exactly how it travels.)

What "prompting" really is. Prompting isn't magic words. It's arranging the text so your desired answer becomes the most likely continuation. That's the entire skill — and the rest of this course is increasingly clever ways to set up that text (with your data, with tools, with memory).

Reaching the model

We keep saying "send the model some text" — but where does it actually go? For the best models, not your laptop. Two reasons: they're enormous (far bigger than a laptop can comfortably handle), and the companies that built them don't hand out the model file, so you can't download Claude or GPT. Instead you reach them through an API: you send your text over the internet and it sends the answer back. Same model — you're just talking to it across the web instead of running it yourself.

Wait — can't I run a model on my own computer?. Yes, actually — just not the giant ones. There are smaller open models (Llama, Mistral, Gemma) you can download and run right on your laptop with a tool like Ollama, fully offline. They're less capable than frontier models like Claude, but they genuinely run on your machine. "It only lives in the cloud" isn't a hard rule — we just use an API here so you're always working with a top-tier model.

The input is a list of messages and the output is the generated message. That's the entire interface you build on for the rest of the course.

Here's what that exchange looks like as real code — and this is the first code in the whole course, so let's be clear: you never have to write this yourself. Your coding assistant writes it for you in the Build section at the end of this phase. Don't parse the syntax; just notice the shape — a list of messages goes in, one message comes back out:

from anthropic import Anthropic

client = Anthropic()  # reads ANTHROPIC_API_KEY from your environment

msg = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=512,
    system="You are a terse senior engineer.",
    messages=[{"role": "user", "content": "Explain a hash map in two sentences."}])

print(msg.content[0].text)

Three lines are worth spotting, because they're the three ideas you already know: model picks which model answers, system is the system prompt from last section, and messages is the conversation so far. Everything else — Anthropic(), .content[0].text — is plumbing that unpacks the envelope the reply arrives in. Plumbing is your assistant's job, not yours.

The messages format. Every turn is {"role": ..., "content": ...} with role user or assistant. The system prompt rides alongside as its own field. A multi-turn chat is just this list growing — you resend the whole history every time, because the model has no memory: each request starts fresh. The "memory" is you, re-sending the transcript.

The three knobs

So far you've sent the model some text and gotten a reply. But every request carries a few settings too — small dials that change how the model answers, even when your text is exactly the same. Three of them matter most. Here's what each one does.

  • System prompt — the rules and personality you set for the whole chat. It's the biggest influence on how the model behaves. "You are a terse senior engineer" produces a completely different reply than the default.
  • Temperature — how much randomness in the next-token pick. 0 = always the top token (repeatable, good for facts/code); higher = more varied (good for brainstorming).
  • Max tokens — a hard cap on how long the reply can be. Too low and answers get cut off mid-sentence.

Temperature is the easiest one to see. It reshapes those next-word scores from earlier: a low temperature narrows them to one clear winner; a high temperature flattens them so more words are in play:

Default to low for anything that must be right. If you're extracting data, writing code, or answering factual questions, use a low temperature. Save the high settings for brainstorming. A "creative" temperature on a SQL generator just gives you creative bugs.

One choice rides on every request that's bigger than any of these three dials — and we've been quietly defaulting it this whole time. That's next.

Picking a model

That bigger choice is which model to use — the model= line in every request. They're not all the same, and no model is best at everything. Picture a triangle with a corner for each thing you care about: speed, quality, cost. Every model lives somewhere on that triangle, and moving toward one corner means moving away from another:

You can't have all three corners at once — a model that's the smartest and the fastest and the cheapest doesn't exist. So picking a model is really answering one question: which corner does this task actually need?

  • Small & cheap (Claude Haiku, GPT-4o-mini) — fast and inexpensive, less capable. Great for classification, extraction, high-volume simple calls.
  • Frontier (Claude Sonnet / Opus, GPT-4o) — smarter, slower, can cost ~30× more per token. Worth it for hard reasoning, code, and agents.
  • The move — start on a strong model to prove the task is even possible, then drop to the smallest model that still passes.

That's the whole game. For a simple, high-volume task, a small model is almost as good for a tiny fraction of the cost. For a genuinely hard reasoning task, the frontier model earns its price. The catch is knowing which task you've got — and you only really know by measuring.

You can't pick blind. "Smallest model that still passes" assumes you can measure passes. You can't eyeball that reliably — which is exactly why Phase 3 builds an eval harness. For now, just feel the difference: run the same prompt on a small and a frontier model and compare quality, latency, and cost.

Build llm_chat.py

Time to build the deliverable — but you won't type it. You'll describe it to your coding assistant and run what it produces: a tiny command-line tool that takes a prompt (plus optional model, system, and temperature) and prints the reply. Every later phase builds on this file.

Don't just run it — read it. Here's roughly what it'll produce, and what each part is doing:

# llm_chat.py — your first reusable LLM call
import sys, argparse
from anthropic import Anthropic

client = Anthropic()  # ANTHROPIC_API_KEY from your .env

def chat(prompt, model="claude-sonnet-4-6", system=None, temperature=1.0):
    msg = client.messages.create(
        model=model,
        max_tokens=1024,
        temperature=temperature,
        system=system or "You are a helpful assistant.",
        messages=[{"role": "user", "content": prompt}])
    return msg.content[0].text, msg.usage

if __name__ == "__main__":
    ap = argparse.ArgumentParser()
    ap.add_argument("prompt")
    ap.add_argument("--model", default="claude-sonnet-4-6")
    ap.add_argument("--system")
    ap.add_argument("--temperature", type=float, default=1.0)
    a = ap.parse_args()
    text, usage = chat(a.prompt, a.model, a.system, a.temperature)
    print(text)
    print(f"\n[{usage.input_tokens} in / {usage.output_tokens} out]", file=sys.stderr)
Deliverable — llm_chat.py. A CLI that takes a prompt, optional model and system message, and returns a response. When you're done you can call any LLM from the terminal in under a minute, you've felt the speed/quality/cost triangle in real numbers, and you have the file Phase 2 plugs its retrieval into.