← Master Index
Vol. 18 Module 18.2 Lecture

Flask

Backend & Infrastructure

How This Lesson Fits the Module & Volume

FastAPI is the default for new AI HTTP APIs in this volume. Flask is still everywhere: internal tools, older microservices, Gradio/A1111-adjacent glue, and teams that want WSGI simplicity. You must read Flask well enough to wrap an SDK, know its limits (sync WSGI, no built-in Pydantic/OpenAPI), and choose deliberately—not by blog-post fashion.

After this page, the process (FastAPI or Flask) goes into Docker. The API contract does not change with the framework.

Learning Objectives

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

  • Build a small Flask JSON API that calls the OpenAI SDK.
  • Explain WSGI vs ASGI and why streaming/WebSockets are harder on classic Flask.
  • Add explicit validation (or Pydantic by hand) instead of trusting request.json.
  • Choose Flask vs FastAPI for a given AI service.
  • Run Flask with a production WSGI server mindset (not app.run(debug=True) on the internet).
  • See Flask as an implementation detail behind the same product DTO.
Definition

Flask is a lightweight WSGI Python web framework: routing, request context, Jinja templates, and extensions (Flask-Login, Flask-RESTful, …). It does not mandate types, async, or OpenAPI. WSGI is a synchronous calling convention (one request, one worker thread/process). Flask 2+ can run some async views, but it is not FastAPI’s ASGI-first design.

Flask vs FastAPI for LLM Backends

AxisFlaskFastAPI
Server modelWSGI (Gunicorn/Waitress)ASGI (Uvicorn)
Validation / docsDIY or marshmallow/APISpecPydantic + OpenAPI default
SSE / WebSocketsPossible, more frictionFirst-class StreamingResponse / Starlette WS
Ecosystem ageHuge; many internal appsNewer; AI/startup default
Templates / HTMLExcellent (Jinja)Possible; not the main story

Same Chat DTO in Flask

# app.py — pip install flask openai # export OPENAI_API_KEY=... # flask --app app run --port 8000 # dev only from flask import Flask, jsonify, request from openai import OpenAI app = Flask(__name__) client = OpenAI() @app.get("/health") def health(): return jsonify(ok=True) @app.post("/v1/chat") def chat(): data = request.get_json(silent=True) or {} prompt = data.get("prompt") if not isinstance(prompt, str) or not prompt.strip(): return jsonify(error="invalid_prompt"), 400 if len(prompt) > 8000: return jsonify(error="prompt_too_long"), 400 try: resp = client.chat.completions.create( model="gpt-4.1-mini", messages=[{"role": "user", "content": prompt}], max_tokens=512, ) except Exception: return jsonify(error="upstream_llm_failed"), 502 usage = resp.usage return jsonify( text=resp.choices[0].message.content or "", model=resp.model, input_tokens=usage.prompt_tokens if usage else 0, output_tokens=usage.completion_tokens if usage else 0, ) # Production: gunicorn app:app --bind 0.0.0.0:8000 --workers 2 # Do not: app.run(host="0.0.0.0", debug=True) on a public IP

When Flask Is Still the Right Call

Choose Flask

  • Existing Flask monolith / extensions
  • Simple sync admin tools
  • HTML dashboards with Jinja

Choose FastAPI

  • New public JSON API
  • Streaming chat, OpenAPI partners
  • Async upstream fan-out

Either way

  • Same DTO + status codes
  • Same Docker/K8s later
  • Same auth and metering

Flask wins

  • Tiny mental model; easy internal tools
  • Battle-tested WSGI ops knowledge
  • Gradio/legacy glue often speaks Flask-ish

Pay the tax

  • You must invent validation and docs
  • Debug server is not production
  • Streaming/WS push you toward ASGI anyway

Related Lectures

LectureRole
FastAPIASGI sibling; preferred for new AI APIs
APIContract independent of Flask
DockerGunicorn/Uvicorn in a container next
A1111Gradio app, not your Flask product
Common Misconception

“Flask can’t do AI.” It can call any SDK; it just won’t give you async/OpenAPI for free. Second: debug=True is a remote-code-execution footgun, not a feature. Third: returning 200 + {"error": ...} (easy in Flask) still breaks clients. Fourth: wrapping A1111 in Flask without auth is still not Module 18.2 deployment.

Knowledge Check

  1. Short Answer: Is classic Flask primarily WSGI or ASGI? Answer: WSGI.
  2. True/False: Flask includes Pydantic OpenAPI by default like FastAPI. Answer: False.
  3. Multiple Choice: Production Flask is usually served with: (a) Gunicorn/Waitress, (b) Automatic1111, (c) t-SNE. Answer: (a).
  4. Short Answer: Why validate request.json yourself? Answer: Flask will not enforce your schema unless you add validation.
  5. True/False: app.run(debug=True) is acceptable on a public IP. Answer: False.
  6. Multiple Choice: Prefer FastAPI when you need: (a) SSE + OpenAPI for a new chat API, (b) only Jinja marketing pages, (c) k-means. Answer: (a).
  7. Short Answer: Should the Flask JSON body match FastAPI’s ChatOut? Answer: Yes—same product contract, different framework.
  8. True/False: Flask replaces Docker. Answer: False.
  9. Multiple Choice: Next lecture: (a) Docker, (b) Gemini, (c) DDIM. Answer: (a).
  10. Short Answer: Name one Flask strength vs FastAPI. Answer: Any of: simplicity, Jinja/HTML, huge legacy ecosystem, WSGI ops familiarity.

Key Takeaways

  • Flask is WSGI-simple; you own validation and docs.
  • Same product DTO as FastAPI; do not fork the contract.
  • Never ship the debug server; use Gunicorn/Waitress.
  • New streaming AI APIs: default FastAPI.
  • Next: Docker.
Trainer’s Guide

Lab: Port the FastAPI chat route to Flask with identical JSON. Hit both from one httpx script. Discuss what you lost (/docs, 422 details).

Whiteboard: WSGI worker blocked on OpenAI vs ASGI concurrency. Then arrow both into a Docker image.

Recap: Flask is a valid WSGI implementation of the same API. Containerize next: Docker.