Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[refactor] 해당하는 내용이 없을 때 로직 변환 #69

Merged
Merged
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@

### BackEnd

![image](https://private-user-images.githubusercontent.com/96857599/357939550-e61acd91-40f3-47c6-b58d-6c210cce9d3e.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjM2NTc1ODksIm5iZiI6MTcyMzY1NzI4OSwicGF0aCI6Ii85Njg1NzU5OS8zNTc5Mzk1NTAtZTYxYWNkOTEtNDBmMy00N2M2LWI1OGQtNmMyMTBjY2U5ZDNlLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE0VDE3NDEyOVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTAyNTRmNzVmYTZjYTZlNjNkMzY0YTMwNWFlNmFmNDM1ZDExNzIxZmY2MDc5NDBkMGQ3ZWU4YmE1N2FiYTYxMmYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.WCKvC1LEVzly9Y5ZAl8HeyIibzegq3DEWjJl69YfIFk)
![image](https://github.com/user-attachments/assets/e61acd91-40f3-47c6-b58d-6c210cce9d3e)

### CI/CD

![image](https://private-user-images.githubusercontent.com/96857599/357939595-ba3f7b00-52c6-471d-ab03-0b1ad9bd7da0.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjM2NTc1ODksIm5iZiI6MTcyMzY1NzI4OSwicGF0aCI6Ii85Njg1NzU5OS8zNTc5Mzk1OTUtYmEzZjdiMDAtNTJjNi00NzFkLWFiMDMtMGIxYWQ5YmQ3ZGEwLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE0VDE3NDEyOVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTk2MDRkNzYxOTNkMjc5MmYwODk3NjE0YWJkMWY5ZGVmMzgzYzE4ZDRlY2EwMDkwZTMwNzg2NjhkNzE5Njk5MDcmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.4OeaRiMw0sZr7raOQRZitZ2aOW0QjQHWTmmMIGnidMI)
![image](https://github.com/user-attachments/assets/ba3f7b00-52c6-471d-ab03-0b1ad9bd7da0)
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import mju.iphak.maru_egg.answer.application.AnswerService;
import mju.iphak.maru_egg.answer.application.AnswerApiClient;
import mju.iphak.maru_egg.answer.docs.AdminAnswerControllerDocs;
import mju.iphak.maru_egg.answer.dto.request.UpdateAnswerContentRequest;
import mju.iphak.maru_egg.common.meta.CustomApiResponse;
Expand All @@ -18,7 +18,7 @@
@RequestMapping("/api/admin/answers")
public class AdminAnswerController implements AdminAnswerControllerDocs {

private final AnswerService answerService;
private final AnswerApiClient answerApiClient;

@CustomApiResponses({
@CustomApiResponse(error = "HttpMessageNotReadableException", status = 400, message = "Invalid input format: JSON parse error: Cannot deserialize value of type `java.lang.Long` from String \"ㅇㅇ\": not a valid `java.lang.Long` value", description = "잘못된 요청 값을 보낸 경우"),
Expand All @@ -27,6 +27,6 @@ public class AdminAnswerController implements AdminAnswerControllerDocs {
})
@PostMapping()
public void updateAnswerContent(@Valid @RequestBody UpdateAnswerContentRequest request) {
answerService.updateAnswerContent(request.id(), request.content());
answerApiClient.updateAnswerContent(request.id(), request.content());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
@RequiredArgsConstructor
@Service
@Transactional
public class AnswerService {
public class AnswerApiClient {

private final AnswerRepository answerRepository;
private final WebClient webClient;
Expand Down
105 changes: 105 additions & 0 deletions src/main/java/mju/iphak/maru_egg/answer/application/AnswerManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package mju.iphak.maru_egg.answer.application;

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import mju.iphak.maru_egg.answer.domain.Answer;
import mju.iphak.maru_egg.answer.domain.AnswerReference;
import mju.iphak.maru_egg.answer.dto.request.LLMAskQuestionRequest;
import mju.iphak.maru_egg.answer.dto.response.AnswerReferenceResponse;
import mju.iphak.maru_egg.answer.dto.response.AnswerResponse;
import mju.iphak.maru_egg.answer.dto.response.LLMAnswerResponse;
import mju.iphak.maru_egg.answer.repository.AnswerReferenceRepository;
import mju.iphak.maru_egg.question.domain.Question;
import mju.iphak.maru_egg.question.domain.QuestionCategory;
import mju.iphak.maru_egg.question.domain.QuestionType;
import mju.iphak.maru_egg.question.dto.response.QuestionResponse;
import mju.iphak.maru_egg.question.repository.QuestionRepository;

@Slf4j
@RequiredArgsConstructor
@Service
@Transactional
public class AnswerManager {

private static final String INVALID_ANSWER = "해당 내용에 대한 정보는 존재하지 않습니다. 정확한 내용은 입학지원팀에 문의해주세요.";
private static final String BASE_MESSAGE = """
질문해주신 내용에 대한 적절한 정보을 발견하지 못 했습니다.

대신 질문해주신 내용에 가장 적합한 자료들을 골라봤어요. 참고하셔서 다시 질문해주세요!

""";
private static final String IPHAK_OFFICE_NUMBER_GUIDE = "\n입학처 상담 전화번호 : 02-300-1799, 1800";

private final QuestionRepository questionRepository;
private final AnswerApiClient answerApiClient;
private final AnswerReferenceRepository answerReferenceRepository;

public QuestionResponse processNewQuestion(QuestionType type, QuestionCategory category, String content,
String contentToken) {
LLMAskQuestionRequest askQuestionRequest = LLMAskQuestionRequest.of(
type.getType(),
category == null ? "" : category.getCategory(),
content
);

LLMAnswerResponse llmAnswerResponse = answerApiClient.askQuestion(askQuestionRequest).block();

if (isInvalidAnswer(llmAnswerResponse)) {
return QuestionResponse.valueOfInvalidQuestion(content, getGuideAnswer(llmAnswerResponse.references()));
}

return saveAndGetQuestionResponse(type, content, contentToken, llmAnswerResponse);
}

private QuestionResponse saveAndGetQuestionResponse(final QuestionType type, final String content,
final String contentToken, final LLMAnswerResponse llmAnswerResponse) {
Question newQuestion = saveQuestion(type,
QuestionCategory.convertToCategory(llmAnswerResponse.questionCategory()), content, contentToken);
Answer newAnswer = saveAnswer(newQuestion, llmAnswerResponse.answer());
saveAnswerReferences(newAnswer, llmAnswerResponse.references());

return createQuestionResponse(newQuestion, newAnswer, llmAnswerResponse.references());
}

private static String getGuideAnswer(final List<AnswerReferenceResponse> references) {
return BASE_MESSAGE + references.stream()
.map(reference -> String.format("참고자료 %d : [%s](%s)",
references.indexOf(reference) + 1,
reference.title(),
reference.link()))
.collect(Collectors.joining("\n")) + IPHAK_OFFICE_NUMBER_GUIDE;
}

private boolean isInvalidAnswer(LLMAnswerResponse llmAnswerResponse) {
return llmAnswerResponse.answer() == null || llmAnswerResponse.answer().equals(INVALID_ANSWER);
}

private Question saveQuestion(QuestionType type, QuestionCategory category, String content, String contentToken) {
Question question = Question.of(content, contentToken, type, category);
return questionRepository.save(question);
}

private void saveAnswerReferences(Answer answer, List<AnswerReferenceResponse> referenceResponses) {
List<AnswerReference> answerReferences = referenceResponses.stream()
.map(reference -> AnswerReference.of(reference.title(), reference.link(), answer))
.toList();
answerReferenceRepository.saveAll(answerReferences);
}

private Answer saveAnswer(Question question, String content) {
Answer newAnswer = Answer.of(question, content);
return answerApiClient.saveAnswer(newAnswer);
}

private QuestionResponse createQuestionResponse(Question question, Answer answer,
List<AnswerReferenceResponse> answerReferenceResponses) {
AnswerResponse answerResponse = AnswerResponse.from(answer);
return QuestionResponse.of(question, answerResponse, answerReferenceResponses);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ public record AnswerResponse(
@Schema(description = "답변 DB 생성 및 업데이트 날짜", example = "생성일자: 2024-07-24T15:49:33, 마지막 DB 갱신일자: 2024-07-24T15:52:49")
String dateInformation
) {
private static final String INVALID_ANSWER = "해당 내용에 대한 정보는 존재하지 않습니다. 정확한 내용은 입학지원팀에 문의해주세요.";

public static AnswerResponse from(Answer answer) {
return AnswerResponse.builder()
.id(answer.getId())
Expand All @@ -30,10 +28,10 @@ public static AnswerResponse from(Answer answer) {
.build();
}

public static AnswerResponse valueOfInvalidAnswer() {
public static AnswerResponse valueOfInvalidAnswer(String content) {
return AnswerResponse.builder()
.id(null)
.content(INVALID_ANSWER)
.content(content)
.renewalYear(0)
.dateInformation(null)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public enum ErrorCode {

// 500 error
INTERNAL_ERROR_SIMILARITY(INTERNAL_SERVER_ERROR, "contentToken: %s, question: %s인 질문의 유사도를 검사하는 도중 오류가 발생했습니다."),
INTERNAL_ERROR_TEXT_SIMILARITY(INTERNAL_SERVER_ERROR, "질문의 유사도를 검사하는 도중 오류가 발생했습니다."),
INTERNAL_ERROR_WEBCLIENT(INTERNAL_SERVER_ERROR, "%s에서 서버 오류가 발생했습니다.");

private final HttpStatus status;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package mju.iphak.maru_egg.question.utils.NLP;
package mju.iphak.maru_egg.common.utils.NLP;

import org.apache.lucene.index.FieldInvertState;
import org.apache.lucene.search.similarities.TFIDFSimilarity;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package mju.iphak.maru_egg.question.utils.NLP;
package mju.iphak.maru_egg.common.utils.NLP;

import java.util.Arrays;
import java.util.HashMap;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package mju.iphak.maru_egg.question.utils;
package mju.iphak.maru_egg.common.utils;

import java.util.List;
import java.util.stream.Collectors;
Expand Down
Loading
Loading