Files
whetstone_RSA/presentations/whetstoneRSA_overkill_deck.html

726 lines
26 KiB
HTML
Raw Normal View History

2026-04-30 19:01:42 +00:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WhetstoneRSA - When LLMs Are Overkill</title>
<style>
:root {
--bg: #0f1117;
--panel: #161b27;
--text: #e2e8f0;
--muted: #94a3b8;
--dim: #64748b;
--line: #2d3748;
--blue: #60a5fa;
--cyan: #22d3ee;
--green: #4ade80;
--amber: #fbbf24;
--red: #fb7185;
}
* { box-sizing: border-box; }
html, body {
margin: 0;
min-height: 100%;
background: var(--bg);
color: var(--text);
font-family: "Segoe UI", system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
}
body { overflow: hidden; }
.deck { width: 100vw; height: 100vh; position: relative; }
.slide {
position: absolute;
inset: 0;
display: none;
padding: 5.5vh 7vw;
overflow: hidden;
}
.slide.active {
display: grid;
grid-template-rows: auto 1fr auto;
gap: 28px;
}
.kicker {
color: var(--dim);
font-size: 0.78rem;
letter-spacing: 0.16em;
text-transform: uppercase;
font-weight: 700;
}
h1, h2 {
margin: 0;
letter-spacing: 0;
font-weight: 680;
}
h1 {
font-size: clamp(3rem, 7vw, 6.6rem);
line-height: 0.98;
max-width: 1080px;
}
h2 {
font-size: clamp(2.35rem, 5.4vw, 5.15rem);
line-height: 1.02;
max-width: 1080px;
}
.subtitle {
color: var(--muted);
font-size: clamp(1.2rem, 2.2vw, 2rem);
line-height: 1.35;
max-width: 980px;
}
.body {
display: flex;
flex-direction: column;
justify-content: center;
min-height: 0;
}
.center { align-items: center; text-align: center; }
.center h1, .center h2, .center .subtitle { margin-left: auto; margin-right: auto; }
.bigline {
font-size: clamp(2rem, 4.1vw, 4.35rem);
line-height: 1.08;
font-weight: 650;
}
.stack { display: flex; flex-direction: column; gap: 18px; max-width: 1080px; }
.bullets {
margin: 0;
padding: 0;
list-style: none;
display: grid;
gap: 18px;
max-width: 980px;
}
.bullets li {
position: relative;
padding-left: 34px;
color: var(--text);
font-size: clamp(1.55rem, 2.8vw, 3rem);
line-height: 1.13;
font-weight: 560;
}
.bullets li::before {
content: "";
position: absolute;
left: 0;
top: 0.46em;
width: 12px;
height: 12px;
border-radius: 999px;
background: var(--cyan);
}
.small-bullets li { font-size: clamp(1.22rem, 2vw, 2.1rem); }
code {
color: var(--cyan);
background: rgba(34, 211, 238, 0.08);
border: 1px solid rgba(34, 211, 238, 0.16);
border-radius: 6px;
padding: 0.08em 0.28em;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
font-size: 0.9em;
}
pre {
margin: 0;
background: #111827;
border: 1px solid var(--line);
border-radius: 8px;
padding: 26px;
color: var(--text);
font-size: clamp(1.15rem, 1.85vw, 1.95rem);
line-height: 1.36;
overflow: hidden;
}
pre code {
background: none;
border: 0;
padding: 0;
color: var(--text);
font-size: 1em;
}
.flow {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 14px;
align-items: stretch;
width: min(1120px, 100%);
}
.flow.three { grid-template-columns: repeat(3, 1fr); }
.flow.two { grid-template-columns: repeat(2, 1fr); }
.box {
border: 1px solid var(--line);
background: var(--panel);
border-radius: 8px;
padding: 24px;
min-height: 140px;
display: flex;
flex-direction: column;
justify-content: center;
gap: 12px;
}
.box .label {
color: var(--dim);
font-size: 0.72rem;
letter-spacing: 0.12em;
text-transform: uppercase;
font-weight: 800;
}
.box .main {
font-size: clamp(1.25rem, 2.15vw, 2.25rem);
line-height: 1.1;
font-weight: 650;
}
.box.blue { border-color: rgba(96, 165, 250, 0.65); }
.box.cyan { border-color: rgba(34, 211, 238, 0.65); }
.box.green { border-color: rgba(74, 222, 128, 0.65); }
.box.amber { border-color: rgba(251, 191, 36, 0.65); }
.box.red { border-color: rgba(251, 113, 133, 0.65); }
.metric {
display: inline-flex;
align-items: baseline;
gap: 12px;
margin-right: 28px;
margin-bottom: 12px;
}
.metric strong {
font-size: clamp(2.8rem, 5.8vw, 5.8rem);
color: var(--cyan);
line-height: 1;
}
.metric span {
color: var(--muted);
font-size: clamp(1rem, 1.55vw, 1.45rem);
}
.table {
width: min(1120px, 100%);
border-collapse: collapse;
font-size: clamp(1rem, 1.55vw, 1.5rem);
}
.table th, .table td {
border-bottom: 1px solid var(--line);
padding: 18px 16px;
text-align: left;
vertical-align: top;
}
.table th {
color: var(--dim);
font-size: 0.75em;
letter-spacing: 0.12em;
text-transform: uppercase;
}
.table td { color: var(--text); }
.table .muted { color: var(--muted); }
.footer {
display: flex;
justify-content: space-between;
align-items: center;
color: var(--dim);
font-size: 0.88rem;
}
.progress {
position: fixed;
left: 0;
bottom: 0;
height: 4px;
background: var(--cyan);
width: 0;
transition: width 120ms ease-out;
z-index: 10;
}
.notes {
position: fixed;
right: 18px;
bottom: 22px;
width: min(560px, calc(100vw - 36px));
max-height: 38vh;
overflow: auto;
background: rgba(15, 17, 23, 0.96);
border: 1px solid var(--line);
border-radius: 8px;
padding: 16px 18px;
color: var(--muted);
font-size: 0.95rem;
line-height: 1.45;
display: none;
z-index: 20;
}
.notes.visible { display: block; }
.notes strong { color: var(--text); }
.hint {
position: fixed;
top: 16px;
right: 18px;
color: var(--dim);
font-size: 0.8rem;
z-index: 11;
}
.accent { color: var(--cyan); }
.green-text { color: var(--green); }
.amber-text { color: var(--amber); }
.red-text { color: var(--red); }
@media (max-width: 800px) {
.slide { padding: 5vh 6vw; }
.flow, .flow.three, .flow.two { grid-template-columns: 1fr; }
.box { min-height: 96px; }
.hint { display: none; }
}
@media print {
body { overflow: visible; }
.deck { height: auto; }
.slide, .slide.active {
position: relative;
display: grid;
page-break-after: always;
height: 100vh;
}
.hint, .progress, .notes { display: none !important; }
}
</style>
</head>
<body>
<div class="deck" id="deck">
<section class="slide active" data-notes="Open with the concrete claim: a lot of current LLM use is a huge model choosing from a tiny menu.">
<div class="kicker">WhetstoneRSA</div>
<div class="body center">
<h1>When LLMs Are Overkill</h1>
<p class="subtitle">Messy input, small menu, local transformer gate</p>
</div>
<div class="footer"><span>1</span><span>main claim</span></div>
</section>
<section class="slide" data-notes="Do not argue that LLMs are bad. Argue that many jobs are much smaller than the model being used.">
<div class="kicker">The starting point</div>
<div class="body center">
<h2>LLMs are amazing.</h2>
<p class="subtitle">But many software decisions are much smaller than an LLM.</p>
</div>
<div class="footer"><span>2</span><span>not anti-LLM</span></div>
</section>
<section class="slide" data-notes="This is the phrase to repeat. It is understandable without data-science vocabulary.">
<div class="kicker">The shape</div>
<div class="body center">
<div class="bigline">The input can be huge.</div>
<div class="bigline"><span class="accent">The output is small.</span></div>
</div>
<div class="footer"><span>3</span><span>the key distinction</span></div>
</section>
<section class="slide" data-notes="Use a generic example before WhetstoneDSL so nobody is lost in project-specific nouns.">
<div class="kicker">Example request</div>
<div class="body center">
<h2><code>show me the failed builds from yesterday</code></h2>
</div>
<div class="footer"><span>4</span><span>messy human phrasing</span></div>
</section>
<section class="slide" data-notes="The user phrasing is flexible. The application behavior is not infinite.">
<div class="kicker">Same intent, many phrasings</div>
<div class="body">
<ul class="bullets small-bullets">
<li>what broke in CI yesterday</li>
<li>pull up yesterday's red builds</li>
<li>did the pipeline fail last night</li>
<li>which build jobs failed since yesterday</li>
</ul>
</div>
<div class="footer"><span>5</span><span>input variety</span></div>
</section>
<section class="slide" data-notes="Now flip the framing. We do not need to generate an answer. We need to choose an allowed action.">
<div class="kicker">What the app actually needs</div>
<div class="body center">
<div class="flow three">
<div class="box cyan"><div class="label">action</div><div class="main">search_builds</div></div>
<div class="box blue"><div class="label">status</div><div class="main">failed</div></div>
<div class="box green"><div class="label">date</div><div class="main">yesterday</div></div>
</div>
</div>
<div class="footer"><span>6</span><span>small structured output</span></div>
</section>
<section class="slide" data-notes="This is the first scale point. The output menu can be counted.">
<div class="kicker">Output scale</div>
<div class="body center">
<pre><code>5 actions x 4 statuses x 4 date buckets
= about 80 structured outputs</code></pre>
</div>
<div class="footer"><span>7</span><span>small menu</span></div>
</section>
<section class="slide" data-notes="This is where regex looks good. It is cheap, fast, local, and totally controlled.">
<div class="kicker">Classical code starts well</div>
<div class="body center">
<pre><code>if text has "failed" and "build":
action = search_builds
if text has "yesterday":
date = yesterday</code></pre>
</div>
<div class="footer"><span>8</span><span>simple at first</span></div>
</section>
<section class="slide" data-notes="The cost is not runtime. The cost is authoring and maintaining all the variants.">
<div class="kicker">Then regex pays the human tax</div>
<div class="body center">
<h2>You enumerate the input side.</h2>
<p class="subtitle">Every new phrase becomes another pattern, exception, or bug.</p>
</div>
<div class="footer"><span>9</span><span>input enumeration</span></div>
</section>
<section class="slide" data-notes="Use conservative numbers. This is not a precise theorem. It is an engineering intuition pump.">
<div class="kicker">Rule explosion</div>
<div class="body center">
<pre><code>5 actions
x 10 common phrasings
x 4 statuses
x 8 time phrasings
= 1,600-ish rule cases</code></pre>
</div>
<div class="footer"><span>10</span><span>conservative example</span></div>
</section>
<section class="slide" data-notes="The classic system is reliable after it matches. The painful part is reaching that match across human language.">
<div class="kicker">Regex tradeoff</div>
<div class="body">
<ul class="bullets">
<li>excellent output control</li>
<li>tiny runtime cost</li>
<li>input coverage gets expensive</li>
</ul>
</div>
<div class="footer"><span>11</span><span>great gate, painful input</span></div>
</section>
<section class="slide" data-notes="This is why developers reach for LLMs. They collapse the input enumeration problem.">
<div class="kicker">LLMs feel easy</div>
<div class="body center">
<h2>They understand the messy input.</h2>
<p class="subtitle">One prompt can replace a pile of brittle phrase rules.</p>
</div>
<div class="footer"><span>12</span><span>the appeal is real</span></div>
</section>
<section class="slide" data-notes="But the machine you brought is not sized to the software decision. It is a general language engine.">
<div class="kicker">But the scale is wrong</div>
<div class="body center">
<h2>A giant general model</h2>
<p class="subtitle">choosing from a tiny application menu.</p>
</div>
<div class="footer"><span>13</span><span>overkill</span></div>
</section>
<section class="slide" data-notes="Use current OpenAI API prices as a familiar external scale. Mention these are API examples, not your local experiment.">
<div class="kicker">API runtime scale</div>
<div class="body center">
<table class="table">
<tr><th>Model</th><th>Input</th><th>Output</th></tr>
<tr><td>GPT-4.1</td><td>$2 / 1M tokens</td><td>$8 / 1M tokens</td></tr>
<tr><td>GPT-4.1 mini</td><td>$0.40 / 1M tokens</td><td>$1.60 / 1M tokens</td></tr>
<tr><td>GPT-4.1 nano</td><td>$0.10 / 1M tokens</td><td>$0.40 / 1M tokens</td></tr>
</table>
</div>
<div class="footer"><span>14</span><span>OpenAI pricing, checked Apr 2026</span></div>
</section>
<section class="slide" data-notes="Fine-tuning is still priced by token volume. It is useful, but it is not the same thing as a tiny local gate.">
<div class="kicker">Fine-tuning scale</div>
<div class="body center">
<table class="table">
<tr><th>Fine-tuned model</th><th>Training</th><th>Runtime input</th><th>Runtime output</th></tr>
<tr><td>GPT-4.1 mini</td><td>$5 / 1M tokens</td><td>$0.80 / 1M</td><td>$3.20 / 1M</td></tr>
<tr><td>GPT-4.1 nano</td><td>$1.50 / 1M tokens</td><td>$0.20 / 1M</td><td>$0.80 / 1M</td></tr>
</table>
</div>
<div class="footer"><span>15</span><span>fine-tuned runtime still has a meter</span></div>
</section>
<section class="slide" data-notes="This is where you pivot to the local model story. The original plan was reasonable: use a local SLM and LoRA.">
<div class="kicker">My original plan</div>
<div class="body center">
<h2>Use LoRA on a local SLM.</h2>
<p class="subtitle">Adapt a small language model to WhetstoneDSL decisions.</p>
</div>
<div class="footer"><span>16</span><span>the first instinct</span></div>
</section>
<section class="slide" data-notes="LoRA adapters can be small, but the base model still has to be loaded and run. That is the key point.">
<div class="kicker">LoRA still carries the base model</div>
<div class="body">
<ul class="bullets">
<li>1B / 3B / 7B parameter base</li>
<li>adapter is small</li>
<li>runtime model is still big</li>
</ul>
</div>
<div class="footer"><span>17</span><span>adapter small, base still large</span></div>
</section>
<section class="slide" data-notes="This is the conceptual turn. Do not adapt a big object until you prove the task deserves one.">
<div class="kicker">The better question</div>
<div class="body center">
<h2>Was the task ever large enough to deserve that model?</h2>
</div>
<div class="footer"><span>18</span><span>question the premise</span></div>
</section>
<section class="slide" data-notes="Now introduce WhetstoneDSL with audience context from your AST-first talk.">
<div class="kicker">Where this came from</div>
<div class="body center">
<h2>WhetstoneDSL</h2>
<p class="subtitle">AST-first programming and universal transpiling</p>
</div>
<div class="footer"><span>19</span><span>creation story</span></div>
</section>
<section class="slide" data-notes="Define taskitems in normal project-management language. This makes prereq_ops understandable.">
<div class="kicker">What a taskitem is</div>
<div class="body">
<ul class="bullets small-bullets">
<li>a small implementation work packet</li>
<li>title, requirements, constraints</li>
<li>acceptance criteria and dependencies</li>
</ul>
</div>
<div class="footer"><span>20</span><span>work packet</span></div>
</section>
<section class="slide" data-notes="A taskitem is not just text. Before it runs, the pipeline needs to decide what prep work is required.">
<div class="kicker">Taskitems need prep decisions</div>
<div class="body center">
<h2>What has to happen before this task runs?</h2>
</div>
<div class="footer"><span>21</span><span>the gate question</span></div>
</section>
<section class="slide" data-notes="This is the WhetstoneDSL gate in plain English. Avoid saying prereq_op first; say prep checklist first.">
<div class="kicker">The prep checklist</div>
<div class="body">
<ul class="bullets small-bullets">
<li>validate the intake</li>
<li>resolve dependencies</li>
<li>send to architect review</li>
</ul>
</div>
<div class="footer"><span>22</span><span>small yes/no decisions</span></div>
</section>
<section class="slide" data-notes="Now give the technical gate name after the audience understands the decision.">
<div class="kicker">In the repo</div>
<div class="body center">
<h2><code>prereq_op_selector</code></h2>
<p class="subtitle">picks the prerequisite operations for a taskitem</p>
</div>
<div class="footer"><span>23</span><span>technical name</span></div>
</section>
<section class="slide" data-notes="This is the tiny-transformer approach in one sentence.">
<div class="kicker">Tiny transformer gate</div>
<div class="body center">
<h2>Learn the messy input.</h2>
<p class="subtitle">Keep the output menu fixed.</p>
</div>
<div class="footer"><span>24</span><span>middle path</span></div>
</section>
<section class="slide" data-notes="This is your actual hardware and training-time number. This makes the project feel grounded.">
<div class="kicker">Actual training cost</div>
<div class="body center">
<div>
<div class="metric"><strong>3 to 5</strong><span>minutes</span></div>
<div class="metric"><strong>3060</strong><span>RTX GPU</span></div>
</div>
<p class="subtitle">per transformer gate</p>
</div>
<div class="footer"><span>25</span><span>consumer hardware</span></div>
</section>
<section class="slide" data-notes="These are the actual model-scale numbers from the WhetstoneRSA materials.">
<div class="kicker">Actual model scale</div>
<div class="body center">
<div>
<div class="metric"><strong>213K</strong><span>parameters</span></div>
<div class="metric"><strong>800KB</strong><span>checkpoint</span></div>
</div>
<p class="subtitle">one specialist per small gate</p>
</div>
<div class="footer"><span>26</span><span>the whole model is small</span></div>
</section>
<section class="slide" data-notes="The data was bootstrapped while using an LLM. That is a feature of the story: use the LLM to create scaffolding, then remove it from repeated runtime.">
<div class="kicker">Training data source</div>
<div class="body center">
<h2>LLM as scaffolding.</h2>
<p class="subtitle">Use it to bootstrap examples, not to sit in every runtime decision.</p>
</div>
<div class="footer"><span>27</span><span>distill repeated decisions</span></div>
</section>
<section class="slide" data-notes="Synthetic data matters because small gates are easy to intentionally vary. You can oversample edge cases and phrase variants.">
<div class="kicker">Synthetic data can help</div>
<div class="body">
<ul class="bullets small-bullets">
<li>generate taskitem variants</li>
<li>assign known labels</li>
<li>oversample edge cases</li>
<li>train the tiny gate directly</li>
</ul>
</div>
<div class="footer"><span>28</span><span>cheap dataset iteration</span></div>
</section>
<section class="slide" data-notes="These are the actual extraction numbers. Keep them short.">
<div class="kicker">First extracted dataset</div>
<div class="body center">
<div>
<div class="metric"><strong>1297</strong><span>clean rows</span></div>
<div class="metric"><strong>1102</strong><span>train</span></div>
<div class="metric"><strong>195</strong><span>eval</span></div>
</div>
</div>
<div class="footer"><span>29</span><span>real pipeline artifacts</span></div>
</section>
<section class="slide" data-notes="This is an important engineering lesson. One of the supposed model outputs was actually a constant rule.">
<div class="kicker">The data caught a design mistake</div>
<div class="body center">
<h2><code>needs_validate_intake</code></h2>
<p class="subtitle">was always true: <span class="accent">1297 / 1297</span></p>
</div>
<div class="footer"><span>30</span><span>not a learned decision</span></div>
</section>
<section class="slide" data-notes="So the gate was split into smaller gates. This is a good result: cheap experiments reveal better architecture.">
<div class="kicker">Split the gate</div>
<div class="body center">
<div class="flow two">
<div class="box cyan"><div class="label">Gate 1</div><div class="main">resolve dependencies?</div></div>
<div class="box blue"><div class="label">Gate 2</div><div class="main">architect review?</div></div>
</div>
</div>
<div class="footer"><span>31</span><span>smaller decisions</span></div>
</section>
<section class="slide" data-notes="The results are not production-ready. Say that directly. The point is that the experiment cost was so low that failure is informative.">
<div class="kicker">First results</div>
<div class="body center">
<table class="table">
<tr><th>Gate</th><th>Accuracy</th><th>Training</th></tr>
<tr><td>resolve dependencies</td><td>69.4%</td><td>3-5 min on 3060</td></tr>
<tr><td>architect review</td><td>75.0%</td><td>3-5 min on 3060</td></tr>
</table>
</div>
<div class="footer"><span>32</span><span>diagnostic, not a victory lap</span></div>
</section>
<section class="slide" data-notes="This explains why the first results were weak without making the project sound weak. The input fields were not designed for this classifier.">
<div class="kicker">What we learned</div>
<div class="body center">
<h2>1297 rows did not mean 1297 different examples.</h2>
<p class="subtitle">There were only about <span class="accent">17 unique text templates</span>.</p>
</div>
<div class="footer"><span>33</span><span>row count is not diversity</span></div>
</section>
<section class="slide" data-notes="This is the central comparison slide. The message is not that tiny transformers always win. It is that they are a real middle option.">
<div class="kicker">The comparison</div>
<div class="body center">
<table class="table">
<tr><th>Approach</th><th>Input handling</th><th>Runtime</th><th>Output control</th></tr>
<tr><td>Regex</td><td>manual enumeration</td><td>tiny</td><td>excellent</td></tr>
<tr><td>LLM / SLM + LoRA</td><td>easy</td><td>base model still runs</td><td>needs guardrails</td></tr>
<tr><td>Tiny gate transformer</td><td>learned</td><td>~800KB specialist</td><td>fixed output head</td></tr>
</table>
</div>
<div class="footer"><span>34</span><span>the middle path</span></div>
</section>
<section class="slide" data-notes="End with the clean contrast. This is the line to remember.">
<div class="kicker">Final claim</div>
<div class="body center">
<div class="stack">
<div class="bigline">LoRA adapts a large model to the task.</div>
<div class="bigline"><span class="accent">WhetstoneRSA asks whether the task deserved the large model.</span></div>
</div>
</div>
<div class="footer"><span>35</span><span>small menu, small machine</span></div>
</section>
</div>
<div class="hint">Click / arrows: navigate · N: notes · F: fullscreen</div>
<div class="notes" id="notes"></div>
<div class="progress" id="progress"></div>
<script>
const slides = Array.from(document.querySelectorAll(".slide"));
const notes = document.getElementById("notes");
const progress = document.getElementById("progress");
let index = 0;
let notesVisible = false;
function indexFromHash() {
const raw = window.location.hash.replace("#", "");
const requested = Number(raw);
if (Number.isInteger(requested) && requested >= 1 && requested <= slides.length) {
index = requested - 1;
}
}
function render(updateHash = true) {
slides.forEach((slide, i) => slide.classList.toggle("active", i === index));
progress.style.width = `${((index + 1) / slides.length) * 100}%`;
notes.innerHTML = `<strong>Speaker notes:</strong><br>${slides[index].dataset.notes || ""}`;
notes.classList.toggle("visible", notesVisible);
document.title = `(${index + 1}/${slides.length}) WhetstoneRSA`;
if (updateHash) {
history.replaceState(null, "", `#${index + 1}`);
}
}
function next() {
index = Math.min(slides.length - 1, index + 1);
render();
}
function prev() {
index = Math.max(0, index - 1);
render();
}
document.addEventListener("click", (event) => {
if (event.target.closest(".notes")) return;
next();
});
document.addEventListener("keydown", (event) => {
if (event.key === "ArrowRight" || event.key === "PageDown" || event.key === " ") {
event.preventDefault();
next();
} else if (event.key === "ArrowLeft" || event.key === "PageUp" || event.key === "Backspace") {
event.preventDefault();
prev();
} else if (event.key.toLowerCase() === "n") {
notesVisible = !notesVisible;
render();
} else if (event.key.toLowerCase() === "f") {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen();
} else {
document.exitFullscreen();
}
}
});
window.addEventListener("hashchange", () => {
indexFromHash();
render(false);
});
indexFromHash();
render(false);
</script>
</body>
</html>