Skip to content

Commit 79fd117

Browse files
authored
Merge f9a38a7 into aad3da8
2 parents aad3da8 + f9a38a7 commit 79fd117

File tree

11 files changed

+699
-35
lines changed

11 files changed

+699
-35
lines changed

firebase-ai/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# Unreleased
2+
* [feature] **Breaking Change**: Add support for Grounding with Google Search (#7042).
3+
* **Action Required:** Update all references of `groundingAttributions`, `webSearchQueries`, `retrievalQueries` in `GroundingMetadata` to be non-optional.
24

35

46
# 16.2.0

firebase-ai/api.txt

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,12 @@ package com.google.firebase.ai.type {
171171
method public com.google.firebase.ai.type.CitationMetadata? getCitationMetadata();
172172
method public com.google.firebase.ai.type.Content getContent();
173173
method public com.google.firebase.ai.type.FinishReason? getFinishReason();
174+
method public com.google.firebase.ai.type.GroundingMetadata? getGroundingMetadata();
174175
method public java.util.List<com.google.firebase.ai.type.SafetyRating> getSafetyRatings();
175176
property public final com.google.firebase.ai.type.CitationMetadata? citationMetadata;
176177
property public final com.google.firebase.ai.type.Content content;
177178
property public final com.google.firebase.ai.type.FinishReason? finishReason;
179+
property public final com.google.firebase.ai.type.GroundingMetadata? groundingMetadata;
178180
property public final java.util.List<com.google.firebase.ai.type.SafetyRating> safetyRatings;
179181
}
180182

@@ -398,6 +400,48 @@ package com.google.firebase.ai.type {
398400
method public com.google.firebase.ai.type.GenerativeBackend vertexAI(String location = "us-central1");
399401
}
400402

403+
public final class GoogleSearch {
404+
ctor public GoogleSearch();
405+
}
406+
407+
@Deprecated public final class GroundingAttribution {
408+
ctor @Deprecated public GroundingAttribution(com.google.firebase.ai.type.Segment segment, Float? confidenceScore);
409+
method @Deprecated public Float? getConfidenceScore();
410+
method @Deprecated public com.google.firebase.ai.type.Segment getSegment();
411+
property @Deprecated public final Float? confidenceScore;
412+
property @Deprecated public final com.google.firebase.ai.type.Segment segment;
413+
}
414+
415+
public final class GroundingChunk {
416+
ctor public GroundingChunk(com.google.firebase.ai.type.WebGroundingChunk? web);
417+
method public com.google.firebase.ai.type.WebGroundingChunk? getWeb();
418+
property public final com.google.firebase.ai.type.WebGroundingChunk? web;
419+
}
420+
421+
public final class GroundingMetadata {
422+
ctor public GroundingMetadata(java.util.List<java.lang.String> webSearchQueries, com.google.firebase.ai.type.SearchEntryPoint? searchEntryPoint, java.util.List<java.lang.String> retrievalQueries, @Deprecated java.util.List<com.google.firebase.ai.type.GroundingAttribution> groundingAttribution, java.util.List<com.google.firebase.ai.type.GroundingChunk> groundingChunks, java.util.List<com.google.firebase.ai.type.GroundingSupport> groundingSupports);
423+
method @Deprecated public java.util.List<com.google.firebase.ai.type.GroundingAttribution> getGroundingAttribution();
424+
method public java.util.List<com.google.firebase.ai.type.GroundingChunk> getGroundingChunks();
425+
method public java.util.List<com.google.firebase.ai.type.GroundingSupport> getGroundingSupports();
426+
method public java.util.List<java.lang.String> getRetrievalQueries();
427+
method public com.google.firebase.ai.type.SearchEntryPoint? getSearchEntryPoint();
428+
method public java.util.List<java.lang.String> getWebSearchQueries();
429+
property @Deprecated public final java.util.List<com.google.firebase.ai.type.GroundingAttribution> groundingAttribution;
430+
property public final java.util.List<com.google.firebase.ai.type.GroundingChunk> groundingChunks;
431+
property public final java.util.List<com.google.firebase.ai.type.GroundingSupport> groundingSupports;
432+
property public final java.util.List<java.lang.String> retrievalQueries;
433+
property public final com.google.firebase.ai.type.SearchEntryPoint? searchEntryPoint;
434+
property public final java.util.List<java.lang.String> webSearchQueries;
435+
}
436+
437+
public final class GroundingSupport {
438+
ctor public GroundingSupport(com.google.firebase.ai.type.Segment segment, java.util.List<java.lang.Integer> groundingChunkIndices);
439+
method public java.util.List<java.lang.Integer> getGroundingChunkIndices();
440+
method public com.google.firebase.ai.type.Segment getSegment();
441+
property public final java.util.List<java.lang.Integer> groundingChunkIndices;
442+
property public final com.google.firebase.ai.type.Segment segment;
443+
}
444+
401445
public final class HarmBlockMethod {
402446
method public int getOrdinal();
403447
property public final int ordinal;
@@ -897,6 +941,26 @@ package com.google.firebase.ai.type {
897941
method public com.google.firebase.ai.type.Schema str(String? description = null, boolean nullable = false, com.google.firebase.ai.type.StringFormat? format = null, String? title = null);
898942
}
899943

944+
public final class SearchEntryPoint {
945+
ctor public SearchEntryPoint(String renderedContent, String? sdkBlob);
946+
method public String getRenderedContent();
947+
method public String? getSdkBlob();
948+
property public final String renderedContent;
949+
property public final String? sdkBlob;
950+
}
951+
952+
public final class Segment {
953+
ctor public Segment(int startIndex, int endIndex, int partIndex, String text);
954+
method public int getEndIndex();
955+
method public int getPartIndex();
956+
method public int getStartIndex();
957+
method public String getText();
958+
property public final int endIndex;
959+
property public final int partIndex;
960+
property public final int startIndex;
961+
property public final String text;
962+
}
963+
900964
public final class SerializationException extends com.google.firebase.ai.type.FirebaseAIException {
901965
}
902966

@@ -935,11 +999,13 @@ package com.google.firebase.ai.type {
935999

9361000
public final class Tool {
9371001
method public static com.google.firebase.ai.type.Tool functionDeclarations(java.util.List<com.google.firebase.ai.type.FunctionDeclaration> functionDeclarations);
1002+
method public static com.google.firebase.ai.type.Tool googleSearch(com.google.firebase.ai.type.GoogleSearch googleSearch = com.google.firebase.ai.type.GoogleSearch());
9381003
field public static final com.google.firebase.ai.type.Tool.Companion Companion;
9391004
}
9401005

9411006
public static final class Tool.Companion {
9421007
method public com.google.firebase.ai.type.Tool functionDeclarations(java.util.List<com.google.firebase.ai.type.FunctionDeclaration> functionDeclarations);
1008+
method public com.google.firebase.ai.type.Tool googleSearch(com.google.firebase.ai.type.GoogleSearch googleSearch = com.google.firebase.ai.type.GoogleSearch());
9431009
}
9441010

9451011
public final class ToolConfig {
@@ -987,5 +1053,15 @@ package com.google.firebase.ai.type {
9871053
@Deprecated public static final class Voices.Companion {
9881054
}
9891055

1056+
public final class WebGroundingChunk {
1057+
ctor public WebGroundingChunk(String? uri, String? title, String? domain);
1058+
method public String? getDomain();
1059+
method public String? getTitle();
1060+
method public String? getUri();
1061+
property public final String? domain;
1062+
property public final String? title;
1063+
property public final String? uri;
1064+
}
1065+
9901066
}
9911067

firebase-ai/src/main/kotlin/com/google/firebase/ai/type/Candidate.kt

Lines changed: 207 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ import kotlinx.serialization.json.JsonNames
3333
* @property safetyRatings A list of [SafetyRating]s describing the generated content.
3434
* @property citationMetadata Metadata about the sources used to generate this content.
3535
* @property finishReason The reason the model stopped generating content, if it exist.
36+
* @property groundingMetadata Metadata returned to the client when grounding is enabled.
3637
*/
3738
public class Candidate
3839
internal constructor(
3940
public val content: Content,
4041
public val safetyRatings: List<SafetyRating>,
4142
public val citationMetadata: CitationMetadata?,
42-
public val finishReason: FinishReason?
43+
public val finishReason: FinishReason?,
44+
public val groundingMetadata: GroundingMetadata?
4345
) {
4446

4547
@Serializable
@@ -48,48 +50,22 @@ internal constructor(
4850
val finishReason: FinishReason.Internal? = null,
4951
val safetyRatings: List<SafetyRating.Internal>? = null,
5052
val citationMetadata: CitationMetadata.Internal? = null,
51-
val groundingMetadata: GroundingMetadata? = null,
53+
val groundingMetadata: GroundingMetadata.Internal? = null
5254
) {
5355
internal fun toPublic(): Candidate {
5456
val safetyRatings = safetyRatings?.mapNotNull { it.toPublic() }.orEmpty()
5557
val citations = citationMetadata?.toPublic()
5658
val finishReason = finishReason?.toPublic()
59+
val groundingMetadata = groundingMetadata?.toPublic()
5760

5861
return Candidate(
5962
this.content?.toPublic() ?: content("model") {},
6063
safetyRatings,
6164
citations,
62-
finishReason
65+
finishReason,
66+
groundingMetadata
6367
)
6468
}
65-
66-
@Serializable
67-
internal data class GroundingMetadata(
68-
@SerialName("web_search_queries") val webSearchQueries: List<String>?,
69-
@SerialName("search_entry_point") val searchEntryPoint: SearchEntryPoint?,
70-
@SerialName("retrieval_queries") val retrievalQueries: List<String>?,
71-
@SerialName("grounding_attribution") val groundingAttribution: List<GroundingAttribution>?,
72-
) {
73-
74-
@Serializable
75-
internal data class SearchEntryPoint(
76-
@SerialName("rendered_content") val renderedContent: String?,
77-
@SerialName("sdk_blob") val sdkBlob: String?,
78-
)
79-
80-
@Serializable
81-
internal data class GroundingAttribution(
82-
val segment: Segment,
83-
@SerialName("confidence_score") val confidenceScore: Float?,
84-
) {
85-
86-
@Serializable
87-
internal data class Segment(
88-
@SerialName("start_index") val startIndex: Int,
89-
@SerialName("end_index") val endIndex: Int,
90-
)
91-
}
92-
}
9369
}
9470
}
9571

@@ -317,3 +293,203 @@ public class FinishReason private constructor(public val name: String, public va
317293
public val MALFORMED_FUNCTION_CALL: FinishReason = FinishReason("MALFORMED_FUNCTION_CALL", 9)
318294
}
319295
}
296+
297+
/**
298+
* Metadata returned to the client when grounding is enabled.
299+
*
300+
* If using Grounding with Google Search, you are required to comply with the "Grounding with Google
301+
* Search" usage requirements for your chosen API provider:
302+
* [Gemini Developer
303+
* API](https://ai.google.dev/gemini-api/terms#grounding-with-google-search) or
304+
* Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) section
305+
* within the Service Specific Terms).
306+
*
307+
* @property webSearchQueries The list of web search queries that the model performed to gather the
308+
* grounding information. These can be used to allow users to explore the search results themselves.
309+
* @property searchEntryPoint Google search entry point for web searches. This contains an HTML/CSS
310+
* snippet that **must** be embedded in an app to display a Google Search Entry point for follow-up
311+
* web searches related to the model's "Grounded Response".
312+
* @property groundingChunks The list of [GroundingChunk] classes. Each chunk represents a piece of
313+
* retrieved content that the model used to ground its response.
314+
* @property groundingSupports The list of [GroundingSupport] objects. Each object details how
315+
* specific segments of the model's response are supported by the `groundingChunks`.
316+
*/
317+
public class GroundingMetadata(
318+
public val webSearchQueries: List<String>,
319+
public val searchEntryPoint: SearchEntryPoint?,
320+
public val retrievalQueries: List<String>,
321+
@Deprecated("Use groundingChunks instead")
322+
public val groundingAttribution: List<GroundingAttribution>,
323+
public val groundingChunks: List<GroundingChunk>,
324+
public val groundingSupports: List<GroundingSupport>,
325+
) {
326+
@Serializable
327+
internal data class Internal(
328+
val webSearchQueries: List<String>?,
329+
val searchEntryPoint: SearchEntryPoint.Internal?,
330+
val retrievalQueries: List<String>?,
331+
@Deprecated("Use groundingChunks instead")
332+
val groundingAttribution: List<GroundingAttribution.Internal>?,
333+
val groundingChunks: List<GroundingChunk.Internal>?,
334+
val groundingSupports: List<GroundingSupport.Internal>?,
335+
) {
336+
internal fun toPublic() =
337+
GroundingMetadata(
338+
webSearchQueries = webSearchQueries.orEmpty(),
339+
searchEntryPoint = searchEntryPoint?.toPublic(),
340+
retrievalQueries = retrievalQueries.orEmpty(),
341+
groundingAttribution = groundingAttribution?.map { it.toPublic() }.orEmpty(),
342+
groundingChunks = groundingChunks?.map { it.toPublic() }.orEmpty(),
343+
groundingSupports = groundingSupports?.map { it.toPublic() }.orEmpty().filterNotNull()
344+
)
345+
}
346+
}
347+
348+
/**
349+
* Represents a Google Search entry point.
350+
*
351+
* @property renderedContent An HTML/CSS snippet that can be embedded in your app. To ensure proper
352+
* rendering, it's recommended to display this content within a `WebView`.
353+
* @property sdkBlob A blob of data for the client SDK to render the search entry point.
354+
*/
355+
public class SearchEntryPoint(
356+
public val renderedContent: String,
357+
public val sdkBlob: String?,
358+
) {
359+
@Serializable
360+
internal data class Internal(
361+
val renderedContent: String?,
362+
val sdkBlob: String?,
363+
) {
364+
internal fun toPublic(): SearchEntryPoint {
365+
// If rendered content is null, the user must not display the grounded result. If they do,
366+
// they violate the service terms. To prevent this from happening, throw an exception.
367+
if (renderedContent == null) {
368+
throw SerializationException("renderedContent is null, should be a string")
369+
}
370+
return SearchEntryPoint(renderedContent = renderedContent, sdkBlob = sdkBlob)
371+
}
372+
}
373+
}
374+
375+
/**
376+
* Represents a chunk of retrieved data that supports a claim in the model's response. This is part
377+
* of the grounding information provided when grounding is enabled.
378+
*
379+
* @property web Contains details if the grounding chunk is from a web source.
380+
*/
381+
public class GroundingChunk(
382+
public val web: WebGroundingChunk?,
383+
) {
384+
@Serializable
385+
internal data class Internal(
386+
val web: WebGroundingChunk.Internal?,
387+
) {
388+
internal fun toPublic() = GroundingChunk(web = web?.toPublic())
389+
}
390+
}
391+
392+
/**
393+
* A grounding chunk from the web.
394+
*
395+
* @property uri The URI of the retrieved web page.
396+
* @property title The title of the retrieved web page.
397+
* @property domain The domain of the original URI from which the content was retrieved. This is
398+
* only populated when using the Vertex AI Gemini API.
399+
*/
400+
public class WebGroundingChunk(
401+
public val uri: String?,
402+
public val title: String?,
403+
public val domain: String?
404+
) {
405+
@Serializable
406+
internal data class Internal(val uri: String?, val title: String?, val domain: String?) {
407+
internal fun toPublic() = WebGroundingChunk(uri = uri, title = title, domain = domain)
408+
}
409+
}
410+
411+
/**
412+
* Provides information about how a specific segment of the model's response is supported by the
413+
* retrieved grounding chunks.
414+
*
415+
* @property segment Specifies the segment of the model's response content that this grounding
416+
* support pertains to.
417+
* @property groundingChunkIndices A list of indices that refer to specific [GroundingChunk] classes
418+
* within the [GroundingMetadata.groundingChunks] array. These referenced chunks are the sources
419+
* that support the claim made in the associated `segment` of the response. For example, an array
420+
* `[1, 3, 4]` means that `groundingChunks[1]`, `groundingChunks[3]`, `groundingChunks[4]` are the
421+
* retrieved content supporting this part of the response.
422+
*/
423+
public class GroundingSupport(
424+
public val segment: Segment,
425+
public val groundingChunkIndices: List<Int>,
426+
) {
427+
@Serializable
428+
internal data class Internal(
429+
val segment: Segment.Internal?,
430+
val groundingChunkIndices: List<Int>?,
431+
) {
432+
internal fun toPublic(): GroundingSupport? {
433+
if (segment == null) {
434+
return null
435+
}
436+
return GroundingSupport(
437+
segment = segment.toPublic(),
438+
groundingChunkIndices = groundingChunkIndices.orEmpty(),
439+
)
440+
}
441+
}
442+
}
443+
444+
@Deprecated("Use GroundingChunk instead")
445+
public class GroundingAttribution(
446+
public val segment: Segment,
447+
public val confidenceScore: Float?,
448+
) {
449+
@Deprecated("Use GroundingChunk instead")
450+
@Serializable
451+
internal data class Internal(
452+
val segment: Segment.Internal,
453+
val confidenceScore: Float?,
454+
) {
455+
internal fun toPublic() =
456+
GroundingAttribution(segment = segment.toPublic(), confidenceScore = confidenceScore)
457+
}
458+
}
459+
460+
/**
461+
* Represents a specific segment within a [Content] object, often used to pinpoint the exact
462+
* location of text or data that grounding information refers to.
463+
*
464+
* @property partIndex The zero-based index of the [Part] object within the `parts` array of its
465+
* parent [Content] object. This identifies which part of the content the segment belongs to.
466+
* @property startIndex The zero-based start index of the segment within the specified [Part],
467+
* measured in UTF-8 bytes. This offset is inclusive, starting from 0 at the beginning of the part's
468+
* content.
469+
* @property endIndex The zero-based end index of the segment within the specified [Part], measured
470+
* in UTF-8 bytes. This offset is exclusive, meaning the character at this index is not included in
471+
* the segment.
472+
* @property text The text corresponding to the segment from the response.
473+
*/
474+
public class Segment(
475+
public val startIndex: Int,
476+
public val endIndex: Int,
477+
public val partIndex: Int,
478+
public val text: String,
479+
) {
480+
@Serializable
481+
internal data class Internal(
482+
val startIndex: Int?,
483+
val endIndex: Int?,
484+
val partIndex: Int?,
485+
val text: String?,
486+
) {
487+
internal fun toPublic() =
488+
Segment(
489+
startIndex = startIndex ?: 0,
490+
endIndex = endIndex ?: 0,
491+
partIndex = partIndex ?: 0,
492+
text = text ?: ""
493+
)
494+
}
495+
}

0 commit comments

Comments
 (0)