Add structured job progress tracking

This commit is contained in:
2026-06-30 14:18:02 +08:00
parent 93af8bcd3a
commit 442b521705
8 changed files with 454 additions and 9 deletions

View File

@@ -15,6 +15,7 @@ from ..coverage import get_coverage_report
from ..modules.results.service import scan_training_curves
from ..modules.system.service import get_conda_envs, get_gpus
from ..modules.weights.service import load_manifest
from ..progress import parse_progress
def _run(command: list[str], cwd: Path | None = None, timeout: int = 60) -> dict:
@@ -57,6 +58,8 @@ def validate_project(run_build: bool = False) -> dict:
checks.append({"name": "weights_manifest_present", "passed": manifest.get("count", 0) >= 1})
curves = scan_training_curves()
checks.append({"name": "training_curves_detected", "passed": len(curves) >= 1, "detail": {"count": len(curves), "examples": [item["relative_path"] for item in curves[:5]]}})
parsed_progress = parse_progress("Epoch(train) [2][25/50] lr: 1e-3\n", status="running")
checks.append({"name": "job_progress_parser", "passed": parsed_progress["stage"] == "training" and parsed_progress["percent"] == 50, "detail": parsed_progress})
checks.append({"name": "gpus_query", "passed": bool(get_gpus().get("available"))})
env_names = [item["name"] for item in get_conda_envs().get("envs", [])]
checks.append({"name": "task_env_exists", "passed": settings.task_conda_env in env_names, "detail": {"env": settings.task_conda_env}})
@@ -98,11 +101,21 @@ def validate_project(run_build: bool = False) -> dict:
frontend_url = os.getenv("SEG_VALIDATE_FRONTEND_URL", "http://127.0.0.1:5173")
health = _fetch(f"{backend_url}/api/health")
datasets = _fetch(f"{backend_url}/api/datasets")
live_jobs = _fetch(f"{backend_url}/api/jobs")
live_coverage = _fetch(f"{backend_url}/api/coverage")
live_curves = _fetch(f"{backend_url}/api/results/curves")
frontend = _fetch(frontend_url)
checks.append({"name": "live_backend_health", "passed": health["passed"] and '"ok":true' in health.get("body", "").replace(" ", ""), "detail": health})
checks.append({"name": "live_dataset_api", "passed": datasets["passed"] and datasets.get("body", "").lstrip().startswith("["), "detail": datasets})
try:
live_job_items = json.loads(live_jobs.get("body", "[]")) if live_jobs.get("passed") else []
except Exception:
live_job_items = []
checks.append({
"name": "live_jobs_progress_api",
"passed": live_jobs["passed"] and isinstance(live_job_items, list) and (not live_job_items or "progress" in live_job_items[0]),
"detail": live_jobs,
})
checks.append({"name": "live_coverage_api", "passed": live_coverage["passed"] and '"task_build_passed":true' in live_coverage.get("body", "").replace(" ", ""), "detail": live_coverage})
checks.append({"name": "live_training_curves_api", "passed": live_curves["passed"] and live_curves.get("body", "").lstrip().startswith("["), "detail": live_curves})
checks.append({"name": "live_frontend_index", "passed": frontend["passed"] and "Seg Data Server" in frontend.get("body", ""), "detail": frontend})