Update app.py
Browse files
app.py
CHANGED
|
@@ -8,12 +8,12 @@ import random
|
|
| 8 |
import numpy as np
|
| 9 |
|
| 10 |
# --- 1. DETERMINISMO TOTAL ---
|
| 11 |
-
# Esto asegura que HF use la misma lógica matemática que tu PC
|
| 12 |
def set_seed(seed=42):
|
| 13 |
random.seed(seed)
|
| 14 |
np.random.seed(seed)
|
| 15 |
torch.manual_seed(seed)
|
| 16 |
-
torch.cuda.
|
|
|
|
| 17 |
|
| 18 |
set_seed(42)
|
| 19 |
|
|
@@ -42,7 +42,6 @@ class MiniGPT(nn.Module):
|
|
| 42 |
|
| 43 |
def forward(self, idx, targets=None):
|
| 44 |
B, T = idx.shape
|
| 45 |
-
# Limitamos el tamaño del bloque para evitar errores de índice
|
| 46 |
T = min(T, block_size)
|
| 47 |
idx = idx[:, -T:]
|
| 48 |
|
|
@@ -62,53 +61,47 @@ class MiniGPT(nn.Module):
|
|
| 62 |
# --- CARGA DEL MODELO ---
|
| 63 |
model = MiniGPT(vocab_size).to(device)
|
| 64 |
if os.path.exists("mini_gpt.pth"):
|
| 65 |
-
|
| 66 |
-
|
|
|
|
|
|
|
| 67 |
model.eval()
|
| 68 |
|
| 69 |
# --- FUNCIÓN DE RESPUESTA OPTIMIZADA ---
|
| 70 |
def responder(mensaje, historial):
|
| 71 |
-
# Formateamos el prompt exactamente como en el entrenamiento
|
| 72 |
-
# Usamos marcas claras para que la IA sepa dónde empezar
|
| 73 |
contexto = f"### Human: {mensaje}\n### Assistant: "
|
| 74 |
tokens = [ord(c) if ord(c) < 256 else 32 for c in contexto]
|
| 75 |
ai_txt = ""
|
| 76 |
|
| 77 |
with torch.no_grad():
|
| 78 |
-
for _ in range(100):
|
| 79 |
idx = torch.tensor([tokens[-block_size:]], dtype=torch.long).to(device)
|
| 80 |
logits, _ = model(idx)
|
| 81 |
|
| 82 |
-
#
|
| 83 |
-
# En lugar de multinomial, usamos argmax para que PC y HF sean gemelos
|
| 84 |
next_token = torch.argmax(logits[:, -1, :], dim=-1).item()
|
| 85 |
-
|
| 86 |
char = chr(next_token)
|
| 87 |
|
| 88 |
-
# Frenado de emergencia si empieza a repetir el prompt
|
| 89 |
if char == "\n" and len(ai_txt) > 5: break
|
| 90 |
if "### Human:" in ai_txt: break
|
| 91 |
|
| 92 |
tokens.append(next_token)
|
| 93 |
ai_txt += char
|
| 94 |
|
| 95 |
-
# --- LIMPIEZA FINAL ---
|
| 96 |
-
# Eliminamos cualquier residuo de las etiquetas de entrenamiento
|
| 97 |
output = ai_txt.split("###")[0].strip()
|
| 98 |
|
| 99 |
-
# Si la respuesta es nula o basura, damos un aviso
|
| 100 |
if not output:
|
| 101 |
return "Lo siento, todavía estoy aprendiendo de este dataset..."
|
| 102 |
|
| 103 |
return output
|
| 104 |
|
| 105 |
# --- INTERFAZ GRADIO ---
|
|
|
|
| 106 |
demo = gr.ChatInterface(
|
| 107 |
fn=responder,
|
| 108 |
title="Mi IA Personal (Sync Edition)",
|
| 109 |
description="Entrenando en PC -> Desplegado en HF. Sincronización de respuestas activa.",
|
| 110 |
-
examples=["Hola", "¿Qué tal?", "Cuéntame algo"]
|
| 111 |
-
theme="soft"
|
| 112 |
)
|
| 113 |
|
| 114 |
if __name__ == "__main__":
|
|
|
|
| 8 |
import numpy as np
|
| 9 |
|
| 10 |
# --- 1. DETERMINISMO TOTAL ---
|
|
|
|
| 11 |
def set_seed(seed=42):
|
| 12 |
random.seed(seed)
|
| 13 |
np.random.seed(seed)
|
| 14 |
torch.manual_seed(seed)
|
| 15 |
+
if torch.cuda.is_available():
|
| 16 |
+
torch.cuda.manual_seed_all(seed)
|
| 17 |
|
| 18 |
set_seed(42)
|
| 19 |
|
|
|
|
| 42 |
|
| 43 |
def forward(self, idx, targets=None):
|
| 44 |
B, T = idx.shape
|
|
|
|
| 45 |
T = min(T, block_size)
|
| 46 |
idx = idx[:, -T:]
|
| 47 |
|
|
|
|
| 61 |
# --- CARGA DEL MODELO ---
|
| 62 |
model = MiniGPT(vocab_size).to(device)
|
| 63 |
if os.path.exists("mini_gpt.pth"):
|
| 64 |
+
try:
|
| 65 |
+
model.load_state_dict(torch.load("mini_gpt.pth", map_location=device))
|
| 66 |
+
except Exception as e:
|
| 67 |
+
print(f"Error al cargar pesos: {e}")
|
| 68 |
model.eval()
|
| 69 |
|
| 70 |
# --- FUNCIÓN DE RESPUESTA OPTIMIZADA ---
|
| 71 |
def responder(mensaje, historial):
|
|
|
|
|
|
|
| 72 |
contexto = f"### Human: {mensaje}\n### Assistant: "
|
| 73 |
tokens = [ord(c) if ord(c) < 256 else 32 for c in contexto]
|
| 74 |
ai_txt = ""
|
| 75 |
|
| 76 |
with torch.no_grad():
|
| 77 |
+
for _ in range(100):
|
| 78 |
idx = torch.tensor([tokens[-block_size:]], dtype=torch.long).to(device)
|
| 79 |
logits, _ = model(idx)
|
| 80 |
|
| 81 |
+
# Greedy Search (Determinista)
|
|
|
|
| 82 |
next_token = torch.argmax(logits[:, -1, :], dim=-1).item()
|
|
|
|
| 83 |
char = chr(next_token)
|
| 84 |
|
|
|
|
| 85 |
if char == "\n" and len(ai_txt) > 5: break
|
| 86 |
if "### Human:" in ai_txt: break
|
| 87 |
|
| 88 |
tokens.append(next_token)
|
| 89 |
ai_txt += char
|
| 90 |
|
|
|
|
|
|
|
| 91 |
output = ai_txt.split("###")[0].strip()
|
| 92 |
|
|
|
|
| 93 |
if not output:
|
| 94 |
return "Lo siento, todavía estoy aprendiendo de este dataset..."
|
| 95 |
|
| 96 |
return output
|
| 97 |
|
| 98 |
# --- INTERFAZ GRADIO ---
|
| 99 |
+
# Eliminado el argumento 'theme' para evitar el TypeError en el servidor de HF
|
| 100 |
demo = gr.ChatInterface(
|
| 101 |
fn=responder,
|
| 102 |
title="Mi IA Personal (Sync Edition)",
|
| 103 |
description="Entrenando en PC -> Desplegado en HF. Sincronización de respuestas activa.",
|
| 104 |
+
examples=["Hola", "¿Qué tal?", "Cuéntame algo"]
|
|
|
|
| 105 |
)
|
| 106 |
|
| 107 |
if __name__ == "__main__":
|