feat: HSAP platform v2 — modular navigation, quality review, audit log, world model simulation
Major changes: - New frontend (platform/web/): Vite + React 18 + TypeScript + Tailwind - 4-module navigation: 数据送标 / 模型管理 / 车队管理 / 系统管理 - Data catalog with charts (DMS/ADAS/Lane 3-tab view) - Quality review workflow (标注质检): Good/Fine/Bad scoring with auto-advance - Audit enhancements: batch operations, rejection categories, Feishu notifications - Operation audit log (操作日志) - World model simulation studio (仿真工坊) - Dataset version management with snapshots and diff - ADAS 7-class dataset integration (138K images organized + compressed) - User management with Feishu integration and pagination - CRUD/search/filter on all pages, card layout redesign - PIL-optimized image overlay rendering - Auto-snapshot on build, in_review workflow stage - Removed embedded algorithm code (now in workspace)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"""DMS YOLO 引擎:local 研发轨 / platform 平台轨。"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
@@ -13,11 +14,25 @@ YOLO_ROOT = WORKSPACE / "algorithms/dms_yolo/code"
|
||||
DATASET_ROOT = WORKSPACE / "datasets/dms"
|
||||
|
||||
|
||||
def _latest_run(task: str) -> tuple[str | None, str | None]:
|
||||
def _resolve_yaml_key(task: str, submode: str | None = None) -> tuple[str, str]:
|
||||
import sys
|
||||
|
||||
scripts = DATASET_ROOT / "scripts"
|
||||
if str(scripts) not in sys.path:
|
||||
sys.path.insert(0, str(scripts))
|
||||
from task_registry import get_mode_config, resolve_task_id, train_yaml_key
|
||||
|
||||
reg = yaml.safe_load((DATASET_ROOT / "datasets.registry.yaml").read_text(encoding="utf-8"))
|
||||
typ = reg["tasks"][task]["type"]
|
||||
task, submode = resolve_task_id(task, submode)
|
||||
mcfg = get_mode_config(task, submode, reg)
|
||||
key = train_yaml_key(task, submode, reg)
|
||||
return key, mcfg["type"]
|
||||
|
||||
|
||||
def _latest_run(task: str, submode: str | None = None) -> tuple[str | None, str | None]:
|
||||
yaml_key, typ = _resolve_yaml_key(task, submode)
|
||||
mode_yolo = {"detect": "detect", "pose": "pose", "classify": "classify"}[typ]
|
||||
runs = sorted((YOLO_ROOT / "runs" / mode_yolo).glob(f"{task}_*"), key=lambda p: p.stat().st_mtime, reverse=True)
|
||||
runs = sorted((YOLO_ROOT / "runs" / mode_yolo).glob(f"{yaml_key}_*"), key=lambda p: p.stat().st_mtime, reverse=True)
|
||||
if not runs:
|
||||
return None, None
|
||||
run_dir = runs[0].resolve()
|
||||
@@ -25,17 +40,21 @@ def _latest_run(task: str) -> tuple[str | None, str | None]:
|
||||
return str(run_dir), str(best) if best.is_file() else None
|
||||
|
||||
|
||||
def train_local(task: str, mode: str = "full", config_overrides: dict | None = None) -> dict[str, Any]:
|
||||
def train_local(task: str, mode: str = "full", config_overrides: dict | None = None, submode: str | None = None) -> dict[str, Any]:
|
||||
"""研发轨:train.sh,不 refresh yaml_active,不更新 candidate。"""
|
||||
env = {**os.environ}
|
||||
if submode:
|
||||
env["SUBMODE"] = submode
|
||||
proc = subprocess.run(
|
||||
[str(DATASET_ROOT / "scripts" / "train.sh"), task, mode],
|
||||
cwd=str(DATASET_ROOT),
|
||||
capture_output=True,
|
||||
text=True,
|
||||
env=env,
|
||||
)
|
||||
if proc.returncode != 0:
|
||||
raise RuntimeError(proc.stderr or proc.stdout)
|
||||
run_dir, best_weights = _latest_run(task)
|
||||
run_dir, best_weights = _latest_run(task, submode)
|
||||
return {
|
||||
"ok": True,
|
||||
"stdout": proc.stdout,
|
||||
@@ -48,28 +67,33 @@ def train_local(task: str, mode: str = "full", config_overrides: dict | None = N
|
||||
}
|
||||
|
||||
|
||||
def train_platform(task: str, mode: str = "full") -> dict[str, Any]:
|
||||
def train_platform(task: str, mode: str = "full", submode: str | None = None) -> dict[str, Any]:
|
||||
"""平台轨:refresh yaml_active + train + 更新 candidate。"""
|
||||
yaml_key, _ = _resolve_yaml_key(task, submode)
|
||||
subprocess.check_call(
|
||||
[sys.executable, str(DATASET_ROOT / "scripts/refresh_yaml.py"), "--task", task],
|
||||
cwd=str(DATASET_ROOT),
|
||||
)
|
||||
env = {**os.environ}
|
||||
if submode:
|
||||
env["SUBMODE"] = submode
|
||||
proc = subprocess.run(
|
||||
[str(DATASET_ROOT / "scripts" / "train.sh"), task, mode],
|
||||
cwd=str(DATASET_ROOT),
|
||||
capture_output=True,
|
||||
text=True,
|
||||
env=env,
|
||||
)
|
||||
if proc.returncode != 0:
|
||||
raise RuntimeError(proc.stderr or proc.stdout)
|
||||
|
||||
run_dir, best_weights = _latest_run(task)
|
||||
run_dir, best_weights = _latest_run(task, submode)
|
||||
candidate = None
|
||||
if best_weights:
|
||||
candidate = best_weights
|
||||
versions_path = DATASET_ROOT / "manifests/train_versions.yaml"
|
||||
versions = yaml.safe_load(versions_path.read_text(encoding="utf-8"))
|
||||
versions[task]["candidate"] = candidate
|
||||
versions[yaml_key]["candidate"] = candidate
|
||||
versions_path.write_text(yaml.dump(versions, allow_unicode=True, sort_keys=False), encoding="utf-8")
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user