From e766e4ed26d53e22490317945ee5469a0a3902a2 Mon Sep 17 00:00:00 2001 From: admin <572701190@qq.com> Date: Tue, 30 Jun 2026 15:46:04 +0800 Subject: [PATCH] Load full artifact scan in dashboard --- README.md | 12 ++++++---- backend/app/agents/evaluation_agent.py | 5 +++- backend/app/main.py | 8 +++---- backend/tests/test_results_service.py | 32 ++++++++++++++++++++++++++ frontend/src/main.tsx | 24 +++++++++++-------- 5 files changed, 61 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 2d72e93..200a728 100644 --- a/README.md +++ b/README.md @@ -57,9 +57,9 @@ written under `var/custom_yolo_runs` and are scanned by the results dashboard. When a dataset is selected, the dataset panel shows its custom YOLO `best.pt`, prediction previews, heatmap previews, and inline training curve previews. Segmentation previews, YOLO heatmaps, and loss/metric artifacts are grouped on -the results dashboard. The artifact browser can filter by model family and -artifact role, and YOLO-style `results.csv` files are parsed into lightweight -training curves. +the results dashboard. The artifact browser loads the full result scan, can +filter by model family and artifact role, and YOLO-style `results.csv` files +are parsed into lightweight training curves. Job APIs and the SSE log stream also expose structured progress parsed from YOLO, MMSeg/MMEngine, SegModel-style epoch logs, and generic tqdm percentages, so the queue and live log panel can show stage, epoch/iteration, and percent @@ -163,8 +163,10 @@ Use `GET /api/coverage` to inspect script-to-task coverage and task buildability. Use `GET /api/capabilities` to inspect the grouped full-function readiness matrix used by the web dashboard and agents. -Use `GET /api/results/curves` to inspect parsed training curves discovered -from YOLO, SegModel, MMSeg, visual-tool, and analysis output directories. +Use `GET /api/results?limit=1000` to inspect browsable artifacts and +`GET /api/results/curves?limit=100` to inspect parsed training curves +discovered from YOLO, SegModel, MMSeg, visual-tool, and analysis output +directories. Use `GET /api/agents/evaluate` and `GET /api/agents/validate` to surface the same evaluation and validation feedback shown in the web dashboard Agent panel. diff --git a/backend/app/agents/evaluation_agent.py b/backend/app/agents/evaluation_agent.py index 6ef59d1..d70bcdf 100644 --- a/backend/app/agents/evaluation_agent.py +++ b/backend/app/agents/evaluation_agent.py @@ -54,7 +54,10 @@ def evaluate_project() -> dict: and "resultFamilyFilter" in frontend_text and "resultRoleFilter" in frontend_text and "familyOptions" in frontend_text - and "roleOptions" in frontend_text, + and "roleOptions" in frontend_text + and "/api/results?limit=1000" in frontend_text + and "setResults(resultsNext)" in frontend_text + and "slice(0, 240)" not in frontend_text, "job_progress_ui": "JobProgressBar" in frontend_text and "progressTrack" in frontend_text, "runtime_readiness_ui": "runtimeReadiness" in frontend_text and "环境就绪" in frontend_text, "capability_matrix_ui": "capabilities" in frontend_text and "全功能矩阵" in frontend_text, diff --git a/backend/app/main.py b/backend/app/main.py index 27223de..f736cf2 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -4,7 +4,7 @@ import asyncio import json from pathlib import Path -from fastapi import FastAPI, File, HTTPException, UploadFile +from fastapi import FastAPI, File, HTTPException, Query, UploadFile from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import FileResponse, StreamingResponse @@ -211,12 +211,12 @@ async def api_job_events(job_id: str): @app.get("/api/results") -def api_results() -> list[dict]: - return scan_results() +def api_results(limit: int = Query(1000, ge=1, le=5000)) -> list[dict]: + return scan_results(limit=limit) @app.get("/api/results/curves") -def api_result_curves(limit: int = 100) -> list[dict]: +def api_result_curves(limit: int = Query(100, ge=1, le=500)) -> list[dict]: return scan_training_curves(limit=limit) diff --git a/backend/tests/test_results_service.py b/backend/tests/test_results_service.py index 882a3b7..80c7f7e 100644 --- a/backend/tests/test_results_service.py +++ b/backend/tests/test_results_service.py @@ -1,5 +1,9 @@ from pathlib import Path +from fastapi.testclient import TestClient + +from app import main +from app.main import app from app.modules.results.service import parse_training_curve @@ -25,3 +29,31 @@ def test_parse_yolo_results_curve(tmp_path: Path): assert "train/seg_loss" in names assert "metrics/mAP50(M)" in names assert all("lr/" not in name for name in names) + + +def test_results_api_honors_limit(monkeypatch): + calls = {} + + def fake_scan_results(limit: int = 1000): + calls["limit"] = limit + return [{"name": "a.png", "relative_path": "var/a.png"}] + + monkeypatch.setattr(main, "scan_results", fake_scan_results) + response = TestClient(app).get("/api/results?limit=123") + + assert response.status_code == 200 + assert calls["limit"] == 123 + + +def test_results_curve_api_honors_limit(monkeypatch): + calls = {} + + def fake_scan_training_curves(limit: int = 100): + calls["limit"] = limit + return [{"name": "results", "relative_path": "var/results.csv"}] + + monkeypatch.setattr(main, "scan_training_curves", fake_scan_training_curves) + response = TestClient(app).get("/api/results/curves?limit=77") + + assert response.status_code == 200 + assert calls["limit"] == 77 diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 5ec75ce..7abbbdf 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -347,8 +347,8 @@ function useData() { api("/api/system/readiness"), api("/api/capabilities"), api("/api/jobs"), - api("/api/results"), - api("/api/results/curves"), + api("/api/results?limit=1000"), + api("/api/results/curves?limit=100"), api("/api/datasets"), api("/api/coverage"), api("/api/acceptance/latest"), @@ -360,8 +360,8 @@ function useData() { setRuntimeReadiness(readinessNext); setCapabilities(capabilitiesNext); setJobs(jobsNext); - setResults(resultsNext.slice(0, 240)); - setCurves(curvesNext.slice(0, 12)); + setResults(resultsNext); + setCurves(curvesNext); setDatasets(datasetsNext); const validationEntries: Array<[string, DatasetValidation]> = []; await Promise.all( @@ -1319,12 +1319,16 @@ function ResultBrowser({ / {total} artifacts );