-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #112 from teamSynapse6/develop
deploy: GPT를 사용하여 질문 비교, 그룹핑하여 담당자에게 전송
- Loading branch information
Showing
19 changed files
with
463 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
src/main/java/com/startingblock/domain/answer/dto/AnswerRequestDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
127 changes: 127 additions & 0 deletions
127
src/main/java/com/startingblock/domain/gpt/application/GptService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
package com.startingblock.domain.gpt.application; | ||
|
||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.startingblock.domain.gpt.dto.DuplicateReq; | ||
import com.startingblock.domain.gpt.dto.GptMessage; | ||
import com.startingblock.domain.gpt.dto.GptRes; | ||
import com.startingblock.domain.gpt.dto.GroupingQuestionReq; | ||
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.HttpMethod; | ||
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.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
|
||
import static com.startingblock.domain.gpt.constant.GptConstant.*; | ||
|
||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class GptService { | ||
|
||
private final RestTemplate restTemplate; | ||
|
||
@Value(value = "${gpt.api-key}") | ||
private String apiKey; | ||
|
||
public Long checkDuplicateQuestion(final DuplicateReq duplicateReq) throws JsonProcessingException { | ||
List<GptMessage> messages = new ArrayList<>(); | ||
|
||
// gpt 역할(프롬프트) 설정 | ||
messages.add(GptMessage.builder() | ||
.role(SYSTEM) | ||
.content(CHECK_DUPLICATE_PROMPT) | ||
.build()); | ||
|
||
// 실제 요청 | ||
messages.add(GptMessage.builder() | ||
.role(USER) | ||
.content(duplicateReq.toJson()) | ||
.build()); | ||
|
||
log.info("Request Messages: {}", messages); | ||
|
||
HashMap<String, Object> requestBody = createRequestBody(messages); | ||
|
||
GptRes chatGptRes = getResponse(createHttpEntity(requestBody)); | ||
|
||
String response = chatGptRes.getChoices().get(0).getMessage().getContent(); | ||
log.info("Response: {}", response); | ||
|
||
return Long.valueOf(response); | ||
} | ||
|
||
public String groupingQuestions(final GroupingQuestionReq questionList) throws JsonProcessingException { | ||
List<GptMessage> messages = new ArrayList<>(); | ||
|
||
// gpt 역할(프롬프트) 설정 | ||
messages.add(GptMessage.builder() | ||
.role(SYSTEM) | ||
.content(CHECK_SIMILARITY_PROMPT) | ||
.build()); | ||
|
||
// 실제 요청 | ||
messages.add(GptMessage.builder() | ||
.role(USER) | ||
.content(questionList.toJson()) | ||
.build()); | ||
|
||
log.info("Request Messages: {}", messages); | ||
|
||
HashMap<String, Object> requestBody = createRequestBody(messages); | ||
|
||
GptRes chatGptRes = getResponse(createHttpEntity(requestBody)); | ||
|
||
String response = chatGptRes.getChoices().get(0).getMessage().getContent(); | ||
log.info("Response: {}", response); | ||
|
||
return response; | ||
} | ||
|
||
// GPT 에 요청할 파라미터를 만드는 메서드 | ||
private static HashMap<String, Object> createRequestBody(final List<GptMessage> messages) { | ||
HashMap<String, Object> requestBody = new HashMap<>(); | ||
requestBody.put("model", CHAT_MODEL); | ||
requestBody.put("messages", messages); | ||
requestBody.put("max_tokens", MAX_TOKEN); | ||
requestBody.put("temperature", TEMPERATURE); | ||
return requestBody; | ||
} | ||
|
||
// api 호출에 필요한 Http Header를 만들고 HTTP 객체를 만드는 메서드 | ||
public HttpEntity<HashMap<String, Object>> createHttpEntity(final HashMap<String, Object> chatGptRequest){ | ||
|
||
HttpHeaders httpHeaders = new HttpHeaders(); | ||
httpHeaders.setContentType(MediaType.parseMediaType(MEDIA_TYPE)); | ||
httpHeaders.add(AUTHORIZATION, BEARER + apiKey); | ||
return new HttpEntity<>(chatGptRequest, httpHeaders); | ||
} | ||
|
||
// GPT API 요청후 response body를 받아오는 메서드 | ||
public GptRes getResponse(final HttpEntity<HashMap<String, Object>> httpEntity){ | ||
|
||
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); | ||
// 답변이 길어질 경우 TimeOut Error 발생하므로 time 설정 | ||
requestFactory.setConnectTimeout(60000); | ||
requestFactory.setReadTimeout(60000); // 1min | ||
|
||
restTemplate.setRequestFactory(requestFactory); | ||
ResponseEntity<GptRes> responseEntity = restTemplate.exchange( | ||
CHAT_URL, | ||
HttpMethod.POST, | ||
httpEntity, | ||
GptRes.class); | ||
|
||
return responseEntity.getBody(); | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
src/main/java/com/startingblock/domain/gpt/constant/GptConstant.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.startingblock.domain.gpt.constant; | ||
|
||
|
||
public final class GptConstant { | ||
|
||
private GptConstant(){} | ||
public static final String AUTHORIZATION = "Authorization"; | ||
public static final String BEARER = "Bearer "; | ||
public static final String CHAT_MODEL = "gpt-4o"; | ||
public static final Integer MAX_TOKEN = 1000; | ||
public static final String USER = "user"; | ||
public static final String SYSTEM = "system"; | ||
public static final Double TEMPERATURE = 0.3; | ||
public static final String MEDIA_TYPE = "application/json; charset=UTF-8"; | ||
public static final String CHAT_URL = "https://api.openai.com/v1/chat/completions"; | ||
|
||
// 프롬프트 | ||
public static final String CHECK_DUPLICATE_PROMPT = | ||
""" | ||
당신은 창업 지원사업에 대한 질문을 기존의 질문들과 비교해주는 사람입니다.\s | ||
[기존 질문]은 JSON 형태로, "questionId"는 질문의 ID값, "content"는 질문의 내용입니다. | ||
newQuestion 을 oldQuestions 리스트의 "content"와 비교해서 유사한 질문이 있다면 유사한 질문의 "questionId"를, 없다면 0을 숫자만 출력하세요. | ||
"""; | ||
|
||
public static final String CHECK_SIMILARITY_PROMPT = | ||
""" | ||
당신은 창업 지원사업에 대한 여러가지 질문들을 유사한 질문들끼리 묶어주는 사람입니다. | ||
질문들은 JSON 형태로, "questionId"는 질문의 ID값, "content"는 질문의 내용입니다. | ||
질문 리스트의 "content" 끼리 비교해서 유사한 질문이 있다면 하나의 질문으로 묶어주세요. | ||
유사한 질문의 내용을 정리해서 "content"에 담아주고, 이때 사용한 질문들의 "questionId"를 "questionId" 배열에 담아서 JSON 형태로 출력하세요. | ||
제가 의도하는 출력 형식은 다음과 같습니다. 반드시 아래 형식을 지키세요. | ||
[{"questionId":[10001, 10002], "content":"제출일이 언제인가요?"}, | ||
{"questionId":[10003], "content":"마감기한 이후에 제출 시 어떻게 하나요?"}] | ||
"""; | ||
} |
25 changes: 25 additions & 0 deletions
25
src/main/java/com/startingblock/domain/gpt/dto/DuplicateReq.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.startingblock.domain.gpt.dto; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
|
||
import java.util.List; | ||
|
||
@Getter | ||
@Builder | ||
public class DuplicateReq { | ||
|
||
@JsonProperty("oldQuestions") | ||
private List<SimpleGPTQuestionReq> oldQuestions; | ||
|
||
@JsonProperty("newQuestion") | ||
private String newQuestion; | ||
|
||
public String toJson() throws JsonProcessingException { | ||
ObjectMapper mapper = new ObjectMapper(); | ||
return mapper.writeValueAsString(this); | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
src/main/java/com/startingblock/domain/gpt/dto/GptMessage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.startingblock.domain.gpt.dto; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Data; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Data | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
@Builder | ||
public class GptMessage { | ||
|
||
private String role; | ||
|
||
private String content; | ||
} |
38 changes: 38 additions & 0 deletions
38
src/main/java/com/startingblock/domain/gpt/dto/GptReq.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package com.startingblock.domain.gpt.dto; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import lombok.Builder; | ||
import lombok.Data; | ||
import lombok.NoArgsConstructor; | ||
|
||
import java.io.Serializable; | ||
import java.util.List; | ||
|
||
@Data | ||
@NoArgsConstructor | ||
public class GptReq implements Serializable { | ||
|
||
private String model; | ||
|
||
@JsonProperty("max_tokens") | ||
private Integer maxTokens; | ||
|
||
private Double temperature; | ||
|
||
private Boolean stream; | ||
|
||
private List<GptMessage> messages; | ||
|
||
@JsonProperty("top_p") | ||
private Double topP; | ||
|
||
@Builder | ||
public GptReq(String model, Integer maxTokens, Double temperature, | ||
Boolean stream, List<GptMessage> messages) { | ||
this.model = model; | ||
this.maxTokens = maxTokens; | ||
this.temperature = temperature; | ||
this.stream = stream; | ||
this.messages = messages; | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
src/main/java/com/startingblock/domain/gpt/dto/GptRes.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package com.startingblock.domain.gpt.dto; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import lombok.Data; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.Setter; | ||
|
||
import java.util.List; | ||
|
||
@Data | ||
@NoArgsConstructor | ||
public class GptRes { | ||
|
||
private String id; | ||
|
||
private String object; | ||
|
||
private long created; | ||
|
||
private String model; | ||
|
||
private Usage usage; | ||
|
||
private List<Choice> choices; | ||
|
||
@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 GptMessage message; | ||
@JsonProperty("finish_reason") | ||
private String finishReason; | ||
private int index; | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
src/main/java/com/startingblock/domain/gpt/dto/GroupingQuestionReq.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package com.startingblock.domain.gpt.dto; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.startingblock.domain.question.dto.QuestionResponseDto; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
|
||
import java.util.List; | ||
|
||
@Getter | ||
@Builder | ||
public class GroupingQuestionReq { | ||
|
||
@JsonProperty("questions") | ||
private List<QuestionResponseDto.QuestionSimpleResponse> questions; | ||
|
||
public String toJson() throws JsonProcessingException { | ||
ObjectMapper mapper = new ObjectMapper(); | ||
return mapper.writeValueAsString(this); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
src/main/java/com/startingblock/domain/gpt/dto/GroupingQuestionRes.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.startingblock.domain.gpt.dto; | ||
|
||
import lombok.Getter; | ||
|
||
import java.util.List; | ||
|
||
@Getter | ||
public class GroupingQuestionRes { | ||
|
||
private List<Long> questionId; | ||
private String content; | ||
|
||
} |
18 changes: 18 additions & 0 deletions
18
src/main/java/com/startingblock/domain/gpt/dto/SimpleGPTQuestionReq.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.startingblock.domain.gpt.dto; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
|
||
import java.io.Serializable; | ||
|
||
@Getter | ||
@Builder | ||
public class SimpleGPTQuestionReq implements Serializable { | ||
|
||
@JsonProperty("qid") | ||
private Long questionId; | ||
|
||
@JsonProperty("content") | ||
private String content; | ||
} |
Oops, something went wrong.