CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-google-genai--google-genai

Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs

Overview
Eval results
Files

content-generation.mddocs/

Content Generation

Generate text content using Gemini models with support for synchronous, asynchronous, and streaming responses. The SDK supports multimodal inputs (text, images, video, audio), structured outputs, system instructions, safety settings, and tool use.

Core Imports

import com.google.genai.Models;
import com.google.genai.AsyncModels;
import com.google.genai.ResponseStream;
import com.google.genai.types.GenerateContentResponse;
import com.google.genai.types.GenerateContentConfig;
import com.google.genai.types.Content;
import com.google.genai.types.Part;
import com.google.genai.types.Candidate;
import com.google.genai.types.UsageMetadata;
import java.util.concurrent.CompletableFuture;

Models Service

package com.google.genai;

public final class Models {
  // Synchronous generation
  public GenerateContentResponse generateContent(
      String model,
      String text,
      GenerateContentConfig config);

  public GenerateContentResponse generateContent(
      String model,
      Content content,
      GenerateContentConfig config);

  public GenerateContentResponse generateContent(
      String model,
      List<Content> contents,
      GenerateContentConfig config);

  // Streaming generation
  public ResponseStream<GenerateContentResponse> generateContentStream(
      String model,
      String text,
      GenerateContentConfig config);

  public ResponseStream<GenerateContentResponse> generateContentStream(
      String model,
      Content content,
      GenerateContentConfig config);

  public ResponseStream<GenerateContentResponse> generateContentStream(
      String model,
      List<Content> contents,
      GenerateContentConfig config);
}

Async Models Service

package com.google.genai;

public final class AsyncModels {
  // Asynchronous generation
  public CompletableFuture<GenerateContentResponse> generateContent(
      String model,
      String text,
      GenerateContentConfig config);

  public CompletableFuture<GenerateContentResponse> generateContent(
      String model,
      Content content,
      GenerateContentConfig config);

  public CompletableFuture<GenerateContentResponse> generateContent(
      String model,
      List<Content> contents,
      GenerateContentConfig config);

  // Asynchronous streaming
  public CompletableFuture<ResponseStream<GenerateContentResponse>> generateContentStream(
      String model,
      String text,
      GenerateContentConfig config);

  public CompletableFuture<ResponseStream<GenerateContentResponse>> generateContentStream(
      String model,
      Content content,
      GenerateContentConfig config);

  public CompletableFuture<ResponseStream<GenerateContentResponse>> generateContentStream(
      String model,
      List<Content> contents,
      GenerateContentConfig config);
}

Generate Content Config

package com.google.genai.types;

public final class GenerateContentConfig {
  public static Builder builder();

  // System and instructions
  public Optional<Content> systemInstruction();

  // Generation parameters
  public Optional<Double> temperature();
  public Optional<Double> topP();
  public Optional<Integer> topK();
  public Optional<Integer> candidateCount();
  public Optional<Integer> maxOutputTokens();
  public Optional<List<String>> stopSequences();
  public Optional<Integer> seed();

  // Penalties
  public Optional<Double> presencePenalty();
  public Optional<Double> frequencyPenalty();

  // Safety and filtering
  public Optional<List<SafetySetting>> safetySettings();

  // Tools
  public Optional<List<Tool>> tools();
  public Optional<ToolConfig> toolConfig();
  public Optional<AutomaticFunctionCallingConfig> automaticFunctionCalling();

  // Structured output
  public Optional<String> responseMimeType();
  public Optional<Schema> responseSchema();
  public Optional<JsonNode> responseJsonSchema();

  // Advanced features
  public Optional<Boolean> responseLogprobs();
  public Optional<Integer> logprobs();
  public Optional<String> cachedContent();
  public Optional<List<String>> responseModalities();
  public Optional<String> mediaResolution();
  public Optional<SpeechConfig> speechConfig();
  public Optional<ThinkingConfig> thinkingConfig();
  public Optional<ImageConfig> imageConfig();

  // HTTP options
  public Optional<HttpOptions> httpOptions();
}

Generate Content Response

