Última notícia há desconhecido
Tutorialpython-ia· Avançado· PT45M

Como Fazer Fine-Tuning de LLMs: Guia Prático

Quando e como especializar LLMs: OpenAI fine-tuning, LoRA e preparação de dataset.

11 de maio de 2026· Atualizado em 14 de maio de 2026por Análises SWEN.AI

O Que e Fine-Tuning e Quando Usar?

Fine-tuning e o processo de continuar o treinamento de um modelo de linguagem pre-treinado usando um dataset especializado. Em vez de partir do zero, voce ajusta os pesos do modelo para que ele aprenda padroes, vocabulario, estilos de resposta e formatos especificos do seu dominio.

A analogia mais clara: e como contratar um generalista altamente qualificado e treinalo intensivamente nas especificidades da sua empresa. Ele ja sabe trabalhar -- voce so esta moldando esse conhecimento para o seu contexto.

Quando vale fazer fine-tuning:

  • Voce quer um formato de saida extremamente consistente (JSON, codigo, templates)
  • Seu dominio tem terminologia ou estilo muito especifico
  • Voce executa a mesma tarefa milhoes de vezes e quer reduzir o tamanho dos prompts (= custo)
  • Prompt engineering chegou ao limite de qualidade
  • Voce precisa que o modelo foque num nicho especifico

Quando NAO vale:

  • Voce quer que o modelo saiba fatos novos (use RAG)
  • Voce tem menos de 50-100 exemplos de qualidade
  • Voce precisa de resultados amanha (fine-tuning demora horas a dias)
  • A tarefa funciona bem com um prompt bem feito

---

Fine-Tuning vs RAG vs Prompt Engineering

Estas tres tecnicas parecem competidoras, mas sao complementares. A escolha depende do problema.

| Criterio | Prompt Engineering | RAG | Fine-Tuning |

|---|---|---|---|

| Implementacao | Minutos | Horas/dias | Dias/semanas |

| Custo | Zero | Baixo (infra) | Medio a alto |

| Dados necessarios | Nenhum | Documentos | 50-10k exemplos |

| Atualizacao do conhecimento | Imediata | Imediata | Requer re-treino |

| Consistencia de formato | Media | Media | Alta |

| Reducao de tokens | Nao | Nao | Sim |

| Ideal para | Ajustes rapidos | Conhecimento dinamico | Estilo/formato fixo |

Recomendacao pratica: comece com prompt engineering. Se voce bater no teto de qualidade, adicione RAG para injetar contexto relevante. So considere fine-tuning quando RAG + prompts ainda nao entregar o que voce precisa -- ou quando o custo de tokens for inaceitavel em producao.

---

Fine-Tuning no GPT-4o-mini (OpenAI): Passo a Passo

A OpenAI permite fine-tuning nos modelos gpt-4o-mini, gpt-3.5-turbo e outros. O processo tem tres etapas: preparar o dataset, fazer o upload e criar o job de treinamento.

Preparando o Dataset

O formato exigido e JSONL (JSON Lines) -- um objeto JSON por linha, no formato de conversa:

{"messages": [{"role": "system", "content": "Classifique sentimentos: POSITIVO, NEGATIVO ou NEUTRO."}, {"role": "user", "content": "O produto chegou rapido e superou minhas expectativas!"}, {"role": "assistant", "content": "POSITIVO"}]}
{"messages": [{"role": "system", "content": "Classifique sentimentos: POSITIVO, NEGATIVO ou NEUTRO."}, {"role": "user", "content": "Demorou 3 semanas e o produto veio danificado."}, {"role": "assistant", "content": "NEGATIVO"}]}
{"messages": [{"role": "system", "content": "Classifique sentimentos: POSITIVO, NEGATIVO ou NEUTRO."}, {"role": "user", "content": "O produto e ok, nada demais."}, {"role": "assistant", "content": "NEUTRO"}]}

