12 Commits

17 changed files with 189 additions and 51 deletions

View File

@@ -1,7 +1,10 @@
services: services:
kamco-changedetection-api: kamco-changedetection-api:
image: kamco-train-app:latest build:
container_name: kamco-train-api context: .
dockerfile: Dockerfile-dev
image: kamco-cd-training-api:${IMAGE_TAG:-latest}
container_name: kamco-cd-training-api
deploy: deploy:
resources: resources:
reservations: reservations:
@@ -9,13 +12,13 @@ services:
- driver: nvidia - driver: nvidia
count: all count: all
capabilities: [gpu] capabilities: [gpu]
ports:
- "7200:8080"
environment: environment:
- SPRING_PROFILES_ACTIVE=dev - SPRING_PROFILES_ACTIVE=dev
- TZ=Asia/Seoul - TZ=Asia/Seoul
- cors.allowed-origins=*
- cors.allowed-origins[0]=*
volumes: volumes:
- /data/training:/data/training - /backup/data/training:/backup/data/training
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
networks: networks:
- kamco-cds - kamco-cds

View File

@@ -37,7 +37,8 @@ public class GpuDmonReader {
int avg = int avg =
deque.isEmpty() deque.isEmpty()
? 0 ? 0
: (int) Math.round(deque.stream().mapToInt(Integer::intValue).average().orElse(0)); : (int)
Math.round(deque.stream().mapToInt(Integer::intValue).average().orElse(0));
result.put(gpu, avg); result.put(gpu, avg);
} }
}); });
@@ -98,8 +99,7 @@ public class GpuDmonReader {
Process process = pb.start(); Process process = pb.start();
// 프로세스 실행 후 stdout 읽기 // 프로세스 실행 후 stdout 읽기
try (BufferedReader br = try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line; String line;

View File

@@ -1,7 +1,12 @@
package com.kamco.cd.training.common.utils; package com.kamco.cd.training.common.utils;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@Slf4j
public final class HeaderUtil { public final class HeaderUtil {
private HeaderUtil() {} private HeaderUtil() {}
@@ -20,4 +25,20 @@ public final class HeaderUtil {
public static String getRequired(HttpServletRequest request, String headerName) { public static String getRequired(HttpServletRequest request, String headerName) {
return get(request, headerName); return get(request, headerName);
} }
public static boolean isEnglishRequest() {
RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
if (!(attrs instanceof ServletRequestAttributes servletAttrs)) {
return false;
}
String acceptLanguage = servletAttrs.getRequest().getHeader("Accept-Language");
if (acceptLanguage == null || acceptLanguage.isBlank()) {
return false;
}
return acceptLanguage.toLowerCase().startsWith("en");
}
} }

View File

@@ -1,5 +1,6 @@
package com.kamco.cd.training.common.utils.enums; package com.kamco.cd.training.common.utils.enums;
import com.kamco.cd.training.common.utils.HeaderUtil;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -31,10 +32,11 @@ public class Enums {
// enum -> CodeDto list // enum -> CodeDto list
public static List<CodeDto> toList(Class<? extends Enum<?>> enumClass) { public static List<CodeDto> toList(Class<? extends Enum<?>> enumClass) {
Object[] enums = enumClass.getEnumConstants(); Object[] enums = enumClass.getEnumConstants();
boolean english = HeaderUtil.isEnglishRequest();
return Arrays.stream(enums) return Arrays.stream(enums)
.map(e -> (EnumType) e) .map(e -> (EnumType) e)
.map(e -> new CodeDto(e.getId(), e.getText())) .map(e -> new CodeDto(e.getId(), english ? e.getId() : e.getText()))
.toList(); .toList();
} }

View File

@@ -293,6 +293,8 @@ public class DatasetApiController {
DatasetService.validateTrainValTestDirs(req.getFilePath()); DatasetService.validateTrainValTestDirs(req.getFilePath());
// 파일 개수 검증 // 파일 개수 검증
DatasetService.validateDirFileCount(req.getFilePath()); DatasetService.validateDirFileCount(req.getFilePath());
// 폴더명(uid)으로 등록한 건이 있는지 체크
datasetService.validateExistsUidChk(req.getFilePath());
datasetAsyncService.insertDeliveriesDatasetAsync(req); datasetAsyncService.insertDeliveriesDatasetAsync(req);
return ApiResponseDto.createOK("ok"); return ApiResponseDto.createOK("ok");

View File

@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import com.kamco.cd.training.common.enums.LearnDataRegister; import com.kamco.cd.training.common.enums.LearnDataRegister;
import com.kamco.cd.training.common.enums.LearnDataType; import com.kamco.cd.training.common.enums.LearnDataType;
import com.kamco.cd.training.common.enums.ModelType; import com.kamco.cd.training.common.enums.ModelType;
import com.kamco.cd.training.common.utils.HeaderUtil;
import com.kamco.cd.training.common.utils.enums.Enums; import com.kamco.cd.training.common.utils.enums.Enums;
import com.kamco.cd.training.common.utils.interfaces.JsonFormatDttm; import com.kamco.cd.training.common.utils.interfaces.JsonFormatDttm;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
@@ -90,7 +91,8 @@ public class DatasetDto {
public String getStatus(String status) { public String getStatus(String status) {
LearnDataRegister type = Enums.fromId(LearnDataRegister.class, status); LearnDataRegister type = Enums.fromId(LearnDataRegister.class, status);
return type == null ? null : type.getText(); boolean english = HeaderUtil.isEnglishRequest();
return type == null ? null : (english ? type.getId() : type.getText());
} }
public String getYear() { public String getYear() {
@@ -99,7 +101,8 @@ public class DatasetDto {
public String getDataTypeName() { public String getDataTypeName() {
LearnDataType type = Enums.fromId(LearnDataType.class, this.dataType); LearnDataType type = Enums.fromId(LearnDataType.class, this.dataType);
return type == null ? null : type.getText(); boolean english = HeaderUtil.isEnglishRequest();
return type == null ? null : (english ? type.getId() : type.getText());
} }
} }
@@ -315,7 +318,7 @@ public class DatasetDto {
public String getDataTypeName(String groupTitleCd) { public String getDataTypeName(String groupTitleCd) {
LearnDataType type = Enums.fromId(LearnDataType.class, groupTitleCd); LearnDataType type = Enums.fromId(LearnDataType.class, groupTitleCd);
return type == null ? null : type.getText(); return type == null ? null : (HeaderUtil.isEnglishRequest() ? type.getId() : type.getText());
} }
public String getYear() { public String getYear() {

View File

@@ -5,6 +5,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.kamco.cd.training.common.enums.DetectionClassification; import com.kamco.cd.training.common.enums.DetectionClassification;
import com.kamco.cd.training.common.utils.HeaderUtil;
import com.kamco.cd.training.common.utils.interfaces.JsonFormatDttm; import com.kamco.cd.training.common.utils.interfaces.JsonFormatDttm;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
@@ -131,7 +132,10 @@ public class DatasetObjDto {
private String classCd; private String classCd;
public String getClassName() { public String getClassName() {
return DetectionClassification.fromString(classCd).getDesc();
return HeaderUtil.isEnglishRequest()
? DetectionClassification.fromString(classCd).getId()
: DetectionClassification.fromString(classCd).getDesc();
// fromString 메서드를 사용하여 안전하게 변환 (미정의 값은 ETC로 처리) // fromString 메서드를 사용하여 안전하게 변환 (미정의 값은 ETC로 처리)
// return DetectionClassification.valueOf(classCd.toUpperCase()).getDesc(); // return DetectionClassification.valueOf(classCd.toUpperCase()).getDesc();
} }

View File

@@ -4,7 +4,11 @@ import com.kamco.cd.training.common.enums.LearnDataRegister;
import com.kamco.cd.training.dataset.dto.DatasetDto.AddDeliveriesReq; import com.kamco.cd.training.dataset.dto.DatasetDto.AddDeliveriesReq;
import com.kamco.cd.training.dataset.dto.DatasetDto.DatasetMngRegDto; import com.kamco.cd.training.dataset.dto.DatasetDto.DatasetMngRegDto;
import com.kamco.cd.training.postgres.core.DatasetCoreService; import com.kamco.cd.training.postgres.core.DatasetCoreService;
import java.util.UUID; import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
@@ -45,7 +49,11 @@ public class DatasetAsyncService {
try { try {
// ===== 1. UID 생성 ===== // ===== 1. UID 생성 =====
String uid = UUID.randomUUID().toString().replace("-", "").toUpperCase(); // String uid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
// 26-05-08: UID를 생성하지 않고 folder name 을 uid 로 저장하기 -> req.getFilePath()
Path selectedPath = Paths.get(req.getFilePath());
String uid = selectedPath.getFileName().toString();
log.info("{} 생성된 UID: {}", LOG_PREFIX, uid); log.info("{} 생성된 UID: {}", LOG_PREFIX, uid);
// ===== 2. 마스터 데이터 생성 ===== // ===== 2. 마스터 데이터 생성 =====
@@ -71,6 +79,7 @@ public class DatasetAsyncService {
datasetMngRegDto.setTitle(title); datasetMngRegDto.setTitle(title);
datasetMngRegDto.setMemo(req.getMemo()); datasetMngRegDto.setMemo(req.getMemo());
datasetMngRegDto.setDatasetPath(req.getFilePath()); datasetMngRegDto.setDatasetPath(req.getFilePath());
datasetMngRegDto.setTotalSize(getDirectorySize(req.getFilePath())); // 선택한 폴더 안의 모든 파일 용량 합계
// 마스터 저장 // 마스터 저장
datasetUid = datasetCoreService.insertDatasetMngData(datasetMngRegDto); datasetUid = datasetCoreService.insertDatasetMngData(datasetMngRegDto);
@@ -121,4 +130,24 @@ public class DatasetAsyncService {
} }
} }
} }
private Long getDirectorySize(String filePath) {
Path selectedPath = Paths.get(filePath);
try (Stream<Path> paths = Files.walk(selectedPath)) {
return paths
.filter(Files::isRegularFile)
.mapToLong(
path -> {
try {
return Files.size(path);
} catch (IOException e) {
return 0L;
}
})
.sum();
} catch (IOException e) {
return 0L;
}
}
} }

View File

@@ -286,7 +286,7 @@ public class DatasetService {
.memo(addReq.getMemo()) .memo(addReq.getMemo())
.roundNo(stage) .roundNo(stage)
.totalSize(addReq.getFileSize()) .totalSize(addReq.getFileSize())
.datasetPath(addReq.getFilePath()) .datasetPath(addReq.getFilePath() + uid)
.build(); .build();
datasetUid = datasetCoreService.insertDatasetMngData(mngRegDto); // tb_dataset 에 insert datasetUid = datasetCoreService.insertDatasetMngData(mngRegDto); // tb_dataset 에 insert
@@ -676,4 +676,18 @@ public class DatasetService {
total, total,
System.currentTimeMillis() - start); System.currentTimeMillis() - start);
} }
public void validateExistsUidChk(String filePath) {
Path selectedPath = Paths.get(filePath);
String uid = selectedPath.getFileName().toString();
// 같은 uid 로 등록한 파일이 있는지 확인
Long existsCnt = datasetCoreService.findDatasetByUidExistsCnt(uid);
if (existsCnt > 0) {
throw new CustomApiException(
ApiResponseCode.DUPLICATE_DATA.getId(),
HttpStatus.CONFLICT,
"이미 등록된 회차 데이터 파일입니다. 확인 부탁드립니다.");
}
}
} }

View File

@@ -277,9 +277,7 @@ public class FileManagerDto {
@Schema(description = "디스크 사용률 (%)", example = "50.5") @Schema(description = "디스크 사용률 (%)", example = "50.5")
private Double usagePercentage; private Double usagePercentage;
@JsonFormatDttm private ZonedDateTime lastModifiedDate;
@JsonFormatDttm
private ZonedDateTime lastModifiedDate;
public ZonedDateTime getLastModifiedDate() { public ZonedDateTime getLastModifiedDate() {
return ZonedDateTime.now(); return ZonedDateTime.now();

View File

@@ -627,8 +627,7 @@ public class FileManagerService {
duPb.redirectErrorStream(true); duPb.redirectErrorStream(true);
Process duProcess = duPb.start(); Process duProcess = duPb.start();
try (java.io.BufferedReader br = try (java.io.BufferedReader br =
new java.io.BufferedReader( new java.io.BufferedReader(new java.io.InputStreamReader(duProcess.getInputStream()))) {
new java.io.InputStreamReader(duProcess.getInputStream()))) {
String line = br.readLine(); String line = br.readLine();
if (line != null) { if (line != null) {
// du -sb 출력 형식: "12345678\t/path/to/dir" // du -sb 출력 형식: "12345678\t/path/to/dir"

View File

@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.kamco.cd.training.common.enums.LearnDataType; import com.kamco.cd.training.common.enums.LearnDataType;
import com.kamco.cd.training.common.enums.TrainStatusType; import com.kamco.cd.training.common.enums.TrainStatusType;
import com.kamco.cd.training.common.enums.TrainType; import com.kamco.cd.training.common.enums.TrainType;
import com.kamco.cd.training.common.utils.HeaderUtil;
import com.kamco.cd.training.common.utils.enums.Enums; import com.kamco.cd.training.common.utils.enums.Enums;
import com.kamco.cd.training.common.utils.interfaces.JsonFormatDttm; import com.kamco.cd.training.common.utils.interfaces.JsonFormatDttm;
import com.kamco.cd.training.dataset.dto.DatasetDto.SelectTransferDataSet; import com.kamco.cd.training.dataset.dto.DatasetDto.SelectTransferDataSet;
@@ -32,6 +33,8 @@ public class ModelTrainDetailDto {
private String modelNo; private String modelNo;
private String modelVer; private String modelVer;
@JsonFormatDttm private ZonedDateTime step1StrtDttm; @JsonFormatDttm private ZonedDateTime step1StrtDttm;
@JsonFormatDttm private ZonedDateTime step1EndDttm;
@JsonFormatDttm private ZonedDateTime step2StrtDttm;
@JsonFormatDttm private ZonedDateTime step2EndDttm; @JsonFormatDttm private ZonedDateTime step2EndDttm;
private String statusCd; private String statusCd;
private String trainType; private String trainType;
@@ -40,7 +43,9 @@ public class ModelTrainDetailDto {
public String getStatusName() { public String getStatusName() {
if (this.statusCd == null || this.statusCd.isBlank()) return null; if (this.statusCd == null || this.statusCd.isBlank()) return null;
try { try {
return TrainStatusType.valueOf(this.statusCd).getText(); // 또는 getName() return HeaderUtil.isEnglishRequest()
? TrainStatusType.valueOf(this.statusCd).getId()
: TrainStatusType.valueOf(this.statusCd).getText(); // 또는 getName()
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return this.statusCd; // 매핑 못하면 코드 그대로 반환(원하면 null 처리) return this.statusCd; // 매핑 못하면 코드 그대로 반환(원하면 null 처리)
} }
@@ -49,18 +54,16 @@ public class ModelTrainDetailDto {
public String getTrainTypeName() { public String getTrainTypeName() {
if (this.trainType == null || this.trainType.isBlank()) return null; if (this.trainType == null || this.trainType.isBlank()) return null;
try { try {
return TrainType.valueOf(this.trainType).getText(); // 또는 getName() return HeaderUtil.isEnglishRequest()
? TrainType.valueOf(this.trainType).getId()
: TrainType.valueOf(this.trainType).getText(); // 또는 getName()
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return this.trainType; // 매핑 못하면 코드 그대로 반환(원하면 null 처리) return this.trainType; // 매핑 못하면 코드 그대로 반환(원하면 null 처리)
} }
} }
private String formatDuration(ZonedDateTime start, ZonedDateTime end) { private String formatDuration(ZonedDateTime start, ZonedDateTime end) {
if (end == null) { if (start == null || end == null) {
end = ZonedDateTime.now();
}
if (start == null) {
return null; return null;
} }
@@ -70,11 +73,42 @@ public class ModelTrainDetailDto {
long minutes = (totalSeconds % 3600) / 60; long minutes = (totalSeconds % 3600) / 60;
long seconds = totalSeconds % 60; long seconds = totalSeconds % 60;
if (HeaderUtil.isEnglishRequest()) {
return String.format("%dh %dm %ds", hours, minutes, seconds);
} else {
return String.format("%d시간 %d분 %d초", hours, minutes, seconds); return String.format("%d시간 %d분 %d초", hours, minutes, seconds);
} }
}
public String getStepAllDuration() { public String getStepAllDuration() {
return formatDuration(this.step1StrtDttm, this.step2EndDttm); if (this.step2EndDttm != null) {
// step1 + step2 실제 소요시간 합산
long step1Seconds = 0;
long step2Seconds = 0;
if (this.step1StrtDttm != null && this.step1EndDttm != null) {
step1Seconds =
Math.abs(Duration.between(this.step1StrtDttm, this.step1EndDttm).getSeconds());
}
if (this.step2StrtDttm != null && this.step2EndDttm != null) {
step2Seconds =
Math.abs(Duration.between(this.step2StrtDttm, this.step2EndDttm).getSeconds());
}
long totalSeconds = step1Seconds + step2Seconds;
long hours = totalSeconds / 3600;
long minutes = (totalSeconds % 3600) / 60;
long seconds = totalSeconds % 60;
if (HeaderUtil.isEnglishRequest()) {
return String.format("%dh %dm %ds", hours, minutes, seconds);
} else {
return String.format("%d시간 %d분 %d초", hours, minutes, seconds);
}
} else {
// step2 없으면 step1만
return formatDuration(this.step1StrtDttm, this.step1EndDttm);
}
} }
} }
@@ -174,7 +208,7 @@ public class ModelTrainDetailDto {
public String getDataTypeName(String groupTitleCd) { public String getDataTypeName(String groupTitleCd) {
LearnDataType type = Enums.fromId(LearnDataType.class, groupTitleCd); LearnDataType type = Enums.fromId(LearnDataType.class, groupTitleCd);
return type == null ? null : type.getText(); return type == null ? null : (HeaderUtil.isEnglishRequest() ? type.getId() : type.getText());
} }
} }

View File

@@ -3,6 +3,7 @@ package com.kamco.cd.training.model.dto;
import com.kamco.cd.training.common.dto.HyperParam; import com.kamco.cd.training.common.dto.HyperParam;
import com.kamco.cd.training.common.enums.TrainStatusType; import com.kamco.cd.training.common.enums.TrainStatusType;
import com.kamco.cd.training.common.enums.TrainType; import com.kamco.cd.training.common.enums.TrainType;
import com.kamco.cd.training.common.utils.HeaderUtil;
import com.kamco.cd.training.common.utils.interfaces.JsonFormatDttm; import com.kamco.cd.training.common.utils.interfaces.JsonFormatDttm;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
@@ -44,8 +45,8 @@ public class ModelTrainMngDto {
private String requestPath; private String requestPath;
private String packingState; private String packingState;
private ZonedDateTime packingStrtDttm; @JsonFormatDttm private ZonedDateTime packingStrtDttm;
private ZonedDateTime packingEndDttm; @JsonFormatDttm private ZonedDateTime packingEndDttm;
private Long beforeModelId; private Long beforeModelId;
private Integer bestEpoch; private Integer bestEpoch;
@@ -53,7 +54,9 @@ public class ModelTrainMngDto {
public String getStatusName() { public String getStatusName() {
if (this.statusCd == null || this.statusCd.isBlank()) return null; if (this.statusCd == null || this.statusCd.isBlank()) return null;
try { try {
return TrainStatusType.valueOf(this.statusCd).getText(); // 또는 getName() return (HeaderUtil.isEnglishRequest()
? TrainStatusType.valueOf(this.statusCd).getId()
: TrainStatusType.valueOf(this.statusCd).getText()); // 또는 getName()
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return this.statusCd; // 매핑 못하면 코드 그대로 반환(원하면 null 처리) return this.statusCd; // 매핑 못하면 코드 그대로 반환(원하면 null 처리)
} }
@@ -62,7 +65,9 @@ public class ModelTrainMngDto {
public String getStep1StatusName() { public String getStep1StatusName() {
if (this.step1Status == null || this.step1Status.isBlank()) return null; if (this.step1Status == null || this.step1Status.isBlank()) return null;
try { try {
return TrainStatusType.valueOf(this.step1Status).getText(); // 또는 getName() return (HeaderUtil.isEnglishRequest()
? TrainStatusType.valueOf(this.step1Status).getId()
: TrainStatusType.valueOf(this.step1Status).getText()); // 또는 getName()
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return this.step1Status; // 매핑 못하면 코드 그대로 반환(원하면 null 처리) return this.step1Status; // 매핑 못하면 코드 그대로 반환(원하면 null 처리)
} }
@@ -71,7 +76,9 @@ public class ModelTrainMngDto {
public String getStep2StatusName() { public String getStep2StatusName() {
if (this.step2Status == null || this.step2Status.isBlank()) return null; if (this.step2Status == null || this.step2Status.isBlank()) return null;
try { try {
return TrainStatusType.valueOf(this.step2Status).getText(); // 또는 getName() return (HeaderUtil.isEnglishRequest()
? TrainStatusType.valueOf(this.step2Status).getId()
: TrainStatusType.valueOf(this.step2Status).getText()); // 또는 getName()
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return this.step2Status; // 매핑 못하면 코드 그대로 반환(원하면 null 처리) return this.step2Status; // 매핑 못하면 코드 그대로 반환(원하면 null 처리)
} }
@@ -80,7 +87,9 @@ public class ModelTrainMngDto {
public String getTrainTypeName() { public String getTrainTypeName() {
if (this.trainType == null || this.trainType.isBlank()) return null; if (this.trainType == null || this.trainType.isBlank()) return null;
try { try {
return TrainType.valueOf(this.trainType).getText(); // 또는 getName() return (HeaderUtil.isEnglishRequest()
? TrainType.valueOf(this.trainType).getId()
: TrainType.valueOf(this.trainType).getText()); // 또는 getName()
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return this.trainType; // 매핑 못하면 코드 그대로 반환(원하면 null 처리) return this.trainType; // 매핑 못하면 코드 그대로 반환(원하면 null 처리)
} }
@@ -97,8 +106,12 @@ public class ModelTrainMngDto {
long minutes = (totalSeconds % 3600) / 60; long minutes = (totalSeconds % 3600) / 60;
long seconds = totalSeconds % 60; long seconds = totalSeconds % 60;
if (HeaderUtil.isEnglishRequest()) {
return String.format("%dh %dm %ds", hours, minutes, seconds);
} else {
return String.format("%d시간 %d분 %d초", hours, minutes, seconds); return String.format("%d시간 %d분 %d초", hours, minutes, seconds);
} }
}
public String getStep1Duration() { public String getStep1Duration() {
return formatDuration(this.step1StrtDttm, this.step1EndDttm); return formatDuration(this.step1StrtDttm, this.step1EndDttm);
@@ -260,7 +273,9 @@ public class ModelTrainMngDto {
public String getStatusName() { public String getStatusName() {
if (this.statusCd == null || this.statusCd.isBlank()) return null; if (this.statusCd == null || this.statusCd.isBlank()) return null;
try { try {
return TrainStatusType.valueOf(this.statusCd).getText(); // 또는 getName() return HeaderUtil.isEnglishRequest()
? TrainStatusType.valueOf(this.statusCd).getId()
: TrainStatusType.valueOf(this.statusCd).getText(); // 또는 getName()
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return this.statusCd; // 매핑 못하면 코드 그대로 반환(원하면 null 처리) return this.statusCd; // 매핑 못하면 코드 그대로 반환(원하면 null 처리)
} }
@@ -269,7 +284,9 @@ public class ModelTrainMngDto {
public String getStep1StatusName() { public String getStep1StatusName() {
if (this.step1Status == null || this.step1Status.isBlank()) return null; if (this.step1Status == null || this.step1Status.isBlank()) return null;
try { try {
return TrainStatusType.valueOf(this.step1Status).getText(); // 또는 getName() return HeaderUtil.isEnglishRequest()
? TrainStatusType.valueOf(this.step1Status).getId()
: TrainStatusType.valueOf(this.step1Status).getText(); // 또는 getName()
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return this.step1Status; // 매핑 못하면 코드 그대로 반환(원하면 null 처리) return this.step1Status; // 매핑 못하면 코드 그대로 반환(원하면 null 처리)
} }
@@ -278,7 +295,9 @@ public class ModelTrainMngDto {
public String getStep2StatusName() { public String getStep2StatusName() {
if (this.step2Status == null || this.step2Status.isBlank()) return null; if (this.step2Status == null || this.step2Status.isBlank()) return null;
try { try {
return TrainStatusType.valueOf(this.step2Status).getText(); // 또는 getName() return HeaderUtil.isEnglishRequest()
? TrainStatusType.valueOf(this.step2Status).getId()
: TrainStatusType.valueOf(this.step2Status).getText(); // 또는 getName()
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return this.step2Status; // 매핑 못하면 코드 그대로 반환(원하면 null 처리) return this.step2Status; // 매핑 못하면 코드 그대로 반환(원하면 null 처리)
} }
@@ -287,7 +306,9 @@ public class ModelTrainMngDto {
public String getTrainTypeName() { public String getTrainTypeName() {
if (this.trainType == null || this.trainType.isBlank()) return null; if (this.trainType == null || this.trainType.isBlank()) return null;
try { try {
return TrainType.valueOf(this.trainType).getText(); // 또는 getName() return HeaderUtil.isEnglishRequest()
? TrainType.valueOf(this.trainType).getId()
: TrainType.valueOf(this.trainType).getText(); // 또는 getName()
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return this.trainType; // 매핑 못하면 코드 그대로 반환(원하면 null 처리) return this.trainType; // 매핑 못하면 코드 그대로 반환(원하면 null 처리)
} }
@@ -304,8 +325,12 @@ public class ModelTrainMngDto {
long minutes = (totalSeconds % 3600) / 60; long minutes = (totalSeconds % 3600) / 60;
long seconds = totalSeconds % 60; long seconds = totalSeconds % 60;
if (HeaderUtil.isEnglishRequest()) {
return String.format("%dh %dm %ds", hours, minutes, seconds);
} else {
return String.format("%d시간 %d분 %d초", hours, minutes, seconds); return String.format("%d시간 %d분 %d초", hours, minutes, seconds);
} }
}
public String getStep1Duration() { public String getStep1Duration() {
return formatDuration(this.step1StrtDttm, this.step1EndDttm); return formatDuration(this.step1StrtDttm, this.step1EndDttm);

View File

@@ -80,6 +80,8 @@ public class ModelDetailRepositoryImpl implements ModelDetailRepositoryCustom {
modelMasterEntity.modelNo, modelMasterEntity.modelNo,
modelMasterEntity.modelVer, modelMasterEntity.modelVer,
modelMasterEntity.step1StrtDttm, modelMasterEntity.step1StrtDttm,
modelMasterEntity.step1EndDttm,
modelMasterEntity.step2StrtDttm,
modelMasterEntity.step2EndDttm, modelMasterEntity.step2EndDttm,
modelMasterEntity.statusCd, modelMasterEntity.statusCd,
modelMasterEntity.trainType, modelMasterEntity.trainType,

View File

@@ -515,7 +515,8 @@ public class DockerTrainService {
} }
c.add("-v"); c.add("-v");
c.add(responseDir + ":/checkpoints"); // c.add(responseDir + ":/checkpoints");
c.add(responseDir + "/" + req.getOutputFolder() + ":/checkpoints");
c.add("kamco-cd-train:latest"); c.add("kamco-cd-train:latest");
@@ -523,7 +524,7 @@ public class DockerTrainService {
c.add("/workspace/change-detection-code/run_evaluation_pipeline.py"); c.add("/workspace/change-detection-code/run_evaluation_pipeline.py");
addArg(c, "--dataset-folder", req.getDatasetFolder()); addArg(c, "--dataset-folder", req.getDatasetFolder());
addArg(c, "--output-folder", req.getOutputFolder()); // addArg(c, "--output-folder", req.getOutputFolder());
c.add("--epoch"); c.add("--epoch");
c.add(modelFile); c.add(modelFile);

View File

@@ -50,16 +50,17 @@ swagger:
file: file:
dataset-dir: /data/training/request/ base_path: /backup/data/training
dataset-dir: ${file.base_path}/request/
dataset-tmp-dir: ${file.dataset-dir}tmp/ dataset-tmp-dir: ${file.dataset-dir}tmp/
pt-path: /data/training/response/v6-cls-checkpoints/ pt-path: ${file.base_path}/response/v6-cls-checkpoints/
pt-FileName: yolov8_6th-6m.pt pt-FileName: yolov8_6th-6m.pt
train: train:
docker: docker:
image: kamco-cd-train:latest image: kamco-cd-train:latest
base_path: /data/training base_path: /backup/data/training
request_dir: ${train.docker.base_path}/request request_dir: ${train.docker.base_path}/request
response_dir: ${train.docker.base_path}/response response_dir: ${train.docker.base_path}/response
symbolic_link_dir: ${train.docker.base_path}/tmp symbolic_link_dir: ${train.docker.base_path}/tmp

View File

@@ -37,8 +37,8 @@ spring:
max-file-size: 10GB max-file-size: 10GB
max-request-size: 10GB max-request-size: 10GB
transaction: #transaction:
default-timeout: 300 # 5분 트랜잭션 타임아웃 # default-timeout: 300 # 5분 트랜잭션 타임아웃
logging: logging:
level: level: