flwr 1.21.0__py3-none-any.whl → 1.22.0__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.
- flwr/cli/app.py +2 -0
- flwr/cli/new/new.py +9 -7
- flwr/cli/new/templates/app/README.flowertune.md.tpl +1 -1
- flwr/cli/new/templates/app/code/client.baseline.py.tpl +64 -47
- flwr/cli/new/templates/app/code/client.huggingface.py.tpl +68 -30
- flwr/cli/new/templates/app/code/client.jax.py.tpl +63 -42
- flwr/cli/new/templates/app/code/client.mlx.py.tpl +80 -51
- flwr/cli/new/templates/app/code/client.numpy.py.tpl +36 -13
- flwr/cli/new/templates/app/code/client.pytorch.py.tpl +71 -46
- flwr/cli/new/templates/app/code/client.pytorch_legacy_api.py.tpl +55 -0
- flwr/cli/new/templates/app/code/client.sklearn.py.tpl +75 -30
- flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +69 -44
- flwr/cli/new/templates/app/code/client.xgboost.py.tpl +110 -0
- flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl +56 -90
- flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +1 -23
- flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl +37 -58
- flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl +39 -44
- flwr/cli/new/templates/app/code/model.baseline.py.tpl +0 -14
- flwr/cli/new/templates/app/code/server.baseline.py.tpl +27 -29
- flwr/cli/new/templates/app/code/server.huggingface.py.tpl +23 -19
- flwr/cli/new/templates/app/code/server.jax.py.tpl +27 -14
- flwr/cli/new/templates/app/code/server.mlx.py.tpl +29 -19
- flwr/cli/new/templates/app/code/server.numpy.py.tpl +30 -17
- flwr/cli/new/templates/app/code/server.pytorch.py.tpl +36 -26
- flwr/cli/new/templates/app/code/server.pytorch_legacy_api.py.tpl +31 -0
- flwr/cli/new/templates/app/code/server.sklearn.py.tpl +29 -21
- flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +28 -19
- flwr/cli/new/templates/app/code/server.xgboost.py.tpl +56 -0
- flwr/cli/new/templates/app/code/task.huggingface.py.tpl +16 -20
- flwr/cli/new/templates/app/code/task.jax.py.tpl +1 -1
- flwr/cli/new/templates/app/code/task.numpy.py.tpl +1 -1
- flwr/cli/new/templates/app/code/task.pytorch.py.tpl +14 -27
- flwr/cli/new/templates/app/code/{task.pytorch_msg_api.py.tpl → task.pytorch_legacy_api.py.tpl} +27 -14
- flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +1 -2
- flwr/cli/new/templates/app/code/task.xgboost.py.tpl +67 -0
- flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +4 -4
- flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +2 -2
- flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +4 -4
- flwr/cli/new/templates/app/pyproject.jax.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +2 -2
- flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +3 -3
- flwr/cli/new/templates/app/{pyproject.pytorch_msg_api.toml.tpl → pyproject.pytorch_legacy_api.toml.tpl} +3 -3
- flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.xgboost.toml.tpl +61 -0
- flwr/cli/pull.py +100 -0
- flwr/cli/utils.py +17 -0
- flwr/clientapp/mod/__init__.py +4 -1
- flwr/clientapp/mod/centraldp_mods.py +156 -40
- flwr/clientapp/mod/localdp_mod.py +169 -0
- flwr/clientapp/typing.py +22 -0
- flwr/common/constant.py +3 -0
- flwr/common/exit/exit_code.py +4 -0
- flwr/common/record/typeddict.py +12 -0
- flwr/proto/control_pb2.py +7 -3
- flwr/proto/control_pb2.pyi +24 -0
- flwr/proto/control_pb2_grpc.py +34 -0
- flwr/proto/control_pb2_grpc.pyi +13 -0
- flwr/server/app.py +13 -0
- flwr/serverapp/strategy/__init__.py +26 -0
- flwr/serverapp/strategy/bulyan.py +238 -0
- flwr/serverapp/strategy/dp_adaptive_clipping.py +335 -0
- flwr/serverapp/strategy/dp_fixed_clipping.py +71 -49
- flwr/serverapp/strategy/fedadagrad.py +0 -3
- flwr/serverapp/strategy/fedadam.py +0 -3
- flwr/serverapp/strategy/fedavg.py +89 -64
- flwr/serverapp/strategy/fedavgm.py +198 -0
- flwr/serverapp/strategy/fedmedian.py +105 -0
- flwr/serverapp/strategy/fedprox.py +174 -0
- flwr/serverapp/strategy/fedtrimmedavg.py +176 -0
- flwr/serverapp/strategy/fedxgb_bagging.py +117 -0
- flwr/serverapp/strategy/fedxgb_cyclic.py +220 -0
- flwr/serverapp/strategy/fedyogi.py +0 -3
- flwr/serverapp/strategy/krum.py +112 -0
- flwr/serverapp/strategy/multikrum.py +247 -0
- flwr/serverapp/strategy/qfedavg.py +252 -0
- flwr/serverapp/strategy/strategy_utils.py +48 -0
- flwr/simulation/app.py +1 -1
- flwr/simulation/run_simulation.py +25 -30
- flwr/supercore/cli/flower_superexec.py +26 -1
- flwr/supercore/constant.py +19 -0
- flwr/supercore/superexec/plugin/exec_plugin.py +11 -1
- flwr/supercore/superexec/run_superexec.py +16 -2
- flwr/superlink/artifact_provider/__init__.py +22 -0
- flwr/superlink/artifact_provider/artifact_provider.py +37 -0
- flwr/superlink/servicer/control/control_grpc.py +3 -0
- flwr/superlink/servicer/control/control_servicer.py +59 -2
- {flwr-1.21.0.dist-info → flwr-1.22.0.dist-info}/METADATA +6 -16
- {flwr-1.21.0.dist-info → flwr-1.22.0.dist-info}/RECORD +93 -74
- flwr/cli/new/templates/app/code/client.pytorch_msg_api.py.tpl +0 -80
- flwr/cli/new/templates/app/code/server.pytorch_msg_api.py.tpl +0 -41
- flwr/serverapp/dp_fixed_clipping.py +0 -352
- flwr/serverapp/strategy/strategy_utils_tests.py +0 -304
- /flwr/cli/new/templates/app/code/{__init__.pytorch_msg_api.py.tpl → __init__.pytorch_legacy_api.py.tpl} +0 -0
- {flwr-1.21.0.dist-info → flwr-1.22.0.dist-info}/WHEEL +0 -0
- {flwr-1.21.0.dist-info → flwr-1.22.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""$project_name: A Flower / $framework_str app."""
|
|
2
|
+
|
|
3
|
+
import xgboost as xgb
|
|
4
|
+
from flwr_datasets import FederatedDataset
|
|
5
|
+
from flwr_datasets.partitioner import IidPartitioner
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def train_test_split(partition, test_fraction, seed):
|
|
9
|
+
"""Split the data into train and validation set given split rate."""
|
|
10
|
+
train_test = partition.train_test_split(test_size=test_fraction, seed=seed)
|
|
11
|
+
partition_train = train_test["train"]
|
|
12
|
+
partition_test = train_test["test"]
|
|
13
|
+
|
|
14
|
+
num_train = len(partition_train)
|
|
15
|
+
num_test = len(partition_test)
|
|
16
|
+
|
|
17
|
+
return partition_train, partition_test, num_train, num_test
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def transform_dataset_to_dmatrix(data):
|
|
21
|
+
"""Transform dataset to DMatrix format for xgboost."""
|
|
22
|
+
x = data["inputs"]
|
|
23
|
+
y = data["label"]
|
|
24
|
+
new_data = xgb.DMatrix(x, label=y)
|
|
25
|
+
return new_data
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
fds = None # Cache FederatedDataset
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def load_data(partition_id, num_clients):
|
|
32
|
+
"""Load partition HIGGS data."""
|
|
33
|
+
# Only initialize `FederatedDataset` once
|
|
34
|
+
global fds
|
|
35
|
+
if fds is None:
|
|
36
|
+
partitioner = IidPartitioner(num_partitions=num_clients)
|
|
37
|
+
fds = FederatedDataset(
|
|
38
|
+
dataset="jxie/higgs",
|
|
39
|
+
partitioners={"train": partitioner},
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Load the partition for this `partition_id`
|
|
43
|
+
partition = fds.load_partition(partition_id, split="train")
|
|
44
|
+
partition.set_format("numpy")
|
|
45
|
+
|
|
46
|
+
# Train/test splitting
|
|
47
|
+
train_data, valid_data, num_train, num_val = train_test_split(
|
|
48
|
+
partition, test_fraction=0.2, seed=42
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Reformat data to DMatrix for xgboost
|
|
52
|
+
train_dmatrix = transform_dataset_to_dmatrix(train_data)
|
|
53
|
+
valid_dmatrix = transform_dataset_to_dmatrix(valid_data)
|
|
54
|
+
|
|
55
|
+
return train_dmatrix, valid_dmatrix, num_train, num_val
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def replace_keys(input_dict, match="-", target="_"):
|
|
59
|
+
"""Recursively replace match string with target string in dictionary keys."""
|
|
60
|
+
new_dict = {}
|
|
61
|
+
for key, value in input_dict.items():
|
|
62
|
+
new_key = key.replace(match, target)
|
|
63
|
+
if isinstance(value, dict):
|
|
64
|
+
new_dict[new_key] = replace_keys(value, match, target)
|
|
65
|
+
else:
|
|
66
|
+
new_dict[new_key] = value
|
|
67
|
+
return new_dict
|
|
@@ -14,10 +14,10 @@ description = ""
|
|
|
14
14
|
license = "Apache-2.0"
|
|
15
15
|
# Dependencies for your Flower App
|
|
16
16
|
dependencies = [
|
|
17
|
-
"flwr[simulation]>=1.
|
|
17
|
+
"flwr[simulation]>=1.22.0",
|
|
18
18
|
"flwr-datasets[vision]>=0.5.0",
|
|
19
|
-
"torch==2.
|
|
20
|
-
"torchvision==0.
|
|
19
|
+
"torch==2.8.0",
|
|
20
|
+
"torchvision==0.23.0",
|
|
21
21
|
]
|
|
22
22
|
|
|
23
23
|
[tool.hatch.metadata]
|
|
@@ -132,7 +132,7 @@ clientapp = "$import_name.client_app:app"
|
|
|
132
132
|
# Custom config values accessible via `context.run_config`
|
|
133
133
|
[tool.flwr.app.config]
|
|
134
134
|
num-server-rounds = 3
|
|
135
|
-
fraction-
|
|
135
|
+
fraction-train = 0.5
|
|
136
136
|
local-epochs = 1
|
|
137
137
|
|
|
138
138
|
# Default federation to use when running the app
|
|
@@ -14,7 +14,7 @@ description = ""
|
|
|
14
14
|
license = "Apache-2.0"
|
|
15
15
|
# Dependencies for your Flower App
|
|
16
16
|
dependencies = [
|
|
17
|
-
"flwr[simulation]>=1.
|
|
17
|
+
"flwr[simulation]>=1.22.0",
|
|
18
18
|
"flwr-datasets>=0.5.0",
|
|
19
19
|
"torch==2.4.0",
|
|
20
20
|
"trl==0.8.1",
|
|
@@ -61,7 +61,7 @@ train.training-arguments.save-steps = 1000
|
|
|
61
61
|
train.training-arguments.save-total-limit = 10
|
|
62
62
|
train.training-arguments.gradient-checkpointing = true
|
|
63
63
|
train.training-arguments.lr-scheduler-type = "constant"
|
|
64
|
-
strategy.fraction-
|
|
64
|
+
strategy.fraction-train = $fraction_train
|
|
65
65
|
strategy.fraction-evaluate = 0.0
|
|
66
66
|
num-server-rounds = 200
|
|
67
67
|
|
|
@@ -14,9 +14,9 @@ description = ""
|
|
|
14
14
|
license = "Apache-2.0"
|
|
15
15
|
# Dependencies for your Flower App
|
|
16
16
|
dependencies = [
|
|
17
|
-
"flwr[simulation]>=1.
|
|
17
|
+
"flwr[simulation]>=1.22.0",
|
|
18
18
|
"flwr-datasets>=0.5.0",
|
|
19
|
-
"torch
|
|
19
|
+
"torch>=2.7.1",
|
|
20
20
|
"transformers>=4.30.0,<5.0",
|
|
21
21
|
"evaluate>=0.4.0,<1.0",
|
|
22
22
|
"datasets>=2.0.0, <3.0",
|
|
@@ -38,8 +38,8 @@ clientapp = "$import_name.client_app:app"
|
|
|
38
38
|
# Custom config values accessible via `context.run_config`
|
|
39
39
|
[tool.flwr.app.config]
|
|
40
40
|
num-server-rounds = 3
|
|
41
|
-
fraction-
|
|
42
|
-
local-
|
|
41
|
+
fraction-train = 0.5
|
|
42
|
+
local-steps = 5
|
|
43
43
|
model-name = "prajjwal1/bert-tiny" # Set a larger model if you have access to more GPU resources
|
|
44
44
|
num-labels = 2
|
|
45
45
|
|
|
@@ -14,9 +14,9 @@ description = ""
|
|
|
14
14
|
license = "Apache-2.0"
|
|
15
15
|
# Dependencies for your Flower App
|
|
16
16
|
dependencies = [
|
|
17
|
-
"flwr[simulation]>=1.
|
|
17
|
+
"flwr[simulation]>=1.22.0",
|
|
18
18
|
"flwr-datasets[vision]>=0.5.0",
|
|
19
|
-
"mlx==0.
|
|
19
|
+
"mlx==0.29.0",
|
|
20
20
|
]
|
|
21
21
|
|
|
22
22
|
[tool.hatch.build.targets.wheel]
|
|
@@ -14,7 +14,7 @@ description = ""
|
|
|
14
14
|
license = "Apache-2.0"
|
|
15
15
|
# Dependencies for your Flower App
|
|
16
16
|
dependencies = [
|
|
17
|
-
"flwr[simulation]>=1.
|
|
17
|
+
"flwr[simulation]>=1.22.0",
|
|
18
18
|
"flwr-datasets[vision]>=0.5.0",
|
|
19
19
|
"torch==2.7.1",
|
|
20
20
|
"torchvision==0.22.1",
|
|
@@ -27,7 +27,6 @@ packages = ["."]
|
|
|
27
27
|
publisher = "$username"
|
|
28
28
|
|
|
29
29
|
# Point to your ServerApp and ClientApp objects
|
|
30
|
-
# Format: "<module>:<object>"
|
|
31
30
|
[tool.flwr.app.components]
|
|
32
31
|
serverapp = "$import_name.server_app:app"
|
|
33
32
|
clientapp = "$import_name.client_app:app"
|
|
@@ -35,8 +34,9 @@ clientapp = "$import_name.client_app:app"
|
|
|
35
34
|
# Custom config values accessible via `context.run_config`
|
|
36
35
|
[tool.flwr.app.config]
|
|
37
36
|
num-server-rounds = 3
|
|
38
|
-
fraction-
|
|
37
|
+
fraction-train = 0.5
|
|
39
38
|
local-epochs = 1
|
|
39
|
+
lr = 0.01
|
|
40
40
|
|
|
41
41
|
# Default federation to use when running the app
|
|
42
42
|
[tool.flwr.federations]
|
|
@@ -14,7 +14,7 @@ description = ""
|
|
|
14
14
|
license = "Apache-2.0"
|
|
15
15
|
# Dependencies for your Flower App
|
|
16
16
|
dependencies = [
|
|
17
|
-
"flwr[simulation]>=1.
|
|
17
|
+
"flwr[simulation]>=1.22.0",
|
|
18
18
|
"flwr-datasets[vision]>=0.5.0",
|
|
19
19
|
"torch==2.7.1",
|
|
20
20
|
"torchvision==0.22.1",
|
|
@@ -27,6 +27,7 @@ packages = ["."]
|
|
|
27
27
|
publisher = "$username"
|
|
28
28
|
|
|
29
29
|
# Point to your ServerApp and ClientApp objects
|
|
30
|
+
# Format: "<module>:<object>"
|
|
30
31
|
[tool.flwr.app.components]
|
|
31
32
|
serverapp = "$import_name.server_app:app"
|
|
32
33
|
clientapp = "$import_name.client_app:app"
|
|
@@ -34,9 +35,8 @@ clientapp = "$import_name.client_app:app"
|
|
|
34
35
|
# Custom config values accessible via `context.run_config`
|
|
35
36
|
[tool.flwr.app.config]
|
|
36
37
|
num-server-rounds = 3
|
|
37
|
-
fraction-
|
|
38
|
+
fraction-fit = 0.5
|
|
38
39
|
local-epochs = 1
|
|
39
|
-
lr = 0.01
|
|
40
40
|
|
|
41
41
|
# Default federation to use when running the app
|
|
42
42
|
[tool.flwr.federations]
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# =====================================================================
|
|
2
|
+
# For a full TOML configuration guide, check the Flower docs:
|
|
3
|
+
# https://flower.ai/docs/framework/how-to-configure-pyproject-toml.html
|
|
4
|
+
# =====================================================================
|
|
5
|
+
|
|
6
|
+
[build-system]
|
|
7
|
+
requires = ["hatchling"]
|
|
8
|
+
build-backend = "hatchling.build"
|
|
9
|
+
|
|
10
|
+
[project]
|
|
11
|
+
name = "$package_name"
|
|
12
|
+
version = "1.0.0"
|
|
13
|
+
description = ""
|
|
14
|
+
license = "Apache-2.0"
|
|
15
|
+
# Dependencies for your Flower App
|
|
16
|
+
dependencies = [
|
|
17
|
+
"flwr[simulation]>=1.22.0",
|
|
18
|
+
"flwr-datasets>=0.5.0",
|
|
19
|
+
"xgboost>=2.0.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.server_app:app"
|
|
30
|
+
clientapp = "$import_name.client_app:app"
|
|
31
|
+
|
|
32
|
+
# Custom config values accessible via `context.run_config`
|
|
33
|
+
[tool.flwr.app.config]
|
|
34
|
+
num-server-rounds = 3
|
|
35
|
+
fraction-train = 0.1
|
|
36
|
+
fraction-evaluate = 0.1
|
|
37
|
+
local-epochs = 1
|
|
38
|
+
|
|
39
|
+
# XGBoost parameters
|
|
40
|
+
params.objective = "binary:logistic"
|
|
41
|
+
params.eta = 0.1 # Learning rate
|
|
42
|
+
params.max-depth = 8
|
|
43
|
+
params.eval-metric = "auc"
|
|
44
|
+
params.nthread = 16
|
|
45
|
+
params.num-parallel-tree = 1
|
|
46
|
+
params.subsample = 1
|
|
47
|
+
params.tree-method = "hist"
|
|
48
|
+
|
|
49
|
+
# Default federation to use when running the app
|
|
50
|
+
[tool.flwr.federations]
|
|
51
|
+
default = "local-simulation"
|
|
52
|
+
|
|
53
|
+
# Local simulation federation with 10 virtual SuperNodes
|
|
54
|
+
[tool.flwr.federations.local-simulation]
|
|
55
|
+
options.num-supernodes = 10
|
|
56
|
+
|
|
57
|
+
# Remote federation example for use with SuperLink
|
|
58
|
+
[tool.flwr.federations.remote-federation]
|
|
59
|
+
address = "<SUPERLINK-ADDRESS>:<PORT>"
|
|
60
|
+
insecure = true # Remove this line to enable TLS
|
|
61
|
+
# root-certificates = "<PATH/TO/ca.crt>" # For TLS setup
|
flwr/cli/pull.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Copyright 2025 Flower Labs GmbH. All Rights Reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
# ==============================================================================
|
|
15
|
+
"""Flower command line interface `pull` command."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Annotated, Optional
|
|
20
|
+
|
|
21
|
+
import typer
|
|
22
|
+
|
|
23
|
+
from flwr.cli.config_utils import (
|
|
24
|
+
exit_if_no_address,
|
|
25
|
+
load_and_validate,
|
|
26
|
+
process_loaded_project_config,
|
|
27
|
+
validate_federation_in_project_config,
|
|
28
|
+
)
|
|
29
|
+
from flwr.cli.constant import FEDERATION_CONFIG_HELP_MESSAGE
|
|
30
|
+
from flwr.common.constant import FAB_CONFIG_FILE
|
|
31
|
+
from flwr.proto.control_pb2 import ( # pylint: disable=E0611
|
|
32
|
+
PullArtifactsRequest,
|
|
33
|
+
PullArtifactsResponse,
|
|
34
|
+
)
|
|
35
|
+
from flwr.proto.control_pb2_grpc import ControlStub
|
|
36
|
+
|
|
37
|
+
from .utils import flwr_cli_grpc_exc_handler, init_channel, try_obtain_cli_auth_plugin
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def pull( # pylint: disable=R0914
|
|
41
|
+
run_id: Annotated[
|
|
42
|
+
int,
|
|
43
|
+
typer.Option(
|
|
44
|
+
"--run-id",
|
|
45
|
+
help="Run ID to pull artifacts from.",
|
|
46
|
+
),
|
|
47
|
+
],
|
|
48
|
+
app: Annotated[
|
|
49
|
+
Path,
|
|
50
|
+
typer.Argument(help="Path of the Flower App to run."),
|
|
51
|
+
] = Path("."),
|
|
52
|
+
federation: Annotated[
|
|
53
|
+
Optional[str],
|
|
54
|
+
typer.Argument(help="Name of the federation."),
|
|
55
|
+
] = None,
|
|
56
|
+
federation_config_overrides: Annotated[
|
|
57
|
+
Optional[list[str]],
|
|
58
|
+
typer.Option(
|
|
59
|
+
"--federation-config",
|
|
60
|
+
help=FEDERATION_CONFIG_HELP_MESSAGE,
|
|
61
|
+
),
|
|
62
|
+
] = None,
|
|
63
|
+
) -> None:
|
|
64
|
+
"""Pull artifacts from a Flower run."""
|
|
65
|
+
typer.secho("Loading project configuration... ", fg=typer.colors.BLUE)
|
|
66
|
+
|
|
67
|
+
pyproject_path = app / FAB_CONFIG_FILE if app else None
|
|
68
|
+
config, errors, warnings = load_and_validate(path=pyproject_path)
|
|
69
|
+
config = process_loaded_project_config(config, errors, warnings)
|
|
70
|
+
federation, federation_config = validate_federation_in_project_config(
|
|
71
|
+
federation, config, federation_config_overrides
|
|
72
|
+
)
|
|
73
|
+
exit_if_no_address(federation_config, "pull")
|
|
74
|
+
channel = None
|
|
75
|
+
try:
|
|
76
|
+
|
|
77
|
+
auth_plugin = try_obtain_cli_auth_plugin(app, federation, federation_config)
|
|
78
|
+
channel = init_channel(app, federation_config, auth_plugin)
|
|
79
|
+
stub = ControlStub(channel)
|
|
80
|
+
with flwr_cli_grpc_exc_handler():
|
|
81
|
+
res: PullArtifactsResponse = stub.PullArtifacts(
|
|
82
|
+
PullArtifactsRequest(run_id=run_id)
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
if not res.url:
|
|
86
|
+
typer.secho(
|
|
87
|
+
f"❌ A download URL for artifacts from run {run_id} couldn't be "
|
|
88
|
+
"obtained.",
|
|
89
|
+
fg=typer.colors.RED,
|
|
90
|
+
bold=True,
|
|
91
|
+
)
|
|
92
|
+
raise typer.Exit(code=1)
|
|
93
|
+
|
|
94
|
+
typer.secho(
|
|
95
|
+
f"✅ Artifacts for run {run_id} can be downloaded from: {res.url}",
|
|
96
|
+
fg=typer.colors.GREEN,
|
|
97
|
+
)
|
|
98
|
+
finally:
|
|
99
|
+
if channel:
|
|
100
|
+
channel.close()
|
flwr/cli/utils.py
CHANGED
|
@@ -32,7 +32,9 @@ from flwr.common.constant import (
|
|
|
32
32
|
AUTH_TYPE_JSON_KEY,
|
|
33
33
|
CREDENTIALS_DIR,
|
|
34
34
|
FLWR_DIR,
|
|
35
|
+
NO_ARTIFACT_PROVIDER_MESSAGE,
|
|
35
36
|
NO_USER_AUTH_MESSAGE,
|
|
37
|
+
PULL_UNFINISHED_RUN_MESSAGE,
|
|
36
38
|
RUN_ID_NOT_FOUND_MESSAGE,
|
|
37
39
|
)
|
|
38
40
|
from flwr.common.grpc import (
|
|
@@ -319,6 +321,12 @@ def flwr_cli_grpc_exc_handler() -> Iterator[None]:
|
|
|
319
321
|
fg=typer.colors.RED,
|
|
320
322
|
bold=True,
|
|
321
323
|
)
|
|
324
|
+
elif e.details() == NO_ARTIFACT_PROVIDER_MESSAGE: # pylint: disable=E1101
|
|
325
|
+
typer.secho(
|
|
326
|
+
"❌ The SuperLink does not support `flwr pull` command.",
|
|
327
|
+
fg=typer.colors.RED,
|
|
328
|
+
bold=True,
|
|
329
|
+
)
|
|
322
330
|
else:
|
|
323
331
|
typer.secho(
|
|
324
332
|
"❌ The SuperLink cannot process this request. Please verify that "
|
|
@@ -356,4 +364,13 @@ def flwr_cli_grpc_exc_handler() -> Iterator[None]:
|
|
|
356
364
|
bold=True,
|
|
357
365
|
)
|
|
358
366
|
raise typer.Exit(code=1) from None
|
|
367
|
+
if e.code() == grpc.StatusCode.FAILED_PRECONDITION:
|
|
368
|
+
if e.details() == PULL_UNFINISHED_RUN_MESSAGE: # pylint: disable=E1101
|
|
369
|
+
typer.secho(
|
|
370
|
+
"❌ Run is not finished yet. Artifacts can only be pulled after "
|
|
371
|
+
"the run is finished. You can check the run status with `flwr ls`.",
|
|
372
|
+
fg=typer.colors.RED,
|
|
373
|
+
bold=True,
|
|
374
|
+
)
|
|
375
|
+
raise typer.Exit(code=1) from None
|
|
359
376
|
raise
|
flwr/clientapp/mod/__init__.py
CHANGED
|
@@ -17,9 +17,12 @@
|
|
|
17
17
|
|
|
18
18
|
from flwr.client.mod.comms_mods import arrays_size_mod, message_size_mod
|
|
19
19
|
|
|
20
|
-
from .centraldp_mods import fixedclipping_mod
|
|
20
|
+
from .centraldp_mods import adaptiveclipping_mod, fixedclipping_mod
|
|
21
|
+
from .localdp_mod import LocalDpMod
|
|
21
22
|
|
|
22
23
|
__all__ = [
|
|
24
|
+
"LocalDpMod",
|
|
25
|
+
"adaptiveclipping_mod",
|
|
23
26
|
"arrays_size_mod",
|
|
24
27
|
"fixedclipping_mod",
|
|
25
28
|
"message_size_mod",
|