Flower Swift SDK 实战指南:在 iOS 应用中集成联邦学习客户端
2026/9/17 16:19:51 网站建设 项目流程

Flower Swift SDK 实战指南:在 iOS 应用中集成联邦学习客户端

【免费下载链接】flowerFlower: A Friendly Federated AI Framework项目地址: https://gitcode.com/GitHub_Trending/flo/flower

Flower(A Friendly Federated AI Framework)为 Swift 开发者提供了一套原生 SDK,让你可以直接在 iOS 应用中实现联邦学习客户端,通过 gRPC 与 Flower 服务器通信,并借助 CoreML 完成本地模型训练。本文以 framework/swift/flwr/README.md 为主线,结合 SDK 源码(FlwrGRPCClient协议、ParameterConverter等)与仓库内的 FLiOS 端到端示例,系统讲解 Swift SDK 的安装方式、核心用法、通信与序列化原理,帮助你在自己的 Swift 项目中快速落地联邦学习能力。

一、Swift SDK 概览:它能做什么

flwrSwift SDK 的目标是“无缝地将 Flower 联邦 AI 框架集成进你现有的机器学习项目中”。从 Sources/Flower/flwr.docc/flwr.md 的说明可以看出,SDK 的核心能力分为三块:

  • Client协议:定义了一个 Flower 客户端必须实现的方法,这是所有客户端实现的统一契约;
  • FlwrGRPC:负责与 Flower 服务器建立 gRPC 双向流连接、收发消息;
  • MLFlwrClient:SDK 附带的默认客户端实现,使用 Apple CoreML 作为本地训练流水线(该实现位于 examples/ios/FLiOS/CoreMLClient/MLFlwrClient.swift,属于示例工程的一部分,而 SDK 包内提供协议与通信基础设施,方便你自行实现定制客户端)。

SDK 本身只要求 iOS 14.0 及以上(包级声明为.iOS(.v16),见 Package.swift),因此可以覆盖绝大多数现代 iOS 设备。

二、安装与集成:将 Swift 包手动接入项目

原文档给出的安装方式非常直接:下载 Flower 项目,然后把 Swift 包手动集成进你的工程

具体步骤如下:

  1. 获取 Flower 项目源码(例如git clone仓库后进入本地副本);
  2. 在 Xcode 中打开你的 iOS 工程,通过File → Add Packages…添加本地包,或直接在Package.swift中通过.package(path:)指向framework/swift/flwr目录;
  3. 在 target 中声明依赖.product(name: "flwr", package: "flwr")即可使用。

之所以推荐“本地路径集成”,是因为该包当前并未作为远程 SwiftPM 仓库发布,直接以本地路径引入最稳妥。包本身的 Package.swift 结构如下:

// swift-tools-version: 5.9 import PackageDescription let package = Package( name: "flwr", platforms: [.iOS(.v16)], products: [ .library(name: "flwr", targets: ["flwr"]), ], dependencies: [ .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.22.0"), .package(url: "https://github.com/apple/swift-protobuf.git", from: "1.26.0"), ], targets: [ .target( name: "flwr", dependencies: [ .product(name: "GRPC", package: "grpc-swift"), .product(name: "NumPy-iOS", package: "NumPy-iOS"), .product(name: "PythonKit", package: "PythonKit"), .product(name: "SwiftProtobuf", package: "swift-protobuf"), ], path: "Sources/Flower"), .testTarget(name: "FlowerTests", dependencies: ["flwr"]), ] )

可见 SDK 对外只暴露一个名为flwr的 library 产物,依赖解析(grpc-swiftNumPy-iOSPythonKitswift-protobuf)全部交由 SwiftPM 自动完成。首次构建会拉取这些依赖,请确保网络可达;如果是在模拟器/真机上运行,SwiftPM 会自动为 iOS 平台编译相应架构的依赖。

三、核心用法:三行代码启动联邦学习客户端

原文档给出了一个结构化的最小用法示例,这也是接入 SDK 的标准范式。完整保留如下,并补充逐行注释:

import flwr // 1. 构建一个符合 Client 协议的客户端实例 // - layerWrappers: 模型各层的信息(由 MLModelInspect 解析 .mlmodel 得到) // - dataLoader: 封装训练/测试数据批次(MLBatchProvider) // - compiledModelUrl: 编译后的 CoreML 模型路径(MLModel.compileModel 的产物) let mlFlwrClient = MLFlwrClient( layerWrappers: layerWrappers, dataLoader: dataLoader, compiledModelUrl: compiledModelUrl ) // 2. 创建指向 Flower 服务器的 gRPC 通信对象 let flwrGRPC = FlwrGRPC(serverHost: hostname, serverPort: port) // 3. 启动客户端并挂接完成回调 startFlwrGRPC(client: mlFlwrClient) { // completion handler print("Federated learning completed") }

