On-device AI[witness]
A Voice Journal That Listens and Never Phones Home
A private self-reflection app that transcribes your voice notes, reflects on them and chats about them with models that run on the phone.
- RecordMic or file upload, 16 kHz mono WAV
- TranscribeWhisper Tiny EN on device
- AnalyzeQwen3 1.7B returns strict JSON, with a heuristic fallback
- StoreLogs and audio saved locally in SQLite
- ChatBM25 retrieval over past logs plus a chosen persona
Rochester, N.Y. Sometimes you have to say something out loud to figure out what you think. [witness] is a voice journal for that. You record a vent (or upload one) and get back a title, a summary, a few insights and a short supportive note. Then you can chat with it about what you said, and it pulls in your older entries for context. It's a self-reflection tool, not therapy, and the README says so up front.
The rule I set for myself: this kind of data should never leave the phone. So everything runs on device. Whisper Tiny handles speech to text and a quantized Qwen3 1.7B does the analysis, both through react-native-executorch. Logs and chats live in local SQLite.
The rule I set for myself: this kind of data should never leave the phone.
Every recording goes through one function, processAudio(), whether it came from the mic, a file or, later, a pendant. I wrote a small dependency-free WAV parser and resampler to turn audio into the 16 kHz mono floats Whisper expects. Qwen3 is prompted for strict JSON: title, summary, insights, support and emotions. If the JSON doesn't parse, a heuristic analyzer takes over, so a bad generation never loses an entry.
Chat uses retrieval over your own logs. BM25 picks the top 4 entries by title, transcript, summary and emotions, with recent entries as a fallback. You can pick one of 4 personas: witness, critical, comforting or logical. If a message contains crisis keywords, the app points you to the 988 lifeline instead of trying to handle it.
The AI layer sits behind one provider interface. In Expo Go a lightweight demo provider runs so the whole app is clickable, and in a dev build the real local models switch on. I built an Android debug APK to test it. The docs also plan a small ESP32S3 pendant that records during the day and syncs over Bluetooth. For now that pendant is a write-up, not hardware.