| @@ -76,7 +76,7 @@ export default defineConfig({ | |||||
| * @name layout 插件 | * @name layout 插件 | ||||
| * @doc https://umijs.org/docs/max/layout-menu | * @doc https://umijs.org/docs/max/layout-menu | ||||
| */ | */ | ||||
| title: '智能软件开发平台', | |||||
| title: '智能材料科研平台', | |||||
| layout: { | layout: { | ||||
| locale: false, | locale: false, | ||||
| ...defaultSettings, | ...defaultSettings, | ||||
| @@ -16,7 +16,7 @@ const Settings: ProLayoutProps & { | |||||
| fixSiderbar: false, | fixSiderbar: false, | ||||
| splitMenus: false, | splitMenus: false, | ||||
| colorWeak: false, | colorWeak: false, | ||||
| title: '智能软件开发平台', | |||||
| title: '智能材料科研平台', | |||||
| pwa: true, | pwa: true, | ||||
| logo: '/assets/images/left-top-logo.png', | logo: '/assets/images/left-top-logo.png', | ||||
| token: { | token: { | ||||
| @@ -112,7 +112,7 @@ export default [ | |||||
| { | { | ||||
| name: '开发环境', | name: '开发环境', | ||||
| path: '', | path: '', | ||||
| component: './DevelopmentEnvironment/List', | |||||
| component: './DevelopmentEnvironment/Editor', | |||||
| }, | }, | ||||
| { | { | ||||
| name: '创建编辑器', | name: '创建编辑器', | ||||
| @@ -241,10 +241,10 @@ const Login: React.FC = () => { | |||||
| style={{ height: '42px', marginRight: '10px' }} | style={{ height: '42px', marginRight: '10px' }} | ||||
| alt="" | alt="" | ||||
| /> | /> | ||||
| 智能软件开发平台 | |||||
| 智能材料科研平台 | |||||
| </div> | </div> | ||||
| <div className={centerTitleBoX}> | <div className={centerTitleBoX}> | ||||
| <span style={{ whiteSpace: 'nowrap' }}>智能软件开发平台</span> | |||||
| <span style={{ whiteSpace: 'nowrap' }}>智能材料科研平台</span> | |||||
| <img | <img | ||||
| src="/assets/images/ai-logo.png" | src="/assets/images/ai-logo.png" | ||||
| @@ -271,7 +271,7 @@ const Login: React.FC = () => { | |||||
| <div className={rightTopTitle}> | <div className={rightTopTitle}> | ||||
| <span style={{ color: '#111111', fontSize: '36px' }}>hello~</span> | <span style={{ color: '#111111', fontSize: '36px' }}>hello~</span> | ||||
| <span style={{ color: '#606b7a', fontSize: '32px', marginLeft: '10px' }}>欢迎登陆</span> | <span style={{ color: '#606b7a', fontSize: '32px', marginLeft: '10px' }}>欢迎登陆</span> | ||||
| <span style={{ color: '#1664ff', fontSize: '32px' }}>智能软件开发平台</span> | |||||
| <span style={{ color: '#1664ff', fontSize: '32px' }}>智能材料科研平台</span> | |||||
| </div> | </div> | ||||
| <div className={containerLoginForm}> | <div className={containerLoginForm}> | ||||
| <div | <div | ||||
| @@ -205,6 +205,17 @@ | |||||
| <groupId>org.springframework.boot</groupId> | <groupId>org.springframework.boot</groupId> | ||||
| <artifactId>spring-boot-starter-websocket</artifactId> | <artifactId>spring-boot-starter-websocket</artifactId> | ||||
| </dependency> | </dependency> | ||||
| <dependency> | |||||
| <groupId>org.json</groupId> | |||||
| <artifactId>json</artifactId> | |||||
| <version>20210307</version> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>org.apache.dubbo</groupId> | |||||
| <artifactId>dubbo</artifactId> | |||||
| <version>3.0.8</version> | |||||
| <scope>compile</scope> | |||||
| </dependency> | |||||
| </dependencies> | </dependencies> | ||||
| @@ -0,0 +1,46 @@ | |||||
| package com.ruoyi.platform.controller.aim; | |||||
| import com.ruoyi.common.core.web.controller.BaseController; | |||||
| import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | |||||
| import com.ruoyi.platform.service.AimService; | |||||
| import com.ruoyi.platform.vo.FrameLogPathVo; | |||||
| import com.ruoyi.platform.vo.InsMetricInfoVo; | |||||
| import com.ruoyi.platform.vo.PodStatusVo; | |||||
| import io.swagger.annotations.Api; | |||||
| import io.swagger.annotations.ApiOperation; | |||||
| import io.swagger.v3.oas.annotations.responses.ApiResponse; | |||||
| import org.springframework.web.bind.annotation.*; | |||||
| import javax.annotation.Resource; | |||||
| import java.util.List; | |||||
| @RestController | |||||
| @RequestMapping("aim") | |||||
| @Api("Aim管理") | |||||
| public class AimController extends BaseController { | |||||
| @Resource | |||||
| private AimService aimService; | |||||
| @GetMapping("/getExpTrainInfos/{experiment_id}") | |||||
| @ApiOperation("获取当前实验的模型训练指标信息") | |||||
| @ApiResponse | |||||
| public GenericsAjaxResult<List<InsMetricInfoVo>> getExpTrainInfos(@PathVariable("experiment_id") Integer experimentId) throws Exception { | |||||
| return genericsSuccess(aimService.getExpTrainInfos(experimentId)); | |||||
| } | |||||
| @GetMapping("/getExpEvaluateInfos/{experiment_id}") | |||||
| @ApiOperation("获取当前实验的模型推理指标信息") | |||||
| @ApiResponse | |||||
| public GenericsAjaxResult<List<InsMetricInfoVo>> getExpEvaluateInfos(@PathVariable("experiment_id") Integer experimentId) throws Exception { | |||||
| return genericsSuccess(aimService.getExpEvaluateInfos(experimentId)); | |||||
| } | |||||
| @PostMapping("/getExpMetrics") | |||||
| @ApiOperation("获取当前实验的指标对比地址") | |||||
| @ApiResponse | |||||
| public GenericsAjaxResult<String> getExpMetrics(@RequestBody List<String> runIds) throws Exception { | |||||
| return genericsSuccess(aimService.getExpMetrics(runIds)); | |||||
| } | |||||
| } | |||||
| @@ -4,6 +4,7 @@ import com.ruoyi.common.core.web.controller.BaseController; | |||||
| import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | ||||
| import com.ruoyi.platform.domain.DevEnvironment; | import com.ruoyi.platform.domain.DevEnvironment; | ||||
| import com.ruoyi.platform.service.DevEnvironmentService; | import com.ruoyi.platform.service.DevEnvironmentService; | ||||
| import com.ruoyi.platform.vo.DevEnvironmentVo; | |||||
| import io.swagger.annotations.Api; | import io.swagger.annotations.Api; | ||||
| import org.springframework.data.domain.Page; | import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.PageRequest; | import org.springframework.data.domain.PageRequest; | ||||
| @@ -56,12 +57,12 @@ public class DevEnvironmentController extends BaseController { | |||||
| /** | /** | ||||
| * 新增数据 | * 新增数据 | ||||
| * | * | ||||
| * @param devEnvironment 实体 | |||||
| * @param devEnvironmentVo 实体 | |||||
| * @return 新增结果 | * @return 新增结果 | ||||
| */ | */ | ||||
| @PostMapping | @PostMapping | ||||
| public ResponseEntity<DevEnvironment> add(@RequestBody DevEnvironment devEnvironment) { | |||||
| return ResponseEntity.ok(this.devEnvironmentService.insert(devEnvironment)); | |||||
| public GenericsAjaxResult<DevEnvironment> add(@RequestBody DevEnvironmentVo devEnvironmentVo) { | |||||
| return genericsSuccess(this.devEnvironmentService.insert(devEnvironmentVo)); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -71,8 +72,8 @@ public class DevEnvironmentController extends BaseController { | |||||
| * @return 编辑结果 | * @return 编辑结果 | ||||
| */ | */ | ||||
| @PutMapping | @PutMapping | ||||
| public ResponseEntity<DevEnvironment> edit(@RequestBody DevEnvironment devEnvironment) { | |||||
| return ResponseEntity.ok(this.devEnvironmentService.update(devEnvironment)); | |||||
| public GenericsAjaxResult<DevEnvironment> edit(@RequestBody DevEnvironment devEnvironment) { | |||||
| return genericsSuccess(this.devEnvironmentService.update(devEnvironment)); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -82,8 +83,8 @@ public class DevEnvironmentController extends BaseController { | |||||
| * @return 删除是否成功 | * @return 删除是否成功 | ||||
| */ | */ | ||||
| @DeleteMapping("{id}") | @DeleteMapping("{id}") | ||||
| public ResponseEntity<String> deleteById(@PathVariable("id") Integer id) { | |||||
| return ResponseEntity.ok(this.devEnvironmentService.removeById(id)); | |||||
| public GenericsAjaxResult<String> deleteById(@PathVariable("id") Integer id) { | |||||
| return genericsSuccess(this.devEnvironmentService.removeById(id)); | |||||
| } | } | ||||
| } | } | ||||
| @@ -3,8 +3,10 @@ package com.ruoyi.platform.controller.jupyter; | |||||
| import com.ruoyi.common.core.web.controller.BaseController; | import com.ruoyi.common.core.web.controller.BaseController; | ||||
| import com.ruoyi.common.core.web.domain.AjaxResult; | import com.ruoyi.common.core.web.domain.AjaxResult; | ||||
| import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | ||||
| import com.ruoyi.platform.domain.DevEnvironment; | |||||
| import com.ruoyi.platform.service.JupyterService; | import com.ruoyi.platform.service.JupyterService; | ||||
| import com.ruoyi.platform.vo.FrameLogPathVo; | import com.ruoyi.platform.vo.FrameLogPathVo; | ||||
| import com.ruoyi.platform.vo.PodStatusVo; | |||||
| import io.swagger.annotations.Api; | import io.swagger.annotations.Api; | ||||
| import io.swagger.annotations.ApiOperation; | import io.swagger.annotations.ApiOperation; | ||||
| import io.swagger.v3.oas.annotations.responses.ApiResponse; | import io.swagger.v3.oas.annotations.responses.ApiResponse; | ||||
| @@ -56,6 +58,13 @@ public class JupyterController extends BaseController { | |||||
| return genericsSuccess(this.jupyterService.stopJupyterService(id)); | return genericsSuccess(this.jupyterService.stopJupyterService(id)); | ||||
| } | } | ||||
| @PostMapping("/getStatus") | |||||
| @ApiOperation("查询jupyter pod状态") | |||||
| @ApiResponse | |||||
| public GenericsAjaxResult<PodStatusVo> getStatus(DevEnvironment devEnvironment) throws Exception { | |||||
| return genericsSuccess(this.jupyterService.getJupyterStatus(devEnvironment)); | |||||
| } | |||||
| @GetMapping(value = "/upload") | @GetMapping(value = "/upload") | ||||
| public AjaxResult upload() throws Exception { | public AjaxResult upload() throws Exception { | ||||
| @@ -4,7 +4,7 @@ import com.ruoyi.common.core.web.controller.BaseController; | |||||
| import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | ||||
| import com.ruoyi.platform.service.TensorBoardService; | import com.ruoyi.platform.service.TensorBoardService; | ||||
| import com.ruoyi.platform.vo.FrameLogPathVo; | import com.ruoyi.platform.vo.FrameLogPathVo; | ||||
| import com.ruoyi.platform.vo.TensorboardStatusVo; | |||||
| import com.ruoyi.platform.vo.PodStatusVo; | |||||
| import io.swagger.annotations.Api; | import io.swagger.annotations.Api; | ||||
| import io.swagger.annotations.ApiOperation; | import io.swagger.annotations.ApiOperation; | ||||
| import io.swagger.v3.oas.annotations.responses.ApiResponse; | import io.swagger.v3.oas.annotations.responses.ApiResponse; | ||||
| @@ -37,7 +37,7 @@ public class TensorBoardController extends BaseController { | |||||
| } | } | ||||
| @PostMapping("/getStatus") | @PostMapping("/getStatus") | ||||
| @ApiResponse | @ApiResponse | ||||
| public GenericsAjaxResult<TensorboardStatusVo> getStatus(@RequestBody FrameLogPathVo frameLogPathVo) throws Exception { | |||||
| public GenericsAjaxResult<PodStatusVo> getStatus(@RequestBody FrameLogPathVo frameLogPathVo) throws Exception { | |||||
| return genericsSuccess(tensorBoardService.getTensorBoardStatus(frameLogPathVo)); | return genericsSuccess(tensorBoardService.getTensorBoardStatus(frameLogPathVo)); | ||||
| } | } | ||||
| } | } | ||||
| @@ -54,7 +54,7 @@ public class DevEnvironment implements Serializable { | |||||
| /** | /** | ||||
| * 备用字段1 | * 备用字段1 | ||||
| */ | */ | ||||
| private String altField1; | |||||
| private String url; | |||||
| /** | /** | ||||
| * 备用字段2 | * 备用字段2 | ||||
| */ | */ | ||||
| @@ -153,12 +153,12 @@ public class DevEnvironment implements Serializable { | |||||
| this.model = model; | this.model = model; | ||||
| } | } | ||||
| public String getAltField1() { | |||||
| return altField1; | |||||
| public String getUrl() { | |||||
| return url; | |||||
| } | } | ||||
| public void setAltField1(String altField1) { | |||||
| this.altField1 = altField1; | |||||
| public void setUrl(String url) { | |||||
| this.url = url; | |||||
| } | } | ||||
| public String getAltField2() { | public String getAltField2() { | ||||
| @@ -48,6 +48,9 @@ public class ExperimentIns implements Serializable { | |||||
| @ApiModelProperty(value = "实验实例全局参数", notes = "以JSON字符串格式存储") | @ApiModelProperty(value = "实验实例全局参数", notes = "以JSON字符串格式存储") | ||||
| @JsonRawValue | @JsonRawValue | ||||
| private String globalParam; | private String globalParam; | ||||
| @ApiModelProperty(value = "参数记录", notes = "以JSON字符串格式存储") | |||||
| @JsonRawValue | |||||
| private String metricRecord; | |||||
| @ApiModelProperty(value = "开始时间") | @ApiModelProperty(value = "开始时间") | ||||
| private Date startTime; | private Date startTime; | ||||
| @@ -210,5 +213,12 @@ public class ExperimentIns implements Serializable { | |||||
| public void setWorkflowId(Long workflowId) {this.workflowId = workflowId;} | public void setWorkflowId(Long workflowId) {this.workflowId = workflowId;} | ||||
| public String getMetricRecord() { | |||||
| return metricRecord; | |||||
| } | |||||
| public void setMetricRecord(String metricRecord) { | |||||
| this.metricRecord = metricRecord; | |||||
| } | |||||
| } | } | ||||
| @@ -84,5 +84,9 @@ public interface ModelDependencyDao { | |||||
| List<ModelDependency> queryByModelDependency(@Param("modelDependency") ModelDependency modelDependency); | List<ModelDependency> queryByModelDependency(@Param("modelDependency") ModelDependency modelDependency); | ||||
| List<ModelDependency> queryChildrenByVersionId(@Param("model_id")String modelId, @Param("version")String version); | List<ModelDependency> queryChildrenByVersionId(@Param("model_id")String modelId, @Param("version")String version); | ||||
| List<ModelDependency> queryByIns(@Param("expInsId")Integer expInsId); | |||||
| ModelDependency queryByInsAndTrainTaskId(@Param("expInsId")Integer expInsId,@Param("taskId") String taskId); | |||||
| } | } | ||||
| @@ -7,20 +7,15 @@ import com.ruoyi.platform.mapper.ExperimentDao; | |||||
| import com.ruoyi.platform.mapper.ExperimentInsDao; | import com.ruoyi.platform.mapper.ExperimentInsDao; | ||||
| import com.ruoyi.platform.mapper.ModelDependencyDao; | import com.ruoyi.platform.mapper.ModelDependencyDao; | ||||
| import com.ruoyi.platform.service.ExperimentInsService; | import com.ruoyi.platform.service.ExperimentInsService; | ||||
| import com.ruoyi.platform.service.ModelDependencyService; | |||||
| import com.ruoyi.platform.utils.JacksonUtil; | import com.ruoyi.platform.utils.JacksonUtil; | ||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.data.domain.Page; | |||||
| import org.springframework.scheduling.annotation.Scheduled; | import org.springframework.scheduling.annotation.Scheduled; | ||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||
| import javax.annotation.Resource; | import javax.annotation.Resource; | ||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.util.ArrayList; | |||||
| import java.util.Date; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| import java.util.*; | |||||
| @Component() | @Component() | ||||
| public class ExperimentInstanceStatusTask { | public class ExperimentInstanceStatusTask { | ||||
| @@ -46,95 +41,94 @@ public class ExperimentInstanceStatusTask { | |||||
| String oldStatus = experimentIns.getStatus(); | String oldStatus = experimentIns.getStatus(); | ||||
| try { | try { | ||||
| experimentIns = experimentInsService.queryStatusFromArgo(experimentIns); | experimentIns = experimentInsService.queryStatusFromArgo(experimentIns); | ||||
| }catch (Exception e){ | |||||
| } catch (Exception e) { | |||||
| experimentIns.setStatus("Failed"); | experimentIns.setStatus("Failed"); | ||||
| } | } | ||||
| if (!StringUtils.equals(oldStatus,experimentIns.getStatus())){ | |||||
| experimentIns.setUpdateTime(new Date()); | |||||
| // 线程安全的添加操作 | |||||
| synchronized (experimentIds) { | |||||
| experimentIds.add(experimentIns.getExperimentId()); | |||||
| } | |||||
| updateList.add(experimentIns); | |||||
| experimentIns.setUpdateTime(new Date()); | |||||
| // 线程安全的添加操作 | |||||
| synchronized (experimentIds) { | |||||
| experimentIds.add(experimentIns.getExperimentId()); | |||||
| } | } | ||||
| // experimentInsDao.update(experimentIns); | |||||
| updateList.add(experimentIns); | |||||
| } | } | ||||
| } | } | ||||
| if (updateList.size() > 0){ | |||||
| if (updateList.size() > 0) { | |||||
| experimentInsDao.insertOrUpdateBatch(updateList); | experimentInsDao.insertOrUpdateBatch(updateList); | ||||
| //遍历模型关系表,找到 | //遍历模型关系表,找到 | ||||
| List<ModelDependency> modelDependencyList = new ArrayList<ModelDependency>(); | List<ModelDependency> modelDependencyList = new ArrayList<ModelDependency>(); | ||||
| for (ExperimentIns experimentIns : updateList){ | |||||
| for (ExperimentIns experimentIns : updateList) { | |||||
| ModelDependency modelDependencyquery = new ModelDependency(); | ModelDependency modelDependencyquery = new ModelDependency(); | ||||
| modelDependencyquery.setExpInsId(experimentIns.getId()); | modelDependencyquery.setExpInsId(experimentIns.getId()); | ||||
| modelDependencyquery.setState(2); | modelDependencyquery.setState(2); | ||||
| List<ModelDependency> modelDependencyListquery = modelDependencyDao.queryByModelDependency(modelDependencyquery); | List<ModelDependency> modelDependencyListquery = modelDependencyDao.queryByModelDependency(modelDependencyquery); | ||||
| if (modelDependencyListquery==null||modelDependencyListquery.size()==0){ | |||||
| if (modelDependencyListquery == null || modelDependencyListquery.size() == 0) { | |||||
| continue; | continue; | ||||
| } | } | ||||
| ModelDependency modelDependency = modelDependencyListquery.get(0); | ModelDependency modelDependency = modelDependencyListquery.get(0); | ||||
| //查看状态, | //查看状态, | ||||
| if (StringUtils.equals("Failed",experimentIns.getStatus())){ | |||||
| if (StringUtils.equals("Failed", experimentIns.getStatus())) { | |||||
| //取出节点状态 | //取出节点状态 | ||||
| String trainTask = modelDependency.getTrainTask(); | String trainTask = modelDependency.getTrainTask(); | ||||
| Map<String, Object> trainMap = JacksonUtil.parseJSONStr2Map(trainTask); | Map<String, Object> trainMap = JacksonUtil.parseJSONStr2Map(trainTask); | ||||
| String task_id = (String) trainMap.get("task_id"); | String task_id = (String) trainMap.get("task_id"); | ||||
| if (StringUtils.isEmpty(task_id)){ | |||||
| if (StringUtils.isEmpty(task_id)) { | |||||
| continue; | continue; | ||||
| } | } | ||||
| String nodesStatus = experimentIns.getNodesStatus(); | String nodesStatus = experimentIns.getNodesStatus(); | ||||
| Map<String, Object> nodeMaps = JacksonUtil.parseJSONStr2Map(nodesStatus); | Map<String, Object> nodeMaps = JacksonUtil.parseJSONStr2Map(nodesStatus); | ||||
| Map<String, Object> nodeMap = JacksonUtil.parseJSONStr2Map(JacksonUtil.toJSONString(nodeMaps.get(task_id))); | Map<String, Object> nodeMap = JacksonUtil.parseJSONStr2Map(JacksonUtil.toJSONString(nodeMaps.get(task_id))); | ||||
| if (nodeMap==null){ | |||||
| if (nodeMap == null) { | |||||
| continue; | continue; | ||||
| } | } | ||||
| if (!StringUtils.equals("Succeeded",(String)nodeMap.get("phase"))){ | |||||
| if (!StringUtils.equals("Succeeded", (String) nodeMap.get("phase"))) { | |||||
| modelDependency.setState(0); | modelDependency.setState(0); | ||||
| modelDependencyList.add(modelDependency); | modelDependencyList.add(modelDependency); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (modelDependencyList.size()>0) { | |||||
| if (modelDependencyList.size() > 0) { | |||||
| modelDependencyDao.insertOrUpdateBatch(modelDependencyList); | modelDependencyDao.insertOrUpdateBatch(modelDependencyList); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @Scheduled(cron = "0/30 * * * * ?") // / 每30S执行一次 | @Scheduled(cron = "0/30 * * * * ?") // / 每30S执行一次 | ||||
| public void executeExperimentStatus() throws IOException { | public void executeExperimentStatus() throws IOException { | ||||
| if (experimentIds.size()==0){ | |||||
| if (experimentIds.size() == 0) { | |||||
| return; | return; | ||||
| } | } | ||||
| // 存储需要更新的实验对象列表 | // 存储需要更新的实验对象列表 | ||||
| List<Experiment> updateExperiments = new ArrayList<>(); | List<Experiment> updateExperiments = new ArrayList<>(); | ||||
| for (Integer experimentId : experimentIds){ | |||||
| for (Integer experimentId : experimentIds) { | |||||
| // 获取当前实验的所有实例列表 | // 获取当前实验的所有实例列表 | ||||
| List<ExperimentIns> insList = experimentInsService.getByExperimentId(experimentId); | List<ExperimentIns> insList = experimentInsService.getByExperimentId(experimentId); | ||||
| List<String> statusList = new ArrayList<String>(); | List<String> statusList = new ArrayList<String>(); | ||||
| // 更新实验状态列表 | // 更新实验状态列表 | ||||
| for (int i=0;i<insList.size();i++){ | |||||
| for (int i = 0; i < insList.size(); i++) { | |||||
| statusList.add(insList.get(i).getStatus()); | statusList.add(insList.get(i).getStatus()); | ||||
| } | } | ||||
| String subStatus = statusList.toString().substring(1, statusList.toString().length() - 1); | String subStatus = statusList.toString().substring(1, statusList.toString().length() - 1); | ||||
| Experiment experiment = experimentDao.queryById(experimentId); | Experiment experiment = experimentDao.queryById(experimentId); | ||||
| // 如果实验状态列表发生变化,则更新实验对象,并加入到需要更新的列表中 | // 如果实验状态列表发生变化,则更新实验对象,并加入到需要更新的列表中 | ||||
| if (!StringUtils.equals(subStatus,experiment.getStatusList())){ | |||||
| if (!StringUtils.equals(subStatus, experiment.getStatusList())) { | |||||
| experiment.setStatusList(subStatus); | experiment.setStatusList(subStatus); | ||||
| updateExperiments.add(experiment); | updateExperiments.add(experiment); | ||||
| } | } | ||||
| } | } | ||||
| if (!updateExperiments.isEmpty()) { | if (!updateExperiments.isEmpty()) { | ||||
| experimentDao.insertOrUpdateBatch(updateExperiments); | experimentDao.insertOrUpdateBatch(updateExperiments); | ||||
| for (int index = 0; index < updateExperiments.size(); index++) { | |||||
| // 线程安全的删除操作 | |||||
| synchronized (experimentIds) { | |||||
| experimentIds.remove(index); | |||||
| // 使用Iterator进行安全的删除操作 | |||||
| Iterator<Integer> iterator = experimentIds.iterator(); | |||||
| while (iterator.hasNext()) { | |||||
| Integer experimentId = iterator.next(); | |||||
| for (Experiment experiment : updateExperiments) { | |||||
| if (experiment.getId().equals(experimentId)) { | |||||
| iterator.remove(); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,14 @@ | |||||
| package com.ruoyi.platform.service; | |||||
| import com.ruoyi.platform.vo.InsMetricInfoVo; | |||||
| import java.util.List; | |||||
| public interface AimService { | |||||
| List<InsMetricInfoVo> getExpTrainInfos(Integer experimentId) throws Exception; | |||||
| List<InsMetricInfoVo> getExpEvaluateInfos(Integer experimentId) throws Exception; | |||||
| String getExpMetrics(List<String> runIds) throws Exception; | |||||
| } | |||||
| @@ -1,6 +1,7 @@ | |||||
| package com.ruoyi.platform.service; | package com.ruoyi.platform.service; | ||||
| import com.ruoyi.platform.domain.DevEnvironment; | import com.ruoyi.platform.domain.DevEnvironment; | ||||
| import com.ruoyi.platform.vo.DevEnvironmentVo; | |||||
| import org.springframework.data.domain.Page; | import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.PageRequest; | import org.springframework.data.domain.PageRequest; | ||||
| @@ -35,7 +36,7 @@ public interface DevEnvironmentService { | |||||
| * @param devEnvironment 实例对象 | * @param devEnvironment 实例对象 | ||||
| * @return 实例对象 | * @return 实例对象 | ||||
| */ | */ | ||||
| DevEnvironment insert(DevEnvironment devEnvironment); | |||||
| DevEnvironment insert(DevEnvironmentVo devEnvironmentVo); | |||||
| /** | /** | ||||
| * 修改数据 | * 修改数据 | ||||
| @@ -1,6 +1,7 @@ | |||||
| package com.ruoyi.platform.service; | package com.ruoyi.platform.service; | ||||
| import com.ruoyi.platform.vo.FrameLogPathVo; | |||||
| import com.ruoyi.platform.domain.DevEnvironment; | |||||
| import com.ruoyi.platform.vo.PodStatusVo; | |||||
| import java.io.InputStream; | import java.io.InputStream; | ||||
| @@ -11,7 +12,9 @@ public interface JupyterService { | |||||
| void mlflow(); | void mlflow(); | ||||
| String runJupyterService(Integer id); | |||||
| String runJupyterService(Integer id) throws Exception; | |||||
| String stopJupyterService(Integer id) throws Exception; | String stopJupyterService(Integer id) throws Exception; | ||||
| PodStatusVo getJupyterStatus(DevEnvironment devEnvironment) throws Exception; | |||||
| } | } | ||||
| @@ -62,4 +62,8 @@ public interface ModelDependencyService { | |||||
| List<ModelDependency> queryByModelDependency(ModelDependency modelDependency) throws IOException; | List<ModelDependency> queryByModelDependency(ModelDependency modelDependency) throws IOException; | ||||
| ModelDependcyTreeVo getModelDependencyTree(ModelDependency modelDependency) throws Exception; | ModelDependcyTreeVo getModelDependencyTree(ModelDependency modelDependency) throws Exception; | ||||
| List<ModelDependency> queryByIns(Integer expInsId); | |||||
| ModelDependency queryByInsAndTrainTaskId(Integer expInsId, String taskId); | |||||
| } | } | ||||
| @@ -1,12 +1,12 @@ | |||||
| package com.ruoyi.platform.service; | package com.ruoyi.platform.service; | ||||
| import com.ruoyi.platform.vo.FrameLogPathVo; | import com.ruoyi.platform.vo.FrameLogPathVo; | ||||
| import com.ruoyi.platform.vo.TensorboardStatusVo; | |||||
| import com.ruoyi.platform.vo.PodStatusVo; | |||||
| public interface TensorBoardService { | public interface TensorBoardService { | ||||
| TensorboardStatusVo getTensorBoardStatus(FrameLogPathVo frameLogPathVo); | |||||
| PodStatusVo getTensorBoardStatus(FrameLogPathVo frameLogPathVo); | |||||
| /** | /** | ||||
| * 在集群中启动TensorBoard容器,并且返回地址,4小时后销毁 | * 在集群中启动TensorBoard容器,并且返回地址,4小时后销毁 | ||||
| * @param frameLogPathVo | * @param frameLogPathVo | ||||
| @@ -0,0 +1,158 @@ | |||||
| package com.ruoyi.platform.service.impl; | |||||
| import com.ruoyi.platform.domain.ExperimentIns; | |||||
| import com.ruoyi.platform.domain.ModelDependency; | |||||
| import com.ruoyi.platform.service.AimService; | |||||
| import com.ruoyi.platform.service.ExperimentInsService; | |||||
| import com.ruoyi.platform.service.ModelDependencyService; | |||||
| import com.ruoyi.platform.utils.AIM64EncoderUtil; | |||||
| import com.ruoyi.platform.utils.HttpUtils; | |||||
| import com.ruoyi.platform.utils.JacksonUtil; | |||||
| import com.ruoyi.platform.utils.JsonUtils; | |||||
| import com.ruoyi.platform.vo.InsMetricInfoVo; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.springframework.beans.factory.annotation.Value; | |||||
| import org.springframework.stereotype.Service; | |||||
| import javax.annotation.Resource; | |||||
| import java.net.URLEncoder; | |||||
| import java.util.*; | |||||
| import java.util.stream.Collectors; | |||||
| @Service | |||||
| public class AimServiceImpl implements AimService { | |||||
| @Resource | |||||
| private ExperimentInsService experimentInsService; | |||||
| @Value("${aim.url}") | |||||
| private String aimUrl; | |||||
| @Value("${aim.proxyUrl}") | |||||
| private String aimProxyUrl; | |||||
| @Override | |||||
| public List<InsMetricInfoVo> getExpTrainInfos(Integer experimentId) throws Exception { | |||||
| return getAimRunInfos(true,experimentId); | |||||
| } | |||||
| @Override | |||||
| public List<InsMetricInfoVo> getExpEvaluateInfos(Integer experimentId) throws Exception { | |||||
| return getAimRunInfos(false,experimentId); | |||||
| } | |||||
| @Override | |||||
| public String getExpMetrics(List<String> runIds) throws Exception { | |||||
| String decode = AIM64EncoderUtil.decode(runIds); | |||||
| return aimUrl+"/metrics?select="+decode; | |||||
| } | |||||
| private List<InsMetricInfoVo> getAimRunInfos(boolean isTrain,Integer experimentId) throws Exception { | |||||
| String experimentName = "experiment-"+experimentId+"-train"; | |||||
| if (!isTrain){ | |||||
| experimentName = "experiment-"+experimentId+"-evaluate"; | |||||
| } | |||||
| String encodedUrlString = URLEncoder.encode("run.experiment==\""+experimentName+"\"", "UTF-8"); | |||||
| String url = aimProxyUrl+"/api/runs/search/run?query="+encodedUrlString; | |||||
| String s = HttpUtils.sendGetRequest(url); | |||||
| List<Map<String, Object>> response = JacksonUtil.parseJSONStr2MapList(s); | |||||
| System.out.println("response: "+JacksonUtil.toJSONString(response)); | |||||
| if (response == null || response.size() == 0){ | |||||
| return new ArrayList<>(); | |||||
| } | |||||
| //查询实例数据 | |||||
| List<ExperimentIns> byExperimentId = experimentInsService.queryByExperimentId(experimentId); | |||||
| if (byExperimentId == null || byExperimentId.size() == 0){ | |||||
| return new ArrayList<>(); | |||||
| } | |||||
| List<InsMetricInfoVo> aimRunInfoList = new ArrayList<>(); | |||||
| for (Map<String, Object> run : response) { | |||||
| InsMetricInfoVo aimRunInfo = new InsMetricInfoVo(); | |||||
| String runHash = (String) run.get("run_hash"); | |||||
| aimRunInfo.setRunId(runHash); | |||||
| Map params= (Map) run.get("params"); | |||||
| Map<String, Object> paramMap = JsonUtils.flattenJson("", params); | |||||
| aimRunInfo.setParams(paramMap); | |||||
| String aimrunId = (String) paramMap.get("id"); | |||||
| Map<String, Object> tracesMap= (Map<String, Object>) run.get("traces"); | |||||
| List<Map<String, Object>> metricList = (List<Map<String, Object>>) tracesMap.get("metric"); | |||||
| //过滤name为__system__开头的对象 | |||||
| aimRunInfo.setMetrics(new HashMap<>()); | |||||
| if (metricList != null && metricList.size() > 0){ | |||||
| List<Map<String, Object>> metricRelList = metricList.stream() | |||||
| .filter(map -> !StringUtils.startsWith((String) map.get("name"),"__system__" )) | |||||
| .collect(Collectors.toList()); | |||||
| if (metricRelList!= null && metricRelList.size() > 0){ | |||||
| Map<String, Object> relMetricMap = new HashMap<>(); | |||||
| for (Map<String, Object> metricMap : metricRelList) { | |||||
| relMetricMap.put((String)metricMap.get("name"), metricMap.get("last_value")); | |||||
| } | |||||
| aimRunInfo.setMetrics(relMetricMap); | |||||
| } | |||||
| } | |||||
| //找到ins | |||||
| for (ExperimentIns ins : byExperimentId) { | |||||
| String metricRecordString = ins.getMetricRecord(); | |||||
| if (StringUtils.isEmpty(metricRecordString)){ | |||||
| continue; | |||||
| } | |||||
| if (metricRecordString.contains(aimrunId)){ | |||||
| aimRunInfo.setExperimentInsId(ins.getId()); | |||||
| aimRunInfo.setStatus(ins.getStatus()); | |||||
| aimRunInfo.setStartTime(ins.getCreateTime()); | |||||
| Map<String, Object> metricRecordMap = JacksonUtil.parseJSONStr2Map(metricRecordString); | |||||
| if (isTrain){ | |||||
| List<Map<String, Object>> records = (List<Map<String, Object>>) metricRecordMap.get("train"); | |||||
| List<String> datasetList = getTrainDateSet(records, aimrunId); | |||||
| aimRunInfo.setDataset(datasetList); | |||||
| }else { | |||||
| List<Map<String, Object>> records = (List<Map<String, Object>>) metricRecordMap.get("evaluate"); | |||||
| List<String> datasetList = getTrainDateSet(records, aimrunId); | |||||
| aimRunInfo.setDataset(datasetList); | |||||
| } | |||||
| aimRunInfoList.add(aimRunInfo); | |||||
| } | |||||
| } | |||||
| } | |||||
| //判断哪个最长 | |||||
| // 获取所有 metrics 的 key 的并集 | |||||
| Set<String> metricsKeys = (Set<String>) aimRunInfoList.stream() | |||||
| .map(InsMetricInfoVo::getMetrics) | |||||
| .flatMap(metrics -> metrics.keySet().stream()) | |||||
| .collect(Collectors.toSet()); | |||||
| // 将并集赋值给每个 InsMetricInfoVo 的 metricsNames 属性 | |||||
| aimRunInfoList.forEach(vo -> vo.setMetricsNames(new ArrayList<>(metricsKeys))); | |||||
| // 获取所有 params 的 key 的并集 | |||||
| Set<String> paramKeys = (Set<String>) aimRunInfoList.stream() | |||||
| .map(InsMetricInfoVo::getParams) | |||||
| .flatMap(params -> params.keySet().stream()) | |||||
| .collect(Collectors.toSet()); | |||||
| // 将并集赋值给每个 InsMetricInfoVo 的 paramsNames 属性 | |||||
| aimRunInfoList.forEach(vo -> vo.setParamsNames(new ArrayList<>(paramKeys))); | |||||
| return aimRunInfoList; | |||||
| } | |||||
| private List<String> getTrainDateSet(List<Map<String, Object>> records, String aimrunId){ | |||||
| List<String> datasetList = new ArrayList<>(); | |||||
| for (Map<String, Object> record : records) { | |||||
| if (StringUtils.equals(aimrunId, (String)record.get("run_id"))) { | |||||
| List<Map<String, Object>> datasets = (List<Map<String, Object>>) record.get("datasets"); | |||||
| if (datasets == null || datasets.size() == 0){ | |||||
| continue; | |||||
| } | |||||
| for (Map<String, Object> dataset : datasets){ | |||||
| String datasetName = (String) dataset.get("dataset_name")+":"+(String) dataset.get("dataset_version"); | |||||
| datasetList.add(datasetName); | |||||
| } | |||||
| break; | |||||
| } | |||||
| } | |||||
| return datasetList; | |||||
| } | |||||
| } | |||||
| @@ -240,7 +240,7 @@ public class DatasetVersionServiceImpl implements DatasetVersionService { | |||||
| datasetVersion.setFileName(dataset.getName()+"_"+labelDatasetVersionVo.getVersion()+"."+labelDatasetVersionVo.getExportType()); | datasetVersion.setFileName(dataset.getName()+"_"+labelDatasetVersionVo.getVersion()+"."+labelDatasetVersionVo.getExportType()); | ||||
| datasetVersion.setFileSize(formattedSize); | datasetVersion.setFileSize(formattedSize); | ||||
| datasetVersion.setUrl(url); | |||||
| datasetVersion.setUrl(objectName); | |||||
| datasetVersion.setDescription(labelDatasetVersionVo.getDesc()); | datasetVersion.setDescription(labelDatasetVersionVo.getDesc()); | ||||
| this.insert(datasetVersion); | this.insert(datasetVersion); | ||||
| } | } | ||||
| @@ -2,13 +2,17 @@ package com.ruoyi.platform.service.impl; | |||||
| import com.ruoyi.common.security.utils.SecurityUtils; | import com.ruoyi.common.security.utils.SecurityUtils; | ||||
| import com.ruoyi.platform.domain.DevEnvironment; | import com.ruoyi.platform.domain.DevEnvironment; | ||||
| import com.ruoyi.platform.domain.PodStatus; | |||||
| import com.ruoyi.platform.mapper.DevEnvironmentDao; | import com.ruoyi.platform.mapper.DevEnvironmentDao; | ||||
| import com.ruoyi.platform.service.DevEnvironmentService; | import com.ruoyi.platform.service.DevEnvironmentService; | ||||
| import com.ruoyi.platform.service.JupyterService; | import com.ruoyi.platform.service.JupyterService; | ||||
| import com.ruoyi.platform.utils.JacksonUtil; | import com.ruoyi.platform.utils.JacksonUtil; | ||||
| import com.ruoyi.platform.vo.DevEnvironmentVo; | |||||
| import com.ruoyi.platform.vo.PodStatusVo; | |||||
| import com.ruoyi.system.api.model.LoginUser; | import com.ruoyi.system.api.model.LoginUser; | ||||
| import io.kubernetes.client.openapi.models.V1PersistentVolumeClaim; | import io.kubernetes.client.openapi.models.V1PersistentVolumeClaim; | ||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| import org.springframework.context.annotation.Lazy; | |||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
| import org.springframework.data.domain.Page; | import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.PageImpl; | import org.springframework.data.domain.PageImpl; | ||||
| @@ -16,6 +20,7 @@ import org.springframework.data.domain.PageRequest; | |||||
| import javax.annotation.Resource; | import javax.annotation.Resource; | ||||
| import java.util.Date; | import java.util.Date; | ||||
| import java.util.List; | |||||
| import java.util.Map; | import java.util.Map; | ||||
| /** | /** | ||||
| @@ -29,8 +34,8 @@ public class DevEnvironmentServiceImpl implements DevEnvironmentService { | |||||
| @Resource | @Resource | ||||
| private DevEnvironmentDao devEnvironmentDao; | private DevEnvironmentDao devEnvironmentDao; | ||||
| @Resource | @Resource | ||||
| @Lazy | |||||
| private JupyterService jupyterService; | private JupyterService jupyterService; | ||||
| @@ -55,23 +60,53 @@ public class DevEnvironmentServiceImpl implements DevEnvironmentService { | |||||
| @Override | @Override | ||||
| public Page<DevEnvironment> queryByPage(DevEnvironment devEnvironment, PageRequest pageRequest) { | public Page<DevEnvironment> queryByPage(DevEnvironment devEnvironment, PageRequest pageRequest) { | ||||
| long total = this.devEnvironmentDao.count(devEnvironment); | long total = this.devEnvironmentDao.count(devEnvironment); | ||||
| return new PageImpl<>(this.devEnvironmentDao.queryAllByLimit(devEnvironment, pageRequest), pageRequest, total); | |||||
| List<DevEnvironment> devEnvironmentList = this.devEnvironmentDao.queryAllByLimit(devEnvironment, pageRequest); | |||||
| //查询每个开发环境的pod状态,注意:只有pod为非终止态时才去调状态接口 | |||||
| devEnvironmentList.forEach(devEnv -> { | |||||
| try{ | |||||
| if (!devEnv.getStatus().equals(PodStatus.Terminated.getName()) && | |||||
| !devEnv.getStatus().equals(PodStatus.Failed.getName())) { | |||||
| PodStatusVo podStatusVo = this.jupyterService.getJupyterStatus(devEnv); | |||||
| devEnv.setStatus(podStatusVo.getStatus()); | |||||
| devEnv.setUrl(podStatusVo.getUrl()); | |||||
| } | |||||
| } catch (Exception e) { | |||||
| devEnv.setStatus(PodStatus.Unknown.getName()); | |||||
| } | |||||
| }); | |||||
| return new PageImpl<>(devEnvironmentList, pageRequest, total); | |||||
| } | } | ||||
| /** | /** | ||||
| * 新增数据 | * 新增数据 | ||||
| * | * | ||||
| * @param devEnvironment 实例对象 | |||||
| * @param devEnvironmentVo 实例对象 | |||||
| * @return 实例对象 | * @return 实例对象 | ||||
| */ | */ | ||||
| @Override | @Override | ||||
| public DevEnvironment insert(DevEnvironment devEnvironment) { | |||||
| public DevEnvironment insert(DevEnvironmentVo devEnvironmentVo) { | |||||
| //插入预备,此时不需要判断版本重复 | //插入预备,此时不需要判断版本重复 | ||||
| DevEnvironment devEnvironment = new DevEnvironment(); | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| devEnvironment.setName(devEnvironmentVo.getName()); | |||||
| //状态先设为未知 | |||||
| devEnvironment.setStatus("Unknown"); | |||||
| devEnvironment.setComputingResource(devEnvironmentVo.getComputingResource()); | |||||
| devEnvironment.setStandard(devEnvironmentVo.getStandard()); | |||||
| devEnvironment.setEnvVariable(devEnvironmentVo.getEnvVariable()); | |||||
| devEnvironment.setImage(devEnvironmentVo.getImage()); | |||||
| // 将 dataset 和 model 转换成 JSON 字符串 | |||||
| String datasetJson = JacksonUtil.toJSONString(devEnvironmentVo.getDataset()); | |||||
| String modelJson = JacksonUtil.toJSONString(devEnvironmentVo.getModel()); | |||||
| devEnvironment.setDataset(datasetJson); | |||||
| devEnvironment.setModel(modelJson); | |||||
| devEnvironment.setCreateBy(loginUser.getUsername()); | devEnvironment.setCreateBy(loginUser.getUsername()); | ||||
| devEnvironment.setUpdateBy(loginUser.getUsername()); | devEnvironment.setUpdateBy(loginUser.getUsername()); | ||||
| devEnvironment.setUpdateTime(new Date()); | devEnvironment.setUpdateTime(new Date()); | ||||
| devEnvironment.setCreateTime(new Date()); | devEnvironment.setCreateTime(new Date()); | ||||
| devEnvironment.setState(1); | |||||
| this.devEnvironmentDao.insert(devEnvironment); | this.devEnvironmentDao.insert(devEnvironment); | ||||
| return devEnvironment; | return devEnvironment; | ||||
| } | } | ||||
| @@ -102,7 +102,6 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { | |||||
| */ | */ | ||||
| @Override | @Override | ||||
| public List<ExperimentIns> getByExperimentId(Integer experimentId) throws IOException { | public List<ExperimentIns> getByExperimentId(Integer experimentId) throws IOException { | ||||
| List<ExperimentIns> experimentInsList = experimentInsDao.getByExperimentId(experimentId); | |||||
| //代码全部迁移至定时任务 | //代码全部迁移至定时任务 | ||||
| //搞个标记,当状态改变才去改表 | //搞个标记,当状态改变才去改表 | ||||
| @@ -138,7 +137,7 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { | |||||
| // experimentDao.update(experiment); | // experimentDao.update(experiment); | ||||
| // } | // } | ||||
| return experimentInsList; | |||||
| return experimentInsDao.getByExperimentId(experimentId); | |||||
| } | } | ||||
| @@ -251,9 +251,14 @@ public class ExperimentServiceImpl implements ExperimentService { | |||||
| if (data == null || MapUtils.isEmpty(data)) { | if (data == null || MapUtils.isEmpty(data)) { | ||||
| throw new RuntimeException("Failed to run workflow."); | throw new RuntimeException("Failed to run workflow."); | ||||
| } | } | ||||
| Map<String, Object> metadata = (Map<String, Object>) data.get("metadata"); | Map<String, Object> metadata = (Map<String, Object>) data.get("metadata"); | ||||
| // 插入记录到实验实例表 | // 插入记录到实验实例表 | ||||
| ExperimentIns experimentIns = new ExperimentIns(); | ExperimentIns experimentIns = new ExperimentIns(); | ||||
| //获取训练参数 | |||||
| experimentIns.setExperimentId(experiment.getId()); | experimentIns.setExperimentId(experiment.getId()); | ||||
| experimentIns.setArgoInsNs((String) metadata.get("namespace")); | experimentIns.setArgoInsNs((String) metadata.get("namespace")); | ||||
| experimentIns.setArgoInsName((String) metadata.get("name")); | experimentIns.setArgoInsName((String) metadata.get("name")); | ||||
| @@ -264,16 +269,25 @@ public class ExperimentServiceImpl implements ExperimentService { | |||||
| //替换argoInsName | //替换argoInsName | ||||
| String outputString = JsonUtils.mapToJson(output); | String outputString = JsonUtils.mapToJson(output); | ||||
| experimentIns.setNodesResult(outputString.replace("{{workflow.name}}", (String) metadata.get("name"))); | experimentIns.setNodesResult(outputString.replace("{{workflow.name}}", (String) metadata.get("name"))); | ||||
| //插入ExperimentIns表中 | |||||
| ExperimentIns insert = experimentInsService.insert(experimentIns); | |||||
| //插入到模型依赖关系表 | |||||
| //得到dependendcy | //得到dependendcy | ||||
| Map<String, Object> converMap2 = JsonUtils.jsonToMap(JacksonUtil.replaceInAarry(convertRes, params)); | Map<String, Object> converMap2 = JsonUtils.jsonToMap(JacksonUtil.replaceInAarry(convertRes, params)); | ||||
| Map<String ,Object> dependendcy = (Map<String, Object>)converMap2.get("model_dependency"); | Map<String ,Object> dependendcy = (Map<String, Object>)converMap2.get("model_dependency"); | ||||
| Map<String ,Object> trainInfo = (Map<String, Object>)converMap2.get("component_info"); | Map<String ,Object> trainInfo = (Map<String, Object>)converMap2.get("component_info"); | ||||
| insertModelDependency(dependendcy,trainInfo,insert.getId(),experiment.getName()); | |||||
| Map<String, Object> metricRecord = (Map<String, Object>) runResMap.get("metric_record"); | |||||
| if (metricRecord != null){ | |||||
| //把训练用的数据集也放进去 | |||||
| addDatesetToMetric(metricRecord, trainInfo); | |||||
| experimentIns.setMetricRecord(JacksonUtil.toJSONString(metricRecord)); | |||||
| } | |||||
| //插入ExperimentIns表中 | |||||
| ExperimentIns insert = experimentInsService.insert(experimentIns); | |||||
| //插入到模型依赖关系表 | |||||
| if (dependendcy != null && trainInfo != null){ | |||||
| insertModelDependency(dependendcy,trainInfo,insert.getId(),experiment.getName()); | |||||
| } | |||||
| }catch (Exception e){ | }catch (Exception e){ | ||||
| throw new RuntimeException(e); | throw new RuntimeException(e); | ||||
| } | } | ||||
| @@ -281,6 +295,37 @@ public class ExperimentServiceImpl implements ExperimentService { | |||||
| experiment.setExperimentInsList(updatedExperimentInsList); | experiment.setExperimentInsList(updatedExperimentInsList); | ||||
| return experiment; | return experiment; | ||||
| } | } | ||||
| private void addDatesetToMetric(Map<String, Object> metricRecord, Map<String, Object> trainInfo) { | |||||
| processMetricPart(metricRecord, trainInfo, "train", "model_train"); | |||||
| processMetricPart(metricRecord, trainInfo, "evaluate", "model_evaluate"); | |||||
| } | |||||
| private void processMetricPart(Map<String, Object> metricRecord, Map<String, Object> trainInfo, String metricKey, String trainInfoKey) { | |||||
| List<Map<String, Object>> metricList = (List<Map<String, Object>>) metricRecord.get(metricKey); | |||||
| if (metricList != null) { | |||||
| for (Map<String, Object> metricRecordItem : metricList) { | |||||
| String taskId = (String) metricRecordItem.get("task_id"); | |||||
| Map<String, Object> trainInfoPart = (Map<String, Object>) trainInfo.get(trainInfoKey); | |||||
| if (trainInfoPart != null) { | |||||
| Map<String, Object> trainInfoDetails = (Map<String, Object>) trainInfoPart.get(taskId); | |||||
| if (trainInfoDetails != null) { | |||||
| List<Map<String, Object>> datasets = (List<Map<String, Object>>) trainInfoDetails.get("datasets"); | |||||
| if (datasets != null) { | |||||
| //查询名字再回填 | |||||
| for (int i = 0; i < datasets.size(); i++) { | |||||
| Dataset dataset = datasetService.queryById((Integer) datasets.get(i).get("dataset_id")); | |||||
| datasets.get(i).put("dataset_name", dataset.getName()); | |||||
| } | |||||
| metricRecordItem.put("datasets", datasets); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| private void insertModelDependency(Map<String ,Object> dependendcy,Map<String ,Object> trainInfo, Integer experimentInsId, String experimentName) throws Exception { | private void insertModelDependency(Map<String ,Object> dependendcy,Map<String ,Object> trainInfo, Integer experimentInsId, String experimentName) throws Exception { | ||||
| Iterator<Map.Entry<String, Object>> dependendcyIterator = dependendcy.entrySet().iterator(); | Iterator<Map.Entry<String, Object>> dependendcyIterator = dependendcy.entrySet().iterator(); | ||||
| Map<String, Object> modelTrain = (Map<String, Object>) trainInfo.get("model_train"); | Map<String, Object> modelTrain = (Map<String, Object>) trainInfo.get("model_train"); | ||||
| @@ -3,6 +3,7 @@ package com.ruoyi.platform.service.impl; | |||||
| import com.ruoyi.common.redis.service.RedisService; | import com.ruoyi.common.redis.service.RedisService; | ||||
| import com.ruoyi.common.security.utils.SecurityUtils; | import com.ruoyi.common.security.utils.SecurityUtils; | ||||
| import com.ruoyi.platform.domain.DevEnvironment; | import com.ruoyi.platform.domain.DevEnvironment; | ||||
| import com.ruoyi.platform.domain.PodStatus; | |||||
| import com.ruoyi.platform.mapper.DevEnvironmentDao; | import com.ruoyi.platform.mapper.DevEnvironmentDao; | ||||
| import com.ruoyi.platform.service.DevEnvironmentService; | import com.ruoyi.platform.service.DevEnvironmentService; | ||||
| import com.ruoyi.platform.service.JupyterService; | import com.ruoyi.platform.service.JupyterService; | ||||
| @@ -10,9 +11,12 @@ import com.ruoyi.platform.utils.JacksonUtil; | |||||
| import com.ruoyi.platform.utils.K8sClientUtil; | import com.ruoyi.platform.utils.K8sClientUtil; | ||||
| import com.ruoyi.platform.utils.MinioUtil; | import com.ruoyi.platform.utils.MinioUtil; | ||||
| import com.ruoyi.platform.utils.MlflowUtil; | import com.ruoyi.platform.utils.MlflowUtil; | ||||
| import com.ruoyi.platform.vo.PodStatusVo; | |||||
| import com.ruoyi.system.api.model.LoginUser; | import com.ruoyi.system.api.model.LoginUser; | ||||
| import io.kubernetes.client.openapi.models.V1PersistentVolumeClaim; | import io.kubernetes.client.openapi.models.V1PersistentVolumeClaim; | ||||
| import io.kubernetes.client.openapi.models.V1Pod; | |||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.context.annotation.Lazy; | |||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
| import javax.annotation.Resource; | import javax.annotation.Resource; | ||||
| @@ -37,6 +41,8 @@ public class JupyterServiceImpl implements JupyterService { | |||||
| private String masterIp; | private String masterIp; | ||||
| @Value("${k8s.storageClassName}") | @Value("${k8s.storageClassName}") | ||||
| private String storageClassName; | private String storageClassName; | ||||
| @Value("${minio.pvcName}") | |||||
| private String minioPvcName; | |||||
| private final MinioUtil minioUtil; | private final MinioUtil minioUtil; | ||||
| @@ -49,6 +55,7 @@ public class JupyterServiceImpl implements JupyterService { | |||||
| private DevEnvironmentDao devEnvironmentDao; | private DevEnvironmentDao devEnvironmentDao; | ||||
| @Resource | @Resource | ||||
| @Lazy | |||||
| private DevEnvironmentService devEnvironmentService; | private DevEnvironmentService devEnvironmentService; | ||||
| @Resource | @Resource | ||||
| @@ -69,10 +76,11 @@ public class JupyterServiceImpl implements JupyterService { | |||||
| } | } | ||||
| @Override | @Override | ||||
| public String runJupyterService(Integer id) { | |||||
| public String runJupyterService(Integer id) throws Exception { | |||||
| DevEnvironment devEnvironment = this.devEnvironmentDao.queryById(id); | DevEnvironment devEnvironment = this.devEnvironmentDao.queryById(id); | ||||
| String envName = devEnvironment.getName(); | |||||
| //TODO 设置环境变量 | |||||
| if(devEnvironment == null){ | |||||
| throw new Exception("开发环境配置不存在"); | |||||
| } | |||||
| // 提取数据集,模型信息,得到数据集模型的path | // 提取数据集,模型信息,得到数据集模型的path | ||||
| Map<String, Object> dataset = JacksonUtil.parseJSONStr2Map(devEnvironment.getDataset()); | Map<String, Object> dataset = JacksonUtil.parseJSONStr2Map(devEnvironment.getDataset()); | ||||
| @@ -81,16 +89,26 @@ public class JupyterServiceImpl implements JupyterService { | |||||
| String modelPath = (String) model.get("path"); | String modelPath = (String) model.get("path"); | ||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String podName = loginUser.getUsername().toLowerCase() + "-editor-pod"; | |||||
| //手动构造pod名称 | |||||
| String podName = loginUser.getUsername().toLowerCase() +"-editor-pod" + "-" + id; | |||||
| String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc"; | String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc"; | ||||
| //新建编辑器的pvc | |||||
| V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName); | V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName); | ||||
| //TODO 设置镜像可配置,这里先用默认镜像启动pod | //TODO 设置镜像可配置,这里先用默认镜像启动pod | ||||
| // 调用修改后的 createPod 方法,传入额外的参数 | // 调用修改后的 createPod 方法,传入额外的参数 | ||||
| Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, pvc, image, datasetPath, modelPath); | |||||
| return masterIp + ":" + podPort; | |||||
| Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, pvc, image, minioPvcName, datasetPath, modelPath); | |||||
| // // 简单的延迟,以便 Pod 有时间启动 | |||||
| // Thread.sleep(2500); | |||||
| // //查询pod状态,更新到数据库 | |||||
| // String podStatus = k8sClientUtil.getPodStatus(podName, namespace); | |||||
| String url = masterIp + ":" + podPort; | |||||
| redisService.setCacheObject(podName,masterIp + ":" + podPort); | |||||
| devEnvironment.setStatus("Pending"); | |||||
| devEnvironment.setUrl(url); | |||||
| this.devEnvironmentService.update(devEnvironment); | |||||
| return url ; | |||||
| } | } | ||||
| @@ -100,21 +118,54 @@ public class JupyterServiceImpl implements JupyterService { | |||||
| if (devEnvironment==null){ | if (devEnvironment==null){ | ||||
| throw new Exception("开发环境配置不存在"); | throw new Exception("开发环境配置不存在"); | ||||
| } | } | ||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String podName = loginUser.getUsername().toLowerCase() + "-editor-pod"; | |||||
| //手动构造pod名称 | |||||
| String podName = loginUser.getUsername().toLowerCase() +"-editor-pod" + "-" + id; | |||||
| //得到pod | |||||
| V1Pod pod = k8sClientUtil.getNSPodList(namespace, podName); | |||||
| if(pod == null){ | |||||
| return "pod不存在!"; | |||||
| } | |||||
| // 使用 Kubernetes API 删除 Pod | // 使用 Kubernetes API 删除 Pod | ||||
| String deleteResult = k8sClientUtil.deletePod(podName, namespace); | String deleteResult = k8sClientUtil.deletePod(podName, namespace); | ||||
| // 检查 Pod 是否存在 | |||||
| boolean exists = k8sClientUtil.checkPodExists(podName, namespace); | |||||
| if (exists) { | |||||
| throw new Exception("Pod " + podName + " 删除失败"); | |||||
| } | |||||
| devEnvironment.setStatus("Terminated"); | |||||
| this.devEnvironmentService.update(devEnvironment); | |||||
| return deleteResult + ",编辑器已停止"; | return deleteResult + ",编辑器已停止"; | ||||
| } | } | ||||
| @Override | |||||
| public PodStatusVo getJupyterStatus(DevEnvironment devEnvironment) throws Exception { | |||||
| String status = PodStatus.Terminated.getName(); | |||||
| PodStatusVo JupyterStatusVo = new PodStatusVo(); | |||||
| JupyterStatusVo.setStatus(status); | |||||
| if (devEnvironment==null){ | |||||
| return JupyterStatusVo; | |||||
| } | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||||
| String podName = loginUser.getUsername().toLowerCase() +"-editor-pod" + "-" + devEnvironment.getId(); | |||||
| try { | |||||
| // 查询相应pod状态 | |||||
| String podStatus = k8sClientUtil.getPodStatus(podName, namespace); | |||||
| for (PodStatus s : PodStatus.values()) { | |||||
| if (s.getName().equals(podStatus)) { | |||||
| status = s.getName(); | |||||
| break; | |||||
| } | |||||
| } | |||||
| } catch (Exception e) { | |||||
| return JupyterStatusVo; | |||||
| } | |||||
| String url = redisService.getCacheObject(podName); | |||||
| JupyterStatusVo.setStatus(status); | |||||
| JupyterStatusVo.setUrl(url); | |||||
| return JupyterStatusVo; | |||||
| } | |||||
| @Override | @Override | ||||
| public void upload(InputStream inputStream) { | public void upload(InputStream inputStream) { | ||||
| @@ -136,4 +187,5 @@ public class JupyterServiceImpl implements JupyterService { | |||||
| } | } | ||||
| @@ -17,10 +17,7 @@ import org.springframework.data.domain.PageRequest; | |||||
| import javax.annotation.Resource; | import javax.annotation.Resource; | ||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.util.ArrayList; | |||||
| import java.util.Date; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| import java.util.*; | |||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||
| /** | /** | ||||
| @@ -97,6 +94,16 @@ public class ModelDependencyServiceImpl implements ModelDependencyService { | |||||
| return modelDependcyTreeVo; | return modelDependcyTreeVo; | ||||
| } | } | ||||
| @Override | |||||
| public List<ModelDependency> queryByIns(Integer expInsId) { | |||||
| return modelDependencyDao.queryByIns(expInsId); | |||||
| } | |||||
| @Override | |||||
| public ModelDependency queryByInsAndTrainTaskId(Integer expInsId, String taskId) { | |||||
| return modelDependencyDao.queryByInsAndTrainTaskId(expInsId,taskId); | |||||
| } | |||||
| /** | /** | ||||
| * 递归父模型 | * 递归父模型 | ||||
| * @param modelDependcyTreeVo | * @param modelDependcyTreeVo | ||||
| @@ -167,8 +174,6 @@ public class ModelDependencyServiceImpl implements ModelDependencyService { | |||||
| modelsVersionquery.setModelsId(currentModelId); | modelsVersionquery.setModelsId(currentModelId); | ||||
| modelsVersionquery.setVersion(modelDependency.getVersion()); | modelsVersionquery.setVersion(modelDependency.getVersion()); | ||||
| ModelsVersion modelsVersion = modelsVersionService.queryByModelsVersion(modelsVersionquery); | ModelsVersion modelsVersion = modelsVersionService.queryByModelsVersion(modelsVersionquery); | ||||
| ExperimentIns experimentIns = experimentInsService.queryById(expInsId); | |||||
| Experiment experiment = experimentService.queryById(experimentIns.getExperimentId()); | |||||
| ModelVersionDependcyVo modelVersionDependcyVo = new ModelVersionDependcyVo(); | ModelVersionDependcyVo modelVersionDependcyVo = new ModelVersionDependcyVo(); | ||||
| modelVersionDependcyVo.setName(models.getName()); | modelVersionDependcyVo.setName(models.getName()); | ||||
| modelVersionDependcyVo.setAvailableRange(models.getAvailableRange()); | modelVersionDependcyVo.setAvailableRange(models.getAvailableRange()); | ||||
| @@ -180,9 +185,18 @@ public class ModelDependencyServiceImpl implements ModelDependencyService { | |||||
| modelVersionDependcyVo.setFileName(modelsVersion.getFileName()); | modelVersionDependcyVo.setFileName(modelsVersion.getFileName()); | ||||
| modelVersionDependcyVo.setFileSize(modelsVersion.getFileSize()); | modelVersionDependcyVo.setFileSize(modelsVersion.getFileSize()); | ||||
| modelVersionDependcyVo.setUrl(modelsVersion.getUrl()); | modelVersionDependcyVo.setUrl(modelsVersion.getUrl()); | ||||
| modelDependcyTreeVo.setWorkflowId(experiment.getWorkflowId()); | |||||
| modelVersionDependcyVo.setCreateBy(modelsVersion.getCreateBy()); | |||||
| modelVersionDependcyVo.setCreateTime(modelsVersion.getCreateTime()); | |||||
| modelDependcyTreeVo.setModelVersionDependcyVo(modelVersionDependcyVo); | modelDependcyTreeVo.setModelVersionDependcyVo(modelVersionDependcyVo); | ||||
| ExperimentIns experimentIns = experimentInsService.queryById(expInsId); | |||||
| if (experimentIns == null){ | |||||
| return modelDependcyTreeVo; | |||||
| } | |||||
| Experiment experiment = experimentService.queryById(experimentIns.getExperimentId()); | |||||
| if (experiment == null){ | |||||
| return modelDependcyTreeVo; | |||||
| } | |||||
| modelDependcyTreeVo.setWorkflowId(experiment.getWorkflowId()); | |||||
| return modelDependcyTreeVo; | return modelDependcyTreeVo; | ||||
| } | } | ||||
| @@ -227,8 +227,8 @@ public class ModelsVersionServiceImpl implements ModelsVersionService { | |||||
| for(ModelsVersion modelsVersion : modelsVersions) { | for(ModelsVersion modelsVersion : modelsVersions) { | ||||
| insertPrepare(modelsVersion); | insertPrepare(modelsVersion); | ||||
| } | } | ||||
| insertModelsDependency(modelsVersions.get(0)); | |||||
| this.modelsVersionDao.insertBatch(modelsVersions); | this.modelsVersionDao.insertBatch(modelsVersions); | ||||
| insertModelsDependency(modelsVersions.get(0)); | |||||
| return "新增模型版本成功"; | return "新增模型版本成功"; | ||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| // 如果出现异常,返回异常消息 | // 如果出现异常,返回异常消息 | ||||
| @@ -7,7 +7,7 @@ import com.ruoyi.platform.domain.PodStatus; | |||||
| import com.ruoyi.platform.service.TensorBoardService; | import com.ruoyi.platform.service.TensorBoardService; | ||||
| import com.ruoyi.platform.utils.K8sClientUtil; | import com.ruoyi.platform.utils.K8sClientUtil; | ||||
| import com.ruoyi.platform.vo.FrameLogPathVo; | import com.ruoyi.platform.vo.FrameLogPathVo; | ||||
| import com.ruoyi.platform.vo.TensorboardStatusVo; | |||||
| import com.ruoyi.platform.vo.PodStatusVo; | |||||
| import com.ruoyi.system.api.model.LoginUser; | import com.ruoyi.system.api.model.LoginUser; | ||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
| @@ -29,9 +29,9 @@ public class TensorBoardServiceImpl implements TensorBoardService { | |||||
| @Resource | @Resource | ||||
| private K8sClientUtil k8sClientUtil; | private K8sClientUtil k8sClientUtil; | ||||
| @Override | @Override | ||||
| public TensorboardStatusVo getTensorBoardStatus(FrameLogPathVo frameLogPathVo){ | |||||
| public PodStatusVo getTensorBoardStatus(FrameLogPathVo frameLogPathVo){ | |||||
| String status = PodStatus.Terminated.getName(); | String status = PodStatus.Terminated.getName(); | ||||
| TensorboardStatusVo tensorboardStatusVo = new TensorboardStatusVo(); | |||||
| PodStatusVo tensorboardStatusVo = new PodStatusVo(); | |||||
| tensorboardStatusVo.setStatus(status); | tensorboardStatusVo.setStatus(status); | ||||
| if (StringUtils.isEmpty(frameLogPathVo.getPath())){ | if (StringUtils.isEmpty(frameLogPathVo.getPath())){ | ||||
| return tensorboardStatusVo; | return tensorboardStatusVo; | ||||
| @@ -133,7 +133,9 @@ public class WorkflowServiceImpl implements WorkflowService { | |||||
| public String removeById(Long id) throws Exception { | public String removeById(Long id) throws Exception { | ||||
| //先根据id提取出对应的流水线 | //先根据id提取出对应的流水线 | ||||
| Workflow workflow = workflowDao.queryById(id); | Workflow workflow = workflowDao.queryById(id); | ||||
| if (workflow == null){ | |||||
| throw new Exception("流水线不存在"); | |||||
| } | |||||
| //判断权限,只有admin和创建者本身可以删除该流水线 | //判断权限,只有admin和创建者本身可以删除该流水线 | ||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String username = loginUser.getUsername(); | String username = loginUser.getUsername(); | ||||
| @@ -142,9 +144,6 @@ public class WorkflowServiceImpl implements WorkflowService { | |||||
| throw new Exception("无权限删除该流水线"); | throw new Exception("无权限删除该流水线"); | ||||
| } | } | ||||
| if (workflow == null){ | |||||
| throw new Exception("流水线不存在"); | |||||
| } | |||||
| //判断这个流水线是否有相关实验存在 | //判断这个流水线是否有相关实验存在 | ||||
| List<Experiment> experimentList = experimentService.queryByWorkflowId(id); | List<Experiment> experimentList = experimentService.queryByWorkflowId(id); | ||||
| if (experimentList!=null&&experimentList.size()>0){ | if (experimentList!=null&&experimentList.size()>0){ | ||||
| @@ -0,0 +1,76 @@ | |||||
| package com.ruoyi.platform.utils; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import java.util.Base64; | |||||
| import java.util.HashMap; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| public class AIM64EncoderUtil { | |||||
| private static final String AIM64_ENCODING_PREFIX = "O-"; | |||||
| private static final Map<String, String> BS64_REPLACE_CHARACTERS_ENCODING = new HashMap<>(); | |||||
| static { | |||||
| BS64_REPLACE_CHARACTERS_ENCODING.put("=", ""); | |||||
| BS64_REPLACE_CHARACTERS_ENCODING.put("+", "-"); | |||||
| BS64_REPLACE_CHARACTERS_ENCODING.put("/", "_"); | |||||
| } | |||||
| public static String aim64encode(Map<String, Object> value) { | |||||
| String jsonEncoded = JSON.toJSONString(value); | |||||
| String base64Encoded = Base64.getEncoder().encodeToString(jsonEncoded.getBytes()); | |||||
| String aim64Encoded = base64Encoded; | |||||
| for (Map.Entry<String, String> entry : BS64_REPLACE_CHARACTERS_ENCODING.entrySet()) { | |||||
| aim64Encoded = aim64Encoded.replace(entry.getKey(), entry.getValue()); | |||||
| } | |||||
| return AIM64_ENCODING_PREFIX + aim64Encoded; | |||||
| } | |||||
| public static String encode(Map<String, Object> value, boolean oneWayHashing) { | |||||
| if (oneWayHashing) { | |||||
| return md5(JSON.toJSONString(value)); | |||||
| } | |||||
| return aim64encode(value); | |||||
| } | |||||
| private static String md5(String input) { | |||||
| try { | |||||
| java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); | |||||
| byte[] array = md.digest(input.getBytes()); | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| for (byte b : array) { | |||||
| sb.append(Integer.toHexString((b & 0xFF) | 0x100).substring(1, 3)); | |||||
| } | |||||
| return sb.toString(); | |||||
| } catch (java.security.NoSuchAlgorithmException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| public static String decode(List<String> runIds) { | |||||
| // 确保 runIds 列表的大小为 3 | |||||
| if (runIds == null || runIds.size() == 0) { | |||||
| throw new IllegalArgumentException("runIds 不能为空"); | |||||
| } | |||||
| // 构建查询字符串 | |||||
| StringBuilder queryBuilder = new StringBuilder("run.hash in ["); | |||||
| for (int i = 0; i < runIds.size(); i++) { | |||||
| if (i > 0) { | |||||
| queryBuilder.append(","); | |||||
| } | |||||
| queryBuilder.append("\"").append(runIds.get(i)).append("\""); | |||||
| } | |||||
| queryBuilder.append("]"); | |||||
| String query = queryBuilder.toString(); | |||||
| Map<String, Object> map = new HashMap<>(); | |||||
| map.put("query", query); | |||||
| map.put("advancedMode", true); | |||||
| map.put("advancedQuery", query); | |||||
| String searchQuery = encode(map, false); | |||||
| return searchQuery; | |||||
| } | |||||
| } | |||||
| @@ -25,6 +25,7 @@ import java.security.cert.X509Certificate; | |||||
| import java.util.HashMap; | import java.util.HashMap; | ||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Map; | import java.util.Map; | ||||
| import java.util.zip.GZIPInputStream; | |||||
| /** | /** | ||||
| * HTTP请求工具类 | * HTTP请求工具类 | ||||
| @@ -447,4 +448,38 @@ public class HttpUtils { | |||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| public static String sendGetRequestgzip(String url) throws Exception { | |||||
| String resultStr = null; | |||||
| HttpGet httpGet = new HttpGet(url); | |||||
| httpGet.setHeader("Content-Type", "application/json"); | |||||
| httpGet.setHeader("Accept-Encoding", "gzip, deflate"); | |||||
| try { | |||||
| HttpResponse response = httpClient.execute(httpGet); | |||||
| int responseCode = response.getStatusLine().getStatusCode(); | |||||
| if (responseCode != 200) { | |||||
| throw new IOException("HTTP request failed with response code: " + responseCode); | |||||
| } | |||||
| // 获取响应内容 | |||||
| InputStream responseStream = response.getEntity().getContent(); | |||||
| // 检查响应是否被压缩 | |||||
| if ("gzip".equalsIgnoreCase(response.getEntity().getContentEncoding().getValue())) { | |||||
| responseStream = new GZIPInputStream(responseStream); | |||||
| } | |||||
| // 读取解压缩后的内容 | |||||
| byte[] buffer = new byte[1024]; | |||||
| int len; | |||||
| StringBuilder decompressedString = new StringBuilder(); | |||||
| while ((len = responseStream.read(buffer)) > 0) { | |||||
| decompressedString.append(new String(buffer, 0, len)); | |||||
| } | |||||
| resultStr = decompressedString.toString(); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return resultStr; | |||||
| } | |||||
| } | } | ||||
| @@ -218,6 +218,7 @@ public class JacksonUtil { | |||||
| */ | */ | ||||
| public static <T> List<T> parseJSONStr2TList(String jsonStr, Class<T> clazz, String dateFormat) { | public static <T> List<T> parseJSONStr2TList(String jsonStr, Class<T> clazz, String dateFormat) { | ||||
| try { | try { | ||||
| if (StringUtils.isEmpty(jsonStr)) { return new ArrayList<T>(); } | |||||
| ObjectMapper objectMapper = getObjectMapper(dateFormat, false, false, true); | ObjectMapper objectMapper = getObjectMapper(dateFormat, false, false, true); | ||||
| CollectionType listType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, clazz); | CollectionType listType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, clazz); | ||||
| return objectMapper.readValue(jsonStr, listType); | return objectMapper.readValue(jsonStr, listType); | ||||
| @@ -1,8 +1,11 @@ | |||||
| package com.ruoyi.platform.utils; | package com.ruoyi.platform.utils; | ||||
| import com.fasterxml.jackson.core.JsonProcessingException; | import com.fasterxml.jackson.core.JsonProcessingException; | ||||
| import com.fasterxml.jackson.databind.ObjectMapper; | import com.fasterxml.jackson.databind.ObjectMapper; | ||||
| import org.json.JSONObject; | |||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.util.HashMap; | |||||
| import java.util.Iterator; | |||||
| import java.util.Map; | import java.util.Map; | ||||
| public class JsonUtils { | public class JsonUtils { | ||||
| @@ -28,4 +31,26 @@ public class JsonUtils { | |||||
| public static <T> T jsonToObject(String json, Class<T> clazz) throws IOException { | public static <T> T jsonToObject(String json, Class<T> clazz) throws IOException { | ||||
| return objectMapper.readValue(json, clazz); | return objectMapper.readValue(json, clazz); | ||||
| } | } | ||||
| // 将JSON字符串转换为扁平化的Map | |||||
| public static Map<String, Object> flattenJson(String prefix, Map<String, Object> map) { | |||||
| Map<String, Object> flatMap = new HashMap<>(); | |||||
| Iterator<Map.Entry<String, Object>> entries = map.entrySet().iterator(); | |||||
| while (entries.hasNext()) { | |||||
| Map.Entry<String, Object> entry = entries.next(); | |||||
| String key = entry.getKey(); | |||||
| Object value = entry.getValue(); | |||||
| if (value instanceof Map) { | |||||
| flatMap.putAll(flattenJson(prefix + key + ".", (Map<String, Object>) value)); | |||||
| } else { | |||||
| flatMap.put(prefix + key, value); | |||||
| } | |||||
| } | |||||
| return flatMap; | |||||
| } | |||||
| } | } | ||||
| @@ -376,7 +376,7 @@ public class K8sClientUtil { | |||||
| } | } | ||||
| public Integer createConfiguredPod(String podName, String namespace, Integer port, String mountPath, V1PersistentVolumeClaim pvc, String image, String datasetPath, String modelPath) { | |||||
| public Integer createConfiguredPod(String podName, String namespace, Integer port, String mountPath, V1PersistentVolumeClaim pvc, String image, String dataPvcName, String datasetPath, String modelPath) { | |||||
| Map<String, String> selector = new LinkedHashMap<>(); | Map<String, String> selector = new LinkedHashMap<>(); | ||||
| selector.put("k8s-jupyter", podName); | selector.put("k8s-jupyter", podName); | ||||
| @@ -402,13 +402,13 @@ public class K8sClientUtil { | |||||
| // 配置卷和卷挂载 | // 配置卷和卷挂载 | ||||
| List<V1VolumeMount> volumeMounts = new ArrayList<>(); | List<V1VolumeMount> volumeMounts = new ArrayList<>(); | ||||
| volumeMounts.add(new V1VolumeMount().name("workspace").mountPath(mountPath)); | volumeMounts.add(new V1VolumeMount().name("workspace").mountPath(mountPath)); | ||||
| volumeMounts.add(new V1VolumeMount().name("dataset").mountPath("/datasets").subPath(datasetPath).readOnly(true)); | |||||
| volumeMounts.add(new V1VolumeMount().name("model").mountPath("/model").subPath(modelPath).readOnly(true)); | |||||
| volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/datasets").subPath(datasetPath).readOnly(true)); | |||||
| volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/model").subPath(modelPath).readOnly(true)); | |||||
| List<V1Volume> volumes = new ArrayList<>(); | List<V1Volume> volumes = new ArrayList<>(); | ||||
| volumes.add(new V1Volume().name("workspace").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName()))); | volumes.add(new V1Volume().name("workspace").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName()))); | ||||
| volumes.add(new V1Volume().name("dataset").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName()))); | |||||
| volumes.add(new V1Volume().name("model").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName()))); | |||||
| volumes.add(new V1Volume().name("minio-pvc").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(dataPvcName))); | |||||
| V1Pod pod = new V1PodBuilder() | V1Pod pod = new V1PodBuilder() | ||||
| .withNewMetadata() | .withNewMetadata() | ||||
| @@ -573,12 +573,8 @@ public class K8sClientUtil { | |||||
| V1Pod pod = api.deleteNamespacedPod(podName, namespace, null, null, null, null, null, null); | V1Pod pod = api.deleteNamespacedPod(podName, namespace, null, null, null, null, null, null); | ||||
| return "Pod " + podName + " 删除请求已发送"; | return "Pod " + podName + " 删除请求已发送"; | ||||
| } catch (ApiException e) { | } catch (ApiException e) { | ||||
| if (e.getCode() == 404) { | |||||
| return "Pod " + podName + " 不存在"; | |||||
| } else { | |||||
| log.error("删除pod异常:" + e.getResponseBody(), e); | |||||
| throw e; | |||||
| } | |||||
| log.error("删除pod异常:" + e.getResponseBody(), e); | |||||
| throw e; | |||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,44 @@ | |||||
| package com.ruoyi.platform.vo; | |||||
| import com.fasterxml.jackson.databind.PropertyNamingStrategy; | |||||
| import com.fasterxml.jackson.databind.annotation.JsonNaming; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| import java.util.Map; | |||||
| @Data | |||||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | |||||
| public class DevEnvironmentVo implements Serializable { | |||||
| private Integer id; | |||||
| private String name; | |||||
| /** | |||||
| * 计算资源 | |||||
| */ | |||||
| private String computingResource; | |||||
| /** | |||||
| * 资源规格 | |||||
| */ | |||||
| private String standard; | |||||
| /** | |||||
| * 环境变量 | |||||
| */ | |||||
| private String envVariable; | |||||
| /** | |||||
| * 所用镜像 | |||||
| */ | |||||
| private String image; | |||||
| /** | |||||
| * 对应数据集 | |||||
| */ | |||||
| private Map<String,Object> dataset; | |||||
| /** | |||||
| * 对应模型 | |||||
| */ | |||||
| private Map<String,Object> model; | |||||
| } | |||||
| @@ -0,0 +1,32 @@ | |||||
| package com.ruoyi.platform.vo; | |||||
| import com.fasterxml.jackson.databind.PropertyNamingStrategy; | |||||
| import com.fasterxml.jackson.databind.annotation.JsonNaming; | |||||
| import io.swagger.annotations.ApiModelProperty; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| import java.util.Date; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | |||||
| @Data | |||||
| public class InsMetricInfoVo implements Serializable { | |||||
| @ApiModelProperty(value = "开始时间") | |||||
| private Date startTime; | |||||
| @ApiModelProperty(value = "实例运行状态") | |||||
| private String status; | |||||
| @ApiModelProperty(value = "使用数据集") | |||||
| private List<String> dataset; | |||||
| @ApiModelProperty(value = "实例ID") | |||||
| private Integer experimentInsId; | |||||
| @ApiModelProperty(value = "训练指标") | |||||
| private Map metrics; | |||||
| @ApiModelProperty(value = "训练参数") | |||||
| private Map params; | |||||
| @ApiModelProperty(value = "训练记录ID") | |||||
| private String runId; | |||||
| private List<String> metricsNames; | |||||
| private List<String> paramsNames; | |||||
| } | |||||
| @@ -7,6 +7,7 @@ import io.swagger.annotations.ApiModelProperty; | |||||
| import lombok.Data; | import lombok.Data; | ||||
| import java.io.Serializable; | import java.io.Serializable; | ||||
| import java.util.Date; | |||||
| @Data | @Data | ||||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | ||||
| @@ -45,4 +46,10 @@ public class ModelVersionDependcyVo implements Serializable { | |||||
| @ApiModelProperty(value = "文件大小") | @ApiModelProperty(value = "文件大小") | ||||
| private String fileSize; | private String fileSize; | ||||
| @ApiModelProperty(value = "创建者") | |||||
| private String createBy; | |||||
| @ApiModelProperty(value = "创建时间") | |||||
| private Date createTime; | |||||
| } | } | ||||
| @@ -6,7 +6,7 @@ import com.fasterxml.jackson.databind.annotation.JsonNaming; | |||||
| import java.io.Serializable; | import java.io.Serializable; | ||||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | ||||
| public class TensorboardStatusVo implements Serializable { | |||||
| public class PodStatusVo implements Serializable { | |||||
| private String status; | private String status; | ||||
| private String url; | private String url; | ||||
| @@ -25,4 +25,5 @@ public class TensorboardStatusVo implements Serializable { | |||||
| public void setUrl(String url) { | public void setUrl(String url) { | ||||
| this.url = url; | this.url = url; | ||||
| } | } | ||||
| } | } | ||||
| @@ -12,7 +12,7 @@ | |||||
| <result property="image" column="image" jdbcType="VARCHAR"/> | <result property="image" column="image" jdbcType="VARCHAR"/> | ||||
| <result property="dataset" column="dataset" jdbcType="VARCHAR"/> | <result property="dataset" column="dataset" jdbcType="VARCHAR"/> | ||||
| <result property="model" column="model" jdbcType="VARCHAR"/> | <result property="model" column="model" jdbcType="VARCHAR"/> | ||||
| <result property="altField1" column="alt_field1" jdbcType="VARCHAR"/> | |||||
| <result property="url" column="url" jdbcType="VARCHAR"/> | |||||
| <result property="altField2" column="alt_field2" jdbcType="VARCHAR"/> | <result property="altField2" column="alt_field2" jdbcType="VARCHAR"/> | ||||
| <result property="createBy" column="create_by" jdbcType="VARCHAR"/> | <result property="createBy" column="create_by" jdbcType="VARCHAR"/> | ||||
| <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/> | <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/> | ||||
| @@ -24,17 +24,18 @@ | |||||
| <!--查询单个--> | <!--查询单个--> | ||||
| <select id="queryById" resultMap="DevEnvironmentMap"> | <select id="queryById" resultMap="DevEnvironmentMap"> | ||||
| select | select | ||||
| id,name,status,computing_resource,standard,env_variable,image,dataset,model,alt_field1,alt_field2,create_by,create_time,update_by,update_time,state | |||||
| id,name,status,computing_resource,standard,env_variable,image,dataset,model,url,alt_field2,create_by,create_time,update_by,update_time,state | |||||
| from dev_environment | from dev_environment | ||||
| where id = #{id} | |||||
| where id = #{id} and state = 1 | |||||
| </select> | </select> | ||||
| <!--查询指定行数据--> | <!--查询指定行数据--> | ||||
| <select id="queryAllByLimit" resultMap="DevEnvironmentMap"> | <select id="queryAllByLimit" resultMap="DevEnvironmentMap"> | ||||
| select | select | ||||
| id,name,status,computing_resource,standard,env_variable,image,dataset,model,alt_field1,alt_field2,create_by,create_time,update_by,update_time,state | |||||
| id,name,status,computing_resource,standard,env_variable,image,dataset,model,url,alt_field2,create_by,create_time,update_by,update_time,state | |||||
| from dev_environment | from dev_environment | ||||
| <where> | <where> | ||||
| state = 1 | |||||
| <if test="devEnvironment.id != null"> | <if test="devEnvironment.id != null"> | ||||
| and id = #{devEnvironment.id} | and id = #{devEnvironment.id} | ||||
| </if> | </if> | ||||
| @@ -62,8 +63,8 @@ | |||||
| <if test="devEnvironment.model != null and devEnvironment.model != ''"> | <if test="devEnvironment.model != null and devEnvironment.model != ''"> | ||||
| and model = #{devEnvironment.model} | and model = #{devEnvironment.model} | ||||
| </if> | </if> | ||||
| <if test="devEnvironment.altField1 != null and devEnvironment.altField1 != ''"> | |||||
| and alt_field1 = #{devEnvironment.altField1} | |||||
| <if test="devEnvironment.url != null and devEnvironment.url != ''"> | |||||
| and url = #{devEnvironment.url} | |||||
| </if> | </if> | ||||
| <if test="devEnvironment.altField2 != null and devEnvironment.altField2 != ''"> | <if test="devEnvironment.altField2 != null and devEnvironment.altField2 != ''"> | ||||
| and alt_field2 = #{devEnvironment.altField2} | and alt_field2 = #{devEnvironment.altField2} | ||||
| @@ -93,6 +94,7 @@ | |||||
| select count(1) | select count(1) | ||||
| from dev_environment | from dev_environment | ||||
| <where> | <where> | ||||
| state = 1 | |||||
| <if test="devEnvironment.id != null"> | <if test="devEnvironment.id != null"> | ||||
| and id = #{devEnvironment.id} | and id = #{devEnvironment.id} | ||||
| </if> | </if> | ||||
| @@ -120,8 +122,8 @@ | |||||
| <if test="devEnvironment.model != null and devEnvironment.model != ''"> | <if test="devEnvironment.model != null and devEnvironment.model != ''"> | ||||
| and model = #{devEnvironment.model} | and model = #{devEnvironment.model} | ||||
| </if> | </if> | ||||
| <if test="devEnvironment.altField1 != null and devEnvironment.altField1 != ''"> | |||||
| and alt_field1 = #{devEnvironment.altField1} | |||||
| <if test="devEnvironment.url != null and devEnvironment.url != ''"> | |||||
| and url = #{devEnvironment.url} | |||||
| </if> | </if> | ||||
| <if test="devEnvironment.altField2 != null and devEnvironment.altField2 != ''"> | <if test="devEnvironment.altField2 != null and devEnvironment.altField2 != ''"> | ||||
| and alt_field2 = #{devEnvironment.altField2} | and alt_field2 = #{devEnvironment.altField2} | ||||
| @@ -146,7 +148,7 @@ | |||||
| <!--新增所有列--> | <!--新增所有列--> | ||||
| <insert id="insert" keyProperty="id" useGeneratedKeys="true"> | <insert id="insert" keyProperty="id" useGeneratedKeys="true"> | ||||
| insert into dev_environment(name,status,computing_resource,standard,env_variable,image,dataset,model,alt_field1,alt_field2,create_by,create_time,update_by,update_time,state) | |||||
| insert into dev_environment(name,status,computing_resource,standard,env_variable,image,dataset,model,url,alt_field2,create_by,create_time,update_by,update_time,state) | |||||
| values (#{devEnvironment.name}, | values (#{devEnvironment.name}, | ||||
| #{devEnvironment.status}, | #{devEnvironment.status}, | ||||
| #{devEnvironment.computingResource}, | #{devEnvironment.computingResource}, | ||||
| @@ -155,7 +157,7 @@ | |||||
| #{devEnvironment.image}, | #{devEnvironment.image}, | ||||
| #{devEnvironment.dataset}, | #{devEnvironment.dataset}, | ||||
| #{devEnvironment.model}, | #{devEnvironment.model}, | ||||
| #{devEnvironment.altField1}, | |||||
| #{devEnvironment.url}, | |||||
| #{devEnvironment.altField2}, | #{devEnvironment.altField2}, | ||||
| #{devEnvironment.createBy}, | #{devEnvironment.createBy}, | ||||
| #{devEnvironment.createTime}, | #{devEnvironment.createTime}, | ||||
| @@ -166,21 +168,21 @@ | |||||
| </insert> | </insert> | ||||
| <insert id="insertBatch" keyProperty="id" useGeneratedKeys="true"> | <insert id="insertBatch" keyProperty="id" useGeneratedKeys="true"> | ||||
| insert into dev_environment(name,status,computing_resource,standard,env_variable,image,dataset,model,alt_field1,alt_field2,create_by,create_time,update_by,update_time,state ) | |||||
| insert into dev_environment(name,status,computing_resource,standard,env_variable,image,dataset,model,url,alt_field2,create_by,create_time,update_by,update_time,state ) | |||||
| values | values | ||||
| <foreach collection="entities" item="entity" separator=","> | <foreach collection="entities" item="entity" separator=","> | ||||
| (#{entity.name},#{entity.status},#{entity.computingResource},#{entity.standard},#{entity.envVariable},#{entity.image},#{entity.dataset},#{entity.model},#{entity.altField1},#{entity.altField2},#{entity.createBy},#{entity.createTime},#{entity.updateBy},#{entity.updateTime},#{entity.state}) | |||||
| (#{entity.name},#{entity.status},#{entity.computingResource},#{entity.standard},#{entity.envVariable},#{entity.image},#{entity.dataset},#{entity.model},#{entity.url},#{entity.altField2},#{entity.createBy},#{entity.createTime},#{entity.updateBy},#{entity.updateTime},#{entity.state}) | |||||
| </foreach> | </foreach> | ||||
| </insert> | </insert> | ||||
| <insert id="insertOrUpdateBatch" keyProperty="id" useGeneratedKeys="true"> | <insert id="insertOrUpdateBatch" keyProperty="id" useGeneratedKeys="true"> | ||||
| insert into dev_environment(name,status,computing_resource,standard,env_variable,image,dataset,model,alt_field1,alt_field2,create_by,create_time,update_by,update_time,state) | |||||
| insert into dev_environment(name,status,computing_resource,standard,env_variable,image,dataset,model,url,alt_field2,create_by,create_time,update_by,update_time,state) | |||||
| values | values | ||||
| <foreach collection="entities" item="entity" separator=","> | <foreach collection="entities" item="entity" separator=","> | ||||
| (#{entity.name}#{entity.status}#{entity.computingResource}#{entity.standard}#{entity.envVariable}#{entity.image}#{entity.dataset}#{entity.model}#{entity.altField1}#{entity.altField2}#{entity.createBy}#{entity.createTime}#{entity.updateBy}#{entity.updateTime}#{entity.state}) | |||||
| (#{entity.name}#{entity.status}#{entity.computingResource}#{entity.standard}#{entity.envVariable}#{entity.image}#{entity.dataset}#{entity.model}#{entity.url}#{entity.altField2}#{entity.createBy}#{entity.createTime}#{entity.updateBy}#{entity.updateTime}#{entity.state}) | |||||
| </foreach> | </foreach> | ||||
| on duplicate key update | on duplicate key update | ||||
| name = values(name)status = values(status)computing_resource = values(computing_resource)standard = values(standard)env_variable = values(env_variable)image = values(image)dataset = values(dataset)model = values(model)alt_field1 = values(alt_field1)alt_field2 = values(alt_field2)create_by = values(create_by)create_time = values(create_time)update_by = values(update_by)update_time = values(update_time)state = values(state) | |||||
| name = values(name)status = values(status)computing_resource = values(computing_resource)standard = values(standard)env_variable = values(env_variable)image = values(image)dataset = values(dataset)model = values(model)url = values(url)alt_field2 = values(alt_field2)create_by = values(create_by)create_time = values(create_time)update_by = values(update_by)update_time = values(update_time)state = values(state) | |||||
| </insert> | </insert> | ||||
| <!--通过主键修改数据--> | <!--通过主键修改数据--> | ||||
| @@ -211,8 +213,8 @@ name = values(name)status = values(status)computing_resource = values(computing_ | |||||
| <if test="devEnvironment.model != null and devEnvironment.model != ''"> | <if test="devEnvironment.model != null and devEnvironment.model != ''"> | ||||
| model = #{devEnvironment.model}, | model = #{devEnvironment.model}, | ||||
| </if> | </if> | ||||
| <if test="devEnvironment.altField1 != null and devEnvironment.altField1 != ''"> | |||||
| alt_field1 = #{devEnvironment.altField1}, | |||||
| <if test="devEnvironment.url != null and devEnvironment.url != ''"> | |||||
| url = #{devEnvironment.url}, | |||||
| </if> | </if> | ||||
| <if test="devEnvironment.altField2 != null and devEnvironment.altField2 != ''"> | <if test="devEnvironment.altField2 != null and devEnvironment.altField2 != ''"> | ||||
| alt_field2 = #{devEnvironment.altField2}, | alt_field2 = #{devEnvironment.altField2}, | ||||
| @@ -12,6 +12,7 @@ | |||||
| <result property="nodesResult" column="nodes_result" jdbcType="VARCHAR"/> | <result property="nodesResult" column="nodes_result" jdbcType="VARCHAR"/> | ||||
| <result property="nodesLogs" column="nodes_logs" jdbcType="VARCHAR"/> | <result property="nodesLogs" column="nodes_logs" jdbcType="VARCHAR"/> | ||||
| <result property="globalParam" column="global_param" jdbcType="VARCHAR"/> | <result property="globalParam" column="global_param" jdbcType="VARCHAR"/> | ||||
| <result property="metricRecord" column="metric_record" jdbcType="VARCHAR"/> | |||||
| <result property="startTime" column="start_time" jdbcType="TIMESTAMP"/> | <result property="startTime" column="start_time" jdbcType="TIMESTAMP"/> | ||||
| <result property="finishTime" column="finish_time" jdbcType="TIMESTAMP"/> | <result property="finishTime" column="finish_time" jdbcType="TIMESTAMP"/> | ||||
| <result property="createBy" column="create_by" jdbcType="VARCHAR"/> | <result property="createBy" column="create_by" jdbcType="VARCHAR"/> | ||||
| @@ -23,7 +24,7 @@ | |||||
| <!--查询非终止态的实例--> | <!--查询非终止态的实例--> | ||||
| <select id="queryByExperimentIsNotTerminated" resultMap="ExperimentInsMap"> | <select id="queryByExperimentIsNotTerminated" resultMap="ExperimentInsMap"> | ||||
| select id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status,nodes_result, nodes_logs,global_param, start_time, finish_time, create_by, create_time, update_by, update_time, state | |||||
| select id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status,nodes_result, nodes_logs,global_param,metric_record, start_time, finish_time, create_by, create_time, update_by, update_time, state | |||||
| from experiment_ins | from experiment_ins | ||||
| where (status NOT IN ('Terminated', 'Succeeded', 'Failed') | where (status NOT IN ('Terminated', 'Succeeded', 'Failed') | ||||
| OR status IS NULL) and state = 1 | OR status IS NULL) and state = 1 | ||||
| @@ -31,14 +32,14 @@ | |||||
| <!--查询单个--> | <!--查询单个--> | ||||
| <select id="queryById" resultMap="ExperimentInsMap"> | <select id="queryById" resultMap="ExperimentInsMap"> | ||||
| select id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status,nodes_result, nodes_logs,global_param, start_time, finish_time, create_by, create_time, update_by, update_time, state | |||||
| select id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status,nodes_result, nodes_logs,global_param,metric_record, start_time, finish_time, create_by, create_time, update_by, update_time, state | |||||
| from experiment_ins | from experiment_ins | ||||
| where id = #{id} and state = 1 | where id = #{id} and state = 1 | ||||
| </select> | </select> | ||||
| <!--查询列表--> | <!--查询列表--> | ||||
| <select id="getByExperimentId" resultMap="ExperimentInsMap"> | <select id="getByExperimentId" resultMap="ExperimentInsMap"> | ||||
| select id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status,nodes_result, nodes_logs, global_param, start_time, finish_time, create_by, create_time, update_by, update_time, state | |||||
| select id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status,nodes_result, nodes_logs, global_param,metric_record, start_time, finish_time, create_by, create_time, update_by, update_time, state | |||||
| from experiment_ins | from experiment_ins | ||||
| where experiment_id = #{experiment_id} and state = 1 | where experiment_id = #{experiment_id} and state = 1 | ||||
| order by create_time DESC | order by create_time DESC | ||||
| @@ -47,7 +48,7 @@ | |||||
| <!--查询最近的3个实例列表--> | <!--查询最近的3个实例列表--> | ||||
| <select id="getLatestInsList" resultMap="ExperimentInsMap"> | <select id="getLatestInsList" resultMap="ExperimentInsMap"> | ||||
| select id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status,nodes_result, nodes_logs, global_param, start_time, finish_time, create_by, create_time, update_by, update_time, state | |||||
| select id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status,nodes_result, nodes_logs, global_param,metric_record, start_time, finish_time, create_by, create_time, update_by, update_time, state | |||||
| from experiment_ins | from experiment_ins | ||||
| where state = 1 | where state = 1 | ||||
| order by create_time DESC | order by create_time DESC | ||||
| @@ -58,7 +59,7 @@ | |||||
| <select id="queryByExperiment" resultMap="ExperimentInsMap"> | <select id="queryByExperiment" resultMap="ExperimentInsMap"> | ||||
| select | select | ||||
| id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status,nodes_result, nodes_logs,global_param, start_time, finish_time, create_by, create_time, update_by, update_time, state | |||||
| id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status,nodes_result, nodes_logs,global_param,metric_record, start_time, finish_time, create_by, create_time, update_by, update_time, state | |||||
| from experiment_ins | from experiment_ins | ||||
| <where> | <where> | ||||
| state = 1 | state = 1 | ||||
| @@ -86,6 +87,9 @@ | |||||
| <if test="experimentIns.globalParam != null and experimentIns.globalParam != ''"> | <if test="experimentIns.globalParam != null and experimentIns.globalParam != ''"> | ||||
| and global_param = #{experimentIns.globalParam} | and global_param = #{experimentIns.globalParam} | ||||
| </if> | </if> | ||||
| <if test="experimentIns.metricRecord != null and experimentIns.metricRecord != ''"> | |||||
| and metric_record = #{experimentIns.metricRecord} | |||||
| </if> | |||||
| <if test="experimentIns.startTime != null"> | <if test="experimentIns.startTime != null"> | ||||
| and start_time = #{experimentIns.startTime} | and start_time = #{experimentIns.startTime} | ||||
| </if> | </if> | ||||
| @@ -110,7 +114,7 @@ | |||||
| <!--查询指定行数据--> | <!--查询指定行数据--> | ||||
| <select id="queryAllByLimit" resultMap="ExperimentInsMap"> | <select id="queryAllByLimit" resultMap="ExperimentInsMap"> | ||||
| select | select | ||||
| id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status,nodes_result, nodes_logs,global_param, start_time, finish_time, create_by, create_time, update_by, update_time, state | |||||
| id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status,nodes_result, nodes_logs,global_param,metric_record, start_time, finish_time, create_by, create_time, update_by, update_time, state | |||||
| from experiment_ins | from experiment_ins | ||||
| <where> | <where> | ||||
| state = 1 | state = 1 | ||||
| @@ -138,6 +142,9 @@ | |||||
| <if test="experimentIns.globalParam != null and experimentIns.globalParam != ''"> | <if test="experimentIns.globalParam != null and experimentIns.globalParam != ''"> | ||||
| and global_param = #{experimentIns.globalParam} | and global_param = #{experimentIns.globalParam} | ||||
| </if> | </if> | ||||
| <if test="experimentIns.metricRecord != null and experimentIns.metricRecord != ''"> | |||||
| and metric_record = #{experimentIns.metricRecord} | |||||
| </if> | |||||
| <if test="experimentIns.startTime != null"> | <if test="experimentIns.startTime != null"> | ||||
| and start_time = #{experimentIns.startTime} | and start_time = #{experimentIns.startTime} | ||||
| </if> | </if> | ||||
| @@ -191,6 +198,9 @@ | |||||
| <if test="experimentIns.globalParam != null and experimentIns.globalParam != ''"> | <if test="experimentIns.globalParam != null and experimentIns.globalParam != ''"> | ||||
| and global_param = #{experimentIns.globalParam} | and global_param = #{experimentIns.globalParam} | ||||
| </if> | </if> | ||||
| <if test="experimentIns.metricRecord != null and experimentIns.metricRecord != ''"> | |||||
| and metric_record = #{experimentIns.metricRecord} | |||||
| </if> | |||||
| <if test="experimentIns.startTime != null"> | <if test="experimentIns.startTime != null"> | ||||
| and start_time = #{experimentIns.startTime} | and start_time = #{experimentIns.startTime} | ||||
| </if> | </if> | ||||
| @@ -213,23 +223,23 @@ | |||||
| </select> | </select> | ||||
| <select id="queryByExperimentId" resultMap="ExperimentInsMap"> | <select id="queryByExperimentId" resultMap="ExperimentInsMap"> | ||||
| select id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status,nodes_result, nodes_logs, global_param, start_time, finish_time, create_by, create_time, update_by, update_time, state | |||||
| select id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status,nodes_result, nodes_logs, global_param,metric_record, start_time, finish_time, create_by, create_time, update_by, update_time, state | |||||
| from experiment_ins | from experiment_ins | ||||
| where experiment_id = #{id} and state = 1 | where experiment_id = #{id} and state = 1 | ||||
| </select> | </select> | ||||
| <!--新增所有列--> | <!--新增所有列--> | ||||
| <insert id="insert" keyProperty="id" useGeneratedKeys="true"> | <insert id="insert" keyProperty="id" useGeneratedKeys="true"> | ||||
| insert into experiment_ins(experiment_id,argo_ins_name,argo_ins_ns,status,nodes_status,nodes_result,nodes_logs,global_param,start_time,finish_time,create_by,create_time,update_by,update_time,state) | |||||
| values (#{experimentIns.experimentId},#{experimentIns.argoInsName},#{experimentIns.argoInsNs},#{experimentIns.status},#{experimentIns.nodesStatus},#{experimentIns.nodesResult},#{experimentIns.nodesLogs},#{experimentIns.globalParam},#{experimentIns.startTime},#{experimentIns.finishTime},#{experimentIns.createBy},#{experimentIns.createTime},#{experimentIns.updateBy},#{experimentIns.updateTime},#{experimentIns.state}) | |||||
| insert into experiment_ins(experiment_id,argo_ins_name,argo_ins_ns,status,nodes_status,nodes_result,nodes_logs,global_param,metric_record,start_time,finish_time,create_by,create_time,update_by,update_time,state) | |||||
| values (#{experimentIns.experimentId},#{experimentIns.argoInsName},#{experimentIns.argoInsNs},#{experimentIns.status},#{experimentIns.nodesStatus},#{experimentIns.nodesResult},#{experimentIns.nodesLogs},#{experimentIns.globalParam},#{experimentIns.metricRecord},#{experimentIns.startTime},#{experimentIns.finishTime},#{experimentIns.createBy},#{experimentIns.createTime},#{experimentIns.updateBy},#{experimentIns.updateTime},#{experimentIns.state}) | |||||
| </insert> | </insert> | ||||
| <insert id="insertBatch" keyProperty="id" useGeneratedKeys="true"> | <insert id="insertBatch" keyProperty="id" useGeneratedKeys="true"> | ||||
| insert into | insert into | ||||
| experiment_ins(experiment_id,argo_ins_name,argo_ins_ns,status,nodes_status,nodes_result,nodes_logs,global_param,start_time,finish_time,create_by,create_time,update_by,update_time,state) | |||||
| experiment_ins(experiment_id,argo_ins_name,argo_ins_ns,status,nodes_status,nodes_result,nodes_logs,global_param,metric_record,start_time,finish_time,create_by,create_time,update_by,update_time,state) | |||||
| values | values | ||||
| <foreach collection="entities" item="entity" separator=","> | <foreach collection="entities" item="entity" separator=","> | ||||
| (#{entity.experimentId},#{entity.argoInsName},#{entity.argoInsNs},#{entity.status},#{entity.nodesStatus},#{entity.nodesResult},#{entity.nodesLogs},#{entity.globalParam},#{entity.startTime},#{entity.finishTime},#{entity.createBy},#{entity.createTime},#{entity.updateBy},#{entity.updateTime},#{entity.state}) | |||||
| (#{entity.experimentId},#{entity.argoInsName},#{entity.argoInsNs},#{entity.status},#{entity.nodesStatus},#{entity.nodesResult},#{entity.nodesLogs},#{entity.globalParam},#{entity.metricRecord},#{entity.startTime},#{entity.finishTime},#{entity.createBy},#{entity.createTime},#{entity.updateBy},#{entity.updateTime},#{entity.state}) | |||||
| </foreach> | </foreach> | ||||
| </insert> | </insert> | ||||
| @@ -244,10 +254,10 @@ | |||||
| <!-- experiment_id = values(experiment_id)argo_ins_name = values(argo_ins_name)argo_ins_ns = values(argo_ins_ns)status = values(status) nodes_status = values(nodes_status) create_by = values(create_by)create_time = values(create_time)update_by = values(update_by)update_time = values(update_time)state = values(state)--> | <!-- experiment_id = values(experiment_id)argo_ins_name = values(argo_ins_name)argo_ins_ns = values(argo_ins_ns)status = values(status) nodes_status = values(nodes_status) create_by = values(create_by)create_time = values(create_time)update_by = values(update_by)update_time = values(update_time)state = values(state)--> | ||||
| <!-- </insert>--> | <!-- </insert>--> | ||||
| <update id="insertOrUpdateBatch"> | <update id="insertOrUpdateBatch"> | ||||
| insert into experiment_ins (id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status, nodes_result, nodes_logs, global_param, start_time, finish_time, create_by, create_time, update_by, update_time, state) | |||||
| insert into experiment_ins (id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status, nodes_result, nodes_logs, global_param,metric_record, start_time, finish_time, create_by, create_time, update_by, update_time, state) | |||||
| values | values | ||||
| <foreach collection="list" item="item" index="index" separator=","> | <foreach collection="list" item="item" index="index" separator=","> | ||||
| (#{item.id}, #{item.experimentId}, #{item.argoInsName}, #{item.argoInsNs}, #{item.status}, #{item.nodesStatus}, #{item.nodesResult}, #{item.nodesLogs}, #{item.globalParam}, #{item.startTime}, #{item.finishTime}, #{item.createBy}, #{item.createTime}, #{item.updateBy}, #{item.updateTime}, #{item.state}) | |||||
| (#{item.id}, #{item.experimentId}, #{item.argoInsName}, #{item.argoInsNs}, #{item.status}, #{item.nodesStatus}, #{item.nodesResult}, #{item.nodesLogs}, #{item.globalParam},#{item.metricRecord}, #{item.startTime}, #{item.finishTime}, #{item.createBy}, #{item.createTime}, #{item.updateBy}, #{item.updateTime}, #{item.state}) | |||||
| </foreach> | </foreach> | ||||
| ON DUPLICATE KEY UPDATE | ON DUPLICATE KEY UPDATE | ||||
| experiment_id = VALUES(experiment_id), | experiment_id = VALUES(experiment_id), | ||||
| @@ -258,6 +268,7 @@ | |||||
| nodes_result = VALUES(nodes_result), | nodes_result = VALUES(nodes_result), | ||||
| nodes_logs = VALUES(nodes_logs), | nodes_logs = VALUES(nodes_logs), | ||||
| global_param = VALUES(global_param), | global_param = VALUES(global_param), | ||||
| metric_record = VALUES(metric_record), | |||||
| start_time = VALUES(start_time), | start_time = VALUES(start_time), | ||||
| finish_time = VALUES(finish_time), | finish_time = VALUES(finish_time), | ||||
| create_by = VALUES(create_by), | create_by = VALUES(create_by), | ||||
| @@ -294,6 +305,9 @@ | |||||
| <if test="experimentIns.globalParam != null and experimentIns.globalParam != ''"> | <if test="experimentIns.globalParam != null and experimentIns.globalParam != ''"> | ||||
| global_param = #{experimentIns.globalParam}, | global_param = #{experimentIns.globalParam}, | ||||
| </if> | </if> | ||||
| <if test="experimentIns.metricRecord != null and experimentIns.metricRecord != ''"> | |||||
| metric_record = #{experimentIns.metricRecord}, | |||||
| </if> | |||||
| <if test="experimentIns.startTime != null"> | <if test="experimentIns.startTime != null"> | ||||
| start_time = #{experimentIns.startTime}, | start_time = #{experimentIns.startTime}, | ||||
| </if> | </if> | ||||
| @@ -14,12 +14,21 @@ | |||||
| <result property="state" column="state" jdbcType="INTEGER"/> | <result property="state" column="state" jdbcType="INTEGER"/> | ||||
| </resultMap> | </resultMap> | ||||
| <!--查询单个--> | |||||
| <!-- 查询单个 --> | |||||
| <select id="queryById" resultMap="ImageMap"> | <select id="queryById" resultMap="ImageMap"> | ||||
| select | select | ||||
| id,name,description,image_type,create_by,create_time,update_by,update_time,state | |||||
| from image | |||||
| where id = #{id} and state = 1 | |||||
| img.id, | |||||
| img.name, | |||||
| img.description, | |||||
| img.image_type, | |||||
| img.create_by, | |||||
| img.create_time, | |||||
| img.update_by, | |||||
| img.update_time, | |||||
| img.state, | |||||
| (SELECT COUNT(*) FROM image_version WHERE image_version.image_id = img.id AND image_version.state = 1) as versionCount | |||||
| from image img | |||||
| where img.id = #{id} and img.state = 1 | |||||
| </select> | </select> | ||||
| <!--查询指定行数据--> | <!--查询指定行数据--> | ||||
| @@ -22,12 +22,28 @@ | |||||
| <result property="state" column="state" jdbcType="INTEGER"/> | <result property="state" column="state" jdbcType="INTEGER"/> | ||||
| </resultMap> | </resultMap> | ||||
| <select id="queryByIns" resultMap="ModelDependencyMap"> | |||||
| select | |||||
| id,current_model_id,exp_ins_id,parent_models,ref_item,train_task,train_dataset,train_params,train_image,test_dataset,project_dependency,version,create_by,create_time,update_by,update_time,state | |||||
| from model_dependency | |||||
| <where> | |||||
| exp_ins_id = #{expInsId} and state = 1 | |||||
| </where> | |||||
| </select> | |||||
| <select id="queryByInsAndTrainTaskId" resultMap="ModelDependencyMap"> | |||||
| select | |||||
| id,current_model_id,exp_ins_id,parent_models,ref_item,train_task,train_dataset,train_params,train_image,test_dataset,project_dependency,version,create_by,create_time,update_by,update_time,state | |||||
| from model_dependency | |||||
| <where> | |||||
| exp_ins_id = #{expInsId} and train_task like concat('%', #{taskId}, '%') limit 1 | |||||
| </where> | |||||
| </select> | |||||
| <select id="queryChildrenByVersionId" resultMap="ModelDependencyMap"> | <select id="queryChildrenByVersionId" resultMap="ModelDependencyMap"> | ||||
| select | select | ||||
| id,current_model_id,exp_ins_id,parent_models,ref_item,train_task,train_dataset,train_params,train_image,test_dataset,project_dependency,version,create_by,create_time,update_by,update_time,state | id,current_model_id,exp_ins_id,parent_models,ref_item,train_task,train_dataset,train_params,train_image,test_dataset,project_dependency,version,create_by,create_time,update_by,update_time,state | ||||
| from model_dependency | from model_dependency | ||||
| <where> | <where> | ||||
| parent_models like concat('%', #{model_id}, '%') AND parent_models like concat('%', #{version}, '%') | |||||
| parent_models like concat('%', #{model_id}, '%') AND parent_models like concat('%', #{version}, '%') and state = 1 | |||||
| </where> | </where> | ||||
| </select> | </select> | ||||
| @@ -321,7 +337,7 @@ | |||||
| state = #{state}, | state = #{state}, | ||||
| </if> | </if> | ||||
| </set> | </set> | ||||
| where id = #{id} and state = 1 | |||||
| where id = #{id} | |||||
| </update> | </update> | ||||
| <!--通过主键删除--> | <!--通过主键删除--> | ||||