Andro0s commited on
Commit
8a66252
·
verified ·
1 Parent(s): 6768da8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +144 -63
app.py CHANGED
@@ -1,121 +1,202 @@
1
  import os
2
  import gradio as gr
3
  from huggingface_hub import login
4
- from datasets import load_dataset
5
  from transformers import AutoTokenizer, AutoModelForCausalLM, Trainer, TrainingArguments, DataCollatorForLanguageModeling, pipeline
6
- from peft import PeftModel
7
 
8
  # ============================================================
9
- # 🔐 Autenticación HuggingFace
10
  # ============================================================
11
- hf_token = os.environ.get("HF_TOKEN")
12
- if hf_token:
13
- login(token=hf_token)
14
- else:
15
- print("⚠️ No se encontró el token. Agrega 'HF_TOKEN' en Settings → Secrets.")
16
 
17
- # ============================================================
18
- # ⚙️ Configuración del modelo y dataset
19
- # ============================================================
20
- BASE_MODEL = "bigcode/santacoder" # Modelo público
21
- LORA_PATH = "./lora_output" # Carpeta donde se guardará LoRA
22
- DATASET_PATH = "tu_dataset.json" # Cambia aquí al nombre de tu dataset
23
 
24
  # ============================================================
25
- # 🔧 Inicializar tokenizer y modelo base
26
  # ============================================================
27
- tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL)
28
- base_model = AutoModelForCausalLM.from_pretrained(BASE_MODEL)
29
-
30
- # 🔧 Asegurar que haya un pad_token
31
- if tokenizer.pad_token is None:
32
- tokenizer.pad_token = tokenizer.eos_token
33
 
34
- # ============================================================
35
- # 🧩 Función de entrenamiento LoRA
36
- # ============================================================
37
- def train_lora(epochs, batch_size, learning_rate):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  try:
39
- dataset = load_dataset("json", data_files=DATASET_PATH)
40
- tokenized = dataset.map(
41
  lambda e: tokenizer(
42
  e["prompt"] + e["completion"],
43
  truncation=True,
44
  padding="max_length",
45
- max_length=256
46
  ),
47
- batched=True
 
48
  )
 
 
 
 
 
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)
51
 
52
  training_args = TrainingArguments(
53
  output_dir=LORA_PATH,
54
  per_device_train_batch_size=int(batch_size),
55
- num_train_epochs=int(epochs),
56
- learning_rate=learning_rate,
57
  save_total_limit=1,
58
  logging_steps=10,
59
- push_to_hub=False
 
 
60
  )
61
 
62
  trainer = Trainer(
63
- model=base_model,
64
  args=training_args,
65
- train_dataset=tokenized["train"],
66
  data_collator=data_collator,
67
  )
68
 
69
  trainer.train()
70
- # Guardar LoRA
71
- base_model.save_pretrained(LORA_PATH)
72
- tokenizer.save_pretrained(LORA_PATH)
 
73
 
74
- return "✅ Entrenamiento completado y guardado en ./lora_output"
75
  except Exception as e:
76
  return f"❌ Error durante el entrenamiento: {e}"
77
 
78
  # ============================================================
79
- # 🤖 Función para generar texto usando LoRA sobre el modelo base
80
  # ============================================================
81
  def generate_text(prompt_text):
82
- try:
83
- # Cargar modelo base
84
- tokenizer_gen = AutoTokenizer.from_pretrained(BASE_MODEL)
85
- base_model_gen = AutoModelForCausalLM.from_pretrained(BASE_MODEL)
86
 
87
- # Aplicar LoRA
88
- model = PeftModel.from_pretrained(base_model_gen, LORA_PATH)
89
-
90
- generator = pipeline("text-generation", model=model, tokenizer=tokenizer_gen)
91
- output = generator(prompt_text, max_new_tokens=100, temperature=0.7, top_p=0.9)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  return output[0]["generated_text"]
 
93
  except Exception as e:
94
- return f"❌ Error generando texto: {e}"
95
 
96
  # ============================================================
97
- # 💻 Interfaz Gradio
98
  # ============================================================
99
- with gr.Blocks(title="AmorCoderAI - Entrenamiento LoRA") as demo:
100
- gr.Markdown("# 💙 AmorCoderAI - Entrenamiento y Pruebas")
101
- gr.Markdown("Entrena y prueba tu modelo basado en `bigcode/santacoder` con LoRA")
102
 
103
  with gr.Tab("🧠 Entrenar"):
104
- epochs = gr.Number(value=1, label="Épocas")
105
- batch_size = gr.Number(value=2, label="Tamaño de lote")
 
106
  learning_rate = gr.Number(value=5e-5, label="Tasa de aprendizaje")
107
- train_button = gr.Button("🚀 Iniciar entrenamiento")
108
- train_output = gr.Textbox(label="Resultado")
109
- train_button.click(train_lora, inputs=[epochs, batch_size, learning_rate], outputs=train_output)
 
 
 
 
110
 
111
  with gr.Tab("✨ Probar modelo"):
