flwr-nightly 1.8.0.dev20240305__py3-none-any.whl → 1.8.0.dev20240306__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- flwr/cli/app.py +2 -0
- flwr/cli/flower_toml.py +151 -0
- flwr/cli/run/__init__.py +21 -0
- flwr/cli/run/run.py +102 -0
- flwr/client/grpc_client/connection.py +9 -14
- flwr/client/message_handler/message_handler.py +5 -10
- flwr/client/mod/centraldp_mods.py +5 -5
- flwr/client/mod/secure_aggregation/secaggplus_mod.py +2 -2
- flwr/common/__init__.py +2 -0
- flwr/common/constant.py +11 -5
- flwr/server/compat/driver_client_proxy.py +5 -11
- flwr/server/workflow/default_workflows.py +4 -8
- flwr/simulation/ray_transport/ray_client_proxy.py +5 -10
- {flwr_nightly-1.8.0.dev20240305.dist-info → flwr_nightly-1.8.0.dev20240306.dist-info}/METADATA +4 -3
- {flwr_nightly-1.8.0.dev20240305.dist-info → flwr_nightly-1.8.0.dev20240306.dist-info}/RECORD +18 -15
- {flwr_nightly-1.8.0.dev20240305.dist-info → flwr_nightly-1.8.0.dev20240306.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.8.0.dev20240305.dist-info → flwr_nightly-1.8.0.dev20240306.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.8.0.dev20240305.dist-info → flwr_nightly-1.8.0.dev20240306.dist-info}/entry_points.txt +0 -0
flwr/cli/app.py
CHANGED
@@ -18,6 +18,7 @@ import typer
|
|
18
18
|
|
19
19
|
from .example import example
|
20
20
|
from .new import new
|
21
|
+
from .run import run
|
21
22
|
|
22
23
|
app = typer.Typer(
|
23
24
|
help=typer.style(
|
@@ -30,6 +31,7 @@ app = typer.Typer(
|
|
30
31
|
|
31
32
|
app.command()(new)
|
32
33
|
app.command()(example)
|
34
|
+
app.command()(run)
|
33
35
|
|
34
36
|
if __name__ == "__main__":
|
35
37
|
app()
|
flwr/cli/flower_toml.py
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
# Copyright 2024 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
|
+
"""Utility to validate the `flower.toml` file."""
|
16
|
+
|
17
|
+
import importlib
|
18
|
+
import os
|
19
|
+
from typing import Any, Dict, List, Optional, Tuple
|
20
|
+
|
21
|
+
import tomli
|
22
|
+
|
23
|
+
|
24
|
+
def load_flower_toml(path: Optional[str] = None) -> Optional[Dict[str, Any]]:
|
25
|
+
"""Load flower.toml and return as dict."""
|
26
|
+
if path is None:
|
27
|
+
cur_dir = os.getcwd()
|
28
|
+
toml_path = os.path.join(cur_dir, "flower.toml")
|
29
|
+
else:
|
30
|
+
toml_path = path
|
31
|
+
|
32
|
+
if not os.path.isfile(toml_path):
|
33
|
+
return None
|
34
|
+
|
35
|
+
with open(toml_path, encoding="utf-8") as toml_file:
|
36
|
+
data = tomli.loads(toml_file.read())
|
37
|
+
return data
|
38
|
+
|
39
|
+
|
40
|
+
def validate_flower_toml_fields(
|
41
|
+
config: Dict[str, Any]
|
42
|
+
) -> Tuple[bool, List[str], List[str]]:
|
43
|
+
"""Validate flower.toml fields."""
|
44
|
+
errors = []
|
45
|
+
warnings = []
|
46
|
+
|
47
|
+
if "project" not in config:
|
48
|
+
errors.append("Missing [project] section")
|
49
|
+
else:
|
50
|
+
if "name" not in config["project"]:
|
51
|
+
errors.append('Property "name" missing in [project]')
|
52
|
+
if "version" not in config["project"]:
|
53
|
+
errors.append('Property "version" missing in [project]')
|
54
|
+
if "description" not in config["project"]:
|
55
|
+
warnings.append('Recommended property "description" missing in [project]')
|
56
|
+
if "license" not in config["project"]:
|
57
|
+
warnings.append('Recommended property "license" missing in [project]')
|
58
|
+
if "authors" not in config["project"]:
|
59
|
+
warnings.append('Recommended property "authors" missing in [project]')
|
60
|
+
|
61
|
+
if "flower" not in config:
|
62
|
+
errors.append("Missing [flower] section")
|
63
|
+
elif "components" not in config["flower"]:
|
64
|
+
errors.append("Missing [flower.components] section")
|
65
|
+
else:
|
66
|
+
if "serverapp" not in config["flower"]["components"]:
|
67
|
+
errors.append('Property "serverapp" missing in [flower.components]')
|
68
|
+
if "clientapp" not in config["flower"]["components"]:
|
69
|
+
errors.append('Property "clientapp" missing in [flower.components]')
|
70
|
+
|
71
|
+
return len(errors) == 0, errors, warnings
|
72
|
+
|
73
|
+
|
74
|
+
def validate_object_reference(ref: str) -> Tuple[bool, Optional[str]]:
|
75
|
+
"""Validate object reference.
|
76
|
+
|
77
|
+
Returns
|
78
|
+
-------
|
79
|
+
Tuple[bool, Optional[str]]
|
80
|
+
A boolean indicating whether an object reference is valid and
|
81
|
+
the reason why it might not be.
|
82
|
+
"""
|
83
|
+
module_str, _, attributes_str = ref.partition(":")
|
84
|
+
if not module_str:
|
85
|
+
return (
|
86
|
+
False,
|
87
|
+
f"Missing module in {ref}",
|
88
|
+
)
|
89
|
+
if not attributes_str:
|
90
|
+
return (
|
91
|
+
False,
|
92
|
+
f"Missing attribute in {ref}",
|
93
|
+
)
|
94
|
+
|
95
|
+
# Load module
|
96
|
+
try:
|
97
|
+
module = importlib.import_module(module_str)
|
98
|
+
except ModuleNotFoundError:
|
99
|
+
return False, f"Unable to load module {module_str}"
|
100
|
+
|
101
|
+
# Recursively load attribute
|
102
|
+
attribute = module
|
103
|
+
try:
|
104
|
+
for attribute_str in attributes_str.split("."):
|
105
|
+
attribute = getattr(attribute, attribute_str)
|
106
|
+
except AttributeError:
|
107
|
+
return (
|
108
|
+
False,
|
109
|
+
f"Unable to load attribute {attributes_str} from module {module_str}",
|
110
|
+
)
|
111
|
+
|
112
|
+
return (True, None)
|
113
|
+
|
114
|
+
|
115
|
+
def validate_flower_toml(config: Dict[str, Any]) -> Tuple[bool, List[str], List[str]]:
|
116
|
+
"""Validate flower.toml."""
|
117
|
+
is_valid, errors, warnings = validate_flower_toml_fields(config)
|
118
|
+
|
119
|
+
if not is_valid:
|
120
|
+
return False, errors, warnings
|
121
|
+
|
122
|
+
# Validate serverapp
|
123
|
+
is_valid, reason = validate_object_reference(
|
124
|
+
config["flower"]["components"]["serverapp"]
|
125
|
+
)
|
126
|
+
if not is_valid and isinstance(reason, str):
|
127
|
+
return False, [reason], []
|
128
|
+
|
129
|
+
# Validate clientapp
|
130
|
+
is_valid, reason = validate_object_reference(
|
131
|
+
config["flower"]["components"]["clientapp"]
|
132
|
+
)
|
133
|
+
|
134
|
+
if not is_valid and isinstance(reason, str):
|
135
|
+
return False, [reason], []
|
136
|
+
|
137
|
+
return True, [], []
|
138
|
+
|
139
|
+
|
140
|
+
def apply_defaults(
|
141
|
+
config: Dict[str, Any],
|
142
|
+
defaults: Dict[str, Any],
|
143
|
+
) -> Dict[str, Any]:
|
144
|
+
"""Apply defaults to config."""
|
145
|
+
for key in defaults:
|
146
|
+
if key in config:
|
147
|
+
if isinstance(config[key], dict) and isinstance(defaults[key], dict):
|
148
|
+
apply_defaults(config[key], defaults[key])
|
149
|
+
else:
|
150
|
+
config[key] = defaults[key]
|
151
|
+
return config
|
flwr/cli/run/__init__.py
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Copyright 2024 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 `run` command."""
|
16
|
+
|
17
|
+
from .run import run as run
|
18
|
+
|
19
|
+
__all__ = [
|
20
|
+
"run",
|
21
|
+
]
|
flwr/cli/run/run.py
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# Copyright 2024 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 `run` command."""
|
16
|
+
|
17
|
+
import sys
|
18
|
+
|
19
|
+
import typer
|
20
|
+
|
21
|
+
from flwr.cli.flower_toml import apply_defaults, load_flower_toml, validate_flower_toml
|
22
|
+
from flwr.simulation.run_simulation import _run_simulation
|
23
|
+
|
24
|
+
|
25
|
+
def run() -> None:
|
26
|
+
"""Run Flower project."""
|
27
|
+
print(
|
28
|
+
typer.style("Loading project configuration... ", fg=typer.colors.BLUE),
|
29
|
+
end="",
|
30
|
+
)
|
31
|
+
config = load_flower_toml()
|
32
|
+
if not config:
|
33
|
+
print(
|
34
|
+
typer.style(
|
35
|
+
"Project configuration could not be loaded. "
|
36
|
+
"flower.toml does not exist.",
|
37
|
+
fg=typer.colors.RED,
|
38
|
+
bold=True,
|
39
|
+
)
|
40
|
+
)
|
41
|
+
sys.exit()
|
42
|
+
print(typer.style("Success", fg=typer.colors.GREEN))
|
43
|
+
|
44
|
+
print(
|
45
|
+
typer.style("Validating project configuration... ", fg=typer.colors.BLUE),
|
46
|
+
end="",
|
47
|
+
)
|
48
|
+
is_valid, errors, warnings = validate_flower_toml(config)
|
49
|
+
if warnings:
|
50
|
+
print(
|
51
|
+
typer.style(
|
52
|
+
"Project configuration is missing the following "
|
53
|
+
"recommended properties:\n"
|
54
|
+
+ "\n".join([f"- {line}" for line in warnings]),
|
55
|
+
fg=typer.colors.RED,
|
56
|
+
bold=True,
|
57
|
+
)
|
58
|
+
)
|
59
|
+
|
60
|
+
if not is_valid:
|
61
|
+
print(
|
62
|
+
typer.style(
|
63
|
+
"Project configuration could not be loaded.\nflower.toml is invalid:\n"
|
64
|
+
+ "\n".join([f"- {line}" for line in errors]),
|
65
|
+
fg=typer.colors.RED,
|
66
|
+
bold=True,
|
67
|
+
)
|
68
|
+
)
|
69
|
+
sys.exit()
|
70
|
+
print(typer.style("Success", fg=typer.colors.GREEN))
|
71
|
+
|
72
|
+
# Apply defaults
|
73
|
+
defaults = {
|
74
|
+
"flower": {
|
75
|
+
"engine": {"name": "simulation", "simulation": {"super-node": {"num": 100}}}
|
76
|
+
}
|
77
|
+
}
|
78
|
+
config = apply_defaults(config, defaults)
|
79
|
+
|
80
|
+
server_app_ref = config["flower"]["components"]["serverapp"]
|
81
|
+
client_app_ref = config["flower"]["components"]["clientapp"]
|
82
|
+
engine = config["flower"]["engine"]["name"]
|
83
|
+
|
84
|
+
if engine == "simulation":
|
85
|
+
num_supernodes = config["flower"]["engine"]["simulation"]["super-node"]["num"]
|
86
|
+
|
87
|
+
print(
|
88
|
+
typer.style("Starting run... ", fg=typer.colors.BLUE),
|
89
|
+
)
|
90
|
+
_run_simulation(
|
91
|
+
server_app_attr=server_app_ref,
|
92
|
+
client_app_attr=client_app_ref,
|
93
|
+
num_supernodes=num_supernodes,
|
94
|
+
)
|
95
|
+
else:
|
96
|
+
print(
|
97
|
+
typer.style(
|
98
|
+
f"Engine '{engine}' is not yet supported in `flwr run`",
|
99
|
+
fg=typer.colors.RED,
|
100
|
+
bold=True,
|
101
|
+
)
|
102
|
+
)
|
@@ -31,12 +31,7 @@ from flwr.common import (
|
|
31
31
|
)
|
32
32
|
from flwr.common import recordset_compat as compat
|
33
33
|
from flwr.common import serde
|
34
|
-
from flwr.common.constant import
|
35
|
-
MESSAGE_TYPE_EVALUATE,
|
36
|
-
MESSAGE_TYPE_FIT,
|
37
|
-
MESSAGE_TYPE_GET_PARAMETERS,
|
38
|
-
MESSAGE_TYPE_GET_PROPERTIES,
|
39
|
-
)
|
34
|
+
from flwr.common.constant import MessageType, MessageTypeLegacy
|
40
35
|
from flwr.common.grpc import create_channel
|
41
36
|
from flwr.common.logger import log
|
42
37
|
from flwr.common.retry_invoker import RetryInvoker
|
@@ -148,22 +143,22 @@ def grpc_connection( # pylint: disable=R0915
|
|
148
143
|
recordset = compat.getpropertiesins_to_recordset(
|
149
144
|
serde.get_properties_ins_from_proto(proto.get_properties_ins)
|
150
145
|
)
|
151
|
-
message_type =
|
146
|
+
message_type = MessageTypeLegacy.GET_PROPERTIES
|
152
147
|
elif field == "get_parameters_ins":
|
153
148
|
recordset = compat.getparametersins_to_recordset(
|
154
149
|
serde.get_parameters_ins_from_proto(proto.get_parameters_ins)
|
155
150
|
)
|
156
|
-
message_type =
|
151
|
+
message_type = MessageTypeLegacy.GET_PARAMETERS
|
157
152
|
elif field == "fit_ins":
|
158
153
|
recordset = compat.fitins_to_recordset(
|
159
154
|
serde.fit_ins_from_proto(proto.fit_ins), False
|
160
155
|
)
|
161
|
-
message_type =
|
156
|
+
message_type = MessageType.TRAIN
|
162
157
|
elif field == "evaluate_ins":
|
163
158
|
recordset = compat.evaluateins_to_recordset(
|
164
159
|
serde.evaluate_ins_from_proto(proto.evaluate_ins), False
|
165
160
|
)
|
166
|
-
message_type =
|
161
|
+
message_type = MessageType.EVALUATE
|
167
162
|
elif field == "reconnect_ins":
|
168
163
|
recordset = RecordSet()
|
169
164
|
recordset.configs_records["config"] = ConfigsRecord(
|
@@ -197,20 +192,20 @@ def grpc_connection( # pylint: disable=R0915
|
|
197
192
|
message_type = message.metadata.message_type
|
198
193
|
|
199
194
|
# RecordSet --> *Res --> *Res proto -> ClientMessage proto
|
200
|
-
if message_type ==
|
195
|
+
if message_type == MessageTypeLegacy.GET_PROPERTIES:
|
201
196
|
getpropres = compat.recordset_to_getpropertiesres(recordset)
|
202
197
|
msg_proto = ClientMessage(
|
203
198
|
get_properties_res=serde.get_properties_res_to_proto(getpropres)
|
204
199
|
)
|
205
|
-
elif message_type ==
|
200
|
+
elif message_type == MessageTypeLegacy.GET_PARAMETERS:
|
206
201
|
getparamres = compat.recordset_to_getparametersres(recordset, False)
|
207
202
|
msg_proto = ClientMessage(
|
208
203
|
get_parameters_res=serde.get_parameters_res_to_proto(getparamres)
|
209
204
|
)
|
210
|
-
elif message_type ==
|
205
|
+
elif message_type == MessageType.TRAIN:
|
211
206
|
fitres = compat.recordset_to_fitres(recordset, False)
|
212
207
|
msg_proto = ClientMessage(fit_res=serde.fit_res_to_proto(fitres))
|
213
|
-
elif message_type ==
|
208
|
+
elif message_type == MessageType.EVALUATE:
|
214
209
|
evalres = compat.recordset_to_evaluateres(recordset)
|
215
210
|
msg_proto = ClientMessage(evaluate_res=serde.evaluate_res_to_proto(evalres))
|
216
211
|
elif message_type == "reconnect":
|
@@ -27,12 +27,7 @@ from flwr.client.client import (
|
|
27
27
|
from flwr.client.numpy_client import NumPyClient
|
28
28
|
from flwr.client.typing import ClientFn
|
29
29
|
from flwr.common import ConfigsRecord, Context, Message, Metadata, RecordSet, log
|
30
|
-
from flwr.common.constant import
|
31
|
-
MESSAGE_TYPE_EVALUATE,
|
32
|
-
MESSAGE_TYPE_FIT,
|
33
|
-
MESSAGE_TYPE_GET_PARAMETERS,
|
34
|
-
MESSAGE_TYPE_GET_PROPERTIES,
|
35
|
-
)
|
30
|
+
from flwr.common.constant import MessageType, MessageTypeLegacy
|
36
31
|
from flwr.common.recordset_compat import (
|
37
32
|
evaluateres_to_recordset,
|
38
33
|
fitres_to_recordset,
|
@@ -115,14 +110,14 @@ def handle_legacy_message_from_msgtype(
|
|
115
110
|
message_type = message.metadata.message_type
|
116
111
|
|
117
112
|
# Handle GetPropertiesIns
|
118
|
-
if message_type ==
|
113
|
+
if message_type == MessageTypeLegacy.GET_PROPERTIES:
|
119
114
|
get_properties_res = maybe_call_get_properties(
|
120
115
|
client=client,
|
121
116
|
get_properties_ins=recordset_to_getpropertiesins(message.content),
|
122
117
|
)
|
123
118
|
out_recordset = getpropertiesres_to_recordset(get_properties_res)
|
124
119
|
# Handle GetParametersIns
|
125
|
-
elif message_type ==
|
120
|
+
elif message_type == MessageTypeLegacy.GET_PARAMETERS:
|
126
121
|
get_parameters_res = maybe_call_get_parameters(
|
127
122
|
client=client,
|
128
123
|
get_parameters_ins=recordset_to_getparametersins(message.content),
|
@@ -131,14 +126,14 @@ def handle_legacy_message_from_msgtype(
|
|
131
126
|
get_parameters_res, keep_input=False
|
132
127
|
)
|
133
128
|
# Handle FitIns
|
134
|
-
elif message_type ==
|
129
|
+
elif message_type == MessageType.TRAIN:
|
135
130
|
fit_res = maybe_call_fit(
|
136
131
|
client=client,
|
137
132
|
fit_ins=recordset_to_fitins(message.content, keep_input=True),
|
138
133
|
)
|
139
134
|
out_recordset = fitres_to_recordset(fit_res, keep_input=False)
|
140
135
|
# Handle EvaluateIns
|
141
|
-
elif message_type ==
|
136
|
+
elif message_type == MessageType.EVALUATE:
|
142
137
|
evaluate_res = maybe_call_evaluate(
|
143
138
|
client=client,
|
144
139
|
evaluate_ins=recordset_to_evaluateins(message.content, keep_input=True),
|
@@ -18,7 +18,7 @@
|
|
18
18
|
from flwr.client.typing import ClientAppCallable
|
19
19
|
from flwr.common import ndarrays_to_parameters, parameters_to_ndarrays
|
20
20
|
from flwr.common import recordset_compat as compat
|
21
|
-
from flwr.common.constant import
|
21
|
+
from flwr.common.constant import MessageType
|
22
22
|
from flwr.common.context import Context
|
23
23
|
from flwr.common.differential_privacy import (
|
24
24
|
compute_adaptive_clip_model_update,
|
@@ -40,7 +40,7 @@ def fixedclipping_mod(
|
|
40
40
|
|
41
41
|
This mod clips the client model updates before sending them to the server.
|
42
42
|
|
43
|
-
It operates on messages with type
|
43
|
+
It operates on messages with type MessageType.TRAIN.
|
44
44
|
|
45
45
|
Notes
|
46
46
|
-----
|
@@ -48,7 +48,7 @@ def fixedclipping_mod(
|
|
48
48
|
|
49
49
|
Typically, fixedclipping_mod should be the last to operate on params.
|
50
50
|
"""
|
51
|
-
if msg.metadata.message_type !=
|
51
|
+
if msg.metadata.message_type != MessageType.TRAIN:
|
52
52
|
return call_next(msg, ctxt)
|
53
53
|
fit_ins = compat.recordset_to_fitins(msg.content, keep_input=True)
|
54
54
|
if KEY_CLIPPING_NORM not in fit_ins.config:
|
@@ -93,7 +93,7 @@ def adaptiveclipping_mod(
|
|
93
93
|
|
94
94
|
It also sends KEY_NORM_BIT to the server for computing the new clipping value.
|
95
95
|
|
96
|
-
It operates on messages with type
|
96
|
+
It operates on messages with type MessageType.TRAIN.
|
97
97
|
|
98
98
|
Notes
|
99
99
|
-----
|
@@ -101,7 +101,7 @@ def adaptiveclipping_mod(
|
|
101
101
|
|
102
102
|
Typically, adaptiveclipping_mod should be the last to operate on params.
|
103
103
|
"""
|
104
|
-
if msg.metadata.message_type !=
|
104
|
+
if msg.metadata.message_type != MessageType.TRAIN:
|
105
105
|
return call_next(msg, ctxt)
|
106
106
|
|
107
107
|
fit_ins = compat.recordset_to_fitins(msg.content, keep_input=True)
|
@@ -30,7 +30,7 @@ from flwr.common import (
|
|
30
30
|
parameters_to_ndarrays,
|
31
31
|
)
|
32
32
|
from flwr.common import recordset_compat as compat
|
33
|
-
from flwr.common.constant import
|
33
|
+
from flwr.common.constant import MessageType
|
34
34
|
from flwr.common.logger import log
|
35
35
|
from flwr.common.secure_aggregation.crypto.shamir import create_shares
|
36
36
|
from flwr.common.secure_aggregation.crypto.symmetric_encryption import (
|
@@ -150,7 +150,7 @@ def secaggplus_mod(
|
|
150
150
|
) -> Message:
|
151
151
|
"""Handle incoming message and return results, following the SecAgg+ protocol."""
|
152
152
|
# Ignore non-fit messages
|
153
|
-
if msg.metadata.message_type !=
|
153
|
+
if msg.metadata.message_type != MessageType.TRAIN:
|
154
154
|
return call_next(msg, ctxt)
|
155
155
|
|
156
156
|
# Retrieve local state
|
flwr/common/__init__.py
CHANGED
@@ -16,6 +16,7 @@
|
|
16
16
|
|
17
17
|
|
18
18
|
from .constant import MessageType as MessageType
|
19
|
+
from .constant import MessageTypeLegacy as MessageTypeLegacy
|
19
20
|
from .context import Context as Context
|
20
21
|
from .date import now as now
|
21
22
|
from .grpc import GRPC_MAX_MESSAGE_LENGTH
|
@@ -85,6 +86,7 @@ __all__ = [
|
|
85
86
|
"log",
|
86
87
|
"Message",
|
87
88
|
"MessageType",
|
89
|
+
"MessageTypeLegacy",
|
88
90
|
"Metadata",
|
89
91
|
"Metrics",
|
90
92
|
"MetricsAggregationFn",
|
flwr/common/constant.py
CHANGED
@@ -36,11 +36,6 @@ TRANSPORT_TYPES = [
|
|
36
36
|
TRANSPORT_TYPE_VCE,
|
37
37
|
]
|
38
38
|
|
39
|
-
MESSAGE_TYPE_GET_PROPERTIES = "get_properties"
|
40
|
-
MESSAGE_TYPE_GET_PARAMETERS = "get_parameters"
|
41
|
-
MESSAGE_TYPE_FIT = "fit"
|
42
|
-
MESSAGE_TYPE_EVALUATE = "evaluate"
|
43
|
-
|
44
39
|
|
45
40
|
class MessageType:
|
46
41
|
"""Message type."""
|
@@ -53,6 +48,17 @@ class MessageType:
|
|
53
48
|
raise TypeError(f"{cls.__name__} cannot be instantiated.")
|
54
49
|
|
55
50
|
|
51
|
+
class MessageTypeLegacy:
|
52
|
+
"""Legacy message type."""
|
53
|
+
|
54
|
+
GET_PROPERTIES = "get_properties"
|
55
|
+
GET_PARAMETERS = "get_parameters"
|
56
|
+
|
57
|
+
def __new__(cls) -> MessageTypeLegacy:
|
58
|
+
"""Prevent instantiation."""
|
59
|
+
raise TypeError(f"{cls.__name__} cannot be instantiated.")
|
60
|
+
|
61
|
+
|
56
62
|
class SType:
|
57
63
|
"""Serialisation type."""
|
58
64
|
|
@@ -19,15 +19,9 @@ import time
|
|
19
19
|
from typing import List, Optional
|
20
20
|
|
21
21
|
from flwr import common
|
22
|
-
from flwr.common import RecordSet
|
22
|
+
from flwr.common import MessageType, MessageTypeLegacy, RecordSet
|
23
23
|
from flwr.common import recordset_compat as compat
|
24
24
|
from flwr.common import serde
|
25
|
-
from flwr.common.constant import (
|
26
|
-
MESSAGE_TYPE_EVALUATE,
|
27
|
-
MESSAGE_TYPE_FIT,
|
28
|
-
MESSAGE_TYPE_GET_PARAMETERS,
|
29
|
-
MESSAGE_TYPE_GET_PROPERTIES,
|
30
|
-
)
|
31
25
|
from flwr.proto import driver_pb2, node_pb2, task_pb2 # pylint: disable=E0611
|
32
26
|
from flwr.server.client_proxy import ClientProxy
|
33
27
|
|
@@ -57,7 +51,7 @@ class DriverClientProxy(ClientProxy):
|
|
57
51
|
out_recordset = compat.getpropertiesins_to_recordset(ins)
|
58
52
|
# Fetch response
|
59
53
|
in_recordset = self._send_receive_recordset(
|
60
|
-
out_recordset,
|
54
|
+
out_recordset, MessageTypeLegacy.GET_PROPERTIES, timeout, group_id
|
61
55
|
)
|
62
56
|
# RecordSet to Res
|
63
57
|
return compat.recordset_to_getpropertiesres(in_recordset)
|
@@ -73,7 +67,7 @@ class DriverClientProxy(ClientProxy):
|
|
73
67
|
out_recordset = compat.getparametersins_to_recordset(ins)
|
74
68
|
# Fetch response
|
75
69
|
in_recordset = self._send_receive_recordset(
|
76
|
-
out_recordset,
|
70
|
+
out_recordset, MessageTypeLegacy.GET_PARAMETERS, timeout, group_id
|
77
71
|
)
|
78
72
|
# RecordSet to Res
|
79
73
|
return compat.recordset_to_getparametersres(in_recordset, False)
|
@@ -86,7 +80,7 @@ class DriverClientProxy(ClientProxy):
|
|
86
80
|
out_recordset = compat.fitins_to_recordset(ins, keep_input=True)
|
87
81
|
# Fetch response
|
88
82
|
in_recordset = self._send_receive_recordset(
|
89
|
-
out_recordset,
|
83
|
+
out_recordset, MessageType.TRAIN, timeout, group_id
|
90
84
|
)
|
91
85
|
# RecordSet to Res
|
92
86
|
return compat.recordset_to_fitres(in_recordset, keep_input=False)
|
@@ -99,7 +93,7 @@ class DriverClientProxy(ClientProxy):
|
|
99
93
|
out_recordset = compat.evaluateins_to_recordset(ins, keep_input=True)
|
100
94
|
# Fetch response
|
101
95
|
in_recordset = self._send_receive_recordset(
|
102
|
-
out_recordset,
|
96
|
+
out_recordset, MessageType.EVALUATE, timeout, group_id
|
103
97
|
)
|
104
98
|
# RecordSet to Res
|
105
99
|
return compat.recordset_to_evaluateres(in_recordset)
|
@@ -21,11 +21,7 @@ from typing import Optional, cast
|
|
21
21
|
|
22
22
|
import flwr.common.recordset_compat as compat
|
23
23
|
from flwr.common import ConfigsRecord, Context, GetParametersIns, log
|
24
|
-
from flwr.common.constant import
|
25
|
-
MESSAGE_TYPE_EVALUATE,
|
26
|
-
MESSAGE_TYPE_FIT,
|
27
|
-
MESSAGE_TYPE_GET_PARAMETERS,
|
28
|
-
)
|
24
|
+
from flwr.common.constant import MessageType, MessageTypeLegacy
|
29
25
|
|
30
26
|
from ..compat.app_utils import start_update_client_manager_thread
|
31
27
|
from ..compat.legacy_context import LegacyContext
|
@@ -134,7 +130,7 @@ def default_init_params_workflow(driver: Driver, context: Context) -> None:
|
|
134
130
|
[
|
135
131
|
driver.create_message(
|
136
132
|
content=content,
|
137
|
-
message_type=
|
133
|
+
message_type=MessageTypeLegacy.GET_PARAMETERS,
|
138
134
|
dst_node_id=random_client.node_id,
|
139
135
|
group_id="",
|
140
136
|
ttl="",
|
@@ -232,7 +228,7 @@ def default_fit_workflow(driver: Driver, context: Context) -> None:
|
|
232
228
|
out_messages = [
|
233
229
|
driver.create_message(
|
234
230
|
content=compat.fitins_to_recordset(fitins, True),
|
235
|
-
message_type=
|
231
|
+
message_type=MessageType.TRAIN,
|
236
232
|
dst_node_id=proxy.node_id,
|
237
233
|
group_id="",
|
238
234
|
ttl="",
|
@@ -313,7 +309,7 @@ def default_evaluate_workflow(driver: Driver, context: Context) -> None:
|
|
313
309
|
out_messages = [
|
314
310
|
driver.create_message(
|
315
311
|
content=compat.evaluateins_to_recordset(evalins, True),
|
316
|
-
message_type=
|
312
|
+
message_type=MessageType.EVALUATE,
|
317
313
|
dst_node_id=proxy.node_id,
|
318
314
|
group_id="",
|
319
315
|
ttl="",
|
@@ -24,12 +24,7 @@ from flwr.client import ClientFn
|
|
24
24
|
from flwr.client.client_app import ClientApp
|
25
25
|
from flwr.client.node_state import NodeState
|
26
26
|
from flwr.common import Message, Metadata, RecordSet
|
27
|
-
from flwr.common.constant import
|
28
|
-
MESSAGE_TYPE_EVALUATE,
|
29
|
-
MESSAGE_TYPE_FIT,
|
30
|
-
MESSAGE_TYPE_GET_PARAMETERS,
|
31
|
-
MESSAGE_TYPE_GET_PROPERTIES,
|
32
|
-
)
|
27
|
+
from flwr.common.constant import MessageType, MessageTypeLegacy
|
33
28
|
from flwr.common.logger import log
|
34
29
|
from flwr.common.recordset_compat import (
|
35
30
|
evaluateins_to_recordset,
|
@@ -126,7 +121,7 @@ class RayActorClientProxy(ClientProxy):
|
|
126
121
|
recordset = getpropertiesins_to_recordset(ins)
|
127
122
|
message = self._wrap_recordset_in_message(
|
128
123
|
recordset,
|
129
|
-
message_type=
|
124
|
+
message_type=MessageTypeLegacy.GET_PROPERTIES,
|
130
125
|
timeout=timeout,
|
131
126
|
group_id=group_id,
|
132
127
|
)
|
@@ -145,7 +140,7 @@ class RayActorClientProxy(ClientProxy):
|
|
145
140
|
recordset = getparametersins_to_recordset(ins)
|
146
141
|
message = self._wrap_recordset_in_message(
|
147
142
|
recordset,
|
148
|
-
message_type=
|
143
|
+
message_type=MessageTypeLegacy.GET_PARAMETERS,
|
149
144
|
timeout=timeout,
|
150
145
|
group_id=group_id,
|
151
146
|
)
|
@@ -163,7 +158,7 @@ class RayActorClientProxy(ClientProxy):
|
|
163
158
|
) # This must stay TRUE since ins are in-memory
|
164
159
|
message = self._wrap_recordset_in_message(
|
165
160
|
recordset,
|
166
|
-
message_type=
|
161
|
+
message_type=MessageType.TRAIN,
|
167
162
|
timeout=timeout,
|
168
163
|
group_id=group_id,
|
169
164
|
)
|
@@ -181,7 +176,7 @@ class RayActorClientProxy(ClientProxy):
|
|
181
176
|
) # This must stay TRUE since ins are in-memory
|
182
177
|
message = self._wrap_recordset_in_message(
|
183
178
|
recordset,
|
184
|
-
message_type=
|
179
|
+
message_type=MessageType.EVALUATE,
|
185
180
|
timeout=timeout,
|
186
181
|
group_id=group_id,
|
187
182
|
)
|
{flwr_nightly-1.8.0.dev20240305.dist-info → flwr_nightly-1.8.0.dev20240306.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: flwr-nightly
|
3
|
-
Version: 1.8.0.
|
3
|
+
Version: 1.8.0.dev20240306
|
4
4
|
Summary: Flower: A Friendly Federated Learning Framework
|
5
5
|
Home-page: https://flower.ai
|
6
6
|
License: Apache-2.0
|
@@ -42,6 +42,7 @@ Requires-Dist: pydantic (<2.0.0) ; extra == "simulation"
|
|
42
42
|
Requires-Dist: ray (==2.6.3) ; extra == "simulation"
|
43
43
|
Requires-Dist: requests (>=2.31.0,<3.0.0) ; extra == "rest"
|
44
44
|
Requires-Dist: starlette (>=0.31.0,<0.32.0) ; extra == "rest"
|
45
|
+
Requires-Dist: tomli (>=2.0.1,<3.0.0)
|
45
46
|
Requires-Dist: typer[all] (>=0.9.0,<0.10.0)
|
46
47
|
Requires-Dist: uvicorn[standard] (>=0.23.0,<0.24.0) ; extra == "rest"
|
47
48
|
Project-URL: Documentation, https://flower.ai
|
@@ -182,7 +183,6 @@ Quickstart examples:
|
|
182
183
|
- [Quickstart (JAX)](https://github.com/adap/flower/tree/main/examples/quickstart-jax)
|
183
184
|
- [Quickstart (MONAI)](https://github.com/adap/flower/tree/main/examples/quickstart-monai)
|
184
185
|
- [Quickstart (scikit-learn)](https://github.com/adap/flower/tree/main/examples/sklearn-logreg-mnist)
|
185
|
-
- [Quickstart (XGBoost)](https://github.com/adap/flower/tree/main/examples/xgboost-quickstart)
|
186
186
|
- [Quickstart (Android [TFLite])](https://github.com/adap/flower/tree/main/examples/android)
|
187
187
|
- [Quickstart (iOS [CoreML])](https://github.com/adap/flower/tree/main/examples/ios)
|
188
188
|
- [Quickstart (MLX)](https://github.com/adap/flower/tree/main/examples/quickstart-mlx)
|
@@ -194,7 +194,8 @@ Other [examples](https://github.com/adap/flower/tree/main/examples):
|
|
194
194
|
- [PyTorch: From Centralized to Federated](https://github.com/adap/flower/tree/main/examples/pytorch-from-centralized-to-federated)
|
195
195
|
- [Vertical FL](https://github.com/adap/flower/tree/main/examples/vertical-fl)
|
196
196
|
- [Federated Finetuning of OpenAI's Whisper](https://github.com/adap/flower/tree/main/examples/whisper-federated-finetuning)
|
197
|
-
- [
|
197
|
+
- [Federated Finetuning of Large Language Model](https://github.com/adap/flower/tree/main/examples/fedllm-finetune)
|
198
|
+
- [Federated Finetuning of a Vision Transformer](https://github.com/adap/flower/tree/main/examples/vit-finetune)
|
198
199
|
- [Advanced Flower with TensorFlow/Keras](https://github.com/adap/flower/tree/main/examples/advanced-tensorflow)
|
199
200
|
- [Advanced Flower with PyTorch](https://github.com/adap/flower/tree/main/examples/advanced-pytorch)
|
200
201
|
- Single-Machine Simulation of Federated Learning Systems ([PyTorch](https://github.com/adap/flower/tree/main/examples/simulation-pytorch)) ([Tensorflow](https://github.com/adap/flower/tree/main/examples/simulation-tensorflow))
|
{flwr_nightly-1.8.0.dev20240305.dist-info → flwr_nightly-1.8.0.dev20240306.dist-info}/RECORD
RENAMED
@@ -1,7 +1,8 @@
|
|
1
1
|
flwr/__init__.py,sha256=VmBWedrCxqmt4QvUHBLqyVEH6p7zaFMD_oCHerXHSVw,937
|
2
2
|
flwr/cli/__init__.py,sha256=cZJVgozlkC6Ni2Hd_FAIrqefrkCGOV18fikToq-6iLw,720
|
3
|
-
flwr/cli/app.py,sha256=
|
3
|
+
flwr/cli/app.py,sha256=38thPnMydBmNAxNE9mz4By-KdRUhJfoUgeDuAxMYF_U,1095
|
4
4
|
flwr/cli/example.py,sha256=EGPYLMQf2MgcYRn5aPp_eYYUA39M8dm69PUM4zhlHuk,2184
|
5
|
+
flwr/cli/flower_toml.py,sha256=SKnE9F8IWvg4F7rAIX1k89kQQ0LhHh08S4zexRRgOrA,4914
|
5
6
|
flwr/cli/new/__init__.py,sha256=cQzK1WH4JP2awef1t2UQ2xjl1agVEz9rwutV18SWV1k,789
|
6
7
|
flwr/cli/new/new.py,sha256=xQU4ouEHP2AntWWAqkfQup0GUFczvGqD9_yHf-U6AsU,4165
|
7
8
|
flwr/cli/new/templates/__init__.py,sha256=4luU8RL-CK8JJCstQ_ON809W9bNTkY1l9zSaPKBkgwY,725
|
@@ -19,6 +20,8 @@ flwr/cli/new/templates/app/flower.toml.tpl,sha256=fLYif3PC2hoWwNn8kTAyUSmDh7jbyh
|
|
19
20
|
flwr/cli/new/templates/app/requirements.numpy.txt.tpl,sha256=xd6_D1E6x3orei85nG1jSUcR_PhbIqEEwDiSW3ILQYY,32
|
20
21
|
flwr/cli/new/templates/app/requirements.pytorch.txt.tpl,sha256=9Z70jsiCPdsbuorhicrSdO6PVQn-3196vKZ5Ka2GkK0,87
|
21
22
|
flwr/cli/new/templates/app/requirements.tensorflow.txt.tpl,sha256=WTbIgK5G_iG0W-xtvQLCZMxL_Og26rFXial2TkYH5dw,211
|
23
|
+
flwr/cli/run/__init__.py,sha256=oCd6HmQDx-sqver1gecgx-uMA38BLTSiiKpl7RGNceg,789
|
24
|
+
flwr/cli/run/run.py,sha256=N9FLGPmtokZqe0xJQ5PcxTpWDtTHcUIklSjaRS-Mwvk,3290
|
22
25
|
flwr/cli/utils.py,sha256=9cCEIt8QmJXz85JNmPk1IHPd7p8E3KDn6h5CfF0nDL4,1926
|
23
26
|
flwr/client/__init__.py,sha256=futk_IdY_N1h8BTve4Iru51bxm7H1gv58ZPIXWi5XUA,1187
|
24
27
|
flwr/client/app.py,sha256=Z_RfL0i-h0Cr3A4_DZrX258c6aWG4aJkO8fYtJYy_kU,23542
|
@@ -26,16 +29,16 @@ flwr/client/client.py,sha256=Vp9UkOkoHdNfn6iMYZsj_5m_GICiFfUlKEVaLad-YhM,8183
|
|
26
29
|
flwr/client/client_app.py,sha256=jrDgJBswP2hD1YdGgQoI3GU_NkliYWVU8glBJLOVzQY,4205
|
27
30
|
flwr/client/dpfedavg_numpy_client.py,sha256=9Tnig4iml2J88HBKNahegjXjbfvIQyBtaIQaqjbeqsA,7435
|
28
31
|
flwr/client/grpc_client/__init__.py,sha256=LsnbqXiJhgQcB0XzAlUQgPx011Uf7Y7yabIC1HxivJ8,735
|
29
|
-
flwr/client/grpc_client/connection.py,sha256=
|
32
|
+
flwr/client/grpc_client/connection.py,sha256=5h8WD_gJgEDTwg-PNZRR4pm6LTS7eNvYKdNbq-uoi_U,8691
|
30
33
|
flwr/client/grpc_rere_client/__init__.py,sha256=avn6W_vHEM_yZEB1S7hCZgnTbXb6ZujqRP_vAzyXu-0,752
|
31
34
|
flwr/client/grpc_rere_client/connection.py,sha256=3kpnUbS06rNQ969EybGx7zZfQPc2JmCuViyrIt610V0,7421
|
32
35
|
flwr/client/message_handler/__init__.py,sha256=abHvBRJJiiaAMNgeILQbMOa6h8WqMK2BcnvxwQZFpic,719
|
33
|
-
flwr/client/message_handler/message_handler.py,sha256=
|
36
|
+
flwr/client/message_handler/message_handler.py,sha256=SlIU-l6GgB3wfA1Qq2x7z1SSSCXO4SO4pM122QNyTvU,6516
|
34
37
|
flwr/client/message_handler/task_handler.py,sha256=ZDJBKmrn2grRMNl1rU1iGs7FiMHL5VmZiSp_6h9GHVU,1824
|
35
38
|
flwr/client/mod/__init__.py,sha256=w6r7n6fWIrrm4lEk36lh9f1Ix6LXgAzQUrgjmMspY98,961
|
36
|
-
flwr/client/mod/centraldp_mods.py,sha256=
|
39
|
+
flwr/client/mod/centraldp_mods.py,sha256=Km-u3NJNxkhTLGDYoqMj31BXJrD_mozUH0DMicyKgI8,4953
|
37
40
|
flwr/client/mod/secure_aggregation/__init__.py,sha256=AzCdezuzX2BfXUuxVRwXdv8-zUIXoU-Bf6u4LRhzvg8,796
|
38
|
-
flwr/client/mod/secure_aggregation/secaggplus_mod.py,sha256=
|
41
|
+
flwr/client/mod/secure_aggregation/secaggplus_mod.py,sha256=XKSxUdozUVcuvEaOV5syEnLr6B7ZlULk_ugh8SOdRWQ,19430
|
39
42
|
flwr/client/mod/utils.py,sha256=lvETHcCYsSWz7h8I772hCV_kZspxqlMqzriMZ-SxmKc,1226
|
40
43
|
flwr/client/node_state.py,sha256=KTTs_l4I0jBM7IsSsbAGjhfL_yZC3QANbzyvyfZBRDM,1778
|
41
44
|
flwr/client/node_state_tests.py,sha256=gPwz0zf2iuDSa11jedkur_u3Xm7lokIDG5ALD2MCvSw,2195
|
@@ -43,9 +46,9 @@ flwr/client/numpy_client.py,sha256=u76GWAdHmJM88Agm2EgLQSvO8Jnk225mJTk-_TmPjFE,1
|
|
43
46
|
flwr/client/rest_client/__init__.py,sha256=ThwOnkMdzxo_UuyTI47Q7y9oSpuTgNT2OuFvJCfuDiw,735
|
44
47
|
flwr/client/rest_client/connection.py,sha256=WGkml4gmrbbJ6OAmW3jARmL5nGaOoXo7JjWQbhPhizM,12422
|
45
48
|
flwr/client/typing.py,sha256=c9EvjlEjasxn1Wqx6bGl6Xg6vM1gMFfmXht-E2i5J-k,1006
|
46
|
-
flwr/common/__init__.py,sha256=
|
49
|
+
flwr/common/__init__.py,sha256=2dhte32YQNGHyxUazJcZuVBT433KgUkJA0FMQ4PBWjQ,3669
|
47
50
|
flwr/common/address.py,sha256=iTAN9jtmIGMrWFnx9XZQl45ZEtQJVZZLYPRBSNVARGI,1882
|
48
|
-
flwr/common/constant.py,sha256=
|
51
|
+
flwr/common/constant.py,sha256=Qh7tsgaqUwU76jnrAa9mbnuvom4ncAa0e6Xsq9jgpBU,1934
|
49
52
|
flwr/common/context.py,sha256=ounF-mWPPtXGwtae3sg5EhF58ScviOa3MVqxRpGVu-8,1313
|
50
53
|
flwr/common/date.py,sha256=UWhBZj49yX9LD4BmatS_ZFZu_-kweGh0KQJ1djyWWH4,891
|
51
54
|
flwr/common/differential_privacy.py,sha256=k9XuH8ZGp3bZtfJbydviCDcjImvcocPtjqLFJLJTgGs,5656
|
@@ -114,7 +117,7 @@ flwr/server/client_proxy.py,sha256=4G-oTwhb45sfWLx2uZdcXD98IZwdTS6F88xe3akCdUg,2
|
|
114
117
|
flwr/server/compat/__init__.py,sha256=VxnJtJyOjNFQXMNi9hIuzNlZM5n0Hj1p3aq_Pm2udw4,892
|
115
118
|
flwr/server/compat/app.py,sha256=2WwkcXJt6HFS1NI9TGnl4CSECMo_VnDQ126vtdDciTs,5288
|
116
119
|
flwr/server/compat/app_utils.py,sha256=-Ey5fyRpovmp4nHglVbliITcbxzxX_0qdtZwwfMS4ZI,3450
|
117
|
-
flwr/server/compat/driver_client_proxy.py,sha256=
|
120
|
+
flwr/server/compat/driver_client_proxy.py,sha256=yOgaKZ6jlvqgewtjM8F906Rik8xqerxMptAhEzevWA0,6368
|
118
121
|
flwr/server/compat/legacy_context.py,sha256=D2s7PvQoDnTexuRmf1uG9Von7GUj4Qqyr7qLklSlKAM,1766
|
119
122
|
flwr/server/criterion.py,sha256=ypbAexbztzGUxNen9RCHF91QeqiEQix4t4Ih3E-42MM,1061
|
120
123
|
flwr/server/driver/__init__.py,sha256=yYyVX1FcDiDFM6rw0-DSZpuRy0EoWRfG9puwlQUswFA,820
|
@@ -180,16 +183,16 @@ flwr/server/utils/__init__.py,sha256=RQVbo-bcsVtp_lJBf7dL5w01FbLrr7v3YedeGp5_YMs
|
|
180
183
|
flwr/server/utils/tensorboard.py,sha256=k0G6bqsLx7wfYbH2KtXsDYcOCfyIeE12-hefXA7lZdg,5485
|
181
184
|
flwr/server/utils/validator.py,sha256=IJN2475yyD_i_9kg_SJ_JodIuZh58ufpWGUDQRAqu2s,4740
|
182
185
|
flwr/server/workflow/__init__.py,sha256=2YrKq5wUwge8Tm1xaAdf2P3l4LbM4olka6tO_0_Mu9A,787
|
183
|
-
flwr/server/workflow/default_workflows.py,sha256=
|
186
|
+
flwr/server/workflow/default_workflows.py,sha256=G-5ziRasLHX2iPpAUg0CtmQ5Pb-x-5-lZAleIlem048,12655
|
184
187
|
flwr/simulation/__init__.py,sha256=hpoKzdovrH0_Cf8HIcXxQxyUUb3BiSk-WUNLf5STHcc,1400
|
185
188
|
flwr/simulation/app.py,sha256=WqJxdXTEuehwMW605p5NMmvBbKYx5tuqnV3Mp7jSWXM,13904
|
186
189
|
flwr/simulation/ray_transport/__init__.py,sha256=FsaAnzC4cw4DqoouBCix6496k29jACkfeIam55BvW9g,734
|
187
190
|
flwr/simulation/ray_transport/ray_actor.py,sha256=zRETW_xuCAOLRFaYnQ-q3IBSz0LIv_0RifGuhgWaYOg,19872
|
188
|
-
flwr/simulation/ray_transport/ray_client_proxy.py,sha256=
|
191
|
+
flwr/simulation/ray_transport/ray_client_proxy.py,sha256=L49gtigsf4vTQgRiqzOgcPEuS_l-EuTj29Ohw6ekbSI,6721
|
189
192
|
flwr/simulation/ray_transport/utils.py,sha256=TYdtfg1P9VfTdLMOJlifInGpxWHYs9UfUqIv2wfkRLA,2392
|
190
193
|
flwr/simulation/run_simulation.py,sha256=1JMP5nYFeGrZzcpw_Q0aDvyla2AvRz5aFJw1i1InSvs,15681
|
191
|
-
flwr_nightly-1.8.0.
|
192
|
-
flwr_nightly-1.8.0.
|
193
|
-
flwr_nightly-1.8.0.
|
194
|
-
flwr_nightly-1.8.0.
|
195
|
-
flwr_nightly-1.8.0.
|
194
|
+
flwr_nightly-1.8.0.dev20240306.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
195
|
+
flwr_nightly-1.8.0.dev20240306.dist-info/METADATA,sha256=wo7hfHBsAblM1fzIAQtlRqKBJoJHOoawPiKcnJSVwZA,15257
|
196
|
+
flwr_nightly-1.8.0.dev20240306.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
197
|
+
flwr_nightly-1.8.0.dev20240306.dist-info/entry_points.txt,sha256=utu2wybGyYJSTtsB2ktY_gmy-XtMFo9EFZdishX0zR4,320
|
198
|
+
flwr_nightly-1.8.0.dev20240306.dist-info/RECORD,,
|
{flwr_nightly-1.8.0.dev20240305.dist-info → flwr_nightly-1.8.0.dev20240306.dist-info}/LICENSE
RENAMED
File without changes
|
File without changes
|
File without changes
|