Learn AI Series (#155) - The Complete AI Stack: Architecture Review
Learn AI Series (#155) - The Complete AI Stack: Architecture Review

What will I learn?
- You will learn how every technique from 154 episodes connects into a coherent whole;
- common AI architectures for common problems: what to combine with what;
- a technology selection framework that accounts for constraints (data, compute, latency, team);
- the "boring AI" that actually ships in production versus the flashy AI that gets conference talks;
- what we deliberately did NOT cover in this series and where to learn it;
- how to think architecturally about AI systems rather than thinking in individual components.
Requirements
- A working modern computer running macOS, Windows or Ubuntu;
- Python 3.10+ installed;
- Familiarity with the full series - this episode ties everything together.
Difficulty
- Advanced
Curriculum (of the Learn AI Series):
- Learn AI Series (#1) - What Machine Learning Actually Is
- Learn AI Series (#2) - Setting Up Your AI Workbench - Python and NumPy
- Learn AI Series (#3) - Your Data Is Just Numbers - How Machines See the World
- Learn AI Series (#4) - Your First Prediction - No Math, Just Intuition
- Learn AI Series (#5) - Patterns in Data - What "Learning" Actually Looks Like
- Learn AI Series (#6) - From Intuition to Math - Why We Need Formulas
- Learn AI Series (#7) - The Training Loop - See It Work Step by Step
- Learn AI Series (#8) - The Math You Actually Need (Part 1) - Linear Algebra
- Learn AI Series (#9) - The Math You Actually Need (Part 2) - Calculus and Probability
- Learn AI Series (#10) - Your First ML Model - Linear Regression From Scratch
- Learn AI Series (#11) - Making Linear Regression Real
- Learn AI Series (#12) - Classification - Logistic Regression From Scratch
- Learn AI Series (#13) - Evaluation - How to Know If Your Model Actually Works
- Learn AI Series (#14) - Data Preparation - The 80% Nobody Talks About
- Learn AI Series (#15) - Feature Engineering and Selection
- Learn AI Series (#16) - Scikit-Learn - The Standard Library of ML
- Learn AI Series (#17) - Decision Trees - How Machines Make Decisions
- Learn AI Series (#18) - Random Forests - Wisdom of Crowds
- Learn AI Series (#19) - Gradient Boosting - The Kaggle Champion
- Learn AI Series (#20) - Support Vector Machines - Drawing the Perfect Boundary
- Learn AI Series (#21) - Mini Project - Predicting Crypto Market Regimes
- Learn AI Series (#22) - K-Means Clustering - Finding Groups
- Learn AI Series (#23) - Advanced Clustering - Beyond K-Means
- Learn AI Series (#24) - Dimensionality Reduction - PCA
- Learn AI Series (#25) - Advanced Dimensionality Reduction - t-SNE and UMAP
- Learn AI Series (#26) - Anomaly Detection - Finding What Doesn't Belong
- Learn AI Series (#27) - Recommendation Systems - "Users Like You Also Liked..."
- Learn AI Series (#28) - Time Series Fundamentals - When Order Matters
- Learn AI Series (#29) - Time Series Forecasting - Predicting What Comes Next
- Learn AI Series (#30) - Natural Language Processing - Text as Data
- Learn AI Series (#31) - Word Embeddings - Meaning in Numbers
- Learn AI Series (#32) - Bayesian Methods - Thinking in Probabilities
- Learn AI Series (#33) - Ensemble Methods Deep Dive - Stacking and Blending
- Learn AI Series (#34) - ML Engineering - From Notebook to Production
- Learn AI Series (#35) - Data Ethics and Bias in ML
- Learn AI Series (#36) - Mini Project - Complete ML Pipeline
- Learn AI Series (#37) - The Perceptron - Where It All Started
- Learn AI Series (#38) - Neural Networks From Scratch - Forward Pass
- Learn AI Series (#39) - Neural Networks From Scratch - Backpropagation
- Learn AI Series (#40) - Training Neural Networks - Practical Challenges
- Learn AI Series (#41) - Optimization Algorithms - SGD, Momentum, Adam
- Learn AI Series (#42) - PyTorch Fundamentals - Tensors and Autograd
- Learn AI Series (#43) - PyTorch Data and Training
- Learn AI Series (#44) - PyTorch nn.Module - Building Real Networks
- Learn AI Series (#45) - Convolutional Neural Networks - Theory
- Learn AI Series (#46) - CNNs in Practice - Classic to Modern Architectures
- Learn AI Series (#47) - CNN Applications - Detection, Segmentation, Style Transfer
- Learn AI Series (#48) - Recurrent Neural Networks - Sequences
- Learn AI Series (#49) - LSTM and GRU - Solving the Memory Problem
- Learn AI Series (#50) - Sequence-to-Sequence Models
- Learn AI Series (#51) - Attention Mechanisms
- Learn AI Series (#52) - The Transformer Architecture (Part 1)
- Learn AI Series (#53) - The Transformer Architecture (Part 2)
- Learn AI Series (#54) - Vision Transformers
- Learn AI Series (#55) - Generative Adversarial Networks
- Learn AI Series (#56) - Mini Project - Building a Transformer From Scratch
- Learn AI Series (#57) - Language Modeling - Predicting the Next Word
- Learn AI Series (#58) - GPT Architecture - Decoder-Only Transformers
- Learn AI Series (#59) - BERT and Encoder Models
- Learn AI Series (#60) - Training Large Language Models
- Learn AI Series (#61) - Instruction Tuning and Alignment
- Learn AI Series (#62) - Prompt Engineering - Getting the Most from LLMs
- Learn AI Series (#63) - Embeddings and Vector Search
- Learn AI Series (#64) - Retrieval-Augmented Generation (RAG) - Basics
- Learn AI Series (#65) - RAG - Advanced Techniques
- Learn AI Series (#66) - Working with LLM APIs
- Learn AI Series (#67) - Building AI Agents (Part 1) - Foundations
- Learn AI Series (#68) - Building AI Agents (Part 2) - Advanced Patterns
- Learn AI Series (#69) - Fine-Tuning Language Models
- Learn AI Series (#70) - Running Local Models
- Learn AI Series (#71) - Text Generation Techniques
- Learn AI Series (#72) - Tokenization Deep Dive
- Learn AI Series (#73) - LLM Evaluation
- Learn AI Series (#74) - The Hugging Face Ecosystem
- Learn AI Series (#75) - Multimodal Models - Text Meets Vision
- Learn AI Series (#76) - Mini Project - Your Own AI Assistant
- Learn AI Series (#77) - Image Processing Fundamentals
- Learn AI Series (#78) - Object Detection (Part 1) - Foundations
- Learn AI Series (#79) - Object Detection (Part 2) - Modern Approaches
- Learn AI Series (#80) - Image Segmentation
- Learn AI Series (#81) - Pose Estimation and Tracking
- Learn AI Series (#82) - Optical Character Recognition
- Learn AI Series (#83) - Video Understanding
- Learn AI Series (#84) - Generative Images - Diffusion Models (Part 1)
- Learn AI Series (#85) - Generative Images - Diffusion Models (Part 2)
- Learn AI Series (#86) - Image-to-Image and Editing
- Learn AI Series (#87) - 3D Vision
- Learn AI Series (#88) - Face Analysis
- Learn AI Series (#89) - Medical and Scientific Imaging
- Learn AI Series (#90) - Self-Supervised Learning for Vision
- Learn AI Series (#91) - Mini Project - Building a Visual AI System
- Learn AI Series (#92) - Audio Fundamentals for AI
- Learn AI Series (#93) - Speech Recognition
- Learn AI Series (#94) - Text-to-Speech (TTS)
- Learn AI Series (#95) - Audio Classification
- Learn AI Series (#96) - Music Generation
- Learn AI Series (#97) - Speaker Recognition and Diarization
- Learn AI Series (#98) - Natural Language Understanding for Voice
- Learn AI Series (#99) - Audio Enhancement
- Learn AI Series (#100) - Multimodal Audio-Visual Models
- Learn AI Series (#101) - Mini Project: Voice-Controlled AI Assistant
- Learn AI Series (#102) - What Is Reinforcement Learning?
- Learn AI Series (#103) - Multi-Armed Bandits
- Learn AI Series (#104) - Dynamic Programming
- Learn AI Series (#105) - Monte Carlo Methods
- Learn AI Series (#106) - Temporal Difference Learning
- Learn AI Series (#107) - Deep Q-Networks (DQN)
- Learn AI Series (#108) - Policy Gradient Methods
- Learn AI Series (#109) - Advanced Policy Optimization
- Learn AI Series (#110) - Model-Based Reinforcement Learning
- Learn AI Series (#111) - Multi-Agent Reinforcement Learning
- Learn AI Series (#112) - RL for Games
- Learn AI Series (#113) - RL for Real-World Applications
- Learn AI Series (#114) - Inverse Reinforcement Learning
- Learn AI Series (#115) - Offline Reinforcement Learning
- Learn AI Series (#116) - Mini Project: Training a Game-Playing AI
- Learn AI Series (#117) - ML System Design
- Learn AI Series (#118) - Data Engineering for AI
- Learn AI Series (#119) - Experiment Tracking and Reproducibility
- Learn AI Series (#120) - Model Optimization: Making Models Fast
- Learn AI Series (#121) - Model Serving Architecture
- Learn AI Series (#122) - Edge AI: Running Models on Devices
- Learn AI Series (#123) - Monitoring ML in Production
- Learn AI Series (#124) - CI/CD for Machine Learning
- Learn AI Series (#125) - GPU Programming Basics
- Learn AI Series (#126) - Distributed Training
- Learn AI Series (#127) - AI Security
- Learn AI Series (#128) - Privacy-Preserving AI
- Learn AI Series (#129) - AutoML and Neural Architecture Search
- Learn AI Series (#130) - Causal Inference and ML
- Learn AI Series (#131) - Graph Neural Networks
- Learn AI Series (#132) - AI for Structured Data
- Learn AI Series (#133) - Synthetic Data Generation
- Learn AI Series (#134) - AI Infrastructure Economics
- Learn AI Series (#135) - Building AI Teams and Processes
- Learn AI Series (#136) - Mini Project: Production AI Platform
- Learn AI Series (#137) - Foundation Models
- Learn AI Series (#138) - Multimodal AI
- Learn AI Series (#139) - AI for Code
- Learn AI Series (#140) - Scientific AI
- Learn AI Series (#141) - Robotics and Embodied AI
- Learn AI Series (#142) - AI Reasoning and Planning
- Learn AI Series (#143) - Continual Learning
- Learn AI Series (#144) - Few-Shot and Zero-Shot Learning
- Learn AI Series (#145) - Neuro-Symbolic AI
- Learn AI Series (#146) - Explainability and Interpretability
- Learn AI Series (#147) - AI Safety and Alignment
- Learn AI Series (#148) - The Economics of AI
- Learn AI Series (#149) - AI Ethics in Practice
- Learn AI Series (#150) - Emerging Frontiers
- Learn AI Series (#151) - Mini Project: Building Something That Matters
- Learn AI Series (#152) - The AI Practitioner's Toolkit
- Learn AI Series (#153) - Building AI Products
- Learn AI Series (#154) - AI Research: How to Read Papers
- Learn AI Series (#155) - The Complete AI Stack: Architecture Review (this post)
Learn AI Series (#155) - The Complete AI Stack: Architecture Review
154 episodes behind us. Nine arcs -- math foundations, classical ML, neural networks, language models, computer vision, audio, reinforcement learning, production engineering, and the frontier stuff. That is a LOT of individual parts. And here is the uncomfortable truth about learning a field one episode at a time: you can know every part and still not know how the machine goes together. So today we are not learning anything new. Today we climb the hill, turn around, and look at the whole map at once.
I want to be clear about what this episode is not. It is not a recap -- we did plenty of those at the tail of each arc, and I am not going to make you sit through another "remember when we covered gradient descent" tour. This is about the architecture: how the pieces snap together into complete systems, and (much more importantly) how you develop the intuition to snap them together yourself when a brand-new problem lands on your desk and nobody hands you the answer.
Having said that, let's climb. Here we go!
The dependency graph
Every technique we covered stands on top of something else. Nothing in this field is an island. If you draw out what-depends-on-what, you get a structure that looks like this:
NumPy/Linear Algebra (#2, #8)
├── Gradient Descent (#6-7)
│ ├── Linear/Logistic Regression (#10-12)
│ │ └── Regularization, Feature Engineering (#11, #15)
│ ├── Neural Networks from Scratch (#37-39)
│ │ ├── Training Tricks (#40-41)
│ │ ├── CNNs (#45-47) ──────────────────────────┐
│ │ ├── RNNs/LSTMs (#48-49) ───────┐ │
│ │ └── Attention (#51) ────────────┤ │
│ │ └── Transformers (#52-53) ──┤ │
│ │ ├── GPT/LLMs (#57-76) ──┤ │
│ │ ├── BERT (#59) ─────────┤ │
│ │ ├── ViT (#54) ──────────┼────────────┤
│ │ └── Diffusion (#84-85) │ │
│ └── PyTorch (#42-44) │ │
│ │ │
├── scikit-learn / Classical ML (#16-20) │ │
│ ├── Trees -> Random Forest (#17-18) │ │
│ ├── Gradient Boosting (#19) ────────│────────────│──┐
│ └── Ensembles (#33) ────────────────│────────────│──┤
│ │ │ │
├── Unsupervised (#22-27) ──────────────│────────────│──│
│ ├── Clustering (#22-23) │ │ │
│ ├── PCA/t-SNE/UMAP (#24-25) │ │ │
│ └── Anomaly Detection (#26) │ │ │
│ │ │ │
├── RL (#102-116) ──────────────────────┘ │ │
│ ├── Value Methods (#104-107) │ │
│ └── Policy Methods (#108-109) │ │
│ │ │
└── Production (#117-136) ──────────────────── uses all ┘
├── System Design (#117)
├── Data Eng (#118)
├── Optimization (#120)
├── Serving (#121)
└── Monitoring (#123)
Stare at that graph for a second, because there is a genuine insight hiding in it: gradient descent and the transformer are the two most connected nodes in the entire field. Almost everything reaches back to one or both of them. If you truly understand how gradient descent optimises a parameterised function (episodes #6-7 and #10, where we built it by hand before we ever touched a library) and how a transformer moves information around with attention (#51-53), then you can read almost any new architecture as "those two ideas, plus some domain-specific way of turning the input into numbers". That is not an exaggeration for effect -- it is genuinely how the field is built. The rest is bookkeeping and good engineering.
Nota bene: notice how much of the graph funnels through the transformer row. GPT, BERT, ViT, diffusion, multimodal -- all downstream of attention. That is not an accident of drawing; that is the actual history of the last several years compressed into an ASCII diagram ;-)
Common architectures for common problems
Here is something they do not tell you at the start: in practice, most AI systems are assembled from a tiny handful of architectural patterns. You do not invent a new architecture for every problem -- you reach for one of maybe five shapes and adapt it. These five cover, in my experience, something like 90% of what actually gets deployed in the real world:
# Architecture 1: Classification / Regression Pipeline
# Episodes: #10-20, #14-16
# When: structured data, clear input->output mapping, plenty of labels
classification_pipeline = {
"data": "Tabular features (numbers, categories)",
"preprocessing": "Imputation, encoding, scaling (#14-16)",
"model": "Gradient boosting (XGBoost/LightGBM) (#19)",
"evaluation": "Cross-validation, calibration (#13)",
"deployment": "FastAPI + batch or real-time (#121)",
"monitoring": "Feature drift + performance drift (#123)",
"example_uses": [
"Fraud detection",
"Credit scoring",
"Churn prediction",
"Pricing optimization",
],
}
# Architecture 2: Embedding + Retrieval System
# Episodes: #31, #63-65
# When: "find similar things" or "answer questions from a knowledge base"
retrieval_system = {
"data": "Documents, products, user profiles",
"preprocessing": "Chunking, cleaning (#64)",
"embedding_model": "Sentence transformer or OpenAI embeddings (#63)",
"vector_store": "FAISS, Chroma, Qdrant (#63)",
"retrieval": "Approximate nearest neighbor search",
"optional_reranker": "Cross-encoder for precision (#65)",
"optional_generator": "LLM for RAG (#64-65)",
"example_uses": [
"Semantic search",
"Document Q&A (RAG)",
"Recommendation systems",
"Duplicate detection",
],
}
# Architecture 3: Foundation Model + Prompt/Fine-tune
# Episodes: #57-62, #66, #69
# When: any NLP task in 2026
llm_system = {
"data": "Text (any format)",
"approach_1_prompt": "API call with system prompt + examples (#62, #66)",
"approach_2_finetune": "LoRA on domain data (#69)",
"approach_3_rag": "Retrieve context + generate (#64-65)",
"structured_output": "JSON mode / function calling (#66)",
"evaluation": "LLM-as-judge + human eval (#73)",
"example_uses": [
"Content generation",
"Summarization",
"Classification",
"Extraction / parsing",
"Code generation",
"Agents and tool use",
],
}
# Architecture 4: Pretrained Vision + Fine-tune
# Episodes: #45-47, #54, #78-80
# When: any image/video task
vision_system = {
"data": "Images or video frames",
"backbone": "ResNet, EfficientNet, ViT (#46, #54)",
"task_head": {
"classification": "Linear layer (#46)",
"detection": "YOLOv8 (#79)",
"segmentation": "SAM or U-Net (#80)",
},
"training": "Fine-tune from pretrained weights (#46)",
"augmentation": "Random crop, flip, color jitter (#43)",
"example_uses": [
"Quality inspection",
"Medical imaging",
"Content moderation",
"Autonomous systems",
],
}
# Architecture 5: Multimodal Pipeline
# Episodes: #75, #100, #138
# When: input or output spans multiple modalities
multimodal_system = {
"encoders": {
"text": "Transformer encoder (#52, #59)",
"image": "ViT or CNN (#54, #46)",
"audio": "Whisper encoder or spectrogram CNN (#93)",
},
"fusion": "Cross-attention or projection to shared space (#138)",
"decoder": "Autoregressive transformer (#53, #58)",
"example_uses": [
"Visual question answering",
"Image captioning",
"Video understanding",
"Audio-visual analysis",
],
}
Notice the pattern that runs through all five: every single one starts from a pretrained model. Training from scratch, in 2026, is the exception -- reserved for the labs with the GPU farms and the research budgets. For the rest of us the real skill is not building architectures at all. It is knowing which pretrained pieces exist, which ones to combine, and how to adapt them to your problem with the least amount of custom work. That is a very different skill from what most courses teach, and it is the one that pays the bills.
The technology selection framework
Alright, so a real problem lands on your desk. A stakeholder wants "AI" for something. You have five architectural shapes in your head and a hundred and fifty episodes of techniques. How do you decide? The mistake almost everyone makes -- and I made it too, for years -- is to start from the technology ("I want to use a transformer") and then go looking for a problem shaped like the tool. Wrong direction. You work backwards, from the constraints. Here is the framework I actually use:
def select_technology(problem):
"""
Constraint-aware technology selection.
Work BACKWARDS from constraints, not forwards from technology.
"""
constraints = {
# Data constraints
"data_size": None, # samples: 100? 10K? 1M?
"data_labels": None, # labeled, partially, unlabeled
"data_modality": None, # tabular, text, image, audio, mixed
"data_sensitivity": None, # public, internal, regulated
# Compute constraints
"training_budget": None, # laptop, single GPU, cluster, cloud
"inference_latency": None,# <10ms, <100ms, <1s, >1s OK
"inference_cost": None, # per prediction budget
# Team constraints
"ml_expertise": None, # beginner, intermediate, expert
"maintenance_budget": None,# can you retrain monthly? quarterly?
# Business constraints
"accuracy_requirement": None, # 80%? 95%? 99.9%?
"explainability": None, # nice-to-have, required, legally mandated
"time_to_deploy": None, # days, weeks, months
}
# The constraint that matters MOST determines your approach
critical_constraint_rules = {
"regulated_data": "Can't use external APIs. Local models or on-prem (#70, #128)",
"sub_10ms_latency": "No LLM APIs. Optimized local model or classical ML (#120)",
"no_labels": "Unsupervised (#22-26), self-supervised (#90), or LLM zero-shot (#144)",
"tiny_dataset": "Transfer learning (#46), few-shot (#144), or feature engineering + small model",
"must_explain": "Linear models (#10-12), trees (#17), SHAP (#146) - avoid black boxes",
"deploy_in_days": "Use existing APIs and pretrained models only (#66, #74)",
"99.9_accuracy": "Ensemble methods (#33), human-in-the-loop, fallback chains",
}
return constraints, critical_constraint_rules
Read that critical_constraint_rules dict slowly, because it is the whole game in one place. The single most common mistake in this field is choosing a technology because it is exciting rather than because the constraints demand it. If your data is tabular, your team is three people, and you need to ship in two weeks -- the answer is gradient boosting (episode #19), full stop. Not a transformer. If your data is text and you need good-enough accuracy fast -- the answer is an LLM API call (#66), not three months training a custom model. Match the tool to the constraints, not to your ambition. Your ambition is not the customer's problem ;-)
Let me make that concrete, because a framework in the abstract is easy to nod along to and hard to actually apply. Suppose a real request comes in: "we get thousands of support emails a day, route each one to the right team." Watch the constraints do the deciding for you:
# Turn a vague request into a stack by answering the constraint questions.
problem = {
"data_modality": "text", # support emails
"data_labels": "partial", # a few thousand historical, hand-tagged
"data_size": "3000 labeled", # small-ish
"inference_latency": "<1s OK", # emails are not real-time
"data_sensitivity": "internal", # customer PII -> be careful with APIs
"ml_expertise": "intermediate",
"time_to_deploy": "3 weeks",
}
def decide_stack(p):
# Constraint 1: sensitive data narrows the field before anything else.
if p["data_sensitivity"] in ("regulated", "internal"):
base = "local model or a vendor with a data-processing agreement (#70, #128)"
else:
base = "any hosted LLM API is fair game (#66)"
# Constraint 2: tiny labeled set -> do NOT train from scratch.
if "3000" in p["data_size"]:
approach = "zero/few-shot LLM classification first (#144), fine-tune only if it underperforms (#69)"
else:
approach = "fine-tune a small encoder like DistilBERT (#59, #69)"
# Constraint 3: relaxed latency means we are not forced into a tiny model.
latency_note = "sub-second budget is generous -- no need to over-optimize (#120)"
return base, approach, latency_note
for line in decide_stack(problem):
print("-", line)
See what happened? At no point did I ask "what is the coolest model". I answered a handful of boring questions and the stack fell out almost on its own. The email router is a few-shot LLM classifier with a fallback, running against a vendor that will sign a data agreement, and I have not written a line of training code yet. THAT is architectural discipline -- and it is way less glamorous than it sounds, which is exactly why it works.
The boring AI that actually ships
Now for the part nobody puts on a conference slide. After quite some years around production systems, here is an observation that took me an embarrassingly long time to accept: the AI that runs most of the world is boring. Not transformers. Not diffusion models. Not reinforcement learning with a clever reward. It is the stuff from the FIRST arc of this very series:
- Logistic regression for click-through rate prediction (trillions of predictions per day across the internet)
- Gradient-boosted trees for fraud detection, credit scoring, recommendation ranking
- TF-IDF + simple classifiers for spam filtering, content categorization
- k-nearest neighbors for recommendation systems at moderate scale
- Moving averages and threshold rules for anomaly detection in monitoring systems
All of that came from episodes #10-20. The first arc. Before we ever touched a neural network. These techniques work, they are fast, they are explainable (a regulator can read them), they are debuggable at 3am, and they do not need a GPU cluster humming in a datacenter. A logistic regression that scores in microseconds and that you can reason about beats a transformer you cannot debug -- almost every time the stakes are real.
Here is why the boring stuff wins on the numbers, made painfully concrete:
# Two ways to score a click-through-rate prediction. Same job, wildly
# different cost. This is why "boring" runs the ad-serving internet.
def boring_ctr(features, weights, bias):
"""Logistic regression. Microseconds. Runs on a potato."""
import math
z = sum(f * w for f, w in zip(features, weights)) + bias
return 1.0 / (1.0 + math.exp(-z)) # one dot product + a sigmoid
# A big neural model would need a matrix library, a loaded checkpoint,
# probably a GPU, and tens of milliseconds per call. At a MILLION requests
# per second (a normal ad exchange), those milliseconds are the whole budget.
example = boring_ctr([0.3, -1.2, 0.8], [1.5, 0.4, -0.9], bias=0.1)
print(round(example, 4)) # a probability, computed in the time it took to read this
That is not a toy -- that is (a stripped-down version of) what actually predicts trillions of ad clicks a day across the internet. Speed and explainability, not raw capability, are what put a model into the hot path.
The exciting stuff -- LLMs, diffusion, multimodal systems -- is increasingly deployed too, do not get me wrong. But it is deployed alongside the boring AI, not instead of it. A production recommendation system might use an LLM to understand messy product descriptions, gradient boosting to rank the candidates, and a dumb rule-based filter to enforce the business constraints that legal insists on. The system is a composition, not a single hero model:
class ProductionRecommender:
"""Real recommender systems are compositions, not single models."""
def recommend(self, user, context, n_results=10):
# Stage 1: Candidate generation (fast, broad)
# Simple embedding similarity or collaborative filtering
candidates = self.candidate_generator.get_candidates(
user, n=1000
)
# Stage 2: Business rules (no ML needed)
# Filter out-of-stock, age-restricted, already-purchased
candidates = self.business_filter.apply(candidates, user, context)
# Stage 3: Ranking (the ML part)
# Gradient boosting on features: user history, item features,
# context (time, device, location)
features = self.feature_builder.build(user, candidates, context)
scores = self.ranker.predict(features)
# Stage 4: Diversification (rule-based)
# Don't show 10 items from the same category
results = self.diversifier.select(candidates, scores, n=n_results)
# Stage 5: Explanation (optional, for transparency)
explanations = self.explainer.explain(user, results)
return results, explanations
Count them: four of the five stages are not machine learning at all. Candidate generation, business rules, diversification, explanation -- plain code, filters, and heuristics. The actual ML (stage 3) is a gradient-boosted tree that scores in about 2ms, and the whole pipeline lands around 50ms end to end. It works. It is boring. It ships. And if you had walked into that room proposing to replace all five stages with one giant end-to-end model, you would have been (correctly) shown the door.
What we didn't cover
Let's be honest with each other for a minute. This has been a long road -- more episodes than either of us probably want to count -- but the field is genuinely vast, and no series covers all of it. Pretending otherwise would be an insult to your intelligence. So here are the honest gaps, the things I either skipped or barely grazed:
not_covered = {
"in_depth": [
"Bayesian deep learning (beyond episode #32's basics)",
"Neural ODEs and continuous-time models",
"Geometric deep learning beyond basic GNNs (#131)",
"Diffusion for non-image modalities (protein design, molecular gen)",
"Compiler-level ML optimization (TVM, Apache TVM, Triton kernels)",
"Hardware-specific optimization (CUDA kernel writing beyond #125)",
"Federated learning at scale (only covered concepts in #128)",
],
"entire_subfields": [
"Computational biology / bioinformatics",
"Computational linguistics (formal syntax/semantics)",
"Signal processing (beyond audio fundamentals)",
"Operations research / mathematical optimization",
"Probabilistic programming (Pyro, Stan, NumPyro)",
],
"practical_skills": [
"ML interviewing and system design interviews",
"Managing ML teams and projects (touched in #135)",
"ML regulation compliance in depth (GDPR, EU AI Act specifics)",
"Cost optimization for large-scale ML pipelines",
],
}
Here is the thing though, and it is the reason I am not the least bit worried about those gaps: for every one of them, this series already handed you the foundation to go learn it on your own. You know how neural networks train (#37-44), so Neural ODEs are an extension of a thing you understand, not an alien concept. You know transformers cold (#52-53), so any shiny new architecture built on attention is readable to you now. You know how to read the paper behind it (that was the previous episode). The foundation was always the point. I was never going to teach you all of AI -- nobody can. I was teaching you how to teach yourself the rest.
Thinking architecturally
So what was the actual meta-skill this whole series was secretly building? It is architectural thinking: looking at a fresh problem and seeing which pieces from your toolkit snap together into a solution. Not "I'll use a transformer because transformers are powerful" (the beginner's reflex), but "this problem has sequential dependencies, variable-length inputs, and needs to attend to long-range context -- so attention is the right inductive bias here, and a pretrained encoder gives me a running start." That shift, from thinking in models to thinking in systems, is the difference between someone who took a course and someone you can hand a vague problem to and actually trust with it.
class ArchitecturalThinking:
"""The questions that guide system design."""
questions = [
# Input
"What is the raw input? (text, images, numbers, mixed)",
"How much of it do I have?",
"How noisy / messy is it?",
"Does the input have structure I should exploit? (sequential, spatial, graph)",
# Output
"What am I predicting? (class, number, sequence, image, action)",
"How precise does it need to be?",
"Does the output need to be explainable?",
# Constraints
"What's the latency budget?",
"What's the compute budget (training and inference)?",
"Are there privacy / regulatory constraints on the data?",
"How often does the data distribution change?",
# System
"Is this a one-shot prediction or part of a loop?",
"Does the system need to improve over time?",
"What happens when the model is wrong?",
"Who maintains this after I'm done?",
]
@staticmethod
def design_principle():
return (
"Start with the simplest approach that could work. "
"Add complexity only when you have evidence that simplicity fails. "
"Every component you add is a component that can break."
)
That design_principle is not a throwaway docstring -- it is the single thread running through this ENTIRE series, from the very first episode to this one. We started with the simplest possible prediction (just the average, all the way back in episode #4) and added complexity only when the problem forced our hand. Linear regression when we needed continuous outputs. Logistic regression when we needed classes. Neural networks when we needed to learn features automatically in stead of hand-crafting them. Transformers when we finally needed variable-length sequences with long-range dependencies. Every single step was earned by evidence that the previous step was not enough.
That is the discipline in practice -- and it is worth having as a literal checklist you run before adding anything to a system:
def should_i_add_complexity(current_system, proposed_addition):
"""Run this BEFORE reaching for the fancier model. Be honest."""
# Do you have EVIDENCE the simple version fails? Not a hunch -- evidence.
if not current_system["has_measured_failure"]:
return "NO -- measure the simple baseline first (#13). You are guessing."
# Will the addition fix the SPECIFIC failure you measured?
if proposed_addition["targets"] != current_system["measured_failure"]:
return "NO -- you are solving a problem you do not actually have."
# Every part you add is a part that can break at 3am. Worth it?
cost = proposed_addition["extra_latency_ms"] + proposed_addition["extra_ops_burden"]
if cost > proposed_addition["expected_gain"]:
return "NO -- the complexity costs more than it buys."
return "YES -- earned. Add it, and measure again."
print(should_i_add_complexity(
{"has_measured_failure": False, "measured_failure": None},
{"targets": "accuracy", "extra_latency_ms": 40, "extra_ops_burden": 5, "expected_gain": 3},
)) # -> "NO -- measure the simple baseline first (#13). You are guessing."
Each step earned, not assumed. THAT is architectural thinking, boiled down to a habit you can actually run in your head.
And that, my friend, is very nearly the whole journey. We have one more stop on this road together -- a quieter, more personal one about where you go from here. But the map is complete. You are holding it now.
What to remember from this one
- The dependency graph of AI techniques centers on two nodes: gradient descent and transformers - deep understanding of both lets you learn almost everything else;
- five architectural patterns cover 90% of real-world AI systems: classification pipeline, embedding + retrieval, LLM + prompt/fine-tune, pretrained vision + task head, and multimodal pipeline;
- select technology by working backwards from constraints (data, compute, latency, team, explainability), not forwards from what's exciting;
- the boring AI (logistic regression, gradient boosting, TF-IDF) runs most of the world's production systems and is deployed alongside, not replaced by, frontier models;
- production systems are compositions: multiple stages, some ML, some rules, some filtering - the ML model is rarely more than one component in a larger pipeline;
- architectural thinking is the meta-skill: asking the right questions about input, output, constraints, and system context, then snapping together the right pieces from your toolkit.