Flower: A Friendly Federated AI Framework
Flower (flwr) is an open-source framework for building federated learning systems. It enables collaborative training of machine learning models across decentralized datasets without exchanging raw data. Currently at version 1.29.0, Flower maintains a rapid release cadence, often releasing minor versions monthly with new features and improvements.
Common errors
-
ModuleNotFoundError: No module named 'flower'
cause The Python package name for Flower is `flwr`, not `flower`.fixChange your import statements from `import flower` to `import flwr` and ensure you installed it using `pip install flwr`. -
AttributeError: 'Client' object has no attribute 'get_parameters' (or 'fit', 'evaluate', etc.)
cause You are attempting to use methods of a `flwr.client.Client` object (or a custom client) that are either not implemented, misspelled, or do not conform to the expected API for parameter exchange and federated operations.fixFor common use cases, subclass `flwr.client.NumPyClient` and override its methods (`get_parameters`, `set_parameters`, `fit`, `evaluate`). If implementing a custom client directly from `flwr.client.Client`, ensure all abstract methods are correctly implemented according to the latest API. -
ValueError: incompatible buffer format, expected 'float32', got 'float64'
cause A mismatch in the data types of NumPy arrays (e.g., `float32` vs `float64`) being exchanged between clients and the server, often due to how different ML frameworks (PyTorch, TensorFlow) handle default data types.fixExplicitly cast all NumPy arrays to the required `dtype` (e.g., `np.float32`) before returning them from client methods like `get_parameters`, `fit`, or `evaluate`. For example: `[v.astype(np.float32) for v in self.model.values()]`. -
grpc._channel._MultiThreadedRendezvous: <_MultiThreadedRendezvous of RPC that terminated with status StatusCode.UNAVAILABLE (or similar connection errors)>
cause The client failed to connect to the Flower server. This could be due to the server not running, an incorrect server address/port, network issues, or a firewall blocking the connection.fixVerify that the Flower server is running and listening on the specified `server_address` (e.g., `127.0.0.1:8080`). Check network connectivity, ensure no firewall is blocking the port, and confirm the port is not already in use by another application. For local testing, ensure the client and server use the exact same address and port. -
ImportError: cannot import name 'xyz' from 'flwr.common'
cause Attempting to import a symbol (e.g., `NDArrays`, `Parameters`) that has been removed or deprecated in favor of the new `Message` API, or has been moved to a different module.fixConsult the `flwr` documentation for the latest API. For parameter exchange, use `flwr.common.Message` or rely on `NumPyClient` which abstracts this. If a symbol was moved, search the documentation or `flwr` source code for its new location.
Warnings
- breaking Flower has migrated its internal communication and strategy APIs from using raw `NDArrays` (lists of NumPy arrays) to a more flexible `Message` API. Older code that directly manipulated `NDArrays` for parameter exchange or implemented custom strategies without the `Message` API will need significant updates.
- gotcha Flower's base installation (`pip install flwr`) does not include machine learning framework dependencies. If you intend to use PyTorch, TensorFlow, or JAX, you must install Flower with the appropriate optional dependencies, otherwise you will encounter `ModuleNotFoundError`.
- gotcha Flower requires Python version `>=3.10` and `<4.0`. Using an incompatible Python interpreter (e.g., Python 3.9 or Python 4.0+) will lead to installation failures, runtime errors, or unexpected behavior.
- breaking The `flwr` CLI has undergone several changes, including the introduction of centralized configuration via a `pyproject.toml` or `flwr.json` file. Old command-line arguments and script patterns for starting servers or simulations might no longer work as expected.
Install
-
pip install flwr -
pip install 'flwr[torch]' -
pip install 'flwr[tensorflow]' -
pip install 'flwr[jax]'
Imports
- start_server
from flwr.server import start_server
- start_client
from flwr.client import start_client
- start_simulation
from flwr.simulation import start_simulation
- Client
from flwr.client import Client
- NumPyClient
from flwr.client import NumPyClient
- Strategy
from flwr.server.strategy import Strategy
- FedAvg
from flwr.server.strategy import FedAvg
- Message
from flwr.common import NDArrays
from flwr.common import Message
Quickstart
import flwr as fw
import numpy as np
from collections import OrderedDict
# 1. Define a Flower Client (inheriting from NumPyClient)
class CifarClient(fw.client.NumPyClient):
def __init__(self):
# In a real scenario, you'd load your actual ML model here
# For this quickstart, we'll use a dummy model with NumPy arrays.
self.model = {
"layer1": np.random.rand(10, 10).astype(np.float32),
"layer2": np.random.rand(10, 1).astype(np.float32)
}
def get_parameters(self, config):
"""Return model parameters as a list of NumPy arrays."""
return [v for v in self.model.values()]
def set_parameters(self, parameters):
"""Set model parameters from a list of NumPy arrays."""
params_dict = zip(self.model.keys(), parameters)
self.model = OrderedDict({k: v for k, v in params_dict})
def fit(self, parameters, config):
"""Simulate training and return updated parameters, number of examples, and metrics."""
self.set_parameters(parameters)
# Simulate training: update weights slightly
new_weights = {k: v + np.random.rand(*v.shape).astype(np.float32) * 0.1 for k, v in self.model.items()}
self.model = OrderedDict(new_weights)
num_examples = 100
metrics = {"accuracy": float(np.random.rand())}
return self.get_parameters({}), num_examples, metrics
def evaluate(self, parameters, config):
"""Simulate evaluation and return loss, number of examples, and metrics."""
self.set_parameters(parameters)
# Simulate evaluation
loss = float(np.random.rand() * 0.5 + 0.5) # Loss between 0.5 and 1.0
accuracy = float(np.random.rand() * 0.2 + 0.7) # Accuracy between 0.7 and 0.9
num_examples = 50
return loss, num_examples, {"accuracy": accuracy}
# 2. Define a Flower Server Strategy
# FedAvg (Federated Averaging) is a common choice.
strategy = fw.server.strategy.FedAvg(
fraction_fit=1.0, # Sample 100% of available clients for training
fraction_evaluate=1.0, # Sample 100% of available clients for evaluation
min_fit_clients=2, # Wait for at least 2 clients to participate in fit
min_evaluate_clients=2, # Wait for at least 2 clients to participate in evaluate
min_available_clients=2, # Total number of clients that need to be connected
)
# 3. Define the client factory function for the simulation
def client_fn(cid: str):
"""Returns a Flower Client for a given client ID."""
print(f"Creating client {cid}...")
return CifarClient().to_client()
# 4. Start the Flower Simulation
print("Starting Flower simulation with 2 clients for 3 rounds...")
fw.simulation.start_simulation(
client_fn=client_fn,
num_clients=2,
config=fw.server.ServerConfig(num_rounds=3),
strategy=strategy,
)
print("Simulation finished.")