27 Commits

Author SHA1 Message Date
32d56cf8fe merge develop_add_log 2026-02-26 13:20:11 +09:00
c3b7daebb7 Merge pull request '미사용 쿼리 삭제, 추론 주석 추가, api/inference/download/ 권한 제거 수정' (#104) from feat/infer_dev_260211 into develop
Reviewed-on: #104
2026-02-26 12:36:40 +09:00
2188d426d4 미사용 쿼리 삭제, 추론 주석 추가, api/inference/download/ 권한 제거 수정 2026-02-26 12:36:02 +09:00
5c2ee0974b Merge pull request '추론실행 수정, develop pull 반영, 국유인 파일경로 dir 하드코딩 수정' (#103) from feat/infer_dev_260211 into develop
Reviewed-on: #103
2026-02-26 12:21:06 +09:00
7980fe1d42 InferenceRunService 미사용 삭제 및 추론 실행
추론제외, 이전연도 사용 별로 분기처리
2026-02-26 12:16:48 +09:00
c10141e915 Merge branch 'develop' of https://kamco.git.gs.dabeeo.com/MVPTeam/kamco-cd-api into feat/infer_dev_260211
# Conflicts:
#	src/main/java/com/kamco/cd/kamcoback/gukyuin/service/GukYuinApiService.java
2026-02-26 12:12:50 +09:00
97565c5369 Merge pull request 'feat/dean/test2_temp' (#102) from feat/dean/test2_temp into develop
Reviewed-on: #102
2026-02-26 11:58:48 +09:00
30f0e1a885 merge develop 2026-02-26 11:57:52 +09:00
ba562261c3 /api/inference/download 로그인 없이 접근 가능하도록 수정 2026-02-26 11:56:21 +09:00
a084c80715 Merge remote-tracking branch 'origin/feat/infer_dev_260211' into feat/infer_dev_260211 2026-02-26 11:53:01 +09:00
a44e93c234 추론 실행 수정 및 추석 추가 작업중 2026-02-26 11:52:56 +09:00
a63b81008a inference_hard_coding 2026-02-26 11:52:51 +09:00
2309357c0d 파일경로를 application.yml에서 가져올수있게 동적으로 처리 (#100)
Reviewed-on: #100
Co-authored-by: dean[백병남] <byungnam.baek@dabeeo.com>
Co-committed-by: dean[백병남] <byungnam.baek@dabeeo.com>
2026-02-26 11:49:49 +09:00
ee76389d6c 파일경로를 application.yml에서 가져올수있게 동적으로 처리 2026-02-26 11:46:17 +09:00
7b15e5bb8c Merge branch 'develop' into feat/infer_dev_260211
# Conflicts:
#	src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceRunService.java
2026-02-26 11:36:40 +09:00
001ad73de7 국유인 파일경로 dir 하드코딩 수정 2026-02-26 11:34:02 +09:00
2508f59a72 운영환경일때 ai팀경로수정 2026-02-26 10:36:10 +09:00
f2307ff0f4 운영환경일때 ai팀경로수정 2026-02-26 10:29:10 +09:00
6f44319d33 운영환경일때 ai팀경로수정 2026-02-26 10:24:29 +09:00
cefacb291b develop pull 2026-02-26 09:54:43 +09:00
744cbb55a9 Merge branch 'develop' of https://kamco.git.gs.dabeeo.com/MVPTeam/kamco-cd-api into feat/infer_dev_260211
# Conflicts:
#	src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceSendDto.java
#	src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceRunService.java
2026-02-26 09:53:11 +09:00
4a120ae5fd 운영환경일때 ai팀경로수정 2026-02-26 09:23:00 +09:00
7c200b057a 운영환경일때 ai팀경로수정 2026-02-26 08:36:53 +09:00
8ac0a00311 운영환경일때 ai팀경로수정 2026-02-26 08:33:53 +09:00
4863091406 추론 run 수정 2026-02-25 22:50:38 +09:00
70c28e0b54 추론 run 수정 2026-02-25 22:40:30 +09:00
9197819340 추론 run 수정 2026-02-25 22:39:49 +09:00
22 changed files with 476 additions and 297 deletions

View File

@@ -279,7 +279,9 @@ public class FIleChecker {
return true; return true;
} }
public static List<Folder> getFolderAll(String dirPath, String sortType, int maxDepth) { // kamco-nfs를 확인하는곳이 있어서 파라미터 추가 사용용도확인후 처리
public static List<Folder> getFolderAll(
String dirPath, String sortType, int maxDepth, String nfsRootDir) {
Path startPath = Paths.get(dirPath); Path startPath = Paths.get(dirPath);
@@ -308,8 +310,12 @@ public class FIleChecker {
String parentPath = path.getParent().toString(); String parentPath = path.getParent().toString();
String fullPath = path.toAbsolutePath().toString(); String fullPath = path.toAbsolutePath().toString();
// 이것이 필요한건가?
// boolean isShowHide =
// !parentFolderNm.equals("kamco-nfs"); // 폴더 리스트에
// kamco-nfs 하위만 나오도록 처리
boolean isShowHide = boolean isShowHide =
!parentFolderNm.equals("kamco-nfs"); // 폴더 리스트에 kamco-nfs 하위만 나오도록 처리 !parentFolderNm.equals(nfsRootDir); // 폴더 리스트에 nfsRootDir 하위만 나오도록 처리
File file = new File(fullPath); File file = new File(fullPath);
int childCnt = getChildFolderCount(file); int childCnt = getChildFolderCount(file);
String lastModified = getLastModified(file); String lastModified = getLastModified(file);
@@ -357,8 +363,8 @@ public class FIleChecker {
return folderList; return folderList;
} }
public static List<Folder> getFolderAll(String dirPath) { public static List<Folder> getFolderAll(String dirPath, String nfsRootDir) {
return getFolderAll(dirPath, "name", 1); return getFolderAll(dirPath, "name", 1, nfsRootDir);
} }
public static int getChildFolderCount(File directory) { public static int getChildFolderCount(File directory) {

View File

@@ -0,0 +1,33 @@
package com.kamco.cd.kamcoback.config;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "file")
public class FileProperties {
private String root;
private String nfs;
private String syncRootDir;
private String syncTmpDir;
private String syncFileExtention;
private String datasetDir;
private String datasetTmpDir;
private String modelDir;
private String modelTmpDir;
private String modelFileExtention;
private String ptPath;
private String datasetResponse;
private TrainingData trainingData;
@Getter
@Setter
public static class TrainingData {
private String geojsonDir;
}
}

View File

@@ -0,0 +1,20 @@
package com.kamco.cd.kamcoback.config;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "inference")
public class InferenceProperties {
private String nfs;
private String url;
private String batchUrl;
private String geojsonDir;
private String jarPath;
private String inferenceServerName;
}

View File

@@ -105,7 +105,8 @@ public class SecurityConfig {
"/api/layer/map/**", "/api/layer/map/**",
"/api/layer/tile-url", "/api/layer/tile-url",
"/api/layer/tile-url-year", "/api/layer/tile-url-year",
"/api/common-code/clazz") "/api/common-code/clazz",
"/api/inference/download/**")
.permitAll() .permitAll()
// 로그인한 사용자만 가능 IAM // 로그인한 사용자만 가능 IAM
.requestMatchers( .requestMatchers(

View File

@@ -16,6 +16,8 @@ public class StartupLogger {
private final Environment environment; private final Environment environment;
private final DataSource dataSource; private final DataSource dataSource;
private final FileProperties fileProperties;
private final InferenceProperties inferenceProperties;
@EventListener(ApplicationReadyEvent.class) @EventListener(ApplicationReadyEvent.class)
public void logStartupInfo() { public void logStartupInfo() {
@@ -79,6 +81,25 @@ public class StartupLogger {
│ DDL Auto : %s │ DDL Auto : %s
│ JDBC Batch Size : %s │ JDBC Batch Size : %s
│ Fetch Batch Size : %s │ Fetch Batch Size : %s
╠════════════════════════════════════════════════════════════════════════════════╣
║ FILE CONFIGURATION ║
╠────────────────────────────────────────────────────────────────────────────────╣
│ Root Directory : %s
│ NFS Mount Path : %s
│ Sync Root Dir : %s
│ Sync Tmp Dir : %s
│ Dataset Dir : %s
│ Model Dir : %s
│ PT Path : %s
╠════════════════════════════════════════════════════════════════════════════════╣
║ INFERENCE CONFIGURATION ║
╠────────────────────────────────────────────────────────────────────────────────╣
│ NFS Mount Path : %s
│ Inference URL : %s
│ Batch URL : %s
│ GeoJSON Dir : %s
│ JAR Path : %s
│ Server Names : %s
╚════════════════════════════════════════════════════════════════════════════════╝ ╚════════════════════════════════════════════════════════════════════════════════╝
""", """,
profileInfo, profileInfo,
@@ -89,7 +110,24 @@ public class StartupLogger {
showSql, showSql,
ddlAuto, ddlAuto,
batchSize, batchSize,
batchFetchSize); batchFetchSize,
fileProperties.getRoot() != null ? fileProperties.getRoot() : "N/A",
fileProperties.getNfs() != null ? fileProperties.getNfs() : "N/A",
fileProperties.getSyncRootDir() != null ? fileProperties.getSyncRootDir() : "N/A",
fileProperties.getSyncTmpDir() != null ? fileProperties.getSyncTmpDir() : "N/A",
fileProperties.getDatasetDir() != null ? fileProperties.getDatasetDir() : "N/A",
fileProperties.getModelDir() != null ? fileProperties.getModelDir() : "N/A",
fileProperties.getPtPath() != null ? fileProperties.getPtPath() : "N/A",
inferenceProperties.getNfs() != null ? inferenceProperties.getNfs() : "N/A",
inferenceProperties.getUrl() != null ? inferenceProperties.getUrl() : "N/A",
inferenceProperties.getBatchUrl() != null ? inferenceProperties.getBatchUrl() : "N/A",
inferenceProperties.getGeojsonDir() != null
? inferenceProperties.getGeojsonDir()
: "N/A",
inferenceProperties.getJarPath() != null ? inferenceProperties.getJarPath() : "N/A",
inferenceProperties.getInferenceServerName() != null
? inferenceProperties.getInferenceServerName()
: "N/A");
log.info(startupMessage); log.info(startupMessage);
} }

View File

@@ -83,7 +83,7 @@ public class ChngDetectMastDto {
@Schema( @Schema(
description = "탐지결과 절대경로명 /kamco_nas/export/{chnDtctId}", description = "탐지결과 절대경로명 /kamco_nas/export/{chnDtctId}",
example = "/kamco-nfs/dataset/export/D5F192EC76D34F6592035BE63A84F591") example = "{file.nfs}/dataset/export/D5F192EC76D34F6592035BE63A84F591")
private String pathNm; private String pathNm;
@Schema(description = "사원번호", example = "123456") @Schema(description = "사원번호", example = "123456")

View File

@@ -66,8 +66,11 @@ public class GukYuinApiService {
@Value("${gukyuin.cdi}") @Value("${gukyuin.cdi}")
private String gukyuinCdiUrl; private String gukyuinCdiUrl;
@Value("${file.dataset-dir}") @Value("${file.nfs}")
private String datasetDir; private String nfs;
// @Value("${file.dataset-dir}")
// private String datasetDir;
@Transactional @Transactional
public ChngDetectMastDto.RegistResDto regist( public ChngDetectMastDto.RegistResDto regist(
@@ -453,7 +456,10 @@ public class GukYuinApiService {
return new ResponseObj(ApiResponseCode.DUPLICATE_DATA, "이미 국유인 연동을 한 회차입니다."); return new ResponseObj(ApiResponseCode.DUPLICATE_DATA, "이미 국유인 연동을 한 회차입니다.");
} }
if (!Files.isDirectory(Path.of("/kamco-nfs/dataset/export/" + info.getUid()))) { // String kamconfsDatasetExportPathfsDatasetExportPath = "/kamco-nfs/dataset/export/";
String kamconfsDatasetExportPathfsDatasetExportPath =
String.format("%s%s", nfs, "/dataset/export/");
if (!Files.isDirectory(Path.of(kamconfsDatasetExportPathfsDatasetExportPath + info.getUid()))) {
return new ResponseObj( return new ResponseObj(
ApiResponseCode.NOT_FOUND_DATA, "파일 경로에 회차 실행 파일이 생성되지 않았습니다. 확인 부탁드립니다."); ApiResponseCode.NOT_FOUND_DATA, "파일 경로에 회차 실행 파일이 생성되지 않았습니다. 확인 부탁드립니다.");
} }
@@ -468,7 +474,7 @@ public class GukYuinApiService {
reqDto.setCrtrYr(String.valueOf(info.getTargetYyyy())); reqDto.setCrtrYr(String.valueOf(info.getTargetYyyy()));
reqDto.setChnDtctSno(String.valueOf(maxStage + 1)); reqDto.setChnDtctSno(String.valueOf(maxStage + 1));
reqDto.setChnDtctId(info.getUid()); reqDto.setChnDtctId(info.getUid());
reqDto.setPathNm("/kamco-nfs/dataset/export/" + info.getUid()); reqDto.setPathNm(kamconfsDatasetExportPathfsDatasetExportPath + info.getUid());
// 1회차를 종료 상태로 처리하고 2회차를 보내야 함 // 1회차를 종료 상태로 처리하고 2회차를 보내야 함
// 추론(learn), 학습데이터(inference) 둘 다 종료 처리 // 추론(learn), 학습데이터(inference) 둘 다 종료 처리

View File

@@ -246,15 +246,15 @@ public class InferenceResultDto {
@NotBlank @NotBlank
private String title; private String title;
@Schema(description = "G1", example = "b40e0f68-c1d8-49fc-93f9-a36270093861") @Schema(description = "G1", example = "643adead-f3d2-4f10-9037-862bee919399")
@NotNull @NotNull
private UUID model1Uuid; private UUID model1Uuid;
@Schema(description = "G2", example = "ec92b7d2-b5a3-4915-9bdf-35fb3ca8ad27") @Schema(description = "G2", example = "dd86b4ef-28e3-4e3d-9ee4-f60d9cb54e13")
@NotNull @NotNull
private UUID model2Uuid; private UUID model2Uuid;
@Schema(description = "G3", example = "37f45782-8ccf-4cf6-911c-a055a1510d39") @Schema(description = "G3", example = "58c1153e-dec6-4424-82a1-189083a9d9dc")
@NotNull @NotNull
private UUID model3Uuid; private UUID model3Uuid;

View File

@@ -5,8 +5,10 @@ import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
/** AI API 추론 실행 DTO */ /** AI API 추론 실행 DTO */
@Slf4j
@Getter @Getter
@Setter @Setter
@NoArgsConstructor @NoArgsConstructor
@@ -23,14 +25,6 @@ public class InferenceSendDto {
private String cd_model_type; private String cd_model_type;
private Double priority; private Double priority;
public String getCd_model_path() {
return cd_model_path==null?null:cd_model_path.replace("kamcd-nfs", "data");
}
public String getCls_model_path() {
return cls_model_path==null?null:cls_model_path.replace("kamcd-nfs", "data");
}
@Getter @Getter
@Setter @Setter
@AllArgsConstructor @AllArgsConstructor
@@ -42,14 +36,5 @@ public class InferenceSendDto {
private Integer input2_year; private Integer input2_year;
private String input1_scene_path; private String input1_scene_path;
private String input2_scene_path; private String input2_scene_path;
public String getInput1_scene_path() {
return input1_scene_path==null?null:input1_scene_path.replace("kamcd-nfs", "data");
}
public String getInput2_scene_path() {
return input2_scene_path==null?null:input2_scene_path.replace("kamcd-nfs", "data");
}
} }
} }

View File

@@ -47,14 +47,12 @@ import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
@@ -67,6 +65,7 @@ import org.springframework.http.MediaType;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
/** 추론 관리 */
@Service @Service
@Log4j2 @Log4j2
@RequiredArgsConstructor @RequiredArgsConstructor
@@ -120,6 +119,12 @@ public class InferenceResultService {
return dto.getUuid(); return dto.getUuid();
} }
/**
* 추론 실행 - 추론제외, 이전년도 도엽 사용 분기
*
* @param req
* @return
*/
@Transactional @Transactional
public UUID run(InferenceResultDto.RegReq req) { public UUID run(InferenceResultDto.RegReq req) {
if (req.getDetectOption().equals(DetectOption.EXCL.getId())) { if (req.getDetectOption().equals(DetectOption.EXCL.getId())) {
@@ -135,8 +140,10 @@ public class InferenceResultService {
* @return * @return
*/ */
public UUID runExcl(InferenceResultDto.RegReq req) { public UUID runExcl(InferenceResultDto.RegReq req) {
// target 도엽 조회
List<MngListDto> targetDtoList = mapSheetMngCoreService.getHstMapSheetList(req); List<MngListDto> targetDtoList = mapSheetMngCoreService.getHstMapSheetList(req);
// target 리스트 추출 (null 제거 + 중복 제거)
List<String> targetList = List<String> targetList =
targetDtoList.stream() targetDtoList.stream()
.map(MngListDto::getMapSheetNum) .map(MngListDto::getMapSheetNum)
@@ -144,32 +151,46 @@ public class InferenceResultService {
.distinct() .distinct()
.toList(); .toList();
// compare 도엽번호 리스트 조회 (null 제거 + 중복 제거)
List<String> compareList = List<String> compareList =
mapSheetMngCoreService.getMapSheetNumByHst(req.getCompareYyyy()).stream() mapSheetMngCoreService.getMapSheetNumByHst(req.getCompareYyyy()).stream()
.filter(Objects::nonNull) .filter(Objects::nonNull)
.distinct() .distinct()
.toList(); .toList();
// compare 기준
Set<String> compareSet = new HashSet<>(compareList); Set<String> compareSet = new HashSet<>(compareList);
// target 기준으로 compare에 존재하는 도엽만 필터링
List<String> filteredTargetList = targetList.stream().filter(compareSet::contains).toList(); List<String> filteredTargetList = targetList.stream().filter(compareSet::contains).toList();
// 도엽 비교 로그 출력
logYearComparison(targetList, compareList, filteredTargetList); logYearComparison(targetList, compareList, filteredTargetList);
// compare geojson 파일 생성
Scene compareScene = Scene compareScene =
getSceneInference( getSceneInference(
req.getCompareYyyy().toString(), req.getCompareYyyy().toString(), // 기준년도
filteredTargetList, filteredTargetList, // 교집합 도엽
req.getMapSheetScope(), req.getMapSheetScope(), // ALL / 부분
req.getDetectOption()); req.getDetectOption()); // EXCL / PREV
// target geojson 파일 생성
Scene targetScene = Scene targetScene =
getSceneInference( getSceneInference(
req.getTargetYyyy().toString(), req.getTargetYyyy().toString(), // 대상년도
filteredTargetList, filteredTargetList, // 교집합 도엽
req.getMapSheetScope(), req.getMapSheetScope(),
req.getDetectOption()); req.getDetectOption());
return executeInference(req, targetDtoList, filteredTargetList, compareScene, targetScene); // 추론 실행
return executeInference(
req,
targetDtoList, // 전체 target 목록
filteredTargetList, // 최종 추론 대상
compareScene, // compare geojson
targetScene // target geojson
);
} }
/** /**
@@ -180,8 +201,10 @@ public class InferenceResultService {
*/ */
@Transactional @Transactional
public UUID runPrev(InferenceResultDto.RegReq req) { public UUID runPrev(InferenceResultDto.RegReq req) {
// target 목록 조회
List<MngListDto> targetDtoList = mapSheetMngCoreService.getHstMapSheetList(req); List<MngListDto> targetDtoList = mapSheetMngCoreService.getHstMapSheetList(req);
// target 도엽번호 리스트 추출 중복 제거
List<String> targetList = List<String> targetList =
targetDtoList.stream() targetDtoList.stream()
.map(MngListDto::getMapSheetNum) .map(MngListDto::getMapSheetNum)
@@ -189,54 +212,60 @@ public class InferenceResultService {
.distinct() .distinct()
.toList(); .toList();
Set<String> targetSet = new HashSet<>(targetList); // compare 목록 조회
List<MapSheetFallbackYearDto> compareDtoList = List<MapSheetFallbackYearDto> compareDtoList =
new ArrayList<>(mapSheetMngCoreService.getMapSheetNumDtoByHst(req.getCompareYyyy())); new ArrayList<>(mapSheetMngCoreService.getMapSheetNumDtoByHst(req.getCompareYyyy()));
// compare 도엽번호 Set 구성
Set<String> compareSet = Set<String> compareSet =
compareDtoList.stream() compareDtoList.stream()
.map(MapSheetFallbackYearDto::getMapSheetNum) .map(MapSheetFallbackYearDto::getMapSheetNum)
.filter(Objects::nonNull) .filter(Objects::nonNull)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
// target에는 있으나 compare에는 없는 도엽 추출
List<String> remainingTargetList = List<String> remainingTargetList =
targetList.stream().filter(s -> !compareSet.contains(s)).toList(); targetList.stream().filter(s -> !compareSet.contains(s)).toList();
// compare에 없을때 이전 년도 사용 가능여부 조회
List<MapSheetFallbackYearDto> fallbackYearDtoList = List<MapSheetFallbackYearDto> fallbackYearDtoList =
mapSheetMngCoreService.findFallbackCompareYearByMapSheets( mapSheetMngCoreService.findFallbackCompareYearByMapSheets(
req.getTargetYyyy(), remainingTargetList); req.getTargetYyyy(), // 대상년도 기준
remainingTargetList // compare에 없는 도엽들
);
// 기존 compare , 사용가능 이전년도 정보 합치기
compareDtoList.addAll(fallbackYearDtoList); compareDtoList.addAll(fallbackYearDtoList);
// mapSheetNum 기준 중복 제거(기존 compare 우선) // 중복제거하여 사용할 compare 도엽 목록
compareDtoList =
new ArrayList<>(
compareDtoList.stream()
.filter(d -> d.getMapSheetNum() != null)
.collect(
Collectors.toMap(
MapSheetFallbackYearDto::getMapSheetNum,
Function.identity(),
(existing, replacement) -> existing,
LinkedHashMap::new))
.values());
Set<String> availableCompareSheets = Set<String> availableCompareSheets =
compareDtoList.stream() compareDtoList.stream()
.map(MapSheetFallbackYearDto::getMapSheetNum) .map(MapSheetFallbackYearDto::getMapSheetNum)
.filter(Objects::nonNull) .filter(Objects::nonNull)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
// 최종 추론 대상 도엽
// target 기준으로 compare 에 존재하는 도엽만 추출
List<String> filteredTargetList = List<String> filteredTargetList =
targetList.stream().filter(availableCompareSheets::contains).toList(); targetList.stream().filter(availableCompareSheets::contains).toList();
// compareDtoList도 최종 기준으로 필터
Set<String> filteredTargetSet = new HashSet<>(filteredTargetList);
List<MapSheetFallbackYearDto> filteredCompareDtoList =
compareDtoList.stream()
.filter(d -> d.getMapSheetNum() != null)
.filter(d -> filteredTargetSet.contains(d.getMapSheetNum()))
.toList();
// compare only 계산 (target에는 없는 compare 도엽 수) log 용
long compareOnlyCount = long compareOnlyCount =
compareDtoList.stream() compareDtoList.stream()
.map(MapSheetFallbackYearDto::getMapSheetNum) .map(MapSheetFallbackYearDto::getMapSheetNum)
.filter(s -> s != null && !targetSet.contains(s)) .filter(s -> s != null && !targetList.contains(s))
.count(); .count();
// 연도별 도엽 비교 로그 출력
log.info( log.info(
""" """
===== MapSheet Year Comparison ===== ===== MapSheet Year Comparison =====
@@ -247,20 +276,13 @@ public class InferenceResultService {
compare Only: {} compare Only: {}
==================================== ====================================
""", """,
targetList.size(), targetList.size(), // target count
compareDtoList.size(), compareDtoList.size(), // compare count
filteredTargetList.size(), filteredTargetList.size(), // target 기준으로 compare 비교하여 최종 추론할 도엽 count
targetList.size() - filteredTargetList.size(), targetList.size() - filteredTargetList.size(), // compare에 존재하지 않는 target 도엽 수
compareOnlyCount); compareOnlyCount); // target 에 존재하지 않는 compare 도엽수
// compareDtoList도 filteredTargetList 기준으로 필터
Set<String> filteredTargetSet = new HashSet<>(filteredTargetList);
List<MapSheetFallbackYearDto> filteredCompareDtoList =
compareDtoList.stream()
.filter(d -> d.getMapSheetNum() != null)
.filter(d -> filteredTargetSet.contains(d.getMapSheetNum()))
.toList();
// compare 기준 geojson 생성 (년도 fallback 반영)
Scene compareScene = Scene compareScene =
getSceneInference( getSceneInference(
filteredCompareDtoList, filteredCompareDtoList,
@@ -268,6 +290,7 @@ public class InferenceResultService {
req.getMapSheetScope(), req.getMapSheetScope(),
req.getDetectOption()); req.getDetectOption());
// target 기준 geojson 생성
Scene targetScene = Scene targetScene =
getSceneInference( getSceneInference(
req.getTargetYyyy().toString(), req.getTargetYyyy().toString(),
@@ -275,6 +298,7 @@ public class InferenceResultService {
req.getMapSheetScope(), req.getMapSheetScope(),
req.getDetectOption()); req.getDetectOption());
// AI 추론 실행
return executeInference(req, targetDtoList, filteredTargetList, compareScene, targetScene); return executeInference(req, targetDtoList, filteredTargetList, compareScene, targetScene);
} }
@@ -355,11 +379,11 @@ public class InferenceResultService {
compare Only: {} compare Only: {}
==================================== ====================================
""", """,
targetList.size(), targetList.size(), // target count
compareList.size(), compareList.size(), // compare count
filteredTargetList.size(), filteredTargetList.size(), // target 기준으로 compare 비교하여 최종 추론할 도엽 count
targetList.size() - filteredTargetList.size(), targetList.size() - filteredTargetList.size(), // compare에 존재하지 않는 target 도엽 수
compareOnlyCount); compareOnlyCount); // target 에 존재하지 않는 compare 도엽수
} }
/** /**
@@ -569,10 +593,11 @@ public class InferenceResultService {
} }
/** /**
* 추론 AI API 호출 * 추론 AI API 호출 batch id를 리턴
* *
* @param dto * @param dto
*/ */
// 같은함수가 왜 두개지
private Long ensureAccepted(InferenceSendDto dto) { private Long ensureAccepted(InferenceSendDto dto) {
if (dto == null) { if (dto == null) {
@@ -580,6 +605,14 @@ public class InferenceResultService {
throw new CustomApiException("BAD_REQUEST", HttpStatus.BAD_REQUEST); throw new CustomApiException("BAD_REQUEST", HttpStatus.BAD_REQUEST);
} }
// [중복]운영환경일때 경로수정 dean 260226
if (profile != null && profile.equals("prod")) {
log.info("========================================================");
log.info("[CHANGE INFERENCE] profile = {} Inforence req", profile);
log.info("========================================================");
log.info("");
}
// 1) 요청 로그 // 1) 요청 로그
try { try {
log.debug("Inference request dto={}", objectMapper.writeValueAsString(dto)); log.debug("Inference request dto={}", objectMapper.writeValueAsString(dto));
@@ -588,19 +621,22 @@ public class InferenceResultService {
} }
// 2) local 환경 임시 처리 // 2) local 환경 임시 처리
if ("local".equals(profile)) { // if ("local".equals(profile)) {
if (dto.getPred_requests_areas() == null) { // if (dto.getPred_requests_areas() == null) {
throw new IllegalStateException("pred_requests_areas is null"); // throw new IllegalStateException("pred_requests_areas is null");
} // }
dto.getPred_requests_areas().setInput1_scene_path("/kamco-nfs/requests/2023_local.geojson"); //
dto.getPred_requests_areas().setInput2_scene_path("/kamco-nfs/requests/2024_local.geojson"); // dto.getPred_requests_areas().setInput1_scene_path("/kamco-nfs/requests/2023_local.geojson");
} //
// dto.getPred_requests_areas().setInput2_scene_path("/kamco-nfs/requests/2024_local.geojson");
// }
// 3) HTTP 호출 // 3) HTTP 호출
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON); headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(List.of(MediaType.APPLICATION_JSON)); headers.setAccept(List.of(MediaType.APPLICATION_JSON));
// 추론 실행 API 호출
ExternalCallResult<String> result = ExternalCallResult<String> result =
externalHttpClient.call(inferenceUrl, HttpMethod.POST, dto, headers, String.class); externalHttpClient.call(inferenceUrl, HttpMethod.POST, dto, headers, String.class);
@@ -615,12 +651,14 @@ public class InferenceResultService {
objectMapper.readValue(result.body(), new TypeReference<>() {}); objectMapper.readValue(result.body(), new TypeReference<>() {});
if (list.isEmpty()) { if (list.isEmpty()) {
throw new IllegalStateException("Inference response is empty"); throw new CustomApiException(
"NOT_FOUND", HttpStatus.NOT_FOUND, "Inference response is empty");
} }
Object batchIdObj = list.get(0).get("batch_id"); Object batchIdObj = list.get(0).get("batch_id");
if (batchIdObj == null) { if (batchIdObj == null) {
throw new IllegalStateException("batch_id not found in response"); throw new CustomApiException(
"NOT_FOUND", HttpStatus.NOT_FOUND, "batch_id not found in response");
} }
return Long.valueOf(batchIdObj.toString()); return Long.valueOf(batchIdObj.toString());
@@ -639,6 +677,7 @@ public class InferenceResultService {
*/ */
private InferenceSendDto getModelInfo(UUID uuid) { private InferenceSendDto getModelInfo(UUID uuid) {
// 모델정보 조회
Basic modelInfo = modelMngCoreService.findByModelUuid(uuid); Basic modelInfo = modelMngCoreService.findByModelUuid(uuid);
String cdModelPath = ""; String cdModelPath = "";
@@ -678,6 +717,7 @@ public class InferenceResultService {
sendDto.setCls_model_version(modelInfo.getModelVer()); sendDto.setCls_model_version(modelInfo.getModelVer());
sendDto.setCd_model_type(modelType); sendDto.setCd_model_type(modelType);
sendDto.setPriority(5d); sendDto.setPriority(5d);
log.info("[Inference Send]SendDto={}", sendDto);
return sendDto; return sendDto;
} }

View File

@@ -47,6 +47,9 @@ public class MapSheetMngService {
private final UploadService uploadService; private final UploadService uploadService;
private final UserUtil userUtil = new UserUtil(); private final UserUtil userUtil = new UserUtil();
@Value("${file.root}")
private String nfsRootDir;
@Value("${file.sync-root-dir}") @Value("${file.sync-root-dir}")
private String syncRootDir; private String syncRootDir;
@@ -111,7 +114,6 @@ public class MapSheetMngService {
public DmlReturn uploadPair( public DmlReturn uploadPair(
MultipartFile tfwFile, String tifFile, Long hstUid, Long tifFileSize) { MultipartFile tfwFile, String tifFile, Long hstUid, Long tifFileSize) {
String rootPath = syncRootDir;
String tmpPath = syncTmpDir; String tmpPath = syncTmpDir;
DmlReturn dmlReturn = new DmlReturn("success", "UPLOAD COMPLETE"); DmlReturn dmlReturn = new DmlReturn("success", "UPLOAD COMPLETE");
@@ -133,6 +135,7 @@ public class MapSheetMngService {
return dmlReturn; return dmlReturn;
} }
// TODO 삭제?
MngDto mngDto = mapSheetMngCoreService.findMapSheetMng(errDto.getMngYyyy()); MngDto mngDto = mapSheetMngCoreService.findMapSheetMng(errDto.getMngYyyy());
// 중복체크 -> 도엽50k/uuid 경로에 업로드 할 거라 overwrite 되지 않음 // 중복체크 -> 도엽50k/uuid 경로에 업로드 할 거라 overwrite 되지 않음
@@ -340,7 +343,7 @@ public class MapSheetMngService {
log.info("[FIND_FOLDER] DIR : {}", dirPath); log.info("[FIND_FOLDER] DIR : {}", dirPath);
List<FIleChecker.Folder> folderList = List<FIleChecker.Folder> folderList =
FIleChecker.getFolderAll(dirPath).stream() FIleChecker.getFolderAll(dirPath, nfsRootDir).stream()
.filter(dir -> dir.getIsValid().equals(true)) .filter(dir -> dir.getIsValid().equals(true))
.toList(); .toList();

View File

@@ -369,6 +369,12 @@ public class InferenceResultCoreService {
return mapSheetLearnRepository.getInferenceServerStatusList(); return mapSheetLearnRepository.getInferenceServerStatusList();
} }
/**
* 진행중 배치 조회
*
* @param status
* @return
*/
public InferenceBatchSheet getInferenceResultByStatus(String status) { public InferenceBatchSheet getInferenceResultByStatus(String status) {
MapSheetLearnEntity entity = MapSheetLearnEntity entity =
mapSheetLearnRepository.getInferenceResultByStatus(status).orElse(null); mapSheetLearnRepository.getInferenceResultByStatus(status).orElse(null);
@@ -403,6 +409,12 @@ public class InferenceResultCoreService {
return mapSheetLearnRepository.getInferenceAiResultById(id, modelUuid); return mapSheetLearnRepository.getInferenceAiResultById(id, modelUuid);
} }
/**
* 추론 진행 현황 상세
*
* @param uuid
* @return
*/
public InferenceStatusDetailDto getInferenceStatus(UUID uuid) { public InferenceStatusDetailDto getInferenceStatus(UUID uuid) {
return mapSheetLearnRepository.getInferenceStatus(uuid); return mapSheetLearnRepository.getInferenceStatus(uuid);
} }

View File

@@ -27,7 +27,6 @@ import java.nio.file.Paths;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@@ -236,84 +235,22 @@ public class MapSheetMngCoreService {
} }
/** /**
* 추론 실행에 필요한 geojson 파일 생성 * geojson 생성
* *
* @param yyyy 영상관리 파일별 년도 * @param yyyy
* @param scenes 5k 도엽 번호 리스트 * @param scenes
* @param mapSheetScope EXCL : 추론제외, PREV 이전 년도 도엽 사용 * @param mapSheetScope
* @param detectOption
* @return * @return
*/ */
public Scene getSceneInference( public Scene getSceneInference(
String yyyy, List<String> scenes, String mapSheetScope, String detectOption) { String yyyy, List<String> scenes, String mapSheetScope, String detectOption) {
List<ImageFeature> features = loadSceneInferenceBySheets(yyyy, scenes);
Map<String, Object> result = new HashMap<>(); return writeSceneGeoJson(yyyy, mapSheetScope, detectOption, features);
boolean isAll = MapSheetScope.ALL.getId().equals(mapSheetScope);
String optionSuffix = "";
if (DetectOption.EXCL.getId().equals(detectOption)) {
optionSuffix = "_EXCL";
} else if (DetectOption.PREV.getId().equals(detectOption)) {
optionSuffix = "_PREV";
}
// 1) 경로/파일명 결정
String targetDir =
"local".equals(activeEnv) ? System.getProperty("user.home") + "/geojson" : inferenceDir;
String filename =
isAll
? String.format("%s_%s_ALL%s.geojson", yyyy, activeEnv, optionSuffix)
: String.format("%s_%s%s.geojson", yyyy, activeEnv, optionSuffix);
Path outputPath = Paths.get(targetDir, filename);
// 2) ALL일 때만 재사용
// if (isAll && Files.exists(outputPath)) {
// return outputPath.toString();
// }
// 3) 데이터 조회
List<ImageFeature> sceneInference = mapSheetMngRepository.getSceneInference(yyyy, scenes);
if (sceneInference == null || sceneInference.isEmpty()) {
log.warn(
"NOT_FOUND_TARGET_YEAR: yyyy={}, isAll={}, scenesSize={}",
yyyy,
isAll,
scenes == null ? 0 : scenes.size());
throw new CustomApiException("NOT_FOUND_TARGET_YEAR", HttpStatus.NOT_FOUND);
}
// 4) 파일 생성
try {
log.info("create Directories outputPath: {}", outputPath);
log.info(
"activeEnv={}, inferenceDir={}, targetDir={}, filename={}",
activeEnv,
inferenceDir,
targetDir,
filename);
log.info("outputPath={}, parent={}", outputPath.toAbsolutePath(), outputPath.getParent());
Files.createDirectories(outputPath.getParent());
new GeoJsonFileWriter()
.exportToFile(sceneInference, "scene_inference_" + yyyy, 5186, outputPath.toString());
log.info("GeoJsonFileWriter: {}", "scene_inference_" + yyyy);
Scene scene = new Scene();
scene.setFeatures(sceneInference);
scene.setFilePath(outputPath.toString());
return scene;
} catch (IOException e) {
log.error(
"FAIL_CREATE_MAP_SHEET_FILE: yyyy={}, isAll={}, path={}", yyyy, isAll, outputPath, e);
throw new CustomApiException("INTERNAL_SERVER_ERROR", HttpStatus.INTERNAL_SERVER_ERROR, e);
}
} }
/** /**
* 년도별로 추론 실행에 필요한 geojson 파일 생성 * geojson 생성
* *
* @param yearDtos * @param yearDtos
* @param yyyy * @param yyyy
@@ -326,17 +263,24 @@ public class MapSheetMngCoreService {
String yyyy, String yyyy,
String mapSheetScope, String mapSheetScope,
String detectOption) { String detectOption) {
Map<String, Object> result = new HashMap<>(); List<ImageFeature> features = loadSceneInferenceByFallbackYears(yearDtos);
return writeSceneGeoJson(yyyy, mapSheetScope, detectOption, features);
}
/**
* 파일 경로/이름 , 파일 생성 , 도엽번호 반환
*
* @param yyyy
* @param mapSheetScope
* @param detectOption
* @param sceneInference
* @return Scene
*/
private Scene writeSceneGeoJson(
String yyyy, String mapSheetScope, String detectOption, List<ImageFeature> sceneInference) {
boolean isAll = MapSheetScope.ALL.getId().equals(mapSheetScope); boolean isAll = MapSheetScope.ALL.getId().equals(mapSheetScope);
String optionSuffix = buildOptionSuffix(detectOption);
String optionSuffix = "";
if (DetectOption.EXCL.getId().equals(detectOption)) {
optionSuffix = "_EXCL";
} else if (DetectOption.PREV.getId().equals(detectOption)) {
optionSuffix = "_PREV";
}
// 1) 경로/파일명 결정
String targetDir = String targetDir =
"local".equals(activeEnv) ? System.getProperty("user.home") + "/geojson" : inferenceDir; "local".equals(activeEnv) ? System.getProperty("user.home") + "/geojson" : inferenceDir;
@@ -347,33 +291,11 @@ public class MapSheetMngCoreService {
Path outputPath = Paths.get(targetDir, filename); Path outputPath = Paths.get(targetDir, filename);
// 3) 데이터 조회
Map<Integer, List<MapSheetFallbackYearDto>> groupedByYear =
yearDtos.stream().collect(Collectors.groupingBy(MapSheetFallbackYearDto::getMngYyyy));
List<ImageFeature> sceneInference = new ArrayList<>();
// 년도별로 루프 돌리기
for (Map.Entry<Integer, List<MapSheetFallbackYearDto>> entry : groupedByYear.entrySet()) {
Integer compareYear = entry.getKey();
List<MapSheetFallbackYearDto> listByYear = entry.getValue();
// 도엽번호만 추출
List<String> sheetNums =
listByYear.stream().map(MapSheetFallbackYearDto::getMapSheetNum).toList();
List<ImageFeature> tempSceneInference =
mapSheetMngRepository.getSceneInference(compareYear.toString(), sheetNums);
tempSceneInference.addAll(sceneInference);
}
if (sceneInference == null || sceneInference.isEmpty()) { if (sceneInference == null || sceneInference.isEmpty()) {
log.warn("NOT_FOUND_TARGET_YEAR: yyyy={}, isAll={}, scenesSize={}", yyyy, isAll, 0); log.warn("NOT_FOUND_TARGET_YEAR: yyyy={}, isAll={}, featuresSize={}", yyyy, isAll, 0);
throw new CustomApiException("NOT_FOUND_TARGET_YEAR", HttpStatus.NOT_FOUND); throw new CustomApiException("NOT_FOUND_TARGET_YEAR", HttpStatus.NOT_FOUND);
} }
// 4) 파일 생성
try { try {
log.info("create Directories outputPath: {}", outputPath); log.info("create Directories outputPath: {}", outputPath);
log.info( log.info(
@@ -383,15 +305,15 @@ public class MapSheetMngCoreService {
targetDir, targetDir,
filename); filename);
log.info("outputPath={}, parent={}", outputPath.toAbsolutePath(), outputPath.getParent()); log.info("outputPath={}, parent={}", outputPath.toAbsolutePath(), outputPath.getParent());
Files.createDirectories(outputPath.getParent()); Files.createDirectories(outputPath.getParent());
new GeoJsonFileWriter() new GeoJsonFileWriter()
.exportToFile(sceneInference, "scene_inference_" + yyyy, 5186, outputPath.toString()); .exportToFile(sceneInference, "scene_inference_" + yyyy, 5186, outputPath.toString());
log.info("GeoJsonFileWriter: {}", "scene_inference_" + yyyy);
Scene scene = new Scene(); Scene scene = new Scene();
scene.setFeatures(sceneInference); scene.setFeatures(sceneInference);
scene.setFilePath(outputPath.toString()); scene.setFilePath(outputPath.toString());
return scene; return scene;
} catch (IOException e) { } catch (IOException e) {
@@ -401,6 +323,80 @@ public class MapSheetMngCoreService {
} }
} }
/**
* geojson 파일명 Suffix
*
* @param detectOption
* @return
*/
private String buildOptionSuffix(String detectOption) {
if (DetectOption.EXCL.getId().equals(detectOption)) return "_EXCL";
if (DetectOption.PREV.getId().equals(detectOption)) return "_PREV";
return "";
}
/**
* 년도, 도엽번호로 조회
*
* @param yyyy
* @param scenes
* @return ImageFeature
*/
private List<ImageFeature> loadSceneInferenceBySheets(String yyyy, List<String> scenes) {
List<ImageFeature> sceneInference = mapSheetMngRepository.getSceneInference(yyyy, scenes);
if (sceneInference == null || sceneInference.isEmpty()) {
log.warn(
"NOT_FOUND_TARGET_YEAR: yyyy={}, scenesSize={}",
yyyy,
scenes == null ? 0 : scenes.size());
throw new CustomApiException("NOT_FOUND_TARGET_YEAR", HttpStatus.NOT_FOUND);
}
return sceneInference;
}
/**
* 년도별로 나눠 조회
*
* @param yearDtos
* @return ImageFeature
*/
private List<ImageFeature> loadSceneInferenceByFallbackYears(
List<MapSheetFallbackYearDto> yearDtos) {
if (yearDtos == null || yearDtos.isEmpty()) {
return List.of();
}
// 년도 별로 루프를 돌리기위해 년도별 정리
Map<Integer, List<MapSheetFallbackYearDto>> groupedByYear =
yearDtos.stream()
.filter(d -> d.getMngYyyy() != null && d.getMapSheetNum() != null)
.collect(Collectors.groupingBy(MapSheetFallbackYearDto::getMngYyyy));
List<ImageFeature> sceneInference = new ArrayList<>();
for (Map.Entry<Integer, List<MapSheetFallbackYearDto>> entry : groupedByYear.entrySet()) {
Integer year = entry.getKey();
// 년도별 mapSheetNum 만들기
List<String> sheetNums =
entry.getValue().stream()
.map(MapSheetFallbackYearDto::getMapSheetNum)
.filter(Objects::nonNull)
.distinct()
.toList();
// tif파일 정보 조회
List<ImageFeature> temp = mapSheetMngRepository.getSceneInference(year.toString(), sheetNums);
if (temp != null && !temp.isEmpty()) {
sceneInference.addAll(temp);
}
}
return sceneInference;
}
/** /**
* 변화탐지 실행 가능 기준 년도 조회 * 변화탐지 실행 가능 기준 년도 조회
* *
@@ -440,6 +436,12 @@ public class MapSheetMngCoreService {
return entity.stream().map(MapSheetMngHstEntity::getMapSheetNum).toList(); return entity.stream().map(MapSheetMngHstEntity::getMapSheetNum).toList();
} }
/**
* 특정 연도의 도엽 이력 데이터를 조회
*
* @param year
* @return
*/
public List<MapSheetFallbackYearDto> getMapSheetNumDtoByHst(Integer year) { public List<MapSheetFallbackYearDto> getMapSheetNumDtoByHst(Integer year) {
List<MapSheetMngHstEntity> entity = mapSheetMngRepository.getMapSheetMngHst(year); List<MapSheetMngHstEntity> entity = mapSheetMngRepository.getMapSheetMngHst(year);
return entity.stream() return entity.stream()

View File

@@ -18,29 +18,99 @@ import org.springframework.data.domain.Page;
public interface MapSheetLearnRepositoryCustom { public interface MapSheetLearnRepositoryCustom {
/**
* 추론 관리 목록 조회
*
* @param req 추론관리 목록 화면 조회 조건
* @return 추론 관리 목록
*/
Page<MapSheetLearnEntity> getInferenceMgnResultList(InferenceResultDto.SearchListReq req); Page<MapSheetLearnEntity> getInferenceMgnResultList(InferenceResultDto.SearchListReq req);
/**
* uuid 조건으로 추론 실행 정보 조회
*
* @param uuid uuid
* @return 추론 실행 정보
*/
Optional<MapSheetLearnEntity> getInferenceResultByUuid(UUID uuid); Optional<MapSheetLearnEntity> getInferenceResultByUuid(UUID uuid);
/**
* 추론 실행중 서버정보 조회 cpu, gpu
*
* @return cpu, gpu 정보
*/
List<InferenceServerStatusDto> getInferenceServerStatusList(); List<InferenceServerStatusDto> getInferenceServerStatusList();
/**
* 추론 실행 목록 진행 상태별 조회
*
* @param status 추론 진행 상태
* @return 추론 실행 정보
*/
Optional<MapSheetLearnEntity> getInferenceResultByStatus(String status); Optional<MapSheetLearnEntity> getInferenceResultByStatus(String status);
/**
* 등록된 추론 실행목록 및 등록된 모델 정보 조회
*
* @param id 추론 실행 테이블 id
* @param modelUuid 모델 uuid
* @return 모델 정보
*/
InferenceProgressDto getInferenceAiResultById(Long id, UUID modelUuid); InferenceProgressDto getInferenceAiResultById(Long id, UUID modelUuid);
/**
* 진행중인 추론 정보 상세 조회
*
* @param uuid 추론진행 uuid
* @return 진행중인 추론정보 상세 정보
*/
InferenceStatusDetailDto getInferenceStatus(UUID uuid); InferenceStatusDetailDto getInferenceStatus(UUID uuid);
/**
* 진행중인 추론이 있는지 조회
*
* @return 진행중인 추론 정보
*/
MapSheetLearnEntity getProcessing(); MapSheetLearnEntity getProcessing();
Integer getLearnStage(Integer compareYear, Integer targetYear); /**
* 추론 결과 정보 조회
*
* @param uuid 추론 uuid
* @return 추론 결과 및 사용 모델 정보
*/
AnalResultInfo getInferenceResultInfo(UUID uuid); AnalResultInfo getInferenceResultInfo(UUID uuid);
/**
* 추론 결과 bbox, point 조회
*
* @param uuid 추론 uuid
* @return bbox, pont 정보
*/
BboxPointDto getBboxPoint(UUID uuid); BboxPointDto getBboxPoint(UUID uuid);
/**
* 분류별 탐지건수 조회
*
* @param uuid 추론 uuid
* @return 분류별 탐지건수 정보
*/
List<Dashboard> getInferenceClassCountList(UUID uuid); List<Dashboard> getInferenceClassCountList(UUID uuid);
/**
* 추론 결과 상세 geom 목록 조회
*
* @param uuid 추론 uuid
* @param searchGeoReq 추론 결과 상세화면 geom 조회 조건
* @return geom 목록 정보
*/
Page<Geom> getInferenceGeomList(UUID uuid, SearchGeoReq searchGeoReq); Page<Geom> getInferenceGeomList(UUID uuid, SearchGeoReq searchGeoReq);
/**
* 국유in연동 가능여부 확인 조회
*
* @param uuid 추론 uuid
* @return 추론 존재여부, 부분도엽 여부, 추론 진행중 여부, 국유인 작업 진행중 여부
*/
GukYuinLinkFacts findLinkFacts(UUID uuid); GukYuinLinkFacts findLinkFacts(UUID uuid);
} }

View File

@@ -291,24 +291,6 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto
.fetchOne(); .fetchOne();
} }
@Override
public Integer getLearnStage(Integer compareYear, Integer targetYear) {
Integer stage =
queryFactory
.select(mapSheetLearnEntity.stage)
.from(mapSheetLearnEntity)
.where(
mapSheetLearnEntity
.compareYyyy
.eq(compareYear)
.and(mapSheetLearnEntity.targetYyyy.eq(targetYear)))
.orderBy(mapSheetLearnEntity.id.desc())
.limit(1)
.fetchOne();
return stage == null ? 1 : stage + 1;
}
@Override @Override
public AnalResultInfo getInferenceResultInfo(UUID uuid) { public AnalResultInfo getInferenceResultInfo(UUID uuid) {
QModelMngEntity m1 = new QModelMngEntity("m1"); QModelMngEntity m1 = new QModelMngEntity("m1");
@@ -528,6 +510,7 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto
@Override @Override
public GukYuinLinkFacts findLinkFacts(UUID uuid) { public GukYuinLinkFacts findLinkFacts(UUID uuid) {
// 해당 추론 있는지 확인
MapSheetLearnEntity learn = MapSheetLearnEntity learn =
queryFactory queryFactory
.selectFrom(QMapSheetLearnEntity.mapSheetLearnEntity) .selectFrom(QMapSheetLearnEntity.mapSheetLearnEntity)
@@ -538,12 +521,14 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto
return new GukYuinLinkFacts(false, false, false, false); return new GukYuinLinkFacts(false, false, false, false);
} }
// 부분 도엽 실행인지 확인
boolean isPartScope = MapSheetScope.PART.getId().equals(learn.getMapSheetScope()); boolean isPartScope = MapSheetScope.PART.getId().equals(learn.getMapSheetScope());
QMapSheetAnalInferenceEntity inf = QMapSheetAnalInferenceEntity.mapSheetAnalInferenceEntity; QMapSheetAnalInferenceEntity inf = QMapSheetAnalInferenceEntity.mapSheetAnalInferenceEntity;
QMapSheetLearnEntity learn2 = new QMapSheetLearnEntity("learn2"); QMapSheetLearnEntity learn2 = new QMapSheetLearnEntity("learn2");
QMapSheetLearnEntity learnQ = QMapSheetLearnEntity.mapSheetLearnEntity; QMapSheetLearnEntity learnQ = QMapSheetLearnEntity.mapSheetLearnEntity;
// 실행중인 추론 있는지 확인
boolean hasRunningInference = boolean hasRunningInference =
queryFactory queryFactory
.selectOne() .selectOne()
@@ -557,6 +542,7 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto
.fetchFirst() .fetchFirst()
!= null; != null;
// 국유인 작업 진행중 있는지 확인
boolean hasOtherUnfinishedGukYuin = boolean hasOtherUnfinishedGukYuin =
queryFactory queryFactory
.selectOne() .selectOne()

View File

@@ -64,6 +64,12 @@ public interface MapSheetMngRepositoryCustom {
List<MapSheetMngDto.MngFilesDto> findByHstUidMapSheetFileList(Long hstUid); List<MapSheetMngDto.MngFilesDto> findByHstUidMapSheetFileList(Long hstUid);
/**
* 변화탐지 실행 가능 기준 연도 조회
*
* @param req 조회 연도, 도엽번호 목록,
* @return
*/
List<MngListDto> findByHstMapSheetTargetList(InferenceResultDto.RegReq req); List<MngListDto> findByHstMapSheetTargetList(InferenceResultDto.RegReq req);
List<MngListDto> findByHstMapSheetTargetList(int mngYyyy, List<String> mapIds); List<MngListDto> findByHstMapSheetTargetList(int mngYyyy, List<String> mapIds);

View File

@@ -355,8 +355,7 @@ public class MapSheetInferenceJobService {
m.setCls_model_version(progressDto.getClsModelVersion()); m.setCls_model_version(progressDto.getClsModelVersion());
m.setCd_model_type(type); m.setCd_model_type(type);
m.setPriority(5d); m.setPriority(5d);
log.info("[BEFORE INFERENCE] BEFORE SendDto={}", m);
// log.info("InferenceSendDto={}", m);
// 추론 실행 api 호출 // 추론 실행 api 호출
Long batchId = ensureAccepted(m); Long batchId = ensureAccepted(m);
@@ -376,6 +375,7 @@ public class MapSheetInferenceJobService {
* @param dto * @param dto
* @return * @return
*/ */
// 같은함수가 왜 두개지
private Long ensureAccepted(InferenceSendDto dto) { private Long ensureAccepted(InferenceSendDto dto) {
if (dto == null) { if (dto == null) {
log.warn("not InferenceSendDto dto"); log.warn("not InferenceSendDto dto");
@@ -383,22 +383,28 @@ public class MapSheetInferenceJobService {
} }
// 1) 요청 로그 // 1) 요청 로그
log.info("Inference request dto={}", dto); log.info("");
log.info("========================================================");
log.info("[SEND INFERENCE] Inference request dto= {}", dto);
log.info("========================================================");
log.info("");
// 2) local 환경 임시 처리 // 2) local 환경 임시 처리
if ("local".equals(profile)) { // if ("local".equals(profile)) {
if (dto.getPred_requests_areas() == null) { // if (dto.getPred_requests_areas() == null) {
throw new IllegalStateException("pred_requests_areas is null"); // throw new IllegalStateException("pred_requests_areas is null");
} // }
dto.getPred_requests_areas().setInput1_scene_path("/kamco-nfs/requests/2023_local.geojson"); //
dto.getPred_requests_areas().setInput2_scene_path("/kamco-nfs/requests/2024_local.geojson"); // dto.getPred_requests_areas().setInput1_scene_path("/kamco-nfs/requests/2023_local.geojson");
} //
// dto.getPred_requests_areas().setInput2_scene_path("/kamco-nfs/requests/2024_local.geojson");
// }
// 3) HTTP 호출 // 3) HTTP 호출
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON); headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(List.of(MediaType.APPLICATION_JSON)); headers.setAccept(List.of(MediaType.APPLICATION_JSON));
// TODO 어떤 URL로 어떤파리티러로 요청한 로딩해야지
ExternalCallResult<String> result = ExternalCallResult<String> result =
externalHttpClient.call(inferenceUrl, HttpMethod.POST, dto, headers, String.class); externalHttpClient.call(inferenceUrl, HttpMethod.POST, dto, headers, String.class);
@@ -413,6 +419,7 @@ public class MapSheetInferenceJobService {
objectMapper.readValue(result.body(), new TypeReference<>() {}); objectMapper.readValue(result.body(), new TypeReference<>() {});
if (list.isEmpty()) { if (list.isEmpty()) {
// 어떤 URL로 어떤파리티러로 요청한 정보를 봐야 재현을 할듯하지요
throw new IllegalStateException("Inference response is empty"); throw new IllegalStateException("Inference response is empty");
} }

View File

@@ -31,7 +31,7 @@ public class TrainingDataReviewJobService {
@Value("${spring.profiles.active}") @Value("${spring.profiles.active}")
private String profile; private String profile;
@Value("${training-data.geojson-dir}") @Value("${file.training-data.geojson-dir}")
private String trainingDataDir; private String trainingDataDir;
private boolean isLocalProfile() { private boolean isLocalProfile() {

View File

@@ -89,36 +89,17 @@ mapsheet:
shp: shp:
baseurl: /app/tmp/detect/result #현재사용안함 baseurl: /app/tmp/detect/result #현재사용안함
file: file:
#sync-root-dir: D:/kamco-nfs/images/ root: kamco-nfs
sync-root-dir: /kamco-nfs/images/ nfs: /kamco-nfs
sync-tmp-dir: /kamco-nfs/requests/temp # image upload temp dir pt-path: ${file.nfs}/ckpt/model/v6-cls-checkpoints/
#sync-tmp-dir: ${file.sync-root-dir}/tmp
sync-file-extention: tfw,tif
# sync-auto-exception-start-year: 2024
# sync-auto-exception-before-year-cnt: 3
#dataset-dir: D:/kamco-nfs/model_output/
dataset-dir: /kamco-nfs/model_output/export/ # 마운트경로 AI 추론결과
dataset-tmp-dir: ${file.dataset-dir}tmp/
#model-dir: D:/kamco-nfs/ckpt/model/
model-dir: /kamco-nfs/ckpt/model/ # 학습서버에서 트레이닝한 모델업로드경로
model-tmp-dir: ${file.model-dir}tmp/
model-file-extention: pth,json,py
pt-path: /kamco-nfs/ckpt/model/v6-cls-checkpoints/
pt-FileName: yolov8_6th-6m.pt pt-FileName: yolov8_6th-6m.pt
dataset-response: /kamco-nfs/dataset/response/
inference: inference:
nfs: /kamco-nfs
url: http://192.168.2.183:8000/jobs url: http://192.168.2.183:8000/jobs
batch-url: http://192.168.2.183:8000/batches batch-url: http://192.168.2.183:8000/batches
geojson-dir: /kamco-nfs/requests/ # 추론실행을 위한 파일생성경로 jar-path: ${inference.nfs}/repo/jar/shp-exporter.jar
jar-path: /kamco-nfs/repo/jar/shp-exporter.jar
inference-server-name: server1,server2,server3,server4 inference-server-name: server1,server2,server3,server4
gukyuin: gukyuin:
@@ -126,9 +107,6 @@ gukyuin:
url: http://192.168.2.129:5301 url: http://192.168.2.129:5301
cdi: ${gukyuin.url}/api/kcd/cdi cdi: ${gukyuin.url}/api/kcd/cdi
training-data:
geojson-dir: /kamco-nfs/dataset/request/
layer: layer:
geoserver-url: https://kamco.geo-dev.gs.dabeeo.com geoserver-url: https://kamco.geo-dev.gs.dabeeo.com
wms-path: geoserver/cd wms-path: geoserver/cd

View File

@@ -67,34 +67,17 @@ mapsheet:
shp: shp:
baseurl: /Users/bokmin/detect/result baseurl: /Users/bokmin/detect/result
file: file:
sync-root-dir: C:/Users/gypark/kamco-nfs/images/ root: kamco-nfs
#sync-root-dir: /kamco-nfs/images/ nfs: C:/Users/gypark/kamco-nfs
sync-tmp-dir: ${file.sync-root-dir}/tmp/ pt-path: ${file.nfs}/ckpt/classification/
sync-file-extention: tfw,tif
# sync-auto-exception-start-year: 2025
# sync-auto-exception-before-year-cnt: 3
dataset-dir: C:/Users/gypark/kamco-nfs/dataset/
#dataset-dir: /kamco-nfs/dataset/export/
dataset-tmp-dir: ${file.dataset-dir}tmp/
model-dir: C:/Users/gypark/kamco-nfs/ckpt/model/
#model-dir: /kamco-nfs/ckpt/model/
model-tmp-dir: ${file.model-dir}tmp/
model-file-extention: pth,json,py
pt-path: /kamco-nfs/ckpt/classification/
pt-FileName: v5-best.pt pt-FileName: v5-best.pt
dataset-response: /kamco-nfs/dataset/response/
inference: inference:
nfs: C:/Users/gyparkkamco-nfs
url: http://10.100.0.11:8000/jobs url: http://10.100.0.11:8000/jobs
batch-url: http://10.100.0.11:8000/batches batch-url: http://10.100.0.11:8000/batches
geojson-dir: /kamco-nfs/requests/ jar-path: jar/shp-exporter.jar
jar-path: jar/makeshp-1.0.0.jar
inference-server-name: server1,server2,server3,server4 inference-server-name: server1,server2,server3,server4
gukyuin: gukyuin:
@@ -102,9 +85,6 @@ gukyuin:
url: http://192.168.2.129:5301 url: http://192.168.2.129:5301
cdi: ${gukyuin.url}/api/kcd/cdi cdi: ${gukyuin.url}/api/kcd/cdi
training-data:
geojson-dir: /kamco-nfs/model_output/labeling/
layer: layer:
geoserver-url: https://kamco.geo-dev.gs.dabeeo.com geoserver-url: https://kamco.geo-dev.gs.dabeeo.com
wms-path: geoserver/cd wms-path: geoserver/cd

View File

@@ -84,36 +84,23 @@ mapsheet:
baseurl: /app/detect/result #현재사용안함 baseurl: /app/detect/result #현재사용안함
file: file:
sync-root-dir: /kamco-nfs/images/ root: data
sync-tmp-dir: /kamco-nfs/repo/tmp # image upload temp dir nfs: /data
sync-file-extention: tfw,tif pt-path: ${file.nfs}/ckpt/model/v6-cls-checkpoints/
#dataset-dir: D:/kamco-nfs/model_output/ #변경 model_output
dataset-dir: /kamco-nfs/model_output/export/ # 마운트경로 AI 추론결과
dataset-tmp-dir: ${file.dataset-dir}tmp/
#model-dir: D:/kamco-nfs/ckpt/model/
model-dir: /kamco-nfs/ckpt/model/ # 학습서버에서 트레이닝한 모델업로드경로
model-tmp-dir: ${file.model-dir}tmp/
model-file-extention: pth,json,py
pt-path: /kamco-nfs/ckpt/v6-cls-checkpoints/
pt-FileName: yolov8_6th-6m.pt pt-FileName: yolov8_6th-6m.pt
dataset-response: /kamco-nfs/dataset/response/
inference: inference:
url: http://127.0.0.1:8000/jobs nfs: /data
batch-url: http://127.0.0.1:8000/batches url: http://172.16.4.56:8000/jobs
geojson-dir: /kamco-nfs/requests/ # 학습서버에서 트레이닝한 모델업로드경로 batch-url: http://172.16.4.56:8000/batches
jar-path: /kamco-nfs/repo/jar/shp-exporter.jar # 추론실행을 위한 파일생성경로 jar-path: ${inference.nfs}/repo/jar/shp-exporter.jar
inference-server-name: server1,server2,server3,server4 inference-server-name: server1,server2,server3,server4
gukyuin: gukyuin:
url: http://127.0.0.1:5301 url: http://127.0.0.1:5301
cdi: ${gukyuin.url}/api/kcd/cdi cdi: ${gukyuin.url}/api/kcd/cdi
training-data:
geojson-dir: /kamco-nfs/dataset/request/
layer: layer:
geoserver-url: https://kamco.geo-dev.gs.dabeeo.com geoserver-url: https://kamco.geo-dev.gs.dabeeo.com

View File

@@ -67,3 +67,22 @@ management:
include: include:
- "health" - "health"
file:
root: kamco-nfs
nfs: /kamco-nfs
sync-root-dir: ${file.nfs}/images/
sync-tmp-dir: ${file.nfs}/requests/temp # image upload temp dir
sync-file-extention: tfw,tif
dataset-dir: ${file.nfs}/model_output/export/ # 마운트경로 AI 추론결과
dataset-tmp-dir: ${file.dataset-dir}tmp/
model-dir: ${file.nfs}/ckpt/model/ # 학습서버에서 트레이닝한 모델업로드경로
model-tmp-dir: ${file.model-dir}tmp/
model-file-extention: pth,json,py
pt-path: ${file.nfs}/ckpt/model/v6-cls-checkpoints/
dataset-response: ${file.nfs}/dataset/response/
training-data:
geojson-dir: ${file.nfs}/dataset/request/
inference:
nfs: /kamco-nfs
geojson-dir: ${inference.nfs}/requests/ # 추론실행을 위한 파일생성경로
jar-path: ${inference.nfs}/repo/jar/shp-exporter.jar