Skip to content

Commit

Permalink
Add and structure Swift SDK API reference (#1943)
Browse files Browse the repository at this point in the history
Co-authored-by: danielnugraha <[email protected]>
Co-authored-by: Taner Topal <[email protected]>
Co-authored-by: Daniel J. Beutel <[email protected]>
  • Loading branch information
4 people authored Jun 28, 2023
1 parent 3740ae1 commit 31c00d8
Show file tree
Hide file tree
Showing 10 changed files with 249 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/swift/flwr/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ let package = Package(
.package(url: "https://github.com/pvieito/PythonKit.git", branch: "master"),
.package(url: "https://github.com/kewlbear/NumPy-iOS.git", branch: "main"),
.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0"),
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.1.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
Expand Down
23 changes: 19 additions & 4 deletions src/swift/flwr/Sources/Flower/Client/Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,33 @@

import Foundation

/// The protocol class for the client implementation.
/// It contains abstract functions required for processing the server statements.
/// The expected return types are derived from the defined return structure.
/// Protocol for Flower clients.
///
/// ## Topics
///
/// ### Functionalities
///
/// - ``getParameters()``
/// - ``getProperties(ins:)-4u0tf``
/// - ``fit(ins:)``
/// - ``evaluate(ins:)``
public protocol Client {

/// Return the current local model parameters.
func getParameters() -> GetParametersRes

/// Return set of client properties.
func getProperties(ins: GetPropertiesIns) -> GetPropertiesRes

/// Refine the provided parameters using the locally held dataset.
func fit(ins: FitIns) -> FitRes

/// Evaluate the provided parameters using the locally held dataset.
func evaluate(ins: EvaluateIns) -> EvaluateRes
}

/// Extension to Client since per default GetPropertiesIns is not implemented.
public extension Client {
/// Extension to Client since per default GetPropertiesIns is not implemented.
func getProperties(ins: GetPropertiesIns) -> GetPropertiesRes {
return GetPropertiesRes(properties: [:], status: Status(code: .getPropertiesNotImplemented, message: String()))
}
Expand Down
8 changes: 8 additions & 0 deletions src/swift/flwr/Sources/Flower/Common/Exception.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@

import Foundation

/// Set of Flower client exceptions.
///
/// ## Topics
///
/// ### Exceptions
///
/// - ``TypeException(_:)``
/// - ``UnknownServerMessage``
public enum FlowerException: Error {
case TypeException(String)
case UnknownServerMessage
Expand Down
25 changes: 25 additions & 0 deletions src/swift/flwr/Sources/Flower/Common/Parameter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,24 @@ import os

let appDirectory = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!

/// A class responsible for (de)serializing model parameters.
///
/// ## Topics
///
/// ### Usage
///
/// - ``shared``
/// - ``finalize()``
///
/// ### Serialization
///
/// - ``multiArrayToData(multiArray:)``
/// - ``arrayToData(array:shape:)``
///
/// ### Deserialization
///
/// - ``dataToMultiArray(data:)``
/// - ``dataToArray(data:)``
@available(iOS 14.0, *)
public class ParameterConverter {
private var np: PythonObject?
Expand All @@ -26,6 +44,8 @@ public class ParameterConverter {

private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "flwr.Flower",
category: String(describing: ParameterConverter.self))

/// ParameterConverter singleton object.
public static let shared = ParameterConverter()

private init() {
Expand Down Expand Up @@ -126,6 +146,7 @@ public class ParameterConverter {
return nil
}

/// Deserialize bytes to MLMultiArray.
public func dataToMultiArray(data: Data) -> MLMultiArray? {
initGroup()
let future = group?.next().submit {
Expand All @@ -145,6 +166,7 @@ public class ParameterConverter {

}

/// Serialize MLMultiArray to bytes.
public func multiArrayToData(multiArray: MLMultiArray) -> Data? {
initGroup()
let future = group?.next().submit {
Expand All @@ -164,6 +186,7 @@ public class ParameterConverter {

}

/// Deserialize bytes into float array.
public func dataToArray(data: Data) -> [Float]? {
initGroup()
let future = group?.next().submit {
Expand All @@ -183,6 +206,7 @@ public class ParameterConverter {

}

/// Serialize float array to bytes.
public func arrayToData(array: [Float], shape: [Int16]) -> Data? {
initGroup()
let future = group?.next().submit {
Expand All @@ -199,6 +223,7 @@ public class ParameterConverter {
}
}

/// Shutdown EventLoopGroup gracefully.
public func finalize() {
initGroup()
let future = group?.next().submit {
Expand Down
84 changes: 84 additions & 0 deletions src/swift/flwr/Sources/Flower/Common/Typing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,37 @@

import Foundation

/// Client status codes.
///
/// ## Topics
///
/// ### Status Codes
///
/// - ``ok``
/// - ``getParametersNotImplemented``
/// - ``getPropertiesNotImplemented``
/// - ``fitNotImplemented``
/// - ``evaluateNotImplemented``
/// - ``UNRECOGNIZED(_:)``
public enum Code: Equatable {
typealias RawValue = Int

/// Everything is okay status code.
case ok

/// No client implementation for getProperties status code.
case getPropertiesNotImplemented

/// No client implementation for getParameters status code.
case getParametersNotImplemented

/// No client implementation for fit status code.
case fitNotImplemented

/// No client implementation for evaluate status code.
case evaluateNotImplemented

/// Unrecognized client status code.
case UNRECOGNIZED(Int)

init(rawValue: Int) {
Expand All @@ -39,13 +63,37 @@ public enum Code: Equatable {
}
}

/// Set of disconnect reasons for client.
///
/// ## Topics
///
/// ### Disconnect Reasons
///
/// - ``unknown``
/// - ``reconnect``
/// - ``powerDisconnected``
/// - ``wifiUnavailable``
/// - ``ack``
/// - ``UNRECOGNIZED(_:)``
public enum ReasonDisconnect {
typealias RawValue = Int

/// Unknown disconnect reason.
case unknown // = 0

/// Reconnect disconnect reason.
case reconnect // = 1

/// Power disconnected disconnect reason.
case powerDisconnected // = 2

/// WiFi unavailable disconnect reason.
case wifiUnavailable // = 3

/// Acknowledge disconnect reason.
case ack // = 4

/// Unrecognized disconnect reason.
case UNRECOGNIZED(Int)

var rawValue: Int {
Expand All @@ -60,17 +108,43 @@ public enum ReasonDisconnect {
}
}

/// Container for a set of recognised single quantity values.
///
/// ## Topics
///
/// ### Scalar Values
///
/// - ``bool``
/// - ``bytes``
/// - ``float``
/// - ``int``
/// - ``str``
public struct Scalar: Equatable {

/// Boolean scalar value.
public var bool: Bool?

/// Raw bytes scalar value.
public var bytes: Data?

/// Float scalar value.
public var float: Float?

/// Integer scalar value.
public var int: Int?

/// String scalar value.
public var str: String?
}

/// Typealias for a dictionary containing String and Scalar key-value pairs.
public typealias Metrics = [String: Scalar]

/// Typealias for a dictionary containing String and Scalar key-value pairs.
public typealias Properties = [String: Scalar]


/// Client status.
public struct Status: Equatable {
public static func == (lhs: Status, rhs: Status) -> Bool {
if lhs.code == rhs.code && lhs.message == rhs.message {
Expand All @@ -88,6 +162,7 @@ public struct Status: Equatable {
}
}

/// Parameters message.
public struct Parameters: Equatable {
public var tensors: [Data]
public var tensorType: String
Expand All @@ -98,6 +173,7 @@ public struct Parameters: Equatable {
}
}

/// Response when asked to return parameters.
public struct GetParametersRes: Equatable {
public var parameters: Parameters
public var status: Status
Expand All @@ -108,11 +184,13 @@ public struct GetParametersRes: Equatable {
}
}

/// Fit instructions for a client.
public struct FitIns: Equatable {
public var parameters: Parameters
public var config: [String: Scalar]
}

/// Fit response from a client.
public struct FitRes: Equatable {
public var parameters: Parameters
public var numExamples: Int
Expand All @@ -127,11 +205,13 @@ public struct FitRes: Equatable {
}
}

/// Evaluate instructions for a client.
public struct EvaluateIns: Equatable {
public var parameters: Parameters
public var config: [String: Scalar]
}

/// Evaluate response from a client.
public struct EvaluateRes: Equatable {
public static func == (lhs: EvaluateRes, rhs: EvaluateRes) -> Bool {
if lhs.loss == rhs.loss && lhs.numExamples == rhs.numExamples && lhs.metrics == rhs.metrics && lhs.status == rhs.status {
Expand All @@ -153,10 +233,12 @@ public struct EvaluateRes: Equatable {
}
}

/// Properties request for a client.
public struct GetPropertiesIns: Equatable {
public var config: Properties
}

/// Properties response from a client.
public struct GetPropertiesRes: Equatable {
public var properties: Properties
public var status: Status
Expand All @@ -166,10 +248,12 @@ public struct GetPropertiesRes: Equatable {
}
}

/// Reconnect message from server to client.
public struct Reconnect: Equatable {
public var seconds: Int?
}

/// Disconnect message from client to server.
public struct Disconnect: Equatable {
public var reason: String
}
Loading

0 comments on commit 31c00d8

Please sign in to comment.