Skip to content

[犀牛鸟-F1]:YOLO-Master Studio —— FastAPI 独立任务引擎与 React 作业管理平台 - #299

Merged
isLinXu merged 53 commits into
Tencent:mainfrom
9-71:rhino-f1-dev
Oct 13, 2026
Merged

isLinXu merged 53 commits into
Tencent:mainfrom
9-71:rhino-f1-dev

Conversation

@9-71

@9-71 9-71 commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

1. 任务目标与完成度

层级 官方目标 本 PR 落地 状态
P0 保留推理;任务列表、状态、日志、产物;predict;system doctor 统一 Job 状态、Live Logs、Artifacts、predict、diagnose/system doctor ✅
P1 train/val/predict/export 统一协议;取消、超时、批量推理、路径白名单、错误回传 五类任务统一协议;cancel/timeout;batch predict;server-owned whitelist;统一错误模型 ✅
P2 E3 路由分析,或 FastAPI + React 前后端分离 独立 FastAPI Task Engine + React/Vite console + Gradio REST 化 ✅

超出基础要求的工程化增强

  • Single Lifecycle Owner
  • CPU / GPU 独立队列与静态并发槽位
  • spawn worker 与 Windows / Linux 进程树治理
  • terminal ownership 与 restart recovery
  • credential sanitization 与 manifest-only artifact exposure
  • symlink / broken-symlink fail-closed
  • Windows / Ubuntu 双平台验证
  • P2 REST E2E Harness

交付物与证据入口

  • 平台内核:核心实现位于 main_engine.py、api/v1/jobs.py、f1/
  • API / Schema:api/v1/jobs.py、core/schema.py、docs/api/job_schema.json
  • 任务与产物页:frontend/、web/、app.py
  • 安全测试:tests/f1/、tests/api/、docs/f1_security_test_report.md
  • 操作手册:docs/f1_user_manual.md
  • 补充工程文档:f1/README.md、f1/RUNTIME_LIFECYCLE.md、f1/handlers/README.md、f1/handlers/USAGE.md

2. 改动摘要与运行架构

本 PR 基于官方冻结 Baseline,将原先与 UI 耦合较紧的任务执行与状态管理能力收敛为独立的 F1 异步任务平台,并完成统一任务协议、生命周期治理、安全边界、FastAPI 服务化与多前端接入。

核验区间:

  • Official Baseline:Tencent/YOLO-Master main @ 2026-08-21 23:59:59 UTC+8
  • Baseline commit:acce839c7e895d6b179de7f7093fa879e237cc7b
  • Final HEAD:ab57103f48c19889b5aec8a8b698759fc2de0043

实际运行架构

Gradio UI ── StudioJobsApiClient ─┐
Zero-build console (/)  ──────────┼── HTTP / REST
React/Vite console (/console)  ───┘
                                  │
                                  ▼
                         FastAPI Task API
                                  │
                                  ▼
               JobsManager (single lifecycle owner)
                       │                   │
                 CPU queue           GPU queue
                       │                   │
                      fixed-slot supervisors
                               │
                               ▼
                  ManagedWorker (spawned process)
                               │
                               ▼
                 JobDispatcherStateMachine
                               │
                               ▼
                    TaskHandlerRegistry
                               │
                               ▼
           train / val / predict / export / diagnose
                               │
                               ▼
                  Ultralytics YOLO Python API

FastAPI 服务内的单例 JobsManager 是生产任务状态、排队、取消、超时、本地持久化与 terminal publication 的唯一生命周期所有者。

任务计算本身运行在 spawn 子进程中,因此这里的架构约束是:

单 API 服务进程 / 单生命周期所有者

而不是整个 Studio 只有一个操作系统进程。

Gradio 不再维护第二套生产 worker 或 job 状态,而是通过 StudioJobsApiClient 调用统一 REST API;f1/ui/jobs_tab.py 中相关 manager 路径仅保留用于兼容。


3. 核心机制

3.1 生命周期与终态所有权

统一任务类型:

  • train
  • val
  • predict
  • export
  • diagnose

统一任务状态:

  • pending
  • running
  • completed
  • failed
  • cancelled

worker 内部由 JobDispatcherStateMachine 驱动:

PENDING → RUNNING → COMPLETED / FAILED

用户取消由 JobsManager 统一协调:

  1. 停止受管进程树;
  2. 发布 CANCELLED / USER_CANCELLED;
  3. 首次取消请求返回 HTTP 202 cancel_requested;
  4. 调用方继续查询直至进入终态;
  5. 对已终态任务重复取消时,直接返回已有终态快照。

