@@ -136,13 +136,16 @@ public struct Candidate: Sendable {
136
136
/// Cited works in the model's response content, if it exists.
137
137
public let citationMetadata : CitationMetadata ?
138
138
139
+ public let groundingMetadata : GroundingMetadata ?
140
+
139
141
/// Initializer for SwiftUI previews or tests.
140
142
public init ( content: ModelContent , safetyRatings: [ SafetyRating ] , finishReason: FinishReason ? ,
141
- citationMetadata: CitationMetadata ? ) {
143
+ citationMetadata: CitationMetadata ? , groundingMetadata : GroundingMetadata ? = nil ) {
142
144
self . content = content
143
145
self . safetyRatings = safetyRatings
144
146
self . finishReason = finishReason
145
147
self . citationMetadata = citationMetadata
148
+ self . groundingMetadata = groundingMetadata
146
149
}
147
150
}
148
151
@@ -299,6 +302,110 @@ public struct PromptFeedback: Sendable {
299
302
}
300
303
}
301
304
305
+ /// Metadata returned to the client when grounding is enabled.
306
+ ///
307
+ /// > Important: If using Grounding with Google Search, you are required to comply with the
308
+ /// "Grounding with Google Search" usage requirements for your chosen API provider:
309
+ /// [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-search)
310
+ /// or Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms)
311
+ /// section within the Service Specific Terms).
312
+ @available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
313
+ public struct GroundingMetadata : Sendable {
314
+ /// A list of web search queries that the model performed to gather the grounding information.
315
+ /// These can be used to allow users to explore the search results themselves.
316
+ public let webSearchQueries : [ String ]
317
+ /// A list of ``GroundingChunk`` structs. Each chunk represents a piece of retrieved content
318
+ /// (e.g., from a web page) that the model used to ground its response.
319
+ public let groundingChunks : [ GroundingChunk ]
320
+ /// A list of ``GroundingSupport`` structs. Each object details how specific segments of the
321
+ /// model's response are supported by the `groundingChunks`.
322
+ public let groundingSupports : [ GroundingSupport ]
323
+ /// Google Search entry point for web searches.
324
+ /// This contains an HTML/CSS snippet that **must** be embedded in an app to display a Google
325
+ /// Search entry point for follow-up web searches related to the model's "Grounded Response".
326
+ public let searchEntryPoint : SearchEntryPoint ?
327
+
328
+ /// A struct representing the Google Search entry point.
329
+ @available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
330
+ public struct SearchEntryPoint : Sendable {
331
+ /// An HTML/CSS snippet that can be embedded in your app.
332
+ ///
333
+ /// To ensure proper rendering, it's recommended to display this content within a `WKWebView`.
334
+ public let renderedContent : String
335
+ }
336
+
337
+ /// Represents a chunk of retrieved data that supports a claim in the model's response. This is
338
+ /// part of the grounding information provided when grounding is enabled.
339
+ @available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
340
+ public struct GroundingChunk : Sendable {
341
+ /// Contains details if the grounding chunk is from a web source.
342
+ public let web : WebGroundingChunk ?
343
+ }
344
+
345
+ /// A grounding chunk sourced from the web.
346
+ @available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
347
+ public struct WebGroundingChunk : Sendable {
348
+ /// The URI of the retrieved web page.
349
+ public let uri : String ?
350
+ /// The title of the retrieved web page.
351
+ public let title : String ?
352
+ /// The domain of the original URI from which the content was retrieved.
353
+ ///
354
+ /// This field is only populated when using the Vertex AI Gemini API.
355
+ public let domain : String ?
356
+ }
357
+
358
+ /// Provides information about how a specific segment of the model's response is supported by the
359
+ /// retrieved grounding chunks.
360
+ @available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
361
+ public struct GroundingSupport : Sendable {
362
+ /// Specifies the segment of the model's response content that this grounding support pertains
363
+ /// to.
364
+ public let segment : Segment
365
+
366
+ /// A list of indices that refer to specific ``GroundingChunk`` structs within the
367
+ /// ``GroundingMetadata/groundingChunks`` array. These referenced chunks are the sources that
368
+ /// support the claim made in the associated `segment` of the response. For example, an array
369
+ /// `[1, 3, 4]`
370
+ /// means that `groundingChunks[1]`, `groundingChunks[3]`, `groundingChunks[4]` are the
371
+ /// retrieved content supporting this part of the response.
372
+ public let groundingChunkIndices : [ Int ]
373
+
374
+ struct Internal {
375
+ let segment : Segment ?
376
+ let groundingChunkIndices : [ Int ]
377
+
378
+ func toPublic( ) -> GroundingSupport ? {
379
+ if segment == nil {
380
+ return nil
381
+ }
382
+ return GroundingSupport (
383
+ segment: segment!,
384
+ groundingChunkIndices: groundingChunkIndices
385
+ )
386
+ }
387
+ }
388
+ }
389
+ }
390
+
391
+ /// Represents a specific segment within a ``ModelContent`` struct, often used to pinpoint the
392
+ /// exact location of text or data that grounding information refers to.
393
+ @available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
394
+ public struct Segment : Sendable {
395
+ /// The zero-based index of the ``Part`` object within the `parts` array of its parent
396
+ /// ``ModelContent`` object. This identifies which part of the content the segment belongs to.
397
+ public let partIndex : Int
398
+ /// The zero-based start index of the segment within the specified ``Part``, measured in UTF-8
399
+ /// bytes. This offset is inclusive, starting from 0 at the beginning of the part's content.
400
+ public let startIndex : Int
401
+ /// The zero-based end index of the segment within the specified ``Part``, measured in UTF-8
402
+ /// bytes. This offset is exclusive, meaning the character at this index is not included in the
403
+ /// segment.
404
+ public let endIndex : Int
405
+ /// The text corresponding to the segment from the response.
406
+ public let text : String
407
+ }
408
+
302
409
// MARK: - Codable Conformances
303
410
304
411
@available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
@@ -369,6 +476,7 @@ extension Candidate: Decodable {
369
476
case safetyRatings
370
477
case finishReason
371
478
case citationMetadata
479
+ case groundingMetadata
372
480
}
373
481
374
482
/// Initializes a response from a decoder. Used for decoding server responses; not for public
@@ -414,6 +522,11 @@ extension Candidate: Decodable {
414
522
CitationMetadata . self,
415
523
forKey: . citationMetadata
416
524
)
525
+
526
+ groundingMetadata = try container. decodeIfPresent (
527
+ GroundingMetadata . self,
528
+ forKey: . groundingMetadata
529
+ )
417
530
}
418
531
}
419
532
@@ -513,3 +626,74 @@ extension PromptFeedback: Decodable {
513
626
}
514
627
}
515
628
}
629
+
630
+ @available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
631
+ extension GroundingMetadata : Decodable {
632
+ enum CodingKeys : String , CodingKey {
633
+ case webSearchQueries
634
+ case groundingChunks
635
+ case groundingSupports
636
+ case searchEntryPoint
637
+ }
638
+
639
+ public init ( from decoder: Decoder ) throws {
640
+ let container = try decoder. container ( keyedBy: CodingKeys . self)
641
+ webSearchQueries = try container. decodeIfPresent ( [ String ] . self, forKey: . webSearchQueries) ?? [ ]
642
+ groundingChunks = try container. decodeIfPresent (
643
+ [ GroundingChunk ] . self,
644
+ forKey: . groundingChunks
645
+ ) ?? [ ]
646
+ groundingSupports = try container. decodeIfPresent (
647
+ [ GroundingSupport . Internal ] . self,
648
+ forKey: . groundingSupports
649
+ ) ? . compactMap { $0. toPublic ( ) } ?? [ ]
650
+ searchEntryPoint = try container. decodeIfPresent (
651
+ SearchEntryPoint . self,
652
+ forKey: . searchEntryPoint
653
+ )
654
+ }
655
+ }
656
+
657
+ @available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
658
+ extension GroundingMetadata . SearchEntryPoint : Decodable { }
659
+
660
+ @available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
661
+ extension GroundingMetadata . GroundingChunk : Decodable { }
662
+
663
+ @available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
664
+ extension GroundingMetadata . WebGroundingChunk : Decodable { }
665
+
666
+ @available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
667
+ extension GroundingMetadata . GroundingSupport . Internal : Decodable {
668
+ enum CodingKeys : String , CodingKey {
669
+ case segment
670
+ case groundingChunkIndices
671
+ }
672
+
673
+ public init ( from decoder: Decoder ) throws {
674
+ let container = try decoder. container ( keyedBy: CodingKeys . self)
675
+ segment = try container. decodeIfPresent ( Segment . self, forKey: . segment)
676
+ groundingChunkIndices = try container. decodeIfPresent (
677
+ [ Int ] . self,
678
+ forKey: . groundingChunkIndices
679
+ ) ?? [ ]
680
+ }
681
+ }
682
+
683
+ @available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
684
+ extension Segment : Decodable {
685
+ enum CodingKeys : String , CodingKey {
686
+ case partIndex
687
+ case startIndex
688
+ case endIndex
689
+ case text
690
+ }
691
+
692
+ public init ( from decoder: Decoder ) throws {
693
+ let container = try decoder. container ( keyedBy: CodingKeys . self)
694
+ partIndex = try container. decodeIfPresent ( Int . self, forKey: . partIndex) ?? 0
695
+ startIndex = try container. decodeIfPresent ( Int . self, forKey: . startIndex) ?? 0
696
+ endIndex = try container. decodeIfPresent ( Int . self, forKey: . endIndex) ?? 0
697
+ text = try container. decodeIfPresent ( String . self, forKey: . text) ?? " "
698
+ }
699
+ }
0 commit comments