-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Rename: AI Task 도메인 이름 변경 - llm 으로 변경 * Refactor: LLM 도메인 애플리케이션 계층과 프레젠테이션 계층 응답 분리 * Feat: LLM 작업 진행 상태 확인 기능 구현 * Feat: 요약 및 문제 결과 조회 기능 구현 * Feat: 요약 및 문제 생성 기능 구현 - AI 서버와 통신하는 부분 제외하고 기능 구현 - 임시 UUID 를 통해 task 저장 * Feat: LLM 서버 콜백 기능 구현 - LLM 서버가 API 콜을 통해 페이지별 요약 및 문제 내용 전달 - task id 를 통해 조회하여 요약 내용과 문제 내용 업데이트 * Refactor: 변수 이름 변경 - 필드명 카멜케이스로 변경 * Refactor: 통일성 없는 부분 수정 - 필드명 변경 - 변수 추출 * Refactor: 예외 종류, 메서드 네이밍 변경 - LLMQueryService 예외 타입 변경 - SummaryAndProblemUpdateResponse 메서드 네이밍 변경 * Refactor: LLMQueryService 응답과 LLMController 응답 분리
- Loading branch information
Showing
34 changed files
with
928 additions
and
140 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
10 changes: 0 additions & 10 deletions
10
src/main/java/notai/aiTask/application/command/AITaskCommand.java
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
28 changes: 0 additions & 28 deletions
28
src/main/java/notai/aiTask/presentation/AITaskController.java
This file was deleted.
Oops, something went wrong.
18 changes: 0 additions & 18 deletions
18
src/main/java/notai/aiTask/presentation/request/AITaskRequest.java
This file was deleted.
Oops, something went wrong.
12 changes: 0 additions & 12 deletions
12
src/main/java/notai/aiTask/presentation/response/AITaskResponse.java
This file was deleted.
Oops, something went wrong.
110 changes: 110 additions & 0 deletions
110
src/main/java/notai/llm/application/LLMQueryService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package notai.llm.application; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import notai.common.exception.type.BadRequestException; | ||
import notai.common.exception.type.InternalServerErrorException; | ||
import notai.common.exception.type.NotFoundException; | ||
import notai.document.domain.DocumentRepository; | ||
import notai.llm.application.result.LLMResultsResult; | ||
import notai.llm.application.result.LLMResultsResult.LLMContent; | ||
import notai.llm.application.result.LLMResultsResult.LLMResult; | ||
import notai.llm.application.result.LLMStatusResult; | ||
import notai.llm.domain.TaskStatus; | ||
import notai.llm.query.LLMQueryRepository; | ||
import notai.problem.query.ProblemQueryRepository; | ||
import notai.problem.query.result.ProblemPageContentResult; | ||
import notai.summary.query.SummaryQueryRepository; | ||
import notai.summary.query.result.SummaryPageContentResult; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
import static notai.llm.domain.TaskStatus.COMPLETED; | ||
import static notai.llm.domain.TaskStatus.IN_PROGRESS; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class LLMQueryService { | ||
|
||
private final LLMQueryRepository llmQueryRepository; | ||
private final DocumentRepository documentRepository; | ||
private final SummaryQueryRepository summaryQueryRepository; | ||
private final ProblemQueryRepository problemQueryRepository; | ||
|
||
public LLMStatusResult fetchTaskStatus(Long documentId) { | ||
checkDocumentExists(documentId); | ||
List<Long> summaryIds = getSummaryIds(documentId); | ||
List<TaskStatus> taskStatuses = getTaskStatuses(summaryIds); | ||
|
||
int totalPages = summaryIds.size(); | ||
int completedPages = Collections.frequency(taskStatuses, COMPLETED); | ||
|
||
if (totalPages == completedPages) { | ||
return LLMStatusResult.of(documentId, COMPLETED, totalPages, completedPages); | ||
} | ||
return LLMStatusResult.of(documentId, IN_PROGRESS, totalPages, completedPages); | ||
} | ||
|
||
public LLMResultsResult findTaskResult(Long documentId) { | ||
checkDocumentExists(documentId); | ||
List<SummaryPageContentResult> summaryResults = getSummaryPageContentResults(documentId); | ||
List<ProblemPageContentResult> problemResults = getProblemPageContentResults(documentId); | ||
checkSummaryAndProblemCountsEqual(summaryResults, problemResults); | ||
|
||
List<LLMResult> results = summaryResults.stream().map(summaryResult -> { | ||
LLMContent content = LLMContent.of( | ||
summaryResult.content(), | ||
findProblemContentByPageNumber(problemResults, summaryResult.pageNumber()) | ||
); | ||
return LLMResult.of(summaryResult.pageNumber(), content); | ||
}).toList(); | ||
|
||
return LLMResultsResult.of(documentId, results); | ||
} | ||
|
||
private void checkDocumentExists(Long documentId) { | ||
if (!documentRepository.existsById(documentId)) { | ||
throw new NotFoundException("해당 강의자료를 찾을 수 없습니다."); | ||
} | ||
} | ||
|
||
private static void checkSummaryAndProblemCountsEqual( | ||
List<SummaryPageContentResult> summaryResults, List<ProblemPageContentResult> problemResults | ||
) { | ||
if (summaryResults.size() != problemResults.size()) { | ||
throw new InternalServerErrorException("AI 요약 및 문제 생성 중에 문제가 발생했습니다."); // 요약 개수와 문제 개수가 불일치 | ||
} | ||
} | ||
|
||
private List<Long> getSummaryIds(Long documentId) { | ||
List<Long> summaryIds = summaryQueryRepository.getSummaryIdsByDocumentId(documentId); | ||
if (summaryIds.isEmpty()) { | ||
throw new BadRequestException("AI 기능을 요청한 기록이 없습니다."); | ||
} | ||
return summaryIds; | ||
} | ||
|
||
private List<TaskStatus> getTaskStatuses(List<Long> summaryIds) { | ||
return summaryIds.stream().map(llmQueryRepository::getTaskStatusBySummaryId).toList(); | ||
} | ||
|
||
private List<SummaryPageContentResult> getSummaryPageContentResults(Long documentId) { | ||
List<SummaryPageContentResult> summaryResults = summaryQueryRepository.getPageNumbersAndContentByDocumentId( | ||
documentId); | ||
if (summaryResults.isEmpty()) { | ||
throw new NotFoundException("AI 기능을 요청한 기록이 없습니다."); | ||
} | ||
return summaryResults; | ||
} | ||
|
||
private List<ProblemPageContentResult> getProblemPageContentResults(Long documentId) { | ||
return problemQueryRepository.getPageNumbersAndContentByDocumentId(documentId); | ||
} | ||
|
||
private String findProblemContentByPageNumber(List<ProblemPageContentResult> results, int pageNumber) { | ||
return results.stream().filter(result -> result.pageNumber() == pageNumber).findFirst().map( | ||
ProblemPageContentResult::content).orElseThrow(() -> new InternalServerErrorException( | ||
"AI 요약 및 문제 생성 중에 문제가 발생했습니다.")); // 요약 페이지와 문제 페이지가 불일치 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package notai.llm.application; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import notai.common.exception.type.NotFoundException; | ||
import notai.document.domain.Document; | ||
import notai.document.domain.DocumentRepository; | ||
import notai.llm.application.command.LLMSubmitCommand; | ||
import notai.llm.application.command.SummaryAndProblemUpdateCommand; | ||
import notai.llm.application.result.LLMSubmitResult; | ||
import notai.llm.domain.LLM; | ||
import notai.llm.domain.LLMRepository; | ||
import notai.problem.domain.Problem; | ||
import notai.problem.domain.ProblemRepository; | ||
import notai.summary.domain.Summary; | ||
import notai.summary.domain.SummaryRepository; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.time.LocalDateTime; | ||
import java.util.UUID; | ||
|
||
/** | ||
* SummaryService 와 ExamService 는 엔티티와 관련된 로직만 처리하고 | ||
* AI 요약 및 문제 생성 요청은 여기서 처리하는 식으로 생각했습니다. | ||
* AI 서버와의 통신은 별도 클래스에서 처리합니다. | ||
*/ | ||
@Service | ||
@Transactional | ||
@RequiredArgsConstructor | ||
public class LLMService { | ||
|
||
private final LLMRepository llmRepository; | ||
private final DocumentRepository documentRepository; | ||
private final SummaryRepository summaryRepository; | ||
private final ProblemRepository problemRepository; | ||
|
||
public LLMSubmitResult submitTask(LLMSubmitCommand command) { | ||
// TODO: document 개발 코드 올려주시면, getById 로 수정 | ||
Document foundDocument = | ||
documentRepository.findById(command.documentId()).orElseThrow(() -> new NotFoundException("")); | ||
|
||
command.pages().forEach(pageNumber -> { | ||
UUID taskId = sendRequestToAIServer(); | ||
Summary summary = new Summary(foundDocument, pageNumber); | ||
Problem problem = new Problem(foundDocument, pageNumber); | ||
|
||
LLM taskRecord = new LLM(taskId, summary, problem); | ||
llmRepository.save(taskRecord); | ||
}); | ||
|
||
return LLMSubmitResult.of(command.documentId(), LocalDateTime.now()); | ||
} | ||
|
||
public Integer updateSummaryAndProblem(SummaryAndProblemUpdateCommand command) { | ||
LLM taskRecord = llmRepository.getById(command.taskId()); | ||
Summary foundSummary = summaryRepository.getById(taskRecord.getSummary().getId()); | ||
Problem foundProblem = problemRepository.getById(taskRecord.getProblem().getId()); | ||
|
||
taskRecord.completeTask(); | ||
foundSummary.updateContent(command.summary()); | ||
foundProblem.updateContent(command.problem()); | ||
|
||
llmRepository.save(taskRecord); | ||
summaryRepository.save(foundSummary); | ||
problemRepository.save(foundProblem); | ||
|
||
return command.pageNumber(); | ||
} | ||
|
||
/** | ||
* 임시 값 반환, 추후 AI 서버에서 작업 단위 UUID 가 반환됨. | ||
*/ | ||
private UUID sendRequestToAIServer() { | ||
return UUID.randomUUID(); | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
src/main/java/notai/llm/application/command/LLMSubmitCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package notai.llm.application.command; | ||
|
||
import java.util.List; | ||
|
||
public record LLMSubmitCommand( | ||
Long documentId, | ||
List<Integer> pages | ||
) { | ||
|
||
} |
11 changes: 11 additions & 0 deletions
11
src/main/java/notai/llm/application/command/SummaryAndProblemUpdateCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package notai.llm.application.command; | ||
|
||
import java.util.UUID; | ||
|
||
public record SummaryAndProblemUpdateCommand( | ||
UUID taskId, | ||
Integer pageNumber, | ||
String summary, | ||
String problem | ||
) { | ||
} |
31 changes: 31 additions & 0 deletions
31
src/main/java/notai/llm/application/result/LLMResultsResult.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package notai.llm.application.result; | ||
|
||
import java.util.List; | ||
|
||
public record LLMResultsResult( | ||
Long documentId, | ||
Integer totalPages, | ||
List<LLMResult> results | ||
) { | ||
public static LLMResultsResult of(Long documentId, List<LLMResult> results) { | ||
return new LLMResultsResult(documentId, results.size(), results); | ||
} | ||
|
||
public record LLMResult( | ||
Integer pageNumber, | ||
LLMContent content | ||
) { | ||
public static LLMResult of(Integer pageNumber, LLMContent content) { | ||
return new LLMResult(pageNumber, content); | ||
} | ||
} | ||
|
||
public record LLMContent( | ||
String summary, | ||
String problem | ||
) { | ||
public static LLMContent of(String summary, String problem) { | ||
return new LLMContent(summary, problem); | ||
} | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
src/main/java/notai/llm/application/result/LLMStatusResult.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package notai.llm.application.result; | ||
|
||
import notai.llm.domain.TaskStatus; | ||
|
||
public record LLMStatusResult( | ||
Long documentId, | ||
TaskStatus overallStatus, | ||
Integer totalPages, | ||
Integer completedPages | ||
) { | ||
public static LLMStatusResult of(Long documentId, TaskStatus overallStatus, Integer totalPages, Integer completedPages) { | ||
return new LLMStatusResult(documentId, overallStatus, totalPages, completedPages); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
src/main/java/notai/llm/application/result/LLMSubmitResult.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package notai.llm.application.result; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
public record LLMSubmitResult( | ||
Long documentId, | ||
LocalDateTime createdAt | ||
) { | ||
public static LLMSubmitResult of(Long documentId, LocalDateTime createdAt) { | ||
return new LLMSubmitResult(documentId, createdAt); | ||
} | ||
} |
Oops, something went wrong.