264 lines
20 KiB
Markdown
264 lines
20 KiB
Markdown
# 微调平台架构与现状说明
|
||
|
||
> 目的:梳理「前端 / 应用后端 / 算力平台」三层当前已实现的功能、哪些是真实可用、哪些是模拟/空壳,
|
||
> 并指出与「后端仅做数据/任务调度,GPU 计算全部下沉到算力服务」这一架构原则之间的缺口。
|
||
>
|
||
> 初始生成日期:2026-07-30。最近更新:2026-07-31。路由前缀统一为 `/modelTF`(前后端、算力 API 共用)。
|
||
|
||
---
|
||
|
||
## 0. 更新日志
|
||
|
||
| 日期 | 变更 |
|
||
|---|---|
|
||
| 2026-07-30 | 初始版本,梳理三层现状与缺口 |
|
||
| 2026-07-31 | 评测/推理后端端点从 `yg_ft1` 移植完成(G5 部分解决);更新缺口状态表与路线图 |
|
||
| 2026-07-31 | 训练派发改造完成:移植 `process_manager.py`/`adapter.py`/`sync.py`,算力 real 执行器就绪,后端轮询线程启动(G1/G2/G4 部分解决) |
|
||
|
||
---
|
||
|
||
## 1. 三层架构总览
|
||
|
||
```
|
||
┌──────────────┐ HTTP /modelTF ┌──────────────────────┐
|
||
│ 前端 │ ───────────────────────▶ │ 应用后端 (backend) │
|
||
│ (Vue3+Vite) │ ◀─────────────────────── │ FastAPI + SQLite/PG │
|
||
└──────────────┘ └──────────┬───────────┘
|
||
│ ✅ 训练派发已打通
|
||
│ ✅ 推理代理已打通
|
||
│ (需算力 venv 装 llamafactory)
|
||
▼
|
||
┌──────────────────────┐
|
||
│ 算力平台 (compute) │
|
||
│ FastAPI + LLaMA-Factory│
|
||
└──────────────────────┘
|
||
```
|
||
|
||
**关键事实**:应用后端与算力平台是**两个独立部署的服务**。
|
||
- 推理路径已打通:后端 `platform.py` 经 `ComputeNodeClient._request()` 代理到算力 `/modelTF/inference/*`。
|
||
- 训练路径已打通:后端 `platform_store.start_task` → `_dispatch_to_compute` → `ComputeNodeClient.create_job` 派发到算力;后台轮询线程(`service.start_compute_sync_worker`)经 `sync.poll_compute_jobs_once` 周期回传状态/日志/指标。
|
||
- 算力 real 执行器已就绪:`compute/agent/process_manager.py` 真正 `subprocess` 拉起 `llamafactory-cli train`。
|
||
- **剩余前置**:算力 venv 需安装 `llamafactory`(G3);基座模型/数据集文件需到达算力节点(阶段 4)。
|
||
|
||
### 1.1 职责边界(架构原则)
|
||
|
||
| 角色 | 职责 | 不得做什么 |
|
||
|---|---|---|
|
||
| **应用后端** | 数据/任务调度与编排:数据集管理、模型元数据、任务生命周期(创建/状态/日志路由)、审批/审计/租户、对外 REST API | **不得**由自身进程执行任何 GPU 计算;**不得**安装 `llamafactory`/`torch` 等训练运行时。GPU 计算须派发给算力服务进程执行(算力服务可与后端同机部署,也可在独立算力节点,取决于部署形态) |
|
||
| **算力服务** | 承载所有 GPU 计算:模型训练(微调)、模型推理、模型评测、数据类型转换等;运行 `llamafactory-cli` 等框架 | 不持有业务元数据;只接收后端派发的作业并回报进度/产物 |
|
||
| **前端** | 交互与可视化,纯调用后端 API | 不直连算力(统一经后端中转) |
|
||
|
||
> **原则**:凡涉及 GPU 的工作负载(训练/推理/评测)一律由后端**派发**给算力服务执行,
|
||
> 后端自身只做调度编排与数据流转——即 GPU 计算必须发生在**算力服务进程内**,而非后端进程内。
|
||
> 算力服务部署在何处(本机或独立节点)不影响该原则。当前 `fine_tune/runner.py` 由后端进程
|
||
> 直接 `subprocess` 跑 `train.py` 属于**违反该原则的临时实现**(见 G1)。
|
||
|
||
---
|
||
|
||
## 2. 前端(frontend/src)功能清单
|
||
|
||
菜单来自 `components/AppSidebar.vue`,共 7 组。功能状态取决于后端是否有对应端点。
|
||
|
||
| 菜单分组 | 功能 | 对应前端视图 | 后端端点 | 状态 |
|
||
|---|---|---|---|---|
|
||
| 服务看板 | 仪表盘(统计/分布/排行) | `dashboard/` | `platform.dashboard_*` | ✅ 真实 |
|
||
| 模型服务 | 模型训练 | `fine-tune/` | `platform.fine-tune*` | ✅ 真实(本地执行,见 G1) |
|
||
| 模型服务 | 模型评测 | `eval/` | `/model-eval/*`、`/dimension/*` | ✅ **已移植**(后端端点+SQL表+Store方法齐备) |
|
||
| 模型服务 | 模型推理 | `inference/` | `/model-compare/*`、`/model-chat/*` | ✅ **已移植**(后端端点+SQL表+Store方法+推理代理齐备) |
|
||
| 模型服务 | 模型对比 | `compare/` | `/model-compare/*`(推理/对比共用) | ✅ **已移植**(与推理共用后端) |
|
||
| 模型服务 | 模型管理 | `model/` | `platform.model-manage*` | ✅ 真实 |
|
||
| 数据治理 | 数据集管理 | `dataset/` | `platform.dataset-manage*` | ✅ 真实 |
|
||
| 数据治理 | 数据处理 | `data-process/` | `data_process` 路由 | ✅ 真实 |
|
||
| 其他工具 | 数据类型转换 | `data-convert/` | 无端点 | ❌ 空壳 UI(纯前端,`ElMessage.info('当前仅完成界面设计')`) |
|
||
| 算力资源 | 算力节点 | `compute/` | `platform.compute*` | ⚠️ 模拟(见 §4) |
|
||
| 平台治理 | 租户/项目/审计/审批 | `tenants/ projects/ audit/ approvals/` | tenant/project/approval/audit 模块 | ✅ 真实 |
|
||
| 系统设置 | 用户设置/性能/日志 | `system/ hardware/ logs/` | system/users + logs | ✅ 真实 |
|
||
|
||
**结论**:评测、推理、对比的后端端点已从 `yg_ft1` 移植完成,前端不再 404。
|
||
剩余空壳 UI 仅 **数据类型转换**(`data-convert/`,纯前端界面,无后端端点)。
|
||
|
||
---
|
||
|
||
## 3. 应用后端(backend/app)真实端点
|
||
|
||
挂载于 `api/v1/router.py` 的 9 个路由:`health / platform / auth / system / tenant / project / resource / approval / data_process`。
|
||
其中大量功能集中在 `endpoints/platform.py`(仪表盘、用户、模型、数据集、微调、算力、项目、日志、评测、推理)。
|
||
|
||
### 3.1 已实现(真实可用)
|
||
- **认证**:`/login`、`/logout`、`/me`(登录写 `sessions` 会话,登出关闭会话)
|
||
- **用户/系统**:`/users` CRUD、重置密码、`/system-info`
|
||
- **租户 / 项目空间 / 审批 / 审计**:各模块路由 + `audit_logs`
|
||
- **数据集管理**:`/dataset-manage*` 全量 CRUD + 文件版本/上传/下载/预览
|
||
- **模型管理**:`/model-manage*` 本地/训练模型 CRUD + 合并
|
||
- **模型训练(微调)**:`/fine-tune*` 全量 CRUD + 启停/暂停/恢复/取消/重试/检查点/事件流/日志
|
||
- **数据处理**:`data_process` 模块(创建/删除/上传/生成/发布,已补审计埋点)
|
||
- **仪表盘**:`/dashboard/overview`、`/dashboard/stats`(含真实登录时长、操作分布)
|
||
- **日志**:`/log-files`、`/log-content`、`/training-log-*`
|
||
- **模型评测** ✅ **已移植**:`/model-eval`(列表/详情/启动/删除)、`/dimension`(CRUD)+ `eval_tasks`/`eval_dimensions` 表
|
||
- **模型推理/对比** ✅ **已移植**:`/model-compare`(CRUD + load/unload + load-status + start-model + chat-with-port + stream-chat)+ `/model-chat/*`(local chat/stream/preload/unload/status + trained preload + batch)+ `compare_tasks` 表
|
||
- **推理代理** ✅ **已打通**:`_select_first_online_node()` + `ComputeNodeClient._request()` 将 `/model-chat/local/*` 请求代理到算力 `/modelTF/inference/*`
|
||
|
||
### 3.2 模拟(看似可用,实则未接真实算力)
|
||
- **算力资源** `/compute/nodes`、`/compute/gpus`、`/compute/queue`、`/compute/jobs`:
|
||
- `test-connection` 返回**写死的 success**(不真连)
|
||
- `create_compute_job` 仅**落库**,无任何派发逻辑
|
||
- `gpus`/`queue` 来自 DB,无真实 GPU 采集
|
||
|
||
### 3.3 ~~缺失~~(前端在调用但后端不存在)
|
||
|
||
> **2026-07-31 更新**:原 G5 列出的 `/model-eval/*`、`/inference/*`、`/model-compare/*` 已全部移植完成。
|
||
> 后端 `modules/eval`、`modules/inference` 目录仍仅有空 `__init__.py`(评测/推理逻辑直接写在 `platform.py` + `platform_store.py` 中,与 `yg_ft1` 架构一致)。
|
||
>
|
||
> 唯一仍缺后端端点的是 **数据类型转换** `/data-convert/*`,但该前端页面本身也是纯展示(`ElMessage.info('当前仅完成界面设计')`),不发送 API 请求。
|
||
|
||
---
|
||
|
||
## 4. 算力平台(compute)现状
|
||
|
||
独立 FastAPI 服务,**与应用后端分开部署**(README 明确说明)。
|
||
|
||
### 已实现
|
||
- **健康检查**:`/modelTF/health`、`/modelTF/v1/compute/health`
|
||
- **作业管理**:`POST/GET /modelTF/compute/jobs`、`.../{id}`、`.../{id}/stop`、`.../{id}/logs`
|
||
- **GPU 资源**:`GET /modelTF/compute/resources/gpus`
|
||
- **文件网关**:`/modelTF/compute/files/upload`、`/download`
|
||
- **LLaMA-Factory 适配**:`engines/llama_factory/adapter.py`
|
||
- `build_command()` 生成 `llamafactory-cli train ...`(SFT/LoRA/量化等参数)
|
||
- `parse_log_line()` 解析 loss/grad_norm/learning_rate/epoch 指标
|
||
- **模型推理** ✅ **已移植**:`engines/llama_factory/inference.py`(`InferenceSession` 类:load/unload/chat/chat_stream)
|
||
- **推理 API 端点** ✅ **已移植**:
|
||
- `POST /modelTF/inference/load` — 加载模型
|
||
- `POST /modelTF/inference/unload` — 卸载模型
|
||
- `GET /modelTF/inference/status` — 查询状态
|
||
- `POST /modelTF/inference/chat` — 同步对话
|
||
- `POST /modelTF/inference/chat/stream` — 流式对话(SSE)
|
||
|
||
### 模拟 / 未实现
|
||
- **`simulator` 模式**(默认开发用):作业状态按时间演进(queued→running→completed),
|
||
生成**合成** loss 日志,GPU 列表为构造数据。可完整跑通 UI 流程。
|
||
- **`real` 模式** ✅ **已实现**:`compute/agent/process_manager.py`(`ProcessManager` 类)真正 `subprocess` 拉起 `llamafactory-cli train`,含日志落盘 / checkpoint / artifacts / GPU 锁定 / stop。
|
||
- **依赖缺失**:`compute/requirements.txt` 已声明 `llamafactory`,
|
||
但算力 venv 实际未安装,且 `LLAMA_FACTORY_HOME` 默认指向 `/app/LLaMA-Factory`(运行时需存在)。
|
||
|
||
---
|
||
|
||
## 5. 与架构目标的缺口(重点)
|
||
|
||
架构原则:**后端仅做数据/任务调度与编排,所有涉及 GPU 的计算(训练/推理/评测/转换)一律派发到算力服务执行;应用后端不得安装或本地运行 `llamafactory`/`torch` 等训练运行时。**
|
||
|
||
| # | 缺口 | 现状 | 影响 |
|
||
|---|---|---|---|
|
||
| **G1** → ✅ 已解决 | ~~训练未派发到算力~~ | `start_task` → `_dispatch_to_compute` 派发到算力;`sync.poll_compute_jobs_once` 回传状态;后台轮询线程启动。`runner.py` 本机执行仅保留为无算力节点时的降级 fallback | 训练走算力执行(需 G3 环境就绪) |
|
||
| **G2** → ✅ 已解决 | ~~算力真实执行器未实现~~ | `compute/agent/process_manager.py` 已移植;`compute/api/main.py` real 模式调用 `ProcessManager.create_job` 真正 `subprocess` 拉起训练 | 算力可执行真实训练 |
|
||
| G3 | llamafactory 未安装 | 已声明于 `compute/requirements.txt`,但算力 venv 未装;按架构**不应**装进后端 venv | 真实训练无法启动 |
|
||
| **G4** → ✅ 已解决 | ~~训练前后端算力未连通~~ | 推理路径已通;训练路径已通(`start_task`→`_dispatch_to_compute`→`ComputeNodeClient.create_job`→算力 `ProcessManager`→`sync.poll_compute_jobs_once` 回传) | 训练 GPU 作业数据与算力已连通 |
|
||
| ~~G5~~ → **已解决大部分** | ~~多个前端模块无后端~~ | 评测 ✅ 已移植;推理/对比 ✅ 已移植;数据转换 ❌ 仍空壳 | 仅数据转换功能不可用(纯 UI 占位) |
|
||
|
||
---
|
||
|
||
## 6. 数据流现状 vs 应有
|
||
|
||
### 6.1 训练 ✅ 已打通(待 G3 环境就绪)
|
||
|
||
```
|
||
前端 创建/启动训练 → 后端 /fine-tune/start → platform_store.start_task(payload)
|
||
→ schedule_node() 选取在线算力节点
|
||
→ _dispatch_to_compute() → ComputeNodeClient.create_job(cfg) 派发到算力
|
||
→ 算力 POST /modelTF/compute/jobs → ProcessManager.create_job() → subprocess llamafactory-cli train
|
||
→ 后台轮询线程 sync.poll_compute_jobs_once() 周期拉取状态/日志/指标 → apply_compute_job 回写
|
||
→ 训练完成 → _ensure_trained_model 登记产物
|
||
```
|
||
|
||
> **降级 fallback**:当无在线算力节点时,`start_task` 降级到 `service.launch_training` → `runner.run_training`(本机 subprocess,违反 §1.1,待移除)。
|
||
>
|
||
> **前置依赖**:算力 venv 需安装 `llamafactory`(G3);基座模型/数据集文件需到达算力节点(阶段 4)。
|
||
|
||
### 6.2 推理 ✅ 已打通
|
||
|
||
```
|
||
前端 新建推理/对话 → 后端 /model-compare/* 或 /model-chat/local/*
|
||
→ 后端 _select_first_online_node(store) 选取在线算力节点
|
||
→ ComputeNodeClient(api_base_url)._request("POST", "/inference/chat", json_data=payload)
|
||
→ 算力平台 POST /modelTF/inference/chat → InferenceSession.chat() → 返回推理结果
|
||
→ 流式:POST /modelTF/inference/chat/stream → SSE 逐字回传
|
||
```
|
||
|
||
> 推理路径已完全打通:后端代理 → 算力执行 → 结果回传。
|
||
> 若算力节点不在线,后端返回降级响应(`"no online compute node available for inference"`)。
|
||
|
||
---
|
||
|
||
## 7. 建议的下一步
|
||
|
||
1. **训练打通**(当前最高优先级缺口):
|
||
- 移植 `yg_ft1` 的 `compute/agent/process_manager.py`(real 执行器)到 `compute/agent/`;
|
||
- 移植 `yg_ft1` 的 `compute_gateway/sync.py`(派发+状态/日志回传)到 `backend/app/modules/compute_gateway/`;
|
||
- 改造 `fine_tune/service.py`:`start_task` 改为经 `compute_gateway.dispatch()` 派发,移除本机 `runner.py` subprocess。
|
||
2. **环境**(低风险):在算力 venv 安装 `llamafactory`;后端 venv 保持不含它。
|
||
3. **联调**:算力平台切 `COMPUTE_EXECUTION_MODE=simulator`,后端改为经算力 API 派发训练,使训练 UI 走通。
|
||
4. **数据转换**(低优先级):补齐 `/data-convert/*` 后端端点(当前前端纯 UI 占位,无 API 调用)。
|
||
|
||
---
|
||
|
||
## 8. 改造路线图:GPU 任务从后端进程派发到算力服务进程
|
||
|
||
目标:落实 §1.1 职责边界——**后端只做数据/任务调度与编排,GPU 计算一律派发给算力服务进程执行**。
|
||
当前 `fine_tune/runner.py` 用后端 venv 本机 `subprocess` 跑 `train.py` 是违反原则的临时实现,需移除并改为「派发 + 回传」。
|
||
|
||
> **参考实现 `yg_ft1`**:同仓下 `e:/yg_ft/yg_ft1` 是更完整的参考版本,本路线图所需能力大多已实现,应**直接迁移/对齐,而非从零编写**:
|
||
> - **训练闭环完整**:`compute/agent/process_manager.py`(real 模式真正 `subprocess` 拉起 `llamafactory-cli train`,含日志落盘 / checkpoint / artifacts / GPU 锁定 / stop)、`compute/engines/llama_factory/adapter.py`(`build_command` / `prepare_runtime_files` / `parse_log_line`)、后端 `compute_gateway/client.py` + `sync.py`(派发 + 状态/日志回传)。
|
||
> - **推理真实端点** ✅ 已迁移:`compute/api/main.py` 的 `/inference/*` + `compute/engines/llama_factory/inference.py` 已于 2026-07-31 移植到当前项目。
|
||
> - **评测** ✅ 后端端点已迁移:`/model-eval/*` + `/dimension/*` + `eval_tasks`/`eval_dimensions` 表 + Store 方法已于 2026-07-31 移植。**但评测执行器(是否走算力)尚未实现**——当前仅落库,无真实评测执行。
|
||
>
|
||
> 因此阶段 1/2/3 本质是**把 `yg_ft1` 的训练相关文件迁移到 `yg_ft` 并对齐接口**;推理已完成;评测需另行补全执行器。
|
||
|
||
> 现状代码支撑:`compute_nodes` 表已带 `api_base_url` 字段(见 `001_platform_runtime.sql`),
|
||
> 算力 API 已有 `jobs/create/get/stop/logs` 与 `resources/gpus`,`adapter.build_command` 可生成 `llamafactory-cli train`。
|
||
> `ComputeNodeClient` 已有 `headers()`、`_request()` 异步方法(推理代理已验证可用)。
|
||
> 缺的是:① 后端 `compute_gateway/sync.py`(派发+回传同步线程);② 训练不走本机;③ 算力 `real` 执行器(`process_manager.py`);④ 数据集/模型文件如何到达算力。
|
||
|
||
### 阶段 0 — 算力环境就绪(前置)—— **待执行**
|
||
- **改动**:在算力服务 venv 安装 `llamafactory`(依赖已声明于 `compute/requirements.txt`),后端 venv 保持不含它。
|
||
- **验证**:算力切 `simulator` 时 `POST /modelTF/compute/jobs` 能返回 `queued`;`pip show llamafactory` 在算力环境为已装、在后端为未装。
|
||
|
||
### 阶段 1 — 后端 `compute_gateway` 桥接 ✅ 已完成
|
||
- **已建文件**:`backend/app/modules/compute_gateway/sync.py`(从 `yg_ft1` 迁移)。
|
||
- **已实现**:
|
||
- `sync.py`:`poll_compute_jobs_once()` 周期性同步线程,从算力 API 拉取 job 状态/日志/指标,写回 `PlatformStore.task`。
|
||
- `client.py` 已有 `create_job`/`get_job`/`stop_job`/`job_logs` 方法(同步)和 `_request`/`headers` 方法(异步,推理已用),直接复用。
|
||
- `_select_first_online_node` 已实现(推理代理已验证)。
|
||
- 后台轮询线程在 `main.py` lifespan 中自动启动。
|
||
|
||
### 阶段 2 — 训练改为「派发 + 回传」 ✅ 已完成
|
||
- **已改文件**:`backend/app/modules/fine_tune/service.py`、`backend/app/db/platform_store.py`、`backend/app/main.py`。
|
||
- **已实现**:
|
||
- `platform_store.start_task` → `schedule_node` → `_dispatch_to_compute` → `ComputeNodeClient.create_job` 派发到算力。
|
||
- 后台轮询线程(`service.start_compute_sync_worker`)启动,周期调 `sync.poll_compute_jobs_once`。
|
||
- `apply_compute_job` 回写状态/进度/日志/checkpoints/artifacts;`record_training_log_metrics` 解析并存储训练指标。
|
||
- `stop_task` 改为先通知算力 `stop_job`,再更新 DB + 释放 GPU。
|
||
- `runner.py` 本机 `subprocess` 仅保留为无算力节点时的降级 fallback(`start_task` 中 `elif` 分支)。
|
||
|
||
### 阶段 3 — 算力 `real` 执行器 ✅ 已移植
|
||
- **已建文件**:`compute/agent/process_manager.py`(从 `yg_ft1` 迁移)。
|
||
- **已改文件**:`compute/api/main.py`(real 模式调用 `ProcessManager`)。
|
||
- **已实现**:`ProcessManager` 类——真正 `subprocess` 拉起 `llamafactory-cli train`,含日志落盘 / checkpoint 收集 / artifacts 收集 / GPU 锁定 / stop。`compute/api/main.py` 的 real 模式不再返回 501。
|
||
|
||
### 阶段 4 — 数据集 / 模型文件到达算力(关键依赖)
|
||
- **问题**:派发后算力节点须能读到**基座模型**与**训练数据集**文件。
|
||
- **方案(二选一或并存)**:
|
||
- A(推荐,生产):基座模型与数据集通过**共享存储**(NFS / 对象存储)挂载到算力节点,路径随派发 config 传入;
|
||
- B(已具备雏形):经算力文件网关 `POST /compute/files/upload` → `/download` 传输(当前为占位,需落盘实现)。
|
||
- **验证**:算力 `real` 执行时能从指定路径加载模型与数据集,不报「文件不存在」。
|
||
|
||
### 阶段 5 — 评测执行器 / 数据转换
|
||
- **评测**:后端端点已移植(`/model-eval/*` 落库),但**真实评测执行器**未实现(是否走算力待定)。需补全评测执行逻辑——可能经 `compute_gateway` 派发到算力,或后端编排调 API 模型评测。
|
||
- **数据转换**:补齐 `/data-convert/*` 后端端点(当前前端纯 UI 占位,无 API 调用)。
|
||
- **验证**:评测任务能真实执行并产出分数;数据转换页面功能可用。
|
||
|
||
### 风险与前置提醒
|
||
1. **阶段 4 文件传递是派发可用性的硬前置**——不解决,算力无数据可训(优先级高于阶段 3)。
|
||
2. **暂停/恢复语义缺口**:算力当前仅 `stop`,阶段 2 需先确定 pause/resume 是否必需、如何映射。
|
||
3. **共享存储/网络可达性**:`compute_nodes.api_base_url` 必须网络可达,且算力与后端时间/路径一致。
|
||
4. **回退策略**:阶段 2 上线前保留本机 `runner` 作为可开关的 fallback(`DISPATCH_TO_COMPUTE=true/false`),便于灰度。
|
||
```
|