I built a local AI assistant fine-tuned on my own conversations
I wanted an AI assistant that is actually mine: it runs on my machine, knows how I talk, and can use my files and shell. So I built JERN, a small open-source assistant around a fine-tuned 1.5B model, and this is how it works and what broke. Why I built it Most assistants are someone else's product:

I wanted an AI assistant that is actually mine: it runs on my machine, knows how I talk, and can use my files and shell. So I built JERN, a small open-source assistant around a fine-tuned 1.5B model, and this is how it works and what broke.
Most assistants are someone else's product: they run on someone else's servers, know nothing about my files, and sound the same for everyone. I wanted one that is mine. It should answer in a voice I chose, be able to look at my own folders and run commands on my own machine, and be small enough to understand end to end.
That meant building it myself, with a small open model I could fine-tune on a single GPU.
JERN stands for Just An Experimental Response Network. It has two models and one app:
Everything runs on my machine with one command: python main.py opens the web UI at http://127.0.0.1:8000.
The training data is one text file, data/chat/conversations.txt, with conversations I wrote: how JERN introduces itself, how it should talk, and examples of when to call a tool. The parser in model/jern/data.py turns that file into a dataset.
On first run the app downloads the base model and fine-tunes it, which takes 5 - 10 minutes on a GPU and an hour or more on a CPU. The result is saved to out-jern/ and reused on later runs.
Why a 1.5B model? It fits a modest GPU, fine-tunes quickly, and is small enough to read and change the whole pipeline. The trade-off is quality, which I come back to below.
The part that makes JERN feel like an assistant rather than a chatbot is the tool loop. The model can emit a tool call, the server runs it, and the result goes back to the model for the next step. Each tool is one file under app/tools/, registered in a ToolRegistry, so writing a new one is a small job.
Built-in tools cover files, shell, web search, downloads and system info. On top of that, JERN can talk to MCP servers configured in mcp.json, such as GitHub. The web UI shows a timeline of each tool call (for example, listing a folder) before the final answer appears.
Because the tools are local, JERN can read my real files and run real commands. That is useful and also a risk, so review what it wants to run before you approve it.
My laptop has no GPU, so I added a way to borrow one. The command python main.py colab --gpu=T4 -- serve runs the model on a free Google Colab T4 and connects it to the same local web UI through an SSH tunnel. The tools still run on my machine.
This is not the same as fully local, and it is worth being exact about why. When the model is on Colab, it receives your messages and whatever the tools return: file listings, file contents, command output. Only the execution stays local. If privacy is the point, run the model on your own hardware and skip Colab.
The setup and the tunnel are covered in docs/colab.md in the repo.
JERN is an experiment. A 1.5B model sometimes picks the wrong tool, repeats itself or gets facts wrong, and shell access on a real machine deserves care. I would rather say so than oversell it.
git clone https://github.com/IshvaraX/JERN cd JERN python -m venv venv pip install -r requirements.txt python main.py Enter fullscreen mode Exit fullscreen mode The repo is MIT licensed and the docs cover every command, the data format and how to write a tool plugin. Issues and pull requests are welcome, and I would especially like to hear how you handle approving commands that a model wants to run.