| @@ -4,6 +4,7 @@ import ( | |||
| "encoding/json" | |||
| "errors" | |||
| "fmt" | |||
| "path" | |||
| "strconv" | |||
| "strings" | |||
| "time" | |||
| @@ -101,7 +102,8 @@ const ( | |||
| ModelArtsTrainJobCheckRunningCompleted ModelArtsJobStatus = "CHECK_RUNNING_COMPLETED" //审核作业已经完成 | |||
| ModelArtsTrainJobCheckFailed ModelArtsJobStatus = "CHECK_FAILED" //审核作业失败 | |||
| DURATION_STR_ZERO = "00:00:00" | |||
| DURATION_STR_ZERO = "00:00:00" | |||
| CloudbrainKeyDuration = 24 * time.Hour | |||
| //grampus | |||
| GrampusStatusPending = "pending" | |||
| @@ -187,6 +189,7 @@ type Cloudbrain struct { | |||
| ModelName string //模型名称 | |||
| ModelVersion string //模型版本 | |||
| CkptName string //权重文件名称 | |||
| PreTrainModelUrl string //预训练模型地址 | |||
| ResultUrl string //推理结果的obs路径 | |||
| User *User `xorm:"-"` | |||
| @@ -278,7 +281,7 @@ func (task *Cloudbrain) IsRunning() bool { | |||
| } | |||
| func ConvertDurationToStr(duration int64) string { | |||
| if duration == 0 { | |||
| if duration <= 0 { | |||
| return DURATION_STR_ZERO | |||
| } | |||
| return util.AddZero(duration/3600) + ":" + util.AddZero(duration%3600/60) + ":" + util.AddZero(duration%60) | |||
| @@ -654,6 +657,8 @@ type FlavorInfo struct { | |||
| UnitPrice int64 `json:"unitPrice"` | |||
| } | |||
| type SpecialPools struct { | |||
| Pools []*SpecialPool `json:"pools"` | |||
| } | |||
| @@ -2295,9 +2300,10 @@ func GetCloudbrainByIds(ids []int64) ([]*Cloudbrain, error) { | |||
| type DatasetInfo struct { | |||
| DataLocalPath string | |||
| Name string | |||
| FullName string | |||
| } | |||
| func GetDatasetInfo(uuidStr string) (map[string]DatasetInfo, string, error) { | |||
| func GetDatasetInfo(uuidStr string, grampusType ...string) (map[string]DatasetInfo, string, error) { | |||
| var datasetNames string | |||
| uuids := strings.Split(uuidStr, ";") | |||
| if len(uuids) > setting.MaxDatasetNum { | |||
| @@ -2330,16 +2336,26 @@ func GetDatasetInfo(uuidStr string) (map[string]DatasetInfo, string, error) { | |||
| return nil, datasetNames, errors.New("the dataset name is same") | |||
| } | |||
| } | |||
| var dataLocalPath string | |||
| if len(grampusType) > 0 { | |||
| if grampusType[0] == GPU { | |||
| dataLocalPath = setting.Attachment.Minio.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID | |||
| } else { | |||
| dataLocalPath = setting.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID + "/" | |||
| } | |||
| dataLocalPath := setting.Attachment.Minio.RealPath + | |||
| setting.Attachment.Minio.Bucket + "/" + | |||
| setting.Attachment.Minio.BasePath + | |||
| AttachmentRelativePath(attach.UUID) + | |||
| attach.UUID | |||
| } else { | |||
| dataLocalPath = setting.Attachment.Minio.RealPath + | |||
| setting.Attachment.Minio.Bucket + "/" + | |||
| setting.Attachment.Minio.BasePath + | |||
| AttachmentRelativePath(attach.UUID) + | |||
| attach.UUID | |||
| } | |||
| datasetInfos[attach.UUID] = DatasetInfo{ | |||
| DataLocalPath: dataLocalPath, | |||
| Name: fileName, | |||
| FullName: attach.Name, | |||
| } | |||
| if i == 0 { | |||
| datasetNames = attach.Name | |||
| @@ -34,6 +34,7 @@ type TaskDetail struct { | |||
| CardDuration string `json:"CardDuration"` | |||
| AiCenter string `json:"AiCenter"` | |||
| FlavorName string `json:"FlavorName"` | |||
| Spec *Specification `json:"Spec"` | |||
| } | |||
| func GetTodayCreatorCount(beginTime time.Time, endTime time.Time) (int64, error) { | |||
| @@ -65,6 +65,19 @@ type TaskAndLimiterConfig struct { | |||
| LimitConfig LimitConfig `xorm:"extends"` | |||
| } | |||
| type PointRule struct { | |||
| UserDailyLimit int64 | |||
| TaskRules []TaskRule | |||
| } | |||
| type TaskRule struct { | |||
| TaskCode string | |||
| AwardType string | |||
| AwardAmount int64 | |||
| RefreshRate string | |||
| LimitNum int64 | |||
| } | |||
| func (TaskAndLimiterConfig) TableName() string { | |||
| return "task_config" | |||
| } | |||
| @@ -23,6 +23,11 @@ type CreateCloudBrainForm struct { | |||
| BootFile string `form:"boot_file"` | |||
| Params string `form:"run_para_list"` | |||
| BranchName string `form:"branch_name"` | |||
| ModelName string `form:"model_name"` | |||
| ModelVersion string `form:"model_version"` | |||
| CkptName string `form:"ckpt_name"` | |||
| LabelName string `form:"label_names"` | |||
| PreTrainModelUrl string `form:"pre_train_model_url"` | |||
| DatasetName string `form:"dataset_name"` | |||
| SpecId int64 `form:"spec_id"` | |||
| } | |||
| @@ -18,6 +18,11 @@ type CreateGrampusTrainJobForm struct { | |||
| WorkServerNumber int `form:"work_server_number" binding:"Required"` | |||
| Image string `form:"image"` | |||
| DatasetName string `form:"dataset_name"` | |||
| ModelName string `form:"model_name"` | |||
| ModelVersion string `form:"model_version"` | |||
| CkptName string `form:"ckpt_name"` | |||
| LabelName string `form:"label_names"` | |||
| PreTrainModelUrl string `form:"pre_train_model_url"` | |||
| SpecId int64 `form:"spec_id"` | |||
| } | |||
| @@ -48,6 +48,11 @@ type CreateModelArtsTrainJobForm struct { | |||
| FlavorName string `form:"flaver_names" binding:"Required"` | |||
| EngineName string `form:"engine_names" binding:"Required"` | |||
| SpecId int64 `form:"spec_id" binding:"Required"` | |||
| ModelName string `form:"model_name"` | |||
| ModelVersion string `form:"model_version"` | |||
| CkptName string `form:"ckpt_name"` | |||
| LabelName string `form:"label_names"` | |||
| PreTrainModelUrl string `form:"pre_train_model_url"` | |||
| } | |||
| type CreateModelArtsInferenceJobForm struct { | |||
| @@ -1,10 +1,11 @@ | |||
| package wechat | |||
| import ( | |||
| "time" | |||
| "code.gitea.io/gitea/modules/redis/redis_client" | |||
| "code.gitea.io/gitea/modules/redis/redis_key" | |||
| "code.gitea.io/gitea/modules/redis/redis_lock" | |||
| "time" | |||
| ) | |||
| var accessTokenLock = redis_lock.NewDistributeLock(redis_key.AccessTokenLockKey()) | |||
| @@ -24,6 +24,7 @@ const ( | |||
| CodeMountPath = "/code" | |||
| DataSetMountPath = "/dataset" | |||
| ModelMountPath = "/model" | |||
| PretrainModelMountPath = "/pretrainmodel" | |||
| LogFile = "log.txt" | |||
| BenchMarkMountPath = "/benchmark" | |||
| BenchMarkResourceID = 1 | |||
| @@ -77,6 +78,8 @@ type GenerateCloudBrainTaskReq struct { | |||
| ModelVersion string | |||
| CkptName string | |||
| LabelName string | |||
| PreTrainModelPath string | |||
| PreTrainModelUrl string | |||
| Spec *models.Specification | |||
| } | |||
| @@ -276,6 +279,16 @@ func GenerateTask(req GenerateCloudBrainTaskReq) error { | |||
| }, | |||
| } | |||
| if req.PreTrainModelUrl != "" { //预训练 | |||
| volumes = append(volumes, models.Volume{ | |||
| HostPath: models.StHostPath{ | |||
| Path: req.PreTrainModelPath, | |||
| MountPath: PretrainModelMountPath, | |||
| ReadOnly: true, | |||
| }, | |||
| }) | |||
| } | |||
| if len(req.DatasetInfos) == 1 { | |||
| volumes = append(volumes, models.Volume{ | |||
| HostPath: models.StHostPath{ | |||
| @@ -359,6 +372,7 @@ func GenerateTask(req GenerateCloudBrainTaskReq) error { | |||
| CkptName: req.CkptName, | |||
| ResultUrl: req.ResultPath, | |||
| LabelName: req.LabelName, | |||
| PreTrainModelUrl: req.PreTrainModelUrl, | |||
| CreatedUnix: createTime, | |||
| UpdatedUnix: createTime, | |||
| CommitID: req.CommitID, | |||
| @@ -145,7 +145,6 @@ sendjob: | |||
| if jobResult.Code != Success { | |||
| return &jobResult, fmt.Errorf("jobResult err: %s", res.String()) | |||
| } | |||
| return &jobResult, nil | |||
| } | |||
| @@ -22,9 +22,6 @@ const ( | |||
| GpuWorkDir = "/tmp/" | |||
| NpuWorkDir = "/cache/" | |||
| CommandPrepareScript = ";mkdir -p output;mkdir -p code;mkdir -p dataset;echo \"start loading script\";wget -q https://git.openi.org.cn/OpenIOSSG/script_for_grampus/archive/master.zip;" + | |||
| "echo \"finish loading script\";unzip -q master.zip;cd script_for_grampus;chmod 777 downloader_for_obs uploader_for_npu downloader_for_minio uploader_for_gpu;" | |||
| CodeArchiveName = "master.zip" | |||
| ) | |||
| @@ -34,6 +31,9 @@ var ( | |||
| ImageInfos *setting.StImageInfosModelArts | |||
| SpecialPools *models.SpecialPools | |||
| CommandPrepareScript = ";mkdir -p output;mkdir -p code;mkdir -p dataset;mkdir -p pretrainmodel;echo \"start loading script\";wget -q https://git.openi.org.cn/OpenIOSSG/%s/archive/master.zip;" + | |||
| "echo \"finish loading script\";unzip -q master.zip;cd %s;chmod 777 downloader_for_obs uploader_for_npu downloader_for_minio uploader_for_gpu;" | |||
| ) | |||
| type GenerateTrainJobReq struct { | |||
| @@ -62,8 +62,16 @@ type GenerateTrainJobReq struct { | |||
| TotalVersionCount int | |||
| ComputeResource string | |||
| ProcessType string | |||
| DatasetName string | |||
| DatasetNames string | |||
| DatasetInfos map[string]models.DatasetInfo | |||
| Params string | |||
| ModelName string | |||
| LabelName string | |||
| CkptName string | |||
| ModelVersion string | |||
| PreTrainModelPath string | |||
| PreTrainModelUrl string | |||
| Spec *models.Specification | |||
| } | |||
| @@ -72,6 +80,8 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error | |||
| centerID, centerName := getCentersParamter(ctx, req) | |||
| log.Info("grampus Command:" + req.Command) | |||
| jobResult, err := createJob(models.CreateGrampusJobRequest{ | |||
| Name: req.JobName, | |||
| Tasks: []models.GrampusTasks{ | |||
| @@ -103,7 +113,7 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error | |||
| JobType: string(models.JobTypeTrain), | |||
| Type: models.TypeC2Net, | |||
| Uuid: req.Uuid, | |||
| DatasetName: req.DatasetName, | |||
| DatasetName: req.DatasetNames, | |||
| CommitID: req.CommitID, | |||
| IsLatestVersion: req.IsLatestVersion, | |||
| ComputeResource: req.ComputeResource, | |||
| @@ -121,6 +131,11 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error | |||
| CreatedUnix: createTime, | |||
| UpdatedUnix: createTime, | |||
| Spec: req.Spec, | |||
| ModelName: req.ModelName, | |||
| ModelVersion: req.ModelVersion, | |||
| LabelName: req.LabelName, | |||
| PreTrainModelUrl: req.PreTrainModelUrl, | |||
| CkptName: req.CkptName, | |||
| }) | |||
| if err != nil { | |||
| @@ -104,6 +104,11 @@ type GenerateTrainJobReq struct { | |||
| UserCommand string | |||
| DatasetName string | |||
| Spec *models.Specification | |||
| ModelName string | |||
| LabelName string | |||
| CkptName string | |||
| ModelVersion string | |||
| PreTrainModelUrl string | |||
| } | |||
| type GenerateInferenceJobReq struct { | |||
| @@ -440,6 +445,11 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error | |||
| CreatedUnix: createTime, | |||
| UpdatedUnix: createTime, | |||
| Spec: req.Spec, | |||
| ModelName: req.ModelName, | |||
| ModelVersion: req.ModelVersion, | |||
| LabelName: req.LabelName, | |||
| PreTrainModelUrl: req.PreTrainModelUrl, | |||
| CkptName: req.CkptName, | |||
| }) | |||
| if createErr != nil { | |||
| @@ -589,6 +599,11 @@ func GenerateTrainJobVersion(ctx *context.Context, req *GenerateTrainJobReq, job | |||
| CreatedUnix: createTime, | |||
| UpdatedUnix: createTime, | |||
| Spec: req.Spec, | |||
| ModelName: req.ModelName, | |||
| ModelVersion: req.ModelVersion, | |||
| LabelName: req.LabelName, | |||
| PreTrainModelUrl: req.PreTrainModelUrl, | |||
| CkptName: req.CkptName, | |||
| }) | |||
| if createErr != nil { | |||
| log.Error("CreateCloudbrain(%s) failed:%v", req.JobName, createErr.Error()) | |||
| @@ -0,0 +1,7 @@ | |||
| package redis_key | |||
| const CLOUDBRAIN_PREFIX = "cloudbrain" | |||
| func CloudbrainBindingJobNameKey(repoId string, jobType string, jobName string) string { | |||
| return KeyJoin(CLOUDBRAIN_PREFIX, repoId, jobType, jobName, "redis_key") | |||
| } | |||
| @@ -1,8 +1,9 @@ | |||
| package redis_lock | |||
| import ( | |||
| "code.gitea.io/gitea/modules/redis/redis_client" | |||
| "time" | |||
| "code.gitea.io/gitea/modules/redis/redis_client" | |||
| ) | |||
| type DistributeLock struct { | |||
| @@ -587,12 +587,13 @@ var ( | |||
| //grampus config | |||
| Grampus = struct { | |||
| Env string | |||
| Host string | |||
| UserName string | |||
| Password string | |||
| SpecialPools string | |||
| C2NetSequence string | |||
| Env string | |||
| Host string | |||
| UserName string | |||
| Password string | |||
| SpecialPools string | |||
| C2NetSequence string | |||
| SyncScriptProject string | |||
| }{} | |||
| C2NetInfos *C2NetSqInfos | |||
| @@ -1576,6 +1577,8 @@ func getGrampusConfig() { | |||
| log.Error("Unmarshal(C2NetSequence) failed:%v", err) | |||
| } | |||
| } | |||
| Grampus.SyncScriptProject = sec.Key("SYNC_SCRIPT_PROJECT").MustString("script_for_grampus") | |||
| } | |||
| func SetRadarMapConfig() { | |||
| @@ -1101,6 +1101,7 @@ cloudbrain_operate = Operate | |||
| cloudbrain_status_createtime = Status/Createtime | |||
| cloudbrain_status_runtime = Running Time | |||
| cloudbrain_jobname_err=Name must start with a lowercase letter or number,can include lowercase letter,number,_ and -,can not end with _, and can be up to 36 characters long. | |||
| cloudbrain_samejob_err=A task with the same name has been created, the system is processing it, please wait a minute. | |||
| cloudbrain_bootfile_err=The bootfile does not exist in the repository | |||
| cloudbrain_query_fail=Failed to query cloudbrain information. | |||
| cloudbrain.mirror_tag = Mirror Tag | |||
| @@ -1105,6 +1105,7 @@ cloudbrain_operate=操作 | |||
| cloudbrain_status_createtime=状态/创建时间 | |||
| cloudbrain_status_runtime = 运行时长 | |||
| cloudbrain_jobname_err=只能以小写字母或数字开头且只包含小写字母、数字、_和-,不能以_结尾,最长36个字符。 | |||
| cloudbrain_samejob_err=同名任务已经被创建,系统处理中,请您稍候。 | |||
| cloudbrain_bootfile_err=仓库中不存在启动文件 | |||
| cloudbrain_query_fail=查询云脑任务失败。 | |||
| cloudbrain.mirror_tag = 镜像标签 | |||
| @@ -3256,6 +3257,8 @@ load_code_failed=代码加载失败,请确认选择了正确的分支。 | |||
| error.dataset_select = 数据集选择错误:数量超过限制或者有同名数据集 | |||
| new_train_gpu_tooltips =训练脚本存储在<strong style="color:#010101">%s</strong>中,数据集存储在<strong style="color:#010101">%s</strong>中,训练输出请存储在<strong style="color:#010101">%s</strong>中以供后续下载。 | |||
| new_infer_gpu_tooltips = 数据集存储在<strong style="color:#010101">%s</strong>中,模型文件存储在<strong style="color:#010101">%s</strong>中,推理输出请存储在<strong style="color:#010101">%s</strong>中以供后续下载。 | |||
| [points] | |||
| points = 积分 | |||
| @@ -3267,5 +3270,4 @@ expected_time = ,预计可用 | |||
| points_acquisition_instructions = 积分获取说明 | |||
| insufficient_points_balance = 积分余额不足 | |||
| new_train_gpu_tooltips =训练脚本存储在<strong style="color:#010101">%s</strong>中,数据集存储在<strong style="color:#010101">%s</strong>中,训练输出请存储在<strong style="color:#010101">%s</strong>中以供后续下载。 | |||
| new_infer_gpu_tooltips = 数据集存储在<strong style="color:#010101">%s</strong>中,模型文件存储在<strong style="color:#010101">%s</strong>中,推理输出请存储在<strong style="color:#010101">%s</strong>中以供后续下载。 | |||
| @@ -733,6 +733,7 @@ func GetCloudbrainsDetailData(ctx *context.Context) { | |||
| ctx.ServerError("Get job failed:", err) | |||
| return | |||
| } | |||
| models.LoadSpecs4CloudbrainInfo(ciTasks) | |||
| nilTime := time.Time{} | |||
| tasks := []models.TaskDetail{} | |||
| for i, task := range ciTasks { | |||
| @@ -769,6 +770,7 @@ func GetCloudbrainsDetailData(ctx *context.Context) { | |||
| } else { | |||
| taskDetail.IsDelete = false | |||
| } | |||
| taskDetail.Spec = ciTasks[i].Spec | |||
| tasks = append(tasks, taskDetail) | |||
| } | |||
| @@ -2,8 +2,6 @@ package repo | |||
| import ( | |||
| "bufio" | |||
| "code.gitea.io/gitea/services/cloudbrain/resource" | |||
| "code.gitea.io/gitea/services/reward/point/account" | |||
| "encoding/json" | |||
| "errors" | |||
| "fmt" | |||
| @@ -17,6 +15,9 @@ import ( | |||
| "time" | |||
| "unicode/utf8" | |||
| "code.gitea.io/gitea/services/cloudbrain/resource" | |||
| "code.gitea.io/gitea/services/reward/point/account" | |||
| "code.gitea.io/gitea/modules/notification" | |||
| "code.gitea.io/gitea/modules/grampus" | |||
| @@ -32,6 +33,8 @@ import ( | |||
| "code.gitea.io/gitea/modules/git" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/modelarts" | |||
| "code.gitea.io/gitea/modules/redis/redis_key" | |||
| "code.gitea.io/gitea/modules/redis/redis_lock" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| "code.gitea.io/gitea/modules/storage" | |||
| "code.gitea.io/gitea/modules/util" | |||
| @@ -138,6 +141,35 @@ func cloudBrainNewDataPrepare(ctx *context.Context) error { | |||
| ctx.Data["benchmarkMode"] = ctx.Query("benchmarkMode") | |||
| if ctx.Cloudbrain != nil { | |||
| ctx.Data["branch_name"] = ctx.Cloudbrain.BranchName | |||
| ctx.Data["image"] = ctx.Cloudbrain.Image | |||
| ctx.Data["image_id"] = ctx.Cloudbrain.ImageID | |||
| ctx.Data["boot_file"] = ctx.Cloudbrain.BootFile | |||
| ctx.Data["description"] = ctx.Cloudbrain.Description | |||
| spec, _ := resource.GetCloudbrainSpec(ctx.Cloudbrain.ID) | |||
| if spec != nil { | |||
| ctx.Data["spec_id"] = spec.ID | |||
| } | |||
| ctx.Data["run_para_list"] = ctx.Cloudbrain.Parameters | |||
| ctx.Data["model_name"] = ctx.Cloudbrain.ModelName | |||
| ctx.Data["label_name"] = ctx.Cloudbrain.LabelName | |||
| ctx.Data["ckpt_name"] = ctx.Cloudbrain.CkptName | |||
| ctx.Data["model_version"] = ctx.Cloudbrain.ModelVersion | |||
| ctx.Data["pre_train_model_url"] = ctx.Cloudbrain.PreTrainModelUrl | |||
| ctx.Data["compute_resource"] = ctx.Cloudbrain.ComputeResource | |||
| ctx.Data["attachment"] = ctx.Cloudbrain.Uuid | |||
| ctx.Data["cluster_type"] = models.OpenICluster | |||
| _, _, datasetNames, _, err := getDatasUrlListByUUIDS(ctx.Cloudbrain.Uuid) | |||
| if err != nil { | |||
| log.Info("query dataset error," + err.Error()) | |||
| ctx.Data["dataset_name"] = "" | |||
| } else { | |||
| ctx.Data["dataset_name"] = datasetNames | |||
| } | |||
| } | |||
| return nil | |||
| } | |||
| @@ -184,8 +216,12 @@ func CloudBrainNew(ctx *context.Context) { | |||
| ctx.Data["PageIsGPUDebug"] = true | |||
| ctx.HTML(200, tplCloudBrainNew) | |||
| } | |||
| func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| ctx.Data["IsCreate"] = true | |||
| cloudBrainCreate(ctx, form) | |||
| } | |||
| func cloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| ctx.Data["PageIsCloudBrain"] = true | |||
| displayJobName := form.DisplayJobName | |||
| jobName := util.ConvertDisplayJobNameToJobName(displayJobName) | |||
| @@ -202,6 +238,16 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| tpl = tplCloudBrainTrainJobNew | |||
| } | |||
| lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), jobType, displayJobName)) | |||
| isOk, err := lock.Lock(models.CloudbrainKeyDuration) | |||
| if !isOk { | |||
| log.Error("lock processed failed:%v", err, ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tpl, &form) | |||
| return | |||
| } | |||
| defer lock.UnLock() | |||
| tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, jobType, displayJobName) | |||
| if err == nil { | |||
| if len(tasks) != 0 { | |||
| @@ -336,13 +382,22 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| Spec: spec, | |||
| } | |||
| if form.ModelName != "" { //使用预训练模型训练 | |||
| req.ModelName = form.ModelName | |||
| req.LabelName = form.LabelName | |||
| req.CkptName = form.CkptName | |||
| req.ModelVersion = form.ModelVersion | |||
| req.PreTrainModelPath = setting.Attachment.Minio.RealPath + form.PreTrainModelUrl | |||
| req.PreTrainModelUrl = form.PreTrainModelUrl | |||
| } | |||
| err = cloudbrain.GenerateTask(req) | |||
| if err != nil { | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr(err.Error(), tpl, &form) | |||
| return | |||
| } | |||
| if jobType == string(models.JobTypeTrain) { | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job?listType=all") | |||
| } else { | |||
| @@ -350,6 +405,11 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| } | |||
| } | |||
| func CloudBrainTrainJobVersionCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| ctx.Data["IsCreate"] = false | |||
| cloudBrainCreate(ctx, form) | |||
| } | |||
| func loadCodeAndMakeModelPath(repo *models.Repository, codePath string, branchName string, jobName string, resultPath string) string { | |||
| err := downloadCode(repo, codePath, branchName) | |||
| if err != nil { | |||
| @@ -386,10 +446,20 @@ func CloudBrainInferenceJobCreate(ctx *context.Context, form auth.CreateCloudBra | |||
| bootFile := strings.TrimSpace(form.BootFile) | |||
| labelName := form.LabelName | |||
| repo := ctx.Repo.Repository | |||
| tpl := tplCloudBrainInferenceJobNew | |||
| lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), jobType, displayJobName)) | |||
| isOk, err := lock.Lock(models.CloudbrainKeyDuration) | |||
| if !isOk { | |||
| log.Error("lock processed failed:%v", err, ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tpl, &form) | |||
| return | |||
| } | |||
| defer lock.UnLock() | |||
| ckptUrl := setting.Attachment.Minio.RealPath + form.TrainUrl + form.CkptName | |||
| log.Info("ckpt url:" + ckptUrl) | |||
| tpl := tplCloudBrainInferenceJobNew | |||
| command, err := getInferenceJobCommand(form) | |||
| if err != nil { | |||
| log.Error("getTrainJobCommand failed: %v", err) | |||
| @@ -1840,6 +1910,10 @@ func SyncCloudbrainStatus() { | |||
| oldStatus := task.Status | |||
| task.Status = grampus.TransTrainJobStatus(result.JobInfo.Status) | |||
| task.Duration = result.JobInfo.RunSec | |||
| if task.Duration < 0 { | |||
| task.Duration = 0 | |||
| } | |||
| task.TrainJobDuration = models.ConvertDurationToStr(task.Duration) | |||
| if task.StartTime == 0 && result.JobInfo.StartedAt > 0 { | |||
| @@ -2234,12 +2308,21 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo | |||
| codePath := setting.JobPath + jobName + cloudbrain.CodeMountPath | |||
| benchmarkTypeID := form.BenchmarkTypeID | |||
| benchmarkChildTypeID := form.BenchmarkChildTypeID | |||
| repo := ctx.Repo.Repository | |||
| ctx.Data["description"] = form.Description | |||
| ctx.Data["benchmarkTypeID"] = benchmarkTypeID | |||
| ctx.Data["benchmark_child_types_id_hidden"] = benchmarkChildTypeID | |||
| repo := ctx.Repo.Repository | |||
| lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), form.JobType, displayJobName)) | |||
| isOk, err := lock.Lock(models.CloudbrainKeyDuration) | |||
| if !isOk { | |||
| log.Error("lock processed failed:%v", err, ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tplCloudBrainBenchmarkNew, &form) | |||
| return | |||
| } | |||
| defer lock.UnLock() | |||
| tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeBenchmark), displayJobName) | |||
| if err == nil { | |||
| @@ -2421,6 +2504,16 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm) | |||
| tpl := tplCloudBrainBenchmarkNew | |||
| command := cloudbrain.GetCloudbrainDebugCommand() | |||
| lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), jobType, displayJobName)) | |||
| isOk, err := lock.Lock(models.CloudbrainKeyDuration) | |||
| if !isOk { | |||
| log.Error("lock processed failed:%v", err, ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tpl, &form) | |||
| return | |||
| } | |||
| defer lock.UnLock() | |||
| tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, jobType, displayJobName) | |||
| if err == nil { | |||
| if len(tasks) != 0 { | |||
| @@ -2581,6 +2674,15 @@ func BenchmarkDel(ctx *context.Context) { | |||
| } | |||
| func CloudBrainTrainJobNew(ctx *context.Context) { | |||
| ctx.Data["IsCreate"] = true | |||
| cloudBrainTrainJobCreate(ctx) | |||
| } | |||
| func CloudBrainTrainJobVersionNew(ctx *context.Context) { | |||
| ctx.Data["IsCreate"] = false | |||
| cloudBrainTrainJobCreate(ctx) | |||
| } | |||
| func cloudBrainTrainJobCreate(ctx *context.Context) { | |||
| err := cloudBrainNewDataPrepare(ctx) | |||
| if err != nil { | |||
| ctx.ServerError("get new train-job info failed", err) | |||
| @@ -2670,6 +2772,9 @@ func getTrainJobCommand(form auth.CreateCloudBrainForm) (string, error) { | |||
| param += " --" + parameter.Label + "=" + parameter.Value | |||
| } | |||
| } | |||
| if form.CkptName != "" { | |||
| param += " --pretrainmodelname" + "=" + form.CkptName | |||
| } | |||
| command += "python /code/" + bootFile + param + " > " + cloudbrain.ModelMountPath + "/" + form.DisplayJobName + "-" + cloudbrain.LogFile | |||
| @@ -1,8 +1,6 @@ | |||
| package repo | |||
| import ( | |||
| "code.gitea.io/gitea/services/cloudbrain/resource" | |||
| "code.gitea.io/gitea/services/reward/point/account" | |||
| "encoding/json" | |||
| "errors" | |||
| "fmt" | |||
| @@ -14,11 +12,18 @@ import ( | |||
| "strings" | |||
| "time" | |||
| "code.gitea.io/gitea/services/cloudbrain/resource" | |||
| "code.gitea.io/gitea/services/reward/point/account" | |||
| "code.gitea.io/gitea/modules/auth" | |||
| "code.gitea.io/gitea/modules/git" | |||
| "code.gitea.io/gitea/modules/grampus" | |||
| "code.gitea.io/gitea/modules/modelarts" | |||
| "code.gitea.io/gitea/modules/notification" | |||
| "code.gitea.io/gitea/modules/redis/redis_key" | |||
| "code.gitea.io/gitea/modules/redis/redis_lock" | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| "code.gitea.io/gitea/modules/util" | |||
| "github.com/unknwon/com" | |||
| @@ -42,7 +47,7 @@ const ( | |||
| ) | |||
| func GrampusTrainJobGPUNew(ctx *context.Context) { | |||
| ctx.Data["datasetType"] = models.TypeCloudBrainOne | |||
| ctx.Data["IsCreate"] = true | |||
| err := grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| if err != nil { | |||
| ctx.ServerError("get new train-job info failed", err) | |||
| @@ -53,7 +58,7 @@ func GrampusTrainJobGPUNew(ctx *context.Context) { | |||
| } | |||
| func GrampusTrainJobNPUNew(ctx *context.Context) { | |||
| ctx.Data["datasetType"] = models.TypeCloudBrainTwo | |||
| ctx.Data["IsCreate"] = true | |||
| err := grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| if err != nil { | |||
| ctx.ServerError("get new train-job info failed", err) | |||
| @@ -135,9 +140,56 @@ func grampusTrainJobNewDataPrepare(ctx *context.Context, processType string) err | |||
| ctx.Data["WaitCount"] = waitCount | |||
| } | |||
| if ctx.Cloudbrain != nil { | |||
| ctx.Data["attachment"] = ctx.Cloudbrain.Uuid | |||
| ctx.Data["boot_file"] = ctx.Cloudbrain.BootFile | |||
| ctx.Data["image_id"] = ctx.Cloudbrain.ImageID | |||
| ctx.Data["run_para_list"] = ctx.Cloudbrain.Parameters | |||
| ctx.Data["description"] = ctx.Cloudbrain.Description | |||
| ctx.Data["branch_name"] = ctx.Cloudbrain.BranchName | |||
| ctx.Data["engine_name"] = ctx.Cloudbrain.EngineName | |||
| ctx.Data["WorkServerNumber"] = ctx.Cloudbrain.WorkServerNumber | |||
| if ctx.Cloudbrain.Image != "" { | |||
| ctx.Data["image"] = ctx.Cloudbrain.Image | |||
| } else { | |||
| ctx.Data["image"] = ctx.Cloudbrain.EngineName | |||
| } | |||
| ctx.Data["dataset_name"] = ctx.Cloudbrain.DatasetName | |||
| ctx.Data["model_name"] = ctx.Cloudbrain.ModelName | |||
| ctx.Data["model_version"] = ctx.Cloudbrain.ModelVersion | |||
| ctx.Data["ckpt_name"] = ctx.Cloudbrain.CkptName | |||
| ctx.Data["label_names"] = ctx.Cloudbrain.LabelName | |||
| ctx.Data["PreTrainModelUrl"] = ctx.Cloudbrain.PreTrainModelUrl | |||
| spec, _ := resource.GetCloudbrainSpec(ctx.Cloudbrain.ID) | |||
| if spec != nil { | |||
| ctx.Data["spec_id"] = spec.ID | |||
| } | |||
| } | |||
| return nil | |||
| } | |||
| func GrampusTrainJobVersionNew(ctx *context.Context) { | |||
| task := ctx.Cloudbrain | |||
| ctx.Data["IsCreate"] = false | |||
| if task.ComputeResource == models.GPUResource { | |||
| err := grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| if err != nil { | |||
| ctx.ServerError("get new train-job version info failed", err) | |||
| return | |||
| } | |||
| ctx.HTML(http.StatusOK, tplGrampusTrainJobGPUNew) | |||
| } else if task.ComputeResource == models.NPUResource { | |||
| err := grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| if err != nil { | |||
| ctx.ServerError("get new train-job version info failed", err) | |||
| return | |||
| } | |||
| ctx.HTML(200, tplGrampusTrainJobNPUNew) | |||
| } | |||
| } | |||
| func prepareGrampusTrainSpecs(ctx *context.Context, computeResource string) { | |||
| noteBookSpecs, _ := resource.FindAvailableSpecs(ctx.User.ID, models.FindSpecsOptions{ | |||
| JobType: models.JobTypeTrain, | |||
| @@ -202,6 +254,7 @@ func grampusParamCheckCreateTrainJob(form auth.CreateGrampusTrainJobForm) error | |||
| } | |||
| func GrampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrainJobForm) { | |||
| ctx.Data["IsCreate"] = true | |||
| displayJobName := form.DisplayJobName | |||
| jobName := util.ConvertDisplayJobNameToJobName(displayJobName) | |||
| uuid := form.Attachment | |||
| @@ -211,28 +264,31 @@ func GrampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| repo := ctx.Repo.Repository | |||
| codeLocalPath := setting.JobPath + jobName + cloudbrain.CodeMountPath + "/" | |||
| codeMinioPath := setting.CBCodePathPrefix + jobName + cloudbrain.CodeMountPath + "/" | |||
| dataMinioPath := setting.Attachment.Minio.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/" + uuid | |||
| branchName := form.BranchName | |||
| image := strings.TrimSpace(form.Image) | |||
| tpl := tplGrampusTrainJobGPUNew | |||
| if !jobNamePattern.MatchString(displayJobName) { | |||
| lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeTrain), displayJobName)) | |||
| isOk, err := lock.Lock(models.CloudbrainKeyDuration) | |||
| if !isOk { | |||
| log.Error("lock processed failed:%v", err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tplGrampusTrainJobGPUNew, &form) | |||
| return | |||
| } | |||
| defer lock.UnLock() | |||
| bootFileExist, err := ctx.Repo.FileExists(bootFile, branchName) | |||
| if err != nil || !bootFileExist { | |||
| log.Error("Get bootfile error:", err, ctx.Data["MsgID"]) | |||
| if !jobNamePattern.MatchString(displayJobName) { | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_bootfile_err"), tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tpl, &form) | |||
| return | |||
| } | |||
| errStr := checkSpecialPool(ctx, "GPU") | |||
| if errStr != "" { | |||
| bootFileExist, err := ctx.Repo.FileExists(bootFile, branchName) | |||
| if err != nil || !bootFileExist { | |||
| log.Error("Get bootfile error:", err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| ctx.RenderWithErr(errStr, tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_bootfile_err"), tpl, &form) | |||
| return | |||
| } | |||
| @@ -241,13 +297,13 @@ func GrampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| if err != nil { | |||
| log.Error("GetGrampusCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| ctx.RenderWithErr("system error", tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr("system error", tpl, &form) | |||
| return | |||
| } else { | |||
| if count >= 1 { | |||
| log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| ctx.RenderWithErr("you have already a running or waiting task, can not create more", tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr("you have already a running or waiting task, can not create more", tpl, &form) | |||
| return | |||
| } | |||
| } | |||
| @@ -256,7 +312,7 @@ func GrampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| if err := grampusParamCheckCreateTrainJob(form); err != nil { | |||
| log.Error("paramCheckCreateTrainJob failed:(%v)", err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| ctx.RenderWithErr(err.Error(), tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr(err.Error(), tpl, &form) | |||
| return | |||
| } | |||
| @@ -266,14 +322,14 @@ func GrampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| if len(tasks) != 0 { | |||
| log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| ctx.RenderWithErr("the job name did already exist", tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr("the job name did already exist", tpl, &form) | |||
| return | |||
| } | |||
| } else { | |||
| if !models.IsErrJobNotExist(err) { | |||
| log.Error("system error, %v", err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| ctx.RenderWithErr("system error", tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr("system error", tpl, &form) | |||
| return | |||
| } | |||
| } | |||
| @@ -286,7 +342,7 @@ func GrampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| }) | |||
| if err != nil || spec == nil { | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| ctx.RenderWithErr("Resource specification not available", tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr("Resource specification not available", tpl, &form) | |||
| return | |||
| } | |||
| @@ -298,11 +354,12 @@ func GrampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| } | |||
| //check dataset | |||
| attachment, err := models.GetAttachmentByUUID(uuid) | |||
| datasetInfos, datasetNames, err := models.GetDatasetInfo(uuid, models.GPU) | |||
| if err != nil { | |||
| log.Error("GetAttachmentByUUID failed:", err.Error(), ctx.Data["MsgID"]) | |||
| log.Error("GetDatasetInfo failed: %v", err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| ctx.RenderWithErr("dataset is not exist", tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tpl, &form) | |||
| return | |||
| } | |||
| @@ -315,7 +372,7 @@ func GrampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| if err := downloadZipCode(ctx, codeLocalPath, branchName); err != nil { | |||
| log.Error("downloadZipCode failed, server timed out: %s (%v)", repo.FullName(), err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tpl, &form) | |||
| return | |||
| } | |||
| @@ -324,7 +381,7 @@ func GrampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| if err := uploadCodeToMinio(codeLocalPath+"/", jobName, cloudbrain.CodeMountPath+"/"); err != nil { | |||
| log.Error("Failed to uploadCodeToMinio: %s (%v)", repo.FullName(), err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tpl, &form) | |||
| return | |||
| } | |||
| @@ -332,7 +389,7 @@ func GrampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| if err := mkModelPath(modelPath); err != nil { | |||
| log.Error("Failed to mkModelPath: %s (%v)", repo.FullName(), err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tpl, &form) | |||
| return | |||
| } | |||
| @@ -340,52 +397,102 @@ func GrampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| if err := uploadCodeToMinio(modelPath, jobName, cloudbrain.ModelMountPath+"/"); err != nil { | |||
| log.Error("Failed to uploadCodeToMinio: %s (%v)", repo.FullName(), err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tpl, &form) | |||
| return | |||
| } | |||
| var datasetRemotePath, allFileName string | |||
| for _, datasetInfo := range datasetInfos { | |||
| if datasetRemotePath == "" { | |||
| datasetRemotePath = datasetInfo.DataLocalPath | |||
| allFileName = datasetInfo.FullName | |||
| } else { | |||
| datasetRemotePath = datasetRemotePath + ";" + datasetInfo.DataLocalPath | |||
| allFileName = allFileName + ";" + datasetInfo.FullName | |||
| } | |||
| } | |||
| //prepare command | |||
| command, err := generateCommand(repo.Name, grampus.ProcessorTypeGPU, codeMinioPath+cloudbrain.DefaultBranchName+".zip", dataMinioPath, bootFile, params, setting.CBCodePathPrefix+jobName+cloudbrain.ModelMountPath+"/", attachment.Name) | |||
| preTrainModelPath := getPreTrainModelPath(form.PreTrainModelUrl, form.CkptName) | |||
| command, err := generateCommand(repo.Name, grampus.ProcessorTypeGPU, codeMinioPath+cloudbrain.DefaultBranchName+".zip", datasetRemotePath, bootFile, params, setting.CBCodePathPrefix+jobName+cloudbrain.ModelMountPath+"/", allFileName, preTrainModelPath, form.CkptName) | |||
| if err != nil { | |||
| log.Error("Failed to generateCommand: %s (%v)", displayJobName, err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| ctx.RenderWithErr("Create task failed, internal error", tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr("Create task failed, internal error", tpl, &form) | |||
| return | |||
| } | |||
| commitID, _ := ctx.Repo.GitRepo.GetBranchCommitID(branchName) | |||
| req := &grampus.GenerateTrainJobReq{ | |||
| JobName: jobName, | |||
| DisplayJobName: displayJobName, | |||
| ComputeResource: models.GPUResource, | |||
| ProcessType: grampus.ProcessorTypeGPU, | |||
| Command: command, | |||
| ImageUrl: image, | |||
| Description: description, | |||
| BootFile: bootFile, | |||
| Uuid: uuid, | |||
| CommitID: commitID, | |||
| BranchName: branchName, | |||
| Params: form.Params, | |||
| EngineName: image, | |||
| DatasetName: attachment.Name, | |||
| JobName: jobName, | |||
| DisplayJobName: displayJobName, | |||
| ComputeResource: models.GPUResource, | |||
| ProcessType: grampus.ProcessorTypeGPU, | |||
| Command: command, | |||
| ImageUrl: image, | |||
| Description: description, | |||
| BootFile: bootFile, | |||
| Uuid: uuid, | |||
| CommitID: commitID, | |||
| BranchName: branchName, | |||
| Params: form.Params, | |||
| EngineName: image, | |||
| DatasetNames: datasetNames, | |||
| DatasetInfos: datasetInfos, | |||
| IsLatestVersion: modelarts.IsLatestVersion, | |||
| VersionCount: modelarts.VersionCountOne, | |||
| WorkServerNumber: 1, | |||
| Spec: spec, | |||
| } | |||
| if form.ModelName != "" { //使用预训练模型训练 | |||
| req.ModelName = form.ModelName | |||
| req.LabelName = form.LabelName | |||
| req.CkptName = form.CkptName | |||
| req.ModelVersion = form.ModelVersion | |||
| req.PreTrainModelUrl = form.PreTrainModelUrl | |||
| } | |||
| err = grampus.GenerateTrainJob(ctx, req) | |||
| if err != nil { | |||
| log.Error("GenerateTrainJob failed:%v", err.Error(), ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||
| ctx.RenderWithErr(err.Error(), tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr(err.Error(), tpl, &form) | |||
| return | |||
| } | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") | |||
| } | |||
| func getPreTrainModelPath(pretrainModelDir string, fileName string) string { | |||
| index := strings.Index(pretrainModelDir, "/") | |||
| if index > 0 { | |||
| filterBucket := pretrainModelDir[index+1:] | |||
| return filterBucket + fileName | |||
| } else { | |||
| return "" | |||
| } | |||
| } | |||
| func GrampusTrainJobVersionCreate(ctx *context.Context, form auth.CreateGrampusTrainJobForm) { | |||
| ctx.Data["IsCreate"] = false | |||
| computeResource := ctx.Query("compute_resource") | |||
| if computeResource == models.GPUResource { | |||
| GrampusTrainJobGpuCreate(ctx, form) | |||
| } else if computeResource == models.NPUResource { | |||
| GrampusTrainJobNpuCreate(ctx, form) | |||
| } else { | |||
| ctx.ServerError("resource error", errors.New("compute resource is not support")) | |||
| return | |||
| } | |||
| } | |||
| func checkSpecialPool(ctx *context.Context, resourceType string) string { | |||
| grampus.InitSpecialPool() | |||
| if grampus.SpecialPools != nil { | |||
| @@ -409,6 +516,7 @@ func checkSpecialPool(ctx *context.Context, resourceType string) string { | |||
| } | |||
| func GrampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrainJobForm) { | |||
| ctx.Data["IsCreate"] = true | |||
| displayJobName := form.DisplayJobName | |||
| jobName := util.ConvertDisplayJobNameToJobName(displayJobName) | |||
| uuid := form.Attachment | |||
| @@ -418,30 +526,34 @@ func GrampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| repo := ctx.Repo.Repository | |||
| codeLocalPath := setting.JobPath + jobName + modelarts.CodePath | |||
| codeObsPath := grampus.JobPath + jobName + modelarts.CodePath | |||
| dataObsPath := setting.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/" + uuid + "/" | |||
| //dataObsPath := setting.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/" + uuid + "/" | |||
| branchName := form.BranchName | |||
| isLatestVersion := modelarts.IsLatestVersion | |||
| versionCount := modelarts.VersionCountOne | |||
| engineName := form.EngineName | |||
| tpl := tplGrampusTrainJobNPUNew | |||
| if !jobNamePattern.MatchString(displayJobName) { | |||
| lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeTrain), displayJobName)) | |||
| isOk, err := lock.Lock(models.CloudbrainKeyDuration) | |||
| if !isOk { | |||
| log.Error("lock processed failed:%v", err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tplGrampusTrainJobNPUNew, &form) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tplGrampusTrainJobNPUNew, &form) | |||
| return | |||
| } | |||
| defer lock.UnLock() | |||
| bootFileExist, err := ctx.Repo.FileExists(bootFile, branchName) | |||
| if err != nil || !bootFileExist { | |||
| log.Error("Get bootfile error:", err, ctx.Data["MsgID"]) | |||
| if !jobNamePattern.MatchString(displayJobName) { | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_bootfile_err"), tplGrampusTrainJobNPUNew, &form) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tpl, &form) | |||
| return | |||
| } | |||
| errStr := checkSpecialPool(ctx, "NPU") | |||
| if errStr != "" { | |||
| bootFileExist, err := ctx.Repo.FileExists(bootFile, branchName) | |||
| if err != nil || !bootFileExist { | |||
| log.Error("Get bootfile error:", err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| ctx.RenderWithErr(errStr, tplGrampusTrainJobGPUNew, &form) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_bootfile_err"), tpl, &form) | |||
| return | |||
| } | |||
| @@ -450,13 +562,13 @@ func GrampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| if err != nil { | |||
| log.Error("GetGrampusCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| ctx.RenderWithErr("system error", tplGrampusTrainJobNPUNew, &form) | |||
| ctx.RenderWithErr("system error", tpl, &form) | |||
| return | |||
| } else { | |||
| if count >= 1 { | |||
| log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| ctx.RenderWithErr("you have already a running or waiting task, can not create more", tplGrampusTrainJobNPUNew, &form) | |||
| ctx.RenderWithErr("you have already a running or waiting task, can not create more", tpl, &form) | |||
| return | |||
| } | |||
| } | |||
| @@ -465,7 +577,7 @@ func GrampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| if err := grampusParamCheckCreateTrainJob(form); err != nil { | |||
| log.Error("paramCheckCreateTrainJob failed:(%v)", err) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| ctx.RenderWithErr(err.Error(), tplGrampusTrainJobNPUNew, &form) | |||
| ctx.RenderWithErr(err.Error(), tpl, &form) | |||
| return | |||
| } | |||
| @@ -475,14 +587,14 @@ func GrampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| if len(tasks) != 0 { | |||
| log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| ctx.RenderWithErr("the job name did already exist", tplGrampusTrainJobNPUNew, &form) | |||
| ctx.RenderWithErr("the job name did already exist", tpl, &form) | |||
| return | |||
| } | |||
| } else { | |||
| if !models.IsErrJobNotExist(err) { | |||
| log.Error("system error, %v", err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| ctx.RenderWithErr("system error", tplGrampusTrainJobNPUNew, &form) | |||
| ctx.RenderWithErr("system error", tpl, &form) | |||
| return | |||
| } | |||
| } | |||
| @@ -495,7 +607,7 @@ func GrampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| }) | |||
| if err != nil || spec == nil { | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| ctx.RenderWithErr("Resource specification not available", tplGrampusTrainJobNPUNew, &form) | |||
| ctx.RenderWithErr("Resource specification not available", tpl, &form) | |||
| return | |||
| } | |||
| if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) { | |||
| @@ -506,11 +618,11 @@ func GrampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| } | |||
| //check dataset | |||
| attachment, err := models.GetAttachmentByUUID(uuid) | |||
| datasetInfos, datasetNames, err := models.GetDatasetInfo(uuid, models.NPU) | |||
| if err != nil { | |||
| log.Error("GetAttachmentByUUID failed:", err.Error(), ctx.Data["MsgID"]) | |||
| log.Error("GetDatasetInfo failed: %v", err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| ctx.RenderWithErr("dataset is not exist", tplGrampusTrainJobNPUNew, &form) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tpl, &form) | |||
| return | |||
| } | |||
| @@ -523,7 +635,7 @@ func GrampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| if err := downloadZipCode(ctx, codeLocalPath, branchName); err != nil { | |||
| log.Error("downloadZipCode failed, server timed out: %s (%v)", repo.FullName(), err) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tplGrampusTrainJobNPUNew, &form) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tpl, &form) | |||
| return | |||
| } | |||
| @@ -531,23 +643,36 @@ func GrampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.OutputPath); err != nil { | |||
| log.Error("Failed to obsMkdir_output: %s (%v)", repo.FullName(), err) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tplGrampusTrainJobNPUNew, &form) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tpl, &form) | |||
| return | |||
| } | |||
| if err := uploadCodeToObs(codeLocalPath, jobName, ""); err != nil { | |||
| log.Error("Failed to uploadCodeToObs: %s (%v)", repo.FullName(), err) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tplGrampusTrainJobNPUNew, &form) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tpl, &form) | |||
| return | |||
| } | |||
| var datasetRemotePath, allFileName string | |||
| for _, datasetInfo := range datasetInfos { | |||
| if datasetRemotePath == "" { | |||
| datasetRemotePath = datasetInfo.DataLocalPath + "'" + datasetInfo.FullName + "'" | |||
| allFileName = datasetInfo.FullName | |||
| } else { | |||
| datasetRemotePath = datasetRemotePath + ";" + datasetInfo.DataLocalPath + "'" + datasetInfo.FullName + "'" | |||
| allFileName = allFileName + ";" + datasetInfo.FullName | |||
| } | |||
| } | |||
| //prepare command | |||
| command, err := generateCommand(repo.Name, grampus.ProcessorTypeNPU, codeObsPath+cloudbrain.DefaultBranchName+".zip", dataObsPath+"'"+attachment.Name+"'", bootFile, params, setting.CodePathPrefix+jobName+modelarts.OutputPath, attachment.Name) | |||
| preTrainModelPath := getPreTrainModelPath(form.PreTrainModelUrl, form.CkptName) | |||
| command, err := generateCommand(repo.Name, grampus.ProcessorTypeNPU, codeObsPath+cloudbrain.DefaultBranchName+".zip", datasetRemotePath, bootFile, params, setting.CodePathPrefix+jobName+modelarts.OutputPath, allFileName, preTrainModelPath, form.CkptName) | |||
| if err != nil { | |||
| log.Error("Failed to generateCommand: %s (%v)", displayJobName, err, ctx.Data["MsgID"]) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| ctx.RenderWithErr("Create task failed, internal error", tplGrampusTrainJobNPUNew, &form) | |||
| ctx.RenderWithErr("Create task failed, internal error", tpl, &form) | |||
| return | |||
| } | |||
| @@ -560,7 +685,6 @@ func GrampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| ProcessType: grampus.ProcessorTypeNPU, | |||
| Command: command, | |||
| ImageId: form.ImageID, | |||
| DataUrl: dataObsPath, | |||
| Description: description, | |||
| CodeObsPath: codeObsPath, | |||
| BootFileUrl: codeObsPath + bootFile, | |||
| @@ -574,15 +698,24 @@ func GrampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||
| EngineName: engineName, | |||
| VersionCount: versionCount, | |||
| TotalVersionCount: modelarts.TotalVersionCount, | |||
| DatasetName: attachment.Name, | |||
| DatasetNames: datasetNames, | |||
| DatasetInfos: datasetInfos, | |||
| Spec: spec, | |||
| } | |||
| if form.ModelName != "" { //使用预训练模型训练 | |||
| req.ModelName = form.ModelName | |||
| req.LabelName = form.LabelName | |||
| req.CkptName = form.CkptName | |||
| req.ModelVersion = form.ModelVersion | |||
| req.PreTrainModelUrl = form.PreTrainModelUrl | |||
| } | |||
| err = grampus.GenerateTrainJob(ctx, req) | |||
| if err != nil { | |||
| log.Error("GenerateTrainJob failed:%v", err.Error()) | |||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||
| ctx.RenderWithErr(err.Error(), tplGrampusTrainJobNPUNew, &form) | |||
| ctx.RenderWithErr(err.Error(), tpl, &form) | |||
| return | |||
| } | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") | |||
| @@ -709,6 +842,9 @@ func GrampusTrainJobShow(ctx *context.Context) { | |||
| task.Status = grampus.TransTrainJobStatus(result.JobInfo.Status) | |||
| if task.Status != result.JobInfo.Status || result.JobInfo.Status == models.GrampusStatusRunning { | |||
| task.Duration = result.JobInfo.RunSec | |||
| if task.Duration < 0 { | |||
| task.Duration = 0 | |||
| } | |||
| task.TrainJobDuration = models.ConvertDurationToStr(task.Duration) | |||
| if task.StartTime == 0 && result.JobInfo.StartedAt > 0 { | |||
| @@ -826,7 +962,7 @@ func GrampusGetLog(ctx *context.Context) { | |||
| return | |||
| } | |||
| func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bootFile, paramSrc, outputRemotePath, datasetName string) (string, error) { | |||
| func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bootFile, paramSrc, outputRemotePath, datasetName, pretrainModelPath, pretrainModelFileName string) (string, error) { | |||
| var command string | |||
| workDir := grampus.NpuWorkDir | |||
| @@ -834,22 +970,22 @@ func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bo | |||
| workDir = grampus.GpuWorkDir | |||
| } | |||
| command += "pwd;cd " + workDir + grampus.CommandPrepareScript | |||
| command += "pwd;cd " + workDir + fmt.Sprintf(grampus.CommandPrepareScript, setting.Grampus.SyncScriptProject, setting.Grampus.SyncScriptProject) | |||
| //download code & dataset | |||
| if processorType == grampus.ProcessorTypeNPU { | |||
| commandDownload := "./downloader_for_obs " + setting.Bucket + " " + codeRemotePath + " " + grampus.CodeArchiveName + " " + dataRemotePath + " '" + datasetName + "';" | |||
| commandDownload := "./downloader_for_obs " + setting.Bucket + " " + codeRemotePath + " " + grampus.CodeArchiveName + " '" + dataRemotePath + "' '" + datasetName + "'" | |||
| commandDownload = processPretrainModelParameter(pretrainModelPath, pretrainModelFileName, commandDownload) | |||
| command += commandDownload | |||
| } else if processorType == grampus.ProcessorTypeGPU { | |||
| commandDownload := "./downloader_for_minio " + setting.Grampus.Env + " " + codeRemotePath + " " + grampus.CodeArchiveName + " " + dataRemotePath + " '" + datasetName + "';" | |||
| commandDownload := "./downloader_for_minio " + setting.Grampus.Env + " " + codeRemotePath + " " + grampus.CodeArchiveName + " '" + dataRemotePath + "' '" + datasetName + "'" | |||
| commandDownload = processPretrainModelParameter(pretrainModelPath, pretrainModelFileName, commandDownload) | |||
| command += commandDownload | |||
| } | |||
| //unzip code & dataset | |||
| toolUnzip := "unzip -q '" | |||
| if strings.HasSuffix(datasetName, ".tar.gz") { | |||
| toolUnzip = "tar -zxvf '" | |||
| } | |||
| commandUnzip := "cd " + workDir + "code;unzip -q master.zip;echo \"start to unzip dataset\";cd " + workDir + "dataset;" + toolUnzip + datasetName + "';" | |||
| unZipDatasetCommand := generateDatasetUnzipCommand(datasetName) | |||
| commandUnzip := "cd " + workDir + "code;unzip -q master.zip;echo \"start to unzip dataset\";cd " + workDir + "dataset;" + unZipDatasetCommand | |||
| command += commandUnzip | |||
| command += "echo \"unzip finished;start to exec code;\";" | |||
| @@ -880,6 +1016,10 @@ func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bo | |||
| } | |||
| } | |||
| if pretrainModelFileName != "" { | |||
| paramCode += " --pretrainmodelname" + "=" + pretrainModelFileName | |||
| } | |||
| var commandCode string | |||
| if processorType == grampus.ProcessorTypeNPU { | |||
| commandCode = "/bin/bash /home/work/run_train_for_openi.sh " + workDir + "code/" + strings.ToLower(repoName) + "/" + bootFile + " /tmp/log/train.log" + paramCode + ";" | |||
| @@ -895,10 +1035,10 @@ func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bo | |||
| //upload models | |||
| if processorType == grampus.ProcessorTypeNPU { | |||
| commandUpload := "cd " + workDir + "script_for_grampus/;./uploader_for_npu " + setting.Bucket + " " + outputRemotePath + " " + workDir + "output/;" | |||
| commandUpload := "cd " + workDir + setting.Grampus.SyncScriptProject + "/;./uploader_for_npu " + setting.Bucket + " " + outputRemotePath + " " + workDir + "output/;" | |||
| command += commandUpload | |||
| } else if processorType == grampus.ProcessorTypeGPU { | |||
| commandUpload := "cd " + workDir + "script_for_grampus/;./uploader_for_gpu " + setting.Grampus.Env + " " + outputRemotePath + " " + workDir + "output/;" | |||
| commandUpload := "cd " + workDir + setting.Grampus.SyncScriptProject + "/;./uploader_for_gpu " + setting.Grampus.Env + " " + outputRemotePath + " " + workDir + "output/;" | |||
| command += commandUpload | |||
| } | |||
| @@ -909,6 +1049,38 @@ func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bo | |||
| return command, nil | |||
| } | |||
| func processPretrainModelParameter(pretrainModelPath string, pretrainModelFileName string, commandDownload string) string { | |||
| commandDownloadTemp := commandDownload | |||
| if pretrainModelPath != "" { | |||
| commandDownloadTemp += " '" + pretrainModelPath + "' '" + pretrainModelFileName + "'" | |||
| } | |||
| commandDownloadTemp += ";" | |||
| return commandDownloadTemp | |||
| } | |||
| func generateDatasetUnzipCommand(datasetName string) string { | |||
| var unZipDatasetCommand string | |||
| datasetNameArray := strings.Split(datasetName, ";") | |||
| if len(datasetNameArray) == 1 { //单数据集 | |||
| unZipDatasetCommand = "unzip -q '" + datasetName + "';" | |||
| if strings.HasSuffix(datasetName, ".tar.gz") { | |||
| unZipDatasetCommand = "tar --strip-components=1 -zxvf '" + datasetName + "';" | |||
| } | |||
| } else { //多数据集 | |||
| for _, datasetNameTemp := range datasetNameArray { | |||
| if strings.HasSuffix(datasetName, ".tar.gz") { | |||
| unZipDatasetCommand = unZipDatasetCommand + "tar -zxvf '" + datasetName + "';" | |||
| } else { | |||
| unZipDatasetCommand = unZipDatasetCommand + "unzip -q '" + datasetNameTemp + "' -d './" + strings.TrimSuffix(datasetNameTemp, ".zip") + "';" | |||
| } | |||
| } | |||
| } | |||
| return unZipDatasetCommand | |||
| } | |||
| func downloadZipCode(ctx *context.Context, codePath, branchName string) error { | |||
| archiveType := git.ZIP | |||
| archivePath := codePath | |||
| @@ -2,9 +2,6 @@ package repo | |||
| import ( | |||
| "archive/zip" | |||
| "code.gitea.io/gitea/modules/modelarts_cd" | |||
| "code.gitea.io/gitea/services/cloudbrain/resource" | |||
| "code.gitea.io/gitea/services/reward/point/account" | |||
| "encoding/json" | |||
| "errors" | |||
| "fmt" | |||
| @@ -18,6 +15,10 @@ import ( | |||
| "time" | |||
| "unicode/utf8" | |||
| "code.gitea.io/gitea/modules/modelarts_cd" | |||
| "code.gitea.io/gitea/services/cloudbrain/resource" | |||
| "code.gitea.io/gitea/services/reward/point/account" | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/auth" | |||
| "code.gitea.io/gitea/modules/base" | |||
| @@ -28,6 +29,8 @@ import ( | |||
| "code.gitea.io/gitea/modules/modelarts" | |||
| "code.gitea.io/gitea/modules/notification" | |||
| "code.gitea.io/gitea/modules/obs" | |||
| "code.gitea.io/gitea/modules/redis/redis_key" | |||
| "code.gitea.io/gitea/modules/redis/redis_lock" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| "code.gitea.io/gitea/modules/storage" | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| @@ -210,6 +213,16 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm | |||
| imageId := form.ImageId | |||
| repo := ctx.Repo.Repository | |||
| lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeDebug), displayJobName)) | |||
| isOk, err := lock.Lock(models.CloudbrainKeyDuration) | |||
| if !isOk { | |||
| log.Error("lock processed failed:%v", err, ctx.Data["MsgID"]) | |||
| notebookNewDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tplModelArtsNotebookNew, &form) | |||
| return | |||
| } | |||
| defer lock.UnLock() | |||
| count, err := models.GetCloudbrainNotebookCountByUserID(ctx.User.ID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainNotebookCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||
| @@ -846,84 +859,6 @@ func setSpecBySpecialPoolConfig(ctx *context.Context, jobType string) { | |||
| } | |||
| } | |||
| func trainJobErrorNewDataPrepare(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) error { | |||
| ctx.Data["PageIsCloudBrain"] = true | |||
| //can, err := canUserCreateTrainJob(ctx.User.ID) | |||
| //if err != nil { | |||
| // ctx.ServerError("canUserCreateTrainJob", err) | |||
| // return | |||
| //} | |||
| // | |||
| //if !can { | |||
| // log.Error("the user can not create train-job") | |||
| // ctx.ServerError("the user can not create train-job", fmt.Errorf("the user can not create train-job")) | |||
| // return | |||
| //} | |||
| t := time.Now() | |||
| var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
| ctx.Data["display_job_name"] = displayJobName | |||
| attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||
| if err != nil { | |||
| ctx.ServerError("GetAllUserAttachments failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["attachments"] = attachs | |||
| var resourcePools modelarts.ResourcePool | |||
| if err = json.Unmarshal([]byte(setting.ResourcePools), &resourcePools); err != nil { | |||
| ctx.ServerError("json.Unmarshal failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["resource_pools"] = resourcePools.Info | |||
| var engines modelarts.Engine | |||
| if err = json.Unmarshal([]byte(setting.Engines), &engines); err != nil { | |||
| ctx.ServerError("json.Unmarshal failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["engines"] = engines.Info | |||
| var versionInfos modelarts.VersionInfo | |||
| if err = json.Unmarshal([]byte(setting.EngineVersions), &versionInfos); err != nil { | |||
| ctx.ServerError("json.Unmarshal failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["engine_versions"] = versionInfos.Version | |||
| prepareCloudbrainTwoTrainSpecs(ctx) | |||
| configList, err := getConfigList(modelarts.PerPage, 1, modelarts.SortByCreateTime, "desc", "", modelarts.ConfigTypeCustom) | |||
| if err != nil { | |||
| ctx.ServerError("getConfigList failed:", err) | |||
| return err | |||
| } | |||
| var Parameters modelarts.Parameters | |||
| if err = json.Unmarshal([]byte(form.Params), &Parameters); err != nil { | |||
| ctx.ServerError("json.Unmarshal failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["params"] = Parameters.Parameter | |||
| ctx.Data["config_list"] = configList.ParaConfigs | |||
| ctx.Data["bootFile"] = form.BootFile | |||
| ctx.Data["uuid"] = form.Attachment | |||
| _, datasetNames, err := models.GetDatasetInfo(form.Attachment) | |||
| if err != nil { | |||
| log.Error("GetDatasetInfo failed: %v", err, ctx.Data["MsgID"]) | |||
| return nil | |||
| } | |||
| ctx.Data["dataset_name"] = datasetNames | |||
| ctx.Data["branch_name"] = form.BranchName | |||
| ctx.Data["datasetType"] = models.TypeCloudBrainTwo | |||
| waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "") | |||
| ctx.Data["WaitCount"] = waitCount | |||
| setMultiNodeIfConfigureMatch(ctx) | |||
| return nil | |||
| } | |||
| func TrainJobNewVersion(ctx *context.Context) { | |||
| err := trainJobNewVersionDataPrepare(ctx) | |||
| @@ -989,12 +924,7 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { | |||
| ctx.Data["spec_id"] = spec.ID | |||
| } | |||
| var Parameters modelarts.Parameters | |||
| if err = json.Unmarshal([]byte(task.Parameters), &Parameters); err != nil { | |||
| ctx.ServerError("json.Unmarshal failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["params"] = Parameters.Parameter | |||
| ctx.Data["run_para_list"] = task.Parameters | |||
| branches, _, err := ctx.Repo.GitRepo.GetBranches(0, 0) | |||
| if err != nil { | |||
| @@ -1017,104 +947,24 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { | |||
| ctx.Data["work_server_number"] = task.WorkServerNumber | |||
| ctx.Data["flavor_name"] = task.FlavorName | |||
| ctx.Data["engine_name"] = task.EngineName | |||
| ctx.Data["uuid"] = task.Uuid | |||
| ctx.Data["attachment"] = task.Uuid | |||
| ctx.Data["flavor_code"] = task.FlavorCode | |||
| ctx.Data["engine_id"] = task.EngineID | |||
| ctx.Data["datasetType"] = models.TypeCloudBrainTwo | |||
| configList, err := getConfigList(modelarts.PerPage, 1, modelarts.SortByCreateTime, "desc", "", modelarts.ConfigTypeCustom) | |||
| if err != nil { | |||
| ctx.ServerError("getConfigList failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["config_list"] = configList.ParaConfigs | |||
| waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "") | |||
| ctx.Data["WaitCount"] = waitCount | |||
| return nil | |||
| } | |||
| func versionErrorDataPrepare(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) error { | |||
| ctx.Data["PageIsCloudBrain"] = true | |||
| var jobID = ctx.Params(":jobid") | |||
| // var versionName = ctx.Params(":version-name") | |||
| var versionName = ctx.Query("version_name") | |||
| task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainByJobIDAndVersionName(%s) failed:%v", jobID, err.Error()) | |||
| return err | |||
| } | |||
| //pretrain model | |||
| ctx.Data["model_name"] = task.ModelName | |||
| ctx.Data["model_version"] = task.ModelVersion | |||
| ctx.Data["ckpt_name"] = task.CkptName | |||
| ctx.Data["label_names"] = task.LabelName | |||
| ctx.Data["pre_train_model_url"] = task.PreTrainModelUrl | |||
| t := time.Now() | |||
| var jobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
| ctx.Data["job_name"] = task.JobName | |||
| attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||
| if err != nil { | |||
| ctx.ServerError("GetAllUserAttachments failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["attachments"] = attachs | |||
| var resourcePools modelarts.ResourcePool | |||
| if err = json.Unmarshal([]byte(setting.ResourcePools), &resourcePools); err != nil { | |||
| ctx.ServerError("json.Unmarshal failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["resource_pools"] = resourcePools.Info | |||
| var engines modelarts.Engine | |||
| if err = json.Unmarshal([]byte(setting.Engines), &engines); err != nil { | |||
| ctx.ServerError("json.Unmarshal failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["engines"] = engines.Info | |||
| var versionInfos modelarts.VersionInfo | |||
| if err = json.Unmarshal([]byte(setting.EngineVersions), &versionInfos); err != nil { | |||
| ctx.ServerError("json.Unmarshal failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["engine_versions"] = versionInfos.Version | |||
| prepareCloudbrainTwoTrainSpecs(ctx) | |||
| var Parameters modelarts.Parameters | |||
| if err = json.Unmarshal([]byte(form.Params), &Parameters); err != nil { | |||
| ctx.ServerError("json.Unmarshal failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["params"] = Parameters.Parameter | |||
| outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath | |||
| ctx.Data["train_url"] = outputObsPath | |||
| branches, _, err := ctx.Repo.GitRepo.GetBranches(0, 0) | |||
| if err != nil { | |||
| ctx.ServerError("GetBranches error:", err) | |||
| return err | |||
| } | |||
| ctx.Data["branches"] = branches | |||
| ctx.Data["description"] = form.Description | |||
| ctx.Data["dataset_name"] = task.DatasetName | |||
| ctx.Data["work_server_number"] = form.WorkServerNumber | |||
| ctx.Data["flavor_name"] = form.FlavorName | |||
| ctx.Data["engine_name"] = form.EngineName | |||
| ctx.Data["flavor_code"] = task.FlavorCode | |||
| ctx.Data["engine_id"] = task.EngineID | |||
| ctx.Data["version_name"] = form.VersionName | |||
| ctx.Data["bootFile"] = form.BootFile | |||
| ctx.Data["uuid"] = form.Attachment | |||
| ctx.Data["branch_name"] = form.BranchName | |||
| configList, err := getConfigList(modelarts.PerPage, 1, modelarts.SortByCreateTime, "desc", "", modelarts.ConfigTypeCustom) | |||
| if err != nil { | |||
| ctx.ServerError("getConfigList failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["config_list"] = configList.ParaConfigs | |||
| ctx.Data["datasetType"] = models.TypeCloudBrainTwo | |||
| waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "") | |||
| ctx.Data["WaitCount"] = waitCount | |||
| @@ -1148,21 +998,31 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| errStr := checkMultiNode(ctx.User.ID, form.WorkServerNumber) | |||
| if errStr != "" { | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr(errStr), tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeTrain), displayJobName)) | |||
| isOk, err := lock.Lock(models.CloudbrainKeyDuration) | |||
| if !isOk { | |||
| log.Error("lock processed failed:%v", err, ctx.Data["MsgID"]) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| defer lock.UnLock() | |||
| count, err := models.GetCloudbrainTrainJobCountByUserID(ctx.User.ID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainTrainJobCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("system error", tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } else { | |||
| if count >= 1 { | |||
| log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("you have already a running or waiting task, can not create more", tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| @@ -1170,7 +1030,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| if err := paramCheckCreateTrainJob(form); err != nil { | |||
| log.Error("paramCheckCreateTrainJob failed:(%v)", err) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| @@ -1178,7 +1038,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| bootFileExist, err := ctx.Repo.FileExists(bootFile, branchName) | |||
| if err != nil || !bootFileExist { | |||
| log.Error("Get bootfile error:", err) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_bootfile_err"), tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| @@ -1189,7 +1049,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| Cluster: models.OpenICluster, | |||
| AiCenterCode: models.AICenterOfCloudBrainTwo}) | |||
| if err != nil || spec == nil { | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("Resource specification not available", tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| @@ -1205,14 +1065,14 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| if err == nil { | |||
| if len(tasks) != 0 { | |||
| log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("the job name did already exist", tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| } else { | |||
| if !models.IsErrJobNotExist(err) { | |||
| log.Error("system error, %v", err, ctx.Data["MsgID"]) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("system error", tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| @@ -1229,7 +1089,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| if err := downloadCode(repo, codeLocalPath, branchName); err != nil { | |||
| log.Error("downloadCode failed, server timed out: %s (%v)", repo.FullName(), err) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| @@ -1237,14 +1097,14 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| //todo: upload code (send to file_server todo this work?) | |||
| if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.OutputPath + VersionOutputPath + "/"); err != nil { | |||
| log.Error("Failed to obsMkdir_output: %s (%v)", repo.FullName(), err) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("Failed to obsMkdir_output", tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.LogPath + VersionOutputPath + "/"); err != nil { | |||
| log.Error("Failed to obsMkdir_log: %s (%v)", repo.FullName(), err) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("Failed to obsMkdir_log", tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| @@ -1253,7 +1113,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| if err := uploadCodeToObs(codeLocalPath, jobName, ""); err != nil { | |||
| // if err := uploadCodeToObs(codeLocalPath, jobName, parentDir); err != nil { | |||
| log.Error("Failed to uploadCodeToObs: %s (%v)", repo.FullName(), err) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| @@ -1265,7 +1125,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| err := json.Unmarshal([]byte(params), ¶meters) | |||
| if err != nil { | |||
| log.Error("Failed to Unmarshal params: %s (%v)", params, err) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("运行参数错误", tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| @@ -1291,7 +1151,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| datasUrlList, dataUrl, datasetNames, isMultiDataset, err := getDatasUrlListByUUIDS(uuid) | |||
| if err != nil { | |||
| log.Error("Failed to getDatasUrlListByUUIDS: %v", err) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("Failed to getDatasUrlListByUUIDS:"+err.Error(), tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| @@ -1299,7 +1159,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| jsondatas, err := json.Marshal(datasUrlList) | |||
| if err != nil { | |||
| log.Error("Failed to Marshal: %v", err) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("json error:"+err.Error(), tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| @@ -1309,6 +1169,13 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| Value: string(jsondatas), | |||
| }) | |||
| } | |||
| if form.ModelName != "" { //使用预训练模型训练 | |||
| ckptUrl := "/" + form.PreTrainModelUrl + form.CkptName | |||
| param = append(param, models.Parameter{ | |||
| Label: modelarts.CkptUrl, | |||
| Value: "s3:/" + ckptUrl, | |||
| }) | |||
| } | |||
| //save param config | |||
| // if isSaveParam == "on" { | |||
| @@ -1377,6 +1244,15 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| DatasetName: datasetNames, | |||
| Spec: spec, | |||
| } | |||
| if form.ModelName != "" { //使用预训练模型训练 | |||
| req.ModelName = form.ModelName | |||
| req.LabelName = form.LabelName | |||
| req.CkptName = form.CkptName | |||
| req.ModelVersion = form.ModelVersion | |||
| req.PreTrainModelUrl = form.PreTrainModelUrl | |||
| } | |||
| userCommand, userImageUrl := getUserCommand(engineID, req) | |||
| req.UserCommand = userCommand | |||
| req.UserImageUrl = userImageUrl | |||
| @@ -1391,7 +1267,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| err = modelarts.GenerateTrainJob(ctx, req) | |||
| if err != nil { | |||
| log.Error("GenerateTrainJob failed:%v", err.Error()) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| @@ -1476,7 +1352,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| errStr := checkMultiNode(ctx.User.ID, form.WorkServerNumber) | |||
| if errStr != "" { | |||
| versionErrorDataPrepare(ctx, form) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr(errStr), tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -1484,13 +1360,13 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| count, err := models.GetCloudbrainTrainJobCountByUserID(ctx.User.ID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainTrainJobCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||
| versionErrorDataPrepare(ctx, form) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr("system error", tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } else { | |||
| if count >= 1 { | |||
| log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) | |||
| versionErrorDataPrepare(ctx, form) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr("you have already a running or waiting task, can not create more", tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -1525,16 +1401,26 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| EngineName := form.EngineName | |||
| isLatestVersion := modelarts.IsLatestVersion | |||
| lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeTrain), displayJobName)) | |||
| isOk, err := lock.Lock(models.CloudbrainKeyDuration) | |||
| if !isOk { | |||
| log.Error("lock processed failed:%v", err, ctx.Data["MsgID"]) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| defer lock.UnLock() | |||
| canNewJob, _ := canUserCreateTrainJobVersion(ctx, latestTask.UserID) | |||
| if !canNewJob { | |||
| versionErrorDataPrepare(ctx, form) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr("user cann't new trainjob", tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| if err := paramCheckCreateTrainJob(form); err != nil { | |||
| log.Error("paramCheckCreateTrainJob failed:(%v)", err) | |||
| versionErrorDataPrepare(ctx, form) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -1542,7 +1428,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| bootFileExist, err := ctx.Repo.FileExists(bootFile, branchName) | |||
| if err != nil || !bootFileExist { | |||
| log.Error("Get bootfile error:", err) | |||
| versionErrorDataPrepare(ctx, form) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_bootfile_err"), tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -1553,13 +1439,13 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| Cluster: models.OpenICluster, | |||
| AiCenterCode: models.AICenterOfCloudBrainTwo}) | |||
| if err != nil || spec == nil { | |||
| versionErrorDataPrepare(ctx, form) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr("Resource specification not available", tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) { | |||
| log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID) | |||
| versionErrorDataPrepare(ctx, form) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -1574,7 +1460,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| commitID, _ := gitRepo.GetBranchCommitID(branchName) | |||
| if err := downloadCode(repo, codeLocalPath, branchName); err != nil { | |||
| log.Error("Failed git clone repo to local(!: %s (%v)", repo.FullName(), err) | |||
| versionErrorDataPrepare(ctx, form) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -1582,14 +1468,14 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| //todo: upload code (send to file_server todo this work?) | |||
| if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.OutputPath + VersionOutputPath + "/"); err != nil { | |||
| log.Error("Failed to obsMkdir_output: %s (%v)", repo.FullName(), err) | |||
| versionErrorDataPrepare(ctx, form) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr("Failed to obsMkdir_output", tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.LogPath + VersionOutputPath + "/"); err != nil { | |||
| log.Error("Failed to obsMkdir_log: %s (%v)", repo.FullName(), err) | |||
| versionErrorDataPrepare(ctx, form) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr("Failed to obsMkdir_log", tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -1599,7 +1485,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| // if err := uploadCodeToObs(codeLocalPath, jobName, ""); err != nil { | |||
| if err := uploadCodeToObs(codeLocalPath, jobName, parentDir); err != nil { | |||
| log.Error("Failed to uploadCodeToObs: %s (%v)", repo.FullName(), err) | |||
| versionErrorDataPrepare(ctx, form) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr("cloudbrain.load_code_failed"), tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -1613,7 +1499,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| err := json.Unmarshal([]byte(params), ¶meters) | |||
| if err != nil { | |||
| log.Error("Failed to Unmarshal params: %s (%v)", params, err) | |||
| versionErrorDataPrepare(ctx, form) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr("运行参数错误", tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -1639,7 +1525,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| datasUrlList, dataUrl, datasetNames, isMultiDataset, err := getDatasUrlListByUUIDS(uuid) | |||
| if err != nil { | |||
| log.Error("Failed to getDatasUrlListByUUIDS: %v", err) | |||
| versionErrorDataPrepare(ctx, form) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr("Failed to getDatasUrlListByUUIDS:"+err.Error(), tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -1647,7 +1533,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| jsondatas, err := json.Marshal(datasUrlList) | |||
| if err != nil { | |||
| log.Error("Failed to Marshal: %v", err) | |||
| versionErrorDataPrepare(ctx, form) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr("json error:"+err.Error(), tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -1658,46 +1544,14 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| }) | |||
| } | |||
| // //save param config | |||
| // if isSaveParam == "on" { | |||
| // saveparams := append(param, models.Parameter{ | |||
| // Label: modelarts.TrainUrl, | |||
| // Value: outputObsPath, | |||
| // }, models.Parameter{ | |||
| // Label: modelarts.DataUrl, | |||
| // Value: dataPath, | |||
| // }) | |||
| // if form.ParameterTemplateName == "" { | |||
| // log.Error("ParameterTemplateName is empty") | |||
| // versionErrorDataPrepare(ctx, form) | |||
| // ctx.RenderWithErr("保存作业参数时,作业参数名称不能为空", tplModelArtsTrainJobVersionNew, &form) | |||
| // return | |||
| // } | |||
| // _, err := modelarts.CreateTrainJobConfig(models.CreateConfigParams{ | |||
| // ConfigName: form.ParameterTemplateName, | |||
| // Description: form.PrameterDescription, | |||
| // DataUrl: dataPath, | |||
| // AppUrl: codeObsPath, | |||
| // BootFileUrl: codeObsPath + bootFile, | |||
| // TrainUrl: outputObsPath, | |||
| // Flavor: models.Flavor{ | |||
| // Code: flavorCode, | |||
| // }, | |||
| // WorkServerNum: workServerNumber, | |||
| // EngineID: int64(engineID), | |||
| // LogUrl: logObsPath, | |||
| // PoolID: poolID, | |||
| // Parameter: saveparams, | |||
| // }) | |||
| if form.ModelName != "" { //使用预训练模型训练 | |||
| ckptUrl := "/" + form.PreTrainModelUrl + form.CkptName | |||
| param = append(param, models.Parameter{ | |||
| Label: modelarts.CkptUrl, | |||
| Value: "s3:/" + ckptUrl, | |||
| }) | |||
| } | |||
| // if err != nil { | |||
| // log.Error("Failed to CreateTrainJobConfig: %v", err) | |||
| // versionErrorDataPrepare(ctx, form) | |||
| // ctx.RenderWithErr("保存作业参数失败:"+err.Error(), tplModelArtsTrainJobVersionNew, &form) | |||
| // return | |||
| // } | |||
| // } | |||
| task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, PreVersionName) | |||
| if err != nil { | |||
| @@ -1732,6 +1586,15 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| DatasetName: datasetNames, | |||
| Spec: spec, | |||
| } | |||
| if form.ModelName != "" { //使用预训练模型训练 | |||
| req.ModelName = form.ModelName | |||
| req.LabelName = form.LabelName | |||
| req.CkptName = form.CkptName | |||
| req.ModelVersion = form.ModelVersion | |||
| req.PreTrainModelUrl = form.PreTrainModelUrl | |||
| } | |||
| userCommand, userImageUrl := getUserCommand(engineID, req) | |||
| req.UserCommand = userCommand | |||
| req.UserImageUrl = userImageUrl | |||
| @@ -1739,7 +1602,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| err = modelarts.GenerateTrainJobVersion(ctx, req, jobID) | |||
| if err != nil { | |||
| log.Error("GenerateTrainJob failed:%v", err.Error()) | |||
| versionErrorDataPrepare(ctx, form) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -2136,6 +1999,16 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference | |||
| return | |||
| } | |||
| lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeInference), displayJobName)) | |||
| isOk, err := lock.Lock(models.CloudbrainKeyDuration) | |||
| if !isOk { | |||
| log.Error("lock processed failed:%v", err, ctx.Data["MsgID"]) | |||
| inferenceJobErrorNewDataPrepare(ctx, form) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tplModelArtsInferenceJobNew, &form) | |||
| return | |||
| } | |||
| defer lock.UnLock() | |||
| count, err := models.GetCloudbrainInferenceJobCountByUserID(ctx.User.ID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainInferenceJobCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||
| @@ -8,6 +8,7 @@ import ( | |||
| "code.gitea.io/gitea/routers/response" | |||
| "code.gitea.io/gitea/services/reward" | |||
| "code.gitea.io/gitea/services/reward/point/account" | |||
| "code.gitea.io/gitea/services/task" | |||
| "errors" | |||
| "net/http" | |||
| ) | |||
| @@ -92,6 +93,17 @@ func GetRulePage(ctx *context.Context) { | |||
| ctx.HTML(200, tplPointRule) | |||
| } | |||
| func GetRuleConfig(ctx *context.Context) { | |||
| r, err := task.GetPointRule() | |||
| if err != nil { | |||
| log.Error("GetRuleConfig error.%v", err) | |||
| ctx.JSON(http.StatusOK, response.ServerError(err.Error())) | |||
| return | |||
| } | |||
| ctx.JSON(http.StatusOK, response.SuccessWithData(r)) | |||
| } | |||
| func GetAdminRewardList(ctx *context.Context) { | |||
| opts, err := buildAdminRewardRecordListOpts(ctx) | |||
| if err != nil { | |||
| @@ -1159,6 +1159,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Get("/download_model", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.CloudBrainDownloadModel) | |||
| //m.Get("/get_log", cloudbrain.AdminOrJobCreaterRightForTrain, repo.GetLogFromModelDir) | |||
| //m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), repo.TrainJobCreateVersion) | |||
| m.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, repo.CloudBrainTrainJobVersionNew) | |||
| m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateCloudBrainForm{}), repo.CloudBrainTrainJobVersionCreate) | |||
| }) | |||
| m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.CloudBrainTrainJobNew) | |||
| m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainForm{}), repo.CloudBrainCreate) | |||
| @@ -1181,6 +1183,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.GrampusStopJob) | |||
| m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.GrampusTrainJobDel) | |||
| m.Get("/model_download", cloudbrain.AdminOrJobCreaterRightForTrain, repo.ModelDownload) | |||
| m.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, repo.GrampusTrainJobVersionNew) | |||
| m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateGrampusTrainJobForm{}), repo.GrampusTrainJobVersionCreate) | |||
| }) | |||
| m.Group("/gpu", func() { | |||
| m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.GrampusTrainJobGPUNew) | |||
| @@ -1435,6 +1439,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Group("/reward/point", func() { | |||
| m.Get("", point.GetPointPage) | |||
| m.Get("/rule", point.GetRulePage) | |||
| m.Get("/rule/config", point.GetRuleConfig) | |||
| m.Get("/account", point.GetPointAccount) | |||
| m.Get("/record/list", point.GetPointRecordList) | |||
| }, reqSignIn) | |||
| @@ -11,7 +11,7 @@ import ( | |||
| func GetSerialNoByRedis() (string, error) { | |||
| now := time.Now() | |||
| r := int64(rand.Intn(4)) + 1 | |||
| r := int64(rand.Intn(3)) + 1 | |||
| n, err := redis_client.IncrBy(redis_key.RewardSerialCounter(now), r) | |||
| if err != nil { | |||
| log.Error("GetSerialNoByRedis RewardSerialCounter error. %v", err) | |||
| @@ -20,5 +20,9 @@ func GetSerialNoByRedis() (string, error) { | |||
| if n == r { | |||
| redis_client.Expire(redis_key.RewardSerialCounter(now), 2*time.Minute) | |||
| } | |||
| //when the counter n exceeds 1000, the length of the serial number will become longer | |||
| if n >= 1000 { | |||
| return now.Format("200601021504") + fmt.Sprintf("%d", n) + fmt.Sprint(rand.Intn(10)), nil | |||
| } | |||
| return now.Format("200601021504") + fmt.Sprintf("%03d", n) + fmt.Sprint(rand.Intn(10)), nil | |||
| } | |||
| @@ -6,8 +6,10 @@ import ( | |||
| "code.gitea.io/gitea/modules/redis/redis_client" | |||
| "code.gitea.io/gitea/modules/redis/redis_key" | |||
| "code.gitea.io/gitea/modules/redis/redis_lock" | |||
| "code.gitea.io/gitea/services/reward/limiter" | |||
| "encoding/json" | |||
| "errors" | |||
| "fmt" | |||
| "time" | |||
| ) | |||
| @@ -181,3 +183,46 @@ func DelTaskConfig(id int64, doer *models.User) error { | |||
| redis_client.Del(redis_key.TaskConfigList()) | |||
| return nil | |||
| } | |||
| func GetPointRule() (*models.PointRule, error) { | |||
| r, err := limiter.GetSingleDailyPointLimitConfig() | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| limiters, err := limiter.GetLimitersByLimitType(models.LimitTypeTask) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| limiterMap := make(map[string]*models.LimitConfig, 0) | |||
| for i := 0; i < len(limiters); i++ { | |||
| limiterMap[limiters[i].LimitCode] = &limiters[i] | |||
| } | |||
| taskConfigs, err := GetTaskConfigList() | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| taskRules := make([]models.TaskRule, len(taskConfigs)) | |||
| for i, taskConfig := range taskConfigs { | |||
| rule := models.TaskRule{ | |||
| TaskCode: taskConfig.TaskCode, | |||
| AwardType: taskConfig.AwardType, | |||
| AwardAmount: taskConfig.AwardAmount, | |||
| } | |||
| limiter := limiterMap[fmt.Sprint(taskConfig.TaskCode)] | |||
| if limiter != nil { | |||
| rule.RefreshRate = limiter.RefreshRate | |||
| rule.LimitNum = limiter.LimitNum | |||
| } | |||
| taskRules[i] = rule | |||
| } | |||
| pointRule := &models.PointRule{ | |||
| TaskRules: taskRules, | |||
| } | |||
| if r != nil { | |||
| pointRule.UserDailyLimit = r.LimitNum | |||
| } | |||
| return pointRule, nil | |||
| } | |||
| @@ -259,6 +259,14 @@ | |||
| </a> | |||
| {{end}} | |||
| </div> | |||
| <!-- 修改任务 --> | |||
| {{if eq .JobType "TRAIN"}} | |||
| <div class="ui compact buttons"> | |||
| <a style="padding: 0.5rem 1rem;" class="ui basic blue button" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 1}}/modelarts/train-job/{{.JobID}}{{else if eq .Cloudbrain.Type 0}}/cloudbrain/train-job/{{.JobID}}{{else if eq .Cloudbrain.Type 2}}/grampus/train-job/{{.JobID}}{{end}}/create_version{{if .VersionName}}?version_name={{.VersionName}}{{end}}"> | |||
| {{$.i18n.Tr "repo.modelarts.modify"}} | |||
| </a> | |||
| </div> | |||
| {{end}} | |||
| <!-- 删除任务 --> | |||
| <form class="ui compact buttons" id="delForm-{{$JobID}}" | |||
| action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE")}}/cloudbrain{{else if eq .JobType "DEBUG"}}{{if eq .ComputeResource "NPU"}}/modelarts/notebook{{else}}/cloudbrain{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .Cloudbrain.Type 1}}/modelarts/train-job{{else if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}/grampus/train-job{{end}}{{else if eq .JobType "INFERENCE"}}{{if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{end}}{{end}}/{{$JobID}}/del?isadminpage=true' | |||
| @@ -20,7 +20,7 @@ | |||
| <div class="column ui vertical text menu"> | |||
| <div class="header item">{{.i18n.Tr "custom.foot.help"}}</div> | |||
| <div class="ui language bottom floating slide up dropdown link item"> | |||
| <i class="world icon"></i> | |||
| <i class="globe icon"></i> | |||
| <div class="text">{{.LangName}}</div> | |||
| <div class="menu"> | |||
| {{range .AllLangs}} | |||
| @@ -29,12 +29,12 @@ | |||
| </div> | |||
| </div> | |||
| <a href="https://git.openi.org.cn/zeizei/OpenI_Learning" class=" item a_margin" target="_blank"><i class="ri-creative-commons-by-line footer_icon" ></i><p class="footer_icon">{{.i18n.Tr "custom.Platform_Tutorial"}}</p> </a> | |||
| {{if .EnableSwagger}}<a href="/api/swagger" class=" item a_margin"><i class="ri-exchange-line footer_icon" > </i><p class="footer_icon">API</p> </a>{{end}} | |||
| <a href="https://git.openi.org.cn/zeizei/OpenI_Learning" class="item" target="_blank"><i class="compass icon" ></i> {{.i18n.Tr "custom.Platform_Tutorial"}}</a> | |||
| {{if .EnableSwagger}}<a href="/api/swagger" class="item"><i class="plug icon"></i> API</a>{{end}} | |||
| {{if .IsSigned}} | |||
| <a href="https://git.openi.org.cn/zeizei/OpenI_Learning/issues/new" class=" item a_margin" target="_blank"><i class="ri-mail-send-line footer_icon"></i><p class="footer_icon">{{.i18n.Tr "custom.foot.advice_feedback"}}</p></a> | |||
| <a href="https://git.openi.org.cn/zeizei/OpenI_Learning/issues/new" class="item" target="_blank"><i class="envelope icon"></i> {{.i18n.Tr "custom.foot.advice_feedback"}}</a> | |||
| {{else}} | |||
| <a href="{{AppSubUrl}}/user/login" class=" item a_margin" ><i class="ri-mail-send-line footer_icon" ></i><p class="footer_icon">{{.i18n.Tr "custom.foot.advice_feedback"}}</p></a> | |||
| <a href="{{AppSubUrl}}/user/login" class="item"><i class="envelope icon"></i> {{.i18n.Tr "custom.foot.advice_feedback"}}</a> | |||
| {{end}} | |||
| {{template "custom/extra_links_footer" .}} | |||
| @@ -18,7 +18,7 @@ | |||
| <div class="column ui vertical text menu"> | |||
| <div class="header item">{{.i18n.Tr "custom.foot.help"}}</div> | |||
| <div class="ui language bottom floating slide up dropdown link item"> | |||
| <i class="world icon"></i> | |||
| <i class="globe icon"></i> | |||
| <div class="text">{{.LangName}}</div> | |||
| <div class="menu"> | |||
| {{range .AllLangs}} | |||
| @@ -26,12 +26,12 @@ | |||
| {{end}} | |||
| </div> | |||
| </div> | |||
| <a href="https://git.openi.org.cn/zeizei/OpenI_Learning" class=" item a_margin" target="_blank"><i class="ri-creative-commons-by-line footer_icon" ></i><p class="footer_icon">{{.i18n.Tr "custom.Platform_Tutorial"}}</p> </a> | |||
| {{if .EnableSwagger}}<a href="/api/swagger" class=" item a_margin"><i class="ri-exchange-line footer_icon" > </i><p class="footer_icon">API</p> </a>{{end}} | |||
| <a href="https://git.openi.org.cn/zeizei/OpenI_Learning" class="item" target="_blank"><i class="compass icon"></i> {{.i18n.Tr "custom.Platform_Tutorial"}} </a> | |||
| {{if .EnableSwagger}}<a href="/api/swagger" class="item"><i class="plug icon" ></i> API</a>{{end}} | |||
| {{if .IsSigned}} | |||
| <a href="https://git.openi.org.cn/zeizei/OpenI_Learning/issues/new" class=" item a_margin" target="_blank"><i class="ri-mail-send-line footer_icon"></i><p class="footer_icon">{{.i18n.Tr "custom.foot.advice_feedback"}}</p></a> | |||
| <a href="https://git.openi.org.cn/zeizei/OpenI_Learning/issues/new" class="item" target="_blank"><i class="envelope icon"></i> {{.i18n.Tr "custom.foot.advice_feedback"}}</a> | |||
| {{else}} | |||
| <a href="{{AppSubUrl}}/user/login" class=" item a_margin" ><i class="ri-mail-send-line footer_icon" ></i><p class="footer_icon footer_icon">{{.i18n.Tr "custom.foot.advice_feedback"}}</p></a> | |||
| <a href="{{AppSubUrl}}/user/login" class="item"><i class="envelope icon"></i> {{.i18n.Tr "custom.foot.advice_feedback"}}</a> | |||
| {{end}} | |||
| {{template "custom/extra_links_footer" .}} | |||
| </div> | |||
| @@ -0,0 +1,37 @@ | |||
| <input type="hidden" id="ai_model_version" name="model_version" value="{{$.model_version}}"> | |||
| <div class="inline min_title fields" style="{{if not .job_name}}width: 96.8%{{else}}width: 94.8%{{end}};"> | |||
| <label class="{{if not .job_name}}label-fix-width{{end}}" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.infer_job.select_model"}}</label> | |||
| <div class="six wide field"> | |||
| <div class="ui fluid search selection dropdown" id="select_model"> | |||
| <input type="hidden" name="model_name" required value="{{$.model_name}}"> | |||
| <div class="text"></div> | |||
| <i class="dropdown icon"></i> | |||
| <div class="menu" id="model_name"> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="three wide field"> | |||
| <div class="ui fluid search selection dropdown" id="select_model_version"> | |||
| <input type="hidden" name="pre_train_model_url" value="{{$.pre_train_model_url}}" required> | |||
| <div class="text"></div> | |||
| <i class="dropdown icon"></i> | |||
| <div class="menu" id="model_name_version"> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="five wide field"> | |||
| <div class="ui fluid search selection dropdown" id="select_model_checkpoint"> | |||
| <input type="hidden" name="ckpt_name" value="{{$.ckpt_name}}" required> | |||
| <div class="text"></div> | |||
| <i class="dropdown icon"></i> | |||
| <div class="menu" id="model_checkpoint"> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <span > | |||
| <i class="question circle icon" data-content="{{.i18n.Tr "cloudbrain.model_file_postfix_rule"}}" data-position="top center" data-variation="inverted mini"></i> | |||
| </span> | |||
| </div> | |||
| @@ -70,7 +70,7 @@ | |||
| <div class="repository"> | |||
| {{template "repo/header" .}} | |||
| <div class="ui container"> | |||
| <div class="cloudbrain-type" style="display: none;" data-cloudbrain-type="{{.datasetType}}" data-repo-link="{{.RepoLink}}" data-queue="{{.QueuesDetail}}" data-queue-start="{{.i18n.Tr "repo.wait_count_start"}}" data-queue-end="{{.i18n.Tr "repo.wait_count_end"}}"></div> | |||
| <div class="cloudbrain-type" style="display: none;" data-cloudbrain-type="{{.datasetType}}" data-repo-link="{{.RepoLink}}" data-flag-model="true" data-dataset-uuid="{{.attachment}}" data-dataset-name="{{.dataset_name}}" data-queue="{{.QueuesDetail}}" data-queue-start="{{.i18n.Tr "repo.wait_count_start"}}" data-queue-end="{{.i18n.Tr "repo.wait_count_end"}}"></div> | |||
| {{template "base/alert" .}} | |||
| <h4 class="ui top attached header"> | |||
| {{.i18n.Tr "repo.modelarts.train_job.new"}} | |||
| @@ -125,15 +125,14 @@ | |||
| <span style="color: #888;font-size: 12px;">{{.i18n.Tr "cloudbrain.new_train_gpu_tooltips" "/code" "/dataset" "/model" | Safe}}</span> | |||
| </div> | |||
| </div> | |||
| <div class="required min_title inline field"> | |||
| <div class="required min_title inline field" style="margin-bottom: 0rem !important;"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||
| <input style="width: 60%;" name="display_job_name" id="display_job_name" | |||
| placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}" | |||
| tabindex="3" onkeyup="this.value=this.value.replace(/[, ]/g,'')" autofocus required | |||
| maxlength="36"> | |||
| <span class="tooltips" style="display: block;margin-left: 11.5rem;">{{.i18n.Tr "repo.cloudbrain_jobname_err"}}</span> | |||
| </div> | |||
| <span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 2rem;">{{.i18n.Tr "repo.cloudbrain_jobname_err"}}</span> | |||
| <div class="inline min_title field"> | |||
| <label class="label-fix-width" style="font-weight: normal;" | |||
| for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}}</label> | |||
| @@ -168,7 +167,7 @@ | |||
| {{end}} | |||
| </select> | |||
| </div> | |||
| {{template "custom/select_model" .}} | |||
| <div class="inline required field" style="display: none;"> | |||
| <label>{{.i18n.Tr "cloudbrain.task_type"}}</label> | |||
| <select id="cloudbrain_job_type" class="ui search dropdown" placeholder="选择任务类型" style='width:385px' | |||
| @@ -176,28 +175,6 @@ | |||
| <option name="job_type" value="TRAIN">TRAIN</option> | |||
| </select> | |||
| </div> | |||
| <!--<div class="required min_title inline field"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.gpu_type"}}</label> | |||
| <select id="cloudbrain_gpu_type" class="ui search width806 dropdown gpu-type" placeholder="选择GPU类型" | |||
| style='width:385px' name="gpu_type"> | |||
| {{if .gpu_type}} | |||
| {{range .train_gpu_types}} | |||
| {{if eq $.gpu_type .Queue}} | |||
| <option value="{{.Queue}}">{{.Value}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| {{range .train_gpu_types}} | |||
| {{if ne $.gpu_type .Queue}} | |||
| <option value="{{.Queue}}">{{.Value}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| {{else}} | |||
| {{range .train_gpu_types}} | |||
| <option value="{{.Queue}}">{{.Value}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| </select> | |||
| </div>--> | |||
| <div id="images-new-cb"> | |||
| </div> | |||
| @@ -228,33 +205,10 @@ | |||
| style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i | |||
| class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | |||
| <input id="store_run_para" type="hidden" name="run_para_list"> | |||
| <div class="dynamic field" style="margin-top: 1rem;" data-params="{{.run_para_list}}"> | |||
| <div class="dynamic field" style="margin-top: 1rem;" data-params="{{.run_para_list}}" data-params-value="{{.i18n.Tr "repo.modelarts.train_job.parameter_value"}}" data-params-name="{{.i18n.Tr "repo.modelarts.train_job.parameter_name"}}"> | |||
| </div> | |||
| </div> | |||
| <!--<div class="required min_title inline field"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label> | |||
| <select id="cloudbrain_resource_spec" class="ui search dropdown" placeholder="选择资源规格" | |||
| style='width:385px' name="resource_spec_id"> | |||
| {{if .resource_spec_id}} | |||
| {{range .train_resource_specs}} | |||
| {{if eq $.resource_spec_id .Id}} | |||
| <option value="{{.Id}}">{{$.i18n.Tr "cloudbrain.gpu_num"}}:{{.GpuNum}},{{$.i18n.Tr "cloudbrain.cpu_num"}}:{{.CpuNum}},{{$.i18n.Tr "cloudbrain.memory"}}(MB):{{.MemMiB}},{{$.i18n.Tr "cloudbrain.shared_memory"}}(MB):{{.ShareMemMiB}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| {{range .train_resource_specs}} | |||
| {{if ne $.resource_spec_id .Id}} | |||
| <option value="{{.Id}}">{{$.i18n.Tr "cloudbrain.gpu_num"}}:{{.GpuNum}},{{$.i18n.Tr "cloudbrain.cpu_num"}}:{{.CpuNum}},{{$.i18n.Tr "cloudbrain.memory"}}(MB):{{.MemMiB}},{{$.i18n.Tr "cloudbrain.shared_memory"}}(MB):{{.ShareMemMiB}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| {{else}} | |||
| {{range .train_resource_specs}} | |||
| <option name="resource_spec_id" value="{{.Id}}"> | |||
| {{$.i18n.Tr "cloudbrain.gpu_num"}}:{{.GpuNum}},{{$.i18n.Tr "cloudbrain.cpu_num"}}:{{.CpuNum}},{{$.i18n.Tr "cloudbrain.memory"}}(MB):{{.MemMiB}},{{$.i18n.Tr "cloudbrain.shared_memory"}}(MB):{{.ShareMemMiB}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| </select> | |||
| </div>--> | |||
| <div class="required min_title inline field"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label> | |||
| @@ -290,166 +244,8 @@ | |||
| </div> | |||
| {{template "base/footer" .}} | |||
| <script src="{{StaticUrlPrefix}}/js/specsuse.js?v={{MD5 AppVer}}" type="text/javascript"></script> | |||
| <script src="{{StaticUrlPrefix}}/js/cloudbrainNew.js?v={{MD5 AppVer}}" type="text/javascript"></script> | |||
| <script> | |||
| let form = document.getElementById('form_id'); | |||
| let createFlag = false | |||
| form.onsubmit = function (e) { | |||
| if(createFlag) return false | |||
| createFlag = true | |||
| } | |||
| $('select.dropdown') | |||
| .dropdown(); | |||
| $('.menu .item') | |||
| .tab(); | |||
| $(document).keydown(function(event){ | |||
| switch(event.keyCode){ | |||
| case 13:return false; | |||
| } | |||
| }); | |||
| $(document).ready(function(){ | |||
| let params = $('.dynamic.field').data('params') | |||
| params&¶ms.parameter.forEach((item,index)=>{ | |||
| Add_parameter(index,flag=true,item) | |||
| }) | |||
| }) | |||
| // 参数增加、删除、修改、保存 | |||
| function Add_parameter(i,flag=false,paramsObject={}) { | |||
| let value = '' | |||
| value += `<div class="two fields width85" id= "para${i}">` | |||
| value += '<div class="field">' | |||
| let placeholder_value='{{.i18n.Tr "repo.modelarts.train_job.parameter_value"}}' | |||
| let placeholder_name='{{.i18n.Tr "repo.modelarts.train_job.parameter_name"}}' | |||
| if(flag){ | |||
| value +=`<input type="text" class="shipping_first-name" value="${paramsObject.label}">` | |||
| }else{ | |||
| value +='<input type="text" class="shipping_first-name" required placeholder="' + placeholder_name+ '">' | |||
| } | |||
| value += '</div>' | |||
| value += '<div class="field">' | |||
| if(flag){ | |||
| value +=`<input type="text" class="shipping_last-name" value="${paramsObject.value}">` | |||
| }else{ | |||
| value +='<input type="text" class="shipping_last-name" required placeholder="' + placeholder_value + '">' | |||
| } | |||
| value += '</div>' | |||
| value += '<span><i class="trash icon"></i></span>' | |||
| value += '</div>' | |||
| $(".dynamic.field").append(value) | |||
| } | |||
| $('#add_run_para').click(function () { | |||
| var len = $(".dynamic.field .two.fields").length | |||
| Add_parameter(len) | |||
| }); | |||
| $(".dynamic.field").on("click", ".trash.icon", function () { | |||
| var index = $(this).parent().parent().index() | |||
| $(this).parent().parent().remove() | |||
| var len = $(".dynamic.field .two.fields").length | |||
| $(".dynamic.field .two.fields").each(function () { | |||
| var cur_index = $(this).index() | |||
| $(this).attr('id', 'para' + cur_index) | |||
| }) | |||
| }); | |||
| $('.question.circle.icon').hover(function () { | |||
| $(this).popup('show') | |||
| }); | |||
| $('select.dropdown') | |||
| .dropdown(); | |||
| var isValidate = false; | |||
| function validate() { | |||
| $('.ui.form') | |||
| .form({ | |||
| on: 'blur', | |||
| fields: { | |||
| boot_file: { | |||
| identifier: 'boot_file', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/.+\.py$/g]', | |||
| } | |||
| ] | |||
| }, | |||
| display_job_name: { | |||
| identifier: 'display_job_name', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/]', | |||
| } | |||
| ] | |||
| }, | |||
| attachment: { | |||
| identifier: 'attachment', | |||
| rules: [ | |||
| { | |||
| type: 'empty', | |||
| } | |||
| ] | |||
| }, | |||
| work_server_number: { | |||
| identifier: 'work_server_number', | |||
| rules: [ | |||
| { | |||
| type: 'integer[1..25]', | |||
| } | |||
| ] | |||
| }, | |||
| branch_name: { | |||
| identifier: 'branch_name', | |||
| rules: [ | |||
| { | |||
| type: 'empty', | |||
| } | |||
| ] | |||
| }, | |||
| spec_id: { | |||
| identifier: 'spec_id', | |||
| rules: [{ type: 'empty' }] | |||
| } | |||
| }, | |||
| onSuccess: function () { | |||
| // $('.ui.page.dimmer').dimmer('show') | |||
| document.getElementById("mask").style.display = "block" | |||
| isValidate = true; | |||
| }, | |||
| onFailure: function (e) { | |||
| isValidate = false; | |||
| return false; | |||
| } | |||
| }) | |||
| } | |||
| document.onreadystatechange = function () { | |||
| if (document.readyState === "complete") { | |||
| document.getElementById("mask").style.display = "none" | |||
| } | |||
| } | |||
| function send_run_para() { | |||
| var run_parameters = [] | |||
| var msg = {} | |||
| $(".dynamic.field .two.fields").each(function () { | |||
| var para_name = $(this).find('input.shipping_first-name').val() | |||
| var para_value = $(this).find('input.shipping_last-name').val() | |||
| run_parameters.push({ "label": para_name, "value": para_value }) | |||
| }) | |||
| msg["parameter"] = run_parameters | |||
| msg = JSON.stringify(msg) | |||
| $('#store_run_para').val(msg) | |||
| } | |||
| validate(); | |||
| $('.ui.create_train_job.green.button').click(function (e) { | |||
| send_run_para(); | |||
| validate(); | |||
| }) | |||
| ;(function() { | |||
| var SPECS = {{ .train_specs }}; | |||
| var showPoint = {{ .CloudBrainPaySwitch }}; | |||
| @@ -251,12 +251,11 @@ | |||
| <span class="accordion-panel-title-content"> | |||
| <span> | |||
| <div style="float: right;"> | |||
| {{if and ($.canDownload) (eq .Status "SUCCEEDED") ($.Permission.CanWrite $.UnitTypeModelManage) }} | |||
| {{if and ($.canDownload) (ne .Status "WAITING") ($.Permission.CanWrite $.UnitTypeModelManage) }} | |||
| <a class="ti-action-menu-item" id="{{.VersionName}}-create-model" | |||
| onclick="showcreate({{.}})">{{$.i18n.Tr "repo.modelarts.create_model"}}</a> | |||
| {{else}} | |||
| <a class="ti-action-menu-item disabled" id="{{.VersionName}}-create-model" | |||
| onclick="showcreate({{.}})">{{$.i18n.Tr "repo.modelarts.create_model"}}</a> | |||
| <a class="ti-action-menu-item disabled" id="{{.VersionName}}-create-model">{{$.i18n.Tr "repo.modelarts.create_model"}}</a> | |||
| {{end}} | |||
| </div> | |||
| @@ -632,7 +631,7 @@ | |||
| <label for="modelSelectedFile">{{.i18n.Tr "repo.model.manage.modelfile"}}</label> | |||
| </div> | |||
| <div class="thirteen wide field" style="position:relative"> | |||
| <input id="modelSelectedFile" type="text" readonly required onclick="showMenu();" name="modelSelectedFile" > | |||
| <input id="modelSelectedFile" type="text" readonly required onclick="showMenu();" name="modelSelectedFile"> | |||
| <div id="menuContent" class="menuContent" style="display:none;"> | |||
| <ul id="treeDemo" class="ztree"></ul> | |||
| </div> | |||
| @@ -838,6 +837,10 @@ | |||
| .modal('show') | |||
| } | |||
| function createModel() { | |||
| if(!$('input#modelSelectedFile').val()){ | |||
| $('input#modelSelectedFile').parent().addClass('error') | |||
| return | |||
| } | |||
| let url_href = `/${userName}/${repoPath}/modelmanage/create_new_model` | |||
| let data = $("#formId").serialize() | |||
| $("#mask").css({ "display": "block", "z-index": "9999" }) | |||
| @@ -62,20 +62,20 @@ | |||
| <div class="repository"> | |||
| {{template "repo/header" .}} | |||
| <div class="ui container"> | |||
| <div class="cloudbrain-type" style="display: none;" data-cloudbrain-type="{{.datasetType}}" data-repo-link="{{.RepoLink}}" data-flag-model="true" data-dataset-uuid="{{.attachment}}" data-dataset-name="{{.dataset_name}}"></div> | |||
| {{template "base/alert" .}} | |||
| <h4 class="ui top attached header"> | |||
| {{.i18n.Tr "repo.modelarts.train_job.new"}} | |||
| </h4> | |||
| <div class="ui attached segment"> | |||
| <!-- equal width --> | |||
| <form id="form_id" class="ui form" action="{{.Link}}" method="post"> | |||
| <form id="form_id" class="ui form" action="{{.Link}}{{if not .IsCreate}}?compute_resource=CPU/GPU{{end}}" method="post"> | |||
| {{.CsrfTokenHtml}} | |||
| <input type="hidden" name="action" value="update"> | |||
| <input type="hidden" id="ai_engine_name" name="engine_name" value=""> | |||
| <input type="hidden" id="ai_flavor_name" name="flavor_name" value=""> | |||
| <input type="hidden" id="ai_image_name" value="{{.image}}"> | |||
| <input type="hidden" id="fail_dataset_name" value="{{$.dataset_name}}"> | |||
| <input type="hidden" id="fail_dataset_uuid" value="{{$.attachment}}"> | |||
| <h4 class="train-job-title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4> | |||
| <div class="required min_title inline field"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_cluster"}}</label> | |||
| @@ -116,12 +116,12 @@ | |||
| <span style="color: #888;font-size: 12px;">{{.i18n.Tr "cloudbrain.new_train_gpu_tooltips" "/tmp/code" "/tmp/dataset" "/tmp/output" | Safe}}</span> | |||
| </div> | |||
| </div> | |||
| <div class="required min_title inline field"> | |||
| <div class="required min_title inline field" style="margin-bottom: 0rem !important;"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||
| <input style="width: 60%;" name="display_job_name" id="display_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}" tabindex="3" onkeyup="this.value=this.value.replace(/[, ]/g,'')" autofocus required maxlength="36"> | |||
| <span class="tooltips" style="margin-left: 11.5rem;display: block;">{{.i18n.Tr "repo.cloudbrain_jobname_err"}}</span> | |||
| </div> | |||
| <span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 2rem;">{{.i18n.Tr "repo.cloudbrain_jobname_err"}}</span> | |||
| <div class="min_title inline field"> | |||
| <label class="label-fix-width" style="font-weight: normal;" for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}}</label> | |||
| {{if .description}} | |||
| @@ -155,7 +155,7 @@ | |||
| {{end}} | |||
| </select> | |||
| </div> | |||
| {{template "custom/select_model" .}} | |||
| <div id="images-new-grampus"> | |||
| </div> | |||
| @@ -173,37 +173,19 @@ | |||
| </div> | |||
| {{template "custom/select_dataset_train" .}} | |||
| <div id="select-multi-dataset"> | |||
| </div> | |||
| <span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 1rem;"></span> | |||
| <div class="inline min_title field"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | |||
| <span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | |||
| <input id="store_run_para" type="hidden" name="run_para_list"> | |||
| <div class="dynamic field" style="margin-top: 1rem;" data-params="{{.run_para_list}}"> | |||
| <div class="dynamic field" style="margin-top: 1rem;" data-params="{{.run_para_list}}" data-params-value="{{.i18n.Tr "repo.modelarts.train_job.parameter_value"}}" data-params-name="{{.i18n.Tr "repo.modelarts.train_job.parameter_name"}}"> | |||
| </div> | |||
| </div> | |||
| <!--<div class="required min_title inline field" id="flavor_name"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | |||
| <select class="ui dropdown width81" id="trainjob-flavor" style='width:385px' name="flavor"> | |||
| {{if .flavor}} | |||
| {{range .flavor_infos}} | |||
| {{if eq $.flavor .ID}} | |||
| <option value="{{.ID}}">{{.Name}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| {{range .flavor_infos}} | |||
| {{if ne $.flavor .ID}} | |||
| <option value="{{.ID}}">{{.Name}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| {{else}} | |||
| {{range .flavor_infos}} | |||
| <option name="flavor" value="{{.ID}}">{{.Name}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| </select> | |||
| </div>--> | |||
| <div class="required min_title inline field" id="flavor_name"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | |||
| <select class="ui dropdown width48" id="__specs__" style='width:385px' name="spec_id" ovalue="{{.spec_id}}" {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}></select> | |||
| @@ -234,172 +216,8 @@ | |||
| </div> | |||
| {{template "base/footer" .}} | |||
| <script src="{{StaticUrlPrefix}}/js/specsuse.js?v={{MD5 AppVer}}" type="text/javascript"></script> | |||
| <script src="{{StaticUrlPrefix}}/js/cloudbrainNew.js?v={{MD5 AppVer}}" type="text/javascript"></script> | |||
| <script> | |||
| let form = document.getElementById('form_id'); | |||
| let createFlag = false | |||
| form.onsubmit = function (e) { | |||
| if(createFlag) return false | |||
| createFlag = true | |||
| } | |||
| $('select.dropdown') | |||
| .dropdown(); | |||
| $('.menu .item') | |||
| .tab(); | |||
| $(document).ready(function(){ | |||
| let params = $('.dynamic.field').data('params') | |||
| params&¶ms.parameter.forEach((item,index)=>{ | |||
| Add_parameter(index,flag=true,item) | |||
| }) | |||
| }) | |||
| // 参数增加、删除、修改、保存 | |||
| function Add_parameter(i,flag=false,paramsObject={}) { | |||
| let value = '' | |||
| value += `<div class="two fields width85" id= "para${i}">` | |||
| value += '<div class="field">' | |||
| let placeholder_value='{{.i18n.Tr "repo.modelarts.train_job.parameter_value"}}' | |||
| let placeholder_name='{{.i18n.Tr "repo.modelarts.train_job.parameter_name"}}' | |||
| if(flag){ | |||
| value +=`<input type="text" class="shipping_first-name" value="${paramsObject.label}">` | |||
| }else{ | |||
| value +='<input type="text" class="shipping_first-name" required placeholder="' + placeholder_name+ '">' | |||
| } | |||
| value += '</div>' | |||
| value += '<div class="field">' | |||
| if(flag){ | |||
| value +=`<input type="text" class="shipping_last-name" value="${paramsObject.value}">` | |||
| }else{ | |||
| value +='<input type="text" class="shipping_last-name" required placeholder="' + placeholder_value+ '">' | |||
| } | |||
| value += '</div>' | |||
| value += '<span><i class="trash icon"></i></span>' | |||
| value += '</div>' | |||
| $(".dynamic.field").append(value) | |||
| } | |||
| $('#add_run_para').click(function () { | |||
| var len = $(".dynamic.field .two.fields").length | |||
| Add_parameter(len) | |||
| }); | |||
| $(".dynamic.field").on("click", ".trash.icon", function () { | |||
| var index = $(this).parent().parent().index() | |||
| $(this).parent().parent().remove() | |||
| var len = $(".dynamic.field .two.fields").length | |||
| $(".dynamic.field .two.fields").each(function () { | |||
| var cur_index = $(this).index() | |||
| $(this).attr('id', 'para' + cur_index) | |||
| }) | |||
| }); | |||
| $('.question.circle.icon').hover(function(){ | |||
| $(this).popup('show') | |||
| }); | |||
| $('select.dropdown') | |||
| .dropdown(); | |||
| var isValidate = false; | |||
| function validate(){ | |||
| $('.ui.form') | |||
| .form({ | |||
| on: 'blur', | |||
| fields: { | |||
| boot_file: { | |||
| identifier : 'boot_file', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/.+\.py$/g]', | |||
| } | |||
| ] | |||
| }, | |||
| display_job_name:{ | |||
| identifier : 'display_job_name', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/]', | |||
| } | |||
| ] | |||
| }, | |||
| attachment:{ | |||
| identifier : 'attachment', | |||
| rules: [ | |||
| { | |||
| type: 'empty', | |||
| } | |||
| ] | |||
| }, | |||
| flavor:{ | |||
| identifier : 'flavor', | |||
| rules: [ | |||
| { | |||
| type: 'empty', | |||
| } | |||
| ] | |||
| }, | |||
| work_server_number: { | |||
| identifier : 'work_server_number', | |||
| rules: [ | |||
| { | |||
| type : 'integer[1..25]', | |||
| } | |||
| ] | |||
| }, | |||
| spec_id: { | |||
| identifier: 'spec_id', | |||
| rules: [{ type: 'empty' }] | |||
| } | |||
| }, | |||
| onSuccess: function(){ | |||
| // $('.ui.page.dimmer').dimmer('show') | |||
| document.getElementById("mask").style.display = "block" | |||
| isValidate = true; | |||
| }, | |||
| onFailure: function(e){ | |||
| isValidate = false; | |||
| return false; | |||
| } | |||
| }) | |||
| } | |||
| document.onreadystatechange = function() { | |||
| if (document.readyState === "complete") { | |||
| document.getElementById("mask").style.display = "none" | |||
| } | |||
| } | |||
| function send_run_para() { | |||
| var run_parameters = [] | |||
| var msg = {} | |||
| $(".dynamic.field .two.fields").each(function () { | |||
| var para_name = $(this).find('input.shipping_first-name').val() | |||
| var para_value = $(this).find('input.shipping_last-name').val() | |||
| run_parameters.push({ "label": para_name, "value": para_value }) | |||
| }) | |||
| msg["parameter"] = run_parameters | |||
| msg = JSON.stringify(msg) | |||
| $('#store_run_para').val(msg) | |||
| } | |||
| function get_name(){ | |||
| let name1=$("#engine_name .text").text() | |||
| let name2=$("#flavor_name .text").text() | |||
| $("input#ai_engine_name").val(name1) | |||
| $("input#ai_flavor_name").val(name2) | |||
| } | |||
| validate(); | |||
| $('.ui.create_train_job.green.button').click(function(e) { | |||
| get_name() | |||
| send_run_para() | |||
| validate(); | |||
| }) | |||
| ;(function() { | |||
| var SPECS = {{ .Specs }}; | |||
| var showPoint = {{ .CloudBrainPaySwitch }}; | |||
| @@ -57,19 +57,18 @@ | |||
| <div class="repository"> | |||
| {{template "repo/header" .}} | |||
| <div class="ui container"> | |||
| <div class="cloudbrain-type" style="display: none;" data-cloudbrain-type="{{.datasetType}}" data-repo-link="{{.RepoLink}}" data-flag-model="true" data-dataset-uuid="{{.attachment}}" data-dataset-name="{{.dataset_name}}"></div> | |||
| {{template "base/alert" .}} | |||
| <h4 class="ui top attached header"> | |||
| {{.i18n.Tr "repo.modelarts.train_job.new"}} | |||
| </h4> | |||
| <div class="ui attached segment"> | |||
| <!-- equal width --> | |||
| <form id="form_id" class="ui form" action="{{.Link}}" method="post"> | |||
| <form id="form_id" class="ui form" action="{{.Link}}{{if not .IsCreate}}?compute_resource=NPU{{end}}" method="post"> | |||
| {{.CsrfTokenHtml}} | |||
| <input type="hidden" name="action" value="update"> | |||
| <input type="hidden" id="ai_engine_name" name="engine_name" value=""> | |||
| <input type="hidden" id="ai_flavor_name" name="flavor_name" value=""> | |||
| <input type="hidden" id="fail_dataset_name" value="{{$.dataset_name}}"> | |||
| <input type="hidden" id="fail_dataset_uuid" value="{{$.attachment}}"> | |||
| <h4 class="train-job-title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4> | |||
| <div class="required min_title inline field"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_cluster"}}</label> | |||
| @@ -110,12 +109,11 @@ | |||
| <span style="color: #888;font-size: 12px;">{{.i18n.Tr "cloudbrain.new_train_gpu_tooltips" "/cache/code" "/cache/dataset" "/cache/output" | Safe}}</span> | |||
| </div> | |||
| </div> | |||
| <div class="required min_title inline field"> | |||
| <div class="required min_title inline field" style="margin-bottom: 0rem !important;"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||
| <input style="width: 60%;" name="display_job_name" id="display_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}" tabindex="3" onkeyup="this.value=this.value.replace(/[, ]/g,'')" autofocus required maxlength="36"> | |||
| <span class="tooltips" style="display: block;margin-left: 11.5rem;">{{.i18n.Tr "repo.cloudbrain_jobname_err"}}</span> | |||
| </div> | |||
| <span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 2rem;">{{.i18n.Tr "repo.cloudbrain_jobname_err"}}</span> | |||
| <div class="min_title inline field"> | |||
| <label class="label-fix-width" style="font-weight: normal;" for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}}</label> | |||
| {{if .description}} | |||
| @@ -149,6 +147,7 @@ | |||
| {{end}} | |||
| </select> | |||
| </div> | |||
| {{template "custom/select_model" .}} | |||
| <div class="required min_title inline field" id="engine_name"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.mirror"}}</label> | |||
| <select class="ui dropdown width81" id="trainjob_images" name="image_id"> | |||
| @@ -184,38 +183,19 @@ | |||
| <a href="https://git.openi.org.cn/OpenIOSSG/MNIST_Example/src/branch/master/train_for_c2net.py" target="_blank">{{.i18n.Tr "cloudbrain.view_sample"}}</a> | |||
| </div> | |||
| {{template "custom/select_dataset_train" .}} | |||
| <div id="select-multi-dataset"> | |||
| </div> | |||
| <span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 1rem;"></span> | |||
| <div class="inline min_title field"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | |||
| <span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | |||
| <input id="store_run_para" type="hidden" name="run_para_list"> | |||
| <div class="dynamic field" style="margin-top: 1rem;" data-params="{{.run_para_list}}"> | |||
| <div class="dynamic field" style="margin-top: 1rem;" data-params="{{.run_para_list}}" data-params-value="{{.i18n.Tr "repo.modelarts.train_job.parameter_value"}}" data-params-name="{{.i18n.Tr "repo.modelarts.train_job.parameter_name"}}"> | |||
| </div> | |||
| </div> | |||
| <!--<div class="required min_title inline field" id="flavor_name"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | |||
| <select class="ui dropdown width81" id="trainjob-flavor" style='width:385px' name="flavor"> | |||
| {{if .flavor}} | |||
| {{range .flavor_infos}} | |||
| {{if eq $.flavor .ID}} | |||
| <option value="{{.ID}}">{{.Name}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| {{range .flavor_infos}} | |||
| {{if ne $.flavor .ID}} | |||
| <option value="{{.ID}}">{{.Name}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| {{else}} | |||
| {{range .flavor_infos}} | |||
| <option name="flavor" value="{{.ID}}">{{.Name}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| </select> | |||
| </div>--> | |||
| <div class="required min_title inline field" id="flavor_name"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | |||
| <select class="ui dropdown width48" id="__specs__" style='width:385px' name="spec_id" ovalue="{{.spec_id}}" {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}></select> | |||
| @@ -260,167 +240,8 @@ | |||
| </div> | |||
| {{template "base/footer" .}} | |||
| <script src="{{StaticUrlPrefix}}/js/specsuse.js?v={{MD5 AppVer}}" type="text/javascript"></script> | |||
| <script src="{{StaticUrlPrefix}}/js/cloudbrainNew.js?v={{MD5 AppVer}}" type="text/javascript"></script> | |||
| <script> | |||
| let form = document.getElementById('form_id'); | |||
| let createFlag = false | |||
| form.onsubmit = function (e) { | |||
| if(createFlag) return false | |||
| createFlag = true | |||
| } | |||
| $('select.dropdown') | |||
| .dropdown(); | |||
| $('.menu .item') | |||
| .tab(); | |||
| $(document).ready(function(){ | |||
| let params = $('.dynamic.field').data('params') | |||
| params&¶ms.parameter.forEach((item,index)=>{ | |||
| Add_parameter(index,flag=true,item) | |||
| }) | |||
| }) | |||
| // 参数增加、删除、修改、保存 | |||
| function Add_parameter(i,flag=false,paramsObject={}) { | |||
| let value = '' | |||
| value += `<div class="two fields width85" id= "para${i}">` | |||
| value += '<div class="field">' | |||
| let placeholder_value='{{.i18n.Tr "repo.modelarts.train_job.parameter_value"}}' | |||
| let placeholder_name='{{.i18n.Tr "repo.modelarts.train_job.parameter_name"}}' | |||
| if(flag){ | |||
| value +=`<input type="text" class="shipping_first-name" value="${paramsObject.label}">` | |||
| }else{ | |||
| value +='<input type="text" class="shipping_first-name" required placeholder="' + placeholder_name+ '">' | |||
| } | |||
| value += '</div>' | |||
| value += '<div class="field">' | |||
| if(flag){ | |||
| value +=`<input type="text" class="shipping_last-name" value="${paramsObject.value}">` | |||
| }else{ | |||
| value +='<input type="text" class="shipping_last-name" required placeholder="' + placeholder_value+ '">' | |||
| } | |||
| value += '</div>' | |||
| value += '<span><i class="trash icon"></i></span>' | |||
| value += '</div>' | |||
| $(".dynamic.field").append(value) | |||
| } | |||
| $('#add_run_para').click(function () { | |||
| var len = $(".dynamic.field .two.fields").length | |||
| Add_parameter(len) | |||
| }); | |||
| $(".dynamic.field").on("click", ".trash.icon", function () { | |||
| var index = $(this).parent().parent().index() | |||
| $(this).parent().parent().remove() | |||
| var len = $(".dynamic.field .two.fields").length | |||
| $(".dynamic.field .two.fields").each(function () { | |||
| var cur_index = $(this).index() | |||
| $(this).attr('id', 'para' + cur_index) | |||
| }) | |||
| }); | |||
| $('.question.circle.icon').hover(function(){ | |||
| $(this).popup('show') | |||
| }); | |||
| $('select.dropdown') | |||
| .dropdown(); | |||
| var isValidate = false; | |||
| function validate(){ | |||
| $('.ui.form') | |||
| .form({ | |||
| on: 'blur', | |||
| fields: { | |||
| boot_file: { | |||
| identifier : 'boot_file', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/.+\.py$/g]', | |||
| } | |||
| ] | |||
| }, | |||
| display_job_name:{ | |||
| identifier : 'display_job_name', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/]', | |||
| } | |||
| ] | |||
| }, | |||
| attachment:{ | |||
| identifier : 'attachment', | |||
| rules: [ | |||
| { | |||
| type: 'empty', | |||
| } | |||
| ] | |||
| }, | |||
| work_server_number: { | |||
| identifier : 'work_server_number', | |||
| rules: [ | |||
| { | |||
| type : 'integer[1..25]', | |||
| } | |||
| ] | |||
| }, | |||
| spec_id: { | |||
| identifier: 'spec_id', | |||
| rules: [{ type: 'empty' }] | |||
| } | |||
| }, | |||
| onSuccess: function(){ | |||
| // $('.ui.page.dimmer').dimmer('show') | |||
| document.getElementById("mask").style.display = "block" | |||
| isValidate = true; | |||
| }, | |||
| onFailure: function(e){ | |||
| isValidate = false; | |||
| return false; | |||
| } | |||
| }) | |||
| } | |||
| document.onreadystatechange = function() { | |||
| if (document.readyState === "complete") { | |||
| document.getElementById("mask").style.display = "none" | |||
| } | |||
| } | |||
| function send_run_para() { | |||
| var run_parameters = [] | |||
| var msg = {} | |||
| $(".dynamic.field .two.fields").each(function () { | |||
| var para_name = $(this).find('input.shipping_first-name').val() | |||
| var para_value = $(this).find('input.shipping_last-name').val() | |||
| run_parameters.push({ "label": para_name, "value": para_value }) | |||
| }) | |||
| msg["parameter"] = run_parameters | |||
| msg = JSON.stringify(msg) | |||
| $('#store_run_para').val(msg) | |||
| } | |||
| function get_name(){ | |||
| let name1=$("#engine_name .text").text() | |||
| let name2=$("#flavor_name .text").text() | |||
| $("input#ai_engine_name").val(name1) | |||
| $("input#ai_flavor_name").val(name2) | |||
| let val_server_num_select = $("#trainjob_work_server_num_select .text").text() | |||
| // console.log("val_server_num_select:",val_server_num_select) | |||
| $("input#trainjob_work_server_num").val(val_server_num_select) | |||
| } | |||
| validate(); | |||
| $('.ui.create_train_job.green.button').click(function(e) { | |||
| get_name() | |||
| send_run_para() | |||
| validate(); | |||
| }) | |||
| ;(function() { | |||
| var SPECS = {{ .Specs }}; | |||
| var showPoint = {{ .CloudBrainPaySwitch }}; | |||
| @@ -263,12 +263,11 @@ | |||
| </div> | |||
| <div style="float: right;"> | |||
| {{if and ($.canDownload) (eq .Status "SUCCEEDED") ($.Permission.CanWrite $.UnitTypeModelManage) }} | |||
| {{if and ($.canDownload) (ne .Status "WAITING") ($.Permission.CanWrite $.UnitTypeModelManage) }} | |||
| <a class="ti-action-menu-item" id="{{.VersionName}}-create-model" | |||
| onclick="showcreate({{.}})">{{$.i18n.Tr "repo.modelarts.create_model"}}</a> | |||
| {{else}} | |||
| <a class="ti-action-menu-item disabled" id="{{.VersionName}}-create-model" | |||
| onclick="showcreate({{.}})">{{$.i18n.Tr "repo.modelarts.create_model"}}</a> | |||
| <a class="ti-action-menu-item disabled" id="{{.VersionName}}-create-model">{{$.i18n.Tr "repo.modelarts.create_model"}}</a> | |||
| {{end}} | |||
| </div> | |||
| @@ -841,6 +840,11 @@ | |||
| .modal('show') | |||
| } | |||
| function createModel() { | |||
| if(!$('input#modelSelectedFile').val()){ | |||
| $('input#modelSelectedFile').parent().addClass('error') | |||
| return | |||
| } | |||
| let url_href = `/${userName}/${repoPath}/modelmanage/create_new_model` | |||
| let data = $("#formId").serialize() | |||
| $("#mask").css({ "display": "block", "z-index": "9999" }) | |||
| @@ -109,7 +109,6 @@ | |||
| {{range .Tasks}} | |||
| <div class="ui grid stackable item"> | |||
| <div class="row"> | |||
| <!-- 任务名 --> | |||
| <div class="three wide column padding0"> | |||
| <a class="title" href='{{if eq .Cloudbrain.Type 1 }}{{$.Link}}/{{.JobID}}{{else if eq .Cloudbrain.Type 0}}{{$.RepoLink}}/cloudbrain/train-job/{{.JobID}}{{else if eq .Cloudbrain.Type 2}}{{$.RepoLink}}/grampus/train-job/{{.JobID}}{{end}}' title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
| @@ -168,6 +167,21 @@ | |||
| </a> | |||
| {{end}} | |||
| </div> | |||
| <!-- 修改任务 --> | |||
| <div class="ui compact buttons"> | |||
| {{$.CsrfTokenHtml}} | |||
| {{if .CanModify}} | |||
| <a style="padding: 0.5rem 1rem;" class="ui basic blue button" href="{{if eq .Cloudbrain.Type 1}}{{$.Link}}/{{.JobID}}{{else if eq .Cloudbrain.Type 0}}{{$.RepoLink}}/cloudbrain/train-job/{{.JobID}}{{else if eq .Cloudbrain.Type 2}}{{$.RepoLink}}/grampus/train-job/{{.JobID}}{{end}}/create_version{{if .VersionName}}?version_name={{.VersionName}}{{end}}"> | |||
| {{$.i18n.Tr "repo.modelarts.modify"}} | |||
| </a> | |||
| {{else}} | |||
| <a class="ui basic disabled button"> | |||
| {{$.i18n.Tr "repo.modelarts.modify"}} | |||
| </a> | |||
| {{end}} | |||
| </div> | |||
| <!-- 删除任务 --> | |||
| <form class="ui compact buttons" id="delForm-{{.JobID}}" action='{{if eq .Cloudbrain.Type 1}}{{$.Link}}/{{.JobID}}{{else if eq .Cloudbrain.Type 0}}{{$.RepoLink}}/cloudbrain/train-job/{{.JobID}}{{else if eq .Cloudbrain.Type 2}}{{$.RepoLink}}/grampus/train-job/{{.JobID}}{{end}}/del' method="post"> | |||
| @@ -62,7 +62,7 @@ | |||
| <div class="repository"> | |||
| {{template "repo/header" .}} | |||
| <div class="ui container"> | |||
| <div class="cloudbrain-type" style="display: none;" data-cloudbrain-type="{{.datasetType}}" data-repo-link="{{.RepoLink}}"></div> | |||
| <div class="cloudbrain-type" style="display: none;" data-cloudbrain-type="{{.datasetType}}" data-repo-link="{{.RepoLink}}" data-flag-model="true" data-dataset-uuid="{{.attachment}}" data-dataset-name="{{.dataset_name}}"></div> | |||
| {{template "base/alert" .}} | |||
| <h4 class="ui top attached header"> | |||
| {{.i18n.Tr "repo.modelarts.train_job.new"}} | |||
| @@ -119,11 +119,11 @@ | |||
| <span style="color: #888;font-size: 12px;">{{.i18n.Tr "cloudbrain.train_dataset_path_rule" | Safe}}</span> | |||
| </div> | |||
| </div> | |||
| <div class="required inline min_title field"> | |||
| <div class="required inline min_title field" style="margin-bottom: 0rem !important;"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||
| <input style="width: 60%;" name="display_job_name" id="display_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}" tabindex="3" onkeyup="this.value=this.value.replace(/[, ]/g,'')" autofocus required maxlength="36"> | |||
| </div> | |||
| <span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 2rem;">{{.i18n.Tr "repo.cloudbrain_jobname_err"}}</span> | |||
| <div class="inline min_title field"> | |||
| <label class="label-fix-width" style="font-weight: normal;" for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}}</label> | |||
| {{if .description}} | |||
| @@ -157,8 +157,8 @@ | |||
| {{end}} | |||
| </select> | |||
| </div> | |||
| {{template "custom/select_model" .}} | |||
| <div class="required inline min_title fields" style="width: 95%;"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.AI_driver"}}</label> | |||
| @@ -215,23 +215,7 @@ | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | |||
| <span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | |||
| <input id="store_run_para" type="hidden" name="run_para_list"> | |||
| <div class="dynamic field" style="margin-top: 1rem;"> | |||
| {{if ne 0 (len .params)}} | |||
| {{range $k ,$v := .params}} | |||
| <div class="two fields width85" id="para{{$k}}"> | |||
| <div class="field"> | |||
| <input type="text" name="shipping_first-name" value={{$v.Label}} required> | |||
| </div> | |||
| <div class="field"> | |||
| <input type="text" name="shipping_last-name" value={{$v.Value}} required> | |||
| </div> | |||
| <span> | |||
| <i class="trash icon"></i> | |||
| </span> | |||
| </div> | |||
| {{end}} | |||
| {{end}} | |||
| <div class="dynamic field" style="margin-top: 1rem;" data-params="{{.run_para_list}}" data-params-value="{{.i18n.Tr "repo.modelarts.train_job.parameter_value"}}" data-params-name="{{.i18n.Tr "repo.modelarts.train_job.parameter_name"}}"> | |||
| </div> | |||
| </div> | |||
| @@ -260,27 +244,6 @@ | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <!--<div class="required inline min_title field" id="flaver_name"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | |||
| <select class="ui dropdown width48" id="trainjob-flavor" name="flavor"> | |||
| {{if .flavor}} | |||
| {{range .flavor_infos}} | |||
| {{if eq $.flavor .Code}} | |||
| <option value="{{.Code}}">{{.Value}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| {{range .flavor_infos}} | |||
| {{if ne $.flavor .Code}} | |||
| <option value="{{.Code}}">{{.Value}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| {{else}} | |||
| {{range .flavor_infos}} | |||
| <option name="flavor" value="{{.Code}}">{{.Value}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| </select> | |||
| </div>--> | |||
| <div class="required inline min_title field" id="flaver_name"> | |||
| <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | |||
| <select class="ui dropdown width48" id="__specs__" name="spec_id" ovalue="{{.spec_id}}" {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}></select> | |||
| @@ -332,7 +295,7 @@ | |||
| <button class="ui create_train_job green button"> | |||
| {{.i18n.Tr "repo.cloudbrain.new"}} | |||
| </button> | |||
| <a class="ui button" href="/">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a> | |||
| <a class="ui button" href="{{.RepoLink}}/modelarts/train-job">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a> | |||
| </div> | |||
| <!-- 模态框 --> | |||
| @@ -343,226 +306,8 @@ | |||
| </div> | |||
| {{template "base/footer" .}} | |||
| <script src="{{StaticUrlPrefix}}/js/specsuse.js?v={{MD5 AppVer}}" type="text/javascript"></script> | |||
| <script src="{{StaticUrlPrefix}}/js/cloudbrainNew.js?v={{MD5 AppVer}}" type="text/javascript"></script> | |||
| <script> | |||
| let form = document.getElementById('form_id'); | |||
| let createFlag = false | |||
| form.onsubmit = function (e) { | |||
| if(createFlag) return false | |||
| createFlag = true | |||
| } | |||
| let url_href = window.location.pathname.split('create')[0] | |||
| $(".ui.button").attr('href', url_href) | |||
| $('select.dropdown') | |||
| .dropdown(); | |||
| $('.menu .item') | |||
| .tab(); | |||
| $(document).keydown(function(event){ | |||
| switch(event.keyCode){ | |||
| case 13:return false; | |||
| } | |||
| }); | |||
| // 参数增加、删除、修改、保存 | |||
| function Add_parameter(i) { | |||
| let placeholder_value='{{.i18n.Tr "repo.modelarts.train_job.parameter_value"}}' | |||
| let placeholder_name='{{.i18n.Tr "repo.modelarts.train_job.parameter_name"}}' | |||
| value = '<div class="two fields width85" id= "para' + i + '">' + | |||
| '<div class="field">' + | |||
| '<input type="text" name="shipping_first-name" required placeholder="' + placeholder_name+ '">' + | |||
| '</div> ' + | |||
| '<div class="field"> ' + | |||
| '<input type="text" name="shipping_last-name" required placeholder="' + placeholder_value+ '">' + | |||
| '</div>' + | |||
| '<span>' + | |||
| '<i class="trash icon">' + | |||
| '</i>' + | |||
| '</span>' + | |||
| '</div>' | |||
| $(".dynamic.field").append(value) | |||
| } | |||
| $('#add_run_para').click(function () { | |||
| var len = $(".dynamic.field .two.fields").length | |||
| Add_parameter(len) | |||
| }); | |||
| $(".dynamic.field").on("click", ".trash.icon", function () { | |||
| var index = $(this).parent().parent().index() | |||
| $(this).parent().parent().remove() | |||
| var len = $(".dynamic.field .two.fields").length | |||
| $(".dynamic.field .two.fields").each(function () { | |||
| var cur_index = $(this).index() | |||
| $(this).attr('id', 'para' + cur_index) | |||
| }) | |||
| }); | |||
| $('.ui.parameter.green.button').click(function () { | |||
| var parameters = []; | |||
| $('table tr').each(function () { | |||
| $(this).find('td:eq(1)').each(function () { | |||
| parameters.push($(this).text()); | |||
| }) | |||
| $(this).find('input').each(function () { | |||
| parameters.push($(this).text()) | |||
| }) | |||
| }); | |||
| $('.ui.parameter.modal') | |||
| .modal('hide'); | |||
| for (var i = 2; i < parameters.length; i++) { | |||
| switch (i) { | |||
| // 数据集uuid待完成 | |||
| // case (2): | |||
| // console.log(1) | |||
| // break; | |||
| // $("#trainjob_datasets").val(parameters[i]); | |||
| // console.log($("#trainjob_datasets").val()) | |||
| case (3): | |||
| $("input[name='boot_file']").val(parameters[i]); | |||
| break; | |||
| case (4): | |||
| var para = parameters[i].split(" ") | |||
| for (var j = 0; j < para.length; j++) { | |||
| var para_name = para[j].split('=')[0] | |||
| var para_value = para[j].split('=')[1] | |||
| var len = $(".dynamic.field .two.fields").length | |||
| Add_parameter(len) | |||
| var pid = 'para' + len | |||
| $(".dynamic.field" + " #" + pid + "").find("input[name=shipping_first-name]").val(para_name) | |||
| $(".dynamic.field" + " #" + pid + "").find("input[name=shipping_last-name]").val(para_value) | |||
| } | |||
| break; | |||
| // 数据集pool_id待完成 | |||
| // case (5): | |||
| // $("select[name='pool_id']").val(parameters[i]); | |||
| // break; | |||
| case (6): | |||
| // $("input[name='work_server_number']").val(parameters[i]); | |||
| break; | |||
| } | |||
| } | |||
| }) | |||
| $('.ui.save.checkbox').click(function () { | |||
| $(this).checkbox({ | |||
| onChange: function () { | |||
| if ($('.ui.save.checkbox').checkbox('is checked')) { | |||
| $('#save_para').removeClass("disabled") | |||
| } else { | |||
| $('#save_para').addClass("disabled") | |||
| } | |||
| } | |||
| }); | |||
| }) | |||
| $('.question.circle.icon').hover(function () { | |||
| $(this).popup('show') | |||
| }); | |||
| $(".item.active.parameter_config").click(function () { | |||
| $('.ui.parameter.modal') | |||
| .modal('setting', 'closable', false) | |||
| .modal('show'); | |||
| }) | |||
| $('.ui.deny.button').click(function () { | |||
| $('.ui.parameter.modal') | |||
| .modal('hide'); | |||
| }) | |||
| $('select.dropdown') | |||
| .dropdown(); | |||
| var isValidate = false; | |||
| function validate() { | |||
| $('.ui.form') | |||
| .form({ | |||
| on: 'blur', | |||
| fields: { | |||
| boot_file: { | |||
| identifier: 'boot_file', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/.+\.py$/g]', | |||
| } | |||
| ] | |||
| }, | |||
| display_job_name: { | |||
| identifier: 'display_job_name', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/]', | |||
| } | |||
| ] | |||
| }, | |||
| attachment: { | |||
| identifier: 'attachment', | |||
| rules: [ | |||
| { | |||
| type: 'empty', | |||
| } | |||
| ] | |||
| }, | |||
| work_server_number: { | |||
| identifier: 'work_server_number', | |||
| rules: [ | |||
| { | |||
| type: 'integer[1..25]', | |||
| } | |||
| ] | |||
| }, | |||
| spec_id: { | |||
| identifier: 'spec_id', | |||
| rules: [{ type: 'empty' }] | |||
| } | |||
| }, | |||
| onSuccess: function () { | |||
| // $('.ui.page.dimmer').dimmer('show') | |||
| document.getElementById("mask").style.display = "block" | |||
| isValidate = true; | |||
| }, | |||
| onFailure: function (e) { | |||
| isValidate = false; | |||
| return false; | |||
| } | |||
| }) | |||
| } | |||
| document.onreadystatechange = function () { | |||
| if (document.readyState === "complete") { | |||
| document.getElementById("mask").style.display = "none" | |||
| } | |||
| } | |||
| function send_run_para() { | |||
| var run_parameters = [] | |||
| var msg = {} | |||
| $(".dynamic.field .two.fields").each(function () { | |||
| var para_name = $(this).find('input[name=shipping_first-name]').val() | |||
| var para_value = $(this).find('input[name=shipping_last-name]').val() | |||
| run_parameters.push({ "label": para_name, "value": para_value }) | |||
| }) | |||
| msg["parameter"] = run_parameters | |||
| msg = JSON.stringify(msg) | |||
| $('#store_run_para').val(msg) | |||
| } | |||
| function get_name() { | |||
| let name1 = $("#engine_name .text").text() | |||
| let name2 = $("#flaver_name .text").text() | |||
| $("input#ai_engine_name").val(name1) | |||
| $("input#ai_flaver_name").val(name2) | |||
| let val_server_num_select = $("#trainjob_work_server_num_select .text").text() | |||
| // console.log("val_server_num_select:",val_server_num_select) | |||
| $("input#trainjob_work_server_num").val(val_server_num_select) | |||
| } | |||
| validate(); | |||
| $('.ui.create_train_job.green.button').click(function (e) { | |||
| get_name() | |||
| send_run_para(); | |||
| validate(); | |||
| }) | |||
| ;(function() { | |||
| var SPECS = {{ .Specs }}; | |||
| var showPoint = {{ .CloudBrainPaySwitch }}; | |||
| @@ -247,12 +247,11 @@ | |||
| <span> | |||
| <div style="float: right;"> | |||
| {{$.CsrfTokenHtml}} | |||
| {{if and (.CanModify) (eq .Status "COMPLETED") ($.Permission.CanWrite $.UnitTypeModelManage) }} | |||
| {{if and (.CanModify) (ne .Status "WAITING") ($.Permission.CanWrite $.UnitTypeModelManage) }} | |||
| <a class="ti-action-menu-item" id="{{.VersionName}}-create-model" | |||
| onclick="showcreate({{.}})">{{$.i18n.Tr "repo.modelarts.create_model"}}</a> | |||
| {{else}} | |||
| <a class="ti-action-menu-item disabled" id="{{.VersionName}}-create-model" | |||
| onclick="showcreate({{.}})">{{$.i18n.Tr "repo.modelarts.create_model"}}</a> | |||
| <a class="ti-action-menu-item disabled" id="{{.VersionName}}-create-model">{{$.i18n.Tr "repo.modelarts.create_model"}}</a> | |||
| {{end}} | |||
| {{if .CanModify}} | |||
| @@ -892,6 +891,10 @@ | |||
| .modal('show') | |||
| } | |||
| function createModel() { | |||
| if(!$('input#modelSelectedFile').val()){ | |||
| $('input#modelSelectedFile').parent().addClass('error') | |||
| return | |||
| } | |||
| let url_href = `/${userName}/${repoPath}/modelmanage/create_new_model` | |||
| let data = $("#formId").serialize() | |||
| $("#mask").css({ "display": "block", "z-index": "9999" }) | |||
| @@ -55,14 +55,14 @@ | |||
| <div class="repository"> | |||
| {{template "repo/header" .}} | |||
| <div class="ui container"> | |||
| <div class="cloudbrain-type" style="display: none;" data-cloudbrain-type="{{.datasetType}}" data-repo-link="{{.RepoLink}}" data-dataset-uuid="{{.uuid}}" data-dataset-name="{{.dataset_name}}"></div> | |||
| <div class="cloudbrain-type" style="display: none;" data-cloudbrain-type="{{.datasetType}}" data-repo-link="{{.RepoLink}}" data-flag-model="true" data-dataset-uuid="{{.attachment}}" data-dataset-name="{{.dataset_name}}"></div> | |||
| {{template "base/alert" .}} | |||
| <h4 class="ui top attached header"> | |||
| {{.i18n.Tr "repo.modelarts.train_job.new"}} | |||
| </h4> | |||
| <div class="ui attached segment"> | |||
| <!-- equal width --> | |||
| <form class="ui form" action="{{$.RepoLink}}/modelarts/train-job/{{.JobID}}/create_version" method="post"> | |||
| <form id="form_id" class="ui form" action="{{$.RepoLink}}/modelarts/train-job/{{.JobID}}/create_version" method="post"> | |||
| {{.CsrfTokenHtml}} | |||
| <input type="hidden" name="action" value="update"> | |||
| {{if .version_name}} | |||
| @@ -154,7 +154,7 @@ | |||
| </div> | |||
| {{template "custom/select_model" .}} | |||
| <div class="required unite min_title inline fields" style="width: 90%;"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.AI_driver"}} </label> | |||
| @@ -202,23 +202,8 @@ | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | |||
| <span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | |||
| <input id="store_run_para" type="hidden" name="run_para_list"> | |||
| <div class="dynamic field" style="margin-top: 1rem;"> | |||
| {{if ne 0 (len .params)}} | |||
| {{range $k ,$v := .params}} | |||
| <div class="two fields width85" id="para{{$k}}"> | |||
| <div class="field"> | |||
| <input type="text" name="shipping_first-name" value={{$v.Label}} required> | |||
| </div> | |||
| <div class="field"> | |||
| <input type="text" name="shipping_last-name" value={{$v.Value}} required> | |||
| </div> | |||
| <span> | |||
| <i class="trash icon"></i> | |||
| </span> | |||
| </div> | |||
| {{end}} | |||
| {{end}} | |||
| <div class="dynamic field" style="margin-top: 1rem;" data-params="{{.run_para_list}}" data-params-value="{{.i18n.Tr "repo.modelarts.train_job.parameter_value"}}" data-params-name="{{.i18n.Tr "repo.modelarts.train_job.parameter_name"}}"> | |||
| </div> | |||
| </div> | |||
| @@ -248,19 +233,6 @@ | |||
| </div> | |||
| </div> | |||
| <!--<div class="required unite min_title inline field" id="flaver_name"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | |||
| <select class="ui dropdown width81" id="trainjob-flavor" style='width:385px' name="flavor"> | |||
| {{if .flavor_name}} | |||
| <option name="flavor" value="{{.flavor_code}}">{{.flavor_name}}</option> | |||
| {{end}} | |||
| {{range .flavor_infos}} | |||
| {{if ne $.flavor_code .Code}} | |||
| <option name="flavor" value="{{.Code}}">{{.Value}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| </select> | |||
| </div>--> | |||
| <div class="required unite min_title inline field" id="flaver_name"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | |||
| <select id="__specs__" class="ui dropdown width80" style='width:385px' name="spec_id" ovalue="{{.spec_id}}" {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}></select> | |||
| @@ -289,7 +261,7 @@ | |||
| <button class="ui create_train_job green button"> | |||
| {{.i18n.Tr "repo.cloudbrain.new"}} | |||
| </button> | |||
| <a class="ui button" href="/">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a> | |||
| <a class="ui button" href="{{.RepoLink}}/modelarts/train-job">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a> | |||
| </div> | |||
| <!-- 模态框 --> | |||
| @@ -300,239 +272,11 @@ | |||
| </div> | |||
| {{template "base/footer" .}} | |||
| <script src="{{StaticUrlPrefix}}/js/specsuse.js?v={{MD5 AppVer}}" type="text/javascript"></script> | |||
| <script src="{{StaticUrlPrefix}}/js/cloudbrainNew.js?v={{MD5 AppVer}}" type="text/javascript"></script> | |||
| <script> | |||
| let url_href = location.pathname.split('/create_version')[0] | |||
| let url_post = location.pathname | |||
| let version_name = location.search.split('?version_name=')[1] | |||
| $("#parents_version").val(version_name) | |||
| $(".ui.button").attr('href',url_href) | |||
| $(".ui.form").attr('action',url_post) | |||
| $("input[name=version_name]").attr('value',version_name) | |||
| $('select.dropdown') | |||
| .dropdown(); | |||
| $('.menu .item') | |||
| .tab(); | |||
| let sever_num = $('#trainjob_work_server_num') | |||
| $('.add').click(function(){ | |||
| sever_num.val(parseInt(sever_num.val())+1) | |||
| if(sever_num.val()>=26){ | |||
| sever_num.val(parseInt(sever_num.val())-1) | |||
| } | |||
| }) | |||
| $('.min').click(function(){ | |||
| sever_num.val(parseInt(sever_num.val())-1) | |||
| if(sever_num.val()<=0){ | |||
| sever_num.val(parseInt(sever_num.val())+1) | |||
| } | |||
| }) | |||
| // 参数增加、删除、修改、保存 | |||
| function Add_parameter(i){ | |||
| let placeholder_value='{{.i18n.Tr "repo.modelarts.train_job.parameter_value"}}' | |||
| let placeholder_name='{{.i18n.Tr "repo.modelarts.train_job.parameter_name"}}' | |||
| value = '<div class="two fields width85" id= "para'+ i +'">' + | |||
| '<div class="field">' + | |||
| '<input type="text" name="shipping_first-name" required placeholder="' + placeholder_name+ '">' + | |||
| '</div> ' + | |||
| '<div class="field"> ' + | |||
| '<input type="text" name="shipping_last-name" required placeholder="' + placeholder_value+ '">' + | |||
| '</div>'+ | |||
| '<span>' + | |||
| '<i class="trash icon">' + | |||
| '</i>' + | |||
| '</span>' + | |||
| '</div>' | |||
| $(".dynamic.field").append(value) | |||
| } | |||
| $('#add_run_para').click(function(){ | |||
| var len = $(".dynamic.field .two.fields").length | |||
| Add_parameter(len) | |||
| }); | |||
| $(".dynamic.field").on("click",".trash.icon", function() { | |||
| var index = $(this).parent().parent().index() | |||
| $(this).parent().parent().remove() | |||
| var len = $(".dynamic.field .two.fields").length | |||
| $(".dynamic.field .two.fields").each(function(){ | |||
| var cur_index = $(this).index() | |||
| $(this).attr('id', 'para' + cur_index) | |||
| }) | |||
| }); | |||
| $('.ui.parameter.green.button').click(function(){ | |||
| var parameters = []; | |||
| $('table tr').each(function() { | |||
| $(this).find('td:eq(1)').each(function(){ | |||
| parameters.push($(this).text()); | |||
| }) | |||
| $(this).find('input').each(function(){ | |||
| parameters.push($(this).text()) | |||
| }) | |||
| }); | |||
| $('.ui.parameter.modal') | |||
| .modal('hide'); | |||
| for(var i = 2; i < parameters.length; i++){ | |||
| switch(i) { | |||
| // 数据集uuid待完成 | |||
| // case (2): | |||
| // console.log(1) | |||
| // break; | |||
| // $("#trainjob_datasets").val(parameters[i]); | |||
| // console.log($("#trainjob_datasets").val()) | |||
| case (3): | |||
| $("input[name='boot_file']").val(parameters[i]); | |||
| break; | |||
| case (4): | |||
| var para = parameters[i].split(" ") | |||
| for(var j = 0; j < para.length; j++){ | |||
| var para_name = para[j].split('=')[0] | |||
| var para_value = para[j].split('=')[1] | |||
| var len = $(".dynamic.field .two.fields").length | |||
| Add_parameter(len) | |||
| var pid = 'para' + len | |||
| $(".dynamic.field"+ " #" + pid + "").find("input[name=shipping_first-name]").val(para_name) | |||
| $(".dynamic.field"+ " #" + pid + "").find("input[name=shipping_last-name]").val(para_value) | |||
| } | |||
| break; | |||
| // 数据集pool_id待完成 | |||
| // case (5): | |||
| // $("select[name='pool_id']").val(parameters[i]); | |||
| // break; | |||
| case (6): | |||
| $("input[name='work_server_number']").val(parameters[i]); | |||
| break; | |||
| } | |||
| } | |||
| }) | |||
| $('.ui.save.checkbox').click(function(){ | |||
| $(this).checkbox({ | |||
| onChange: function(){ | |||
| if ($('.ui.save.checkbox').checkbox('is checked')){ | |||
| $('#save_para').removeClass("disabled") | |||
| }else{ | |||
| $('#save_para').addClass("disabled") | |||
| } | |||
| } | |||
| }); | |||
| }) | |||
| $('.question.circle.icon').hover(function(){ | |||
| $(this).popup('show') | |||
| }); | |||
| $(".item.active.parameter_config").click(function(){ | |||
| $('.ui.parameter.modal') | |||
| .modal('setting', 'closable', false) | |||
| .modal('show'); | |||
| }) | |||
| $('.ui.deny.button').click(function(){ | |||
| $('.ui.parameter.modal') | |||
| .modal('hide'); | |||
| }) | |||
| $('select.dropdown') | |||
| .dropdown(); | |||
| var isValidate = false; | |||
| function validate(){ | |||
| $('.ui.form') | |||
| .form({ | |||
| on: 'blur', | |||
| inline:true, | |||
| fields: { | |||
| boot_file: { | |||
| identifier : 'boot_file', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/.+\.py$/g]', | |||
| prompt : '启动文件必须为.py结尾' | |||
| } | |||
| ] | |||
| }, | |||
| job_name:{ | |||
| identifier : 'job_name', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/^[a-zA-Z0-9-_]{1,36}$/]', | |||
| prompt : '只包含大小写字母、数字、_和-,最长36个字符。' | |||
| } | |||
| ] | |||
| }, | |||
| display_job_name:{ | |||
| identifier : 'display_job_name', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/^[a-zA-Z0-9-_]{1,36}$/]', | |||
| prompt : '只包含大小写字母、数字、_和-,最长36个字符。' | |||
| } | |||
| ] | |||
| }, | |||
| attachment:{ | |||
| identifier : 'attachment', | |||
| rules: [ | |||
| { | |||
| type: 'empty', | |||
| prompt : '选择一个数据集' | |||
| } | |||
| ] | |||
| }, | |||
| spec_id: { | |||
| identifier: 'spec_id', | |||
| rules: [{ type: 'empty' }] | |||
| } | |||
| }, | |||
| onSuccess: function(){ | |||
| // $('.ui.page.dimmer').dimmer('show') | |||
| document.getElementById("mask").style.display = "block" | |||
| isValidate = true; | |||
| }, | |||
| onFailure: function(e){ | |||
| isValidate = false; | |||
| return false; | |||
| } | |||
| }) | |||
| } | |||
| document.onreadystatechange = function() { | |||
| if (document.readyState === "complete") { | |||
| document.getElementById("mask").style.display = "none" | |||
| } | |||
| } | |||
| function send_run_para(){ | |||
| var run_parameters = [] | |||
| var msg = {} | |||
| $(".dynamic.field .two.fields").each(function(){ | |||
| var para_name = $(this).find('input[name=shipping_first-name]').val() | |||
| var para_value = $(this).find('input[name=shipping_last-name]').val() | |||
| run_parameters.push({"label": para_name, "value": para_value}) | |||
| }) | |||
| msg["parameter"] = run_parameters | |||
| msg = JSON.stringify(msg) | |||
| $('#store_run_para').val(msg) | |||
| } | |||
| function get_name(){ | |||
| let name1=$("#engine_name .text").text() | |||
| let name2=$("#flaver_name .text").text() | |||
| $("input#ai_engine_name").val(name1) | |||
| $("input#ai_flaver_name").val(name2) | |||
| } | |||
| validate() | |||
| $('.ui.create_train_job.green.button').click(function(e) { | |||
| get_name() | |||
| send_run_para() | |||
| validate() | |||
| }) | |||
| ;(function() { | |||
| var SPECS = {{ .Specs }}; | |||
| var showPoint = {{ .CloudBrainPaySwitch }}; | |||
| @@ -16,10 +16,10 @@ | |||
| text-align: center; | |||
| } | |||
| </style> | |||
| <div class="ui container"> | |||
| <div class="ui container rule-container" style="display:none;"> | |||
| <h1 class="ui center am-pt-30 am-pb-20">个人算力积分奖励规则</h1> | |||
| <div class="ui divider am-pb-10"></div> | |||
| <p>说明:单日用户积分的获取上限为50分。</p> | |||
| <p>说明:单日用户积分的获取上限为<span class="daily-limit"> - </span>分。该积分仅用于算力资源使用,打榜活动积分将另行计算。</p> | |||
| <table class="m-table"> | |||
| <tr> | |||
| <th style="width:200px;">奖励名称</th> | |||
| @@ -27,85 +27,126 @@ | |||
| <th style="width:200px;">上限值</th> | |||
| <th>奖励细节澄清</th> | |||
| </tr> | |||
| <tr> | |||
| <tr key="34"> | |||
| <td class="t-center">完成微信扫码验证</td> | |||
| <td class="t-center">50</td> | |||
| <td class="t-center">累计积分获取上限50</td> | |||
| <td>1、首次完成微信扫码验证,即获取50积分。<br>2、同个账号,更换微信号码再验证不重复给积分。<br>3、同一个微信,绑定第一个账号时奖励50分,下次绑定其他账号时不再奖励。</td> | |||
| <td class="t-center point">-</td> | |||
| <td class="t-center"><span class="typ">累计</span>积分获取上限<span class="limit"> - </span></td> | |||
| <td>1、首次完成微信扫码验证,即获取积分。<br>2、同个账号,更换微信号码再验证不重复给积分。<br>3、同一个微信,绑定第一个账号时奖励积分,下次绑定其他账号时不再奖励。</td> | |||
| </tr> | |||
| <tr> | |||
| <tr key="1"> | |||
| <td class="t-center">创建或Fork公开项目</td> | |||
| <td class="t-center">1</td> | |||
| <td class="t-center">每日积分获取上限3</td> | |||
| <td class="t-center point">-</td> | |||
| <td class="t-center"><span class="typ">每日</span>积分获取上限<span class="limit"> - </span></td> | |||
| <td>请注意项目质量,请勿复制粘贴或者重复公开项目,任何非常规的以公开项目去获取积分的行为将被认定为积分舞弊,将扣除所有积分。</td> | |||
| </tr> | |||
| <tr> | |||
| <tr key="7"> | |||
| <td class="t-center">每日提出PR</td> | |||
| <td class="t-center">1</td> | |||
| <td class="t-center">每日积分获取上限3</td> | |||
| <td class="t-center point">-</td> | |||
| <td class="t-center"><span class="typ">每日</span>积分获取上限<span class="limit"> - </span></td> | |||
| <td></td> | |||
| </tr> | |||
| <tr> | |||
| <tr key="40"> | |||
| <td class="t-center">每日commit</td> | |||
| <td class="t-center">1</td> | |||
| <td class="t-center">每日积分获取上限3</td> | |||
| <td class="t-center point">-</td> | |||
| <td class="t-center"><span class="typ">每日</span>积分获取上限<span class="limit"> - </span></td> | |||
| <td>通过前台界面和后台命令行方式commit,都可获得奖励积分。</td> | |||
| </tr> | |||
| <tr> | |||
| <tr key="6"> | |||
| <td class="t-center">每日提出任务</td> | |||
| <td class="t-center">1</td> | |||
| <td class="t-center">每日积分获取上限3</td> | |||
| <td class="t-center point">-</td> | |||
| <td class="t-center"><span class="typ">每日</span>积分获取上限<span class="limit"> - </span></td> | |||
| <td></td> | |||
| </tr> | |||
| <tr> | |||
| <tr key="10"> | |||
| <td class="t-center">发表评论</td> | |||
| <td class="t-center">1</td> | |||
| <td class="t-center">每日积分获取上限2</td> | |||
| <td class="t-center point">-</td> | |||
| <td class="t-center"><span class="typ">每日</span>积分获取上限<span class="limit"> - </span></td> | |||
| <td>禁止空评论或评论后马上删除等非正常获取积分的方式,一经发现将扣除所有积分。</td> | |||
| </tr> | |||
| <tr> | |||
| <tr key="24"> | |||
| <td class="t-center">上传数据集文件</td> | |||
| <td class="t-center">1</td> | |||
| <td class="t-center">每日积分获取上限1</td> | |||
| <td class="t-center point">-</td> | |||
| <td class="t-center"><span class="typ">每日</span>积分获取上限<span class="limit"> - </span></td> | |||
| <td>请注意数据集质量,请勿复制粘贴或者重复公开数据集,任何非常规的以公开数据集去获取积分的行为将被认定为积分舞弊,将扣除所有积分。</td> | |||
| </tr> | |||
| <tr> | |||
| <tr key="36"> | |||
| <td class="t-center">数据集被平台推荐</td> | |||
| <td class="t-center">5</td> | |||
| <td class="t-center">每日积分获取上限15</td> | |||
| <td class="t-center point">-</td> | |||
| <td class="t-center"><span class="typ">每日</span>积分获取上限<span class="limit"> - </span></td> | |||
| <td>仅统计属于个人的数据集,属于组织的数据集暂不统计。</td> | |||
| </tr> | |||
| <tr> | |||
| <tr key="30"> | |||
| <td class="t-center">导入新模型</td> | |||
| <td class="t-center">1</td> | |||
| <td class="t-center">每日积分获取上限3</td> | |||
| <td class="t-center point">-</td> | |||
| <td class="t-center"><span class="typ">每日</span>积分获取上限<span class="limit"> - </span></td> | |||
| <td>请注意模型质量,请勿重复导入相同模型,任何非常规的以导入新模型去获取 积分的行为将被认定为积分舞弊,将扣除所有积分。</td> | |||
| </tr> | |||
| <tr> | |||
| <tr key="35"> | |||
| <td class="t-center">每日运行云脑任务</td> | |||
| <td class="t-center">10</td> | |||
| <td class="t-center">每日积分获取上限10</td> | |||
| <td class="t-center point">-</td> | |||
| <td class="t-center"><span class="typ">每日</span>积分获取上限<span class="limit"> - </span></td> | |||
| <td> 每日运行调试、训练、推理、评测中任何一种任务,即可获得。</td> | |||
| </tr> | |||
| <tr> | |||
| <tr key="37"> | |||
| <td class="t-center">提交新公开镜像</td> | |||
| <td class="t-center">1</td> | |||
| <td class="t-center">每日积分获取上限3</td> | |||
| <td class="t-center point">-</td> | |||
| <td class="t-center"><span class="typ">每日</span>积分获取上限<span class="limit"> - </span></td> | |||
| <td></td> | |||
| </tr> | |||
| <tr> | |||
| <tr key="38"> | |||
| <td class="t-center">镜像被平台推荐</td> | |||
| <td class="t-center">5</td> | |||
| <td class="t-center">每日积分获取上限15</td> | |||
| <td class="t-center point">-</td> | |||
| <td class="t-center"><span class="typ">每日</span>积分获取上限<span class="limit"> - </span></td> | |||
| <td></td> | |||
| </tr> | |||
| <tr> | |||
| <tr key="39"> | |||
| <td class="t-center">首次更换头像</td> | |||
| <td class="t-center">2</td> | |||
| <td class="t-center">累计积分获取上限2</td> | |||
| <td>首次更换头像,积分+2。</td> | |||
| <td class="t-center point">-</td> | |||
| <td class="t-center"><span class="typ">累计</span>积分获取上限<span class="limit"> - </span></td> | |||
| <td>首次更换头像,获得积分。</td> | |||
| </tr> | |||
| </table> | |||
| </div> | |||
| {{template "base/footer" .}} | |||
| {{template "base/footer" .}} | |||
| <script> | |||
| ;(function() { | |||
| var ruleContainer = $('.rule-container'); | |||
| var dailyLimitEl = ruleContainer.find('.daily-limit'); | |||
| var ruleTrs = ruleContainer.find('tr[key]'); | |||
| $.ajax({ | |||
| url: '/reward/point/rule/config', | |||
| type: "get", | |||
| data: {}, | |||
| contentType: "application/json; charset=utf-8", | |||
| success(res) { | |||
| if (res && res.Code === 0) { | |||
| var data = res.Data; | |||
| dailyLimitEl.text(data.UserDailyLimit); | |||
| var taskRules = data.TaskRules; | |||
| for (var i = 0, iLen = ruleTrs.length; i < iLen; i++) { | |||
| var ruleTr = ruleTrs.eq(i); | |||
| var key = ruleTr.attr('key'); | |||
| var findOr = false; | |||
| for (var j = 0, jLen = taskRules.length; j < jLen; j++) { | |||
| var taskRule = taskRules[j]; | |||
| if (taskRule.TaskCode == key) { | |||
| ruleTr.find('.point').text(taskRule.AwardAmount); | |||
| ruleTr.find('.typ').text(taskRule.RefreshRate == 'DAILY' ? '每日' : taskRule.RefreshRate == 'NOT_CYCLE' ? '累计' : taskRule.RefreshRate); | |||
| ruleTr.find('.limit').text(taskRule.LimitNum); | |||
| findOr = true; | |||
| break; | |||
| } | |||
| } | |||
| if (!findOr) ruleTr.hide(); | |||
| } | |||
| } | |||
| ruleContainer.show(); | |||
| }, | |||
| error(err) { | |||
| console.log(err); | |||
| ruleContainer.show(); | |||
| }, | |||
| }); | |||
| })(); | |||
| </script> | |||
| @@ -229,6 +229,14 @@ | |||
| </a> | |||
| </div> | |||
| {{end}} | |||
| <!-- 修改任务 --> | |||
| {{if eq .JobType "TRAIN"}} | |||
| <div class="ui compact buttons"> | |||
| <a style="padding: 0.5rem 1rem;" class="ui basic blue button" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 1}}/modelarts/train-job/{{.JobID}}{{else if eq .Cloudbrain.Type 0}}/cloudbrain/train-job/{{.JobID}}{{else if eq .Cloudbrain.Type 2}}/grampus/train-job/{{.JobID}}{{end}}/create_version{{if .VersionName}}?version_name={{.VersionName}}{{end}}"> | |||
| {{$.i18n.Tr "repo.modelarts.modify"}} | |||
| </a> | |||
| </div> | |||
| {{end}} | |||
| <!-- 删除任务 --> | |||
| <form class="ui compact buttons" id="delForm-{{$JobID}}" | |||
| @@ -21,6 +21,11 @@ | |||
| v-if="confirmDatasetList && confirmFlag" | |||
| > | |||
| <input type="hidden" name="attachment" :value="confirmDatasetList" /> | |||
| <input | |||
| type="hidden" | |||
| name="dataset_name" | |||
| :value="confirmDatasetNameList" | |||
| /> | |||
| <div class="multi-dataset-box"> | |||
| <span | |||
| v-for="(item, index) in confirmChecklist" | |||
| @@ -600,6 +605,7 @@ export default { | |||
| checkList: [], | |||
| confirmChecklist: [], | |||
| confirmDatasetList: "", | |||
| confirmDatasetNameList: "", | |||
| confirmFlag: false, | |||
| saveStatusList: [], | |||
| @@ -928,6 +934,7 @@ export default { | |||
| }, | |||
| confirmDataset() { | |||
| this.confirmDatasetList = this.saveStatusList.join(";"); | |||
| this.confirmDatasetNameList = this.checkList.join(";"); | |||
| this.confirmChecklist = this.checkList; | |||
| this.dialogVisible = false; | |||
| this.confirmFlag = true; | |||
| @@ -7,9 +7,9 @@ | |||
| v-if="benchmarkNew" | |||
| class="label-fix-width" | |||
| style="font-weight: normal" | |||
| >{{i18n.image_label}}</label | |||
| >{{ i18n.image_label }}</label | |||
| > | |||
| <label v-else>{{i18n.image_label}}</label> | |||
| <label v-else>{{ i18n.image_label }}</label> | |||
| <input | |||
| v-if="benchmarkNew" | |||
| type="text" | |||
| @@ -17,6 +17,7 @@ | |||
| :value="imageAddress" | |||
| style="width: 48.5%" | |||
| :placeholder="i18n.image_select_placeholder" | |||
| required | |||
| /> | |||
| <input | |||
| v-else | |||
| @@ -24,15 +25,20 @@ | |||
| name="image" | |||
| :value="imageAddress" | |||
| :placeholder="i18n.image_select_placeholder" | |||
| required | |||
| /> | |||
| <el-button | |||
| type="text" | |||
| @click="dialogVisible = true" | |||
| icon="el-icon-plus" | |||
| style="color: #0366d6" | |||
| >{{i18n.image_select}} | |||
| >{{ i18n.image_select }} | |||
| </el-button> | |||
| <el-dialog :title="i18n.image_select" :visible.sync="dialogVisible" width="50%"> | |||
| <el-dialog | |||
| :title="i18n.image_select" | |||
| :visible.sync="dialogVisible" | |||
| width="50%" | |||
| > | |||
| <div | |||
| class="ui icon input" | |||
| style="z-index: 9999; position: absolute; right: 50px; height: 30px" | |||
| @@ -48,7 +54,11 @@ | |||
| /> | |||
| </div> | |||
| <el-tabs v-model="activeName" @tab-click="handleClick"> | |||
| <el-tab-pane :label="i18n.image_public" name="first" v-loading="loadingPublic"> | |||
| <el-tab-pane | |||
| :label="i18n.image_public" | |||
| name="first" | |||
| v-loading="loadingPublic" | |||
| > | |||
| <div | |||
| style=" | |||
| display: flex; | |||
| @@ -120,7 +130,7 @@ | |||
| selectImages(publicData.place, publicData.tag) | |||
| " | |||
| > | |||
| {{i18n.image_use}} | |||
| {{ i18n.image_use }} | |||
| </button> | |||
| </div> | |||
| </div> | |||
| @@ -446,4 +446,142 @@ export default async function initCloudrainSow() { | |||
| html += "</div>"; | |||
| $(`#dir_list${version_name}`).append(html); | |||
| } | |||
| let nameMap, nameList; | |||
| let RepoLink = $(".cloudbrain-type").data("repo-link"); | |||
| let type = $(".cloudbrain-type").data("cloudbrain-type"); | |||
| let flagModel = $(".cloudbrain-type").data("flag-model"); | |||
| // 获取模型列表和模型名称对应的模型版本 | |||
| $(document).ready(function () { | |||
| if (!flagModel) return; | |||
| else { | |||
| $.get( | |||
| `${RepoLink}/modelmanage/query_model_for_predict?type=${type}`, | |||
| (data) => { | |||
| nameMap = data.nameMap; | |||
| nameList = data.nameList; | |||
| let html = `<div class="item"></div>`; | |||
| nameList.forEach((element) => { | |||
| html += `<div class="item" data-value=${element}>${element}</div>`; | |||
| }); | |||
| if (nameList.length !== 0) { | |||
| $("#model_name").append(html); | |||
| } | |||
| let faildModelName = $('input[name="model_name"]').val(); | |||
| let faildModelVersion = $('input[name="model_version"]').val(); | |||
| let faildTrainUrl = $('input[name="pre_train_model_url"]').val(); | |||
| let faildCkptName = $('input[name="ckpt_name"]').val(); | |||
| // 新建错误的表单返回初始化 | |||
| if (faildModelName && nameList.includes(faildModelName)) { | |||
| $("#select_model").dropdown("set text", faildModelName); | |||
| $("#select_model").dropdown("set value", faildModelName); | |||
| $("#select_model_version").dropdown("set text", faildModelVersion); | |||
| $("#select_model_version").dropdown("set value", faildTrainUrl); | |||
| $("#select_model_checkpoint").dropdown("set text", faildCkptName); | |||
| $("#select_model_checkpoint").dropdown("set value", faildCkptName); | |||
| } | |||
| } | |||
| ); | |||
| } | |||
| $("#select_model").dropdown({ | |||
| onChange: function (value, text, $selectedItem) { | |||
| $("#model_name_version").empty(); | |||
| if (value) { | |||
| let html = ""; | |||
| nameMap[value].forEach((element) => { | |||
| let { TrainTaskInfo } = element; | |||
| TrainTaskInfo = JSON.parse(TrainTaskInfo); | |||
| html += `<div class="item" data-label="${element.Label}" data-id="${element.ID}" data-value="${element.Path}">${element.Version}</div>`; | |||
| }); | |||
| $("#model_name_version").append(html); | |||
| const initVersionText = $( | |||
| "#model_name_version div.item:first-child" | |||
| ).text(); | |||
| const initVersionValue = $( | |||
| "#model_name_version div.item:first-child" | |||
| ).data("value"); | |||
| $("#select_model_version").dropdown("set text", initVersionText); | |||
| $("#select_model_version").dropdown( | |||
| "set value", | |||
| initVersionValue, | |||
| initVersionText, | |||
| $("#model_name_version div.item:first-child") | |||
| ); | |||
| } else { | |||
| $("#select_model_version").dropdown("set text", ""); | |||
| $("#select_model_version").dropdown("set value", ""); | |||
| $("#select_model_checkpoint").dropdown("set text", ""); | |||
| $("#select_model_checkpoint").dropdown("set value", ""); | |||
| } | |||
| }, | |||
| }); | |||
| $("#select_model_version").dropdown({ | |||
| onChange: function (value, text, $selectedItem) { | |||
| if (!value) return; | |||
| const dataID = | |||
| $selectedItem && $selectedItem[0].getAttribute("data-id"); | |||
| $("input#ai_model_version").val(text); | |||
| $("#select_model_checkpoint").addClass("loading"); | |||
| $("#model_checkpoint").empty(); | |||
| let html = ""; | |||
| loadCheckpointList(dataID).then((res) => { | |||
| res.forEach((element) => { | |||
| const ckptSuffix = element.FileName.split("."); | |||
| const loadCheckpointFile = [ | |||
| "ckpt", | |||
| "pb", | |||
| "h5", | |||
| "json", | |||
| "pkl", | |||
| "pth", | |||
| "t7", | |||
| "pdparams", | |||
| "onnx", | |||
| "pbtxt", | |||
| "keras", | |||
| "mlmodel", | |||
| "cfg", | |||
| "pt", | |||
| ]; | |||
| if ( | |||
| !element.IsDir && | |||
| loadCheckpointFile.includes(ckptSuffix[ckptSuffix.length - 1]) | |||
| ) { | |||
| html += `<div class="item" data-value=${element.FileName}>${element.FileName}</div>`; | |||
| } | |||
| }); | |||
| $("#model_checkpoint").append(html); | |||
| $("#select_model_checkpoint").removeClass("loading"); | |||
| const initVersionText = $( | |||
| "#model_checkpoint div.item:first-child" | |||
| ).text(); | |||
| const initVersionValue = $( | |||
| "#model_checkpoint div.item:first-child" | |||
| ).data("value"); | |||
| $("#select_model_checkpoint").dropdown("set text", initVersionText); | |||
| $("#select_model_checkpoint").dropdown( | |||
| "set value", | |||
| initVersionValue, | |||
| initVersionText, | |||
| $("#model_name_version div.item:first-child") | |||
| ); | |||
| }); | |||
| }, | |||
| }); | |||
| }); | |||
| function loadCheckpointList(value) { | |||
| return new Promise((resolve, reject) => { | |||
| $.get( | |||
| `${RepoLink}/modelmanage/query_modelfile_for_predict`, | |||
| { ID: value }, | |||
| (data) => { | |||
| resolve(data); | |||
| } | |||
| ); | |||
| }); | |||
| } | |||
| } | |||
| @@ -0,0 +1,161 @@ | |||
| let form = document.getElementById("form_id"); | |||
| let createFlag = false; | |||
| let flag; | |||
| form.onsubmit = function (e) { | |||
| if (createFlag) return false; | |||
| createFlag = true; | |||
| }; | |||
| $("select.dropdown").dropdown(); | |||
| $(document).keydown(function (event) { | |||
| switch (event.keyCode) { | |||
| case 13: | |||
| return false; | |||
| } | |||
| }); | |||
| $(".menu .item").tab(); | |||
| $(document).ready(createParamter()); | |||
| function createParamter() { | |||
| let params = $(".dynamic.field").data("params"); | |||
| params && | |||
| params.parameter.forEach((item, index) => { | |||
| Add_parameter(index, (flag = true), item); | |||
| }); | |||
| } | |||
| // 参数增加、删除、修改、保存 | |||
| function Add_parameter(i, flag = false, paramsObject = {}) { | |||
| let value = ""; | |||
| value += `<div class="two fields width85" id= "para${i}">`; | |||
| value += '<div class="field">'; | |||
| let placeholder_value = $(".dynamic.field").data("params-value"); | |||
| let placeholder_name = $(".dynamic.field").data("params-name"); | |||
| if (flag) { | |||
| value += `<input type="text" class="shipping_first-name" value="${paramsObject.label}">`; | |||
| } else { | |||
| value += | |||
| '<input type="text" class="shipping_first-name" required placeholder="' + | |||
| placeholder_name + | |||
| '">'; | |||
| } | |||
| value += "</div>"; | |||
| value += '<div class="field">'; | |||
| if (flag) { | |||
| value += `<input type="text" class="shipping_last-name" value="${paramsObject.value}">`; | |||
| } else { | |||
| value += | |||
| '<input type="text" class="shipping_last-name" required placeholder="' + | |||
| placeholder_value + | |||
| '">'; | |||
| } | |||
| value += "</div>"; | |||
| value += '<span><i class="trash icon"></i></span>'; | |||
| value += "</div>"; | |||
| $(".dynamic.field").append(value); | |||
| } | |||
| $("#add_run_para").click(function () { | |||
| var len = $(".dynamic.field .two.fields").length; | |||
| Add_parameter(len); | |||
| }); | |||
| $(".dynamic.field").on("click", ".trash.icon", function () { | |||
| var index = $(this).parent().parent().index(); | |||
| $(this).parent().parent().remove(); | |||
| var len = $(".dynamic.field .two.fields").length; | |||
| $(".dynamic.field .two.fields").each(function () { | |||
| var cur_index = $(this).index(); | |||
| $(this).attr("id", "para" + cur_index); | |||
| }); | |||
| }); | |||
| $(".question.circle.icon").hover(function () { | |||
| $(this).popup("show"); | |||
| }); | |||
| var isValidate = false; | |||
| function validate() { | |||
| $(".ui.form").form({ | |||
| on: "blur", | |||
| inline: true, | |||
| fields: { | |||
| boot_file: { | |||
| identifier: "boot_file", | |||
| rules: [ | |||
| { | |||
| type: "regExp[/.+.py$/g]", | |||
| prompt: "启动文件必须为.py结尾", | |||
| }, | |||
| ], | |||
| }, | |||
| job_name: { | |||
| identifier: "job_name", | |||
| rules: [ | |||
| { | |||
| type: "regExp[/^[a-zA-Z0-9-_]{1,36}$/]", | |||
| prompt: "只包含大小写字母、数字、_和-,最长36个字符。", | |||
| }, | |||
| ], | |||
| }, | |||
| display_job_name: { | |||
| identifier: "display_job_name", | |||
| rules: [ | |||
| { | |||
| type: "regExp[/^[a-zA-Z0-9-_]{1,36}$/]", | |||
| prompt: "只包含大小写字母、数字、_和-,最长36个字符。", | |||
| }, | |||
| ], | |||
| }, | |||
| attachment: { | |||
| identifier: "attachment", | |||
| rules: [ | |||
| { | |||
| type: "empty", | |||
| prompt: "选择一个数据集", | |||
| }, | |||
| ], | |||
| }, | |||
| spec_id: { | |||
| identifier: "spec_id", | |||
| rules: [{ type: "empty" }], | |||
| }, | |||
| }, | |||
| onSuccess: function () { | |||
| // $('.ui.page.dimmer').dimmer('show') | |||
| document.getElementById("mask").style.display = "block"; | |||
| isValidate = true; | |||
| }, | |||
| onFailure: function (e) { | |||
| isValidate = false; | |||
| return false; | |||
| }, | |||
| }); | |||
| } | |||
| document.onreadystatechange = function () { | |||
| if (document.readyState === "complete") { | |||
| document.getElementById("mask").style.display = "none"; | |||
| } | |||
| }; | |||
| function send_run_para() { | |||
| var run_parameters = []; | |||
| var msg = {}; | |||
| $(".dynamic.field .two.fields").each(function () { | |||
| var para_name = $(this).find("input.shipping_first-name").val(); | |||
| var para_value = $(this).find("input.shipping_last-name").val(); | |||
| run_parameters.push({ label: para_name, value: para_value }); | |||
| }); | |||
| msg["parameter"] = run_parameters; | |||
| msg = JSON.stringify(msg); | |||
| $("#store_run_para").val(msg); | |||
| } | |||
| function get_name() { | |||
| let name1 = $("#engine_name .text").text(); | |||
| let name2 = $("#flaver_name .text").text(); | |||
| $("input#ai_engine_name").val(name1); | |||
| $("input#ai_flaver_name").val(name2); | |||
| } | |||
| validate(); | |||
| $(".ui.create_train_job.green.button").click(function (e) { | |||
| get_name(); | |||
| send_run_para(); | |||
| validate(); | |||
| }); | |||
| @@ -16,11 +16,11 @@ | |||
| </div> | |||
| </div> | |||
| <div class="__r_p_summary"> | |||
| <div class="__r_p_summary_item-c __flex-1"> | |||
| <div class="__r_p_summary_item-c __flex-1" style="position:relative;"> | |||
| <div class="__val">{{ summaryInfo.available }}</div> | |||
| <div class="__exp">{{ $t('CurrAvailableCalcPoints') }}</div> | |||
| </div> | |||
| <div class="__r_p_summary_line"></div> | |||
| <div class="__r_p_summary_line"></div> | |||
| </div> | |||
| <div class="__r_p_summary_item-c __flex-1"> | |||
| <div class="__val">{{ summaryInfo.gain }}</div> | |||
| <div class="__exp">{{ $t('totalGainCalcPoints') }}</div> | |||
| @@ -28,7 +28,7 @@ | |||
| <div class="__r_p_summary_item-c __flex-1"> | |||
| <div class="__val">{{ summaryInfo.used }}</div> | |||
| <div class="__exp">{{ $t('totalConsumeCalcPoints') }}</div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="__r_p_tab"> | |||
| <div class="__r_p_tab-item" :class="tabIndex === 0 ? '__focus' : ''" style="border-radius: 5px 0px 0px 5px" | |||
| @@ -267,9 +267,12 @@ export default { | |||
| } | |||
| .__r_p_summary_line { | |||
| position: absolute; | |||
| top: 0; | |||
| right: 1px; | |||
| width: 1px; | |||
| height: 80%; | |||
| background-color: rgb(212, 212, 213); | |||
| height: 100%; | |||
| border-right: 1px solid rgb(212, 212, 213); | |||
| } | |||
| .__r_p_tab { | |||