← Master Index
Vol. 18 Module 18.2 Lecture

FastAPI

Backend & Infrastructure

How This Lesson Fits the Module & Volume

The previous lecture defined your product API. FastAPI is this curriculum’s default way to implement it in Python: type hints, Pydantic validation, async, and free OpenAPI at /docs. You will wrap Module 18.1 SDKs (OpenAI first) so browsers never hold vendor keys.

Next: Flask as the older/simpler sibling, then Docker so this process is reproducible. Streaming and auth land later in the same module—design the app so those lectures plug in, not rewrite everything.

Learning Objectives

By the end of this lesson, students should be able to:

  • Create a FastAPI app with Pydantic request/response models for chat.
  • Call the OpenAI SDK from a route without leaking the SDK type to clients.
  • Use async def + thread/async clients so one slow LLM does not block the event loop carelessly.
  • Read auto-generated OpenAPI and treat it as the contract artifact.
  • Sketch SSE streaming (full treatment in the streaming lecture).
  • Contrast FastAPI with Flask and know when each is enough.
Definition

FastAPI is a Python web framework built on Starlette (ASGI) and Pydantic. You declare path operations with decorators, annotate parameter types, and get validation, serialization, and OpenAPI for free. It runs under Uvicorn (or Gunicorn+Uvicorn workers). It is not a model server like vLLM/Triton and not Kubernetes—it is the HTTP process that will later sit in a container.

Why FastAPI for AI Wrappers

NeedFastAPI feature
Strict JSON in/outPydantic models = runtime validation + docs
Many concurrent waits on vendor APIsASGI + async (still: do not block on sync SDK calls blindly)
Token streaming to browsersStreamingResponse / SSE (later lecture)
Partner integrations/docs OpenAPI as living contract

Minimal Chat Wrapper

# main.py — pip install fastapi uvicorn openai pydantic # export OPENAI_API_KEY=... # uvicorn main:app --reload --host 0.0.0.0 --port 8000 from typing import Literal from fastapi import FastAPI, HTTPException from pydantic import BaseModel, Field from openai import OpenAI app = FastAPI(title="Curriculum Chat API", version="1.0.0") client = OpenAI() class ChatIn(BaseModel): prompt: str = Field(min_length=1, max_length=8000) provider: Literal["openai"] = "openai" class ChatOut(BaseModel): text: str model: str input_tokens: int output_tokens: int @app.get("/health") def health(): return {"ok": True} @app.post("/v1/chat", response_model=ChatOut) def chat(body: ChatIn): try: resp = client.chat.completions.create( model="gpt-4.1-mini", messages=[{"role": "user", "content": body.prompt}], max_tokens=512, ) except Exception as exc: raise HTTPException(status_code=502, detail="upstream_llm_failed") from exc choice = resp.choices[0].message.content or "" usage = resp.usage return ChatOut( text=choice, model=resp.model, input_tokens=usage.prompt_tokens if usage else 0, output_tokens=usage.completion_tokens if usage else 0, ) # Next: auth dependency, SSE stream, Celery for long jobs, Docker CMD uvicorn

FastAPI vs Flask (preview)

FastAPI

  • ASGI, async-native
  • Pydantic + OpenAPI default
  • Best default for new AI APIs

Flask

  • WSGI, tiny, everywhere
  • You add schema/docs yourself
  • Fine for simple sync tools

Neither is

  • A GPU scheduler
  • A queue (see Celery/Redis)
  • An auth protocol (see Authentication)

Do

  • Return your DTOs, not raw SDK objects
  • Map upstream failures to 502/504, validation to 422
  • Keep secrets in env; inject clients via lifespan

Don’t

  • Run CPU-heavy tokenization on the event loop without care
  • Ship --reload in production
  • Expose /docs unauthenticated on the public internet forever

Related Lectures

LectureRole
APIThe contract you just implemented
OpenAI SDKUpstream client inside the route
FlaskWSGI alternative
DockerPackage Uvicorn next
Streaming / AuthPlug into this app, don’t fork it
Common Misconception

“FastAPI is async so my OpenAI call is automatically non-blocking.” The official sync client still blocks a worker thread unless you use the async client or asyncio.to_thread. Second: Pydantic validation is not authentication. Third: /docs is not a substitute for a changelog when you break ChatOut. Fourth: FastAPI will not quantize a 70B model—that is Module 18.3.

Knowledge Check

  1. Short Answer: Which two libraries sit under FastAPI? Answer: Starlette (ASGI) and Pydantic.
  2. True/False: Uvicorn is a common ASGI server for FastAPI. Answer: True.
  3. Multiple Choice: Invalid JSON body typically becomes: (a) 422, (b) 301, (c) CFG 7. Answer: (a).
  4. Short Answer: Why use response_model=ChatOut? Answer: Validate/serialize a stable DTO and document it in OpenAPI.
  5. True/False: Returning the raw OpenAI response object is a good public contract. Answer: False.
  6. Multiple Choice: Upstream LLM outage should often be: (a) 502/504, (b) 204, (c) 418 only. Answer: (a).
  7. Short Answer: What command starts this app locally in the sketch? Answer: uvicorn main:app --reload --host 0.0.0.0 --port 8000 (or equivalent).
  8. True/False: FastAPI replaces Redis and Celery. Answer: False.
  9. Multiple Choice: Next lecture: (a) Flask, (b) FLUX, (c) PCA. Answer: (a).
  10. Short Answer: Name one reason FastAPI beats a notebook requests.post for products. Answer: Any of: validation, OpenAPI, status codes, middleware/auth, concurrency, deployment shape.

Key Takeaways

  • FastAPI implements your API with Pydantic + OpenAPI + Uvicorn.
  • Wrap SDKs; return DTOs; map errors honestly.
  • Async is not magic—do not block the event loop on sync I/O.
  • Auth, SSE, Docker, queues come next; keep the app small.
  • Next: Flask.
Trainer’s Guide

Lab: Implement the sketch, hit /docs, then add a second provider stub (anthropic) behind the same ChatOut. Break the schema on purpose and show 422.

Whiteboard: Request → Pydantic → SDK → DTO. Mark where JWT will hook (Authentication) and where SSE will replace JSON (Streaming).

Recap: FastAPI is the default Python AI API. Compare the WSGI path next: Flask.