forgot-me

A local-first memory assistant built with friends over a hackathon weekend: it reads the files on your phone, describes them with a local LLM, and answers questions about them without anything leaving your network.

Python, FastAPI, ChromaDB, Ollama, React Native, TypeScript, Docker · source on GitHub

Phone (Expo Go)                    Your machine (Docker)
+------------------+               +---------------------------+
|  React Native    |  HTTP/JSON    |  FastAPI backend :8000    |
|                  | ------------> |                           |
|  - scan folders  |               |  storage agent            |
|  - queue files   |               |   detect modality         |
|  - ask questions |               |   extract content         |
|  - browse memory |               |   describe with the LLM   |
|  - see events    |               |   pull out dates          |
+------------------+               |   embed and store         |
                                   |                           |
                                   |  ChromaDB  vectors        |
                                   |  SQLite    events         |
                                   |  Ollama    Qwen2.5-3B     |
                                   +---------------------------+

What it does

Point it at a folder on your phone and it works through the files one at a time: a PDF, a photo, a voice note, a calendar invite, an email. Each one is turned into a couple of sentences of description by a local model, and that description — not the file — is what gets embedded and stored. Then you can ask questions in plain language and get an answer that cites the files it came from.

It also reads dates out of whatever it ingests, so deadlines and appointments end up in a list of upcoming events, with an optional Discord webhook when something new turns up.

Ingestion

base64 in -> detect modality -> route to a processor
   .pdf   PyMuPDF        text
   .jpg   BLIP           caption
   .mp3   Whisper tiny   transcript
   .ics   icalendar      events
   .docx  python-docx    paragraphs
   .eml   email.parser   headers + body
        |
   LLM writes a description, a category and a summary
        |
   LLM looks for dates and deadlines
        |
   description -> MiniLM embedding -> ChromaDB
   events -> SQLite -> webhooks

Only the description is stored. It keeps the vector store small, it searches better than raw page text, and the file itself never leaves the phone.

Querying

The question is embedded with the same model, ChromaDB returns the nearest descriptions, and anything far from the best match is dropped before the model sees it. The answer then goes through a second call that checks it against those descriptions; if it doesn’t hold up, the answer comes back with that said plainly rather than quietly.

The rules we worked under

The hackathon brief ruled out hosted models entirely, so everything runs on the machine in the corner: Ollama with Qwen2.5-3B, under 4B parameters, with the phone talking to it over the LAN. No OpenAI, no Anthropic, no API keys. That constraint ended up shaping most of the design — the description-first storage, the small embedding model, the single-file-at-a-time queue with retries, all of it is about getting useful behaviour out of a 3B model on one machine.

Running it

git clone https://github.com/mootez-1337/forgot-me.git && cd forgot-me
ollama pull qwen2.5:3b          # with OLLAMA_HOST=0.0.0.0 so Docker can reach it
docker compose up --build       # backend on :8000

cd mobile && npm install && npx expo start   # open in Expo Go, same Wi-Fi

The app asks for the backend’s LAN address on first run. Nothing is authenticated, so keep it on a network you trust.

Who built it

A weekend, four of us: Moatez Ben Slimen, Ragheb Rayen, Hiba Msallem and me.