112
- prompt = gr.Textbox(label="Escribe un prompt")
113
- generate_button = gr.Button("💬 Generar texto")
114
- output_box = gr.Textbox(label="Salida generada")
115
  generate_button.click(generate_text, inputs=prompt, outputs=output_box)
116
 
117
  # ============================================================
118
- # 🚀 Lanzar app
119
  # ============================================================
120
  if __name__ == "__main__":
121
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import gradio as gr
3
  from huggingface_hub import login
4
+ from datasets import load_dataset, Dataset
5
  from transformers import AutoTokenizer, AutoModelForCausalLM, Trainer, TrainingArguments, DataCollatorForLanguageModeling, pipeline
6
+ from peft import get_peft_model, LoraConfig, TaskType, PeftModel
7
 
8
  # ============================================================
9
+ # ⚙️ CONFIGURACIÓN GLOBAL
10
  # ============================================================
11
+ BASE_MODEL = "bigcode/santacoder" # Modelo a refinar
12
+ LORA_PATH = "./lora_output" # Directorio para guardar los adaptadores
13
+ DATASET_PATH = "tu_dataset.json" # ¡Asegúrate de que este archivo exista!
 
 
14
 
15
+ # Variables globales inicializadas como None
16
+ tokenizer = None
17
+ lora_model = None
18
+ tokenized_dataset = None
19
+ lora_generator = None
 
20
 
21
  # ============================================================
22
+ # 🔐 AUTENTICACIÓN Y PRE-CARGA
23
  # ============================================================
 
 
 
 
 
 
24
 
25
+ def setup_resources():
26
+ """Carga y configura todos los recursos (modelo, tokenizer, dataset) una sola vez."""
27
+ global tokenizer, lora_model, tokenized_dataset
28
+
29
+ # 1. Autenticación
30
+ hf_token = os.environ.get("HF_TOKEN")
31
+ if hf_token:
32
+ login(token=hf_token)
33
+ else:
34
+ print("⚠️ Token no encontrado. La app intentará correr sin autenticación de escritura.")
35
+
36
+ # 2. Carga del Tokenizer y Modelo Base
37
+ print("\n🔄 Cargando modelo y tokenizer...")
38
+ tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL)
39
+ # Usa device_map="auto" para cargar el modelo de forma eficiente en la(s) GPU
40
+ base_model = AutoModelForCausalLM.from_pretrained(BASE_MODEL, device_map="auto")
41
+
42
+ if tokenizer.pad_token is None:
43
+ tokenizer.pad_token = tokenizer.eos_token
44
+
45
+ # 3. Configuración y Aplicación LoRA (PEFT)
46
+ peft_config = LoraConfig(
47
+ task_type=TaskType.CAUSAL_LM,
48
+ r=8,
49
+ lora_alpha=32,
50
+ lora_dropout=0.1,
51
+ # 'c_proj' y 'c_attn' son comunes en modelos GPT/causales
52
+ target_modules=["c_proj", "c_attn"],
53
+ )
54
+ lora_model = get_peft_model(base_model, peft_config)
55
+ print(f"✅ Modelo LoRA preparado. Parámetros entrenables: {lora_model.print_trainable_parameters()}")
56
+
57
+ # 4. Carga y Tokenización del Dataset (para evitar errores de longitud)
58
+ print("📚 Cargando y tokenizando dataset...")
59
  try:
60
+ raw_dataset = load_dataset("json", data_files=DATASET_PATH)
61
+ tokenized_dataset = raw_dataset.map(
62
  lambda e: tokenizer(
63
  e["prompt"] + e["completion"],
64
  truncation=True,
65
  padding="max_length",
66
+ max_length=256 # Mantener esta longitud consistente para evitar errores
67
  ),
68
+ batched=True,
69
+ remove_columns=raw_dataset["train"].column_names
70
  )
71
+ print("✅ Dataset tokenizado correctamente.")
72
+ except Exception as e:
73
+ tokenized_dataset = None
74
+ print(f"❌ Error al cargar o tokenizar el dataset. El auto-entrenamiento fallará. {e}")
75
+
76
 
77
+ # ============================================================
78
+ # 🧩 FUNCIÓN DE ENTRENAMIENTO
79
+ # ============================================================
80
+ def train_lora(epochs=1, batch_size=2, learning_rate=5e-5):
81
+ """Ejecuta el entrenamiento del modelo LoRA."""
82
+ global lora_model, tokenized_dataset, lora_generator
83
+
84
+ if tokenized_dataset is None or "train" not in tokenized_dataset:
85
+ return "❌ Error: El dataset no pudo cargarse o está vacío. No se puede entrenar."
86
+
87
+ try:
88
+ # Re-inicializa el generador a None para que se recargue después del entrenamiento
89
+ lora_generator = None
90
+
91
  data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)
92
 
93
  training_args = TrainingArguments(
94
  output_dir=LORA_PATH,
95
  per_device_train_batch_size=int(batch_size),
96
+ num_train_epochs=float(epochs),
97
+ learning_rate=float(learning_rate),
98
  save_total_limit=1,
99
  logging_steps=10,
100
+ push_to_hub=False,
101
+ # Desactiva la evaluación para simplificar el auto-entrenamiento
102
+ disable_tqdm=True
103
  )
