| @@ -26,10 +26,11 @@ spec: | |||||
| volumeMounts: | volumeMounts: | ||||
| - name: resource-volume | - name: resource-volume | ||||
| mountPath: /home/resource/ | mountPath: /home/resource/ | ||||
| subPath: mini-model-platform-data | |||||
| volumes: | volumes: | ||||
| - name: resource-volume | - name: resource-volume | ||||
| persistentVolumeClaim: | |||||
| claimName: platform-data-pvc-nfs | |||||
| hostPath: | |||||
| path: /platform-data | |||||
| --- | --- | ||||
| apiVersion: v1 | apiVersion: v1 | ||||
| kind: Service | kind: Service | ||||
| @@ -24,19 +24,19 @@ public class AimController extends BaseController { | |||||
| @GetMapping("/getExpTrainInfos/{experiment_id}") | @GetMapping("/getExpTrainInfos/{experiment_id}") | ||||
| @ApiOperation("获取当前实验的模型训练指标信息") | @ApiOperation("获取当前实验的模型训练指标信息") | ||||
| @ApiResponse | @ApiResponse | ||||
| public GenericsAjaxResult<List<InsMetricInfoVo>> getExpTrainInfos(@RequestParam(value = "offset", required = false) String offset, | |||||
| @RequestParam(value = "limit") int limit, | |||||
| @PathVariable("experiment_id") Integer experimentId) throws Exception { | |||||
| return genericsSuccess(aimService.getExpTrainInfos(experimentId, offset, limit)); | |||||
| public GenericsAjaxResult<List<InsMetricInfoVo>> getExpTrainInfos(@RequestParam(value = "page") int page, | |||||
| @RequestParam(value = "size") int size, | |||||
| @PathVariable("experiment_id") Integer experimentId) { | |||||
| return genericsSuccess(aimService.getExpInfos(true, experimentId, page, size)); | |||||
| } | } | ||||
| @GetMapping("/getExpEvaluateInfos/{experiment_id}") | @GetMapping("/getExpEvaluateInfos/{experiment_id}") | ||||
| @ApiOperation("获取当前实验的模型推理指标信息") | @ApiOperation("获取当前实验的模型推理指标信息") | ||||
| @ApiResponse | @ApiResponse | ||||
| public GenericsAjaxResult<List<InsMetricInfoVo>> getExpEvaluateInfos(@RequestParam(value = "offset", required = false) String offset, | |||||
| @RequestParam(value = "limit") int limit, | |||||
| @PathVariable("experiment_id") Integer experimentId) throws Exception { | |||||
| return genericsSuccess(aimService.getExpEvaluateInfos(experimentId, offset, limit)); | |||||
| public GenericsAjaxResult<List<InsMetricInfoVo>> getExpEvaluateInfos(@RequestParam(value = "page") int page, | |||||
| @RequestParam(value = "size") int size, | |||||
| @PathVariable("experiment_id") Integer experimentId) { | |||||
| return genericsSuccess(aimService.getExpInfos(false, experimentId, page, size)); | |||||
| } | } | ||||
| @PostMapping("/getExpMetrics") | @PostMapping("/getExpMetrics") | ||||
| @@ -89,6 +89,12 @@ public class ServiceController extends BaseController { | |||||
| return genericsSuccess(serviceService.getServiceVersion(id)); | return genericsSuccess(serviceService.getServiceVersion(id)); | ||||
| } | } | ||||
| @GetMapping("serviceVersionCompare") | |||||
| @ApiOperation("服务版本版本对比") | |||||
| public GenericsAjaxResult<Map<String, Object>> serviceVersionCompare(@RequestParam("id1") Long id1, @RequestParam("id2") Long id2) throws IllegalAccessException { | |||||
| return genericsSuccess(serviceService.serviceVersionCompare(id1, id2)); | |||||
| } | |||||
| @GetMapping("/serviceVersionList/{id}") | @GetMapping("/serviceVersionList/{id}") | ||||
| @ApiOperation("查询服务版本列表") | @ApiOperation("查询服务版本列表") | ||||
| public GenericsAjaxResult<List<ServiceVersion>> serviceVersionList(@PathVariable("id") Long id) { | public GenericsAjaxResult<List<ServiceVersion>> serviceVersionList(@PathVariable("id") Long id) { | ||||
| @@ -49,32 +49,48 @@ public class ExperimentInstanceStatusTask { | |||||
| //运行成功的实验实例记录指标数值 | //运行成功的实验实例记录指标数值 | ||||
| if (Constant.Succeeded.equals(experimentIns.getStatus())) { | if (Constant.Succeeded.equals(experimentIns.getStatus())) { | ||||
| Map<String, Object> metricRecord = JacksonUtil.parseJSONStr2Map(experimentIns.getMetricRecord()); | Map<String, Object> metricRecord = JacksonUtil.parseJSONStr2Map(experimentIns.getMetricRecord()); | ||||
| List<Map<String, Object>> trainMetricRecord = (List<Map<String, Object>>) metricRecord.get("train"); | |||||
| List<Map<String, Object>> evaluateMetricRecord = (List<Map<String, Object>>) metricRecord.get("evaluate"); | |||||
| List<Map<String, Object>> trainMetricRecords = (List<Map<String, Object>>) metricRecord.get("train"); | |||||
| List<Map<String, Object>> evaluateMetricRecords = (List<Map<String, Object>>) metricRecord.get("evaluate"); | |||||
| HashMap<String, Object> metricValue = new HashMap<>(); | HashMap<String, Object> metricValue = new HashMap<>(); | ||||
| HashMap<String, Object> trainMetricValue = new HashMap<>(); | |||||
| HashMap<String, Object> evaluateMetricValue = new HashMap<>(); | |||||
| HashMap<String, Object> trainMetricValues = new HashMap<>(); | |||||
| HashMap<String, Object> evaluateMetricValues = new HashMap<>(); | |||||
| if (trainMetricRecord != null && !trainMetricRecord.isEmpty()) { | |||||
| String runId = (String) trainMetricRecord.get(0).get("run_id"); | |||||
| List<InsMetricInfoVo> expTrainInfos = aimService.getExpTrainInfos1(true, experimentIns.getExperimentId(), runId); | |||||
| for (InsMetricInfoVo expTrainInfo : expTrainInfos) { | |||||
| Map metrics = expTrainInfo.getMetrics(); | |||||
| trainMetricValue.putAll(metrics); | |||||
| if (trainMetricRecords != null && !trainMetricRecords.isEmpty()) { | |||||
| for (Map<String, Object> trainMetricRecord : trainMetricRecords) { | |||||
| HashMap<String, Object> trainMetricValue = new HashMap<>(); | |||||
| String taskId = (String) trainMetricRecord.get("task_id"); | |||||
| if (taskId.startsWith("model-train")) { | |||||
| String runId = (String) trainMetricRecord.get("run_id"); | |||||
| List<InsMetricInfoVo> expTrainInfos = aimService.getExpInfos1(true, experimentIns.getExperimentId(), runId); | |||||
| for (InsMetricInfoVo expTrainInfo : expTrainInfos) { | |||||
| Map metrics = expTrainInfo.getMetrics(); | |||||
| trainMetricValue.putAll(metrics); | |||||
| trainMetricValue.put("run_hash", expTrainInfo.getRunId()); | |||||
| } | |||||
| } | |||||
| trainMetricValues.put(taskId, trainMetricValue); | |||||
| } | } | ||||
| } | } | ||||
| if (evaluateMetricRecord != null && !evaluateMetricRecord.isEmpty()) { | |||||
| String runId = (String) evaluateMetricRecord.get(0).get("run_id"); | |||||
| List<InsMetricInfoVo> expTrainInfos = aimService.getExpTrainInfos1(false, experimentIns.getExperimentId(), runId); | |||||
| for (InsMetricInfoVo expTrainInfo : expTrainInfos) { | |||||
| Map metrics = expTrainInfo.getMetrics(); | |||||
| evaluateMetricValue.putAll(metrics); | |||||
| if (evaluateMetricRecords != null && !evaluateMetricRecords.isEmpty()) { | |||||
| for (Map<String, Object> evaluateMetricRecord : evaluateMetricRecords) { | |||||
| HashMap<String, Object> evaluateMetricValue = new HashMap<>(); | |||||
| String taskId = (String) evaluateMetricRecord.get("task_id"); | |||||
| if (taskId.startsWith("model-evaluate")) { | |||||
| String runId = (String) evaluateMetricRecord.get("run_id"); | |||||
| List<InsMetricInfoVo> expTrainInfos = aimService.getExpInfos1(false, experimentIns.getExperimentId(), runId); | |||||
| for (InsMetricInfoVo expTrainInfo : expTrainInfos) { | |||||
| Map metrics = expTrainInfo.getMetrics(); | |||||
| evaluateMetricValue.putAll(metrics); | |||||
| evaluateMetricValue.put("run_hash", expTrainInfo.getRunId()); | |||||
| } | |||||
| } | |||||
| evaluateMetricValues.put(taskId, evaluateMetricValue); | |||||
| } | } | ||||
| } | } | ||||
| metricValue.put("train", trainMetricValue); | |||||
| metricValue.put("evaluate", evaluateMetricValue); | |||||
| metricValue.put("train", trainMetricValues); | |||||
| metricValue.put("evaluate", evaluateMetricValues); | |||||
| experimentIns.setMetricValue(JsonUtils.mapToJson(metricValue)); | experimentIns.setMetricValue(JsonUtils.mapToJson(metricValue)); | ||||
| } | } | ||||
| experimentIns.setUpdateTime(new Date()); | experimentIns.setUpdateTime(new Date()); | ||||
| @@ -10,10 +10,12 @@ public interface AimService { | |||||
| List<InsMetricInfoVo> getExpTrainInfos(Integer experimentId, String offset, int limit) throws Exception; | List<InsMetricInfoVo> getExpTrainInfos(Integer experimentId, String offset, int limit) throws Exception; | ||||
| List<InsMetricInfoVo> getExpTrainInfos1(boolean isTrain, Integer experimentId, String runId) throws Exception; | |||||
| List<InsMetricInfoVo> getExpEvaluateInfos(Integer experimentId, String offset, int limit) throws Exception; | List<InsMetricInfoVo> getExpEvaluateInfos(Integer experimentId, String offset, int limit) throws Exception; | ||||
| List<InsMetricInfoVo> getExpInfos(boolean isTrain, Integer experimentId, int page, int size); | |||||
| List<InsMetricInfoVo> getExpInfos1(boolean isTrain, Integer experimentId, String runId) throws Exception; | |||||
| String getExpMetrics(List<String> runIds) throws Exception; | String getExpMetrics(List<String> runIds) throws Exception; | ||||
| HashMap<String, Object> queryMetricsParams(String runId) throws Exception; | HashMap<String, Object> queryMetricsParams(String runId) throws Exception; | ||||
| @@ -28,6 +28,8 @@ public interface ServiceService { | |||||
| ServiceVersionVo getServiceVersion(Long id); | ServiceVersionVo getServiceVersion(Long id); | ||||
| Map<String, Object> serviceVersionCompare(Long id1, Long id2) throws IllegalAccessException; | |||||
| String deleteService(Long id); | String deleteService(Long id); | ||||
| String deleteServiceVersion(Long id); | String deleteServiceVersion(Long id); | ||||
| @@ -1,7 +1,10 @@ | |||||
| package com.ruoyi.platform.service.impl; | package com.ruoyi.platform.service.impl; | ||||
| import com.alibaba.fastjson2.JSON; | import com.alibaba.fastjson2.JSON; | ||||
| import com.alibaba.fastjson2.JSONArray; | |||||
| import com.alibaba.fastjson2.JSONObject; | |||||
| import com.ruoyi.platform.domain.ExperimentIns; | import com.ruoyi.platform.domain.ExperimentIns; | ||||
| import com.ruoyi.platform.mapper.ExperimentInsDao; | |||||
| import com.ruoyi.platform.service.AimService; | import com.ruoyi.platform.service.AimService; | ||||
| import com.ruoyi.platform.service.ExperimentInsService; | import com.ruoyi.platform.service.ExperimentInsService; | ||||
| import com.ruoyi.platform.utils.AIM64EncoderUtil; | import com.ruoyi.platform.utils.AIM64EncoderUtil; | ||||
| @@ -11,6 +14,7 @@ import com.ruoyi.platform.utils.JsonUtils; | |||||
| import com.ruoyi.platform.vo.InsMetricInfoVo; | import com.ruoyi.platform.vo.InsMetricInfoVo; | ||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.data.domain.PageRequest; | |||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
| import javax.annotation.Resource; | import javax.annotation.Resource; | ||||
| @@ -23,6 +27,8 @@ import java.util.stream.Collectors; | |||||
| public class AimServiceImpl implements AimService { | public class AimServiceImpl implements AimService { | ||||
| @Resource | @Resource | ||||
| private ExperimentInsService experimentInsService; | private ExperimentInsService experimentInsService; | ||||
| @Resource | |||||
| private ExperimentInsDao experimentInsDao; | |||||
| @Value("${aim.url}") | @Value("${aim.url}") | ||||
| private String aimUrl; | private String aimUrl; | ||||
| @@ -145,9 +151,59 @@ public class AimServiceImpl implements AimService { | |||||
| return aimRunInfoList; | return aimRunInfoList; | ||||
| } | } | ||||
| public List<InsMetricInfoVo> getExpInfos(boolean isTrain, Integer experimentId, int page, int size) { | |||||
| PageRequest pageRequest = PageRequest.of(page, size); | |||||
| ExperimentIns query = new ExperimentIns(); | |||||
| query.setExperimentId(experimentId); | |||||
| List<ExperimentIns> experimentInsList = experimentInsDao.queryAllByLimit(query, pageRequest); | |||||
| if (experimentInsList == null || experimentInsList.size() == 0) { | |||||
| return new ArrayList<>(); | |||||
| } | |||||
| List<InsMetricInfoVo> aimRunInfoList = new ArrayList<>(); | |||||
| for (ExperimentIns experimentIns : experimentInsList) { | |||||
| InsMetricInfoVo aimRunInfo = new InsMetricInfoVo(); | |||||
| aimRunInfo.setExperimentInsId(experimentIns.getId()); | |||||
| aimRunInfo.setStartTime(experimentIns.getCreateTime()); | |||||
| aimRunInfo.setStatus(experimentIns.getStatus()); | |||||
| //解析参数 | |||||
| JSONArray params = JSON.parseArray(experimentIns.getGlobalParam()); | |||||
| HashMap<String, Object> paramsMap = new HashMap<>(); | |||||
| List<String> paramsNames = new ArrayList<>(); | |||||
| for (int i = 0; i < params.size(); i++) { | |||||
| JSONObject jsonObject = params.getJSONObject(i); | |||||
| String paramName = jsonObject.getString("param_name"); | |||||
| String paramValue = jsonObject.getString("param_value"); | |||||
| paramsMap.put(paramName, paramValue); | |||||
| paramsNames.add(paramName); | |||||
| } | |||||
| aimRunInfo.setParams(paramsMap); | |||||
| aimRunInfo.setParamsNames(paramsNames); | |||||
| //解析数据集 | |||||
| Map<String, Object> metricRecord = JacksonUtil.parseJSONStr2Map(experimentIns.getMetricRecord()); | |||||
| if (isTrain) { | |||||
| aimRunInfo.setDataset(getDataset("train", metricRecord)); | |||||
| } else { | |||||
| aimRunInfo.setDataset(getDataset("evaluate", metricRecord)); | |||||
| } | |||||
| //解析指标 | |||||
| Map<String, Object> metricValue = JacksonUtil.parseJSONStr2Map(experimentIns.getMetricValue()); | |||||
| if (isTrain) { | |||||
| setMetricValue("train",metricValue,aimRunInfo); | |||||
| } else { | |||||
| setMetricValue("evaluate",metricValue,aimRunInfo); | |||||
| } | |||||
| aimRunInfoList.add(aimRunInfo); | |||||
| } | |||||
| return aimRunInfoList; | |||||
| } | |||||
| @Override | @Override | ||||
| public List<InsMetricInfoVo> getExpTrainInfos1(boolean isTrain, Integer experimentId, String runId) throws Exception { | |||||
| public List<InsMetricInfoVo> getExpInfos1(boolean isTrain, Integer experimentId, String runId) throws Exception { | |||||
| String encodedUrlString = URLEncoder.encode("run.id==\"" + runId + "\"", "UTF-8"); | String encodedUrlString = URLEncoder.encode("run.id==\"" + runId + "\"", "UTF-8"); | ||||
| String url = aimProxyUrl + "/api/runs/search/run?query=" + encodedUrlString; | String url = aimProxyUrl + "/api/runs/search/run?query=" + encodedUrlString; | ||||
| String s = HttpUtils.sendGet(url, null); | String s = HttpUtils.sendGet(url, null); | ||||
| @@ -235,6 +291,40 @@ public class AimServiceImpl implements AimService { | |||||
| return aimRunInfoList; | return aimRunInfoList; | ||||
| } | } | ||||
| private List<String> getDataset(String isTrain, Map<String, Object> metricRecord) { | |||||
| List<String> datasetList = new ArrayList<>(); | |||||
| List<Map<String, Object>> trainMetricRecords = (List<Map<String, Object>>) metricRecord.get(isTrain); | |||||
| for (Map<String, Object> trainMetricRecord : trainMetricRecords) { | |||||
| String taskId = (String) trainMetricRecord.get("task_id"); | |||||
| if (taskId.startsWith("model-" + isTrain)) { | |||||
| List<Map<String, Object>> datasets = (List<Map<String, Object>>) trainMetricRecord.get("datasets"); | |||||
| for (Map<String, Object> dataset : datasets) { | |||||
| String datasetName = dataset.get("dataset_name") + ":" + dataset.get("dataset_version"); | |||||
| datasetList.add(datasetName); | |||||
| } | |||||
| } | |||||
| } | |||||
| return datasetList; | |||||
| } | |||||
| private void setMetricValue(String isTrain, Map<String, Object> metricValue, InsMetricInfoVo aimRunInfo){ | |||||
| Map<String, Object> metricValues = (Map<String, Object>) metricValue.get(isTrain); | |||||
| HashMap<String, Object> metrics = new HashMap<>(); | |||||
| List<String> metricsNames = new ArrayList<>(); | |||||
| for (String key : metricValues.keySet()) { | |||||
| Map<String, Object> valueMap = (Map<String, Object>) metricValues.get(key); | |||||
| aimRunInfo.setRunId((String) valueMap.get("run_hash")); | |||||
| metrics.putAll(valueMap.entrySet().stream().filter(entry -> !entry.getKey().equals("run_hash")).collect(Collectors.toMap( | |||||
| Map.Entry::getKey, | |||||
| Map.Entry::getValue | |||||
| ))); | |||||
| metricsNames.addAll(valueMap.keySet().stream().filter(entry -> !entry.equals("run_hash")).collect(Collectors.toList())); | |||||
| } | |||||
| aimRunInfo.setMetrics(metrics); | |||||
| aimRunInfo.setMetricsNames(metricsNames); | |||||
| } | |||||
| private List<String> getTrainDateSet(List<Map<String, Object>> records, String aimrunId) { | private List<String> getTrainDateSet(List<Map<String, Object>> records, String aimrunId) { | ||||
| List<String> datasetList = new ArrayList<>(); | List<String> datasetList = new ArrayList<>(); | ||||
| @@ -165,9 +165,9 @@ public class DatasetVersionServiceImpl implements DatasetVersionService { | |||||
| .findFirst() | .findFirst() | ||||
| .ifPresent(datasetVersion -> { | .ifPresent(datasetVersion -> { | ||||
| String url = datasetVersion.getUrl(); | String url = datasetVersion.getUrl(); | ||||
| // response.put("path", url); | |||||
| String path = bucketName + '/' + url.substring(0, url.lastIndexOf('/')); | |||||
| response.put("path", path); | |||||
| response.put("path", url); | |||||
| // String path = bucketName + '/' + url.substring(0, url.lastIndexOf('/')); | |||||
| // response.put("path", path); | |||||
| }); | }); | ||||
| response.put("content", datasetVersionList); | response.put("content", datasetVersionList); | ||||
| @@ -172,15 +172,6 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { | |||||
| public Page<ExperimentIns> queryByPage(ExperimentIns experimentIns, PageRequest pageRequest) throws IOException { | public Page<ExperimentIns> queryByPage(ExperimentIns experimentIns, PageRequest pageRequest) throws IOException { | ||||
| long total = this.experimentInsDao.count(experimentIns); | long total = this.experimentInsDao.count(experimentIns); | ||||
| List<ExperimentIns> experimentInsList = this.experimentInsDao.queryAllByLimit(experimentIns, pageRequest); | List<ExperimentIns> experimentInsList = this.experimentInsDao.queryAllByLimit(experimentIns, pageRequest); | ||||
| // if (experimentInsList!=null && experimentInsList.size()>0) { | |||||
| // for (ExperimentIns ins : experimentInsList) { | |||||
| // //如果实验实例不为空或者 | |||||
| // if (ins != null && StringUtils.isEmpty(ins.getStatus())) { | |||||
| // ins = this.queryStatusFromArgo(ins); | |||||
| // this.update(ins); | |||||
| // } | |||||
| // } | |||||
| // } | |||||
| return new PageImpl<>(experimentInsList, pageRequest, total); | return new PageImpl<>(experimentInsList, pageRequest, total); | ||||
| } | } | ||||
| @@ -61,10 +61,10 @@ public class ImageServiceImpl implements ImageService { | |||||
| @Resource | @Resource | ||||
| private MinioService minioService; | private MinioService minioService; | ||||
| // @Value("${minio.dataReleaseBucketName}") | |||||
| // private String bucketName; | |||||
| @Value("${harbor.bucketName}") | |||||
| @Value("${minio.dataReleaseBucketName}") | |||||
| private String bucketName; | private String bucketName; | ||||
| // @Value("${harbor.bucketName}") | |||||
| // private String bucketName; | |||||
| @Value("${harbor.repository}") | @Value("${harbor.repository}") | ||||
| private String repository; | private String repository; | ||||
| @Value("${harbor.harborUrl}") | @Value("${harbor.harborUrl}") | ||||
| @@ -101,14 +101,14 @@ public class JupyterServiceImpl implements JupyterService { | |||||
| //构造pod名称 | //构造pod名称 | ||||
| String podName = loginUser.getUsername().toLowerCase() + "-editor-pod" + "-" + id; | String podName = loginUser.getUsername().toLowerCase() + "-editor-pod" + "-" + id; | ||||
| //新建编辑器的pvc | //新建编辑器的pvc | ||||
| String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc"; | |||||
| V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName); | |||||
| // String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc"; | |||||
| // V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName); | |||||
| //TODO 设置镜像可配置,这里先用默认镜像启动pod | //TODO 设置镜像可配置,这里先用默认镜像启动pod | ||||
| // 调用修改后的 createPod 方法,传入额外的参数 | // 调用修改后的 createPod 方法,传入额外的参数 | ||||
| Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, pvc, devEnvironment, minioPvcName, datasetPath, modelPath); | |||||
| // Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, null, devEnvironment, minioPvcName, datasetPath, modelPath); | |||||
| // Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, pvc, devEnvironment, minioPvcName, datasetPath, modelPath); | |||||
| Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, null, devEnvironment, minioPvcName, datasetPath, modelPath); | |||||
| String url = masterIp + ":" + podPort; | String url = masterIp + ":" + podPort; | ||||
| redisService.setCacheObject(podName, masterIp + ":" + podPort); | redisService.setCacheObject(podName, masterIp + ":" + podPort); | ||||
| devEnvironment.setStatus("Pending"); | devEnvironment.setStatus("Pending"); | ||||
| @@ -1300,7 +1300,7 @@ public class ModelsServiceImpl implements ModelsService { | |||||
| for (int i = 0; i < trainMetrics.size(); i++) { | for (int i = 0; i < trainMetrics.size(); i++) { | ||||
| JSONObject jsonObject = trainMetrics.getJSONObject(i); | JSONObject jsonObject = trainMetrics.getJSONObject(i); | ||||
| String runId = jsonObject.getString("run_id"); | String runId = jsonObject.getString("run_id"); | ||||
| List<InsMetricInfoVo> expTrainInfos = aimsService.getExpTrainInfos1(true, modelMetaVo.getTrainTask().getExperimentId(), runId); | |||||
| List<InsMetricInfoVo> expTrainInfos = aimsService.getExpInfos1(true, modelMetaVo.getTrainTask().getExperimentId(), runId); | |||||
| for (InsMetricInfoVo expTrainInfo : expTrainInfos) { | for (InsMetricInfoVo expTrainInfo : expTrainInfos) { | ||||
| Map metrics1 = expTrainInfo.getMetrics(); | Map metrics1 = expTrainInfo.getMetrics(); | ||||
| train.putAll(metrics1); | train.putAll(metrics1); | ||||
| @@ -1322,7 +1322,7 @@ public class ModelsServiceImpl implements ModelsService { | |||||
| for (int i = 0; i < testMetrics.size(); i++) { | for (int i = 0; i < testMetrics.size(); i++) { | ||||
| JSONObject jsonObject = testMetrics.getJSONObject(i); | JSONObject jsonObject = testMetrics.getJSONObject(i); | ||||
| String runId = jsonObject.getString("run_id"); | String runId = jsonObject.getString("run_id"); | ||||
| List<InsMetricInfoVo> expTestInfos = aimsService.getExpTrainInfos1(false, modelMetaVo.getTrainTask().getExperimentId(), runId); | |||||
| List<InsMetricInfoVo> expTestInfos = aimsService.getExpInfos1(false, modelMetaVo.getTrainTask().getExperimentId(), runId); | |||||
| for (InsMetricInfoVo expTestInfo : expTestInfos) { | for (InsMetricInfoVo expTestInfo : expTestInfos) { | ||||
| Map metrics1 = expTestInfo.getMetrics(); | Map metrics1 = expTestInfo.getMetrics(); | ||||
| evaluate.putAll(metrics1); | evaluate.putAll(metrics1); | ||||
| @@ -43,9 +43,7 @@ public class ModelsVersionServiceImpl implements ModelsVersionService { | |||||
| @Resource | @Resource | ||||
| @Lazy | @Lazy | ||||
| private ModelDependencyService modelDependencyService; | private ModelDependencyService modelDependencyService; | ||||
| // 固定存储桶名 | |||||
| @Value("${minio.dataReleaseBucketName}") | |||||
| private String bucketName; | |||||
| /** | /** | ||||
| * 通过ID查询单条数据 | * 通过ID查询单条数据 | ||||
| @@ -7,6 +7,7 @@ import com.ruoyi.platform.constant.Constant; | |||||
| import com.ruoyi.platform.domain.ServiceVersion; | import com.ruoyi.platform.domain.ServiceVersion; | ||||
| import com.ruoyi.platform.mapper.ServiceDao; | import com.ruoyi.platform.mapper.ServiceDao; | ||||
| import com.ruoyi.platform.service.ServiceService; | import com.ruoyi.platform.service.ServiceService; | ||||
| import com.ruoyi.platform.utils.ConvertUtil; | |||||
| import com.ruoyi.platform.utils.HttpUtils; | import com.ruoyi.platform.utils.HttpUtils; | ||||
| import com.ruoyi.platform.utils.JacksonUtil; | import com.ruoyi.platform.utils.JacksonUtil; | ||||
| import com.ruoyi.platform.vo.serviceVos.ServiceCodeConfigVo; | import com.ruoyi.platform.vo.serviceVos.ServiceCodeConfigVo; | ||||
| @@ -157,6 +158,28 @@ public class ServiceServiceImpl implements ServiceService { | |||||
| return serviceVersionVo; | return serviceVersionVo; | ||||
| } | } | ||||
| @Override | |||||
| public Map<String, Object> serviceVersionCompare(Long id1, Long id2) throws IllegalAccessException { | |||||
| HashMap<String, Object> result = new HashMap<>(); | |||||
| ServiceVersion serviceVersion1 = serviceDao.getServiceVersionById(id1); | |||||
| ServiceVersion serviceVersion2 = serviceDao.getServiceVersionById(id2); | |||||
| com.ruoyi.platform.domain.Service service = serviceDao.getServiceById(serviceVersion1.getServiceId()); | |||||
| ServiceVersionVo serviceVersionVo1 = getServiceVersionVo(serviceVersion1); | |||||
| ServiceVersionVo serviceVersionVo2 = getServiceVersionVo(serviceVersion2); | |||||
| serviceVersionVo1.setServiceName(service.getServiceName()); | |||||
| serviceVersionVo2.setServiceName(service.getServiceName()); | |||||
| Map<String, String> compareMap = ConvertUtil.compareObjects(serviceVersion1, serviceVersion2); | |||||
| result.put("version1", serviceVersionVo1); | |||||
| result.put("version2", serviceVersionVo2); | |||||
| result.put("differences", compareMap); | |||||
| return result; | |||||
| } | |||||
| @Override | @Override | ||||
| public String deleteService(Long id) { | public String deleteService(Long id) { | ||||
| com.ruoyi.platform.domain.Service service = serviceDao.getServiceById(id); | com.ruoyi.platform.domain.Service service = serviceDao.getServiceById(id); | ||||
| @@ -59,17 +59,17 @@ public class TensorBoardServiceImpl implements TensorBoardService { | |||||
| @Override | @Override | ||||
| public String runTensorBoard(FrameLogPathVo frameLogPathVo) throws Exception { | public String runTensorBoard(FrameLogPathVo frameLogPathVo) throws Exception { | ||||
| if (StringUtils.isEmpty(frameLogPathVo.getPath())||StringUtils.isEmpty(frameLogPathVo.getPvcName())){ | |||||
| throw new Exception("存储路径或存储为空"); | |||||
| } | |||||
| // if (StringUtils.isEmpty(frameLogPathVo.getPath())) { | |||||
| // throw new Exception("存储路径为空"); | |||||
| // if (StringUtils.isEmpty(frameLogPathVo.getPath())||StringUtils.isEmpty(frameLogPathVo.getPvcName())){ | |||||
| // throw new Exception("存储路径或存储为空"); | |||||
| // } | // } | ||||
| if (StringUtils.isEmpty(frameLogPathVo.getPath())) { | |||||
| throw new Exception("存储路径为空"); | |||||
| } | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String podName = loginUser.getUsername().toLowerCase()+"-"+frameLogPathVo.getPath().split("/")[2]+ "-tensorboard-pod"; | String podName = loginUser.getUsername().toLowerCase()+"-"+frameLogPathVo.getPath().split("/")[2]+ "-tensorboard-pod"; | ||||
| Integer podPort = k8sClientUtil.createPodWithSubPath(podName, StringUtils.isEmpty(frameLogPathVo.getNamespace()) ? "default" : frameLogPathVo.getNamespace(), port, mountPath, frameLogPathVo.getPath(), frameLogPathVo.getPvcName(), image); | |||||
| // Integer podPort = k8sClientUtil.createPodWithSubPath(podName, StringUtils.isEmpty(frameLogPathVo.getNamespace()) ? "default" : frameLogPathVo.getNamespace(), port, mountPath, frameLogPathVo.getPath(), image); | |||||
| // Integer podPort = k8sClientUtil.createPodWithSubPath(podName, StringUtils.isEmpty(frameLogPathVo.getNamespace()) ? "default" : frameLogPathVo.getNamespace(), port, mountPath, frameLogPathVo.getPath(), frameLogPathVo.getPvcName(), image); | |||||
| Integer podPort = k8sClientUtil.createPodWithSubPath(podName, StringUtils.isEmpty(frameLogPathVo.getNamespace()) ? "default" : frameLogPathVo.getNamespace(), port, mountPath, frameLogPathVo.getPath(), image); | |||||
| redisService.setCacheObject(podName, masterIp + ":" + podPort); | redisService.setCacheObject(podName, masterIp + ":" + podPort); | ||||
| return masterIp + ":" + podPort; | return masterIp + ":" + podPort; | ||||
| } | } | ||||
| @@ -158,5 +158,40 @@ public class ConvertUtil { | |||||
| } | } | ||||
| return sb.toString(); | return sb.toString(); | ||||
| } | } | ||||
| private static String toSnakeCase(String camelCase) { | |||||
| return camelCase.replaceAll( | |||||
| String.format("%s|%s|%s", | |||||
| "(?<=[a-z])(?=[A-Z])", // 小写字母后接大写字母 | |||||
| "(?<=[^A-Z])(?=[A-Z][a-z])", // 非大写字母后接大写字母开头的小写字母 | |||||
| "(?<=[A-Z])(?=[A-Z][a-z][0-9])" // 大写字母后接另一个大写字母开头的小写字母和数字(可选,根据需求调整) | |||||
| ), | |||||
| "_" | |||||
| ).toLowerCase(); | |||||
| } | |||||
| public static Map<String, String> compareObjects(Object obj1, Object obj2) throws IllegalAccessException { | |||||
| Map<String, String> differences = new HashMap<>(); | |||||
| // Get the class of the first object | |||||
| Class<?> clazz = obj1.getClass(); | |||||
| // Iterate over all fields of the class | |||||
| for (Field field : clazz.getDeclaredFields()) { | |||||
| // Set the fields to be accessible | |||||
| field.setAccessible(true); | |||||
| // Get the field value from both objects | |||||
| Object value1 = field.get(obj1); | |||||
| Object value2 = field.get(obj2); | |||||
| // Compare the field values | |||||
| if ((value1 !=null && !value1.equals(value2)) || (value2 !=null && !value2.equals(value1))) { | |||||
| differences.put(toSnakeCase(field.getName()), "Field " + field.getName() + " differs: " + value1 + " vs " + value2); | |||||
| } | |||||
| } | |||||
| return differences; | |||||
| } | |||||
| } | } | ||||
| @@ -36,8 +36,8 @@ import java.util.*; | |||||
| @Component | @Component | ||||
| public class K8sClientUtil { | public class K8sClientUtil { | ||||
| // @Value("${jupyter.hostPath}") | |||||
| // private String hostPath; | |||||
| @Value("${jupyter.hostPath}") | |||||
| private String hostPath; | |||||
| private String http; | private String http; | ||||
| private String token; | private String token; | ||||
| @@ -316,8 +316,8 @@ public class K8sClientUtil { | |||||
| * @param image 镜像 | * @param image 镜像 | ||||
| * @return 创建成功的pod,的nodePort端口 | * @return 创建成功的pod,的nodePort端口 | ||||
| */ | */ | ||||
| public Integer createPodWithSubPath(String podName, String namespace, Integer port, String mountPath, String subPath, String pvcName, String image) { | |||||
| // public Integer createPodWithSubPath(String podName, String namespace, Integer port, String mountPath, String subPath, String image) { | |||||
| // public Integer createPodWithSubPath(String podName, String namespace, Integer port, String mountPath, String subPath, String pvcName, String image) { | |||||
| public Integer createPodWithSubPath(String podName, String namespace, Integer port, String mountPath, String subPath, String image) { | |||||
| Map<String, String> selector = new LinkedHashMap<>(); | Map<String, String> selector = new LinkedHashMap<>(); | ||||
| selector.put("k8s-jupyter", podName); | selector.put("k8s-jupyter", podName); | ||||
| @@ -341,6 +341,9 @@ public class K8sClientUtil { | |||||
| } | } | ||||
| } | } | ||||
| int lastIndex = hostPath.lastIndexOf('/'); | |||||
| String newPath = hostPath.substring(0, lastIndex); | |||||
| V1Pod pod = new V1PodBuilder() | V1Pod pod = new V1PodBuilder() | ||||
| .withNewMetadata() | .withNewMetadata() | ||||
| .withName(podName) | .withName(podName) | ||||
| @@ -368,8 +371,8 @@ public class K8sClientUtil { | |||||
| .endContainer() | .endContainer() | ||||
| .addNewVolume() | .addNewVolume() | ||||
| .withName("workspace") | .withName("workspace") | ||||
| // .withHostPath(new V1HostPathVolumeSource().path(hostPath).type("DirectoryOrCreate")) | |||||
| .withPersistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvcName)) | |||||
| .withHostPath(new V1HostPathVolumeSource().path(newPath).type("DirectoryOrCreate")) | |||||
| // .withPersistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvcName)) | |||||
| .endVolume() | .endVolume() | ||||
| .withTerminationGracePeriodSeconds(14400L) | .withTerminationGracePeriodSeconds(14400L) | ||||
| .endSpec() | .endSpec() | ||||
| @@ -451,25 +454,25 @@ public class K8sClientUtil { | |||||
| } | } | ||||
| } | } | ||||
| // 配置卷和卷挂载 | |||||
| // List<V1VolumeMount> volumeMounts = new ArrayList<>(); | |||||
| // volumeMounts.add(new V1VolumeMount().name("workspace").mountPath("/opt/notebooks")); | |||||
| // volumeMounts.add(new V1VolumeMount().name("data").mountPath("/opt/dataset").subPath(datasetPath).readOnly(true)); | |||||
| // volumeMounts.add(new V1VolumeMount().name("data").mountPath("/opt/model").subPath(modelPath).readOnly(true)); | |||||
| // | |||||
| // List<V1Volume> volumes = new ArrayList<>(); | |||||
| // volumes.add(new V1Volume().name("workspace").hostPath(new V1HostPathVolumeSource().path(hostPath + "/" + podName + "/notebooks").type("DirectoryOrCreate"))); | |||||
| // volumes.add(new V1Volume().name("data").hostPath(new V1HostPathVolumeSource().path(hostPath).type("DirectoryOrCreate"))); | |||||
| // 配置卷和卷挂载 | // 配置卷和卷挂载 | ||||
| List<V1VolumeMount> volumeMounts = new ArrayList<>(); | List<V1VolumeMount> volumeMounts = new ArrayList<>(); | ||||
| volumeMounts.add(new V1VolumeMount().name("workspace").mountPath(mountPath)); | |||||
| volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/data").subPath(datasetPath).readOnly(true)); | |||||
| volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/model").subPath(modelPath).readOnly(true)); | |||||
| volumeMounts.add(new V1VolumeMount().name("workspace").mountPath("/opt/notebooks")); | |||||
| volumeMounts.add(new V1VolumeMount().name("data").mountPath("/opt/dataset").subPath(datasetPath).readOnly(true)); | |||||
| volumeMounts.add(new V1VolumeMount().name("data").mountPath("/opt/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("minio-pvc").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(dataPvcName))); | |||||
| volumes.add(new V1Volume().name("workspace").hostPath(new V1HostPathVolumeSource().path(hostPath + "/" + podName + "/notebooks").type("DirectoryOrCreate"))); | |||||
| volumes.add(new V1Volume().name("data").hostPath(new V1HostPathVolumeSource().path(hostPath).type("DirectoryOrCreate"))); | |||||
| // 配置卷和卷挂载 | |||||
| // List<V1VolumeMount> volumeMounts = new ArrayList<>(); | |||||
| // volumeMounts.add(new V1VolumeMount().name("workspace").mountPath(mountPath)); | |||||
| // volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/data").subPath(datasetPath).readOnly(true)); | |||||
| // volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/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("minio-pvc").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(dataPvcName))); | |||||
| //配置资源 | //配置资源 | ||||
| @@ -394,21 +394,24 @@ public class MinioUtil { | |||||
| for (Result<Item> result : results) { | for (Result<Item> result : results) { | ||||
| Item item = result.get(); | Item item = result.get(); | ||||
| String objectName = item.objectName(); | String objectName = item.objectName(); | ||||
| InputStream objectStream = minioClient.getObject( | |||||
| GetObjectArgs.builder().bucket(bucketName).object(objectName).build()); | |||||
| // Create a zip entry for each object | |||||
| ZipEntry zipEntry = new ZipEntry(objectName); | |||||
| zip.putNextEntry(zipEntry); | |||||
| // Write object data to zip stream | |||||
| byte[] buffer = new byte[1024]; | |||||
| int bytesRead; | |||||
| while ((bytesRead = objectStream.read(buffer)) != -1) { | |||||
| zip.write(buffer, 0, bytesRead); | |||||
| if (!objectName.contains(".git")) { | |||||
| InputStream objectStream = minioClient.getObject( | |||||
| GetObjectArgs.builder().bucket(bucketName).object(objectName).build()); | |||||
| // Create a zip entry for each object | |||||
| ZipEntry zipEntry = new ZipEntry(objectName); | |||||
| zip.putNextEntry(zipEntry); | |||||
| // Write object data to zip stream | |||||
| byte[] buffer = new byte[1024]; | |||||
| int bytesRead; | |||||
| while ((bytesRead = objectStream.read(buffer)) != -1) { | |||||
| zip.write(buffer, 0, bytesRead); | |||||
| } | |||||
| zip.closeEntry(); | |||||
| objectStream.close(); | |||||
| } | } | ||||
| zip.closeEntry(); | |||||
| objectStream.close(); | |||||
| } | } | ||||
| zip.finish(); | zip.finish(); | ||||
| @@ -10,7 +10,7 @@ public class FrameLogPathVo implements Serializable { | |||||
| String path; | String path; | ||||
| String namespace; | String namespace; | ||||
| String pvcName; | |||||
| // String pvcName; | |||||
| public String getPath() { | public String getPath() { | ||||
| return path; | return path; | ||||
| } | } | ||||
| @@ -27,11 +27,11 @@ public class FrameLogPathVo implements Serializable { | |||||
| this.namespace = namespace; | this.namespace = namespace; | ||||
| } | } | ||||
| public String getPvcName() { | |||||
| return pvcName; | |||||
| } | |||||
| public void setPvcName(String pvcName) { | |||||
| this.pvcName = pvcName; | |||||
| } | |||||
| // public String getPvcName() { | |||||
| // return pvcName; | |||||
| // } | |||||
| // | |||||
| // public void setPvcName(String pvcName) { | |||||
| // this.pvcName = pvcName; | |||||
| // } | |||||
| } | } | ||||
| @@ -275,10 +275,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,metric_record, 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, metric_value) | |||||
| 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.metricRecord}, #{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}, #{item.metricValue}) | |||||
| </foreach> | </foreach> | ||||
| ON DUPLICATE KEY UPDATE | ON DUPLICATE KEY UPDATE | ||||
| experiment_id = VALUES(experiment_id), | experiment_id = VALUES(experiment_id), | ||||
| @@ -296,7 +296,8 @@ | |||||
| create_time = VALUES(create_time), | create_time = VALUES(create_time), | ||||
| update_by = VALUES(update_by), | update_by = VALUES(update_by), | ||||
| update_time = VALUES(update_time), | update_time = VALUES(update_time), | ||||
| state = VALUES(state); | |||||
| state = VALUES(state), | |||||
| metric_value = VALUES(metric_value); | |||||
| </update> | </update> | ||||
| <update id="update"> | <update id="update"> | ||||