#4434 V20230628

Merged
ychao_1983 merged 221 commits from V20230628 into develop 10 months ago
  1. +1
    -1
      cmd/web.go
  2. +4
    -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. +15
    -4
      models/cloudbrain.go
  9. +10
    -0
      models/issue_comment.go
  10. +2
    -0
      models/notification.go
  11. +14
    -2
      models/review.go
  12. +1
    -0
      models/task_config.go
  13. +8
    -17
      modules/setting/setting.go
  14. +5
    -0
      modules/structs/cloudbrain.go
  15. +4
    -1
      options/locale/locale_en-US.ini
  16. +4
    -1
      options/locale/locale_zh-CN.ini
  17. +5
    -3
      public/home/home.js
  18. +6
    -2
      routers/api/v1/api.go
  19. +44
    -9
      routers/api/v1/repo/cloudbrain.go
  20. +1
    -1
      routers/api/v1/repo/cloudbrain_dashboard.go
  21. +2
    -0
      routers/repo/ai_model_manage.go
  22. +81
    -0
      routers/repo/ai_model_square.go
  23. +0
    -150
      routers/repo/grampus.go
  24. +1
    -0
      routers/response/response_list.go
  25. +4
    -4
      routers/routes/routes.go
  26. +2
    -0
      routers/user/notification.go
  27. +23
    -10
      services/ai_task_service/cluster/c2net.go
  28. +13
    -2
      services/ai_task_service/cluster/cloudbrain_one.go
  29. +4
    -1
      services/ai_task_service/container_builder/code_builder.go
  30. +4
    -2
      services/ai_task_service/container_builder/dataset_builder.go
  31. +19
    -10
      services/ai_task_service/container_builder/output_path_builder.go
  32. +10
    -3
      services/ai_task_service/task/grampus_notebook_task.go
  33. +7
    -21
      services/ai_task_service/task/grampus_online_infer_task.go
  34. +31
    -4
      services/ai_task_service/task/opt_handler.go
  35. +2
    -1
      services/ai_task_service/task/task_service.go
  36. +13
    -3
      services/cloudbrain/cloudbrainTask/notebook.go
  37. +26
    -10
      services/cloudbrain/util.go
  38. +55
    -11
      services/pull/review.go
  39. +1
    -1
      services/socketwrap/clientManager.go
  40. +1
    -0
      templates/admin/cloudbrain/search.tmpl
  41. +1
    -0
      templates/admin/cloudbrain/search_dashboard.tmpl
  42. +2
    -3
      templates/base/footer.tmpl
  43. +5
    -2
      templates/custom/home/home_screen_map.tmpl
  44. +1
    -34
      templates/notice.tmpl
  45. +1
    -1
      templates/repo/cloudbrain/benchmark/index.tmpl
  46. +1
    -1
      templates/repo/modelarts/inferencejob/index.tmpl
  47. +1
    -1
      templates/repo/modelarts/trainjob/index.tmpl
  48. +8
    -0
      templates/user/dashboard/feeds.tmpl
  49. +1
    -1
      templates/user/notification/notification.tmpl
  50. +10
    -1
      templates/user/notification/notification_div.tmpl
  51. +44
    -0
      web_src/js/features/notification.js
  52. +54
    -55
      web_src/js/router/index.js
  53. +29
    -0
      web_src/less/openi.less
  54. +67
    -3
      web_src/vuepages/apis/modules/cloudbrain.js
  55. +12
    -0
      web_src/vuepages/apis/modules/modelsquare.js
  56. +16
    -3
      web_src/vuepages/components/cloudbrain/ModelSelect.vue
  57. +25
    -4
      web_src/vuepages/components/cloudbrain/SpecSelect.vue
  58. +21
    -1
      web_src/vuepages/components/cloudbrain/details/ConfigInfo.vue
  59. +176
    -48
      web_src/vuepages/components/cloudbrain/details/ResultDownload.vue
  60. +2
    -2
      web_src/vuepages/const/index.js
  61. +24
    -6
      web_src/vuepages/langs/config/en-US.js
  62. +23
    -5
      web_src/vuepages/langs/config/zh-CN.js
  63. +55
    -4
      web_src/vuepages/pages/cloudbrain/configs.js
  64. +61
    -3
      web_src/vuepages/pages/cloudbrain/create/index.vue
  65. +1
    -1
      web_src/vuepages/pages/dataset/square/components/PublicDataset.vue
  66. +32
    -2
      web_src/vuepages/pages/home/screenmap/index.vue
  67. +78
    -6
      web_src/vuepages/pages/modelmanage/components/ModelHeader.vue
  68. +1
    -1
      web_src/vuepages/pages/modelmanage/files/index.vue
  69. +1
    -1
      web_src/vuepages/pages/modelmanage/fileupload/index.vue
  70. +1
    -1
      web_src/vuepages/pages/modelmanage/graph/index.vue
  71. +166
    -7
      web_src/vuepages/pages/modelmanage/intro/index.vue
  72. +1
    -1
      web_src/vuepages/pages/modelmanage/settings/index.vue
  73. +10
    -1
      web_src/vuepages/pages/modelsquare/square/components/ModelCondition.vue
  74. +19
    -4
      web_src/vuepages/pages/modelsquare/square/components/ModelItem.vue
  75. +1
    -0
      web_src/vuepages/pages/modelsquare/square/components/ModelList.vue
  76. +3
    -0
      web_src/vuepages/pages/modelsquare/square/index.vue
  77. +11885
    -11885
      yarn.lock

+ 1
- 1
cmd/web.go View File

@@ -167,7 +167,7 @@ func runWeb(ctx *cli.Context) error {
if setting.EnablePprof { if setting.EnablePprof {
go func() { go func() {
log.Info("Starting pprof server on localhost:6060") 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))
}() }()
} }




+ 4
- 7
entity/ai_task.go View File

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


"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"

"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/structs"
@@ -93,6 +94,7 @@ type AITaskDetailInfo struct {
ImageName string `json:"image_name"` ImageName string `json:"image_name"`
CreatorName string `json:"creator_name"` CreatorName string `json:"creator_name"`
EngineName string `json:"engine_name"` EngineName string `json:"engine_name"`
FailedReason string `json:"failed_reason"`
} }


func (a *AITaskDetailInfo) Tr(language string) { func (a *AITaskDetailInfo) Tr(language string) {
@@ -108,10 +110,9 @@ func (a *AITaskDetailInfo) RemovePretrainModelList() {


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

if len(aiCenterInfo) == 2 { 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 { if language == defaultLanguage {
return info.Content return info.Content
} else { } else {
@@ -120,15 +121,11 @@ func getAiCenterShow(aiCenter string, language string) string {
} else { } else {
return aiCenterInfo[1] return aiCenterInfo[1]
} }

} else { } else {
return aiCenterInfo[1] return aiCenterInfo[1]
} }

} }

return "" return ""

} }


var defaultLanguage = "zh-CN" var defaultLanguage = "zh-CN"


+ 9
- 7
entity/container.go View File

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


type ContainerData 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 type ContainerDataType string


+ 1
- 0
entity/images.go View File

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


