feat(dashboard): progress bar live + top fitness sulla pagina Overview
Aggiunto blocco "Progresso run" sopra le metriche statiche con: - progress bar generazioni (gens_done / n_generations) - progress bar evaluations (evals_done / pop × gen) con percentuale - metric top fitness / median fitness / cost so far - pulsante Refresh manuale + timestamp ultimo update - emoji status (🟢 running / ✅ completed / ❌ failed) Niente nuove dipendenze: solo st.progress + st.rerun standard Streamlit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
import streamlit as st
|
||||
|
||||
from multi_swarm.dashboard.data import (
|
||||
evaluations_df,
|
||||
generations_df,
|
||||
get_repo,
|
||||
get_run_overview,
|
||||
list_runs_df,
|
||||
@@ -25,6 +28,41 @@ st.dataframe(runs[["id", "name", "started_at", "completed_at", "status", "total_
|
||||
selected = st.selectbox("Seleziona run per dettaglio", runs["id"].tolist())
|
||||
overview = get_run_overview(repo, selected)
|
||||
|
||||
# --- Progress live ---
|
||||
cfg = overview["config"]
|
||||
pop_size = int(cfg.get("population_size", 0))
|
||||
n_gens = int(cfg.get("n_generations", 0))
|
||||
evals = evaluations_df(repo, selected)
|
||||
gens = generations_df(repo, selected)
|
||||
|
||||
evals_done = len(evals)
|
||||
evals_total = max(pop_size * n_gens, 1)
|
||||
gens_done = int(gens["completed_at"].notna().sum()) if not gens.empty else 0
|
||||
|
||||
status_emoji = {"running": "🟢", "completed": "✅", "failed": "❌"}.get(overview["status"], "⚪")
|
||||
top_fit = float(evals["fitness"].max()) if not evals.empty else float("nan")
|
||||
|
||||
st.subheader(f"{status_emoji} Progresso run")
|
||||
st.progress(
|
||||
min(gens_done / max(n_gens, 1), 1.0),
|
||||
text=f"Generations: {gens_done}/{n_gens}",
|
||||
)
|
||||
st.progress(
|
||||
min(evals_done / evals_total, 1.0),
|
||||
text=f"Evaluations: {evals_done}/{evals_total} ({100*evals_done/evals_total:.1f}%)",
|
||||
)
|
||||
pcol1, pcol2, pcol3 = st.columns(3)
|
||||
pcol1.metric("Top fitness", f"{top_fit:.4f}" if evals_done else "—")
|
||||
pcol2.metric("Median fitness", f"{evals['fitness'].median():.4f}" if evals_done else "—")
|
||||
pcol3.metric("Cost so far", f"${overview['total_cost_usd']:.4f}")
|
||||
|
||||
ref_col1, ref_col2 = st.columns([1, 4])
|
||||
if ref_col1.button("🔄 Refresh"):
|
||||
st.rerun()
|
||||
ref_col2.caption(f"Last update: {datetime.now().strftime('%H:%M:%S')}")
|
||||
|
||||
st.divider()
|
||||
|
||||
col1, col2, col3, col4 = st.columns(4)
|
||||
col1.metric("Status", overview["status"])
|
||||
col2.metric("Cost (USD)", f"{overview['total_cost_usd']:.4f}")
|
||||
@@ -32,7 +70,6 @@ col3.metric("Started", overview["started_at"])
|
||||
col4.metric("Completed", overview["completed_at"] or "—")
|
||||
|
||||
st.subheader("Statistiche evaluations")
|
||||
evals = evaluations_df(repo, selected)
|
||||
col5, col6, col7, col8 = st.columns(4)
|
||||
if not evals.empty:
|
||||
parse_success = 100 * (evals["parse_error"].isna().sum() / len(evals))
|
||||
|
||||
Reference in New Issue
Block a user