Avaliando e implantando seu modelo ajustado
Execute avaliações quantitativas comparando o modelo base e o modelo ajustado em casos de teste reservados, converta-o para GGUF para inferência local e disponibilize-o por meio do llama.cpp ou do vLLM.
Avaliando e implantando seu modelo ajustado é uma aula grátis de AI Engineering Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de AI Engineering Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de AI Engineering Academy inclui 4 aulas no total.
Por que a avaliação deve vir antes da implantação
Um modelo ajustado que apresenta bom desempenho nos dados de treinamento pode ter desempenho pior que o modelo base no seu caso de uso real em produção. A única maneira de saber é fazer uma avaliação rigorosa. O ajuste fino pode causar esquecimento catastrófico — perda de capacidades que o modelo base possuía —, especialização excessiva — bom desempenho na sua tarefa, mas pior desempenho em tarefas relacionadas — ou regressões sutis nos comportamentos de segurança. Nunca implante um modelo ajustado sem avaliá-lo em comparação com o modelo base usando um conjunto de testes representativo.
Criando um conjunto de testes reservado
Seu conjunto de testes deve ser completamente separado dos dados de treinamento e validação — os exemplos não podem ter sido vistos pelo modelo durante nenhuma etapa do treinamento. O conjunto de testes deve representar a distribuição completa das entradas de produção: casos comuns, casos extremos e entradas adversariais. Para tarefas de seguimento de instruções, inclua exemplos que exijam seguir todos os aspectos da instrução, não apenas os mais comuns. Um conjunto de testes com 100 a 500 exemplos normalmente é suficiente para uma avaliação confiável.
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')Métricas quantitativas para avaliação específica da tarefa
Escolha métricas de avaliação compatíveis com sua tarefa. Para extração de JSON, meça a taxa de conformidade com o esquema e a precisão por campo. Para classificação, meça a acurácia, a precisão e a revocação por classe. Para geração de texto, use a pontuação de um LLM como avaliador para medir a qualidade. Para conformidade de formato, meça a taxa de conformidade exata com o formato. Execute cada métrica tanto no modelo base quanto no modelo ajustado para medir a diferença de melhoria.
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 metricsAvaliação com LLM como avaliador
Para tarefas de geração aberta, use um LLM como avaliador para pontuar as saídas do modelo ajustado em comparação com as saídas esperadas. Solicite ao GPT-4o que atue como avaliador, forneça a entrada, a saída esperada e a saída do modelo, e peça que avalie a correção, a completude e a conformidade de formato em uma escala de 1 a 5. Calcule a média das pontuações no conjunto de testes para obter uma classificação geral de qualidade. Compare a pontuação do modelo ajustado com a do modelo base no mesmo conjunto de testes.
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)Executando a avaliação comparativa
Execute uma avaliação direta comparando o modelo base, o modelo ajustado e, opcionalmente, uma referência forte baseada em prompts em todos os casos de teste. Gere saídas de cada modelo para cada caso de teste e, em seguida, pontue todas as saídas com suas métricas de avaliação. Produza uma tabela comparativa mostrando as pontuações das métricas, os desvios padrão e exemplos de situações em que o modelo ajustado supera ou fica atrás da referência.
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 summaryTestes de regressão para esquecimento catastrófico
O ajuste fino pode degradar as capacidades gerais do modelo, um fenômeno chamado esquecimento catastrófico. Execute uma suíte de testes de regressão tanto no modelo base quanto no modelo ajustado, abrangendo tarefas importantes além da tarefa-alvo: respostas a perguntas gerais, raciocínio, geração de código e seguimento de instruções. Se o modelo ajustado obtiver uma pontuação significativamente menor nessas tarefas, o posto do LoRA pode estar alto demais ou você pode ter treinado por épocas demais.
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 rateConvertendo para GGUF para inferência local
Para implantação local sem uma infraestrutura cara de GPU, converta seu modelo mesclado para o formato GGUF e execute a inferência com llama.cpp. O GGUF oferece vários níveis de quantização: Q4_K_M — 4 bits, bom equilíbrio entre qualidade e velocidade —, Q8_0 — 8 bits, qualidade próxima da total — e Q2_K — 2 bits, muito rápido, mas com qualidade inferior. Um modelo de 7 bilhões de parâmetros quantizado em Q4 requer apenas cerca de 4 GB de RAM e pode ser executado em CPU a uma velocidade de 1 a 5 tokens por segundo.
# 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'])Servindo com vLLM em produção
Para servir um modelo ajustado em produção em escala, o vLLM é atualmente o padrão. O vLLM usa PagedAttention para agrupar várias solicitações com eficiência, aumentando significativamente a capacidade de processamento da GPU. Ele oferece suporte a pontos de acesso de API compatíveis com a OpenAI, funcionando como substituto direto da API da OpenAI. Uma única GPU A100 executando vLLM com um modelo ajustado de 7 bilhões de parâmetros pode processar centenas de solicitações por 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)Teste A/B do modelo ajustado
Antes de mudar completamente para o modelo ajustado em produção, execute um teste A/B: direcione uma porcentagem do tráfego de produção — comece com 5% a 10% — para o modelo ajustado, enquanto a maioria continua usando o modelo base ou a abordagem de prompt existente. Monitore as pontuações de qualidade, a latência e as métricas de satisfação dos usuários nos dois grupos. Só aumente a parcela de tráfego do modelo ajustado se o teste A/B confirmar uma melhoria após um número estatisticamente significativo de solicitações.
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 summaryMantendo modelos ajustados ao longo do tempo
Modelos ajustados exigem manutenção contínua. Quando o modelo base for atualizado — por exemplo, com uma nova versão do GPT-4o ou uma nova versão do Mistral —, os pesos do seu adaptador podem deixar de ser compatíveis, e talvez seja necessário treinar novamente. Quando os requisitos da sua tarefa mudarem, você precisará atualizar os dados de treinamento e treinar novamente. Quando descobrir novos modos de falha em produção, adicione exemplos ao seu conjunto de treinamento. Planeje o retreinamento periódico como parte do fluxo de trabalho das operações de aprendizado de máquina em produção.
Matriz de decisão de implantação
A escolha de uma estratégia de implantação para seu modelo ajustado depende da sua escala e das restrições da sua infraestrutura. Para baixo volume (menos de 1.000 solicitações/dia), a API de ajuste fino da OpenAI é a opção mais simples. Para volume médio (de 1.000 a 100.000/dia), considere usar vLLM em uma única instância com GPU. Para aplicações de alto volume ou críticas em relação à latência, use vLLM com várias GPUs, considere o paralelismo de tensores e adicione uma camada de cache na frente. Para dados sensíveis à privacidade, hospede o modelo em sua própria infraestrutura usando GGUF/llama.cpp ou vLLM.
Verificação rápida
Teste sua compreensão sobre a avaliação e a implantação de modelos ajustados apresentadas nesta lição.
Recapitulação da lição
Nesta lição, você aprendeu que a avaliação rigorosa antes da implantação, comparando o modelo ajustado com o modelo base em casos de teste reservados, é indispensável; que o teste de regressão detecta o esquecimento catastrófico de capacidades gerais causado pela especialização excessiva; e que as opções de implantação vão da API gerenciada de ajuste fino da OpenAI, pela simplicidade, ao vLLM, para servir modelos em produção com alto volume de requisições, e ao GGUF/llama.cpp, para inferência local baseada em CPU. Parabéns por concluir a trilha de Engenharia de IA!
Perguntas Frequentes
A aula “Avaliando e implantando seu modelo ajustado” é grátis?
Sim — o texto completo de “Avaliando e implantando seu modelo ajustado” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de AI Engineering Academy, atualize para CoddyKit PRO. O curso de AI Engineering Academy inclui 4 aulas no total.
O que vou aprender em “Avaliando e implantando seu modelo ajustado”?
Execute avaliações quantitativas comparando o modelo base e o modelo ajustado em casos de teste reservados, converta-o para GGUF para inferência local e disponibilize-o por meio do llama.cpp ou do vL… Você pratica AI Engineering Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar AI Engineering Academy?
Nenhuma experiência prévia é necessária. AI Engineering Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Avaliando e implantando seu modelo ajustado”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de AI Engineering Academy?
Sim. Cada aula de AI Engineering Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Quando o ajuste fino supera a engenharia de prompts
- Preparando um conjunto de dados de treinamento de alta qualidade
- Ajuste fino com LoRA usando Hugging Face PEFT
- Avaliando e implantando seu modelo ajustado