flwr-nightly 1.11.0.dev20240829__py3-none-any.whl → 1.11.1.dev20240911__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of flwr-nightly might be problematic. Click here for more details.
- flwr/cli/new/new.py +23 -37
- flwr/cli/new/templates/app/code/client.huggingface.py.tpl +19 -29
- flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -3
- flwr/cli/new/templates/app/code/server.huggingface.py.tpl +18 -3
- flwr/cli/new/templates/app/code/task.huggingface.py.tpl +16 -13
- flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +9 -1
- flwr/client/client_app.py +2 -2
- flwr/client/grpc_rere_client/client_interceptor.py +2 -3
- flwr/common/record/recordset.py +1 -1
- flwr/common/record/typeddict.py +24 -1
- flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +2 -1
- flwr/server/superlink/fleet/vce/backend/raybackend.py +21 -12
- flwr/simulation/ray_transport/ray_actor.py +2 -2
- flwr/simulation/run_simulation.py +14 -2
- flwr/superexec/app.py +3 -1
- {flwr_nightly-1.11.0.dev20240829.dist-info → flwr_nightly-1.11.1.dev20240911.dist-info}/METADATA +1 -1
- {flwr_nightly-1.11.0.dev20240829.dist-info → flwr_nightly-1.11.1.dev20240911.dist-info}/RECORD +20 -20
- {flwr_nightly-1.11.0.dev20240829.dist-info → flwr_nightly-1.11.1.dev20240911.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.11.0.dev20240829.dist-info → flwr_nightly-1.11.1.dev20240911.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.11.0.dev20240829.dist-info → flwr_nightly-1.11.1.dev20240911.dist-info}/entry_points.txt +0 -0
flwr/cli/new/new.py
CHANGED
|
@@ -136,36 +136,23 @@ def new(
|
|
|
136
136
|
username = prompt_text("Please provide your Flower username")
|
|
137
137
|
|
|
138
138
|
if framework is not None:
|
|
139
|
-
|
|
139
|
+
framework_str = str(framework.value)
|
|
140
140
|
else:
|
|
141
|
-
|
|
141
|
+
framework_str = prompt_options(
|
|
142
142
|
"Please select ML framework by typing in the number",
|
|
143
143
|
[mlf.value for mlf in MlFramework],
|
|
144
144
|
)
|
|
145
|
-
selected_value = [
|
|
146
|
-
name
|
|
147
|
-
for name, value in vars(MlFramework).items()
|
|
148
|
-
if value == framework_value
|
|
149
|
-
]
|
|
150
|
-
framework_str_upper = selected_value[0]
|
|
151
|
-
|
|
152
|
-
framework_str = framework_str_upper.lower()
|
|
153
145
|
|
|
154
146
|
llm_challenge_str = None
|
|
155
|
-
if framework_str ==
|
|
147
|
+
if framework_str == MlFramework.FLOWERTUNE:
|
|
156
148
|
llm_challenge_value = prompt_options(
|
|
157
149
|
"Please select LLM challenge by typing in the number",
|
|
158
150
|
sorted([challenge.value for challenge in LlmChallengeName]),
|
|
159
151
|
)
|
|
160
|
-
|
|
161
|
-
name
|
|
162
|
-
for name, value in vars(LlmChallengeName).items()
|
|
163
|
-
if value == llm_challenge_value
|
|
164
|
-
]
|
|
165
|
-
llm_challenge_str = selected_value[0]
|
|
166
|
-
llm_challenge_str = llm_challenge_str.lower()
|
|
152
|
+
llm_challenge_str = llm_challenge_value.lower()
|
|
167
153
|
|
|
168
|
-
|
|
154
|
+
if framework_str == MlFramework.BASELINE:
|
|
155
|
+
framework_str = "baseline"
|
|
169
156
|
|
|
170
157
|
print(
|
|
171
158
|
typer.style(
|
|
@@ -176,19 +163,21 @@ def new(
|
|
|
176
163
|
)
|
|
177
164
|
|
|
178
165
|
context = {
|
|
179
|
-
"framework_str":
|
|
166
|
+
"framework_str": framework_str,
|
|
180
167
|
"import_name": import_name.replace("-", "_"),
|
|
181
168
|
"package_name": package_name,
|
|
182
169
|
"project_name": app_name,
|
|
183
170
|
"username": username,
|
|
184
171
|
}
|
|
185
172
|
|
|
173
|
+
template_name = framework_str.lower()
|
|
174
|
+
|
|
186
175
|
# List of files to render
|
|
187
176
|
if llm_challenge_str:
|
|
188
177
|
files = {
|
|
189
178
|
".gitignore": {"template": "app/.gitignore.tpl"},
|
|
190
|
-
"pyproject.toml": {"template": f"app/pyproject.{
|
|
191
|
-
"README.md": {"template": f"app/README.{
|
|
179
|
+
"pyproject.toml": {"template": f"app/pyproject.{template_name}.toml.tpl"},
|
|
180
|
+
"README.md": {"template": f"app/README.{template_name}.md.tpl"},
|
|
192
181
|
f"{import_name}/__init__.py": {"template": "app/code/__init__.py.tpl"},
|
|
193
182
|
f"{import_name}/server_app.py": {
|
|
194
183
|
"template": "app/code/flwr_tune/server_app.py.tpl"
|
|
@@ -196,7 +185,6 @@ def new(
|
|
|
196
185
|
f"{import_name}/client_app.py": {
|
|
197
186
|
"template": "app/code/flwr_tune/client_app.py.tpl"
|
|
198
187
|
},
|
|
199
|
-
f"{import_name}/app.py": {"template": "app/code/flwr_tune/app.py.tpl"},
|
|
200
188
|
f"{import_name}/models.py": {
|
|
201
189
|
"template": "app/code/flwr_tune/models.py.tpl"
|
|
202
190
|
},
|
|
@@ -236,44 +224,42 @@ def new(
|
|
|
236
224
|
files = {
|
|
237
225
|
".gitignore": {"template": "app/.gitignore.tpl"},
|
|
238
226
|
"README.md": {"template": "app/README.md.tpl"},
|
|
239
|
-
"pyproject.toml": {"template": f"app/pyproject.{
|
|
227
|
+
"pyproject.toml": {"template": f"app/pyproject.{template_name}.toml.tpl"},
|
|
240
228
|
f"{import_name}/__init__.py": {"template": "app/code/__init__.py.tpl"},
|
|
241
229
|
f"{import_name}/server_app.py": {
|
|
242
|
-
"template": f"app/code/server.{
|
|
230
|
+
"template": f"app/code/server.{template_name}.py.tpl"
|
|
243
231
|
},
|
|
244
232
|
f"{import_name}/client_app.py": {
|
|
245
|
-
"template": f"app/code/client.{
|
|
233
|
+
"template": f"app/code/client.{template_name}.py.tpl"
|
|
246
234
|
},
|
|
247
235
|
}
|
|
248
236
|
|
|
249
237
|
# Depending on the framework, generate task.py file
|
|
250
238
|
frameworks_with_tasks = [
|
|
251
|
-
MlFramework.PYTORCH.value
|
|
252
|
-
MlFramework.JAX.value
|
|
253
|
-
MlFramework.HUGGINGFACE.value
|
|
254
|
-
MlFramework.MLX.value
|
|
255
|
-
MlFramework.TENSORFLOW.value
|
|
239
|
+
MlFramework.PYTORCH.value,
|
|
240
|
+
MlFramework.JAX.value,
|
|
241
|
+
MlFramework.HUGGINGFACE.value,
|
|
242
|
+
MlFramework.MLX.value,
|
|
243
|
+
MlFramework.TENSORFLOW.value,
|
|
256
244
|
]
|
|
257
245
|
if framework_str in frameworks_with_tasks:
|
|
258
246
|
files[f"{import_name}/task.py"] = {
|
|
259
|
-
"template": f"app/code/task.{
|
|
247
|
+
"template": f"app/code/task.{template_name}.py.tpl"
|
|
260
248
|
}
|
|
261
249
|
|
|
262
|
-
if
|
|
250
|
+
if framework_str == "baseline":
|
|
263
251
|
# Include additional files for baseline template
|
|
264
252
|
for file_name in ["model", "dataset", "strategy", "utils", "__init__"]:
|
|
265
253
|
files[f"{import_name}/{file_name}.py"] = {
|
|
266
|
-
"template": f"app/code/{file_name}.{
|
|
254
|
+
"template": f"app/code/{file_name}.{template_name}.py.tpl"
|
|
267
255
|
}
|
|
268
256
|
|
|
269
257
|
# Replace README.md
|
|
270
|
-
files["README.md"]["template"] = f"app/README.{
|
|
258
|
+
files["README.md"]["template"] = f"app/README.{template_name}.md.tpl"
|
|
271
259
|
|
|
272
260
|
# Add LICENSE
|
|
273
261
|
files["LICENSE"] = {"template": "app/LICENSE.tpl"}
|
|
274
262
|
|
|
275
|
-
context["framework_str"] = "baseline"
|
|
276
|
-
|
|
277
263
|
for file_path, value in files.items():
|
|
278
264
|
render_and_create(
|
|
279
265
|
file_path=project_dir / file_path,
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
"""$project_name: A Flower / $framework_str app."""
|
|
2
2
|
|
|
3
|
+
import torch
|
|
3
4
|
from flwr.client import ClientApp, NumPyClient
|
|
4
5
|
from flwr.common import Context
|
|
5
6
|
from transformers import AutoModelForSequenceClassification
|
|
6
7
|
|
|
7
|
-
from $import_name.task import
|
|
8
|
-
get_weights,
|
|
9
|
-
load_data,
|
|
10
|
-
set_weights,
|
|
11
|
-
train,
|
|
12
|
-
test,
|
|
13
|
-
CHECKPOINT,
|
|
14
|
-
DEVICE,
|
|
15
|
-
)
|
|
8
|
+
from $import_name.task import get_weights, load_data, set_weights, test, train
|
|
16
9
|
|
|
17
10
|
|
|
18
11
|
# Flower client
|
|
@@ -22,37 +15,34 @@ class FlowerClient(NumPyClient):
|
|
|
22
15
|
self.trainloader = trainloader
|
|
23
16
|
self.testloader = testloader
|
|
24
17
|
self.local_epochs = local_epochs
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return get_weights(self.net)
|
|
28
|
-
|
|
29
|
-
def set_parameters(self, parameters):
|
|
30
|
-
set_weights(self.net, parameters)
|
|
18
|
+
self.device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
|
|
19
|
+
self.net.to(self.device)
|
|
31
20
|
|
|
32
21
|
def fit(self, parameters, config):
|
|
33
|
-
self.
|
|
34
|
-
train(
|
|
35
|
-
|
|
36
|
-
self.trainloader,
|
|
37
|
-
epochs=self.local_epochs,
|
|
38
|
-
)
|
|
39
|
-
return self.get_parameters(config={}), len(self.trainloader), {}
|
|
22
|
+
set_weights(self.net, parameters)
|
|
23
|
+
train(self.net, self.trainloader, epochs=self.local_epochs, device=self.device)
|
|
24
|
+
return get_weights(self.net), len(self.trainloader), {}
|
|
40
25
|
|
|
41
26
|
def evaluate(self, parameters, config):
|
|
42
|
-
self.
|
|
43
|
-
loss, accuracy = test(self.net, self.testloader)
|
|
27
|
+
set_weights(self.net, parameters)
|
|
28
|
+
loss, accuracy = test(self.net, self.testloader, self.device)
|
|
44
29
|
return float(loss), len(self.testloader), {"accuracy": accuracy}
|
|
45
30
|
|
|
46
31
|
|
|
47
32
|
def client_fn(context: Context):
|
|
48
|
-
# Load model and data
|
|
49
|
-
net = AutoModelForSequenceClassification.from_pretrained(
|
|
50
|
-
CHECKPOINT, num_labels=2
|
|
51
|
-
).to(DEVICE)
|
|
52
33
|
|
|
34
|
+
# Get this client's dataset partition
|
|
53
35
|
partition_id = context.node_config["partition-id"]
|
|
54
36
|
num_partitions = context.node_config["num-partitions"]
|
|
55
|
-
|
|
37
|
+
model_name = context.run_config["model-name"]
|
|
38
|
+
trainloader, valloader = load_data(partition_id, num_partitions, model_name)
|
|
39
|
+
|
|
40
|
+
# Load model
|
|
41
|
+
num_labels = context.run_config["num-labels"]
|
|
42
|
+
net = AutoModelForSequenceClassification.from_pretrained(
|
|
43
|
+
model_name, num_labels=num_labels
|
|
44
|
+
)
|
|
45
|
+
|
|
56
46
|
local_epochs = context.run_config["local-epochs"]
|
|
57
47
|
|
|
58
48
|
# Return Client instance
|
|
@@ -17,9 +17,6 @@ class FlowerClient(NumPyClient):
|
|
|
17
17
|
self.batch_size = batch_size
|
|
18
18
|
self.verbose = verbose
|
|
19
19
|
|
|
20
|
-
def get_parameters(self, config):
|
|
21
|
-
return self.model.get_weights()
|
|
22
|
-
|
|
23
20
|
def fit(self, parameters, config):
|
|
24
21
|
self.model.set_weights(parameters)
|
|
25
22
|
self.model.fit(
|
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
"""$project_name: A Flower / $framework_str app."""
|
|
2
2
|
|
|
3
|
-
from flwr.common import Context
|
|
4
|
-
from flwr.server.strategy import FedAvg
|
|
3
|
+
from flwr.common import Context, ndarrays_to_parameters
|
|
5
4
|
from flwr.server import ServerApp, ServerAppComponents, ServerConfig
|
|
5
|
+
from flwr.server.strategy import FedAvg
|
|
6
|
+
from transformers import AutoModelForSequenceClassification
|
|
7
|
+
|
|
8
|
+
from $import_name.task import get_weights
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
def server_fn(context: Context):
|
|
9
12
|
# Read from config
|
|
10
13
|
num_rounds = context.run_config["num-server-rounds"]
|
|
14
|
+
fraction_fit = context.run_config["fraction-fit"]
|
|
15
|
+
|
|
16
|
+
# Initialize global model
|
|
17
|
+
model_name = context.run_config["model-name"]
|
|
18
|
+
num_labels = context.run_config["num-labels"]
|
|
19
|
+
net = AutoModelForSequenceClassification.from_pretrained(
|
|
20
|
+
model_name, num_labels=num_labels
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
weights = get_weights(net)
|
|
24
|
+
initial_parameters = ndarrays_to_parameters(weights)
|
|
11
25
|
|
|
12
26
|
# Define strategy
|
|
13
27
|
strategy = FedAvg(
|
|
14
|
-
fraction_fit=
|
|
28
|
+
fraction_fit=fraction_fit,
|
|
15
29
|
fraction_evaluate=1.0,
|
|
30
|
+
initial_parameters=initial_parameters,
|
|
16
31
|
)
|
|
17
32
|
config = ServerConfig(num_rounds=num_rounds)
|
|
18
33
|
|
|
@@ -4,24 +4,25 @@ import warnings
|
|
|
4
4
|
from collections import OrderedDict
|
|
5
5
|
|
|
6
6
|
import torch
|
|
7
|
+
import transformers
|
|
8
|
+
from datasets.utils.logging import disable_progress_bar
|
|
7
9
|
from evaluate import load as load_metric
|
|
10
|
+
from flwr_datasets import FederatedDataset
|
|
11
|
+
from flwr_datasets.partitioner import IidPartitioner
|
|
8
12
|
from torch.optim import AdamW
|
|
9
13
|
from torch.utils.data import DataLoader
|
|
10
14
|
from transformers import AutoTokenizer, DataCollatorWithPadding
|
|
11
15
|
|
|
12
|
-
from flwr_datasets import FederatedDataset
|
|
13
|
-
from flwr_datasets.partitioner import IidPartitioner
|
|
14
|
-
|
|
15
|
-
|
|
16
16
|
warnings.filterwarnings("ignore", category=UserWarning)
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
warnings.filterwarnings("ignore", category=FutureWarning)
|
|
18
|
+
disable_progress_bar()
|
|
19
|
+
transformers.logging.set_verbosity_error()
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
fds = None # Cache FederatedDataset
|
|
22
23
|
|
|
23
24
|
|
|
24
|
-
def load_data(partition_id: int, num_partitions: int):
|
|
25
|
+
def load_data(partition_id: int, num_partitions: int, model_name: str):
|
|
25
26
|
"""Load IMDB data (training and eval)"""
|
|
26
27
|
# Only initialize `FederatedDataset` once
|
|
27
28
|
global fds
|
|
@@ -35,10 +36,12 @@ def load_data(partition_id: int, num_partitions: int):
|
|
|
35
36
|
# Divide data: 80% train, 20% test
|
|
36
37
|
partition_train_test = partition.train_test_split(test_size=0.2, seed=42)
|
|
37
38
|
|
|
38
|
-
tokenizer = AutoTokenizer.from_pretrained(
|
|
39
|
+
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
|
39
40
|
|
|
40
41
|
def tokenize_function(examples):
|
|
41
|
-
return tokenizer(
|
|
42
|
+
return tokenizer(
|
|
43
|
+
examples["text"], truncation=True, add_special_tokens=True, max_length=512
|
|
44
|
+
)
|
|
42
45
|
|
|
43
46
|
partition_train_test = partition_train_test.map(tokenize_function, batched=True)
|
|
44
47
|
partition_train_test = partition_train_test.remove_columns("text")
|
|
@@ -59,12 +62,12 @@ def load_data(partition_id: int, num_partitions: int):
|
|
|
59
62
|
return trainloader, testloader
|
|
60
63
|
|
|
61
64
|
|
|
62
|
-
def train(net, trainloader, epochs):
|
|
65
|
+
def train(net, trainloader, epochs, device):
|
|
63
66
|
optimizer = AdamW(net.parameters(), lr=5e-5)
|
|
64
67
|
net.train()
|
|
65
68
|
for _ in range(epochs):
|
|
66
69
|
for batch in trainloader:
|
|
67
|
-
batch = {k: v.to(
|
|
70
|
+
batch = {k: v.to(device) for k, v in batch.items()}
|
|
68
71
|
outputs = net(**batch)
|
|
69
72
|
loss = outputs.loss
|
|
70
73
|
loss.backward()
|
|
@@ -72,12 +75,12 @@ def train(net, trainloader, epochs):
|
|
|
72
75
|
optimizer.zero_grad()
|
|
73
76
|
|
|
74
77
|
|
|
75
|
-
def test(net, testloader):
|
|
78
|
+
def test(net, testloader, device):
|
|
76
79
|
metric = load_metric("accuracy")
|
|
77
80
|
loss = 0
|
|
78
81
|
net.eval()
|
|
79
82
|
for batch in testloader:
|
|
80
|
-
batch = {k: v.to(
|
|
83
|
+
batch = {k: v.to(device) for k, v in batch.items()}
|
|
81
84
|
with torch.no_grad():
|
|
82
85
|
outputs = net(**batch)
|
|
83
86
|
logits = outputs.logits
|
|
@@ -8,7 +8,7 @@ version = "1.0.0"
|
|
|
8
8
|
description = ""
|
|
9
9
|
license = "Apache-2.0"
|
|
10
10
|
dependencies = [
|
|
11
|
-
"flwr[simulation]>=1.
|
|
11
|
+
"flwr[simulation]>=1.11.0",
|
|
12
12
|
"flwr-datasets>=0.3.0",
|
|
13
13
|
"torch==2.2.1",
|
|
14
14
|
"transformers>=4.30.0,<5.0",
|
|
@@ -29,10 +29,18 @@ clientapp = "$import_name.client_app:app"
|
|
|
29
29
|
|
|
30
30
|
[tool.flwr.app.config]
|
|
31
31
|
num-server-rounds = 3
|
|
32
|
+
fraction-fit = 0.5
|
|
32
33
|
local-epochs = 1
|
|
34
|
+
model-name = "prajjwal1/bert-tiny" # Set a larger model if you have access to more GPU resources
|
|
35
|
+
num-labels = 2
|
|
33
36
|
|
|
34
37
|
[tool.flwr.federations]
|
|
35
38
|
default = "localhost"
|
|
36
39
|
|
|
37
40
|
[tool.flwr.federations.localhost]
|
|
38
41
|
options.num-supernodes = 10
|
|
42
|
+
|
|
43
|
+
[tool.flwr.federations.localhost-gpu]
|
|
44
|
+
options.num-supernodes = 10
|
|
45
|
+
options.backend.client-resources.num-cpus = 4 # each ClientApp assumes to use 4CPUs
|
|
46
|
+
options.backend.client-resources.num-gpus = 0.25 # at most 4 ClientApps will run in a given GPU
|
flwr/client/client_app.py
CHANGED
|
@@ -41,11 +41,11 @@ def _alert_erroneous_client_fn() -> None:
|
|
|
41
41
|
|
|
42
42
|
def _inspect_maybe_adapt_client_fn_signature(client_fn: ClientFnExt) -> ClientFnExt:
|
|
43
43
|
client_fn_args = inspect.signature(client_fn).parameters
|
|
44
|
-
first_arg = list(client_fn_args.keys())[0]
|
|
45
44
|
|
|
46
45
|
if len(client_fn_args) != 1:
|
|
47
46
|
_alert_erroneous_client_fn()
|
|
48
47
|
|
|
48
|
+
first_arg = list(client_fn_args.keys())[0]
|
|
49
49
|
first_arg_type = client_fn_args[first_arg].annotation
|
|
50
50
|
|
|
51
51
|
if first_arg_type is str or first_arg == "cid":
|
|
@@ -263,7 +263,7 @@ def _registration_error(fn_name: str) -> ValueError:
|
|
|
263
263
|
>>> class FlowerClient(NumPyClient):
|
|
264
264
|
>>> # ...
|
|
265
265
|
>>>
|
|
266
|
-
>>> def client_fn(
|
|
266
|
+
>>> def client_fn(context: Context):
|
|
267
267
|
>>> return FlowerClient().to_client()
|
|
268
268
|
>>>
|
|
269
269
|
>>> app = ClientApp(
|
|
@@ -130,13 +130,12 @@ class AuthenticateClientInterceptor(grpc.UnaryUnaryClientInterceptor): # type:
|
|
|
130
130
|
if self.shared_secret is None:
|
|
131
131
|
raise RuntimeError("Failure to compute hmac")
|
|
132
132
|
|
|
133
|
+
message_bytes = request.SerializeToString(deterministic=True)
|
|
133
134
|
metadata.append(
|
|
134
135
|
(
|
|
135
136
|
_AUTH_TOKEN_HEADER,
|
|
136
137
|
base64.urlsafe_b64encode(
|
|
137
|
-
compute_hmac(
|
|
138
|
-
self.shared_secret, request.SerializeToString(True)
|
|
139
|
-
)
|
|
138
|
+
compute_hmac(self.shared_secret, message_bytes)
|
|
140
139
|
),
|
|
141
140
|
)
|
|
142
141
|
)
|
flwr/common/record/recordset.py
CHANGED
|
@@ -119,7 +119,7 @@ class RecordSet:
|
|
|
119
119
|
Let's see an example.
|
|
120
120
|
|
|
121
121
|
>>> from flwr.common import RecordSet
|
|
122
|
-
>>> from flwr.common import
|
|
122
|
+
>>> from flwr.common import ConfigsRecord, MetricsRecord, ParametersRecord
|
|
123
123
|
>>>
|
|
124
124
|
>>> # Let's begin with an empty record
|
|
125
125
|
>>> my_recordset = RecordSet()
|
flwr/common/record/typeddict.py
CHANGED
|
@@ -15,7 +15,18 @@
|
|
|
15
15
|
"""Typed dict base class for *Records."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
from typing import
|
|
18
|
+
from typing import (
|
|
19
|
+
Callable,
|
|
20
|
+
Dict,
|
|
21
|
+
Generic,
|
|
22
|
+
ItemsView,
|
|
23
|
+
Iterator,
|
|
24
|
+
KeysView,
|
|
25
|
+
MutableMapping,
|
|
26
|
+
TypeVar,
|
|
27
|
+
ValuesView,
|
|
28
|
+
cast,
|
|
29
|
+
)
|
|
19
30
|
|
|
20
31
|
K = TypeVar("K") # Key type
|
|
21
32
|
V = TypeVar("V") # Value type
|
|
@@ -73,3 +84,15 @@ class TypedDict(MutableMapping[K, V], Generic[K, V]):
|
|
|
73
84
|
if isinstance(other, dict):
|
|
74
85
|
return data == other
|
|
75
86
|
return NotImplemented
|
|
87
|
+
|
|
88
|
+
def keys(self) -> KeysView[K]:
|
|
89
|
+
"""D.keys() -> a set-like object providing a view on D's keys."""
|
|
90
|
+
return cast(Dict[K, V], self.__dict__["_data"]).keys()
|
|
91
|
+
|
|
92
|
+
def values(self) -> ValuesView[V]:
|
|
93
|
+
"""D.values() -> an object providing a view on D's values."""
|
|
94
|
+
return cast(Dict[K, V], self.__dict__["_data"]).values()
|
|
95
|
+
|
|
96
|
+
def items(self) -> ItemsView[K, V]:
|
|
97
|
+
"""D.items() -> a set-like object providing a view on D's items."""
|
|
98
|
+
return cast(Dict[K, V], self.__dict__["_data"]).items()
|
|
@@ -188,7 +188,8 @@ class AuthenticateServerInterceptor(grpc.ServerInterceptor): # type: ignore
|
|
|
188
188
|
self, public_key: ec.EllipticCurvePublicKey, request: Request, hmac_value: bytes
|
|
189
189
|
) -> bool:
|
|
190
190
|
shared_secret = generate_shared_key(self.server_private_key, public_key)
|
|
191
|
-
|
|
191
|
+
message_bytes = request.SerializeToString(deterministic=True)
|
|
192
|
+
return verify_hmac(shared_secret, message_bytes, hmac_value)
|
|
192
193
|
|
|
193
194
|
def _create_authenticated_node(
|
|
194
195
|
self,
|
|
@@ -52,16 +52,11 @@ class RayBackend(Backend):
|
|
|
52
52
|
|
|
53
53
|
# Validate client resources
|
|
54
54
|
self.client_resources_key = "client_resources"
|
|
55
|
-
client_resources = self._validate_client_resources(config=backend_config)
|
|
55
|
+
self.client_resources = self._validate_client_resources(config=backend_config)
|
|
56
56
|
|
|
57
|
-
#
|
|
58
|
-
actor_kwargs = self._validate_actor_arguments(config=backend_config)
|
|
59
|
-
|
|
60
|
-
self.pool = BasicActorPool(
|
|
61
|
-
actor_type=ClientAppActor,
|
|
62
|
-
client_resources=client_resources,
|
|
63
|
-
actor_kwargs=actor_kwargs,
|
|
64
|
-
)
|
|
57
|
+
# Valide actor resources
|
|
58
|
+
self.actor_kwargs = self._validate_actor_arguments(config=backend_config)
|
|
59
|
+
self.pool: Optional[BasicActorPool] = None
|
|
65
60
|
|
|
66
61
|
self.app_fn: Optional[Callable[[], ClientApp]] = None
|
|
67
62
|
|
|
@@ -122,14 +117,24 @@ class RayBackend(Backend):
|
|
|
122
117
|
@property
|
|
123
118
|
def num_workers(self) -> int:
|
|
124
119
|
"""Return number of actors in pool."""
|
|
125
|
-
return self.pool.num_actors
|
|
120
|
+
return self.pool.num_actors if self.pool else 0
|
|
126
121
|
|
|
127
122
|
def is_worker_idle(self) -> bool:
|
|
128
123
|
"""Report whether the pool has idle actors."""
|
|
129
|
-
return self.pool.is_actor_available()
|
|
124
|
+
return self.pool.is_actor_available() if self.pool else False
|
|
130
125
|
|
|
131
126
|
def build(self, app_fn: Callable[[], ClientApp]) -> None:
|
|
132
127
|
"""Build pool of Ray actors that this backend will submit jobs to."""
|
|
128
|
+
# Create Actor Pool
|
|
129
|
+
try:
|
|
130
|
+
self.pool = BasicActorPool(
|
|
131
|
+
actor_type=ClientAppActor,
|
|
132
|
+
client_resources=self.client_resources,
|
|
133
|
+
actor_kwargs=self.actor_kwargs,
|
|
134
|
+
)
|
|
135
|
+
except Exception as ex:
|
|
136
|
+
raise ex
|
|
137
|
+
|
|
133
138
|
self.pool.add_actors_to_pool(self.pool.actors_capacity)
|
|
134
139
|
# Set ClientApp callable that ray actors will use
|
|
135
140
|
self.app_fn = app_fn
|
|
@@ -146,6 +151,9 @@ class RayBackend(Backend):
|
|
|
146
151
|
"""
|
|
147
152
|
partition_id = context.node_config[PARTITION_ID_KEY]
|
|
148
153
|
|
|
154
|
+
if self.pool is None:
|
|
155
|
+
raise ValueError("The actor pool is empty, unfit to process messages.")
|
|
156
|
+
|
|
149
157
|
if self.app_fn is None:
|
|
150
158
|
raise ValueError(
|
|
151
159
|
"Unspecified function to load a `ClientApp`. "
|
|
@@ -179,6 +187,7 @@ class RayBackend(Backend):
|
|
|
179
187
|
|
|
180
188
|
def terminate(self) -> None:
|
|
181
189
|
"""Terminate all actors in actor pool."""
|
|
182
|
-
self.pool
|
|
190
|
+
if self.pool:
|
|
191
|
+
self.pool.terminate_all_actors()
|
|
183
192
|
ray.shutdown()
|
|
184
193
|
log(DEBUG, "Terminated %s", self.__class__.__name__)
|
|
@@ -124,14 +124,14 @@ def pool_size_from_resources(client_resources: Dict[str, Union[int, float]]) ->
|
|
|
124
124
|
WARNING,
|
|
125
125
|
"The ActorPool is empty. The system (CPUs=%s, GPUs=%s) "
|
|
126
126
|
"does not meet the criteria to host at least one client with resources:"
|
|
127
|
-
" %s. Lowering
|
|
127
|
+
" %s. Lowering these resources could help.",
|
|
128
128
|
num_cpus,
|
|
129
129
|
num_gpus,
|
|
130
130
|
client_resources,
|
|
131
131
|
)
|
|
132
132
|
raise ValueError(
|
|
133
133
|
"ActorPool is empty. Stopping Simulation. "
|
|
134
|
-
"Check
|
|
134
|
+
"Check `num_cpus` and/or `num_gpus` passed to the simulation engine"
|
|
135
135
|
)
|
|
136
136
|
|
|
137
137
|
return total_num_actors
|
|
@@ -216,6 +216,7 @@ def run_simulation_from_cli() -> None:
|
|
|
216
216
|
app_dir=app_dir,
|
|
217
217
|
run=run,
|
|
218
218
|
enable_tf_gpu_growth=args.enable_tf_gpu_growth,
|
|
219
|
+
delay_start=args.delay_start,
|
|
219
220
|
verbose_logging=args.verbose,
|
|
220
221
|
server_app_run_config=fused_config,
|
|
221
222
|
is_app=is_app,
|
|
@@ -309,7 +310,6 @@ def run_serverapp_th(
|
|
|
309
310
|
f_stop: threading.Event,
|
|
310
311
|
has_exception: threading.Event,
|
|
311
312
|
enable_tf_gpu_growth: bool,
|
|
312
|
-
delay_launch: int = 3,
|
|
313
313
|
) -> threading.Thread:
|
|
314
314
|
"""Run SeverApp in a thread."""
|
|
315
315
|
|
|
@@ -365,7 +365,6 @@ def run_serverapp_th(
|
|
|
365
365
|
server_app,
|
|
366
366
|
),
|
|
367
367
|
)
|
|
368
|
-
sleep(delay_launch)
|
|
369
368
|
serverapp_th.start()
|
|
370
369
|
return serverapp_th
|
|
371
370
|
|
|
@@ -380,6 +379,7 @@ def _main_loop(
|
|
|
380
379
|
enable_tf_gpu_growth: bool,
|
|
381
380
|
run: Run,
|
|
382
381
|
exit_event: EventType,
|
|
382
|
+
delay_start: int,
|
|
383
383
|
flwr_dir: Optional[str] = None,
|
|
384
384
|
client_app: Optional[ClientApp] = None,
|
|
385
385
|
client_app_attr: Optional[str] = None,
|
|
@@ -419,6 +419,9 @@ def _main_loop(
|
|
|
419
419
|
enable_tf_gpu_growth=enable_tf_gpu_growth,
|
|
420
420
|
)
|
|
421
421
|
|
|
422
|
+
# Buffer time so the `ServerApp` in separate thread is ready
|
|
423
|
+
log(DEBUG, "Buffer time delay: %ds", delay_start)
|
|
424
|
+
sleep(delay_start)
|
|
422
425
|
# Start Simulation Engine
|
|
423
426
|
vce.start_vce(
|
|
424
427
|
num_supernodes=num_supernodes,
|
|
@@ -467,6 +470,7 @@ def _run_simulation(
|
|
|
467
470
|
flwr_dir: Optional[str] = None,
|
|
468
471
|
run: Optional[Run] = None,
|
|
469
472
|
enable_tf_gpu_growth: bool = False,
|
|
473
|
+
delay_start: int = 5,
|
|
470
474
|
verbose_logging: bool = False,
|
|
471
475
|
is_app: bool = False,
|
|
472
476
|
) -> None:
|
|
@@ -523,6 +527,7 @@ def _run_simulation(
|
|
|
523
527
|
enable_tf_gpu_growth,
|
|
524
528
|
run,
|
|
525
529
|
exit_event,
|
|
530
|
+
delay_start,
|
|
526
531
|
flwr_dir,
|
|
527
532
|
client_app,
|
|
528
533
|
client_app_attr,
|
|
@@ -610,6 +615,13 @@ def _parse_args_run_simulation() -> argparse.ArgumentParser:
|
|
|
610
615
|
"Read more about how `tf.config.experimental.set_memory_growth()` works in "
|
|
611
616
|
"the TensorFlow documentation: https://www.tensorflow.org/api/stable.",
|
|
612
617
|
)
|
|
618
|
+
parser.add_argument(
|
|
619
|
+
"--delay-start",
|
|
620
|
+
type=int,
|
|
621
|
+
default=3,
|
|
622
|
+
help="Buffer time (in seconds) to delay the start the simulation engine after "
|
|
623
|
+
"the `ServerApp`, which runs in a separate thread, has been launched.",
|
|
624
|
+
)
|
|
613
625
|
parser.add_argument(
|
|
614
626
|
"--verbose",
|
|
615
627
|
action="store_true",
|
flwr/superexec/app.py
CHANGED
|
@@ -56,7 +56,9 @@ def run_superexec() -> None:
|
|
|
56
56
|
address=address,
|
|
57
57
|
executor=_load_executor(args),
|
|
58
58
|
certificates=certificates,
|
|
59
|
-
config=parse_config_args(
|
|
59
|
+
config=parse_config_args(
|
|
60
|
+
[args.executor_config] if args.executor_config else args.executor_config
|
|
61
|
+
),
|
|
60
62
|
)
|
|
61
63
|
|
|
62
64
|
grpc_servers = [superexec_server]
|
{flwr_nightly-1.11.0.dev20240829.dist-info → flwr_nightly-1.11.1.dev20240911.dist-info}/RECORD
RENAMED
|
@@ -6,7 +6,7 @@ flwr/cli/config_utils.py,sha256=mDGXbcIxG14UpkUplILBYUkSk5M1LeTzZYDGNx-pFpU,7540
|
|
|
6
6
|
flwr/cli/example.py,sha256=1bGDYll3BXQY2kRqSN-oICqS5n1b9m0g0RvXTopXHl4,2215
|
|
7
7
|
flwr/cli/install.py,sha256=tUncrbZYRbC9QEcWSeTER16plPEoU-ERP0-nMgWiSPo,7094
|
|
8
8
|
flwr/cli/new/__init__.py,sha256=cQzK1WH4JP2awef1t2UQ2xjl1agVEz9rwutV18SWV1k,789
|
|
9
|
-
flwr/cli/new/new.py,sha256=
|
|
9
|
+
flwr/cli/new/new.py,sha256=9nBm6yjy3q4AHxT-wzV3n5cgO82F19xajfrdu3DIfyk,9605
|
|
10
10
|
flwr/cli/new/templates/__init__.py,sha256=4luU8RL-CK8JJCstQ_ON809W9bNTkY1l9zSaPKBkgwY,725
|
|
11
11
|
flwr/cli/new/templates/app/.gitignore.tpl,sha256=XixnHdyeMB2vwkGtGnwHqoWpH-9WChdyG0GXe57duhc,3078
|
|
12
12
|
flwr/cli/new/templates/app/LICENSE.tpl,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
@@ -18,13 +18,13 @@ flwr/cli/new/templates/app/code/__init__.baseline.py.tpl,sha256=YkHAgppUeD2BnBoG
|
|
|
18
18
|
flwr/cli/new/templates/app/code/__init__.py,sha256=EM6vfvgAILKPaPn7H1wMV1Wi01WyZCP_Eg6NxD6oWg8,736
|
|
19
19
|
flwr/cli/new/templates/app/code/__init__.py.tpl,sha256=J0Gn74E7khpLyKJVNqOPu7ev93vkcu1PZugsbxtABMw,52
|
|
20
20
|
flwr/cli/new/templates/app/code/client.baseline.py.tpl,sha256=1htktXX3jXX05r0vuG_afjS1sXGtuONW9EpiQ7vSBes,1901
|
|
21
|
-
flwr/cli/new/templates/app/code/client.huggingface.py.tpl,sha256=
|
|
21
|
+
flwr/cli/new/templates/app/code/client.huggingface.py.tpl,sha256=ifD08KwjdoGieV26hFCgf3PQB6rMhj_NZLo5iUUndm8,1846
|
|
22
22
|
flwr/cli/new/templates/app/code/client.jax.py.tpl,sha256=c2LDew2V8BUybZJiz1FeB3Kq4ey0Q2s0S5qNPUTNmI4,1490
|
|
23
23
|
flwr/cli/new/templates/app/code/client.mlx.py.tpl,sha256=gxipt57ldc741qwRqSWtsLQH05JODKdGMTtvoXiBzDA,2906
|
|
24
24
|
flwr/cli/new/templates/app/code/client.numpy.py.tpl,sha256=DMUXvQd2dr-wEn0ZrYJQhZ0OFUT4PKoHXtiD2haWnCI,570
|
|
25
25
|
flwr/cli/new/templates/app/code/client.pytorch.py.tpl,sha256=WczaR5avJUhfw2Grn2KEC4tDJ4voIYG-2pAy-7i2cT8,1685
|
|
26
26
|
flwr/cli/new/templates/app/code/client.sklearn.py.tpl,sha256=xW9cuKhybk5S8IeDZhbeb0DNegDIJGEYrzMKsxgc2GE,2978
|
|
27
|
-
flwr/cli/new/templates/app/code/client.tensorflow.py.tpl,sha256=
|
|
27
|
+
flwr/cli/new/templates/app/code/client.tensorflow.py.tpl,sha256=yBiiU7B9Kf70U52cPkNs_dUpYrrTwbUi2os-PAyheaM,1680
|
|
28
28
|
flwr/cli/new/templates/app/code/dataset.baseline.py.tpl,sha256=jbd_exHAk2-Blu_kVutjPO6a_dkJQWb232zxSeXIZ1k,1453
|
|
29
29
|
flwr/cli/new/templates/app/code/flwr_tune/__init__.py,sha256=JgNgBtKdm1jKM9625WxappCAVUGtYAmcjKSsXJ1u3ZQ,748
|
|
30
30
|
flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl,sha256=DbotzaXzLDwplVBkJLOe5Lt5b6Yutwv9rJ69oVwyrvU,4397
|
|
@@ -34,7 +34,7 @@ flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl,sha256=yMVcbfGkTPV9A
|
|
|
34
34
|
flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl,sha256=BhiqRg9w1MGuU5h2_vrLhRc0oHItYzE69qX_JI411k8,2754
|
|
35
35
|
flwr/cli/new/templates/app/code/model.baseline.py.tpl,sha256=cSz6-IWsnMl7s04DW4URINiIppCIberrtE8NqK6Qz48,2571
|
|
36
36
|
flwr/cli/new/templates/app/code/server.baseline.py.tpl,sha256=outx7lDXsWS8QXKWOGOiDno6eE8WL7LBD51ZkAuC3WU,1570
|
|
37
|
-
flwr/cli/new/templates/app/code/server.huggingface.py.tpl,sha256=
|
|
37
|
+
flwr/cli/new/templates/app/code/server.huggingface.py.tpl,sha256=0PJmnZvR9_VPLSak1yVfkOx3dmqo6cynhY1l2s4AZrE,1158
|
|
38
38
|
flwr/cli/new/templates/app/code/server.jax.py.tpl,sha256=pIdUH-LgWRAGWQYLlivMNf8XnDSNDe2cCuRjlxbRzys,529
|
|
39
39
|
flwr/cli/new/templates/app/code/server.mlx.py.tpl,sha256=RqiZ0k468SOlm9dcPr-fvA8xcWv4zwDCbJfBwL7P9Us,529
|
|
40
40
|
flwr/cli/new/templates/app/code/server.numpy.py.tpl,sha256=RqiZ0k468SOlm9dcPr-fvA8xcWv4zwDCbJfBwL7P9Us,529
|
|
@@ -42,7 +42,7 @@ flwr/cli/new/templates/app/code/server.pytorch.py.tpl,sha256=DW5c8vzXCvFeIE8YIWB
|
|
|
42
42
|
flwr/cli/new/templates/app/code/server.sklearn.py.tpl,sha256=25Ae3kDqjDdBl8LwkDwye69nevd02Pk_e7F3SQKLdyk,624
|
|
43
43
|
flwr/cli/new/templates/app/code/server.tensorflow.py.tpl,sha256=xMhQ7AumowgLkgUilgjVK7IbpRhPjslhVJU-vID6NY8,856
|
|
44
44
|
flwr/cli/new/templates/app/code/strategy.baseline.py.tpl,sha256=YkHAgppUeD2BnBoGfVB6dEvBfjuIPGsU1gw4CiUi3qA,40
|
|
45
|
-
flwr/cli/new/templates/app/code/task.huggingface.py.tpl,sha256=
|
|
45
|
+
flwr/cli/new/templates/app/code/task.huggingface.py.tpl,sha256=ua6cAhJYPUCwML20DEucM0F4ZzzsEVQLYrRvhQ7CGRE,3347
|
|
46
46
|
flwr/cli/new/templates/app/code/task.jax.py.tpl,sha256=F05eg149c9icRyVNdfcLyZvAXROQ7QhfifoGw_U1dsg,1530
|
|
47
47
|
flwr/cli/new/templates/app/code/task.mlx.py.tpl,sha256=jWtCULLRr_9bCIJvoTLMx037-SDl_LF8udtA1UGoXDk,2946
|
|
48
48
|
flwr/cli/new/templates/app/code/task.pytorch.py.tpl,sha256=NgbPix74X1t3ybaGjqdls30vF1i5oY3L7EQExhWhN74,3812
|
|
@@ -50,7 +50,7 @@ flwr/cli/new/templates/app/code/task.tensorflow.py.tpl,sha256=SKXAZdgBnPpbAbJ90R
|
|
|
50
50
|
flwr/cli/new/templates/app/code/utils.baseline.py.tpl,sha256=YkHAgppUeD2BnBoGfVB6dEvBfjuIPGsU1gw4CiUi3qA,40
|
|
51
51
|
flwr/cli/new/templates/app/pyproject.baseline.toml.tpl,sha256=4gi90W9_B1kj6rYkpvVJxhNX9Yctsv9OH6CzXP-dcE4,2666
|
|
52
52
|
flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl,sha256=pogRZLrwSfN_XH4NxDdMkhMh1O_7DP90VOoP-cP0HvI,1827
|
|
53
|
-
flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl,sha256=
|
|
53
|
+
flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl,sha256=CHJgkPNkJfzJhEbTe15uiV3AhOtIddQi-yofPZsCk3E,1143
|
|
54
54
|
flwr/cli/new/templates/app/pyproject.jax.toml.tpl,sha256=Tq6jeGcoOKzMwWWYxMVnzMcipLURHLiW69iYlD1ywMg,659
|
|
55
55
|
flwr/cli/new/templates/app/pyproject.mlx.toml.tpl,sha256=SHwYAA2qgIlOAU3Sb9BKSZcZ7O9biACg27MHexXUtDw,741
|
|
56
56
|
flwr/cli/new/templates/app/pyproject.numpy.toml.tpl,sha256=-FCi64ygMgQke3zApUt0XtkIBo3WtQoPAPhtp_FqkPE,612
|
|
@@ -63,7 +63,7 @@ flwr/cli/utils.py,sha256=l65Ul0YsSBPuypk0uorAtEDmLEYiUrzpCXi6zCg9mJ4,4506
|
|
|
63
63
|
flwr/client/__init__.py,sha256=DGDoO0AEAfz-0CUFmLdyUUweAS64-07AOnmDfWUefK4,1192
|
|
64
64
|
flwr/client/app.py,sha256=o_2bhmlBeZATtWnAPZhL-Q1Ly0QZxc9ou4i7t0HKumE,31956
|
|
65
65
|
flwr/client/client.py,sha256=gy6WVlMUFAp8oevN4xpQPX30vPOIYGVqdbuFlTWkyG4,9080
|
|
66
|
-
flwr/client/client_app.py,sha256=
|
|
66
|
+
flwr/client/client_app.py,sha256=6TIH-B5lgKn199uzcjxfFKiGvKN5tmKYFpsovUrSXoo,10396
|
|
67
67
|
flwr/client/clientapp/__init__.py,sha256=kZqChGnTChQ1WGSUkIlW2S5bc0d0mzDubCAmZUGRpEY,800
|
|
68
68
|
flwr/client/clientapp/app.py,sha256=4QtblvJsZ0-V-QBbzyNqWV13ugrgJmkZnsHpBCuqgi8,7797
|
|
69
69
|
flwr/client/clientapp/clientappio_servicer.py,sha256=5L6bjw_j3Mnx9kRFwYwxDNABKurBO5q1jZOWE_X11wQ,8522
|
|
@@ -74,7 +74,7 @@ flwr/client/grpc_adapter_client/connection.py,sha256=aOlCYasl8f2CrfcN-WrVEmvjAZF
|
|
|
74
74
|
flwr/client/grpc_client/__init__.py,sha256=LsnbqXiJhgQcB0XzAlUQgPx011Uf7Y7yabIC1HxivJ8,735
|
|
75
75
|
flwr/client/grpc_client/connection.py,sha256=czhRm23fwTgjN24Vf5nyNQ3hcb5Fo_5k-o9yZnelQCs,9362
|
|
76
76
|
flwr/client/grpc_rere_client/__init__.py,sha256=MK-oSoV3kwUEQnIwl0GN4OpiHR7eLOrMA8ikunET130,752
|
|
77
|
-
flwr/client/grpc_rere_client/client_interceptor.py,sha256=
|
|
77
|
+
flwr/client/grpc_rere_client/client_interceptor.py,sha256=eONCq-uRYvRCxjdP4wIi_FDynDipHs3DYjExgzAcJ5M,5240
|
|
78
78
|
flwr/client/grpc_rere_client/connection.py,sha256=aiIWW9fVgJZNeZ9SjUAx5ax-3825JrjYc5E5l7XvzyM,10913
|
|
79
79
|
flwr/client/grpc_rere_client/grpc_adapter.py,sha256=Pw7Toi4wCUIEdBMyv4yKirjgW6814gFhhAmsTYmV4IM,5005
|
|
80
80
|
flwr/client/heartbeat.py,sha256=cx37mJBH8LyoIN4Lks85wtqT1mnU5GulQnr4pGCvAq0,2404
|
|
@@ -118,8 +118,8 @@ flwr/common/record/configsrecord.py,sha256=6nIpGaeB_o8SvjMfD_iehJC1efAHgWyaeGfLD
|
|
|
118
118
|
flwr/common/record/conversion_utils.py,sha256=n3I3SI2P6hUjyxbWNc0QAch-SEhfMK6Hm-UUaplAlUc,1393
|
|
119
119
|
flwr/common/record/metricsrecord.py,sha256=aTuw0gWjRaZhekf76zg0h0rES3iEnTIGPZ7-jN2PYO4,5764
|
|
120
120
|
flwr/common/record/parametersrecord.py,sha256=mOcERCUylgWLQ-hISYmOHXlt-Qohv8YtPnJdLO0Kr8U,7730
|
|
121
|
-
flwr/common/record/recordset.py,sha256=
|
|
122
|
-
flwr/common/record/typeddict.py,sha256=
|
|
121
|
+
flwr/common/record/recordset.py,sha256=sSofrBycZSqiHR4TzfI4_QoIIN-5B1LnMG0C9CiByAo,8312
|
|
122
|
+
flwr/common/record/typeddict.py,sha256=TDPLdeuHiAUy9JyfJN0VF1zSyqdnf_uNWUFjAd2z_Os,3623
|
|
123
123
|
flwr/common/recordset_compat.py,sha256=5prvfx8mT4ZWIEU4Gmz2wzCbO4yPjQ3ONr20uKt3UM0,13973
|
|
124
124
|
flwr/common/retry_invoker.py,sha256=dQY5fPIKhy9OiFswZhLxA9fB455u-DYCvDVcFJmrPDk,11707
|
|
125
125
|
flwr/common/secure_aggregation/__init__.py,sha256=erPnTWdOfMH0K0HQTmj5foDJ6t3iYcExy2aACy8iZNQ,731
|
|
@@ -254,7 +254,7 @@ flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py,sha256=h3EhqgelegVC4E
|
|
|
254
254
|
flwr/server/superlink/fleet/grpc_bidi/grpc_server.py,sha256=DIXCYfPwm5paWq6hccReW0tB7-dTfq4vvMZ7CsiuYf4,12292
|
|
255
255
|
flwr/server/superlink/fleet/grpc_rere/__init__.py,sha256=j2hyC342am-_Hgp1g80Y3fGDzfTI6n8QOOn2PyWf4eg,758
|
|
256
256
|
flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py,sha256=bgoLQEhahVHjdlRDk_58zyKFeMOziiPUXSbYMhOxybY,4757
|
|
257
|
-
flwr/server/superlink/fleet/grpc_rere/server_interceptor.py,sha256=
|
|
257
|
+
flwr/server/superlink/fleet/grpc_rere/server_interceptor.py,sha256=zN8TIdg9ZxKtmrwtarWUPdm08jUBBGoz59ndO3C-7jg,7985
|
|
258
258
|
flwr/server/superlink/fleet/message_handler/__init__.py,sha256=h8oLD7uo5lKICPy0rRdKRjTYe62u8PKkT_fA4xF5JPA,731
|
|
259
259
|
flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=9qDDPwj3txHPo2dNaWQiO3UpGno5Zm9IMhJXnAPZbqg,4439
|
|
260
260
|
flwr/server/superlink/fleet/rest_rere/__init__.py,sha256=5jbYbAn75sGv-gBwOPDySE0kz96F6dTYLeMrGqNi4lM,735
|
|
@@ -262,7 +262,7 @@ flwr/server/superlink/fleet/rest_rere/rest_api.py,sha256=3wegOVJadA3pH_2CwZHQ3Uw
|
|
|
262
262
|
flwr/server/superlink/fleet/vce/__init__.py,sha256=36MHKiefnJeyjwMQzVUK4m06Ojon3WDcwZGQsAcyVhQ,783
|
|
263
263
|
flwr/server/superlink/fleet/vce/backend/__init__.py,sha256=psQjI1DQHOM5uWVXM27l_wPHjfEkMUTP-_8-lEFH1JA,1466
|
|
264
264
|
flwr/server/superlink/fleet/vce/backend/backend.py,sha256=YugFH_XYclqmq07er5ne1DZc7PgR9lWGs5LY_YIHwc8,2207
|
|
265
|
-
flwr/server/superlink/fleet/vce/backend/raybackend.py,sha256=
|
|
265
|
+
flwr/server/superlink/fleet/vce/backend/raybackend.py,sha256=VQ63rZytcavfDedfjArAejPi3VGYXrfcsb8yi57prRc,7168
|
|
266
266
|
flwr/server/superlink/fleet/vce/vce_api.py,sha256=lTQ2WycKK4-w22EPoJJz1qn73j9ZTwBlNz2cla2Zv0Q,12653
|
|
267
267
|
flwr/server/superlink/state/__init__.py,sha256=Gj2OTFLXvA-mAjBvwuKDM3rDrVaQPcIoybSa2uskMTE,1003
|
|
268
268
|
flwr/server/superlink/state/in_memory_state.py,sha256=eNXOVt3HhJOYxkbYRNWEudCaNrYj2B7tOU9xgKbM2Ag,13166
|
|
@@ -283,19 +283,19 @@ flwr/server/workflow/secure_aggregation/secaggplus_workflow.py,sha256=vdS_AeRYBv
|
|
|
283
283
|
flwr/simulation/__init__.py,sha256=ybVBW3xT6cg_IasJV4_ymI3bVrCbFhw1mmcfrdfl3q0,1359
|
|
284
284
|
flwr/simulation/app.py,sha256=te3dQB3eodPwzsv1y4daPyaskIAaOtgoHaQLobrqoqY,15163
|
|
285
285
|
flwr/simulation/ray_transport/__init__.py,sha256=wzcEEwUUlulnXsg6raCA1nGpP3LlAQDtJ8zNkCXcVbA,734
|
|
286
|
-
flwr/simulation/ray_transport/ray_actor.py,sha256=
|
|
286
|
+
flwr/simulation/ray_transport/ray_actor.py,sha256=IbFwbRFxKHoLjgx_LTuehS0L3uHPw_SPaMfA4wHA0Xk,19026
|
|
287
287
|
flwr/simulation/ray_transport/ray_client_proxy.py,sha256=0abIsU0VBk9rNJZOKHIyzYGy3ZnWBgqYocX_oct1EP0,7307
|
|
288
288
|
flwr/simulation/ray_transport/utils.py,sha256=TYdtfg1P9VfTdLMOJlifInGpxWHYs9UfUqIv2wfkRLA,2392
|
|
289
|
-
flwr/simulation/run_simulation.py,sha256=
|
|
289
|
+
flwr/simulation/run_simulation.py,sha256=hnH3qThfg_ii2tMu1y3X4ZWbw99CNk7vfduQ1fdZxbY,22750
|
|
290
290
|
flwr/superexec/__init__.py,sha256=fcj366jh4RFby_vDwLroU4kepzqbnJgseZD_jUr_Mko,715
|
|
291
|
-
flwr/superexec/app.py,sha256=
|
|
291
|
+
flwr/superexec/app.py,sha256=gH25dr7FL9IWODSOtP0-r59iuOKDeSXLLPxpEAL50BM,6561
|
|
292
292
|
flwr/superexec/deployment.py,sha256=1qhztkcZDjaSbicligbXGqn49gbpN271rTlEVAnNuWw,6283
|
|
293
293
|
flwr/superexec/exec_grpc.py,sha256=PhqGoZEpTMxSQmUSV8Wgtzb1Za_pHJ-adZqo5RYnDyE,1942
|
|
294
294
|
flwr/superexec/exec_servicer.py,sha256=jl0aKVjm0PLQABcTL5c3jdSIzb0Z6hpVOtrAn4Ob7ts,2323
|
|
295
295
|
flwr/superexec/executor.py,sha256=k_adivto6R2U82DADOHNvdtobehBYreRek1gOEBIQnQ,2318
|
|
296
296
|
flwr/superexec/simulation.py,sha256=J6pw-RqCSiUed8I_3MasZH4tl57ZmDebPAHNnbb0-vE,7420
|
|
297
|
-
flwr_nightly-1.11.
|
|
298
|
-
flwr_nightly-1.11.
|
|
299
|
-
flwr_nightly-1.11.
|
|
300
|
-
flwr_nightly-1.11.
|
|
301
|
-
flwr_nightly-1.11.
|
|
297
|
+
flwr_nightly-1.11.1.dev20240911.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
298
|
+
flwr_nightly-1.11.1.dev20240911.dist-info/METADATA,sha256=96wpiwqS16Lsmrnng5_AdtynkNwGP4BsjBY0jRwKYYk,15703
|
|
299
|
+
flwr_nightly-1.11.1.dev20240911.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
300
|
+
flwr_nightly-1.11.1.dev20240911.dist-info/entry_points.txt,sha256=WUCbqhLEOzjx_lyATIM0-f0e8kOVaQjzwOvyOxHrMhs,434
|
|
301
|
+
flwr_nightly-1.11.1.dev20240911.dist-info/RECORD,,
|
{flwr_nightly-1.11.0.dev20240829.dist-info → flwr_nightly-1.11.1.dev20240911.dist-info}/LICENSE
RENAMED
|
File without changes
|
{flwr_nightly-1.11.0.dev20240829.dist-info → flwr_nightly-1.11.1.dev20240911.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|