flwr-nightly 1.11.0.dev20240823__py3-none-any.whl → 1.11.1.dev20240912__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.

Files changed (61) hide show
  1. flwr/cli/app.py +0 -2
  2. flwr/cli/new/new.py +41 -40
  3. flwr/cli/new/templates/app/LICENSE.tpl +202 -0
  4. flwr/cli/new/templates/app/README.baseline.md.tpl +127 -0
  5. flwr/cli/new/templates/app/README.flowertune.md.tpl +16 -6
  6. flwr/cli/new/templates/app/code/__init__.baseline.py.tpl +1 -0
  7. flwr/cli/new/templates/app/code/client.baseline.py.tpl +58 -0
  8. flwr/cli/new/templates/app/code/client.huggingface.py.tpl +19 -29
  9. flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -3
  10. flwr/cli/new/templates/app/code/dataset.baseline.py.tpl +36 -0
  11. flwr/cli/new/templates/app/code/flwr_tune/{client.py.tpl → client_app.py.tpl} +50 -40
  12. flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl +32 -2
  13. flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +0 -3
  14. flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl +95 -0
  15. flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl +83 -0
  16. flwr/cli/new/templates/app/code/model.baseline.py.tpl +80 -0
  17. flwr/cli/new/templates/app/code/server.baseline.py.tpl +46 -0
  18. flwr/cli/new/templates/app/code/server.huggingface.py.tpl +18 -3
  19. flwr/cli/new/templates/app/code/strategy.baseline.py.tpl +1 -0
  20. flwr/cli/new/templates/app/code/task.huggingface.py.tpl +16 -13
  21. flwr/cli/new/templates/app/code/utils.baseline.py.tpl +1 -0
  22. flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +138 -0
  23. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +34 -7
  24. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +9 -1
  25. flwr/cli/run/run.py +2 -2
  26. flwr/client/__init__.py +0 -4
  27. flwr/client/app.py +3 -4
  28. flwr/client/client_app.py +2 -2
  29. flwr/client/grpc_rere_client/client_interceptor.py +15 -7
  30. flwr/client/supernode/app.py +8 -7
  31. flwr/common/config.py +14 -11
  32. flwr/common/constant.py +12 -1
  33. flwr/common/record/recordset.py +1 -1
  34. flwr/common/record/typeddict.py +24 -1
  35. flwr/common/telemetry.py +36 -30
  36. flwr/server/__init__.py +0 -4
  37. flwr/server/app.py +21 -22
  38. flwr/server/compat/app.py +0 -5
  39. flwr/server/driver/grpc_driver.py +3 -6
  40. flwr/server/run_serverapp.py +20 -7
  41. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +19 -8
  42. flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +13 -12
  43. flwr/server/superlink/fleet/vce/backend/raybackend.py +21 -12
  44. flwr/server/superlink/state/in_memory_state.py +15 -15
  45. flwr/server/superlink/state/sqlite_state.py +10 -10
  46. flwr/server/superlink/state/state.py +8 -8
  47. flwr/simulation/ray_transport/ray_actor.py +2 -2
  48. flwr/simulation/run_simulation.py +37 -8
  49. flwr/superexec/__init__.py +0 -6
  50. flwr/superexec/app.py +5 -3
  51. flwr/superexec/deployment.py +2 -2
  52. {flwr_nightly-1.11.0.dev20240823.dist-info → flwr_nightly-1.11.1.dev20240912.dist-info}/METADATA +3 -3
  53. {flwr_nightly-1.11.0.dev20240823.dist-info → flwr_nightly-1.11.1.dev20240912.dist-info}/RECORD +56 -48
  54. flwr_nightly-1.11.1.dev20240912.dist-info/entry_points.txt +10 -0
  55. flwr/cli/new/templates/app/code/flwr_tune/app.py.tpl +0 -89
  56. flwr/cli/new/templates/app/code/flwr_tune/config.yaml.tpl +0 -34
  57. flwr/cli/new/templates/app/code/flwr_tune/server.py.tpl +0 -48
  58. flwr/cli/new/templates/app/code/flwr_tune/static_config.yaml.tpl +0 -11
  59. flwr_nightly-1.11.0.dev20240823.dist-info/entry_points.txt +0 -10
  60. {flwr_nightly-1.11.0.dev20240823.dist-info → flwr_nightly-1.11.1.dev20240912.dist-info}/LICENSE +0 -0
  61. {flwr_nightly-1.11.0.dev20240823.dist-info → flwr_nightly-1.11.1.dev20240912.dist-info}/WHEEL +0 -0
@@ -45,7 +45,7 @@ class InMemoryState(State): # pylint: disable=R0902,R0904
45
45
  self.task_ins_store: Dict[UUID, TaskIns] = {}
46
46
  self.task_res_store: Dict[UUID, TaskRes] = {}
47
47
 
48
- self.client_public_keys: Set[bytes] = set()
48
+ self.node_public_keys: Set[bytes] = set()
49
49
  self.server_public_key: Optional[bytes] = None
50
50
  self.server_private_key: Optional[bytes] = None
51
51
 
@@ -237,7 +237,7 @@ class InMemoryState(State): # pylint: disable=R0902,R0904
237
237
  return node_id
238
238
 
239
239
  def delete_node(self, node_id: int, public_key: Optional[bytes] = None) -> None:
240
- """Delete a client node."""
240
+ """Delete a node."""
241
241
  with self.lock:
242
242
  if node_id not in self.node_ids:
243
243
  raise ValueError(f"Node {node_id} not found")
@@ -254,7 +254,7 @@ class InMemoryState(State): # pylint: disable=R0902,R0904
254
254
  del self.node_ids[node_id]
255
255
 
256
256
  def get_nodes(self, run_id: int) -> Set[int]:
257
- """Return all available client nodes.
257
+ """Return all available nodes.
258
258
 
259
259
  Constraints
260
260
  -----------
@@ -271,9 +271,9 @@ class InMemoryState(State): # pylint: disable=R0902,R0904
271
271
  if online_until > current_time
272
272
  }
273
273
 
274
- def get_node_id(self, client_public_key: bytes) -> Optional[int]:
275
- """Retrieve stored `node_id` filtered by `client_public_keys`."""
276
- return self.public_key_to_node_id.get(client_public_key)
274
+ def get_node_id(self, node_public_key: bytes) -> Optional[int]:
275
+ """Retrieve stored `node_id` filtered by `node_public_keys`."""
276
+ return self.public_key_to_node_id.get(node_public_key)
277
277
 
