@@ -31,41 +31,62 @@ extension [ModelContent] {
3131 }
3232}
3333
34- /// A type describing data in media formats interpretable by an AI model. Each generative AI
35- /// request or response contains an `Array` of ``ModelContent``s, and each ``ModelContent`` value
36- /// may comprise multiple heterogeneous ``Part``s.
3734@available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
38- public struct ModelContent : Equatable , Sendable {
39- enum InternalPart : Equatable , Sendable {
35+ struct InternalPart : Equatable , Sendable {
36+ enum OneOfData : Equatable , Sendable {
4037 case text( String )
41- case inlineData( mimetype : String , Data )
42- case fileData( mimetype : String , uri : String )
38+ case inlineData( InlineData )
39+ case fileData( FileData )
4340 case functionCall( FunctionCall )
4441 case functionResponse( FunctionResponse )
4542 }
4643
44+ let data : OneOfData
45+
46+ let isThought : Bool ?
47+
48+ let thoughtSignature : String ?
49+
50+ init ( _ data: OneOfData , isThought: Bool ? , thoughtSignature: String ? ) {
51+ self . data = data
52+ self . isThought = isThought
53+ self . thoughtSignature = thoughtSignature
54+ }
55+ }
56+
57+ /// A type describing data in media formats interpretable by an AI model. Each generative AI
58+ /// request or response contains an `Array` of ``ModelContent``s, and each ``ModelContent`` value
59+ /// may comprise multiple heterogeneous ``Part``s.
60+ @available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
61+ public struct ModelContent : Equatable , Sendable {
4762 /// The role of the entity creating the ``ModelContent``. For user-generated client requests,
4863 /// for example, the role is `user`.
4964 public let role : String ?
5065
5166 /// The data parts comprising this ``ModelContent`` value.
5267 public var parts : [ any Part ] {
53- var convertedParts = [ any Part ] ( )
54- for part in internalParts {
55- switch part {
68+ return internalParts. map { part -> any Part in
69+ switch part. data {
5670 case let . text( text) :
57- convertedParts. append ( TextPart ( text) )
58- case let . inlineData( mimetype, data) :
59- convertedParts. append ( InlineDataPart ( data: data, mimeType: mimetype) )
60- case let . fileData( mimetype, uri) :
61- convertedParts. append ( FileDataPart ( uri: uri, mimeType: mimetype) )
71+ return TextPart ( text, isThought: part. isThought, thoughtSignature: part. thoughtSignature)
72+ case let . inlineData( inlineData) :
73+ return InlineDataPart (
74+ inlineData, isThought: part. isThought, thoughtSignature: part. thoughtSignature
75+ )
76+ case let . fileData( fileData) :
77+ return FileDataPart (
78+ fileData, isThought: part. isThought, thoughtSignature: part. thoughtSignature
79+ )
6280 case let . functionCall( functionCall) :
63- convertedParts. append ( FunctionCallPart ( functionCall) )
81+ return FunctionCallPart (
82+ functionCall, isThought: part. isThought, thoughtSignature: part. thoughtSignature
83+ )
6484 case let . functionResponse( functionResponse) :
65- convertedParts. append ( FunctionResponsePart ( functionResponse) )
85+ return FunctionResponsePart (
86+ functionResponse, isThought: part. isThought, thoughtSignature: part. thoughtSignature
87+ )
6688 }
6789 }
68- return convertedParts
6990 }
7091
7192 // TODO: Refactor this
@@ -78,17 +99,35 @@ public struct ModelContent: Equatable, Sendable {
7899 for part in parts {
79100 switch part {
80101 case let textPart as TextPart :
81- convertedParts. append ( . text( textPart. text) )
102+ convertedParts. append ( InternalPart (
103+ . text( textPart. text) ,
104+ isThought: textPart. _isThought,
105+ thoughtSignature: textPart. thoughtSignature
106+ ) )
82107 case let inlineDataPart as InlineDataPart :
83- let inlineData = inlineDataPart. inlineData
84- convertedParts. append ( . inlineData( mimetype: inlineData. mimeType, inlineData. data) )
108+ convertedParts. append ( InternalPart (
109+ . inlineData( inlineDataPart. inlineData) ,
110+ isThought: inlineDataPart. _isThought,
111+ thoughtSignature: inlineDataPart. thoughtSignature
112+ ) )
85113 case let fileDataPart as FileDataPart :
86- let fileData = fileDataPart. fileData
87- convertedParts. append ( . fileData( mimetype: fileData. mimeType, uri: fileData. fileURI) )
114+ convertedParts. append ( InternalPart (
115+ . fileData( fileDataPart. fileData) ,
116+ isThought: fileDataPart. _isThought,
117+ thoughtSignature: fileDataPart. thoughtSignature
118+ ) )
88119 case let functionCallPart as FunctionCallPart :
89- convertedParts. append ( . functionCall( functionCallPart. functionCall) )
120+ convertedParts. append ( InternalPart (
121+ . functionCall( functionCallPart. functionCall) ,
122+ isThought: functionCallPart. _isThought,
123+ thoughtSignature: functionCallPart. thoughtSignature
124+ ) )
90125 case let functionResponsePart as FunctionResponsePart :
91- convertedParts. append ( . functionResponse( functionResponsePart. functionResponse) )
126+ convertedParts. append ( InternalPart (
127+ . functionResponse( functionResponsePart. functionResponse) ,
128+ isThought: functionResponsePart. _isThought,
129+ thoughtSignature: functionResponsePart. thoughtSignature
130+ ) )
92131 default :
93132 fatalError ( )
94133 }
@@ -102,6 +141,11 @@ public struct ModelContent: Equatable, Sendable {
102141 let content = parts. flatMap { $0. partsValue }
103142 self . init ( role: role, parts: content)
104143 }
144+
145+ init ( role: String ? , parts: [ InternalPart ] ) {
146+ self . role = role
147+ internalParts = parts
148+ }
105149}
106150
107151// MARK: Codable Conformances
@@ -121,7 +165,29 @@ extension ModelContent: Codable {
121165}
122166
123167@available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
124- extension ModelContent . InternalPart : Codable {
168+ extension InternalPart : Codable {
169+ enum CodingKeys : String , CodingKey {
170+ case isThought = " thought "
171+ case thoughtSignature
172+ }
173+
174+ public func encode( to encoder: Encoder ) throws {
175+ try data. encode ( to: encoder)
176+ var container = encoder. container ( keyedBy: CodingKeys . self)
177+ try container. encodeIfPresent ( isThought, forKey: . isThought)
178+ try container. encodeIfPresent ( thoughtSignature, forKey: . thoughtSignature)
179+ }
180+
181+ public init ( from decoder: Decoder ) throws {
182+ data = try OneOfData ( from: decoder)
183+ let container = try decoder. container ( keyedBy: CodingKeys . self)
184+ isThought = try container. decodeIfPresent ( Bool . self, forKey: . isThought)
185+ thoughtSignature = try container. decodeIfPresent ( String . self, forKey: . thoughtSignature)
186+ }
187+ }
188+
189+ @available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
190+ extension InternalPart . OneOfData : Codable {
125191 enum CodingKeys : String , CodingKey {
126192 case text
127193 case inlineData
@@ -135,10 +201,10 @@ extension ModelContent.InternalPart: Codable {
135201 switch self {
136202 case let . text( text) :
137203 try container. encode ( text, forKey: . text)
138- case let . inlineData( mimetype , bytes ) :
139- try container. encode ( InlineData ( data : bytes , mimeType : mimetype ) , forKey: . inlineData)
140- case let . fileData( mimetype : mimetype , url ) :
141- try container. encode ( FileData ( fileURI : url , mimeType : mimetype ) , forKey: . fileData)
204+ case let . inlineData( inlineData ) :
205+ try container. encode ( inlineData , forKey: . inlineData)
206+ case let . fileData( fileData ) :
207+ try container. encode ( fileData , forKey: . fileData)
142208 case let . functionCall( functionCall) :
143209 try container. encode ( functionCall, forKey: . functionCall)
144210 case let . functionResponse( functionResponse) :
@@ -151,11 +217,9 @@ extension ModelContent.InternalPart: Codable {
151217 if values. contains ( . text) {
152218 self = try . text( values. decode ( String . self, forKey: . text) )
153219 } else if values. contains ( . inlineData) {
154- let inlineData = try values. decode ( InlineData . self, forKey: . inlineData)
155- self = . inlineData( mimetype: inlineData. mimeType, inlineData. data)
220+ self = try . inlineData( values. decode ( InlineData . self, forKey: . inlineData) )
156221 } else if values. contains ( . fileData) {
157- let fileData = try values. decode ( FileData . self, forKey: . fileData)
158- self = . fileData( mimetype: fileData. mimeType, uri: fileData. fileURI)
222+ self = try . fileData( values. decode ( FileData . self, forKey: . fileData) )
159223 } else if values. contains ( . functionCall) {
160224 self = try . functionCall( values. decode ( FunctionCall . self, forKey: . functionCall) )
161225 } else if values. contains ( . functionResponse) {
0 commit comments