Upgrade to Flower Next¶
Welcome to the migration guide for updating Flower to Flower Next! Whether you’re a seasoned user or just getting started, this guide will help you smoothly transition your existing setup to take advantage of the latest features and improvements in Flower Next, starting from version 1.8.
Note
This guide shows how to reuse pre-1.8
Flower code with minimum code changes by
using the compatibility layer in Flower Next. In another guide, we will show how
to run Flower Next end-to-end with pure Flower Next APIs.
Let’s dive in!
Installer la mise à jour¶
Using pip¶
Here’s how to update an existing installation of Flower to Flower Next with pip
:
$ python -m pip install -U flwr
or if you need Flower Next with simulation:
$ python -m pip install -U "flwr[simulation]"
Ensure you set the following version constraint in your requirements.txt
# Without simulation support
flwr>=1.8,<2.0
# With simulation support
flwr[simulation]>=1.8, <2.0
or pyproject.toml
:
# Without simulation support
dependencies = ["flwr>=1.8,2.0"]
# With simulation support
dependencies = ["flwr[simulation]>=1.8,2.0"]
Using Poetry¶
Update the flwr
dependency in pyproject.toml
and then reinstall (don’t forget to
delete poetry.lock
via rm poetry.lock
before running poetry install
).
Ensure you set the following version constraint in your pyproject.toml
:
[tool.poetry.dependencies]
python = "^3.9"
# Without simulation support
flwr = ">=1.8,<2.0"
# With simulation support
flwr = { version = ">=1.8,<2.0", extras = ["simulation"] }
Changements nécessaires¶
In Flower Next, the infrastructure and application layers have been decoupled.
Instead of starting a client in code via start_client()
, you create a
ClientApp()
and start it via the command line. Instead of starting a server in
code via start_server()
, you create a ServerApp()
and start it via the command
line. The long-running components of server and client are called SuperLink and
SuperNode. The following non-breaking changes that require manual updates and allow you
to run your project both in the traditional way and in the Flower Next way:
ClientApp()
¶
Wrap your existing client with
ClientApp()
instead of launching it viastart_client()
. Here’s an example:
# Flower 1.8
def client_fn(cid: str):
return flwr.client.FlowerClient().to_client()
app = flwr.client.ClientApp(
client_fn=client_fn,
)
# Flower 1.7
if __name__ == "__main__":
flwr.client.start_client(
server_address="127.0.0.1:8080",
client=flwr.client.FlowerClient().to_client(),
)
ServerApp()
¶
Wrap your existing strategy with
ServerApp()
instead of starting the server viastart_server()
. Here’s an example:
# Flower 1.8
app = flwr.server.ServerApp(
config=config,
strategy=strategy,
)
# Flower 1.7
if __name__ == "__main__":
flwr.server.start_server(
server_address="0.0.0.0:8080",
config=config,
strategy=strategy,
)
Deployment¶
Run the
SuperLink
usingflower-superlink
before running, in sequence,flower-client-app
(2x) andflower-server-app
. There is no need to execute client.py and server.py as Python scripts.Here’s an example to start the server without HTTPS (only for prototyping):
# Start a Superlink
$ flower-superlink --insecure
# In a new terminal window, start a long-running SuperNode
$ flower-client-app client:app --insecure
# In another terminal window, start another long-running SuperNode (at least 2 SuperNodes are required)
$ flower-client-app client:app --insecure
# In yet another terminal window, run the ServerApp (this starts the actual training run)
$ flower-server-app server:app --insecure
Here’s another example to start with HTTPS. Use the
--ssl-ca-certfile
,--ssl-certfile
, and--ssl-keyfile
command line options to pass paths to (CA certificate, server certificate, and server private key).
# Start a secure Superlink
$ flower-superlink \
--ssl-ca-certfile <your-ca-cert-filepath> \
--ssl-certfile <your-server-cert-filepath> \
--ssl-keyfile <your-privatekey-filepath>
# In a new terminal window, start a long-running secure SuperNode
$ flower-client-app client:app \
--root-certificates <your-ca-cert-filepath> \
--superlink 127.0.0.1:9092
# In another terminal window, start another long-running secure SuperNode (at least 2 SuperNodes are required)
$ flower-client-app client:app \
--root-certificates <your-ca-cert-filepath> \
--superlink 127.0.0.1:9092
# In yet another terminal window, run the ServerApp (this starts the actual training run)
$ flower-server-app server:app \
--root-certificates <your-ca-cert-filepath> \
--superlink 127.0.0.1:9091
Simulation in CLI¶
Wrap your existing client and strategy with
ClientApp()
andServerApp()
, respectively. There is no need to usestart_simulation()
anymore. Here’s an example:
# Regular Flower client implementation
class FlowerClient(NumPyClient):
# ...
pass
# Flower 1.8
def client_fn(cid: str):
return FlowerClient().to_client()
client_app = flwr.client.ClientApp(
client_fn=client_fn,
)
server_app = flwr.server.ServerApp(
config=config,
strategy=strategy,
)
# Flower 1.7
if __name__ == "__main__":
hist = flwr.simulation.start_simulation(
num_clients=100,
# ...
)
Run
flower-simulation
in CLI and point to theserver_app
/client_app
object in the code instead of executing the Python script. Here’s an example (assuming theserver_app
andclient_app
objects are in asim.py
module):
# Flower 1.8
$ flower-simulation \
--server-app=sim:server_app \
--client-app=sim:client_app \
--num-supernodes=100
# Flower 1.7
$ python sim.py
Set default resources for each
ClientApp()
using the--backend-config
command line argument instead of setting theclient_resources
argument instart_simulation()
. Here’s an example:
# Flower 1.8
$ flower-simulation \
--client-app=sim:client_app \
--server-app=sim:server_app \
--num-supernodes=100 \
--backend-config='{"client_resources": {"num_cpus": 2, "num_gpus": 0.25}}'
# Flower 1.7 (in `sim.py`)
if __name__ == "__main__":
hist = flwr.simulation.start_simulation(
num_clients=100, client_resources={"num_cpus": 2, "num_gpus": 0.25}, ...
)
Simulation in a Notebook¶
Run
run_simulation()
in your notebook instead ofstart_simulation()
. Here’s an example:
NUM_CLIENTS = 10 # Replace by any integer greater than zero
def client_fn(cid: str):
# ...
return FlowerClient().to_client()
client_app = flwr.client.ClientApp(
client_fn=client_fn,
)
server_app = flwr.server.ServerApp(
config=config,
strategy=strategy,
)
backend_config = {"client_resources": {"num_cpus": 2, "num_gpus": 0.25}}
# Flower 1.8
flwr.simulation.run_simulation(
server_app=server_app,
client_app=client_app,
num_supernodes=NUM_CLIENTS,
backend_config=backend_config,
)
# Flower 1.7
flwr.simulation.start_simulation(
client_fn=client_fn,
num_clients=NUM_CLIENTS,
config=config,
strategy=strategy,
client_resources=backend_config["client_resources"],
)
Aide supplémentaire¶
Some official Flower code examples are already
updated to Flower Next so they can serve as a reference for using the Flower Next API.
If there are further questions, join the Flower Slack
and use the channel #questions
. You can also participate in Flower Discuss where you can find us answering questions, or share and
learn from others about migrating to Flower Next.
Important
As we continuously enhance Flower Next at a rapid pace, we’ll be periodically updating this guide. Please feel free to share any feedback with us!
Happy migrating! 🚀