Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/main/java/com/api/sss/config/exception/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ public enum ErrorCode {
UNSUPPORTED_TOKEN(401, "지원하지 않는 토큰입니다."),
FASTAPI_COMMUNICATION_ERROR(500, "FastAPI와의 통신 중 오류가 발생했습니다."),
FILE_NOT_FOUND(400, "입력 파일이 없습니다."),
FILE_READ_ERROR(500, "서버에서 파일을 읽어들이는 중 오류가 발생했습니다.");
FILE_READ_ERROR(500, "서버에서 파일을 읽어들이는 중 오류가 발생했습니다."),
TICKER_NOT_FOUND(400, "해당 코인을 찾을 수 없습니다");

private final int code;
private final String message;
Expand Down
55 changes: 32 additions & 23 deletions src/main/java/com/api/sss/model/controller/ModelController.java
Original file line number Diff line number Diff line change
@@ -1,9 +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;
import java.util.List;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -14,31 +11,44 @@
import com.api.sss.config.response.dto.CustomResponse;
import com.api.sss.config.response.dto.SuccessStatus;
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;
import com.api.sss.model.service.CoinTickerService;
import com.api.sss.model.service.ModelService;

import io.swagger.v3.oas.annotations.Operation;
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;

import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1")
public class ModelController {

RestTemplate restTemplate = new RestTemplate();
private final ModelService modelService;

private final CoinTickerService coinTickerService;

@Operation(
summary = "코인 시세 예측 API",
description = "코인종목 명을 입력받아 FastAPI 서비스에 전달하고 답변을 받아옵니다."
)
@ApiResponse(responseCode = "200", description = "답변 수신 성공")
@ApiResponse(
responseCode = "400",
description = "코인 종목-ticker 간 매칭 실패",
content = @Content(mediaType = "application/json", examples = @ExampleObject(value = """
{
"code": 400,
"message": "해당 코인을 찾을 수 없습니다."
}
"""))
)
@ApiResponse(
responseCode = "500",
description = "FastAPI 서비스 오류 또는 통신 실패",
Expand All @@ -56,7 +66,6 @@ public CustomResponse<ChatPredictResponse> predictCoin(
return CustomResponse.success(response, SuccessStatus.SUCCESS);
}


@Operation(
summary = "질문 전송 API",
description = "질문을 FastAPI 서비스에 전달하고 답변을 받아옵니다."
Expand All @@ -66,11 +75,11 @@ public CustomResponse<ChatPredictResponse> predictCoin(
responseCode = "500",
description = "FastAPI 서비스 오류 또는 통신 실패",
content = @Content(mediaType = "application/json", examples = @ExampleObject(value = """
{
"code": 500,
"message": "FastAPI와의 통신 중 오류가 발생했습니다."
}
"""))
{
"code": 500,
"message": "FastAPI와의 통신 중 오류가 발생했습니다."
}
"""))
)
@PostMapping("/chat/ask")
public CustomResponse<ChatAskResponse> askQuestion(@RequestBody ChatAskRequest request) {
Expand All @@ -79,19 +88,19 @@ public CustomResponse<ChatAskResponse> askQuestion(@RequestBody ChatAskRequest r
}

@Operation(
summary = "카드뉴스 API",
description = "키워드를 입력하면 관련 뉴스 URL을 반환합니다."
summary = "카드뉴스 API",
description = "키워드를 입력하면 관련 뉴스 URL을 반환합니다."
)
@ApiResponse(responseCode = "200", description = "답변 수신 성공")
@ApiResponse(
responseCode = "500",
description = "FastAPI 서비스 오류 또는 통신 실패",
content = @Content(mediaType = "application/json", examples = @ExampleObject(value = """
{
"code": 500,
"message": "FastAPI와의 통신 중 오류가 발생했습니다."
}
"""))
responseCode = "500",
description = "FastAPI 서비스 오류 또는 통신 실패",
content = @Content(mediaType = "application/json", examples = @ExampleObject(value = """
{
"code": 500,
"message": "FastAPI와의 통신 중 오류가 발생했습니다."
}
"""))
)
@PostMapping("/news")
public CustomResponse<List<NewsResponse.Result>> getNews(@RequestBody NewsRequest request) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.api.sss.model.dto.request;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
@AllArgsConstructor
public class ChatPredictTickerRequest {
private String coinTicker;
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
package com.api.sss.model.dto.response;

import java.time.LocalDateTime;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Builder
@AllArgsConstructor
public class ChatPredictResponse {
private String coinTicker;
private String coinName;
private String prediction;
private float prob;
private LocalDateTime timestamp;
}
72 changes: 72 additions & 0 deletions src/main/java/com/api/sss/model/service/CoinTickerService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.api.sss.model.service;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.api.sss.config.exception.CustomException;
import com.api.sss.config.exception.ErrorCode;

import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class CoinTickerService {

private final RestTemplate restTemplate = new RestTemplate();
private final Map<String, String> tickerMap = new ConcurrentHashMap<>();

@PostConstruct
public void getTickerMap() {
String UPBIT_URL = "https://api.upbit.com/v1/market/all?isDetails=false";

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Void> entity = new HttpEntity<>(headers);

ResponseEntity<UpbitMarket[]> response = restTemplate.exchange(
UPBIT_URL,
HttpMethod.GET,
entity,
UpbitMarket[].class
);

UpbitMarket[] body = response.getBody();
if (body == null) {
return;
}

List<UpbitMarket> data = Arrays.asList(body);

for (UpbitMarket coin : data) {
String market = coin.getMarket();
String coinName = coin.getCoinName();
if (market != null && coinName != null && market.contains("KRW")) {
tickerMap.put(coinName, market);
}
}

tickerMap.put("엑스알피", "KRW-XRP");
tickerMap.put("리플", "KRW-XRP");
}

public String getCoinTicker(String coinName) {
if (tickerMap.get(coinName) != null) {
return tickerMap.get(coinName);
}
throw new CustomException(ErrorCode.TICKER_NOT_FOUND);
}

}


41 changes: 25 additions & 16 deletions src/main/java/com/api/sss/model/service/ModelService.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.api.sss.model.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
Expand All @@ -16,6 +14,7 @@
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.ChatPredictTickerRequest;
import com.api.sss.model.dto.request.NewsRequest;
import com.api.sss.model.dto.response.ChatAskResponse;
import com.api.sss.model.dto.response.ChatPredictResponse;
Expand All @@ -25,32 +24,43 @@
public class ModelService {

private final RestTemplate restTemplate = new RestTemplate();
private final String FASTAPI_URL = "http://203.153.147.12:5050";
// private final String FASTAPI_URL = "http://203.153.147.12:5050";
private final String FASTAPI_URL = "http://localhost:5050";
private final CoinTickerService coinTickerService;

public ModelService(CoinTickerService coinTickerService) {
this.coinTickerService = coinTickerService;
}

public ChatPredictResponse predictCoin(ChatPredictRequest request) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<ChatPredictRequest> entity = new HttpEntity<>(request, headers);
String coinTicker = coinTickerService.getCoinTicker(request.getCoinName());
ChatPredictTickerRequest chatPredictTickerRequest = ChatPredictTickerRequest.builder()
.coinTicker(coinTicker)
.build();
HttpEntity<ChatPredictTickerRequest> entity = new HttpEntity<>(chatPredictTickerRequest, headers);

try {
// TODO: return response.getBody();
// ResponseEntity<String> response = restTemplate.exchange(
// FASTAPI_URL + "/chat/predict",
// HttpMethod.POST,
// entity,
// String.class
// );
return ChatPredictResponse.builder()
.prediction(request.getCoinName())
.build();
ResponseEntity<ChatPredictResponse> response = restTemplate.exchange(
FASTAPI_URL + "/chat/predict",
HttpMethod.POST,
entity,
ChatPredictResponse.class
);

ChatPredictResponse body = response.getBody();
if (body != null) {
body.setCoinName(request.getCoinName());
}

return body;
} catch (Exception e) {
throw new CustomException(ErrorCode.FASTAPI_COMMUNICATION_ERROR);
}
}


public List<NewsResponse.Result> cardNews(NewsRequest request) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
Expand Down Expand Up @@ -89,5 +99,4 @@ public ChatAskResponse askQuestion(ChatAskRequest request) {
}
}


}
15 changes: 15 additions & 0 deletions src/main/java/com/api/sss/model/service/UpbitMarket.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.api.sss.model.service;

import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.Getter;

@Getter
public class UpbitMarket {

@JsonProperty("market")
private String market;

@JsonProperty("korean_name")
private String coinName;
}