Skip to content

fl_server_api.serializers.model

Classes:

Name Description
ModelSerializer

A common serializer for the polymorphic Model class.

ModelSerializerNoWeights

A model serializer that excludes the model weights.

ModelSerializerNoWeightsWithStats

A model serializer that excludes the model weights but includes the model statistics.

Functions:

Name Description
load_and_create_model_request

Load and create a model from a Django request.

load_model_request

Load model data from a Django request.

verify_model_object

Verify the model object.

Attributes:

Name Type Description
GlobalModelSerializer
LocalModelSerializer
MeanModelSerializer
ModelFallbackSerializer
SWAGModelSerializer

Attributes

GlobalModelSerializer module-attribute

GlobalModelSerializer = _create_model_serializer(GlobalModel)

LocalModelSerializer module-attribute

LocalModelSerializer = _create_model_serializer(LocalModel)

MeanModelSerializer module-attribute

MeanModelSerializer = _create_model_serializer(MeanModel)

ModelFallbackSerializer module-attribute

ModelFallbackSerializer = _create_model_serializer(Model, name='ModelFallbackSerializer')

SWAGModelSerializer module-attribute

SWAGModelSerializer = _create_model_serializer(SWAGModel)

Classes

ModelSerializer

Bases: ModelSerializer


              flowchart TD
              fl_server_api.serializers.model.ModelSerializer[ModelSerializer]

              

              click fl_server_api.serializers.model.ModelSerializer href "" "fl_server_api.serializers.model.ModelSerializer"
            

A common serializer for the polymorphic Model class.

The model classes GlobalModel, LocalModel, MeanModel, and SWAGModel are supported.

Classes:

Name Description
Meta

Methods:

Name Description
get_serializer

Get the appropriate serializer based on the model type.

to_representation

Generate a dictionary representation of the corresponding model instance.

Source code in fl_server_api/serializers/model.py
class ModelSerializer(serializers.ModelSerializer):
    """
    A common serializer for the polymorphic Model class.

    The model classes `GlobalModel`, `LocalModel`, `MeanModel`, and `SWAGModel` are supported.
    """

    class Meta:
        model = Model
        exclude = ["polymorphic_ctype"]

    @classmethod
    def get_serializer(cls, model: Type[Model]):
        """
        Get the appropriate serializer based on the model type.

        Args:
            model (Type[Model]): The model class.

        Returns:
            Type[serializers.ModelSerializer]: The serializer class for the model.
        """
        if model == GlobalModel:
            return GlobalModelSerializer
        if model == LocalModel:
            return LocalModelSerializer
        if model == MeanModel:
            return MeanModelSerializer
        if model == SWAGModel:
            return SWAGModelSerializer
        getLogger("fl.server").warning(f"Using fallback model serializer for {model.__name__}")
        return ModelFallbackSerializer

    def to_representation(self, instance: Model):
        """
        Generate a dictionary representation of the corresponding model instance.

        Args:
            instance (Model): The Model instance.

        Returns:
            dict: The dictionary representation of the Model instance.
        """
        serializer = self.get_serializer(instance.__class__)
        return serializer(instance, context=self.context).data

Classes

Meta

Attributes:

Name Type Description
exclude
model
Source code in fl_server_api/serializers/model.py
class Meta:
    model = Model
    exclude = ["polymorphic_ctype"]
Attributes
exclude class-attribute instance-attribute
exclude = ['polymorphic_ctype']
model class-attribute instance-attribute
model = Model

Functions

get_serializer classmethod
get_serializer(model: Type[Model])

Get the appropriate serializer based on the model type.

Parameters:

Name Type Description Default
model
Type[Model]

The model class.

required

Returns:

Type Description

Type[serializers.ModelSerializer]: The serializer class for the model.

Source code in fl_server_api/serializers/model.py
@classmethod
def get_serializer(cls, model: Type[Model]):
    """
    Get the appropriate serializer based on the model type.

    Args:
        model (Type[Model]): The model class.

    Returns:
        Type[serializers.ModelSerializer]: The serializer class for the model.
    """
    if model == GlobalModel:
        return GlobalModelSerializer
    if model == LocalModel:
        return LocalModelSerializer
    if model == MeanModel:
        return MeanModelSerializer
    if model == SWAGModel:
        return SWAGModelSerializer
    getLogger("fl.server").warning(f"Using fallback model serializer for {model.__name__}")
    return ModelFallbackSerializer
