From 5fc93b64b60f96e4b28e194c69aadef6286a2405 Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Tue, 23 Jun 2026 14:25:16 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A0=84=EC=9D=B4=ED=95=99=EC=8A=B5=20API=20?= =?UTF-8?q?=ED=98=B8=EC=B6=9C=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/ModelMngRepositoryImpl.java | 9 +++++++- .../training/train/dto/TrainRunRequest.java | 6 ++++++ .../train/service/DockerTrainService.java | 21 +++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/kamco/cd/training/postgres/repository/model/ModelMngRepositoryImpl.java b/src/main/java/com/kamco/cd/training/postgres/repository/model/ModelMngRepositoryImpl.java index d879bdb..abc86c2 100644 --- a/src/main/java/com/kamco/cd/training/postgres/repository/model/ModelMngRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/training/postgres/repository/model/ModelMngRepositoryImpl.java @@ -146,6 +146,8 @@ public class ModelMngRepositoryImpl implements ModelMngRepositoryCustom { @Override public TrainRunRequest findTrainRunRequest(Long modelId) { + QModelMasterEntity beforeModel = new QModelMasterEntity("beforeModel"); + return queryFactory .select( Projections.constructor( @@ -193,12 +195,17 @@ public class ModelMngRepositoryImpl implements ModelMngRepositoryCustom { Expressions.nullExpression(Integer.class), Expressions.nullExpression(String.class), modelHyperParamEntity.uuid, - modelMasterEntity.reqTmpYn)) + modelMasterEntity.reqTmpYn, + modelMasterEntity.trainType, + beforeModel.uuid, + beforeModel.bestEpoch)) .from(modelMasterEntity) .leftJoin(modelHyperParamEntity) .on(modelHyperParamEntity.id.eq(modelMasterEntity.hyperParamId)) .leftJoin(modelConfigEntity) .on(modelConfigEntity.model.id.eq(modelMasterEntity.id)) + .leftJoin(beforeModel) + .on(modelMasterEntity.beforeModelId.eq(beforeModel.id)) .where(modelMasterEntity.id.eq(modelId)) .fetchOne(); } diff --git a/src/main/java/com/kamco/cd/training/train/dto/TrainRunRequest.java b/src/main/java/com/kamco/cd/training/train/dto/TrainRunRequest.java index 45faef9..accf597 100644 --- a/src/main/java/com/kamco/cd/training/train/dto/TrainRunRequest.java +++ b/src/main/java/com/kamco/cd/training/train/dto/TrainRunRequest.java @@ -86,6 +86,12 @@ public class TrainRunRequest { private Boolean reqTmpYn; // tmp 심볼릭 링크를 쓰는지 아닌지 여부 + private String trainType; // 일반 : GENERAL, 전이 : TRANSFER + + private UUID beforeModelUUID; + private Integer + beforeBestEpoch; // 전이학습인 경우, before 모델 베스트 pth 경로를 보내야 해서 before 모델의 bestEpoch 을 조회하기 + public String getOutputFolder() { return String.valueOf(this.outputFolder); } diff --git a/src/main/java/com/kamco/cd/training/train/service/DockerTrainService.java b/src/main/java/com/kamco/cd/training/train/service/DockerTrainService.java index ca3a799..3dc6736 100644 --- a/src/main/java/com/kamco/cd/training/train/service/DockerTrainService.java +++ b/src/main/java/com/kamco/cd/training/train/service/DockerTrainService.java @@ -379,9 +379,30 @@ public class DockerTrainService { addArg(c, "--saturation-range", req.getSaturationRange()); addArg(c, "--hue-delta", req.getHueDelta()); + // 재시작을 위한 파라미터 if (req.getResumeFrom() != null && !req.getResumeFrom().isBlank()) { c.add("--resume"); addArg(c, "--load-from", req.getResumeFrom()); + } else if ("TRANSFER".equals(req.getTrainType()) + && req.getBeforeModelUUID() != null + && req.getBeforeBestEpoch() != null) { + // 재시작이 아닌데 전이학습인 경우, 전이학습을 위한 파라미터 + String finalLoadFromPath; + String bestModelFileName = "best_changed_fscore_epoch_" + req.getBeforeBestEpoch() + ".pth"; + String epochFileName = "epoch_" + req.getBeforeBestEpoch() + ".pth"; + + // 이전 모델 response 경로 + Path beforeModelDir = Path.of(responseDir).resolve(req.getBeforeModelUUID().toString()); + // 이전 모델 response 의 베스트 fscore pth 모델 파일 경로 + Path bestFilePath = beforeModelDir.resolve(bestModelFileName); + + // 베스트 fscore 파일이 있으면 그 경로를 사용, 없으면 epoch_00.pth 파일 경로 사용 + if (Files.exists(bestFilePath)) { + finalLoadFromPath = bestFilePath.toString(); + } else { + finalLoadFromPath = beforeModelDir.resolve(epochFileName).toString(); + } + addArg(c, "--load-from", finalLoadFromPath); } addArg(c, "--save-interval", 1);