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:
2026-06-03 11:40:21 +08:00
parent 7c43b44c57
commit e72bc061c5
5487 changed files with 979207 additions and 6197 deletions

View File

@@ -0,0 +1,78 @@
# 平台批次台账与审批入湖
主路径已替代飞书多维表格 API 拉取。飞书表仅作可选人工备忘(`FEISHU_BITABLE_SYNC_ENABLED=0`)。
相关文档:[LABELING_SOP.md](./LABELING_SOP.md) §5.2 · Pilot[PILOT_BATCH.md](./PILOT_BATCH.md)
## 角色分工
| 角色 | 操作 |
|------|------|
| 协调员labeler | HSAP → **批次台账**:新建/编辑申请 → **提交审批** |
| 数据平台reviewer | **审核管理**:动作「数据送标入湖」→ 通过/驳回 |
| 标注协调 | 入湖后在 **送标工作台 → 待送标** 开 Campaign |
权限:`write:delivery_submit`(提交)、`read:deliveries`(查看台账)、`write:approval_review`(批准入湖)。
## 状态说明
| 状态 | 含义 |
|------|------|
| `draft` | 草稿,可编辑 |
| `pending_review` | 已提交,待审核 |
| `rejected` | 驳回,可改后再提交 |
| `ingesting` | 审批通过Job 执行 analyze + promote |
| `in_lake` | 已入 inbox可送标 |
| `ingest_failed` | 入湖失败,见 `error_message` |
## 表单字段(对齐原飞书列)
- **项目 / 任务 / 子模式 / 批次名**:与 inbox 规则一致;单层任务 `mode` 可空;**批次名 ≠ 任务名**。
- **数据路径**:容器内或 NAS **绝对路径**,提交前须存在且含图像。
- **来源类型、车辆/场景、采集起止、预估张数、备注**:可选。
API`GET/POST/PATCH /api/v1/deliveries``POST /api/v1/deliveries/{id}/submit`
## 与 Pilot `20260525_pilot` 联调
1. 确认 inbox 已有数据:`/data/hsap/datasets/dms/inbox/addw/20260525_pilot`(见 [PILOT_BATCH.md](./PILOT_BATCH.md))。
2. **批次台账** 新建:项目 `dms`,任务 `addw`,批次 `20260525_pilot`,路径填上列目录。
3. **提交审批****审核管理** 批准 → 状态 `in_lake``inbox_path` 回写。
4. **送标工作台** 待送标可见该批次 → 开始标注。
演示已入湖批次:可在库中直接将记录标为 `in_lake` 并填 `inbox_path`,跳过审批。
## 部署注意
- 升级后重启 platform/worker`docker compose restart platform worker`,以便 `create_all` 创建 `batch_deliveries` 并种子权限。
- 飞书同步保持关闭:`manifests/feishu.env``FEISHU_BITABLE_SYNC_ENABLED=0`
## 前端构建(必做)
HSAP 页面来自 Label Studio 工程编译后的静态包,**改 TSX 后必须重建**才会在 `http://127.0.0.1:8787` 生效:
```bash
bash /home/chengfanglu/DATA/HSAP/scripts/build_hsap_ls_ui.sh
cd /home/chengfanglu/DATA/HSAP && docker compose restart platform
```
浏览器访问后请 **强制刷新**Ctrl+Shift+R。开发热更新可选用`docker compose --profile dev up`(见 `docker-compose.yml` 注释)。
## UI 闭环路径Phase A
| 步骤 | 页面 | 说明 |
|------|------|------|
| 1 | 批次台账 `/deliveries` | 列表有进度条;提交后状态「待审核」 |
| 2 | 审核管理 `/audit` | 动作「数据送标入湖」;详情页可看待审 Job 与 inbox_path |
| 3 | 送标工作台 `/labeling` | 待送标见批次;已入湖台账显示申请 ID |
| 4 | 进行中标注 | 开 Campaign / 画布 |
协调员登录默认进入 **批次台账**;审核员默认进入 **审核管理**(见 `defaultLanding.ts`)。
## 验收清单
- [ ] 协调员创建并提交申请
- [ ] 审核员看到「数据送标入湖」并批准Job 成功
- [ ] `GET /api/v1/deliveries` 显示 `in_lake``inbox_path` 正确
- [ ] 送标工作台可见批次并可开 Campaign
- [ ] 驳回后可编辑再提交

View File

