chatpersona

turns a whatsapp chat into a persona you can talk to, all running locally on ollama.

2026-03-01 | hack

i wanted to see how much of a person actually lives in their messages.

try it

you'll need python 3.11 or newer, and ollama running.

ollama pull llama3.2:latest
ollama pull qwen3-embedding:0.6b
git clone https://github.com/OPDhaker/chatpersona && cd chatpersona
python3 -m venv venv && source venv/bin/activate
pip install -e .
chatpersona init
chatpersona chat "<profile>"

init asks for your exported chat, who you want to talk to, and which model to use. if something's off, chatpersona doctor tells you what:

$ chatpersona doctor
PASS  Python version     Using Python 3.13.2, which meets the >=3.11 requirement.
PASS  Ollama reachable   Ollama responded at http://127.0.0.1:11434.
PASS  Local models       Found 2 local Ollama model(s).
PASS  Chat model         Usable chat models were found. Default choice: `llama3.2:latest`.
PASS  Embedding model    Embedding retrieval can use `qwen3-embedding:0.6b`.
PASS  Profile storage    Local profile storage is writable at `~/.chatpersona/profiles`.

everything runs on your own machine, so the chats never leave your laptop.

how a reply gets made

under the hood it's retrieval plus two prompts to a small local model:

  1. it reads the export and pairs every message they got with how they replied
  2. when you send something, it pulls up their real replies to the most similar messages1
  3. a planner model decides what they'd say
  4. a second pass rewrites it in their texting shape: how long their messages run, and how many they send in a row

the hard part

a reply that said the right thing still didn't sound like them. that's why every reply runs twice: once to decide what to say, and once to say it the way they would.

it still only takes one-on-one whatsapp exports, on a mac. i'd make the import step generic from the start, so other apps and group chats could plug in later.

Footnotes

  1. matched by meaning, with qwen3-embedding and a local chroma index. without an embedding model, it falls back to matching words. ↩

projects