Avançado 25 minFine-tuning

Fine-tuning de LLM localmente: exemplo passo a passo LoRA / QLoRA

O fine-tuning local de LLMs com LoRA e QLoRA permite adaptar um modelo de 8-9B (como Qwen 3.5 9B) ao seu vocabulário profissional, ao seu estilo de escrita ou a um formato de resposta específico — tudo isso em uma RTX 3090 usada. Não é mais necessário um cluster A100. Este guia leva você de nenhuma experiência prévia a um modelo GGUF carregado no Ollama, passando pelo formato do dataset, pelo notebook Unsloth passo a passo e pela exportação final.

Por Mohamed Meguedmi·Atualização 2026-08-27·Testado no Windows, macOS e Linux

#Por que fazer fine-tuning de um LLM local?

Um LLM de base é versátil, mas imperfeito para seu uso específico. A engenharia de prompts e o RAG resolvem 80% dos casos — o fine-tuning serve para os 20% restantes. Você deveria considerar o fine-tuning quando seu modelo precisa responder em um formato estrito (JSON, tags, estrutura interna), respeitar um estilo corporativo (tom, vocabulário), dominar uma área especializada (médica, jurídica ou técnica ligada à sua atividade) ou reproduzir comportamentos que nenhum prompt consegue realmente estabilizar.

Por outro lado, não use o fine-tuning para injetar conhecimento factual (o RAG faz isso melhor e permanece atualizado), corrigir uma única alucinação (um prompt melhor já basta) ou competir com o GPT-5 em benchmarks (você não ganhará).

i
Regra empírica
Se você puder expressar o que deseja com menos de 5 exemplos em um prompt, crie um prompt de sistema. Se tiver 50 ou mais exemplos e o modelo ainda se desviar das instruções, faça um fine-tuning.

#LoRA vs ajuste fino completo: por que LoRA vence

O kit IA Local

Seu ChatGPT privado e gratuito na sua máquina em 1 hora — LM Studio, Ollama, Open WebUI, seus documentos, sem nuvem.

  • Espaço online vitalício
  • PDF + arquivos
  • Atualizações vitalícias

O fine-tuning completo atualiza todos os parâmetros do modelo. Para um 7B em FP16, são 14 GB de pesos + cerca de 30 GB para os gradientes e o otimizador Adam. Total: no mínimo 40 a 60 GB de VRAM. Inacessível sem uma A100 80GB ou uma H100.

LoRA (Low-Rank Adaptation) congela os pesos originais e treina apenas pequenas matrizes de adaptação de posto r, inseridas nas camadas de atenção. Concretamente, para um modelo de 7B com r=16, você treina cerca de 20 milhões de parâmetros em vez de 7 bilhões — ou seja, 0,3% do modelo. A VRAM necessária para os gradientes e o otimizador cai drasticamente.

Fine-tune completo 7B
~60 GB de VRAM, 2-4× A100, várias horas, arquivo de saída de 14 GB.
LoRA 7B
~16 GB de VRAM, uma RTX 4080 é suficiente, 30 minutos a 2 horas, adaptador de apenas 30 a 200 MB.
QLoRA 7B
~6 GB de VRAM, uma RTX 3060 de 12 GB é suficiente, qualidade quase idêntica à da LoRA clássica.
→
Quase equivalente na prática
Em datasets de tamanho moderado (< 10.000 exemplos), o LoRA alcança 95 a 99% da qualidade de um fine-tune completo. A diferença só se torna perceptível em tarefas muito distantes do pré-treinamento. Para o seu primeiro fine-tune, não se preocupe em pensar nisso: use LoRA.

#QLoRA: a revolução da VRAM

O QLoRA vai mais longe: o modelo base é carregado em 4 bits (NF4, NormalFloat 4 bits) em vez de FP16. Durante o treinamento, os pesos permanecem quantizados; apenas os adaptadores LoRA em FP16 recebem os gradientes. Resultado: um 7B cabe em 5 a 6 GB de VRAM, um 13B em 10 GB, um 70B em 48 GB.

A perda de qualidade é desprezível graças a duas técnicas: a quantização NF4 (calibrada com base na distribuição gaussiana dos pesos) e a quantização dupla (as próprias constantes de quantização são quantizadas). Na prática, na maioria dos benchmarks, QLoRA fica a menos de 1% de diferença em relação a LoRA FP16.

i
A escolha padrão certa
Para um primeiro fine-tuning local, QLoRA é quase sempre a melhor escolha. Você economiza 60-70% de VRAM com perda de qualidade imperceptível. Mude para LoRA clássica apenas se o objetivo for uso em produção crítica com uma RTX 4090 ou superior.

#VRAM necessária por tamanho do modelo

