Browse Source

Merge branch 'V20220630' into web-0630

tags/v1.22.6.2^2
zhoupzh 3 years ago
parent
commit
ad856eef8f
41 changed files with 6198 additions and 4030 deletions
  1. +37
    -1
      models/attachment.go
  2. +70
    -0
      models/cloudbrain.go
  3. +112
    -14
      models/dataset.go
  4. +7
    -0
      models/dataset_star.go
  5. +50
    -21
      models/user_business_analysis.go
  6. +8
    -6
      models/user_business_struct.go
  7. +184
    -141
      modules/cloudbrain/cloudbrain.go
  8. +41
    -5
      modules/grampus/grampus.go
  9. +6
    -14
      modules/modelarts/modelarts.go
  10. +9
    -4
      modules/setting/setting.go
  11. +5
    -0
      options/locale/locale_en-US.ini
  12. +6
    -2
      options/locale/locale_zh-CN.ini
  13. +8
    -2
      public/home/home.js
  14. +2
    -7
      routers/admin/cloudbrains.go
  15. +4
    -3
      routers/admin/dataset.go
  16. +3
    -10
      routers/api/v1/repo/repo_dashbord.go
  17. +10
    -9
      routers/home.go
  18. +120
    -35
      routers/repo/cloudbrain.go
  19. +78
    -0
      routers/repo/dataset.go
  20. +67
    -5
      routers/repo/grampus.go
  21. +123
    -8
      routers/repo/modelarts.go
  22. +5
    -0
      routers/routes/routes.go
  23. +1
    -0
      routers/user/profile.go
  24. +1
    -1
      services/socketwrap/clientManager.go
  25. +3
    -3
      templates/admin/cloudbrain/list.tmpl
  26. +2
    -2
      templates/custom/select_dataset_train.tmpl
  27. +1
    -1
      templates/explore/datasets.tmpl
  28. +1
    -1
      templates/repo/cloudbrain/benchmark/show.tmpl
  29. +5
    -5
      templates/repo/cloudbrain/new.tmpl
  30. +1
    -1
      templates/repo/cloudbrain/show.tmpl
  31. +50
    -52
      templates/repo/cloudbrain/trainjob/new.tmpl
  32. +38
    -36
      templates/repo/grampus/trainjob/gpu/new.tmpl
  33. +39
    -38
      templates/repo/grampus/trainjob/npu/new.tmpl
  34. +4
    -1
      templates/repo/modelarts/notebook/new.tmpl
  35. +32
    -44
      templates/repo/modelarts/notebook/show.tmpl
  36. +123
    -135
      templates/repo/modelarts/trainjob/new.tmpl
  37. +1155
    -0
      web_src/js/components/dataset/selectDataset.vue
  38. +283
    -207
      web_src/js/components/images/selectGrampusImages.vue
  39. +560
    -367
      web_src/js/components/images/selectImages.vue
  40. +2095
    -2121
      web_src/js/index.js
  41. +849
    -728
      web_src/less/openi.less

+ 37
- 1
models/attachment.go View File

@@ -110,8 +110,15 @@ func (a *Attachment) IncreaseDownloadCount() error {
}

