From 4e2af9415c95b7936d295b6e07e7f4212ff073c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=84=B8=EC=A7=84?= Date: Tue, 22 Oct 2024 23:03:43 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20SpringAi=20gpt=20=EC=9A=B0=EC=84=A0=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0=EB=A7=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 14 ++++++ .../splanet/splanet/config/OpenAIConfig.java | 21 +++++++++ .../com/splanet/splanet/gpt/ChatResponse.java | 9 ++++ .../java/com/splanet/splanet/gpt/Choice.java | 8 ++++ .../java/com/splanet/splanet/gpt/Message.java | 12 +++++ .../splanet/splanet/gpt/OpenAiChatClient.java | 47 +++++++++++++++++++ .../java/com/splanet/splanet/gpt/Prompt.java | 12 +++++ 7 files changed, 123 insertions(+) create mode 100644 src/main/java/com/splanet/splanet/config/OpenAIConfig.java create mode 100644 src/main/java/com/splanet/splanet/gpt/ChatResponse.java create mode 100644 src/main/java/com/splanet/splanet/gpt/Choice.java create mode 100644 src/main/java/com/splanet/splanet/gpt/Message.java create mode 100644 src/main/java/com/splanet/splanet/gpt/OpenAiChatClient.java create mode 100644 src/main/java/com/splanet/splanet/gpt/Prompt.java diff --git a/build.gradle b/build.gradle index c00aa0c1..d854b872 100644 --- a/build.gradle +++ b/build.gradle @@ -23,6 +23,12 @@ configurations { repositories { mavenCentral() + maven { + url 'https://repo.spring.io/milestone' + } + maven { + url 'https://repo.spring.io/snapshot' + } } dependencies { @@ -60,6 +66,14 @@ dependencies { testImplementation 'org.springframework.security:spring-security-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + //gpt + // implementation 'org.springframework.boot:spring-boot-starter-web' + // implementation 'com.fasterxml.jackson.core:jackson-databind' + // implementation 'org.springframework.boot:spring-boot-starter' + implementation platform("org.springframework.ai:spring-ai-bom:0.8.0") + implementation 'org.springframework.ai:spring-ai-openai' + + } tasks.named('test') { diff --git a/src/main/java/com/splanet/splanet/config/OpenAIConfig.java b/src/main/java/com/splanet/splanet/config/OpenAIConfig.java new file mode 100644 index 00000000..974a3739 --- /dev/null +++ b/src/main/java/com/splanet/splanet/config/OpenAIConfig.java @@ -0,0 +1,21 @@ +package com.splanet.splanet.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class OpenAIConfig { + @Value("${spring.ai.gpt.api-key}") + private String apiKey; + @Bean + public RestTemplate template(){ + RestTemplate restTemplate = new RestTemplate(); + restTemplate.getInterceptors().add((request, body, execution) -> { + request.getHeaders().add("Authorization", "Bearer " + apiKey); + return execution.execute(request, body); + }); + return restTemplate; + } +} \ No newline at end of file diff --git a/src/main/java/com/splanet/splanet/gpt/ChatResponse.java b/src/main/java/com/splanet/splanet/gpt/ChatResponse.java new file mode 100644 index 00000000..25d92c71 --- /dev/null +++ b/src/main/java/com/splanet/splanet/gpt/ChatResponse.java @@ -0,0 +1,9 @@ +package com.splanet.splanet.gpt; + +import lombok.Getter; +import java.util.List; + +@Getter +public class ChatResponse { + private List choices; // Choice 객체 리스트 +} \ No newline at end of file diff --git a/src/main/java/com/splanet/splanet/gpt/Choice.java b/src/main/java/com/splanet/splanet/gpt/Choice.java new file mode 100644 index 00000000..be2070a0 --- /dev/null +++ b/src/main/java/com/splanet/splanet/gpt/Choice.java @@ -0,0 +1,8 @@ +package com.splanet.splanet.gpt; + +import lombok.Getter; + +@Getter +public class Choice { + private Message message; // Message 객체 +} \ No newline at end of file diff --git a/src/main/java/com/splanet/splanet/gpt/Message.java b/src/main/java/com/splanet/splanet/gpt/Message.java new file mode 100644 index 00000000..55b59650 --- /dev/null +++ b/src/main/java/com/splanet/splanet/gpt/Message.java @@ -0,0 +1,12 @@ +package com.splanet.splanet.gpt; + +import lombok.Getter; + +@Getter +public class Message { + private String content; // 메시지 내용 + + public Message(String content) { + this.content = content; + } +} \ No newline at end of file diff --git a/src/main/java/com/splanet/splanet/gpt/OpenAiChatClient.java b/src/main/java/com/splanet/splanet/gpt/OpenAiChatClient.java new file mode 100644 index 00000000..27da861e --- /dev/null +++ b/src/main/java/com/splanet/splanet/gpt/OpenAiChatClient.java @@ -0,0 +1,47 @@ +package com.splanet.splanet.gpt; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Flux; + +import java.util.List; + +@Component +public class OpenAiChatClient { + + private final WebClient webClient; + + @Value("${spring.ai.gpt.api-key}") + private String apiKey; + + public OpenAiChatClient(WebClient.Builder webClientBuilder) { + this.webClient = webClientBuilder.baseUrl("https://api.openai.com/v1").build(); + } + + public String call(String message) { + Message userMessage = new Message(message); // 메시지 객체 생성 + Prompt prompt = new Prompt(List.of(userMessage)); // Message 객체를 리스트로 감싸서 Prompt 생성 + + ChatResponse response = webClient.post() + .uri("/chat/completions") + .header("Authorization", "Bearer " + apiKey) // 프로퍼티에서 가져온 API 키 사용 + .bodyValue(prompt) + .retrieve() + .bodyToMono(ChatResponse.class) + .block(); // 블록하여 응답을 기다림 + + return response != null && response.getChoices() != null && !response.getChoices().isEmpty() + ? response.getChoices().get(0).getMessage().getContent() + : "No response"; + } + + public Flux stream(Prompt prompt) { + return webClient.post() + .uri("/chat/completions") + .header("Authorization", "Bearer " + apiKey) // 프로퍼티에서 가져온 API 키 사용 + .bodyValue(prompt) + .retrieve() + .bodyToFlux(ChatResponse.class); // Stream the response + } +} \ No newline at end of file diff --git a/src/main/java/com/splanet/splanet/gpt/Prompt.java b/src/main/java/com/splanet/splanet/gpt/Prompt.java new file mode 100644 index 00000000..27da96c1 --- /dev/null +++ b/src/main/java/com/splanet/splanet/gpt/Prompt.java @@ -0,0 +1,12 @@ +package com.splanet.splanet.gpt; + +import lombok.Getter; +import lombok.AllArgsConstructor; + +import java.util.List; + +@Getter +@AllArgsConstructor // 모든 필드를 사용하는 생성자를 자동 생성 +public class Prompt { + private List messages; // 메시지 목록 +} \ No newline at end of file