Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 4 additions & 23 deletions Sources/OpenAIKit/OpenAI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,10 @@ public final class OpenAI {
/// - Parameter b64Data: The `Base64` data itself in `String` form.
/// - Returns: A `UIImage` object.
public func decodeBase64Image(_ b64Data: String) throws -> UIImage {
do {
guard let data = Data(base64Encoded: b64Data) else {
throw OpenAIError.invalidData
}

guard let image = UIImage(data: data) else {
throw OpenAIError.invalidData
}

return image
} catch {
guard let data = Data(base64Encoded: b64Data), let image = UIImage(data: data) else {
throw OpenAIError.invalidData
}
return image
}
#endif

Expand All @@ -73,19 +64,10 @@ public final class OpenAI {
/// - Parameter b64Data: The `Base64` data itself in `String` form.
/// - Returns: An `NSImage` object.
public func decodeBase64Image(_ b64Data: String) throws -> NSImage {
do {
guard let data = Data(base64Encoded: b64Data) else {
throw OpenAIError.invalidData
}

guard let image = NSImage(data: data) else {
throw OpenAIError.invalidData
}

return image
} catch {
guard let data = Data(base64Encoded: b64Data), let image = NSImage(data: data) else {
throw OpenAIError.invalidData
}
return image
}
#endif

Expand All @@ -96,7 +78,6 @@ public final class OpenAI {
guard let result = URL(string: "https://api.openai.com/v1\(path)") else {
throw OpenAIError.invalidUrl
}

return result
}
}
Expand Down
58 changes: 27 additions & 31 deletions Sources/OpenAIKit/Utils/OpenAIKitSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -229,47 +229,43 @@ final class OpenAIKitSession {
formSubmission: Bool = false
) async throws -> T {
guard let apiKey = apiKey else { throw OpenAIError.noApiKey }

if bodyRequired {
guard let body = body else { throw OpenAIError.noBody }

if formSubmission {
let formRequest = FormDataHelper(formUrl: url)

body.forEach { (key, value) in
if let dataValue = value as? FormData {
formRequest.addDataField(named: key, formData: dataValue)
} else {
formRequest.addTextField(named: key, value: "\(value)")
}
}

let request = formRequest.asURLRequest(apiKey: apiKey)
let data = try await self.asyncData(with: request)

return try OpenAIKitSession.decodeData(with: data)
} else {
let jsonData = try? JSONSerialization.data(withJSONObject: body)
guard let body = body else {
if !bodyRequired && !formSubmission { // no body req - no form
let data = try await self.asyncData(
with: url, method: method,
headers: ["Authorization": "Bearer \(apiKey)"],
body: jsonData
with: url,
method: method,
headers: ["Authorization": "Bearer \(apiKey)"]
)

return try OpenAIKitSession.decodeData(with: data)
}
throw OpenAIError.noBody // no body
}

if !bodyRequired && !formSubmission {
if formSubmission { // body required + form sub
let formRequest = FormDataHelper(formUrl: url)

body.forEach { (key, value) in
if let dataValue = value as? FormData {
formRequest.addDataField(named: key, formData: dataValue)
} else {
formRequest.addTextField(named: key, value: "\(value)")
}
}

let request = formRequest.asURLRequest(apiKey: apiKey)
let data = try await self.asyncData(with: request)

return try OpenAIKitSession.decodeData(with: data)
} else { // body required only
let jsonData = try? JSONSerialization.data(withJSONObject: body)
let data = try await self.asyncData(
with: url,
method: method,
headers: ["Authorization": "Bearer \(apiKey)"]
with: url, method: method,
headers: ["Authorization": "Bearer \(apiKey)"],
body: jsonData
)

return try OpenAIKitSession.decodeData(with: data)
}

throw OpenAIError.noBody
}
}
25 changes: 4 additions & 21 deletions Sources/OpenAIKit/Utils/OpenAIStreamer/OpenAISource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -231,27 +231,10 @@ public extension OpenAISource {
let connection = OpenAISource(url: self.url)

connection.onMessageCallback = { message in
do {
if message.data != nil, message.data! == "[DONE]" {
continuation.finish()
}

guard let data = message.data?.data(using: .utf8) else {
throw OpenAIError.invalidData
}
let result = try OpenAIKitSession.decodeData(T.self, with: data)
continuation.yield(result)
} catch {
do {
guard let data = message.data?.data(using: .utf8) else {
throw OpenAIError.invalidData
}
let errorOpenAI = try JSONDecoder().decode(OpenAIErrorResponse.self, from: data)
continuation.finish(throwing: errorOpenAI)
} catch {
continuation.finish(throwing: error)
}
}
guard let messageData = message.data, messageData != "[DONE]"
else { return message.data == nil ? continuation.finish(throwing: OpenAIError.invalidData) : continuation.finish() }
do { continuation.yield(try OpenAIKitSession.decodeData(T.self, with: Data(messageData.utf8))) }
catch { continuation.finish(throwing: error) }
}

continuation.onTermination = { @Sendable _ in
Expand Down