Said It: Gemma finds the 6 promises I forgot, offline, in 17 seconds
This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady What I Built "Kal bhej dunga" is the most broken promise in India, and I've said it in every group chat I'm in. Sai
This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
What I Built
"Kal bhej dunga" is the most broken promise in India, and I've said it in every group chat I'm in.
Said It reads your exported WhatsApp chat on your own laptop, finds the promises you made, works out which ones are late, and drafts the "sorry, here it is" reply. Gemma runs locally in Ollama, so 0 bytes of your chat leave the machine.
Who gets to be lazier: anyone in a group project, a flat group or a family chat who types "will do tomorrow" and then sleeps for a week.
| Task | Before | With Said It | Saved |
|---|---|---|---|
| Find every promise I made | Reread all 29 messages | 16.9 s, 17 local model calls | the reread |
| Messages I actually read | 29 | 6 cards (3 late, 2 due soon, 1 already kept) | 23 fewer (β79%) |
| Turn "kal" / "parso" into a date a week later | Mental math (or forget) | Computed in code: kal = +1 day, parso = +2 | No guessing |
| Write the apology reply | sit there wording it | Drafted in 0.86 s, 9 words | the blank-box stare |
By the numbers
-
3.4 GB: the whole model (
gemma3:4b) on disk - 16.9 s: a full run of 17 Gemma calls on an RTX 4050 Laptop GPU
- ~50 tokens/s: average generation speed (range 42β56)
- 6 / 6: promises found in the sample chat, with 0 decoys flagged
-
0 bytes: chat text sent anywhere except
localhost:11434 - 3: commands to run it
Demo
Live site: ayushkr23.github.io/said-it. Without Ollama it replays a real recorded run. With Ollama, it runs live on your own machine.
Watch the 1:23 explainer: YouTube
Said It
Finds the promises you made in a WhatsApp export, on your laptop, with Gemma through Ollama. Chat text is never sent to a remote API.
π¬ Project Demo
βΆοΈ Watch the SAID-IT Demo
Live demo Β· MIT Β· Vite 8 Β· React 19 Β· TypeScript
https://github.com/ayushkr23/said-it/blob/main/docs/said-it.mp4
The 1:23 demo: the chat, Gemma finding the promises, and the one reply. Sound on.
What it does
Export a WhatsApp chat (.txt, or the .zip WhatsApp writes). Drop it in. Said It:
- Parses the export in the browser
- Reads only your messages
- Asks
gemma3:4bto quote the commitment words - Turns
kal/parso/ weekday names into dates in code - Asks a yes/no βalready kept?β question per candidate
- Drafts one reply, under 25 words
On the bundled sample chat (src/data/sample-chat.txt + src/data/recorded.json):
| Before | With Said It | |
|---|---|---|
| Messages you read | 29 | 6 cards (3 late, 2 due |
Try this in 60 seconds:
- On the home page, pull the lever. Everyone else's messages drop away and only your promises are left, stamped.
- Flip the Open switch to see what changes when the model lives on your laptop.
- Open Run it and press Replay a recorded run: all 17 calls stream in with real timings, no install needed.
- Have Ollama? Drop the bundled sample chat (or your own
.txt/.zipexport) and watch Gemma work live.
Code
Said It
Finds the promises you made in a WhatsApp export, on your laptop, with Gemma through Ollama. Chat text is never sent to a remote API.
π¬ Project Demo
βΆοΈ Watch the SAID-IT Demo
Live demo Β· MIT Β· Vite 8 Β· React 19 Β· TypeScript
https://github.com/ayushkr23/said-it/blob/main/docs/said-it.mp4
The 1:23 demo: the chat, Gemma finding the promises, and the one reply. Sound on.
What it does
Export a WhatsApp chat (.txt, or the .zip WhatsApp writes). Drop it in. Said It:
- Parses the export in the browser
- Reads only your messages
- Asks
gemma3:4bto quote the commitment words - Turns
kal/parso/ weekday names into dates in code - Asks a yes/no βalready kept?β question per candidate
- Drafts one reply, under 25 words
On the bundled sample chat (src/data/sample-chat.txt + src/data/recorded.json):
| Before | With Said It | |
|---|---|---|
| Messages you read | 29 | 6 cards (3 late, 2 due |
said-it/
βββ src/lib/whatsapp.ts # parses WhatsApp exports (.txt / .zip)
βββ src/lib/promises.ts # filter β classify β dates β kept? β reply
βββ src/lib/ollama.ts # one fetch to localhost:11434, JSON-schema output
βββ src/sections/ # lever, night timeline, details, open switch
βββ src/pages/Run.tsx # drop your export, run live or replay
βββ scripts/check-parse.ts # end-to-end run on the sample chat
Quick start: 3 commands (with Node and Ollama installed):
ollama pull gemma3:4b
git clone https://github.com/ayushkr23/said-it && cd said-it && npm i
npm run dev
License: MIT Β· TypeScript Β· React 19 Β· Vite 8 Β· motion Β· fflate Β· Tests: 0 unit tests, 1 end-to-end check script
How I Built It
A small model can't be trusted with judgement, so I gave it only the jobs it can do and checked everything else in code.
WhatsApp export (.txt / .zip, unzipped in the browser)
β
βΌ
parse β keep only MY messages (β₯3 words, recent)
β
βΌ
βββββββββ Gemma 3 4B via Ollama (localhost:11434) βββββββββ
β 1. classify each message β must QUOTE the promise words β
β 2. "already kept?" yes/no per candidate β
β 3. draft one reply β€ 25 words β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β²
βΌ β code checks: quote exists? done-marker?
due dates computed in code β late / soon / kept β UI
Why gemma3:4b: it's 3.4 GB, runs at ~50 tok/s on a laptop GPU, and handled Hinglish lines like "parso tak viva questions ka doc share karta hu" in my sample with no translation step.
The pipeline (runs on demand, once per export):
- Parse and filter in the browser: 29 messages become 9 of mine worth reading.
- Classify, one message per call: 9 calls, ~1.38 s each. The output is forced into a JSON schema.
- Date in code: "kal" = +1 day, "parso" = +2. A promise with no date goes stale after 2 days.
- "Already kept?" check: 7 calls, ~0.51 s each, comparing each promise with later messages.
- Reply for the easiest late promise: 1 call, 0.86 s, under 25 words, retried if the rules fail.
Design decisions:
- One message per call, so a single confusing line can't throw off the whole batch.
- The model never does date maths. Code does.
- Temperature is 0.1 and the output is JSON only, so runs repeat closely.
What was hard:
- Gemma said "yes, promise" to almost everything. The fix: the schema makes it quote the exact commitment words before deciding, and code rejects the result if that quote isn't really in the message.
- "Sent the SQL dump" looked like a promise. Past-tense completion words ("sent", "booked", "done", plus Hindi equivalents) are now filtered out before Gemma ever sees the message.
- Saying a promise was kept was too easy. I narrowed it to one yes/no question per candidate, against messages that came after it.
Tradeoffs and limitations:
- Accuracy is measured on one sample chat I wrote myself (6 promises, 3 decoys). That's a smoke test, not a benchmark.
- The parser targets Android export format. The UI accepts a
.zip(how iPhone exports often arrive); treat iOS as unverified. - Fonts load from Google Fonts. No chat data goes with that request. "Works with wifi off" is not verified.
- The hosted site needs
OLLAMA_ORIGINSset before it can talk to your local Ollama. Until then, replay still works.
Why Does Open Innovation Matter?
A group chat is the most private text you own, and it's full of friends who never agreed to have it uploaded.
| Closed API | Open-weight Gemma (Said It) | |
|---|---|---|
| Chat text sent out | Every message you analyse | 0 bytes |
| Cost per run (~5,900 tokens) | Per-token billing | βΉ0 marginal |
| Needs internet | Yes | No, except Google Fonts on first load |
| Model changes under you | Whenever the provider updates it | Pinned: gemma3:4b
|
| Can you inspect it? | Prompts only | Prompts, schema, weights |
Said It only works because the model sits next to the data. A pinned open model means my 6/6 result is the same next month; a silently updated closed model could break the quote check overnight.
Fork it, point Ollama at a different open model, and you have a promise tracker for Telegram, Slack or your own language.
The Lazy Payoff
Every run costs 16.9 seconds and βΉ0. The time it saves is the reread you no longer do.
On the sample: 29 messages down to 6 cards, one 9-word reply, 23 messages you don't have to look at again. That's the sloth version of a weekly review.
I haven't timed a stranger using it yet. If you run it on a real chat, tell me how many late cards it printed.
The sloth didn't get faster. It just stopped forgetting.
Prize Categories
Best Use of Gemma: all 17 model calls, from finding promises to the "already kept?" check to the drafted reply, are gemma3:4b running locally in Ollama, for 16.9 s per run.
Best Use of ElevenLabs: the 1:23 explainer is narrated with ElevenLabs. I wrote the script, generated the voice there, and synced it to the film: the chat, Gemma finding the six promises, and the one reply. Watch it on YouTube. The app stays local. ElevenLabs is the voice of the demo, not a call the app makes.
Try it in 3 commands, and tell me what you promised and forgot.
Star the repo if Said It caught you too.
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.


