feat: 合并 Docker Compose、标注表格优化与部署文档
将 platform + CVAT 合并为单文件 docker-compose.yml,完善 .env 与 init/dev_up 脚本; 新增 docs/DEPLOY.md 与更新 README 以支持新机器部署;含数据湖示例、车队地图、 紧凑表格 UI、ADAS det_7cls 路径与批次台账等近期改动。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1098,15 +1098,22 @@ def register_batch(
|
||||
|
||||
meta_path = write_meta(batch_dir, data)
|
||||
invalidate_catalog_cache()
|
||||
batch_row = enrich_batch(
|
||||
batch_dir,
|
||||
project=project,
|
||||
task=task,
|
||||
pack=pack,
|
||||
batch=batch,
|
||||
location=location,
|
||||
)
|
||||
try:
|
||||
from as_platform.labeling.batch_index import upsert_batch_dict
|
||||
|
||||
upsert_batch_dict(batch_row)
|
||||
except Exception:
|
||||
pass
|
||||
return {
|
||||
"ok": True,
|
||||
"meta_path": str(meta_path),
|
||||
"batch": enrich_batch(
|
||||
batch_dir,
|
||||
project=project,
|
||||
task=task,
|
||||
pack=pack,
|
||||
batch=batch,
|
||||
location=location,
|
||||
),
|
||||
"batch": batch_row,
|
||||
}
|
||||
|
||||
@@ -425,6 +425,11 @@ def promote_candidate_to_inbox(
|
||||
raise ValueError(f"任务 {task} 为 multi,须指定 mode(如 batch_0516)")
|
||||
dest = _resolve_dms_inbox_dest(root, reg, task, eff_mode, batch_name)
|
||||
reg_batch = eff_mode or batch_name
|
||||
elif project == "adas":
|
||||
if not task:
|
||||
raise ValueError("ADAS 晋级需要 task(det_7cls 或 cuboid_7cls)")
|
||||
dest = root / "inbox" / task / batch_name
|
||||
reg_batch = batch_name
|
||||
else:
|
||||
dest = root / "inbox" / batch_name
|
||||
reg_batch = batch_name
|
||||
@@ -439,7 +444,7 @@ def promote_candidate_to_inbox(
|
||||
row = enrich_batch(
|
||||
dest,
|
||||
project=project,
|
||||
task=task if project == "dms" else None,
|
||||
task=task,
|
||||
pack=None,
|
||||
batch=reg_batch,
|
||||
location="inbox",
|
||||
@@ -482,6 +487,12 @@ def promote_candidate_to_inbox(
|
||||
db.flush()
|
||||
|
||||
invalidate_catalog_cache()
|
||||
try:
|
||||
from as_platform.labeling.batch_index import upsert_batch_dict
|
||||
|
||||
upsert_batch_dict({**meta, "path": str(dest), "location": "inbox"})
|
||||
except Exception:
|
||||
pass
|
||||
return {
|
||||
"ok": True,
|
||||
"candidate_id": candidate_id,
|
||||
|
||||
@@ -6,20 +6,35 @@ from pathlib import Path
|
||||
|
||||
from as_platform.data.promote.base import PackPromoteAdapter, PromoteContext, PromoteResult
|
||||
from as_platform.data.promote.manifest import refresh_dms_yaml
|
||||
from as_platform.data.promote.validate.dms_yolo import validate_dms_task
|
||||
from as_platform.data.promote.validate.dms_yolo import validate_dms_inbox_batch
|
||||
|
||||
_DMS_SCRIPTS = Path(__file__).resolve().parents[4] / "datasets" / "dms" / "scripts"
|
||||
if str(_DMS_SCRIPTS) not in sys.path:
|
||||
sys.path.insert(0, str(_DMS_SCRIPTS))
|
||||
|
||||
|
||||
def _resolve_promote_pack_dir(project_root: Path, pack: str) -> Path:
|
||||
"""解析 pack 目录;损坏的 workspace 软链则回退为 HSAP 内真实目录。"""
|
||||
candidate = project_root / "packs" / pack
|
||||
if candidate.is_symlink():
|
||||
try:
|
||||
resolved = candidate.resolve()
|
||||
if resolved.is_dir():
|
||||
return resolved
|
||||
except OSError:
|
||||
pass
|
||||
candidate.unlink()
|
||||
candidate.mkdir(parents=True, exist_ok=True)
|
||||
return candidate
|
||||
|
||||
|
||||
class DmsYoloPromoteAdapter(PackPromoteAdapter):
|
||||
project = "dms"
|
||||
|
||||
def validate(self, ctx: PromoteContext) -> list[str]:
|
||||
if ctx.skip_validate:
|
||||
return []
|
||||
return validate_dms_task(ctx.task)
|
||||
return validate_dms_inbox_batch(ctx.batch_dir)
|
||||
|
||||
def promote(self, ctx: PromoteContext) -> PromoteResult:
|
||||
from ingest_incremental import promote_inbox_batch
|
||||
@@ -34,8 +49,7 @@ class DmsYoloPromoteAdapter(PackPromoteAdapter):
|
||||
warnings=[f"batch_dir missing: {ctx.batch_dir}"],
|
||||
)
|
||||
|
||||
pack_dir = ctx.project_root / "packs" / ctx.pack
|
||||
pack_dir.mkdir(parents=True, exist_ok=True)
|
||||
pack_dir = _resolve_promote_pack_dir(ctx.project_root, ctx.pack)
|
||||
|
||||
detail = promote_inbox_batch(
|
||||
root=ctx.project_root,
|
||||
@@ -46,7 +60,7 @@ class DmsYoloPromoteAdapter(PackPromoteAdapter):
|
||||
dry_run=ctx.dry_run,
|
||||
refresh=ctx.refresh and not ctx.dry_run,
|
||||
)
|
||||
if ctx.refresh and not ctx.dry_run and not ctx.skip_validate:
|
||||
if ctx.refresh and not ctx.dry_run:
|
||||
refresh_dms_yaml(task=ctx.task)
|
||||
|
||||
added = int(detail.get("added") or 0)
|
||||
|
||||
@@ -8,6 +8,17 @@ from pathlib import Path
|
||||
from as_platform.config import WORKSPACE
|
||||
|
||||
|
||||
def validate_dms_inbox_batch(batch_dir: Path) -> list[str]:
|
||||
"""Promote 前校验单个 inbox 批次(不要求 pack 目录已存在)。"""
|
||||
from as_platform.labeling.batch_stage import batch_has_yolo_labels
|
||||
|
||||
if not batch_dir.is_dir():
|
||||
return [f"batch_dir missing: {batch_dir}"]
|
||||
if not batch_has_yolo_labels(batch_dir):
|
||||
return [f"no YOLO labels under {batch_dir} (先执行 labeling_export)"]
|
||||
return []
|
||||
|
||||
|
||||
def validate_dms_task(task: str | None) -> list[str]:
|
||||
cmd = [sys.executable, str(WORKSPACE / "scripts" / "validate_dms_tasks.py")]
|
||||
if task:
|
||||
|
||||
Reference in New Issue
Block a user