Diretrizes para o dataset:

  • Minimo de 10 exemplos (recomendado: 50-500+)
  • Qualidade > quantidade: exemplos ruins ensinam comportamentos ruins
  • Cada exemplo deve ser representativo do caso de uso real
  • Varie os exemplos -- nao repita o mesmo padrao com palavras diferentes
  • Separe 10-20% para validacao (parametro validation_file)

Script para gerar e validar o dataset:

import json

def criar_exemplo(system: str, user: str, assistant: str) -> dict:
    return {"messages": [
        {"role": "system", "content": system},
        {"role": "user", "content": user},
        {"role": "assistant", "content": assistant}
    ]}

def salvar_jsonl(exemplos: list, caminho: str):
    with open(caminho, "w", encoding="utf-8") as f:
        for ex in exemplos:
            f.write(json.dumps(ex, ensure_ascii=False) + "\n")

def validar_jsonl(caminho: str) -> bool:
    with open(caminho, "r", encoding="utf-8") as f:
        for i, linha in enumerate(f, 1):
            try:
                obj = json.loads(linha)
                assert "messages" in obj
                for msg in obj["messages"]:
                    assert "role" in msg and "content" in msg
            except Exception as e:
                print(f"Erro na linha {i}: {e}")
                return False
    print(f"Dataset valido! {i} exemplos.")
    return True

Upload e Criacao do Job

from openai import OpenAI

client = OpenAI()

# 1. Upload do arquivo de treino
with open("dataset_treino.jsonl", "rb") as f:
    arquivo = client.files.create(file=f, purpose="fine-tune")

print(f"Arquivo criado: {arquivo.id}")

# 2. Upload do arquivo de validacao (opcional mas recomendado)
with open("dataset_validacao.jsonl", "rb") as f:
    arquivo_val = client.files.create(file=f, purpose="fine-tune")

# 3. Criar o job de fine-tuning
job = client.fine_tuning.jobs.create(
    training_file=arquivo.id,
    validation_file=arquivo_val.id,
    model="gpt-4o-mini-2024-07-18",
    hyperparameters={
        "n_epochs": 3,
        "batch_size": "auto",
        "learning_rate_multiplier": "auto"
    },
    suffix="meu-classificador-v1"
)

print(f"Job criado: {job.id}")
print(f"Status: {job.status}")

Monitorando e Usando o Modelo Fine-Tuned

import time
from openai import OpenAI

client = OpenAI()

def monitorar_job(job_id: str):
    while True:
        job = client.fine_tuning.jobs.retrieve(job_id)
        print(f"Status: {job.status}")

        if job.status in ("succeeded", "failed", "cancelled"):
            if job.status == "succeeded":
                print(f"Modelo: {job.fine_tuned_model}")
            return job

        eventos = client.fine_tuning.jobs.list_events(job_id, limit=3)
        for ev in reversed(eventos.data):
            print(f"  [{ev.created_at}] {ev.message}")

        time.sleep(30)

def usar_modelo(modelo_id: str, mensagem: str) -> str:
    response = client.chat.completions.create(
        model=modelo_id,
        messages=[
            {"role": "system", "content": "Classifique sentimentos."},
            {"role": "user", "content": mensagem}
        ],
        temperature=0
    )
    return response.choices[0].message.content

modelo = "ft:gpt-4o-mini-2024-07-18:minha-org:classificador-v1:abc123"
print(usar_modelo(modelo, "Adorei o atendimento!"))  # POSITIVO

---

Fine-Tuning Local com LoRA/QLoRA

Para modelos open-source (LLaMA 3, Mistral, Qwen, Gemma), e possivel fazer fine-tuning localmente sem pagar por API. LoRA (Low-Rank Adaptation) e QLoRA (LoRA quantizado) reduzem drasticamente a memoria necessaria.

Configurando Ambiente

pip install transformers datasets peft accelerate bitsandbytes trl
nvidia-smi  # verificar CUDA

