All projects

May 2025

Echo

An open-source LLM fine-tuned on five years of my messages, to talk and think like me.

A digital clone of myself, built from five years of my own Telegram history. The model was never the hard part: most of the work went into turning a raw chat export into training data. I fine-tuned LLaMA 3 and Gemma 3 with Unsloth, then served the result through a few FastAPI services behind a Streamlit front end, all on one GPU box.

The experiment

I wanted to know what a model trained on my own messages would sound like.

It works, which is the funny part and the unsettling part at the same time.

A chat with the fine-tuned model, which replies in Singlish about wanting to eat Kovan food.
It picked up the Singlish, the LOLs and the habit of suggesting food. I didn't tell it to.

Five years of messages isn’t a dataset

A chat export is a pile of JSON with no notion of a turn, a topic or a reply. Most of the work was turning it into something a model could learn from: deciding what counts as a conversation, who said what, which messages to keep and how to pair a prompt with a response.

The data preparation screen, showing statistics about the processed chat export.
The unglamorous half, and the half that decided how good the result was.

How I built it

I fine-tuned open-source LLaMA 3 and Gemma 3 models with Unsloth. Its memory-efficient training path made the experiments practical on the hardware available to me, which was a single T4.

I split the application into small services: one for data preparation, one for training and inference, and a Streamlit front end over both. Everything runs in Docker on one machine.

Architecture diagram: a Streamlit frontend, a data preparation service and an Unsloth training backend, all in Docker on one EC2 instance with a Tesla T4.
Three containers on one GPU box. Not elegant, but every part of it was mine to debug.

Looking back

Training a model on private conversations made me think harder about whose data it really is. Half of every chat is someone else’s messages.

The data has its own limits too. A chat export reflects who I was speaking to and what conversations I kept, so the model can only learn from that sample.