func IncreaseAttachmentUseNumber(uuid string) error {

uuidArray := strings.Split(uuid, ";")
for i := range uuidArray {
uuidArray[i] = "'" + uuidArray[i] + "'"
}

uuidInCondition := "(" + strings.Join(uuidArray, ",") + ")"
// Update use number.
if _, err := x.Exec("UPDATE `attachment` SET use_number=use_number+1 WHERE uuid=?", uuid); err != nil {
if _, err := x.Exec("UPDATE `attachment` SET use_number=use_number+1 WHERE uuid in " + uuidInCondition); err != nil {
return fmt.Errorf("increase attachment use count: %v", err)
}

@@ -560,6 +567,35 @@ func GetAttachmentSizeByDatasetID(datasetID int64) (int64, error) {
return total, nil
}

func AttachmentsByDatasetOption(datasets []int64, opts *SearchDatasetOptions) ([]*Attachment, error) {
sess := x.NewSession()
defer sess.Close()
var cond = builder.NewCond()
cond = cond.And(builder.In("attachment.dataset_id", datasets))
if opts.JustNeedZipFile {
cond = cond.And(builder.Gt{"attachment.decompress_state": 0})
}
if opts.PublicOnly {
cond = cond.And(builder.Eq{"attachment.is_private": false})
}
if opts.CloudBrainType >= 0 {
cond = cond.And(builder.Eq{"attachment.type": opts.CloudBrainType})
}
if opts.UploadAttachmentByMe {
cond = cond.And(
builder.Eq{"attachment.uploader_id": opts.User.ID},
)
}

attachments := make([]*Attachment, 0)
if err := sess.Table(&Attachment{}).Where(cond).
Find(&attachments); err != nil {
return nil, fmt.Errorf("Find: %v", err)
}
return attachments, nil

}

func GetAllAttachmentSize() (int64, error) {
return x.SumInt(&Attachment{}, "size")
}


+ 70
- 0
models/cloudbrain.go View File

@@ -2,6 +2,7 @@ package models

import (
"encoding/json"
"errors"
"fmt"
"strconv"
"strings"
@@ -565,6 +566,17 @@ type FlavorInfo struct {
Desc string `json:"desc"`
}

type SpecialPools struct {
Pools []*SpecialPool `json:"pools"`
}
type SpecialPool struct {
Org string `json:"org"`
Type string `json:"type"`
IsExclusive bool `json:"isExclusive"`
Pool []*GpuInfo `json:"pool"`
JobType []string `json:"jobType"`
}

type ImageInfosModelArts struct {
ImageInfo []*ImageInfoModelArts `json:"image_info"`
}
@@ -988,6 +1000,16 @@ type Parameter struct {
type Parameters struct {
Parameter []Parameter `json:"parameter"`
}
type Datasurl struct {
DatasetUrl string `json:"dataset_url"`
DatasetName string `json:"dataset_name"`
}

type DatasetDownload struct {
DatasetName string `json:"dataset_name"`
DatasetDownloadLink string `json:"dataset_download_link"`
RepositoryLink string `json:"repository_link"`
}

type DataSource struct {
DatasetID string `json:"dataset_id"`
@@ -1944,3 +1966,51 @@ func CloudbrainAllStatic(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, er
}
return cloudbrains, count, nil
}

type DatasetInfo struct {
DataLocalPath string
Name string
}

func GetDatasetInfo(uuidStr string) (map[string]DatasetInfo, string, error) {
var datasetNames string
uuids := strings.Split(uuidStr, ";")
if len(uuids) > setting.MaxDatasetNum {
log.Error("the dataset count(%d) exceed the limit", len(uuids))
return nil, datasetNames, errors.New("the dataset count exceed the limit")
}

datasetInfos := make(map[string]DatasetInfo)
attachs, err := GetAttachmentsByUUIDs(uuids)
if err != nil {
log.Error("GetAttachmentsByUUIDs failed: %v", err)
return nil, datasetNames, err
}
for i, attach := range attachs {
fileName := strings.TrimSuffix(strings.TrimSuffix(strings.TrimSuffix(attach.Name, ".zip"), ".tar.gz"), ".tgz")
for _, datasetInfo := range datasetInfos {
if fileName == datasetInfo.Name {
log.Error("the dataset name is same: %v", attach.Name)
return nil, datasetNames, errors.New("the dataset name is same")
}
}

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,
}
if i == 0 {
datasetNames = attach.Name
} else {
datasetNames += ";" + attach.Name
}
}

return datasetInfos, datasetNames, nil
}

+ 112
- 14
models/dataset.go View File

@@ -81,12 +81,14 @@ func (datasets DatasetList) loadAttributes(e Engine) error {
if err := e.
Where("id > 0").
In("id", keysInt64(userIdSet)).
Cols("id", "lower_name", "name", "full_name", "email").
Find(&users); err != nil {
return fmt.Errorf("find users: %v", err)
}
if err := e.
Where("id > 0").
In("id", keysInt64(set)).
Cols("id", "owner_id", "owner_name", "lower_name", "name", "description", "alias", "lower_alias").
Find(&repos); err != nil {
return fmt.Errorf("find repos: %v", err)
}
@@ -98,19 +100,77 @@ func (datasets DatasetList) loadAttributes(e Engine) error {
return nil
}

func (datasets DatasetList) loadAttachmentAttributes(opts *SearchDatasetOptions) error {
if len(datasets) == 0 {
return nil
}
datasetIDs := make([]int64, len(datasets))
for i := range datasets {
datasetIDs[i] = datasets[i].ID
}
attachments, err := AttachmentsByDatasetOption(datasetIDs, opts)
if err != nil {
return fmt.Errorf("GetAttachmentsByDatasetIds failed error: %v", err)
}

permissionMap := make(map[int64]*Permission, len(datasets))

for _, attachment := range attachments {

for i := range datasets {
if attachment.DatasetID == datasets[i].ID {
if opts.StarByMe {
var permission *Permission
if permission = permissionMap[datasets[i].ID]; permission == nil {
permissionInstance, err := GetUserRepoPermission(datasets[i].Repo, opts.User)
if err != nil {
return fmt.Errorf("GetPermission failed error: %v", err)
}
permission = &permissionInstance
}

if permission.HasAccess() {
datasets[i].Attachments = append(datasets[i].Attachments, attachment)
} else if !attachment.IsPrivate {
datasets[i].Attachments = append(datasets[i].Attachments, attachment)
}
} else {
datasets[i].Attachments = append(datasets[i].Attachments, attachment)
}

}

}

}

for i := range datasets {
datasets[i].Repo.Owner = nil
}
return nil

}

type SearchDatasetOptions struct {
Keyword string
OwnerID int64
User *User
RepoID int64
IncludePublic bool
RecommendOnly bool
Category string
Task string
License string
DatasetIDs []int64
DatasetIDs []int64 // 目前只在StarByMe为true时起作用
ListOptions
SearchOrderBy
IsOwner bool
IsOwner bool
StarByMe bool
CloudBrainType int //0 cloudbrain 1 modelarts -1 all
PublicOnly bool
JustNeedZipFile bool
NeedAttachment bool
UploadAttachmentByMe bool
}

func CreateDataset(dataset *Dataset) (err error) {
@@ -159,30 +219,40 @@ func SearchDatasetCondition(opts *SearchDatasetOptions) builder.Cond {
if opts.RepoID > 0 {
cond = cond.And(builder.Eq{"dataset.repo_id": opts.RepoID})
}
if opts.IncludePublic {

if opts.PublicOnly {
cond = cond.And(builder.Eq{"dataset.status": DatasetStatusPublic})
cond = cond.And(builder.Eq{"attachment.is_private": false})
} else if opts.IncludePublic {
cond = cond.And(builder.Eq{"dataset.status": DatasetStatusPublic})
cond = cond.And(builder.Eq{"attachment.is_private": false})
if opts.OwnerID > 0 {

subCon := builder.NewCond()
subCon = subCon.And(builder.Eq{"repository.owner_id": opts.OwnerID})
subCon = generateFilterCond(opts, subCon)
cond = cond.Or(subCon)

}
} else if opts.OwnerID > 0 {
} else if opts.OwnerID > 0 && !opts.StarByMe && !opts.UploadAttachmentByMe {
cond = cond.And(builder.Eq{"repository.owner_id": opts.OwnerID})
if !opts.IsOwner {
cond = cond.And(builder.Eq{"dataset.status": DatasetStatusPublic})
cond = cond.And(builder.Eq{"attachment.is_private": false})
}
}

if len(opts.DatasetIDs) > 0 {
subCon := builder.NewCond()
subCon = subCon.And(builder.In("dataset.id", opts.DatasetIDs))
subCon = generateFilterCond(opts, subCon)
cond = cond.Or(subCon)
if opts.StarByMe {
cond = cond.And(builder.In("dataset.id", opts.DatasetIDs))
} else {
subCon := builder.NewCond()
subCon = subCon.And(builder.In("dataset.id", opts.DatasetIDs))
subCon = generateFilterCond(opts, subCon)
cond = cond.Or(subCon)
}
} else {
if opts.StarByMe {
cond = cond.And(builder.Eq{"dataset.id": -1})
}
}

return cond
@@ -208,6 +278,17 @@ func generateFilterCond(opts *SearchDatasetOptions, cond builder.Cond) builder.C
cond = cond.And(builder.Eq{"dataset.recommend": opts.RecommendOnly})
}

if opts.JustNeedZipFile {
cond = cond.And(builder.Gt{"attachment.decompress_state": 0})
}

if opts.CloudBrainType >= 0 {
cond = cond.And(builder.Eq{"attachment.type": opts.CloudBrainType})
}
if opts.UploadAttachmentByMe {
cond = cond.And(builder.Eq{"attachment.uploader_id": opts.User.ID})
}

return cond
}

@@ -234,7 +315,6 @@ func SearchDatasetByCondition(opts *SearchDatasetOptions, cond builder.Cond) (Da
sess.Select(selectColumnsSql).Join("INNER", "repository", "repository.id = dataset.repo_id").
Join("INNER", "attachment", "attachment.dataset_id=dataset.id").
Where(cond).OrderBy(opts.SearchOrderBy.String())

if opts.PageSize > 0 {
sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
}
@@ -246,6 +326,12 @@ func SearchDatasetByCondition(opts *SearchDatasetOptions, cond builder.Cond) (Da
return nil, 0, fmt.Errorf("LoadAttributes: %v", err)
}

if opts.NeedAttachment {
if err = datasets.loadAttachmentAttributes(opts); err != nil {
return nil, 0, fmt.Errorf("LoadAttributes: %v", err)
}
}

return datasets, count, nil
}

@@ -362,10 +448,22 @@ func UpdateDataset(ctx DBContext, rel *Dataset) error {
func IncreaseDatasetUseCount(uuid string) {

IncreaseAttachmentUseNumber(uuid)
attachments, _ := GetAttachmentsByUUIDs(strings.Split(uuid, ";"))

countMap := make(map[int64]int)

for _, attachment := range attachments {
value, ok := countMap[attachment.DatasetID]
if ok {
countMap[attachment.DatasetID] = value + 1
} else {
countMap[attachment.DatasetID] = 1
}

}

attachment, _ := GetAttachmentByUUID(uuid)
if attachment != nil {
x.Exec("UPDATE `dataset` SET use_count=use_count+1 WHERE id=?", attachment.DatasetID)
for key, value := range countMap {
x.Exec("UPDATE `dataset` SET use_count=use_count+? WHERE id=?", value, key)
}

}


+ 7
- 0
models/dataset_star.go View File

@@ -68,3 +68,10 @@ func isDatasetStaring(e Engine, userID, datasetID int64) bool {
has, _ := e.Get(&DatasetStar{0, userID, datasetID, 0})
return has
}

func GetDatasetIdsStarByUser(userID int64) []int64 {
var datasets []int64
_ = x.Table("dataset_star").Where("uid=?", userID).
Cols("dataset_star.dataset_id").Find(&datasets)
return datasets
}

+ 50
- 21
models/user_business_analysis.go View File

@@ -955,6 +955,8 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time,
return err
}
userNewAddActivity := make(map[int64]map[int64]int64)
userAcitvateJsonMap := make(map[int64]map[int64]int64)
userCurrentDayRegistMap := make(map[int64]map[int64]int64)
ParaWeight := getParaWeight()
userMetrics := make(map[string]int)
var indexTotal int64
@@ -1028,7 +1030,10 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time,
log.Info("has activity." + userRecord.Name)
addUserToMap(userNewAddActivity, userRecord.CreatedUnix, dateRecord.ID)
}

if userRecord.IsActive {
addUserToMap(userAcitvateJsonMap, userRecord.CreatedUnix, dateRecord.ID)
}
addUserToMap(userCurrentDayRegistMap, userRecord.CreatedUnix, dateRecord.ID)
}

indexTotal += PAGE_SIZE
@@ -1064,36 +1069,61 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time,
}
statictisSess.Insert(&useMetrics)
//update new user activity
updateNewUserAcitivity(userNewAddActivity, statictisSess)
updateNewUserAcitivity(userNewAddActivity, userAcitvateJsonMap, userCurrentDayRegistMap, statictisSess)
return nil
}

func updateNewUserAcitivity(currentUserActivity map[int64]map[int64]int64, statictisSess *xorm.Session) {
for key, value := range currentUserActivity {
func updateNewUserAcitivity(currentUserActivity map[int64]map[int64]int64, userAcitvateJsonMap map[int64]map[int64]int64, userCurrentDayRegistMap map[int64]map[int64]int64, statictisSess *xorm.Session) {
for key, value := range userCurrentDayRegistMap {
useMetrics := &UserMetrics{CountDate: key}
userAcitvateValue := userAcitvateJsonMap[key]
HuodongValue := currentUserActivity[key]
has, err := statictisSess.Get(useMetrics)
if err == nil && has {
userIdArrays := strings.Split(useMetrics.HasActivityUserJson, ",")
for _, userIdStr := range userIdArrays {
userIdInt, err := strconv.ParseInt(userIdStr, 10, 64)
if err == nil {
value[userIdInt] = userIdInt
}
}
userIdArray := ""
for _, tmpValue := range value {
userIdArray += fmt.Sprint(tmpValue) + ","
}
useMetrics.HasActivityUser = len(value)
if len(userIdArray) > 0 {
useMetrics.HasActivityUserJson = userIdArray[0 : len(userIdArray)-1]
}
updateSql := "update public.user_metrics set has_activity_user_json='" + useMetrics.HasActivityUserJson + "',regist_activity_user=" + fmt.Sprint(useMetrics.HasActivityUser) + " where count_date=" + fmt.Sprint(key)
ActivityUserArray, HuodongTotal := setUniqueUserId(useMetrics.HasActivityUserJson, HuodongValue)
useMetrics.HasActivityUser = HuodongTotal
useMetrics.HasActivityUserJson = ActivityUserArray

useMetrics.CurrentDayRegistUser = len(value)

RegistUserArray, lenRegistUser := setUniqueUserId(useMetrics.ActivityUserJson, userAcitvateValue)
useMetrics.ActivityUserJson = RegistUserArray
useMetrics.ActivateRegistUser = lenRegistUser

updateSql := "update public.user_metrics set has_activity_user_json='" + useMetrics.HasActivityUserJson +
"',regist_activity_user=" + fmt.Sprint(useMetrics.HasActivityUser) +
",activity_user_json='" + useMetrics.ActivityUserJson + "'" +
",activate_regist_user=" + fmt.Sprint(useMetrics.ActivateRegistUser) +
",not_activate_regist_user=" + fmt.Sprint(useMetrics.CurrentDayRegistUser-useMetrics.ActivateRegistUser) +
",current_day_regist_user=" + fmt.Sprint(useMetrics.CurrentDayRegistUser) +
" where count_date=" + fmt.Sprint(key)

statictisSess.Exec(updateSql)
}
}
}

func setUniqueUserId(jsonString string, value map[int64]int64) (string, int) {
if value == nil {
value = make(map[int64]int64, 0)
}
userIdArrays := strings.Split(jsonString, ",")
for _, userIdStr := range userIdArrays {
userIdInt, err := strconv.ParseInt(userIdStr, 10, 64)
if err == nil {
value[userIdInt] = userIdInt
}
}
userIdArray := ""
for _, tmpValue := range value {
userIdArray += fmt.Sprint(tmpValue) + ","
}
if len(userIdArray) > 0 {
return userIdArray[0 : len(userIdArray)-1], len(value)
}
return userIdArray, len(value)
}

func addUserToMap(currentUserActivity map[int64]map[int64]int64, registDate timeutil.TimeStamp, userId int64) {
CountDateTime := time.Date(registDate.Year(), registDate.AsTime().Month(), registDate.AsTime().Day(), 0, 1, 0, 0, registDate.AsTime().Location())
CountDate := CountDateTime.Unix()
@@ -1104,7 +1134,6 @@ func addUserToMap(currentUserActivity map[int64]map[int64]int64, registDate time
} else {
currentUserActivity[CountDate][userId] = userId
}

}

func setUserMetrics(userMetrics map[string]int, user *User, start_time int64, end_time int64, dateRecord UserBusinessAnalysis) {


+ 8
- 6
models/user_business_struct.go View File

@@ -467,11 +467,11 @@ type UserAnalysisPara struct {

type UserMetrics struct {
CountDate int64 `xorm:"pk"`
ActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"`
NotActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"`
ActivateIndex float64 `xorm:"NOT NULL DEFAULT 0"`
RegistActivityUser int `xorm:"NOT NULL DEFAULT 0"`
HasActivityUser int `xorm:"NOT NULL DEFAULT 0"`
ActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"` //当天激活用户
NotActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"` //当天未激活用户
ActivateIndex float64 `xorm:"NOT NULL DEFAULT 0"` //激活比率
RegistActivityUser int `xorm:"NOT NULL DEFAULT 0"` //当天注册激活的人中,有贡献活动的人
HasActivityUser int `xorm:"NOT NULL DEFAULT 0"` //当天有贡献活动的人
TotalUser int `xorm:"NOT NULL DEFAULT 0"`
TotalRegistUser int `xorm:"-"`
TotalActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"`
@@ -480,5 +480,7 @@ type UserMetrics struct {
DisplayDate string `xorm:"-"`
DataDate string `xorm:"NULL"`
DaysForMonth int `xorm:"NOT NULL DEFAULT 0"`
HasActivityUserJson string `xorm:"text NULL"`
HasActivityUserJson string `xorm:"text NULL"` //贡献活动用户列表
ActivityUserJson string `xorm:"text NULL"` //激活用户列表
CurrentDayRegistUser int `xorm:"NOT NULL DEFAULT 0"` //当天注册用户
}

+ 184
- 141
modules/cloudbrain/cloudbrain.go View File

@@ -44,6 +44,32 @@ var (
TrainResourceSpecs *models.ResourceSpecs
)

type GenerateCloudBrainTaskReq struct {
Ctx *context.Context
DisplayJobName string
JobName string
Image string
Command string
CodePath string
ModelPath string
BenchmarkPath string
Snn4ImageNetPath string
BrainScorePath string
JobType string
GpuQueue string
Description string
BranchName string
BootFile string
Params string
CommitID string
Uuids string
DatasetNames string
DatasetInfos map[string]models.DatasetInfo
BenchmarkTypeID int
BenchmarkChildTypeID int
ResourceSpecId int
}

func isAdminOrOwnerOrJobCreater(ctx *context.Context, job *models.Cloudbrain, err error) bool {
if !ctx.IsSigned {
return false
@@ -184,23 +210,17 @@ func AdminOrImageCreaterRight(ctx *context.Context) {

}

func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, uuid, codePath, modelPath, benchmarkPath, snn4imagenetPath, brainScorePath, jobType, gpuQueue, description, branchName, bootFile, params, commitID string, benchmarkTypeID, benchmarkChildTypeID, resourceSpecId int) error {

dataActualPath := setting.Attachment.Minio.RealPath +
setting.Attachment.Minio.Bucket + "/" +
setting.Attachment.Minio.BasePath +
models.AttachmentRelativePath(uuid) +
uuid

func GenerateTask(req GenerateCloudBrainTaskReq) error {
var resourceSpec *models.ResourceSpec
var versionCount int
if jobType == string(models.JobTypeTrain) {

if req.JobType == string(models.JobTypeTrain) {
versionCount = 1
if TrainResourceSpecs == nil {
json.Unmarshal([]byte(setting.TrainResourceSpecs), &TrainResourceSpecs)
}
for _, spec := range TrainResourceSpecs.ResourceSpec {
if resourceSpecId == spec.Id {
if req.ResourceSpecId == spec.Id {
resourceSpec = spec
}
}
@@ -209,7 +229,7 @@ func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command,
json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs)
}
for _, spec := range ResourceSpecs.ResourceSpec {
if resourceSpecId == spec.Id {
if req.ResourceSpecId == spec.Id {
resourceSpec = spec
}
}
@@ -217,25 +237,74 @@ func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command,
}

if resourceSpec == nil {
log.Error("no such resourceSpecId(%d)", resourceSpecId, ctx.Data["MsgID"])
log.Error("no such resourceSpecId(%d)", req.ResourceSpecId, req.Ctx.Data["MsgID"])
return errors.New("no such resourceSpec")
}

var datasetName string
attach, err := models.GetAttachmentByUUID(uuid)
if err != nil {
//for benchmark, do not return error
log.Error("GetAttachmentByUUID failed:%v", err)
volumes := []models.Volume{
{
HostPath: models.StHostPath{
Path: req.CodePath,
MountPath: CodeMountPath,
ReadOnly: false,
},
},
{
HostPath: models.StHostPath{
Path: req.ModelPath,
MountPath: ModelMountPath,
ReadOnly: false,
},
},
{
HostPath: models.StHostPath{
Path: req.BenchmarkPath,
MountPath: BenchMarkMountPath,
ReadOnly: true,
},
},
{
HostPath: models.StHostPath{
Path: req.Snn4ImageNetPath,
MountPath: Snn4imagenetMountPath,
ReadOnly: true,
},
},
{
HostPath: models.StHostPath{
Path: req.BrainScorePath,
MountPath: BrainScoreMountPath,
ReadOnly: true,
},
},
}

if len(req.DatasetInfos) == 1 {
volumes = append(volumes, models.Volume{
HostPath: models.StHostPath{
Path: req.DatasetInfos[req.Uuids].DataLocalPath,
MountPath: DataSetMountPath,
ReadOnly: true,
},
})
} else {
datasetName = attach.Name
for _, dataset := range req.DatasetInfos {
volumes = append(volumes, models.Volume{
HostPath: models.StHostPath{
Path: dataset.DataLocalPath,
MountPath: DataSetMountPath + "/" + dataset.Name,
ReadOnly: true,
},
})
}
}

createTime := timeutil.TimeStampNow()
jobResult, err := CreateJob(jobName, models.CreateJobParams{
JobName: jobName,
jobResult, err := CreateJob(req.JobName, models.CreateJobParams{
JobName: req.JobName,
RetryCount: 1,
GpuType: gpuQueue,
Image: image,
GpuType: req.GpuQueue,
Image: req.Image,
TaskRoles: []models.TaskRole{
{
Name: SubTaskName,
@@ -246,94 +315,51 @@ func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command,
GPUNumber: resourceSpec.GpuNum,
MemoryMB: resourceSpec.MemMiB,
ShmMB: resourceSpec.ShareMemMiB,
Command: command,
Command: req.Command,
NeedIBDevice: false,
IsMainRole: false,
UseNNI: false,
},
},
Volumes: []models.Volume{
{
HostPath: models.StHostPath{
Path: codePath,
MountPath: CodeMountPath,
ReadOnly: false,
},
},
{
HostPath: models.StHostPath{
Path: dataActualPath,
MountPath: DataSetMountPath,
ReadOnly: true,
},
},
{
HostPath: models.StHostPath{
Path: modelPath,
MountPath: ModelMountPath,
ReadOnly: false,
},
},
{
HostPath: models.StHostPath{
Path: benchmarkPath,
MountPath: BenchMarkMountPath,
ReadOnly: true,
},
},
{
HostPath: models.StHostPath{
Path: snn4imagenetPath,
MountPath: Snn4imagenetMountPath,
ReadOnly: true,
},
},
{
HostPath: models.StHostPath{
Path: brainScorePath,
MountPath: BrainScoreMountPath,
ReadOnly: true,
},
},
},
Volumes: volumes,
})
if err != nil {
log.Error("CreateJob failed:", err.Error(), ctx.Data["MsgID"])
log.Error("CreateJob failed:", err.Error(), req.Ctx.Data["MsgID"])
return err
}
if jobResult.Code != Success {
log.Error("CreateJob(%s) failed:%s", jobName, jobResult.Msg, ctx.Data["MsgID"])
log.Error("CreateJob(%s) failed:%s", req.JobName, jobResult.Msg, req.Ctx.Data["MsgID"])
return errors.New(jobResult.Msg)
}

var jobID = jobResult.Payload["jobId"].(string)
err = models.CreateCloudbrain(&models.Cloudbrain{
Status: string(models.JobWaiting),
UserID: ctx.User.ID,
RepoID: ctx.Repo.Repository.ID,
UserID: req.Ctx.User.ID,
RepoID: req.Ctx.Repo.Repository.ID,
JobID: jobID,
JobName: jobName,
DisplayJobName: displayJobName,
JobName: req.JobName,
DisplayJobName: req.DisplayJobName,
SubTaskName: SubTaskName,
JobType: jobType,
JobType: req.JobType,
Type: models.TypeCloudBrainOne,
Uuid: uuid,
Image: image,
GpuQueue: gpuQueue,
ResourceSpecId: resourceSpecId,
Uuid: req.Uuids,
Image: req.Image,
GpuQueue: req.GpuQueue,
ResourceSpecId: req.ResourceSpecId,
ComputeResource: models.GPUResource,
BenchmarkTypeID: benchmarkTypeID,
BenchmarkChildTypeID: benchmarkChildTypeID,
Description: description,
BenchmarkTypeID: req.BenchmarkTypeID,
BenchmarkChildTypeID: req.BenchmarkChildTypeID,
Description: req.Description,
IsLatestVersion: "1",
VersionCount: versionCount,
BranchName: branchName,
BootFile: bootFile,
DatasetName: datasetName,
Parameters: params,
BranchName: req.BranchName,
BootFile: req.BootFile,
DatasetName: req.DatasetNames,
Parameters: req.Params,
CreatedUnix: createTime,
UpdatedUnix: createTime,
CommitID: commitID,
CommitID: req.CommitID,
})

if err != nil {
@@ -342,17 +368,17 @@ func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command,

task, err := models.GetCloudbrainByJobID(jobID)
if err != nil {
log.Error("GetCloudbrainByName failed: %v", err.Error())
log.Error("GetCloudbrainByJobID failed: %v", err.Error())
return err
}
stringId := strconv.FormatInt(task.ID, 10)

if IsBenchmarkJob(jobType) {
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateBenchMarkTask)
} else if string(models.JobTypeTrain) == jobType {
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobID, displayJobName, models.ActionCreateGPUTrainTask)
if IsBenchmarkJob(req.JobType) {
notification.NotifyOtherTask(req.Ctx.User, req.Ctx.Repo.Repository, stringId, req.DisplayJobName, models.ActionCreateBenchMarkTask)
} else if string(models.JobTypeTrain) == req.JobType {
notification.NotifyOtherTask(req.Ctx.User, req.Ctx.Repo.Repository, jobID, req.DisplayJobName, models.ActionCreateGPUTrainTask)
} else {
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateDebugGPUTask)
notification.NotifyOtherTask(req.Ctx.User, req.Ctx.Repo.Repository, stringId, req.DisplayJobName, models.ActionCreateDebugGPUTask)
}

return nil
@@ -363,11 +389,6 @@ func IsBenchmarkJob(jobType string) bool {
}

func RestartTask(ctx *context.Context, task *models.Cloudbrain, newID *string) error {
dataActualPath := setting.Attachment.Minio.RealPath +
setting.Attachment.Minio.Bucket + "/" +
setting.Attachment.Minio.BasePath +
models.AttachmentRelativePath(task.Uuid) +
task.Uuid
jobName := task.JobName

var resourceSpec *models.ResourceSpec
@@ -385,6 +406,70 @@ func RestartTask(ctx *context.Context, task *models.Cloudbrain, newID *string) e
return errors.New("no such resourceSpec")
}

datasetInfos, _, err := models.GetDatasetInfo(task.Uuid)
if err != nil {
log.Error("GetDatasetInfo failed:%v", err, ctx.Data["MsgID"])
return err
}

volumes := []models.Volume{
{
HostPath: models.StHostPath{
Path: storage.GetMinioPath(jobName, CodeMountPath+"/"),
MountPath: CodeMountPath,
ReadOnly: false,
},
},
{
HostPath: models.StHostPath{
Path: storage.GetMinioPath(jobName, ModelMountPath+"/"),
MountPath: ModelMountPath,
ReadOnly: false,
},
},
{
HostPath: models.StHostPath{
Path: storage.GetMinioPath(jobName, BenchMarkMountPath+"/"),
MountPath: BenchMarkMountPath,
ReadOnly: true,
},
},
{
HostPath: models.StHostPath{
Path: storage.GetMinioPath(jobName, Snn4imagenetMountPath+"/"),
MountPath: Snn4imagenetMountPath,
ReadOnly: true,
},
},
{
HostPath: models.StHostPath{
Path: storage.GetMinioPath(jobName, BrainScoreMountPath+"/"),
MountPath: BrainScoreMountPath,
ReadOnly: true,
},
},
}

if len(datasetInfos) == 1 {
volumes = append(volumes, models.Volume{
HostPath: models.StHostPath{
Path: datasetInfos[task.Uuid].DataLocalPath,
MountPath: DataSetMountPath,
ReadOnly: true,
},
})
} else {
for _, dataset := range datasetInfos {
volumes = append(volumes, models.Volume{
HostPath: models.StHostPath{
Path: dataset.DataLocalPath,
MountPath: DataSetMountPath + "/" + dataset.Name,
ReadOnly: true,
},
})
}
}

createTime := timeutil.TimeStampNow()
jobResult, err := CreateJob(jobName, models.CreateJobParams{
JobName: jobName,
@@ -407,50 +492,7 @@ func RestartTask(ctx *context.Context, task *models.Cloudbrain, newID *string) e
UseNNI: false,
},
},
Volumes: []models.Volume{
{
HostPath: models.StHostPath{
Path: storage.GetMinioPath(jobName, CodeMountPath+"/"),
MountPath: CodeMountPath,
ReadOnly: false,
},
},
{
HostPath: models.StHostPath{
Path: dataActualPath,
MountPath: DataSetMountPath,
ReadOnly: true,
},
},
{
HostPath: models.StHostPath{
Path: storage.GetMinioPath(jobName, ModelMountPath+"/"),
MountPath: ModelMountPath,
ReadOnly: false,
},
},
{
HostPath: models.StHostPath{
Path: storage.GetMinioPath(jobName, BenchMarkMountPath+"/"),
MountPath: BenchMarkMountPath,
ReadOnly: true,
},
},
{
HostPath: models.StHostPath{
Path: storage.GetMinioPath(jobName, Snn4imagenetMountPath+"/"),
MountPath: Snn4imagenetMountPath,
ReadOnly: true,
},
},
{
HostPath: models.StHostPath{
Path: storage.GetMinioPath(jobName, BrainScoreMountPath+"/"),
MountPath: BrainScoreMountPath,
ReadOnly: true,
},
},
},
Volumes: volumes,
})
if err != nil {
log.Error("CreateJob failed:%v", err.Error(), ctx.Data["MsgID"])
@@ -473,6 +515,7 @@ func RestartTask(ctx *context.Context, task *models.Cloudbrain, newID *string) e
JobType: task.JobType,
Type: task.Type,
Uuid: task.Uuid,
DatasetName: task.DatasetName,
Image: task.Image,
GpuQueue: task.GpuQueue,
ResourceSpecId: task.ResourceSpecId,


+ 41
- 5
modules/grampus/grampus.go View File

@@ -1,12 +1,16 @@
package grampus

import (
"encoding/json"
"strings"

"code.gitea.io/gitea/modules/setting"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/timeutil"
"strings"
)

const (
@@ -15,12 +19,14 @@ const (
ProcessorTypeNPU = "npu.huawei.com/NPU"
ProcessorTypeGPU = "nvidia.com/gpu"

CommandPrepareScript = "pwd;cd /cache;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;" +
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_obs downloader_for_minio uploader_for_minio;"
//CommandPrepareScript = "pwd;cd /cache;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_obs downloader_for_minio uploader_for_minio;"

//CommandPrepareScript = "bash;pwd;apt-get -y update;apt-get -y upgrade;apt-get -y install wget;apt-get -y install unzip;" +
// "cd /tmp;mkdir -p output;mkdir -p code;mkdir -p dataset;wget -q https://git.openi.org.cn/OpenIOSSG/script_for_grampus/archive/master.zip;" +
// "unzip -q master.zip;cd script_for_grampus;chmod 777 downloader_for_obs uploader_for_obs downloader_for_minio uploader_for_minio;"
CodeArchiveName = "master.zip"
)

@@ -28,6 +34,8 @@ var (
poolInfos *models.PoolInfos
FlavorInfos *models.FlavorInfos
ImageInfos *models.ImageInfosModelArts

SpecialPools *models.SpecialPools
)

type GenerateTrainJobReq struct {
@@ -63,6 +71,27 @@ type GenerateTrainJobReq struct {

func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error) {
createTime := timeutil.TimeStampNow()

var CenterID []string
var CenterName []string

if SpecialPools != nil {
for _, pool := range SpecialPools.Pools {
if !pool.IsExclusive && strings.Contains(req.ComputeResource, pool.Type) {
org, _ := models.GetOrgByName(pool.Org)
if org != nil {
isOrgMember, _ := models.IsOrganizationMember(org.ID, ctx.User.ID)
if isOrgMember {
for _, info := range pool.Pool {
CenterID = append(CenterID, info.Queue)
CenterName = append(CenterName, info.Value)
}
}
}
}
}
}

jobResult, err := createJob(models.CreateGrampusJobRequest{
Name: req.JobName,
Tasks: []models.GrampusTasks{
@@ -72,6 +101,8 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error
ResourceSpecId: req.ResourceSpecId,
ImageId: req.ImageId,
ImageUrl: req.ImageUrl,
CenterID: CenterID,
CenterName: CenterName,
ReplicaNum: 1,
},
},
@@ -136,3 +167,8 @@ func TransTrainJobStatus(status string) string {

return strings.ToUpper(status)
}
func InitSpecialPool() {
if SpecialPools == nil && setting.Grampus.SpecialPools != "" {
json.Unmarshal([]byte(setting.Grampus.SpecialPools), &SpecialPools)
}
}

+ 6
- 14
modules/modelarts/modelarts.go View File

@@ -1,13 +1,14 @@
package modelarts

import (
"code.gitea.io/gitea/modules/timeutil"
"encoding/json"
"errors"
"fmt"
"path"
"strconv"

"code.gitea.io/gitea/modules/timeutil"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
@@ -50,6 +51,7 @@ const (
Lines = 500
TrainUrl = "train_url"
DataUrl = "data_url"
MultiDataUrl = "multi_data_url"
ResultUrl = "result_url"
CkptUrl = "ckpt_url"
DeviceTarget = "device_target"
@@ -96,6 +98,7 @@ type GenerateTrainJobReq struct {
VersionCount int
EngineName string
TotalVersionCount int
DatasetName string
}

type GenerateInferenceJobReq struct {
@@ -335,11 +338,6 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error
return err
}

attach, err := models.GetAttachmentByUUID(req.Uuid)
if err != nil {
log.Error("GetAttachmentByUUID(%s) failed:%v", strconv.FormatInt(jobResult.JobID, 10), err.Error())
return err
}
jobId := strconv.FormatInt(jobResult.JobID, 10)
err = models.CreateCloudbrain(&models.Cloudbrain{
Status: TransTrainJobStatus(jobResult.Status),
@@ -353,7 +351,7 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error
VersionID: jobResult.VersionID,
VersionName: jobResult.VersionName,
Uuid: req.Uuid,
DatasetName: attach.Name,
DatasetName: req.DatasetName,
CommitID: req.CommitID,
IsLatestVersion: req.IsLatestVersion,
ComputeResource: models.NPUResource,
@@ -408,12 +406,6 @@ func GenerateTrainJobVersion(ctx *context.Context, req *GenerateTrainJobReq, job
return err
}

attach, err := models.GetAttachmentByUUID(req.Uuid)
if err != nil {
log.Error("GetAttachmentByUUID(%s) failed:%v", strconv.FormatInt(jobResult.JobID, 10), err.Error())
return err
}

var jobTypes []string
jobTypes = append(jobTypes, string(models.JobTypeTrain))
repo := ctx.Repo.Repository
@@ -441,7 +433,7 @@ func GenerateTrainJobVersion(ctx *context.Context, req *GenerateTrainJobReq, job
VersionID: jobResult.VersionID,
VersionName: jobResult.VersionName,
Uuid: req.Uuid,
DatasetName: attach.Name,
DatasetName: req.DatasetName,
CommitID: req.CommitID,
IsLatestVersion: req.IsLatestVersion,
PreVersionName: req.PreVersionName,


+ 9
- 4
modules/setting/setting.go View File

@@ -465,6 +465,7 @@ var (
MaxDuration int64
TrainGpuTypes string
TrainResourceSpecs string
MaxDatasetNum int

//benchmark config
IsBenchmarkEnabled bool
@@ -530,10 +531,11 @@ var (

//grampus config
Grampus = struct {
Env string
Host string
UserName string
Password string
Env string
Host string
UserName string
Password string
SpecialPools string
}{}

//elk config
@@ -1309,6 +1311,7 @@ func NewContext() {
MaxDuration = sec.Key("MAX_DURATION").MustInt64(14400)
TrainGpuTypes = sec.Key("TRAIN_GPU_TYPES").MustString("")
TrainResourceSpecs = sec.Key("TRAIN_RESOURCE_SPECS").MustString("")
MaxDatasetNum = sec.Key("MAX_DATASET_NUM").MustInt(5)

sec = Cfg.Section("benchmark")
IsBenchmarkEnabled = sec.Key("ENABLED").MustBool(false)
@@ -1412,6 +1415,8 @@ func GetGrampusConfig() {
Grampus.Host = sec.Key("SERVER_HOST").MustString("")
Grampus.UserName = sec.Key("USERNAME").MustString("")
Grampus.Password = sec.Key("PASSWORD").MustString("")
Grampus.SpecialPools = sec.Key("SPECIAL_POOL").MustString("")

}

func SetRadarMapConfig() {


+ 5
- 0
options/locale/locale_en-US.ini View File

@@ -902,6 +902,7 @@ unzip_successed=Unzip Successed
unzip_failed=Unzip Failed
unzip_stared=Unzipping
unzip_status=Unzip Status
collection_num=Collection Nums
[repo]
owner = Owner
repo_name = Repository Name
@@ -1178,6 +1179,8 @@ model.manage.model_accuracy = Model Accuracy

grampus.train_job.ai_center = AI Center
grampus.dataset_path_rule = The code is storaged in /cache/code;the dataset is storaged in /cache/dataset;and please put your model into /cache/output, then you can download it online。
grampus.gpu_dataset_path_rule = The code is storaged in /tmp/code;the dataset is storaged in /tmp/dataset;and please put your model into /tmp/output, then you can download it online。
grampus.no_operate_right = You have no right to do this operation.

template.items = Template Items
template.git_content = Git Content (Default Branch)
@@ -3076,3 +3079,5 @@ TRAIN = TRAIN
INFERENCE = INFERENCE
BENCHMARK = BENCHMARK
brain_area = Brain Area

error.dataset_select = dataset select error:the count exceed the limit or has same name

+ 6
- 2
options/locale/locale_zh-CN.ini View File

@@ -907,7 +907,7 @@ unzip_successed=解压成功
unzip_failed=解压失败
unzip_stared=解压中
unzip_status=解压状态
collection_num=收藏数量
[repo]
owner=拥有者
repo_name=项目名称
@@ -1192,6 +1192,9 @@ model.manage.model_accuracy = 模型精度

grampus.train_job.ai_center=智算中心
grampus.dataset_path_rule = 训练脚本存储在/cache/code中,数据集存储在/cache/dataset中,训练输出请存储在/cache/output中以供后续下载。
grampus.gpu_dataset_path_rule = 训练脚本存储在/tmp/code中,数据集存储在/tmp/dataset中,训练输出请存储在/tmp/output中以供后续下载。

grampus.no_operate_right = 您没有权限创建这类任务。

template.items=模板选项
template.git_content=Git数据(默认分支)
@@ -1471,7 +1474,7 @@ issues.filter_sort.mostforks=派生由多到少
issues.filter_sort.fewestforks=派生由少到多
issues.filter_sort.downloadtimes=下载次数
issues.filter_sort.citations=引用次数
issues.filter_sort.moststars=收藏数量
issues.filter_sort.moststars=点赞由多到少
issues.filter_sort.mostusecount=最多引用
issues.filter_sort.fewestusecount=最少引用

@@ -3092,3 +3095,4 @@ INFERENCE = 推理任务
BENCHMARK = 评测任务
brain_area = 脑区

error.dataset_select = 数据集选择错误:数量超过限制或者有同名数据集

+ 8
- 2
public/home/home.js View File

@@ -156,7 +156,7 @@ document.onreadystatechange = function () {
html += recordPrefix + actionName;
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>"
}
else if(record.OpType == "24" || record.OpType == "26" || record.OpType == "27" || record.OpType == "28" || record.OpType == "30" || record.OpType == "31"){
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 += " <a href=\"" + getTaskLink(record) + "\" rel=\"nofollow\">" + record.RefName + "</a>"
}
@@ -201,6 +201,8 @@ function getTaskLink(record){
re = re + "/modelmanage/show_model_info?name=" + record.RefName;
}else if(record.OpType == 31){
re = re + "/cloudbrain/train-job/" + record.Content;
}else if(record.OpType == 32 || record.OpType == 33){
re = re + "/grampus/train-job/" + record.Content;
}
re = encodeURI(re);
return re;
@@ -374,7 +376,9 @@ var actionNameZH={
"28":"创建了推理任务",
"29":"创建了评测任务",
"30":"导入了新模型",
"31":"创建了CPU/GPU类型训练任务"
"31":"创建了CPU/GPU类型训练任务",
"32":"创建了NPU类型训练任务",
"33":"创建了CPU/GPU类型训练任务"
};

var actionNameEN={
@@ -401,6 +405,8 @@ var actionNameEN={
"29":" created profiling task",
"30":" created new model",
"31":" created CPU/GPU type training task",
"32":" created NPU type training task",
"33":" created CPU/GPU type training task"
};

var repoAndOrgZH={


+ 2
- 7
routers/admin/cloudbrains.go View File

@@ -43,12 +43,6 @@ func CloudBrains(ctx *context.Context) {
if page <= 0 {
page = 1
}
debugType := models.TypeCloudBrainAll
if listType == models.GPUResource {
debugType = models.TypeCloudBrainOne
} else if listType == models.NPUResource {
debugType = models.TypeCloudBrainTwo
}

var jobTypes []string
jobTypeNot := false
@@ -77,13 +71,14 @@ func CloudBrains(ctx *context.Context) {
PageSize: setting.UI.IssuePagingNum,
},
Keyword: keyword,
Type: debugType,
JobTypeNot: jobTypeNot,
JobStatusNot: jobStatusNot,
JobStatus: jobStatuses,
JobTypes: jobTypes,
NeedRepoInfo: true,
IsLatestVersion: modelarts.IsLatestVersion,
ComputeResource: listType,
Type: models.TypeCloudBrainAll,
})
if err != nil {
ctx.ServerError("Get job failed:", err)


+ 4
- 3
routers/admin/dataset.go View File

@@ -77,9 +77,10 @@ func Datasets(ctx *context.Context) {
Page: page,
PageSize: setting.UI.ExplorePagingNum,
},
Keyword: keyword,
RecommendOnly: ctx.QueryBool("recommend"),
SearchOrderBy: orderBy,
Keyword: keyword,
RecommendOnly: ctx.QueryBool("recommend"),
CloudBrainType: -1,
SearchOrderBy: orderBy,
})
if err != nil {
ctx.ServerError("SearchDataset", err)


+ 3
- 10
routers/api/v1/repo/repo_dashbord.go View File

@@ -887,19 +887,12 @@ func getTimePeroid(ctx *context.Context, recordBeginTime time.Time) (time.Time,
if queryType == "all" {
beginTime = recordBeginTimeTemp
endTime = now
} else if queryType == "today" {
} else if queryType == "yesterday" {
endTime = now
beginTime = time.Date(endTime.Year(), endTime.Month(), endTime.Day(), 0, 0, 0, 0, now.Location())
} else if queryType == "yesterday" {
endTime = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
beginTime = endTime.AddDate(0, 0, -1)

} else if queryType == "last_7day" {
beginTime = now.AddDate(0, 0, -7)
beginTime = time.Date(beginTime.Year(), beginTime.Month(), beginTime.Day(), 0, 0, 0, 0, now.Location())
endTime = now
} else if queryType == "last_30day" {
beginTime = now.AddDate(0, 0, -30)
} else if queryType == "current_week" {
beginTime = now.AddDate(0, 0, -int(time.Now().Weekday())+2) //begin from monday
beginTime = time.Date(beginTime.Year(), beginTime.Month(), beginTime.Day(), 0, 0, 0, 0, now.Location())
endTime = now
} else if queryType == "current_month" {


+ 10
- 9
routers/home.go View File

@@ -351,15 +351,16 @@ func ExploreDatasets(ctx *context.Context) {
}

opts := &models.SearchDatasetOptions{
Keyword: keyword,
IncludePublic: true,
SearchOrderBy: orderBy,
Category: category,
Task: task,
License: license,
OwnerID: ownerID,
DatasetIDs: datasetsIds,
RecommendOnly: ctx.QueryBool("recommend"),
Keyword: keyword,
IncludePublic: true,
SearchOrderBy: orderBy,
Category: category,
Task: task,
License: license,
OwnerID: ownerID,
DatasetIDs: datasetsIds,
RecommendOnly: ctx.QueryBool("recommend"),
CloudBrainType: -1,
ListOptions: models.ListOptions{
Page: page,
PageSize: 30,


+ 120
- 35
routers/repo/cloudbrain.go View File

@@ -208,27 +208,14 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {
displayJobName := form.DisplayJobName
jobName := util.ConvertDisplayJobNameToJobName(displayJobName)
image := strings.TrimSpace(form.Image)
uuid := form.Attachment
uuids := form.Attachment
jobType := form.JobType
gpuQueue := form.GpuType
codePath := setting.JobPath + jobName + cloudbrain.CodeMountPath
resourceSpecId := form.ResourceSpecId
branchName := form.BranchName
repo := ctx.Repo.Repository

tpl := tplCloudBrainNew
command := cloudbrain.Command
if jobType == string(models.JobTypeTrain) {
tpl = tplCloudBrainTrainJobNew
commandTrain, err := getTrainJobCommand(form)
if err != nil {
log.Error("getTrainJobCommand failed: %v", err)
ctx.RenderWithErr(err.Error(), tpl, &form)
return
}

command = commandTrain
}

tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, jobType, displayJobName)
if err == nil {
@@ -274,6 +261,27 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {
}
}

datasetInfos, datasetNames, err := models.GetDatasetInfo(uuids)
if err != nil {
log.Error("GetDatasetInfo failed: %v", err, ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tpl, &form)
return
}

command := cloudbrain.Command
if jobType == string(models.JobTypeTrain) {
tpl = tplCloudBrainTrainJobNew
commandTrain, err := getTrainJobCommand(form)
if err != nil {
log.Error("getTrainJobCommand failed: %v", err)
ctx.RenderWithErr(err.Error(), tpl, &form)
return
}

command = commandTrain
}

if branchName == "" {
branchName = cloudbrain.DefaultBranchName
}
@@ -286,11 +294,33 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {

commitID, _ := ctx.Repo.GitRepo.GetBranchCommitID(branchName)

err = cloudbrain.GenerateTask(ctx, displayJobName, jobName, image, command, uuid, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"),
storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"),
storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"),
storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, form.Description, branchName, form.BootFile, form.Params,
commitID, 0, 0, resourceSpecId)
req := cloudbrain.GenerateCloudBrainTaskReq{
Ctx: ctx,
DisplayJobName: displayJobName,
JobName: jobName,
Image: image,
Command: command,
Uuids: uuids,
DatasetNames: datasetNames,
DatasetInfos: datasetInfos,
CodePath: storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"),
ModelPath: storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"),
BenchmarkPath: storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"),
Snn4ImageNetPath: storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"),
BrainScorePath: storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"),
JobType: jobType,
GpuQueue: gpuQueue,
Description: form.Description,
BranchName: branchName,
BootFile: form.BootFile,
Params: form.Params,
CommitID: commitID,
BenchmarkTypeID: 0,
BenchmarkChildTypeID: 0,
ResourceSpecId: resourceSpecId,
}

err = cloudbrain.GenerateTask(req)
if err != nil {
cloudBrainNewDataPrepare(ctx)
ctx.RenderWithErr(err.Error(), tpl, &form)
@@ -575,12 +605,6 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo
}

}
attachment, err := models.GetAttachmentByUUID(task.Uuid)
if err == nil {
ctx.Data["datasetname"] = attachment.Name
} else {
ctx.Data["datasetname"] = ""
}

ctx.Data["task"] = task
ctx.Data["jobName"] = task.JobName
@@ -2011,11 +2035,42 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo
//return
}

err = cloudbrain.GenerateTask(ctx, displayJobName, jobName, image, command, childInfo.Attachment, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"),
storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"),
storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"),
storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), string(models.JobTypeBenchmark), gpuQueue, form.Description, cloudbrain.DefaultBranchName, "", "",
"", benchmarkTypeID, benchmarkChildTypeID, resourceSpecId)
uuid := childInfo.Attachment
datasetInfos, datasetNames, err := models.GetDatasetInfo(uuid)
if err != nil {
log.Error("GetDatasetInfo failed: %v", err, ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tplCloudBrainBenchmarkNew, &form)
return
}

req := cloudbrain.GenerateCloudBrainTaskReq{
Ctx: ctx,
DisplayJobName: displayJobName,
JobName: jobName,
Image: image,
Command: command,
Uuids: uuid,
DatasetNames: datasetNames,
DatasetInfos: datasetInfos,
CodePath: storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"),
ModelPath: storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"),
BenchmarkPath: storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"),
Snn4ImageNetPath: storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"),
BrainScorePath: storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"),
JobType: string(models.JobTypeBenchmark),
GpuQueue: gpuQueue,
Description: form.Description,
BranchName: cloudbrain.DefaultBranchName,
BootFile: "",
Params: "",
CommitID: "",
BenchmarkTypeID: benchmarkTypeID,
BenchmarkChildTypeID: benchmarkChildTypeID,
ResourceSpecId: resourceSpecId,
}

err = cloudbrain.GenerateTask(req)
if err != nil {
cloudBrainNewDataPrepare(ctx)
ctx.RenderWithErr(err.Error(), tplCloudBrainBenchmarkNew, &form)
@@ -2109,11 +2164,41 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm)
command = fmt.Sprintf(cloudbrain.BrainScoreCommand, getBrainRegion(benchmarkChildTypeID), displayJobName, trimSpaceNewlineInString(form.Description))
}

err = cloudbrain.GenerateTask(ctx, displayJobName, jobName, image, command, uuid, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"),
storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"),
storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"),
storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, form.Description, branchName, form.BootFile, form.Params,
"", 0, benchmarkChildTypeID, resourceSpecId)
datasetInfos, datasetNames, err := models.GetDatasetInfo(uuid)
if err != nil {
log.Error("GetDatasetInfo failed: %v", err, ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tpl, &form)
return
}

req := cloudbrain.GenerateCloudBrainTaskReq{
Ctx: ctx,
DisplayJobName: displayJobName,
JobName: jobName,
Image: image,
Command: command,
Uuids: uuid,
DatasetNames: datasetNames,
DatasetInfos: datasetInfos,
CodePath: storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"),
ModelPath: storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"),
BenchmarkPath: storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"),
Snn4ImageNetPath: storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"),
BrainScorePath: storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"),
JobType: jobType,
GpuQueue: gpuQueue,
Description: form.Description,
BranchName: branchName,
BootFile: form.BootFile,
Params: form.Params,
CommitID: "",
BenchmarkTypeID: 0,
BenchmarkChildTypeID: benchmarkChildTypeID,
ResourceSpecId: resourceSpecId,
}

err = cloudbrain.GenerateTask(req)
if err != nil {
cloudBrainNewDataPrepare(ctx)
ctx.RenderWithErr(err.Error(), tpl, &form)


+ 78
- 0
routers/repo/dataset.go View File

@@ -410,6 +410,84 @@ func MyDatasets(ctx *context.Context) {
})
}

func datasetMultiple(ctx *context.Context, opts *models.SearchDatasetOptions) {
page := ctx.QueryInt("page")
cloudbrainType := ctx.QueryInt("type")
keyword := strings.Trim(ctx.Query("q"), " ")
orderBy := models.SearchOrderByRecentUpdated
opts.Keyword = keyword
opts.SearchOrderBy = orderBy
opts.RecommendOnly = ctx.QueryBool("recommend")
opts.CloudBrainType = cloudbrainType
opts.ListOptions = models.ListOptions{
Page: page,
PageSize: setting.UI.DatasetPagingNum,
}
opts.NeedAttachment = true
opts.JustNeedZipFile = true
opts.User = ctx.User

datasets, count, err := models.SearchDataset(opts)

if err != nil {
ctx.ServerError("datasets", err)
return
}

data, err := json.Marshal(datasets)
if err != nil {
log.Error("json.Marshal failed:", err.Error())
ctx.JSON(200, map[string]string{
"result_code": "-1",
"error_msg": err.Error(),
"data": "",
})
return
}
ctx.JSON(200, map[string]string{
"result_code": "0",
"data": string(data),
"count": strconv.FormatInt(count, 10),
})

}

func CurrentRepoDatasetMultiple(ctx *context.Context) {

opts := &models.SearchDatasetOptions{
RepoID: ctx.Repo.Repository.ID,
}
datasetMultiple(ctx, opts)

}

func MyDatasetsMultiple(ctx *context.Context) {

opts := &models.SearchDatasetOptions{
UploadAttachmentByMe: true,
}
datasetMultiple(ctx, opts)

}

func PublicDatasetMultiple(ctx *context.Context) {

opts := &models.SearchDatasetOptions{
PublicOnly: true,
}
datasetMultiple(ctx, opts)

}

func MyFavoriteDatasetMultiple(ctx *context.Context) {

opts := &models.SearchDatasetOptions{
StarByMe: true,
DatasetIDs: models.GetDatasetIdsStarByUser(ctx.User.ID),
}
datasetMultiple(ctx, opts)
}

func PublicDataset(ctx *context.Context) {
page := ctx.QueryInt("page")
cloudbrainType := ctx.QueryInt("type")


+ 67
- 5
routers/repo/grampus.go View File

@@ -71,6 +71,25 @@ func grampusTrainJobNewDataPrepare(ctx *context.Context, processType string) err
ctx.Data["images"] = images.Infos
}

grampus.InitSpecialPool()

ctx.Data["GPUEnabled"] = true
ctx.Data["NPUEnabled"] = true

if grampus.SpecialPools != nil {
for _, pool := range grampus.SpecialPools.Pools {
if pool.IsExclusive {
org, _ := models.GetOrgByName(pool.Org)
if org != nil {
isOrgMember, _ := models.IsOrganizationMember(org.ID, ctx.User.ID)
if !isOrgMember {
ctx.Data[pool.Type+"Enabled"] = false
}
}
}
}
}

//get valid resource specs
specs, err := grampus.GetResourceSpecs(processType)
if err != nil {
@@ -128,10 +147,18 @@ func GrampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain
image := strings.TrimSpace(form.Image)

if !jobNamePattern.MatchString(displayJobName) {
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tplGrampusTrainJobGPUNew, &form)
return
}

errStr := checkSpecialPool(ctx, "GPU")
if errStr != "" {
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU)
ctx.RenderWithErr(errStr, tplGrampusTrainJobGPUNew, &form)
return
}

//check count limit
count, err := models.GetGrampusCountByUserID(ctx.User.ID, string(models.JobTypeTrain), models.GPUResource)
if err != nil {
@@ -263,6 +290,28 @@ func GrampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job")
}

func checkSpecialPool(ctx *context.Context, resourceType string) string {
grampus.InitSpecialPool()
if grampus.SpecialPools != nil {
for _, pool := range grampus.SpecialPools.Pools {

if pool.IsExclusive && pool.Type == resourceType {

org, _ := models.GetOrgByName(pool.Org)
if org != nil {
isOrgMember, _ := models.IsOrganizationMember(org.ID, ctx.User.ID)
if !isOrgMember {
return ctx.Tr("repo.grampus.no_operate_right")
}
}
}

}

}
return ""
}

func GrampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrainJobForm) {
displayJobName := form.DisplayJobName
jobName := util.ConvertDisplayJobNameToJobName(displayJobName)
@@ -281,10 +330,18 @@ func GrampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain
engineName := form.EngineName

if !jobNamePattern.MatchString(displayJobName) {
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tplGrampusTrainJobNPUNew, &form)
return
}

errStr := checkSpecialPool(ctx, "NPU")
if errStr != "" {
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU)
ctx.RenderWithErr(errStr, tplGrampusTrainJobGPUNew, &form)
return
}

//check count limit
count, err := models.GetGrampusCountByUserID(ctx.User.ID, string(models.JobTypeTrain), models.NPUResource)
if err != nil {
@@ -607,7 +664,12 @@ func GrampusGetLog(ctx *context.Context) {
func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bootFile, paramSrc, outputRemotePath, datasetName string) (string, error) {
var command string

command += grampus.CommandPrepareScript
workDir := grampus.NpuWorkDir
if processorType == grampus.ProcessorTypeGPU {
workDir = grampus.GpuWorkDir
}

command += "pwd;cd " + workDir + grampus.CommandPrepareScript
//download code & dataset
if processorType == grampus.ProcessorTypeNPU {
commandDownload := "./downloader_for_obs " + setting.Bucket + " " + codeRemotePath + " " + grampus.CodeArchiveName + " " + dataRemotePath + " " + datasetName + ";"
@@ -626,7 +688,7 @@ func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bo
if strings.HasSuffix(datasetName, ".tar.gz") {
toolUnzip = "tar -zxvf "
}
commandUnzip := "cd /cache/code;unzip -q master.zip;echo \"start to unzip dataset\";cd /cache/dataset;" + toolUnzip + datasetName + ";"
commandUnzip := "cd " + workDir + "code;unzip -q master.zip;echo \"start to unzip dataset\";cd " + workDir + "dataset;" + toolUnzip + datasetName + ";"
command += commandUnzip

//check unzip result
@@ -655,7 +717,7 @@ func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bo
}
}

commandCode := "cd /cache/code/" + strings.ToLower(repoName) + ";python " + bootFile + paramCode + ";"
commandCode := "cd " + workDir + "code/" + strings.ToLower(repoName) + ";python " + bootFile + paramCode + ";"
command += commandCode

//get exec result
@@ -664,10 +726,10 @@ func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bo

//upload models
if processorType == grampus.ProcessorTypeNPU {
commandUpload := "cd /cache/script_for_grampus/;./uploader_for_obs " + setting.Bucket + " " + outputRemotePath + " " + "/cache/output/;"
commandUpload := "cd " + workDir + "script_for_grampus/;./uploader_for_obs " + setting.Bucket + " " + outputRemotePath + " " + workDir + "output/;"
command += commandUpload
} else if processorType == grampus.ProcessorTypeGPU {
commandUpload := "cd /cache/script_for_grampus/;./uploader_for_minio " + setting.Grampus.Env + " " + outputRemotePath + " " + "/cache/output/;"
commandUpload := "cd " + workDir + "script_for_grampus/;./uploader_for_minio " + setting.Grampus.Env + " " + outputRemotePath + " " + workDir + "output/;"
command += commandUpload
}



+ 123
- 8
routers/repo/modelarts.go View File

@@ -285,14 +285,37 @@ func NotebookShow(ctx *context.Context) {
}
}

datasetDownloadLink := ""
datasetDownload := make([]models.DatasetDownload, 0)
if ctx.IsSigned {
if task.Uuid != "" && task.UserID == ctx.User.ID {
attachment, err := models.GetAttachmentByUUID(task.Uuid)
if err == nil {
task.DatasetName = attachment.Name
datasetDownloadLink = attachment.S3DownloadURL()
uuidList := strings.Split(task.Uuid, ";")
for _, uuidStr := range uuidList {
attachment, err := models.GetAttachmentByUUID(uuidStr)
if err != nil {
log.Error("GetAttachmentByUUID failed:%v", err.Error())
return
}
dataset, err := models.GetDatasetByID(attachment.DatasetID)
if err != nil {
log.Error("GetDatasetByID failed:%v", err.Error())
return
}
repo, err := models.GetRepositoryByID(dataset.RepoID)
if err != nil {
log.Error("GetRepositoryByID failed:%v", err.Error())
return
}
datasetDownload = append(datasetDownload, models.DatasetDownload{
DatasetName: attachment.Name,
DatasetDownloadLink: attachment.S3DownloadURL(),
RepositoryLink: repo.Link() + "/datasets",
})

}
// datasetName, err := GetDatasetNameByUUID(task.Uuid)
// if err == nil {
// task.DatasetName = datasetName
// }
}
}
user, err := models.GetUserByID(task.UserID)
@@ -324,7 +347,7 @@ func NotebookShow(ctx *context.Context) {
task.TrainJobDuration = models.ConvertDurationToStr(task.Duration)
}
ctx.Data["duration"] = task.TrainJobDuration
ctx.Data["datasetDownloadLink"] = datasetDownloadLink
ctx.Data["datasetDownload"] = datasetDownload
ctx.Data["task"] = task
ctx.Data["ID"] = ID
ctx.Data["jobName"] = task.JobName
@@ -962,7 +985,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm)
codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath
outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath + VersionOutputPath + "/"
logObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.LogPath + VersionOutputPath + "/"
dataPath := "/" + setting.Bucket + "/" + setting.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/" + uuid + uuid + "/"
// dataPath := "/" + setting.Bucket + "/" + setting.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/" + uuid + uuid + "/"
branch_name := form.BranchName
isLatestVersion := modelarts.IsLatestVersion
FlavorName := form.FlavorName
@@ -1078,6 +1101,27 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm)
Value: modelarts.Ascend,
})
}
datasUrlList, dataUrl, datasetNames, isMultiDataset, err := getDatasUrlListByUUIDS(uuid)
if err != nil {
log.Error("Failed to getDatasUrlListByUUIDS: %v", err)
trainJobErrorNewDataPrepare(ctx, form)
ctx.RenderWithErr("Failed to getDatasUrlListByUUIDS:"+err.Error(), tplModelArtsTrainJobNew, &form)
return
}
dataPath := dataUrl
jsondatas, err := json.Marshal(datasUrlList)
if err != nil {
log.Error("Failed to Marshal: %v", err)
trainJobErrorNewDataPrepare(ctx, form)
ctx.RenderWithErr("json error:"+err.Error(), tplModelArtsTrainJobNew, &form)
return
}
if isMultiDataset {
param = append(param, models.Parameter{
Label: modelarts.MultiDataUrl,
Value: string(jsondatas),
})
}

//save param config
if isSaveParam == "on" {
@@ -1144,6 +1188,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm)
EngineName: EngineName,
VersionCount: VersionCount,
TotalVersionCount: modelarts.TotalVersionCount,
DatasetName: datasetNames,
}

//将params转换Parameters.Parameter,出错时返回给前端
@@ -1205,7 +1250,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ
codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath + VersionOutputPath + "/"
outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath + VersionOutputPath + "/"
logObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.LogPath + VersionOutputPath + "/"
dataPath := "/" + setting.Bucket + "/" + setting.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/" + uuid + uuid + "/"
// dataPath := "/" + setting.Bucket + "/" + setting.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/" + uuid + uuid + "/"
branch_name := form.BranchName
PreVersionName := form.VersionName
FlavorName := form.FlavorName
@@ -1297,6 +1342,28 @@ 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)
ctx.RenderWithErr("Failed to getDatasUrlListByUUIDS:"+err.Error(), tplModelArtsTrainJobVersionNew, &form)
return
}
dataPath := dataUrl
jsondatas, err := json.Marshal(datasUrlList)
if err != nil {
log.Error("Failed to Marshal: %v", err)
versionErrorDataPrepare(ctx, form)
ctx.RenderWithErr("json error:"+err.Error(), tplModelArtsTrainJobVersionNew, &form)
return
}
if isMultiDataset {
param = append(param, models.Parameter{
Label: modelarts.MultiDataUrl,
Value: string(jsondatas),
})
}

//save param config
if isSaveParam == "on" {
saveparams := append(param, models.Parameter{
@@ -1369,6 +1436,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ
EngineName: EngineName,
PreVersionName: PreVersionName,
TotalVersionCount: latestTask.TotalVersionCount + 1,
DatasetName: datasetNames,
}

err = modelarts.GenerateTrainJobVersion(ctx, req, jobID)
@@ -2414,3 +2482,50 @@ func TrainJobDownloadLogFile(ctx *context.Context) {
ctx.Resp.Header().Set("Cache-Control", "max-age=0")
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently)
}
func getDatasUrlListByUUIDS(uuidStr string) ([]models.Datasurl, string, string, bool, error) {
var isMultiDataset bool
var dataUrl string
var datasetNames string
var datasUrlList []models.Datasurl
uuids := strings.Split(uuidStr, ";")
if len(uuids) > setting.MaxDatasetNum {
log.Error("the dataset count(%d) exceed the limit", len(uuids))
return datasUrlList, dataUrl, datasetNames, isMultiDataset, errors.New("the dataset count exceed the limit")
}

datasetInfos := make(map[string]models.DatasetInfo)
attachs, err := models.GetAttachmentsByUUIDs(uuids)
if err != nil {
log.Error("GetAttachmentsByUUIDs failed: %v", err)
return datasUrlList, dataUrl, datasetNames, isMultiDataset, errors.New("GetAttachmentsByUUIDs failed")
}
for i, attach := range attachs {
fileName := strings.TrimSuffix(strings.TrimSuffix(strings.TrimSuffix(attach.Name, ".zip"), ".tar.gz"), ".tgz")
for _, datasetInfo := range datasetInfos {
if fileName == datasetInfo.Name {
log.Error("the dataset name is same: %v", attach.Name)
return datasUrlList, dataUrl, datasetNames, isMultiDataset, errors.New("the dataset name is same")
}
}
if len(attachs) <= 1 {
dataUrl = "/" + setting.Bucket + "/" + setting.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID + attach.UUID + "/"
isMultiDataset = false
} else {
dataUrl = "/" + setting.Bucket + "/" + setting.BasePath + path.Join(attachs[0].UUID[0:1], attachs[0].UUID[1:2]) + "/" + attachs[0].UUID + attachs[0].UUID + "/"
datasetUrl := "s3://" + setting.Bucket + "/" + setting.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID + attach.UUID + "/"
datasUrlList = append(datasUrlList, models.Datasurl{
DatasetUrl: datasetUrl,
DatasetName: fileName,
})
isMultiDataset = true
}

if i == 0 {
datasetNames = attach.Name
} else {
datasetNames += ";" + attach.Name
}
}

return datasUrlList, dataUrl, datasetNames, isMultiDataset, nil
}

+ 5
- 0
routers/routes/routes.go View File

@@ -1026,6 +1026,11 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/public_datasets", repo.PublicDataset)
m.Get("/my_favorite", repo.MyFavoriteDataset)

m.Get("/current_repo_m", repo.CurrentRepoDatasetMultiple)
m.Get("/my_datasets_m", repo.MyDatasetsMultiple)
m.Get("/public_datasets_m", repo.PublicDatasetMultiple)
m.Get("/my_favorite_m", repo.MyFavoriteDatasetMultiple)

m.Group("/status", func() {
m.Get("/:uuid", repo.GetDatasetStatus)
})


+ 1
- 0
routers/user/profile.go View File

@@ -263,6 +263,7 @@ func Profile(ctx *context.Context) {
Page: page,
PageSize: setting.UI.ExplorePagingNum,
},
CloudBrainType: -1,
}

if len(datasetSearchOptions.SearchOrderBy) == 0 {


+ 1
- 1
services/socketwrap/clientManager.go View File

@@ -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}
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}

type ClientsManager struct {
Clients *orderedmap.OrderedMap


+ 3
- 3
templates/admin/cloudbrain/list.tmpl View File

@@ -102,7 +102,7 @@
</a>
{{else if eq .JobType "TRAIN"}}
<a class="title"
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts{{end}}/train-job/{{$JobID}}"
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 0}}/cloudbrain{{else if eq .Cloudbrain.Type 1}}/modelarts{{else if eq .Cloudbrain.Type 2}}/grampus{{end}}/train-job/{{$JobID}}"
title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
@@ -204,7 +204,7 @@
{{else}}
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}"
class="ui basic ai_stop_version {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "SUCCEEDED" "STOPPED"}}disabled {{else}} blue {{end}}button"
data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain/train-job{{else}}/modelarts/{{if eq .JobType "INFERENCE"}}inference-job{{else}}train-job{{end}}{{end}}"
data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}/grampus/train-job{{else}}/modelarts/{{if eq .JobType "INFERENCE"}}inference-job{{else}}train-job{{end}}{{end}}"
data-jobid="{{$JobID}}" data-version="{{.VersionName}}">
{{$.i18n.Tr "repo.stop"}}
</a>
@@ -212,7 +212,7 @@
</div>
<!-- 删除任务 -->
<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 .ComputeResource "NPU"}}/modelarts/notebook{{else}}/cloudbrain{{end}}/train-job{{end}}/{{$JobID}}/del?isadminpage=true'
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}}{{end}}/{{$JobID}}/del?isadminpage=true'
method="post">
{{$.CsrfTokenHtml}}
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}"


+ 2
- 2
templates/custom/select_dataset_train.tmpl View File

@@ -1,11 +1,11 @@
<div class="dataset-repolink" id="dataset-repolink-init" style="display: none;" data-repolink="{{.RepoLink}}"
data-dataset-type="{{.datasetType}}"></div>
<div class="inline required unite min_title field" id="dataset-base" style="margin-bottom: 0 !important;">
<div class="inline required min_title field" id="dataset-base" style="margin-bottom: 0 !important;">
{{if or (.benchmarkMode) (.newInference)}}
<label
style="font-weight: normal;">{{if .benchmarkMode}}{{.i18n.Tr "repo.model_manager"}}</label><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>{{else}}{{.i18n.Tr "dataset.dataset"}}</label>&nbsp;&nbsp;&nbsp;&nbsp;{{end}}
{{else}}
<label style="font-weight: normal;">{{.i18n.Tr "dataset.dataset"}}</label>&nbsp;&nbsp;&nbsp;
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "dataset.dataset"}}</label>
{{end}}
<input type="hidden" name="attachment" :value="dataset_uuid">
<input class="disabled" type="text" :value="dataset_name" required onfocus="this.blur();" style="width: 48.5%;">


+ 1
- 1
templates/explore/datasets.tmpl View File

@@ -154,7 +154,7 @@
<a class="{{if eq .SortType "downloadtimes"}}active{{end}} item"
href="{{$.Link}}?sort=downloadtimes&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{$.License}}&recommend={{$.Recommend}}">{{.i18n.Tr "repo.issues.filter_sort.downloadtimes"}}</a>
<a class="{{if eq .SortType "moststars"}}active{{end}} item"
href="{{$.Link}}?sort=moststars&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{$.License}}&recommend={{$.Recommend}}">{{.i18n.Tr "repo.issues.filter_sort.moststars"}}</a>
href="{{$.Link}}?sort=moststars&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{$.License}}&recommend={{$.Recommend}}">{{.i18n.Tr "dataset.collection_num"}}</a>
<a class="{{if eq .SortType "mostusecount"}}active{{end}} item"
href="{{$.Link}}?sort=mostusecount&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{$.License}}&recommend={{$.Recommend}}">{{.i18n.Tr "repo.issues.filter_sort.mostusecount"}}</a>
</div>


+ 1
- 1
templates/repo/cloudbrain/benchmark/show.tmpl View File

@@ -474,7 +474,7 @@

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-mirror">
{{$.datasetname}}
{{.DatasetName}}
</div>
</td>
</tr>


+ 5
- 5
templates/repo/cloudbrain/new.tmpl View File

@@ -104,6 +104,7 @@
top: 14px;
z-index: 2; */
}

</style>

<div id="mask">
@@ -119,8 +120,8 @@
<div class="repository">
{{template "repo/header" .}}
<div class="repository new repo ui middle very relaxed page grid">

<div class="column">
<div class="cloudbrain-type" style="display: none;" data-cloudbrain-type="{{.datasetType}}" data-repo-link="{{.RepoLink}}"></div>
{{template "base/alert" .}}
<div class="ui negative message" id="messageInfo">
<p></p>
@@ -218,8 +219,10 @@
<div id="images-new-cb">

</div>
<div id="select-multi-dataset">

{{template "custom/select_dataset" .}}
</div>
<div class="inline required field">
<label>{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="cloudbrain_resource_spec" class="ui search dropdown"
@@ -278,8 +281,6 @@
</div>
</div>
</form>


</div>
</div>
</div>
@@ -373,5 +374,4 @@
$('#store_category').attr("value", selected_value)
})


</script>

+ 1
- 1
templates/repo/cloudbrain/show.tmpl View File

@@ -409,7 +409,7 @@
<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-BenchmarkTypeName">
{{$.datasetname}}
{{.DatasetName}}
</div>
</td>
</tr>


+ 50
- 52
templates/repo/cloudbrain/trainjob/new.tmpl View File

@@ -1,20 +1,14 @@
{{template "base/head" .}}
<style>
.unite {
.train-job-title {
font-family: SourceHanSansSC-medium !important;
color: rgba(16, 16, 16, 100) !important;
}

.title {
font-size: 16px !important;
padding-left: 3rem !important;
}

.min_title {
.min_title{
font-size: 14px !important;
padding-left: 6rem !important;
margin-bottom: 2rem !important;

}

.width {
@@ -33,9 +27,10 @@

.width85 {
width: 85% !important;
margin-left: 4.5rem !important;
margin-left: 10.5rem !important;
align-items: center;
}
.width81 {
margin-left: 1.5rem !important;
width: 81% !important;
@@ -60,6 +55,14 @@
text-align: center;
color: #C2C7CC;
}
.label-fix-width{
width: 140px !important;
text-align: right;
font-family: SourceHanSansSC-medium !important;
color: rgba(16, 16, 16, 100) !important;
font-size: 14px !important;
}

</style>
<!-- <div class="ui page dimmer">
<div class="ui text loader">{{.i18n.Tr "loading"}}</div>
@@ -76,6 +79,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>
{{template "base/alert" .}}
<h4 class="ui top attached header">
{{.i18n.Tr "repo.modelarts.train_job.new"}}
@@ -87,22 +91,22 @@
<input type="hidden" name="action" value="update">
<input type="hidden" id="ai_engine_name" name="engine_names" value="">
<input type="hidden" id="ai_flaver_name" name="flaver_names" value="">
<h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4>
<h4 class="train-job-title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4>
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_cluster"}}</label>
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_cluster"}}</label>
<div class="ui blue mini menu compact selectcloudbrain">
<a class="active item" href="{{.RepoLink}}/cloudbrain/train-job/create">
<svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg>
{{.i18n.Tr "cloudbrain.resource_cluster_openi"}}
</a>
<a class="item" href="{{.RepoLink}}/grampus/train-job/npu/create">
<svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg>
{{.i18n.Tr "cloudbrain.resource_cluster_c2net"}}(Beta)
<svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg>
{{.i18n.Tr "cloudbrain.resource_cluster_c2net"}}(Beta)
</a>
</div>
</div>
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label>
<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label>
<div class="ui blue mini menu compact selectcloudbrain">
<a class="active item" href="{{.RepoLink}}/cloudbrain/train-job/create">
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16"
@@ -123,18 +127,18 @@
Ascend NPU</a>
</div>
</div>
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label>
<div class="required min_title inline field">
<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="64">
<span class="tooltips" style="display: block;">{{.i18n.Tr "cloudbrain.job_name_rule"}}</span>
<span class="tooltips" style="display: block;margin-left: 11.5rem;">{{.i18n.Tr "cloudbrain.job_name_rule"}}</span>
</div>

<div class="unite min_title inline field">
<label style="font-weight: normal;"
for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}}&nbsp;&nbsp;</label>
<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>
<textarea style="width: 80%;" id="description" name="description" rows="3" maxlength="255"
placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}}
onchange="this.value=this.value.substring(0, 255)"
@@ -143,11 +147,11 @@
</div>
<div class="ui divider"></div>

<h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.parameter_setting"}}:</h4>
<h4 class="train-job-title ui header ">{{.i18n.Tr "repo.modelarts.train_job.parameter_setting"}}:</h4>


<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.code_version"}}</label>
<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.code_version"}}</label>
<select class="ui dropdown width80 left2" id="code_version" name="branch_name">
{{if .branch_name}}
<option name="branch_name" value="{{.branch_name}}">{{.branch_name}}</option>
@@ -175,8 +179,8 @@
</select>
</div>

<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.gpu_type"}}</label>
<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" placeholder="选择GPU类型"
style='width:385px' name="gpu_type">
{{range .train_gpu_types}}
@@ -184,27 +188,12 @@
{{end}}
</select>
</div>

<!-- <div class="required unite min_title inline field" style="position: relative;">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.mirror"}}&nbsp;</label>
<input class="width81" type="text" list="cloudbrain_image" placeholder="{{.i18n.Tr "cloudbrain.choose_mirror"}}" name="image" required autofocus maxlength="255">
<i class="times circle outline icon icons" style="visibility: hidden;" onclick="clearValue()"></i>
<datalist class="ui search" id="cloudbrain_image" name="image">
{{range .images}}
<option name="image" value="{{.Place}}">{{.PlaceView}}</option>
{{end}}
{{range .public_images}}
<option name="image" value="{{.Place}}">{{.PlaceView}}</option>
{{end}}
</datalist>
</div> -->

<div id="images-new-cb">

</div>

<div class="inline unite min_title field required">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label>
<div class="inline field min_title required">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label>
{{if .bootFile}}
<input style="width: 48.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}"
tabindex="3" autofocus required maxlength="255">
@@ -219,13 +208,17 @@
</span>
<a href="https://git.openi.org.cn/OpenIOSSG/MNIST_PytorchExample_GPU" target="_blank">查看样例</a>
</div>
<div id="select-multi-dataset">

</div>


{{template "custom/select_dataset_train" .}}
<!-- {{template "custom/select_dataset_train" .}} -->
<span class="tooltips"
style="margin-left: 11.5rem;margin-bottom: 2rem;">训练脚本存储在/code中,数据集存储在/dataset中,训练输出请存储在/model中以供后续下载。</span>
<div class="inline unite min_title field">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label>
style="margin-left: 11.5rem;margin-bottom: 1rem;">训练脚本存储在/code中,数据集存储在/dataset中,训练输出请存储在/model中以供后续下载。</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>
@@ -252,8 +245,8 @@
</div>
</div>

<div class="required inline unite min_title field">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<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">
{{range .train_resource_specs}}
@@ -263,7 +256,8 @@
</select>
</div>

<div class="inline unite min_title field">
<div class="inline field" style="padding: 1rem 0;">
<label class="label-fix-width"></label>
<button class="ui create_train_job green button">
{{.i18n.Tr "repo.cloudbrain.new"}}
</button>
@@ -287,7 +281,11 @@

$('.menu .item')
.tab();

$(document).keydown(function(event){
switch(event.keyCode){
case 13:return false;
}
});
let sever_num = $('#trainjob_work_server_num')
$('.add').click(function () {
sever_num.val(parseInt(sever_num.val()) + 1)


+ 38
- 36
templates/repo/grampus/trainjob/gpu/new.tmpl View File

@@ -1,20 +1,15 @@
{{template "base/head" .}}
<style>

.unite{
.train-job-title {
font-family: SourceHanSansSC-medium !important;
color: rgba(16, 16, 16, 100) !important;
}

.title{
font-size: 16px !important;
padding-left: 3rem !important;
}
.min_title{
font-size: 14px !important;
padding-left: 6rem !important;
margin-bottom: 2rem !important;

}
.width{
width:100% !important;
@@ -29,10 +24,10 @@
}
.width85{
width: 85% !important;
margin-left: 4.5rem !important;
margin-left: 10.5rem !important;
align-items: center;
}
.width81{
margin-left: 1.5rem !important;
width: 81% !important;
}

@@ -53,7 +48,13 @@
text-align: center;
color: #C2C7CC;
}

.label-fix-width{
width: 140px !important;
text-align: right;
font-family: SourceHanSansSC-medium !important;
color: rgba(16, 16, 16, 100) !important;
font-size: 14px !important;
}
</style>
<!-- <div class="ui page dimmer">
<div class="ui text loader">{{.i18n.Tr "loading"}}</div>
@@ -81,31 +82,31 @@
<input type="hidden" name="action" value="update">
<input type="hidden" id="ai_engine_name" name="engine_names" value="">
<input type="hidden" id="ai_flavor_name" name="flavor_name" value="">
<h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4>
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_cluster"}}</label>
<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>
<div class="ui blue mini menu compact selectcloudbrain">
<a class="item" href="{{.RepoLink}}/cloudbrain/train-job/create">
<svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg>
{{.i18n.Tr "cloudbrain.resource_cluster_openi"}}
</a>
<a class="active item" href="{{.RepoLink}}/grampus/train-job/npu/create">
<svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg>
{{.i18n.Tr "cloudbrain.resource_cluster_c2net"}}
</a>
<a class="active item" href="{{.RepoLink}}/grampus/train-job/{{if.NPUEnabled}}npu{{else}}gpu{{end}}/create">
<svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg>
{{.i18n.Tr "cloudbrain.resource_cluster_c2net"}}(Beta)
</a>
</div>
</div>
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label>
<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label>
<div class="ui blue mini menu compact selectcloudbrain">
<a class="active item" href="{{.RepoLink}}/grampus/train-job/gpu/create">
<a {{if.GPUEnabled}}class="active item" href="{{.RepoLink}}/grampus/train-job/gpu/create"{{else}}href="javascript:return false;" class="item disabled" {{end}}>
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16">
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/>
</svg>
CPU/GPU
</a>
<a class="item" href="{{.RepoLink}}/grampus/train-job/npu/create">
<a {{if.NPUEnabled}}class="item" href="{{.RepoLink}}/grampus/train-job/npu/create"{{else}}href="javascript:return false;" class="item disabled" {{end}} >
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16">
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/>
@@ -113,23 +114,23 @@
Ascend NPU</a>
</div>
</div>
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label>
<div class="required min_title inline field">
<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="64">
<span class="tooltips" style="display: block;">{{.i18n.Tr "cloudbrain.job_name_rule"}}</span>
<span class="tooltips" style="margin-left: 11.5rem;display: block;">{{.i18n.Tr "cloudbrain.job_name_rule"}}</span>
</div>
<div class="unite min_title inline field">
<label style="font-weight: normal;" for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}}&nbsp;&nbsp;</label>
<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>
<textarea style="width: 80%;" id="description" name="description" rows="3" maxlength="255" placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}} onchange="this.value=this.value.substring(0, 255)" onkeydown="this.value=this.value.substring(0, 255)" onkeyup="this.value=this.value.substring(0, 255)"></textarea>
</div>
<div class="ui divider"></div>

