- Email[email protected]
- Phone+962 797 166 177
- Birthday1982-09-25
- LocationAmman, Jordan
Teaching a Tiny Model to Sound Like Me: A LoRA Fine-Tuning Experiment
Welcome back to the lab. Last post was about removing something from a language model — its reflex to refuse certain requests. This one's the opposite exercise: teaching a model something it never knew at all. Same small model, same free Colab GPU, completely different technique. If abliteration is surgery, LoRA fine-tuning is tutoring.
What LoRA Actually Does
Full fine-tuning of a language model means updating every single weight — expensive, slow, and complete overkill for a small experiment. LoRA (Low-Rank Adaptation) takes a shortcut. Instead of touching the model's existing weights directly, it freezes them entirely and trains a pair of small "adapter" matrices alongside each layer. The model's original knowledge stays untouched; the adapters learn the new behaviour on top.
The numbers make the case for themselves. On a model this size, the adapters I trained came out to about 11 million trainable parameters against 1.25 billion total — under 1% of the model actually got touched. That's the whole appeal: a fraction of the compute and memory of full fine-tuning, for results that hold up surprisingly well on a narrow, well-defined task.
The Experiment: Teach It to Be Me
Rather than a generic style transfer test, I went with something more fun to evaluate: could a 1-billion-parameter model learn to write in my own voice, using my blog posts and CV as the only training material?
The dataset ended up being two things stitched together:
-
38 of my own blog posts, cleaned out of a raw CSV export, HTML tags stripped, into plain instruction-response pairs — "write a post titled X" paired with the actual post text.
-
12 additional Q&A pairs drafted from my CV — questions like "what's your background" or "tell me about your time in Australia," answered in the same voice as the blog posts, to round out the persona beyond just IoT topics.
Fifty examples all up. Small by any serious training standard, but enough to test whether the mechanism actually works, which was the whole point.
Building the Dataset
The blog CSV export needed a proper clean-up pass — HTML paragraph tags, stray line breaks, and a few rounds of regex to stop the training text from including markup noise:
def clean_html(raw):
text = html.unescape(raw)
text = text.replace('\r\n', '\n').replace('\r', '\n')
text = re.sub(r'</p>\s*<p[^>]*>', '\n\n', text)
text = re.sub(r'<p[^>]*>', '', text)
text = re.sub(r'<br\s*/?>', '\n', text)
text = re.sub(r'<[^>]+>', '', text)
return text.strip()
Each cleaned post got wrapped into a chat-style training example, with a system prompt describing the persona sitting in front of every single one:
SYSTEM_PROMPT = (
"You are Yazan Daradkeh, a Senior Digital Product Manager and AI specialist "
"from Amman, Jordan, with 20+ years of experience in digital products, AI "
"integration, and IoT/smart home systems. You write in a direct, informal, "
"technically fluent voice with occasional Australian phrasing picked up from "
"years working in Melbourne."
)
The Training Run
TRL's SFTTrainer plus PEFT's LoraConfig did the heavy lifting:
lora_config = LoraConfig(
r=16,
lora_alpha=32,
lora_dropout=0.05,
target_modules="all-linear",
task_type="CAUSAL_LM",
)
Rank 16 with alpha 32 is a common starting convention — alpha at roughly double the rank gives a clean scaling factor without much tuning drama. Targeting "all-linear" modules rather than just the attention layers gave the adapters the widest possible surface to learn from, which matters more when your dataset is on the small side, like mine.
With only fifty examples, one or two training epochs barely nudges the weights. I ran six passes over the data instead — more than you'd want on a large, general-purpose dataset, but reasonable here since the goal was style transfer on a narrow, personal corpus rather than broad generalisation.
What I Learned Along the Way
Every fresh Colab session comes with its own little tax: packages not installed, working directories that don't persist the way you expect between cells, path errors from relative versus absolute references. None of it was hard, exactly, just the normal friction of learning a new toolchain by actually using it rather than reading about it. A version mismatch between peft and torchao was the trickiest one — a stricter version check inside peft than the Colab environment shipped with by default, fixed with a one-line upgrade.
Honest Fine Print
Fifty examples is genuinely small. This project was never going to produce a model that deeply "is" me — it's a model that's picked up some rhythm and vocabulary from a narrow slice of my writing, mostly IoT and smart-home topics, since that's what the blog corpus skews toward. Ask it to write in my voice about something the training data never touched, and it's extrapolating a lot further than when it's asked about MQTT brokers. There's also a real risk with a dataset this size of the model just memorising specific phrases rather than generalising the style — worth testing carefully rather than assuming success.
None of that is a knock on LoRA as a technique. It's a reflection of dataset size, which is exactly the variable I was choosing to keep small for a first attempt.
The Verdict
Two very different tools, same small model, same afternoon-sized budget: one for removing a behaviour, one for teaching a new one. If you've been curious about fine-tuning but assumed it needs a server farm and a research team, a 1-billion-parameter model on a free Colab GPU is a genuinely honest way to learn the mechanics without burning real money finding out what you don't know yet.
If you've got any questions or want a hand setting up your own fine-tuning experiment, don't hesitate to reach out at [email protected] or connect with me via www.yazan.me. I'm always keen to help out!
"If you've got any questions or need a hand wrangling your own setup, don't hesitate to reach out at [email protected] or connect with me via www.yazan.me. I'm always keen to help out!"