diff --git a/genai/snippets/src/main/java/genai/tools/ToolsGoogleMapsCoordinatesWithTxt.java b/genai/snippets/src/main/java/genai/tools/ToolsGoogleMapsCoordinatesWithTxt.java new file mode 100644 index 00000000000..1b7f749539f --- /dev/null +++ b/genai/snippets/src/main/java/genai/tools/ToolsGoogleMapsCoordinatesWithTxt.java @@ -0,0 +1,76 @@ +/* + * 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.tools; + +// [START googlegenaisdk_tools_google_maps_coordinates_with_txt] + +import com.google.genai.Client; +import com.google.genai.types.GenerateContentConfig; +import com.google.genai.types.GenerateContentResponse; +import com.google.genai.types.GoogleMaps; +import com.google.genai.types.HttpOptions; +import com.google.genai.types.LatLng; +import com.google.genai.types.RetrievalConfig; +import com.google.genai.types.Tool; +import com.google.genai.types.ToolConfig; + +public class ToolsGoogleMapsCoordinatesWithTxt { + + public static void main(String[] args) { + // TODO(developer): Replace these variables before running the sample. + String modelId = "gemini-2.5-flash"; + generateContent(modelId); + } + + // Generates content with Google Maps Tool. + public static String generateContent(String modelId) { + // Client Initialization. Once created, it can be reused for multiple requests. + try (Client client = + Client.builder() + .location("global") + .vertexAI(true) + .httpOptions(HttpOptions.builder().apiVersion("v1").build()) + .build()) { + + // Set the Google Maps Tool. + Tool tool = Tool.builder().googleMaps(GoogleMaps.builder().build()).build(); + + ToolConfig toolConfig = + ToolConfig.builder() + .retrievalConfig( + RetrievalConfig.builder() + // Pass coordinates for location-aware grounding + .latLng(LatLng.builder().latitude(40.7128).longitude(-74.006).build()) + // Localize Maps results + .languageCode("en_US") + .build()) + .build(); + + GenerateContentResponse response = + client.models.generateContent( + modelId, + "Where can I get the best espresso near me?", + GenerateContentConfig.builder().tools(tool).toolConfig(toolConfig).build()); + + System.out.println(response.text()); + // Example response: + // Here are some of the top-rated coffee shops near you that serve excellent espresso... + return response.text(); + } + } +} +// [END googlegenaisdk_tools_google_maps_coordinates_with_txt] diff --git a/genai/snippets/src/main/java/genai/tools/ToolsGoogleSearchAndUrlContextWithTxt.java b/genai/snippets/src/main/java/genai/tools/ToolsGoogleSearchAndUrlContextWithTxt.java new file mode 100644 index 00000000000..ac2d3e4aad0 --- /dev/null +++ b/genai/snippets/src/main/java/genai/tools/ToolsGoogleSearchAndUrlContextWithTxt.java @@ -0,0 +1,95 @@ +/* + * 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.tools; + +// [START googlegenaisdk_tools_google_search_and_urlcontext_with_txt] + +import com.google.genai.Client; +import com.google.genai.types.Candidate; +import com.google.genai.types.Content; +import com.google.genai.types.GenerateContentConfig; +import com.google.genai.types.GenerateContentResponse; +import com.google.genai.types.GoogleSearch; +import com.google.genai.types.HttpOptions; +import com.google.genai.types.Tool; +import com.google.genai.types.UrlContext; +import java.util.List; + +public class ToolsGoogleSearchAndUrlContextWithTxt { + + public static void main(String[] args) { + // TODO(developer): Replace these variables before running the sample. + String modelId = "gemini-2.5-flash"; + String url = "https://www.google.com/search?q=events+in+New+York"; + generateContent(modelId, url); + } + + // Generates content with the Url Context and Google Search Tools. + public static String generateContent(String modelId, String url) { + // Client Initialization. Once created, it can be reused for multiple requests. + try (Client client = + Client.builder() + .location("global") + .vertexAI(true) + .httpOptions(HttpOptions.builder().apiVersion("v1beta1").build()) + .build()) { + + // Set the Url Context and Google Search tools. + List tools = + List.of( + Tool.builder().urlContext(UrlContext.builder().build()).build(), + Tool.builder().googleSearch(GoogleSearch.builder().build()).build()); + + String prompt = + String.format( + "Give me three day events schedule based on %s. Also let me know what" + + " needs to be taken care of considering weather and commute.", + url); + + GenerateContentResponse response = + client.models.generateContent( + modelId, + prompt, + GenerateContentConfig.builder().tools(tools).responseModalities("TEXT").build()); + + // Get response candidate. + Candidate candidate = + response + .candidates() + .flatMap(candidates -> candidates.stream().findFirst()) + .orElseThrow( + () -> + new IllegalStateException( + "No response candidate was generated by the model.")); + + // Print parts of the response. + candidate + .content() + .flatMap(Content::parts) + .ifPresent(parts -> parts.forEach(part -> part.text().ifPresent(System.out::println))); + // Example response: + // Three-Day Event Schedule in... + // **Day 1: Friday, October 24, 2025** + // * **Evening Event:** Attend the **2025... + + candidate.urlContextMetadata().ifPresent(System.out::println); + + return response.text(); + } + } +} +// [END googlegenaisdk_tools_google_search_and_urlcontext_with_txt] diff --git a/genai/snippets/src/main/java/genai/tools/ToolsGoogleSearchWithText.java b/genai/snippets/src/main/java/genai/tools/ToolsGoogleSearchWithText.java index 7c053dbd1e7..ff8a0d132e8 100644 --- a/genai/snippets/src/main/java/genai/tools/ToolsGoogleSearchWithText.java +++ b/genai/snippets/src/main/java/genai/tools/ToolsGoogleSearchWithText.java @@ -33,7 +33,7 @@ public static void main(String[] args) { generateContent(modelId); } - // Generates text with Google Search tool + // Generates content with Google Search tool public static String generateContent(String modelId) { // Initialize client that will be used to send requests. This client only needs to be created // once, and can be reused for multiple requests. diff --git a/genai/snippets/src/main/java/genai/tools/ToolsUrlContextWithTxt.java b/genai/snippets/src/main/java/genai/tools/ToolsUrlContextWithTxt.java new file mode 100644 index 00000000000..3e16014ca5b --- /dev/null +++ b/genai/snippets/src/main/java/genai/tools/ToolsUrlContextWithTxt.java @@ -0,0 +1,92 @@ +/* + * 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.tools; + +// [START googlegenaisdk_tools_urlcontext_with_txt] + +import com.google.genai.Client; +import com.google.genai.types.Candidate; +import com.google.genai.types.Content; +import com.google.genai.types.GenerateContentConfig; +import com.google.genai.types.GenerateContentResponse; +import com.google.genai.types.HttpOptions; +import com.google.genai.types.Tool; +import com.google.genai.types.UrlContext; + +public class ToolsUrlContextWithTxt { + + public static void main(String[] args) { + // TODO(developer): Replace these variables before running the sample. + String modelId = "gemini-2.5-flash"; + String url1 = "https://cloud.google.com/vertex-ai/generative-ai/docs"; + String url2 = "https://cloud.google.com/docs/overview"; + generateContent(modelId, url1, url2); + } + + // Generates text with the Url Context Tool. + public static String generateContent(String modelId, String url1, String url2) { + // Client Initialization. Once created, it can be reused for multiple requests. + try (Client client = + Client.builder() + .location("global") + .vertexAI(true) + .httpOptions(HttpOptions.builder().apiVersion("v1").build()) + .build()) { + + String prompt = + String.format("Compare the content, purpose, and audiences of %s and %s", url1, url2); + + // Set the Url Context Tool. + Tool tool = Tool.builder().urlContext(UrlContext.builder().build()).build(); + + GenerateContentResponse response = + client.models.generateContent( + modelId, + prompt, + GenerateContentConfig.builder().tools(tool).responseModalities("TEXT").build()); + + // Get response candidate. + Candidate candidate = + response + .candidates() + .flatMap(candidates -> candidates.stream().findFirst()) + .orElseThrow( + () -> + new IllegalStateException( + "No response candidate was generated by the model.")); + + // Print parts of the response. + candidate + .content() + .flatMap(Content::parts) + .ifPresent(parts -> parts.forEach(part -> part.text().ifPresent(System.out::println))); + // Example response: + // The two Google Cloud documentation pages serve distinct purposes and cater to different + // audiences within the broader Google Cloud ecosystem + + candidate.urlContextMetadata().ifPresent(System.out::println); + // Example response: + // UrlContextMetadata{urlMetadata=Optional[[UrlMetadata{ + // retrievedUrl=Optional[https://cloud.google.com/vertex-ai/generative-ai/docs], + // urlRetrievalStatus=Optional[URL_RETRIEVAL_STATUS_SUCCESS]}, + // UrlMetadata{retrievedUrl=Optional[https://cloud.google.com/docs/overview], + // urlRetrievalStatus=Optional[URL_RETRIEVAL_STATUS_SUCCESS]}]]} + return response.text(); + } + } +} +// [END googlegenaisdk_tools_urlcontext_with_txt] diff --git a/genai/snippets/src/test/java/genai/tools/ToolsIT.java b/genai/snippets/src/test/java/genai/tools/ToolsIT.java index 1bbf109580d..d6cc8285ce3 100644 --- a/genai/snippets/src/test/java/genai/tools/ToolsIT.java +++ b/genai/snippets/src/test/java/genai/tools/ToolsIT.java @@ -43,7 +43,6 @@ import org.junit.runners.JUnit4; import org.mockito.MockedStatic; - @RunWith(JUnit4.class) public class ToolsIT { @@ -114,22 +113,52 @@ public void testToolsCodeExecWithTextLocalImage() throws IOException { assertThat(bout.toString()).contains("Outcome:"); } + @Test + public void testToolsGoogleMapsCoordinatesWithTxt() { + String response = ToolsGoogleMapsCoordinatesWithTxt.generateContent(GEMINI_FLASH); + assertThat(response).isNotEmpty(); + assertThat(bout.toString()).contains(response); + } + + @Test + public void testToolsGoogleSearchAndUrlContextWithTxt() { + String url = "https://www.google.com/search?q=events+in+New+York"; + String response = ToolsGoogleSearchAndUrlContextWithTxt.generateContent(GEMINI_FLASH, url); + assertThat(response).isNotEmpty(); + assertThat(bout.toString()).contains(response); + } + @Test public void testToolsGoogleSearchWithText() { String response = ToolsGoogleSearchWithText.generateContent(GEMINI_FLASH); assertThat(response).isNotEmpty(); } + @Test + public void testToolsUrlContextWithTxt() { + String url1 = "https://cloud.google.com/vertex-ai/generative-ai/docs"; + String url2 = "https://cloud.google.com/docs/overview"; + String response = ToolsUrlContextWithTxt.generateContent(GEMINI_FLASH, url1, url2); + assertThat(response).isNotEmpty(); + String output = bout.toString(); + assertThat(output).contains("UrlContextMetadata"); + assertThat(output).contains("urlRetrievalStatus"); + assertThat(output).contains("URL_RETRIEVAL_STATUS_SUCCESS"); + assertThat(output).contains(url1); + assertThat(output).contains(url2); + } + @Test public void testToolsVaisWithText() throws NoSuchFieldException, IllegalAccessException { - String response = "The process for making an appointment to renew your driver's license" + String response = + "The process for making an appointment to renew your driver's license" + " varies depending on your location."; String datastore = - String.format( - "projects/%s/locations/global/collections/default_collection/" - + "dataStores/grounding-test-datastore", - PROJECT_ID); + String.format( + "projects/%s/locations/global/collections/default_collection/" + + "dataStores/grounding-test-datastore", + PROJECT_ID); Client.Builder mockedBuilder = mock(Client.Builder.class, RETURNS_SELF); Client mockedClient = mock(Client.class); @@ -158,4 +187,4 @@ public void testToolsVaisWithText() throws NoSuchFieldException, IllegalAccessEx assertThat(response).isEqualTo(generatedResponse); } } -} \ No newline at end of file +}