这三个步骤分别对应 SDK 的三个核心抽象:客户端实现(Client)、通信通道(FlwrGRPC)、启动入口(startFlwrGRPC。其中FlwrGRPC的初始化器签名(见 FlwrGRPC.swift)为:

public init( serverHost: String, serverPort: Int, extendedInterceptor: InterceptorExtension? = nil )
  • serverHost:服务器地址(如"localhost"或局域网 IP);
  • serverPort:服务器监听端口(与 Python 端start_server的端口一致,示例中为8080);
  • extendedInterceptor:可选的自定义 gRPC 拦截器,用于观测/记录通信内容,详见下文第五节。

启动入口有两个重载:

public func startFlwrGRPC(client: Client) public func startFlwrGRPC(client: Client, completion: @escaping () -> Void)

不带completion的版本内部等价于传入空闭包。当联邦训练流程结束(服务器发送ReconnectIns/关闭流)时,completion会被调用——仓库示例正是借此把 UI 状态切换为“Federated learning completed”。

3.1 主动断开连接

除了被动等待流程结束,FlwrGRPC还提供了主动断开的方法:

public func abortGRPCConnection( reasonDisconnect: ReasonDisconnect, completion: @escaping () -> Void )

它会构造一条携带断开原因(ReasonDisconnect)的DisconnectRes消息发给服务器,然后关闭 gRPC 通道与事件循环组。ReasonDisconnect枚举定义于 Typing.swift,可取值为:unknown(0)reconnect(1)powerDisconnected(2)(电量断开)、wifiUnavailable(3)(Wi-Fi 不可用)、ack(4)(确认)。移动端场景下,电量与网络状态是客户端脱离联邦训练的主要原因,SDK 为此预留了语义化的断连原因。

四、Client 协议与消息类型:定制你的联邦客户端

Client协议是 SDK 最核心的抽象,定义于 Client.swift:

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 }

这四个方法与 Flower 联邦学习协议中的服务器→客户端指令一一对应:服务器下发全局参数请求客户端fit(本地训练)、evaluate(本地评估)、getParameters(上传参数)、getProperties(上报属性)。协议扩展(同文件 L35-L39)为getProperties提供了默认实现——返回Status(code: .getPropertiesNotImplemented, ...),因此你实现的客户端即使不提供属性上报也能编译通过。

4.1 消息类型速查

SDK 在 Typing.swift 中定义了完整的消息结构体,与 Flower 的 protobuf 协议一一对应:

类型字段语义
Parameterstensors: [Data]tensorType: String模型参数(多个张量的字节流)
GetParametersResparametersstatus返回本地参数
GetPropertiesIns/Resconfig/propertiesstatus属性请求与响应
FitInsparametersconfig训练指令(含服务器下发的全局参数与配置)
FitResparametersnumExamplesmetricsstatus训练结果
EvaluateInsparametersconfig评估指令
EvaluateReslossnumExamplesmetricsstatus评估结果(损失值)
Reconnect/Disconnectseconds/reason重连与断连消息
Statuscodemessage客户端状态
Scalarbool/bytes/float/int/str通用标量值容器

其中MetricsProperties均为[String: Scalar]字典别名;Status.code使用Code枚举(okgetPropertiesNotImplementedgetParametersNotImplementedfitNotImplementedevaluateNotImplemented等),便于服务器识别客户端能力缺失。

4.2 服务器消息的分发逻辑

FlwrGRPC收到服务器消息后,交由 MessageHandler.swift 中的handle(client:serverMsg:)按消息类型分发:

