Files

458 lines
11 KiB
Markdown
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.
# 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。
- 注册表 -> 插件市场。
- 单用户 -> 多租户、鉴权、配额、计费。