<h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.parameter_setting"}}:</h4>
<h4 class="train-job-title ui header ">{{.i18n.Tr "repo.modelarts.train_job.parameter_setting"}}:</h4>

<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.code_version"}}</label>
<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.code_version"}}</label>
<select class="ui dropdown width80 left2" id="code_version" name="branch_name">
{{if .branch_name}}
<option name="branch_name" value="{{.branch_name}}">{{.branch_name}}</option>
@@ -152,8 +153,8 @@
<div id="images-new-grampus">
</div>

<div class="inline unite min_title field required">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label>
<div class="inline min_title field required">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label>
{{if .bootFile}}
<input style="width: 48.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}" tabindex="3" autofocus required maxlength="255" >
{{else}}
@@ -167,9 +168,9 @@

{{template "custom/select_dataset_train" .}}
<span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 2rem;">{{.i18n.Tr "repo.grampus.dataset_path_rule"}}</span>
<div class="inline unite min_title field">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label>
<span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 2rem;">{{.i18n.Tr "repo.grampus.gpu_dataset_path_rule"}}</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;">
@@ -194,8 +195,8 @@
</div>
</div>

<div class="required unite min_title inline field" id="flavor_name">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label>
<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">
{{range .flavor_infos}}
<option name="flavor" value="{{.ID}}">{{.Name}}</option>
@@ -203,7 +204,8 @@
</select>
</div>
<div class="inline unite min_title field">
<div class="inline min_title field">
<label class="label-fix-width"></label>
<button class="ui create_train_job green button">
{{.i18n.Tr "repo.cloudbrain.new"}}
</button>


