跳到正文
DEV Community· ANIRUDDHA ADAK·· 2 小時前AI 評分55

Hammock 以 Gemma 在瀏覽器內將 WhatsApp 羣組聊天摘要成兩行

Hammock: my group chat in two lines, read by Gemma inside a browser tab 🦥

AI 導讀

Hammock 是一款在瀏覽器內運行的工具,將 WhatsApp 羣組聊天匯出檔整理成兩行摘要、待辦事項及一鍵回覆草稿。聊天內容留在裝置內;首次執行並下載模型後可離線使用,預設採用 Gemma 3 1B IT,另可選 Gemma 4 E2B IT,程式負責解析、篩選訊息及核對摘要中的數字。

正文

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady

What I Built

Hammock 🦥 turns a group chat you have been ignoring into two lines:

  1. What happened, written by Gemma.
  2. What needs you, found by code and phrased by Gemma as a short to-do, with three one-tap reply drafts (👍 On it, ⏳ Later, 🙅 Kind no).

You export a WhatsApp group (⋮ → More → Export chat → Without media), drop the .txt on the page, type your name, and lie back. Everything runs inside the browser tab: no server, no account, no API key. After the first visit it opens and runs with the Wi-Fi off.

It is for the person who opens a family or college group after a busy day, sees "312 unread", and closes the app again. You only need to know two things: did anything change, and is anyone waiting on me? Hammock answers those and skips the rest.

The laziest part needs no AI at all. Before a model wakes up, plain code:

  • finds your last message and only looks at what came after it,
  • skips the good-mornings, forwards, stickers, emoji-only lines, "very nice 👍" and "This message was deleted", and tells you how many it skipped,
  • pulls out every message that mentions your name or nickname.

Only what survives goes to Gemma.

The deterministic step on the made-up family chat: 74 messages to catch up on, 64 skipped, 10 worth a look, 2 mention you

Demo

Try it: https://aniruddhaadak80.github.io/API_projects/hammock/

Use Chrome or Edge on a laptop with WebGPU for the real experience. Two made-up sample chats are built in (a family group in the Android export format, a hackathon team in the iOS format), so you can try it without sharing anything. The first run downloads Gemma once (about 0.8 GB) and your browser caches it.

Hammock landing page

Code

Hammock lives in the hammock/ folder (MIT). No build step: one index.html, plain ES modules, a Web Worker for the model, and a small service worker for offline use.

src/core.js     parser, noise filter, "since you last spoke" window, mention finder,
                prompts, output cleaners, number check (pure functions, no DOM)
src/worker.js   the only file that touches a model (Transformers.js, WebGPU or WASM)
src/app.js      UI and worker plumbing
test/           14 node --test unit tests for core.js
docs/eval.md    what I measured, including where the small model gets it wrong

How I Built It

Open pieces at the core

  • Gemma 3 1B IT (4-bit ONNX, onnx-community/gemma-3-1b-it-ONNX) is the default "Nap" model. On WebGPU it uses q4f16, or q4 when the GPU has no fp16 support.
  • Gemma 4 E2B IT (4-bit ONNX, about 3 GB) is the optional "Deep sleep" model, WebGPU only.
  • Transformers.js on ONNX Runtime Web runs both, inside a Web Worker so the page stays responsive. Weights come from the Hugging Face Hub once and stay in the browser cache.

The design rule: code decides, Gemma writes.

Small models are good at compressing a messy thread into plain language. They are bad at who did what and at digits. So I split the work:

Job Who does it
Parse Android / iOS exports, 12h and 24h clocks, day-first and month-first dates Code
Find your last message, skip the noise, count what was skipped Code
Decide which messages are aimed at you Code (word match on your name and nicknames)
Write "what happened" Gemma
Turn each "needs you" message into a to-do Gemma, then a cleaner that rejects bad output
Check every number in the summary against the chat Code, and the UI flags anything Gemma made up
Draft a reply in the tone you tap Gemma

