Programa
Qwen3.6-35B-A3B é um modelo mixture-of-experts leve, criado para tarefas intensivas de code generation, raciocínio e contexto longo. Ele tem 35B de parâmetros totais com 3B ativos por token, o que o torna mais eficiente na execução sem perder desempenho. Também oferece uma janela de contexto de 262K tokens, sendo útil para bases de código maiores, documentos longos e fluxos de trabalho em múltiplas etapas.
O modelo se sai especialmente bem em benchmarks de código e de agentes, com resultados fortes no SWE-bench, Terminal-Bench e Claw-Eval. Ele também se mantém competitivo em benchmarks amplos de raciocínio e conhecimento, como GPQA, AIME 2026, MMLU-Pro e C-Eval, o que o torna uma base sólida para experimentos de fine-tuning que exigem tanto desempenho prático em tarefas quanto capacidade geral de raciocínio.
Neste guia, vamos configurar um ambiente RunPod H100 NVL, preparar o projeto, carregar e limpar um dataset de perguntas e respostas médicas, executar o Qwen3.6 em quantização de 4 bits, formatar prompts, criar utilitários de avaliação, testar o modelo base antes do fine-tuning, treinar e salvar o adapter e, por fim, comparar o modelo novamente após o fine-tuning.
Aviso: este tutorial demonstra um processo técnico de fine-tuning apenas para fins educacionais. O modelo resultante não é destinado ao uso médico ou clínico e não deve ser utilizado para diagnóstico, tomada de decisão ou cuidados com pacientes.
Etapa 1: configure o ambiente de treinamento
Na primeira parte, vamos iniciar uma instância H100 NVL no RunPod, instalar as bibliotecas necessárias, conectar ao Hugging Face e definir a configuração principal do projeto.
Alugue uma máquina com GPU H100 NVL
Comece acessando o RunPod e selecionando uma máquina com GPU H100 NVL. Essa GPU vem com cerca de 94 GB de VRAM e 94 GB de RAM do sistema, suficientes para este fluxo de trabalho de fine-tuning do Qwen3.6.
Escolha o template mais recente do PyTorch e edite a configuração do pod antes do deploy. Defina o tamanho do disco do container para 100 GB e o do volume para 200 GB. Isso garante espaço suficiente para baixar o modelo, armazenar dependências em cache e salvar localmente o adapter com fine-tuning.

Também é recomendado adicionar uma variável de ambiente HF_TOKEN nessa etapa. Isso permitirá que você faça login no Hugging Face depois, facilite o acesso ao download do modelo e torne mais simples enviar o modelo ajustado ao Hub após o treinamento.
Antes de iniciar a instância, revise o resumo do pod para verificar o custo estimado. Quando tudo estiver correto, faça o deploy do pod.