Os números abaixo são mínimos realistas com Unsloth, tamanho de lote de 2, sequência de 2048 tokens e gradient checkpointing ativado. Adicione 20% de margem para os picos e o sistema operacional.

Modelo 2-3B (Qwen 3.5 2B, Granite 4.2 3B)
QLoRA: 4 GB de VRAM · LoRA FP16: 8 GB · GTX 1660 com 6 GB ou RTX 3050 são suficientes em QLoRA.
Modelo 8-9B (Granite 4.2 8B, Qwen 3.5 9B)
QLoRA: 6 GB de VRAM · LoRA FP16: 16 GB · RTX 3060 com 12 GB é confortável, RTX 3090 ideal.
Modelo 12B (Gemma 4 12B)
QLoRA: 10 GB VRAM · LoRA FP16: 28 GB · RTX 3090/4090 24 GB em QLoRA, A100 40GB em LoRA.
Modelo 27-35B (Qwen 3.8 27B, Qwen 3.6 35B-A3B)
QLoRA: 22 GB de VRAM · LoRA FP16: impossível em hardware de consumo · RTX 3090/4090 ou RTX 5090 com QLoRA estrito.
Modelo 70B (denso de ponta)
QLoRA: 48 GB VRAM · 2× RTX 3090 ou 1× A100 80GB · multi-GPU obrigatório com Unsloth Pro.

Para este guia, o modelo alvo é um 8-9B em QLoRA na RTX 3090 de 24 GB. É a combinação mais universal: uma RTX 3060 de 12 GB também é suficiente, mas uma RTX 3090 usada (preço variável) permite usar todos os tamanhos até 12B em QLoRA com conforto. Uma RTX 4090 ou 5090 oferece uma aceleração de 1,5 a 2×, mas não é indispensável.

#Pré-requisitos de hardware e software

GPU NVIDIA com CUDA 11.8+
No mínimo, uma RTX 3060 de 12 GB; uma RTX 3090 é recomendada. As GPUs AMD com ROCm funcionam parcialmente, mas o Unsloth é otimizado para CUDA — use uma GPU NVIDIA neste primeiro guia.
Python 3.10 ou 3.11
Não 3.12 (incompatibilidades com bitsandbytes no momento da redação). Use conda ou pyenv.
32 GB de RAM do sistema
16 GB podem ser suficientes, mas o carregamento inicial do modelo e a preparação do conjunto de dados são mais confortáveis com 32 GB.
50 GB de espaço em disco
Modelo base + checkpoints + adaptador mesclado + exportação GGUF Q4_K_M. Reserve espaço com folga.
Conexão adequada
O download inicial do modelo 8-9B é de 5 a 8 GB. Uma única vez.

No lado de software, usamos Unsloth (github.com/unslothai/unsloth), um framework que reescreve os kernels Triton para ganhar 2× de velocidade e 60% de memória em comparação com o padrão PEFT do Hugging Face. Instalação em um ambiente dedicado:

Instalação do Unsloth
conda create -n unsloth python=3.11 -y
conda activate unsloth
pip install --upgrade pip
pip install "unsloth[cu121-torch240] @ git+https://github.com/unslothai/unsloth.git"
pip install --no-deps trl peft accelerate bitsandbytes
!
Versões CUDA
Adapte cu121-torch240 à sua instalação: cu118 para CUDA 11.8, cu124 para CUDA 12.4. Verifique no canto superior direito da saída de nvidia-smi. Uma versão incorreta causará erros confusos na primeira importação.

#Preparar seu dataset no formato JSONL

O formato padrão para fine-tuning de instruções é JSONL (um objeto JSON por linha). Três variantes são comuns:

Formato Alpaca (o mais simples)
{"instruction": "Traduis en français formel.", "input": "Hey, what's up?", "output": "Bonjour, comment allez-vous ?"}
{"instruction": "Résume en une phrase.", "input": "Le chat noir a sauté...", "output": "Un chat noir saute sur la table."}
Formato ShareGPT (múltiplos turnos)
{"conversations": [
  {"from": "system", "value": "Tu es un assistant juridique."},
  {"from": "human", "value": "Qu'est-ce qu'une clause léonine ?"},
  {"from": "gpt", "value": "Une clause léonine est une disposition contractuelle..."}
]}

Para um primeiro ajuste fino, escolha Alpaca: um único turno de conversa, formato claro, com suporte nativo do Unsloth. Algumas regras cruciais para a qualidade:

