LeetLLM
My PlanLearnGlossaryTracksPracticeBlog
LeetLLM

Your go-to resource for mastering AI & LLM systems.

Product

  • Learn
  • Glossary
  • Tracks
  • Practice
  • Blog
  • RSS

Legal

  • Terms of Service
  • Privacy Policy

© 2026 LeetLLM. All rights reserved.

All Topics
Your Progress
0%

0 of 158 articles completed

🛠️Computing Foundations0/9
Git, Shell, Linux for AIDocker for Reproducible AIPython for AI EngineeringNumPy and Tensor ShapesCUDA for ML TrainingMPS & Metal for ML on MacData Structures for AISQL and Data ModelingAlgorithms for ML Engineers
📊Math & Statistics0/8
Gradients and BackpropVectors, Matrices & TensorsLinear Algebra for MLAdam, Momentum, SchedulersProbability for Machine LearningStatistics and UncertaintyDistributions and SamplingHypothesis Tests, Intervals, and pass@k
📚Preparation & Prerequisites0/13
Neural Networks from ScratchCNNs from ScratchTraining & BackpropagationSoftmax, Cross-Entropy & OptimizationRNNs, LSTMs, GRUs, and Sequence ModelingAutoencoders and VAEsThe Transformer Architecture End-to-EndLanguage Modeling & Next TokensFrom GPT to Modern LLMsPrompt Engineering FundamentalsCalling LLM APIs in ProductionFirst AI App End-to-EndThe LLM Lifecycle
🧮ML Algorithms & Evaluation0/11
Linear Regression from ScratchLogistic Regression and MetricsDecision Trees, Forests, and BoostingReinforcement Learning BasicsValidation and LeakageClustering and PCACore Retrieval AlgorithmsDecoding AlgorithmsExperiment Design and A/B TestingPyTorch Training LoopsDataset Pipelines and Data Quality
📦Production ML Systems0/6
Feature Engineering for Production MLBatch and Streaming Feature PipelinesGradient Boosted Trees in ProductionRanking and Recommendation SystemsForecasting and Anomaly DetectionMonitoring Predictive Models
🧪Core LLM Foundations0/8
The Bitter Lesson & ComputeBPE, WordPiece, and SentencePieceStatic to Contextual EmbeddingsPerplexity & Model EvaluationFile Ingestion for AIChunking StrategiesLLM Benchmarks & LimitationsInstruction Tuning & Chat Templates
🧰Applied LLM Engineering0/24
Dimensionality Reduction for EmbeddingsCoT, ToT & Self-Consistency PromptingFunction Calling & Tool UseMCP & Tool Protocol StandardsContext EngineeringPrompt Injection DefenseResponsible AI GovernanceData Labeling and Human FeedbackEvaluating AI AgentsProduction RAG PipelinesHybrid Search: Dense + SparseReranking and Cross-Encoders for RAGRAG Evaluation for Reliable AnswersLLM-as-a-Judge EvaluationBias & Fairness in LLMsHallucination Detection & MitigationLLM Observability & MonitoringExperiment Tracking with MLflow and W&BPrompt Optimization with DSPyModel Versioning & DeploymentSemantic Caching & Cost OptimizationLLM Cost Engineering & Token EconomicsModel Gateways, Routing, and FallbacksDesign an Automated Support Agent
🎓Portfolio Capstones0/8
Capstone: Delivery ETA PredictionCapstone: Product RankingCapstone: Demand ForecastingCapstone: Image Damage ClassifierCapstone: Production ML PipelineCapstone: Document QACapstone: Eval DashboardCapstone: Fine-Tuned Classifier
🧠Transformer Deep Dives0/8
Sentence Embeddings & Contrastive LossEmbedding Similarity & QuantizationScaled Dot-Product AttentionVision Transformers and Image EncodersPositional Encoding: RoPE & ALiBiLayer Normalization: Pre-LN vs Post-LNMechanistic InterpretabilityDecoding Strategies: Greedy to Nucleus
🧬Advanced Training & Adaptation0/15
Scaling Laws & Compute-Optimal TrainingPre-training Data at ScaleBuild GPT from Scratch LabContinued Pretraining for Domain ShiftSynthetic Data PipelinesSupervised Fine-Tuning PipelineMixed Precision TrainingDistributed Training: FSDP & ZeROLoRA & Parameter-Efficient TuningReward Modeling from Preference DataRLHF & DPO AlignmentConstitutional AI & Red TeamingRLVR & Verifiable RewardsKnowledge Distillation for LLMsModel Merging and Weight Interpolation
🤖Advanced Agents & Retrieval0/16
Vector DB Internals: HNSW & IVFAdvanced RAG: HyDE & Self-RAGGraphRAG & Knowledge GraphsRAG Security & Access ControlStructured Output GenerationReAct & Plan-and-ExecuteGuardrails & Safety FiltersCode Generation & SandboxingComputer-Use / GUI / Browser AgentsHuman-in-the-Loop Agent ArchitectureAI Coding Workflow with AgentsAgent Memory & PersistenceAgent Failure & RecoveryRecursive Language Models (RLM)Multi-Agent OrchestrationCapstone: Production Agent
⚡Inference & Production Scale0/19
Inference: TTFT, TPS & KV CacheMulti-Query & Grouped-Query AttentionKV Cache & PagedAttentionPrefix Caching and Prompt CachingFlashAttention & Memory EfficiencyContinuous Batching & SchedulingScaling LLM InferenceModel Parallelism for LLM InferenceModel Quantization: GPTQ, AWQ & GGUFLocal LLM DeploymentSLM Specialization & Edge DeploymentSpeculative DecodingLong Context Window ManagementMixture of Experts ArchitectureMamba & State Space ModelsReasoning & Test-Time ComputeAdvanced MLOps & DevOps for AIGPU Serving & AutoscalingA/B Testing for LLMs
🏗️System Design Capstones0/9
Content Moderation SystemCode Completion SystemMulti-Tenant LLM PlatformLLM-Powered Search EngineVision-Language Models & CLIPMultimodal LLM ArchitectureDiffusion Models: Images & TextReal-Time Voice AI AgentReasoning & Test-Time Compute
🎤AI Lab Interviewing0/4
AI Lab Coding Interview: Python SystemsAI Lab System Design InterviewAI Lab Behavioral InterviewAI Lab Technical Presentation
Back to Topics
LearnCore LLM FoundationsThe Bitter Lesson & Compute
📈MediumReasoning & Scaling

