Drowzy:毋須再伸手關掉鬧鐘
Drowzy: no need to cancel the wake up alarm anymore
Drowzy 是一款可用語音控制的鬧鐘,用戶可要求延後響鬧或關閉鬧鐘,毋須伸手拿手機。它以 whisper.cpp 和透過 Ollama 執行的開放權重 LLM 在本機處理語音,毋須連接網絡;鬧鐘響 5 秒後錄音 4 秒,並在語意不清時繼續響鬧。作者以合成西班牙語語音測試完整流程,尚未驗證實際麥克風及 Android/Termux。
Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady 🦥
This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
What I Built
Drowzy is an alarm clock you can argue with from under the blanket. When it rings, you don't reach for your phone: you just say "cinco minutitos más" (or "snooze for ten", or "ya estoy despierto, apágala") and it does the right thing. It rings for 5 seconds, goes quiet, listens for 4, understands you, and then snoozes for the time you asked or turns off.
It's for anyone whose worst daily movement is the arm stretch to the nightstand. It's built around the one thing a lazy person actually wants: that being awake is optional until they decide otherwise, and that the alarm can't be fooled into shutting up for good.
Safety guards, because a lazy alarm that makes you late is worse than none:
- It never dismisses by itself. Silence, mumbling or an unclear sentence keeps it ringing.
- After 3 snoozes, the first "turn it off" only buys 2 more minutes; the next one works.
- If the language model is unreachable, a keyword fallback takes over.
- It gives up (and stays quiet) after 30 minutes instead of pretending you woke up.
Demo
Code
Drowzy
An alarm you snooze or dismiss by talking, without moving. Fully local: whisper.cpp for speech-to-text and an open-weight LLM through Ollama to understand what you mean. Nothing leaves the device, and it works in airplane mode.
alarm rings 5 s -> silence -> records 4 s -> whisper.cpp -> Ollama (JSON) -> snooze N min | dismiss | keep ringing
Say "cinco minutitos más" and it snoozes 5 minutes. Say "ya estoy despierto, apágala" and it stops. Mumbling or noise keeps it ringing.
Safety guards (so it can't make you late)
- It never dismisses by itself: empty audio, noise or an unclear phrase keeps the alarm ringing.
- After
max_snoozes(default 3) the first "dismiss" only buys a shortforced_snooze_minutes, and long snoozes are capped. The next "dismiss" works. - If Ollama is down or too slow, a keyword fallback takes over.
- It gives up after
max_ring_minutesand returns…
How I Built It
alarm rings 5 s -> silence -> record 4 s -> whisper.cpp -> Ollama (JSON) -> snooze N min | dismiss | keep ringing
-
Speech-to-text: whisper.cpp with the multilingual
ggml-basemodel, called as a subprocess. Roughly 2 s per phrase on my laptop's CPU. -
Understanding: an open-weight model served by Ollama (
qwen3:4b-instructon my PC;qwen2.5:1.5bis the default for phones). The prompt asks for strict JSON using Ollama's structured output (format=<JSON schema>, temperature 0) with a few Spanish and English examples:{"action": "snooze|dismiss|ignore", "minutes": 5, "reply": "..."}. When in doubt, the model is told to pickignore. -
Glue: Python with Typer, Pydantic and
sounddevice. On Android it runs in Termux through Termux:API for audio, withscripts/setup_termux.shdoing the setup. - Why it rings and listens in turns: if it recorded while ringing, the microphone would just hear the alarm. Alternating sound and silence avoids needing echo cancellation.
-
Cold start: the first LLM call after boot took 37–47 s on CPU. So Drowzy preloads the model 3 minutes before the alarm and keeps it loaded (
keep_alive).
The core is covered by 25 unit tests (intent parsing, the ring loop's guards, scheduling) and 11 integration tests that hit a real Ollama model with no fallback allowed.
What I verified, and what I didn't
- Verified: the full chain with real sound output, real whisper.cpp and a real Ollama model, using synthetic Spanish voice clips fed in place of the microphone: "cinco minutitos más" → 5-minute snooze, "ya estoy despierto, apágala" → dismissed, and the same phrase after 3 snoozes → a forced 2-minute snooze.
- Not verified yet: my laptop's microphone only recorded silence in my test, so I haven't yet shouted a phrase into it. And I haven't run the Android/Termux path on a phone.
- Latency is not great yet: about 2 s of Whisper plus about 6 s of LLM once the model is warm (4B parameters on CPU). A smaller model should cut that, but I haven't measured it.
Why Does Open Innovation Matter?
- It works in airplane mode. You can put the phone in airplane mode overnight and the alarm still understands you.
- Your bedroom audio stays on your device. An always-listening alarm that streams your voice to a cloud API is not something I'd want next to my bed. Here, audio goes from the microphone to whisper.cpp and nowhere else.
- No per-snooze bill. I can say "five more minutes" as many times as I like without paying per call.
- I can swap and tune the model. Changing the model is a one-line config edit, and the prompt and examples are mine to adjust to my own way of mumbling.
來源:DEV Community · dev.to