- Python 87.8%
- Shell 9.6%
- Dockerfile 2.6%
| argo | ||
| backend | ||
| docker | ||
| docs | ||
| scripts | ||
| .gitignore | ||
| .python-version | ||
| build.sh | ||
| install.sh | ||
| main.py | ||
| pyproject.toml | ||
| README.md | ||
| uv.lock | ||
ModelForge 模型锻造平台技术架构设计文档
1. 项目定位
ModelForge 是一个面向模型转换、优化、验证与可复现执行的轻量级平台。
平台第一阶段聚焦 QNN 模型转换与优化,后续可扩展支持更多模型后端,例如 TensorRT、OpenVINO、ONNX Runtime、TFLite、NCNN 等。
系统底层是一个容器化任务执行平台,上层是面向非专业用户的一键式模型转换与优化产品。
整体定位:
ModelForge = 模型转换优化产品 + 可复现容器任务平台
对普通用户:
上传模型 -> 选择目标平台 -> 选择优化策略 -> 一键转换 -> 下载结果
对算法工程师和平台工程师:
任务模板 -> 容器执行 -> 日志追踪 -> 产物留痕 -> 调试复现
2. 设计目标
2.1 产品目标
平台需要让非专业用户通过简单网页操作完成模型转换和优化。
用户不需要理解:
Kubernetes
Docker
Pod
Job
MinIO
Manifest
命令行参数
容器镜像
用户只需要理解:
模型文件
目标平台
优化等级
转换结果
报告下载
2.2 技术目标
平台底层需要支持:
- 容器化任务执行。
- 单机 K3s 部署。
- 每个任务独立运行。
- 输入、输出、日志、配置完整留痕。
- 任务可复现。
- 任务可克隆。
- 任务可调试。
- 支持进入运行中容器排查问题。
- 后续可扩展到多机 Kubernetes。
- 后续可扩展到更多模型转换后端。
- 后续可扩展为低代码模型转换产品。
3. 项目命名
推荐项目名:
ModelForge
中文名:
模型锻造平台
项目含义:
Model = 模型
Forge = 锻造、转换、优化、生成产物
推荐模块命名:
modelforge-api 后端 API 服务
modelforge-web 前端 Web 控制台
modelforge-core 任务和模板核心模块
modelforge-runner 通用任务运行器
modelforge-qnn QNN 转换插件 / QNN Runner
modelforge-deploy 部署配置
modelforge-sdk 可选 Python SDK
推荐产品 Slogan:
Upload. Convert. Optimize. Reproduce.
中文:
上传模型,一键转换,自动优化,全程可复现。
4. 总体架构
4.1 总体架构图
flowchart TD
USER[普通用户 / 算法工程师] --> WEB[ModelForge Web]
WEB --> API[ModelForge API]
API --> PG[(PostgreSQL)]
API --> MINIO[(MinIO)]
API --> K3S[K3s API Server]
API --> TEMPLATE[Template Engine]
TEMPLATE --> MANIFEST[Task Manifest]
TEMPLATE --> JOBYAML[Kubernetes Job YAML]
API --> K3S
K3S --> JOB[Kubernetes Job]
JOB --> POD[Task Pod]
POD --> RUNNER[ModelForge Runner Container]
RUNNER --> MINIO
API --> LOGWATCHER[Log / Pod Watcher]
LOGWATCHER --> PG
LOGWATCHER --> MINIO
WEB --> TERMINAL[Web Terminal]
TERMINAL --> API
API --> EXEC[K8s Exec API]
EXEC --> POD
5. 产品分层设计
ModelForge 采用五层产品架构。
┌────────────────────────────────────────────┐
│ Product Layer │
│ 面向非专业用户的一键模型转换与优化页面 │
└────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────┐
│ Template Layer │
│ 模型转换模板、优化模板、参数表单、任务预设 │
└────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────┐
│ Task Layer │
│ 任务创建、状态管理、事件流、日志、产物、复现 │
└────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────┐
│ Execution Layer │
│ K3s、Kubernetes Job、Pod、Container、Exec │
└────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────┐
│ Artifact Layer │
│ MinIO:输入、输出、日志、Manifest、报告 │
└────────────────────────────────────────────┘
6. 用户视角分层
6.1 普通模式
普通模式面向非专业用户。
用户页面只暴露必要参数:
上传模型
选择模型来源格式
选择目标平台
选择目标芯片
选择精度模式
选择优化等级
开始转换
查看进度
下载结果
查看报告
普通用户不需要看到:
镜像
命令
参数
环境变量
K8s Job
Pod
Manifest
MinIO 路径
6.2 高级模式
高级模式面向算法工程师、平台工程师。
高级模式可以查看和配置:
容器镜像
镜像 digest
执行命令
执行参数
环境变量
资源限制
任务 Manifest
Kubernetes Job YAML
Pod YAML
实时日志
输入输出文件
调试终端
任务事件流
7. 核心领域模型
平台不要只围绕 Task 设计,而应该围绕以下核心对象设计:
Project
Model
Template
Task
Artifact
Report
DebugSession
7.1 Project
Project 表示一个用户项目。
例如:
手机端目标检测模型优化
车载感知模型 QNN 转换
边缘设备模型加速项目
一个 Project 下可以有多个 Model。
7.2 Model
Model 表示用户上传的模型资产。
核心字段:
model_id
project_id
model_name
source_format
framework
input_shape
opset_version
file_uri
checksum
created_at
Model 是后续转换、优化、验证任务的基础输入。
7.3 Template
Template 表示一种任务模板。
例如:
QNN 标准转换模板
QNN INT8 量化模板
TensorRT FP16 优化模板
ONNX Simplify 模板
Benchmark 模板
Accuracy Check 模板
Template 是平台最重要的扩展点。
新增一种模型转换能力时,优先通过新增 Template 实现,而不是修改核心任务系统。
7.4 Task
Task 表示一次具体执行记录。
一个 Task 可以来自某个 Template,也可以来自高级模式下的自定义任务。
核心字段:
task_id
project_id
model_id
template_id
task_type
status
manifest_uri
input_prefix
output_prefix
log_prefix
created_at
started_at
finished_at
7.5 Artifact
Artifact 表示任务输入、输出、日志、报告等文件。
Artifact 类型包括:
input_model
input_config
output_model
output_package
stdout_log
stderr_log
manifest
job_yaml
pod_yaml
report
debug_record
7.6 Report
Report 表示任务生成的结构化报告。
例如:
转换结果
模型输入输出信息
算子支持情况
优化策略
性能结果
转换日志摘要
错误原因
推荐修复方式
7.7 DebugSession
DebugSession 表示一次调试会话。
用于记录:
调试用户
调试开始时间
调试结束时间
目标 Pod
目标容器
调试命令记录
调试会话日志
8. 推荐技术选型
8.1 总体技术栈
| 模块 | 技术选型 | 说明 |
|---|---|---|
| 前端 | React + Ant Design / Vue3 + Naive UI | 管理后台和产品页面均适合 |
| 后端 | FastAPI | Python 生态友好,适合模型平台 |
| 数据库 | PostgreSQL | 保存任务状态、事件、索引、配置 |
| 对象存储 | MinIO | 保存输入、输出、日志、Manifest、报告 |
| 容器编排 | K3s | 单机轻量 Kubernetes |
| 任务执行 | Kubernetes Job | 每个任务对应一个 Job |
| 调试能力 | K8s exec + WebSocket Terminal | 支持进入运行中容器 |
| 临时调试容器 | Ephemeral Container,可选 | 镜像缺调试工具时使用 |
| 镜像仓库 | Harbor / Docker Registry | 保存 Runner 镜像 |
| API 文档 | OpenAPI / Swagger | 前后端对接 |
| 鉴权 | JWT | 简单实用 |
| 部署 | Helm / Kustomize | 便于后续维护 |
| 模板渲染 | Jinja2 / Jsonnet | 渲染 Job YAML 和命令参数 |
| 日志存储 | MinIO + PgSQL 索引 | 大日志不进数据库 |
9. 为什么选择 K3s
当前平台是单机平台,但任务形态已经接近批处理容器平台。
如果直接使用 Docker Engine,需要自行实现:
任务生命周期管理
容器状态追踪
资源限制
任务取消
任务超时
日志采集
容器重试
任务隔离
后续多机迁移
GPU 调度
使用 K3s 后,上述能力大部分由 Kubernetes 提供。
K3s 适合当前场景的原因:
轻量
单机可部署
兼容 Kubernetes API
支持 Job
支持资源限制
支持 namespace
支持 Secret
支持 ConfigMap
支持 ServiceAccount
支持后续平滑迁移到标准 Kubernetes
因此,第一版执行层建议使用:
K3s + Kubernetes Job
而不是:
Docker Engine + 自研调度器
10. 任务执行架构
10.1 执行模型
每个模型转换任务对应一个 Kubernetes Job。
Task
-> Task Manifest
-> Job YAML
-> Kubernetes Job
-> Pod
-> Runner Container
10.2 任务执行流程
sequenceDiagram
participant User as 用户
participant Web as Web 页面
participant API as ModelForge API
participant PG as PostgreSQL
participant S3 as MinIO
participant K3s as K3s
participant Pod as Runner Pod
User->>Web: 创建转换任务
Web->>API: 提交模型和转换参数
API->>PG: 创建 Task
API->>S3: 保存输入文件
API->>S3: 保存 Task Manifest
API->>S3: 保存 Job YAML
API->>K3s: 创建 Kubernetes Job
K3s->>Pod: 启动 Runner 容器
Pod->>S3: 下载输入文件
Pod->>Pod: 执行模型转换 / 优化
Pod->>S3: 上传输出文件和报告
API->>K3s: 监听 Pod / Job 状态
API->>S3: 保存 stdout / stderr
API->>PG: 更新 Task 状态
Web->>API: 查询结果
API->>Web: 返回产物和报告
11. Task Manifest 设计
Task Manifest 是任务可复现的核心。
每个任务创建后生成一份不可变 Manifest。
Manifest 保存:
任务 ID
任务类型
模型信息
输入文件 URI
输入文件 checksum
执行镜像
镜像 digest
执行命令
执行参数
环境变量
资源配置
模板版本
Runner 版本
输出路径
调试配置
创建时间
创建用户
示例:
apiVersion: modelforge/v1
kind: ModelTask
metadata:
task_id: "task-20260605-000001"
project_id: "project-001"
model_id: "model-001"
created_by: "user-a"
created_at: "2026-06-05T10:00:00+09:00"
spec:
task_type: "qnn_convert"
template_id: "qnn_convert_default"
template_version: "1.0.0"
model:
name: "resnet50.onnx"
source_format: "onnx"
uri: "s3://modelforge/tasks/task-20260605-000001/input/resnet50.onnx"
checksum: "sha256:xxxx"
runner:
image: "registry.local/modelforge-qnn:1.0.0"
image_digest: "sha256:xxxx"
command:
- "python"
- "/app/run.py"
args:
- "--input=/workspace/input/resnet50.onnx"
- "--output=/workspace/output"
- "--target=qnn"
- "--precision=fp16"
resources:
cpu: "8"
memory: "32Gi"
gpu: 0
artifact:
bucket: "modelforge"
task_prefix: "tasks/task-20260605-000001"
input_prefix: "tasks/task-20260605-000001/input"
output_prefix: "tasks/task-20260605-000001/output"
log_prefix: "tasks/task-20260605-000001/logs"
debug:
enabled: false
keep_alive_on_failure: true
shell: "/bin/bash"
12. Template 设计
Template 是平台扩展的核心。
新增一种能力时,优先新增 Template,而不是改核心代码。
12.1 Template 组成
一个 Template 包含:
基础信息
用户表单 Schema
参数校验规则
Runner 镜像
命令模板
参数模板
资源默认值
输出产物规则
报告解析规则
12.2 Template 示例
template_id: qnn_convert_default
name: QNN 标准转换
category: qnn
version: 1.0.0
ui_schema:
fields:
- name: target_chip
label: 目标芯片
type: select
required: true
options:
- SA8295
- SA8650
- SM8650
- name: precision
label: 精度模式
type: select
required: true
options:
- FP16
- INT8
- name: optimization_level
label: 优化等级
type: select
required: true
options:
- fast
- balanced
- max
runner:
image: registry.local/modelforge-qnn:1.0.0
command:
- python
- /app/run.py
args_template:
- "--target-chip={{ target_chip }}"
- "--precision={{ precision }}"
- "--optimization-level={{ optimization_level }}"
resources:
default:
cpu: "4"
memory: "16Gi"
gpu: 0
max:
cpu: "16"
memory: "64Gi"
gpu: 1
outputs:
- name: qnn_package
path: /workspace/output
type: directory
- name: report
path: /workspace/output/report.json
type: file
13. Runner 设计
Runner 是实际运行在容器中的执行程序。
Runner 负责:
读取 Task Manifest
从 MinIO 下载输入
准备 workspace
执行转换命令
捕获 stdout/stderr
保存输出文件
生成 report.json
上传输出到 MinIO
返回标准 exit code
支持 debug keep-alive
13.1 Runner 执行流程
启动容器
-> 读取 manifest
-> 下载 input
-> 创建 workspace
-> 执行转换
-> 收集 output
-> 生成 report
-> 上传 output/report/logs
-> 退出
13.2 Runner 目录约定
/workspace/
input/
model.onnx
config.yaml
output/
model.so
context.bin
report.json
logs/
stdout.log
stderr.log
tmp/
13.3 Runner 返回码约定
0 成功
10 输入文件错误
11 参数错误
20 模型格式不支持
21 算子不支持
30 QNN 转换失败
31 量化失败
40 输出上传失败
50 系统异常
14. 调试模式设计
14.1 调试能力分层
调试能力分为三层:
K8s exec
Ephemeral Container
Debug Sidecar
14.2 K8s exec
第一阶段优先实现 K8s exec。
用于进入正在运行的主容器:
Web Terminal
-> ModelForge API
-> K8s exec websocket
-> Runner Container
适合:
查看文件
执行 shell
查看中间产物
手动运行命令
排查转换失败原因
14.3 失败后保活
第一阶段推荐使用失败后保活策略。
当任务失败且开启 debug 模式时,Runner 不立即退出,而是保持容器运行。
python /app/run.py
EXIT_CODE=$?
if [ "$DEBUG_KEEP_ALIVE" = "true" ] && [ "$EXIT_CODE" != "0" ]; then
echo "Task failed, keep container alive for debugging"
sleep infinity
fi
exit $EXIT_CODE
这样平台可以通过 Web Terminal 进入容器调试。
14.4 Ephemeral Container
第二阶段可支持 Ephemeral Container。
适合主镜像过于精简,没有 bash、curl、strace 等工具时使用。
Pod
- runner container
- ephemeral debug container
14.5 Debug Sidecar
Sidecar 不作为默认调试方案,只在需要常驻调试代理时使用。
适合:
文件浏览 agent
Web shell agent
metrics exporter
artifact syncer
debug proxy
不建议所有任务默认注入 sidecar,避免增加资源开销和安全风险。
15. MinIO 存储设计
15.1 Bucket 设计
建议使用一个主 bucket:
modelforge
目录结构:
modelforge/
projects/
{project_id}/
models/
{model_id}/
original/
metadata.json
tasks/
{task_id}/
manifest/
task_manifest.yaml
job.yaml
pod.yaml
image_info.json
input/
model.onnx
config.yaml
calibration_data/
output/
converted_model/
package.zip
report.json
logs/
stdout.log
stderr.log
events.jsonl
debug/
sessions/
session_001.json
metadata/
env.json
command.json
resources.json
15.2 存储原则
输入文件不可变
Manifest 不可变
Job YAML 必须保存
Pod YAML 必须保存
stdout/stderr 存 MinIO
PgSQL 只保存日志 URI
产物按 task_id 隔离
报告结构化保存
大文件不进数据库
16. PostgreSQL 数据模型
16.1 projects
CREATE TABLE projects (
id UUID PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
created_by VARCHAR(128),
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);
16.2 models
CREATE TABLE models (
id UUID PRIMARY KEY,
project_id UUID REFERENCES projects(id),
name VARCHAR(255) NOT NULL,
source_format VARCHAR(64),
framework VARCHAR(64),
input_shape JSONB,
metadata JSONB,
file_uri TEXT NOT NULL,
checksum VARCHAR(128),
created_by VARCHAR(128),
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
16.3 task_templates
CREATE TABLE task_templates (
id UUID PRIMARY KEY,
name VARCHAR(255) NOT NULL,
category VARCHAR(64),
version VARCHAR(64),
description TEXT,
ui_schema JSONB,
runner_spec JSONB,
resource_spec JSONB,
output_spec JSONB,
enabled BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);
16.4 tasks
CREATE TABLE tasks (
id UUID PRIMARY KEY,
project_id UUID REFERENCES projects(id),
model_id UUID REFERENCES models(id),
template_id UUID REFERENCES task_templates(id),
name VARCHAR(255) NOT NULL,
task_type VARCHAR(64) NOT NULL,
status VARCHAR(32) NOT NULL,
image VARCHAR(512),
image_digest VARCHAR(256),
command JSONB,
args JSONB,
env JSONB,
resources JSONB,
manifest_uri TEXT,
job_yaml_uri TEXT,
pod_yaml_uri TEXT,
input_prefix TEXT,
output_prefix TEXT,
log_prefix TEXT,
k8s_namespace VARCHAR(128),
k8s_job_name VARCHAR(255),
k8s_pod_name VARCHAR(255),
exit_code INTEGER,
error_message TEXT,
debug_enabled BOOLEAN DEFAULT FALSE,
keep_alive_on_failure BOOLEAN DEFAULT FALSE,
created_by VARCHAR(128),
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
submitted_at TIMESTAMP,
started_at TIMESTAMP,
finished_at TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);
16.5 task_events
CREATE TABLE task_events (
id BIGSERIAL PRIMARY KEY,
task_id UUID REFERENCES tasks(id),
event_type VARCHAR(64) NOT NULL,
level VARCHAR(16) DEFAULT 'INFO',
message TEXT,
payload JSONB,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
16.6 artifacts
CREATE TABLE artifacts (
id BIGSERIAL PRIMARY KEY,
task_id UUID REFERENCES tasks(id),
model_id UUID REFERENCES models(id),
artifact_type VARCHAR(64) NOT NULL,
name VARCHAR(255),
uri TEXT NOT NULL,
size_bytes BIGINT,
checksum VARCHAR(128),
metadata JSONB,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
16.7 reports
CREATE TABLE reports (
id UUID PRIMARY KEY,
task_id UUID REFERENCES tasks(id),
report_type VARCHAR(64),
report_uri TEXT,
summary JSONB,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
16.8 debug_sessions
CREATE TABLE debug_sessions (
id UUID PRIMARY KEY,
task_id UUID REFERENCES tasks(id),
user_id VARCHAR(128),
pod_name VARCHAR(255),
container_name VARCHAR(255),
status VARCHAR(32),
started_at TIMESTAMP NOT NULL DEFAULT NOW(),
ended_at TIMESTAMP,
transcript_uri TEXT
);
17. 任务状态机
stateDiagram-v2
[*] --> CREATED
CREATED --> UPLOADING
UPLOADING --> READY
READY --> SUBMITTED
SUBMITTED --> SCHEDULING
SCHEDULING --> RUNNING
RUNNING --> SUCCEEDED
RUNNING --> FAILED
RUNNING --> CANCELLING
CANCELLING --> CANCELLED
FAILED --> DEBUGGING
DEBUGGING --> FAILED
FAILED --> RETRYING
RETRYING --> SUBMITTED
SUCCEEDED --> [*]
CANCELLED --> [*]
状态说明:
| 状态 | 含义 |
|---|---|
| CREATED | 任务已创建 |
| UPLOADING | 输入文件上传中 |
| READY | 输入和配置已准备好 |
| SUBMITTED | 已提交到 K3s |
| SCHEDULING | Pod 调度中 |
| RUNNING | 容器运行中 |
| SUCCEEDED | 成功 |
| FAILED | 失败 |
| DEBUGGING | 调试中 |
| RETRYING | 重试中 |
| CANCELLING | 取消中 |
| CANCELLED | 已取消 |
18. 后端架构设计
18.1 后端目录结构
backend/
app/
api/
routes_projects.py
routes_models.py
routes_tasks.py
routes_templates.py
routes_artifacts.py
routes_reports.py
routes_logs.py
routes_debug.py
core/
config.py
security.py
errors.py
db/
session.py
models.py
repositories.py
services/
project_service.py
model_service.py
task_service.py
template_service.py
manifest_service.py
minio_service.py
k8s_service.py
log_service.py
artifact_service.py
report_service.py
debug_service.py
workers/
k8s_watcher.py
log_collector.py
artifact_scanner.py
schemas/
project.py
model.py
task.py
template.py
artifact.py
report.py
debug.py
main.py
18.2 后端核心服务
ProjectService
管理项目
ModelService
管理模型资产
TemplateService
管理任务模板和 UI schema
TaskService
管理任务生命周期
ManifestService
生成和保存 Task Manifest
K8sService
渲染 Job YAML、提交 Job、取消 Job、查询 Pod
MinioService
上传、下载、生成预签名 URL
LogService
采集和查询日志
ArtifactService
扫描和登记产物
ReportService
解析和展示报告
DebugService
管理 exec、terminal、debug session
19. 前端架构设计
19.1 前端页面
普通用户页面:
- 项目列表
- 项目详情
- 模型上传
- 一键转换
- 转换进度
- 结果下载
- 报告查看
高级用户页面:
- 任务列表
- 任务详情
- 模板管理
- Manifest 查看
- Job YAML 查看
- Pod YAML 查看
- 实时日志
- Web Terminal
- Artifact Browser
19.2 前端目录结构
frontend/
src/
pages/
Projects/
Models/
ConvertWizard/
TaskList/
TaskDetail/
TemplateManager/
ArtifactBrowser/
Reports/
DebugTerminal/
components/
ModelUploader/
TemplateForm/
TaskStatusTag/
TaskTimeline/
LogViewer/
WebTerminal/
ArtifactTable/
ReportViewer/
ManifestViewer/
YamlViewer/
api/
projectApi.ts
modelApi.ts
taskApi.ts
templateApi.ts
artifactApi.ts
reportApi.ts
debugApi.ts
stores/
projectStore.ts
modelStore.ts
taskStore.ts
userStore.ts
20. 前后端接口设计
20.1 接口风格
采用:
REST API + WebSocket
REST API 用于:
项目管理
模型管理
模板管理
任务创建
任务查询
产物查询
报告查询
任务取消
任务重试
任务克隆
WebSocket 用于:
实时日志
Web Terminal
任务状态推送
统一 API 前缀:
/api/v1
20.2 Project API
GET /api/v1/projects
POST /api/v1/projects
GET /api/v1/projects/{project_id}
PUT /api/v1/projects/{project_id}
DELETE /api/v1/projects/{project_id}
20.3 Model API
GET /api/v1/projects/{project_id}/models
POST /api/v1/projects/{project_id}/models
GET /api/v1/models/{model_id}
DELETE /api/v1/models/{model_id}
上传模型:
POST /api/v1/projects/{project_id}/models/upload
Content-Type: multipart/form-data
20.4 Template API
GET /api/v1/templates
POST /api/v1/templates
GET /api/v1/templates/{template_id}
PUT /api/v1/templates/{template_id}
DELETE /api/v1/templates/{template_id}
获取模板表单 schema:
GET /api/v1/templates/{template_id}/ui-schema
20.5 Task API
创建任务:
POST /api/v1/tasks
Request:
{
"project_id": "project-001",
"model_id": "model-001",
"template_id": "qnn_convert_default",
"name": "resnet50-qnn-fp16",
"params": {
"target_chip": "SA8650",
"precision": "FP16",
"optimization_level": "balanced"
},
"debug": {
"enabled": true,
"keep_alive_on_failure": true
}
}
Response:
{
"task_id": "task-20260605-000001",
"status": "CREATED"
}
提交任务:
POST /api/v1/tasks/{task_id}/submit
查询任务:
GET /api/v1/tasks/{task_id}
查询任务事件:
GET /api/v1/tasks/{task_id}/events
取消任务:
POST /api/v1/tasks/{task_id}/cancel
重试任务:
POST /api/v1/tasks/{task_id}/retry
克隆任务:
POST /api/v1/tasks/{task_id}/clone
20.6 Artifact API
GET /api/v1/tasks/{task_id}/artifacts
GET /api/v1/artifacts/{artifact_id}/download
返回示例:
{
"artifacts": [
{
"id": 1,
"name": "package.zip",
"artifact_type": "output_package",
"size_bytes": 1024000,
"download_url": "https://..."
}
]
}
20.7 Report API
GET /api/v1/tasks/{task_id}/report
返回示例:
{
"task_id": "task-001",
"status": "SUCCEEDED",
"summary": {
"source_format": "onnx",
"target_format": "qnn",
"precision": "FP16",
"output_files": 3,
"warnings": 1
}
}
20.8 Log API
获取完整日志:
GET /api/v1/tasks/{task_id}/logs?stream=stdout
实时日志:
WS /api/v1/tasks/{task_id}/logs/ws
WebSocket 消息:
{
"timestamp": "2026-06-05T10:00:00+09:00",
"stream": "stdout",
"line": "Start model conversion..."
}
20.9 Debug API
开启调试:
POST /api/v1/tasks/{task_id}/debug/enable
关闭调试:
POST /api/v1/tasks/{task_id}/debug/disable
Web Terminal:
WS /api/v1/tasks/{task_id}/terminal
前端发送:
{
"type": "stdin",
"data": "ls -lah\n"
}
后端返回:
{
"type": "stdout",
"data": "total 12K\n"
}
21. Kubernetes Job 模板
apiVersion: batch/v1
kind: Job
metadata:
name: modelforge-task-${TASK_ID}
namespace: modelforge
labels:
app: modelforge
task_id: "${TASK_ID}"
task_type: "${TASK_TYPE}"
spec:
backoffLimit: 0
activeDeadlineSeconds: 7200
ttlSecondsAfterFinished: 86400
template:
metadata:
labels:
app: modelforge
task_id: "${TASK_ID}"
spec:
restartPolicy: Never
serviceAccountName: modelforge-runner
containers:
- name: runner
image: "${IMAGE}"
imagePullPolicy: IfNotPresent
command:
- "python"
- "/app/runner.py"
args:
- "--manifest"
- "s3://modelforge/tasks/${TASK_ID}/manifest/task_manifest.yaml"
env:
- name: TASK_ID
value: "${TASK_ID}"
- name: DEBUG_KEEP_ALIVE
value: "${DEBUG_KEEP_ALIVE}"
- name: S3_ENDPOINT
valueFrom:
secretKeyRef:
name: minio-secret
key: endpoint
- name: S3_ACCESS_KEY
valueFrom:
secretKeyRef:
name: minio-secret
key: access_key
- name: S3_SECRET_KEY
valueFrom:
secretKeyRef:
name: minio-secret
key: secret_key
resources:
requests:
cpu: "${CPU_REQUEST}"
memory: "${MEMORY_REQUEST}"
limits:
cpu: "${CPU_LIMIT}"
memory: "${MEMORY_LIMIT}"
volumeMounts:
- name: workspace
mountPath: /workspace
volumes:
- name: workspace
emptyDir: {}
22. 网络架构
flowchart LR
USER[用户浏览器] -->|HTTPS 443| INGRESS[Ingress / Nginx]
INGRESS -->|HTTP 3000| WEB[ModelForge Web]
INGRESS -->|HTTP 8000| API[ModelForge API]
API -->|5432| PG[(PostgreSQL)]
API -->|9000| MINIO[(MinIO)]
API -->|6443| K3S[K3s API Server]
K3S --> POD[Task Pod]
POD -->|9000| MINIO
POD -->|443/5000| REGISTRY[Image Registry]
USER -->|WebSocket 443| INGRESS
INGRESS --> API
API -->|K8s exec websocket| K3S
K3S --> POD
端口规划:
| 服务 | 端口 | 暴露范围 |
|---|---|---|
| Web | 80 / 443 | 用户 |
| API | 8000 | Ingress 内部 |
| PostgreSQL | 5432 | 集群内部 |
| MinIO API | 9000 | 集群内部,可选外部 |
| MinIO Console | 9001 | 管理员 |
| K3s API | 6443 | 后端访问 |
| Registry | 5000 / 443 | 集群内部 |
| WebSocket Terminal | 443 | 用户通过 Ingress 访问 |
23. 部署架构
单机部署建议:
一台服务器
- K3s
- ModelForge API
- ModelForge Web
- PostgreSQL
- MinIO
- Image Registry
- QNN Runner Job
部署方式:
K3s 安装脚本
Helm / Kustomize 部署平台组件
Namespace 隔离
Secret 管理 MinIO 凭证
ServiceAccount 控制 Runner 权限
Ingress 暴露 Web 和 API
Namespace 建议:
modelforge-system 平台服务
modelforge-tasks 任务 Job
modelforge-storage MinIO / PostgreSQL,可选
24. 可扩展设计
24.1 模型后端扩展
后续可以通过新增 Template 和 Runner 镜像扩展:
QNN
TensorRT
OpenVINO
TFLite
NCNN
ONNX Runtime
TVM
核心平台不需要感知具体转换逻辑。
24.2 Pipeline 扩展
第一阶段 Task 可以是单步骤任务。
后续可扩展为线性 Pipeline:
模型检查
-> 模型转换
-> 模型优化
-> Benchmark
-> 报告生成
再后续可接入 Argo Workflows,实现复杂 DAG。
但第一版不建议直接上 Argo,避免复杂度过高。
24.3 UI 扩展
通过 Template 的 ui_schema 自动生成表单。
新增模板时,前端不需要硬编码页面。
普通用户看到的是模板表单:
目标芯片
精度模式
优化等级
输入 shape
是否量化
后端根据模板生成:
Task Manifest
Job YAML
Runner 参数
输出规则
报告解析规则
24.4 执行层扩展
第一阶段:
K3s Job Executor
后续可以扩展:
Kubernetes Job Executor
Argo Workflow Executor
Docker Executor
Remote Cluster Executor
建议定义统一执行接口:
class Executor:
def submit(task_manifest): ...
def cancel(task_id): ...
def get_status(task_id): ...
def get_logs(task_id): ...
def exec(task_id, command): ...
25. 系统复杂度控制原则
第一版只保留必要核心能力:
Project
Model
Template
Task
Artifact
Report
Debug
不要一开始引入:
复杂 DAG
多租户资源配额
完整 MLOps 模型注册中心
在线推理服务
多集群调度
复杂审批流
复杂 RBAC
Argo Workflows
Prometheus 全量监控体系
第一版核心闭环:
上传模型
-> 选择模板
-> 生成任务
-> K3s Job 执行
-> 保存日志
-> 保存产物
-> 生成报告
-> 支持调试
-> 支持复现
26. 最终推荐架构
最终推荐第一版架构:
ModelForge Web
ModelForge API
PostgreSQL
MinIO
K3s
Kubernetes Job
ModelForge Runner
产品抽象:
Project
Model
Template
Task
Artifact
Report
技术抽象:
Task Manifest
Job Renderer
Runner
Executor
Artifact Store
Debug Session
核心原则:
用户使用产品能力;
平台维护任务模板;
K3s 负责容器生命周期;
MinIO 负责文件留痕;
PostgreSQL 负责状态和索引;
Task Manifest 负责可复现;
Runner 负责具体模型转换;
Template 负责后续扩展。
该架构既能满足当前单机 QNN 转换平台需求,也能为后续非专业用户的一键模型转换与优化系统留下足够扩展空间。
15. Argo Workflows 集成(扩展架构)
15.1 概述
为了提升流水线的可扩展性、可观测性和并行能力,ModelForge 新增 Argo Workflows 作为 第二执行引擎。与原有的单 Pod 多 InitContainer 方案不同,Argo 模式下流水线的每个步骤 都运行在独立的 Pod 中,形成 DAG(有向无环图)工作流。
15.2 架构对比
| 维度 | 原有 K8s Job 模式 | Argo Workflows 模式 |
|---|---|---|
| 执行单元 | 单 Pod + InitContainer + Sidecar | 多 Pod DAG |
| 并行度 | 串行 | 并行 + 串行混合 |
| 重试策略 | 整个 Job 重试 | 按步骤独立重试 |
| 资源分配 | Pod 级别统一 | 按步骤独立 CPU/内存 |
| 可观测性 | kubectl logs | Argo UI + CLI + Grafana |
| 产物传递 | EmptyDir 共享卷 | 卷 + S3 混合 |
| 扩展新步骤 | 修改模板 YAML + 镜像 | 新增 DAG 节点 + 镜像 |
15.3 流水线步骤
sync-input (MinIO 下载)
├── quant-prep (量化数据预处理)
└── onnx-optimize (ONNX 优化简化)
└── qnn-convert (QNN 转换 → lib.so)
├── generate-ctx (生成 HTP ctx.bin)
├── upload-outputs (产物上传 MinIO)
└── precision-analysis (精度分析)
15.4 快速试用
# 1. 切换到 Argo 分支
git checkout feature/argo-workflow
# 2. 安装 Argo Workflows
bash argo/install.sh
# 3. 构建新镜像
bash docker/build-argo-images.sh
# 4. 通过 CLI 提交流水线
bash argo/submit-workflow.sh \
--model "projects/<pid>/models/<mid>/original/model.onnx" \
--precision INT8 \
--chip QCS8550
15.5 通过 API 使用
创建 Task 时指定 template_id: argo_qnn_pipeline,后端自动识别
template_mode: argo 并使用 ArgoExecutor 提交工作流。
详细文档见 argo/README.md。