Instale as bibliotecas necessárias
Quando o pod estiver pronto, abra o link do Jupyter Notebook no painel do RunPod para iniciar o JupyterLab. Crie um novo notebook Python e instale as bibliotecas necessárias para o fine-tuning quantizado, carregamento do dataset e supervised fine-tuning com TRL.
pip install -q -U transformers accelerate peft trl bitsandbytes datasets sentencepiece
Faça login no Hugging Face
Em seguida, faça login no Hugging Face usando a variável de ambiente HF_TOKEN que você adicionou ao criar o pod. Isso evita colocar seu token diretamente no notebook e deixa o fluxo mais organizado.
import os
from huggingface_hub import login
hf_token = os.getenv("HF_TOKEN")
login(token=hf_token)
Importe as bibliotecas e defina a configuração
Agora importe as bibliotecas necessárias e defina os valores de configuração que usaremos ao longo do tutorial. Isso inclui o ID do modelo, o nome do dataset, tamanhos de amostra, diretório de saída e seed aleatória.
import os
import random
import re
import torch
from datasets import load_dataset
from peft import LoraConfig, prepare_model_for_kbit_training
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
BitsAndBytesConfig,
set_seed,
)
from trl import SFTConfig, SFTTrainer
MODEL_ID = "Qwen/Qwen3.6-35B-A3B"
DATASET_ID = "keivalya/MedQuad-MedicalQnADataset"
SAMPLE_SIZE = 240
EVAL_SIZE = 24
COMPARISON_SAMPLE_COUNT = 3
MAX_SEQ_LENGTH = 768
OUTPUT_DIR = "qwen36-medquad-quick"
SEED = 42
set_seed(SEED)
random.seed(SEED)
def supports_bf16() -> bool:
return torch.cuda.is_available() and torch.cuda.get_device_capability(0)[0] >= 8
print(f"PyTorch: {torch.__version__}")
print(f"CUDA available: {torch.cuda.is_available()}")
if torch.cuda.is_available():
print(f"GPU: {torch.cuda.get_device_name(0)}")
print(
f"GPU memory (GB): {torch.cuda.get_device_properties(0).total_memory / 1024**3:.1f}"
)
Ao executar esta célula, você deve ver a confirmação de que o CUDA está disponível e que o notebook está conectado a uma GPU NVIDIA H100 NVL.
PyTorch: 2.8.0+cu128
CUDA available: True
GPU: NVIDIA H100 NVL
GPU memory (GB): 93.1Engenheiro associado de IA para cientistas de dados
Etapa 2: carregue e prepare o dataset
Nesta parte, vamos carregar o dataset médico de perguntas e respostas MedQuad, limpar os campos de texto, filtrar exemplos de menor qualidade e criar divisões pequenas de treino e avaliação para um fine-tuning rápido.
Carregue o dataset MedQuad
Começamos carregando a divisão de treino do MedQuad do Hugging Face. Após o carregamento, inspecionamos a estrutura do dataset, os nomes das colunas e o primeiro exemplo para entender o tipo de pares de perguntas e respostas médicas com os quais vamos trabalhar.
raw_dataset = load_dataset(DATASET_ID, split="train")
print(raw_dataset)
print("First example:", raw_dataset[0])
Isso mostra que o MedQuad contém 16.407 exemplos de perguntas e respostas médicas distribuídos em três campos: qtype, Question e Answer.
Dataset({
features: ['qtype', 'Question', 'Answer'],
num_rows: 16407
})
First example: {'qtype': 'susceptibility', 'Question': 'Who is at risk for Lymphocytic Choriomeningitis (LCM)? ?', 'Answer': 'LCMV infections can occur after exposure to fresh urine, droppings, saliva, or nesting materials from infected rodents. Transmission may also occur when these materials are directly introduced into broken skin, the nose, the eyes, or the mouth, or presumably, via the bite of an infected rodent. Person-to-person transmission has not been reported, with the exception of vertical transmission from infected mother to fetus, and rarely, through organ transplantation.'}
Limpe os campos de texto
Em seguida, definimos uma pequena função de limpeza de texto e uma regra de filtragem para remover amostras de baixa qualidade. A etapa de limpeza normaliza espaços em branco extras, enquanto a filtragem remove exemplos com perguntas muito curtas, respostas muito curtas, respostas longas demais ou modelos de resposta genéricos que são pouco úteis para o treinamento.
def clean_text(text):
text = re.sub(r"\s+", " ", str(text)).strip()
return text
BAD_ANSWER_PREFIXES = (
"These resources address",
"These resources from MedlinePlus",
"For more information, go to",
"For more information go to",
)
def keep_example(example):
question = clean_text(example["Question"])
answer = clean_text(example["Answer"])
if len(question) < 12 or len(answer) < 40:
return False
if len(answer) > 900:
return False
if any(answer.startswith(prefix) for prefix in BAD_ANSWER_PREFIXES):
return False
return True
filtered_dataset = raw_dataset.filter(keep_example)
Crie as divisões de treino e avaliação
Depois da filtragem, embaralhamos o dataset, selecionamos um subconjunto menor para este tutorial rápido e dividimos em conjuntos de treino e avaliação. Assim, a execução fica leve, mas ainda permite comparar o modelo antes e depois do fine-tuning.
subset = filtered_dataset.shuffle(seed=SEED).select(range(SAMPLE_SIZE))
split_dataset = subset.train_test_split(test_size=EVAL_SIZE, seed=SEED)
train_dataset = split_dataset["train"]
eval_dataset = split_dataset["test"]
print(f"Filtered dataset size: {len(filtered_dataset)}")
print(f"Train size: {len(train_dataset)}")
print(f"Eval size: {len(eval_dataset)}")
Após a filtragem, restam 7.355 exemplos de melhor qualidade, dos quais amostramos 216 exemplos de treino e 24 de avaliação para este fine-tuning rápido.
Filtered dataset size: 7355
Train size: 216
Eval size: 24
Etapa 3: carregue o Qwen3.6 com quantização de 4 bits
Nesta etapa, vamos configurar a quantização de 4 bits com BitsAndBytes, carregar o tokenizer do Qwen3.6 e então carregar o modelo base para que ele rode com mais eficiência na GPU H100 NVL.
Configure o BitsAndBytes para carregamento em 4 bits
O Qwen3.6 ainda é um modelo grande; carregá-lo em precisão total consumiria muito mais memória. Para tornar o fine-tuning mais eficiente, carregamos o modelo em 4 bits com o BitsAndBytes. Isso reduz o uso de memória, mantendo o modelo prático para fine-tuning com QLoRA.
Aqui usamos nf4 quantization, ativamos double quantization e definimos o dtype de computação como bfloat16 quando a GPU oferecer suporte.
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
bnb_4bit_compute_dtype=torch.bfloat16 if supports_bf16() else torch.float16,
)
Carregue o tokenizer
Em seguida, carregamos o tokenizer do Qwen3.6. Também verificamos se já existe um token de padding definido. Se estiver ausente, reutilizamos o token de fim de sequência como padding para que o batching funcione corretamente no treinamento e na geração.
tokenizer = AutoTokenizer.from_pretrained(
MODEL_ID,
trust_remote_code=True,
use_fast=False,
)
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
Carregue o modelo base
Agora carregamos o modelo base Qwen3.6 com as configurações de quantização de 4 bits definidas anteriormente. Usamos device_map="auto" para que o modelo seja alocado automaticamente na GPU disponível e novamente usamos bfloat16 quando suportado para computação mais eficiente.
Após carregar o modelo, definimos o ID do token de padding e desativamos o uso de cache. Isso é importante porque o cache é útil em inferência, mas durante o fine-tuning pode atrapalhar o treinamento e aumentar o consumo de memória.
model = AutoModelForCausalLM.from_pretrained(
MODEL_ID,
quantization_config=bnb_config,
device_map="auto",
dtype=torch.bfloat16 if supports_bf16() else torch.float16,
trust_remote_code=True,
)
model.config.pad_token_id = tokenizer.pad_token_id
model.config.use_cache = False
Etapa 4: formate os prompts e crie o helper de avaliação
Nesta etapa, vamos definir a estrutura de prompt do Qwen3.6, limpar as saídas do modelo, criar funções auxiliares para treino e inferência e preparar algumas amostras de prévia para comparar o modelo antes e depois do fine-tuning.
Defina o prompt de sistema
Começamos definindo um prompt de sistema curto que orienta como o modelo deve responder. Como é uma tarefa de perguntas e respostas médicas, queremos respostas diretas, factuais e objetivas.
SYSTEM_PROMPT = "Answer the medical question directly in 2-4 factual sentences."
Aplique o template de chat
O Qwen3.6 usa um formato de entrada em estilo chat, então precisamos de uma função auxiliar que converta nossas mensagens na estrutura correta de prompt. Essa função aplica o template de chat do tokenizer e desativa a saída de raciocínio para manter o foco na resposta final.
def apply_chat_template(messages, add_generation_prompt=False):
kwargs = {
"tokenize": False,
"add_generation_prompt": add_generation_prompt,
}
try:
return tokenizer.apply_chat_template(
messages,
enable_thinking=False,
**kwargs,
)
except TypeError:
return tokenizer.apply_chat_template(
messages,
chat_template_kwargs={"enable_thinking": False},
**kwargs,
)
Limpe a saída do modelo
Agora definimos uma pequena função de limpeza para normalizar o texto gerado. Ela remove espaços em excesso e elimina qualquer prefixo answer: no início, caso apareça na saída.
def clean_answer_text(answer):
answer = clean_text(answer)
answer = re.sub(r"^answer\s*:\s*", "", answer, flags=re.IGNORECASE)
return answer
Monte o prompt do usuário
Também criamos uma função auxiliar para o prompt do usuário. Ela mantém o formato da pergunta consistente entre treino e avaliação e orienta o modelo a retornar apenas a resposta, sem repetir a pergunta.
def make_user_prompt(question):
return (
f"Question: {clean_text(question)}\n\n"
"Respond with only the answer. Do not restate the question."
)
Formate exemplos para supervised fine-tuning
Agora podemos formatar cada exemplo do dataset como uma conversa completa em estilo chat, com mensagem de sistema, pergunta do usuário e a resposta esperada do assistente. Essa é a estrutura que usaremos para o supervised fine-tuning.
def format_training_example(example):
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{
"role": "user",
"content": make_user_prompt(example["Question"]),
},
{
"role": "assistant",
"content": clean_answer_text(example["Answer"]),
},
]
return {"text": apply_chat_template(messages, add_generation_prompt=False)}
Gere respostas de baseline
Antes de começar o treinamento, precisamos de uma função auxiliar que gere respostas com o modelo base. Vamos usá-la para comparar as respostas antes e depois do fine-tuning.
A função abaixo monta o prompt, tokeniza, roda a geração e remove quaisquer traços de <think> e formatações extras da saída.
@torch.inference_mode()
def generate_answer(question, max_new_tokens=160):
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{
"role": "user",
"content": make_user_prompt(question),
},
]
prompt = apply_chat_template(messages, add_generation_prompt=True)
model_inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
generated = model.generate(
**model_inputs,
max_new_tokens=max_new_tokens,
do_sample=False,
pad_token_id=tokenizer.pad_token_id,
eos_token_id=tokenizer.eos_token_id,
)
new_tokens = generated[0][model_inputs["input_ids"].shape[1] :]
text = tokenizer.decode(new_tokens, skip_special_tokens=True).strip()
return clean_answer_text(re.sub(r"<think>.*?</think>", " ", text, flags=re.DOTALL))
Também adicionamos uma pequena função para encurtar saídas longas ao imprimir exemplos de prévia.
def clip_text(text, max_chars=600):
text = re.sub(r"<think>.*?</think>", " ", text, flags=re.DOTALL)
text = re.sub(r"\s+", " ", text).strip()
return text if len(text) <= max_chars else text[:max_chars] + "..."
Crie amostras de prévia para comparação
Por fim, criamos uma função auxiliar que monta algumas linhas de comparação lado a lado. Cada linha contém a pergunta, a predição do modelo e a resposta de referência. Isso nos dá uma forma rápida de inspecionar o desempenho antes e depois do fine-tuning.
def generate_preview_rows(dataset, sample_count=COMPARISON_SAMPLE_COUNT):
sample_count = min(sample_count, len(dataset))
subset = dataset.select(range(sample_count))
previews = []
for row in subset:
previews.append(
{
"question": row["Question"],
"prediction": generate_answer(row["Question"]),
"reference": clean_answer_text(row["Answer"]),
}
)
return previews
formatted_train_dataset = train_dataset.map(
format_training_example,
remove_columns=train_dataset.column_names,
)
comparison_examples = eval_dataset.shuffle(seed=SEED).select(
range(COMPARISON_SAMPLE_COUNT)
)
print(formatted_train_dataset[0])
Ao imprimir o primeiro exemplo formatado de treino, você deve ver uma amostra em estilo chat com o prompt de sistema, a pergunta do usuário e a resposta do assistente já encapsulados no template do Qwen.
{'text': '<|im_start|>system\nAnswer the medical question directly in 2-4 factual sentences.<|im_end|>\n<|im_start|>user\nQuestion: What is (are) COPD ?\n\nRespond with only the answer. Do not restate the question.<|im_end|>\n<|im_start|>assistant\n<think>\n\n</think>\n\nMore information on COPD is available at: What is COPD? and at the Learn More, Breathe Better Campaign For information on quitting smoking, visit http://www.surgeongeneral.gov/tobacco/ or Smokefree.gov. For information on the H1N1 flu and COPD, go to The Centers for Disease Control and Prevention.<|im_end|>\n'}
Etapa 5: avalie o modelo base antes do fine-tuning
Vamos testar o modelo base Qwen3.6 em alguns exemplos de avaliação antes do treinamento. Isso nos dá um baseline para comparar como o modelo muda após o fine-tuning.
Começamos gerando respostas de prévia para algumas amostras do conjunto de avaliação.
Cada prévia inclui a pergunta, a resposta do modelo antes do fine-tuning e a resposta de referência do dataset.
baseline_previews = generate_preview_rows(comparison_examples)
for idx, sample in enumerate(baseline_previews, start=1):
print(f"\n--- Preview {idx} ---")
print("Question:", sample["question"])
print("Model answer (before fine-tuning):", clip_text(sample["prediction"]))
print("Reference answer:", clip_text(sample["reference"]))
Aqui estão as comparações lado a lado entre a resposta atual do modelo e a resposta de referência. Esses exemplos ajudam a entender o ponto de partida do modelo antes de qualquer treinamento específico da tarefa.

