flwr-nightly 1.8.0.dev20240315__py3-none-any.whl → 1.11.0.dev20240813__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of flwr-nightly might be problematic. Click here for more details.

Files changed (237) hide show
  1. flwr/cli/app.py +7 -0
  2. flwr/cli/build.py +150 -0
  3. flwr/cli/config_utils.py +219 -0
  4. flwr/cli/example.py +3 -1
  5. flwr/cli/install.py +227 -0
  6. flwr/cli/new/new.py +179 -48
  7. flwr/cli/new/templates/app/.gitignore.tpl +160 -0
  8. flwr/cli/new/templates/app/README.flowertune.md.tpl +56 -0
  9. flwr/cli/new/templates/app/README.md.tpl +1 -5
  10. flwr/cli/new/templates/app/code/__init__.py.tpl +1 -1
  11. flwr/cli/new/templates/app/code/client.huggingface.py.tpl +65 -0
  12. flwr/cli/new/templates/app/code/client.jax.py.tpl +56 -0
  13. flwr/cli/new/templates/app/code/client.mlx.py.tpl +93 -0
  14. flwr/cli/new/templates/app/code/client.numpy.py.tpl +3 -2
  15. flwr/cli/new/templates/app/code/client.pytorch.py.tpl +23 -11
  16. flwr/cli/new/templates/app/code/client.sklearn.py.tpl +97 -0
  17. flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +60 -1
  18. flwr/cli/new/templates/app/code/flwr_tune/__init__.py +15 -0
  19. flwr/cli/new/templates/app/code/flwr_tune/app.py.tpl +89 -0
  20. flwr/cli/new/templates/app/code/flwr_tune/client.py.tpl +126 -0
  21. flwr/cli/new/templates/app/code/flwr_tune/config.yaml.tpl +34 -0
  22. flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl +57 -0
  23. flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +59 -0
  24. flwr/cli/new/templates/app/code/flwr_tune/server.py.tpl +48 -0
  25. flwr/cli/new/templates/app/code/flwr_tune/static_config.yaml.tpl +11 -0
  26. flwr/cli/new/templates/app/code/server.huggingface.py.tpl +23 -0
  27. flwr/cli/new/templates/app/code/server.jax.py.tpl +20 -0
  28. flwr/cli/new/templates/app/code/server.mlx.py.tpl +20 -0
  29. flwr/cli/new/templates/app/code/server.numpy.py.tpl +17 -9
  30. flwr/cli/new/templates/app/code/server.pytorch.py.tpl +21 -18
  31. flwr/cli/new/templates/app/code/server.sklearn.py.tpl +24 -0
  32. flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +29 -1
  33. flwr/cli/new/templates/app/code/task.huggingface.py.tpl +99 -0
  34. flwr/cli/new/templates/app/code/task.jax.py.tpl +57 -0
  35. flwr/cli/new/templates/app/code/task.mlx.py.tpl +102 -0
  36. flwr/cli/new/templates/app/code/task.pytorch.py.tpl +28 -23
  37. flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +53 -0
  38. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +39 -0
  39. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +38 -0
  40. flwr/cli/new/templates/app/pyproject.jax.toml.tpl +34 -0
  41. flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +39 -0
  42. flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +25 -12
  43. flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +29 -14
  44. flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +33 -0
  45. flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +29 -14
  46. flwr/cli/run/run.py +168 -17
  47. flwr/cli/utils.py +75 -4
  48. flwr/client/__init__.py +6 -1
  49. flwr/client/app.py +239 -248
  50. flwr/client/client_app.py +70 -9
  51. flwr/client/dpfedavg_numpy_client.py +1 -1
  52. flwr/client/grpc_adapter_client/__init__.py +15 -0
  53. flwr/client/grpc_adapter_client/connection.py +97 -0
  54. flwr/client/grpc_client/connection.py +18 -5
  55. flwr/client/grpc_rere_client/__init__.py +1 -1
  56. flwr/client/grpc_rere_client/client_interceptor.py +158 -0
  57. flwr/client/grpc_rere_client/connection.py +127 -33
  58. flwr/client/grpc_rere_client/grpc_adapter.py +140 -0
  59. flwr/client/heartbeat.py +74 -0
  60. flwr/client/message_handler/__init__.py +1 -1
  61. flwr/client/message_handler/message_handler.py +7 -7
  62. flwr/client/mod/__init__.py +5 -5
  63. flwr/client/mod/centraldp_mods.py +4 -2
  64. flwr/client/mod/comms_mods.py +4 -4
  65. flwr/client/mod/localdp_mod.py +9 -4
  66. flwr/client/mod/secure_aggregation/__init__.py +1 -1
  67. flwr/client/mod/secure_aggregation/secaggplus_mod.py +1 -1
  68. flwr/client/mod/utils.py +1 -1
  69. flwr/client/node_state.py +60 -10
  70. flwr/client/node_state_tests.py +4 -3
  71. flwr/client/rest_client/__init__.py +1 -1
  72. flwr/client/rest_client/connection.py +177 -157
  73. flwr/client/supernode/__init__.py +26 -0
  74. flwr/client/supernode/app.py +464 -0
  75. flwr/client/typing.py +1 -0
  76. flwr/common/__init__.py +13 -11
  77. flwr/common/address.py +1 -1
  78. flwr/common/config.py +193 -0
  79. flwr/common/constant.py +42 -1
  80. flwr/common/context.py +26 -1
  81. flwr/common/date.py +1 -1
  82. flwr/common/dp.py +1 -1
  83. flwr/common/grpc.py +6 -2
  84. flwr/common/logger.py +79 -8
  85. flwr/common/message.py +167 -105
  86. flwr/common/object_ref.py +126 -25
  87. flwr/common/record/__init__.py +1 -1
  88. flwr/common/record/parametersrecord.py +0 -1
  89. flwr/common/record/recordset.py +78 -27
  90. flwr/common/recordset_compat.py +8 -1
  91. flwr/common/retry_invoker.py +25 -13
  92. flwr/common/secure_aggregation/__init__.py +1 -1
  93. flwr/common/secure_aggregation/crypto/__init__.py +1 -1
  94. flwr/common/secure_aggregation/crypto/shamir.py +1 -1
  95. flwr/common/secure_aggregation/crypto/symmetric_encryption.py +21 -2
  96. flwr/common/secure_aggregation/ndarrays_arithmetic.py +1 -1
  97. flwr/common/secure_aggregation/quantization.py +1 -1
  98. flwr/common/secure_aggregation/secaggplus_constants.py +1 -1
  99. flwr/common/secure_aggregation/secaggplus_utils.py +1 -1
  100. flwr/common/serde.py +209 -3
  101. flwr/common/telemetry.py +25 -0
  102. flwr/common/typing.py +38 -0
  103. flwr/common/version.py +14 -0
  104. flwr/proto/clientappio_pb2.py +41 -0
  105. flwr/proto/clientappio_pb2.pyi +110 -0
  106. flwr/proto/clientappio_pb2_grpc.py +101 -0
  107. flwr/proto/clientappio_pb2_grpc.pyi +40 -0
  108. flwr/proto/common_pb2.py +36 -0
  109. flwr/proto/common_pb2.pyi +121 -0
  110. flwr/proto/common_pb2_grpc.py +4 -0
  111. flwr/proto/common_pb2_grpc.pyi +4 -0
  112. flwr/proto/driver_pb2.py +26 -19
  113. flwr/proto/driver_pb2.pyi +34 -0
  114. flwr/proto/driver_pb2_grpc.py +70 -0
  115. flwr/proto/driver_pb2_grpc.pyi +28 -0
  116. flwr/proto/exec_pb2.py +43 -0
  117. flwr/proto/exec_pb2.pyi +95 -0
  118. flwr/proto/exec_pb2_grpc.py +101 -0
  119. flwr/proto/exec_pb2_grpc.pyi +41 -0
  120. flwr/proto/fab_pb2.py +30 -0
  121. flwr/proto/fab_pb2.pyi +56 -0
  122. flwr/proto/fab_pb2_grpc.py +4 -0
  123. flwr/proto/fab_pb2_grpc.pyi +4 -0
  124. flwr/proto/fleet_pb2.py +29 -23
  125. flwr/proto/fleet_pb2.pyi +33 -0
  126. flwr/proto/fleet_pb2_grpc.py +102 -0
  127. flwr/proto/fleet_pb2_grpc.pyi +35 -0
  128. flwr/proto/grpcadapter_pb2.py +32 -0
  129. flwr/proto/grpcadapter_pb2.pyi +43 -0
  130. flwr/proto/grpcadapter_pb2_grpc.py +66 -0
  131. flwr/proto/grpcadapter_pb2_grpc.pyi +24 -0
  132. flwr/proto/message_pb2.py +41 -0
  133. flwr/proto/message_pb2.pyi +122 -0
  134. flwr/proto/message_pb2_grpc.py +4 -0
  135. flwr/proto/message_pb2_grpc.pyi +4 -0
  136. flwr/proto/run_pb2.py +35 -0
  137. flwr/proto/run_pb2.pyi +76 -0
  138. flwr/proto/run_pb2_grpc.py +4 -0
  139. flwr/proto/run_pb2_grpc.pyi +4 -0
  140. flwr/proto/task_pb2.py +7 -8
  141. flwr/proto/task_pb2.pyi +8 -5
  142. flwr/server/__init__.py +4 -8
  143. flwr/server/app.py +298 -350
  144. flwr/server/compat/app.py +6 -57
  145. flwr/server/compat/app_utils.py +5 -4
  146. flwr/server/compat/driver_client_proxy.py +29 -48
  147. flwr/server/compat/legacy_context.py +5 -4
  148. flwr/server/driver/__init__.py +2 -0
  149. flwr/server/driver/driver.py +22 -132
  150. flwr/server/driver/grpc_driver.py +224 -74
  151. flwr/server/driver/inmemory_driver.py +183 -0
  152. flwr/server/history.py +20 -20
  153. flwr/server/run_serverapp.py +121 -34
  154. flwr/server/server.py +11 -7
  155. flwr/server/server_app.py +59 -10
  156. flwr/server/serverapp_components.py +52 -0
  157. flwr/server/strategy/__init__.py +2 -2
  158. flwr/server/strategy/bulyan.py +1 -1
  159. flwr/server/strategy/dp_adaptive_clipping.py +3 -3
  160. flwr/server/strategy/dp_fixed_clipping.py +4 -3
  161. flwr/server/strategy/dpfedavg_adaptive.py +1 -1
  162. flwr/server/strategy/dpfedavg_fixed.py +1 -1
  163. flwr/server/strategy/fedadagrad.py +1 -1
  164. flwr/server/strategy/fedadam.py +1 -1
  165. flwr/server/strategy/fedavg_android.py +1 -1
  166. flwr/server/strategy/fedavgm.py +1 -1
  167. flwr/server/strategy/fedmedian.py +1 -1
  168. flwr/server/strategy/fedopt.py +1 -1
  169. flwr/server/strategy/fedprox.py +1 -1
  170. flwr/server/strategy/fedxgb_bagging.py +1 -1
  171. flwr/server/strategy/fedxgb_cyclic.py +1 -1
  172. flwr/server/strategy/fedxgb_nn_avg.py +1 -1
  173. flwr/server/strategy/fedyogi.py +1 -1
  174. flwr/server/strategy/krum.py +1 -1
  175. flwr/server/strategy/qfedavg.py +1 -1
  176. flwr/server/superlink/driver/__init__.py +1 -1
  177. flwr/server/superlink/driver/driver_grpc.py +1 -1
  178. flwr/server/superlink/driver/driver_servicer.py +51 -4
  179. flwr/server/superlink/ffs/__init__.py +24 -0
  180. flwr/server/superlink/ffs/disk_ffs.py +104 -0
  181. flwr/server/superlink/ffs/ffs.py +79 -0
  182. flwr/server/superlink/fleet/__init__.py +1 -1
  183. flwr/server/superlink/fleet/grpc_adapter/__init__.py +15 -0
  184. flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +131 -0
  185. flwr/server/superlink/fleet/grpc_bidi/__init__.py +1 -1
  186. flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +1 -1
  187. flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +1 -1
  188. flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +1 -1
  189. flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +8 -2
  190. flwr/server/superlink/fleet/grpc_rere/__init__.py +1 -1
  191. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +30 -2
  192. flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +214 -0
  193. flwr/server/superlink/fleet/message_handler/__init__.py +1 -1
  194. flwr/server/superlink/fleet/message_handler/message_handler.py +42 -2
  195. flwr/server/superlink/fleet/rest_rere/__init__.py +1 -1
  196. flwr/server/superlink/fleet/rest_rere/rest_api.py +59 -1
  197. flwr/server/superlink/fleet/vce/backend/__init__.py +1 -1
  198. flwr/server/superlink/fleet/vce/backend/backend.py +5 -5
  199. flwr/server/superlink/fleet/vce/backend/raybackend.py +53 -56
  200. flwr/server/superlink/fleet/vce/vce_api.py +190 -127
  201. flwr/server/superlink/state/__init__.py +1 -1
  202. flwr/server/superlink/state/in_memory_state.py +159 -42
  203. flwr/server/superlink/state/sqlite_state.py +243 -39
  204. flwr/server/superlink/state/state.py +81 -6
  205. flwr/server/superlink/state/state_factory.py +11 -2
  206. flwr/server/superlink/state/utils.py +62 -0
  207. flwr/server/typing.py +2 -0
  208. flwr/server/utils/__init__.py +1 -1
  209. flwr/server/utils/tensorboard.py +1 -1
  210. flwr/server/utils/validator.py +23 -9
  211. flwr/server/workflow/default_workflows.py +67 -25
  212. flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +18 -6
  213. flwr/simulation/__init__.py +7 -4
  214. flwr/simulation/app.py +67 -36
  215. flwr/simulation/ray_transport/__init__.py +1 -1
  216. flwr/simulation/ray_transport/ray_actor.py +20 -46
  217. flwr/simulation/ray_transport/ray_client_proxy.py +36 -16
  218. flwr/simulation/run_simulation.py +308 -92
  219. flwr/superexec/__init__.py +21 -0
  220. flwr/superexec/app.py +184 -0
  221. flwr/superexec/deployment.py +185 -0
  222. flwr/superexec/exec_grpc.py +55 -0
  223. flwr/superexec/exec_servicer.py +70 -0
  224. flwr/superexec/executor.py +75 -0
  225. flwr/superexec/simulation.py +193 -0
  226. {flwr_nightly-1.8.0.dev20240315.dist-info → flwr_nightly-1.11.0.dev20240813.dist-info}/METADATA +10 -6
  227. flwr_nightly-1.11.0.dev20240813.dist-info/RECORD +288 -0
  228. flwr_nightly-1.11.0.dev20240813.dist-info/entry_points.txt +10 -0
  229. flwr/cli/flower_toml.py +0 -140
  230. flwr/cli/new/templates/app/flower.toml.tpl +0 -13
  231. flwr/cli/new/templates/app/requirements.numpy.txt.tpl +0 -2
  232. flwr/cli/new/templates/app/requirements.pytorch.txt.tpl +0 -4
  233. flwr/cli/new/templates/app/requirements.tensorflow.txt.tpl +0 -4
  234. flwr_nightly-1.8.0.dev20240315.dist-info/RECORD +0 -211
  235. flwr_nightly-1.8.0.dev20240315.dist-info/entry_points.txt +0 -9
  236. {flwr_nightly-1.8.0.dev20240315.dist-info → flwr_nightly-1.11.0.dev20240813.dist-info}/LICENSE +0 -0
  237. {flwr_nightly-1.8.0.dev20240315.dist-info → flwr_nightly-1.11.0.dev20240813.dist-info}/WHEEL +0 -0