Volume mínimo
300 exemplos para observar um efeito, 1.000 a 5.000 para um fine-tune sólido, 10.000+ para algo sério. Menos de 300, você perde seu tempo.
Qualidade > quantidade
100 exemplos impecáveis superam 5000 exemplos com ruído. Releia. Peça a outra pessoa para reler. O modelo aprende literalmente seu conjunto de dados, inclusive os defeitos.
Diversidade dos inputs
Se todos os seus inputs começarem com "Traduza", o modelo não saberá mais fazer nada além disso. Varie as formulações.
Comprimentos equilibrados
Se todas as suas saídas tiverem 2 frases, o modelo não saberá mais produzir uma resposta longa. Misture.
Reserve 10% para validação
Separe aleatoriamente train.jsonl e val.jsonl para medir o overfitting.
→
Gerar um conjunto de dados sintético
Você não tem 1000 exemplos à mão? Use um modelo grande (Claude, GPT-5 ou Qwen 3.8 27B local) para gerar pares de instrução/saída sintéticos a partir de seus documentos internos. Essa é a técnica padrão, chamada de "self-instruct". Estime de 1 a 2 horas de geração para 1000 exemplos.

#O notebook Unsloth comentado

Aqui está um script completo e mínimo para fazer o fine-tuning do Qwen 3.5 9B com QLoRA no seu conjunto de dados. Executar em um arquivo .py ou em um notebook Jupyter.

finetune.py — etapa 1: carregamento
from unsloth import FastLanguageModel
import torch

MODEL = "unsloth/Qwen3.5-9B-Instruct-bnb-4bit"
MAX_SEQ = 2048

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = MODEL,
    max_seq_length = MAX_SEQ,
    dtype = None,           # auto : bf16 sur Ampere+, fp16 sinon
    load_in_4bit = True,    # QLoRA : modèle quantifié 4-bit
)

O Unsloth hospeda versões pré-quantizadas em 4 bits da maioria dos modelos populares no Hugging Face (prefixo unsloth/). Download mais rápido, inicialização imediata. A primeira execução baixa aproximadamente 5 GB.

finetune.py — etapa 2: configuração LoRA
model = FastLanguageModel.get_peft_model(
    model,
    r = 16,                  # rang de la décomposition LoRA
    target_modules = [
        "q_proj", "k_proj", "v_proj", "o_proj",
        "gate_proj", "up_proj", "down_proj",
    ],
    lora_alpha = 16,
    lora_dropout = 0,
    bias = "none",
    use_gradient_checkpointing = "unsloth",  # économie VRAM
    random_state = 42,
)

O posto r=16 é um bom valor padrão. Aumente para 32 ou 64 se você tiver muitos dados (>10k) e um domínio muito distante do pré-treinamento. Um posto mais alto = mais parâmetros treináveis = mais capacidade, mas maior risco de sobreajuste.

finetune.py — etapa 3: conjunto de dados
from datasets import load_dataset

ALPACA_PROMPT = """### Instruction:
{}

### Input:
{}

### Réponse:
{}"""

EOS = tokenizer.eos_token

def format_prompt(ex):
    texts = [
        ALPACA_PROMPT.format(i, inp or "", out) + EOS
        for i, inp, out in zip(ex["instruction"], ex["input"], ex["output"])
    ]
    return {"text": texts}

ds = load_dataset("json", data_files="train.jsonl", split="train")
ds = ds.map(format_prompt, batched=True)
!
Não esqueça o token EOS
Sem EOS no final de cada exemplo, o modelo aprende a nunca parar. Sintoma típico: seu modelo ajustado por fine-tuning gera sem parar, repete ou emenda uma nova pergunta inventada. Sempre verifique se tokenizer.eos_token foi de fato adicionado.
finetune.py — etapa 4: treinamento
from trl import SFTTrainer
from transformers import TrainingArguments

trainer = SFTTrainer(
    model = model,
    tokenizer = tokenizer,
    train_dataset = ds,
    dataset_text_field = "text",
    max_seq_length = MAX_SEQ,
    args = TrainingArguments(
        per_device_train_batch_size = 2,
        gradient_accumulation_steps = 4,    # batch effectif = 8
        warmup_steps = 10,
        num_train_epochs = 3,
        learning_rate = 2e-4,
        fp16 = not torch.cuda.is_bf16_supported(),
        bf16 = torch.cuda.is_bf16_supported(),
        logging_steps = 10,
        optim = "adamw_8bit",
        weight_decay = 0.01,
        lr_scheduler_type = "linear",
        seed = 42,
        output_dir = "outputs",
    ),
)

trainer.train()

Em uma RTX 3090, com um conjunto de dados de 1000 exemplos e 3 épocas, conte com 20 a 40 minutos. Em uma RTX 4090, 12 a 25 minutos. Em uma RTX 5090, cerca de 8 a 15 minutos. Monitore a perda: ela deve diminuir de forma constante e depois se estabilizar. Se voltar a subir na validação, você está causando sobreajuste.

