#3044 V20221019

Merged
ychao_1983 merged 299 commits from V20221019 into develop 1 year ago
  1. +1
    -1
      Makefile
  2. +0
    -1
      models/action.go
  3. +39
    -23
      models/cloudbrain.go
  4. +31
    -1
      models/cloudbrain_static.go
  5. +1
    -1
      models/repo.go
  6. +249
    -0
      modules/aisafety/resty.go
  7. +13
    -13
      modules/cloudbrain/cloudbrain.go
  8. +17
    -3
      modules/cron/tasks_basic.go
  9. +11
    -0
      modules/grampus/grampus.go
  10. +21
    -11
      modules/modelarts/modelarts.go
  11. +2
    -1
      modules/repository/create.go
  12. +37
    -1
      modules/setting/setting.go
  13. +0
    -30
      modules/timer/timer.go
  14. +27
    -6
      options/locale/locale_en-US.ini
  15. +27
    -8
      options/locale/locale_zh-CN.ini
  16. +6
    -4
      public/home/home.js
  17. BIN
      public/img/origin.png
  18. BIN
      public/img/tuomin.png
  19. +7
    -5
      routers/admin/cloudbrains.go
  20. +2
    -0
      routers/admin/resources.go
  21. +1
    -0
      routers/api/v1/api.go
  22. +191
    -47
      routers/api/v1/repo/cloudbrain.go
  23. +178
    -157
      routers/api/v1/repo/cloudbrain_dashboard.go
  24. +2
    -1
      routers/api/v1/repo/fork.go
  25. +78
    -0
      routers/modelapp/desensitization.go
  26. +13
    -0
      routers/repo/ai_model_manage.go
  27. +1049
    -0
      routers/repo/aisafety.go
  28. +55
    -124
      routers/repo/cloudbrain.go
  29. +3
    -3
      routers/repo/editor.go
  30. +5
    -5
      routers/repo/grampus.go
  31. +6
    -5
      routers/repo/modelarts.go
  32. +2
    -1
      routers/repo/repo.go
  33. +2
    -1
      routers/repo/setting.go
  34. +3
    -2
      routers/repo/setting_protected_branch.go
  35. +20
    -4
      routers/routes/routes.go
  36. +1
    -5
      routers/user/home.go
  37. +58
    -23
      templates/admin/cloudbrain/list.tmpl
  38. +1
    -0
      templates/admin/cloudbrain/search.tmpl
  39. +15
    -1
      templates/base/head_navbar.tmpl
  40. +14
    -0
      templates/base/head_navbar_fluid.tmpl
  41. +14
    -0
      templates/base/head_navbar_home.tmpl
  42. +14
    -0
      templates/base/head_navbar_pro.tmpl
  43. +13
    -0
      templates/model/tuomin/upload.tmpl
  44. +0
    -80
      templates/org/member/members.tmpl
  45. +43
    -10
      templates/repo/cloudbrain/benchmark/index.tmpl
  46. +75
    -1
      templates/repo/cloudbrain/benchmark/new.tmpl
  47. +1
    -1
      templates/repo/cloudbrain/trainjob/show.tmpl
  48. +1
    -1
      templates/repo/grampus/trainjob/show.tmpl
  49. +14
    -3
      templates/repo/modelarts/notebook/show.tmpl
  50. +16
    -20
      templates/repo/modelarts/trainjob/new.tmpl
  51. +3
    -4
      templates/repo/modelarts/trainjob/show.tmpl
  52. +2
    -2
      templates/repo/modelmanage/convertIndex.tmpl
  53. +2
    -2
      templates/repo/modelmanage/showinfo.tmpl
  54. +63
    -0
      templates/repo/modelsafety/indicators_descr.tmpl
  55. +469
    -0
      templates/repo/modelsafety/new.tmpl
  56. +1
    -0
      templates/repo/modelsafety/newgpu.tmpl
  57. +1
    -0
      templates/repo/modelsafety/newnpu.tmpl
  58. +893
    -0
      templates/repo/modelsafety/show.tmpl
  59. +69
    -36
      templates/user/dashboard/cloudbrains.tmpl
  60. +2
    -1
      web_src/js/components/dataset/selectDataset.vue
  61. +2
    -1
      web_src/js/components/images/selectGrampusImages.vue
  62. +3
    -1
      web_src/js/components/images/selectImages.vue
  63. +4
    -0
      web_src/js/features/cloudbrainShow.js
  64. +3
    -1
      web_src/js/features/cloudrbanin.js
  65. +1
    -0
      web_src/js/index.js
  66. +3
    -2
      web_src/js/standalone/cloudbrainNew.js
  67. +13
    -0
      web_src/vuepages/apis/modules/desensitization.js
  68. +16
    -0
      web_src/vuepages/langs/config/en-US.js
  69. +16
    -0
      web_src/vuepages/langs/config/zh-CN.js
  70. +380
    -0
      web_src/vuepages/pages/model/tuomin/index.vue
  71. +17
    -0
      web_src/vuepages/pages/model/tuomin/vp-model-tuomin.js
  72. +8
    -8
      web_src/vuepages/pages/resources/specification/index.vue
  73. +4
    -0
      web_src/vuepages/pages/reward/point/utils.js

+ 1
- 1
Makefile View File

@@ -85,7 +85,7 @@ LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(G

GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/integrations/migration-test,$(filter-out code.gitea.io/gitea/integrations,$(shell $(GO) list -mod=vendor ./... | grep -v /vendor/)))

WEBPACK_SOURCES := $(shell find web_src/js web_src/less -type f)
WEBPACK_SOURCES := $(shell find web_src/js web_src/less web_src/vuepages -type f)
WEBPACK_CONFIGS := webpack.config.js
WEBPACK_CONFIGS_TMP := webpack_temp.config.js
WEBPACK_CONFIGS_PRO := webpack_pro.config.js


+ 0
- 1
models/action.go View File

@@ -65,7 +65,6 @@ const (
ActionCreateImage //36
ActionImageRecommend //37
ActionChangeUserAvatar //38

)

// Action represents user operation type and other information to


+ 39
- 23
models/cloudbrain.go View File