The Bitter Lesson & Compute

Use Sutton's Bitter Lesson to compare rules, learning, and search through a measured AI-incident routing lab.

15 min read
Learning path
Step 48 of 158 in the full curriculum
Monitoring Predictive ModelsBPE, WordPiece, and SentencePiece

You just built a conventional ML product path: time-safe features, deployed predictive models, and monitoring gates that preserve held-out evidence and an audit trail. Now comes a harder design question: when your system is wrong, should you write another rule, learn from more examples, or spend more compute searching among possible answers?

Rich Sutton's 2019 essay The Bitter Lesson gives a demanding answer. Across long stretches of AI history, he argues, methods that can use increasing computation eventually outperform systems built around expert-written knowledge. He names two broadly scalable methods: learning, which improves a model from experience, and search, which explores choices before acting.[1]Reference 1The Bitter Lesson.http://www.incompleteideas.net/IncIdeas/BitterLesson.html

More compute doesn't automatically fix a system. You'll build a tiny AI-incident router, see when rules are useful, measure where they fail, and decide what additional budget can honestly buy.

Where effort compounds

Suppose Alex writes issue #48291: "Decode latency spiked after yesterday's reranker deploy." An AI operations system must choose a route: serving latency, answer quality, or access/auth.

A rule can say if "latency" in text: route_to("latency"). That works on wording the author anticipated. A learner can fit patterns from labeled issues such as TTFT spike, unsupported citation, and OAuth callback failed. A search step can generate several possible actions and check each one against evaluation evidence before committing.

Those are different ways to spend effort:

ApproachWhat a human specifiesWhat can improve laterFailure to watch
RulesKeywords and branchesMore rulesNew phrasing escapes the rulebook
LearningData, objective, evaluationMore clean labels and training computeBad labels or leakage teach the wrong behavior
SearchCandidates and a checkerMore candidate or verification budgetA weak checker rewards the wrong answer