type GetImageReq struct { type GetImageReq struct {


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

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

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


sendjob: sendjob:


+ 2
- 0
models/action.go View File

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


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


+ 61
- 40
models/ai_model_manage.go View File

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


type AiModelManage struct { 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 { type AiModelFile struct {
@@ -127,6 +130,7 @@ type AiModelQueryOptions struct {
FrameFilter int FrameFilter int
ComputeResourceFilter string ComputeResourceFilter string
NotNeedEmpty bool NotNeedEmpty bool
HasOnlineUrl int
} }


func (a *AiModelConvert) IsGpuTrainTask() bool { func (a *AiModelConvert) IsGpuTrainTask() bool {
@@ -333,6 +337,20 @@ func ModifyModelDescription(id string, description string) error {
return nil 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 { func ModifyModelPrivate(id string, isPrivate bool) error {
var sess *xorm.Session var sess *xorm.Session
sess = x.ID(id) sess = x.ID(id)
@@ -549,6 +567,9 @@ func QueryModel(opts *AiModelQueryOptions) ([]*AiModelManage, int64, error) {
if opts.NotNeedEmpty { if opts.NotNeedEmpty {
where += " and ai_model_manage.size > 0 " where += " and ai_model_manage.size > 0 "
} }
if opts.HasOnlineUrl > 0 {
where += " and ai_model_manage.has_online_url =1 "
}
var count int64 var count int64
var err error var err error
if opts.IsCollected { if opts.IsCollected {


+ 15
- 4
models/cloudbrain.go View File

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


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


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


const ( const (
@@ -256,7 +259,7 @@ type Cloudbrain struct {
LabelName string //标签名称 LabelName string //标签名称
ModelName string //模型名称 ModelName string //模型名称
ModelVersion string //模型版本 ModelVersion string //模型版本
CkptName string //权重文件名称
CkptName string `xorm:"varchar(2550)"` //权重文件名称
ModelId string //模型ID ModelId string //模型ID
ModelRepoName string `xorm:"-"` ModelRepoName string `xorm:"-"`
ModelRepoOwnerName string `xorm:"-"` ModelRepoOwnerName string `xorm:"-"`
@@ -446,7 +449,7 @@ func (task *Cloudbrain) NeedActiveStop() bool {
//是否允许创建多版本 //是否允许创建多版本
//目前只有启智NPU可以 //目前只有启智NPU可以
func (task *Cloudbrain) IsAllowedToCreateMultipleVersions() bool { func (task *Cloudbrain) IsAllowedToCreateMultipleVersions() bool {
if task.Type == TypeCloudBrainTwo && task.ComputeResource == NPUResource {
if task.Type == TypeCloudBrainTwo && task.ComputeResource == NPUResource && task.JobType != string(JobTypeDebug) {
return true return true
} }
return false return false
@@ -504,6 +507,10 @@ func (task *Cloudbrain) IsNPUTask() bool {
return task.ComputeResource == NPUResource return task.ComputeResource == NPUResource
} }


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

func ConvertDurationToStr(duration int64) string { func ConvertDurationToStr(duration int64) string {
if duration <= 0 { if duration <= 0 {
return DURATION_STR_ZERO return DURATION_STR_ZERO
@@ -1950,6 +1957,7 @@ type GrampusNotebookTask struct {
CenterName []string `json:"centerName"` CenterName []string `json:"centerName"`
Code GrampusDataset `json:"code"` Code GrampusDataset `json:"code"`
Datasets []GrampusDataset `json:"datasets"` Datasets []GrampusDataset `json:"datasets"`
OutPut GrampusDataset `json:"output"`
CodeUrl string `json:"codeUrl"` CodeUrl string `json:"codeUrl"`
DataUrl string `json:"dataUrl"` DataUrl string `json:"dataUrl"`
ImageId string `json:"imageId"` ImageId string `json:"imageId"`
@@ -2285,6 +2293,9 @@ func CloudbrainsVersionList(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int, e
} }


func GetCloudbrainEarlyVersionList(task *Cloudbrain) ([]*Cloudbrain, error) { func GetCloudbrainEarlyVersionList(task *Cloudbrain) ([]*Cloudbrain, error) {
if task.JobID == "" {
return []*Cloudbrain{}, nil
}
cloudbrains := make([]*Cloudbrain, 0) cloudbrains := make([]*Cloudbrain, 0)
if err := x.Where(builder.NewCond(). if err := x.Where(builder.NewCond().
And(builder.Eq{"cloudbrain.repo_id": task.RepoID}). And(builder.Eq{"cloudbrain.repo_id": task.RepoID}).
@@ -3172,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 dataLocalPath = setting.Attachment.Minio.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID
} else if grampusType[0] == NPU { } else if grampusType[0] == NPU {
dataLocalPath = setting.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID + "/" 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 { if attach.Type == TypeCloudBrainOne {
dataLocalPath = setting.Attachment.Minio.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID dataLocalPath = setting.Attachment.Minio.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID
} else { } else {
@@ -3317,7 +3328,7 @@ func LoadSpecs4CloudbrainInfo(tasks []*CloudbrainInfo) error {


func GetCloudBrainByModelId(modelId string) ([]*Cloudbrain, error) { func GetCloudBrainByModelId(modelId string) ([]*Cloudbrain, error) {
cloudBrains := make([]*Cloudbrain, 0) 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 return cloudBrains, err
} }




+ 10
- 0
models/issue_comment.go View File

@@ -578,6 +578,7 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err
RefCommentID: opts.RefCommentID, RefCommentID: opts.RefCommentID,
RefAction: opts.RefAction, RefAction: opts.RefAction,
RefIsPull: opts.RefIsPull, RefIsPull: opts.RefIsPull,
Invalidated: opts.Invalidated,
} }
if _, err = e.Insert(comment); err != nil { if _, err = e.Insert(comment); err != nil {
return nil, err return nil, err
@@ -740,6 +741,7 @@ type CreateCommentOptions struct {
RefCommentID int64 RefCommentID int64
RefAction references.XRefAction RefAction references.XRefAction
RefIsPull bool RefIsPull bool
Invalidated bool
} }


// CreateComment creates comment of issue or commit. // CreateComment creates comment of issue or commit.
@@ -815,6 +817,8 @@ type FindCommentsOptions struct {
ReviewID int64 ReviewID int64
Since int64 Since int64
Before int64 Before int64
Line int64
TreePath string
Type CommentType Type CommentType
} }


@@ -838,6 +842,12 @@ func (opts *FindCommentsOptions) toConds() builder.Cond {
if opts.Type != CommentTypeUnknown { if opts.Type != CommentTypeUnknown {
cond = cond.And(builder.Eq{"comment.type": opts.Type}) cond = cond.And(builder.Eq{"comment.type": opts.Type})
} }
if opts.Line != 0 {
cond = cond.And(builder.Eq{"comment.line": opts.Line})
}
if len(opts.TreePath) > 0 {
cond = cond.And(builder.Eq{"comment.tree_path": opts.TreePath})
}
return cond return cond
} }




+ 2
- 0
models/notification.go View File

@@ -29,6 +29,8 @@ const (
NotificationStatusUnread NotificationStatus = iota + 1 NotificationStatusUnread NotificationStatus = iota + 1
// NotificationStatusRead represents a read notification // NotificationStatusRead represents a read notification
NotificationStatusRead NotificationStatusRead
// NotificationStatusRead represents a notification
NotificationStatusNotice
// NotificationStatusPinned represents a pinned notification // NotificationStatusPinned represents a pinned notification
NotificationStatusPinned NotificationStatusPinned
) )


+ 14
- 2
models/review.go View File

@@ -182,6 +182,18 @@ func findReviews(e Engine, opts FindReviewOptions) ([]*Review, error) {
Find(&reviews) Find(&reviews)
} }


func findReviewsSortByDesc(e Engine, opts FindReviewOptions) ([]*Review, error) {
reviews := make([]*Review, 0, 10)
sess := e.Where(opts.toCond())
if opts.Page > 0 {
sess = opts.ListOptions.setSessionPagination(sess)
}
return reviews, sess.
Desc("created_unix").
Desc("id").
Find(&reviews)
}

// FindReviews returns reviews passing FindReviewOptions // FindReviews returns reviews passing FindReviewOptions
func FindReviews(opts FindReviewOptions) ([]*Review, error) { func FindReviews(opts FindReviewOptions) ([]*Review, error) {
return findReviews(x, opts) return findReviews(x, opts)
@@ -246,7 +258,7 @@ func getCurrentReview(e Engine, reviewer *User, issue *Issue) (*Review, error) {
if reviewer == nil { if reviewer == nil {
return nil, nil return nil, nil
} }
reviews, err := findReviews(e, FindReviewOptions{
reviews, err := findReviewsSortByDesc(e, FindReviewOptions{
Type: ReviewTypePending, Type: ReviewTypePending,
IssueID: issue.ID, IssueID: issue.ID,
ReviewerID: reviewer.ID, ReviewerID: reviewer.ID,
@@ -264,7 +276,7 @@ func getCurrentReview(e Engine, reviewer *User, issue *Issue) (*Review, error) {


// ReviewExists returns whether a review exists for a particular line of code in the PR // ReviewExists returns whether a review exists for a particular line of code in the PR
func ReviewExists(issue *Issue, treePath string, line int64) (bool, error) { func ReviewExists(issue *Issue, treePath string, line int64) (bool, error) {
return x.Cols("id").Where("invalidated=false").Exist(&Comment{IssueID: issue.ID, TreePath: treePath, Line: line, Type: CommentTypeCode})
return x.Cols("id").Exist(&Comment{IssueID: issue.ID, TreePath: treePath, Line: line, Type: CommentTypeCode})
} }


// GetCurrentReview returns the current pending review of reviewer for given issue // GetCurrentReview returns the current pending review of reviewer for given issue


+ 1
- 0
models/task_config.go View File

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


+ 8
- 17
modules/setting/setting.go View File

@@ -653,11 +653,10 @@ var (
RunAtStart bool RunAtStart bool
}{} }{}


C2NetInfos *C2NetSqInfos
CenterInfos *AiCenterInfos
C2NetMapInfo map[string]*C2NetSequenceInfo
AiCenterCodeAndNameMapInfo map[string]*C2NetSequenceInfo

C2NetInfos *C2NetSqInfos
CenterInfos *AiCenterInfos
AiCenterCodeAndNameMapInfo map[string]*C2NetSequenceInfo
C2NetLocInfos *C2NetSqInfos
AiCenterCodeAndNameAndLocMapInfo map[string]*C2NetSequenceInfo AiCenterCodeAndNameAndLocMapInfo map[string]*C2NetSequenceInfo


//elk config //elk config
@@ -1854,27 +1853,19 @@ func GetGrampusConfig() {
Grampus.UserName = sec.Key("USERNAME").MustString("") Grampus.UserName = sec.Key("USERNAME").MustString("")
Grampus.Password = sec.Key("PASSWORD").MustString("") Grampus.Password = sec.Key("PASSWORD").MustString("")
Grampus.SpecialPools = sec.Key("SPECIAL_POOL").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.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.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.UsageRateBeginTime = sec.Key("USAGE_RATE_BEGIN_TIME").MustString("2021-01-01 00:00:00")
Grampus.GPUImageCommonName = sec.Key("GPU_IMAGE_COMMON_NAME").MustString("image") 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 Grampus.AiCenterCodeAndNameAndLocInfo != "" {
if err := json.Unmarshal([]byte(Grampus.AiCenterCodeAndNameAndLocInfo), &C2NetInfos); err != nil {
if err := json.Unmarshal([]byte(Grampus.AiCenterCodeAndNameAndLocInfo), &C2NetLocInfos); err != nil {
log.Error("Unmarshal(AiCenterCodeAndNameLocInfo) failed:%v", err) log.Error("Unmarshal(AiCenterCodeAndNameLocInfo) failed:%v", err)
} }
AiCenterCodeAndNameAndLocMapInfo = make(map[string]*C2NetSequenceInfo) AiCenterCodeAndNameAndLocMapInfo = make(map[string]*C2NetSequenceInfo)
for _, value := range C2NetInfos.C2NetSqInfo {
for _, value := range C2NetLocInfos.C2NetSqInfo {
AiCenterCodeAndNameAndLocMapInfo[value.Name] = value AiCenterCodeAndNameAndLocMapInfo[value.Name] = value
} }
} }


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

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

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

+ 4
- 1
options/locale/locale_en-US.ini View File

@@ -1301,7 +1301,7 @@ model_Evaluation_not_created = Model evaluation has not been created
repo_not_initialized = Code version: You have not initialized the code repository, please <a href="%s"> initialized </a> first ; repo_not_initialized = Code version: You have not initialized the code repository, please <a href="%s"> initialized </a> first ;
debug_task_running_limit =Running time: no more than 4 hours, it will automatically stop if it exceeds 4 hours; debug_task_running_limit =Running time: no more than 4 hours, it will automatically stop if it exceeds 4 hours;
dataset_desc = Dataset: Cloud Brain 1 provides CPU/GPU,Cloud Brain 2 provides Ascend NPU.And dataset also needs to be uploaded to the corresponding environment; dataset_desc = Dataset: Cloud Brain 1 provides CPU/GPU,Cloud Brain 2 provides Ascend NPU.And dataset also needs to be uploaded to the corresponding environment;
platform_instructions = Instructions for use: You can refer to the <a href="https://openi.pcl.ac.cn/zeizei/OpenI_Learning"> OpenI_Learning </a> course of Qizhi AI collaboration platform.
platform_instructions = Instructions for use: You can refer to the OpenI AI collaboration platform<a href="%s"> Help Center </a>.
platform_instructions1 = Instructions for use: You can refer to the platform_instructions1 = Instructions for use: You can refer to the
platform_instructions2 = OpenI_Learning platform_instructions2 = OpenI_Learning
platform_instructions3 = course of Openi AI collaboration platform. platform_instructions3 = course of Openi AI collaboration platform.
@@ -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. 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. 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.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.train_job.ai_center = AI Center
grampus.dataset_path_rule = The code is storaged in /cache/code;the dataset is storaged in /cache/dataset;and please put your model into /cache/output, then you can download it online。 grampus.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_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_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_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_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_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>` task_inferencejob=`created reasoning task <a href="%s/modelarts/inference-job/%s">%s</a>`
@@ -3238,6 +3240,7 @@ max_size_tooltips= You can only upload a maximum of ? files at a time. The uploa
notifications = Notifications notifications = Notifications
unread = Unread unread = Unread
read = Read read = Read
notice = Notice
no_unread = No unread notifications. no_unread = No unread notifications.
no_read = No read notifications. no_read = No read notifications.
pin = Pin notification pin = Pin notification


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

@@ -1313,7 +1313,7 @@ model_Evaluation_not_created = 未创建过评测任务
repo_not_initialized = 代码版本:您还没有初始化代码仓库,请先<a href=%s>创建代码版本</a>; repo_not_initialized = 代码版本:您还没有初始化代码仓库,请先<a href=%s>创建代码版本</a>;
debug_task_running_limit = 运行时长:最长不超过4个小时,超过4个小时将自动停止; debug_task_running_limit = 运行时长:最长不超过4个小时,超过4个小时将自动停止;
dataset_desc = 数据集:云脑1提供 CPU / GPU 资源,云脑2提供 Ascend NPU 资源,调试使用的数据集也需要上传到对应的环境; dataset_desc = 数据集:云脑1提供 CPU / GPU 资源,云脑2提供 Ascend NPU 资源,调试使用的数据集也需要上传到对应的环境;
platform_instructions = 使用说明:可以参考启智AI协作平台<a href="https://openi.pcl.ac.cn/zeizei/OpenI_Learning">小白训练营课程</a>。
platform_instructions = 使用说明:可以参考启智AI协作平台 <a href="%s" target="_blank">帮助中心</a>。
platform_instructions1 = 使用说明:可以参考启智AI协作平台 platform_instructions1 = 使用说明:可以参考启智AI协作平台
platform_instructions2 = 小白训练营课程 platform_instructions2 = 小白训练营课程
platform_instructions3 = 。 platform_instructions3 = 。
@@ -1402,6 +1402,7 @@ modelconvert.manage.no_operate_right=您没有操作权限。
debug.manage.model_not_exist=任务中选择的模型不存在或者已被删除,请新建调试任务。 debug.manage.model_not_exist=任务中选择的模型不存在或者已被删除,请新建调试任务。
train.manage.model_not_exist=任务中选择的模型不存在或者已被删除,请新建训练任务。 train.manage.model_not_exist=任务中选择的模型不存在或者已被删除,请新建训练任务。
debug.manage.dataset_not_exist=任务中选择的部分数据集不存在或者已被删除,请新建调试任务。 debug.manage.dataset_not_exist=任务中选择的部分数据集不存在或者已被删除,请新建调试任务。
debug.manage.model_num_over_limit=任务中选择的模型限制不超过30个文件


grampus.train_job.ai_center=智算中心 grampus.train_job.ai_center=智算中心
grampus.dataset_path_rule = 训练脚本存储在/cache/code中,数据集存储在/cache/dataset中,训练输出请存储在/cache/output中以供后续下载。 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_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_mludebugjob=`创建了MLU类型调试任务 <a href="%s/grampus/notebook/%s">%s</a>`
task_c2ent_mlutrainjob=`创建了MLU类型训练任务 <a href="%s/grampus/train-job/%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_c2ent_onlineinferjob=`创建了GPU类型在线推理任务 <a href="%s/grampus/onlineinfer/%s">%s</a>`
task_nputrainjob=`创建了NPU类型训练任务 <a href="%s/modelarts/train-job/%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>` task_inferencejob=`创建了推理任务 <a href="%s/modelarts/inference-job/%s">%s</a>`
@@ -3256,6 +3258,7 @@ max_size_tooltips=一次最多只能上传?个文件, 上传已达到上限,
notifications=通知 notifications=通知
unread=未读消息 unread=未读消息
read=已读消息 read=已读消息
notice=通知公告
no_unread=没有未读通知。 no_unread=没有未读通知。
no_read=没有未读通知。 no_read=没有未读通知。
pin=Pin 通知 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>" 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; html += recordPrefix + actionName;
const taskLink = getTaskLink(record); const taskLink = getTaskLink(record);
if (taskLink) { if (taskLink) {
@@ -313,7 +313,7 @@ function getTaskLink(record){
re = re + "/cloudbrain/train-job/" + record.Content; re = re + "/cloudbrain/train-job/" + record.Content;
}else if(record.OpType == 32 || record.OpType == 33 || record.OpType == 42 || record.OpType == 44){ }else if(record.OpType == 32 || record.OpType == 33 || record.OpType == 42 || record.OpType == 44){
re = re + "/grampus/train-job/" + record.Content; 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) { if (record.Cloudbrain) {
re = re + "/grampus/notebook/" + record.Cloudbrain.ID; re = re + "/grampus/notebook/" + record.Cloudbrain.ID;
} else { } else {
@@ -484,7 +484,8 @@ var actionNameZH={
"42":"创建了GCU类型训练任务", "42":"创建了GCU类型训练任务",
"43":"创建了MLU类型调试任务", "43":"创建了MLU类型调试任务",
"44":"创建了MLU类型训练任务", "44":"创建了MLU类型训练任务",
"45":"创建了GPU在线推理任务",
"45":"创建了GPU类型在线推理任务",
"46":"创建了DCU类型调试任务",
}; };


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


var repoAndOrgZH={ var repoAndOrgZH={


+ 6
- 2
routers/api/v1/api.go View File

@@ -59,12 +59,12 @@
package v1 package v1


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


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


"code.gitea.io/gitea/entity"


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


@@ -934,6 +934,10 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/status", reqToken(), bind(api.CreateFileNotebookJobOption{}), repo.FileNoteBookStatus) 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.Group("/repos", func() {
m.Get("/search", repo.Search) m.Get("/search", repo.Search)




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

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


import ( import (
"bufio" "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" "encoding/json"
"fmt" "fmt"
"io" "io"
@@ -23,17 +19,21 @@ import (
"strings" "strings"
"time" "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/services/reward/point/account"


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


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

"code.gitea.io/gitea/modules/convert" "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" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/services/cloudbrain/cloudbrainTask"


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


@@ -122,6 +122,31 @@ func CreateFileNoteBook(ctx *context.APIContext, option api.CreateFileNotebookJo
CreateFileNotebookTask(ctx.Context, option) 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) { func CreateFileNotebookTask(ctx *context.Context, option api.CreateFileNotebookJobOption) {
displayJobName := cloudbrainService.GetDisplayJobName(ctx.User.Name) displayJobName := cloudbrainService.GetDisplayJobName(ctx.User.Name)
jobName := util.ConvertDisplayJobNameToJobName(displayJobName) jobName := util.ConvertDisplayJobNameToJobName(displayJobName)
@@ -1301,7 +1326,16 @@ func CloudBrainModelList(ctx *context.APIContext) {
dirs, err := routerRepo.GetModelDirs(task.JobName, parentDir) dirs, err := routerRepo.GetModelDirs(task.JobName, parentDir)
if err != nil { if err != nil {
log.Error("GetModelDirs failed:%v", err.Error(), ctx.Data["msgID"]) 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 return
} }


@@ -1329,6 +1363,7 @@ func CloudBrainModelList(ctx *context.APIContext) {
"Path": dirArray, "Path": dirArray,
"Dirs": fileInfos, "Dirs": fileInfos,
"task": task, "task": task,
"CanDownload": cloudbrain.CanDeleteJob(ctx.Context, task),
"PageIsCloudBrain": true, "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) aiCenterCodeMap := make(map[string]string)
for _, resourceQueue := range resourceQueues { for _, resourceQueue := range resourceQueues {
if _, ok := aiCenterCodeMap[resourceQueue.AiCenterCode]; !ok { 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 aiCenterCodeMap[resourceQueue.AiCenterCode] = resourceQueue.AiCenterCode
Resource = append(Resource, resourceQueue) Resource = append(Resource, resourceQueue)
} }


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

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

ctx.JSON(http.StatusOK, modelResult) ctx.JSON(http.StatusOK, modelResult)
} }




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

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


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

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

@@ -1310,7 +1310,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/debug", reqWechatBind, cloudbrain.AdminOrJobCreaterRight, repo.GrampusNotebookDebug) m.Get("/debug", reqWechatBind, cloudbrain.AdminOrJobCreaterRight, repo.GrampusNotebookDebug)
m.Get("/commit_image", cloudbrain.AdminOrJobCreaterRight, repo.GrampusCommitImageShow) m.Get("/commit_image", cloudbrain.AdminOrJobCreaterRight, repo.GrampusCommitImageShow)
m.Post("/commit_image", cloudbrain.AdminOrJobCreaterRight, bindIgnErr(auth.CommitImageGrampusForm{}), repo.GrampusCommitImage) m.Post("/commit_image", cloudbrain.AdminOrJobCreaterRight, bindIgnErr(auth.CommitImageGrampusForm{}), repo.GrampusCommitImage)
m.Post("/restart", reqWechatBind, cloudbrain.AdminOrJobCreaterRight, repo.GrampusNotebookRestart)
m.Post("/restart", reqWechatBindForApi, cloudbrain.AdminOrJobCreaterRight, repo.GrampusNotebookRestart)
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.GrampusStopJob) m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.GrampusStopJob)
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.GrampusNotebookDel) m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.GrampusNotebookDel)
}) })
@@ -1332,8 +1332,8 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("", reqRepoCloudBrainReader, repo.GrampusTrainJobShow) m.Get("", reqRepoCloudBrainReader, repo.GrampusTrainJobShow)
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.GrampusStopJob) m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.GrampusStopJob)
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.GrampusTrainJobDel) 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.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, context.PointAccount(), repo.GrampusTrainJobVersionNew)
m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateGrampusTrainJobForm{}), context.PointAccount(), repo.GrampusTrainJobVersionCreate) m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateGrampusTrainJobForm{}), context.PointAccount(), repo.GrampusTrainJobVersionCreate)
}) })
@@ -1417,7 +1417,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Group("/:id", func() { m.Group("/:id", func() {
m.Get("", reqRepoCloudBrainReader, repo.NotebookShow) m.Get("", reqRepoCloudBrainReader, repo.NotebookShow)
m.Get("/debug", cloudbrain.AdminOrJobCreaterRight, repo.NotebookDebug2) m.Get("/debug", cloudbrain.AdminOrJobCreaterRight, repo.NotebookDebug2)
m.Post("/restart", cloudbrain.AdminOrJobCreaterRight, repo.NotebookRestart)
m.Post("/restart", reqWechatBindForApi, cloudbrain.AdminOrJobCreaterRight, repo.NotebookRestart)
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.NotebookStop) m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.NotebookStop)
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.NotebookDel) m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.NotebookDel)
}) })


+ 2
- 0
routers/user/notification.go View File

@@ -73,6 +73,8 @@ func getNotifications(c *context.Context) {
switch keyword { switch keyword {
case "read": case "read":
status = models.NotificationStatusRead status = models.NotificationStatusRead
case "notice":
status = models.NotificationStatusNotice
default: default:
status = models.NotificationStatusUnread status = models.NotificationStatusUnread
} }


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

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


"code.gitea.io/gitea/entity" "code.gitea.io/gitea/entity"
"code.gitea.io/gitea/manager/client/grampus" "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) { func (c C2NetClusterAdapter) CreateOnlineInfer(req entity.CreateNoteBookTaskRequest) (*entity.CreateNoteBookTaskResponse, error) {
log.Info("start to CreateOnlineInfer ")
jobResult, err := grampus.CreateNotebookJob(convertOnlineInfer2Grampus(req)) jobResult, err := grampus.CreateNotebookJob(convertOnlineInfer2Grampus(req))
if err != nil { if err != nil {
log.Error("CreateNoteBook failed: %v", err.Error()) log.Error("CreateNoteBook failed: %v", err.Error())
@@ -81,9 +83,12 @@ func convertNoteBookReq2Grampus(req entity.CreateNoteBookTaskRequest) models.Cre
codePath = codePath[0:strings.LastIndex(codePath, "/")] 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;" 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) 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" // 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 { if models.NPU == req.Tasks[0].Spec.ComputeResource {
command = "" command = ""
@@ -116,7 +121,7 @@ func generateCommand(repoName, bootFile, datasetName string) string {
//prepare //prepare
//command := "bash && cd /code && unzip master.zip && cd test-export-data && uvicorn train:app --host 0.0.0.0 --port $OCTOPUS_NOTEBOOK_PORT" //command := "bash && cd /code && unzip master.zip && cd test-export-data && uvicorn train:app --host 0.0.0.0 --port $OCTOPUS_NOTEBOOK_PORT"
workDir := "/" 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) command += "pwd; cd " + workDir + fmt.Sprintf(model_grampus.CommandPrepareScriptGpu)


//unzip code & dataset //unzip code & dataset
@@ -141,7 +146,9 @@ func generateCommand(repoName, bootFile, datasetName string) string {
if strings.HasSuffix(bootonlyfile, ".py") { if strings.HasSuffix(bootonlyfile, ".py") {
bootonlyfile = bootonlyfile[0 : len(bootonlyfile)-3] 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) log.Info("comand=" + command)
return command return command
@@ -156,18 +163,23 @@ func getCopyCmd(datasetName, repoName, bootfilepath string) string {
} }


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

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


func convertContainer2Grampus(d entity.ContainerData) models.GrampusDataset { func convertContainer2Grampus(d entity.ContainerData) models.GrampusDataset {
return 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,
} }
} }




+ 13
- 2
services/ai_task_service/cluster/cloudbrain_one.go View File

@@ -173,10 +173,15 @@ func (c CloudbrainOneClusterAdapter) GetNoteBookOperationProfile(jobId string) (
log.Error("ConvertToJobResultPayload failed:%v", err) log.Error("ConvertToJobResultPayload failed:%v", err)
return nil, err return nil, err
} }
return parseDiagnosticsToOperationProfile(result.JobStatus.AppExitDiagnostics), nil

taskRoles := result.TaskRoles
taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{}))
ExitDiagnostics := taskRes.TaskStatuses[0].ExitDiagnostics

return parseDiagnosticsToOperationProfile(result.JobStatus.AppExitDiagnostics,ExitDiagnostics), nil
} }


func parseDiagnosticsToOperationProfile(appExitDiagnostics string) *entity.OperationProfile {
func parseDiagnosticsToOperationProfile(appExitDiagnostics string, exitDiagnostics string) *entity.OperationProfile {
if appExitDiagnostics == "" { if appExitDiagnostics == "" {
return nil return nil
} }
@@ -211,6 +216,12 @@ func parseDiagnosticsToOperationProfile(appExitDiagnostics string) *entity.Opera
Action: e.Action, Action: e.Action,
}) })
} }
if exitDiagnostics != ""{
events = append(events, entity.ProfileEvent{
Message: exitDiagnostics,
Reason: "Error",
})
}
return &entity.OperationProfile{Events: events} return &entity.OperationProfile{Events: events}
} }




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

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


import ( import (
"strings"

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


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


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

//再次调试和在线运行notebook不需要下载、上传代码 //再次调试和在线运行notebook不需要下载、上传代码
if !ctx.Request.IsRestartRequest && !ctx.Request.IsFileNoteBookRequest { 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 { if err := DownloadCode(ctx, codeLocalPath, b.Opts.NotArchive); err != nil {
log.Error("downloadZipCode failed, server timed out: %s (%v)", repo.FullName(), err) log.Error("downloadZipCode failed, server timed out: %s (%v)", repo.FullName(), err)
return nil, response.LOAD_CODE_FAILED 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 package container_builder


import ( import (
"strings"

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


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


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

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


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

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


import ( import (
"fmt"

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

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


uploader := upload.SelectUploaderFromStorageType(storageTypes[0]) uploader := upload.SelectUploaderFromStorageType(storageTypes[0])
remoteDir := uploader.GetJobDefaultObjectKeyPrefix(jobName) + cloudbrain.ModelMountPath 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{{ 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 }}, nil
} }




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

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


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

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


"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
@@ -55,7 +57,7 @@ func (g GrampusNoteBookTaskTemplate) GetConfig(opts entity.GetAITaskConfigOpts)
codePath := "/code" codePath := "/code"
datasetPath := "/dataset" datasetPath := "/dataset"
pretrainModelPath := "/pretrainmodel" pretrainModelPath := "/pretrainmodel"
if opts.ComputeSource == models.NPU {
if opts.ComputeSource == models.NPU || opts.ComputeSource == models.DCU {
return entity.AITaskConfig{ return entity.AITaskConfig{
DatasetMaxSize: setting.DebugAttachSize * 1000 * 1000 * 1000, DatasetMaxSize: setting.DebugAttachSize * 1000 * 1000 * 1000,
ContainerSteps: map[entity.ContainerDataType]*entity.ContainerBuildOpts{ 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() createTime := timeutil.TimeStampNow()
res, err := c.CreateNoteBook(req) res, err := c.CreateNoteBook(req)
if err != nil { if err != nil {
@@ -229,6 +234,8 @@ func (GrampusNoteBookTaskTemplate) NotifyCreation(ctx *context.CreationContext)
actionType = models.ActionCreateGrampusGCUDebugTask actionType = models.ActionCreateGrampusGCUDebugTask
case models.MLU: case models.MLU:
actionType = models.ActionCreateGrampusMLUDebugTask actionType = models.ActionCreateGrampusMLUDebugTask
case models.DCU:
actionType = models.ActionCreateGrampusDCUDebugTask
} }
task, err := models.GetCloudbrainByCloudbrainID(ctx.NewCloudbrain.ID) task, err := models.GetCloudbrainByCloudbrainID(ctx.NewCloudbrain.ID)
if err != nil { 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.CheckBranchExists).
Next(t.CheckModel). Next(t.CheckModel).
Next(t.InsertCloudbrainRecord4Async). 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) Operate(ctx)
if err != nil { if err != nil {
log.Error("create GrampusNoteBookTask err.%v", err) 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 { 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 := "" containerPrefix := ""
codePath := "/code" codePath := "/code"
datasetPath := "/dataset" datasetPath := "/dataset"
pretrainModelPath := "/pretrainmodel" pretrainModelPath := "/pretrainmodel"
if opts.ComputeSource == models.GCU {
containerPrefix = "/tmp"
}
outputPath := "/output"


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


+ 31
- 4
services/ai_task_service/task/opt_handler.go View File

@@ -113,11 +113,26 @@ func (DefaultCreationHandler) BuildRequest4Restart(ctx *context.CreationContext)


func (DefaultCreationHandler) CheckDatasetExists(ctx *context.CreationContext) *response.BizError { func (DefaultCreationHandler) CheckDatasetExists(ctx *context.CreationContext) *response.BizError {
log.Info("Start to CheckDataset.displayJobName=%s jobType=%s cluster=%s", ctx.Request.DisplayJobName, ctx.Request.JobType, ctx.Request.Cluster) log.Info("Start to CheckDataset.displayJobName=%s jobType=%s cluster=%s", ctx.Request.DisplayJobName, ctx.Request.JobType, ctx.Request.Cluster)
if hasDatasetDeleted(ctx.Request.DatasetUUIDStr) {
datasetUUIDStr := ctx.Request.DatasetUUIDStr
if datasetUUIDStr == "" {
return nil
}
uuids := strings.Split(datasetUUIDStr, ";")
attachs, _ := models.GetAttachmentsByUUIDs(uuids)

if len(attachs) < len(uuids) {
log.Info("CheckDataset hasDatasetDeleted.displayJobName=%s jobType=%s cluster=%s", ctx.Request.DisplayJobName, ctx.Request.JobType, ctx.Request.Cluster) log.Info("CheckDataset hasDatasetDeleted.displayJobName=%s jobType=%s cluster=%s", ctx.Request.DisplayJobName, ctx.Request.JobType, ctx.Request.Cluster)
return response.DATASET_NOT_EXISTS return response.DATASET_NOT_EXISTS
} }

var datasetNames string
for i := 0; i < len(uuids); i++ {
for j := 0; j < len(attachs); j++ {
if uuids[i] == attachs[j].UUID {
datasetNames += attachs[j].Name + ";"
}
}
}
ctx.Request.DatasetNames = strings.TrimSuffix(datasetNames, ";")
log.Info("CheckDataset success.displayJobName=%s jobType=%s cluster=%s", ctx.Request.DisplayJobName, ctx.Request.JobType, ctx.Request.Cluster) log.Info("CheckDataset success.displayJobName=%s jobType=%s cluster=%s", ctx.Request.DisplayJobName, ctx.Request.JobType, ctx.Request.Cluster)
return nil return nil
} }
@@ -159,7 +174,11 @@ func (DefaultCreationHandler) CheckDatasetSize(ctx *context.CreationContext) *re


func (DefaultCreationHandler) CheckModel(ctx *context.CreationContext) *response.BizError { 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) 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) log.Info("CheckModel hasModelFileDeleted.displayJobName=%s jobType=%s cluster=%s", ctx.Request.DisplayJobName, ctx.Request.JobType, ctx.Request.Cluster)
return response.MODEL_NOT_EXISTS return response.MODEL_NOT_EXISTS
} }
@@ -205,7 +224,7 @@ func (DefaultCreationHandler) CheckOutput4Restart(ctx *context.CreationContext)
if task.Cleared { if task.Cleared {
return response.RESULT_CLEARD return response.RESULT_CLEARD
} }
if !task.IsNPUTask() {
if !(task.IsNPUTask() || task.IsDCUTask()) {
if _, err := os.Stat(getTaskOldJobPath(task)); err != nil { 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) 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 return response.RESULT_CLEARD
@@ -246,6 +265,14 @@ func hasModelFileDeleted(modelId, pretrainModelCkptName string) bool {
return false 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 { func (DefaultCreationHandler) CheckParam(ctx *context.CreationContext) *response.BizError {
req := ctx.Request req := ctx.Request
log.Info("Start to CheckParam.displayJobName=%s jobType=%s cluster=%s", req.DisplayJobName, req.JobType, req.Cluster) log.Info("Start to CheckParam.displayJobName=%s jobType=%s cluster=%s", req.DisplayJobName, req.JobType, req.Cluster)


+ 2
- 1
services/ai_task_service/task/task_service.go View File

@@ -114,6 +114,7 @@ func buildAITaskInfo(task *models.Cloudbrain, creator *models.User, config entit
StartTime: task.StartTime, StartTime: task.StartTime,
EndTime: task.EndTime, EndTime: task.EndTime,
Description: task.Description, Description: task.Description,
FailedReason: task.FailedReason,
CommitID: task.CommitID, CommitID: task.CommitID,
BranchName: task.BranchName, BranchName: task.BranchName,
ImageName: imageName, ImageName: imageName,
@@ -761,7 +762,7 @@ func GetModelDownload(task *models.Cloudbrain) []*models.ModelDownload {
} else { } else {
model, err = models.QueryModelById(task.ModelId) model, err = models.QueryModelById(task.ModelId)
} }
if err != nil {
if err != nil || model == nil {
return pretrainModelList return pretrainModelList
} }




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

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


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


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

"code.gitea.io/gitea/modules/grampus" "code.gitea.io/gitea/modules/grampus"
"code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"
@@ -874,6 +875,13 @@ func fileExists(gitRepo *git.Repository, path string, branch string) (bool, erro
return true, nil 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 { func GrampusNotebookDebug(ctx *context.Context) error {


result, err := grampus.GetNotebookJob(ctx.Cloudbrain.JobID) result, err := grampus.GetNotebookJob(ctx.Cloudbrain.JobID)
@@ -882,8 +890,7 @@ func GrampusNotebookDebug(ctx *context.Context) error {
return err return err
} }
if len(result.JobInfo.Tasks) > 0 { 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 nil
} }
return fmt.Errorf("Can not find the job.") return fmt.Errorf("Can not find the job.")
@@ -1005,6 +1012,9 @@ func GrampusNotebookRestart(ctx *context.Context) {
} else if task.ComputeResource == models.GCUResource { } else if task.ComputeResource == models.GCUResource {
computeSourceSimple = models.GCU computeSourceSimple = models.GCU
action = models.ActionCreateGrampusGCUDebugTask 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{ spec, err = resource.GetAndCheckSpec(ctx.User.ID, oldSpec.ID, models.FindSpecsOptions{


+ 26
- 10
services/cloudbrain/util.go View File

@@ -12,8 +12,9 @@ import (
) )


func GetAiCenterShowByAiCenterId(aiCenterId string, ctx *context.Context) string { func GetAiCenterShowByAiCenterId(aiCenterId string, ctx *context.Context) string {
if setting.AiCenterCodeAndNameAndLocMapInfo != nil {
if info, ok := setting.AiCenterCodeAndNameAndLocMapInfo[aiCenterId]; ok {
aiCenterAndNameInfo := getAiCenterAndNameInfo()
if aiCenterAndNameInfo != nil {
if info, ok := aiCenterAndNameInfo[aiCenterId]; ok {
if ctx.Language() == "zh-CN" { if ctx.Language() == "zh-CN" {
return info.Content return info.Content
} else { } else {
@@ -24,12 +25,19 @@ func GetAiCenterShowByAiCenterId(aiCenterId string, ctx *context.Context) string
return aiCenterId return aiCenterId
} }


func getAiCenterAndNameInfo() map[string]*setting.C2NetSequenceInfo {
if setting.AiCenterCodeAndNameAndLocMapInfo != nil {
return setting.AiCenterCodeAndNameAndLocMapInfo
}
return setting.AiCenterCodeAndNameMapInfo
}

func GetAiCenterShow(aiCenter string, ctx *context.Context) string { func GetAiCenterShow(aiCenter string, ctx *context.Context) string {
aiCenterInfo := strings.Split(aiCenter, "+") aiCenterInfo := strings.Split(aiCenter, "+")

aiCenterAndNameInfo := getAiCenterAndNameInfo()
if len(aiCenterInfo) == 2 { if len(aiCenterInfo) == 2 {
if setting.AiCenterCodeAndNameAndLocMapInfo != nil {
if info, ok := setting.AiCenterCodeAndNameAndLocMapInfo[aiCenterInfo[0]]; ok {
if aiCenterAndNameInfo != nil {
if info, ok := aiCenterAndNameInfo[aiCenterInfo[0]]; ok {
if ctx.Language() == "zh-CN" { if ctx.Language() == "zh-CN" {
return info.Content return info.Content
} else { } else {
@@ -42,11 +50,18 @@ func GetAiCenterShow(aiCenter string, ctx *context.Context) string {
} else { } else {
return aiCenterInfo[1] 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 "" return ""

} }


func GetDisplayJobName(username string) string { func GetDisplayJobName(username string) string {
@@ -72,8 +87,9 @@ func jobNamePrefixValid(s string) string {
} }


func GetAiCenterInfoByCenterCode(aiCenterCode string) *setting.C2NetSequenceInfo { func GetAiCenterInfoByCenterCode(aiCenterCode string) *setting.C2NetSequenceInfo {
if setting.AiCenterCodeAndNameAndLocMapInfo != nil {
if info, ok := setting.AiCenterCodeAndNameAndLocMapInfo[aiCenterCode]; ok {
aiCenterAndNameInfo := getAiCenterAndNameInfo()
if aiCenterAndNameInfo != nil {
if info, ok := aiCenterAndNameInfo[aiCenterCode]; ok {
return info return info
} else { } else {
return nil return nil


+ 55
- 11
services/pull/review.go View File

@@ -29,7 +29,7 @@ func CreateCodeComment(doer *models.User, gitRepo *git.Repository, issue *models
// - Comments that are part of a review // - Comments that are part of a review
// - Comments that reply to an existing review // - Comments that reply to an existing review


if !isReview {
if !isReview && replyReviewID != 0 {
// It's not part of a review; maybe a reply to a review comment or a single comment. // It's not part of a review; maybe a reply to a review comment or a single comment.
// Check if there are reviews for that line already; if there are, this is a reply // Check if there are reviews for that line already; if there are, this is a reply
if existsReview, err = models.ReviewExists(issue, treePath, line); err != nil { if existsReview, err = models.ReviewExists(issue, treePath, line); err != nil {
@@ -77,6 +77,35 @@ func CreateCodeComment(doer *models.User, gitRepo *git.Repository, issue *models
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else {
invalidated := false
first, err := models.FindComments(models.FindCommentsOptions{
ReviewID: review.ID,
Line: line,
TreePath: treePath,
Type: models.CommentTypeCode,
ListOptions: models.ListOptions{
PageSize: 1,
Page: 1,
},
})
if err == nil && len(first) > 0 {
invalidated = first[0].Invalidated
}

if invalidated && replyReviewID == 0 {
review, err = models.CreateReview(models.CreateReviewOptions{
Type: models.ReviewTypePending,
Reviewer: doer,
Issue: issue,
Official: false,
CommitID: latestCommitID,
})
if err != nil {
return nil, err
}
}

} }


comment, err := createCodeComment( comment, err := createCodeComment(
@@ -123,6 +152,7 @@ func createCodeComment(doer *models.User, repo *models.Repository, issue *models
// FIXME validate treePath // FIXME validate treePath
// Get latest commit referencing the commented line // Get latest commit referencing the commented line
// No need for get commit for base branch changes // No need for get commit for base branch changes
invalidated := false
if line > 0 { if line > 0 {
commit, err := gitRepo.LineBlame(pr.GetGitRefName(), gitRepo.Path, treePath, uint(line)) commit, err := gitRepo.LineBlame(pr.GetGitRefName(), gitRepo.Path, treePath, uint(line))
if err == nil { if err == nil {
@@ -134,6 +164,19 @@ func createCodeComment(doer *models.User, repo *models.Repository, issue *models


// Only fetch diff if comment is review comment // Only fetch diff if comment is review comment
if reviewID != 0 { if reviewID != 0 {
first, err := models.FindComments(models.FindCommentsOptions{
ReviewID: reviewID,
Line: line,
TreePath: treePath,
Type: models.CommentTypeCode,
ListOptions: models.ListOptions{
PageSize: 1,
Page: 1,
},
})
if err == nil && len(first) > 0 {
invalidated = first[0].Invalidated
}
headCommitID, err := gitRepo.GetRefCommitID(pr.GetGitRefName()) headCommitID, err := gitRepo.GetRefCommitID(pr.GetGitRefName())
if err != nil { if err != nil {
return nil, fmt.Errorf("GetRefCommitID[%s]: %v", pr.GetGitRefName(), err) return nil, fmt.Errorf("GetRefCommitID[%s]: %v", pr.GetGitRefName(), err)
@@ -145,16 +188,17 @@ func createCodeComment(doer *models.User, repo *models.Repository, issue *models
patch = git.CutDiffAroundLine(patchBuf, int64((&models.Comment{Line: line}).UnsignedLine()), line < 0, setting.UI.CodeCommentLines) patch = git.CutDiffAroundLine(patchBuf, int64((&models.Comment{Line: line}).UnsignedLine()), line < 0, setting.UI.CodeCommentLines)
} }
return models.CreateComment(&models.CreateCommentOptions{ return models.CreateComment(&models.CreateCommentOptions{
Type: models.CommentTypeCode,
Doer: doer,
Repo: repo,
Issue: issue,
Content: content,
LineNum: line,
TreePath: treePath,
CommitSHA: commitID,
ReviewID: reviewID,
Patch: patch,
Type: models.CommentTypeCode,
Doer: doer,
Repo: repo,
Issue: issue,
Content: content,
LineNum: line,
TreePath: treePath,
CommitSHA: commitID,
ReviewID: reviewID,
Patch: patch,
Invalidated: invalidated,
}) })
} }




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

@@ -10,7 +10,7 @@ import (
"github.com/elliotchance/orderedmap" "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 { type ClientsManager struct {
Clients *orderedmap.OrderedMap 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=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=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=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> </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;"> <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=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=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=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> </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;"> <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="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/vue-2.6.10.min.js?v={{MD5 AppVer}}"></script>
<script src="/rotation3D/rotation3D.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 html =document.documentElement;
var lang = html.attributes["lang"] var lang = html.attributes["lang"]
var isZh = true; 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 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> <h2>{{.i18n.Tr "home.c2net_title"}}</h2>
<p><span class="ui text grey">{{.i18n.Tr "home.c2net_desc"}}</p> <p><span class="ui text grey">{{.i18n.Tr "home.c2net_desc"}}</p>
<div style="display:flex;align-items:center;justify-content:center;"> <div style="display:flex;align-items:center;justify-content:center;">
@@ -9,5 +9,8 @@
</div> </div>
<div id="__vue-root"></div> <div id="__vue-root"></div>
</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> <script src="{{StaticUrlPrefix}}/js/vp-screen-map.js?v={{MD5 AppVer}}"></script>

+ 1
- 34
templates/notice.tmpl View File

@@ -1,38 +1,5 @@


{{template "base/head_home" .}} {{template "base/head_home" .}}
<style>
.notice-container {
}
.notice-row {
display: flex;
justify-content: space-between;
align-items: center;
height: 52px;
border-bottom: 1px solid rgba(157, 197, 226, 0.2);
padding: 0 16px;
}
.notice-title {
flex: 1;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.notice-title a {
font-size: 16px;
color: rgb(16, 16, 16);
}
.notice-title a:hover {
opacity: 0.8;
}
.notice-time {
width: 150px;
text-align: right;
font-size: 14px;
color: rgba(16, 16, 16, 0.6);
}
</style>
<div class="ui container"> <div class="ui container">
<h3 class="ui center am-pt-30 am-pb-20">{{.i18n.Tr "notice_announcement"}}</h3> <h3 class="ui center am-pt-30 am-pb-20">{{.i18n.Tr "notice_announcement"}}</h3>
<div class="notice-container"> <div class="notice-container">
@@ -41,7 +8,6 @@
{{template "base/footer" .}} {{template "base/footer" .}}
<script> <script>
;(function() { ;(function() {
var isZh = document.documentElement.getAttribute('lang') == 'zh-CN';
function getNotice() { function getNotice() {
$.ajax({ $.ajax({
type:"GET", type:"GET",
@@ -51,6 +17,7 @@
filename: 'notice/notice.json', filename: 'notice/notice.json',
}, },
success:function(data){ success:function(data){
var isZh = document.documentElement.getAttribute('lang') == 'zh-CN';
if (!data) return; if (!data) return;
try { try {
var noticeList = JSON.parse(data).Notices || []; var noticeList = JSON.parse(data).Notices || [];


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

@@ -61,7 +61,7 @@
{{if $.RepoIsEmpty}} {{if $.RepoIsEmpty}}
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.repo_not_initialized" .RepoLink | Safe}}</div> <div class="bgtask-content-txt">{{$.i18n.Tr "repo.repo_not_initialized" .RepoLink | Safe}}</div>
{{end}} {{end}}
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.platform_instructions" | Safe}}</div>
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.platform_instructions" "https://openi.pcl.ac.cn/docs/index.html#/cloudbrain/eval" | Safe}}</div>
</div> </div>
</div> </div>
{{else}} {{else}}


+ 1
- 1
templates/repo/modelarts/inferencejob/index.tmpl View File

@@ -67,7 +67,7 @@
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.model_not_exist" .RepoLink .RepoLink | Safe}}</div> <div class="bgtask-content-txt">{{$.i18n.Tr "repo.model_not_exist" .RepoLink .RepoLink | Safe}}</div>
{{end}} {{end}}
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.dataset_desc"}}</div> <div class="bgtask-content-txt">{{$.i18n.Tr "repo.dataset_desc"}}</div>
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.platform_instructions" | Safe}}</div>
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.platform_instructions" "https://openi.pcl.ac.cn/docs/index.html#/cloudbrain/infer/inference-job" | Safe}}</div>
</div> </div>
</div> </div>
{{else}} {{else}}


+ 1
- 1
templates/repo/modelarts/trainjob/index.tmpl View File

@@ -72,7 +72,7 @@
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.repo_not_initialized" .RepoLink | Safe}}</div> <div class="bgtask-content-txt">{{$.i18n.Tr "repo.repo_not_initialized" .RepoLink | Safe}}</div>
{{end}} {{end}}
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.dataset_desc"}}</div> <div class="bgtask-content-txt">{{$.i18n.Tr "repo.dataset_desc"}}</div>
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.platform_instructions" | Safe}}</div>
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.platform_instructions" "https://openi.pcl.ac.cn/docs/index.html#/cloudbrain/train/train" | Safe}}</div>
</div> </div>
</div> </div>
{{else}} {{else}}


+ 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}} {{$.i18n.Tr "action.task_c2ent_mludebugjob" .GetRepoLink (Printf "%d" .Cloudbrain.ID) .RefName | Str2html}}
{{else}} {{else}}
{{$.i18n.Tr "action.task_c2ent_mludebugjob" "" "" "" | Str2html}}<span style="">{{.RefName}}{{$.i18n.Tr "repo.issues.deleted_milestone"}}</span> {{$.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}} {{end}}
{{else if eq .GetOpType 44}} {{else if eq .GetOpType 44}}
{{$.i18n.Tr "action.task_c2ent_mlutrainjob" .GetRepoLink .Content .RefName | Str2html}} {{$.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> <span class="text grey"><i class="ri-voice-recognition-line icon big"></i></span>
{{else if eq .GetOpType 45}} {{else if eq .GetOpType 45}}
<span class="text grey"><i class="ri-voice-recognition-line icon big"></i></span> <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}} {{else if eq .GetOpType 27}}
<span class="text grey"><i class="ri-character-recognition-line icon big"></i></span> <span class="text grey"><i class="ri-character-recognition-line icon big"></i></span>
{{else if eq .GetOpType 28}} {{else if eq .GetOpType 28}}


+ 1
- 1
templates/user/notification/notification.tmpl View File

@@ -1,3 +1,3 @@
{{template "base/head" .}} {{template "base/head" .}}
{{template "user/notification/notification_div" .}} {{template "user/notification/notification_div" .}}
{{template "base/footer" .}}
{{template "base/footer" .}}

+ 10
- 1
templates/user/notification/notification_div.tmpl View File

@@ -10,6 +10,9 @@
<a href="{{AppSubUrl}}/notifications?q=read" class="{{if eq .Status 2}}active{{end}} item"> <a href="{{AppSubUrl}}/notifications?q=read" class="{{if eq .Status 2}}active{{end}} item">
{{.i18n.Tr "notification.read"}} {{.i18n.Tr "notification.read"}}
</a> </a>
<a href="{{AppSubUrl}}/notifications?q=notice" class="{{if eq .Status 3}}active{{end}} item">
{{.i18n.Tr "notification.notice"}}
</a>
{{if and (eq .Status 1)}} {{if and (eq .Status 1)}}
<form action="{{AppSubUrl}}/notifications/purge" method="POST" style="margin-left: auto;"> <form action="{{AppSubUrl}}/notifications/purge" method="POST" style="margin-left: auto;">
{{$.CsrfTokenHtml}} {{$.CsrfTokenHtml}}
@@ -25,8 +28,14 @@
{{if eq (len .Notifications) 0}} {{if eq (len .Notifications) 0}}
{{if eq .Status 1}} {{if eq .Status 1}}
{{.i18n.Tr "notification.no_unread"}} {{.i18n.Tr "notification.no_unread"}}
{{else}}
{{else if eq .Status 2}}
{{.i18n.Tr "notification.no_read"}} {{.i18n.Tr "notification.no_read"}}
{{else}}
<div class="notice-container" id="notice-container-json" style="min-height: 100px;">
<div class="ui inverted active dimmer" style="display: none;">
<div class="ui loader"></div>
</div>
</div>
{{end}} {{end}}
{{else}} {{else}}
<table class="ui unstackable striped very compact small selectable table" id="notification_table"> <table class="ui unstackable striped very compact small selectable table" id="notification_table">


+ 44
- 0
web_src/js/features/notification.js View File

@@ -16,6 +16,12 @@ export function initNotificationsTable() {


return false; return false;
}); });
const notificationDiv= $('#notice-container-json');
if (!notificationDiv.length) {
return;
} else {
getNotice()
}
} }


export function initNotificationCount() { export function initNotificationCount() {
@@ -139,6 +145,44 @@ export function initNotificationCount() {


fn(NotificationSettings.MinTimeout, notificationCount.text()); fn(NotificationSettings.MinTimeout, notificationCount.text());
} }
function getNotice() {
$('.notice-container .ui.dimmer').css('display','block')
$.ajax({
type:"GET",
url:"/dashboard/invitation",
dataType:"json",
data: {
filename: 'notice/notice.json',
},
success: function (data) {
$('.notice-container .ui.dimmer').css('display','none')
const isZh = document.documentElement.getAttribute('lang') == 'zh-CN';
if (!data) return;
try {
const noticeList = JSON.parse(data).Notices || [];
const noticeEl = $('.notice-container');
for (let i = 0, iLen = noticeList.length; i < iLen; i++) {
let noticeObj = noticeList[i];
noticeEl.append(`<div class="notice-row">
<div class="notice-title">
<a class="_hm-notice" href="${noticeObj.Link}">
<i class="ri-arrow-right-s-line" style="vertical-align:-2px;"></i>
<span>${isZh ? noticeObj.Title : (noticeObj.Title_en || noticeObj.Title)}</span>
</a>
</div>
<div class="notice-time">${noticeObj.Date || ''}</div>
</div>`);
}
} catch (e) {
console.info(e);
}
},
error: function (err) {
$('.notice-container .ui.dimmer').css('display','none')
console.info(err);
}
});
}


async function updateNotificationCountWithCallback(callback, timeout, lastCount) { async function updateNotificationCountWithCallback(callback, timeout, lastCount) {
const currentCount = $('.notification_count').text(); const currentCount = $('.notification_count').text();


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

@@ -1,12 +1,12 @@
import Vue from 'vue' import Vue from 'vue'
import Router from 'vue-router' 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' import IdeProject from '../components/IdeProject.vue'


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


export default new 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,
},
*/
],
}) })

+ 29
- 0
web_src/less/openi.less View File

@@ -1512,4 +1512,33 @@ i.SUCCEEDED {
span{ span{
color: rgba(242, 113, 28, 1); color: rgba(242, 113, 28, 1);
} }
}

.notice-row {
display: flex;
justify-content: space-between;
align-items: center;
height: 52px;
border-bottom: 1px solid rgba(157, 197, 226, 0.2);
padding: 0 16px;
}
.notice-title {
flex: 1;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.notice-title a {
font-size: 16px;
color: rgb(16, 16, 16);
}
.notice-title a:hover {
opacity: 0.8;
}
.notice-time {
width: 150px;
text-align: right;
font-size: 14px;
color: rgba(16, 16, 16, 0.6);
} }

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




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

@@ -2,7 +2,12 @@
<div class="form-row"> <div class="form-row">
<div class="title"><span :class="required ? 'required' : ''">{{ $t('cloudbrainObj.resourceSpec') }}</span></div> <div class="title"><span :class="required ? 'required' : ''">{{ $t('cloudbrainObj.resourceSpec') }}</span></div>
<div class="content" :class="errStatus ? 'error' : ''"> <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" <el-select class="spec-sel field-input" :class="configs.showPoint ? 'spec-show-point' : ''" v-model="spec"
:placeholder="$t('cloudbrainObj.specPlaceholder')" @change="changeSpec"> :placeholder="$t('cloudbrainObj.specPlaceholder')" @change="changeSpec">
<div slot="prefix" class="spec-sel-icon spec-op-icon"> <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]; return this.list.filter(item => item.id == this.spec)[0];
}, },
}, },
beforeMount() { }
beforeMount() {
}
}; };
</script> </script>


@@ -153,7 +159,21 @@ export default {
flex: inherit; flex: inherit;
width: 50%; width: 50%;
margin-right: 5px; 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 { .spec-info {
flex: 1; flex: 1;


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


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


+ 21
- 1
web_src/vuepages/components/cloudbrain/details/ConfigInfo.vue View File

@@ -1,7 +1,11 @@
<template> <template>
<div class="item-container"> <div class="item-container">
<template v-for="(item, index) in configs.fields"> <template v-for="(item, index) in configs.fields">
<div v-if="item != 'dataset' && item != 'modelList'" class="item-block">
<div v-if="item != 'dataset' && item != 'modelList' && item != 'failedReason'" class="item-block">
<div class="title"> {{ renderTitle(item) }} </div>
<div class="content" v-html="renderContent(item)"></div>
</div>
<div v-if="item == 'failedReason' && renderContent(item)" class="item-block item-failed-reason">
<div class="title"> {{ renderTitle(item) }} </div> <div class="title"> {{ renderTitle(item) }} </div>
<div class="content" v-html="renderContent(item)"></div> <div class="content" v-html="renderContent(item)"></div>
</div> </div>
@@ -180,6 +184,9 @@ export default {
case 'bootFile': case 'bootFile':
result = i18n.t('modelManage.bootFile'); result = i18n.t('modelManage.bootFile');
break; break;
case 'failedReason':
result = i18n.t('cloudbrainObj.failedReason');
break;
default: default:
break; break;
} }
@@ -280,6 +287,9 @@ export default {
case 'bootFile': case 'bootFile':
result = task.boot_file; result = task.boot_file;
break; break;
case 'failedReason':
result = task.failed_reason;
break;
default: default:
break; break;
} }
@@ -376,6 +386,16 @@ export default {
} }
} }
} }

&.item-failed-reason {
width: 100%;

.content {
overflow: auto;
text-overflow: clip;
white-space: break-spaces;
}
}
} }


/deep/.clipboard { /deep/.clipboard {


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

@@ -1,8 +1,8 @@
<template> <template>
<div class="item-container"> <div class="item-container">
<div class="content"> <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 style="width:100%;margin-right:20px;">
<div class="title files-path-c"> <div class="title files-path-c">
<div class="file-path" v-for="(item, index) in filePath"> <div class="file-path" v-for="(item, index) in filePath">
@@ -15,13 +15,14 @@
</div> </div>
</div> </div>
<div class="right-btn-c"> <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> </a>
</div> </div>
</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 <el-table-column column-key="FileName" prop="FileName" sortable
:sort-method="(a, b) => a.FileName.toLocaleLowerCase().localeCompare(b.FileName.toLocaleLowerCase())" :sort-method="(a, b) => a.FileName.toLocaleLowerCase().localeCompare(b.FileName.toLocaleLowerCase())"
:label="$t('modelManage.fileName')" align="left" header-align="left"> :label="$t('modelManage.fileName')" align="left" header-align="left">
@@ -33,8 +34,8 @@
<span>{{ scope.row.FileName }}</span> <span>{{ scope.row.FileName }}</span>
</div> </div>
</a> </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"> <div class="fitted" :title="scope.row.FileName">
<i class="icon file" width="16" height="16" aria-hidden="true"></i> <i class="icon file" width="16" height="16" aria-hidden="true"></i>
<span>{{ scope.row.FileName }}</span> <span>{{ scope.row.FileName }}</span>
@@ -44,13 +45,41 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column column-key="SizeShow" prop="SizeShow" sortable :sort-method="(a, b) => a.Size - b.Size" <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>
<el-table-column column-key="ModTime" prop="ModTime" sortable <el-table-column column-key="ModTime" prop="ModTime" sortable
:sort-method="(a, b) => a.ModTimeNum - b.ModTimeNum" :label="$t('modelManage.updateTime')" align="center" :sort-method="(a, b) => a.ModTimeNum - b.ModTimeNum" :label="$t('modelManage.updateTime')" align="center"
header-align="center" width="200"> header-align="center" width="200">
</el-table-column> </el-table-column>
</el-table> </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> </div>
</div> </div>
@@ -58,7 +87,10 @@
</template> </template>


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


@@ -70,45 +102,64 @@ export default {
}, },
data() { data() {
return { return {
version: 'V0001',
filesList: [], filesList: [],
filePath: [], filePath: [],
canDownload: true,
loading: false, loading: false,
isTaskTerminal: null,
canDownload: true,
canReschedule: false,
resultStatus: -2,
resultPath: '',
}; };
}, },
methods: { methods: {
getDirFiles(dir) { getDirFiles(dir) {
dir = dir.length ? dir.slice(1) : ''; 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 => { }).then(res => {
this.loading = false;
res = res.data; 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 || []; 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 => { }).catch(err => {
this.loading = false;
console.log(err); console.log(err);
}); });
}, },
@@ -126,13 +177,37 @@ export default {
const dir = this.filePath.map((item) => item.path).join('/'); const dir = this.filePath.map((item) => item.path).join('/');
this.getDirFiles(dir); 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() { 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.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() { } beforeMount() { }
@@ -144,6 +219,8 @@ export default {
margin-bottom: 20px; margin-bottom: 20px;


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

.top { .top {
display: flex; display: flex;
align-items: center; 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 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 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') }]; 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') }];


// 模型 // 模型


+ 24
- 6
web_src/vuepages/langs/config/en-US.js View File

@@ -101,7 +101,7 @@ const en = {
emptyPage: 'Request forbidden by administrative rules', emptyPage: 'Request forbidden by administrative rules',
emptyPageDescr: 'The page you are trying to reach either <strong>does not exist</strong> or <strong>you are not authorized</strong> to view it.', emptyPageDescr: 'The page you are trying to reach either <strong>does not exist</strong> or <strong>you are not authorized</strong> to view it.',
handleTask: 'Processing tasks', handleTask: 'Processing tasks',
freeCompute:'Inclusive computing power',
freeCompute: 'Inclusive computing power',
resourcesManagement: { resourcesManagement: {
OpenI: 'OpenI', OpenI: 'OpenI',
C2Net: 'C2Net', C2Net: 'C2Net',
@@ -303,7 +303,7 @@ const en = {
trainTask: 'Train task', trainTask: 'Train task',
codeBranch: 'Code branch', codeBranch: 'Code branch',
bootFile: 'Boot file', bootFile: 'Boot file',
viewSamples:'View samples',
viewSamples: 'View samples',
trainDataset: 'Train dataset', trainDataset: 'Train dataset',
datasetfile: 'Dataset files', datasetfile: 'Dataset files',
specInfo: 'Specifications', specInfo: 'Specifications',
@@ -343,6 +343,13 @@ const en = {
derivedModel: 'Derived Model', derivedModel: 'Derived Model',
refRepository: 'Reference repository', refRepository: 'Reference repository',
modelDownloadAll: 'Download All', 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: { repos: {
activeOrganization: 'Active Organization', activeOrganization: 'Active Organization',
@@ -413,7 +420,8 @@ const en = {
model_search: 'Search model', model_search: 'Search model',
model_square_empty: 'No Models', 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]', 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: { datasetObj: {
dataset_label: "Dataset", dataset_label: "Dataset",
@@ -436,6 +444,7 @@ const en = {
}, },
specObj: { 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', 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: { datasets: {
computer_vision: "computer vision", computer_vision: "computer vision",
@@ -479,7 +488,7 @@ const en = {
downloadtimes: 'Download times', downloadtimes: 'Download times',
citations: 'Citations', citations: 'Citations',
default: "Default", default: "Default",
latest: "Newest",
newest: "Newest",
oldest: "Oldest", oldest: "Oldest",
recentupdate: "Recently updated", recentupdate: "Recently updated",
leastupdate: "Least recently updated", leastupdate: "Least recently updated",
@@ -556,6 +565,7 @@ const en = {
log: 'Log', log: 'Log',
resourceOccupancy: 'Resource Occupancy', resourceOccupancy: 'Resource Occupancy',
modelDownload: 'Model Download', modelDownload: 'Model Download',
failedReason: 'Failed reason',
publicImage: 'Public Image', publicImage: 'Public Image',
myImage: 'My Images', myImage: 'My Images',
myFavImage: 'My collected images', myFavImage: 'My collected images',
@@ -570,9 +580,9 @@ const en = {
debugTaskEmptyTitle: 'Debug task has not been created', debugTaskEmptyTitle: 'Debug task has not been created',
debugTaskEmptyTip1: 'Running time: no more than 4 hours, it will automatically stop if it exceeds 4 hours;', debugTaskEmptyTip1: 'Running time: no more than 4 hours, it will automatically stop if it exceeds 4 hours;',
debugTaskEmptyTip2: 'Dataset: Cloud Brain 1 provides CPU/GPU,Cloud Brain 2 provides Ascend NPU.And dataset also needs to be uploaded to the corresponding environment;', debugTaskEmptyTip2: 'Dataset: Cloud Brain 1 provides CPU/GPU,Cloud Brain 2 provides Ascend NPU.And dataset also needs to be uploaded to the corresponding environment;',
debugTaskEmptyTip3: 'Instructions for use: You can refer to the <a href="https://openi.pcl.ac.cn/zeizei/OpenI_Learning"> OpenI_Learning </a> course of Qizhi AI collaboration platform.',
debugTaskEmptyTip3: 'Instructions for use: You can refer to the OpenI AI collaboration platform<a href="{url}"> Help Center </a>.',
onlineInferTaskEmptyTitle: 'Online Inference task has not been created', onlineInferTaskEmptyTitle: 'Online Inference task has not been created',
onlineInferEmptyTip2:'Dataset: Cloud Brain 1 provides CPU/GPU,Cloud Brain 2 provides Ascend NPU.And dataset also needs to be uploaded to the corresponding environment;',
onlineInferEmptyTip2: 'Dataset: Cloud Brain 1 provides CPU/GPU,Cloud Brain 2 provides Ascend NPU.And dataset also needs to be uploaded to the corresponding environment;',
deleteConfirmTips: 'Are you sure you want to delete this task? Once this task is deleted, it cannot be recovered.', deleteConfirmTips: 'Are you sure you want to delete this task? Once this task is deleted, it cannot be recovered.',
deletingTips: 'Task deletion in progress, please wait', deletingTips: 'Task deletion in progress, please wait',
tabTitDebug: 'Debug Task', tabTitDebug: 'Debug Task',
@@ -580,6 +590,14 @@ const en = {
tabTitInference: 'Inference Job', tabTitInference: 'Inference Job',
tabTitBenchmark: 'Model Evaluation', tabTitBenchmark: 'Model Evaluation',
tabTitOnlineInference: 'Online Inference', 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",


}, },
} }


+ 23
- 5
web_src/vuepages/langs/config/zh-CN.js View File

@@ -100,7 +100,7 @@ const zh = {
emptyPage: '您的访问受限!', emptyPage: '您的访问受限!',
emptyPageDescr: '您正尝试访问的页面 <strong>不存在</strong> 或 <strong>您尚未被授权</strong> 查看该页面。', emptyPageDescr: '您正尝试访问的页面 <strong>不存在</strong> 或 <strong>您尚未被授权</strong> 查看该页面。',
handleTask: '处理任务', handleTask: '处理任务',
freeCompute:'普惠算力',
freeCompute: '普惠算力',
resourcesManagement: { resourcesManagement: {
OpenI: "启智集群", OpenI: "启智集群",
C2Net: "智算集群", C2Net: "智算集群",
@@ -319,7 +319,7 @@ const zh = {
trainTask: '训练任务', trainTask: '训练任务',
codeBranch: '代码分支', codeBranch: '代码分支',
bootFile: '启动文件', bootFile: '启动文件',
viewSamples:'查看样例',
viewSamples: '查看样例',
trainDataset: '训练数据集', trainDataset: '训练数据集',
datasetfile: '数据集文件', datasetfile: '数据集文件',
specInfo: '规格', specInfo: '规格',
@@ -359,6 +359,13 @@ const zh = {
derivedModel: '衍生模型', derivedModel: '衍生模型',
refRepository: '引用项目', refRepository: '引用项目',
modelDownloadAll: '下载全部模型文件', modelDownloadAll: '下载全部模型文件',
otherOnline: '其他在线体验入口',
trainUsedDataList: '训练该模型使用的数据集',
modelUseTaskList: '使用该模型的任务',
forkModelSuccess: '模型内容复制完成,fork成功!',
debugModel: '调试模型',
onlineInference: '在线体验',
deleted:'已删除',
}, },
repos: { repos: {
activeOrganization: '活跃组织', activeOrganization: '活跃组织',
@@ -429,7 +436,8 @@ const zh = {
model_search: '搜索模型', model_search: '搜索模型',
model_square_empty: '空荡荡的,什么都没有', model_square_empty: '空荡荡的,什么都没有',
model_suport_file_tips: '模型文件支持的格式为 [ckpt, pb, h5, json, pkl, pth, t7, pdparams, onnx, pbtxt, keras, mlmodel, cfg, pt]', 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: { datasetObj: {
dataset_label: "数据集", dataset_label: "数据集",
@@ -452,6 +460,7 @@ const zh = {
}, },
specObj: { specObj: {
resSelectTips: '「资源规格」是您运行该任务使用的硬件,为了更多人能够使用本平台的资源,请按照您的实际需求进行选择。', resSelectTips: '「资源规格」是您运行该任务使用的硬件,为了更多人能够使用本平台的资源,请按照您的实际需求进行选择。',
no_use_resource: '暂无可用资源'
}, },
datasets: { datasets: {
computer_vision: "计算机视觉", computer_vision: "计算机视觉",
@@ -494,7 +503,7 @@ const zh = {
downloadtimes: '下载次数', downloadtimes: '下载次数',
citations: '引用次数', citations: '引用次数',
default: "默认排序", default: "默认排序",
latest: "最新创建",
newest: "最新创建",
oldest: "最早创建", oldest: "最早创建",
recentupdate: "最近更新", recentupdate: "最近更新",
leastupdate: "最少更新", leastupdate: "最少更新",
@@ -572,6 +581,7 @@ const zh = {
log: '日志', log: '日志',
resourceOccupancy: '资源占用情况', resourceOccupancy: '资源占用情况',
modelDownload: '结果下载', modelDownload: '结果下载',
failedReason: '运行失败原因',
publicImage: '公开镜像', publicImage: '公开镜像',
myImage: '我的镜像', myImage: '我的镜像',
myFavImage: '我收藏的镜像', myFavImage: '我收藏的镜像',
@@ -586,7 +596,7 @@ const zh = {
debugTaskEmptyTitle: '未创建过调试任务', debugTaskEmptyTitle: '未创建过调试任务',
debugTaskEmptyTip1: '运行时长:最长不超过4个小时,超过4个小时将自动停止;', debugTaskEmptyTip1: '运行时长:最长不超过4个小时,超过4个小时将自动停止;',
debugTaskEmptyTip2: '数据集:云脑1提供 CPU / GPU 资源,云脑2提供 Ascend NPU 资源,调试使用的数据集也需要上传到对应的环境;', debugTaskEmptyTip2: '数据集:云脑1提供 CPU / GPU 资源,云脑2提供 Ascend NPU 资源,调试使用的数据集也需要上传到对应的环境;',
debugTaskEmptyTip3: '使用说明:可以参考启智AI协作平台<a href="https://openi.pcl.ac.cn/zeizei/OpenI_Learning">小白训练营课程</a>。',
debugTaskEmptyTip3: '使用说明:可以参考启智AI协作平台 <a href="{url}" target="_blank">帮助中心</a>。',
onlineInferTaskEmptyTitle: '未创建过在线推理任务', onlineInferTaskEmptyTitle: '未创建过在线推理任务',
onlineInferEmptyTip2: '数据集:云脑1提供 CPU / GPU 资源,云脑2提供 Ascend NPU 资源,在线推理使用的数据集也需要上传到对应的环境;', onlineInferEmptyTip2: '数据集:云脑1提供 CPU / GPU 资源,云脑2提供 Ascend NPU 资源,在线推理使用的数据集也需要上传到对应的环境;',
deleteConfirmTips: '您确认删除该任务么?此任务一旦删除不可恢复。', deleteConfirmTips: '您确认删除该任务么?此任务一旦删除不可恢复。',
@@ -596,6 +606,14 @@ const zh = {
tabTitInference: '推理任务', tabTitInference: '推理任务',
tabTitBenchmark: '评测任务', tabTitBenchmark: '评测任务',
tabTitOnlineInference: '在线推理', tabTitOnlineInference: '在线推理',
allResultDownload: '全部结果下载',
downloadDisplayMaxCountTips: '单目录下最多显示100个文件或文件夹',
file_sync_ing: "文件同步中,请稍侯",
file_sync_wait: "文件等待同步中,请稍侯",
file_sync_fail: "文件同步失败",
no_file_to_download: "没有文件可以下载,稍后再来看看",
task_not_finished: "任务还未结束,稍后再来看看",
retrieve_results: "重新获取结果",


}, },
} }


+ 55
- 4
web_src/vuepages/pages/cloudbrain/configs.js View File

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


const CLUSTERS = [{ k: 'OpenI', v: i18n.t('cloudbrainObj.openi') }, { k: 'C2Net', v: i18n.t('cloudbrainObj.c2net') }]; 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 = { 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> 中以供后续下载。', '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': [{ 'C2Net': [{
url: 'grampus/notebook/create?type=0', url: 'grampus/notebook/create?type=0',
computerResouces: ['GPU', 'NPU', 'GCU', 'MLU'],
computerResouces: ['GPU', 'NPU', 'GCU', 'MLU', 'DCU'],
'GPU': [{ 'GPU': [{
url: 'grampus/notebook/create?type=0', url: 'grampus/notebook/create?type=0',
clusterType: 'C2Net', clusterType: 'C2Net',
@@ -135,6 +135,24 @@ export const CreatePageConfigs = {
spec: { required: true }, 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: 'NPU', v: 'NPU' },
{ k: 'GCU', v: 'GCU' }, { k: 'GCU', v: 'GCU' },
{ k: 'MLU', v: 'MLU' }, { k: 'MLU', v: 'MLU' },
{ k: 'DCU', v: 'DCU' },
], ],
pages: [{ pages: [{
jobType: 'DEBUG', jobType: 'DEBUG',
@@ -295,7 +314,7 @@ export const ListPageConfigs = {
emptyTitle: i18n.t('cloudbrainObj.debugTaskEmptyTitle'), emptyTitle: i18n.t('cloudbrainObj.debugTaskEmptyTitle'),
emptyTip1: i18n.t('cloudbrainObj.debugTaskEmptyTip1'), emptyTip1: i18n.t('cloudbrainObj.debugTaskEmptyTip1'),
emptyTip2: i18n.t('cloudbrainObj.debugTaskEmptyTip2'), emptyTip2: i18n.t('cloudbrainObj.debugTaskEmptyTip2'),
emptyTip3: i18n.t('cloudbrainObj.debugTaskEmptyTip3'),
emptyTip3: i18n.t('cloudbrainObj.debugTaskEmptyTip3', {url:'https://openi.pcl.ac.cn/docs/index.html#/cloudbrain/debug/debug'}),
}, { }, {
jobType: 'TRAIN', jobType: 'TRAIN',
jobTypeName: getListValueWithKey(JOB_TYPE, 'TRAIN'), jobTypeName: getListValueWithKey(JOB_TYPE, 'TRAIN'),
@@ -325,7 +344,7 @@ export const ListPageConfigs = {
emptyTitle: i18n.t('cloudbrainObj.onlineInferTaskEmptyTitle'), emptyTitle: i18n.t('cloudbrainObj.onlineInferTaskEmptyTitle'),
emptyTip2: i18n.t('cloudbrainObj.onlineInferEmptyTip2'), emptyTip2: i18n.t('cloudbrainObj.onlineInferEmptyTip2'),
emptyTip3: i18n.t('cloudbrainObj.debugTaskEmptyTip3'),
emptyTip3: i18n.t('cloudbrainObj.debugTaskEmptyTip3', { url:'https://openi.pcl.ac.cn/docs/index.html#/cloudbrain/infer/online-inference'}),
}] }]
}; };
export const DetailPageConfigs = { export const DetailPageConfigs = {
@@ -351,6 +370,7 @@ export const DetailPageConfigs = {
'endTime', 'modelPath', 'endTime', 'modelPath',
'duration', 'outputPath', 'duration', 'outputPath',
'descr', '', 'descr', '',
'failedReason',
'dataset', 'dataset',
'modelList', 'modelList',
] ]
@@ -380,6 +400,7 @@ export const DetailPageConfigs = {
'endTime', '', 'endTime', '',
'duration', '', 'duration', '',
'descr', '', 'descr', '',
'failedReason',
'dataset', 'dataset',
'modelList', 'modelList',
], ],
@@ -406,6 +427,7 @@ export const DetailPageConfigs = {
'endTime', 'datasetPath', 'endTime', 'datasetPath',
'duration', 'modelPath', 'duration', 'modelPath',
'descr', '', 'descr', '',
'failedReason',
'dataset', 'dataset',
'modelList', 'modelList',
] ]
@@ -430,6 +452,7 @@ export const DetailPageConfigs = {
'endTime', '', 'endTime', '',
'duration', '', 'duration', '',
'descr', '', 'descr', '',
'failedReason',
'dataset', 'dataset',
'modelList', 'modelList',
], ],
@@ -456,6 +479,7 @@ export const DetailPageConfigs = {
'endTime', '', 'endTime', '',
'duration', '', 'duration', '',
'descr', '', 'descr', '',
'failedReason',
'dataset', 'dataset',
'modelList', 'modelList',
] ]
@@ -480,6 +504,7 @@ export const DetailPageConfigs = {
'endTime', '', 'endTime', '',
'duration', '', 'duration', '',
'descr', '', 'descr', '',
'failedReason',
'dataset', 'dataset',
'modelList', 'modelList',
] ]
@@ -487,6 +512,30 @@ export const DetailPageConfigs = {
name: 'operationProfile' 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'
}],
}],
}] }]
}], }],
/* /*
@@ -612,6 +661,8 @@ export const DetailPageConfigs = {
] ]
}, { }, {
name: 'operationProfile' name: 'operationProfile'
},{
name: 'resultDownload'
}], }],
}], }],
}] }]


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

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


export default { export default {
data() { data() {
@@ -141,6 +142,7 @@ export default {
maskLoading: false, maskLoading: false,
maskLoadingContent: '', maskLoadingContent: '',
datasetSize: 0, datasetSize: 0,
noSpecFlag:false,
}; };
}, },
components: { components: {
@@ -251,6 +253,35 @@ export default {
window.history.back(); 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() { beforeMount() {
const urlParams = getUrlSearchParams(); const urlParams = getUrlSearchParams();
@@ -266,6 +297,31 @@ export default {
this.cancel(); this.cancel();
return; return;
} }
if(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({ getAiTaskPrepareInfo({
repoOwnerName: this.repoOwnerName, repoOwnerName: this.repoOwnerName,
repoName: this.repoName, repoName: this.repoName,
@@ -282,8 +338,10 @@ export default {
this.specConfigs.showPoint = data.pay_switch; this.specConfigs.showPoint = data.pay_switch;
this.specConfigs.blance = data.point_account ? data.point_account.balance : 0; this.specConfigs.blance = data.point_account ? data.point_account.balance : 0;
this.specConfigs.specs = data.specs || []; this.specConfigs.specs = data.specs || [];
if(!this.specConfigs.specs.length){
this.noSpecFlag = true
}
this.queueNum = data.wait_count || 1; this.queueNum = data.wait_count || 1;

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


+ 1
- 1
web_src/vuepages/pages/dataset/square/components/PublicDataset.vue View File

@@ -146,7 +146,7 @@ export default {
sortSelect: 'default', sortSelect: 'default',
sortList:[ sortList:[
{name:'default',active:true}, {name:'default',active:true},
{name:'latest',active:false},
{name:'newest',active:false},
{name:'recentupdate',active:false}, {name:'recentupdate',active:false},
{name:'downloadtimes',active:false}, {name:'downloadtimes',active:false},
{name:'moststars',active:false}, {name:'moststars',active:false},


+ 32
- 2
web_src/vuepages/pages/home/screenmap/index.vue View File

@@ -167,6 +167,16 @@ methods: {
position: 'right', position: 'right',
show: false 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: { emphasis: {
label: { label: {
show: true show: true
@@ -205,6 +215,16 @@ methods: {
position: 'right', position: 'right',
show: false 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: { emphasis: {
label: { label: {
show: true show: true
@@ -249,6 +269,16 @@ methods: {
position: 'right', position: 'right',
show: true 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', showEffectOn: 'render',
rippleEffect: { rippleEffect: {
brushType: 'stroke' brushType: 'stroke'
@@ -282,10 +312,10 @@ methods: {
effect: { effect: {
show: true, show: true,
symbol:'rect', symbol:'rect',
period: 1.5, // 速度
period: 2.5, // 速度
trailLength: 0.5, // 特效拖尾 trailLength: 0.5, // 特效拖尾
color: '#007BFF', color: '#007BFF',
symbolSize: 3
symbolSize: 3,
}, },
lineStyle: { lineStyle: {
color: 'rgba(255,255,255,0.1)', color: 'rgba(255,255,255,0.1)',


+ 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"> <img src="/img/jian.svg" v-if="model.recommend == 1">
</div> </div>
<div class="title-r"> <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 outline icon" :title="$t('star')"></i>
<i v-if="isCollected" class="heart icon" :title="$t('unStar')"></i> <i v-if="isCollected" class="heart icon" :title="$t('unStar')"></i>
<span>{{ $t('star') }}</span> <span>{{ $t('star') }}</span>
</div> </div>
<div>{{ collectedCount }}</div>
<div class="like-btn">{{ collectedCount }}</div>
</div> </div>
</div> </div>
<div class="sub-title"> <div class="sub-title">
@@ -71,7 +80,7 @@
</template> </template>


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


export default { export default {
name: "ModelHeader", name: "ModelHeader",
@@ -80,7 +89,7 @@ export default {
repoOwnerName: { type: String, default: '' }, repoOwnerName: { type: String, default: '' },
repoName: { type: String, default: '' }, repoName: { type: String, default: '' },
modelName: { type: String, default: '' }, modelName: { type: String, default: '' },
tab: { type: String, default: 'intro' }
tab: { type: String, default: 'intro' },
}, },
components: {}, components: {},
data() { data() {
@@ -89,6 +98,9 @@ export default {
isCollected: false, isCollected: false,
collectedCount: '', collectedCount: '',
isSetting: false, isSetting: false,
fullscreenLoading: false,
isCanDebug:false,
loginName:'zhoupzh',
}; };
}, },
methods: { methods: {
@@ -114,6 +126,49 @@ export default {
this.$message.error(err); this.$message.error(err);
this.isSetting = false; 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=0&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: { watch: {
@@ -121,12 +176,23 @@ export default {
handler(newVal) { handler(newVal) {
this.isCollected = newVal.isCollected; this.isCollected = newVal.isCollected;
this.collectedCount = newVal.collectedCount; this.collectedCount = newVal.collectedCount;
if(newVal.userName===this.loginName){
this.isCanDebug = true
}else{
this.isCanDebug = false
}
}, },
immediate: true, immediate: true,
deep: 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> </script>


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


>div {
.like-btn {
height: 30px; height: 30px;
border-color: rgb(225, 227, 230); border-color: rgb(225, 227, 230);
border-width: 1px; border-width: 1px;
@@ -203,6 +269,12 @@ export default {
cursor: 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> <NotFound></NotFound>
</div> </div>
<div v-else> <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"> :model="modelData">
</ModelHeader> </ModelHeader>
<div class="ui container"> <div class="ui container">


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

@@ -4,7 +4,7 @@
<NotFound></NotFound> <NotFound></NotFound>
</div> </div>
<div v-else> <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> </ModelHeader>
<div class="ui container"> <div class="ui container">
<div class="header"> <div class="header">


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

@@ -4,7 +4,7 @@
<NotFound></NotFound> <NotFound></NotFound>
</div> </div>
<div v-else> <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> </ModelHeader>
<div class="ui container"> <div class="ui container">
<div ref="graphContainerRef" class="graph-container"></div> <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> <NotFound></NotFound>
</div> </div>
<div v-else> <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"> :model="modelData">
</ModelHeader> </ModelHeader>
<div class="ui container content"> <div class="ui container content">
@@ -112,6 +112,54 @@
<div class="value">{{ modelData.createTimeStr }}</div> <div class="value">{{ modelData.createTimeStr }}</div>
</div> </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> </div>
</div> </div>
@@ -157,12 +205,19 @@ export default {
previewContent: '', previewContent: '',


submitLoading: false, submitLoading: false,

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


}; };
}, },
components: { ModelHeader, NotFound }, components: { ModelHeader, NotFound },
methods: { methods: {
createIntro() { createIntro() {
this.content = this.emptyDefaultContent;
this.content = this.emptyDefaultContent;
this.toggleEdit(true); this.toggleEdit(true);
}, },
changeEditTab(tab) { changeEditTab(tab) {
@@ -253,6 +308,10 @@ export default {
this.introEmpty = false; this.introEmpty = false;
this.content = data.content; this.content = data.content;
this.htmlContent = data.htmlcontent; 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; this.introFileName = data.fileName;
window.setTimeout(() => { window.setTimeout(() => {
@@ -300,6 +359,54 @@ export default {
}); });
this.submitLoading = false; 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() { beforeMount() {
@@ -338,6 +445,10 @@ export default {
}; };
this.labels = model.label ? model.label.trim().split(/\s+/) : []; this.labels = model.label ? model.label.trim().split(/\s+/) : [];
this.canEdit = model.isCanOper; 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(); this.getIntroInfo();
} else { } else {
this.emptyPage = true; this.emptyPage = true;
@@ -363,8 +474,8 @@ export default {
margin-top: 32px; margin-top: 32px;


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


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


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


.title { .title {
@@ -526,7 +638,31 @@ export default {
margin-bottom: 8px; margin-bottom: 8px;
line-height: 20px; 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 { .labels {
margin-top: 12px; margin-top: 12px;
margin-bottom: 12px; margin-bottom: 12px;
@@ -575,7 +711,24 @@ export default {
border-radius: 2px; border-radius: 2px;
font-size: 12px; 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 { .summary {
.row { .row {
display: flex; display: flex;
@@ -584,13 +737,19 @@ export default {
.label { .label {
color: rgb(136, 136, 136) color: rgb(136, 136, 136)
} }

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

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

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


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

@@ -36,7 +36,11 @@
</span> </span>
</div> </div>
<div class="footer-r"> <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>
</div> </div>
</a> </a>
@@ -57,6 +61,7 @@ export default {
isCollected: false, isCollected: false,
collectedCount: 0, collectedCount: 0,
isSetting: false, isSetting: false,
hasOnlineUrl:0,
}; };
}, },
methods: { methods: {
@@ -89,6 +94,8 @@ export default {
beforeMount() { beforeMount() {
this.isCollected = this.data.isCollected; this.isCollected = this.data.isCollected;
this.collectedCount = this.data.collectedCount; this.collectedCount = this.data.collectedCount;
this.hasOnlineUrl = this.data.hasOnlineUrl

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


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

.greenPoint{
display: inline-block;
width: 8px;
height: 8px;
margin-right: 5px;
background-color: #5dbf77;
border-radius: 50%;
}
.item-engine { .item-engine {
color: rgba(136, 136, 136, 0.9); 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, queryType: this.condition.tab,
orderBy: this.condition.sort, orderBy: this.condition.sort,
recommend: this.condition.onlyRecommend, recommend: this.condition.onlyRecommend,
hasOnlineUrl: this.condition.hasOnlineUrl,
frame: this.condition.engine, frame: this.condition.engine,
label: this.condition.label, label: this.condition.label,
page: this.condition.page, page: this.condition.page,


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

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




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


Loading…
Cancel
Save