to_representation
to_representation(instance: Model)

Generate a dictionary representation of the corresponding model instance.

Parameters:

Name Type Description Default
instance
Model

The Model instance.

required

Returns:

Name Type Description
dict

The dictionary representation of the Model instance.

Source code in fl_server_api/serializers/model.py
def to_representation(self, instance: Model):
    """
    Generate a dictionary representation of the corresponding model instance.

    Args:
        instance (Model): The Model instance.

    Returns:
        dict: The dictionary representation of the Model instance.
    """
    serializer = self.get_serializer(instance.__class__)
    return serializer(instance, context=self.context).data

ModelSerializerNoWeights

Bases: ModelSerializer


              flowchart TD
              fl_server_api.serializers.model.ModelSerializerNoWeights[ModelSerializerNoWeights]
              fl_server_api.serializers.model.ModelSerializer[ModelSerializer]

                              fl_server_api.serializers.model.ModelSerializer --> fl_server_api.serializers.model.ModelSerializerNoWeights
                


              click fl_server_api.serializers.model.ModelSerializerNoWeights href "" "fl_server_api.serializers.model.ModelSerializerNoWeights"
              click fl_server_api.serializers.model.ModelSerializer href "" "fl_server_api.serializers.model.ModelSerializer"
            

A model serializer that excludes the model weights.

Classes:

Name Description
Meta
Source code in fl_server_api/serializers/model.py
class ModelSerializerNoWeights(ModelSerializer):
    """
    A model serializer that excludes the model weights.
    """

    class Meta:
        model = Model
        exclude = ["polymorphic_ctype", "weights"]
        include = ["has_preprocessing"]

Classes

Meta

Attributes:

Name Type Description
exclude
include
model
Source code in fl_server_api/serializers/model.py
class Meta:
    model = Model
    exclude = ["polymorphic_ctype", "weights"]
    include = ["has_preprocessing"]
Attributes
exclude class-attribute instance-attribute
exclude = ['polymorphic_ctype', 'weights']
include class-attribute instance-attribute
include = ['has_preprocessing']
model class-attribute instance-attribute
model = Model

ModelSerializerNoWeightsWithStats

Bases: ModelSerializerNoWeights


              flowchart TD
              fl_server_api.serializers.model.ModelSerializerNoWeightsWithStats[ModelSerializerNoWeightsWithStats]
              fl_server_api.serializers.model.ModelSerializerNoWeights[ModelSerializerNoWeights]
              fl_server_api.serializers.model.ModelSerializer[ModelSerializer]

                              fl_server_api.serializers.model.ModelSerializerNoWeights --> fl_server_api.serializers.model.ModelSerializerNoWeightsWithStats
                                fl_server_api.serializers.model.ModelSerializer --> fl_server_api.serializers.model.ModelSerializerNoWeights
                



              click fl_server_api.serializers.model.ModelSerializerNoWeightsWithStats href "" "fl_server_api.serializers.model.ModelSerializerNoWeightsWithStats"
              click fl_server_api.serializers.model.ModelSerializerNoWeights href "" "fl_server_api.serializers.model.ModelSerializerNoWeights"
              click fl_server_api.serializers.model.ModelSerializer href "" "fl_server_api.serializers.model.ModelSerializer"
            

A model serializer that excludes the model weights but includes the model statistics.

Classes:

Name Description
Meta
Source code in fl_server_api/serializers/model.py
class ModelSerializerNoWeightsWithStats(ModelSerializerNoWeights):
    """
    A model serializer that excludes the model weights but includes the model statistics.
    """

    class Meta:
        model = Model
        exclude = ["polymorphic_ctype", "weights"]
        include = ["stats"]
        include = ["has_preprocessing", "stats"]

Classes

Meta

Attributes:

Name Type Description
exclude
include
model
Source code in fl_server_api/serializers/model.py
class Meta:
    model = Model
    exclude = ["polymorphic_ctype", "weights"]
    include = ["stats"]
    include = ["has_preprocessing", "stats"]
Attributes
exclude class-attribute instance-attribute
exclude = ['polymorphic_ctype', 'weights']
include class-attribute instance-attribute
include = ['has_preprocessing', 'stats']
model class-attribute instance-attribute
model = Model

Functions

load_and_create_model_request

