Skip to content

Commit ae1d29d

Browse files
jdomingrJuan Dominguez
andauthored
feat(genai): add new tool samples (#10191)
* feat(genai): add new tool samples * chore(genai): update comments * refactor(genai): change stream chain and exception message * refactor(genai): improve tests by checking the response --------- Co-authored-by: Juan Dominguez <[email protected]>
1 parent 567844f commit ae1d29d

File tree

5 files changed

+300
-8
lines changed

5 files changed

+300
-8
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package genai.tools;
18+
19+
// [START googlegenaisdk_tools_google_maps_coordinates_with_txt]
20+
21+
import com.google.genai.Client;
22+
import com.google.genai.types.GenerateContentConfig;
23+
import com.google.genai.types.GenerateContentResponse;
24+
import com.google.genai.types.GoogleMaps;
25+
import com.google.genai.types.HttpOptions;
26+
import com.google.genai.types.LatLng;
27+
import com.google.genai.types.RetrievalConfig;
28+
import com.google.genai.types.Tool;
29+
import com.google.genai.types.ToolConfig;
30+
31+
public class ToolsGoogleMapsCoordinatesWithTxt {
32+
33+
public static void main(String[] args) {
34+
// TODO(developer): Replace these variables before running the sample.
35+
String modelId = "gemini-2.5-flash";
36+
generateContent(modelId);
37+
}
38+
39+
// Generates content with Google Maps Tool.
40+
public static String generateContent(String modelId) {
41+
// Client Initialization. Once created, it can be reused for multiple requests.
42+
try (Client client =
43+
Client.builder()
44+
.location("global")
45+
.vertexAI(true)
46+
.httpOptions(HttpOptions.builder().apiVersion("v1").build())
47+
.build()) {
48+
49+
// Set the Google Maps Tool.
50+
Tool tool = Tool.builder().googleMaps(GoogleMaps.builder().build()).build();
51+
52+
ToolConfig toolConfig =
53+
ToolConfig.builder()
54+
.retrievalConfig(
55+
RetrievalConfig.builder()
56+
// Pass coordinates for location-aware grounding
57+
.latLng(LatLng.builder().latitude(40.7128).longitude(-74.006).build())
58+
// Localize Maps results
59+
.languageCode("en_US")
60+
.build())
61+
.build();
62+
63+
GenerateContentResponse response =
64+
client.models.generateContent(
65+
modelId,
66+
"Where can I get the best espresso near me?",
67+
GenerateContentConfig.builder().tools(tool).toolConfig(toolConfig).build());
68+
69+
System.out.println(response.text());
70+
// Example response:
71+
// Here are some of the top-rated coffee shops near you that serve excellent espresso...
72+
return response.text();
73+
}
74+
}
75+
}
76+
// [END googlegenaisdk_tools_google_maps_coordinates_with_txt]
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package genai.tools;
18+
19+
// [START googlegenaisdk_tools_google_search_and_urlcontext_with_txt]
20+
21+
import com.google.genai.Client;
22+
import com.google.genai.types.Candidate;
23+
import com.google.genai.types.Content;
24+
import com.google.genai.types.GenerateContentConfig;
25+
import com.google.genai.types.GenerateContentResponse;
26+
import com.google.genai.types.GoogleSearch;
27+
import com.google.genai.types.HttpOptions;
28+
import com.google.genai.types.Tool;
29+
import com.google.genai.types.UrlContext;
30+
import java.util.List;
31+
32+
public class ToolsGoogleSearchAndUrlContextWithTxt {
33+
34+
public static void main(String[] args) {
35+
// TODO(developer): Replace these variables before running the sample.
36+
String modelId = "gemini-2.5-flash";
37+
String url = "https://www.google.com/search?q=events+in+New+York";
38+
generateContent(modelId, url);
39+
}
40+
41+
// Generates content with the Url Context and Google Search Tools.
42+
public static String generateContent(String modelId, String url) {
43+
// Client Initialization. Once created, it can be reused for multiple requests.
44+
try (Client client =
45+
Client.builder()
46+
.location("global")
47+
.vertexAI(true)
48+
.httpOptions(HttpOptions.builder().apiVersion("v1beta1").build())
49+
.build()) {
50+
51+
// Set the Url Context and Google Search tools.
52+
List<Tool> tools =
53+
List.of(
54+
Tool.builder().urlContext(UrlContext.builder().build()).build(),
55+
Tool.builder().googleSearch(GoogleSearch.builder().build()).build());
56+
57+
String prompt =
58+
String.format(
59+
"Give me three day events schedule based on %s. Also let me know what"
60+
+ " needs to be taken care of considering weather and commute.",
61+
url);
62+
63+
GenerateContentResponse response =
64+
client.models.generateContent(
65+
modelId,
66+
prompt,
67+
GenerateContentConfig.builder().tools(tools).responseModalities("TEXT").build());
68+
69+
// Get response candidate.
70+
Candidate candidate =
71+
response
72+
.candidates()
73+
.flatMap(candidates -> candidates.stream().findFirst())
74+
.orElseThrow(
75+
() ->
76+
new IllegalStateException(
77+
"No response candidate was generated by the model."));
78+
79+
// Print parts of the response.
80+
candidate
81+
.content()
82+
.flatMap(Content::parts)
83+
.ifPresent(parts -> parts.forEach(part -> part.text().ifPresent(System.out::println)));
84+
// Example response:
85+
// Three-Day Event Schedule in...
86+
// **Day 1: Friday, October 24, 2025**
87+
// * **Evening Event:** Attend the **2025...
88+
89+
candidate.urlContextMetadata().ifPresent(System.out::println);
90+
91+
return response.text();
92+
}
93+
}
94+
}
95+
// [END googlegenaisdk_tools_google_search_and_urlcontext_with_txt]

genai/snippets/src/main/java/genai/tools/ToolsGoogleSearchWithText.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public static void main(String[] args) {
3333
generateContent(modelId);
3434
}
3535

36-
// Generates text with Google Search tool
36+
// Generates content with Google Search tool
3737
public static String generateContent(String modelId) {
3838
// Initialize client that will be used to send requests. This client only needs to be created
3939
// once, and can be reused for multiple requests.
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package genai.tools;
18+
19+
// [START googlegenaisdk_tools_urlcontext_with_txt]
20+
21+
import com.google.genai.Client;
22+
import com.google.genai.types.Candidate;
23+
import com.google.genai.types.Content;
24+
import com.google.genai.types.GenerateContentConfig;
25+
import com.google.genai.types.GenerateContentResponse;
26+
import com.google.genai.types.HttpOptions;
27+
import com.google.genai.types.Tool;
28+
import com.google.genai.types.UrlContext;
29+
30+
public class ToolsUrlContextWithTxt {
31+
32+
public static void main(String[] args) {
33+
// TODO(developer): Replace these variables before running the sample.
34+
String modelId = "gemini-2.5-flash";
35+
String url1 = "https://cloud.google.com/vertex-ai/generative-ai/docs";
36+
String url2 = "https://cloud.google.com/docs/overview";
37+
generateContent(modelId, url1, url2);
38+
}
39+
40+
// Generates text with the Url Context Tool.
41+
public static String generateContent(String modelId, String url1, String url2) {
42+
// Client Initialization. Once created, it can be reused for multiple requests.
43+
try (Client client =
44+
Client.builder()
45+
.location("global")
46+
.vertexAI(true)
47+
.httpOptions(HttpOptions.builder().apiVersion("v1").build())
48+
.build()) {
49+
50+
String prompt =
51+
String.format("Compare the content, purpose, and audiences of %s and %s", url1, url2);
52+
53+
// Set the Url Context Tool.
54+
Tool tool = Tool.builder().urlContext(UrlContext.builder().build()).build();
55+
56+
GenerateContentResponse response =
57+
client.models.generateContent(
58+
modelId,
59+
prompt,
60+
GenerateContentConfig.builder().tools(tool).responseModalities("TEXT").build());
61+
62+
// Get response candidate.
63+
Candidate candidate =
64+
response
65+
.candidates()
66+
.flatMap(candidates -> candidates.stream().findFirst())
67+
.orElseThrow(
68+
() ->
69+
new IllegalStateException(
70+
"No response candidate was generated by the model."));
71+
72+
// Print parts of the response.
73+
candidate
74+
.content()
75+
.flatMap(Content::parts)
76+
.ifPresent(parts -> parts.forEach(part -> part.text().ifPresent(System.out::println)));
77+
// Example response:
78+
// The two Google Cloud documentation pages serve distinct purposes and cater to different
79+
// audiences within the broader Google Cloud ecosystem
80+
81+
candidate.urlContextMetadata().ifPresent(System.out::println);
82+
// Example response:
83+
// UrlContextMetadata{urlMetadata=Optional[[UrlMetadata{
84+
// retrievedUrl=Optional[https://cloud.google.com/vertex-ai/generative-ai/docs],
85+
// urlRetrievalStatus=Optional[URL_RETRIEVAL_STATUS_SUCCESS]},
86+
// UrlMetadata{retrievedUrl=Optional[https://cloud.google.com/docs/overview],
87+
// urlRetrievalStatus=Optional[URL_RETRIEVAL_STATUS_SUCCESS]}]]}
88+
return response.text();
89+
}
90+
}
91+
}
92+
// [END googlegenaisdk_tools_urlcontext_with_txt]

genai/snippets/src/test/java/genai/tools/ToolsIT.java

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
import org.junit.runners.JUnit4;
4444
import org.mockito.MockedStatic;
4545

46-
4746
@RunWith(JUnit4.class)
4847
public class ToolsIT {
4948

@@ -114,22 +113,52 @@ public void testToolsCodeExecWithTextLocalImage() throws IOException {
114113
assertThat(bout.toString()).contains("Outcome:");
115114
}
116115

116+
@Test
117+
public void testToolsGoogleMapsCoordinatesWithTxt() {
118+
String response = ToolsGoogleMapsCoordinatesWithTxt.generateContent(GEMINI_FLASH);
119+
assertThat(response).isNotEmpty();
120+
assertThat(bout.toString()).contains(response);
121+
}
122+
123+
@Test
124+
public void testToolsGoogleSearchAndUrlContextWithTxt() {
125+
String url = "https://www.google.com/search?q=events+in+New+York";
126+
String response = ToolsGoogleSearchAndUrlContextWithTxt.generateContent(GEMINI_FLASH, url);
127+
assertThat(response).isNotEmpty();
128+
assertThat(bout.toString()).contains(response);
129+
}
130+
117131
@Test
118132
public void testToolsGoogleSearchWithText() {
119133
String response = ToolsGoogleSearchWithText.generateContent(GEMINI_FLASH);
120134
assertThat(response).isNotEmpty();
121135
}
122136

137+
@Test
138+
public void testToolsUrlContextWithTxt() {
139+
String url1 = "https://cloud.google.com/vertex-ai/generative-ai/docs";
140+
String url2 = "https://cloud.google.com/docs/overview";
141+
String response = ToolsUrlContextWithTxt.generateContent(GEMINI_FLASH, url1, url2);
142+
assertThat(response).isNotEmpty();
143+
String output = bout.toString();
144+
assertThat(output).contains("UrlContextMetadata");
145+
assertThat(output).contains("urlRetrievalStatus");
146+
assertThat(output).contains("URL_RETRIEVAL_STATUS_SUCCESS");
147+
assertThat(output).contains(url1);
148+
assertThat(output).contains(url2);
149+
}
150+
123151
@Test
124152
public void testToolsVaisWithText() throws NoSuchFieldException, IllegalAccessException {
125-
String response = "The process for making an appointment to renew your driver's license"
153+
String response =
154+
"The process for making an appointment to renew your driver's license"
126155
+ " varies depending on your location.";
127156

128157
String datastore =
129-
String.format(
130-
"projects/%s/locations/global/collections/default_collection/"
131-
+ "dataStores/grounding-test-datastore",
132-
PROJECT_ID);
158+
String.format(
159+
"projects/%s/locations/global/collections/default_collection/"
160+
+ "dataStores/grounding-test-datastore",
161+
PROJECT_ID);
133162

134163
Client.Builder mockedBuilder = mock(Client.Builder.class, RETURNS_SELF);
135164
Client mockedClient = mock(Client.class);
@@ -158,4 +187,4 @@ public void testToolsVaisWithText() throws NoSuchFieldException, IllegalAccessEx
158187
assertThat(response).isEqualTo(generatedResponse);
159188
}
160189
}
161-
}
190+
}

0 commit comments

Comments
 (0)