379 lines
16 KiB
Go
379 lines
16 KiB
Go
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 只存元数据。
|
||
// 图片访问与 zip 导出为直接写响应体场景,由 controller 以 *ghttp.Request 方法实现
|
||
// (见 controller/admin.go 的 Image/ExportDataset 方法)。
|
||
|
||
// ---------- 数据集管理 ----------
|
||
|
||
// 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|空
|
||
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"`
|
||
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:1152x2048,704x704" 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{}
|
||
|
||
// AdminDatasetExportReq 数据集 zip 导出(直写响应体下载;标注衔接与备份用)
|
||
type AdminDatasetExportReq struct {
|
||
g.Meta `path:"/datasets/export" method:"get" summary:"导出数据集 zip" tags:"管理端"`
|
||
DatasetId int64 `json:"datasetId" v:"required|min:1" dc:"数据集 id"`
|
||
}
|
||
|
||
type AdminDatasetExportRes struct{}
|
||
|
||
// AdminDatasetCoverUploadReq 上传数据集封面(multipart 单文件;覆盖旧封面,存图片目录 cover<ext>)
|
||
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 任务时拒绝)
|
||
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:"required|length:1,50" dc:"任务名称"`
|
||
Imgsz int `json:"imgsz" v:"integer|min:64|max:2048" dc:"输入尺寸,默认 704"`
|
||
Epochs int `json:"epochs" v:"integer|min:1|max:1000" dc:"训练轮数,默认 150"`
|
||
Batch int `json:"batch" v:"integer|min:1|max:128" dc:"批大小,默认 16"`
|
||
Device string `json:"device" v:"length:0,16" dc:"设备,默认 0"`
|
||
}
|
||
|
||
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/models/<name>/latest.tflite
|
||
}
|
||
|
||
type ModelCatalogRes struct {
|
||
List []*ModelCatalogItem `json:"list"`
|
||
}
|