Mettere a punto ("fine-tuning") un modello linguistico open su dati tuoi e' diventato sorprendentemente accessibile: con la libreria Unsloth, la tecnica LoRA/QLoRA e una GPU gratuita di Google Colab puoi addestrare un modello da 7-8 miliardi di parametri in meno di un'ora, senza spendere nulla e senza hardware tuo. In questa guida costruiamo, passo passo, un piccolo modello specializzato — per esempio un assistente che risponde nello stile e con le informazioni che gli forniamo — e lo esportiamo in un formato usabile in locale con Ollama.

A chi serve, cosa otterrai, prerequisiti

E' una guida di livello intermedio/avanzato, utile a sviluppatori, data analyst, makers e a chi vuole capire davvero come funziona la personalizzazione di un LLM. Alla fine avrai: un modello fine-tuned sui tuoi esempi, salvato sia come "adattatore" LoRA sia come file GGUF quantizzato, e lo userai in locale. Prerequisiti: un account Google (per Colab e Google Drive); conoscenza di base di Python; un dataset di esempi in formato istruzione-risposta (anche solo 50-500 esempi per iniziare); facoltativo, un account Hugging Face se vuoi caricare il modello. Nessun costo: il piano gratuito di Colab offre una GPU (tipicamente una NVIDIA T4 da 16 GB) sufficiente per i modelli piccoli. Per modelli piu' grandi serve Colab Pro o una GPU locale potente.

Capire le scelte: perche' Unsloth, LoRA e QLoRA

Addestrare "tutto" un modello (full fine-tuning) richiede decine o centinaia di GB di VRAM: fuori portata per la maggior parte di noi. LoRA (Low-Rank Adaptation) aggira il problema: invece di modificare tutti i pesi, addestra piccoli "adattatori" aggiuntivi (pochi milioni di parametri), lasciando intatto il modello base. QLoRA aggiunge la quantizzazione a 4 bit del modello base, riducendo ancora la memoria. Unsloth e' una libreria che ottimizza tutto questo: stesso risultato di Hugging Face TRL ma con consumo di memoria piu' basso e velocita' 2-5 volte maggiore, il che e' decisivo su una T4. Alternative: Axolotl e Hugging Face TRL/PEFT direttamente (piu' flessibili, meno ottimizzati), o servizi gestiti di fine-tuning di OpenAI/Google (piu' semplici ma a pagamento e meno trasparenti).

Il fine-tuning leggero (LoRA/QLoRA) addestra solo una piccola parte del modello: gira anche su una GPU gratuita di Colab.

Quale modello base scegliere

Per stare nella T4 gratuita, scegli un modello da circa 1-8 miliardi di parametri. Buone scelte nel 2026: Llama 3.x 8B Instruct, Qwen 3.x 7B Instruct, Mistral 7B, Gemma 2/3 (2-9B), oppure i modelli "base" gia' quantizzati che Unsloth pubblica su Hugging Face (nomi del tipo unsloth/llama-3-8b-Instruct-bnb-4bit). Scegli sempre la versione Instruct/Chat se vuoi un assistente, e controlla la licenza (Apache, MIT o le licenze community di Llama/Gemma) per l'uso che ne farai.

Procedimento passo passo

  1. Apri Colab: vai su colab.research.google.com, crea un nuovo notebook, poi menu Runtime > Change runtime type e seleziona una GPU (T4). Verifica con una cella: !nvidia-smi.
  2. Installa Unsloth:
!pip install -q "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git"
!pip install -q --no-deps trl peft accelerate bitsandbytes
  1. Carica il modello base quantizzato a 4 bit:
from unsloth import FastLanguageModel
import torch
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name="unsloth/llama-3-8b-Instruct-bnb-4bit",
    max_seq_length=2048,
    load_in_4bit=True,
)
  1. Aggiungi gli adattatori LoRA:
model = FastLanguageModel.get_peft_model(
    model, r=16, 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",
)
  1. Prepara il dataset. Il formato piu' semplice e' un file JSONL con coppie istruzione/risposta. Esempio di una riga (su una sola riga nel file): {"instruction":"Spiega cos'e' un firewall a un principiante","input":"","output":"Un firewall e' come un buttafuori per la rete del tuo computer..."}. Carica il file su Colab (icona cartella a sinistra) o leggilo da Google Drive. Poi:
from datasets import load_dataset
dataset = load_dataset("json", data_files="miei_dati.jsonl", split="train")

def formatta(ex):
    istr = ex["instruction"]
    if ex.get("input"):
        istr += "\n\n" + ex["input"]
    testo = tokenizer.apply_chat_template(
        [{"role":"user","content":istr},
         {"role":"assistant","content":ex["output"]}],
        tokenize=False)
    return {"text": testo}

dataset = dataset.map(formatta)
  1. Addestra con il trainer di TRL:
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, max_steps=60, 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()