Sutton's thesis concerns the long-run direction of research, not a ban on rules. A promotion gate or a required human approval can be exactly the right safety boundary. The warning is about making a growing rulebook carry the core intelligence of a messy task.

Three-lane comparison for the same latency-regression issue: keyword rules miss the unseen phrase token delay and require a new branch, learned scores route the issue toward latency examples, and search scores trace, rollback, and ignore candidates before selecting the evidence-backed trace. Three-lane comparison for the same latency-regression issue: keyword rules miss the unseen phrase token delay and require a new branch, learned scores route the issue toward latency examples, and search scores trace, rollback, and ignore candidates before selecting the evidence-backed trace.
The same issue creates different work. Rules pay with an engineer after each unseen phrase; learning pays at training time to move a reusable decision boundary; search pays at request time to score alternatives against evidence.

See a rulebook reach its boundary

Start with a router that a developer can ship in an afternoon. Three keywords cover obvious cases.

01-rules-have-boundaries.py
1cases = [ 2 ("decode timeout in prod", "latency"), 3 ("tokens arrive slowly", "latency"), 4 ("answer cites wrong doc", "quality"), 5 ("citation points to stale source", "quality"), 6 ("password reset please", "access"), 7 ("can't authenticate", "access"), 8] 9 10def rule_route(text: str) -> str: 11 text = text.lower() 12 rules = {"timeout": "latency", "citation": "quality", "password": "access"} 13 for keyword, route in rules.items(): 14 if keyword in text: 15 return route 16 return "manual_review" 17 18predictions = [(text, expected, rule_route(text)) for text, expected in cases] 19correct = sum(expected == predicted for _, expected, predicted in predictions) 20misses = [text for text, expected, predicted in predictions if expected != predicted] 21 22print(f"correct={correct}/{len(cases)}") 23print("misses:", misses) 24assert correct == 3
Rule router baseline
1correct=3/6 2misses: ['tokens arrive slowly', 'answer cites wrong doc', "can't authenticate"]

The router isn't foolish. It catches exact, high-signal phrases quickly. Its limit is visible: compute won't make those three conditions recognize tokens arrive slowly or can't authenticate. A human must anticipate and encode every expansion.

Now add rules that fix today's misses, then test tomorrow's wording.

02-rule-churn.py
1old_cases = [ 2 ("decode timeout in prod", "latency"), 3 ("tokens arrive slowly", "latency"), 4 ("answer cites wrong doc", "quality"), 5 ("citation points to stale source", "quality"), 6 ("password reset please", "access"), 7 ("can't authenticate", "access"), 8] 9new_cases = [ 10 ("TTFT spiked today", "latency"), 11 ("response used unsupported claim", "quality"), 12 ("OAuth callback fails again", "access"), 13] 14 15expanded_rules = { 16 "timeout": "latency", 17 "tokens": "latency", 18 "cites": "quality", 19 "citation": "quality", 20 "stale source": "quality", 21 "password": "access", 22 "authenticate": "access", 23} 24 25def route(text: str) -> str: 26 lowered = text.lower() 27 for keyword, label in expanded_rules.items(): 28 if keyword in lowered: 29 return label 30 return "manual_review" 31 32old_score = sum(route(text) == label for text, label in old_cases) 33new_score = sum(route(text) == label for text, label in new_cases) 34print(f"rules={len(expanded_rules)} old_set={old_score}/6 new_set={new_score}/3") 35print("new misses:", [text for text, label in new_cases if route(text) != label]) 36assert old_score == 6 and new_score == 0
Rule churn under new wording
1rules=7 old_set=6/6 new_set=0/3 2new misses: ['TTFT spiked today', 'response used unsupported claim', 'OAuth callback fails again']

The second result is the treadmill Sutton warns about. More engineer-hours repair yesterday's errors but don't automatically create a method that adapts to tomorrow's distribution.

Conceptual curve for an AI-incident router: routing rules improve early and flatten, while a learned router can continue improving as labeled issues and training budget grow. Conceptual curve for an AI-incident router: routing rules improve early and flatten, while a learned router can continue improving as labeled issues and training budget grow.
The crossover is a design hypothesis, not a guaranteed curve. Learning earns its extra budget only when labels, evaluation, and deployment feedback remain trustworthy.

Replace phrases with evidence from examples