package com.google.genai.types;

public final class GenerateContentResponse {
  // Response data
  public Optional<List<Candidate>> candidates();
  public Optional<String> modelVersion();
  public Optional<PromptFeedback> promptFeedback();
  public Optional<UsageMetadata> usageMetadata();
  public Optional<String> responseId();
  public Optional<HttpResponse> sdkHttpResponse();
  public Optional<List<Content>> automaticFunctionCallingHistory();

  // Convenience methods
  public String text();
  public Part part(int index);
  public Part part();
}

Candidate

package com.google.genai.types;

public final class Candidate {
  public Optional<Content> content();
  public Optional<String> finishReason();
  public Optional<List<SafetyRating>> safetyRatings();
  public Optional<CitationMetadata> citationMetadata();
  public Optional<Integer> tokenCount();
  public Optional<Integer> index();
  public Optional<GroundingMetadata> groundingMetadata();
  public Optional<Double> avgLogprobs();
  public Optional<LogprobsResult> logprobsResult();
}

Usage Metadata

package com.google.genai.types;

public final class UsageMetadata {
  public Optional<Integer> promptTokenCount();
  public Optional<Integer> candidatesTokenCount();
  public Optional<Integer> totalTokenCount();
  public Optional<Integer> cachedContentTokenCount();
}

Prompt Feedback

package com.google.genai.types;

public final class PromptFeedback {
  public Optional<String> blockReason();
  public Optional<List<SafetyRating>> safetyRatings();
}

Basic Usage

Simple Text Generation

import com.google.genai.Client;
import com.google.genai.types.GenerateContentResponse;

Client client = new Client();

GenerateContentResponse response = client.models.generateContent(
    "gemini-2.0-flash",
    "What is your name?",
    null
);

System.out.println(response.text());

With Configuration

import com.google.genai.types.GenerateContentConfig;

GenerateContentConfig config = GenerateContentConfig.builder()
    .temperature(0.7)
    .maxOutputTokens(1024)
    .topP(0.95)
    .topK(40)
    .build();

GenerateContentResponse response = client.models.generateContent(
    "gemini-2.0-flash",
    "Write a creative story about a robot",
    config
);

System.out.println(response.text());

Accessing Response Details

GenerateContentResponse response = client.models.generateContent(
    "gemini-2.0-flash",
    "Tell me about AI",
    null
);

// Get text (convenience method)
String text = response.text();

// Get first part
Part part = response.part();

// Get specific part by index
Part part2 = response.part(0);

// Access candidates
response.candidates().ifPresent(candidates -> {
    for (Candidate candidate : candidates) {
        System.out.println("Finish reason: " + candidate.finishReason().orElse("N/A"));
        System.out.println("Token count: " + candidate.tokenCount().orElse(0));
    }
});

// Access usage metadata
response.usageMetadata().ifPresent(usage -> {
    System.out.println("Prompt tokens: " + usage.promptTokenCount().orElse(0));
    System.out.println("Response tokens: " + usage.candidatesTokenCount().orElse(0));
    System.out.println("Total tokens: " + usage.totalTokenCount().orElse(0));
});

// Access HTTP response metadata
response.sdkHttpResponse().ifPresent(httpResponse -> {
    System.out.println("Headers: " + httpResponse.headers());
});

Multimodal Input

Text and Image

import com.google.genai.types.Content;
import com.google.genai.types.Part;

Content content = Content.fromParts(
    Part.fromText("Describe this image"),
    Part.fromUri("gs://path/to/image.jpg", "image/jpeg")
);

GenerateContentResponse response = client.models.generateContent(
    "gemini-2.0-flash",
    content,
    null
);

System.out.println(response.text());

With Local Image File

import com.google.genai.types.Image;
import java.nio.file.Files;
import java.nio.file.Paths;

// Read image bytes
byte[] imageBytes = Files.readAllBytes(Paths.get("path/to/image.jpg"));

// Create image from bytes
Image image = Image.builder()
    .imageBytes(imageBytes)
    .mimeType("image/jpeg")
    .build();

