Parte 3 di 5: Personalizzazione di Modelli Pre-addestrati
Bentornato! Nel nostro ultimo articolo, abbiamo costruito un sistema RAG che dà all'IA accesso alle tue informazioni specifiche. Oggi facciamo un passo avanti — andremo effettivamente a modificare come un modello di IA pensa e risponde attraverso il fine-tuning. Userò un modello open-source per questo esempio dimostrativo.
RAG vs Fine-Tuning: Qual è la Differenza?
Pensala così:
RAG è come dare a qualcuno un libro di riferimento. Rimane la stessa persona, ma ora ha accesso a informazioni specifiche quando risponde alle domande.
Fine-tuning è come mandare qualcuno a una formazione specializzata. Stai effettivamente cambiando come pensa e risponde in base alle tue esigenze specifiche.
Quando Dovresti Fare Fine-Tuning?
Il fine-tuning è potente, ma non è sempre necessario. Considera il fine-tuning quando:
- Hai bisogno che l'IA adotti un tono o uno stile specifico
- Il tuo dominio ha terminologia o concetti specializzati
- Desideri risposte coerenti in molti scenari diversi
- RAG non ti sta dando la qualità di risposte di cui hai bisogno
- Hai dati di addestramento sufficienti (di solito centinaia di esempi)
- Hai bisogno che il modello funzioni offline o in ambienti isolati
Configurazione dell'Ambiente
Useremo Google Colab con una GPU T4 per questo tutorial, ma puoi adattarlo a qualsiasi ambiente con capacità CUDA:
# Install required packages !pip install bitsandbytesimport os import torch from datasets import Dataset from transformers import ( AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer, BitsAndBytesConfig ) from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training, PeftModel
Scelta del Modello Giusto
Per questo tutorial, useremo TinyLlama-1.1B, ma ecco alcune opzioni eccellenti per diverse esigenze:
# Ultra-light models (good for experimentation) # model_name = "distilgpt2" # 82M parameters # model_name = "gpt2" # 124M parameters # model_name = "EleutherAI/gpt-neo-125M" # 125M parameters# Small but capable models # model_name = "microsoft/DialoGPT-medium" # 355M parameters # model_name = "microsoft/DialoGPT-large" # 762M parameters model_name = "TinyLlama/TinyLlama-1.1B-Chat-v1.0" # 1.1B parameters - choosing this one # For production use (if you have more GPU memory) # model_name = "microsoft/phi-2" # 2.7B parameters # model_name = "stabilityai/stablelm-2-1_6b" # 1.6B parameters
Preparazione dei Dati di Addestramento
La chiave per un fine-tuning di successo è data di addestramento di alta qualità. Ecco come lo strutturiamo:
# Sample dataset for MyNextDeveloper (MND)
data = {
"text": [
"User asks: Write a 3-bullet overview of MND.nAssistant: - Remote-first, founded 2022 in Mumbain- Staff augmentation + full-cycle web/API, UI/UX, AI/MLn- Agile/TDD, POSH culture, transparent pricing",
"User asks: Where is MND headquartered?nAssistant: Malabar Hill, Mumbai",
"User asks: What services does MND offer?nAssistant: Staff augmentation, API development, web development, UI/UX design, AI/ML solutions",
"User asks: What is MND's tech stack?nAssistant: Angular, React, Next.js, Node.js, Django, Python, Docker, AWS",
"User asks: What is MND's pricing model?nAssistant: Project pricing starting at $10,000 with hourly rates between $25 and $49",
"User asks: What is MND's mission?nAssistant: To solve the trust gap between startups and engineers by emphasizing empathy, communication, and transparency",
"User asks: What is MND's culture like?nAssistant: Agile practices, test-driven development, and POSH-compliant culture",
"User asks: When was MND founded?nAssistant: 2022"
]
}
# Convert to HuggingFace dataset
dataset = Dataset.from_dict(data)
Principi chiave per i dati di addestramento:
- Usa una formattazione coerente (nota il modello "User asks:" e "Assistant:")
- Mantieni le risposte fattuali e concise
- Copri le informazioni più importanti sul tuo dominio
- Qualità rispetto alla quantità: 50 esempi perfetti battono 500 mediocri
Addestramento Efficiente con LoRA e Quantizzazione
Invece di fare fine-tuning sull'intero modello (che richiede una memoria GPU massiccia), useremo due tecniche di efficienza:
1. Quantizzazione (4-bit)
La quantizzazione è una tecnica di compressione utilizzata per rendere i modelli di linguaggio di grandi dimensioni (LLM) più piccoli e veloci senza ridurre pesantemente l'accuratezza.
- Normalmente, i pesi dell'LLM sono memorizzati come numeri in virgola mobile a 32 bit (FP32).
- La quantizzazione riduce questa precisione a 16-bit (FP16/BF16), 8-bit (INT8), 4-bit (INT4) o anche inferiore.
👉 Esempio:
- Un modello con 10 miliardi di parametri in FP32 richiede ~40 GB di memoria.
- Se lo quantizziamo a INT8 (8-bit) → richiede solo ~10 GB.
- Se andiamo a INT4 (4-bit) → solo ~5 GB.
⚡ Perché è utile?
- Permette ai modelli di funzionare su GPU più piccole (o anche CPU).
- Accelera l'inferenza.
- Leggero compromesso nell'accuratezza, ma spesso trascurabile.
# Configure 4-bit quantization bnb_config = BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_quant_type="nf4", bnb_4bit_use_double_quant=True, bnb_4bit_compute_dtype=torch.float16 )# Load model with quantization model = AutoModelForCausalLM.from_pretrained( model_name, quantization_config=bnb_config, device_map="auto", torch_dtype=torch.float16 )
2. LoRA (Low-Rank Adaptation)
LoRA è un metodo parameter-efficient fine-tuning (PEFT).
Normalmente, per fare fine-tuning di un LLM enorme (come LLaMA-65B o GPT-J), avremmo bisogno di centinaia di GB di memoria GPU. LoRA risolve questo:
- Congelando i pesi del modello originale.
- Aggiungendo piccole matrici addestrabili (adattatori a basso rango) dentro i layer del modello.
- Durante il fine-tuning, vengono aggiornate solo queste piccole matrici.
👉 Esempio:
- Il fine-tuning completo di un modello da 65B potrebbe richiedere ~1 TB di memoria GPU.
- Con LoRA, addestri solo pochi milioni di parametri → richiede < 20 GB di memoria GPU.
⚡ Perché è utile?
- Rende possibile il fine-tuning di LLM massicci su hardware consumer (1–2 GPU).
- Facile "unire" o "separare" adattatori → puoi cambiare rapidamente compiti.
- Spesso raggiunge prestazioni vicine al fine-tuning completo.
# Configure LoRA based on model architecture if "TinyLlama" in model_name or "Llama" in model_name: target_modules = ["q_proj", "k_proj", "v_proj", "o_proj"] elif "gpt" in model_name.lower() or "DialoGPT" in model_name: target_modules = ["c_attn", "c_proj"] else: target_modules = ["q_proj", "v_proj"]lora_config = LoraConfig( r=8, # Rank of adaptation lora_alpha=16, # LoRA scaling parameter target_modules=target_modules, lora_dropout=0.05, bias="none", task_type="CAUSAL_LM" ) # Apply LoRA to the model model = get_peft_model(model, lora_config) model.print_trainable_parameters()
Stiamo addestrando solo lo 0,2% dei parametri!
Addestramento del Modello
# Tokenize the data def tokenize_function(examples): tokenized_inputs = tokenizer( examples["text"], truncation=True, padding="max_length", max_length=512, return_tensors="pt" ) # Create labels by copying input tokens tokenized_inputs["labels"] = tokenized_inputs["input_ids"].clone() return tokenized_inputs# Split dataset train_dataset = dataset.select(range(8)) eval_dataset = dataset.select(range(8, 11)) # Apply tokenization train_dataset = train_dataset.map(tokenize_function, batched=True) eval_dataset = eval_dataset.map(tokenize_function, batched=True) # Configure training training_args = TrainingArguments( output_dir="./mnd-finetune-outputs", num_train_epochs=5, per_device_train_batch_size=4, per_device_eval_batch_size=4, gradient_accumulation_steps=2, warmup_steps=10, learning_rate=3e-4, weight_decay=0.01, logging_steps=1, save_steps=30, eval_strategy="steps", eval_steps=15, save_total_limit=2, load_best_model_at_end=True, fp16=True, report_to=None # Disable wandb logging ) # Create trainer and start training trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset, tokenizer=tokenizer, ) print("Starting training...") trainer.train() # Save the adapter adapter_dir = "./mnd-finetune-outputs/final_adapter" model.save_pretrained(adapter_dir) tokenizer.save_pretrained(adapter_dir)
Test del Modello Fine-Tuned
def load_model_for_inference():
"""Load the fine-tuned model for inference"""
# Load base model
base_model = AutoModelForCausalLM.from_pretrained(
model_name,
quantization_config=bnb_config,
device_map="auto",
torch_dtype=torch.float16
)
# Load the fine-tuned adapter
model = PeftModel.from_pretrained(base_model, adapter_dir)
model = model.merge_and_unload()
# Load tokenizer
tokenizer = AutoTokenizer.from_pretrained(adapter_dir)
return model, tokenizer
def generate_response(model, tokenizer, prompt, max_length=256, temperature=0.7):
"""Generate response for a given prompt"""
formatted_prompt = f"User asks: {prompt}nAssistant:"
inputs = tokenizer.encode(formatted_prompt, return_tensors="pt")
inputs = inputs.to(model.device)
with torch.no_grad():
outputs = model.generate(
inputs,
max_length=max_length,
temperature=temperature,
top_p=0.9,
do_sample=True,
pad_token_id=tokenizer.eos_token_id,
repetition_penalty=1.1
)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
assistant_response = response.split("Assistant:")[-1].strip()
return assistant_response
# Load fine-tuned model and test
model, tokenizer = load_model_for_inference()
test_prompts = [
"What makes MND different from other development companies?",
"Can you tell me about MND's team?",
"What is the company culture at MND?"
]
for prompt in test_prompts:
response = generate_response(model, tokenizer, prompt)
print(f"Q: {prompt}")
print(f"A: {response}n")
Google Colab
Ecco il link di Google Colab per questo articolo che puoi eseguire con un clic: link
I Costi Reali
A differenza delle API commerciali, i tuoi costi sono principalmente:
- Configurazione Iniziale: Tempo GPU per l'addestramento
- Archiviazione: Pesi del modello (~4GB per TinyLlama con adattatori LoRA)
- Inferenza: Il tuo hardware o istanze GPU cloud
Per un modello piccolo come TinyLlama, puoi eseguire l'inferenza su:
- Google Colab (livello gratuito con limitazioni)
- AWS t3.medium con GPU (~$0,05/ora)
- Il tuo hardware (RTX 3060 o migliore)
Migliori Pratiche dall'Esperienza Reale
1. Inizia in Piccolo e Scala Inizia con distilgpt2 o gpt2 per testare i tuoi dati e il processo, poi passa a modelli più grandi.
2. Monitora l'Overfitting Con piccoli dataset, i modelli possono memorizzare piuttosto che imparare. Guarda la tua perdita di valutazione.
3. La Coerenza del Formato è Critica Il formato esatto dei tuoi dati di addestramento è enormemente importante. Sii coerente con la punteggiatura, gli spazi e la struttura.
4. Prova con Domande Non Viste Sempre prova con domande non presenti nei tuoi dati di addestramento per assicurarti la generalizzazione.
5. Salva Checkpoint Regolari L'addestramento può essere interrotto. Salva di frequente e prova i checkpoint intermedi.
Insidie Comuni e Soluzioni
Problema: Il modello genera testo ripetitivo o insensato Soluzione: Abbassa il tasso di apprendimento, aumenta la regolarizzazione o migliora la qualità dei dati di addestramento
Problema: Il modello dimentica la conoscenza generale Soluzione: Includi alcuni esempi generali nei tuoi dati di addestramento o usa un modello base più grande
Problema: Le risposte sono troppo generiche Soluzione: Rendi i tuoi esempi di addestramento più specifici e dettagliati
Problema: Problemi di memoria GPU Soluzione: Riduci la dimensione del batch, usa una quantizzazione più aggressiva o il controllo del gradiente
Combinare con RAG
Ecco la parte potente: puoi combinare il tuo modello fine-tuned con RAG per il meglio di entrambi i mondi:
- Fine-tune per comprensione del dominio, tono e conoscenza generale dell'azienda
- Usa RAG per informazioni attuali, documenti specifici o specifiche tecniche dettagliate
Questo ti dà un modello che "pensa" come la tua azienda ma può accedere a informazioni aggiornate.
Cosa C'è Dopo
Nel nostro prossimo articolo, diventiamo completamente personalizzati — costruendo un modello di linguaggio da zero, completamente tuo, in esecuzione sul tuo hardware con i tuoi dati.
Il fine-tuning di modelli open-source ti dà un controllo senza precedenti sul tuo assistente AI. Puoi assicurarti che comprenda il tuo dominio, parli con la tua voce e non invii mai i tuoi dati a terze parti. Con le moderne tecniche di efficienza come LoRA e quantizzazione, è più accessibile che mai.
Il futuro dell'IA non è solo usare il modello di qualcun altro — è fare dell'IA veramente il tuo.
In arrivo: Articolo 4 — "Costruire il Tuo Proprio Modello di Linguaggio: Piccolo ma Potente"


