| @@ -76,7 +76,7 @@ export default defineConfig({ | |||
| * @name layout 插件 | |||
| * @doc https://umijs.org/docs/max/layout-menu | |||
| */ | |||
| title: '智能软件开发平台', | |||
| title: '智能材料科研平台', | |||
| layout: { | |||
| locale: false, | |||
| ...defaultSettings, | |||
| @@ -16,7 +16,7 @@ const Settings: ProLayoutProps & { | |||
| fixSiderbar: false, | |||
| splitMenus: false, | |||
| colorWeak: false, | |||
| title: '智能软件开发平台', | |||
| title: '智能材料科研平台', | |||
| pwa: true, | |||
| logo: '/assets/images/left-top-logo.png', | |||
| token: { | |||
| @@ -112,7 +112,7 @@ export default [ | |||
| { | |||
| name: '开发环境', | |||
| path: '', | |||
| component: './DevelopmentEnvironment/List', | |||
| component: './DevelopmentEnvironment/Editor', | |||
| }, | |||
| { | |||
| name: '创建编辑器', | |||
| @@ -241,10 +241,10 @@ const Login: React.FC = () => { | |||
| style={{ height: '42px', marginRight: '10px' }} | |||
| alt="" | |||
| /> | |||
| 智能软件开发平台 | |||
| 智能材料科研平台 | |||
| </div> | |||
| <div className={centerTitleBoX}> | |||
| <span style={{ whiteSpace: 'nowrap' }}>智能软件开发平台</span> | |||
| <span style={{ whiteSpace: 'nowrap' }}>智能材料科研平台</span> | |||
| <img | |||
| src="/assets/images/ai-logo.png" | |||
| @@ -271,7 +271,7 @@ const Login: React.FC = () => { | |||
| <div className={rightTopTitle}> | |||
| <span style={{ color: '#111111', fontSize: '36px' }}>hello~</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 className={containerLoginForm}> | |||
| <div | |||
| @@ -205,6 +205,17 @@ | |||
| <groupId>org.springframework.boot</groupId> | |||
| <artifactId>spring-boot-starter-websocket</artifactId> | |||
| </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> | |||
| @@ -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.platform.domain.DevEnvironment; | |||
| import com.ruoyi.platform.service.DevEnvironmentService; | |||
| import com.ruoyi.platform.vo.DevEnvironmentVo; | |||
| import io.swagger.annotations.Api; | |||
| import org.springframework.data.domain.Page; | |||
| import org.springframework.data.domain.PageRequest; | |||
| @@ -56,12 +57,12 @@ public class DevEnvironmentController extends BaseController { | |||
| /** | |||
| * 新增数据 | |||
| * | |||
| * @param devEnvironment 实体 | |||
| * @param devEnvironmentVo 实体 | |||
| * @return 新增结果 | |||
| */ | |||
| @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 编辑结果 | |||
| */ | |||
| @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 删除是否成功 | |||
| */ | |||
| @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.domain.AjaxResult; | |||
| import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | |||
| import com.ruoyi.platform.domain.DevEnvironment; | |||
| import com.ruoyi.platform.service.JupyterService; | |||
| import com.ruoyi.platform.vo.FrameLogPathVo; | |||
| import com.ruoyi.platform.vo.PodStatusVo; | |||
| import io.swagger.annotations.Api; | |||
| import io.swagger.annotations.ApiOperation; | |||
| import io.swagger.v3.oas.annotations.responses.ApiResponse; | |||
| @@ -56,6 +58,13 @@ public class JupyterController extends BaseController { | |||
| 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") | |||
| 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.platform.service.TensorBoardService; | |||
| 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.ApiOperation; | |||
| import io.swagger.v3.oas.annotations.responses.ApiResponse; | |||
| @@ -37,7 +37,7 @@ public class TensorBoardController extends BaseController { | |||
| } | |||
| @PostMapping("/getStatus") | |||
| @ApiResponse | |||
| public GenericsAjaxResult<TensorboardStatusVo> getStatus(@RequestBody FrameLogPathVo frameLogPathVo) throws Exception { | |||
| public GenericsAjaxResult<PodStatusVo> getStatus(@RequestBody FrameLogPathVo frameLogPathVo) throws Exception { | |||
| return genericsSuccess(tensorBoardService.getTensorBoardStatus(frameLogPathVo)); | |||
| } | |||
| } | |||
| @@ -54,7 +54,7 @@ public class DevEnvironment implements Serializable { | |||
| /** | |||
| * 备用字段1 | |||
| */ | |||
| private String altField1; | |||
| private String url; | |||
| /** | |||
| * 备用字段2 | |||
| */ | |||
| @@ -153,12 +153,12 @@ public class DevEnvironment implements Serializable { | |||
| 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() { | |||
| @@ -48,6 +48,9 @@ public class ExperimentIns implements Serializable { | |||
| @ApiModelProperty(value = "实验实例全局参数", notes = "以JSON字符串格式存储") | |||
| @JsonRawValue | |||
| private String globalParam; | |||
| @ApiModelProperty(value = "参数记录", notes = "以JSON字符串格式存储") | |||
| @JsonRawValue | |||
| private String metricRecord; | |||
| @ApiModelProperty(value = "开始时间") | |||
| private Date startTime; | |||
| @@ -210,5 +213,12 @@ public class ExperimentIns implements Serializable { | |||
| 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> 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.ModelDependencyDao; | |||
| import com.ruoyi.platform.service.ExperimentInsService; | |||
| import com.ruoyi.platform.service.ModelDependencyService; | |||
| import com.ruoyi.platform.utils.JacksonUtil; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.data.domain.Page; | |||
| import org.springframework.scheduling.annotation.Scheduled; | |||
| import org.springframework.stereotype.Component; | |||
| import javax.annotation.Resource; | |||
| import java.io.IOException; | |||
| import java.util.ArrayList; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import java.util.*; | |||
| @Component() | |||
| public class ExperimentInstanceStatusTask { | |||
| @@ -46,95 +41,94 @@ public class ExperimentInstanceStatusTask { | |||
| String oldStatus = experimentIns.getStatus(); | |||
| try { | |||
| experimentIns = experimentInsService.queryStatusFromArgo(experimentIns); | |||
| }catch (Exception e){ | |||
| } catch (Exception e) { | |||
| 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); | |||
| //遍历模型关系表,找到 | |||
| List<ModelDependency> modelDependencyList = new ArrayList<ModelDependency>(); | |||
| for (ExperimentIns experimentIns : updateList){ | |||
| for (ExperimentIns experimentIns : updateList) { | |||
| ModelDependency modelDependencyquery = new ModelDependency(); | |||
| modelDependencyquery.setExpInsId(experimentIns.getId()); | |||
| modelDependencyquery.setState(2); | |||
| List<ModelDependency> modelDependencyListquery = modelDependencyDao.queryByModelDependency(modelDependencyquery); | |||
| if (modelDependencyListquery==null||modelDependencyListquery.size()==0){ | |||
| if (modelDependencyListquery == null || modelDependencyListquery.size() == 0) { | |||
| continue; | |||
| } | |||
| ModelDependency modelDependency = modelDependencyListquery.get(0); | |||
| //查看状态, | |||
| if (StringUtils.equals("Failed",experimentIns.getStatus())){ | |||
| if (StringUtils.equals("Failed", experimentIns.getStatus())) { | |||
| //取出节点状态 | |||
| String trainTask = modelDependency.getTrainTask(); | |||
| Map<String, Object> trainMap = JacksonUtil.parseJSONStr2Map(trainTask); | |||
| String task_id = (String) trainMap.get("task_id"); | |||
| if (StringUtils.isEmpty(task_id)){ | |||
| if (StringUtils.isEmpty(task_id)) { | |||
| continue; | |||
| } | |||
| String nodesStatus = experimentIns.getNodesStatus(); | |||
| Map<String, Object> nodeMaps = JacksonUtil.parseJSONStr2Map(nodesStatus); | |||
| Map<String, Object> nodeMap = JacksonUtil.parseJSONStr2Map(JacksonUtil.toJSONString(nodeMaps.get(task_id))); | |||
| if (nodeMap==null){ | |||
| if (nodeMap == null) { | |||
| continue; | |||
| } | |||
| if (!StringUtils.equals("Succeeded",(String)nodeMap.get("phase"))){ | |||
| if (!StringUtils.equals("Succeeded", (String) nodeMap.get("phase"))) { | |||
| modelDependency.setState(0); | |||
| modelDependencyList.add(modelDependency); | |||
| } | |||
| } | |||
| } | |||
| if (modelDependencyList.size()>0) { | |||
| if (modelDependencyList.size() > 0) { | |||
| modelDependencyDao.insertOrUpdateBatch(modelDependencyList); | |||
| } | |||
| } | |||
| } | |||
| @Scheduled(cron = "0/30 * * * * ?") // / 每30S执行一次 | |||
| public void executeExperimentStatus() throws IOException { | |||
| if (experimentIds.size()==0){ | |||
| if (experimentIds.size() == 0) { | |||
| return; | |||
| } | |||
| // 存储需要更新的实验对象列表 | |||
| List<Experiment> updateExperiments = new ArrayList<>(); | |||
| for (Integer experimentId : experimentIds){ | |||
| for (Integer experimentId : experimentIds) { | |||
| // 获取当前实验的所有实例列表 | |||
| List<ExperimentIns> insList = experimentInsService.getByExperimentId(experimentId); | |||
| 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()); | |||
| } | |||
| String subStatus = statusList.toString().substring(1, statusList.toString().length() - 1); | |||
| Experiment experiment = experimentDao.queryById(experimentId); | |||
| // 如果实验状态列表发生变化,则更新实验对象,并加入到需要更新的列表中 | |||
| if (!StringUtils.equals(subStatus,experiment.getStatusList())){ | |||
| if (!StringUtils.equals(subStatus, experiment.getStatusList())) { | |||
| experiment.setStatusList(subStatus); | |||
| updateExperiments.add(experiment); | |||
| } | |||
| } | |||
| if (!updateExperiments.isEmpty()) { | |||
| 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; | |||
| import com.ruoyi.platform.domain.DevEnvironment; | |||
| import com.ruoyi.platform.vo.DevEnvironmentVo; | |||
| import org.springframework.data.domain.Page; | |||
| import org.springframework.data.domain.PageRequest; | |||
| @@ -35,7 +36,7 @@ public interface DevEnvironmentService { | |||
| * @param devEnvironment 实例对象 | |||
| * @return 实例对象 | |||
| */ | |||
| DevEnvironment insert(DevEnvironment devEnvironment); | |||
| DevEnvironment insert(DevEnvironmentVo devEnvironmentVo); | |||
| /** | |||
| * 修改数据 | |||
| @@ -1,6 +1,7 @@ | |||
| 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; | |||
| @@ -11,7 +12,9 @@ public interface JupyterService { | |||
| void mlflow(); | |||
| String runJupyterService(Integer id); | |||
| String runJupyterService(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; | |||
| 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; | |||
| import com.ruoyi.platform.vo.FrameLogPathVo; | |||
| import com.ruoyi.platform.vo.TensorboardStatusVo; | |||
| import com.ruoyi.platform.vo.PodStatusVo; | |||
| public interface TensorBoardService { | |||
| TensorboardStatusVo getTensorBoardStatus(FrameLogPathVo frameLogPathVo); | |||
| PodStatusVo getTensorBoardStatus(FrameLogPathVo frameLogPathVo); | |||
| /** | |||
| * 在集群中启动TensorBoard容器,并且返回地址,4小时后销毁 | |||
| * @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.setFileSize(formattedSize); | |||
| datasetVersion.setUrl(url); | |||
| datasetVersion.setUrl(objectName); | |||
| datasetVersion.setDescription(labelDatasetVersionVo.getDesc()); | |||
| this.insert(datasetVersion); | |||
| } | |||
| @@ -2,13 +2,17 @@ package com.ruoyi.platform.service.impl; | |||
| import com.ruoyi.common.security.utils.SecurityUtils; | |||
| import com.ruoyi.platform.domain.DevEnvironment; | |||
| import com.ruoyi.platform.domain.PodStatus; | |||
| import com.ruoyi.platform.mapper.DevEnvironmentDao; | |||
| import com.ruoyi.platform.service.DevEnvironmentService; | |||
| import com.ruoyi.platform.service.JupyterService; | |||
| 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 io.kubernetes.client.openapi.models.V1PersistentVolumeClaim; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.springframework.context.annotation.Lazy; | |||
| import org.springframework.stereotype.Service; | |||
| import org.springframework.data.domain.Page; | |||
| import org.springframework.data.domain.PageImpl; | |||
| @@ -16,6 +20,7 @@ import org.springframework.data.domain.PageRequest; | |||
| import javax.annotation.Resource; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| /** | |||
| @@ -29,8 +34,8 @@ public class DevEnvironmentServiceImpl implements DevEnvironmentService { | |||
| @Resource | |||
| private DevEnvironmentDao devEnvironmentDao; | |||
| @Resource | |||
| @Lazy | |||
| private JupyterService jupyterService; | |||
| @@ -55,23 +60,53 @@ public class DevEnvironmentServiceImpl implements DevEnvironmentService { | |||
| @Override | |||
| public Page<DevEnvironment> queryByPage(DevEnvironment devEnvironment, PageRequest pageRequest) { | |||
| 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 实例对象 | |||
| */ | |||
| @Override | |||
| public DevEnvironment insert(DevEnvironment devEnvironment) { | |||
| public DevEnvironment insert(DevEnvironmentVo devEnvironmentVo) { | |||
| //插入预备,此时不需要判断版本重复 | |||
| DevEnvironment devEnvironment = new DevEnvironment(); | |||
| 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.setUpdateBy(loginUser.getUsername()); | |||
| devEnvironment.setUpdateTime(new Date()); | |||
| devEnvironment.setCreateTime(new Date()); | |||
| devEnvironment.setState(1); | |||
| this.devEnvironmentDao.insert(devEnvironment); | |||
| return devEnvironment; | |||
| } | |||
| @@ -102,7 +102,6 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { | |||
| */ | |||
| @Override | |||
| 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); | |||
| // } | |||
| return experimentInsList; | |||
| return experimentInsDao.getByExperimentId(experimentId); | |||
| } | |||
| @@ -251,9 +251,14 @@ public class ExperimentServiceImpl implements ExperimentService { | |||
| if (data == null || MapUtils.isEmpty(data)) { | |||
| throw new RuntimeException("Failed to run workflow."); | |||
| } | |||
| Map<String, Object> metadata = (Map<String, Object>) data.get("metadata"); | |||
| // 插入记录到实验实例表 | |||
| ExperimentIns experimentIns = new ExperimentIns(); | |||
| //获取训练参数 | |||
| experimentIns.setExperimentId(experiment.getId()); | |||
| experimentIns.setArgoInsNs((String) metadata.get("namespace")); | |||
| experimentIns.setArgoInsName((String) metadata.get("name")); | |||
| @@ -264,16 +269,25 @@ public class ExperimentServiceImpl implements ExperimentService { | |||
| //替换argoInsName | |||
| String outputString = JsonUtils.mapToJson(output); | |||
| experimentIns.setNodesResult(outputString.replace("{{workflow.name}}", (String) metadata.get("name"))); | |||
| //插入ExperimentIns表中 | |||
| ExperimentIns insert = experimentInsService.insert(experimentIns); | |||
| //插入到模型依赖关系表 | |||
| //得到dependendcy | |||
| Map<String, Object> converMap2 = JsonUtils.jsonToMap(JacksonUtil.replaceInAarry(convertRes, params)); | |||
| Map<String ,Object> dependendcy = (Map<String, Object>)converMap2.get("model_dependency"); | |||
| 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){ | |||
| throw new RuntimeException(e); | |||
| } | |||
| @@ -281,6 +295,37 @@ public class ExperimentServiceImpl implements ExperimentService { | |||
| experiment.setExperimentInsList(updatedExperimentInsList); | |||
| 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 { | |||
| Iterator<Map.Entry<String, Object>> dependendcyIterator = dependendcy.entrySet().iterator(); | |||
| 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.security.utils.SecurityUtils; | |||
| import com.ruoyi.platform.domain.DevEnvironment; | |||
| import com.ruoyi.platform.domain.PodStatus; | |||
| import com.ruoyi.platform.mapper.DevEnvironmentDao; | |||
| import com.ruoyi.platform.service.DevEnvironmentService; | |||
| 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.MinioUtil; | |||
| import com.ruoyi.platform.utils.MlflowUtil; | |||
| import com.ruoyi.platform.vo.PodStatusVo; | |||
| import com.ruoyi.system.api.model.LoginUser; | |||
| import io.kubernetes.client.openapi.models.V1PersistentVolumeClaim; | |||
| import io.kubernetes.client.openapi.models.V1Pod; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.context.annotation.Lazy; | |||
| import org.springframework.stereotype.Service; | |||
| import javax.annotation.Resource; | |||
| @@ -37,6 +41,8 @@ public class JupyterServiceImpl implements JupyterService { | |||
| private String masterIp; | |||
| @Value("${k8s.storageClassName}") | |||
| private String storageClassName; | |||
| @Value("${minio.pvcName}") | |||
| private String minioPvcName; | |||
| private final MinioUtil minioUtil; | |||
| @@ -49,6 +55,7 @@ public class JupyterServiceImpl implements JupyterService { | |||
| private DevEnvironmentDao devEnvironmentDao; | |||
| @Resource | |||
| @Lazy | |||
| private DevEnvironmentService devEnvironmentService; | |||
| @Resource | |||
| @@ -69,10 +76,11 @@ public class JupyterServiceImpl implements JupyterService { | |||
| } | |||
| @Override | |||
| public String runJupyterService(Integer id) { | |||
| public String runJupyterService(Integer id) throws Exception { | |||
| DevEnvironment devEnvironment = this.devEnvironmentDao.queryById(id); | |||
| String envName = devEnvironment.getName(); | |||
| //TODO 设置环境变量 | |||
| if(devEnvironment == null){ | |||
| throw new Exception("开发环境配置不存在"); | |||
| } | |||
| // 提取数据集,模型信息,得到数据集模型的path | |||
| Map<String, Object> dataset = JacksonUtil.parseJSONStr2Map(devEnvironment.getDataset()); | |||
| @@ -81,16 +89,26 @@ public class JupyterServiceImpl implements JupyterService { | |||
| String modelPath = (String) model.get("path"); | |||
| 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"; | |||
| //新建编辑器的pvc | |||
| V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName); | |||
| //TODO 设置镜像可配置,这里先用默认镜像启动pod | |||
| // 调用修改后的 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){ | |||
| throw new Exception("开发环境配置不存在"); | |||
| } | |||
| 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 | |||
| 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 + ",编辑器已停止"; | |||
| } | |||
| @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 | |||
| 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 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; | |||
| /** | |||
| @@ -97,6 +94,16 @@ public class ModelDependencyServiceImpl implements ModelDependencyService { | |||
| 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 | |||
| @@ -167,8 +174,6 @@ public class ModelDependencyServiceImpl implements ModelDependencyService { | |||
| modelsVersionquery.setModelsId(currentModelId); | |||
| modelsVersionquery.setVersion(modelDependency.getVersion()); | |||
| ModelsVersion modelsVersion = modelsVersionService.queryByModelsVersion(modelsVersionquery); | |||
| ExperimentIns experimentIns = experimentInsService.queryById(expInsId); | |||
| Experiment experiment = experimentService.queryById(experimentIns.getExperimentId()); | |||
| ModelVersionDependcyVo modelVersionDependcyVo = new ModelVersionDependcyVo(); | |||
| modelVersionDependcyVo.setName(models.getName()); | |||
| modelVersionDependcyVo.setAvailableRange(models.getAvailableRange()); | |||
| @@ -180,9 +185,18 @@ public class ModelDependencyServiceImpl implements ModelDependencyService { | |||
| modelVersionDependcyVo.setFileName(modelsVersion.getFileName()); | |||
| modelVersionDependcyVo.setFileSize(modelsVersion.getFileSize()); | |||
| modelVersionDependcyVo.setUrl(modelsVersion.getUrl()); | |||
| modelDependcyTreeVo.setWorkflowId(experiment.getWorkflowId()); | |||
| modelVersionDependcyVo.setCreateBy(modelsVersion.getCreateBy()); | |||
| modelVersionDependcyVo.setCreateTime(modelsVersion.getCreateTime()); | |||
| 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; | |||
| } | |||
| @@ -227,8 +227,8 @@ public class ModelsVersionServiceImpl implements ModelsVersionService { | |||
| for(ModelsVersion modelsVersion : modelsVersions) { | |||
| insertPrepare(modelsVersion); | |||
| } | |||
| insertModelsDependency(modelsVersions.get(0)); | |||
| this.modelsVersionDao.insertBatch(modelsVersions); | |||
| insertModelsDependency(modelsVersions.get(0)); | |||
| return "新增模型版本成功"; | |||
| } catch (Exception e) { | |||
| // 如果出现异常,返回异常消息 | |||
| @@ -7,7 +7,7 @@ import com.ruoyi.platform.domain.PodStatus; | |||
| import com.ruoyi.platform.service.TensorBoardService; | |||
| import com.ruoyi.platform.utils.K8sClientUtil; | |||
| 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 org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.stereotype.Service; | |||
| @@ -29,9 +29,9 @@ public class TensorBoardServiceImpl implements TensorBoardService { | |||
| @Resource | |||
| private K8sClientUtil k8sClientUtil; | |||
| @Override | |||
| public TensorboardStatusVo getTensorBoardStatus(FrameLogPathVo frameLogPathVo){ | |||
| public PodStatusVo getTensorBoardStatus(FrameLogPathVo frameLogPathVo){ | |||
| String status = PodStatus.Terminated.getName(); | |||
| TensorboardStatusVo tensorboardStatusVo = new TensorboardStatusVo(); | |||
| PodStatusVo tensorboardStatusVo = new PodStatusVo(); | |||
| tensorboardStatusVo.setStatus(status); | |||
| if (StringUtils.isEmpty(frameLogPathVo.getPath())){ | |||
| return tensorboardStatusVo; | |||
| @@ -133,7 +133,9 @@ public class WorkflowServiceImpl implements WorkflowService { | |||
| public String removeById(Long id) throws Exception { | |||
| //先根据id提取出对应的流水线 | |||
| Workflow workflow = workflowDao.queryById(id); | |||
| if (workflow == null){ | |||
| throw new Exception("流水线不存在"); | |||
| } | |||
| //判断权限,只有admin和创建者本身可以删除该流水线 | |||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||
| String username = loginUser.getUsername(); | |||
| @@ -142,9 +144,6 @@ public class WorkflowServiceImpl implements WorkflowService { | |||
| throw new Exception("无权限删除该流水线"); | |||
| } | |||
| if (workflow == null){ | |||
| throw new Exception("流水线不存在"); | |||
| } | |||
| //判断这个流水线是否有相关实验存在 | |||
| List<Experiment> experimentList = experimentService.queryByWorkflowId(id); | |||
| 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.List; | |||
| import java.util.Map; | |||
| import java.util.zip.GZIPInputStream; | |||
| /** | |||
| * HTTP请求工具类 | |||
| @@ -447,4 +448,38 @@ public class HttpUtils { | |||
| 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) { | |||
| try { | |||
| if (StringUtils.isEmpty(jsonStr)) { return new ArrayList<T>(); } | |||
| ObjectMapper objectMapper = getObjectMapper(dateFormat, false, false, true); | |||
| CollectionType listType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, clazz); | |||
| return objectMapper.readValue(jsonStr, listType); | |||
| @@ -1,8 +1,11 @@ | |||
| package com.ruoyi.platform.utils; | |||
| import com.fasterxml.jackson.core.JsonProcessingException; | |||
| import com.fasterxml.jackson.databind.ObjectMapper; | |||
| import org.json.JSONObject; | |||
| import java.io.IOException; | |||
| import java.util.HashMap; | |||
| import java.util.Iterator; | |||
| import java.util.Map; | |||
| public class JsonUtils { | |||
| @@ -28,4 +31,26 @@ public class JsonUtils { | |||
| public static <T> T jsonToObject(String json, Class<T> clazz) throws IOException { | |||
| 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<>(); | |||
| selector.put("k8s-jupyter", podName); | |||
| @@ -402,13 +402,13 @@ public class K8sClientUtil { | |||
| // 配置卷和卷挂载 | |||
| List<V1VolumeMount> volumeMounts = new ArrayList<>(); | |||
| 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<>(); | |||
| 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() | |||
| .withNewMetadata() | |||
| @@ -573,12 +573,8 @@ public class K8sClientUtil { | |||
| V1Pod pod = api.deleteNamespacedPod(podName, namespace, null, null, null, null, null, null); | |||
| return "Pod " + podName + " 删除请求已发送"; | |||
| } 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 java.io.Serializable; | |||
| import java.util.Date; | |||
| @Data | |||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | |||
| @@ -45,4 +46,10 @@ public class ModelVersionDependcyVo implements Serializable { | |||
| @ApiModelProperty(value = "文件大小") | |||
| 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; | |||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | |||
| public class TensorboardStatusVo implements Serializable { | |||
| public class PodStatusVo implements Serializable { | |||
| private String status; | |||
| private String url; | |||
| @@ -25,4 +25,5 @@ public class TensorboardStatusVo implements Serializable { | |||
| public void setUrl(String url) { | |||
| this.url = url; | |||
| } | |||
| } | |||
| @@ -12,7 +12,7 @@ | |||
| <result property="image" column="image" jdbcType="VARCHAR"/> | |||
| <result property="dataset" column="dataset" 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="createBy" column="create_by" jdbcType="VARCHAR"/> | |||
| <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/> | |||
| @@ -24,17 +24,18 @@ | |||
| <!--查询单个--> | |||
| <select id="queryById" resultMap="DevEnvironmentMap"> | |||
| 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 | |||
| where id = #{id} | |||
| where id = #{id} and state = 1 | |||
| </select> | |||
| <!--查询指定行数据--> | |||
| <select id="queryAllByLimit" resultMap="DevEnvironmentMap"> | |||
| 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 | |||
| <where> | |||
| state = 1 | |||
| <if test="devEnvironment.id != null"> | |||
| and id = #{devEnvironment.id} | |||
| </if> | |||
| @@ -62,8 +63,8 @@ | |||
| <if test="devEnvironment.model != null and devEnvironment.model != ''"> | |||
| and model = #{devEnvironment.model} | |||
| </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 test="devEnvironment.altField2 != null and devEnvironment.altField2 != ''"> | |||
| and alt_field2 = #{devEnvironment.altField2} | |||
| @@ -93,6 +94,7 @@ | |||
| select count(1) | |||
| from dev_environment | |||
| <where> | |||
| state = 1 | |||
| <if test="devEnvironment.id != null"> | |||
| and id = #{devEnvironment.id} | |||
| </if> | |||
| @@ -120,8 +122,8 @@ | |||
| <if test="devEnvironment.model != null and devEnvironment.model != ''"> | |||
| and model = #{devEnvironment.model} | |||
| </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 test="devEnvironment.altField2 != null and devEnvironment.altField2 != ''"> | |||
| and alt_field2 = #{devEnvironment.altField2} | |||
| @@ -146,7 +148,7 @@ | |||
| <!--新增所有列--> | |||
| <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}, | |||
| #{devEnvironment.status}, | |||
| #{devEnvironment.computingResource}, | |||
| @@ -155,7 +157,7 @@ | |||
| #{devEnvironment.image}, | |||
| #{devEnvironment.dataset}, | |||
| #{devEnvironment.model}, | |||
| #{devEnvironment.altField1}, | |||
| #{devEnvironment.url}, | |||
| #{devEnvironment.altField2}, | |||
| #{devEnvironment.createBy}, | |||
| #{devEnvironment.createTime}, | |||
| @@ -166,21 +168,21 @@ | |||
| </insert> | |||
| <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 | |||
| <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> | |||
| </insert> | |||
| <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 | |||
| <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> | |||
| 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> | |||
| <!--通过主键修改数据--> | |||
| @@ -211,8 +213,8 @@ name = values(name)status = values(status)computing_resource = values(computing_ | |||
| <if test="devEnvironment.model != null and devEnvironment.model != ''"> | |||
| model = #{devEnvironment.model}, | |||
| </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 test="devEnvironment.altField2 != null and devEnvironment.altField2 != ''"> | |||
| alt_field2 = #{devEnvironment.altField2}, | |||
| @@ -12,6 +12,7 @@ | |||
| <result property="nodesResult" column="nodes_result" jdbcType="VARCHAR"/> | |||
| <result property="nodesLogs" column="nodes_logs" 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="finishTime" column="finish_time" jdbcType="TIMESTAMP"/> | |||
| <result property="createBy" column="create_by" jdbcType="VARCHAR"/> | |||
| @@ -23,7 +24,7 @@ | |||
| <!--查询非终止态的实例--> | |||
| <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 | |||
| where (status NOT IN ('Terminated', 'Succeeded', 'Failed') | |||
| OR status IS NULL) and state = 1 | |||
| @@ -31,14 +32,14 @@ | |||
| <!--查询单个--> | |||
| <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 | |||
| where id = #{id} and state = 1 | |||
| </select> | |||
| <!--查询列表--> | |||
| <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 | |||
| where experiment_id = #{experiment_id} and state = 1 | |||
| order by create_time DESC | |||
| @@ -47,7 +48,7 @@ | |||
| <!--查询最近的3个实例列表--> | |||
| <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 | |||
| where state = 1 | |||
| order by create_time DESC | |||
| @@ -58,7 +59,7 @@ | |||
| <select id="queryByExperiment" 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 | |||
| 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 | |||
| <where> | |||
| state = 1 | |||
| @@ -86,6 +87,9 @@ | |||
| <if test="experimentIns.globalParam != null and experimentIns.globalParam != ''"> | |||
| and global_param = #{experimentIns.globalParam} | |||
| </if> | |||
| <if test="experimentIns.metricRecord != null and experimentIns.metricRecord != ''"> | |||
| and metric_record = #{experimentIns.metricRecord} | |||
| </if> | |||
| <if test="experimentIns.startTime != null"> | |||
| and start_time = #{experimentIns.startTime} | |||
| </if> | |||
| @@ -110,7 +114,7 @@ | |||
| <!--查询指定行数据--> | |||
| <select id="queryAllByLimit" 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 | |||
| 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 | |||
| <where> | |||
| state = 1 | |||
| @@ -138,6 +142,9 @@ | |||
| <if test="experimentIns.globalParam != null and experimentIns.globalParam != ''"> | |||
| and global_param = #{experimentIns.globalParam} | |||
| </if> | |||
| <if test="experimentIns.metricRecord != null and experimentIns.metricRecord != ''"> | |||
| and metric_record = #{experimentIns.metricRecord} | |||
| </if> | |||
| <if test="experimentIns.startTime != null"> | |||
| and start_time = #{experimentIns.startTime} | |||
| </if> | |||
| @@ -191,6 +198,9 @@ | |||
| <if test="experimentIns.globalParam != null and experimentIns.globalParam != ''"> | |||
| and global_param = #{experimentIns.globalParam} | |||
| </if> | |||
| <if test="experimentIns.metricRecord != null and experimentIns.metricRecord != ''"> | |||
| and metric_record = #{experimentIns.metricRecord} | |||
| </if> | |||
| <if test="experimentIns.startTime != null"> | |||
| and start_time = #{experimentIns.startTime} | |||
| </if> | |||
| @@ -213,23 +223,23 @@ | |||
| </select> | |||
| <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 | |||
| where experiment_id = #{id} and state = 1 | |||
| </select> | |||
| <!--新增所有列--> | |||
| <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 id="insertBatch" 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) | |||
| 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 | |||
| <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> | |||
| </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)--> | |||
| <!-- </insert>--> | |||
| <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 | |||
| <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> | |||
| ON DUPLICATE KEY UPDATE | |||
| experiment_id = VALUES(experiment_id), | |||
| @@ -258,6 +268,7 @@ | |||
| nodes_result = VALUES(nodes_result), | |||
| nodes_logs = VALUES(nodes_logs), | |||
| global_param = VALUES(global_param), | |||
| metric_record = VALUES(metric_record), | |||
| start_time = VALUES(start_time), | |||
| finish_time = VALUES(finish_time), | |||
| create_by = VALUES(create_by), | |||
| @@ -294,6 +305,9 @@ | |||
| <if test="experimentIns.globalParam != null and experimentIns.globalParam != ''"> | |||
| global_param = #{experimentIns.globalParam}, | |||
| </if> | |||
| <if test="experimentIns.metricRecord != null and experimentIns.metricRecord != ''"> | |||
| metric_record = #{experimentIns.metricRecord}, | |||
| </if> | |||
| <if test="experimentIns.startTime != null"> | |||
| start_time = #{experimentIns.startTime}, | |||
| </if> | |||
| @@ -14,12 +14,21 @@ | |||
| <result property="state" column="state" jdbcType="INTEGER"/> | |||
| </resultMap> | |||
| <!--查询单个--> | |||
| <!-- 查询单个 --> | |||
| <select id="queryById" resultMap="ImageMap"> | |||
| 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> | |||
| <!--查询指定行数据--> | |||
| @@ -22,12 +22,28 @@ | |||
| <result property="state" column="state" jdbcType="INTEGER"/> | |||
| </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,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> | |||
| 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> | |||
| </select> | |||
| @@ -321,7 +337,7 @@ | |||
| state = #{state}, | |||
| </if> | |||
| </set> | |||
| where id = #{id} and state = 1 | |||
| where id = #{id} | |||
| </update> | |||
| <!--通过主键删除--> | |||