From 73c4f3885b60828fbbb92abb433f6bae92d611f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yuan-Ting=20Hsieh=20=28=E8=AC=9D=E6=B2=85=E5=BB=B7=29?= Date: Fri, 30 Aug 2024 16:19:00 -0700 Subject: [PATCH] Deprecate decorator pattern (#2891) * Deprecate client api decorator pattern * Update doc --- docs/programming_guide/execution_api_type.rst | 2 +- .../execution_api_type/client_api.rst | 18 ++++-------------- nvflare/client/decorator.py | 3 +++ .../app/custom/cifar10_structured_fl.py | 2 +- .../app/custom/cifar10_structured_fl.py | 2 +- 5 files changed, 10 insertions(+), 17 deletions(-) diff --git a/docs/programming_guide/execution_api_type.rst b/docs/programming_guide/execution_api_type.rst index 9f39978307..0f04d6d894 100644 --- a/docs/programming_guide/execution_api_type.rst +++ b/docs/programming_guide/execution_api_type.rst @@ -35,7 +35,7 @@ The :ref:`client_api` provides the most straightforward way to write FL code, and can easily be used to convert centralized code with minimal code changes. The Client API uses the :class:`FLModel` object for data transfer and supports common tasks such as train, validate, and submit_model. -Options for using decorators or PyTorch Lightning are also available. +Option for using PyTorch Lightning is also available. For Client API executors, the in-process and external-process executors are provided for different use cases. We recommend users start with the Client API, and to consider the other types diff --git a/docs/programming_guide/execution_api_type/client_api.rst b/docs/programming_guide/execution_api_type/client_api.rst index dee674477c..4b6f509aef 100644 --- a/docs/programming_guide/execution_api_type/client_api.rst +++ b/docs/programming_guide/execution_api_type/client_api.rst @@ -110,20 +110,6 @@ Below is a table overview of key Client APIs. - Returns whether the current task is a submit_model task. - :func:`is_submit_model` -.. list-table:: Decorator APIs - :widths: 25 25 50 - :header-rows: 1 - - * - API - - Description - - API Doc Link - * - train - - A decorator to wraps the training logic. - - :func:`train` - * - evaluate - - A decorator to wraps the evaluate logic. - - :func:`evaluate` - .. list-table:: Lightning APIs :widths: 25 25 50 :header-rows: 1 @@ -158,6 +144,10 @@ information about all of the Client API functionalities. If you are using PyTorch Lightning in your training code, you can check the Lightning API Module :mod:`nvflare.app_opt.lightning.api`. +.. note:: + The decorator API has been deprecated since release 2.5.0. + Please use the Client API instead. + Client API communication patterns ================================= diff --git a/nvflare/client/decorator.py b/nvflare/client/decorator.py index 4a8b47e890..7117e9c105 100644 --- a/nvflare/client/decorator.py +++ b/nvflare/client/decorator.py @@ -16,6 +16,7 @@ from inspect import signature from nvflare.app_common.abstract.fl_model import FLModel +from nvflare.fuel.utils.deprecated import deprecated from .api import is_train, receive, send @@ -34,6 +35,7 @@ def __init__(self): object_holder = ObjectHolder() +@deprecated("@flare.train is deprecated and will be removed in a future version." "Use flare send/receive instead.") def train( _func=None, **root_kwargs, @@ -86,6 +88,7 @@ def wrapper(*args, **kwargs): return decorator(_func) +@deprecated("@flare.evaluate is deprecated and will be removed in a future version." "Use flare send/receive instead.") def evaluate( _func=None, **root_kwargs, diff --git a/tests/integration_test/data/jobs/decorator/app/custom/cifar10_structured_fl.py b/tests/integration_test/data/jobs/decorator/app/custom/cifar10_structured_fl.py index 74aaf898f7..bd645bcd37 100644 --- a/tests/integration_test/data/jobs/decorator/app/custom/cifar10_structured_fl.py +++ b/tests/integration_test/data/jobs/decorator/app/custom/cifar10_structured_fl.py @@ -94,7 +94,7 @@ def train(input_model=None, total_epochs=2, lr=0.001): # (5) decorates with flare.evaluate and load model from the first argument @flare.evaluate def fl_evaluate(input_model=None): - return evaluate(input_weights=input_model.params) + return {"accuracy": evaluate(input_weights=input_model.params)} # wraps evaluate logic into a method def evaluate(input_weights): diff --git a/tests/integration_test/data/jobs/decorator_in_process/app/custom/cifar10_structured_fl.py b/tests/integration_test/data/jobs/decorator_in_process/app/custom/cifar10_structured_fl.py index 74aaf898f7..bd645bcd37 100644 --- a/tests/integration_test/data/jobs/decorator_in_process/app/custom/cifar10_structured_fl.py +++ b/tests/integration_test/data/jobs/decorator_in_process/app/custom/cifar10_structured_fl.py @@ -94,7 +94,7 @@ def train(input_model=None, total_epochs=2, lr=0.001): # (5) decorates with flare.evaluate and load model from the first argument @flare.evaluate def fl_evaluate(input_model=None): - return evaluate(input_weights=input_model.params) + return {"accuracy": evaluate(input_weights=input_model.params)} # wraps evaluate logic into a method def evaluate(input_weights):