Skip to content

Commit 7f0ef21

Browse files
committed
completed full iTest pass.
1 parent 460f4bd commit 7f0ef21

File tree

3 files changed

+181
-14
lines changed

3 files changed

+181
-14
lines changed

common/api-review/ai.api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,7 @@ export interface GroundingChunk {
680680

681681
// @public
682682
export interface GroundingMetadata {
683+
googleMapsWidgetContextToken?: string;
683684
groundingChunks?: GroundingChunk[];
684685
groundingSupports?: GroundingSupport[];
685686
// @deprecated (undocumented)

packages/ai/integration/generate-content.test.ts

Lines changed: 167 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -170,42 +170,151 @@ describe('Generate Content', function () {
170170
expect(groundingSupport.segment?.text).to.exist;
171171
// Since partIndex and startIndex are commonly 0, they may be omitted from responses.
172172
});
173+
expect(groundingMetadata!.googleMapsWidgetContextToken).to.not.exist;
173174
});
174175

175-
it('generateContent: google maps grounding', async () => {
176+
it('generateContent: google maps grounding prompt location', async () => {
177+
const model = getGenerativeModel(testConfig.ai, {
178+
model: testConfig.model,
179+
generationConfig: commonGenerationConfig,
180+
safetySettings: commonSafetySettings,
181+
tools: [{ googleMaps: {} }]
182+
});
183+
184+
const result = await model.generateContent(
185+
'Where is a good place to grab a coffee near Arlington, MA?'
186+
);
187+
const response = result.response;
188+
const groundingMetadata = response.candidates?.[0].groundingMetadata;
189+
expect(groundingMetadata).to.exist;
190+
expect(
191+
groundingMetadata!.groundingChunks
192+
).to.have.length.greaterThanOrEqual(1);
193+
groundingMetadata!.groundingChunks!.forEach(groundingChunk => {
194+
expect(groundingChunk.maps).to.exist;
195+
expect(groundingChunk.maps!.uri).to.exist;
196+
expect(groundingChunk.maps!.title).to.exist;
197+
expect(groundingChunk.maps!.placeId).to.exist;
198+
});
199+
expect(
200+
groundingMetadata?.groundingSupports
201+
).to.have.length.greaterThanOrEqual(1);
202+
groundingMetadata!.groundingSupports!.forEach(groundingSupport => {
203+
expect(
204+
groundingSupport.groundingChunkIndices
205+
).to.have.length.greaterThanOrEqual(1);
206+
expect(groundingSupport.segment).to.exist;
207+
expect(groundingSupport.segment?.endIndex).to.exist;
208+
expect(groundingSupport.segment?.text).to.exist;
209+
});
210+
expect(groundingMetadata!.googleMapsWidgetContextToken).to.not.exist;
211+
});
212+
213+
it('generateContent: google maps grounding prompt location enableWidget true', async () => {
214+
const model = getGenerativeModel(testConfig.ai, {
215+
model: testConfig.model,
216+
generationConfig: commonGenerationConfig,
217+
safetySettings: commonSafetySettings,
218+
tools: [{ googleMaps: { enableWidget: true } }]
219+
});
220+
221+
const result = await model.generateContent(
222+
'Where is a good place to grab a coffee near Arlington, MA?'
223+
//'Where is the closest starbucks?'
224+
);
225+
const response = result.response;
226+
const groundingMetadata = response.candidates?.[0].groundingMetadata;
227+
expect(groundingMetadata).to.exist;
228+
expect(
229+
groundingMetadata!.groundingChunks
230+
).to.have.length.greaterThanOrEqual(1);
231+
groundingMetadata!.groundingChunks!.forEach(groundingChunk => {
232+
expect(groundingChunk.maps).to.exist;
233+
expect(groundingChunk.maps!.uri).to.exist;
234+
expect(groundingChunk.maps!.title).to.exist;
235+
expect(groundingChunk.maps!.placeId).to.exist;
236+
});
237+
expect(
238+
groundingMetadata?.groundingSupports
239+
).to.have.length.greaterThanOrEqual(1);
240+
groundingMetadata!.groundingSupports!.forEach(groundingSupport => {
241+
expect(
242+
groundingSupport.groundingChunkIndices
243+
).to.have.length.greaterThanOrEqual(1);
244+
expect(groundingSupport.segment).to.exist;
245+
expect(groundingSupport.segment?.endIndex).to.exist;
246+
expect(groundingSupport.segment?.text).to.exist;
247+
});
248+
expect(groundingMetadata!.googleMapsWidgetContextToken).to.exist;
249+
});
250+
251+
it('generateContent: google maps grounding prompt location enableWidget false', async () => {
252+
const model = getGenerativeModel(testConfig.ai, {
253+
model: testConfig.model,
254+
generationConfig: commonGenerationConfig,
255+
safetySettings: commonSafetySettings,
256+
tools: [{ googleMaps: { enableWidget: false } }]
257+
});
258+
259+
const result = await model.generateContent(
260+
'Where is a good place to grab a coffee near Arlington, MA?'
261+
//'Where is the closest starbucks?'
262+
);
263+
const response = result.response;
264+
const groundingMetadata = response.candidates?.[0].groundingMetadata;
265+
expect(groundingMetadata).to.exist;
266+
expect(
267+
groundingMetadata!.groundingChunks
268+
).to.have.length.greaterThanOrEqual(1);
269+
groundingMetadata!.groundingChunks!.forEach(groundingChunk => {
270+
expect(groundingChunk.maps).to.exist;
271+
expect(groundingChunk.maps!.uri).to.exist;
272+
expect(groundingChunk.maps!.title).to.exist;
273+
expect(groundingChunk.maps!.placeId).to.exist;
274+
});
275+
expect(
276+
groundingMetadata?.groundingSupports
277+
).to.have.length.greaterThanOrEqual(1);
278+
groundingMetadata!.groundingSupports!.forEach(groundingSupport => {
279+
expect(
280+
groundingSupport.groundingChunkIndices
281+
).to.have.length.greaterThanOrEqual(1);
282+
expect(groundingSupport.segment).to.exist;
283+
expect(groundingSupport.segment?.endIndex).to.exist;
284+
expect(groundingSupport.segment?.text).to.exist;
285+
});
286+
expect(groundingMetadata!.googleMapsWidgetContextToken).to.not.exist;
287+
});
288+
289+
it('generateContent: google maps grounding with lat long', async () => {
176290
const model = getGenerativeModel(testConfig.ai, {
177291
model: testConfig.model,
178292
generationConfig: commonGenerationConfig,
179293
safetySettings: commonSafetySettings,
180294
tools: [{ googleMaps: {} }],
181295
toolConfig: {
182296
retrievalConfig: {
183-
// Optionally provide the relevant location context (this is in Los Angeles)
184297
latLng: {
185-
latitude: 34.050481,
186-
longitude: -118.248526,
187-
},
188-
},
189-
},
298+
latitude: 42.4154,
299+
longitude: 71.1565
300+
}
301+
}
302+
}
190303
});
191304

192305
const result = await model.generateContent(
193-
'Where is a good place to grab a coffee in Arlington, MA?'
306+
'Where is a good place to grab a coffee near here?'
194307
//'Where is the closest starbucks?'
195308
);
196309
const response = result.response;
197-
const trimmedText = response.text().trim();
198310
const groundingMetadata = response.candidates?.[0].groundingMetadata;
199311
expect(groundingMetadata).to.exist;
200-
console.error("DEDB grounding medataData: ", JSON.stringify(groundingMetadata));
201312
expect(
202313
groundingMetadata!.groundingChunks
203314
).to.have.length.greaterThanOrEqual(1);
204315
groundingMetadata!.groundingChunks!.forEach(groundingChunk => {
205-
console.log("Grounding Chunk: ", JSON.stringify(groundingChunk));
206316
expect(groundingChunk.maps).to.exist;
207317
expect(groundingChunk.maps!.uri).to.exist;
208-
//expect(groundingChunk.maps!.text).to.exist;
209318
expect(groundingChunk.maps!.title).to.exist;
210319
expect(groundingChunk.maps!.placeId).to.exist;
211320
});
@@ -219,10 +328,55 @@ describe('Generate Content', function () {
219328
expect(groundingSupport.segment).to.exist;
220329
expect(groundingSupport.segment?.endIndex).to.exist;
221330
expect(groundingSupport.segment?.text).to.exist;
222-
// Since partIndex and startIndex are commonly 0, they may be omitted from responses.
223331
});
332+
expect(groundingMetadata!.googleMapsWidgetContextToken).to.not.exist;
224333
});
225334

