FL Client over Secure RPCΒΆ
In this notebook, we will present how to launch a gRPC client as an FL client with an authenticator. To pair with the server notebook, we consider only one client.
[1]:
num_clients = 1
Load client configurationsΒΆ
We load the configuration for the client from examples/resources/configs/mnist/client_1.yaml
[2]:
from omegaconf import OmegaConf
client_config_file = "../../examples/resources/configs/mnist/client_1.yaml"
client_config = OmegaConf.load(client_config_file)
print(OmegaConf.to_yaml(client_config))
client_id: Client1
train_configs:
device: cpu
logging_output_dirname: ./output
logging_output_filename: result
data_configs:
dataset_path: ./resources/dataset/mnist_dataset.py
dataset_name: get_mnist
dataset_kwargs:
num_clients: 2
client_id: 0
partition_strategy: class_noniid
visualization: true
output_dirname: ./output
output_filename: visualization.pdf
comm_configs:
grpc_configs:
server_uri: localhost:50051
max_message_size: 1048576
use_ssl: false
π‘ We need to change the relative path in data_configs.dataset_path to point to the right file relative to this notebook.
π‘ We also need to change data_configs.dataset_kwargs.num_clients to 1 to make sure we only partition the MNIST dataset to one client split. We change data_configs.dataset_kwargs.visualization to False as well.
[3]:
client_config.data_configs.dataset_path = (
"../../examples/resources/dataset/mnist_dataset.py"
)
client_config.data_configs.dataset_kwargs.num_clients = num_clients
client_config.data_configs.dataset_kwargs.visualization = False
Create secure SSL channel and authenticatorΒΆ
The client requires a root certificate to verify the server certificate. In this example, we provide that root certificate, assuming that the server uses self-signed certificate and key provided by gRPC official documentation.
π‘ Please check this tutorial for more details on how to generate SSL certificates for securing the gRPC connections in practice.
To use the provided root certificate, user just to need to set the following. If the user would like to use his own root certificate, just change this to the file path to the local root certificate.
[4]:
client_config.comm_configs.grpc_configs.use_ssl = True
client_config.comm_configs.grpc_configs.root_certificate = (
"../../src/appfl/comm/grpc/credentials/root.crt"
)
We also need to set configurations to use the naive authenticator and provide the auth_token agreed with the server for authentication.
[5]:
client_config.comm_configs.grpc_configs.use_authenticator = True
client_config.comm_configs.grpc_configs.authenticator = "NaiveAuthenticator"
client_config.comm_configs.grpc_configs.authenticator_args = {
"auth_token": "A_SECRET_DEMO_TOKEN"
}
Create the client agent and communicatorΒΆ
Now we are ready to create the client agent using the client_agent defined and modified above, as well as a GRPCClientCommunicator to send request to the server.
β οΈ Please make sure that you have started the server from the other notebook!
[6]:
from appfl.agent import ClientAgent
from appfl.comm.grpc import GRPCClientCommunicator
client_agent = ClientAgent(client_agent_config=client_config)
client_communicator = GRPCClientCommunicator(
client_id=client_agent.get_id(),
**client_config.comm_configs.grpc_configs,
)
appfl: β
[2025-01-08 09:56:31,188 Client1]: Logging to ./output/result_Client1_2025-01-08-09-56-31.txt
Start the FL experimentΒΆ
Client start the FL experiment by doing the following things:
Obtain general client-side configurations from the server and load them
Obtain the initial global model from the server
[Optional] Send the number of local data to the server
Iteratively train the model and update the global model until receiving a
DONEstatus flag from the server.
π‘ The server is also logging several information regarding the recipe of client requests.
[7]:
# Obtain general client-side configurations from the server and load them
client_config = client_communicator.get_configuration()
client_agent.load_config(client_config)
# Obtain the initial global model from the server
init_global_model = client_communicator.get_global_model(init_model=True)
client_agent.load_parameters(init_global_model)
# Send the number of local data to the server
sample_size = client_agent.get_sample_size()
client_communicator.invoke_custom_action(
action="set_sample_size", sample_size=sample_size
)
while True:
client_agent.train()
local_model = client_agent.get_parameters()
if isinstance(local_model, tuple):
local_model, meta_data_local = local_model[0], local_model[1]
else:
meta_data_local = {}
new_global_model, metadata = client_communicator.update_global_model(
local_model, **meta_data_local
)
if metadata["status"] == "DONE":
break
client_agent.load_parameters(new_global_model)
client_communicator.invoke_custom_action(action="close_connection")
appfl: β
[2025-01-08 09:56:38,152 Client1]: Round Pre Val? Time Train Loss Train Accuracy Val Loss Val Accuracy
appfl: β
[2025-01-08 09:56:39,176 Client1]: 0 Y 2.3006 15.9300
appfl: β
[2025-01-08 09:56:42,203 Client1]: 0 N 3.0259 0.0621 82.6719 0.1759 94.5900
appfl: β
[2025-01-08 09:56:43,288 Client1]: 1 Y 0.1759 94.5900
appfl: β
[2025-01-08 09:56:46,287 Client1]: 1 N 2.9982 0.0181 94.7969 0.1036 96.7900
appfl: β
[2025-01-08 09:56:47,328 Client1]: 2 Y 0.1036 96.7900
appfl: β
[2025-01-08 09:56:50,102 Client1]: 2 N 2.7733 0.0125 96.4062 0.0782 97.5500
appfl: β
[2025-01-08 09:56:51,153 Client1]: 3 Y 0.0782 97.5500
appfl: β
[2025-01-08 09:56:54,004 Client1]: 3 N 2.8507 0.0100 97.1719 0.0651 97.9100
appfl: β
[2025-01-08 09:56:55,064 Client1]: 4 Y 0.0651 97.9100
appfl: β
[2025-01-08 09:56:58,036 Client1]: 4 N 2.9708 0.0081 97.6406 0.0603 98.0500
appfl: β
[2025-01-08 09:56:59,089 Client1]: 5 Y 0.0603 98.0500
appfl: β
[2025-01-08 09:57:01,960 Client1]: 5 N 2.8703 0.0072 97.9531 0.0503 98.4800
appfl: β
[2025-01-08 09:57:03,026 Client1]: 6 Y 0.0503 98.4800
appfl: β
[2025-01-08 09:57:05,943 Client1]: 6 N 2.9161 0.0065 98.0000 0.0406 98.7400
appfl: β
[2025-01-08 09:57:07,040 Client1]: 7 Y 0.0406 98.7400
appfl: β
[2025-01-08 09:57:09,872 Client1]: 7 N 2.8316 0.0052 98.3906 0.0523 98.3900
appfl: β
[2025-01-08 09:57:10,958 Client1]: 8 Y 0.0523 98.3900
appfl: β
[2025-01-08 09:57:13,716 Client1]: 8 N 2.7568 0.0065 98.0781 0.0383 98.7300
appfl: β
[2025-01-08 09:57:14,771 Client1]: 9 Y 0.0383 98.7300
appfl: β
[2025-01-08 09:57:17,594 Client1]: 9 N 2.8216 0.0049 98.6562 0.0402 98.7100
[7]:
{}