-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[FirebaseAI] Add support for Grounding with Google Search #15014
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
f6cd757
8e76a6b
5e5be35
bb42191
1dad0e6
84f548c
72901b4
0c011ae
c7eb33e
da9fdc9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -136,13 +136,16 @@ public struct Candidate: Sendable { | |
/// Cited works in the model's response content, if it exists. | ||
public let citationMetadata: CitationMetadata? | ||
|
||
public let groundingMetadata: GroundingMetadata? | ||
|
||
/// Initializer for SwiftUI previews or tests. | ||
public init(content: ModelContent, safetyRatings: [SafetyRating], finishReason: FinishReason?, | ||
citationMetadata: CitationMetadata?) { | ||
citationMetadata: CitationMetadata?, groundingMetadata: GroundingMetadata? = nil) { | ||
self.content = content | ||
self.safetyRatings = safetyRatings | ||
self.finishReason = finishReason | ||
self.citationMetadata = citationMetadata | ||
self.groundingMetadata = groundingMetadata | ||
} | ||
} | ||
|
||
|
@@ -299,6 +302,123 @@ public struct PromptFeedback: Sendable { | |
} | ||
} | ||
|
||
/// Metadata returned to the client when grounding is enabled. | ||
/// | ||
/// > Important: If using Grounding with Google Search, you are required to comply with the [Service | ||
/// Specific Terms](https://cloud.google.com/terms/service-terms) for *Grounding with Google | ||
/// Search*. | ||
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) | ||
public struct GroundingMetadata: Sendable { | ||
/// A list of web search queries that the model performed to gather the grounding information. | ||
/// These can be used to allow users to explore the search results themselves. | ||
/// | ||
/// > Important: If using Grounding with Google Search, you are required to comply with the | ||
/// [Service Specific Terms](https://cloud.google.com/terms/service-terms) for *Grounding with | ||
/// Google Search*. | ||
public let webSearchQueries: [String] | ||
/// A list of ``GroundingChunk`` structs. Each chunk represents a piece of retrieved content | ||
/// (e.g., from a web page) that the model used to ground its response. | ||
/// | ||
/// > Important: If using Grounding with Google Search, you are required to comply with the | ||
/// [Service Specific Terms](https://cloud.google.com/terms/service-terms) for *Grounding with | ||
/// Google Search*. | ||
public let groundingChunks: [GroundingChunk] | ||
/// A list of ``GroundingSupport`` structs. Each object details how specific segments of the | ||
/// model's response are supported by the `groundingChunks`. | ||
/// | ||
/// > Important: If using Grounding with Google Search, you are required to comply with the | ||
/// [Service Specific Terms](https://cloud.google.com/terms/service-terms) for *Grounding with | ||
/// Google Search*. | ||
public let groundingSupports: [GroundingSupport] | ||
/// Google search entry point for web searches. | ||
/// This contains an HTML/CSS snippet that **must** be embedded in an app to display a Google | ||
/// Search Entry point for follow-up web searches related to the model's "Grounded Response". | ||
/// | ||
/// > Important: If using Grounding with Google Search, you are required to comply with the | ||
/// [Service Specific Terms](https://cloud.google.com/terms/service-terms) for *Grounding with | ||
/// Google Search*. | ||
public let searchEntryPoint: SearchEntryPoint? | ||
|
||
/// A struct representing the Google Search entry point. | ||
/// | ||
/// > Important: If using Grounding with Google Search, you are required to comply with the | ||
/// [Service Specific Terms](https://cloud.google.com/terms/service-terms) for *Grounding with | ||
/// Google Search*. | ||
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) | ||
public struct SearchEntryPoint: Sendable { | ||
/// An HTML/CSS snippet that can be embedded in your app. The snippet is designed to avoid | ||
/// undesired interaction with the rest of the page's CSS. | ||
/// | ||
/// To ensure proper rendering, it's recommended to display this content within a `WKWebView`. | ||
public let renderedContent: String? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think it's likely that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we are re-evaluating mirroring the protos for this, we should make this non-optional. Displaying a grounded result without displaying Thoughts? @andrewheard @paulb777 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Failing early when the service terms can't be met SGTM |
||
} | ||
|
||
/// Represents a chunk of retrieved data that supports a claim in the model's response. This is | ||
/// part | ||
/// of the grounding information provided when grounding is enabled. | ||
/// | ||
/// > Important: If using Grounding with Google Search, you are required to comply with the | ||
/// [Service Specific Terms](https://cloud.google.com/terms/service-terms) for *Grounding with | ||
/// Google Search*. | ||
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) | ||
public struct GroundingChunk: Sendable { | ||
/// Contains details if the grounding chunk is from a web source. | ||
public let web: WebGroundingChunk? | ||
} | ||
|
||
/// A grounding chunk sourced from the web. | ||
/// | ||
/// > Important: If using Grounding with Google Search, you are required to comply with the | ||
/// [Service Specific Terms](https://cloud.google.com/terms/service-terms) for *Grounding with | ||
/// Google Search*. | ||
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) | ||
public struct WebGroundingChunk: Sendable { | ||
/// The URI of the retrieved web page. | ||
public let uri: String? | ||
/// The title of the retrieved web page. | ||
public let title: String? | ||
dlarocque marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// The domain of the original URI from which the content was retrieved (e.g., `example.com`). | ||
/// | ||
/// This field is only populated when using the Vertex AI Gemini API. | ||
public let domain: String? | ||
} | ||
|
||
/// Provides information about how a specific segment of the model's response is supported by the | ||
/// retrieved grounding chunks. | ||
/// | ||
/// > Important: If using Grounding with Google Search, you are required to comply with the | ||
/// [Service Specific Terms](https://cloud.google.com/terms/service-terms) for *Grounding with | ||
/// Google Search*. | ||
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) | ||
public struct GroundingSupport: Sendable { | ||
/// Specifies the segment of the model's response content that this grounding support pertains | ||
/// to. | ||
public let segment: Segment? | ||
Comment on lines
+394
to
+396
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Based on the documentation for GroundingSupport above
Does it make sense for a developer to ever get a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. It does not make sense for a developer to get a This should be non-optional, and we should remove the |
||
|
||
/// A list of indices that refer to specific ``GroundingChunk`` structs within the | ||
/// ``GroundingMetadata/groundingChunks`` array. These referenced chunks are the sources that | ||
/// support the claim made in the associated `segment` of the response. | ||
public let groundingChunkIndices: [Int] | ||
} | ||
} | ||
|
||
/// Represents a specific segment within a ``ModelContent`` struct, often used to pinpoint the | ||
/// exact location of text or data that grounding information refers to. | ||
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) | ||
public struct Segment: Sendable { | ||
/// The zero-based index of the ``Part`` object within the `parts` array of its parent | ||
/// ``ModelContent`` object. This identifies which part of the content the segment belongs to. | ||
public let partIndex: Int | ||
/// The zero-based start index of the segment within the specified ``Part``, measured in UTF-8 | ||
/// bytes. This offset is inclusive, starting from 0 at the beginning of the part's content. | ||
public let startIndex: Int | ||
/// The zero-based end index of the segment within the specified ``Part``, measured in UTF-8 | ||
/// bytes. This offset is exclusive. | ||
public let endIndex: Int | ||
/// The text content of the segment. | ||
public let text: String | ||
} | ||
|
||
// MARK: - Codable Conformances | ||
|
||
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) | ||
|
@@ -369,6 +489,7 @@ extension Candidate: Decodable { | |
case safetyRatings | ||
case finishReason | ||
case citationMetadata | ||
case groundingMetadata | ||
} | ||
|
||
/// Initializes a response from a decoder. Used for decoding server responses; not for public | ||
|
@@ -414,6 +535,11 @@ extension Candidate: Decodable { | |
CitationMetadata.self, | ||
forKey: .citationMetadata | ||
) | ||
|
||
groundingMetadata = try container.decodeIfPresent( | ||
GroundingMetadata.self, | ||
forKey: .groundingMetadata | ||
) | ||
} | ||
} | ||
|
||
|
@@ -513,3 +639,74 @@ extension PromptFeedback: Decodable { | |
} | ||
} | ||
} | ||
|
||
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) | ||
extension GroundingMetadata: Decodable { | ||
enum CodingKeys: String, CodingKey { | ||
case webSearchQueries | ||
case groundingChunks | ||
case groundingSupports | ||
case searchEntryPoint | ||
} | ||
|
||
public init(from decoder: Decoder) throws { | ||
let container = try decoder.container(keyedBy: CodingKeys.self) | ||
webSearchQueries = try container.decodeIfPresent([String].self, forKey: .webSearchQueries) ?? [] | ||
groundingChunks = try container.decodeIfPresent( | ||
[GroundingChunk].self, | ||
forKey: .groundingChunks | ||
) ?? [] | ||
groundingSupports = try container.decodeIfPresent( | ||
[GroundingSupport].self, | ||
forKey: .groundingSupports | ||
) ?? [] | ||
searchEntryPoint = try container.decodeIfPresent( | ||
SearchEntryPoint.self, | ||
forKey: .searchEntryPoint | ||
) | ||
} | ||
} | ||
|
||
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) | ||
extension GroundingMetadata.SearchEntryPoint: Decodable {} | ||
|
||
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) | ||
extension GroundingMetadata.GroundingChunk: Decodable {} | ||
|
||
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) | ||
extension GroundingMetadata.WebGroundingChunk: Decodable {} | ||
|
||
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) | ||
extension GroundingMetadata.GroundingSupport: Decodable { | ||
enum CodingKeys: String, CodingKey { | ||
case segment | ||
case groundingChunkIndices | ||
} | ||
|
||
public init(from decoder: Decoder) throws { | ||
let container = try decoder.container(keyedBy: CodingKeys.self) | ||
segment = try container.decodeIfPresent(Segment.self, forKey: .segment) | ||
groundingChunkIndices = try container.decodeIfPresent( | ||
[Int].self, | ||
forKey: .groundingChunkIndices | ||
) ?? [] | ||
} | ||
} | ||
|
||
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) | ||
extension Segment: Decodable { | ||
enum CodingKeys: String, CodingKey { | ||
case partIndex | ||
case startIndex | ||
case endIndex | ||
case text | ||
} | ||
|
||
public init(from decoder: Decoder) throws { | ||
let container = try decoder.container(keyedBy: CodingKeys.self) | ||
partIndex = try container.decodeIfPresent(Int.self, forKey: .partIndex) ?? 0 | ||
startIndex = try container.decodeIfPresent(Int.self, forKey: .startIndex) ?? 0 | ||
endIndex = try container.decodeIfPresent(Int.self, forKey: .endIndex) ?? 0 | ||
text = try container.decodeIfPresent(String.self, forKey: .text) ?? "" | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.