+ 39
- 38
templates/repo/grampus/trainjob/npu/new.tmpl View File

@@ -1,20 +1,14 @@
{{template "base/head" .}}
<style>

.unite{
.train-job-title {
font-family: SourceHanSansSC-medium !important;
color: rgba(16, 16, 16, 100) !important;
}

.title{
font-size: 16px !important;
padding-left: 3rem !important;
}
.min_title{
font-size: 14px !important;
padding-left: 6rem !important;
margin-bottom: 2rem !important;

}
.width{
width:100% !important;
@@ -25,10 +19,10 @@
}
.width85{
width: 85% !important;
margin-left: 4.5rem !important;
margin-left: 10.5rem !important;
align-items: center;
}
.width81{
margin-left: 1.5rem;
width: 81% !important;
}

@@ -49,7 +43,13 @@
text-align: center;
color: #C2C7CC;
}

.label-fix-width{
width: 140px !important;
text-align: right;
font-family: SourceHanSansSC-medium !important;
color: rgba(16, 16, 16, 100) !important;
font-size: 14px !important;
}
</style>
<!-- <div class="ui page dimmer">
<div class="ui text loader">{{.i18n.Tr "loading"}}</div>
@@ -77,31 +77,31 @@
<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="">
<h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4>
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_cluster"}}</label>
<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>
<div class="ui blue mini menu compact selectcloudbrain">
<a class="item" href="{{.RepoLink}}/cloudbrain/train-job/create">
<svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg>
{{.i18n.Tr "cloudbrain.resource_cluster_openi"}}
</a>
<a class="active item" href="{{.RepoLink}}/grampus/train-job/npu/create">
<svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg>
{{.i18n.Tr "cloudbrain.resource_cluster_c2net"}}(Beta)
<a class="active item" href="{{.RepoLink}}/grampus/train-job/{{if.NPUEnabled}}npu{{else}}gpu{{end}}/create">
<svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg>
{{.i18n.Tr "cloudbrain.resource_cluster_c2net"}}(Beta)
</a>
</div>
</div>
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label>
<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label>
<div class="ui blue mini menu compact selectcloudbrain">
<!--a class="item" href="{{.RepoLink}}/grampus/train-job/gpu/create" type="hidden">
<a {{if.GPUEnabled}}class="item" href="{{.RepoLink}}/grampus/train-job/gpu/create"{{else}}href="javascript:return false;" class="item disabled" {{end}}>
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16">
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/>
</svg>
CPU/GPU
</a-->
<a class="active item" href="{{.RepoLink}}/grampus/train-job/npu/create">
</a>
<a {{if.NPUEnabled}}class="active item" href="{{.RepoLink}}/grampus/train-job/npu/create"{{else}}href="javascript:return false;" class="item disabled" {{end}} >
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16">
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/>
@@ -109,23 +109,23 @@
Ascend NPU</a>
</div>
</div>
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label>
<div class="required min_title inline field">
<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="64">
<span class="tooltips" style="display: block;">{{.i18n.Tr "cloudbrain.job_name_rule"}}</span>
</div>