Content content = Content.fromParts(
    Part.fromText("What's in this image?"),
    Part.fromImage(image)
);

GenerateContentResponse response = client.models.generateContent(
    "gemini-2.0-flash",
    content,
    null
);

Video Input

import com.google.genai.types.Video;

Video video = Video.builder()
    .videoUri("gs://path/to/video.mp4")
    .mimeType("video/mp4")
    .build();

Content content = Content.fromParts(
    Part.fromText("Summarize this video"),
    Part.fromVideo(video)
);

GenerateContentResponse response = client.models.generateContent(
    "gemini-2.0-flash",
    content,
    null
);

Multiple Content Parts

import com.google.common.collect.ImmutableList;

Content content = Content.builder()
    .parts(ImmutableList.of(
        Part.fromText("Compare these two images:"),
        Part.fromUri("gs://bucket/image1.jpg", "image/jpeg"),
        Part.fromUri("gs://bucket/image2.jpg", "image/jpeg")
    ))
    .role("user")
    .build();

GenerateContentResponse response = client.models.generateContent(
    "gemini-2.0-flash",
    content,
    null
);

System Instructions

import com.google.genai.types.Content;
import com.google.genai.types.Part;
import com.google.genai.types.GenerateContentConfig;

Content systemInstruction = Content.fromParts(
    Part.fromText("You are a helpful assistant that speaks like Shakespeare.")
);

GenerateContentConfig config = GenerateContentConfig.builder()
    .systemInstruction(systemInstruction)
    .build();

GenerateContentResponse response = client.models.generateContent(
    "gemini-2.0-flash",
    "Tell me about the weather",
    config
);

Safety Settings

import com.google.genai.types.SafetySetting;
import com.google.genai.types.HarmCategory;
import com.google.genai.types.HarmBlockThreshold;
import com.google.common.collect.ImmutableList;

ImmutableList<SafetySetting> safetySettings = ImmutableList.of(
    SafetySetting.builder()
        .category(HarmCategory.Known.HARM_CATEGORY_HATE_SPEECH)
        .threshold(HarmBlockThreshold.Known.BLOCK_ONLY_HIGH)
        .build(),
    SafetySetting.builder()
        .category(HarmCategory.Known.HARM_CATEGORY_DANGEROUS_CONTENT)
        .threshold(HarmBlockThreshold.Known.BLOCK_MEDIUM_AND_ABOVE)
        .build(),
    SafetySetting.builder()
        .category(HarmCategory.Known.HARM_CATEGORY_SEXUALLY_EXPLICIT)
        .threshold(HarmBlockThreshold.Known.BLOCK_LOW_AND_ABOVE)
        .build()
);

GenerateContentConfig config = GenerateContentConfig.builder()
    .safetySettings(safetySettings)
    .build();

GenerateContentResponse response = client.models.generateContent(
    "gemini-2.0-flash",
    "Your prompt here",
    config
);

// Check if prompt was blocked
response.promptFeedback().ifPresent(feedback -> {
    if (feedback.blockReason().isPresent()) {
        System.out.println("Blocked: " + feedback.blockReason().get());
    }
});

Structured Output

JSON Schema Response

import com.google.genai.types.Schema;
import com.google.genai.types.Type;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableList;

// Define schema using ImmutableMap
ImmutableMap<String, Object> schema = ImmutableMap.of(
    "type", "object",
    "properties", ImmutableMap.of(
        "recipe_name", ImmutableMap.of("type", "string"),
        "ingredients", ImmutableMap.of(
            "type", "array",
            "items", ImmutableMap.of("type", "string")
        ),
        "steps", ImmutableMap.of(
            "type", "array",
            "items", ImmutableMap.of("type", "string")
        )
    ),
    "required", ImmutableList.of("recipe_name", "ingredients", "steps")
);

GenerateContentConfig config = GenerateContentConfig.builder()
    .responseMimeType("application/json")
    .responseSchema(schema)
    .build();

GenerateContentResponse response = client.models.generateContent(
    "gemini-2.0-flash",
    "Give me a recipe for chocolate chip cookies",
    config
);

