Fine-tuning na prática — LoRA, QLoRA, DPO

TL;DR

A nota 16 - Fine-tuning vs prompting vs RAG decide quando fine-tunar; esta mostra como. Três camadas. Full fine-tuning atualiza todos os pesos — máximo poder, custo proibitivo (precisa do modelo inteiro + estados do otimizador na memória). PEFT (parameter-efficient fine-tuning) congela o modelo base e treina só um punhado de pesos novos: LoRA injeta matrizes de baixo posto e treina <1% dos parâmetros; QLoRA põe LoRA em cima de um base quantizado em 4 bits, e aí um modelo de 65B fine-tuna numa única GPU. E depois do SFT vem o alinhamento por preferência: DPO substitui o RLHF (reward model + PPO) por uma perda direta sobre pares “resposta boa / resposta ruim” — mais barato e mais estável. A regra de bolso de 2026: QLoRA para o SFT, DPO para o polimento, full fine-tuning quase nunca.

O insight que tornou fine-tuning acessível

Em 2021, fine-tunar um modelo de 65B parâmetros exigia um cluster de GPUs, semanas de computação e equipe especializada. Em 2023, um pesquisador com uma única GPU de consumidor (RTX 3090) podia fazer a mesma coisa em horas. O que mudou não foi o hardware — foi a descoberta de que você não precisa atualizar todos os pesos para mudar o comportamento do modelo.

A intuição veio de uma observação empírica: durante o fine-tuning, as atualizações de peso (ΔW) têm posto intrínseco baixo. Isso significa que, mesmo que ΔW seja uma matriz gigante (ex.: 4096×4096), ela pode ser aproximada por duas matrizes pequenas multiplicadas. Em vez de treinar 16 milhões de pesos, você treina apenas alguns milhares. O resultado? 99% do compute de treino reduzido, com perda de qualidade desprezível em tarefas de domínio.

Isso não era óbvio. A intuição dominante até então era “mais parâmetros = mais capacidade = melhor resultado”. LoRA mostrou que, para adaptar um modelo que já sabe muita coisa, a maioria dos parâmetros é ruído — você precisa mudar uma direção específica no espaço de pesos, não todos os eixos.

O que é

Fine-tuning é mudar os pesos do modelo — diferente de prompting/RAG, que só mexem no input (ver 16 - Fine-tuning vs prompting vs RAG). Mas “fine-tuning” virou guarda-chuva para coisas bem diferentes. Vale separar o que você ensina de como você ensina:

  • SFT (Supervised Fine-Tuning) — você dá pares entrada → saída ideal e o modelo aprende a imitar. Ensina forma e comportamento: formato de output, tom, jargão de domínio, seguir um schema. É o mesmo SFT do pipeline de treino de fronteira (18 - Como LLMs são treinados — pretraining, SFT, RLHF), só que num modelo já pronto e com seus dados.
  • Preference tuning — em vez de uma resposta certa, você dá duas (uma melhor, uma pior) e ensina o modelo a preferir a melhor. Ensina julgamento: ser mais útil, menos prolixo, recusar o que deve recusar. DPO e RLHF vivem aqui.

O resumo de uma frase

SFT ensina a imitar um exemplo; preference tuning ensina a escolher entre dois. As duas camadas mexem nos pesos — o que muda é o sinal de treino.

E há um eixo ortogonal: quantos pesos você toca. É aí que entram full FT, LoRA e QLoRA.

Por que importa

MotivaçãoPor que fine-tuning (e não prompt/RAG)
Formato/estilo consistente em escalaUm modelo fine-tuned “já nasce” no formato — sem gastar tokens de few-shot a cada chamada
Latência e custo por chamadaPrompt curto + modelo menor especializado bate prompt gigante num flagship
Jargão e comportamento de domínioPadrões que nenhum prompt captura bem (clínico, jurídico, código interno)
Soberania / on-premVocê é dono dos pesos — roda local (10 - Modelos locais e self-hosting), sem vazar dado para API
Destilar um comportamentoCapturar num modelo aberto o jeito de responder de um modelo maior (fronteira com destilação)

Fine-tuning ensina forma, não fatos

O erro clássico é fine-tunar para “ensinar conhecimento”. Não funciona bem: o modelo memoriza ruído e alucina com confiança. Conhecimento que muda → RAG. Comportamento/formato estável → fine-tuning. Ver a árvore de decisão em 16 - Fine-tuning vs prompting vs RAG.

Como funciona

Full fine-tuning — o caminho caro

