From 3c128c4f9c4ea9d03bc07530b12c39c627c265bb Mon Sep 17 00:00:00 2001 From: HoyiTT Date: Sat, 28 Jun 2025 14:48:59 +0900 Subject: [PATCH] =?UTF-8?q?[feat]=20#29=20=EC=A0=9C=EB=AF=B8=EB=82=98?= =?UTF-8?q?=EC=9D=B4=20=EA=B7=B8=EB=9D=BC=EC=9A=B4=EB=94=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + .../kernellabs/application/GeminiService.java | 46 +++++++++++++++++++ .../controller/GeminiController.java | 37 +++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 src/main/java/com/kernellabs/kernellabs/application/GeminiService.java create mode 100644 src/main/java/com/kernellabs/kernellabs/presentation/controller/GeminiController.java diff --git a/build.gradle b/build.gradle index 6bef8bf..2977bf9 100644 --- a/build.gradle +++ b/build.gradle @@ -29,11 +29,13 @@ dependencies { implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-webflux' + implementation 'com.google.genai:google-genai:1.6.0' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' runtimeOnly 'com.mysql:mysql-connector-j' + } tasks.named('test') { diff --git a/src/main/java/com/kernellabs/kernellabs/application/GeminiService.java b/src/main/java/com/kernellabs/kernellabs/application/GeminiService.java new file mode 100644 index 0000000..e10234e --- /dev/null +++ b/src/main/java/com/kernellabs/kernellabs/application/GeminiService.java @@ -0,0 +1,46 @@ +package com.kernellabs.kernellabs.application; + +import autovalue.shaded.com.google.common.collect.ImmutableList; +import com.google.genai.Client; +import com.google.genai.types.GenerateContentConfig; +import com.google.genai.types.GenerateContentResponse; +import com.google.genai.types.GoogleSearch; +import com.google.genai.types.Tool; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +public class GeminiService { + + private final Client client; + private final Tool googleSearchTool; + private final String modelName; + + public GeminiService( + @Value("${gemini.api.key}") String apiKey, + @Value("${gemini.model:gemini-2.5-flash}") String modelName + ) { + this.client = Client.builder() + .apiKey(apiKey) + .build(); + + this.googleSearchTool = Tool.builder() + .googleSearch(GoogleSearch.builder().build()) + .build(); + + this.modelName = modelName; + } + + public String generateAnswer(String prompt) { + GenerateContentConfig config = GenerateContentConfig.builder() + .tools(ImmutableList.of(googleSearchTool)) + .build(); + + // ← 여기를 client.models()가 아니라 client.models 로 접근 + GenerateContentResponse res = client.models + .generateContent(modelName, prompt, config); + + return res.text(); + } + +} diff --git a/src/main/java/com/kernellabs/kernellabs/presentation/controller/GeminiController.java b/src/main/java/com/kernellabs/kernellabs/presentation/controller/GeminiController.java new file mode 100644 index 0000000..1ac63e8 --- /dev/null +++ b/src/main/java/com/kernellabs/kernellabs/presentation/controller/GeminiController.java @@ -0,0 +1,37 @@ +package com.kernellabs.kernellabs.presentation.controller; + +import com.kernellabs.kernellabs.application.GeminiService; +import jakarta.validation.Valid; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +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; + +@RestController +@RequestMapping("/api/genie") +@AllArgsConstructor +public class GeminiController { + private final GeminiService geminiService; + + @PostMapping("/chat") + public ResponseEntity chat(@Valid @RequestBody ChatRequest req) { + String answer = geminiService.generateAnswer(req.getPrompt()); + return ResponseEntity.ok(new ChatResponse(answer)); + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class ChatRequest { + private String prompt; + } + + @Data @NoArgsConstructor @AllArgsConstructor + public static class ChatResponse { + private String answer; + } +}