@@ -53,8 +53,11 @@ const (
JobFailed CloudbrainStatus = "FAILED"
JobRunning CloudbrainStatus = "RUNNING"

ModelSafetyTesting CloudbrainStatus = "TESTING"

JobTypeDebug JobType = "DEBUG"
JobTypeBenchmark JobType = "BENCHMARK"
JobTypeModelSafety JobType = "MODELSAFETY"
JobTypeSnn4imagenet JobType = "SNN4IMAGENET"
JobTypeBrainScore JobType = "BRAINSCORE"
JobTypeTrain JobType = "TRAIN"
@@ -172,26 +175,26 @@ type Cloudbrain struct {
ImageID string //grampus image_id
AiCenter string //grampus ai center: center_id+center_name

TrainUrl string //输出模型的obs路径
BranchName string //分支名称
Parameters string //传给modelarts的param参数
BootFile string //启动文件
DataUrl string //数据集的obs路径
LogUrl string //日志输出的obs路径
PreVersionId int64 //父版本的版本id
FlavorCode string //modelarts上的规格id
Description string `xorm:"varchar(256)"` //描述
WorkServerNumber int //节点数
FlavorName string //规格名称
EngineName string //引擎名称
TotalVersionCount int //任务的所有版本数量,包括删除的
LabelName string //标签名称
ModelName string //模型名称
ModelVersion string //模型版本
CkptName string //权重文件名称
PreTrainModelUrl string //预训练模型地址
ResultUrl string //推理结果的obs路径
TrainUrl string //输出模型的obs路径
BranchName string //分支名称
Parameters string //传给modelarts的param参数
BootFile string //启动文件
DataUrl string //数据集的obs路径
LogUrl string //日志输出的obs路径
PreVersionId int64 //父版本的版本id
FlavorCode string //modelarts上的规格id
Description string `xorm:"varchar(256)"` //描述
WorkServerNumber int //节点数
FlavorName string //规格名称
EngineName string //引擎名称
TotalVersionCount int //任务的所有版本数量,包括删除的
LabelName string //标签名称
ModelName string //模型名称
ModelVersion string //模型版本
CkptName string //权重文件名称
PreTrainModelUrl string //预训练模型地址
ResultUrl string //推理结果的obs路径
ResultJson string `xorm:"varchar(4000)"`
User *User `xorm:"-"`
Repo *Repository `xorm:"-"`
BenchmarkType string `xorm:"-"` //算法评测,模型评测
@@ -1490,6 +1493,8 @@ type GrampusTasks struct {
ReplicaNum int `json:"replicaNum"`
Datasets []GrampusDataset `json:"datasets"`
Models []GrampusDataset `json:"models"`
Code GrampusDataset `json:"code"`
BootFile string `json:"bootFile"`
}

type GrampusDataset struct {
@@ -2003,6 +2008,13 @@ func GetStoppedJobWithNoStartTimeEndTime() ([]*Cloudbrain, error) {
return cloudbrains, x.SQL("select * from cloudbrain where status in (?,?,?,?,?,?,?) and (start_time is null or end_time is null) limit 100", ModelArtsTrainJobCompleted, ModelArtsTrainJobFailed, ModelArtsTrainJobKilled, ModelArtsStopped, JobStopped, JobFailed, JobSucceeded).Find(&cloudbrains)
}

func GetModelSafetyTestTask() ([]*Cloudbrain, error) {
cloudbrains := make([]*Cloudbrain, 0)
sess := x.Where("job_type = ?", string(JobTypeModelSafety))
err := sess.Find(&cloudbrains)
return cloudbrains, err
}

func GetCloudbrainCountByUserID(userID int64, jobType string) (int, error) {
count, err := x.In("status", JobWaiting, JobRunning).And("job_type = ? and user_id = ? and type = ?", jobType, userID, TypeCloudBrainOne).Count(new(Cloudbrain))
return int(count), err
@@ -2017,7 +2029,12 @@ func GetCloudbrainRunCountByRepoID(repoID int64) (int, error) {
}

func GetBenchmarkCountByUserID(userID int64) (int, error) {
count, err := x.In("status", JobWaiting, JobRunning).And("(job_type = ? or job_type = ? or job_type = ?) and user_id = ? and type = ?", string(JobTypeBenchmark), string(JobTypeBrainScore), string(JobTypeSnn4imagenet), userID, TypeCloudBrainOne).Count(new(Cloudbrain))
count, err := x.In("status", JobWaiting, JobRunning).And("(job_type = ? or job_type = ? or job_type = ?) and user_id = ? and type = ?", string(JobTypeBenchmark), string(JobTypeModelSafety), string(JobTypeBrainScore), string(JobTypeSnn4imagenet), userID, TypeCloudBrainOne).Count(new(Cloudbrain))
return int(count), err
}

func GetModelSafetyCountByUserID(userID int64) (int, error) {
count, err := x.In("status", JobWaiting, JobRunning).And("job_type = ? and user_id = ?", string(JobTypeModelSafety), userID).Count(new(Cloudbrain))
return int(count), err
}

@@ -2281,8 +2298,7 @@ func CloudbrainAllStatic(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, er
}
sess.OrderBy("cloudbrain.created_unix DESC")
cloudbrains := make([]*CloudbrainInfo, 0, setting.UI.IssuePagingNum)
if err := sess.Cols("status", "type", "job_type", "train_job_duration", "duration", "compute_resource",
"created_unix", "start_time", "end_time").Table(&Cloudbrain{}).Unscoped().Where(cond).
if err := sess.Table(&Cloudbrain{}).Unscoped().Where(cond).
Find(&cloudbrains); err != nil {
return nil, 0, fmt.Errorf("Find: %v", err)
}


+ 31
- 1
models/cloudbrain_static.go View File

@@ -34,6 +34,7 @@ type TaskDetail struct {
CardDuration string `json:"CardDuration"`
AiCenter string `json:"AiCenter"`
FlavorName string `json:"FlavorName"`
WorkServerNum int64 `json:"WorkServerNum"`
Spec *Specification `json:"Spec"`
}

@@ -44,16 +45,45 @@ func GetTodayCreatorCount(beginTime time.Time, endTime time.Time) (int64, error)
return x.SQL(countSql).Count()
}
func GetTodayCloudbrainCount(beginTime time.Time, endTime time.Time) (int64, error) {
countSql := "SELECT count FROM " +
countSql := "SELECT count(*) FROM " +
"public.cloudbrain where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) +
" and created_unix<=" + strconv.FormatInt(endTime.Unix(), 10)
return x.SQL(countSql).Count()
}
func GetTodayRunningCount(beginTime time.Time, endTime time.Time) (int64, error) {
countSql := "SELECT count(*) FROM " +
"public.cloudbrain where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) +
" and created_unix<=" + strconv.FormatInt(endTime.Unix(), 10) + " and (status='" + string(JobRunning) + "'" +
" or status='" + string(ModelArtsTrainJobInit) + "')"
return x.SQL(countSql).Count()
}
func GetTodayWaitingCount(beginTime time.Time, endTime time.Time) (int64, error) {
countSql := "SELECT count(*) FROM " +
"public.cloudbrain where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) +
" and created_unix<=" + strconv.FormatInt(endTime.Unix(), 10) + " and status='" + string(JobWaiting) + "'"
return x.SQL(countSql).Count()
}

func GetCreatorCount() (int64, error) {
countSql := "SELECT count(distinct user_id) FROM public.cloudbrain"
return x.SQL(countSql).Count()
}

func GetCloudbrainTypeCount() ([]map[string]string, error) {
countSql := "SELECT type,count(*) num FROM public.cloudbrain group by type order by num desc"
return x.QueryString(countSql)
}

func GetCloudbrainStatusCount() ([]map[string]string, error) {
countSql := "SELECT status,count(*) num FROM public.cloudbrain group by status order by num desc"
return x.QueryString(countSql)
}

func GetCloudbrainTpyeDurationSum() ([]map[string]string, error) {
countSql := "SELECT type,sum(duration) FROM public.cloudbrain group by type order by sum(duration) desc"
return x.QueryString(countSql)
}

func GetRecordBeginTime() ([]*CloudbrainInfo, error) {
sess := x.NewSession()
defer sess.Close()


+ 1
- 1
models/repo.go View File

@@ -679,7 +679,7 @@ func (repo *Repository) getAssignees(e Engine) (_ []*User, err error) {
userIDs[i] = accesses[i].UserID
}

if err = e.In("id", userIDs).Find(&users); err != nil {
if err = e.In("id", userIDs).OrderBy("name asc").Find(&users); err != nil {
return nil, err
}
}


+ 249
- 0
modules/aisafety/resty.go View File

@@ -0,0 +1,249 @@
package aisafety

import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"net/url"
"sort"
"strings"

"code.gitea.io/gitea/modules/log"

"github.com/go-resty/resty/v2"
)

var (
restyClient *resty.Client
HOST string
KEY string
)

type TaskReq struct {
UnionId string //评测任务ID,唯一标识,由后端生成UUID
EvalName string //评测任务名称
EvalContent string //评测任务描述
TLPath string //
Indicators []string //评测指标,由GetAlgorithmList接口返回的指标列表中的title属性值
CDPath string
CDName string //对抗数据集名称
BDPath string
BDName string //原数据集名称
}

type ReturnMsg struct {
Code string `json:"code"`
Msg string `json:"msg"`
Data ReturnData `json:"data"`
Times int64 `json:"times"`
}

type ReturnData struct {
ID int `json:"id"`
No string `json:"no"`
StandardJson string `json:"standardJson"`
Code int `json:"code"`
Msg string `json:"msg"`
Status int `json:"status"`
}

const (
APPID = "1"
LogPageSize = 500
LogPageTokenExpired = "5m"
pageSize = 15
Success = "S000"
)

func getRestyClient() *resty.Client {
if restyClient == nil {
restyClient = resty.New()
}
return restyClient
}

func checkSetting() {
if len(HOST) != 0 && len(KEY) != 0 {
return
}
_ = loginCloudbrain()
}

func loginCloudbrain() error {
HOST = "http://221.122.70.196:8081/atp-api"
KEY = "1"
return nil
}

func createSign(params map[string]interface{}, signKey string) string {
var sceneList []string
for k := range params {
sceneList = append(sceneList, k)
}
sort.Strings(sceneList)
re := ""
for _, key := range sceneList {
if params[key] != nil {
re += key + "=" + fmt.Sprint(params[key]) + "&"
}
}
re += "key=" + signKey
log.Info("sign key:" + re)
h := md5.New()
h.Write([]byte(re))
return strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
}

func getParams(req TaskReq) (map[string]interface{}, string) {
params := make(map[string]interface{})
reStr := ""

params["unionId"] = req.UnionId
reStr += "unionId=" + req.UnionId
params["evalName"] = req.EvalName
reStr += "&evalName=" + req.EvalName
params["evalContent"] = req.EvalContent
reStr += "&evalContent=" + url.QueryEscape(req.EvalContent)
params["TLPath"] = req.TLPath
reStr += "&TLPath=" + url.QueryEscape(req.TLPath)

params["CDName"] = req.CDName
reStr += "&CDName=" + url.QueryEscape(req.CDName)

params["BDName"] = req.BDName
reStr += "&BDName=" + url.QueryEscape(req.BDName)

if req.CDPath != "" {
params["CDPath"] = req.CDPath
reStr += "&CDPath=" + url.QueryEscape(req.CDPath)
}
if req.BDPath != "" {
params["BDPath"] = req.BDPath
reStr += "&BDPath=" + url.QueryEscape(req.BDPath)
}
indicators := ""
if len(req.Indicators) > 0 {
for _, tmp := range req.Indicators {
indicators += tmp + "|"
}
}
if len(indicators) > 0 {
indicators = indicators[0 : len(indicators)-1]
}

params["Indicators"] = indicators
log.Info("indicators=" + indicators)
reStr += "&Indicators=" + url.QueryEscape(indicators)

return params, reStr
}

func CreateSafetyTask(req TaskReq, jsonstr string) (string, error) {
checkSetting()
client := getRestyClient()

//reqPara, _ := json.Marshal(body)
//log.Warn("job req:", jsonstr)

params, urlQuerys := getParams(req)

bodyMap := make(map[string]interface{})
//reJsonMap := make(map[string]interface{})
bodyMap["resJson"] = jsonstr
//bodyMap["externalEvalParam"] = reJsonMap

//reqPara, _ := json.Marshal(bodyMap)
//log.Warn("job req json:", string(reqPara))

res, err := client.R().
SetHeader("Content-Type", "application/json").
SetHeader("appId", APPID).
SetHeader("sign", createSign(params, KEY)).
//SetAuthToken(TOKEN).
SetBody(bodyMap).
Post(HOST + "/v1/external/eval-standard/create?" + urlQuerys)
log.Info("url=" + HOST + "/v1/external/eval-standard/create?" + urlQuerys)

responseStr := string(res.Body())
log.Info("CreateSafetyTask responseStr=" + responseStr + " res code=" + fmt.Sprint(res.StatusCode()))

if err != nil {
return "", fmt.Errorf("resty create job: %s", err)
} else {
log.Info("result string=" + " res code=" + fmt.Sprint(res.StatusCode()))
}

reMap := make(map[string]interface{})

err = json.Unmarshal(res.Body(), &reMap)
if err == nil && reMap["code"] == "0" {
dataMap := (reMap["data"]).(map[string]interface{})
return fmt.Sprint(dataMap["serialNo"]), nil
}
return "", nil
}

func GetAlgorithmList() (map[string]interface{}, error) {
checkSetting()
client := getRestyClient()
params := make(map[string]interface{})

jsonResult := make(map[string]interface{})
sign := createSign(params, KEY)

res, err := client.R().
SetHeader("Content-Type", "application/json").
SetHeader("appId", APPID).
SetHeader("sign", sign).
Get(HOST + "/v1/external/eval-standard/algorithmList")

log.Info("url=" + HOST + "/v1/external/eval-standard/algorithmList" + " sign=" + sign + " appId=" + APPID)

jsonerr := json.Unmarshal(res.Body(), &jsonResult)
if jsonerr == nil {
log.Info("jsonResult code=" + fmt.Sprint(jsonResult["msg"]))
}
responseStr := string(res.Body())
log.Info("GetAlgorithmList responseStr=" + responseStr + " res code=" + fmt.Sprint(res.StatusCode()))

if err != nil {
log.Info("error =" + err.Error())
return nil, fmt.Errorf("resty GetJob: %v", err)
} else {
reMap := make(map[string]interface{})
err = json.Unmarshal(res.Body(), &reMap)
if err == nil && reMap["code"] == "0" {
return reMap, nil
} else {
return nil, fmt.Errorf("get error,code not 0")
}
}

}

func GetTaskStatus(jobID string) (*ReturnMsg, error) {
checkSetting()
client := getRestyClient()
var reMap ReturnMsg
params := make(map[string]interface{})
params["serialNo"] = jobID

res, err := client.R().
SetHeader("Content-Type", "application/json").
SetHeader("appId", APPID).
SetHeader("sign", createSign(params, KEY)).
SetResult(&reMap).
Get(HOST + "/v1/external/eval-standard/query?serialNo=" + jobID)

log.Info("url=" + HOST + "/v1/external/eval-standard/query?serialNo=" + jobID)
responseStr := string(res.Body())
log.Info("GetTaskStatus responseStr=" + responseStr + " res code=" + fmt.Sprint(res.StatusCode()))

if err != nil {
log.Info("error =" + err.Error())
return nil, fmt.Errorf("Get task status error: %v", err)
} else {
return &reMap, nil
}
}

+ 13
- 13
modules/cloudbrain/cloudbrain.go View File

@@ -20,19 +20,19 @@ import (
const (
//Command = `pip3 install jupyterlab==2.2.5 -i https://pypi.tuna.tsinghua.edu.cn/simple;service ssh stop;jupyter lab --no-browser --ip=0.0.0.0 --allow-root --notebook-dir="/code" --port=80 --LabApp.token="" --LabApp.allow_origin="self https://cloudbrain.pcl.ac.cn"`
//CommandBenchmark = `echo "start benchmark";python /code/test.py;echo "end benchmark"`
CommandBenchmark = `cd /benchmark && bash run_bk.sh >/model/benchmark-log.txt`
CodeMountPath = "/code"
DataSetMountPath = "/dataset"
ModelMountPath = "/model"
CommandBenchmark = `cd /benchmark && bash run_bk.sh >/model/benchmark-log.txt`
CodeMountPath = "/code"
DataSetMountPath = "/dataset"
ModelMountPath = "/model"
PretrainModelMountPath = "/pretrainmodel"
LogFile = "log.txt"
BenchMarkMountPath = "/benchmark"
BenchMarkResourceID = 1
Snn4imagenetMountPath = "/snn4imagenet"
BrainScoreMountPath = "/brainscore"
TaskInfoName = "/taskInfo"
Snn4imagenetCommand = `/opt/conda/bin/python /snn4imagenet/testSNN_script.py --modelname '%s' --modelpath '/dataset' --modeldescription '%s' >/model/benchmark-log.txt`
BrainScoreCommand = `bash /brainscore/brainscore_test_par4shSrcipt.sh -b '%s' -n '%s' -p '/dataset' -d '%s' >/model/benchmark-log.txt`
LogFile = "log.txt"
BenchMarkMountPath = "/benchmark"
BenchMarkResourceID = 1
Snn4imagenetMountPath = "/snn4imagenet"
BrainScoreMountPath = "/brainscore"
TaskInfoName = "/taskInfo"
Snn4imagenetCommand = `/opt/conda/bin/python /snn4imagenet/testSNN_script.py --modelname '%s' --modelpath '/dataset' --modeldescription '%s' >/model/benchmark-log.txt`
BrainScoreCommand = `bash /brainscore/brainscore_test_par4shSrcipt.sh -b '%s' -n '%s' -p '/dataset' -d '%s' >/model/benchmark-log.txt`

SubTaskName = "task1"

@@ -405,7 +405,7 @@ func GenerateTask(req GenerateCloudBrainTaskReq) error {
}

func IsBenchmarkJob(jobType string) bool {
return string(models.JobTypeBenchmark) == jobType || string(models.JobTypeBrainScore) == jobType || string(models.JobTypeSnn4imagenet) == jobType
return string(models.JobTypeModelSafety) == jobType || string(models.JobTypeBenchmark) == jobType || string(models.JobTypeBrainScore) == jobType || string(models.JobTypeSnn4imagenet) == jobType
}

func GetWaitingCloudbrainCount(cloudbrainType int, computeResource string, jobTypes ...models.JobType) int64 {


+ 17
- 3
modules/cron/tasks_basic.go View File

@@ -5,12 +5,13 @@
package cron

import (
"code.gitea.io/gitea/services/reward"
"code.gitea.io/gitea/services/cloudbrain/resource"
"code.gitea.io/gitea/modules/modelarts"
"context"
"time"

"code.gitea.io/gitea/modules/modelarts"
"code.gitea.io/gitea/services/cloudbrain/resource"
"code.gitea.io/gitea/services/reward"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/migrations"
repository_service "code.gitea.io/gitea/modules/repository"
@@ -122,6 +123,17 @@ func registerHandleUnDecompressAttachment() {
})
}

func registerHandleModelSafetyTask() {
RegisterTaskFatal("handle_modelsafety_task", &BaseConfig{
Enabled: true,
RunAtStart: true,
Schedule: "@every 5m",
}, func(ctx context.Context, _ *models.User, _ Config) error {
repo.TimerHandleModelSafetyTestTask()
return nil
})
}

func registerHandleBlockChainUnSuccessUsers() {
RegisterTaskFatal("handle_blockchain_unsuccess_users", &BaseConfig{
Enabled: true,
@@ -279,4 +291,6 @@ func initBasicTasks() {

//registerRewardPeriodTask()
registerCloudbrainPointDeductTask()

registerHandleModelSafetyTask()
}

+ 11
- 0
modules/grampus/grampus.go View File

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

import (
"code.gitea.io/gitea/modules/cloudbrain"
"encoding/json"
"strings"

@@ -73,6 +74,7 @@ type GenerateTrainJobReq struct {
PreTrainModelPath string
PreTrainModelUrl string
Spec *models.Specification
CodeName string
}

func getEndPoint() string {
@@ -102,6 +104,7 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error
centerID, centerName := getCentersParamter(ctx, req)

var datasetGrampus, modelGrampus []models.GrampusDataset
var codeGrampus models.GrampusDataset
if ProcessorTypeNPU == req.ProcessType {
datasetGrampus = getDatasetGrampus(req.DatasetInfos)
if len(req.ModelName) != 0 {
@@ -114,6 +117,12 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error
},
}
}
codeGrampus = models.GrampusDataset{
Name: req.CodeName,
Bucket: setting.Bucket,
EndPoint: getEndPoint(),
ObjectKey: req.CodeObsPath + cloudbrain.DefaultBranchName + ".zip",
}
}

jobResult, err := createJob(models.CreateGrampusJobRequest{
@@ -130,6 +139,8 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error
ReplicaNum: 1,
Datasets: datasetGrampus,
Models: modelGrampus,
Code: codeGrampus,
BootFile: req.BootFile,
},
},
})


+ 21
- 11
modules/modelarts/modelarts.go View File

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

import (
"code.gitea.io/gitea/modules/modelarts_cd"
"encoding/json"
"errors"
"fmt"
@@ -9,6 +8,8 @@ import (
"strconv"
"strings"

"code.gitea.io/gitea/modules/modelarts_cd"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
@@ -70,8 +71,8 @@ const (
var (
poolInfos *models.PoolInfos
TrainFlavorInfos *Flavor
SpecialPools *models.SpecialPools
MultiNodeConfig *MultiNodes
SpecialPools *models.SpecialPools
MultiNodeConfig *MultiNodes
)

type GenerateTrainJobReq struct {
@@ -141,6 +142,7 @@ type GenerateInferenceJobReq struct {
ResultUrl string
Spec *models.Specification
DatasetName string
JobType string
}

type VersionInfo struct {
@@ -173,12 +175,12 @@ type ResourcePool struct {
} `json:"resource_pool"`
}

type MultiNodes struct{
type MultiNodes struct {
Info []OrgMultiNode `json:"multinode"`
}
type OrgMultiNode struct{
type OrgMultiNode struct {
Org string `json:"org"`
Node []int `json:"node"`
Node []int `json:"node"`
}

// type Parameter struct {
@@ -709,7 +711,7 @@ func GenerateInferenceJob(ctx *context.Context, req *GenerateInferenceJobReq) (e
Status: models.TempJobStatus,
Type: models.TypeCloudBrainTwo,
JobName: req.JobName,
JobType: string(models.JobTypeInference),
JobType: req.JobType,
})
if err != nil {
log.Error("InsertCloudbrainTemp failed: %v", err.Error())
@@ -732,7 +734,7 @@ func GenerateInferenceJob(ctx *context.Context, req *GenerateInferenceJobReq) (e
JobID: jobID,
JobName: req.JobName,
DisplayJobName: req.DisplayJobName,
JobType: string(models.JobTypeInference),
JobType: req.JobType,
Type: models.TypeCloudBrainTwo,
VersionID: jobResult.VersionID,
VersionName: jobResult.VersionName,
@@ -769,7 +771,15 @@ func GenerateInferenceJob(ctx *context.Context, req *GenerateInferenceJobReq) (e
log.Error("CreateCloudbrain(%s) failed:%v", req.JobName, err.Error())
return err
}
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobID, req.DisplayJobName, models.ActionCreateInferenceTask)
if req.JobType == string(models.JobTypeModelSafety) {
task, err := models.GetCloudbrainByJobID(jobID)
if err == nil {
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, fmt.Sprint(task.ID), req.DisplayJobName, models.ActionCreateBenchMarkTask)
}
} else {
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobID, req.DisplayJobName, models.ActionCreateInferenceTask)
}

return nil
}

@@ -798,8 +808,8 @@ func InitSpecialPool() {
}
}

func InitMultiNode(){
if MultiNodeConfig ==nil && setting.ModelArtsMultiNode!=""{
func InitMultiNode() {
if MultiNodeConfig == nil && setting.ModelArtsMultiNode != "" {
json.Unmarshal([]byte(setting.ModelArtsMultiNode), &MultiNodeConfig)
}



+ 2
- 1
modules/repository/create.go View File

@@ -8,6 +8,7 @@ import (
"fmt"
"os"
"strings"
"text/template"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/git"
@@ -34,7 +35,7 @@ func CreateRepository(doer, u *models.User, opts models.CreateRepoOptions) (_ *m
Name: opts.Name,
Alias: opts.Alias,
LowerName: strings.ToLower(opts.Name),
Description: opts.Description,
Description: template.HTMLEscapeString(opts.Description),
OriginalURL: opts.OriginalURL,
OriginalServiceType: opts.GitServiceType,
IsPrivate: opts.IsPrivate,


+ 37
- 1
modules/setting/setting.go View File

@@ -394,7 +394,7 @@ var (
DefaultGitTreesPerPage int
DefaultMaxBlobSize int64
}{
EnableSwagger: true,
EnableSwagger: false,
SwaggerURL: "",
MaxResponseItems: 50,
DefaultPagingNum: 30,
@@ -707,6 +707,22 @@ var (
NPU_MINDSPORE_IMAGE_ID int
NPU_TENSORFLOW_IMAGE_ID int
}{}

ModelSafetyTest = struct {
NPUBaseDataSetName string
NPUBaseDataSetUUID string
NPUCombatDataSetName string
NPUCombatDataSetUUID string

GPUBaseDataSetName string
GPUBaseDataSetUUID string
GPUCombatDataSetName string
GPUCombatDataSetUUID string
}{}

ModelApp = struct {
DesensitizationUrl string
}{}
)

// DateLang transforms standard language locale name to corresponding value in datetime plugin.
@@ -1527,6 +1543,20 @@ func NewContext() {
getGrampusConfig()
getModelartsCDConfig()
getModelConvertConfig()
getModelSafetyConfig()
getModelAppConfig()
}

func getModelSafetyConfig() {
sec := Cfg.Section("model_safety_test")
ModelSafetyTest.GPUBaseDataSetName = sec.Key("GPUBaseDataSetName").MustString("")
ModelSafetyTest.GPUBaseDataSetUUID = sec.Key("GPUBaseDataSetUUID").MustString("")
ModelSafetyTest.GPUCombatDataSetName = sec.Key("GPUCombatDataSetName").MustString("")
ModelSafetyTest.GPUCombatDataSetUUID = sec.Key("GPUCombatDataSetUUID").MustString("")
ModelSafetyTest.NPUBaseDataSetName = sec.Key("NPUBaseDataSetName").MustString("")
ModelSafetyTest.NPUBaseDataSetUUID = sec.Key("NPUBaseDataSetUUID").MustString("")
ModelSafetyTest.NPUCombatDataSetName = sec.Key("NPUCombatDataSetName").MustString("")
ModelSafetyTest.NPUCombatDataSetUUID = sec.Key("NPUCombatDataSetUUID").MustString("")
}

func getModelConvertConfig() {
@@ -1548,6 +1578,12 @@ func getModelConvertConfig() {
ModelConvert.NPU_TENSORFLOW_IMAGE_ID = sec.Key("NPU_TENSORFLOW_IMAGE_ID").MustInt(35)
}

func getModelAppConfig() {
sec := Cfg.Section("model_app")
ModelApp.DesensitizationUrl = sec.Key("desensitization_url").MustString("")

}

func getModelartsCDConfig() {
sec := Cfg.Section("modelarts-cd")



+ 0
- 30
modules/timer/timer.go View File

@@ -1,30 +0,0 @@
package timer

import (
"github.com/robfig/cron/v3"

"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/routers/repo"
)

func LaunchCronJob() {
log.Trace("Run cron job")

c := cron.New()

spec := "*/10 * * * *"
c.AddFunc(spec, repo.HandleUnDecompressAttachment)

specCheckBlockChainUserSuccess := "*/10 * * * *"
c.AddFunc(specCheckBlockChainUserSuccess, repo.HandleBlockChainUnSuccessUsers)

specCheckRepoBlockChainSuccess := "*/1 * * * *"
c.AddFunc(specCheckRepoBlockChainSuccess, repo.HandleBlockChainUnSuccessRepos)

specCheckUnTransformedPRs := "*/1 * * * *"
c.AddFunc(specCheckUnTransformedPRs, repo.HandleBlockChainMergedPulls)

specCheckBlockChainCommitSuccess := "*/3 * * * *"
c.AddFunc(specCheckBlockChainCommitSuccess, repo.HandleBlockChainUnSuccessCommits)
c.Start()
}

+ 27
- 6
options/locale/locale_en-US.ini View File

@@ -1058,6 +1058,7 @@ modify_image=Modify Image
image_exist=Image name has been used, please use a new one.
image_committing=Image is submitting, please try again later.
image_commit_fail=Failed to submit image, please try again later.
image_over_20g=Failed to submit image, the size of image can not be over 20GB.
image_not_exist=Image does not exits.
image_edit_fail=Failed to edit image, please try again later.
image_delete_fail=Failed to delete image, please try again later.
@@ -1373,7 +1374,9 @@ fork_guest_user = Sign in to fork this repository.
copy_link = Copy
copy_link_success = Link has been copied
copy_link_error = Use ⌘C or Ctrl-C to copy
copy = Copy
copied = Copied OK
copied_error = Copied error
unwatch = Unwatch
watch = Watch
unstar = Unstar
@@ -3207,11 +3210,11 @@ wrong_specification=You cannot use this specification, please choose another ite
resource_use=Resource Occupancy

job_name_rule = Please enter letters, numbers, _ and - up to 64 characters and cannot end with a dash (-).
train_dataset_path_rule = The dataset location is stored in the environment variable <strong style="color:#010101">data_url</strong>, the pre-trained model is storaged in the environment <strong style="color:#010101">ckpt_url</strong>, and the output path is stored in the environment variable <strong style="color:#010101">train_url</strong>.
infer_dataset_path_rule = The dataset location is stored in the environment variable <strong style="color:#010101">data_url</strong>, and the output path is stored in the environment variable <strong style="color:#010101">result_url</strong>.
train_dataset_path_rule = The dataset location is stored in the run parameter <strong style="color:#010101">data_url</strong>, the pre-trained model is storaged in the run parameter <strong style="color:#010101">ckpt_url</strong>, and the output path is stored in the run parameter <strong style="color:#010101">train_url</strong>.
infer_dataset_path_rule = The dataset location is stored in the run parameter <strong style="color:#010101">data_url</strong>, and the output path is stored in the run parameter <strong style="color:#010101">result_url</strong>.
view_sample = View sample
inference_output_path_rule = The inference output path is stored in the environment variable result_url.
model_file_path_rule=The model file location is stored in the environment variable ckpt_url
inference_output_path_rule = The inference output path is stored in the run parameter result_url.
model_file_path_rule=The model file location is stored in the run parameter ckpt_url
model_file_postfix_rule = The supported format of the model file is [ckpt, pb, h5, json, pkl, pth, t7, pdparams, onnx, pbtxt, keras, mlmodel, cfg, pt]
model_convert_postfix_rule = The supported format of the model file is [.pth, .pkl, .onnx, .mindir, .ckpt, .pb]
delete_task = Delete task
@@ -3231,6 +3234,7 @@ point_hr = Point/hr
DEBUG = DEBUG
SNN4IMAGENET = BENCHMARK
BRAINSCORE = BENCHMARK
MODELSAFETY = BENCHMARK
TRAIN = TRAIN
INFERENCE = INFERENCE
BENCHMARK = BENCHMARK
@@ -3244,8 +3248,8 @@ Stopped_success_update_status_fail=Succeed in stopping th job, but failed to upd
load_code_failed=Fail to load code, please check if the right branch is selected.

error.dataset_select = dataset select error:the count exceed the limit or has same name
new_train_gpu_tooltips = The code is storaged in <strong style="color:#010101">%s</strong>, the dataset is storaged in <strong style="color:#010101">%s</strong>, the pre-trained model is storaged in the environment <strong style="color:#010101">%s</strong>, and please put your model into <strong style="color:#010101">%s</strong> then you can download it online
new_train_npu_tooltips = The code is storaged in <strong style="color:#010101">%s</strong>, the pre-trained model is storaged in the environment <strong style="color:#010101">%s</strong>, and please put your model into <strong style="color:#010101">%s</strong> then you can download it online
new_train_gpu_tooltips = The code is storaged in <strong style="color:#010101">%s</strong>, the dataset is storaged in <strong style="color:#010101">%s</strong>, the pre-trained model is storaged in the run parameter <strong style="color:#010101">%s</strong>, and please put your model into <strong style="color:#010101">%s</strong> then you can download it online
new_train_npu_tooltips = The code is storaged in <strong style="color:#010101">%s</strong>, the pre-trained model is storaged in the run parameter <strong style="color:#010101">%s</strong>, and please put your model into <strong style="color:#010101">%s</strong> then you can download it online
new_infer_gpu_tooltips = The dataset is stored in <strong style="color:#010101">%s</strong>, the model file is stored in <strong style="color:#010101">%s</strong>, please store the inference output in <strong style="color:#010101">%s</strong> for subsequent downloads.

[points]
@@ -3257,3 +3261,20 @@ hours = Hours
expected_time = , expected to be available for
points_acquisition_instructions = Points Acquisition Instructions
insufficient_points_balance = Insufficient points balance

[modelsafety]
model_security_evaluation = Model Security Evaluation
base_data_set = Base Data Set
combat_data_set = Combat Data Set
evaluation_indicators = Evaluation Indicators
evaluation_result = Evaluation Result
no_data = No Data
untargetted = Untargetted
targetted = targetted
new_model_security_evaluation_tips = Model Security Evaluation just used for image classification

[model_app]
get_file_fail= Can not get the image content, please try again later.
content_type_unsupported=Allowed image type is jpg, jpeg or png.
process_image_fail=Fail to process image, please try again later.


+ 27
- 8
options/locale/locale_zh-CN.ini View File

@@ -1059,6 +1059,7 @@ modify_image=修改镜像
image_exist=镜像Tag已被使用,请修改镜像Tag。
image_committing=镜像正在提交中,请稍后再试。
image_commit_fail=提交镜像失败,请稍后再试。
image_over_20g=提交镜像失败,镜像大小不能超过20GB。
image_not_exist=镜像不存在。
image_edit_fail=编辑镜像失败,请稍后再试。
image_delete_fail=删除镜像失败,请稍后再试。
@@ -1389,7 +1390,9 @@ fork_guest_user=登录并 派生 这个项目。
copy_link=复制链接
copy_link_success=已复制链接
copy_link_error=请按下 ⌘-C 或 Ctrl-C 复制
copy=复制
copied=复制成功
copied_error=复制失败
unwatch=取消关注
watch=关注
unstar=取消点赞
@@ -2022,7 +2025,7 @@ settings.githooks=管理 Git 钩子
settings.basic_settings=基本设置
settings.mirror_settings=镜像设置
settings.sync_mirror=同步
settings.mirror_sync_in_progress=镜像同步正在进行中,请稍后再试。
settings.mirror_sync_in_progress=镜像同步正在进行中,请稍后再试。
settings.email_notifications.enable=启用邮件通知
settings.email_notifications.onmention=只在被提到时邮件通知
settings.email_notifications.disable=停用邮件通知
@@ -3225,11 +3228,11 @@ card_type = 卡类型
wrong_specification=您目前不能使用这个资源规格,请选择其他资源规格。

job_name_rule = 请输入字母、数字、_和-,最长64个字符,且不能以中划线(-)结尾。
train_dataset_path_rule = 数据集位置存储在环境变量<strong style="color:#010101">data_url</strong>中,预训练模型存放在环境变量<strong style="color:#010101">ckpt_url</strong>中,训练输出路径存储在环境变量<strong style="color:#010101">train_url</strong>中。
infer_dataset_path_rule = 数据集位置存储在环境变量<strong style="color:#010101">data_url</strong>中,推理输出路径存储在环境变量<strong style="color:#010101">result_url</strong>中。
train_dataset_path_rule = 数据集位置存储在运行参数 <strong style="color:#010101">data_url</strong> 中,预训练模型存放在运行参数 <strong style="color:#010101">ckpt_url</strong> 中,训练输出路径存储在运行参数 <strong style="color:#010101">train_url</strong> 中。
infer_dataset_path_rule = 数据集位置存储在运行参数 <strong style="color:#010101">data_url</strong> 中,推理输出路径存储在运行参数 <strong style="color:#010101">result_url</strong> 中。
view_sample = 查看样例
inference_output_path_rule = 推理输出路径存储在环境变量result_url中。
model_file_path_rule = 模型文件位置存储在环境变量ckpt_url中。
inference_output_path_rule = 推理输出路径存储在运行参数 result_url 中。
model_file_path_rule = 模型文件位置存储在运行参数 ckpt_url 中。
model_file_postfix_rule = 模型文件支持的格式为 [ckpt, pb, h5, json, pkl, pth, t7, pdparams, onnx, pbtxt, keras, mlmodel, cfg, pt]
model_convert_postfix_rule = 模型文件支持的格式为 [.pth, .pkl, .onnx, .mindir, .ckpt, .pb]
delete_task = 删除任务
@@ -3249,6 +3252,7 @@ point_hr = 积分/时
DEBUG = 调试任务
SNN4IMAGENET = 评测任务
BRAINSCORE = 评测任务
MODELSAFETY = 评测任务
TRAIN = 训练任务
INFERENCE = 推理任务
BENCHMARK = 评测任务
@@ -3263,9 +3267,9 @@ load_code_failed=代码加载失败,请确认选择了正确的分支。


error.dataset_select = 数据集选择错误:数量超过限制或者有同名数据集
new_train_gpu_tooltips =训练脚本存储在<strong style="color:#010101">%s</strong>中,数据集存储在<strong style="color:#010101">%s</strong>中,预训练模型存放在环境变量<strong style="color:#010101">%s</strong>中,训练输出请存储在<strong style="color:#010101">%s</strong>中以供后续下载。
new_train_npu_tooltips =训练脚本存储在<strong style="color:#010101">%s</strong>中,预训练模型存放在环境变量<strong style="color:#010101">%s</strong>中,训练输出请存储在<strong style="color:#010101">%s</strong>中以供后续下载。
new_infer_gpu_tooltips = 数据集存储在<strong style="color:#010101">%s</strong>中,模型文件存储在<strong style="color:#010101">%s</strong>中,推理输出请存储在<strong style="color:#010101">%s</strong>中以供后续下载。
new_train_gpu_tooltips = 训练脚本存储在 <strong style="color:#010101">%s</strong> 中,数据集存储在 <strong style="color:#010101">%s</strong> 中,预训练模型存放在运行参数 <strong style="color:#010101">%s</strong> 中,训练输出请存储在 <strong style="color:#010101">%s</strong> 中以供后续下载。
new_train_npu_tooltips = 训练脚本存储在 <strong style="color:#010101">%s</strong> 中,预训练模型存放在运行参数 <strong style="color:#010101">%s</strong> 中,训练输出请存储在 <strong style="color:#010101">%s</strong> 中以供后续下载。
new_infer_gpu_tooltips = 数据集存储在 <strong style="color:#010101">%s</strong> 中,模型文件存储在 <strong style="color:#010101">%s</strong> 中,推理输出请存储在 <strong style="color:#010101">%s</strong> 中以供后续下载。

[points]
points = 积分
@@ -3277,4 +3281,19 @@ expected_time = ,预计可用
points_acquisition_instructions = 积分获取说明
insufficient_points_balance = 积分余额不足

[modelsafety]
model_security_evaluation = 模型安全评测
base_data_set = 原始数据集
combat_data_set = 对抗数据集
evaluation_indicators = 评测指标
evaluation_result = 评测结果
no_data = 无数据
untargetted = 非定向
targetted = 定向
new_model_security_evaluation_tips = 模型安全评测只适用于图像分类

[model_app]
get_file_fail= 获取上传文件失败,请稍后再试。
content_type_unsupported=请上传jpg、jpeg或png图片。
process_image_fail=图片处理失败,请稍后再试。


+ 6
- 4
public/home/home.js View File

@@ -81,8 +81,11 @@ var isZh = true;
if(lang != null && lang.nodeValue =="en-US" ){
isZh=false;
}

document.onreadystatechange = function () {
if(document.readyState != "complete"){
return;
}
console.log("Start to open WebSocket." + document.readyState);
queryRecommendData();

var output = document.getElementById("newmessage");
@@ -102,10 +105,9 @@ document.onreadystatechange = function () {
var html = "";
if (data != null){
if(messageQueue.length > maxSize){
delete messageQueue[0];
}else{
messageQueue.push(data);
messageQueue.splice(0,1);
}
messageQueue.push(data);
var currentTime = new Date().getTime();
for(var i = 0; i < messageQueue.length; i++){
var record = messageQueue[i];


BIN
public/img/origin.png View File

Before After
Width: 1920  |  Height: 1080  |  Size: 2.2 MiB

BIN
public/img/tuomin.png View File

Before After
Width: 1920  |  Height: 1080  |  Size: 1.8 MiB

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

@@ -52,7 +52,7 @@ func CloudBrains(ctx *context.Context) {
var jobTypes []string
jobTypeNot := false
if jobType == string(models.JobTypeBenchmark) {
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet))
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeModelSafety), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet))
} else if jobType != "all" && jobType != "" {
jobTypes = append(jobTypes, jobType)
}
@@ -98,8 +98,6 @@ func CloudBrains(ctx *context.Context) {
ciTasks[i].CanDebug = true
ciTasks[i].CanDel = true
ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource
ciTasks[i].Cloudbrain.AiCenter = repo.GetCloudbrainAiCenter(task.Cloudbrain, ctx)
ciTasks[i].Cloudbrain.Cluster = repo.GetCloudbrainCluster(task.Cloudbrain, ctx)
}

pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, getTotalPage(count, setting.UI.IssuePagingNum))
@@ -179,6 +177,7 @@ func DownloadCloudBrains(ctx *context.Context) {
log.Warn("Can not get cloud brain info", err)
continue
}
models.LoadSpecs4CloudbrainInfo(pageRecords)
for _, record := range pageRecords {

for k, v := range allValues(row, record, ctx) {
@@ -208,8 +207,11 @@ func allValues(row int, rs *models.CloudbrainInfo, ctx *context.Context) map[str
}

func getCloudbrainCardType(rs *models.CloudbrainInfo) string {
_, cardType, _ := repo.GetCloudbrainCardNumAndType(rs.Cloudbrain)
return cardType
if rs.Cloudbrain.Spec != nil {
return rs.Cloudbrain.Spec.AccCardType
} else {
return ""
}
}

func getRepoPathName(rs *models.CloudbrainInfo) string {


+ 2
- 0
routers/admin/resources.go View File

@@ -221,6 +221,7 @@ func GetResourceSceneList(ctx *context.Context) {

func AddResourceScene(ctx *context.Context, req models.ResourceSceneReq) {
req.CreatorId = ctx.User.ID
req.ExclusiveOrg = strings.ReplaceAll(req.ExclusiveOrg, " ", "")
err := resource.AddResourceScene(req)
if err != nil {
log.Error("AddResourceScene error. %v", err)
@@ -238,6 +239,7 @@ func UpdateResourceScene(ctx *context.Context, req models.ResourceSceneReq) {
var err error
switch action {
case "edit":
req.ExclusiveOrg = strings.ReplaceAll(req.ExclusiveOrg, " ", "")
err = resource.UpdateResourceScene(req)
case "delete":
err = resource.DeleteResourceScene(id)


+ 1
- 0
routers/api/v1/api.go View File

@@ -590,6 +590,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/downloadAll", repo.DownloadCloudBrainBoard)
m.Group("/cloudbrain", func() {
m.Get("/overview", repo.GetAllCloudbrainsOverview)
m.Get("/overview_duration", repo.GetOverviewDuration)
m.Get("/distribution", repo.GetAllCloudbrainsPeriodDistribution)
m.Get("/trend", repo.GetAllCloudbrainsTrend)
m.Get("/trend_detail_data", repo.GetAllCloudbrainsTrendDetail)


+ 191
- 47
routers/api/v1/repo/cloudbrain.go View File

@@ -12,6 +12,7 @@ import (
"net/http"
"os"
"sort"
"strconv"
"strings"
"time"

@@ -67,49 +68,62 @@ func GetCloudbrainTask(ctx *context.APIContext) {
log.Error("GetCloudbrainByID failed:", err)
return
}
jobResult, err := cloudbrain.GetJob(job.JobID)
if err != nil {
ctx.NotFound(err)
log.Error("GetJob failed:", err)
return
}
result, _ := models.ConvertToJobResultPayload(jobResult.Payload)
if err != nil {
ctx.NotFound(err)
log.Error("ConvertToJobResultPayload failed:", err)
return
}
oldStatus := job.Status
job.Status = result.JobStatus.State
taskRoles := result.TaskRoles
taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{}))
if result.JobStatus.State != string(models.JobWaiting) && result.JobStatus.State != string(models.JobFailed) {
job.ContainerIp = taskRes.TaskStatuses[0].ContainerIP
job.ContainerID = taskRes.TaskStatuses[0].ContainerID
job.Status = taskRes.TaskStatuses[0].State
}

if result.JobStatus.State != string(models.JobWaiting) {
models.ParseAndSetDurationFromCloudBrainOne(result, job)
if oldStatus != job.Status {
notification.NotifyChangeCloudbrainStatus(job, oldStatus)
if job.JobType == string(models.JobTypeModelSafety) {
routerRepo.GetAiSafetyTaskByJob(job)
job, err = models.GetCloudbrainByID(ID)
ctx.JSON(http.StatusOK, map[string]interface{}{
"ID": ID,
"JobName": job.JobName,
"JobStatus": job.Status,
"SubState": "",
"CreatedTime": job.CreatedUnix.Format("2006-01-02 15:04:05"),
"CompletedTime": job.UpdatedUnix.Format("2006-01-02 15:04:05"),
"JobDuration": job.TrainJobDuration,
})
} else {
jobResult, err := cloudbrain.GetJob(job.JobID)
if err != nil {
ctx.NotFound(err)
log.Error("GetJob failed:", err)
return
}
err = models.UpdateJob(job)
result, _ := models.ConvertToJobResultPayload(jobResult.Payload)
if err != nil {
log.Error("UpdateJob failed:", err)
ctx.NotFound(err)
log.Error("ConvertToJobResultPayload failed:", err)
return
}
oldStatus := job.Status
job.Status = result.JobStatus.State
taskRoles := result.TaskRoles
taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{}))
if result.JobStatus.State != string(models.JobWaiting) && result.JobStatus.State != string(models.JobFailed) {
job.ContainerIp = taskRes.TaskStatuses[0].ContainerIP
job.ContainerID = taskRes.TaskStatuses[0].ContainerID
job.Status = taskRes.TaskStatuses[0].State
}
}

ctx.JSON(http.StatusOK, map[string]interface{}{
"ID": ID,
"JobName": result.Config.JobName,
"JobStatus": result.JobStatus.State,
"SubState": result.JobStatus.SubState,
"CreatedTime": time.Unix(result.JobStatus.CreatedTime/1000, 0).Format("2006-01-02 15:04:05"),
"CompletedTime": time.Unix(result.JobStatus.CompletedTime/1000, 0).Format("2006-01-02 15:04:05"),
"JobDuration": job.TrainJobDuration,
})
if result.JobStatus.State != string(models.JobWaiting) {
models.ParseAndSetDurationFromCloudBrainOne(result, job)
if oldStatus != job.Status {
notification.NotifyChangeCloudbrainStatus(job, oldStatus)
}
err = models.UpdateJob(job)
if err != nil {
log.Error("UpdateJob failed:", err)
}
}

ctx.JSON(http.StatusOK, map[string]interface{}{
"ID": ID,
"JobName": result.Config.JobName,
"JobStatus": result.JobStatus.State,
"SubState": result.JobStatus.SubState,
"CreatedTime": time.Unix(result.JobStatus.CreatedTime/1000, 0).Format("2006-01-02 15:04:05"),
"CompletedTime": time.Unix(result.JobStatus.CompletedTime/1000, 0).Format("2006-01-02 15:04:05"),
"JobDuration": job.TrainJobDuration,
})
}
}

func GetCloudBrainInferenceJob(ctx *context.APIContext) {
@@ -370,6 +384,96 @@ func CloudbrainForModelConvertGetLog(ctx *context.Context) {
ctx.JSON(http.StatusOK, result)
}

func ModelSafetyGetLog(ctx *context.APIContext) {
ID := ctx.Params(":id")
job, err := models.GetCloudbrainByID(ID)
if err != nil {
log.Error("GetCloudbrainByJobName failed: %v", err, ctx.Data["MsgID"])
ctx.ServerError(err.Error(), err)
return
}
if job.JobType == string(models.JobTypeModelSafety) {
if job.Type == models.TypeCloudBrainTwo {
//TrainJobForModelConvertGetLog(ctx)
var baseLine = ctx.Query("base_line")
var order = ctx.Query("order")
var lines = ctx.Query("lines")
lines_int, err := strconv.Atoi(lines)
if err != nil {
log.Error("change lines(%d) string to int failed", lines_int)
}

if order != modelarts.OrderDesc && order != modelarts.OrderAsc {
log.Error("order(%s) check failed", order)
ctx.JSON(http.StatusBadRequest, map[string]interface{}{
"err_msg": "order check failed",
})
return
}
resultLogFile, err := modelarts.GetTrainJobLogFileNames(job.JobID, strconv.FormatInt(job.VersionID, 10))
if err != nil {
log.Error("GetTrainJobLogFileNames(%s) failed:%v", job.JobID, err.Error())
}
result, err := modelarts.GetTrainJobLog(job.JobID, strconv.FormatInt(job.VersionID, 10), baseLine, resultLogFile.LogFileList[0], order, lines_int)
if err != nil {
log.Error("GetTrainJobLog(%s) failed:%v", job.JobID, err.Error())
}
if err != nil {
log.Error("trainJobGetLog(%s) failed:%v", job.JobID, err.Error())
// ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobShow, nil)
ctx.JSON(http.StatusOK, map[string]interface{}{
"JobID": job.JobID,
"LogFileName": "",
"StartLine": "0",
"EndLine": "0",
"Content": "",
"Lines": 0,
"CanLogDownload": false,
})
return
}
ctx.Data["log_file_name"] = resultLogFile.LogFileList[0]
ctx.JSON(http.StatusOK, map[string]interface{}{
"JobID": job.JobID,
"LogFileName": resultLogFile.LogFileList[0],
"StartLine": result.StartLine,
"EndLine": result.EndLine,
"Content": result.Content,
"Lines": result.Lines,
"CanLogDownload": isCanDownloadLog(ctx, job),
})
}
}
//result := ""
//ctx.JSON(http.StatusOK, result)
}

func isCanDownloadLog(ctx *context.APIContext, job *models.Cloudbrain) bool {
if !ctx.IsSigned {
return false
}
return ctx.IsUserSiteAdmin() || ctx.User.ID == job.UserID
}

func ModelSafetyDownloadLogFile(ctx *context.Context) {
ID := ctx.Params(":id")
job, err := models.GetCloudbrainByID(ID)
if err != nil {
log.Error("GetCloudbrainByJobName failed: %v", err, ctx.Data["MsgID"])
ctx.ServerError(err.Error(), err)
return
}
if job.JobType == string(models.JobTypeModelSafety) {
if job.Type == models.TypeCloudBrainOne {
CloudbrainDownloadLogFile(ctx)
} else if job.Type == models.TypeCloudBrainTwo {
ctx.SetParams("jobid", job.JobID)
ctx.Req.Form.Set("version_name", job.VersionName)
routerRepo.TrainJobDownloadLogFile(ctx)
}
}
}

func CloudbrainDownloadLogFile(ctx *context.Context) {
ID := ctx.Params(":id")
job, err := models.GetCloudbrainByID(ID)
@@ -378,13 +482,18 @@ func CloudbrainDownloadLogFile(ctx *context.Context) {
ctx.ServerError(err.Error(), err)
return
}
if job.JobType == string(models.JobTypeModelSafety) {
if job.Type == models.TypeCloudBrainTwo {
ModelSafetyDownloadLogFile(ctx)
return
}
}

logDir := "/model"
if job.JobType == string(models.JobTypeInference) {
if job.JobType == string(models.JobTypeInference) || job.JobType == string(models.JobTypeModelSafety) {
logDir = cloudbrain.ResultPath
}
prefix := "/" + setting.CBCodePathPrefix + job.JobName + logDir
files, err := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, "")
files, err := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, setting.CBCodePathPrefix+job.JobName+logDir, "")
if err != nil {
log.Error("query cloudbrain model failed: %v", err)
return
@@ -397,17 +506,22 @@ func CloudbrainDownloadLogFile(ctx *context.Context) {
}
}
if fileName != "" {
prefix := "/" + setting.CBCodePathPrefix + job.JobName + logDir
url, err := storage.Attachments.PresignedGetURL(prefix+"/"+fileName, fileName)
if err != nil {
log.Error("Get minio get SignedUrl failed: %v", err.Error(), ctx.Data["msgID"])
ctx.ServerError("Get minio get SignedUrl failed", err)
return
}
log.Info("fileName=" + fileName)
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusTemporaryRedirect)
} else {
log.Info("fileName is null.")

}
}

func CloudbrainGetLog(ctx *context.Context) {
func CloudbrainGetLog(ctx *context.APIContext) {
ID := ctx.Params(":id")
job, err := models.GetCloudbrainByID(ID)
if err != nil {
@@ -415,12 +529,31 @@ func CloudbrainGetLog(ctx *context.Context) {
ctx.ServerError(err.Error(), err)
return
}
if job.JobType == string(models.JobTypeModelSafety) {
if job.Type == models.TypeCloudBrainOne {
result, err := cloudbrain.GetJob(job.JobID)
existStr := ""
if err == nil && result != nil {
jobRes, _ := models.ConvertToJobResultPayload(result.Payload)
taskRoles := jobRes.TaskRoles
taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{}))
existStr = taskRes.TaskStatuses[0].ExitDiagnostics
}
ctx.Data["existStr"] = existStr
log.Info("existStr=" + existStr)
} else {
ModelSafetyGetLog(ctx)
return
}

}

lines := ctx.QueryInt("lines")
baseLine := ctx.Query("base_line")
order := ctx.Query("order")
var result map[string]interface{}
resultPath := "/model"
if job.JobType == string(models.JobTypeInference) {
if job.JobType == string(models.JobTypeInference) || job.JobType == string(models.JobTypeModelSafety) {
resultPath = "/result"
}
if baseLine == "" && order == "desc" {
@@ -447,12 +580,19 @@ func CloudbrainGetLog(ctx *context.Context) {
return
}
}
content := ""
if result["Content"] != nil {
content = result["Content"].(string)
}
if ctx.Data["existStr"] != nil && result["Lines"].(int) < 50 {
content = content + ctx.Data["existStr"].(string)
}
re := map[string]interface{}{
"JobID": ID,
"LogFileName": result["FileName"],
"StartLine": result["StartLine"],
"EndLine": result["EndLine"],
"Content": result["Content"],
"Content": content,
"Lines": result["Lines"],
"CanLogDownload": result["FileName"] != "",
}
@@ -485,7 +625,7 @@ func getAllLineFromFile(path string) int {
}

func getLastLogFromModelDir(jobName string, lines int, resultPath string) map[string]interface{} {
prefix := "/" + setting.CBCodePathPrefix + jobName + resultPath
prefix := setting.CBCodePathPrefix + jobName + resultPath
files, err := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, "")
if err != nil {
log.Error("query cloudbrain model failed: %v", err)
@@ -546,7 +686,7 @@ func getLastLogFromModelDir(jobName string, lines int, resultPath string) map[st
}

func getLogFromModelDir(jobName string, startLine int, endLine int, resultPath string) map[string]interface{} {
prefix := "/" + setting.CBCodePathPrefix + jobName + resultPath
prefix := setting.CBCodePathPrefix + jobName + resultPath
files, err := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, "")
if err != nil {
log.Error("query cloudbrain model failed: %v", err)
@@ -577,8 +717,12 @@ func getLogFromModelDir(jobName string, startLine int, endLine int, resultPath s
r := bufio.NewReader(reader)
for i := 0; i < endLine; i++ {
line, error := r.ReadString('\n')
log.Info("line=" + line)
if error == io.EOF {
if i >= startLine {
fileEndLine = i
re = re + line
count++
}
log.Info("read file completed.")
break
}


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

@@ -19,6 +19,7 @@ type DateCloudbrainNum struct {
CloudOneJobTypeRes map[string]int `json:"cloudOneJobTypeRes"`
CloudTwoJobTypeRes map[string]int `json:"cloudTwoJobTypeRes"`
IntelligentNetJobTypeRes map[string]int `json:"intelligentNetJobTypeRes"`
CDCenterJobTypeRes map[string]int `json:"cDCenterJobTypeRes"`
CloudBrainPeriodNum map[int]int `json:"cloudBrainPeriodNum"`
CloudBrainComputeResource map[string]int `json:"cloudBrainComputeResource"`
}
@@ -53,20 +54,90 @@ func GetAllCloudbrainsOverview(ctx *context.Context) {
log.Error("Can not query todayCreatorCount.", err)
return
}
cloudbrainTypeCount, err := models.GetCloudbrainTypeCount()
log.Info("cloudbrainTypeCount:", cloudbrainTypeCount)
if err != nil {
log.Error("Can not query cloudbrainTypeCount.", err)
return
}

cloudbrainTpyeDurationSum, err := models.GetCloudbrainTpyeDurationSum()
log.Info("cloudbrainTpyeDurationSum:", cloudbrainTpyeDurationSum)
if err != nil {
log.Error("Can not query cloudbrainTpyeDurationSum.", err)
return
}

todayCloudbrainCount, err := models.GetTodayCloudbrainCount(beginTime, endTime)
log.Info("todayCloudbrainCount:", todayCloudbrainCount)
if err != nil {
log.Error("Can not query todayCloudbrainCount.", err)
return
}

todayRunningCount, err := models.GetTodayRunningCount(beginTime, endTime)
log.Info("todayRunningCount:", todayRunningCount)
if err != nil {
log.Error("Can not query todayRunningCount.", err)
return
}

todayWaitingCount, err := models.GetTodayWaitingCount(beginTime, endTime)
log.Info("todayWaittingCount:", todayWaitingCount)
if err != nil {
log.Error("Can not query todayWaitingCount.", err)
return
}

todayCompletedCount := todayCloudbrainCount - todayRunningCount - todayWaitingCount
log.Info("todayCompletedCount:", todayCompletedCount)

creatorCount, err := models.GetCreatorCount()
if err != nil {
log.Error("Can not query creatorCount.", err)
return
}
todayStatusResult := make(map[string]int)
cloudBrainNum := make(map[int]int)
cloudBrainOneDuration := int64(0)
cloudBrainTwoDuration := int64(0)
intelligentNetDuration := int64(0)
todayNewJobCount := 0

ctx.JSON(http.StatusOK, map[string]interface{}{
"recordBeginTime": recordBeginTime,
"updateTime": now.Unix(),
"todayCreatorCount": todayCreatorCount,
"creatorCount": creatorCount,
"todayRunningCount": todayRunningCount,
"todayCompletedCount": todayCompletedCount,
"todayWaitingCount": todayWaitingCount,
"todayNewJobCount": todayCloudbrainCount,
"cloudbrainTypeCount": cloudbrainTypeCount,
})
}
func GetOverviewDuration(ctx *context.Context) {
recordCloudbrain, err := models.GetRecordBeginTime()
if err != nil {
log.Error("Can not get recordCloudbrain", err)
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err"))
return
}
recordBeginTime := recordCloudbrain[0].Cloudbrain.CreatedUnix
now := time.Now()
endTime := now
page := 1
pagesize := 1000
pagesize := 10000
count := pagesize
worker_server_num := 1
cardNum := 1
durationAllSum := int64(0)
cardDuSum := int64(0)

cloudBrainOneCardDuSum := int64(0)
cloudBrainTwoCardDuSum := int64(0)
c2NetCardDuSum := int64(0)
cDNetCardDuSum := int64(0)

cloudBrainOneDuration := int64(0)
cloudBrainTwoDuration := int64(0)
c2NetDuration := int64(0)
cDCenterDuration := int64(0)

for count == pagesize && count != 0 {
cloudbrains, _, err := models.CloudbrainAllStatic(&models.CloudbrainsOptions{
ListOptions: models.ListOptions{
@@ -81,72 +152,53 @@ func GetAllCloudbrainsOverview(ctx *context.Context) {
ctx.ServerError("Get cloudbrains failed:", err)
return
}
models.LoadSpecs4CloudbrainInfo(cloudbrains)

for _, cloudbrain := range cloudbrains {
if int64(cloudbrain.Cloudbrain.CreatedUnix) >= beginTime.Unix() && int64(cloudbrain.Cloudbrain.CreatedUnix) < endTime.Unix() {
todayNewJobCount += 1
if _, ok := todayStatusResult[cloudbrain.Status]; !ok {
todayStatusResult[cloudbrain.Status] = 1
} else {
todayStatusResult[cloudbrain.Status] += 1
}
if cloudbrain.Cloudbrain.WorkServerNumber >= 1 {
worker_server_num = cloudbrain.Cloudbrain.WorkServerNumber
} else {
worker_server_num = 1
}

if _, ok := cloudBrainNum[cloudbrain.Cloudbrain.Type]; !ok {
cloudBrainNum[cloudbrain.Cloudbrain.Type] = 1
if cloudbrain.Cloudbrain.Spec == nil {
cardNum = 1
} else {
cloudBrainNum[cloudbrain.Cloudbrain.Type] += 1
cardNum = cloudbrain.Cloudbrain.Spec.AccCardsNum
}

duration := cloudbrain.Duration
durationSum := cloudbrain.Duration * int64(worker_server_num) * int64(cardNum)
if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainOne {
cloudBrainOneDuration = cloudBrainOneDuration + cloudbrain.Cloudbrain.Duration
}
if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainTwo {
cloudBrainTwoDuration = cloudBrainTwoDuration + cloudbrain.Cloudbrain.Duration
cloudBrainOneDuration += duration
cloudBrainOneCardDuSum += durationSum
} else if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainTwo {
cloudBrainTwoDuration += duration
cloudBrainTwoCardDuSum += durationSum
} else if cloudbrain.Cloudbrain.Type == models.TypeC2Net {
c2NetDuration += duration
c2NetCardDuSum += durationSum
} else if cloudbrain.Cloudbrain.Type == models.TypeCDCenter {
cDCenterDuration += duration
cDNetCardDuSum += durationSum
}
if cloudbrain.Cloudbrain.Type == models.TypeC2Net {
intelligentNetDuration = intelligentNetDuration + cloudbrain.Cloudbrain.Duration
}

}
count = len(cloudbrains)
page += 1
}

statusNameList := []string{string(models.ModelArtsTrainJobCompleted), string(models.JobFailed), string(models.ModelArtsTrainJobInit),
string(models.JobRunning), string(models.ModelArtsStartFailed), string(models.JobStopped), string(models.JobSucceeded),
string(models.JobWaiting), string(models.ModelArtsTrainJobKilled)}
for _, v := range statusNameList {
if _, ok := todayStatusResult[v]; !ok {
todayStatusResult[v] = 0
}
}

cloudBrainTypeList := []int{0, 1, 2}
for _, v := range cloudBrainTypeList {
if _, ok := cloudBrainNum[v]; !ok {
cloudBrainNum[v] = 0
durationAllSum += duration
cardDuSum += durationSum
count = len(cloudbrains)
page += 1
}
}

todayRunningCount := todayStatusResult[string(models.JobRunning)]
todayCompletedCount := todayStatusResult[string(models.ModelArtsTrainJobCompleted)] + todayStatusResult[string(models.JobFailed)] +
todayStatusResult[string(models.ModelArtsStartFailed)] + todayStatusResult[string(models.JobStopped)] + todayStatusResult[string(models.JobSucceeded)] + todayStatusResult[string(models.ModelArtsTrainJobKilled)]
todayWaitingCount := todayStatusResult[string(models.ModelArtsTrainJobInit)] + todayStatusResult[string(models.JobWaiting)]

ctx.JSON(http.StatusOK, map[string]interface{}{
"recordBeginTime": recordBeginTime,
"updateTime": now.Unix(),
"cloudBrainNum": cloudBrainNum,
"cloudBrainOneDuration": cloudBrainOneDuration,
"cloudBrainTwoDuration": cloudBrainTwoDuration,
"intelligentNetDuration": intelligentNetDuration,
"todayCreatorCount": todayCreatorCount,
"creatorCount": creatorCount,
"todayRunningCount": todayRunningCount,
"todayCompletedCount": todayCompletedCount,
"todayWaitingCount": todayWaitingCount,
"todayNewJobCount": todayNewJobCount,
"cloudBrainOneCardDuSum": cloudBrainOneCardDuSum,
"cloudBrainTwoCardDuSum": cloudBrainTwoCardDuSum,
"c2NetCardDuSum": c2NetCardDuSum,
"cDNetCardDuSum": cDNetCardDuSum,
"cardDuSum": cardDuSum,

"cloudBrainOneDuration": cloudBrainOneDuration,
"cloudBrainTwoDuration": cloudBrainTwoDuration,
"c2NetDuration": c2NetDuration,
"cDCenterDuration": cDCenterDuration,
"durationSum": durationAllSum,
})
}

@@ -500,6 +552,7 @@ func GetAllCloudbrainsPeriodDistribution(ctx *context.Context) {
cloudOneJobTypeRes := make(map[string]int)
cloudTwoJobTypeRes := make(map[string]int)
intelligentNetJobTypeRes := make(map[string]int)
cDCenterJobTypeRes := make(map[string]int)
cloudBrainPeriodNum := make(map[int]int)
cloudBrainComputeResource := make(map[string]int)
beginTimeTemp := beginTime.Unix()
@@ -508,9 +561,9 @@ func GetAllCloudbrainsPeriodDistribution(ctx *context.Context) {
}

page := 1
pagesize := 1000
pagesize := 10000
count := pagesize
//Each time a maximum of 1000 pieces of data are detected to the memory, batch processing
//Each time a maximum of 10000 pieces of data are detected to the memory, batch processing
for count == pagesize && count != 0 {
cloudbrains, _, err := models.CloudbrainAllStatic(&models.CloudbrainsOptions{
ListOptions: models.ListOptions{
@@ -548,6 +601,13 @@ func GetAllCloudbrainsPeriodDistribution(ctx *context.Context) {
intelligentNetJobTypeRes[cloudbrain.JobType] += 1
}
}
if cloudbrain.Cloudbrain.Type == models.TypeCDCenter {
if _, ok := cDCenterJobTypeRes[cloudbrain.JobType]; !ok {
cDCenterJobTypeRes[cloudbrain.JobType] = 1
} else {
cDCenterJobTypeRes[cloudbrain.JobType] += 1
}
}

if _, ok := cloudBrainPeriodNum[cloudbrain.Cloudbrain.Type]; !ok {
cloudBrainPeriodNum[cloudbrain.Cloudbrain.Type] = 1
@@ -566,7 +626,7 @@ func GetAllCloudbrainsPeriodDistribution(ctx *context.Context) {
}

jobTypeList := []string{string(models.JobTypeDebug), string(models.JobTypeTrain), string(models.JobTypeInference), string(models.JobTypeBenchmark),
string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet)}
string(models.JobTypeModelSafety), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet)}
for _, v := range jobTypeList {
if _, ok := cloudOneJobTypeRes[v]; !ok {
cloudOneJobTypeRes[v] = 0
@@ -577,8 +637,11 @@ func GetAllCloudbrainsPeriodDistribution(ctx *context.Context) {
if _, ok := intelligentNetJobTypeRes[v]; !ok {
intelligentNetJobTypeRes[v] = 0
}
if _, ok := cDCenterJobTypeRes[v]; !ok {
cDCenterJobTypeRes[v] = 0
}
}
cloudBrainTypeList := []int{0, 1, 2}
cloudBrainTypeList := []int{0, 1, 2, 3}
for _, v := range cloudBrainTypeList {
if _, ok := cloudBrainPeriodNum[v]; !ok {
cloudBrainPeriodNum[v] = 0
@@ -592,77 +655,30 @@ func GetAllCloudbrainsPeriodDistribution(ctx *context.Context) {
}
}

cloudOneJobTypeRes["EVALUATION"] = cloudOneJobTypeRes[string(models.JobTypeBenchmark)] + cloudOneJobTypeRes[string(models.JobTypeSnn4imagenet)] + cloudOneJobTypeRes[string(models.JobTypeBrainScore)]
cloudTwoJobTypeRes["EVALUATION"] = cloudTwoJobTypeRes[string(models.JobTypeBenchmark)] + cloudTwoJobTypeRes[string(models.JobTypeSnn4imagenet)] + cloudTwoJobTypeRes[string(models.JobTypeBrainScore)]
intelligentNetJobTypeRes["EVALUATION"] = intelligentNetJobTypeRes[string(models.JobTypeBenchmark)] + intelligentNetJobTypeRes[string(models.JobTypeSnn4imagenet)] + intelligentNetJobTypeRes[string(models.JobTypeBrainScore)]
cloudOneJobTypeRes["EVALUATION"] = cloudBrainPeriodNum[0] - cloudOneJobTypeRes[string(models.JobTypeTrain)] - cloudOneJobTypeRes[string(models.JobTypeInference)] - cloudOneJobTypeRes[string(models.JobTypeDebug)]
cloudTwoJobTypeRes["EVALUATION"] = cloudBrainPeriodNum[1] - cloudTwoJobTypeRes[string(models.JobTypeTrain)] - cloudTwoJobTypeRes[string(models.JobTypeInference)] - cloudTwoJobTypeRes[string(models.JobTypeDebug)]
intelligentNetJobTypeRes["EVALUATION"] = cloudBrainPeriodNum[2] - intelligentNetJobTypeRes[string(models.JobTypeTrain)] - intelligentNetJobTypeRes[string(models.JobTypeInference)] - intelligentNetJobTypeRes[string(models.JobTypeDebug)]
cDCenterJobTypeRes["EVALUATION"] = cloudBrainPeriodNum[3] - cDCenterJobTypeRes[string(models.JobTypeTrain)] - cDCenterJobTypeRes[string(models.JobTypeInference)] - cDCenterJobTypeRes[string(models.JobTypeDebug)]
ctx.JSON(http.StatusOK, map[string]interface{}{
"cloudOneJobTypeRes": cloudOneJobTypeRes,
"cloudTwoJobTypeRes": cloudTwoJobTypeRes,
"intelligentNetJobTypeRes": intelligentNetJobTypeRes,
"cDCenterJobTypeRes": cDCenterJobTypeRes,
"cloudBrainPeriodNum": cloudBrainPeriodNum,
"cloudBrainComputeResource": cloudBrainComputeResource,
})
}

func GetCloudbrainsStatusAnalysis(ctx *context.Context) {
recordCloudbrain, err := models.GetRecordBeginTime()
cloudbrainStatusCount, err := models.GetCloudbrainStatusCount()
log.Info("cloudbrainStatusCount:", cloudbrainStatusCount)
if err != nil {
log.Error("Can not get recordCloudbrain", err)
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err"))
log.Error("Can not query cloudbrainStatusCount.", err)
return
}
recordBeginTime := recordCloudbrain[0].Cloudbrain.CreatedUnix
endTime := time.Now()
cloudBrainStatusResult := make(map[string]int)
cloudBrainStatusAnalysis := make(map[string]int)
totalCount := 0

page := 1
pagesize := 1000
count := pagesize
for count == pagesize && count != 0 {
cloudbrains, _, err := models.CloudbrainAllStatic(&models.CloudbrainsOptions{
ListOptions: models.ListOptions{
Page: page,
PageSize: pagesize,
},
Type: models.TypeCloudBrainAll,
BeginTimeUnix: int64(recordBeginTime),
EndTimeUnix: endTime.Unix(),
})
if err != nil {
ctx.ServerError("Get cloudbrains failed:", err)
return
}
for _, cloudbrain := range cloudbrains {
if _, ok := cloudBrainStatusResult[cloudbrain.Status]; !ok {
cloudBrainStatusResult[cloudbrain.Status] = 1
} else {
cloudBrainStatusResult[cloudbrain.Status] += 1
}
}
count = len(cloudbrains)
totalCount = totalCount + count
page += 1
}

var jobStatuses []string
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))
jobStatusesCount := 0
for _, v := range jobStatuses {
if _, ok := cloudBrainStatusResult[v]; !ok {
cloudBrainStatusAnalysis[v] = 0
} else {
cloudBrainStatusAnalysis[v] = cloudBrainStatusResult[v]
}
jobStatusesCount = jobStatusesCount + cloudBrainStatusResult[v]
}
cloudBrainStatusAnalysis["OTHER"] = totalCount - jobStatusesCount

ctx.JSON(http.StatusOK, map[string]interface{}{
"cloudBrainStatusResult": cloudBrainStatusAnalysis,
"cloudbrainStatusCount": cloudbrainStatusCount,
})
}

@@ -693,7 +709,7 @@ func GetCloudbrainsDetailData(ctx *context.Context) {
var jobTypes []string
jobTypeNot := false
if jobType == string(models.JobTypeBenchmark) {
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet))
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeModelSafety), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet))
} else if jobType != "all" && jobType != "" {
jobTypes = append(jobTypes, jobType)
}
@@ -738,7 +754,6 @@ func GetCloudbrainsDetailData(ctx *context.Context) {
tasks := []models.TaskDetail{}
for i, task := range ciTasks {
ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource

var taskDetail models.TaskDetail
taskDetail.ID = ciTasks[i].Cloudbrain.ID
taskDetail.JobID = ciTasks[i].Cloudbrain.JobID
@@ -758,11 +773,12 @@ func GetCloudbrainsDetailData(ctx *context.Context) {
taskDetail.RepoName = ciTasks[i].Repo.OwnerName + "/" + ciTasks[i].Repo.Name
taskDetail.RepoAlias = ciTasks[i].Repo.OwnerName + "/" + ciTasks[i].Repo.Alias
}
taskDetail.CardNum, taskDetail.CardType, _ = repo.GetCloudbrainCardNumAndType(ciTasks[i].Cloudbrain)
if ciTasks[i].Cloudbrain.WorkServerNumber >= 1 {
taskDetail.WorkServerNum = int64(ciTasks[i].Cloudbrain.WorkServerNumber)
} else {
taskDetail.WorkServerNum = 1
}
taskDetail.CardDuration = repo.GetCloudbrainCardDuration(ciTasks[i].Cloudbrain)
taskDetail.AiCenter = repo.GetCloudbrainAiCenter(ciTasks[i].Cloudbrain, ctx)
taskDetail.FlavorName, _ = repo.GetCloudbrainFlavorName(ciTasks[i].Cloudbrain)

taskDetail.WaitTime = repo.GetCloudbrainWaitTime(ciTasks[i].Cloudbrain)

if ciTasks[i].Cloudbrain.DeletedAt != nilTime || ciTasks[i].Repo == nil {
@@ -787,17 +803,6 @@ func GetCloudbrainsDetailData(ctx *context.Context) {
})
}

func getCloudbrainAiCenter(task models.Cloudbrain, ctx *context.Context) string {
if task.Type == models.TypeCloudBrainOne {
return ctx.Tr("repo.cloudbrain1")
} else if task.Type == models.TypeCloudBrainTwo {
return ctx.Tr("repo.cloudbrain2")
} else if task.Type == models.TypeC2Net {
return task.AiCenter
}
return ""
}

func GetCloudbrainsCreateHoursData(ctx *context.Context) {
recordCloudbrain, err := models.GetRecordBeginTime()
if err != nil {
@@ -958,11 +963,12 @@ func GetRunningTop(ctx *context.Context) {
})
}

func getCloudbrainCount(beginTime time.Time, endTime time.Time, cloudbrains []*models.CloudbrainInfo) (map[string]int, map[string]int, map[string]int, map[int]int, map[string]int) {
func getCloudbrainCount(beginTime time.Time, endTime time.Time, cloudbrains []*models.CloudbrainInfo) (map[string]int, map[string]int, map[string]int, map[string]int, map[int]int, map[string]int) {

cloudOneJobTypeRes := make(map[string]int)
cloudTwoJobTypeRes := make(map[string]int)
intelligentNetJobTypeRes := make(map[string]int)
cDCenterJobTypeRes := make(map[string]int)
cloudBrainPeriodNum := make(map[int]int)
cloudBrainComputeResource := make(map[string]int)
for _, cloudbrain := range cloudbrains {
@@ -1005,7 +1011,7 @@ func getCloudbrainCount(beginTime time.Time, endTime time.Time, cloudbrains []*m
}

jobTypeList := []string{"DEBUG", "BENCHMARK", "INFERENCE", "TRAIN", "SNN4IMAGENET", "BRAINSCORE"}
cloudBrainTypeList := []int{0, 1, 2}
cloudBrainTypeList := []int{0, 1, 2, 3}
for _, v := range jobTypeList {
if _, ok := cloudOneJobTypeRes[v]; !ok {
cloudOneJobTypeRes[v] = 0
@@ -1016,14 +1022,17 @@ func getCloudbrainCount(beginTime time.Time, endTime time.Time, cloudbrains []*m
if _, ok := intelligentNetJobTypeRes[v]; !ok {
intelligentNetJobTypeRes[v] = 0
}
if _, ok := cDCenterJobTypeRes[v]; !ok {
cDCenterJobTypeRes[v] = 0
}
}
for _, v := range cloudBrainTypeList {
if _, ok := cloudBrainPeriodNum[v]; !ok {
cloudBrainPeriodNum[v] = 0
}
}
cloudBrainPeriodNum[-1] = cloudBrainPeriodNum[0] + cloudBrainPeriodNum[1] + cloudBrainPeriodNum[2]
return cloudOneJobTypeRes, cloudTwoJobTypeRes, intelligentNetJobTypeRes, cloudBrainPeriodNum, cloudBrainComputeResource
cloudBrainPeriodNum[-1] = cloudBrainPeriodNum[0] + cloudBrainPeriodNum[1] + cloudBrainPeriodNum[2] + cloudBrainPeriodNum[3]
return cloudOneJobTypeRes, cloudTwoJobTypeRes, intelligentNetJobTypeRes, cDCenterJobTypeRes, cloudBrainPeriodNum, cloudBrainComputeResource
}

func getDayCloudbrainNum(beginTime time.Time, endTime time.Time) ([]DateCloudbrainNum, error) {
@@ -1040,12 +1049,13 @@ func getDayCloudbrainNum(beginTime time.Time, endTime time.Time) ([]DateCloudbra
}
dayCloudbrainNum := make([]DateCloudbrainNum, 0)
for endTimeTemp.Before(endTime) || endTimeTemp.Equal(endTime) {
cloudOneJobTypeRes, cloudTwoJobTypeRes, intelligentNetJobTypeRes, cloudBrainPeriodNum, cloudBrainComputeResource := getCloudbrainCount(beginTime, endTimeTemp, cloudbrains)
cloudOneJobTypeRes, cloudTwoJobTypeRes, intelligentNetJobTypeRes, cDCenterJobTypeRes, cloudBrainPeriodNum, cloudBrainComputeResource := getCloudbrainCount(beginTime, endTimeTemp, cloudbrains)
dayCloudbrainNum = append(dayCloudbrainNum, DateCloudbrainNum{
Date: beginTime.Format("2006/01/02"),
CloudOneJobTypeRes: cloudOneJobTypeRes,
CloudTwoJobTypeRes: cloudTwoJobTypeRes,
IntelligentNetJobTypeRes: intelligentNetJobTypeRes,
CDCenterJobTypeRes: cDCenterJobTypeRes,
CloudBrainPeriodNum: cloudBrainPeriodNum,
CloudBrainComputeResource: cloudBrainComputeResource,
})
@@ -1075,12 +1085,13 @@ func getMonthCloudbrainNum(beginTime time.Time, endTime time.Time) ([]DateCloudb
return nil, err
}
for endTimeTemp.Before(endTime) || endTimeTemp.Equal(endTime) {
cloudOneJobTypeRes, cloudTwoJobTypeRes, intelligentNetJobTypeRes, cloudBrainPeriodNum, cloudBrainComputeResource := getCloudbrainCount(beginTime, endTimeTemp, cloudbrains)
cloudOneJobTypeRes, cloudTwoJobTypeRes, intelligentNetJobTypeRes, cDCenterJobTypeRes, cloudBrainPeriodNum, cloudBrainComputeResource := getCloudbrainCount(beginTime, endTimeTemp, cloudbrains)
monthCloudbrainNum = append(monthCloudbrainNum, DateCloudbrainNum{
Date: beginTime.Format("2006/01"),
CloudOneJobTypeRes: cloudOneJobTypeRes,
CloudTwoJobTypeRes: cloudTwoJobTypeRes,
IntelligentNetJobTypeRes: intelligentNetJobTypeRes,
CDCenterJobTypeRes: cDCenterJobTypeRes,
CloudBrainPeriodNum: cloudBrainPeriodNum,
CloudBrainComputeResource: cloudBrainComputeResource,
})
@@ -1113,7 +1124,7 @@ func getDayCloudbrainInfo(beginTime time.Time, endTime time.Time) ([]DateCloudbr
dayCloudbrainInfo := make([]DateCloudbrainInfo, 0)
count := 0
for beginTime.Before(endTimeTemp) || beginTime.Equal(endTimeTemp) {
_, _, _, cloudBrainPeriodNum, cloudBrainComputeResource := getCloudbrainCount(endTimeTemp, endTime, cloudbrains)
_, _, _, _, cloudBrainPeriodNum, cloudBrainComputeResource := getCloudbrainCount(endTimeTemp, endTime, cloudbrains)
dayCloudbrainInfo = append(dayCloudbrainInfo, DateCloudbrainInfo{
Date: endTimeTemp.Format("2006/01/02"),
CloudBrainPeriodNum: cloudBrainPeriodNum,
@@ -1144,7 +1155,7 @@ func getMonthCloudbrainInfo(beginTime time.Time, endTime time.Time) ([]DateCloud
dayCloudbrainInfo := make([]DateCloudbrainInfo, 0)
count := 0
for beginTime.Before(endTimeTemp) || beginTime.Equal(endTimeTemp) || (endTimeTemp.Before(beginTime) && beginTime.Before(endTime)) {
_, _, _, cloudBrainPeriodNum, cloudBrainComputeResource := getCloudbrainCount(endTimeTemp, endTime, cloudbrains)
_, _, _, _, cloudBrainPeriodNum, cloudBrainComputeResource := getCloudbrainCount(endTimeTemp, endTime, cloudbrains)
dayCloudbrainInfo = append(dayCloudbrainInfo, DateCloudbrainInfo{
Date: endTimeTemp.Format("2006/01"),
CloudBrainPeriodNum: cloudBrainPeriodNum,
@@ -1205,6 +1216,7 @@ func DownloadCloudBrainBoard(ctx *context.Context) {
log.Warn("Can not get cloud brain info", err)
continue
}
models.LoadSpecs4CloudbrainInfo(pageRecords)
for _, record := range pageRecords {

for k, v := range allCloudbrainValues(row, record, ctx) {
@@ -1235,10 +1247,9 @@ func allCloudbrainHeader(ctx *context.Context) map[string]string {
"H1": ctx.Tr("cloudbrain.card_duration"),
"I1": ctx.Tr("repo.modelarts.train_job.start_time"), "J1": ctx.Tr("repo.modelarts.train_job.end_time"),
"K1": ctx.Tr("repo.modelarts.computing_resources"), "L1": ctx.Tr("cloudbrain.card_type"),
"M1": ctx.Tr("repo.grampus.train_job.ai_center"), "N1": ctx.Tr("cloudbrain.resource_specification"),
"O1": ctx.Tr("repo.cloudbrain_creator"), "P1": ctx.Tr("repo.repo_name"), "Q1": ctx.Tr("repo.cloudbrain_task_name"),
"R1": ctx.Tr("repo.modelarts.deletetime")}

"M1": ctx.Tr("repo.modelarts.train_job.amount_of_compute_node"), "N1": ctx.Tr("repo.grampus.train_job.ai_center"),
"O1": ctx.Tr("cloudbrain.resource_specification"), "P1": ctx.Tr("repo.cloudbrain_creator"), "Q1": ctx.Tr("repo.repo_name"),
"R1": ctx.Tr("repo.cloudbrain_task_name"), "S1": ctx.Tr("repo.modelarts.deletetime")}
}
func allCloudbrainValues(row int, rs *models.CloudbrainInfo, ctx *context.Context) map[string]string {
return map[string]string{getCellName("A", row): rs.DisplayJobName, getCellName("B", row): getCloudbrainType(rs, ctx), getCellName("C", row): rs.Status, getCellName("D", row): rs.JobType,
@@ -1246,9 +1257,16 @@ func allCloudbrainValues(row int, rs *models.CloudbrainInfo, ctx *context.Contex
getCellName("G", row): rs.TrainJobDuration, getCellName("H", row): repo.GetCloudbrainCardDuration(rs.Cloudbrain),
getCellName("I", row): getBrainStartTime(rs),
getCellName("J", row): getBrainEndTime(rs), getCellName("K", row): rs.ComputeResource, getCellName("L", row): getCloudbrainCardType(rs),
getCellName("M", row): repo.GetCloudbrainAiCenter(rs.Cloudbrain, ctx), getCellName("N", row): getCloudbrainFlavorName(rs),
getCellName("O", row): rs.Name, getCellName("P", row): getBrainRepo(rs),
getCellName("Q", row): rs.JobName, getCellName("R", row): getBrainDeleteTime(rs),
getCellName("M", row): getWorkServerNum(rs), getCellName("N", row): repo.GetCloudbrainAiCenter(rs.Cloudbrain, ctx),
getCellName("O", row): getCloudbrainFlavorName(rs), getCellName("P", row): rs.Name,
getCellName("Q", row): getBrainRepo(rs), getCellName("R", row): rs.JobName, getCellName("S", row): getBrainDeleteTime(rs),
}
}
func getWorkServerNum(rs *models.CloudbrainInfo) string {
if rs.Cloudbrain.WorkServerNumber >= 1 {
return fmt.Sprint(rs.Cloudbrain.WorkServerNumber)
} else {
return "1"
}
}
func getBrainRepo(rs *models.CloudbrainInfo) string {
@@ -1287,11 +1305,14 @@ func getCloudbrainType(rs *models.CloudbrainInfo, ctx *context.Context) string {
}
}
func getCloudbrainCardType(rs *models.CloudbrainInfo) string {
_, cardType, _ := repo.GetCloudbrainCardNumAndType(rs.Cloudbrain)
return cardType
if rs.Cloudbrain.Spec != nil {
return rs.Cloudbrain.Spec.AccCardType
} else {
return ""
}
}
func getCloudbrainFlavorName(rs *models.CloudbrainInfo) string {
flavorName, _ := repo.GetCloudbrainFlavorName(rs.Cloudbrain)
flavorName := repo.GetCloudbrainFlavorName(rs.Cloudbrain)
return flavorName
}



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

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

import (
"fmt"
"html/template"
"net/http"

"code.gitea.io/gitea/models"
@@ -118,7 +119,7 @@ func CreateFork(ctx *context.APIContext, form api.CreateForkOption) {
forker = org
}

fork, err := repo_service.ForkRepository(ctx.User, forker, repo, repo.Name, repo.Description, repo.Alias)
fork, err := repo_service.ForkRepository(ctx.User, forker, repo, repo.Name, template.HTMLEscapeString(repo.Description), repo.Alias)
if err != nil {
ctx.Error(http.StatusInternalServerError, "ForkRepository", err)
return


+ 78
- 0
routers/modelapp/desensitization.go View File

@@ -0,0 +1,78 @@
package modelapp

import (
"bytes"
"code.gitea.io/gitea/models"
"crypto/tls"
"image"
"image/png"
"net/http"
"strconv"

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

"code.gitea.io/gitea/modules/base"

"code.gitea.io/gitea/modules/context"
"github.com/go-resty/resty/v2"
)

var restyClient *resty.Client
var tplExploreUpload base.TplName = "model/tuomin/upload"
var uploadUrl = "/extension/tuomin/upload"
var allowedContentType = []string{"image/jpeg", "image/jpg", "image/png"}

func ProcessImageUI(ctx *context.Context) {
ctx.HTML(200, tplExploreUpload)
}

func ProcessImage(ctx *context.Context) {

file, header, err := ctx.GetFile("file")
if err != nil {
ctx.JSON(http.StatusBadRequest,models.BaseErrorMessage(ctx.Tr("model_app.get_file_fail")))
return
}
defer file.Close()

contentType := header.Header.Get("Content-Type")

if !isInAllowedContentType(contentType) {
ctx.JSON(http.StatusBadRequest,models.BaseErrorMessage(ctx.Tr("model_app.content_type_unsupported")))
return
}

client := getRestyClient()
res, err := client.R().SetMultipartField(
"file", header.Filename, contentType, file).Post(setting.ModelApp.DesensitizationUrl + "?mode=" + strconv.Itoa(ctx.QueryInt("mode")))
if err != nil {
ctx.JSON(http.StatusBadRequest,models.BaseErrorMessage(ctx.Tr("model_app.process_image_fail")))
return
}
image, _, err := image.Decode(bytes.NewReader(res.Body()))
if err != nil {
ctx.JSON(http.StatusBadRequest,models.BaseErrorMessage(ctx.Tr("model_app.process_image_fail")))
return
}

png.Encode(ctx.Resp, image)
return

}

func isInAllowedContentType(contentType string) bool {
for _, allowType := range allowedContentType {
if allowType == contentType {
return true
}
}
return false
}

func getRestyClient() *resty.Client {
if restyClient == nil {
restyClient = resty.New()
restyClient.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})
}
return restyClient
}

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

@@ -8,6 +8,7 @@ import (
"net/http"
"net/url"
"path"
"regexp"
"strings"

"code.gitea.io/gitea/models"
@@ -85,6 +86,7 @@ func saveModelByParameters(jobId string, versionName string, name string, versio
accuracy["Precision"] = ""
accuracyJson, _ := json.Marshal(accuracy)
log.Info("accuracyJson=" + string(accuracyJson))
aiTask.ContainerIp = ""
aiTaskJson, _ := json.Marshal(aiTask)

model := &models.AiModelManage{
@@ -635,6 +637,7 @@ func ShowSingleModel(ctx *context.Context) {
userNameMap := queryUserName(userIds)

for _, model := range models {
removeIpInfo(model)
value := userNameMap[model.UserId]
if value != nil {
model.UserName = value.Name
@@ -644,6 +647,13 @@ func ShowSingleModel(ctx *context.Context) {
ctx.JSON(http.StatusOK, models)
}

func removeIpInfo(model *models.AiModelManage) {
reg, _ := regexp.Compile(`[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}`)
taskInfo := model.TrainTaskInfo
taskInfo = reg.ReplaceAllString(taskInfo, "")
model.TrainTaskInfo = taskInfo
}

func queryUserName(intSlice []int64) map[int64]*models.User {
keys := make(map[int64]string)
uniqueElements := []int64{}
@@ -677,6 +687,7 @@ func ShowOneVersionOtherModel(ctx *context.Context) {
userNameMap := queryUserName(userIds)

for _, model := range aimodels {
removeIpInfo(model)
value := userNameMap[model.UserId]
if value != nil {
model.UserName = value.Name
@@ -793,6 +804,7 @@ func ShowModelPageInfo(ctx *context.Context) {
userNameMap := queryUserName(userIds)

for _, model := range modelResult {
removeIpInfo(model)
value := userNameMap[model.UserId]
if value != nil {
model.UserName = value.Name
@@ -866,6 +878,7 @@ func QueryModelListForPredict(ctx *context.Context) {

nameMap := make(map[string][]*models.AiModelManage)
for _, model := range modelResult {
removeIpInfo(model)
if _, value := nameMap[model.Name]; !value {
models := make([]*models.AiModelManage, 0)
models = append(models, model)


+ 1049
- 0
routers/repo/aisafety.go View File

@@ -0,0 +1,1049 @@
package repo

import (
"bufio"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"strconv"
"strings"
"time"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/aisafety"
"code.gitea.io/gitea/modules/cloudbrain"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/modelarts"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/cloudbrain/resource"
"code.gitea.io/gitea/services/reward/point/account"
uuid "github.com/satori/go.uuid"
)

const (
tplModelSafetyTestCreateGrampusGpu = "repo/modelsafety/newgrampusgpu"
tplModelSafetyTestCreateGrampusNpu = "repo/modelsafety/newgrampusnpu"
tplModelSafetyTestCreateGpu = "repo/modelsafety/newgpu"
tplModelSafetyTestCreateNpu = "repo/modelsafety/newnpu"
tplModelSafetyTestShow = "repo/modelsafety/show"
)

func CloudBrainAiSafetyCreateTest(ctx *context.Context) {
log.Info("start to create CloudBrainAiSafetyCreate")
uuid := uuid.NewV4()
id := uuid.String()
seriaNoParas := ctx.Query("serialNo")
fileName := ctx.Query("fileName")

//if jobType == string(models.JobTypeBenchmark) {
req := aisafety.TaskReq{
UnionId: id,
EvalName: "test1",
EvalContent: "test1",
TLPath: "test1",
Indicators: []string{"ACC", "ASS"},
CDName: "CIFAR10_1000_FGSM",
BDName: "CIFAR10_1000基础数据集",
}
aisafety.GetAlgorithmList()
if seriaNoParas != "" {
aisafety.GetTaskStatus(seriaNoParas)
} else {
jsonStr, err := getJsonContent("http://192.168.207.34:8065/Test_zap1234/openi_aisafety/raw/branch/master/result/" + fileName)
serialNo, err := aisafety.CreateSafetyTask(req, jsonStr)
if err == nil {
log.Info("serialNo=" + serialNo)
time.Sleep(time.Duration(2) * time.Second)
aisafety.GetTaskStatus(serialNo)
} else {
log.Info("CreateSafetyTask error," + err.Error())
}
}
}

func GetAiSafetyTaskByJob(job *models.Cloudbrain) {
if job == nil {
log.Error("GetCloudbrainByJobID failed")
return
}
syncAiSafetyTaskStatus(job)
}

func GetAiSafetyTaskTmpl(ctx *context.Context) {
ctx.Data["id"] = ctx.Params(":id")
ctx.Data["PageIsCloudBrain"] = true
ctx.HTML(200, tplModelSafetyTestShow)
}

func GetAiSafetyTask(ctx *context.Context) {
var ID = ctx.Params(":id")
job, err := models.GetCloudbrainByIDWithDeleted(ID)
if err != nil {
log.Error("GetCloudbrainByJobID failed:" + err.Error())
return
}
syncAiSafetyTaskStatus(job)
job, err = models.GetCloudbrainByIDWithDeleted(ID)
job.BenchmarkType = "安全评测"
job.BenchmarkTypeName = "Image Classification"
job.CanModify = cloudbrain.CanModifyJob(ctx, job)
job.CanDel = cloudbrain.CanDeleteJob(ctx, job)
if job.Parameters == "{\"parameter\":[]}" {
job.Parameters = ""
}
s, err := resource.GetCloudbrainSpec(job.ID)
if err == nil {
job.Spec = s
}
user, err := models.GetUserByID(job.UserID)
if err == nil {
tmpUser := &models.User{
Name: user.Name,
}
job.User = tmpUser
}

ctx.JSON(200, job)
}

func StopAiSafetyTask(ctx *context.Context) {
log.Info("start to stop the task.")
var ID = ctx.Params(":id")
task, err := models.GetCloudbrainByIDWithDeleted(ID)
result := make(map[string]interface{})
result["result_code"] = "-1"
if err != nil {
log.Info("query task error.err=" + err.Error())
log.Error("GetCloudbrainByJobID failed:" + err.Error())
result["msg"] = "No such task."
ctx.JSON(200, result)
return
}
if isTaskNotFinished(task.Status) {
if task.Type == models.TypeCloudBrainTwo {
log.Info("start to stop model arts task.")
_, err := modelarts.StopTrainJob(task.JobID, strconv.FormatInt(task.VersionID, 10))
if err != nil {
log.Info("stop failed.err=" + err.Error())
}
task.Status = string(models.JobStopped)
if task.EndTime == 0 {
task.EndTime = timeutil.TimeStampNow()
}
task.ComputeAndSetDuration()
err = models.UpdateJob(task)
if err != nil {
log.Error("UpdateJob(%s) failed:%v", task.JobName, err, ctx.Data["msgID"])
result["msg"] = "cloudbrain.Stopped_success_update_status_fail"
ctx.JSON(200, result)
return
}
//queryTaskStatusFromCloudbrainTwo(job)
} else if task.Type == models.TypeCloudBrainOne {
if task.Status == string(models.JobStopped) || task.Status == string(models.JobFailed) || task.Status == string(models.JobSucceeded) {
log.Error("the job(%s) has been stopped", task.JobName, ctx.Data["msgID"])
result["msg"] = "cloudbrain.Already_stopped"
ctx.JSON(200, result)
return
}
err := cloudbrain.StopJob(task.JobID)
if err != nil {
log.Error("StopJob(%s) failed:%v", task.JobName, err, ctx.Data["msgID"])
result["msg"] = "cloudbrain.Stopped_failed"
ctx.JSON(200, result)
return
}
task.Status = string(models.JobStopped)
if task.EndTime == 0 {
task.EndTime = timeutil.TimeStampNow()
}
task.ComputeAndSetDuration()
err = models.UpdateJob(task)
if err != nil {
log.Error("UpdateJob(%s) failed:%v", task.JobName, err, ctx.Data["msgID"])
result["msg"] = "cloudbrain.Stopped_success_update_status_fail"
ctx.JSON(200, result)
return
}
}
} else {
if task.Status == string(models.ModelSafetyTesting) {
//修改为Failed
task.Status = string(models.JobStopped)
if task.EndTime == 0 {
task.EndTime = timeutil.TimeStampNow()
}
task.ComputeAndSetDuration()
err = models.UpdateJob(task)
if err != nil {
log.Error("UpdateJob(%s) failed:%v", task.JobName, err, ctx.Data["msgID"])
result["msg"] = "cloudbrain.Stopped_success_update_status_fail"
ctx.JSON(200, result)
return
}
} else {
log.Info("The job is finished. status=" + task.Status)
}
}
result["result_code"] = "0"
result["msg"] = "succeed"
ctx.JSON(200, result)

}

func DelAiSafetyTask(ctx *context.Context) {
var ID = ctx.Params(":id")
task, err := models.GetCloudbrainByIDWithDeleted(ID)

if err != nil {
log.Error("GetCloudbrainByJobID failed:" + err.Error())
ctx.ServerError("No such task.", err)
return
}
if task.Status != string(models.JobStopped) && task.Status != string(models.JobFailed) && task.Status != string(models.JobSucceeded) {
log.Error("the job(%s) has not been stopped", task.JobName, ctx.Data["msgID"])
ctx.ServerError("the job("+task.JobName+") has not been stopped", nil)
return
}
if task.Type == models.TypeCloudBrainOne {
DeleteCloudbrainJobStorage(task.JobName, models.TypeCloudBrainOne)
}
err = models.DeleteJob(task)
if err != nil {
ctx.ServerError(err.Error(), err)
return
}
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/cloudbrain/benchmark")
}

func syncAiSafetyTaskStatus(job *models.Cloudbrain) {
log.Info("start to query safety task status.")
if isTaskNotFinished(job.Status) {
if job.Type == models.TypeCloudBrainTwo {
queryTaskStatusFromCloudbrainTwo(job)
} else if job.Type == models.TypeCloudBrainOne {
queryTaskStatusFromCloudbrain(job)
}
} else {
if job.Status == string(models.ModelSafetyTesting) {
queryTaskStatusFromModelSafetyTestServer(job)
} else {
log.Info("The job is finished. status=" + job.Status)
}
}
}

func TimerHandleModelSafetyTestTask() {
log.Info("start to TimerHandleModelSafetyTestTask")
tasks, err := models.GetModelSafetyTestTask()
if err == nil {
if tasks != nil && len(tasks) > 0 {
for _, job := range tasks {
syncAiSafetyTaskStatus(job)
}
} else {
log.Info("query running model safety test task 0.")
}
} else {
log.Info("query running model safety test task err." + err.Error())
}
}

func queryTaskStatusFromCloudbrainTwo(job *models.Cloudbrain) {
log.Info("The task not finished,name=" + job.DisplayJobName)
result, err := modelarts.GetTrainJob(job.JobID, strconv.FormatInt(job.VersionID, 10))
if err != nil {
log.Info("query train job error." + err.Error())
return
}

job.Status = modelarts.TransTrainJobStatus(result.IntStatus)
job.Duration = result.Duration / 1000
job.TrainJobDuration = result.TrainJobDuration

if job.StartTime == 0 && result.StartTime > 0 {
job.StartTime = timeutil.TimeStamp(result.StartTime / 1000)
}
job.TrainJobDuration = models.ConvertDurationToStr(job.Duration)
if job.EndTime == 0 && models.IsTrainJobTerminal(job.Status) && job.StartTime > 0 {
job.EndTime = job.StartTime.Add(job.Duration)
}
job.CorrectCreateUnix()

if job.Status != string(models.ModelArtsTrainJobCompleted) {
log.Info("CloudbrainTwo task status=" + job.Status)
err = models.UpdateJob(job)
if err != nil {
log.Error("UpdateJob failed:", err)
}
} else {
log.Info("start to deal ModelSafetyTesting, task status=" + job.Status)
job.Status = string(models.ModelSafetyTesting)
err = models.UpdateJob(job)
if err != nil {
log.Error("UpdateJob failed:", err)
}
//send msg to beihang
sendNPUInferenceResultToTest(job)
}

}

func queryTaskStatusFromCloudbrain(job *models.Cloudbrain) {

log.Info("The task not finished,name=" + job.DisplayJobName)
jobResult, err := cloudbrain.GetJob(job.JobID)

result, err := models.ConvertToJobResultPayload(jobResult.Payload)
if err != nil {
log.Error("ConvertToJobResultPayload failed:", err)
return
}
job.Status = result.JobStatus.State
if result.JobStatus.State != string(models.JobWaiting) && result.JobStatus.State != string(models.JobFailed) {
taskRoles := result.TaskRoles
taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{}))
job.Status = taskRes.TaskStatuses[0].State
}
models.ParseAndSetDurationFromCloudBrainOne(result, job)
//updateCloudBrainOneJobTime(job)
log.Info("cloud brain one job status=" + job.Status)
if result.JobStatus.State != string(models.JobSucceeded) {
err = models.UpdateJob(job)
if err != nil {
log.Error("UpdateJob failed:", err)
}
} else {
//
job.Status = string(models.ModelSafetyTesting)
err = models.UpdateJob(job)
if err != nil {
log.Error("UpdateJob failed:", err)
}
//send msg to beihang
sendGPUInferenceResultToTest(job)
}
}

func queryTaskStatusFromModelSafetyTestServer(job *models.Cloudbrain) {
result, err := aisafety.GetTaskStatus(job.PreVersionName)
if err == nil {
if result.Code == "0" {
if result.Data.Status == 1 {
log.Info("The task is running....")
} else {
if result.Data.Code == 0 {
job.ResultJson = result.Data.StandardJson
job.Status = string(models.JobSucceeded)
err = models.UpdateJob(job)
if err != nil {
log.Error("UpdateJob failed:", err)
}
} else {
job.ResultJson = result.Data.Msg
job.Status = string(models.JobFailed)
err = models.UpdateJob(job)
if err != nil {
log.Error("UpdateJob failed:", err)
}
}
}
} else {
log.Info("The task is failed.")
job.Status = string(models.JobFailed)
err = models.UpdateJob(job)
if err != nil {
log.Error("UpdateJob failed:", err)
}
}
} else {
log.Info("The task not found.....")
}
}

func getAisafetyTaskReq(job *models.Cloudbrain) aisafety.TaskReq {
datasetname := job.DatasetName
datasetnames := strings.Split(datasetname, ";")
indicator := job.LabelName
EvalContent := "test1"
if job.Description != "" {
EvalContent = job.Description
}
req := aisafety.TaskReq{
UnionId: job.JobID,
EvalName: job.DisplayJobName,
EvalContent: EvalContent,
TLPath: "test1",
Indicators: strings.Split(indicator, ";"),
CDName: strings.Split(datasetnames[1], ".")[0],
BDName: strings.Split(datasetnames[0], ".")[0] + "基础数据集",
}
log.Info("CDName=" + req.CDName)
log.Info("BDName=" + req.BDName)
return req
}

func sendGPUInferenceResultToTest(job *models.Cloudbrain) {
log.Info("send sendGPUInferenceResultToTest")
req := getAisafetyTaskReq(job)
resultDir := "/result"
prefix := setting.CBCodePathPrefix + job.JobName + resultDir
files, err := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, "")
if err != nil {
log.Error("query cloudbrain one model failed: %v", err)
return
}
jsonContent := ""
for _, file := range files {
if strings.HasSuffix(file.FileName, "result.json") {
path := storage.GetMinioPath(job.JobName+resultDir+"/", file.FileName)
log.Info("path=" + path)
reader, err := os.Open(path)
defer reader.Close()
if err == nil {
r := bufio.NewReader(reader)
for {
line, error := r.ReadString('\n')
jsonContent += line
if error == io.EOF {
log.Info("read file completed.")
break
}
if error != nil {
log.Info("read file error." + error.Error())
break
}
}
}
break
}
}
if jsonContent != "" {
sendHttpReqToBeihang(job, jsonContent, req)
} else {
updateJobFailed(job, "推理生成的Json数据为空,无法进行评测。")
}
}

func sendNPUInferenceResultToTest(job *models.Cloudbrain) {
log.Info("start to sendNPUInferenceResultToTest")
req := getAisafetyTaskReq(job)
jsonContent := ""
VersionOutputPath := modelarts.GetOutputPathByCount(modelarts.TotalVersionCount)
resultPath := modelarts.JobPath + job.JobName + modelarts.ResultPath + VersionOutputPath + "/result.json"
resultPath = resultPath[1:]
log.Info("bucket=" + setting.Bucket + " resultPath=" + resultPath)
body, err := storage.ObsDownloadAFile(setting.Bucket, resultPath)
if err != nil {
log.Info("ObsDownloadAFile error." + err.Error() + " resultPath=" + resultPath)
} else {
defer body.Close()
var data []byte
p := make([]byte, 4096)
var readErr error
var readCount int
for {
readCount, readErr = body.Read(p)
if readCount > 0 {
data = append(data, p[:readCount]...)
}
if readErr != nil || readCount == 0 {
break
}
}
jsonContent = string(data)
}

if jsonContent != "" {
sendHttpReqToBeihang(job, jsonContent, req)
} else {
updateJobFailed(job, "推理生成的Json数据为空,无法进行评测。")
}
}
func updateJobFailed(job *models.Cloudbrain, msg string) {
log.Info("The json is null. so set it failed.")
//update task failed.
job.Status = string(models.ModelArtsTrainJobFailed)
job.ResultJson = msg
err := models.UpdateJob(job)
if err != nil {
log.Error("UpdateJob failed:", err)
}
}
func sendHttpReqToBeihang(job *models.Cloudbrain, jsonContent string, req aisafety.TaskReq) {
log.Info("start to send beihang ...")
serialNo, err := aisafety.CreateSafetyTask(req, jsonContent)
if err == nil {
//update serial no to db
job.PreVersionName = serialNo
err = models.UpdateJob(job)
if err != nil {
log.Error("UpdateJob failed:", err)
}
}
}

func isTaskNotFinished(status string) bool {
if status == string(models.ModelArtsTrainJobRunning) || status == string(models.ModelArtsTrainJobWaiting) {
return true
}
if status == string(models.JobWaiting) || status == string(models.JobRunning) {
return true
}

if status == string(models.ModelArtsTrainJobUnknown) || status == string(models.ModelArtsTrainJobInit) {
return true
}
if status == string(models.ModelArtsTrainJobImageCreating) || status == string(models.ModelArtsTrainJobSubmitTrying) {
return true
}
return false
}

func AiSafetyCreateForGetGPU(ctx *context.Context) {
t := time.Now()
ctx.Data["PageIsCloudBrain"] = true
ctx.Data["IsCreate"] = true
ctx.Data["type"] = models.TypeCloudBrainOne
ctx.Data["compute_resource"] = models.GPUResource
ctx.Data["datasetType"] = models.TypeCloudBrainOne
ctx.Data["BaseDataSetName"] = setting.ModelSafetyTest.GPUBaseDataSetName
ctx.Data["BaseDataSetUUID"] = setting.ModelSafetyTest.GPUBaseDataSetUUID
ctx.Data["CombatDataSetName"] = setting.ModelSafetyTest.GPUCombatDataSetName
ctx.Data["CombatDataSetUUID"] = setting.ModelSafetyTest.GPUCombatDataSetUUID
log.Info("GPUBaseDataSetName=" + setting.ModelSafetyTest.GPUBaseDataSetName)
log.Info("GPUBaseDataSetUUID=" + setting.ModelSafetyTest.GPUBaseDataSetUUID)
log.Info("GPUCombatDataSetName=" + setting.ModelSafetyTest.GPUCombatDataSetName)
log.Info("GPUCombatDataSetUUID=" + setting.ModelSafetyTest.GPUCombatDataSetUUID)
var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
ctx.Data["display_job_name"] = displayJobName
prepareCloudbrainOneSpecs(ctx)
queuesDetail, _ := cloudbrain.GetQueuesDetail()
if queuesDetail != nil {
ctx.Data["QueuesDetail"] = queuesDetail
reqPara, _ := json.Marshal(queuesDetail)
log.Warn("The GPU WaitCount json:", string(reqPara))
} else {
log.Info("The GPU WaitCount not get")
}
ctx.HTML(200, tplModelSafetyTestCreateGpu)
}

func AiSafetyCreateForGetNPU(ctx *context.Context) {
t := time.Now()
ctx.Data["PageIsCloudBrain"] = true
ctx.Data["IsCreate"] = true
ctx.Data["type"] = models.TypeCloudBrainTwo
ctx.Data["compute_resource"] = models.NPUResource
var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
ctx.Data["display_job_name"] = displayJobName
ctx.Data["datasetType"] = models.TypeCloudBrainTwo
ctx.Data["BaseDataSetName"] = setting.ModelSafetyTest.NPUBaseDataSetName
ctx.Data["BaseDataSetUUID"] = setting.ModelSafetyTest.NPUBaseDataSetUUID
ctx.Data["CombatDataSetName"] = setting.ModelSafetyTest.NPUCombatDataSetName
ctx.Data["CombatDataSetUUID"] = setting.ModelSafetyTest.NPUCombatDataSetUUID

log.Info("NPUBaseDataSetName=" + setting.ModelSafetyTest.NPUBaseDataSetName)
log.Info("NPUBaseDataSetUUID=" + setting.ModelSafetyTest.NPUBaseDataSetUUID)
log.Info("NPUCombatDataSetName=" + setting.ModelSafetyTest.NPUCombatDataSetName)
log.Info("NPUCombatDataSetUUID=" + setting.ModelSafetyTest.NPUCombatDataSetUUID)
var resourcePools modelarts.ResourcePool
if err := json.Unmarshal([]byte(setting.ResourcePools), &resourcePools); err != nil {
ctx.ServerError("json.Unmarshal failed:", err)
}
ctx.Data["resource_pools"] = resourcePools.Info

var engines modelarts.Engine
if err := json.Unmarshal([]byte(setting.Engines), &engines); err != nil {
ctx.ServerError("json.Unmarshal failed:", err)
}
ctx.Data["engines"] = engines.Info

var versionInfos modelarts.VersionInfo
if err := json.Unmarshal([]byte(setting.EngineVersions), &versionInfos); err != nil {
ctx.ServerError("json.Unmarshal failed:", err)
}
ctx.Data["engine_versions"] = versionInfos.Version

prepareCloudbrainTwoInferenceSpecs(ctx)
waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "")
ctx.Data["WaitCount"] = waitCount
log.Info("The NPU WaitCount is " + fmt.Sprint(waitCount))
ctx.HTML(200, tplModelSafetyTestCreateNpu)
}

func AiSafetyCreateForPost(ctx *context.Context) {
ctx.Data["PageIsCloudBrain"] = true
displayJobName := ctx.Query("display_job_name")
jobName := util.ConvertDisplayJobNameToJobName(displayJobName)

taskType := ctx.QueryInt("type")
description := ctx.Query("description")
ctx.Data["type"] = taskType
ctx.Data["displayJobName"] = displayJobName
ctx.Data["description"] = description

repo := ctx.Repo.Repository

tpname := tplCloudBrainModelSafetyNewNpu
if taskType == models.TypeCloudBrainOne {
tpname = tplCloudBrainModelSafetyNewGpu
}

tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeModelSafety), displayJobName)
if err == nil {
if len(tasks) != 0 {
log.Error("the job name did already exist", ctx.Data["MsgID"])
modelSafetyNewDataPrepare(ctx)
ctx.RenderWithErr("the job name did already exist", tpname, nil)
return
}
} else {
if !models.IsErrJobNotExist(err) {
log.Error("system error, %v", err, ctx.Data["MsgID"])
modelSafetyNewDataPrepare(ctx)
ctx.RenderWithErr("system error", tpname, nil)
return
}
}

if !jobNamePattern.MatchString(jobName) {
modelSafetyNewDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tpname, nil)
return
}

count, err := models.GetModelSafetyCountByUserID(ctx.User.ID)
if err != nil {
log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"])
modelSafetyNewDataPrepare(ctx)
ctx.RenderWithErr("system error", tpname, nil)
return
} else {
if count >= 1 {
log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
modelSafetyNewDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain.morethanonejob"), tpname, nil)
return
}
}
BootFile := ctx.Query("boot_file")
BootFile = strings.TrimSpace(BootFile)
bootFileExist, err := ctx.Repo.FileExists(BootFile, cloudbrain.DefaultBranchName)
if err != nil || !bootFileExist {
log.Error("Get bootfile error:", err)
modelSafetyNewDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_bootfile_err"), tpname, nil)
return
}
if taskType == models.TypeCloudBrainTwo {
err = createForNPU(ctx, jobName)
} else if taskType == models.TypeCloudBrainOne {
err = createForGPU(ctx, jobName)
}
if err != nil {
modelSafetyNewDataPrepare(ctx)
ctx.RenderWithErr(err.Error(), tpname, nil)
} else {
log.Info("to redirect...")
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/cloudbrain/benchmark")
}
}

func createForNPU(ctx *context.Context, jobName string) error {
VersionOutputPath := modelarts.GetOutputPathByCount(modelarts.TotalVersionCount)
BootFile := ctx.Query("boot_file")
BootFile = strings.TrimSpace(BootFile)
displayJobName := ctx.Query("display_job_name")
description := ctx.Query("description")

srcDataset := ctx.Query("src_dataset") //uuid
combatDataset := ctx.Query("combat_dataset") //uuid
evaluationIndex := ctx.Query("evaluation_index")
Params := ctx.Query("run_para_list")
specId := ctx.QueryInt64("spec_id")

engineID := ctx.QueryInt("engine_id")
log.Info("engine_id=" + fmt.Sprint(engineID))
poolID := ctx.Query("pool_id")
repo := ctx.Repo.Repository

trainUrl := ctx.Query("train_url")
modelName := ctx.Query("model_name")
modelVersion := ctx.Query("model_version")
ckptName := ctx.Query("ckpt_name")
ckptUrl := "/" + trainUrl + ckptName
log.Info("ckpt url:" + ckptUrl)

FlavorName := ctx.Query("flaver_names")
EngineName := ctx.Query("engine_names")

isLatestVersion := modelarts.IsLatestVersion
VersionCount := modelarts.VersionCountOne

codeLocalPath := setting.JobPath + jobName + modelarts.CodePath
codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath
resultObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.ResultPath + VersionOutputPath + "/"
logObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.LogPath + VersionOutputPath + "/"
log.Info("ckpt url:" + ckptUrl)
spec, err := resource.GetAndCheckSpec(ctx.User.ID, specId, models.FindSpecsOptions{
JobType: models.JobTypeInference,
ComputeResource: models.NPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainTwo})
if err != nil || spec == nil {

//ctx.RenderWithErr("Resource specification not available", tplCloudBrainModelSafetyNewNpu, nil)
return errors.New("Resource specification not available")
}
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID)
return errors.New(ctx.Tr("points.insufficient_points_balance"))
}

//todo: del the codeLocalPath
_, err = ioutil.ReadDir(codeLocalPath)
if err == nil {
os.RemoveAll(codeLocalPath)
}

gitRepo, _ := git.OpenRepository(repo.RepoPath())
commitID, _ := gitRepo.GetBranchCommitID(cloudbrain.DefaultBranchName)

if err := downloadCode(repo, codeLocalPath, cloudbrain.DefaultBranchName); err != nil {
log.Error("Create task failed, server timed out: %s (%v)", repo.FullName(), err)
return errors.New(ctx.Tr("cloudbrain.load_code_failed"))
}

//todo: upload code (send to file_server todo this work?)
if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.ResultPath + VersionOutputPath + "/"); err != nil {
log.Error("Failed to obsMkdir_result: %s (%v)", repo.FullName(), err)
return errors.New("Failed to obsMkdir_result")
}

if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.LogPath + VersionOutputPath + "/"); err != nil {
log.Error("Failed to obsMkdir_log: %s (%v)", repo.FullName(), err)
return errors.New("Failed to obsMkdir_log")
}

if err := uploadCodeToObs(codeLocalPath, jobName, ""); err != nil {
log.Error("Failed to uploadCodeToObs: %s (%v)", repo.FullName(), err)
return errors.New(ctx.Tr("cloudbrain.load_code_failed"))
}

var parameters models.Parameters
param := make([]models.Parameter, 0)
param = append(param, models.Parameter{
Label: modelarts.ResultUrl,
Value: "s3:/" + resultObsPath,
}, models.Parameter{
Label: modelarts.CkptUrl,
Value: "s3:/" + ckptUrl,
})
uuid := srcDataset + ";" + combatDataset
datasUrlList, dataUrl, datasetNames, isMultiDataset, err := getDatasUrlListByUUIDS(uuid)
if err != nil {
return err
}
dataPath := dataUrl
jsondatas, err := json.Marshal(datasUrlList)
if err != nil {
log.Error("Failed to Marshal: %v", err)
return err
}
if isMultiDataset {
param = append(param, models.Parameter{
Label: modelarts.MultiDataUrl,
Value: string(jsondatas),
})
}

existDeviceTarget := false
if len(Params) != 0 {
err := json.Unmarshal([]byte(Params), &parameters)
if err != nil {
log.Error("Failed to Unmarshal params: %s (%v)", Params, err)
return errors.New("运行参数错误")
}

for _, parameter := range parameters.Parameter {
if parameter.Label == modelarts.DeviceTarget {
existDeviceTarget = true
}
if parameter.Label != modelarts.TrainUrl && parameter.Label != modelarts.DataUrl {
param = append(param, models.Parameter{
Label: parameter.Label,
Value: parameter.Value,
})
}
}
}
if !existDeviceTarget {
param = append(param, models.Parameter{
Label: modelarts.DeviceTarget,
Value: modelarts.Ascend,
})
}

req := &modelarts.GenerateInferenceJobReq{
JobName: jobName,
DisplayJobName: displayJobName,
DataUrl: dataPath,
Description: description,
CodeObsPath: codeObsPath,
BootFileUrl: codeObsPath + BootFile,
BootFile: BootFile,
TrainUrl: trainUrl,
WorkServerNumber: 1,
EngineID: int64(engineID),
LogUrl: logObsPath,
PoolID: poolID,
Uuid: uuid,
Parameters: param, //modelarts train parameters
CommitID: commitID,
BranchName: cloudbrain.DefaultBranchName,
Params: Params,
FlavorName: FlavorName,
EngineName: EngineName,
LabelName: evaluationIndex,
IsLatestVersion: isLatestVersion,
VersionCount: VersionCount,
TotalVersionCount: modelarts.TotalVersionCount,
ModelName: modelName,
ModelVersion: modelVersion,
CkptName: ckptName,
ResultUrl: resultObsPath,
Spec: spec,
DatasetName: datasetNames,
JobType: string(models.JobTypeModelSafety),
}

err = modelarts.GenerateInferenceJob(ctx, req)
if err != nil {
log.Error("GenerateTrainJob failed:%v", err.Error())
return err
}
return nil
}

func createForGPU(ctx *context.Context, jobName string) error {
BootFile := ctx.Query("boot_file")
BootFile = strings.TrimSpace(BootFile)
displayJobName := ctx.Query("display_job_name")
description := ctx.Query("description")
image := strings.TrimSpace(ctx.Query("image"))
srcDataset := ctx.Query("src_dataset") //uuid
combatDataset := ctx.Query("combat_dataset") //uuid
evaluationIndex := ctx.Query("evaluation_index")
Params := ctx.Query("run_para_list")
specId := ctx.QueryInt64("spec_id")
TrainUrl := ctx.Query("train_url")
CkptName := ctx.Query("ckpt_name")
modelName := ctx.Query("model_name")
modelVersion := ctx.Query("model_version")

ckptUrl := setting.Attachment.Minio.RealPath + TrainUrl + CkptName
log.Info("ckpt url:" + ckptUrl)
spec, err := resource.GetAndCheckSpec(ctx.User.ID, specId, models.FindSpecsOptions{
JobType: models.JobTypeBenchmark,
ComputeResource: models.GPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainOne})
if err != nil || spec == nil {
return errors.New("Resource specification not available")
}

if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID)
return errors.New(ctx.Tr("points.insufficient_points_balance"))
}

repo := ctx.Repo.Repository
codePath := setting.JobPath + jobName + cloudbrain.CodeMountPath
os.RemoveAll(codePath)

if err := downloadCode(repo, codePath, cloudbrain.DefaultBranchName); err != nil {
log.Error("downloadCode failed, %v", err, ctx.Data["MsgID"])
return errors.New("system error")
}

err = uploadCodeToMinio(codePath+"/", jobName, cloudbrain.CodeMountPath+"/")
if err != nil {
log.Error("uploadCodeToMinio failed, %v", err, ctx.Data["MsgID"])
return errors.New("system error")
}

uuid := srcDataset + ";" + combatDataset
datasetInfos, datasetNames, err := models.GetDatasetInfo(uuid)
log.Info("uuid=" + uuid)
if err != nil {
log.Error("GetDatasetInfo failed: %v", err, ctx.Data["MsgID"])
return errors.New(ctx.Tr("cloudbrain.error.dataset_select"))
}
command, err := getGpuModelSafetyCommand(BootFile, Params, CkptName, displayJobName)
if err != nil {
log.Error("Get Command failed: %v", err, ctx.Data["MsgID"])
return errors.New(ctx.Tr("cloudbrain.error.dataset_select"))
}
log.Info("Command=" + command)

req := cloudbrain.GenerateCloudBrainTaskReq{
Ctx: ctx,
DisplayJobName: displayJobName,
JobName: jobName,
Image: image,
Command: command,
Uuids: uuid,
DatasetNames: datasetNames,
DatasetInfos: datasetInfos,
CodePath: storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"),
ModelPath: setting.Attachment.Minio.RealPath + TrainUrl,
BenchmarkPath: storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"),
Snn4ImageNetPath: storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"),
BrainScorePath: storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"),
JobType: string(models.JobTypeModelSafety),
Description: description,
BranchName: cloudbrain.DefaultBranchName,
BootFile: BootFile,
Params: Params,
CommitID: "",
ModelName: modelName,
ModelVersion: modelVersion,
CkptName: CkptName,
ResultPath: storage.GetMinioPath(jobName, cloudbrain.ResultPath+"/"),
Spec: spec,
LabelName: evaluationIndex,
}

err = cloudbrain.GenerateTask(req)
if err != nil {
return err
}
return nil
}

func getGpuModelSafetyCommand(BootFile string, params string, CkptName string, DisplayJobName string) (string, error) {
var command string
bootFile := strings.TrimSpace(BootFile)

if !strings.HasSuffix(bootFile, ".py") {
log.Error("bootFile(%s) format error", bootFile)
return command, errors.New("bootFile format error")
}

var parameters models.Parameters
var param string
if len(params) != 0 {
err := json.Unmarshal([]byte(params), &parameters)
if err != nil {
log.Error("Failed to Unmarshal params: %s (%v)", params, err)
return command, err
}

for _, parameter := range parameters.Parameter {
param += " --" + parameter.Label + "=" + parameter.Value
}
}

param += " --ckpt_url=" + cloudbrain.ModelMountPath + "/" + CkptName

command += "python /code/" + bootFile + param + " > " + cloudbrain.ResultPath + "/" + DisplayJobName + "-" + cloudbrain.LogFile

return command, nil
}

func modelSafetyNewDataPrepare(ctx *context.Context) error {
ctx.Data["PageIsCloudBrain"] = true
ctx.Data["type"] = ctx.QueryInt("type")
ctx.Data["boot_file"] = ctx.Query("boot_file")
ctx.Data["display_job_name"] = ctx.Query("display_job_name")
ctx.Data["description"] = ctx.Query("description")
ctx.Data["image"] = strings.TrimSpace(ctx.Query("image"))
ctx.Data["src_dataset"] = ctx.Query("src_dataset") //uuid
ctx.Data["combat_dataset"] = ctx.Query("combat_dataset") //uuid
ctx.Data["evaluationIndex"] = ctx.Query("evaluation_index")
ctx.Data["run_para_list"] = ctx.Query("run_para_list")
ctx.Data["spec_id"] = ctx.QueryInt64("spec_id")
ctx.Data["train_url"] = ctx.Query("train_url")
ctx.Data["ckpt_name"] = ctx.Query("ckpt_name")

ctx.Data["train_url"] = ctx.Query("train_url")
ctx.Data["ckpt_name"] = ctx.Query("ckpt_name")
ctx.Data["model_name"] = ctx.Query("model_name")
ctx.Data["model_version"] = ctx.Query("model_version")

if ctx.QueryInt("type") == models.TypeCloudBrainOne {
ctx.Data["type"] = models.TypeCloudBrainOne
ctx.Data["compute_resource"] = models.GPUResource
ctx.Data["datasetType"] = models.TypeCloudBrainOne

ctx.Data["BaseDataSetName"] = setting.ModelSafetyTest.GPUBaseDataSetName
ctx.Data["BaseDataSetUUID"] = setting.ModelSafetyTest.GPUBaseDataSetUUID
ctx.Data["CombatDataSetName"] = setting.ModelSafetyTest.GPUCombatDataSetName
ctx.Data["CombatDataSetUUID"] = setting.ModelSafetyTest.GPUCombatDataSetUUID
prepareCloudbrainOneSpecs(ctx)

queuesDetail, _ := cloudbrain.GetQueuesDetail()
if queuesDetail != nil {
ctx.Data["QueuesDetail"] = queuesDetail
}

} else {
ctx.Data["engine_id"] = ctx.QueryInt("engine_id")
ctx.Data["pool_id"] = ctx.Query("pool_id")

ctx.Data["type"] = models.TypeCloudBrainTwo
ctx.Data["compute_resource"] = models.NPUResource
ctx.Data["datasetType"] = models.TypeCloudBrainTwo
ctx.Data["BaseDataSetName"] = setting.ModelSafetyTest.NPUBaseDataSetName
ctx.Data["BaseDataSetUUID"] = setting.ModelSafetyTest.NPUBaseDataSetUUID
ctx.Data["CombatDataSetName"] = setting.ModelSafetyTest.NPUCombatDataSetName
ctx.Data["CombatDataSetUUID"] = setting.ModelSafetyTest.NPUCombatDataSetUUID

var engines modelarts.Engine
if err := json.Unmarshal([]byte(setting.Engines), &engines); err != nil {
ctx.ServerError("json.Unmarshal failed:", err)
}
ctx.Data["engines"] = engines.Info

var versionInfos modelarts.VersionInfo
if err := json.Unmarshal([]byte(setting.EngineVersions), &versionInfos); err != nil {
ctx.ServerError("json.Unmarshal failed:", err)
}
ctx.Data["engine_versions"] = versionInfos.Version
prepareCloudbrainTwoInferenceSpecs(ctx)

waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "")
ctx.Data["WaitCount"] = waitCount
}

return nil
}

func getJsonContent(url string) (string, error) {

resp, err := http.Get(url)
if err != nil || resp.StatusCode != 200 {
log.Info("Get organizations url error=" + err.Error())
return "", err
}
bytes, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
log.Info("Get organizations url error=" + err.Error())
return "", err
}
str := string(bytes)
//log.Info("json str =" + str)

return str, nil
}

+ 55
- 124
routers/repo/cloudbrain.go View File

@@ -51,6 +51,9 @@ const (
tplCloudBrainBenchmarkNew base.TplName = "repo/cloudbrain/benchmark/new"
tplCloudBrainBenchmarkShow base.TplName = "repo/cloudbrain/benchmark/show"

tplCloudBrainModelSafetyNewGpu base.TplName = "repo/modelsafety/newgpu"
tplCloudBrainModelSafetyNewNpu base.TplName = "repo/modelsafety/newnpu"

tplCloudBrainImageSubmit base.TplName = "repo/cloudbrain/image/submit"
tplCloudBrainImageEdit base.TplName = "repo/cloudbrain/image/edit"

@@ -140,8 +143,11 @@ func cloudBrainNewDataPrepare(ctx *context.Context) error {
ctx.Data["is_brainscore_enabled"] = setting.IsBrainScoreEnabled

ctx.Data["datasetType"] = models.TypeCloudBrainOne

ctx.Data["benchmarkMode"] = ctx.Query("benchmarkMode")
defaultMode := ctx.Query("benchmarkMode")
if defaultMode == "" {
defaultMode = "alogrithm"
}
ctx.Data["benchmarkMode"] = defaultMode

if ctx.Cloudbrain != nil {
ctx.Data["branch_name"] = ctx.Cloudbrain.BranchName
@@ -734,7 +740,10 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo
} else {
task, err = models.GetCloudbrainByIDWithDeleted(ctx.Params(":id"))
}

if task.JobType == string(models.JobTypeModelSafety) {
GetAiSafetyTaskTmpl(ctx)
return
}
if err != nil {
log.Info("error:" + err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
@@ -760,8 +769,8 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo
ctx.Data["ExitDiagnostics"] = taskRes.TaskStatuses[0].ExitDiagnostics
oldStatus := task.Status
task.Status = taskRes.TaskStatuses[0].State
task.ContainerIp = ""
task.ContainerID = taskRes.TaskStatuses[0].ContainerID
task.ContainerIp = taskRes.TaskStatuses[0].ContainerIP
models.ParseAndSetDurationFromCloudBrainOne(jobRes, task)

if task.DeletedAt.IsZero() { //normal record
@@ -1147,6 +1156,8 @@ func CloudBrainCommitImage(ctx *context.Context, form auth.CommitImageCloudBrain

} else if models.IsErrorImageCommitting(err) {
ctx.JSON(200, models.BaseErrorMessage(ctx.Tr("repo.image_committing")))
} else if isOver20GError(err) {
ctx.JSON(200, models.BaseErrorMessage(ctx.Tr("repo.image_over_20g")))
} else {
ctx.JSON(200, models.BaseErrorMessage(ctx.Tr("repo.image_commit_fail")))
}
@@ -1156,6 +1167,10 @@ func CloudBrainCommitImage(ctx *context.Context, form auth.CommitImageCloudBrain
ctx.JSON(200, models.BaseOKMessage)
}

func isOver20GError(err error) bool {
return strings.Contains(err.Error(), "over max image size 20GB")
}

func checkTopics(Topics string) ([]string, string) {
var topics = make([]string, 0)
var topicsStr = strings.TrimSpace(Topics)
@@ -1821,6 +1836,9 @@ func SyncCloudbrainStatus() {
}

for _, task := range cloudBrains {
if task.JobType == string(models.JobTypeModelSafety) {
continue
}
if task.Type == models.TypeCloudBrainOne {
result, err := cloudbrain.GetJob(task.JobID)
if err != nil {
@@ -2106,14 +2124,14 @@ func CloudBrainBenchmarkIndex(ctx *context.Context) {
}

var jobTypes []string
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet))
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet), string(models.JobTypeModelSafety))
ciTasks, count, err := models.Cloudbrains(&models.CloudbrainsOptions{
ListOptions: models.ListOptions{
Page: page,
PageSize: setting.UI.IssuePagingNum,
},
RepoID: repo.ID,
Type: models.TypeCloudBrainOne,
Type: -1,
JobTypes: jobTypes,
})
if err != nil {
@@ -2160,6 +2178,10 @@ func CloudBrainBenchmarkIndex(ctx *context.Context) {
}
}
}
if task.JobType == string(models.JobTypeModelSafety) {
ciTasks[i].BenchmarkType = "安全评测"
ciTasks[i].BenchmarkTypeName = "Image Classification"
}
}

pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5)
@@ -2813,16 +2835,11 @@ func GetBenchmarkTypes(ctx *context.Context) *models.BenchmarkTypes {
}

func GetCloudbrainAiCenter(task models.Cloudbrain, ctx *context.Context) string {
if task.Type == models.TypeCloudBrainOne {
return ctx.Tr("repo.cloudbrain1")
} else if task.Type == models.TypeCloudBrainTwo {
return ctx.Tr("repo.cloudbrain2")
} else if task.Type == models.TypeCDCenter {
return ctx.Tr("repo.cdCenter")
} else if task.Type == models.TypeC2Net {
return getCutStringAiCenterByAiCenter(task.AiCenter)
if task.Spec != nil {
return task.Spec.AiCenterName
} else {
return ""
}
return ""
}
func getCutStringAiCenterByAiCenter(aiCenter string) string {
if aiCenter == "" {
@@ -2841,8 +2858,24 @@ func GetCloudbrainCluster(task models.Cloudbrain, ctx *context.Context) string {
return ""
}
func GetCloudbrainCardDuration(task models.Cloudbrain) string {
cardNum, _, _ := GetCloudbrainCardNumAndType(task)
cardDuration := models.ConvertDurationToStr(int64(cardNum) * task.Duration)
cardNum := int(0)
spec, err := resource.GetCloudbrainSpec(task.ID)
if err != nil {
log.Info("error:" + err.Error())
return ""
}
if spec != nil {
cardNum = spec.AccCardsNum
} else {
cardNum = 1
}
var workServerNumber int64
if task.WorkServerNumber >= 1 {
workServerNumber = int64(task.WorkServerNumber)
} else {
workServerNumber = 1
}
cardDuration := models.ConvertDurationToStr(workServerNumber * int64(cardNum) * task.Duration)
return cardDuration
}
func GetCloudbrainWaitTime(task models.Cloudbrain) string {
@@ -2869,114 +2902,12 @@ func GetCloudbrainWaitTime(task models.Cloudbrain) string {
}
return waitTime
}

func GetCloudbrainCardNumAndType(task models.Cloudbrain) (int, string, error) {
if !models.SpecsMapInitFlag {
models.InitCloudbrainOneResourceSpecMap()
}
if !models.GpuInfosMapInitFlag {
models.InitCloudbrainOneGpuInfoMap()
}
flavorName, err := GetCloudbrainFlavorName(task)
if err != nil {
return 0, "", nil
}
return getCardNumAndTypeByFlavorname(flavorName)
}

func getCardNumAndTypeByFlavorname(FlavorName string) (int, string, error) {
if FlavorName == "" {
return 0, "", nil
} else {
var beginIndex = strings.Index(FlavorName, ":")
var lastIndex = strings.LastIndex(FlavorName, ":")
var endIndex = strings.Index(FlavorName, "*")
if endIndex >= (beginIndex+1) && lastIndex >= (endIndex+1) {
cardNum, err := strconv.Atoi(strings.TrimSpace(FlavorName[beginIndex+1 : endIndex]))
if err != nil {
log.Error("strconv.Atoi failed: %v", err)
return 0, "", err
}
cardType := strings.TrimSpace(FlavorName[endIndex+1 : lastIndex])
return cardNum, cardType, err
}
return 0, "", nil
}
}

func GetCloudbrainFlavorName(task models.Cloudbrain) (string, error) {
if task.Type == models.TypeCloudBrainOne {
resourceSpec, gpuInfo, err := getCloudBrainOneResourceSpec(task)
if err != nil {
log.Info("getCloudBrainOneResourceSpec err:", err)
return "", err
} else {
if resourceSpec == nil || gpuInfo == nil {
err := errors.New("resourceSpec or gpuInfo is nil")
return "", err
} else {
CloudbrainOneFlavorName := "GPU:" + strconv.Itoa(resourceSpec.GpuNum) + "*Nvidia-" + gpuInfo.Value +
" | CPU:" + strconv.Itoa(resourceSpec.CpuNum) + "核" + strconv.Itoa(resourceSpec.MemMiB) + "MB"
return CloudbrainOneFlavorName, nil
}
}
} else if (task.Type == models.TypeCloudBrainTwo || task.Type == models.TypeC2Net || task.Type == models.TypeCDCenter) && task.FlavorName != "" {
replaceFlavorName := strings.ReplaceAll(task.FlavorName, ":", ":")
return replaceFlavorName, nil
} else if (task.Type == models.TypeCloudBrainTwo || task.Type == models.TypeCDCenter) && task.FlavorName == "" && task.FlavorCode != "" {
cloudbrainTwoFlavorName := getFlavorNameByFlavorCode(task.FlavorCode)
return cloudbrainTwoFlavorName, nil
} else if task.Type == models.TypeCloudBrainTwo && task.JobType == string(models.JobTypeDebug) && task.FlavorName == "" && task.FlavorCode == "" {
tasks, err := models.GetModelartsReDebugTaskByJobId(task.JobID)
if err != nil {
return "", err
}
if len(tasks) >= 1 {
return getFlavorNameByFlavorCode(tasks[0].FlavorCode), nil
}
return "", nil
}
return "", nil
}

func getCloudBrainOneResourceSpec(task models.Cloudbrain) (*models.ResourceSpec, *models.GpuInfo, error) {
gpuQueueDefault := "openidebug"
if task.GpuQueue != "" {
gpuQueueDefault = task.GpuQueue
}
if task.ResourceSpecId >= 0 {
if task.JobType == string(models.JobTypeTrain) {
if models.CloudbrainTrainResourceSpecsMap[task.ResourceSpecId] != nil {
return models.CloudbrainTrainResourceSpecsMap[task.ResourceSpecId], models.CloudbrainTrainGpuInfosMap[gpuQueueDefault], nil
} else {
return models.CloudbrainSpecialResourceSpecsMap[task.ResourceSpecId], models.CloudbrainSpecialGpuInfosMap[gpuQueueDefault], nil
}
} else if task.JobType == string(models.JobTypeDebug) {
if models.CloudbrainDebugResourceSpecsMap[task.ResourceSpecId] != nil {
return models.CloudbrainDebugResourceSpecsMap[task.ResourceSpecId], models.CloudbrainDebugGpuInfosMap[gpuQueueDefault], nil
} else {
return models.CloudbrainSpecialResourceSpecsMap[task.ResourceSpecId], models.CloudbrainSpecialGpuInfosMap[gpuQueueDefault], nil
}
} else if task.JobType == string(models.JobTypeInference) {
return models.CloudbrainInferenceResourceSpecsMap[task.ResourceSpecId], models.CloudbrainInferenceGpuInfosMap[gpuQueueDefault], nil
} else if task.JobType == string(models.JobTypeBenchmark) || task.JobType == string(models.JobTypeSnn4imagenet) || task.JobType == string(models.JobTypeBrainScore) {
return models.CloudbrainBenchmarkResourceSpecsMap[task.ResourceSpecId], models.CloudbrainBenchmarkGpuInfosMap[gpuQueueDefault], nil
}
func GetCloudbrainFlavorName(task models.Cloudbrain) string {
if task.Spec != nil {
flavorName := task.Spec.ComputeResource + ":" + fmt.Sprint(task.Spec.AccCardsNum) + "*" + task.Spec.AccCardType +
",内存:" + strconv.FormatInt(int64(task.Spec.MemGiB), 10) + "GB,共享内存:" + strconv.FormatInt(int64(task.Spec.ShareMemGiB), 10) + "GB"
return flavorName
} else {
err := errors.New("ResourceSpecId is null")
return nil, nil, err
}
return nil, nil, nil
}
func getFlavorNameByFlavorCode(flavorCode string) string {
index := strings.LastIndex(flavorCode, ".")
cardNum, err := strconv.Atoi(strings.TrimSpace(flavorCode[index+1 : len(flavorCode)]))
if err != nil {
log.Error("strconv.Atoi failed: %v", err)
return ""
}
cloudbrainTwoFlavorName := "Ascend:" + strings.TrimSpace(flavorCode[index+1:len(flavorCode)]) +
"*Ascend-910(" + strconv.Itoa(cardNum*32) + "GB)|ARM:" + strconv.Itoa(cardNum*24) +
"核" + strconv.Itoa(cardNum*256) + "GB"
return cloudbrainTwoFlavorName
}

+ 3
- 3
routers/repo/editor.go View File

@@ -303,7 +303,7 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
}

if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(models.UnitTypePullRequests) {
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + ctx.Repo.BranchName + "..." + form.NewBranchName)
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName))
} else {
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath))
}
@@ -475,7 +475,7 @@ func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {

ctx.Flash.Success(ctx.Tr("repo.editor.file_delete_success", ctx.Repo.TreePath))
if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(models.UnitTypePullRequests) {
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + ctx.Repo.BranchName + "..." + form.NewBranchName)
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName))
} else {
treePath := filepath.Dir(ctx.Repo.TreePath)
if treePath == "." {
@@ -686,7 +686,7 @@ func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) {
}

if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(models.UnitTypePullRequests) {
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + ctx.Repo.BranchName + "..." + form.NewBranchName)
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName))
} else {
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath))
}


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

@@ -713,6 +713,7 @@ func grampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain
DatasetNames: datasetNames,
DatasetInfos: datasetInfos,
Spec: spec,
CodeName: strings.ToLower(repo.Name),
}
if form.ModelName != "" { //使用预训练模型训练
req.ModelName = form.ModelName
@@ -837,6 +838,7 @@ func GrampusTrainJobShow(ctx *context.Context) {
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
return
}
task.ContainerIp = ""

if task.DeletedAt.IsZero() { //normal record
result, err := grampus.GetJob(task.JobID)
@@ -976,8 +978,7 @@ func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bo
command += "pwd;cd " + workDir + fmt.Sprintf(grampus.CommandPrepareScript, setting.Grampus.SyncScriptProject, setting.Grampus.SyncScriptProject)
//download code & dataset
if processorType == grampus.ProcessorTypeNPU {
commandDownload := "./downloader_for_obs " + setting.Bucket + " " + codeRemotePath + " " + grampus.CodeArchiveName + ";"
command += commandDownload
//no need to download code & dataset by internet
} else if processorType == grampus.ProcessorTypeGPU {
commandDownload := "./downloader_for_minio " + setting.Grampus.Env + " " + codeRemotePath + " " + grampus.CodeArchiveName + " '" + dataRemotePath + "' '" + datasetName + "'"
commandDownload = processPretrainModelParameter(pretrainModelPath, pretrainModelFileName, commandDownload)
@@ -986,8 +987,7 @@ func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bo

//unzip code & dataset
if processorType == grampus.ProcessorTypeNPU {
commandUnzip := "cd " + workDir + "code;unzip -q master.zip;"
command += commandUnzip
//no need to process
} else if processorType == grampus.ProcessorTypeGPU {
unZipDatasetCommand := generateDatasetUnzipCommand(datasetName)
commandUnzip := "cd " + workDir + "code;unzip -q master.zip;echo \"start to unzip dataset\";cd " + workDir + "dataset;" + unZipDatasetCommand
@@ -1024,7 +1024,7 @@ func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bo

var commandCode string
if processorType == grampus.ProcessorTypeNPU {
commandCode = "/bin/bash /home/work/run_train_for_openi.sh " + workDir + "code/" + strings.ToLower(repoName) + "/" + bootFile + " /tmp/log/train.log" + paramCode + ";"
commandCode = "/bin/bash /home/work/run_train_for_openi.sh /home/work/openi.py /tmp/log/train.log" + paramCode + ";"
} else if processorType == grampus.ProcessorTypeGPU {
if pretrainModelFileName != "" {
paramCode += " --ckpt_url" + "=" + workDir + "pretrainmodel/" + pretrainModelFileName


+ 6
- 5
routers/repo/modelarts.go View File

@@ -985,7 +985,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm)
//isSaveParam := form.IsSaveParam
repo := ctx.Repo.Repository
codeLocalPath := setting.JobPath + jobName + modelarts.CodePath
codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath
codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath + VersionOutputPath + "/"
outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath + VersionOutputPath + "/"
logObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.LogPath + VersionOutputPath + "/"
// dataPath := "/" + setting.Bucket + "/" + setting.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/" + uuid + uuid + "/"
@@ -1108,8 +1108,8 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm)
return
}

// parentDir := VersionOutputPath + "/"
if err := uploadCodeToObs(codeLocalPath, jobName, ""); err != nil {
parentDir := VersionOutputPath + "/"
if err := uploadCodeToObs(codeLocalPath, jobName, parentDir); err != nil {
// if err := uploadCodeToObs(codeLocalPath, jobName, parentDir); err != nil {
log.Error("Failed to uploadCodeToObs: %s (%v)", repo.FullName(), err)
trainJobNewDataPrepare(ctx)
@@ -1795,7 +1795,7 @@ func TrainJobShow(ctx *context.Context) {
datasetList = append(datasetList, GetCloudBrainDataSetInfo(task.Uuid, task.DatasetName, false))
VersionListTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain)
VersionListTasks[i].CanModify = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain)
VersionListTasks[i].ContainerIp = ""
//add spec
s, err := resource.GetCloudbrainSpec(task.Cloudbrain.ID)
if err != nil {
@@ -2200,6 +2200,7 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference
ResultUrl: resultObsPath,
Spec: spec,
DatasetName: datasetNames,
JobType: string(models.JobTypeInference),
}

err = modelarts.GenerateInferenceJob(ctx, req)
@@ -2737,7 +2738,7 @@ func TrainJobDownloadLogFile(ctx *context.Context) {
return
}
ctx.Resp.Header().Set("Cache-Control", "max-age=0")
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently)
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusTemporaryRedirect)
}
func getDatasUrlListByUUIDS(uuidStr string) ([]models.Datasurl, string, string, bool, error) {
var isMultiDataset bool


+ 2
- 1
routers/repo/repo.go View File

@@ -12,6 +12,7 @@ import (
"path"
"regexp"
"strings"
"text/template"
"unicode/utf8"

"code.gitea.io/gitea/modules/validation"
@@ -212,7 +213,7 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) {
opts := models.GenerateRepoOptions{
Name: form.RepoName,
Alias: form.Alias,
Description: form.Description,
Description: template.HTMLEscapeString(form.Description),
Private: form.Private,
GitContent: form.GitContent,
Topics: form.Topics,


+ 2
- 1
routers/repo/setting.go View File

@@ -8,6 +8,7 @@ package repo
import (
"errors"
"fmt"
"html/template"
"io/ioutil"
"net/url"
"regexp"
@@ -129,7 +130,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
// In case it's just a case change.
repo.Name = newRepoName
repo.LowerName = strings.ToLower(newRepoName)
repo.Description = form.Description
repo.Description = template.HTMLEscapeString(form.Description)
repo.Website = form.Website
repo.IsTemplate = form.Template
repo.Alias = newAlias


+ 3
- 2
routers/repo/setting_protected_branch.go View File

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

import (
"code.gitea.io/gitea/modules/util"
"fmt"
"strings"
"time"
@@ -192,7 +193,7 @@ func SettingsProtectedBranchPost(ctx *context.Context, f auth.ProtectBranchForm)
}
if f.RequiredApprovals < 0 {
ctx.Flash.Error(ctx.Tr("repo.settings.protected_branch_required_approvals_min"))
ctx.Redirect(fmt.Sprintf("%s/settings/branches/%s", ctx.Repo.RepoLink, branch))
ctx.Redirect(fmt.Sprintf("%s/settings/branches/%s", ctx.Repo.RepoLink, util.PathEscapeSegments(branch)))
}

var whitelistUsers, whitelistTeams, mergeWhitelistUsers, mergeWhitelistTeams, approvalsWhitelistUsers, approvalsWhitelistTeams []int64
@@ -263,7 +264,7 @@ func SettingsProtectedBranchPost(ctx *context.Context, f auth.ProtectBranchForm)
return
}
ctx.Flash.Success(ctx.Tr("repo.settings.update_protect_branch_success", branch))
ctx.Redirect(fmt.Sprintf("%s/settings/branches/%s", ctx.Repo.RepoLink, branch))
ctx.Redirect(fmt.Sprintf("%s/settings/branches/%s", ctx.Repo.RepoLink, util.PathEscapeSegments(branch)))
} else {
if protectBranch != nil {
if err := ctx.Repo.Repository.DeleteProtectedBranch(protectBranch.ID); err != nil {


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

@@ -6,15 +6,17 @@ package routes

import (
"bytes"
"code.gitea.io/gitea/routers/reward/point"
"code.gitea.io/gitea/routers/task"
"code.gitea.io/gitea/services/reward"
"encoding/gob"
"net/http"
"path"
"text/template"
"time"

"code.gitea.io/gitea/routers/modelapp"
"code.gitea.io/gitea/routers/reward/point"
"code.gitea.io/gitea/routers/task"
"code.gitea.io/gitea/services/reward"

"code.gitea.io/gitea/modules/slideimage"

"code.gitea.io/gitea/routers/image"
@@ -346,6 +348,8 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/user/login/kanban", user.SignInPostAPI)
m.Get("/home/term", routers.HomeTerm)
m.Get("/home/privacy", routers.HomePrivacy)
m.Get("/extension/tuomin/upload", modelapp.ProcessImageUI)
m.Post("/extension/tuomin/upload", reqSignIn, modelapp.ProcessImage)
m.Group("/explore", func() {
m.Get("", func(ctx *context.Context) {
ctx.Redirect(setting.AppSubURL + "/explore/repos")
@@ -1198,7 +1202,7 @@ func RegisterRoutes(m *macaron.Macaron) {
}, context.RepoRef())
m.Group("/modelmanage", func() {
m.Post("/create_model", repo.SaveModel)
m.Post("/create_model_convert", reqRepoModelManageWriter, repo.SaveModelConvert)
m.Post("/create_model_convert", reqWechatBind, reqRepoModelManageWriter, repo.SaveModelConvert)
m.Post("/create_new_model", repo.SaveNewNameModel)
m.Delete("/delete_model", repo.DeleteModel)
m.Post("/delete_model_convert/:id", repo.DeleteModelConvert)
@@ -1225,6 +1229,18 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/downloadall", repo.DownloadMultiModelFile)
}, context.RepoRef())

m.Group("/modelsafety", func() {
m.Group("/:id", func() {
m.Get("/show", reqRepoCloudBrainWriter, repo.GetAiSafetyTaskTmpl)
m.Get("", reqRepoCloudBrainWriter, repo.GetAiSafetyTask)
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.StopAiSafetyTask)
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.DelAiSafetyTask)
})
m.Get("/create_gpu", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.AiSafetyCreateForGetGPU)
m.Get("/create_npu", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.AiSafetyCreateForGetNPU)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, repo.AiSafetyCreateForPost)
}, context.RepoRef())

m.Group("/debugjob", func() {
m.Get("", reqRepoCloudBrainReader, repo.DebugJobIndex)
}, context.RepoRef())


+ 1
- 5
routers/user/home.go View File

@@ -23,7 +23,6 @@ import (
"code.gitea.io/gitea/modules/modelarts"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/repo"
issue_service "code.gitea.io/gitea/services/issue"
pull_service "code.gitea.io/gitea/services/pull"

@@ -778,7 +777,7 @@ func Cloudbrains(ctx *context.Context) {
var jobTypes []string
jobTypeNot := false
if jobType == string(models.JobTypeBenchmark) {
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet))
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeModelSafety), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet))
} else if jobType != "all" && jobType != "" {
jobTypes = append(jobTypes, jobType)
}
@@ -841,9 +840,6 @@ func Cloudbrains(ctx *context.Context) {
ciTasks[i].CanDebug = true
ciTasks[i].CanDel = true
ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource
ciTasks[i].Cloudbrain.AiCenter = repo.GetCloudbrainAiCenter(task.Cloudbrain, ctx)
ciTasks[i].Cloudbrain.Cluster = repo.GetCloudbrainCluster(task.Cloudbrain, ctx)

}

pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, getTotalPage(count, setting.UI.IssuePagingNum))


+ 58
- 23
templates/admin/cloudbrain/list.tmpl View File

@@ -89,7 +89,7 @@
<div class="row">
<!-- 任务名 -->
{{$JobID := '0'}}
{{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK"}}
{{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK" "MODELSAFETY"}}
{{$JobID = .Cloudbrain.ID}}
{{else}}
{{$JobID = .JobID}}
@@ -124,7 +124,7 @@
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if eq .JobType "BENCHMARK"}}
{{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">
@@ -135,14 +135,13 @@
</div>
<!-- 集群 -->
<div class="one wide column text center nowrap" style="width:6% !important;">
<span
style="font-size: 12px;">{{if .Cluster}}{{.Cluster}}{{else}}--{{end}}</span>
<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: 6% !important;">
<span class="job-status" id="{{$JobID}}"
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG"}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{else if eq .JobType "INFERENCE"}}/modelarts/inference-job{{else if eq .JobType "TRAIN"}}/modelarts/train-job{{else if eq .JobType "BENCHMARK"}}/cloudbrain{{end}}'
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG"}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{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}}">
<span><i id="{{$JobID}}-icon" style="vertical-align: middle;"
class="{{.Status}}"></i><span id="{{$JobID}}-text"
@@ -171,8 +170,7 @@
</div>
<!-- 智算中心 -->
<div class="one wide column text center nowrap" style="width:8% !important;">
<span
style="font-size: 12px;">{{if .AiCenter}}{{.AiCenter}}{{else}}--{{end}}</span>
<span style="font-size: 12px;" class="aicenter_{{.DisplayJobName}}_{{$JobID}}">{{if .AiCenter}}{{.AiCenter}}{{else}}--{{end}}</span>
</div>
<!-- XPU类型 -->
<div class="one wide column text center nowrap" style="width:8% !important;">
@@ -185,6 +183,17 @@
var spanEl = document.querySelector('.card_type_{{.DisplayJobName}}_{{$JobID}}');
spanEl.setAttribute('title', cardType);
spanEl.innerText = cardType;
var cluster = spec.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>
<!-- 创建者 -->
@@ -205,11 +214,12 @@
<!-- 云脑侧名称 -->
<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"
<span class="ui poping up clipboard" data-position="top center" id="clipboard-btn-{{.JobName}}" 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-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>
@@ -238,8 +248,19 @@
</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 "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "SUCCEEDED" "STOPPED" "STOPPING"}}disabled {{else}} blue {{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" "BENCHMARK" "SNN4IMAGENET" "BRAINSCORE"}}
<form id="stopForm-{{$JobID}}" style="margin-left:-1px;">
{{$.CsrfTokenHtml}}
@@ -258,6 +279,7 @@
{{$.i18n.Tr "repo.stop"}}
</a>
{{end}}
{{end}}
</div>
<!-- 修改任务 -->
{{if eq .JobType "TRAIN"}}
@@ -268,17 +290,30 @@
</div>
{{end}}
<!-- 删除任务 -->
<form class="ui compact buttons" id="delForm-{{$JobID}}"
action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE")}}/cloudbrain{{else if eq .JobType "DEBUG"}}{{if eq .ComputeResource "NPU"}}/modelarts/notebook{{else}}/cloudbrain{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .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{{end}}{{end}}/{{$JobID}}/del?isadminpage=true'
method="post">
{{$.CsrfTokenHtml}}
<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="" class="ui basic ai_delete blue button"
style="border-radius: .28571429rem;">
{{$.i18n.Tr "repo.delete"}}
</a>
</form>
{{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}}
<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")}}/cloudbrain{{else if eq .JobType "DEBUG"}}{{if eq .ComputeResource "NPU"}}/modelarts/notebook{{else}}/cloudbrain{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .Cloudbrain.Type 1}}/modelarts/train-job{{else if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}/grampus/train-job{{end}}{{else if eq .JobType "INFERENCE"}}{{if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{end}}{{end}}/{{$JobID}}/del?isadminpage=true'
method="post">
{{$.CsrfTokenHtml}}
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}"
data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{$JobID}}/del_version?isadminpage=true"
data-version="" class="ui basic ai_delete blue button"
style="border-radius: .28571429rem;">
{{$.i18n.Tr "repo.delete"}}
</a>
</form>
{{end}}
</div>
</div>
</div>


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

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


+ 15
- 1
templates/base/head_navbar.tmpl View File

@@ -32,9 +32,15 @@
</div>
</div>
</div>

<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a>
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a>
<div class="ui simple dropdown item" >
{{.i18n.Tr "repo.model_manager"}}
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="{{AppSubUrl}}/extension/tuomin/upload">模型体验</a>
</div>
</div>
<div class="ui simple dropdown item" id='dropdown_explore'>
{{.i18n.Tr "explore"}}
<i class="dropdown icon"></i>
@@ -68,6 +74,14 @@

<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a>
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a>
<div class="ui simple dropdown item" >
{{.i18n.Tr "repo.model_manager"}}
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="{{AppSubUrl}}/extension/tuomin/upload">模型体验</a>
</div>
</div>
<div class="ui simple dropdown item" id='dropdown_PageHome'>
{{.i18n.Tr "explore"}}
<i class="dropdown icon"></i>


+ 14
- 0
templates/base/head_navbar_fluid.tmpl View File

@@ -34,6 +34,13 @@
</div>
<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a>
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a>
<div class="ui simple dropdown item" >
{{.i18n.Tr "repo.model_manager"}}
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="{{AppSubUrl}}/extension/tuomin/upload">模型体验</a>
</div>
</div>
<div class="ui dropdown item" id='dropdown_explore'>
{{.i18n.Tr "explore"}}
<i class="dropdown icon"></i>
@@ -66,6 +73,13 @@
</div>
<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a>
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a>
<div class="ui simple dropdown item" >
{{.i18n.Tr "repo.model_manager"}}
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="{{AppSubUrl}}/extension/tuomin/upload">模型体验</a>
</div>
</div>
<div class="ui dropdown item" id='dropdown_PageHome'>
{{.i18n.Tr "explore"}}
<i class="dropdown icon"></i>


+ 14
- 0
templates/base/head_navbar_home.tmpl View File

@@ -26,6 +26,13 @@
</div>
<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a>
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a>
<div class="ui simple dropdown item" >
{{.i18n.Tr "repo.model_manager"}}
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="{{AppSubUrl}}/extension/tuomin/upload">模型体验</a>
</div>
</div>
<div class="ui dropdown item" id='dropdown_explore'>
{{.i18n.Tr "explore"}}
<i class="dropdown icon"></i>
@@ -59,6 +66,13 @@

<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a>
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a>
<div class="ui simple dropdown item" >
{{.i18n.Tr "repo.model_manager"}}
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="{{AppSubUrl}}/extension/tuomin/upload">模型体验</a>
</div>
</div>
<div class="ui dropdown item" id='dropdown_PageHome'>
{{.i18n.Tr "explore"}}
<i class="dropdown icon"></i>


+ 14
- 0
templates/base/head_navbar_pro.tmpl View File

@@ -36,6 +36,13 @@

<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a>
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a>
<div class="ui simple dropdown item" >
{{.i18n.Tr "repo.model_manager"}}
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="{{AppSubUrl}}/extension/tuomin/upload">模型体验</a>
</div>
</div>
<div class="ui dropdown item" id='dropdown_explore'>
{{.i18n.Tr "explore"}}
<i class="dropdown icon"></i>
@@ -69,6 +76,13 @@

<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a>
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a>
<div class="ui simple dropdown item" >
{{.i18n.Tr "repo.model_manager"}}
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="{{AppSubUrl}}/extension/tuomin/upload">模型体验</a>
</div>
</div>
<div class="ui dropdown item" id='dropdown_PageHome'>
{{.i18n.Tr "explore"}}
<i class="dropdown icon"></i>


+ 13
- 0
templates/model/tuomin/upload.tmpl View File

@@ -0,0 +1,13 @@
{{template "base/head" .}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/vp-model-tuomin.css?v={{MD5 AppVer}}" />
<div>
{{if .Flash}}
<div class="sixteen wide column">
{{template "base/alert" .}}
</div>
{{end}}
<div id="isSignd" data-sign="{{$.IsSigned}}" style="display: none;"></div>
<div id="__vue-root"></div>
</div>
<script src="{{StaticUrlPrefix}}/js/vp-model-tuomin.js?v={{MD5 AppVer}}"></script>
{{template "base/footer" .}}

+ 0
- 80
templates/org/member/members.tmpl View File

@@ -1,80 +0,0 @@
{{template "base/head" .}}
<div class="organization members">
{{template "org/header" .}}
<div class="ui container">
{{template "base/alert" .}}
{{template "org/navber" .}}
<div class="ui stackable grid">
<div class="ui sixteen wide computer column list">
{{ range .Members}}
<div class="item ui grid">
<div class="three wide mobile two wide tablet one wide computer column">
<img class="ui avatar" src="{{.SizedRelAvatarLink 48}}">
</div>
<div class="seven wide mobile three wide tablet three wide computer column">
<div class="meta"><a href="{{.HomeLink}}">{{.Name}}</a></div>
<div class="meta">{{.FullName}}</div>
</div>
<div class="ui three wide tablet four wide computer column center tablet only computer only">
<div class="meta">
{{$.i18n.Tr "org.members.membership_visibility"}}
</div>
<div class="meta">
{{ $isPublic := index $.MembersIsPublicMember .ID}}
{{if $isPublic}}
<strong>{{$.i18n.Tr "org.members.public"}}</strong>
{{if or (eq $.SignedUser.ID .ID) $.IsOrganizationOwner}}(<a class="link-action" href data-url="{{$.OrgLink}}/members/action/private?uid={{.ID}}">{{$.i18n.Tr "org.members.public_helper"}}</a>){{end}}
{{else}}
<strong>{{$.i18n.Tr "org.members.private"}}</strong>
{{if or (eq $.SignedUser.ID .ID) $.IsOrganizationOwner}}(<a class="link-action" href data-url="{{$.OrgLink}}/members/action/public?uid={{.ID}}">{{$.i18n.Tr "org.members.private_helper"}}</a>){{end}}
{{end}}
</div>
</div>
<div class="five wide mobile three wide tablet three wide computer column">
<div class="meta">
{{$.i18n.Tr "org.members.member_role"}}
</div>
<div class="meta">
<strong>{{if index $.MembersIsUserOrgOwner .ID}}{{svg "octicon-shield-lock" 16}} {{$.i18n.Tr "org.members.owner"}}{{else}}{{$.i18n.Tr "org.members.member"}}{{end}}</strong>
</div>
</div>
<div class="ui one wide column center tablet only computer only">
<div class="meta">
2FA
</div>
<div class="meta">
<strong>
{{if index $.MembersTwoFaStatus .ID}}
<span class="text green">{{svg "octicon-check" 16}}</span>
{{else}}
{{svg "octicon-x" 16}}
{{end}}
</strong>
</div>
</div>
<div class="ui three wide column tablet only computer only">
<div class="text right">
{{if eq $.SignedUser.ID .ID}}
<form method="post" action="{{$.OrgLink}}/members/action/leave">
{{$.CsrfTokenHtml}}
<button type="submit" class="ui red small button" name="uid" value="{{.ID}}">{{$.i18n.Tr "org.members.leave"}}</button>
</form>
{{else if $.IsOrganizationOwner}}
<form method="post" action="{{$.OrgLink}}/members/action/remove">
{{$.CsrfTokenHtml}}
<button type="submit" class="ui red small button" name="uid" value="{{.ID}}">{{$.i18n.Tr "org.members.remove"}}</button>
</form>
{{end}}
</div>
</div>
</div>
{{end}}
</div>
{{template "base/paginate" .}}
</div>
</div>
</div>
{{template "base/footer" .}}

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

@@ -99,7 +99,6 @@
{{range .Tasks}}
<div class="ui grid stackable item">
<div class="row">

<!-- 任务名 -->
<div class="three wide column padding0" style="width: 18% !important;">
<a class="title" href="{{$.Link}}/{{.Cloudbrain.ID}}" title="{{.DisplayJobName}}" style="font-size: 14px;">
@@ -108,18 +107,24 @@
</div>
<!-- 任务状态 -->
<div class="two wide column text center padding0" style="width: 10.5% !important;">
<span class="job-status" id="{{.Cloudbrain.ID}}" data-repopath="{{$.RepoRelPath}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}" data-jobid="{{.Cloudbrain.ID}}" data-version="{{.VersionName}}">
<span class="job-status" id="{{.Cloudbrain.ID}}" data-repopath="{{$.RepoRelPath}}{{if or (eq .JobType "MODELSAFETY") (eq .ComputeResource "CPU/GPU")}}/cloudbrain{{else}}/modelarts/notebook{{end}}" data-jobid="{{.Cloudbrain.ID}}" data-version="{{.VersionName}}">
<span><i id="{{.Cloudbrain.ID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="{{.Cloudbrain.ID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
</span>
</div>
<div class="two wide column text center padding0" style="width: 10.5% !important;">
{{.BenchmarkType}}
{{.BenchmarkType}}
</div>
{{if eq .JobType "MODELSAFETY"}}
<div class="two wide column text center padding0" style="width: 10.5% !important;">
{{.BenchmarkTypeName}}
</div>
{{else}}
<div class="two wide column text center padding0" style="width: 10.5% !important;">
<a style="font-size: 12px;" href="{{.BenchmarkTypeRankLink}}" target="_blank">
{{.BenchmarkTypeName}}
{{.BenchmarkTypeName}}
</a>
</div>
{{end}}
<!-- 任务创建时间 -->
<div class="two wide column text center padding0" style="width: 8.5% !important;">
<span style="font-size: 12px;" class="">{{TimeSinceUnix .Cloudbrain.CreatedUnix $.Lang}}</span>
@@ -142,9 +147,36 @@
</div>

<div class="three wide column text center padding0" style="width: 20% !important;">
<div class="ui compact buttons" >
<!-- 停止任务 -->
<form id="stopForm-{{.Cloudbrain.ID}}" style="margin-left:-1px;">
<div class="ui compact buttons" >
{{if eq .JobType "MODELSAFETY"}}
<!-- 停止任务 -->
<form id="stopForm-{{.Cloudbrain.ID}}" style="margin-left:-1px;">
{{$.CsrfTokenHtml}}
{{if .CanDel}}
<a id="ai-stop-{{.Cloudbrain.ID}}" class='ui basic ai_stop {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "STOPPING" "CREATING" "STARTING" "SUCCEEDED"}}disabled {{else}}blue {{end}}button' data-repopath="{{$.RepoLink}}/modelsafety/{{.Cloudbrain.ID}}/stop" data-jobid="{{.Cloudbrain.ID}}">
{{$.i18n.Tr "repo.stop"}}
</a>
{{else}}
<a class="ui basic disabled button">{{$.i18n.Tr "repo.stop"}}</a>
{{end}}
</form>
<!-- 删除任务 -->
<form id="delForm-{{.Cloudbrain.ID}}" action="{{$.RepoLink}}/modelsafety/{{.Cloudbrain.ID}}/del" method="post">
<input type="hidden" name="debugListType" value="all">
{{$.CsrfTokenHtml}}
{{if .CanDel}}
<a id="ai-delete-{{.Cloudbrain.ID}}" class='ui basic ai_delete {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "SUCCEEDED"}}blue {{else}}disabled {{end}}button' style="border-radius: .28571429rem;">
{{$.i18n.Tr "repo.delete"}}
</a>
{{else}}
<a class="ui basic button disabled" style="border-radius: .28571429rem;">
{{$.i18n.Tr "repo.delete"}}
</a>
{{end}}
</form>
{{else}}
<!-- 停止任务 -->
<form id="stopForm-{{.Cloudbrain.ID}}" style="margin-left:-1px;">
{{$.CsrfTokenHtml}}
{{if .CanDel}}
<a id="ai-stop-{{.Cloudbrain.ID}}" class='ui basic ai_stop {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "STOPPING" "CREATING" "STARTING" "SUCCEEDED"}}disabled {{else}}blue {{end}}button' data-repopath="{{$.RepoLink}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/stop" data-jobid="{{.Cloudbrain.ID}}">
@@ -162,8 +194,8 @@
{{$.i18n.Tr "repo.score"}}
</a>
{{end}}
<!-- 删除任务 -->
<form id="delForm-{{.Cloudbrain.ID}}" action="{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain/benchmark{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/del" method="post">
<!-- 删除任务 -->
<form id="delForm-{{.Cloudbrain.ID}}" action="{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain/benchmark{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/del" method="post">
<input type="hidden" name="debugListType" value="all">
{{$.CsrfTokenHtml}}
{{if .CanDel}}
@@ -175,7 +207,8 @@
{{$.i18n.Tr "repo.delete"}}
</a>
{{end}}
</form>
</form>
{{end}}
</div>
</div>
</div>


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

@@ -50,6 +50,8 @@
href="{{.Link}}?benchmarkMode=alogrithm">{{.i18n.Tr "repo.cloudbrain.benchmark.algorithm"}}</a>
<a class="active item model_benchmark"
href="{{.Link}}?benchmarkMode=model">{{.i18n.Tr "repo.cloudbrain.benchmark.model"}}</a>
<a class="item aisafety_benchmark"
href="{{.RepoLink}}/modelsafety/create_gpu">模型安全评测</a>
</div>
</div>
<div>
@@ -153,7 +155,7 @@
</div>
</div>
</form>
{{else}}
{{else if eq .benchmarkMode "alogrithm"}}
<form id="form_id" class="ui form alogrithm_form" action="{{.Link}}?benchmarkMode=alogrithm" method="post">
{{.CsrfTokenHtml}}
<input type="hidden" name="action" value="update">
@@ -165,6 +167,8 @@
href="{{.Link}}?benchmarkMode=alogrithm">{{.i18n.Tr "repo.cloudbrain.benchmark.algorithm"}}</a>
<a class="item model_benchmark"
href="{{.Link}}?benchmarkMode=model">{{.i18n.Tr "repo.cloudbrain.benchmark.model"}}</a>
<a class="item aisafety_benchmark"
href="{{.RepoLink}}/modelsafety/create_gpu">模型安全评测</a>
</div>
</div>

@@ -281,6 +285,76 @@
</div>
</div>
</form>
{{else if eq .benchmarkMode "aisafety"}}
<form id="form_id" class="ui form alogrithm_form" action="{{.Link}}?benchmarkMode=alogrithm" method="post">
{{.CsrfTokenHtml}}
<input type="hidden" name="action" value="update">
<input type="hidden" name="job_type" value="BENCHMARK">
<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_scenes"}}</label>
<div class="ui blue small menu compact selectcloudbrain">
<a class="item alogrithm_benchmark"
href="{{.Link}}?benchmarkMode=alogrithm">{{.i18n.Tr "repo.cloudbrain.benchmark.algorithm"}}</a>
<a class="item model_benchmark"
href="{{.Link}}?benchmarkMode=model">{{.i18n.Tr "repo.cloudbrain.benchmark.model"}}</a>
<a class="active item aisafety_benchmark"
href="{{.RepoLink}}/modelsafety/create_gpu">模型安全评测</a>
</div>
</div>

<div>
<div class="min_title inline field" style="margin-top:-10px;">
<label class="label-fix-width" style="font-weight: normal;"></label>
{{template "custom/task_wait_count" .}}
</div>
<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label>
<input style="width: 80%;" name="display_job_name" id="trainjob_job_name"
placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}"
tabindex="3" autofocus required maxlength="36">
<span class="tooltips" style="display: block;margin-left: 11.5rem;">{{.i18n.Tr "repo.cloudbrain_jobname_err"}}</span>
</div>
<div class="min_title inline field">
<label class="label-fix-width" style="font-weight: normal;"
for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}}</label>
<textarea style="width: 80%;" id="description" name="description" rows="3" maxlength="254"
placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}}
onchange="this.value=this.value.substring(0, 255)"
onkeydown="this.value=this.value.substring(0, 255)"
onkeyup="this.value=this.value.substring(0, 255)">{{.description}}</textarea>
</div>


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

<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="__specs__" class="ui search dropdown width48"
placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px' ovalue="{{.spec_id}}"
name="spec_id">
</select>
</div>

<div class="inline min_title field required">
<label class="label-fix-width" style="font-weight: normal;">推理程序</label>
<input disabled="disabled" style="width: 33.5%;" name="test_file" id="test_file" value="test.py"
tabindex="3" autofocus required maxlength="254">
<a id="test_href_id" href="https://git.openi.org.cn/CV_benchmark/CV_reID_benchmark"
target="_blank">{{.i18n.Tr "cloudbrain.view_sample"}}</a>
</div>


<div class="inline unite min_title field">
<label class="label-fix-width" style="font-weight: normal;"></label>
<button class="ui create_train_job green button">
{{.i18n.Tr "repo.cloudbrain.new"}}
</button>
<a class="ui button" href="/">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a>
</div>
</div>
</form>

{{end}}
</div>
</div>


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

@@ -253,7 +253,7 @@
<div style="float: right;">
{{if and ($.canDownload) (ne .Status "WAITING") ($.Permission.CanWrite $.UnitTypeModelManage) }}
<a class="ti-action-menu-item" id="{{.VersionName}}-create-model"
onclick="showcreate({{.}})">{{$.i18n.Tr "repo.modelarts.create_model"}}</a>
onclick="showcreate({DisplayJobName:{{.DisplayJobName}},JobName:{{.JobName}},JobID:{{.JobID}},VersionName:{{.VersionName}}})">{{$.i18n.Tr "repo.modelarts.create_model"}}</a>
{{else}}
<a class="ti-action-menu-item disabled" id="{{.VersionName}}-create-model">{{$.i18n.Tr "repo.modelarts.create_model"}}</a>
{{end}}


+ 1
- 1
templates/repo/grampus/trainjob/show.tmpl View File

@@ -265,7 +265,7 @@
<div style="float: right;">
{{if and ($.canDownload) (ne .Status "WAITING") ($.Permission.CanWrite $.UnitTypeModelManage) }}
<a class="ti-action-menu-item" id="{{.VersionName}}-create-model"
onclick="showcreate({{.}})">{{$.i18n.Tr "repo.modelarts.create_model"}}</a>
onclick="showcreate({DisplayJobName:{{.DisplayJobName}},JobName:{{.JobName}},JobID:{{.JobID}},VersionName:{{.VersionName}},EngineName:{{.EngineName}},ComputeResource:{{.ComputeResource}},Type:{{.Type}}})">{{$.i18n.Tr "repo.modelarts.create_model"}}</a>
{{else}}
<a class="ti-action-menu-item disabled" id="{{.VersionName}}-create-model">{{$.i18n.Tr "repo.modelarts.create_model"}}</a>
{{end}}


+ 14
- 3
templates/repo/modelarts/notebook/show.tmpl View File

@@ -207,6 +207,18 @@
padding-left: 1rem;
padding-top: 0.5rem;
}
.dataset_nowrap_two_line{
word-wrap: break-word;
word-break: break-all;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
line-clamp: 2;
-webkit-line-clamp: 2;
text-overflow: -o-ellipsis-lastline;
max-height: 50px;
}
</style>
<div class="repository">
{{template "repo/header" .}}
@@ -437,15 +449,14 @@
<tbody>
{{range $.datasetDownload}}
<tr>
<td style="word-wrap: break-word;word-break: break-all;">
<td class="dataset_nowrap_two_line">
{{if eq .IsDelete true}}
{{.DatasetName}}({{$.i18n.Tr "dataset.file_deleted"}})
{{else}}
<a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a>
{{end}}
</td>
<td style="word-wrap: break-word;word-break: break-all;">{{.DatasetDownloadLink}}</td>
<td><div class="dataset_nowrap_two_line">{{.DatasetDownloadLink}}</div></td>
<td class="center aligned"><a class="ui poping up clipboard" id="clipboard-btn-dataset" data-original="{{$.i18n.Tr "repo.copy_link"}}" data-success="{{$.i18n.Tr "repo.copy_link_success"}}" data-error="{{$.i18n.Tr "repo.copy_link_error"}}" data-content="{{$.i18n.Tr "repo.copy_link"}}" data-variation="inverted tiny" data-clipboard-text="{{.DatasetDownloadLink}}">{{$.i18n.Tr "dataset.download_copy"}}</a></td>
</tr>
{{end}}


+ 16
- 20
templates/repo/modelarts/trainjob/new.tmpl View File

@@ -261,29 +261,25 @@
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</label>

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

<input style="border-radius: 0;text-align: center;" type="hidden" name="work_server_number"
id="trainjob_work_server_num" tabindex="3" autofocus required maxlength="255" value="1"
readonly>
<div class="field" id="trainjob_work_server_num_select" name="work_server_number_select">
<select class="ui dropdown width" style='width: 100%;' name="work_server_id">
{{if .WorkNode}}
{{range .WorkNode}}
<select class="ui dropdown width" style='width: 100%;' name="work_server_number">
{{if .WorkNode}}
{{range .WorkNode}}

{{if $.work_server_number}}
{{if eq . $.work_server_number }}
<option name="server_id" selected value="{{.}}">{{.}}</option>
{{else}}
<option name="server_id" value="{{.}}">{{.}}</option>
{{end}}
{{else}}
<option name="server_id" value="{{.}}">{{.}}</option>
{{end}}
{{end}}
{{if $.work_server_number}}
{{if eq . $.work_server_number }}
<option name="server_id" selected value="{{.}}">{{.}}</option>
{{else}}
<option name="server_id" value="{{.}}">{{.}}</option>
{{end}}
{{else}}
<option name="server_id" value="{{.}}">{{.}}</option>
{{end}}
{{end}}

{{else}}
<option name="server_id" value="1">1</option>
{{end}}
{{else}}
<option name="server_id" value="1">1</option>
{{end}}
</select>
</div>



+ 3
- 4
templates/repo/modelarts/trainjob/show.tmpl View File

@@ -249,7 +249,7 @@
{{$.CsrfTokenHtml}}
{{if and (.CanModify) (ne .Status "WAITING") ($.Permission.CanWrite $.UnitTypeModelManage) }}
<a class="ti-action-menu-item" id="{{.VersionName}}-create-model"
onclick="showcreate({{.}})">{{$.i18n.Tr "repo.modelarts.create_model"}}</a>
onclick="showcreate({DisplayJobName:{{.DisplayJobName}},JobName:{{.JobName}},JobID:{{.JobID}},VersionName:{{.VersionName}},EngineID:{{.EngineID}}})">{{$.i18n.Tr "repo.modelarts.create_model"}}</a>
{{else}}
<a class="ti-action-menu-item disabled" id="{{.VersionName}}-create-model">{{$.i18n.Tr "repo.modelarts.create_model"}}</a>
{{end}}
@@ -783,7 +783,6 @@
}
let dirKey="isOnlyDir--:&";
function loadSelectedModelFile(trainJob){
console.log("trainJob=" + trainJob);
$('#choice_file').dropdown('clear')
$("#model-file").empty()
if(trainJob ==null || trainJob ==""){
@@ -893,11 +892,11 @@
$('#JobName').val(obj.DisplayJobName).addClass('model_disabled')
$('input[name="JobId"]').val(obj.JobID)
$('input[name="VersionName"]').val(obj.VersionName).addClass('model_disabled')
if(obj.EngineID ==122 || obj.EngineID ==35 || obj.EngineID ==-1){
if(obj.EngineID ==122 || obj.EngineID ==35 || obj.EngineID ==-1 || obj.EngineID ==37){
$('input[name="Engine_name"]').val("MindSpore").addClass('model_disabled');
$('input[name="Engine"]').val(2);
}
if(obj.EngineID ==121){
if(obj.EngineID ==121 || obj.EngineID ==38){
$('input[name="Engine_name"]').val("TensorFlow").addClass('model_disabled');
$('input[name="Engine"]').val(1);
}


+ 2
- 2
templates/repo/modelmanage/convertIndex.tmpl View File

@@ -581,10 +581,10 @@
if(versionList[0].Engine == engineOption){
return "selected=\"selected\"";
}else{
if(versionList[0].Engine==122 && engineOption==2){
if((versionList[0].Engine==122 || versionList[0].Engine==37) && engineOption==2){
return "selected=\"selected\"";
}
if(versionList[0].Engine==121 && engineOption==1){
if((versionList[0].Engine==121 || versionList[0].Engine==38) && engineOption==1){
return "selected=\"selected\"";
}
}


+ 2
- 2
templates/repo/modelmanage/showinfo.tmpl View File

@@ -244,9 +244,9 @@ function loadInfo(){
function getEngineName(model){
if(model.Engine == 0){
return "PyTorch";
}else if(model.Engine == 1 || model.Engine == 121){
}else if(model.Engine == 1 || model.Engine == 121 || model.Engine == 38){
return "TensorFlow";
}else if(model.Engine == 2 || model.Engine == 122 || model.Engine == 35){
}else if(model.Engine == 2 || model.Engine == 122 || model.Engine == 35 || model.Engine == 37){
return "MindSpore";
}else if(model.Engine == 3){
return "Other";


+ 63
- 0
templates/repo/modelsafety/indicators_descr.tmpl View File

@@ -0,0 +1,63 @@
<span>
<i class="question circle icon indicators_descr" style="cursor:pointer;"></i>
<div class="ui flowing popup bottom left transition hidden" style="inset: 564px auto auto 1px; width: 920px">
<table class="ui celled table">
<thead>
<tr>
<th style="width:80px;">指标</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td data-label="指标">ACC</td>
<td data-label="说明" indicator="ACC">Accuracy:精确度,计算模型预测准确率,该指标越高,说明评测结果越好。</td>
</tr>
<!-- <tr>
<td data-label="指标">CAV</td>
<td data-label="说明" indicator="CAV">Classification Accuracy Variance:用于评估深度学习模型性能的最重要指标为准确性。该指标值越高,说明评测结果越好。</td>
</tr> -->
<tr>
<td data-label="指标">ASS</td>
<td data-label="说明" indicator="ASS">Average Structural Similarity:所有攻击成功对抗样本与其原始样本间的平均相似性。该指标越大,说明评测结果越好。</td>
</tr>
<tr>
<td data-label="指标">ALDp</td>
<td data-label="说明" indicator="ALDp">Average LpDistortion:为所有攻击成功的对抗样本的平均归一化Lp失真度,ALDp值越小,对抗样本的不可感知性越强。</td>
</tr>
<tr>
<td data-label="指标">ACAC</td>
<td data-label="说明" indicator="ACAC">Average Confidence of Adversarial Class(ACAC):这个数值越高,攻击算法的攻击能力越强。</td>
</tr>
<!-- <tr>
<td data-label="指标">ACTC</td>
<td data-label="说明" indicator="ACTC">Average Confidence of True Class(ACTC):这个数值越低,攻击算法的攻击能力越强。</td>
</tr> -->
<tr>
<td data-label="指标">PSD</td>
<td data-label="说明" indicator="PSD">Perturbation Sensitivity Distance:用于评测人类对扰动的感知能力。该指标值越大,说明评测结果越差。</td>
</tr>
<!-- <tr>
<td data-label="指标">CACC</td>
<td data-label="说明" indicator="CACC">Clean ACC:该值计算的是原始未被攻击的样本,使用模型和groundtruth相比较的模型的本身的一个。</td>
</tr> -->
</tbody>
</table>
</div>
</span>
<script>
;(function() {
setTimeout(function(){
$('.indicators_descr').popup({
inline: true,
hoverable: true,
position: 'top center',
delay: {
show: 300,
hide: 800
}
});
}, 1000);
})();
</script>

+ 469
- 0
templates/repo/modelsafety/new.tmpl View File

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

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

.min_title{
font-size: 14px !important;
margin-bottom: 2rem !important;
}
.width100 {
width: 100% !important;
}

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

.width85 {
width: 85% !important;
margin-left: 10.5rem !important;
align-items: center;
}

.width48 {
width: 48.5% !important;
}

.nowrapx {
white-space: nowrap !important;
}

.v-middle {
vertical-align: middle;
}

.label-required:after {
margin: -0.2em 0 0 0.2em;
content: '*';
color: #db2828;
visibility: visible !important;
}
</style>
{{template "custom/global_mask" .}}
<div class="repository">
{{template "repo/header" .}}
<div class="ui container">
{{$Grampus := (or (eq (index (SubJumpablePath .Link) 1) "create_grampus_gpu") (eq (index (SubJumpablePath .Link) 1) "create_grampus_npu"))}}
<div class="cloudbrain-type" style="display: none;" data-grampus="{{$Grampus}}" data-cloudbrain-type="{{.datasetType}}" data-repo-link="{{.RepoLink}}" data-flag-model="true" data-dataset-uuid="{{.attachment}}" data-dataset-name="{{.dataset_name}}" data-queue="{{.QueuesDetail}}" data-queue-start="{{.i18n.Tr "repo.wait_count_start"}}" data-queue-end="{{.i18n.Tr "repo.wait_count_end"}}"></div>
{{template "base/alert" .}}
<h4 class="ui top attached header">
{{.i18n.Tr "repo.modelarts.evaluate_job.new_job"}}
</h4>
<div class="ui attached segment">
<input type="hidden" name="benchmarkMode" value="{{.benchmarkMode}}">
<form id="form_id" class="ui form alogrithm_form" action="{{.RepoLink}}/modelsafety/create" method="post">
{{.CsrfTokenHtml}}
<input type="hidden" name="compute_resource" value="{{.compute_resource}}">
<input type="hidden" name="type" value="{{.type}}">
<input type="hidden" id="ai_engine_name" name="engine_names" value="">
<input type="hidden" id="ai_flaver_name" name="flaver_names" value="">
<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_scenes"}}</label>
<div class="ui blue small menu compact selectcloudbrain">
<a class="item alogrithm_benchmark"
href="{{.RepoLink}}/cloudbrain/benchmark/create?benchmarkMode=alogrithm">{{.i18n.Tr "repo.cloudbrain.benchmark.algorithm"}}</a>
<a class="item model_benchmark"
href="{{.RepoLink}}/cloudbrain/benchmark/create?benchmarkMode=model">{{.i18n.Tr "repo.cloudbrain.benchmark.model"}}</a>
<a class="item active model_safe_benchmark"
href="{{.Link}}">{{.i18n.Tr "modelsafety.model_security_evaluation"}}</a>
</div>
</div>
<!-- <div class="required unite min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_cluster"}}</label>
<div class="ui blue mini menu compact selectcloudbrain">
<a class="item {{if not $Grampus}}active{{end}}" href="{{.RepoLink}}/modelsafety/create_gpu">
<svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg>
{{.i18n.Tr "cloudbrain.resource_cluster_openi"}}
</a>
<a class="item {{if $Grampus}}active{{end}}" href="{{.RepoLink}}/modelsafety/create_grampus_gpu">
<svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg>
{{.i18n.Tr "cloudbrain.resource_cluster_c2net"}}(Beta)
</a>
</div>
</div> -->
<div class="inline min_title required field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label>
<div class="ui blue mini menu compact selectcloudbrain">
<a class="{{if eq .datasetType 0}}active{{end}} item" href="{{.RepoLink}}/modelsafety/create_{{if $Grampus}}grampus_{{end}}gpu">
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16"
height="16">
<path fill="none" d="M0 0h24v24H0z" />
<path
d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z" />
</svg>
CPU/GPU
</a>
<a class="{{if eq .datasetType 1}}active{{end}} item" href="{{.RepoLink}}/modelsafety/create_{{if $Grampus}}grampus_{{end}}npu">
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16"
height="16">
<path fill="none" d="M0 0h24v24H0z" />
<path
d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z" />
</svg>
Ascend NPU</a>
</div>
</div>
<div>
<div class="min_title inline field" style="margin-top:-10px;">
<label class="label-fix-width" style="font-weight: normal;"></label>
{{template "custom/task_wait_count" .}}
</div>
<div class="min_title inline field" style="margin-top:-20px;margin-bottom:12px !important;">
<label class="label-fix-width" style="font-weight: normal;"></label>
<div style="display:inline-block;">
<div style="display:flex;align-items:center;color:#f2711c;">
<i class="ri-error-warning-line" style="margin-right: 0.5rem; font-size: 14px"></i>
<span style="font-size: 12px">{{.i18n.Tr "modelsafety.new_model_security_evaluation_tips"}}</span>
</div>
</div>
</div>
<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label>
<input style="width: 80%;" name="display_job_name" id="trainjob_job_name"
placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}"
tabindex="3" autofocus required maxlength="36">
<span class="tooltips" style="display: block;margin-left: 11.5rem;">{{.i18n.Tr "repo.cloudbrain_jobname_err"}}</span>
</div>
<div class="min_title inline field">
<label class="label-fix-width" style="font-weight: normal;"
for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}}</label>
<textarea style="width: 80%;" id="description" name="description" rows="2" maxlength="254"
placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}}
onchange="this.value=this.value.substring(0, 255)"
onkeydown="this.value=this.value.substring(0, 255)"
onkeyup="this.value=this.value.substring(0, 255)">{{.description}}</textarea>
</div>
<input type="hidden" id="ai_model_version" name="model_version" value="{{$.model_version}}">
<div class="required unite inline min_title fields" style="width: 96.8%;">
<div class="required eight wide field">
<label style="font-size:14px;font-weight: normal;white-space: nowrap;width: 210px;text-align: right;">{{.i18n.Tr "repo.modelarts.infer_job.select_model"}}</label>
<div class="ui fluid selection dropdown" id="select_model">
<input type="hidden" name="model_name" required value="{{.model_name}}">
<div class="text"></div>
<i class="dropdown icon"></i>
<div class="menu" id="model_name">
</div>
</div>
</div>
<input type="hidden" name="pre_train_model_url" value="{{.train_url}}">
<div class="three wide field">
<div class="ui fluid selection dropdown" id="select_model_version">
<input type="hidden" name="train_url" required value="{{.train_url}}">
<div class="text"></div>
<i class="dropdown icon"></i>
<div class="menu" id="model_name_version"></div>
</div>
</div>
<div class="five wide field">
<div class="ui fluid selection dropdown" id="select_model_checkpoint">
<input type="hidden" name="ckpt_name" required value="{{.ckpt_name}}">
<div class="text"></div>
<i class="dropdown icon"></i>
<div class="menu" id="model_checkpoint">
</div>
</div>
</div>
<span >
<i class="question circle icon" data-content="{{.i18n.Tr "cloudbrain.model_file_postfix_rule"}}" data-position="top center" data-variation="inverted mini"></i>
</span>
</div>
<div class="required inline min_title field " style="display: none;">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.resource_pool"}}</label>
<select class="ui dropdown width48" id="trainjob_resource_pool" name="pool_id">
{{range .resource_pools}}
<option value="{{.ID}}">{{.Value}}</option>
{{end}}
</select>
</div>
{{if not $Grampus}}
{{if eq .datasetType 0}}
<div id="images-new-cb"></div>
<input type="hidden" id="ai_image_name" value="{{.image}}">
{{else}}
<div class="required inline min_title fields" style="width: 95%;">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.AI_driver"}}</label>
<div class="field" style="flex: 1.5;">
<select class="ui dropdown width100" id="trainjob_engines">
{{range .engines}}
<option value="{{.Value}}">{{.Value}}</option>
{{end}}
</select>
</div>
<div class="field" style="flex: 2;" id="engine_name">
<select class="ui dropdown width100" id="trainjob_engine_versions" name="engine_id">
{{if .engine_id}}
{{range .engine_versions}}
{{if eq $.engine_id .ID}}
<option value="{{.ID}}">{{.Value}}</option>
{{end}}
{{end}}
{{range .engine_versions}}
{{if ne $.engine_id .ID}}
<option value="{{.ID}}">{{.Value}}</option>
{{end}}
{{end}}
{{else}}
{{range .engine_versions}}
<option value="{{.ID}}">{{.Value}}</option>
{{end}}
{{end}}
</select>
</div>
</div>
{{end}}
{{else}}
{{if eq .datasetType 0}}
<div id="images-new-grampus"></div>
{{else}}
<div class="required min_title inline field" id="engine_name">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.mirror"}}</label>
<select class="ui dropdown width48" id="trainjob_images" name="image_id">
{{if .image_id}}
{{range .images}}
{{if eq $.image_id .ID}}
<option value="{{.ID}}">{{.Name}}</option>
{{end}}
{{end}}
{{range .images}}
{{if ne $.image_id .ID}}
<option value="{{.ID}}">{{.Name}}</option>
{{end}}
{{end}}
{{else}}
{{range .images}}
<option name="image_id" value="{{.ID}}">{{.Name}}</option>
{{end}}
{{end}}
</select>
</div>
{{end}}
{{end}}

<div class="inline field min_title required">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label>
<input style="width: 48.5%;" name="boot_file" id="trainjob_boot_file" value="{{.boot_file}}" tabindex="3" autofocus required maxlength="255">
<span>
<i class="question circle icon link" data-content={{.i18n.Tr "repo.modelarts.train_job.boot_file_helper"}} data-position="right center" data-variation="mini"></i>
</span>
<a href="https://git.openi.org.cn/OpenIOSSG/aisafety" target="_blank">{{.i18n.Tr "cloudbrain.view_sample"}}</a>
</div>
<div class="inline field min_title required fields" style="width: 95%;">
<label class="label-fix-width label-required" style="font-weight: normal;">{{.i18n.Tr "modelsafety.base_data_set"}}</label>
<div class="field" style="flex:1.5">
<select id="baseDataSet-sel" class="ui dropdown width100" name="src_dataset" ovalue="{{.src_dataset}}"></select>
</div>
<div class="field" style="flex:2;display:flex;">
<label class="label-fix-width label-required" style="font-weight:normal;display:flex;justify-content:right;align-items: center;">{{.i18n.Tr "modelsafety.combat_data_set"}}</label>
<div style="flex:1">
<select id="combatDataSet-sel" class="ui dropdown width100" name="combat_dataset" ovalue="{{.combat_dataset}}"></select>
</div>
</div>
</div>
<div class="inline min_title field required">
<label class="label-fix-width" style="font-weight:normal;">{{.i18n.Tr "modelsafety.evaluation_indicators"}}</label>
<input type="text" style="display:none;" name="evaluation_index" />
<select id="job_indicators" class="ui dropdown width48 v-middle" multiple style='width:385px;' ovalue="{{.evaluationIndex}}">
<option value="ACC">ACC</option>
<!-- <option value="CAV">CAV</option>-->
<option value="ASS">ASS</option>
<option value="ALDp">ALDp</option>
<option value="ACAC">ACAC</option>
<!-- <option value="ACTC">ACTC</option> -->
<option value="PSD">PSD</option>
<!-- <option value="CACC">CACC</option> -->
</select>
{{template "repo/modelsafety/indicators_descr".}}
</div>
<div class="inline min_title field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label>
<span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;">
<i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}
</span>
<input id="store_run_para" type="hidden" name="run_para_list">
<div class="dynamic field" style="margin-top: 1rem;" data-params="{{.run_para_list}}" data-params-value="{{.i18n.Tr "repo.modelarts.train_job.parameter_value"}}" data-params-name="{{.i18n.Tr "repo.modelarts.train_job.parameter_name"}}"></div>
</div>
<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="__specs__" class="ui dropdown width48"
placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px' ovalue="{{.spec_id}}"
{{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}
name="spec_id">
</select>
{{if .CloudBrainPaySwitch}}
<div class="cloudbrain_resource_spec_blance_tip width48" style="padding:0 5px;margin:6px 0;margin-left:155px;font-size:12px;">
<span>{{$.i18n.Tr "points.balance_of_points"}}<span style="color:red;margin: 0 3px">{{.PointAccount.Balance}}</span>{{$.i18n.Tr "points.points"}}</span><span>{{$.i18n.Tr "points.expected_time"}}<span style="color:red;margin: 0 3px" class="can-use-time"></span>{{$.i18n.Tr "points.hours"}}</span>
<span style="float:right;">
<i class="question circle icon link" data-position="right center" data-variation="mini"></i>
<a href="{{AppSubUrl}}/reward/point/rule" target="_blank">{{$.i18n.Tr "points.points_acquisition_instructions"}}</a>
</span>
</div>
{{end}}
</div>
<div class="inline unite min_title field">
<label class="label-fix-width" style="font-weight: normal;"></label>
<button class="ui create_train_job green button">
{{.i18n.Tr "repo.cloudbrain.new"}}
</button>
<a class="ui button" href="{{.RepoLink}}/cloudbrain/benchmark">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a>
</div>
</div>
</form>
</div>
</div>
</div>
{{template "base/footer" .}}
<script src="{{StaticUrlPrefix}}/js/specsuse.js?v={{MD5 AppVer}}" type="text/javascript"></script>
<script src="{{StaticUrlPrefix}}/js/cloudbrainNew.js?v={{MD5 AppVer}}" type="text/javascript"></script>

<script>
let form = document.getElementById('form_id');
let createFlag = false
form.onsubmit = function (e) {
if(createFlag) return false
createFlag = true
}
$('.menu .item').tab();
var isValidate = false;
function validate() {
$('.ui.form')
.form({
on: 'blur',
fields: {
boot_file: {
identifier: "boot_file",
rules: [
{
type: "regExp[/.+.py$/g]",
},
],
},
job_name: {
identifier: "job_name",
rules: [
{
type: "regExp[/^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/]",
},
],
},
display_job_name: {
identifier: "display_job_name",
rules: [
{
type: "regExp[/^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/]",
},
],
},
attachment: {
identifier: "attachment",
rules: [
{
type: "empty",
},
],
},
spec_id: {
identifier: "spec_id",
rules: [{ type: "empty" }],
},
evaluation_index:{
identifier: 'evaluation_index',
rules: [{ type: 'empty', } ]
},
model_name:{
identifier: 'model_name',
rules: [{ type: 'empty', } ]
},
train_url:{
identifier: 'train_url',
rules: [{ type: 'empty', }]
},
ckpt_name:{
identifier: 'ckpt_name',
rules: [{ type: 'empty', }]
},
},
onSuccess: function () {
document.getElementById("mask").style.display = "block";
isValidate = true;
},
onFailure: function (e) {
document.getElementById("mask").style.display = "none";
isValidate = false;
createFlag = false;
return false;
}
})
}

validate();
$('.ui.create_train_job.green.button').click(function (e) {
validate();
});

;(function() {
var SPECS = {{ .benchmark_specs }} || {{ .Specs }};
var showPoint = {{ .CloudBrainPaySwitch }};
window.renderSpecsSelect($('#__specs__'), SPECS, showPoint, {
gpu_memory: {{$.i18n.Tr "cloudbrain.gpu_memory"}},
free: {{$.i18n.Tr "cloudbrain.free"}},
point_hr: {{$.i18n.Tr "cloudbrain.point_hr"}},
memory: {{$.i18n.Tr "cloudbrain.memory"}},
shared_memory: {{$.i18n.Tr "cloudbrain.shared_memory"}},
});
})();

;(function() {
var baseDataSetName = {{.BaseDataSetName}} || '';
var baseDataSetUUID = {{.BaseDataSetUUID}} || '';
var combatDataSetName = {{.CombatDataSetName}} || '';
var combatDataSetUUID = {{.CombatDataSetUUID}} || '';
var baseDataSetSel = $('#baseDataSet-sel');
var combatDataSetSel = $('#combatDataSet-sel');

function initDataSetSelect(names, keys, selectEl) {
selectEl.empty();
var nameList = names.split(',');
var keyList = keys.split(',')
for (var i = 0, iLen = nameList.length; i < iLen; i++) {
selectEl.append(`<option index="${i}" value="${keyList[i]}">${nameList[i]}</option>`);
}
var oValue = selectEl.attr('ovalue');
oValue && selectEl.val(oValue);
selectEl.on('change', function() {
var self = $(this);
var selectIndex = self.find('option:selected').attr('index');
var type = self.attr('id');
if (type === 'baseDataSet-sel') {
var val = combatDataSetSel.find('option[index="'+selectIndex+'"]').attr('value');
combatDataSetSel.dropdown('set selected', val);
} else {
var val = baseDataSetSel.find('option[index="'+selectIndex+'"]').attr('value');
baseDataSetSel.dropdown('set selected', val);
}
}).trigger('change');
}
initDataSetSelect(baseDataSetName, baseDataSetUUID, baseDataSetSel);
initDataSetSelect(combatDataSetName, combatDataSetUUID, combatDataSetSel);
$('#job_indicators').on('change', function() {
var value = $(this).val();
$('input[name="evaluation_index"]').val(value.join(';'));
}).trigger('change');
var oIndicators = $('#job_indicators').attr('ovalue');
if (oIndicators) {
$('input[name="evaluation_index"]').val(oIndicators);
$('#job_indicators').dropdown('set exactly', oIndicators.split(';'))
};
})();
</script>

+ 1
- 0
templates/repo/modelsafety/newgpu.tmpl View File

@@ -0,0 +1 @@
{{template "repo/modelsafety/new".}}

+ 1
- 0
templates/repo/modelsafety/newnpu.tmpl View File

@@ -0,0 +1 @@
{{template "repo/modelsafety/new".}}

+ 893
- 0
templates/repo/modelsafety/show.tmpl View File

@@ -0,0 +1,893 @@
{{template "base/head" .}}
<style>
.according-panel-heading {
box-sizing: border-box;
padding: 8px 16px;
color: #252b3a;
background-color: #f2f5fc;
line-height: 1.5;
cursor: pointer;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
}

.accordion-panel-title {
margin-top: 0;
margin-bottom: 0;
color: #252b3a;
}

.accordion-panel-title-content {
vertical-align: middle;
display: inline-block;
width: calc(100% - 32px);
cursor: default;
}

.acc-margin-bottom {
margin-bottom: 5px;
}

.title_text {
font-size: 12px;
}

.ac-display-inblock {
display: inline-block;
}

.cti-mgRight-sm {
margin-right: 8px;
}

.ac-text-normal {
font-size: 14px;
color: #575d6c;
}

.uc-accordionTitle-black {
color: #333;
}

.accordion-border {
border: 1px solid #cce2ff;
}

.padding0 {
padding: 0 !important;
}

.content-pad {
padding: 15px 35px;
}

.content-margin {
margin: 10px 5px;
}

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

.ac-grid {
display: block;
*zoom: 1;
}

.ac-grid-col {
float: left;
width: 100%;
}

.ac-grid-col2 .ac-grid-col {
width: 50%;
}

.ti-form {
text-align: left;
max-width: 100%;
vertical-align: middle;
}

.ti-form>tbody {
font-size: 12px;
}

.ti-form>tbody,
.ti-form>tbody>tr {
vertical-align: inherit;
}

.ti-text-form-label {

padding-bottom: 20px;
padding-right: 20px;
color: #8a8e99;
font-size: 12px;
white-space: nowrap !important;
width: 80px;
line-height: 30px;
}

.ti-text-form-content {
line-height: 30px;
padding-bottom: 20px;
}

.ti-form>tbody>tr>td {
vertical-align: top;
white-space: normal;
}

td,
th {
padding: 0;
}

.ac-grid-col .text-span {
width: 420px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

.redo-color {
color: #3291F8;
}

.ti-action-menu-item:not(:last-child) {
margin-right: 10px;
padding-right: 11px;
text-decoration: none !important;
color: #526ecc;
cursor: pointer;
display: inline-block;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
position: relative;
}

.ti-action-menu-item:not(:last-child):after {
content: "";
display: inline-block;
position: absolute;
height: 12px;
right: 0;
top: 50%;
-webkit-transform: translateY(-6px);
-ms-transform: translateY(-6px);
-o-transform: translateY(-6px);
transform: translateY(-6px);
border-right: 1px solid #dfe1e6;
}

.text-width80 {
width: 100px;
line-height: 30px;
}

.border-according {
border: 1px solid #dfe1e6;
}

.disabled {
cursor: default;
pointer-events: none;
color: rgba(0, 0, 0, .6) !important;
opacity: .45 !important;
}

.pad20 {

border: 0px !important;
}

.model_file_bread {
margin-bottom: -0.5rem !important;
padding-left: 1rem;
padding-top: 0.5rem;
}
</style>
<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="repository">
{{template "repo/header" .}}
<div class="ui container">
<h4 class="ui header" id="vertical-segment">
<div class="ui breadcrumb">
<a class="section" href="{{.RepoLink}}/debugjob?debugListType=all">
{{$.i18n.Tr "repo.cloudbrain"}}
</a>
<div class="divider"> / </div>
<a class="section" href="{{$.RepoLink}}/cloudbrain/benchmark">
{{$.i18n.Tr "repo.modelarts.evaluate_job"}}
</a>
<div class="divider"> / </div>
<div class="active section" vfield="DisplayJobName"></div>
</div>
</h4>
<div class="ui accordion border-according" id="accordion" data-repopath="{{$.RepoRelPath}}/cloudbrain" data-jobid="" vdatajobid="ID" data-version="">
<input type="hidden" id="jobId_input" name="jobId_input" value="" vvalue="JobID">
<div class="active title padding0">
<div class="according-panel-heading">
<div class="accordion-panel-title">
<i class="dropdown icon"></i>
<span class="accordion-panel-title-content">
<span>
<div class="ac-display-inblock title_text acc-margin-bottom">
<span class="cti-mgRight-sm">
<span vtime="CreatedUnix"></span>
</span>
<span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.status"}}:
<span id="-status-span">
<i id="icon" style="vertical-align: middle;" class="{{.Status}}" vclass="Status"></i>
<span id="text" style="margin-left: 0.4em;font-size: 12px;" vfield="Status"></span>
</span>
</span>
<span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}:</span>
<span class="cti-mgRight-sm uc-accordionTitle-black" id="-duration-span" vfield="TrainJobDuration"></span>
</div>
</span>
</span>
</div>
</div>
</div>
<div class="active content">
<div class="content-pad">
<div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);">
<a class="active item" data-tab="first0">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a>
<a class="item log_bottom" data-tab="second0" data-version="">{{$.i18n.Tr "repo.modelarts.log"}}</a>
<a class="item" data-tab="third0" data-version="">{{.i18n.Tr "modelsafety.evaluation_result"}}</a>
</div>
<div class="ui tab active" data-tab="first0">
<div style="padding-top: 10px;">
<div class="tab_2_content">
<div class="ac-grid ac-grid-col2">
<div class="ac-grid-col">
<table class="ti-form">
<tbody class="ti-text-form">
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain_task"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" vfield="DisplayJobName"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.status"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" id="-status" vfield="Status"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.createtime"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w">
<span style="font-size: 12px;" class="v-field" vtime="CreatedUnix"></span>
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.time.starttime"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w v-field" vtime="StartTime" id="-startTime"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.time.endtime"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w v-field" vtime="EndTime" id="-EndTime"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" vfield="TrainJobDuration" id="-duration"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80" vimagetitle="Image">
<span style="display:none;">{{$.i18n.Tr "cloudbrain.mirror"}}</span>
<span style="display:none;">{{$.i18n.Tr "repo.modelarts.train_job.AI_driver"}}</span>
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="-mirror">
<span class="ui poping up clipboard" data-position="top center" id="clipboard-btn" style="cursor:pointer"
data-clipboard-text="{{.Image}}"
data-success="{{$.i18n.Tr "repo.copied"}}"
data-error="{{$.i18n.Tr "repo.copied_error"}}"
data-content="{{$.i18n.Tr "repo.copy"}}"
data-variation="inverted tiny"
vdataclipboardtext="Image"
>
<span vtitle="Image" vimage="Image" ></span></span>
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.benchmark.evaluate_scenes"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" vfield="BenchmarkType"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.benchmark.evaluate_type"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" vfield="BenchmarkTypeName"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{.i18n.Tr "modelsafety.base_data_set"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" vdataset0="DatasetName"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{.i18n.Tr "modelsafety.combat_data_set"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" vdataset1="DatasetName"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" vtitle="Parameters" vfield="Parameters"></div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="ac-grid-col">
<table class="ti-form">
<tbody class="ti-text-form">
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.code_version"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" vfield="BranchName"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.description"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" vtitle="Description" vfield="Description"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
<span>{{$.i18n.Tr "repo.modelarts.train_job.resource_type"}}</span>
</td>
<td class="ti-text-form-content resorce_type">
<div class="text-span text-span-w"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.standard"}}
</td>
<td class="ti-text-form-content spec">
<div class="text-span text-span-w"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.model_name"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" vfield="ModelName"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelconvert.modelversion"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" vfield="ModelVersion"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.infer_job_model_file"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" vfield="CkptName"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain_creator"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" id="-mirror" vuser="User.Name"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.start_file"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" vfield="BootFile"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{.i18n.Tr "modelsafety.evaluation_indicators"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" vfield="LabelName"></div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>

</div>
</div>
<div class="ui tab" data-tab="second0">
<div>
<a id="-log-down"
class='{{if $.canDownload}}ti-download-file{{else}}disabled{{end}}'
href="/api/v1/repos/{{$.RepoRelPath}}/cloudbrain">
<i class="ri-download-cloud-2-line"></i>
<span style="margin-left: 0.3rem;">{{$.i18n.Tr "repo.modelarts.download_log"}}</span>
</a>
</div>
<div
style="position: relative;border: 1px solid rgba(0,0,0,.2);padding: 0 10px;margin-top: 10px;">
<span>
<a title="滚动到顶部" style="position: absolute; right: -32px;cursor: pointer;"
class="log_top" data-version=""><i class="icon-to-top"></i></a>
</span>
<span class="log-info-">
<a title="滚动到底部" style="position: absolute; bottom: 10px;right: -32px;cursor: pointer;"
class="log_bottom" data-version=""><i
class="icon-to-bottom"></i></a>
</span>
<div class="ui message message" style="display: none;">
<div id="header"></div>
</div>
<div class="ui attached log log-scroll" id="log" data-version=""
style="height: 300px !important; overflow: auto;">
<div class="ui inverted active dimmer">
<div class="ui loader"></div>
</div>
<input type="hidden" name="end_line" value>
<input type="hidden" name="start_line" value>
<pre id="log_file"></pre>
</div>
</div>
</div>
<div class="ui tab" data-tab="third0">
<style>
.__res_item {
margin-bottom: 20px;
}
.__res_title {
height: 50px;
display: flex;
align-items: center;
margin-bottom: 10px;
}
.__res_title_icon {
height: 48px;
width: 48px;
margin-right: 8px;
}
.bNIWIE.fill:not([stroke]) {
fill: rgb(105, 192, 255);
}
.bNIWIE.fill:not([fill]) {
fill: rgb(105, 192, 255);
}
.__res_title_txt {
font-family: SourceHanSansSC;
font-size: 14px;
font-style: normal;
line-height: 20px;
text-decoration: none;
}
.__res_title_txt1 {
font-weight: 700;
color: rgb(3, 102, 214);
}
.__res_title_txt2 {
font-weight: 300;
color: rgba(136,136,136,1);
}
.__res_table_container {
overflow-x: auto;
}
.__res_table_container table {
border-bottom-left-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
.__res_table_container th, .__res_table_container td {
text-align: center !important;
}
.__res_chart_container {
height:280px;
border: 1px solid rgba(34,36,38,.1);
margin-top: -1px;
border-bottom-left-radius: .28571429rem;
border-bottom-right-radius: .28571429rem;
}
.__res_no_data {
height: 200px;
display: flex;
justify-content: center;
align-items: center;
}
</style>
<div style="display:none;">
{{template "repo/modelsafety/indicators_descr".}}
</div>
<div class="__res_container">
<div class="__res_no_data">{{.i18n.Tr "modelsafety.no_data"}}</div>
</div>
</div>
</div>
</div>
</div>
{{template "base/paginate" .}}
</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>
{{template "base/footer" .}}

<script src="{{StaticUrlPrefix}}/js/specsuse.js?v={{MD5 AppVer}}" type="text/javascript"></script>

<script>
;(function() {
function paddingZeros(str, len) {
str = str.toString();
if (str.length < len) {
str = new Array(len - str.length).fill('0').join('') + str;
}
return str;
}

function timeFormat(date) {
return `${date.getFullYear()}-${paddingZeros(date.getMonth() + 1, 2)}-${paddingZeros(date.getDate(), 2)} ${paddingZeros(date.getHours(), 2)}:${paddingZeros(date.getMinutes(), 2)}:${paddingZeros(date.getSeconds(), 2)}`;
}

function initTable(tableEl, data) {
tableEl.empty();
var lanUntargetted = {{.i18n.Tr "modelsafety.untargetted"}};
var lanTargetted = {{.i18n.Tr "modelsafety.targetted"}};
if (data.indicator === 'ALDp') {
tableEl.append(`
<table class="ui celled table">
<thead>
<tr class="tr-head"><th colspan="2" style="width:100px;">${data.indicator}</th></tr>
</thead>
<tbody>
<tr class="tr-untargetted"><td rowspan="3">${lanUntargetted}</td><td>L_0 norm</td></tr>
<tr class="tr-untargetted"><td style="border-left: 1px solid rgba(34,36,38,.1);">L_2 norm</td></tr>
<tr class="tr-untargetted"><td style="border-left: 1px solid rgba(34,36,38,.1);">L_inf norm</td></tr>
<tr class="tr-targetted"><td rowspan="3">${lanTargetted}</td><td>L_0 norm</td></tr>
<tr class="tr-targetted"><td style="border-left: 1px solid rgba(34,36,38,.1);">L_2 norm</td></tr>
<tr class="tr-targetted"><td style="border-left: 1px solid rgba(34,36,38,.1);">L_inf norm</td></tr>
</tbody>
</table>`);
var trHead = tableEl.find('tr.tr-head');
var trUntargetted = tableEl.find('tr.tr-untargetted');
var trTargetted = tableEl.find('tr.tr-targetted');
for (var i = 0, iLen = data.params.length; i < iLen; i++) {
var params = data.params;
var untargetted = data.untargetted;
var targetted = data.targetted;
trHead.append(`<th>param(${params[i]})</th>`);
trUntargetted.eq(0).append(`<td>${Number(untargetted[i][0]).toFixed(3)}</td>`);
trUntargetted.eq(1).append(`<td>${Number(untargetted[i][1]).toFixed(3)}</td>`);
trUntargetted.eq(2).append(`<td>${Number(untargetted[i][2]).toFixed(3)}</td>`);
trTargetted.eq(0).append(`<td>${Number(targetted[i][0]).toFixed(3)}</td>`);
trTargetted.eq(1).append(`<td>${Number(targetted[i][1]).toFixed(3)}</td>`);
trTargetted.eq(2).append(`<td>${Number(targetted[i][2]).toFixed(3)}</td>`);
}
} else {
tableEl.append(`
<table class="ui celled table">
<thead>
<tr class="tr-head"><th style="width:100px;">${data.indicator}</th></tr>
</thead>
<tbody>
<tr class="tr-untargetted"><td>{{.i18n.Tr "modelsafety.untargetted"}}</td></tr>
<tr class="tr-targetted"><td>{{.i18n.Tr "modelsafety.targetted"}}</td></tr>
</tbody>
</table>`);
var trHead = tableEl.find('tr.tr-head');
var trUntargetted = tableEl.find('tr.tr-untargetted');
var trTargetted = tableEl.find('tr.tr-targetted');
for (var i = 0, iLen = data.params.length; i < iLen; i++) {
var params = data.params;
var untargetted = data.untargetted;
var targetted = data.targetted;
trHead.append(`<th>param(${params[i]})</th>`);
trUntargetted.append(`<td>${Number(untargetted[i]).toFixed(3)}</td>`);
trTargetted.append(`<td>${Number(targetted[i]).toFixed(3)}</td>`);
}
}
}

function initChart(chartEl, data) {
var chartHandle = chartEl.data('chart');
chartHandle && chartHandle.dispose();
chartHandle && window.removeEventListener('resize', chartHandle.resize);
chartHandle = echarts.init(chartEl[0]);
chartEl.data('chart', chartHandle);
var lanUntargetted = {{.i18n.Tr "modelsafety.untargetted"}};
var lanTargetted = {{.i18n.Tr "modelsafety.targetted"}};
var option = {
tooltip: {
trigger: 'axis'
},
color: ['rgb(80, 135, 236)', 'rgb(104, 187, 196)'],
legend: {
data: [lanUntargetted, lanTargetted],
top: '15',
},
grid: {
top: '50',
left: '20',
right: '20',
bottom: '20',
containLabel: true
},
xAxis: {
type: 'category',
data: data.params.map(function(item){ return `param(${item})`}),
},
yAxis: {
type: 'value'
},
series: [
{
name: lanUntargetted,
type: 'line',
data: (data.untargetted || []).map(function(item){ return Number(Number(item).toFixed(3)) }),
},
{
name: lanTargetted,
type: 'line',
data: (data.targetted || []).map(function(item){ return Number(Number(item).toFixed(3)) }),
}
]
};
if (data.indicator === 'ALDp') {
option.color = ['rgb(80, 135, 236)', 'rgb(247, 238, 209)', 'rgb(231, 230, 238)', 'rgb(104, 187, 196)', 'rgb(211, 183, 136)', 'rgb(159, 131, 179)'];
option.legend.data = [`${lanUntargetted}(L_0)`, `${lanUntargetted}(L_2)`, `${lanUntargetted}(L_inf)`,
`${lanTargetted}(L_0)`, `${lanTargetted}(L_2)`, `${lanTargetted}(L_inf)`];
option.series = [
{
name: `${lanUntargetted}(L_0)`,
type: 'line',
data: (data.untargetted || []).map(function(item){ return Number(item[0].toFixed(3)) }),
},
{
name: `${lanUntargetted}(L_2)`,
type: 'line',
data: (data.untargetted || []).map(function(item){ return Number(item[1].toFixed(3)) }),
},
{
name: `${lanUntargetted}(L_inf)`,
type: 'line',
data: (data.untargetted || []).map(function(item){ return Number(item[2].toFixed(3)) }),
},
{
name: `${lanTargetted}(L_0)`,
type: 'line',
data: (data.targetted || []).map(function(item){ return Number(item[0].toFixed(3)) }),
},
{
name: `${lanTargetted}(L_2)`,
type: 'line',
data: (data.targetted || []).map(function(item){ return Number(item[1].toFixed(3)) }),
},
{
name: `${lanTargetted}(L_inf)`,
type: 'line',
data: (data.targetted || []).map(function(item){ return Number(item[2].toFixed(3)) }),
}
];
}
chartHandle.setOption(option);
window.addEventListener('resize', chartHandle.resize);
}

function initResItems(list) {
var resContainer = $('.__res_container');
resContainer.empty();
for (var i = 0, iLen = list.length; i < iLen; i++) {
var item = list[i], indicator = item.indicator;
var descr = $(`[indicator="${indicator}"]`).text();
var resItemContainer = $(`<div class="__res_item">
<div class="__res_title">
<div class="__res_title_icon">
<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-16fsqc8-0 bNIWIE svg-icon-path-icon fill" viewBox="0 0 32 32" width="48" height="48"><defs data-reactroot=""></defs><g><path d="M8.155 26.783c-3.342-2.449-5.488-6.36-5.488-10.771 0-0.004 0-0.008 0-0.012v0.001c0-7.364 5.969-13.333 13.333-13.333s13.333 5.969 13.333 13.333c0 0.003 0 0.007 0 0.011 0 4.412-2.146 8.323-5.451 10.745l-0.037 0.026-1.353-2.319c2.549-1.969 4.175-5.026 4.175-8.464 0-5.891-4.776-10.667-10.667-10.667s-10.667 4.776-10.667 10.667c0 3.437 1.626 6.494 4.15 8.445l0.025 0.018-1.353 2.319zM10.867 22.136c-1.758-1.477-2.867-3.677-2.867-6.136 0-4.418 3.582-8 8-8s8 3.582 8 8c0 2.459-1.109 4.658-2.854 6.126l-0.012 0.010-1.373-2.355c0.972-0.966 1.573-2.304 1.573-3.782 0-2.946-2.388-5.333-5.333-5.333s-5.333 2.388-5.333 5.333c0 1.478 0.601 2.816 1.573 3.782l0 0-1.373 2.355zM14.667 17.333h2.667v12h-2.667v-12z"></path></g></svg>
</div>
<div class="__res_title_txt">
<div class="__res_title_txt1">${indicator}-${item.name}</div>
<div class="__res_title_txt2">${descr}</div>
</div>
</div>
<div class="__res_table_container"></div>
<div class="__res_chart_container"></div>
</div>`);
resContainer.append(resItemContainer);
initTable(resItemContainer.find('.__res_table_container'), item);
initChart(resItemContainer.find('.__res_chart_container'), item);
}
};

function initResTab(data) {
var name = data.name;
var params = data.params;
var indicators = Object.keys(data.targetted);
var list = [];
for (var i = 0, iLen = indicators.length; i < iLen; i++) {
var indicator = indicators[i];
var obj = {
name: name,
params: params.flat(),
indicator: indicator,
targetted: data.targetted[indicator]['targets'],
untargetted: data.untargetted[indicator],
};
list.push(obj);
}
initResItems(list);
}

var resultData;
function initData() {
$.ajax({
url: window.location.href.replace('cloudbrain/benchmark', 'modelsafety'),
type: "get",
data: {},
contentType: "application/json; charset=utf-8",
success(res) {
for (var key in res) {
$(`[vfield="${key}"]`).text(res[key]);
$(`[vclass="${key}"]`).addClass(res[key]);
$(`[vtime="${key}"]`).text(res[key] ? timeFormat(new Date(res[key] * 1000)) : '--');
$(`[vtitle="${key}"]`).attr('title', res[key]);
$(`[vdataset0="${key}"]`).text(res[key] ? res[key].toString().split(';')[0] : '');
$(`[vdataset1="${key}"]`).text(res[key] ? res[key].toString().split(';')[1] : '');
$(`[vvalue="${key}"]`).val(res[key]);
$(`[vdatajobid="${key}"]`).attr('data-jobid', res[key]);
}
$(`[vfield="Description"]`).text(res['Description'] || '--');
$(`[vfield="Parameters"]`).text(res['Parameters'] || '--');

var imageName = res['Image'] || res['EngineName'];
$(`[vimagetitle="Image"] span`).hide();
if (res.Type === 0) {
imageName = res['Image'];
$(`[vimagetitle="Image"] span`).eq(0).show();
} else {
imageName = res['EngineName'];
$(`[vimagetitle="Image"] span`).eq(1).show();
}
$(`[vdataclipboardtext="Image"]`).attr('data-clipboard-text', imageName);
$(`[vimage="Image"]`).text(imageName);
$(`[vtitle="Image"]`).attr('title', imageName);
$(`[vuser="User.Name"]`).text(res['User'] && res['User']['Name']);

if (res.Spec) {
var SPEC = res.Spec;
var showPoint = false;
var specStr = window.renderSpecStr(SPEC, showPoint, {
gpu_memory: {{$.i18n.Tr "cloudbrain.gpu_memory"}},
free: {{$.i18n.Tr "cloudbrain.free"}},
point_hr: {{$.i18n.Tr "cloudbrain.point_hr"}},
memory: {{$.i18n.Tr "cloudbrain.memory"}},
shared_memory: {{$.i18n.Tr "cloudbrain.shared_memory"}},
});
$('td.ti-text-form-content.spec div').text(specStr);
SPEC && $('td.ti-text-form-content.resorce_type div').text(getListValueWithKey(ACC_CARD_TYPE, SPEC.AccCardType));
}
var oLogHref = $('#-log-down').attr('href');
$('#-log-down').attr('href', oLogHref + `/${res.ID}/download_log_file`);
if (res.ResultJson) {
try {
resultData = JSON.parse(res.ResultJson);
} catch(e) {
resultData = res.ResultJson;
}
}
},
error(err) {
console.log(err);
},
});
}

initData();
$(document).ready(function () {
$('.ui.accordion').accordion({ selector: { trigger: '.icon' } });
});

$('.pointing.secondary.menu .item').tab({
onVisible: function(tabPath) {
if (tabPath === 'first0') {
initData();
}
if (tabPath === 'third0') {
if (resultData) {
if (typeof resultData === 'object') {
initResTab(resultData);
} else if (typeof resultData === 'string') {
var resContainer = $('.__res_container');
resContainer.find('.__res_no_data').text(resultData);
}
}
}
},
});

})();
</script>

+ 69
- 36
templates/user/dashboard/cloudbrains.tmpl View File

@@ -15,11 +15,11 @@
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%;">
<div class="ui container" style="width:90%;overflow-x:auto;overflow-y:hidden">
{{template "base/alert" .}}
<div class="ui grid">
<div class="ui grid" style="min-width:1700px;">
<div class="row">
<div class="ui sixteen wide column">
<div class="ui sixteen wide column" style="margin-bottom:15px;">
<!-- 任务展示 -->
<div class="dataset list">
<!-- 表头 -->
@@ -71,7 +71,7 @@
<div class="row">
<!-- 任务名 -->
{{$JobID := '0'}}
{{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK"}}
{{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK" "MODELSAFETY"}}
{{$JobID = .Cloudbrain.ID}}
{{else}}
{{$JobID = .JobID}}
@@ -85,7 +85,7 @@
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE")}}
{{else if (eq .JobType "SNN4IMAGENET" "BRAINSCORE")}}
<a class="title"
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/cloudbrain/benchmark/{{$JobID}}"
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px">
@@ -106,7 +106,7 @@
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if eq .JobType "BENCHMARK"}}
{{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">
@@ -117,14 +117,13 @@
</div>
<!-- 集群 -->
<div class="one wide column text center nowrap" style="width:8% !important;">
<span
style="font-size: 12px;">{{if .Cluster}}{{.Cluster}}{{else}}--{{end}}</span>
<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"}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{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"}}/cloudbrain{{end}}'
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG"}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{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}}">
<span><i id="{{$JobID}}-icon" style="vertical-align: middle;"
class="{{.Status}}"></i><span id="{{$JobID}}-text"
@@ -155,8 +154,7 @@
<!-- 智算中心 -->
<div class="one wide column text center nowrap" style="width:8% !important;">
<span
style="font-size: 12px;">{{if .AiCenter}}{{.AiCenter}}{{else}}--{{end}}</span>
<span style="font-size: 12px;" class="aicenter_{{.DisplayJobName}}_{{$JobID}}">{{if .AiCenter}}{{.AiCenter}}{{else}}--{{end}}</span>
</div>
<!-- XPU类型 -->
<div class="one wide column text center nowrap" style="width:10% !important;">
@@ -169,6 +167,17 @@
var spanEl = document.querySelector('.card_type_{{.DisplayJobName}}_{{$JobID}}');
spanEl.setAttribute('title', cardType);
spanEl.innerText = cardType;
var cluster = spec.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>
<!-- 项目 -->
@@ -202,23 +211,35 @@
{{end}}
<!-- 停止任务 -->
<div class="ui compact buttons">
{{if eq .JobType "DEBUG" "BENCHMARK" "SNN4IMAGENET" "BRAINSCORE"}}
<form id="stopForm-{{$JobID}}" style="margin-left:-1px;">
{{$.CsrfTokenHtml}}
{{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 "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "SUCCEEDED" "STOPPED" "STOPPING" "CREATE_FAILED"}}disabled {{else}} blue {{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" "BENCHMARK" "SNN4IMAGENET" "BRAINSCORE"}}
<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 "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "SUCCEEDED" "STOPPED" "STOPPING" "CREATE_FAILED"}}disabled {{else}} blue {{end}}button'
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else if eq .JobType "BENCHMARK" }}/cloudbrain/benchmark{{else if eq .ComputeResource "NPU" }}/modelarts/notebook{{end}}/{{$JobID}}/stop'
data-jobid="{{$JobID}}">
{{$.i18n.Tr "repo.stop"}}
</a>
</form>
{{else}}
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}"
class='ui basic ai_stop {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "SUCCEEDED" "STOPPED" "STOPPING" "CREATE_FAILED"}}disabled {{else}} blue {{end}}button'
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else if eq .JobType "BENCHMARK" }}/cloudbrain/benchmark{{else if eq .ComputeResource "NPU" }}/modelarts/notebook{{end}}/{{$JobID}}/stop'
data-jobid="{{$JobID}}">
class='ui basic ai_stop_version {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "STOPPED" "SUCCEEDED" "CREATE_FAILED"}}disabled {{else}} blue {{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-version="{{.VersionName}}">
{{$.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 "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "STOPPED" "SUCCEEDED" "CREATE_FAILED"}}disabled {{else}} blue {{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-version="{{.VersionName}}">
{{$.i18n.Tr "repo.stop"}}
</a>
{{end}}
{{end}}
</div>
{{if eq .JobType "BENCHMARK"}}
@@ -228,7 +249,6 @@
{{$.i18n.Tr "repo.score"}}
</a>
</div>

{{end}}
<!-- 修改任务 -->
{{if eq .JobType "TRAIN"}}
@@ -239,6 +259,18 @@
</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}}
<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")}}/cloudbrain{{else if eq .JobType "DEBUG"}}{{if eq .ComputeResource "NPU"}}/modelarts/notebook{{else}}/cloudbrain{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .Cloudbrain.Type 1}}/modelarts/train-job{{else if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}/grampus/train-job{{end}}{{else if eq .JobType "INFERENCE"}}{{if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{end}}{{end}}/{{$JobID}}/del?ishomepage=true'
method="post">
@@ -250,6 +282,8 @@
{{$.i18n.Tr "repo.delete"}}
</a>
</form>
{{end}}
</div>
</div>
</div>
@@ -377,19 +411,18 @@
</div>

{{end}}
{{end}}
<div id="app" style="margin-top: 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>
{{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>
<!-- 确认模态框 -->


+ 2
- 1
web_src/js/components/dataset/selectDataset.vue View File

@@ -1011,7 +1011,8 @@ export default {
if (
location.href.indexOf("benchmark") !== -1 ||
location.href.indexOf("train-job") !== -1 ||
location.href.indexOf("inference") !== -1
location.href.indexOf("inference") !== -1 ||
location.href.indexOf("modelsafety") !== -1
) {
this.benchmarkNew = true;
}


+ 2
- 1
web_src/js/components/images/selectGrampusImages.vue View File

@@ -242,7 +242,8 @@ export default {
this.getImageListPublic();
if (
location.href.indexOf("benchmark") !== -1 ||
location.href.indexOf("train-job") !== -1
location.href.indexOf("train-job") !== -1 ||
location.href.indexOf("modelsafety") !== -1
) {
this.benchmarkNew = true;
}


+ 3
- 1
web_src/js/components/images/selectImages.vue View File

@@ -47,6 +47,7 @@
type="text"
:placeholder="i18n.image_search_placeholder"
v-model="search"
@keydown.enter.stop.prevent="searchName"
/>
</div>
<el-tabs v-model="activeName" @tab-click="handleClick">
@@ -505,7 +506,8 @@ export default {
if (
location.href.indexOf("train-job") !== -1 ||
location.href.indexOf("inference-job") !== -1 ||
location.href.indexOf("benchmark") !== -1
location.href.indexOf("benchmark") !== -1 ||
location.href.indexOf("modelsafety") !== -1
) {
this.benchmarkNew = true;
}


+ 4
- 0
web_src/js/features/cloudbrainShow.js View File

@@ -148,6 +148,10 @@ export default async function initCloudrainSow() {
$(`#${version_name}-log-down`)
.removeClass("ti-download-file")
.addClass("disabled");
} else {
$(`#${version_name}-log-down`)
.addClass("ti-download-file")
.removeClass("disabled");
}
$(`#log${version_name} input[name=end_line]`).val(data.EndLine); //如果变动就改变所对应的值
$(`#log${version_name} input[name=start_line]`).val(data.StartLine);


+ 3
- 1
web_src/js/features/cloudrbanin.js View File

@@ -8,6 +8,7 @@ export default async function initCloudrain() {
function loadJobStatus() {
$(".job-status").each((index, job) => {
const ID = job.dataset.jobid;
if (!ID) return;
const repoPath = job.dataset.repopath;
// const computeResource = job.dataset.resource
const versionname = job.dataset.version;
@@ -144,6 +145,7 @@ export default async function initCloudrain() {
function loadShowJobStatus() {
$(".ui.accordion.border-according").each((index, job) => {
const jobID = job.dataset.jobid;
if (!jobID) return;
const repoPath = job.dataset.repopath;
const versionname = job.dataset.version;
// ['IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED']
@@ -152,7 +154,7 @@ export default async function initCloudrain() {
// || job.textContent.trim() == 'CANCELED' || job.textContent.trim() == 'LOST') {
// return
// }
let status = $(`#${versionname}-status-span`).text();
let status = $(`#${versionname}-status-span`).text().trim();

if (
[


+ 1
- 0
web_src/js/index.js View File

@@ -65,6 +65,7 @@ const { AppSubUrl, StaticUrlPrefix, csrf } = window.config;
Object.defineProperty(Vue.prototype, "$echarts", {
value: echarts,
});
window.echarts = echarts;

function htmlEncode(text) {
return jQuery("<div />").text(text).html();


+ 3
- 2
web_src/js/standalone/cloudbrainNew.js View File

@@ -89,7 +89,7 @@
identifier: "job_name",
rules: [
{
type: "regExp[/^[a-zA-Z0-9-_]{1,36}$/]",
type: "regExp[/^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/]",
},
],
},
@@ -97,7 +97,7 @@
identifier: "display_job_name",
rules: [
{
type: "regExp[/^[a-zA-Z0-9-_]{1,36}$/]",
type: "regExp[/^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/]",
},
],
},
@@ -121,6 +121,7 @@
},
onFailure: function (e) {
isValidate = false;
createFlag = false;
return false;
},
});


+ 13
- 0
web_src/vuepages/apis/modules/desensitization.js View File

@@ -0,0 +1,13 @@
import service from "../service";

// 数据脱敏接口
export const postImgDesensitization = (params, data) => {
return service({
url: "/extension/tuomin/upload",
headers: { Accept: "image/png" },
responseType: "blob",
method: "POST",
params: params,
data: data,
});
};

+ 16
- 0
web_src/vuepages/langs/config/en-US.js View File

@@ -176,6 +176,22 @@ const en = {
Activated: 'Activated',
notActive: 'Not active',
},
tranformImageFailed:'Picture desensitization failed',
originPicture:'Origin picture',
desensitizationPicture:'Desensitization picture',
desensitizationObject:'Desensitization object',
example:'Example',
startDesensitization:'Start desensitization',
all:'All',
onlyFace:'Only face',
onlyLicensePlate:'Only license plate',
dragThePictureHere:'Drag the picture here',
or:'or',
clickUpload:'Click upload',
dataDesensitizationModelExperience:'Data desensitization model experience',
dataDesensitizationModelDesc:'Use AI technology to desensitize the face and license plate number in the picture. For more information about this model, please visit the project',
limitFilesUpload:'Only jpg/jpeg/png files can be uploaded',
limitSizeUpload:'The size of the uploaded file cannot exceed 20M!',
}

export default en;

+ 16
- 0
web_src/vuepages/langs/config/zh-CN.js View File

@@ -176,6 +176,22 @@ const zh = {
Activated: '已激活',
notActive: '未激活',
},
tranformImageFailed:'图片脱敏失败',
originPicture:'原始图片',
desensitizationPicture:'脱敏图片',
desensitizationObject:'脱敏对象',
example:'示例',
startDesensitization:'开始处理',
all:'全部',
onlyFace:'仅人脸',
onlyLicensePlate:'仅车牌',
dragThePictureHere:'拖动图片到这里',
or:'或',
clickUpload:'点击上传',
dataDesensitizationModelExperience:'数据脱敏模型体验',
dataDesensitizationModelDesc:'利用人工智能AI技术,把图片中的人脸、车牌号码进行脱敏处理。该模型更多信息请访问项目',
limitFilesUpload:'只能上传 jpg/jpeg/png 格式的文件',
limitSizeUpload:'上传文件大小不能超过 20M !',
}

export default zh;

+ 380
- 0
web_src/vuepages/pages/model/tuomin/index.vue View File

@@ -0,0 +1,380 @@
<template>
<div class="ui container">
<div class="tuomin-title">
<h2>{{ $t("dataDesensitizationModelExperience") }}</h2>
<p>
{{ $t("dataDesensitizationModelDesc") }} &nbsp;<a
href="https://git.openi.org.cn/tengxiao/tuomin"
target="_blank"
>tengxiao / tuomin</a
>
</p>
</div>
<el-row :gutter="12" style="margin-top: 33px">
<el-col :xs="24" :span="12">
<div class="tuomin-content-image">
<div class="tuomin-icon">
<i
class="ri-image-line"
style="font-size: 16px; margin-right: 2px"
></i>
<span style="font-size: 12px">img</span>
</div>
<div style="height: 230px; width: 96%; margin: 0 auto">
<el-upload
action="#"
accept=".jpg,.jpeg,.png,.JPG,.JPEG,.PNG"
:show-file-list="false"
:on-change="handleChangePicture"
list-type="picture-card"
:file-list="fileList"
:style="{ display: ImageUrl ? 'none' : 'block' }"
:auto-upload="false"
drag
>
<div class="el-upload__text">
{{ $t("dragThePictureHere")
}}<span style="color: rgba(136, 136, 136, 0.87)">{{
$t("or")
}}</span
>{{ $t("clickUpload") }}
</div>
</el-upload>

<img class="preview-image" v-if="ImageUrl" :src="ImageUrl" alt="" />
</div>
<div>
<div class="tuomin-radio-model">
<label class="radio-label"
>{{ $t("desensitizationObject") }}:</label
>
<div>
<el-radio-group v-model="radio">
<el-radio :label="2">{{ $t("all") }}</el-radio>
<el-radio :label="1">{{ $t("onlyFace") }}</el-radio>
<el-radio :label="0">{{ $t("onlyLicensePlate") }}</el-radio>
</el-radio-group>
</div>
</div>
<div class="tuomin-button-model">
<el-button @click="cancelUpload">{{ $t("cancel") }}</el-button>
<el-button
:disabled="fileList.length < 1"
@click="startTranform"
type="primary"
>{{ $t("startDesensitization") }}</el-button
>
</div>
</div>
</div>
</el-col>
<el-col :xs="24" :span="12">
<div class="tuomin-content-image" v-loading="tranformImageLoading">
<div class="tuomin-icon">
<i
class="ri-image-line"
style="font-size: 16px; margin-right: 2px"
></i>
<span style="font-size: 12px">output</span>
</div>
<div
v-if="resultImgSrc"
class="tuomin-icon-download"
@click="downImg"
>
<i
class="ri-download-2-line"
style="font-size: 16px; margin-right: 2px"
></i>
<span style="font-size: 14px">下载</span>
</div>
<div style="height: 358px">
<el-image
style="height: 100%; width: 100%"
:src="resultImgSrc"
:preview-src-list="[resultImgSrc]"
>
<div slot="error" class="image-slot">
<i style="font-size: 0" class="el-icon-picture-outline"></i>
</div>
</el-image>
</div>
</div>
</el-col>
</el-row>

<div style="margin: 39px 0 21px 0">
<span>{{ $t("example") }}:</span>
</div>

<div class="table-container">
<div>
<el-table border :data="tableData1" style="width: 100%">
<el-table-column :label="$t('originPicture')" align="center">
<template slot-scope="scope">
<div style="width: 100%; height: 200px">
<el-image
style="height: 100%; width: 100%"
:src="scope.row.imgSrc1"
:preview-src-list="[scope.row.imgSrc1]"
>
<div slot="error" class="image-slot">
<i style="font-size: 0" class="el-icon-picture-outline"></i>
</div>
</el-image>
</div>
</template>
</el-table-column>
<el-table-column :label="$t('desensitizationPicture')" align="center">
<template slot-scope="scope">
<div style="width: 100%; height: 200px">
<el-image
style="height: 100%; width: 100%"
:src="scope.row.imgSrc2"
:preview-src-list="[scope.row.imgSrc2]"
>
<div slot="error" class="image-slot">
<i style="font-size: 0" class="el-icon-picture-outline"></i>
</div>
</el-image>
</div>
</template>
</el-table-column>
<el-table-column
prop="mode"
:label="$t('desensitizationObject')"
align="center"
header-align="center"
>
</el-table-column>
</el-table>
</div>
</div>
</div>
</template>

<script>
import { postImgDesensitization } from "~/apis/modules/desensitization";
export default {
data() {
return {
ImageUrl: "",
radio: 2,
file: "",
fileList: [],
resultImgSrc: "",
tranformImageLoading: false,
tableData1: [
{
imgSrc1: "/img/origin.png",
imgSrc2: "/img/tuomin.png",
mode: this.$t("all"),
},
],
startFlag: false,
};
},
components: {},
methods: {
// 选择文件、移除文件、上传文件成功/失败后,都会触发
handleChangePicture(file, fileList) {
let acceptList = ["jpg", "jpeg", "png"];
// 根据文件名获取文件的后缀名
let fileType = file.name.split(".").pop().toLowerCase();
// 判断文件格式是否符合要求
if (acceptList.indexOf(fileType) === -1) {
this.$message.error(this.$t("limitFilesUpload"));
return false;
}
// 判断文件大小是否符合要求
if (file.size / 1024 / 1024 > 20) {
this.$message.error(this.$t("limitSizeUpload"));
return false;
}

this.ImageUrl = URL.createObjectURL(file.raw);
this.file = file;
this.fileList = fileList;
},
cancelUpload() {
this.ImageUrl = "";
this.file = "";
this.fileList = [];
},
downImg() {
const a = document.createElement("a");
a.download = "result.png";
a.style.display = "none";
a.href = this.resultImgSrc;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
},
startTranform() {
if (!this.startFlag) {
window.location.href = "/user/login";
return;
}
if (!this.file) return;
let fd = new FormData();
fd.append("file", this.file.raw);
this.tranformImageLoading = true;
postImgDesensitization({ mode: this.radio }, fd)
.then((res) => {
const objectURL = URL.createObjectURL(res.data);
this.resultImgSrc = objectURL;
this.tranformImageLoading = false;
})
.catch((err) => {
this.tranformImageLoading = false;
if (err.response.status === 400) {
const fr = new FileReader();
fr.onload = (e) => {
try {
const jsonResult = JSON.parse(e.target.result);
this.$message({
type: "error",
message: jsonResult.Message,
});
} catch (e) {
this.$message({
type: "error",
message: this.$t("tranformImageFailed"),
});
}
};
fr.readAsText(err.response.data);
} else {
this.$message({
type: "error",
message: this.$t("tranformImageFailed"),
});
}
});
},
},
mounted() {
const signEl = document.querySelector("#isSignd");
this.startFlag = !!signEl.getAttribute("data-sign");
},
beforeDestroy() {},
};
</script>

<style scoped lang="less">
.tuomin-title {
margin-top: 34px;
h2 {
display: flex;
justify-content: center;
}
p {
display: flex;
justify-content: center;
color: rgba(136, 136, 136, 0.87);
}
}
.tuomin-content-image {
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 5px;
min-height: 358px;
position: relative;
.tuomin-icon {
z-index: 99;
display: flex;
align-items: center;
position: absolute;
left: 0;
top: 0;
width: 66px;
height: 22px;
justify-content: center;
color: rgba(136, 136, 136, 0.87);
border-radius: 5px 0px 10px 0px;
border: 1px solid rgba(0, 0, 0, 0.1);
}
.tuomin-icon-download {
z-index: 99;
display: flex;
align-items: center;
position: absolute;
right: 10px;
bottom: 10px;
width: 66px;
height: 30px;
justify-content: center;
color: rgba(255, 255, 255, 1);
background-color: rgba(0, 0, 0, 0);
background: transparent;
border: 1px solid rgba(136, 136, 136, 0.5);
border-radius: 4px;
cursor: pointer;
}
.el-upload__text {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.preview-image {
height: 100%;
width: 100%;
}
.tuomin-radio-model {
display: flex;
margin: 25px 12px 0 12px;
.radio-label {
font-weight: 600;
margin-right: 4px;
color: rgba(16, 16, 16, 1);
}
}
.tuomin-button-model {
text-align: right;
margin: 22px 12px 0 12px;
}
}
/deep/ .el-upload--picture-card {
width: 100%;
background: #ffff;
border: none;
border-bottom: 1px dashed #888;
border-radius: 0;
min-height: 230px;
}
/deep/ .el-upload-dragger {
width: 100%;
background: #ffff;
border: none;
border-radius: 0;
height: 100%;
}
.table-container {
margin-bottom: 16px;

/deep/ .el-table__header {
th {
background: rgb(245, 245, 246);
font-size: 14px;
color: rgb(36, 36, 36);
font-weight: 400;
}
}

/deep/ .el-table__body {
td {
font-size: 14px;
}
}
}
.center {
display: flex;
justify-content: center;
}

@media screen and (max-width: 768px) {
body {
background-color: black;
}
}
</style>

+ 17
- 0
web_src/vuepages/pages/model/tuomin/vp-model-tuomin.js View File

@@ -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');

+ 8
- 8
web_src/vuepages/pages/resources/specification/index.vue View File

@@ -21,16 +21,16 @@
</div>
</div>
<div class="table-container">
<div style="min-height:600px;">
<el-table border :data="tableData" style="width: 100%;min-width:1700px;" v-loading="loading" stripe>
<el-table-column prop="ID" label="ID" align="center" header-align="center" width="60"></el-table-column>
<el-table-column prop="SpecStr" :label="$t('resourcesManagement.resourceSpecification')" align="left"
header-align="center" min-width="160">
<div style="min-height:600px;overflow-x:auto;">
<el-table border :data="tableData" style="width:100%;" v-loading="loading" stripe>
<el-table-column prop="ID" label="ID" align="center" header-align="center" width="60" fixed></el-table-column>
<el-table-column prop="SpecStr" :label="$t('resourcesManagement.resourceSpecification')" align="left" fixed
header-align="center" min-width="200">
</el-table-column>
<el-table-column prop="QueueInfo" :label="$t('resourcesManagement.resQueue')" align="center"
<el-table-column prop="QueueInfo" :label="$t('resourcesManagement.resQueue')" align="center" fixed
header-align="center" min-width="100">
</el-table-column>
<el-table-column prop="SourceSpecId" :label="$t('resourcesManagement.sourceSpecCode')" align="center"
<el-table-column prop="SourceSpecId" :label="$t('resourcesManagement.sourceSpecCode')" align="center" min-width="120"
header-align="center">
</el-table-column>
<el-table-column prop="AccCardsNum" :label="$t('resourcesManagement.accCardsNum')" align="center"
@@ -43,7 +43,7 @@
header-align="center"></el-table-column>
<el-table-column prop="ShareMemGiB" :label="`${$t('resourcesManagement.shareMem')}(GB)`" align="center"
header-align="center"></el-table-column>
<el-table-column prop="UpdatedTimeStr" :label="$t('resourcesManagement.lastUpdateTime')" align="center"
<el-table-column prop="UpdatedTimeStr" :label="$t('resourcesManagement.lastUpdateTime')" align="center" min-width="140"
header-align="center"></el-table-column>
<el-table-column prop="UnitPrice"
:label="`${$t('resourcesManagement.unitPrice')}(${$t('resourcesManagement.point_hr')})`" align="center"


+ 4
- 0
web_src/vuepages/pages/reward/point/utils.js View File

@@ -87,6 +87,10 @@ export const getRewardPointRecordInfo = (record) => {
if (record.SourceType === 'ADMIN_OPERATE') {
out.remark = record.Remark;
} else if (record.SourceType === 'ACCOMPLISH_TASK') {
if (record.Action?.Cloudbrain?.JobType === 'MODELSAFETY') {
record.Action.Cloudbrain.oJobType = 'MODELSAFETY';
record.Action.Cloudbrain.JobType = 'BENCHMARK';
}
switch (record?.Action?.TaskType) {
case 'CreatePublicRepo': // 创建公开项目 - 创建了项目OpenI/aiforge
out.remark = `${i18n.t('createdRepository')}<a href="${record.Action.RepoLink}" rel="nofollow">${record.Action.ShortRepoFullDisplayName}</a>`;


Loading…
Cancel
Save