Con 60 "step" e poche centinaia di esempi l'addestramento dura pochi minuti. Per un risultato serio aumenta gli step o imposta num_train_epochs=1 al posto di max_steps e tieni d'occhio la loss: deve scendere e poi stabilizzarsi (se risale, stai facendo overfitting: riduci epoche o learning rate).

  1. Prova il modello subito:
FastLanguageModel.for_inference(model)
msg = [{"role":"user","content":"Spiega cos'e' una VPN in due frasi"}]
inputs = tokenizer.apply_chat_template(msg, return_tensors="pt", add_generation_prompt=True).to("cuda")
out = model.generate(input_ids=inputs, max_new_tokens=200)
print(tokenizer.decode(out[0], skip_special_tokens=True))
  1. Salva ed esporta. Per tenere solo l'adattatore LoRA (pochi MB): model.save_pretrained("lora_model"); tokenizer.save_pretrained("lora_model"). Per ottenere un file GGUF quantizzato da usare con Ollama o llama.cpp: model.save_pretrained_gguf("modello_gguf", tokenizer, quantization_method="q4_k_m"). Scarica i file (o salvali su Google Drive montandolo con from google.colab import drive; drive.mount('/content/drive')).
Con Unsloth e la quantizzazione a 4 bit, un modello da 7-8 miliardi di parametri si addestra sulla GPU T4 del piano gratuito di Colab.

Usare il modello in locale con Ollama

Sul tuo PC, dopo aver installato Ollama, crea un file chiamato Modelfile nella cartella dove hai messo il GGUF:

FROM ./modello_gguf/unsloth.Q4_K_M.gguf
PARAMETER temperature 0.7
SYSTEM "Sei un assistente che spiega la cybersicurezza in modo semplice."

Poi: ollama create mio-assistente -f Modelfile e infine ollama run mio-assistente. Ora hai il tuo modello personalizzato che gira offline, gratis e senza inviare dati a nessuno.

Errori comuni e soluzioni

  • "CUDA out of memory" — Riduci max_seq_length (es. 1024), per_device_train_batch_size a 1, usa un modello piu' piccolo, oppure riavvia il runtime (Runtime > Restart) per liberare memoria.
  • "No GPU available" / runtime su CPU — Vai in Runtime > Change runtime type e seleziona GPU; se Colab non te la da', riprova piu' tardi o usa Colab Pro.
  • Il modello risponde male o ripete — Dataset troppo piccolo o sbilanciato: aggiungi esempi vari e di qualita'; controlla che il formato del chat template sia coerente; non esagerare con le epoche.
  • "bitsandbytes" non si installa — Aggiorna pip, reinstalla con la versione indicata dalla documentazione di Unsloth; assicurati che il runtime sia su GPU prima di installare.
  • L'export GGUF fallisce — Serve spazio su disco e RAM: libera l'output, riavvia il runtime e riprova; in alternativa salva l'adattatore LoRA e fai la conversione GGUF in un secondo notebook con llama.cpp.
  • La sessione Colab si disconnette — Il piano gratuito ha limiti di tempo: salva spesso su Drive, tieni la scheda attiva, e per addestramenti lunghi valuta Colab Pro o una macchina cloud.

Varianti, alternative e quando NON fare fine-tuning

Varianti: aumenta r (es. 32 o 64) per piu' capacita' di adattamento a costo di piu' memoria; usa dataset di conversazioni multi-turno se vuoi un chatbot; fai "continued pretraining" su testo grezzo (non istruzioni) se vuoi insegnare un dominio molto specifico. Alternative agli strumenti: Axolotl per configurazioni piu' complesse via file YAML; i servizi gestiti di OpenAI o Google se preferisci semplicita' e non ti serve il modello in locale; LM Studio per testare i GGUF con interfaccia grafica.

Quando NON conviene: se il tuo obiettivo e' far rispondere il modello su documenti aziendali aggiornati, quasi sempre e' meglio una pipeline RAG (recupero dei documenti + modello generico) che un fine-tuning, perche' e' piu' economica, aggiornabile e meno soggetta a "inventare". Il fine-tuning conviene quando vuoi cambiare lo stile, il formato delle risposte, il tono, o specializzare il modello su un compito ripetitivo; non e' il modo giusto per iniettare conoscenza fattuale che cambia spesso. E ricorda: un modello fine-tuned su dati di scarsa qualita' diventa peggiore, non migliore.

Come proseguire

Parti piccolo: 100-200 esempi ben fatti, un modello da 7-8B, 1 epoca, e verifica con qualche prompt reale. Poi itera: aggiungi esempi dove il modello sbaglia, aumenta gli step, prova un modello base diverso. Quando sei soddisfatto, esporta in GGUF, mettilo in Ollama e — se vuoi condividerlo — caricalo su Hugging Face con model.push_to_hub_gguf(...). Per approfondire, la documentazione ufficiale di Unsloth (sul loro repository GitHub) ha notebook pronti per Llama, Qwen, Gemma e Mistral, ed e' tenuta aggiornata a ogni nuova versione dei modelli.