switch serverMsg.msg { case .reconnectIns: // 服务器要求重连/结束 let tuple = reconnect(reconnectMsg: serverMsg.reconnectIns) return (disconnectMsg, sleepDuration, false) case .getParametersIns: return (getParameters(client: client), 0, true) case .fitIns: return (fit(client: client, fitMsg: serverMsg.fitIns), 0, true) case .evaluateIns: return (evaluate(client: client, evaluateMsg: serverMsg.evaluateIns), 0, true) case .getPropertiesIns: return (getProperties(client: client, propertiesMsg: serverMsg.getPropertiesIns), 0, true) default: throw FlowerException.UnknownServerMessage }

返回的三元组(ClientMessage, sleepDuration, keepConnection)中:false表示流程结束应关闭连接,true表示保持连接等待下一条指令。特别地,reconnect处理逻辑(同文件 L38-L50)会读取服务器下发的seconds字段:若不为 0,则回执reason = .reconnect并携带睡眠时长;若为 0,则回执reason = .ack表示正常结束。这正好解释了上一节completion回调的触发时机。

五、通信层深度解析:gRPC 双向流与连接配置

FlwrGRPC基于grpc-swift实现客户端到服务器的通信,关键实现见 FlwrGRPC.swift。

5.1 连接初始化

初始化时(L79-L101)会完成以下配置:

  • 事件循环组PlatformSupport.makeEventLoopGroup(loopCount: 1, networkPreference: .best)
  • Keepalive 策略ClientConnectionKeepalive(interval: .seconds(1000), timeout: .seconds(999), permitWithoutCalls: true, maximumPingsWithoutData: 0)——在无 RPC 调用时也允许发送心跳,间隔 1000 秒、超时 999 秒,适合移动端省电场景;
  • 传输安全:默认transportSecurity: .plaintext(明文),即客户端默认以非 TLS 方式连接;
  • 消息长度上限maxMessageLength = 536870912(512 MB),并通过 gRPC 自定义 metadata(maxReceiveMessageLength/maxSendMessageLength)随请求一同下发,保证大模型参数(如大型 CNN 权重)也能完整传输。

5.2 双向流启动

startFlwrGRPC(L116-L134)内部创建Flwr_Proto_FlowerServiceNIOClient,调用join(callOptions:handler:)建立双向流式 RPC

self.bidirectionalStream = grpcClient.join(callOptions: callOptions, handler: { sm in do { let promise = self.eventLoopGroup.next().makePromise(of: GRPCResponse.self) let response = try handle(client: client, serverMsg: sm) promise.succeed(response) self.sendResponse(future: promise.futureResult, completion: completion) } catch { self.log.error("\(error)") } })

收到每条服务器消息后,分发到Client实现并异步等待执行结果,再通过sendResponse(L136-L148)把客户端响应写回流中。整个训练循环(多轮fit/evaluate)都在这一条长连接上完成,completion仅在流程终结时触发一次。

5.3 拦截器机制

SDK 内置了一套 gRPC 拦截器管线,位于 Interceptors.swift 与 InterceptorExtension.swift:

  • FlowerClientInterceptors会记录收发消息的 metadata、消息类型与文本大小,例如> Sending request FitRes with text size ...
  • 同时它把原始 gRPC 消息包装成GRPCPartWrapper.metadata(header:).message(content:).end(status:trailers:)),转发给用户自定义的InterceptorExtension

这意味着你可以在不改动 SDK 源码的前提下,注入自己的拦截器来观测每个请求/响应。仓库中的 FLiOS 示例正是通过FlwrGRPC(serverHost:serverPort:extendedInterceptor: BenchmarkInterceptor())挂接基准测试拦截器(见 FLiOSModel.swift),用于统计联邦训练的通信耗时。

六、参数序列化:PythonKit + NumPy 桥接 CoreML

联邦学习需要在客户端与服务器之间传递模型权重,而 CoreML 的MLMultiArray无法直接塞进 gRPC 消息。SDK 用ParameterConverter解决了这一问题,实现见 Parameter.swift:

  • 单例模式ParameterConverter.shared,内部持有一个MultiThreadedEventLoopGroup,并在首次使用时通过PythonSupport.initialize()初始化 Python 运行时、NumPySupport.sitePackagesURL.insertPythonPath()注入 NumPy 搜索路径,再Python.import("numpy")导入 NumPy;
  • 序列化multiArrayToData(multiArray:)MLMultiArray展平为[Float]后转成 NumPy 数组,np.save到临时文件再读回DataarrayToData(array:shape:)则直接用makeNumpyArray().reshape(shape)
  • 反序列化dataToMultiArray(data:)dataToArray(data:)Data写回临时文件后np.load,再还原为MLMultiArray[Float]
  • 资源释放finalize()会调用PythonSupport.finalize()并优雅关闭事件循环组。

