Browse Source

增加模型转换任务界面。

Signed-off-by: zouap <zouap@pcl.ac.cn>
tags/v1.22.7.1
zouap 3 years ago
parent
commit
87375ce6cc
8 changed files with 421 additions and 10 deletions
  1. +107
    -3
      models/ai_model_manage.go
  2. +1
    -0
      models/models.go
  3. +3
    -0
      options/locale/locale_en-US.ini
  4. +3
    -0
      options/locale/locale_zh-CN.ini
  5. +15
    -6
      routers/repo/ai_model_manage.go
  6. +1
    -0
      routers/routes/routes.go
  7. +285
    -0
      templates/repo/modelmanage/convertIndex.tmpl
  8. +6
    -1
      templates/repo/modelmanage/index.tmpl

+ 107
- 3
models/ai_model_manage.go View File

@@ -39,6 +39,29 @@ type AiModelManage struct {
IsCanDelete bool
}

type AiModelManageConvert struct {
ID string `xorm:"pk"`
Name string `xorm:"INDEX NOT NULL"`
Status int `xorm:"NOT NULL DEFAULT 0"`
SrcEngine int `xorm:"NOT NULL DEFAULT 0"`
RepoId int64 `xorm:"INDEX NULL"`
ModelId string `xorm:"NOT NULL"`
ModelVersion string `xorm:"NOT NULL"`
DestFormat int `xorm:"NOT NULL DEFAULT 0"`
NetOutputFormat int `xorm:"NULL"`
UserId int64 `xorm:"NOT NULL"`
RunTime int64 `xorm:"NULL"`
InputShape string `xorm:"varchar(2000)"`
InputDataFormat string `xorm:"NOT NULL"`
Description string `xorm:"varchar(2000)"`
CreatedUnix timeutil.TimeStamp `xorm:"created"`
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
UserName string
UserRelAvatarLink string
IsCanOper bool
IsCanDelete bool
}

