diff --git a/google-ai-gemini-examples/pom.xml b/google-ai-gemini-examples/pom.xml
new file mode 100644
index 00000000..e66b1ec5
--- /dev/null
+++ b/google-ai-gemini-examples/pom.xml
@@ -0,0 +1,59 @@
+
+
This example shows how to: + *
Requires the {@code GOOGLE_AI_GEMINI_API_KEY} environment variable to be set or by other means to get the API key. + */ +public class Example01_SimpleChat { + public static void main(String[] args) { + String apiKey = System.getenv("GOOGLE_AI_GEMINI_API_KEY"); + ChatModel model = GoogleAiGeminiChatModel.builder() + .apiKey(apiKey) + .modelName("gemini-2.5-flash-lite") + .build(); + + String response = model.chat("What is the capital of France?"); + + System.out.println(response); + } +} \ No newline at end of file diff --git a/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example02_StreamingChat.java b/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example02_StreamingChat.java new file mode 100644 index 00000000..f3cd0c6b --- /dev/null +++ b/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example02_StreamingChat.java @@ -0,0 +1,66 @@ +package dev.langchain4j.example.gemini; + +import dev.langchain4j.model.chat.response.ChatResponse; +import dev.langchain4j.model.chat.response.StreamingChatResponseHandler; +import dev.langchain4j.model.googleai.GoogleAiGeminiStreamingChatModel; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +import static java.util.concurrent.TimeUnit.SECONDS; + +/** + * Demonstrates streaming chat responses with Google AI Gemini. + * + *
This example shows how to: + *
Requires the {@code GOOGLE_AI_GEMINI_API_KEY} environment variable to be set.
+ */
+public class Example02_StreamingChat {
+ static class WaitingChatResponseHandler implements StreamingChatResponseHandler {
+ // Future used to wait for a response
+ private final CompletableFuture This example shows how to:
+ * Requires the {@code GOOGLE_AI_GEMINI_API_KEY} environment variable to be set.
+ *
+ * Learn response = model.embed("The quick brown fox jumps over the lazy dog.");
+
+ Embedding embedding = response.content();
+
+ System.out.println("Embedding dimension: " + embedding.dimension());
+ System.out.println("First 10 values: ");
+ for (int i = 0; i < 10; i++) {
+ System.out.printf(" [%d]: %.6f%n", i, embedding.vector()[i]);
+ }
+ }
+}
\ No newline at end of file
diff --git a/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example04_TokenCounting.java b/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example04_TokenCounting.java
new file mode 100644
index 00000000..4e36b33f
--- /dev/null
+++ b/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example04_TokenCounting.java
@@ -0,0 +1,47 @@
+package dev.langchain4j.example.gemini;
+
+import dev.langchain4j.data.message.SystemMessage;
+import dev.langchain4j.data.message.UserMessage;
+import dev.langchain4j.model.googleai.GoogleAiGeminiTokenCountEstimator;
+
+import java.util.List;
+
+/**
+ * Demonstrates token counting with Google AI Gemini.
+ *
+ * This example shows how to:
+ * Requires the {@code GOOGLE_AI_GEMINI_API_KEY} environment variable to be set.
+ *
+ * Learn more This example shows how to:
+ * Requires the {@code GOOGLE_AI_GEMINI_API_KEY} environment variable to be set.
+ *
+ * Learn more This example shows how to:
+ * Requires the {@code GOOGLE_AI_GEMINI_API_KEY} environment variable to be set.
+ *
+ * Learn more This example shows how to:
+ * Task types include:
+ * Requires the {@code GOOGLE_AI_GEMINI_API_KEY} environment variable to be set.
+ *
+ * Learn more This example shows how to:
+ * This pattern is useful for processing large files or reusing the same file
+ * across multiple chat requests without re-uploading.
+ *
+ * Requires the {@code GOOGLE_AI_GEMINI_API_KEY} environment variable to be set.
+ */
+public class Example08_FileUpload {
+
+ public static void main(String[] args) throws Exception {
+ String apiKey = System.getenv("GOOGLE_AI_GEMINI_API_KEY");
+
+ GeminiFiles geminiFiles = GeminiFiles.builder()
+ .apiKey(apiKey)
+ .build();
+
+ ChatModel model = GoogleAiGeminiChatModel.builder()
+ .apiKey(apiKey)
+ .modelName("gemini-2.5-flash-lite")
+ .logRequestsAndResponses(true)
+ .build();
+
+ // Create a sample text file to upload
+ var file = Path.of(Example08_FileUpload.class.getClassLoader().getResource("q4-planning.pdf").toURI());
+
+ GeminiFile uploadedFile = null;
+ try {
+ // Upload the file
+ System.out.println("Uploading file...");
+ uploadedFile = geminiFiles.uploadFile(file, "meeting-notes.txt");
+
+ // Wait for processing
+ while (uploadedFile.isProcessing()) {
+ Thread.sleep(500);
+ uploadedFile = geminiFiles.getMetadata(uploadedFile.name());
+ }
+
+ if (uploadedFile.isFailed()) {
+ System.err.println("File processing failed!");
+ return;
+ }
+
+ System.out.println("File uploaded successfully: " + uploadedFile.uri());
+
+ // Use the uploaded file in a chat request
+ UserMessage userMessage = UserMessage.from(
+ PdfFileContent.from(uploadedFile.uri()),
+ TextContent.from("Summarize this document and list the action items with their owners.")
+ );
+
+ System.out.println("\nAsking Gemini to analyze the uploaded file...\n");
+
+ ChatResponse response = model.chat(userMessage);
+
+ System.out.println("Response:");
+ System.out.println(response.aiMessage().text());
+
+ } finally {
+ // Clean up: delete uploaded file and local temp file
+ if (uploadedFile != null) {
+ geminiFiles.deleteFile(uploadedFile.name());
+ System.out.println("\nUploaded file deleted.");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example09_MultimodalChat.java b/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example09_MultimodalChat.java
new file mode 100644
index 00000000..d353b168
--- /dev/null
+++ b/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example09_MultimodalChat.java
@@ -0,0 +1,47 @@
+package dev.langchain4j.example.gemini;
+
+import dev.langchain4j.data.message.ImageContent;
+import dev.langchain4j.data.message.TextContent;
+import dev.langchain4j.data.message.UserMessage;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.chat.response.ChatResponse;
+import dev.langchain4j.model.googleai.GoogleAiGeminiChatModel;
+
+/**
+ * Demonstrates multimodal chat capabilities with Google AI Gemini.
+ *
+ * This example shows how to:
+ * Gemini supports various multimodal inputs including images, audio, video, and PDFs.
+ *
+ * Requires the {@code GOOGLE_AI_GEMINI_API_KEY} environment variable to be set.
+ */
+public class Example09_MultimodalChat {
+
+ public static void main(String[] args) {
+ ChatModel model = GoogleAiGeminiChatModel.builder()
+ .apiKey(System.getenv("GOOGLE_AI_GEMINI_API_KEY"))
+ .modelName("gemini-2.5-flash-lite")
+ .build();
+
+ // Example using a public image URL
+ String imageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg";
+
+ UserMessage userMessage = UserMessage.from(
+ ImageContent.from(imageUrl),
+ TextContent.from("What do you see in this image? Describe it in detail.")
+ );
+
+ System.out.println("Sending image with question to Gemini...\n");
+
+ ChatResponse response = model.chat(userMessage);
+
+ System.out.println("Response:");
+ System.out.println(response.aiMessage().text());
+ }
+}
\ No newline at end of file
diff --git a/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example10_ChatWithThinking.java b/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example10_ChatWithThinking.java
new file mode 100644
index 00000000..01f2d59b
--- /dev/null
+++ b/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example10_ChatWithThinking.java
@@ -0,0 +1,57 @@
+package dev.langchain4j.example.gemini;
+
+import dev.langchain4j.data.message.UserMessage;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.chat.response.ChatResponse;
+import dev.langchain4j.model.googleai.GeminiThinkingConfig;
+import dev.langchain4j.model.googleai.GoogleAiGeminiChatModel;
+
+/**
+ * Demonstrates the thinking/reasoning capability of Google AI Gemini.
+ *
+ * This example shows how to:
+ * Thinking mode allows the model to perform step-by-step reasoning before
+ * providing a final answer, which is especially useful for complex problems.
+ *
+ * Requires the {@code GOOGLE_AI_GEMINI_API_KEY} environment variable to be set.
+ */
+public class Example10_ChatWithThinking {
+
+ public static void main(String[] args) {
+ ChatModel model = GoogleAiGeminiChatModel.builder()
+ .apiKey(System.getenv("GOOGLE_AI_GEMINI_API_KEY"))
+ .modelName("gemini-2.5-flash-lite")
+ .thinkingConfig(GeminiThinkingConfig.builder()
+ .thinkingBudget(2048)
+ .build())
+ .returnThinking(true)
+ .build();
+
+ String problem = """
+ You are in a room with three light switches, each controlling one of three light bulbs in another room
+ you cannot see from where you are. You can flip the switches as many times as you want, but you can
+ only enter the room with the bulbs once. How do you determine which switch controls which bulb?
+ """;
+
+ System.out.println("Problem: " + problem);
+ System.out.println("Asking Gemini with thinking enabled...\n");
+
+ ChatResponse response = model.chat(UserMessage.from(problem));
+
+ // Display thinking process if available
+ if (response.aiMessage().thinking() != null) {
+ System.out.println("=== Thinking Process ===");
+ System.out.println(response.aiMessage().thinking());
+ System.out.println();
+ }
+
+ System.out.println("=== Final Answer ===");
+ System.out.println(response.aiMessage().text());
+ }
+}
\ No newline at end of file
diff --git a/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example11_ChatWithSafetySettings.java b/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example11_ChatWithSafetySettings.java
new file mode 100644
index 00000000..c90b67fe
--- /dev/null
+++ b/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example11_ChatWithSafetySettings.java
@@ -0,0 +1,79 @@
+package dev.langchain4j.example.gemini;
+
+import dev.langchain4j.data.message.UserMessage;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.chat.response.ChatResponse;
+import dev.langchain4j.model.googleai.GoogleAiGeminiChatModel;
+import dev.langchain4j.model.googleai.GeminiHarmBlockThreshold;
+import dev.langchain4j.model.googleai.GeminiHarmCategory;
+import dev.langchain4j.model.googleai.GeminiSafetySetting;
+
+import java.util.List;
+
+/**
+ * Demonstrates configuring safety settings with Google AI Gemini.
+ *
+ * This example shows how to:
+ * Available harm categories:
+ * Available thresholds (from most to least restrictive):
+ * Requires the {@code GOOGLE_AI_GEMINI_API_KEY} environment variable to be set.
+ *
+ * Learn more Batch processing is ideal for large-scale, non-urgent tasks, offering:
+ * This example shows how to:
+ * Requires the {@code GOOGLE_AI_GEMINI_API_KEY} environment variable to be set.
+ */
+public class Example12_BatchChatInline {
+
+ public static void main(String[] args) throws Exception {
+ var batchModel = GoogleAiGeminiBatchChatModel.builder()
+ .apiKey(System.getenv("GOOGLE_AI_GEMINI_API_KEY"))
+ .modelName("gemini-2.5-flash-lite")
+ .logRequestsAndResponses(true)
+ .build();
+
+ var requests = List.of(
+ ChatRequest.builder()
+ .modelName("gemini-2.5-flash-lite")
+ .messages(UserMessage.from("What is the capital of France?"))
+ .build(),
+ ChatRequest.builder()
+ .modelName("gemini-2.5-flash-lite")
+ .messages(UserMessage.from("What is the capital of Japan?"))
+ .build(),
+ ChatRequest.builder()
+ .modelName("gemini-2.5-flash-lite")
+ .messages(UserMessage.from("What is the capital of Brazil?"))
+ .build()
+ );
+
+ System.out.println("Submitting batch with " + requests.size() + " requests...");
+
+ BatchResponse> response = batchModel.createBatchInline("capitals-batch", 0L, requests);
+ BatchName batchName = getBatchName(response);
+
+ System.out.println("Batch created: " + batchName.value());
+ System.out.println("Polling for completion...");
+
+ // Poll until complete
+ do {
+ Thread.sleep(5000);
+ response = batchModel.retrieveBatchResults(batchName);
+ System.out.println(" Status: " + response.getClass().getSimpleName());
+ } while (response instanceof BatchIncomplete);
+
+ // Process results
+ if (response instanceof BatchSuccess> success) {
+ System.out.println("\nBatch completed successfully!");
+ System.out.println("Results:");
+
+ var results = success.responses();
+ for (int i = 0; i < results.size(); i++) {
+ var chatResponse = (dev.langchain4j.model.chat.response.ChatResponse) results.get(i);
+ System.out.println(" " + (i + 1) + ". " + chatResponse.aiMessage().text());
+ }
+ } else {
+ System.err.println("Batch failed: " + response);
+ }
+
+ // Clean up
+ batchModel.deleteBatchJob(batchName);
+ System.out.println("\nBatch job deleted.");
+ }
+
+ private static BatchName getBatchName(BatchResponse> response) {
+ if (response instanceof BatchSuccess> success) {
+ return success.batchName();
+ } else if (response instanceof BatchIncomplete incomplete) {
+ return incomplete.batchName();
+ } else {
+ throw new IllegalStateException("Unexpected response type: " + response);
+ }
+ }
+
+ private static GoogleAiGeminiBatchChatModel createBatchModel() throws Exception {
+ // Use reflection to access the non-public builder() method
+ Method builderMethod = GoogleAiGeminiBatchChatModel.class.getDeclaredMethod("builder");
+ builderMethod.setAccessible(true);
+ Object builder = builderMethod.invoke(null);
+
+ Class> builderClass = builder.getClass();
+
+ Method apiKeyMethod = builderClass.getMethod("apiKey", String.class);
+ builder = apiKeyMethod.invoke(builder, System.getenv("GOOGLE_AI_GEMINI_API_KEY"));
+
+ Method modelNameMethod = builderClass.getMethod("modelName", String.class);
+ builder = modelNameMethod.invoke(builder, "gemini-2.5-flash-lite");
+
+ Method logMethodName = builderClass.getMethod("logRequestsAndResponses", Boolean.class);
+ builder = logMethodName.invoke(builder, true);
+
+ Method buildMethod = builderClass.getMethod("build");
+ return (GoogleAiGeminiBatchChatModel) buildMethod.invoke(builder);
+ }
+}
\ No newline at end of file
diff --git a/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example13_BatchEmbeddingInline.java b/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example13_BatchEmbeddingInline.java
new file mode 100644
index 00000000..4dbf6d0c
--- /dev/null
+++ b/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example13_BatchEmbeddingInline.java
@@ -0,0 +1,98 @@
+package dev.langchain4j.example.gemini;
+
+import dev.langchain4j.data.embedding.Embedding;
+import dev.langchain4j.data.segment.TextSegment;
+import dev.langchain4j.model.googleai.BatchRequestResponse.BatchIncomplete;
+import dev.langchain4j.model.googleai.BatchRequestResponse.BatchName;
+import dev.langchain4j.model.googleai.BatchRequestResponse.BatchResponse;
+import dev.langchain4j.model.googleai.BatchRequestResponse.BatchSuccess;
+import dev.langchain4j.model.googleai.GoogleAiGeminiBatchEmbeddingModel;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * Demonstrates inline batch embedding processing with Google AI Gemini.
+ *
+ * Batch processing is ideal for large-scale, non-urgent embedding tasks, offering:
+ * This example shows how to:
+ * Requires the {@code GOOGLE_AI_GEMINI_API_KEY} environment variable to be set.
+ */
+public class Example13_BatchEmbeddingInline {
+
+ public static void main(String[] args) throws Exception {
+ GoogleAiGeminiBatchEmbeddingModel batchModel =
+ GoogleAiGeminiBatchEmbeddingModel.builder().apiKey(System.getenv("GOOGLE_AI_GEMINI_API_KEY"))
+ .modelName("gemini-embedding-001")
+ .logRequestsAndResponses(true)
+ .build();
+
+ List File-based batching is ideal for very large batches that exceed the 20MB inline limit.
+ * The workflow is:
+ * Benefits:
+ * Requires the {@code GOOGLE_AI_GEMINI_API_KEY} environment variable to be set.
+ */
+public class Example14_BatchChatFromFile {
+
+ public static void main(String[] args) throws Exception {
+ var apiKey = System.getenv("GOOGLE_AI_GEMINI_API_KEY");
+
+ var batchModel = GoogleAiGeminiBatchChatModel.builder()
+ .apiKey(System.getenv("GOOGLE_AI_GEMINI_API_KEY"))
+ .modelName("gemini-2.5-flash-lite")
+ .logRequestsAndResponses(true)
+ .build();
+ var geminiFiles = GeminiFiles.builder().apiKey(apiKey).build();
+
+ var requests = List.of(
+ new BatchFileRequest<>("solar-system",
+ ChatRequest.builder()
+ .messages(UserMessage.from("What is the largest planet in our solar system?"))
+ .build()),
+ new BatchFileRequest<>("speed-of-light",
+ ChatRequest.builder()
+ .messages(UserMessage.from("What is the speed of light in km/s?"))
+ .build()),
+ new BatchFileRequest<>("romeo-juliet",
+ ChatRequest.builder()
+ .messages(UserMessage.from("Who wrote Romeo and Juliet?"))
+ .build()),
+ new BatchFileRequest<>("water",
+ ChatRequest.builder()
+ .messages(UserMessage.from("What is the chemical formula for water?"))
+ .build())
+ );
+
+ // Step 1: Write requests to a local JSONL file
+ var tempFile = Files.createTempFile("batch-requests-", ".jsonl");
+ var writer = JsonLinesWriters.streaming(tempFile);
+ System.out.println("Writing batch requests to: " + tempFile);
+ batchModel.writeBatchToFile(writer, requests);
+
+ // Verify JSONL content
+ System.out.println("JSONL content:");
+ Files.readAllLines(tempFile).forEach(line -> System.out.println(" " + line));
+
+ // Step 2: Upload the file using Gemini Files API
+ System.out.println("\nUploading file to Gemini Files API...");
+ var uploadedFile = geminiFiles.uploadFile(tempFile, "batch-requests.jsonl");
+ System.out.println("Uploaded file URI: " + uploadedFile.uri());
+ System.out.println("File state: " + uploadedFile.state());
+
+ // Wait for file to become ACTIVE
+ while (uploadedFile.isProcessing()) {
+ System.out.println(" Waiting for file to become active...");
+ Thread.sleep(2000);
+ uploadedFile = geminiFiles.getMetadata(uploadedFile.name());
+ }
+
+ if (!uploadedFile.isActive()) {
+ System.err.println("File upload failed: " + uploadedFile.state());
+ return;
+ }
+
+ System.out.println("File is now ACTIVE");
+
+ // Step 3: Create batch job from the uploaded file
+ System.out.println("\nCreating batch job from uploaded file...");
+ BatchResponse> response = batchModel.createBatchFromFile("file-based-batch", uploadedFile);
+ BatchName batchName = getBatchName(response);
+
+ System.out.println("Batch created: " + batchName.value());
+ System.out.println("Polling for completion...");
+
+ // Step 4: Poll until complete
+ do {
+ Thread.sleep(5000);
+ response = batchModel.retrieveBatchResults(batchName);
+ System.out.println(" Status: " + response.getClass().getSimpleName());
+ } while (response instanceof BatchIncomplete);
+
+ // Step 5: Process results
+ if (response instanceof BatchSuccess> success) {
+ System.out.println("\nBatch completed successfully!");
+ System.out.println("Results:");
+
+ var results = success.responses();
+ for (int i = 0; i < results.size(); i++) {
+ var chatResponse = (ChatResponse) results.get(i);
+ System.out.println(" " + (i + 1) + ". " + chatResponse.aiMessage().text());
+ }
+ } else {
+ System.err.println("Batch failed: " + response);
+ }
+
+ // Clean up
+ System.out.println("\nCleaning up...");
+ batchModel.deleteBatchJob(batchName);
+ System.out.println("Batch job deleted.");
+
+ geminiFiles.deleteFile(uploadedFile.name());
+ System.out.println("Uploaded file deleted.");
+
+ Files.deleteIfExists(tempFile);
+ System.out.println("Local temp file deleted.");
+ }
+
+ private static BatchName getBatchName(BatchResponse> response) {
+ if (response instanceof BatchSuccess> success) {
+ return success.batchName();
+ } else if (response instanceof BatchIncomplete incomplete) {
+ return incomplete.batchName();
+ } else {
+ throw new IllegalStateException("Unexpected response type: " + response);
+ }
+ }
+}
\ No newline at end of file
diff --git a/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example15_BatchEmbedFromFile.java b/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example15_BatchEmbedFromFile.java
new file mode 100644
index 00000000..e6d82763
--- /dev/null
+++ b/google-ai-gemini-examples/src/main/java/dev/langchain4j/example/gemini/Example15_BatchEmbedFromFile.java
@@ -0,0 +1,141 @@
+package dev.langchain4j.example.gemini;
+
+import dev.langchain4j.data.embedding.Embedding;
+import dev.langchain4j.data.segment.TextSegment;
+import dev.langchain4j.model.googleai.BatchRequestResponse.*;
+import dev.langchain4j.model.googleai.GeminiFiles;
+import dev.langchain4j.model.googleai.GoogleAiGeminiBatchEmbeddingModel;
+import dev.langchain4j.model.googleai.jsonl.JsonLinesWriters;
+
+import java.nio.file.Files;
+import java.util.List;
+
+/**
+ * Demonstrates file-based batch embedding processing with Google AI Gemini.
+ *
+ * File-based batching is ideal for very large batches that exceed the 20MB inline limit.
+ * The workflow is:
+ * Benefits:
+ * Requires the {@code GOOGLE_AI_GEMINI_API_KEY} environment variable to be set.
+ */
+public class Example15_BatchEmbedFromFile {
+
+ public static void main(String[] args) throws Exception {
+ var apiKey = System.getenv("GOOGLE_AI_GEMINI_API_KEY");
+
+ GoogleAiGeminiBatchEmbeddingModel batchModel = GoogleAiGeminiBatchEmbeddingModel.builder()
+ .apiKey(apiKey)
+ .modelName("gemini-embedding-001")
+ .logRequestsAndResponses(true)
+ .build();
+
+ var geminiFiles = GeminiFiles.builder().apiKey(apiKey).build();
+
+ var segments = List.of(
+ new BatchFileRequest<>("ai-text", TextSegment.from("Artificial intelligence is transforming industries worldwide.")),
+ new BatchFileRequest<>("ml-text", TextSegment.from("Machine learning enables computers to learn from data.")),
+ new BatchFileRequest<>("nlp-text", TextSegment.from("Natural language processing helps machines understand human language.")),
+ new BatchFileRequest<>("dl-text", TextSegment.from("Deep learning uses neural networks with multiple layers."))
+ );
+
+ // Step 1: Write requests to a local JSONL file
+ var tempFile = Files.createTempFile("batch-embed-requests-", ".jsonl");
+ var writer = JsonLinesWriters.streaming(tempFile);
+ System.out.println("Writing batch embedding requests to: " + tempFile);
+ batchModel.writeBatchToFile(writer, segments);
+
+ // Verify JSONL content
+ System.out.println("JSONL content:");
+ Files.readAllLines(tempFile).forEach(line -> System.out.println(" " + line));
+
+ // Step 2: Upload the file using Gemini Files API
+ System.out.println("\nUploading file to Gemini Files API...");
+ var uploadedFile = geminiFiles.uploadFile(tempFile, "batch-embed-requests.jsonl");
+ System.out.println("Uploaded file URI: " + uploadedFile.uri());
+ System.out.println("File state: " + uploadedFile.state());
+
+ // Wait for file to become ACTIVE
+ while (uploadedFile.isProcessing()) {
+ System.out.println(" Waiting for file to become active...");
+ Thread.sleep(2000);
+ uploadedFile = geminiFiles.getMetadata(uploadedFile.name());
+ }
+
+ if (!uploadedFile.isActive()) {
+ System.err.println("File upload failed: " + uploadedFile.state());
+ return;
+ }
+
+ System.out.println("File is now ACTIVE");
+
+ // Step 3: Create batch job from the uploaded file
+ System.out.println("\nCreating batch embedding job from uploaded file...");
+ BatchResponse> response = batchModel.createBatchFromFile("file-based-embedding-batch", uploadedFile);
+ BatchName batchName = getBatchName(response);
+
+ System.out.println("Batch created: " + batchName.value());
+ System.out.println("Polling for completion...");
+
+ // Step 4: Poll until complete
+ do {
+ Thread.sleep(5000);
+ response = batchModel.retrieveBatchResults(batchName);
+ System.out.println(" Status: " + response.getClass().getSimpleName());
+ } while (response instanceof BatchIncomplete);
+
+ // Step 5: Process results
+ if (response instanceof BatchSuccess> success) {
+ System.out.println("\nBatch completed successfully!");
+ System.out.println("Results:");
+
+ var results = success.responses();
+ for (int i = 0; i < results.size(); i++) {
+ var embedding = (Embedding) results.get(i);
+ System.out.println("\n " + (i + 1) + ". " + segments.get(i).key());
+ System.out.println(" Dimension: " + embedding.dimension());
+ System.out.print(" Vector (first 5 values): [");
+ for (int j = 0; j < 5 && j < embedding.vector().length; j++) {
+ System.out.printf("%.6f%s", embedding.vector()[j], j < 4 ? ", " : "");
+ }
+ System.out.println("]");
+ }
+ } else {
+ System.err.println("Batch failed: " + response);
+ }
+
+ // Clean up
+ System.out.println("\nCleaning up...");
+ batchModel.deleteBatchJob(batchName);
+ System.out.println("Batch job deleted.");
+
+ geminiFiles.deleteFile(uploadedFile.name());
+ System.out.println("Uploaded file deleted.");
+
+ Files.deleteIfExists(tempFile);
+ System.out.println("Local temp file deleted.");
+ }
+
+ private static BatchName getBatchName(BatchResponse> response) {
+ if (response instanceof BatchSuccess> success) {
+ return success.batchName();
+ } else if (response instanceof BatchIncomplete> incomplete) {
+ return incomplete.batchName();
+ } else {
+ throw new IllegalStateException("Unexpected response type: " + response);
+ }
+ }
+}
\ No newline at end of file
diff --git a/google-ai-gemini-examples/src/main/resources/q4-planning.pdf b/google-ai-gemini-examples/src/main/resources/q4-planning.pdf
new file mode 100644
index 00000000..29539cd1
Binary files /dev/null and b/google-ai-gemini-examples/src/main/resources/q4-planning.pdf differ
diff --git a/pom.xml b/pom.xml
index 3cf26612..76268b5a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,11 +18,15 @@
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *