Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs
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.
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;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);
}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);
}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();
}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();
}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();
}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();
}package com.google.genai.types;
public final class PromptFeedback {
public Optional<String> blockReason();
public Optional<List<SafetyRating>> safetyRatings();
}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());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());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());
});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());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
);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
);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
);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
);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());
}
});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());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();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();
}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();
}
}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());
}
}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());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);
});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;
});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());
}
}
});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();
}
});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
);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
);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);
});
});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 encounteredGenerateContentConfig 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);// 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
);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-genaidocs