feat: 初始化 WOV meta 仓库

This commit is contained in:
cat-shark
2026-08-08 21:08:48 +08:00
commit 15100a0c97
3 changed files with 686 additions and 0 deletions
+457
View File
@@ -0,0 +1,457 @@
# AI Workflow Platform MVP Design
## 1. MVP 目标
用最小但完整的闭环验证这个架构:管理员在后台注册节点、编排工作流并发布;普通用户只上传视频,后端动态组装节点并执行;节点无人使用后自动回收。
MVP 只做单机版本,不做 Kubernetes、多租户、计费和分布式 GPU 池。目标是在一台机器上跑通:
```text
上传视频 -> ffmpeg 提音 -> faster-whisper 转写 -> LLM 翻译 -> VR ASS 生成 -> 下载结果
```
## 2. 整体架构
```mermaid
flowchart LR
Admin[管理后台] --> AdminAPI[FastAPI Admin API]
AdminAPI --> DB[(SQLite)]
AdminAPI --> Registry[节点注册中心]
Registry --> Manager[节点管理器]
Manager --> NodeA[ASR 节点]
Manager --> NodeB[LLM 节点]
Manager --> NodeC[ASS 节点]
User[用户前端] --> UserAPI[FastAPI User API]
UserAPI --> Scheduler[工作流调度器]
Scheduler --> Registry
Scheduler --> Runs[WorkflowRun]
Runs --> DB
Scheduler --> Manager
```
关键原则:
- 节点不是写死在应用里的函数,而是独立进程,按统一协议提供服务。
- 工作流是数据库里的版本化 DAG,不是业务代码。
- 调度器只负责编排,不直接加载模型。
- 节点实例由节点管理器统一创建、分配、回收。
## 3. MVP 范围
### 3.1 本期包含
- 节点注册中心,支持登记节点类型、能力、参数、启动命令、资源要求。
- 节点生命周期:COLD / STARTING / READY / BUSY / IDLE / STOPPING。
- 工作流 DAG 定义、校验、版本化、发布。
- 单机工作流执行器,按拓扑顺序调度节点。
- 用户上传接口、任务状态查询、进度事件、产物下载。
- 管理后台节点管理和工作流画布。
- 用户端工作流列表、上传页、进度页、结果页。
- 一条可运行的视频字幕示例工作流。
### 3.2 本期不做
- Kubernetes、GPU 自动扩缩、跨机器节点池。
- 多租户、用户认证、计费、配额。
- 节点在线热部署和插件市场。
- 可视化工作流调试器。
- 分布式任务队列和 Worker 集群。
## 4. 节点抽象
### 4.1 节点 Manifest
```json
{
"id": "faster-whisper",
"name": "Faster Whisper ASR",
"version": "1.0.0",
"capability": "asr",
"command": ["python", "-m", "nodes.whisper_node"],
"env": {
"MODEL_PATH": "./models/faster-whisper-large-v3"
},
"input_schema": {
"audio_uri": "file"
},
"output_schema": {
"srt_uri": "file"
},
"max_concurrency": 1,
"idle_ttl_seconds": 300,
"health_timeout_seconds": 10
}
```
字段含义:
- `capability`:节点能力类型,例如 `asr``llm``ffmpeg``subtitle`
- `command`:节点进程启动命令。
- `env`:模型路径、API Key 等环境变量。
- `input_schema` / `output_schema`:用于工作流校验和节点参数检查。
- `max_concurrency`:单实例最大并发任务数。
- `idle_ttl_seconds`:空闲多久后回收。
### 4.2 节点进程协议
每个节点是一个独立进程,对外提供两个 HTTP 接口:
```text
GET /health
POST /invoke
```
`POST /invoke` 请求:
```json
{
"run_id": "run_123",
"node_instance_id": "ni_456",
"inputs": {
"audio_uri": "storage/runs/run_123/audio.wav"
},
"params": {
"language": "ja",
"beam_size": 1
},
"output_dir": "storage/runs/run_123/steps/whisper"
}
```
`POST /invoke` 响应:
```json
{
"status": "completed",
"outputs": {
"srt_uri": "storage/runs/run_123/steps/whisper/output.srt"
}
}
```
节点执行过程中可以上报进度事件:
```json
{
"run_id": "run_123",
"node_id": "faster-whisper",
"progress": 0.45,
"message": "正在转录第 120/300 段"
}
```
MVP 阶段节点通过本地文件系统交换产物,未来把 `storage/...` 换成对象存储 URI 即可。
### 4.3 节点生命周期
```text
COLD -> STARTING -> READY -> BUSY -> READY -> IDLE -> STOPPING -> STOPPED
| |
+---------- ERROR <------------+
```
- `COLD`:没有进程,只有注册信息。
- `STARTING`:进程已拉起,等待 `/health` 就绪。
- `READY`:进程就绪,模型已加载,可以接收任务。
- `BUSY`:正在执行任务。
- `IDLE`:任务完成,等待下一任务或回收。
- `STOPPING`:超过 `idle_ttl_seconds`,正在优雅退出。
- `ERROR`:启动或执行失败。
节点管理器定时扫描实例状态:
- 任务申请节点时,优先分配 `READY` 实例。
- 没有实例时,从 `COLD` 启动。
- `BUSY` 实例不能被回收。
- `IDLE` 超过 TTL 后先卸载模型并停止进程。
- 被调度器标记为长期热门的节点可以配置 `keep_warm=true`,不回收。
## 5. 工作流定义
工作流是一份带版本号的 DAG JSON:
```json
{
"name": "video-to-vr-ass",
"version": 1,
"nodes": [
{
"id": "extract",
"node_type": "ffmpeg-extract",
"params": {
"sample_rate": 16000,
"channels": 1
}
},
{
"id": "asr",
"node_type": "faster-whisper",
"params": {
"language": "ja"
}
},
{
"id": "translate",
"node_type": "llm-translate",
"params": {
"target_language": "zh-CN"
}
},
{
"id": "ass",
"node_type": "srt-to-dual-eye-ass",
"params": {
"resolution": "3840x1920"
}
}
],
"edges": [
{"from": "extract", "to": "asr"},
{"from": "asr", "to": "translate"},
{"from": "translate", "to": "ass"}
],
"entry_inputs": {
"video_uri": "file"
},
"final_outputs": {
"cn_srt": "translate.srt_uri",
"ass": "ass.ass_uri"
}
}
```
工作流校验规则:
- 所有 `node_type` 必须已注册。
- 边必须引用存在的节点。
- 每个节点的输入必须有上游产物或工作流入口输入。
- 工作流必须是无环图。
- 发布前必须通过一次 dry-run 校验。
## 6. 执行模型
用户触发工作流后:
1. 创建 `WorkflowRun`,状态为 `QUEUED`
2. 调度器读取工作流 DAG,做拓扑排序。
3. 对每个节点调用节点管理器申请实例。
4. 节点执行完毕后,产物 URI 写入 `Artifact`
5. 所有节点完成后,`WorkflowRun` 状态变为 `COMPLETED`
6. 任一节点失败,按重试策略重试;超过次数后标记 `FAILED`
MVP 的调度策略:
- 只支持线性链和简单 DAG。
- 没有依赖关系的节点可以并发执行。
- 节点之间只通过产物 URI 通信,不允许共享内存。
- 每个节点执行前检查健康状态,节点不可用时重新启动。
WorkflowRun 状态:
```text
QUEUED -> RUNNING -> COMPLETED
| |
+-> FAILED +
|
+-> CANCELLED
```
## 7. 数据模型
MVP 使用 SQLite,表结构如下。
### nodes
```text
id, name, version, capability, manifest_json, status, created_at
```
### workflows
```text
id, name, slug, description, published, latest_version, created_at
```
### workflow_versions
```text
id, workflow_id, version, definition_json, created_at
```
### workflow_runs
```text
id, workflow_id, workflow_version, status, current_node_id,
progress, error, input_uri, created_at, updated_at
```
### node_instances
```text
id, node_id, status, pid, address, started_at, last_used_at,
busy_since, error
```
### artifacts
```text
id, run_id, node_id, name, uri, mime_type, size, created_at
```
## 8. API 设计
### 管理端
```text
GET /api/admin/nodes
POST /api/admin/nodes
GET /api/admin/nodes/{node_id}
DELETE /api/admin/nodes/{node_id}
GET /api/admin/node-instances
POST /api/admin/node-instances/{id}/stop
GET /api/admin/workflows
POST /api/admin/workflows
GET /api/admin/workflows/{workflow_id}
PUT /api/admin/workflows/{workflow_id}
POST /api/admin/workflows/{workflow_id}/validate
POST /api/admin/workflows/{workflow_id}/publish
```
### 用户端
```text
GET /api/apps
POST /api/apps/{workflow_id}/runs
GET /api/runs/{run_id}
GET /api/runs/{run_id}/events
GET /api/runs/{run_id}/artifacts/{artifact_name}
```
上传接口使用 `multipart/form-data`
```text
POST /api/apps/{workflow_id}/runs
Content-Type: multipart/form-data
body: file=video.mp4
```
进度接口使用 SSE
```text
GET /api/runs/{run_id}/events
Accept: text/event-stream
```
## 9. 前端设计
### 管理后台
页面:
- `/admin/nodes`:节点注册列表。
- `/admin/workflows`:工作流列表。
- `/admin/workflows/{id}`React Flow 画布。
- `/admin/workflows/{id}/publish`:发布确认。
画布能力:
- 左侧节点面板,按 capability 分组。
- 拖拽节点到画布。
- 节点参数面板。
- 保存、校验、发布。
MVP 不实现节点在线调试器,只实现“保存 -> 校验 -> 发布 -> 后台试跑”。
### 用户端
页面:
- `/`:已发布工作流列表。
- `/app/{workflow_id}`:上传页。
- `/runs/{run_id}`:进度页和结果下载。
用户端不展示任何工作流细节,只展示输入表单、进度、产物。
## 10. 示例工作流
### 节点清单
| 节点 | capability | 作用 |
| --- | --- | --- |
| `ffmpeg-extract` | media | 提取 16kHz 单声道音频 |
| `faster-whisper` | asr | 日语语音转写为 SRT |
| `srt-normalize` | subtitle | 清洗 SRT 格式 |
| `llm-translate` | llm | 调用 Ollama/OpenAI 兼容接口翻译 |
| `srt-to-dual-eye-ass` | subtitle | 生成 VR 双眼 ASS |
### 验收标准
1. 管理员注册上述节点,画一条工作流并发布。
2. 用户上传一个测试视频。
3. 后端自动按 DAG 执行提音、转写、翻译、ASS 转换。
4. 用户能看到进度并能下载 `.CN.srt``_dual_eye.ass`
5. 节点空闲超过 TTL 后进程被回收。
6. 新注册一个 ASR 节点后,编辑器中可以替换节点并重新发布,不需要改业务代码。
## 11. 技术选型
```text
Backend: Python 3.12 + FastAPI + Pydantic + SQLite
Executor: 单进程调度器 + 子进程节点
Node host: Python HTTP 服务(Uvicorn
Storage: 本地 storage/ 目录
Admin UI: React + Vite + React Flow
User UI: React + Vite
Deploy: Docker Compose
```
MVP 不引入 Redis 和 Celery,因为单机单调度器已经可以演示核心概念。任务状态持久化在 SQLite,节点状态由节点管理器维护。
## 12. 实现里程碑
### M1:节点基础能力
- 节点注册表。
- 节点管理器。
- 一个 `echo` 示例节点。
- 节点生命周期与 TTL 回收。
### M2:工作流执行
- 工作流 CRUD 和版本化。
- DAG 校验。
- 调度器按拓扑顺序执行。
- WorkflowRun 状态机和产物管理。
### M3:用户服务闭环
- 上传接口。
- 任务状态和 SSE 进度。
- 产物下载。
### M4:管理后台 UI
- React Flow 工作流画布。
- 节点注册页面。
- 发布流程。
### M5:字幕演示工作流
- ffmpeg 提音。
- faster-whisper 转写。
- LLM 翻译。
- SRT 转 VR 双眼 ASS。
- 完整端到端验收。
## 13. 后续扩展路径
- SQLite -> PostgreSQL。
- 本地文件 -> MinIO/S3。
- 单机调度器 -> Redis + Celery/Temporal。
- 子进程节点 -> 容器节点 + Kubernetes。
- 节点管理器 -> KEDA 自动扩缩和 scale-to-zero。
- 注册表 -> 插件市场。
- 单用户 -> 多租户、鉴权、配额、计费。