yoel commited on
Commit
a2dd494
·
1 Parent(s): 302b2b5

Refactor: mejora la interfaz de evaluación agregando campos para nombre y matrícula, y actualiza la gestión del leaderboard

Browse files
Files changed (4) hide show
  1. .gitignore +1 -1
  2. app.py +24 -4
  3. evaluation.py +81 -10
  4. utils.py +51 -0
.gitignore CHANGED
@@ -25,7 +25,7 @@ share/python-wheels/
25
  .installed.cfg
26
  *.egg
27
  MANIFEST
28
-
29
  # PyInstaller
30
  # Usually these files are written by a python script from a template
31
  # before PyInstaller builds the exe, so as to inject date/other infos into it.
 
25
  .installed.cfg
26
  *.egg
27
  MANIFEST
28
+ leaderboard.json
29
  # PyInstaller
30
  # Usually these files are written by a python script from a template
31
  # before PyInstaller builds the exe, so as to inject date/other infos into it.
app.py CHANGED
@@ -10,19 +10,39 @@ etiquetas, num_clases, codigo = cargar_etiquetas()
10
  test_dataloader = cargar_dataset(codigo)
11
 
12
 
13
- def interface_wrapper(model_file):
14
- return evaluate_interface(model_file, num_clases, test_dataloader)
15
 
16
 
17
  # Interfaz de Gradio
18
  demo = gr.Interface(
19
  fn=interface_wrapper,
20
  inputs=[
 
 
21
  gr.File(label="Archivo del modelo (.safetensor)"),
22
  ],
23
- outputs=gr.Textbox(label="Resultado", lines=1),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  title="Evaluador de modelos",
25
- description="Carga un archivo .safetensor y evalúa su precisión en el conjunto de datos de evaluación.",
26
  )
27
 
28
  if __name__ == "__main__":
 
10
  test_dataloader = cargar_dataset(codigo)
11
 
12
 
13
+ def interface_wrapper(nombre, matricula, model_file):
14
+ return evaluate_interface(nombre, matricula, model_file, num_clases, test_dataloader)
15
 
16
 
17
  # Interfaz de Gradio
18
  demo = gr.Interface(
19
  fn=interface_wrapper,
20
  inputs=[
21
+ gr.Textbox(label="Nombre completo"),
22
+ gr.Textbox(label="Matrícula"),
23
  gr.File(label="Archivo del modelo (.safetensor)"),
24
  ],
25
+ outputs=[
26
+ gr.Textbox(label="Precisión"),
27
+ gr.Textbox(label="SHA256 del modelo"),
28
+ gr.Textbox(label="Calificación"),
29
+ gr.Dataframe(
30
+ headers=[
31
+ "Nombre",
32
+ "Matrícula",
33
+ "Accuracy",
34
+ "Puntaje",
35
+ "SHA256",
36
+ "Duplicado",
37
+ "Fecha (UTC)",
38
+ ],
39
+ datatype=["str", "str", "str", "number", "str", "str", "str"],
40
+ row_count=(0, "dynamic"),
41
+ label="Leaderboard",
42
+ ),
43
+ ],
44
  title="Evaluador de modelos",
45
+ description="Ingresa tus datos, carga un .safetensor y revisa tu lugar en el leaderboard.",
46
  )
47
 
48
  if __name__ == "__main__":
evaluation.py CHANGED
@@ -1,7 +1,14 @@
1
  import torch
 
2
  from safetensors.torch import load_model
3
  from models import FromZero
4
- from utils import multiclass_accuracy
 
 
 
 
 
 
5
 
6
 
7
  def cargar_evaluar_modelo(archivo, num_clases, test_dataloader):
@@ -27,20 +34,84 @@ def cargar_evaluar_modelo(archivo, num_clases, test_dataloader):
27
  return f"Error: {str(e)}"
28
 
29
 
30
- def evaluate_interface(model_file, num_clases, test_dataloader):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  if model_file is None:
32
- return "Por favor, carga un archivo .safetensor"
33
 
34
- # Verificamos que el archivo sea .safetensor
35
  if not model_file.name.endswith(".safetensor") and not model_file.name.endswith(
36
  ".safetensors"
37
  ):
38
- return "Por favor, carga un archivo con extensión .safetensor o .safetensors"
 
 
 
 
 
39
 
40
- # Evaluamos el modelo
41
  accuracy = cargar_evaluar_modelo(model_file.name, num_clases, test_dataloader)
42
 
43
- if isinstance(accuracy, float):
44
- return f"Precisión del modelo: {accuracy*100:.2f}%"
45
- else:
46
- return accuracy
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import torch
2
+ from datetime import datetime, timezone
3
  from safetensors.torch import load_model
4
  from models import FromZero
5
+ from utils import (
6
+ multiclass_accuracy,
7
+ calcular_puntaje,
8
+ cargar_leaderboard,
9
+ guardar_registro_leaderboard,
10
+ obtener_sha256,
11
+ )
12
 
13
 
14
  def cargar_evaluar_modelo(archivo, num_clases, test_dataloader):
 
34
  return f"Error: {str(e)}"
35
 
36
 
