|
|
|
@ -125,12 +125,14 @@ public class ExperimentsController {
|
|
|
|
// .doOnError(e -> log.error("Kubeflow experiment 등록 실패", e));
|
|
|
|
// .doOnError(e -> log.error("Kubeflow experiment 등록 실패", e));
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
@Operation(summary = "Experiment 등록 (Kubeflow + MLflow)")
|
|
|
|
|
|
|
|
@PostMapping
|
|
|
|
@PostMapping
|
|
|
|
@Transactional
|
|
|
|
@Transactional
|
|
|
|
public Mono<ResponseEntity<ExperimentsEntity>> createExperiment(@RequestBody ExperimentsEntity experiment) {
|
|
|
|
public Mono<ResponseEntity<ExperimentsEntity>> createExperiment(@RequestBody ExperimentsEntity experiment) {
|
|
|
|
|
|
|
|
|
|
|
|
ExperimentsEntity saved = experimentsService.save(experiment);
|
|
|
|
// DB에 미리 저장하지 않고, 메모리에 보관
|
|
|
|
|
|
|
|
ExperimentsEntity saved = new ExperimentsEntity();
|
|
|
|
|
|
|
|
saved.setDisplayName(experiment.getDisplayName());
|
|
|
|
|
|
|
|
saved.setDescription(experiment.getDescription());
|
|
|
|
|
|
|
|
|
|
|
|
Map<String, Object> kubeflowPayload = new HashMap<>();
|
|
|
|
Map<String, Object> kubeflowPayload = new HashMap<>();
|
|
|
|
kubeflowPayload.put("display_name", saved.getDisplayName());
|
|
|
|
kubeflowPayload.put("display_name", saved.getDisplayName());
|
|
|
|
@ -146,7 +148,6 @@ public class ExperimentsController {
|
|
|
|
.retrieve()
|
|
|
|
.retrieve()
|
|
|
|
.bodyToMono(Map.class)
|
|
|
|
.bodyToMono(Map.class)
|
|
|
|
.flatMap(kubeflowResp -> {
|
|
|
|
.flatMap(kubeflowResp -> {
|
|
|
|
// Kubeflow 응답 처리
|
|
|
|
|
|
|
|
if (kubeflowResp.containsKey("experiment_id")) {
|
|
|
|
if (kubeflowResp.containsKey("experiment_id")) {
|
|
|
|
saved.setKubeFlowId((String) kubeflowResp.get("experiment_id"));
|
|
|
|
saved.setKubeFlowId((String) kubeflowResp.get("experiment_id"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -157,18 +158,7 @@ public class ExperimentsController {
|
|
|
|
.toLocalDateTime()
|
|
|
|
.toLocalDateTime()
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (kubeflowResp.containsKey("last_run_created_at")) {
|
|
|
|
|
|
|
|
saved.setKubeflowLastRunCreatedAt(
|
|
|
|
|
|
|
|
Instant.parse((String) kubeflowResp.get("last_run_created_at"))
|
|
|
|
|
|
|
|
.atZone(ZoneId.of("Asia/Seoul"))
|
|
|
|
|
|
|
|
.toLocalDateTime()
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (kubeflowResp.containsKey("storage_state")) {
|
|
|
|
|
|
|
|
saved.setKubeflowStorageState((String) kubeflowResp.get("storage_state"));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
experimentsService.save(saved);
|
|
|
|
|
|
|
|
log.info("Kubeflow experiment 등록 완료: {}", kubeflowResp);
|
|
|
|
log.info("Kubeflow experiment 등록 완료: {}", kubeflowResp);
|
|
|
|
|
|
|
|
|
|
|
|
// 2️⃣ MLflow 등록
|
|
|
|
// 2️⃣ MLflow 등록
|
|
|
|
@ -188,56 +178,30 @@ public class ExperimentsController {
|
|
|
|
log.info("MLflow experiment 등록 완료: {}", createResp);
|
|
|
|
log.info("MLflow experiment 등록 완료: {}", createResp);
|
|
|
|
String mlflowExpId = (String) createResp.get("experiment_id");
|
|
|
|
String mlflowExpId = (String) createResp.get("experiment_id");
|
|
|
|
|
|
|
|
|
|
|
|
// 3️⃣ MLflow 조회
|
|
|
|
return webClientBuilder.build()
|
|
|
|
return webClientBuilder
|
|
|
|
|
|
|
|
.build()
|
|
|
|
|
|
|
|
.get()
|
|
|
|
.get()
|
|
|
|
.uri(mlflowBaseUrl + "/ajax-api/2.0/mlflow/experiments/get?experiment_id=" + mlflowExpId)
|
|
|
|
.uri(mlflowBaseUrl + "/ajax-api/2.0/mlflow/experiments/get?experiment_id=" + mlflowExpId)
|
|
|
|
.headers(headers -> headers.setBasicAuth(mlflowUser, mlflowPassword))
|
|
|
|
.headers(headers -> headers.setBasicAuth(mlflowUser, mlflowPassword))
|
|
|
|
.retrieve()
|
|
|
|
.retrieve()
|
|
|
|
.bodyToMono(Map.class)
|
|
|
|
.bodyToMono(Map.class)
|
|
|
|
.flatMap(getResp -> {
|
|
|
|
.map(getResp -> {
|
|
|
|
log.info("MLflow experiment 상세 조회 완료: {}", getResp);
|
|
|
|
|
|
|
|
// 필요한 필드를 entity에 반영
|
|
|
|
|
|
|
|
if (getResp.containsKey("experiment")) {
|
|
|
|
if (getResp.containsKey("experiment")) {
|
|
|
|
Map<String, Object> exp = (Map<String, Object>) getResp.get("experiment");
|
|
|
|
Map<String, Object> exp = (Map<String, Object>) getResp.get("experiment");
|
|
|
|
|
|
|
|
saved.setMlFlowId((String) exp.get("experiment_id"));
|
|
|
|
|
|
|
|
saved.setMlflow_artifactLocation((String) exp.get("artifact_location"));
|
|
|
|
|
|
|
|
saved.setMlflowLifecycleStage((String) exp.get("lifecycle_stage"));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MLflow 응답 필드 반영
|
|
|
|
// DB 저장은 외부 호출이 모두 성공한 이후
|
|
|
|
if (exp.containsKey("experiment_id")) {
|
|
|
|
ExperimentsEntity finalSaved = experimentsService.save(saved);
|
|
|
|
saved.setMlFlowId((String) exp.get("experiment_id"));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (exp.containsKey("artifact_location")) {
|
|
|
|
return ResponseEntity.ok(finalSaved);
|
|
|
|
saved.setMlflow_artifactLocation((String) exp.get("artifact_location"));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (exp.containsKey("lifecycle_stage")) {
|
|
|
|
|
|
|
|
saved.setMlflowLifecycleStage((String) exp.get("lifecycle_stage"));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (exp.containsKey("created_at")) {
|
|
|
|
|
|
|
|
// created_at은 timestamp(ms)로 올 수도 있으므로 Instant 변환
|
|
|
|
|
|
|
|
Object createdAtObj = exp.get("created_at");
|
|
|
|
|
|
|
|
Instant createdAtInstant = null;
|
|
|
|
|
|
|
|
if (createdAtObj instanceof Number) {
|
|
|
|
|
|
|
|
createdAtInstant = Instant.ofEpochMilli(((Number) createdAtObj).longValue());
|
|
|
|
|
|
|
|
} else if (createdAtObj instanceof String) {
|
|
|
|
|
|
|
|
createdAtInstant = Instant.parse((String) createdAtObj);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (createdAtInstant != null) {
|
|
|
|
|
|
|
|
saved.setMlflowCreatedAt(
|
|
|
|
|
|
|
|
createdAtInstant.atZone(ZoneId.of("Asia/Seoul")).toLocalDateTime()
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
experimentsService.save(saved);
|
|
|
|
|
|
|
|
return Mono.just(ResponseEntity.ok(saved));
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.doOnError(e -> log.error("Experiment 등록 실패", e));
|
|
|
|
.doOnError(e -> log.error("Experiment 등록 실패", e));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Operation(summary = "Experiment 수정")
|
|
|
|
@Operation(summary = "Experiment 수정")
|
|
|
|
@PutMapping("/{id}")
|
|
|
|
@PutMapping("/{id}")
|
|
|
|
public ResponseEntity<ExperimentsEntity> updateExperiment(
|
|
|
|
public ResponseEntity<ExperimentsEntity> updateExperiment(
|
|
|
|
|