Feat: Report 틀 구현 S11P21S002-215
This commit is contained in:
parent
650e3ec6ee
commit
22de4b5b34
@ -127,7 +127,7 @@ public class AiModelService {
|
||||
}
|
||||
|
||||
@CheckPrivilege(PrivilegeType.EDITOR)
|
||||
public void train(final Integer projectId, Integer modelId) {
|
||||
public void train(final Integer projectId, final Integer modelId) {
|
||||
trainProgressCheck(projectId);
|
||||
|
||||
// FastAPI 서버로 학습 요청을 전송
|
||||
|
@ -0,0 +1,24 @@
|
||||
package com.worlabel.domain.report.controller;
|
||||
|
||||
import com.worlabel.domain.report.entity.dto.ReportResponse;
|
||||
import com.worlabel.domain.report.service.ReportService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/reports")
|
||||
@RequiredArgsConstructor
|
||||
public class ReportController {
|
||||
|
||||
private final ReportService reportService;
|
||||
|
||||
@GetMapping("/model/{model_id}")
|
||||
public List<ReportResponse> getReportsByModelId(@PathVariable("model_id") final Integer modelId) {
|
||||
return reportService.getReportsByModelId(modelId);
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package com.worlabel.domain.report.entity;
|
||||
|
||||
import com.worlabel.domain.model.entity.AiModel;
|
||||
import com.worlabel.global.common.BaseEntity;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@Entity
|
||||
@Table(name = "report")
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public class Report extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@Column(name = "report_id", nullable = false)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 소속된 모델
|
||||
*/
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "model_id", nullable = false)
|
||||
private AiModel aiModel;
|
||||
|
||||
/**
|
||||
* 전체 에포크
|
||||
*/
|
||||
@Column(name = "total_epochs", nullable = false)
|
||||
private Integer totalEpochs;
|
||||
|
||||
/**
|
||||
* 현재 에포크
|
||||
*/
|
||||
@Column(name = "epoch", nullable = false)
|
||||
private Integer epoch;
|
||||
|
||||
@Column(name = "box_loss", nullable = false)
|
||||
private double boxLoss;
|
||||
|
||||
@Column(name = "cls_loss", nullable = false)
|
||||
private double clsLoss;
|
||||
|
||||
@Column(name = "dfl_loss", nullable = false)
|
||||
private double dflLoss;
|
||||
|
||||
@Column(name = "fitness", nullable = false)
|
||||
private double fitness;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.worlabel.domain.report.entity.dto;
|
||||
|
||||
import com.worlabel.domain.report.entity.Report;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class ReportResponse {
|
||||
private Integer id;
|
||||
private Integer totalEpochs;
|
||||
private Integer epoch;
|
||||
private double boxLoss;
|
||||
private double clsLoss;
|
||||
private double dflLoss;
|
||||
private double fitness;
|
||||
|
||||
public static ReportResponse from(final Report report) {
|
||||
return new ReportResponse(
|
||||
report.getId(),
|
||||
report.getTotalEpochs(),
|
||||
report.getEpoch(),
|
||||
report.getBoxLoss(),
|
||||
report.getClsLoss(),
|
||||
report.getDflLoss(),
|
||||
report.getFitness());
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.worlabel.domain.report.repository;
|
||||
|
||||
import com.worlabel.domain.report.entity.Report;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ReportRepository extends JpaRepository<Report, Integer> {
|
||||
|
||||
List<Report> findByAiModelId(Integer modelId);
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.worlabel.domain.report.service;
|
||||
|
||||
import com.worlabel.domain.report.entity.Report;
|
||||
import com.worlabel.domain.report.entity.dto.ReportResponse;
|
||||
import com.worlabel.domain.report.repository.ReportRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
@RequiredArgsConstructor
|
||||
public class ReportService {
|
||||
|
||||
private final ReportRepository reportRepository;
|
||||
|
||||
public List<ReportResponse> getReportsByModelId(final Integer modelId) {
|
||||
List<Report> reports = reportRepository.findByAiModelId(modelId);
|
||||
return reports.stream()
|
||||
.map(ReportResponse::from)
|
||||
.toList();
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.worlabel.domain.result.controller;
|
||||
|
||||
import com.worlabel.domain.result.entity.dto.ResultResponse;
|
||||
import com.worlabel.domain.result.service.ResultService;
|
||||
import com.worlabel.global.config.swagger.SwaggerApiError;
|
||||
import com.worlabel.global.config.swagger.SwaggerApiSuccess;
|
||||
import com.worlabel.global.exception.ErrorCode;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "결과 관련 API")
|
||||
@RestController
|
||||
@RequestMapping("/api/results")
|
||||
@RequiredArgsConstructor
|
||||
public class ResultController {
|
||||
|
||||
private final ResultService resultService;
|
||||
|
||||
@Operation(summary = "모델 결과 조회", description = "모델 결과를 조회합니다.")
|
||||
@SwaggerApiSuccess(description = "모델 결과를 성공적으로 조회합니다")
|
||||
@SwaggerApiError({ErrorCode.EMPTY_REQUEST_PARAMETER, ErrorCode.SERVER_ERROR})
|
||||
@GetMapping("/model/{model_id}")
|
||||
public List<ResultResponse> getResultsByModelId(@PathVariable("model_id") final Integer modelId) {
|
||||
return resultService.getResultsByModelId(modelId);
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.worlabel.domain.result.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
public enum Optimizer {
|
||||
|
||||
AUTO("AUTO"),
|
||||
SGD("SGD"),
|
||||
ADAM("ADAM"),
|
||||
ADAMW("ADAMW"),
|
||||
NADAM("NADAM"),
|
||||
RADAM("RADAM"),
|
||||
RMSPROP("RMSPROP");
|
||||
|
||||
private final String value;
|
||||
|
||||
Optimizer(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public static Optimizer from(String value) {
|
||||
for (Optimizer status : Optimizer.values()) {
|
||||
if (status.getValue().equals(value.toUpperCase())) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.worlabel.domain.result.entity;
|
||||
|
||||
import com.worlabel.domain.model.entity.AiModel;
|
||||
import com.worlabel.global.common.BaseEntity;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@Entity
|
||||
@Table(name = "result")
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public class Result extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@Column(name = "result_id", nullable = false)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 소속된 모델
|
||||
*/
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "model_id", nullable = false)
|
||||
private AiModel aiModel;
|
||||
|
||||
@Column(name = "precision", nullable = false)
|
||||
private double precision;
|
||||
|
||||
@Column(name = "recall", nullable = false)
|
||||
private double recall;
|
||||
|
||||
@Column(name = "mAP50", nullable = false)
|
||||
private double mAP50;
|
||||
|
||||
@Column(name = "mAP50-95", nullable = false)
|
||||
private double mAP5095;
|
||||
|
||||
@Column(name = "fitness", nullable = false)
|
||||
private double fitness;
|
||||
|
||||
@Column(name = "ratio", nullable = false)
|
||||
private double ratio;
|
||||
|
||||
@Column(name = "epochs", nullable = false)
|
||||
private double epochs;
|
||||
|
||||
@Column(name = "batch", nullable = false)
|
||||
private double batch;
|
||||
|
||||
@Column(name = "ir0", nullable = false)
|
||||
private double ir0;
|
||||
|
||||
@Column(name = "irf", nullable = false)
|
||||
private double irf;
|
||||
|
||||
@Column(name = "optimizer", nullable = false)
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Optimizer optimizer;
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package com.worlabel.domain.result.entity.dto;
|
||||
|
||||
import com.worlabel.domain.result.entity.Optimizer;
|
||||
import com.worlabel.domain.result.entity.Result;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class ResultResponse {
|
||||
private Integer id;
|
||||
private double precision;
|
||||
private double recall;
|
||||
private double mAP50;
|
||||
private double mAP5095;
|
||||
private double fitness;
|
||||
private double ratio;
|
||||
private double epochs;
|
||||
private double batch;
|
||||
private double ir0;
|
||||
private double irf;
|
||||
private Optimizer optimizer;
|
||||
|
||||
public static ResultResponse fromResult(final Result result) {
|
||||
return new ResultResponse(
|
||||
result.getId(),
|
||||
result.getPrecision(),
|
||||
result.getRecall(),
|
||||
result.getMAP50(),
|
||||
result.getMAP5095(),
|
||||
result.getFitness(),
|
||||
result.getRatio(),
|
||||
result.getEpochs(),
|
||||
result.getBatch(),
|
||||
result.getIr0(),
|
||||
result.getIrf(),
|
||||
result.getOptimizer());
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.worlabel.domain.result.repository;
|
||||
|
||||
import com.worlabel.domain.result.entity.Result;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ResultRepository extends JpaRepository<Result, Integer> {
|
||||
|
||||
List<Result> findByAiModelId(Integer modelId);
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.worlabel.domain.result.service;
|
||||
|
||||
import com.worlabel.domain.result.entity.Result;
|
||||
import com.worlabel.domain.result.entity.dto.ResultResponse;
|
||||
import com.worlabel.domain.result.repository.ResultRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
@RequiredArgsConstructor
|
||||
public class ResultService {
|
||||
|
||||
private final ResultRepository resultRepository;
|
||||
|
||||
public List<ResultResponse> getResultsByModelId(final Integer modelId) {
|
||||
List<Result> results = resultRepository.findByAiModelId(modelId);
|
||||
return results.stream()
|
||||
.map(ResultResponse::fromResult)
|
||||
.toList();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user