From 5f9f29c43aaf32813341fdc619b37fd0bb868503 Mon Sep 17 00:00:00 2001 From: bjkim Date: Mon, 13 Oct 2025 20:10:59 +0900 Subject: [PATCH] =?UTF-8?q?[ADD]=20MLflow=20run=20=EB=8B=A8=EA=B1=B4=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controllers/MlflowController.java | 54 +++++++++++++++++-- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/src/main/java/kr/re/etri/autoflow/controllers/MlflowController.java b/src/main/java/kr/re/etri/autoflow/controllers/MlflowController.java index 773dcd4..d7aadc3 100644 --- a/src/main/java/kr/re/etri/autoflow/controllers/MlflowController.java +++ b/src/main/java/kr/re/etri/autoflow/controllers/MlflowController.java @@ -1,6 +1,8 @@ package kr.re.etri.autoflow.controllers; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -25,9 +27,20 @@ public class MlflowController { .build(); } - @Operation(summary = "Experiment 조회", description = "Experiment 이름으로 MLflow Experiment 정보를 조회합니다.") + @Operation( + summary = "Experiment 조회", + description = "Experiment 이름으로 MLflow Experiment 정보를 조회합니다.", + responses = { + @ApiResponse(responseCode = "200", description = "Experiment 정보 조회 성공"), + @ApiResponse(responseCode = "404", description = "Experiment를 찾을 수 없음"), + @ApiResponse(responseCode = "500", description = "서버 오류 발생") + } + ) @GetMapping(value = "/experiment", produces = MediaType.APPLICATION_JSON_VALUE) - public Map getExperimentByName(@RequestParam String experimentName) { + public Map getExperimentByName( + @Parameter(description = "조회할 Experiment 이름", required = true, example = "MyExperiment") + @RequestParam String experimentName) { + Map response = webClient.get() .uri(uriBuilder -> uriBuilder .path("/experiments/get-by-name") @@ -44,10 +57,42 @@ public class MlflowController { return (Map) response.get("experiment"); } + @Operation( + summary = "Run 단건 조회", + description = "주어진 Run ID의 상세 정보를 조회합니다. MLflow API `/runs/get`를 호출하여 Run 정보를 반환합니다.", + responses = { + @ApiResponse(responseCode = "200", description = "Run 정보 조회 성공"), + @ApiResponse(responseCode = "500", description = "서버 오류 발생") + } + ) + @GetMapping(value = "/run", produces = MediaType.APPLICATION_JSON_VALUE) + public Mono> getRun( + @Parameter(description = "조회할 Run ID", required = true, example = "59e4f75b29eb4354b9e9e2ec9d93e2e3") + @RequestParam String runId) { + + String uri = String.format("/runs/get?run_id=%s", runId); + + return webClient.get() + .uri(uri) + .retrieve() + .bodyToMono(String.class) + .map(ResponseEntity::ok) + .onErrorResume(e -> Mono.just(ResponseEntity.internalServerError().body(e.getMessage()))); + } - @Operation(summary = "Experiment의 Run 목록 조회", description = "주어진 Experiment ID의 Run을 최대 1000개까지 조회합니다.") + @Operation( + summary = "Experiment의 Run 목록 조회", + description = "주어진 Experiment ID의 Run을 최대 1000개까지 조회합니다. MLflow API `/runs/search`를 호출합니다.", + responses = { + @ApiResponse(responseCode = "200", description = "Run 목록 조회 성공"), + @ApiResponse(responseCode = "500", description = "서버 오류 발생") + } + ) @GetMapping(value = "/runs", produces = MediaType.APPLICATION_JSON_VALUE) - public Mono> getRuns(@RequestParam String experimentId) { + public Mono> getRuns( + @Parameter(description = "조회할 Experiment ID", required = true, example = "1234567890abcdef") + @RequestParam String experimentId) { + Map body = Map.of( "experiment_ids", Collections.singletonList(experimentId), "order_by", Collections.singletonList("attribute.start_time DESC"), @@ -63,5 +108,4 @@ public class MlflowController { .map(ResponseEntity::ok) .onErrorResume(e -> Mono.just(ResponseEntity.internalServerError().body(e.getMessage()))); } - }