load_and_create_model_request(request: HttpRequest) -> Model

Load and create a model from a Django request.

Parameters:

Name Type Description Default

request

HttpRequest

The request object.

required

Returns:

Name Type Description
Model Model

The created model.

Source code in fl_server_api/serializers/model.py
def load_and_create_model_request(request: HttpRequest) -> Model:
    """
    Load and create a model from a Django request.

    Args:
        request (HttpRequest): The request object.

    Returns:
        Model: The created model.
    """
    model_cls, data = load_model_request(request)
    if model_cls is MeanModel:
        sub_models = data.pop("models")
        model = model_cls.objects.create(**data)
        model.models.set(sub_models)
        return model
    return model_cls.objects.create(**data)

load_model_request

load_model_request(request: HttpRequest) -> tuple[Type[Model], dict[str, Any]]

Load model data from a Django request.

Parameters:

Name Type Description Default

request

HttpRequest

The request object.

required

Returns:

Type Description
tuple[Type[Model], dict[str, Any]]

Tuple[Type[Model], Dict[str, Any]]: The model class and parsed request data.

Source code in fl_server_api/serializers/model.py
def load_model_request(request: HttpRequest) -> Tuple[Type[Model], Dict[str, Any]]:
    """
    Load model data from a Django request.

    Args:
        request (HttpRequest): The request object.

    Returns:
        Tuple[Type[Model], Dict[str, Any]]: The model class and parsed request data.
    """
    if request.content_type == "application/json":
        data = request.data
    else:  # multipart/form-data
        data = request.POST.dict()
    data["owner"] = request.user
    model_type = data.pop("type", "GLOBAL").upper()

    # name and description are required
    if "name" not in data:
        raise ValidationError("Missing required field: name")
    if "description" not in data:
        raise ValidationError("Missing required field: description")

    # round is an optional field (it may not even make sense to be able to set it)
    if "round" not in data:
        data["round"] = 0

    # QueryDict removes all "None" entities.
    # Therefore, we need to manually parse the data to dict (the "normal" python way) and get the correct data
    if request.content_type == "application/json":
        data["input_shape"] = dict(request.data).get("input_shape", None)
    else:  # multipart/form-data
        data["input_shape"] = dict(request.POST).get("input_shape", None)
    # input_shape contains None as String but this is not parseable to a nullable int later -> parsing
    if "input_shape" in data:
        if data["input_shape"] is None:
            # nothing to do
            pass
        elif isinstance(data["input_shape"], str) and data["input_shape"].upper() in ["NONE", "NULL"]:
            data["input_shape"] = None
        elif not isinstance(data["input_shape"], Sequence):
            data["input_shape"] = None
        elif len(data["input_shape"]) < 1:
            data["input_shape"] = None
        else:
            data["input_shape"] = [None if str(x).upper() in ["NONE", "NULL"] else x for x in data["input_shape"]]

    # model_file is required except for MEAN models
    if model_type != "MEAN":
        data["weights"] = get_file(request, "model_file")
        verify_model_object(data["weights"])

    # model_preprocessing_file is optional
    data["preprocessing"] = None
    if request.FILES.__contains__("model_preprocessing_file"):
        data["preprocessing"] = get_file(request, "model_preprocessing_file")
        verify_model_object(data["preprocessing"], "preprocessing")

    # MEAN models require a list of model UUIDs
    if model_type == "MEAN":
        data = _parse_mean_model_models(data)

    # return class type and parsed data
    match model_type:
        case "SWAG": return SWAGModel, data
        case "MEAN": return MeanModel, data
        case _: return GlobalModel, data

verify_model_object

verify_model_object(model: bytes, file_type_name: str = 'model') -> None

Verify the model object.

Parameters:

Name Type Description Default

model

bytes

The model object.

required

file_type_name

str

The file type name. Defaults to "model".

'model'

Raises:

Type Description
ValidationError

If the model object is invalid.

Source code in fl_server_api/serializers/model.py
def verify_model_object(model: bytes, file_type_name: str = "model") -> None:
    """
    Verify the model object.

    Args:
        model (bytes): The model object.
        file_type_name (str, optional): The file type name. Defaults to "model".

    Raises:
        ValidationError: If the model object is invalid.
    """
    try:
        to_torch_module(model)
    except Exception as e:
        raise ValidationError(f"Invalid {file_type_name} file: {e}") from e