flwr-nightly 1.8.0.dev20240220__py3-none-any.whl → 1.8.0.dev20240222__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
flwr/client/app.py CHANGED
@@ -506,9 +506,7 @@ def start_numpy_client(
506
506
  )
507
507
 
508
508
 
509
- def _init_connection(
510
- transport: Optional[str], server_address: str
511
- ) -> Tuple[
509
+ def _init_connection(transport: Optional[str], server_address: str) -> Tuple[
512
510
  Callable[
513
511
  [str, bool, int, Union[bytes, str, None]],
514
512
  ContextManager[
flwr/common/__init__.py CHANGED
@@ -31,6 +31,7 @@ from .record import ConfigsRecord as ConfigsRecord
31
31
  from .record import MetricsRecord as MetricsRecord
32
32
  from .record import ParametersRecord as ParametersRecord
33
33
  from .record import RecordSet as RecordSet
34
+ from .record import array_from_numpy as array_from_numpy
34
35
  from .telemetry import EventType as EventType
35
36
  from .telemetry import event as event
36
37
  from .typing import ClientMessage as ClientMessage
@@ -58,6 +59,7 @@ from .typing import Status as Status
58
59
 
59
60
  __all__ = [
60
61
  "Array",
62
+ "array_from_numpy",
61
63
  "bytes_to_ndarray",
62
64
  "ClientMessage",
63
65
  "Code",
flwr/common/constant.py CHANGED
@@ -15,6 +15,8 @@
15
15
  """Flower constants."""
16
16
 
17
17
 
18
+ from __future__ import annotations
19
+
18
20
  MISSING_EXTRA_REST = """
19
21
  Extra dependencies required for using the REST-based Fleet API are missing.
20
22
 
@@ -26,13 +28,25 @@ To use the REST API, install `flwr` with the `rest` extra:
26
28
  TRANSPORT_TYPE_GRPC_BIDI = "grpc-bidi"
27
29
  TRANSPORT_TYPE_GRPC_RERE = "grpc-rere"
28
30
  TRANSPORT_TYPE_REST = "rest"
31
+ TRANSPORT_TYPE_VCE = "vce"
29
32
  TRANSPORT_TYPES = [
30
33
  TRANSPORT_TYPE_GRPC_BIDI,
31
34
  TRANSPORT_TYPE_GRPC_RERE,
32
35
  TRANSPORT_TYPE_REST,
36
+ TRANSPORT_TYPE_VCE,
33
37
  ]
34
38
 
35
39
  MESSAGE_TYPE_GET_PROPERTIES = "get_properties"
36
40
  MESSAGE_TYPE_GET_PARAMETERS = "get_parameters"
37
41
  MESSAGE_TYPE_FIT = "fit"
38
42
  MESSAGE_TYPE_EVALUATE = "evaluate"
43
+
44
+
45
+ class SType:
46
+ """Serialisation type."""
47
+
48
+ NUMPY = "numpy.ndarray"
49
+
50
+ def __new__(cls) -> SType:
51
+ """Prevent instantiation."""
52
+ raise TypeError(f"{cls.__name__} cannot be instantiated.")
@@ -15,12 +15,14 @@
15
15
  """Record APIs."""
16
16
 
17
17
  from .configsrecord import ConfigsRecord
18
+ from .conversion_utils import array_from_numpy
18
19
  from .metricsrecord import MetricsRecord
19
20
  from .parametersrecord import Array, ParametersRecord
20
21
  from .recordset import RecordSet
21
22
 
22
23
  __all__ = [
23
24
  "Array",
25
+ "array_from_numpy",
24
26
  "ConfigsRecord",
25
27
  "MetricsRecord",
26
28
  "ParametersRecord",
@@ -0,0 +1,40 @@
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
+ """Conversion utility functions for Records."""
16
+
17
+
18
+ from io import BytesIO
19
+
20
+ import numpy as np
21
+
22
+ from ..constant import SType
23
+ from ..typing import NDArray
24
+ from .parametersrecord import Array
25
+
26
+
27
+ def array_from_numpy(ndarray: NDArray) -> Array:
28
+ """Create Array from NumPy ndarray."""
29
+ buffer = BytesIO()
30
+ # WARNING: NEVER set allow_pickle to true.
31
+ # Reason: loading pickled data can execute arbitrary code
32
+ # Source: https://numpy.org/doc/stable/reference/generated/numpy.save.html
33
+ np.save(buffer, ndarray, allow_pickle=False)
34
+ data = buffer.getvalue()
35
+ return Array(
36
+ dtype=str(ndarray.dtype),
37
+ shape=list(ndarray.shape),
38
+ stype=SType.NUMPY,
39
+ data=data,
40
+ )
@@ -14,10 +14,14 @@
14
14
  # ==============================================================================
15
15
  """ParametersRecord and Array."""
16
16
 
17
-
18
17
  from dataclasses import dataclass
19
- from typing import List, Optional, OrderedDict
18
+ from io import BytesIO
19
+ from typing import List, Optional, OrderedDict, cast
20
+
21
+ import numpy as np
20
22
 
23
+ from ..constant import SType
24
+ from ..typing import NDArray
21
25
  from .typeddict import TypedDict
22
26
 
23
27
 
@@ -51,6 +55,19 @@ class Array:
51
55
  stype: str
52
56
  data: bytes
53
57
 
58
+ def numpy(self) -> NDArray:
59
+ """Return the array as a NumPy array."""
60
+ if self.stype != SType.NUMPY:
61
+ raise TypeError(
62
+ f"Unsupported serialization type for numpy conversion: '{self.stype}'"
63
+ )
64
+ bytes_io = BytesIO(self.data)
65
+ # WARNING: NEVER set allow_pickle to true.
66
+ # Reason: loading pickled data can execute arbitrary code
67
+ # Source: https://numpy.org/doc/stable/reference/generated/numpy.load.html
68
+ ndarray_deserialized = np.load(bytes_io, allow_pickle=False)
69
+ return cast(NDArray, ndarray_deserialized)
70
+
54
71
 
55
72
  def _check_key(key: str) -> None:
56
73
  """Check if key is of expected type."""
flwr/common/version.py CHANGED
@@ -1,6 +1,5 @@
1
1
  """Flower package version helper."""
2
2
 
3
-
4
3
  import importlib.metadata as importlib_metadata
5
4
  from typing import Tuple
6
5
 
flwr/server/app.py CHANGED
@@ -34,6 +34,7 @@ from flwr.common.constant import (
34
34
  MISSING_EXTRA_REST,
35
35
  TRANSPORT_TYPE_GRPC_RERE,
36
36
  TRANSPORT_TYPE_REST,
37
+ TRANSPORT_TYPE_VCE,
37
38
  )
38
39
  from flwr.common.logger import log
39
40
  from flwr.proto.driver_pb2_grpc import ( # pylint: disable=E0611
@@ -43,17 +44,18 @@ from flwr.proto.fleet_pb2_grpc import ( # pylint: disable=E0611
43
44
  add_FleetServicer_to_server,
44
45
  )
45
46
 
46
- from .client_manager import ClientManager, SimpleClientManager
47
+ from .client_manager import ClientManager
47
48
  from .history import History
48
- from .server import Server
49
+ from .server import Server, init_defaults, run_fl
49
50
  from .server_config import ServerConfig
50
- from .strategy import FedAvg, Strategy
51
+ from .strategy import Strategy
51
52
  from .superlink.driver.driver_servicer import DriverServicer
52
53
  from .superlink.fleet.grpc_bidi.grpc_server import (
53
54
  generic_create_grpc_server,
54
55
  start_grpc_server,
55
56
  )
56
57
  from .superlink.fleet.grpc_rere.fleet_servicer import FleetServicer
58
+ from .superlink.fleet.vce import start_vce
57
59
  from .superlink.state import StateFactory
58
60
 
59
61
  ADDRESS_DRIVER_API = "0.0.0.0:9091"
@@ -183,47 +185,6 @@ def start_server( # pylint: disable=too-many-arguments,too-many-locals
183
185
  return hist
184
186
 
185
187
 
186
- def init_defaults(
187
- server: Optional[Server],
188
- config: Optional[ServerConfig],
189
- strategy: Optional[Strategy],
190
- client_manager: Optional[ClientManager],
191
- ) -> Tuple[Server, ServerConfig]:
192
- """Create server instance if none was given."""
193
- if server is None:
194
- if client_manager is None:
195
- client_manager = SimpleClientManager()
196
- if strategy is None:
197
- strategy = FedAvg()
198
- server = Server(client_manager=client_manager, strategy=strategy)
199
- elif strategy is not None:
200
- log(WARN, "Both server and strategy were provided, ignoring strategy")
201
-
202
- # Set default config values
203
- if config is None:
204
- config = ServerConfig()
205
-
206
- return server, config
207
-
208
-
209
- def run_fl(
210
- server: Server,
211
- config: ServerConfig,
212
- ) -> History:
213
- """Train a model on the given server and return the History object."""
214
- hist = server.fit(num_rounds=config.num_rounds, timeout=config.round_timeout)
215
- log(INFO, "app_fit: losses_distributed %s", str(hist.losses_distributed))
216
- log(INFO, "app_fit: metrics_distributed_fit %s", str(hist.metrics_distributed_fit))
217
- log(INFO, "app_fit: metrics_distributed %s", str(hist.metrics_distributed))
218
- log(INFO, "app_fit: losses_centralized %s", str(hist.losses_centralized))
219
- log(INFO, "app_fit: metrics_centralized %s", str(hist.metrics_centralized))
220
-
221
- # Graceful shutdown
222
- server.disconnect_all_clients(timeout=config.round_timeout)
223
-
224
- return hist
225
-
226
-
227
188
  def run_driver_api() -> None:
228
189
  """Run Flower server (Driver API)."""
229
190
  log(INFO, "Starting Flower server (Driver API)")
@@ -401,6 +362,15 @@ def run_superlink() -> None:
401
362
  certificates=certificates,
402
363
  )
403
364
  grpc_servers.append(fleet_server)
365
+ elif args.fleet_api_type == TRANSPORT_TYPE_VCE:
366
+ _run_fleet_api_vce(
367
+ num_supernodes=args.num_supernodes,
368
+ client_app_module_name=args.client_app,
369
+ backend_name=args.backend,
370
+ backend_config_json_stream=args.backend_config,
371
+ working_dir=args.dir,
372
+ state_factory=state_factory,
373
+ )
404
374
  else:
405
375
  raise ValueError(f"Unknown fleet_api_type: {args.fleet_api_type}")
406
376
 
@@ -537,6 +507,27 @@ def _run_fleet_api_grpc_rere(
537
507
  return fleet_grpc_server
538
508
 
539
509
 
510
+ # pylint: disable=too-many-arguments
511
+ def _run_fleet_api_vce(
512
+ num_supernodes: int,
513
+ client_app_module_name: str,
514
+ backend_name: str,
515
+ backend_config_json_stream: str,
516
+ working_dir: str,
517
+ state_factory: StateFactory,
518
+ ) -> None:
519
+ log(INFO, "Flower VCE: Starting Fleet API (VirtualClientEngine)")
520
+
521
+ start_vce(
522
+ num_supernodes=num_supernodes,
523
+ client_app_module_name=client_app_module_name,
524
+ backend_name=backend_name,
525
+ backend_config_json_stream=backend_config_json_stream,
526
+ state_factory=state_factory,
527
+ working_dir=working_dir,
528
+ )
529
+
530
+
540
531
  # pylint: disable=import-outside-toplevel,too-many-arguments
541
532
  def _run_fleet_api_rest(
542
533
  host: str,
@@ -714,6 +705,14 @@ def _add_args_fleet_api(parser: argparse.ArgumentParser) -> None:
714
705
  help="Start a Fleet API server (REST, experimental)",
715
706
  )
716
707
 
708
+ ex_group.add_argument(
709
+ "--vce",
710
+ action="store_const",
711
+ dest="fleet_api_type",
712
+ const=TRANSPORT_TYPE_VCE,
713
+ help="Start a Fleet API server (VirtualClientEngine)",
714
+ )
715
+
717
716
  # Fleet API gRPC-rere options
718
717
  grpc_rere_group = parser.add_argument_group(
719
718
  "Fleet API (gRPC-rere) server options", ""
@@ -749,3 +748,36 @@ def _add_args_fleet_api(parser: argparse.ArgumentParser) -> None:
749
748
  type=int,
750
749
  default=1,
751
750
  )
751
+
752
+ # Fleet API VCE options
753
+ vce_group = parser.add_argument_group("Fleet API (VCE) server options", "")
754
+ vce_group.add_argument(
755
+ "--client-app",
756
+ help="For example: `client:app` or `project.package.module:wrapper.app`.",
757
+ )
758
+ vce_group.add_argument(
759
+ "--num-supernodes",
760
+ type=int,
761
+ help="Number of simulated SuperNodes.",
762
+ )
763
+ vce_group.add_argument(
764
+ "--backend",
765
+ default="ray",
766
+ type=str,
767
+ help="Simulation backend that executes the ClientApp.",
768
+ )
769
+ vce_group.add_argument(
770
+ "--backend-config",
771
+ type=str,
772
+ default='{"client_resources": {"num_cpus":1, "num_gpus":0.0}, "tensorflow": 0}',
773
+ help='A JSON formatted stream, e.g \'{"<keyA>":<value>, "<keyB>":<value>}\' to '
774
+ "configure a backend. Values supported in <value> are those included by "
775
+ "`flwr.common.typing.ConfigsRecordValues`. ",
776
+ )
777
+ parser.add_argument(
778
+ "--dir",
779
+ default="",
780
+ help="Add specified directory to the PYTHONPATH and load"
781
+ "ClientApp from there."
782
+ " Default: current working directory.",
783
+ )
flwr/server/compat/app.py CHANGED
@@ -26,10 +26,9 @@ from flwr.common import EventType, event
26
26
  from flwr.common.address import parse_address
27
27
  from flwr.common.logger import log, warn_deprecated_feature
28
28
  from flwr.proto import driver_pb2 # pylint: disable=E0611
29
- from flwr.server.app import init_defaults, run_fl
30
29
  from flwr.server.client_manager import ClientManager
31
30
  from flwr.server.history import History
32
- from flwr.server.server import Server
31
+ from flwr.server.server import Server, init_defaults, run_fl
33
32
  from flwr.server.server_config import ServerConfig
34
33
  from flwr.server.strategy import Strategy
35
34
 
flwr/server/server.py CHANGED
@@ -17,7 +17,7 @@
17
17
 
18
18
  import concurrent.futures
19
19
  import timeit
20
- from logging import DEBUG, INFO
20
+ from logging import DEBUG, INFO, WARN
21
21
  from typing import Dict, List, Optional, Tuple, Union
22
22
 
23
23
  from flwr.common import (
@@ -33,11 +33,13 @@ from flwr.common import (
33
33
  )
34
34
  from flwr.common.logger import log
35
35
  from flwr.common.typing import GetParametersIns
36
- from flwr.server.client_manager import ClientManager
36
+ from flwr.server.client_manager import ClientManager, SimpleClientManager
37
37
  from flwr.server.client_proxy import ClientProxy
38
38
  from flwr.server.history import History
39
39
  from flwr.server.strategy import FedAvg, Strategy
40
40
 
41
+ from .server_config import ServerConfig
42
+
41
43
  FitResultsAndFailures = Tuple[
42
44
  List[Tuple[ClientProxy, FitRes]],
43
45
  List[Union[Tuple[ClientProxy, FitRes], BaseException]],
@@ -441,3 +443,44 @@ def _handle_finished_future_after_evaluate(
441
443
 
442
444
  # Not successful, client returned a result where the status code is not OK
443
445
  failures.append(result)
446
+
447
+
448
+ def init_defaults(
449
+ server: Optional[Server],
450
+ config: Optional[ServerConfig],
451
+ strategy: Optional[Strategy],
452
+ client_manager: Optional[ClientManager],
453
+ ) -> Tuple[Server, ServerConfig]:
454
+ """Create server instance if none was given."""
455
+ if server is None:
456
+ if client_manager is None:
457
+ client_manager = SimpleClientManager()
458
+ if strategy is None:
459
+ strategy = FedAvg()
460
+ server = Server(client_manager=client_manager, strategy=strategy)
461
+ elif strategy is not None:
462
+ log(WARN, "Both server and strategy were provided, ignoring strategy")
463
+
464
+ # Set default config values
465
+ if config is None:
466
+ config = ServerConfig()
467
+
468
+ return server, config
469
+
470
+
471
+ def run_fl(
472
+ server: Server,
473
+ config: ServerConfig,
474
+ ) -> History:
475
+ """Train a model on the given server and return the History object."""
476
+ hist = server.fit(num_rounds=config.num_rounds, timeout=config.round_timeout)
477
+ log(INFO, "app_fit: losses_distributed %s", str(hist.losses_distributed))
478
+ log(INFO, "app_fit: metrics_distributed_fit %s", str(hist.metrics_distributed_fit))
479
+ log(INFO, "app_fit: metrics_distributed %s", str(hist.metrics_distributed))
480
+ log(INFO, "app_fit: losses_centralized %s", str(hist.losses_centralized))
481
+ log(INFO, "app_fit: metrics_centralized %s", str(hist.metrics_centralized))
482
+
483
+ # Graceful shutdown
484
+ server.disconnect_all_clients(timeout=config.round_timeout)
485
+
486
+ return hist
@@ -104,9 +104,9 @@ class DPFedAvgFixed(Strategy):
104
104
  """
105
105
  additional_config = {"dpfedavg_clip_norm": self.clip_norm}
106
106
  if not self.server_side_noising:
107
- additional_config[
108
- "dpfedavg_noise_stddev"
109
- ] = self._calc_client_noise_stddev()
107
+ additional_config["dpfedavg_noise_stddev"] = (
108
+ self._calc_client_noise_stddev()
109
+ )
110
110
 
111
111
  client_instructions = self.strategy.configure_fit(
112
112
  server_round, parameters, client_manager
@@ -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
+ """Fleet VirtualClientEngine side."""
16
+
17
+ from .vce_api import start_vce
18
+
19
+ __all__ = [
20
+ "start_vce",
21
+ ]
@@ -0,0 +1,71 @@
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
+ """Fleet VirtualClientEngine API."""
16
+
17
+ import json
18
+ from logging import INFO
19
+ from typing import Dict
20
+
21
+ from flwr.client.clientapp import ClientApp, load_client_app
22
+ from flwr.client.node_state import NodeState
23
+ from flwr.common.logger import log
24
+ from flwr.server.superlink.state import StateFactory
25
+
26
+ NodeToPartitionMapping = Dict[int, int]
27
+
28
+
29
+ def _register_nodes(
30
+ num_nodes: int, state_factory: StateFactory
31
+ ) -> NodeToPartitionMapping:
32
+ """Register nodes with the StateFactory and create node-id:partition-id mapping."""
33
+ nodes_mapping: NodeToPartitionMapping = {}
34
+ state = state_factory.state()
35
+ for i in range(num_nodes):
36
+ node_id = state.create_node()
37
+ nodes_mapping[node_id] = i
38
+ log(INFO, "Registered %i nodes", len(nodes_mapping))
39
+ return nodes_mapping
40
+
41
+
42
+ # pylint: disable=too-many-arguments,unused-argument
43
+ def start_vce(
44
+ num_supernodes: int,
45
+ client_app_module_name: str,
46
+ backend_name: str,
47
+ backend_config_json_stream: str,
48
+ state_factory: StateFactory,
49
+ working_dir: str,
50
+ ) -> None:
51
+ """Start Fleet API with the VirtualClientEngine (VCE)."""
52
+ # Register SuperNodes
53
+ nodes_mapping = _register_nodes(
54
+ num_nodes=num_supernodes, state_factory=state_factory
55
+ )
56
+
57
+ # Construct mapping of NodeStates
58
+ node_states: Dict[int, NodeState] = {}
59
+ for node_id in nodes_mapping:
60
+ node_states[node_id] = NodeState()
61
+
62
+ # Load backend config
63
+ _ = json.loads(backend_config_json_stream)
64
+
65
+ log(INFO, "client_app_str = %s", client_app_module_name)
66
+
67
+ def _load() -> ClientApp:
68
+ app: ClientApp = load_client_app(client_app_module_name)
69
+ return app
70
+
71
+ # start backend
flwr/simulation/app.py CHANGED
@@ -28,10 +28,9 @@ from ray.util.scheduling_strategies import NodeAffinitySchedulingStrategy
28
28
  from flwr.client import ClientFn
29
29
  from flwr.common import EventType, event
30
30
  from flwr.common.logger import log
31
- from flwr.server import Server
32
- from flwr.server.app import init_defaults, run_fl
33
31
  from flwr.server.client_manager import ClientManager
34
32
  from flwr.server.history import History
33
+ from flwr.server.server import Server, init_defaults, run_fl
35
34
  from flwr.server.server_config import ServerConfig
36
35
  from flwr.server.strategy import Strategy
37
36
  from flwr.simulation.ray_transport.ray_actor import (
@@ -220,7 +219,7 @@ def start_simulation(
220
219
  log(
221
220
  INFO,
222
221
  "Optimize your simulation with Flower VCE: "
223
- "https://flower.dev/docs/framework/how-to-run-simulations.html",
222
+ "https://flower.ai/docs/framework/how-to-run-simulations.html",
224
223
  )
225
224
 
226
225
  # Log the resources that a single client will be able to use
@@ -338,7 +337,7 @@ def start_simulation(
338
337
  "disconnected. The head node might still be alive but cannot accommodate "
339
338
  "any actor with resources: %s."
340
339
  "\nTake a look at the Flower simulation examples for guidance "
341
- "<https://flower.dev/docs/framework/how-to-run-simulations.html>.",
340
+ "<https://flower.ai/docs/framework/how-to-run-simulations.html>.",
342
341
  client_resources,
343
342
  client_resources,
344
343
  )
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flwr-nightly
3
- Version: 1.8.0.dev20240220
3
+ Version: 1.8.0.dev20240222
4
4
  Summary: Flower: A Friendly Federated Learning Framework
5
- Home-page: https://flower.dev
5
+ Home-page: https://flower.ai
6
6
  License: Apache-2.0
7
7
  Keywords: flower,fl,federated learning,federated analytics,federated evaluation,machine learning
8
8
  Author: The Flower Authors
9
- Author-email: hello@flower.dev
9
+ Author-email: hello@flower.ai
10
10
  Requires-Python: >=3.8,<4.0
11
11
  Classifier: Development Status :: 5 - Production/Stable
12
12
  Classifier: Intended Audience :: Developers
@@ -44,7 +44,7 @@ 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
45
  Requires-Dist: typer[all] (>=0.9.0,<0.10.0)
46
46
  Requires-Dist: uvicorn[standard] (>=0.23.0,<0.24.0) ; extra == "rest"
47
- Project-URL: Documentation, https://flower.dev
47
+ Project-URL: Documentation, https://flower.ai
48
48
  Project-URL: Repository, https://github.com/adap/flower
49
49
  Description-Content-Type: text/markdown
50
50
 
@@ -199,6 +199,7 @@ Other [examples](https://github.com/adap/flower/tree/main/examples):
199
199
  - 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))
200
200
  - [Comprehensive Flower+XGBoost](https://github.com/adap/flower/tree/main/examples/xgboost-comprehensive)
201
201
  - [Flower through Docker Compose and with Grafana dashboard](https://github.com/adap/flower/tree/main/examples/flower-via-docker-compose)
202
+ - [Flower with KaplanMeierFitter from the lifelines library](https://github.com/adap/flower/tree/main/examples/federated-kaplna-meier-fitter)
202
203
 
203
204
  ## Community
204
205
 
@@ -18,7 +18,7 @@ flwr/cli/new/templates/app/requirements.pytorch.txt.tpl,sha256=9Z70jsiCPdsbuorhi
18
18
  flwr/cli/new/templates/app/requirements.tensorflow.txt.tpl,sha256=WTbIgK5G_iG0W-xtvQLCZMxL_Og26rFXial2TkYH5dw,211
19
19
  flwr/cli/utils.py,sha256=9cCEIt8QmJXz85JNmPk1IHPd7p8E3KDn6h5CfF0nDL4,1926
20
20
  flwr/client/__init__.py,sha256=ypNGqhSDxEPX_6XwcQyVseBf8oS_Zvs_JkrLbVIeKxw,1186
21
- flwr/client/app.py,sha256=UQR3eQB5U3krn5S4jednr-agfrmdfA7Yk2o4rtmV8LQ,19989
21
+ flwr/client/app.py,sha256=BxQGhdhFiw9JrKu-TcgmyshN02K9QpgWPxFVEcQ4Mb8,19983
22
22
  flwr/client/client.py,sha256=Vp9UkOkoHdNfn6iMYZsj_5m_GICiFfUlKEVaLad-YhM,8183
23
23
  flwr/client/clientapp.py,sha256=jrDgJBswP2hD1YdGgQoI3GU_NkliYWVU8glBJLOVzQY,4205
24
24
  flwr/client/dpfedavg_numpy_client.py,sha256=9Tnig4iml2J88HBKNahegjXjbfvIQyBtaIQaqjbeqsA,7435
@@ -39,9 +39,9 @@ flwr/client/numpy_client.py,sha256=u76GWAdHmJM88Agm2EgLQSvO8Jnk225mJTk-_TmPjFE,1
39
39
  flwr/client/rest_client/__init__.py,sha256=ThwOnkMdzxo_UuyTI47Q7y9oSpuTgNT2OuFvJCfuDiw,735
40
40
  flwr/client/rest_client/connection.py,sha256=363X5FZPg2H8f9dZk_IhUrVK-DGiDHfIodJNat-W8XE,11903
41
41
  flwr/client/typing.py,sha256=c9EvjlEjasxn1Wqx6bGl6Xg6vM1gMFfmXht-E2i5J-k,1006
42
- flwr/common/__init__.py,sha256=OL0_IdXtcmgOsITK81znjUqMlzEhV98HDSmM4Hg0YIE,3385
42
+ flwr/common/__init__.py,sha256=Pm7NIXPNUxQGe8mMv9L7xFi5VohYnJEpgR-RP7gMDQQ,3466
43
43
  flwr/common/address.py,sha256=iTAN9jtmIGMrWFnx9XZQl45ZEtQJVZZLYPRBSNVARGI,1882
44
- flwr/common/constant.py,sha256=-ffTmVtI4mqb5vu6Cw81_7aGMzoTeIl2qvLnyMzQTHw,1275
44
+ flwr/common/constant.py,sha256=jVUVKXo1cFb2HpRYqV70WKMG4RqCVrq7H6KC7zXs23Y,1572
45
45
  flwr/common/context.py,sha256=ounF-mWPPtXGwtae3sg5EhF58ScviOa3MVqxRpGVu-8,1313
46
46
  flwr/common/date.py,sha256=UWhBZj49yX9LD4BmatS_ZFZu_-kweGh0KQJ1djyWWH4,891
47
47
  flwr/common/differential_privacy.py,sha256=pVSKRhciVNtdBlhoz1H0--8N5PMLjdO_bA1PLGq4WZ8,2969
@@ -51,10 +51,11 @@ flwr/common/grpc.py,sha256=qVLB0d6bCuaBRW5YB0vEZXsR7Bo3R2lh4ONiCocqwRI,2270
51
51
  flwr/common/logger.py,sha256=qX_gqEyrmGOH0x_r8uQ1Vskz4fGvEij9asdo4DUOPY8,4135
52
52
  flwr/common/message.py,sha256=tXkOAIYnPN5cW2OVggVTAUSaBxEDqoFGpST7uPpIAho,6198
53
53
  flwr/common/parameter.py,sha256=-bFAUayToYDF50FZGrBC1hQYJCQDtB2bbr3ZuVLMtdE,2095
54
- flwr/common/record/__init__.py,sha256=NYVYER-n3JTd_sPuttZtw_hrBOyeeMUDgxaF1Yx32Oc,983
54
+ flwr/common/record/__init__.py,sha256=33OaDW2bvaW952DFHH1amHclv4AuDZu385jXjHhXoog,1054
55
55
  flwr/common/record/configsrecord.py,sha256=qL-hQ6ZFOOWJYCUHeFiao2vcO5rnk585Ns5Yxfb1sp4,3378
56
+ flwr/common/record/conversion_utils.py,sha256=n3I3SI2P6hUjyxbWNc0QAch-SEhfMK6Hm-UUaplAlUc,1393
56
57
  flwr/common/record/metricsrecord.py,sha256=iEihUVNqwyZtbim7FfqJ7ksEbPef6cqTZ1w4-_C5afw,3360
57
- flwr/common/record/parametersrecord.py,sha256=WMQ7ZViS4E3DR0ynin1AceYx0Ncla4LccLey2QLj6jE,3617
58
+ flwr/common/record/parametersrecord.py,sha256=ii8Ol5W3dk_5YUWSFbbLC5KWep2eqlSWfCsgSM4Pedg,4331
58
59
  flwr/common/record/recordset.py,sha256=OeRcBMGqx9vutWRz1xkujBPHlVpU58R1EcFRHEQrePo,2351
59
60
  flwr/common/record/typeddict.py,sha256=2NW8JF27p1uNWaqDbJ7bMkItA5x4ygYT8aHrf8NaqnE,3879
60
61
  flwr/common/recordset_compat.py,sha256=MXabdTaE9ItZ05oid6YLWtdbvgGHbTXsnMoTSJYYpcY,13842
@@ -70,7 +71,7 @@ flwr/common/secure_aggregation/secaggplus_utils.py,sha256=PleDyDu7jHNAfbRoEaoQiO
70
71
  flwr/common/serde.py,sha256=0N2SG6T71rVIGPiUIBIZfyWyNGQTp-MjDpy9sDUvrXc,20622
71
72
  flwr/common/telemetry.py,sha256=JkFB6WBOskqAJfzSM-l6tQfRiSi2oiysClfg0-5T7NY,7782
72
73
  flwr/common/typing.py,sha256=3Wu6Ol1Ja6Gb0WdlcXVEn1EHYJbc4oRRJA81vEegxBo,4382
73
- flwr/common/version.py,sha256=A0MKvyKPrV8wLg0YCAODTqM71v26NEH36c6JYtfgg0o,667
74
+ flwr/common/version.py,sha256=_RDSMGZPEuGKYViZuXPotDtXMvh4iyDH9XOCO4qtPO8,666
74
75
  flwr/proto/__init__.py,sha256=hbY7JYakwZwCkYgCNlmHdc8rtvfoJbAZLalMdc--CGc,683
75
76
  flwr/proto/driver_pb2.py,sha256=JHIdjNPTgp6YHD-_lz5ZZFB0VIOR3_GmcaOTN4jndc4,3115
76
77
  flwr/proto/driver_pb2.pyi,sha256=xwl2AqIWn0SwAlg-x5RUQeqr6DC48eywnqmD7gbaaFs,4670
@@ -98,11 +99,11 @@ flwr/proto/transport_pb2_grpc.py,sha256=vLN3EHtx2aEEMCO4f1Upu-l27BPzd3-5pV-u8wPc
98
99
  flwr/proto/transport_pb2_grpc.pyi,sha256=AGXf8RiIiW2J5IKMlm_3qT3AzcDa4F3P5IqUjve_esA,766
99
100
  flwr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
100
101
  flwr/server/__init__.py,sha256=_Wv3UkZzSXzbKWXyl2yY8tU6oqf_XqIruggpHjnmikE,1662
101
- flwr/server/app.py,sha256=ymCT16agP_R4MpWnFDP9BHW940fELzQ-zVc5Q5wHDcI,25409
102
+ flwr/server/app.py,sha256=0-p--_yF8rHTPxjrwZnBkEZgEeyAAqJ-i18vdCHTq5g,26328
102
103
  flwr/server/client_manager.py,sha256=T8UDSRJBVD3fyIDI7NTAA-NA7GPrMNNgH2OAF54RRxE,6127
103
104
  flwr/server/client_proxy.py,sha256=8ScGDvP3jHbl8DV3hyFID5N5VEVlXn8ZTQXtkdOfssI,2234
104
105
  flwr/server/compat/__init__.py,sha256=KNvRFANbIc8LFRKHsBVfxcbOSekEImWgNq_gapCkbic,812
105
- flwr/server/compat/app.py,sha256=vhHN5hijhYjfOQdynDB0MloW4zsVzx9roysk2JQtEk4,7886
106
+ flwr/server/compat/app.py,sha256=lfPCbY4WVMvKdscBxraikBn97SEuSwR_dUDoTHTMe7w,7859
106
107
  flwr/server/compat/driver_client_proxy.py,sha256=S3lI6Wi7fpkbg6GEi6TSzB6RHsrIdg1w44sLe-94UUk,6148
107
108
  flwr/server/criterion.py,sha256=ypbAexbztzGUxNen9RCHF91QeqiEQix4t4Ih3E-42MM,1061
108
109
  flwr/server/driver/__init__.py,sha256=yYyVX1FcDiDFM6rw0-DSZpuRy0EoWRfG9puwlQUswFA,820
@@ -110,7 +111,7 @@ flwr/server/driver/driver.py,sha256=DApIRFeEzReZpdAsbFQ68haSUONMstblyOt6qcseMNc,
110
111
  flwr/server/driver/grpc_driver.py,sha256=Ekcxx4Miqume02fiBjBRJhItaOFNpn120WT3uRIPWIc,4585
111
112
  flwr/server/history.py,sha256=W7PHCFX7dLXrdnaVfl5V4tuzmtxh6zArkWYxVXvTZ1c,4904
112
113
  flwr/server/run_serverapp.py,sha256=tYNbz11xMvkbcMty6u5nkLHmZhwIjSO78CfW-Aas5R8,4488
113
- flwr/server/server.py,sha256=skrNgQp9vlCVHruovlaB0Rh1W7xdH7KqEfVCMZGpK7c,15965
114
+ flwr/server/server.py,sha256=kUIqgLIXnWcSrhEhXXkaZPRooYhTGGX-RDCYzG9J76g,17495
114
115
  flwr/server/server_app.py,sha256=avNQ7AMMKsn09ly81C3UBgOfHhM_R29l4MrzlalGoj8,5892
115
116
  flwr/server/server_config.py,sha256=yOHpkdyuhOm--Gy_4Vofvu6jCDxhyECEDpIy02beuCg,1018
116
117
  flwr/server/strategy/__init__.py,sha256=qYOURtpO5DtaDXzvo0wd1lv0cP3wGQxbhqn3s5i8--k,2220
@@ -118,7 +119,7 @@ flwr/server/strategy/aggregate.py,sha256=QyRIJtI5gnuY1NbgrcrOvkHxGIxBvApq7d9Y4xl
118
119
  flwr/server/strategy/bulyan.py,sha256=8GsSVJzRSoSWE2zQUKqC3Z795grdN9xpmc3MSGGXnzM,6532
119
120
  flwr/server/strategy/dp_fixed_clipping.py,sha256=185P6F17uOtRByDaQSCpKj6jCGgP4271xhoMLUl2oR8,6671
120
121
  flwr/server/strategy/dpfedavg_adaptive.py,sha256=hLJkPQJl1bHjwrBNg3PSRFKf3no0hg5EHiFaWhHlWqw,4877
121
- flwr/server/strategy/dpfedavg_fixed.py,sha256=mV_UimlGigUJjc2a9dmUig5EuVZ4yGIb9pkq31bKG1A,7217
122
+ flwr/server/strategy/dpfedavg_fixed.py,sha256=G0yYxrPoM-MHQ889DYN3OeNiEeU0yQrjgAzcq0G653w,7219
122
123
  flwr/server/strategy/fault_tolerant_fedavg.py,sha256=veGcehB6rXT_MihNDrD1v5JY-TxJi7fybdDl-OZooDQ,5900
123
124
  flwr/server/strategy/fedadagrad.py,sha256=9yoVdZOFTjQ7DpaVrYLH9ca88WgJVWepld6UXybGQMY,6505
124
125
  flwr/server/strategy/fedadam.py,sha256=Zvqo6oChwB2aDGHeLXHNE74nHGwkFAWODLZ8f6Dtq1g,6763
@@ -151,6 +152,8 @@ flwr/server/superlink/fleet/message_handler/__init__.py,sha256=hEY0l61ojH8Iz30_K
151
152
  flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=iUBTJ2fzVL0XB8vfaEzCNJ6okeuOWrK6LJe__ElP9x8,2833
152
153
  flwr/server/superlink/fleet/rest_rere/__init__.py,sha256=VKDvDq5H8koOUztpmQacVzGJXPLEEkL1Vmolxt3mvnY,735
153
154
  flwr/server/superlink/fleet/rest_rere/rest_api.py,sha256=7JCs7NW4Qq8W5QhXxqsQNFiCLlRY-b_iD420vH1Mu-U,5906
155
+ flwr/server/superlink/fleet/vce/__init__.py,sha256=bogHbcWSXkD7wZkqUXiLRKQTJUs7jtr5uwaGlmoA-Yc,785
156
+ flwr/server/superlink/fleet/vce/vce_api.py,sha256=okSRawmpRD5FntvBYFgAv55dQtXJbZLzHr2XxEqGArM,2351
154
157
  flwr/server/superlink/state/__init__.py,sha256=ij-7Ms-hyordQdRmGQxY1-nVa4OhixJ0jr7_YDkys0s,1003
155
158
  flwr/server/superlink/state/in_memory_state.py,sha256=viGGGyg7LwwxKfCnndV6Tp9poVeZTrbN9z0tt-4qrqI,7903
156
159
  flwr/server/superlink/state/sqlite_state.py,sha256=Adc2g1DecAN9Cl9F8lekuTb885mIHiOi6sQv4nxbmSc,21203
@@ -161,13 +164,13 @@ flwr/server/utils/__init__.py,sha256=RQVbo-bcsVtp_lJBf7dL5w01FbLrr7v3YedeGp5_YMs
161
164
  flwr/server/utils/tensorboard.py,sha256=k0G6bqsLx7wfYbH2KtXsDYcOCfyIeE12-hefXA7lZdg,5485
162
165
  flwr/server/utils/validator.py,sha256=IJN2475yyD_i_9kg_SJ_JodIuZh58ufpWGUDQRAqu2s,4740
163
166
  flwr/simulation/__init__.py,sha256=E2eD5FlTmZZ80u21FmWCkacrM7O4mrEHD8iXqeCaBUQ,1278
164
- flwr/simulation/app.py,sha256=TFXAgkRJjeYyLQOmeTi7MfUEmmlziCW1K0EpPHPm_hQ,13926
167
+ flwr/simulation/app.py,sha256=WqJxdXTEuehwMW605p5NMmvBbKYx5tuqnV3Mp7jSWXM,13904
165
168
  flwr/simulation/ray_transport/__init__.py,sha256=FsaAnzC4cw4DqoouBCix6496k29jACkfeIam55BvW9g,734
166
169
  flwr/simulation/ray_transport/ray_actor.py,sha256=mg-vsqt8w6ZtGLkHlz6SnZtZz5HcQY0gYiKSlzYT27A,16591
167
170
  flwr/simulation/ray_transport/ray_client_proxy.py,sha256=8I1g8nK0Vz7ygpOSzGZ1oXTfwi1vez8fxYWCdSXBrXE,6290
168
171
  flwr/simulation/ray_transport/utils.py,sha256=TYdtfg1P9VfTdLMOJlifInGpxWHYs9UfUqIv2wfkRLA,2392
169
- flwr_nightly-1.8.0.dev20240220.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
170
- flwr_nightly-1.8.0.dev20240220.dist-info/METADATA,sha256=-1UOJqzcAM3_UiSZIeLn-oSr6bsXdbYKUg_LKZtqt3k,14901
171
- flwr_nightly-1.8.0.dev20240220.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
172
- flwr_nightly-1.8.0.dev20240220.dist-info/entry_points.txt,sha256=S1zLNFLrz0uPWs4Zrgo2EPY0iQiIcCJHrIAlnQkkOBI,262
173
- flwr_nightly-1.8.0.dev20240220.dist-info/RECORD,,
172
+ flwr_nightly-1.8.0.dev20240222.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
173
+ flwr_nightly-1.8.0.dev20240222.dist-info/METADATA,sha256=GyA7xLs4BePK4FYLf19kYaR5vZT9SmSl3Qj5sZ6eosc,15040
174
+ flwr_nightly-1.8.0.dev20240222.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
175
+ flwr_nightly-1.8.0.dev20240222.dist-info/entry_points.txt,sha256=S1zLNFLrz0uPWs4Zrgo2EPY0iQiIcCJHrIAlnQkkOBI,262
176
+ flwr_nightly-1.8.0.dev20240222.dist-info/RECORD,,