104
 
105
  trainer = Trainer(
106
+ model=lora_model, # Usa el modelo LoRA global
107
  args=training_args,
108
+ train_dataset=tokenized_dataset["train"],
109
  data_collator=data_collator,
110
  )
111
 
112
  trainer.train()
113
+
114
+ # Guardar solo los adaptadores LoRA (PEFT)
115
+ lora_model.save_pretrained(LORA_PATH)
116
+ tokenizer.save_pretrained(LORA_PATH)
117
 
118
+ return "✅ Entrenamiento completado y adaptadores LoRA guardados en **./lora_output**"
119
  except Exception as e:
120
  return f"❌ Error durante el entrenamiento: {e}"
121
 
122
  # ============================================================
123
+ # 🤖 FUNCIÓN DE GENERACIÓN (INFERENCIA)
124
  # ============================================================
125
  def generate_text(prompt_text):
126
+ """Genera texto usando el modelo base + adaptadores LoRA."""
127
+ global lora_generator, lora_model
 
 
128
 
129
+ try:
130
+ # Carga el generador SOLO la primera vez o después del entrenamiento
131
+ if lora_generator is None:
132
+
133
+ # Cargar el modelo base limpio (sin los adaptadores LoRA)
134
+ base_model_gen = AutoModelForCausalLM.from_pretrained(BASE_MODEL, device_map="auto")
135
+
136
+ # Aplicar los adaptadores guardados
137
+ if os.path.exists(LORA_PATH):
138
+ model_with_lora = PeftModel.from_pretrained(base_model_gen, LORA_PATH)
139
+ else:
140
+ # Si no hay adaptadores entrenados, usa el modelo base inicial
141
+ model_with_lora = lora_model if lora_model else base_model_gen
142
+
143
+ # Fusionar el modelo base y los adaptadores para una inferencia más rápida
144
+ final_model = model_with_lora.merge_and_unload()
145
+
146
+ lora_generator = pipeline("text-generation", model=final_model, tokenizer=tokenizer)
147
+
148
+ output = lora_generator(prompt_text, max_new_tokens=100, temperature=0.7, top_p=0.9)
149
  return output[0]["generated_text"]
150
+
151
  except Exception as e:
152
+ return f"❌ Error generando texto (Asegúrate de que el modelo base y/o LoRA estén cargados): {e}"
153
 
154
  # ============================================================
155
+ # 💻 INTERFAZ GRADIO
156
  # ============================================================
157
+ with gr.Blocks(title="AmorCoderAI - LoRA") as demo:
158
+ gr.Markdown("# 💙 AmorCoderAI - Entrenamiento y Pruebas LoRA")
159
+ gr.Markdown(f"Modelo base: `{BASE_MODEL}`. Adaptadores guardados en `{LORA_PATH}`.")
160
 
161
  with gr.Tab("🧠 Entrenar"):
162
+ gr.Markdown("--- **¡CUIDADO!** El entrenamiento es lento y consume muchos recursos. ---")
163
+ epochs = gr.Number(value=1, label="Épocas", precision=0)
164
+ batch_size = gr.Number(value=2, label="Tamaño de lote (ajusta según tu RAM/VRAM)", precision=0)
165
  learning_rate = gr.Number(value=5e-5, label="Tasa de aprendizaje")
166
+ train_button = gr.Button("🚀 Iniciar entrenamiento Manual")
167
+ train_output = gr.Textbox(label="Resultado del Entrenamiento Manual")
168
+ train_button.click(
169
+ train_lora,
170
+ inputs=[epochs, batch_size, learning_rate],
171
+ outputs=train_output
172
+ )
173
 
174
  with gr.Tab("✨ Probar modelo"):
175
+ prompt = gr.Textbox(label="Escribe código (ej: 'def bubble_sort(arr):')", lines=4)
176
+ generate_button = gr.Button("💬 Generar código")
177
+ output_box = gr.Textbox(label="Salida generada", lines=10)
178
  generate_button.click(generate_text, inputs=prompt, outputs=output_box)
179
 
180
  # ============================================================
181
+ # 🚀 LANZAR APP Y AUTO-ENTRENAMIENTO
182
  # ============================================================
183
  if __name__ == "__main__":
184
+ # 1. Cargar recursos
185
+ setup_resources()
186
+
187
+ # 2. AUTO-ENTRENAMIENTO (¡El código se 'autocorre' aquí!)
188
+ print("\n=============================================")
189
+ print("🤖 INICIANDO AUTO-ENTRENAMIENTO...")
190
+ print("=============================================")
191
+
192
+ # Parámetros de auto-entrenamiento: 1 época, batch size 2, LR 5e-5
193
+ auto_train_result = train_lora(epochs=1, batch_size=2, learning_rate=5e-5)
194
+
195
+ print(f"\nFIN DEL AUTO-ENTRENAMIENTO: {auto_train_result}")
196
+
197
+ # 3. Lanzar la Interfaz Gradio
198
+ print("\n=============================================")
199
+ print("💻 LANZANDO INTERFAZ GRADIO")
200
+ print("=============================================")
201
+ demo.launch()
202
+