| @@ -62,6 +62,7 @@ type Cloudbrain struct { | |||
| Type int `xorm:"INDEX DEFAULT 0"` | |||
| VersionID int64 `xorm:"INDEX DEFAULT 0"` | |||
| VersionName string | |||
| Uuid string | |||
| User *User `xorm:"-"` | |||
| Repo *Repository `xorm:"-"` | |||
| @@ -636,18 +637,20 @@ type GetTrainJobResult struct { | |||
| //DataSource []DataSource `json:"data_source"` | |||
| //SpecID int64 `json:"spec_id"` | |||
| EngineID int64 `json:"engine_id"` | |||
| EngineName string `json:"engine_name"` | |||
| EngineVersion string `json:"engine_version"` | |||
| //ModelID int64 `json:"model_id"` | |||
| TrainUrl string `json:"train_url"` //训练作业的输出文件OBS路径URL | |||
| LogUrl string `json:"log_url"` | |||
| //UserImageUrl string `json:"user_image_url"` | |||
| //UserCommand string `json:"user_command"` | |||
| CreateVersion bool `json:"create_version"` | |||
| //Volumes []Volumes `json:"volumes"` | |||
| Flavor Flavor `json:"flavor"` | |||
| PoolID string `json:"pool_id"` | |||
| PoolName string `json:"pool_name"` | |||
| NasMountPath string `json:"nas_mount_path"` | |||
| NasShareAddr string `json:"nas_share_addr"` | |||
| DatasetName string | |||
| } | |||
| type GetTrainJobLogResult struct { | |||
| @@ -107,6 +107,7 @@ func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath, | |||
| SubTaskName: SubTaskName, | |||
| JobType: jobType, | |||
| Type: models.TypeCloudBrainOne, | |||
| Uuid: uuid, | |||
| }) | |||
| if err != nil { | |||
| @@ -129,6 +129,7 @@ func GenerateTask(ctx *context.Context, jobName, uuid, description string) error | |||
| JobName: jobName, | |||
| JobType: string(models.JobTypeDebug), | |||
| Type: models.TypeCloudBrainNotebook, | |||
| Uuid: uuid, | |||
| }) | |||
| if err != nil { | |||
| @@ -173,6 +174,7 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) error { | |||
| Type: models.TypeCloudBrainTrainJob, | |||
| VersionID: jobResult.VersionID, | |||
| VersionName: jobResult.VersionName, | |||
| Uuid: req.Uuid, | |||
| }) | |||
| if err != nil { | |||
| @@ -854,7 +854,10 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| }, reqRepoReader(models.UnitTypeCloudBrain)) | |||
| m.Group("/modelarts", func() { | |||
| m.Group("/notebook", func() { | |||
| m.Get("/:jobid", repo.GetModelArtsTask) | |||
| m.Get("/:jobid", repo.GetModelArtsNotebook) | |||
| }) | |||
| m.Group("/train-job", func() { | |||
| m.Get("/:jobid", repo.GetModelArtsTrainJob) | |||
| }) | |||
| }, reqRepoReader(models.UnitTypeCloudBrain)) | |||
| }, repoAssignment()) | |||
| @@ -11,9 +11,10 @@ import ( | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/modelarts" | |||
| "net/http" | |||
| "strconv" | |||
| ) | |||
| func GetModelArtsTask(ctx *context.APIContext) { | |||
| func GetModelArtsNotebook(ctx *context.APIContext) { | |||
| var ( | |||
| err error | |||
| ) | |||
| @@ -43,3 +44,34 @@ func GetModelArtsTask(ctx *context.APIContext) { | |||
| }) | |||
| } | |||
| func GetModelArtsTrainJob(ctx *context.APIContext) { | |||
| var ( | |||
| err error | |||
| ) | |||
| jobID := ctx.Params(":jobid") | |||
| repoID := ctx.Repo.Repository.ID | |||
| job, err := models.GetRepoCloudBrainByJobID(repoID, jobID) | |||
| if err != nil { | |||
| ctx.NotFound(err) | |||
| return | |||
| } | |||
| result, err := modelarts.GetTrainJob(jobID, strconv.FormatInt(job.VersionID, 10)) | |||
| if err != nil { | |||
| ctx.NotFound(err) | |||
| return | |||
| } | |||
| job.Status = modelarts.TransTrainJobStatus(result.IntStatus) | |||
| err = models.UpdateJob(job) | |||
| if err != nil { | |||
| log.Error("UpdateJob failed:", err) | |||
| } | |||
| ctx.JSON(http.StatusOK, map[string]interface{}{ | |||
| "JobID": jobID, | |||
| "JobStatus": job.Status, | |||
| }) | |||
| } | |||
| @@ -427,6 +427,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| EngineID: int64(engineID), | |||
| LogUrl: logObsPath, | |||
| PoolID: poolID, | |||
| Uuid: uuid, | |||
| } | |||
| err := modelarts.GenerateTrainJob(ctx, req) | |||
| @@ -537,6 +538,13 @@ func TrainJobShow(ctx *context.Context) { | |||
| return | |||
| } | |||
| attach, err := models.GetAttachmentByUUID(task.Uuid) | |||
| if err != nil { | |||
| log.Error("GetAttachmentByUUID(%s) failed:%v", jobID, err.Error()) | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobIndex, nil) | |||
| return | |||
| } | |||
| result, err := modelarts.GetTrainJob(jobID, strconv.FormatInt(task.VersionID, 10)) | |||
| if err != nil { | |||
| log.Error("GetJob(%s) failed:%v", jobID, err.Error()) | |||
| @@ -547,6 +555,7 @@ func TrainJobShow(ctx *context.Context) { | |||
| if result != nil { | |||
| result.CreateTime = time.Unix(int64(result.LongCreateTime/1000), 0).Format("2006-01-02 15:04:05") | |||
| result.Status = modelarts.TransTrainJobStatus(result.IntStatus) | |||
| result.DatasetName = attach.Name | |||
| } | |||
| ctx.Data["task"] = task | |||
| @@ -92,10 +92,10 @@ | |||
| </div> | |||
| <!-- 任务创建时间 --> | |||
| <div class="three wide column"> | |||
| <!-- <div class="three wide column"> | |||
| <span class="ui text center">{{svg "octicon-flame" 16}} {{TimeSinceUnix .CreatedUnix $.Lang}}</span> | |||
| </div> | |||
| </div> --> | |||
| <!-- 删除 --> | |||
| <div class="two wide column"> | |||
| <div class="ui text center clipboard"> | |||
| @@ -125,6 +125,27 @@ | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <!-- 确认模态框 --> | |||
| <div id="deletemodel"> | |||
| <div class="ui basic modal"> | |||
| <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> 取消操作 | |||
| </div> | |||
| <div class="ui green basic inverted ok button"> | |||
| <i class="checkmark icon"></i> 确定操作 | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| {{template "base/footer" .}} | |||
| @@ -160,4 +181,24 @@ | |||
| .modal('show') | |||
| } | |||
| } | |||
| // 加载任务状态 | |||
| $(document).ready(function() { | |||
| $(".job-status").each((index, job) => { | |||
| const jobID = job.dataset.jobid; | |||
| const repoPath = job.dataset.repopath; | |||
| if (job.textContent.trim() == 'STOPPED') { | |||
| return | |||
| } | |||
| $.get(`/api/v1/repos/${repoPath}/modelarts/train-job/${jobID}`, (data) => { | |||
| const jobID = data.JobID | |||
| const status = data.JobStatus | |||
| $('#' + jobID).text(status) | |||
| // console.log(data) | |||
| }).fail(function(err) { | |||
| console.log(err); | |||
| }); | |||
| }); | |||
| }); | |||
| </script> | |||
| @@ -66,7 +66,7 @@ | |||
| <tbody> | |||
| <tr> | |||
| <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.AI_driver"}} </td> | |||
| <td>{{.result.BootFileUrl}}</td> | |||
| <td>{{.result.EngineName}} | {{.result.EngineVersion}}</td> | |||
| </tr> | |||
| <tr> | |||
| <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.start_file"}}</td> | |||
| @@ -74,7 +74,7 @@ | |||
| </tr> | |||
| <tr> | |||
| <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.dataset"}} </td> | |||
| <td>{{.result.BootFileUrl}}</td> | |||
| <td>{{.result.DatasetName}}</td> | |||
| </tr> | |||
| <tr> | |||
| <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.run_parameter"}} </td> | |||