diff --git a/build.gradle b/build.gradle index bc334e9..dec7615 100644 --- a/build.gradle +++ b/build.gradle @@ -44,8 +44,11 @@ dependencies { implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.4' implementation 'org.springdoc:springdoc-openapi-starter-webmvc-api:2.0.4' implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' + /* Chat GPT */ + implementation 'com.theokanning.openai-gpt3-java:service:0.12.0' + implementation 'io.github.flashvayne:chatgpt-spring-boot-starter:1.0.4' } tasks.named('test') { useJUnitPlatform() -} +} \ No newline at end of file diff --git a/src/main/java/com/hackathon/hackathon/domain/chatGPT/config/ChatGptConfig.java b/src/main/java/com/hackathon/hackathon/domain/chatGPT/config/ChatGptConfig.java new file mode 100644 index 0000000..3312fa4 --- /dev/null +++ b/src/main/java/com/hackathon/hackathon/domain/chatGPT/config/ChatGptConfig.java @@ -0,0 +1,18 @@ +package com.hackathon.hackathon.domain.chatGPT.config; + +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ChatGptConfig { + public static final String AUTHORIZATION = "Authorization"; + public static final String BEARER = "Bearer "; + public static final String CHAT_MODEL = "gpt-3.5-turbo"; + public static final Integer MAX_TOKEN = 300; + public static final Boolean STREAM = false; + public static final String ROLE = "user"; + public static final Double TEMPERATURE = 0.6; + //public static final Double TOP_P = 1.0; + public static final String MEDIA_TYPE = "application/json; charset=UTF-8"; + //completions : 질답 + public static final String CHAT_URL = "https://api.openai.com/v1/chat/completions"; +} diff --git a/src/main/java/com/hackathon/hackathon/domain/chatGPT/config/RestTemplateConfig.java b/src/main/java/com/hackathon/hackathon/domain/chatGPT/config/RestTemplateConfig.java new file mode 100644 index 0000000..15e1b99 --- /dev/null +++ b/src/main/java/com/hackathon/hackathon/domain/chatGPT/config/RestTemplateConfig.java @@ -0,0 +1,14 @@ +package com.hackathon.hackathon.domain.chatGPT.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestTemplateConfig { + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } +} \ No newline at end of file diff --git a/src/main/java/com/hackathon/hackathon/domain/chatGPT/controller/ChatGptController.java b/src/main/java/com/hackathon/hackathon/domain/chatGPT/controller/ChatGptController.java new file mode 100644 index 0000000..83c422a --- /dev/null +++ b/src/main/java/com/hackathon/hackathon/domain/chatGPT/controller/ChatGptController.java @@ -0,0 +1,47 @@ +package com.hackathon.hackathon.domain.chatGPT.controller; + +import com.hackathon.hackathon.domain.chatGPT.dto.request.QuestionRequestDTO; +import com.hackathon.hackathon.domain.chatGPT.dto.response.ChatGptColorResponseDTO; +import com.hackathon.hackathon.domain.chatGPT.dto.response.ChatGptResponseDTO; +import com.hackathon.hackathon.domain.chatGPT.service.ChatGptService; +import com.hackathon.hackathon.global.response.SuccessResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.models.responses.ApiResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Locale; + +@RequiredArgsConstructor +@RequestMapping("/chat-gpt") +@RestController +public class ChatGptController { + //private final ApiResponse apiResponse; + private final ChatGptService chatGptService; + + @Operation(summary = "Question to Chat-GPT") + @PostMapping("/question") + public SuccessResponse sendQuestion( + Locale locale, + HttpServletRequest request, + HttpServletResponse response, + @RequestBody QuestionRequestDTO questionRequest) { + String code = "200"; + ChatGptColorResponseDTO chatGptColorResponseDTO = null; + try { + chatGptColorResponseDTO = chatGptService.askQuestion(questionRequest); + System.out.println(chatGptColorResponseDTO); + } catch (Exception e) { +// apiResponse.printErrorMessage(e); + code = e.getMessage(); + } + //return 부분은 자유롭게 수정하시면됩니다. ex)return chatGptResponse; + return SuccessResponse.onSuccess(200, chatGptColorResponseDTO); + } +} \ No newline at end of file diff --git a/src/main/java/com/hackathon/hackathon/domain/chatGPT/dto/request/ChatGptRequestDTO.java b/src/main/java/com/hackathon/hackathon/domain/chatGPT/dto/request/ChatGptRequestDTO.java new file mode 100644 index 0000000..cb3acfd --- /dev/null +++ b/src/main/java/com/hackathon/hackathon/domain/chatGPT/dto/request/ChatGptRequestDTO.java @@ -0,0 +1,32 @@ +package com.hackathon.hackathon.domain.chatGPT.dto.request; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.hackathon.hackathon.domain.chatGPT.entity.ChatGptMessage; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +@Getter +@NoArgsConstructor +public class ChatGptRequestDTO implements Serializable { + private String model; + @JsonProperty("max_tokens") + private Integer maxTokens; + private Double temperature; + private Boolean stream; + private List messages; + + @Builder + public ChatGptRequestDTO(String model, Integer maxTokens, Double temperature, + Boolean stream, List messages) { + this.model = model; + this.maxTokens = maxTokens; + this.temperature = temperature; + this.stream = stream; + this.messages = messages; + } + +} diff --git a/src/main/java/com/hackathon/hackathon/domain/chatGPT/dto/request/QuestionRequestDTO.java b/src/main/java/com/hackathon/hackathon/domain/chatGPT/dto/request/QuestionRequestDTO.java new file mode 100644 index 0000000..8c15927 --- /dev/null +++ b/src/main/java/com/hackathon/hackathon/domain/chatGPT/dto/request/QuestionRequestDTO.java @@ -0,0 +1,12 @@ +package com.hackathon.hackathon.domain.chatGPT.dto.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Getter +@NoArgsConstructor +public class QuestionRequestDTO implements Serializable { + private String question; +} diff --git a/src/main/java/com/hackathon/hackathon/domain/chatGPT/dto/response/ChatGptColorResponseDTO.java b/src/main/java/com/hackathon/hackathon/domain/chatGPT/dto/response/ChatGptColorResponseDTO.java new file mode 100644 index 0000000..bd49efc --- /dev/null +++ b/src/main/java/com/hackathon/hackathon/domain/chatGPT/dto/response/ChatGptColorResponseDTO.java @@ -0,0 +1,15 @@ +package com.hackathon.hackathon.domain.chatGPT.dto.response; + +import lombok.Builder; +import lombok.Getter; + +@Getter +public class ChatGptColorResponseDTO { + + private String color; + + @Builder + public ChatGptColorResponseDTO(String color) { + this.color = color; + } +} diff --git a/src/main/java/com/hackathon/hackathon/domain/chatGPT/dto/response/ChatGptResponseDTO.java b/src/main/java/com/hackathon/hackathon/domain/chatGPT/dto/response/ChatGptResponseDTO.java new file mode 100644 index 0000000..8c59ab1 --- /dev/null +++ b/src/main/java/com/hackathon/hackathon/domain/chatGPT/dto/response/ChatGptResponseDTO.java @@ -0,0 +1,42 @@ +package com.hackathon.hackathon.domain.chatGPT.dto.response; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.hackathon.hackathon.domain.chatGPT.entity.ChatGptMessage; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.List; + +@Getter +@NoArgsConstructor +public class ChatGptResponseDTO { + private String id; + private String object; + private long created; + private String model; + @JsonProperty("system_fingerprint") + private String systemFingerprint; + private List choices; + private Usage usage; + + @Getter + @Setter + public static class Usage { + @JsonProperty("prompt_tokens") + private int promptTokens; + @JsonProperty("completion_tokens") + private int completionTokens; + @JsonProperty("total_tokens") + private int totalTokens; + } + + @Getter + @Setter + public static class Choice { + private int index; + private ChatGptMessage message; + @JsonProperty("finish_reason") + private String finishReason; + } +} diff --git a/src/main/java/com/hackathon/hackathon/domain/chatGPT/entity/ChatGptMessage.java b/src/main/java/com/hackathon/hackathon/domain/chatGPT/entity/ChatGptMessage.java new file mode 100644 index 0000000..660d161 --- /dev/null +++ b/src/main/java/com/hackathon/hackathon/domain/chatGPT/entity/ChatGptMessage.java @@ -0,0 +1,16 @@ +package com.hackathon.hackathon.domain.chatGPT.entity; + +import lombok.Builder; +import lombok.Getter; + +@Getter +public class ChatGptMessage { + private String role; + private String content; + + @Builder + public ChatGptMessage(String role, String content) { + this.role = role; + this.content = content; + } +} diff --git a/src/main/java/com/hackathon/hackathon/domain/chatGPT/service/ChatGptService.java b/src/main/java/com/hackathon/hackathon/domain/chatGPT/service/ChatGptService.java new file mode 100644 index 0000000..088d804 --- /dev/null +++ b/src/main/java/com/hackathon/hackathon/domain/chatGPT/service/ChatGptService.java @@ -0,0 +1,90 @@ +package com.hackathon.hackathon.domain.chatGPT.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.hackathon.hackathon.domain.chatGPT.dto.request.ChatGptRequestDTO; +import com.hackathon.hackathon.domain.chatGPT.dto.request.QuestionRequestDTO; +import com.hackathon.hackathon.domain.chatGPT.dto.response.ChatGptColorResponseDTO; +import com.hackathon.hackathon.domain.chatGPT.dto.response.ChatGptResponseDTO; +import com.hackathon.hackathon.domain.chatGPT.dto.response.ChatGptResponseDTO.Choice; +import com.hackathon.hackathon.domain.chatGPT.config.ChatGptConfig; +import com.hackathon.hackathon.domain.chatGPT.entity.ChatGptMessage; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@RequiredArgsConstructor +@Service +public class ChatGptService { + private final RestTemplate restTemplate; + + + //api key를 application.yml에 넣어두었습니다. + @Value("${chatgpt.api-key}") + private String apiKey; + + public ChatGptResponseDTO buildHttpEntity(ChatGptRequestDTO chatGptRequest){ + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setContentType(MediaType.parseMediaType(ChatGptConfig.MEDIA_TYPE)); + httpHeaders.add(ChatGptConfig.AUTHORIZATION, ChatGptConfig.BEARER + apiKey); + return getResponse(new HttpEntity<>(chatGptRequest, httpHeaders)); + } + + public ChatGptResponseDTO getResponse(HttpEntity chatGptRequestHttpEntity){ + + SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); + requestFactory.setConnectTimeout(60000); + //답변이 길어질 경우 TimeOut Error가 발생하니 1분정도 설정해줍니다. + requestFactory.setReadTimeout(60 * 1000); // 1min = 60 sec * 1,000ms + restTemplate.setRequestFactory(requestFactory); + + ResponseEntity responseEntity = restTemplate.postForEntity( + ChatGptConfig.CHAT_URL, + chatGptRequestHttpEntity, + ChatGptResponseDTO.class); + + return responseEntity.getBody(); + } + public ChatGptColorResponseDTO askQuestion(QuestionRequestDTO questionRequest){ + List messages = new ArrayList<>(); + messages.add(ChatGptMessage.builder() + .role(ChatGptConfig.ROLE) + .content(questionRequest.getQuestion()) + .build()); + ChatGptResponseDTO test = buildHttpEntity( new ChatGptRequestDTO( + ChatGptConfig.CHAT_MODEL, + ChatGptConfig.MAX_TOKEN, + ChatGptConfig.TEMPERATURE, + ChatGptConfig.STREAM, + messages + //ChatGptConfig.TOP_P + )); + System.out.println(test.getChoices()); + + // Json에서 color만 추출해 반환 + ChatGptResponseDTO.Choice firstChoice = test.getChoices().get(0); + String tt = test.getChoices().get(0).getFinishReason(); + System.out.println(tt); + System.out.println(firstChoice); + test.getChoices().get(0).getMessage(); + String color = String.valueOf(firstChoice.getMessage()); + System.out.println(color.toString()); + ChatGptColorResponseDTO chatGptColorResponseDTO = ChatGptColorResponseDTO.builder() + .color(color) + .build(); + return chatGptColorResponseDTO; + } +} \ No newline at end of file diff --git a/src/main/java/com/hackathon/hackathon/domain/user/repositroy/UserRepository.java b/src/main/java/com/hackathon/hackathon/domain/user/repositroy/UserRepository.java index 4c6bbb4..d5bd2e5 100644 --- a/src/main/java/com/hackathon/hackathon/domain/user/repositroy/UserRepository.java +++ b/src/main/java/com/hackathon/hackathon/domain/user/repositroy/UserRepository.java @@ -8,5 +8,4 @@ public interface UserRepository extends JpaRepository { Optional findByAuthInfoEmail(String email); Boolean existsByAuthInfoEmail(String email); - Optional findByEmail(String email); }