// Response will be valid JSON matching the schema
System.out.println(response.text());

Using Schema Builder

import com.google.genai.types.Schema;
import com.google.genai.types.Type;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableList;

Schema schema = Schema.builder()
    .type(Type.Known.OBJECT)
    .properties(ImmutableMap.of(
        "name", Schema.builder()
            .type(Type.Known.STRING)
            .description("Person's name")
            .build(),
        "age", Schema.builder()
            .type(Type.Known.INTEGER)
            .description("Person's age")
            .build()
    ))
    .required(ImmutableList.of("name", "age"))
    .build();

GenerateContentConfig config = GenerateContentConfig.builder()
    .responseMimeType("application/json")
    .responseSchema(schema)
    .build();

Streaming

Basic Streaming

import com.google.genai.ResponseStream;

try (ResponseStream<GenerateContentResponse> stream =
    client.models.generateContentStream(
        "gemini-2.0-flash",
        "Tell me a long story",
        null)) {

    for (GenerateContentResponse chunk : stream) {
        System.out.print(chunk.text());
    }
    System.out.println();
}

Streaming with Configuration

GenerateContentConfig config = GenerateContentConfig.builder()
    .temperature(0.9)
    .maxOutputTokens(2048)
    .build();

try (ResponseStream<GenerateContentResponse> stream =
    client.models.generateContentStream(
        "gemini-2.0-flash",
        "Write a detailed essay about AI",
        config)) {

    for (GenerateContentResponse chunk : stream) {
        // Process each chunk as it arrives
        System.out.print(chunk.text());
        System.out.flush();
    }
}

Streaming with Multimodal Input

import com.google.genai.types.Content;
import com.google.genai.types.Part;

Content content = Content.fromParts(
    Part.fromText("Describe this image in detail"),
    Part.fromUri("gs://bucket/image.jpg", "image/jpeg")
);

try (ResponseStream<GenerateContentResponse> stream =
    client.models.generateContentStream("gemini-2.0-flash", content, null)) {

    for (GenerateContentResponse chunk : stream) {
        System.out.print(chunk.text());
    }
}

Asynchronous Generation

Basic Async

import java.util.concurrent.CompletableFuture;

CompletableFuture<GenerateContentResponse> future =
    client.async.models.generateContent(
        "gemini-2.0-flash",
        "What is AI?",
        null
    );

// Use thenAccept for callback
future.thenAccept(response -> {
    System.out.println("Async response: " + response.text());
});

// Or block and wait
GenerateContentResponse response = future.join();
System.out.println(response.text());

Multiple Async Requests

import java.util.concurrent.CompletableFuture;
import java.util.List;
import java.util.stream.Collectors;

List<CompletableFuture<GenerateContentResponse>> futures = List.of(
    client.async.models.generateContent("gemini-2.0-flash", "What is AI?", null),
    client.async.models.generateContent("gemini-2.0-flash", "What is ML?", null),
    client.async.models.generateContent("gemini-2.0-flash", "What is DL?", null)
);

// Wait for all to complete
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
    .thenRun(() -> {
        List<String> responses = futures.stream()
            .map(CompletableFuture::join)
            .map(GenerateContentResponse::text)
            .collect(Collectors.toList());

        responses.forEach(System.out::println);
    });

Async with Error Handling

CompletableFuture<GenerateContentResponse> future =
    client.async.models.generateContent(
        "gemini-2.0-flash",
        "Your prompt",
        null
    );

future
    .thenAccept(response -> {
        System.out.println("Success: " + response.text());
    })
    .exceptionally(throwable -> {
        System.err.println("Error: " + throwable.getMessage());
        return null;
    });

Async Streaming

CompletableFuture<ResponseStream<GenerateContentResponse>> futureStream =
    client.async.models.generateContentStream(
        "gemini-2.0-flash",
        "Tell a story",
        null
    );

futureStream.thenAccept(stream -> {
    try (ResponseStream<GenerateContentResponse> s = stream) {
        for (GenerateContentResponse chunk : s) {
            System.out.print(chunk.text());
        }
    }
});