Atualiza todos os pesos. O problema não é a inferência, é o treino: com Adam em precisão mista, cada parâmetro custa ~16-20 bytes (pesos fp16 + gradientes fp16 + dois estados do otimizador em fp32 + master weights). Um modelo de 7B já pede ~120GB só de estado de treino — multi-GPU obrigatório. Além do custo, há o risco de catastrophic forgetting: ao reescrever tudo, o modelo esquece habilidades gerais. Por isso, fora de labs, full FT é raro.

LoRA — treinar 1% e fingir que treinou tudo

A sacada (Hu et al., 2021): o update de peso durante o fine-tuning tem posto intrínseco baixo — ele não precisa de todos aqueles graus de liberdade. Então, em vez de aprender a matriz cheia ΔW (enorme), congela-se W e aprende-se ΔW = B·A, com A e B finas (posto r pequeno, tipo 8-64). Treina-se só A e Bmenos de 1% dos parâmetros.

W_efetivo = W_congelado + (alpha/r)·B·A
            └─ não treina ─┘  └── treina (LoRA) ──┘
graph LR
    subgraph "Camada de atenção com LoRA"
        X["Input x"] --> W["W original\n4096×4096\n(16.7M params)\n🔒 congelado"]
        X --> A["Matriz A\n4096×8\n(32k params)\n✏️ treina"]
        A --> B["Matriz B\n8×4096\n(32k params)\n✏️ treina"]
        W --> SUM["Σ soma"]
        B --> SUM
        SUM --> Y["Output h"]
    end
    note1["Total treinável: 64k params\nvs 16.7M do original\n= 0.38%"]
    style W fill:#cccccc,stroke:#666666
    style A fill:#99ff99,stroke:#009900
    style B fill:#99ff99,stroke:#009900
    style note1 fill:#fff3cd

Consequências práticas:

  • Memória despenca — sem estados de otimizador para bilhões de pesos; o grande custo vira só o base congelado em fp16 (~14GB para um 7B).
  • Adapters são plugáveis — o B·A treinado é um arquivo de poucos MB. Você troca de “personalidade” trocando o adapter, sobre o mesmo base. Dá para ter dezenas.
  • Hiperparâmetros que importam: r (posto — capacidade), alpha (escala do update), e os target modules (em quais projeções injetar — começa por q_proj/v_proj, expande para MLP se precisar).

QLoRA — onde compressão e fine-tuning se encontram

QLoRA (Dettmers et al., 2023) leva LoRA ao extremo: quantiza o base congelado para 4 bits (formato NF4) e prende os adapters LoRA, em precisão maior, por cima. O gradiente passa através do base quantizado, mas só os adapters aprendem.

graph TD
    subgraph "QLoRA: arquitetura de memória"
        BASE["Modelo base\n65B params\nQuantizado NF4 (4 bits)\n~33 GB na GPU\n🔒 congelado"]
        LORA["Adapters LoRA\nFP16 (16 bits)\n~30 MB\n✏️ treináveis"]
        PAGED["Paged Optimizers\nEstados em CPU RAM\nem vez de GPU VRAM"]
        BASE -- "gradiente passa\nthrough (STE)" --> LORA
        PAGED -- "swap sob\ndemanda" --> LORA
    end
    RESULT["🎯 Resultado:\nFine-tuning de 65B\nem 1 GPU de 48GB\n(ex: A6000)"]
    LORA --> RESULT
    style BASE fill:#ffcc99,stroke:#cc6600
    style LORA fill:#99ff99,stroke:#009900
    style PAGED fill:#e6e6ff,stroke:#6666cc

Com double quantization e paged optimizers, isso põe o fine-tuning de um 33B/65B numa única GPU. É a ponte literal com a nota 20 - Compressão de modelos — quantização e destilação: a quantização aqui não é só para rodar barato, é para treinar barato. Em 2026, QLoRA é o default de quem fine-tuna modelo aberto fora de um cluster.

DPO — alinhamento por preferência sem o circo do RLHF

Depois do SFT, você quer ajustar julgamento. O caminho clássico, o RLHF (18 - Como LLMs são treinados — pretraining, SFT, RLHF), treina um reward model e depois roda PPO — duas etapas, instável, caro de acertar. O DPO (Rafailov et al., 2023) reformula tudo como uma perda direta: dado um triplo (prompt, resposta escolhida, resposta rejeitada), otimize o modelo para dar mais probabilidade à escolhida que à rejeitada — sem reward model, sem loop de RL.

