Fine-tuning di un LLM e' diventato accessibile a chiunque abbia una connessione internet e un account Google. La libreria Unsloth, sviluppata dai fratelli Daniel e Michael Han a partire dal 2024 e ora arrivata alla versione 0.10, riduce di un fattore 2-5 volte la memoria e il tempo necessari per addestrare un modello, rendendo possibile fare LoRA fine-tuning su Google Colab gratis, con la GPU T4 che Google mette a disposizione senza costi. In questo tutorial avanzato addestreremo Llama 3.3 8B a rispondere come consulente legale specializzato in privacy, partendo da un dataset di domande e risposte in italiano. Il training intero costa zero euro e dura circa 30 minuti.
A chi serve e cosa imparerai
Questo tutorial e' pensato per sviluppatori e ricercatori che hanno gia' familiarita' con Python e che vogliono specializzare un LLM open su un dominio: assistenza clienti, codice legacy, scrittura tecnica, traduzione su una nicchia. Alla fine avrai:
- Un modello Llama 3.3 8B fine-tuned con le tue Q&A.
- Il file di pesi adattatore LoRA caricato su Hugging Face.
- Un export in formato GGUF compatibile con Ollama, per girare il modello sul tuo laptop.
Prerequisiti:
- Un account Google per Colab.
- Un account Hugging Face e un token con scope "write".
- Aver accettato la licenza di Llama 3.3 sulla pagina Meta-Llama (gratuita, automatica per uso non commerciale fino a 700 milioni di utenti).
- Un file JSONL con almeno 200-500 esempi di Q&A nel tuo dominio. Per il tutorial useremo un dataset open di esempio.
Quali strumenti, perche' e quanto costano
Le opzioni per fare fine-tuning sono diverse, ma per fare LoRA in 30 minuti con budget zero la combinazione vincente e' una:
- Unsloth (la nostra prima scelta): open-source, ottimizzato per Llama, Mistral, Gemma e Qwen, gestisce QLoRA in 4-bit, riduce la memoria di ~70%.
- Hugging Face PEFT + Transformers (alternativa): piu' generale ma meno ottimizzato.
- NVIDIA NeMo Curator: enterprise, eccellente ma overkill per progetti piccoli.
- Servizi a pagamento come Together.ai e Fireworks: piu' veloci ma costano dai 5 ai 20 dollari per un fine-tune da 30 minuti.
L'ambiente di esecuzione e' Google Colab. Il piano gratuito da' accesso a una GPU NVIDIA T4 (16 GB di VRAM) per circa 4 ore al giorno. Per progetti seri conviene Colab Pro a 10 dollari/mese che da' GPU L4 o A100 e sessioni piu' lunghe, ma per questo tutorial il free e' sufficiente.
Procedimento passo-passo
Step 1. Apri Google Colab, crea un nuovo notebook e dal menu Runtime > Change runtime type seleziona T4 GPU (sezione Hardware accelerator).
Step 2. Installa Unsloth e le dipendenze nel primo cell:
%%capture
!pip install "unsloth[colab-new]@git+https://github.com/unslothai/unsloth.git"
!pip install --no-deps "trl<0.10.0" peft accelerate bitsandbytes
!pip install datasets sentencepiece
Step 3. Carica Llama 3.3 8B in versione 4-bit:
from unsloth import FastLanguageModel
import torch
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "unsloth/Meta-Llama-3.3-8B-Instruct-bnb-4bit",
max_seq_length = 2048,
dtype = None, # Unsloth sceglie il tipo migliore
load_in_4bit = True,
)
Unsloth scarica il modello pre-quantizzato in 4-bit (circa 6 GB) dal mirror Hugging Face. Il download dura 1-2 minuti.
Step 4. Configura il LoRA adapter:
model = FastLanguageModel.get_peft_model(
model,
r = 16, # rank LoRA (8 e' minimo, 32 e' piu' espressivo)
target_modules = ["q_proj","k_proj","v_proj","o_proj",
"gate_proj","up_proj","down_proj"],
lora_alpha = 16,
lora_dropout = 0,
bias = "none",
use_gradient_checkpointing = "unsloth",
random_state = 3407,
)
Il rank 16 e' un buon compromesso per dataset da 200-2000 esempi. Per dataset piu' grandi sali a 32 o 64.
Step 5. Carica il tuo dataset. Per il tutorial usiamo un dataset di esempio di Q&A legali italiane:
from datasets import load_dataset
dataset = load_dataset("json", data_files="qa_privacy_italiane.jsonl",
split="train")
# Ogni riga del JSONL: {"question": "...", "answer": "..."}
def to_chat(ex):
return {"text": tokenizer.apply_chat_template([
{"role": "user", "content": ex["question"]},
{"role": "assistant", "content": ex["answer"]},
], tokenize=False)}
dataset = dataset.map(to_chat)
Se non hai un dataset, puoi sostituire con uno pubblico: load_dataset("yahma/alpaca-cleaned", split="train[:500]").
Step 6. Avvia il training con TRL SFTTrainer:
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 = 3,
learning_rate = 2e-4,
fp16 = not torch.cuda.is_bf16_supported(),
bf16 = torch.cuda.is_bf16_supported(),
logging_steps = 5,
output_dir = "outputs",
optim = "adamw_8bit",
seed = 3407,
),
)
trainer.train()
Il training di 500 esempi per 3 epoch dura circa 25-30 minuti sulla T4 free. Vedrai la loss scendere da circa 2.0 a 0.4-0.6, segno che il modello sta imparando lo stile delle tue Q&A.
Testare il modello fine-tuned
A training completato, prova il modello con un prompt nel dominio:
FastLanguageModel.for_inference(model)
prompt = tokenizer.apply_chat_template([
{"role":"user","content":"Posso conservare i log di un dipendente senza informarlo?"},
], tokenize=False, add_generation_prompt=True)
out = model.generate(**tokenizer(prompt, return_tensors="pt").to("cuda"),
max_new_tokens=300, temperature=0.3)
print(tokenizer.decode(out[0], skip_special_tokens=True))
Confronta con la versione base di Llama 3.3 senza fine-tuning: il modello adattato dovrebbe citare il GDPR, l'articolo 4 dello Statuto dei lavoratori, le linee guida del Garante. Quello base risponde in modo piu' generico, spesso in inglese.
Salvare e usare il modello dopo il training
Due strade. La prima e' caricare i pesi LoRA su Hugging Face (pochi MB, lo scarico e' istantaneo):
model.push_to_hub("tuo-username/llama3-privacy-italia-lora",
token="hf_xxx")
tokenizer.push_to_hub("tuo-username/llama3-privacy-italia-lora",
token="hf_xxx")
La seconda, e piu' interessante, e' esportare il modello completo (base + LoRA mergiati) in formato GGUF per usarlo con Ollama sul tuo laptop:
model.save_pretrained_gguf("llama3-privacy-italia",
tokenizer, quantization_method="q4_k_m")
Risultato: un file da ~5 GB che puoi importare in Ollama con ollama create llama3-privacy -f Modelfile e usare da terminale come qualsiasi modello locale.
Errori comuni e come risolverli
- "CUDA out of memory" alla prima epoch: la T4 non basta per batch size 2 con max_seq_length 4096. Riduci
max_seq_lengtha 1024 o usa rank 8. - Loss che non scende sotto 1.5: il dataset e' troppo eterogeneo. Filtra gli esempi piu' rumorosi o aumenta le epoche a 5.
- Loss che scende sotto 0.1 e modello "overfittato": hai fatto training troppo a lungo. Riduci le epoche o aumenta la dimensione del dataset.
- Errore HuggingFace 401 quando carichi Llama: non hai accettato la licenza di Meta-Llama-3 sulla pagina del modello, oppure il token HF non ha permesso "read" sul modello gated.
Varianti e quando NON fare fine-tuning
Per dataset piccoli (sotto 100 esempi) il fine-tuning rischia di degradare il modello. Meglio usare few-shot prompting direttamente in produzione, oppure RAG (retrieval augmented generation) con una vector database. Per task molto specifici e dataset grandissimi (oltre 50.000 esempi) conviene un full fine-tuning su una GPU piu' grossa: in quel caso usa QLoRA + ZeRO-3 con Hugging Face Accelerate, su una L4 o A100 di Colab Pro+. Per modelli piu' piccoli (3B, 1B) e fine-tuning ultra rapido, Unsloth supporta anche Gemma 3 e Qwen 3 con la stessa procedura.
Come proseguire
Una volta padroneggiato il flusso, le possibilita' si moltiplicano. Per produzione, puoi servire il modello con vLLM per ottenere throughput elevato e supporto OpenAI-compatible API. Per dataset enterprise, puoi combinare LoRA con DPO (Direct Preference Optimization) per allineare il modello alle preferenze umane senza RLHF. Tutto, su una T4 gratuita di Colab. La barriera all'ingresso del fine-tuning, nel 2026, e' bassissima.




