Ajuste Fino Supervisionado

O que é Ajuste Fino Supervisionado (Supervised Fine-Tuning, SFT)?

O ajuste fino supervisionado (supervised fine-tuning, SFT) é uma forma comum de adaptar um modelo de linguagem grande (large language model, LLM) pré-treinado (pretrained) para seguir instruções e executar tarefas específicas com mais confiabilidade. No SFT, você pega um modelo que já aprendeu padrões gerais de linguagem durante o pré-treinamento (pretraining) e continua treinando-o em um conjunto de dados rotulado (labeled dataset) de exemplos de instrução–resposta (às vezes chamado de ajuste por instruções (instruction tuning)).

Conceitualmente, o SFT trata um LLM como um gerador condicional (conditional generator):

  • Entrada: uma instrução (e, opcionalmente, contexto extra como um documento, saída de ferramentas ou histórico de conversa)
  • Alvo: uma resposta desejada escrita por um humano (ou por um modelo de alta qualidade)

Ao otimizar o modelo para reproduzir as respostas-alvo, o SFT ensina como responder nos estilos, formatos e comportamentos que você deseja.

O SFT normalmente faz parte de um pipeline mais amplo de adaptação de LLM:

  • Pré-treinamento em grandes textos não rotulados (predição do próximo token (next-token prediction))
  • SFT em dados rotulados de instrução–resposta
  • Etapas opcionais de otimização de preferências / alinhamento (preference optimization / alignment) (por exemplo, abordagens no estilo aprendizado por reforço com feedback humano (Reinforcement Learning from Human Feedback, RLHF))

Este artigo foca na etapa de SFT: formatos de dados, objetivo de treinamento e considerações práticas — e como o SFT se relaciona com métodos eficientes em parâmetros, como LoRA (Adaptação de Baixa Patente; Low-Rank Adaptation) sob o guarda-chuva de Ajuste Fino Eficiente em Parâmetros (PEFT; Parameter-Efficient Fine-Tuning).

Por que o SFT funciona para LLMs

O pré-treinamento ensina a um LLM padrões linguísticos e factuais amplos usando predição do próximo token. No entanto, modelos pré-treinados não são necessariamente bons em:

  • Seguir instruções explícitas (“Escreva um objeto JSON com os campos X e Y”)
  • Recusar solicitações inseguras de forma consistente
  • Produzir saídas estruturadas (structured outputs) com confiabilidade
  • Adotar um tom ou estilo de domínio específico (jurídico, médico, suporte ao cliente)
  • Lidar com convenções de chat de múltiplos turnos (papéis system/user/assistant)

O SFT resolve isso fornecendo supervisão direta: dada esta instrução/contexto, produza esta resposta. Após o SFT, o modelo tende a ser:

  • Mais prestativo e melhor em seguir instruções
  • Mais consistente na formatação
  • Melhor nas tarefas representadas no conjunto de treinamento

O SFT não concede magicamente novas capacidades fora da distribuição dos dados; ele, em geral, melhora comportamentos que estão presentes no conjunto de dados e que são compatíveis com o conhecimento latente do modelo pré-treinado.

Formatos comuns de dados para SFT

Conjuntos de dados de SFT vêm em múltiplas formas, mas todos se reduzem ao mesmo padrão de treinamento: concatenar um contexto semelhante a um prompt (prompt) com uma resposta-alvo e, então, treinar o modelo para prever os tokens (tokens) da resposta.

1) Instrução–resposta de turno único (o “instruction tuning” clássico)

Um formato JSONL comum é:

{"instruction": "Summarize the following text in 2 sentences.", "input": "Text: ...", "output": "Two-sentence summary ..."}

Muitas vezes input é opcional. Na hora do treinamento, você o converte em um modelo de prompt, como:

Instruction: Summarize the following text in 2 sentences.
Input: Text: ...
Response: Two-sentence summary ...

2) Formato de chat / mensagens (conversas de múltiplos turnos)

Muitos LLMs modernos são treinados com “papéis” (roles) explícitos (system/user/assistant). Um formato típico:

{
  "messages": [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "Write a haiku about compilers."},
    {"role": "assistant", "content": "Parsing the quiet\nTokens fall in ordered streams\nErrors fade to null"}
  ]
}

Para treinamento com múltiplos turnos, você pode incluir vários pares user/assistant, em que o modelo aprende a gerar cada turno do assistente condicionado ao histórico.

3) Formato “Prompt + completion” (APIs no estilo completion)

Alguns conjuntos de dados armazenam exatamente o que o modelo vê e o que ele deve completar (completion):

{"prompt": "<|user|>Explain gradient descent.\n<|assistant|>", "completion": "Gradient descent is ..."}

Esse formato é conveniente porque mapeia diretamente para o treinamento de predição do próximo token, mas você precisa ter cuidado com onde o modelo está autorizado a aprender (ver “mascaramento da perda (loss masking)” abaixo).

4) Saídas estruturadas (JSON, XML, chamadas de função)

O SFT é amplamente usado para impor saídas estruturadas:

{
  "instruction": "Extract entities and return valid JSON with keys: people, orgs.",
  "input": "Apple hired Jane Doe from Acme Corp.",
  "output": "{\"people\": [\"Jane Doe\"], \"orgs\": [\"Apple\", \"Acme Corp\"]}"
}

Na prática, você frequentemente mistura exemplos estruturados e não estruturados para evitar fragilidade.

O objetivo de treinamento: entropia cruzada nos tokens-alvo

O SFT normalmente usa o objetivo padrão de modelagem de linguagem: maximizar a verossimilhança dos tokens de resposta desejados dado o contexto do prompt. De forma equivalente, minimizar a perda de entropia cruzada (cross-entropy loss) (Perda de Entropia Cruzada) sobre os tokens-alvo.

Dada uma sequência de tokens dividida em:

  • tokens de prompt/contexto: (x_{1:m})
  • tokens de alvo/resposta: (y_{1:n})

O SFT treina o modelo para prever cada próximo token-alvo:

[ \mathcal{L} = -\sum_{t=1}^{n} \log p_\theta(y_t \mid x_{1:m}, y_{1:t-1}) ]

Essa é a mesma mecânica do pré-treinamento (predição do próximo token) usando Arquitetura Transformer, otimizada via Retropropagação e Descida do Gradiente — mas aplicada a sequências rotuladas por instruções.

Teacher forcing e por que isso importa

Durante o treinamento, o modelo recebe os tokens anteriores de verdade-terreno (forçamento do professor (teacher forcing)), e não suas próprias saídas amostradas. Isso torna a otimização estável e eficiente, mas também significa:

  • O modelo aprende a imitar as respostas do conjunto de dados de perto
  • Erros podem se acumular no tempo de inferência se o modelo se desviar do estilo de resposta esperado (uma forma de viés de exposição (exposure bias))

Mascaramento da perda (treinar apenas nos tokens do assistente)

No SFT de chat, é comum computar a perda apenas nos tokens do assistente, e não nos tokens de system/user. Ou seja, você alimenta a conversa inteira como entrada, mas só penaliza erros nos turnos do assistente.

Por quê?

  • Em geral, você não quer que o modelo “aprenda” a produzir mensagens do usuário
  • Você quer que a massa de probabilidade do modelo se concentre em gerar boas respostas do assistente, e não em reproduzir o prompt

Concretamente, a maior parte do código de treinamento constrói labels iguais aos IDs de tokens de entrada, e então define os rótulos como -100 (ignore index) para tokens que não devem contribuir para a perda (tokens de system/user/prefixo).

Exemplo prático: uma amostra de treinamento do início ao fim

Suponha que queremos ensinar o modelo a responder em um modelo específico.

Instrução

Classifique o sentimento como Positivo, Neutro ou Negativo. Produza apenas o rótulo.

Entrada

“A atualização corrigiu minhas quedas, mas a interface ainda é confusa.”

Alvo

Neutro

Um modelo de prompt simples poderia ser:

Instruction: Classify the sentiment as Positive, Neutral, or Negative. Output only the label.
Text: The update fixed my crashes, but the UI is still confusing.
Answer:

O modelo é treinado para gerar Neutral após Answer:.

Se você incluir muitos exemplos desse tipo, o SFT tende a melhorar:

  • Seguir “Output only the label”
  • Não adicionar explicação extra
  • Formatação consistente entre tarefas

Qualidade do conjunto de dados: o principal fator dos resultados de SFT

Para SFT, a qualidade dos dados geralmente importa mais do que a quantidade de dados a partir de certo ponto. Dimensões-chave:

Correção e utilidade

Se seu conjunto de dados contém respostas erradas, o modelo irá aprendê-las. Até problemas sutis — como respostas que soam confiantes, mas são vagas — podem aumentar comportamento semelhante a alucinações (hallucination).

Verificações práticas:

  • Amostrar e revisar manualmente exemplos
  • Usar validadores automatizados para saídas estruturadas (por exemplo, checagens de parse de JSON)
  • Filtrar respostas com contradições, recusas quando ajuda é apropriada, ou verbosidade excessiva

Diversidade e cobertura de instruções

Se você treinar apenas em sumarização, não espere grandes melhorias em geração de código. Seu conjunto de dados deve refletir a distribuição das tarefas que você considera importantes:

  • Perguntas e respostas, extração, reescrita, classificação, arcabouço para uso de ferramentas, etc.
  • Diferentes domínios (documentação de produto, tickets de suporte, wiki interna, texto jurídico)

Uma estratégia comum é misturar múltiplos tipos de tarefa para melhorar o seguimento geral de instruções.

Consistência de estilo e políticas

Se metade do seu conjunto de dados responde de forma breve e metade responde com longas redações, o modelo fará uma média disso. Se o comportamento de segurança for inconsistente (às vezes recusando, às vezes atendendo), o modelo também será inconsistente.

Defina e imponha:

  • diretrizes de tom (conciso vs verboso)
  • limites da política de recusa
  • política de citação ou de “dizer que não sabe”

Vazamento e contaminação de dados

Se benchmarks de avaliação aparecerem nos dados de treinamento, os resultados se tornam enganosos. Isso é uma forma de vazamento de dados (data leakage).

Mitigações:

  • Deduplicar contra conjuntos de avaliação (correspondência exata e aproximada)
  • Usar divisões baseadas no tempo quando possível (treinar com dados mais antigos, testar com dados mais novos)
  • Rastrear cuidadosamente a proveniência do conjunto de dados

Sobreajuste, esquecimento catastrófico e generalização

SFT é aprendizado supervisionado; ele pode sofrer sobreajuste como qualquer outro.

Sintomas de sobreajuste

  • A perda de treinamento diminui enquanto a perda de validação aumenta
  • O modelo fica excessivamente “guiado por template”, frágil a variações do prompt
  • O modelo tem pior desempenho em tarefas gerais que antes conseguia resolver

Mitigações:

  • Parada antecipada (early stopping) com base em métricas de validação
  • Taxas de aprendizado menores (comum em ajuste fino de LLM)
  • Regularização (decaimento de pesos (weight decay)), dropout (dropout) (se habilitado)
  • Aumentar o tamanho/diversidade do conjunto de dados, melhorar a qualidade dos rótulos

Esquecimento catastrófico

Se você fizer SFT intensivamente em dados estreitos (por exemplo, cláusulas de contratos jurídicos), o modelo pode perder a habilidade de conversa geral ou comportamentos de conhecimento geral. Isso é chamado de esquecimento catastrófico (catastrophic forgetting).

Mitigações comuns:

  • Misturar dados gerais de instruções
  • Misturar uma pequena quantidade de texto geral (às vezes chamado de “replay”)
  • Usar taxas de aprendizado menores e menos épocas (epochs)
  • Usar métodos eficientes em parâmetros para restringir atualizações (ver abaixo)

Considerações de configuração de treinamento (o que praticantes ajustam)

Taxa de aprendizado e número de épocas