335+
it('generateContent: google maps grounding with lat long enableWidget true', async () => {
336+
const model = getGenerativeModel(testConfig.ai, {
337+
model: testConfig.model,
338+
generationConfig: commonGenerationConfig,
339+
safetySettings: commonSafetySettings,
340+
tools: [{ googleMaps: { enableWidget: true } }],
341+
toolConfig: {
342+
retrievalConfig: {
343+
latLng: {
344+
latitude: 42.4154,
345+
longitude: 71.1565
346+
}
347+
}
348+
}
349+
});
350+
351+
const result = await model.generateContent(
352+
'Where is a good place to grab a coffee near here?'
353+
//'Where is the closest starbucks?'
354+
);
355+
const response = result.response;
356+
const groundingMetadata = response.candidates?.[0].groundingMetadata;
357+
expect(groundingMetadata).to.exist;
358+
expect(
359+
groundingMetadata!.groundingChunks
360+
).to.have.length.greaterThanOrEqual(1);
361+
groundingMetadata!.groundingChunks!.forEach(groundingChunk => {
362+
expect(groundingChunk.maps).to.exist;
363+
expect(groundingChunk.maps!.uri).to.exist;
364+
expect(groundingChunk.maps!.title).to.exist;
365+
expect(groundingChunk.maps!.placeId).to.exist;
366+
});
367+
expect(
368+
groundingMetadata?.groundingSupports
369+
).to.have.length.greaterThanOrEqual(1);
370+
groundingMetadata!.groundingSupports!.forEach(groundingSupport => {
371+
expect(
372+
groundingSupport.groundingChunkIndices
373+
).to.have.length.greaterThanOrEqual(1);
374+
expect(groundingSupport.segment).to.exist;
375+
expect(groundingSupport.segment?.endIndex).to.exist;
376+
expect(groundingSupport.segment?.text).to.exist;
377+
});
378+
expect(groundingMetadata!.googleMapsWidgetContextToken).to.exist;
379+
});
226380

