Do Dataset ao Ollama: Fine-Tuning de LLMs com Unsloth na Sua GPU em 2026
Você sabia que a empresa média gastou US$ 1,2 milhão em chamadas de API de IA em 2025? O número é de uma pesquisa da a16z de janeiro de 2026 — e representa um aumento de 108% em relação ao ano anterior. (Fonte: kargin-utkin.com)
É por isso que times de ML do mundo inteiro estão migrando para fine-tuning local. Em vez de pagar por cada chamada de API, eles compram uma GPU e ajustam o modelo dentro de casa. O custo fixo substitui o variável.
A ferramenta que está liderando essa mudança chama-se Unsloth. E ela resolve o principal problema do fine-tuning local: a falta de VRAM.
Neste tutorial, você vai aprender a fazer fine-tuning de LLMs como Llama 4, Qwen 3.6 e Gemma 4 na sua própria GPU — do download do modelo base até o deploy no Ollama. Tudo com hardware de consumo (8 a 24 GB de VRAM), usando QLoRA e a biblioteca Unsloth. O resultado: treinamento 2x mais rápido e 70% menos uso de VRAM em relação ao baseline do HuggingFace TRL. (Fonte: dibi8.com)
O que é Unsloth e por que ele virou padrão
Unsloth começou como uma biblioteca experimental de kernels otimizados para fine-tuning. Em maio de 2026, são 64.900+ estrelas no GitHub e 1,8 milhão de downloads mensais no PyPI. (Fonte: github.com/unslothai/unsloth)
O segredo está na engenharia de baixo nível: a biblioteca reescreve os kernels de atenção e feed-forward em CUDA manual, eliminando desperdícios de memória que frameworks como o HuggingFace TRL tratam como "custo aceitável". Resultado prático: um modelo de 7B que normalmente precisaria de 24 GB de VRAM para fine-tuning roda com folga em 10 GB com QLoRA.
"Unsloth acelera o treinamento em 2x e reduz o uso de VRAM em até 70% comparado ao baseline HuggingFace TRL, permitindo fine-tuning de modelos de 7B em GPUs com apenas 8-10GB de VRAM via QLoRA." — Documentação oficial do Unsloth
Em 2026, a biblioteca deu um salto: juntou-se ao ecossistema PyTorch, lançou a versão v0.1.41-beta com suporte a 500+ modelos (incluindo Llama 4, Qwen 3.6, Gemma 4, DeepSeek e gpt-oss), e introduziu treinamento MoE 12x mais rápido. (Fonte: unsloth.ai)
Antes de começar: o que você precisa de hardware
A beleza do Unsloth é que ele roda em GPUs que você provavelmente já tem. Aqui vai uma tabela prática:
| Modelo | VRAM Mínima (QLoRA 4-bit) | GPU Recomendada | Tempo Estimado (500 exemplos) |
|---|---|---|---|
| Llama 3.2 1B / Qwen 2.5 0.5B | 4 GB | GTX 1660 / RTX 3050 | ~3 min |
| Llama 3.2 3B / Qwen 2.5 3B | 6 GB | RTX 3060 12GB | ~5 min |
| Llama 3 8B / Qwen 2.5 7B | 10 GB | RTX 3080 / RTX 4060 Ti | ~12 min |
| Gemma 2 9B / Llama 3 13B | 14 GB | RTX 3090 24GB | ~20 min |
| Qwen 3 32B / DeepSeek Coder 33B | 20 GB | RTX 4090 24GB | ~35 min |
| Llama 3 70B / Qwen 3 72B | 24 GB+ | RTX 4090 + offloading | ~60 min |
A linha mais usada hoje é a do meio: Llama 3 8B com 10 GB de VRAM. É o ponto ideal entre qualidade do modelo e acessibilidade de hardware. Uma RTX 3080 (10GB) usada custa por volta de R$ 2.500 no Brasil (maio/2026) — menos que dois meses de API da OpenAI para um time pequeno.
Dependências de software
Antes de qualquer coisa, você precisa de:
- Python 3.10+ (recomendo 3.11)
- CUDA 12.1+ e cuDNN 8.9
- PyTorch 2.4+ com suporte CUDA
- Git LFS (para baixar modelos grandes)
Se você está no Windows, use WSL2 com Ubuntu 22.04 — a experiência é muito mais estável para fine-tuning.
Passo 1: Montando o ambiente
Abra seu terminal e crie um ambiente virtual:
python -m venv unsloth-env
source unsloth-env/bin/activate
Instale o PyTorch com CUDA:
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124
E então o Unsloth:
pip install unsloth
Esse comando instala o Unsloth e todas as dependências — inclusive os kernels CUDA compilados. A instalação leva de 2 a 5 minutos. Se preferir a versão mais recente (que pode incluir kernels experimentais para MoE):
pip install git+https://github.com/unslothai/unsloth.git
Pronto. Ambiente montado.
Passo 2: Escolhendo o modelo base
O Unsloth suporta 500+ modelos, mas nem todos valem o esforço. Minhas recomendações em maio de 2026:
- Llama 3.2 3B — leve, rápido, ideal para prototipação. Versão mais recente da Meta.
- Qwen 2.5 7B — melhor custo-benefício em português. A Alibaba investiu pesado em dados em PT.
- Gemma 4 9B — o modelo mais novo do Google DeepMind. Forte em raciocínio lógico.
- Llama 4 8B — suporte nativo a MoE, mas exige mais VRAM.
Para este tutorial, vamos usar o Llama 3.2 3B. Ele roda em GPUs de 6 GB, o fine-tuning termina em minutos, e a qualidade é boa o suficiente para testar o pipeline completo.
No código:
from unsloth import FastLanguageModel
import torch
model_name = "unsloth/Llama-3.2-3B-bnb-4bit"
model, tokenizer = FastLanguageModel.from_pretrained( model_name=model_name, max_seq_length=2048, dtype=None, load_in_4bit=True, )
O parâmetro load_in_4bit=True carrega o modelo quantizado em 4 bits — é o que reduz a VRAM de ~16 GB para ~6 GB. Sem ele, você precisaria de uma GPU de servidor.
Passo 3: Preparando o dataset
Fine-tuning sem dataset bom é como cozinhar com ingredientes vencidos. O resultado pode até sair, mas ninguém vai querer comer.
O formato esperado pelo Unsloth é simples: uma lista de dicionários com instruction, input e output. Ou, se você preferir, só conversations no formato ChatML.
Vou usar um exemplo concreto: vamos afinar o modelo para responder perguntas técnicas sobre Python no estilo do NeuralPulse — didático, direto e com exemplos.
dataset = [
{
"instruction": "Explique o que é uma closure em Python.",
"input": "",
"output": (
"Closure é uma função que 'lembra' do escopo onde foi criada, "
"mesmo depois que esse escopo já terminou. Na prática: você define "
"uma função dentro de outra, e a interna accessa variáveis da externa. "
"Exemplo:\n\ndef multiplicador(n):\n def interna(x):\n "
"return x * n\n return interna\n\ndobro = multiplicador(2)\n"
"print(dobro(5)) # 10"
),
},
{
"instruction": "Qual a diferença entre list e tuple?",
"input": "",
"output": (
"List é mutável (você pode adicionar, remover, alterar itens). "
"Tuple é imutável (uma vez criada, não muda). Por isso tuple é mais "
"rápida e segura para dados que não devem ser alterados. Use list "
"para listas dinâmicas, tuple para constantes e chaves de dicionário."
),
},
# Adicione mais 100-500 exemplos aqui
]
Com 100 a 500 exemplos bem escritos você já vê diferença. Com 1.000+, o modelo muda de comportamento de forma significativa.
Agora, carregue os dados no formato esperado pelo Unsloth:
from datasets import Dataset
Converte para formato Alpaca
def format_alpaca(example): prompt = ( "Abaixo está uma instrução que descreve uma tarefa. " "Escreva uma resposta que complete o que foi pedido.\n\n" f"### Instrução:\n{example['instruction']}\n\n" f"### Resposta:\n{example['output']}" ) return {"text": prompt}
dataset_hf = Dataset.from_list(dataset) dataset_hf = dataset_hf.map(format_alpaca)
Dica importante: se você tem dados em JSON ou CSV, o HuggingFace datasets aceita load_dataset("json", data_files="caminho.json") direto. O Unsloth não impõe formato rígido — ele só precisa de um campo text com o prompt completo.
Passo 4: Configurando o QLoRA
Aqui é onde a mágica acontece. O QLoRA combina dois truques:
- LoRA (Low-Rank Adaptation): em vez de treinar todos os parâmetros da rede (o que seria inviável na sua GPU), treina apenas matrizes pequenas acopladas às camadas de atenção. É como colocar "adesivos" no modelo original.
- 4-bit NormalFloat: quantiza os pesos do modelo original para 4 bits, reduzindo drasticamente o consumo de VRAM.
O Unsloth simplifica a configuração:
model = FastLanguageModel.get_peft_model(
model,
r=16, # LoRA rank — quanto maior, mais capacidade de adaptação
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=42,
max_seq_length=2048,
use_rslora=False,
)
Parâmetros para prestar atenção:
| Parâmetro | Valor Recomendado | Efeito |
|---|---|---|
r (rank) | 8-32 | Rank 16 é o padrão ouro. Mais que 32 superajusta. |
lora_alpha | 16-32 | Escala das adaptações. Mantenha igual ao rank. |
lora_dropout | 0 | Dropout atrapalha fine-tuning com datasets pequenos. Só use se tiver 10k+ exemplos. |
max_seq_length | 2048-4096 | Contexto máximo. 2048 é suficiente para 90% dos casos. |
Passo 5: Rodando o treinamento
Com o modelo configurado e o dataset pronto, é hora de treinar:
from trl import SFTTrainer
from transformers import TrainingArguments
trainer = SFTTrainer( model=model, tokenizer=tokenizer, train_dataset=dataset_hf, dataset_text_field="text", max_seq_length=2048, dataset_num_proc=2, args=TrainingArguments( per_device_train_batch_size=2, gradient_accumulation_steps=4, warmup_steps=5, 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=42, output_dir="outputs", report_to="none", ), )
trainer.train()
Com learning rate 2e-4, LoRA rank 16 e 500 exemplos, o treinamento no Llama 3.2 3B leva entre 5 e 10 minutos em uma RTX 4090. Em uma RTX 3060 (12 GB), cerca de 15 minutos. (Fonte: vucense.com)
Você vai ver o loss descendo a cada step. Um loss final entre 0.4 e 0.8 costuma indicar um bom fine-tuning. Abaixo de 0.3, pode ser sinal de overfitting — aí vale reduzir o número de épocas ou aumentar o dataset.
Passo 6: Exportando para GGUF
Com o modelo treinado, você quer usá-lo fora do Python. O formato GGUF (criado pelo llama.cpp) é o padrão para inferência local eficiente — e o Unsloth exporta direto para ele:
model.save_pretrained_gguf(
"modelo-afinado-gguf",
tokenizer,
quantization_method="q4_k_m",
)
Esse comando salva o modelo em formato GGUF com quantização Q4_K_M (um bom equilíbrio entre qualidade e tamanho). O arquivo gerado tem cerca de 2-3 GB para um modelo 3B, contra 6 GB do formato original.
Se você quiser testar antes de exportar, o próprio Unsloth já permite inferência direta:
FastLanguageModel.for_inference(model)
inputs = tokenizer(
["""Abaixo está uma instrução que descreve uma tarefa.
Escreva uma resposta que complete o que foi pedido.
Instrução:
Explique o que é uma closure em Python.
Resposta:"""],
return_tensors="pt",
).to("cuda")
outputs = model.generate(**inputs, max_new_tokens=256, temperature=0.7) print(tokenizer.decode(outputs[0]))
Passo 7: Deploy no Ollama
O Ollama é a ferramenta mais simples para rodar LLMs localmente. Com o modelo em GGUF, o deploy é questão de minutos.
Primeiro, crie um arquivo Modelfile:
FROM ./modelo-afinado-gguf/consolidated-01.gguf
TEMPLATE """{{ .Prompt }}"""
PARAMETER temperature 0.7 PARAMETER top_p 0.9 PARAMETER num_ctx 2048
Depois, crie o modelo no Ollama e teste:
ollama create neuralpulse-python-tutor --f Modelfile
ollama run neuralpulse-python-tutor
Pronto. Você digitou ollama run e está conversando com seu modelo afinado. Sem internet, sem API key, sem custo por chamada.
Custo: local vs nuvem — quando vale a pena?
A pergunta que todo mundo faz: "Compensa financeiramente?"
A pesquisa da Presenc.ai (2026) mapeou o ponto de equilíbrio. (Fonte: presenc.ai)
| Cenário | Investimento Inicial | Custo Mensal | Chamadas/mês | Custo por 1M tokens |
|---|---|---|---|---|
| Local (RTX 3090 + CPU 16GB RAM) | ~US$ 1.200 (uma vez) | ~US$ 83 (energia + manutenção) | Ilimitado | ~US$ 0,05 |
| OpenAI GPT-4o mini (API) | US$ 0 | Variável | 10.000 | US$ 0,15 |
| OpenAI GPT-4o (API) | US$ 0 | Variável | 10.000 | US$ 2,50 |
| Anthropic Claude 3.5 Sonnet (API) | US$ 0 | Variável | 10.000 | US$ 3,00 |
| Groq Llama 3 70B (API) | US$ 0 | Variável | 10.000 | US$ 0,59 |
O ponto de equilíbrio para um modelo 7B com utilização moderada (30%) fica entre 4 e 9 meses. Acima de 10 mil chamadas por mês, o custo local é drasticamente menor.
Para times que fazem fine-tuning iterativo — testam, ajustam, repetem — a conta fecha ainda mais rápido. Cada experimento que você rodaria na nuvem custa algo. Na sua GPU, custa só a eletricidade.
Conclusão
Fine-tuning local de LLMs deixou de ser coisa de laboratório com 8 GPUs A100. Com o Unsloth + QLoRA, você pega um modelo de 7 bilhões de parâmetros, adapta com seus dados e coloca em produção — tudo em uma GPU de consumo, em menos de 15 minutos.
O ecossistema está maduro: Unsloth resolveu o gargalo de VRAM e velocidade, o GGUF padronizou a distribuição, e o Ollama simplificou o deploy. O que falta é só você trazer os dados.
Se quiser ir além, confira o tutorial anterior aqui do NeuralPulse sobre RAG do zero com Python, LangChain e ChromaDB. A combinação de fine-tuning + RAG é o que as empresas mais avançadas estão usando hoje: o fine-tuning adapta o tom e o conhecimento, o RAG traz dados atualizados sem precisar retreinar.
A próxima fronteira? Fine-tuning de modelos MoE (como o Llama 4 e Qwen 3.6) que o Unsloth já suporta com aceleração de 12x. Mas isso é assunto para o próximo post.
Sua vez: pega a tabela de hardware ali em cima, vê qual GPU você tem disponível, e testa o pipeline. O código deste tutorial está todo aqui — é só copiar, colar e adaptar seu dataset.
Se funcionar, conta pra gente nos comentários. Se quebrar, conta também — a gente ajuda a debuggar.
Artigos Relacionados
NeuralPulse
Blog profissional sobre Inteligencia Artificial. Exploramos tendencias, ferramentas, tutoriais e analises profundas sobre como a IA esta transformando negocios, tecnologia e o dia a dia.
Receba as novidades sobre IA
Junte-se a milhares de leitores que acompanham as ultimas tendencias em inteligencia artificial.
Artigos Relacionados
Function Calling na Prática: Tutorial Python para Chatbots com LLMs que Executam Ações em 2026
Aprenda a implementar function calling em Python com OpenAI, Anthropic Claude e Google Gemini. Tutorial completo com código para integrar APIs, bancos de dad...
Árvore de Decisão vs Random Forest vs XGBoost: Tutorial Prático de Machine Learning em 2026 (com Código Python e Dados Reais)
Comparação prática entre Árvore de Decisão, Random Forest e XGBoost para classificação em 2026, com implementação passo a passo em Python e análise de perfor...
RAG Avançado em 2026: Chunking Semântico, Reranking e Consultas Híbridas para Chatbots que Realmente Funcionam
Guia prático e detalhado com código Python para implementar RAG avançado em 2026: chunking semântico, reranking com cross-encoder e consultas híbridas. Reduz...
Comentarios
Powered by Disqus
Para ativar os comentarios, configure seu shortname do Disqus no componente.
<div id="disqus_thread"></div>