@@ -0,0 +1,46 @@
# HSAP UI 浏览器验收记录
API 自动化:`bash HSAP/scripts/smoke_platform_api.sh`(含 labeling + fleet health
## 自动化结果(最近一次)
| 检查项 | 命令/路径 | 预期 |
|--------|-----------|------|
| Health | `GET /api/v1/health` | `status: ok` |
| 标注批次 | `GET /api/v1/labeling/batches` | `items.length >= 1`(当前约 7 |
| Bootstrap / export / ml | `smoke_platform_api.sh` | exit 0`ALL_OK` |
| 车队配置 | `GET /api/v1/fleet/map-config` | `enabled: true`(需 `AS_FLEET_MAP_ENABLED` |
| 车队 live | `GET /api/v1/fleet/live` | `vehicles.length >= 1`(演示约 3 |
详细缺口见 [QA_GAP_REPORT.md](QA_GAP_REPORT.md)。
## 浏览器手动清单
- [ ] 登录 `http://127.0.0.1:8787`(强刷 Ctrl+Shift+R
- [ ] **送标工作台**Tab 待送标/标中/待入库/上传入湖;待送标「开始标注」;待入库选 pack 提交审核;上传 promote 后回待送标;见 [LABELING_SOP.md](LABELING_SOP.md)
- [ ] **标注任务**:可见 `dam/batch_0516` 等批次;表头有 **进度**、**分包** 列;展开行可 **均分未分配任务**
- [ ] **送标工作台·标中**:左侧列表有进度/分包列;右侧 **任务分配** 面板(协调员)
- [ ] **分包验收**:协调员对 batch 均分给 2 人 → 各员画布 task 数约一半、互不重叠A 保存后 A 的 completed +1
- [ ] **批次台账**:导航「批次台账」可见;新建申请(项目/任务/批次名/数据路径)→ 提交审批;`GET /api/v1/deliveries` 状态 `pending_review`
- [ ] **审批入湖**:审核管理出现「数据送标入湖」,详情展示结构化字段(非仅 JSON批准后 Job 成功,台账 `in_lake``inbox_path` 正确
- [ ] **送标衔接**:送标工作台待送标可见该批次;驳回后可编辑再提交(见 [BATCH_DELIVERY_OPS.md](BATCH_DELIVERY_OPS.md)
- [ ] (可选)飞书表仅人工备忘:`FEISHU_BITABLE_SYNC_ENABLED=0`,不依赖 `bitable/sync`
- [ ] **画布**`dam_15cls.xml`inbox 有图时可保存;内部标注员顶栏 **我的进度**;协调员可切 **全部/仅我的**
- [ ] **Jobs**:导出后出现 `labeling_export`
- [ ] **审核**列表、详情、lightbox缩略图含 YOLO 叠加框
- [ ] **车队**瓦片可见地图左、CRUD 右(宽屏);重置演示后有蓝点
- [ ] **训练**:发起 + 详情 + registry
- [ ] **数据目录**:视角「训练包」下先选 `dms_v1` 再选任务dam/addw_face 等);「采集批次」下选任务再选 0516 批次;两种视角图表数值可不同;`dms_v1`+`dam` 刷新后框宽高散点非空
## 已知缺口
- **标注 tasks 为空**inbox 目录无图片时正常;往 registry inbox 路径放样例 jpg 后再测
- **瓦片灰屏**:设置 `AS_MAP_TILE_PROVIDER=osm` 或配置 `AS_AMAP_KEY`UI 已支持瓦片失败自动切 OSM
## 环境变量(车队地图)
```bash
AS_FLEET_MAP_ENABLED=1
AS_MAP_TILE_PROVIDER=gaode # 或 osm
AS_AMAP_KEY= # 高德 key可选
```

65
docs/DATASET_TASKS.md Normal file
View File

@@ -0,0 +1,65 @@
# HSAP 数据目录 · 任务划分
## 域domain
| domain | 含义 | 平台任务 ID |
|--------|------|-------------|
| **dms** | 舱内驾驶员监控(人脸/疲劳/分心/DAM | `ddaw`, `addw`, `addw_face`, `dam`(含 0516/0417 两批次) |
| **forward** | 前向 ADAS · 交通标志 | `forward`(含检测 + 细分类两种子模式) |
数据目录页任务下拉按域分组显示;**forward** 选中后需再选 **子模式**`detect`(粗检测 4 类)或 `classify`(细分类 ~92 类)。
## DAM 任务 `dam`(合并原 dam / dam_0417
同一套 **15 类** 驾驶员监控检测face、眼嘴、眼镜/烟/手机、driver 等),仅采集批次不同:
| 子模式 | 原目录 | 说明 |
|--------|--------|------|
| **batch_0516** | `dam/`dam_0516 | 约 5k 图 |
| **batch_0417** | `dam_0417/` | 约 2.5k 图 |
训练 yaml`dam__batch_0516.yaml``dam__batch_0417.yaml`。别名:`dam_0417``dam` + `batch_0417`
```bash
python datasets/dms/scripts/migrate_dam_layout.py \
--pack-dir /path/to/packs/dms_v1 --dms-root /path/to/datasets/dms
```
## 前向任务 `forward`(合并原 isa / isa_class
| 子模式 | 原任务 ID | 目录(包内) | 说明 |
|--------|-----------|--------------|------|
| **detect** | `isa` | `forward/detect/` | YOLO 检测indicative / prohibitory / warning / vehicle |
| **classify** | `isa_class` | `forward/classify/` | 文件夹分类,具体牌型 |
训练 yaml`manifests/yaml_active/forward__detect.yaml``forward__classify.yaml`
训练命令示例:
```bash
SUBMODE=detect ./scripts/train.sh forward full
SUBMODE=classify ./scripts/train.sh forward full
```
入库 inbox
- `datasets/dms/inbox/forward/detect/<batch>`
- `datasets/dms/inbox/forward/classify/<batch>`
## 迁移旧目录
若数据仍在 `packs/dms_v1/isa``isa_class`
```bash
python datasets/dms/scripts/migrate_forward_layout.py \
--pack-dir /path/to/packs/dms_v1 \
--dms-root /path/to/datasets/dms
```
默认创建符号链接,不搬动原数据。完成后执行 `refresh_yaml.py` 并在平台 **数据目录** 点刷新。
## 兼容别名
脚本与 API 仍接受旧 ID会自动映射
- `isa``forward` + `detect`
- `isa_class``forward` + `classify`

36
docs/DATA_LAKE_GAP.md Normal file
View File

@@ -0,0 +1,36 @@
# 数据入湖清单 vs HSAP 实现差距
对照 [DATA_LAKE_CHECKLIST.md](DATA_LAKE_CHECKLIST.md) 阶段 AE 与当前 `as_platform` 能力。
| 阶段 | 清单要求 | HSAP 现状 | 差距 |
|------|----------|-----------|------|
| **A 上传接入** | zip/目录上传、进度、candidate_id | `POST /api/v1/data/upload/file``DatasetCandidate` 表;**analyzed 后可 `POST .../promote-inbox`** | 无统一 `lake/staging/` 路径约定;进度条依赖前端 upload |
| **A** | staging 区隔离 | 候选写入 DB + 磁盘路径 | 未强制 `lake/staging/<project>/<candidate_id>/` 目录规范 |
| **B 自动分析** | 上传后异步 quality worker | `inspect-upload`、部分 catalog 刷新 | 无独立 QualityWorker JobDMS/Lane 报告未统一落 `quality.json` |
| **B** | DMS/Lane 指标 | Catalog、`catalogDms`、validate 脚本 | Catalog 已展示采样指标(条/饼/竖柱/雷达/划分柱/散点/密度);**非**上传触发全自动 |
| **C 审核流** | 自动提交审核单 | `approvals``submit` API | 已有;与送标 register 联动 |
| **C** | 通过/驳回规范 | `approve`/`reject` | 已有 |
| **D 版本入湖** | 审核后晋级 curated | `ingest_incremental``register_batch` stage | **主路径在 ml.py/as.py**,非 candidate→lake 闸门 |
| **D** | catalog 索引更新 | `GET /catalog` refresh | 已有 |
| **E 运维安全** | 失败可读、重试 | Job 队列、approval 备注 | 部分;上传重试靠前端 |
## 已有可复用组件
- 数据候选:`platform/as_platform/db/models.py``DatasetCandidate`
- 上传 API`server.py``upload/file``inspect-upload`
- 审核:`audit/queue.py``/api/v1/approvals/*`
- 入湖 CLI`as.py build` / `add` + `ingest_incremental.py`
## 建议下一里程碑(未在本汇总 plan 全量实现)
1. 统一 staging 根目录与环境变量 `AS_LAKE_STAGING_ROOT`
2. 上传完成 → 入队 `quality_analyze` Job → 写 `quality.json`
3. 审核通过后调用现有 `ingest_incremental` 并更新 `batch.meta` stage
## 验收脚本
```bash
bash HSAP/scripts/smoke_manifest_alignment.sh
bash HSAP/scripts/smoke_platform_api.sh
curl -sS -H "Authorization: Bearer $TOKEN" http://127.0.0.1:8787/api/v1/pending/gates
```

View File

@@ -143,6 +143,13 @@ HSAP/
3. upsert 用户并签发 JWT
4. 前端保存 token后续所有 API 带 `Bearer`
### 5.4 飞书多维表格(内网出站)
- 操作:[FEISHU_BITABLE_OPS.md](./FEISHU_BITABLE_OPS.md);开发:[FEISHU_INTEGRATION_DEV.md](./FEISHU_INTEGRATION_DEV.md)
- 配置:`manifests/feishu.env``FEISHU_BITABLE_APP_TOKEN``FEISHU_BITABLE_TABLE_ID`
- API`GET/POST /api/v1/integrations/feishu/bitable/*``FEISHU_BITABLE_SYNC_ENABLED=1` 时后台轮询回写
- 验证:`bash scripts/feishu_bitable_verify.sh`
---
## 6. 审核与任务执行链路
@@ -179,7 +186,7 @@ HSAP/
关键页面:
- 登录页(飞书/开发登录)
- 送标工作台
- 送标工作台(操作 SOP 见 [LABELING_SOP.md](./LABELING_SOP.md)
- 数据目录
- 审核管理
- Job 监控

261
docs/DEVELOPMENT_ROADMAP.md Normal file
View File

@@ -0,0 +1,261 @@
# HSAP 开发计划2026 Q2
本文是 HSAPHuaxu Sentinel Active Safety Platform的**分期开发路线图**,与现有文档对齐:
- 标注验收:[PHASE_ROLLOUT_DMS.md](./PHASE_ROLLOUT_DMS.md)
- 送标 SOP[LABELING_SOP.md](./LABELING_SOP.md)
- 缺口跟踪:[QA_GAP_REPORT.md](./QA_GAP_REPORT.md)、[DATA_LAKE_GAP.md](./DATA_LAKE_GAP.md)
- 本地开发:[DEVELOPMENT_GUIDE.md](./DEVELOPMENT_GUIDE.md)
---
## 1. 架构原则(维持当前技术栈)
**结论:现阶段不引入 RabbitMQ / KafkaDB + thread/worker + Redis 足够。**
| 层级 | 选型 | 用途 |
|------|------|------|
| API | FastAPI + Label Studio Editor 壳 | 送标 / 标注 / 审核 / 训练 / 车队 |
| 持久化 | PostgreSQL生产/ SQLite本机 | Job、Campaign、用户、审批 |
| 异步 Job | `thread`(本机)/ `worker`Docker | 导出、build、训练、入湖分析 |
| Redis | List 队列 + Pub/Sub + 标注锁 | 仅 worker 模式强依赖;本机可跳过 |
| 训练/数据 | `as.py` + DMS/Lane registry | inbox → pack → train |
```mermaid
flowchart TB
subgraph dev [本机开发 thread 模式]
RunLocal[run_local.sh]
ThreadExec[daemon Thread 跑 Job]
RunLocal --> ThreadExec
end
subgraph prod [生产 Docker worker 模式]
Platform[platform :8787]
RedisQ[Redis as:job_queue]
Worker[worker.py]
Platform -->|push_job| RedisQ
RedisQ -->|brpop| Worker
end
subgraph future [未来可选 触发条件见 §6]
MQ[RabbitMQ / Kafka]
MQ -.->|替换 Redis List| RedisQ
end
```
**环境对照**
| 场景 | 启动方式 | Job 执行 | Redis |
|------|----------|----------|-------|
| 本机快速开发 | `bash scripts/run_local.sh` | 进程内 thread | 可选(锁回退 memory |
| 联调 / 演示 | `docker compose up -d platform worker redis postgres` | 独立 worker | 必须 |
| 训练机 | 仅 `worker.py` + Redis | GPU 节点消费队列 | 必须 |
---
## 2. 阶段总览
| 阶段 | 时间盒 | 目标 | 退出标准 |
|------|--------|------|----------|
| **A** 标注闭环 | 12 周 | dam/addw/addw_face 画布→导出→入库可 E2E | P0+P1 清单全绿 |
| **B** 生产运行态 | 1 周 | Docker worker + Redis 稳定跑导出/训练 Job | smoke + Jobs 页成功 |
| **C** 数据入湖 | 2 周 | 批次台账、飞书、MinIO 主路径打通 | DATA_LAKE checklist AE |
| **D** 扩展任务 | 23 周 | forward / lane 画布 + 导出 | P2 清单 |
| **E** 体验与治理 | 持续 | 关键点 UX、审计、权限、文档 | 标注员可独立操作 |
| **F** 架构演进 | 按需 | MQ / 多 worker / 监控 | 见 §6 触发条件 |
---
## 3. 阶段 A标注闭环当前最高优先级
### A.1 已完成(代码侧)
- [x] `dms_pose.xml`face + 37 关键点)
- [x] `export_ls_to_yolo.py`detect 5 字段 / pose 116 字段)
- [x] `runner.py` 导出前转换 + `as.py build`
- [x] `batch_stage.py` 有 txt 才设 `returned`
- [x] `test_export_ls_to_yolo.py` 单元测试
- [x] `run_local.sh` / `wait_for_db.py` thread 模式跳过 Redis 等待
### A.2 待完成(验收)
| # | 任务 | 负责人建议 | 验收 |
|---|------|------------|------|
| A2.1 | inbox 放入样例图dam/addw_face 各 ≥3 张) | 数据/协调员 | `GET .../tasks` 非空 |
| A2.2 | 浏览器dam 检测框标注保存 | 标注员 | `labels/ls_annotations/*.json` |
| A2.3 | 浏览器addw_face 框 + 关键点保存 | 标注员 | JSON 含 `rectanglelabels` + `keypointlabels` |
| A2.4 | 导出 Job → `labels/train/*.txt` | 协调员 | dam 5 字段addw_face 116 字段 |
| A2.5 | 提交入库审核 → build 进 pack | 工程师 | 数据目录可见新 sources |
| A2.6 | 审核预览叠加框 + 关键点 | 审核员 | preview 缩略图正确 |
| A2.7 | 更新 QA_GAPexport 已对接) | 开发 | 文档与代码一致 |
**命令**
```bash
# 离线
python3 /home/chengfanglu/DATA/HSAP/datasets/dms/scripts/test_export_ls_to_yolo.py
# 本机平台
cd /home/chengfanglu/DATA/HSAP && bash scripts/run_local.sh
# API 冒烟(平台起来后)
bash /home/chengfanglu/DATA/HSAP/scripts/smoke_labeling_api.sh
```
### A.3 addw_face 专项增强可选A 通过后)
| 任务 | 说明 |
|------|------|
| 关键点语义名 | 在 `addw_face_37.yaml``display_name`(若有外协规范) |
| 标注进度 | 进度 API 增加「已标 kpt 数/37」 |
| 多脸策略 | 文档化 bbox-关键点分配规则;必要时 UI 约束单脸 |
---
## 4. 阶段 B生产运行态worker + Redis
### B.1 基础设施
```bash
cd /home/chengfanglu/DATA/HSAP
docker compose up -d postgres redis platform worker
# .env: AS_REDIS_PORT=6380 → run_local 已自动对齐
```
| 任务 | 说明 |
|------|------|
| B1.1 | 确认 `AS_JOB_EXECUTOR=worker` 在 compose 内生效 |
| B1.2 | 导出/训练 Job 仅 worker 消费platform 不阻塞 |
| B1.3 | `/api/v1/health``redis_connected=true` |
| B1.4 | 标注锁走 Redis多标注员并行时不抢标 |
### B.2 可观测性(轻量)
| 任务 | 说明 |
|------|------|
| B2.1 | Jobs 页failed Job 展示 `export_convert` / stderr 摘要 |
| B2.2 | `manifests/trace_log.jsonl` 关键 span 文档化 |
| B2.3 | worker 日志:`执行 Job job-xxx` 与 platform 对齐 |
### B.3 本机 vs Docker 文档
在 [DEVELOPMENT_GUIDE.md](./DEVELOPMENT_GUIDE.md) 增加一节:
- 日常改代码 → `run_local.sh`thread无 Redis
- 验证导出/训练链路 → `docker compose up worker`
- 禁止混用thread 模式提交的 Job 不会被 Docker worker 消费(同一 Redis 时可消费,但 DB 需一致)
---
## 5. 阶段 CE数据入湖与任务扩展
### C. 数据入湖(见 DATA_LAKE_GAP.md
- 批次台账 → 审批入湖 → inbox 出现在送标工作台
- 飞书多维表格同步(可选,`FEISHU_BITABLE_SYNC_ENABLED=0` 可关)
- MinIO staging`docker compose --profile minio up`
- 上传 ZIP → 分析 → promote inbox
### D. forward / laneP2
| 任务 | 文件/动作 |
|------|-----------|
| `forward_4cls.xml` / `forward_cls.xml` | 补 label_studio 模板 |
| `lane_ufld_mask.xml` + `export_ls_to_lane_gt.py` | **已实现**BrushLabels → PNG + train_gt.txt |
| registry profile `lane__lane_v1` | 导出 `lane_gt_txt` + `build lane` |
### E. 体验与治理
- 37 关键点侧栏分组Header 分块)
- 角色权限:`internal_labeler` / `labeler` / `reviewer` 回归
- 外协 ZIP`import-vendor` 与平台标注双轨说明([VENDOR_RETURN.md](./VENDOR_RETURN.md)
- 前端变更后:`bash scripts/build_hsap_ls_ui.sh` + 强刷
---
## 6. 阶段 F何时引入 MQ暂不实施
**当前不引入。** 满足以下 **任意 2 条** 时再立项:
1. Job 入队 > 10/s sustained或 Redis List 延迟明显
2. 需要优先级队列(训练插队、导出低优先级)
3. 需要死信队列 + 自动重试(现仅靠 Job 表 failed + 人工重跑)
4. 多机房 / 多 worker 池Redis 单点成为瓶颈
5. 消息审计与回放成为合规要求
**迁移策略(预留,不改 API**
- 保持 `enqueue_job` / `Job` 表不变
-`redis/bus.py``push_job` / `pop_job` 抽象为 `JobTransport` 接口
- 实现 `RedisListTransport`(现逻辑)与 `RabbitMQTransport`(新)
- 事件 Pub/Sub 可迁至 MQ fanout或保留 Redis
---
## 7. 里程碑与依赖
```mermaid
gantt
title HSAP 开发里程碑(示意)
dateFormat YYYY-MM-DD
section 标注闭环
A_inbox样例与浏览器E2E :a1, 2026-05-27, 7d
A_export_build验收 :a2, after a1, 5d
section 生产态
B_docker_worker稳定 :b1, after a2, 5d
section 入湖
C_批次台账与promote :c1, after a1, 14d
section 扩展
D_forward_lane :d1, after a2, 14d
```
**硬依赖**
- A 完成前:不启动 forward/lane 大改
- B 与 A 可并行Docker 环境给工程师,标注 E2E 给协调员
- C 依赖 A 至少 dam 一条链路通
---
## 8. 风险与对策
| 风险 | 对策 |
|------|------|
| inbox 无图tasks 为空 | A2.1 放样例PILOT_BATCH 文档 |
| 本机无 Redis误以为平台坏了 | 已改 thread 跳过等待;文档说明 |
| Redis 端口 6379 vs 6380 | `run_local.sh``.env` AS_REDIS_PORT |
| 37 点 UX 差、漏标 | maxUsages=1后续进度 KPI |
| 关键点顺序与历史 pack 不一致 | 严格 `addw_face_37.yaml`;导出单测 |
| thread 与 worker 混用同一 DB | 开发指南写明一种 Job 执行器 |
| QA_GAP 过时 | A2.7 同步更新 |
---
## 9. 近期两周行动清单(可执行)
**第 1 周**
1. 协调员dam/batch_0516、addw_face inbox 各放样例图
2. 标注员:各标 2 张,确认保存 JSON
3. 开发:`run_local.sh` 或 compose 起 platform跑通 export → build
4. 全员:勾选 [BROWSER_QA_CHECKLIST.md](./BROWSER_QA_CHECKLIST.md)
**第 2 周**
1. compose 起 worker + redis重复 export 验证 Job 在 worker 日志出现
2. addw_face 导出 txt 抽 1 条对照 `dms_v1/addw_face` 历史样本116 字段)
3. 提交入库审核 → 数据目录刷新
4. 更新 QA_GAP / PHASE_ROLLOUT 勾选状态
---
## 10. 文档维护
| 文档 | 更新时机 |
|------|----------|
| PHASE_ROLLOUT_DMS.md | 每完成一个 pilot 勾选 |
| QA_GAP_REPORT.md | export/ML/入湖状态变化时 |
| DEVELOPMENT_ROADMAP.md本文 | 阶段切换或 MQ 触发条件变化时 |
| LABELING_SOP.md | 标注流程或格式变更时 |
---
*版本2026-05-27 · 与关键点接入、thread/worker 架构讨论对齐*

170
docs/FEISHU_BITABLE_OPS.md Normal file
View File

@@ -0,0 +1,170 @@
# 飞书多维表格操作手册(内网)
> **主路径**:批次登记与入湖已改为 HSAP **批次台账 + 审核入湖**[BATCH_DELIVERY_OPS.md](./BATCH_DELIVERY_OPS.md))。飞书表仅作可选人工备忘;默认 `FEISHU_BITABLE_SYNC_ENABLED=0`,勿再依赖 API 拉表。
配套开发说明:[FEISHU_INTEGRATION_DEV.md](./FEISHU_INTEGRATION_DEV.md)
交接模板:[FEISHU_DEV_HANDOFF.md](./FEISHU_DEV_HANDOFF.md)
对象暂存(可选):[MINIO_STAGING.md](./MINIO_STAGING.md)
联调小样批次:[PILOT_BATCH.md](./PILOT_BATCH.md)
内网 **不要** 配置多维表格「自动化 → Webhook → HSAP URL」。由 HSAP 定时 **出站** 回写表格(`FEISHU_BITABLE_SYNC_ENABLED=1`)。
---
## 1. 建群
| 项 | 内容 |
|----|------|
| 群名 | **HSAP·数据标注协作** |
| 成员 | 协调员、内部标注员、数据/运维 |
| 群公告 | ① 多维表格链接 ② 新批次先建表行 ③ 批次名 ≠ 任务名 ④ 内标须飞书登录 HSAP 至少一次 ⑤ `HSAPhttp://<内网地址>:8787运维补充` |
外协另建 **HSAP·外协回传**(不进主表)。
---
## 2. 建多维表格
1. 群内 → **多维表格** → 新建
2. Base**HSAP 数据批次台账**
3. 表 1**数据批次台账**(主表;采集明细表 Phase C 再做)
记下并填入 [FEISHU_DEV_HANDOFF.md](./FEISHU_DEV_HANDOFF.md)
- **app_token**URL `/base/` 后一串
- **table_id**URL 参数 `table=`(无则交开发用 API 查询)
---
## 3. 主表列(中文列名,顺序建议)
### 只标 addw / ddaw / addw_face 时(推荐简化)
若台账**只登记单层 DMS 任务**(不做 dam 0516、前向 detect 等),**可以不建「子模式」列**,或在各视图里 **隐藏** 该列。匹配与落盘只靠:
**项目 + 任务 + 批次名**(路径为 `inbox/<任务>/<批次名>/`)。
任务单选里也可只保留 `ddaw` `addw` `addw_face`,减少误填。
### 人工填写
| 列名 | 类型 | 必填 | 说明 |
|------|------|------|------|
| 批次编号 | 自动编号 | 是 | 如 `001`;同步到 HSAP `external_id` |
| 项目 | 单选 `dms` `lane` | 是 | 舱内一般用 `dms` |
| 任务 | 单选 | 是 | 单层任务:`ddaw` `addw` `addw_face`;若表内也登 dam/forward 见下节 |
| 子模式 | 单选 | **可选列** | **仅**任务为 `dam`、`forward` 时填写;单层任务**不填、可删列/隐藏** |
| 批次名 | 文本 | 是 | **≠ 任务名**;勿用训练包名 `dms_v1`/`dms_v2`,用 `YYYYMMDD_场景` |
| 来源类型 | 单选 | 建议 | 采集车 / 回流标注 / 外协 / 实验集 / 其他 |
| 车型或场景 | 文本 | 否 | 溯源,如车型、工控机 |
| 采集开始 / 采集结束 | 日期 | 否 | |
| 数据路径 | 文本 | 落盘前建议填 | 内网 NAS 绝对路径;与附件二选一 |
| 数据附件 | 附件 | 否 | 仅小样本 ZIP |
| 预估张数 | 数字 | 否 | |
| 备注 | 多行文本 | 否 | 可写训练包目标,如「合并进 dms_v2」 |
| 负责人 | 人员 | 建议 | 「待我处理」视图用 |
| 标注员 | 人员多选 | 标注前 | 内标;须已飞书登录 HSAP |
| 外协方 | 文本 | 否 | 有值则走 ZIP 回传,不内标分包 |
### 何时才需要「子模式」列
| 任务 | 子模式 | inbox 示例 |
|------|--------|------------|
| `ddaw` `addw` `addw_face` | **不需要** | `inbox/addw/20250526_SE882/` |
| `dam` | 填 `batch_0516` 等 | `inbox/dam/batch_0516/` |
| `forward` | 填 `detect` / `classify` | `inbox/forward/detect/` |
不登 dam/forward 时:**删除或隐藏「子模式」列即可**HSAP 同步不依赖该列。
### 状态单选9 项)
`草稿` `待落盘` `分析中` `待送标` `标注中` `待入库` `已入库` `落盘失败` `驳回/作废`
内网用法:`待落盘` = 通知协调员去 HSAP 落盘;`分析中` 由 HSAP 回写,勿手改。
### 系统回写(勿手改)
候选ID、活动ID、Inbox路径、HSAP进度、HSAP链接、失败原因、最后同步、记录ID
---
## 4. 填写规范
1. **一批次一行**;批次名 = `YYYYMMDD_场景`(如 `20250526_SE882`**不要**用任务名或训练包名(`addw``dms_v2`)。
2. **流程**:草稿 → 填齐(路径/来源/负责人)→ **待落盘** → HSAP 落盘/送标。
3. **子模式**单层任务addw/ddaw/addw_face**一律不填**;表里没有这一列也可以。
4. **训练包**`dms_v1``dms_v2`)写在 **备注**,不要写在批次名。
5. **外协**:填外协方,标注员留空。
**示例addw无子模式列**
| 项目 | 任务 | 批次名 | 来源类型 | 车型或场景 | 数据路径 | 状态 |
|------|------|--------|----------|------------|----------|------|
| dms | addw | 20250526_SE882 | 采集车 | SE882电动垂卡 | `/NAS/.../images` | 草稿→待落盘 |
路径对照见 [LABELING_SOP.md](./LABELING_SOP.md) §5.2 飞书批次台账。
---
## 5. 视图
- **全部批次**(默认)
- **待我处理**:负责人=我,状态∈草稿/待落盘/待送标
- **标注中**:状态=标注中
日常视图建议 **隐藏**子模式若不用、记录ID、候选ID、活动ID系统列可在「全部批次」保留以便核对
---
## 6. 开放平台
1. [open.feishu.cn](https://open.feishu.cn) → 现有 HSAP 应用 → 权限:**查看、评论、编辑和管理多维表格** → 发布
2. 表格 **分享** → 添加协作者 → **企业应用****可管理**(独立 `/base/` 多维表格wiki 内嵌见 §8
3. 将 app_token、table_id 写入 `manifests/feishu.env`(见 example
验证:`bash HSAP/scripts/feishu_bitable_verify.sh`(需平台已启动且 env 已填)
---
## 7. 自检清单
- [ ] 群 + 表 + 群公告链接
- [ ] 列与 9 态状态齐全
- [ ] 3 个视图
- [ ] 应用权限 + 表格协作者
- [ ] feishu.env 已配置 BITABLE_*
- [ ] 试填 1 行草稿dms / addw / 批次名 `20250526_test`**无子模式**
- [ ] 2 名内标已飞书登录 HSAP
---
## 8. 文档库里加不上「企业应用」怎么办
知识库wiki内嵌的多维表格 + **高级权限** 时,分享里往往**只能加人/群,搜不到企业应用**。开放平台发布版本**不能**代替这一步。
**推荐(联调/生产):复制为独立多维表格**
1. 飞书左侧 **多维表格**(不要只在 wiki 里操作)→ **新建****从现有复制**
2. 命名如 `HSAP数据批次台账-API`,把列/视图按本表建好(或整库复制)。
3. 打开后地址栏为 `.../base/Basc...?table=tbl...` → 写入 `feishu.env`
- `FEISHU_BITABLE_APP_TOKEN=Basc...`
- `FEISHU_BITABLE_TABLE_ID=tbl...`
- `FEISHU_BITABLE_WIKI_NODE_TOKEN=`(留空)
4. **分享 → 添加协作者 → 企业应用「主动安全算法平台」→ 可管理**(独立 base 一般能搜到)。
5. wiki 原表可保留给人看HSAP 只同步 **-API** 这张表。群公告里可写两个链接。
**临时联调(不做飞书回写)**
- `FEISHU_BITABLE_SYNC_ENABLED=0`台账手填HSAP 仍用 inbox / 送标工作台。
- 小样 `20260525_pilot` 可照常走标注管线。
**可选**
- 所有者 **关闭高级权限** 后再试分享里加应用(不保证 wiki 仍可见应用)。
- 找飞书租户管理员确认是否允许「企业应用」担任多维表格协作者。
---
## 9. 已有 inbox 补录
`inbox/ddaw/ddaw`:新建一行,任务=ddaw批次名用新命名规则备注写「磁盘目录 ddaw」状态按实际选待送标/标注中HSAP 同步后会填 Inbox路径。

View File

@@ -0,0 +1,63 @@
# 飞书多维表格 → HSAP 开发交接单
运维/协调员填好后交给开发写入 `HSAP/manifests/feishu.env`(勿提交含密钥的 feishu.env 到 git
## 从 URL 截取(最快)
在电脑浏览器打开 **「HSAP数据批次台账」** 多维表格,看地址栏,形态类似:
```text
https://xxx.feishu.cn/base/Bascnxxxxxxxxxxxxxxxx?table=tblxxxxxxxxxxxx&view=vewxxxxxxxx
└─ APP_TOKEN ─┘ └─ TABLE_ID ─┘
```
- **APP_TOKEN** → 填 `FEISHU_BITABLE_APP_TOKEN``/base/` 后面、`?` 前面整段,常以大写 `Basc` 开头)
- **TABLE_ID** → 填 `FEISHU_BITABLE_TABLE_ID``table=` 后面、`&` 前面,以 `tbl` 开头)
**表只在知识库wiki里、没有 `/base/` 链接时:**
- **WIKI 节点** → 填 `FEISHU_BITABLE_WIKI_NODE_TOKEN``/wiki/` 后面、`?` 前面,如 `SFvfwCqskiWM0Jk0VfPcdtkun9c`
- `FEISHU_BITABLE_APP_TOKEN` 留空HSAP 会用 wiki API 解析出真正的 Basc `obj_token`
- 开放平台须开通 **wiki:node:read**(或 wiki:wiki:readonly+ **bitable:app**,并给表格 **企业应用可管理**
## 必填
| 变量 | 值 | 获取方式 |
|------|-----|----------|
| `FEISHU_BITABLE_APP_TOKEN` | | 浏览器打开台账,地址栏 `/base/``?table=` 之间整段(见下文「从 URL 截取」) |
| `FEISHU_BITABLE_TABLE_ID` | | 地址栏 `table=` 后、`&` 前,形如 `tblXXXXXXXX`;或配好 APP_TOKEN 后跑 `feishu_bitable_verify.sh` 列出 |
## 已有(登录应用)
| 变量 | 值 |
|------|-----|
| `FEISHU_APP_ID` | |
| `FEISHU_APP_SECRET` | |
## 建议
| 变量 | 值 |
|------|-----|
| `AS_FRONTEND_URL` | 内网 HSAP 根 URL`http://192.168.x.x:8787` |
| `FEISHU_BITABLE_SYNC_ENABLED` | `1` |
| `FEISHU_BITABLE_SYNC_INTERVAL_SEC` | `120` |
| `FEISHU_BITABLE_AUTO_INGEST` | `0`(内网 Phase A 保持 0 |
## 可选
| 变量 | 值 |
|------|-----|
| `FEISHU_LABELING_CHAT_ID` | 协作群 chat_id群机器人通知 |
## 表格列名
默认与 [FEISHU_BITABLE_OPS.md](./FEISHU_BITABLE_OPS.md) 中文列名一致;若飞书表改了列名,在 `feishu.env``FEISHU_BITABLE_FIELD_*` 覆盖(见 `feishu.env.example`)。
## 验证
```bash
cd HSAP
# 确保 manifests/feishu.env 已填 BITABLE_*
bash scripts/feishu_bitable_verify.sh
curl -sS -H "Authorization: Bearer $TOKEN" http://127.0.0.1:8787/api/v1/integrations/feishu/bitable/status
```

View File

@@ -0,0 +1,29 @@
# HSAP 飞书集成(内网开发说明)
操作手册:[FEISHU_BITABLE_OPS.md](./FEISHU_BITABLE_OPS.md)
## 架构
- **入站**:无 Webhook飞书云访问不到内网
- **出站**`tenant_access_token` 调用 Bitable API 回写记录
- **轮询**`FEISHU_BITABLE_SYNC_INTERVAL_SEC`(默认 120s`POST /api/v1/integrations/feishu/bitable/sync`
## 模块
| 路径 | 说明 |
|------|------|
| `platform/as_platform/integrations/feishu_bitable.py` | API 客户端、列映射 |
| `platform/as_platform/integrations/feishu_bitable_sync.py` | HSAP→表同步 |
| `platform/as_platform/integrations/feishu_bitable_ingest.py` | 待落盘→analyze→promote |
| `platform/as_platform/integrations/feishu_notify.py` | 群文本通知(可选) |
| `platform/as_platform/jobs/feishu_bitable_sync.py` | `run_sync_cycle()` 后台轮询 |
| `platform/as_platform/api/feishu_routes.py` | status / sync / ingest / backfill-hints |
## 权限
- `POST .../sync``GET .../backfill-hints`:需 `write:labeling_assign``*`
## Phase
- **A**(默认):回写 Inbox路径、HSAP进度、活动ID、状态、链接
- **B**`FEISHU_BITABLE_AUTO_INGEST=1` 时轮询「待落盘」→ analyze → promote`POST .../bitable/ingest`

81
docs/FLEET_MAP.md Normal file
View File

@@ -0,0 +1,81 @@
# HSAP 车队地图(演示 / T-Box
## 功能
- 实时查看采集车位置与当前趟次轨迹(**默认高德栅格底图**,国内可访问;可选 `AS_MAP_TILE_PROVIDER=osm`
- 演示环境默认注入 3 台**长沙**周边假车湘A轨迹由贝塞尔曲线密点生成弯道而非直线折线后台每 8 秒模拟 T-Box 推进
## 环境变量
| 变量 | 默认 | 说明 |
|------|------|------|
| `AS_FLEET_MAP_ENABLED` | `1` | 启用车队 API |
| `AS_FLEET_MOCK_SEED` | `1` | 首次启动无车辆时注入演示数据 |
| `AS_FLEET_MOCK_SIMULATE` | `1` | 后台模拟 GPS 推进 |
| `AS_FLEET_SIM_INTERVAL_SEC` | `8` | 模拟间隔秒 |
| `AS_TBOX_INGEST_TOKEN` | `hsap-demo-tbox-token` | T-Box 上报 Token |
| `AS_MAP_TILE_PROVIDER` | `gaode` | 底图:`gaode` / `osm`(国内勿用 osm易灰屏 |
| `AS_AMAP_KEY` | 空 | 高德 Web JS Key可选后续 AMap API |
## T-Box 与车辆关联(无需页面「新建车辆」)
关联键是 **`device_id`**(入库字段 `tbox_device_id`
1. 运维在 T-Box / 采集机配置 HSAP 上报地址与 `X-Tbox-Token`(环境变量 `AS_TBOX_INGEST_TOKEN`)。
2. 终端首次 `POST /api/v1/tbox/gps` 时,若该 `device_id` 不存在,平台**自动创建**车辆记录(可用 body 里的 `plate_no` 填车牌)。
3. 后续同一 `device_id` 的点写入当前 active 行程;`run_signal=end/idle` 时结束行程。
可选 body 字段:`plate_no``engineer``project``batch``speed_kmh``heading``ts`
Web 页仅用于查看地图、改车牌备注、GPX 补录;**不需要**手工新建车辆。
## T-Box 上报示例
```bash
curl -X POST http://127.0.0.1:8787/api/v1/tbox/gps \
-H "Content-Type: application/json" \
-H "X-Tbox-Token: hsap-demo-tbox-token" \
-d '{"device_id":"TBOX-001","lat":22.72,"lng":114.25,"speed_kmh":40,"run_signal":"active","plate_no":"湘A·采集01"}'
```
## 手动重播种 / 推进
需登录且具备 `write:fleet`(工程师/管理员):
- `POST /api/v1/fleet/mock/seed` — 仅在无车辆时创建演示数据
- `POST /api/v1/fleet/mock/reseed` — 清空并重新注入长沙演示数据
- `POST /api/v1/fleet/mock/tick` — 手动推进一轮模拟 GPS
切换区域后重新注入:
```bash
curl -X POST http://127.0.0.1:8787/api/v1/fleet/mock/reseed \
-H "Authorization: Bearer <你的 token>"
```
## Phase 2 API生产化
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/api/v1/tbox/gps/batch` | 批量上报(最多 100 点body `{"points":[...]}` |
| GET | `/api/v1/fleet/stream` | SSE 推送 `fleet.gps`(需 Redis + JWT |
| POST | `/api/v1/fleet/runs/import-csv` | CSV 补录:`lat,lng` 或带表头 `lat,lng,ts`;可选 `project`/`batch` 关联 DMS 批次 |
**超时关趟:** 车辆超过 10 分钟无新 GPS`RUN_IDLE_TIMEOUT_MIN`)时,`/fleet/live` 与 ingest 前会自动结束 active 行程。
## GPX 轨迹补录
`write:fleet`
```bash
curl -X POST http://127.0.0.1:8787/api/v1/fleet/runs/import-gpx \
-H "Authorization: Bearer <token>" \
-F vehicle_id=1 \
-F file=@track.gpx
```
前端车队页侧栏也可选择车辆上传 `.gpx` 文件。
## 前端
导航 **车队地图**(权限 `read:fleet`),页面每 15 秒轮询 live选中行程显示里程与里程碑地图红色点为里程碑。

74
docs/GIT_PUSH.md Normal file
View File

@@ -0,0 +1,74 @@
# HSAP 推送到 git.sanyele.com
## 为什么 SSH 一直 Permission denied
经检测,`git.sanyele.com:22` 返回的是 **Ubuntu 系统 OpenSSH**,不是 Gitea 的 Git SSH 服务。
因此:
- 在 Gitea 网页里添加的 SSH 公钥 **不会** 在 22 端口生效
- 终端问 `git@git.sanyele.com's password` 时,填 Gitea 登录密码 **永远不对**
**结论:请使用 HTTPS + Personal Access Token 推送。**
---
## HTTPS 推送步骤
### 1. 生成 Token
1. 登录 https://git.sanyele.com`Chengfang.LU@hx-electronics.com`
2. **设置****应用****生成新令牌**
3. 名称:`HSAP-push`
4. 权限:勾选 **`write:repository`**(或 repo 写权限)
5. 生成后 **复制 Token**(只显示一次)
### 2. 配置 remote已默认 HTTPS
```bash
cd ~/DATA/HSAP
git remote set-url origin https://git.sanyele.com/ChengFang.LU/HSAP.git
```
### 3. Push在系统终端不要用 Cursor 内置 Git
```bash
unset GIT_ASKPASS
export GIT_TERMINAL_PROMPT=1
git push -u origin main
```
提示时:
| 字段 | 填写 |
|------|------|
| Username | `Chengfang.LU@hx-electronics.com` |
| Password | **粘贴 Token**(不是登录密码) |
### 4. 保存凭据(可选)
```bash
git config --local credential.helper store
git push -u origin main
# 输入一次 Token 后会记住
```
---
## 若仍 401
- 确认仓库 `ChengFang.LU/HSAP` 已创建且你有写权限
- 清除错误缓存:`printf "protocol=https\nhost=git.sanyele.com\n\n" | git credential reject`
- 联系管理员确认是否 **仅允许 HTTPS**,以及 Token 权限策略
---
## 需要 SSH 时
请联系 Git 管理员确认:
- Gitea SSH 是否启用、监听端口(非 22
- 是否有内网/VPN 专用地址(如 `git-ssh.xxx.com:2222`
在管理员提供正确 SSH 地址前,请使用 HTTPS + Token。

208
docs/LABELING_SOP.md Normal file
View File

@@ -0,0 +1,208 @@
# 送标工作台 SOP
本文说明 HSAP 中 **送标** 的含义、应投递的数据形态、人员协作方式,以及与数据入湖路径的分工。配套实现见送标工作台 UI 与 `POST /api/v1/data/candidates/{id}/promote-inbox`
## 1. 送标是什么
**送标** = 把一批数据纳入标注流水线,并(通常)**开启标注活动Campaign**,阶段变为 `out_for_labeling`(送标中)。
| 阶段 | 含义 | 目录特征DMS |
|------|------|-----------------|
| `raw_pool` | 待标注原图 | 有 `images/`,无 `labels/` |
| `out_for_labeling` | 送标中 | 已 open Campaign |
| `returned` | 回传待入库 | 有 `images/` + `labels/`YOLO txt |
| `ingested` | 已入库 | 已进入 pack/sources 或 Lane gt |
**登记 meta**`更多操作` 内)只写入 `batch.meta.yaml`**不等于**已送标。
### 1.1 口语里的「送标数据」
通常指 **还没标完** 的原图批次(`raw_pool`),即 inbox 里只有 `images/`、没有 `labels/`。标完后进入 `returned`(待入库),不再算「待送标」。
## 2. 送标工作台怎么用(协调员)
侧栏 **送标工作台**`/labeling`)负责 **收件 + 派单****进行中标注**`/labeling/campaigns`)负责画布、导出、外协回传。不要两页重复找「进入标注」。
| Tab | 对应阶段 | 你要做的事 |
|-----|----------|------------|
| **待送标**(默认) | `raw_pool` | 选批次 → **开始标注** / **开始并指派** |
| **标中** | `out_for_labeling` | **继续标注**;协调员在此 **均分未分配任务**(见 §5.1 |
| **待入库** | `returned` | 选训练包 → **提交入库审核** |
| **上传入湖** | 入湖候选 | 上传 ZIP → 分析完成 → **送入 inbox**(自动切回待送标) |
页顶 **协调员三步**:进数据 → 开始标注 → 回传后提交入库。KPI 卡片可点击,与 Tab 联动。
```text
落盘 inbox 或 上传入湖
→ 待送标 Tab开始标注
→ 进行中标注:画布 / 外协回传
→ 待入库 Tab提交入库审核
→ 审核通过 → build → 数据目录
```
## 3. 两条数据路径(勿混淆)
### 路径 Ainbox 落盘(主送标路径)
运维/脚本将批次放到约定目录 → 刷新工作台 → **待送标** Tab 出现该批次。
### 路径 B页面上传 ZIP入湖候选
工作台 **上传入湖** Tab → `manifests/lake/uploads/` → 分析完成 → **送入 inbox** → 自动出现在 **待送标**
路径 B 不会在上传瞬间出现在批次表;必须 **分析完成 + 送入 inbox**(或手工落盘路径 A
## 4. 应投递什么
### 4.1 DMS 检测(如 `dam` + `batch_0516`
**待标注(原图池)**
```text
datasets/dms/inbox/dam/batch_0516/
images/train/ # 或 images/
*.jpg
```
**外协/平台已标回传**
```text
<batch>/
images/train/
labels/train/
# YOLO: class_id cx cy w h (0~1)
```
任务 id 填 registry 中的 **`dam`**0516/0417 是 **mode**,目录对应 `inbox/dam/batch_0516`(见 [datasets.registry.yaml](../datasets/dms/datasets.registry.yaml))。
### 4.2 DMS 人脸关键点(`addw_face`
画布使用 `dms_pose.xml`**face 检测框** + **37 个关键点**`kp_00``kp_36`)。保存为 Label Studio JSON`labels/ls_annotations/*.json`);导出时转为 YOLO pose 行:
```text
0 <cx> <cy> <w> <h> <kpt0_x> <kpt0_y> <kpt0_v> ... <kpt36_x> <kpt36_y> <kpt36_v>
```
**116 字段**`5 + 37×3`)。已标注点 `v=2`,未标注点 `0 0 0`。坐标LS 为图像百分比 0100YOLO 为 01。
检测任务(`dam`/`addw`/`ddaw`)导出为 5 字段 YOLO detect 行,与 pose **共用** `export_ls_to_yolo.py`
数据目录「框宽高散点」统计的是 **检测框宽高**,不是关键点坐标。
### 4.3 外协 ZIP
结构见 [VENDOR_RETURN.md](./VENDOR_RETURN.md)。在 **标注任务** 页对已有 Campaign **导入回传**,不要与送标工作台 ZIP 上传混用。
### 4.4 LaneUFLD 分割 mask
`project=lane`,任务 `lane_v1`。画布使用 **`lane_ufld_mask.xml`****BrushLabels 画笔** 沿每条车道线涂抹(`lane_1``lane_5`,对应 mask 像素值 26
标注保存为 Label Studio JSON`labels/ls_annotations/*.json`);导出时转为 UFLD 训练包:
```text
<batch>/
images/...
annotations/.../*.png # 单通道 mask0=背景2~6=各车道线
list/train_gt.txt # 两列images/...jpg annotations/...png
```
**进行中标注** 页点 **导出** 会运行 `export_ls_to_lane_gt.py`,并触发 `as.py build lane` 合并 active_packs 列表。依赖 **numpy**(与 Lane 训练环境一致)。
| 像素值 | 标签 |
|--------|------|
| 0 | 背景 |
| 2 | lane_1 |
| 3 | lane_2 |
| 4 | lane_3 |
| 5 | lane_4 |
| 6 | lane_5 |
详见 [LANE_LABELING_PLAN.md](./LANE_LABELING_PLAN.md) 与 [`workspace/lane`](../../workspace/lane/) 数据规范。
## 5. 人员分配与任务分包
| 角色 | 职责 |
|------|------|
| `labeler`(协调员) | 看待处理批次、送入 inbox、登记 meta、提交入库审核、**指派批次负责人**、**按人分包 task** |
| `internal_labeler` | 画布仅见 **分给自己的** task顶栏显示「我的进度」 |
| `vendor_labeler` | 导入外协 ZIP整包回传不走分包表 |
**批次负责人**`assigned_to_*`)表示本批 **主责协调人****分包**`labeling_task_assignments`)按 **单张图 task_id** 分给内部标注员,二者并存。
**操作顺序**
1. 协调员inbox 落盘或上传分析后 **送入 inbox**
2. 送标工作台 **待送标**:选批次 → **开始标注**open Campaign→ 可选指派批次负责人。
3. **标中** Tab 或 **进行中标注**:协调员勾选标注员 → **均分未分配任务**
4. 标注员:侧栏 **进行中标注** → 进入画布(默认 `assignee=me`)→ 保存后个人 `completed` +1。
5. 外协:**导入回传**(不走分包)。
6. 回传齐后:`returned`**提交入库审核** → 审核批准 → build/ingest → **数据目录** 刷新。
### 5.1 任务分包与进度
| 概念 | 说明 |
|------|------|
| `total_tasks` | 批次 `images/` 下图片数(与画布 task 一致) |
| `completed_tasks` | `labels/ls_annotations/*.json` 中非空 `result` 数量 |
| `assigned_tasks` | 分包表行数;未分配部分仅协调员可标(默认) |
| 进度 API | `GET /api/v1/labeling/campaigns/{id}/progress` |
| 均分 | `POST .../assign-tasks` `{ "mode": "even", "user_ids": [...] }` |
协调员在 **进行中标注** 展开行,或 **送标工作台 → 标中** 右侧详情,可查看总进度、按人表并 **均分**。内部标注员对 **未分给自己** 的 task 保存会 **403**(默认禁止抢标)。
画布:协调员可切换 **全部任务 / 仅我的**;标注员仅见自己的分包列表。待入库 Tab 建议在 `completed === total` 时再提交(软提示)。
### 5.2 批次台账与审批入湖(主路径)
操作手册:[BATCH_DELIVERY_OPS.md](./BATCH_DELIVERY_OPS.md)
| 步骤 | HSAP批次台账 + 审核) | 后续 |
|------|-------------------------|------|
| 登记 | **批次台账** 新建草稿(项目/任务/批次名/数据路径) | — |
| 入湖 | **提交审批** → 数据平台 **审核管理** 批准「数据送标入湖」 | Jobanalyze → promote → inbox |
| 送标 | 状态 **已入湖** | 送标工作台 → 待送标 → 开始标注 |
| 标注 | — | 进行中标注 → 均分 → 画布 |
| 入库 | — | 回传 → 待入库 → 提交入库审核 → build |
- 新批次:**先填台账并审批入湖**,再开 Campaign`批次名` 禁止与 `任务` 相同(避免 `inbox/ddaw/ddaw`)。
- **数据路径** 为容器/NAS 绝对路径,提交前须存在;也可在本页「上传入湖」走 ZIP 候选(与台账并行)。
- 飞书多维表格 **不再** 作为系统数据源(`FEISHU_BITABLE_SYNC_ENABLED=0`);可选仅作人工备忘,见 [FEISHU_BITABLE_OPS.md](./FEISHU_BITABLE_OPS.md)。
## 6. 推荐数据闭环
### 现网(今日可执行)
```text
采集原图 → inbox(raw_pool) → 开启 Campaign → 标注/外协回传 → returned
→ 提交入库审核 → ingest → 数据目录 → 训练
```
验证:`python HSAP/as.py pending``GET /api/v1/pending`
## 6.1 数据目录「范围」(二级下拉)
数据目录用 **视角 + 两级下拉**,勿与送标工作台 pending始终按 **inbox 批次目录**)混淆:
| 视角 | 第一级 | 第二级 | 含义 |
|------|--------|--------|------|
| **训练包**(默认) | `dms_v1` 等 | `dam` / `addw_face` / `前向·粗检测` / `前向·细分类` … | 该包下各任务的 train/val 快照;前向在 registry 为单任务双 mode目录按 mode 拆开显示 |
| **采集批次** | 任务(如 `dam` | `0516 批次` 等 mode | 单波送标质量 |
| **车道线** | lane pack | — | Lane 列表统计 |
增量条(合并前)仍在磁盘 `packs/<pack>/<task>/sources/<批次名>/`;合并用 `python HSAP/as.py build dms dam --pack dms_v1 --all-sources`
- 送标/审核:送标工作台或 **采集批次** 视角。
- 训练发版:**训练包 → 任务**;新版本在 `workflow.registry.yaml``active_packs` 启用。
### 目标态DATA_LAKE
上传 → staging → quality.json → 审核 → curated 版本 → 数据目录。见 [DATA_LAKE_CHECKLIST.md](./DATA_LAKE_CHECKLIST.md)、差距 [DATA_LAKE_GAP.md](./DATA_LAKE_GAP.md)。
## 7. 常见问题
| 现象 | 原因 | 处理 |
|------|------|------|
| 待处理批次为 0 | inbox 无目录或无图 | 按 §3 落盘,或上传后 **送入 inbox** |
| 上传成功但批次仍空 | 未 promote | 等分析完成 → 点 **送入 inbox** |
| 画布无图 | inbox 路径空 | [QA_GAP_REPORT.md](./QA_GAP_REPORT.md) |
| DAM 无散点、ADDW 有 | 曾见 Docker 内 symlink 断链 | 已修复 `resolve_task_data_for_scan`;数据目录点 **刷新** |

View File

@@ -0,0 +1,198 @@
# 用 Label Studio 工程前端整体替换 HSAP UI
## 现状
| 已完成 | 说明 |
|--------|------|
| NX 应用 `apps/hsap-platform``@humansignal/ui` + tailwind | 登录、侧栏、全模块页 |
| `libs/editor` 标注画布 | `/labeling/campaigns/:id/annotate` |
| 标注 REST API | bootstrap / tasks / media / annotations / export / ml |
| Catalog / 审核 / 训练 / Job / 车队 | 接 HSAP `/api/v1` |
| `yarn hsap:build``platform/ui-hsap/dist` | `build_hsap_ls_ui.sh` |
| 废弃 `build_web.sh` | 旧 Vite 仅应急回退 |
**结论:** 生产 UI 以 [`workspace/BK2/label-studio/web`](../../workspace/BK2/label-studio/web) 的 `hsap-platform` 为准;旧 `HSAP/platform/web` 已移除。
---
## 目标架构
```mermaid
flowchart LR
subgraph browser [浏览器]
LSFE[label-studio_web 构建产物]
end
subgraph backend [HSAP 后端 不变]
API[FastAPI :8787 /api/v1]
PG[(PostgreSQL)]
end
LSFE -->|JWT + REST| API
API --> PG
```
- **前端:** `label-studio/web``yarn build` → 静态资源由 Nginx 或 FastAPI 挂载
- **后端:** 仍为 `HSAP/platform/as_platform`(标注 Campaign、pending、catalog、审核、训练
- **不跑** Label Studio Django仅复用其 **React 壳 + 组件库 + Editor**
---
## 实施步骤(按顺序)
### 1. 在 LS 工程中新增 HSAP 应用壳
路径建议:`label-studio/web/apps/hsap-platform/`(或 `apps/labelstudio/src/pages/Hsap/`
- 复制/参考 `Menubar``SidebarMenu``RootPage` 布局
- **去掉** Heartex / Label Studio logo 与产品首页
- 侧栏导航映射 HSAP 路由:
- 送标 / 标注任务 / 数据目录 / 审核 / 训练 / Job / 车队
### 2. API 适配层(关键)
LS 默认 `ApiProvider` 指向 Django `/api/projects` 等。
新建 **`HsapApiProvider`**(或扩展 `ApiConfig`
- `gateway`: `http://127.0.0.1:8787/api/v1`(开发)/ 同源 `/api/v1`(生产)
- HSAP 页面继续调用现有接口:`pending``catalog``labeling/batches``approvals`
- **不**实现 LS 的 projects/users 全量端点(删减模块)
### 3. 页面迁移顺序
| 优先级 | 页面 | LS 组件 |
|--------|------|---------|
| P0 | 登录 | `@humansignal/ui` Card/Button |
| P0 | 壳 + 标注任务列表 | Menubar + Table |
| P1 | 送标工作台 | 同上 |
| P1 | 标注画布 | `libs/editor` + HSAP labeling API |
| P2 | 数据目录 / 审核 | DataManager 风格表格(可选轻量自写) |
| P2 | Export | 参考 LS Settings 布局,接 HSAP API |
| P3 | 训练 / Job / 车队 | 逐步迁 |
### 4. 构建与 Docker
**推荐(宿主机无 Node 时也可用):**
```bash
cd HSAP
bash scripts/build_hsap_ls_ui.sh
```
脚本在 Docker `node:22-alpine` 内挂载 **整个** `label-studio` 仓库NX 需要根目录 `pyproject.toml`),执行 `yarn hsap:build`,输出到 `platform/ui-hsap/dist`
**手动:**
```bash
cd workspace/BK2/label-studio/web
yarn install
yarn hsap:build
cp -a dist/apps/hsap-platform/. ../../HSAP/platform/ui-hsap/dist/
```
`HSAP/Dockerfile`
- 不再在镜像内构建 `platform/web`
- 构建前需已有 `platform/ui-hsap/dist`(由上述脚本生成)
- FastAPI `_mount_ui()` 仅挂载 `ui-hsap/dist`(须先执行 `build_hsap_ls_ui.sh`
### 5. 废弃清单(已完成)
- 已删除 `HSAP/platform/web` 源码与 `docker-compose``web-dev` 服务
- 仅保留 `platform/ui-hsap/dist` 为 Web 静态资源
---
## 与标注闭环的关系
- **任务键** 仍为 `project + task + mode + batch`(见 `labeling.registry.yaml`
- **Editor** 在 LS 壳内路由 `/labeling/.../annotate`
- **ML / Export** 在 LS 风格设置页,逻辑走 HSAP worker
---
## 本地开发
**A. HSAP 一体(:8787**
```bash
bash HSAP/scripts/build_hsap_ls_ui.sh
cd HSAP && docker compose up -d --build platform
# 浏览器 http://127.0.0.1:8787 强刷缓存
```
**B. 前端 HMR:8015**
```bash
cd HSAP && docker compose up -d postgres redis platform
cd workspace/BK2/label-studio/web
yarn hsap:dev
# http://127.0.0.1:8015 /api 代理到 8787
```
---
## 样式说明(若页面像「纯 HTML」
构建产物里 **有** CSS/JS`main.css` 200KB、`main.js` 700KB。若侧栏挤在左边、无间距/配色,通常是:
1. **设计 token 未打进包** — 需在 `main.tsx` 引入 `@humansignal/ui/src/styles.prefix.css`(与 `tailwind.css` 一起)
2. **Tailwind 未进 `main.css`** — HSAP 生产构建需把 tailwind 抽到 `main.css`(见 `webpack.config.js` `standalone-hsap`
3. **`index.html` 误用 `type="module"`** — `build_hsap_ls_ui.sh` 会改回普通 `<script src="main.js">`
浏览器 **强刷** 后应看到 LS 浅色主题与圆角卡片。
---
## 浏览器验收清单
1. 登录 `http://127.0.0.1:8787`(或 HMR `:8015`
2. **标注任务** 可见 registry 批次(如 `dam/batch_0516`
3. 进入画布:加载 `dam_15cls.xml`;有 inbox 图片时可框选保存
4. **导出** 后在 **Jobs** 页看到 `labeling_export`
5. **审核** 列表 → 详情 → 缩略图 lightbox可提交审核动作
6. **车队** 地图瓦片 + 车辆 CRUD + 行程轨迹
7. **训练** 发起记录、查看详情与 registry
8. **数据目录** DMS scope + 类别分布条形图
```bash
bash HSAP/scripts/smoke_platform_api.sh # labeling + fleet + health
```
详见 [BROWSER_QA_CHECKLIST.md](BROWSER_QA_CHECKLIST.md)。
### 车队地图环境变量
| 变量 | 说明 |
|------|------|
| `AS_FLEET_MAP_ENABLED=1` | 启用车队 API |
| `AS_MAP_TILE_PROVIDER` | `gaode`(默认)或 `osm` |
| `AS_AMAP_KEY` | 高德 Web 服务 Key可选无 key 时 UI 会尝试公开瓦片,失败自动切 OSM |
## 角色与权限(阶段五)
| 角色 code | 用途 |
|-----------|------|
| `internal_labeler` | 内部标注:`read:pending``read:jobs` |
| `labeler` | 送标登记:`write:approval_submit:register` |
| `reviewer` | 审核:`write:approval_review` |
| `engineer` | 全功能(含 `*` 或训练提交) |
开发环境 `dev/login` 用户通常带 `*`;生产请在用户管理分配角色。
## 后续增强(可选)
1. 审核 overlay 细化(多边形/关键点样式)
2. 标注锁多实例 Redis 一致性
3. 更大路线图见 `label_studio_hsap` planAnnotationRevision PG 等)
## 新增路由Plan 汇总里程碑)
| 路由 | 说明 |
|------|------|
| `/labeling/export` | 导出与入库 |
| `POST .../import-vendor` | 第三方 ZIP 回传 |
| `GET /api/v1/fleet/stream` | SSERedis |
| `POST /api/v1/tbox/gps/batch` | 批量 GPS |
| `POST .../import-csv` | CSV 轨迹补录 |
验收与差距见 [QA_GAP_REPORT.md](QA_GAP_REPORT.md)、[DATA_LAKE_GAP.md](DATA_LAKE_GAP.md)。

251
docs/LANE_LABELING_PLAN.md Normal file
View File

@@ -0,0 +1,251 @@
# HSAP 车道线标注接入计划
本文说明如何在 HSAP 平台接入车道线标注,与 DMS 检测/pose **共存**。对齐 [`workspace/lane/DATASET`](../../workspace/lane/DATASET) 的 UFLD 训练规范。配套总路线图见 [DEVELOPMENT_ROADMAP.md](./DEVELOPMENT_ROADMAP.md) 阶段 D。
---
## 1. 目标与边界
**目标**HSAP 画布标注车道线 → 导出 **PNG 分割 mask + `list/train_gt.txt`**`as.py build lane` → UFLD 训练。
**不做(本期)**CULane `.lines.txt` 折线画布archive 历史格式保留,二期可选)。
| Profile | 编辑器 | 导出 | 现状 |
|---------|--------|------|------|
| DMS | `dms_detect.xml` / `dms_pose.xml` | `yolo` / `yolo_pose` | 已实现 |
| **lane_v1** | **`lane_culane.xml`(缺失)** | **`lane_gt_txt`** | registry 占位 |
**命名**registry 中 `lane_culane.xml` 为历史名;实现文件建议 `lane_ufld_mask.xml`(内容为 **BrushLabels**),并在 registry 更新。
```mermaid
flowchart TB
subgraph canvas [HSAP 画布]
XML["lane_ufld_mask.xml"]
LSJSON["labels/ls_annotations/*.json"]
end
subgraph export [导出]
Raster["export_ls_to_lane_gt.py"]
PNG["annotations/.../*.png"]
List["list/train_gt.txt"]
end
subgraph train [训练]
Build["as.py build lane"]
UFLD["UFLD train"]
end
XML --> LSJSON --> Raster --> PNG
Raster --> List
PNG --> Build
List --> Build --> UFLD
```
---
## 2. 你们现有的 Lane 数据规范(背景)
实体数据:[`workspace/lane/`](../../workspace/lane/)[`workspace/Lane/dataset`](../../workspace/Lane/dataset) 为软链入口)。
**训练标准格式**UFLD
```text
DATASET/
├── images/<src_...>/frame_xxxxx.jpg
├── annotations/<src_...>/frame_xxxxx.png # 单通道 mask像素值=车道 ID
└── list/train_gt.txt # 两列:图路径 + mask 路径
```
`train_gt.txt` 示例:
```text
images/src_culane/.../frame_004140.jpg annotations/src_culane/.../frame_004140.png
```
**像素编码**(见 [`vis_random_sample.py`](../../workspace/lane/scripts/vis_random_sample.py)
| 像素值 | 含义 |
|--------|------|
| 0 | 背景 |
| 26 | 各条车道线 |
archive 里另有 JSON 折线、`.lines.txt`CULane由 [`build_ufld_dataset.py`](../../workspace/lane/scripts/build_ufld_dataset.py) 转成 mask 包;**平台标注应直接产出 mask**,不再绕折线。
---
## 3. 阶段一:编辑器模板(画布层)
### 3.1 新增 XML
路径:`HSAP/datasets/lane/configs/label_studio/lane_ufld_mask.xml`
```xml
<View>
<Image name="image" value="$image" zoom="true"/>
<BrushLabels name="lanes" toName="image" strokeWidth="3">
<Label value="lane_1" background="#00FF00"/>
<Label value="lane_2" background="#0080FF"/>
<Label value="lane_3" background="#FF0000"/>
<Label value="lane_4" background="#FF00FF"/>
<Label value="lane_5" background="#00FFFF"/>
</BrushLabels>
</View>
```
标注员操作:选 lane 标签 → 画笔沿车道线涂抹(与离线 LabelMe/CVAT 涂 mask 一致)。
### 3.2 像素 manifest
路径:`HSAP/datasets/lane/configs/lane_mask_encoding.yaml`
```yaml
background: 0
lanes:
- {label: lane_1, pixel: 2}
- {label: lane_2, pixel: 3}
- {label: lane_3, pixel: 4}
- {label: lane_4, pixel: 5}
- {label: lane_5, pixel: 6}
```
### 3.3 修复模板路径
[`annotate.py`](../platform/as_platform/labeling/annotate.py) 当前 `LABEL_CONFIG_DIR` 仅指向 DMSLane 读不到模板:
- `dms``datasets/dms/configs/label_studio/`
- `lane``datasets/lane/configs/label_studio/`
更新 [`labeling.registry.yaml`](../datasets/labeling.registry.yaml)
```yaml
lane__lane_v1:
editor_template: lane_ufld_mask.xml
export_default: lane_gt_txt
```
无需改 Label Studio 前端源码Brush 为 Editor 内置)。
---
## 4. 阶段二:格式转换(核心)
新增:`HSAP/datasets/lane/scripts/export_ls_to_lane_gt.py`
### 4.1 输入
`labels/ls_annotations/<task_id>.json``result[]``type: "brushlabels"`RLE / polygon
### 4.2 输出
| 产物 | 规则 |
|------|------|
| PNG mask | `annotations/<mirror_path>.png`,单通道 uint8 |
| list 行 | `list/train_gt.txt``images/...jpg annotations/...png` |
| 合并逻辑 | 多 brush region 按 label→pixel 合成一张 mask |
### 4.3 与 offline 流程共存
| 路径 | 说明 |
|------|------|
| **HSAP 画布** | ls_annotations → export → pack 内 images/annotations/list |
| **外协 archive** | 继续 `build_ufld_pack.py` 整包入库 |
| **训练** | 两路经 `merge_ufld_lists.py` 去重合并 |
---
## 5. 阶段三Campaign 与导出 Job
### 5.1 批次目录
```text
datasets/lane/inbox/<batch>/
images/...
annotations/ # 导出生成
list/train_gt.txt
labels/ls_annotations/
```
或增量包 `DATASET-AddBy-<工程师>-<日期>/`(见 [`DATASETS_LAYOUT.md`](../../workspace/lane/DATASETS_LAYOUT.md))。
### 5.2 runner
[`runner.py`](../platform/as_platform/jobs/runner.py) 增加:
```text
export_default == lane_gt_txt
→ export_ls_to_lane_gt(batch_dir)
→ as.py build lane
```
与 DMS `yolo` / `yolo_pose` **分支共存**
### 5.3 batch_stage
扩展 [`batch_stage.py`](../platform/as_platform/labeling/batch_stage.py)`list/train_gt.txt` 非空且 PNG 存在 → `stage=returned`
---
## 6. 阶段四:验证与文档
| 项 | 动作 |
|----|------|
| 单元测试 | `test_export_ls_to_lane_gt.py` |
| 可视化 | `workspace/lane/scripts/vis_random_sample.py` 叠加 |
| smoke | 扩展 `smoke_labeling_api.sh` lane 分支 |
| 文档 | LABELING_SOP §4.4、PHASE_ROLLOUT P2、BROWSER_QA_CHECKLIST |
---
## 7. 风险与对策
| # | 风险 | 对策 |
|---|------|------|
| 1 | Lane 模板读 DMS 目录 | annotate 按 project 分目录 |
| 2 | Brush RLE 解码失败 | 单测 + 参考 LS RLE 解码 |
| 3 | 像素值与历史 pack 不一致 | manifest 固定;导出后 scan unique values |
| 4 | 多线 overlap | 按 lane 顺序合并SOP 约定尽量不交叉涂 |
| 5 | 线宽不一致 | strokeWidth=3文档约定 |
| 6 | list 路径错误 | 相对 pack 根build 用 `--prefix-from-pack` |
| 7 | 折线 vs mask 混淆 | SOPUFLD 只认 mask |
| 8 | workspace/lane 软链 | `setup_links.sh` 保持 datasets/lane → workspace/lane |
---
## 8. 排期建议
| 阶段 | 时间 | 内容 |
|------|------|------|
| 一 | 35 天 | XML + encoding + annotate 路径 |
| 二 | 57 天 | export 脚本 + 单测 |
| 三 | 23 天 | runner + inbox 试点 |
| 四 | 2 天 | 文档 + 浏览器验收 |
**建议**DMS 阶段 A[PHASE_ROLLOUT_DMS.md](./PHASE_ROLLOUT_DMS.md))基本通过后再启动 Lane避免 E2E 并行分散。
---
## 9. 验收标准
- [ ] Lane Campaign 画布Brush 五车道工具
- [ ] 保存 JSON 含 `brushlabels`
- [ ] 导出 PNG 像素值符合 manifest
- [ ] `list/train_gt.txt` 两列正确
- [ ] `as.py build lane` 成功
- [ ] `vis_random_sample.py` 叠加正确
- [ ] 与 DMS Campaign 可同时存在
---
## 10. 关键文件清单
| 操作 | 路径 |
|------|------|
| 新增 | `datasets/lane/configs/label_studio/lane_ufld_mask.xml` |
| 新增 | `datasets/lane/configs/lane_mask_encoding.yaml` |
| 新增 | `datasets/lane/scripts/export_ls_to_lane_gt.py` |
| 新增 | `datasets/lane/scripts/test_export_ls_to_lane_gt.py` |
| 修改 | `platform/as_platform/labeling/annotate.py` |
| 修改 | `datasets/labeling.registry.yaml` |
| 修改 | `platform/as_platform/jobs/runner.py` |
| 修改 | `platform/as_platform/labeling/batch_stage.py` |
---
*版本2026-05-27 · 对齐 workspace/lane UFLD mask 规范*

77
docs/MINIO_STAGING.md Normal file
View File

@@ -0,0 +1,77 @@
# MinIO 暂存区(联调搭建)
HSAP **尚未**实现 S3 API 自动拉取;先起 MinIO 用于:**上传试验 + 对象路径规范**。数据进标注仍须落到 `datasets/.../inbox`Console 上传后 **同步到目录**,或等 Phase C S3 拉取)。
## 1. 启动(与 HSAP 同 compose
```bash
cd /home/chengfanglu/DATA/HSAP
docker compose --profile minio up -d
```
| 服务 | 地址 | 默认账号 |
|------|------|----------|
| S3 API | http://127.0.0.1:9000 | 见 `manifests/minio.env.example` |
| Console | http://127.0.0.1:9001 | 同上 |
创建桶 `hsap-staging`(仅首次):
```bash
docker compose --profile minio run --rm minio-init
```
## 2. 上传试数据
Console → 桶 **hsap-staging** → 建目录,例如:
```text
addw/20250526_SE882/images/train/*.jpg
```
与飞书表一致:**任务 addw**、**批次名 20250526_SE882**(无子模式)。
**联调现成小样**:见 [PILOT_BATCH.md](./PILOT_BATCH.md)`20260525_pilot`12 张,已落 inbox + MinIO
## 3. 让 HSAP 能读到(当前必做)
平台容器**不能**直接填 `s3://...`,需同步到挂载目录。
**方式 A宿主机同步到 HSAP datasets推荐联调**
```bash
# 安装 mc 或使用 compose 里的 mc 容器
docker run --rm --network host \
-v /home/chengfanglu/DATA/HSAP/datasets:/datasets \
minio/mc:latest sh -c '
mc alias set local http://127.0.0.1:9000 minioadmin minioadmin_change_me
mc mirror --overwrite local/hsap-staging/addw/20250526_SE882 /datasets/dms/inbox/addw/20250526_SE882
'
```
飞书 **数据路径**(若开 AUTO_INGEST填容器内路径
```text
/data/hsap/datasets/dms/inbox/addw/20250526_SE882
```
**方式 B只测 MinIO暂不联动 HSAP**
仅验证 Console 上传、桶结构HSAP 仍用送标工作台 **上传入湖** 或手工 inbox。
## 4. 与飞书台账
| 飞书字段 | 现在 | MinIO 成熟后 |
|----------|------|----------------|
| 数据路径 | NAS / inbox 绝对路径 | 可改为 `s3://hsap-staging/addw/20250526_SE882/`(待开发) |
| 备注 | 可写「对象在 MinIO hsap-staging」 | |
## 5. 安全提醒
- 默认账号密码仅 **内网联调**,勿暴露到公网。
- 生产请改 `MINIO_ROOT_PASSWORD`,并用独立 AK/SK。
## 6. 停止
```bash
docker compose --profile minio down
# 数据在卷 hsap_minio_data 中保留
```

38
docs/PHASE_ROLLOUT_DMS.md Normal file
View File

@@ -0,0 +1,38 @@
# DMS 标注分期验收addw pilot
## P0dam / ddaw检测
- [ ] 批次台账入湖 → inbox 有 `images/train`
- [ ] 送标工作台「待送标」可见批次
- [ ] 进入标注左侧工具箱face 等)+ 保存
- [ ] 提交后 `batch.meta` stage = `labeling_submitted`「待入库」Tab 可见
- [ ] 导出 Job 成功后 stage = `returned`
- [ ] 提交入库审核 → build 通过
## P1addw / addw_face当前 pilot
Pilot`inbox/addw/20260525_pilot`12 张)
- [x] `dms_detect.xml` 四类标签
- [x] `dms_pose.xml`face 框 + 37 关键点(`kp_00``kp_36`
- [x] `export_ls_to_yolo.py`LS JSON → YOLO detect / YOLO pose
- [ ] 标注保存至 `labels/ls_annotations/*.json`
- [ ] 提交 / 导出 / 待入库全链路(见 P0 检查项)
- [ ] addw_face 导出 txt 每行 116 字段,通过 `validate_pose_label`
```bash
python3 datasets/dms/scripts/test_export_ls_to_yolo.py
```
## P2forward / lane
- [ ] `forward__detect` / `forward__classify` registry 模板
- [ ] lane `lane_culane.xml` 画布 smoke
## 自动化
```bash
bash scripts/smoke_labeling_api.sh
bash scripts/smoke_pending_gate.sh
python3 scripts/lake_checklist_audit.py
```

86
docs/PILOT_BATCH.md Normal file
View File

@@ -0,0 +1,86 @@
# 联调小样:`20260525_pilot`addw
已在本机准备好 **12 张** ADDW 检测原图(来自 `reports/gt_gallery/addw`,每类 3 张),用于走通:**飞书台账 →(可选 MinIO→ inbox → HSAP 落盘/送标**。
## 1. 数据位置
| 位置 | 路径 |
|------|------|
| 宿主机 inbox | `/home/chengfanglu/DATA/HSAP/datasets/dms/inbox/addw/20260525_pilot/` |
| 平台容器内(飞书 **数据路径** / AUTO_INGEST | `/data/hsap/datasets/dms/inbox/addw/20260525_pilot` |
| MinIO 对象前缀 | `hsap-staging/addw/20260525_pilot/images/train/*.jpg` |
目录结构:
```text
20260525_pilot/
images/train/
face__*.jpg
eye_open__*.jpg
nod_eye__*.jpg
nod_face__*.jpg
```
## 2. 飞书表填一行(复制对照)
| 列 | 填写值 |
|----|--------|
| 项目 | `dms` |
| 任务 | `addw` |
| 子模式 | **留空**(可无此列) |
| 批次名 | `20260525_pilot` |
| 来源类型 | `联调样例` |
| 车型或场景 | `pipeline_test` |
| 数据路径 | `/data/hsap/datasets/dms/inbox/addw/20260525_pilot` |
| 状态 | 先 `草稿` → 核对后改 **`待落盘`** |
| 预估张数 | `12` |
| 备注 | `联调小样;对象已同步 MinIO hsap-staging/addw/20260525_pilot` |
**不要**把批次名写成 `addw``dms_v2`
## 3. 推荐走通顺序
### A. 已有磁盘数据(最快)
1. 飞书新建上表一行 → 状态 **待落盘**
2. HSAP配置 `manifests/feishu.env` 后执行同步,或送标工作台 **扫描 inbox / 落盘**
3. 批次进入 **待送标** → 开 Campaign → 内标 2 人各领几张验证分包。
### B. 顺带练 MinIO
1. Console 打开 http://127.0.0.1:9001 → 桶 `hsap-staging` → 确认已有 `addw/20260525_pilot/`
2. 若删了桶内数据,从 inbox 再 mirror 一次:
```bash
docker run --rm --network host \
-v /home/chengfanglu/DATA/HSAP/datasets:/datasets \
minio/mc:latest sh -c '
mc alias set local http://127.0.0.1:9000 minioadmin minioadmin_change_me
mc mirror --overwrite /datasets/dms/inbox/addw/20260525_pilot \
local/hsap-staging/addw/20260525_pilot
'
```
3. 飞书 **数据路径** 仍填容器 inbox 路径(当前不支持仅填 `s3://`)。
## 4. 验收点
- [ ] 飞书同步后 **Inbox路径**、**HSAP链接** 有值
- [ ] 送标工作台能看到 `addw / 20260525_pilot`,约 12 张待送标
- [ ] 开启标注后 task 可打开画布
- [ ] 可选MinIO Console 中对象数与 inbox 一致
## 5. 清理
```bash
# 仅删 inbox 样例(需 root/容器内)
docker exec hsap-platform rm -rf /data/hsap/datasets/dms/inbox/addw/20260525_pilot
# MinIO 前缀
docker run --rm --network host minio/mc:latest sh -c '
mc alias set local http://127.0.0.1:9000 minioadmin minioadmin_change_me
mc rm -r --force local/hsap-staging/addw/20260525_pilot
'
```
飞书行改 **驳回/作废** 或删除即可。

39
docs/QA_GAP_REPORT.md Normal file
View File

@@ -0,0 +1,39 @@
# HSAP 验收与缺口报告
生成方式:`bash HSAP/scripts/smoke_platform_api.sh` + 对照 [BROWSER_QA_CHECKLIST.md](BROWSER_QA_CHECKLIST.md)
**最近 smoke** 通过(`ALL_OK`health / labeling batches(7) / fleet live(3) / export-jobs / bootstrap / export / ml-predict 均正常。
## API 自动化
| 项 | 状态 | 备注 |
|----|------|------|
| Health + DB/Redis | 通过 | |
| labeling/batches | 通过 | 7 条(含 registry_only 占位批次) |
| dam bootstrap | 通过 | `dam_15cls.xml` 已写入 campaign |
| export / ml-predict | 通过 | ExportJob 与 jobs 队列联动 |
| fleet map-config / live | 通过 | 需 `AS_FLEET_MAP_ENABLED=1` |
## 浏览器(需人工勾选)
见 [BROWSER_QA_CHECKLIST.md](BROWSER_QA_CHECKLIST.md)。自动化无法覆盖 UI 布局与瓦片加载。
## 已确认缺口
| 缺口 | 影响 | 缓解 |
|------|------|------|
| inbox **无样例图片** | `tasks` 为空,画布无法 E2E 框选保存 | 往 `datasets/dms/inbox/dam/batch_0516/` 放 jpg或 reseed 演示批次 |
| export worker 占位 | job `message` 为记录型,未真跑 YOLO 转换 | 见 runner `labeling_export`;后续对接 `as.py build` |
| ML 预标 | 已停用 | 无 UI / 无 `POST .../ml/predict` |
| 无 vendor 回传 | 第三方离线标无法导入 | 本里程碑新增 `import-vendor` API |
| 无独立 Export/ML 页 | 仅在 Campaign 行操作 | 本里程碑新增 `/labeling/export``/labeling/ml` |
| 车队无 SSE | 15s 轮询 | 本里程碑新增 `/fleet/stream` |
| 数据入湖 staging | checklist AE 未全实现 | 见 [DATA_LAKE_GAP.md](DATA_LAKE_GAP.md) |
## 建议复测命令
```bash
bash HSAP/scripts/smoke_platform_api.sh
bash HSAP/scripts/smoke_labeling_api.sh
cd HSAP && docker compose up -d --build platform
```

26
docs/VENDOR_RETURN.md Normal file
View File

@@ -0,0 +1,26 @@
# 第三方标注回传包
## ZIP 结构
```text
vendor_return.zip
├── manifest.json # 可选format, task, batch
├── images/ # jpg/png
└── labels/ # yolo txt 或 json
```
## API
```bash
curl -X POST "http://127.0.0.1:8787/api/v1/labeling/campaigns/{campaign_id}/import-vendor" \
-H "Authorization: Bearer <token>" \
-F "file=@vendor_return.zip"
```
权限:`write:labeling_vendor`工程师、vendor_labeler 角色)。
导入后自动写入 `LabelingCampaignAccess`vendor_labeler图片落批次 `images/`,标签落 `labels/`
## 前端
标注任务列表 → **导入回传**;或侧栏 **导出与入库**