Vuoi che un modello linguistico risponda con il tono della tua azienda, conosca il tuo gergo tecnico o segua un formato preciso che con i prompt non riesci a imporre? La risposta si chiama fine-tuning: si prende un modello gia' addestrato e lo si specializza sui propri dati. La buona notizia e' che oggi si puo' fare gratis, in un'ora, senza una GPU costosa. In questa guida useremo Unsloth e la tecnica LoRA dentro un notebook gratuito di Google Colab.
A chi serve e cosa otterrai
Questa guida e' pensata per sviluppatori e smanettoni con basi di Python, che vogliono capire concretamente come si addestra un LLM. Al termine avrai un modello specializzato sui tuoi esempi, salvato come piccolo "adattatore" LoRA da pochi MB, ed esportabile per girare in locale con Ollama. Non serve essere esperti di machine learning: ogni passaggio e' una cella da eseguire.
Prerequisiti reali:
- un account Google (per Google Colab, che offre gratis una GPU NVIDIA T4 con 16 GB);
- un account gratuito su Hugging Face e un access token (per scaricare i modelli ed, eventualmente, pubblicare il risultato);
- un dataset di esempi: anche solo 50-100 coppie domanda/risposta nel tuo dominio bastano per vedere un effetto.
Perche' LoRA e Unsloth (e le alternative)
Addestrare da zero tutti i miliardi di parametri di un modello e' fuori portata per chiunque non abbia un data center. LoRA (Low-Rank Adaptation) aggira il problema: congela i pesi originali e addestra solo un piccolo insieme di "adattatori" aggiuntivi. Risultato: prestazioni vicine al fine-tuning completo usando fino a 4 volte meno memoria. La variante QLoRA aggiunge la quantizzazione a 4 bit, permettendo di lavorare anche su modelli grandi con la VRAM ridotta di Colab.
Unsloth e' una libreria che riscrive i passaggi piu' pesanti dell'addestramento con kernel ottimizzati: rende il training circa 2 volte piu' veloce e con meno memoria, restando compatibile con l'ecosistema Hugging Face. In alternativa si possono usare Axolotl o LLaMA-Factory (piu' configurabili ma meno immediati) oppure transformers + peft a mano (massimo controllo, piu' codice). Per iniziare, Unsloth e' la prima scelta per velocita' e semplicita'.
Passo 1 — Prepara Colab e installa Unsloth
Apri Google Colab, crea un nuovo notebook e attiva la GPU: menu Runtime > Cambia tipo di runtime > T4 GPU. Poi, nella prima cella, installa Unsloth:
!pip install unsloth
# verifica la GPU assegnata
!nvidia-smi
Passo 2 — Carica il modello in 4 bit
Carichiamo un modello base gia' quantizzato. Llama 3.1 8B e' un'ottima scelta di partenza, ma la stessa procedura vale per Qwen, Mistral o altri tra i 500+ supportati.
from unsloth import FastLanguageModel
import torch
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "unsloth/Meta-Llama-3.1-8B-Instruct-bnb-4bit",
max_seq_length = 2048,
load_in_4bit = True,
)
Passo 3 — Aggiungi gli adattatori LoRA
model = FastLanguageModel.get_peft_model(
model,
r = 16, # rango degli adattatori
lora_alpha = 16,
lora_dropout = 0,
target_modules = ["q_proj","k_proj","v_proj","o_proj",
"gate_proj","up_proj","down_proj"],
use_gradient_checkpointing = "unsloth",
)
I valori r = 16 e lora_alpha = 16 sono un buon punto di partenza: alza r (32, 64) se il compito e' complesso e hai molti dati.
Passo 4 — Prepara il dataset
Il formato piu' semplice e' una lista di conversazioni. Puoi caricare un tuo file JSONL da Hugging Face o costruirne uno al volo. Ogni esempio deve seguire il template di chat del modello:
from datasets import load_dataset
# esempio: un tuo dataset in formato {"instruction":..., "output":...}
dataset = load_dataset("json", data_files="i_miei_esempi.jsonl", split="train")
def formatta(ex):
msgs = [
{"role": "user", "content": ex["instruction"]},
{"role": "assistant", "content": ex["output"]},
]
return {"text": tokenizer.apply_chat_template(msgs, tokenize=False)}
dataset = dataset.map(formatta)
Passo 5 — Avvia l'addestramento
from trl import SFTTrainer
from transformers import TrainingArguments
trainer = SFTTrainer(
model = model,
tokenizer = tokenizer,
train_dataset = dataset,
dataset_text_field = "text",
max_seq_length = 2048,
args = TrainingArguments(
per_device_train_batch_size = 2,
gradient_accumulation_steps = 4,
warmup_steps = 5,
num_train_epochs = 2, # 1-3 epoche bastano quasi sempre
learning_rate = 2e-4,
fp16 = not torch.cuda.is_bf16_supported(),
bf16 = torch.cuda.is_bf16_supported(),
logging_steps = 1,
optim = "adamw_8bit",
output_dir = "outputs",
),
)
trainer.train()
Su un dataset di poche centinaia di esempi l'addestramento dura tipicamente da pochi minuti a mezz'ora sulla T4. Tieni d'occhio la loss: deve scendere e poi stabilizzarsi.
Passo 6 — Provalo e salvalo
FastLanguageModel.for_inference(model)
inputs = tokenizer.apply_chat_template(
[{"role":"user","content":"Scrivi una mail di benvenuto a un nuovo cliente."}],
tokenize=True, add_generation_prompt=True, return_tensors="pt").to("cuda")
out = model.generate(input_ids=inputs, max_new_tokens=256)
print(tokenizer.decode(out[0]))
# salva il solo adattatore LoRA (pochi MB)
model.save_pretrained("mio_modello_lora")
# oppure esporta in GGUF per Ollama / llama.cpp
model.save_pretrained_gguf("mio_modello_gguf", tokenizer, quantization_method="q4_k_m")
Il file GGUF puo' essere caricato in Ollama con un breve Modelfile, cosi' il tuo modello specializzato gira in locale sul tuo PC senza connessione.
Errori comuni e come risolverli
- "CUDA out of memory" → riduci
per_device_train_batch_sizea 1, abbassamax_seq_length(es. 1024) o usa un modello piu' piccolo (3B invece di 8B). - Colab si disconnette → la sessione gratuita ha limiti di tempo: salva i checkpoint spesso e tieni la scheda attiva. Per dataset grandi valuta Colab Pro o Kaggle (30 ore di GPU a settimana).
- Il modello "dimentica" le capacita' generali → segno di overfitting: riduci le epoche, abbassa il learning rate o aggiungi dati piu' vari.
- Risposte ripetitive o nel formato sbagliato → controlla che il
chat_templatesia quello giusto del modello e che gli esempi siano coerenti tra loro.
Varianti, casi avanzati e quando NON farlo
Per modelli piu' grandi (70B) usa QLoRA su Colab Pro o su una GPU a noleggio. Per dati molto strutturati, valuta di mescolare i tuoi esempi con un piccolo set generico per non perdere le capacita' di base. E un avvertimento utile: il fine-tuning non e' sempre la risposta. Se ti serve solo dare al modello accesso a documenti aggiornati, conviene quasi sempre un sistema RAG (recupero dei testi pertinenti da mettere nel prompt), piu' semplice da mantenere. Il fine-tuning brilla quando devi insegnare uno stile, un formato o un comportamento, non per memorizzare informazioni che cambiano spesso.
Da qui puoi proseguire studiando gli iperparametri di LoRA nella documentazione di Unsloth e la libreria PEFT di Hugging Face, che sta sotto a tutto questo. Con poche decine di esempi ben fatti, il salto di qualita' rispetto al solo prompting e' spesso sorprendente.




