Um modelo como o Claude Opus 5 ou o Gemini 3.7 Flash resolve praticamente qualquer tarefa genérica, mas nenhum dos dois vai escrever exatamente no tom da sua marca ou devolver sempre o mesmo formato de JSON que o seu sistema espera. Para isso existe o fine-tuning: pegar num modelo open source e afiná-lo com os seus próprios dados. O problema é que o processo clássico, com Hugging Face Transformers puro, consome muita VRAM e demora horas mesmo em tarefas simples. É aí que entra o Unsloth, uma biblioteca open source que reescreveu partes do treino em kernels Triton personalizados e promete o dobro da velocidade com muito menos memória.
Este tutorial mostra como instalar o Unsloth, escolher um modelo base atual, treinar um adaptador LoRA ou QLoRA, testar os resultados e exportar tudo para correr localmente no Ollama. No final vai ter um script Python completo e funcional, uma tabela de custos reais de GPU e uma lista de erros que costumam fazer perder uma tarde inteira a quem tenta isto pela primeira vez.
Este guia não parte do zero absoluto. Assume que já experimentou modelos generalistas por API, seja o ChatGPT, o Gemini ou o Claude, e que já sentiu o limite do que um prompt bem escrito consegue garantir de forma consistente. Talvez o modelo continue a variar a estrutura da resposta de pedido para pedido, ou “esqueça” uma instrução depois de várias trocas de mensagens na mesma conversa. É precisamente nesse ponto que compensa investir algumas horas a preparar dados de treino próprios, em vez de continuar a empilhar regras num prompt cada vez mais longo e cada vez mais frágil a cada atualização do modelo por trás da API.
O que é o Unsloth e porque está a mudar o fine-tuning em 2026
O Unsloth nasceu como um projeto focado numa ideia simples: o treino com LoRA e QLoRA passa a maior parte do tempo a fazer operações matemáticas repetitivas que podem ser otimizadas ao nível do kernel de GPU. Em vez de depender só do código genérico do Hugging Face Transformers, o Unsloth reescreve os pontos mais pesados do cálculo em Triton, a linguagem de kernels da OpenAI, e evita recomputação desnecessária de gradientes. O resultado, segundo a documentação oficial do projeto, é treino até 2x mais rápido e até 70% menos uso de VRAM face ao Hugging Face Transformers com PEFT normal, sem perda de precisão no resultado final.
Para arquiteturas MoE (mixture of experts), a equipa do projeto reporta ganhos ainda maiores: até 12x mais rápido e 35% menos VRAM em comparação com a versão 4 do Transformers, segundo notas de lançamento publicadas em fevereiro de 2026. O repositório no GitHub já passou a marca de 70 mil estrelas, segundo dados recolhidos em agosto de 2026, o que o coloca entre as ferramentas de fine-tuning open source mais usadas do momento, ao lado do Axolotl e do LLaMA-Factory.
O que torna o Unsloth particularmente atrativo para quem está a começar é a lista de modelos suportados. À data deste artigo, a ferramenta cobre famílias como Qwen3.8, DeepSeek (arquitetura R1 e V3), GLM 4.7, Gemma 3 e Gemma 3n, Llama 4, Mistral v0.3 e ainda modelos open weight mais recentes como o gpt-oss-20b. Isto significa que consegue treinar praticamente qualquer modelo relevante lançado nos últimos meses sem trocar de ferramenta a cada novo release.
Unsloth vs Axolotl vs LLaMA-Factory: como se posiciona
O Unsloth não é a única opção para quem quer treinar modelos localmente. O Axolotl, que chegou à versão 0.18.0 em julho de 2026, segue uma filosofia diferente: tudo é configurado por um único ficheiro YAML, o que agrada a quem gosta de deixar a configuração documentada e versionada num repositório Git. O LLaMA-Factory, também atualizado nesse mesmo mês para a versão 0.9.5, aposta numa interface web e numa CLI sem código, pensada para quem prefere clicar em vez de escrever scripts, e afirma suportar mais de cem arquiteturas de modelos diferentes.
O Unsloth ocupa um lugar intermédio. Continua a exigir código Python, ao contrário do LLaMA-Factory, mas em troca entrega o maior ganho de velocidade e a maior redução de VRAM das três opções, segundo os números publicados pelas próprias equipas. Para quem já sabe programar em Python e quer o máximo de controlo sobre cada hiperparâmetro sem abrir mão de desempenho, é normalmente a escolha mais equilibrada. Para equipas que preferem um YAML declarativo ou uma interface gráfica, o Axolotl ou o LLaMA-Factory podem encaixar melhor no fluxo de trabalho.
Vale ainda referir que as três ferramentas partilham a mesma base teórica, LoRA e QLoRA sobre modelos Hugging Face, e produzem adaptadores compatíveis entre si na maioria dos casos. Isto significa que não fica preso à escolha inicial: um adaptador treinado com Unsloth pode normalmente ser carregado e avaliado com as bibliotecas PEFT padrão, sem depender da ferramenta que o gerou.
Pré-requisitos: hardware, software e contas necessárias
Antes de instalar seja o que for, vale a pena confirmar se o seu hardware aguenta o processo. A boa notícia é que o QLoRA em 4 bits baixa bastante a fasquia de entrada. A documentação oficial do Unsloth indica um mínimo absoluto de 5 GB de VRAM para treinar um modelo de 7 mil milhões de parâmetros e 6 GB para um de 8 mil milhões, sempre em modo QLoRA de 4 bits. Na prática, esses números são o limiar teórico: com datasets maiores ou contexto mais longo, vai precisar de mais margem.
| Componente | Requisito mínimo | Recomendado |
|---|---|---|
| GPU (modelo 7B, QLoRA 4-bit) | 5 GB VRAM | 12 GB ou mais (RTX 3060/4070 ou superior) |
| GPU (modelo 8B, QLoRA 4-bit) | 6 GB VRAM | 16 GB ou mais |
| RAM do sistema | 16 GB | 32 GB |
| Python | 3.10 | 3.11 ou 3.12 |
| CUDA Toolkit | 12.1 | 12.4 ou superior |
| Espaço em disco | 20 GB livres | 60 GB (para vários checkpoints) |
| Alternativa sem GPU própria | Google Colab (tier gratuito, GPU T4) | Colab Pro ou GPU cloud alugada |
Se não tiver uma GPU Nvidia em casa, o caminho mais simples é abrir um notebook gratuito no Google Colab. A própria equipa do Unsloth mantém notebooks prontos a usar com a GPU T4 do tier gratuito, o que chega perfeitamente para os exemplos deste tutorial. Também vai precisar de uma conta gratuita na Hugging Face (para descarregar modelos e, opcionalmente, publicar o resultado) e, se quiser correr o modelo final localmente, do Ollama instalado na sua máquina.
Um detalhe que costuma passar despercebido é a diferença entre VRAM da GPU e RAM do sistema. Os números da tabela acima referem-se sempre à memória da placa gráfica, não à memória do computador. Mesmo com 32 GB de RAM na máquina, o treino falha se a GPU não tiver a VRAM mínima indicada, porque o modelo e os gradientes precisam de viver na memória dedicada à GPU durante o processo. Se a sua placa tiver menos VRAM do que os valores recomendados, ainda assim vale a pena tentar com um modelo menor, de 3B ou 4B de parâmetros, antes de desistir de treinar localmente.
LoRA vs QLoRA: qual escolher para o seu projeto
Os dois métodos partem da mesma ideia central, descrita no artigo original de Hu et al. sobre Low-Rank Adaptation (LoRA): em vez de atualizar todos os pesos do modelo, treina-se apenas um par de matrizes pequenas que se somam aos pesos originais. Isto reduz drasticamente o número de parâmetros treináveis, muitas vezes para menos de 1% do total do modelo. O QLoRA, apresentado no paper de Dettmers et al., junta essa técnica à quantização de 4 bits do modelo base, o que reduz ainda mais o consumo de memória à custa de um pequeno custo computacional extra por causa da desquantização durante o treino.
| Critério | LoRA | QLoRA |
|---|---|---|
| Precisão do modelo base | 16-bit (bfloat16/float16) | 4-bit quantizado |
| Uso de VRAM | Moderado | Baixo, ideal para GPUs de consumo |
| Velocidade de treino | Mais rápida | Ligeiramente mais lenta por passo |
| Qualidade final típica | Muito próxima do fine-tuning completo | Próxima do LoRA, com perda marginal |
| Melhor para | Quem já tem 16 GB+ de VRAM | Quem tem 6-12 GB de VRAM ou GPU gratuita |
Na prática, a recomendação para a maioria dos casos é simples. Se a sua GPU tem 16 GB ou mais de VRAM livre, use LoRA normal para ganhar velocidade. Se está limitado a uma placa de consumo ou ao Colab gratuito, o QLoRA em 4 bits é o caminho certo. Este tutorial usa QLoRA como exemplo principal, precisamente porque é o cenário mais acessível a quem está a começar.
Passo 1: Preparar o ambiente Python
Comece por criar um ambiente virtual isolado. Isto evita conflitos entre versões do PyTorch, do CUDA e das bibliotecas de quantização, que são a causa mais comum de erros de instalação neste tipo de projeto.
python3 -m venv unsloth-env
source unsloth-env/bin/activate
# Confirmar a versão do Python (recomendado 3.10 a 3.12)
python --version
# Confirmar se a GPU e o driver Nvidia estão visíveis
nvidia-smi
Se o comando nvidia-smi não devolver nada, confirme os drivers Nvidia antes de continuar. Não vale a pena avançar para a instalação do Unsloth sem esta confirmação, porque o erro só vai aparecer mais tarde e vai ser mais difícil de diagnosticar.
Passo 2: Instalar o Unsloth e as dependências
A instalação recomendada usa o gestor de pacotes pip com o pacote específico para a versão do CUDA instalada. O projeto disponibiliza um instalador que deteta automaticamente a configuração da máquina.
pip install --upgrade pip
# Instalação recomendada pela documentação oficial
pip install unsloth
# Dependências adicionais usadas neste tutorial
pip install trl peft accelerate bitsandbytes datasets huggingface_hub
Depois de instalar, vale a pena confirmar que tudo importa sem erros. Este pequeno teste poupa tempo mais à frente:
python -c "from unsloth import FastLanguageModel; print('Unsloth pronto')"
Se este comando falhar com um erro relacionado com bitsandbytes ou com símbolos CUDA em falta, salte já para a secção de resolução de problemas mais abaixo, porque esse é, de longe, o erro mais comum nesta fase.
Passo 3: Escolher e carregar o modelo base em 4-bit
A escolha do modelo base depende do objetivo. Para tarefas de texto geral em português, um modelo entre 7B e 9B de parâmetros costuma dar um bom equilíbrio entre qualidade e velocidade de treino numa GPU de consumo. O exemplo abaixo usa uma versão quantizada em 4 bits, já preparada pela equipa do Unsloth, o que acelera o download e poupa memória logo desde o carregamento.
from unsloth import FastLanguageModel
import torch
max_seq_length = 2048
dtype = None # None deixa o Unsloth escolher bfloat16 ou float16 conforme a GPU
load_in_4bit = True
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="unsloth/Qwen3.8-8B-bnb-4bit",
max_seq_length=max_seq_length,
dtype=dtype,
load_in_4bit=load_in_4bit,
)
O parâmetro max_seq_length merece atenção especial. Se o definir demasiado baixo, o treino vai truncar exemplos mais longos do dataset sem qualquer aviso visível, o que degrada a qualidade final sem que o erro apareça na consola. Confirme sempre o comprimento médio e máximo dos seus exemplos antes de fixar este valor.
Passo 4: Configurar os adaptadores LoRA
Com o modelo carregado, o passo seguinte é envolvê-lo com os adaptadores LoRA através da função get_peft_model. Os parâmetros mais importantes aqui são o r (o rank das matrizes de baixa dimensão) e o lora_alpha (o fator de escala aplicado a essas matrizes).
model = FastLanguageModel.get_peft_model(
model,
r=16,
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",
random_state=3407,
)
Um rank de 16 é um bom ponto de partida para a maioria dos casos. Ranks mais altos, como 64 ou 128, dão ao modelo mais capacidade para memorizar padrões específicos, mas aumentam o risco de overfitting em datasets pequenos e o tempo de treino. A opção use_gradient_checkpointing="unsloth" ativa a versão otimizada de gradient checkpointing do próprio projeto, que reduz ainda mais o pico de VRAM sem o abrandamento habitual desta técnica.
Passo 5: Preparar e formatar o dataset de treino
O fine-tuning só é tão bom quanto os dados que o alimentam. Para um dataset de instrução simples, o formato de chat costuma dar melhores resultados do que blocos de texto livre, porque ensina o modelo a respeitar a estrutura de pergunta e resposta. O exemplo abaixo usa um ficheiro JSONL local com pares de pergunta e resposta.
from datasets import load_dataset
dataset = load_dataset("json", data_files="dados_treino.jsonl", split="train")
def formatar_exemplo(exemplo):
texto = tokenizer.apply_chat_template(
[
{"role": "user", "content": exemplo["pergunta"]},
{"role": "assistant", "content": exemplo["resposta"]},
],
tokenize=False,
add_generation_prompt=False,
)
return {"text": texto}
dataset = dataset.map(formatar_exemplo)
print(dataset[0]["text"])
Um erro frequente nesta fase é esquecer o token de fim de sequência (EOS) no fim de cada exemplo, o que faz o modelo continuar a “falar” indefinidamente depois de treinado. A função apply_chat_template do tokenizer já trata disso automaticamente na maioria dos modelos recentes, mas vale sempre a pena imprimir alguns exemplos formatados antes de arrancar o treino, para confirmar visualmente que o resultado está correto.
Como preparar um dataset que realmente melhora o modelo
A parte mais subestimada de qualquer projeto de fine-tuning não é o código, é o dataset. Um adaptador LoRA treinado sobre dados inconsistentes produz um modelo confiante mas errado, o que é pior do que um modelo que admite não saber responder. Antes de escrever a primeira linha de treino, vale a pena passar por uma pequena checklist de qualidade.
- Consistência de formato. Todas as respostas devem seguir a mesma estrutura. Se metade dos exemplos responde em bullet points e a outra metade em texto corrido, o modelo aprende a alternar de forma imprevisível.
- Remoção de duplicados. Exemplos repetidos, mesmo que ligeiramente reformulados, inflacionam artificialmente o peso de certos padrões e aumentam o risco de overfitting.
- Separação entre treino e validação. Reserve entre 10% e 15% dos exemplos para validação, nunca vistos durante o treino, para conseguir medir se o modelo está a generalizar ou apenas a decorar.
- Cobertura de casos-limite. Inclua exemplos de perguntas ambíguas, pedidos fora de âmbito e situações em que a resposta correta é recusar ou pedir esclarecimento. Sem isto, o modelo tende a inventar respostas para tudo.
- Revisão humana da amostra final. Mesmo com poucos recursos, reveja manualmente uma amostra aleatória de 5% a 10% do dataset antes do treino. É a forma mais rápida de apanhar erros de formatação ou respostas incorretas que passaram despercebidos.
Para acompanhar a qualidade ao longo do treino, adicione um conjunto de validação ao SFTTrainer e monitorize a métrica de eval_loss a par da loss de treino. Se a loss de treino continuar a descer enquanto a de validação sobe, é o sinal clássico de overfitting, e a resposta normalmente passa por reduzir o número de épocas, baixar o rank LoRA ou aumentar a diversidade do dataset, em vez de simplesmente treinar durante mais tempo.
from datasets import load_dataset
dataset_completo = load_dataset("json", data_files="dados_treino.jsonl", split="train")
dataset_dividido = dataset_completo.train_test_split(test_size=0.12, seed=3407)
dataset_treino = dataset_dividido["train"]
dataset_validacao = dataset_dividido["test"]
print(f"Exemplos de treino: {len(dataset_treino)}")
print(f"Exemplos de validação: {len(dataset_validacao)}")
Este pequeno passo extra, dividir o dataset antes de configurar o SFTTrainer, é o que separa um projeto de fine-tuning bem avaliado de um projeto onde só se descobre que o modelo decorou os dados depois de o pôr em produção e reparar que falha com perguntas ligeiramente diferentes das do treino.
Passo 6: Configurar o SFTTrainer e os hiperparâmetros
O Unsloth integra-se diretamente com o SFTTrainer da biblioteca TRL da Hugging Face, o que significa que não precisa de escrever o loop de treino do zero.
from trl import SFTTrainer, SFTConfig
trainer = SFTTrainer(
model=model,
tokenizer=tokenizer,
train_dataset=dataset,
dataset_text_field="text",
max_seq_length=max_seq_length,
args=SFTConfig(
per_device_train_batch_size=2,
gradient_accumulation_steps=4,
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=1,
optim="adamw_8bit",
weight_decay=0.01,
lr_scheduler_type="linear",
seed=3407,
output_dir="checkpoints",
save_strategy="steps",
save_steps=50,
),
)
Repare no optim="adamw_8bit": este otimizador quantizado reduz ainda mais a memória ocupada pelos estados do otimizador, algo que faz diferença real em GPUs com menos de 12 GB. O gradient_accumulation_steps simula um batch maior sem exigir mais VRAM de uma só vez, o que é essencial quando o batch_size real tem de ficar baixo.
Passo 7: Treinar e monitorizar o processo
Com tudo configurado, arrancar o treino é uma única linha. O importante aqui é acompanhar a evolução da loss nos primeiros passos, porque é nesse período que a maioria dos problemas de configuração se torna visível.
trainer_stats = trainer.train()
print(trainer_stats)
Numa configuração típica com um dataset de algumas centenas de exemplos e uma GPU de gama média, cada época deve demorar entre alguns minutos e cerca de meia hora, dependendo do tamanho do modelo e do comprimento dos exemplos. Se a loss não descer de forma consistente ao longo dos primeiros 20 a 30 passos, pare o treino e reveja o dataset e o learning rate antes de continuar. Continuar um treino mal configurado só desperdiça tempo de GPU.
Passo 8: Testar o modelo treinado
Antes de exportar seja o que for, teste o modelo diretamente em memória. O Unsloth otimiza também a fase de inferência, ativada com FastLanguageModel.for_inference.
FastLanguageModel.for_inference(model)
mensagens = [{"role": "user", "content": "Explica o que é fine-tuning num parágrafo curto."}]
inputs = tokenizer.apply_chat_template(
mensagens, tokenize=True, add_generation_prompt=True, return_tensors="pt"
).to("cuda")
saida = model.generate(input_ids=inputs, max_new_tokens=200, temperature=0.7)
print(tokenizer.decode(saida[0], skip_special_tokens=True))
Um exemplo de saída esperada, depois de um fine-tuning bem-sucedido com dados sobre suporte técnico de uma aplicação fictícia, seria algo como: “Fine-tuning é o processo de ajustar um modelo já treinado com dados específicos da sua aplicação, para que ele responda no formato e tom que a sua equipa espera, sem precisar de reescrever prompts longos a cada pedido.” Se a resposta sair genérica, sem refletir o vocabulário do seu dataset, o modelo provavelmente precisa de mais épocas de treino ou de um rank LoRA mais alto.
Passo 9: Exportar para GGUF
Para correr o modelo fora do ambiente Python, em ferramentas como o Ollama ou o llama.cpp, é preciso converter para o formato GGUF. O Unsloth inclui uma função direta para isto, que trata da conversão e da quantização num único passo.
model.save_pretrained_gguf(
"modelo_afinado_gguf",
tokenizer,
quantization_method="q4_k_m",
)
A quantização q4_k_m é um ponto de equilíbrio comum entre tamanho de ficheiro e qualidade de resposta. Se o objetivo for correr num portátil com pouca RAM, métodos mais agressivos como q3_k_m reduzem ainda mais o tamanho, à custa de alguma qualidade. Este passo pode demorar vários minutos e precisa de espaço em disco temporário equivalente a duas a três vezes o tamanho do modelo original, por isso confirme o espaço livre antes de arrancar.
Passo 10: Fazer merge dos pesos e publicar no Hugging Face Hub
Se preferir manter o modelo em formato Hugging Face normal, em vez de GGUF, pode fazer o merge dos pesos LoRA diretamente no modelo base e publicar o resultado. Isto é útil para partilhar o modelo com a equipa ou para o usar depois com outras ferramentas de serving, como o vLLM.
from huggingface_hub import login
login(token="o_seu_token_aqui")
model.push_to_hub_merged(
"o-seu-utilizador/modelo-afinado-pt",
tokenizer,
save_method="merged_16bit",
)
Nunca escreva o token de acesso diretamente no código se o projeto for para um repositório partilhado. Use variáveis de ambiente ou o comando huggingface-cli login em vez disso, e confirme que o repositório está marcado como privado se os dados de treino tiverem qualquer informação sensível da sua empresa.
Passo 11: Correr o modelo no Ollama
Com o ficheiro GGUF pronto, criar um modelo no Ollama exige apenas um ficheiro Modelfile simples e dois comandos.
# Ficheiro Modelfile
cat > Modelfile << 'EOF'
FROM ./modelo_afinado_gguf/modelo.q4_k_m.gguf
PARAMETER temperature 0.7
PARAMETER num_ctx 2048
EOF
# Registar e correr o modelo
ollama create modelo-afinado-pt -f Modelfile
ollama run modelo-afinado-pt
A partir deste ponto, o modelo comporta-se como qualquer outro modelo do Ollama, disponível também através da API REST local na porta 11434, o que permite integrá-lo em scripts ou aplicações próprias sem depender de nenhuma API externa paga.
Passo 12: Guardar checkpoints e automatizar com um script completo
Para projetos reais, vale a pena juntar tudo num único script reprodutível, que pode ser corrido de novo com um dataset atualizado sempre que necessário. Este é o projeto funcional completo deste tutorial, do carregamento do modelo até à exportação para GGUF.
import torch
from unsloth import FastLanguageModel
from datasets import load_dataset
from trl import SFTTrainer, SFTConfig
# 1. Carregar modelo base em 4-bit
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="unsloth/Qwen3.8-8B-bnb-4bit",
max_seq_length=2048,
dtype=None,
load_in_4bit=True,
)
# 2. Adicionar adaptadores LoRA
model = FastLanguageModel.get_peft_model(
model, r=16, lora_alpha=16, lora_dropout=0, bias="none",
use_gradient_checkpointing="unsloth", random_state=3407,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"],
)
# 3. Carregar e formatar o dataset
dataset = load_dataset("json", data_files="dados_treino.jsonl", split="train")
dataset = dataset.map(lambda ex: {"text": tokenizer.apply_chat_template(
[{"role": "user", "content": ex["pergunta"]},
{"role": "assistant", "content": ex["resposta"]}],
tokenize=False)})
# 4. Configurar e correr o treino
trainer = SFTTrainer(
model=model, tokenizer=tokenizer, train_dataset=dataset,
dataset_text_field="text", max_seq_length=2048,
args=SFTConfig(
per_device_train_batch_size=2, gradient_accumulation_steps=4,
num_train_epochs=3, learning_rate=2e-4, optim="adamw_8bit",
logging_steps=1, output_dir="checkpoints",
save_strategy="steps", save_steps=50,
bf16=torch.cuda.is_bf16_supported(),
fp16=not torch.cuda.is_bf16_supported(),
),
)
trainer.train()
# 5. Exportar para GGUF, pronto para o Ollama
model.save_pretrained_gguf("modelo_afinado_gguf", tokenizer, quantization_method="q4_k_m")
print("Concluído. Ficheiro GGUF disponível em modelo_afinado_gguf/")
Se o treino for interrompido a meio, seja por falta de energia ou por um limite de sessão no Colab, o parâmetro save_steps=50 garante que existe sempre um checkpoint recente na pasta checkpoints. Para retomar a partir daí, basta passar resume_from_checkpoint=True ao chamar trainer.train() outra vez.
Erros comuns que custam horas de debugging
- Misturar fp16 e bf16 sem verificar o suporte da GPU. GPUs mais antigas, como algumas da série RTX 20, não suportam bfloat16, e forçar essa opção gera erros ou resultados corrompidos. Use sempre
torch.cuda.is_bf16_supported()para decidir automaticamente. - Dataset sem token EOS ou com formato de chat inconsistente. Isto faz o modelo continuar a gerar texto sem parar, mesmo depois de responder corretamente à pergunta original.
- Rank LoRA desproporcional ao tamanho do dataset. Um rank de 64 ou mais num dataset com menos de 200 exemplos tende a decorar as respostas em vez de generalizar, e a loss de validação sobe enquanto a de treino desce.
- Esquecer o gradient checkpointing em GPUs com pouca VRAM. Sem esta opção ativa, um modelo de 8B pode facilmente ultrapassar os 8 GB disponíveis numa placa de gama média.
- Fazer merge dos pesos LoRA antes de confirmar que o adaptador funciona bem sozinho. Depois do merge é muito mais difícil isolar se um problema vem do modelo base ou do adaptador treinado.
- Ignorar o learning rate schedule e deixar a taxa fixa e alta durante todo o treino. Isto costuma provocar instabilidade na loss nas últimas épocas, mesmo quando o início do treino parecia estável.
Resolução de problemas: 8 situações reais
1. CUDA out of memory logo no carregamento do modelo. Reduza o max_seq_length, confirme que load_in_4bit=True está ativo e feche outros processos que estejam a usar a GPU, incluindo o browser com aceleração por hardware.
2. ImportError relacionado com bitsandbytes. Normalmente indica uma versão de CUDA incompatível com o pacote pré-compilado. Confirme a versão com nvidia-smi e reinstale bitsandbytes depois de atualizar o driver, se necessário.
3. O tokenizer não tem pad token definido. Alguns modelos base não definem um pad_token por omissão. Defina-o manualmente com tokenizer.pad_token = tokenizer.eos_token antes de iniciar o treino.
4. A loss aparece como NaN a partir de um certo passo. É quase sempre sinal de learning rate demasiado alto ou de gradientes a explodir. Baixe a taxa de aprendizagem e ative max_grad_norm no SFTConfig para cortar gradientes extremos.
5. O modelo treinado ignora o formato pedido e responde como antes do fine-tuning. Verifique se o dataset foi mesmo usado (imprima alguns exemplos formatados) e aumente o número de épocas, já que dois ou três epochs raramente bastam para mudanças de comportamento mais complexas.
6. O treino é muito mais lento do que o esperado no Colab gratuito. A GPU T4 é partilhada e tem menos throughput do que placas mais recentes. Reduza o batch size, aumente o gradient_accumulation_steps e evite sessões muito longas, que podem ser interrompidas pelo próprio Colab.
7. A exportação para GGUF falha com erro de espaço em disco. O processo de conversão precisa de espaço temporário adicional. Liberte espaço ou exporte diretamente para um disco externo com mais capacidade.
8. O modelo corre no Ollama mas devolve texto sem sentido. Confirme que a quantização usada no save_pretrained_gguf corresponde à referenciada no Modelfile e que o num_ctx definido não é maior do que o max_seq_length usado no treino.
Dicas avançadas para ir além do básico
Depois de dominar o fluxo básico, há várias direções para explorar. Para quem trabalha com modelos MoE, como variantes do GLM ou do DeepSeek, os ganhos de velocidade do Unsloth são particularmente relevantes, com a documentação a apontar até 12x mais rapidez nesse tipo de arquitetura. Vale a pena testar também o suporte a contexto mais longo, que permite treinar com documentos inteiros em vez de fragmentos curtos, algo útil para tarefas de resumo ou de resposta a perguntas sobre documentos internos.
Outra direção interessante é combinar o fine-tuning supervisionado com técnicas de alinhamento por preferências, treinando o modelo não só para imitar respostas corretas, mas para preferir umas respostas a outras. Isto exige um dataset diferente, com pares de resposta boa e má para a mesma pergunta, e normalmente só compensa depois de já ter um modelo base afinado e estável através do processo descrito neste tutorial.
Por fim, se o objetivo for produção e não apenas um projeto pessoal, vale a pena automatizar todo o pipeline com um script de avaliação que corre um conjunto fixo de perguntas de teste depois de cada treino, e compara os resultados com a versão anterior antes de substituir o modelo em uso.
Também vale a pena experimentar o treino com múltiplos adaptadores LoRA guardados em paralelo, uma técnica útil quando precisa de várias variações do mesmo modelo base para diferentes clientes ou casos de uso. Como o adaptador ocupa apenas alguns megabytes, comparado com vários gigabytes do modelo completo, é perfeitamente viável manter dezenas de adaptadores diferentes e trocar entre eles em tempo de inferência, carregando o mesmo modelo base uma única vez na memória e aplicando o adaptador certo consoante o pedido recebido.
Para equipas que já correm vários modelos afinados em produção, ferramentas de serving como o vLLM suportam o carregamento dinâmico de múltiplos adaptadores LoRA sobre o mesmo modelo base, o que evita duplicar a VRAM ocupada por cada versão treinada e simplifica bastante a operação do lado da infraestrutura.
Quanto custa isto: GPU cloud vs hardware próprio
Para quem não tem uma GPU dedicada, alugar capacidade na cloud costuma ser o caminho mais rápido para começar, sem o investimento inicial em hardware. A tabela seguinte resume as opções mais comuns para este tipo de treino.
| Opção | VRAM | Bom para | Custo típico |
|---|---|---|---|
| Google Colab (tier gratuito) | GPU T4, 16 GB | Testes e datasets pequenos | Gratuito, com limites de sessão |
| Google Colab Pro | GPU melhor, mais RAM | Sessões mais longas e estáveis | Subscrição mensal paga |
| GPU cloud alugada (por hora) | Variável, 24 GB a 80 GB | Modelos maiores, treinos longos | Pago por hora de utilização |
| GPU de consumo própria | 12 GB a 24 GB | Uso recorrente, vários projetos | Investimento único em hardware |
Note que os valores exatos de custo por hora variam consoante o fornecedor e a região, e mudam com frequência, por isso a melhor prática é confirmar o preço atualizado diretamente na página do fornecedor antes de reservar capacidade, em vez de confiar em números fixos que ficam desatualizados rapidamente.
Um critério prático para decidir entre alugar e comprar é a frequência de uso. Quem vai treinar um modelo uma vez, para um projeto pontual, normalmente sai a ganhar com o Colab gratuito ou com uma instância alugada por algumas horas. Quem planeia treinar modelos com regularidade, seja para ajustar o mesmo produto todas as semanas ou para testar várias configurações em paralelo, tende a recuperar o investimento numa GPU própria em poucos meses, além de ganhar a vantagem de não depender da disponibilidade de capacidade na cloud em horas de pico.
Perguntas frequentes
O Unsloth é gratuito?
Sim, a biblioteca principal é open source e gratuita. A equipa também vende serviços adicionais, como treino gerido na cloud, mas o fluxo descrito neste tutorial não exige nenhum pagamento à Unsloth.
Preciso de saber Python avançado para seguir este tutorial?
Não. Conhecimento básico de Python, como usar funções e ler mensagens de erro, chega para seguir todos os passos. As partes mais complexas já vêm encapsuladas nas funções do Unsloth e do TRL.
Quantos exemplos preciso no dataset para obter bons resultados?
Não existe um número mágico, mas datasets com pelo menos algumas centenas de exemplos de boa qualidade costumam dar resultados mais consistentes do que datasets maiores mas mal revistos. Qualidade e consistência do formato pesam mais do que o volume puro.
Posso usar o Unsloth sem GPU, só com CPU?
Tecnicamente é possível carregar modelos pequenos em CPU, mas o treino torna-se impraticavelmente lento. Para fine-tuning real, uma GPU, mesmo que seja a T4 gratuita do Colab, é praticamente obrigatória.
Qual a diferença entre este processo e usar diretamente o Hugging Face Transformers com PEFT?
O resultado final, um adaptador LoRA compatível, é semelhante. A diferença está na velocidade e no consumo de memória durante o treino, graças aos kernels otimizados do Unsloth, o que permite treinar modelos maiores em GPUs mais modestas ou terminar o treino mais depressa no mesmo hardware.
O modelo treinado localmente pode ser usado comercialmente?
Depende da licença do modelo base escolhido, não do Unsloth em si. Antes de usar o resultado em produção, confirme sempre a licença específica do modelo que descarregou, porque nem todos os modelos open weight permitem uso comercial sem restrições.
Vale a pena fazer fine-tuning em vez de usar RAG?
São técnicas complementares, não substitutas. O RAG é melhor para dar ao modelo acesso a informação atualizada ou específica de documentos. O fine-tuning é melhor para mudar o comportamento, o tom ou o formato de resposta do modelo. Muitos projetos reais combinam os dois.
Related Coverage
- Fine-Tuning de LLMs com Hugging Face: 10 Passos [2026]
- Ollama: 178K GitHub Stars, LLMs Locais em 12 Passos [2026]
- LM Studio: Rodar IA Local em 12 Passos, 45 Min [2026]
- vLLM + Docker: Rodar DeepSeek V4 Flash em 13 Passos [2026]
- API Mistral AI: Chatbot RAG em 12 Passos, 60 Min [2026]
Para mais artigos sobre modelos, ferramentas e infraestrutura de inteligência artificial, veja a categoria Inteligência Artificial do shattered.io.




