From 20a89e4cfddab4b420d7bd4d0632c376557787bd Mon Sep 17 00:00:00 2001 From: cfloress Date: Thu, 4 Dec 2025 18:28:26 -0300 Subject: [PATCH 1/4] genai: added controlled generation samples --- ...ntrolledGenerationWithEnumClassSchema.java | 93 +++++++++++++++ ...ontrolledGenerationWithNullableSchema.java | 109 ++++++++++++++++++ ...ontrolledGenerationWithResponseSchema.java | 101 ++++++++++++++++ ...rolledGenerationWithEnumClassSchemaIT.java | 72 ++++++++++++ ...trolledGenerationWithNullableSchemaIT.java | 84 ++++++++++++++ ...trolledGenerationWithResponseSchemaIT.java | 70 +++++++++++ 6 files changed, 529 insertions(+) create mode 100644 genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchema.java create mode 100644 genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithNullableSchema.java create mode 100644 genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithResponseSchema.java create mode 100644 genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchemaIT.java create mode 100644 genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithNullableSchemaIT.java create mode 100644 genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithResponseSchemaIT.java diff --git a/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchema.java b/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchema.java new file mode 100644 index 00000000000..01463abdf89 --- /dev/null +++ b/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchema.java @@ -0,0 +1,93 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package genai.controlledgeneration; + +// [START googlegenaisdk_ctrlgen_with_enum_class_schema] + +import com.google.genai.Client; +import com.google.genai.types.GenerateContentConfig; +import com.google.genai.types.GenerateContentResponse; +import com.google.genai.types.HttpOptions; +import com.google.genai.types.Schema; +import com.google.genai.types.Type; + +import java.util.List; + +public class ControlledGenerationWithEnumClassSchema { + + // Enum mirroring the Python sample + public enum InstrumentClass { + PERCUSSION("Percussion"), + STRING("String"), + WOODWIND("Woodwind"), + BRASS("Brass"), + KEYBOARD("Keyboard"); + + private final String value; + + InstrumentClass(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + public static void main(String[] args) { + String modelId = "gemini-2.5-flash"; + String prompt = "What type of instrument is a guitar?"; + generateContent(modelId, prompt); + } + + public static String generateContent(String modelId, String contents) { + + try (Client client = + Client.builder() + .location("global") + .vertexAI(true) + .httpOptions(HttpOptions.builder().apiVersion("v1").build()) + .build()) { + + // Build schema using enum values + Schema responseSchema = + Schema.builder() + .type(Type.Known.STRING) + .enum_(List.of( + InstrumentClass.PERCUSSION.getValue(), + InstrumentClass.STRING.getValue(), + InstrumentClass.WOODWIND.getValue(), + InstrumentClass.BRASS.getValue(), + InstrumentClass.KEYBOARD.getValue())) + .build(); + + GenerateContentConfig config = + GenerateContentConfig.builder() + .responseMimeType("text/x.enum") + .responseSchema(responseSchema) + .build(); + + GenerateContentResponse response = client.models.generateContent(modelId, contents, config); + + System.out.println(response.text()); + // Example response: + // String + return response.text(); + } + } +} +// [END googlegenaisdk_ctrlgen_with_enum_class_schema] \ No newline at end of file diff --git a/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithNullableSchema.java b/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithNullableSchema.java new file mode 100644 index 00000000000..5e9d79e8272 --- /dev/null +++ b/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithNullableSchema.java @@ -0,0 +1,109 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package genai.controlledgeneration; + +// [START googlegenaisdk_ctrlgen_with_nullable_schema] + +import com.google.genai.Client; +import com.google.genai.types.GenerateContentConfig; +import com.google.genai.types.GenerateContentResponse; +import com.google.genai.types.HttpOptions; +import com.google.genai.types.Schema; +import com.google.genai.types.Type; + +import java.util.List; +import java.util.Map; + +public class ControlledGenerationWithNullableSchema { + + public static void main(String[] args) { + String modelId = "gemini-2.5-flash"; + + String prompt = "The week ahead brings a mix of weather conditions.\n" + + "Sunday is expected to be sunny with a temperature of 77°F and a humidity level of 50%. " + + "Winds will be light at around 10 km/h.\n" + + "Monday will see partly cloudy skies with a slightly cooler temperature of 72°F and the winds " + + "will pick up slightly to around 15 km/h.\n" + + "Tuesday brings rain showers, with temperatures dropping to 64°F and humidity rising to 70%.\n" + + "Wednesday may see thunderstorms, with a temperature of 68°F.\n" + + "Thursday will be cloudy with a temperature of 66°F and moderate humidity at 60%.\n" + + "Friday returns to partly cloudy conditions, with a temperature of 73°F and the Winds will be " + + "light at 12 km/h.\n" + + "Finally, Saturday rounds off the week with sunny skies, a temperature of 80°F, and a humidity " + + "level of 40%. Winds will be gentle at 8 km/h.\n"; + + generateContent(modelId, prompt); + } + + public static String generateContent(String modelId, String contents) { + + try (Client client = + Client.builder() + .location("global") + .vertexAI(true) + .httpOptions(HttpOptions.builder().apiVersion("v1").build()) + .build()) { + + // Define schema for array items (each weather entry object) + Schema dayForecastSchema = + Schema.builder() + .type(Type.Known.OBJECT) + .properties( + Map.of( + "Day", Schema.builder().type(Type.Known.STRING).nullable(true).build(), + "Forecast", Schema.builder().type(Type.Known.STRING).nullable(true).build(), + "Temperature", Schema.builder().type(Type.Known.INTEGER).nullable(true).build(), + "Humidity", Schema.builder().type(Type.Known.STRING).nullable(true).build(), + "Wind Speed", Schema.builder().type(Type.Known.INTEGER).nullable(true).build())) + .required(List.of("Day", "Temperature", "Forecast", "Wind Speed")) + .build(); + + // Full response schema + Schema responseSchema = + Schema.builder() + .type(Type.Known.OBJECT) + .properties( + Map.of( + "forecast", + Schema.builder() + .type(Type.Known.ARRAY) + .items(dayForecastSchema) + .build())) + .build(); + + GenerateContentConfig config = + GenerateContentConfig.builder() + .responseMimeType("application/json") + .responseSchema(responseSchema) + .build(); + + GenerateContentResponse response = client.models.generateContent(modelId, contents, config); + + System.out.println(response.text()); + // Example response: + // {"forecast": [{"Day": "Sunday", "Forecast": "sunny", "Temperature": 77, "Wind Speed": 10, "Humidity": "50%"}, + // {"Day": "Monday", "Forecast": "partly cloudy", "Temperature": 72, "Wind Speed": 15}, + // {"Day": "Tuesday", "Forecast": "rain showers", "Temperature": 64, "Wind Speed": null, "Humidity": "70%"}, + // {"Day": "Wednesday", "Forecast": "thunderstorms", "Temperature": 68, "Wind Speed": null}, + // {"Day": "Thursday", "Forecast": "cloudy", "Temperature": 66, "Wind Speed": null, "Humidity": "60%"}, + // {"Day": "Friday", "Forecast": "partly cloudy", "Temperature": 73, "Wind Speed": 12}, + // {"Day": "Saturday", "Forecast": "sunny", "Temperature": 80, "Wind Speed": 8, "Humidity": "40%"}]} + return response.text(); + } + } +} +// [END googlegenaisdk_ctrlgen_with_nullable_schema] \ No newline at end of file diff --git a/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithResponseSchema.java b/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithResponseSchema.java new file mode 100644 index 00000000000..0c9fdb48bb3 --- /dev/null +++ b/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithResponseSchema.java @@ -0,0 +1,101 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package genai.controlledgeneration; + +// [START googlegenaisdk_ctrlgen_with_resp_schema] + +import com.google.genai.Client; +import com.google.genai.types.GenerateContentConfig; +import com.google.genai.types.GenerateContentResponse; +import com.google.genai.types.HttpOptions; +import com.google.genai.types.Schema; +import com.google.genai.types.Type; + +import java.util.List; +import java.util.Map; + +public class ControlledGenerationWithResponseSchema { + + public static void main(String[] args) { + String modelId = "gemini-2.5-flash"; + + String contents = "List a few popular cookie recipes."; + + generateContent(modelId, contents); + } + + public static String generateContent(String modelId, String contents) { + + try (Client client = + Client.builder() + .location("global") + .vertexAI(true) + .httpOptions(HttpOptions.builder().apiVersion("v1").build()) + .build()) { + + // Schema for each item in array + Schema recipeSchema = + Schema.builder() + .type(Type.Known.OBJECT) + .properties( + Map.of( + "recipe_name", Schema.builder().type(Type.Known.STRING).build(), + "ingredients", Schema.builder() + .type(Type.Known.ARRAY) + .items(Schema.builder().type(Type.Known.STRING).build()) + .build())) + .required(List.of("recipe_name", "ingredients")) + .build(); + + // Full root schema (array) + Schema responseSchema = + Schema.builder() + .type(Type.Known.ARRAY) + .items(recipeSchema) + .build(); + + GenerateContentConfig config = + GenerateContentConfig.builder() + .responseMimeType("application/json") + .responseSchema(responseSchema) + .build(); + + GenerateContentResponse response = client.models.generateContent(modelId, contents, config); + + System.out.println(response.text()); + // Example response: + // [ + // { + // "ingredients": [ + // "2 1/4 cups all-purpose flour", + // "1 teaspoon baking soda", + // "1 teaspoon salt", + // "1 cup (2 sticks) unsalted butter, softened", + // "3/4 cup granulated sugar", + // "3/4 cup packed brown sugar", + // "1 teaspoon vanilla extract", + // "2 large eggs", + // "2 cups chocolate chips", + // ], + // "recipe_name": "Chocolate Chip Cookies", + // } + // ] + return response.text(); + } + } +} +// [END googlegenaisdk_ctrlgen_with_resp_schema] \ No newline at end of file diff --git a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchemaIT.java b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchemaIT.java new file mode 100644 index 00000000000..368332c6581 --- /dev/null +++ b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchemaIT.java @@ -0,0 +1,72 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package genai.controlledgeneration; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class ControlledGenerationWithEnumClassSchemaIT { + + private static final String MODEL = "gemini-2.5-flash"; + private ByteArrayOutputStream bout; + private PrintStream out; + + public static void requireEnvVar(String envVarName) { + assertWithMessage(String.format("Missing environment variable '%s'", envVarName)) + .that(System.getenv(envVarName)) + .isNotEmpty(); + } + + @BeforeClass + public static void checkRequirements() { + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + } + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + System.setOut(out); + } + + @After + public void tearDown() { + System.setOut(null); + } + + @Test + public void testControlledGenerationWithEnumClassSchema() { + String prompt = "What type of instrument is a guitar?"; + String response = + ControlledGenerationWithEnumClassSchema.generateContent(MODEL, prompt); + + assertThat(response).isNotEmpty(); + // The response *should* contain one of the expected enum values + assertThat(response) + .contains("String"); + } +} \ No newline at end of file diff --git a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithNullableSchemaIT.java b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithNullableSchemaIT.java new file mode 100644 index 00000000000..6685c82dce1 --- /dev/null +++ b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithNullableSchemaIT.java @@ -0,0 +1,84 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package genai.controlledgeneration; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class ControlledGenerationWithNullableSchemaIT { + + private static final String GEMINI_FLASH = "gemini-2.5-flash"; + private ByteArrayOutputStream bout; + private PrintStream out; + + // Ensures required environment variables are set. + public static void requireEnvVar(String envVarName) { + assertWithMessage(String.format("Missing environment variable '%s' ", envVarName)) + .that(System.getenv(envVarName)) + .isNotEmpty(); + } + + @BeforeClass + public static void checkRequirements() { + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + } + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + System.setOut(out); + } + + @After + public void tearDown() { + System.setOut(null); + } + + @Test + public void testControlledGenerationWithNullableSchema() { + String prompt = + "The week ahead brings a mix of weather conditions.\n" + + "Sunday is expected to be sunny with a temperature of 77°F and a humidity level of 50%. " + + "Winds will be light at around 10 km/h.\n" + + "Monday will see partly cloudy skies with a slightly cooler temperature of 72°F and the winds " + + "will pick up slightly to around 15 km/h.\n" + + "Tuesday brings rain showers, with temperatures dropping to 64°F and humidity rising to 70%.\n" + + "Wednesday may see thunderstorms, with a temperature of 68°F.\n" + + "Thursday will be cloudy with a temperature of 66°F and moderate humidity at 60%.\n" + + "Friday returns to partly cloudy conditions, with a temperature of 73°F and the Winds will be " + + "light at 12 km/h.\n" + + "Finally, Saturday rounds off the week with sunny skies, a temperature of 80°F, and a humidity " + + "level of 40%. Winds will be gentle at 8 km/h.\n"; + + String response = + ControlledGenerationWithNullableSchema.generateContent(GEMINI_FLASH, prompt); + + assertThat(response).isNotEmpty(); + assertThat(response).contains("forecast"); + } +} \ No newline at end of file diff --git a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithResponseSchemaIT.java b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithResponseSchemaIT.java new file mode 100644 index 00000000000..fdd3a8c1ed3 --- /dev/null +++ b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithResponseSchemaIT.java @@ -0,0 +1,70 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package genai.controlledgeneration; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class ControlledGenerationWithResponseSchemaIT { + + private static final String MODEL = "gemini-2.5-flash"; + private ByteArrayOutputStream bout; + private PrintStream out; + + public static void requireEnvVar(String envVarName) { + assertWithMessage(String.format("Missing environment variable '%s' ", envVarName)) + .that(System.getenv(envVarName)) + .isNotEmpty(); + } + + @BeforeClass + public static void checkRequirements() { + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + } + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + System.setOut(out); + } + + @After + public void tearDown() { + System.setOut(null); + } + + @Test + public void testControlledGenerationWithResponseSchema() { + String prompt = "List a few popular cookie recipes."; + + String response = ControlledGenerationWithResponseSchema.generateContent(MODEL, prompt); + + assertThat(response).isNotEmpty(); + assertThat(response).contains("recipe_name"); + } +} \ No newline at end of file From 6ef5940414c3f30ce7a9df872b6751e0f65b9ef4 Mon Sep 17 00:00:00 2001 From: cfloress Date: Thu, 4 Dec 2025 18:55:52 -0300 Subject: [PATCH 2/4] genai: PR comments --- .../ControlledGenerationWithEnumClassSchemaIT.java | 6 +++--- .../ControlledGenerationWithResponseSchemaIT.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchemaIT.java b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchemaIT.java index 368332c6581..3252623de9f 100644 --- a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchemaIT.java +++ b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchemaIT.java @@ -31,7 +31,7 @@ @RunWith(JUnit4.class) public class ControlledGenerationWithEnumClassSchemaIT { - private static final String MODEL = "gemini-2.5-flash"; + private static final String GEMINI_FLASH = "gemini-2.5-flash"; private ByteArrayOutputStream bout; private PrintStream out; @@ -62,11 +62,11 @@ public void tearDown() { public void testControlledGenerationWithEnumClassSchema() { String prompt = "What type of instrument is a guitar?"; String response = - ControlledGenerationWithEnumClassSchema.generateContent(MODEL, prompt); + ControlledGenerationWithEnumClassSchema.generateContent(GEMINI_FLASH, prompt); assertThat(response).isNotEmpty(); // The response *should* contain one of the expected enum values assertThat(response) - .contains("String"); + .isEqualTo("String"); } } \ No newline at end of file diff --git a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithResponseSchemaIT.java b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithResponseSchemaIT.java index fdd3a8c1ed3..0ce029f9057 100644 --- a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithResponseSchemaIT.java +++ b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithResponseSchemaIT.java @@ -31,7 +31,7 @@ @RunWith(JUnit4.class) public class ControlledGenerationWithResponseSchemaIT { - private static final String MODEL = "gemini-2.5-flash"; + private static final String GEMINI_FLASH = "gemini-2.5-flash"; private ByteArrayOutputStream bout; private PrintStream out; @@ -62,7 +62,7 @@ public void tearDown() { public void testControlledGenerationWithResponseSchema() { String prompt = "List a few popular cookie recipes."; - String response = ControlledGenerationWithResponseSchema.generateContent(MODEL, prompt); + String response = ControlledGenerationWithResponseSchema.generateContent(GEMINI_FLASH, prompt); assertThat(response).isNotEmpty(); assertThat(response).contains("recipe_name"); From 1d5df8400757a6d103cd5627709f78a58bf8535b Mon Sep 17 00:00:00 2001 From: cfloress Date: Thu, 4 Dec 2025 22:22:22 -0300 Subject: [PATCH 3/4] genai: PR refactor --- .../ControlledGenerationIT.java | 42 ++++++++++ ...rolledGenerationWithEnumClassSchemaIT.java | 72 ---------------- ...trolledGenerationWithNullableSchemaIT.java | 84 ------------------- ...trolledGenerationWithResponseSchemaIT.java | 70 ---------------- 4 files changed, 42 insertions(+), 226 deletions(-) delete mode 100644 genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchemaIT.java delete mode 100644 genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithNullableSchemaIT.java delete mode 100644 genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithResponseSchemaIT.java diff --git a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationIT.java b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationIT.java index 83980a77446..f55c76b4634 100644 --- a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationIT.java +++ b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationIT.java @@ -65,4 +65,46 @@ public void testControlledGenerationWithEnumSchema() { String response = ControlledGenerationWithEnumSchema.generateContent(GEMINI_FLASH, prompt); assertThat(response).isNotEmpty(); } + + @Test + public void testControlledGenerationWithEnumClassSchema() { + String prompt = "What type of instrument is a guitar?"; + String response = ControlledGenerationWithEnumClassSchema.generateContent(GEMINI_FLASH, prompt); + + assertThat(response).isNotEmpty(); + assertThat(response).isEqualTo("String"); + } + + @Test + public void testControlledGenerationWithNullableSchema() { + String prompt = + "The week ahead brings a mix of weather conditions.\n" + + "Sunday is expected to be sunny with a temperature of 77°F and a humidity level of 50%. " + + "Winds will be light at around 10 km/h.\n" + + "Monday will see partly cloudy skies with a slightly cooler temperature of 72°F and the winds " + + "will pick up slightly to around 15 km/h.\n" + + "Tuesday brings rain showers, with temperatures dropping to 64°F and humidity rising to 70%.\n" + + "Wednesday may see thunderstorms, with a temperature of 68°F.\n" + + "Thursday will be cloudy with a temperature of 66°F and moderate humidity at 60%.\n" + + "Friday returns to partly cloudy conditions, with a temperature of 73°F and the Winds will be " + + "light at 12 km/h.\n" + + "Finally, Saturday rounds off the week with sunny skies, a temperature of 80°F, and a humidity " + + "level of 40%. Winds will be gentle at 8 km/h.\n"; + + String response = ControlledGenerationWithNullableSchema.generateContent(GEMINI_FLASH, prompt); + + assertThat(response).isNotEmpty(); + assertThat(response).contains("forecast"); + } + + @Test + public void testControlledGenerationWithResponseSchema() { + String prompt = "List a few popular cookie recipes."; + + String response = ControlledGenerationWithResponseSchema.generateContent(GEMINI_FLASH, prompt); + + assertThat(response).isNotEmpty(); + assertThat(response).contains("recipe_name"); + } + } diff --git a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchemaIT.java b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchemaIT.java deleted file mode 100644 index 3252623de9f..00000000000 --- a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchemaIT.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2025 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package genai.controlledgeneration; - -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ControlledGenerationWithEnumClassSchemaIT { - - private static final String GEMINI_FLASH = "gemini-2.5-flash"; - private ByteArrayOutputStream bout; - private PrintStream out; - - public static void requireEnvVar(String envVarName) { - assertWithMessage(String.format("Missing environment variable '%s'", envVarName)) - .that(System.getenv(envVarName)) - .isNotEmpty(); - } - - @BeforeClass - public static void checkRequirements() { - requireEnvVar("GOOGLE_CLOUD_PROJECT"); - } - - @Before - public void setUp() { - bout = new ByteArrayOutputStream(); - out = new PrintStream(bout); - System.setOut(out); - } - - @After - public void tearDown() { - System.setOut(null); - } - - @Test - public void testControlledGenerationWithEnumClassSchema() { - String prompt = "What type of instrument is a guitar?"; - String response = - ControlledGenerationWithEnumClassSchema.generateContent(GEMINI_FLASH, prompt); - - assertThat(response).isNotEmpty(); - // The response *should* contain one of the expected enum values - assertThat(response) - .isEqualTo("String"); - } -} \ No newline at end of file diff --git a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithNullableSchemaIT.java b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithNullableSchemaIT.java deleted file mode 100644 index 6685c82dce1..00000000000 --- a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithNullableSchemaIT.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2025 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package genai.controlledgeneration; - -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ControlledGenerationWithNullableSchemaIT { - - private static final String GEMINI_FLASH = "gemini-2.5-flash"; - private ByteArrayOutputStream bout; - private PrintStream out; - - // Ensures required environment variables are set. - public static void requireEnvVar(String envVarName) { - assertWithMessage(String.format("Missing environment variable '%s' ", envVarName)) - .that(System.getenv(envVarName)) - .isNotEmpty(); - } - - @BeforeClass - public static void checkRequirements() { - requireEnvVar("GOOGLE_CLOUD_PROJECT"); - } - - @Before - public void setUp() { - bout = new ByteArrayOutputStream(); - out = new PrintStream(bout); - System.setOut(out); - } - - @After - public void tearDown() { - System.setOut(null); - } - - @Test - public void testControlledGenerationWithNullableSchema() { - String prompt = - "The week ahead brings a mix of weather conditions.\n" - + "Sunday is expected to be sunny with a temperature of 77°F and a humidity level of 50%. " - + "Winds will be light at around 10 km/h.\n" - + "Monday will see partly cloudy skies with a slightly cooler temperature of 72°F and the winds " - + "will pick up slightly to around 15 km/h.\n" - + "Tuesday brings rain showers, with temperatures dropping to 64°F and humidity rising to 70%.\n" - + "Wednesday may see thunderstorms, with a temperature of 68°F.\n" - + "Thursday will be cloudy with a temperature of 66°F and moderate humidity at 60%.\n" - + "Friday returns to partly cloudy conditions, with a temperature of 73°F and the Winds will be " - + "light at 12 km/h.\n" - + "Finally, Saturday rounds off the week with sunny skies, a temperature of 80°F, and a humidity " - + "level of 40%. Winds will be gentle at 8 km/h.\n"; - - String response = - ControlledGenerationWithNullableSchema.generateContent(GEMINI_FLASH, prompt); - - assertThat(response).isNotEmpty(); - assertThat(response).contains("forecast"); - } -} \ No newline at end of file diff --git a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithResponseSchemaIT.java b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithResponseSchemaIT.java deleted file mode 100644 index 0ce029f9057..00000000000 --- a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationWithResponseSchemaIT.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2025 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package genai.controlledgeneration; - -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ControlledGenerationWithResponseSchemaIT { - - private static final String GEMINI_FLASH = "gemini-2.5-flash"; - private ByteArrayOutputStream bout; - private PrintStream out; - - public static void requireEnvVar(String envVarName) { - assertWithMessage(String.format("Missing environment variable '%s' ", envVarName)) - .that(System.getenv(envVarName)) - .isNotEmpty(); - } - - @BeforeClass - public static void checkRequirements() { - requireEnvVar("GOOGLE_CLOUD_PROJECT"); - } - - @Before - public void setUp() { - bout = new ByteArrayOutputStream(); - out = new PrintStream(bout); - System.setOut(out); - } - - @After - public void tearDown() { - System.setOut(null); - } - - @Test - public void testControlledGenerationWithResponseSchema() { - String prompt = "List a few popular cookie recipes."; - - String response = ControlledGenerationWithResponseSchema.generateContent(GEMINI_FLASH, prompt); - - assertThat(response).isNotEmpty(); - assertThat(response).contains("recipe_name"); - } -} \ No newline at end of file From de269acd946aeacb9b0f03e75218ae420301b19d Mon Sep 17 00:00:00 2001 From: cfloress Date: Fri, 5 Dec 2025 16:44:58 -0300 Subject: [PATCH 4/4] genai: lint fixed --- ...ntrolledGenerationWithEnumClassSchema.java | 115 +++++++------- ...ontrolledGenerationWithNullableSchema.java | 147 ++++++++++-------- ...ontrolledGenerationWithResponseSchema.java | 119 +++++++------- .../ControlledGenerationIT.java | 84 +++++----- 4 files changed, 241 insertions(+), 224 deletions(-) diff --git a/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchema.java b/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchema.java index 01463abdf89..72dd2abf726 100644 --- a/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchema.java +++ b/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithEnumClassSchema.java @@ -24,70 +24,73 @@ import com.google.genai.types.HttpOptions; import com.google.genai.types.Schema; import com.google.genai.types.Type; - import java.util.List; public class ControlledGenerationWithEnumClassSchema { - // Enum mirroring the Python sample - public enum InstrumentClass { - PERCUSSION("Percussion"), - STRING("String"), - WOODWIND("Woodwind"), - BRASS("Brass"), - KEYBOARD("Keyboard"); - - private final String value; - - InstrumentClass(String value) { - this.value = value; - } - - public String getValue() { - return value; - } + public static void main(String[] args) { + // TODO(developer): Replace these variables before running the sample. + String modelId = "gemini-2.5-flash"; + String prompt = "What type of instrument is a guitar?"; + generateContent(modelId, prompt); + } + + // Generates content with an enum class response schema + public static String generateContent(String modelId, String contents) { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. + try (Client client = + Client.builder() + .location("global") + .vertexAI(true) + .httpOptions(HttpOptions.builder().apiVersion("v1").build()) + .build()) { + + // Build schema using enum values + Schema responseSchema = + Schema.builder() + .type(Type.Known.STRING) + .enum_( + List.of( + InstrumentClass.PERCUSSION.getValue(), + InstrumentClass.STRING.getValue(), + InstrumentClass.WOODWIND.getValue(), + InstrumentClass.BRASS.getValue(), + InstrumentClass.KEYBOARD.getValue())) + .build(); + + GenerateContentConfig config = + GenerateContentConfig.builder() + .responseMimeType("text/x.enum") + .responseSchema(responseSchema) + .build(); + + GenerateContentResponse response = client.models.generateContent(modelId, contents, config); + + System.out.println(response.text()); + // Example response: + // String + return response.text(); } + } - public static void main(String[] args) { - String modelId = "gemini-2.5-flash"; - String prompt = "What type of instrument is a guitar?"; - generateContent(modelId, prompt); - } + // Enum mirroring the Python sample + public enum InstrumentClass { + PERCUSSION("Percussion"), + STRING("String"), + WOODWIND("Woodwind"), + BRASS("Brass"), + KEYBOARD("Keyboard"); - public static String generateContent(String modelId, String contents) { + private final String value; - try (Client client = - Client.builder() - .location("global") - .vertexAI(true) - .httpOptions(HttpOptions.builder().apiVersion("v1").build()) - .build()) { - - // Build schema using enum values - Schema responseSchema = - Schema.builder() - .type(Type.Known.STRING) - .enum_(List.of( - InstrumentClass.PERCUSSION.getValue(), - InstrumentClass.STRING.getValue(), - InstrumentClass.WOODWIND.getValue(), - InstrumentClass.BRASS.getValue(), - InstrumentClass.KEYBOARD.getValue())) - .build(); - - GenerateContentConfig config = - GenerateContentConfig.builder() - .responseMimeType("text/x.enum") - .responseSchema(responseSchema) - .build(); - - GenerateContentResponse response = client.models.generateContent(modelId, contents, config); + InstrumentClass(String value) { + this.value = value; + } - System.out.println(response.text()); - // Example response: - // String - return response.text(); - } + public String getValue() { + return value; } + } } -// [END googlegenaisdk_ctrlgen_with_enum_class_schema] \ No newline at end of file +// [END googlegenaisdk_ctrlgen_with_enum_class_schema] diff --git a/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithNullableSchema.java b/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithNullableSchema.java index 5e9d79e8272..d9fbc5007e0 100644 --- a/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithNullableSchema.java +++ b/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithNullableSchema.java @@ -24,86 +24,97 @@ import com.google.genai.types.HttpOptions; import com.google.genai.types.Schema; import com.google.genai.types.Type; - import java.util.List; import java.util.Map; public class ControlledGenerationWithNullableSchema { - public static void main(String[] args) { - String modelId = "gemini-2.5-flash"; - - String prompt = "The week ahead brings a mix of weather conditions.\n" - + "Sunday is expected to be sunny with a temperature of 77°F and a humidity level of 50%. " - + "Winds will be light at around 10 km/h.\n" - + "Monday will see partly cloudy skies with a slightly cooler temperature of 72°F and the winds " - + "will pick up slightly to around 15 km/h.\n" - + "Tuesday brings rain showers, with temperatures dropping to 64°F and humidity rising to 70%.\n" - + "Wednesday may see thunderstorms, with a temperature of 68°F.\n" - + "Thursday will be cloudy with a temperature of 66°F and moderate humidity at 60%.\n" - + "Friday returns to partly cloudy conditions, with a temperature of 73°F and the Winds will be " - + "light at 12 km/h.\n" - + "Finally, Saturday rounds off the week with sunny skies, a temperature of 80°F, and a humidity " - + "level of 40%. Winds will be gentle at 8 km/h.\n"; + public static void main(String[] args) { + // TODO(developer): Replace these variables before running the sample. + String modelId = "gemini-2.5-flash"; - generateContent(modelId, prompt); - } + String prompt = + "The week ahead brings a mix of weather conditions.\n" + + "Sunday is expected to be sunny with a temperature " + + "of 77°F and a humidity level of 50%. " + + "Winds will be light at around 10 km/h.\n" + + "Monday will see partly cloudy skies with " + + "a slightly cooler temperature of 72°F and the winds " + + "will pick up slightly to around 15 km/h.\n" + + "Tuesday brings rain showers, with temperatures dropping " + + "to 64°F and humidity rising to 70%.\n" + + "Wednesday may see thunderstorms, with a temperature of 68°F.\n" + + "Thursday will be cloudy with a temperature of 66°F and moderate humidity at 60%.\n" + + "Friday returns to partly cloudy conditions, with " + + "a temperature of 73°F and the Winds will be " + + "light at 12 km/h.\n" + + "Finally, Saturday rounds off the week with sunny skies, a " + + "temperature of 80°F, and a humidity " + + "level of 40%. Winds will be gentle at 8 km/h.\n"; - public static String generateContent(String modelId, String contents) { + generateContent(modelId, prompt); + } - try (Client client = - Client.builder() - .location("global") - .vertexAI(true) - .httpOptions(HttpOptions.builder().apiVersion("v1").build()) - .build()) { + // Generates content with a nullable response schema + public static String generateContent(String modelId, String contents) { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. + try (Client client = + Client.builder() + .location("global") + .vertexAI(true) + .httpOptions(HttpOptions.builder().apiVersion("v1").build()) + .build()) { - // Define schema for array items (each weather entry object) - Schema dayForecastSchema = - Schema.builder() - .type(Type.Known.OBJECT) - .properties( - Map.of( - "Day", Schema.builder().type(Type.Known.STRING).nullable(true).build(), - "Forecast", Schema.builder().type(Type.Known.STRING).nullable(true).build(), - "Temperature", Schema.builder().type(Type.Known.INTEGER).nullable(true).build(), - "Humidity", Schema.builder().type(Type.Known.STRING).nullable(true).build(), - "Wind Speed", Schema.builder().type(Type.Known.INTEGER).nullable(true).build())) - .required(List.of("Day", "Temperature", "Forecast", "Wind Speed")) - .build(); + // Define schema for array items (each weather entry object) + Schema dayForecastSchema = + Schema.builder() + .type(Type.Known.OBJECT) + .properties( + Map.of( + "Day", Schema.builder().type(Type.Known.STRING).nullable(true).build(), + "Forecast", Schema.builder().type(Type.Known.STRING).nullable(true).build(), + "Temperature", + Schema.builder().type(Type.Known.INTEGER).nullable(true).build(), + "Humidity", Schema.builder().type(Type.Known.STRING).nullable(true).build(), + "Wind Speed", + Schema.builder().type(Type.Known.INTEGER).nullable(true).build())) + .required(List.of("Day", "Temperature", "Forecast", "Wind Speed")) + .build(); - // Full response schema - Schema responseSchema = - Schema.builder() - .type(Type.Known.OBJECT) - .properties( - Map.of( - "forecast", - Schema.builder() - .type(Type.Known.ARRAY) - .items(dayForecastSchema) - .build())) - .build(); + // Full response schema + Schema responseSchema = + Schema.builder() + .type(Type.Known.OBJECT) + .properties( + Map.of( + "forecast", + Schema.builder().type(Type.Known.ARRAY).items(dayForecastSchema).build())) + .build(); - GenerateContentConfig config = - GenerateContentConfig.builder() - .responseMimeType("application/json") - .responseSchema(responseSchema) - .build(); + GenerateContentConfig config = + GenerateContentConfig.builder() + .responseMimeType("application/json") + .responseSchema(responseSchema) + .build(); - GenerateContentResponse response = client.models.generateContent(modelId, contents, config); + GenerateContentResponse response = client.models.generateContent(modelId, contents, config); - System.out.println(response.text()); - // Example response: - // {"forecast": [{"Day": "Sunday", "Forecast": "sunny", "Temperature": 77, "Wind Speed": 10, "Humidity": "50%"}, - // {"Day": "Monday", "Forecast": "partly cloudy", "Temperature": 72, "Wind Speed": 15}, - // {"Day": "Tuesday", "Forecast": "rain showers", "Temperature": 64, "Wind Speed": null, "Humidity": "70%"}, - // {"Day": "Wednesday", "Forecast": "thunderstorms", "Temperature": 68, "Wind Speed": null}, - // {"Day": "Thursday", "Forecast": "cloudy", "Temperature": 66, "Wind Speed": null, "Humidity": "60%"}, - // {"Day": "Friday", "Forecast": "partly cloudy", "Temperature": 73, "Wind Speed": 12}, - // {"Day": "Saturday", "Forecast": "sunny", "Temperature": 80, "Wind Speed": 8, "Humidity": "40%"}]} - return response.text(); - } + System.out.println(response.text()); + // Example response: + // {"forecast": [{"Day": "Sunday", "Forecast": "sunny", "Temperature": 77, "Wind Speed": 10, + // "Humidity": "50%"}, + // {"Day": "Monday", "Forecast": "partly cloudy", "Temperature": 72, "Wind Speed": 15}, + // {"Day": "Tuesday", "Forecast": "rain showers", "Temperature": 64, "Wind Speed": null, + // "Humidity": "70%"}, + // {"Day": "Wednesday", "Forecast": "thunderstorms", "Temperature": 68, "Wind Speed": null}, + // {"Day": "Thursday", "Forecast": "cloudy", "Temperature": 66, "Wind Speed": null, + // "Humidity": "60%"}, + // {"Day": "Friday", "Forecast": "partly cloudy", "Temperature": 73, "Wind Speed": 12}, + // {"Day": "Saturday", "Forecast": "sunny", "Temperature": 80, "Wind Speed": 8, "Humidity": + // "40%"}]} + return response.text(); } + } } -// [END googlegenaisdk_ctrlgen_with_nullable_schema] \ No newline at end of file +// [END googlegenaisdk_ctrlgen_with_nullable_schema] diff --git a/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithResponseSchema.java b/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithResponseSchema.java index 0c9fdb48bb3..97a0b3d2132 100644 --- a/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithResponseSchema.java +++ b/genai/snippets/src/main/java/genai/controlledgeneration/ControlledGenerationWithResponseSchema.java @@ -24,78 +24,77 @@ import com.google.genai.types.HttpOptions; import com.google.genai.types.Schema; import com.google.genai.types.Type; - import java.util.List; import java.util.Map; public class ControlledGenerationWithResponseSchema { - public static void main(String[] args) { - String modelId = "gemini-2.5-flash"; - - String contents = "List a few popular cookie recipes."; + public static void main(String[] args) { + // TODO(developer): Replace these variables before running the sample. + String modelId = "gemini-2.5-flash"; - generateContent(modelId, contents); - } + String contents = "List a few popular cookie recipes."; - public static String generateContent(String modelId, String contents) { + generateContent(modelId, contents); + } - try (Client client = - Client.builder() - .location("global") - .vertexAI(true) - .httpOptions(HttpOptions.builder().apiVersion("v1").build()) - .build()) { + // Generates content with a response schema + public static String generateContent(String modelId, String contents) { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. + try (Client client = + Client.builder() + .location("global") + .vertexAI(true) + .httpOptions(HttpOptions.builder().apiVersion("v1").build()) + .build()) { - // Schema for each item in array - Schema recipeSchema = - Schema.builder() - .type(Type.Known.OBJECT) - .properties( - Map.of( - "recipe_name", Schema.builder().type(Type.Known.STRING).build(), - "ingredients", Schema.builder() - .type(Type.Known.ARRAY) - .items(Schema.builder().type(Type.Known.STRING).build()) - .build())) - .required(List.of("recipe_name", "ingredients")) - .build(); + // Schema for each item in array + Schema recipeSchema = + Schema.builder() + .type(Type.Known.OBJECT) + .properties( + Map.of( + "recipe_name", Schema.builder().type(Type.Known.STRING).build(), + "ingredients", + Schema.builder() + .type(Type.Known.ARRAY) + .items(Schema.builder().type(Type.Known.STRING).build()) + .build())) + .required(List.of("recipe_name", "ingredients")) + .build(); - // Full root schema (array) - Schema responseSchema = - Schema.builder() - .type(Type.Known.ARRAY) - .items(recipeSchema) - .build(); + // Full root schema (array) + Schema responseSchema = Schema.builder().type(Type.Known.ARRAY).items(recipeSchema).build(); - GenerateContentConfig config = - GenerateContentConfig.builder() - .responseMimeType("application/json") - .responseSchema(responseSchema) - .build(); + GenerateContentConfig config = + GenerateContentConfig.builder() + .responseMimeType("application/json") + .responseSchema(responseSchema) + .build(); - GenerateContentResponse response = client.models.generateContent(modelId, contents, config); + GenerateContentResponse response = client.models.generateContent(modelId, contents, config); - System.out.println(response.text()); - // Example response: - // [ - // { - // "ingredients": [ - // "2 1/4 cups all-purpose flour", - // "1 teaspoon baking soda", - // "1 teaspoon salt", - // "1 cup (2 sticks) unsalted butter, softened", - // "3/4 cup granulated sugar", - // "3/4 cup packed brown sugar", - // "1 teaspoon vanilla extract", - // "2 large eggs", - // "2 cups chocolate chips", - // ], - // "recipe_name": "Chocolate Chip Cookies", - // } - // ] - return response.text(); - } + System.out.println(response.text()); + // Example response: + // [ + // { + // "ingredients": [ + // "2 1/4 cups all-purpose flour", + // "1 teaspoon baking soda", + // "1 teaspoon salt", + // "1 cup (2 sticks) unsalted butter, softened", + // "3/4 cup granulated sugar", + // "3/4 cup packed brown sugar", + // "1 teaspoon vanilla extract", + // "2 large eggs", + // "2 cups chocolate chips", + // ], + // "recipe_name": "Chocolate Chip Cookies", + // } + // ] + return response.text(); } + } } -// [END googlegenaisdk_ctrlgen_with_resp_schema] \ No newline at end of file +// [END googlegenaisdk_ctrlgen_with_resp_schema] diff --git a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationIT.java b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationIT.java index f55c76b4634..bdd6fe2c05e 100644 --- a/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationIT.java +++ b/genai/snippets/src/test/java/genai/controlledgeneration/ControlledGenerationIT.java @@ -66,45 +66,49 @@ public void testControlledGenerationWithEnumSchema() { assertThat(response).isNotEmpty(); } - @Test - public void testControlledGenerationWithEnumClassSchema() { - String prompt = "What type of instrument is a guitar?"; - String response = ControlledGenerationWithEnumClassSchema.generateContent(GEMINI_FLASH, prompt); - - assertThat(response).isNotEmpty(); - assertThat(response).isEqualTo("String"); - } - - @Test - public void testControlledGenerationWithNullableSchema() { - String prompt = - "The week ahead brings a mix of weather conditions.\n" - + "Sunday is expected to be sunny with a temperature of 77°F and a humidity level of 50%. " - + "Winds will be light at around 10 km/h.\n" - + "Monday will see partly cloudy skies with a slightly cooler temperature of 72°F and the winds " - + "will pick up slightly to around 15 km/h.\n" - + "Tuesday brings rain showers, with temperatures dropping to 64°F and humidity rising to 70%.\n" - + "Wednesday may see thunderstorms, with a temperature of 68°F.\n" - + "Thursday will be cloudy with a temperature of 66°F and moderate humidity at 60%.\n" - + "Friday returns to partly cloudy conditions, with a temperature of 73°F and the Winds will be " - + "light at 12 km/h.\n" - + "Finally, Saturday rounds off the week with sunny skies, a temperature of 80°F, and a humidity " - + "level of 40%. Winds will be gentle at 8 km/h.\n"; - - String response = ControlledGenerationWithNullableSchema.generateContent(GEMINI_FLASH, prompt); - - assertThat(response).isNotEmpty(); - assertThat(response).contains("forecast"); - } - - @Test - public void testControlledGenerationWithResponseSchema() { - String prompt = "List a few popular cookie recipes."; - - String response = ControlledGenerationWithResponseSchema.generateContent(GEMINI_FLASH, prompt); - - assertThat(response).isNotEmpty(); - assertThat(response).contains("recipe_name"); - } + @Test + public void testControlledGenerationWithEnumClassSchema() { + String prompt = "What type of instrument is a guitar?"; + String response = ControlledGenerationWithEnumClassSchema.generateContent(GEMINI_FLASH, prompt); + + assertThat(response).isNotEmpty(); + assertThat(response).isEqualTo("String"); + } + + @Test + public void testControlledGenerationWithNullableSchema() { + String prompt = + "The week ahead brings a mix of weather conditions.\n" + + "Sunday is expected to be sunny with a temperature " + + "of 77°F and a humidity level of 50%. " + + "Winds will be light at around 10 km/h.\n" + + "Monday will see partly cloudy skies with " + + "a slightly cooler temperature of 72°F and the winds " + + "will pick up slightly to around 15 km/h.\n" + + "Tuesday brings rain showers, with temperatures dropping " + + "to 64°F and humidity rising to 70%.\n" + + "Wednesday may see thunderstorms, with a temperature of 68°F.\n" + + "Thursday will be cloudy with a temperature of 66°F and moderate humidity at 60%.\n" + + "Friday returns to partly cloudy conditions, with " + + "a temperature of 73°F and the Winds will be " + + "light at 12 km/h.\n" + + "Finally, Saturday rounds off the week with sunny skies, a " + + "temperature of 80°F, and a humidity " + + "level of 40%. Winds will be gentle at 8 km/h.\n"; + + String response = ControlledGenerationWithNullableSchema.generateContent(GEMINI_FLASH, prompt); + + assertThat(response).isNotEmpty(); + assertThat(response).contains("forecast"); + } + + @Test + public void testControlledGenerationWithResponseSchema() { + String prompt = "List a few popular cookie recipes."; + String response = ControlledGenerationWithResponseSchema.generateContent(GEMINI_FLASH, prompt); + + assertThat(response).isNotEmpty(); + assertThat(response).contains("recipe_name"); + } }