Skip to content

Google GenAI SDK for Java โ€‹

TL;DR โ€‹

Google Gen AI Java SDK โ€‹

build.gradle.kts
kts
// implementation("com.google.cloud:google-cloud-vertexai:1.40.0") // Deprecated
implementation("com.google.genai:google-genai:1.30.0")

๋ฐฑ์—”๋“œ ์ž๋ฐ” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ Gemini API ๋ฅผ ์—ฐ๋™ํ•˜๋ ค๊ณ  ํ• ๋•Œ๋Š” Vertex AI SDK ๋ณด๋‹ค๋Š” Google Gen AI Java SDK๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”. Vertex AI SDK๋Š” ์•ž์œผ๋กœ ์ง€์› ์ข…๋ฃŒ๋  ์˜ˆ์ •์ด๋ฏ€๋กœ ์ถ”์ฒœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์œ„์™€ ๊ฐ™์ด Gen AI SDK์— ๋Œ€ํ•œ ์˜์กด์„ฑ์„ build.gradle ์— ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”.

Streaming content generation โ€‹

๊ณต์‹ ์˜ˆ์ œ ์ฝ”๋“œ๋Š” ๊นƒํ—ˆ๋ธŒ ๋ฆฌํŒŒ์ง€ํ† ๋ฆฌ์˜ examples ํด๋”์—์„œ ์ฐธ๊ณ ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ €๋Š” models.streamGenerateContent๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ AI ์‘๋‹ต์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ „๋‹ฌํ•˜๋Š” ์˜ˆ์ œ๋ฅผ ์ž‘์„ฑํ•ด๋ณผ๊ฒŒ์š”.

GenAIController.java
java
@PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamGenAI(@RequestBody PromptRequest request) {
    Content content = Content.builder()
            .parts(Part.builder().text(request.getPrompt()).build())
            .build();

    GenerateContentConfig generateContentConfig = GenerateContentConfig.builder()
            .systemInstruction(Content.builder()
                    .parts(Part.builder().text("๋ฐ˜๋“œ์‹œ ํ•œ๊ตญ์–ด๋กœ ๋‹ต๋ณ€ํ•ฉ๋‹ˆ๋‹ค.").build())
                    .build())
            .build();

    Client client = Client.builder().build();
    ResponseStream<GenerateContentResponse> generateContentResponses = client.models.generateContentStream(request.getModel(), List.of(content), generateContentConfig);
    return Flux.fromIterable(generateContentResponses)
            .map(response -> {
                log.info("{} -> {}", response.text(), response.finishReason());
                return response.text();
            });
}

FinishReason์ด STOP์ด๋ฉด ์‘๋‹ต์ด ๋๋‚ฌ๋‹ค๋Š” ์˜๋ฏธ์—์š”!
๊ทธ๋ฆฌ๊ณ  ๋ถ€๋ถ„ ์‘๋‹ต์ด ์˜ฌ๋•Œ์—๋Š” FINISH_REASON_UNSPECIFIED ์ž…๋‹ˆ๋‹ค.

์œ„ stream ์—”๋“œํฌ์ธํŠธ์˜ ์‘๋‹ต์€ text/event-stream;charset=UTF-8 ์ด์—์š”. ์ด stream ์š”์ฒญ์„ ํ”„๋ก ํŠธ์—”๋“œ์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•ด์•ผํ• ๊นŒ์š”? ๋ธŒ๋ผ์šฐ์ €์—์„œ SSE(Server-Sent-Event)๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ EventSource API๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ Fetch ๋˜๋Š” Axios ๋กœ๋„ ์ด๋ฒคํŠธ ์ŠคํŠธ๋ฆผ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”.

genai.js
js
import axios from 'axios';
async function streamGenAI() {
  try {
    const response = await axios.post('http://localhost:8080/api/genai/stream', 
      { prompt: '์•ˆ๋…•ํ•˜์„ธ์š”! ๊ฐ„๋‹จํ•œ ์ธ์‚ฌ๋ง์„ ํ•ด์ฃผ์„ธ์š”.' },
      {
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'text/event-stream'
        },
        responseType: 'stream'
      }
    );

    // ์ŠคํŠธ๋ฆผ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ
    response.data.on('data', (chunk) => {
      const text = chunk.toString();
      console.log('๋ฐ›์€ ์ฒญํฌ:', text);
    });

    response.data.on('end', () => {
      console.log('์ŠคํŠธ๋ฆฌ๋ฐ ์™„๋ฃŒ');
    });

    response.data.on('error', (error) => {
      console.error('์ŠคํŠธ๋ฆฌ๋ฐ ์˜ค๋ฅ˜:', error);
    });

  } catch (error) {
    console.error('์š”์ฒญ ์‹คํŒจ:', error.message);
  }
}

Axios ์—์„œ๋Š” responseType์„ stream์œผ๋กœ ์„ค์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

Spring AI - Google GenAI Chat โ€‹

build.gradle.kts
kts
implementation(platform("org.springframework.ai:spring-ai-bom:1.0.0"))
implementation("org.springframework.ai:spring-ai-openai")
implementation("org.springframework.ai:spring-ai-starter-model-google-genai")

์ตœ์‹  ์Šคํ”„๋ง ๋ถ€ํŠธ ํ”„๋กœ์ ํŠธ๋ผ๋ฉด Spring AI ํ”„๋กœ์ ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Gemini API๋ฅผ ๋” ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์‹ค๋ฌด์—์„œ ๋‹ค๋ฃจ๋Š” ์Šคํ”„๋ง ๋ถ€ํŠธ ํ”„๋กœ์ ํŠธ ๋ฒ„์ „์ด ๋‚ฎ์œผ๋ฉด Google GenAI SDK๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•ด์„œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผํ•ด์š”. ๊ทธ๋ฆฌ๊ณ  ์ด๋ ‡๊ฒŒ SDK๋ฅผ ํ™œ์šฉํ•˜๋ฉด WebClient๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ง์ ‘ HTTP ํ†ต์‹ ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค๋Š” ๊ตฌํ˜„ ๊ณผ์ •์—์„œ์˜ ์‹ค์ˆ˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์–ด์š”.

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

Released under the MIT License.