type AiModelQueryOptions struct {
ListOptions
RepoID int64 // include all repos if empty
@@ -47,7 +70,20 @@ type AiModelQueryOptions struct {
SortType string
New int
// JobStatus CloudbrainStatus
Type int
Type int
Status int
}

func SaveModelConvert(modelConvert *AiModelManageConvert) error {
sess := x.NewSession()
defer sess.Close()
re, err := sess.Insert(modelConvert)
if err != nil {
log.Info("insert modelConvert error." + err.Error())
return err
}
log.Info("success to save modelConvert db.re=" + fmt.Sprint((re)))
return nil
}

func SaveModelToDb(model *AiModelManage) error {
@@ -63,6 +99,20 @@ func SaveModelToDb(model *AiModelManage) error {
return nil
}

func QueryModelConvertById(id string) (*AiModelManageConvert, error) {
sess := x.NewSession()
defer sess.Close()
sess.Select("*").Table(new(AiModelManageConvert)).Where("id='" + id + "'")
aiModelManageConvertList := make([]*AiModelManageConvert, 0)
err := sess.Find(&aiModelManageConvertList)
if err == nil {
if len(aiModelManageConvertList) == 1 {
return aiModelManageConvertList[0], nil
}
}
return nil, err
}

func QueryModelById(id string) (*AiModelManage, error) {
sess := x.NewSession()
defer sess.Close()
@@ -78,10 +128,22 @@ func QueryModelById(id string) (*AiModelManage, error) {
return nil, err
}

func DeleteModelById(id string) error {
func DeleteModelConvertById(id string) error {
sess := x.NewSession()
defer sess.Close()
re, err := sess.Delete(&AiModelManageConvert{
ID: id,
})
if err != nil {
return err
}
log.Info("success to delete AiModelManageConvert from db.re=" + fmt.Sprint((re)))
return nil
}

func DeleteModelById(id string) error {
sess := x.NewSession()
defer sess.Close()
re, err := sess.Delete(&AiModelManage{
ID: id,
})
@@ -90,7 +152,6 @@ func DeleteModelById(id string) error {
}
log.Info("success to delete from db.re=" + fmt.Sprint((re)))
return nil

}

func ModifyModelDescription(id string, description string) error {
@@ -201,3 +262,46 @@ func QueryModel(opts *AiModelQueryOptions) ([]*AiModelManage, int64, error) {

return aiModelManages, count, nil
}

func QueryModelConvert(opts *AiModelQueryOptions) ([]*AiModelManageConvert, int64, error) {
sess := x.NewSession()
defer sess.Close()
var cond = builder.NewCond()
if opts.RepoID > 0 {
cond = cond.And(
builder.Eq{"ai_model_manage_convert.repo_id": opts.RepoID},
)
}
if opts.UserID > 0 {
cond = cond.And(
builder.Eq{"ai_model_manage_convert.user_id": opts.UserID},
)
}
if (opts.Status) >= 0 {
cond = cond.And(
builder.Eq{"ai_model_manage_convert.status": opts.Status},
)
}
count, err := sess.Where(cond).Count(new(AiModelManageConvert))
if err != nil {
return nil, 0, fmt.Errorf("Count: %v", err)
}

if opts.Page >= 0 && opts.PageSize > 0 {
var start int
if opts.Page == 0 {
start = 0
} else {
start = (opts.Page - 1) * opts.PageSize
}
sess.Limit(opts.PageSize, start)
}
sess.OrderBy("ai_model_manage_convert.created_unix DESC")
aiModelManageConvert := make([]*AiModelManageConvert, 0, setting.UI.IssuePagingNum)
if err := sess.Table(new(AiModelManageConvert)).Where(cond).
Find(&aiModelManageConvert); err != nil {
return nil, 0, fmt.Errorf("Find: %v", err)
}

return aiModelManageConvert, count, nil
}

+ 1
- 0
models/models.go View File

@@ -144,6 +144,7 @@ func init() {
new(WechatBindLog),
new(OrgStatistic),
new(SearchRecord),
new(AiModelManageConvert),
)

tablesStatistic = append(tablesStatistic,


+ 3
- 0
options/locale/locale_en-US.ini View File

@@ -1145,6 +1145,9 @@ model.manage.Recall = Recall
model.manage.sava_model = Sava Model
model.manage.model_manage = ModelManage
model.manage.model_accuracy = Model Accuracy
model.convert=Model Transformation
model.list=Model List
model.manage.create_new_convert_task=Create Model Transformation Task

template.items = Template Items
template.git_content = Git Content (Default Branch)


+ 3
- 0
options/locale/locale_zh-CN.ini View File

@@ -1156,6 +1156,9 @@ model.manage.Recall = 召回率
model.manage.sava_model = 保存模型
model.manage.model_manage = 模型管理
model.manage.model_accuracy = 模型精度
model.convert=模型转换任务
model.list=模型列表
model.manage.create_new_convert_task=创建模型转换任务

template.items=模板选项
template.git_content=Git数据(默认分支)


+ 15
- 6
routers/repo/ai_model_manage.go View File

@@ -20,12 +20,13 @@ import (
)

const (
Model_prefix = "aimodels/"
tplModelManageIndex = "repo/modelmanage/index"
tplModelManageDownload = "repo/modelmanage/download"
tplModelInfo = "repo/modelmanage/showinfo"
MODEL_LATEST = 1
MODEL_NOT_LATEST = 0
Model_prefix = "aimodels/"
tplModelManageIndex = "repo/modelmanage/index"
tplModelManageConvertIndex = "repo/modelmanage/convertIndex"
tplModelManageDownload = "repo/modelmanage/download"
tplModelInfo = "repo/modelmanage/showinfo"
MODEL_LATEST = 1
MODEL_NOT_LATEST = 0
)

func saveModelByParameters(jobId string, versionName string, name string, version string, label string, description string, ctx *context.Context) error {
@@ -617,6 +618,14 @@ func ShowModelTemplate(ctx *context.Context) {
ctx.HTML(200, tplModelManageIndex)
}

func ConvertModelTemplate(ctx *context.Context) {
ctx.Data["isModelManage"] = true
ctx.Data["MODEL_COUNT"] = 0
ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage)
ctx.Data["TRAIN_COUNT"] = 0
ctx.HTML(200, tplModelManageConvertIndex)
}

func isQueryRight(ctx *context.Context) bool {
if ctx.Repo.Repository.IsPrivate {
if ctx.Repo.CanRead(models.UnitTypeModelManage) || ctx.User.IsAdmin || ctx.Repo.IsAdmin() || ctx.Repo.IsOwner() {


+ 1
- 0
routers/routes/routes.go View File

@@ -1081,6 +1081,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Delete("/delete_model", repo.DeleteModel)
m.Put("/modify_model", repo.ModifyModelInfo)
m.Get("/show_model", reqRepoModelManageReader, repo.ShowModelTemplate)
m.Get("/convert_model", reqRepoModelManageReader, repo.ConvertModelTemplate)
m.Get("/show_model_info", repo.ShowModelInfo)
m.Get("/show_model_info_api", repo.ShowSingleModel)
m.Get("/show_model_api", repo.ShowModelPageInfo)


+ 285
- 0
templates/repo/modelmanage/convertIndex.tmpl View File

@@ -0,0 +1,285 @@
<!-- 头部导航栏 -->
{{template "base/head" .}}
<!-- 弹窗 -->
<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>
{{$repository := .Repository.ID}}
<!-- 提示框 -->
<div class="alert"></div>

<div class="repository release dataset-list view">
{{template "repo/header" .}}
<!-- 列表容器 -->
<div class="ui container {{if ne $.MODEL_COUNT 0}}active loader {{end}}" id="loadContainer">
{{template "base/alert" .}}
<div class="ui two column stackable grid">
<div class="column">
<div class="ui blue small menu compact selectcloudbrain">
<a class="item" href="{{.RepoLink}}/modelmanage/show_model">{{$.i18n.Tr "repo.model.list"}}</a>
<a class="active item" href="{{.RepoLink}}/modelmanage/convert_model">{{$.i18n.Tr "repo.model.convert"}}</a>
</div>
</div>
<div class="column right aligned">
<!-- -->
<a class="ui button {{if .Permission.CanWrite $.UnitTypeModelManage}} green {{else}} disabled {{end}}" onclick="showcreate(this)">{{$.i18n.Tr "repo.model.manage.create_new_convert_task"}}</a>
</div>
</div>
<!-- 中下列表展示区 -->
<div class="ui grid" style="display: none;">
<div class="row" style="padding-top: 0;">
<div class="ui sixteen wide column">
<!-- 任务展示 -->
<div class="dataset list" id="model_list">

<div class="ui grid stackable" style="background: #f0f0f0;;">
<div class="row">
<div class="three wide column padding0">
<span style="margin:0 6px">任务名称</span>
</div>
<div class="two wide column text center padding0">
<span>状态</span>
</div>
<div class="two wide column text center padding0">
<span>原模型框架</span>
</div>
<div class="two wide column text center padding0">
<span>转换后格式</span>
</div>
<div class="one wide column text center padding0">
<span>创建时间</span>
</div>
<div class="two wide column text center padding0">
<span>运行时长</span>
</div>
<div class="one wide column text center padding0">
<span>{{$.i18n.Tr "repo.cloudbrain_creator"}}</span>
</div>
<div class="three wide column text center padding0">
<span>{{$.i18n.Tr "repo.cloudbrain_operate"}}</span>
</div>
</div>
</div>
<!-- 表头 -->
</div>
</div>
</div>
</div>
</div>

</div>

<!-- div full height-->
</div>



<!-- 确认模态框 -->
<div id="deletemodel">
<div class="ui basic modal first">
<div class="ui icon header">
<i class="trash icon"></i> 删除模型
</div>

<div class="content">
<p>你确认删除该模型转换任务么?一旦删除不可恢复。</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 id="newmodelconvert">
<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">
<input type="hidden" name="initModel" value="{{$.MODEL_COUNT}}">
<div class="ui error message">
<!-- <p>asdasdasd</p> -->
</div>
<input type="hidden" name="_csrf" value="">
<div class="required inline field" id="task_name">
<label>任务名称</label>
<input style="width: 45%;" id="name" name="Name" required maxlength="25" onkeyup="this.value=this.value.replace(/[, ]/g,'')">
</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 fields ">
<div class="required ten wide field">
<label style="margin-left: -23px;">模型</label>
<div class="ui dropdown selection search width83 loading" id="choice_model">
<input type="hidden" id="ModelId" name="ModelId" required>
<div class="default text">选择模型</div>
<i class="dropdown icon"></i>
<div class="menu" id="model-name">
</div>
</div>
</div>
</div>
<div class="inline fields ">
<div class="required six widde field">
<label>模型版本</label>
<div class="ui dropdown selection search width70" id="choice_version">
<input type="hidden" id="ModelVersion" name="ModelVersion" required>
<div class="default text">选择版本</div>
<i class="dropdown icon"></i>
<div class="menu" id="model-version">

</div>
</div>
</div>
</div>
<div class="inline fields ">
<div class="required six widde field">
<label>原模型框架</label>
<div class="ui dropdown selection search width70" id="choice_engine">
<input type="hidden" id="SrcEngine" name="SrcEngine" required>
<div class="default text">原模型框架</div>
<i class="dropdown icon"></i>
<div class="menu" id="src-engine">

</div>
</div>
</div>
</div>
<div class="required inline field" id="inputshape_div">
<label>输入张量形状</label>
<input style="width: 45%;" id="inputshape" name="inputshape" 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 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>


{{template "base/footer" .}}

<script>
let repolink = {{.RepoLink}}
let repoId = {{$repository}}
const {_AppSubUrl, _StaticUrlPrefix, csrf} = window.config;
$('input[name="_csrf"]').val(csrf)

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 showcreate(obj){
$('.ui.modal.second')
.modal({
centered: false,
onShow:function(){
$('#model_header').text("导入新模型")
$('input[name="Version"]').addClass('model_disabled')
$('.ui.dimmer').css({"background-color":"rgb(136, 136, 136,0.7)"})
$("#job-name").empty()
createModelName()
loadTrainList()

},
onHide:function(){
document.getElementById("formId").reset();
$('#choice_model').dropdown('clear')
$('#choice_version').dropdown('clear')
$('.ui.dimmer').css({"background-color":""})
$('.ui.error.message').text()
$('.ui.error.message').css('display','none')

}
})
.modal('show')
}

$(function(){
$('#choice_model').dropdown({
onChange:function(value){
$(".ui.dropdown.selection.search.width70").addClass("loading")
$('#choice_version').dropdown('clear')
$("#job-version").empty()
loadTrainVersion(value)
}
})
})
function loadTrainList(){
$.get(`${repolink}/modelmanage/query_train_job?repoId=${repoId}`, (data) => {

const n_length = data.length
let train_html=''
for (let i=0;i<n_length;i++){
train_html += `<div class="item" data-value="${data[i].JobID}">${data[i].DisplayJobName}</div>`
train_html += '</div>'
}
$("#job-name").append(train_html)
$(".ui.dropdown.selection.search.width83").removeClass("loading")
$('#choice_model .default.text').text(data[0].DisplayJobName)
$('#choice_model input[name="JobId"]').val(data[0].JobID)
loadTrainVersion()

})
}
function loadTrainVersion(value){
let JobID = !value ?$('#choice_model input[name="JobId"]').val(): value
$.get(`${repolink}/modelmanage/query_train_job_version?JobID=${JobID}`, (data) => {
const n_length = data.length
let train_html=''
for (let i=0;i<n_length;i++){
train_html += `<div class="item" data-value="${data[i].VersionName}">${data[i].VersionName}</div>`
train_html += '</div>'
}
if(data.length){
$("#job-version").append(train_html)
$(".ui.dropdown.selection.search.width70").removeClass("loading")
var versionName = data[0].VersionName;
if(versionName==null || versionName==""){
versionName="V0001";
}
$('#choice_version .default.text').text(versionName)
$('#choice_version input[name="VersionName"]').val(versionName)
}

})
}
</script>


+ 6
- 1
templates/repo/modelmanage/index.tmpl View File

@@ -20,7 +20,12 @@
<div class="ui container {{if ne $.MODEL_COUNT 0}}active loader {{end}}" id="loadContainer">
{{template "base/alert" .}}
<div class="ui two column stackable grid">
<div class="column"></div>
<div class="column">
<div class="ui blue small menu compact selectcloudbrain">
<a class="active item" href="{{.RepoLink}}/modelmanage/show_model">{{$.i18n.Tr "repo.model.list"}}</a>
<a class="item" href="{{.RepoLink}}/modelmanage/convert_model">{{$.i18n.Tr "repo.model.convert"}}</a>
</div>
</div>
<div class="column right aligned">
<!-- -->
<a class="ui button {{if .Permission.CanWrite $.UnitTypeModelManage}} green {{else}} disabled {{end}}" onclick="showcreate(this)">{{$.i18n.Tr "repo.model.manage.import_new_model"}}</a>


Loading…
Cancel
Save