diff --git a/src/main/java/com/api/sss/model/controller/ModelController.java b/src/main/java/com/api/sss/model/controller/ModelController.java index ad2bf9f..6c4e338 100644 --- a/src/main/java/com/api/sss/model/controller/ModelController.java +++ b/src/main/java/com/api/sss/model/controller/ModelController.java @@ -1,5 +1,6 @@ package com.api.sss.model.controller; +import com.api.sss.model.dto.request.ChatPredictRequest; import com.api.sss.model.dto.request.NewsRequest; import com.api.sss.model.dto.response.NewsResponse; import com.api.sss.model.service.ModelService; @@ -14,6 +15,7 @@ import com.api.sss.config.response.dto.SuccessStatus; import com.api.sss.model.dto.request.ChatAskRequest; import com.api.sss.model.dto.response.ChatAskResponse; +import com.api.sss.model.dto.response.ChatPredictResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -31,6 +33,30 @@ public class ModelController { RestTemplate restTemplate = new RestTemplate(); private final ModelService modelService; + + @Operation( + summary = "코인 시세 예측 API", + description = "코인종목 명을 입력받아 FastAPI 서비스에 전달하고 답변을 받아옵니다." + ) + @ApiResponse(responseCode = "200", description = "답변 수신 성공") + @ApiResponse( + responseCode = "500", + description = "FastAPI 서비스 오류 또는 통신 실패", + content = @Content(mediaType = "application/json", examples = @ExampleObject(value = """ + { + "code": 500, + "message": "FastAPI와의 통신 중 오류가 발생했습니다." + } + """)) + ) + @PostMapping(path = "/chat/predict") + public CustomResponse predictCoin( + @RequestBody ChatPredictRequest request) { + ChatPredictResponse response = modelService.predictCoin(request); + return CustomResponse.success(response, SuccessStatus.SUCCESS); + } + + @Operation( summary = "질문 전송 API", description = "질문을 FastAPI 서비스에 전달하고 답변을 받아옵니다." diff --git a/src/main/java/com/api/sss/model/dto/request/ChatPredictRequest.java b/src/main/java/com/api/sss/model/dto/request/ChatPredictRequest.java new file mode 100644 index 0000000..1602d5e --- /dev/null +++ b/src/main/java/com/api/sss/model/dto/request/ChatPredictRequest.java @@ -0,0 +1,10 @@ +package com.api.sss.model.dto.request; + +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; + +@Getter +public class ChatPredictRequest { + @NotBlank(message = "종목명은 비어 있을 수 없습니다.") + private String coinName; +} diff --git a/src/main/java/com/api/sss/stt/dto/response/ChatPredictResponse.java b/src/main/java/com/api/sss/model/dto/response/ChatPredictResponse.java similarity index 82% rename from src/main/java/com/api/sss/stt/dto/response/ChatPredictResponse.java rename to src/main/java/com/api/sss/model/dto/response/ChatPredictResponse.java index c21ce81..1209146 100644 --- a/src/main/java/com/api/sss/stt/dto/response/ChatPredictResponse.java +++ b/src/main/java/com/api/sss/model/dto/response/ChatPredictResponse.java @@ -1,4 +1,4 @@ -package com.api.sss.stt.dto.response; +package com.api.sss.model.dto.response; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/src/main/java/com/api/sss/model/service/ModelService.java b/src/main/java/com/api/sss/model/service/ModelService.java index ddf9cc9..1c06dc7 100644 --- a/src/main/java/com/api/sss/model/service/ModelService.java +++ b/src/main/java/com/api/sss/model/service/ModelService.java @@ -15,8 +15,10 @@ import com.api.sss.config.exception.CustomException; import com.api.sss.config.exception.ErrorCode; import com.api.sss.model.dto.request.ChatAskRequest; +import com.api.sss.model.dto.request.ChatPredictRequest; import com.api.sss.model.dto.request.NewsRequest; import com.api.sss.model.dto.response.ChatAskResponse; +import com.api.sss.model.dto.response.ChatPredictResponse; import com.api.sss.model.dto.response.NewsResponse; @Service @@ -25,6 +27,30 @@ public class ModelService { private final RestTemplate restTemplate = new RestTemplate(); private final String FASTAPI_URL = "http://203.153.147.12:5050"; + + public ChatPredictResponse predictCoin(ChatPredictRequest request) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity entity = new HttpEntity<>(request, headers); + + try { + // TODO: return response.getBody(); + // ResponseEntity response = restTemplate.exchange( + // FASTAPI_URL + "/chat/predict", + // HttpMethod.POST, + // entity, + // String.class + // ); + return ChatPredictResponse.builder() + .prediction(request.getCoinName()) + .build(); + } catch (Exception e) { + throw new CustomException(ErrorCode.FASTAPI_COMMUNICATION_ERROR); + } + } + + public List cardNews(NewsRequest request) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); @@ -63,25 +89,5 @@ public ChatAskResponse askQuestion(ChatAskRequest request) { } } - public String predictCoin(String coinName) { - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - - Map body = new HashMap<>(); - body.put("coinName", coinName); - HttpEntity> entity = new HttpEntity<>(body, headers); - try { - // TODO: return response.getBody(); - // ResponseEntity response = restTemplate.exchange( - // FASTAPI_URL + "/chat/predict", - // HttpMethod.POST, - // entity, - // String.class - // ); - return coinName; - } catch (Exception e) { - throw new CustomException(ErrorCode.FASTAPI_COMMUNICATION_ERROR); - } - } } diff --git a/src/main/java/com/api/sss/stt/controller/SttController.java b/src/main/java/com/api/sss/stt/controller/SttController.java deleted file mode 100644 index 91386cb..0000000 --- a/src/main/java/com/api/sss/stt/controller/SttController.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.api.sss.stt.controller; - -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.multipart.MultipartFile; - -import com.api.sss.config.response.dto.CustomResponse; -import com.api.sss.config.response.dto.SuccessStatus; -import com.api.sss.stt.dto.response.ChatPredictResponse; -import com.api.sss.stt.service.SttService; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.ExampleObject; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import lombok.RequiredArgsConstructor; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1") -public class SttController { - - private final SttService sttService; - - @Operation( - summary = "코인 시세 예측 API", - description = "STT로 코인종목 명을 입력받아 FastAPI 서비스에 전달하고 답변을 받아옵니다." - ) - @ApiResponse(responseCode = "200", description = "답변 수신 성공") - @ApiResponse( - responseCode = "500", - description = "FastAPI 서비스 오류 또는 통신 실패", - content = @Content(mediaType = "application/json", examples = @ExampleObject(value = """ - { - "code": 500, - "message": "FastAPI와의 통신 중 오류가 발생했습니다." - } - """)) - // 종목명 인식 실패했을 시 response 추가 필요 - ) - @PostMapping(path = "/chat/predict", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - public CustomResponse predictCoin( - @Parameter( - description = "업로드할 44100Hz mp3 음성 파일", - content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA_VALUE) - ) - @RequestParam("file") MultipartFile file) { - ChatPredictResponse response = sttService.predictCoin(file); - return CustomResponse.success(response, SuccessStatus.SUCCESS); - } - -} diff --git a/src/main/java/com/api/sss/stt/service/SttService.java b/src/main/java/com/api/sss/stt/service/SttService.java deleted file mode 100644 index 36169b7..0000000 --- a/src/main/java/com/api/sss/stt/service/SttService.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.api.sss.stt.service; - -import java.io.IOException; -import java.util.List; - -import org.springframework.stereotype.Service; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.multipart.MultipartFile; - -import com.api.sss.config.exception.CustomException; -import com.api.sss.config.exception.ErrorCode; -import com.api.sss.model.service.ModelService; -import com.api.sss.stt.dto.response.ChatPredictResponse; -import com.google.cloud.speech.v1.RecognitionAudio; -import com.google.cloud.speech.v1.RecognitionConfig; -import com.google.cloud.speech.v1.RecognizeResponse; -import com.google.cloud.speech.v1.SpeechClient; -import com.google.cloud.speech.v1.SpeechRecognitionAlternative; -import com.google.cloud.speech.v1.SpeechRecognitionResult; -import com.google.protobuf.ByteString; - -import lombok.RequiredArgsConstructor; - -@Service -@RequiredArgsConstructor -public class SttService { - - private final SpeechClient speechClient; - private final ModelService modelService; - - public ChatPredictResponse predictCoin(@RequestParam("file") MultipartFile file) { - String coinName = transcribe(file); - - return ChatPredictResponse.builder() - .prediction(modelService.predictCoin(coinName)) - .build(); - } - - public String transcribe(MultipartFile file) { - if (file.isEmpty()) { - throw new CustomException(ErrorCode.FILE_NOT_FOUND); - } - - try { - ByteString audioBytes = ByteString.copyFrom(file.getBytes()); - - RecognitionAudio audio = RecognitionAudio.newBuilder() - .setContent(audioBytes) - .build(); - - RecognitionConfig config = RecognitionConfig.newBuilder() - .setEncoding(RecognitionConfig.AudioEncoding.MP3) - .setSampleRateHertz(44100) - .setLanguageCode("ko-KR") - .build(); - - RecognizeResponse response = speechClient.recognize(config, audio); - - List results = response.getResultsList(); - StringBuilder transcription = new StringBuilder(); - - for (SpeechRecognitionResult result : results) { - SpeechRecognitionAlternative alternative = result.getAlternativesList().get(0); - transcription.append(alternative.getTranscript()); - } - - return transcription.toString(); - } catch (IOException e) { - throw new CustomException(ErrorCode.FILE_NOT_FOUND); - } - - } - -}