终态保护规则:

  • JobsManager 仅在任务仍为非终态时接受 worker completion
  • 迟到的成功或失败 completion 不会覆盖既有 status / result / error
  • timeout 从任务进入 running 后开始计算,不包含 pending queue 等待时间
  • 服务关闭时停止 supervisor 与受管 worker
  • 服务重启后,未完成任务统一修正为:
FAILED / SERVICE_RESTARTED

3.2 队列、Worker 与并发控制

  • CPU 与 GPU 使用独立队列
  • 默认 CPU 并发槽位:2
  • 默认 GPU 并发槽位:1
  • 默认 pending capacity:100
  • pending capacity 满时返回 HTTP 429
  • ManagedWorker 使用独立 spawn 子进程执行具体任务

当前调度属于静态资源槽位模型,暂不包含:

  • 动态资源探测
  • 任务优先级
  • 自动重试

3.3 日志、产物与持久化

持久化

  • 任务状态保存为本地 JSON
  • 通过临时文件替换降低部分写入风险
  • 当前属于 best-effort 本地持久化
  • 不等价于事务数据库或分布式 durable queue

实时日志

Live Logs 使用 HTTP cursor 增量读取,支持:

  • 分页
  • tail
  • 终态后历史查询

终态保护规则:

  • terminal status / result / error 不会被迟到 worker completion 覆盖
  • 已产生或迟到到达的日志仍可继续保留和读取
  • 因此日志流本身不属于 immutable terminal snapshot

任务产物

  • Artifact 下载仅允许访问任务 manifest 中显式登记的文件
  • 不允许通过任意目录浏览扩大可下载范围

3.4 安全边界

执行前安全校验

服务端在任务进入执行链前统一强制:

  • allow_shell = false
  • path_whitelisted = true
  • 客户端提交的 whitelist roots / patterns 不可扩大服务端权限
  • model、data、output 分别按 server-owned trusted roots 校验
  • 网络数据源仅允许配置的 HTTP(S) host
  • 拒绝目录穿越与 sibling-prefix escape
  • 拒绝越界 existing symlink 与 broken symlink
  • 允许受信根目录内尚不存在的普通输出叶子目录
  • 校验安全 job_id
  • Artifact 下载必须精确命中任务 manifest

凭据脱敏

结构化脱敏覆盖:

  • job logs
  • error 信息
  • 持久化字段

第三方库或子进程直接写入 stdout / stderr 的内容,不属于上述结构化脱敏保证。

进程树治理

  • Windows:Job Object
  • Linux:session / process-group / subreaper

上述机制用于取消、关闭与孤儿进程回收,属于生命周期治理,不构成每任务 OS 安全沙箱。


3.5 服务与前端交付

服务入口

FastAPI Task Engine 可独立启动:

python main_engine.py

启动后提供:

  • /health
  • Job REST API
  • OpenAPI

前端结构

  • frontend/:无需 Node 构建的验证控制台,挂载到 /
  • web/:React + TypeScript + Vite 控制台源码
  • web/dist 存在时,React 控制台挂载到 /console
  • Gradio 作为独立进程,通过 StudioJobsApiClient 使用同一 FastAPI 后端
  • start_studio.py 提供 FastAPI + Gradio 组合启动入口

CI 覆盖

当前 CI 覆盖:

  • Python lint
  • format
  • smoke
  • unit test
  • coverage

4. 测试与 CI 证据

4.1 Windows / Python 3.12

执行:

pytest tests/f1/ tests/api/ --cov=f1 --cov=core

结果:

412 passed, 11 skipped, 3 warnings
TOTAL: 2369 statements, 518 missed, 78% coverage

Windows 下 11 个 skip 均为需要系统符号链接创建权限的测试场景。

3 个 warning 包括:

  • 2 个 ONNX exporter deprecation warning
  • 1 个本地 .pytest_cache 写入权限 warning

4.2 F1 Smoke

fast-smoke        PASS
dry-run           PASS
contract          PASS
security guards   PASS
real GPU path     PASS

合计:

5 / 5 PASS

Smoke 覆盖快速执行、dry-run、协议、安全守卫及 GPU 执行路径等基础验证场景。


4.3 其他本地检查

ruff check ...             PASS
ruff format --check ...    PASS
git diff --check           PASS
npm run lint               PASS
tsc --noEmit               PASS

React / TypeScript 源码已通过 lint 与类型检查。


