Configurando o Axolotl com Malvorlage — o que funciona de fato
A maioria dos tutoriais na internet mostra um arquivo YAML bonito e bem formatado que nunca dá problema na prática. O problema é que os exemplos oficiais passam uma ideia simplificada do Axolotl que não corresponde ao que acontece quando você tenta rodar algo com GPU memory limitada ou dados inconsistentes. Eu passei semanas ajustando configs até descobrir onde o pipeline realmente quebra. Axolotl malvorlage se refere ao template ou configuração YAML que você usa para direcionar o fine-tuning dentro do Axolotl. Não é um formato proprietário — é basicamente um config que mapeia datasets, modelo base, parâmetros de otimização e paths de saída. O termo "malvorlage" aparece porque muitos usuários (e algumas versões antigas da documentação) tratam isso como algo separado, quando na verdade é só o arquivo de configuração padrão do Axolotl, apenas chamado de forma coloquial em certas comunidades.
Qual o formato esperado de um axolotl malvorlage
O arquivo normalmente termina em .yml ou .yaml e fica dentro do diretório config/ do repositório. A estrutura básica inclui: model_name_or_path — o caminho para o modelo base (Llama, Mistral, Qwen, etc.). Esse campo é obrigatório e costuma apontar para um diretório local ou um ID do Hugging Face Hub.
dataset_config — aqui você lista os datasets e as colunas que servem como prompt e completion. O formato é uma lista de dicionários, cada um com fields como name, type, columns. Se uma coluna estiver ausente no dataset, o Axolotl falha silenciosamente nos primeiros steps até você notar pelo missing KeyError no log. flash_attention, gradient_checkpointing, bf16 — flags de otimização. flash_attention=True reduz memória mas exige um kernel compatível. gradient_checkpointing trade-off velocidade por consumo de VRAM, compensando apenas em etapas longas. bf16 precisa de hardware Ampere+ (RTX 30xx, A100, H100).
output_dir — onde os checkpoints e o modelo final vão parar. Lembre-se de que o Axolotl salva estado de treinamento completo, não apenas pesos — isso pode crescer para dezenas de GB em runs longos. Um arquivo mínimo que funciona em produção (testado com Llama-2-7B e 8k context) tem cerca de 40-60 linhas. Vou mostrar um exemplo depois.
Problema real que encontrei e o workaround exato
Num setup com dois GPUs RTX 4090 em modo deepspeed stage 2, o treinamento travava no step 142 com um erro de shape incompatível entre attention_mask e input_ids. A causa não estava no YAML em si — era uma inconsistência no dataset onde algumas amostras tinham padding truncado pelo tokenizer. O Axolotl normalmente lida com isso, mas o deepspeed compounding com um bug de alinhamento causava o crash. O workaround foi rodar um script de pré-processamento antes do fine-tuning para garantir que todos os tokens de atenção tivessem o mesmo length do input. Usei uma função simples que faz padding até múltiplo de 8 e recalcula a attention_mask consistentemente. Depois disso, o crash sumiu. Levei três dias para isolar isso porque o erro não aparecia no step 1 — só quando o optimizer state acumulava o desalinhamento.
Outro ponto: muitos usuários esquecem que o campo neftune_noise_alpha precisa estar presente (mesmo que como 0) quando se usa NEFTune. Se omitido, o Axolotl assume None e pula o noise, o que pode causar overfit em datasets pequenos sem aviso.
Limitações reais da abordagem com malvorlage padrão
O Axolotl não gerencia múltiplos datasets com diferentes schemas no mesmo config. Você precisa de arquivos YAML separados ou juntar tudo num dataset unificado com colunas nullable — o que aumenta a chance de samples vazios quebrarem o dataloader. Memory usage é imprevisível. O mesmo malvorlage pode rodar com 16GB em uma GPU e OOM em outra porque o Axolotl reserva overhead dinâmico para gradientes e optimizer states. Teste sempre com micro_batch_size=1 e gradient_accumulation_steps=8 antes de aumentar o batch, especialmente em GPUs consumer.
Dataset eval durante treino não é confiável com o formato padrão. O Axolotl calcula loss mas não normaliza corretamente entre tokens de padding, então métricas de avaliação durante o run são apenas referenciais. Confie mais no loss final do que em métricas intermediárias. Se você tem menos de 48GB de VRAM total e quer treinar modelos acima de 13B, considere usar QLoRA com 4-bit quantization em vez de full fine-tuning. O Axolotl suporta, mas o template muda — bitsandbytes entra como dependência adicional e o formato de carregamento do modelo base é diferente.
Template básico de exemplo (axolotl malvorlage para Llama-2-7B)
Aqui está um config que usei em produção. Ele foi ajustado para rodar em uma única RTX 4090 com 24GB, batch efetivo de 64, usando gradient checkpointing. model_name_or_path: "meta-llama/Llama-2-7b-hf"
dataset_config: - name: custom_conversations type: sharegpt columns: conversations: conversations roles: ["user", "assistant"] sequence_length: 2048
output_dir: "./output/llama2-7b-conversational-v1" mixed_precision: bf16
👉 Clique no botão abaixo para saber mais sobre o assunto!
flash_attention: true gradient_checkpointing: true
wandb_project: "axolotl-tuning" epochs: 3
batch_size: 4 gradient_accumulation_steps: 8
learning_rate: 2e-5 warmup_ratio: 0.05
optimizer: paged_adamw_32bit lr_scheduler: cosine
save_steps: 100 logging_steps: 10
val_set_size: 0.05 evaluation_strategy: steps
eval_steps: 100 report_to: wandb
neftune_noise_alpha: 5 resume_from_checkpoint: null
local_rank: 0 O tempo de treino com esse config roda cerca de 4-6 horas num Llama-2-7B com 3 epochs, dependendo do tamanho do dataset. Datasets maiores que 50k samples tendem a ter diminishing returns após o epoch 2 — o loss para de cair significativamente e o risco de overfit aumenta. Em alguns casos, parar no epoch 2 já entrega qualidade comparable com metade do tempo de treino.
Se você precisa fazer deploy rápido de um modelo tuned, o formato de saída do Axolotl é compatível com vLLM e llama.cpp diretamente. Basta converter o output_dir para safetensors se necessário — o Axolotl já salva nesse formato por padrão, mas verifique antes de carregar em inferência. Modelos convertidos manualmente costumam ter incompatibilidade de shard que quebra o carregador. O Axolotl em si ainda não tem suporte nativo a múltiplas GPUs com ZeRO stage 3 em todas as versões. Se você tem cluster com várias GPUs e quer escalar, verifique a versão do deepspeed instalada e se o pacote está compilado com o kernel correto. Versões mais novas do Axolotl (0.5+) melhoraram isso, mas o estado da arte ainda é instável fora de ambientes controlados.