LLMs são sensíveis à taxa de aprendizado. Padrões típicos:

  • O ajuste fino completo (full fine-tuning) frequentemente usa taxas de aprendizado pequenas (por exemplo, na faixa de 1e-6 a 2e-5, altamente dependente do tamanho do modelo e dos dados)
  • 1–3 épocas é comum; mais pode causar sobreajuste, a menos que o conjunto de dados seja grande e diverso

Comprimento de sequência, empacotamento e formação de lotes

Exemplos de SFT podem ser curtos (classificação) ou longos (chat de múltiplos turnos). Treinamento eficiente frequentemente usa:

  • Empacotamento (packing): concatenar múltiplos exemplos curtos em uma sequência longa para reduzir desperdício com padding
  • Atenção cuidadosa para não “contaminar” rótulos entre exemplos empacotados (os tokens de prompt de cada exemplo devem permanecer mascarados adequadamente)

Tokenização e tokens especiais

Seu formato de prompt deve corresponder aos tokens esperados pelo modelo (por exemplo, marcadores de papel em chat). Formatação incompatível pode causar grandes regressões de qualidade, porque o modelo foi pré-treinado ou ajustado por instruções com uma convenção específica (Tokenização também é relevante).

Avaliação: além da perda

A perda de validação é útil, mas não suficiente. Uma boa avaliação frequentemente inclui:

  • Métricas específicas de tarefa (accuracy/F1 para classificação, ROUGE para sumarização, pass@k para código, etc.)
  • Métricas de aderência a formato (taxa de parse de JSON)
  • Avaliação humana de utilidade, factualidade e segurança
  • Testes de regressão (regression tests) para comportamentos conhecidos (“não revela segredos”, “usa o esquema (schema) exigido”, etc.)

Ajuste fino completo vs PEFT: onde o LoRA se encaixa

SFT descreve o objetivo de treinamento e os dados (instrução–resposta supervisionada). Como você aplica atualizações aos parâmetros do modelo é uma escolha separada:

  • Ajuste fino completo: atualizar todos (ou a maioria) dos pesos do modelo
  • Ajuste fino eficiente em parâmetros (PEFT): atualizar um pequeno número de parâmetros enquanto congela o modelo-base (base model)

Métodos de PEFT são descritos com mais detalhes em Ajuste Fino Eficiente em Parâmetros (PEFT). Uma técnica de PEFT amplamente usada para SFT é o LoRA (Adaptação de Baixa Patente; Low-Rank Adaptation).

Por que usar LoRA para SFT?

O LoRA injeta pequenas matrizes de baixa patente treináveis em certas camadas lineares (frequentemente projeções de atenção (attention) e/ou do perceptron multicamadas (multi-layer perceptron, MLP)). Benefícios:

  • Uso de memória de vídeo (VRAM) muito menor do que no ajuste fino completo
  • Treinamento mais rápido e experimentação mais fácil
  • Você pode manter múltiplos “adaptadores (adapters)” para diferentes tarefas/domínios sobre um único modelo-base
  • Frequentemente reduz o esquecimento catastrófico porque os pesos-base ficam congelados

Trade-offs:

  • A qualidade de pico pode ser ligeiramente menor do que no ajuste fino completo em alguns cenários (embora frequentemente comparável)
  • Exige escolha cuidadosa de módulos-alvo, posto (rank) e escala (scaling)

Na prática, muitas equipes adotam SFT + LoRA como linha de base padrão: é custo-efetivo e tipicamente forte.

Como o SFT se relaciona com outros métodos de alinhamento

O SFT ensina o modelo a imitar “boas respostas”. No entanto, conjuntos de dados de instruções geralmente contêm uma resposta escolhida por prompt, e não codificam explicitamente preferências entre múltiplas respostas.

Outras etapas de alinhamento (frequentemente aplicadas após o SFT) usam comparações ou recompensas para moldar o comportamento:

  • Aprendizado de preferências: “A resposta A é melhor do que a resposta B”
  • Modelagem de recompensa (reward modeling) + aprendizado por reforço (reinforcement learning) (estilo RL)
  • Variantes de otimização direta de preferências (direct preference optimization)