A learned system needs a representation. Before tokenization becomes a full lesson, use the smallest representation possible: lowercase words. An issue becomes a set of observed terms, and training records which route each term appeared with.

03-token-evidence.py
1import re 2from collections import Counter 3 4training = [ 5 ("decode latency timeout", "latency"), 6 ("ttft spike tokens", "latency"), 7 ("wrong citation unsupported answer", "quality"), 8 ("stale source hallucination", "quality"), 9 ("password login access", "access"), 10 ("oauth callback auth", "access"), 11] 12 13def tokens(text: str) -> list[str]: 14 return re.findall(r"[a-z]+", text.lower()) 15 16by_label = {} 17for text, label in training: 18 by_label.setdefault(label, Counter()).update(tokens(text)) 19 20print("quality evidence:", sorted(by_label["quality"])) 21print("latency evidence:", sorted(by_label["latency"])) 22assert by_label["quality"]["citation"] == 1
Issue tokens
1quality evidence: ['answer', 'citation', 'hallucination', 'source', 'stale', 'unsupported', 'wrong'] 2latency evidence: ['decode', 'latency', 'spike', 'timeout', 'tokens', 'ttft']

That representation is primitive, but its source of knowledge is different from the rulebook. No engineer chose that citation or ttft should indicate a route. Labeled examples supplied that association.

Use those counts as a tiny learned classifier: score each route by how many words it shares with a new issue.

04-learn-from-labeled-issues.py
1import re 2from collections import Counter, defaultdict 3 4training = [ 5 ("decode latency timeout", "latency"), 6 ("ttft spike tokens", "latency"), 7 ("wrong citation unsupported answer", "quality"), 8 ("stale source hallucination", "quality"), 9 ("password login access", "access"), 10 ("oauth callback auth", "access"), 11] 12held_out = [ 13 ("latency spike tokens", "latency"), 14 ("unsupported citation answer", "quality"), 15 ("reset password", "access"), 16 ("stale source answer", "quality"), 17 ("bad graph query", "manual_review"), 18] 19 20def tokenize(text: str) -> list[str]: 21 return re.findall(r"[a-z]+", text.lower()) 22 23counts = defaultdict(Counter) 24for text, label in training: 25 counts[label].update(tokenize(text)) 26 27def predict(text: str) -> str: 28 words = tokenize(text) 29 scores = {label: sum(counter[word] for word in words) for label, counter in counts.items()} 30 best_score = max(scores.values()) 31 winners = [label for label, score in scores.items() if score == best_score] 32 return winners[0] if best_score > 0 and len(winners) == 1 else "manual_review" 33 34results = [(text, label, predict(text)) for text, label in held_out] 35correct = sum(expected == predicted for _, expected, predicted in results) 36print(f"held_out={correct}/{len(held_out)}") 37print("predictions:", [predicted for _, _, predicted in results]) 38assert correct == 5
Learned router evaluation
1held_out=5/5 2predictions: ['latency', 'quality', 'access', 'quality', 'manual_review']

Don't confuse this tiny word-overlap model with an LLM. Its role is to make the principle observable: a general learning procedure can absorb new labeled examples without a developer adding a condition for each phrase. When no observed word supports a unique route, the router abstains with manual_review instead of turning a tie into an arbitrary production decision.

05-add-one-correction.py
1import re 2from collections import Counter, defaultdict 3 4base = [ 5 ("timeout tokens", "latency"), 6 ("wrong citation", "quality"), 7 ("password reset", "access"), 8] 9issue = "bad graph query" 10 11def train_and_predict(rows: list[tuple[str, str]], text: str) -> str: 12 counts = defaultdict(Counter) 13 for example, label in rows: 14 counts[label].update(re.findall(r"[a-z]+", example.lower())) 15 words = re.findall(r"[a-z]+", text.lower()) 16 scores = {label: sum(counter[word] for word in words) for label, counter in counts.items()} 17 best_score = max(scores.values()) 18 winners = [label for label, score in scores.items() if score == best_score] 19 return winners[0] if best_score > 0 and len(winners) == 1 else "manual_review" 20 21before = train_and_predict(base, issue) 22after = train_and_predict(base + [("bad graph query citation", "quality")], issue) 23print(f"before_correction={before}") 24print(f"after_correction={after}") 25assert before == "manual_review" and after == "quality"
Correction becomes training data
1before_correction=manual_review 2after_correction=quality

