-
Notifications
You must be signed in to change notification settings - Fork 3
[feature] 지원자의 지원서를 요약해서 메모에 추가한다. #809
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
seongwon030
merged 17 commits into
develop/be
from
feature/#805-summary-application-content-MOA-301
Nov 9, 2025
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
5cd1ccc
feat: rabbitmq config 파일 추가
lepitaaar b14178a
chore: AQMP dependency 추가
lepitaaar 1d250c3
refactor: 파일 포맷팅
lepitaaar e051bec
feat: rabbitmq consumer & publisher 추가
lepitaaar ab294e1
feat: 지원서 요약 메시지 객체 추가
lepitaaar 1f1aa40
feat: 지원서 저장시 요약 queue에 추가
lepitaaar 41d1b89
feat: AI 서버로 요청하기위한 restTemplate 추가
lepitaaar 5af7618
feat: AI요청과 응답을 위한 dto 추가
lepitaaar 5b6dda3
feat: gemma3 서버로 모델 요청 후 동기로 요약 응답 받게 변경
lepitaaar 9e2561d
Merge branch 'develop/be' into feature/#805-summary-application-conte…
lepitaaar e13df36
refactor: prompt 수정
lepitaaar f999653
Merge remote-tracking branch 'origin/feature/#805-summary-application…
lepitaaar c2b9c6e
fix: import 추가
lepitaaar d3c9891
refactor: rabbitmq config 설정에 queue, binding, exchange 셋업.
lepitaaar bf8539a
refactor: RabbitTemplate 기본 exchange, routingkey 연결
lepitaaar 98af7d5
refactor: dlq, dlx 추가 3번 재시도시 dlq로 이동
lepitaaar 8ae47c0
feat: add transaction
lepitaaar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
This file contains hidden or 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
7 changes: 7 additions & 0 deletions
7
backend/src/main/java/moadong/club/payload/dto/ApplicantSummaryMessage.java
This file contains hidden or 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,7 @@ | ||
| package moadong.club.payload.dto; | ||
|
|
||
| public record ApplicantSummaryMessage( | ||
| String applicationFormId, | ||
| String applicantId | ||
| ) { | ||
| } |
This file contains hidden or 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
This file contains hidden or 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
63 changes: 63 additions & 0 deletions
63
backend/src/main/java/moadong/club/summary/ApplicantIdMessageConsumer.java
This file contains hidden or 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,63 @@ | ||
| package moadong.club.summary; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import moadong.club.entity.ClubApplicant; | ||
| import moadong.club.entity.ClubApplicationForm; | ||
| import moadong.club.entity.ClubApplicationFormQuestion; | ||
| import moadong.club.entity.ClubQuestionAnswer; | ||
| import moadong.club.payload.dto.ApplicantSummaryMessage; | ||
| import moadong.club.repository.ClubApplicantsRepository; | ||
| import moadong.club.repository.ClubApplicationFormsRepository; | ||
| import moadong.gemma.dto.AIResponse; | ||
| import moadong.gemma.service.GemmaService; | ||
| import moadong.global.exception.ErrorCode; | ||
| import moadong.global.exception.RestApiException; | ||
| import moadong.global.util.AESCipher; | ||
| import org.springframework.amqp.rabbit.annotation.RabbitListener; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| import java.util.Map; | ||
| import java.util.function.Function; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| @Component | ||
| @Slf4j | ||
| @RequiredArgsConstructor | ||
| public class ApplicantIdMessageConsumer { | ||
|
|
||
| private final ClubApplicantsRepository clubApplicantsRepository; | ||
| private final ClubApplicationFormsRepository clubApplicationFormsRepository; | ||
| private final AESCipher cipher; | ||
| private final GemmaService gemmaService; | ||
| private final ApplicantIdMessagePublisher publisher; | ||
|
|
||
| @RabbitListener(queues = "${rabbitmq.summary.queue}", concurrency = "1") | ||
| public void receiveMessage(ApplicantSummaryMessage message) { | ||
| StringBuilder prompt = new StringBuilder("너는 전문 면접관이다. 다음은 동아리 application의 질문과 지원자의 답변이다. 질문은 무시하고, 지원자의 '답변'에서 핵심만 뽑아라. summarize max length 100 response format: '{response: summarize}'. application: "); | ||
lepitaaar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ClubApplicant clubApplicant = clubApplicantsRepository.findById(message.applicantId()).orElseThrow(() -> new RestApiException(ErrorCode.APPLICANT_NOT_FOUND)); | ||
| ClubApplicationForm clubApplicationForm = clubApplicationFormsRepository.findById(message.applicationFormId()).orElseThrow(() -> new RestApiException(ErrorCode.APPLICATION_NOT_FOUND)); | ||
| Map<Long, ClubApplicationFormQuestion> questionMap = clubApplicationForm.getQuestions().stream() | ||
| .collect(Collectors.toMap(ClubApplicationFormQuestion::getId, Function.identity())); | ||
|
|
||
| try { | ||
| for (ClubQuestionAnswer answer : clubApplicant.getAnswers()) { | ||
| String decryptedValue = cipher.decrypt(answer.getValue()); | ||
| prompt.append(answer.getId()).append(". ") | ||
| .append(questionMap.get(answer.getId()).getTitle()) | ||
| .append(": ") | ||
| .append(decryptedValue); | ||
| prompt.append(","); | ||
| } | ||
lepitaaar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } catch (Exception e) { | ||
| log.error("AES_CIPHER_ERROR", e); | ||
| throw new RestApiException(ErrorCode.AES_CIPHER_ERROR); | ||
| } | ||
|
|
||
| AIResponse summarizeContent = gemmaService.getSummarizeContent(prompt.toString()); | ||
|
|
||
| clubApplicant.updateMemo(summarizeContent.response()); | ||
|
|
||
| clubApplicantsRepository.save(clubApplicant); | ||
| } | ||
lepitaaar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
19 changes: 19 additions & 0 deletions
19
backend/src/main/java/moadong/club/summary/ApplicantIdMessagePublisher.java
This file contains hidden or 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,19 @@ | ||
| package moadong.club.summary; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
| import moadong.club.payload.dto.ApplicantSummaryMessage; | ||
| import org.springframework.amqp.rabbit.core.RabbitTemplate; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| @Component | ||
| @RequiredArgsConstructor | ||
| public class ApplicantIdMessagePublisher { | ||
|
|
||
| private final RabbitTemplate applicantIdTemplate; | ||
|
|
||
| public void addApplicantIdToQueue(String applicationFormId, String applicantId) { | ||
| ApplicantSummaryMessage message = new ApplicantSummaryMessage(applicationFormId, applicantId); | ||
|
|
||
| applicantIdTemplate.convertAndSend(message); | ||
| } | ||
lepitaaar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
This file contains hidden or 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 moadong.gemma.dto; | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||
|
|
||
| public record AIRequest( | ||
| String model, | ||
| String prompt, | ||
| String format, | ||
| boolean stream, | ||
| @JsonProperty("keep_alive") int keepAlive | ||
| ) { | ||
| } |
This file contains hidden or 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,6 @@ | ||
| package moadong.gemma.dto; | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||
|
|
||
| public record AIResponse(@JsonProperty("response") String response) { | ||
| } |
40 changes: 40 additions & 0 deletions
40
backend/src/main/java/moadong/gemma/service/GemmaService.java
This file contains hidden or 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,40 @@ | ||
| package moadong.gemma.service; | ||
|
|
||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import moadong.gemma.dto.AIRequest; | ||
| import moadong.gemma.dto.AIResponse; | ||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.stereotype.Service; | ||
| import org.springframework.web.client.RestTemplate; | ||
|
|
||
| @Service | ||
| @RequiredArgsConstructor | ||
| @Slf4j | ||
| public class GemmaService { | ||
|
|
||
| private final RestTemplate restTemplate; | ||
| private final ObjectMapper objectMapper; | ||
|
|
||
| @Value("${gemma.server.host}") | ||
| private String gemmaServerHost; | ||
|
|
||
| @Value("${gemma.server.port}") | ||
| private String gemmaServerPort; | ||
|
|
||
| public AIResponse getSummarizeContent(String prompt) { | ||
| try { | ||
| String gemmaServerUrl = "http://" + gemmaServerHost + ":" + gemmaServerPort + "/api/generate"; | ||
| AIRequest request = new AIRequest("gemma3:4b", prompt, "json", false, -1); | ||
| AIResponse response = restTemplate.postForObject(gemmaServerUrl, request, AIResponse.class); | ||
| if (response != null) { | ||
| return objectMapper.readValue(response.response(), AIResponse.class); | ||
| } | ||
| } catch (Exception e) { | ||
| log.error("Json Serialize Error: ", e); | ||
| return null; | ||
| } | ||
| return null; | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
앞으론 if 뒤에 띄어쓰기 잘 하겠습니다,,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
꿀팁 한개 드리면 option + command + l 누르면 intellij 자동으로 포맷팅해줍니다 ㅇㅁㅇ