amarorn commited on
Commit
d6c8680
·
1 Parent(s): 3f4afaf

Corrigir repositório para beAnalytic/Training

Browse files
Files changed (3) hide show
  1. Dockerfile +37 -0
  2. README.md +57 -5
  3. train.py +294 -0
Dockerfile ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM huggingface/transformers-pytorch-gpu:latest
2
+
3
+ WORKDIR /app
4
+
5
+ # Instalar dependências do sistema
6
+ # python-is-python3 cria automaticamente o symlink python -> python3
7
+ RUN apt-get update && apt-get install -y --no-install-recommends \
8
+ git \
9
+ python3 \
10
+ python3-pip \
11
+ python-is-python3 \
12
+ && rm -rf /var/lib/apt/lists/*
13
+
14
+ # Verificar que python está disponível (entrypoint do NVIDIA precisa)
15
+ RUN python --version && \
16
+ python3 --version && \
17
+ echo "✅ Python disponível: $(which python)"
18
+
19
+ # Instalar dependências Python
20
+ COPY requirements.txt .
21
+ RUN python3 -m pip install --no-cache-dir --upgrade pip && \
22
+ python3 -m pip install --no-cache-dir -r requirements.txt
23
+
24
+ # Copiar scripts de treinamento
25
+ COPY train.py /app/train.py
26
+ COPY app.py /app/app.py
27
+
28
+ # Configurar variáveis de ambiente padrão (podem ser sobrescritas)
29
+ ENV MODEL_NAME=microsoft/Phi-3-mini-4k-instruct
30
+ ENV DATASET_REPO=beAnalytic/eda-training-dataset
31
+ ENV OUTPUT_REPO=beAnalytic/eda-llm-model
32
+
33
+ # Executar treinamento
34
+ # Usar 'python' (que será o symlink para python3 criado acima)
35
+ # O entrypoint do NVIDIA espera 'python' estar disponível
36
+ CMD ["python", "/app/app.py"]
37
+
README.md CHANGED
@@ -1,10 +1,62 @@
1
  ---
2
- title: Training
3
- emoji: 🐠
4
- colorFrom: yellow
5
- colorTo: yellow
6
  sdk: docker
 
 
7
  pinned: false
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: EDA Model Training
3
+ emoji: 🤖
4
+ colorFrom: blue
5
+ colorTo: purple
6
  sdk: docker
7
+ sdk_version: "latest"
8
+ app_file: app.py
9
  pinned: false
10
  ---
11
 
12
+ # Treinamento do Modelo EDA
13
+
14
+ Este Space contém o script de treinamento para o modelo de Análise Exploratória de Dados (EDA).
15
+
16
+ ## Configuração
17
+
18
+ ### Variáveis de Ambiente Obrigatórias
19
+
20
+ **⚠️ IMPORTANTE**: Configure a variável de ambiente `HF_TOKEN` no Settings do Space para habilitar o push automático dos checkpoints para o Hub.
21
+
22
+ ### Variáveis de Ambiente
23
+
24
+ Configure as seguintes variáveis de ambiente no Settings do Space:
25
+
26
+ - **`HF_TOKEN`** (OBRIGATÓRIO): Seu token do HuggingFace com permissões de escrita
27
+ - Gere em: https://huggingface.co/settings/tokens
28
+ - Permissões necessárias: `write`
29
+ - Sem este token, o treinamento funcionará mas os checkpoints não serão enviados ao Hub
30
+
31
+ - `MODEL_NAME`: Modelo base (padrão: `microsoft/Phi-3-mini-4k-instruct`)
32
+ - `DATASET_REPO`: ID do dataset (padrão: `beAnalytic/eda-training-dataset`)
33
+ - `OUTPUT_REPO`: ID do modelo de saída (padrão: `beAnalytic/eda-llm-model`)
34
+
35
+ ### Como Configurar HF_TOKEN no Space
36
+
37
+ 1. Acesse: https://huggingface.co/spaces/beAnalytic/Training/settings
38
+ 2. Vá para a seção **"Repository secrets"**
39
+ 3. Clique em **"New secret"**
40
+ 4. Nome: `HF_TOKEN`
41
+ 5. Valor: Cole seu token do HuggingFace
42
+ 6. Clique em **"Add secret"**
43
+
44
+ **Nota**: O token será usado automaticamente pelo script durante o treinamento.
45
+
46
+ ### Execução
47
+
48
+ O script `train.py` será executado automaticamente quando o Space for iniciado.
49
+
50
+ ## Estrutura
51
+
52
+ - `train.py`: Script principal de treinamento
53
+ - `training_config.json`: Configurações de treinamento
54
+ - `requirements.txt`: Dependências Python
55
+
56
+ ## Monitoramento
57
+
58
+ Acompanhe o progresso do treinamento através dos logs do Space na aba "Logs".
59
+
60
+ ## Resultados
61
+
62
+ O modelo treinado será salvo automaticamente no HuggingFace Hub no repositório especificado em `OUTPUT_REPO`.
train.py ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Script de treinamento gerado para HuggingFace Training Platform.
4
+ Execute este script no HuggingFace Training ou localmente.
5
+ """
6
+
7
+ from datasets import load_dataset
8
+ from transformers import (
9
+ AutoModelForCausalLM,
10
+ AutoTokenizer,
11
+ TrainingArguments,
12
+ Trainer,
13
+ DataCollatorForLanguageModeling,
14
+ )
15
+ from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
16
+ from transformers import BitsAndBytesConfig
17
+ from huggingface_hub import login as hf_login, logout as hf_logout
18
+ import torch
19
+ import os
20
+
21
+ # Configuração (pode ser sobrescrita por variáveis de ambiente)
22
+ MODEL_NAME = os.getenv("MODEL_NAME", "microsoft/Phi-3-mini-4k-instruct")
23
+ DATASET_REPO = os.getenv("DATASET_REPO", "beAnalytic/eda-training-dataset")
24
+ OUTPUT_REPO = os.getenv("OUTPUT_REPO", "beAnalytic/eda-llm-model")
25
+ HF_TOKEN = os.getenv("HF_TOKEN")
26
+
27
+ # Autenticar no HuggingFace se token estiver disponível
28
+ # IMPORTANTE: Limpar qualquer token do ambiente se não estiver configurado explicitamente
29
+ push_to_hub_enabled = False
30
+
31
+ # Primeiro, limpar qualquer autenticação existente para garantir estado limpo
32
+ try:
33
+ hf_logout()
34
+ except Exception:
35
+ pass
36
+
37
+ # Limpar tokens alternativos do ambiente (mantém HF_TOKEN que será usado depois)
38
+ tokens_to_remove = ["HUGGING_FACE_HUB_TOKEN", "HF_HUB_TOKEN", "HUGGINGFACE_HUB_TOKEN"]
39
+ for token_var in tokens_to_remove:
40
+ if token_var in os.environ:
41
+ del os.environ[token_var]
42
+
43
+ # Limpar cache de autenticação (hf_logout já faz isso)
44
+ try:
45
+ hf_logout()
46
+ except Exception:
47
+ pass
48
+
49
+ if HF_TOKEN and HF_TOKEN.strip():
50
+ print("Autenticando no HuggingFace Hub...")
51
+ try:
52
+ hf_login(token=HF_TOKEN, add_to_git_credential=False)
53
+ print("✅ Autenticação bem-sucedida!")
54
+ push_to_hub_enabled = True
55
+ except Exception as e:
56
+ print(f"⚠️ Aviso: Erro ao autenticar no HuggingFace: {e}")
57
+ print("O treinamento continuará, mas o push para o Hub será desabilitado.")
58
+ push_to_hub_enabled = False
59
+ # Limpar novamente após falha
60
+ try:
61
+ hf_logout()
62
+ except Exception:
63
+ pass
64
+ else:
65
+ print("⚠️ Aviso: HF_TOKEN não encontrado ou vazio. O push para o Hub será desabilitado.")
66
+ print("Configure a variável de ambiente HF_TOKEN no Space para habilitar push automático.")
67
+ push_to_hub_enabled = False
68
+
69
+ # Carregar dataset
70
+ print(f"Carregando dataset: {DATASET_REPO}")
71
+ dataset = load_dataset(DATASET_REPO)
72
+
73
+ # Carregar modelo e tokenizer
74
+ print(f"Carregando modelo: {MODEL_NAME}")
75
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
76
+ tokenizer.pad_token = tokenizer.eos_token
77
+
78
+ # Configurar quantização 4-bit
79
+ bnb_config = BitsAndBytesConfig(
80
+ load_in_4bit=True,
81
+ bnb_4bit_compute_dtype=torch.float16,
82
+ bnb_4bit_quant_type="nf4",
83
+ bnb_4bit_use_double_quant=True,
84
+ )
85
+
86
+ model = AutoModelForCausalLM.from_pretrained(
87
+ MODEL_NAME,
88
+ quantization_config=bnb_config,
89
+ device_map="auto",
90
+ trust_remote_code=True,
91
+ )
92
+
93
+ # Preparar modelo para LoRA
94
+ model = prepare_model_for_kbit_training(model)
95
+
96
+ # Configurar LoRA
97
+ peft_config = LoraConfig(
98
+ r=16,
99
+ lora_alpha=32,
100
+ target_modules=['q_proj', 'v_proj', 'k_proj', 'o_proj'],
101
+ lora_dropout=0.1,
102
+ bias="none",
103
+ task_type="CAUSAL_LM",
104
+ )
105
+
106
+ model = get_peft_model(model, peft_config)
107
+
108
+ # Formatar prompts
109
+ def format_prompt(example):
110
+ system_prompt = (
111
+ "Você é um analista de dados sênior realizando uma Análise Exploratória de Dados (EDA) "
112
+ "com rigor estatístico, honestidade analítica e pensamento crítico.\n\n"
113
+ "Seu objetivo não é gerar insights a qualquer custo, mas avaliar se os dados possuem "
114
+ "estrutura informativa, comportamento emergente ou apenas relações estruturais triviais."
115
+ )
116
+
117
+ instruction = example.get("instruction", "")
118
+ input_text = example.get("input", "")
119
+ output_text = example.get("output", "")
120
+
121
+ prompt = f"<|system|>\n{system_prompt}\n<|user|>\n{instruction}\n\n{input_text}\n<|assistant|>\n{output_text}<|end|>"
122
+ return {"text": prompt}
123
+
124
+ # Aplicar formatação
125
+ train_dataset = dataset["train"].map(format_prompt, remove_columns=dataset["train"].column_names)
126
+ eval_dataset = dataset["validation"].map(format_prompt, remove_columns=dataset["validation"].column_names)
127
+
128
+ # Tokenizar
129
+ def tokenize_function(examples):
130
+ return tokenizer(
131
+ examples["text"],
132
+ truncation=True,
133
+ max_length=1024,
134
+ padding="max_length",
135
+ )
136
+
137
+ train_dataset = train_dataset.map(tokenize_function, batched=True, remove_columns=["text"])
138
+ eval_dataset = eval_dataset.map(tokenize_function, batched=True, remove_columns=["text"])
139
+
140
+ # Configurar argumentos de treinamento
141
+ # push_to_hub_enabled já foi definido acima durante a autenticação
142
+
143
+ # Argumentos base de treinamento
144
+ training_args_dict = {
145
+ "output_dir": "./results",
146
+ "num_train_epochs": 3,
147
+ "per_device_train_batch_size": 4,
148
+ "per_device_eval_batch_size": 4,
149
+ "learning_rate": 3e-05,
150
+ "warmup_steps": 100,
151
+ "logging_steps": 10,
152
+ "save_steps": 500,
153
+ "eval_strategy": "steps",
154
+ "eval_steps": 500,
155
+ "save_total_limit": 3,
156
+ "load_best_model_at_end": True,
157
+ "fp16": True,
158
+ "gradient_accumulation_steps": 2,
159
+ }
160
+
161
+ # Adicionar parâmetros do Hub apenas se autenticado
162
+ # IMPORTANTE: Não passar NENHUM parâmetro relacionado ao Hub quando não há token
163
+ # para evitar que o Trainer tente inicializar o repositório
164
+ if push_to_hub_enabled:
165
+ training_args_dict.update({
166
+ "push_to_hub": True,
167
+ "hub_model_id": OUTPUT_REPO,
168
+ "hub_strategy": "checkpoint",
169
+ })
170
+ else:
171
+ # Garantir explicitamente que push_to_hub está desabilitado
172
+ # E que hub_model_id é None (não passar o parâmetro pode fazer o Trainer usar um valor padrão)
173
+ training_args_dict["push_to_hub"] = False
174
+ training_args_dict["hub_model_id"] = None
175
+
176
+ training_args = TrainingArguments(**training_args_dict)
177
+
178
+ if push_to_hub_enabled:
179
+ print(f"✅ Push para Hub habilitado: {OUTPUT_REPO}")
180
+ else:
181
+ print("ℹ️ Push para Hub desabilitado (HF_TOKEN não configurado)")
182
+ print("Os checkpoints serão salvos apenas localmente em ./results")
183
+
184
+ # Data collator
185
+ data_collator = DataCollatorForLanguageModeling(
186
+ tokenizer=tokenizer,
187
+ mlm=False,
188
+ )
189
+
190
+ # Trainer
191
+ # IMPORTANTE: Garantir que não há token no ambiente quando push_to_hub está desabilitado
192
+ # para evitar que o Trainer tente inicializar o repositório durante __init__
193
+ if not push_to_hub_enabled:
194
+ # Limpar todos os possíveis tokens do ambiente
195
+ tokens_to_remove = ["HUGGING_FACE_HUB_TOKEN", "HF_HUB_TOKEN", "HUGGINGFACE_HUB_TOKEN"]
196
+ for token_var in tokens_to_remove:
197
+ if token_var in os.environ:
198
+ del os.environ[token_var]
199
+
200
+ # Fazer logout para garantir que não há token no cache
201
+ try:
202
+ hf_logout()
203
+ except Exception:
204
+ pass
205
+
206
+ # Verificação de segurança - garantir que push_to_hub está False
207
+ if training_args.push_to_hub:
208
+ print("⚠️ AVISO: push_to_hub está True mas não há token! Forçando False...")
209
+ training_args.push_to_hub = False
210
+ if training_args.hub_model_id is not None:
211
+ print("⚠️ AVISO: hub_model_id está definido mas não há token! Removendo...")
212
+ training_args.hub_model_id = None
213
+
214
+ print(f"🔍 Debug: push_to_hub={training_args.push_to_hub}, hub_model_id={training_args.hub_model_id}")
215
+ print(f"🔍 Debug: push_to_hub_enabled={push_to_hub_enabled}")
216
+
217
+ # Verificação final: se push_to_hub está False, garantir que não há token no cache
218
+ if not push_to_hub_enabled:
219
+ # Limpar qualquer token residual do cache
220
+ try:
221
+ hf_logout()
222
+ except Exception:
223
+ pass
224
+
225
+ # Verificação final dos argumentos
226
+ if training_args.push_to_hub or training_args.hub_model_id:
227
+ print("❌ ERRO: push_to_hub ou hub_model_id ainda está definido! Corrigindo...")
228
+ training_args.push_to_hub = False
229
+ training_args.hub_model_id = None
230
+
231
+ print(f"✅ Criando Trainer com push_to_hub={training_args.push_to_hub}, hub_model_id={training_args.hub_model_id}")
232
+
233
+ # Criar Trainer
234
+ # Se push_to_hub está False, garantir que não há token no cache antes de criar
235
+ if not push_to_hub_enabled:
236
+ # Última verificação: limpar qualquer token residual
237
+ try:
238
+ hf_logout()
239
+ except Exception:
240
+ pass
241
+
242
+ try:
243
+ trainer = Trainer(
244
+ model=model,
245
+ args=training_args,
246
+ train_dataset=train_dataset,
247
+ eval_dataset=eval_dataset,
248
+ data_collator=data_collator,
249
+ )
250
+ print("✅ Trainer criado com sucesso!")
251
+ except Exception as e:
252
+ if "401" in str(e) or "Unauthorized" in str(e):
253
+ print("❌ ERRO: Trainer tentou autenticar sem token válido!")
254
+ print("Isso não deveria acontecer. Verificando configuração...")
255
+ print(f"push_to_hub={training_args.push_to_hub}")
256
+ print(f"hub_model_id={training_args.hub_model_id}")
257
+ print(f"push_to_hub_enabled={push_to_hub_enabled}")
258
+ # Tentar novamente após limpar tudo
259
+ try:
260
+ hf_logout()
261
+ except Exception:
262
+ pass
263
+ # Forçar push_to_hub=False novamente
264
+ training_args.push_to_hub = False
265
+ training_args.hub_model_id = None
266
+ print("Tentando criar Trainer novamente com push_to_hub=False...")
267
+ trainer = Trainer(
268
+ model=model,
269
+ args=training_args,
270
+ train_dataset=train_dataset,
271
+ eval_dataset=eval_dataset,
272
+ data_collator=data_collator,
273
+ )
274
+ else:
275
+ raise
276
+
277
+ # Treinar
278
+ print("Iniciando treinamento...")
279
+ trainer.train()
280
+
281
+ # Fazer push final apenas se autenticado
282
+ if push_to_hub_enabled:
283
+ print(f"Fazendo push do modelo final para {OUTPUT_REPO}")
284
+ try:
285
+ trainer.push_to_hub()
286
+ print("✅ Push para Hub concluído!")
287
+ except Exception as e:
288
+ print(f"❌ Erro ao fazer push para Hub: {e}")
289
+ print("Os checkpoints estão salvos localmente em ./results")
290
+ else:
291
+ print("ℹ️ Push para Hub pulado (HF_TOKEN não configurado)")
292
+ print("Os checkpoints estão salvos em ./results")
293
+
294
+ print("✅ Treinamento concluído!")