Before correction, the safe answer is manual_review: the learner has no matching evidence. The correction alone doesn't prove generalization. You'd still evaluate on untouched issues, just as you did for datasets and training loops. It does show a useful operational property: production feedback can become evidence for the next training run instead of another permanent branch.

Diagram showing Resolved issues fit router, New issue candidate route, Verify policy evidence, and Route or escalate log outcome. Diagram showing Resolved issues fit router, New issue candidate route, Verify policy evidence, and Route or escalate log outcome.
Resolved issues fit router, New issue candidate route, Verify policy evidence, and Route or escalate log outcome.

Search spends compute after training

Learning isn't the only scalable method in Sutton's essay. Search spends computation at decision time. For an AI-operations agent, search might mean proposing multiple actions, retrieving evidence for each, and sending the best supported route forward.

Train-time and inference-time compute diagram showing resolved AI incidents fitting one evaluated router release, then a hard request searching four candidate actions whose verifier scores zero, negative one, one, and two before selecting the evidence-backed eval trace and block-promotion action. Train-time and inference-time compute diagram showing resolved AI incidents fitting one evaluated router release, then a hard request searching four candidate actions whose verifier scores zero, negative one, one, and two before selecting the evidence-backed eval trace and block-promotion action.
Training pays once to fit an evaluated router release. For the hard eval issue, request-time search spends a budget of 4 to find the only candidate with both run and metric evidence.

This next miniature isn't a language model. It's a transparent candidate-and-verifier loop that lets you see why additional inference budget helps only when better candidates and a meaningful checker exist.

06-search-with-a-verifier.py
1issue = "RAG answer failed citation_precision on run R42" 2candidates = [ 3 ("quality", "Retry later.", []), 4 ("promote", "Promote anyway.", []), 5 ("quality", "Open eval trace.", ["run R42"]), 6 ("quality", "Open eval trace; block promotion until citation_precision recovers.", ["run R42", "citation_precision"]), 7] 8 9def verifier(candidate: tuple[str, str, list[str]]) -> int: 10 route, _, evidence = candidate 11 if route != "quality": 12 return -1 13 return len(evidence) 14 15for budget in (1, 2, 4): 16 selected = max(candidates[:budget], key=verifier) 17 print(f"budget={budget} route={selected[0]} evidence={len(selected[2])} action={selected[1]}") 18 19assert verifier(max(candidates, key=verifier)) == 2
Inference-time search budget
1budget=1 route=quality evidence=0 action=Retry later. 2budget=2 route=quality evidence=0 action=Retry later. 3budget=4 route=quality evidence=2 action=Open eval trace; block promotion until citation_precision recovers.

The first candidate is cheap and weak. With four candidates, the verifier can choose an action tied to eval-run and metric evidence. If every candidate were wrong, or if the verifier rewarded promotion without release evidence, extra search would amplify error instead.

Snell and collaborators study this question for LLM reasoning: their experiments find that test-time strategies depend on prompt difficulty, and an adaptive allocation can use inference computation more efficiently than a fixed best-of-NNN baseline on their evaluated tasks.[2]Reference 2Scaling LLM Test-Time Compute Optimally Can Be More Effective Than Scaling Model Parameters.https://arxiv.org/abs/2408.03314 That result supports a conditional claim, not "thinking longer always works."

Connect the lesson to language-model training

Language models give learning an unusually clean objective: predict the next token. Kaplan and collaborators measured smooth empirical power-law relationships between cross-entropy loss and model size, dataset size, and training computation for the Transformer language models they studied.[3]Reference 3Scaling Laws for Neural Language Modelshttps://arxiv.org/abs/2001.08361 That's evidence that a general learning objective can turn additional scale into predictable improvement within an experimental regime.

For a dense decoder-only Transformer, engineers often estimate training compute with:

C≈6NDC \approx 6NDC≈6ND

Here, CCC is training floating-point operations (FLOPs), NNN is the number of model parameters, and DDD is the number of training tokens. The factor 6 is a planning approximation for forward and backward passes, not a promise about hardware throughput or model quality.[4]Reference 4Training Compute-Optimal Large Language Models.https://arxiv.org/abs/2203.15556

