Skip to content
This repository has been archived by the owner on Oct 20, 2024. It is now read-only.

Commit

Permalink
Merge pull request #42 from FinFellows/develop
Browse files Browse the repository at this point in the history
[DEPLOY]: 중간 배포
  • Loading branch information
sejineer authored Jan 4, 2024
2 parents b654332 + 25eb0f6 commit 26e181d
Show file tree
Hide file tree
Showing 48 changed files with 1,411 additions and 104 deletions.
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'

//gpt
implementation group: 'com.theokanning.openai-gpt3-java', name: 'client', version: '0.9.0'
implementation 'io.github.flashvayne:chatgpt-spring-boot-starter:1.0.4'

//webflux
implementation 'org.springframework.boot:spring-boot-starter-webflux'

compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'com.mysql:mysql-connector-j'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.finfellows.domain.chatbot.domain;

public class Chatbot {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.finfellows.domain.chatbot.domain.repository;

public interface ChatbotRepository {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.finfellows.domain.chatgpt.application;

import io.github.flashvayne.chatgpt.service.ChatgptService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class ChatGptService {

// 라이브러리 제공
private final ChatgptService chatgptService;

@Value("${chatgpt.api-key}")
private String apiKey;
// private final ObjectMapper objectMapper = new ObjectMapper()
// .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
// .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE );
// public Flux<String> ask(ChatgptQuestionRequest chatGptQuestionRequest) throws JsonProcessingException {
// WebClient client = WebClient.builder()
// .baseUrl(ChatgptConfig.CHAT_URL)
// .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
// .defaultHeader(ChatgptConfig.AUTHORIZATION, ChatgptConfig.BEARER + apiKey)
// .build();
//
// List<ChatGptMessage> messages = new ArrayList<>();
// messages.add(ChatGptMessage.builder()
// .role(ChatgptConfig.ROLE)
// .content(chatGptQuestionRequest.getQuestion())
// .build());
//
// ChatgptRequest chatGptRequest = new ChatgptRequest(
// ChatgptConfig.CHAT_MODEL,
// ChatgptConfig.MAX_TOKEN,
// ChatgptConfig.TEMPERATURE,
// ChatgptConfig.STREAM_TRUE,
// messages
// );
//
// String requestValue = objectMapper.writeValueAsString(chatGptRequest);
//
// Flux<String> eventStream = client.post()
// .bodyValue(requestValue)
// .accept(MediaType.TEXT_EVENT_STREAM)
// .retrieve()
// .bodyToFlux(String.class);
//
// return eventStream;
// }

// 단답 답변
public String getChatResponse(String prompt) {
System.out.print(apiKey);
// ChatGPT에 질문 전송
return chatgptService.sendMessage(prompt);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.finfellows.domain.chatgpt.config;

import com.theokanning.openai.OpenAiService;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.Duration;

@Slf4j
@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_TRUE = true;
public static final Boolean STREAM_FALSE = false;
public static final String ROLE = "user";
public static final Double TEMPERATURE = 0.6;
public static final String MEDIA_TYPE = "application/json; charset=UTF-8";
public static final String CHAT_URL = "https://api.openai.com/v1/chat/completions";

@Value("${chatgpt.api-key}")
private String token;

@Bean
public OpenAiService openAiService() {
log.info("token: {}을 활용한 OpenApiService를 생성합니다!", token);
return new OpenAiService(token, Duration.ofSeconds(60));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.finfellows.domain.chatgpt.domain;

import lombok.Builder;
import lombok.Data;

@Builder
@Data
public class ChatGptMessage {
private String role;
private String content;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.finfellows.domain.chatgpt.dto.request;

import lombok.Getter;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Getter
@NoArgsConstructor
public class ChatgptQuestionRequest implements Serializable {
private String question;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.finfellows.domain.chatgpt.dto.request;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.finfellows.domain.chatgpt.domain.ChatGptMessage;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.*;

@Getter
@NoArgsConstructor
//chatGPT에 요청할 DTO Format
public class ChatgptRequest implements Serializable {
private String model;
@JsonProperty("max_tokens")
private Integer maxTokens;
private Double temperature;
private Boolean stream;
private List<ChatGptMessage> messages;

//@JsonProperty("top_p")
//private Double topP;

@Builder
public ChatgptRequest(String model, Integer maxTokens, Double temperature,
Boolean stream, List<ChatGptMessage> messages
/*,Double topP*/) {
this.model = model;
this.maxTokens = maxTokens;
this.temperature = temperature;
this.stream = stream;
this.messages = messages;
//this.topP = topP;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.finfellows.domain.chatgpt.dto.response;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.*;

@Getter
@NoArgsConstructor
//GPT 답변에 대한 DTO
public class ChatgptResponse {
private String id;
private String model;
private List<String> choices;

@Getter
@Setter
public static class Usage {
private int totalTokens;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.finfellows.domain.chatgpt.presentation;

import com.finfellows.domain.chatgpt.application.ChatGptService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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;

@RestController
@RequestMapping("/api/v1/chat-gpt")
@RequiredArgsConstructor
@Slf4j
public class ChatGptController {
private final ChatGptService chatgptService;

// @PostMapping(value="/ask-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
// public Flux<String> ask(Locale locale,
// HttpServletRequest request,
// HttpServletResponse response,
// @RequestBody ChatgptQuestionRequest chatGptQuestionRequest){
// try {
// return chatgptService.ask(chatGptQuestionRequest);
// }catch (JsonProcessingException je){
// log.error(je.getMessage());
// return Flux.empty();
// }
// }

// 단답 테스트
// https://yjkim-dev.tistory.com/56
@PostMapping("")
public String test(@RequestBody String question) {
return chatgptService.getChatResponse(question);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.finfellows.domain.comment.application;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.finfellows.domain.chatgpt.domain.ChatGptMessage;
import com.finfellows.domain.chatgpt.application.ChatGptService;
import com.finfellows.domain.chatgpt.config.ChatgptConfig;
import com.finfellows.domain.chatgpt.dto.request.ChatgptQuestionRequest;
import com.finfellows.domain.chatgpt.dto.request.ChatgptRequest;
import com.finfellows.domain.chatgpt.dto.response.ChatgptResponse;
import com.finfellows.domain.comment.domain.repository.CommentRepository;
import com.finfellows.domain.user.domain.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.*;

@Service
@RequiredArgsConstructor
public class CommentService {
private final UserRepository userRepository;
private final ChatGptService chatGptService;
private final CommentRepository commentRepository;

@Autowired
private RestTemplate restTemplate;

@Value("${chatgpt.api-key}")
private String apiKey;
private final ObjectMapper objectMapper = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);

// gpt 단답
public HttpEntity<ChatgptRequest> buildHttpEntity(ChatgptRequest chatGptRequest) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.parseMediaType(ChatgptConfig.MEDIA_TYPE));
httpHeaders.add(ChatgptConfig.AUTHORIZATION, ChatgptConfig.BEARER + apiKey);
return new HttpEntity<>(chatGptRequest, httpHeaders);
}

// gpt 단답
public ChatgptResponse getResponse(HttpEntity<ChatgptRequest> chatGptRequestHttpEntity) {

SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(60000);
//답변이 길어질 경우 TimeOut Error가 발생하니 1분정도 설정해줍니다.
requestFactory.setReadTimeout(60 * 1000); // 1min = 60 sec * 1,000ms
restTemplate.setRequestFactory(requestFactory);

ResponseEntity<ChatgptResponse> responseEntity = restTemplate.postForEntity(
ChatgptConfig.CHAT_URL,
chatGptRequestHttpEntity,
ChatgptResponse.class);

return responseEntity.getBody();
}

// gpt 단답
public ChatgptResponse askQuestion(ChatgptQuestionRequest questionRequest) {
List<ChatGptMessage> messages = new ArrayList<>();
messages.add(ChatGptMessage.builder()
.role(ChatgptConfig.ROLE)
.content(questionRequest.getQuestion())
.build());
return this.getResponse(
this.buildHttpEntity(
new ChatgptRequest(
ChatgptConfig.CHAT_MODEL,
ChatgptConfig.MAX_TOKEN,
ChatgptConfig.TEMPERATURE,
ChatgptConfig.STREAM_FALSE,
messages
)
)
);
}
}
33 changes: 33 additions & 0 deletions src/main/java/com/finfellows/domain/comment/domain/Comment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.finfellows.domain.comment.domain;

import com.finfellows.domain.common.BaseEntity;
import com.finfellows.domain.user.domain.User;
import jakarta.persistence.*;
import lombok.*;

@Entity
@Table(name="Comment")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class Comment extends BaseEntity {

//질문 내용 저장 칼럼 필요함.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="comment_id", updatable = false, nullable = false, unique = true)
private Long commentId;

@Column(name="comment_content")
private String commentContent;

@ManyToOne
@JoinColumn(name="user_id")
private User userId;

@Builder
public Comment(Long commentId, String commentContent, User userId){
this.commentId=commentId;
this.commentContent=commentContent;
this.userId=userId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.finfellows.domain.comment.domain.repository;

import com.finfellows.domain.comment.domain.Comment;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CommentRepository extends JpaRepository<Comment, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.finfellows.domain.comment.presentation;

import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class CommentController {
}
Loading

0 comments on commit 26e181d

Please sign in to comment.