@@ -0,0 +1,53 @@
1
+ """$project_name: A Flower / $framework_str app."""
2
+
3
+ import os
4
+
5
+ import keras
6
+ from keras import layers
7
+ from flwr_datasets import FederatedDataset
8
+ from flwr_datasets.partitioner import IidPartitioner
9
+
10
+
11
+ # Make TensorFlow log less verbose
12
+ os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"
13
+
14
+
15
+ def load_model():
16
+ # Define a simple CNN for CIFAR-10 and set Adam optimizer
17
+ model = keras.Sequential(
18
+ [
19
+ keras.Input(shape=(32, 32, 3)),
20
+ layers.Conv2D(32, kernel_size=(3, 3), activation="relu"),
21
+ layers.MaxPooling2D(pool_size=(2, 2)),
22
+ layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),
23
+ layers.MaxPooling2D(pool_size=(2, 2)),
24
+ layers.Flatten(),
25
+ layers.Dropout(0.5),
26
+ layers.Dense(10, activation="softmax"),
27
+ ]
28
+ )
29
+ model.compile("adam", "sparse_categorical_crossentropy", metrics=["accuracy"])
30
+ return model
31
+
32
+
33
+ fds = None # Cache FederatedDataset
34
+
35
+
36
+ def load_data(partition_id, num_partitions):
37
+ # Download and partition dataset
38
+ # Only initialize `FederatedDataset` once
39
+ global fds
40
+ if fds is None:
41
+ partitioner = IidPartitioner(num_partitions=num_partitions)
42
+ fds = FederatedDataset(
43
+ dataset="uoft-cs/cifar10",
44
+ partitioners={"train": partitioner},
45
+ )
46
+ partition = fds.load_partition(partition_id, "train")
47
+ partition.set_format("numpy")
48
+
49
+ # Divide data on each node: 80% train, 20% test
50
+ partition = partition.train_test_split(test_size=0.2)
51
+ x_train, y_train = partition["train"]["img"] / 255.0, partition["train"]["label"]
52
+ x_test, y_test = partition["test"]["img"] / 255.0, partition["test"]["label"]
53
+ return x_train, y_train, x_test, y_test
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "$package_name"
7
+ version = "1.0.0"
8
+ description = ""
9
+ license = "Apache-2.0"
10
+ dependencies = [
11
+ "flwr[simulation]>=1.9.0,<2.0",
12
+ "flwr-datasets>=0.1.0,<1.0.0",
13
+ "hydra-core==1.3.2",
14
+ "trl==0.8.1",
15
+ "bitsandbytes==0.43.0",
16
+ "scipy==1.13.0",
17
+ "peft==0.6.2",
18
+ "transformers==4.39.3",
19
+ "sentencepiece==0.2.0",
20
+ ]
21
+
22
+ [tool.hatch.build.targets.wheel]
23
+ packages = ["."]
24
+
25
+ [tool.flwr.app]
26
+ publisher = "$username"
27
+
28
+ [tool.flwr.app.components]
29
+ serverapp = "$import_name.app:server"
30
+ clientapp = "$import_name.app:client"
31
+
32
+ [tool.flwr.app.config]
33
+ num-server-rounds = 3
34
+
35
+ [tool.flwr.federations]
36
+ default = "local-simulation"
37
+
38
+ [tool.flwr.federations.local-simulation]
39
+ options.num-supernodes = 10
@@ -0,0 +1,38 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "$package_name"
7
+ version = "1.0.0"
8
+ description = ""
9
+ license = "Apache-2.0"
10
+ dependencies = [
11
+ "flwr[simulation]>=1.10.0",
12
+ "flwr-datasets>=0.3.0",
13
+ "torch==2.2.1",
14
+ "transformers>=4.30.0,<5.0",
15
+ "evaluate>=0.4.0,<1.0",
16
+ "datasets>=2.0.0, <3.0",
17
+ "scikit-learn>=1.3.1, <2.0",
18
+ ]
19
+
20
+ [tool.hatch.build.targets.wheel]
21
+ packages = ["."]
22
+
23
+ [tool.flwr.app]
24
+ publisher = "$username"
25
+
26
+ [tool.flwr.app.components]
27
+ serverapp = "$import_name.server_app:app"
28
+ clientapp = "$import_name.client_app:app"
29
+
30
+ [tool.flwr.app.config]
31
+ num-server-rounds = 3
32
+ local-epochs = 1
33
+
34
+ [tool.flwr.federations]
35
+ default = "localhost"
36
+
37
+ [tool.flwr.federations.localhost]
38
+ options.num-supernodes = 10
@@ -0,0 +1,34 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "$package_name"
7
+ version = "1.0.0"
8
+ description = ""
9
+ license = "Apache-2.0"
10
+ dependencies = [
11
+ "flwr[simulation]>=1.10.0",
12
+ "jax==0.4.13",
13
+ "jaxlib==0.4.13",
14
+ "scikit-learn==1.3.2",
15
+ ]
16
+
17
+ [tool.hatch.build.targets.wheel]
18
+ packages = ["."]
19
+
20
+ [tool.flwr.app]
21
+ publisher = "$username"
22
+
23
+ [tool.flwr.app.components]
24
+ serverapp = "$import_name.server_app:app"
25
+ clientapp = "$import_name.client_app:app"
26
+
27
+ [tool.flwr.app.config]
28
+ num-server-rounds = 3
29
+
30
+ [tool.flwr.federations]
31
+ default = "local-simulation"
32
+
33
+ [tool.flwr.federations.local-simulation]
34
+ options.num-supernodes = 10
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "$package_name"
7
+ version = "1.0.0"
8
+ description = ""
9
+ license = "Apache-2.0"
10
+ dependencies = [
11
+ "flwr[simulation]>=1.10.0",
12
+ "flwr-datasets[vision]>=0.3.0",
13
+ "mlx==0.16.1",
14
+ "numpy==1.24.4",
15
+ ]
16
+
17
+ [tool.hatch.build.targets.wheel]
18
+ packages = ["."]
19
+
20
+ [tool.flwr.app]
21
+ publisher = "$username"
22
+
23
+ [tool.flwr.app.components]
24
+ serverapp = "$import_name.server_app:app"
25
+ clientapp = "$import_name.client_app:app"
26
+
27
+ [tool.flwr.app.config]
28
+ num-server-rounds = 3
29
+ local-epochs = 1
30
+ num-layers = 2
31
+ hidden-dim = 32
32
+ batch-size = 256
33
+ lr = 0.1
34
+
35
+ [tool.flwr.federations]
36
+ default = "local-simulation"
37
+
38
+ [tool.flwr.federations.local-simulation]
39
+ options.num-supernodes = 10
@@ -1,19 +1,32 @@
1
1
  [build-system]
2
- requires = ["poetry-core>=1.4.0"]
3
- build-backend = "poetry.core.masonry.api"
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
4
 
5
- [tool.poetry]
6
- name = "$project_name"
5
+ [project]
6
+ name = "$package_name"
7
7
  version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
- authors = [
11
- "The Flower Authors <hello@flower.ai>",
10
+ dependencies = [
11
+ "flwr[simulation]>=1.10.0",
12
+ "numpy>=1.21.0",
12
13
  ]
13
- readme = "README.md"
14
14
 
15
- [tool.poetry.dependencies]
16
- python = "^3.9"
17
- # Mandatory dependencies
18
- numpy = "^1.21.0"
19
- flwr = { version = "^1.8.0", extras = ["simulation"] }
15
+ [tool.hatch.build.targets.wheel]
16
+ packages = ["."]
17
+
18
+ [tool.flwr.app]
19
+ publisher = "$username"
20
+
21
+ [tool.flwr.app.components]
22
+ serverapp = "$import_name.server_app:app"
23
+ clientapp = "$import_name.client_app:app"
24
+
25
+ [tool.flwr.app.config]
26
+ num-server-rounds = 3
27
+
28
+ [tool.flwr.federations]
29
+ default = "local-simulation"
30
+
31
+ [tool.flwr.federations.local-simulation]
32
+ options.num-supernodes = 10
@@ -1,21 +1,36 @@
1
1
  [build-system]
2
- requires = ["poetry-core>=1.4.0"]
3
- build-backend = "poetry.core.masonry.api"
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
4
 
5
- [tool.poetry]
6
- name = "$project_name"
5
+ [project]
6
+ name = "$package_name"
7
7
  version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
- authors = [
11
- "The Flower Authors <hello@flower.ai>",
10
+ dependencies = [
11
+ "flwr[simulation]>=1.10.0",
12
+ "flwr-datasets[vision]>=0.3.0",
13
+ "torch==2.2.1",
14
+ "torchvision==0.17.1",
12
15
  ]
13
- readme = "README.md"
14
16
 
15
- [tool.poetry.dependencies]
16
- python = "^3.9"
17
- # Mandatory dependencies
18
- flwr-nightly = { version = "1.8.0.dev20240313", extras = ["simulation"] }
19
- flwr-datasets = { version = "0.0.2", extras = ["vision"] }
20
- torch = "2.2.1"
21
- torchvision = "0.17.1"
17
+ [tool.hatch.build.targets.wheel]
18
+ packages = ["."]
19
+
20
+ [tool.flwr.app]
21
+ publisher = "$username"
22
+
23
+ [tool.flwr.app.components]
24
+ serverapp = "$import_name.server_app:app"
25
+ clientapp = "$import_name.client_app:app"
26
+
27
+ [tool.flwr.app.config]
28
+ num-server-rounds = 3
29
+ fraction-fit = 0.5
30
+ local-epochs = 1
31
+
32
+ [tool.flwr.federations]
33
+ default = "local-simulation"
34
+
35
+ [tool.flwr.federations.local-simulation]
36
+ options.num-supernodes = 10
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "$package_name"
7
+ version = "1.0.0"
8
+ description = ""
9
+ license = "Apache-2.0"
10
+ dependencies = [
11
+ "flwr[simulation]>=1.10.0",
12
+ "flwr-datasets[vision]>=0.3.0",
13
+ "scikit-learn>=1.1.1",
14
+ ]
15
+
16
+ [tool.hatch.build.targets.wheel]
17
+ packages = ["."]
18
+
19
+ [tool.flwr.app]
20
+ publisher = "$username"
21
+
22
+ [tool.flwr.app.components]
23
+ serverapp = "$import_name.server_app:app"
24
+ clientapp = "$import_name.client_app:app"
25
+
26
+ [tool.flwr.app.config]
27
+ num-server-rounds = 3
28
+
29
+ [tool.flwr.federations]
30
+ default = "local-simulation"
31
+
32
+ [tool.flwr.federations.local-simulation]
33
+ options.num-supernodes = 10
@@ -1,21 +1,36 @@
1
1
  [build-system]
2
- requires = ["poetry-core>=1.4.0"]
3
- build-backend = "poetry.core.masonry.api"
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
4
 
5
- [tool.poetry]
6
- name = "$project_name"
5
+ [project]
6
+ name = "$package_name"
7
7
  version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
- authors = [
11
- "The Flower Authors <hello@flower.ai>",
10
+ dependencies = [
11
+ "flwr[simulation]>=1.10.0",
12
+ "flwr-datasets[vision]>=0.3.0",
13
+ "tensorflow>=2.11.1",
12
14
  ]
13
- readme = "README.md"
14
15
 
15
- [tool.poetry.dependencies]
16
- python = ">=3.9,<3.11"
17
- # Mandatory dependencies
18
- flwr = { version = "^1.8.0", extras = ["simulation"] }
19
- flwr-datasets = { version = "^0.0.2", extras = ["vision"] }
20
- tensorflow-cpu = { version = ">=2.9.1,<2.11.1 || >2.11.1", markers = "platform_machine == \"x86_64\"" }
21
- tensorflow-macos = { version = ">=2.9.1,<2.11.1 || >2.11.1", markers = "sys_platform == \"darwin\" and platform_machine == \"arm64\"" }
16
+ [tool.hatch.build.targets.wheel]
17
+ packages = ["."]
18
+
19
+ [tool.flwr.app]
20
+ publisher = "$username"
21
+
22
+ [tool.flwr.app.components]
23
+ serverapp = "$import_name.server_app:app"
24
+ clientapp = "$import_name.client_app:app"
25
+
26
+ [tool.flwr.app.config]
27
+ num-server-rounds = 3
28
+ local-epochs = 1
29
+ batch-size = 32
30
+ verbose = false
31
+
32
+ [tool.flwr.federations]
33
+ default = "local-simulation"
34
+
35
+ [tool.flwr.federations.local-simulation]
36
+ options.num-supernodes = 10
flwr/cli/run/run.py CHANGED
@@ -14,23 +14,57 @@
14
14
  # ==============================================================================
15
15
  """Flower command line interface `run` command."""
16
16
 
17
+ import subprocess
17
18
  import sys
19
+ from logging import DEBUG
20
+ from pathlib import Path
21
+ from typing import Any, Dict, List, Optional
18
22
 
19
23
  import typer
24
+ from typing_extensions import Annotated
20
25
 
21
- from flwr.cli import flower_toml
22
- from flwr.simulation.run_simulation import _run_simulation
26
+ from flwr.cli.build import build
27
+ from flwr.cli.config_utils import load_and_validate
28
+ from flwr.common.config import flatten_dict, parse_config_args
29
+ from flwr.common.grpc import GRPC_MAX_MESSAGE_LENGTH, create_channel
30
+ from flwr.common.logger import log
31
+ from flwr.common.serde import user_config_to_proto
32
+ from flwr.proto.exec_pb2 import StartRunRequest # pylint: disable=E0611
33
+ from flwr.proto.exec_pb2_grpc import ExecStub
23
34
 
24
35
 
25
- def run() -> None:
26
- """Run Flower project."""
36
+ # pylint: disable-next=too-many-locals
37
+ def run(
38
+ app: Annotated[
39
+ Path,
40
+ typer.Argument(help="Path of the Flower App to run."),
41
+ ] = Path("."),
42
+ federation: Annotated[
43
+ Optional[str],
44
+ typer.Argument(help="Name of the federation to run the app on."),
45
+ ] = None,
46
+ config_overrides: Annotated[
47
+ Optional[List[str]],
48
+ typer.Option(
49
+ "--run-config",
50
+ "-c",
51
+ help="Override configuration key-value pairs, should be of the format:\n\n"
52
+ "`--run-config key1=value1,key2=value2 --run-config key3=value3`\n\n"
53
+ "Note that `key1`, `key2`, and `key3` in this example need to exist "
54
+ "inside the `pyproject.toml` in order to be properly overriden.",
55
+ ),
56
+ ] = None,
57
+ ) -> None:
58
+ """Run Flower App."""
27
59
  typer.secho("Loading project configuration... ", fg=typer.colors.BLUE)
28
60
 
29
- config, errors, warnings = flower_toml.load_and_validate_with_defaults()
61
+ pyproject_path = app / "pyproject.toml" if app else None
62
+ config, errors, warnings = load_and_validate(path=pyproject_path)
30
63
 
31
64
  if config is None:
32
65
  typer.secho(
33
- "Project configuration could not be loaded.\nflower.toml is invalid:\n"
66
+ "Project configuration could not be loaded.\n"
67
+ "pyproject.toml is invalid:\n"
34
68
  + "\n".join([f"- {line}" for line in errors]),
35
69
  fg=typer.colors.RED,
36
70
  bold=True,
@@ -47,22 +81,139 @@ def run() -> None:
47
81
 
48
82
  typer.secho("Success", fg=typer.colors.GREEN)
49
83
 
50
- server_app_ref = config["flower"]["components"]["serverapp"]
51
- client_app_ref = config["flower"]["components"]["clientapp"]
52
- engine = config["flower"]["engine"]["name"]
84
+ federation = federation or config["tool"]["flwr"]["federations"].get("default")
53
85
 
54
- if engine == "simulation":
55
- num_supernodes = config["flower"]["engine"]["simulation"]["supernode"]["num"]
86
+ if federation is None:
87
+ typer.secho(
88
+ "❌ No federation name was provided and the project's `pyproject.toml` "
89
+ "doesn't declare a default federation (with a SuperExec address or an "
90
+ "`options.num-supernodes` value).",
91
+ fg=typer.colors.RED,
92
+ bold=True,
93
+ )
94
+ raise typer.Exit(code=1)
56
95
 
57
- typer.secho("Starting run... ", fg=typer.colors.BLUE)
58
- _run_simulation(
59
- server_app_attr=server_app_ref,
60
- client_app_attr=client_app_ref,
61
- num_supernodes=num_supernodes,
96
+ # Validate the federation exists in the configuration
97
+ federation_config = config["tool"]["flwr"]["federations"].get(federation)
98
+ if federation_config is None:
99
+ available_feds = {
100
+ fed for fed in config["tool"]["flwr"]["federations"] if fed != "default"
101
+ }
102
+ typer.secho(
103
+ f"❌ There is no `{federation}` federation declared in "
104
+ "`pyproject.toml`.\n The following federations were found:\n\n"
105
+ + "\n".join(available_feds),
106
+ fg=typer.colors.RED,
107
+ bold=True,
62
108
  )
109
+ raise typer.Exit(code=1)
110
+
111
+ if "address" in federation_config:
112
+ _run_with_superexec(app, federation_config, config_overrides)
113
+ else:
114
+ _run_without_superexec(app, federation_config, config_overrides, federation)
115
+
116
+
117
+ def _run_with_superexec(
118
+ app: Optional[Path],
119
+ federation_config: Dict[str, Any],
120
+ config_overrides: Optional[List[str]],
121
+ ) -> None:
122
+
123
+ def on_channel_state_change(channel_connectivity: str) -> None:
124
+ """Log channel connectivity."""
125
+ log(DEBUG, channel_connectivity)
126
+
127
+ insecure_str = federation_config.get("insecure")
128
+ if root_certificates := federation_config.get("root-certificates"):
129
+ root_certificates_bytes = Path(root_certificates).read_bytes()
130
+ if insecure := bool(insecure_str):
131
+ typer.secho(
132
+ "❌ `root_certificates` were provided but the `insecure` parameter"
133
+ "is set to `True`.",
134
+ fg=typer.colors.RED,
135
+ bold=True,
136
+ )
137
+ raise typer.Exit(code=1)
63
138
  else:
139
+ root_certificates_bytes = None
140
+ if insecure_str is None:
141
+ typer.secho(
142
+ "❌ To disable TLS, set `insecure = true` in `pyproject.toml`.",
143
+ fg=typer.colors.RED,
144
+ bold=True,
145
+ )
146
+ raise typer.Exit(code=1)
147
+ if not (insecure := bool(insecure_str)):
148
+ typer.secho(
149
+ "❌ No certificate were given yet `insecure` is set to `False`.",
150
+ fg=typer.colors.RED,
151
+ bold=True,
152
+ )
153
+ raise typer.Exit(code=1)
154
+
155
+ channel = create_channel(
156
+ server_address=federation_config["address"],
157
+ insecure=insecure,
158
+ root_certificates=root_certificates_bytes,
159
+ max_message_length=GRPC_MAX_MESSAGE_LENGTH,
160
+ interceptors=None,
161
+ )
162
+ channel.subscribe(on_channel_state_change)
163
+ stub = ExecStub(channel)
164
+
165
+ fab_path = Path(build(app))
166
+
167
+ req = StartRunRequest(
168
+ fab_file=fab_path.read_bytes(),
169
+ override_config=user_config_to_proto(
170
+ parse_config_args(config_overrides, separator=",")
171
+ ),
172
+ federation_config=user_config_to_proto(
173
+ flatten_dict(federation_config.get("options"))
174
+ ),
175
+ )
176
+ res = stub.StartRun(req)
177
+
178
+ # Delete FAB file once it has been sent to the SuperExec
179
+ fab_path.unlink()
180
+ typer.secho(f"🎊 Successfully started run {res.run_id}", fg=typer.colors.GREEN)
181
+
182
+
183
+ def _run_without_superexec(
184
+ app: Optional[Path],
185
+ federation_config: Dict[str, Any],
186
+ config_overrides: Optional[List[str]],
187
+ federation: str,
188
+ ) -> None:
189
+ try:
190
+ num_supernodes = federation_config["options"]["num-supernodes"]
191
+ except KeyError as err:
64
192
  typer.secho(
65
- f"Engine '{engine}' is not yet supported in `flwr run`",
193
+ " The project's `pyproject.toml` needs to declare the number of"
194
+ " SuperNodes in the simulation. To simulate 10 SuperNodes,"
195
+ " use the following notation:\n\n"
196
+ f"[tool.flwr.federations.{federation}]\n"
197
+ "options.num-supernodes = 10\n",
66
198
  fg=typer.colors.RED,
67
199
  bold=True,
68
200
  )
201
+ raise typer.Exit(code=1) from err
202
+
203
+ command = [
204
+ "flower-simulation",
205
+ "--app",
206
+ f"{app}",
207
+ "--num-supernodes",
208
+ f"{num_supernodes}",
209
+ ]
210
+
211
+ if config_overrides:
212
+ command.extend(["--run-config", f"{','.join(config_overrides)}"])
213
+
214
+ # Run the simulation
215
+ subprocess.run(
216
+ command,
217
+ check=True,
218
+ text=True,
219
+ )