V20240129.patch_merge
into V20240402
1 month ago
@@ -74,6 +74,7 @@ type QueryAITaskRes struct { | |||
EarlyVersionList []*AITaskDetailInfo `json:"early_version_list"` | |||
CanCreateVersion bool `json:"can_create_version"` | |||
CanDownload bool `json:"can_download"` | |||
CanModify bool `json:"can_modify"` | |||
} | |||
func (r *QueryAITaskRes) TryToRemoveDatasetAndModelInfo(currentUser *models.User) { | |||
@@ -211,18 +212,25 @@ type AITaskBriefInfo struct { | |||
IsFileNotebook bool `json:"is_file_notebook"` | |||
IsFineTuneTask bool `json:"is_fine_tune_task"` | |||
APPName string `json:"app_name"` | |||
AccCardType string `json:"acc_card_type"` | |||
JobName string `json:"job_name"` | |||
} | |||
func (a *AITaskBriefInfo) Tr(language string) { | |||
aiCenterInfo := strings.Split(a.AICenter, "+") | |||
aiCenterCode := aiCenterInfo[0] | |||
aiCenterName := "" | |||
if len(aiCenterCode) >= 2 { | |||
if len(aiCenterInfo) >= 2 { | |||
aiCenterName = aiCenterInfo[1] | |||
} | |||
a.AICenter = models.GetAiCenterShow(aiCenterCode, aiCenterName, language) | |||
} | |||
func (a *AITaskBriefInfo) ClearNonPublicFields() *AITaskBriefInfo { | |||
a.JobName = "" | |||
return a | |||
} | |||
type AITaskListRes struct { | |||
Tasks []*AITaskInfo4List `json:"tasks"` | |||
Total int64 `json:"total"` | |||
@@ -236,9 +244,25 @@ type AITaskInfo4List struct { | |||
Creator UserBriefInfo `json:"creator"` | |||
CanModify bool `json:"can_modify"` | |||
CanDelete bool `json:"can_delete"` | |||
RepoName string `json:"repo_name"` | |||
OwnerName string `json:"owner_name"` | |||
} | |||
func ConvertCloudbrainToAITaskBriefInfo(task *models.Cloudbrain) *AITaskBriefInfo { | |||
accCardType := "" | |||
if task.Spec != nil { | |||
accCardType = task.Spec.AccCardType | |||
} | |||
aiCenter := task.AiCenter | |||
switch task.Type { | |||
case models.TypeCloudBrainOne: | |||
aiCenter = models.AICenterOfCloudBrainOne | |||
case models.TypeCloudBrainTwo: | |||
aiCenter = models.AICenterOfCloudBrainTwo | |||
case models.TypeCDCenter: | |||
aiCenter = models.AICenterOfChengdu | |||
} | |||
return &AITaskBriefInfo{ | |||
ID: task.ID, | |||
JobType: task.JobType, | |||
@@ -251,10 +275,12 @@ func ConvertCloudbrainToAITaskBriefInfo(task *models.Cloudbrain) *AITaskBriefInf | |||
ComputeSource: task.GetStandardComputeSource(), | |||
StartTime: task.StartTime, | |||
EndTime: task.EndTime, | |||
AICenter: task.AiCenter, | |||
AICenter: aiCenter, | |||
IsFileNotebook: task.IsFileNoteBookTask(), | |||
IsFineTuneTask: task.FineTune, | |||
APPName: task.AppName, | |||
AccCardType: accCardType, | |||
JobName: task.JobName, | |||
} | |||
} | |||
@@ -328,6 +354,18 @@ type GetTaskListReq struct { | |||
Operator *models.User | |||
IsRepoOwner bool | |||
} | |||
type GetMyTaskListReq struct { | |||
models.ListOptions | |||
ComputeSource *models.ComputeSource | |||
JobType string | |||
JobStatus string | |||
User *models.User | |||
IsRepoOwner bool | |||
Keyword string | |||
AICenter string | |||
Cluster string | |||
ExcludeStatus []string | |||
} | |||
type AITaskBaseConfig struct { | |||
ContainerSteps map[ContainerDataType]*ContainerBuildOpts `json:"container_configs"` | |||
@@ -337,6 +375,9 @@ type AITaskBaseConfig struct { | |||
DatasetsMaxNum int | |||
ModelMaxNum int | |||
ModelLimitSizeGB int | |||
AutoStopDuration int64 | |||
//主动检测调式地址是否可用 | |||
DebugAddressCheck bool | |||
} | |||
func GetAITaskConfigFromCloudbrainConfig(config *models.CloudbrainConfig) *AITaskBaseConfig { | |||
@@ -50,6 +50,43 @@ type CreateNoteBookTaskResponse struct { | |||
Status string | |||
UserID string | |||
} | |||
type CreateGeneralTaskRequest struct { | |||
Name string | |||
Description string | |||
Tasks []GeneralTask | |||
PrimitiveDatasetName string | |||
RepoName string | |||
} | |||
type GeneralTask struct { | |||
AutoStopDuration int64 | |||
Name string | |||
Capacity int | |||
Queues []models.ResourceQueue | |||
Code []ContainerData | |||
Datasets []ContainerData | |||
PreTrainModel []ContainerData | |||
OutPut []ContainerData | |||
ImageId string | |||
ImageUrl string | |||
ResourceSpecId string | |||
BootFile string | |||
Spec *models.Specification | |||
EnvVariables models.GrampusEnvVarReq | |||
} | |||
type CreateGeneralTaskResponse struct { | |||
StartedAt int64 | |||
RunSec int64 | |||
CompletedAt int64 | |||
CreatedAt int64 | |||
UpdatedAt int64 | |||
Desc string | |||
JobID string | |||
Name string | |||
Status string | |||
UserID string | |||
} | |||
type RestartNoteBookTaskResponse struct { | |||
JobId string `json:"newId"` | |||
@@ -440,12 +440,13 @@ func GetGrampusMetrics(jobID string, startTime int64, endTime int64, nodeId ...i | |||
checkSetting() | |||
client := getRestyClient() | |||
var result models.NewModelArtsMetricStatisticResult | |||
var grampusResult models.GrampusMetricStatisticResult | |||
url := HOST + urlTrainJob + "/" + jobID + "/task/0/replica/0/metrics" | |||
if len(nodeId) > 0 { | |||
url = HOST + urlTrainJob + "/" + jobID + "/task/0/replica/0/metrics/node/" + strconv.Itoa(nodeId[0]) | |||
} | |||
var step int64 = 60 | |||
if startTime > 0 { | |||
var step int64 = 60 | |||
size := int64(math.Ceil(float64(endTime-startTime)/float64(step))) + 1 | |||
@@ -463,13 +464,18 @@ func GetGrampusMetrics(jobID string, startTime int64, endTime int64, nodeId ...i | |||
if err != nil { | |||
return result, fmt.Errorf("resty GetTrainJobLog: %v", err) | |||
} | |||
if err = json.Unmarshal([]byte(res.String()), &result); err != nil { | |||
if err = json.Unmarshal([]byte(res.String()), &grampusResult); err != nil { | |||
log.Error("GetGrampusMetrics json.Unmarshal failed(%s): %v", res.String(), err.Error()) | |||
return result, fmt.Errorf("json.Unmarshal failed(%s): %v", res.String(), err.Error()) | |||
} | |||
if res.StatusCode() != http.StatusOK { | |||
return result, fmt.Errorf("Call GrampusMetrics failed(%d)", res.StatusCode()) | |||
} | |||
result = models.NewModelArtsMetricStatisticResult{ | |||
MetricsInfo: grampusResult.MetricsInfo, | |||
Step: step, | |||
} | |||
return result, nil | |||
} | |||
@@ -79,7 +79,8 @@ const ( | |||
ActionCreateGrampusGPUInferenceTask //50 | |||
ActionCreateGrampusILUVATARInferenceTask //51 | |||
ActionInviteFriendRegister //52 | |||
ActionCreateGrampusILUVATARTrainTask | |||
ActionCreateGrampusILUVATARTrainTask //53 | |||
ActionCreateGeneralGPUTask //54 | |||
) | |||
// Action represents user operation type and other information to | |||
@@ -114,15 +115,6 @@ type ActionShow struct { | |||
IssueInfos []string | |||
CommentLink string | |||
Cloudbrain *CloudbrainShow4Action | |||
Data map[string]interface{} | |||
} | |||
func (a *ActionShow) AddData(key string, val interface{}) { | |||
if a.Data == nil { | |||
a.Data = map[string]interface{}{key: val} | |||
} else { | |||
a.Data[key] = val | |||
} | |||
} | |||
// GetOpType gets the ActionType of this action. | |||
@@ -153,6 +145,8 @@ func (a *Action) FilterCloudbrainInfo() { | |||
if a.Cloudbrain.DeletedAt.IsZero() { | |||
newCloudbrain := &Cloudbrain{} | |||
newCloudbrain.ID = a.Cloudbrain.ID | |||
newCloudbrain.JobType = a.Cloudbrain.JobType | |||
newCloudbrain.ComputeResource = a.Cloudbrain.ComputeResource | |||
a.Cloudbrain = newCloudbrain | |||
} else { | |||
a.Cloudbrain = nil | |||
@@ -304,28 +298,7 @@ func (a *Action) ToShow() *ActionShow { | |||
if strings.Contains(a.Content, "|") && a.IsIssueAction() { | |||
actionShow.IssueInfos = a.GetIssueInfos() | |||
} | |||
if strings.Contains(a.Content, "|") && a.IsInviteAction() { | |||
ids := strings.Split(a.Content, "|") | |||
if len(ids) >= 2 { | |||
var invitedId int64 | |||
var invitedName string | |||
if len(ids) >= 4 { | |||
invitedName = ids[3] | |||
} | |||
invitedId, _ = strconv.ParseInt(ids[1], 10, 64) | |||
if invitedId > 0 { | |||
invitedUser, _ := GetUserByID(invitedId) | |||
if invitedUser != nil { | |||
actionShow.AddData("InvitedUserName", invitedUser.Name) | |||
actionShow.AddData("InvitedUserNotExists", false) | |||
} else { | |||
actionShow.AddData("InvitedUserName", invitedName) | |||
actionShow.AddData("InvitedUserNotExists", true) | |||
} | |||
} | |||
} | |||
actionShow.IssueInfos = a.GetIssueInfos() | |||
} | |||
if a.Repo != nil { | |||
actionShow.RepoLink = a.GetRepoLink() | |||
actionShow.ShortRepoFullDisplayName = a.ShortRepoFullDisplayName() | |||
@@ -468,7 +441,8 @@ func (a *Action) IsCloudbrainAction() bool { | |||
ActionCreateSuperComputeTask, | |||
ActionCreateGrampusILUVATARInferenceTask, | |||
ActionCreateGrampusGPUInferenceTask, | |||
ActionCreateGrampusILUVATARTrainTask: | |||
ActionCreateGrampusILUVATARTrainTask, | |||
ActionCreateGeneralGPUTask: | |||
return true | |||
} | |||
return false | |||
@@ -492,14 +466,6 @@ func (a *Action) IsIssueAction() bool { | |||
return false | |||
} | |||
func (a *Action) IsInviteAction() bool { | |||
switch a.OpType { | |||
case ActionInviteFriendRegister: | |||
return true | |||
} | |||
return false | |||
} | |||
// GetFeedsOptions options for retrieving feeds | |||
type GetFeedsOptions struct { | |||
RequestedUser *User // the user we want activity for | |||
@@ -19,56 +19,64 @@ const OrderByIDDesc = "card_request.id desc" | |||
const OrderByStatus = "card_request.status asc,card_request.id desc" | |||
type CardRequest struct { | |||
ID int64 `xorm:"pk autoincr"` | |||
ComputeResource string | |||
UID int64 | |||
UserName string `xorm:"-"` | |||
CardType string | |||
AccCardsNum string | |||
DiskCapacity int64 | |||
ResourceType int | |||
BeginDate string | |||
BeginUnix int64 `xorm:"INDEX"` | |||
EndDate string | |||
EndUnix int64 `xorm:"INDEX"` | |||
Contact string | |||
PhoneNumber string | |||
EmailAddress string | |||
Wechat string | |||
Org string `xorm:"varchar(500)"` | |||
Description string `xorm:"varchar(3000)"` | |||
Status int | |||
Review string `xorm:"varchar(3000)"` | |||
CreatedUnix int64 `xorm:"INDEX created"` | |||
UpdatedUnix int64 `xorm:"INDEX updated"` | |||
DeleteUnix int64 `xorm:"deleted"` | |||
ID int64 `xorm:"pk autoincr"` | |||
ComputeResource string | |||
UID int64 | |||
UserName string `xorm:"-"` | |||
CardType string | |||
AccCardsNum string | |||
DiskCapacity int64 | |||
ResourceType int | |||
BeginDate string | |||
BeginUnix int64 `xorm:"INDEX"` | |||
EndDate string | |||
EndUnix int64 `xorm:"INDEX"` | |||
Contact string | |||
PhoneNumber string | |||
EmailAddress string | |||
Wechat string | |||
IsResearchProject bool | |||
InstitutionName string | |||
ProjectName string | |||
ProjectCode string | |||
Org string `xorm:"varchar(500)"` | |||
Description string `xorm:"varchar(3000)"` | |||
Status int | |||
Review string `xorm:"varchar(3000)"` | |||
CreatedUnix int64 `xorm:"INDEX created"` | |||
UpdatedUnix int64 `xorm:"INDEX updated"` | |||
DeleteUnix int64 `xorm:"deleted"` | |||
} | |||
type CardRequestSpecRes struct { | |||
ID int64 | |||
ComputeResource string | |||
UID int64 | |||
UserName string | |||
CardType string | |||
AccCardsNum string | |||
DiskCapacity int64 | |||
ResourceType int | |||
BeginDate string | |||
BeginUnix int64 | |||
EndDate string | |||
EndUnix int64 | |||
Contact string | |||
PhoneNumber string | |||
EmailAddress string | |||
Wechat string | |||
Org string | |||
Description string | |||
Status int | |||
Review string | |||
CreatedUnix int64 | |||
UpdatedUnix int64 | |||
DeleteUnix int64 | |||
Specs []RequestSpecInfo | |||
ID int64 | |||
ComputeResource string | |||
UID int64 | |||
UserName string | |||
CardType string | |||
AccCardsNum string | |||
DiskCapacity int64 | |||
ResourceType int | |||
BeginDate string | |||
BeginUnix int64 | |||
EndDate string | |||
EndUnix int64 | |||
Contact string | |||
PhoneNumber string | |||
EmailAddress string | |||
Wechat string | |||
IsResearchProject bool | |||
InstitutionName string | |||
ProjectName string | |||
ProjectCode string | |||
Org string | |||
Description string | |||
Status int | |||
Review string | |||
CreatedUnix int64 | |||
UpdatedUnix int64 | |||
DeleteUnix int64 | |||
Specs []RequestSpecInfo | |||
} | |||
func (CardRequestSpecRes) TableName() string { | |||
@@ -88,17 +96,18 @@ type CardRequestOptions struct { | |||
OrderBy string | |||
Keyword string | |||
AiCenterCode string | |||
QueueId int64 | |||
ComputeResource string | |||
AccCardType string | |||
Cluster string | |||
ResourceType int | |||
UseBeginTime int64 | |||
UseEndTime int64 | |||
BeginTimeUnix int64 | |||
EndTimeUnix int64 | |||
NeedSpec bool | |||
AiCenterCode string | |||
QueueId int64 | |||
ComputeResource string | |||
AccCardType string | |||
Cluster string | |||
ResourceType int | |||
UseBeginTime int64 | |||
UseEndTime int64 | |||
BeginTimeUnix int64 | |||
EndTimeUnix int64 | |||
NeedSpec bool | |||
IsResearchProject int | |||
} | |||
type CardRequestShowList struct { | |||
Total int64 `json:"total"` | |||
@@ -106,27 +115,31 @@ type CardRequestShowList struct { | |||
} | |||
type CardRequestSpecShow struct { | |||
ID int64 `json:"id"` | |||
ComputeResource string `json:"compute_resource"` | |||
CardType string `json:"card_type"` | |||
AccCardsNum string `json:"acc_cards_num"` | |||
BeginDate string `json:"begin_date"` | |||
EndDate string `json:"end_date"` | |||
ResourceType int `json:"resource_type"` | |||
DiskCapacity int64 `json:"disk_capacity"` | |||
UID int64 `json:"uid"` | |||
UserName string `json:"user_name"` | |||
TargetCenter []string `json:"target_center"` | |||
Contact string `json:"contact"` | |||
PhoneNumber string `json:"phone_number"` | |||
EmailAddress string `json:"email_address"` | |||
Wechat string `json:"wechat"` | |||
Org string `json:"org"` | |||
Description string `json:"description"` | |||
Status int `json:"status"` | |||
Review string `json:"review"` | |||
CreatedUnix int64 `json:"created_unix"` | |||
Specs []RequestSpecInfo `json:"specs"` | |||
ID int64 `json:"id"` | |||
ComputeResource string `json:"compute_resource"` | |||
CardType string `json:"card_type"` | |||
AccCardsNum string `json:"acc_cards_num"` | |||
BeginDate string `json:"begin_date"` | |||
EndDate string `json:"end_date"` | |||
ResourceType int `json:"resource_type"` | |||
DiskCapacity int64 `json:"disk_capacity"` | |||
UID int64 `json:"uid"` | |||
UserName string `json:"user_name"` | |||
TargetCenter []string `json:"target_center"` | |||
Contact string `json:"contact"` | |||
PhoneNumber string `json:"phone_number"` | |||
EmailAddress string `json:"email_address"` | |||
Wechat string `json:"wechat"` | |||
IsResearchProject bool `json:"is_research_project"` | |||
InstitutionName string `json:"institution_name"` | |||
ProjectName string `json:"project_name"` | |||
ProjectCode string `json:"project_code"` | |||
Org string `json:"org"` | |||
Description string `json:"description"` | |||
Status int `json:"status"` | |||
Review string `json:"review"` | |||
CreatedUnix int64 `json:"created_unix"` | |||
Specs []RequestSpecInfo `json:"specs"` | |||
} | |||
type RequestSpecInfo struct { | |||
@@ -330,11 +343,17 @@ func SearchCardRequest(opts *CardRequestOptions) (int64, []*CardRequestSpecRes, | |||
if opts.OrderBy == "" { | |||
opts.OrderBy = OrderByIDDesc | |||
} | |||
if opts.IsResearchProject == 1 { | |||
cond = cond.And(builder.Or(builder.Eq{"card_request.is_research_project": false}, builder.IsNull{"card_request.is_research_project"})) | |||
} | |||
if opts.IsResearchProject == 2 { | |||
cond = cond.And(builder.Eq{"card_request.is_research_project": true}) | |||
} | |||
cond = cond.And(builder.NewCond().Or(builder.Eq{"card_request.delete_unix": 0}).Or(builder.IsNull{"card_request.delete_unix"})) | |||
cols := []string{"card_request.id", "card_request.compute_resource", "card_request.contact", "card_request.card_type", "card_request.acc_cards_num", | |||
"card_request.disk_capacity", "card_request.resource_type", "card_request.begin_date", "card_request.end_date", "card_request.uid", | |||
"card_request.phone_number", "card_request.email_address", "card_request.wechat", "card_request.org", "card_request.description", "card_request.status", "card_request.review", | |||
"card_request.phone_number", "card_request.email_address", "card_request.wechat", "card_request.is_research_project", "card_request.institution_name", "card_request.project_name", "card_request.project_code", "card_request.org", "card_request.description", "card_request.status", "card_request.review", | |||
"card_request.created_unix"} | |||
var count int64 | |||
var err error | |||
@@ -440,6 +459,6 @@ func SearchCardRequest(opts *CardRequestOptions) (int64, []*CardRequestSpecRes, | |||
} | |||
func UpdateCardRequest(cardRequest *CardRequest) error { | |||
_, err := x.ID(cardRequest.ID).Cols("compute_resource", "contact", "card_type", "acc_cards_num", "disk_capacity", "resource_type", "begin_date", "end_date", "phone_number", "wechat", "email_address", "org", "description", "begin_unix", "end_unix").Update(cardRequest) | |||
_, err := x.ID(cardRequest.ID).Cols("compute_resource", "contact", "card_type", "acc_cards_num", "disk_capacity", "resource_type", "begin_date", "end_date", "phone_number", "wechat", "is_research_project", "institution_name", "project_name", "project_code", "email_address", "org", "description", "begin_unix", "end_unix").Update(cardRequest) | |||
return err | |||
} |
@@ -80,6 +80,7 @@ const ( | |||
JobTypeInference JobType = "INFERENCE" | |||
JobTypeOnlineInference JobType = "ONLINEINFERENCE" | |||
JobTypeSuperCompute JobType = "HPC" | |||
JobTypeGeneral JobType = "GENERAL" | |||
//notebook | |||
ModelArtsCreateQueue ModelArtsJobStatus = "CREATE_QUEUING" //免费资源创建排队中 | |||
@@ -396,6 +397,19 @@ func (task *Cloudbrain) ToShow() *CloudbrainShow { | |||
return c | |||
} | |||
func (task *Cloudbrain) LoadSpec() error { | |||
if task.Spec != nil { | |||
return nil | |||
} | |||
spec := &CloudbrainSpec{} | |||
_, err := x.Where("cloudbrain_id = ?", task.ID).Get(spec) | |||
if err != nil { | |||
return err | |||
} | |||
task.Spec = spec.ConvertToSpecification() | |||
return nil | |||
} | |||
func (task *Cloudbrain) IsRestartTask() bool { | |||
n, _ := x.Where("display_job_name = ?", task.DisplayJobName).Unscoped().Count(&Cloudbrain{}) | |||
if n > 1 { | |||
@@ -487,6 +501,22 @@ func (task *Cloudbrain) GetAiCenter() string { | |||
} | |||
func (task *Cloudbrain) GetAiCenterName() string { | |||
if task.Type == TypeCloudBrainOne { | |||
return "云脑一" | |||
} else if task.Type == TypeCloudBrainTwo { | |||
return "云脑二" | |||
} else if task.Type == TypeCDCenter { | |||
return "启智成都智算" | |||
} else { | |||
tmpArray := strings.Split(task.AiCenter, "+") | |||
if len(tmpArray) == 2 { | |||
return tmpArray[1] | |||
} | |||
} | |||
return task.AiCenter | |||
} | |||
// 是否为在线notebook文件任务 | |||
func (task *Cloudbrain) IsFileNoteBookTask() bool { | |||
return task.JobType == string(JobTypeDebug) && task.BootFile != "" | |||
@@ -2237,6 +2267,11 @@ type Metrics struct { | |||
type NewModelArtsMetricStatisticResult struct { | |||
MetricsInfo []NewModelArtsMetrics `json:"metrics"` //监控详情 | |||
Step int64 `json:"step"` | |||
} | |||
type GrampusMetricStatisticResult struct { | |||
MetricsInfo []NewModelArtsMetrics `json:"metrics"` //监控详情 | |||
} | |||
type NewModelArtsMetrics struct { | |||
@@ -117,6 +117,7 @@ type SearchAvailableValueOptions struct { | |||
IncludeOwnerOnly bool | |||
IncludeStarByMe bool | |||
UID int64 | |||
AiCenterId string | |||
} | |||
type SearchImageOptions struct { | |||
@@ -142,6 +143,7 @@ type SearchImageOptions struct { | |||
AiCenterId string | |||
TrainType string | |||
ComputeResource string | |||
OnlyOpenIImage bool | |||
ListOptions | |||
SearchOrderBy | |||
} | |||
@@ -502,6 +504,9 @@ func GetImageAvailableColumnValues(opts *SearchAvailableValueOptions) []string { | |||
cond = cond.And(builder.Eq{"uid": opts.UID}) | |||
} | |||
if opts.AiCenterId != "" { | |||
cond = cond.And(builder.Like{"ai_center_images", "\"aiCenterId\":\"" + opts.AiCenterId + "\""}) | |||
} | |||
if opts.IncludeStarByMe { | |||
@@ -661,6 +666,9 @@ func SearchImageCondition(opts *SearchImageOptions) builder.Cond { | |||
if opts.CloudbrainType >= 0 { | |||
cond = cond.And(builder.Eq{"cloudbrain_type": opts.CloudbrainType}) | |||
} | |||
if opts.OnlyOpenIImage { | |||
cond = cond.And(builder.Or(builder.Eq{"grampus_base_image": 0}, builder.IsNull{"grampus_base_image"})) | |||
} | |||
return cond | |||
} | |||
@@ -544,6 +544,25 @@ func GetAiCenterShow(aiCenterCode, aiCenterName, language string) string { | |||
if aiCenterName == "" { | |||
aiCenterName = aiCenterCode | |||
} | |||
if aiCenterCode == AICenterOfCloudBrainOne { | |||
if language == defaultLanguage { | |||
return "云脑一" | |||
} else { | |||
return AICenterOfCloudBrainOne | |||
} | |||
} else if aiCenterCode == AICenterOfCloudBrainTwo { | |||
if language == defaultLanguage { | |||
return "云脑二" | |||
} else { | |||
return AICenterOfCloudBrainTwo | |||
} | |||
} else if aiCenterCode == AICenterOfChengdu { | |||
if language == defaultLanguage { | |||
return "启智成都智算" | |||
} else { | |||
return AICenterOfChengdu | |||
} | |||
} | |||
if setting.AiCenterCodeAndNameAndLocMapInfo != nil { | |||
if info, ok := setting.AiCenterCodeAndNameAndLocMapInfo[aiCenterCode]; ok { | |||
if language == defaultLanguage { | |||
@@ -86,7 +86,8 @@ func GetTaskTypeFromAction(a ActionType) TaskType { | |||
ActionCreateGrampusGPUTrainTask, | |||
ActionCreateGrampusGPUInferenceTask, | |||
ActionCreateGrampusILUVATARInferenceTask, | |||
ActionCreateGrampusILUVATARTrainTask: | |||
ActionCreateGrampusILUVATARTrainTask, | |||
ActionCreateGeneralGPUTask: | |||
return TaskCreateCloudbrainTask | |||
case ActionCreateRepo: | |||
return TaskCreatePublicRepo | |||
@@ -70,6 +70,12 @@ type DefaultWechatTemplate struct { | |||
Remark TemplateValue `json:"remark"` | |||
} | |||
type WechatDurationWechatTemplate struct { | |||
Keyword1 TemplateValue `json:"thing11"` | |||
Keyword2 TemplateValue `json:"time9"` | |||
Keyword3 TemplateValue `json:"thing3"` | |||
} | |||
type ActionInfo struct { | |||
Scene Scene `json:"scene"` | |||
} | |||
@@ -12,14 +12,15 @@ import ( | |||
type JobOperateType string | |||
const ( | |||
JobOperateTypeStart JobOperateType = "start" | |||
JobOperateTypeStop JobOperateType = "stop" | |||
JobOperateTypeStart JobOperateType = "start" | |||
JobOperateTypeStop JobOperateType = "stop" | |||
JobOperateTypeLongRunning JobOperateType = "long_running" | |||
) | |||
type CloudbrainStartMsg struct { | |||
} | |||
func (CloudbrainStartMsg) Data(ctx *TemplateContext) *DefaultWechatTemplate { | |||
func (CloudbrainStartMsg) Data(ctx *TemplateContext) interface{} { | |||
return &DefaultWechatTemplate{ | |||
First: TemplateValue{Value: setting.CloudbrainStartedTitle}, | |||
Keyword1: TemplateValue{Value: ctx.Cloudbrain.DisplayJobName}, | |||
@@ -61,7 +62,7 @@ func (CloudbrainStartMsg) TemplateId(ctx *TemplateContext) string { | |||
type CloudbrainStopMsg struct { | |||
} | |||
func (CloudbrainStopMsg) Data(ctx *TemplateContext) *DefaultWechatTemplate { | |||
func (CloudbrainStopMsg) Data(ctx *TemplateContext) interface{} { | |||
return &DefaultWechatTemplate{ | |||
First: TemplateValue{Value: fmt.Sprintf(setting.CloudbrainStoppedTitle, ctx.Cloudbrain.Status)}, | |||
Keyword1: TemplateValue{Value: ctx.Cloudbrain.DisplayJobName}, | |||
@@ -107,6 +108,7 @@ func (CloudbrainStopMsg) TemplateId(ctx *TemplateContext) string { | |||
var startMsg = &CloudbrainStartMsg{} | |||
var stopMsg = &CloudbrainStopMsg{} | |||
var ComingStopMsg = &CloudbrainComingToStopMsg{} | |||
var LongRunningMsg = &CloudbrainLongRunningMsg{} | |||
func GetTemplateFromOperateType(operate JobOperateType) Template { | |||
switch operate { | |||
@@ -150,6 +152,14 @@ func getCloudbrainTemplateUrl(cloudbrain models.Cloudbrain, repo *models.Reposit | |||
} | |||
case string(models.JobTypeInference): | |||
url += "/modelarts/inference-job/" + fmt.Sprint(cloudbrain.JobID) | |||
case string(models.JobTypeGeneral): | |||
if cloudbrain.Type == models.TypeCloudBrainOne { | |||
url += "/cloudbrain/general/" + fmt.Sprint(cloudbrain.ID) | |||
} else if cloudbrain.Type == models.TypeCloudBrainTwo { | |||
url += "/modelarts/general/" + fmt.Sprint(cloudbrain.ID) | |||
} else if cloudbrain.Type == models.TypeC2Net { | |||
url += "/grampus/general/" + fmt.Sprint(cloudbrain.ID) | |||
} | |||
} | |||
return url | |||
} | |||
@@ -170,6 +180,73 @@ func getJobTypeDisplayName(jobType string) string { | |||
string(models.JobTypeBrainScore), | |||
string(models.JobTypeSnn4Ecoset): | |||
return "推理任务" | |||
case string(models.JobTypeGeneral): | |||
return "通用任务" | |||
} | |||
return "" | |||
} | |||
type CloudbrainLongRunningMsg struct { | |||
} | |||
func (CloudbrainLongRunningMsg) Data(ctx *TemplateContext) interface{} { | |||
formattedDuration := formatDuration(ctx.Duration) | |||
formattedRemark := "" | |||
if formattedDuration == "" { | |||
formattedRemark = "任务运行中" | |||
} else { | |||
formattedRemark = fmt.Sprintf("任务运行时间超过%s", formattedDuration) | |||
} | |||
d := int64(ctx.Duration.Seconds()) | |||
t := int64(ctx.Cloudbrain.StartTime) + d | |||
return &WechatDurationWechatTemplate{ | |||
Keyword1: TemplateValue{Value: ctx.Cloudbrain.DisplayJobName}, | |||
Keyword2: TemplateValue{Value: time.Unix(t, 0).Format("2006-01-02 15:04:05")}, | |||
Keyword3: TemplateValue{Value: formattedRemark}, | |||
} | |||
} | |||
func formatDuration(duration time.Duration) string { | |||
switch { | |||
case duration >= time.Second && duration < time.Minute: | |||
return fmt.Sprintf("%d秒", int(duration.Seconds())) | |||
case duration >= time.Minute && duration < time.Hour: | |||
return fmt.Sprintf("%d分钟", int(duration.Minutes())) | |||
case duration >= time.Hour && duration < 24*time.Hour: | |||
return fmt.Sprintf("%d小时", int(duration.Hours())) | |||
case duration >= 24*time.Hour: | |||
days := duration / (24 * time.Hour) | |||
return fmt.Sprintf("%d天", days) | |||
default: | |||
return "" | |||
} | |||
} | |||
func (CloudbrainLongRunningMsg) ShouldSend(ctx *TemplateContext) bool { | |||
if len(setting.CloudbrainLongRunningNotifyList) == 0 { | |||
return false | |||
} | |||
for _, v := range setting.CloudbrainStartedNotifyList { | |||
if v == ctx.Cloudbrain.JobType { | |||
return true | |||
} | |||
} | |||
return false | |||
} | |||
func (CloudbrainLongRunningMsg) MsgId(ctx *TemplateContext) string { | |||
return string(JobOperateTypeLongRunning) + "_" + fmt.Sprint(ctx.Cloudbrain.ID) + "_" + ctx.Duration.String() | |||
} | |||
func (CloudbrainLongRunningMsg) Url(ctx *TemplateContext) string { | |||
repo, err := models.GetRepositoryByID(ctx.Cloudbrain.RepoID) | |||
if err != nil { | |||
log.Error("CloudbrainStartMsg GetRepositoryByID error,%v", err) | |||
return "" | |||
} | |||
return getCloudbrainTemplateUrl(*ctx.Cloudbrain, repo) | |||
} | |||
func (CloudbrainLongRunningMsg) TemplateId(ctx *TemplateContext) string { | |||
return setting.CloudbrainLongRunningTemplateId | |||
} |
@@ -12,7 +12,7 @@ type FinetuneStartMsg struct { | |||
var FinetuneMsg = &FinetuneStartMsg{} | |||
func (FinetuneStartMsg) Data(ctx *TemplateContext) *DefaultWechatTemplate { | |||
func (FinetuneStartMsg) Data(ctx *TemplateContext) interface{} { | |||
return &DefaultWechatTemplate{ | |||
First: TemplateValue{Value: setting.FineTune.Pangu.Wechat.Title}, | |||
Keyword1: TemplateValue{Value: ctx.ModelartsDeploy.DisplayJobName}, | |||
@@ -11,7 +11,7 @@ import ( | |||
type CloudbrainComingToStopMsg struct { | |||
} | |||
func (CloudbrainComingToStopMsg) Data(ctx *TemplateContext) *DefaultWechatTemplate { | |||
func (CloudbrainComingToStopMsg) Data(ctx *TemplateContext) interface{} { | |||
var balance int64 | |||
if ctx.PointAccount != nil { | |||
balance = ctx.PointAccount.Balance | |||
@@ -3,6 +3,7 @@ package wechat | |||
import ( | |||
"errors" | |||
"fmt" | |||
"time" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/log" | |||
@@ -11,7 +12,7 @@ import ( | |||
type Template interface { | |||
ShouldSend(ctx *TemplateContext) bool | |||
Data(ctx *TemplateContext) *DefaultWechatTemplate | |||
Data(ctx *TemplateContext) interface{} | |||
MsgId(ctx *TemplateContext) string | |||
Url(ctx *TemplateContext) string | |||
TemplateId(ctx *TemplateContext) string | |||
@@ -22,6 +23,7 @@ type TemplateContext struct { | |||
EstimatedEndTime timeutil.TimeStamp | |||
PointAccount *models.PointAccount | |||
ModelartsDeploy *models.ModelartsDeploy | |||
Duration time.Duration | |||
} | |||
func SendTemplateMsg(template Template, ctx *TemplateContext, userId int64) error { | |||
@@ -49,7 +51,7 @@ func SendTemplateMsg(template Template, ctx *TemplateContext, userId int64) erro | |||
ClientMsgId: template.MsgId(ctx), | |||
Data: d, | |||
} | |||
log.Info("SendTemplateMsg before calling.userId = %d,req=%v data=%v", userId, req, *d) | |||
log.Info("SendTemplateMsg before calling.userId = %d,req=%v data=%v", userId, req, d) | |||
err, retryFlag := sendTemplateMsg(req) | |||
if retryFlag { | |||
log.Info("SendTemplateMsg calling.userId = %d", userId) | |||
@@ -9,6 +9,7 @@ import ( | |||
"code.gitea.io/gitea/modules/auth" | |||
"code.gitea.io/gitea/modules/repository" | |||
"code.gitea.io/gitea/modules/timeutil" | |||
"time" | |||
) | |||
// Notifier defines an interface to notify receiver | |||
@@ -68,4 +69,5 @@ type Notifier interface { | |||
NotifyCloudbrainTaskComingToFinished(cloudbrain *models.Cloudbrain, endTime timeutil.TimeStamp, account *models.PointAccount) | |||
NotifyChangeFinetuneStatus(deployment *models.ModelartsDeploy) | |||
NotifyInviteFriendRegister(inviter, invited *models.User) | |||
NotifyLongRunningAITask(cloudbrain *models.Cloudbrain, duration time.Duration) | |||
} |
@@ -9,6 +9,7 @@ import ( | |||
"code.gitea.io/gitea/modules/auth" | |||
"code.gitea.io/gitea/modules/repository" | |||
"code.gitea.io/gitea/modules/timeutil" | |||
"time" | |||
) | |||
// NullNotifier implements a blank notifier | |||
@@ -193,3 +194,7 @@ func (*NullNotifier) NotifyChangeFinetuneStatus(deployment *models.ModelartsDepl | |||
func (*NullNotifier) NotifyInviteFriendRegister(inviter, invited *models.User) { | |||
} | |||
func (*NullNotifier) NotifyLongRunningAITask(cloudbrain *models.Cloudbrain, duration time.Duration) { | |||
} |
@@ -19,6 +19,7 @@ import ( | |||
"code.gitea.io/gitea/modules/repository" | |||
"code.gitea.io/gitea/modules/setting" | |||
"code.gitea.io/gitea/modules/timeutil" | |||
"time" | |||
) | |||
var ( | |||
@@ -340,3 +341,10 @@ func NotifyInviteFriendRegister(inviter, invited *models.User) { | |||
notifier.NotifyInviteFriendRegister(inviter, invited) | |||
} | |||
} | |||
// NotifyAITaskDuration | |||
func NotifyLongRunningAITask(cloudbrain *models.Cloudbrain, duration time.Duration) { | |||
for _, notifier := range notifiers { | |||
notifier.NotifyLongRunningAITask(cloudbrain, duration) | |||
} | |||
} |
@@ -10,6 +10,7 @@ import ( | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/notification/base" | |||
"code.gitea.io/gitea/modules/timeutil" | |||
"time" | |||
) | |||
type wechatNotifier struct { | |||
@@ -47,3 +48,9 @@ func (*wechatNotifier) NotifyChangeFinetuneStatus(deployment *models.ModelartsDe | |||
template := wechat.FinetuneMsg | |||
go wechat.SendTemplateMsg(template, &wechat.TemplateContext{ModelartsDeploy: deployment}, deployment.UserID) | |||
} | |||
func (*wechatNotifier) NotifyLongRunningAITask(cloudbrain *models.Cloudbrain, duration time.Duration) { | |||
log.Info("NotifyAITaskDuration cloudbrain.id=%d", cloudbrain.ID) | |||
template := wechat.LongRunningMsg | |||
go wechat.SendTemplateMsg(template, &wechat.TemplateContext{Cloudbrain: cloudbrain, Duration: duration}, cloudbrain.UserID) | |||
} |
@@ -1,5 +1,11 @@ | |||
package redis_key | |||
import ( | |||
"code.gitea.io/gitea/models" | |||
"fmt" | |||
"time" | |||
) | |||
const PREFIX = "wechat" | |||
func WechatBindingUserIdKey(sceneStr string) string { | |||
@@ -12,3 +18,7 @@ func WechatAccessTokenKey() string { | |||
func AccessTokenLockKey() string { | |||
return KeyJoin(PREFIX, "access_token_lock") | |||
} | |||
func LongRunningNotificationKey(cloudbrain *models.Cloudbrain, duration time.Duration) string { | |||
return KeyJoin(PREFIX, fmt.Sprint(cloudbrain.ID), duration.String(), "long_running_notification") | |||
} |
@@ -716,19 +716,22 @@ var ( | |||
TreePathOfSubscribe string | |||
//wechat template msg config | |||
CloudbrainStartedTemplateId string | |||
CloudbrainStartedNotifyList []string | |||
CloudbrainStartedTitle string | |||
CloudbrainStartedRemark string | |||
CloudbrainStoppedTemplateId string | |||
CloudbrainStoppedNotifyList []string | |||
CloudbrainStoppedTitle string | |||
CloudbrainStoppedRemark string | |||
CloudbrainComingStopTemplateId string | |||
CloudbrainComingStopTitle string | |||
CloudbrainComingStopChargeLink string | |||
CloudbrainComingStopRemark string | |||
CloudbrainComingStopSendFlag bool | |||
CloudbrainStartedTemplateId string | |||
CloudbrainStartedNotifyList []string | |||
CloudbrainStartedTitle string | |||
CloudbrainStartedRemark string | |||
CloudbrainStoppedTemplateId string | |||
CloudbrainStoppedNotifyList []string | |||
CloudbrainStoppedTitle string | |||
CloudbrainStoppedRemark string | |||
CloudbrainComingStopTemplateId string | |||
CloudbrainComingStopTitle string | |||
CloudbrainComingStopChargeLink string | |||
CloudbrainComingStopRemark string | |||
CloudbrainComingStopSendFlag bool | |||
CloudbrainLongRunningNotifyList []string | |||
CloudbrainLongRunningTemplateId string | |||
CloudbrainLongRunningNotifyInterval time.Duration | |||
//repo square config | |||
IncubationSourceOrgName string | |||
@@ -1717,6 +1720,9 @@ func NewContext() { | |||
CloudbrainComingStopChargeLink = sec.Key("CLOUDBRAIN_COMING_STOP_CHARGE_LINK").MustString("请参考“个人中心 > 算力积分”页面的“积分获取说明”获取积分。") | |||
CloudbrainComingStopRemark = sec.Key("CLOUDBRAIN_COMING_STOP_REMARK").MustString("为了不影响您使用,请您尽快获取算力积分。") | |||
CloudbrainComingStopSendFlag = sec.Key("CLOUDBRAIN_COMING_STOP_SEND_FLAG").MustBool(true) | |||
CloudbrainLongRunningNotifyList = strings.Split(sec.Key("CLOUDBRAIN_LONG_RUNNING_NOTIFY_LIST").MustString("GENERAL"), ",") | |||
CloudbrainLongRunningTemplateId = sec.Key("CLOUDBRAIN_LONG_RUNNING_TEMPLATE_ID").MustString("") | |||
CloudbrainLongRunningNotifyInterval, _ = time.ParseDuration(sec.Key("CLOUDBRAIN_LONG_RUNNING_NOTIFY_INTERVAL").MustString("")) | |||
sec = Cfg.Section("repo-square") | |||
IncubationSourceOrgName = sec.Key("INCUBATION_ORG_NAME").MustString("OpenI") | |||
@@ -1,22 +1,26 @@ | |||
package structs | |||
type CardReq struct { | |||
ID int64 `json:"id"` | |||
ComputeResource string `json:"compute_resource" binding:"Required"` | |||
CardType string `json:"card_type" binding:"Required"` | |||
AccCardsNum string `json:"acc_cards_num" binding:"Required"` | |||
DiskCapacity int64 `json:"disk_capacity"` | |||
ResourceType int `json:"resource_type" binding:"Required"` | |||
BeginDate string `json:"begin_date" binding:"Required"` | |||
EndDate string `json:"end_date" binding:"Required"` | |||
Contact string `json:"contact" binding:"Required"` | |||
PhoneNumber string `json:"phone_number" binding:"Required"` | |||
EmailAddress string `json:"email_address" binding:"Required;Email;MaxSize(254)"` | |||
Wechat string `json:"wechat" binding:"Required;MaxSize(254)"` | |||
Org string `json:"org" binding:"MaxSize(500)"` | |||
Description string `json:"description" binding:"MaxSize(3000)"` | |||
Review string `json:"review"` | |||
SpecIds []int64 `json:"spec_ids"` | |||
ID int64 `json:"id"` | |||
ComputeResource string `json:"compute_resource" binding:"Required"` | |||
CardType string `json:"card_type" binding:"Required"` | |||
AccCardsNum string `json:"acc_cards_num" binding:"Required"` | |||
DiskCapacity int64 `json:"disk_capacity"` | |||
ResourceType int `json:"resource_type" binding:"Required"` | |||
BeginDate string `json:"begin_date" binding:"Required"` | |||
EndDate string `json:"end_date" binding:"Required"` | |||
Contact string `json:"contact" binding:"Required"` | |||
PhoneNumber string `json:"phone_number" binding:"Required"` | |||
EmailAddress string `json:"email_address" binding:"Required;Email;MaxSize(254)"` | |||
Wechat string `json:"wechat" binding:"Required;MaxSize(254)"` | |||
IsResearchProject bool `json:"is_research_project"` | |||
InstitutionName string `json:"institution_name" binding:"MaxSize(254)"` | |||
ProjectName string `json:"project_name" binding:"MaxSize(254)"` | |||
ProjectCode string `json:"project_code" binding:"MaxSize(254)"` | |||
Org string `json:"org" binding:"MaxSize(500)"` | |||
Description string `json:"description" binding:"MaxSize(3000)"` | |||
Review string `json:"review"` | |||
SpecIds []int64 `json:"spec_ids"` | |||
} | |||
type RequestSpecInfo struct { | |||
@@ -1307,6 +1307,7 @@ cloudbrain.morethanonejob=You already have a running or waiting task, create it | |||
cloudbrain.morethanonejob1=You have created an <span style="color:rgba(242, 113, 28, 1);"> equivalent task </span> that is waiting or running, please wait for the task to finish before creating it. | |||
cloudbrain.morethanonejob2=You can view all your Cloud Brain tasks in <a href="/cloudbrains" target="_blank"> Home > Cloudbrain Task </a>. | |||
modelarts.general_job = General Task | |||
modelarts.online_infer = Online Inference | |||
modelarts.infer_job_model = Model | |||
modelarts.infer_job_model_file = Model File | |||
@@ -3246,6 +3247,7 @@ task_createmodel=`created new model <a href="%s/modelmanage/model_readme_tmpl?na | |||
task_gputrainjob=`created CPU/GPU training task <a href="%s/cloudbrain/train-job/%s">%s</a>` | |||
task_c2netnputrainjob=`created NPU training task <a href="%s/grampus/train-job/%s">%s</a>` | |||
task_c2netgputrainjob=`created CPU/GPU training task <a href="%s/grampus/train-job/%s">%s</a>` | |||
task_c2netgeneraljob=`created GPU general task <a href="%s/grampus/general/%s">%s</a>` | |||
binded_wechat=binded WeChat | |||
dataset_recommended=`created dataset <a href="%s/datasets">%s</a> was set as recommended dataset` | |||
create_image=`committed image <span style="font-weight:bold;">%s</span>` | |||
@@ -1319,6 +1319,7 @@ cloudbrain.morethanonejob=您已经创建了一个正在等待或运行中的同 | |||
cloudbrain.morethanonejob1=您已经有 <span style="color:rgba(242, 113, 28, 1);">同类任务</span> 正在等待或运行中,请等待任务结束再创建; | |||
cloudbrain.morethanonejob2=可以在 “<a href="/cloudbrains" target="_blank" >个人中心 > 云脑任务</a>” 查看您所有的云脑任务。 | |||
modelarts.general_job = 通用任务 | |||
modelarts.online_infer = 在线推理 | |||
modelarts.infer_job_model = 模型名称 | |||
modelarts.infer_job_model_file = 模型文件 | |||
@@ -3265,6 +3266,7 @@ task_createmodel=`导入了新模型 <a href="%s/modelmanage/model_readme_tmpl?n | |||
task_gputrainjob=`创建了CPU/GPU类型训练任务 <a href="%s/cloudbrain/train-job/%s">%s</a>` | |||
task_c2netnputrainjob=`创建了NPU类型训练任务 <a href="%s/grampus/train-job/%s">%s</a>` | |||
task_c2netgputrainjob=`创建了CPU/GPU类型训练任务 <a href="%s/grampus/train-job/%s">%s</a>` | |||
task_c2netgeneraljob=`创建了GPU类型通用任务 <a href="%s/grampus/general/%s">%s</a>` | |||
binded_wechat=绑定微信 | |||
dataset_recommended=`创建的数据集 <a href="%s/datasets">%s</a> 被设置为推荐数据集` | |||
create_image=`提交了镜像 <span style="font-weight:bold;">%s</span>` | |||
@@ -255,7 +255,7 @@ document.onreadystatechange = function () { | |||
} | |||
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"|| record.OpType == "47" | |||
|| record.OpType == "48"|| record.OpType == "49" || record.OpType == "53" | |||
|| record.OpType == "48"|| record.OpType == "49" || record.OpType == "53" || record.OpType == "54" | |||
){ | |||
html += recordPrefix + actionName; | |||
const taskLink = getTaskLink(record); | |||
@@ -348,6 +348,12 @@ function getTaskLink(record){ | |||
re = re + "/supercompute/job/" + record.Cloudbrain.ID; | |||
} else if(record.OpType == 45){ | |||
re = re + "/grampus/onlineinfer/" + record.Content; | |||
} else if(record.OpType == 54){ | |||
if (record.Cloudbrain) { | |||
re = re + "/grampus/general/" + record.Cloudbrain.ID; | |||
} else { | |||
re = ''; | |||
} | |||
} | |||
re = encodeURI(re); | |||
return re; | |||
@@ -519,6 +525,7 @@ var actionNameZH={ | |||
"48":"创建了ILUVATAR-GPGPU类型调试任务", | |||
"49":"创建了METAX-GPGPU类型调试任务", | |||
"53":"创建了ILUVATAR-GPGPU类型训练任务", | |||
"54":"创建了GPU类型通用任务", | |||
}; | |||
var actionNameEN={ | |||
@@ -564,6 +571,7 @@ var actionNameEN={ | |||
"48":" created ILUVATAR-GPGPU type debugging task ", | |||
"49":" created METAX-GPGPU type debugging task ", | |||
"53":" created ILUVATAR-GPGPU type training task ", | |||
"54":" created GPU type general task ", | |||
}; | |||
var repoAndOrgZH={ | |||
@@ -4,7 +4,6 @@ import ( | |||
"net/http" | |||
"net/url" | |||
"strconv" | |||
"strings" | |||
"time" | |||
"github.com/360EntSecGroup-Skylar/excelize/v2" | |||
@@ -16,7 +15,6 @@ import ( | |||
"code.gitea.io/gitea/modules/base" | |||
"code.gitea.io/gitea/modules/context" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/setting" | |||
cloudbrainService "code.gitea.io/gitea/services/cloudbrain" | |||
) | |||
@@ -29,98 +27,9 @@ const ( | |||
) | |||
func CloudBrains(ctx *context.Context) { | |||
ctx.Data["Title"] = ctx.Tr("admin.cloudBrains") | |||
ctx.Data["PageIsAdmin"] = true | |||
ctx.Data["PageIsAdminCloudBrains"] = true | |||
listType := ctx.Query("listType") | |||
jobType := ctx.Query("jobType") | |||
jobStatus := ctx.Query("jobStatus") | |||
aiCenter := ctx.Query("aiCenter") | |||
cluster := ctx.Query("cluster") | |||
ctx.Data["ListType"] = listType | |||
ctx.Data["JobType"] = jobType | |||
ctx.Data["JobStatus"] = jobStatus | |||
ctx.Data["aiCenter"] = aiCenter | |||
ctx.Data["cluster"] = cluster | |||
page := ctx.QueryInt("page") | |||
if page <= 0 { | |||
page = 1 | |||
} | |||
var jobTypes []string | |||
jobTypeNot := false | |||
if jobType == string(models.JobTypeBenchmark) { | |||
jobTypes = append(jobTypes, models.AllBenchMarkJobType()...) | |||
} else if jobType != "all" && jobType != "" { | |||
jobTypes = append(jobTypes, jobType) | |||
} | |||
var jobStatuses []string | |||
jobStatusNot := false | |||
if jobStatus == "other" { | |||
jobStatusNot = true | |||
jobStatuses = append(jobStatuses, string(models.ModelArtsTrainJobWaiting), string(models.ModelArtsTrainJobFailed), string(models.ModelArtsRunning), string(models.ModelArtsTrainJobCompleted), | |||
string(models.ModelArtsStarting), string(models.ModelArtsRestarting), string(models.ModelArtsStartFailed), | |||
string(models.ModelArtsStopping), string(models.ModelArtsStopped), string(models.JobSucceeded)) | |||
} else if jobStatus != "all" && jobStatus != "" { | |||
jobStatuses = append(jobStatuses, jobStatus) | |||
} | |||
keyword := strings.Trim(ctx.Query("q"), " ") | |||
ciTasks, count, err := models.Cloudbrains(&models.CloudbrainsOptions{ | |||
ListOptions: models.ListOptions{ | |||
Page: page, | |||
PageSize: setting.UI.IssuePagingNum, | |||
}, | |||
Keyword: keyword, | |||
JobTypeNot: jobTypeNot, | |||
JobStatusNot: jobStatusNot, | |||
JobStatus: jobStatuses, | |||
JobTypes: jobTypes, | |||
NeedRepoInfo: true, | |||
IsLatestVersion: modelarts.IsLatestVersion, | |||
ComputeResource: listType, | |||
Type: models.TypeCloudBrainAll, | |||
AiCenter: aiCenter, | |||
Cluster: cluster, | |||
}) | |||
if err != nil { | |||
ctx.ServerError("Get job failed:", err) | |||
return | |||
} | |||
models.LoadSpecs4CloudbrainInfo(ciTasks) | |||
for i, task := range ciTasks { | |||
ciTasks[i] = cloudbrainService.UpdateCloudbrainAiCenter(ciTasks[i]) | |||
ciTasks[i].Cloudbrain.AiCenter = repo.GetAiCenterNameByCode(ciTasks[i].Cloudbrain.AiCenter, ctx.Language()) | |||
ciTasks[i].CanDebug = true | |||
ciTasks[i].CanDel = true | |||
ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource | |||
if ciTasks[i].Cloudbrain.Spec != nil { | |||
if ciTasks[i].Cloudbrain.Type == models.TypeC2Net { | |||
ciTasks[i].Cloudbrain.Spec.Cluster = models.C2NetCluster | |||
} else { | |||
ciTasks[i].Cloudbrain.Spec.Cluster = models.OpenICluster | |||
} | |||
} | |||
} | |||
pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, getTotalPage(count, setting.UI.IssuePagingNum)) | |||
pager.SetDefaultParams(ctx) | |||
pager.AddParam(ctx, "listType", "ListType") | |||
ctx.Data["Page"] = pager | |||
ctx.Data["PageIsCloudBrain"] = true | |||
ctx.Data["Tasks"] = ciTasks | |||
ctx.Data["CanCreate"] = true | |||
ctx.Data["Keyword"] = keyword | |||
ctx.HTML(200, tplCloudBrains) | |||
} | |||
func Images(ctx *context.Context) { | |||
@@ -257,6 +257,7 @@ func GetAITaskInfo(ctx *context.Context) { | |||
CanDownload: cloudbrain.CanDownloadJob(ctx, job), | |||
EarlyVersionList: earlyVersionList, | |||
CanCreateVersion: job.CanUserModify(ctx.User), | |||
CanModify: job.CanUserModify(ctx.User), | |||
} | |||
//根据权限去掉数据集和模型信息 | |||
res.TryToRemoveDatasetAndModelInfo(ctx.User) | |||
@@ -280,6 +281,7 @@ func GetAITaskBriefInfo(ctx *context.Context) { | |||
return | |||
} | |||
res.Tr(ctx.Language()) | |||
res.ClearNonPublicFields() | |||
ctx.JSON(http.StatusOK, response.OuterSuccessWithData(res)) | |||
} | |||
@@ -469,7 +471,7 @@ func GetAITaskList(ctx *context.Context) { | |||
if jobType != "" { | |||
jobTypes = append(jobTypes, jobType) | |||
} | |||
result, err := task.GetAITaskList(entity.GetTaskListReq{ | |||
result, err := task.GetRepoAITaskList(entity.GetTaskListReq{ | |||
ListOptions: models.ListOptions{ | |||
PageSize: setting.UI.IssuePagingNum, | |||
Page: page, | |||
@@ -487,6 +489,9 @@ func GetAITaskList(ctx *context.Context) { | |||
} | |||
result.CanCreateTask = cloudbrain.CanCreateOrDebugJob(ctx) | |||
result.IsRepoEmpty = ctx.Repo.Repository.IsEmpty | |||
for _, r := range result.Tasks { | |||
r.Task.Tr(ctx.Language()) | |||
} | |||
ctx.JSON(http.StatusOK, response.OuterSuccessWithData(result)) | |||
} | |||
@@ -577,3 +582,105 @@ func GenerateSDKCode(ctx *context.Context) { | |||
code := task.GenerateSDKCode(datasetNames, pretrainModelNames, parameterKeys, models.JobType(jobType)) | |||
ctx.JSON(http.StatusOK, response.OuterSuccessWithData(map[string]string{"code": code})) | |||
} | |||
func GetMyAITaskList(ctx *context.Context) { | |||
jobType := ctx.Query("job_type") | |||
jobStatus := ctx.Query("job_status") | |||
aiCenter := ctx.Query("ai_center") | |||
cluster := ctx.Query("cluster") | |||
computeSourceName := ctx.Query("compute_source") | |||
excludeStatus := []string{} | |||
if jobStatus == "other" { | |||
statusStr := ctx.Query("exclude_status") | |||
if statusStr == "" { | |||
ctx.JSON(http.StatusOK, response.PARAM_ERROR) | |||
} | |||
excludeStatus = strings.Split(statusStr, ",") | |||
} | |||
keyword := strings.Trim(ctx.Query("q"), " ") | |||
page := ctx.QueryInt("page") | |||
if page <= 0 { | |||
page = 1 | |||
} | |||
pageSize := ctx.QueryInt("pageSize") | |||
if pageSize <= 0 || pageSize > 100 { | |||
pageSize = setting.UI.IssuePagingNum | |||
} | |||
computeSource := models.GetComputeSourceInstance(computeSourceName) | |||
result, err := task.GetMyAITaskList(entity.GetMyTaskListReq{ | |||
ListOptions: models.ListOptions{ | |||
PageSize: pageSize, | |||
Page: page, | |||
}, | |||
ComputeSource: computeSource, | |||
JobType: jobType, | |||
User: ctx.User, | |||
IsRepoOwner: ctx.Repo.IsOwner(), | |||
JobStatus: jobStatus, | |||
Keyword: keyword, | |||
AICenter: aiCenter, | |||
Cluster: cluster, | |||
ExcludeStatus: excludeStatus, | |||
}) | |||
if err != nil { | |||
log.Error("GetMyAITaskList error,err=%v", err) | |||
ctx.JSON(http.StatusOK, response.OuterTrBizError(err, ctx)) | |||
return | |||
} | |||
result.CanCreateTask = cloudbrain.CanCreateOrDebugJob(ctx) | |||
for _, r := range result.Tasks { | |||
r.Task.Tr(ctx.Language()) | |||
} | |||
ctx.JSON(http.StatusOK, response.OuterSuccessWithData(result)) | |||
} | |||
func GetAITaskList4Admin(ctx *context.Context) { | |||
jobType := ctx.Query("job_type") | |||
jobStatus := ctx.Query("job_status") | |||
aiCenter := ctx.Query("ai_center") | |||
cluster := ctx.Query("cluster") | |||
computeSourceName := ctx.Query("compute_source") | |||
excludeStatus := []string{} | |||
if jobStatus == "other" { | |||
statusStr := ctx.Query("exclude_status") | |||
if statusStr == "" { | |||
ctx.JSON(http.StatusOK, response.PARAM_ERROR) | |||
} | |||
excludeStatus = strings.Split(statusStr, ",") | |||
} | |||
keyword := strings.Trim(ctx.Query("q"), " ") | |||
page := ctx.QueryInt("page") | |||
if page <= 0 { | |||
page = 1 | |||
} | |||
pageSize := ctx.QueryInt("pageSize") | |||
if pageSize <= 0 || pageSize > 100 { | |||
pageSize = setting.UI.IssuePagingNum | |||
} | |||
computeSource := models.GetComputeSourceInstance(computeSourceName) | |||
result, err := task.GetAITaskList4Admin(entity.GetMyTaskListReq{ | |||
ListOptions: models.ListOptions{ | |||
PageSize: pageSize, | |||
Page: page, | |||
}, | |||
ComputeSource: computeSource, | |||
JobType: jobType, | |||
User: ctx.User, | |||
JobStatus: jobStatus, | |||
Keyword: keyword, | |||
AICenter: aiCenter, | |||
Cluster: cluster, | |||
ExcludeStatus: excludeStatus, | |||
}) | |||
if err != nil { | |||
log.Error("GetMyAITaskList error,err=%v", err) | |||
ctx.JSON(http.StatusOK, response.OuterTrBizError(err, ctx)) | |||
return | |||
} | |||
result.CanCreateTask = cloudbrain.CanCreateOrDebugJob(ctx) | |||
for _, r := range result.Tasks { | |||
r.Task.Tr(ctx.Language()) | |||
} | |||
ctx.JSON(http.StatusOK, response.OuterSuccessWithData(result)) | |||
} |
@@ -681,6 +681,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Group("/ai_task", func() { | |||
m.Get("/generate_sdk_code", ai_task.GenerateSDKCode) | |||
m.Get("/my_list", reqToken(), ai_task.GetMyAITaskList) | |||
}) | |||
// Miscellaneous | |||
@@ -1471,6 +1472,9 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Combo("").Post(bind(models.OperateRoleReq{}), admin.AddUserRole). | |||
Delete(bind(models.OperateRoleReq{}), admin.DeleteUserRole) | |||
}) | |||
m.Group("/ai_task", func() { | |||
m.Get("/list", ai_task.GetAITaskList4Admin) | |||
}) | |||
}, reqToken(), reqSiteAdmin()) | |||
m.Group("/topics", func() { | |||
@@ -119,6 +119,16 @@ func GetAvailableFilerInfo(ctx *context.APIContext) { | |||
IncludeStarByMe: starByMe, | |||
UID: getUID(ctx), | |||
} | |||
if ctx.QueryInt64("spec") > 0 { | |||
spec, err := models.FindSpecs(models.FindSpecsOptions{ | |||
SpecId: ctx.QueryInt64("spec"), | |||
}) | |||
if err == nil { | |||
opts.AiCenterId = spec[0].AiCenterCode | |||
} | |||
} | |||
ctx.JSON(http.StatusOK, models.BaseMessageWithDataApi{ | |||
Data: models.GetImageAvailableColumnValues(opts), | |||
}) | |||
@@ -153,18 +153,19 @@ func GetAdminCardRequestList(ctx *context.Context) { | |||
useBeginTime.Unix() | |||
opts := &models.CardRequestOptions{ | |||
OrderBy: models.OrderByStatus, | |||
NeedSpec: true, | |||
Keyword: strings.Trim(ctx.Query("q"), " "), | |||
AiCenterCode: ctx.Query("center"), | |||
Cluster: ctx.Query("cluster"), | |||
ComputeResource: ctx.Query("resource"), | |||
AccCardType: ctx.Query("cardType"), | |||
QueueId: ctx.QueryInt64("queue"), | |||
UseBeginTime: getTimeUnix(ctx.Query("useBeginTime")), | |||
UseEndTime: getTimeUnix(ctx.Query("useEndTime")), | |||
BeginTimeUnix: getTimeUnix(ctx.Query("beginTime")), | |||
EndTimeUnix: getTimeUnix(ctx.Query("endTime")), | |||
OrderBy: models.OrderByStatus, | |||
NeedSpec: true, | |||
Keyword: strings.Trim(ctx.Query("q"), " "), | |||
AiCenterCode: ctx.Query("center"), | |||
Cluster: ctx.Query("cluster"), | |||
ComputeResource: ctx.Query("resource"), | |||
AccCardType: ctx.Query("cardType"), | |||
QueueId: ctx.QueryInt64("queue"), | |||
IsResearchProject: ctx.QueryInt("isResearchProject"), | |||
UseBeginTime: getTimeUnix(ctx.Query("useBeginTime")), | |||
UseEndTime: getTimeUnix(ctx.Query("useEndTime")), | |||
BeginTimeUnix: getTimeUnix(ctx.Query("beginTime")), | |||
EndTimeUnix: getTimeUnix(ctx.Query("endTime")), | |||
} | |||
opts.ListOptions = models.ListOptions{ | |||
Page: page, | |||
@@ -306,6 +307,10 @@ func getRequestShowList(ctx *context.Context, opts *models.CardRequestOptions, c | |||
customShow.PhoneNumber = v.PhoneNumber | |||
customShow.EmailAddress = v.EmailAddress | |||
customShow.Wechat = v.Wechat | |||
customShow.IsResearchProject = v.IsResearchProject | |||
customShow.InstitutionName = v.InstitutionName | |||
customShow.ProjectName = v.ProjectName | |||
customShow.ProjectCode = v.ProjectCode | |||
customShow.Contact = v.Contact | |||
customShow.Specs = v.Specs | |||
customShow.Org = v.Org | |||
@@ -1775,6 +1775,7 @@ func GetImages(ctx *context.Context, opts *models.SearchImageOptions) { | |||
opts.OperationSystem = ctx.Query("os") | |||
opts.OperationSystemVersion = ctx.Query("osVersion") | |||
opts.ThirdPackages = ctx.Query("thirdParty") | |||
opts.OnlyOpenIImage = ctx.QueryBool("onlyOpenIImage") | |||
if ctx.QueryInt64("spec") > 0 { | |||
spec, err := models.FindSpecs(models.FindSpecsOptions{ | |||
@@ -2136,107 +2137,12 @@ func SyncCloudbrainStatus() { | |||
if task.JobType == string(models.JobTypeModelSafety) { | |||
continue | |||
} | |||
if task.IsNewAITask() { | |||
task, _ = ai_task.UpdateCloudbrain(task) | |||
if task.Duration >= setting.MaxDuration && task.JobType == string(models.JobTypeDebug) { | |||
ai_task.StopCloudbrain(task) | |||
} | |||
continue | |||
} | |||
if task.Type == models.TypeCloudBrainOne { | |||
task, err = cloudbrainTask.SyncCloudBrainOneStatus(task) | |||
if err != nil { | |||
log.Error("Sync cloud brain one (%s) failed:%v", task.JobName, err) | |||
continue | |||
} | |||
} else if task.Type == models.TypeCloudBrainTwo || task.Type == models.TypeCDCenter { | |||
if task.JobType == string(models.JobTypeDebug) { | |||
err := modelarts.HandleNotebookInfo(task) | |||
if err != nil { | |||
log.Error("HandleNotebookInfo(%s) failed:%v", task.DisplayJobName, err) | |||
continue | |||
} | |||
} else if task.JobType == string(models.JobTypeTrain) || task.JobType == string(models.JobTypeInference) { | |||
err := modelarts.HandleTrainJobInfo(task) | |||
if err != nil { | |||
log.Error("HandleTrainJobInfo(%s) failed:%v", task.DisplayJobName, err) | |||
continue | |||
} | |||
} else { | |||
log.Error("task.JobType(%s) is error:%s", task.DisplayJobName, task.JobType) | |||
} | |||
} else if task.Type == models.TypeC2Net { | |||
if task.JobType == string(models.JobTypeDebug) || task.JobType == string(models.JobTypeSuperCompute) { | |||
cloudbrainTask.SyncGrampusNotebookStatus(task) | |||
} else { | |||
result, err := grampus.GetJob(task.JobID) | |||
if err != nil { | |||
log.Error("GetTrainJob(%s) failed:%v", task.DisplayJobName, err) | |||
continue | |||
} | |||
if result != nil { | |||
if len(result.JobInfo.Tasks) > 0 { | |||
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) | |||
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(%s) failed:%v", task.JobName, err) | |||
continue | |||
} | |||
} | |||
} | |||
} else { | |||
log.Error("task.Type(%s) is error:%d", task.JobName, task.Type) | |||
} | |||
if task.Status != string(models.JobWaiting) { | |||
if (task.Duration >= setting.MaxDuration && task.JobType == string(models.JobTypeDebug)) || (task.Duration >= setting.Grampus.MMLSparkMaxTime && task.JobType == string(models.JobTypeSuperCompute)) { | |||
log.Info("begin to stop job(%s), because of the duration", task.DisplayJobName) | |||
err = cloudbrainTask.StopDebugJob(task) | |||
if err != nil { | |||
log.Error("StopJob(%s) failed:%v", task.DisplayJobName, err) | |||
continue | |||
} | |||
oldStatus := task.Status | |||
task.Status = string(models.JobStopped) | |||
if task.EndTime == 0 { | |||
task.EndTime = timeutil.TimeStampNow() | |||
} | |||
task.ComputeAndSetDuration() | |||
if oldStatus != task.Status { | |||
notification.NotifyChangeCloudbrainStatus(task, oldStatus) | |||
} | |||
err = models.UpdateJob(task) | |||
if err != nil { | |||
log.Error("UpdateJob(%s) failed:%v", task.DisplayJobName, err) | |||
continue | |||
} | |||
} | |||
task, _ = ai_task.UpdateCloudbrain(task) | |||
if task.Duration >= setting.MaxDuration && task.JobType == string(models.JobTypeDebug) { | |||
ai_task.StopCloudbrain(task) | |||
} | |||
go ai_task.TryToNotifyLongRunningTask(task) | |||
} | |||
return | |||
@@ -0,0 +1,28 @@ | |||
package repo | |||
import ( | |||
"net/http" | |||
"code.gitea.io/gitea/modules/base" | |||
"code.gitea.io/gitea/modules/context" | |||
) | |||
const ( | |||
tplGrampusGeneralIndex base.TplName = "repo/grampus/general/list" | |||
tplGrampusGeneralShow base.TplName = "repo/grampus/general/show" | |||
tplGrampusGeneralNew base.TplName = "repo/grampus/general/new" | |||
) | |||
func GrampusGeneralNew(ctx *context.Context) { | |||
ctx.Data["PageIsCloudBrain"] = true | |||
ctx.HTML(http.StatusOK, tplGrampusGeneralNew) | |||
} | |||
func GrampusGeneralShow(ctx *context.Context) { | |||
ctx.Data["PageIsCloudBrain"] = true | |||
ctx.HTML(http.StatusOK, tplGrampusGeneralShow) | |||
} | |||
func GrampusGeneralIndex(ctx *context.Context) { | |||
ctx.Data["PageIsCloudBrain"] = true | |||
ctx.HTML(http.StatusOK, tplGrampusGeneralIndex) | |||
} |
@@ -69,7 +69,7 @@ func RepoStatisticDaily(date string) { | |||
var error_projects = make([]string, 0) | |||
pool := tunny.NewFunc(4, statisticOneRepo) | |||
pool := tunny.NewFunc(8, statisticOneRepo) | |||
defer pool.Close() | |||
statisticWg.Add(len(repos)) | |||
for _, repo := range repos { | |||
@@ -1381,6 +1381,14 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.GrampusOnlineInferNew) | |||
}) | |||
m.Group("/general", func() { | |||
m.Get("", reqRepoCloudBrainReader, repo.GrampusGeneralIndex) | |||
m.Group("/:id", func() { | |||
m.Get("", reqRepoCloudBrainReader, repo.GrampusGeneralShow) | |||
}) | |||
m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.GrampusGeneralNew) | |||
}) | |||
m.Group("/train-job", func() { | |||
m.Group("/:jobid", func() { | |||
m.Get("", reqRepoCloudBrainReader, repo.GrampusTrainJobShow) | |||
@@ -20,11 +20,8 @@ import ( | |||
issue_indexer "code.gitea.io/gitea/modules/indexer/issues" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/markup/markdown" | |||
"code.gitea.io/gitea/modules/modelarts" | |||
"code.gitea.io/gitea/modules/setting" | |||
"code.gitea.io/gitea/modules/util" | |||
"code.gitea.io/gitea/routers/repo" | |||
cloudbrainService "code.gitea.io/gitea/services/cloudbrain" | |||
issue_service "code.gitea.io/gitea/services/issue" | |||
pull_service "code.gitea.io/gitea/services/pull" | |||
@@ -756,112 +753,7 @@ func Email2User(ctx *context.Context) { | |||
} | |||
func Cloudbrains(ctx *context.Context) { | |||
ctx.Data["Title"] = ctx.Tr("user.cloudbrains") | |||
listType := ctx.Query("listType") | |||
jobType := ctx.Query("jobType") | |||
jobStatus := ctx.Query("jobStatus") | |||
aiCenter := ctx.Query("aiCenter") | |||
cluster := ctx.Query("cluster") | |||
ctx.Data["ListType"] = listType | |||
ctx.Data["JobType"] = jobType | |||
ctx.Data["JobStatus"] = jobStatus | |||
ctx.Data["aiCenter"] = aiCenter | |||
ctx.Data["cluster"] = cluster | |||
page := ctx.QueryInt("page") | |||
if page <= 0 { | |||
page = 1 | |||
} | |||
var jobTypes []string | |||
jobTypeNot := false | |||
if jobType == string(models.JobTypeBenchmark) { | |||
jobTypes = models.AllBenchMarkJobType() | |||
} else if jobType != "all" && jobType != "" { | |||
jobTypes = append(jobTypes, jobType) | |||
} | |||
var jobStatuses []string | |||
jobStatusNot := false | |||
if jobStatus == "other" { | |||
jobStatusNot = true | |||
jobStatuses = append(jobStatuses, string(models.ModelArtsTrainJobWaiting), string(models.ModelArtsTrainJobFailed), string(models.ModelArtsRunning), string(models.ModelArtsTrainJobCompleted), | |||
string(models.ModelArtsStarting), string(models.ModelArtsRestarting), string(models.ModelArtsStartFailed), | |||
string(models.ModelArtsStopping), string(models.ModelArtsStopped), string(models.JobSucceeded)) | |||
} else if jobStatus != "all" && jobStatus != "" { | |||
jobStatuses = append(jobStatuses, jobStatus) | |||
} | |||
keyword := strings.Trim(ctx.Query("q"), " ") | |||
ctxUser := getDashboardContextUser(ctx) | |||
if ctx.Written() { | |||
return | |||
} | |||
repos, _, err := models.SearchRepository(&models.SearchRepoOptions{ | |||
Actor: ctx.User, | |||
OwnerID: ctxUser.ID, | |||
Private: true, | |||
}) | |||
if err != nil { | |||
ctx.ServerError("SearchRepository", err) | |||
return | |||
} | |||
var repoIDList []int64 | |||
for i, _ := range repos { | |||
repoIDList = append(repoIDList, repos[i].ID) | |||
} | |||
ciTasks, count, err := models.Cloudbrains(&models.CloudbrainsOptions{ | |||
ListOptions: models.ListOptions{ | |||
Page: page, | |||
PageSize: setting.UI.IssuePagingNum, | |||
}, | |||
Keyword: keyword, | |||
UserID: ctxUser.ID, | |||
JobTypeNot: jobTypeNot, | |||
JobStatusNot: jobStatusNot, | |||
JobStatus: jobStatuses, | |||
JobTypes: jobTypes, | |||
NeedRepoInfo: true, | |||
IsLatestVersion: modelarts.IsLatestVersion, | |||
RepoIDList: repoIDList, | |||
ComputeResource: listType, | |||
Type: models.TypeCloudBrainAll, | |||
AiCenter: aiCenter, | |||
Cluster: cluster, | |||
}) | |||
if err != nil { | |||
ctx.ServerError("Get job failed:", err) | |||
return | |||
} | |||
models.LoadSpecs4CloudbrainInfo(ciTasks) | |||
for i, _ := range ciTasks { | |||
ciTasks[i] = cloudbrainService.UpdateCloudbrainAiCenter(ciTasks[i]) | |||
ciTasks[i].Cloudbrain.AiCenter = repo.GetAiCenterNameByCode(ciTasks[i].Cloudbrain.AiCenter, ctx.Language()) | |||
ciTasks[i].CanDebug = true | |||
ciTasks[i].CanDel = true | |||
ciTasks[i].Cloudbrain.ComputeResource = ciTasks[i].ComputeResource | |||
if ciTasks[i].Cloudbrain.Spec != nil { | |||
if ciTasks[i].Cloudbrain.Type == models.TypeC2Net { | |||
ciTasks[i].Cloudbrain.Spec.Cluster = models.C2NetCluster | |||
} else { | |||
ciTasks[i].Cloudbrain.Spec.Cluster = models.OpenICluster | |||
} | |||
} | |||
} | |||
pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, getTotalPage(count, setting.UI.IssuePagingNum)) | |||
pager.SetDefaultParams(ctx) | |||
pager.AddParam(ctx, "listType", "ListType") | |||
ctx.Data["Page"] = pager | |||
ctx.Data["PageIsUserCloudBrain"] = true | |||
ctx.Data["Tasks"] = ciTasks | |||
ctx.Data["CanCreate"] = true | |||
ctx.Data["Keyword"] = keyword | |||
ctx.HTML(200, tplCloudbrains) | |||
} | |||
func getTotalPage(total int64, pageSize int) int { | |||
@@ -67,6 +67,25 @@ func (c C2NetClusterAdapter) CreateOnlineInfer(req entity.CreateNoteBookTaskRequ | |||
return convertGrampus2NoteBookRes(jobResult), nil | |||
} | |||
func (c C2NetClusterAdapter) CreateGeneralTask(req entity.CreateGeneralTaskRequest) (*entity.CreateGeneralTaskResponse, error) { | |||
log.Info("start to CreateGeneralTask req=%+v", req) | |||
newReq, err := convertGeneralTaskReq2Grampus(req) | |||
if err != nil { | |||
log.Error("CreateGeneralTask err.req=%+v err=%v", req, err) | |||
return nil, err | |||
} | |||
jobResult, err := grampus.CreateNotebookJob(newReq) | |||
if err != nil { | |||
log.Error("CreateGeneralTask failed: %v", err.Error()) | |||
return nil, err | |||
} | |||
if jobResult.ErrorCode > 0 { | |||
log.Error("CreateGeneralTask call grampus err.req.Name = %s ErrorCode = %d ErrorMsg = %s", req.Name, jobResult.ErrorCode, jobResult.ErrorMsg) | |||
return nil, errors.New(fmt.Sprintf("CreateGeneralTask err[%d%s]", jobResult.ErrorCode, jobResult.ErrorMsg)) | |||
} | |||
return convertGrampus2GeneralTaskRes(jobResult), nil | |||
} | |||
func (c C2NetClusterAdapter) GetNotebookImages(req entity.GetImageReq, centerId ...string) ([]entity.ClusterImage, bool, error) { | |||
processType := req.ComputeSource.FullName | |||
images, err := grampus.GetImages(processType, string(req.JobType)) | |||
@@ -166,6 +185,20 @@ func convertOnlineInfer2Grampus(req entity.CreateNoteBookTaskRequest) (models.Cr | |||
return models.CreateGrampusInferenceRequest{Name: req.Name, Tasks: tasks}, nil | |||
} | |||
func convertGeneralTaskReq2Grampus(req entity.CreateGeneralTaskRequest) (models.CreateGrampusNotebookRequest, error) { | |||
tasks := make([]models.GrampusNotebookTask, len(req.Tasks)) | |||
for i := 0; i < len(req.Tasks); i++ { | |||
t := req.Tasks[i] | |||
task, err := convertGeneralTask2Grampus(t) | |||
if err != nil { | |||
return models.CreateGrampusNotebookRequest{}, err | |||
} | |||
tasks[i] = task | |||
} | |||
return models.CreateGrampusNotebookRequest{Name: req.Name, Tasks: tasks}, nil | |||
} | |||
func generateCommand(repoName, bootFile, datasetName string) string { | |||
//prepare | |||
@@ -280,6 +313,37 @@ func convertNoteBookTask2Grampus(t entity.NoteBookTask, command string) (models. | |||
}, nil | |||
} | |||
func convertGeneralTask2Grampus(t entity.GeneralTask) (models.GrampusNotebookTask, error) { | |||
code := models.GrampusDataset{} | |||
codeArray := convertContainerArray2GrampusArray(t.Code) | |||
if codeArray != nil && len(codeArray) > 0 { | |||
code = codeArray[0] | |||
} | |||
output := models.GrampusDataset{} | |||
outputArray := convertContainerArray2GrampusArray(t.OutPut) | |||
if outputArray != nil && len(outputArray) > 0 { | |||
output = outputArray[0] | |||
} | |||
centerIds, err := getGrampusAvailableCenterIds(t.Queues, t.ImageId, *models.GetComputeSourceInstance(t.Spec.ComputeResource), models.JobTypeDebug) | |||
if err != nil { | |||
return models.GrampusNotebookTask{}, err | |||
} | |||
return models.GrampusNotebookTask{ | |||
Name: t.Name, | |||
ResourceSpecId: t.Spec.SourceSpecId, | |||
ImageId: t.ImageId, | |||
ImageUrl: t.ImageUrl, | |||
Datasets: convertContainerArray2GrampusArray(t.Datasets), | |||
PreTrainModel: convertContainerArray2GrampusArray(t.PreTrainModel), | |||
Code: code, | |||
OutPut: output, | |||
EnvVariables: t.EnvVariables, | |||
AutoStopDuration: t.AutoStopDuration, | |||
Capacity: t.Capacity, | |||
CenterID: centerIds, | |||
}, nil | |||
} | |||
func getGrampusAvailableCenterIds(queues []models.ResourceQueue, imageId string, computeSource models.ComputeSource, jobType models.JobType) ([]string, error) { | |||
if len(queues) == 0 { | |||
return []string{}, nil | |||
@@ -399,6 +463,22 @@ func convertGrampus2NoteBookRes(res *models.GrampusNotebookResponse) *entity.Cre | |||
} | |||
} | |||
func convertGrampus2GeneralTaskRes(res *models.GrampusNotebookResponse) *entity.CreateGeneralTaskResponse { | |||
jobInfo := res.JobInfo | |||
return &entity.CreateGeneralTaskResponse{ | |||
StartedAt: jobInfo.StartedAt, | |||
RunSec: jobInfo.RunSec, | |||
CompletedAt: jobInfo.CompletedAt, | |||
CreatedAt: jobInfo.CreatedAt, | |||
UpdatedAt: jobInfo.UpdatedAt, | |||
Desc: jobInfo.Desc, | |||
JobID: jobInfo.JobID, | |||
Name: jobInfo.Name, | |||
Status: jobInfo.Status, | |||
UserID: jobInfo.UserID, | |||
} | |||
} | |||
func (c C2NetClusterAdapter) RestartNoteBook(jobId string) (*entity.RestartNoteBookTaskResponse, error) { | |||
res, err := grampus.RestartNotebookJob(jobId) | |||
if err != nil { | |||
@@ -809,16 +889,11 @@ func (c C2NetClusterAdapter) GetResourceUsage(opts entity.ClusterResourceUsageOp | |||
nodeId := opts.NodeId | |||
jobId := opts.JobId | |||
if opts.ComputeSource == models.NPU { | |||
startTime = 0 | |||
endTime = 0 | |||
} else { | |||
if startTime == 0 { | |||
startTime = time.Now().Unix() - 30*60 | |||
} | |||
if endTime == 0 { | |||
endTime = time.Now().Unix() | |||
} | |||
if startTime == 0 { | |||
startTime = time.Now().Unix() - 30*60 | |||
} | |||
if endTime == 0 { | |||
endTime = time.Now().Unix() | |||
} | |||
var result models.NewModelArtsMetricStatisticResult | |||
if opts.WorkServerNumber <= 1 { | |||
@@ -827,7 +902,7 @@ func (c C2NetClusterAdapter) GetResourceUsage(opts entity.ClusterResourceUsageOp | |||
if nodeId > opts.WorkServerNumber-1 { | |||
return nil, response.PARAM_ERROR.ToError() | |||
} | |||
result, err = grampus.GetGrampusMetrics(opts.JobId, opts.StartTime, opts.EndTime, nodeId) | |||
result, err = grampus.GetGrampusMetrics(opts.JobId, startTime, endTime, nodeId) | |||
} | |||
if err != nil { | |||
@@ -37,6 +37,10 @@ func (c CloudbrainOneClusterAdapter) CreateOnlineInfer(req entity.CreateNoteBook | |||
return nil, nil | |||
} | |||
func (c CloudbrainOneClusterAdapter) CreateGeneralTask(req entity.CreateGeneralTaskRequest) (*entity.CreateGeneralTaskResponse, error) { | |||
return nil, nil | |||
} | |||
func (c CloudbrainOneClusterAdapter) GetNotebookImages(req entity.GetImageReq, centerId ...string) ([]entity.ClusterImage, bool, error) { | |||
return nil, true, nil | |||
} | |||
@@ -102,6 +102,10 @@ func (c CloudbrainTwoClusterAdapter) CreateOnlineInfer(req entity.CreateNoteBook | |||
return nil, nil | |||
} | |||
func (c CloudbrainTwoClusterAdapter) CreateGeneralTask(req entity.CreateGeneralTaskRequest) (*entity.CreateGeneralTaskResponse, error) { | |||
return nil, nil | |||
} | |||
var cloudbrainTwoNotebookImages []entity.ClusterImage | |||
func (c CloudbrainTwoClusterAdapter) GetNotebookImages(req entity.GetImageReq, centerId ...string) ([]entity.ClusterImage, bool, error) { | |||
@@ -51,4 +51,5 @@ type ClusterAdapter interface { | |||
GetNotebookImages(req entity.GetImageReq, centerId ...string) ([]entity.ClusterImage, bool, error) | |||
GetTrainImages(req entity.GetImageReq, centerId ...string) ([]entity.ClusterImage, bool, error) | |||
CreateOnlineInfer(req entity.CreateNoteBookTaskRequest) (*entity.CreateNoteBookTaskResponse, error) | |||
CreateGeneralTask(req entity.CreateGeneralTaskRequest) (*entity.CreateGeneralTaskResponse, error) | |||
} |
@@ -36,6 +36,7 @@ func GetCloudbrainOneNotebookConfig(opts entity.AITaskConfigKey) *entity.AITaskB | |||
DatasetsMaxNum: setting.MaxDatasetNum, | |||
ModelLimitSizeGB: setting.DEBUG_MODEL_SIZE_LIMIT_GB, | |||
ModelMaxNum: setting.DEBUG_MODEL_NUM_LIMIT, | |||
DebugAddressCheck: true, | |||
ContainerSteps: map[entity.ContainerDataType]*entity.ContainerBuildOpts{ | |||
entity.ContainerCode: { | |||
ContainerPath: "/code", | |||
@@ -75,6 +76,7 @@ func GetCloudbrainOneNotebookConfig(opts entity.AITaskConfigKey) *entity.AITaskB | |||
Uncompressed: true, | |||
}, | |||
}, | |||
DebugAddressCheck: true, | |||
} | |||
} | |||
@@ -0,0 +1,166 @@ | |||
package task | |||
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/modules/timeutil" | |||
"code.gitea.io/gitea/routers/response" | |||
"code.gitea.io/gitea/services/ai_task_service/context" | |||
) | |||
type GrampusGeneralTaskTemplate struct { | |||
DefaultAITaskTemplate | |||
} | |||
func init() { | |||
t := &GrampusGeneralTaskTemplate{ | |||
DefaultAITaskTemplate: DefaultAITaskTemplate{ | |||
ClusterType: entity.C2Net, | |||
JobType: models.JobTypeGeneral, | |||
Config: GetGeneralTaskConfig, | |||
}, | |||
} | |||
RegisterTask(models.JobTypeGeneral, entity.C2Net, t) | |||
} | |||
func GetGeneralTaskConfig(opts entity.AITaskConfigKey) *entity.AITaskBaseConfig { | |||
codePath := "/code" | |||
datasetPath := "/dataset" | |||
pretrainModelPath := "/pretrainmodel" | |||
config := &entity.AITaskBaseConfig{ | |||
ContainerSteps: map[entity.ContainerDataType]*entity.ContainerBuildOpts{ | |||
entity.ContainerCode: { | |||
ContainerPath: codePath, | |||
ReadOnly: false, | |||
AcceptStorageType: []entity.StorageType{entity.MINIO, entity.OBS}, | |||
VolumeFolder: true, | |||
}, | |||
entity.ContainerDataset: { | |||
ContainerPath: datasetPath, | |||
ReadOnly: true, | |||
AcceptStorageType: []entity.StorageType{entity.MINIO, entity.OBS}, | |||
}, | |||
entity.ContainerPreTrainModel: { | |||
ContainerPath: pretrainModelPath, | |||
ReadOnly: true, | |||
AcceptStorageType: []entity.StorageType{entity.MINIO, entity.OBS}, | |||
}, | |||
}, | |||
ActionType: models.ActionCreateGeneralGPUTask, | |||
DatasetsLimitSizeGB: setting.DebugAttachSize, | |||
DatasetsMaxNum: setting.MaxDatasetNum, | |||
ModelLimitSizeGB: setting.DEBUG_MODEL_SIZE_LIMIT_GB, | |||
ModelMaxNum: setting.DEBUG_MODEL_NUM_LIMIT, | |||
DebugAddressCheck: true, | |||
} | |||
return config | |||
} | |||
func (t GrampusGeneralTaskTemplate) Create(ctx *context.CreationContext) (*entity.CreateTaskRes, *response.BizError) { | |||
c := &CreateOperator{} | |||
err := c.Next(t.CheckParamFormat). | |||
Next(t.CheckMultiRequest). | |||
Next(t.CheckDisplayJobName). | |||
//Next(t.CheckNotebookCount). | |||
Next(t.LoadSpec). | |||
Next(t.CheckPointBalance). | |||
Next(t.CheckDatasets). | |||
Next(t.CheckBranchExists). | |||
Next(t.CheckModels). | |||
Next(t.InsertCloudbrainRecord4Async). | |||
AsyncNextWithErrFun(t.BuildContainerData, t.GetAvailableQueues, t.CallCreationAPI, t.AfterCallCreationAPI4Async, t.NotifyCreation, t.HandleErr4Async). | |||
Operate(ctx) | |||
if err != nil { | |||
log.Error("create GrampusNoteBookTask err.%v", err) | |||
return nil, err | |||
} | |||
return &entity.CreateTaskRes{ID: ctx.NewCloudbrain.ID}, nil | |||
} | |||
func (g GrampusGeneralTaskTemplate) CallCreationAPI(ctx *context.CreationContext) *response.BizError { | |||
c := g.GetMyCluster() | |||
if c == nil { | |||
log.Error("Get cluster failed") | |||
return response.SYSTEM_ERROR | |||
} | |||
form := ctx.Request | |||
imageUrl := strings.TrimSpace(form.ImageUrl) | |||
if form.ImageID != "" { | |||
imageUrl = "" | |||
} | |||
req := entity.CreateGeneralTaskRequest{ | |||
Name: form.JobName, | |||
Tasks: []entity.GeneralTask{ | |||
{ | |||
Name: form.JobName, | |||
ResourceSpecId: ctx.Spec.SourceSpecId, | |||
ImageId: form.ImageID, | |||
ImageUrl: imageUrl, | |||
Datasets: ctx.GetContainerDataArray(entity.ContainerDataset), | |||
PreTrainModel: ctx.GetContainerDataArray(entity.ContainerPreTrainModel), | |||
Code: ctx.GetContainerDataArray(entity.ContainerCode), | |||
EnvVariables: models.GrampusEnvVarReq{}, | |||
Capacity: setting.Capacity, | |||
Queues: ctx.Queues, | |||
Spec: ctx.Spec, | |||
}, | |||
}, | |||
} | |||
createTime := timeutil.TimeStampNow() | |||
res, err := c.CreateGeneralTask(req) | |||
if err != nil { | |||
log.Error("GrampusGeneralTaskTemplate CreateGeneralTask err.req=%+v err=%v", req, err) | |||
return response.NewBizError(err) | |||
} | |||
if res.JobID == "" { | |||
log.Error("GrampusGeneralTaskTemplate CreateGeneralTask failed.Cloudbrain.JobID=%s", ctx.SourceCloudbrain.JobID) | |||
return response.CREATE_FAILED | |||
} | |||
ctx.Response = &entity.CreationResponse{ | |||
JobID: res.JobID, | |||
Status: res.Status, | |||
CreateTime: createTime, | |||
} | |||
return nil | |||
} | |||
func (g GrampusGeneralTaskTemplate) GetImages(computeSource models.ComputeSource, centerId ...string) ([]entity.ClusterImage, bool, *response.BizError) { | |||
c := g.GetMyCluster() | |||
if c == nil { | |||
log.Error("Get cluster failed") | |||
return nil, false, response.SYSTEM_ERROR | |||
} | |||
var images []entity.ClusterImage | |||
var customFlag bool | |||
var err error | |||
images, customFlag, err = c.GetNotebookImages(entity.GetImageReq{ | |||
ComputeSource: computeSource, | |||
JobType: models.JobTypeDebug, | |||
}, centerId...) | |||
if err != nil { | |||
log.Error("GetImages err.computeSource=%s err =%v", computeSource.Name, err) | |||
return nil, false, response.NewBizError(err) | |||
} | |||
return images, customFlag, nil | |||
} | |||
func (g GrampusGeneralTaskTemplate) GetOperationProfile(cloudbrainId int64) (*entity.OperationProfile, *response.BizError) { | |||
c := g.GetMyCluster() | |||
if c == nil { | |||
log.Error("Get cluster failed,cloudbrainId=%d", cloudbrainId) | |||
return nil, response.SYSTEM_ERROR | |||
} | |||
s, err := GetOperationProfile(cloudbrainId, c.GetNoteBookOperationProfile) | |||
if err != nil { | |||
log.Error("GetOperationProfile err.cloudbrainId=%d err =%v", cloudbrainId, err) | |||
return nil, nil | |||
} | |||
return s, nil | |||
} |
@@ -2,6 +2,8 @@ package task | |||
import ( | |||
"errors" | |||
"net/http" | |||
"strings" | |||
"time" | |||
cloudbrainService "code.gitea.io/gitea/services/cloudbrain" | |||
@@ -175,6 +177,25 @@ func (g DefaultAITaskTemplate) GetAllowedWorkerNum(userId int64, computeSource * | |||
return []int{1}, nil | |||
} | |||
func (g DefaultAITaskTemplate) CheckDebugAddress(cloudbrain *models.Cloudbrain) bool { | |||
config := g.GetConfig(entity.AITaskConfigKey{ | |||
ComputeSource: cloudbrain.GetStandardComputeSource(), | |||
IsFileNoteBookRequest: cloudbrain.IsFileNoteBookTask(), | |||
}) | |||
if !config.DebugAddressCheck { | |||
return true | |||
} | |||
url, err := g.GetDebugUrl(cloudbrain.ID) | |||
if err != nil || url == "" { | |||
return false | |||
} | |||
res, httpErr := http.Get(url) | |||
if httpErr != nil || res.StatusCode != http.StatusOK { | |||
return false | |||
} | |||
return true | |||
} | |||
func (g DefaultAITaskTemplate) Query(cloudbrainId int64) (*entity.AITaskDetailInfo, *response.BizError) { | |||
//查询时先更新,然后再查询本地数据 | |||
g.Update(cloudbrainId) | |||
@@ -307,14 +328,35 @@ func (g DefaultAITaskTemplate) Update(cloudbrainId int64) *response.BizError { | |||
log.Info("AI task is preparing.No need to update from remote.cloudbrainId=%d", cloudbrainId) | |||
return nil | |||
} | |||
//查询任务在集群上的状态 | |||
log.Info("start to UpdateAITaskFromRemote.task.DisplayJobName = %s task.Status = %s", cloudbrain.DisplayJobName, cloudbrain.Status) | |||
var res *entity.QueryTaskResponse | |||
if g.JobType == models.JobTypeDebug || g.JobType == models.JobTypeOnlineInference { | |||
err = UpdateAITaskFromRemote(cloudbrain, c.QueryNoteBook) | |||
res, err = c.QueryNoteBook(entity.JobIdAndVersionId{JobID: cloudbrain.JobID, VersionID: cloudbrain.VersionID}) | |||
} else { | |||
err = UpdateAITaskFromRemote(cloudbrain, c.QueryTrainJob) | |||
res, err = c.QueryTrainJob(entity.JobIdAndVersionId{JobID: cloudbrain.JobID, VersionID: cloudbrain.VersionID}) | |||
} | |||
log.Info("remoteQueryFunc task.DisplayJobName = %s res = %+v ", cloudbrain.DisplayJobName, res) | |||
if err != nil { | |||
log.Error("query from remote err.cloudbrainID = %d err=%v", cloudbrain.ID, err) | |||
return response.NewBizError(err) | |||
} | |||
if res == nil || res.JobId == "" { | |||
log.Error("query from remote failed,response is empty,cloudbrainID = %d ", cloudbrain.ID) | |||
return response.NewBizError(errors.New("response is empty")) | |||
} | |||
if strings.ToUpper(res.Status) == string(models.JobRunning) && strings.ToUpper(cloudbrain.Status) == string(models.JobWaiting) { | |||
if !g.CheckDebugAddress(cloudbrain) { | |||
log.Error("check debug address failed.cloudbrain.id = %d", cloudbrain.ID) | |||
return nil | |||
} | |||
} | |||
err = UpdateByQueryResponse(res, cloudbrain) | |||
if err != nil { | |||
log.Error("UpdateAITaskFromRemote err.cloudbrainId=%d err=%v", cloudbrainId, err) | |||
log.Error("UpdateByQueryResponse err.cloudbrainId=%d err=%v", cloudbrainId, err) | |||
return response.NewBizError(err) | |||
} | |||
log.Info("updateTask success.cloudbrainId=%d", cloudbrainId) | |||
@@ -8,7 +8,7 @@ import ( | |||
"code.gitea.io/gitea/routers/response" | |||
) | |||
func GetAITaskList(req entity.GetTaskListReq) (*entity.AITaskListRes, *response.BizError) { | |||
func GetRepoAITaskList(req entity.GetTaskListReq) (*entity.AITaskListRes, *response.BizError) { | |||
page := req.Page | |||
if page <= 0 { | |||
page = 1 | |||
@@ -34,7 +34,7 @@ func GetAITaskList(req entity.GetTaskListReq) (*entity.AITaskListRes, *response. | |||
for i := 0; i < len(tasks); i++ { | |||
r[i] = &entity.AITaskInfo4List{ | |||
Task: entity.ConvertCloudbrainToAITaskBriefInfo(&tasks[i].Cloudbrain), | |||
Task: entity.ConvertCloudbrainToAITaskBriefInfo(&tasks[i].Cloudbrain).ClearNonPublicFields(), | |||
Creator: *entity.ConvertUserToBrief(&tasks[i].User), | |||
CanModify: tasks[i].CanUserModify(req.Operator), | |||
CanDelete: tasks[i].CanUserDelete(req.Operator, req.IsRepoOwner), | |||
@@ -48,3 +48,156 @@ func GetAITaskList(req entity.GetTaskListReq) (*entity.AITaskListRes, *response. | |||
Page: page, | |||
}, nil | |||
} | |||
func GetMyAITaskList(req entity.GetMyTaskListReq) (*entity.AITaskListRes, *response.BizError) { | |||
var jobTypes []string | |||
jobTypeNot := false | |||
if req.JobType == string(models.JobTypeBenchmark) { | |||
jobTypes = models.AllBenchMarkJobType() | |||
} else if req.JobType != "all" && req.JobType != "" { | |||
jobTypes = append(jobTypes, req.JobType) | |||
} | |||
var jobStatuses []string | |||
jobStatusNot := false | |||
if req.JobStatus == "other" { | |||
jobStatusNot = true | |||
jobStatuses = append(jobStatuses, req.ExcludeStatus...) | |||
} else if req.JobStatus != "all" && req.JobStatus != "" { | |||
jobStatuses = append(jobStatuses, req.JobStatus) | |||
} | |||
repos, _, err := models.SearchRepository(&models.SearchRepoOptions{ | |||
Actor: req.User, | |||
OwnerID: req.User.ID, | |||
Private: true, | |||
}) | |||
if err != nil { | |||
return nil, response.NewBizError(err) | |||
} | |||
var repoIDList []int64 | |||
for i, _ := range repos { | |||
repoIDList = append(repoIDList, repos[i].ID) | |||
} | |||
computeSourceName := "" | |||
if req.ComputeSource != nil { | |||
computeSourceName = req.ComputeSource.GetCloudbrainFormat() | |||
} | |||
tasks, count, err := models.Cloudbrains(&models.CloudbrainsOptions{ | |||
ListOptions: models.ListOptions{ | |||
Page: req.Page, | |||
PageSize: req.PageSize, | |||
}, | |||
Keyword: req.Keyword, | |||
UserID: req.User.ID, | |||
JobTypeNot: jobTypeNot, | |||
JobStatusNot: jobStatusNot, | |||
JobStatus: jobStatuses, | |||
JobTypes: jobTypes, | |||
NeedRepoInfo: true, | |||
IsLatestVersion: modelarts.IsLatestVersion, | |||
RepoIDList: repoIDList, | |||
ComputeResource: computeSourceName, | |||
Type: models.TypeCloudBrainAll, | |||
AiCenter: req.AICenter, | |||
Cluster: req.Cluster, | |||
}) | |||
if err != nil { | |||
log.Error("GetMyAITaskList query cloudbrains err. req=%+v,err=%v", req, err) | |||
return nil, response.NewBizError(err) | |||
} | |||
models.LoadSpecs4CloudbrainInfo(tasks) | |||
r := make([]*entity.AITaskInfo4List, len(tasks)) | |||
for i := 0; i < len(tasks); i++ { | |||
r[i] = &entity.AITaskInfo4List{ | |||
Task: entity.ConvertCloudbrainToAITaskBriefInfo(&tasks[i].Cloudbrain).ClearNonPublicFields(), | |||
CanModify: tasks[i].CanUserModify(req.User), | |||
CanDelete: tasks[i].CanUserDelete(req.User, req.IsRepoOwner), | |||
RepoName: tasks[i].Repo.Name, | |||
OwnerName: tasks[i].Repo.OwnerName, | |||
} | |||
} | |||
return &entity.AITaskListRes{ | |||
Tasks: r, | |||
Total: count, | |||
PageSize: req.PageSize, | |||
Page: req.Page, | |||
}, nil | |||
} | |||
func GetAITaskList4Admin(req entity.GetMyTaskListReq) (*entity.AITaskListRes, *response.BizError) { | |||
var jobTypes []string | |||
jobTypeNot := false | |||
if req.JobType == string(models.JobTypeBenchmark) { | |||
jobTypes = models.AllBenchMarkJobType() | |||
} else if req.JobType != "all" && req.JobType != "" { | |||
jobTypes = append(jobTypes, req.JobType) | |||
} | |||
var jobStatuses []string | |||
jobStatusNot := false | |||
if req.JobStatus == "other" { | |||
jobStatusNot = true | |||
jobStatuses = append(jobStatuses, req.ExcludeStatus...) | |||
} else if req.JobStatus != "all" && req.JobStatus != "" { | |||
jobStatuses = append(jobStatuses, req.JobStatus) | |||
} | |||
computeSourceName := "" | |||
if req.ComputeSource != nil { | |||
computeSourceName = req.ComputeSource.GetCloudbrainFormat() | |||
} | |||
tasks, count, err := models.Cloudbrains(&models.CloudbrainsOptions{ | |||
ListOptions: models.ListOptions{ | |||
Page: req.Page, | |||
PageSize: req.PageSize, | |||
}, | |||
Keyword: req.Keyword, | |||
JobTypeNot: jobTypeNot, | |||
JobStatusNot: jobStatusNot, | |||
JobStatus: jobStatuses, | |||
JobTypes: jobTypes, | |||
NeedRepoInfo: true, | |||
IsLatestVersion: modelarts.IsLatestVersion, | |||
ComputeResource: computeSourceName, | |||
Type: models.TypeCloudBrainAll, | |||
AiCenter: req.AICenter, | |||
Cluster: req.Cluster, | |||
}) | |||
if err != nil { | |||
log.Error("GetMyAITaskList query cloudbrains err. req=%+v,err=%v", req, err) | |||
return nil, response.NewBizError(err) | |||
} | |||
models.LoadSpecs4CloudbrainInfo(tasks) | |||
r := make([]*entity.AITaskInfo4List, len(tasks)) | |||
for i := 0; i < len(tasks); i++ { | |||
var repoName, ownerName string | |||
if tasks[i].Repo != nil { | |||
repoName = tasks[i].Repo.Name | |||
ownerName = tasks[i].Repo.OwnerName | |||
} | |||
creator := entity.UserBriefInfo{} | |||
if tasks[i].User.ID > 0 { | |||
creator = *entity.ConvertUserToBrief(&tasks[i].User) | |||
} | |||
r[i] = &entity.AITaskInfo4List{ | |||
Task: entity.ConvertCloudbrainToAITaskBriefInfo(&tasks[i].Cloudbrain), | |||
Creator: creator, | |||
CanModify: true, | |||
CanDelete: true, | |||
RepoName: repoName, | |||
OwnerName: ownerName, | |||
} | |||
} | |||
return &entity.AITaskListRes{ | |||
Tasks: r, | |||
Total: count, | |||
PageSize: req.PageSize, | |||
Page: req.Page, | |||
}, nil | |||
} |
@@ -7,6 +7,8 @@ import ( | |||
"code.gitea.io/gitea/modules/git" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/notification" | |||
"code.gitea.io/gitea/modules/redis/redis_key" | |||
"code.gitea.io/gitea/modules/redis/redis_lock" | |||
"code.gitea.io/gitea/modules/setting" | |||
"code.gitea.io/gitea/modules/storage" | |||
"code.gitea.io/gitea/routers/response" | |||
@@ -24,6 +26,7 @@ import ( | |||
"path" | |||
"strconv" | |||
"strings" | |||
"time" | |||
) | |||
type QueryFunc func(opts entity.JobIdAndVersionId) (*entity.QueryTaskResponse, error) | |||
@@ -212,28 +215,10 @@ func QueryTaskBriefInfo(id int64) (*entity.AITaskBriefInfo, error) { | |||
log.Error("QueryTaskBriefInfo GetCloudbrainByCloudbrainID err.id=%d err=%v", id, err) | |||
return nil, err | |||
} | |||
task.LoadSpec() | |||
return entity.ConvertCloudbrainToAITaskBriefInfo(task), nil | |||
} | |||
func UpdateAITaskFromRemote(task *models.Cloudbrain, remoteFunc QueryFunc) error { | |||
log.Info("start to UpdateAITaskFromRemote.task.DisplayJobName = %s task.Status = %s", task.DisplayJobName, task.Status) | |||
res, err := remoteFunc(entity.JobIdAndVersionId{JobID: task.JobID, VersionID: task.VersionID}) | |||
log.Info("remoteQueryFunc task.DisplayJobName = %s res = %+v ", task.DisplayJobName, res) | |||
if err != nil { | |||
log.Error("query from remote err.cloudbrainID = %d err=%v", task.ID, err) | |||
return err | |||
} | |||
if res == nil { | |||
log.Error("query from remote failed,response is empty,cloudbrainID = %d ", task.ID) | |||
return errors.New("response is empty") | |||
} | |||
if res.JobId == "" { | |||
log.Error("query from remote failed,response jobId is empty,cloudbrainID = %d ", task.ID) | |||
return nil | |||
} | |||
return UpdateByQueryResponse(res, task) | |||
} | |||
func StopAITaskByJobNameFromRemote(task *models.Cloudbrain, queryFunc QueryListFunc, stopFunc StopFunc) error { | |||
if task.IsTerminal() { | |||
return nil | |||
@@ -508,13 +493,16 @@ func QueryNoteBookUrl(id int64, getNoteBookUrl GetNotebookUrlFunc, fileName stri | |||
if err != nil { | |||
return "", err | |||
} | |||
if !cloudbrain.IsRunning() { | |||
return "", errors.New("AI task is not running") | |||
if cloudbrain.JobID == "" { | |||
return "", errors.New("JobID is empty") | |||
} | |||
url, err := getNoteBookUrl(cloudbrain.JobID) | |||
if err != nil { | |||
return "", err | |||
} | |||
if url == "" { | |||
return "", nil | |||
} | |||
if fileName != "" { | |||
url = transferFileNotebookUrl(url, fileName) | |||
} | |||
@@ -897,3 +885,40 @@ func ClearNotebook() { | |||
} | |||
} | |||
func TryToNotifyLongRunningTask(cloudbrain *models.Cloudbrain) { | |||
startTimestamp := int64(cloudbrain.StartTime) | |||
if setting.CloudbrainLongRunningNotifyInterval == 0 || startTimestamp == 0 { | |||
return | |||
} | |||
currentTimestamp := time.Now().Unix() | |||
matchIndex := 0 | |||
i := 1 | |||
for { | |||
duration := time.Duration(i) * setting.CloudbrainLongRunningNotifyInterval | |||
s := int64(duration.Seconds()) | |||
if currentTimestamp-startTimestamp < s { | |||
matchIndex = i - 1 | |||
break | |||
} | |||
i++ | |||
} | |||
if matchIndex <= 0 { | |||
return | |||
} | |||
d := time.Duration(matchIndex) * setting.CloudbrainLongRunningNotifyInterval | |||
if hasLongRunningNotificationSendBefore(cloudbrain, d) { | |||
return | |||
} | |||
notification.NotifyLongRunningAITask(cloudbrain, d) | |||
} | |||
func hasLongRunningNotificationSendBefore(cloudbrain *models.Cloudbrain, duration time.Duration) bool { | |||
key := redis_key.LongRunningNotificationKey(cloudbrain, duration) | |||
lock := redis_lock.NewDistributeLock(key) | |||
success, err := lock.Lock(duration + 1*time.Hour) | |||
if err != nil { | |||
return true | |||
} | |||
return !success | |||
} |
@@ -45,20 +45,24 @@ func DisagreeRequest(cardReq api.CardReq) error { | |||
func UpdateCardRequestAdmin(cardReq api.CardReq) error { | |||
request := models.CardRequest{ | |||
ID: cardReq.ID, | |||
ComputeResource: cardReq.ComputeResource, | |||
CardType: cardReq.CardType, | |||
AccCardsNum: cardReq.AccCardsNum, | |||
EmailAddress: cardReq.EmailAddress, | |||
DiskCapacity: cardReq.DiskCapacity, | |||
Contact: cardReq.Contact, | |||
PhoneNumber: cardReq.PhoneNumber, | |||
Wechat: cardReq.Wechat, | |||
BeginDate: cardReq.BeginDate, | |||
EndDate: cardReq.EndDate, | |||
Description: cardReq.Description, | |||
Org: cardReq.Org, | |||
ResourceType: cardReq.ResourceType, | |||
ID: cardReq.ID, | |||
ComputeResource: cardReq.ComputeResource, | |||
CardType: cardReq.CardType, | |||
AccCardsNum: cardReq.AccCardsNum, | |||
EmailAddress: cardReq.EmailAddress, | |||
DiskCapacity: cardReq.DiskCapacity, | |||
Contact: cardReq.Contact, | |||
PhoneNumber: cardReq.PhoneNumber, | |||
Wechat: cardReq.Wechat, | |||
IsResearchProject: cardReq.IsResearchProject, | |||
InstitutionName: cardReq.InstitutionName, | |||
ProjectName: cardReq.ProjectName, | |||
ProjectCode: cardReq.ProjectCode, | |||
BeginDate: cardReq.BeginDate, | |||
EndDate: cardReq.EndDate, | |||
Description: cardReq.Description, | |||
Org: cardReq.Org, | |||
ResourceType: cardReq.ResourceType, | |||
} | |||
beginTime, err := time.Parse(DATE_LAYOUT, cardReq.BeginDate) | |||
if err != nil { | |||
@@ -93,6 +97,10 @@ func UpdateCardRequest(cardReq api.CardReq, request *models.CardRequest) error { | |||
request.EmailAddress = cardReq.EmailAddress | |||
request.PhoneNumber = cardReq.PhoneNumber | |||
request.Wechat = cardReq.Wechat | |||
request.IsResearchProject = cardReq.IsResearchProject | |||
request.InstitutionName = cardReq.InstitutionName | |||
request.ProjectName = cardReq.ProjectName | |||
request.ProjectCode = cardReq.ProjectCode | |||
beginTime, err := time.Parse(DATE_LAYOUT, cardReq.BeginDate) | |||
if err != nil { | |||
@@ -115,21 +123,25 @@ func UpdateCardRequest(cardReq api.CardReq, request *models.CardRequest) error { | |||
func CreateCardRequest(cardReq api.CardReq, uid int64) error { | |||
bean := &models.CardRequest{ | |||
UID: uid, | |||
ComputeResource: cardReq.ComputeResource, | |||
CardType: cardReq.CardType, | |||
AccCardsNum: cardReq.AccCardsNum, | |||
EmailAddress: cardReq.EmailAddress, | |||
DiskCapacity: cardReq.DiskCapacity, | |||
Contact: cardReq.Contact, | |||
PhoneNumber: cardReq.PhoneNumber, | |||
Wechat: cardReq.Wechat, | |||
BeginDate: cardReq.BeginDate, | |||
EndDate: cardReq.EndDate, | |||
Description: cardReq.Description, | |||
Org: cardReq.Org, | |||
ResourceType: cardReq.ResourceType, | |||
Status: models.CARD_REQUEST_COMMIT, | |||
UID: uid, | |||
ComputeResource: cardReq.ComputeResource, | |||
CardType: cardReq.CardType, | |||
AccCardsNum: cardReq.AccCardsNum, | |||
EmailAddress: cardReq.EmailAddress, | |||
DiskCapacity: cardReq.DiskCapacity, | |||
Contact: cardReq.Contact, | |||
PhoneNumber: cardReq.PhoneNumber, | |||
Wechat: cardReq.Wechat, | |||
IsResearchProject: cardReq.IsResearchProject, | |||
InstitutionName: cardReq.InstitutionName, | |||
ProjectName: cardReq.ProjectName, | |||
ProjectCode: cardReq.ProjectCode, | |||
BeginDate: cardReq.BeginDate, | |||
EndDate: cardReq.EndDate, | |||
Description: cardReq.Description, | |||
Org: cardReq.Org, | |||
ResourceType: cardReq.ResourceType, | |||
Status: models.CARD_REQUEST_COMMIT, | |||
} | |||
beginTime, err := time.Parse(DATE_LAYOUT, cardReq.BeginDate) | |||
@@ -60,7 +60,9 @@ func filterGrampusImage(all []models.GrampusImage) []models.GrampusImage { | |||
result := make([]models.GrampusImage, 0) | |||
for _, tmp := range all { | |||
computeResource := getComputeResourceByProcessType(tmp.ProcessorType) | |||
if computeResource == "GCU" || computeResource == "MLU" || computeResource == "ILUVATAR-GPGPU" || computeResource == "METAX-GPGPU" { | |||
if computeResource == "GCU" || computeResource == "MLU" || | |||
computeResource == "ILUVATAR-GPGPU" || computeResource == "METAX-GPGPU" || | |||
computeResource == "GPU" { | |||
result = append(result, tmp) | |||
} | |||
} | |||
@@ -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, 46, 47, 48, 49, 50, 51, 53} | |||
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, 47, 48, 49, 50, 51, 53, 54} | |||
type ClientsManager struct { | |||
Clients *orderedmap.OrderedMap | |||
@@ -1,579 +1,10 @@ | |||
{{template "base/head" .}} | |||
<script src="{{StaticUrlPrefix}}/js/specsuse.js?v={{MD5 AppVer}}" type="text/javascript"></script> | |||
<!-- 弹窗 --> | |||
<div id="mask"> | |||
<div id="loadingPage"> | |||
<div class="rect1"></div> | |||
<div class="rect2"></div> | |||
<div class="rect3"></div> | |||
<div class="rect4"></div> | |||
<div class="rect5"></div> | |||
</div> | |||
</div> | |||
<!-- 提示框 --> | |||
<div class="alert"></div> | |||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/vp-cloudbrain-tasks.css?v={{MD5 AppVer}}" /> | |||
<div class="admin user"> | |||
<div class="cloudbrain_debug" style="display: none;" data-debug="{{$.i18n.Tr "repo.debug"}}" | |||
data-debug-again="{{$.i18n.Tr "repo.debug_again"}}" | |||
data-all-cluster="{{.i18n.Tr "cloudbrain.all_resource_cluster"}}" | |||
data-all-aiCenter="{{.i18n.Tr "cloudbrain.all_ai_center"}}" | |||
data-cluster-c2net="{{.i18n.Tr "cloudbrain.resource_cluster_c2net"}}" | |||
data-cluster-openi="{{.i18n.Tr "cloudbrain.resource_cluster_openi"}}" | |||
data-all-task="{{.i18n.Tr "admin.cloudbrain.all_task_types"}}" | |||
data-all-compute="{{.i18n.Tr "admin.cloudbrain.all_computing_resources"}}" | |||
data-all-status="{{.i18n.Tr "admin.cloudbrain.all_status"}}"></div> | |||
{{template "admin/navbar" .}} | |||
<div class="ui container"> | |||
{{template "base/alert" .}} | |||
<div class="ui grid" style="margin:0"> | |||
<div class="row" style="border: 1px solid #d4d4d5;margin-top: 0px;padding-top: 0;"> | |||
{{template "admin/cloudbrain/search" .}} | |||
<div class="ui six wide column right aligned" style="margin: 1rem 0;"> | |||
<a class="ui compact blue basic icon button" style="box-shadow: none !important; padding: 0.8em;" | |||
href="/admin/cloudbrains/download"><i | |||
class="ri-download-line middle aligned icon"></i>{{.i18n.Tr "admin.cloudbrain.download_report"}}</a> | |||
</div> | |||
<div class="ui sixteen wide column" style="overflow-x:auto;"> | |||
<!-- 任务展示 --> | |||
<div class="dataset list" style="min-width:2100px;margin-top:15px;margin-bottom:15px;"> | |||
<!-- 表头 --> | |||
<div class="ui grid stackable" style="background: #f0f0f0;;"> | |||
<div class="row"> | |||
<div class="two wide column nowrap" style="width:10% !important;"> | |||
<span>{{$.i18n.Tr "repo.cloudbrain_task"}}</span> | |||
</div> | |||
<!-- 集群 --> | |||
<div class="one wide column text center nowrap" style="width:6% !important;"> | |||
<span>{{$.i18n.Tr "repo.modelarts.cluster"}}</span> | |||
</div> | |||
<div class="two wide column text center nowrap" style="width: 8% !important;"> | |||
<span>{{$.i18n.Tr "repo.modelarts.status"}}</span> | |||
</div> | |||
<div class="one wide column text center nowrap" style="width:6% !important;"> | |||
<span>{{$.i18n.Tr "repo.cloudbrain_task_type"}}</span> | |||
</div> | |||
<div class="two wide column text center nowrap" style="width: 8% !important;"> | |||
<span>{{$.i18n.Tr "repo.modelarts.createtime"}}</span> | |||
</div> | |||
<div class="one wide column text center nowrap" style="width: 5% !important;"> | |||
<span>{{$.i18n.Tr "repo.cloudbrain_status_runtime"}}</span> | |||
</div> | |||
<div class="one wide column text center nowrap" style="width: 5% !important;"> | |||
<span>{{$.i18n.Tr "repo.modelarts.computing_resources"}}</span> | |||
</div> | |||
<!-- 智算中心 --> | |||
<div class="one wide column text center nowrap" style="width:7% !important;"> | |||
<span>{{$.i18n.Tr "repo.modelarts.ai_center"}}</span> | |||
</div> | |||
<!-- XPU类型 --> | |||
<div class="one wide column text center nowrap" style="width:7% !important;"> | |||
<span>{{$.i18n.Tr "repo.modelarts.card_type"}}</span> | |||
</div> | |||
<div class="one wide column text center nowrap" style="width:4% !important;"> | |||
<span>{{$.i18n.Tr "repo.cloudbrain_creator"}}</span> | |||
</div> | |||
<div class="two wide column text center nowrap" style="width:10% !important;"> | |||
<span>{{$.i18n.Tr "repository"}}</span> | |||
</div> | |||
<div class="two wide column text center nowrap" style="width:10% !important;"> | |||
<span>{{.i18n.Tr "admin.cloudbrain.cloudbrain_name"}}</span> | |||
</div> | |||
<div class="two wide column text center nowrap" style="width: 12%!important;"> | |||
<span>{{$.i18n.Tr "repo.cloudbrain_operate"}}</span> | |||
</div> | |||
</div> | |||
</div> | |||
{{range .Tasks}} | |||
{{if .Repo}} | |||
<div class="ui grid stackable item"> | |||
<div class="row"> | |||
<!-- 任务名 --> | |||
{{$JobID := '0'}} | |||
{{if eq .JobType "DEBUG" "TRAIN" "INFERENCE" "HPC" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK" "MODELSAFETY" "SNN4ECOSET" "SIM2BRAIN_SNN" "ONLINEINFERENCE"}} | |||
{{$JobID = .Cloudbrain.ID}} | |||
{{else}} | |||
{{$JobID = .JobID}} | |||
{{end}} | |||
<!-- {{$JobID}} --> | |||
<div class="two wide column nowrap" style="width:10% !important;"> | |||
{{if eq .JobType "DEBUG"}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}/{{$JobID}}" | |||
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "HPC"}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/supercompute/job/{{$JobID}}" | |||
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE") (eq .JobType "SNN4ECOSET") (eq .JobType "SIM2BRAIN_SNN")}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/cloudbrain/benchmark/{{$JobID}}" | |||
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "INFERENCE"}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/{{if eq .Cloudbrain.Type 2}}grampus{{else if eq .Cloudbrain.Type 1}}modelarts{{else if eq .Cloudbrain.Type 0}}cloudbrain{{end}}/inference-job/{{$JobID}}" | |||
title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "TRAIN"}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 0}}/cloudbrain{{else if eq .Cloudbrain.Type 1}}/modelarts{{else if eq .Cloudbrain.Type 2}}/grampus{{end}}/train-job/{{$JobID}}" | |||
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "BENCHMARK" "MODELSAFETY"}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/cloudbrain/benchmark/{{$JobID}}" | |||
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "ONLINEINFERENCE"}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/grampus/onlineinfer/{{$JobID}}" | |||
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{end}} | |||
</div> | |||
<!-- 集群 --> | |||
<div class="one wide column text center nowrap" style="width:6% !important;"> | |||
<span style="font-size: 12px;" class="cluster_{{.DisplayJobName}}_{{$JobID}}">{{if .Cluster}}{{.Cluster}}{{else}}--{{end}}</span> | |||
</div> | |||
<!-- 任务状态 --> | |||
<div class="two wide column text center nowrap" | |||
style="width: 8% !important;"> | |||
<span class="job-status" id="{{$JobID}}" | |||
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG" "ONLINEINFERENCE" "HPC"}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}{{else if eq .JobType "INFERENCE"}}/modelarts/train-job{{else if eq .JobType "TRAIN"}}/modelarts/train-job{{else if eq .JobType "BENCHMARK" "MODELSAFETY"}}/cloudbrain{{end}}' | |||
data-jobid="{{$JobID}}" data-version="{{.VersionName}}" | |||
data-cloudbrainid="{{.Cloudbrain.ID}}" data-datamigrate='{{$.i18n.Tr "repo.migratingData"}}' data-centerpend='{{$.i18n.Tr "repo.centerPending"}}'> | |||
<span> | |||
<i id="{{$JobID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i> | |||
<span id="{{$JobID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span> | |||
{{if eq .Status "WAITING"}}<i id="{{$JobID}}-icon-detail" class="{{.DetailedStatus}}" style="vertical-align: middle;" title='{{$.i18n.Tr (printf "repo.%s" .DetailedStatus)}}'></i>{{end}} | |||
</span> | |||
</span> | |||
</div> | |||
<!-- 任务类型 --> | |||
<div class="one wide column text center nowrap" style="width: 6% !important;"> | |||
<span style="font-size: 12px;">{{.JobType}} </span> | |||
</div> | |||
<!-- 任务创建时间 --> | |||
<div class="two wide column text center nowrap" style="width: 8% !important;"> | |||
<span style="font-size: 12px;" | |||
class="">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span> | |||
</div> | |||
<!-- 任务运行时间 --> | |||
<div class="one wide column text center nowrap" style="width: 5% !important;"> | |||
<span style="font-size: 12px;" | |||
id="duration-{{$JobID}}">{{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}}</span> | |||
</div> | |||
<!-- 计算资源 --> | |||
<div class="one wide column text center nowrap" style="width: 5% !important;"> | |||
<span | |||
style="font-size: 12px;" title="{{.ComputeResource}}">{{if .ComputeResource}}{{.ComputeResource}}{{else}}--{{end}}</span> | |||
</div> | |||
<!-- 智算中心 --> | |||
<div class="one wide column text center nowrap" style="width:7% !important;"> | |||
<span style="font-size: 12px;" id="cluster-{{$JobID}}" class="aicenter_{{.DisplayJobName}}_{{$JobID}}" title="{{if .AiCenter}}{{.AiCenter}}{{else}}--{{end}}">{{if .AiCenter}}{{.AiCenter}}{{else}}--{{end}}</span> | |||
</div> | |||
<!-- XPU类型 --> | |||
<div class="one wide column text center nowrap" style="width:7% !important;"> | |||
<span style="font-size: 12px;" title="" class="card_type_{{.DisplayJobName}}_{{$JobID}}"></span> | |||
</div> | |||
<script> | |||
(function(){ | |||
var spec = {{.Spec}} || {}; | |||
var cardType = getListValueWithKey(ACC_CARD_TYPE, spec.AccCardType) || '--'; | |||
var spanEl = document.querySelector('.card_type_{{.DisplayJobName}}_{{$JobID}}'); | |||
spanEl.setAttribute('title', cardType); | |||
spanEl.innerText = cardType; | |||
var cluster = {{.Cluster}} || '--'; | |||
var clusterName = document.querySelector('.cloudbrain_debug').dataset['cluster' + cluster[0] + cluster.toLocaleLowerCase().slice(1)] || '--'; | |||
spanEl = document.querySelector('.cluster_{{.DisplayJobName}}_{{$JobID}}'); | |||
spanEl.setAttribute('title', cluster); | |||
spanEl.innerText = clusterName; | |||
// var aiCenter = spec.AiCenterName || '--'; | |||
// spanEl = document.querySelector('.aicenter_{{.DisplayJobName}}_{{$JobID}}'); | |||
// spanEl.setAttribute('title', aiCenter); | |||
// spanEl.innerText = aiCenter; | |||
})(); | |||
</script> | |||
<!-- 创建者 --> | |||
<div class="one wide column text center nowrap" style="width:4% !important;"> | |||
{{if .User.Name}} | |||
<a href="{{AppSubUrl}}/{{.User.Name}}" title="{{.User.Name}}"><img | |||
class="ui avatar image" src="{{.User.RelAvatarLink}}"></a> | |||
{{else}} | |||
<a title="Ghost"><img class="ui avatar image" | |||
src="{{AppSubUrl}}/user/avatar/Ghost/-1"></a> | |||
{{end}} | |||
</div> | |||
<!-- 项目 --> | |||
<div class="two wide column text center nowrap" style="width:10% !important;"> | |||
<a href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}" | |||
title="{{.Repo.OwnerName}}/{{.Repo.Alias}}">{{.Repo.OwnerName}}/{{.Repo.Alias}}</a> | |||
</div> | |||
<!-- 云脑侧名称 --> | |||
<div class="two wide column text center nowrap" | |||
style="overflow: hidden;text-overflow:ellipsis;width:10% !important;"> | |||
<span class="ui poping up clipboard" data-position="top center" id="clipboard-btn-{{.JobName}}" style="cursor:pointer" | |||
data-clipboard-text="{{.JobName}}" | |||
data-original="{{$.i18n.Tr "repo.copy"}}" | |||
data-success="{{$.i18n.Tr "repo.copied"}}" | |||
data-error="{{$.i18n.Tr "repo.copied_error"}}" | |||
data-content="{{$.i18n.Tr "repo.copy"}}" | |||
data-variation="inverted tiny" | |||
> | |||
<span class="fitted" title="{{.JobName}}">{{.JobName}}</span> | |||
</span> | |||
</div> | |||
<div class="two wide column text center nowrap" style="width: 14%!important;"> | |||
{{if eq .JobType "DEBUG"}} | |||
<div class="ui compact buttons"> | |||
<form id="debugAgainForm-{{$JobID}}"> | |||
{{$.CsrfTokenHtml}} | |||
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}} | |||
<a style="margin: 0 1rem;" id="ai-debug-{{$JobID}}" | |||
class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING" "CREATED_FAILED"}}disabled {{else}}blue {{end}}button' | |||
data-jobid="{{$JobID}}" | |||
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}/{{$JobID}}/'> | |||
{{$.i18n.Tr "repo.debug"}} | |||
</a> | |||
{{else}} | |||
{{if not .BootFile}} | |||
<a id="ai-debug-{{$JobID}}" | |||
class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING" "CREATED_FAILED"}} disabled {{else}}blue {{end}}button' | |||
data-jobid="{{$JobID}}" | |||
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}/{{$JobID}}/'> | |||
{{$.i18n.Tr "repo.debug_again"}} | |||
</a> | |||
{{end}} | |||
{{end}} | |||
</form> | |||
</div> | |||
{{end}} | |||
{{if eq .JobType "ONLINEINFERENCE"}} | |||
<div class="ui compact buttons"> | |||
<form id="debugAgainForm-{{$JobID}}"> | |||
{{$.CsrfTokenHtml}} | |||
<a id="ai-debug-infer-{{$JobID}}" | |||
class='ui basic ai_debug {{if eq .Status "RUNNING"}} blue {{else}} disabled {{end}}button' | |||
data-jobid="{{$JobID}}" | |||
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}/{{$JobID}}/'> | |||
{{$.i18n.Tr "repo.online_debug"}} | |||
</a> | |||
</form> | |||
</div> | |||
{{end}} | |||
{{if eq .JobType "HPC"}} | |||
<div class="ui compact buttons"> | |||
<form id="debugAgainForm-{{$JobID}}"> | |||
{{$.CsrfTokenHtml}} | |||
<a id="ai-debug-infer-{{$JobID}}" | |||
class='ui basic ai_debug {{if eq .Status "RUNNING"}} blue {{else}} disabled {{end}}button' | |||
data-jobid="{{$JobID}}" | |||
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}/{{$JobID}}/'> | |||
{{$.i18n.Tr "repo.start_use"}} | |||
</a> | |||
</form> | |||
</div> | |||
{{end}} | |||
<!-- 停止任务 --> | |||
<div class="ui compact buttons"> | |||
{{if eq .JobType "MODELSAFETY"}} | |||
<form id="stopForm-{{$JobID}}" style="margin-left:-1px;"> | |||
{{$.CsrfTokenHtml}} | |||
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" | |||
class='ui basic ai_stop {{if eq .Status "RUNNING" "WAITING"}} blue {{else}} disabled {{end}} button' | |||
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/modelsafety/{{$JobID}}/stop' | |||
data-jobid="{{$JobID}}"> | |||
{{$.i18n.Tr "repo.stop"}} | |||
</a> | |||
</form> | |||
{{else}} | |||
{{if eq .JobType "DEBUG" "HPC" "BENCHMARK" "SNN4IMAGENET" "BRAINSCORE" "SNN4ECOSET" "SIM2BRAIN_SNN" "ONLINEINFERENCE"}} | |||
<form id="stopForm-{{$JobID}}" style="margin-left:-1px;"> | |||
{{$.CsrfTokenHtml}} | |||
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" | |||
class='ui basic ai_stop {{if eq .Status "RUNNING" "WAITING"}} blue {{else}} disabled {{end}} button' | |||
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else if eq .JobType "BENCHMARK" }}/cloudbrain/benchmark{{else if eq .ComputeResource "NPU" }}/modelarts/notebook{{end}}{{end}}/{{$JobID}}/stop' | |||
data-jobid="{{$JobID}}" data-bootfile="{{.BootFile}}"> | |||
{{$.i18n.Tr "repo.stop"}} | |||
</a> | |||
</form> | |||
{{else}} | |||
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" | |||
class="ui basic ai_stop_version {{if eq .Status "RUNNING" "WAITING"}} blue {{else}} disabled {{end}} button" | |||
data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}/{{if eq .JobType "INFERENCE"}}{{if eq .Cloudbrain.Type 1}}modelarts/inference-job{{else}}cloudbrain/train-job{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .Cloudbrain.Type 1}}modelarts/train-job{{else if eq .Cloudbrain.Type 0}}cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}grampus/train-job{{end}}{{end}}" | |||
data-jobid="{{$JobID}}" | |||
data-cloudbrainid="{{.Cloudbrain.ID}}" | |||
data-version="{{.VersionName}}"> | |||
{{$.i18n.Tr "repo.stop"}} | |||
</a> | |||
{{end}} | |||
{{end}} | |||
</div> | |||
<!-- 修改任务 --> | |||
{{if and (eq .JobType "TRAIN") (not .FineTune)}} | |||
<div class="ui compact buttons __btn_edit__"> | |||
<a style="padding: 0.5rem 1rem;" class="ui basic blue button" href='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 1}}/modelarts/train-job{{else if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}/grampus/train-job/{{if eq .ComputeResource "CPU/GPU"}}gpu{{else}}{{ToLower .ComputeResource}}{{end}}{{end}}/create?modify=true&id={{$JobID}}'> | |||
{{$.i18n.Tr "repo.modelarts.modify"}} | |||
</a> | |||
</div> | |||
{{end}} | |||
<!-- 删除任务 --> | |||
{{if eq .JobType "MODELSAFETY"}} | |||
<form class="ui compact buttons" id="delForm-{{$JobID}}" | |||
action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/modelsafety/{{$JobID}}/del?isadminpage=true' | |||
method="post"> | |||
{{$.CsrfTokenHtml}} | |||
<input type="hidden" value="{{.Cloudbrain.ID}}" style="display:none" name="id" /> | |||
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}" | |||
class="ui basic ai_delete blue button" | |||
style="border-radius: .28571429rem;"> | |||
{{$.i18n.Tr "repo.delete"}} | |||
</a> | |||
</form> | |||
{{else}} | |||
<form class="ui compact buttons" id="delForm-{{$JobID}}" | |||
action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE") (eq .JobType "SNN4ECOSET") (eq .JobType "SIM2BRAIN_SNN")}}/cloudbrain{{else if eq .JobType "DEBUG" "ONLINEINFERENCE" "HPC"}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .Cloudbrain.Type 1}}/modelarts/train-job{{else if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}/grampus/train-job{{end}}{{else if eq .JobType "INFERENCE"}}{{if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{else if eq .Cloudbrain.Type 1}}/modelarts/train-job{{else if eq .Cloudbrain.Type 2}}/grampus/train-job{{end}}{{end}}/{{$JobID}}/del?isadminpage=true' | |||
method="post"> | |||
{{$.CsrfTokenHtml}} | |||
<input type="hidden" value="{{.Cloudbrain.ID}}" style="display:none" name="id" /> | |||
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}" | |||
data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{$JobID}}/del_version?isadminpage=true" | |||
data-version="{{.VersionName}}" | |||
data-cloudbrainid="{{.Cloudbrain.ID}}" | |||
class="ui basic ai_delete blue button" | |||
style="border-radius: .28571429rem;"> | |||
{{$.i18n.Tr "repo.delete"}} | |||
</a> | |||
</form> | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> | |||
{{else}} | |||
{{$JobID := '0'}} | |||
{{if eq .JobType "DEBUG" "TRAIN" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK" "SNN4ECOSET" "SIM2BRAIN_SNN"}} | |||
{{$JobID = .Cloudbrain.ID}} | |||
{{else}} | |||
{{$JobID = .JobID}} | |||
{{end}} | |||
<div class="ui grid stackable item"> | |||
<div class="row"> | |||
<!-- 任务名 --> | |||
<div class="two wide column nowrap" style="width:10% !important;"> | |||
{{if eq .JobType "DEBUG"}} | |||
<a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "INFERENCE"}} | |||
<a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "TRAIN"}} | |||
<a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "BENCHMARK"}} | |||
<a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{end}} | |||
</div> | |||
<!-- 集群 --> | |||
<div class="one wide column text center nowrap" style="width:6% !important;"> | |||
<span | |||
style="font-size: 12px;">{{if .Cluster}}{{.Cluster}}{{else}}--{{end}}</span> | |||
</div> | |||
<!-- 任务状态 --> | |||
<div class="two wide column text center nowrap" | |||
style="width: 8% !important;"> | |||
<span class="job-status" id="{{$JobID}}" | |||
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG" "ONLINEINFERENCE" "HPC"}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}{{else if eq .JobType "INFERENCE"}}/modelarts/inference-job{{else if eq .JobType "TRAIN"}}/modelarts/train-job{{else if eq .JobType "BENCHMARK" "MODELSAFETY"}}/cloudbrain{{end}}' | |||
data-jobid="{{$JobID}}" data-version="{{.VersionName}}" | |||
data-cloudbrainid="{{.Cloudbrain.ID}}" data-datamigrate='{{$.i18n.Tr "repo.migratingData"}}' data-centerpend='{{$.i18n.Tr "repo.centerPending"}}'> | |||
<span> | |||
<i id="{{$JobID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i> | |||
<span id="{{$JobID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span> | |||
{{if eq .Status "WAITING"}}<i id="{{$JobID}}-icon-detail" class="{{.DetailedStatus}}" style="vertical-align: middle;" title='{{$.i18n.Tr (printf "repo.%s" .DetailedStatus)}}'></i>{{end}} | |||
</span> | |||
</span> | |||
</div> | |||
<!-- 任务类型 --> | |||
<div class="one wide column text center nowrap" style="width:6% !important;"> | |||
<span style="font-size: 12px;">{{.JobType}} </span> | |||
</div> | |||
<!-- 任务创建时间 --> | |||
<div class="two wide column text center nowrap" style="width: 8% !important;"> | |||
<span style="font-size: 12px;" | |||
class="">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span> | |||
</div> | |||
<!-- 任务运行时间 --> | |||
<div class="one wide column text center nowrap" style="width:5% !important;"> | |||
<span style="font-size: 12px;" | |||
id="duration-{{$JobID}}">{{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}}</span> | |||
</div> | |||
<!-- 计算资源 --> | |||
<div class="one wide column text center nowrap" style="width:5% !important;"> | |||
<span | |||
style="font-size: 12px;" title="{{.ComputeResource}}">{{if .ComputeResource}}{{.ComputeResource}}{{else}}--{{end}}</span> | |||
</div> | |||
<!-- 智算中心 --> | |||
<div class="one wide column text center nowrap" style="width:7% !important;"> | |||
<span | |||
style="font-size: 12px;">{{if .AiCenter}}{{.AiCenter}}{{else}}--{{end}}</span> | |||
</div> | |||
<!-- XPU类型 --> | |||
<div class="one wide column text center nowrap" style="width:7% !important;"> | |||
<span style="font-size: 12px;" title="{{.CardType}}"> | |||
{{if .CardType}}{{.CardType}}{{else}}--{{end}} | |||
</span> | |||
</div> | |||
<!-- 创建者 --> | |||
<div class="one wide column text center nowrap" style="width:4% !important;"> | |||
{{if .User.Name}} | |||
<a href="{{AppSubUrl}}/{{.User.Name}}" title="{{.User.Name}}"><img | |||
class="ui avatar image" src="{{.User.RelAvatarLink}}"></a> | |||
{{else}} | |||
<a title="Ghost"><img class="ui avatar image" | |||
src="{{AppSubUrl}}/user/avatar/Ghost/-1"></a> | |||
{{end}} | |||
</div> | |||
<!-- 项目 --> | |||
<div class="two wide column text center nowrap" style="width:10% !important;"> | |||
<a href="" title="">--</a> | |||
</div> | |||
<!-- 云脑侧名称 --> | |||
<div class="two wide column text center nowrap" | |||
style="overflow: hidden;text-overflow:ellipsis;width:10% !important;"> | |||
<span class="ui poping up clipboard" data-position="top center" id="clipboard-btn" style="cursor:pointer" | |||
data-clipboard-text="{{.JobName}}" | |||
data-success="{{$.i18n.Tr "repo.copy_link_success"}}" | |||
data-error="{{$.i18n.Tr "repo.copy_link_error"}}" | |||
data-content="{{$.i18n.Tr "repo.copy_link"}}" | |||
data-variation="inverted tiny" | |||
> | |||
<span class="fitted" title="{{.JobName}}">{{.JobName}}</span> | |||
</span> | |||
</div> | |||
<div class="two wide column text center nowrap" style="width: 14%!important;"> | |||
{{if eq .JobType "DEBUG"}} | |||
<div class="ui compact buttons"> | |||
<form id="debugAgainForm-{{$JobID}}"> | |||
{{$.CsrfTokenHtml}} | |||
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}} | |||
<a style="margin: 0 1rem;" id="ai-debug-{{$JobID}}" | |||
class='ui basic disabled button'> | |||
{{$.i18n.Tr "repo.debug"}} | |||
</a> | |||
{{else}} | |||
<a id="ai-debug-{{$JobID}}" class='ui basic disabled button'> | |||
{{$.i18n.Tr "repo.debug_again"}} | |||
</a> | |||
{{end}} | |||
</form> | |||
</div> | |||
{{end}} | |||
<!-- 停止任务 --> | |||
<div class="ui compact buttons"> | |||
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" | |||
class="ui basic disabled button" data-jobid="{{$JobID}}" | |||
data-version="{{.VersionName}}"> | |||
{{$.i18n.Tr "repo.stop"}} | |||
</a> | |||
</div> | |||
<!-- 删除任务 --> | |||
<form class="ui compact buttons" id="delForm-{{$JobID}}" action='' method="post"> | |||
{{$.CsrfTokenHtml}} | |||
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}" | |||
class="ui basic disabled button" style="border-radius: .28571429rem;"> | |||
{{$.i18n.Tr "repo.delete"}} | |||
</a> | |||
</form> | |||
</div> | |||
</div> | |||
</div> | |||
{{end}} | |||
{{end}} | |||
</div> | |||
</div> | |||
<div id="app" style="margin-top: 2rem;width:100%;"> | |||
<div class="center"> | |||
<el-pagination background @current-change="handleCurrentChange" :current-page="page" | |||
:page-sizes="[10]" :page-size="10" layout="total, sizes, prev, pager, next, jumper" | |||
:total="{{.Page.Paginater.Total}}"> | |||
</el-pagination> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<!-- 确认模态框 --> | |||
<div id="deletemodel"> | |||
<div class="ui basic modal"> | |||
<div class="ui icon header"> | |||
<i class="trash icon"></i> {{.i18n.Tr "cloudbrain.delete_task"}} | |||
</div> | |||
<div class="content"> | |||
<p>{{.i18n.Tr "cloudbrain.task_delete_confirm"}}</p> | |||
</div> | |||
<div class="actions"> | |||
<div class="ui red basic inverted cancel button"> | |||
<i class="remove icon"></i> {{.i18n.Tr "cloudbrain.operate_cancel"}} | |||
</div> | |||
<div class="ui green basic inverted ok button"> | |||
<i class="checkmark icon"></i> {{.i18n.Tr "cloudbrain.operate_confirm"}} | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="ui modal debug-again-alert"> | |||
<div class="ui message" style="background-color: rgba(242, 113, 28, 0.05);border: 1px solid rgba(242, 113, 28, 1);border-radius: 5px;"> | |||
<div style="display: flex;align-items: center;"> | |||
<i class="ri-information-line" style="font-size: 35px;color: rgba(242, 113, 28, 1);;"></i> | |||
<div style="text-align: left;margin-left: 1rem;"> | |||
<div style="font-weight: 600;line-height: 2;">{{.i18n.Tr "repo.cloudbrain.morethanonejob1" | Safe }}</div> | |||
<div style="color:#939393">{{.i18n.Tr "repo.cloudbrain.morethanonejob2" | Safe}}</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div id="__vue-root"></div> | |||
</div> | |||
</div> | |||
<script> | |||
document.addEventListener('DOMContentLoaded', function() { | |||
var editbtns = $('.__btn_edit__'); | |||
var curHref = window.location.href; | |||
for (var i = 0, iLen = editbtns.length; i < iLen; i++) { | |||
var buttonEl = editbtns.eq(i).find('a'); | |||
var oHref = buttonEl.attr('href'); | |||
var hasSearch = oHref.split('?').length > 1; | |||
buttonEl.attr('href', oHref + (hasSearch ? '&' : '?') + 'backurl=' + encodeURIComponent(curHref)); | |||
} | |||
}); | |||
</script> | |||
{{template "base/footer" .}} | |||
<script src="{{StaticUrlPrefix}}/js/vp-cloudbrain-tasks.js?v={{MD5 AppVer}}"></script> | |||
{{template "base/footer" .}} |
@@ -34,6 +34,7 @@ | |||
<a class="item" href="{{.RepoLink}}/modelarts/inference-job">{{$.i18n.Tr "repo.modelarts.infer_job"}}</a> | |||
<a class="active item" href="{{.RepoLink}}/cloudbrain/benchmark">{{$.i18n.Tr "repo.modelarts.evaluate_job"}}</a> | |||
<a class="item" href="{{.RepoLink}}/grampus/onlineinfer">{{$.i18n.Tr "repo.modelarts.online_infer"}}</a> | |||
<a class="item" href="{{.RepoLink}}/grampus/general">{{$.i18n.Tr "repo.modelarts.general_job"}}</a> | |||
{{if MLOPS}} | |||
<a class="item" href="{{MlopsHost}}/AIStudio/mlops/deploy-online/edge-inference?reponame={{.Repository.Name}}&repoId={{.Repository.ID}}" target="_blank"> | |||
在线推理1 | |||
@@ -0,0 +1,8 @@ | |||
{{template "base/head" .}} | |||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/vp-cloudbrain-list.css?v={{MD5 AppVer}}" /> | |||
<div class="repository release dataset-list view"> | |||
{{template "repo/header" .}} | |||
<div id="__vue-root"></div> | |||
</div> | |||
<script src="{{StaticUrlPrefix}}/js/vp-cloudbrain-list.js?v={{MD5 AppVer}}"></script> | |||
{{template "base/footer" .}} |
@@ -0,0 +1 @@ | |||
{{ template "repo/cloudbrain/cloudbraincreate" .}} |
@@ -0,0 +1 @@ | |||
{{ template "repo/cloudbrain/cloudbraindetail" .}} |
@@ -1,529 +1,7 @@ | |||
{{template "base/head" .}} | |||
<!-- 提示框 --> | |||
<div class="alert"></div> | |||
<script src="{{StaticUrlPrefix}}/js/specsuse.js?v={{MD5 AppVer}}" type="text/javascript"></script> | |||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/vp-cloudbrain-tasks.css?v={{MD5 AppVer}}" /> | |||
<div class="explore users"> | |||
<div class="cloudbrain_debug" style="display: none;" data-debug="{{$.i18n.Tr "repo.debug"}}" | |||
data-debug-again="{{$.i18n.Tr "repo.debug_again"}}" data-debug-task="{{$.i18n.Tr "cloudbrain.DEBUG"}}" | |||
data-train-task="{{$.i18n.Tr "cloudbrain.TRAIN"}}" data-inference-task="{{$.i18n.Tr "cloudbrain.INFERENCE"}}" | |||
data-benchmark-task="{{$.i18n.Tr "cloudbrain.BENCHMARK"}}" data-inferonline-task="{{$.i18n.Tr "cloudbrain.ONLINEINFERENCE"}}" | |||
data-supercompute-task="{{$.i18n.Tr "repo.superComputeTask"}}" | |||
data-all-cluster="{{.i18n.Tr "cloudbrain.all_resource_cluster"}}" | |||
data-all-aiCenter="{{.i18n.Tr "cloudbrain.all_ai_center"}}" | |||
data-cluster-c2net="{{.i18n.Tr "cloudbrain.resource_cluster_c2net"}}" | |||
data-cluster-openi="{{.i18n.Tr "cloudbrain.resource_cluster_openi"}}" | |||
data-all-task="{{.i18n.Tr "admin.cloudbrain.all_task_types"}}" | |||
data-all-compute="{{.i18n.Tr "admin.cloudbrain.all_computing_resources"}}" | |||
data-all-status="{{.i18n.Tr "admin.cloudbrain.all_status"}}"></div> | |||
{{template "admin/cloudbrain/search_dashboard" .}} | |||
<div class="ui container" style="width:90%;overflow-x:auto;overflow-y:hidden"> | |||
{{template "base/alert" .}} | |||
<div class="ui grid" style="min-width:1700px;"> | |||
<div class="row"> | |||
<div class="ui sixteen wide column" style="margin-bottom:15px;"> | |||
<!-- 任务展示 --> | |||
<div class="dataset list"> | |||
<!-- 表头 --> | |||
<div class="ui grid stackable" style="background: #f0f0f0;;"> | |||
<div class="row"> | |||
<div class="three wide column nowrap" style="width:12%!important"> | |||
<span>{{$.i18n.Tr "repo.cloudbrain_task"}}</span> | |||
</div> | |||
<!-- 集群 --> | |||
<div class="one wide column text center nowrap" style="width:8% !important;"> | |||
<span>{{$.i18n.Tr "repo.modelarts.cluster"}}</span> | |||
</div> | |||
<div class="two wide column text center nowrap" style="width: 8% !important;"> | |||
<span>{{$.i18n.Tr "repo.modelarts.status"}}</span> | |||
</div> | |||
<div class="one wide column text center nowrap" style="width:8% !important"> | |||
<span>{{$.i18n.Tr "repo.cloudbrain_task_type"}}</span> | |||
</div> | |||
<div class="two wide column text center nowrap" style="width: 8% !important;"> | |||
<span>{{$.i18n.Tr "repo.modelarts.createtime"}}</span> | |||
</div> | |||
<div class="one wide column text center nowrap" style="width:6% !important;"> | |||
<span>{{$.i18n.Tr "repo.cloudbrain_status_runtime"}}</span> | |||
</div> | |||
<div class="one wide column text center nowrap" style="width:6% !important;"> | |||
<span>{{$.i18n.Tr "repo.modelarts.computing_resources"}}</span> | |||
</div> | |||
<!-- 智算中心 --> | |||
<div class="one wide column text center nowrap" style="width:8% !important;"> | |||
<span>{{$.i18n.Tr "repo.modelarts.ai_center"}}</span> | |||
</div> | |||
<!-- XPU类型 --> | |||
<div class="one wide column text center nowrap" style="width:10% !important;"> | |||
<span>{{$.i18n.Tr "repo.modelarts.card_type"}}</span> | |||
</div> | |||
<div class="two wide column text center nowrap" style="width: 11%!important;"> | |||
<span>{{$.i18n.Tr "repository"}}</span> | |||
</div> | |||
<div class="three wide column text center nowrap" style="width: 15%!important;"> | |||
<span>{{$.i18n.Tr "repo.cloudbrain_operate"}}</span> | |||
</div> | |||
</div> | |||
</div> | |||
{{range .Tasks}} | |||
{{if .Repo}} | |||
<div class="ui grid stackable item"> | |||
<div class="row"> | |||
<!-- 任务名 --> | |||
{{$JobID := '0'}} | |||
{{if eq .JobType "DEBUG" "TRAIN" "INFERENCE" "HPC" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK" "MODELSAFETY" "SNN4ECOSET" "SIM2BRAIN_SNN" "ONLINEINFERENCE"}} | |||
{{$JobID = .Cloudbrain.ID}} | |||
{{else}} | |||
{{$JobID = .JobID}} | |||
{{end}} | |||
<!-- {{$JobID}} --> | |||
<div class="three wide column nowrap" style="width:12% !important"> | |||
{{if eq .JobType "DEBUG"}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}/{{$JobID}}" | |||
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "HPC"}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/supercompute/job/{{$JobID}}" | |||
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if (eq .JobType "SNN4IMAGENET" "BRAINSCORE" "SNN4ECOSET" "SIM2BRAIN_SNN")}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/cloudbrain/benchmark/{{$JobID}}" | |||
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "INFERENCE"}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/{{if eq .Cloudbrain.Type 2}}grampus{{else if eq .Cloudbrain.Type 1}}modelarts{{else if eq .Cloudbrain.Type 0}}cloudbrain{{end}}/inference-job/{{$JobID}}" | |||
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "TRAIN"}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/{{if eq .Cloudbrain.Type 1}}modelarts{{else if eq .Cloudbrain.Type 0}}cloudbrain{{else if eq .Cloudbrain.Type 2}}grampus{{end}}/train-job/{{$JobID}}" | |||
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "BENCHMARK" "MODELSAFETY"}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/cloudbrain/benchmark/{{$JobID}}" | |||
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "ONLINEINFERENCE"}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/grampus/onlineinfer/{{$JobID}}" | |||
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{end}} | |||
</div> | |||
<!-- 集群 --> | |||
<div class="one wide column text center nowrap" style="width:8% !important;"> | |||
<span style="font-size: 12px;" class="cluster_{{.DisplayJobName}}_{{$JobID}}">{{if .Cluster}}{{.Cluster}}{{else}}--{{end}}</span> | |||
</div> | |||
<!-- 任务状态 --> | |||
<div class="two wide column text center nowrap" | |||
style="width: 8% !important;"> | |||
<span class="job-status" id="{{$JobID}}" | |||
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG" "ONLINEINFERENCE" "HPC"}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}{{else if eq .JobType "INFERENCE"}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts{{end}}/inference-job{{else if eq .JobType "TRAIN"}}{{if eq .ComputeResource "NPU"}}/modelarts/train-job{{else}}/cloudbrain/train-job{{end}}{{else if eq .JobType "BENCHMARK" "MODELSAFETY"}}/cloudbrain{{end}}' | |||
data-jobid="{{$JobID}}" data-version="{{.VersionName}}" | |||
data-cloudbrainid="{{.Cloudbrain.ID}}" | |||
data-bootfile="{{.BootFile}}" data-datamigrate='{{$.i18n.Tr "repo.migratingData"}}' data-centerpend='{{$.i18n.Tr "repo.centerPending"}}'> | |||
<span> | |||
<i id="{{$JobID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i> | |||
<span id="{{$JobID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span> | |||
{{if eq .Status "WAITING"}}<i id="{{$JobID}}-icon-detail" class="{{.DetailedStatus}}" style="vertical-align: middle;" title='{{$.i18n.Tr (printf "repo.%s" .DetailedStatus)}}'></i>{{end}} | |||
</span> | |||
</span> | |||
</div> | |||
<!-- 任务类型 --> | |||
{{$JobType := $.i18n.Tr (printf "cloudbrain.%s" .JobType)}} | |||
<div class="one wide column text center nowrap" style="width:8% !important"> | |||
<span style="font-size: 12px;" title="{{.JobType}}">{{$JobType}}</span> | |||
</div> | |||
<!-- 任务创建时间 --> | |||
<div class="two wide column text center nowrap" style="width: 8% !important;"> | |||
<span style="font-size: 12px;" | |||
class="">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span> | |||
</div> | |||
<!-- 任务运行时间 --> | |||
<div class="one wide column text center nowrap" style="width:6% !important;"> | |||
<span style="font-size: 12px;" | |||
id="duration-{{$JobID}}">{{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}}</span> | |||
</div> | |||
<!-- 计算资源 --> | |||
<div class="one wide column text center nowrap" style="width:6% !important;"> | |||
<span | |||
style="font-size: 12px;" title="{{.ComputeResource}}">{{if .ComputeResource}}{{.ComputeResource}}{{else}}--{{end}}</span> | |||
</div> | |||
<!-- 智算中心 --> | |||
<div class="one wide column text center nowrap" style="width:8% !important;"> | |||
<span style="font-size: 12px;" id="cluster-{{$JobID}}" class="aicenter_{{.DisplayJobName}}_{{$JobID}}" title="{{if .AiCenter}}{{.AiCenter}}{{else}}--{{end}}">{{if .AiCenter}}{{.AiCenter}}{{else}}--{{end}}</span> | |||
</div> | |||
<!-- XPU类型 --> | |||
<div class="one wide column text center nowrap" style="width:10% !important;"> | |||
<span style="font-size: 12px;" title="" class="card_type_{{.DisplayJobName}}_{{$JobID}}"></span> | |||
</div> | |||
<script> | |||
(function(){ | |||
var spec = {{.Spec}} || {}; | |||
var cardType = getListValueWithKey(ACC_CARD_TYPE, spec.AccCardType) || '--'; | |||
var spanEl = document.querySelector('.card_type_{{.DisplayJobName}}_{{$JobID}}'); | |||
spanEl.setAttribute('title', cardType); | |||
spanEl.innerText = cardType; | |||
var cluster = {{.Cluster}} || '--'; | |||
var clusterName = document.querySelector('.cloudbrain_debug').dataset['cluster' + cluster[0] + cluster.toLocaleLowerCase().slice(1)] || '--'; | |||
spanEl = document.querySelector('.cluster_{{.DisplayJobName}}_{{$JobID}}'); | |||
spanEl.setAttribute('title', cluster); | |||
spanEl.innerText = clusterName; | |||
// var aiCenter = spec.AiCenterName || '--'; | |||
// spanEl = document.querySelector('.aicenter_{{.DisplayJobName}}_{{$JobID}}'); | |||
// spanEl.setAttribute('title', aiCenter); | |||
// spanEl.innerText = aiCenter; | |||
})(); | |||
</script> | |||
<!-- 项目 --> | |||
<div class="two wide column text center nowrap" style="width: 11%!important;"> | |||
<a href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}" | |||
title="{{.Repo.OwnerName}}/{{.Repo.Alias}}">{{.Repo.OwnerName}}/{{.Repo.Alias}}</a> | |||
</div> | |||
<div class="three wide column text center nowrap" style="width: 15%!important;"> | |||
{{if eq .JobType "DEBUG"}} | |||
<div class="ui compact buttons"> | |||
<form id="debugAgainForm-{{$JobID}}"> | |||
{{$.CsrfTokenHtml}} | |||
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}} | |||
<a style="margin: 0 1rem;" id="ai-debug-{{$JobID}}" | |||
class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING" "CREATED_FAILED"}}disabled {{else}}blue {{end}}button' | |||
data-jobid="{{$JobID}}" | |||
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}/{{$JobID}}/'> | |||
{{$.i18n.Tr "repo.debug"}} | |||
</a> | |||
{{else}} | |||
{{if not .BootFile}} | |||
<a id="ai-debug-{{$JobID}}" | |||
class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING" "CREATED_FAILED"}} disabled {{else}}blue {{end}}button' | |||
data-jobid="{{$JobID}}" | |||
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}/{{$JobID}}/'> | |||
{{$.i18n.Tr "repo.debug_again"}} | |||
</a> | |||
{{end}} | |||
{{end}} | |||
</form> | |||
</div> | |||
{{end}} | |||
{{if eq .JobType "ONLINEINFERENCE"}} | |||
<div class="ui compact buttons"> | |||
<form id="debugAgainForm-{{$JobID}}"> | |||
{{$.CsrfTokenHtml}} | |||
<a id="ai-debug-infer-{{$JobID}}" | |||
class='ui basic ai_debug {{if eq .Status "RUNNING"}} blue {{else}} disabled {{end}}button' | |||
data-jobid="{{$JobID}}" | |||
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}/{{$JobID}}/'> | |||
{{$.i18n.Tr "repo.online_debug"}} | |||
</a> | |||
</form> | |||
</div> | |||
{{end}} | |||
{{if eq .JobType "HPC"}} | |||
<div class="ui compact buttons"> | |||
<form id="debugAgainForm-{{$JobID}}"> | |||
{{$.CsrfTokenHtml}} | |||
<a id="ai-debug-infer-{{$JobID}}" | |||
class='ui basic ai_debug {{if eq .Status "RUNNING"}} blue {{else}} disabled {{end}}button' | |||
data-jobid="{{$JobID}}" | |||
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}/{{$JobID}}/'> | |||
{{$.i18n.Tr "repo.start_use"}} | |||
</a> | |||
</form> | |||
</div> | |||
{{end}} | |||
<!-- 停止任务 --> | |||
<div class="ui compact buttons"> | |||
{{if eq .JobType "MODELSAFETY"}} | |||
<form id="stopForm-{{$JobID}}" style="margin-left:-1px;"> | |||
{{$.CsrfTokenHtml}} | |||
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" | |||
class='ui basic ai_stop {{if eq .Status "RUNNING" "WAITING"}} blue {{else}} disabled {{end}} button' | |||
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/modelsafety/{{$JobID}}/stop' | |||
data-jobid="{{$JobID}}"> | |||
{{$.i18n.Tr "repo.stop"}} | |||
</a> | |||
</form> | |||
{{else}} | |||
{{if eq .JobType "DEBUG" "HPC" "BENCHMARK" "SNN4IMAGENET" "BRAINSCORE" "SNN4ECOSET" "SIM2BRAIN_SNN" "ONLINEINFERENCE"}} | |||
<form id="stopForm-{{$JobID}}" style="margin-left:-1px;"> | |||
{{$.CsrfTokenHtml}} | |||
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" | |||
class='ui basic ai_stop {{if eq .Status "RUNNING" "WAITING"}} blue {{else}} disabled {{end}} button' | |||
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else if eq .JobType "BENCHMARK" }}/cloudbrain/benchmark{{else if eq .ComputeResource "NPU" }}/modelarts/notebook{{end}}{{end}}/{{$JobID}}/stop' | |||
data-jobid="{{$JobID}}" data-bootfile="{{.BootFile}}"> | |||
{{$.i18n.Tr "repo.stop"}} | |||
</a> | |||
</form> | |||
{{else}} | |||
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" | |||
class='ui basic ai_stop_version {{if eq .Status "RUNNING" "WAITING"}} blue {{else}} disabled {{end}} button' | |||
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}/{{if eq .JobType "INFERENCE"}}{{if eq .Cloudbrain.Type 1}}modelarts/inference-job{{else}}cloudbrain/train-job{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .Cloudbrain.Type 1}}modelarts/train-job{{else if eq .Cloudbrain.Type 0}}cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}grampus/train-job{{end}}{{end}}' | |||
data-jobid="{{$JobID}}" | |||
data-cloudbrainid="{{.Cloudbrain.ID}}" | |||
data-version="{{.VersionName}}" data-bootfile="{{.BootFile}}"> | |||
{{$.i18n.Tr "repo.stop"}} | |||
</a> | |||
{{end}} | |||
{{end}} | |||
</div> | |||
{{if eq .JobType "BENCHMARK"}} | |||
<div class="ui compact buttons"> | |||
<a class="ui basic button {{if $.IsSigned}} blue{{else}} disabled{{end}}" | |||
href="{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}/rate" target="_blank"> | |||
{{$.i18n.Tr "repo.score"}} | |||
</a> | |||
</div> | |||
{{end}} | |||
<!-- 修改任务 --> | |||
{{if and (eq .JobType "TRAIN") (not .FineTune)}} | |||
<div class="ui compact buttons __btn_edit__"> | |||
<a style="padding: 0.5rem 1rem;" class="ui basic blue button" href='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 1}}/modelarts/train-job{{else if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}/grampus/train-job/{{if eq .ComputeResource "CPU/GPU"}}gpu{{else}}{{ToLower .ComputeResource}}{{end}}{{end}}/create?modify=true&id={{$JobID}}'> | |||
{{$.i18n.Tr "repo.modelarts.modify"}} | |||
</a> | |||
</div> | |||
{{end}} | |||
<!-- 删除任务 --> | |||
{{if eq .JobType "MODELSAFETY"}} | |||
<form class="ui compact buttons" id="delForm-{{$JobID}}" | |||
action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/modelsafety/{{$JobID}}/del?ishomepage=true' | |||
method="post"> | |||
{{$.CsrfTokenHtml}} | |||
<input type="hidden" value="{{.Cloudbrain.ID}}" style="display:none" name="id" /> | |||
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}" | |||
class="ui basic ai_delete blue button" | |||
style="border-radius: .28571429rem;"> | |||
{{$.i18n.Tr "repo.delete"}} | |||
</a> | |||
</form> | |||
{{else}} | |||
<form class="ui compact buttons" id="delForm-{{$JobID}}" | |||
action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE") (eq .JobType "SNN4ECOSET") (eq .JobType "SIM2BRAIN_SNN")}}/cloudbrain{{else if eq .JobType "DEBUG" "ONLINEINFERENCE" "HPC"}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .Cloudbrain.Type 1}}/modelarts/train-job{{else if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}/grampus/train-job{{end}}{{else if eq .JobType "INFERENCE"}}{{if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{else if eq .Cloudbrain.Type 1}}/modelarts/train-job{{else if eq .Cloudbrain.Type 2}}/grampus/train-job{{end}}{{end}}/{{$JobID}}/del?ishomepage=true' | |||
method="post"> | |||
{{$.CsrfTokenHtml}} | |||
<input type="hidden" value="{{.Cloudbrain.ID}}" style="display:none" name="id" /> | |||
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}" | |||
data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{$JobID}}/del_version?ishomepage=true" | |||
data-version="{{.VersionName}}" | |||
data-cloudbrainid="{{.Cloudbrain.ID}}" | |||
class="ui basic ai_delete blue button" | |||
style="border-radius: .28571429rem;"> | |||
{{$.i18n.Tr "repo.delete"}} | |||
</a> | |||
</form> | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> | |||
{{else}} | |||
{{$JobID := '0'}} | |||
{{if eq .JobType "DEBUG" "TRAIN" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK" "SNN4ECOSET" "SIM2BRAIN_SNN"}} | |||
{{$JobID = .Cloudbrain.ID}} | |||
{{else}} | |||
{{$JobID = .JobID}} | |||
{{end}} | |||
<div class="ui grid stackable item"> | |||
<div class="row"> | |||
<!-- 任务名 --> | |||
<div class="three wide column nowrap" style="width:12% !important"> | |||
{{if eq .JobType "DEBUG"}} | |||
<a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "INFERENCE"}} | |||
<a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "TRAIN"}} | |||
<a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "BENCHMARK"}} | |||
<a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{end}} | |||
</div> | |||
<!-- 集群 --> | |||
<div class="one wide column text center nowrap" style="width:8% !important;"> | |||
<span | |||
style="font-size: 12px;">{{if .Cluster}}{{.Cluster}}{{else}}--{{end}}</span> | |||
</div> | |||
<!-- 任务状态 --> | |||
<div class="two wide column text center nowrap" | |||
style="padding-left: 2.2rem !important; width: 8% !important;"> | |||
<span class="job-status" id="{{$JobID}}" | |||
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG" "ONLINEINFERENCE" "HPC"}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}{{else if eq .JobType "INFERENCE"}}/modelarts/train-job{{else if eq .JobType "TRAIN"}}/modelarts/train-job{{else if eq .JobType "BENCHMARK" "MODELSAFETY"}}/cloudbrain{{end}}' | |||
data-jobid="{{$JobID}}" data-version="{{.VersionName}}" | |||
data-cloudbrainid="{{.Cloudbrain.ID}}" data-datamigrate='{{$.i18n.Tr "repo.migratingData"}}' data-centerpend='{{$.i18n.Tr "repo.centerPending"}}'> | |||
<span> | |||
<i id="{{$JobID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i> | |||
<span id="{{$JobID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span> | |||
{{if eq .Status "WAITING"}}<i id="{{$JobID}}-icon-detail" class="{{.DetailedStatus}}" style="vertical-align: middle;" title='{{$.i18n.Tr (printf "repo.%s" .DetailedStatus)}}'></i>{{end}} | |||
</span> | |||
</span> | |||
</div> | |||
<!-- 任务类型 --> | |||
{{$JobType := $.i18n.Tr (printf "cloudbrain.%s" .JobType)}} | |||
<div class="one wide column text center nowrap" style="width:8%"> | |||
<span style="font-size: 12px;" title="{{.JobType}}">{{$JobType}}</span> | |||
</div> | |||
<!-- 任务创建时间 --> | |||
<div class="two wide column text center nowrap" style="width: 8% !important;"> | |||
<span style="font-size: 12px;" | |||
class="">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span> | |||
</div> | |||
<!-- 任务运行时间 --> | |||
<div class="one wide column text center nowrap" style="width:6% !important;"> | |||
<span style="font-size: 12px;" | |||
id="duration-{{$JobID}}">{{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}}</span> | |||
</div> | |||
<!-- 计算资源 --> | |||
<div class="one wide column text center nowrap" style="width:6% !important;"> | |||
<span | |||
style="font-size: 12px;" title="{{.ComputeResource}}">{{if .ComputeResource}}{{.ComputeResource}}{{else}}--{{end}}</span> | |||
</div> | |||
<!-- 智算中心 --> | |||
<div class="one wide column text center nowrap" style="width:8% !important;"> | |||
<span | |||
style="font-size: 12px;">{{if .AiCenter}}{{.AiCenter}}{{else}}--{{end}}</span> | |||
</div> | |||
<!-- XPU类型 --> | |||
<div class="one wide column text center nowrap" style="width:10% !important;"> | |||
<span style="font-size: 12px;" title="{{.CardType}}"> | |||
{{if .CardType}}{{.CardType}}{{else}}--{{end}} | |||
</span> | |||
</div> | |||
<!-- 项目 --> | |||
<div class="two wide column text center nowrap" style="width: 11%!important;"> | |||
<a href="" title="">--</a> | |||
</div> | |||
<div class="three wide column text center nowrap" style="width: 15%!important;"> | |||
{{if eq .JobType "DEBUG"}} | |||
<div class="ui compact buttons"> | |||
<form id="debugAgainForm-{{$JobID}}"> | |||
{{$.CsrfTokenHtml}} | |||
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}} | |||
<a style="margin: 0 1rem;" id="ai-debug-{{$JobID}}" | |||
class='ui basic disabled button'> | |||
{{$.i18n.Tr "repo.debug"}} | |||
</a> | |||
{{else}} | |||
<a id="ai-debug-{{$JobID}}" class='ui basic disabled button'> | |||
{{$.i18n.Tr "repo.debug_again"}} | |||
</a> | |||
{{end}} | |||
</form> | |||
</div> | |||
{{end}} | |||
<!-- 停止任务 --> | |||
<div class="ui compact buttons"> | |||
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" | |||
class="ui basic disabled button" data-jobid="{{$JobID}}" | |||
data-version="{{.VersionName}}"> | |||
{{$.i18n.Tr "repo.stop"}} | |||
</a> | |||
</div> | |||
<!-- 删除任务 --> | |||
<form class="ui compact buttons" id="delForm-{{$JobID}}" action='' method="post"> | |||
{{$.CsrfTokenHtml}} | |||
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}" | |||
class="ui basic disabled button" style="border-radius: .28571429rem;"> | |||
{{$.i18n.Tr "repo.delete"}} | |||
</a> | |||
</form> | |||
</div> | |||
</div> | |||
</div> | |||
{{end}} | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div id="app" style="margin-top: 2rem;margin-bottom: 2rem;"> | |||
<div class="center"> | |||
<el-pagination background @current-change="handleCurrentChange" :current-page="page" | |||
:page-sizes="[10]" :page-size="10" layout="total, sizes, prev, pager, next, jumper" | |||
:total="{{.Page.Paginater.Total}}"> | |||
</el-pagination> | |||
</div> | |||
</div> | |||
<!-- 确认模态框 --> | |||
<div id="deletemodel"> | |||
<div class="ui basic modal"> | |||
<div class="ui icon header"> | |||
<i class="trash icon"></i> {{.i18n.Tr "cloudbrain.delete_task"}} | |||
</div> | |||
<div class="content"> | |||
<p>{{.i18n.Tr "cloudbrain.task_delete_confirm"}}</p> | |||
</div> | |||
<div class="actions"> | |||
<div class="ui red basic inverted cancel button"> | |||
<i class="remove icon"></i> {{.i18n.Tr "cloudbrain.operate_cancel"}} | |||
</div> | |||
<div class="ui green basic inverted ok button"> | |||
<i class="checkmark icon"></i> {{.i18n.Tr "cloudbrain.operate_confirm"}} | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="ui modal debug-again-alert"> | |||
<div class="ui message" style="background-color: rgba(242, 113, 28, 0.05);border: 1px solid rgba(242, 113, 28, 1);border-radius: 5px;"> | |||
<div style="display: flex;align-items: center;"> | |||
<i class="ri-information-line" style="font-size: 35px;color: rgba(242, 113, 28, 1);;"></i> | |||
<div style="text-align: left;margin-left: 1rem;"> | |||
<div style="font-weight: 600;line-height: 2;">{{.i18n.Tr "repo.cloudbrain.morethanonejob1" | Safe }}</div> | |||
<div style="color:#939393">{{.i18n.Tr "repo.cloudbrain.morethanonejob2" | Safe}}</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div id="__vue-root"></div> | |||
</div> | |||
<script> | |||
document.addEventListener('DOMContentLoaded', function() { | |||
var editbtns = $('.__btn_edit__'); | |||
var curHref = window.location.href; | |||
for (var i = 0, iLen = editbtns.length; i < iLen; i++) { | |||
var buttonEl = editbtns.eq(i).find('a'); | |||
var oHref = buttonEl.attr('href'); | |||
var hasSearch = oHref.split('?').length > 1; | |||
buttonEl.attr('href', oHref + (hasSearch ? '&' : '?') + 'backurl=' + encodeURIComponent(curHref)); | |||
} | |||
}); | |||
</script> | |||
<script src="{{StaticUrlPrefix}}/js/vp-cloudbrain-tasks.js?v={{MD5 AppVer}}"></script> | |||
{{template "base/footer" .}} |
@@ -1,4 +1,4 @@ | |||
<script>var Feeds={{.Feeds}};</script> | |||
<script>var Feeds = {{.Feeds}};</script> | |||
{{range .Feeds}} | |||
<div class="news"> | |||
<div class="ui left"> | |||
@@ -192,13 +192,19 @@ | |||
{{$.i18n.Tr "action.task_c2ent_mlutrainjob" .GetRepoLink (Printf "%d" .Cloudbrain.ID) .RefName | Str2html}} | |||
{{else}} | |||
{{$.i18n.Tr "action.task_c2ent_mlutrainjob" "" "" "" | Str2html}}<span style="">{{.RefName}}{{$.i18n.Tr "repo.issues.deleted_milestone"}}</span> | |||
{{end}} | |||
{{end}} | |||
{{else if eq .GetOpType 53}} | |||
{{if .Cloudbrain}} | |||
{{$.i18n.Tr "action.task_c2net_gpgpu_iluvatar_trainjob" .GetRepoLink (Printf "%d" .Cloudbrain.ID) .RefName | Str2html}} | |||
{{else}} | |||
{{$.i18n.Tr "action.task_c2net_gpgpu_iluvatar_trainjob" "" "" "" | Str2html}}<span style="">{{.RefName}}{{$.i18n.Tr "repo.issues.deleted_milestone"}}</span> | |||
{{end}} | |||
{{else if eq .GetOpType 54}} | |||
{{if .Cloudbrain}} | |||
{{$.i18n.Tr "action.task_c2netgeneraljob" .GetRepoLink (Printf "%d" .Cloudbrain.ID) .RefName | Str2html}} | |||
{{else}} | |||
{{$.i18n.Tr "action.task_c2netgeneraljob" "" "" "" | Str2html}}<span style="">{{.RefName}}{{$.i18n.Tr "repo.issues.deleted_milestone"}}</span> | |||
{{end}} | |||
{{else if eq .GetOpType 45}} | |||
{{$.i18n.Tr "action.task_c2ent_onlineinferjob" .GetRepoLink .Content .RefName | Str2html}} | |||
{{end}} | |||
@@ -270,6 +276,8 @@ | |||
<span class="text grey"><i class="ri-haze-2-line icon big"></i></span> | |||
{{else if eq .GetOpType 53}} | |||
<span class="text grey"><i class="ri-voice-recognition-line icon big"></i></span> | |||
{{else if eq .GetOpType 54}} | |||
<span class="text grey"><i class="ri-voice-recognition-line icon big"></i></span> | |||
{{else if eq .GetOpType 29}} | |||
<span class="text grey"><i class="ri-vip-crown-line icon big"></i></span> | |||
{{else if eq .GetOpType 30}} | |||
@@ -330,22 +330,26 @@ i.INFO { | |||
.i-bg-orange { | |||
background-position: -495px -51px; | |||
} | |||
.dataMigrating{ | |||
.dataMigrating { | |||
display: inline-block; | |||
width: 18px; | |||
height: 18px; | |||
margin-left: 8px; | |||
background: url("/img/icons.svg"); | |||
background-position: -56px -52px; | |||
background-position: -58px -52px; | |||
} | |||
.centerPending{ | |||
.centerPending { | |||
display: inline-block; | |||
width: 18px; | |||
height: 18px; | |||
margin-left: 8px; | |||
background: url("/img/icons.svg"); | |||
background-position: -511px -52px; | |||
background-position: -514px -52px; | |||
} | |||
.ImagePulling { | |||
display: inline-block; | |||
width: 18px; | |||
height: 18px; | |||
background: url("/img/icons.svg"); | |||
background-position: -86px -52px; | |||
} | |||
.FAILED, | |||
.START_FAILED, | |||
@@ -249,3 +249,23 @@ export const setAiTaskExportDataset = (data) => { | |||
data: Qs.stringify(data), | |||
}); | |||
} | |||
// 个人中心-云脑任务列表 | |||
// job_type,job_status,ai_center,cluster,compute_source,q,page,pageSize | |||
export const getMyAiTasks = (params) => { | |||
return service({ | |||
url: `/api/v1/ai_task/my_list`, | |||
method: 'get', | |||
params: { ...params }, | |||
}); | |||
} | |||
// 管理后台-云脑任务列表 | |||
// job_type,job_status,ai_center,cluster,compute_source,q,page,pageSize | |||
export const getAdminAiTasks = (params) => { | |||
return service({ | |||
url: `/api/v1/admin/ai_task/list`, | |||
method: 'get', | |||
params: { ...params }, | |||
}); | |||
} |
@@ -1,4 +1,5 @@ | |||
import service from '../service'; | |||
import Qs from 'qs'; | |||
// 获取promote配置数据 | |||
export const getStaticFile = (filePathName) => { | |||
@@ -74,3 +75,30 @@ export const getSDKCode = (params) => { | |||
}); | |||
} | |||
// 查询智算列表 | |||
export const getAiCenterList = () => { | |||
return service({ | |||
url: `/resources/queue/centers`, | |||
method: 'get', | |||
params: {} | |||
}); | |||
}; | |||
// 查询所有资源队列名称列表 | |||
export const getResQueueCode = (params) => { | |||
return service({ | |||
url: `/explore/card_request/resources/queue/codes`, | |||
method: 'get', | |||
params, | |||
}); | |||
}; | |||
// common form post | |||
export const commonFormPost = (url, data) => { | |||
return service({ | |||
url: url, | |||
method: 'post', | |||
params: {}, | |||
data: Qs.stringify(data), | |||
}); | |||
} |
@@ -27,6 +27,7 @@ export const getImages = (params) => { | |||
python: params.python, | |||
spec: params.spec, | |||
trainType: params.trainType, | |||
onlyOpenIImage: params.onlyOpenIImage, | |||
page: params.page || 1, | |||
pageSize: params.pageSize || 5, | |||
} | |||
@@ -0,0 +1,86 @@ | |||
<template> | |||
<div class="preview-container markdown" :class="isTaskDetail ? 'task-detail' : ''"> | |||
<div class="markdown-content"> | |||
<p class="title-h" style="font-weight:bold" v-html="$t('cloudbrainObj.generalTaskSdkCodeTip0')"></p> | |||
<div class="content-c"> | |||
<p v-html="$t('cloudbrainObj.generalTaskSdkCodeTip1')"></p> | |||
<pre | |||
class="code-block"><code class="chroma language-text" v-html="$t('cloudbrainObj.generalTaskSdkCodeTip2')"></code></pre> | |||
<p v-html="$t('cloudbrainObj.generalTaskSdkCodeTip3')"></p> | |||
<pre class="code-block"><code class="chroma language-text">🎉 You're ready to go live at https://be22fe9f-d140-474c-81f4-30fb068157b5.tunnel.paracloud.com => http://127.0.0.1:7860 | |||
</code></pre> | |||
<p v-html="$t('cloudbrainObj.generalTaskSdkCodeTip4')"></p> | |||
</div> | |||
</div> | |||
<div class="segment-line"></div> | |||
</div> | |||
</template> | |||
<script> | |||
export default { | |||
name: 'GeneralTaskCodeTips', | |||
props: { | |||
isTaskDetail: { default: false }, | |||
}, | |||
data() { | |||
return {}; | |||
}, | |||
methods: { | |||
}, | |||
mounted() { }, | |||
}; | |||
</script> | |||
<style scoped lang="less"> | |||
.preview-container { | |||
.markdown-content { | |||
font-size: 14px; | |||
p { | |||
font-size: 14px; | |||
margin-bottom: 14px; | |||
} | |||
.code-block { | |||
font-size: 85%; | |||
} | |||
} | |||
.segment-line { | |||
border-top: 1px solid rgba(34, 36, 38, .15); | |||
border-bottom: 1px solid rgba(255, 255, 255, .1); | |||
font-size: 1rem; | |||
line-height: 1; | |||
height: 0; | |||
margin-bottom: 12px !important; | |||
} | |||
} | |||
.task-detail.preview-container { | |||
.markdown-content { | |||
.title-h { | |||
color: #8a8e99; | |||
font-size: 12px; | |||
font-weight: 700; | |||
margin-bottom: 8px; | |||
} | |||
.content-c { | |||
position: relative; | |||
border: 1px solid rgba(34, 36, 38, 0.15); | |||
padding: 0.6em 0.8em; | |||
overflow: auto; | |||
p { | |||
font-size: 13px; | |||
margin-bottom: 10px; | |||
} | |||
} | |||
.segment-line { | |||
display: none; | |||
} | |||
} | |||
} | |||
</style> |
@@ -8,6 +8,9 @@ | |||
<el-input class="field-input" v-model="imageUrl" @input="imageChange" | |||
:readonly="configs.computerResouce != 'GPU'" :placeholder="configs.computerResouce == 'GPU' ? | |||
$t('cloudbrainObj.selectImagePlaceholder') : $t('cloudbrainObj.selectImage')"></el-input> | |||
<div class="tips" v-if="errStatus && showInnerUrlTip" style="color:#e0b4b4"> | |||
{{ $t('cloudbrainObj.imageInnerUrlErrTips') }} | |||
</div> | |||
</div> | |||
</div> | |||
<div class="right-area"> | |||
@@ -152,6 +155,7 @@ export default { | |||
version, | |||
python, | |||
compute_resource: this.configs.computerResouce, | |||
spec: this.configs.computerResouce == 'GPU' && this.configs.taskType != 'GENERAL' ? -1 : this.spec, | |||
recommend: this.dlgActiveName == 'first' ? true : undefined, | |||
mine: this.dlgActiveName == 'second' ? true : undefined, | |||
star: this.dlgActiveName == 'third' ? true : undefined, | |||
@@ -194,6 +198,7 @@ export default { | |||
dlgTotal: 0, | |||
errStatus: false, | |||
showInnerUrlTip: false, | |||
}; | |||
}, | |||
watch: { | |||
@@ -307,8 +312,10 @@ export default { | |||
frameworkVersion: this.dlgCascaderFilter.value[1], | |||
python: this.dlgCascaderFilter.value[2], | |||
cuda: this.dlgCascaderFilter.value[3], | |||
spec: this.configs.computerResouce == 'GPU' ? -1 : this.spec, | |||
trainType: this.configs.computerResouce == 'GPU' ? undefined : getListValueWithKey(JOB_TYPE, this.configs.taskType, 'k', 'train_type'), | |||
spec: this.configs.computerResouce == 'GPU' && this.configs.taskType != 'GENERAL' ? -1 : this.spec, | |||
trainType: this.configs.computerResouce == 'GPU' && this.configs.taskType != 'GENERAL' ? | |||
undefined : getListValueWithKey(JOB_TYPE, this.configs.taskType, 'k', 'train_type'), | |||
onlyOpenIImage: this.configs.computerResouce == 'GPU' && this.configs.taskType != 'GENERAL' ? true : undefined, | |||
} | |||
this.dlgLoading = true; | |||
getImages(params).then(res => { | |||
@@ -366,8 +373,20 @@ export default { | |||
this.dlgPage = page; | |||
this.searchImageData(); | |||
}, | |||
checkInnerUrl(url) { | |||
const regex = /^dockerhub\.pcl\.ac\.cn|^192\./; | |||
if (url && regex.test(url)) { | |||
this.showInnerUrlTip = true; | |||
return true; | |||
} | |||
this.showInnerUrlTip = false; | |||
return false; | |||
}, | |||
check() { | |||
if (this.required && this.imageUrl == '') { | |||
if (this.required && | |||
(this.imageUrl == '' | |||
|| (this.configs.taskType == 'GENERAL' && this.checkInnerUrl(this.imageUrl)) | |||
)) { | |||
this.errStatus = true; | |||
} else { | |||
this.errStatus = false; | |||
@@ -391,6 +410,8 @@ export default { | |||
align-items: center; | |||
.btn-select { | |||
align-self: flex-start; | |||
margin-top: 9px; | |||
display: flex; | |||
justify-content: center; | |||
align-items: center; | |||
@@ -6,7 +6,7 @@ | |||
</div> | |||
<div class="content" :class="errStatus ? 'error' : ''"> | |||
<el-select class="field-input" v-model="currentValue" @change="handleChange"> | |||
<el-option v-for="item in images" :key="item.image_id" :value="item.image_id" | |||
<el-option v-for="(item, index) in images" :key="`${index}-${item.image_id}`" :value="item.image_id" | |||
:label="item.image_name"></el-option> | |||
</el-select> | |||
</div> | |||
@@ -1,7 +1,10 @@ | |||
<template> | |||
<div> | |||
<div class="title"> | |||
<GeneralTaskCodeTips v-if="showGeneralTaskCodeTip" :hasCode="codeContent"></GeneralTaskCodeTips> | |||
<div class="title" style="font-weight:bold"> | |||
<p><span v-html="$t('cloudbrainObj.sdkCodeTip1')"></span></p> | |||
</div> | |||
<div class="title"> | |||
<p v-show="codeContent"><span>{{ $t('cloudbrainObj.sdkCodeTip2') }}</span></p> | |||
</div> | |||
<div class="content" v-show="codeContent"> | |||
@@ -25,6 +28,7 @@ | |||
import hljs from 'highlight.js'; | |||
import { getSDKCode } from '~/apis/modules/common'; | |||
import { initClipboard } from '~/utils'; | |||
import GeneralTaskCodeTips from './GeneralTaskCodeTips.vue' | |||
export default { | |||
name: 'SDKCode', | |||
@@ -32,7 +36,9 @@ export default { | |||
pageConfigs: { type: Object, required: true, }, | |||
formConfigs: { type: Object, required: true, }, | |||
data: { type: Object, required: true }, | |||
specConfigs: { type: Object, required: true }, | |||
}, | |||
components: { GeneralTaskCodeTips }, | |||
data() { | |||
return { | |||
repoOwnerName: location.pathname.split('/')[1], | |||
@@ -58,6 +64,13 @@ export default { | |||
codeHtml() { | |||
return hljs.highlight('python', this.codeContent).value; | |||
}, | |||
showGeneralTaskCodeTip() { | |||
let specLen = 0; | |||
for (let key in this.specConfigs.specs) { | |||
specLen += this.specConfigs.specs[key].length; | |||
} | |||
return this.pageConfigs.taskType == 'GENERAL' && specLen; | |||
}, | |||
}, | |||
methods: { | |||
getCode() { | |||
@@ -1,7 +1,8 @@ | |||
<template> | |||
<div class="item-container"> | |||
<template v-for="(item, index) in configs.fields"> | |||
<div :key="item + '-' + index" v-if="item != 'dataset' && item != 'modelList' && item != 'failedReason'" | |||
<div :key="item + '-' + index" | |||
v-if="item != 'dataset' && item != 'modelList' && item != 'failedReason' && item != 'generalTaskCodeTips'" | |||
class="item-block"> | |||
<div class="title"> {{ renderTitle(item) }} </div> | |||
<div class="content" v-html="renderContent(item)"></div> | |||
@@ -88,20 +89,26 @@ | |||
<pre><code class="python hljs" v-html="renderHljs(data.task.sdk_code)"></code></pre> | |||
</div> | |||
<div class="copy-btn"> | |||
<a href="javascript:;" class="ui poping up clipboard" :id="`clipboard-${sparkMD5Hash(data.task.sdk_code)}`" | |||
data-position="top center" data-variation="inverted tiny" :data-success="$t('copySuccess')" | |||
:data-content="$t('copy')" :data-original="$t('copy')" :data-clipboard-text="data.task.sdk_code"> | |||
<a href="javascript:;" class="ui poping up clipboard" | |||
:id="`clipboard-${sparkMD5Hash(data.task.sdk_code)}`" data-position="top center" | |||
data-variation="inverted tiny" :data-success="$t('copySuccess')" :data-content="$t('copy')" | |||
:data-original="$t('copy')" :data-clipboard-text="data.task.sdk_code"> | |||
<i style="font-size:14px;" class="copy outline icon"></i> | |||
</a> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div :key="item + '-' + index" v-if="item == 'generalTaskCodeTips' && data.can_modify" | |||
class="item-block item-model-code"> | |||
<GeneralTaskCodeTips :isTaskDetail="true"></GeneralTaskCodeTips> | |||
</div> | |||
</template> | |||
</div> | |||
</template> | |||
<script> | |||
import GeneralTaskCodeTips from '../GeneralTaskCodeTips.vue' | |||
import { renderSpecObject, initClipboard } from '~/utils'; | |||
import { i18n } from '~/langs'; | |||
import { formatDate } from 'element-ui/lib/utils/date-util'; | |||
@@ -115,6 +122,7 @@ export default { | |||
data: { type: Object, default: () => { return {} } }, | |||
nosdkcode: { type: Boolean, default: false }, | |||
}, | |||
components: { GeneralTaskCodeTips }, | |||
data() { | |||
return { | |||
clipboardHandler: null | |||
@@ -4,6 +4,7 @@ | |||
<p :key="index + '-1'"><b>[{{ item.reason }}]</b> <span>{{ item.timestampStr }}</span></p> | |||
<p :key="index + '-2'">{{ item.message }}</p> | |||
</template> | |||
<p v-if="events.length == 0 && !loading">{{ this.$t('noMessage') }}</p> | |||
</div> | |||
</template> | |||
@@ -12,7 +12,8 @@ export const JOB_TYPE = [ | |||
{ k: 'INFERENCE', v: i18n.t('inferenceTask'), train_type: 'TrainJob' }, | |||
{ k: 'BENCHMARK', v: i18n.t('benchmarkTask') }, | |||
{ k: 'ONLINEINFERENCE', v: i18n.t('onlineinfer') }, | |||
{ k: 'HPC', v: i18n.t('superComputeTask') } | |||
{ k: 'HPC', v: i18n.t('superComputeTask') }, | |||
{ k: 'GENERAL', v: i18n.t('generalTask'), train_type: 'Notebook' } | |||
]; | |||
// 资源管理 | |||
export const CLUSTERS = [{ k: 'OpenI', v: i18n.t('resourcesManagement.OpenI') }, { k: 'C2Net', v: i18n.t('resourcesManagement.C2Net') }]; | |||
@@ -25,7 +26,7 @@ export const COMPUTER_RESOURCES_COLORS = { | |||
'ILUVATAR-GPGPU': '#0038bd', | |||
'METAX-GPGPU': '#5c246a', | |||
}; | |||
export const ACC_CARD_TYPE = [{ k: 'T4', v: 'T4' }, { k: 'A100', v: 'A100' }, { k: 'V100', v: 'V100' }, { k: 'ASCEND910', v: 'Ascend 910' }, { k: 'ASCEND-D910B', v: 'Ascend-D910B' }, { k: 'MLU270', v: 'MLU270' }, { k: 'MLU290', v: 'MLU290' }, { k: 'RTX3080', v: 'RTX3080' }, { k: 'ENFLAME-T20', v: 'ENFLAME-T20' }, { k: 'DCU', v: 'DCU' }, { k: 'BI-V100', v: 'BI-V100' }, { k: 'MR-V100', v: 'MR-V100' }, { k: 'N100', v: 'N100' }]; | |||
export const ACC_CARD_TYPE = [{ k: 'T4', v: 'T4' }, { k: 'A100', v: 'A100' }, { k: 'V100', v: 'V100' }, { k: 'ASCEND910', v: 'Ascend 910' }, { k: 'ASCEND-D910B', v: 'Ascend-D910B' }, { k: 'MLU270', v: 'MLU270' }, { k: 'MLU290', v: 'MLU290' }, { k: 'RTX3080', v: 'RTX3080' }, { k: '3090', v: '3090' }, { k: 'ENFLAME-T20', v: 'ENFLAME-T20' }, { k: 'DCU', v: 'DCU' }, { k: 'BI-V100', v: 'BI-V100' }, { k: 'MR-V100', v: 'MR-V100' }, { k: 'N100', v: 'N100' }]; | |||
export const SPECIFICATION_STATUS = [{ k: '1', v: i18n.t('resourcesManagement.willOnShelf') }, { k: '2', v: i18n.t('resourcesManagement.onShelf') }, { k: '3', v: i18n.t('resourcesManagement.offShelf') }]; | |||
export const NETWORK_TYPE = [{ k: 1, v: `${i18n.t('cloudbrainObj.networkType')}(${i18n.t('cloudbrainObj.noInternet')})` }, { k: 2, v: `${i18n.t('cloudbrainObj.networkType')}(${i18n.t('cloudbrainObj.hasInternet')})` }]; | |||
export const NETWORK_TYPE_VALUE = [{ k: 1, v: i18n.t('cloudbrainObj.noInternet') }, { k: 2, v: i18n.t('cloudbrainObj.hasInternet') }]; | |||
@@ -1,6 +1,7 @@ | |||
const en = { | |||
loading: 'Loading...', | |||
noData: 'No Data', | |||
noMessage: "No Message", | |||
noDataset: 'No Datasets', | |||
date: 'Date', | |||
@@ -42,6 +43,7 @@ const en = { | |||
benchmarkTask: 'Benchmark Task', | |||
onlineinfer: "Online Inference", | |||
superComputeTask: "HPC Task", | |||
generalTask: "General Task", | |||
createPublicProject: 'Create Public Projects', | |||
dailyPutforwardTasks: 'Daily Put Forward Tasks', | |||
dailyPR: 'Daily PR', | |||
@@ -190,6 +192,7 @@ const en = { | |||
resSceneName: 'Resources Scene Name', | |||
jobType: 'Job Type', | |||
allJobType: 'All Job Type', | |||
allJobStatus: 'All Job Status', | |||
sceneType: "Community Scene Type", | |||
allSceneType: "All Community Scene Type", | |||
isExclusiveSpec: 'Is Exclusive Spec?', | |||
@@ -632,7 +635,8 @@ const en = { | |||
appName: 'App name', | |||
appList: 'App List', | |||
taskNameTips: 'Name must start with a lowercase letter or number,can include lowercase letter,number,_ and -,can not end with _, and can be up to 36 characters long.', | |||
taskNameTips1: 'Name must start with a lowercase letter,can include lowercase letter,number,and -, and between 5 and 26 characters.', | |||
taskNameTips1: 'Name must start with a lowercase letter,can include lowercase letter,number,and -, and between 5 and 26 characters.', | |||
imageInnerUrlErrTips: 'The image url you specified is not applicable to this task. Please specify a different image.', | |||
taskDescr: 'Description', | |||
taskDescrPlaceholder: 'The description should not exceed 255 characters', | |||
codeBranch: 'Code branch', | |||
@@ -712,6 +716,8 @@ const en = { | |||
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;', | |||
superTaskEmptyTitle: 'HPC task has not been created', | |||
generalTaskEmptyTitle: 'General task has not been created', | |||
generalTaskEmptyTip1: 'This task type has the following characteristics and can only be used after submitting a usage application and approval on the <a href="/computingpower/demand">Computing resources</a> page:\n (1) Provide a jupyter debugging environment.\n (2) The running time is unlimited, but points are required.\n (3) Supports open ports.\n (4) Saving images is not supported, and debugging again is not supported.', | |||
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', | |||
@@ -725,6 +731,7 @@ const en = { | |||
bootFileTips: 'The startup file is the entry file that your program executes, and it must be a file ending in .py', | |||
viewSample: 'View sample', | |||
tabTitOnlineInference: 'Online Inference', | |||
tabTitGeneral: 'General Task', | |||
allResultDownload: 'All result download', | |||
downloadDisplayMaxCountTips: 'Display up to {count} files or folders in a single directory', | |||
file_sync_ing: "File synchronization in progress, please wait", | |||
@@ -757,6 +764,7 @@ const en = { | |||
scrollToBottom: 'Scroll to bottom', | |||
migratingData: 'Data migration in progress', | |||
centerPending: 'Queuing in sub centers', | |||
imagePulling: 'Pulling image in progress', | |||
sdkUseWay: 'c2net library usage', | |||
dialogTips: { | |||
@@ -776,6 +784,18 @@ const en = { | |||
codeUseDlgTitle: 'How to obtain models, datasets, and output paths in code via the c2net library', | |||
sdkCodeTip1: 'Please use c2net library to access relevant resources in the container, which can be referred to as <a target="_blank" href="https://openi.pcl.ac.cn/docs/index.html#/cloudbrain/codepath">Help</a>.', | |||
sdkCodeTip2: 'Based on the type of cloud brain task you choose, as well as the specified datasets, models, etc. The example code for accessing datasets and models and uploading training output are as follows:', | |||
generalTaskSdkCodeTip0: 'How to open ports for general task', | |||
generalTaskSdkCodeTip1: 'Run the following command to configure HTTP proxy in the environment:', | |||
generalTaskSdkCodeTip2: '/root/bin/scc tunnel http http://127.0.0.1:7860 (Port number 7860 can be customized)', | |||
generalTaskSdkCodeTip3: 'After successful configuration, output the following information:', | |||
generalTaskSdkCodeTip4: 'You can use the address <code>https://be22fe9f-d140-474c-81f4-30fb068157b5.tunnel.paracloud.com</code> to access the corresponding service.', | |||
searchTaskName: 'Search Task Name...', | |||
searchTaskNameOrCreator: 'Search Task Name/Creator...', | |||
downloadReport: 'Download Report', | |||
cloudbrainTaskType: 'Task Type', | |||
repo: 'Repository', | |||
cloudbrainTaskName: 'Cloudbrain Name', | |||
}, | |||
superComputeObj: { | |||
mmlSparkDescr: `The full name of MMLSpark is Microsoft Machine Learning for Apache Spark, which enables users to run customized container images and grants them root accesses within the container. Users can directly use Microsoft's MMLSpark provided by the platform.\nNote: MMLSpark is a Spark version provided by Microsoft for machine learning environments( <a target="_blank" href="https://github.com/Azure/mmlspark">https://github.com/Azure/mmlspark</a> )Regarding mmlspark, please refer to the following paper: <a target="_blank" href="https://arxiv.org/pdf/1810.08744.pdf">https://arxiv.org/pdf/1810.08744.pdf</a>`, | |||
@@ -1,6 +1,7 @@ | |||
const zh = { | |||
loading: "加载中...", | |||
noData: "暂无数据", | |||
noMessage: "暂无信息", | |||
date: "日期", | |||
noDataset: "空荡荡的,什么都没有", | |||
confirm: "确定", | |||
@@ -41,6 +42,7 @@ const zh = { | |||
benchmarkTask: "评测任务", | |||
onlineinfer: "在线推理", | |||
superComputeTask: "超算任务", | |||
generalTask: "通用任务", | |||
createPublicProject: "创建公开项目", | |||
dailyPutforwardTasks: "每日提出任务", | |||
dailyPR: "每日提出PR", | |||
@@ -189,6 +191,7 @@ const zh = { | |||
resSceneName: "应用场景名称", | |||
jobType: "任务类型", | |||
allJobType: "全部任务类型", | |||
allJobStatus: "全部任务状态", | |||
sceneType: "社区资源性质", | |||
allSceneType: "全部社区资源性质", | |||
isExclusiveSpec: "是否专属资源规格", | |||
@@ -648,6 +651,7 @@ const zh = { | |||
appList: '应用列表', | |||
taskNameTips: '只能以小写字母或数字开头且只包含小写字母、数字、_和-,不能以_结尾,最长36个字符。', | |||
taskNameTips1: '只能以小写字母开头,包含数字、小写字母和短横线(-),长度为5~26个字符。', | |||
imageInnerUrlErrTips: '您指定的镜像地址不适用于该任务,请重新指定其它镜像。', | |||
taskDescr: '任务描述', | |||
taskDescrPlaceholder: '描述字数不超过255个字符', | |||
codeBranch: '代码分支', | |||
@@ -727,6 +731,8 @@ const zh = { | |||
onlineInferTaskEmptyTitle: '未创建过在线推理任务', | |||
onlineInferEmptyTip2: '数据集:云脑1提供 CPU / GPU 资源,云脑2提供 Ascend NPU 资源,在线推理使用的数据集也需要上传到对应的环境;', | |||
superTaskEmptyTitle: '未创建过超算任务', | |||
generalTaskEmptyTitle: '未创建过通用任务', | |||
generalTaskEmptyTip1: '该任务类型具有如下特点,需在 <a href="/computingpower/demand">算力资源</a> 页面提交使用申请并审核通过后才能使用:\n(1)提供jupyter调试环境。\n(2)运行时间不限时,但需消耗积分。\n(3)支持开放端口。\n(4)不支持保存镜像,不支持再次调试。', | |||
deleteConfirmTips: '您确认删除该任务么?此任务一旦删除不可恢复。', | |||
deletingTips: '任务删除中,请稍后', | |||
tabTitDebug: '调试任务', | |||
@@ -740,6 +746,7 @@ const zh = { | |||
bootFileTips: '启动文件是您程序执行的入口文件,必须是以.py结尾的文件。比如train.py、main.py、example/train.py、case/main.py。', | |||
viewSample: '查看样例', | |||
tabTitOnlineInference: '在线推理', | |||
tabTitGeneral: '通用任务', | |||
allResultDownload: '全部结果下载', | |||
downloadDisplayMaxCountTips: '单目录下最多显示{count}个文件或文件夹', | |||
file_sync_ing: "文件同步中,请稍侯", | |||
@@ -772,6 +779,7 @@ const zh = { | |||
scrollToBottom: '滚动到底部', | |||
migratingData: '数据迁移中', | |||
centerPending: '分中心排队中', | |||
imagePulling: '拉取镜像中', | |||
sdkUseWay: '通过c2net库访问方式', | |||
dialogTips: { | |||
@@ -791,6 +799,18 @@ const zh = { | |||
codeUseDlgTitle: '如何在代码中通过c2net库方式获取模型、数据集和输出路径', | |||
sdkCodeTip1: '请使用c2net库方式在容器中访问相关资源,可参考<a target="_blank" href="https://openi.pcl.ac.cn/docs/index.html#/cloudbrain/codepath">使用帮助</a>。', | |||
sdkCodeTip2: '根据您选择的云脑任务类型,指定的数据集、模型等,访问数据集和模型,回传结果的示例代码如下:', | |||
generalTaskSdkCodeTip0: '通用任务如何开放端口', | |||
generalTaskSdkCodeTip1: '运行以下命令可在环境中配置HTTP代理:', | |||
generalTaskSdkCodeTip2: '/root/bin/scc tunnel http http://127.0.0.1:7860 (端口号7860可自定义)', | |||
generalTaskSdkCodeTip3: '配置成功后,输出如下信息:', | |||
generalTaskSdkCodeTip4: '即可使用地址<code>https://be22fe9f-d140-474c-81f4-30fb068157b5.tunnel.paracloud.com</code>访问相应服务。', | |||
searchTaskName: '搜索任务名称...', | |||
searchTaskNameOrCreator: '搜索任务名称/创建者...', | |||
downloadReport: '下载此报告', | |||
cloudbrainTaskType: '云脑任务类型', | |||
repo: '项目', | |||
cloudbrainTaskName: '云脑侧任务', | |||
}, | |||
superComputeObj: { | |||
mmlSparkDescr: `MMLSpark全称为Microsoft Machine Learning for Apache Spark,支持用户运行自制容器镜像,且赋予了用户容器内root权限。用户可直接使用平台提供的微软的MMLSpark。\n注:MMLSpark是微软提供针对机器学习环境的Spark版本(<a target="_blank" href="https://github.com/Azure/mmlspark">https://github.com/Azure/mmlspark</a>),关于mmlspark可参考论文:<a target="_blank" href="https://arxiv.org/pdf/1810.08744.pdf">https://arxiv.org/pdf/1810.08744.pdf</a>`, | |||
@@ -194,7 +194,7 @@ export const CreatePageConfigs = { | |||
taskDescr: { required: false, }, | |||
branchName: { required: true, }, | |||
model: { required: false, multiple: true, useExceedSize: true }, | |||
imagev1: { required: true, type: -1 }, | |||
imagev1: { required: true, type: -1 }, | |||
dataset: { required: false, useExceedSize: true }, | |||
networkType: { required: true }, | |||
spec: { required: true }, | |||
@@ -589,6 +589,36 @@ export const CreatePageConfigs = { | |||
}], | |||
}] | |||
}], | |||
// 通用任务 | |||
'GENERAL': [{ | |||
url: 'grampus/general', | |||
clusters: ['C2Net'], | |||
'C2Net': [{ | |||
url: 'grampus/general/create?type=0', | |||
computerResouces: ['GPU'], | |||
'GPU': [{ | |||
url: 'grampus/general/create?type=0', | |||
clusterType: 'C2Net', | |||
tips2: i18n.t('cloudbrainObj.pathTips3', { | |||
code: '/code', | |||
dataset: '/dataset', | |||
model: '/pretrainmodel', | |||
}), | |||
hideTips2: true, | |||
form: { | |||
taskName: { required: true, }, | |||
taskDescr: { required: false, }, | |||
taskType: {}, | |||
branchName: {}, | |||
model: { required: false, multiple: true, useExceedSize: true }, | |||
imagev1: { required: true, type: -1 }, | |||
dataset: { required: false, type: 0, useExceedSize: true }, | |||
networkType: { required: true }, | |||
spec: {}, | |||
}, | |||
}], | |||
}] | |||
}], | |||
}; | |||
export const ListPageConfigs = { | |||
@@ -598,7 +628,8 @@ export const ListPageConfigs = { | |||
{ key: 'TRAIN', label: i18n.t('cloudbrainObj.tabTitTrain'), url: 'modelarts/train-job?listType=all', }, | |||
{ key: 'INFERENCE', label: i18n.t('cloudbrainObj.tabTitInference'), url: 'modelarts/inference-job', }, | |||
{ key: 'BENCHMARK', label: i18n.t('cloudbrainObj.tabTitBenchmark'), url: 'cloudbrain/benchmark', }, | |||
{ key: 'ONLINEINFERENCE', label: i18n.t('cloudbrainObj.tabTitOnlineInference'), url: 'grampus/onlineinfer', } | |||
{ key: 'ONLINEINFERENCE', label: i18n.t('cloudbrainObj.tabTitOnlineInference'), url: 'grampus/onlineinfer', }, | |||
{ key: 'GENERAL', label: i18n.t('cloudbrainObj.tabTitGeneral'), url: 'grampus/general', } | |||
], | |||
pages: [{ | |||
jobType: 'DEBUG', | |||
@@ -654,6 +685,17 @@ export const ListPageConfigs = { | |||
emptyTip0: true, | |||
emptyTip2: i18n.t('cloudbrainObj.onlineInferEmptyTip2'), | |||
emptyTip3: i18n.t('cloudbrainObj.debugTaskEmptyTip3', { url: 'https://openi.pcl.ac.cn/docs/index.html#/cloudbrain/infer/online-inference' }), | |||
}, { | |||
jobType: 'GENERAL', | |||
sortList: getSortList([]), | |||
jobTypeName: getListValueWithKey(JOB_TYPE, 'GENERAL'), | |||
url: 'grampus/general', | |||
createUrl: 'grampus/general/create?type=0', | |||
columns: ['taskName', 'status', 'createTime', 'clusterAndComputeResource', 'creator'], | |||
operations: ['debug', 'stop', 'modify', 'delete'], | |||
emptyTitle: i18n.t('cloudbrainObj.generalTaskEmptyTitle'), | |||
emptyTip1: i18n.t('cloudbrainObj.generalTaskEmptyTip1'), | |||
emptyTip3: i18n.t('cloudbrainObj.debugTaskEmptyTip3', { url: 'https://openi.pcl.ac.cn/docs/index.html#/cloudbrain/paraCloud' }), | |||
}] | |||
}; | |||
@@ -1347,6 +1389,39 @@ export const DetailPageConfigs = { | |||
}], | |||
}] | |||
}], | |||
// 通用任务 | |||
'GENERAL': [{ | |||
listUrl: 'grampus/general', | |||
clusters: ['C2Net'], | |||
'C2Net': [{ | |||
'GPU': [{ | |||
detailUrl: 'grampus/general/', | |||
summary: [], | |||
operations: [], | |||
tabs: [{ | |||
name: 'configInfo', | |||
fields: [ | |||
'taskName', 'imagev1', | |||
'status', 'spec', | |||
'creator', 'aiCenter', | |||
'branch', 'hasInternet', | |||
'computerRes', '', | |||
'createTime', '', | |||
'startTime', '', | |||
'endTime', '', | |||
'duration', '', | |||
'descr', '', | |||
'failedReason', | |||
'dataset', | |||
'modelList', | |||
'generalTaskCodeTips', | |||
] | |||
}, { | |||
name: 'operationProfile' | |||
}], | |||
}], | |||
}] | |||
}], | |||
}; | |||
export const getCreatePageConfigs = (url) => { | |||
@@ -55,11 +55,13 @@ | |||
<DatasetSelect ref="datasetRef" v-if="formCfg.dataset" v-model="state.dataset" | |||
:required="formCfg.dataset.required" | |||
:type="formCfg.dataset.type != undefined ? formCfg.dataset.type : -1" :repoOwnerName="repoOwnerName" | |||
:repoName="repoName" :exceedSize="datasetSize" :useExceedSize="formCfg.dataset.useExceedSize || false"> | |||
:repoName="repoName" :exceedSize="datasetSize" | |||
:useExceedSize="formCfg.dataset.useExceedSize || false"> | |||
</DatasetSelect> | |||
<ModelSelect ref="modelRef" v-if="formCfg.model" v-model="state.model" :required="formCfg.model.required" | |||
:multiple="formCfg.model.multiple" :repoOwnerName="repoOwnerName" :repoName="repoName" | |||
:exceedSize="modelSize" :useExceedSize="formCfg.model.useExceedSize"></ModelSelect> | |||
<ModelSelect ref="modelRef" v-if="formCfg.model" v-model="state.model" | |||
:required="formCfg.model.required" :multiple="formCfg.model.multiple" :repoOwnerName="repoOwnerName" | |||
:repoName="repoName" :exceedSize="modelSize" :useExceedSize="formCfg.model.useExceedSize"> | |||
</ModelSelect> | |||
<BranchName ref="branchNameRef" v-if="formCfg.branchName" v-model="state.branchName" | |||
:required="formCfg.branchName.required" :branches="branchList"> | |||
</BranchName> | |||
@@ -77,15 +79,17 @@ | |||
<div class="left-area"> | |||
<div class="title"></div> | |||
<div class="content" style="margin-left:4px;"> | |||
<el-checkbox v-model="state.isContinue">{{ this.$t('cloudbrainObj.reuseLastResult') }}</el-checkbox> | |||
<el-checkbox v-model="state.isContinue">{{ this.$t('cloudbrainObj.reuseLastResult') | |||
}}</el-checkbox> | |||
<el-tooltip style="margin-left:12px" placement="top" effect="light"> | |||
<i class="question circle icon link" style="margin-top:-7px"></i> | |||
<div slot="content"> | |||
<div style="width:200px;text-align:center;">{{ this.$t('cloudbrainObj.continue_helper') }}</div> | |||
<div style="width:200px;text-align:center;">{{ this.$t('cloudbrainObj.continue_helper') }} | |||
</div> | |||
</div> | |||
</el-tooltip> | |||
<a :href="pageCfg.modify ? pageCfg.modify.continueSampleUrl : 'javascript:;'" target="_blank">{{ | |||
$t('modelManage.viewSamples') }}</a> | |||
$t('modelManage.viewSamples') }}</a> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -95,7 +99,8 @@ | |||
<div class="content"> | |||
<el-button type="primary" | |||
:disabled="maskLoading || alreadyMsgBoxShow || !specConfigs.specs[state.networkType].length" | |||
size="default" class="submit-btn" @click="submit">{{ $t('cloudbrainObj.createTask') }}</el-button> | |||
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> | |||
</div> | |||
@@ -108,7 +113,8 @@ | |||
<div class="icon ri-arrow-drop-right-line"></div> | |||
</div> | |||
<div class="form-right-content" v-show="showFormRight"> | |||
<SDKCode ref="sdkCodeRef" :data="state" :pageConfigs="pageCfg" :formConfigs="formCfg"></SDKCode> | |||
<SDKCode ref="sdkCodeRef" :data="state" :pageConfigs="pageCfg" :formConfigs="formCfg" | |||
:specConfigs="specConfigs"></SDKCode> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -7,7 +7,7 @@ | |||
<div v-if="!loading" class="ui container"> | |||
<div class="head-path"> | |||
<a class="section" :href="`/${repoOwnerName}/${repoName}/debugjob?debugListType=all`">{{ | |||
$t('cloudbrainObj.cloudbrain') }}</a> | |||
$t('cloudbrainObj.cloudbrain') }}</a> | |||
<span class="divider">/</span> | |||
<a class="section" :href="`/${repoOwnerName}/${repoName}/${pageCfg.listUrl}`">{{ pageCfg.taskTypeName }}</a> | |||
<span class="divider">/</span> | |||
@@ -25,8 +25,12 @@ | |||
<span>{{ $t('status') }}:</span> | |||
<i :class="item.task.status"></i> | |||
<span>{{ item.task.status }}</span> | |||
<i v-if="item.task.detailed_status==='dataMigrating' && item.task.status==='WAITING'" :class="item.task.detailed_status" :title="$t('cloudbrainObj.migratingData')"></i> | |||
<i v-if="item.task.detailed_status==='centerPending' && item.task.status==='WAITING'" :class="item.task.detailed_status" :title="$t('cloudbrainObj.centerPending')"></i> | |||
<i v-if="item.task.detailed_status === 'dataMigrating' && item.task.status === 'WAITING'" | |||
:class="item.task.detailed_status" :title="$t('cloudbrainObj.migratingData')"></i> | |||
<i v-if="item.task.detailed_status === 'centerPending' && item.task.status === 'WAITING'" | |||
:class="item.task.detailed_status" :title="$t('cloudbrainObj.centerPending')"></i> | |||
<i v-if="item.task.detailed_status === 'ImagePulling' && item.task.status === 'WAITING'" | |||
:class="item.task.detailed_status" :title="$t('cloudbrainObj.imagePulling')"></i> | |||
</span> | |||
<span class="task-duration"> | |||
<span>{{ $t('cloudbrainObj.runDuration') }}:</span><span>{{ item.task.formatted_duration }}</span> | |||
@@ -47,7 +51,7 @@ | |||
</ExportDataset> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</template> | |||
<div class="content"> | |||
<el-tabs v-model="item.activeName" @tab-click="tabChange(item)"> | |||
@@ -282,12 +286,14 @@ export default { | |||
line-height: 1.5; | |||
cursor: default; | |||
position: relative; | |||
.title { | |||
height: 100%; | |||
width: 100%; | |||
display: flex; | |||
align-items: center; | |||
justify-content: space-between; | |||
.title-l { | |||
display: flex; | |||
align-items: center; | |||
@@ -304,7 +310,8 @@ export default { | |||
align-items: center; | |||
margin-right: 12px; | |||
i { | |||
i, | |||
span { | |||
margin-right: 4px; | |||
} | |||
} | |||
@@ -43,8 +43,8 @@ | |||
<span>{{ scope.row.task.versionCount }}</span> | |||
</template> | |||
</el-table-column> | |||
<el-table-column v-if="pageCfg.page.columns.indexOf('modelInfo') >= 0" :label="$t('repos.model')" align="left" | |||
header-align="left" width="100"> | |||
<el-table-column v-if="pageCfg.page.columns.indexOf('modelInfo') >= 0" :label="$t('repos.model')" | |||
align="left" header-align="left" width="100"> | |||
<template slot-scope="scope"> | |||
<span>{{ scope.row.task.model }}</span> | |||
</template> | |||
@@ -59,6 +59,8 @@ | |||
:class="scope.row.task.detailed_status" :title="$t('cloudbrainObj.migratingData')"></i> | |||
<i v-if="scope.row.task.detailed_status === 'centerPending' && scope.row.task.status === 'WAITING'" | |||
:class="scope.row.task.detailed_status" :title="$t('cloudbrainObj.centerPending')"></i> | |||
<i v-if="scope.row.task.detailed_status === 'ImagePulling' && scope.row.task.status === 'WAITING'" | |||
:class="scope.row.task.detailed_status" :title="$t('cloudbrainObj.imagePulling')"></i> | |||
</div> | |||
</template> | |||
</el-table-column> | |||
@@ -77,7 +79,8 @@ | |||
</template> | |||
</el-table-column> | |||
<el-table-column v-if="pageCfg.page.columns.indexOf('clusterAndComputeResource') >= 0" | |||
:label="$t('cloudbrainObj.clusterAndComputeResource')" align="center" header-align="center" min-width="150"> | |||
:label="$t('cloudbrainObj.clusterAndComputeResource')" align="center" header-align="center" | |||
min-width="150"> | |||
<template slot-scope="scope"> | |||
<span>{{ scope.row.task.clusterName }} {{ scope.row.task.computeSourceShow }}</span> | |||
</template> | |||
@@ -102,36 +105,37 @@ | |||
<a href="javascript:;" v-if="pageCfg.page.operations.indexOf('onlineInfer') >= 0" | |||
@click="opDebug(scope.row)" | |||
:class="scope.row.can_modify && scope.row.task.canDebug ? '' : 'disabled'">{{ | |||
$t('onlineinfer') | |||
}}</a> | |||
$t('onlineinfer') | |||
}}</a> | |||
<a href="javascript:;" v-if="pageCfg.page.operations.indexOf('debug') >= 0 && scope.row.task.canDebug" | |||
@click="opDebug(scope.row)" | |||
:class="scope.row.can_modify && scope.row.task.canDebug ? '' : 'disabled'">{{ | |||
$t('cloudbrainObj.debug') | |||
}}</a> | |||
$t('cloudbrainObj.debug') | |||
}}</a> | |||
<a href="javascript:;" | |||
v-if="pageCfg.page.operations.indexOf('redebug') >= 0 && !scope.row.task.canDebug && !scope.row.task.is_file_notebook" | |||
@click="opReDebug(scope.row)" | |||
:class="scope.row.can_modify && scope.row.task.canReDebug ? '' : 'disabled'">{{ | |||
$t('cloudbrainObj.reDebug') }}</a> | |||
$t('cloudbrainObj.reDebug') }}</a> | |||
<a href="javascript:;" v-if="pageCfg.page.operations.indexOf('stop') >= 0" @click="opStop(scope.row)" | |||
:class="scope.row.can_delete && scope.row.task.canStop ? '' : 'disabled'">{{ $t('cloudbrainObj.stop') | |||
}}</a> | |||
:class="scope.row.can_delete && scope.row.task.canStop ? '' : 'disabled'">{{ | |||
$t('cloudbrainObj.stop') | |||
}}</a> | |||
<a href="javascript:;" | |||
v-if="pageCfg.page.operations.indexOf('modify') >= 0 && scope.row.task.can_modify && !scope.row.task.is_fine_tune_task" | |||
@click="opModify(scope.row)" | |||
:class="scope.row.can_modify && scope.row.task.canModify ? '' : 'disabled'">{{ | |||
$t('cloudbrainObj.modify') | |||
}}</a> | |||
$t('cloudbrainObj.modify') | |||
}}</a> | |||
<a href="javascript:;" v-if="pageCfg.page.operations.indexOf('download') >= 0" | |||
@click="opDownload(scope.row)" | |||
:class="scope.row.can_delete && scope.row.task.canDelete ? '' : 'disabled'">{{ | |||
$t('cloudbrainObj.modelDownload') | |||
}}</a> | |||
$t('cloudbrainObj.modelDownload') | |||
}}</a> | |||
<a href="javascript:;" v-if="pageCfg.page.operations.indexOf('delete') >= 0" | |||
@click="opDelete(scope.row)" | |||
:class="scope.row.can_delete && scope.row.task.canDelete ? '' : 'disabled'">{{ | |||
$t('cloudbrainObj.delete') }}</a> | |||
$t('cloudbrainObj.delete') }}</a> | |||
<el-dropdown size="default" trigger="click" | |||
v-if="pageCfg.page.operations.indexOf('debugMore') >= 0 && scope.row.can_modify && scope.row.task.hasDebugMore"> | |||
<span class="el-dropdown-link"> | |||
@@ -139,7 +143,8 @@ | |||
</span> | |||
<el-dropdown-menu slot="dropdown"> | |||
<el-dropdown-item :disabled="!scope.row.task.canSaveImage"><a target="_blank" | |||
:href="scope.row.task.saveImageUrl">{{ $t('cloudbrainObj.commitImage') }}</a></el-dropdown-item> | |||
:href="scope.row.task.saveImageUrl">{{ $t('cloudbrainObj.commitImage') | |||
}}</a></el-dropdown-item> | |||
<el-dropdown-item v-if="scope.row.task.canDownloadModel"><a target="_blank" | |||
:href="scope.row.task.downloadModelUrl">{{ $t('cloudbrainObj.downloadModel') | |||
}}</a></el-dropdown-item> | |||
@@ -431,7 +436,8 @@ export default { | |||
opModify(row) { | |||
if (this.operating) return; | |||
const task = row.task; | |||
window.location.href = `/${task.repoOwnerName}/${task.repoName}/${task.createPageUrl}?modify=true&id=${task.id}`; | |||
const url = `/${task.repoOwnerName}/${task.repoName}/${task.createPageUrl}`; | |||
window.location.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + `modify=true&id=${task.id}`; | |||
}, | |||
opDelete(row) { | |||
if (this.operating) return; | |||
@@ -621,7 +627,8 @@ export default { | |||
display: flex; | |||
align-items: center; | |||
i { | |||
i, | |||
span { | |||
margin-right: 4px; | |||
} | |||
} | |||
@@ -722,6 +729,7 @@ export default { | |||
color: #a6a6a6; | |||
line-height: 22px; | |||
margin-bottom: 4px; | |||
white-space: pre-wrap; | |||
} | |||
} | |||
} | |||
@@ -0,0 +1,736 @@ | |||
<template> | |||
<div :class="isAdminPage ? 'admin-page' : ''"> | |||
<div v-if="!isAdminPage" class="searchbar-c"> | |||
<div class="ui container"> | |||
<div class="ui two column centered grid"> | |||
<div class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" | |||
style="margin-top:1.2rem"> | |||
<div class="ui fluid action input"> | |||
<input v-model="conds.q" :placeholder="$t('cloudbrainObj.searchTaskName')" autofocus | |||
@keyup.enter="search" /> | |||
<button class="ui green button" @click="search">{{ $t('repos.search') }}</button> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div v-if="isAdminPage" class="ui attached segment"> | |||
<div class="ui form ignore-dirty" style="max-width: 90%"> | |||
<div class="ui fluid action input"> | |||
<input v-model="conds.q" :placeholder="$t('cloudbrainObj.searchTaskNameOrCreator')" autofocus | |||
@keyup.enter="search" /> | |||
<button class="ui blue button" @click="search">{{ $t('repos.search') }}</button> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="content"> | |||
<div class="tips" v-if="!isAdminPage" v-html="$t('cloudbrainObj.maxTaskTips')"></div> | |||
<div class="list-head"> | |||
<div class="filters-c"> | |||
<el-select v-model="conds.cluster" @change="changeConds"> | |||
<el-option v-for="(item) in clusterList" :key="item.k" :value="item.k" :label="item.v"></el-option> | |||
</el-select> | |||
<el-select v-model="conds.aicenter" @change="changeConds"> | |||
<el-option v-for="(item) in aicenterList" :key="item.k" :value="item.k" :label="item.v"></el-option> | |||
</el-select> | |||
<el-select v-model="conds.taskType" @change="changeConds"> | |||
<el-option v-for="(item) in taskTypeList" :key="item.k" :value="item.k" :label="item.v"></el-option> | |||
</el-select> | |||
<el-select v-model="conds.computeResource" @change="changeConds"> | |||
<el-option v-for="(item) in computeResourceList" :key="item.k" :value="item.k" :label="item.v"></el-option> | |||
</el-select> | |||
<el-select v-model="conds.status" @change="changeConds"> | |||
<el-option v-for="(item) in statusList" :key="item.k" :value="item.k" :label="item.v"></el-option> | |||
</el-select> | |||
</div> | |||
<div class="right"> | |||
<a v-if="isAdminPage" class="ui compact blue basic icon button" | |||
style="box-shadow: none !important; padding: 0.8em;" href="/admin/cloudbrains/download"><i | |||
class="ri-download-line middle aligned icon"></i>{{ $t('cloudbrainObj.downloadReport') }}</a> | |||
</div> | |||
</div> | |||
<div class="list-body table-container" v-loading="loading"> | |||
<el-table :data="tableData" style="min-width:100%" v-loading="loading" stripe> | |||
<el-table-column :label="$t('cloudbrainObj.taskName')" align="left" header-align="left" width="240"> | |||
<template slot-scope="scope"> | |||
<a class="dispaly-job-name" :href="scope.row.task.jobLink"> | |||
{{ scope.row.task.display_job_name }} | |||
</a> | |||
</template> | |||
</el-table-column> | |||
<el-table-column :label="$t('cloudbrainObj.cluster')" align="center" header-align="center" width="125"> | |||
<template slot-scope="scope"> | |||
<span>{{ scope.row.task.clusterName }}</span> | |||
</template> | |||
</el-table-column> | |||
<el-table-column prop="Status" :label="$t('status')" align="left" header-align="center" width="140"> | |||
<template slot-scope="scope"> | |||
<div class="status-wrap"> | |||
<i :class="scope.row.task.status"></i> | |||
<span>{{ scope.row.task.status }}</span> | |||
<i v-if="scope.row.task.detailed_status === 'dataMigrating' && scope.row.task.status === 'WAITING'" | |||
:class="scope.row.task.detailed_status" :title="$t('cloudbrainObj.migratingData')"></i> | |||
<i v-if="scope.row.task.detailed_status === 'centerPending' && scope.row.task.status === 'WAITING'" | |||
:class="scope.row.task.detailed_status" :title="$t('cloudbrainObj.centerPending')"></i> | |||
<i v-if="scope.row.task.detailed_status === 'ImagePulling' && scope.row.task.status === 'WAITING'" | |||
:class="scope.row.task.detailed_status" :title="$t('cloudbrainObj.imagePulling')"></i> | |||
</div> | |||
</template> | |||
</el-table-column> | |||
<el-table-column :label="$t('cloudbrainObj.cloudbrainTaskType')" align="center" header-align="center" | |||
width="125"> | |||
<template slot-scope="scope"> | |||
<span>{{ scope.row.task.jobTypeShow }}</span> | |||
</template> | |||
</el-table-column> | |||
<el-table-column prop="created_unix" :label="$t('cloudbrainObj.createTime')" align="center" | |||
header-align="center" width="190"> | |||
<template slot-scope="scope"> | |||
<span>{{ dateFormat(scope.row.task.created_unix) }}</span> | |||
</template> | |||
</el-table-column> | |||
<el-table-column prop="formatted_duration" :label="$t('cloudbrainObj.runDuration')" align="center" | |||
header-align="center" width="110"> | |||
<template slot-scope="scope"> | |||
<span>{{ scope.row.task.formatted_duration }}</span> | |||
</template> | |||
</el-table-column> | |||
<el-table-column :label="$t('cloudbrainObj.computeResource')" align="center" header-align="center" | |||
width="160"> | |||
<template slot-scope="scope"> | |||
<span>{{ scope.row.task.computeSourceShow }}</span> | |||
</template> | |||
</el-table-column> | |||
<el-table-column :label="$t('resourcesManagement.aiCenter')" align="center" header-align="center" width="200"> | |||
<template slot-scope="scope"> | |||
<span>{{ scope.row.task.ai_center }}</span> | |||
</template> | |||
</el-table-column> | |||
<el-table-column :label="$t('resourcesManagement.accCardType')" align="center" header-align="center" | |||
width="150"> | |||
<template slot-scope="scope"> | |||
<span>{{ scope.row.task.acc_card_type }}</span> | |||
</template> | |||
</el-table-column> | |||
<el-table-column v-if="isAdminPage" :label="$t('modelManage.creator')" align="left" width="80" | |||
header-align="center"> | |||
<template slot-scope="scope"> | |||
<div class="creator-wrap"> | |||
<a :href="'/' + scope.row.creator.name" :title="scope.row.creator.full_name"> | |||
<img :src="scope.row.creator.rel_avatar_link"> | |||
</a> | |||
</div> | |||
</template> | |||
</el-table-column> | |||
<el-table-column :label="$t('cloudbrainObj.repo')" align="center" header-align="center" width="200"> | |||
<template slot-scope="scope"> | |||
<a class="row-repo" :href="`/${scope.row.task.repoOwnerName}/${scope.row.task.repoName}`"> | |||
{{ scope.row.task.repoOwnerName }}/{{ scope.row.task.repoName }} | |||
</a> | |||
</template> | |||
</el-table-column> | |||
<el-table-column v-if="isAdminPage" :label="$t('cloudbrainObj.cloudbrainTaskName')" align="center" | |||
header-align="center" width="210"> | |||
<template slot-scope="scope"> | |||
<span class="ui poping up clipboard" :id="`clipboard-${scope.row.task.jobNameShow}`" | |||
data-position="top center" data-variation="inverted tiny" :data-success="$t('copySuccess')" | |||
:data-content="$t('copy')" :data-original="$t('copy')" | |||
:data-clipboard-text="scope.row.task.jobNameShow"> | |||
<span :title="scope.row.task.jobNameShow" style="cursor:pointer;"> | |||
{{ scope.row.task.jobNameShow }} | |||
</span> | |||
</span> | |||
</template> | |||
</el-table-column> | |||
<el-table-column prop="operation" :label="$t('operation')" align="left" width="280" header-align="center" | |||
fixed="right"> | |||
<template slot-scope="scope"> | |||
<div class="op-wrap"> | |||
<a href="javascript:;" v-if="scope.row.task.operations.indexOf('onlineInfer') >= 0" | |||
@click="opDebug(scope.row)" | |||
:class="scope.row.can_modify && scope.row.task.canDebug ? '' : 'disabled'">{{ | |||
$t('onlineinfer') | |||
}}</a> | |||
<a href="javascript:;" v-if="scope.row.task.operations.indexOf('debug') >= 0 && scope.row.task.canDebug" | |||
@click="opDebug(scope.row)" | |||
:class="scope.row.can_modify && scope.row.task.canDebug ? '' : 'disabled'">{{ | |||
$t('cloudbrainObj.debug') | |||
}}</a> | |||
<a href="javascript:;" | |||
v-if="scope.row.task.operations.indexOf('start') >= 0 && scope.row.can_modify && scope.row.task.canDebug" | |||
@click="opDebug(scope.row)" | |||
:class="scope.row.can_modify && scope.row.task.canDebug ? '' : 'disabled'">{{ | |||
$t('cloudbrainObj.startUse') | |||
}}</a> | |||
<a href="javascript:;" | |||
v-if="scope.row.task.operations.indexOf('redebug') >= 0 && !scope.row.task.canDebug && !scope.row.task.is_file_notebook" | |||
@click="opReDebug(scope.row)" | |||
:class="scope.row.can_modify && scope.row.task.canReDebug ? '' : 'disabled'">{{ | |||
$t('cloudbrainObj.reDebug') }}</a> | |||
<a href="javascript:;" v-if="scope.row.task.operations.indexOf('stop') >= 0" @click="opStop(scope.row)" | |||
:class="scope.row.can_delete && scope.row.task.canStop ? '' : 'disabled'">{{ $t('cloudbrainObj.stop') | |||
}}</a> | |||
<a href="javascript:;" | |||
v-if="scope.row.task.operations.indexOf('modify') >= 0 && scope.row.task.can_modify && !scope.row.task.is_fine_tune_task" | |||
@click="opModify(scope.row)" | |||
:class="scope.row.can_modify && scope.row.task.canModify ? '' : 'disabled'">{{ | |||
$t('cloudbrainObj.modify') | |||
}}</a> | |||
<a href="javascript:;" v-if="scope.row.task.operations.indexOf('delete') >= 0" | |||
@click="opDelete(scope.row)" | |||
:class="scope.row.can_delete && scope.row.task.canDelete ? '' : 'disabled'">{{ | |||
$t('cloudbrainObj.delete') }}</a> | |||
<el-dropdown size="default" trigger="click" | |||
v-if="scope.row.task.operations.indexOf('debugMore') >= 0 && scope.row.can_modify && scope.row.task.hasDebugMore"> | |||
<span class="el-dropdown-link"> | |||
{{ $t('cloudbrainObj.more') }}<i class="el-icon-arrow-down el-icon--right"></i> | |||
</span> | |||
<el-dropdown-menu slot="dropdown"> | |||
<el-dropdown-item :disabled="!scope.row.task.canSaveImage"><a target="_blank" | |||
:href="scope.row.task.saveImageUrl">{{ $t('cloudbrainObj.commitImage') }}</a></el-dropdown-item> | |||
<el-dropdown-item v-if="scope.row.task.canDownloadModel"><a target="_blank" | |||
:href="scope.row.task.downloadModelUrl">{{ $t('cloudbrainObj.downloadModel') | |||
}}</a></el-dropdown-item> | |||
</el-dropdown-menu> | |||
</el-dropdown> | |||
</div> | |||
</template> | |||
</el-table-column> | |||
</el-table> | |||
</div> | |||
<div class="list-foot"> | |||
<el-pagination ref="paginationRef" background @current-change="currentChange" @size-change="sizeChange" | |||
:current-page.sync="page" :page-sizes="pageSizes" :page-size.sync="pageSize" | |||
layout="total, sizes, prev, pager, next, jumper" :total="total"> | |||
</el-pagination> | |||
</div> | |||
</div> | |||
<LoadingMask :loading="maskLoading" :content="maskLoadingContent"></LoadingMask> | |||
</div> | |||
</template> | |||
<script> | |||
import LoadingMask from '~/components/cloudbrain/LoadingMask.vue'; | |||
import { timeSinceUnix, getListValueWithKey } from '~/utils'; | |||
import { CloudBrainTools } from '../tools'; | |||
import { CLUSTERS, COMPUTER_RESOURCES, JOB_TYPE } from '~/const'; | |||
import { getMyAiTasks, getAdminAiTasks, getAiTaskDebugUrl, getAiTaskRestart, stopAiTask, deleteAiTask } from '~/apis/modules/cloudbrain'; | |||
import { getAiCenterList, commonFormPost } from '~/apis/modules/common'; | |||
import { getCreatePageConfigsByTask } from '../configs'; | |||
import relativeTime from 'dayjs/plugin/relativeTime'; | |||
import localizedFormat from 'dayjs/plugin/localizedFormat'; | |||
import 'dayjs/locale/zh-cn'; | |||
import 'dayjs/locale/en'; | |||
import dayjs from 'dayjs'; | |||
import { lang } from '~/langs'; | |||
dayjs.locale(lang == 'zh-CN' ? 'zh-cn' : 'en'); | |||
dayjs.extend(relativeTime); | |||
dayjs.extend(localizedFormat); | |||
const cloudBrainTools = new CloudBrainTools(); | |||
const OperationsMap = { | |||
DEBUG: ['debug', 'redebug', 'stop', 'delete'], | |||
TRAIN: ['stop', 'modify', 'delete'], | |||
INFERENCE: ['stop', 'delete'], | |||
BENCHMARK: ['stop', 'delete'], | |||
SIM2BRAIN_SNN: ['stop', 'delete'], | |||
SNN4ECOSET: ['stop', 'delete'], | |||
SNN4IMAGENET: ['stop', 'delete'], | |||
BRAINSCORE: ['stop', 'delete'], | |||
MODELSAFETY: ['stop', 'delete'], | |||
ONLINEINFERENCE: ['onlineInfer', 'stop', 'delete'], | |||
HPC: ['start', 'stop', 'delete'], | |||
GENERAL: ['debug', 'stop', 'modify', 'delete'], | |||
}; | |||
const BenchmarkTypeList = ['BENCHMARK', 'SIM2BRAIN_SNN', 'SNN4ECOSET', 'SNN4IMAGENET', 'BRAINSCORE', 'MODELSAFETY']; | |||
const UseJobStatusList = ['STARTING', 'RUNNING', 'RESTARTING', 'START_FAILED', 'STOPPING', 'STOPPED', | |||
'WAITING', 'COMPLETED', 'SUCCEEDED', 'FAILED', 'KILLED', 'CREATED_FAILED' | |||
]; | |||
export default { | |||
data() { | |||
return { | |||
isAdminPage: true, | |||
conds: { | |||
q: '', | |||
cluster: '', | |||
aicenter: '', | |||
taskType: '', | |||
computeResource: '', | |||
status: '', | |||
}, | |||
clusterList: [{ k: '', v: this.$t('resourcesManagement.allCluster') }, ...CLUSTERS], | |||
aicenterList: [{ k: '', v: this.$t('resourcesManagement.allAiCenter') }], | |||
taskTypeList: [{ k: '', v: this.$t('resourcesManagement.allJobType') }, ...JOB_TYPE], | |||
computeResourceList: [{ k: '', v: this.$t('resourcesManagement.allComputeResource') }, ...COMPUTER_RESOURCES], | |||
statusList: [{ k: '', v: this.$t('resourcesManagement.allJobStatus') }, ...[...UseJobStatusList, 'other'] | |||
.map(item => ({ k: item, v: item.toLocaleUpperCase() }))], | |||
tableData: [], | |||
page: 1, | |||
pageSize: 10, | |||
total: 0, | |||
pageSizes: [10, 20, 30, 50], | |||
loading: false, | |||
maskLoading: false, | |||
maskLoadingContent: '', | |||
}; | |||
}, | |||
components: { LoadingMask }, | |||
methods: { | |||
getTableData() { | |||
this.loading = true; | |||
const params = { | |||
job_type: this.conds.taskType, | |||
job_status: this.conds.status, | |||
ai_center: this.conds.aicenter, | |||
cluster: this.conds.cluster == 'OpenI' ? 'resource_cluster_openi' : this.conds.cluster == 'C2Net' ? 'resource_cluster_c2net' : this.conds.cluster, | |||
compute_source: this.conds.computeResource, | |||
q: this.conds.q, | |||
page: this.page, | |||
pageSize: this.pageSize, | |||
exclude_status: this.conds.status == 'other' ? UseJobStatusList.join(',') : undefined, | |||
}; | |||
const getApi = this.isAdminPage ? getAdminAiTasks : getMyAiTasks; | |||
getApi(params).then(res => { | |||
this.loading = false; | |||
res = res.data; | |||
if (res.code == 0) { | |||
const data = res.data; | |||
this.canCreateTask = data.can_create_task; | |||
this.isRepoEmpty = data.is_repo_empty; | |||
this.total = data.total; | |||
data.tasks.forEach(item => { | |||
const obj = Object.assign({}, item); | |||
delete obj.task; | |||
const task = item.task; | |||
Object.assign(task, obj); | |||
task.computeSourceShow = task.compute_source == 'GPU' ? 'CPU/GPU' : task.compute_source; | |||
task.clusterName = getListValueWithKey(CLUSTERS, task.cluster); | |||
task.repoOwnerName = item.owner_name; | |||
task.repoName = item.repo_name; | |||
task.jobLink = `/${item.owner_name}/${item.repo_name}/${cloudBrainTools.getAiJobLink(task)}`; | |||
task.createdFromNow = this.calcFromNow(task.created_unix); | |||
task.jobNameShow = task.job_name; | |||
task.jobTypeShow = BenchmarkTypeList.indexOf(task.job_type) >= 0 ? this.$t('benchmarkTask') : getListValueWithKey(JOB_TYPE, task.job_type); | |||
task.operations = OperationsMap[task.job_type] || []; | |||
const taskCreatePageCfgList = getCreatePageConfigsByTask(task); | |||
if (taskCreatePageCfgList && taskCreatePageCfgList.length) { | |||
task.createPageUrl = taskCreatePageCfgList[0].url; | |||
} | |||
cloudBrainTools.checkOperation(task); | |||
}); | |||
this.tableData = data.tasks || []; | |||
cloudBrainTools.initRefreshData(this.tableData); | |||
} | |||
}).catch(err => { | |||
this.loading = false; | |||
console.log(err); | |||
}); | |||
}, | |||
search() { | |||
this.page = 1; | |||
this.getTableData(); | |||
}, | |||
changeConds() { | |||
this.page = 1; | |||
this.getTableData(); | |||
}, | |||
currentChange(page) { | |||
this.page = page; | |||
this.getTableData(); | |||
}, | |||
sizeChange(pageSize) { | |||
this.page = 1; | |||
this.pageSize = pageSize; | |||
this.getTableData(); | |||
}, | |||
calcFromNow(unix) { | |||
return timeSinceUnix(unix, Date.now() / 1000); | |||
}, | |||
dateFormat(unix) { | |||
return dayjs(unix * 1000).format('YYYY-MM-DD HH:mm:ss'); | |||
}, | |||
// operations | |||
opDebug(row) { | |||
if (this.operating) return; | |||
this.operating = true; | |||
getAiTaskDebugUrl({ | |||
repoOwnerName: row.task.repoOwnerName, | |||
repoName: row.task.repoName, | |||
id: row.task.id, | |||
}).then(res => { | |||
this.operating = false; | |||
res = res.data; | |||
if (res.code == 0) { | |||
if (res.data && res.data.url) { | |||
window.open(res.data.url) | |||
} | |||
} else { | |||
this.$message({ | |||
type: 'error', | |||
message: res.msg, | |||
}); | |||
} | |||
}).catch(err => { | |||
this.operating = false; | |||
console.log(err); | |||
}); | |||
}, | |||
opReDebug(row) { | |||
if (this.operating) return; | |||
this.operating = true; | |||
getAiTaskRestart({ | |||
repoOwnerName: row.task.repoOwnerName, | |||
repoName: row.task.repoName, | |||
id: row.task.id, | |||
}).then(res => { | |||
this.operating = false; | |||
res = res.data; | |||
if (res.code == 0) { | |||
this.page = 1; | |||
this.getTableData(); | |||
} else if (res.code == 2004) { | |||
this.taskAlreadyDialogShow = true; | |||
} else { | |||
this.$message({ | |||
type: 'error', | |||
message: res.msg, | |||
}); | |||
} | |||
}).catch(err => { | |||
this.operating = false; | |||
}); | |||
}, | |||
opStop(row) { | |||
if (this.operating) return; | |||
this.operating = true; | |||
if (BenchmarkTypeList.indexOf(row.task.job_type) >= 0) { | |||
let url = ''; | |||
if (row.task.job_type == 'MODELSAFETY') { | |||
url = `/${row.task.repoOwnerName}/${row.task.repoName}/modelsafety/${row.task.id}/stop`; | |||
} else if (row.task.job_type == 'BENCHMARK') { | |||
url = `/${row.task.repoOwnerName}/${row.task.repoName}/cloudbrain/benchmark/${row.task.id}/stop`; | |||
} else { | |||
url = `/${row.task.repoOwnerName}/${row.task.repoName}/cloudbrain/${row.task.id}/stop`; | |||
} | |||
url = url + (this.isAdminPage ? '?isadminpage=true' : ''); | |||
const formData = { id: row.task.id }; | |||
commonFormPost(url, formData).then(res => { | |||
this.operating = false; | |||
row.task.createdFromNow = this.calcFromNow(row.task.created_unix); | |||
cloudBrainTools.checkOperation(row.task); | |||
this.getTableData(); | |||
}).catch(err => { | |||
this.operating = false; | |||
this.$message({ | |||
type: 'error', | |||
message: this.$t('operationFailed'), | |||
}); | |||
}); | |||
} else { | |||
stopAiTask({ | |||
repoOwnerName: row.task.repoOwnerName, | |||
repoName: row.task.repoName, | |||
id: row.task.id, | |||
}).then(res => { | |||
this.operating = false; | |||
res = res.data; | |||
if (res.code == 0) { | |||
const data = res.data; | |||
Object.assign(row.task, data); | |||
row.task.createdFromNow = this.calcFromNow(row.task.created_unix); | |||
cloudBrainTools.checkOperation(row.task); | |||
} else { | |||
this.$message({ | |||
type: 'error', | |||
message: res.msg | |||
}); | |||
} | |||
}).catch(err => { | |||
this.operating = false; | |||
this.$message({ | |||
type: 'error', | |||
message: this.$t('operationFailed'), | |||
}); | |||
}); | |||
} | |||
}, | |||
opModify(row) { | |||
if (this.operating) return; | |||
const task = row.task; | |||
const url = `/${task.repoOwnerName}/${task.repoName}/${task.createPageUrl}`; | |||
window.location.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + `modify=true&id=${task.id}&backurl=${encodeURIComponent(window.location.href)}`; | |||
}, | |||
opDelete(row) { | |||
if (this.operating) return; | |||
this.$confirm(this.$t('cloudbrainObj.deleteConfirmTips'), this.$t('tips'), { | |||
confirmButtonText: this.$t('confirm'), | |||
cancelButtonText: this.$t('cancel'), | |||
type: 'warning' | |||
}).then(() => { | |||
this.operating = true; | |||
this.maskLoading = true; | |||
this.maskLoadingContent = this.$t('cloudbrainObj.deletingTips'); | |||
if (BenchmarkTypeList.indexOf(row.task.job_type) >= 0 | |||
|| (row.task.job_type == 'INFERENCE' && row.task.cluster == 'OpenI' | |||
&& (row.task.compute_source == 'GPU' || row.task.compute_source == 'CPU/GPU')) | |||
) { | |||
let url = ''; | |||
if (row.task.job_type == 'MODELSAFETY') { | |||
url = `/${row.task.repoOwnerName}/${row.task.repoName}/modelsafety/${row.task.id}/del`; | |||
} else if (row.task.job_type == 'BENCHMARK') { | |||
url = `/${row.task.repoOwnerName}/${row.task.repoName}/cloudbrain/benchmark/${row.task.id}/del`; | |||
} else { | |||
url = `/${row.task.repoOwnerName}/${row.task.repoName}/cloudbrain/${row.task.id}/del`; | |||
} | |||
url = url + (this.isAdminPage ? '?isadminpage=true' : ''); | |||
const formData = { id: row.task.id }; | |||
commonFormPost(url, formData).then(res => { | |||
this.operating = false; | |||
this.maskLoading = false; | |||
if (this.total % this.pageSize == 1 && this.page > 1) { | |||
this.page -= 1; | |||
} | |||
this.getTableData(); | |||
}).catch(err => { | |||
this.operating = false; | |||
this.maskLoading = false; | |||
this.$message({ | |||
type: 'error', | |||
message: this.$t('operationFailed'), | |||
}); | |||
}); | |||
} else { | |||
deleteAiTask({ | |||
repoOwnerName: row.task.repoOwnerName, | |||
repoName: row.task.repoName, | |||
id: row.task.id, | |||
}).then(res => { | |||
this.operating = false; | |||
this.maskLoading = false; | |||
if (this.total % this.pageSize == 1 && this.page > 1) { | |||
this.page -= 1; | |||
} | |||
this.getTableData(); | |||
}).catch(err => { | |||
this.maskLoading = false; | |||
this.operating = false; | |||
this.$message({ | |||
type: 'error', | |||
message: this.$t('operationFailed'), | |||
}); | |||
}); | |||
} | |||
}).catch(() => { | |||
this.$message({ | |||
type: 'info', | |||
message: this.$t('cancelOperate'), | |||
}); | |||
}); | |||
}, | |||
}, | |||
beforeMount() { | |||
this.isAdminPage = window.location.href.indexOf('admin/cloudbrains') >= 0; | |||
getAiCenterList().then(res => { | |||
res = res.data; | |||
if (res.Code == 0) { | |||
const data = res.Data || []; | |||
data.forEach(item => { | |||
this.aicenterList.push({ | |||
k: item.AiCenterCode, | |||
v: item.AiCenterName, | |||
}); | |||
}); | |||
} | |||
}).catch(err => { | |||
console.log(err); | |||
}); | |||
this.getTableData(); | |||
}, | |||
mounted() { }, | |||
beforeDestroy() { }, | |||
}; | |||
</script> | |||
<style scoped lang="less"> | |||
@import '~/components/cloudbrain/cloudbrain.less'; | |||
.searchbar-c { | |||
padding-top: 15px; | |||
padding-bottom: 15px; | |||
padding-left: 0; | |||
margin-bottom: 20px; | |||
background-color: #f5f5f6 !important; | |||
border-bottom: 1px solid rgba(34, 36, 38, 0.15); | |||
} | |||
.content { | |||
margin: 10px 40px; | |||
.tips { | |||
margin-top: 1.2rem; | |||
margin-bottom: 1.2rem; | |||
color: #888888; | |||
font-size: 14px; | |||
/deep/ span { | |||
color: #f2711c; | |||
} | |||
} | |||
.list-head { | |||
margin-top: 12px; | |||
margin-bottom: 12px; | |||
display: flex; | |||
align-items: center; | |||
justify-content: space-between; | |||
.filters-c { | |||
.el-select { | |||
margin-right: 12px; | |||
height: 36px; | |||
width: 200px; | |||
/deep/.el-input--small { | |||
height: 36px; | |||
} | |||
/deep/.el-input__inner { | |||
height: 36px; | |||
&:visited { | |||
border-color: #85b7d9; | |||
} | |||
&:focus { | |||
border-color: #85b7d9; | |||
} | |||
&:active { | |||
border-color: #85b7d9; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
.table-container { | |||
/deep/ .el-table__body { | |||
td { | |||
height: 64px; | |||
} | |||
} | |||
.dispaly-job-name { | |||
font-size: 14px; | |||
font-weight: bold; | |||
} | |||
.status-wrap { | |||
display: flex; | |||
align-items: center; | |||
i, | |||
span { | |||
margin-right: 4px; | |||
} | |||
} | |||
.creator-wrap { | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
img { | |||
height: 28px; | |||
width: 28px; | |||
border-radius: 100%; | |||
} | |||
} | |||
.row-repo { | |||
font-size: 14px; | |||
} | |||
.op-wrap { | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
a { | |||
margin: 0 10px; | |||
font-size: 14px; | |||
color: #1678c2; | |||
&.disabled { | |||
color: rgba(0, 0, 0, .87); | |||
} | |||
} | |||
.el-dropdown { | |||
margin: 0 10px; | |||
color: rgba(0, 0, 0, .87); | |||
cursor: pointer; | |||
} | |||
} | |||
} | |||
.list-foot { | |||
text-align: center; | |||
margin-top: 12px; | |||
} | |||
/deep/ .el-dropdown-menu__item { | |||
a { | |||
color: #1678c2; | |||
} | |||
&.is-disabled { | |||
color: rgba(0, 0, 0, .87); | |||
pointer-events: none; | |||
opacity: 0.45 !important; | |||
a { | |||
color: rgba(0, 0, 0, .87); | |||
pointer-events: none; | |||
opacity: 0.45 !important; | |||
} | |||
} | |||
} | |||
.admin-page { | |||
border: 1px solid #d4d4d5; | |||
margin-top: 0px; | |||
padding-top: 0; | |||
box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15); | |||
.content { | |||
margin: 10px 10px; | |||
.list-head { | |||
margin-top: 16px; | |||
margin-bottom: 22px; | |||
} | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,17 @@ | |||
import Vue from 'vue'; | |||
import ElementUI from 'element-ui'; | |||
import 'element-ui/lib/theme-chalk/index.css'; | |||
import localeEn from 'element-ui/lib/locale/lang/en'; | |||
import localeZh from 'element-ui/lib/locale/lang/zh-CN'; | |||
import { i18n, lang } from '~/langs'; | |||
import App from './index.vue'; | |||
Vue.use(ElementUI, { | |||
locale: lang === 'zh-CN' ? localeZh : localeEn, | |||
size: 'small', | |||
}); | |||
new Vue({ | |||
i18n, | |||
render: (h) => h(App), | |||
}).$mount('#__vue-root'); |
@@ -98,7 +98,7 @@ export class CloudBrainTools { | |||
} else { | |||
task.canDelete = false; | |||
} | |||
if ((task.compute_source == 'GPU' || task.compute_source == 'GCU' || task.compute_source == 'MLU'|| task.compute_source == 'ILUVATAR-GPGPU'|| task.compute_source == 'METAX-GPGPU') && task.job_type == 'DEBUG') { | |||
if ((task.compute_source == 'GPU' || task.compute_source == 'GCU' || task.compute_source == 'MLU' || task.compute_source == 'ILUVATAR-GPGPU' || task.compute_source == 'METAX-GPGPU') && task.job_type == 'DEBUG') { | |||
task.hasDebugMore = true; | |||
if (task.canDebug) { | |||
task.canSaveImage = true; | |||
@@ -126,12 +126,12 @@ export class CloudBrainTools { | |||
task.canSaveImage = false; | |||
task.canDownloadModel = false; | |||
} | |||
if (task.job_type == 'TRAIN') { | |||
if (task.job_type == 'TRAIN' || task.job_type == 'GENERAL') { | |||
task.canModify = true; | |||
if (task.is_fine_tune_task) { | |||
task.canModify = false; | |||
} | |||
if (task.can_download) { | |||
if (task.job_type == 'TRAIN' && task.can_download) { | |||
task.canExportOutput = true; | |||
} | |||
} | |||
@@ -173,6 +173,12 @@ export class CloudBrainTools { | |||
} | |||
break; | |||
case 'BENCHMARK': | |||
case 'BRAINSCORE': | |||
case 'SNN4IMAGENET': | |||
case 'SNN4ECOSET': | |||
case 'SIM2BRAIN_SNN': | |||
case 'MODELSAFETY': | |||
link += `cloudbrain/benchmark/${taskInfo.id}`; | |||
break; | |||
case 'ONLINEINFERENCE': | |||
if (taskInfo.cluster == 'OpenI') { | |||
@@ -188,6 +194,9 @@ export class CloudBrainTools { | |||
case 'HPC': | |||
link += `supercompute/job/${taskInfo.id}`; | |||
break; | |||
case 'GENERAL': | |||
link += `grampus/general/${taskInfo.id}`; | |||
break; | |||
default: | |||
break; | |||
} | |||
@@ -46,6 +46,19 @@ | |||
<el-form-item label="使用组织" prop="org"> | |||
<el-input v-model="form.org" placeholder="请输入平台组织账号,多个用英文分号;分隔" maxlength="255"></el-input> | |||
</el-form-item> | |||
<el-form-item label="是否用于科研项目" prop="is_research_project"> | |||
<el-radio v-model="form.is_research_project" :label="false">用于非科研项目</el-radio> | |||
<el-radio v-model="form.is_research_project" :label="true">用于科研项目</el-radio> | |||
</el-form-item> | |||
<el-form-item v-if="form.is_research_project" label="高校或科研机构名称" prop="institution_name"> | |||
<el-input v-model="form.institution_name" placeholder="请输入" maxlength="127"></el-input> | |||
</el-form-item> | |||
<el-form-item v-if="form.is_research_project" label="科研项目名称" prop="project_name"> | |||
<el-input v-model="form.project_name" placeholder="请输入" maxlength="127"></el-input> | |||
</el-form-item> | |||
<el-form-item v-if="form.is_research_project" label="科研项目编码" prop="project_code"> | |||
<el-input v-model="form.project_code" placeholder="请输入" maxlength="127"></el-input> | |||
</el-form-item> | |||
<el-form-item label="使用背景" prop="description"> | |||
<el-input type="textarea" v-model="form.description" placeholder="请输入算力使用需求,如背景介绍、具体使用场景等" | |||
maxlength="500"></el-input> | |||
@@ -55,7 +68,8 @@ | |||
</el-form-item> | |||
<el-form-item v-if="type == 'edit'" label="状态" prop="description"> | |||
<div class="status-c"> | |||
<span class="status pending" v-if="data.status == 1"><i class="el-icon-stopwatch"></i><span>待处理</span></span> | |||
<span class="status pending" v-if="data.status == 1"><i | |||
class="el-icon-stopwatch"></i><span>待处理</span></span> | |||
<span class="status accepted" v-if="data.status == 2"><i | |||
class="el-icon-circle-check"></i><span>已接纳</span></span> | |||
<span class="status refuse" v-if="data.status == 3"><i | |||
@@ -96,6 +110,10 @@ export default { | |||
phone_number: '', | |||
email_address: '', | |||
org: '', | |||
is_research_project: false, | |||
institution_name: '', | |||
project_name: '', | |||
project_code: '', | |||
description: '', | |||
}, | |||
formRules: { | |||
@@ -173,10 +191,14 @@ export default { | |||
trigger: 'blur', | |||
} | |||
], | |||
is_research_project: [{ required: true, message: ' ' }], | |||
institution_name: [{ required: true, message: ' ' }], | |||
project_name: [{ required: true, message: ' ' }], | |||
project_code: [{ required: true, message: ' ' }], | |||
}, | |||
computeResourceList: [], | |||
computeResourceCardTypeMap: { | |||
'GPU': ['A100', 'V100', 'T4'], | |||
'GPU': ['A100', 'V100', 'T4', '3090'], | |||
}, | |||
cardTypeList: [], | |||
resourceTypeList: [ | |||
@@ -242,6 +264,11 @@ export default { | |||
begin_date: formatDate(this.form.use_time[0], 'yyyy-MM-dd'), | |||
end_date: formatDate(this.form.use_time[1], 'yyyy-MM-dd'), | |||
}; | |||
if (!this.form.is_research_project) { | |||
submitData.institution_name = ''; | |||
submitData.project_name = ''; | |||
submitData.project_code = ''; | |||
} | |||
delete submitData['use_time']; | |||
if (this.type == 'add') { | |||
this._addDemand(submitData); | |||
@@ -351,6 +378,14 @@ export default { | |||
min-width: 20px; | |||
} | |||
} | |||
/deep/ .el-form-item__label { | |||
line-height: 20px; | |||
height: 40px; | |||
display: flex; | |||
align-items: center; | |||
justify-content: flex-end; | |||
} | |||
} | |||
.status-c { | |||
@@ -36,7 +36,8 @@ | |||
</div> | |||
</div> | |||
<div class="item-tab-c"> | |||
<div class="item-tab" :class="editTab == 'edit' ? 'focus' : ''" tab="edit" @click="changeEditTab('edit')"> | |||
<div class="item-tab" :class="editTab == 'edit' ? 'focus' : ''" tab="edit" | |||
@click="changeEditTab('edit')"> | |||
<svg class="svg octicon-code" width="16" height="16" aria-hidden="true"> | |||
<use xlink:href="#octicon-code"></use> | |||
</svg> | |||
@@ -59,7 +60,8 @@ | |||
</div> | |||
<div class="conmit-btn-c"> | |||
<el-button size="default" class="btn confirm-btn" :disabled="this.content == this.editContent" | |||
v-loading="submitLoading" :class="this.content == this.editContent ? '_disabled_' : ''" @click="submit"> | |||
v-loading="submitLoading" :class="this.content == this.editContent ? '_disabled_' : ''" | |||
@click="submit"> | |||
{{ $t('submit') }} </el-button> | |||
<el-button size="default" class="btn" @click="toggleEdit(false)">{{ $t('cancel') }}</el-button> | |||
</div> | |||
@@ -124,7 +126,7 @@ | |||
<!-- <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> | |||
$t('modelManage.onlineInference') }}</a> | |||
</div> | |||
</template> | |||
<template v-if="onlineAddressList.length"> | |||
@@ -161,7 +163,7 @@ | |||
<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" :key="item.jobName"> | |||
<div class="detail-address" v-for="(item, index) in modelUseTaskList" :key="index"> | |||
<li class="nowrap"> | |||
<a :href="item.url" :title="item.jobName">{{ item.jobName }}</a> | |||
</li> | |||
@@ -181,6 +183,9 @@ import { getUrlSearchParams, setWebpackPublicPath, getListValueWithKey, transFil | |||
import { getModelInfoByName, getMarkdownPreview, getModelIntroduce, setModelIntroduce, getModelLicenseList } from '~/apis/modules/modelmanage'; | |||
import { MODEL_ENGINES } from '~/const'; | |||
import { formatDate } from 'element-ui/lib/utils/date-util'; | |||
import { CloudBrainTools } from '~/pages/cloudbrain/tools'; | |||
const cloudBrainTools = new CloudBrainTools(); | |||
export default { | |||
data() { | |||
@@ -219,8 +224,6 @@ export default { | |||
trainUsedDataList: [], | |||
modelUseTaskList: [], | |||
onlineUrl: '', | |||
}; | |||
}, | |||
components: { ModelHeader, NotFound }, | |||
@@ -372,49 +375,14 @@ export default { | |||
getFullUrlForType(data) { | |||
const result = [] | |||
data.forEach(element => { | |||
const detailObj = { jobName: element.displayJobName } | |||
const detailObj = { ...element, 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}` | |||
} | |||
} | |||
element.job_type = element.jobType | |||
element.cluster = element.type == 2 ? 'C2Net' : 'OpenI' | |||
element.compute_source = element.computeResource == 'CPU/GPU' ? 'GPU' : element.computeResource | |||
detailObj.url = `/${prefixRepoLink}/${cloudBrainTools.getAiJobLink(element)}` | |||
result.push(detailObj) | |||
}); | |||
return result | |||
} | |||
}, | |||
@@ -66,6 +66,9 @@ const getJobTypeLink = (record, type) => { | |||
case 'HPC': | |||
link += `/supercompute/job/${cloudbrain.ID}`; | |||
break; | |||
case 'GENERAL': | |||
link += `/grampus/general/${cloudbrain.ID}`; | |||
break; | |||
default: | |||
break; | |||
}; | |||
Dear OpenI User
Thank you for your continuous support to the Openl Qizhi Community AI Collaboration Platform. In order to protect your usage rights and ensure network security, we updated the Openl Qizhi Community AI Collaboration Platform Usage Agreement in January 2024. The updated agreement specifies that users are prohibited from using intranet penetration tools. After you click "Agree and continue", you can continue to use our services. Thank you for your cooperation and understanding.
For more agreement content, please refer to the《Openl Qizhi Community AI Collaboration Platform Usage Agreement》