O SFT ainda é fundamental porque:

  • Fornece uma inicialização supervisionada forte para alinhamento posterior
  • Ensina seguimento básico de instruções e formatação
  • Métodos de preferência geralmente funcionam melhor quando o modelo já produz candidatos razoáveis

Armadilhas comuns no SFT (e como evitá-las)

Treinar com dados sintéticos de baixa qualidade sem filtragem

Dados sintéticos de instrução podem ajudar, mas, se você gerar grandes volumes sem controle de qualidade, o modelo pode aprender:

  • texto prolixo de preenchimento
  • raciocínio incorreto
  • comportamento de recusa e segurança inconsistente

Mitigação: use filtros fortes (heurísticas (heuristics) + avaliadores baseados em modelo (model-based judges)) e mantenha um conjunto central revisado por humanos.

Templates de prompt inconsistentes

Se seu conjunto de dados usa múltiplos templates incompatíveis (“### Instruction”, “User:”, diferentes tokens de papel), o modelo pode ficar confuso.

Mitigação: padronize em um formato canônico alinhado à convenção de chat do modelo-base.

Não mascarar os tokens do prompt

Se você computa a perda sobre toda a sequência concatenada (prompt + resposta), o modelo pode aprender a reproduzir o prompt e os papéis. Isso pode causar comportamentos estranhos (por exemplo, produzir User: ou repetir instruções).

Mitigação: masque tokens que não sejam do assistente na perda.

Otimizar demais por “utilidade” em detrimento da veracidade

Exemplos de SFT frequentemente recompensam respostas confiantes e completas — mesmo quando o prompt não pode ser respondido.

Mitigação:

  • incluir exemplos que corretamente dizem “Eu não sei” ou pedem esclarecimento
  • adicionar tarefas que exigem citar o contexto fornecido e recusar fabricar fora dele

Aplicações práticas do SFT

O SFT é amplamente usado para:

  • Assistentes de chat: melhor seguimento de instruções, padrões mais seguros, persona consistente
  • Adaptação a domínio: por exemplo, helpdesk interno de TI, suporte a redação jurídica, estruturação de notas médicas (com governança apropriada)
  • Extração de informação: converter texto não estruturado em campos estruturados
  • Rascunho para suporte ao cliente: controle de tom, aderência a políticas, respostas com template
  • Assistentes de código: guias de estilo, padrões específicos de API, convenções da empresa
  • Chamada de ferramentas / funções (tool / function calling): produzir saídas restritas que acionam ferramentas com confiabilidade

Um padrão recorrente é começar com um modelo-base geral e, em seguida, aplicar SFT em um conjunto de dados cuidadosamente curado que reflita o ambiente-alvo.

Esboço mínimo em pseudo-código (o que “é” o SFT computacionalmente)

Em alto nível, SFT é apenas predição do próximo token em sequências rotuladas:

# Pseudo-code
for batch in dataloader:
    input_ids, attention_mask, labels = batch

    # labels: -100 for tokens we want to ignore (e.g., user/system tokens)
    logits = model(input_ids, attention_mask=attention_mask).logits

    loss = cross_entropy(logits.view(-1, vocab_size), labels.view(-1), ignore_index=-100)
    loss.backward()
    optimizer.step()
    optimizer.zero_grad()

Todo o resto — templates, mascaramento, empacotamento, adaptadores, avaliação — determina se este loop simples produz um modelo útil e capaz de seguir instruções.

Resumo

O ajuste fino supervisionado (SFT) adapta um LLM pré-treinado ao treinar em pares rotulados de instrução–resposta, tipicamente usando perda de entropia cruzada nos tokens-alvo (do assistente). É a forma padrão de melhorar o seguimento de instruções, a confiabilidade de formatação e o desempenho em domínio/tarefa — desde que o conjunto de dados seja de alta qualidade e esteja bem alinhado ao comportamento desejado.

Na prática, o sucesso do SFT depende fortemente de:

O SFT não é o fim do alinhamento, mas costuma ser a etapa mais impactante e acessível para transformar um LLM geral em um sistema útil e capaz de seguir instruções.