<div class="unite min_title inline field">
<label style="font-weight: normal;" for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}}&nbsp;&nbsp;</label>
<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>
<textarea style="width: 80%;" id="description" name="description" rows="3" maxlength="255" placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}} onchange="this.value=this.value.substring(0, 255)" onkeydown="this.value=this.value.substring(0, 255)" onkeyup="this.value=this.value.substring(0, 255)"></textarea>
</div>
<div class="ui divider"></div>

<h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.parameter_setting"}}:</h4>
<h4 class="train-job-title title ui header ">{{.i18n.Tr "repo.modelarts.train_job.parameter_setting"}}:</h4>


<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.code_version"}}</label>
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.code_version"}}</label>
<select class="ui dropdown width80 left2" id="code_version" name="branch_name">
{{if .branch_name}}
<option name="branch_name" value="{{.branch_name}}">{{.branch_name}}</option>
@@ -145,8 +145,8 @@
</select>
</div>

<div class="required unite min_title inline field" id="engine_name">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.mirror"}}</label>
<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">
{{range .images}}
<option name="image_id" value="{{.ID}}">{{.Name}}</option>
@@ -154,8 +154,8 @@
</select>
</div>

<div class="inline unite min_title field required">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label>
<div class="inline min_title field required">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label>
{{if .bootFile}}
<input style="width: 48.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}" tabindex="3" autofocus required maxlength="255" >
{{else}}
@@ -169,24 +169,24 @@
{{template "custom/select_dataset_train" .}}
<span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 2rem;">{{.i18n.Tr "repo.grampus.dataset_path_rule"}}</span>
<div class="inline unite min_title field">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label>
<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;">
</div>
</div>

