From 92146da8213e5d7b57276ef1b4b32239acab613c Mon Sep 17 00:00:00 2001 From: zouap Date: Tue, 1 Nov 2022 16:45:11 +0800 Subject: [PATCH 001/106] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- routers/repo/ai_model_manage.go | 8 ++++++++ routers/routes/routes.go | 2 ++ 2 files changed, 10 insertions(+) diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index f2b0fc6d1..3545b090b 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -189,6 +189,14 @@ func SaveNewNameModel(ctx *context.Context) { log.Info("save model end.") } +func SaveLocalModel(ctx *context.Context) { + +} + +func UploadLocalModel(ctx *context.Context) { + +} + func SaveModel(ctx *context.Context) { if !ctx.Repo.CanWrite(models.UnitTypeModelManage) { ctx.Error(403, ctx.Tr("repo.model_noright")) diff --git a/routers/routes/routes.go b/routers/routes/routes.go index fd8b274e6..588a00c18 100755 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -1233,6 +1233,8 @@ func RegisterRoutes(m *macaron.Macaron) { }, context.RepoRef()) m.Group("/modelmanage", func() { m.Post("/create_model", repo.SaveModel) + m.Post("/upload_local_model", repo.UploadLocalModel) + m.Post("/create_local_model", repo.SaveLocalModel) m.Post("/create_model_convert", reqWechatBind, reqRepoModelManageWriter, repo.SaveModelConvert) m.Post("/create_new_model", repo.SaveNewNameModel) m.Delete("/delete_model", repo.DeleteModel) From 7d310b184aae0f039d863c82579fcb067e18f69f Mon Sep 17 00:00:00 2001 From: zouap Date: Tue, 1 Nov 2022 17:54:14 +0800 Subject: [PATCH 002/106] =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=8F=8A=E6=A8=A1=E5=9E=8B=E8=BD=AC=E6=8D=A2=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=A4=A7=E5=B0=8F=E5=86=99=E7=BB=9F=E4=B8=80=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- models/ai_model_manage.go | 116 +++++++++--------- routers/api/v1/api.go | 12 ++ routers/api/v1/repo/modelmanage.go | 106 ++++++++++++++++ routers/repo/ai_model_convert.go | 61 ++++++---- routers/repo/ai_model_manage.go | 162 +++++++++++++++++-------- templates/repo/cloudbrain/inference/new.tmpl | 6 +- templates/repo/cloudbrain/trainjob/show.tmpl | 36 +++--- templates/repo/grampus/trainjob/show.tmpl | 41 ++++--- templates/repo/modelarts/inferencejob/new.tmpl | 6 +- templates/repo/modelarts/trainjob/show.tmpl | 45 +++---- templates/repo/modelmanage/convertIndex.tmpl | 74 +++++------ templates/repo/modelmanage/index.tmpl | 54 +++++---- templates/repo/modelmanage/showinfo.tmpl | 140 +++++++++++---------- web_src/js/components/Model.vue | 156 ++++++++++++------------ web_src/js/features/cloudbrainShow.js | 8 +- 15 files changed, 609 insertions(+), 414 deletions(-) create mode 100644 routers/api/v1/repo/modelmanage.go diff --git a/models/ai_model_manage.go b/models/ai_model_manage.go index d9adda2dc..0d754b0ba 100644 --- a/models/ai_model_manage.go +++ b/models/ai_model_manage.go @@ -12,67 +12,67 @@ import ( ) type AiModelManage struct { - ID string `xorm:"pk"` - Name string `xorm:"INDEX NOT NULL"` - Version string `xorm:"NOT NULL"` - VersionCount int `xorm:"NOT NULL DEFAULT 0"` - New int `xorm:"NOT NULL"` - Type int `xorm:"NOT NULL"` - Size int64 `xorm:"NOT NULL"` - Description string `xorm:"varchar(2000)"` - Label string `xorm:"varchar(1000)"` - Path string `xorm:"varchar(400) NOT NULL"` - DownloadCount int `xorm:"NOT NULL DEFAULT 0"` - Engine int64 `xorm:"NOT NULL DEFAULT 0"` - Status int `xorm:"NOT NULL DEFAULT 0"` - StatusDesc string `xorm:"varchar(500)"` - Accuracy string `xorm:"varchar(1000)"` - AttachmentId string `xorm:"NULL"` - RepoId int64 `xorm:"INDEX NULL"` - CodeBranch string `xorm:"varchar(400) NULL"` - CodeCommitID string `xorm:"NULL"` - UserId int64 `xorm:"NOT NULL"` - UserName string - UserRelAvatarLink string - TrainTaskInfo string `xorm:"text NULL"` - CreatedUnix timeutil.TimeStamp `xorm:"created"` - UpdatedUnix timeutil.TimeStamp `xorm:"updated"` - IsCanOper bool - IsCanDelete bool + ID string `xorm:"pk" json:"id"` + Name string `xorm:"INDEX NOT NULL" json:"name"` + Version string `xorm:"NOT NULL" json:"version"` + VersionCount int `xorm:"NOT NULL DEFAULT 0" json:"versionCount"` + New int `xorm:"NOT NULL" json:"new"` + Type int `xorm:"NOT NULL" json:"type"` + Size int64 `xorm:"NOT NULL" json:"size"` + Description string `xorm:"varchar(2000)" json:"description"` + Label string `xorm:"varchar(1000)" json:"label"` + Path string `xorm:"varchar(400) NOT NULL" json:"path"` + DownloadCount int `xorm:"NOT NULL DEFAULT 0" json:"downloadCount"` + Engine int64 `xorm:"NOT NULL DEFAULT 0" json:"engine"` + Status int `xorm:"NOT NULL DEFAULT 0" json:"status"` + StatusDesc string `xorm:"varchar(500)" json:"statusDesc"` + Accuracy string `xorm:"varchar(1000)" json:"accuracy"` + AttachmentId string `xorm:"NULL" json:"attachmentId"` + RepoId int64 `xorm:"INDEX NULL" json:"repoId"` + CodeBranch string `xorm:"varchar(400) NULL" json:"codeBranch"` + CodeCommitID string `xorm:"NULL" json:"codeCommitID"` + UserId int64 `xorm:"NOT NULL" json:"userId"` + UserName string `json:"userName"` + UserRelAvatarLink string `json:"userRelAvatarLink"` + TrainTaskInfo string `xorm:"text NULL" json:"trainTaskInfo"` + CreatedUnix timeutil.TimeStamp `xorm:"created" json:"createdUnix"` + UpdatedUnix timeutil.TimeStamp `xorm:"updated" json:"updatedUnix"` + IsCanOper bool `json:"isCanOper"` + IsCanDelete bool `json:"isCanDelete"` } type AiModelConvert struct { - ID string `xorm:"pk"` - Name string `xorm:"INDEX NOT NULL"` - Status string `xorm:"NULL"` - StatusResult string `xorm:"NULL"` - SrcEngine int `xorm:"NOT NULL DEFAULT 0"` - RepoId int64 `xorm:"INDEX NULL"` - ModelId string `xorm:"NOT NULL"` - ModelName string `xorm:"NULL"` - ModelVersion string `xorm:"NOT NULL"` - ModelPath string `xorm:"NULL"` - DestFormat int `xorm:"NOT NULL DEFAULT 0"` - NetOutputFormat int `xorm:"NULL"` - UserId int64 `xorm:"NOT NULL"` - CloudBrainTaskId string `xorm:"NULL"` - ModelArtsVersionId string `xorm:"NULL"` - ContainerID string - ContainerIp string - RunTime int64 `xorm:"NULL"` - TrainJobDuration string - InputShape string `xorm:"varchar(2000)"` - InputDataFormat string `xorm:"NOT NULL"` - Description string `xorm:"varchar(2000)"` - Path string `xorm:"varchar(400) NOT NULL"` - CreatedUnix timeutil.TimeStamp `xorm:"created"` - UpdatedUnix timeutil.TimeStamp `xorm:"updated"` - StartTime timeutil.TimeStamp - EndTime timeutil.TimeStamp - UserName string - UserRelAvatarLink string - IsCanOper bool - IsCanDelete bool + ID string `xorm:"pk" json:"id"` + Name string `xorm:"INDEX NOT NULL" json:"name"` + Status string `xorm:"NULL" json:"status"` + StatusResult string `xorm:"NULL" json:"statusResult"` + SrcEngine int `xorm:"NOT NULL DEFAULT 0" json:"srcEngine"` + RepoId int64 `xorm:"INDEX NULL" json:"repoId"` + ModelId string `xorm:"NOT NULL" json:"modelId"` + ModelName string `xorm:"NULL" json:"modelName"` + ModelVersion string `xorm:"NOT NULL" json:"modelVersion"` + ModelPath string `xorm:"NULL" json:"modelPath"` + DestFormat int `xorm:"NOT NULL DEFAULT 0" json:"destFormat"` + NetOutputFormat int `xorm:"NULL" json:"netOutputFormat"` + UserId int64 `xorm:"NOT NULL" json:"userId"` + CloudBrainTaskId string `xorm:"NULL" json:"cloudBrainTaskId"` + ModelArtsVersionId string `xorm:"NULL" json:"modelArtsVersionId"` + ContainerID string `json:"containerID"` + ContainerIp string `json:"containerIp"` + RunTime int64 `xorm:"NULL" json:"runTime"` + TrainJobDuration string `json:"trainJobDuration"` + InputShape string `xorm:"varchar(2000)" json:"inputShape"` + InputDataFormat string `xorm:"NOT NULL" json:"inputDataFormat"` + Description string `xorm:"varchar(2000)" json:"description"` + Path string `xorm:"varchar(400) NOT NULL" json:"path"` + CreatedUnix timeutil.TimeStamp `xorm:"created" json:"createdUnix"` + UpdatedUnix timeutil.TimeStamp `xorm:"updated" json:"updatedUnix"` + StartTime timeutil.TimeStamp `json:"startTime"` + EndTime timeutil.TimeStamp `json:"endTime"` + UserName string `json:"userName"` + UserRelAvatarLink string `json:"userRelAvatarLink"` + IsCanOper bool `json:"isCanOper"` + IsCanDelete bool `json:"isCanDelete"` } type AiModelQueryOptions struct { diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 69de79c10..87d5b37f0 100755 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -953,6 +953,18 @@ func RegisterRoutes(m *macaron.Macaron) { }) }, reqRepoReader(models.UnitTypeCloudBrain)) m.Group("/modelmanage", func() { + m.Post("/create_new_model", repo.CreateNewModel) + m.Get("/show_model_api", repo.ShowModelManageApi) + m.Delete("/delete_model", repo.DeleteModel) + m.Get("/downloadall", repo.DownloadModel) + m.Get("/query_model_byId", repo.QueryModelById) + m.Get("/query_model_for_predict", repo.QueryModelListForPredict) + m.Get("/query_modelfile_for_predict", repo.QueryModelFileForPredict) + m.Get("/query_train_job", repo.QueryTrainJobList) + m.Get("/query_train_model", repo.QueryTrainModelList) + m.Get("/query_train_job_version", repo.QueryTrainJobVersionList) + m.Post("/create_model_convert", repo.CreateModelConvert) + m.Get("/show_model_convert_page") m.Get("/:id", repo.GetCloudbrainModelConvertTask) m.Get("/:id/log", repo.CloudbrainForModelConvertGetLog) m.Get("/:id/modelartlog", repo.TrainJobForModelConvertGetLog) diff --git a/routers/api/v1/repo/modelmanage.go b/routers/api/v1/repo/modelmanage.go new file mode 100644 index 000000000..2c1fd9f01 --- /dev/null +++ b/routers/api/v1/repo/modelmanage.go @@ -0,0 +1,106 @@ +package repo + +import ( + "net/http" + + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/storage" + routerRepo "code.gitea.io/gitea/routers/repo" +) + +type FileInfo struct { + FileName string `json:"fileName"` + ModTime string `json:"modTime"` + IsDir bool `json:"isDir"` + Size int64 `json:"size"` + ParenDir string `json:"parenDir"` + UUID string `json:"uuid"` +} + +func CreateNewModel(ctx *context.APIContext) { + log.Info("CreateNewModel by api.") + routerRepo.SaveModel(ctx.Context) +} + +func ShowModelManageApi(ctx *context.APIContext) { + log.Info("ShowModelManageApi by api.") + routerRepo.ShowModelPageInfo(ctx.Context) +} + +func DeleteModel(ctx *context.APIContext) { + log.Info("DeleteModel by api.") + routerRepo.DeleteModel(ctx.Context) +} + +func DownloadModel(ctx *context.APIContext) { + log.Info("DownloadModel by api.") + routerRepo.DownloadMultiModelFile(ctx.Context) +} + +func QueryModelById(ctx *context.APIContext) { + log.Info("QueryModelById by api.") + routerRepo.QueryModelById(ctx.Context) +} + +func QueryModelListForPredict(ctx *context.APIContext) { + log.Info("QueryModelListForPredict by api.") + routerRepo.QueryModelListForPredict(ctx.Context) +} + +func QueryTrainModelList(ctx *context.APIContext) { + result, err := routerRepo.QueryTrainModelFileById(ctx.Context) + if err != nil { + log.Info("query error." + err.Error()) + } + re := convertFileFormat(result) + ctx.JSON(http.StatusOK, re) +} + +func convertFileFormat(result []storage.FileInfo) []FileInfo { + re := make([]FileInfo, 0) + if result != nil { + for _, file := range result { + tmpFile := FileInfo{ + FileName: file.FileName, + ModTime: file.ModTime, + IsDir: file.IsDir, + Size: file.Size, + ParenDir: file.ParenDir, + UUID: file.UUID, + } + re = append(re, tmpFile) + } + } + return re +} + +func QueryModelFileForPredict(ctx *context.APIContext) { + log.Info("QueryModelFileForPredict by api.") + id := ctx.Query("id") + result := routerRepo.QueryModelFileByID(id) + re := convertFileFormat(result) + ctx.JSON(http.StatusOK, re) +} + +func CreateModelConvert(ctx *context.APIContext) { + log.Info("CreateModelConvert by api.") + routerRepo.SaveModelConvert(ctx.Context) +} + +func ShowModelConvertPage(ctx *context.APIContext) { + log.Info("ShowModelConvertPage by api.") + modelResult, count, err := routerRepo.GetModelConvertPageData(ctx.Context) + if err == nil { + mapInterface := make(map[string]interface{}) + mapInterface["data"] = modelResult + mapInterface["count"] = count + ctx.JSON(http.StatusOK, mapInterface) + } else { + mapInterface := make(map[string]interface{}) + mapInterface["data"] = nil + mapInterface["count"] = 0 + ctx.JSON(http.StatusOK, mapInterface) + } + +} diff --git a/routers/repo/ai_model_convert.go b/routers/repo/ai_model_convert.go index bd6a01072..560ace8fd 100644 --- a/routers/repo/ai_model_convert.go +++ b/routers/repo/ai_model_convert.go @@ -74,27 +74,27 @@ func SaveModelConvert(ctx *context.Context) { log.Info("save model convert start.") if !ctx.Repo.CanWrite(models.UnitTypeModelManage) { ctx.JSON(200, map[string]string{ - "result_code": "1", - "message": ctx.Tr("repo.modelconvert.manage.no_operate_right"), + "code": "1", + "msg": ctx.Tr("repo.modelconvert.manage.no_operate_right"), }) return } name := ctx.Query("name") desc := ctx.Query("desc") modelId := ctx.Query("modelId") - modelPath := ctx.Query("ModelFile") - SrcEngine := ctx.QueryInt("SrcEngine") + modelPath := ctx.Query("modelFile") + SrcEngine := ctx.QueryInt("srcEngine") InputShape := ctx.Query("inputshape") InputDataFormat := ctx.Query("inputdataformat") - DestFormat := ctx.QueryInt("DestFormat") - NetOutputFormat := ctx.QueryInt("NetOutputFormat") + DestFormat := ctx.QueryInt("destFormat") + NetOutputFormat := ctx.QueryInt("netOutputFormat") task, err := models.QueryModelById(modelId) if err != nil { log.Error("no such model!", err.Error()) ctx.JSON(200, map[string]string{ - "result_code": "1", - "message": ctx.Tr("repo.modelconvert.manage.model_not_exist"), + "code": "1", + "msg": ctx.Tr("repo.modelconvert.manage.model_not_exist"), }) return } @@ -105,8 +105,8 @@ func SaveModelConvert(ctx *context.Context) { if convert.Name == name { log.Info("convert.Name=" + name + " convert.id=" + convert.ID) ctx.JSON(200, map[string]string{ - "result_code": "1", - "message": ctx.Tr("repo.modelconvert.manage.create_error1"), + "code": "1", + "msg": ctx.Tr("repo.modelconvert.manage.create_error1"), }) return } @@ -119,8 +119,8 @@ func SaveModelConvert(ctx *context.Context) { if isRunningTask(convert.Status) { log.Info("convert.Status=" + convert.Status + " convert.id=" + convert.ID) ctx.JSON(200, map[string]string{ - "result_code": "1", - "message": ctx.Tr("repo.modelconvert.manage.create_error2"), + "code": "1", + "msg": ctx.Tr("repo.modelconvert.manage.create_error2"), }) return } @@ -150,7 +150,7 @@ func SaveModelConvert(ctx *context.Context) { go goCreateTask(modelConvert, ctx, task) ctx.JSON(200, map[string]string{ - "result_code": "0", + "code": "0", }) } @@ -604,11 +604,11 @@ func StopModelConvert(ctx *context.Context) { } func ShowModelConvertInfo(ctx *context.Context) { - ctx.Data["ID"] = ctx.Query("ID") + ctx.Data["ID"] = ctx.Query("id") ctx.Data["isModelManage"] = true ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage) - job, err := models.QueryModelConvertById(ctx.Query("ID")) + job, err := models.QueryModelConvertById(ctx.Query("id")) if err == nil { if job.TrainJobDuration == "" { job.TrainJobDuration = "00:00:00" @@ -715,6 +715,26 @@ func ShowModelConvertPageInfo(ctx *context.Context) { if pageSize <= 0 { pageSize = setting.UI.IssuePagingNum } + modelResult, count, err := GetModelConvertPageData(ctx) + if err == nil { + pager := context.NewPagination(int(count), page, pageSize, 5) + ctx.Data["Page"] = pager + ctx.Data["Tasks"] = modelResult + ctx.Data["MODEL_CONVERT_COUNT"] = count + } else { + ctx.ServerError("Query data error.", err) + } +} + +func GetModelConvertPageData(ctx *context.Context) ([]*models.AiModelConvert, int64, error) { + page := ctx.QueryInt("page") + if page <= 0 { + page = 1 + } + pageSize := ctx.QueryInt("pageSize") + if pageSize <= 0 { + pageSize = setting.UI.IssuePagingNum + } repoId := ctx.Repo.Repository.ID modelResult, count, err := models.QueryModelConvert(&models.AiModelQueryOptions{ ListOptions: models.ListOptions{ @@ -725,10 +745,8 @@ func ShowModelConvertPageInfo(ctx *context.Context) { }) if err != nil { log.Info("query db error." + err.Error()) - ctx.ServerError("Cloudbrain", err) - return + return nil, 0, err } - ctx.Data["MODEL_CONVERT_COUNT"] = count userIds := make([]int64, len(modelResult)) for i, model := range modelResult { model.IsCanOper = isOper(ctx, model.UserId) @@ -743,10 +761,7 @@ func ShowModelConvertPageInfo(ctx *context.Context) { model.UserRelAvatarLink = value.RelAvatarLink() } } - pager := context.NewPagination(int(count), page, pageSize, 5) - ctx.Data["Page"] = pager - ctx.Data["Tasks"] = modelResult - + return modelResult, count, nil } func ModelConvertDownloadModel(ctx *context.Context) { @@ -757,7 +772,7 @@ func ModelConvertDownloadModel(ctx *context.Context) { ctx.ServerError("Not found task.", err) return } - AllDownload := ctx.QueryBool("AllDownload") + AllDownload := ctx.QueryBool("allDownload") if AllDownload { if job.IsGpuTrainTask() { path := setting.CBCodePathPrefix + job.ID + "/model/" diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index 3545b090b..a82930909 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -17,7 +17,6 @@ import ( "code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" - "code.gitea.io/gitea/services/cloudbrain/resource" uuid "github.com/satori/go.uuid" ) @@ -34,13 +33,13 @@ const ( STATUS_ERROR = 2 ) -func saveModelByParameters(jobId string, versionName string, name string, version string, label string, description string, engine int, ctx *context.Context) error { +func saveModelByParameters(jobId string, versionName string, name string, version string, label string, description string, engine int, ctx *context.Context) (string, error) { aiTask, err := models.GetCloudbrainByJobIDAndVersionName(jobId, versionName) if err != nil { aiTask, err = models.GetRepoCloudBrainByJobID(ctx.Repo.Repository.ID, jobId) if err != nil { log.Info("query task error." + err.Error()) - return err + return "", err } else { log.Info("query gpu train task.") } @@ -56,7 +55,7 @@ func saveModelByParameters(jobId string, versionName string, name string, versio if len(aimodels) > 0 { for _, model := range aimodels { if model.Version == version { - return errors.New(ctx.Tr("repo.model.manage.create_error")) + return "", errors.New(ctx.Tr("repo.model.manage.create_error")) } if model.New == MODEL_LATEST { lastNewModelId = model.ID @@ -111,7 +110,7 @@ func saveModelByParameters(jobId string, versionName string, name string, versio err = models.SaveModelToDb(model) if err != nil { - return err + return "", err } if len(lastNewModelId) > 0 { //udpate status and version count @@ -134,7 +133,7 @@ func saveModelByParameters(jobId string, versionName string, name string, versio log.Info("save model end.") notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, id, name, models.ActionCreateNewModelTask) - return nil + return id, nil } func asyncToCopyModel(aiTask *models.Cloudbrain, id string, modelSelectedFile string) { @@ -173,7 +172,7 @@ func SaveNewNameModel(ctx *context.Context) { ctx.Error(403, ctx.Tr("repo.model_noright")) return } - name := ctx.Query("Name") + name := ctx.Query("name") if name == "" { ctx.Error(500, fmt.Sprintf("name or version is null.")) return @@ -203,38 +202,42 @@ func SaveModel(ctx *context.Context) { return } log.Info("save model start.") - JobId := ctx.Query("JobId") - VersionName := ctx.Query("VersionName") - name := ctx.Query("Name") - version := ctx.Query("Version") - label := ctx.Query("Label") - description := ctx.Query("Description") - engine := ctx.QueryInt("Engine") + JobId := ctx.Query("jobId") + VersionName := ctx.Query("versionName") + name := ctx.Query("name") + version := ctx.Query("version") + label := ctx.Query("label") + description := ctx.Query("description") + engine := ctx.QueryInt("engine") modelSelectedFile := ctx.Query("modelSelectedFile") log.Info("engine=" + fmt.Sprint(engine) + " modelSelectedFile=" + modelSelectedFile) - + re := map[string]string{ + "code": "-1", + } if JobId == "" || VersionName == "" { - ctx.Error(500, fmt.Sprintf("JobId or VersionName is null.")) + re["msg"] = "JobId or VersionName is null." + ctx.JSON(200, re) return } if modelSelectedFile == "" { - ctx.Error(500, fmt.Sprintf("Not selected model file.")) + re["msg"] = "Not selected model file." + ctx.JSON(200, re) return } - if name == "" || version == "" { - ctx.Error(500, fmt.Sprintf("name or version is null.")) + re["msg"] = "name or version is null." + ctx.JSON(200, re) return } - - err := saveModelByParameters(JobId, VersionName, name, version, label, description, engine, ctx) - + id, err := saveModelByParameters(JobId, VersionName, name, version, label, description, engine, ctx) if err != nil { log.Info("save model error." + err.Error()) - ctx.Error(500, fmt.Sprintf("save model error. %v", err)) - return + re["msg"] = err.Error() + } else { + re["code"] = "0" + re["id"] = id } - ctx.Status(200) + ctx.JSON(200, re) log.Info("save model end.") } @@ -299,13 +302,17 @@ func downloadModelFromCloudBrainOne(modelUUID string, jobName string, parentDir func DeleteModel(ctx *context.Context) { log.Info("delete model start.") - id := ctx.Query("ID") + id := ctx.Query("id") err := deleteModelByID(ctx, id) if err != nil { - ctx.JSON(500, err.Error()) + re := map[string]string{ + "code": "-1", + } + re["msg"] = err.Error() + ctx.JSON(200, re) } else { ctx.JSON(200, map[string]string{ - "result_code": "0", + "code": "0", }) } } @@ -362,7 +369,7 @@ func QueryModelByParameters(repoId int64, page int) ([]*models.AiModelManage, in func DownloadMultiModelFile(ctx *context.Context) { log.Info("DownloadMultiModelFile start.") - id := ctx.Query("ID") + id := ctx.Query("id") log.Info("id=" + id) task, err := models.QueryModelById(id) if err != nil { @@ -495,7 +502,10 @@ func downloadFromCloudBrainTwo(path string, task *models.AiModelManage, ctx *con func QueryTrainJobVersionList(ctx *context.Context) { log.Info("query train job version list. start.") - JobID := ctx.Query("JobID") + JobID := ctx.Query("jobId") + if JobID == "" { + JobID = ctx.Query("JobId") + } VersionListTasks, count, err := models.QueryModelTrainJobVersionList(JobID) @@ -523,20 +533,33 @@ func QueryTrainJobList(ctx *context.Context) { } -func QueryTrainModelList(ctx *context.Context) { - log.Info("query train job list. start.") - jobName := ctx.Query("jobName") - taskType := ctx.QueryInt("type") - VersionName := ctx.Query("VersionName") +func QueryTrainModelFileById(ctx *context.Context) ([]storage.FileInfo, error) { + JobID := ctx.Query("jobId") + VersionListTasks, count, err := models.QueryModelTrainJobVersionList(JobID) + if err == nil { + if count == 1 { + task := VersionListTasks[0] + jobName := task.JobName + taskType := task.Type + VersionName := task.VersionName + modelDbResult, err := getModelFromObjectSave(jobName, taskType, VersionName) + return modelDbResult, err + } + } + log.Info("get TypeCloudBrainTwo TrainJobListModel failed:", err) + return nil, errors.New("Not found task.") +} + +func getModelFromObjectSave(jobName string, taskType int, VersionName string) ([]storage.FileInfo, error) { if taskType == models.TypeCloudBrainTwo { objectkey := path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, VersionName) + "/" modelDbResult, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, objectkey) log.Info("bucket=" + setting.Bucket + " objectkey=" + objectkey) if err != nil { log.Info("get TypeCloudBrainTwo TrainJobListModel failed:", err) + return nil, err } else { - ctx.JSON(200, modelDbResult) - return + return modelDbResult, nil } } else if taskType == models.TypeCloudBrainOne { modelSrcPrefix := setting.CBCodePathPrefix + jobName + "/model/" @@ -544,12 +567,30 @@ func QueryTrainModelList(ctx *context.Context) { modelDbResult, err := storage.GetAllObjectByBucketAndPrefixMinio(bucketName, modelSrcPrefix) if err != nil { log.Info("get TypeCloudBrainOne TrainJobListModel failed:", err) + return nil, err } else { - ctx.JSON(200, modelDbResult) - return + return modelDbResult, nil } } - ctx.JSON(200, "") + return nil, errors.New("Not support.") +} + +func QueryTrainModelList(ctx *context.Context) { + log.Info("query train job list. start.") + jobName := ctx.Query("jobName") + taskType := ctx.QueryInt("type") + VersionName := ctx.Query("versionName") + if VersionName == "" { + VersionName = ctx.Query("VersionName") + } + modelDbResult, err := getModelFromObjectSave(jobName, taskType, VersionName) + if err != nil { + log.Info("get TypeCloudBrainTwo TrainJobListModel failed:", err) + ctx.JSON(200, "") + } else { + ctx.JSON(200, modelDbResult) + return + } } func DownloadSingleModelFile(ctx *context.Context) { @@ -620,7 +661,7 @@ func DownloadSingleModelFile(ctx *context.Context) { } func ShowModelInfo(ctx *context.Context) { - ctx.Data["ID"] = ctx.Query("ID") + ctx.Data["ID"] = ctx.Query("id") ctx.Data["name"] = ctx.Query("name") ctx.Data["isModelManage"] = true ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage) @@ -628,6 +669,19 @@ func ShowModelInfo(ctx *context.Context) { ctx.HTML(200, tplModelInfo) } +func QueryModelById(ctx *context.Context) { + id := ctx.Query("id") + model, err := models.QueryModelById(id) + if err == nil { + model.IsCanOper = isOper(ctx, model.UserId) + model.IsCanDelete = isCanDelete(ctx, model.UserId) + removeIpInfo(model) + ctx.JSON(http.StatusOK, model) + } else { + ctx.JSON(http.StatusNotFound, nil) + } +} + func ShowSingleModel(ctx *context.Context) { name := ctx.Query("name") @@ -836,8 +890,8 @@ func ModifyModel(id string, description string) error { func ModifyModelInfo(ctx *context.Context) { log.Info("modify model start.") - id := ctx.Query("ID") - description := ctx.Query("Description") + id := ctx.Query("id") + description := ctx.Query("description") task, err := models.QueryModelById(id) if err != nil { @@ -902,28 +956,36 @@ func QueryModelListForPredict(ctx *context.Context) { } func QueryModelFileForPredict(ctx *context.Context) { - id := ctx.Query("ID") + id := ctx.Query("id") + if id == "" { + id = ctx.Query("ID") + } + ctx.JSON(http.StatusOK, QueryModelFileByID(id)) +} + +func QueryModelFileByID(id string) []storage.FileInfo { model, err := models.QueryModelById(id) if err == nil { if model.Type == models.TypeCloudBrainTwo { prefix := model.Path[len(setting.Bucket)+1:] fileinfos, _ := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, prefix) - ctx.JSON(http.StatusOK, fileinfos) + return fileinfos } else if model.Type == models.TypeCloudBrainOne { prefix := model.Path[len(setting.Attachment.Minio.Bucket)+1:] fileinfos, _ := storage.GetAllObjectByBucketAndPrefixMinio(setting.Attachment.Minio.Bucket, prefix) - ctx.JSON(http.StatusOK, fileinfos) + return fileinfos } } else { log.Error("no such model!", err.Error()) - ctx.ServerError("no such model:", err) - return } - + return nil } func QueryOneLevelModelFile(ctx *context.Context) { - id := ctx.Query("ID") + id := ctx.Query("id") + if id == "" { + id = ctx.Query("ID") + } parentDir := ctx.Query("parentDir") model, err := models.QueryModelById(id) if err != nil { diff --git a/templates/repo/cloudbrain/inference/new.tmpl b/templates/repo/cloudbrain/inference/new.tmpl index df737f995..f2b389393 100644 --- a/templates/repo/cloudbrain/inference/new.tmpl +++ b/templates/repo/cloudbrain/inference/new.tmpl @@ -331,9 +331,7 @@ $('#model_name_version').empty() let html = '' nameMap[value].forEach(element => { - let {TrainTaskInfo} = element - TrainTaskInfo = JSON.parse(TrainTaskInfo) - html += `
${element.Version}
` + html += `
${element.version}
` }); $('#model_name_version').append(html) $("#select_model_version").removeClass("loading") @@ -387,7 +385,7 @@ } function loadCheckpointList(value){ return new Promise((resolve,reject)=>{ - $.get(`${RepoLink}/modelmanage/query_modelfile_for_predict`,{ID:value}, (data) => { + $.get(`${RepoLink}/modelmanage/query_modelfile_for_predict`,{id:value}, (data) => { resolve(data) }) }) diff --git a/templates/repo/cloudbrain/trainjob/show.tmpl b/templates/repo/cloudbrain/trainjob/show.tmpl index 44ac57319..2e4d5689b 100644 --- a/templates/repo/cloudbrain/trainjob/show.tmpl +++ b/templates/repo/cloudbrain/trainjob/show.tmpl @@ -633,24 +633,24 @@
- - + +
-
- +
@@ -364,9 +364,9 @@ $("#task_name").removeClass("error") } - data['desc']= $('#Description').val() - data['modelId'] = $('#ModelVersion').val() - data['SrcEngine'] = $('#SrcEngine').val(); + data['desc']= $('#description').val() + data['modelId'] = $('#modelVersion').val() + data['srcEngine'] = $('#srcEngine').val(); data['inputshape']= $('#inputshape').val(); if(inputshapeNotValid(data['inputshape'])){ @@ -379,10 +379,10 @@ } data['inputdataformat']= $('#inputdataformat').val(); - data['DestFormat'] = $('#DestFormat').val(); - data['NetOutputFormat']= $('#NetOutputFormat').val(); - data['ModelFile'] = $('#ModelFile').val(); - if(data['ModelFile']==""){ + data['destFormat'] = $('#destFormat').val(); + data['netOutputFormat']= $('#netOutputFormat').val(); + data['modelFile'] = $('#modelFile').val(); + if(data['modelFile']==""){ $('.ui.error.message').text("{{.i18n.Tr "repo.modelconvert.modelfileempty"}}") $('.ui.error.message').css('display','block') $("#ModelFile_Div").addClass("error") @@ -392,11 +392,11 @@ } $.post(`${repolink}/modelmanage/create_model_convert`,data,(result) => { console.log("result=" + result); - if(result.result_code ==0){ + if(result.code ==0){ $('.ui.modal.second').modal('hide'); window.location.reload(); }else{ - $('.ui.error.message').text(result.message) + $('.ui.error.message').text(result.msg) $('.ui.error.message').css('display','block') } }) @@ -456,7 +456,7 @@ $('#choice_version').dropdown({ onChange:function(value){ console.log("model version:" + value); - $('#choice_version input[name="ModelVersion"]').val(value) + $('#choice_version input[name="modelVersion"]').val(value) loadModelFile(value); } }) @@ -464,26 +464,26 @@ $('#choice_file').dropdown({ onChange:function(value){ console.log("model file:" + value); - $('#choice_file input[name="ModelFile"]').val(value) + $('#choice_file input[name="modelFile"]').val(value) } }) }) function srcEngineChanged(){ - var ele = window.document.getElementById("SrcEngine"); + var ele = window.document.getElementById("srcEngine"); var index=ele.selectedIndex; var options=ele.options; var option = options[index]; - console.log("SrcEngine value=" + option); + console.log("srcEngine value=" + option); let destFormatHtml = ""; let netOutputFormatHtml = ""; if(option==null || option =="undefined" || option.value == 0){ destFormatHtml += "" netOutputFormatHtml += ""; } - $('#DestFormat').html(destFormatHtml); - $('#NetOutputFormat').html(netOutputFormatHtml); + $('#destFormat').html(destFormatHtml); + $('#netOutputFormat').html(netOutputFormatHtml); } function loadModelList(){ @@ -509,7 +509,7 @@ if(modelId ==null || modelId ==""){ console.log("modelId is null"); }else{ - $.get(`${repolink}/modelmanage/query_modelfile_for_predict?ID=${modelId}`, (data) => { + $.get(`${repolink}/modelmanage/query_modelfile_for_predict?id=${modelId}`, (data) => { const n_length = data.length let file_html='' let firstFileName ='' @@ -526,7 +526,7 @@ } $("#model-file").append(file_html) $('#choice_file .default.text').text(firstFileName) - $('#choice_file input[name="ModelFile"]').val(firstFileName) + $('#choice_file input[name="modelFile"]').val(firstFileName) }) } @@ -550,19 +550,19 @@ n_length = versionList.length let train_html='' for (let i=0;i${versionList[i].Version}
` + train_html += `
${versionList[i].version}
` train_html += '
' } $("#model-version").append(train_html) - $('#choice_version .default.text').text(versionList[0].Version) - $('#choice_version input[name="ModelVersion"]').val(versionList[0].ID) - loadModelFile(versionList[0].ID); + $('#choice_version .default.text').text(versionList[0].version) + $('#choice_version input[name="modelVersion"]').val(versionList[0].id) + loadModelFile(versionList[0].id); } setEngineValue(value); } function setEngineValue(value){ - $('#SrcEngine').dropdown('clear'); + $('#srcEngine').dropdown('clear'); console.log("setEngineValue value=" + value); let html = "" html +=""; @@ -580,13 +580,13 @@ let nameMap = modelData.nameMap let versionList = nameMap[modelName] if(versionList != null && versionList.length >0){ - if(versionList[0].Engine == engineOption){ + if(versionList[0].engine == engineOption){ return "selected=\"selected\""; }else{ - if((versionList[0].Engine==122 || versionList[0].Engine==37) && engineOption==2){ + if((versionList[0].engine==122 || versionList[0].engine==37) && engineOption==2){ return "selected=\"selected\""; } - if((versionList[0].Engine==121 || versionList[0].Engine==38) && engineOption==1){ + if((versionList[0].engine==121 || versionList[0].engine==38) && engineOption==1){ return "selected=\"selected\""; } } diff --git a/templates/repo/modelmanage/index.tmpl b/templates/repo/modelmanage/index.tmpl index 062e1908f..2699bed01 100644 --- a/templates/repo/modelmanage/index.tmpl +++ b/templates/repo/modelmanage/index.tmpl @@ -138,20 +138,20 @@
- +
- +   - {{template "base/footer" .}} + + + diff --git a/templates/repo/modelmanage/index.tmpl b/templates/repo/modelmanage/index.tmpl index 2cced090f..7f21e4053 100644 --- a/templates/repo/modelmanage/index.tmpl +++ b/templates/repo/modelmanage/index.tmpl @@ -77,7 +77,7 @@ 导入本地模型 导入线上模型 + href="{{.RepoLink}}/modelmanage/create_online_model_tmpl">导入线上模型
{{if eq $.MODEL_COUNT 0}} diff --git a/web_src/vuepages/pages/modelmanage/common/modelmanage-common-detail.vue b/web_src/vuepages/pages/modelmanage/common/modelmanage-common-detail.vue index 997722807..1aff6d33f 100644 --- a/web_src/vuepages/pages/modelmanage/common/modelmanage-common-detail.vue +++ b/web_src/vuepages/pages/modelmanage/common/modelmanage-common-detail.vue @@ -21,8 +21,8 @@
可用集群:
-
- {{ state.type == 0 ? 'CPU/GPU' : 'NPU' }} +
+ {{ state.typeStr }}
@@ -32,10 +32,22 @@
{{ state.modelSize }}
-
+
描述:
-
-
{{ state.description }}
+
+
+ {{ state.description }} + +
+
+ + + +
@@ -52,10 +64,22 @@
{{ state.createTime }}
-
+
标签:
-
-
{{ state.label }}
+
+
+ {{ state.label }} + +
+
+ + + +
@@ -66,13 +90,13 @@
训练任务:
-
{{ state.displayJobName }}
+
代码分支:
-
{{ state.branchName }}
+
@@ -192,6 +216,10 @@ export default { label: '', description: '', }, + editDescr: '', + isEidtDescr: false, + editLabel: '', + isEidtLabel: false, engineList: MODEL_ENGINES, curVersion: '', modelList: [], @@ -205,6 +233,7 @@ export default { this.modelType = data.modelType; this.canOperate = data.isCanOper; this.state.type = data.type; + this.state.typeStr = data.type == 0 ? 'CPU/GPU' : data.type == 1 ? 'NPU' : ''; this.state.id = data.id; this.state.name = data.name; this.state.version = data.version; @@ -212,7 +241,9 @@ export default { this.state.engineName = getListValueWithKey(MODEL_ENGINES, data.engine.toString()); this.state.modelSize = transFileSize(data.size); this.state.label = data.label || '--'; + this.state._label = data.label; this.state.description = data.description || '--'; + this.state._description = data.description; this.state.createTime = formatDate(new Date(data.createdUnix * 1000), 'yyyy-MM-dd HH:mm:ss'); const trainTaskInfo = data.trainTaskInfo ? JSON.parse(data.trainTaskInfo) : ''; @@ -228,14 +259,27 @@ export default { if (trainTaskInfo) { const parameters = trainTaskInfo.Parameters ? JSON.parse(trainTaskInfo.Parameters).parameter : []; const parametersStr = parameters.map((item) => { return item.label + '=' + item.value }).join('; '); + const taskType = trainTaskInfo.Type; + let taskUrl = location.href.split('modelmanage')[0]; + if (taskType == 0) { + taskUrl = taskUrl + 'cloudbrain/train-job/' + trainTaskInfo.JobID; + } else if (taskType == 1) { + taskUrl = taskUrl + 'modelarts/train-job/' + trainTaskInfo.JobID; + } else if (taskType == 2) { + taskUrl = taskUrl + 'grampus/train-job/' + trainTaskInfo.JobID; + } + const versionName = trainTaskInfo.VersionName; + const versionHtml = versionName ? `${versionName}` : ''; + const codeCommitID = data.codeCommitID; + const codeCommitIDHtml = codeCommitID ? `${codeCommitID}` : ''; Object.assign(this.state, { - displayJobName: trainTaskInfo.DisplayJobName, - branchName: trainTaskInfo.BranchName, + displayJobName: `${trainTaskInfo.DisplayJobName}${versionHtml}`, + branchName: `${trainTaskInfo.BranchName}${codeCommitIDHtml}`, bootFile: trainTaskInfo.BootFile, datasetName: trainTaskInfo.DatasetName, parameters: parametersStr || '--', workServerNumber: trainTaskInfo.WorkServerNumber || '--', - specStr: trainTaskInfo.Spec ? trainTaskInfo.Spec.toString() : '--' + specStr: trainTaskInfo.FlavorName || '--', }); } this.curVersion = version; @@ -256,6 +300,43 @@ export default { goUploadPage() { window.location.href = `${this.repo}/modelmanage/create_local_model_tmpl2?type=0&name=${this.state.name}&id=${this.state.id}`; }, + submitEidt(type) { + const obj = { + repo: this.repo, + type: this.state.type, + id: this.state.id, + name: this.state.name, + version: this.state.version, + engine: this.state.engine, + label: type == 'label' ? this.editLabel : this.state.label, + description: type == 'descr' ? this.editDescr : this.state.description, + }; + modifyModel(obj).then(res => { + res = res.data; + if (res && res.code == '0') { + if (type == 'label') { + this.state.label = this.editLabel; + this.state._label = this.editLabel; + this.isEidtLabel = false; + } else if (type == 'descr') { + this.state.description = this.editDescr; + this.state._description = this.editDescr; + this.isEidtDescr = false; + } + } else { + this.$message({ + type: 'error', + message: '信息修改失败', + }); + } + }).catch(err => { + console.log(err); + this.$message({ + type: 'error', + message: '信息修改失败', + }); + }); + }, deleteFile(file) { this.$confirm('请确认是否删除当前模型文件?', this.$t('tips'), { confirmButtonText: this.$t('confirm1'), @@ -350,8 +431,12 @@ export default { .row { display: flex; height: 32px; - align-items: center; margin-bottom: 4px; + align-items: center; + + &.edit-row { + height: unset; + } .tit { width: 160px; @@ -365,14 +450,30 @@ export default { position: relative; height: 20px; + &.edit-val { + height: unset; + } + .txt-wrap { position: absolute; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; width: 100%; + + /deep/.append-txt { + margin-left: 6px; + background-color: gainsboro; + padding: 2px; + border-radius: 2px; + font-size: 12px; + } } } + + .txt-edit { + padding-right: 20px; + } } } } @@ -466,9 +567,13 @@ export default { } } -/deep/ .el-input__inner { - font-weight: 600; +.el-select { + /deep/ .el-input__inner { + font-weight: 600; + } +} +/deep/ .el-input__inner { &:focus { border-color: #85b7d9; } From 208a99809fb830d1a29e0074bd713623f3c313c7 Mon Sep 17 00:00:00 2001 From: chenyifan01 Date: Wed, 9 Nov 2022 15:36:01 +0800 Subject: [PATCH 037/106] Revert "#3157" This reverts commit 3aca1dc0749ccbe1af32063a2a621fe721f6bb01. --- routers/api/v1/repo/cloudbrain.go | 23 ++++------------------- routers/api/v1/repo/modelarts.go | 22 +++++----------------- routers/repo/grampus.go | 12 ++---------- 3 files changed, 11 insertions(+), 46 deletions(-) diff --git a/routers/api/v1/repo/cloudbrain.go b/routers/api/v1/repo/cloudbrain.go index 9da1251e4..7022dc011 100755 --- a/routers/api/v1/repo/cloudbrain.go +++ b/routers/api/v1/repo/cloudbrain.go @@ -607,24 +607,6 @@ func CloudbrainGetLog(ctx *context.APIContext) { lines := ctx.QueryInt("lines") baseLine := ctx.Query("base_line") order := ctx.Query("order") - - //Logs can only be downloaded if the file exists - //and the current user is an administrator or the creator of the task - if !job.IsUserHasRight(ctx.User) { - re := map[string]interface{}{ - "JobID": ID, - "LogFileName": "", - "StartLine": 0, - "EndLine": 0, - "Content": "", - "Lines": 0, - "CanLogDownload": false, - "StartTime": job.StartTime, - } - ctx.JSON(http.StatusOK, re) - return - } - var result map[string]interface{} resultPath := "/model" if job.JobType == string(models.JobTypeInference) || job.JobType == string(models.JobTypeModelSafety) { @@ -668,7 +650,10 @@ func CloudbrainGetLog(ctx *context.APIContext) { content = content + ctx.Data["existStr"].(string) } logFileName := result["FileName"] - canLogDownload := logFileName != nil && logFileName != "" + + //Logs can only be downloaded if the file exists + //and the current user is an administrator or the creator of the task + canLogDownload := logFileName != nil && logFileName != "" && job.IsUserHasRight(ctx.User) re := map[string]interface{}{ "JobID": ID, diff --git a/routers/api/v1/repo/modelarts.go b/routers/api/v1/repo/modelarts.go index 00cdea0ef..16e4997a3 100755 --- a/routers/api/v1/repo/modelarts.go +++ b/routers/api/v1/repo/modelarts.go @@ -274,21 +274,6 @@ func TrainJobGetLog(ctx *context.APIContext) { log.Error("GetCloudbrainByJobID(%s) failed:%v", jobID, err.Error()) return } - - if !task.IsUserHasRight(ctx.User) { - ctx.JSON(http.StatusOK, map[string]interface{}{ - "JobID": jobID, - "LogFileName": "", - "StartLine": 0, - "EndLine": 0, - "Content": "", - "Lines": 0, - "CanLogDownload": false, - "StartTime": task.StartTime, - }) - return - } - resultLogFile, result, err := trainJobGetLogContent(jobID, task.VersionID, baseLine, order, lines_int) if err != nil { log.Error("trainJobGetLog(%s) failed:%v", jobID, err.Error()) @@ -305,12 +290,15 @@ func TrainJobGetLog(ctx *context.APIContext) { "EndLine": result.EndLine, "Content": result.Content, "Lines": result.Lines, - "CanLogDownload": canLogDownload(task), + "CanLogDownload": canLogDownload(ctx.User, task), "StartTime": task.StartTime, }) } -func canLogDownload(task *models.Cloudbrain) bool { +func canLogDownload(user *models.User, task *models.Cloudbrain) bool { + if task == nil || !task.IsUserHasRight(user) { + return false + } prefix := strings.TrimPrefix(path.Join(setting.TrainJobModelPath, task.JobName, modelarts.LogPath, task.VersionName), "/") + "/job" _, err := storage.GetObsLogFileName(prefix) if err != nil { diff --git a/routers/repo/grampus.go b/routers/repo/grampus.go index a2a021a43..e16d39a00 100755 --- a/routers/repo/grampus.go +++ b/routers/repo/grampus.go @@ -935,25 +935,17 @@ func GrampusGetLog(ctx *context.Context) { return } - if !job.IsUserHasRight(ctx.User) { - ctx.JSON(http.StatusOK, map[string]interface{}{ - "JobName": job.JobName, - "Content": "", - "CanLogDownload": false, - }) - return - } - content, err := grampus.GetTrainJobLog(job.JobID) if err != nil { log.Error("GetTrainJobLog failed: %v", err, ctx.Data["MsgID"]) ctx.ServerError(err.Error(), err) return } + canLogDownload := err == nil && job.IsUserHasRight(ctx.User) ctx.JSON(http.StatusOK, map[string]interface{}{ "JobName": job.JobName, "Content": content, - "CanLogDownload": true, + "CanLogDownload": canLogDownload, }) return From ce24e32f900caba3844bbe2fc37bdf21dc4fc44a Mon Sep 17 00:00:00 2001 From: chenyifan01 Date: Wed, 9 Nov 2022 17:07:11 +0800 Subject: [PATCH 038/106] #3157 fix bug --- routers/repo/grampus.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/routers/repo/grampus.go b/routers/repo/grampus.go index e16d39a00..aa3b7ef78 100755 --- a/routers/repo/grampus.go +++ b/routers/repo/grampus.go @@ -938,7 +938,11 @@ func GrampusGetLog(ctx *context.Context) { content, err := grampus.GetTrainJobLog(job.JobID) if err != nil { log.Error("GetTrainJobLog failed: %v", err, ctx.Data["MsgID"]) - ctx.ServerError(err.Error(), err) + ctx.JSON(http.StatusOK, map[string]interface{}{ + "JobName": job.JobName, + "Content": "", + "CanLogDownload": false, + }) return } canLogDownload := err == nil && job.IsUserHasRight(ctx.User) From bedb6e63eaf32a527aa7ad2f37820c82a6d7c427 Mon Sep 17 00:00:00 2001 From: ychao_1983 Date: Thu, 10 Nov 2022 10:52:42 +0800 Subject: [PATCH 039/106] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20'services/cloudbra?= =?UTF-8?q?in/cloudbrainTask/sync=5Fstatus.go'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- services/cloudbrain/cloudbrainTask/sync_status.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/cloudbrain/cloudbrainTask/sync_status.go b/services/cloudbrain/cloudbrainTask/sync_status.go index 7153a7ec0..67dc4d3b7 100644 --- a/services/cloudbrain/cloudbrainTask/sync_status.go +++ b/services/cloudbrain/cloudbrainTask/sync_status.go @@ -14,7 +14,7 @@ import ( var noteBookOKMap = make(map[int64]int, 20) //if a task notebook url can get two times, the notebook can browser. -const successfulCount = 2 +const successfulCount = 3 func SyncCloudBrainOneStatus(task *models.Cloudbrain) (*models.Cloudbrain, error) { jobResult, err := cloudbrain.GetJob(task.JobID) From 9a07c96e53580f5d3e0b1611c0f33cdbdc932804 Mon Sep 17 00:00:00 2001 From: chenshihai Date: Thu, 10 Nov 2022 13:08:22 +0800 Subject: [PATCH 040/106] update --- options/locale/locale_en-US.ini | 4 +- options/locale/locale_zh-CN.ini | 4 +- templates/repo/modelmanage/create_online.tmpl | 24 ++-- templates/repo/modelmanage/index.tmpl | 7 +- web_src/js/components/Model.vue | 4 +- web_src/js/components/basic/editDialog.vue | 2 +- web_src/js/features/i18nVue.js | 6 + web_src/js/index.js | 12 +- web_src/vuepages/langs/config/en-US.js | 60 ++++++++ web_src/vuepages/langs/config/zh-CN.js | 60 ++++++++ .../common/modelmanage-common-detail.vue | 90 +++++++----- .../local/modelmanage-local-create-1.vue | 55 +++++--- .../local/modelmanage-local-create-2.vue | 152 +++++++++++---------- 13 files changed, 331 insertions(+), 149 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 955690800..7eac45622 100755 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1266,11 +1266,13 @@ model.manage.model_accuracy = Model Accuracy model.convert=Model Transformation model.list=Model List model.manage.create_new_convert_task=Create Model Transformation Task - +model.manage.import_local_model=Import Local Model +model.manage.import_online_model=Import Online Model model.manage.notcreatemodel=No model has been created model.manage.init1=Code version: You have not initialized the code repository, please model.manage.init2=initialized first ; model.manage.createtrainjob_tip=Training task: you haven't created a training task, please create it first +model.manage.createmodel_tip=You can import local model or online model. Import online model should create model.manage.createtrainjob=Training task. model.manage.delete=Delete Model model.manage.delete_confirm=Are you sure to delete this model? Once this model is deleted, it cannot be restored. diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 63ff87345..afcc50436 100755 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -1281,11 +1281,13 @@ model.manage.model_accuracy = 模型精度 model.convert=模型转换任务 model.list=模型列表 model.manage.create_new_convert_task=创建模型转换任务 - +model.manage.import_local_model=导入本地模型 +model.manage.import_online_model=导入线上模型 model.manage.notcreatemodel=未创建过模型 model.manage.init1=代码版本:您还没有初始化代码仓库,请先 model.manage.init2=创建代码版本; model.manage.createtrainjob_tip=训练任务:您还没创建过训练任务,请先创建 +model.manage.createmodel_tip=您可以导入本地模型或者导入线上模型。导入线上模型需先 model.manage.createtrainjob=训练任务。 model.manage.delete=删除模型 model.manage.delete_confirm=你确认删除该模型么?此模型一旦删除不可恢复。 diff --git a/templates/repo/modelmanage/create_online.tmpl b/templates/repo/modelmanage/create_online.tmpl index db3ca6cf9..f3334a98a 100644 --- a/templates/repo/modelmanage/create_online.tmpl +++ b/templates/repo/modelmanage/create_online.tmpl @@ -56,7 +56,7 @@
-

+

{{.i18n.Tr "repo.model.manage.import_online_model"}}

@@ -95,7 +95,7 @@
-
+ -
-
- -
+
-
- +
+ +
@@ -253,8 +251,7 @@ $('.ui.modal.second') .modal({ centered: false, - onShow: function () { - $('#model_header').text({{.i18n.Tr "repo.model.manage.import_new_model"}}) + onShow: function () { $('input[name="version"]').addClass('model_disabled') $('.ui.dimmer').css({ "background-color": "rgb(136, 136, 136,0.7)" }) $("#job-name").empty() @@ -277,7 +274,6 @@ .modal('show') } */ - $('#model_header').text({{.i18n.Tr "repo.model.manage.import_new_model"}}) $('input[name="version"]').addClass('model_disabled') $('.ui.dimmer').css({ "background-color": "rgb(136, 136, 136,0.7)" }) $("#job-name").empty() diff --git a/templates/repo/modelmanage/index.tmpl b/templates/repo/modelmanage/index.tmpl index 7f21e4053..1befa48ee 100644 --- a/templates/repo/modelmanage/index.tmpl +++ b/templates/repo/modelmanage/index.tmpl @@ -75,9 +75,9 @@
导入本地模型 + href="{{.RepoLink}}/modelmanage/create_local_model_tmpl1">{{$.i18n.Tr "repo.model.manage.import_local_model"}} 导入线上模型 + href="{{.RepoLink}}/modelmanage/create_online_model_tmpl">{{$.i18n.Tr "repo.model.manage.import_online_model"}}
{{if eq $.MODEL_COUNT 0}} @@ -85,6 +85,7 @@
{{$.i18n.Tr "repo.model.manage.notcreatemodel"}}
+ +
{{$.i18n.Tr "repo.model.manage.createmodel_tip"}} {{$.i18n.Tr "repo.model.manage.createtrainjob"}}
{{$.i18n.Tr "repo.platform_instructions1"}} {{$.i18n.Tr "repo.platform_instructions2"}} {{$.i18n.Tr "repo.platform_instructions3"}}
diff --git a/web_src/js/components/Model.vue b/web_src/js/components/Model.vue index 62fca9b91..2a179878b 100644 --- a/web_src/js/components/Model.vue +++ b/web_src/js/components/Model.vue @@ -23,7 +23,7 @@ - {{ scope.row.modelType == '1' ? '本地' : '线上' }} + {{ scope.row.modelType == '1' ? i18n.local : i18n.online }} {{ '修改' }}{{ i18n.modify }} - +
diff --git a/web_src/js/features/i18nVue.js b/web_src/js/features/i18nVue.js index f6d5a6411..2983b3dc1 100644 --- a/web_src/js/features/i18nVue.js +++ b/web_src/js/features/i18nVue.js @@ -105,6 +105,9 @@ export const i18nVue = { file_sync_fail:"文件同步失败", no_file_to_download:"没有文件可以下载", task_not_finished:"任务还未结束,稍后再来看看", + local:"本地", + online:"线上", + modify:"修改", }, US: { computer_vision: "computer vision", @@ -216,5 +219,8 @@ export const i18nVue = { file_sync_fail:"File synchronization failed", no_file_to_download:"No files can be downloaded", task_not_finished:"Task not finished yet, please wait", + local:"Local", + online:"Online", + modify:"Modify", }, }; diff --git a/web_src/js/index.js b/web_src/js/index.js index a781261a9..5b40d829e 100755 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -6,8 +6,10 @@ import "./publicpath.js"; import "./polyfills.js"; import "./features/letteravatar.js"; import Vue from "vue"; -import ElementUI from "element-ui"; import "element-ui/lib/theme-chalk/index.css"; +import localeEn from 'element-ui/lib/locale/lang/en'; +import localeZh from 'element-ui/lib/locale/lang/zh-CN'; +import ElementUI from "element-ui"; import axios from "axios"; import qs from "qs"; import Cookies from "js-cookie"; @@ -54,15 +56,19 @@ import { Message } from "element-ui"; import { i18nVue } from "./features/i18nVue.js"; import './features/ad.js'; -Vue.use(ElementUI); Vue.prototype.$axios = axios; Vue.prototype.$Cookies = Cookies; Vue.prototype.qs = qs; Vue.prototype.$message = Message; Vue.prototype.$locale = i18nVue; -window.i18n = i18nVue[document.querySelector('html').getAttribute('lang') == 'zh-CN' ? 'CN' : 'US']; +const lang = document.querySelector('html').getAttribute('lang'); +window.i18n = i18nVue[lang == 'zh-CN' ? 'CN' : 'US']; const { AppSubUrl, StaticUrlPrefix, csrf } = window.config; +Vue.use(ElementUI, { + locale: lang === 'zh-CN' ? localeZh : localeEn, +}); + Object.defineProperty(Vue.prototype, "$echarts", { value: echarts, }); diff --git a/web_src/vuepages/langs/config/en-US.js b/web_src/vuepages/langs/config/en-US.js index bcd1cfe43..1c160ee1d 100644 --- a/web_src/vuepages/langs/config/en-US.js +++ b/web_src/vuepages/langs/config/en-US.js @@ -193,6 +193,66 @@ const en = { dataDesensitizationModelDesc:'Use AI technology to desensitize the face and license plate number in the picture. For more information about this model, please visit the project', limitFilesUpload:'Only jpg/jpeg/png files can be uploaded', limitSizeUpload:'The size of the uploaded file cannot exceed 20M!', + modelManage: { + modelManage: 'Model management', + modelName: 'Model name', + useCluster: 'Available clusters', + local: 'Local', + online: 'Online', + createModel: 'Create Model', + importLocalModel: 'Import Lacal Model', + importOnlineModel: 'Import Online Model', + modifyModelInfo: 'Modify model information', + addModelFiles: 'Add model files', + uploadModelFiles: 'Upload model files', + pleaseInputModelName: 'Please input model name', + version: 'Version', + modelEngine: 'Model engine', + modelLabel: 'Model label', + modelLabelInputTips: 'Input labels, multiple labels are separated by spaces', + modelDescr: 'Model description', + modelDescrInputTips: 'The description should not exceed 256 characters', + confirm: 'Confirm', + cancel: 'Cancel', + modelCreateFailed: 'Model create failed', + modelModifyFailed: 'Model modify failed', + fileUpload: 'File upload', + upload: 'Upload', + uploadStatus: 'Upload status', + modelFileUploadDefaultTips: 'Click to add files or drag files here directly', + modelFileUploadErrTips: 'Up to 10 files can be uploaded at a time, and the total file size of the model does not exceed 200GB', + fileIstoBig: 'File is to big', + removeFile: 'Rmove file', + uploadSuccess: 'upload success', + uploadFailed: 'upload failed', + calcFileMd5: 'Calculating file MD5...', + uploading: 'Uploading...', + fileHasAlreadyInTheModel: 'This file has already in the model: ', + basicInfo: 'Basic information', + modelSize: 'Model size', + descr: 'Description', + createTime: 'Create Time', + label: 'Label', + trainTaskInfo: 'Train task information', + trainTask: 'Train task', + codeBranch: 'Code branch', + bootFile: 'Boot file', + trainDataset: 'Train dataset', + specInfo: 'Specifications', + workServerNumber: 'Amount of compute node', + runParameters: 'Run parameters', + seeMore: 'See more', + collapseDetails: 'Collapse details', + modelFilesList: 'Mode files list', + fileName: 'File name', + fileSize: 'File size', + updateTime: 'Upate Time', + operate: 'Operation', + delete: 'Delete', + infoModificationFailed: 'Information modify failed', + deleteModelFileConfirmTips: 'Are you sure you want to delete the current model file?', + modelFileDeleteFailed: 'Model file delete failed', + }, } export default en; diff --git a/web_src/vuepages/langs/config/zh-CN.js b/web_src/vuepages/langs/config/zh-CN.js index 5b8e800d8..2f87c7e15 100644 --- a/web_src/vuepages/langs/config/zh-CN.js +++ b/web_src/vuepages/langs/config/zh-CN.js @@ -193,6 +193,66 @@ const zh = { dataDesensitizationModelDesc:'利用人工智能AI技术,把图片中的人脸、车牌号码进行脱敏处理。该模型更多信息请访问项目', limitFilesUpload:'只能上传 jpg/jpeg/png 格式的文件', limitSizeUpload:'上传文件大小不能超过 20M !', + modelManage: { + modelManage: '模型管理', + modelName: '模型名称', + useCluster: '可用集群', + local: '本地', + online: '线上', + createModel: '创建模型', + importLocalModel: '导入本地模型', + importOnlineModel: '导入线上模型', + modifyModelInfo: '修改模型信息', + addModelFiles: '增加模型文件', + uploadModelFiles: '上传模型文件', + pleaseInputModelName: '请输入模型名称', + version: '版本', + modelEngine: '模型框架', + modelLabel: '模型标签', + modelLabelInputTips: '输入标签,多个标签用空格区分', + modelDescr: '模型描述', + modelDescrInputTips: '描述字数不超过255个字符', + confirm: '确定', + cancel: '取消', + modelCreateFailed: '模型创建失败', + modelModifyFailed: '模型修改失败', + fileUpload: '文件上传', + upload: '上传', + uploadStatus: '上传状态', + modelFileUploadDefaultTips: '点击添加文件或直接拖拽文件到此处', + modelFileUploadErrTips: '单次最多上传10个文件,模型总文件大小不超过200G', + fileIstoBig: '文件太大', + removeFile: '移除文件', + uploadSuccess: '上传成功', + uploadFailed: '上传失败', + calcFileMd5: '计算文件MD5...', + uploading: '上传中...', + fileHasAlreadyInTheModel: '该文件已上传在模型:', + basicInfo: '基本信息', + modelSize: '模型大小', + descr: '描述', + createTime: '创建时间', + label: '标签', + trainTaskInfo: '训练相关信息', + trainTask: '训练任务', + codeBranch: '代码分支', + bootFile: '启动文件', + trainDataset: '训练数据集', + specInfo: '规格', + workServerNumber: '计算节点', + runParameters: '运行参数', + seeMore: '查看更多信息', + collapseDetails: '折叠详细信息', + modelFilesList: '模型文件列表', + fileName: '文件名称', + fileSize: '文件大小', + updateTime: '更新时间', + operate: '操作', + delete: '删除', + infoModificationFailed: '信息修改失败', + deleteModelFileConfirmTips: '请确认是否删除当前模型文件?', + modelFileDeleteFailed: '模型文件删除失败', + }, } export default zh; diff --git a/web_src/vuepages/pages/modelmanage/common/modelmanage-common-detail.vue b/web_src/vuepages/pages/modelmanage/common/modelmanage-common-detail.vue index 1aff6d33f..442db17be 100644 --- a/web_src/vuepages/pages/modelmanage/common/modelmanage-common-detail.vue +++ b/web_src/vuepages/pages/modelmanage/common/modelmanage-common-detail.vue @@ -2,7 +2,7 @@
@@ -15,11 +15,11 @@
-
基本信息:
+
{{ $t('modelManage.basicInfo') }}:
-
可用集群:
+
{{ $t('modelManage.useCluster') }}:
{{ state.typeStr }} @@ -27,13 +27,13 @@
-
模型大小:
+
{{ $t('modelManage.modelSize') }}:
{{ state.modelSize }}
-
描述:
+
{{ $t('modelManage.descr') }}:
@@ -42,7 +42,8 @@ class="el-icon-edit" @click="editDescr = state._description; isEidtDescr = true;">
- +
-
模型框架:
+
{{ $t('modelManage.modelEngine') }}:
{{ state.engineName }}
-
创建时间:
+
{{ $t('modelManage.createTime') }}:
{{ state.createTime }}
-
标签:
+
{{ $t('modelManage.label') }}:
@@ -74,7 +75,8 @@ class="el-icon-edit" @click="editLabel = state._label; isEidtLabel = true;">
- +
-
训练相关信息:
+
{{ $t('modelManage.trainTaskInfo') }}:
-
训练任务:
+
{{ $t('modelManage.trainTask') }}:
-
代码分支:
+
{{ $t('modelManage.codeBranch') }}:
-
启动文件:
+
{{ $t('modelManage.bootFile') }}:
{{ state.bootFile }}
-
训练数据集:
+
{{ $t('modelManage.trainDataset') }}:
{{ state.datasetName }}
@@ -114,19 +116,19 @@
-
规格:
+
{{ $t('modelManage.specInfo') }}:
{{ state.specStr }}
-
计算节点:
+
{{ $t('modelManage.workServerNumber') }}:
{{ state.workServerNumber }}
-
运行参数:
+
{{ $t('modelManage.runParameters') }}:
{{ state.parameters }}
@@ -138,27 +140,28 @@
- {{ isExpanded ? '折叠详细信息' : '查看更多信息' }} + {{ isExpanded ? $t('modelManage.collapseDetails') : $t('modelManage.seeMore') }}
-
模型文件列表:
+
{{ $t('modelManage.modelFilesList') }}:
{{ state.version }} /
- 上传模型文件 + {{ $t('modelManage.uploadModelFiles') }}
- + - + - + - + @@ -198,6 +201,7 @@ import { MODEL_ENGINES } from '~/const'; import { formatDate } from 'element-ui/lib/utils/date-util'; const REPO_NAME = location.pathname.split('/')[2]; +const MAX_LABEL_COUNT = 5; export default { data() { @@ -298,7 +302,18 @@ export default { }) }, goUploadPage() { - window.location.href = `${this.repo}/modelmanage/create_local_model_tmpl2?type=0&name=${this.state.name}&id=${this.state.id}`; + window.location.href = `${this.repo}/modelmanage/create_local_model_tmpl2?type=1&name=${this.state.name}&id=${this.state.id}`; + }, + backToModelListPage() { + const list = window.location.href.split('/'); + list.pop(); + list.push('show_model'); + window.location.href = list.join('/'); + }, + labelInput() { + const hasEndSpace = this.editLabel[this.editLabel.length - 1] == ' '; + const list = this.editLabel.trim().split(' ').filter(label => label != ''); + this.editLabel = list.slice(0, MAX_LABEL_COUNT).join(' ') + (hasEndSpace && list.length < MAX_LABEL_COUNT ? ' ' : ''); }, submitEidt(type) { const obj = { @@ -326,19 +341,19 @@ export default { } else { this.$message({ type: 'error', - message: '信息修改失败', + message: this.$t('modelManage.infoModificationFailed'), }); } }).catch(err => { console.log(err); this.$message({ type: 'error', - message: '信息修改失败', + message: this.$t('modelManage.infoModificationFailed'), }); }); }, deleteFile(file) { - this.$confirm('请确认是否删除当前模型文件?', this.$t('tips'), { + this.$confirm(this.$t('modelManage.deleteModelFileConfirmTips'), this.$t('tips'), { confirmButtonText: this.$t('confirm1'), cancelButtonText: this.$t('cancel'), type: 'warning', @@ -355,14 +370,14 @@ export default { } else { this.$message({ type: 'error', - message: '模型文件删除失败', + message: this.$t('modelManage.modelFileDeleteFailed'), }); } }).catch(err => { console.log(err); this.$message({ type: 'error', - message: '模型文件删除失败', + message: this.$t('modelManage.modelFileDeleteFailed'), }); }); }).catch(() => { }); @@ -387,10 +402,10 @@ export default { }).catch(err => { this.loading = false; console.log(err); - this.cancel(); + this.backToModelListPage(); }); } else { - this.cancel(); + this.backToModelListPage(); } }, beforeDestroy() { @@ -414,6 +429,7 @@ export default { font-weight: 550; font-size: 14px; color: rgb(16, 16, 16); + margin-bottom: 10px; } .detail-info { diff --git a/web_src/vuepages/pages/modelmanage/local/modelmanage-local-create-1.vue b/web_src/vuepages/pages/modelmanage/local/modelmanage-local-create-1.vue index 2a1895c16..3c3b35c58 100644 --- a/web_src/vuepages/pages/modelmanage/local/modelmanage-local-create-1.vue +++ b/web_src/vuepages/pages/modelmanage/local/modelmanage-local-create-1.vue @@ -1,23 +1,24 @@