flwr-nightly 1.8.0.dev20240305__py3-none-any.whl → 1.8.0.dev20240306__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/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
|