也就是说,SDK 通过 PythonKit 在 iOS 上借道 NumPy 完成“字节流 ↔ 张量”的转换,张量形状信息也随序列化过程保留。仓库测试 FlowerTests.swift 验证了[Float] → Data → [Float]的往返一致性(含[1,2,3,4]与浮点精度用例),可作为接入自研模型的参考。

七、依赖项说明

原文档列出了三个关键依赖,结合 Package.swift 实际声明的四个包,整理如下:

依赖用途版本约束
grpc-swiftgRPC 通信框架,提供GRPCChannel、双向流、拦截器等from: 1.22.0
NumPy-iOS在 iOS 上编译 NumPy,供参数序列化使用branch: main
PythonKitSwift 与 Python 运行时互操作,负责调用 NumPybranch: master
swift-protobuf编译 Flower protobuf 消息(transport.pb.swifttransport.grpc.swift位于 Sources/Flower/FlowerProto)from: 1.26.0

其中PythonKitNumPy-iOS采用分支依赖,grpc-swiftswift-protobuf采用版本依赖。需要说明的是:这些依赖在构建时会从各自的远程仓库拉取,PythonKit/NumPy-iOS属于社区维护项目,使用前请留意其自身的许可证与维护状态。

八、端到端实践:FLiOS 示例 + Python 服务器

SDK 的完整落地可以参考仓库中的 examples/ios 示例工程(FLiOS)。它是一套面向研究者的 iOS 联邦学习应用,默认使用 MNIST 数据集与手写数字识别模型,引导用户依次完成“准备训练/测试数据 → 初始化本地客户端 → 连接服务器 → 启动联邦训练”的完整流程。

8.1 启动 Python 联邦服务器

examples/ios目录下先安装 Python 依赖(poetry installpip install -r requirements.txt),然后启动服务器:

python3 server.py -c 1 -r 1

server.py 中-c/--clients指定最小参与客户端数,-r/--rounds指定联邦轮数,默认各为 1;服务器监听[::]:8080,并自定义了SaveModelStrategy(继承FedAvg),每轮聚合后会把权重保存为round-{rnd}-weights.npz供离线分析。

8.2 在 iOS 端运行

  1. 用 Xcode 打开FLiOS.xcodeproj,等待 SwiftPM 拉取依赖后编译运行(可在模拟器或真机部署);
  2. 在 App 内依次点击加载训练集与测试集;
  3. 在界面文本框中填入服务器的 hostname 与端口(默认localhost:8080,真机场景应填写运行服务器电脑的局域网 IP);
  4. 点击 Start 启动联邦训练,训练结束会显示 “Federated learning completed”。

8.3 客户端实现样例

示例中 MLFlwrClient.swift 是Client协议的 CoreML 实现,其核心逻辑非常值得借鉴:

  • getParameters():调用parameters.initializeParameters()后用weightsToParameters()导出本地权重,返回GetParametersRes
  • fit(ins:):先用parametersToWeights(parameters: ins.parameters)把服务器下发的全局参数写入模型配置,再通过MLUpdateTask在本地数据集上训练(runMLTask(configuration:task: .train)),最后返回更新后的参数与样本数;
  • evaluate(ins:):同样写入参数后在测试集上跑 1 个 epoch(configuration.parameters = [epochs: 1]),返回损失值与样本数。

配合 FLiOSModel.swift 中的startFederatedLearning()可以看到完整调用链:MLModel.compileModel编译模型 →MLModelInspect解析层结构 → 构造MLFlwrClientFlwrGRPC(serverHost:serverPort:extendedInterceptor:)startFlwrGRPC(client:completion:)。这与你自己的 App 中接入 SDK 的路径完全一致。

九、许可证

Flower Swift SDK 采用Apache-2.0许可证(详见 LICENSE),你可以自由使用、修改与分发,只需保留原始版权声明与许可条款。

总结

Flower Swift SDK 提供了一条在 iOS 原生环境中参与联邦学习的成熟路径:Client协议统一了客户端行为契约,FlwrGRPC封装了 gRPC 双向流通信,ParameterConverter通过 PythonKit/NumPy 桥接 CoreML 张量与字节流,InterceptorExtension则开放了通信观测能力。参考本文的安装步骤、核心用法与 FLiOS 示例,你可以在自己的 Swift 项目中快速搭建起一个可对接 Flower 服务器的联邦学习客户端,并在此基础上按需定制模型训练流程与通信策略。

【免费下载链接】flowerFlower: A Friendly Federated AI Framework项目地址: https://gitcode.com/GitHub_Trending/flo/flower

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询