Files
observer/server/biz/model/dto/training.go
T
2026-08-27 17:54:48 +08:00

370 lines
16 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package dto
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gtime"
)
// 模型训练体系接口(数据集 → 标注 → 训练 → 模型版本),组前缀 /api/v1/admin。
// 图片/标注/模型文件均在服务器磁盘(app.datasetDir),DB 只存元数据。
// 图片访问为直接写响应体场景,由 controller 以 *ghttp.Request 方法实现
// (见 controller/admin.go 的 Image 方法)。
// ---------- 数据集管理 ----------
// AdminDatasetListReq 数据集列表(创建时间倒序)
type AdminDatasetListReq struct {
g.Meta `path:"/datasets" method:"get" summary:"数据集列表" tags:"管理端"`
Keyword string `json:"keyword" v:"length:0,50" dc:"名称模糊匹配"`
Page int `json:"page" v:"integer|min:1" dc:"页码,默认 1"`
Size int `json:"size" v:"integer|min:1|max:100" dc:"每页条数,默认 20"`
}
// AdminDatasetItem 数据集条目(卡片展示用;AI 端点/训练机 SSH 走 config.yml 全局配置(localAi / training.ssh))
type AdminDatasetItem struct {
Id int64 `json:"id"`
Name string `json:"name"`
Source string `json:"source"` // manual | ai
ImageCount int64 `json:"imageCount"`
LabeledCount int64 `json:"labeledCount"`
Status string `json:"status"` // building | labeled | synced
Cover string `json:"cover"` // 封面文件名
Description string `json:"description"` // 描述
TrainingId int64 `json:"trainingId"` // 最新训练记录 id(发布/详情用)
TrainingStatus string `json:"trainingStatus"` // 最新训练记录状态 running|success|failed|空
TrainingError string `json:"trainingError"` // 最新训练记录失败原因(failed 时展示用)
TrainingCurrentEpoch int `json:"trainingCurrentEpoch"`
TrainingTotalEpochs int `json:"trainingTotalEpochs"`
CreatedAt *gtime.Time `json:"createdAt"`
UpdatedAt *gtime.Time `json:"updatedAt"`
}
type AdminDatasetListRes struct {
Total int64 `json:"total"`
List []*AdminDatasetItem `json:"list"`
}
// AdminDatasetUpdateReq 更新数据集配置(空值字段不覆盖原值,保留现有配置;改名时同步迁移
// 图片目录与模型文件,名称唯一且同是磁盘目录名;
// AI 端点/训练机 SSH 走 config.yml 全局配置(localAi / training.ssh))
type AdminDatasetUpdateReq struct {
g.Meta `path:"/datasets/update" method:"post" summary:"更新数据集配置" tags:"管理端"`
Id int64 `json:"id" v:"required|min:1" dc:"数据集 id"`
Name string `json:"name" v:"length:0,50" dc:"数据集名称(非空且变化才更新;同是目录名)"`
Description string `json:"description" v:"length:0,500" dc:"描述(非空才更新)"`
Cover string `json:"cover" v:"length:0,200" dc:"封面文件名(非空才更新)"`
}
type AdminDatasetUpdateRes struct {
Id int64 `json:"id"`
}
// AdminDatasetCreateReq 新建数据集(名称同时是磁盘目录名:中文/字母/数字/下划线/短横线,唯一)
type AdminDatasetCreateReq struct {
g.Meta `path:"/datasets" method:"post" summary:"新建数据集" tags:"管理端"`
Name string `json:"name" v:"required|regex:^[a-zA-Z0-9_一-龥-]+$|length:1,50" dc:"数据集名称(同是目录名,唯一)"`
Source string `json:"source" v:"required|in:manual,ai" dc:"图片来源 manual|ai"`
}
type AdminDatasetCreateRes struct {
Id int64 `json:"id"`
}
// AdminDatasetDeleteReq 删除数据集(删除图片文件+标注目录+记录;AI 生成图为付费资产,前端须带确认文案)
type AdminDatasetDeleteReq struct {
g.Meta `path:"/datasets/delete" method:"post" summary:"删除数据集" tags:"管理端"`
Id int64 `json:"id" v:"required|min:1" dc:"数据集 id"`
}
type AdminDatasetDeleteRes struct{}
// AdminDatasetUploadReq 上传图片(multipart 多文件;重名跳过并计数)
type AdminDatasetUploadReq struct {
g.Meta `path:"/datasets/upload" method:"post" summary:"上传图片" tags:"管理端" mime:"multipart/form-data"`
DatasetId int64 `json:"datasetId" v:"required|min:1" dc:"数据集 id"`
Files []*ghttp.UploadFile `json:"files" dc:"图片文件(jpg/jpeg/png,多选)"`
}
type AdminDatasetUploadRes struct {
Added int `json:"added"`
Skipped int `json:"skipped"` // 重名跳过数
}
// AdminDatasetGenerateReq AI 生成图片(同步执行;prompt 禁止含目标位置描述,前端模板+文案约束)
type AdminDatasetGenerateReq struct {
g.Meta `path:"/datasets/generate" method:"post" summary:"AI 生成图片" tags:"管理端"`
DatasetId int64 `json:"datasetId" v:"required|min:1" dc:"数据集 id"`
Prompt string `json:"prompt" v:"required|length:5,500" dc:"生成提示词(禁止含位置描述)"`
Count int `json:"count" v:"required|integer|min:1|max:8" dc:"生成张数 1-8"`
Size string `json:"size" v:"required|in:704x1248" dc:"图片尺寸"`
}
type AdminDatasetGenerateRes struct {
Generated int `json:"generated"` // 成功张数(失败时可能 < count,已成功的图保留)
}
// AdminDatasetImagesReq 数据集图片列表(标注工作台/网格预览用)
type AdminDatasetImagesReq struct {
g.Meta `path:"/datasets/images" method:"get" summary:"数据集图片列表" tags:"管理端"`
DatasetId int64 `json:"datasetId" v:"required|min:1" dc:"数据集 id"`
}
// AdminImageItem 图片条目(url 为管理端图片访问地址,前端拼 apiBaseUrl 使用)
type AdminImageItem struct {
Id int64 `json:"id"`
Filename string `json:"filename"`
Source string `json:"source"` // manual | ai
Prompt string `json:"prompt"`
Url string `json:"url"`
CreatedAt *gtime.Time `json:"createdAt"`
}
type AdminDatasetImagesRes struct {
List []*AdminImageItem `json:"list"`
}
// AdminDatasetImagesDeleteReq 删除图片(删文件+删记录;付费资产,前端须带确认文案)
type AdminDatasetImagesDeleteReq struct {
g.Meta `path:"/datasets/images/delete" method:"post" summary:"删除图片" tags:"管理端"`
DatasetId int64 `json:"datasetId" v:"required|min:1" dc:"数据集 id"`
Ids []int64 `json:"ids" v:"required|min-length:1" dc:"图片记录 id 列表"`
}
type AdminDatasetImagesDeleteRes struct{}
// AdminDatasetImageReq 图片访问(直写响应体,例外场景:controller 经 service 校验归属后输出二进制)
type AdminDatasetImageReq struct {
g.Meta `path:"/datasets/image" method:"get" summary:"图片访问" tags:"管理端"`
DatasetId int64 `json:"datasetId" v:"required|min:1" dc:"数据集 id"`
Filename string `json:"filename" v:"required" dc:"图片文件名"`
}
type AdminDatasetImageRes struct{}
// AdminDatasetCoverUploadReq 上传数据集封面(multipart 单文件;覆盖旧封面,UUID 命名 jpg)
type AdminDatasetCoverUploadReq struct {
g.Meta `path:"/datasets/cover" method:"post" summary:"上传数据集封面" tags:"管理端" mime:"multipart/form-data"`
DatasetId int64 `json:"datasetId" v:"required|min:1" dc:"数据集 id"`
File *ghttp.UploadFile `json:"file" dc:"封面图片(jpg/jpeg/png,≤2MB)"`
}
type AdminDatasetCoverUploadRes struct{}
// AdminDatasetCoverReq 封面访问(直写响应体,与 Image 同模式)
type AdminDatasetCoverReq struct {
g.Meta `path:"/datasets/cover" method:"get" summary:"数据集封面访问" tags:"管理端"`
DatasetId int64 `json:"datasetId" v:"required|min:1" dc:"数据集 id"`
}
type AdminDatasetCoverRes struct{}
// AdminDatasetCoverDeleteReq 删除数据集封面(删文件+清字段;列表卡片恢复占位图)
type AdminDatasetCoverDeleteReq struct {
g.Meta `path:"/datasets/cover/delete" method:"post" summary:"删除数据集封面" tags:"管理端"`
DatasetId int64 `json:"datasetId" v:"required|min:1" dc:"数据集 id"`
}
type AdminDatasetCoverDeleteRes struct{}
// ---------- 训练编排 ----------
// AdminTrainingListReq 训练任务列表(创建时间倒序)
type AdminTrainingListReq struct {
g.Meta `path:"/trainings" method:"get" summary:"训练任务列表" tags:"管理端"`
Status string `json:"status" v:"in:running,success,failed" dc:"状态筛选"`
Page int `json:"page" v:"integer|min:1" dc:"页码,默认 1"`
Size int `json:"size" v:"integer|min:1|max:100" dc:"每页条数,默认 20"`
}
// AdminTrainingItem 训练任务条目(列表不含日志尾部,详情接口返回)
type AdminTrainingItem struct {
Id int64 `json:"id"`
Name string `json:"name"`
DatasetId int64 `json:"datasetId"`
DatasetName string `json:"datasetName"`
Status string `json:"status"` // running | success | failed
Imgsz int `json:"imgsz"`
Epochs int `json:"epochs"`
Batch int `json:"batch"`
Device string `json:"device"`
CurrentEpoch int `json:"currentEpoch"`
TotalEpochs int `json:"totalEpochs"`
Metrics string `json:"metrics"`
Error string `json:"error"`
StartedAt *gtime.Time `json:"startedAt"`
FinishedAt *gtime.Time `json:"finishedAt"`
CreatedAt *gtime.Time `json:"createdAt"`
}
type AdminTrainingListRes struct {
Total int64 `json:"total"`
List []*AdminTrainingItem `json:"list"`
}
// AdminTrainingStartReq 发起训练(并发度 1:已有 running 任务时拒绝;训练参数走 config.yml training 节点,name 空则自动生成)
type AdminTrainingStartReq struct {
g.Meta `path:"/trainings" method:"post" summary:"发起训练" tags:"管理端"`
DatasetId int64 `json:"datasetId" v:"required|min:1" dc:"数据集 id"`
Name string `json:"name" v:"length:0,50" dc:"任务名称,空自动生成"`
}
type AdminTrainingStartRes struct {
Id int64 `json:"id"`
}
// AdminTrainingDetailReq 训练任务详情(含日志尾部)
type AdminTrainingDetailReq struct {
g.Meta `path:"/trainings/detail" method:"get" summary:"训练任务详情" tags:"管理端"`
Id int64 `json:"id" v:"required|min:1" dc:"训练任务 id"`
}
// AdminTrainingDetailRes 详情 = 条目 + 日志尾部
type AdminTrainingDetailRes struct {
AdminTrainingItem
LogTail string `json:"logTail"`
}
// AdminTrainingCancelReq 取消训练(杀进程,任务置 failed)
type AdminTrainingCancelReq struct {
g.Meta `path:"/trainings/cancel" method:"post" summary:"取消训练" tags:"管理端"`
Id int64 `json:"id" v:"required|min:1" dc:"训练任务 id"`
}
type AdminTrainingCancelRes struct{}
// AdminTrainingPublishReq 发布模型版本(仅 success 任务;按数据集版本号 m<major>.<minor>.<patch> 自增)
type AdminTrainingPublishReq struct {
g.Meta `path:"/trainings/publish" method:"post" summary:"发布模型版本" tags:"管理端"`
Id int64 `json:"id" v:"required|min:1" dc:"训练任务 id"`
}
type AdminTrainingPublishRes struct {
Version string `json:"version"`
}
// ---------- 模型版本 ----------
// ---------- 预标注 ----------
// AdminLabelTaskListReq 预标注任务列表(创建时间倒序)
type AdminLabelTaskListReq struct {
g.Meta `path:"/label-tasks" method:"get" summary:"预标注任务列表" tags:"管理端"`
Page int `json:"page" v:"integer|min:1" dc:"页码,默认 1"`
Size int `json:"size" v:"integer|min:1|max:100" dc:"每页条数,默认 20"`
}
type AdminLabelTaskItem struct {
Id int64 `json:"id"`
DatasetId int64 `json:"datasetId"`
DatasetName string `json:"datasetName"`
Status string `json:"status"` // running | done
Total int `json:"total"`
Done int `json:"done"`
Error string `json:"error"`
CreatedAt *gtime.Time `json:"createdAt"`
FinishedAt *gtime.Time `json:"finishedAt"`
}
type AdminLabelTaskListRes struct {
Total int64 `json:"total"`
List []*AdminLabelTaskItem `json:"list"`
}
// AdminLabelTaskStartReq 发起预标注(RF-DETR 扫描,候选框合并入 datasets/<name>/boxes.json
type AdminLabelTaskStartReq struct {
g.Meta `path:"/label-tasks" method:"post" summary:"发起预标注" tags:"管理端"`
DatasetId int64 `json:"datasetId" v:"required|min:1" dc:"数据集 id"`
Filenames []string `json:"filenames" v:"length:0,500" dc:"选中图片列表(多选批量);缺省=全量扫描"`
}
type AdminLabelTaskStartRes struct {
Id int64 `json:"id"`
}
// AdminLabelTaskDetailReq 预标注任务详情(每张图候选框 + 已确认标注,供工作台 canvas 叠框)
type AdminLabelTaskDetailReq struct {
g.Meta `path:"/label-tasks/detail" method:"get" summary:"预标注任务详情" tags:"管理端"`
Id int64 `json:"id" v:"required|min:1" dc:"标注任务 id"`
}
// AdminLabelBox 单框(归一化 xywh,坐标 0~1)
type AdminLabelBox struct {
Cx float64 `json:"cx"`
Cy float64 `json:"cy"`
W float64 `json:"w"`
H float64 `json:"h"`
Confidence float64 `json:"confidence"` // 人工框为 1
Class int `json:"class"` // 0 确认 | 1 疑似
}
// AdminLabelImageItem 工作台单张图:全部标注(labels_json,AI 自动标注与人工框同层,人工可修改/清理)
type AdminLabelImageItem struct {
Filename string `json:"filename"`
Url string `json:"url"`
Width int `json:"width"`
Height int `json:"height"`
Boxes []*AdminLabelBox `json:"boxes"`
Labeled bool `json:"labeled"` // 有标注(AI 自动标注或人工保存)
}
type AdminLabelTaskDetailRes struct {
TaskId int64 `json:"taskId"`
DatasetId int64 `json:"datasetId"`
DatasetName string `json:"datasetName"`
Status string `json:"status"`
Total int `json:"total"`
Done int `json:"done"`
Error string `json:"error"`
Images []*AdminLabelImageItem `json:"images"`
}
// AdminLabelWorkbenchReq 标注工作台数据(无历史任务时直接用数据集图片 + 已确认标注,
// 候选框读数据集目录 boxes.json)
type AdminLabelWorkbenchReq struct {
g.Meta `path:"/label-workbench" method:"get" summary:"标注工作台数据" tags:"管理端"`
DatasetId int64 `json:"datasetId" v:"required|min:1" dc:"数据集 id"`
}
type AdminLabelWorkbenchRes struct {
DatasetId int64 `json:"datasetId"`
DatasetName string `json:"datasetName"`
Images []*AdminLabelImageItem `json:"images"`
}
// AdminLabelSaveReq 保存单张图标注(工作台「保存本张」;覆写 dataset_image.labels_json
type AdminLabelSaveReq struct {
g.Meta `path:"/label-tasks/save" method:"post" summary:"保存图片标注" tags:"管理端"`
DatasetId int64 `json:"datasetId" v:"required|min:1" dc:"数据集 id"`
Filename string `json:"filename" v:"required|length:1,200" dc:"图片文件名"`
Boxes []*AdminLabelBox `json:"boxes" dc:"确认后的框列表(空=清空标注)"`
}
type AdminLabelSaveRes struct {
LabeledCount int64 `json:"labeledCount"` // 该数据集当前已标注图数
}
// ---------- 客户端模型目录 ----------
// ModelCatalogReq 模型目录(客户端登录态):全部数据集的当前生效模型
type ModelCatalogReq struct {
g.Meta `path:"/models" method:"get" summary:"模型目录" tags:"客户端"`
}
// ModelCatalogItem 客户端模型条目(App 按需下载,多模型并行推理合并)
type ModelCatalogItem struct {
DatasetId int64 `json:"datasetId"`
DatasetName string `json:"datasetName"`
Version string `json:"version"`
Labels []string `json:"labels"` // 类别名,App 推理结果展示用
SizeBytes int64 `json:"sizeBytes"`
Sha256 string `json:"sha256"`
Notes string `json:"notes"`
PublishedAt *gtime.Time `json:"publishedAt"`
DownloadUrl string `json:"downloadUrl"` // /download/trainings/<name>.tflite
}
type ModelCatalogRes struct {
List []*ModelCatalogItem `json:"list"`
}