A partir desses exemplos, já dá para ver que o modelo base é capaz de produzir respostas médicas relevantes e geralmente corretas.
No entanto, suas respostas nem sempre combinam com o estilo, o nível de detalhe ou a redação das respostas de referência do dataset. Em alguns casos, o modelo traz uma explicação mais ampla ou genérica, enquanto a resposta de referência é mais específica e melhor alinhada ao formato-alvo.
Etapa 6: configure o QLoRA para fine-tuning
Nesta parte, vamos definir as configurações do adapter LoRA, configurar os argumentos de supervised fine-tuning e inicializar o trainer que conduzirá o processo de treinamento com QLoRA.
Defina a configuração do LoRA
Em vez de atualizar todos os parâmetros do modelo, o QLoRA ajusta um conjunto bem menor de pesos treináveis do adapter. Isso torna o treinamento muito mais eficiente em memória, sem impedir a adaptação do modelo à nova tarefa.
Aqui, definimos uma configuração LoRA com rank 8, fator de escala 16 e um dropout pequeno. Também miramos todas as camadas lineares para aplicar os adapters de forma ampla no modelo.
lora_config = LoraConfig(
r=8,
lora_alpha=16,
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
target_modules="all-linear",
)
Defina os argumentos do trainer
Agora, definimos a configuração de treinamento usando SFTConfig. Essas definições controlam como a execução de supervised fine-tuning vai se comportar, incluindo tamanho de batch, acumulação de gradientes, taxa de aprendizado, frequência de logging e modo de precisão.
Este tutorial usa uma configuração leve com uma época de treinamento e batch pequeno, mantendo a execução prática para demonstração. Também ativamos gradient checkpointing e AdamW paginado em 8 bits para reduzir o uso de memória durante o treinamento.
trainer_config = SFTConfig(
output_dir=OUTPUT_DIR,
dataset_text_field="text",
max_length=MAX_SEQ_LENGTH,
per_device_train_batch_size=2,
gradient_accumulation_steps=2,
num_train_epochs=1,
learning_rate=1e-4,
warmup_steps=5,
logging_steps=5,
save_strategy="epoch",
report_to="none",
packing=False,
gradient_checkpointing=True,
optim="paged_adamw_8bit",
bf16=supports_bf16(),
fp16=not supports_bf16(),
)
Inicialize o SFTTrainer
Com as configurações do adapter e os argumentos de treinamento prontos, podemos inicializar o SFTTrainer. Ele reúne o modelo base, o dataset de treino formatado, a configuração do LoRA e o tokenizer para preparar o modelo para o supervised fine-tuning.
trainer = SFTTrainer(
model=model,
train_dataset=formatted_train_dataset,
peft_config=lora_config,
args=trainer_config,
processing_class=tokenizer,
)
Antes de iniciar o treinamento, vale a pena confirmar quantos parâmetros serão, de fato, atualizados. Uma das grandes vantagens do QLoRA é que apenas uma fração muito pequena do modelo se torna treinável.
trainer.model.print_trainable_parameters()
Isso mostra que apenas cerca de 0,03% de todos os parâmetros do modelo estão sendo treinados. É isso que torna o QLoRA uma abordagem tão prática para fazer fine-tuning de LLMs em hardware limitado.
trainable params: 11,238,720 || all params: 34,671,849,408 || trainable%: 0.0324
Etapa 7: treine o modelo e salve o adapter
Nesta seção, vamos iniciar a execução de supervised fine-tuning, salvar o adapter treinado localmente e depois enviá-lo ao Hugging Face para reutilização futura.
Inicie o fine-tuning
Com o modelo, o dataset e o trainer prontos, podemos começar o processo de fine-tuning. O trainer vai percorrer o conjunto de treino formatado e atualizar apenas os pesos do adapter LoRA, em vez do modelo completo.
train_result = trainer.train()
train_result
Durante o treinamento, você deve ver a loss diminuir gradualmente. Isso é um bom sinal de que o modelo está aprendendo o formato da tarefa e se adaptando aos dados de perguntas e respostas médicas.

Salve os pesos ajustados
Assim que o treinamento terminar, salve localmente o adapter com fine-tuning e o tokenizer. Isso fornece um checkpoint reutilizável que você pode carregar depois sem repetir toda a execução de treinamento.
trainer.model.save_pretrained(OUTPUT_DIR)
tokenizer.save_pretrained(OUTPUT_DIR)
Envie o modelo para o Hugging Face
Depois de salvar o adapter localmente, você pode enviá-lo ao Hugging Face. Isso facilita compartilhar, versionar e recarregar o modelo ajustado em futuros notebooks ou fluxos de deploy.
HF_REPO_ID = "kingabzpro/qwen36-medquad-quick"
trainer.model.push_to_hub(HF_REPO_ID)
tokenizer.push_to_hub(HF_REPO_ID)
Após o upload, o adapter ajustado ficará disponível no repositório.

Fonte: kingabzpro/qwen36-medquad-quick
Etapa 8: avalie o modelo após o fine-tuning
Com o treinamento concluído, podemos avaliar o modelo ajustado nas mesmas amostras de comparação usadas antes. Isso permite uma comparação direta de antes e depois nas exatas mesmas perguntas.
model.eval()
fine_tuned_previews = generate_preview_rows(comparison_examples)
for idx, (before, after) in enumerate(
zip(baseline_previews, fine_tuned_previews), start=1
):
print(f"\n{'=' * 80}")
print(f"Sample {idx}")
print(f"{'=' * 80}")
print("Question:", before["question"])
print("\nBefore fine-tuning:")
print(clip_text(before["prediction"]))
print("\nAfter fine-tuning:")
print(clip_text(after["prediction"]))
print("\nReference answer:")
print(clip_text(before["reference"]))
Você verá a resposta de baseline, a resposta após o fine-tuning e a resposta de referência para cada amostra. Isso facilita observar como o adapter mudou o estilo e o conteúdo das respostas do modelo.