graph TD
    subgraph "RLHF (clássico) — 3 etapas"
        SFT_A["1. SFT"]
        RM["2. Reward Model\n(treinar separado)"]
        PPO["3. PPO\n(loop de RL instável)"]
        SFT_A --> RM --> PPO
    end
    subgraph "DPO — 1 etapa"
        DATA["Pares\n(prompt, chosen, rejected)"]
        DPO_LOSS["Perda DPO\n(log(σ(log π(chosen) - log π(rejected)))"]
        SFT_B["Modelo SFT\n(referência congelada)"]
        DATA --> DPO_LOSS
        SFT_B -- "KL regularization" --> DPO_LOSS
    end
    style PPO fill:#ff9999,stroke:#cc0000
    style DPO_LOSS fill:#99ff99,stroke:#009900

Um modelo de referência congelado (o próprio SFT) segura a rédea (um termo de KL) para o modelo não desandar. Variantes que você vai encontrar:

  • IPO — corrige uma tendência do DPO de “overfitar” a preferência.
  • KTO — usa rótulos binários soltos (isto é bom / isto é ruim), sem precisar de pares — mais fácil de coletar dado.
  • ORPO — funde SFT + preferência numa única etapa, sem modelo de referência. O mais enxuto dos pipelines.

A pipeline típica de um modelo aberto

flowchart TD
    BASE["Base pré-treinado\n(Llama 4 / Qwen 3 / Mistral)"]
    SFT["SFT com QLoRA\n→ Aprende formato, tom, jargão\nDados: pares entrada→saída\n~1k-100k exemplos"]
    INST["Modelo instruído"]
    DPO["DPO / ORPO\n→ Polimento de julgamento\nDados: triplos chosen/rejected\n~1k-10k pares"]
    ALIGN["Modelo alinhado"]
    MERGE["Merge adapter → base\nQuantiza para GGUF/GPTQ\n(opcional)"]
    DEPLOY["Deploy\nLocal (Ollama) / Edge / API"]

    BASE --> SFT --> INST --> DPO --> ALIGN --> MERGE --> DEPLOY
    style SFT fill:#99ccff,stroke:#0066cc
    style DPO fill:#99ff99,stroke:#009900
    style MERGE fill:#ffcc99,stroke:#cc6600

Quando usar qual

SituaçãoTécnicaMotivo
Tenho cluster e preciso do máximo de qualidadeFull fine-tuningSó aqui vale o custo; raro
SFT de um modelo aberto em 1 GPUQLoRA4-bit + adapters = cabe e é barato
Várias especializações sobre um baseLoRA (adapters)Troca de adapter, não de modelo
Polir comportamento depois do SFTDPO (ou ORPO)Alinhamento estável, sem reward model
Só tenho rótulos “bom/ruim” avulsosKTODispensa pares de preferência
Preciso de conhecimento atualizadoNada disso → RAGFine-tuning não guarda fatos bem

Ferramentas (2026)

  • HuggingFace PEFT + TRLpeft implementa LoRA/QLoRA; trl traz SFTTrainer, DPOTrainer, ORPOTrainer. O caminho de referência.
  • Axolotl — fine-tuning dirigido por arquivo de config (YAML); popular para reprodutibilidade.
  • Unsloth — kernels otimizados: ~2× mais rápido e menos VRAM que o baseline.
  • Llama-Factory — UI + CLI cobrindo SFT/DPO/quantização num lugar só.
  • Managed — OpenAI fine-tuning, Together, Fireworks, Predibase: você sobe o dataset, eles treinam (geralmente LoRA por baixo) e servem.

O formato do dado é metade do jogo: SFT pede pares instrução → resposta; DPO pede triplos prompt / chosen / rejected. Dado sujo = modelo pior.

Armadilhas

"Fine-tuning é sempre melhor"

É o mais caro e o menos flexível. Esgote prompting + RAG antes (16 - Fine-tuning vs prompting vs RAG).

Poucos dados, ou dados sujos

1.000 exemplos limpos batem 100.000 ruidosos. Abaixo de ~1k, costuma memorizar em vez de generalizar.

r mal calibrado

Posto alto demais overfita e desperdiça; baixo demais não aprende. Comece pequeno (8-16) e suba se o eval pedir.

Esquecer de avaliar no seu golden set

Benchmark genérico mente. Meça o modelo fine-tuned na sua tarefa (19 - Evaluation de LLMs em produção).

DPO sobre-otimizado

Preferência empurrada longe demais degrada qualidade geral; o termo de KL contra o modelo de referência existe para isso — não o zere.

Merge de LoRA em base quantizado

Fundir o adapter de volta num base 4-bit perde precisão; sirva o adapter separado ou faça o merge em fp16.

Destilar de API fechada

Treinar com saídas de um modelo comercial de terceiros costuma violar os ToS do provider (mesma armadilha da destilação).

Como explicar em inglês

Fine-tuning updates model weights (unlike prompting/RAG, which only modify inputs). In practice, full fine-tuning (all weights) is rarely viable outside of ML labs due to memory cost (~16-20 bytes per parameter for optimizer states). LoRA makes fine-tuning practical by exploiting the empirical observation that weight updates are low-rank: instead of training ΔW (the full weight delta), it trains two small matrices A and B such that ΔW ≈ BA, reducing trainable parameters by 99%+. QLoRA extends LoRA by quantizing the frozen base model to 4-bit NF4, reducing GPU memory enough to fine-tune a 65B model on a single GPU. After supervised fine-tuning (SFT), DPO replaces the unstable RLHF pipeline (reward model + PPO) with a direct loss over preference pairs — simpler, cheaper, and more stable.

PTEN
Ajuste finoFine-tuning
Ajuste fino supervisionadoSupervised fine-tuning (SFT)
Ajuste fino eficiente em parâmetrosParameter-Efficient Fine-Tuning (PEFT)
Adaptação de baixo postoLow-Rank Adaptation (LoRA)
AdaptadorAdapter
Posto da matrizMatrix rank
Esquecimento catastróficoCatastrophic forgetting
Otimização direta de preferênciaDirect Preference Optimization (DPO)
Modelo de recompensaReward model
Par de preferênciaPreference pair (chosen/rejected)
Quantização de 4 bits4-bit quantization / NF4
Otimizadores paginadosPaged optimizers

Ver mais

O que vem a seguir

Esta é a última nota do galho Anatomia dos LLMs. Se você chegou até aqui, já tem o modelo: como ele é montado (tokenização, atenção, janela de contexto), como é treinado (pretraining, SFT, RLHF) e como é adaptado depois de pronto (LoRA, QLoRA, DPO). Mas um LLM fine-tuned sozinho não é um produto — é uma peça. Três trilhas fecham o resto do quebra-cabeça:

  • Anatomia de Agents — um modelo (fine-tuned ou não) vira agent quando ganha um loop de decisão: observar, escolher uma ferramenta, agir, repetir. As técnicas desta nota moldam o comportamento; agents moldam o fluxo de controle em volta desse comportamento.
  • RAG e Vector Databases — o callout de “Por que importa” já avisou: fine-tuning ensina forma, não fatos. Quando o conhecimento muda com frequência (documentação, base de clientes, notícias), a resposta não é re-treinar — é buscar e injetar contexto em tempo de execução. RAG é o “irmão” que resolve o que fine-tuning propositalmente não resolve.
  • Context Engineering — junto de RAG, a outra face da mesma moeda: em vez de mudar os pesos (fine-tuning) ou buscar fatos (RAG), você desenha o que entra no prompt — prompt, contexto, intenção, especificação. Muita adaptação de comportamento que hoje vira LoRA começou como um problema mal-resolvido de context engineering.

A pergunta que guia qual trilha seguir: você quer mudar como o modelo se comporta (fine-tuning, já feito), como ele decide e age (Agents), o que ele sabe no momento da chamada (RAG) ou o que você coloca na frente dele (Context Engineering)? Frequentemente a resposta certa em produção é “os quatro, em camadas” — mas agora você tem o vocabulário pra escolher a dose certa de cada um.

Veja também

Referências

  • Hu et al.LoRA: Low-Rank Adaptation of Large Language Models (2021). arxiv:2106.09685. O método PEFT dominante.
  • Dettmers et al.QLoRA: Efficient Finetuning of Quantized LLMs (2023). arxiv:2305.14314. NF4, double quant, paged optimizers.
  • Rafailov et al.Direct Preference Optimization (2023). arxiv:2305.18290. RLHF sem reward model.
  • Hong et al.ORPO: Monolithic Preference Optimization without Reference Model (2024). arxiv:2403.07691.
  • HuggingFacePEFT e TRL (docs). Implementações de referência de LoRA/QLoRA e SFT/DPO/ORPO.
  • Unsloth / Axolotl (GitHub) — toolchains de fine-tuning otimizadas e config-driven.