Downloaders#

A downloader is a component used to stored the model file in some way. It is a callable of the type DownloaderCallable that receive a model, perform an action to store it and returns some kind of identification of the action performed.

Downloader is an interface for downloaders that forces you to make instances of the class callable of type DownloaderCallable. You need to implement the __call__ method when you inherit from it.

File System Downloader#

The library provides a downloader implementation capable of stores model files in a file system; FileSystemDownloader.

>>> from devo_ml.modelmanager.downloader import FileSystemDownloader

>>> downloader = FileSystemDownloader("~/download/models/")

A FileSystemDownloader needs a root path to be constructed, it is where files will be downloaded. The file name will be the model name plus the inferred extension from the engine. The extension will be empty if it can not infer, e.g: if there is no extension associated to the engine.

Note

The FileSystemDownloader it used as a fallback downloader when a downloader is not provided when creating a Client, and in places where it is not possible passing custom downloaders; client factories and functions facade.

Example AWS S3 Bucket Downloader#

This is an example of how to customize the behavior of the client on downloading the model files. Let’s implement a AWS S3 Bucket downloader.

import boto3

from devo_ml.modelmanager.engines import get_default_engine_extension
from devo_ml.modelmanager.downloader import Downloader
from devo_ml.modelmanager.downloader import get_image_bytes


class AwsS3BucketDownloader(Downloader):
    def __init__(
        self,
        bucket: str = None,
        region: str = None,
        access_key: str = None,
        access_secret: str = None
    ) -> None:
        self.bucket = bucket
        self.region = region
        self.access_key = access_key
        self.access_secret = access_secret

    def __call__(self, model: dict) -> str:
        name = model.get("name")
        engine = model.get("engine")
        if not name or not engine:
            raise ValueError("Invalid model")
        image_bytes = get_image_bytes(model.get("image", {}))
        ext = get_default_engine_extension(engine)
        s3 = boto3.client(
            "s3",
            region_name=self.region,
            aws_access_key_id=self.access_key,
            aws_secret_access_key=self.access_secret
        )
        s3.upload_fileobj(
            io.BytesIO(image_bytes),
            self.bucket,
            f"{name}{ext}"
        )
        return f"{self.bucket}/{name}{ext}"

Warning

This is not a fully tested code, please, if you are going to use it, test and tune it according to your needs.