<div class="required unite min_title inline field" id="flavor_name">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label>
<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">
{{range .flavor_infos}}
<option name="flavor" value="{{.ID}}">{{.Name}}</option>
{{end}}
</select>
</div>
<div class="inline required unite min_title field">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</label>
<div class="inline required min_title field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</label>

<div class="ui labeled input" style="width: 5%;">

@@ -200,7 +200,8 @@
</div>
</div>

<div class="inline unite min_title field">
<div class="inline min_title field">
<label class="label-fix-width"></label>
<button class="ui create_train_job green button">
{{.i18n.Tr "repo.cloudbrain.new"}}
</button>


+ 4
- 1
templates/repo/modelarts/notebook/new.tmpl View File

@@ -18,6 +18,7 @@
{{template "repo/header" .}}
<div class="repository new repo ui middle very relaxed page grid">
<div class="column">
<div class="cloudbrain-type" style="display: none;" data-cloudbrain-type="{{.datasetType}}" data-repo-link="{{.RepoLink}}"></div>
{{template "base/alert" .}}
<div class="ui negative message" id="messageInfo">
<p></p>
@@ -59,7 +60,9 @@
{{end}}
</select>
</div>
{{template "custom/select_dataset" .}}
<div id="select-multi-dataset">

</div>

<!--<div class="inline required field">
<label>工作环境</label>


+ 32
- 44
templates/repo/modelarts/notebook/show.tmpl View File

@@ -69,7 +69,6 @@
}

.tab_2_content {
min-height: 460px;
margin-left: 10px;
}

@@ -338,30 +337,6 @@
</div>
</td>
</tr>

<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-duration">
{{$.duration}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.datasetdownload"}}
</td>

<td class="ti-text-form-content">
<div class="text-span-new" id="model_description">
{{$.datasetDownloadLink}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "cloudbrain.description"}}
@@ -392,24 +367,6 @@
</div>
</td>
</tr>



<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.dataset"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-BenchmarkTypeName">
{{.DatasetName}}
</div>
</td>
</tr>



<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.standard"}}
@@ -456,6 +413,18 @@
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-duration">
{{$.duration}}
</div>
</td>
</tr>


</tbody>
@@ -463,8 +432,26 @@
</div>
</div>

</div>

<div style="clear:both">
<table style="border:none" class="ui fixed small stackable table">
<thead>
<tr><th style="color: #8a8e99;font-size:12px" class="three wide center aligned">数据集文件</th>
<th style="color: #8a8e99;font-size:12px"class="eleven wide">数据集下载地址</th>
<th style="color: #8a8e99;font-size:12px" class="two wide center aligned">操作</th>
</tr></thead>
<tbody>
{{range $.datasetDownload}}
<tr>
<td style="word-wrap: break-word;word-break: break-all;"><a href="{{.RepositoryLink}}">{{.DatasetName}}</a></td>
<td style="word-wrap: break-word;word-break: break-all;">{{.DatasetDownloadLink}}</td>
<td class="center aligned"><a class="ui poping up clipboard" id="clipboard-btn" data-original="{{$.i18n.Tr "repo.copy_link"}}" data-success="{{$.i18n.Tr "repo.copy_link_success"}}" data-error="{{$.i18n.Tr "repo.copy_link_error"}}" data-content="{{$.i18n.Tr "repo.copy_link"}}" data-variation="inverted tiny" data-clipboard-text="{{.DatasetDownloadLink}}">复制链接</a></td>
</tr>
{{end}}
</tbody>
</table>
</div>
</div>
</div>

@@ -509,4 +496,5 @@
$(document).ready(function () {
$('.secondary.menu .item').tab();
});
console.log({{$.datasetDownload}})
</script>

+ 123
- 135
templates/repo/modelarts/trainjob/new.tmpl View File

@@ -1,59 +1,58 @@
{{template "base/head" .}}
<style>
.unite {
.train-job-title {
font-family: SourceHanSansSC-medium !important;
color: rgba(16, 16, 16, 100) !important;
font-size: 16px !important;
padding-left: 3rem !important;
}
.min_title{
font-size: 14px !important;
margin-bottom: 2rem !important;
}
.width{
width:100% !important;
}
.width48{
width: 48.5% !important;
}
.width80{
width: 80.7% !important;
margin-left: 10px;
}
.width85{
width: 85% !important;
margin-left: 10.5rem !important;
align-items: center;
}
.width81{
margin-left: 1.5rem;
width: 81% !important;
}

.add{font-size: 18px;
padding: 0.5rem;
border: 1px solid rgba(187, 187, 187, 100);
border-radius: 0px 5px 5px 0px;
line-height: 21px;
text-align: center;
color: #C2C7CC;
}
.min{
font-size: 18px;
padding: 0.5rem;
border: 1px solid rgba(187, 187, 187, 100);
border-radius: 5px 0px 0px 5px;
line-height: 21px;
text-align: center;
color: #C2C7CC;
}
.label-fix-width{
width: 140px !important;
text-align: right;
font-family: SourceHanSansSC-medium !important;
color: rgba(16, 16, 16, 100) !important;
}

.title {
font-size: 16px !important;
padding-left: 3rem !important;
}

.min_title {
font-size: 14px !important;
padding-left: 6rem !important;
margin-bottom: 2rem !important;

}

.width {
width: 100% !important;
}

.width80 {
width: 80.7% !important;
margin-left: 10px;
}

.width85 {
width: 85% !important;
margin-left: 4.5rem !important;
}

.width81 {
margin-left: 1.5rem;
width: 81% !important;
}

.add {
font-size: 18px;
padding: 0.5rem;
border: 1px solid rgba(187, 187, 187, 100);
border-radius: 0px 5px 5px 0px;
line-height: 21px;
text-align: center;
color: #C2C7CC;
}

.min {
font-size: 18px;
padding: 0.5rem;
border: 1px solid rgba(187, 187, 187, 100);
border-radius: 5px 0px 0px 5px;
line-height: 21px;
text-align: center;
color: #C2C7CC;
}
</style>
<!-- <div class="ui page dimmer">
@@ -71,6 +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}}"></div>
{{template "base/alert" .}}
<h4 class="ui top attached header">
{{.i18n.Tr "repo.modelarts.train_job.new"}}
@@ -82,9 +82,9 @@
<input type="hidden" name="action" value="update">
<input type="hidden" id="ai_engine_name" name="engine_names" value="">
<input type="hidden" id="ai_flaver_name" name="flaver_names" value="">
<h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4>
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_cluster"}}</label>
<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>
<div class="ui blue mini menu compact selectcloudbrain">
<a class="active item" href="{{.RepoLink}}/cloudbrain/train-job/create">
<svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg>
@@ -96,8 +96,8 @@
</a>
</div>
</div>
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label>
<div class="required inline min_title field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label>
<div class="ui blue mini menu compact selectcloudbrain">
<a class="item" href="{{.RepoLink}}/cloudbrain/train-job/create">
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16"
@@ -118,55 +118,46 @@
Ascend NPU</a>
</div>
</div>
<div class="required unite min_title inline field">
<label 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="64">
<span class="tooltips" style="display: block;">{{.i18n.Tr "cloudbrain.job_name_rule"}}</span>
<div class="required inline min_title field">
<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="64">
<span class="tooltips" style="margin-left:11.5rem;display: block;">{{.i18n.Tr "cloudbrain.job_name_rule"}}</span>
</div>

<div class="unite min_title inline field">
<label style="font-weight: normal;"
for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}}&nbsp;&nbsp;</label>
<textarea style="width: 80%;" id="description" name="description" rows="3" maxlength="255"
placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}}
onchange="this.value=this.value.substring(0, 255)"
onkeydown="this.value=this.value.substring(0, 255)"
onkeyup="this.value=this.value.substring(0, 255)"></textarea>
<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>
<textarea style="width: 80%;" id="description" name="description" rows="3" maxlength="255" placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}} onchange="this.value=this.value.substring(0, 255)" onkeydown="this.value=this.value.substring(0, 255)" onkeyup="this.value=this.value.substring(0, 255)"></textarea>
</div>
<div class="ui divider"></div>

<h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.parameter_setting"}}:</h4>
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.code_version"}}</label>
<select class="ui dropdown width80 left2" id="code_version" name="branch_name">
{{if .branch_name}}
<option name="branch_name" value="{{.branch_name}}">{{.branch_name}}</option>
{{range $k, $v :=.Branches}}
{{ if ne $v $.branch_name }}
<option name="branch_name" value="{{$v}}">{{$v}}</option>
{{end}}
{{end}}
{{else}}
<option name="branch_name" value="{{.branchName}}">{{.branchName}}</option>
{{range $k, $v :=.Branches}}
{{ if ne $v $.branchName }}
<option name="branch_name" value="{{$v}}">{{$v}}</option>
{{end}}
{{end}}
{{end}}
</select>
<h4 class="train-job-title ui header ">{{.i18n.Tr "repo.modelarts.train_job.parameter_setting"}}:</h4>

<div class="required inline min_title field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.code_version"}}</label>
<select class="ui dropdown width80 left2" id="code_version" name="branch_name">
{{if .branch_name}}
<option name="branch_name" value="{{.branch_name}}">{{.branch_name}}</option>
{{range $k, $v :=.Branches}}
{{ if ne $v $.branch_name }}
<option name="branch_name" value="{{$v}}">{{$v}}</option>
{{end}}
{{end}}
{{else}}
<option name="branch_name" value="{{.branchName}}">{{.branchName}}</option>
{{range $k, $v :=.Branches}}
{{ if ne $v $.branchName }}
<option name="branch_name" value="{{$v}}">{{$v}}</option>
{{end}}
{{end}}
{{end}}
</select>
</div>



<div class="required unite min_title inline fields" style="width: 90%;">
<label
style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.AI_driver"}}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</label>
<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>
<div class="field" style="flex: 1.5;">
<select class="ui dropdown width" id="trainjob_engines">
{{range .engines}}
@@ -176,44 +167,37 @@
</div>

<div class="field" style="flex: 2;" id="engine_name">
<select class="ui dropdown width" id="trainjob_engine_versions" style='width: 100%;'
name="engine_id">
{{range .engine_versions}}
<option name="engine_id" value="{{.ID}}">{{.Value}}</option>
{{end}}
<select class="ui dropdown width" id="trainjob_engine_versions" name="engine_id">
{{range .engine_versions}}
<option name="engine_id" value="{{.ID}}">{{.Value}}</option>
{{end}}
</select>

</div>

</div>

<div class="inline unite min_title field required">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label>
{{if .bootFile}}
<input style="width: 48.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}"
tabindex="3" autofocus required maxlength="255">
{{else}}
<input style="width: 48.5%;" name="boot_file" id="trainjob_boot_file" value="" tabindex="3"
autofocus required maxlength="255">
{{end}}
<span>
<i class="question circle icon link"
data-content={{.i18n.Tr "repo.modelarts.train_job.boot_file_helper"}}
data-position="right center" data-variation="mini"></i>
</span>
<a href="https://git.openi.org.cn/OpenIOSSG/MINIST_Example"
target="_blank">{{.i18n.Tr "cloudbrain.view_sample"}}</a>
<div class="inline field min_title required">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label>
{{if .bootFile}}
<input style="width: 48.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}" tabindex="3" autofocus required maxlength="255" >
{{else}}
<input style="width: 48.5%;" name="boot_file" id="trainjob_boot_file" value="" tabindex="3" autofocus required maxlength="255" >
{{end}}
<span>
<i class="question circle icon link" data-content={{.i18n.Tr "repo.modelarts.train_job.boot_file_helper"}} data-position="right center" data-variation="mini"></i>
</span>
<a href="https://git.openi.org.cn/OpenIOSSG/MINIST_Example" target="_blank">{{.i18n.Tr "cloudbrain.view_sample"}}</a>
</div>
<div id="select-multi-dataset">

