Files
HSAP/datasets/dms/scripts/task_registry.py
Chengfang Lu e72bc061c5 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)
2026-06-03 11:40:21 +08:00

167 lines
5.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""DMS 任务注册表domain 分组、multi 任务(前向 detect+classify、旧 ID 别名。"""
from __future__ import annotations
from typing import Any
DOMAIN_LABELS = {
"dms": "舱内 DMS",
"forward": "前向 ADAS",
}
# 报表 / 旧目录名 -> (task, mode)
REPORT_TASK_ALIASES: dict[str, tuple[str, str | None]] = {
"isa": ("forward", "detect"),
"isa_detect": ("forward", "detect"),
"isa_class": ("forward", "classify"),
"isa_class_0116": ("forward", "classify"),
"dam_0417": ("dam", "batch_0417"),
}
LEGACY_TASK_ALIASES: dict[str, tuple[str, str | None]] = {
"isa": ("forward", "detect"),
"isa_class": ("forward", "classify"),
"dam_0417": ("dam", "batch_0417"),
}
def load_registry(reg: dict) -> dict[str, Any]:
return reg.get("tasks") or {}
def resolve_task_id(task: str, mode: str | None = None) -> tuple[str, str | None]:
"""用户/历史 task ID -> (canonical_task, mode)。"""
if task in LEGACY_TASK_ALIASES:
t, m = LEGACY_TASK_ALIASES[task]
return t, mode or m
return task, mode
def report_task_key(task: str, mode: str | None = None) -> str:
"""catalog 报表 CSV 中的任务列名。"""
t, m = resolve_task_id(task, mode)
if t == "forward" and m == "detect":
return "isa"
if t == "forward" and m == "classify":
return "isa_class"
if t == "dam" and m == "batch_0516":
return "dam"
if t == "dam" and m == "batch_0417":
return "dam_0417"
return task
def train_yaml_key(task: str, mode: str | None, reg: dict) -> str:
"""manifests/yaml_active 与 train.sh 使用的文件名(不含 .yaml"""
task, mode = resolve_task_id(task, mode)
tcfg = load_registry(reg)[task]
if tcfg.get("type") == "multi":
if not mode:
raise ValueError(f"任务 {task} 需指定 modedetect / classify")
return f"{task}__{mode}"
return task
def get_mode_config(task: str, mode: str | None, reg: dict) -> dict[str, Any]:
task, mode = resolve_task_id(task, mode)
tcfg = load_registry(reg)[task]
if tcfg.get("type") != "multi":
return {**tcfg, "task": task, "mode": None}
modes = tcfg.get("modes") or {}
if not mode:
raise ValueError(f"任务 {task} 需指定 mode")
if mode not in modes:
raise ValueError(f"未知 mode: {task}/{mode}")
mcfg = dict(modes[mode])
mcfg["task"] = task
mcfg["mode"] = mode
mcfg["task_dir"] = f"{tcfg.get('task_dir', task)}/{mcfg.get('subdir', mode)}"
mcfg["domain"] = tcfg.get("domain")
mcfg["label"] = mcfg.get("label") or tcfg.get("label")
return mcfg
def task_data_dir(pack_dir, task: str, mode: str | None, reg: dict):
from pathlib import Path
mcfg = get_mode_config(task, mode, reg)
return Path(pack_dir) / mcfg["task_dir"]
def inbox_dir(root, task: str, mode: str | None, reg: dict):
from pathlib import Path
task, mode = resolve_task_id(task, mode)
tcfg = load_registry(reg)[task]
if tcfg.get("type") == "multi":
mcfg = tcfg["modes"][mode or ""]
rel = mcfg.get("inbox") or f"inbox/{task}/{mode}"
return Path(root) / rel
return Path(root) / (tcfg.get("inbox") or f"inbox/{task}")
def iter_catalog_tasks(reg: dict) -> list[tuple[str, dict[str, Any]]]:
"""catalog 顶层任务列表。"""
out: list[tuple[str, dict[str, Any]]] = []
for task, tcfg in load_registry(reg).items():
entry = {
"domain": tcfg.get("domain", "dms"),
"domain_label": DOMAIN_LABELS.get(tcfg.get("domain", "dms"), tcfg.get("domain", "dms")),
"label": tcfg.get("label", task),
"type": tcfg.get("type"),
}
if tcfg.get("type") == "multi":
entry["modes"] = {}
for mode, mcfg in (tcfg.get("modes") or {}).items():
entry["modes"][mode] = {
"label": mcfg.get("label", mode),
"type": mcfg.get("type"),
"nc": mcfg.get("nc"),
"names": mcfg.get("names"),
"packs": [],
"class_counts": {},
}
else:
entry["nc"] = tcfg.get("nc")
entry["names"] = tcfg.get("names")
entry["packs"] = []
entry["class_counts"] = {}
out.append((task, entry))
return out
def map_report_task(report_name: str) -> tuple[str, str | None]:
if report_name in REPORT_TASK_ALIASES:
return REPORT_TASK_ALIASES[report_name]
return report_name, None
def task_defs_for_pending(reg: dict) -> dict[str, Any]:
"""平台 pending API 的 task_defs。"""
defs: dict[str, Any] = {}
for task, tcfg in load_registry(reg).items():
if tcfg.get("type") == "multi":
defs[task] = {
"type": "multi",
"domain": tcfg.get("domain", "dms"),
"label": tcfg.get("label", task),
"modes": {
m: {
"type": mc.get("type"),
"nc": mc.get("nc"),
"names": mc.get("names"),
"task_dir": f"{tcfg.get('task_dir', task)}/{mc.get('subdir', m)}",
}
for m, mc in (tcfg.get("modes") or {}).items()
},
}
else:
defs[task] = {
"type": tcfg.get("type"),
"domain": tcfg.get("domain", "dms"),
"label": tcfg.get("label", task),
"nc": tcfg.get("nc"),
"names": tcfg.get("names"),
"task_dir": tcfg.get("task_dir", task),
}
return defs