Why this phase exists
AI engineering is 80% ordinary software engineering under unusual constraints: everything is async and streamed, everything is untyped JSON until you force types onto it, and everything talks to slow, expensive, flaky external APIs. This phase teaches exactly the Python that serves those constraints — and skips the rest of the language’s folklore. The filter for every topic below: will a later phase use this? If not, it’s out.
Part A — Python, from the start (the AI engineering subset)
Work through these in order, writing small scripts at every step. Type-hint everything from day one — in this field, schemas are the job.
[!TIP] Part A is built out in
01-foundations/part-a/— a lesson and a set of failing tests for each bullet below. Read the lesson, fill in the drills, runuv run pytest phases/01-foundations/part-auntil it’s green.
- Core mechanics: variables, numbers, strings and f-strings, truthiness;
list,dict,set,tupleand when each fits; slicing; control flow. Dicts get special attention — every API payload you’ll ever touch is one. - Functions, properly: positional vs keyword args, defaults (and the mutable-default trap),
*args/**kwargs, functions as values, closures. Provider SDKs and frameworks assume fluency here. - Comprehensions & iteration: list/dict comprehensions,
enumerate,zip, sorting withkey=. - Errors:
try/except/finally, raising your own exceptions, exception chaining. API-calling code is mostly error handling; get comfortable early. - Files & data:
pathlib, reading/writing text, andjsondeeply — JSON is the substrate of everything LLM.csvin passing. - Modules & structure: imports, packages, the
src/layout, entry points. - Just enough OOP: classes,
@dataclass, methods, properties, minimal inheritance; preferProtocol(structural typing) over class hierarchies. You’ll use many classes and write few. - Generators & iterators:
yield, generator functions, lazy iteration. This is literally how token streaming works — Part B depends on it. - Decorators & context managers: at read-and-use level (
@app.get(...),with open(...),@pytest.fixture) — FastAPI and pytest are built from them. Write one trivial decorator and one context manager to demystify the syntax, then move on. - Type hints: every signature typed;
Optional/unions,Literal,TypedDict, generics as they come up. - A little SQL:
SELECT,JOIN,GROUP BY, indexes at a practical level. From Phase 4 onward your app data, vectors, and full-text search all live in PostgreSQL.
Explicitly skipped: metaclasses, multiple-inheritance puzzles, threading/multiprocessing internals (asyncio covers this roadmap’s concurrency), NumPy/pandas, notebooks-as-a-lifestyle, classical ML (sklearn), statistics. If a tutorial starts with a gradient, close the tab.
Part B — the engineering substrate
- Modern Python tooling: uv for packages/environments/Python versions (it has effectively replaced pip + venv + pyenv + poetry), ruff for linting + formatting,
pyrightfor type checking,pytestfor tests. Set these up once as your default project template. - Pydantic v2: models, validators,
model_json_schema(), serialization. This is the load-bearing library of Python AI engineering — it defines your API contracts, your LLM output schemas, and your tool signatures. - asyncio:
async/await,gather, semaphores for concurrency limits, async generators. LLM apps are I/O-bound; concurrency is how you make 100 extraction calls take 30 seconds instead of 30 minutes. - FastAPI: routes, dependency injection, Pydantic request/response models, background tasks,
StreamingResponse. - Streaming over HTTP: what Server-Sent Events (SSE) are and how to produce/consume them. Every chat UI you’ll ever build streams tokens this way.
- Docker: write a Dockerfile for a Python service, multi-stage builds, compose for app + database. Competence, not expertise.
- Git hygiene: branches, meaningful commits, PR-shaped changes — your later projects are portfolio pieces.
Warm-up project: wrangle
A CLI that turns messy JSON into clean, typed data — pure Part A muscle, zero web code.
- Feed it a real messy export: browser bookmarks, a social/streaming data export, or any public JSON dataset.
- Parse → validate into Pydantic models → normalize (dates, URLs) and dedupe → emit clean JSON plus a terminal summary report (counts, top categories, rejects with reasons).
- Typed end-to-end,
pytestcoverage for the ugly edge cases,ruffclean, propersrc/layout, installable entry point (uv run wrangle ...).
If Python is fresh, expect this to take a few evenings. That’s the point — it exercises every Part A topic in one artifact.
Main project: mockstream
A FastAPI service that pretends to be an LLM API — so you learn the transport layer with zero API cost, and get a reusable test double for later phases.
POST /v1/chataccepts{messages: [...], stream: bool}validated by Pydantic; rejects malformed input with useful errors.- Non-streaming mode returns a canned completion after an artificial delay.
- Streaming mode returns SSE, emitting word-by-word chunks with realistic pacing, terminated by a
[DONE]event (mirror the shape of a real provider’s streaming format). - A
httpx-based async client script consumes the stream and prints tokens as they arrive; run 20 concurrent requests bounded by a semaphore. - Typed end-to-end (
pyrightclean), tested (pytest+httpxtest client, including a streaming test), linted (ruff), Dockerized (compose file runs it).
Stretch: add a failure mode (random 429s with Retry-After) and make your client handle it with exponential backoff — you’ll reuse this exact logic against real providers in Phase 2.
Resources
- The official Python tutorial — chapters 1–9 map almost exactly onto Part A; read actively, typing every example
- Exercism Python track — free drills; do a handful per Part A topic until it’s automatic
- Real Python — topical deep-dives for when a concept (decorators, generators, asyncio) won’t click
- SQLBolt — interactive SQL basics in an afternoon
- uv docs — read “Working on projects” end to end; it’s short
- Pydantic docs — Models, Validators, JSON Schema pages
- FastAPI tutorial — through “Bigger Applications”; skim the rest
- asyncio — Python docs plus any good “asyncio for web APIs” walkthrough
- MDN on Server-Sent Events — short and definitive