以“小而稳”的方式实现任务交换平台第一版,使其能够可靠运行在单台 VPS 上。
实现优先级如下:
- 简单可落地
- 全流程可追踪
- 先支持文件
- 给后续扩展保留清晰边界
- 后端:FastAPI
- 模板引擎:Jinja2
- 页面交互:HTMX
- ORM 与迁移:SQLAlchemy + Alembic
- 数据库:PostgreSQL
- 文件存储:先做本地磁盘抽象,后续可替换
- 反向代理与 HTTPS:宿主机已有的 Caddy 或 Nginx
- 部署方式:Docker Compose 运行
app + db
这套组合的原因:
- Python 更适合接 Agent 生态和自动化逻辑
- 服务端渲染页面比单独做 SPA 更快落地
- PostgreSQL 足够支撑第一版
- 本地磁盘存储在 VPS 上运维成本最低
task-exchange-platform/
README.md
README.zh-CN.md
docs/
PRODUCT.md
PRODUCT.zh-CN.md
DEVELOPMENT_GUIDE.md
DEVELOPMENT_GUIDE.zh-CN.md
examples/
task-package/
submission/
app/
main.py
config.py
db.py
deps.py
models/
schemas/
routes/
services/
storage/
templates/
static/
migrations/
tests/
deploy/
docker-compose.yml
表示人类、Agent 或服务账号。
建议字段:
idtypenamestatusreasoning_tierbrowser_capabilitycompute_capacityspeed_tierlast_seen_at
建议字段:
idtitledescriptionstatuscreated_by_actor_idassigned_to_actor_idexecutor_constraintsreasoning_tierbrowser_requirementcompute_requirementspeed_prioritycreated_atupdated_at
建议字段:
idtask_idversionmanifest_jsonbundle_pathsha256created_by_actor_idcreated_at
建议字段:
idtask_idexecutor_actor_idstatusprogress_percentlease_untilstarted_atended_atsummary
建议字段:
idtask_run_idsubmitted_by_actor_idsummaryresult_jsonreview_statusreviewed_by_actor_idreviewed_atcreated_at
MVP 阶段建议只保留一个统一的文件表。
建议字段:
idtask_idrun_idsubmission_iduploaded_by_actor_idkindoriginal_namestored_namemime_typeextensionsize_bytesstorage_pathsha256created_at
记录任务生命周期中的关键事件。
建议字段:
idtask_idrun_idactor_idevent_typepayload_jsoncreated_at
采用两种入口,但都映射到同一个 Actor 模型:
- 人类:登录后使用 Session/Cookie
- Agent:使用 Bearer API Key
业务逻辑层不能分裂成两套系统。无论是人类还是 Agent,都应该调用同一套领域服务。
POST /api/tasksGET /api/tasksGET /api/tasks/{task_id}POST /api/tasks/{task_id}/claimPOST /api/tasks/{task_id}/progressPOST /api/tasks/{task_id}/submitPOST /api/tasks/{task_id}/approvePOST /api/tasks/{task_id}/rejectGET /api/files/{file_id}/download
GET /api/actors/me
服务端渲染的任务列表页,支持筛选:
- 状态
- 执行者限制
- 推理等级
- 浏览器需求
任务详情页,展示:
- 任务元数据
- 任务包文件列表
- 事件历史
- 提交结果文件列表
- 审核面板
基于表单的任务创建页,使用 multipart/form-data 上传。
用于运维可见性的 Actor 列表页。
第一版先实现文件系统存储服务。
建议目录结构:
data/
files/
YYYY/
MM/
DD/
<file-id>-<sanitized-name>
这样做的原因:
- 实现简单
- 不把业务语义强耦合到磁盘目录结构
- 后续迁移到对象存储更方便
单独实现一个任务包解析服务,用于:
- 校验
manifest.yaml - 把元数据写入数据库
- 将文件抽取到存储层
- 创建文件元数据记录
不要把解析逻辑直接写进路由处理函数。
- 定稿一版 manifest 契约
- 建立 SQLAlchemy 模型
- 打通任务创建、领取、进度、提交、审核主链路
- 增加 Web 页面与 Agent API Key
- 增加 Alembic 迁移和健康检查
- 强化 manifest schema 校验和版本化
- 细化登录与权限控制
- 增强运维可观测性
- 补齐 PostgreSQL 生产配置说明
建议本地开发循环:
- 启动 PostgreSQL
- 执行数据库迁移:
alembic upgrade head - 以热重载方式启动 FastAPI
- 上传一个示例任务包
- 通过 API 完成领取与提交
- 在浏览器中验证任务页面和文件下载
推荐命令:
pip install -r requirements.txt
alembic upgrade head
uvicorn app.main:app --reload配置建议:
- 默认
AUTO_INIT_DB=false - 测试环境显式设置
AUTO_INIT_DB=true
健康检查接口:
GET /healthzGET /readyz
建议配合阅读:
docs/DEPLOYMENT_LOCAL.zh-CN.md
推荐的单机部署组成:
- FastAPI 应用容器
- PostgreSQL 容器
- 持久化挂载卷,用于
data/
反向代理不再由本仓库内置提供。Compose 会把应用绑定到 VPS 宿主机
127.0.0.1:8000,再由你机器上已有的 Caddy 或 Nginx 转发进去。
最小部署建议:
- 开启 HTTPS
- 应用端口仅对宿主机反代开放
- 备份 PostgreSQL 和文件目录
- 所有密钥和配置都放环境变量,不写入 Git
- 生产环境设置
AUTO_INIT_DB=false - 容器启动前执行
alembic upgrade head
宿主机 Caddy 最小示例:
tasks.example.com {
encode gzip
reverse_proxy 127.0.0.1:8000
}第一版至少做到:
- API Key 只存哈希值
- 文件下载必须鉴权
- 校验上传文件大小和扩展名
- 清洗文件名
- 记录所有审核决策
- 对外接口加基础限流
MVP 必须覆盖的测试:
- manifest 校验测试
- 任务状态流转测试
- claim 权限测试
- 文件上传下载测试
- 提交与审核测试
- 路由层保持轻薄
- 业务逻辑写入 services
- 请求和响应都用明确 schema
- 文件存储必须走抽象接口
- 每个重要状态变化都写入 event
建议按这个顺序开始编码:
- 强化 manifest schema 校验和版本管理
- 增加更细的登录与权限控制
- 完善 PostgreSQL 生产配置说明
- 扩展运维观测与任务筛选能力