DEV Community

Kehan Hasalawa
Kehan Hasalawa

Posted on

Ofrenda: a private, offline ofrenda that remembers with open-weight models

Hacktoberfest Open-Source AI Challenge: Ghost in the Machine Submission 👻🌼

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine

What I Built

Ofrenda is a local-first virtual ofrenda, the altar families build for Día de los Muertos. You add someone you miss, write down the stories you never want to lose, and then talk with an AI companion that knows only what you wrote. You can type to it, or press 📞 and have a real voice conversation, like a phone call.

I read "Ghost in the Machine" gently. It isn't a ghost that haunts you. It's the people who stay with us through the stories we keep. Two rules came from that:

  • The AI speaks about your loved one, never as them. There is no fake séance with someone you actually miss.
  • If no story matches a question, the model is never called. The app says "no story about that yet" instead of inventing a memory.

Everything runs on your own computer: the language model, the speech recognition, the data. Nothing is uploaded anywhere.

Demo

A full walkthrough: adding a person, writing stories, chatting, and a voice call, with narration and subtitles.

In the demo I add Abuela Rosa, write a few stories (like "The night the mole burned"), ask the AI about them, and then talk to it out loud.

Code

GitHub logo Hasalawa / ofrenda

A private, offline virtual ofrenda for Día de los Muertos. Keep the stories of people you miss, then talk about them by chat or voice call with a local open-weight AI (Ollama + Whisper). Nothing leaves your computer.

Ofrenda: those we remember never really leave

CI Python 3.10+ License: MIT Runs offline Open-weight AI Core dependencies: none

A private, candle-lit ofrenda for the people you miss.
Write down their stories, then talk about them with an AI that only knows what you tell it by typing or by a hands-free voice call. Everything runs on your own computer

Quick start · How it works · Voice calls · Privacy · Why open source

Built for the Hacktoberfest Open-Source AI Challenge, Week 4: Ghost in the Machine. The ghost here is not a haunting. It is the people who stay with us through the stories we keep.


🎬 See it

Demo: the altar, asking about a grandmother's stories, the stories tab













The altar with a photo frame, candles and marigolds
The altar. Papel picado, marigolds, flickering candles, a framed portrait.

Chatting about Abuela Rosa
Ask anything. Answers stream in live and come only from the stories you wrote.

The stories tab
Keep the stories. Add memories, offerings, and write a remembrance.

A hands-free voice call
Call. Just speak. It listens, thinks, and talks back.

Screenshots use the bundled demo data: an illustrated, fictional grandmother. Replies in your own…




MIT licensed. Quick start: pip install -e ".[audio]", ollama pull llama3.2:3b, ofrenda serve.

How I Built It

  • Language model: any open-weight model served by Ollama. The default is llama3.2:3b, and you can switch with OFRENDA_MODEL. Answers stream live to the browser.
  • Speech to text: faster-whisper (Whisper) runs locally. A small voice-activity detector in the browser finds the end of each sentence, then the audio is sent to the local server and transcribed. No speech API is involved.
  • Voice out: the answer is spoken sentence by sentence while it is still streaming, using the voices already installed on your device.
  • Grounding: a small keyword retriever (with a tiny stemmer) picks the relevant stories, so even a 3B model on a laptop only sees what matters. The system prompt forbids speaking as the person or inventing details. Follow-up questions like "and then?" reuse the previous question's context.
  • Web app: a zero-dependency Python server bound to 127.0.0.1 (with a Host-header check), and one offline single-page UI (no CDN, no tracking). It has falling marigold petals, papel picado, flickering candles, a Talk / Stories / Offerings drawer, and a voice-call screen.
  • Core: Python standard library only. One JSON file holds the data, and ofrenda build exports a self-contained printable HTML page.
  • Graceful fallback: with no model running, remember and ask still work from templates and your own stories.
  • CI/CD (GitHub Actions): ruff lint and pytest on Python 3.10 to 3.13, a smoke test, a package build, release on v* tags, and the demo page deployed to GitHub Pages.

Why Does Open Innovation Matter?

Family stories are some of the most private data there is. With a closed API, grandma's stories would be uploaded to a server I don't control, and the project would stop working the day that service changes its terms or disappears.

With open-weight models running locally:

  • It stays private. Voices, stories and photos never leave the machine.
  • It works offline. Nothing is needed except your laptop.
  • It's swappable. You can change the model, or fine-tune one on a family's own language, including dialects big models handle poorly.
  • It's free to run. Anyone can use it, with no subscription and no API key.
  • It can't be taken away. The memories don't depend on a company's roadmap.

A closed API could have made a nicer demo. It couldn't have made something I would trust with someone's grandmother.

My Agent Session

I built Ofrenda in a long, iterative session with an AI coding agent (Claude Code). The agent wrote the code, tests and CI. I steered with real feedback from running it on my own Windows machine, and that feedback shaped the project:

  1. First version: a CLI plus a static page. I then asked for a graphical, English-only app where you actually talk to the AI.
  2. Voice calls: I asked for a phone-call experience. The agent added browser voice-activity detection, local Whisper, and sentence-by-sentence speech.
  3. Real bugs from my machine: a metadata_errors crash from an old PyAV (fixed by decoding WAV ourselves), and "no story about that" replies to greetings (now explained in the README).
  4. Polish: a demo with stories and a portrait, a README with diagrams, CI/CD fixes (GitHub Pages must be enabled), and this demo video.

The Spirit of It

The moment that made it real for me was the voice call. I said, out loud, "What happened the night the mole burned?" and a calm voice answered with the story I had written, in my own words, and nothing more. When I asked something that wasn't written anywhere, it simply said it didn't have a story about that yet.

That honesty matters. Grief tools are dangerous when they pretend. Ofrenda doesn't bring anyone back, and it doesn't pretend to. It keeps the stories alive and lets you hear them again whenever you want to.

(The demo uses a fictional grandmother, Abuela Rosa, with an illustrated portrait. You can add your own family.)

Prize Categories

I'm entering the main Ghost in the Machine challenge: an open-source, open-weight, local-first AI project built around remembrance.

Top comments (0)