Skip to content

Commit f907011

Browse files
authored
Merge pull request #46 from HSU-Talky/dev
Merge dev into main
2 parents 69336ff + 386abcc commit f907011

23 files changed

Lines changed: 338 additions & 254 deletions

src/main/java/com/example/talky/adapter/ai/AiServerClient.java

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/main/java/com/example/talky/adapter/ai/AiServerClientImpl.java

Lines changed: 0 additions & 86 deletions
This file was deleted.

src/main/java/com/example/talky/domain/auth/entity/NormalUser.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ public class NormalUser extends User{
4343
@JoinColumn(name = "guardian_id")
4444
private Guardians guardians;
4545

46+
@Column(name = "guardian_name")
47+
private String guardianName;
48+
49+
@Column(name = "guardian_phone")
50+
private String guardianPhone;
51+
4652
private boolean isAcceptedLocationInfo;
4753

4854
@Override
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package com.example.talky.domain.recommendation.service;
22

3-
import com.example.talky.domain.recommendation.web.dto.GetContextReq;
43
import com.example.talky.global.ai.dto.AiRcmdRes;
5-
import com.example.talky.global.response.SuccessResponse;
6-
import org.springframework.http.ResponseEntity;
4+
import com.fasterxml.jackson.core.JsonProcessingException;
5+
import org.springframework.web.multipart.MultipartFile;
76

87
public interface RcmdService {
9-
AiRcmdRes getAiRcmd(GetContextReq req, Long normalId);
8+
9+
AiRcmdRes getAiRcmd(MultipartFile file, String metadataJson, Long normalId) throws JsonProcessingException;
1010
}

src/main/java/com/example/talky/domain/recommendation/service/RcmdServiceImpl.java

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
11
package com.example.talky.domain.recommendation.service;
22

3-
import com.example.talky.adapter.ai.AiServerClient;
4-
import com.example.talky.adapter.ai.response.RecommendationResponse;
3+
import com.example.talky.global.ai.FastApiClient;
54
import com.example.talky.domain.auth.entity.NormalUser;
65
import com.example.talky.domain.auth.exception.UserNotFoundException;
76
import com.example.talky.domain.auth.repository.UserRepository;
87
import com.example.talky.domain.favorites.entity.Favorite;
98
import com.example.talky.domain.favorites.exception.FavoriteNorFoundException;
109
import com.example.talky.domain.favorites.repository.FavoriteRepository;
11-
import com.example.talky.domain.recommendation.entity.Speech;
1210
import com.example.talky.domain.recommendation.entity.Conversation;
11+
import com.example.talky.domain.recommendation.entity.Speech;
1312
import com.example.talky.domain.recommendation.repository.ConversationRepository;
1413
import com.example.talky.domain.recommendation.repository.SpeechRepository;
1514
import com.example.talky.domain.recommendation.web.dto.GetContextReq;
16-
import com.example.talky.global.ai.dto.AiRcmdRes;
1715
import com.example.talky.global.ai.dto.ToAiReq;
18-
import com.example.talky.global.response.SuccessResponse;
16+
import com.example.talky.global.ai.dto.AiRcmdRes;
17+
import com.fasterxml.jackson.core.JsonProcessingException;
18+
import com.fasterxml.jackson.databind.ObjectMapper;
1919
import jakarta.transaction.Transactional;
2020
import lombok.RequiredArgsConstructor;
2121
import lombok.extern.slf4j.Slf4j;
22-
import org.springframework.http.HttpStatus;
23-
import org.springframework.http.ResponseEntity;
2422
import org.springframework.stereotype.Service;
23+
import org.springframework.web.multipart.MultipartFile;
2524

2625
import java.util.ArrayList;
2726
import java.util.List;
@@ -32,15 +31,18 @@
3231
@RequiredArgsConstructor
3332
public class RcmdServiceImpl implements RcmdService {
3433

35-
private final AiServerClient aiServerClient;
34+
private final FastApiClient fastApiClient;
3635
private final UserRepository userRepository;
3736
private final FavoriteRepository favoriteRepository;
3837
private final ConversationRepository conversationRepository; // AI 추적용
3938
private final SpeechRepository speechRepository; // 별도 API용
39+
private final ObjectMapper objectMapper;
4040

4141
@Transactional
4242
@Override
43-
public AiRcmdRes getAiRcmd(GetContextReq req, Long normalId) {
43+
public AiRcmdRes getAiRcmd(MultipartFile file, String metadataJson, Long normalId) throws JsonProcessingException {
44+
// 메타데이터 JSON 파싱
45+
GetContextReq req = objectMapper.readValue(metadataJson, GetContextReq.class);
4446
String choose = req.getChoose();
4547

4648
// choose == null -> drop all record(새로운 user 대화 이력 테이블 사용)
@@ -71,11 +73,9 @@ public AiRcmdRes getAiRcmd(GetContextReq req, Long normalId) {
7173

7274
if(req.getChoose() != null && req.getSttMessage() != null) {
7375
tracking.addFirst(req.getChoose());
74-
tracking.addFirst(req.getSttMessage());
75-
} else if (req.getSttMessage() != null) {
76-
tracking.add(req.getSttMessage());
7776
}
7877

78+
// 변경된 대화 기록 저장
7979
conversation.modify(tracking);
8080

8181
// Context 3 - 데이터베이스에 저장
@@ -97,32 +97,30 @@ public AiRcmdRes getAiRcmd(GetContextReq req, Long normalId) {
9797
.map(Favorite::getSentence)
9898
.toList();
9999

100-
// 이전 대화 기록이 없을 시 NPE 예외 던지는 중임
101-
List<String> conversations = conversation.getConversations();
100+
// AI 서버로 보낼 요청 객체 (ToAiReq) 생성
101+
// sttMessage는 현재 턴에서는 AI 서버가 파일로부터 생성하므로 null로 설정
102+
ToAiReq toAiReq = ToAiReq.builder()
103+
.keywords(req.getKeywords())
104+
.context(req.getContext())
105+
.choose(choose)
106+
.conversation(conversation.getConversations())
107+
.favorites(favorites)
108+
.sttMessage(null)
109+
.build();
110+
111+
// AI 서버 호출
112+
AiRcmdRes response = fastApiClient.getAiRecommendation(toAiReq, file);
113+
String category = response.getCategory();
114+
String sttResultFromAi = response.getSttMessage(); // AI 서버로부터 STT 결과 수신
102115

103-
ToAiReq toAiReq;
104-
log.info("choose={}, conversations={}", choose, conversations);
105-
if(choose == null && conversations == null) {
106-
//log.info("잘못 들어옴");
107-
toAiReq = ToAiReq.builder()
108-
.keywords(req.getKeywords())
109-
.context(req.getContext())
110-
.build();
116+
// AI 서버에서 받은 STT 결과를 다음 턴의 컨텍스트를 위해 대화 기록에 추가
117+
if (sttResultFromAi != null) {
118+
tracking.add(sttResultFromAi);
119+
conversation.modify(tracking);
120+
conversationRepository.saveAndFlush(conversation);
111121
}
112-
else {
113-
//log.info("잘 들어왓음");
114-
toAiReq = ToAiReq.builder()
115-
.keywords(req.getKeywords())
116-
.context(req.getContext())
117-
.conversations(conversations)
118-
.favorites(favorites)
119-
.sttMessage(req.getSttMessage())
120-
.build();
121-
}
122-
log.info(toAiReq.toString());
123-
AiRcmdRes response = aiServerClient.getAiRcmdSentences(toAiReq);
124-
// 카테고리 획득
125-
String category = response.getCategory();
122+
123+
// 음성 기록 저장 (통계용)
126124
speechRepository.save(Speech.builder()
127125
.normalUser((NormalUser) userRepository.findById(normalId)
128126
.orElseThrow(UserNotFoundException::new))
@@ -133,6 +131,7 @@ public AiRcmdRes getAiRcmd(GetContextReq req, Long normalId) {
133131
}
134132

135133
private boolean favoriteIsPresent(Long normalId, String choose) {
134+
if (choose == null) return false;
136135
return favoriteRepository.findByNormalUserIdAndSentence(normalId, choose).isPresent();
137136
}
138137
}

src/main/java/com/example/talky/domain/recommendation/web/controller/RcmdController.java

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
package com.example.talky.domain.recommendation.web.controller;
22

33
import com.example.talky.domain.recommendation.service.RcmdService;
4-
import com.example.talky.domain.recommendation.web.dto.GetContextReq;
54
import com.example.talky.global.ai.dto.AiRcmdRes;
65
import com.example.talky.global.response.SuccessResponse;
76
import com.example.talky.global.security.CustomUserDetails;
7+
import com.fasterxml.jackson.core.JsonProcessingException;
8+
import com.fasterxml.jackson.databind.ObjectMapper;
89
import lombok.RequiredArgsConstructor;
910
import lombok.extern.slf4j.Slf4j;
1011
import org.springframework.http.HttpStatus;
1112
import org.springframework.http.ResponseEntity;
12-
import org.springframework.http.converter.HttpMessageNotReadableException;
1313
import org.springframework.security.core.annotation.AuthenticationPrincipal;
14-
import org.springframework.validation.annotation.Validated;
15-
import org.springframework.web.bind.annotation.PostMapping;
16-
import org.springframework.web.bind.annotation.RequestBody;
17-
import org.springframework.web.bind.annotation.RequestMapping;
18-
import org.springframework.web.bind.annotation.RestController;
14+
import org.springframework.web.bind.annotation.*;
15+
import org.springframework.web.multipart.MultipartFile;
1916

2017
@Slf4j
2118
@RestController
@@ -27,13 +24,15 @@ public class RcmdController {
2724

2825
@PostMapping("/context")
2926
public ResponseEntity<SuccessResponse<?>> getAiSentence(
30-
@Validated @RequestBody GetContextReq req,
31-
@AuthenticationPrincipal CustomUserDetails userDetails) {
32-
log.info(req.toString());
27+
@RequestParam(value = "file", required = false) MultipartFile file, // 사용자의 음성 파일 (MP3 등)
28+
@RequestParam("metadata") String metadataJson, // 메타데이터 (JSON 문자열)
29+
@AuthenticationPrincipal CustomUserDetails userDetails) throws JsonProcessingException {
30+
3331
Long normalId = userDetails.getNormalUser().getId();
3432

35-
// 서비스 계층 호출
36-
AiRcmdRes response = rcmdService.getAiRcmd(req, normalId);
33+
// 서비스 계층 호출: 클라이언트로부터 받은 파일과 메타데이터를 서비스로 전달
34+
// sttMessage는 더 이상 클라이언트에서 직접 받지 않음 (AI 서버에서 처리)
35+
AiRcmdRes response = rcmdService.getAiRcmd(file, metadataJson, normalId);
3736
return ResponseEntity.status(HttpStatus.OK).body(SuccessResponse.ok(response));
3837
}
3938

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,15 @@
11
package com.example.talky.domain.recommendation.web.dto;
22

3-
import jakarta.validation.constraints.NotBlank;
4-
import jakarta.validation.constraints.NotEmpty;
5-
import lombok.AllArgsConstructor;
63
import lombok.Getter;
7-
import lombok.ToString;
4+
import lombok.NoArgsConstructor;
85

96
import java.util.List;
107

118
@Getter
12-
@ToString
13-
@AllArgsConstructor
9+
@NoArgsConstructor
1410
public class GetContextReq {
15-
// @NotEmpty(message = "장소는 필수 전달값입니다.")
16-
// private String place;
17-
18-
@NotEmpty(message = "키워드는 필수 입력값입니다.")
1911
private List<String> keywords;
20-
2112
private String context;
2213
private String choose;
23-
24-
private List<String> conversations;
25-
private String sttMessage;
14+
private String sttMessage; // 사용자가 음성으로 입력한 mp3 파일을 서버에서 텍스트로 변환(STT)한 결과값. 추천 문장 생성에 활용됨.
2615
}

src/main/java/com/example/talky/domain/stt/service/SttService.java

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/main/java/com/example/talky/domain/stt/service/SttServiceImpl.java

Lines changed: 0 additions & 21 deletions
This file was deleted.

src/main/java/com/example/talky/domain/stt/web/controller/SttController.java

Lines changed: 0 additions & 27 deletions
This file was deleted.

0 commit comments

Comments
 (0)