Multiple Candidates

GenerateContentConfig config = GenerateContentConfig.builder()
    .candidateCount(3) // Request 3 different responses
    .temperature(0.9)
    .build();

GenerateContentResponse response = client.models.generateContent(
    "gemini-2.0-flash",
    "Write a creative opening line for a story",
    config
);

// Access all candidates
response.candidates().ifPresent(candidates -> {
    for (int i = 0; i < candidates.size(); i++) {
        Candidate candidate = candidates.get(i);
        System.out.println("Candidate " + (i + 1) + ":");
        candidate.content().ifPresent(content -> {
            content.parts().ifPresent(parts -> {
                parts.forEach(part -> {
                    part.text().ifPresent(System.out::println);
                });
            });
        });
        System.out.println();
    }
});

Advanced Features

Response Modalities

import com.google.common.collect.ImmutableList;

GenerateContentConfig config = GenerateContentConfig.builder()
    .responseModalities(ImmutableList.of("TEXT", "IMAGE"))
    .build();

GenerateContentResponse response = client.models.generateContent(
    "gemini-2.0-flash",
    "Create an image of a sunset",
    config
);

Thinking Configuration

import com.google.genai.types.ThinkingConfig;

GenerateContentConfig config = GenerateContentConfig.builder()
    .thinkingConfig(ThinkingConfig.builder()
        .thinkingBudget(0) // Disable thinking mode
        .build())
    .build();

GenerateContentResponse response = client.models.generateContent(
    "gemini-2.0-flash",
    "Solve this problem",
    config
);

Log Probabilities

GenerateContentConfig config = GenerateContentConfig.builder()
    .responseLogprobs(true)
    .logprobs(5) // Return top 5 log probabilities per token
    .build();

GenerateContentResponse response = client.models.generateContent(
    "gemini-2.0-flash",
    "Complete this: The quick brown",
    config
);

// Access log probabilities
response.candidates().ifPresent(candidates -> {
    candidates.get(0).logprobsResult().ifPresent(logprobs -> {
        System.out.println("Log probabilities: " + logprobs);
    });
});

Stop Sequences

import com.google.common.collect.ImmutableList;

GenerateContentConfig config = GenerateContentConfig.builder()
    .stopSequences(ImmutableList.of("\n\n", "END", "###"))
    .build();

GenerateContentResponse response = client.models.generateContent(
    "gemini-2.0-flash",
    "Write a paragraph",
    config
);
// Generation stops when any stop sequence is encountered

Seed for Reproducibility

GenerateContentConfig config = GenerateContentConfig.builder()
    .seed(42)
    .temperature(0.0)
    .build();

// Same prompt with same seed should produce similar results
GenerateContentResponse response1 = client.models.generateContent(
    "gemini-2.0-flash", "Tell me a fact", config);
GenerateContentResponse response2 = client.models.generateContent(
    "gemini-2.0-flash", "Tell me a fact", config);

Using Cached Content

// First create cached content (see caching.md)
String cachedContentName = "cachedContents/abc123";

GenerateContentConfig config = GenerateContentConfig.builder()
    .cachedContent(cachedContentName)
    .build();

GenerateContentResponse response = client.models.generateContent(
    "gemini-2.0-flash",
    "Based on the cached context, answer this question",
    config
);

Response Stream Class

package com.google.genai;

public final class ResponseStream<T> implements Iterable<T>, AutoCloseable {
  public Iterator<T> iterator();
  public void close();
}

The ResponseStream implements both Iterable<T> and AutoCloseable, making it suitable for use in try-with-resources blocks and foreach loops.

Install with Tessl CLI

npx tessl i tessl/maven-com-google-genai--google-genai

docs

batch-operations.md

caching.md

chat-sessions.md

client-configuration.md

content-generation.md

embeddings-tokens.md

error-handling.md

file-search-stores.md

files-management.md

image-operations.md

index.md

live-sessions.md

model-tuning.md

operations.md

tools-functions.md

types-reference.md

video-generation.md

tile.json