Requisitos minimos:

  • LoRA em modelo 7B: ~16GB VRAM (RTX 4080/4090, A100)
  • QLoRA 4-bit em modelo 7B: ~8GB VRAM (RTX 3080/4070)
  • QLoRA 4-bit em modelo 13B: ~12-14GB VRAM

Codigo com Transformers + PEFT

import torch
from datasets import Dataset
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig, TrainingArguments
from peft import LoraConfig, get_peft_model, TaskType
from trl import SFTTrainer

MODEL_ID = "meta-llama/Meta-Llama-3-8B-Instruct"
OUTPUT_DIR = "./llama3-finetuned"

# Configuracao QLoRA 4-bit
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16
)

tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
tokenizer.pad_token = tokenizer.eos_token

model = AutoModelForCausalLM.from_pretrained(
    MODEL_ID, quantization_config=bnb_config, device_map="auto"
)

lora_config = LoraConfig(
    r=16, lora_alpha=32,
    target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
    lora_dropout=0.05, bias="none",
    task_type=TaskType.CAUSAL_LM
)

model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# trainable params: 6,815,744 || all params: 8,037,367,808 (0.0848%)

def formatar_exemplo(ex):
    return f"<|system|>\n{ex['system']}\n<|user|>\n{ex['input']}\n<|assistant|>\n{ex['output']}"

dados_raw = [
    {"system": "Voce e um assistente de culinaria.", "input": "Como faco arroz perfeito?", "output": "Use 2 partes de agua para 1 de arroz..."},
]

dataset = Dataset.from_list([{"text": formatar_exemplo(d)} for d in dados_raw])

args = TrainingArguments(
    output_dir=OUTPUT_DIR, num_train_epochs=3,
    per_device_train_batch_size=2, gradient_accumulation_steps=4,
    learning_rate=2e-4, fp16=True, logging_steps=10,
    save_strategy="epoch", report_to="none"
)

trainer = SFTTrainer(
    model=model, train_dataset=dataset, args=args,
    dataset_text_field="text", max_seq_length=512, packing=False
)

trainer.train()
trainer.model.save_pretrained(OUTPUT_DIR)
print("Fine-tuning concluido!")

---

Avaliando a Qualidade do Fine-Tuning

Fine-tuning sem avaliacao e um desperdicio. Use estas metricas e estrategias:

Metricas automaticas:

  • Loss de validacao -- deve cair ao longo do treino sem subir ao final (overfitting)
  • Perplexity -- quanto menor, mais o modelo entende os exemplos
  • Accuracy por categoria -- para classificacao, meca por classe

Avaliacao humana (gold standard):

  • Crie 50-100 casos de teste com resposta esperada
  • Compare: modelo base vs fine-tuned vs GPT-4o como referencia
  • Use escala de 1-5 para qualidade, relevancia e formato
from openai import OpenAI

client = OpenAI()

def avaliar_modelo(modelo_base, modelo_finetuned, casos_teste):
    resultados = {"base": [], "finetuned": []}

    for caso in casos_teste:
        for modelo, chave in [(modelo_base, "base"), (modelo_finetuned, "finetuned")]:
            resp = client.chat.completions.create(
                model=modelo,
                messages=[
                    {"role": "system", "content": caso["system"]},
                    {"role": "user", "content": caso["input"]}
                ],
                temperature=0
            )
            obtido = resp.choices[0].message.content.strip()
            resultados[chave].append({
                "input": caso["input"],
                "esperado": caso["expected"],
                "obtido": obtido,
                "correto": obtido == caso["expected"].strip()
            })

    n = len(casos_teste)
    acc_base = sum(r["correto"] for r in resultados["base"]) / n
    acc_ft = sum(r["correto"] for r in resultados["finetuned"]) / n
    print(f"Acuracia base: {acc_base:.1%}")
    print(f"Acuracia fine-tuned: {acc_ft:.1%}")
    print(f"Melhoria: {(acc_ft - acc_base):.1%}")
    return resultados