278
278
  def create_run(
279
279
  self,
@@ -318,19 +318,19 @@ class InMemoryState(State): # pylint: disable=R0902,R0904
318
318
  """Retrieve `server_public_key` in urlsafe bytes."""
319
319
  return self.server_public_key
320
320
 
321
- def store_client_public_keys(self, public_keys: Set[bytes]) -> None:
322
- """Store a set of `client_public_keys` in state."""
321
+ def store_node_public_keys(self, public_keys: Set[bytes]) -> None:
322
+ """Store a set of `node_public_keys` in state."""
323
323
  with self.lock:
324
- self.client_public_keys = public_keys
324
+ self.node_public_keys = public_keys
325
325
 
326
- def store_client_public_key(self, public_key: bytes) -> None:
327
- """Store a `client_public_key` in state."""
326
+ def store_node_public_key(self, public_key: bytes) -> None:
327
+ """Store a `node_public_key` in state."""
328
328
  with self.lock:
329
- self.client_public_keys.add(public_key)
329
+ self.node_public_keys.add(public_key)
330
330
 
331
- def get_client_public_keys(self) -> Set[bytes]:
332
- """Retrieve all currently stored `client_public_keys` as a set."""
333
- return self.client_public_keys
331
+ def get_node_public_keys(self) -> Set[bytes]:
332
+ """Retrieve all currently stored `node_public_keys` as a set."""
333
+ return self.node_public_keys
334
334
 
335
335
  def get_run(self, run_id: int) -> Optional[Run]:
336
336
  """Retrieve information about the run with the specified `run_id`."""
@@ -569,7 +569,7 @@ class SqliteState(State): # pylint: disable=R0904
569
569
  return node_id
570
570
 
571
571
  def delete_node(self, node_id: int, public_key: Optional[bytes] = None) -> None:
572
- """Delete a client node."""
572
+ """Delete a node."""
573
573
  query = "DELETE FROM node WHERE node_id = ?"
574
574
  params = (node_id,)
575
575
 
@@ -607,10 +607,10 @@ class SqliteState(State): # pylint: disable=R0904
607
607
  result: Set[int] = {row["node_id"] for row in rows}
608
608
  return result
609
609
 
610
- def get_node_id(self, client_public_key: bytes) -> Optional[int]:
611
- """Retrieve stored `node_id` filtered by `client_public_keys`."""
610
+ def get_node_id(self, node_public_key: bytes) -> Optional[int]:
611
+ """Retrieve stored `node_id` filtered by `node_public_keys`."""
612
612
  query = "SELECT node_id FROM node WHERE public_key = :public_key;"
613
- row = self.query(query, {"public_key": client_public_key})
613
+ row = self.query(query, {"public_key": node_public_key})
614
614
  if len(row) > 0:
615
615
  node_id: int = row[0]["node_id"]
616
616
  return node_id
@@ -684,19 +684,19 @@ class SqliteState(State): # pylint: disable=R0904
684
684
  public_key = None
685
685
  return public_key
686
686
 
687
- def store_client_public_keys(self, public_keys: Set[bytes]) -> None:
688
- """Store a set of `client_public_keys` in state."""
687
+ def store_node_public_keys(self, public_keys: Set[bytes]) -> None:
688
+ """Store a set of `node_public_keys` in state."""
689
689
  query = "INSERT INTO public_key (public_key) VALUES (?)"
690
690
  data = [(key,) for key in public_keys]
691
691
  self.query(query, data)
692
692
 
693
- def store_client_public_key(self, public_key: bytes) -> None:
694
- """Store a `client_public_key` in state."""
693
+ def store_node_public_key(self, public_key: bytes) -> None:
694
+ """Store a `node_public_key` in state."""
695
695
  query = "INSERT INTO public_key (public_key) VALUES (:public_key)"
696
696
  self.query(query, {"public_key": public_key})
697
697
 
698
- def get_client_public_keys(self) -> Set[bytes]:
699
- """Retrieve all currently stored `client_public_keys` as a set."""
698
+ def get_node_public_keys(self) -> Set[bytes]:
699
+ """Retrieve all currently stored `node_public_keys` as a set."""
700
700
  query = "SELECT public_key FROM public_key"
701
701
  rows = self.query(query)
702
702
  result: Set[bytes] = {row["public_key"] for row in rows}
@@ -153,8 +153,8 @@ class State(abc.ABC): # pylint: disable=R0904
153
153
  """
154
154
 
155
155
  @abc.abstractmethod
156
- def get_node_id(self, client_public_key: bytes) -> Optional[int]:
157
- """Retrieve stored `node_id` filtered by `client_public_keys`."""
156
+ def get_node_id(self, node_public_key: bytes) -> Optional[int]:
157
+ """Retrieve stored `node_id` filtered by `node_public_keys`."""
158
158
 
159
159
  @abc.abstractmethod
160
160
  def create_run(
@@ -199,16 +199,16 @@ class State(abc.ABC): # pylint: disable=R0904
199
199
  """Retrieve `server_public_key` in urlsafe bytes."""
200
200
 
201
201
  @abc.abstractmethod
202
- def store_client_public_keys(self, public_keys: Set[bytes]) -> None:
203
- """Store a set of `client_public_keys` in state."""
202
+ def store_node_public_keys(self, public_keys: Set[bytes]) -> None:
203
+ """Store a set of `node_public_keys` in state."""
204
204
 
205
205
  @abc.abstractmethod
206
- def store_client_public_key(self, public_key: bytes) -> None:
207
- """Store a `client_public_key` in state."""
206
+ def store_node_public_key(self, public_key: bytes) -> None:
207
+ """Store a `node_public_key` in state."""
208
208
 
209
209
  @abc.abstractmethod
210
- def get_client_public_keys(self) -> Set[bytes]:
211
- """Retrieve all currently stored `client_public_keys` as a set."""
210
+ def get_node_public_keys(self) -> Set[bytes]:
211
+ """Retrieve all currently stored `node_public_keys` as a set."""
212
212
 
213
213
  @abc.abstractmethod
214
214
  def acknowledge_ping(self, node_id: int, ping_interval: float) -> bool:
@@ -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 the `client_resources` could help.",
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 'client_resources' passed to `start_simulation`"
134
+ "Check `num_cpus` and/or `num_gpus` passed to the simulation engine"
135
135
  )
136
136
 
137
137
  return total_num_actors
@@ -109,6 +109,11 @@ def run_simulation_from_cli() -> None:
109
109
  """Run Simulation Engine from the CLI."""
110
110
  args = _parse_args_run_simulation().parse_args()
111
111
 
112
+ event(
113
+ EventType.CLI_FLOWER_SIMULATION_ENTER,
114
+ event_details={"backend": args.backend, "num-supernodes": args.num_supernodes},
115
+ )
116
+
112
117
  # Add warnings for deprecated server_app and client_app arguments
113
118
  if args.server_app:
114
119
  warn_deprecated_feature(
@@ -177,7 +182,9 @@ def run_simulation_from_cli() -> None:
177
182
  client_app_attr = app_components["clientapp"]
178
183
  server_app_attr = app_components["serverapp"]
179
184
 
180
- override_config = parse_config_args([args.run_config])
185
+ override_config = parse_config_args(
186
+ [args.run_config] if args.run_config else args.run_config
187
+ )
181
188
  fused_config = get_fused_config_from_dir(app_path, override_config)
182
189
  app_dir = args.app
183
190
  is_app = True
@@ -209,9 +216,11 @@ def run_simulation_from_cli() -> None:
209
216
  app_dir=app_dir,
210
217
  run=run,
211
218
  enable_tf_gpu_growth=args.enable_tf_gpu_growth,
219
+ delay_start=args.delay_start,
212
220
  verbose_logging=args.verbose,
213
221
  server_app_run_config=fused_config,
214
222
  is_app=is_app,
223
+ exit_event=EventType.CLI_FLOWER_SIMULATION_LEAVE,
215
224
  )
216
225
 
217
226
 
@@ -265,6 +274,11 @@ def run_simulation(
265
274
  When disabled, only INFO, WARNING and ERROR log messages will be shown. If
266
275
  enabled, DEBUG-level logs will be displayed.
267
276
  """
277
+ event(
278
+ EventType.PYTHON_API_RUN_SIMULATION_ENTER,
279
+ event_details={"backend": backend_name, "num-supernodes": num_supernodes},
280
+ )
281
+
268
282
  if enable_tf_gpu_growth:
269
283
  warn_deprecated_feature_with_example(
270
284
  "Passing `enable_tf_gpu_growth=True` is deprecated.",
@@ -282,6 +296,7 @@ def run_simulation(
282
296
  backend_config=backend_config,
283
297
  enable_tf_gpu_growth=enable_tf_gpu_growth,
284
298
  verbose_logging=verbose_logging,
299
+ exit_event=EventType.PYTHON_API_RUN_SIMULATION_LEAVE,
285
300
  )
286
301
 
287
302
 
@@ -295,7 +310,6 @@ def run_serverapp_th(
295
310
  f_stop: threading.Event,
296
311
  has_exception: threading.Event,
297
312
  enable_tf_gpu_growth: bool,
298
- delay_launch: int = 3,
299
313
  ) -> threading.Thread:
300
314
  """Run SeverApp in a thread."""
301
315
 
@@ -351,7 +365,6 @@ def run_serverapp_th(
351
365
  server_app,
352
366
  ),
353
367
  )
354
- sleep(delay_launch)
355
368
  serverapp_th.start()
356
369
  return serverapp_th
357
370
 
@@ -365,6 +378,8 @@ def _main_loop(
365
378
  is_app: bool,
366
379
  enable_tf_gpu_growth: bool,
367
380
  run: Run,
381
+ exit_event: EventType,
382
+ delay_start: int,
368
383
  flwr_dir: Optional[str] = None,
369
384
  client_app: Optional[ClientApp] = None,
370
385
  client_app_attr: Optional[str] = None,
@@ -372,7 +387,7 @@ def _main_loop(
372
387
  server_app_attr: Optional[str] = None,
373
388
  server_app_run_config: Optional[UserConfig] = None,
374
389
  ) -> None:
375
- """Launch SuperLink with Simulation Engine, then ServerApp on a separate thread."""
390
+ """Start ServerApp on a separate thread, then launch Simulation Engine."""
376
391
  # Initialize StateFactory
377
392
  state_factory = StateFactory(":flwr-in-memory-state:")
378
393
 
@@ -380,6 +395,7 @@ def _main_loop(
380
395
  # A Threading event to indicate if an exception was raised in the ServerApp thread
381
396
  server_app_thread_has_exception = threading.Event()
382
397
  serverapp_th = None
398
+ success = True
383
399
  try:
384
400
  # Register run
385
401
  log(DEBUG, "Pre-registering run with id %s", run.run_id)
@@ -403,8 +419,10 @@ def _main_loop(
403
419
  enable_tf_gpu_growth=enable_tf_gpu_growth,
404
420
  )
405
421
 
406
- # SuperLink with Simulation Engine
407
- event(EventType.RUN_SUPERLINK_ENTER)
422
+ # Buffer time so the `ServerApp` in separate thread is ready
423
+ log(DEBUG, "Buffer time delay: %ds", delay_start)
424
+ sleep(delay_start)
425
+ # Start Simulation Engine
408
426
  vce.start_vce(
409
427
  num_supernodes=num_supernodes,
410
428
  client_app_attr=client_app_attr,
@@ -422,13 +440,13 @@ def _main_loop(
422
440
  except Exception as ex:
423
441
  log(ERROR, "An exception occurred !! %s", ex)
424
442
  log(ERROR, traceback.format_exc())
443
+ success = False
425
444
  raise RuntimeError("An error was encountered. Ending simulation.") from ex
426
445
 
427
446
  finally:
428
447
  # Trigger stop event
429
448
  f_stop.set()
430
-
431
- event(EventType.RUN_SUPERLINK_LEAVE)
449
+ event(exit_event, event_details={"success": success})
432
450
  if serverapp_th:
433
451
  serverapp_th.join()
434
452
  if server_app_thread_has_exception.is_set():
@@ -440,6 +458,7 @@ def _main_loop(
440
458
  # pylint: disable=too-many-arguments,too-many-locals
441
459
  def _run_simulation(
442
460
  num_supernodes: int,
461
+ exit_event: EventType,
443
462
  client_app: Optional[ClientApp] = None,
444
463
  server_app: Optional[ServerApp] = None,
445
464
  backend_name: str = "ray",
@@ -451,6 +470,7 @@ def _run_simulation(
451
470
  flwr_dir: Optional[str] = None,
452
471
  run: Optional[Run] = None,
453
472
  enable_tf_gpu_growth: bool = False,
473
+ delay_start: int = 5,
454
474
  verbose_logging: bool = False,
455
475
  is_app: bool = False,
456
476
  ) -> None:
@@ -506,6 +526,8 @@ def _run_simulation(
506
526
  is_app,
507
527
  enable_tf_gpu_growth,
508
528
  run,
529
+ exit_event,
530
+ delay_start,
509
531
  flwr_dir,
510
532
  client_app,
511
533
  client_app_attr,
@@ -593,6 +615,13 @@ def _parse_args_run_simulation() -> argparse.ArgumentParser:
593
615
  "Read more about how `tf.config.experimental.set_memory_growth()` works in "
594
616
  "the TensorFlow documentation: https://www.tensorflow.org/api/stable.",
595
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
+ )
596
625
  parser.add_argument(
597
626
  "--verbose",
598
627
  action="store_true",
@@ -13,9 +13,3 @@
13
13
  # limitations under the License.
14
14
  # ==============================================================================
15
15
  """Flower SuperExec service."""
16
-
17
- from .app import run_superexec as run_superexec
18
-
19
- __all__ = [
20
- "run_superexec",
21
- ]
flwr/superexec/app.py CHANGED
@@ -25,7 +25,7 @@ import grpc
25
25
  from flwr.common import EventType, event, log
26
26
  from flwr.common.address import parse_address
27
27
  from flwr.common.config import parse_config_args
28
- from flwr.common.constant import SUPEREXEC_DEFAULT_ADDRESS
28
+ from flwr.common.constant import EXEC_API_DEFAULT_ADDRESS
29
29
  from flwr.common.exit_handlers import register_exit_handlers
30
30
  from flwr.common.object_ref import load_app, validate
31
31
 
@@ -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([args.executor_config]),
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]
@@ -79,7 +81,7 @@ def _parse_args_run_superexec() -> argparse.ArgumentParser:
79
81
  parser.add_argument(
80
82
  "--address",
81
83
  help="SuperExec (gRPC) server address (IPv4, IPv6, or a domain name)",
82
- default=SUPEREXEC_DEFAULT_ADDRESS,
84
+ default=EXEC_API_DEFAULT_ADDRESS,
83
85
  )
84
86
  parser.add_argument(
85
87
  "--executor",
@@ -23,13 +23,13 @@ from typing import Optional
23
23
  from typing_extensions import override
24
24
 
25
25
  from flwr.cli.install import install_from_fab
26
+ from flwr.common.constant import DRIVER_API_DEFAULT_ADDRESS
26
27
  from flwr.common.grpc import create_channel
27
28
  from flwr.common.logger import log
28
29
  from flwr.common.serde import fab_to_proto, user_config_to_proto
29
30
  from flwr.common.typing import Fab, UserConfig
30
31
  from flwr.proto.driver_pb2 import CreateRunRequest # pylint: disable=E0611
31
32
  from flwr.proto.driver_pb2_grpc import DriverStub
32
- from flwr.server.driver.grpc_driver import DEFAULT_SERVER_ADDRESS_DRIVER
33
33
 
34
34
  from .executor import Executor, RunTracker
35
35
 
@@ -50,7 +50,7 @@ class DeploymentEngine(Executor):
50
50
 
51
51
  def __init__(
52
52
  self,
53
- superlink: str = DEFAULT_SERVER_ADDRESS_DRIVER,
53
+ superlink: str = DRIVER_API_DEFAULT_ADDRESS,
54
54
  root_certificates: Optional[str] = None,
55
55
  flwr_dir: Optional[str] = None,
56
56
  ) -> None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flwr-nightly
3
- Version: 1.11.0.dev20240823
3
+ Version: 1.11.1.dev20240912
4
4
  Summary: Flower: A Friendly Federated Learning Framework
5
5
  Home-page: https://flower.ai
6
6
  License: Apache-2.0
@@ -195,8 +195,8 @@ Other [examples](https://github.com/adap/flower/tree/main/examples):
195
195
  - [PyTorch: From Centralized to Federated](https://github.com/adap/flower/tree/main/examples/pytorch-from-centralized-to-federated)
196
196
  - [Vertical FL](https://github.com/adap/flower/tree/main/examples/vertical-fl)
197
197
  - [Federated Finetuning of OpenAI's Whisper](https://github.com/adap/flower/tree/main/examples/whisper-federated-finetuning)
198
- - [Federated Finetuning of Large Language Model](https://github.com/adap/flower/tree/main/examples/llm-flowertune)
199
- - [Federated Finetuning of a Vision Transformer](https://github.com/adap/flower/tree/main/examples/vit-finetune)
198
+ - [Federated Finetuning of Large Language Model](https://github.com/adap/flower/tree/main/examples/flowertune-llm)
199
+ - [Federated Finetuning of a Vision Transformer](https://github.com/adap/flower/tree/main/examples/flowertune-vit)
200
200
  - [Advanced Flower with TensorFlow/Keras](https://github.com/adap/flower/tree/main/examples/advanced-tensorflow)
201
201
  - [Advanced Flower with PyTorch](https://github.com/adap/flower/tree/main/examples/advanced-pytorch)
202
202
  - 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))