I built my friend a study ghost that runs with the Wi-Fi off
DEV Community

I built my friend a study ghost that runs with the Wi-Fi off

This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend What I Built Three days before Anushka's Microbiology exam, the problem wasn't that she wasn't studying. She was studying constantly, and still failing, because she was re-reading the chapters she already knew. Nobody had ever told her which topics she was actually weak at. You can't see that from the inside. So I built Ghost Tutor: a study ghost that lives in a notebook on a desk, reads her notes, and quizzes her until it finds the cracks. She pastes in her notes. The ghost splits them into topics, writes multiple-choice questions grounded in her own material, and tracks which topics she keeps getting wrong. It always serves her weakest topic first. It marks her wrong answers in red pen, bleeds ink into the page, throws a crumpled ball of paper onto the desk, and stamps her report card like a tired teacher: READY , NEEDS WORK , or SEE ME AFTER CLASS . It also roasts her, if she asks it to. She picks the ghost's mood by its face. The important part: it runs entirely on a laptop. No account, no API key, no internet. Her notes never leave her machine. Demo Visit the live app: https://ghosttutors.onrender.com/ Paste some sample notes in the Notes tab, then go to Study and answer a question. The ghost writes it live from your notes. Turn off your Wi-Fi and ask another question in the Ask tab - it still works. That's the money shot. Code ๐Ÿ‘ป Ghost Tutor A study ghost that reads a friend's notes, finds the cracks, and haunts them until the exam. Built on open-weight Gemma. Runs fully on a laptop with zero API keys. Every cloud integration switches on with one env var and falls back gracefully when it isn't set. Live demo → ghosttutors.onrender.com How it works Your notes │ โ–ผ [ Gemma splits into topics ] │ ├──โ–ถ Study tab ──โ–ถ MCQ written from your notes ──โ–ถ answer ──โ–ถ mastery score updated │ ↑ weakest topic first (Beta + spaced repetition) │ ├──โ–ถ Ask tab ──โ–ถ Mastra agent picks a tool ──โ–ถ search_notes / get_progress / │ remember / find_web_practice ──โ–ถ grounded answer │ ├──โ–ถ Report tab ──โ–ถ TabPFN reads 7 features per attempt ──โ–ถ predicted exam score │ └──โ–ถ Plan tab ──โ–ถ day-by-day schedule, weakest topics first, ends in mock test At 9 pm each night, a… Clone it and you are two commands from a working tutor: npm install && npm start With nothing else installed it still works - it cuts fill-in-the-blank questions straight out of your notes and labels them offline · from your notes , so it never pretends to be smarter than it is. Add Ollama and the ghost starts writing real questions. How I Built It Gemma 3 4B (open weights, via Ollama) is the brain. It splits notes into topics, writes the questions, reacts in character, and explains the answers. Embeddings come from nomic-embed-text , also local. Mastra runs the "Ask the Ghost" agent, with four tools over the student's own data: search_notes , get_progress , remember , and find_web_practice . Ask "which topic am I weakest at?" and it calls get_progress ; ask "explain Mitochondria" and it calls search_notes . It picks correctly on its own - here it is in the server log, deciding: [agent] tool get_progress() [agent] tool search_notes("Mitochondrial structure") ElevenLabs gives the ghost a real voice and listens to spoken answers. MongoDB Atlas stores the student profile, long-term agent memory, quiz history, and generated questions - so the ghost remembers everything across sessions. Tiger Data runs pgvector + full-text hybrid search (RRF) over notes and a Timescale hypertable of attempts, so recall is fast and grounded. SerpApi brings fresh web practice questions for topics Anushka is weak at, so studying never goes stale. Sentry traces every LLM call, tool invocation, and partner integration, so I can see exactly what the ghost did and how long it took. Render hosts the live app and Temporal worker, so Anushka can use it from anywhere. The bug that justifies the whole project The first real question Gemma wrote was good: Which organelle is responsible for cellular respiration? Options: Ribosome / Mitochondrion / Lysosome / Golgi Apparatus "answer": 2 ← Lysosome "explanation": "The mitochondrion is the powerhouse of the cell… it produces energy through cellular respiration." Read it twice. The model's own explanation says Mitochondrion. Its answer index says Lysosome. It did this on three runs out of three. A 4B model can reason about the content and still not count to three. If I had shipped that, Anushka would have been taught the wrong answer, in her own notes' words, with a confident explanation attached. That is worse than no tutor at all. The fix was to stop asking the model to do the thing it is bad at. Now it returns the correct answer as text plus three wrong ones, and my code shuffles them and computes the index: const options = [correct, ...wrong].sort(() => Math.random() - 0.5); return { options, answer: options.indexOf(correct) }; Then it checks the correct answer actually appears in the student's notes, and regenerates if it doesn't. Two tests lock it down - one runs the shuffle 20 times and asserts the index always lands on the right option. Gemma also returned 8 options because it copied my prompt's placeholder letters, asked the same question three times in a row, and leaked ** markdown into the ghost's dialogue. All fixed, all found by running it. Why Does Open Innovation Matter? I could see the model fail. That is the entire argument. A closed API would have handed me the same confidently wrong JSON, and I would have had no way to watch it happen three times, read the raw output, and conclude this model cannot pick an index. I could run it a hundred times for free while I figured that out. Metering that debugging loop would have shortened it, and I'd have shipped the bug. I swapped the model mid-build, in one line. Gemma 3 can't call tools in Ollama, so the Mastra agent couldn't use its tools. I pulled Gemma 4, set AGENT_MODEL=gemma4:e2b-it-q4_K_M , and the agent started calling get_progress on its own. Questions still run on Gemma 3, because it's faster. Two models, each doing what it's good at, picked by me, swappable by anyone who clones this. It costs nothing per question. Someone cramming for an exam asks hundreds of questions a night. Any per-token price turns a study tool into a thing you ration. The ghost is free to pester Anushka forever, which is the only way a tutor works. Her notes stay hers. A student's notes are an unflattering picture of what she doesn't understand yet. Those shouldn't be sitting in someone's logs. On this build they never leave the laptop. And it works with the Wi-Fi off. That's not a hypothetical where she lives. It is the difference between a study tool and a study tool that was there the night before the exam. What Anushka Said "This is actually really useful. The questions are hard and it remembers what I got wrong. Also the ghost roasting me is weirdly motivating." Prize Categories - Best Use of Gemma - Gemma 3 4B writes every question and explanation locally; Gemma 4 E2B drives the tool-calling agent. - Best Use of Mastra - Agent orchestrates four tools ( search_notes ,get_progress ,remember ,find_web_practice ) over the student's own data, picking correctly on its own. - Best Use of MongoDB Atlas - Stores student profile, long-term agent memory, quiz history, and generated questions across sessions. - Best Use of Tiger Data - Runs pgvector + full-text hybrid search (RRF) for note recall and Timescale hypertable for attempt time series. - Best Use of SerpApi - Brings fresh web practice questions for weak topics so studying never goes stale. - Best Use of ElevenLabs - Tutor voice (TTS) for questions and spoken answer input (STT). - Best Use of Sentry Agent Tracing - Traces every LLM call, tool invocation, and partner integration to show what the ghost did and how long it took. - Best Use of Render - Hosts the live app so the ghost works from anywhere. - Best Use of GitHub Copilot - Copilot reviewed the PR and caught inconsistencies in the agent tool signatures. Top comments (0)

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.