tributario / train_model.py
rwayz's picture
Update train_model.py
dc0bd9c verified
import torch
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
TrainingArguments,
Trainer,
DataCollatorForSeq2Seq,
)
from datasets import load_dataset
import os
from huggingface_hub import login, HfApi
# ✅ Configuração Inicial
os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True" # Melhora alocação de memória GPUs
# ✅ Autenticação no Hugging Face
HF_API_KEY = os.getenv("HF_API_KEY")
if not HF_API_KEY:
raise ValueError("❌ ERRO: Token Hugging Face não encontrado no ambiente.")
login(HF_API_KEY)
# ✅ Definição de Variáveis
DATASET_NAME = "rwayz/reasoning" # Dataset personalizado
MODEL_NAME = "meta-llama/Llama-3.1-8B-Instruct" # Modelo base
NEW_MODEL_NAME = "APPONTE/reasoning-llama-8b" # Novo modelo treinado
# ✅ Carregamento do Dataset
print(f"🔄 Carregando dataset: {DATASET_NAME}...")
dataset = load_dataset(DATASET_NAME)
print("✅ Dataset carregado com sucesso!")
# ✅ Exibir estrutura do dataset
print("📌 Colunas do dataset:", dataset["train"].column_names)
# ✅ Função para filtrar exemplos inválidos
def filter_invalid_examples(example):
fields = [
"IdCandidato", "Id", "Tags", "Url", "Url Perfil", "Cadastrado", "Nome", "Sexo",
"Data de Nascimento", "Documento Pessoal", "Cidade", "E-mail", "Telefone", "Etapa atual",
"Status da etapa", "Status na vaga", "Plataforma", "Objetivo profissional", "Tipo formacao", "Nome formacao", "Instituicao formacao", "Inicio formacao",
"Fim formacao", "Conclusao formacao", "Empresa experiencia", "Cargo experiencia", "Inicio experiencia",
"Fim experiencia", "Descricao atividades", "Tempo de experiencias formatado",
"Tempo formatado calculado", "Tipo idioma", "Nivel idioma", "Criado em", "Atualizado em", "Pontuacao Final", "Classificacao Final", "Top", "Aderencia ao Perfil",
"Status Profissional", "porcentagem_escolaridade", "porcentagem_posgraduacao", "porcentagem_idioma",
"porcentagem_experiencias", "porcentagem_experiencia_descricao", "Inconsistencia Experiencia",
"porcentagem_experiencia_desejada", "porcentagem_experiencia_trajetoria", "porcentagem_experiencia_instituicao_ou_setores",
"porcentagem_cargos_e_funcaos", "porcentagem_certificacao", "porcentagem_estabilidade", "porcentagem_cargos_recentes"
]
return any(bool(str(example.get(field, '')).strip()) for field in fields)
# 🔄 Remover exemplos inválidos
print("🔄 Removendo exemplos inválidos...")
dataset = dataset.filter(filter_invalid_examples)
print(f"✅ Dataset filtrado! {len(dataset['train'])} exemplos restantes.")
# ✅ Função para tratar dados nulos e tokenizar corretamente
def tokenize_function(examples):
inputs = ""
targets = ""
# 🔹 Coletar e tratar todos os campos, convertendo nulos em strings vazias
fields = [
"IdCandidato", "Id", "Tags", "Url", "Url Perfil", "Cadastrado", "Nome", "Sexo",
"Data de Nascimento", "Documento Pessoal", "Cidade", "E-mail", "Telefone", "Etapa atual",
"Status da etapa", "Status na vaga", "Plataforma", "Objetivo profissional", "Tipo formacao", "Nome formacao", "Instituicao formacao", "Inicio formacao",
"Fim formacao", "Conclusao formacao", "Empresa experiencia", "Cargo experiencia", "Inicio experiencia",
"Fim experiencia", "Descricao atividades", "Tempo de experiencias formatado",
"Tempo formatado calculado", "Tipo idioma", "Nivel idioma", "Criado em", "Atualizado em", "Pontuacao Final", "Classificacao Final", "Top", "Aderencia ao Perfil",
"Status Profissional", "porcentagem_escolaridade", "porcentagem_posgraduacao", "porcentagem_idioma",
"porcentagem_experiencias", "porcentagem_experiencia_descricao", "Inconsistencia Experiencia",
"porcentagem_experiencia_desejada", "porcentagem_experiencia_trajetoria", "porcentagem_experiencia_instituicao_ou_setores",
"porcentagem_cargos_e_funcaos", "porcentagem_certificacao", "porcentagem_estabilidade", "porcentagem_cargos_recentes"
]
# 🔹 Criar uma string formatada com todas as informações relevantes
inputs = "\n".join([f"{field}: {str(examples.get(field, '') or '').strip()}" for field in fields])
# 🔹 Definir como alvo a pontuação final, classificação e aderência ao perfil
targets = f"Pontuacao Final: {str(examples.get('Pontuacao Final', '')).strip()} | Classificacao Final: {str(examples.get('Classificacao Final', '')).strip()} | Aderencia ao Perfil: {str(examples.get('Aderencia ao Perfil', '')).strip()}"
# 🔹 Tokenizar input_ids e labels
model_inputs = tokenizer(inputs, padding="max_length", truncation=True, max_length=512)
labels = tokenizer(targets, padding="max_length", truncation=True, max_length=512)
model_inputs["labels"] = labels["input_ids"]
return model_inputs
# 🔹 Aplicar tokenização corretamente e adicionar labels
print("🔄 Tokenizando dataset...")
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, token=HF_API_KEY)
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
model = AutoModelForCausalLM.from_pretrained(
MODEL_NAME,
torch_dtype=torch.bfloat16,
device_map="auto",
token=HF_API_KEY
)
# ✅ Aplicar a tokenização ao novo dataset
tokenized_datasets = dataset.map(tokenize_function, batched=False, remove_columns=dataset["train"].column_names)
print("✅ Dataset tokenizado!")
# ✅ Criar Data Collator para empacotar os dados
from transformers import DataCollatorForSeq2Seq
data_collator = DataCollatorForSeq2Seq(tokenizer, model=model, padding=True)
# ✅ Ajuste de Hiperparâmetros para LOGS DETALHADOS
training_args = TrainingArguments(
output_dir="./results",
eval_strategy="steps",
eval_steps=1000, # 🔹 Avaliação frequente
save_strategy="steps",
save_steps=2500, # 🔹 Salvar checkpoints
per_device_train_batch_size=2,
per_device_eval_batch_size=2,
gradient_accumulation_steps=4,
num_train_epochs=10, # 🔹 Mais épocas para um treinamento robusto
weight_decay=0.01,
logging_dir="./logs",
logging_strategy="steps",
logging_steps=50, # 🔹 Logs frequentes
save_total_limit=2,
push_to_hub=True,
hub_model_id=NEW_MODEL_NAME,
hub_token=HF_API_KEY,
gradient_checkpointing=True,
bf16=True,
learning_rate=1e-6, # 🔹 Aprendizado mais lento
max_grad_norm=0.2,
warmup_ratio=0.1,
lr_scheduler_type="cosine",
optim="adamw_torch"
)
# ✅ Configurar Trainer para Fine-Tuning
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_datasets["train"],
eval_dataset=tokenized_datasets["train"],
data_collator=data_collator,
)
# ✅ Iniciar Treinamento
print("🚀 Iniciando treinamento do modelo...")
try:
trainer.train()
print("✅ Treinamento concluído!")
except RuntimeError as e:
print(f"❌ ERRO NO TREINAMENTO: {str(e)}")
# ✅ Salvar o Modelo Treinado Localmente
print("💾 Salvando modelo localmente...")
model.save_pretrained("./results")
tokenizer.save_pretrained("./results")
print("✅ Modelo salvo localmente em './results'!")
# ✅ Upload do modelo treinado para Hugging Face
print(f"🔄 Enviando modelo para o Hugging Face: {NEW_MODEL_NAME}...")
api = HfApi()
api.upload_folder(
folder_path="./results",
repo_id=NEW_MODEL_NAME,
repo_type="model",
token=HF_API_KEY
)
print(f"✅ Modelo salvo no Hugging Face: {NEW_MODEL_NAME}!")
print(f"🔗 Link do modelo: https://huggingface.co/rwayz/{NEW_MODEL_NAME}")