| @@ -19,8 +19,8 @@ type JobType string | |||||
| type ModelArtsJobStatus string | type ModelArtsJobStatus string | ||||
| const ( | const ( | ||||
| NPUResource = "NPU" | |||||
| GPUResource = "CPU/GPU" | |||||
| NPUResource = "NPU" | |||||
| GPUResource = "CPU/GPU" | |||||
| JobWaiting CloudbrainStatus = "WAITING" | JobWaiting CloudbrainStatus = "WAITING" | ||||
| JobStopped CloudbrainStatus = "STOPPED" | JobStopped CloudbrainStatus = "STOPPED" | ||||
| @@ -210,7 +210,7 @@ type CloudbrainsOptions struct { | |||||
| JobType string | JobType string | ||||
| VersionName string | VersionName string | ||||
| IsLatestVersion string | IsLatestVersion string | ||||
| JobTypeNot bool | |||||
| JobTypeNot bool | |||||
| } | } | ||||
| type TaskPod struct { | type TaskPod struct { | ||||
| @@ -975,7 +975,9 @@ func QueryModelTrainJobList(repoId int64) ([]*CloudbrainInfo, int, error) { | |||||
| cond = cond.And( | cond = cond.And( | ||||
| builder.Eq{"Status": "COMPLETED"}, | builder.Eq{"Status": "COMPLETED"}, | ||||
| ) | ) | ||||
| cond = cond.And( | |||||
| builder.Eq{"job_type": "TRAIN"}, | |||||
| ) | |||||
| cloudbrains := make([]*CloudbrainInfo, 0) | cloudbrains := make([]*CloudbrainInfo, 0) | ||||
| if err := sess.Select("job_id,job_name").Table(&Cloudbrain{}).Where(cond).OrderBy("created_unix DESC"). | if err := sess.Select("job_id,job_name").Table(&Cloudbrain{}).Where(cond).OrderBy("created_unix DESC"). | ||||
| Find(&cloudbrains); err != nil { | Find(&cloudbrains); err != nil { | ||||
| @@ -844,6 +844,7 @@ modelarts.current_version=Current version | |||||
| modelarts.parent_version=Parent Version | modelarts.parent_version=Parent Version | ||||
| modelarts.run_version=Run Version | modelarts.run_version=Run Version | ||||
| modelarts.train_job.compute_node=Compute Node | modelarts.train_job.compute_node=Compute Node | ||||
| modelarts.create_model = Create Model | |||||
| modelarts.train_job.basic_info=Basic Info | modelarts.train_job.basic_info=Basic Info | ||||
| @@ -849,6 +849,7 @@ modelarts.modify=修改 | |||||
| modelarts.current_version=当前版本 | modelarts.current_version=当前版本 | ||||
| modelarts.parent_version=父版本 | modelarts.parent_version=父版本 | ||||
| modelarts.run_version=运行版本 | modelarts.run_version=运行版本 | ||||
| modelarts.create_model=创建模型 | |||||
| @@ -99,6 +99,18 @@ func saveModelByParameters(jobId string, versionName string, name string, versio | |||||
| //udpate status and version count | //udpate status and version count | ||||
| models.ModifyModelNewProperty(lastNewModelId, MODEL_NOT_LATEST, 0) | models.ModifyModelNewProperty(lastNewModelId, MODEL_NOT_LATEST, 0) | ||||
| } | } | ||||
| var units []models.RepoUnit | |||||
| var deleteUnitTypes []models.UnitType | |||||
| units = append(units, models.RepoUnit{ | |||||
| RepoID: ctx.Repo.Repository.ID, | |||||
| Type: models.UnitTypeModelManage, | |||||
| Config: &models.ModelManageConfig{ | |||||
| EnableModelManage: true, | |||||
| }, | |||||
| }) | |||||
| deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeModelManage) | |||||
| models.UpdateRepositoryUnits(ctx.Repo.Repository, units, deleteUnitTypes) | |||||
| log.Info("save model end.") | log.Info("save model end.") | ||||
| @@ -130,10 +142,13 @@ func SaveModel(ctx *context.Context) { | |||||
| version := ctx.Query("Version") | version := ctx.Query("Version") | ||||
| label := ctx.Query("Label") | label := ctx.Query("Label") | ||||
| description := ctx.Query("Description") | description := ctx.Query("Description") | ||||
| trainTaskCreate := ctx.QueryBool("trainTaskCreate") | |||||
| if !ctx.Repo.CanWrite(models.UnitTypeModelManage) { | |||||
| ctx.ServerError("No right.", errors.New(ctx.Tr("repo.model_noright"))) | |||||
| return | |||||
| if !trainTaskCreate { | |||||
| if !ctx.Repo.CanWrite(models.UnitTypeModelManage) { | |||||
| ctx.ServerError("No right.", errors.New(ctx.Tr("repo.model_noright"))) | |||||
| return | |||||
| } | |||||
| } | } | ||||
| if JobId == "" || VersionName == "" { | if JobId == "" || VersionName == "" { | ||||
| @@ -474,6 +489,23 @@ func ShowOneVersionOtherModel(ctx *context.Context) { | |||||
| func ShowModelTemplate(ctx *context.Context) { | func ShowModelTemplate(ctx *context.Context) { | ||||
| ctx.Data["isModelManage"] = true | ctx.Data["isModelManage"] = true | ||||
| repoId := ctx.Repo.Repository.ID | |||||
| Type := -1 | |||||
| _, count, _ := models.QueryModel(&models.AiModelQueryOptions{ | |||||
| ListOptions: models.ListOptions{ | |||||
| Page: 1, | |||||
| PageSize: 2, | |||||
| }, | |||||
| RepoID: repoId, | |||||
| Type: Type, | |||||
| New: MODEL_LATEST, | |||||
| }) | |||||
| ctx.Data["MODEL_COUNT"] = count | |||||
| _, trainCount, _ := models.QueryModelTrainJobList(repoId) | |||||
| log.Info("query train count=" + fmt.Sprint(trainCount)) | |||||
| ctx.Data["TRAIN_COUNT"] = trainCount | |||||
| ctx.HTML(200, tplModelManageIndex) | ctx.HTML(200, tplModelManageIndex) | ||||
| } | } | ||||
| @@ -586,3 +618,67 @@ func ModifyModelInfo(ctx *context.Context) { | |||||
| } | } | ||||
| } | } | ||||
| func QueryModelListForPredict(ctx *context.Context) { | |||||
| repoId := ctx.Repo.Repository.ID | |||||
| modelResult, count, err := models.QueryModel(&models.AiModelQueryOptions{ | |||||
| ListOptions: models.ListOptions{ | |||||
| Page: -1, | |||||
| PageSize: -1, | |||||
| }, | |||||
| RepoID: repoId, | |||||
| Type: -1, | |||||
| New: -1, | |||||
| }) | |||||
| if err != nil { | |||||
| ctx.ServerError("Cloudbrain", err) | |||||
| return | |||||
| } | |||||
| log.Info("query return count=" + fmt.Sprint(count)) | |||||
| nameList := make([]string, 0) | |||||
| nameMap := make(map[string][]*models.AiModelManage) | |||||
| for _, model := range modelResult { | |||||
| if _, value := nameMap[model.Name]; !value { | |||||
| models := make([]*models.AiModelManage, 0) | |||||
| models = append(models, model) | |||||
| nameMap[model.Name] = models | |||||
| nameList = append(nameList, model.Name) | |||||
| } else { | |||||
| nameMap[model.Name] = append(nameMap[model.Name], model) | |||||
| } | |||||
| } | |||||
| mapInterface := make(map[string]interface{}) | |||||
| mapInterface["nameList"] = nameList | |||||
| mapInterface["nameMap"] = nameMap | |||||
| ctx.JSON(http.StatusOK, mapInterface) | |||||
| } | |||||
| func QueryModelFileForPredict(ctx *context.Context) { | |||||
| id := ctx.Query("ID") | |||||
| model, err := models.QueryModelById(id) | |||||
| if err != nil { | |||||
| log.Error("no such model!", err.Error()) | |||||
| ctx.ServerError("no such model:", err) | |||||
| return | |||||
| } | |||||
| prefix := model.Path[len(setting.Bucket)+1:] | |||||
| fileinfos, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, prefix) | |||||
| ctx.JSON(http.StatusOK, fileinfos) | |||||
| } | |||||
| func QueryOneLevelModelFile(ctx *context.Context) { | |||||
| id := ctx.Query("ID") | |||||
| parentDir := ctx.Query("parentDir") | |||||
| model, err := models.QueryModelById(id) | |||||
| if err != nil { | |||||
| log.Error("no such model!", err.Error()) | |||||
| ctx.ServerError("no such model:", err) | |||||
| return | |||||
| } | |||||
| prefix := model.Path[len(setting.Bucket)+1:] | |||||
| fileinfos, err := storage.GetOneLevelAllObjectUnderDir(setting.Bucket, prefix, parentDir) | |||||
| ctx.JSON(http.StatusOK, fileinfos) | |||||
| } | |||||
| @@ -982,7 +982,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| }, context.RepoRef()) | }, context.RepoRef()) | ||||
| m.Group("/modelmanage", func() { | m.Group("/modelmanage", func() { | ||||
| m.Post("/create_model", reqRepoModelManageWriter, repo.SaveModel) | m.Post("/create_model", reqRepoModelManageWriter, repo.SaveModel) | ||||
| m.Post("/create_new_model", reqRepoModelManageWriter, repo.SaveNewNameModel) | |||||
| m.Post("/create_new_model", repo.SaveNewNameModel) | |||||
| m.Delete("/delete_model", repo.DeleteModel) | m.Delete("/delete_model", repo.DeleteModel) | ||||
| m.Put("/modify_model", repo.ModifyModelInfo) | m.Put("/modify_model", repo.ModifyModelInfo) | ||||
| m.Get("/show_model", reqRepoModelManageReader, repo.ShowModelTemplate) | m.Get("/show_model", reqRepoModelManageReader, repo.ShowModelTemplate) | ||||
| @@ -992,6 +992,9 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| m.Get("/show_model_child_api", repo.ShowOneVersionOtherModel) | m.Get("/show_model_child_api", repo.ShowOneVersionOtherModel) | ||||
| m.Get("/query_train_job", reqRepoCloudBrainReader, repo.QueryTrainJobList) | m.Get("/query_train_job", reqRepoCloudBrainReader, repo.QueryTrainJobList) | ||||
| m.Get("/query_train_job_version", reqRepoCloudBrainReader, repo.QueryTrainJobVersionList) | m.Get("/query_train_job_version", reqRepoCloudBrainReader, repo.QueryTrainJobVersionList) | ||||
| m.Get("/query_model_for_predict", reqRepoCloudBrainReader, repo.QueryModelListForPredict) | |||||
| m.Get("/query_modelfile_for_predict", reqRepoCloudBrainReader, repo.QueryModelFileForPredict) | |||||
| m.Get("/query_onelevel_modelfile", reqRepoCloudBrainReader, repo.QueryOneLevelModelFile) | |||||
| m.Group("/:ID", func() { | m.Group("/:ID", func() { | ||||
| m.Get("", repo.ShowSingleModel) | m.Get("", repo.ShowSingleModel) | ||||
| m.Get("/downloadsingle", repo.DownloadSingleModelFile) | m.Get("/downloadsingle", repo.DownloadSingleModelFile) | ||||
| @@ -331,7 +331,7 @@ | |||||
| </a> | </a> | ||||
| {{end}} | {{end}} | ||||
| {{else}} | {{else}} | ||||
| {{if eq .Status "RUNNING"}} | |||||
| {{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}} | |||||
| <a class="ui basic disabled button"> | <a class="ui basic disabled button"> | ||||
| {{$.i18n.Tr "repo.debug"}} | {{$.i18n.Tr "repo.debug"}} | ||||
| </a> | </a> | ||||
| @@ -161,6 +161,15 @@ td, th { | |||||
| padding-top: 0.5rem ; | padding-top: 0.5rem ; | ||||
| } | } | ||||
| </style> | </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"> | <div class="repository"> | ||||
| {{template "repo/header" .}} | {{template "repo/header" .}} | ||||
| <div class="ui container"> | <div class="ui container"> | ||||
| @@ -186,6 +195,12 @@ td, th { | |||||
| <span class="accordion-panel-title-content"> | <span class="accordion-panel-title-content"> | ||||
| <span> | <span> | ||||
| <div style="float: right;"> | <div style="float: right;"> | ||||
| {{$.CsrfTokenHtml}} | |||||
| {{if .CanModify}} | |||||
| <a class="ti-action-menu-item" onclick="showcreate({{.}})">{{$.i18n.Tr "repo.modelarts.create_model"}}</a> | |||||
| {{else}} | |||||
| <a class="ti-action-menu-item disabled">{{$.i18n.Tr "repo.modelarts.create_model"}}</a> | |||||
| {{end}} | |||||
| {{$.CsrfTokenHtml}} | {{$.CsrfTokenHtml}} | ||||
| {{if .CanModify}} | {{if .CanModify}} | ||||
| <a class="ti-action-menu-item" href="{{$.RepoLink}}/modelarts/train-job/{{.JobID}}/create_version?version_name={{.VersionName}}">{{$.i18n.Tr "repo.modelarts.modify"}}</a> | <a class="ti-action-menu-item" href="{{$.RepoLink}}/modelarts/train-job/{{.JobID}}/create_version?version_name={{.VersionName}}">{{$.i18n.Tr "repo.modelarts.modify"}}</a> | ||||
| @@ -446,6 +461,62 @@ td, th { | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <!-- 创建模型 --> | |||||
| <div id="newmodel"> | |||||
| <div class="ui modal second"> | |||||
| <div class="header" style="padding: 1rem;background-color: rgba(240, 240, 240, 100);"> | |||||
| <h4 id="model_header">导入新模型</h4> | |||||
| </div> | |||||
| <div class="content content-padding"> | |||||
| <form id="formId" method="POST" class="ui form"> | |||||
| <div class="ui error message"> | |||||
| </div> | |||||
| {{$.CsrfTokenHtml}} | |||||
| <input type="hidden" name="trainTaskCreate" value="true"> | |||||
| <div class="two inline fields "> | |||||
| <div class="required ten wide field"> | |||||
| <label style="margin-left: -23px;">选择训练任务</label> | |||||
| <input type="hidden" class="width83" id="JobId" name="JobId" readonly required> | |||||
| <input class="width83" id="JobName" readonly required> | |||||
| </div> | |||||
| <div class="required six widde field"> | |||||
| <label>版本</label> | |||||
| <input class="width70" id="VersionName" name="VersionName" readonly required> | |||||
| </div> | |||||
| </div> | |||||
| <div class="required inline field" id="modelname"> | |||||
| <label>模型名称</label> | |||||
| <input style="width: 45%;" id="name" name="Name" required maxlength="25" onkeyup="this.value=this.value.replace(/[, ]/g,'')"> | |||||
| </div> | |||||
| <div class="required inline field" id="verionname"> | |||||
| <label>模型版本</label> | |||||
| <input style="width: 45%;" id="version" name="Version" value="" readonly required maxlength="255"> | |||||
| </div> | |||||
| <div class="inline field"> | |||||
| <label>模型标签</label> | |||||
| <input style="width: 83%;margin-left: 7px;" id="label" name="Label" maxlength="255" placeholder='{{.i18n.Tr "repo.modelarts.train_job.label_place"}}'> | |||||
| </div> | |||||
| <div class="inline field"> | |||||
| <label for="description">模型描述</label> | |||||
| <textarea style="width: 83%;margin-left: 7px;" id="Description" name="Description" rows="3" maxlength="255" 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, 256)"></textarea> | |||||
| </div> | |||||
| <div class="inline field" style="margin-left: 75px;"> | |||||
| <button onclick="createModel()" id="submitId" type="button" class="ui create_train_job green button" style="position: absolute;"> | |||||
| {{.i18n.Tr "repo.model.manage.sava_model"}} | |||||
| </button> | |||||
| </div> | |||||
| </form> | |||||
| <div class="actions" style="display: inline-block;margin-left: 180px;"> | |||||
| <button class="ui button cancel" >{{.i18n.Tr "repo.cloudbrain.cancel"}}</button> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | </div> | ||||
| {{template "base/footer" .}} | {{template "base/footer" .}} | ||||
| @@ -479,7 +550,61 @@ td, th { | |||||
| } | } | ||||
| let timeid = window.setInterval(loadJobStatus, 30000); | let timeid = window.setInterval(loadJobStatus, 30000); | ||||
| $(document).ready(loadJobStatus); | $(document).ready(loadJobStatus); | ||||
| function showcreate(obj){ | |||||
| $('.ui.modal.second') | |||||
| .modal({ | |||||
| centered: false, | |||||
| onShow:function(){ | |||||
| $('input[name="Version"]').addClass('model_disabled') | |||||
| // $('input[name="JobId"]').text(obj.JobName) | |||||
| $('#JobName').val(obj.JobName).addClass('model_disabled') | |||||
| $('input[name="JobId"]').val(obj.JobID) | |||||
| $('input[name="VersionName"]').val(obj.VersionName).addClass('model_disabled') | |||||
| $('.ui.dimmer').css({"background-color":"rgb(136, 136, 136,0.7)"}) | |||||
| createModelName() | |||||
| }, | |||||
| onHide:function(){ | |||||
| document.getElementById("formId").reset(); | |||||
| $('.ui.dimmer').css({"background-color":""}) | |||||
| $('.ui.error.message').text() | |||||
| $('.ui.error.message').css('display','none') | |||||
| } | |||||
| }) | |||||
| .modal('show') | |||||
| } | |||||
| function createModel(){ | |||||
| let url_href = `/${userName}/${repoPath}/modelmanage/create_new_model` | |||||
| let data = $("#formId").serialize() | |||||
| $("#mask").css({"display":"block","z-index":"9999"}) | |||||
| $.ajax({ | |||||
| url:url_href, | |||||
| type:'POST', | |||||
| data:data, | |||||
| success:function(res){ | |||||
| location.href=`/${userName}/${repoPath}/modelmanage/show_model` | |||||
| $('.ui.modal.second').modal('hide') | |||||
| }, | |||||
| error: function(xhr){ | |||||
| // 隐藏 loading | |||||
| // 只有请求不正常(状态码不为200)才会执行 | |||||
| $('.ui.error.message').text(xhr.responseText) | |||||
| $('.ui.error.message').css('display','block') | |||||
| }, | |||||
| complete:function(xhr){ | |||||
| $("#mask").css({"display":"none","z-index":"1"}) | |||||
| } | |||||
| }) | |||||
| } | |||||
| function createModelName(){ | |||||
| let repoName = location.pathname.split('/')[2] | |||||
| let modelName = repoName + '_model_' + Math.random().toString(36).substr(2, 4) | |||||
| $('#name').val(modelName) | |||||
| $('#version').val("0.0.1") | |||||
| } | |||||
| function renderSize(value){ | function renderSize(value){ | ||||
| if(null==value||value==''){ | if(null==value||value==''){ | ||||
| return "0 Bytes"; | return "0 Bytes"; | ||||
| @@ -17,16 +17,30 @@ | |||||
| <div class="repository release dataset-list view"> | <div class="repository release dataset-list view"> | ||||
| {{template "repo/header" .}} | {{template "repo/header" .}} | ||||
| <!-- 列表容器 --> | <!-- 列表容器 --> | ||||
| <div class="ui container active loader" id="loadContainer"> | |||||
| <div class="ui container {{if ne $.MODEL_COUNT 0}}active loader {{end}}" id="loadContainer"> | |||||
| {{template "base/alert" .}} | {{template "base/alert" .}} | ||||
| <div class="ui two column stackable grid" style="display: none;"> | |||||
| <div class="ui two column stackable grid"> | |||||
| <div class="column"></div> | <div class="column"></div> | ||||
| <div class="column right aligned"> | <div class="column right aligned"> | ||||
| <!-- --> | <!-- --> | ||||
| <a class="ui button {{if .Permission.CanWrite $.UnitTypeCloudBrain}} green {{else}} disabled {{end}}" onclick="showcreate(this)">{{$.i18n.Tr "repo.model.manage.import_new_model"}}</a> | <a class="ui button {{if .Permission.CanWrite $.UnitTypeCloudBrain}} green {{else}} disabled {{end}}" onclick="showcreate(this)">{{$.i18n.Tr "repo.model.manage.import_new_model"}}</a> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| {{if eq $.MODEL_COUNT 0}} | |||||
| <div class="ui placeholder segment bgtask-none"> | |||||
| <div class="ui icon header bgtask-header-pic"></div> | |||||
| <div class="bgtask-content-header">未创建过模型</div> | |||||
| <div class="bgtask-content"> | |||||
| {{if $.RepoIsEmpty}} | |||||
| <div class="bgtask-content-txt">代码版本:您还没有初始化代码仓库,请先<a href="{{.RepoLink}}">创建代码版本;</a></div> | |||||
| {{end}} | |||||
| {{if eq $.TRAIN_COUNT 0}} | |||||
| <div class="bgtask-content-txt">训练任务:你还没创建过训练任务,请先创建训练任务。</div> | |||||
| {{end}} | |||||
| <div class="bgtask-content-txt">使用说明:可以参考启智AI协作平台<a href="https://git.openi.org.cn/zeizei/OpenI_Learning">小白训练营课程。</a></div> | |||||
| </div> | |||||
| </div> | |||||
| {{else}} | |||||
| <!-- 中下列表展示区 --> | <!-- 中下列表展示区 --> | ||||
| <div class="ui grid" style="display: none;"> | <div class="ui grid" style="display: none;"> | ||||
| <div class="row" style="padding-top: 0;"> | <div class="row" style="padding-top: 0;"> | ||||
| @@ -38,6 +52,7 @@ | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| {{end}} | |||||
| </div> | </div> | ||||
| @@ -89,7 +104,6 @@ | |||||
| <div class="menu" id="job-name"> | <div class="menu" id="job-name"> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="required six widde field"> | <div class="required six widde field"> | ||||
| <label>版本</label> | <label>版本</label> | ||||
| @@ -103,7 +117,6 @@ | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="required inline field" id="modelname"> | <div class="required inline field" id="modelname"> | ||||
| <label>模型名称</label> | <label>模型名称</label> | ||||
| <input style="width: 45%;" id="name" name="Name" required maxlength="25" onkeyup="this.value=this.value.replace(/[, ]/g,'')"> | <input style="width: 45%;" id="name" name="Name" required maxlength="25" onkeyup="this.value=this.value.replace(/[, ]/g,'')"> | ||||
| @@ -78,100 +78,121 @@ | |||||
| </select> | </select> | ||||
| </h4> | </h4> | ||||
| <div id="showInfo" style="border:1px solid #e2e2e2;padding: 20px 60px;margin-top:24px"> | <div id="showInfo" style="border:1px solid #e2e2e2;padding: 20px 60px;margin-top:24px"> | ||||
| <div class="half-table"> | |||||
| <span class="model_header_text">基本信息</span> | |||||
| <table class="tableStyle" style="margin-top:20px;"> | |||||
| <tbody> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.model_name"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="ModelName" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.version"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="Version" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.migrate_items_labels"}}</td> | |||||
| <td class="ti-text-form-content"> | |||||
| <div id="Label" style="overflow: hidden;width: 95%;"> | |||||
| <div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);"> | |||||
| <a class="active item" data-tab="first">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | |||||
| <a class="item" data-tab="second">{{$.i18n.Tr "repo.model_download"}}</a> | |||||
| </div> | |||||
| <div class="ui tab active" data-tab="first"> | |||||
| <div class="half-table"> | |||||
| <span class="model_header_text">基本信息</span> | |||||
| <table class="tableStyle" style="margin-top:20px;"> | |||||
| <tbody> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.model_name"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="ModelName" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.version"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="Version" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.migrate_items_labels"}}</td> | |||||
| <td class="ti-text-form-content"> | |||||
| <div id="Label" style="overflow: hidden;width: 95%;"> | |||||
| </div> | |||||
| </div> | |||||
| </td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.model_size"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="Size" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.createtime"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="CreateTime" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.description"}}</td> | |||||
| <td class="ti-text-form-content" > | |||||
| <div id="edit-td" style="display:flex"> | |||||
| <span id="Description" title="" class="iword-elipsis"></span> | |||||
| <i id="edit-pencil" data-id="" data-desc="" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></i> | |||||
| </div> | |||||
| </td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.code_version"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="CodeBranch" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.start_file"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="BootFile" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.train_dataset"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="DatasetName" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="Parameters" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.AI_driver"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="EngineName" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.standard"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="FlavorName" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.compute_node"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="WorkServerNumber" title=""></span></td> | |||||
| </tr> | |||||
| </tbody> | |||||
| </table> | |||||
| </td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.model_size"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="Size" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.createtime"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="CreateTime" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.description"}}</td> | |||||
| <td class="ti-text-form-content" > | |||||
| <div id="edit-td" style="display:flex"> | |||||
| <span id="Description" title="" class="iword-elipsis"></span> | |||||
| <i id="edit-pencil" data-id="" data-desc="" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></i> | |||||
| </div> | |||||
| </td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.code_version"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="CodeBranch" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.start_file"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="BootFile" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.train_dataset"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="DatasetName" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="Parameters" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.AI_driver"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="EngineName" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.standard"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="FlavorName" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.compute_node"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="WorkServerNumber" title=""></span></td> | |||||
| </tr> | |||||
| </tbody> | |||||
| </table> | |||||
| </div> | |||||
| <div class="half-table"> | |||||
| <span class="model_header_text">{{$.i18n.Tr "repo.model.manage.model_accuracy"}}</span> | |||||
| <table class="tableStyle" style="margin-top:20px;"> | |||||
| <tbody> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.Accuracy"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="Accuracy" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">F1</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="F1" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.Precision"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="Precision" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.Recall"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="Recall" title=""></span></td> | |||||
| </tr> | |||||
| </tbody> | |||||
| </table> | |||||
| </div> | |||||
| <div style="clear: both;"></div> | |||||
| </div> | </div> | ||||
| <div class="half-table"> | |||||
| <span class="model_header_text">{{$.i18n.Tr "repo.model.manage.model_accuracy"}}</span> | |||||
| <table class="tableStyle" style="margin-top:20px;"> | |||||
| <tbody> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.Accuracy"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="Accuracy" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">F1</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="F1" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.Precision"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="Precision" title=""></span></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.Recall"}}</td> | |||||
| <td class="ti-text-form-content word-elipsis"><span id="Recall" title=""></span></td> | |||||
| </tr> | |||||
| </tbody> | |||||
| </table> | |||||
| <div class="ui tab" data-tab="second"> | |||||
| <input type="hidden" name="model" value="-1"> | |||||
| <input type="hidden" name="modelback" value="-1"> | |||||
| <div class='ui breadcrumb model_file_bread' id='file_breadcrumb'> | |||||
| <div class="active section"></div> | |||||
| <div class="divider"> / </div> | |||||
| </div> | |||||
| <div id="dir_list"> | |||||
| </div> | |||||
| </div> | </div> | ||||
| <div style="clear: both;"></div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -179,6 +200,9 @@ | |||||
| <script> | <script> | ||||
| let url = location.href.split('show_model')[0] | let url = location.href.split('show_model')[0] | ||||
| let ID = location.search.split('?name=').pop() | let ID = location.search.split('?name=').pop() | ||||
| $(document).ready(function(){ | |||||
| $('.secondary.menu .item').tab(); | |||||
| }); | |||||
| $(document).ready(loadInfo); | $(document).ready(loadInfo); | ||||
| function changeInfo(version){ | function changeInfo(version){ | ||||
| $.get(`${url}show_model_info_api?name=${ID}`,(data)=>{ | $.get(`${url}show_model_info_api?name=${ID}`,(data)=>{ | ||||
| @@ -190,6 +214,7 @@ function changeInfo(version){ | |||||
| let [initObj,initModelAcc,id] = returnArray | let [initObj,initModelAcc,id] = returnArray | ||||
| editorCancel('','') | editorCancel('','') | ||||
| renderInfo(initObj,initModelAcc,id) | renderInfo(initObj,initModelAcc,id) | ||||
| loadModelFile(versionData[0].ID,versionData[0].Version,'','','init') | |||||
| }) | }) | ||||
| } | } | ||||
| function loadInfo(){ | function loadInfo(){ | ||||
| @@ -206,6 +231,7 @@ function loadInfo(){ | |||||
| returnArray = transObj(data) | returnArray = transObj(data) | ||||
| let [initObj,initModelAcc,id] = returnArray | let [initObj,initModelAcc,id] = returnArray | ||||
| renderInfo(initObj,initModelAcc,id) | renderInfo(initObj,initModelAcc,id) | ||||
| loadModelFile(data[0].ID,data[0].Version,'','','init') | |||||
| }) | }) | ||||
| } | } | ||||
| function transObj(data){ | function transObj(data){ | ||||
| @@ -297,7 +323,6 @@ function renderInfo(obj,accObj,id){ | |||||
| let descriptionText=obj[key].replace(/\r\n|\n/g,'enter;') | let descriptionText=obj[key].replace(/\r\n|\n/g,'enter;') | ||||
| $(`#${key}`).text(obj[key]) | $(`#${key}`).text(obj[key]) | ||||
| $(`#${key}`).attr("title",obj[key]) | $(`#${key}`).attr("title",obj[key]) | ||||
| $('#edit-pencil').attr("data-id",id) | $('#edit-pencil').attr("data-id",id) | ||||
| $('#edit-pencil').attr("data-desc",descriptionText) | $('#edit-pencil').attr("data-desc",descriptionText) | ||||
| } | } | ||||
| @@ -333,8 +358,6 @@ function renderInfo(obj,accObj,id){ | |||||
| $(`#${key}`).text(parameter) | $(`#${key}`).text(parameter) | ||||
| $(`#${key}`).attr("title",parameter) | $(`#${key}`).attr("title",parameter) | ||||
| } | } | ||||
| } | } | ||||
| else{ | else{ | ||||
| $(`#${key}`).text(obj[key]) | $(`#${key}`).text(obj[key]) | ||||
| @@ -348,4 +371,108 @@ function renderInfo(obj,accObj,id){ | |||||
| } | } | ||||
| } | } | ||||
| function loadModelFile(ID,version_name,parents,filename,init){ | |||||
| $.get(`${url}query_onelevel_modelfile?ID=${ID}&parentDir=${parents}`, (data) => { | |||||
| $('#dir_list').empty() | |||||
| renderDir(data,ID,version_name) | |||||
| if(init==="init"){ | |||||
| $('input[name=model]').val("") | |||||
| $('input[name=modelback]').val(version_name) | |||||
| $('#file_breadcrumb').empty() | |||||
| let htmlBread = "" | |||||
| htmlBread += `<div class='active section'>${version_name}</div>` | |||||
| htmlBread += "<div class='divider'> / </div>" | |||||
| $('#file_breadcrumb').append(htmlBread) | |||||
| }else{ | |||||
| renderBrend(ID,version_name,parents,filename,init) | |||||
| } | |||||
| }) | |||||
| } | |||||
| function renderSize(value){ | |||||
| if(null==value||value==''){ | |||||
| return "0 Bytes"; | |||||
| } | |||||
| var unitArr = new Array("Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"); | |||||
| var index=0; | |||||
| var srcsize = parseFloat(value); | |||||
| index=Math.floor(Math.log(srcsize)/Math.log(1024)); | |||||
| var size =srcsize/Math.pow(1024,index); | |||||
| size=size.toFixed(2);//保留的小数位数 | |||||
| return size+unitArr[index]; | |||||
| } | |||||
| function renderBrend(ID,version_name,parents,filename,init){ | |||||
| if(init=="folder"){ | |||||
| let htmlBrend = "" | |||||
| let sectionName=$('#file_breadcrumb .active.section').text() | |||||
| let parents1 = $('input[name=model]').val() | |||||
| let filename1 = $('input[name=modelback]').val() | |||||
| if(parents1===""){ | |||||
| $('#file_breadcrumb .active.section').replaceWith(`<a class='section' onclick="loadModelFile('${ID}','${version_name}','${parents1}','','init')">${sectionName}</a>`) | |||||
| }else{ | |||||
| $('#file_breadcrumb .active.section').replaceWith(`<a class='section' onclick="loadModelFile('${ID}','${version_name}','${parents1}','${filename1}')">${sectionName}</a>`) | |||||
| } | |||||
| htmlBrend += `<div class='active section'>${filename}</div>` | |||||
| htmlBrend += "<div class='divider'> / </div>" | |||||
| $('#file_breadcrumb').append(htmlBrend) | |||||
| $('input[name=model]').val(parents) | |||||
| $('input[name=modelback]').val(filename) | |||||
| }else{ | |||||
| $('input[name=model]').val(parents) | |||||
| $('input[name=modelbac]').val(filename) | |||||
| $('#file_breadcrumb a.section:contains(${filename})').nextAll().remove() | |||||
| $('#file_breadcrumb a.section:contains(${filename})').replaceWith(`<div class='active section'>${filename}</div>`) | |||||
| $('#file_breadcrumb div.section:contains(${filename})').append("<div class='divider'> / </div>") | |||||
| } | |||||
| } | |||||
| function renderDir(data,ID,version_name){ | |||||
| let html="" | |||||
| html += "<div class='ui grid' style='margin:0;'>" | |||||
| html += "<div class='row' style='padding: 0;'>" | |||||
| html += "<div class='ui sixteen wide column' style='padding:1rem;'>" | |||||
| html += "<div class='dir list'>" | |||||
| html += "<table id='repo-files-table' class='ui single line table pad20'>" | |||||
| html += '<tbody>' | |||||
| for(let i=0;i<data.length;i++){ | |||||
| let dirs_size = renderSize(data[i].Size) | |||||
| html += "<tr>" | |||||
| html += "<td class='name six wid'>" | |||||
| html += "<span class='truncate'>" | |||||
| html += "<span class='octicon octicon-file-directory'>" | |||||
| html += "</span>" | |||||
| if(data[i].IsDir){ | |||||
| html += `<a onclick="loadModelFile('${ID}','${version_name}','${data[i].ParenDir}','${data[i].FileName}','folder')">` | |||||
| html += "<span class='fitted'><i class='folder icon' width='16' height='16' aria-hidden='true'></i>" + data[i].FileName + "</span>" | |||||
| }else{ | |||||
| html += `<a href="${url}${ID}/downloadsingle?parentDir=${data[i].ParenDir}&fileName=${data[i].FileName}">` | |||||
| html += "<span class='fitted'><i class='file icon' width='16' height='16' aria-hidden='true'></i>" + data[i].FileName + "</span>" | |||||
| } | |||||
| html += '</a>' | |||||
| html += "</span>" | |||||
| html += "</td>" | |||||
| html += "<td class='message seven wide'>" | |||||
| if(data[i].IsDir){ | |||||
| html += "<span class='truncate has-emoji'></span>" | |||||
| }else{ | |||||
| html += "<span class='truncate has-emoji'>"+ `${dirs_size}` + "</span>" | |||||
| } | |||||
| html += "</td>" | |||||
| html += "<td class='text right age three wide'>" | |||||
| html += "<span class='truncate has-emoji'>" + data[i].ModTime + "</span>" | |||||
| html += "</td>" | |||||
| html += "</tr>" | |||||
| } | |||||
| html += "</tbody>" | |||||
| html += "</table>" | |||||
| html += "</div>" | |||||
| html += "</div>" | |||||
| html += "</div>" | |||||
| html += "</div>" | |||||
| $('#dir_list').append(html) | |||||
| } | |||||
| </script> | </script> | ||||