Os exemplos mostram que o fine-tuning ajudou o modelo a se aproximar mais do estilo do dataset-alvo, especialmente em perguntas médicas curtas e factuais.
Ao mesmo tempo, os resultados também deixam claro que foi uma execução pequena de fine-tuning em um subconjunto limitado do dataset, então a melhoria em todas as amostras não é garantida. Algumas respostas ficam mais alinhadas à distribuição de treino, enquanto outras podem perder detalhes úteis ou ficar estreitas demais.
Para obter resultados melhores, o próximo passo seria treinar no dataset completo em vez de um subconjunto pequeno e executar o fine-tuning por pelo menos 3 épocas. Você também pode aumentar o rank do LoRA para dar mais capacidade de aprendizado ao adapter e refinar ainda mais o prompt de sistema para que o modelo siga o estilo desejado de resposta médica com mais consistência.
Essas mudanças provavelmente trarão melhorias mais estáveis em um conjunto mais amplo de perguntas.
Considerações finais
Fazer fine-tuning de um modelo de linguagem moderno não é tão simples quanto parece à primeira vista.
Embora o Qwen3.6-35B-A3B seja um mixture-of-experts eficiente, com 35 bilhões de parâmetros totais, ainda exige computação pesada só para carregá-lo em 4 bits e prepará-lo para o treino. O treinamento em si também continua caro, especialmente quando você sai de um subconjunto experimental pequeno e passa a trabalhar com um dataset maior ou múltiplas épocas.
O hardware faz muita diferença. Neste tutorial, usamos uma H100 NVL para manter o fluxo prático. Em uma GPU mais antiga, o tempo de treino pode aumentar bastante. Mesmo em uma A100, uma configuração similar pode levar cerca de uma hora, e GPUs mais fracas levariam bem mais.
Então, embora QLoRA e o carregamento em 4 bits tornem o fine-tuning mais acessível, isso não o transforma em algo leve no dia a dia. Também vale questionar se o fine-tuning é realmente necessário. Para muitas tarefas básicas, não recomendo partir direto para o fine-tuning.
Se você investir tempo em melhorar o prompt, estruturar melhor o fluxo de trabalho e usar ferramentas, MCPs ou métodos de recuperação (retrieval), muitas vezes dá para chegar perto do comportamento desejado sem treinar nada. Em muitos casos, isso te leva a uns 80% do resultado que você quer, além de ser mais rápido, barato e fácil de iterar.
O fine-tuning se torna bem mais valioso quando você precisa que o modelo aprenda de forma consistente um estilo de resposta, comportamento de domínio ou formato institucional muito específico. Aí começa a fazer sentido. Se você quer que o modelo responda exatamente como um determinado hospital, sistema de saúde ou fluxo de trabalho especializado, então o fine-tuning é o melhor caminho.
Em outras palavras: comece com prompting e design do fluxo de trabalho e recorra ao fine-tuning quando realmente precisar que o modelo internalize uma forma especializada de responder.

Sou um cientista de dados certificado que gosta de criar aplicativos de aprendizado de máquina e escrever blogs sobre ciência de dados. No momento, estou me concentrando na criação e edição de conteúdo e no trabalho com modelos de linguagem de grande porte.