---

Custo e Tempo Estimados

| Cenario | Modelo | Exemplos | Epochs | Tempo estimado | Custo estimado |

|---|---|---|---|---|---|

| Classificacao simples | gpt-4o-mini | 100 | 3 | 5-15 min | US$ 0,30 |

| Classificacao medio | gpt-4o-mini | 1.000 | 3 | 20-40 min | US$ 3,00 |

| Tarefa complexa | gpt-4o-mini | 5.000 | 3 | 1-2h | US$ 15,00 |

| LLaMA 3 8B (LoRA) | local | 1.000 | 3 | 30-60 min | Custo eletrico |

| LLaMA 3 8B (LoRA) | RunPod A100 | 5.000 | 3 | 1-2h | US$ 3-8 |

Obs: o custo da OpenAI para fine-tuning do gpt-4o-mini e de US$ 3,00 por 1M tokens de treino. Verifique a pagina de precos -- valores mudam.

---

Erros Comuns

Dataset pequeno ou desequilibrado: com menos de 50 exemplos, o modelo overfita. Com classes desequilibradas (90% de uma classe), ele aprende a ignorar as minoritarias.

Exemplos inconsistentes: se voce tem exemplos similares com respostas diferentes, o modelo nao converge. Revise manualmente antes de enviar.

Nao separar validacao: sem conjunto de validacao, voce nao sabe se esta sofrendo overfitting. Sempre separe 10-20% dos dados.

Re-usar o modelo fine-tuned para outro dominio: modelos fine-tuned tendem a esquecer capacidades gerais (catastrophic forgetting). Use-os apenas para a tarefa treinada.

Nao testar incrementalmente: treine com 100 exemplos, avalie, depois 500, avalie novamente. Escale so quando ver melhoria consistente.

Epochs demais: mais epochs nao e sempre melhor. A loss de validacao pode subir enquanto a de treino cai -- isso e overfitting. Monitore a curva de validacao.

---

Perguntas Frequentes

1. Quantos exemplos preciso para fine-tuning?

Depende da complexidade da tarefa. Para classificacao com 2-3 classes, 100 exemplos de qualidade podem ser suficientes. Para geracao de texto com estilo especifico, 500-2000 exemplos sao mais seguros. A OpenAI aceita a partir de 10, mas 50+ e o minimo pratico.

2. Fine-tuning muda o conhecimento do modelo?

Nao diretamente. Fine-tuning ajusta o comportamento, o estilo e o formato das respostas -- nao injeta fatos novos. Se voce quer que o modelo saiba informacoes recentes ou proprietarias, use RAG.

3. Posso fazer fine-tuning em GPT-4o (nao mini)?

Sim, a OpenAI disponibiliza fine-tuning para gpt-4o mas o custo e significativamente maior. Para a maioria dos casos, gpt-4o-mini fine-tuned supera o GPT-4o base em tarefas especificas.

4. O que e catastrophic forgetting?

E quando o modelo fine-tuned perde capacidades gerais ao especializar-se. Mais comum em modelos pequenos e com datasets grandes. A OpenAI mitiga isso no fine-tuning via API -- em modelos locais, tecnicas como regularizacao e replay de dados ajudam.

5. LoRA vs QLoRA: qual usar?

Use QLoRA se voce tem GPU com menos de 24GB VRAM -- o 4-bit reduz a memoria pela metade sem perda significativa de qualidade. Use LoRA sem quantizacao se tiver hardware suficiente e quiser o maximo de qualidade.

6. Posso publicar ou vender um modelo fine-tuned?

Depende da licenca do modelo base. Modelos como LLaMA 3 tem licencas que permitem uso comercial com restricoes. Modelos da OpenAI via fine-tuning API ficam na infraestrutura deles -- voce nao recebe os pesos, apenas acesso via API.

Tutoriais relacionados