07-estimate-training-flops.py
1def dense_training_flops(parameters: int, tokens: int) -> int: 2 return 6 * parameters * tokens 3 4plans = [ 5 ("small study", 1_000_000_000, 20_000_000_000), 6 ("larger run", 7_000_000_000, 140_000_000_000), 7] 8 9for name, parameters, tokens in plans: 10 flops = dense_training_flops(parameters, tokens) 11 print(f"{name}: {flops / 1e21:.2f} zettaFLOPs") 12 13assert dense_training_flops(7_000_000_000, 140_000_000_000) == 5_880_000_000_000_000_000_000
Training FLOPs estimate
1small study: 0.12 zettaFLOPs 2larger run: 5.88 zettaFLOPs

More compute isn't the same as better allocation. Hoffmann and collaborators trained more than 400 models and reported that, under their compute-optimal fits, parameter count and training-token count should scale together: doubling one calls for roughly doubling the other.[4]Reference 4Training Compute-Optimal Large Language Models.https://arxiv.org/abs/2203.15556

Use the FLOPs approximation to expose the tradeoff under one fixed budget. This calculation doesn't select the best model; it only tells you how many tokens each model size can afford at that budget.

08-allocate-a-fixed-training-budget.py
1budget = 6 * 7_000_000_000 * 140_000_000_000 2model_sizes = [1_000_000_000, 7_000_000_000, 14_000_000_000] 3 4for parameters in model_sizes: 5 affordable_tokens = budget // (6 * parameters) 6 print(f"N={parameters / 1e9:.0f}B -> D={affordable_tokens / 1e9:.0f}B tokens") 7 8assert budget // (6 * 14_000_000_000) == 70_000_000_000
Fixed-budget tradeoff
1N=1B -> D=980B tokens 2N=7B -> D=140B tokens 3N=14B -> D=70B tokens

That calculation matters because "make the model bigger" can consume the budget needed to expose it to sufficient data. A research scientist doesn't ask only how much compute is available. They ask how to allocate it, what evaluation will reveal, and which failure mode an extra unit of compute addresses.

History is evidence, not a slogan

Sutton's essay supports a broad historical pattern. A careful reader should also notice where the evidence stops.

DomainWhat the source supportsWhat you shouldn't claim from it
Chess and GoSutton describes delayed success from scaled search and learning; AlphaZero learned chess, shogi, and Go from self-play with only game rules and reached superhuman play within 24 hours.[1]Reference 1The Bitter Lesson.http://www.incompleteideas.net/IncIdeas/BitterLesson.html[5]Reference 5Mastering Chess and Shogi by Self-Play with a General Reinforcement Learning Algorithm.https://arxiv.org/abs/1712.01815That search eliminates every useful prior or safety rule
Speech and visionSutton points to statistical/deep-learning methods replacing increasingly elaborate human feature engineering.[1]Reference 1The Bitter Lesson.http://www.incompleteideas.net/IncIdeas/BitterLesson.htmlThat modern architectures contain no inductive biases
Language modelsScaling studies measure improvement of Transformer language models as model size, tokens, and compute change.[3]Reference 3Scaling Laws for Neural Language Modelshttps://arxiv.org/abs/2001.08361[4]Reference 4Training Compute-Optimal Large Language Models.https://arxiv.org/abs/2203.15556That LLM pretraining proves Sutton's full claim about agents learning from experience

That last distinction is important. Internet text contains human-written knowledge. Training on more of it can be a strong general procedure while still relying on human-produced data. Treat the Bitter Lesson as a research heuristic: prefer methods that can absorb more evidence and compute, then demand measurement.

Keep rules where they belong

Rules belong at contractual boundaries, not inside a growing list of guessed user intents. For an AI release system, the model can suggest a promotion route, but policy can require review for a failed gate or missing eval evidence.

