Valutare e distribuire il modello sottoposto a fine-tuning
Esegua valutazioni quantitative confrontando il modello di base e quello sottoposto a fine-tuning su casi di test esclusi dall'addestramento, converta il modello in GGUF per l'inferenza locale e lo renda disponibile tramite llama.cpp o vLLM.
Valutare e distribuire il modello sottoposto a fine-tuning è una lezione AI Engineering Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Engineering Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Engineering Academy include 4 lezioni in totale.
Perché la valutazione deve precedere la distribuzione
Un modello sottoposto a fine-tuning che ottiene buone prestazioni sui dati di addestramento potrebbe funzionare peggio del modello di base nel Suo effettivo caso d'uso in produzione. L'unico modo per accertarlo è eseguire una valutazione rigorosa. Il fine-tuning può causare dimenticanza catastrofica (perdita di capacità presenti nel modello di base), eccessiva specializzazione (buone prestazioni nell'attività specifica, ma peggiori in attività correlate) o regressioni sottili nei comportamenti di sicurezza. Non distribuisca mai un modello sottoposto a fine-tuning senza confrontarlo con il modello di base su un set di test rappresentativo.
Creazione di un set di test riservato
Il set di test deve essere completamente separato dai dati di addestramento e di validazione: deve contenere esempi che il modello non ha mai visto in nessuna fase dell'addestramento. Il set di test dovrebbe rappresentare la distribuzione completa degli input di produzione: casi comuni, casi limite e input avversari. Per le attività di esecuzione delle istruzioni, includa esempi che richiedano di seguire tutti gli aspetti dell'istruzione, non solo quelli più comuni. Un set di test composto da 100-500 esempi è in genere sufficiente per una valutazione affidabile.
import json
from typing import TypedDict
class TestCase(TypedDict):
input: str # the user message
expected_output: str # the ideal response
category: str # e.g., 'format', 'accuracy', 'edge_case'
evaluation_method: str # 'exact_match', 'json_schema', 'llm_judge'
# Load test set (never used during training)
def load_test_set(path: str) -> list[TestCase]:
cases = []
with open(path) as f:
for line in f:
data = json.loads(line.strip())
cases.append({
'input': data['messages'][-2]['content'], # user message
'expected_output': data['messages'][-1]['content'], # assistant response
'category': data.get('metadata', {}).get('category', 'general'),
'evaluation_method': data.get('metadata', {}).get('eval_method', 'llm_judge')
})
return cases
test_set = load_test_set('test.jsonl')
print(f'Test set loaded: {len(test_set)} examples')Metriche quantitative per la valutazione specifica dell'attività
Scelga metriche di valutazione adatte all'attività. Per l'estrazione JSON, misuri il tasso di conformità allo schema e l'accuratezza a livello di campo. Per la classificazione, misuri accuratezza, precisione e richiamo per classe. Per la generazione di testo, utilizzi la valutazione LLM-as-judge per misurare la qualità. Per la conformità al formato, misuri il tasso di conformità al formato esatto. Esegua ogni metrica sia sul modello di base sia sul modello sottoposto a fine-tuning, così da misurare la variazione del miglioramento.
import json
def evaluate_json_extraction(model_output: str, expected: str, schema: dict) -> dict:
metrics = {'valid_json': False, 'schema_compliant': False, 'field_accuracy': 0.0}
try:
parsed = json.loads(model_output.strip())
metrics['valid_json'] = True
# Check schema compliance
required_fields = schema.get('required', [])
all_present = all(field in parsed for field in required_fields)
correct_types = all(
isinstance(parsed.get(field), schema['properties'][field]['expected_type'])
for field in required_fields if field in parsed
)
metrics['schema_compliant'] = all_present and correct_types
# Field-level accuracy against expected output
expected_parsed = json.loads(expected)
correct_fields = sum(1 for k in expected_parsed if parsed.get(k) == expected_parsed[k])
metrics['field_accuracy'] = correct_fields / len(expected_parsed) if expected_parsed else 0.0
except json.JSONDecodeError:
pass # valid_json stays False
return metricsValutazione LLM-as-Judge
Per le attività di generazione a risposta aperta, utilizzi un LLM-as-judge per valutare gli output del modello sottoposto a fine-tuning rispetto agli output attesi. Chieda a GPT-4o di agire come valutatore, fornisca l'input, l'output atteso e l'output del modello, quindi chieda di valutare correttezza, completezza e conformità al formato su una scala da 1 a 5. Calcoli la media dei punteggi sull'intero set di test per ottenere una valutazione complessiva della qualità. Confronti il punteggio del modello sottoposto a fine-tuning con quello del modello di base sullo stesso set di test.
from openai import OpenAI
client = OpenAI()
def llm_judge_score(instruction: str, expected: str, actual: str) -> dict:
judge_prompt = f'''Evaluate the quality of an AI assistant response.
Instruction given to assistant:
{instruction}
Expected ideal response:
{expected}
Actual response from model being evaluated:
{actual}
Rate the actual response on these criteria (1=poor, 5=excellent):
1. Correctness: Is the information accurate?
2. Format compliance: Does it follow the expected output format?
3. Completeness: Does it address all parts of the instruction?
Return JSON: {{"correctness": N, "format": N, "completeness": N, "overall": N, "reason": "brief explanation"}}'''
response = client.chat.completions.create(
model='gpt-4o',
messages=[{'role': 'user', 'content': judge_prompt}],
response_format={'type': 'json_object'}
)
return json.loads(response.choices[0].message.content)Esecuzione della valutazione comparativa
Esegua una valutazione testa a testa confrontando il modello di base, il modello sottoposto a fine-tuning e, facoltativamente, una solida baseline basata sul prompting su tutti i casi di test. Generi gli output di ciascun modello per ogni caso di test, quindi valuti tutti gli output con le metriche definite. Produca una tabella comparativa che mostri i punteggi delle metriche, le deviazioni standard e alcuni esempi dei casi in cui il modello sottoposto a fine-tuning prevale o perde rispetto alla baseline.
def run_full_evaluation(test_set: list, models: dict, system_prompt: str) -> dict:
results = {name: {'scores': [], 'errors': 0} for name in models}
for i, test_case in enumerate(test_set):
print(f'Evaluating test case {i+1}/{len(test_set)}')
for model_name, model_fn in models.items():
try:
output = model_fn(test_case['input'], system_prompt)
score = llm_judge_score(
test_case['input'],
test_case['expected_output'],
output
)
results[model_name]['scores'].append(score['overall'])
except Exception as e:
results[model_name]['errors'] += 1
results[model_name]['scores'].append(0)
# Summarize
summary = {}
for name, data in results.items():
scores = data['scores']
summary[name] = {
'mean_score': sum(scores) / len(scores),
'errors': data['errors']
}
print(f'{name}: mean={summary[name]["mean_score"]:.2f}, errors={data["errors"]}')
return summaryTest di regressione per la dimenticanza catastrofica
Il fine-tuning può compromettere le capacità generali del modello, un fenomeno chiamato dimenticanza catastrofica. Esegua una suite di test di regressione sia sul modello di base sia su quello sottoposto a fine-tuning, includendo le attività che considera importanti oltre a quella obiettivo: risposta a domande generiche, ragionamento, generazione di codice e rispetto delle istruzioni. Se il modello sottoposto a fine-tuning ottiene punteggi significativamente inferiori in queste attività, il rank LoRA potrebbe essere troppo alto oppure potrebbe aver eseguito l'addestramento per troppe epoche.
REGRESSION_TEST_CASES = [
# General QA
{'input': 'What is the capital of France?', 'expected_substring': 'Paris'},
{'input': 'What is 17 * 23?', 'expected_substring': '391'},
# Instruction following
{'input': 'List 3 planets. Format as: 1. Planet Name', 'expected_pattern': r'^1\. '},
# Reasoning
{'input': 'If all A are B and all B are C, are all A also C?', 'expected_substring': 'yes'},
]
def run_regression_tests(model_fn, test_cases: list) -> float:
passed = 0
for test in test_cases:
output = model_fn(test['input'], '')
if 'expected_substring' in test:
if test['expected_substring'].lower() in output.lower():
passed += 1
elif 'expected_pattern' in test:
import re
if re.search(test['expected_pattern'], output):
passed += 1
rate = passed / len(test_cases)
print(f'Regression test pass rate: {rate:.1%} ({passed}/{len(test_cases)})')
return rateConversione in GGUF per l'inferenza locale
Per la distribuzione locale senza una costosa infrastruttura GPU, converta il modello unito nel formato GGUF ed esegua l'inferenza con llama.cpp. GGUF supporta diversi livelli di quantizzazione: Q4_K_M (4 bit, buon equilibrio tra qualità e velocità), Q8_0 (8 bit, qualità quasi completa) e Q2_K (2 bit, molto veloce ma di qualità inferiore). Un modello 7B quantizzato Q4 richiede solo circa 4 GB di RAM e può essere eseguito sulla CPU a 1-5 token al secondo.
# Step 1: Convert merged HuggingFace model to GGUF
# git clone https://github.com/ggerganov/llama.cpp
# python llama.cpp/convert_hf_to_gguf.py ./merged-model --outtype f16 --outfile model-f16.gguf
# Step 2: Quantize to 4-bit
# ./llama.cpp/llama-quantize model-f16.gguf model-q4.gguf Q4_K_M
# Step 3: Run inference with llama.cpp Python bindings
# pip install llama-cpp-python
from llama_cpp import Llama
llm = Llama(
model_path='./model-q4.gguf',
n_ctx=4096, # context window
n_threads=8, # CPU threads
n_gpu_layers=0 # set > 0 to offload layers to GPU
)
output = llm.create_chat_completion(
messages=[{'role': 'user', 'content': 'What is the capital of France?'}],
temperature=0.1
)
print(output['choices'][0]['message']['content'])Distribuzione con vLLM in produzione
Per fornire in produzione un modello sottoposto a fine-tuning su larga scala, vLLM è attualmente lo standard. vLLM utilizza PagedAttention per raggruppare in batch più richieste in modo efficiente, aumentando notevolmente il throughput della GPU. Supporta endpoint API compatibili con OpenAI, quindi può sostituire direttamente l'API di OpenAI. Una singola GPU A100 con vLLM e un modello 7B sottoposto a fine-tuning può gestire centinaia di richieste al minuto.
# Start vLLM server (run from command line)
# pip install vllm
# python -m vllm.entrypoints.openai.api_server \
# --model ./merged-model \
# --host 0.0.0.0 \
# --port 8000 \
# --max-model-len 4096 \
# --tensor-parallel-size 1
# Use with OpenAI client (drop-in replacement)
from openai import OpenAI
client = OpenAI(
base_url='http://localhost:8000/v1',
api_key='not-needed' # vLLM doesn't require auth by default
)
response = client.chat.completions.create(
model='merged-model', # model name matches the path you passed to vLLM
messages=[{'role': 'user', 'content': 'Extract JSON from: "Alice, 30, NYC"'}]
)
print(response.choices[0].message.content)Test A/B del modello sottoposto a fine-tuning
Prima di passare completamente al modello sottoposto a fine-tuning in produzione, esegua un test A/B: indirizzi una percentuale del traffico di produzione (iniziando dal 5-10%) al modello sottoposto a fine-tuning, mentre la maggior parte del traffico continua a utilizzare il modello di base o l'approccio basato sul prompt esistente. Monitori per entrambi i gruppi i punteggi di qualità, la latenza e le metriche di soddisfazione degli utenti. Aumenti la quota di traffico del modello sottoposto a fine-tuning solo se il test A/B conferma un miglioramento dopo un numero statisticamente significativo di richieste.
import random
class ModelRouter:
def __init__(self, fine_tuned_traffic_fraction=0.1):
self.ft_fraction = fine_tuned_traffic_fraction
self.metrics = {'base': {'count': 0, 'quality_sum': 0}, 'fine_tuned': {'count': 0, 'quality_sum': 0}}
def route(self, user_id: str, request: str) -> dict:
# Deterministic routing by user_id (same user always goes to same model)
use_fine_tuned = (hash(user_id) % 100) < (self.ft_fraction * 100)
model_group = 'fine_tuned' if use_fine_tuned else 'base'
response = call_model(request, use_fine_tuned=use_fine_tuned)
return {'response': response, 'model_group': model_group}
def record_quality(self, model_group: str, quality_score: float):
self.metrics[model_group]['count'] += 1
self.metrics[model_group]['quality_sum'] += quality_score
def ab_test_summary(self) -> dict:
summary = {}
for group, data in self.metrics.items():
avg = data['quality_sum'] / data['count'] if data['count'] > 0 else 0
summary[group] = {'avg_quality': avg, 'n': data['count']}
return summaryManutenzione dei modelli sottoposti a fine-tuning nel tempo
I modelli sottoposti a fine-tuning richiedono una manutenzione continua. Quando il modello di base viene aggiornato (una nuova versione di GPT-4o, una nuova release di Mistral), i pesi dell'adapter potrebbero non essere compatibili e potrebbe essere necessario eseguire nuovamente l'addestramento. Quando cambiano i requisiti dell'attività, è necessario aggiornare i dati di addestramento e ripetere l'addestramento. Quando scopre nuove modalità di errore in produzione, aggiunga esempi al set di addestramento. Pianifichi il riaddestramento periodico come parte del flusso di lavoro operativo di ML in produzione.
Matrice decisionale per la distribuzione
La scelta della strategia di deployment per il modello sottoposto a fine-tuning dipende dalla scala e dai vincoli dell'infrastruttura. Per un basso volume (meno di 1000 richieste al giorno), l'API di fine-tuning di OpenAI è la soluzione più semplice. Per un volume medio (1000–100.000 richieste al giorno), consideri vLLM su una singola istanza GPU. Per applicazioni ad alto volume o sensibili alla latenza, utilizzi vLLM con più GPU, valuti il parallelismo tensoriale e aggiunga un livello di caching davanti. Per dati sensibili dal punto di vista della privacy, esegua il self-hosting sulla propria infrastruttura con GGUF/llama.cpp o vLLM.
Verifica rapida
Verifichi la comprensione della valutazione e del deployment dei modelli sottoposti a fine-tuning trattati in questa lezione.
Riepilogo della lezione
In questa lezione ha imparato che una valutazione rigorosa prima del deployment, che confronti il modello sottoposto a fine-tuning con il modello di base su casi di test esclusi dall'addestramento, è imprescindibile; i test di regressione rilevano l'oblio catastrofico delle capacità generali causato da un'eccessiva specializzazione; e le opzioni di deployment spaziano dall'API gestita di fine-tuning di OpenAI, per la semplicità, a vLLM, per il serving in produzione ad alta velocità, e a GGUF/llama.cpp, per l'inferenza locale basata su CPU. Congratulazioni per aver completato il percorso di AI Engineering!
Domande Frequenti
La lezione «Valutare e distribuire il modello sottoposto a fine-tuning» è gratuita?
Sì — il testo completo di «Valutare e distribuire il modello sottoposto a fine-tuning» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Engineering Academy, passa a CoddyKit PRO. Il corso AI Engineering Academy include 4 lezioni in totale.
Cosa imparerò in «Valutare e distribuire il modello sottoposto a fine-tuning»?
Esegua valutazioni quantitative confrontando il modello di base e quello sottoposto a fine-tuning su casi di test esclusi dall'addestramento, converta il modello in GGUF per l'inferenza locale e lo r… Eserciti AI Engineering Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare AI Engineering Academy?
Non è richiesta alcuna esperienza precedente. AI Engineering Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Valutare e distribuire il modello sottoposto a fine-tuning»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione AI Engineering Academy?
Sì. Ogni lezione AI Engineering Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Quando il fine-tuning supera il prompting
- Preparare un dataset di addestramento di alta qualità
- Fine-tuning LoRA con Hugging Face PEFT
- Valutare e distribuire il modello sottoposto a fine-tuning