diff --git a/.gitignore b/.gitignore index ceeeaa92c..aca4040d2 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ coverage.all /custom/conf/app.ini !/custom/conf/app.ini.sample /custom/public/kanban +/custom/public/annual-report /data /indexers /log diff --git a/custom/public/css/placeholder-home.css b/custom/public/css/placeholder-home.css new file mode 100644 index 000000000..9f0431def --- /dev/null +++ b/custom/public/css/placeholder-home.css @@ -0,0 +1 @@ +/* placeholder-home.css */ diff --git a/custom/public/css/placeholder.css b/custom/public/css/placeholder.css new file mode 100644 index 000000000..1ae0f997e --- /dev/null +++ b/custom/public/css/placeholder.css @@ -0,0 +1 @@ +/* placeholder.css */ diff --git a/custom/public/img/home-banner-02-1.jpg b/custom/public/img/home-banner-02-1.jpg new file mode 100644 index 000000000..13a090eac Binary files /dev/null and b/custom/public/img/home-banner-02-1.jpg differ diff --git a/custom/public/img/home-banner-02-2.png b/custom/public/img/home-banner-02-2.png new file mode 100644 index 000000000..c48c347de Binary files /dev/null and b/custom/public/img/home-banner-02-2.png differ diff --git a/custom/public/img/logo-w-origin.svg b/custom/public/img/logo-w-origin.svg new file mode 100644 index 000000000..133f63d23 --- /dev/null +++ b/custom/public/img/logo-w-origin.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + diff --git a/custom/public/img/logo-w.svg b/custom/public/img/logo-w.svg index 133f63d23..48308634c 100644 --- a/custom/public/img/logo-w.svg +++ b/custom/public/img/logo-w.svg @@ -1,45 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/custom/public/js/placeholder-home.js b/custom/public/js/placeholder-home.js new file mode 100644 index 000000000..f967c5fcb --- /dev/null +++ b/custom/public/js/placeholder-home.js @@ -0,0 +1 @@ +/* placeholder-home.js */ diff --git a/custom/public/js/placeholder.js b/custom/public/js/placeholder.js new file mode 100644 index 000000000..e2c4bcff7 --- /dev/null +++ b/custom/public/js/placeholder.js @@ -0,0 +1 @@ +/* placeholder.js */ diff --git a/models/action.go b/models/action.go index 869acb762..6d93fbcd3 100755 --- a/models/action.go +++ b/models/action.go @@ -67,6 +67,7 @@ const ( ActionChangeUserAvatar //38 ActionCreateGrampusNPUDebugTask //39 ActionCreateGrampusGPUDebugTask //40 + ActionCreateGrampusGCUDebugTask //41 ) // Action represents user operation type and other information to @@ -380,7 +381,8 @@ func (a *Action) IsCloudbrainAction() bool { ActionCreateGrampusGPUDebugTask, ActionCreateGrampusNPUDebugTask, ActionCreateGrampusNPUTrainTask, - ActionCreateGrampusGPUTrainTask: + ActionCreateGrampusGPUTrainTask, + ActionCreateGrampusGCUDebugTask: return true } return false diff --git a/models/cloudbrain.go b/models/cloudbrain.go index 85e3c36f8..e0df17753 100755 --- a/models/cloudbrain.go +++ b/models/cloudbrain.go @@ -30,11 +30,13 @@ const ( TypeCDCenter //成都智算中心 TypeCloudBrainAll = -1 + AccCardsNumAll = -1 ) const ( NPUResource = "NPU" GPUResource = "CPU/GPU" + GCUResource = "GCU" AllResource = "all" //notebook storage category @@ -135,6 +137,11 @@ const ( //ComputeResource GPU = "GPU" NPU = "NPU" + GCU = "GCU" +) + +const ( + AIModelPath = "aimodels/" ) type Cloudbrain struct { @@ -180,14 +187,14 @@ type Cloudbrain struct { AiCenter string //grampus ai center: center_id+center_name TrainUrl string //输出模型的obs路径 - BranchName string //分支名称 + BranchName string `xorm:"varchar(2550)"` //分支名称 Parameters string //传给modelarts的param参数 - BootFile string //启动文件 + BootFile string `xorm:"varchar(2550)"` //启动文件 DataUrl string `xorm:"varchar(3500)"` //数据集的obs路径 LogUrl string //日志输出的obs路径 PreVersionId int64 //父版本的版本id FlavorCode string //modelarts上的规格id - Description string `xorm:"varchar(256)"` //描述 + Description string `xorm:"varchar(2550)"` //描述 WorkServerNumber int //节点数 FlavorName string //规格名称 EngineName string //引擎名称 @@ -303,6 +310,9 @@ func (task *Cloudbrain) IsUserHasRight(user *User) bool { func (task *Cloudbrain) IsGPUTask() bool { return task.ComputeResource == GPUResource } +func (task *Cloudbrain) IsGCUTask() bool { + return task.ComputeResource == GCUResource +} func (task *Cloudbrain) IsNPUTask() bool { return task.ComputeResource == NPUResource } @@ -2653,6 +2663,7 @@ type DatasetInfo struct { DataLocalPath string Name string FullName string + Type int Size int } @@ -2693,8 +2704,14 @@ func GetDatasetInfo(uuidStr string, grampusType ...string) (map[string]DatasetIn 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 { + } else if grampusType[0] == NPU { dataLocalPath = setting.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID + "/" + } else if grampusType[0] == GCU { + if attach.Type == TypeCloudBrainOne { + 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 + "/" + } } } else { @@ -2709,6 +2726,7 @@ func GetDatasetInfo(uuidStr string, grampusType ...string) (map[string]DatasetIn DataLocalPath: dataLocalPath, Name: fileName, FullName: attach.Name, + Type: attach.Type, Size: int(attach.Size), } if i == 0 { diff --git a/models/task_config.go b/models/task_config.go index f86032fc9..14ca6b223 100644 --- a/models/task_config.go +++ b/models/task_config.go @@ -39,6 +39,7 @@ func GetTaskTypeFromAction(a ActionType) TaskType { ActionCreateGrampusGPUDebugTask, ActionCreateGrampusNPUDebugTask, ActionCreateGrampusNPUTrainTask, + ActionCreateGrampusGCUDebugTask, ActionCreateGrampusGPUTrainTask: return TaskCreateCloudbrainTask case ActionCreateRepo: diff --git a/models/user_analysis_for_activity.go b/models/user_analysis_for_activity.go index 99ff990ce..d872669e6 100644 --- a/models/user_analysis_for_activity.go +++ b/models/user_analysis_for_activity.go @@ -1,6 +1,7 @@ package models import ( + "encoding/json" "fmt" "time" @@ -450,19 +451,42 @@ func QueryUserLoginInfo(userIds []int64) []*UserLoginLog { return loginList } +var WeekBonusData = make(map[int64][]int) + func QueryUserAnnualReport(userId int64) *UserSummaryCurrentYear { statictisSess := xStatistic.NewSession() defer statictisSess.Close() log.Info("userId=" + fmt.Sprint(userId)) + if len(WeekBonusData) == 0 { + WeekBonusData = getBonusWeekDataMap() + } reList := make([]*UserSummaryCurrentYear, 0) err := statictisSess.Select("*").Table(new(UserSummaryCurrentYear)).Where("id=" + fmt.Sprint(userId)).Find(&reList) if err == nil { if len(reList) > 0 { + record, ok := WeekBonusData[userId] + if ok { + bonusInfo := make(map[string]int) + bonusInfo["order"] = record[0] + bonusInfo["money"] = record[1] + bonusInfo["week"] = record[2] + bonusInfo["num"] = record[3] + bonusInfoJson, _ := json.Marshal(bonusInfo) + reList[0].WeekBonusData = string(bonusInfoJson) + } return reList[0] } } else { log.Info("error:=" + err.Error()) } + dbuser, err := GetUserByID(userId) + if err == nil { + return &UserSummaryCurrentYear{ + ID: dbuser.ID, + Name: dbuser.Name, + RegistDate: dbuser.CreatedUnix, + } + } return nil } diff --git a/models/user_business_analysis.go b/models/user_business_analysis.go index d5ab871ce..cf0ad7e1a 100644 --- a/models/user_business_analysis.go +++ b/models/user_business_analysis.go @@ -880,6 +880,76 @@ func isUserYearData(tableName string) bool { return false } +func getBonusWeekDataMap() map[int64][]int { + bonusMap := make(map[int64][]int) + url := setting.RecommentRepoAddr + "bonus/weekdata/record.txt" + content, err := GetContentFromPromote(url) + if err == nil { + filenames := strings.Split(content, "\n") + for i := 0; i < len(filenames); i++ { + if strings.HasSuffix(filenames[i], "\r") { + filenames[i] = filenames[i][0 : len(filenames[i])-len("\r")] + } + url = setting.RecommentRepoAddr + "bonus/weekdata/" + filenames[i] + csvContent, err1 := GetContentFromPromote(url) + if err1 == nil { + //read csv + lines := strings.Split(csvContent, "\n") + for j := 1; j < len(lines); j++ { + if strings.HasSuffix(lines[j], "\r") { + lines[j] = lines[j][0 : len(lines[j])-len("\r")] + } + log.Info("aLine=" + lines[j]) + aLine := strings.Split(lines[j], ",") + if len(aLine) < 4 { + continue + } + userId := getInt64Value(aLine[0]) + order := getIntValue(aLine[2]) + money := getIntValue(aLine[3]) + week, num := getWeekAndNum(filenames[i]) + //log.Info("userId=" + fmt.Sprint(userId) + " order=" + fmt.Sprint(order) + " money=" + fmt.Sprint(money) + " week=" + fmt.Sprint(week) + " num=" + fmt.Sprint(num)) + //email := lines[2] + record, ok := bonusMap[userId] + if !ok { + record = make([]int, 4) + record[0] = order + record[1] = money + record[2] = week + record[3] = num + bonusMap[userId] = record + } else { + if record[0] > order { + record[0] = order + record[1] = money + record[2] = week + record[3] = num + } else { + if record[0] == order && record[1] < money { + record[1] = money + record[2] = week + record[3] = num + } + } + } + } + } + } + } + return bonusMap +} + +func getWeekAndNum(name string) (int, int) { + name = name[0 : len(name)-4] + tmp := strings.Split(name, "_") + if len(tmp) == 2 { + week := getIntValue(tmp[0]) + num := getIntValue(tmp[1]) + return week, num + } + return 0, 0 +} + func getBonusMap() map[string]map[string]int { bonusMap := make(map[string]map[string]int) url := setting.RecommentRepoAddr + "bonus/record.txt" @@ -887,12 +957,18 @@ func getBonusMap() map[string]map[string]int { if err == nil { filenames := strings.Split(content, "\n") for i := 0; i < len(filenames); i++ { + if strings.HasSuffix(filenames[i], "\r") { + filenames[i] = filenames[i][0 : len(filenames[i])-len("\r")] + } url = setting.RecommentRepoAddr + "bonus/" + filenames[i] csvContent, err1 := GetContentFromPromote(url) if err1 == nil { //read csv lines := strings.Split(csvContent, "\n") for j := 1; j < len(lines); j++ { + if strings.HasSuffix(lines[j], "\r") { + lines[j] = lines[j][0 : len(lines[j])-len("\r")] + } aLine := strings.Split(lines[j], ",") if len(aLine) < 7 { continue @@ -923,6 +999,14 @@ func getIntValue(val string) int { return 0 } +func getInt64Value(val string) int64 { + i, err := strconv.ParseInt(val, 10, 64) + if err == nil { + return i + } + return 0 +} + func getPlayARoll(bonusMap map[string]map[string]int, userName string, scoreMap map[string]float64) string { bonusInfo := make(map[string]string) record, ok := bonusMap[userName] @@ -959,19 +1043,16 @@ func getCloudBrainInfo(dateRecordAll UserBusinessAnalysisAll, CloudBrainTaskItem trainscore = float64(dateRecordAll.GpuTrainJob+dateRecordAll.NpuTrainJob) / float64(50) } cloudBrainInfo["inference_task_num"] = fmt.Sprint(dateRecordAll.NpuInferenceJob + CloudBrainTaskItemMap[fmt.Sprint(dateRecordAll.ID)+"_GpuInferenceJob"]) + cloudBrainInfo["benchmark_task_num"] = fmt.Sprint(dateRecordAll.GpuBenchMarkJob) cloudBrainInfo["card_runtime"] = fmt.Sprint(dateRecordAll.CloudBrainRunTime) - if dateRecordAll.CloudBrainRunTime >= 100 { - runtime = float64(dateRecordAll.CloudBrainRunTime) / float64(100) - } cloudBrainInfo["card_runtime_money"] = fmt.Sprint(dateRecordAll.CloudBrainRunTime * 5) cloudBrainInfo["CloudBrainOne"] = fmt.Sprint(CloudBrainTaskItemMap[fmt.Sprint(dateRecordAll.ID)+"_CloudBrainOne"]) cloudBrainInfo["CloudBrainTwo"] = fmt.Sprint(CloudBrainTaskItemMap[fmt.Sprint(dateRecordAll.ID)+"_CloudBrainTwo"]) cloudBrainInfo["C2Net"] = fmt.Sprint(CloudBrainTaskItemMap[fmt.Sprint(dateRecordAll.ID)+"_C2Net"]) - cloudBrainInfoJson, _ := json.Marshal(cloudBrainInfo) scoreMap["trainscore"] = trainscore scoreMap["debugscore"] = debugscore - scoreMap["runtime"] = runtime + return string(cloudBrainInfoJson) } else { scoreMap["trainscore"] = trainscore @@ -1311,7 +1392,7 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, useMetrics.TotalActivateRegistUser = getMapKeyStringValue("TotalActivateRegistUser", userMetrics) useMetrics.TotalHasActivityUser = getMapKeyStringValue("TotalHasActivityUser", userMetrics) useMetrics.CurrentDayRegistUser = getMapKeyStringValue("CurrentDayRegistUser", userMetrics) - count, err = sess.Where("type=0").Count(new(User)) + count, err = sess.Where("type=0 and created_unix<=" + fmt.Sprint(end_unix)).Count(new(User)) if err != nil { log.Info("query user error. return.") } @@ -2416,7 +2497,7 @@ func queryCloudBrainTask(start_unix int64, end_unix int64) (map[int64]int, map[s var indexTotal int64 indexTotal = 0 for { - sess.Select("id,job_type,user_id,duration,train_job_duration,type").Table("cloudbrain").Unscoped().Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) + sess.Select("id,job_type,user_id,duration,train_job_duration,type,compute_resource").Table("cloudbrain").Unscoped().Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) cloudTaskList := make([]*Cloudbrain, 0) sess.Find(&cloudTaskList) log.Info("query cloudbrain size=" + fmt.Sprint(len(cloudTaskList))) @@ -2435,6 +2516,8 @@ func queryCloudBrainTask(start_unix int64, end_unix int64) (map[int64]int, map[s setMapKey("NpuTrainJob", cloudTaskRecord.UserID, 1, resultItemMap) } else if cloudTaskRecord.JobType == "INFERENCE" { setMapKey("NpuInferenceJob", cloudTaskRecord.UserID, 1, resultItemMap) + } else if cloudTaskRecord.JobType == "BENCHMARK" || cloudTaskRecord.JobType == "MODELSAFETY" { + setMapKey("GpuBenchMarkJob", cloudTaskRecord.UserID, 1, resultItemMap) } else { setMapKey("NpuDebugJob", cloudTaskRecord.UserID, 1, resultItemMap) } @@ -2444,12 +2527,12 @@ func queryCloudBrainTask(start_unix int64, end_unix int64) (map[int64]int, map[s setMapKey("GpuTrainJob", cloudTaskRecord.UserID, 1, resultItemMap) } else if cloudTaskRecord.JobType == "INFERENCE" { setMapKey("GpuInferenceJob", cloudTaskRecord.UserID, 1, resultItemMap) - } else if cloudTaskRecord.JobType == "BENCHMARK" { + } else if cloudTaskRecord.JobType == "BENCHMARK" || cloudTaskRecord.JobType == "MODELSAFETY" { setMapKey("GpuBenchMarkJob", cloudTaskRecord.UserID, 1, resultItemMap) } else { setMapKey("GpuDebugJob", cloudTaskRecord.UserID, 1, resultItemMap) } - } else if cloudTaskRecord.Type == 2 { + } else if cloudTaskRecord.Type == 2 || cloudTaskRecord.Type == 3 { setMapKey("C2Net", cloudTaskRecord.UserID, 1, resultItemMap) if cloudTaskRecord.ComputeResource == NPUResource { if cloudTaskRecord.JobType == "TRAIN" { diff --git a/models/user_business_struct.go b/models/user_business_struct.go index 00c7f6176..61f499732 100644 --- a/models/user_business_struct.go +++ b/models/user_business_struct.go @@ -18,9 +18,9 @@ type UserSummaryCurrentYear struct { CodeInfo string `xorm:"varchar(500)"` //代码提交次数,提交总代码行数,最晚的提交时间 CloudBrainInfo string `xorm:"varchar(1000)"` //,创建了XX 个云脑任务,调试任务XX 个,训练任务XX 个,推理任务XX 个,累计运行了XXXX 卡时,累计节省xxxxx 元 //这些免费的算力资源分别有,XX% 来自鹏城云脑1,XX% 来自鹏城云脑2,XX% 来自智算网络 - PlayARoll string `xorm:"varchar(500)"` //你参加了XX 次“我为开源打榜狂”活动,累计上榜XX 次,总共获得了社区XXX 元的激励 - - Label string `xorm:"varchar(500)"` + PlayARoll string `xorm:"varchar(500)"` //你参加了XX 次“我为开源打榜狂”活动,累计上榜XX 次,总共获得了社区XXX 元的激励 + WeekBonusData string `xorm:"-"` + Label string `xorm:"varchar(500)"` } type UserBusinessAnalysisCurrentYear struct { diff --git a/modules/context/auth.go b/modules/context/auth.go index efde3bc2e..c9af1456d 100755 --- a/modules/context/auth.go +++ b/modules/context/auth.go @@ -81,7 +81,12 @@ func Toggle(options *ToggleOptions) macaron.Handler { // Redirect to dashboard if user tries to visit any non-login page. if options.SignOutRequired && ctx.IsSigned && ctx.Req.URL.RequestURI() != "/" { - ctx.Redirect(setting.AppSubURL + "/") + redirectTo := ctx.Query("redirect_to") + if len(redirectTo) > 0 { + ctx.Redirect(redirectTo) + } else { + ctx.Redirect(setting.AppSubURL + "/") + } return } diff --git a/modules/grampus/grampus.go b/modules/grampus/grampus.go index 37e6fc1bf..b65b42bdd 100755 --- a/modules/grampus/grampus.go +++ b/modules/grampus/grampus.go @@ -19,6 +19,7 @@ const ( ProcessorTypeNPU = "npu.huawei.com/NPU" ProcessorTypeGPU = "nvidia.com/gpu" + ProcessorTypeGCU = "enflame-tech.com/gcu" GpuWorkDir = "/tmp/" NpuWorkDir = "/cache/" @@ -108,6 +109,7 @@ type GenerateNotebookJobReq struct { Spec *models.Specification CodeName string ModelPath string //参考启智GPU调试, 挂载/model目录用户的模型可以输出到这个目录 + ModelStorageType int } func getEndPoint() string { @@ -148,6 +150,36 @@ func getDatasetGPUGrampus(datasetInfos map[string]models.DatasetInfo) ([]models. } return datasetGrampus, command } +func getDatasetGCUGrampus(datasetInfos map[string]models.DatasetInfo) ([]models.GrampusDataset, string) { + var datasetGrampus []models.GrampusDataset + var command = "" + obsEndPoint := getEndPoint() + for uuid, datasetInfo := range datasetInfos { + if datasetInfo.Type == models.TypeCloudBrainOne { + datasetGrampus = append(datasetGrampus, models.GrampusDataset{ + Name: datasetInfo.FullName, + Bucket: setting.Attachment.Minio.Bucket, + EndPoint: setting.Attachment.Minio.Endpoint, + ObjectKey: datasetInfo.DataLocalPath, + ReadOnly: true, + ContainerPath: "/dataset1/" + datasetInfo.Name, + }) + + command += "cp /dataset1/'" + datasetInfo.Name + "'/" + uuid + " /dataset/'" + datasetInfo.FullName + "';" + + } else { + datasetGrampus = append(datasetGrampus, models.GrampusDataset{ + Name: datasetInfo.FullName, + Bucket: setting.Bucket, + EndPoint: obsEndPoint, + ObjectKey: datasetInfo.DataLocalPath + datasetInfo.FullName, + ContainerPath: "/dataset/" + datasetInfo.Name, + }) + } + + } + return datasetGrampus, command +} func GenerateNotebookJob(ctx *context.Context, req *GenerateNotebookJobReq) (jobId string, err error) { createTime := timeutil.TimeStampNow() @@ -178,25 +210,45 @@ func GenerateNotebookJob(ctx *context.Context, req *GenerateNotebookJobReq) (job imageUrl = "" req.Command = "" } else { - datasetGrampus, cpCommand = getDatasetGPUGrampus(req.DatasetInfos) + if ProcessorTypeGCU == req.ProcessType { + datasetGrampus, cpCommand = getDatasetGCUGrampus(req.DatasetInfos) + } else { + datasetGrampus, cpCommand = getDatasetGPUGrampus(req.DatasetInfos) + } if len(req.ModelName) != 0 { - datasetGrampus = append(datasetGrampus, models.GrampusDataset{ - Name: req.ModelName, - Bucket: setting.Attachment.Minio.Bucket, - EndPoint: setting.Attachment.Minio.Endpoint, - ObjectKey: req.PreTrainModelPath, - ReadOnly: true, - ContainerPath: cloudbrain.PretrainModelMountPath, - }) + if req.ModelStorageType == models.TypeCloudBrainOne { + datasetGrampus = append(datasetGrampus, models.GrampusDataset{ + Name: req.ModelName, + Bucket: setting.Attachment.Minio.Bucket, + EndPoint: setting.Attachment.Minio.Endpoint, + ObjectKey: req.PreTrainModelPath, + ReadOnly: true, + ContainerPath: cloudbrain.PretrainModelMountPath, + }) + } else { + datasetGrampus = append(datasetGrampus, models.GrampusDataset{ + Name: req.ModelName, + Bucket: setting.Bucket, + EndPoint: getEndPoint(), + ReadOnly: true, + ObjectKey: req.PreTrainModelPath, + ContainerPath: cloudbrain.PretrainModelMountPath, + }) + } + } + codeArchiveName := cloudbrain.DefaultBranchName + ".zip" codeGrampus = models.GrampusDataset{ Name: req.CodeName, Bucket: setting.Attachment.Minio.Bucket, EndPoint: setting.Attachment.Minio.Endpoint, - ObjectKey: req.CodeStoragePath + cloudbrain.DefaultBranchName + ".zip", + ObjectKey: req.CodeStoragePath + codeArchiveName, ReadOnly: false, ContainerPath: cloudbrain.CodeMountPath, } + if ProcessorTypeGCU == req.ProcessType { + imageUrl = "" + } req.Command = fmt.Sprintf(CommandGpuDebug, cpCommand, setting.CullIdleTimeout, setting.CullIdleTimeout, setting.CullInterval, setting.CullIdleTimeout, setting.CullInterval) log.Info("debug command:" + req.Command) @@ -215,6 +267,7 @@ func GenerateNotebookJob(ctx *context.Context, req *GenerateNotebookJobReq) (job AutoStopDuration: autoStopDurationMs, Capacity: setting.Capacity, Command: req.Command, + CenterID: req.Spec.GetAvailableCenterIds(ctx.User.ID), }, }, }) @@ -263,6 +316,8 @@ func GenerateNotebookJob(ctx *context.Context, req *GenerateNotebookJobReq) (job actionType = models.ActionCreateGrampusNPUDebugTask } else if req.ComputeResource == models.GPUResource { actionType = models.ActionCreateGrampusGPUDebugTask + } else if req.ComputeResource == models.GCUResource { + actionType = models.ActionCreateGrampusGCUDebugTask } task, err := models.GetCloudbrainByJobID(jobID) if err != nil { diff --git a/modules/storage/minio_ext.go b/modules/storage/minio_ext.go index d4a8abba5..6aeb89aab 100755 --- a/modules/storage/minio_ext.go +++ b/modules/storage/minio_ext.go @@ -391,3 +391,19 @@ func GetPartInfos(objectName string, uploadID string) (string, error) { return chunks, nil } + +func IsObjectExist4Minio(bucket, objectName string) (bool, error) { + _, core, err := getClients() + if err != nil { + log.Error("getClients failed:", err.Error()) + return false, err + } + + _, err = core.StatObject(bucket, objectName, miniov6.StatObjectOptions{}) + if err != nil { + log.Error("GetObjectMetadata error.%v", err) + return false, err + } + + return true, nil +} diff --git a/modules/storage/obs.go b/modules/storage/obs.go index 83b03ed44..d00d000b5 100755 --- a/modules/storage/obs.go +++ b/modules/storage/obs.go @@ -614,7 +614,7 @@ func ObsCreateObject(path string) error { return nil } -func GetObsLogFileName(prefix string) (string, error) { +func GetObsLogFileName(prefix string) ([]FileInfo, error) { input := &obs.ListObjectsInput{} input.Bucket = setting.Bucket input.Prefix = prefix @@ -622,10 +622,39 @@ func GetObsLogFileName(prefix string) (string, error) { output, err := ObsCli.ListObjects(input) if err != nil { log.Error("PutObject failed:", err.Error()) - return "", err + return nil, err } if output == nil || len(output.Contents) == 0 { - return "", errors.New("obs log files not exist") + return nil, errors.New("obs log files not exist") + } + fileInfos := make([]FileInfo, 0) + for _, val := range output.Contents { + //result[num] = c.Key + if strings.HasSuffix(val.Key, ".log") { + log.Info("log fileName=" + val.Key) + fileInfo := FileInfo{ + ModTime: val.LastModified.Local().Format("2006-01-02 15:04:05"), + FileName: val.Key[len(prefix)-3:], //加上 job + Size: val.Size, + IsDir: false, + ParenDir: prefix[0 : len(prefix)-3], + } + fileInfos = append(fileInfos, fileInfo) + } + + } + return fileInfos, nil +} + +func IsObjectExist4Obs(bucket, key string) (bool, error) { + + _, err := ObsCli.GetObjectMetadata(&obs.GetObjectMetadataInput{ + Bucket: bucket, + Key: key, + }) + if err != nil { + log.Error("GetObjectMetadata error.%v", err) + return false, err } - return output.Contents[0].Key, nil + return true, nil } diff --git a/modules/templates/helper.go b/modules/templates/helper.go index 88c63c8c7..ce8c5dfe7 100755 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -106,7 +106,8 @@ func NewFuncMap() []template.FuncMap { "SafeJS": SafeJS, "Str2html": Str2html, "subOne": subOne, - "addOne": addOne, + "addOne": addOne, + "TimeStampNow": timeutil.TimeStampNow, "TimeSince": timeutil.TimeSince, "TimeSinceUnix": timeutil.TimeSinceUnix, "TimeSinceUnix1": timeutil.TimeSinceUnix1, @@ -367,6 +368,7 @@ func NewTextFuncMap() []texttmpl.FuncMap { "AppDomain": func() string { return setting.Domain }, + "TimeStampNow": timeutil.TimeStampNow, "TimeSince": timeutil.TimeSince, "TimeSinceUnix": timeutil.TimeSinceUnix, "TimeSinceUnix1": timeutil.TimeSinceUnix1, diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 59c8f100b..5fc02c609 100755 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -406,6 +406,8 @@ sspi_auth_failed = SSPI authentication failed change_email = Change email change_email_address = Change email address new_email_address = New email address +openi_community_really_awesome = OpenI, Really Awesome! + [phone] format_err=The format of phone number is wrong. query_err=Fail to query phone number, please try again later. @@ -1061,6 +1063,8 @@ model_rename=Duplicate model name, please modify model name. notebook_file_not_exist=Notebook file does not exist. notebook_select_wrong=Please select a Notebook(.ipynb) file first. +notebook_path_too_long=The total length of selected file or files path exceed 255 characters, please select a shorter path file or change the file path. +notebook_branch_name_too_long=The total length of branch or branches name exceed 255 characters, please select a file in other branch. notebook_file_no_right=You have no right to access the Notebook(.ipynb) file. notebook_repo_conflict=The files in different branches of the same repository can not run together. debug_again_fail=Fail to restart debug task, please try again later. @@ -1095,8 +1099,8 @@ image_delete_fail=Failed to delete image, please try again later. image_overwrite=You had submitted the same name image before, are you sure to overwrite the original image? download=Download score=Score -wait_count_start = Your current queue position is -wait_count_end = +wait_count_start = Your current queue position is +wait_count_end = file_limit_100 = Display up to 100 files or folders in a single directory images.name = Image Tag images.name_placerholder = Please enter the image name @@ -1261,6 +1265,13 @@ modelarts.fullscreen_log_file = View in full screen modelarts.exit_full_screen = Exit fullscreen modelarts.no_node_right = The value of 'Amount of Compute Node' is wrong, you have no right to use the current value of 'Amount of Compute Node'. +scrolled_logs_top = You have scrolled to the top of the log +scrolled_logs_top_pls_retry = You have scrolled to the top of the log, please try again later! +scrolled_logs_bottom = You have scrolled to the bottom of the log +scrolled_logs_bottom_pls_retry = You have scrolled to the bottom of the log, please try again later! + +canceled_operation = You have canceled the operation +successfully_deleted = Successfully deleted debug_task_not_created = Debug task has not been created train_task_not_created = Train task has not been created @@ -1349,6 +1360,7 @@ modelconvert.inputshapeerror=Format input error, please input such as: 1,1,32,32 modelconvert.manage.create_error1=A model transformation task with the same name already exists. modelconvert.manage.create_error2=Only one running model transformation task can be created. modelconvert.manage.model_not_exist=The model in the task does not exist or has been deleted. +modelconvert.manage.model_file_not_exist=The model file in the task does not exist or has been deleted. modelconvert.manage.no_operate_right=You have no right to do the operation. debug.manage.model_not_exist=The model in the task does not exist or has been deleted, please create a new debug job. @@ -1474,7 +1486,7 @@ blame = Blame normal_view = Normal View line = line lines = lines -notebook_open = Open in Notebook +notebook_open = Run Online editor.new_file = New File editor.upload_file = Upload File @@ -3135,6 +3147,7 @@ task_gpudebugjob=`created CPU/GPU type debugging task %s` task_c2net_gpudebugjob=`created CPU/GPU type debugging task %s` task_c2net_npudebugjob=`created NPU type debugging task %s` +task_c2ent_gcudebugjob=`created GCU type debugging task %s` task_nputrainjob=`created NPU training task %s` task_inferencejob=`created reasoning task %s` task_benchmark=`created profiling task %s` @@ -3295,6 +3308,7 @@ point_hr = Point/hr DEBUG = DEBUG SNN4IMAGENET = BENCHMARK BRAINSCORE = BENCHMARK +SNN4ECOSET = BENCHMARK MODELSAFETY = BENCHMARK TRAIN = TRAIN INFERENCE = INFERENCE @@ -3309,6 +3323,7 @@ Stopped_success_update_status_fail=Succeed in stopping th job, but failed to upd load_code_failed=Fail to load code, please check if the right branch is selected. error.dataset_select = dataset select error:the count exceed the limit or has same name +error.partial_datasets_not_available = There are non-existent or deleted files in the selected dataset file, please select again new_train_gpu_tooltips = The code is storaged in %s, the dataset is storaged in %s, the pre-trained model is storaged in the run parameter %s, and please put your model into %s then you can download it online new_debug_gpu_tooltips = The code is storaged in %s, the dataset is storaged in %s, the pre-trained model is storaged in the %s, and please put your model into %s then you can download it online new_debug_gpu_tooltips1 = The code is storaged in %s, the dataset is storaged in %s, the pre-trained model is storaged in the %s. diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 3793c7382..4dc2e4c89 100755 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -73,7 +73,7 @@ your_starred=已点赞 your_settings=设置 invite_friends=邀请好友 your_friend=您的好友 -invite_you_to_join_the_OpenI_AI_Collaboration_Platform_and_enjoy_abundant_free_computing_resources=邀请您加入启智社区AI协作平台,畅享充沛的免费算力资源! +invite_you_to_join_the_OpenI_AI_Collaboration_Platform_and_enjoy_abundant_free_computing_resources=邀请您加入启智社区AI协作平台,畅享充沛的普惠算力资源! recommender=推荐人 all=所有 @@ -409,6 +409,8 @@ sspi_auth_failed=SSPI 认证失败 change_email=修改邮箱 change_email_address=修改邮箱地址 new_email_address=新邮箱地址 +openi_community_really_awesome=启智社区 确实给力 + [phone] format_err=手机号格式错误。 query_err=查询手机号失败,请稍后再试。 @@ -1060,6 +1062,8 @@ model_rename=模型名称重复,请修改模型名称 notebook_file_not_exist=Notebook文件不存在。 notebook_select_wrong=请先选择Notebook(.ipynb)文件。 +notebook_path_too_long=选择的一个或多个Notebook文件路径总长度超过255个字符,请选择路径较短的文件或调整文件路径。 +notebook_branch_name_too_long=选择的一个或多个Notebook文件分支名总长度超过255个字符,请选择其他分支的文件。 notebook_file_no_right=您没有这个Notebook文件的读权限。 notebook_repo_conflict=同一个仓库的不同分支文件不能同时运行。 debug_again_fail=再次调试失败,请稍后再试。 @@ -1081,7 +1085,7 @@ delete=删除 more=更多 gpu_type_all=全部 model_download=结果下载 -all_result_download=全部结果下载 +all_result_download=全部结果下载 submit_image=提交镜像 modify_image=修改镜像 image_exist=镜像Tag已被使用,请修改镜像Tag。 @@ -1273,6 +1277,13 @@ modelarts.fullscreen_log_file=全屏查看 modelarts.exit_full_screen=退出全屏 modelarts.no_node_right = 计算节点数的值配置错误,您没有权限使用当前配置的计算节点数。 +scrolled_logs_top = 您已翻阅至日志顶部 +scrolled_logs_top_pls_retry = 您已翻阅至日志顶部,请稍后再试! +scrolled_logs_bottom = 您已翻阅至日志底部 +scrolled_logs_bottom_pls_retry = 您已翻阅至日志底部,请稍后再试! + +canceled_operation = 您已取消操作 +successfully_deleted = 删除成功 debug_task_not_created = 未创建过调试任务 train_task_not_created = 未创建过训练任务 @@ -1363,6 +1374,7 @@ modelconvert.modelfileempty=请选择模型文件。 modelconvert.manage.create_error1=相同的名称模型转换任务已经存在。 modelconvert.manage.create_error2=只能创建一个正在运行的模型转换任务。 modelconvert.manage.model_not_exist=任务中选择的模型不存在或者已被删除。 +modelconvert.manage.model_file_not_exist=任务中选择的模型文件不存在或者已被删除。 modelconvert.manage.no_operate_right=您没有操作权限。 @@ -1492,7 +1504,7 @@ normal_view=普通视图 line=行 lines=行 -notebook_open = 在Notebook中打开 +notebook_open = 在线运行 editor.new_file=新建文件 editor.upload_file=上传文件 @@ -3154,6 +3166,7 @@ task_gpudebugjob=`创建了CPU/GPU类型调试任务 task_npudebugjob=`创建了NPU类型调试任务 %s` task_c2net_gpudebugjob=`创建了CPU/GPU类型调试任务 %s` task_c2net_npudebugjob=`创建了NPU类型调试任务 %s` +task_c2ent_gcudebugjob=`创建了GCU类型调试任务 %s` task_nputrainjob=`创建了NPU类型训练任务 %s` task_inferencejob=`创建了推理任务 %s` task_benchmark=`创建了评测任务 %s` @@ -3316,6 +3329,7 @@ point_hr = 积分/时 DEBUG = 调试任务 SNN4IMAGENET = 评测任务 BRAINSCORE = 评测任务 +SNN4ECOSET = 评测任务 MODELSAFETY = 评测任务 TRAIN = 训练任务 INFERENCE = 推理任务 @@ -3331,6 +3345,7 @@ load_code_failed=代码加载失败,请确认选择了正确的分支。 error.debug_datasetsize = 数据集大小超过限制('%d'GB) error.dataset_select = 数据集选择错误:数量超过限制或者有同名数据集 +error.partial_datasets_not_available = 选择的数据集文件中有不存在或已删除的文件,请重新选择 new_train_gpu_tooltips = 训练脚本存储在 %s 中,数据集存储在 %s 中,预训练模型存放在运行参数 %s 中,训练输出请存储在 %s 中以供后续下载。 new_debug_gpu_tooltips = 项目代码存储在 %s 中,数据集存储在 %s 中,选择的模型存储在 %s 中,调试输出请存储在 %s 中以供后续下载。 new_debug_gpu_tooltips1 = 项目代码存储在 %s 中,数据集存储在 %s 中,选择的模型存储在 %s 中。 diff --git a/public/home/home.js b/public/home/home.js index fe843161e..2c70ca8ee 100755 --- a/public/home/home.js +++ b/public/home/home.js @@ -243,11 +243,12 @@ document.onreadystatechange = function () { html += recordPrefix + actionName; html += " " + getRepotext(record) + "" } - else if(record.OpType == "24" || record.OpType == "26" || record.OpType == "27" || record.OpType == "28" || record.OpType == "30" || record.OpType == "31" || record.OpType == "32" || record.OpType == "33"){ + else if(record.OpType == "24" || record.OpType == "26" || record.OpType == "27" || record.OpType == "28" || record.OpType == "30" + || record.OpType == "31" || record.OpType == "32" || record.OpType == "33"){ html += recordPrefix + actionName; html += " " + record.RefName + "" } - else if(record.OpType == "25" || record.OpType == "29" || record.OpType == "39" || record.OpType == "40"){ + else if(record.OpType == "25" || record.OpType == "29" || record.OpType == "39" || record.OpType == "40" || record.OpType == "41"){ html += recordPrefix + actionName; html += " " + record.RefName + "" } @@ -294,7 +295,7 @@ function getTaskLink(record){ re = re + "/cloudbrain/train-job/" + record.Content; }else if(record.OpType == 32 || record.OpType == 33){ re = re + "/grampus/train-job/" + record.Content; - }else if(record.OpType == 39 || record.OpType == 40){ + }else if(record.OpType == 39 || record.OpType == 40 || record.OpType == 41){ re = re + "/grampus/notebook/" + record.Content; } @@ -453,9 +454,10 @@ var actionNameZH={ "33":"创建了CPU/GPU类型训练任务", "35":"创建的数据集 {dataset} 被设置为推荐数据集", "36":"提交了镜像 {image}", - "37": "提交的镜像 {image} 被设置为推荐镜像", + "37":"提交的镜像 {image} 被设置为推荐镜像", "39":"创建了CPU/GPU类型调试任务", "40":"创建了NPU类型调试任务", + "41":"创建了GCU类型训练任务", }; var actionNameEN={ @@ -486,9 +488,10 @@ var actionNameEN={ "33":" created CPU/GPU type training task", "35":" created dataset {dataset} was set as recommended dataset", "36":"committed image {image}", - "37": "committed image {image} was set as recommended image", + "37":"committed image {image} was set as recommended image", "39":" created CPU/GPU type debugging task ", "40":" created NPU type debugging task ", + "41":" created GCU type debugging task ", }; var repoAndOrgZH={ diff --git a/public/img/login_bg_default.png b/public/img/login_bg_default.png new file mode 100644 index 000000000..0c80142c9 Binary files /dev/null and b/public/img/login_bg_default.png differ diff --git a/routers/api/v1/repo/attachments.go b/routers/api/v1/repo/attachments.go index cb36ba2ee..7db8c9067 100644 --- a/routers/api/v1/repo/attachments.go +++ b/routers/api/v1/repo/attachments.go @@ -1,22 +1,67 @@ package repo import ( + "net/http" + + "code.gitea.io/gitea/modules/log" + + "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" routeRepo "code.gitea.io/gitea/routers/repo" ) func GetSuccessChunks(ctx *context.APIContext) { + if errStr := checkDatasetPermission(ctx); errStr != "" { + ctx.JSON(http.StatusForbidden, ctx.Tr(errStr)) + } + routeRepo.GetSuccessChunks(ctx.Context) } +func checkDatasetPermission(ctx *context.APIContext) string { + datasetId := ctx.QueryInt64("dataset_id") + + dataset, err := models.GetDatasetByID(datasetId) + if err != nil { + log.Warn("can not find dataset", err) + + return "dataset.query_dataset_fail" + } + repo, err := models.GetRepositoryByID(dataset.RepoID) + if err != nil { + log.Warn("can not find repo", err) + return "dataset.query_dataset_fail" + } + + permission, err := models.GetUserRepoPermission(repo, ctx.User) + if err != nil { + log.Warn("can not find repo permission for user", err) + return "dataset.query_dataset_fail" + } + if !permission.CanWrite(models.UnitTypeDatasets) { + + return "error.no_right" + } + return "" +} + func NewMultipart(ctx *context.APIContext) { + if errStr := checkDatasetPermission(ctx); errStr != "" { + ctx.JSON(http.StatusForbidden, ctx.Tr(errStr)) + } routeRepo.NewMultipart(ctx.Context) } func GetMultipartUploadUrl(ctx *context.APIContext) { + if errStr := checkDatasetPermission(ctx); errStr != "" { + ctx.JSON(http.StatusForbidden, ctx.Tr(errStr)) + } routeRepo.GetMultipartUploadUrl(ctx.Context) } func CompleteMultipart(ctx *context.APIContext) { + if errStr := checkDatasetPermission(ctx); errStr != "" { + ctx.JSON(http.StatusForbidden, ctx.Tr(errStr)) + } routeRepo.CompleteMultipart(ctx.Context) } diff --git a/routers/api/v1/repo/cloudbrain_dashboard.go b/routers/api/v1/repo/cloudbrain_dashboard.go index 1fbef897b..b980c70b3 100755 --- a/routers/api/v1/repo/cloudbrain_dashboard.go +++ b/routers/api/v1/repo/cloudbrain_dashboard.go @@ -1260,8 +1260,8 @@ func DownloadCloudBrainBoard(ctx *context.Context) { Type: models.TypeCloudBrainAll, BeginTimeUnix: int64(recordBeginTime), EndTimeUnix: endTime.Unix(), + AccCardsNum: models.AccCardsNumAll, }) - log.Info("totalcountisis:", total) if err != nil { log.Warn("Can not get cloud brain info", err) @@ -1290,6 +1290,7 @@ func DownloadCloudBrainBoard(ctx *context.Context) { BeginTimeUnix: int64(recordBeginTime), EndTimeUnix: endTime.Unix(), NeedRepoInfo: true, + AccCardsNum: models.AccCardsNumAll, }) if err != nil { log.Warn("Can not get cloud brain info", err) diff --git a/routers/home.go b/routers/home.go index 40a41bd68..21b1db946 100755 --- a/routers/home.go +++ b/routers/home.go @@ -42,6 +42,7 @@ const ( tplExploreImages base.TplName = "explore/images" tplExploreExploreDataAnalysis base.TplName = "explore/data_analysis" tplHomeTerm base.TplName = "terms" + tplHomeAnnual base.TplName = "annual_privacy" tplHomePrivacy base.TplName = "privacy" tplResoruceDesc base.TplName = "resource_desc" tplRepoSquare base.TplName = "explore/repos/square" @@ -966,6 +967,9 @@ func RecommendHomeInfo(ctx *context.Context) { func HomeTerm(ctx *context.Context) { ctx.HTML(200, tplHomeTerm) } +func HomeAnnual(ctx *context.Context) { + ctx.HTML(200, tplHomeAnnual) +} func HomePrivacy(ctx *context.Context) { ctx.HTML(200, tplHomePrivacy) diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index a074119fc..e67568394 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -76,7 +76,7 @@ func saveModelByParameters(jobId string, versionName string, name string, versio cloudType := aiTask.Type modelSelectedFile := ctx.Query("modelSelectedFile") //download model zip //train type - if aiTask.ComputeResource == models.NPUResource { + if aiTask.ComputeResource == models.NPUResource || aiTask.ComputeResource == models.GCUResource { cloudType = models.TypeCloudBrainTwo } else if aiTask.ComputeResource == models.GPUResource { cloudType = models.TypeCloudBrainOne diff --git a/routers/repo/grampus.go b/routers/repo/grampus.go index 9c204aff2..254cc6203 100755 --- a/routers/repo/grampus.go +++ b/routers/repo/grampus.go @@ -53,6 +53,8 @@ const ( //NPU tplGrampusNotebookNPUNew base.TplName = "repo/grampus/notebook/npu/new" tplGrampusTrainJobNPUNew base.TplName = "repo/grampus/trainjob/npu/new" + //GCU + tplGrampusNotebookGCUNew base.TplName = "repo/grampus/notebook/gcu/new" ) func GrampusNotebookNew(ctx *context.Context) { @@ -61,6 +63,8 @@ func GrampusNotebookNew(ctx *context.Context) { processType := grampus.ProcessorTypeGPU if notebookType == 1 { processType = grampus.ProcessorTypeNPU + } else if notebookType == 2 { + processType = grampus.ProcessorTypeGCU } err := grampusNotebookNewDataPrepare(ctx, processType) if err != nil { @@ -69,8 +73,10 @@ func GrampusNotebookNew(ctx *context.Context) { } if processType == grampus.ProcessorTypeGPU { ctx.HTML(http.StatusOK, tplGrampusNotebookGPUNew) - } else { + } else if processType == grampus.ProcessorTypeNPU { ctx.HTML(http.StatusOK, tplGrampusNotebookNPUNew) + } else if processType == grampus.ProcessorTypeGCU { + ctx.HTML(http.StatusOK, tplGrampusNotebookGCUNew) } } @@ -117,6 +123,12 @@ func GrampusNotebookCreate(ctx *context.Context, form auth.CreateGrampusNotebook computeSource = models.NPUResource computeSourceSimple = models.NPU codeStoragePath = grampus.JobPath + jobName + modelarts.CodePath + } else if form.Type == 2 { + tpl = tplGrampusNotebookGCUNew + processType = grampus.ProcessorTypeGCU + computeSource = models.GCUResource + computeSourceSimple = models.GCU + codeStoragePath = setting.CBCodePathPrefix + jobName + cloudbrain.CodeMountPath + "/" } lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeDebug), displayJobName)) @@ -199,6 +211,12 @@ func GrampusNotebookCreate(ctx *context.Context, form auth.CreateGrampusNotebook ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tpl, &form) return } + uuidArray := strings.Split(uuid, ";") + if datasetInfos == nil || len(datasetInfos) < len(uuidArray) { + grampusNotebookNewDataPrepare(ctx, processType) + ctx.RenderWithErr(ctx.Tr("cloudbrain.error.partial_datasets_not_available"), tpl, &form) + return + } } //prepare code and out path @@ -215,7 +233,7 @@ func GrampusNotebookCreate(ctx *context.Context, form auth.CreateGrampusNotebook return } - if processType == grampus.ProcessorTypeGPU { + if processType == grampus.ProcessorTypeGPU || processType == grampus.ProcessorTypeGCU { if err := uploadCodeToMinio(codeLocalPath+"/", jobName, cloudbrain.CodeMountPath+"/"); err != nil { log.Error("Failed to uploadCodeToMinio: %s (%v)", repo.FullName(), err, ctx.Data["MsgID"]) grampusNotebookNewDataPrepare(ctx, processType) @@ -255,20 +273,26 @@ func GrampusNotebookCreate(ctx *context.Context, form auth.CreateGrampusNotebook if form.ModelName != "" { //使用预训练模型训练 - _, err := models.QueryModelByPath(form.PreTrainModelUrl) + m, err := models.QueryModelByPath(form.PreTrainModelUrl) if err != nil { log.Error("Can not find model", err) grampusNotebookNewDataPrepare(ctx, processType) ctx.RenderWithErr(ctx.Tr("repo.modelconvert.manage.model_not_exist"), tpl, &form) return } + if !cloudbrainTask.IsModelFileExists(m, form.CkptName) { + log.Error("model file not exist.name = %s", form.CkptName) + grampusNotebookNewDataPrepare(ctx, processType) + ctx.RenderWithErr(ctx.Tr("repo.modelconvert.manage.model_file_not_exist"), tpl, &form) + return + } req.ModelName = form.ModelName req.LabelName = form.LabelName req.CkptName = form.CkptName req.ModelVersion = form.ModelVersion req.PreTrainModelUrl = form.PreTrainModelUrl req.PreTrainModelPath = getPreTrainModelPath(form.PreTrainModelUrl, form.CkptName) - + req.ModelStorageType = m.Type } _, err = grampus.GenerateNotebookJob(ctx, req) @@ -287,7 +311,7 @@ func grampusNotebookNewDataPrepare(ctx *context.Context, processType string) err ctx.Data["display_job_name"] = displayJobName //get valid images - if processType == grampus.ProcessorTypeNPU { + if processType == grampus.ProcessorTypeNPU || processType == grampus.ProcessorTypeGCU { images, err := grampus.GetImages(processType, string(models.JobTypeDebug)) if err != nil { log.Error("GetImages failed:", err.Error()) @@ -303,6 +327,10 @@ func grampusNotebookNewDataPrepare(ctx *context.Context, processType string) err computeResourceSimple = models.NPU datasetType = models.TypeCloudBrainTwo computeResource = models.NPUResource + } else if processType == grampus.ProcessorTypeGCU { + computeResourceSimple = models.GCU + datasetType = models.TypeCloudBrainAll + computeResource = models.GCUResource } prepareGrampusSpecs(ctx, computeResourceSimple, models.JobTypeDebug) @@ -1660,7 +1688,11 @@ func GrampusNotebookRestart(ctx *context.Context) { if task.ComputeResource == models.NPUResource { computeSourceSimple = models.NPU action = models.ActionCreateGrampusNPUDebugTask + } else if task.ComputeResource == models.GCUResource { + computeSourceSimple = models.GCU + action = models.ActionCreateGrampusGCUDebugTask } + spec, err = resource.GetAndCheckSpec(ctx.User.ID, oldSpec.ID, models.FindSpecsOptions{ JobType: models.JobType(task.JobType), ComputeResource: computeSourceSimple, @@ -1676,7 +1708,7 @@ func GrampusNotebookRestart(ctx *context.Context) { errorMsg = ctx.Tr("points.insufficient_points_balance") break } - if task.IsGPUTask() { + if task.IsGPUTask() || task.IsGCUTask() { if _, err := os.Stat(getOldJobPath(task)); err != nil { log.Error("Can not find job minio path", err) resultCode = "-1" diff --git a/routers/repo/modelarts.go b/routers/repo/modelarts.go index e0b9cd1b6..fe109422e 100755 --- a/routers/repo/modelarts.go +++ b/routers/repo/modelarts.go @@ -483,7 +483,7 @@ func getFileUrl(url string, filename string) string { } } - return url + middle + filename + return url + middle + filename + "?reset" } func NotebookRestart(ctx *context.Context) { @@ -2893,15 +2893,19 @@ func TrainJobDownloadLogFile(ctx *context.Context) { ctx.ServerError("GetObsLogFileName", err) return } - - url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, key) - if err != nil { - log.Error("GetObsCreateSignedUrlByBucketAndKey failed: %v", err.Error(), ctx.Data["msgID"]) - ctx.ServerError("GetObsCreateSignedUrlByBucketAndKey", err) - return + if len(key) > 1 { + ObsDownloadManyFile(prefix[0:len(prefix)-3], ctx, task.DisplayJobName+".zip", key) + } else { + url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, key[0].ParenDir+key[0].FileName) + if err != nil { + log.Error("GetObsCreateSignedUrlByBucketAndKey failed: %v", err.Error(), ctx.Data["msgID"]) + ctx.ServerError("GetObsCreateSignedUrlByBucketAndKey", err) + return + } + ctx.Resp.Header().Set("Cache-Control", "max-age=0") + http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusTemporaryRedirect) } - ctx.Resp.Header().Set("Cache-Control", "max-age=0") - http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusTemporaryRedirect) + } func getDatasUrlListByUUIDS(uuidStr string) ([]models.Datasurl, string, string, bool, error) { var isMultiDataset bool diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 85e1b8a25..2def76ff4 100755 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -359,6 +359,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/all/dosearch/", routers.SearchApi) m.Post("/user/login/kanban", user.SignInPostAPI) m.Get("/home/term", routers.HomeTerm) + m.Get("/home/annual_privacy", routers.HomeAnnual) m.Get("/home/notice", routers.HomeNoticeTmpl) m.Get("/home/privacy", routers.HomePrivacy) m.Get("/extension/tuomin/upload", modelapp.ProcessImageUI) diff --git a/routers/user/auth.go b/routers/user/auth.go index 5314571d2..61f53e200 100755 --- a/routers/user/auth.go +++ b/routers/user/auth.go @@ -36,6 +36,7 @@ import ( "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/externalaccount" "code.gitea.io/gitea/services/mailer" + "code.gitea.io/gitea/services/repository" "gitea.com/macaron/captcha" "github.com/markbates/goth" @@ -120,7 +121,6 @@ func checkAutoLogin(ctx *context.Context) bool { ctx.ServerError("AutoSignIn", err) return true } - redirectTo := ctx.Query("redirect_to") if len(redirectTo) > 0 { ctx.SetCookie("redirect_to", redirectTo, 0, setting.AppSubURL, "", setting.SessionConfig.Secure, true) @@ -129,7 +129,6 @@ func checkAutoLogin(ctx *context.Context) bool { } if isSucceed { - isCourse := ctx.QueryBool("course") ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL, "", setting.SessionConfig.Secure, true) if redirectTo == "" && isCourse { @@ -137,7 +136,6 @@ func checkAutoLogin(ctx *context.Context) bool { ctx.RedirectToFirst(redirectToCourse) } else { ctx.RedirectToFirst(redirectTo, setting.AppSubURL+string(setting.LandingPageURL)) - } return true } @@ -145,10 +143,14 @@ func checkAutoLogin(ctx *context.Context) bool { return false } +func getActivityTpl() string { + result, _ := repository.RecommendContentFromPromote(setting.RecommentRepoAddr + "/signin/activity_tpl") + return result +} + // SignIn render sign in page func SignIn(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("sign_in") - // Check auto-login. if checkAutoLogin(ctx) { return @@ -168,6 +170,7 @@ func SignIn(ctx *context.Context) { ctx.Data["PageIsLogin"] = true ctx.Data["EnableSSPI"] = models.IsSSPIEnabled() ctx.Data["EnableCloudBrain"] = true + ctx.Data["ActivityTpl"] = getActivityTpl() ctx.HTML(200, tplSignIn) } @@ -185,6 +188,7 @@ func SignInCloudBrain(ctx *context.Context) { ctx.Data["PageIsSignIn"] = true ctx.Data["PageIsCloudBrainLogin"] = true ctx.Data["EnableCloudBrain"] = true + ctx.Data["ActivityTpl"] = getActivityTpl() ctx.HTML(200, tplSignInCloudBrain) } @@ -197,6 +201,7 @@ func SignInPhone(ctx *context.Context) { } ctx.Data["PageIsPhoneLogin"] = true + ctx.Data["ActivityTpl"] = getActivityTpl() ctx.HTML(200, tplSignInPhone) } @@ -206,6 +211,7 @@ func SignInPhonePost(ctx *context.Context, form auth.PhoneNumberCodeForm) { ctx.Data["PageIsPhoneLogin"] = true ctx.Data["IsCourse"] = ctx.QueryBool("course") ctx.Data["EnableCloudBrain"] = true + ctx.Data["ActivityTpl"] = getActivityTpl() if ctx.HasError() { ctx.HTML(200, tplSignInPhone) @@ -270,7 +276,6 @@ func SignInPostAPI(ctx *context.Context) { func SignInPostCommon(ctx *context.Context, form auth.SignInForm) { ctx.Data["Title"] = ctx.Tr("sign_in") - orderedOAuth2Names, oauth2Providers, err := models.GetActiveOAuth2Providers() if err != nil { ctx.ServerError("UserSignIn", err) @@ -285,7 +290,6 @@ func SignInPostCommon(ctx *context.Context, form auth.SignInForm) { ctx.Data["IsCourse"] = ctx.QueryBool("course") ctx.Data["EnableSSPI"] = models.IsSSPIEnabled() ctx.Data["EnableCloudBrain"] = true - if ctx.HasError() { ctx.HTML(200, tplSignIn) return @@ -356,6 +360,7 @@ func SignInPostCommon(ctx *context.Context, form auth.SignInForm) { func SignInCloudBrainPost(ctx *context.Context, form auth.SignInForm) { ctx.Data["PageIsCloudBrainLogin"] = true ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login/cloud_brain" + ctx.Data["ActivityTpl"] = getActivityTpl() SignInPostCommon(ctx, form) } @@ -363,6 +368,7 @@ func SignInCloudBrainPost(ctx *context.Context, form auth.SignInForm) { func SignInPost(ctx *context.Context, form auth.SignInForm) { ctx.Data["PageIsLogin"] = true ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login" + ctx.Data["ActivityTpl"] = getActivityTpl() SignInPostCommon(ctx, form) } @@ -757,7 +763,6 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR } return redirectTo } - if obeyRedirect { ctx.Redirect(setting.AppSubURL + "/dashboard") } @@ -1257,6 +1262,7 @@ func SignUp(ctx *context.Context) { //Show Disabled Registration message if DisableRegistration or AllowOnlyExternalRegistration options are true ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration || setting.Service.AllowOnlyExternalRegistration + ctx.Data["ActivityTpl"] = getActivityTpl() ctx.HTML(200, tplSignUp) } @@ -1272,6 +1278,7 @@ func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterFo ctx.Data["CaptchaType"] = setting.Service.CaptchaType ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey ctx.Data["PageIsSignUp"] = true + ctx.Data["ActivityTpl"] = getActivityTpl() //Permission denied if DisableRegistration or AllowOnlyExternalRegistration options are true if setting.Service.DisableRegistration || setting.Service.AllowOnlyExternalRegistration { diff --git a/services/cloudbrain/cloudbrainTask/ai_model.go b/services/cloudbrain/cloudbrainTask/ai_model.go new file mode 100644 index 000000000..02cc392be --- /dev/null +++ b/services/cloudbrain/cloudbrainTask/ai_model.go @@ -0,0 +1,30 @@ +package cloudbrainTask + +import ( + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/storage" +) + +func IsModelFileExists(model *models.AiModelManage, fileName string) bool { + if model.Type == models.TypeCloudBrainTwo { + key := models.AIModelPath + models.AttachmentRelativePath(model.ID) + "/" + fileName + log.Info("IsModelFileExists TypeCloudBrainTwo key=%s", key) + isExist, err := storage.IsObjectExist4Obs(setting.Bucket, key) + if err != nil { + return false + } + return isExist + } else if model.Type == models.TypeCloudBrainOne { + prefix := models.AIModelPath + models.AttachmentRelativePath(model.ID) + "/" + objectName := prefix + fileName + log.Info("IsModelFileExists TypeCloudBrainOne objectName=%s", objectName) + isExist, err := storage.IsObjectExist4Minio(setting.Attachment.Minio.Bucket, objectName) + if err != nil { + return false + } + return isExist + } + return false +} diff --git a/services/cloudbrain/cloudbrainTask/count.go b/services/cloudbrain/cloudbrainTask/count.go index 172fa1502..0010164ae 100644 --- a/services/cloudbrain/cloudbrainTask/count.go +++ b/services/cloudbrain/cloudbrainTask/count.go @@ -72,6 +72,11 @@ var StatusInfoDict = map[string]StatusInfo{string(models.JobTypeDebug) + "-" + s JobType: []models.JobType{models.JobTypeDebug}, NotFinalStatuses: GrampusNotFinalStatuses, ComputeResource: models.NPUResource, +}, string(models.JobTypeDebug) + "-" + strconv.Itoa(models.TypeC2Net) + "-" + models.GCUResource: { + CloudBrainTypes: []int{models.TypeC2Net}, + JobType: []models.JobType{models.JobTypeDebug}, + NotFinalStatuses: GrampusNotFinalStatuses, + ComputeResource: models.GCUResource, }} func GetNotFinalStatusTaskCount(uid int64, cloudbrainType int, jobType string, computeResource ...string) (int, error) { diff --git a/services/cloudbrain/cloudbrainTask/notebook.go b/services/cloudbrain/cloudbrainTask/notebook.go index 3526f6549..ff1a2100a 100644 --- a/services/cloudbrain/cloudbrainTask/notebook.go +++ b/services/cloudbrain/cloudbrainTask/notebook.go @@ -35,6 +35,7 @@ const NoteBookExtension = ".ipynb" const CPUType = 0 const GPUType = 1 const NPUType = 2 +const CharacterLength = 2550 func FileNotebookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption) { @@ -46,6 +47,14 @@ func FileNotebookCreate(ctx *context.Context, option api.CreateFileNotebookJobOp ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_select_wrong"))) return } + if len(getBootFile(option.File, option.OwnerName, option.ProjectName)) > CharacterLength { + ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_path_too_long"))) + return + } + if len(option.BranchName) > CharacterLength { + ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_branch_name_too_long"))) + return + } isNotebookFileExist, _ := isNoteBookFileExist(ctx, option) if !isNotebookFileExist { @@ -105,14 +114,29 @@ func FileNotebookCreate(ctx *context.Context, option api.CreateFileNotebookJobOp err = downloadCode(sourceRepo, getCodePath(noteBook.JobName, sourceRepo), option.BranchName) if err != nil { log.Error("download code failed", err) - ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.load_code_failed"))) - return + if !strings.Contains(err.Error(), "already exists and is not an empty directory") { + ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.load_code_failed"))) + return + } } } if !isRepoFileMatch(option, noteBook) { - noteBook.BootFile += ";" + getBootFile(option.File, option.OwnerName, option.ProjectName) - noteBook.BranchName += ";" + option.BranchName - noteBook.Description += ";" + getDescription(option) + if len(noteBook.BootFile)+len(getBootFile(option.File, option.OwnerName, option.ProjectName))+1 <= CharacterLength { + noteBook.BootFile += ";" + getBootFile(option.File, option.OwnerName, option.ProjectName) + } else { + ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_path_too_long"))) + return + } + if len(noteBook.BranchName)+len(option.BranchName)+1 <= CharacterLength { + noteBook.BranchName += ";" + option.BranchName + } else { + ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_branch_name_too_long"))) + return + } + + if len(noteBook.Description)+len(getDescription(option))+1 <= CharacterLength { + noteBook.Description += ";" + getDescription(option) + } err := models.UpdateJob(noteBook) if err != nil { @@ -417,7 +441,7 @@ func cloudBrainFileNoteBookCreate(ctx *context.Context, option api.CreateFileNot } func getCloudbrainType(optionType int) int { - if optionType < 1 { + if optionType <= GPUType { return models.TypeCloudBrainOne } if setting.ModelartsCD.Enabled { @@ -431,7 +455,11 @@ func getCodePath(jobName string, repo *models.Repository) string { } func getDescription(option api.CreateFileNotebookJobOption) string { - return option.OwnerName + "/" + option.ProjectName + "/" + option.File + des := option.OwnerName + "/" + option.ProjectName + "/" + option.File + if len(des) <= CharacterLength { + return des + } + return "" } func modelartsFileNoteBookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption, repo *models.Repository, sourceRepo *models.Repository) { diff --git a/services/socketwrap/clientManager.go b/services/socketwrap/clientManager.go index 7bac92ab8..2a752acf5 100755 --- a/services/socketwrap/clientManager.go +++ b/services/socketwrap/clientManager.go @@ -10,7 +10,7 @@ import ( "github.com/elliotchance/orderedmap" ) -var opTypes = []int{1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 39, 40} +var opTypes = []int{1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 39, 40, 41} type ClientsManager struct { Clients *orderedmap.OrderedMap diff --git a/templates/admin/cloudbrain/list.tmpl b/templates/admin/cloudbrain/list.tmpl index f6d20216a..91b0e913a 100755 --- a/templates/admin/cloudbrain/list.tmpl +++ b/templates/admin/cloudbrain/list.tmpl @@ -89,21 +89,21 @@
{{$JobID := '0'}} - {{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK" "MODELSAFETY"}} + {{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK" "MODELSAFETY" "SNN4ECOSET"}} {{$JobID = .Cloudbrain.ID}} {{else}} {{$JobID = .JobID}} {{end}}
- {{if eq .JobType "DEBUG"}} + {{if eq .JobType "DEBUG"}} {{.DisplayJobName}} - {{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE")}} + {{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE") (eq .JobType "SNN4ECOSET")}} @@ -233,7 +233,7 @@ {{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}} {{$.i18n.Tr "repo.debug"}} @@ -263,7 +263,7 @@ {{else}} - {{if eq .JobType "DEBUG" "BENCHMARK" "SNN4IMAGENET" "BRAINSCORE"}} + {{if eq .JobType "DEBUG" "BENCHMARK" "SNN4IMAGENET" "BRAINSCORE" "SNN4ECOSET"}}
{{$.CsrfTokenHtml}} {{else}} {{$.CsrfTokenHtml}} {{$.i18n.Tr "repo.delete"}} @@ -321,7 +321,7 @@
{{else}} {{$JobID := '0'}} - {{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK"}} + {{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK" "SNN4ECOSET"}} {{$JobID = .Cloudbrain.ID}} {{else}} {{$JobID = .JobID}} diff --git a/templates/admin/cloudbrain/search.tmpl b/templates/admin/cloudbrain/search.tmpl index 09e5f865e..95332ad0f 100644 --- a/templates/admin/cloudbrain/search.tmpl +++ b/templates/admin/cloudbrain/search.tmpl @@ -35,6 +35,7 @@ SNN4IMAGENET BRAINSCORE MODELSAFETY + SNN4ECOSET
+
diff --git a/templates/explore/images.tmpl b/templates/explore/images.tmpl index 90913d89c..52d901424 100644 --- a/templates/explore/images.tmpl +++ b/templates/explore/images.tmpl @@ -1,4 +1,5 @@ {{template "base/head" .}} +
diff --git a/templates/explore/organizations.tmpl b/templates/explore/organizations.tmpl index 5faf039af..dad7dfc93 100644 --- a/templates/explore/organizations.tmpl +++ b/templates/explore/organizations.tmpl @@ -1,8 +1,8 @@ - - - - + + + + {{template "base/head" .}}
diff --git a/templates/explore/repo_orgtop.tmpl b/templates/explore/repo_orgtop.tmpl index bba16dd47..17d02189f 100755 --- a/templates/explore/repo_orgtop.tmpl +++ b/templates/explore/repo_orgtop.tmpl @@ -1,5 +1,5 @@ - - + + - + @@ -266,8 +266,8 @@ {{template "base/footer" .}} - - + +
- {{template "user/auth/signin_navbar" .}} -
-
- {{template "user/auth/signin_inner" .}} +
+
+
+
+ {{ if .ActivityTpl }} + {{ .ActivityTpl | Safe}} + {{ else }} + {{ template "user/auth/signin_up_img_default" .}} + {{ end }} +
+
+
+
+ {{template "user/auth/signin_navbar" .}} + {{template "user/auth/signin_inner" .}} +
+
diff --git a/templates/user/auth/signin_cloud_brain.tmpl b/templates/user/auth/signin_cloud_brain.tmpl index 6b0b9c38f..9412d83e6 100755 --- a/templates/user/auth/signin_cloud_brain.tmpl +++ b/templates/user/auth/signin_cloud_brain.tmpl @@ -1,9 +1,48 @@ {{template "base/head" .}} +