Spaces:
Sleeping
Sleeping
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- .gitignore +1 -1
- app.py +24 -4
- evaluation.py +81 -10
- 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=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
title="Evaluador de modelos",
|
| 25 |
-
description="
|
| 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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
|
| 40 |
-
|
| 41 |
accuracy = cargar_evaluar_modelo(model_file.name, num_clases, test_dataloader)
|
| 42 |
|
| 43 |
-
if isinstance(accuracy,
|
| 44 |
-
return
|
| 45 |
-
|
| 46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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")
|