4.4 Ubuntu / Python 3.10

最新 source branch CI:

测试结果:

422 passed, 1 skipped, 3 warnings
TOTAL: 2369 statements, 516 missed, 78% coverage
F1 smoke: 5/5 PASS
Ruff lint: PASS
Ruff format: PASS

Linux 环境实际执行了 Windows 因权限跳过的 symlink / broken-symlink 边界测试。

Windows 本地验证与 Ubuntu CI 共同覆盖了当前实现的主要跨平台行为。


5. 机制验证与边界实验

5.1 终态所有权

覆盖三种终态:

  • completed
  • failed
  • cancelled

并分别注入迟到的成功与失败 worker completion:

3 terminal states × 2 late outcomes = 6 / 6 PASS

验证结果:

  • terminal status 保持不变
  • result / error snapshot 保持不变
  • 迟到 worker completion 不会重新发布任务终态
  • 迟到日志仍可保留与查询,但不会改变既有 terminal metadata

该实验验证了 JobsManager 对任务终态的统一裁决能力。


5.2 实时日志

已验证:

  • cursor 单调前进
  • 分页读取无重复、无丢失
  • tail 请求不会把非终态任务误判为完成
  • cancel 后历史日志仍可读取
  • cancel 后到达的迟到日志仍可保留
  • 日志追加不会反向修改 terminal status / result / error

因此,终态 metadata 与日志流保持明确边界:终态状态与结果不会被迟到 completion 覆盖,日志则继续承担任务可观测性职责。


5.3 安全负向验证

覆盖场景包括:

  • allow_shell=true
  • path_whitelisted=false
  • 客户端伪造 whitelist roots / patterns
  • shell payload
  • .. traversal
  • sibling-prefix escape
  • model / data / output root escape
  • existing symlink escape
  • broken symlink escape
  • 非法 job_id
  • 非 manifest artifact
  • 结构化日志、错误与持久化字段中的凭据泄露场景

上述非法输入均被拒绝,或在进入受控日志、错误与持久化表面前完成脱敏。


6. 可复现性

6.1 基准与验证版本

官方 Baseline 固定为:

Tencent/YOLO-Master main
@ 2026-08-21 23:59:59 UTC+8

Baseline commit:
acce839c7e895d6b179de7f7093fa879e237cc7b

Baseline 用于定义本 PR 的官方对照起点。

当前自动化验证证据对应的 source branch 提交为:

Verified commit:
ab57103f48c19889b5aec8a8b698759fc2de0043

CI Run:
https://github.com/9-71/YOLO-Master/actions/runs/34948210888

验证提交用于关联具体测试结果,不作为长期固定的“最终 HEAD”。


6.2 独立 FastAPI Engine

启动:

python main_engine.py

启动后提供:

GET /health
/api/v1/jobs/*
OpenAPI

6.3 FastAPI + Gradio 组合启动

python start_studio.py

该入口同时启动 FastAPI Task Engine 与 Gradio 客户端,Gradio 通过 StudioJobsApiClient 使用统一 REST 后端。


6.4 F1 / API 测试

pytest tests/f1/ tests/api/ --cov=f1 --cov=core

6.5 REST 端到端验证

仓库提供:

scripts/smoke_p2_engine.py

用于在 FastAPI Engine 已启动的情况下验证 REST 调用链,包括:

  • /health
  • Job 提交
  • 状态查询
  • Live Logs
  • cancel
  • Artifacts
  • 静态产物访问

6.6 自动化验证

CI workflow:

.github/workflows/f1_ci.yml

当前复现证据由以下内容共同构成:

  • 固定官方 Baseline
  • Windows / Ubuntu 双平台测试结果
  • F1 Smoke
  • 终态所有权验证
  • Live Logs 行为验证
  • 安全负向验证
  • REST 端到端验证入口
  • CI workflow
  • 用户手册与运行时工程文档

7. Agent 兼容边界

本 PR 聚焦 F1 任务平台,不重构既有正式 agent/ runtime。

正式 Agent 继续使用自身的 dispatcher、handlers 与异步任务机制;F1 则通过 FastAPI、JobsManager、worker 与 F1 handlers 管理 Studio Job,两套运行时保持明确边界。

Agent 的 yolo.ui.launch 仍可启动 app.py,其中 Jobs 界面通过 StudioJobsApiClient 调用 F1 REST API。因此二者的集成关系是:

Agent UI launch
      ↓
    app.py
      ↓
StudioJobsApiClient
      ↓
F1 REST API

该关系属于 UI / API 层集成,不表示 Agent dispatcher 与 F1 dispatcher / handlers 共用同一运行时。

f1/skills.py 同时保留 F1-native direct-call adapter,可直接复用 F1 dispatcher / handlers,作为 F1 能力的独立调用入口。


8. 已知局限

  1. 单机运行与本地持久化
    当前采用单 API 服务进程与单生命周期所有者,任务状态使用本地 JSON best-effort 持久化;暂不支持多节点调度、分布式 durable queue、任务断点恢复、优先级与自动重试。

  2. 静态资源调度与 HTTP 日志轮询
    CPU / GPU 并发槽位由配置确定,不根据实时负载或显存动态调整;Live Logs 当前采用 HTTP cursor polling,不提供 WebSocket / SSE。

  3. 面向受信部署环境的安全边界
    当前未提供认证、RBAC、租户隔离或每任务 OS sandbox。Windows Job Object 与 Linux process-group / subreaper 用于任务进程生命周期治理,不等同于强安全隔离。

  4. 前端交付方式
    仓库提供 React + TypeScript + Vite 源码,web/dist 由部署方构建后挂载到 /console;零构建控制台仍可直接通过 / 使用。

  5. 部分结果展示与环境复现仍可完善
    OBB / classification 的部分指标展示尚未完全覆盖;运行依赖尚未全面锁定,ONNX export 当前仍存在 legacy exporter deprecation warning。


9. 结果

本 PR 完成了 P0 / P1 要求,并选择 FastAPI + React 前后端分离 路线完成 P2。

围绕统一异步任务平台,进一步形成了以下工程能力:

  • train / val / predict / export / diagnose 统一任务协议
  • JobsManager 单一生命周期所有权与终态保护
  • CPU / GPU 独立队列、静态并发槽位与 spawn worker
  • cancel、timeout、shutdown 与 restart recovery
  • Live Logs 与 manifest-based Artifacts 的完整 Job 闭环
  • 服务端路径白名单、symlink 边界防护与结构化凭据脱敏
  • Gradio、零构建控制台与 React 共用统一 REST 后端
  • Windows / Ubuntu 双平台验证及 CI 自动化证据

最终运行链路收敛为:

多前端
   ↓
统一 REST Contract
   ↓
FastAPI Task API
   ↓
JobsManager
(single lifecycle owner)
   ↓
Queue / ManagedWorker
   ↓
Dispatcher / Handler
   ↓
Ultralytics YOLO

由此将原本分散在界面侧的任务提交、状态、日志、产物与生命周期管理,收敛为独立、统一且可验证的 F1 异步任务平台。

当前验证结论限定于单机、受信部署环境;本 PR 不扩大声明为分布式、多租户、动态资源调度、强事务持久化或每任务 OS 级强隔离平台。

9-71 added 30 commits August 24, 2026 17:47
- Refactor job dispatch layer into dynamic TaskHandlerRegistry pattern
- Implement JobDispatcherStateMachine with strict lifecycle and exception safety
- Deliver 4 concrete task handlers: diagnose, predict, train, and export
- Enforce fail-closed security: path whitelisting, shell blocking, and isolation
- Add comprehensive test suite (86 passed) and ensure 100% ruff compliance
- Refactor job dispatch layer into dynamic TaskHandlerRegistry pattern
- Implement JobDispatcherStateMachine with strict lifecycle and exception safety
- Deliver 4 concrete task handlers: diagnose, predict, train, and export
- Enforce fail-closed security: path whitelisting, shell blocking, and isolation
- Add comprehensive test suite (86 passed) and ensure 100% ruff compliance
- Align all module documentation to standard technical English
- Implement SystemDoctorSkill and PredictSkill exposing standard tool metadata
- Enforce fail-closed security and schema translation to JobDispatcherStateMachine
- Add 15 unit tests covering skills execution, validation, and security rejection
- Fix singleton registry state pollution in test_handlers_framework with backup/restore fixtures
- Achieve 101/101 test suite pass rate with 100% ruff compliance
- Deliver JobsManager with thread-safe lifecycle and non-blocking polling
- Build Gradio Jobs Tab UI with submission forms, live log stream, and artifacts preview
- Fix non-reentrant lock self-deadlock in cancel_job and isolate mock events
- Complete standalone manual verification (diagnose, predict, security violation)
- Replace literal '作业' with standard AI engineering term '任务' across UI labels and alerts
- Refine device hints and artifact tab labels
- Update doctests and regression assertions to lock new terminology
- core/security.py: translate mixed Chinese/English docstrings
  (sanitize_env_dict, sanitize_log_text) to Google-style English
- docs/reports/f1-evaluation-report: serve Instrument Sans / JetBrains Mono
  via Google Fonts and echarts/mermaid via jsDelivr CDN instead of vendored
  .ttf and .min.js files
- untrack vendored binary/JS assets (git rm --cached) and add .gitignore
  rules to prevent re-committing them
@isLinXu

isLinXu commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator

整体做得不错,测试覆盖和安全边界都比较扎实。几个问题说一下:

PR 太大了,27K 行 90 个文件,review 起来很吃力,建议拆成核心引擎、FastAPI 服务、前端、文档几个分别提。
f1/smoke_run.log 是运行产物,别提交进来了,加到 gitignore 里。
3d1cc7f 和 f85985a 两个 commit 内容一样,合并前 squash 一下。
jobs_manager.py 一千多行有点重了,持久化、日志、产物、队列全塞一个类里,后面维护会很痛苦,建议拆一下。
JSON 持久化不太靠谱,写一半挂了状态文件就坏了,至少加个 .bak 回退。
没有 graceful shutdown,训练任务跑到一半关服务会直接丢进度,应该先让 worker 存 checkpoint 再退。
没有认证,现在只能 localhost 用,后续要上至少加个 token auth。
文档散在六七个文件里,收一收放到 docs/f1/ 下面统一管。

另外日志轮询、API 分页、GPU 健康检查这些可以后面再补,不着急。Skills 和 Agent 集成到 Studio 平台的事也可以作为后续规划。

@9-71

9-71 commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor Author

根据之前的 review 反馈,我正在将这个较大的 PR 拆分为多个更小、可独立审查的 PR,以降低 review 成本。

目前的拆分进度:

后续 PR 提交后,我会持续更新这里的关联链接。

PR #299 保留作为完整实现和历史讨论的参考。感谢之前的审查与建议!

@isLinXu
isLinXu merged commit 39b5a2b into Tencent:main Oct 13, 2026
1 check passed
@9-71

9-71 commented Oct 14, 2026

Copy link
Copy Markdown
Contributor Author

感谢合并 #299!也注意到您通过 #314 对原 F1 平台进行了主线集成和冲突处理。

我重新检查了当前主线:#299 的 FastAPI、前端及 F1 Runtime 已经落地,之前拆分的 Studio Core/Runtime(#310、#312、#313)也已合并。目前生产 FastAPI 仍使用 f1.JobsManager,新版 studio.JobsManager 则作为独立 Runtime 存在,两套实现尚未完成接入统一。

我此前已经完成了新版 FastAPI Service(原计划 PR4)的独立实现和验证。
考虑到 #299 已经集成,我准备调整 PR4 的范围:复用现有 FastAPI 和客户端接口,将底层任务执行逐步迁移至 Studio Runtime,并保留必要的兼容性,避免重复引入一套 Service。

现在想明确一下后续架构方向:是否打算以 Studio Runtime 作为最终统一的执行内核,旧 F1 实现暂时保留兼容,待验证后逐步清理?

如果已有其他集成安排,我也会相应调整后续 PR 的范围。

@isLinXu

isLinXu commented Oct 14, 2026

Copy link
Copy Markdown
Collaborator

感谢合并 #299!也注意到您通过 #314 对原 F1 平台进行了主线集成和冲突处理。

我重新检查了当前主线:#299 的 FastAPI、前端及 F1 Runtime 已经落地,之前拆分的 Studio Core/Runtime(#310、#312、#313)也已合并。目前生产 FastAPI 仍使用 f1.JobsManager,新版 studio.JobsManager 则作为独立 Runtime 存在,两套实现尚未完成接入统一。

我此前已经完成了新版 FastAPI Service(原计划 PR4)的独立实现和验证。 考虑到 #299 已经集成,我准备调整 PR4 的范围:复用现有 FastAPI 和客户端接口,将底层任务执行逐步迁移至 Studio Runtime,并保留必要的兼容性,避免重复引入一套 Service。

现在想明确一下后续架构方向:是否打算以 Studio Runtime 作为最终统一的执行内核,旧 F1 实现暂时保留兼容,待验证后逐步清理?

如果已有其他集成安排,我也会相应调整后续 PR 的范围。

是的,目前打算以 Studio Runtime 作为最终统一的执行内核,后续逐步更新

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants