Spaces:
Running
Running
Update src/streamlit_app.py
Browse files- src/streamlit_app.py +51 -3
src/streamlit_app.py
CHANGED
|
@@ -16,6 +16,7 @@ os.environ.setdefault("STREAMLIT_SERVER_FILE_WATCHER_TYPE", "none")
|
|
| 16 |
|
| 17 |
import pandas as pd
|
| 18 |
import streamlit as st
|
|
|
|
| 19 |
import torch
|
| 20 |
from huggingface_hub import model_info
|
| 21 |
from transformers import AutoModelForCausalLM, AutoTokenizer
|
|
@@ -82,6 +83,32 @@ def _liberar_memoria() -> None:
|
|
| 82 |
torch.cuda.empty_cache()
|
| 83 |
|
| 84 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
@st.cache_data(show_spinner=False, ttl=3600)
|
| 86 |
def validar_modelo_existe(model_id: str) -> tuple[bool, str]:
|
| 87 |
try:
|
|
@@ -184,8 +211,30 @@ modo = st.radio(
|
|
| 184 |
"Selecciona el modo",
|
| 185 |
options=[ModoEvaluacion.POR_DEFECTO.value, ModoEvaluacion.PERSONALIZADA.value],
|
| 186 |
format_func=lambda x: "Evaluación por defecto" if x == ModoEvaluacion.POR_DEFECTO.value else "Evaluación personalizada",
|
|
|
|
| 187 |
)
|
| 188 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 189 |
# Unico parametro editable en UI para ambos modos.
|
| 190 |
timeout_segundos = st.slider(
|
| 191 |
"Timeout por llamada (segundos)",
|
|
@@ -355,16 +404,17 @@ if st.button("Comenzar evaluación", key="comenzar_eval", disabled=st.session_st
|
|
| 355 |
temp_dir = Path(tempfile.mkdtemp(prefix="equitia_space_"))
|
| 356 |
job_dir = temp_dir / "job"
|
| 357 |
start_ts = time.perf_counter()
|
|
|
|
| 358 |
|
| 359 |
progress = st.progress(0.0)
|
| 360 |
progress_label = st.empty()
|
| 361 |
estado_fase = st.empty()
|
|
|
|
| 362 |
|
| 363 |
def on_progress(done: int, total: int, current_file: str) -> None:
|
| 364 |
ratio = (done / total) if total else 0.0
|
| 365 |
elapsed = _formatear_duracion(time.perf_counter() - start_ts)
|
| 366 |
progress.progress(ratio)
|
| 367 |
-
estado_fase.info("Ejecutando proceso de evaluación")
|
| 368 |
progress_label.info(
|
| 369 |
f"Progreso: {done}/{total} prompts evaluados ({ratio * 100:.1f}%). Archivo actual: {current_file}. Tiempo: {elapsed}"
|
| 370 |
)
|
|
@@ -377,11 +427,9 @@ if st.button("Comenzar evaluación", key="comenzar_eval", disabled=st.session_st
|
|
| 377 |
)
|
| 378 |
|
| 379 |
try:
|
| 380 |
-
estado_fase.info("Obteniendo modelo a evaluar")
|
| 381 |
with st.spinner("Obteniendo modelo a evaluar..."):
|
| 382 |
cargar_modelo_transformers(st.session_state["modelo_eval_confirmado"])
|
| 383 |
|
| 384 |
-
estado_fase.info("Ejecutando proceso de evaluación")
|
| 385 |
with st.spinner("Ejecutando proceso de evaluación..."):
|
| 386 |
result = ejecutar_job(
|
| 387 |
request,
|
|
|
|
| 16 |
|
| 17 |
import pandas as pd
|
| 18 |
import streamlit as st
|
| 19 |
+
import streamlit.components.v1 as components
|
| 20 |
import torch
|
| 21 |
from huggingface_hub import model_info
|
| 22 |
from transformers import AutoModelForCausalLM, AutoTokenizer
|
|
|
|
| 83 |
torch.cuda.empty_cache()
|
| 84 |
|
| 85 |
|
| 86 |
+
def _render_reloj_tiempo_real(inicio_epoch: int) -> None:
|
| 87 |
+
components.html(
|
| 88 |
+
f"""
|
| 89 |
+
<div style='padding:0.35rem 0; font-size:0.95rem; color:#374151;'>
|
| 90 |
+
<strong>Tiempo transcurrido:</strong> <span id='equitia-live-timer'>00:00:00</span>
|
| 91 |
+
</div>
|
| 92 |
+
<script>
|
| 93 |
+
const startEpoch = {inicio_epoch};
|
| 94 |
+
function pad(n) {{ return String(n).padStart(2, '0'); }}
|
| 95 |
+
function tick() {{
|
| 96 |
+
const now = Math.floor(Date.now() / 1000);
|
| 97 |
+
const diff = Math.max(0, now - startEpoch);
|
| 98 |
+
const hh = Math.floor(diff / 3600);
|
| 99 |
+
const mm = Math.floor((diff % 3600) / 60);
|
| 100 |
+
const ss = diff % 60;
|
| 101 |
+
const el = document.getElementById('equitia-live-timer');
|
| 102 |
+
if (el) el.textContent = `${{pad(hh)}}:${{pad(mm)}}:${{pad(ss)}}`;
|
| 103 |
+
}}
|
| 104 |
+
tick();
|
| 105 |
+
setInterval(tick, 1000);
|
| 106 |
+
</script>
|
| 107 |
+
""",
|
| 108 |
+
height=42,
|
| 109 |
+
)
|
| 110 |
+
|
| 111 |
+
|
| 112 |
@st.cache_data(show_spinner=False, ttl=3600)
|
| 113 |
def validar_modelo_existe(model_id: str) -> tuple[bool, str]:
|
| 114 |
try:
|
|
|
|
| 211 |
"Selecciona el modo",
|
| 212 |
options=[ModoEvaluacion.POR_DEFECTO.value, ModoEvaluacion.PERSONALIZADA.value],
|
| 213 |
format_func=lambda x: "Evaluación por defecto" if x == ModoEvaluacion.POR_DEFECTO.value else "Evaluación personalizada",
|
| 214 |
+
disabled=st.session_state["eval_running"],
|
| 215 |
)
|
| 216 |
|
| 217 |
+
if st.session_state["eval_running"] and not st.session_state.get("eval_success"):
|
| 218 |
+
st.warning("Hay una evaluación en curso o interrumpida por una interacción.")
|
| 219 |
+
st.caption("No cambies parámetros ahora. Puedes cancelarla de forma segura.")
|
| 220 |
+
confirmar_cancelacion = st.checkbox(
|
| 221 |
+
"Confirmo que quiero cancelar la evaluación actual",
|
| 222 |
+
key="confirmar_cancelacion_eval",
|
| 223 |
+
value=False,
|
| 224 |
+
)
|
| 225 |
+
if st.button("Cancelar evaluación", key="cancelar_eval_btn"):
|
| 226 |
+
if confirmar_cancelacion:
|
| 227 |
+
st.session_state["eval_running"] = False
|
| 228 |
+
st.session_state["eval_success"] = False
|
| 229 |
+
st.session_state["last_result"] = None
|
| 230 |
+
st.session_state["modelo_eval_validado"] = False
|
| 231 |
+
st.session_state["modelo_eval_confirmado"] = ""
|
| 232 |
+
_liberar_memoria()
|
| 233 |
+
st.rerun()
|
| 234 |
+
else:
|
| 235 |
+
st.error("Debes confirmar la cancelación antes de continuar.")
|
| 236 |
+
st.stop()
|
| 237 |
+
|
| 238 |
# Unico parametro editable en UI para ambos modos.
|
| 239 |
timeout_segundos = st.slider(
|
| 240 |
"Timeout por llamada (segundos)",
|
|
|
|
| 404 |
temp_dir = Path(tempfile.mkdtemp(prefix="equitia_space_"))
|
| 405 |
job_dir = temp_dir / "job"
|
| 406 |
start_ts = time.perf_counter()
|
| 407 |
+
start_epoch = int(time.time())
|
| 408 |
|
| 409 |
progress = st.progress(0.0)
|
| 410 |
progress_label = st.empty()
|
| 411 |
estado_fase = st.empty()
|
| 412 |
+
_render_reloj_tiempo_real(start_epoch)
|
| 413 |
|
| 414 |
def on_progress(done: int, total: int, current_file: str) -> None:
|
| 415 |
ratio = (done / total) if total else 0.0
|
| 416 |
elapsed = _formatear_duracion(time.perf_counter() - start_ts)
|
| 417 |
progress.progress(ratio)
|
|
|
|
| 418 |
progress_label.info(
|
| 419 |
f"Progreso: {done}/{total} prompts evaluados ({ratio * 100:.1f}%). Archivo actual: {current_file}. Tiempo: {elapsed}"
|
| 420 |
)
|
|
|
|
| 427 |
)
|
| 428 |
|
| 429 |
try:
|
|
|
|
| 430 |
with st.spinner("Obteniendo modelo a evaluar..."):
|
| 431 |
cargar_modelo_transformers(st.session_state["modelo_eval_confirmado"])
|
| 432 |
|
|
|
|
| 433 |
with st.spinner("Ejecutando proceso de evaluación..."):
|
| 434 |
result = ejecutar_job(
|
| 435 |
request,
|