#4421 合入DCU调试,在线推理及日志获取等功能。

Merged
ychao_1983 merged 159 commits from zouap into V20230628 10 months ago
  1. +1
    -1
      cmd/web.go
  2. +3
    -7
      entity/ai_task.go
  3. +9
    -7
      entity/container.go
  4. +1
    -0
      entity/images.go
  5. +2
    -1
      manager/client/grampus/grampus.go
  6. +2
    -0
      models/action.go
  7. +61
    -40
      models/ai_model_manage.go
  8. +11
    -3
      models/cloudbrain.go
  9. +1
    -0
      models/task_config.go
  10. +2
    -11
      modules/setting/setting.go
  11. +5
    -0
      modules/structs/cloudbrain.go
  12. +2
    -0
      options/locale/locale_en-US.ini
  13. +3
    -1
      options/locale/locale_zh-CN.ini
  14. +5
    -3
      public/home/home.js
  15. +10
    -4
      routers/api/v1/api.go
  16. +44
    -9
      routers/api/v1/repo/cloudbrain.go
  17. +1
    -1
      routers/api/v1/repo/cloudbrain_dashboard.go
  18. +2
    -0
      routers/repo/ai_model_manage.go
  19. +79
    -0
      routers/repo/ai_model_square.go
  20. +0
    -150
      routers/repo/grampus.go
  21. +1
    -0
      routers/response/response_list.go
  22. +2
    -2
      routers/routes/routes.go
  23. +23
    -10
      services/ai_task_service/cluster/c2net.go
  24. +4
    -1
      services/ai_task_service/container_builder/code_builder.go
  25. +4
    -2
      services/ai_task_service/container_builder/dataset_builder.go
  26. +19
    -10
      services/ai_task_service/container_builder/output_path_builder.go
  27. +10
    -3
      services/ai_task_service/task/grampus_notebook_task.go
  28. +7
    -21
      services/ai_task_service/task/grampus_online_infer_task.go
  29. +14
    -2
      services/ai_task_service/task/opt_handler.go
  30. +13
    -3
      services/cloudbrain/cloudbrainTask/notebook.go
  31. +11
    -5
      services/cloudbrain/util.go
  32. +1
    -1
      services/socketwrap/clientManager.go
  33. +1
    -0
      templates/admin/cloudbrain/search.tmpl
  34. +1
    -0
      templates/admin/cloudbrain/search_dashboard.tmpl
  35. +2
    -3
      templates/base/footer.tmpl
  36. +5
    -2
      templates/custom/home/home_screen_map.tmpl
  37. +8
    -0
      templates/user/dashboard/feeds.tmpl
  38. +54
    -55
      web_src/js/router/index.js
  39. +67
    -3
      web_src/vuepages/apis/modules/cloudbrain.js
  40. +12
    -0
      web_src/vuepages/apis/modules/modelsquare.js
  41. +16
    -3
      web_src/vuepages/components/cloudbrain/ModelSelect.vue
  42. +25
    -4
      web_src/vuepages/components/cloudbrain/SpecSelect.vue
  43. +176
    -48
      web_src/vuepages/components/cloudbrain/details/ResultDownload.vue
  44. +2
    -2
      web_src/vuepages/const/index.js
  45. +18
    -1
      web_src/vuepages/langs/config/en-US.js
  46. +18
    -1
      web_src/vuepages/langs/config/zh-CN.js
  47. +48
    -2
      web_src/vuepages/pages/cloudbrain/configs.js
  48. +62
    -3
      web_src/vuepages/pages/cloudbrain/create/index.vue
  49. +91
    -4
      web_src/vuepages/pages/home/screenmap/index.vue
  50. +78
    -6
      web_src/vuepages/pages/modelmanage/components/ModelHeader.vue
  51. +1
    -1
      web_src/vuepages/pages/modelmanage/files/index.vue
  52. +1
    -1
      web_src/vuepages/pages/modelmanage/fileupload/index.vue
  53. +1
    -1
      web_src/vuepages/pages/modelmanage/graph/index.vue
  54. +166
    -7
      web_src/vuepages/pages/modelmanage/intro/index.vue
  55. +1
    -1
      web_src/vuepages/pages/modelmanage/settings/index.vue
  56. +10
    -1
      web_src/vuepages/pages/modelsquare/square/components/ModelCondition.vue
  57. +19
    -4
      web_src/vuepages/pages/modelsquare/square/components/ModelItem.vue
  58. +1
    -0
      web_src/vuepages/pages/modelsquare/square/components/ModelList.vue
  59. +3
    -0
      web_src/vuepages/pages/modelsquare/square/index.vue
  60. +11885
    -11885
      yarn.lock

+ 1
- 1
cmd/web.go View File