227381
describe('URL Context', async () => {
228382
// URL Context is not supported in Google AI for gemini-2.0-flash

packages/ai/src/types/responses.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,19 @@ export interface Citation {
212212
/**
213213
* Metadata returned when grounding is enabled.
214214
*
215-
* Currently, only Grounding with Google Search is supported (see {@link GoogleSearchTool}).
215+
* Currently, only Grounding with Google Search and Google Maps is supported
216+
* (see {@link GoogleSearchTool} and {@link GoogleMapsTool}, respectively).
216217
*
217218
* Important: If using Grounding with Google Search, you are required to comply with the
218219
* "Grounding with Google Search" usage requirements for your chosen API provider: {@link https://ai.google.dev/gemini-api/terms#grounding-with-google-search | Gemini Developer API}
219220
* or Vertex AI Gemini API (see {@link https://cloud.google.com/terms/service-terms | Service Terms}
220221
* section within the Service Specific Terms).
221222
*
223+
* Important: If using Grounding with Google Maps, you are required to comply with the
224+
* "Grounding with Google Maps" usage requirements for your chosen API provider: {@link https://ai.google.dev/gemini-api/terms#grounding-with-google-maps | Gemini Developer API}
225+
* or Vertex AI Gemini API (see {@link https://cloud.google.com/terms/service-terms | Service Terms}
226+
* section within the Service Specific Terms).
227+
*
222228
* @public
223229
*/
224230
export interface GroundingMetadata {
@@ -247,6 +253,12 @@ export interface GroundingMetadata {
247253
* @deprecated Use {@link GroundingSupport} instead.
248254
*/
249255
retrievalQueries?: string[];
256+
/**
257+
* Resource name of the Google Maps widget context token that can be used with the
258+
* `PlacesContextElement` widget in order to render contextual data. Only populated in the case
259+
* that grounding with Google Maps is enabled.
260+
*/
261+
googleMapsWidgetContextToken?: string;
250262
}
251263

252264
/**

0 commit comments

Comments
 (0)