→
Quando parar
3 épocas são um bom valor padrão para um conjunto de dados de 1k a 5k exemplos. Acima de 5 épocas, o risco de overfitting torna-se sério: o modelo recita de cor em vez de generalizar. Se você tiver mais de 20k exemplos, reduza para 1 a 2 épocas.

#Exportar GGUF para Ollama

Seu adaptador LoRA está em outputs/. É um arquivo de algumas dezenas de MB, separado do modelo base. Para usá-lo em Ollama, são necessárias duas etapas: fundir o adaptador com o modelo e depois converter para GGUF quantizado.

finetune.py — etapa 5: exportar GGUF Q4_K_M
model.save_pretrained_gguf(
    "mon-modele-gguf",
    tokenizer,
    quantization_method = "q4_k_m",  # le défaut recommandé
)

O Unsloth cuida de tudo: fusão do adaptador com o modelo base, conversão via llama.cpp e quantização Q4_K_M. O resultado: um arquivo mon-modele-gguf/unsloth.Q4_K_M.gguf de cerca de 5,3 GB para um 9B. Q5_K_M e Q8_0 estão disponíveis se você quiser mais precisão (e arquivos maiores).

Para carregar no Ollama que escuta em localhost:11434, crie um arquivo Modelfile mínimo e salve o modelo:

Modelfile
cat > Modelfile <<EOF
FROM ./mon-modele-gguf/unsloth.Q4_K_M.gguf

TEMPLATE """### Instruction:
{{ .Prompt }}

### Réponse:
"""

PARAMETER temperature 0.7
PARAMETER stop "### Instruction:"
EOF

ollama create mon-modele -f Modelfile
ollama run mon-modele
i
O template deve corresponder
O template Ollama deve reproduzir exatamente o formato usado durante o treinamento (aqui Alpaca com ### Instruction: e ### Réponse:). Caso contrário, o modelo recebe prompts que nunca viu e começa a inventar. Se você usou ShareGPT ou ChatML, adapte conforme necessário.

#Dicas e solução de problemas

OutOfMemoryError na inicialização
Reduza per_device_train_batch_size para 1 e aumente gradient_accumulation_steps proporcionalmente. Reduza max_seq_length para 1024 se seus exemplos forem curtos.
Perda que não cai
Taxa de aprendizado muito baixa (tente 5e-4) ou formato de prompt corrompido. Imprima 2-3 exemplos de ds[0]["text"] e verifique visualmente se eles correspondem ao que você deseja.
Perda que explode (NaN)
Taxa de aprendizado muito alta. Volte para 1e-4. Ou ative bf16 se você estava usando fp16 em Ampere+ — fp16 tende a causar overflow.
Modelo que repete infinitamente
Token EOS ausente no treinamento ou parâmetro stop ausente no Modelfile. Os dois problemas frequentemente ocorrem ao mesmo tempo.
Sobreajuste visível
A perda de treino diminui, enquanto a perda de validação aumenta. Pare na época em que elas divergem. Reduza epochs ou aumente lora_dropout para 0.05.
Exportação para GGUF que falha
O Unsloth baixa o llama.cpp automaticamente na primeira execução — certifique-se de ter git, cmake e build-essential instalados no Linux. No Mac, execute xcode-select --install.
Modelo que ignora as novas instruções
Dataset pouco variado ou posto da LoRA muito baixo. Defina r=32 e lora_alpha=64 e execute novamente.
→
Manter o adaptador separado
Para iterar rapidamente, mantenha também uma versão não mesclada do adaptador (~100 MB) com model.save_pretrained("adapter"). Você pode reutilizá-la mais tarde com outro modelo base ou combiná-la a outros adaptadores sem ter que baixar tudo de novo.

#Para se aprofundar

Você tem um primeiro modelo com ajuste fino rodando no Ollama. Três caminhos naturais para se aprofundar:

Escolher a quantização correta
Você exportou em Q4_K_M por padrão. O guia de escolha da quantização compara Q4_K_M, Q5_K_M, Q8_0 e FP16 — útil para decidir se a qualidade do seu fine-tune merece Q5 ou Q8.
RAG em vez de fine-tune para conhecimento
Se você quiser que o modelo conheça seus documentos (e não apenas um estilo), o guia Introdução ao RAG local explica por que o RAG é quase sempre preferível ao fine-tune para injetar fatos.
Hardware para passar para modelos grandes
Para fazer o ajuste fino de modelos de 32B ou 70B com QLoRA, são necessários 24 GB e 48 GB de VRAM, respectivamente. O guia sobre qual LLM usar com 24 GB de VRAM mostra o que é possível nas RTX 3090, 4090 e RX 7900 XTX.
Este guia ajudou você?

Um comentário, um erro ou uma observação? Avise-nos; isso ajuda a melhorar o guia para todos.