{{template "custom/select_dataset_train" .}}
<span class="tooltips"
style="margin-left: 11.5rem;margin-bottom: 2rem;">{{.i18n.Tr "cloudbrain.dataset_path_rule"}}</span>
<div class="inline unite min_title field">
<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>
<span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 1rem;">{{.i18n.Tr "cloudbrain.dataset_path_rule"}}</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;">
{{if ne 0 (len .params)}}
{{range $k ,$v := .params}}
@@ -235,7 +219,7 @@
</div>


<div class="required field " style="display: none;">
<div class="required min_title field " style="display: none;">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.resource_pool"}}</label>
<select class="ui dropdown" id="trainjob_resource_pool" style='width:385px' name="pool_id">
{{range .resource_pools}}
@@ -261,17 +245,16 @@
</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">
<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">
{{range .flavor_infos}}
<option name="flavor" value="{{.Code}}">{{.Value}}</option>
{{end}}
</select>
</div>
<div class="inline required unite min_title field">
<label
style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</label>
<div class="inline required min_title field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</label>

<div class="ui labeled input" style="width: 5%;">

@@ -287,7 +270,8 @@
</div>
</div>

<div class="inline unite min_title field">
<div class="inline field" style="padding: 1rem 0;">
<label class="label-fix-width"></label>
<button class="ui create_train_job green button">
{{.i18n.Tr "repo.cloudbrain.new"}}
</button>
@@ -310,7 +294,11 @@

$('.menu .item')
.tab();

$(document).keydown(function(event){
switch(event.keyCode){
case 13:return false;
}
});
// let sever_num = $("#trainjob_work_server_num_select .text").text() //$('#trainjob_work_server_num')
// console.log("sever_num:",sever_num)
// $('.add').click(function(){


+ 1155
- 0
web_src/js/components/dataset/selectDataset.vue
File diff suppressed because it is too large
View File


+ 283
- 207
web_src/js/components/images/selectGrampusImages.vue View File

@@ -1,216 +1,292 @@
<template>

<div class="inline required field" :class="{ 'unite': benchmarkNew, 'min_title': benchmarkNew}">
<label v-if="benchmarkNew" style="font-weight: normal;">镜像</label>
<label v-else>镜像</label>
<span v-if="benchmarkNew">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<input v-if="benchmarkNew" type="text" name="image" :value="imageAddress" style="width: 48.5%;"
placeholder="选择镜像或输入镜像地址">
<input v-else type="text" name="image" :value="imageAddress" placeholder="选择镜像或输入镜像地址">
<el-button type="text" @click="dialogVisible = true" icon="el-icon-plus" style="color: #0366d6;">选择镜像
</el-button>
<el-dialog title="选择镜像" :visible.sync="dialogVisible" width="50%">
<div class="ui icon input" style="z-index: 9999;position: absolute;right: 50px;height:30px;">
<i class="search icon" style="cursor: pointer;pointer-events:auto"></i>
<input type="text" placeholder="搜镜像Tag/描述/标签..." v-model="search">
<div
class="inline required field"
:class="{ unite: benchmarkNew, min_title: benchmarkNew }"
>
<label
v-if="benchmarkNew"
class="label-fix-width"
style="font-weight: normal"
>镜像</label
>
<label v-else>镜像</label>
<input
v-if="benchmarkNew"
type="text"
name="image"
:value="imageAddress"
style="width: 48.5%"
placeholder="选择镜像或输入镜像地址"
/>
<input
v-else
type="text"
name="image"
:value="imageAddress"
placeholder="选择镜像或输入镜像地址"
/>
<el-button
type="text"
@click="dialogVisible = true"
icon="el-icon-plus"
style="color: #0366d6"
>选择镜像
</el-button>
<el-dialog title="选择镜像" :visible.sync="dialogVisible" width="50%">
<div
class="ui icon input"
style="z-index: 9999; position: absolute; right: 50px; height: 30px"
>
<i
class="search icon"
style="cursor: pointer; pointer-events: auto"
></i>
<input
type="text"
placeholder="搜镜像Tag/描述/标签..."
v-model="search"
/>
</div>
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="公开镜像" name="first" v-loading="loadingPublic">
<div
style="
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem 0;
border-bottom: 1px solid #f5f5f5;
"
v-for="(publicData, index) in tableDataPublic"
:key="index"
>
<div style="width: 90%">
<div
style="
display: flex;
align-items: center;
justify-content: space-between;
"
>
<div style="display: flex; align-items: center">
<span
class="panel_dataset_name text-over"
style="margin-left: 0"
>{{ publicData.tag }}
</span>
<img
v-if="publicData.type == 5"
src="/img/jian.svg"
style="margin-left: 0.5rem"
/>
</div>

<div v-if="!!publicData.topics" class="text-over">
<span
v-for="(topic, index) in publicData.topics"
class="ui repo-topic label topic"
>{{ topic }}</span
>
</div>
</div>
<div style="margin-top: 8px; display: flex">
<a
v-if="publicData.relAvatarLink || publicData.userName"
:title="publicData.userName"
style="cursor: default"
>
<img
class="ui avatar mini image"
style="width: 20px; height: 20px"
:src="publicData.relAvatarLink"
/>
</a>
<a v-else
><img
class="ui avatar mini image"
title="Ghost"
src="/user/avatar/ghost/-1"
style="width: 20px; height: 20px"
/></a>
<span class="panel_datset_desc">{{
publicData.description
}}</span>
</div>
</div>
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="公开镜像" name="first" v-loading="loadingPublic">
<div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5"
v-for="(publicData,index) in tableDataPublic" :key="index">
<div style="width: 90%;">
<div style="display: flex;align-items: center;justify-content: space-between;">
<div style="display: flex;align-items: center;">
<span class="panel_dataset_name text-over"
style="margin-left: 0;">{{publicData.tag}} </span>
<img v-if="publicData.type==5" src="/img/jian.svg" style="margin-left: 0.5rem;">
</div>

<div v-if="!!publicData.topics" class="text-over">
<span v-for="(topic,index) in publicData.topics"
class="ui repo-topic label topic">{{topic}}</span>
</div>
</div>
<div style="margin-top: 8px;display: flex;">
<a v-if="publicData.relAvatarLink||publicData.userName" :title="publicData.userName"
style="cursor: default;">
<img class="ui avatar mini image" style="width: 20px;height: 20px;"
:src="publicData.relAvatarLink">
</a>
<a v-else><img class="ui avatar mini image" title="Ghost" src="/user/avatar/ghost/-1"
style="width: 20px;height: 20px;"></a>
<span class="panel_datset_desc">{{publicData.description}}</span>
</div>
</div>
<div>
<button class="ui primary basic button mini"
@click.stop.prevent="selectImages(publicData.place,publicData.tag)">使用</button>
</div>
</div>
<div class="ui container" style="margin-top:50px;text-align:center">
<el-pagination background @current-change="handleCurrentChangePublic"
:current-page="currentPagePublic" :page-size="pageSizePublic"
layout="total, prev, pager, next" :total="totalNumPublic">
</el-pagination>
</div>
</el-tab-pane>
</el-tabs>
</el-dialog>
</div>



<div>
<button
class="ui primary basic button mini"
@click.stop.prevent="
selectImages(publicData.place, publicData.tag)
"
>
使用
</button>
</div>
</div>
<div
class="ui container"
style="margin-top: 50px; text-align: center"
>
<el-pagination
background
@current-change="handleCurrentChangePublic"
:current-page="currentPagePublic"
:page-size="pageSizePublic"
layout="total, prev, pager, next"
:total="totalNumPublic"
>
</el-pagination>
</div>
</el-tab-pane>
</el-tabs>
</el-dialog>
</div>
</template>

<script>

const { _AppSubUrl, _StaticUrlPrefix, csrf } = window.config;




export default {
components: {

},
data() {
return {
dialogVisible: false,
benchmarkNew: false,
imageAddress: '',
activeName: 'first',
search: '',
checked: false,
currentPagePublic: 1,
pageSizePublic: 5,
totalNumPublic: 0,
paramsPublic: { page: 1, pageSize: 5, q: '', recommend: false,cloudbrainType: 2 },
tableDataPublic: [],
loadingPublic: false,

};
},
methods: {
handleClick(tab, event) {
this.search = ''
if (tab.name == "first") {
this.paramsPublic.q = ''
this.getImageListPublic()
}

},
tableHeaderStyle({ row, column, rowIndex, columnIndex }) {

if (rowIndex === 0) {
return 'background:#f5f5f6;color:#606266'
}

},

handleCurrentChangePublic(val) {
this.paramsPublic.page = val
this.getImageListPublic()

},

getImageListPublic() {
this.loadingPublic = true
this.$axios.get('/explore/images/public', {
params: this.paramsPublic
}).then((res) => {
this.totalNumPublic = res.data.count
this.tableDataPublic = res.data.images
this.loadingPublic = false
})
},

searchName() {
if (this.activeName == 'first') {
this.paramsPublic.q = this.search
this.paramsPublic.page = 1
this.getImageListPublic()
}

},

selectImages(place) {
this.imageAddress = place
this.dialogVisible = false
},

},
watch: {
search(val) {
if (this.activeName == 'first') {
this.paramsPublic.q = val
this.getImageListPublic()
}
}

},
mounted() {
this.getImageListPublic()
if (location.href.indexOf('benchmark') !== -1 || location.href.indexOf('train-job') !== -1) {
this.benchmarkNew = true
}
},
created() {

}

const { _AppSubUrl, _StaticUrlPrefix, csrf } = window.config;

export default {
components: {},
data() {
return {
dialogVisible: false,
benchmarkNew: false,
imageAddress: "",
activeName: "first",
search: "",
checked: false,
currentPagePublic: 1,
pageSizePublic: 5,
totalNumPublic: 0,
paramsPublic: {
page: 1,
pageSize: 5,
q: "",
recommend: false,
cloudbrainType: 2,
},
tableDataPublic: [],
loadingPublic: false,
};
},
methods: {
handleClick(tab, event) {
this.search = "";
if (tab.name == "first") {
this.paramsPublic.q = "";
this.getImageListPublic();
}
},
tableHeaderStyle({ row, column, rowIndex, columnIndex }) {
if (rowIndex === 0) {
return "background:#f5f5f6;color:#606266";
}
},

handleCurrentChangePublic(val) {
this.paramsPublic.page = val;
this.getImageListPublic();
},

getImageListPublic() {
this.loadingPublic = true;
this.$axios
.get("/explore/images/public", {
params: this.paramsPublic,
})
.then((res) => {
this.totalNumPublic = res.data.count;
this.tableDataPublic = res.data.images;
this.loadingPublic = false;
});
},

searchName() {
if (this.activeName == "first") {
this.paramsPublic.q = this.search;
this.paramsPublic.page = 1;
this.getImageListPublic();
}
},

selectImages(place) {
this.imageAddress = place;
this.dialogVisible = false;
},
},
watch: {
search(val) {
if (this.activeName == "first") {
this.paramsPublic.q = val;
this.getImageListPublic();
}
},
},
mounted() {
this.getImageListPublic();
if (
location.href.indexOf("benchmark") !== -1 ||
location.href.indexOf("train-job") !== -1
) {
this.benchmarkNew = true;
}
},
created() {},
};
</script>

<style scoped>
.header-wrapper {
background-color: #f5f5f6;
padding-top: 15px;
}

.image_text {
padding: 25px 0 55px 0;
}

#header {
position: relative;
top: -40px;
}

#success {
background-color: #5bb973;
color: white;
}

.text-over {
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
}

.image_title {
display: inline-block;
width: 80%;
cursor: default;
color: rgb(66, 98, 144);
}

.image_desc {
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
display: -webkit-box;
text-overflow: ellipsis;
overflow: hidden;
}

.heart-stroke {
stroke: #666;
stroke-width: 2;
fill: #fff
}

.stars_active {
fill: #FA8C16 !important;
stroke: #FA8C16 !important
}
</style>
.header-wrapper {
background-color: #f5f5f6;
padding-top: 15px;
}
.image_text {
padding: 25px 0 55px 0;
}
#header {
position: relative;
top: -40px;
}
#success {
background-color: #5bb973;
color: white;
}
.text-over {
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
}
.image_title {
display: inline-block;
width: 80%;
cursor: default;
color: rgb(66, 98, 144);
}
.image_desc {
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
display: -webkit-box;
text-overflow: ellipsis;
overflow: hidden;
}
.heart-stroke {
stroke: #666;
stroke-width: 2;
fill: #fff;
}
.stars_active {
fill: #fa8c16 !important;
stroke: #fa8c16 !important;
}
</style>

+ 560
- 367
web_src/js/components/images/selectImages.vue View File

@@ -1,376 +1,569 @@
<template>

<div class="inline required field" :class="{ 'unite': benchmarkNew, 'min_title': benchmarkNew}">
<label v-if="benchmarkNew" style="font-weight: normal;">镜像</label>
<label v-else>镜像</label>
<span v-if="benchmarkNew">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<input v-if="benchmarkNew" type="text" name="image" :value="imageAddress" style="width: 48.5%;"
placeholder="选择镜像或输入镜像地址" required>
<input v-else type="text" name="image" :value="imageAddress" placeholder="选择镜像或输入镜像地址" required>
<el-button type="text" @click="dialogVisible = true" icon="el-icon-plus" style="color: #0366d6;">选择镜像
</el-button>
<el-dialog title="选择镜像" :visible.sync="dialogVisible" width="50%">
<div class="ui icon input" style="z-index: 9999;position: absolute;right: 50px;height:30px;">
<i class="search icon" style="cursor: pointer;pointer-events:auto"></i>
<input type="text" placeholder="搜镜像Tag/描述/标签..." v-model="search">
<div
class="inline required field"
:class="{ min_title: benchmarkNew, unite: benchmark }"
>
<label
v-if="benchmarkNew"
class="label-fix-width"
style="font-weight: normal"
>镜像</label
>
<label v-else>镜像</label>
<span v-if="benchmark">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<input
v-if="benchmarkNew"
type="text"
name="image"
:value="imageAddress"
style="width: 48.5%"
placeholder="选择镜像或输入镜像地址"
required
/>
<input
v-else
type="text"
name="image"
:value="imageAddress"
placeholder="选择镜像或输入镜像地址"
required
/>
<el-button
type="text"
@click="dialogVisible = true"
icon="el-icon-plus"
style="color: #0366d6"
>选择镜像
</el-button>
<el-dialog title="选择镜像" :visible.sync="dialogVisible" width="50%">
<div
class="ui icon input"
style="z-index: 9999; position: absolute; right: 50px; height: 30px"
>
<i
class="search icon"
style="cursor: pointer; pointer-events: auto"
></i>
<input
type="text"
placeholder="搜镜像Tag/描述/标签..."
v-model="search"
/>
</div>
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="公开镜像" name="first" v-loading="loadingPublic">
<div
style="
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem 0;
border-bottom: 1px solid #f5f5f5;
"
v-for="(publicData, index) in tableDataPublic"
:key="index"
>
<div style="width: 90%">
<div
style="
display: flex;
align-items: center;
justify-content: space-between;
"
>
<div style="display: flex; align-items: center">
<span
class="panel_dataset_name text-over"
style="margin-left: 0"
>{{ publicData.tag }}
</span>
<img
v-if="publicData.type == 5"
src="/img/jian.svg"
style="margin-left: 0.5rem"
/>
</div>

<div v-if="!!publicData.topics" class="text-over">
<span
v-for="(topic, index) in publicData.topics"
class="ui repo-topic label topic"
>{{ topic }}</span
>
</div>
</div>
<div style="margin-top: 8px; display: flex">
<a
v-if="publicData.relAvatarLink || publicData.userName"
:title="publicData.userName"
style="cursor: default"
>
<img
class="ui avatar mini image"
style="width: 20px; height: 20px"
:src="publicData.relAvatarLink"
/>
</a>
<a v-else
><img
class="ui avatar mini image"
title="Ghost"
src="/user/avatar/ghost/-1"
style="width: 20px; height: 20px"
/></a>
<span class="panel_datset_desc">{{
publicData.description
}}</span>
</div>
</div>
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="公开镜像" name="first" v-loading="loadingPublic">
<div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5"
v-for="(publicData,index) in tableDataPublic" :key="index">
<div style="width: 90%;">
<div style="display: flex;align-items: center;justify-content: space-between;">
<div style="display: flex;align-items: center;">
<span class="panel_dataset_name text-over"
style="margin-left: 0;">{{publicData.tag}} </span>
<img v-if="publicData.type==5" src="/img/jian.svg" style="margin-left: 0.5rem;">
</div>

<div v-if="!!publicData.topics" class="text-over">
<span v-for="(topic,index) in publicData.topics"
class="ui repo-topic label topic">{{topic}}</span>
</div>
</div>
<div style="margin-top: 8px;display: flex;">
<a v-if="publicData.relAvatarLink||publicData.userName" :title="publicData.userName"
style="cursor: default;">
<img class="ui avatar mini image" style="width: 20px;height: 20px;"
:src="publicData.relAvatarLink">
</a>
<a v-else><img class="ui avatar mini image" title="Ghost" src="/user/avatar/ghost/-1"
style="width: 20px;height: 20px;"></a>
<span class="panel_datset_desc">{{publicData.description}}</span>
</div>
</div>
<div>
<button class="ui primary basic button mini"
@click.stop.prevent="selectImages(publicData.place,publicData.tag)">使用</button>
</div>
</div>
<div class="ui container" style="margin-top:50px;text-align:center">
<el-pagination background @current-change="handleCurrentChangePublic"
:current-page="currentPagePublic" :page-size="pageSizePublic"
layout="total, prev, pager, next" :total="totalNumPublic">
</el-pagination>
</div>
</el-tab-pane>