@@ -167,7 +167,7 @@ func runWeb(ctx *cli.Context) error {
if setting.EnablePprof {
go func() {
log.Info("Starting pprof server on localhost:6060")
log.Info("%v", http.ListenAndServe("localhost:6060", nil))
log.Info("%v", http.ListenAndServe("192.168.207.34:6060", nil))
}()
}



+ 3
- 7
entity/ai_task.go View File

@@ -4,6 +4,7 @@ import (
"strings"

"code.gitea.io/gitea/models"

"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
@@ -109,10 +110,9 @@ func (a *AITaskDetailInfo) RemovePretrainModelList() {

func getAiCenterShow(aiCenter string, language string) string {
aiCenterInfo := strings.Split(aiCenter, "+")

if len(aiCenterInfo) == 2 {
if setting.C2NetMapInfo != nil {
if info, ok := setting.C2NetMapInfo[aiCenterInfo[0]]; ok {
if setting.AiCenterCodeAndNameMapInfo != nil {
if info, ok := setting.AiCenterCodeAndNameMapInfo[aiCenterInfo[0]]; ok {
if language == defaultLanguage {
return info.Content
} else {
@@ -121,15 +121,11 @@ func getAiCenterShow(aiCenter string, language string) string {
} else {
return aiCenterInfo[1]
}

} else {
return aiCenterInfo[1]
}

}

return ""

}

var defaultLanguage = "zh-CN"


+ 9
- 7
entity/container.go View File

@@ -8,13 +8,15 @@ type TaskData struct {
}

type ContainerData struct {
Name string `json:"name"`
Bucket string `json:"bucket"`
EndPoint string `json:"endPoint"`
ObjectKey string `json:"objectKey"`
ContainerPath string `json:"containerPath"`
RealPath string `json:"realPath"`
ReadOnly bool `json:"readOnly"`
Name string `json:"name"`
Bucket string `json:"bucket"`
EndPoint string `json:"endPoint"`
ObjectKey string `json:"objectKey"`
ContainerPath string `json:"containerPath"`
RealPath string `json:"realPath"`
ReadOnly bool `json:"readOnly"`
Size int64 `json:"size"`
GetBackEndpoint string `json:"getBackEndpoint"`
}

type ContainerDataType string


+ 1
- 0
entity/images.go View File

@@ -5,6 +5,7 @@ import "code.gitea.io/gitea/models"
type ClusterImage struct {
ImageId string `json:"image_id"`
ImageName string `json:"image_name"`
ImageUrl string `json:"image_url"`
}

type GetImageReq struct {


+ 2
- 1
manager/client/grampus/grampus.go View File

@@ -92,7 +92,8 @@ func CreateNotebookJob(req models.CreateGrampusNotebookRequest) (*models.Grampus
checkSetting()
client := getRestyClient()
var result models.GrampusNotebookResponse

reqJson, _ := json.Marshal(req)
log.Info("Online infer REQ:" + string(reqJson))
retry := 0

sendjob:


+ 2
- 0
models/action.go View File

@@ -72,6 +72,7 @@ const (
ActionCreateGrampusMLUDebugTask //43
ActionCreateGrampusMLUTrainTask //44
ActionCreateGrampusGPUOnlineInferTask //45
ActionCreateGrampusDCUDebugTask //46
)

// Action represents user operation type and other information to
@@ -423,6 +424,7 @@ func (a *Action) IsCloudbrainAction() bool {
ActionCreateGrampusGPUTrainTask,
ActionCreateGrampusGCUTrainTask,
ActionCreateGrampusGCUDebugTask,
ActionCreateGrampusDCUDebugTask,
ActionCreateGrampusMLUDebugTask:
return true
}


+ 61
- 40
models/ai_model_manage.go View File

@@ -13,46 +13,49 @@ import (
)

type AiModelManage struct {
ID string `xorm:"pk" json:"id"`
Name string `xorm:"INDEX NOT NULL" json:"name"`
ModelType int `xorm:"NULL" json:"modelType"`
Version string `xorm:"NOT NULL" json:"version"`
VersionCount int `xorm:"NOT NULL DEFAULT 0" json:"versionCount"`
New int `xorm:"NOT NULL" json:"new"`
Type int `xorm:"NOT NULL" json:"type"`
Size int64 `xorm:"NOT NULL" json:"size"`
Description string `xorm:"varchar(2000)" json:"description"`
Label string `xorm:"varchar(1000)" json:"label"`
Path string `xorm:"varchar(400) NOT NULL" json:"path"`
DownloadCount int `xorm:"NOT NULL DEFAULT 0" json:"downloadCount"`
Engine int64 `xorm:"NOT NULL DEFAULT 0" json:"engine"`
ComputeResource string `json:"computeResource"`
Status int `xorm:"NOT NULL DEFAULT 0" json:"status"`
StatusDesc string `xorm:"varchar(500)" json:"statusDesc"`
Accuracy string `xorm:"varchar(1000)" json:"accuracy"`
AttachmentId string `xorm:"NULL" json:"attachmentId"`
RepoId int64 `xorm:"INDEX NULL" json:"repoId"`
CodeBranch string `xorm:"varchar(400) NULL" json:"codeBranch"`
CodeCommitID string `xorm:"NULL" json:"codeCommitID"`
Recommend int `xorm:"NOT NULL DEFAULT 0" json:"recommend"`
UserId int64 `xorm:"NOT NULL" json:"userId"`
IsPrivate bool `xorm:"DEFAULT true" json:"isPrivate"`
UserName string `xorm:"-" json:"userName"`
UserRelAvatarLink string `xorm:"-" json:"userRelAvatarLink"`
TrainTaskInfo string `xorm:"text NULL" json:"trainTaskInfo"`
CreatedUnix timeutil.TimeStamp `xorm:"created" json:"createdUnix"`
UpdatedUnix timeutil.TimeStamp `xorm:"updated" json:"updatedUnix"`
IsCanOper bool `xorm:"-" json:"isCanOper"`
IsCanDelete bool `xorm:"-" json:"isCanDelete"`
IsCanDownload bool `xorm:"-" json:"isCanDownload"`
IsCollected bool `xorm:"-" json:"isCollected"`
RepoName string `xorm:"-" json:"repoName"`
RepoDisplayName string `xorm:"-" json:"repoDisplayName"`
RepoOwnerName string `xorm:"-" json:"repoOwnerName"`
DatasetInfo []*DatasetDownload `xorm:"-" json:"datasetInfo"`
ReferenceCount int `xorm:"NOT NULL DEFAULT 0" json:"referenceCount"`
CollectedCount int `xorm:"NOT NULL DEFAULT 0" json:"collectedCount"`
ModelFileList []storage.FileInfo `xorm:"-" json:"modelFileList"`
ID string `xorm:"pk" json:"id"`
Name string `xorm:"INDEX NOT NULL" json:"name"`
ModelType int `xorm:"NULL" json:"modelType"`
Version string `xorm:"NOT NULL" json:"version"`
VersionCount int `xorm:"NOT NULL DEFAULT 0" json:"versionCount"`
New int `xorm:"NOT NULL" json:"new"`
Type int `xorm:"NOT NULL" json:"type"`
Size int64 `xorm:"NOT NULL" json:"size"`
Description string `xorm:"varchar(2000)" json:"description"`
Label string `xorm:"varchar(1000)" json:"label"`
Path string `xorm:"varchar(400) NOT NULL" json:"path"`
DownloadCount int `xorm:"NOT NULL DEFAULT 0" json:"downloadCount"`
Engine int64 `xorm:"NOT NULL DEFAULT 0" json:"engine"`
ComputeResource string `json:"computeResource"`
Status int `xorm:"NOT NULL DEFAULT 0" json:"status"`
StatusDesc string `xorm:"varchar(500)" json:"statusDesc"`
Accuracy string `xorm:"varchar(1000)" json:"accuracy"`
AttachmentId string `xorm:"NULL" json:"attachmentId"`
RepoId int64 `xorm:"INDEX NULL" json:"repoId"`
CodeBranch string `xorm:"varchar(400) NULL" json:"codeBranch"`
CodeCommitID string `xorm:"NULL" json:"codeCommitID"`
Recommend int `xorm:"NOT NULL DEFAULT 0" json:"recommend"`
UserId int64 `xorm:"NOT NULL" json:"userId"`
IsPrivate bool `xorm:"DEFAULT true" json:"isPrivate"`
UserName string `xorm:"-" json:"userName"`
UserRelAvatarLink string `xorm:"-" json:"userRelAvatarLink"`
TrainTaskInfo string `xorm:"text NULL" json:"trainTaskInfo"`
CreatedUnix timeutil.TimeStamp `xorm:"created" json:"createdUnix"`
UpdatedUnix timeutil.TimeStamp `xorm:"updated" json:"updatedUnix"`
IsCanOper bool `xorm:"-" json:"isCanOper"`
IsCanDelete bool `xorm:"-" json:"isCanDelete"`
IsCanDownload bool `xorm:"-" json:"isCanDownload"`
IsCollected bool `xorm:"-" json:"isCollected"`
RepoName string `xorm:"-" json:"repoName"`
RepoDisplayName string `xorm:"-" json:"repoDisplayName"`
RepoOwnerName string `xorm:"-" json:"repoOwnerName"`
DatasetInfo []*DatasetDownload `xorm:"-" json:"datasetInfo"`
ReferenceCount int `xorm:"NOT NULL DEFAULT 0" json:"referenceCount"`
CollectedCount int `xorm:"NOT NULL DEFAULT 0" json:"collectedCount"`
ModelFileList []storage.FileInfo `xorm:"-" json:"modelFileList"`
OnlineInfo []map[string]interface{} `xorm:"-" json:"onlineInfo"`
UsedCloudbrain []map[string]interface{} `xorm:"-" json:"usedCloudbrain"`
HasOnlineUrl int `xorm:"NOT NULL DEFAULT 0" json:"hasOnlineUrl"`
}

type AiModelFile struct {
@@ -127,6 +130,7 @@ type AiModelQueryOptions struct {
FrameFilter int
ComputeResourceFilter string
NotNeedEmpty bool
HasOnlineUrl int
}

func (a *AiModelConvert) IsGpuTrainTask() bool {
@@ -333,6 +337,20 @@ func ModifyModelDescription(id string, description string) error {
return nil
}

func ModifyModelHashOnlineUrl(id string, hasOnlineUrl int) error {
var sess *xorm.Session
sess = x.ID(id)
defer sess.Close()
re, err := sess.Cols("has_online_url").Update(&AiModelManage{
HasOnlineUrl: hasOnlineUrl,
})
if err != nil {
return err
}
log.Info("success to update hasOnlineUrl from db.re=" + fmt.Sprint((re)))
return nil
}

func ModifyModelPrivate(id string, isPrivate bool) error {
var sess *xorm.Session
sess = x.ID(id)
@@ -549,6 +567,9 @@ func QueryModel(opts *AiModelQueryOptions) ([]*AiModelManage, int64, error) {
if opts.NotNeedEmpty {
where += " and ai_model_manage.size > 0 "
}
if opts.HasOnlineUrl > 0 {
where += " and ai_model_manage.has_online_url =1 "
}
var count int64
var err error
if opts.IsCollected {


+ 11
- 3
models/cloudbrain.go View File

@@ -157,11 +157,13 @@ const (
NPU = "NPU"
GCU = "GCU"
MLU = "MLU"
DCU = "DCU"

ProcessorTypeNPU = "npu.huawei.com/NPU"
ProcessorTypeGPU = "nvidia.com/gpu"
ProcessorTypeGCU = "enflame-tech.com/gcu"
ProcessorTypeMLU = "cambricon.com/mlu"
ProcessorTypeDCU = "ac.sugon.com/dcu"
)

type ComputeSource struct {
@@ -191,6 +193,7 @@ var ComputeSourceMap = map[string]*ComputeSource{
NPU: {Name: NPU, FullName: ProcessorTypeNPU},
GCU: {Name: GCU, FullName: ProcessorTypeGCU},
MLU: {Name: MLU, FullName: ProcessorTypeMLU},
DCU: {Name: DCU, FullName: ProcessorTypeDCU},
}

const (
@@ -256,7 +259,7 @@ type Cloudbrain struct {
LabelName string //标签名称
ModelName string //模型名称
ModelVersion string //模型版本
CkptName string //权重文件名称
CkptName string `xorm:"varchar(2550)"` //权重文件名称
ModelId string //模型ID
ModelRepoName string `xorm:"-"`
ModelRepoOwnerName string `xorm:"-"`
@@ -504,6 +507,10 @@ func (task *Cloudbrain) IsNPUTask() bool {
return task.ComputeResource == NPUResource
}

func (task *Cloudbrain) IsDCUTask() bool {
return task.ComputeResource == DCU
}

func ConvertDurationToStr(duration int64) string {
if duration <= 0 {
return DURATION_STR_ZERO
@@ -1950,6 +1957,7 @@ type GrampusNotebookTask struct {
CenterName []string `json:"centerName"`
Code GrampusDataset `json:"code"`
Datasets []GrampusDataset `json:"datasets"`
OutPut GrampusDataset `json:"output"`
CodeUrl string `json:"codeUrl"`
DataUrl string `json:"dataUrl"`
ImageId string `json:"imageId"`
@@ -3175,7 +3183,7 @@ func GetDatasetInfo(uuidStr string, grampusType ...string) (map[string]DatasetIn
dataLocalPath = setting.Attachment.Minio.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID
} else if grampusType[0] == NPU {
dataLocalPath = setting.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID + "/"
} else if grampusType[0] == GCU || grampusType[0] == MLU {
} else if grampusType[0] == GCU || grampusType[0] == MLU || grampusType[0] == DCU {
if attach.Type == TypeCloudBrainOne {
dataLocalPath = setting.Attachment.Minio.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID
} else {
@@ -3320,7 +3328,7 @@ func LoadSpecs4CloudbrainInfo(tasks []*CloudbrainInfo) error {

func GetCloudBrainByModelId(modelId string) ([]*Cloudbrain, error) {
cloudBrains := make([]*Cloudbrain, 0)
err := x.AllCols().Where("model_id=?", modelId).OrderBy("created_unix asc").Find(&cloudBrains)
err := x.AllCols().Where("model_id=?", modelId).OrderBy("created_unix desc").Find(&cloudBrains)
return cloudBrains, err
}



+ 1
- 0
models/task_config.go View File

@@ -42,6 +42,7 @@ func GetTaskTypeFromAction(a ActionType) TaskType {
ActionCreateGrampusGCUDebugTask,
ActionCreateGrampusGCUTrainTask,
ActionCreateGrampusMLUDebugTask,
ActionCreateGrampusDCUDebugTask,
ActionCreateGrampusGPUOnlineInferTask,
ActionCreateGrampusGPUTrainTask:
return TaskCreateCloudbrainTask


+ 2
- 11
modules/setting/setting.go View File

@@ -655,7 +655,6 @@ var (

C2NetInfos *C2NetSqInfos
CenterInfos *AiCenterInfos
C2NetMapInfo map[string]*C2NetSequenceInfo
AiCenterCodeAndNameMapInfo map[string]*C2NetSequenceInfo
C2NetLocInfos *C2NetSqInfos
AiCenterCodeAndNameAndLocMapInfo map[string]*C2NetSequenceInfo
@@ -1854,21 +1853,13 @@ func GetGrampusConfig() {
Grampus.UserName = sec.Key("USERNAME").MustString("")
Grampus.Password = sec.Key("PASSWORD").MustString("")
Grampus.SpecialPools = sec.Key("SPECIAL_POOL").MustString("")
Grampus.C2NetSequence = sec.Key("C2NET_SEQUENCE").MustString("{\"sequence\":[{\"id\":1,\"name\":\"cloudbrain_one\",\"content\":\"鹏城云脑一号\",\"content_en\":\"Pencheng Cloudbrain Ⅰ\"},{\"id\":2,\"name\":\"cloudbrain_two\",\"content\":\"鹏城云脑二号\",\"content_en\":\"Pencheng Cloudbrain Ⅱ\"},{\"id\":3,\"name\":\"beida\",\"content\":\"北大人工智能集群系统\",\"content_en\":\"Peking University AI Center\"},{\"id\":4,\"name\":\"hefei\",\"content\":\"合肥类脑智能开放平台\",\"content_en\":\"Hefei AI Center\"},{\"id\":5,\"name\":\"wuhan\",\"content\":\"武汉人工智能计算中心\",\"content_en\":\"Wuhan AI Center\"},{\"id\":6,\"name\":\"xian\",\"content\":\"西安未来人工智能计算中心\",\"content_en\":\"Xi'an AI Center\"},{\"id\":7,\"pclcci\":\"more\",\"content\":\"鹏城云计算所\",\"content_en\":\"Pengcheng Cloud Computing Institute\"},{\"id\":8,\"name\":\"xuchang\",\"content\":\"中原人工智能计算中心\",\"content_en\":\"Zhongyuan AI Center\"},{\"id\":9,\"name\":\"chengdu\",\"content\":\"成都人工智能计算中心\",\"content_en\":\"Chengdu AI Center\"},{\"id\":10,\"name\":\"more\",\"content\":\"横琴先进智能计算中心\",\"content_en\":\"Hengqin AI Center\"},{\"id\":11,\"name\":\"more\",\"content\":\"国家超级计算济南中心\",\"content_en\":\"HPC & AI Center\"}]}")
//Grampus.C2NetSequence = sec.Key("C2NET_SEQUENCE").MustString("{\"sequence\":[{\"id\":1,\"name\":\"cloudbrain_one\",\"content\":\"鹏城云脑一号\",\"content_en\":\"Pencheng Cloudbrain Ⅰ\"},{\"id\":2,\"name\":\"cloudbrain_two\",\"content\":\"鹏城云脑二号\",\"content_en\":\"Pencheng Cloudbrain Ⅱ\"},{\"id\":3,\"name\":\"beida\",\"content\":\"北大人工智能集群系统\",\"content_en\":\"Peking University AI Center\"},{\"id\":4,\"name\":\"hefei\",\"content\":\"合肥类脑智能开放平台\",\"content_en\":\"Hefei AI Center\"},{\"id\":5,\"name\":\"wuhan\",\"content\":\"武汉人工智能计算中心\",\"content_en\":\"Wuhan AI Center\"},{\"id\":6,\"name\":\"xian\",\"content\":\"西安未来人工智能计算中心\",\"content_en\":\"Xi'an AI Center\"},{\"id\":7,\"pclcci\":\"more\",\"content\":\"鹏城云计算所\",\"content_en\":\"Pengcheng Cloud Computing Institute\"},{\"id\":8,\"name\":\"xuchang\",\"content\":\"中原人工智能计算中心\",\"content_en\":\"Zhongyuan AI Center\"},{\"id\":9,\"name\":\"chengdu\",\"content\":\"成都人工智能计算中心\",\"content_en\":\"Chengdu AI Center\"},{\"id\":10,\"name\":\"more\",\"content\":\"横琴先进智能计算中心\",\"content_en\":\"Hengqin AI Center\"},{\"id\":11,\"name\":\"more\",\"content\":\"国家超级计算济南中心\",\"content_en\":\"HPC & AI Center\"}]}")
Grampus.AiCenterCodeAndNameInfo = sec.Key("AI_CENTER_CODE_AND_NAME").MustString("{\"sequence\":[{\"id\":1,\"name\":\"cloudbrain_one\",\"content\":\"鹏城云脑一号\",\"content_en\":\"Pencheng Cloudbrain Ⅰ\"},{\"id\":2,\"name\":\"cloudbrain_two\",\"content\":\"鹏城云脑二号\",\"content_en\":\"Pencheng Cloudbrain Ⅱ\"},{\"id\":3,\"name\":\"beida\",\"content\":\"北大人工智能集群系统\",\"content_en\":\"Peking University AI Center\"},{\"id\":4,\"name\":\"hefei\",\"content\":\"合肥类脑智能开放平台\",\"content_en\":\"Hefei AI Center\"},{\"id\":5,\"name\":\"wuhan\",\"content\":\"武汉人工智能计算中心\",\"content_en\":\"Wuhan AI Center\"},{\"id\":6,\"name\":\"xian\",\"content\":\"西安未来人工智能计算中心\",\"content_en\":\"Xi'an AI Center\"},{\"id\":7,\"pclcci\":\"more\",\"content\":\"鹏城云计算所\",\"content_en\":\"Pengcheng Cloud Computing Institute\"},{\"id\":8,\"name\":\"xuchang\",\"content\":\"中原人工智能计算中心\",\"content_en\":\"Zhongyuan AI Center\"},{\"id\":9,\"name\":\"chengdu\",\"content\":\"成都人工智能计算中心\",\"content_en\":\"Chengdu AI Center\"},{\"id\":10,\"name\":\"more\",\"content\":\"横琴先进智能计算中心\",\"content_en\":\"Hengqin AI Center\"},{\"id\":11,\"name\":\"more\",\"content\":\"国家超级计算济南中心\",\"content_en\":\"HPC & AI Center\"}]}")
Grampus.AiCenterCodeAndNameAndLocInfo = sec.Key("AI_CENTER_CODE_AND_NAME_AND_LOC").MustString("{\"sequence\":[{\"id\":1,\"name\":\"cloudbrain_one\",\"content\":\"鹏城云脑一号\",\"content_en\":\"Pencheng Cloudbrain Ⅰ\"},{\"id\":2,\"name\":\"cloudbrain_two\",\"content\":\"鹏城云脑二号\",\"content_en\":\"Pencheng Cloudbrain Ⅱ\"},{\"id\":3,\"name\":\"beida\",\"content\":\"北大人工智能集群系统\",\"content_en\":\"Peking University AI Center\"},{\"id\":4,\"name\":\"hefei\",\"content\":\"合肥类脑智能开放平台\",\"content_en\":\"Hefei AI Center\"},{\"id\":5,\"name\":\"wuhan\",\"content\":\"武汉人工智能计算中心\",\"content_en\":\"Wuhan AI Center\"},{\"id\":6,\"name\":\"xian\",\"content\":\"西安未来人工智能计算中心\",\"content_en\":\"Xi'an AI Center\"},{\"id\":7,\"pclcci\":\"more\",\"content\":\"鹏城云计算所\",\"content_en\":\"Pengcheng Cloud Computing Institute\"},{\"id\":8,\"name\":\"xuchang\",\"content\":\"中原人工智能计算中心\",\"content_en\":\"Zhongyuan AI Center\"},{\"id\":9,\"name\":\"chengdu\",\"content\":\"成都人工智能计算中心\",\"content_en\":\"Chengdu AI Center\"},{\"id\":10,\"name\":\"more\",\"content\":\"横琴先进智能计算中心\",\"content_en\":\"Hengqin AI Center\"},{\"id\":11,\"name\":\"more\",\"content\":\"国家超级计算济南中心\",\"content_en\":\"HPC & AI Center\"}]}")

Grampus.UsageRateBeginTime = sec.Key("USAGE_RATE_BEGIN_TIME").MustString("2021-01-01 00:00:00")
Grampus.GPUImageCommonName = sec.Key("GPU_IMAGE_COMMON_NAME").MustString("image")
if Grampus.C2NetSequence != "" {
if err := json.Unmarshal([]byte(Grampus.C2NetSequence), &C2NetInfos); err != nil {
log.Error("Unmarshal(C2NetSequence) failed:%v", err)
}
C2NetMapInfo = make(map[string]*C2NetSequenceInfo)
for _, value := range C2NetInfos.C2NetSqInfo {
C2NetMapInfo[value.Name] = value
}
}

if Grampus.AiCenterCodeAndNameAndLocInfo != "" {
if err := json.Unmarshal([]byte(Grampus.AiCenterCodeAndNameAndLocInfo), &C2NetLocInfos); err != nil {
log.Error("Unmarshal(AiCenterCodeAndNameLocInfo) failed:%v", err)


+ 5
- 0
modules/structs/cloudbrain.go View File

@@ -155,3 +155,8 @@ type PointAccountShow struct {
CreatedUnix int64 `json:"created_unix"`
UpdatedUnix int64 `json:"updated_unix"`
}

type CreateModelNoteBook struct {
RepoId int64 `json:"repoId" binding:"Required"`
ModelId string `json:"modelId" binding:"Required"`
}

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

@@ -1388,6 +1388,7 @@ modelconvert.manage.no_operate_right=You have no right to do the operation.
debug.manage.model_not_exist=The model in the task does not exist or has been deleted, please create a new debug job.
train.manage.model_not_exist=The model in the task does not exist or has been deleted, please create a new train job.
debug.manage.dataset_not_exist=The part of datasets in the task does not exist or has been deleted, please create a new debug job.
debug.manage.model_num_over_limit=The number of models exceeds the limit of 30

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。
@@ -3179,6 +3180,7 @@ task_c2ent_gcudebugjob=`created GCU type debugging task <a href="%s/grampus/trai
task_c2ent_gcutrainjob=`created GCU type train task <a href="%s/modelarts/train-job/%s">%s</a>`
task_c2ent_mludebugjob=`created MLU type debugging task <a href="%s/grampus/train-job/%s">%s</a>`
task_c2ent_mlutrainjob=`created MLU type train task <a href="%s/modelarts/train-job/%s">%s</a>`
task_c2net_dcudebugjob=`created DCU type debugging task <a href="%s/grampus/notebook/%s">%s</a>`
task_c2ent_onlineinferjob=`created GPU type online inference task <a href="%s/grampus/onlineinfer/%s">%s</a>`
task_nputrainjob=`created NPU training task <a href="%s/modelarts/train-job/%s">%s</a>`
task_inferencejob=`created reasoning task <a href="%s/modelarts/inference-job/%s">%s</a>`


+ 3
- 1
options/locale/locale_zh-CN.ini View File

@@ -1402,6 +1402,7 @@ modelconvert.manage.no_operate_right=您没有操作权限。
debug.manage.model_not_exist=任务中选择的模型不存在或者已被删除,请新建调试任务。
train.manage.model_not_exist=任务中选择的模型不存在或者已被删除,请新建训练任务。
debug.manage.dataset_not_exist=任务中选择的部分数据集不存在或者已被删除,请新建调试任务。
debug.manage.model_num_over_limit=任务中选择的模型限制不超过30个文件

grampus.train_job.ai_center=智算中心
grampus.dataset_path_rule = 训练脚本存储在/cache/code中,数据集存储在/cache/dataset中,训练输出请存储在/cache/output中以供后续下载。
@@ -3197,6 +3198,7 @@ task_c2ent_gcudebugjob=`创建了GCU类型调试任务 <a href="%s/grampus/noteb
task_c2ent_gcutrainjob=`创建了GCU类型训练任务 <a href="%s/grampus/train-job/%s">%s</a>`
task_c2ent_mludebugjob=`创建了MLU类型调试任务 <a href="%s/grampus/notebook/%s">%s</a>`
task_c2ent_mlutrainjob=`创建了MLU类型训练任务 <a href="%s/grampus/train-job/%s">%s</a>`
task_c2net_dcudebugjob=`创建了DCU类型调试任务 <a href="%s/grampus/notebook/%s">%s</a>`
task_c2ent_onlineinferjob=`创建了GPU类型在线推理任务 <a href="%s/grampus/onlineinfer/%s">%s</a>`
task_nputrainjob=`创建了NPU类型训练任务 <a href="%s/modelarts/train-job/%s">%s</a>`
task_inferencejob=`创建了推理任务 <a href="%s/modelarts/inference-job/%s">%s</a>`
@@ -3256,7 +3258,7 @@ max_size_tooltips=一次最多只能上传?个文件, 上传已达到上限,
notifications=通知
unread=未读消息
read=已读消息
notice=通知消息
notice=通知公告
no_unread=没有未读通知。
no_read=没有未读通知。
pin=Pin 通知


+ 5
- 3
public/home/home.js View File

@@ -253,7 +253,7 @@ document.onreadystatechange = function () {
html += " <span style=\"color: rgba(0,0,0,0.3)\">" + record.RefName + "</span>"
}
}
else if(record.OpType == "25" || record.OpType == "29" || record.OpType == "39" || record.OpType == "40" || record.OpType == "41" || record.OpType == "43"|| record.OpType == "44"|| record.OpType == "45"){
else if(record.OpType == "25" || record.OpType == "29" || record.OpType == "39" || record.OpType == "40" || record.OpType == "41" || record.OpType == "43"|| record.OpType == "44"|| record.OpType == "45"|| record.OpType == "46"){
html += recordPrefix + actionName;
const taskLink = getTaskLink(record);
if (taskLink) {
@@ -313,7 +313,7 @@ function getTaskLink(record){
re = re + "/cloudbrain/train-job/" + record.Content;
}else if(record.OpType == 32 || record.OpType == 33 || record.OpType == 42 || record.OpType == 44){
re = re + "/grampus/train-job/" + record.Content;
}else if(record.OpType == 39 || record.OpType == 40 || record.OpType == 41 || record.OpType == 43){
}else if(record.OpType == 39 || record.OpType == 40 || record.OpType == 41 || record.OpType == 43|| record.OpType == 46){
if (record.Cloudbrain) {
re = re + "/grampus/notebook/" + record.Cloudbrain.ID;
} else {
@@ -484,7 +484,8 @@ var actionNameZH={
"42":"创建了GCU类型训练任务",
"43":"创建了MLU类型调试任务",
"44":"创建了MLU类型训练任务",
"45":"创建了GPU在线推理任务",
"45":"创建了GPU类型在线推理任务",
"46":"创建了DCU类型调试任务",
};

var actionNameEN={
@@ -523,6 +524,7 @@ var actionNameEN={
"43":" created MLU type debugging task ",
"44":" created MLU type training task ",
"45":" created GPU type online inference task ",
"46":" created DCU type debugging task ",
};

var repoAndOrgZH={


+ 10
- 4
routers/api/v1/api.go View File

@@ -59,11 +59,13 @@
package v1

import (
"code.gitea.io/gitea/entity"
"code.gitea.io/gitea/routers/response"
"net/http"
"strings"

"code.gitea.io/gitea/routers/response"

"code.gitea.io/gitea/entity"

cloudbrainService "code.gitea.io/gitea/services/cloudbrain"

"code.gitea.io/gitea/routers/ai_task"
@@ -646,8 +648,8 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Group("/:username/:reponame", func() {
m.Group("/ai_task", func() {
m.Post("/create", reqWeChatStandard(), reqRepoWriter(models.UnitTypeCloudBrain), bind(entity.CreateReq{}), ai_task.CreateAITask)
m.Post("/stop", reqRepoWriter(models.UnitTypeCloudBrain), reqAITaskInRepo(), reqAdminOrOwnerAITaskCreator(), ai_task.StopAITask)
m.Post("/del", reqRepoWriter(models.UnitTypeCloudBrain), reqAITaskInRepo(), reqAdminOrOwnerAITaskCreator(), ai_task.DelAITask)
m.Post("/stop", reqWeChatStandard(), reqRepoWriter(models.UnitTypeCloudBrain), reqAITaskInRepo(), reqAdminOrOwnerAITaskCreator(), ai_task.StopAITask)
m.Post("/del", reqWeChatStandard(), reqRepoWriter(models.UnitTypeCloudBrain), reqAITaskInRepo(), reqAdminOrOwnerAITaskCreator(), ai_task.DelAITask)
m.Post("/restart", reqWeChatStandard(), reqRepoWriter(models.UnitTypeCloudBrain), reqAITaskInRepo(), reqAdminOrAITaskCreator(), ai_task.RestartAITask)
m.Get("/log", reqWeChatStandard(), reqRepoWriter(models.UnitTypeCloudBrain), reqAITaskInRepo(), ai_task.GetAITaskLog)
m.Get("/output", reqWeChatStandard(), reqRepoWriter(models.UnitTypeCloudBrain), reqAITaskInRepo(), ai_task.GetAITaskOutput)
@@ -932,6 +934,10 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/status", reqToken(), bind(api.CreateFileNotebookJobOption{}), repo.FileNoteBookStatus)
})

m.Group("/model_notebook", func() {
m.Post("/create", reqToken(), reqWeChatStandard(), bind(api.CreateModelNoteBook{}), repo.CreateModelNoteBook)
})

m.Group("/repos", func() {
m.Get("/search", repo.Search)



+ 44
- 9
routers/api/v1/repo/cloudbrain.go View File

@@ -7,10 +7,6 @@ package repo

import (
"bufio"
"code.gitea.io/gitea/entity"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/response"
"code.gitea.io/gitea/services/ai_task_service/task"
"encoding/json"
"fmt"
"io"
@@ -23,17 +19,21 @@ import (
"strings"
"time"

"code.gitea.io/gitea/entity"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/response"
"code.gitea.io/gitea/services/ai_task_service/task"

"code.gitea.io/gitea/services/reward/point/account"

"code.gitea.io/gitea/modules/grampus"

cloudbrainService "code.gitea.io/gitea/services/cloudbrain"

"code.gitea.io/gitea/modules/convert"
"code.gitea.io/gitea/services/cloudbrain/cloudbrainTask"
cloudbrainService "code.gitea.io/gitea/services/cloudbrain"
repo_service "code.gitea.io/gitea/services/repository"

api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/services/cloudbrain/cloudbrainTask"

"code.gitea.io/gitea/modules/notification"

@@ -122,6 +122,31 @@ func CreateFileNoteBook(ctx *context.APIContext, option api.CreateFileNotebookJo
CreateFileNotebookTask(ctx.Context, option)
}

func CreateModelNoteBook(ctx *context.APIContext, option api.CreateModelNoteBook) {
log.Info("repoId 1=" + fmt.Sprint(option.RepoId) + " modelId=" + option.ModelId)
re := make(map[string]interface{}, 0)
oldRepoId := option.RepoId

oldRepo, err := models.GetRepositoryByID(oldRepoId)
if err != nil {
log.Info("get repo err=" + err.Error())
ctx.JSON(http.StatusOK, re)
return
}

existRepo, _ := models.GetRepositoryByName(ctx.User.ID, oldRepo.Name)
if existRepo == nil {
_, err := repo_service.ForkRepository(ctx.User, ctx.User, oldRepo, oldRepo.Name, oldRepo.Description, oldRepo.Alias)
if err != nil {
log.Info("fork repository error.err=" + err.Error())
ctx.JSON(http.StatusOK, re)
return
}
}
re["repoPath"] = ctx.User.Name + "/" + oldRepo.Name
ctx.JSON(http.StatusOK, re)
}

func CreateFileNotebookTask(ctx *context.Context, option api.CreateFileNotebookJobOption) {
displayJobName := cloudbrainService.GetDisplayJobName(ctx.User.Name)
jobName := util.ConvertDisplayJobNameToJobName(displayJobName)
@@ -1301,7 +1326,16 @@ func CloudBrainModelList(ctx *context.APIContext) {
dirs, err := routerRepo.GetModelDirs(task.JobName, parentDir)
if err != nil {
log.Error("GetModelDirs failed:%v", err.Error(), ctx.Data["msgID"])
ctx.ServerError("GetModelDirs failed:", err)
ctx.JSON(http.StatusOK, map[string]interface{}{
"JobID": jobID,
"VersionName": versionName,
"StatusOK": 0,
"Path": dirArray,
"Dirs": "",
"task": task,
"CanDownload": false,
"PageIsCloudBrain": true,
})
return
}

@@ -1329,6 +1363,7 @@ func CloudBrainModelList(ctx *context.APIContext) {
"Path": dirArray,
"Dirs": fileInfos,
"task": task,
"CanDownload": cloudbrain.CanDeleteJob(ctx.Context, task),
"PageIsCloudBrain": true,
})
}


+ 1
- 1
routers/api/v1/repo/cloudbrain_dashboard.go View File

@@ -2120,7 +2120,7 @@ func GetResourceQueues(ctx *context.Context) {
aiCenterCodeMap := make(map[string]string)
for _, resourceQueue := range resourceQueues {
if _, ok := aiCenterCodeMap[resourceQueue.AiCenterCode]; !ok {
resourceQueue.AiCenterName = repo.GetAiCenterNameByCode(resourceQueue.AiCenterCode, ctx.Language())
resourceQueue.AiCenterName = cloudbrainService.GetAiCenterShow(resourceQueue.AiCenterCode, ctx)
aiCenterCodeMap[resourceQueue.AiCenterCode] = resourceQueue.AiCenterCode
Resource = append(Resource, resourceQueue)
}


+ 2
- 0
routers/repo/ai_model_manage.go View File

@@ -968,6 +968,7 @@ func ShowSingleModel(ctx *context.Context) {
continue
}
}
setModelRelateInfo(model)
modelResult = append(modelResult, model)
}
userNameMap := queryUserName(userIds)
@@ -980,6 +981,7 @@ func ShowSingleModel(ctx *context.Context) {
model.UserRelAvatarLink = value.RelAvatarLink()
}
}

ctx.JSON(http.StatusOK, modelResult)
}



+ 79
- 0
routers/repo/ai_model_square.go View File

@@ -5,15 +5,18 @@ import (
"fmt"
"io/ioutil"
"net/http"
"regexp"
"strconv"
"strings"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/grampus"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/services/cloudbrain/cloudbrainTask"
"code.gitea.io/gitea/services/cloudbrain/modelmanage"
"code.gitea.io/gitea/services/repository"
)
@@ -54,6 +57,7 @@ func ModelSquareData(ctx *context.Context) {
pageSize = setting.UI.IssuePagingNum
}
isRecommend := ctx.QueryBool("recommend")
isOnlineUrl := ctx.QueryBool("hasOnlineUrl")
queryType := ctx.QueryInt("queryType")
labelFilter := ctx.Query("label")
frameFilterStr := ctx.Query("frame")
@@ -73,6 +77,10 @@ func ModelSquareData(ctx *context.Context) {
var collected_user_id int64
var repo_id int64
var typeInt int
hasOnlineUrl := 0
if isOnlineUrl {
hasOnlineUrl = 1
}
typeInt = -1
if TypeStr != "" {
//typeInt, _ = strconv.Atoi(TypeStr)
@@ -144,6 +152,7 @@ func ModelSquareData(ctx *context.Context) {
SortType: SortType,
RepoID: repo_id,
NotNeedEmpty: notNeedEmpty,
HasOnlineUrl: hasOnlineUrl,
})
if err != nil {
ctx.ServerError("Cloudbrain", err)
@@ -442,6 +451,7 @@ func ModifyModelReadMe(ctx *context.Context) {
}
if err == nil {
content := ctx.Query("content")
hasOnlineUrl := hasOnlineUrlInReadme(content)
path := Model_prefix + models.AttachmentRelativePath(id) + "/"
if model.Type == models.TypeCloudBrainTwo {
err = storage.PutStringToObs(setting.Bucket, path+README_FILE_NAME, content)
@@ -454,6 +464,9 @@ func ModifyModelReadMe(ctx *context.Context) {
} else {
re["msg"] = "Cannot support the model type=" + fmt.Sprint(model.Type)
}
if hasOnlineUrl {
models.ModifyModelHashOnlineUrl(id, 1)
}
ctx.JSON(200, re)
} else {
re["msg"] = "No such model."
@@ -461,6 +474,21 @@ func ModifyModelReadMe(ctx *context.Context) {
}
}

func hasOnlineUrlInReadme(content string) bool {
re := regexp.MustCompile(`在线体验地址\s+(.+)`)
match := re.FindStringSubmatch(content)
if len(match) > 1 {
url := match[1]
log.Info("find online url=" + url)
re := regexp.MustCompile(`^\s*|\r?\n`)
filteredStr := re.ReplaceAllString(url, "")
if strings.HasPrefix(filteredStr, "http") {
return true
}
}
return false
}

func QueryModelReadMe(ctx *context.Context) {
id := ctx.Query("id")
model, err := models.QueryModelById(id)
@@ -531,3 +559,54 @@ func QueryModelLabel(ctx *context.Context) {
ctx.JSON(200, "")
}
}

func setModelRelateInfo(model *models.AiModelManage) {
online := make([]map[string]interface{}, 0)
othertaskList := make([]map[string]interface{}, 0)
re, err := models.GetCloudBrainByModelId(model.ID)
if err == nil && len(re) > 0 {
for _, task := range re {
if task.JobType == string(models.JobTypeOnlineInference) {
if task.Status == string(models.JobRunning) {
repo, err1 := models.GetRepositoryByID(task.RepoID)
if err1 == nil && !repo.IsPrivate {
onlineTask := make(map[string]interface{})
onlineTask["repoName"] = repo.Name
onlineTask["ownerName"] = repo.OwnerName
onlineTask["repoDisplayName"] = repo.DisplayName()
onlineTask["repoId"] = repo.ID
onlineTask["onlineInferUrl"] = getOnlineInferUrl(task.JobID)
online = append(online, onlineTask)
}
}
} else {
otherTask := make(map[string]interface{})
repo, err1 := models.GetRepositoryByID(task.RepoID)
if err1 == nil && !repo.IsPrivate {
otherTask["repoName"] = repo.Name
otherTask["ownerName"] = repo.OwnerName
otherTask["repoDisplayName"] = repo.DisplayName()
otherTask["jobId"] = task.JobID
otherTask["id"] = task.ID
otherTask["jobType"] = task.JobType
otherTask["type"] = task.Type
otherTask["computeResource"] = task.ComputeResource
otherTask["jobName"] = task.JobName
otherTask["displayJobName"] = task.DisplayJobName
othertaskList = append(othertaskList, otherTask)
}
}
}
}
setModelDataSet(model)
model.OnlineInfo = online
model.UsedCloudbrain = othertaskList
}

func getOnlineInferUrl(jobId string) string {
result, err := grampus.GetNotebookJob(jobId)
if err != nil {
return ""
}
return cloudbrainTask.GrampusNotebookUrl(result)
}

+ 0
- 150
routers/repo/grampus.go View File

@@ -1446,156 +1446,6 @@ func GrampusNotebookShow(ctx *context.Context) {
ctx.Data["PageIsCloudBrain"] = true
ctx.HTML(http.StatusOK, tplGrampusNotebookShow)
return
/*
var task *models.Cloudbrain
task, err := models.GetCloudbrainByIDWithDeleted(ctx.Params(":id"))
if err != nil {
log.Error("GetCloudbrainByID failed:" + err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
return
}
task.ContainerIp = ""

if task.IsNewAITask() {
task, _ = ai_task.UpdateCloudbrain(task)
} else if task.DeletedAt.IsZero() && cloudbrainTask.IsTaskNotStop(task) { //normal record
result, err := grampus.GetNotebookJob(task.JobID)
if err != nil {
log.Error("GetJob failed:" + err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
return
}

if result != nil {
if len(result.JobInfo.Tasks[0].CenterID) == 1 && len(result.JobInfo.Tasks[0].CenterName) == 1 {
task.AiCenter = result.JobInfo.Tasks[0].CenterID[0] + "+" + result.JobInfo.Tasks[0].CenterName[0]
}
oldStatus := task.Status
task.Status = grampus.TransTrainJobStatus(result.JobInfo.Status)
if task.Status != oldStatus || task.Status == models.GrampusStatusRunning {
task.Duration = result.JobInfo.RunSec
if task.Duration < 0 {
task.Duration = 0
}
task.TrainJobDuration = models.ConvertDurationToStr(task.Duration)

if task.StartTime == 0 && result.JobInfo.StartedAt > 0 {
task.StartTime = timeutil.TimeStamp(result.JobInfo.StartedAt)
}
if task.EndTime == 0 && models.IsTrainJobTerminal(task.Status) && task.StartTime > 0 {
task.EndTime = task.StartTime.Add(task.Duration)
}
task.CorrectCreateUnix()
if oldStatus != task.Status {
notification.NotifyChangeCloudbrainStatus(task, oldStatus)
}
}
err = models.UpdateJob(task)
if err != nil {
log.Error("UpdateJob failed:" + err.Error())
}
}
}

if len(task.Parameters) > 0 {
var parameters models.Parameters
err := json.Unmarshal([]byte(task.Parameters), &parameters)
if err != nil {
log.Error("Failed to Unmarshal Parameters: %s (%v)", task.Parameters, err)
ctx.ServerError("system error", err)
return
}

if len(parameters.Parameter) > 0 {
paramTemp := ""
for _, Parameter := range parameters.Parameter {
param := Parameter.Label + " = " + Parameter.Value + "; "
paramTemp = paramTemp + param
}
task.Parameters = paramTemp[:len(paramTemp)-2]
} else {
task.Parameters = ""
}
}
user, err := models.GetUserByID(task.UserID)
if err == nil {
task.User = user
}

prepareSpec4Show(ctx, task)

ctx.Data["task"] = task
ctx.Data["datasetDownload"] = getDatasetDownloadInfo(ctx, task)
ctx.Data["modelDownload"] = getModelDownloadInfo(ctx, task)
ctx.Data["canDownload"] = cloudbrain.CanDownloadJob(ctx, task)
ctx.Data["ai_center"] = cloudbrainService.GetAiCenterShow(task.AiCenter, ctx)
ctx.Data["code_path"] = cloudbrain.CodeMountPath
ctx.Data["dataset_path"] = cloudbrain.DataSetMountPath
ctx.Data["model_path"] = cloudbrain.ModelMountPath
ctx.HTML(http.StatusOK, tplGrampusNotebookShow)
*/
}

func getDatasetDownloadInfo(ctx *context.Context, task *models.Cloudbrain) []*models.DatasetDownload {
datasetDownload := make([]*models.DatasetDownload, 0)
if ctx.IsSigned {
if task.Uuid != "" && task.UserID == ctx.User.ID {
if task.IsGPUTask() {
return GetCloudBrainDataSetInfo(task.Uuid, task.DatasetName, false)
} else {
datasetDownload = GetCloudBrainDataSetInfo(task.Uuid, task.DatasetName, false)
datasetObsUrlList := make([]NotebookDataset, 0)
_ = json.Unmarshal([]byte(task.DataUrl), &datasetObsUrlList)

for _, datasetInfo := range datasetDownload {

for _, datasetObs := range datasetObsUrlList {
log.Info("datasetObsUrl:" + datasetObs.DatasetUrl + "datasetName:" + datasetInfo.DatasetName)
if strings.Contains(datasetObs.DatasetUrl, datasetInfo.DatasetName) {
datasetInfo.DatasetDownloadLink = datasetObs.DatasetUrl
break
}
}

}

}

}
}

return datasetDownload
}

func getModelDownloadInfo(ctx *context.Context, task *models.Cloudbrain) *models.ModelDownload {
var modelDownload models.ModelDownload
if ctx.IsSigned {
if task.ModelName != "" && task.UserID == ctx.User.ID {
if task.IsNPUTask() {
modelDownload = models.ModelDownload{
Name: task.CkptName,
DownloadLink: "",
IsDelete: false,
}
if !modelmanage.HasModelFile(task) {
modelDownload.IsDelete = true
}
datasetObsUrlList := make([]NotebookDataset, 0)
_ = json.Unmarshal([]byte(task.DataUrl), &datasetObsUrlList)
for _, datasetObs := range datasetObsUrlList {
if strings.Contains(datasetObs.DatasetUrl, task.CkptName) {
modelDownload.DownloadLink = datasetObs.DatasetUrl
break
}
}

}

}

}

return &modelDownload
}

func GrampusTrainJobShow(ctx *context.Context) {


+ 1
- 0
routers/response/response_list.go View File

@@ -33,3 +33,4 @@ var DATASET_SELECT_ERROR = &BizError{Code: 2017, DefaultMsg: "Dataset select err
var PARTIAL_DATASETS_NOT_AVAILABLE = &BizError{Code: 2018, DefaultMsg: "There are non-existent or deleted files in the selected dataset file, please select again", TrCode: "cloudbrain.error.partial_datasets_not_available"}
var LOAD_CODE_FAILED = &BizError{Code: 2019, DefaultMsg: "Fail to load code, please check if the right branch is selected.", TrCode: "cloudbrain.load_code_failed"}
var BRANCH_NOT_EXISTS = &BizError{Code: 2020, DefaultMsg: "The branch does not exist", TrCode: "ai_task.branch_not_exists"}
var MODEL_NUM_OVER_LIMIT = &BizError{Code: 2021, DefaultMsg: "The number of models exceeds the limit of 30", TrCode: "repo.debug.manage.model_num_over_limit"}

+ 2
- 2
routers/routes/routes.go View File

@@ -1332,8 +1332,8 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("", reqRepoCloudBrainReader, repo.GrampusTrainJobShow)
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.GrampusStopJob)
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.GrampusTrainJobDel)
m.Get("/model_download", cloudbrain.AdminOrJobCreaterRightForTrain, repo.ModelDownload)
m.Get("/download_multi_model", cloudbrain.AdminOrJobCreaterRightForTrain, repo.MultiModelDownload)
m.Get("/model_download", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.ModelDownload)
m.Get("/download_multi_model", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.MultiModelDownload)
m.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, context.PointAccount(), repo.GrampusTrainJobVersionNew)
m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateGrampusTrainJobForm{}), context.PointAccount(), repo.GrampusTrainJobVersionCreate)
})


+ 23
- 10
services/ai_task_service/cluster/c2net.go View File

@@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"strings"
"time"

"code.gitea.io/gitea/entity"
"code.gitea.io/gitea/manager/client/grampus"
@@ -37,6 +38,7 @@ func (c C2NetClusterAdapter) CreateNoteBook(req entity.CreateNoteBookTaskRequest
}

func (c C2NetClusterAdapter) CreateOnlineInfer(req entity.CreateNoteBookTaskRequest) (*entity.CreateNoteBookTaskResponse, error) {
log.Info("start to CreateOnlineInfer ")
jobResult, err := grampus.CreateNotebookJob(convertOnlineInfer2Grampus(req))
if err != nil {
log.Error("CreateNoteBook failed: %v", err.Error())
@@ -81,9 +83,12 @@ func convertNoteBookReq2Grampus(req entity.CreateNoteBookTaskRequest) models.Cre
codePath = codePath[0:strings.LastIndex(codePath, "/")]
}
}

var commandGpuDebug = "mkdir -p /dataset;! [ -x \"$(command -v jupyter)\" ] && pip install jupyterlab==3 -i https://pypi.tuna.tsinghua.edu.cn/simple;jupyter lab --ServerApp.shutdown_no_activity_timeout=%s --TerminalManager.cull_inactive_timeout=%s --TerminalManager.cull_interval=%s --MappingKernelManager.cull_idle_timeout=%s --MappingKernelManager.cull_interval=%s --MappingKernelManager.cull_connected=True --MappingKernelManager.cull_busy=True --no-browser --ip=0.0.0.0 --allow-root --notebook-dir='%s' --port=$OCTOPUS_NOTEBOOK_PORT --LabApp.token='' --LabApp.allow_origin='*' --LabApp.base_url=$OCTOPUS_NOTEBOOK_BASE_URL;"
command := fmt.Sprintf(commandGpuDebug, setting.CullIdleTimeout, setting.CullIdleTimeout, setting.CullInterval, setting.CullIdleTimeout, setting.CullInterval, codePath)
if models.DCU == req.Tasks[0].Spec.ComputeResource {
command = "cp -r /code /tmp;cp -r /dataset /tmp;cp -r /pretrainmodel /tmp;"
}
//command := fmt.Sprintf(commandGpuDebug, setting.CullIdleTimeout, setting.CullIdleTimeout, setting.CullInterval, setting.CullIdleTimeout, setting.CullInterval, codePath)
// command := "bash && cd /code && unzip master.zip && cd test-export-data && uvicorn train:app --host 0.0.0.0 --port $OCTOPUS_NOTEBOOK_PORT"
if models.NPU == req.Tasks[0].Spec.ComputeResource {
command = ""
@@ -116,7 +121,7 @@ func generateCommand(repoName, bootFile, datasetName string) string {
//prepare
//command := "bash && cd /code && unzip master.zip && cd test-export-data && uvicorn train:app --host 0.0.0.0 --port $OCTOPUS_NOTEBOOK_PORT"
workDir := "/"
command := "pip install gradio fastapi -i https://pypi.tuna.tsinghua.edu.cn/simple;"
command := "mkdir /output;pip install gradio fastapi -i https://pypi.tuna.tsinghua.edu.cn/simple;"
command += "pwd; cd " + workDir + fmt.Sprintf(model_grampus.CommandPrepareScriptGpu)

//unzip code & dataset
@@ -141,7 +146,9 @@ func generateCommand(repoName, bootFile, datasetName string) string {
if strings.HasSuffix(bootonlyfile, ".py") {
bootonlyfile = bootonlyfile[0 : len(bootonlyfile)-3]
}
command += "cd " + copyDatasetPath + ";uvicorn " + bootonlyfile + ":app --host 0.0.0.0 --port $OCTOPUS_NOTEBOOK_PORT "
currentTimeNow := time.Now()
timePostfix := currentTimeNow.Format("20060102_150405")
command += "cd " + copyDatasetPath + ";echo " + timePostfix + " | tee /output/log_" + timePostfix + ".txt; uvicorn " + bootonlyfile + ":app --host 0.0.0.0 --port $OCTOPUS_NOTEBOOK_PORT 2>&1 | tee -a /output/log_" + timePostfix + ".txt;"

log.Info("comand=" + command)
return command
@@ -156,18 +163,23 @@ func getCopyCmd(datasetName, repoName, bootfilepath string) string {
}

func convertNoteBookTask2Grampus(t entity.NoteBookTask, command string) models.GrampusNotebookTask {

code := models.GrampusDataset{}
codeArray := convertContainerArray2Grampus(t.Code)
if codeArray != nil && len(codeArray) > 0 {
code = codeArray[0]
}
output := models.GrampusDataset{}
outputArray := convertContainerArray2Grampus(t.OutPut)
if outputArray != nil && len(outputArray) > 0 {
output = outputArray[0]
}
return models.GrampusNotebookTask{
Name: t.Name,
ResourceSpecId: t.Spec.SourceSpecId,
ImageId: t.ImageId,
ImageUrl: t.ImageUrl,
Datasets: convertContainerArray2Grampus(t.Datasets),
OutPut: output,
Code: code,
AutoStopDuration: t.AutoStopDuration,
Capacity: t.Capacity,
@@ -187,12 +199,13 @@ func convertContainerArray2Grampus(containerDatas []entity.ContainerData) []mode

func convertContainer2Grampus(d entity.ContainerData) models.GrampusDataset {
return models.GrampusDataset{
Name: d.Name,
Bucket: d.Bucket,
EndPoint: d.EndPoint,
ObjectKey: d.ObjectKey,
ContainerPath: d.ContainerPath,
ReadOnly: d.ReadOnly,
Name: d.Name,
Bucket: d.Bucket,
EndPoint: d.EndPoint,
ObjectKey: d.ObjectKey,
ContainerPath: d.ContainerPath,
ReadOnly: d.ReadOnly,
GetBackEndpoint: d.GetBackEndpoint,
}
}



+ 4
- 1
services/ai_task_service/container_builder/code_builder.go View File

@@ -1,6 +1,8 @@
package container_builder

import (
"strings"

"code.gitea.io/gitea/entity"
"code.gitea.io/gitea/modules/cloudbrain"
"code.gitea.io/gitea/modules/log"
@@ -8,7 +10,6 @@ import (
"code.gitea.io/gitea/routers/response"
"code.gitea.io/gitea/services/ai_task_service/context"
"code.gitea.io/gitea/services/ai_task_service/upload"
"strings"
)

type CodeBuilder struct {
@@ -44,8 +45,10 @@ func (b *CodeBuilder) Build(ctx *context.CreationContext) ([]entity.ContainerDat
uploader := upload.SelectUploaderFromStorageType(storageTypes[0])

remoteDir := uploader.GetJobDefaultObjectKeyPrefix(jobName) + cloudbrain.CodeMountPath

//再次调试和在线运行notebook不需要下载、上传代码
if !ctx.Request.IsRestartRequest && !ctx.Request.IsFileNoteBookRequest {
log.Info("start to upload to remoteDir=" + remoteDir + " codeLocalPath=" + codeLocalPath)
if err := DownloadCode(ctx, codeLocalPath, b.Opts.NotArchive); err != nil {
log.Error("downloadZipCode failed, server timed out: %s (%v)", repo.FullName(), err)
return nil, response.LOAD_CODE_FAILED


+ 4
- 2
services/ai_task_service/container_builder/dataset_builder.go View File

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

import (
"strings"

"code.gitea.io/gitea/entity"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/routers/response"
"code.gitea.io/gitea/services/ai_task_service/context"
"strings"
)

type DatasetBuilder struct {
@@ -69,6 +70,7 @@ func (b *DatasetBuilder) Build(ctx *context.CreationContext) ([]entity.Container
ReadOnly: b.Opts.ReadOnly,
ContainerPath: b.Opts.ContainerPath + "/" + name,
RealPath: minioUploader.GetRealPath(objectKey),
Size: datasetInfo.Size,
})

} else {
@@ -80,9 +82,9 @@ func (b *DatasetBuilder) Build(ctx *context.CreationContext) ([]entity.Container
ObjectKey: objectKey,
ReadOnly: b.Opts.ReadOnly,
ContainerPath: b.Opts.ContainerPath + "/" + name,
Size: datasetInfo.Size,
})
}

}
ctx.Request.DatasetNames = datasetNames
return data, nil


+ 19
- 10
services/ai_task_service/container_builder/output_path_builder.go View File

@@ -1,7 +1,10 @@
package container_builder

import (
"fmt"

"code.gitea.io/gitea/entity"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/cloudbrain"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/routers/response"
@@ -26,7 +29,10 @@ func (b *OutputPathBuilder) Build(ctx *context.CreationContext) ([]entity.Contai
if b.Opts.Disable {
return nil, nil
}
log.Info("go here len(storageTypes)=")

storageTypes := b.Opts.AcceptStorageType
log.Info("len=" + fmt.Sprint(len(storageTypes)))
if storageTypes == nil || len(storageTypes) == 0 {
return nil, response.SYSTEM_ERROR
}
@@ -35,18 +41,21 @@ func (b *OutputPathBuilder) Build(ctx *context.CreationContext) ([]entity.Contai

uploader := upload.SelectUploaderFromStorageType(storageTypes[0])
remoteDir := uploader.GetJobDefaultObjectKeyPrefix(jobName) + cloudbrain.ModelMountPath
err := uploader.MKDIR(remoteDir)
if err != nil {
log.Error("MKDIR err.displayJobName = %s err=%v", ctx.Request.DisplayJobName, err)
return nil, response.NewBizError(err)
if ctx.Request.JobType != models.JobTypeOnlineInference {
err := uploader.MKDIR(remoteDir)
if err != nil {
log.Error("MKDIR err.displayJobName = %s err=%v", ctx.Request.DisplayJobName, err)
return nil, response.NewBizError(err)
}
}
return []entity.ContainerData{{
ContainerPath: b.Opts.ContainerPath,
ReadOnly: b.Opts.ReadOnly,
ObjectKey: remoteDir,
RealPath: uploader.GetRealPath(remoteDir),
Bucket: uploader.GetBucket(),
EndPoint: uploader.GetEndpoint(),
ContainerPath: b.Opts.ContainerPath,
ReadOnly: b.Opts.ReadOnly,
ObjectKey: remoteDir,
RealPath: uploader.GetRealPath(remoteDir),
Bucket: uploader.GetBucket(),
EndPoint: uploader.GetEndpoint(),
GetBackEndpoint: uploader.GetEndpoint(),
}}, nil
}



+ 10
- 3
services/ai_task_service/task/grampus_notebook_task.go View File

@@ -1,11 +1,13 @@
package task

import (
"encoding/json"
"strconv"
"strings"

"code.gitea.io/gitea/entity"
"code.gitea.io/gitea/routers/response"
"code.gitea.io/gitea/services/ai_task_service/container_builder"
"strconv"
"strings"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log"
@@ -55,7 +57,7 @@ func (g GrampusNoteBookTaskTemplate) GetConfig(opts entity.GetAITaskConfigOpts)
codePath := "/code"
datasetPath := "/dataset"
pretrainModelPath := "/pretrainmodel"
if opts.ComputeSource == models.NPU {
if opts.ComputeSource == models.NPU || opts.ComputeSource == models.DCU {
return entity.AITaskConfig{
DatasetMaxSize: setting.DebugAttachSize * 1000 * 1000 * 1000,
ContainerSteps: map[entity.ContainerDataType]*entity.ContainerBuildOpts{
@@ -170,6 +172,9 @@ func (g GrampusNoteBookTaskTemplate) CallCreationAPI(ctx *context.CreationContex
},
},
}
reqJson, _ := json.Marshal(req)
log.Info("DCU REQ:" + string(reqJson))

createTime := timeutil.TimeStampNow()
res, err := c.CreateNoteBook(req)
if err != nil {
@@ -229,6 +234,8 @@ func (GrampusNoteBookTaskTemplate) NotifyCreation(ctx *context.CreationContext)
actionType = models.ActionCreateGrampusGCUDebugTask
case models.MLU:
actionType = models.ActionCreateGrampusMLUDebugTask
case models.DCU:
actionType = models.ActionCreateGrampusDCUDebugTask
}
task, err := models.GetCloudbrainByCloudbrainID(ctx.NewCloudbrain.ID)
if err != nil {


+ 7
- 21
services/ai_task_service/task/grampus_online_infer_task.go View File

@@ -44,7 +44,7 @@ func (t GrampusOnlineInferTaskTemplate) Create(ctx *context.CreationContext) (*e
Next(t.CheckBranchExists).
Next(t.CheckModel).
Next(t.InsertCloudbrainRecord4Async).
AsyncNext(t.BuildContainerData, t.CallCreationAPI, t.AfterCallCreationAPI4Async, t.NotifyCreation).
AsyncNextWithErrFun(t.BuildContainerData, t.CallCreationAPI, t.AfterCallCreationAPI4Async, t.NotifyCreation, t.HandleErr4Async).
Operate(ctx)
if err != nil {
log.Error("create GrampusNoteBookTask err.%v", err)
@@ -54,30 +54,11 @@ func (t GrampusOnlineInferTaskTemplate) Create(ctx *context.CreationContext) (*e
}

func (g GrampusOnlineInferTaskTemplate) GetConfig(opts entity.GetAITaskConfigOpts) entity.AITaskConfig {
if opts.ComputeSource == models.NPU {
return entity.AITaskConfig{
DatasetMaxSize: setting.DebugAttachSize * 1000 * 1000 * 1000,
ContainerSteps: map[entity.ContainerDataType]*entity.ContainerBuildOpts{
entity.ContainerCode: {
AcceptStorageType: []entity.StorageType{entity.OBS},
},
entity.ContainerDataset: {
AcceptStorageType: []entity.StorageType{entity.MINIO, entity.OBS},
},
entity.ContainerPreTrainModel: {
AcceptStorageType: []entity.StorageType{entity.MINIO, entity.OBS},
},
},
}
}

containerPrefix := ""
codePath := "/code"
datasetPath := "/dataset"
pretrainModelPath := "/pretrainmodel"
if opts.ComputeSource == models.GCU {
containerPrefix = "/tmp"
}
outputPath := "/output"

return entity.AITaskConfig{
DatasetMaxSize: setting.DebugAttachSize * 1000 * 1000 * 1000,
@@ -97,6 +78,10 @@ func (g GrampusOnlineInferTaskTemplate) GetConfig(opts entity.GetAITaskConfigOpt
ReadOnly: true,
AcceptStorageType: []entity.StorageType{entity.MINIO, entity.OBS},
},
entity.ContainerOutPutPath: {
ContainerPath: containerPrefix + outputPath,
AcceptStorageType: []entity.StorageType{entity.MINIO},
},
},
}
}
@@ -130,6 +115,7 @@ func (g GrampusOnlineInferTaskTemplate) CallCreationAPI(ctx *context.CreationCon
ImageUrl: imageUrl,
Datasets: append(ctx.GetContainerDataArray(entity.ContainerDataset), ctx.GetContainerDataArray(entity.ContainerPreTrainModel)...),
Code: ctx.GetContainerDataArray(entity.ContainerCode),
OutPut: ctx.GetContainerDataArray(entity.ContainerOutPutPath),
AutoStopDuration: -1,
Capacity: setting.Capacity,
CenterID: ctx.Spec.GetAvailableCenterIds(ctx.User.ID, models.JobTypeOnlineInference),


+ 14
- 2
services/ai_task_service/task/opt_handler.go View File

@@ -174,7 +174,11 @@ func (DefaultCreationHandler) CheckDatasetSize(ctx *context.CreationContext) *re

func (DefaultCreationHandler) CheckModel(ctx *context.CreationContext) *response.BizError {
log.Info("Start to CheckModel.displayJobName=%s jobType=%s cluster=%s", ctx.Request.DisplayJobName, ctx.Request.JobType, ctx.Request.Cluster)
if hasModelFileDeleted(ctx.Request.PretrainModelId, ctx.Request.PretrainModelCkptName) { //使用预训练模型训练
if hasModelNumOverLimit(ctx.Request.PretrainModelCkptName) { //检查模型数量是否超出限制
log.Info("CheckModel hasModelNumOverLimit displayJobName=%s jobType=%s cluster=%s", ctx.Request.DisplayJobName, ctx.Request.JobType, ctx.Request.Cluster)
return response.MODEL_NUM_OVER_LIMIT
}
if hasModelFileDeleted(ctx.Request.PretrainModelId, ctx.Request.PretrainModelCkptName) { //检查模型文件是否存在
log.Info("CheckModel hasModelFileDeleted.displayJobName=%s jobType=%s cluster=%s", ctx.Request.DisplayJobName, ctx.Request.JobType, ctx.Request.Cluster)
return response.MODEL_NOT_EXISTS
}
@@ -220,7 +224,7 @@ func (DefaultCreationHandler) CheckOutput4Restart(ctx *context.CreationContext)
if task.Cleared {
return response.RESULT_CLEARD
}
if !task.IsNPUTask() {
if !(task.IsNPUTask() || task.IsDCUTask()) {
if _, err := os.Stat(getTaskOldJobPath(task)); err != nil {
log.Error("Can not find job minio path.displayJobName=%s jobType=%s cluster=%s err=%v", ctx.Request.DisplayJobName, ctx.Request.JobType, ctx.Request.Cluster, err)
return response.RESULT_CLEARD
@@ -261,6 +265,14 @@ func hasModelFileDeleted(modelId, pretrainModelCkptName string) bool {
return false
}

func hasModelNumOverLimit(pretrainModelCkptName string) bool {
CkptNames := strings.Split(pretrainModelCkptName, ";")
if len(CkptNames) > 30 {
return true
}
return false
}

func (DefaultCreationHandler) CheckParam(ctx *context.CreationContext) *response.BizError {
req := ctx.Request
log.Info("Start to CheckParam.displayJobName=%s jobType=%s cluster=%s", req.DisplayJobName, req.JobType, req.Cluster)


+ 13
- 3
services/cloudbrain/cloudbrainTask/notebook.go View File

@@ -1,7 +1,6 @@
package cloudbrainTask

import (
"code.gitea.io/gitea/modules/storage"
"errors"
"fmt"
"io/ioutil"
@@ -11,6 +10,8 @@ import (
"strconv"
"strings"

"code.gitea.io/gitea/modules/storage"

"code.gitea.io/gitea/modules/grampus"
"code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/timeutil"
@@ -874,6 +875,13 @@ func fileExists(gitRepo *git.Repository, path string, branch string) (bool, erro
return true, nil
}

func GrampusNotebookUrl(result *models.GrampusNotebookResponse) string {
if len(result.JobInfo.Tasks) > 0 {
return (result.JobInfo.Tasks[0].Url + "?token=" + result.JobInfo.Tasks[0].Token)
}
return ""
}

func GrampusNotebookDebug(ctx *context.Context) error {

result, err := grampus.GetNotebookJob(ctx.Cloudbrain.JobID)
@@ -882,8 +890,7 @@ func GrampusNotebookDebug(ctx *context.Context) error {
return err
}
if len(result.JobInfo.Tasks) > 0 {

ctx.Redirect(result.JobInfo.Tasks[0].Url + "?token=" + result.JobInfo.Tasks[0].Token)
ctx.Redirect(GrampusNotebookUrl(result))
return nil
}
return fmt.Errorf("Can not find the job.")
@@ -1005,6 +1012,9 @@ func GrampusNotebookRestart(ctx *context.Context) {
} else if task.ComputeResource == models.GCUResource {
computeSourceSimple = models.GCU
action = models.ActionCreateGrampusGCUDebugTask
} else if task.ComputeResource == models.DCU {
computeSourceSimple = models.DCU
action = models.ActionCreateGrampusDCUDebugTask
}

spec, err = resource.GetAndCheckSpec(ctx.User.ID, oldSpec.ID, models.FindSpecsOptions{


+ 11
- 5
services/cloudbrain/util.go View File

@@ -34,9 +34,8 @@ func getAiCenterAndNameInfo() map[string]*setting.C2NetSequenceInfo {

func GetAiCenterShow(aiCenter string, ctx *context.Context) string {
aiCenterInfo := strings.Split(aiCenter, "+")
aiCenterAndNameInfo := getAiCenterAndNameInfo()
if len(aiCenterInfo) == 2 {
aiCenterAndNameInfo := getAiCenterAndNameInfo()
if aiCenterAndNameInfo != nil {
if info, ok := aiCenterAndNameInfo[aiCenterInfo[0]]; ok {
if ctx.Language() == "zh-CN" {
@@ -51,11 +50,18 @@ func GetAiCenterShow(aiCenter string, ctx *context.Context) string {
} else {
return aiCenterInfo[1]
}

} else {
if aiCenterAndNameInfo != nil {
if info, ok := aiCenterAndNameInfo[aiCenterInfo[0]]; ok {
if ctx.Language() == "zh-CN" {
return info.Content
} else {
return info.ContentEN
}
}
}
}

return ""

}

func GetDisplayJobName(username string) string {


+ 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, 32, 33, 35, 39, 40, 41, 42, 43, 44, 45}
var opTypes = []int{1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 39, 40, 41, 42, 43, 44, 45, 46}

type ClientsManager struct {
Clients *orderedmap.OrderedMap


+ 1
- 0
templates/admin/cloudbrain/search.tmpl View File

@@ -49,6 +49,7 @@
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=NPU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="NPU">NPU</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=GCU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="GCU">GCU</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=MLU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="MLU">MLU</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=DCU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="DCU">DCU</a>
</div>
</div>
<div class="ui selection dropdown" style="min-width: 10em;min-height:2.6em;border-radius: .28571429rem;margin-right: 1em;padding: .67em 3.2em .7em 1em;">


+ 1
- 0
templates/admin/cloudbrain/search_dashboard.tmpl View File

@@ -60,6 +60,7 @@
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=NPU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="NPU">NPU</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=GCU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="GCU">GCU</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=MLU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="MLU">MLU</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=DCU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="DCU">DCU</a>
</div>
</div>
<div class="ui selection dropdown" style="min-width: 10em;min-height:2.6em;border-radius: .28571429rem;margin-right: 1em;padding: .67em 3.2em .7em 1em;">


+ 2
- 3
templates/base/footer.tmpl View File

@@ -51,9 +51,8 @@
<!--script src="https://www.jq22.com/jquery/jquery-1.10.2.js?v={{MD5 AppVer}}"></script-->
<script src="/rotation3D/vue-2.6.10.min.js?v={{MD5 AppVer}}"></script>
<script src="/rotation3D/rotation3D.js?v={{MD5 AppVer}}"></script>
<script>
console.log("a")
var jobTask={};
<script>
var jobTask={};
var html =document.documentElement;
var lang = html.attributes["lang"]
var isZh = true;


+ 5
- 2
templates/custom/home/home_screen_map.tmpl View File

@@ -1,5 +1,5 @@
<div style="position: relative;margin-bottom: -80px;">
<div class="ui center am-pt-30 am-pb-30" style="position:absolute;z-index:5;padding-bottom:2.5rem !important;width: 100%;">
<div class="ui center am-pt-30 am-pb-30" style="position:absolute;z-index:5;padding-bottom:2.5rem !important;left: 50%;transform: translate(-50%, 0%);">
<h2>{{.i18n.Tr "home.c2net_title"}}</h2>
<p><span class="ui text grey">{{.i18n.Tr "home.c2net_desc"}}</p>
<div style="display:flex;align-items:center;justify-content:center;">
@@ -9,5 +9,8 @@
</div>
<div id="__vue-root"></div>
</div>
<script type="text/javascript" src="https://api.map.baidu.com/getscript?v=3.0&ak=MSRIap3Scat9FPicR8TekAsA8uyvaWSE"></script>
<script>
window.HOST_TYPE = "2";
</script>
<script type="text/javascript" src="https://api.map.baidu.com/getscript?v=3.0&ak=MSRIap3Scat9FPicR8TekAsA8uyvaWSE&s=1"></script>
<script src="{{StaticUrlPrefix}}/js/vp-screen-map.js?v={{MD5 AppVer}}"></script>

+ 8
- 0
templates/user/dashboard/feeds.tmpl View File

@@ -125,6 +125,12 @@
{{$.i18n.Tr "action.task_c2ent_mludebugjob" .GetRepoLink (Printf "%d" .Cloudbrain.ID) .RefName | Str2html}}
{{else}}
{{$.i18n.Tr "action.task_c2ent_mludebugjob" "" "" "" | Str2html}}<span style="">{{.RefName}}{{$.i18n.Tr "repo.issues.deleted_milestone"}}</span>
{{end}}
{{else if eq .GetOpType 46}}
{{if .Cloudbrain}}
{{$.i18n.Tr "action.task_c2net_dcudebugjob" .GetRepoLink (Printf "%d" .Cloudbrain.ID) .RefName | Str2html}}
{{else}}
{{$.i18n.Tr "action.task_c2net_dcudebugjob" "" "" "" | Str2html}}<span style="">{{.RefName}}{{$.i18n.Tr "repo.issues.deleted_milestone"}}</span>
{{end}}
{{else if eq .GetOpType 44}}
{{$.i18n.Tr "action.task_c2ent_mlutrainjob" .GetRepoLink .Content .RefName | Str2html}}
@@ -181,6 +187,8 @@
<span class="text grey"><i class="ri-voice-recognition-line icon big"></i></span>
{{else if eq .GetOpType 45}}
<span class="text grey"><i class="ri-voice-recognition-line icon big"></i></span>
{{else if eq .GetOpType 46}}
<span class="text grey"><i class="ri-voice-recognition-line icon big"></i></span>
{{else if eq .GetOpType 27}}
<span class="text grey"><i class="ri-character-recognition-line icon big"></i></span>
{{else if eq .GetOpType 28}}


+ 54
- 55
web_src/js/router/index.js View File

@@ -1,12 +1,12 @@
import Vue from 'vue'
import Router from 'vue-router'
import DataAnalysis from '../components/DataAnalysis.vue'
import ProAnalysis from '../components/ProAnalysis.vue'
import ProTrend from '../components/ProTrend.vue'
import UserTrend from '../components/UserTrend.vue'
import UserAnalysis from '../components/UserAnalysis.vue'
import BrainAnalysis from '../components/BrainAnalysis.vue'
import Overview from '../components/Overview.vue'
// import DataAnalysis from '../components/DataAnalysis.vue'
// import ProAnalysis from '../components/ProAnalysis.vue'
// import ProTrend from '../components/ProTrend.vue'
// import UserTrend from '../components/UserTrend.vue'
// import UserAnalysis from '../components/UserAnalysis.vue'
// import BrainAnalysis from '../components/BrainAnalysis.vue'
// import Overview from '../components/Overview.vue'
import IdeProject from '../components/IdeProject.vue'

const originalPush = Router.prototype.push
@@ -17,54 +17,53 @@ Router.prototype.push = function push(location) {
Vue.use(Router)

export default new Router({
mode: 'history',
base: '/', //添加根目录
scrollBehavior: () => ({ y: 0 }),
routes:[
{
path:'/ide/project',
name:'ide',
component:IdeProject,
},
{
path:'/explore/data_analysis/',redirect:'/explore/data_analysis/ProAnalysis',
name:'ProAnalysis',
component:ProAnalysis,
},

{
path:'/explore/data_analysis/Overview',
name:'Overview',
component:Overview,
},
{
path:'/explore/data_analysis/ProTrend',
name:'ProTrend',
component:ProTrend,
},
{
path:'/explore/data_analysis/ProAnalysis',
name:'ProAnalysis',
component:ProAnalysis,
},
{
path:'/explore/data_analysis/UserAnalysis',
name:'UserAnalysis',
component:UserAnalysis,
},
{
path:'/explore/data_analysis/UserTrend',
name:'UserTrend',
component:UserTrend,
},

{
path:'/explore/data_analysis/BrainAnalysis',
name:'BrainAnalysis',
component:BrainAnalysis,
},

],
mode: 'history',
base: '/', //添加根目录
scrollBehavior: () => ({ y: 0 }),
routes: [
{
path: '/ide/project',
name: 'ide',
component: IdeProject,
},
/*
{
path:'/explore/data_analysis/',redirect:'/explore/data_analysis/ProAnalysis',
name:'ProAnalysis',
component:ProAnalysis,
},

{
path:'/explore/data_analysis/Overview',
name:'Overview',
component:Overview,
},
{
path:'/explore/data_analysis/ProTrend',
name:'ProTrend',
component:ProTrend,
},
{
path:'/explore/data_analysis/ProAnalysis',
name:'ProAnalysis',
component:ProAnalysis,
},
{
path:'/explore/data_analysis/UserAnalysis',
name:'UserAnalysis',
component:UserAnalysis,
},
{
path:'/explore/data_analysis/UserTrend',
name:'UserTrend',
component:UserTrend,
},

{
path:'/explore/data_analysis/BrainAnalysis',
name:'BrainAnalysis',
component:BrainAnalysis,
},
*/
],
})

+ 67
- 3
web_src/vuepages/apis/modules/cloudbrain.js View File

@@ -103,12 +103,27 @@ export const getAiTaskOperationProfile = (params) => {
}

// 查询任务结果下载
// params: version_name, parentDir
// params: id, parent_dir, node_id
export const getAiTaskOutputResult = (params) => {
return service({
url: `/api/v1/repos/Itx003/openi-notebook/modelarts/train-job/159191/model_list`,
url: `/api/v1/${params.repoOwnerName}/${params.repoName}/ai_task/output`,
method: 'get',
params: { ...params },
params: {
id: params.id,
parent_dir: params.parent_dir,
},
});
}

// params: id, parent_dir, node_id
export const getAiTaskOutputResult1 = (params) => {
return service({
url: `/api/v1/repos/${params.repoOwnerName}/${params.repoName}/cloudbrain/train-job/${params.id}/model_list`,
method: 'get',
params: {
version_name: '',
parentDir: params.parent_dir,
},
});
}

@@ -193,3 +208,52 @@ export const setAiTaskExportDataset = (data) => {
data: data,
});
}

// 下载训练任务的某一个结果文件
// params-id,file_name,parent_dir
export const downLoadAiTaskResultFile = (params) => {
return service({
url: `/api/v1/${params.repoOwnerName}/${params.repoName}/ai_task/output/download`,
method: 'get',
params: {
id: params.id,
file_name: params.file_name,
parent_dir: params.parent_dir,
},
}).then(res => {
downLoadFileHandler(res);
return res;
});
}

// 下载训练任务的所有结果文件
// params-id
export const downLoadAiTaskResultFileAll = (params) => {
return service({
url: `/api/v1/${params.repoOwnerName}/${params.repoName}/ai_task/output/download/all`,
method: 'get',
params: { id: params.id, },
}).then(res => {
downLoadFileHandler(res);
return res;
});
}

export const setAiTaskOutputReschedule = (data) => {
return service({
url: `/api/v1/${data.repoOwnerName}/${data.repoName}/ai_task/output/reschedule`,
method: 'post',
data: { id: data.id, },
params: {},
});
}


export const setAiTaskOutputReschedule1 = (data) => {
return service({
url: `/api/v1/${data.repoOwnerName}/${data.repoName}//cloudbrain/train-job/${data.id}/model/reschedule`,
method: 'post',
data: { },
params: {},
});
}

+ 12
- 0
web_src/vuepages/apis/modules/modelsquare.js View File

@@ -42,3 +42,15 @@ export const setModelRecommend = (data) => {
data: Qs.stringify(data),
});
}


// 调试模型
// data: repoId 为需要fork得项目名称
export const createModelNotebook = (data) => {
return service({
url: "/api/v1/model_notebook/create",
method: "post",
data,
params: {},
});
};

+ 16
- 3
web_src/vuepages/components/cloudbrain/ModelSelect.vue View File

@@ -113,7 +113,7 @@

<script>
import { getModelList } from '~/apis/modules/modelsquare';
import { getUrlSearchParams } from '~/utils';
// const supportCheckPointFileExt = ["ckpt", "pb", "h5", "json", "pkl", "pth", "t7", "pdparams", "onnx", "pbtxt", "keras", "mlmodel", "cfg", "pt"];
export default {
name: "ModelSelect",
@@ -162,6 +162,13 @@ export default {
newVal = newVal === undefined ? [] : newVal;
this.selectList = [...newVal];
}
},
dlgSearchValue:{
handler(newVal) {
if(newVal===''){
this.searchModelData();
}
}
}
},
methods: {
@@ -282,7 +289,7 @@ export default {
},
onTreeCheckChange(data) {
if (this.multiple) {
this.maxCount = Infinity;
this.maxCount = 30;
}
if (
this.dlgSelectedModelList.length === 0 ||
@@ -345,7 +352,13 @@ export default {
},
},
beforeMount() { },
mounted() { },
mounted() {
const urlParams = getUrlSearchParams();
if(urlParams.model_name){
this.dlgActiveName = 'third'
this.dlgSearchValue = urlParams.model_name
}
},
};
</script>



+ 25
- 4
web_src/vuepages/components/cloudbrain/SpecSelect.vue View File

@@ -2,7 +2,12 @@
<div class="form-row">
<div class="title"><span :class="required ? 'required' : ''">{{ $t('cloudbrainObj.resourceSpec') }}</span></div>
<div class="content" :class="errStatus ? 'error' : ''">
<div class="spec-info">
<div class="spec-list-c" v-if="!list.length">
<div class="spec-item-placeholder" style="color: red;">
{{ $t('specObj.no_use_resource') }}
</div>
</div>
<div v-else class="spec-info">
<el-select class="spec-sel field-input" :class="configs.showPoint ? 'spec-show-point' : ''" v-model="spec"
:placeholder="$t('cloudbrainObj.specPlaceholder')" @change="changeSpec">
<div slot="prefix" class="spec-sel-icon spec-op-icon">
@@ -141,7 +146,8 @@ export default {
return this.list.filter(item => item.id == this.spec)[0];
},
},
beforeMount() { }
beforeMount() {
}
};
</script>

@@ -153,7 +159,21 @@ export default {
flex: inherit;
width: 50%;
margin-right: 5px;

.spec-list-c{
min-height: 37.6px;
border-radius: 4px;
border: 1px solid #DCDFE6;
box-sizing: border-box;
color: #606266;
padding: 4px 15px;
.spec-item-placeholder {
height: 27px;
line-height: 27px;
color: rgba(0, 0, 0, 0.4);
opacity: 0.45 !important;
font-size: 14px;
}
}
.spec-info {
flex: 1;

@@ -263,7 +283,8 @@ export default {

.NPU_icon,
.GCU_icon,
.MLU_icon {
.MLU_icon,
.DCU_icon {
color: white;
width: 22px;
height: 22px;


+ 176
- 48
web_src/vuepages/components/cloudbrain/details/ResultDownload.vue View File

@@ -1,8 +1,8 @@
<template>
<div class="item-container">
<div class="content">
<div class="files-info">
<div class="top">
<div class="files-info" v-loading="loading">
<div class="top" v-if="isTaskTerminal === true && resultStatus == 0">
<div style="width:100%;margin-right:20px;">
<div class="title files-path-c">
<div class="file-path" v-for="(item, index) in filePath">
@@ -15,13 +15,14 @@
</div>
</div>
<div class="right-btn-c">
<a class="download-btn" download :href="``">
<i class="ri-download-cloud-2-line"></i> {{ `全部结果下载` }}
<a class="download-btn" :class="!canDownload ? 'disabled-download' : ''" :href="`/${data.task.repoOwnerName}/${data.task.repoName}/grampus/train-job/${data.task.job_id}/download_multi_model?version_name=`"
>
<i class="ri-download-cloud-2-line"></i> {{ this.$t('cloudbrainObj.allResultDownload') }}
</a>
</div>
</div>
<div class="table-container">
<el-table ref="tableRef" :data="filesList" row-key="sn" style="width: 100%" v-loading="loading">
<div class="table-container" v-if="isTaskTerminal === true && resultStatus == 0">
<el-table ref="tableRef" :data="filesList" row-key="sn" style="width: 100%">
<el-table-column column-key="FileName" prop="FileName" sortable
:sort-method="(a, b) => a.FileName.toLocaleLowerCase().localeCompare(b.FileName.toLocaleLowerCase())"
:label="$t('modelManage.fileName')" align="left" header-align="left">
@@ -33,8 +34,8 @@
<span>{{ scope.row.FileName }}</span>
</div>
</a>
<a v-else :class="!canDownload ? 'disabled-download' : ''"
:href="canDownload ? `javascript:void 0;` : 'javascript:;'">
<a v-else :class="!canDownload ? 'disabled-download' : ''"
:href="`/${data.task.repoOwnerName}/${data.task.repoName}/grampus/train-job/${data.task.job_id}/model_download?version_name=&file_name=${scope.row.FileName}&parent_dir=${scope.row.ParenDir}`">
<div class="fitted" :title="scope.row.FileName">
<i class="icon file" width="16" height="16" aria-hidden="true"></i>
<span>{{ scope.row.FileName }}</span>
@@ -44,13 +45,41 @@
</template>
</el-table-column>
<el-table-column column-key="SizeShow" prop="SizeShow" sortable :sort-method="(a, b) => a.Size - b.Size"
:label="$t('modelManage.fileSize')" align="center" header-align="center" width="200">
:label="$t('modelManage.fileSize')" align="left" header-align="left" width="200">
</el-table-column>
<el-table-column column-key="ModTime" prop="ModTime" sortable
:sort-method="(a, b) => a.ModTimeNum - b.ModTimeNum" :label="$t('modelManage.updateTime')" align="center"
header-align="center" width="200">
</el-table-column>
</el-table>
<div class="max-count-tips"><i class="el-icon-warning-outline"></i>{{
this.$t('cloudbrainObj.downloadDisplayMaxCountTips') }}</div>
</div>
<div class="status-tips" v-if="isTaskTerminal === false">
<div>
<i class="ri-time-line"></i>
<span>{{ this.$t('cloudbrainObj.task_not_finished') }}</span>
</div>
</div>
<div class="status-tips" v-else-if="isTaskTerminal === true && resultStatus != 0">
<div v-if="resultStatus == 1">
<i class="ri-loader-2-line rotating"></i>
<span>{{ this.$t('cloudbrainObj.file_sync_ing') }}</span>
</div>
<div v-if="resultStatus == 2">
<i class="ri-alert-line"></i>
<span>{{ this.$t('cloudbrainObj.file_sync_fail') }}</span>
<a v-if="canReschedule" class="retry" href="javascript:void(0)" @click="retry">{{
this.$t('cloudbrainObj.retrieve_results') }}</a>
</div>
<div v-if="resultStatus == 3">
<i class="ri-time-line"></i>
<span>{{ this.$t('cloudbrainObj.file_sync_wait') }}</span>
</div>
<div v-if="resultStatus == 4">
<i class="ri-emotion-unhappy-line"></i>
<span>{{ this.$t('cloudbrainObj.no_file_to_download') }}</span>
</div>
</div>
</div>
</div>
@@ -58,7 +87,10 @@
</template>

<script>
import { getAiTaskOutputResult } from '~/apis/modules/cloudbrain';
import {
getAiTaskOutputResult, setAiTaskOutputReschedule,
getAiTaskOutputResult1,setAiTaskOutputReschedule1,
} from '~/apis/modules/cloudbrain';
import { transFileSize } from '~/utils';
import { formatDate } from 'element-ui/lib/utils/date-util';

@@ -70,45 +102,64 @@ export default {
},
data() {
return {
version: 'V0001',
filesList: [],
filePath: [],
canDownload: true,
loading: false,
isTaskTerminal: null,
canDownload: true,
canReschedule: false,
resultStatus: -2,
resultPath: '',
};
},
methods: {
getDirFiles(dir) {
dir = dir.length ? dir.slice(1) : '';
getAiTaskOutputResult({
version_name: this.version,
parentDir: dir,
const task = this.data.task;
this.loading = true;
getAiTaskOutputResult1({
repoOwnerName: task.repoOwnerName,
repoName: task.repoName,
id: task.job_id,
parent_dir: dir,
}).then(res => {
this.loading = false;
res = res.data;
if (res.StatusOK == 0) { // 成功 0
/*** if (res.code == 0 && res.data && res.data.output) {
const data = res.data.output;
this.isTaskTerminal = data.is_task_terminal;
this.canDownload = data.can_download;
this.canReschedule = data.can_reschedule;
this.resultStatus = data.status;
this.resultPath = data.path;
if (this.resultStatus == 0) { // 成功 0
const list = data.file_list || [];
list.forEach(item => {
item.SizeShow = item.IsDir ? '' : transFileSize(item.Size);
item.ModTimeNum = new Date(item.ModTime).getTime();
});
list.sort((a, b) => a.FileName.localeCompare(b.FileName));
list.sort((a, b) => b.ModTimeNum - a.ModTimeNum);
this.filesList = list;
this.$refs['tableRef']?.clearSort();
}
} ***/
if(res.StatusOK == 0){
this.canDownload = res.CanDownload
this.isTaskTerminal = true
this.resultStatus = res.StatusOK
const list = res.Dirs || [];
list.forEach(item => {
item.SizeShow = item.IsDir ? '' : transFileSize(item.Size);
item.ModTimeNum = new Date(item.ModTime).getTime();
});
list.sort((a, b) => a.FileName.localeCompare(b.FileName));
list.sort((a, b) => b.ModTimeNum - a.ModTimeNum);
this.filesList = list;
this.$refs['tableRef']?.clearSort();
} else if (res.StatusOK == -1) { // 任务未结束 -1

} else if (res.StatusOK == 1) { // 处理中 1

} else if (res.StatusOK == 2) { // 失败 2

} else if (res.StatusOK == 3) { // 等待同步 3

} else if (res.StatusOK == 4) { // 无文件 4

} else {

list.forEach(item => {
item.SizeShow = item.IsDir ? '' : transFileSize(item.Size);
item.ModTimeNum = new Date(item.ModTime).getTime();
});
list.sort((a, b) => a.FileName.localeCompare(b.FileName));
list.sort((a, b) => b.ModTimeNum - a.ModTimeNum);
this.filesList = list;
this.$refs['tableRef']?.clearSort();
}
}).catch(err => {
this.loading = false;
console.log(err);
});
},
@@ -126,13 +177,37 @@ export default {
const dir = this.filePath.map((item) => item.path).join('/');
this.getDirFiles(dir);
},
retry() {
const task = this.data.task;
setAiTaskOutputReschedule1({
repoOwnerName: task.repoOwnerName,
repoName: task.repoName,
id: task.job_id,
}).then(res => {
res = res.data;
if (res.code == 0) {
this.refresh();
} else {
this.$message({
type: 'error',
message: res.msg,
});
}
}).catch(err => {
console.log(err);
})
},
refresh() {
// console.log('ResorceUseage refresh');
// console.log(this.configs);
// console.log(this.data);
this.filePath = [{ label: 'V0001', path: '' }];
const task = this.data.task;
this.filesList = [];
this.getDirFiles('');
const version = task.current_version_name;
if (version) {
this.filePath = [{ label: version, path: `/${version}` }];
this.getDirFiles(`/${version}`);
} else {
this.filePath = [{ label: 'result', path: '' }];
this.getDirFiles('');
}
}
},
beforeMount() { }
@@ -144,6 +219,8 @@ export default {
margin-bottom: 20px;

.files-info {
min-height: 220px;

.top {
display: flex;
align-items: center;
@@ -225,14 +302,65 @@ export default {
}
}

.disabled-download {
cursor: default;
pointer-events: none;
color: rgba(0, 0, 0, .6) !important;
opacity: .45 !important;
}
}
}
.disabled-download {
cursor: default;
pointer-events: none;
color: rgba(0, 0, 0, .6) !important;
opacity: .45 !important;
}
.max-count-tips {
display: flex;
align-items: center;
justify-content: end;
color: #f2711c;
font-size: 14px;
margin-top: 10px;

i {
margin-right: 5px;
}
}
}
}
</style>

.status-tips {
height: 200px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
color: rgb(16, 16, 16);

div {
display: flex;
justify-content: center;
align-items: center;

i {
margin-right: 5px;
}
}

.retry {
text-decoration: underline;
margin-left: 0.5rem
}
}

@keyframes rotation {
from {
transform: rotate(0deg);
}

to {
transform: rotate(360deg);
}
}

.rotating {
animation: rotation 4s linear infinite;
}
</style>

+ 2
- 2
web_src/vuepages/const/index.js View File

@@ -11,8 +11,8 @@ export const JOB_TYPE = [{ k: 'DEBUG', v: i18n.t('debugTask') }, { k: 'TRAIN', v
// 资源管理
export const CLUSTERS = [{ k: 'OpenI', v: i18n.t('resourcesManagement.OpenI') }, { k: 'C2Net', v: i18n.t('resourcesManagement.C2Net') }];
export const AI_CENTER = [{ k: 'OpenIOne', v: i18n.t('resourcesManagement.OpenIOne') }, { k: 'OpenITwo', v: i18n.t('resourcesManagement.OpenITwo') }, { k: 'OpenIChengdu', v: i18n.t('resourcesManagement.OpenIChengdu') }, { k: 'pclcci', v: i18n.t('resourcesManagement.pclcci') }, { k: 'hefei', v: i18n.t('resourcesManagement.hefeiCenter') }, { k: 'xuchang', v: i18n.t('resourcesManagement.xuchangCenter') }];
export const COMPUTER_RESOURCES = [{ k: 'GPU', v: 'GPU' }, { k: 'NPU', v: 'NPU' }, { k: 'GCU', v: 'GCU' }, { k: 'MLU', v: 'MLU' }];
export const ACC_CARD_TYPE = [{ k: 'T4', v: 'T4' }, { k: 'A100', v: 'A100' }, { k: 'V100', v: 'V100' }, { k: 'ASCEND910', v: 'Ascend 910' }, { k: 'MLU270', v: 'MLU270' }, { k: 'MLU290', v: 'MLU290' }, { k: 'RTX3080', v: 'RTX3080' }, { k: 'ENFLAME-T20', v: 'ENFLAME-T20' }];
export const COMPUTER_RESOURCES = [{ k: 'GPU', v: 'GPU' }, { k: 'NPU', v: 'NPU' }, { k: 'GCU', v: 'GCU' }, { k: 'MLU', v: 'MLU' }, { k: 'DCU', v: 'DCU' }];
export const ACC_CARD_TYPE = [{ k: 'T4', v: 'T4' }, { k: 'A100', v: 'A100' }, { k: 'V100', v: 'V100' }, { k: 'ASCEND910', v: 'Ascend 910' }, { k: 'MLU270', v: 'MLU270' }, { k: 'MLU290', v: 'MLU290' }, { k: 'RTX3080', v: 'RTX3080' }, { k: 'ENFLAME-T20', v: 'ENFLAME-T20' }, { k: 'DCU', v: 'DCU' }];
export const SPECIFICATION_STATUS = [{ k: '1', v: i18n.t('resourcesManagement.willOnShelf') }, { k: '2', v: i18n.t('resourcesManagement.onShelf') }, { k: '3', v: i18n.t('resourcesManagement.offShelf') }];

// 模型


+ 18
- 1
web_src/vuepages/langs/config/en-US.js View File

@@ -343,6 +343,13 @@ const en = {
derivedModel: 'Derived Model',
refRepository: 'Reference repository',
modelDownloadAll: 'Download All',
otherOnline: 'Other online url',
trainUsedDataList: 'The dataset used for the model',
modelUseTaskList: 'The task used for the model',
forkModelSuccess: 'The model content has been copied and forked successfully!',
debugModel: 'Debug Model',
onlineInference: 'online Inference',
deleted:'Deleted',
},
repos: {
activeOrganization: 'Active Organization',
@@ -413,7 +420,8 @@ const en = {
model_search: 'Search model',
model_square_empty: 'No Models',
model_suport_file_tips: 'The supported format of the model file is [ckpt, pb, h5, json, pkl, pth, t7, pdparams, onnx, pbtxt, keras, mlmodel, cfg, pt]',
boot_file_helper: 'The startup file is the entry file that your program executes, and it must be a file ending in .py'
boot_file_helper: 'The startup file is the entry file that your program executes, and it must be a file ending in .py',
can_online_infer: 'Online',
},
datasetObj: {
dataset_label: "Dataset",
@@ -436,6 +444,7 @@ const en = {
},
specObj: {
resSelectTips: 'The "resource specification" is the hardware you use to run the task. In order for more people to use the resources of this platform, please select according to your actual needs',
no_use_resource: 'No resources available',
},
datasets: {
computer_vision: "computer vision",
@@ -581,6 +590,14 @@ const en = {
tabTitInference: 'Inference Job',
tabTitBenchmark: 'Model Evaluation',
tabTitOnlineInference: 'Online Inference',
allResultDownload: 'All result download',
downloadDisplayMaxCountTips: 'Display up to 100 files or folders in a single directory',
file_sync_ing: "File synchronization in progress, please wait",
file_sync_ing: "File synchronization in waitting, please wait",
file_sync_fail: "File synchronization failed",
no_file_to_download: "No files can be downloaded",
task_not_finished: "Task not finished yet, please wait",
retrieve_results: "Retrieve results",

},
}


+ 18
- 1
web_src/vuepages/langs/config/zh-CN.js View File

@@ -359,6 +359,13 @@ const zh = {
derivedModel: '衍生模型',
refRepository: '引用项目',
modelDownloadAll: '下载全部模型文件',
otherOnline: '其他在线体验入口',
trainUsedDataList: '训练该模型使用的数据集',
modelUseTaskList: '使用该模型的任务',
forkModelSuccess: '模型内容复制完成,fork成功!',
debugModel: '调试模型',
onlineInference: '在线体验',
deleted:'已删除',
},
repos: {
activeOrganization: '活跃组织',
@@ -429,7 +436,8 @@ const zh = {
model_search: '搜索模型',
model_square_empty: '空荡荡的,什么都没有',
model_suport_file_tips: '模型文件支持的格式为 [ckpt, pb, h5, json, pkl, pth, t7, pdparams, onnx, pbtxt, keras, mlmodel, cfg, pt]',
boot_file_helper: '启动文件是您程序执行的入口文件,必须是以.py结尾的文件。比如train.py、main.py、example/train.py、case/main.py。'
boot_file_helper: '启动文件是您程序执行的入口文件,必须是以.py结尾的文件。比如train.py、main.py、example/train.py、case/main.py。',
can_online_infer: '可体验',
},
datasetObj: {
dataset_label: "数据集",
@@ -452,6 +460,7 @@ const zh = {
},
specObj: {
resSelectTips: '「资源规格」是您运行该任务使用的硬件,为了更多人能够使用本平台的资源,请按照您的实际需求进行选择。',
no_use_resource: '暂无可用资源'
},
datasets: {
computer_vision: "计算机视觉",
@@ -597,6 +606,14 @@ const zh = {
tabTitInference: '推理任务',
tabTitBenchmark: '评测任务',
tabTitOnlineInference: '在线推理',
allResultDownload: '全部结果下载',
downloadDisplayMaxCountTips: '单目录下最多显示100个文件或文件夹',
file_sync_ing: "文件同步中,请稍侯",
file_sync_wait: "文件等待同步中,请稍侯",
file_sync_fail: "文件同步失败",
no_file_to_download: "没有文件可以下载,稍后再来看看",
task_not_finished: "任务还未结束,稍后再来看看",
retrieve_results: "重新获取结果",

},
}


+ 48
- 2
web_src/vuepages/pages/cloudbrain/configs.js View File

@@ -3,7 +3,7 @@ import { JOB_TYPE } from '~/const';
import { getListValueWithKey } from '~/utils';

const CLUSTERS = [{ k: 'OpenI', v: i18n.t('cloudbrainObj.openi') }, { k: 'C2Net', v: i18n.t('cloudbrainObj.c2net') }];
const COMPUTER_RESOURCES = [{ k: 'GPU', v: 'CPU/GPU' }, { k: 'NPU', v: 'Ascend NPU' }, { k: 'GCU', v: 'GCU' }, { k: 'MLU', v: 'MLU' }];
const COMPUTER_RESOURCES = [{ k: 'GPU', v: 'CPU/GPU' }, { k: 'NPU', v: 'Ascend NPU' }, { k: 'GCU', v: 'GCU' }, { k: 'MLU', v: 'MLU' },{ k: 'DCU', v: 'DCU' }];

const TIPS = {
'1': '项目代码存储在 <strong style="color:#010101">/code</strong> 中,数据集存储在 <strong style="color:#010101">/dataset</strong> 中,选择的模型存储在 <strong style="color:#010101">/pretrainmodel</strong> 中,调试输出请存储在 <strong style="color:#010101">/model</strong> 中以供后续下载。',
@@ -65,7 +65,7 @@ export const CreatePageConfigs = {
}],
'C2Net': [{
url: 'grampus/notebook/create?type=0',
computerResouces: ['GPU', 'NPU', 'GCU', 'MLU'],
computerResouces: ['GPU', 'NPU', 'GCU', 'MLU', 'DCU'],
'GPU': [{
url: 'grampus/notebook/create?type=0',
clusterType: 'C2Net',
@@ -135,6 +135,24 @@ export const CreatePageConfigs = {
spec: { required: true },
},
}],
'DCU': [{
url: 'grampus/notebook/create?type=4',
clusterType: 'C2Net',
tips2: i18n.t('cloudbrainObj.pathTips3', {
code: '/tmp/code',
dataset: '/tmp/dataset',
model: '/tmp/pretrainmodel',
}),
form: {
taskName: { required: true, },
taskDescr: { required: false, },
branchName: { required: true, },
model: { required: false, multiple: true },
imagev2: { required: true },
dataset: { required: false },
spec: { required: true },
},
}],
}]
}],
// 训练任务
@@ -284,6 +302,7 @@ export const ListPageConfigs = {
{ k: 'NPU', v: 'NPU' },
{ k: 'GCU', v: 'GCU' },
{ k: 'MLU', v: 'MLU' },
{ k: 'DCU', v: 'DCU' },
],
pages: [{
jobType: 'DEBUG',
@@ -493,6 +512,30 @@ export const DetailPageConfigs = {
name: 'operationProfile'
}],
}],
'DCU': [{
detailUrl: 'grampus/notebook/',
summary: [],
operations: [],
tabs: [{
name: 'configInfo',
fields: [
'taskName', 'imagev2',
'status', 'spec',
'creator', 'aiCenter',
'branch', 'modelName',
'computerRes', 'modelVersion',
'createTime', 'modelFiles',
'startTime', '',
'endTime', '',
'duration', '',
'descr', '',
'dataset',
'modelList',
]
}, {
name: 'operationProfile'
}],
}],
}]
}],
/*
@@ -618,6 +661,8 @@ export const DetailPageConfigs = {
]
}, {
name: 'operationProfile'
},{
name: 'resultDownload'
}],
}],
}]
@@ -764,6 +809,7 @@ export const getDetailPageConfigs = (url, computeSource) => {
const data = pages[i4];
if (data) {
const _url = data.detailUrl;
console.log(url,data.detailUrl)
if (url.indexOf(_url) > -1 && computeSource == computerResouce) {
out = {
listUrl: cfg1.listUrl || '',


+ 62
- 3
web_src/vuepages/pages/cloudbrain/create/index.vue View File

@@ -67,7 +67,7 @@
<div class="form-row">
<div class="title"></div>
<div class="content">
<el-button type="primary" :disabled="maskLoading || alreadyMsgBoxShow" size="default" class="submit-btn"
<el-button type="primary" :disabled="maskLoading || alreadyMsgBoxShow || noSpecFlag" size="default" class="submit-btn"
@click="submit">{{ $t('cloudbrainObj.createTask') }}</el-button>
<el-button class="cancel-btn" size="default" @click="cancel">{{ $t('cancel') }}</el-button>
</div>
@@ -100,6 +100,7 @@ import LoadingMask from '~/components/cloudbrain/LoadingMask.vue';
import { getCreatePageConfigs } from '../configs';
import { getUrlSearchParams } from '~/utils';
import { getAiTaskPrepareInfo, createAiTask } from '~/apis/modules/cloudbrain';
import { getModelList } from '~/apis/modules/modelsquare';

export default {
data() {
@@ -141,6 +142,7 @@ export default {
maskLoading: false,
maskLoadingContent: '',
datasetSize: 0,
noSpecFlag:false,
};
},
components: {
@@ -251,6 +253,35 @@ export default {
window.history.back();
}
},
transformTreeData(data) {
for (let i = 0, iLen = data.length; i < iLen; i++) {
const dataI = data[i];
const _children = dataI.modelFileList || [];
const children = [];
dataI.parent = true;
dataI.disabled = true;
_children.forEach(item => {
item.ModTimeNum = new Date(item.ModTime).getTime();
})
_children.sort((a, b) => a.FileName.localeCompare(b.FileName));
_children.sort((a, b) => b.ModTimeNum - a.ModTimeNum);
for (let j = 0, jLen = _children.length; j < jLen; j++) {
const file = _children[j];
if (file.IsDir) continue;
// const arr = file.FileName.split('.');
// if (!supportCheckPointFileExt.includes(arr[arr.length - 1])) continue;
file._modelID = dataI.id;
file._modelName = dataI.name;
file._modelVersion = dataI.version;
file._preTrainModelUrl = dataI.path;
file.name = file.FileName;
file.id = `${file._modelID}|${file._modelName}|${file._modelVersion}|${file._preTrainModelUrl}|${file.name}`;
children.push(file);
}
dataI.children = children;
}
return data;
},
},
beforeMount() {
const urlParams = getUrlSearchParams();
@@ -266,6 +297,32 @@ export default {
this.cancel();
return;
}
if(urlParams.model_image){
console.log("urlParams.model_image",urlParams.model_image)
this.state.image_url = urlParams.model_image
}
if(urlParams.model_name){
const params = {
type: 1,
queryType: 1,
repoOwnerName: '',
repoName: '',
q: urlParams.model_name,
page: 1,
needModelFile: true,
notNeedEmpty: true,
};
getModelList(params).then((res)=>{
if(res.data.count===1){
const data = res.data?.data || [];
const transData = this.transformTreeData(data)
this.state.model = transData[0].modelFileList.splice(0,30)
}
}).catch((err)=>{
console.log(err)
})
}
getAiTaskPrepareInfo({
repoOwnerName: this.repoOwnerName,
repoName: this.repoName,
@@ -282,8 +339,10 @@ export default {
this.specConfigs.showPoint = data.pay_switch;
this.specConfigs.blance = data.point_account ? data.point_account.balance : 0;
this.specConfigs.specs = data.specs || [];
if(!this.specConfigs.specs.length){
this.noSpecFlag = true
}
this.queueNum = data.wait_count || 1;

this.state.branchName = data.default_branch;
this.state.taskName = data.display_job_name;
this.state.spec = this.specConfigs.specs.length ? this.specConfigs.specs[0].id.toString() : '';
@@ -301,7 +360,7 @@ export default {
console.log(err);
});
},
mounted() { },
mounted() {},
beforeDestroy() { },
};
</script>


+ 91
- 4
web_src/vuepages/pages/home/screenmap/index.vue View File

@@ -167,6 +167,16 @@ methods: {
position: 'right',
show: false
},
tooltip:{
formatter: (params)=>{
const marker = `
<div>${params.seriesName}</div>
<span style=\"display:inline-block;margin-right:4px;border-radius:10px;width:10px;height:10px;background-color:rgb(251, 118, 123);\"></span>
<span>${params.data.name}</span>
`
return marker
}
},
emphasis: {
label: {
show: true
@@ -205,6 +215,16 @@ methods: {
position: 'right',
show: false
},
tooltip:{
formatter: (params)=>{
const marker = `
<div>${params.seriesName}</div>
<span style=\"display:inline-block;margin-right:4px;border-radius:10px;width:10px;height:10px;background-color:rgb(251, 118, 123);\"></span>
<span>${params.data.name}</span>
`
return marker
}
},
emphasis: {
label: {
show: true
@@ -249,6 +269,16 @@ methods: {
position: 'right',
show: true
},
tooltip:{
formatter: (params)=>{
const marker = `
<div>${params.seriesName}</div>
<span style=\"display:inline-block;margin-right:4px;border-radius:10px;width:10px;height:10px;background-color:rgb(251, 118, 123);\"></span>
<span>${params.data.name}</span>
`
return marker
}
},
showEffectOn: 'render',
rippleEffect: {
brushType: 'stroke'
@@ -281,11 +311,12 @@ methods: {
zlevel: 2,
effect: {
show: true,
symbol:'rect',
period: 1.5, // 速度
trailLength: 0.5, // 特效拖尾
symbol:'circle',
period: 3, // 速度
trailLength: 0.4, // 特效拖尾
color: '#007BFF',
symbolSize: 3
symbolSize: 3,
},
lineStyle: {
color: 'rgba(255,255,255,0.1)',
@@ -365,6 +396,62 @@ methods: {
}else{

}
this.TaskLine = [
{
coords: [
[146.726242, -6.569828], // 流出位置
[113.91, 22.54] // 流入位置
]
},
{
coords: [
[-73.740833, 45.470556],
[113.91, 22.54]
]
},
{
coords: [
[113.91, 22.54],
[115.480656, 35.23375]
]
},
{
coords: [
[120.26, 31.91],
[117.27, 31.86]
]
},
{
coords: [
[113.91, 22.54],
[114.31, 30.52]
]
},
{
coords: [
[113.91, 22.54],
[103.73, 36.03]
]
},
{
coords: [
[113, 28.21],
[118.88, 28.97]
]
},
{
coords: [
[116.7, 39.53],
[113.91, 22.54]
]
},
{
coords: [
[116.4, 39.9],
[113.91, 22.54]
]
}
]
this.getOption()
}catch(error){
console.log(error)


+ 78
- 6
web_src/vuepages/pages/modelmanage/components/ModelHeader.vue View File

@@ -7,12 +7,21 @@
<img src="/img/jian.svg" v-if="model.recommend == 1">
</div>
<div class="title-r">
<div @click="changeFav">
<div style="background: transparent;" v-if="!isCanDebug && !model.isPrivate">
<el-button class="create-btn" size="mini" type="primary" @click="createOnlineDebug"
v-loading.fullscreen.lock="fullscreenLoading"
element-loading-text="拼命加载中"
element-loading-background="rgba(0, 0, 0, 0.8)"
>
{{ $t('modelManage.debugModel') }}
</el-button>
</div>
<div @click="changeFav" class="like-btn">
<i v-if="!isCollected" class="heart outline icon" :title="$t('star')"></i>
<i v-if="isCollected" class="heart icon" :title="$t('unStar')"></i>
<span>{{ $t('star') }}</span>
</div>
<div>{{ collectedCount }}</div>
<div class="like-btn">{{ collectedCount }}</div>
</div>
</div>
<div class="sub-title">
@@ -71,7 +80,7 @@
</template>

<script>
import { setModelFav } from '~/apis/modules/modelsquare';
import { setModelFav,createModelNotebook } from '~/apis/modules/modelsquare';

export default {
name: "ModelHeader",
@@ -80,7 +89,7 @@ export default {
repoOwnerName: { type: String, default: '' },
repoName: { type: String, default: '' },
modelName: { type: String, default: '' },
tab: { type: String, default: 'intro' }
tab: { type: String, default: 'intro' },
},
components: {},
data() {
@@ -89,6 +98,9 @@ export default {
isCollected: false,
collectedCount: '',
isSetting: false,
fullscreenLoading: false,
isCanDebug:false,
loginName:'zhoupzh',
};
},
methods: {
@@ -114,6 +126,49 @@ export default {
this.$message.error(err);
this.isSetting = false;
});
},
createOnlineDebug(){
this.fullscreenLoading = true;
createModelNotebook({repoId:this.model.repoId,modelId:this.model.id}).then((res)=>{
this.$message.success(this.$t('modelManage.forkModelSuccess'));
this.fullscreenLoading = false;
const repoPath = res.data.repoPath
if(this.model.modelType===1){
if(this.model.computeResource==='CPU/GPU'){
window.open(`/${repoPath}/grampus/notebook/create?type=0&model_name=${this.model.name}`)
}else{
window.open(`/${repoPath}/grampus/notebook/create?type=1&model_name=${this.model.name}`)
}
}else{
const trainTaskInfo = this.model.trainTaskInfo ? JSON.parse(this.model.trainTaskInfo) : '';
const taskType = trainTaskInfo.Type;
const ComputeResource = trainTaskInfo.ComputeResource
const image = trainTaskInfo.Image
let taskUrl = ''
if (taskType == 0) {
taskUrl = `/${repoPath}/cloudbrain/create?model_name=${this.model.name}&model_image=${image}`
} else if (taskType == 1) {
taskUrl = `/${repoPath}/modelarts/notebook/create?model_name=${this.model.name}`
} else if (taskType == 2) {
if(ComputeResource==="NPU"){
taskUrl = `/${repoPath}/grampus/notebook/create?type=1&model_name=${this.model.name}`
}else if(ComputeResource==="GCU"){
taskUrl = `/${repoPath}/grampus/notebook/create?type=2&model_name=${this.model.name}`
}else{
taskUrl = `/${repoPath}/grampus/notebook/create?type=2&model_name=${this.model.name}&model_image=${image}`
}
}
window.open(taskUrl)
}
}).catch((err)=>{
if(err.response.status===401){
window.location.href = `/user/login?redirect_to=${encodeURIComponent(window.location.href)}`;
}else{
this.$message.error(err);
}
this.fullscreenLoading = false;
})
}
},
watch: {
@@ -121,12 +176,23 @@ export default {
handler(newVal) {
this.isCollected = newVal.isCollected;
this.collectedCount = newVal.collectedCount;
if(newVal.userName===this.loginName){
this.isCanDebug = true
}else{
this.isCanDebug = false
}
},
immediate: true,
deep: true,
},
},
mounted() { },
mounted() {},
beforeMount() {
const isLogin = !!document.querySelector('meta[name="_uid"]');
if(isLogin){
this.loginName = document.querySelector('meta[name="_uid"]').getAttribute('content-ext')
}
},
};
</script>

@@ -179,7 +245,7 @@ export default {
display: flex;
align-items: center;

>div {
.like-btn {
height: 30px;
border-color: rgb(225, 227, 230);
border-width: 1px;
@@ -203,6 +269,12 @@ export default {
cursor: default;
}
}
.create-btn {
font-size: 14px;
margin-right: 1rem;
background-color: #1684FC;

}
}
}



+ 1
- 1
web_src/vuepages/pages/modelmanage/files/index.vue View File

@@ -4,7 +4,7 @@
<NotFound></NotFound>
</div>
<div v-else>
<ModelHeader :tab="'files'" :repoOwnerName="repoOwnerName" :repoName="repoName" :modelName="modelName"
<ModelHeader :tab="'files'" :repoOwnerName="repoOwnerName" :repoName="repoName" :modelName="modelName" v-if="JSON.stringify(modelData)!=='{}'"
:model="modelData">
</ModelHeader>
<div class="ui container">


+ 1
- 1
web_src/vuepages/pages/modelmanage/fileupload/index.vue View File

@@ -4,7 +4,7 @@
<NotFound></NotFound>
</div>
<div v-else>
<ModelHeader :tab="'files'" :repoOwnerName="repoOwnerName" :repoName="repoName" :modelName="modelName" :model="modelData">
<ModelHeader :tab="'files'" :repoOwnerName="repoOwnerName" :repoName="repoName" :modelName="modelName" :model="modelData" v-if="JSON.stringify(modelData)!=='{}'">
</ModelHeader>
<div class="ui container">
<div class="header">


+ 1
- 1
web_src/vuepages/pages/modelmanage/graph/index.vue View File

@@ -4,7 +4,7 @@
<NotFound></NotFound>
</div>
<div v-else>
<ModelHeader :tab="'graph'" :repoOwnerName="repoOwnerName" :repoName="repoName" :modelName="modelName" :model="modelData">
<ModelHeader :tab="'graph'" :repoOwnerName="repoOwnerName" :repoName="repoName" :modelName="modelName" :model="modelData" v-if="JSON.stringify(modelData)!=='{}'">
</ModelHeader>
<div class="ui container">
<div ref="graphContainerRef" class="graph-container"></div>


+ 166
- 7
web_src/vuepages/pages/modelmanage/intro/index.vue View File

@@ -4,7 +4,7 @@
<NotFound></NotFound>
</div>
<div v-else>
<ModelHeader :tab="'intro'" :repoOwnerName="repoOwnerName" :repoName="repoName" :modelName="modelName"
<ModelHeader :tab="'intro'" :repoOwnerName="repoOwnerName" :repoName="repoName" :modelName="modelName" v-if="JSON.stringify(modelData)!=='{}'"
:model="modelData">
</ModelHeader>
<div class="ui container content">
@@ -112,6 +112,54 @@
<div class="value">{{ modelData.createTimeStr }}</div>
</div>
</div>
<div class="online-container" v-if="onlineUrl || onlineAddressList.length">
<template v-if="onlineUrl">
<!-- <div class="divider-column-vertical"></div> -->
<div class="online-address">
<a :href="onlineUrl" target="_blank" style="width: 50%;background: rgb(255, 255, 255);">{{ $t('modelManage.onlineInference') }}</a>
</div>
</template>
<template v-if="onlineAddressList.length">
<!-- <div class="divider-column-vertical"></div> -->
<div class="summary" style="margin-left: 1rem;margin-top:1.5rem">
<div class="title">{{ $t('modelManage.otherOnline') }}:</div>
<div class="detail-address" v-for="item in onlineAddressList">
<li class="nowrap">
<a :href="item.onlineInferUrl">{{item.ownerName}}/{{item.repoDisplayName}}</a>
</li>
</div>
</div>
</template>
</div>
<template v-if="trainUsedDataList.length">
<div class="divider-column-vertical"></div>
<div class="summary" style="margin-left: 1rem;">
<div class="title">{{ $t('modelManage.trainUsedDataList') }}:</div>
<div class="detail-address" v-for="item in trainUsedDataList">
<span style="display: flex;" v-if="!item.is_delete">
<i style="margin-right: 0.5rem;" class="ri-stack-line"></i>
<a class="nowrap" :href="item.repository_link" :title="item.dataset_name">{{item.dataset_name}}</a>
</span>
<span v-else style="display: flex;color:#888888" class="nowrap">
<i style="margin-right: 0.5rem;" class="ri-stack-line"></i>
<span style="width: 70%;" class="nowrap">{{item.dataset_name}}</span>
<span>{{ $t('modelManage.deleted') }}</span>
</span>
</div>
</div>
</template>
<template v-if="modelUseTaskList.length">
<div class="divider-column-vertical"></div>
<div class="summary" style="margin-left: 1rem;">
<div class="title">{{ $t('modelManage.modelUseTaskList') }}:</div>
<div class="detail-address" v-for="item in modelUseTaskList">
<li class="nowrap">
<a :href="item.url" :title="item.jobName">{{item.jobName}}</a>
</li>
</div>
</div>
</template>
</div>
</div>
</div>
@@ -157,12 +205,19 @@ export default {
previewContent: '',

submitLoading: false,

onlineAddressList: [],
trainUsedDataList: [],
modelUseTaskList: [],
onlineUrl:'',


};
},
components: { ModelHeader, NotFound },
methods: {
createIntro() {
this.content = this.emptyDefaultContent;
this.content = this.emptyDefaultContent;
this.toggleEdit(true);
},
changeEditTab(tab) {
@@ -253,6 +308,10 @@ export default {
this.introEmpty = false;
this.content = data.content;
this.htmlContent = data.htmlcontent;
const match = data.content.match(/(#+)(.*)在线体验地址\s+(http[s]?:\/\/\S+)/g);
if(match){
this.onlineUrl = 'http' + match[0].split('http')[1]
}
}
this.introFileName = data.fileName;
window.setTimeout(() => {
@@ -300,6 +359,54 @@ export default {
});
this.submitLoading = false;
});
},
getFullUrlForType(data){
const result = []
data.forEach(element => {
const detailObj = {jobName:element.displayJobName}
const prefixRepoLink = `${element.ownerName}/${element.repoName}`
if(element.type === 0){
if(element.jobType==='DEBUG'){
detailObj.url = `/${prefixRepoLink}/cloudbrain/${element.id}`
}else if(element.jobType==='TRAIN'){
detailObj.url = `/${prefixRepoLink}/cloudbrain/train-job/${element.jobId}`
}else if(element.jobType==='INFERENCE'){
detailObj.url = `/${prefixRepoLink}/cloudbrain/inference-job/${element.jobId}`
}else if(element.jobType==='BENCHMARK' || element.jobType==='MODELSAFETY'){
detailObj.url = `/${prefixRepoLink}/cloudbrain/benchmark/${element.id}`
}else{
}
}
if(element.type === 1){
if(element.jobType==='DEBUG'){
detailObj.url = `/${prefixRepoLink}/modelarts/notebook/${element.id}`
}else if(element.jobType==='TRAIN'){
detailObj.url = `/${prefixRepoLink}/modelarts/train-job/${element.id}`
}else if(element.jobType==='INFERENCE'){
detailObj.url = `/${prefixRepoLink}/modelarts/inference-job/${element.id}`
}else if(element.jobType==='BENCHMARK' || element.jobType==='MODELSAFETY'){
detailObj.url = `/${prefixRepoLink}/cloudbrain/benchmark/${element.id}`
}else{
}

}
if(element.type === 2){
if(element.jobType==='DEBUG'){
detailObj.url = `/${prefixRepoLink}/grampus/notebook/${element.id}`
}else if(element.jobType==='TRAIN'){
detailObj.url = `/${prefixRepoLink}/grampus/train-job/${element.jobId}`
}else if(element.jobType==='INFERENCE'){

}else if(element.jobType==='BENCHMARK'){

}else{
detailObj.url = `/${prefixRepoLink}/grampus/onlineinfer/${element.id}`
}
}
result.push(detailObj)
});
return result
}
},
beforeMount() {
@@ -338,6 +445,10 @@ export default {
};
this.labels = model.label ? model.label.trim().split(/\s+/) : [];
this.canEdit = model.isCanOper;
this.onlineAddressList = model.onlineInfo
this.trainUsedDataList = model.datasetInfo === null ? [] : model.datasetInfo
const modelUseTaskList = model.usedCloudbrain.length > 5 ? model.usedCloudbrain.slice(0,5) : model.usedCloudbrain
this.modelUseTaskList = this.getFullUrlForType(modelUseTaskList)
this.getIntroInfo();
} else {
this.emptyPage = true;
@@ -363,8 +474,8 @@ export default {
margin-top: 32px;

.content-l {
flex: 11;
width: 0;
flex: 12;
width: 75%;

.read-mode {
.head {
@@ -510,6 +621,7 @@ export default {

.content-r {
flex: 4;
width: 25%;
margin-left: 32px;

.title {
@@ -526,7 +638,31 @@ export default {
margin-bottom: 8px;
line-height: 20px;
}

.online-container{
background: linear-gradient(180deg, rgba(203,212,251,0.3) 0%,rgba(255,255,255,0) 100%);
border-color: rgb(225, 227, 230);
border-width: 1px 0px 0px;
border-style: solid;
margin-top: 1.5rem;
.online-address {
width: 100%;
display: flex;
justify-content: center;
margin-top: 1.5rem;
a{
width: 50%;
background: rgb(255, 255, 255);
color: rgb(22, 132, 252);
border-color: rgb(22, 132, 252);
border-width: 1px;
border-style: solid;
text-align: center;
line-height: 20px;
padding: 0.4rem 0;
}
}
}
.labels {
margin-top: 12px;
margin-bottom: 12px;
@@ -575,7 +711,24 @@ export default {
border-radius: 2px;
font-size: 12px;
}

.divider-column-vertical {
background-color: rgb(243 244 246);
height: 1px;
margin-bottom: 1.25rem;
margin-top: 1.25rem;
}
.detail-address{
margin: 0.5rem 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
color: rgba(5, 127, 255, 1);
>a {
color: rgba(5, 127, 255, 1);
}
}
.summary {
.row {
display: flex;
@@ -584,13 +737,19 @@ export default {
.label {
color: rgb(136, 136, 136)
}

.value {
color: rgb(16, 16, 16);
flex: 1;
}
}
.title{
height: 20px;
color: rgba(136, 136, 136, 1);
font-size: 14px;
margin-bottom: 1.2rem;
}
}
}
}
</style>

+ 1
- 1
web_src/vuepages/pages/modelmanage/settings/index.vue View File

@@ -4,7 +4,7 @@
<NotFound></NotFound>
</div>
<div v-else>
<ModelHeader :tab="'settings'" :repoOwnerName="repoOwnerName" :repoName="repoName" :modelName="modelName"
<ModelHeader :tab="'settings'" :repoOwnerName="repoOwnerName" :repoName="repoName" :modelName="modelName" v-if="JSON.stringify(modelData)!=='{}'"
:model="modelData">
</ModelHeader>
<div class="ui container content-wrap">


+ 10
- 1
web_src/vuepages/pages/modelsquare/square/components/ModelCondition.vue View File

@@ -13,6 +13,9 @@
<el-checkbox v-model="conds.onlyRecommend" @change="changeRecommend">
{{ $t('datasets.platform_recommendations') }}
</el-checkbox>
<el-checkbox v-model="conds.hasOnlineUrl" @change="changeOnline">
{{ $t('modelObj.can_online_infer') }}
</el-checkbox>
</div>
<div>
<el-dropdown class="sort-c" trigger="click" size="default">
@@ -57,7 +60,7 @@ export default {
label: this.$t('datasets.default'),
}, {
key: 'created_unix',
label: this.$t('datasets.latest'),
label: this.$t('datasets.newest'),
}, {
key: 'updated_unix',
label: this.$t('datasets.recentupdate'),
@@ -90,6 +93,11 @@ export default {
onlyRecommend: this.conds.onlyRecommend,
});
},
changeOnline(item){
this.$emit('changeCondition', {
hasOnlineUrl: this.conds.hasOnlineUrl,
});
},
changeSort(item) {
this.conds.sort = item.key;
this.$emit('changeCondition', {
@@ -103,6 +111,7 @@ export default {
this.conds.tab = newVal.tab || '1';
this.conds.sort = newVal.sort || '';
this.conds.onlyRecommend = newVal.onlyRecommend || false;
this.conds.hasOnlineUrl = newVal.hasOnlineUrl || false;
},
immediate: true,
deep: true,


+ 19
- 4
web_src/vuepages/pages/modelsquare/square/components/ModelItem.vue View File

@@ -36,7 +36,11 @@
</span>
</div>
<div class="footer-r">
<span class="item-engine" style="margin-left:5px;"> {{ data.engineName || data.engine }} </span>
<span style="white-space: nowrap;" v-if="hasOnlineUrl">
<span class="greenPoint"></span>
{{ $t('modelObj.can_online_infer') }}
</span>
<span class="item-engine"> {{ data.engineName || data.engine }} </span>
</div>
</div>
</a>
@@ -57,6 +61,7 @@ export default {
isCollected: false,
collectedCount: 0,
isSetting: false,
hasOnlineUrl:0,
};
},
methods: {
@@ -89,6 +94,8 @@ export default {
beforeMount() {
this.isCollected = this.data.isCollected;
this.collectedCount = this.data.collectedCount;
this.hasOnlineUrl = this.data.hasOnlineUrl

},
};
</script>
@@ -228,14 +235,22 @@ export default {
}

.footer-r {
text-align: right;
min-width: 140px;
display: flex;
justify-content: end;
font-size: 12px;
font-weight: 300;
color: rgb(136, 136, 136);

.greenPoint{
display: inline-block;
width: 8px;
height: 8px;
margin-right: 5px;
background-color: #5dbf77;
border-radius: 50%;
}
.item-engine {
color: rgba(136, 136, 136, 0.9);
margin-left: 10px;
}
}
}


+ 1
- 0
web_src/vuepages/pages/modelsquare/square/components/ModelList.vue View File

@@ -51,6 +51,7 @@ export default {
queryType: this.condition.tab,
orderBy: this.condition.sort,
recommend: this.condition.onlyRecommend,
hasOnlineUrl: this.condition.hasOnlineUrl,
frame: this.condition.engine,
label: this.condition.label,
page: this.condition.page,


+ 3
- 0
web_src/vuepages/pages/modelsquare/square/index.vue View File

@@ -41,6 +41,7 @@ export default {
tab: '1',
sort: '',
onlyRecommend: false,
hasOnlineUrl: false,
engine: '',
label: '',
page: 1,
@@ -63,6 +64,7 @@ export default {
`&tab=${encodeURIComponent(this.condition.tab)}` +
`&sort=${encodeURIComponent(this.condition.sort)}` +
`&onlyRecommend=${encodeURIComponent(this.condition.onlyRecommend)}` +
`&hasOnlineUrl=${encodeURIComponent(this.condition.hasOnlineUrl)}` +
`&engine=${encodeURIComponent(this.condition.engine)}` +
`&label=${encodeURIComponent(this.condition.label)}` +
`&page=${encodeURIComponent(this.condition.page)}` +
@@ -75,6 +77,7 @@ export default {
this.condition.tab = urlParams.tab || '1';
this.condition.sort = urlParams.sort || '';
this.condition.onlyRecommend = urlParams.onlyRecommend == 'true' ? true : false;
this.condition.hasOnlineUrl = urlParams.hasOnlineUrl == 'true' ? true : false;
this.condition.engine = urlParams.engine || '';
this.condition.label = urlParams.label || '';



+ 11885
- 11885
yarn.lock
File diff suppressed because it is too large
View File


Loading…
Cancel
Save