#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 {
go func() {
log.Info("Starting pprof server on localhost:6060")
log.Info("%v", http.ListenAndServe("localhost:6060", nil))
log.Info("%v", http.ListenAndServe("192.168.207.34:6060", nil))
}()
}



+ 4
- 7
entity/ai_task.go View File

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

"code.gitea.io/gitea/models"

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

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

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

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

} else {
return aiCenterInfo[1]
}

}

return ""

}

var defaultLanguage = "zh-CN"


+ 9
- 7
entity/container.go View File

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

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

type ContainerDataType string


+ 1
- 0
entity/images.go View File

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

type GetImageReq struct {


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

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

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

sendjob:


+ 2
- 0
models/action.go View File

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

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


+ 61
- 40
models/ai_model_manage.go View File

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

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

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

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

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

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


+ 15
- 4
models/cloudbrain.go View File

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

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

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

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

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

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

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

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



+ 10
- 0
models/issue_comment.go View File

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

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

@@ -838,6 +842,12 @@ func (opts *FindCommentsOptions) toConds() builder.Cond {
if opts.Type != CommentTypeUnknown {
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
}



+ 2
- 0
models/notification.go View File

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


+ 14
- 2
models/review.go View File

@@ -182,6 +182,18 @@ func findReviews(e Engine, opts FindReviewOptions) ([]*Review, error) {
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
func FindReviews(opts FindReviewOptions) ([]*Review, error) {
return findReviews(x, opts)
@@ -246,7 +258,7 @@ func getCurrentReview(e Engine, reviewer *User, issue *Issue) (*Review, error) {
if reviewer == nil {
return nil, nil
}
reviews, err := findReviews(e, FindReviewOptions{
reviews, err := findReviewsSortByDesc(e, FindReviewOptions{
Type: ReviewTypePending,
IssueID: issue.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
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


+ 1
- 0
models/task_config.go View File

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


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

@@ -653,11 +653,10 @@ var (
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

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

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

if Grampus.AiCenterCodeAndNameAndLocInfo != "" {
if err := json.Unmarshal([]byte(Grampus.AiCenterCodeAndNameAndLocInfo), &C2NetInfos); err != nil {
if err := json.Unmarshal([]byte(Grampus.AiCenterCodeAndNameAndLocInfo), &C2NetLocInfos); err != nil {
log.Error("Unmarshal(AiCenterCodeAndNameLocInfo) failed:%v", err)
}
AiCenterCodeAndNameAndLocMapInfo = make(map[string]*C2NetSequenceInfo)
for _, value := range C2NetInfos.C2NetSqInfo {
for _, value := range C2NetLocInfos.C2NetSqInfo {
AiCenterCodeAndNameAndLocMapInfo[value.Name] = value
}
}


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

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

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

+ 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 ;
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;
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_instructions2 = OpenI_Learning
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.
train.manage.model_not_exist=The model in the task does not exist or has been deleted, please create a new train job.
debug.manage.dataset_not_exist=The part of datasets in the task does not exist or has been deleted, please create a new debug job.
debug.manage.model_num_over_limit=The number of models exceeds the limit of 30

grampus.train_job.ai_center = AI Center
grampus.dataset_path_rule = The code is storaged in /cache/code;the dataset is storaged in /cache/dataset;and please put your model into /cache/output, then you can download it online。
@@ -3179,6 +3180,7 @@ task_c2ent_gcudebugjob=`created GCU type debugging task <a href="%s/grampus/trai
task_c2ent_gcutrainjob=`created GCU type train task <a href="%s/modelarts/train-job/%s">%s</a>`
task_c2ent_mludebugjob=`created MLU type debugging task <a href="%s/grampus/train-job/%s">%s</a>`
task_c2ent_mlutrainjob=`created MLU type train task <a href="%s/modelarts/train-job/%s">%s</a>`
task_c2net_dcudebugjob=`created DCU type debugging task <a href="%s/grampus/notebook/%s">%s</a>`
task_c2ent_onlineinferjob=`created GPU type online inference task <a href="%s/grampus/onlineinfer/%s">%s</a>`
task_nputrainjob=`created NPU training task <a href="%s/modelarts/train-job/%s">%s</a>`
task_inferencejob=`created reasoning task <a href="%s/modelarts/inference-job/%s">%s</a>`
@@ -3238,6 +3240,7 @@ max_size_tooltips= You can only upload a maximum of ? files at a time. The uploa
notifications = Notifications
unread = Unread
read = Read
notice = Notice
no_unread = No unread notifications.
no_read = No read notifications.
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>;
debug_task_running_limit = 运行时长:最长不超过4个小时,超过4个小时将自动停止;
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_instructions2 = 小白训练营课程
platform_instructions3 = 。
@@ -1402,6 +1402,7 @@ modelconvert.manage.no_operate_right=您没有操作权限。
debug.manage.model_not_exist=任务中选择的模型不存在或者已被删除,请新建调试任务。
train.manage.model_not_exist=任务中选择的模型不存在或者已被删除,请新建训练任务。
debug.manage.dataset_not_exist=任务中选择的部分数据集不存在或者已被删除,请新建调试任务。
debug.manage.model_num_over_limit=任务中选择的模型限制不超过30个文件

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


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

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

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

var repoAndOrgZH={


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

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

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

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

"code.gitea.io/gitea/entity"

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

@@ -934,6 +934,10 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/status", reqToken(), bind(api.CreateFileNotebookJobOption{}), repo.FileNoteBookStatus)
})

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

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



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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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


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

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

ctx.JSON(http.StatusOK, modelResult)
}



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

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

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

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

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

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

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

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

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

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

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

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

prepareSpec4Show(ctx, task)

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

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

for _, datasetInfo := range datasetDownload {

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

}

}

}
}

return datasetDownload
}

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

}

}

}

return &modelDownload
}

func GrampusTrainJobShow(ctx *context.Context) {


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

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

+ 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("/commit_image", cloudbrain.AdminOrJobCreaterRight, repo.GrampusCommitImageShow)
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("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.GrampusNotebookDel)
})
@@ -1332,8 +1332,8 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("", reqRepoCloudBrainReader, repo.GrampusTrainJobShow)
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.GrampusStopJob)
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.GrampusTrainJobDel)
m.Get("/model_download", cloudbrain.AdminOrJobCreaterRightForTrain, repo.ModelDownload)
m.Get("/download_multi_model", cloudbrain.AdminOrJobCreaterRightForTrain, repo.MultiModelDownload)
m.Get("/model_download", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.ModelDownload)
m.Get("/download_multi_model", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.MultiModelDownload)
m.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, context.PointAccount(), repo.GrampusTrainJobVersionNew)
m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateGrampusTrainJobForm{}), context.PointAccount(), repo.GrampusTrainJobVersionCreate)
})
@@ -1417,7 +1417,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Group("/:id", func() {
m.Get("", reqRepoCloudBrainReader, repo.NotebookShow)
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("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.NotebookDel)
})


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

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


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

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

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

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

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

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

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

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

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

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



+ 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)
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 == "" {
return nil
}
@@ -211,6 +216,12 @@ func parseDiagnosticsToOperationProfile(appExitDiagnostics string) *entity.Opera
Action: e.Action,
})
}
if exitDiagnostics != ""{
events = append(events, entity.ProfileEvent{
Message: exitDiagnostics,
Reason: "Error",
})
}
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

import (
"strings"

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

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

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

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


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

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

import (
"strings"

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

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

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

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


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

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

import (
"fmt"

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

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

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



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

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

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

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

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

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


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

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

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

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

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


+ 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 {
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)
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)
return nil
}
@@ -159,7 +174,11 @@ func (DefaultCreationHandler) CheckDatasetSize(ctx *context.CreationContext) *re

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

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

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


+ 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,
EndTime: task.EndTime,
Description: task.Description,
FailedReason: task.FailedReason,
CommitID: task.CommitID,
BranchName: task.BranchName,
ImageName: imageName,
@@ -761,7 +762,7 @@ func GetModelDownload(task *models.Cloudbrain) []*models.ModelDownload {
} else {
model, err = models.QueryModelById(task.ModelId)
}
if err != nil {
if err != nil || model == nil {
return pretrainModelList
}



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

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

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

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

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

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

func GrampusNotebookDebug(ctx *context.Context) error {

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

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

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


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

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

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" {
return info.Content
} else {
@@ -24,12 +25,19 @@ func GetAiCenterShowByAiCenterId(aiCenterId string, ctx *context.Context) string
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 {
aiCenterInfo := strings.Split(aiCenter, "+")

aiCenterAndNameInfo := getAiCenterAndNameInfo()
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" {
return info.Content
} else {
@@ -42,11 +50,18 @@ func GetAiCenterShow(aiCenter string, ctx *context.Context) string {
} else {
return aiCenterInfo[1]
}

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

return ""

}

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

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
} else {
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 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.
// 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 {
@@ -77,6 +77,35 @@ func CreateCodeComment(doer *models.User, gitRepo *git.Repository, issue *models
if err != nil {
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(
@@ -123,6 +152,7 @@ func createCodeComment(doer *models.User, repo *models.Repository, issue *models
// FIXME validate treePath
// Get latest commit referencing the commented line
// No need for get commit for base branch changes
invalidated := false
if line > 0 {
commit, err := gitRepo.LineBlame(pr.GetGitRefName(), gitRepo.Path, treePath, uint(line))
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
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())
if err != nil {
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)
}
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"
)

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

type ClientsManager struct {
Clients *orderedmap.OrderedMap


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

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


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

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


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

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


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

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

+ 1
- 34
templates/notice.tmpl View File

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

{{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">
<h3 class="ui center am-pt-30 am-pb-20">{{.i18n.Tr "notice_announcement"}}</h3>
<div class="notice-container">
@@ -41,7 +8,6 @@
{{template "base/footer" .}}
<script>
;(function() {
var isZh = document.documentElement.getAttribute('lang') == 'zh-CN';
function getNotice() {
$.ajax({
type:"GET",
@@ -51,6 +17,7 @@
filename: 'notice/notice.json',
},
success:function(data){
var isZh = document.documentElement.getAttribute('lang') == 'zh-CN';
if (!data) return;
try {
var noticeList = JSON.parse(data).Notices || [];


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

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


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

@@ -1,3 +1,3 @@
{{template "base/head" .}}
{{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">
{{.i18n.Tr "notification.read"}}
</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)}}
<form action="{{AppSubUrl}}/notifications/purge" method="POST" style="margin-left: auto;">
{{$.CsrfTokenHtml}}
@@ -25,8 +28,14 @@
{{if eq (len .Notifications) 0}}
{{if eq .Status 1}}
{{.i18n.Tr "notification.no_unread"}}
{{else}}
{{else if eq .Status 2}}
{{.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}}
{{else}}
<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;
});
const notificationDiv= $('#notice-container-json');
if (!notificationDiv.length) {
return;
} else {
getNotice()
}
}

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

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) {
const currentCount = $('.notification_count').text();


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

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

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

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

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

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

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

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

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

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

@@ -1512,4 +1512,33 @@ i.SUCCEEDED {
span{
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) => {
return service({
url: `/api/v1/repos/Itx003/openi-notebook/modelarts/train-job/159191/model_list`,
url: `/api/v1/${params.repoOwnerName}/${params.repoName}/ai_task/output`,
method: 'get',
params: { ...params },
params: {
id: params.id,
parent_dir: params.parent_dir,
},
});
}

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

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

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

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

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


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

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

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


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

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

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

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



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

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

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

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

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

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


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

@@ -1,7 +1,11 @@
<template>
<div class="item-container">
<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="content" v-html="renderContent(item)"></div>
</div>
@@ -180,6 +184,9 @@ export default {
case 'bootFile':
result = i18n.t('modelManage.bootFile');
break;
case 'failedReason':
result = i18n.t('cloudbrainObj.failedReason');
break;
default:
break;
}
@@ -280,6 +287,9 @@ export default {
case 'bootFile':
result = task.boot_file;
break;
case 'failedReason':
result = task.failed_reason;
break;
default:
break;
}
@@ -376,6 +386,16 @@ export default {
}
}
}

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

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

/deep/.clipboard {


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

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

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

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

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

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

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

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

} else {

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

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

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

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

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

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

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

i {
margin-right: 5px;
}
}

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

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

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

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

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

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

// 模型


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

@@ -101,7 +101,7 @@ const en = {
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.',
handleTask: 'Processing tasks',
freeCompute:'Inclusive computing power',
freeCompute: 'Inclusive computing power',
resourcesManagement: {
OpenI: 'OpenI',
C2Net: 'C2Net',
@@ -303,7 +303,7 @@ const en = {
trainTask: 'Train task',
codeBranch: 'Code branch',
bootFile: 'Boot file',
viewSamples:'View samples',
viewSamples: 'View samples',
trainDataset: 'Train dataset',
datasetfile: 'Dataset files',
specInfo: 'Specifications',
@@ -343,6 +343,13 @@ const en = {
derivedModel: 'Derived Model',
refRepository: 'Reference repository',
modelDownloadAll: 'Download All',
otherOnline: 'Other online url',
trainUsedDataList: 'The dataset used for the model',
modelUseTaskList: 'The task used for the model',
forkModelSuccess: 'The model content has been copied and forked successfully!',
debugModel: 'Debug Model',
onlineInference: 'online Inference',
deleted:'Deleted',
},
repos: {
activeOrganization: 'Active Organization',
@@ -413,7 +420,8 @@ const en = {
model_search: 'Search model',
model_square_empty: 'No Models',
model_suport_file_tips: 'The supported format of the model file is [ckpt, pb, h5, json, pkl, pth, t7, pdparams, onnx, pbtxt, keras, mlmodel, cfg, pt]',
boot_file_helper: 'The startup file is the entry file that your program executes, and it must be a file ending in .py'
boot_file_helper: 'The startup file is the entry file that your program executes, and it must be a file ending in .py',
can_online_infer: 'Online',
},
datasetObj: {
dataset_label: "Dataset",
@@ -436,6 +444,7 @@ const en = {
},
specObj: {
resSelectTips: 'The "resource specification" is the hardware you use to run the task. In order for more people to use the resources of this platform, please select according to your actual needs',
no_use_resource: 'No resources available',
},
datasets: {
computer_vision: "computer vision",
@@ -479,7 +488,7 @@ const en = {
downloadtimes: 'Download times',
citations: 'Citations',
default: "Default",
latest: "Newest",
newest: "Newest",
oldest: "Oldest",
recentupdate: "Recently updated",
leastupdate: "Least recently updated",
@@ -556,6 +565,7 @@ const en = {
log: 'Log',
resourceOccupancy: 'Resource Occupancy',
modelDownload: 'Model Download',
failedReason: 'Failed reason',
publicImage: 'Public Image',
myImage: 'My Images',
myFavImage: 'My collected images',
@@ -570,9 +580,9 @@ const en = {
debugTaskEmptyTitle: 'Debug task has not been created',
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;',
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',
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.',
deletingTips: 'Task deletion in progress, please wait',
tabTitDebug: 'Debug Task',
@@ -580,6 +590,14 @@ const en = {
tabTitInference: 'Inference Job',
tabTitBenchmark: 'Model Evaluation',
tabTitOnlineInference: 'Online Inference',
allResultDownload: 'All result download',
downloadDisplayMaxCountTips: 'Display up to 100 files or folders in a single directory',
file_sync_ing: "File synchronization in progress, please wait",
file_sync_ing: "File synchronization in waitting, please wait",
file_sync_fail: "File synchronization failed",
no_file_to_download: "No files can be downloaded",
task_not_finished: "Task not finished yet, please wait",
retrieve_results: "Retrieve results",

},
}


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

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

},
}


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

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

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

const TIPS = {
'1': '项目代码存储在 <strong style="color:#010101">/code</strong> 中,数据集存储在 <strong style="color:#010101">/dataset</strong> 中,选择的模型存储在 <strong style="color:#010101">/pretrainmodel</strong> 中,调试输出请存储在 <strong style="color:#010101">/model</strong> 中以供后续下载。',
@@ -65,7 +65,7 @@ export const CreatePageConfigs = {
}],
'C2Net': [{
url: 'grampus/notebook/create?type=0',
computerResouces: ['GPU', 'NPU', 'GCU', 'MLU'],
computerResouces: ['GPU', 'NPU', 'GCU', 'MLU', 'DCU'],
'GPU': [{
url: 'grampus/notebook/create?type=0',
clusterType: 'C2Net',
@@ -135,6 +135,24 @@ export const CreatePageConfigs = {
spec: { required: true },
},
}],
'DCU': [{
url: 'grampus/notebook/create?type=4',
clusterType: 'C2Net',
tips2: i18n.t('cloudbrainObj.pathTips3', {
code: '/tmp/code',
dataset: '/tmp/dataset',
model: '/tmp/pretrainmodel',
}),
form: {
taskName: { required: true, },
taskDescr: { required: false, },
branchName: { required: true, },
model: { required: false, multiple: true },
imagev2: { required: true },
dataset: { required: false },
spec: { required: true },
},
}],
}]
}],
// 训练任务
@@ -284,6 +302,7 @@ export const ListPageConfigs = {
{ k: 'NPU', v: 'NPU' },
{ k: 'GCU', v: 'GCU' },
{ k: 'MLU', v: 'MLU' },
{ k: 'DCU', v: 'DCU' },
],
pages: [{
jobType: 'DEBUG',
@@ -295,7 +314,7 @@ export const ListPageConfigs = {
emptyTitle: i18n.t('cloudbrainObj.debugTaskEmptyTitle'),
emptyTip1: i18n.t('cloudbrainObj.debugTaskEmptyTip1'),
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',
jobTypeName: getListValueWithKey(JOB_TYPE, 'TRAIN'),
@@ -325,7 +344,7 @@ export const ListPageConfigs = {
emptyTitle: i18n.t('cloudbrainObj.onlineInferTaskEmptyTitle'),
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 = {
@@ -351,6 +370,7 @@ export const DetailPageConfigs = {
'endTime', 'modelPath',
'duration', 'outputPath',
'descr', '',
'failedReason',
'dataset',
'modelList',
]
@@ -380,6 +400,7 @@ export const DetailPageConfigs = {
'endTime', '',
'duration', '',
'descr', '',
'failedReason',
'dataset',
'modelList',
],
@@ -406,6 +427,7 @@ export const DetailPageConfigs = {
'endTime', 'datasetPath',
'duration', 'modelPath',
'descr', '',
'failedReason',
'dataset',
'modelList',
]
@@ -430,6 +452,7 @@ export const DetailPageConfigs = {
'endTime', '',
'duration', '',
'descr', '',
'failedReason',
'dataset',
'modelList',
],
@@ -456,6 +479,7 @@ export const DetailPageConfigs = {
'endTime', '',
'duration', '',
'descr', '',
'failedReason',
'dataset',
'modelList',
]
@@ -480,6 +504,7 @@ export const DetailPageConfigs = {
'endTime', '',
'duration', '',
'descr', '',
'failedReason',
'dataset',
'modelList',
]
@@ -487,6 +512,30 @@ export const DetailPageConfigs = {
name: 'operationProfile'
}],
}],
'DCU': [{
detailUrl: 'grampus/notebook/',
summary: [],
operations: [],
tabs: [{
name: 'configInfo',
fields: [
'taskName', 'imagev2',
'status', 'spec',
'creator', 'aiCenter',
'branch', 'modelName',
'computerRes', 'modelVersion',
'createTime', 'modelFiles',
'startTime', '',
'endTime', '',
'duration', '',
'descr', '',
'dataset',
'modelList',
]
}, {
name: 'operationProfile'
}],
}],
}]
}],
/*
@@ -612,6 +661,8 @@ export const DetailPageConfigs = {
]
}, {
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="title"></div>
<div class="content">
<el-button type="primary" :disabled="maskLoading || alreadyMsgBoxShow" size="default" class="submit-btn"
<el-button type="primary" :disabled="maskLoading || alreadyMsgBoxShow || noSpecFlag" size="default" class="submit-btn"
@click="submit">{{ $t('cloudbrainObj.createTask') }}</el-button>
<el-button class="cancel-btn" size="default" @click="cancel">{{ $t('cancel') }}</el-button>
</div>
@@ -100,6 +100,7 @@ import LoadingMask from '~/components/cloudbrain/LoadingMask.vue';
import { getCreatePageConfigs } from '../configs';
import { getUrlSearchParams } from '~/utils';
import { getAiTaskPrepareInfo, createAiTask } from '~/apis/modules/cloudbrain';
import { getModelList } from '~/apis/modules/modelsquare';

export default {
data() {
@@ -141,6 +142,7 @@ export default {
maskLoading: false,
maskLoadingContent: '',
datasetSize: 0,
noSpecFlag:false,
};
},
components: {
@@ -251,6 +253,35 @@ export default {
window.history.back();
}
},
transformTreeData(data) {
for (let i = 0, iLen = data.length; i < iLen; i++) {
const dataI = data[i];
const _children = dataI.modelFileList || [];
const children = [];
dataI.parent = true;
dataI.disabled = true;
_children.forEach(item => {
item.ModTimeNum = new Date(item.ModTime).getTime();
})
_children.sort((a, b) => a.FileName.localeCompare(b.FileName));
_children.sort((a, b) => b.ModTimeNum - a.ModTimeNum);
for (let j = 0, jLen = _children.length; j < jLen; j++) {
const file = _children[j];
if (file.IsDir) continue;
// const arr = file.FileName.split('.');
// if (!supportCheckPointFileExt.includes(arr[arr.length - 1])) continue;
file._modelID = dataI.id;
file._modelName = dataI.name;
file._modelVersion = dataI.version;
file._preTrainModelUrl = dataI.path;
file.name = file.FileName;
file.id = `${file._modelID}|${file._modelName}|${file._modelVersion}|${file._preTrainModelUrl}|${file.name}`;
children.push(file);
}
dataI.children = children;
}
return data;
},
},
beforeMount() {
const urlParams = getUrlSearchParams();
@@ -266,6 +297,31 @@ export default {
this.cancel();
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({
repoOwnerName: this.repoOwnerName,
repoName: this.repoName,
@@ -282,8 +338,10 @@ export default {
this.specConfigs.showPoint = data.pay_switch;
this.specConfigs.blance = data.point_account ? data.point_account.balance : 0;
this.specConfigs.specs = data.specs || [];
if(!this.specConfigs.specs.length){
this.noSpecFlag = true
}
this.queueNum = data.wait_count || 1;

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


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

@@ -146,7 +146,7 @@ export default {
sortSelect: 'default',
sortList:[
{name:'default',active:true},
{name:'latest',active:false},
{name:'newest',active:false},
{name:'recentupdate',active:false},
{name:'downloadtimes',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',
show: false
},
tooltip:{
formatter: (params)=>{
const marker = `
<div>${params.seriesName}</div>
<span style=\"display:inline-block;margin-right:4px;border-radius:10px;width:10px;height:10px;background-color:rgb(251, 118, 123);\"></span>
<span>${params.data.name}</span>
`
return marker
}
},
emphasis: {
label: {
show: true
@@ -205,6 +215,16 @@ methods: {
position: 'right',
show: false
},
tooltip:{
formatter: (params)=>{
const marker = `
<div>${params.seriesName}</div>
<span style=\"display:inline-block;margin-right:4px;border-radius:10px;width:10px;height:10px;background-color:rgb(251, 118, 123);\"></span>
<span>${params.data.name}</span>
`
return marker
}
},
emphasis: {
label: {
show: true
@@ -249,6 +269,16 @@ methods: {
position: 'right',
show: true
},
tooltip:{
formatter: (params)=>{
const marker = `
<div>${params.seriesName}</div>
<span style=\"display:inline-block;margin-right:4px;border-radius:10px;width:10px;height:10px;background-color:rgb(251, 118, 123);\"></span>
<span>${params.data.name}</span>
`
return marker
}
},
showEffectOn: 'render',
rippleEffect: {
brushType: 'stroke'
@@ -282,10 +312,10 @@ methods: {
effect: {
show: true,
symbol:'rect',
period: 1.5, // 速度
period: 2.5, // 速度
trailLength: 0.5, // 特效拖尾
color: '#007BFF',
symbolSize: 3
symbolSize: 3,
},
lineStyle: {
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">
</div>
<div class="title-r">
<div @click="changeFav">
<div style="background: transparent;" v-if="!isCanDebug && !model.isPrivate">
<el-button class="create-btn" size="mini" type="primary" @click="createOnlineDebug"
v-loading.fullscreen.lock="fullscreenLoading"
element-loading-text="拼命加载中"
element-loading-background="rgba(0, 0, 0, 0.8)"
>
{{ $t('modelManage.debugModel') }}
</el-button>
</div>
<div @click="changeFav" class="like-btn">
<i v-if="!isCollected" class="heart outline icon" :title="$t('star')"></i>
<i v-if="isCollected" class="heart icon" :title="$t('unStar')"></i>
<span>{{ $t('star') }}</span>
</div>
<div>{{ collectedCount }}</div>
<div class="like-btn">{{ collectedCount }}</div>
</div>
</div>
<div class="sub-title">
@@ -71,7 +80,7 @@
</template>

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

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

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

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

}
}
}



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

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


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

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


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

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


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

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

submitLoading: false,

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


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

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

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

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

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

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

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

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

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

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

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

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

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


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

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


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

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

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

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

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


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

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


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

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



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


Loading…
Cancel
Save