Ambiguity-consequence matrix showing deterministic lookups at low ambiguity and risk, learned intent for free-form issues, policy rules for high-consequence thresholds, and a hybrid path that classifies ship the candidate before routing a low-score promotion to human review. Ambiguity-consequence matrix showing deterministic lookups at low ambiguity and risk, learned intent for free-form issues, policy rules for high-consequence thresholds, and a hybrid path that classifies ship the candidate before routing a low-score promotion to human review.
Use learning where meaning is ambiguous, rules where execution risk is explicit, and both when a free-form request can trigger a costly action. Here the model identifies promotion intent; the policy gate sends a low-score candidate to review.
09-keep-policy-gates.py
1def release_action(proposed_route: str, eval_score: float, evidence: set[str]) -> str: 2 if proposed_route == "promote" and eval_score < 0.95: 3 return "human_review_failed_gate" 4 if proposed_route == "promote" and "eval_report" not in evidence: 5 return "request_evidence" 6 return proposed_route 7 8examples = [ 9 ("promote", 0.98, {"eval_report"}), 10 ("promote", 0.91, {"eval_report"}), 11 ("promote", 0.98, set()), 12] 13decisions = [release_action(*example) for example in examples] 14print("decisions:", decisions) 15assert decisions == ["promote", "human_review_failed_gate", "request_evidence"]
Guardrail around capability
1decisions: ['promote', 'human_review_failed_gate', 'request_evidence']

The rule here isn't pretending to understand language. It protects an action with business and safety consequences. Learning handles messy phrasing; the gate controls what the learned component may execute.

Finally, leave a receipt. This one records the tiny lesson fixture, not a launch approval. A system that consumes more compute but can't report its evaluated split, training procedure, inference budget, verifier, policy gates, and escalation monitor isn't ready for a production experiment.

10-log-the-compute-decision.py
1from hashlib import sha256 2from json import dumps 3 4evaluation = { 5 "split": "incident-router-held-out-v1", 6 "correct": 5, 7 "total": 5, 8 "manual_review_routes": 1, 9} 10evaluation["accuracy"] = evaluation["correct"] / evaluation["total"] 11receipt = { 12 "component": "incident-router-word-overlap-v1", 13 "training": { 14 "procedure": "token-overlap-counts-v1", 15 "examples": 6, 16 }, 17 "evaluation": evaluation, 18 "search": { 19 "candidate_budget": 4, 20 "verifier": "eval-evidence-v1", 21 }, 22 "policy_gates": ["promotion_below_0_95_requires_review", "promotion_requires_eval_report"], 23 "monitor": "manual_escalation_rate", 24} 25payload = dumps(receipt, sort_keys=True, separators=(",", ":")) 26 27print(dumps(receipt, indent=2, sort_keys=True)) 28print("receipt sha256:", sha256(payload.encode()).hexdigest()[:12]) 29assert receipt["search"]["candidate_budget"] == 4 30assert receipt["evaluation"]["accuracy"] == 1.0
Compute decision receipt
1{ 2 "component": "incident-router-word-overlap-v1", 3 "evaluation": { 4 "accuracy": 1.0, 5 "correct": 5, 6 "manual_review_routes": 1, 7 "split": "incident-router-held-out-v1", 8 "total": 5 9 }, 10 "monitor": "manual_escalation_rate", 11 "policy_gates": [ 12 "promotion_below_0_95_requires_review", 13 "promotion_requires_eval_report" 14 ], 15 "search": { 16 "candidate_budget": 4, 17 "verifier": "eval-evidence-v1" 18 }, 19 "training": { 20 "examples": 6, 21 "procedure": "token-overlap-counts-v1" 22 } 23} 24receipt sha256: 957f864a4562

What to carry forward

The Bitter Lesson isn't "throw compute at every problem." It's a test for your design:

  1. Can new labeled evidence improve the capability without new handwritten branches?
  2. Can additional search or verification budget be measured against a held-out task?
  3. Are policy gates protecting actions rather than trying to encode every meaning?
  4. Can you report the compute budget and the evaluation that justified it?

Language models begin by converting raw text into discrete pieces. Tokenizers are a perfect next place to ask the same question: which reusable units can be learned from data, and what mistakes are introduced at that boundary?

Mastery check

Checkpoints

Evaluation rubric

  • Foundational: State Sutton's thesis and distinguish learning from search.
  • Practical: Run the incident-router examples and explain why a correction is data for a learner but rule debt for a keyword router.
  • Quantitative: Estimate dense-model training FLOPs and compare model/token allocations under a fixed budget.
  • Production: Design one learned component, one policy gate, and one logged metric for an automated AI-operations workflow.

