Skip to content

Commit

Permalink
Suplier naming and paginate
Browse files Browse the repository at this point in the history
  • Loading branch information
Maia-jp committed Jun 3, 2024
1 parent 274ef91 commit 64a294b
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 10 deletions.
2 changes: 1 addition & 1 deletion Sources/aiXplainKit/Modules/Asset/Suplier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public struct Supplier: Codable {
let id: Int

/// The name of the supplier.
let name: String
public let name: String

/// A unique code associated with the supplier.
let code: String
Expand Down
26 changes: 17 additions & 9 deletions Sources/aiXplainKit/Modules/Model/Model.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ do {
// Handle errors
}```
*/
public final class Model: DecodableAsset, CustomStringConvertible {
public final class Model: DecodableAsset, EncodableAsset, CustomStringConvertible {

/// Unique identifier for the model.
public var id: String
public var id: String

/// Name of the model.
public let name: String
Expand Down Expand Up @@ -99,13 +99,8 @@ public final class Model: DecodableAsset, CustomStringConvertible {
name = try container.decode(String.self, forKey: .name)
modelDescription = try container.decodeIfPresent(String.self, forKey: .description) ?? "An ML Model"

// Check if the "supplier" key is present and not an empty object
if var supplierContainer = try? container.nestedUnkeyedContainer(forKey: .supplier) {
supplier = try supplierContainer.decode(Supplier.self)
} else {
// Provide a default value for the supplier if it's missing or an empty object
supplier = Supplier(id: 0, name: "no", code: "")
}
// Decode the supplier field as a keyed container
supplier = try container.decodeIfPresent(Supplier.self, forKey: .supplier) ?? Supplier(id: 0, name: "no", code: "")

version = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .version).decodeIfPresent(String.self, forKey: .id) ?? "-"
pricing = try container.decode(Pricing.self, forKey: .pricing)
Expand Down Expand Up @@ -138,6 +133,19 @@ public final class Model: DecodableAsset, CustomStringConvertible {
self.logger = Logger(subsystem: "AiXplain", category: "Model(\(name)")
self.networking = networking
}


public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(name, forKey: .name)
try container.encode(modelDescription, forKey: .description)
try container.encode(supplier, forKey: .supplier)
try container.encode(version, forKey: .version)
try container.encode(license, forKey: .license)
try container.encode(privacy, forKey: .privacy)
try container.encode(pricing, forKey: .pricing)
}

// Private enum for coding keys to improve readability and maintainability.
private enum CodingKeys: String, CodingKey {
Expand Down
47 changes: 47 additions & 0 deletions Sources/aiXplainKit/Modules/Model/Query/ModelQuery.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// File.swift
//
//
// Created by Joao Pedro Monteiro Maia on 22/05/24.
//

import Foundation

//TODO: Add docs, this represents a query for a model
public struct ModelQuery{
var query:String?
var pageNumber:Int = 0
var pageSize:Int = 40
var functions:[String]

public init(query: String? = nil, pageNumber: Int = 0, pageSize: Int = 40, functions: [String]) {
self.query = query
self.pageNumber = pageNumber
self.pageSize = pageSize
self.functions = functions
}




public func buildQuery() throws ->Data{
var body:[String:Decodable] = ["pageNumber": pageNumber, "pageSize": pageSize]

if !functions.isEmpty{
body["functions"] = functions
}

if let q = query{
body["q"] = q
}


guard let jsonData = try? JSONSerialization.data(withJSONObject: body, options: []) else {
throw PipelineError.inputEncodingError //TODO: Implement proper error
}

return jsonData
}


}
4 changes: 4 additions & 0 deletions Sources/aiXplainKit/Networking/Networking+Endpoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ extension Networking {
case pipelines(pipelineIdentifier: String)

case pipelineRun(pipelineIdentifier: String)

case paginateModels

/// The path for the endpoint
var path: String {
Expand All @@ -63,6 +65,8 @@ extension Networking {
return "/sdk/pipelines/\(pipelineIdentifier)"
case .pipelineRun(pipelineIdentifier: let pipelineIdentifier):
return "/assets/pipeline/execution/run/\(pipelineIdentifier)"
case .paginateModels:
return "/sdk/models/paginate"
}
}
}
Expand Down
48 changes: 48 additions & 0 deletions Sources/aiXplainKit/Provider/ModelProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,5 +78,53 @@ public final class ModelProvider {
}

}

//TODO: Docs
public func list(_ query:ModelQuery) async throws -> [Model]{
let headers: [String: String] = try networking.buildHeader()

guard let url = APIKeyManager.shared.BACKEND_URL else {
throw ModelError.missingBackendURL
}

let endpoint = Networking.Endpoint.paginateModels
guard let url = URL(string: url.absoluteString + endpoint.path) else {
throw ModelError.invalidURL(url: url.absoluteString + endpoint.path)
}

let body = try query.buildQuery()
let response = try await networking.post(url: url, headers: headers, body: body)

if let httpUrlResponse = response.1 as? HTTPURLResponse,
httpUrlResponse.statusCode != 201 {
throw NetworkingError.invalidStatusCode(statusCode: httpUrlResponse.statusCode)
}


if let stringedResponse = String(data: response.0, encoding: .utf8){
return parseModelQueryResponse(stringedResponse) ?? []
}
return []

}

//TODO: Docs
private func parseModelQueryResponse(_ jsonData: String) -> [Model]? {
guard let data = jsonData.data(using: .utf8),
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
let itemsData = json["items"] as? [[String: Any]] else {
return nil
}

let items = itemsData.compactMap { itemDict -> Model? in
guard let itemData = try? JSONSerialization.data(withJSONObject: itemDict, options: []) else {
return nil
}

return try? JSONDecoder().decode(Model.self, from: itemData)
}

return items
}

}

0 comments on commit 64a294b

Please sign in to comment.