Spaces:
Runtime error
Runtime error
import gradio as gr | |
import requests | |
import os | |
import pandas as pd | |
import numpy as np | |
import matplotlib | |
matplotlib.use('Agg') | |
import matplotlib.pyplot as plt | |
import io | |
import base64 | |
import json | |
import time | |
import subprocess | |
from huggingface_hub import Repository | |
# ----------------------------------------------------------------------------- | |
# CONFIGURACIÓN DEL REPO DEL SPACE Y DE LA REFERENCIA | |
# ----------------------------------------------------------------------------- | |
SPACE_REPO_URL = "https://huggingface.co/spaces/JulioContrerasH/my-challenge" | |
SPACE_LOCAL_DIR = "." # Usa la carpeta actual (el mismo repo del Space) | |
# URL de tu archivo de referencia CSV en un dataset (por ejemplo, "reference.csv") | |
REFERENCE_FILE_URL = ( | |
"https://huggingface.co/datasets/JulioContrerasH/my-challenge-submissions/resolve/main/reference.csv" | |
) | |
LOCAL_REF_PATH = "reference.csv" # Lo guardaremos con este nombre local | |
def git_set_identity(name: str, email: str): | |
"""Configura la identidad de git en el repo local.""" | |
try: | |
subprocess.run(["git", "config", "user.name", name], check=True) | |
subprocess.run(["git", "config", "user.email", email], check=True) | |
except Exception as e: | |
print("Error setting git identity:", e) | |
def setup_local_repo_for_push(): | |
""" | |
Inicializa un objeto 'Repository' apuntando al mismo repo del Space. | |
Requiere un token con permisos de escritura, guardado en HF_SPACE_TOKEN | |
como secret en la configuración del Space. | |
También configura user_name y user_email para que los commits no den error. | |
""" | |
token = os.environ.get("HF_SPACE_TOKEN", None) # Revisar que se llame así en los secrets | |
if not token: | |
print("WARNING: HF_SPACE_TOKEN no está configurado. No se podrá hacer push.") | |
return None | |
repo = Repository( | |
local_dir=SPACE_LOCAL_DIR, | |
clone_from=SPACE_REPO_URL, | |
use_auth_token=token | |
) | |
# Configurar user.name y user.email | |
git_set_identity("JulioContrerasH", "contrerasnetk@gmail.com") | |
# Forzar la URL remota para que lleve el token | |
# user: "__token__" (literal) y password: <token> | |
new_url = f"https://__token__:{token}@huggingface.co/spaces/JulioContrerasH/my-challenge" | |
subprocess.run(["git", "remote", "set-url", "origin", new_url], cwd=".", check=True) | |
# Por si se actualizó el Space en remoto | |
try: | |
repo.git_pull() | |
except: | |
pass | |
return repo | |
# Inicializamos la posibilidad de hacer push a nuestro Space | |
space_repo = setup_local_repo_for_push() | |
def add_submission_entry(entry): | |
""" | |
Abre/crea submissions.jsonl (en la raíz del Space), | |
agrega la nueva 'entry', y hace commit+push al repo. | |
""" | |
global space_repo | |
if space_repo is None: | |
print("No repo handle (space_repo is None). Skipping save.") | |
return | |
submissions_file = "submissions.jsonl" | |
# 1) Traer la última versión de remoto (por si hubo otros commits) | |
space_repo.git_pull() | |
# 2) Leer el archivo actual (si existe) | |
submissions = [] | |
if os.path.exists(submissions_file): | |
with open(submissions_file, "r") as f: | |
for line in f: | |
line = line.strip() | |
if line: | |
submissions.append(json.loads(line)) | |
# 3) Añadir la nueva entrada | |
submissions.append(entry) | |
# 4) Guardar sobrescribiendo | |
with open(submissions_file, "w") as f: | |
for s in submissions: | |
f.write(json.dumps(s) + "\n") | |
# 5) Hacer commit y push | |
space_repo.git_add(submissions_file) | |
space_repo.git_commit("Add new submission entry") | |
try: | |
space_repo.git_push() | |
print("Submission pushed successfully to the Space repo.") | |
except Exception as e: | |
print("Error pushing submission:", e) | |
# ----------------------------------------------------------------------------- | |
# DESCARGA DEL ARCHIVO DE REFERENCIA | |
# ----------------------------------------------------------------------------- | |
def download_reference(): | |
""" | |
Descarga el CSV de referencia desde el dataset en Hugging Face, | |
guardándolo como 'reference.csv' si no existe aún. | |
""" | |
if not os.path.exists(LOCAL_REF_PATH): | |
print("Descargando archivo de referencia...") | |
r = requests.get(REFERENCE_FILE_URL) | |
r.raise_for_status() | |
with open(LOCAL_REF_PATH, 'wb') as f: | |
f.write(r.content) | |
print("Descarga completa:", LOCAL_REF_PATH) | |
download_reference() # Se ejecuta al iniciar el Space | |
# ----------------------------------------------------------------------------- | |
# LÓGICA DE EVALUACIÓN | |
# ----------------------------------------------------------------------------- | |
def evaluate_prediction(pred_path, ref_path): | |
""" | |
Lee el CSV subido (pred_path) y el CSV de referencia (ref_path), | |
Calcula el MRE y RMSE, y retorna un dict con resultados. | |
Formato esperado: | |
- reference.csv: [wavelength, power] | |
- predictions.csv: [wavelength, prediction] | |
""" | |
# Leer la referencia | |
df_ref = pd.read_csv(ref_path) | |
# Leer la predicción | |
df_pred = pd.read_csv(pred_path) | |
# Merge en base a 'wavelength' | |
df_merged = pd.merge(df_ref, df_pred, on='wavelength', how='inner') | |
real = df_merged['power'].values | |
pred = df_merged['prediction'].values | |
# Calcular MRE | |
mre = np.abs((pred - real) / real) | |
mre_mean = mre.mean() | |
# Calcular RMSE | |
rmse = np.sqrt(np.mean((pred - real)**2)) | |
# Retornar | |
return { | |
"mre_mean": float(mre_mean), | |
"rmse": float(rmse), | |
"mre_spectrum": mre.tolist() | |
} | |
def evaluate_and_save(pred_file, participant_name): | |
""" | |
1. Toma el archivo subido (pred_file). | |
2. Evalúa comparándolo con la referencia (LOCAL_REF_PATH). | |
3. Agrega la entrada a submissions.jsonl. | |
4. Genera una gráfica y mensaje de resultados. | |
""" | |
if not pred_file: | |
return "No file uploaded", None | |
pred_path = pred_file.name | |
results = evaluate_prediction(pred_path, LOCAL_REF_PATH) | |
# Guardar submission en submissions.jsonl | |
submission_entry = { | |
"submission_id": int(time.time()), | |
"participant": participant_name, | |
"mre_mean": results["mre_mean"], | |
"rmse": results["rmse"], | |
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S") | |
} | |
add_submission_entry(submission_entry) | |
# Graficar | |
mre_spectrum = results["mre_spectrum"] | |
plt.figure(figsize=(6,4)) | |
plt.plot(np.arange(len(mre_spectrum)), mre_spectrum, marker='o', label='MRE Spectrum') | |
plt.xlabel('Index') | |
plt.ylabel('MRE') | |
plt.title('Spectral Error') | |
plt.legend() | |
buf = io.BytesIO() | |
plt.savefig(buf, format='png') | |
plt.close() | |
buf.seek(0) | |
img_str = base64.b64encode(buf.read()).decode('utf-8') | |
img_str = f"data:image/png;base64,{img_str}" | |
# Mensaje final | |
message = ( | |
f"Participant: {participant_name}\n" | |
f"MRE mean: {results['mre_mean']:.4f}\n" | |
f"RMSE: {results['rmse']:.4f}" | |
) | |
return message, img_str | |
# ----------------------------------------------------------------------------- | |
# INTERFAZ GRADIO | |
# ----------------------------------------------------------------------------- | |
with gr.Blocks() as demo: | |
gr.Markdown("# My Challenge\nSube tu archivo de predicciones en CSV para evaluar tu modelo.") | |
participant_name = gr.Textbox(label="Nombre del participante") | |
pred_file = gr.File(label="Subir archivo CSV (predictions.csv)") | |
output_message = gr.Textbox(label="Resultados") | |
output_image = gr.HTML(label="Gráfica") | |
submit_btn = gr.Button("Evaluar") | |
submit_btn.click( | |
fn=evaluate_and_save, | |
inputs=[pred_file, participant_name], | |
outputs=[output_message, output_image] | |
) | |
demo.launch() | |