233 lines
16 KiB
Markdown
233 lines
16 KiB
Markdown
# AGENTS.md
|
||
|
||
## 项目定位
|
||
|
||
本仓库是 WOV AI Workflow Platform 的工作区 meta-repo,不参与业务逻辑,也不包含平台或节点的业务代码。它的作用是维护跨仓库协调信息,把 API、前端、基础设施和各个模型节点关联起来。
|
||
|
||
业务代码分别放在独立 Git 仓库中,每个模型节点也是一个独立 Git 仓库,可以单独管理版本、发布和部署。
|
||
|
||
平台的目标是让管理员在后台注册和编排各种模型节点,把编排结果发布成独立服务;普通用户只上传视频或输入数据,由后端按工作流动态组装节点并执行。节点在无人使用时回收,新模型出现后可以快速注册为新节点并复用到已有工作流或新应用中。
|
||
|
||
详细 MVP 设计见 [MVP-DESIGN.md](./MVP-DESIGN.md)。
|
||
|
||
## 仓库结构与 Git 管理
|
||
|
||
本仓库的定位与 LPT 工作区 meta-repo 一致:主仓库不保存产品代码,只保存跨仓库说明、目录约定和初始化方式。子项目目录各自是独立 Git 仓库。
|
||
|
||
**提交规则(强制)**:未经用户明确许可,禁止对任何子仓库或本仓库执行 `git commit` / `git push`;改动完成后汇报并等待用户指示。
|
||
|
||
## Python 环境与 uv 管理
|
||
|
||
所有 Python 子项目统一使用 uv 管理虚拟环境和依赖,禁止直接使用 pip 修改依赖。
|
||
|
||
### 基础命令
|
||
|
||
```powershell
|
||
uv sync # 在子项目目录中安装当前 pyproject.toml 的依赖(含 dev group)
|
||
uv run <command> # 在子项目虚拟环境中运行命令
|
||
uv add <package> # 添加依赖并更新 lockfile
|
||
uv lock # 仅更新 uv.lock
|
||
```
|
||
|
||
### 约定
|
||
|
||
- 每个 Python 子项目在自己的目录下执行 `uv sync`,虚拟环境位于对应目录的 `.venv`。
|
||
- 测试依赖放在 `[dependency-groups] dev`,由 `uv sync` 默认安装,不需要额外 `--extra dev`。
|
||
- 子项目之间的本地依赖使用路径依赖,例如 `wov-api` 和 `wov-node-*` 通过 `../wov-sdk` 引用 `wov-sdk`。
|
||
- 新增 Python 依赖时先进入对应子项目目录,使用 `uv add`,不要修改系统 Python 或全局环境。
|
||
- `uv.lock` 属于对应子仓库,由子仓库单独管理。
|
||
- 不在 meta-repo 根目录创建统一 Python 环境;环境必须归属各独立业务仓库。
|
||
- 不使用 `pip install`、`pip freeze` 或手写 `requirements.txt` 替代 uv。
|
||
|
||
## 测试与覆盖率
|
||
|
||
- 所有 Python 子项目必须达到 100% 行覆盖率。
|
||
- 测试必须调用真实代码路径,不得在测试类中重写业务逻辑来模拟被测功能。
|
||
- 只允许在 I/O 边界使用 mock/stub:文件系统、网络、子进程、环境变量、时间。
|
||
- 每个子项目使用 pytest,并在 CI 中启用 `--cov-fail-under=100`,覆盖率不达标视为失败。
|
||
- 新增业务代码时,必须同步补齐覆盖其真实路径的测试。
|
||
|
||
## 代码注释规范
|
||
|
||
- 本仓库及所有子仓库的源码(Python、JavaScript、HTML、CSS、TOML 等支持注释的文件)必须配有详细中文注释,说明模块/文件职责、核心类与函数的作用以及关键逻辑,确保后续维护人员无需通读全部实现即可快速理解工作原理。
|
||
- 新增或修改代码时,必须同步补充或更新对应注释;不得删除已有注释。
|
||
- 测试代码同样必须配有中文注释,说明每条测试验证的行为与覆盖的路径。
|
||
- JSON 数据文件(例如 `node.manifest.json`)按 JSON 规范不支持注释,字段语义以 `wov-sdk` 的 `NodeManifest` 模型注释和各子仓库 AGENTS.md 为准;修改 JSON 字段时须同步更新文档。
|
||
- 提交前检查是否为新代码补齐注释,未补注释的代码视为未完成。
|
||
|
||
## 目标运行环境
|
||
|
||
- 本服务的最终部署目标是 Linux,通常以 Docker/Kubernetes 容器运行。
|
||
- 当前 Windows 只作为本地开发环境,不允许在业务代码中写死 Windows 路径、盘符或 Windows 专用命令。
|
||
- 路径处理统一使用 `pathlib`;节点 Python 解析必须同时兼容 Windows 的 `.venv/Scripts/python.exe` 和 Linux 的 `.venv/bin/python`。
|
||
- ffmpeg 在 Linux 上可使用系统包,也允许通过 `imageio-ffmpeg` 使用内置二进制,节点代码不能假设 ffmpeg 一定在 PATH。
|
||
- 测试必须可以在 Windows 和 Linux 上运行;涉及平台分支的代码应同时覆盖两种路径解析。
|
||
- 100% 行覆盖率只保证代码路径被覆盖,不覆盖外部运行环境状态,例如端口占用、防火墙、权限和残留进程。
|
||
- 端口、进程、网络权限类问题不属于行覆盖率范围,应通过启动检查、端口检查和 uvicorn 冒烟测试补充。
|
||
- 本地出现 `WinError 10013` / `WinError 10048` 时,先用 `netstat -ano | findstr :<port>` 确认是否有残留监听进程,再决定停进程或换端口。
|
||
|
||
## Windows / PowerShell 执行规则
|
||
|
||
- 默认 shell 视为 Windows PowerShell 5.1;不要假设 Bash、zsh 或 PowerShell 7。必要时先查 `$PSVersionTable.PSVersion`。
|
||
- Windows 桌面、Visual Studio/MSBuild、WPF/WinForms/WinUI、COM、注册表、服务、系统托盘、PyInstaller、UI 自动化等任务优先用 Windows 原生环境;不要默认切 WSL。
|
||
- 仅在 Linux 部署、Bash 脚本、Linux 工具链或项目本身位于 WSL 时考虑 WSL;跨环境前确认仓库路径、依赖和运行目标。
|
||
- 禁止把 Bash 语法交给 PowerShell:`python - <<'PY'`、`cat <<EOF`、`export`、`source`、`rm -rf`、`cp -r`、`xargs`、Bash 后台 `&`。
|
||
- PowerShell 中 `&` 是调用运算符;URL 或参数含 `&` 时整体单引号引用。
|
||
- 避免 PowerShell 5.1 下使用 Bash 风格 `&&` / `||`;顺序步骤用多行 PowerShell、短命令或多次工具调用。
|
||
- 参数含空格、括号、中文、`&|;><$` 或引号时默认用单引号;只有需要变量插值时才用双引号。
|
||
- 外部程序路径可能有空格时,用 `& 'C:\path with spaces\tool.exe' arg1`;多参数外部命令优先数组 splatting。
|
||
- PowerShell 数组传给外部程序时直接 splat;不要把多个路径或参数拼成一个带空格的字符串。
|
||
- 文件操作优先 PowerShell 原生命令和 `-LiteralPath`;遇到参数不存在先按 PowerShell 5.1 兼容写法处理。
|
||
- 复杂 Python 不用 `python -c`;涉及 SQL、JSON、中文、反斜杠路径、换行或多层引号时,用仓库脚本、临时 `.py` 或 `apply_patch`。
|
||
- 禁止在 PowerShell 用 Bash here-doc。临时传 Python 源码只允许 PowerShell here-string,且尽量保持 ASCII。
|
||
- Python 源码含中文常量时,不通过 PowerShell 管道传给 `python -`;用 UTF-8 脚本文件、仓库脚本或 `\uXXXX`。
|
||
- 不只依赖 `chcp 65001` 解决编码;必要时同时设置 `$OutputEncoding`、`[Console]::InputEncoding`、`[Console]::OutputEncoding`、`PYTHONUTF8`、`PYTHONIOENCODING`。
|
||
- 搜索文本/文件优先 `rg` / `rg --files`;多个根目录作为多个独立参数传入。
|
||
- `sqlite3.exe` 不存在时用 Python `sqlite3` 查询,不反复尝试不存在的 CLI。
|
||
- 编辑文件优先 `apply_patch`;不要用复杂 PowerShell 字符串重写文件。
|
||
- 数据库或生产内容写操作前先查询当前数据;写入必须有明确筛选条件,禁止无条件 `DELETE` / `UPDATE`。
|
||
- 出现 `ParserError`、`CommandNotFoundException`、`ParameterBindingException`、`Cannot find path`、Python `SyntaxError` 时,先排查 shell 语法、引用、PATH、PowerShell 5.1 兼容和 `workdir`。
|
||
- 同一 PowerShell 命令连续失败两次后,停止微调长命令;改短命令、脚本文件、数组 splatting 或分步验证。
|
||
|
||
### 子仓库规划
|
||
|
||
| 目录 | 用途 | 仓库 |
|
||
| --- | --- | --- |
|
||
| `subtitle-generate` | WOV meta 仓库 | `ssh://git@git.cat-shark.xyz:2222/cat-shark/subtitle-generate.git` |
|
||
| `wov-api` | FastAPI 后端:节点注册、工作流、调度、用户 API | `ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-api.git` |
|
||
| `wov-web` | React 管理后台和用户端 | `ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-web.git` |
|
||
| `wov-sdk` | 节点协议、Manifest、SDK 与测试工具 | `ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-sdk.git` |
|
||
| `wov-node-echo` | 示例节点,验证节点协议和生命周期回收 | `ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-node-echo.git` |
|
||
| `wov-node-ffmpeg` | 提音、转码、媒体处理节点 | `ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-node-ffmpeg.git` |
|
||
| `wov-node-whisper` | faster-whisper ASR 节点 | `ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-node-whisper.git` |
|
||
| `wov-node-llm` | LLM 翻译/润色节点 | `ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-node-llm.git` |
|
||
| `wov-node-ass` | SRT/ASS 和 VR 双眼字幕节点 | `ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-node-ass.git` |
|
||
| `wov-docs` | 系统文档与设计文档 | 待创建:`ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-docs.git` |
|
||
| `wov-infra` | Docker/Kubernetes/部署清单 | 待创建:`ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-infra.git` |
|
||
|
||
已推送仓库的分支均为 `master`。SSH 端口为 `2222`,认证使用本机 `id_ed25519` key。节点数量不限于上表,新增模型时新增独立仓库即可。
|
||
|
||
### meta-repo 规则
|
||
|
||
- 主仓库只维护 `AGENTS.md` 和 `.gitignore`,不创建业务代码。
|
||
- MVP 阶段设计文档暂时保留在主仓库;`wov-docs` 建立后迁出。
|
||
- `.gitignore` 忽略所有子项目目录,避免把独立 Git 仓库提交进主仓库。
|
||
- 首次 clone 主仓库后,子项目目录缺失时按本表 clone;主仓库自身不复制子项目内容。
|
||
- 修改子项目时必须进入对应目录,并使用 `git -C <目录> <command>` 执行 Git 操作。
|
||
- 禁止在 meta-repo 根目录执行跨仓库 `git add .`,禁止删除子项目内的 `.git`。
|
||
- 每个节点仓库必须包含 `AGENTS.md`、`node.manifest.json`,并使用 Git tag 作为节点版本。
|
||
- 平台运行时不应依赖 meta-repo 源码树中的节点代码,节点由节点注册中心按仓库地址和版本拉取。
|
||
|
||
### 子仓库初始化
|
||
|
||
```powershell
|
||
git clone -b master ssh://git@git.cat-shark.xyz:2222/cat-shark/subtitle-generate.git subtitle-generate
|
||
git clone -b master ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-api.git wov-api
|
||
git clone -b master ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-web.git wov-web
|
||
git clone -b master ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-sdk.git wov-sdk
|
||
git clone -b master ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-node-echo.git wov-node-echo
|
||
git clone -b master ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-node-ffmpeg.git wov-node-ffmpeg
|
||
git clone -b master ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-node-whisper.git wov-node-whisper
|
||
git clone -b master ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-node-llm.git wov-node-llm
|
||
git clone -b master ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-node-ass.git wov-node-ass
|
||
# wov-docs / wov-infra 尚未创建,创建后执行:
|
||
# git clone -b master ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-docs.git wov-docs
|
||
# git clone -b master ssh://git@git.cat-shark.xyz:2222/cat-shark/wov-infra.git wov-infra
|
||
```
|
||
|
||
进入或修改某个子仓库前,先读取该子仓库根目录的 `AGENTS.md`;如果缺失,则读取 `README.md`。
|
||
|
||
## 最终设计目标
|
||
|
||
以下原则是平台的北极星,任何设计决策都应朝这些方向移动:
|
||
|
||
1. 模型能力标准化。每个模型都包装成统一协议下的节点,节点声明能力、输入输出、资源要求和生命周期策略。
|
||
2. 工作流即数据。工作流以版本化 DAG 存储,不写死在业务代码里;发布后的工作流自动成为面向用户的服务。
|
||
3. 节点按需运行。节点只在被使用时初始化,空闲后卸载模型、停止进程并回收资源。
|
||
4. 动态组装。用户触发工作流时,调度器按 DAG 动态申请节点实例并执行,而不是预启动整条流水线。
|
||
5. 高复用。ASR、LLM、TTS、字幕处理等节点可被任意工作流复用;新增模型通过注册新节点接入,无需重写业务应用。
|
||
6. 可弹性伸缩。API、调度器、节点实例最终可以独立水平扩展,节点宿主可以漂移,不依赖单机状态。
|
||
|
||
## 最终目标下的关键不变式
|
||
|
||
后续开发中,以下约束不应被破坏:
|
||
|
||
- 节点之间不直接调用,只通过产物 URI 交换数据。
|
||
- 节点实例必须无状态,中间产物落在共享存储,不放在节点进程内部。
|
||
- 工作流必须是数据文件或数据库记录,不允许把步骤顺序写死在应用代码里。
|
||
- 节点管理器是节点实例生命周期的唯一所有者,API 和调度器不能直接拉起或杀死节点进程。
|
||
- 节点协议和 Manifest 要长期稳定,宁可先少做功能,也不轻易改协议。
|
||
- 存储、队列、调度器都要通过抽象边界隔离,方便从单机实现替换为分布式实现。
|
||
- 用户端永远只看到“输入 -> 进度 -> 结果”,不暴露工作流细节。
|
||
|
||
## MVP 的妥协理由
|
||
|
||
MVP 采用单机简化实现,原因是先验证核心抽象,而不是过早引入分布式复杂度。每个妥协都必须保留通往最终目标的路径。
|
||
|
||
### 1. 单机运行,而不是 Kubernetes
|
||
|
||
- 妥协:MVP 在一台机器上运行 API、调度器和节点进程。
|
||
- 理由:先验证节点协议、生命周期和动态组装是否成立。
|
||
- 通往目标的路径:节点已经独立成进程,后续可以把进程宿主替换为容器 Pod,把节点管理器升级为集群调度器。
|
||
|
||
### 2. SQLite,而不是 PostgreSQL
|
||
|
||
- 妥协:MVP 使用 SQLite 持久化节点、工作流和任务状态。
|
||
- 理由:降低运维成本,单机足够承载演示数据。
|
||
- 通往目标的路径:数据访问通过 Repository 层隔离,后续替换为 PostgreSQL 不需要改业务逻辑。
|
||
|
||
### 3. 本地文件存储,而不是 S3/MinIO
|
||
|
||
- 妥协:MVP 使用本地 `storage/` 目录保存输入和产物。
|
||
- 理由:减少一个基础设施依赖,方便本地调试。
|
||
- 通往目标的路径:所有产物都使用 URI 传递,禁止直接使用裸路径;后续引入存储适配器并切换到对象存储。
|
||
|
||
### 4. 单机调度器,而不是 Celery/Temporal
|
||
|
||
- 妥协:MVP 由进程内调度器顺序执行工作流节点。
|
||
- 理由:先证明工作流 DAG 和节点调度的正确性。
|
||
- 通往目标的路径:调度逻辑和任务队列解耦,WorkflowRun 状态已持久化,后续可以替换为 Redis + Celery/Temporal。
|
||
|
||
### 5. 子进程节点,而不是独立容器
|
||
|
||
- 妥协:MVP 节点以本地子进程方式启动,通过 localhost HTTP 通信。
|
||
- 理由:避免容器网络、镜像仓库和资源调度带来的初期复杂度。
|
||
- 通往目标的路径:节点协议是 HTTP,进程启动参数来自 Manifest,后续可直接包成容器并保留同一协议。
|
||
|
||
### 6. 只实现线性链和简单 DAG
|
||
|
||
- 妥协:MVP 先支持顺序执行和少量并行。
|
||
- 理由:字幕示例工作流是线性链,先跑通完整闭环。
|
||
- 通往目标的路径:调度器已经按 DAG 拓扑排序,复杂分支和循环留到后续阶段。
|
||
|
||
### 7. 无鉴权、计费、多租户
|
||
|
||
- 妥协:MVP 不实现用户认证、配额和计费。
|
||
- 理由:这些不是验证平台核心抽象的必要条件。
|
||
- 通往目标的路径:API 设计上保留用户与工作流的边界,后续增加 auth 中间件和用量记录。
|
||
|
||
### 8. 不做在线插件热部署
|
||
|
||
- 妥协:MVP 通过注册接口登记节点,不实现插件市场或热加载。
|
||
- 理由:先保证节点协议和生命周期稳定。
|
||
- 通往目标的路径:节点注册表结构保留版本和 Manifest,后续可以扩展为可下载、可安装的插件包。
|
||
|
||
## MVP 完成标准
|
||
|
||
1. 管理员可以注册节点,并在画布上编排工作流后发布。
|
||
2. 用户上传视频,后端自动组装节点完成“提音 -> 转写 -> 翻译 -> ASS 转换”。
|
||
3. 用户能看到进度并下载最终产物。
|
||
4. 节点空闲超过 TTL 后被回收,新任务到达时能重新初始化。
|
||
5. 新增一个同能力节点后,不修改业务代码即可替换工作流中的节点并重新发布。
|
||
|
||
## 开发时的检查清单
|
||
|
||
每完成一个功能,都应检查:
|
||
|
||
- 是否仍然满足“工作流即数据”。
|
||
- 节点是否无状态,是否只通过产物 URI 通信。
|
||
- 是否新增了绕过节点管理器的生命周期操作。
|
||
- 是否新增了无法平滑迁移到对象存储或分布式队列的硬编码路径。
|
||
- 是否把工作流步骤、节点协议或模型调用写死在了业务代码里。
|
||
- 是否保持了“用户端只看到输入、进度、结果”的边界。
|