<el-tab-pane label="我的镜像" name="second" v-loading="loadingCustom">
<div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5"
v-for="(customData,index) in tableDataCustom" :key="index">
<div style="width: 90%;">
<div style="display: flex;align-items: center;justify-content: space-between;">
<span class="panel_dataset_name text-over" style="margin-left: 0;">{{customData.tag}}
</span>
<div v-if="!!customData.topics" class="text-over">
<span v-for="(topic,index) in customData.topics"
class="ui repo-topic label topic">{{topic}}</span>
</div>
</div>
<div style="margin-top: 8px;display: flex;">
<a v-if="customData.relAvatarLink||customData.userName" :title="customData.userName"
style="cursor: default;">
<img class="ui avatar mini image" style="width: 20px;height: 20px;"
:src="customData.relAvatarLink">
</a>
<a v-else><img class="ui avatar mini image" title="Ghost" src="/user/avatar/ghost/-1"
style="width: 20px;height: 20px;"></a>

<span class="panel_datset_desc">{{customData.description}}</span>
</div>
</div>
<div>
<button v-if="customData.status===1" class="ui primary basic button mini"
@click.stop.prevent="selectImages(customData.place,customData.tag)">使用</button>
<span v-if="customData.status===0" style="display: flex;align-items: center;">
<i class="CREATING"></i>
<span style="margin-left: 0.4em;font-size: 12px;color: #5A5A5A;">提交中</span>
</span>
<span v-if="customData.status===2" style="display: flex;align-items: center;">
<i class="FAILED"></i>
<el-tooltip class="item" effect="dark" content="检测提交镜像是否大小超过20G!" placement="left">
<span style="margin-left: 0.4em;font-size: 12px;color:red;">提交失败</span>
</el-tooltip>

</span>
</div>
</div>
<div class="ui container" style="margin-top:50px;text-align:center">
<el-pagination background @current-change="handleCurrentChangeCustom"
:current-page="currentPageCustom" :page-size="pageSizeCustom"
layout="total, prev, pager, next" :total="totalNumCustom">
</el-pagination>
</div>
</el-tab-pane>

<el-tab-pane label="我收藏的镜像" name="third">
<div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5"
v-for="(starData,index) in tableDataStar" :key="index">
<div style="width: 90%;">
<div style="display: flex;align-items: center;justify-content: space-between;">
<div style="display: flex;align-items: center;">
<span class="panel_dataset_name text-over" style="margin-left: 0;">{{starData.tag}}
</span>
<img v-if="starData.type==5" src="/img/jian.svg" style="margin-left: 0.5rem;">
</div>

<div v-if="!!starData.topics" class="text-over">
<span v-for="(topic,index) in starData.topics"
class="ui repo-topic label topic">{{topic}}</span>
</div>
</div>
<div style="margin-top: 8px;display: flex;">
<a v-if="starData.relAvatarLink||starData.userName" :title="starData.userName"
style="cursor: default;">
<img class="ui avatar mini image" style="width: 20px;height: 20px;"
:src="starData.relAvatarLink">
</a>
<a v-else><img class="ui avatar mini image" title="Ghost" src="/user/avatar/ghost/-1"
style="width: 20px;height: 20px;"></a>
<span class="panel_datset_desc">{{starData.description}}</span>
</div>
</div>
<div>
<button class="ui primary basic button mini"
@click.stop.prevent="selectImages(starData.place,starData.tag)">使用</button>
</div>
</div>
<div class="ui container" style="margin-top:50px;text-align:center">
<el-pagination background @current-change="handleCurrentChangeStar"
:current-page="currentPageStar" :page-size="pageSizeStar" layout="total, prev, pager, next"
:total="totalNumStar">
</el-pagination>
</div>
</el-tab-pane>
</el-tabs>
</el-dialog>
</div>



<div>
<button
class="ui primary basic button mini"
@click.stop.prevent="
selectImages(publicData.place, publicData.tag)
"
>
使用
</button>
</div>
</div>
<div
class="ui container"
style="margin-top: 50px; text-align: center"
>
<el-pagination
background
@current-change="handleCurrentChangePublic"
:current-page="currentPagePublic"
:page-size="pageSizePublic"
layout="total, prev, pager, next"
:total="totalNumPublic"
>
</el-pagination>
</div>
</el-tab-pane>

<el-tab-pane label="我的镜像" name="second" v-loading="loadingCustom">
<div
style="
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem 0;
border-bottom: 1px solid #f5f5f5;
"
v-for="(customData, index) in tableDataCustom"
:key="index"
>
<div style="width: 90%">
<div
style="
display: flex;
align-items: center;
justify-content: space-between;
"
>
<span
class="panel_dataset_name text-over"
style="margin-left: 0"
>{{ customData.tag }}
</span>
<div v-if="!!customData.topics" class="text-over">
<span
v-for="(topic, index) in customData.topics"
class="ui repo-topic label topic"
>{{ topic }}</span
>
</div>
</div>
<div style="margin-top: 8px; display: flex">
<a
v-if="customData.relAvatarLink || customData.userName"
:title="customData.userName"
style="cursor: default"
>
<img
class="ui avatar mini image"
style="width: 20px; height: 20px"
:src="customData.relAvatarLink"
/>
</a>
<a v-else
><img
class="ui avatar mini image"
title="Ghost"
src="/user/avatar/ghost/-1"
style="width: 20px; height: 20px"
/></a>

<span class="panel_datset_desc">{{
customData.description
}}</span>
</div>
</div>
<div>
<button
v-if="customData.status === 1"
class="ui primary basic button mini"
@click.stop.prevent="
selectImages(customData.place, customData.tag)
"
>
使用
</button>
<span
v-if="customData.status === 0"
style="display: flex; align-items: center"
>
<i class="CREATING"></i>
<span
style="margin-left: 0.4em; font-size: 12px; color: #5a5a5a"
>提交中</span
>
</span>
<span
v-if="customData.status === 2"
style="display: flex; align-items: center"
>
<i class="FAILED"></i>
<el-tooltip
class="item"
effect="dark"
content="检测提交镜像是否大小超过20G!"
placement="left"
>
<span style="margin-left: 0.4em; font-size: 12px; color: red"
>提交失败</span
>
</el-tooltip>
</span>
</div>
</div>
<div
class="ui container"
style="margin-top: 50px; text-align: center"
>
<el-pagination
background
@current-change="handleCurrentChangeCustom"
:current-page="currentPageCustom"
:page-size="pageSizeCustom"
layout="total, prev, pager, next"
:total="totalNumCustom"
>
</el-pagination>
</div>
</el-tab-pane>

<el-tab-pane label="我收藏的镜像" name="third">
<div
style="
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem 0;
border-bottom: 1px solid #f5f5f5;
"
v-for="(starData, index) in tableDataStar"
:key="index"
>
<div style="width: 90%">
<div
style="
display: flex;
align-items: center;
justify-content: space-between;
"
>
<div style="display: flex; align-items: center">
<span
class="panel_dataset_name text-over"
style="margin-left: 0"
>{{ starData.tag }}
</span>
<img
v-if="starData.type == 5"
src="/img/jian.svg"
style="margin-left: 0.5rem"
/>
</div>

<div v-if="!!starData.topics" class="text-over">
<span
v-for="(topic, index) in starData.topics"
class="ui repo-topic label topic"
>{{ topic }}</span
>
</div>
</div>
<div style="margin-top: 8px; display: flex">
<a
v-if="starData.relAvatarLink || starData.userName"
:title="starData.userName"
style="cursor: default"
>
<img
class="ui avatar mini image"
style="width: 20px; height: 20px"
:src="starData.relAvatarLink"
/>
</a>
<a v-else
><img
class="ui avatar mini image"
title="Ghost"
src="/user/avatar/ghost/-1"
style="width: 20px; height: 20px"
/></a>
<span class="panel_datset_desc">{{
starData.description
}}</span>
</div>
</div>
<div>
<button
class="ui primary basic button mini"
@click.stop.prevent="selectImages(starData.place, starData.tag)"
>
使用
</button>
</div>
</div>
<div
class="ui container"
style="margin-top: 50px; text-align: center"
>
<el-pagination
background
@current-change="handleCurrentChangeStar"
:current-page="currentPageStar"
:page-size="pageSizeStar"
layout="total, prev, pager, next"
:total="totalNumStar"
>
</el-pagination>
</div>
</el-tab-pane>
</el-tabs>
</el-dialog>
</div>
</template>

<script>

const { _AppSubUrl, _StaticUrlPrefix, csrf } = window.config;




export default {
components: {

},
data() {
return {
dialogVisible: false,
benchmarkNew: false,
imageAddress: '',
activeName: 'first',
search: '',
checked: false,
currentPagePublic: 1,
pageSizePublic: 5,
totalNumPublic: 0,
paramsPublic: { page: 1, pageSize: 5, q: '', recommend: false },
tableDataPublic: [],
loadingPublic: false,

currentPageCustom: 1,
pageSizeCustom: 5,
totalNumCustom: 0,
paramsCustom: { page: 1, pageSize: 5, q: '' },
tableDataCustom: [],
starCustom: [],
loadingCustom: false,

currentPageStar: 1,
pageSizeStar: 5,
totalNumStar: 0,
paramsStar: { page: 1, pageSize: 5, q: '' },
tableDataStar: [],
loadingStar: false
};
},
methods: {
handleClick(tab, event) {
this.search = ''
if (tab.name == "first") {
this.paramsPublic.q = ''
this.getImageListPublic()
}
if (tab.name == "second") {
this.getImageListCustom()
}
if (tab.name == "third") {
this.getImageListStar()
}

},
tableHeaderStyle({ row, column, rowIndex, columnIndex }) {

if (rowIndex === 0) {
return 'background:#f5f5f6;color:#606266'
}

},

handleCurrentChangePublic(val) {
this.paramsPublic.page = val
this.getImageListPublic()

},

handleCurrentChangeCustom(val) {
this.paramsCustom.page = val
this.getImageListCustom()

},
handleCurrentChangeStar(val) {
this.paramsStar.page = val
this.getImageListStar()

},
getImageListPublic() {
this.loadingPublic = true
this.$axios.get('/explore/images/public', {
params: this.paramsPublic
}).then((res) => {
this.totalNumPublic = res.data.count
this.tableDataPublic = res.data.images
this.loadingPublic = false
})
},

getImageListCustom() {
this.loadingCustom = true
this.$axios.get('/explore/images/custom', {
params: this.paramsCustom
}).then((res) => {
this.totalNumCustom = res.data.count
this.tableDataCustom = res.data.images
this.tableDataCustom.forEach(element => {
this.starCustom.push({ id: element.id, })

});
this.loadingCustom = false
})
},

getImageListStar() {
this.loadingStar = true
this.$axios.get('/explore/images/star', {
params: this.paramsStar
}).then((res) => {
this.totalNumStar = res.data.count
this.tableDataStar = res.data.images
this.loadingStar = false
})
},
searchName() {
if (this.activeName == 'first') {
this.paramsPublic.q = this.search
this.paramsPublic.page = 1
this.getImageListPublic()
}
if (this.activeName == 'second') {
this.paramsCustom.q = this.search
this.paramsCustom.page = 1
this.getImageListCustom()
}
if (this.activeName == 'third') {
this.paramsStar.q = this.search
this.paramsStar.page = 1
this.getImageListStar()
}

},
selectImages(place) {
this.imageAddress = place
this.dialogVisible = false
},

},
watch: {
search(val) {
if (this.activeName == 'first') {
this.paramsPublic.q = val
this.getImageListPublic()
}
if (this.activeName == 'second') {
this.paramsCustom.q = val
this.getImageListCustom()
}
if (this.activeName == 'third') {
this.paramsStar.q = val
this.getImageListStar()
}
}

},
mounted() {
this.getImageListPublic()
if (location.href.indexOf('benchmark') !== -1 || location.href.indexOf('train-job') !== -1) {
this.benchmarkNew = true
}
},
created() {

}

const { _AppSubUrl, _StaticUrlPrefix, csrf } = window.config;

export default {
components: {},
data() {
return {
dialogVisible: false,
benchmarkNew: false,
benchmark: false,
imageAddress: "",
activeName: "first",
search: "",
checked: false,
currentPagePublic: 1,
pageSizePublic: 5,
totalNumPublic: 0,
paramsPublic: { page: 1, pageSize: 5, q: "", recommend: false },
tableDataPublic: [],
loadingPublic: false,

currentPageCustom: 1,
pageSizeCustom: 5,
totalNumCustom: 0,
paramsCustom: { page: 1, pageSize: 5, q: "" },
tableDataCustom: [],
starCustom: [],
loadingCustom: false,

currentPageStar: 1,
pageSizeStar: 5,
totalNumStar: 0,
paramsStar: { page: 1, pageSize: 5, q: "" },
tableDataStar: [],
loadingStar: false,
};
</script>

<style scoped>
.header-wrapper {
background-color: #f5f5f6;
padding-top: 15px;
},
methods: {
handleClick(tab, event) {
this.search = "";
if (tab.name == "first") {
this.paramsPublic.q = "";
this.getImageListPublic();
}
if (tab.name == "second") {
this.getImageListCustom();
}
if (tab.name == "third") {
this.getImageListStar();
}
},
tableHeaderStyle({ row, column, rowIndex, columnIndex }) {
if (rowIndex === 0) {
return "background:#f5f5f6;color:#606266";
}
},

handleCurrentChangePublic(val) {
this.paramsPublic.page = val;
this.getImageListPublic();
},

handleCurrentChangeCustom(val) {
this.paramsCustom.page = val;
this.getImageListCustom();
},
handleCurrentChangeStar(val) {
this.paramsStar.page = val;
this.getImageListStar();
},
getImageListPublic() {
this.loadingPublic = true;
this.$axios
.get("/explore/images/public", {
params: this.paramsPublic,
})
.then((res) => {
this.totalNumPublic = res.data.count;
this.tableDataPublic = res.data.images;
this.loadingPublic = false;
});
},

getImageListCustom() {
this.loadingCustom = true;
this.$axios
.get("/explore/images/custom", {
params: this.paramsCustom,
})
.then((res) => {
this.totalNumCustom = res.data.count;
this.tableDataCustom = res.data.images;
this.tableDataCustom.forEach((element) => {
this.starCustom.push({ id: element.id });
});
this.loadingCustom = false;
});
},

getImageListStar() {
this.loadingStar = true;
this.$axios
.get("/explore/images/star", {
params: this.paramsStar,
})
.then((res) => {
this.totalNumStar = res.data.count;
this.tableDataStar = res.data.images;
this.loadingStar = false;
});
},
searchName() {
if (this.activeName == "first") {
this.paramsPublic.q = this.search;
this.paramsPublic.page = 1;
this.getImageListPublic();
}
if (this.activeName == "second") {
this.paramsCustom.q = this.search;
this.paramsCustom.page = 1;
this.getImageListCustom();
}
if (this.activeName == "third") {
this.paramsStar.q = this.search;
this.paramsStar.page = 1;
this.getImageListStar();
}
},
selectImages(place) {
this.imageAddress = place;
this.dialogVisible = false;
},
},
watch: {
search(val) {
if (this.activeName == "first") {
this.paramsPublic.q = val;
this.getImageListPublic();
}
if (this.activeName == "second") {
this.paramsCustom.q = val;
this.getImageListCustom();
}
if (this.activeName == "third") {
this.paramsStar.q = val;
this.getImageListStar();
}
},
},
mounted() {
this.getImageListPublic();
if (
location.href.indexOf("train-job") !== -1 ||
location.href.indexOf("benchmark") !== -1
) {
this.benchmarkNew = true;
}

.image_text {
padding: 25px 0 55px 0;
}

#header {
position: relative;
top: -40px;
}

#success {
background-color: #5bb973;
color: white;
}

.text-over {
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
}

.image_title {
display: inline-block;
width: 80%;
cursor: default;
color: rgb(66, 98, 144);
}

.image_desc {
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
display: -webkit-box;
text-overflow: ellipsis;
overflow: hidden;
}

.heart-stroke {
stroke: #666;
stroke-width: 2;
fill: #fff
if (location.href.indexOf("cloudbrain/benchmark/") !== -1) {
this.benchmark = true;
}
},
created() {},
};
</script>

.stars_active {
fill: #FA8C16 !important;
stroke: #FA8C16 !important
}
</style>
<style scoped>
.header-wrapper {
background-color: #f5f5f6;
padding-top: 15px;
}

.image_text {
padding: 25px 0 55px 0;
}

#header {
position: relative;
top: -40px;
}

#success {
background-color: #5bb973;
color: white;
}

.text-over {
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
}

.image_title {
display: inline-block;
width: 80%;
cursor: default;
color: rgb(66, 98, 144);
}

.image_desc {
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
display: -webkit-box;
text-overflow: ellipsis;
overflow: hidden;
}

.heart-stroke {
stroke: #666;
stroke-width: 2;
fill: #fff;
}

.stars_active {
fill: #fa8c16 !important;
stroke: #fa8c16 !important;
}
</style>

+ 2095
- 2121
web_src/js/index.js
File diff suppressed because it is too large
View File


+ 849
- 728
web_src/less/openi.less
File diff suppressed because it is too large
View File


Loading…
Cancel
Save