Long chats are split into chunks the 1B model can hold, summarised part by part, then merged.

What I measured (all on made-up chats, on a 2-vCPU sandbox with no GPU)

With the 4-bit weights the WebGPU path uses (run in Node with onnxruntime-node, greedy decoding, the exact prompts from src/core.js):

Gemma 3 1B Gemma 4 E2B
Family group, line one "The wedding of Rini is moved to December 12th due to a double booking. Train bookings are being finalized for December 11th." (9.9 s) "Rini's wedding date has changed from 5 Dec to 12 Dec due to a double booking. A gift contribution of 2000 each is due by 1 Dec." (23.6 s)
Hackathon team, line one Got the gist, but blamed the wrong person for a broken build ❌ Right people, and it said Meera "fixed" the Safari import when it was her cache (21.9 s)
To-dos "Book your leave for the wedding", "Call Dida this week", "Start the how-it-works section" (about 2.5 s each) similar, a bit more specific, about 2x slower

That wrong-person mistake is the reason "what needs you" is never decided by the model.

The honest bit: the CPU fallback. Without WebGPU, Hammock falls back to WASM. ONNX Runtime Web's WASM backend has no kernel for the GatherBlockQuantized op in the 4-bit export (I also tried the 8-bit Gemma 3 270M export, same error), so the CPU path uses the 1 GB 8-bit 1B export. I ran the full app in headless Chromium on that path and it exposed two real bugs: the summary came back empty, and one to-do was the prompt's own instruction ("Start with a verb, under 12 words"). Now:

  • empty summary → one retry on the last 8 messages; if that fails too, the page says so instead of pretending,
  • to-dos that echo the instructions, start with "Okay, here's…", or ramble are rejected and replaced with a plain excerpt of the message,
  • "Ma is asking you to book leave" is rewritten to "Book leave".

After the fixes the CPU run finished end to end in 132 s for the family sample. The retried summary was fluent but wrong about who did what, and I put that exact screenshot in the README rather than hiding it:

CPU fallback result: the summary misattributes actions, the to-dos and reply draft work

Not measured yet: speed on a real laptop GPU, Safari, Firefox, phones. If you try it, I would love a comment with your browser, GPU and how long it took.

Why Does Open Innovation Matter?

Group chats are the most personal text most of us have: family plans, money, health updates, people's phone numbers. A closed API would mean uploading all of that to someone else's server just to be told "the wedding moved".

With open weights running in the tab:

  • The chat never leaves the device. The file is read with FileReader. In the headless runs, every request the page made was a GET for the app's own files, Transformers.js from jsDelivr, or the model weights from Hugging Face. No request carried chat text. You can check yourself in DevTools → Network, or just switch the Wi-Fi off after the first run.
  • It costs nothing to run, forever. No key, no quota, no bill. Set it up once and it keeps working.
  • It works offline. Train, flight, bad signal, it does not care.
  • I can see why it fails. Because I control the model, the prompts and the decoding, I could measure exactly where the 1B model goes wrong and build the guard rails (code-found mentions, number check, output rejection) around it. With a black-box API I would only see the final text.

The Lazy Payoff

On the made-up family chat: 74 messages since "Arjun" last spoke. Code skips 64 of them without reading (19 greetings, 16 emoji-only, 13 photos or stickers, 12 one-word reactions, 2 deleted, 2 forwards), Gemma reads the remaining 10, and you get back two lines plus two to-dos, each with a reply draft one tap away.

I have only measured this on the two sample chats so far, so I am not going to claim minutes saved per day. What I can say: the skip and mention counts are deterministic and pinned by tests, so the "you can ignore these 64" part does not depend on the model being right.

Prize Categories

  • Best Use of Gemma: Gemma 3 1B (default) and Gemma 4 E2B (optional) run entirely in the browser through Transformers.js and ONNX Runtime Web. Gemma writes the summary, the to-dos and the replies; code checks its work.

Thanks for reading. Now go lie down. 🦥

來源:DEV Community · dev.to