File size: 14,301 Bytes
5ae41ba 39de7f1 5ae41ba 6512e07 a77efaf 6512e07 5ae41ba a77efaf 5ae41ba daff47b 5ae41ba a77efaf 5ae41ba 783a9bb | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | <!DOCTYPE html>
<!-- Exam Panic Rescue field notes -->
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Exam Panic Rescue — Field Notes</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Newsreader:ital,opsz,wght@0,6..72,400;0,6..72,500;0,6..72,600;1,6..72,400&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
:root{
--ink:#13201c; --soft:#3c4b45; --faint:#6b7a73;
--green:#005844; --green-d:#03372c; --coral:#84231b;
--paper:#ffffff; --rule:#e7e2d6; --wash:#f6f4ee;
--measure:40rem;
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
margin:0; background:var(--paper); color:var(--ink);
font-family:"Inter",system-ui,sans-serif; font-size:19px; line-height:1.7;
-webkit-font-smoothing:antialiased;
}
.wrap{max-width:var(--measure); margin:0 auto; padding:0 7vw;}
@media(min-width:760px){ .wrap{padding:0 24px;} }
header.masthead{
border-bottom:2px solid var(--ink); margin-top:56px; padding-bottom:14px;
display:flex; justify-content:space-between; align-items:baseline; gap:16px;
}
.masthead .brand{font-family:"Inter"; font-weight:700; letter-spacing:.16em; text-transform:uppercase; font-size:13px; color:var(--green);}
.masthead .meta{font-size:13px; color:var(--faint); letter-spacing:.04em;}
h1{
font-family:"Newsreader",serif; font-weight:600; font-size:clamp(2.4rem,6vw,3.6rem);
line-height:1.05; letter-spacing:-.015em; margin:38px 0 10px;
}
.dek{font-family:"Newsreader",serif; font-style:italic; font-size:clamp(1.15rem,2.6vw,1.5rem); color:var(--soft); line-height:1.45; margin:0 0 26px; max-width:34rem;}
.byline{font-size:14px; color:var(--faint); border-top:1px solid var(--rule); border-bottom:1px solid var(--rule); padding:12px 0; margin-bottom:40px; letter-spacing:.02em;}
.byline b{color:var(--green-d); font-weight:600;}
article h2{
font-family:"Newsreader",serif; font-weight:600; font-size:clamp(1.5rem,3.4vw,2rem);
letter-spacing:-.01em; margin:48px 0 4px; line-height:1.15;
}
article h2 .num{display:block; font-family:"Inter"; font-weight:700; font-size:12px; letter-spacing:.18em; text-transform:uppercase; color:var(--coral); margin-bottom:8px;}
article h3{font-family:"Inter"; font-weight:700; font-size:1.06rem; margin:30px 0 2px; color:var(--green-d);}
p{margin:14px 0;}
a{color:var(--green); text-underline-offset:3px; text-decoration-thickness:1px;}
strong{color:var(--green-d);}
.lead{font-size:1.12rem;}
.lead::first-letter{
font-family:"Newsreader",serif; font-weight:600; float:left; font-size:4.2rem; line-height:.78;
padding:6px 12px 0 0; color:var(--coral);
}
ul{margin:14px 0; padding-left:1.1em;}
li{margin:9px 0;}
li::marker{color:var(--green);}
.pull{
border-left:3px solid var(--green); background:var(--wash); margin:30px 0;
padding:18px 22px; font-family:"Newsreader",serif; font-style:italic; font-size:1.3rem;
line-height:1.4; color:var(--green-d);
}
.models{border:1px solid var(--rule); border-radius:12px; overflow:hidden; margin:26px 0;}
.models .row{display:grid; grid-template-columns:1fr; gap:2px 18px; padding:14px 18px; border-bottom:1px solid var(--rule);}
@media(min-width:620px){ .models .row{grid-template-columns:15rem 1fr;} }
.models .row:last-child{border-bottom:0;}
.models .row b{color:var(--green-d); font-weight:600;}
.models .row span{color:var(--soft); font-size:.96rem;}
.note{font-size:.92rem; color:var(--faint);}
hr.div{border:0; border-top:1px solid var(--rule); margin:46px 0;}
.links{background:var(--green-d); color:#f3efe4; border-radius:14px; padding:26px 26px; margin:40px 0 8px;}
.links h2{color:#fff; margin:0 0 12px; font-size:1.3rem;}
.links a{color:#ffd9b0; display:inline-block; word-break:break-word;}
.links .lrow{padding:8px 0; border-top:1px solid rgba(255,255,255,.16); font-size:.98rem;}
.links .lrow:first-of-type{border-top:0;}
.links .lrow b{color:#fff; display:block; font-size:.8rem; letter-spacing:.12em; text-transform:uppercase; margin-bottom:2px; font-weight:700;}
footer{margin:30px 0 80px; font-size:13px; color:var(--faint); line-height:1.6;}
</style>
</head>
<body>
<div class="wrap">
<header class="masthead">
<span class="brand">Field Notes</span>
<span class="meta">Build Small Hackathon · Backyard AI</span>
</header>
<h1>A calm tool, built on small models</h1>
<p class="dek">What I learned shipping Exam Panic Rescue — a last-minute study triage app that runs entirely on models you wouldn't call large.</p>
<p class="byline">A build report for <b>Exam Panic Rescue</b> · OpenBMB MiniCPM · NVIDIA Nemotron · Hugging Face ZeroGPU · ≤32B throughout</p>
<article>
<p class="lead">Every exam season has the same bad hour. Two hours left, the syllabus is a wall, and you're rereading the same page without retaining a word. You're not studying anymore — you're panicking with a book open. I wanted a tool that does one thing for that exact moment: tell a stressed student what to do <em>next</em>, and nothing more.</p>
<p>Exam Panic Rescue is deliberately narrow. A student pastes what they half-know, what's scaring them, and how many minutes are left — or snaps a photo of their syllabus — and gets back one ranked rescue plan, five practice drills written for their own topics, a triage clock that runs in real time, and a one-page final sheet to read before they walk in. It can read that sheet aloud. That's the whole product. The hard part was resisting everything else.</p>
<h2><span class="num">★ — Real-world proof</span>What happened when a real student used it</h2>
<p>The test that matters for a tool like this isn't a benchmark — it's whether a real person reaches for it in their actual worst hour. The day before a university <strong>Machine Learning</strong> exam, a final-year student (I'll call them <strong>R.</strong>, shared with their consent and anonymized) opened the live app with eight hours left and this panic dump:</p>
<div class="pull">"I know the basics of backpropagation but I keep going blank on the mathematical derivations of backprop and CNN convolutional dimensions. I'm afraid I'll freeze when calculating output sizes."</div>
<p>The small model wrote them a recall-first plan, a triage clock across the eight hours, and five drills aimed exactly at the leak — parameter counts, a CNN output-dimension calculation, a cross-entropy gradient derivation, and a max-pooling output-size question.</p>
<p><strong>The next day, one of those model-written drills closely matched a question that actually appeared on the exam.</strong> R. said the tool was genuinely useful. That's the whole thesis in one real data point: a small model, given a tight job, produced practice that mapped onto a real exam for a real student. The full anonymized session is in the public <a href="https://huggingface.co/datasets/build-small-hackathon/exam-panic-rescue-build-trace" target="_blank" rel="noopener noreferrer">build-trace dataset</a> (the <code>real_user</code> config).</p>
<h2><span class="num">01 — The constraint</span>Small models, on purpose</h2>
<p>The hackathon rule is a ceiling: nothing over 32B. I treated it as a design value instead of a limitation. A panicking student doesn't need a frontier model to be told "stop opening new chapters and protect these five marks." The intelligence that matters here is <strong>judgment under time pressure</strong>, and small models are more than enough to write good drills and a tight plan — if you give them a tight job.</p>
<div class="models">
<div class="row"><b>OpenBMB MiniCPM-V-4.5</b><span>The primary engine. Writes the rescue plan, drills, and answers — and, being a vision-language model, reads a photo of the syllabus directly in the same call.</span></div>
<div class="row"><b>OpenBMB VoxCPM2</b><span>Reads the final sheet aloud for the last-minute walk-in.</span></div>
<div class="row"><b>NVIDIA Nemotron-Mini-4B</b><span>Selectable text-only alternate (4B).</span></div>
<div class="row"><b>OpenBMB MiniCPM4 0.5B (GGUF)</b><span>Runs through the llama.cpp runtime on CPU — the Llama Champion path, and a genuinely tiny 0.5B Tiny Titan.</span></div>
</div>
<p class="note">All five run on Hugging Face ZeroGPU. Every generation prints a runtime note saying exactly which model ran and on what hardware — so the model behind any output is never ambiguous.</p>
<h2><span class="num">02 — The lesson that cost me the most</span>Cold starts on a shared GPU</h2>
<p>ZeroGPU is wonderful and free, but it has a shape you have to design around: the GPU is only attached <em>inside</em> a decorated function, and that function has a strict time budget. My first version loaded each model inside that budget. The default model stayed warm and was instant. But the moment a student picked the Nemotron engine, or uploaded the first photo, the app had to <strong>download several gigabytes of weights inside the GPU window</strong> — and a cold download plus load plus generation blew straight through the limit. ZeroGPU aborted the call, and the user got the deterministic fallback instead of the real model.</p>
<p>The symptom was maddening: the same code that worked beautifully on the second call fell back instantly on the first. The fix, once I understood it, was small and clean — <strong>prefetch the weights on the CPU, before ever touching the GPU.</strong> Move the multi-gigabyte download out of the timed window so the GPU call only pays the fast load-and-generate cost. After that, a cold first call returns real model output instead of a template. I verified it live: the exact Nemotron call that used to fall back now returns a real packet.</p>
<div class="pull">The bug taught me the platform. The download wasn't slow — it was in the wrong place.</div>
<h2><span class="num">03 — Honesty as a feature</span>Never crash, never lie</h2>
<p>Because the model can be cold, or the GPU can be busy, or a node can fault, I decided early that the app must <strong>always return a complete, useful packet</strong> — and must always tell the truth about how it made it. So there's a deterministic study engine underneath every model path. If a model is unavailable, the student still gets a real plan, real drills, and a real triage clock from templates, with a runtime note that says plainly "fallback used." Nothing errors out in a student's face, and nothing pretends a model ran when it didn't.</p>
<p>This turned out to matter for judging too. For a Backyard AI tool, the trust comes from the thing being honest about its own limits — a runtime note that says "Generated with MiniCPM-V-4.5 on ZeroGPU" or "fallback used" is worth more than a confident black box.</p>
<h2><span class="num">04 — Small things that were not small</span>Getting the details right</h2>
<h3>The time math</h3>
<p>The triage clock splits the remaining minutes into blocks. My first version's blocks didn't sum back to the total — a rounding leak. Rewriting it with largest-remainder apportionment fixed it so the clock is always exactly the time the student actually has, from 15 minutes to a full day.</p>
<h3>Designing for a panicking human</h3>
<p>An overflowing examples table made the demo feel like a spreadsheet, so it became four large one-tap panic cases. A dark-mode rendering bug hid dark label text on dark surfaces, so I forced the cream light theme the whole design was built for. The copyable field-note block overflowed on a 390px phone until I wrapped it. None of this is glamorous; all of it is the difference between "tool" and "toy."</p>
<h3>The operational reality of a free Space</h3>
<p>A live ZeroGPU Space is a real piece of infrastructure. I hit a transient ECC GPU fault (fixed by a restart), and a Space that paused itself after a burst of heavy testing. The lesson: treat the live demo like production — verify it end to end, and check it's actually <em>running</em> before you rely on it.</p>
<h2><span class="num">05 — What's still open</span>Honest gaps</h2>
<ul>
<li><strong>The real test is a real student.</strong> The Backyard AI track is judged on whether the person you built it for actually used it. The app ships a field-note prompt to capture an honest before/after — and that's the validation I care about most.</li>
<li><strong>First-call latency on secondary models.</strong> The prefetch fix trades a fast-but-fake fallback for real-but-slower output on a cold first call. For a panic tool, I think real wins — but warming the model before a live demo is still the move.</li>
</ul>
<hr class="div">
<p>If there's one thing I'd take to the next build: a tight job for a small model, an honest fallback under it, and a runtime note that never lies, will get you a tool people can actually trust in their worst hour. You don't need a giant model to rescue one stressed student.</p>
<div class="links">
<h2>Try it / read the code</h2>
<div class="lrow"><b>Live app</b><a href="https://huggingface.co/spaces/build-small-hackathon/exam-panic-rescue" target="_blank" rel="noopener noreferrer">huggingface.co/spaces/build-small-hackathon/exam-panic-rescue</a></div>
<div class="lrow"><b>Code</b><a href="https://github.com/himanshu748/exam-panic-rescue" target="_blank" rel="noopener noreferrer">github.com/himanshu748/exam-panic-rescue</a></div>
<div class="lrow"><b>Open build traces</b><a href="https://huggingface.co/datasets/build-small-hackathon/exam-panic-rescue-build-trace" target="_blank" rel="noopener noreferrer">huggingface.co/datasets/build-small-hackathon/exam-panic-rescue-build-trace</a></div>
</div>
</article>
<footer>
Built for the Build Small Hackathon · Backyard AI track. Models: OpenBMB MiniCPM (text, vision, voice), NVIDIA Nemotron-Mini-4B, all ≤32B on Hugging Face ZeroGPU. MIT licensed.
</footer>
</div>
</body>
</html>
|