@@ -63,4 +63,80 @@ public enum OpenAIRequest {
6363 let result = try JSONDecoder ( ) . decode ( T . self, from: text. data ( using: . utf8) !)
6464 return result
6565 }
66+
67+ struct PayloadWithImage < Schema: Codable > : Codable {
68+ let model : String
69+ let input : [ Input ]
70+ let reasoning : Reasoning
71+ let instructions : String
72+ let text : TextObject
73+ struct Reasoning : Codable {
74+ let effort : String ?
75+ }
76+ struct TextObject : Codable {
77+ let format : Schema
78+ }
79+ struct Input : Codable {
80+ var role : String
81+ var content : [ Content ]
82+ init ( content: [ Content ] ) {
83+ self . role = " user "
84+ self . content = content
85+ }
86+ struct Content : Codable {
87+ var type : String
88+ var detail : String ?
89+ var image_url : String ?
90+ var text : String ?
91+ }
92+ }
93+ }
94+
95+ public static func request< T: OpenAIStructureObject > ( input: String , instructions: String , image: Data , model: OpenAIModel , object: T . Type , apiKey: String ) async throws -> T {
96+ var req = URLRequest ( url: endpoint)
97+ req. httpMethod = " POST "
98+ req. addValue ( " application/json " , forHTTPHeaderField: " Content-Type " )
99+ req. addValue ( " Bearer \( apiKey) " , forHTTPHeaderField: " Authorization " )
100+ let payload : PayloadWithImage < SchemaRequest >
101+ if model. hasReasoning, case let OpenAIModel . o4_mini( reasoningEffort) = model {
102+ payload = PayloadWithImage (
103+ model: model. modelName,
104+ input: [
105+ . init(
106+ content: [
107+ . init( type: " input_text " , text: input) ,
108+ . init( type: " input_image " , detail: " high " , image_url: " data:image/jpeg;base64, " + image. base64EncodedString ( ) )
109+ ]
110+ )
111+ ] ,
112+ reasoning: . init( effort: reasoningEffort. rawValue) ,
113+ instructions: instructions,
114+ text: . init( format: T . schema)
115+ )
116+ } else {
117+ payload = PayloadWithImage (
118+ model: model. modelName,
119+ input: [
120+ . init(
121+ content: [
122+ . init( type: " input_text " , text: input) ,
123+ . init( type: " input_image " , detail: " high " , image_url: " data:image/jpeg;base64, " + image. base64EncodedString ( ) )
124+ ]
125+ )
126+ ] ,
127+ reasoning: . init( effort: nil ) ,
128+ instructions: instructions,
129+ text: . init( format: T . schema)
130+ )
131+ }
132+ req. httpBody = try JSONEncoder ( ) . encode ( payload)
133+ req. timeoutInterval = 300
134+ let ( data, _) = try await URLSession . shared. data ( for: req)
135+ guard let decoded = try ? JSONDecoder ( ) . decode ( OpenAIResponse . self, from: data) else {
136+ throw OpenAIStructureError ( message: String ( data: data, encoding: . utf8) ?? " error " )
137+ }
138+ let text = decoded. output. last!. content!. last!. text!
139+ let result = try JSONDecoder ( ) . decode ( T . self, from: text. data ( using: . utf8) !)
140+ return result
141+ }
66142}
0 commit comments