37
+ def _formatear_leaderboard(registros):
38
+ if not registros:
39
+ return []
40
+ ordenados = sorted(
41
+ registros,
42
+ key=lambda r: (r["puntaje"], r["accuracy"]),
43
+ reverse=True,
44
+ )
45
+ tabla = []
46
+ for entry in ordenados:
47
+ sha_marcado = entry["sha256"] + (" *" if entry.get("duplicado") else "")
48
+ duplicado = "Sí" if entry.get("duplicado") else "No"
49
+ tabla.append(
50
+ [
51
+ entry["nombre"],
52
+ entry["matricula"],
53
+ f"{entry['accuracy_pct']:.2f}%",
54
+ entry["puntaje"],
55
+ sha_marcado,
56
+ duplicado,
57
+ entry["timestamp"],
58
+ ]
59
+ )
60
+ return tabla
61
+
62
+
63
+ def evaluate_interface(nombre, matricula, model_file, num_clases, test_dataloader):
64
+ nombre = (nombre or "").strip()
65
+ matricula = (matricula or "").strip()
66
+ tabla_lideres = _formatear_leaderboard(cargar_leaderboard())
67
+
68
+ if not nombre or not matricula:
69
+ return (
70
+ "Por favor, ingresa nombre y matrícula.",
71
+ "",
72
+ "",
73
+ tabla_lideres,
74
+ )
75
+
76
  if model_file is None:
77
+ return ("Por favor, carga un archivo .safetensor", "", "", tabla_lideres)
78
 
 
79
  if not model_file.name.endswith(".safetensor") and not model_file.name.endswith(
80
  ".safetensors"
81
  ):
82
+ return (
83
+ "Por favor, carga un archivo con extensión .safetensor o .safetensors",
84
+ "",
85
+ "",
86
+ tabla_lideres,
87
+ )
88
 
89
+ sha256 = obtener_sha256(model_file.name)
90
  accuracy = cargar_evaluar_modelo(model_file.name, num_clases, test_dataloader)
91
 
92
+ if isinstance(accuracy, str):
93
+ return (accuracy, "", "", tabla_lideres)
94
+
95
+ puntaje = calcular_puntaje(accuracy)
96
+ accuracy_pct = accuracy * 100
97
+ registro = {
98
+ "nombre": nombre,
99
+ "matricula": matricula,
100
+ "accuracy": accuracy,
101
+ "accuracy_pct": accuracy_pct,
102
+ "puntaje": puntaje,
103
+ "sha256": sha256,
104
+ "timestamp": datetime.now(timezone.utc).isoformat(),
105
+ }
106
+ registros = guardar_registro_leaderboard(registro)
107
+ tabla_final = _formatear_leaderboard(registros)
108
+ sha_marcado = sha256 + (
109
+ " *" if any(r["sha256"] == sha256 and r.get("duplicado") for r in registros) else ""
110
+ )
111
+
112
+ return (
113
+ f"Precisión del modelo: {accuracy_pct:.2f}%",
114
+ f"SHA256: {sha_marcado}",
115
+ f"Puntaje asignado: {puntaje} pts",
116
+ tabla_final,
117
+ )
utils.py CHANGED
@@ -1,4 +1,10 @@
1
  import torch
 
 
 
 
 
 
2
 
3
 
4
  def cargar_etiquetas():
@@ -21,3 +27,48 @@ def multiclass_accuracy(predictions, labels):
21
  accuracy = correct_predictions / labels.size(0)
22
 
23
  return accuracy
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import torch
2
+ import json
3
+ import hashlib
4
+ from collections import Counter
5
+ from pathlib import Path
6
+
7
+ LEADERBOARD_PATH = Path("leaderboard.json")
8
 
9
 
10
  def cargar_etiquetas():
 
27
  accuracy = correct_predictions / labels.size(0)
28
 
29
  return accuracy
30
+
31
+
32
+ def obtener_sha256(ruta_archivo):
33
+ sha256 = hashlib.sha256()
34
+ with open(ruta_archivo, "rb") as archivo:
35
+ for bloque in iter(lambda: archivo.read(8192), b""):
36
+ sha256.update(bloque)
37
+ return sha256.hexdigest()
38
+
39
+
40
+ def calcular_puntaje(accuracy):
41
+ accuracy_pct = accuracy * 100
42
+ base = max(0, min(accuracy_pct - 55, 20))
43
+ extra = 10 if accuracy_pct > 95 else 0
44
+ return int(base + extra)
45
+
46
+
47
+ def cargar_leaderboard():
48
+ if not LEADERBOARD_PATH.exists():
49
+ return []
50
+ with LEADERBOARD_PATH.open("r", encoding="utf-8") as f:
51
+ return json.load(f)
52
+
53
+
54
+ def _marcar_duplicados(registros):
55
+ conteo = Counter(entry["sha256"] for entry in registros)
56
+ for entry in registros:
57
+ entry["duplicado"] = conteo[entry["sha256"]] > 1
58
+ return registros
59
+
60
+
61
+ def guardar_registro_leaderboard(entry, max_entries=500):
62
+ registros = cargar_leaderboard()
63
+ registros.append(entry)
64
+ registros = registros[-max_entries:]
65
+ registros = _marcar_duplicados(registros)
66
+ LEADERBOARD_PATH.write_text(
67
+ json.dumps(registros, indent=2, ensure_ascii=False),
68
+ encoding="utf-8",
69
+ )
70
+ return registros
71
+
72
+
73
+ def limpiar_leaderboard():
74
+ LEADERBOARD_PATH.write_text("[]", encoding="utf-8")