Пример #1
0
def save(bento_service, dst, version=None):
    """
    Save given BentoService along with all artifacts to target path
    """

    if version is None:
        version = _generate_new_version_str()
    _validate_version_str(version)

    if bento_service._version_major is not None and bento_service._version_minor is not None:
        # BentoML uses semantic versioning for BentoService distribution
        # when user specified the MAJOR and MINOR version number along with
        # the BentoService class definition with '@ver' decorator.
        # The parameter version(or auto generated version) here will be used as
        # PATCH field in the final version:
        version = '.'.join(
            [str(bento_service._version_major),
             str(bento_service._version_minor), version])

    # Full path containing saved BentoArchive, it the dst path with service name
    # and service version as prefix. e.g.:
    # - s3://my-bucket/base_path => s3://my-bucket/base_path/service_name/version/
    # - /tmp/my_bento_archive/ => /tmp/my_bento_archive/service_name/version/
    full_saved_path = os.path.join(dst, bento_service.name, version)

    if is_s3_url(dst):
        with TempDirectory() as tempdir:
            _save(bento_service, tempdir, version)
            upload_to_s3(full_saved_path, tempdir)
    else:
        _save(bento_service, dst, version)

    return full_saved_path
Пример #2
0
def save(bento_service, dst, version=None):
    """Save given BentoService along with all its artifacts, source code and
    dependencies to target path

    Args:
        bento_service (bentoml.service.BentoService): a Bento Service instance
        dst (str): Destination of where the bento service will be saved. It could
            be a local file path or a s3 path
        version (:obj:`str`, optional): version text to use for saved archive

    Returns:
        string: The complete path of saved Bento service.
    """

    if version is None:
        version = _generate_new_version_str()
    _validate_version_str(version)

    if (bento_service._version_major is not None
            and bento_service._version_minor is not None):
        # BentoML uses semantic versioning for BentoService distribution
        # when user specified the MAJOR and MINOR version number along with
        # the BentoService class definition with '@ver' decorator.
        # The parameter version(or auto generated version) here will be used as
        # PATCH field in the final version:
        version = ".".join([
            str(bento_service._version_major),
            str(bento_service._version_minor),
            version,
        ])

    # Full path containing saved BentoArchive, it the dst path with service name
    # and service version as prefix. e.g.:
    # - s3://my-bucket/base_path => s3://my-bucket/base_path/service_name/version/
    # - /tmp/my_bento_archive/ => /tmp/my_bento_archive/service_name/version/
    full_saved_path = os.path.join(dst, bento_service.name, version)

    if is_s3_url(dst):
        with TempDirectory() as tempdir:
            _save(bento_service, tempdir, version)
            upload_to_s3(full_saved_path, tempdir)
    else:
        _save(bento_service, dst, version)

    LOG.info("BentoService %s:%s saved to %s", bento_service.name, version,
             full_saved_path)
    return full_saved_path
Пример #3
0
def save(bento_service, dst, version=None, pypi_package_version="1.0.0"):
    """
    Save given BentoService along with all artifacts to target path
    """

    if version is None:
        version = _generate_new_version_str()
    _validate_version_str(version)

    # Full path containing saved BentoArchive, it the dst path with service name
    # and service version as prefix. e.g.:
    # - s3://my-bucket/base_path => s3://my-bucket/base_path/service_name/version/
    # - /tmp/my_bento_archive/ => /tmp/my_bento_archive/service_name/version/
    full_saved_path = os.path.join(dst, bento_service.name, version)

    if is_s3_url(dst):
        with TempDirectory() as tempdir:
            _save(bento_service, tempdir, version, pypi_package_version)
            upload_to_s3(full_saved_path, tempdir)
    else:
        _save(bento_service, dst, version, pypi_package_version)

    return full_saved_path
Пример #4
0
def save(bento_service, dst, version=None, pypi_package_version="1.0.0"):
    """
    Save given BentoService along with all artifacts to target path
    """

    if version is None:
        version = _generate_new_version_str()
    _validate_version_str(version)

    s3_url = None
    if is_s3_url(dst):
        s3_url = os.path.join(dst, bento_service.name, version)
        # TODO: check s3_url not exist, otherwise raise exception
        temp_dir = tempfile.mkdtemp()
        Path(temp_dir, bento_service.name).mkdir(parents=True, exist_ok=True)
        # Update path to subfolder in the form of 'base/service_name/version/'
        path = os.path.join(temp_dir, bento_service.name, version)
    else:
        Path(os.path.join(dst), bento_service.name).mkdir(parents=True, exist_ok=True)
        # Update path to subfolder in the form of 'base/service_name/version/'
        path = os.path.join(dst, bento_service.name, version)

        if os.path.exists(path):
            raise ValueError("Version {version} in Path: {dst} already "
                             "exist.".format(version=version, dst=dst))

    os.mkdir(path)
    module_base_path = os.path.join(path, bento_service.name)
    os.mkdir(module_base_path)

    # write README.md with user model's docstring
    if bento_service.__class__.__doc__:
        model_description = bento_service.__class__.__doc__.strip()
    else:
        model_description = DEFAULT_BENTO_ARCHIVE_DESCRIPTION
    with open(os.path.join(path, 'README.md'), 'w') as f:
        f.write(model_description)

    # save all model artifacts to 'base_path/name/artifacts/' directory
    bento_service.artifacts.save(module_base_path)

    # write conda environment, requirement.txt
    bento_service.env.save(path)

    # TODO: add bentoml.find_packages helper for more fine grained control over
    # this process, e.g. packages=find_packages(base, [], exclude=[], used_module_only=True)
    # copy over all custom model code
    module_name, module_file = copy_used_py_modules(bento_service.__class__.__module__,
                                                    os.path.join(path, bento_service.name))

    if os.path.isabs(module_file):
        module_file = module_name.replace('.', os.sep) + '.py'

    # create __init__.py
    with open(os.path.join(path, bento_service.name, '__init__.py'), "w") as f:
        f.write(
            INIT_PY_TEMPLATE.format(service_name=bento_service.name, module_name=module_name,
                                    pypi_package_version=pypi_package_version))

    # write setup.py, make exported model pip installable
    setup_py_content = BENTO_MODEL_SETUP_PY_TEMPLATE.format(
        name=bento_service.name, pypi_package_version=pypi_package_version,
        long_description=model_description)
    with open(os.path.join(path, 'setup.py'), 'w') as f:
        f.write(setup_py_content)

    with open(os.path.join(path, 'MANIFEST.in'), 'w') as f:
        f.write(MANIFEST_IN_TEMPLATE.format(service_name=bento_service.name))

    # write Dockerfile
    with open(os.path.join(path, 'Dockerfile'), 'w') as f:
        f.write(
            BENTO_SERVER_SINGLE_MODEL_DOCKERFILE_TEMPLATE.format(
                conda_env_name=bento_service.env.get_conda_env_name()))

    # write bentoml.yml
    bentoml_yml_content = BENTOML_CONFIG_YAML_TEMPLATE.format(
        service_name=bento_service.name, bentoml_version=BENTOML_VERSION, service_version=version,
        module_name=module_name, module_file=module_file, created_at=str(datetime.now()))
    with open(os.path.join(path, 'bentoml.yml'), 'w') as f:
        f.write(bentoml_yml_content)
    # Also write bentoml.yml to module base path to make it accessible
    # as package data after pip installed as a python package
    with open(os.path.join(module_base_path, 'bentoml.yml'), 'w') as f:
        f.write(bentoml_yml_content)

    if s3_url:
        upload_to_s3(s3_url, path)
        return s3_url
    else:
        return path