From 55970e9dbc9f9885baa08989d451b97bc5f5f0e6 Mon Sep 17 00:00:00 2001 From: zouap Date: Mon, 30 May 2022 11:12:24 +0800 Subject: [PATCH 001/349] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- models/cloudbrain.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/cloudbrain.go b/models/cloudbrain.go index 480350c8d..db91875ef 100755 --- a/models/cloudbrain.go +++ b/models/cloudbrain.go @@ -1300,7 +1300,7 @@ func QueryModelTrainJobList(repoId int64) ([]*CloudbrainInfo, int, error) { builder.Eq{"repo_id": repoId}, ) cond = cond.And( - builder.Eq{"Status": "COMPLETED"}, + builder.In("Status", "COMPLETED", "SUCCEEDED"), ) cond = cond.And( builder.Eq{"job_type": "TRAIN"}, From 8bc64ef9eed90df35c53d27756833fe23fbd2ed0 Mon Sep 17 00:00:00 2001 From: zouap Date: Mon, 30 May 2022 11:13:31 +0800 Subject: [PATCH 002/349] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0GPU=E8=AE=AD=E7=BB=83=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E6=A8=A1=E5=9E=8B=E9=80=89=E6=8B=A9=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- models/cloudbrain.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/models/cloudbrain.go b/models/cloudbrain.go index db91875ef..9f517b51d 100755 --- a/models/cloudbrain.go +++ b/models/cloudbrain.go @@ -1279,7 +1279,8 @@ func QueryModelTrainJobVersionList(jobId string) ([]*CloudbrainInfo, int, error) builder.Eq{"cloudbrain.job_id": jobId}, ) cond = cond.And( - builder.Eq{"cloudbrain.Status": "COMPLETED"}, + builder.In("cloudbrain.Status", "COMPLETED", "SUCCEEDED"), + //builder.Eq{"cloudbrain.Status": "COMPLETED"}, ) sess.OrderBy("cloudbrain.created_unix DESC") From 90558a4c611bd6c909e89ef1fea7be8a2f5ab64e Mon Sep 17 00:00:00 2001 From: zouap Date: Mon, 30 May 2022 14:22:22 +0800 Subject: [PATCH 003/349] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- modules/storage/minio_ext.go | 33 +++++++++++++++++++++++++++++++++ routers/repo/ai_model_manage.go | 17 +++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/modules/storage/minio_ext.go b/modules/storage/minio_ext.go index 167cd0488..9e9c91573 100755 --- a/modules/storage/minio_ext.go +++ b/modules/storage/minio_ext.go @@ -116,6 +116,39 @@ func GenMultiPartSignedUrl(uuid string, uploadId string, partNumber int, partSiz } +func MinioPathCopy(bucketName string, srcPath string, destPath string) (int64, error) { + _, core, err := getClients() + var count int64 + count = 0 + if err != nil { + log.Error("getClients failed:", err.Error()) + return count, err + } + delimiter := "" + marker := "" + for { + output, err := core.ListObjects(bucketName, srcPath, marker, delimiter, 1000) + if err == nil { + for _, val := range output.Contents { + srcObjectName := val.Key + destObjectName := destPath + srcObjectName[len(srcPath):] + log.Info("srcObjectName=" + srcObjectName + " destObjectName=" + destObjectName) + core.CopyObject(bucketName, srcObjectName, bucketName, destObjectName, val.UserMetadata) + count++ + } + if output.IsTruncated { + marker = output.NextMarker + } else { + break + } + } else { + log.Info("list error." + err.Error()) + return 0, err + } + } + return count, nil +} + func NewMultiPartUpload(uuid string) (string, error) { _, core, err := getClients() if err != nil { diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index e2040e0d2..ed882ffd7 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -39,7 +39,6 @@ func saveModelByParameters(jobId string, versionName string, name string, versio modelPath := id var lastNewModelId string var modelSize int64 - cloudType := models.TypeCloudBrainTwo log.Info("find task name:" + aiTask.JobName) aimodels := models.QueryModelByName(name, aiTask.RepoID) @@ -53,7 +52,7 @@ func saveModelByParameters(jobId string, versionName string, name string, versio } } } - cloudType = aiTask.Type + cloudType := aiTask.Type //download model zip //train type if cloudType == models.TypeCloudBrainTwo { modelPath, modelSize, err = downloadModelFromCloudBrainTwo(id, aiTask.JobName, "", aiTask.TrainUrl) @@ -61,6 +60,8 @@ func saveModelByParameters(jobId string, versionName string, name string, versio log.Info("download model from CloudBrainTwo faild." + err.Error()) return err } + } else if cloudType == models.TypeCloudBrainOne { + } accuracy := make(map[string]string) accuracy["F1"] = "" @@ -199,6 +200,18 @@ func downloadModelFromCloudBrainTwo(modelUUID string, jobName string, parentDir return dataActualPath, size, nil } +func downloadModelFromCloudBrainOne(modelUUID string, jobName string, parentDir string, trainUrl string) (string, int64, error) { + modelActualPath := storage.GetMinioPath(jobName, "/model/") + destKeyNamePrefix := Model_prefix + models.AttachmentRelativePath(modelUUID) + "/" + size, err := storage.MinioPathCopy(setting.Bucket, modelActualPath, destKeyNamePrefix) + if err == nil { + dataActualPath := setting.Bucket + "/" + destKeyNamePrefix + return dataActualPath, size, nil + } else { + return "", 0, nil + } +} + func DeleteModel(ctx *context.Context) { log.Info("delete model start.") id := ctx.Query("ID") From f067782abb33f415975995b93eb513da8935e437 Mon Sep 17 00:00:00 2001 From: zouap Date: Mon, 30 May 2022 15:08:38 +0800 Subject: [PATCH 004/349] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- routers/repo/ai_model_manage.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index ed882ffd7..78d2e1327 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -61,7 +61,11 @@ func saveModelByParameters(jobId string, versionName string, name string, versio return err } } else if cloudType == models.TypeCloudBrainOne { - + modelPath, modelSize, err = downloadModelFromCloudBrainOne(id, aiTask.JobName, "", aiTask.TrainUrl) + if err != nil { + log.Info("download model from CloudBrainOne faild." + err.Error()) + return err + } } accuracy := make(map[string]string) accuracy["F1"] = "" @@ -290,7 +294,15 @@ func DownloadMultiModelFile(ctx *context.Context) { } path := Model_prefix + models.AttachmentRelativePath(id) + "/" + if task.Type == models.TypeCloudBrainTwo { + + } else if task.Type == models.TypeCloudBrainOne { + + } + +} +func downloadFromCloudBrainTwo(path string, task *models.AiModelManage, ctx *context.Context, id string) { allFile, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, path) if err == nil { //count++ From 3075b8c23fc1826bce888c805e691c092ef31c8e Mon Sep 17 00:00:00 2001 From: zouap Date: Mon, 30 May 2022 15:41:20 +0800 Subject: [PATCH 005/349] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- modules/storage/minio_ext.go | 101 ++++++++++++++++++++++++++++++++++++++++ routers/repo/ai_model_manage.go | 58 +++++++++++++++++++++-- 2 files changed, 156 insertions(+), 3 deletions(-) diff --git a/modules/storage/minio_ext.go b/modules/storage/minio_ext.go index 9e9c91573..6aeaec623 100755 --- a/modules/storage/minio_ext.go +++ b/modules/storage/minio_ext.go @@ -116,6 +116,107 @@ func GenMultiPartSignedUrl(uuid string, uploadId string, partNumber int, partSiz } +func GetAllObjectByBucketAndPrefixMinio(bucket string, prefix string) ([]FileInfo, error) { + _, core, err := getClients() + if err != nil { + log.Error("getClients failed:", err.Error()) + return nil, err + } + prefixLen := len(prefix) + delimiter := "" + marker := "" + index := 1 + fileInfoList := FileInfoList{} + for { + output, err := core.ListObjects(bucket, prefix, marker, delimiter, 1000) + if err == nil { + log.Info("Page:%d\n", index) + index++ + for _, val := range output.Contents { + var isDir bool + if prefixLen == len(val.Key) { + continue + } + if strings.HasSuffix(val.Key, "/") { + isDir = true + } else { + isDir = false + } + fileInfo := FileInfo{ + ModTime: val.LastModified.Format("2006-01-02 15:04:05"), + FileName: val.Key[prefixLen:], + Size: val.Size, + IsDir: isDir, + ParenDir: "", + } + fileInfoList = append(fileInfoList, fileInfo) + } + if output.IsTruncated { + marker = output.NextMarker + } else { + break + } + } else { + log.Info("list error." + err.Error()) + return nil, err + } + } + sort.Sort(fileInfoList) + return fileInfoList, nil +} + +func GetOneLevelAllObjectUnderDirMinio(bucket string, prefixRootPath string, relativePath string) ([]FileInfo, error) { + _, core, err := getClients() + if err != nil { + log.Error("getClients failed:", err.Error()) + return nil, err + } + + Prefix := prefixRootPath + relativePath + if !strings.HasSuffix(Prefix, "/") { + Prefix += "/" + } + output, err := core.ListObjects(bucket, Prefix, "", "", 1000) + fileInfos := make([]FileInfo, 0) + prefixLen := len(Prefix) + if err == nil { + for _, val := range output.Contents { + log.Info("val key=" + val.Key) + var isDir bool + var fileName string + if val.Key == Prefix { + continue + } + if strings.Contains(val.Key[prefixLen:len(val.Key)-1], "/") { + continue + } + if strings.HasSuffix(val.Key, "/") { + isDir = true + fileName = val.Key[prefixLen : len(val.Key)-1] + relativePath += val.Key[prefixLen:] + } else { + isDir = false + fileName = val.Key[prefixLen:] + } + fileInfo := FileInfo{ + ModTime: val.LastModified.Local().Format("2006-01-02 15:04:05"), + FileName: fileName, + Size: val.Size, + IsDir: isDir, + ParenDir: relativePath, + } + fileInfos = append(fileInfos, fileInfo) + } + return fileInfos, err + } else { + + log.Error("Message:%s", err.Error()) + + return nil, err + } + +} + func MinioPathCopy(bucketName string, srcPath string, destPath string) (int64, error) { _, core, err := getClients() var count int64 diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index 78d2e1327..53030949e 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "net/http" + "net/url" "path" "strings" @@ -295,13 +296,64 @@ func DownloadMultiModelFile(ctx *context.Context) { path := Model_prefix + models.AttachmentRelativePath(id) + "/" if task.Type == models.TypeCloudBrainTwo { - + downloadFromCloudBrainTwo(path, task, ctx, id) } else if task.Type == models.TypeCloudBrainOne { - + downloadFromCloudBrainOne(path, task, ctx, id) } } +func downloadFromCloudBrainOne(path string, task *models.AiModelManage, ctx *context.Context, id string) { + allFile, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, path) + if err == nil { + //count++ + models.ModifyModelDownloadCount(id) + + returnFileName := task.Name + "_" + task.Version + ".zip" + ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(returnFileName)) + ctx.Resp.Header().Set("Content-Type", "application/octet-stream") + w := zip.NewWriter(ctx.Resp) + defer w.Close() + for _, oneFile := range allFile { + if oneFile.IsDir { + log.Info("zip dir name:" + oneFile.FileName) + } else { + log.Info("zip file name:" + oneFile.FileName) + fDest, err := w.Create(oneFile.FileName) + if err != nil { + log.Info("create zip entry error, download file failed: %s\n", err.Error()) + ctx.ServerError("download file failed:", err) + return + } + body, err := storage.ObsDownloadAFile(setting.Bucket, path+oneFile.FileName) + if err != nil { + log.Info("download file failed: %s\n", err.Error()) + ctx.ServerError("download file failed:", err) + return + } else { + defer body.Close() + p := make([]byte, 1024) + var readErr error + var readCount int + // 读取对象内容 + for { + readCount, readErr = body.Read(p) + if readCount > 0 { + fDest.Write(p[:readCount]) + } + if readErr != nil { + break + } + } + } + } + } + } else { + log.Info("error,msg=" + err.Error()) + ctx.ServerError("no file to download.", err) + } +} + func downloadFromCloudBrainTwo(path string, task *models.AiModelManage, ctx *context.Context, id string) { allFile, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, path) if err == nil { @@ -309,7 +361,7 @@ func downloadFromCloudBrainTwo(path string, task *models.AiModelManage, ctx *con models.ModifyModelDownloadCount(id) returnFileName := task.Name + "_" + task.Version + ".zip" - ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+returnFileName) + ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(returnFileName)) ctx.Resp.Header().Set("Content-Type", "application/octet-stream") w := zip.NewWriter(ctx.Resp) defer w.Close() From bcb5f69d0377e36ca01e2cfd8184da355703c111 Mon Sep 17 00:00:00 2001 From: zouap Date: Mon, 30 May 2022 17:54:35 +0800 Subject: [PATCH 006/349] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=8C=E5=AF=B9minio=E6=A8=A1=E5=9E=8B=E8=BF=9B=E8=A1=8C?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- modules/storage/minio.go | 10 ++++++++++ modules/storage/minio_ext.go | 1 - routers/repo/ai_model_manage.go | 21 +++++++++++---------- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/modules/storage/minio.go b/modules/storage/minio.go index 7b914817d..47f70e12d 100755 --- a/modules/storage/minio.go +++ b/modules/storage/minio.go @@ -59,6 +59,16 @@ func (m *MinioStorage) buildMinioPath(p string) string { return strings.TrimPrefix(path.Join(m.basePath, p), "/") } +func (m *MinioStorage) DownloadAFile(bucket string, objectName string) (io.ReadCloser, error) { + + var opts = minio.GetObjectOptions{} + object, err := m.client.GetObject(m.bucket, objectName, opts) + if err != nil { + return nil, err + } + return object, nil +} + // Open open a file func (m *MinioStorage) Open(path string) (io.ReadCloser, error) { var opts = minio.GetObjectOptions{} diff --git a/modules/storage/minio_ext.go b/modules/storage/minio_ext.go index 6aeaec623..82efcc710 100755 --- a/modules/storage/minio_ext.go +++ b/modules/storage/minio_ext.go @@ -113,7 +113,6 @@ func GenMultiPartSignedUrl(uuid string, uploadId string, partNumber int, partSiz objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/") return minioClient.GenUploadPartSignedUrl(uploadId, bucketName, objectName, partNumber, partSize, PresignedUploadPartUrlExpireTime, setting.Attachment.Minio.Location) - } func GetAllObjectByBucketAndPrefixMinio(bucket string, prefix string) ([]FileInfo, error) { diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index 53030949e..ef8c4b754 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -207,14 +207,15 @@ func downloadModelFromCloudBrainTwo(modelUUID string, jobName string, parentDir func downloadModelFromCloudBrainOne(modelUUID string, jobName string, parentDir string, trainUrl string) (string, int64, error) { modelActualPath := storage.GetMinioPath(jobName, "/model/") - destKeyNamePrefix := Model_prefix + models.AttachmentRelativePath(modelUUID) + "/" - size, err := storage.MinioPathCopy(setting.Bucket, modelActualPath, destKeyNamePrefix) - if err == nil { - dataActualPath := setting.Bucket + "/" + destKeyNamePrefix - return dataActualPath, size, nil - } else { - return "", 0, nil - } + log.Info("modelActualPath=" + modelActualPath) + //destKeyNamePrefix := Model_prefix + models.AttachmentRelativePath(modelUUID) + "/" + //size, err := storage.MinioPathCopy(setting.Bucket, modelActualPath, destKeyNamePrefix) + //if err == nil { + // dataActualPath := setting.Bucket + "/" + destKeyNamePrefix + // return dataActualPath, size, nil + //} else { + return "", 0, nil + //} } func DeleteModel(ctx *context.Context) { @@ -304,7 +305,7 @@ func DownloadMultiModelFile(ctx *context.Context) { } func downloadFromCloudBrainOne(path string, task *models.AiModelManage, ctx *context.Context, id string) { - allFile, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, path) + allFile, err := storage.GetAllObjectByBucketAndPrefixMinio(setting.Attachment.Minio.Bucket, path) if err == nil { //count++ models.ModifyModelDownloadCount(id) @@ -325,7 +326,7 @@ func downloadFromCloudBrainOne(path string, task *models.AiModelManage, ctx *con ctx.ServerError("download file failed:", err) return } - body, err := storage.ObsDownloadAFile(setting.Bucket, path+oneFile.FileName) + body, err := storage.Attachments.Open(oneFile.FileName) if err != nil { log.Info("download file failed: %s\n", err.Error()) ctx.ServerError("download file failed:", err) From 6ac80be14ce1353f025088ef1bba15902499bf2e Mon Sep 17 00:00:00 2001 From: zouap Date: Tue, 31 May 2022 09:29:16 +0800 Subject: [PATCH 007/349] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- templates/repo/modelmanage/index.tmpl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/templates/repo/modelmanage/index.tmpl b/templates/repo/modelmanage/index.tmpl index 73baa6c93..e65fbf004 100644 --- a/templates/repo/modelmanage/index.tmpl +++ b/templates/repo/modelmanage/index.tmpl @@ -248,8 +248,12 @@ if(data.length){ $("#job-version").append(train_html) $(".ui.dropdown.selection.search.width70").removeClass("loading") - $('#choice_version .default.text').text(data[0].VersionName) - $('#choice_version input[name="VersionName"]').val(data[0].VersionName) + var versionName = data[0].VersionName; + if(versionName==null || versionName==""){ + versionName="V0001"; + } + $('#choice_version .default.text').text(versionName) + $('#choice_version input[name="VersionName"]').val(versionName) } }) From 0bae82764609658bb01edf122b212e886f667f3f Mon Sep 17 00:00:00 2001 From: zouap Date: Tue, 31 May 2022 09:43:09 +0800 Subject: [PATCH 008/349] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- routers/repo/ai_model_manage.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index ef8c4b754..375bbaaa6 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -31,10 +31,14 @@ const ( func saveModelByParameters(jobId string, versionName string, name string, version string, label string, description string, ctx *context.Context) error { aiTask, err := models.GetCloudbrainByJobIDAndVersionName(jobId, versionName) if err != nil { - log.Info("query task error." + err.Error()) - return err + aiTask, err = models.GetRepoCloudBrainByJobID(ctx.Repo.Repository.ID, jobId) + if err != nil { + log.Info("query task error." + err.Error()) + return err + } else { + log.Info("query gpu train task.") + } } - uuid := uuid.NewV4() id := uuid.String() modelPath := id From 0866da75780cd32d65a118f77f22a519f47de97c Mon Sep 17 00:00:00 2001 From: zouap Date: Tue, 31 May 2022 09:53:22 +0800 Subject: [PATCH 009/349] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- routers/repo/ai_model_manage.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index 375bbaaa6..173966742 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -212,14 +212,16 @@ func downloadModelFromCloudBrainTwo(modelUUID string, jobName string, parentDir func downloadModelFromCloudBrainOne(modelUUID string, jobName string, parentDir string, trainUrl string) (string, int64, error) { modelActualPath := storage.GetMinioPath(jobName, "/model/") log.Info("modelActualPath=" + modelActualPath) - //destKeyNamePrefix := Model_prefix + models.AttachmentRelativePath(modelUUID) + "/" - //size, err := storage.MinioPathCopy(setting.Bucket, modelActualPath, destKeyNamePrefix) - //if err == nil { - // dataActualPath := setting.Bucket + "/" + destKeyNamePrefix - // return dataActualPath, size, nil - //} else { - return "", 0, nil - //} + modelSrcPrefix := setting.CBCodePathPrefix + jobName + "/model/" + destKeyNamePrefix := Model_prefix + models.AttachmentRelativePath(modelUUID) + "/" + log.Info("destKeyNamePrefix=" + destKeyNamePrefix + " modelSrcPrefix=" + modelSrcPrefix) + size, err := storage.MinioPathCopy(setting.Bucket, modelSrcPrefix, destKeyNamePrefix) + if err == nil { + dataActualPath := setting.Bucket + "/" + destKeyNamePrefix + return dataActualPath, size, nil + } else { + return "", 0, nil + } } func DeleteModel(ctx *context.Context) { From 8ffdd2113ba898a21b9511db6828fd34a849ef77 Mon Sep 17 00:00:00 2001 From: zouap Date: Tue, 31 May 2022 10:05:40 +0800 Subject: [PATCH 010/349] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- routers/repo/ai_model_manage.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index 173966742..e7ce72e11 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -214,10 +214,11 @@ func downloadModelFromCloudBrainOne(modelUUID string, jobName string, parentDir log.Info("modelActualPath=" + modelActualPath) modelSrcPrefix := setting.CBCodePathPrefix + jobName + "/model/" destKeyNamePrefix := Model_prefix + models.AttachmentRelativePath(modelUUID) + "/" - log.Info("destKeyNamePrefix=" + destKeyNamePrefix + " modelSrcPrefix=" + modelSrcPrefix) - size, err := storage.MinioPathCopy(setting.Bucket, modelSrcPrefix, destKeyNamePrefix) + bucketName := setting.Attachment.Minio.Bucket + log.Info("destKeyNamePrefix=" + destKeyNamePrefix + " modelSrcPrefix=" + modelSrcPrefix + " bucket=" + bucketName) + size, err := storage.MinioPathCopy(bucketName, modelSrcPrefix, destKeyNamePrefix) if err == nil { - dataActualPath := setting.Bucket + "/" + destKeyNamePrefix + dataActualPath := bucketName + "/" + destKeyNamePrefix return dataActualPath, size, nil } else { return "", 0, nil From 086c12b9604d6c86cf6a41f936122e74c7c1a0c4 Mon Sep 17 00:00:00 2001 From: zouap Date: Tue, 31 May 2022 10:18:34 +0800 Subject: [PATCH 011/349] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- routers/repo/ai_model_manage.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index e7ce72e11..a3a49af3a 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -774,9 +774,11 @@ func QueryModelFileForPredict(ctx *context.Context) { 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) + if model.Type == models.TypeCloudBrainTwo { + prefix := model.Path[len(setting.Bucket)+1:] + fileinfos, _ := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, prefix) + ctx.JSON(http.StatusOK, fileinfos) + } } func QueryOneLevelModelFile(ctx *context.Context) { @@ -788,7 +790,14 @@ func QueryOneLevelModelFile(ctx *context.Context) { 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) + if model.Type == models.TypeCloudBrainTwo { + prefix := model.Path[len(setting.Bucket)+1:] + fileinfos, _ := storage.GetOneLevelAllObjectUnderDir(setting.Bucket, prefix, parentDir) + ctx.JSON(http.StatusOK, fileinfos) + } else if model.Type == models.TypeCloudBrainOne { + prefix := model.Path[len(setting.Attachment.Minio.Bucket)+1:] + fileinfos, _ := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, parentDir) + ctx.JSON(http.StatusOK, fileinfos) + } + } From 7206faf1c7212b9a62c966ac2e612076060639b7 Mon Sep 17 00:00:00 2001 From: zouap Date: Tue, 31 May 2022 10:23:36 +0800 Subject: [PATCH 012/349] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- modules/storage/minio_ext.go | 1 + routers/repo/ai_model_manage.go | 2 ++ 2 files changed, 3 insertions(+) diff --git a/modules/storage/minio_ext.go b/modules/storage/minio_ext.go index 82efcc710..cbbc0179b 100755 --- a/modules/storage/minio_ext.go +++ b/modules/storage/minio_ext.go @@ -175,6 +175,7 @@ func GetOneLevelAllObjectUnderDirMinio(bucket string, prefixRootPath string, rel if !strings.HasSuffix(Prefix, "/") { Prefix += "/" } + log.Info("bucket=" + bucket + " Prefix=" + Prefix) output, err := core.ListObjects(bucket, Prefix, "", "", 1000) fileInfos := make([]FileInfo, 0) prefixLen := len(Prefix) diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index a3a49af3a..4bc54bf5f 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -791,10 +791,12 @@ func QueryOneLevelModelFile(ctx *context.Context) { return } if model.Type == models.TypeCloudBrainTwo { + log.Info("TypeCloudBrainTwo list model file.") prefix := model.Path[len(setting.Bucket)+1:] fileinfos, _ := storage.GetOneLevelAllObjectUnderDir(setting.Bucket, prefix, parentDir) ctx.JSON(http.StatusOK, fileinfos) } else if model.Type == models.TypeCloudBrainOne { + log.Info("TypeCloudBrainOne list model file.") prefix := model.Path[len(setting.Attachment.Minio.Bucket)+1:] fileinfos, _ := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, parentDir) ctx.JSON(http.StatusOK, fileinfos) From cf23e013ee02695416709c42967d7142902cb529 Mon Sep 17 00:00:00 2001 From: zouap Date: Tue, 31 May 2022 10:40:29 +0800 Subject: [PATCH 013/349] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- routers/repo/ai_model_manage.go | 65 ++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index 4bc54bf5f..7a02a5322 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -459,42 +459,55 @@ func DownloadSingleModelFile(ctx *context.Context) { ctx.NotFound(ctx.Req.URL.RequestURI(), nil) return } - if setting.PROXYURL != "" { - body, err := storage.ObsDownloadAFile(setting.Bucket, path) - if err != nil { - log.Info("download error.") + if task.Type == models.TypeCloudBrainTwo { + if setting.PROXYURL != "" { + body, err := storage.ObsDownloadAFile(setting.Bucket, path) + if err != nil { + log.Info("download error.") + } else { + //count++ + models.ModifyModelDownloadCount(id) + defer body.Close() + ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+fileName) + ctx.Resp.Header().Set("Content-Type", "application/octet-stream") + p := make([]byte, 1024) + var readErr error + var readCount int + // 读取对象内容 + for { + readCount, readErr = body.Read(p) + if readCount > 0 { + ctx.Resp.Write(p[:readCount]) + //fmt.Printf("%s", p[:readCount]) + } + if readErr != nil { + break + } + } + } } else { + url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, path) + if err != nil { + log.Error("GetObsCreateSignedUrl failed: %v", err.Error(), ctx.Data["msgID"]) + ctx.ServerError("GetObsCreateSignedUrl", err) + return + } //count++ models.ModifyModelDownloadCount(id) - defer body.Close() - ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+fileName) - ctx.Resp.Header().Set("Content-Type", "application/octet-stream") - p := make([]byte, 1024) - var readErr error - var readCount int - // 读取对象内容 - for { - readCount, readErr = body.Read(p) - if readCount > 0 { - ctx.Resp.Write(p[:readCount]) - //fmt.Printf("%s", p[:readCount]) - } - if readErr != nil { - break - } - } + http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) } - } else { - url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, path) + } else if task.Type == models.TypeCloudBrainOne { + log.Info("start to down load minio file.") + url, err := storage.Attachments.PresignedGetURL(path, fileName) if err != nil { - log.Error("GetObsCreateSignedUrl failed: %v", err.Error(), ctx.Data["msgID"]) - ctx.ServerError("GetObsCreateSignedUrl", err) + log.Error("Get minio get SignedUrl failed: %v", err.Error(), ctx.Data["msgID"]) + ctx.ServerError("Get minio get SignedUrl failed", err) return } - //count++ models.ModifyModelDownloadCount(id) http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) } + } func ShowModelInfo(ctx *context.Context) { From 788764a51fe8bec061f62ff3bb2e29090bb3d158 Mon Sep 17 00:00:00 2001 From: zouap Date: Tue, 31 May 2022 10:46:23 +0800 Subject: [PATCH 014/349] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- modules/storage/minio_ext.go | 10 +++++----- routers/repo/ai_model_manage.go | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/storage/minio_ext.go b/modules/storage/minio_ext.go index cbbc0179b..514ac7204 100755 --- a/modules/storage/minio_ext.go +++ b/modules/storage/minio_ext.go @@ -219,11 +219,11 @@ func GetOneLevelAllObjectUnderDirMinio(bucket string, prefixRootPath string, rel func MinioPathCopy(bucketName string, srcPath string, destPath string) (int64, error) { _, core, err := getClients() - var count int64 - count = 0 + var fileTotalSize int64 + fileTotalSize = 0 if err != nil { log.Error("getClients failed:", err.Error()) - return count, err + return fileTotalSize, err } delimiter := "" marker := "" @@ -235,7 +235,7 @@ func MinioPathCopy(bucketName string, srcPath string, destPath string) (int64, e destObjectName := destPath + srcObjectName[len(srcPath):] log.Info("srcObjectName=" + srcObjectName + " destObjectName=" + destObjectName) core.CopyObject(bucketName, srcObjectName, bucketName, destObjectName, val.UserMetadata) - count++ + fileTotalSize += val.Size } if output.IsTruncated { marker = output.NextMarker @@ -247,7 +247,7 @@ func MinioPathCopy(bucketName string, srcPath string, destPath string) (int64, e return 0, err } } - return count, nil + return fileTotalSize, nil } func NewMultiPartUpload(uuid string) (string, error) { diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index 7a02a5322..a13095d52 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -333,7 +333,7 @@ func downloadFromCloudBrainOne(path string, task *models.AiModelManage, ctx *con ctx.ServerError("download file failed:", err) return } - body, err := storage.Attachments.Open(oneFile.FileName) + body, err := storage.Attachments.Open(path + oneFile.FileName) if err != nil { log.Info("download file failed: %s\n", err.Error()) ctx.ServerError("download file failed:", err) From 87375ce6cc68818c4b8d389742d6041cab755051 Mon Sep 17 00:00:00 2001 From: zouap Date: Tue, 31 May 2022 16:15:02 +0800 Subject: [PATCH 015/349] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2=E4=BB=BB=E5=8A=A1=E7=95=8C=E9=9D=A2=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- models/ai_model_manage.go | 110 ++++++++++- models/models.go | 1 + options/locale/locale_en-US.ini | 3 + options/locale/locale_zh-CN.ini | 3 + routers/repo/ai_model_manage.go | 21 +- routers/routes/routes.go | 1 + templates/repo/modelmanage/convertIndex.tmpl | 285 +++++++++++++++++++++++++++ templates/repo/modelmanage/index.tmpl | 7 +- 8 files changed, 421 insertions(+), 10 deletions(-) create mode 100644 templates/repo/modelmanage/convertIndex.tmpl diff --git a/models/ai_model_manage.go b/models/ai_model_manage.go index ed696fcf0..ac4aed302 100644 --- a/models/ai_model_manage.go +++ b/models/ai_model_manage.go @@ -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 +} diff --git a/models/models.go b/models/models.go index 2a2e119fb..962cb3ce9 100755 --- a/models/models.go +++ b/models/models.go @@ -144,6 +144,7 @@ func init() { new(WechatBindLog), new(OrgStatistic), new(SearchRecord), + new(AiModelManageConvert), ) tablesStatistic = append(tablesStatistic, diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 735525efb..7bc41e910 100755 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -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) diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 483ddde6c..260c24e49 100755 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -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数据(默认分支) diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index a13095d52..4db546180 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -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() { diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 1e1a862ff..12447b96b 100755 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -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) diff --git a/templates/repo/modelmanage/convertIndex.tmpl b/templates/repo/modelmanage/convertIndex.tmpl new file mode 100644 index 000000000..4230cfd05 --- /dev/null +++ b/templates/repo/modelmanage/convertIndex.tmpl @@ -0,0 +1,285 @@ + +{{template "base/head" .}} + +
+
+
+
+
+
+
+
+
+{{$repository := .Repository.ID}} + +
+ +
+ {{template "repo/header" .}} + +
+ {{template "base/alert" .}} + + + + +
+ +
+ + + + + + + +
+ +
+
+ + + +{{template "base/footer" .}} + + + diff --git a/templates/repo/modelmanage/index.tmpl b/templates/repo/modelmanage/index.tmpl index e65fbf004..5f3936ff6 100644 --- a/templates/repo/modelmanage/index.tmpl +++ b/templates/repo/modelmanage/index.tmpl @@ -20,7 +20,12 @@
{{template "base/alert" .}}
-
+
{{$.i18n.Tr "repo.model.manage.import_new_model"}} From 1a7eb69d939dd6999bdee04024f405cb4cfe4318 Mon Sep 17 00:00:00 2001 From: zouap Date: Tue, 31 May 2022 16:17:48 +0800 Subject: [PATCH 016/349] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2=E4=BB=BB=E5=8A=A1=E7=95=8C=E9=9D=A2=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- templates/repo/modelmanage/convertIndex.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/modelmanage/convertIndex.tmpl b/templates/repo/modelmanage/convertIndex.tmpl index 4230cfd05..b72feb9db 100644 --- a/templates/repo/modelmanage/convertIndex.tmpl +++ b/templates/repo/modelmanage/convertIndex.tmpl @@ -37,7 +37,7 @@
-
+
From 7ca7d93905ba62a96e3a649db9e2139cab82934b Mon Sep 17 00:00:00 2001 From: zouap Date: Tue, 31 May 2022 16:35:38 +0800 Subject: [PATCH 017/349] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2=E4=BB=BB=E5=8A=A1=E7=95=8C=E9=9D=A2=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- templates/repo/modelmanage/convertIndex.tmpl | 54 ++++++++++++++-------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/templates/repo/modelmanage/convertIndex.tmpl b/templates/repo/modelmanage/convertIndex.tmpl index b72feb9db..e9b7e2016 100644 --- a/templates/repo/modelmanage/convertIndex.tmpl +++ b/templates/repo/modelmanage/convertIndex.tmpl @@ -33,12 +33,12 @@
-