Label Studio / CVAT 双引擎 · 图像/文本/音频/视频/时序全类型 · 规模不限 · 可开发落地
1. 设计目标与规模弹性
各模态样本量独立配置,架构按"亿级样本可扩展"设计——存储走对象存储横向扩容,算力走多 Worker/多 GPU 伸缩,任务按分片并行,任何量级只改资源不改进程。
| 规模维度 | 弹性机制 |
| 存储 | MinIO 对象存储横向加盘/加节点,视频/音频/图像分桶隔离 |
| 算力 | GPU Worker 按队列积压自动扩缩(云 GPU 按需) |
| 任务 | 按帧区间/时间窗/段落分片,分片数随样本量线性增加 |
| 人工标注 | 标注员可多开引擎并发,任务分片分发 |
| 单点上限 | 不设业务上限,PostgreSQL 亿级行 + 分区表兜底 |
2. 技术栈(落地清单)
| 层 | 选型 | 版本参考 |
| 后端框架 | Python 3.12 + FastAPI + SQLAlchemy 2 + Pydantic 2 | FastAPI ≥0.110 |
| 队列调度 | Celery 5 + Redis 7 | 任务分片与 Worker 伸缩 |
| 元数据库 | PostgreSQL 16 | 亿级行分区表 |
| 对象存储 | MinIO | S3 兼容,引擎直挂 |
| 标注引擎A | CVAT(视觉主引擎) | 开源版 v2.x,容器化 |
| 标注引擎B | Label Studio(全类型) | v1.13+,S3 同步 |
| 视频模型 | Ultralytics YOLO + BoxMOT(ByteTrack) | YOLOv8/v11 |
| ASR | faster-whisper | small/medium/large 按需 |
| LLM 标注 | DeepSeek API / Ollama 本地 | 文本 NER/分类/关系 |
| 编排 | Docker Compose 起步 → K8s 演进 | Compose v2 |
3. 总体架构与代码目录
五层架构:接入层 → 核心服务 → 引擎层 → 自动标注管道 → 数据层。目录结构如下(FastAPI 单体 + 多 Worker):
annotation-platform/
├── docker-compose.yml # 平台编排(PG/MinIO/Redis/API/Workers)
├── docker-compose.engines.yml # CVAT + Label Studio 引擎编排
├── .env.example # 全部连接参数/密钥
├── backend/
│ ├── app/
│ │ ├── main.py # FastAPI 入口
│ │ ├── config.py # pydantic-settings
│ │ ├── api/ # 路由
│ │ │ ├── datasets.py items.py tasks.py
│ │ │ ├── annotations.py jobs.py export.py
│ │ ├── models/ # SQLAlchemy 模型
│ │ ├── schemas/ # Pydantic schema
│ │ ├── adapters/ # 双引擎适配层(核心)
│ │ │ ├── base.py uaf.py
│ │ │ ├── cvat.py label_studio.py
│ │ ├── services/ # 业务逻辑
│ │ │ ├── import_service.py task_service.py
│ │ │ └── prelabel_service.py export_service.py
│ │ └── core/ # 队列/配置
│ ├── workers/ # 五条模态管道(独立进程)
│ │ ├── video_pipe.py image_pipe.py
│ │ ├── text_pipe.py audio_pipe.py ts_pipe.py
│ ├── ml/ # 推理封装
│ │ ├── detector.py tracker.py asr.py llm_client.py
│ └── requirements.txt
├── frontend/ # 管理控制台(可复用羽山前端栈)
└── deploy/ # 部署脚本/健康检查
4. 数据库设计(核心 DDL)
六张核心表:dataset / data_item / annotation_task / annotation / auto_job / user。标注结果存 UAF 结构(shape JSONB),按模态解释。
CREATE TABLE dataset (
id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL,
type TEXT NOT NULL CHECK (type IN ('image','text','audio','video','time_series')),
engine TEXT NOT NULL DEFAULT 'label_studio' CHECK (engine IN ('cvat','label_studio')),
label_config TEXT, -- LS 配置 / CVAT 标签定义
status TEXT DEFAULT 'active',
created_at TIMESTAMPTZ DEFAULT now());
CREATE TABLE data_item (
id BIGSERIAL PRIMARY KEY,
dataset_id BIGINT REFERENCES dataset(id) ON DELETE CASCADE,
storage_key TEXT NOT NULL, -- MinIO 对象键
meta JSONB, -- duration/fps/sample_rate/width/height
status TEXT DEFAULT 'imported',
created_at TIMESTAMPTZ DEFAULT now());
CREATE TABLE annotation_task (
id BIGSERIAL PRIMARY KEY,
dataset_id BIGINT REFERENCES dataset(id),
engine_type TEXT NOT NULL, -- cvat | label_studio
engine_task_id TEXT, -- 引擎侧任务ID
split JSONB, -- 帧区间/时间窗/段落范围
assignee_id BIGINT,
status TEXT DEFAULT 'pending',
created_at TIMESTAMPTZ DEFAULT now());
CREATE TABLE annotation (
id BIGSERIAL PRIMARY KEY,
item_id BIGINT REFERENCES data_item(id) ON DELETE CASCADE,
label TEXT NOT NULL,
shape JSONB, -- bbox/polygon/track/span/wave_range
source TEXT DEFAULT 'human' CHECK (source IN ('auto','human')),
model_version TEXT,
confidence REAL,
reviewed BOOLEAN DEFAULT FALSE,
created_by BIGINT,
created_at TIMESTAMPTZ DEFAULT now());
CREATE TABLE auto_job (
id BIGSERIAL PRIMARY KEY,
dataset_id BIGINT REFERENCES dataset(id),
pipe_type TEXT NOT NULL, -- video/image/text/audio/ts
params JSONB, -- fps/batch/模型名
model_version TEXT,
status TEXT DEFAULT 'pending',
stats JSONB, -- 处理帧数/耗时/检出数
created_at TIMESTAMPTZ DEFAULT now());
亿级扩展:data_item 与 annotation 按 dataset_id 分区(PARTITION BY RANGE/HASH),annotation 按 item_id 建索引 + shape 走 GIN 索引支撑按标签检索。
5. API 设计(核心端点)
POST /api/datasets # 创建数据集(指定type+engine)
GET /api/datasets # 数据集列表
POST /api/datasets/{id}/import # 批量导入(分片/离线硬盘)
GET /api/datasets/{id}/stats # 统计(样本/标注/进度)
POST /api/datasets/{id}/prelabel # 触发自动标注作业
POST /api/datasets/{id}/tasks # 创建人工标注任务(自动分片)
GET /api/tasks/{id}/open # 302跳转引擎标注页
GET /api/tasks/{id}/sync # 从引擎拉取最新标注→UAF
POST /api/annotations # 保存/更新标注(UAF)
GET /api/export?fmt=coco|yolo|ls_json # 按需导出训练格式
POST /api/jobs/{id}/retry # 失败作业重试
GET /api/engines/status # CVAT/LS 健康检查
6. 双引擎集成方案(落地细节)
| 引擎 | 数据接入 | 预标注回填 | 标注拉回 |
| CVAT | S3 云存储挂载(直连 MinIO 桶),不复制数据 | API 上传 shapes.xml + 帧索引;或用内置 auto-annotation 服务 | 任务完成回调/轮询 → 下载标注 → 转 UAF |
| Label Studio | LS S3 同步 + 任务 JSON 导入 | Prediction API 导入预标注(带 confidence) | GET 任务标注 → 转 UAF |
关键实现要点:① CVAT 用 Cloud Storage 特性挂 MinIO,避免 3.4TB 级拷贝;② LS 预标注走 predictions(可区分 auto/human 且可回滚);③ 平台侧定时轮询引擎任务状态 + Webhook 回调,增量拉取标注写入 annotation 表。
7. 自动标注管道(工程化)
| 模态 | Worker 流程 | 模型 |
| 视频 | FFmpeg归一化→抽帧2fps→检测→ByteTrack→传播→UAF回填 | YOLOv8m/v11 + BoxMOT |
| 图像 | 批量检测/分割→UAF | YOLO |
| 音频 | 切段→ASR→时间戳对齐→事件分类 | faster-whisper |
| 文本 | 批量 LLM 调用(NER/分类)→置信度过滤 | DeepSeek API/Ollama |
| 时序 | 滑窗模式识别/异常检测→区间标注 | 轻量模型/规则 |
工程要点:每个管道 = 独立 Celery task,参数化(fps/模型/batch);处理进度与统计写入 auto_job.stats;失败自动重试 + 断点续跑(按 data_item 幂等);低置信度结果标记 review_required,质检优先派发。
8. 任务调度与伸缩
五条模态队列隔离(video/image/text/audio/ts),Worker 按类型消费:GPU 队列(video/image/audio)挂 4090 节点,CPU 队列(text/ts)挂普通节点;云 GPU 按队列积压自动扩缩;文本管道可纯走 LLM API 零本地卡。人工任务分片:视频按帧区间(默认 60s/片)、音频按时段、文本按段落、时序按时间窗。
9. 部署方案
# docker-compose.yml 服务清单
services:
postgres: image: postgres:16 # 元数据
minio: image: minio/minio # 对象存储(视频/音频/图像/文本/时序桶)
redis: image: redis:7 # 队列
api: build: ./backend # FastAPI
worker-video: build: ./backend # GPU: YOLO+ByteTrack
worker-audio: build: ./backend # GPU: faster-whisper
worker-text: build: ./backend # CPU: LLM 客户端
worker-ts: build: ./backend # CPU: 时序
# docker-compose.engines.yml:
cvat: cvat/server + cvat/worker # 视觉引擎
label-studio: heartsignal/label-studio # 全类型引擎
部署步骤:① 起引擎编排(CVAT/LS 初始化账号);② 起平台编排;③ 平台侧配置引擎地址/密钥(.env);④ 健康检查全绿后导入数据。生产建议:Compose → K8s,GPU 用 nodeSelector 固定,MinIO 用独立盘 RAID。
10. 开发里程碑(8 周)
| 里程碑 | 周期 | 交付物 |
| M1 骨架 | 2周 | Compose 起 LS+CVAT+MinIO+PG+Redis;数据导入;图像/文本人工标注可用 |
| M2 视频管道 | 2周 | 抽帧+YOLO+ByteTrack;预标注回填 CVAT;任务分片 |
| M3 音频+文本管道 | 2周 | faster-whisper ASR 管道;DeepSeek 文本预标注 |
| M4 时序+质检 | 1周 | 时序管道;模态质检规则;多格式导出(COCO/YOLO/LS) |
| M5 闭环+伸缩 | 1周 | 难例回流主动学习;多 Worker/多 GPU 伸缩;Webhook 同步 |
11. 成本弹性公式
存储 = 样本数 × 单样本大小 × 副本数 # 视频3min480p≈34MB/条
视频算力 = 样本数 × 时长s × fps ÷ 300fps # 4090单卡
音频算力 = 总时长h ÷ (20×并行度) # faster-whisper small
文本成本 = 篇数 × tokens/篇 × DeepSeek单价 # 通常数元~数十元
GPU按需 = 用多少付多少,队列积压触发扩容
无固定 10 万基线:样本量只是公式输入,架构层不设上限。
羽山数智,致力于成为企业数据智能的实践者。
📌关于羽山数据
面向企业数智化转型需求,羽山数据通过数据产品、智能体应用、场景化 Demo、PoC 验证与 FDE 项目制交付,帮助客户把数据真正转化为可分析、可执行、可审计、可落地的业务能力。在 AI 编程工具应用领域,羽山强调“人机协同”的工程实践:AI 负责加速可标准化部分,人负责架构判断、代码审查和质量把控,确保 AI 提升的是团队真实的交付能力,而不只是代码提交量。
● 商务合作:孟经理
● Email:mengfanhui@yushanshuju.com
● 公司官网:www.usendata.com/
● 地址:上海市虹口区飞虹路 118 号
© 2026 羽山数据 | 转载请注明出处

194

被折叠的 条评论
为什么被折叠?