Common pitfalls

"Compute will fix bad data"

  • Symptom: You enlarge a model or sample more candidates while labels leak or contradict one another.
  • Cause: General methods can amplify the data and objectives they're given.
  • Fix: Keep the dataset-quality and held-out evaluation discipline from the earlier data and production-ML lessons.

"Rules are forbidden"

  • Symptom: You let a learned router auto-promote low-score candidates without a policy boundary.
  • Cause: You've confused scalable capability with unconstrained execution.
  • Fix: Use rules for auditable gates and learning for messy recognition.

"More search always improves an answer"

  • Symptom: Cost and latency rise, but accepted answers don't improve.
  • Cause: Candidate generation or verification is too weak for added budget to help.
  • Fix: Evaluate budget levels on held-out tasks and stop spending where gains vanish.

"A deterministic tie-break is safe"

  • Symptom: An unseen issue is sent to the first route in a sorted label list.
  • Cause: The classifier turns missing evidence into a reproducible but unsupported action.
  • Fix: Abstain when no route has positive evidence or when several routes share the best score.
Complete the lesson

Mastery Check

Answer every question, then check your score. Score above 75% to mark this lesson complete.

1.A keyword incident router catches phrases like timeout and citation, but it misses tokens arrive slowly, answer cites wrong doc, and tomorrow's new wording. The team wants future corrections to improve routing without adding one permanent branch per phrase. Which change shifts the core capability from handwritten rules to a method that can improve from evaluated labeled evidence?
2.An AI-release learned router proposes the route promote. Company policy says candidates below 0.95 eval score require human review, and any promotion without an eval report should request evidence first. Which design correctly separates learned intent recognition from auditable execution policy?
3.An engineer uses C approx 6ND for a dense decoder-only Transformer, where N is parameter count and D is training-token count. They then claim the number proves the model's quality and expected wall-clock runtime. Which statement correctly describes what this formula does and does not justify?
4.An AI-operations agent uses inference-time search: it generates candidate actions and scores each with an eval-evidence verifier. For a failed RAG eval, increasing the budget from 2 to 4 candidates reveals an action with both run R42 and citation_precision evidence. Which conclusion correctly describes when extra inference-time search is useful?
5.A word-overlap router was trained on timeout tokens -> latency, wrong citation -> quality, and password reset -> access. For a new issue, it sums exact observed word counts per label and returns a label only when one label has a positive top score. What should it return for bad graph query before any correction is added?
6.A team has the same training FLOP budget as a 7B-parameter dense Transformer trained on 140B tokens, using C≈6NDC \approx 6NDC≈6ND. If it instead trains a 14B-parameter model under the same budget, how many tokens can it afford, and what trade-off does that show?
7.A word-overlap router sends bad graph query to manual review. The team adds the labeled example bad graph query citation -> quality, retrains, and then tests the original issue again. It now predicts quality. What conclusion is justified?
8.A team observes smooth held-out cross-entropy scaling as model size, tokens, and compute increase across its clean Transformer experiments. Another project has leaked labels and no promotion approval gates. What does the scaling evidence justify?
9.An AI-operations team is preparing a production experiment for a learned router with inference-time search. The team must make its compute decision reproducible and auditable. Which record should it log?

9 questions remaining.

Next Step
Continue to BPE, WordPiece, and SentencePiece

You now know why methods that absorb more data and computation matter. Next you'll build the text-to-token boundary that makes language-model learning possible and measure the tradeoffs it introduces.

PreviousMonitoring Predictive Models
Share this article
XFacebookLinkedInBlueskyRedditHacker NewsEmail
References

The Bitter Lesson.

Sutton, R. S. · 2019

Scaling LLM Test-Time Compute Optimally Can Be More Effective Than Scaling Model Parameters.

Snell, C., et al. · 2024 · arXiv preprint

Scaling Laws for Neural Language Models

Kaplan et al. · 2020

Training Compute-Optimal Large Language Models.

Hoffmann, J., et al. · 2022 · NeurIPS 2022

Mastering Chess and Shogi by Self-Play with a General Reinforcement Learning Algorithm.

Silver, D., et al. · 2017 · arXiv preprint

Discussion

Questions and insights from fellow learners.

Discussion loads when you reach this section.