Source code for ersilia.core.base
import os
from pathlib import Path
from .. import logger
from ..default import EOS, PACK_METHOD_BENTOML, PACK_METHOD_FASTAPI
from ..tools.bentoml.exceptions import BentoMLException
from ..utils.config import Config, Credentials
from ..utils.terminal import run_command
home = str(Path.home())
[docs]
class ErsiliaBase(object):
"""
Base class of Ersilia.
This class is used as a configuration for many of the classes of the package.
"""
def __init__(self, config_json=None, credentials_json=None):
self.eos_dir = EOS
self.config_json = config_json
self.credentials_json = credentials_json
self.cfg = Config(json_file=config_json)
self.cred = Credentials(json_file=credentials_json)
self._tmp_dir = self._abs_path(os.path.join(EOS, self.cfg.LOCAL.TMP))
if not os.path.exists(self._tmp_dir):
os.makedirs(self._tmp_dir, exist_ok=True)
self._dest_dir = self._abs_path(os.path.join(EOS, self.cfg.LOCAL.DEST))
if not os.path.exists(self._dest_dir):
os.makedirs(self._dest_dir, exist_ok=True)
self._bentoml_dir = os.path.join(
self._abs_path(os.path.join(Path.home(), "bentoml")), "repository"
)
self._bundles_dir = os.path.join(self.eos_dir, "repository")
if not os.path.exists(self._bundles_dir):
os.makedirs(self._bundles_dir, exist_ok=True)
self.logger = logger
@staticmethod
def _abs_path(path):
return os.path.abspath(path)
def _model_path(self, model_id):
folder = os.path.join(self._dest_dir, model_id)
return folder
def _get_latest_bentoml_tag(self, model_id):
path = os.path.join(self._bentoml_dir, model_id)
if not os.path.exists(path):
return None
items = sorted(os.listdir(path))
if not items:
return None
else:
return items[-1]
def _get_latest_bundle_tag(self, model_id):
path = os.path.join(self._bundles_dir, model_id)
if not os.path.exists(path):
return None
items = sorted(os.listdir(path))
if not items:
return None
else:
return items[-1]
def _get_bentoml_location(self, model_id):
tag = self._get_latest_bentoml_tag(model_id)
path = os.path.join(self._bentoml_dir, model_id)
if not os.path.exists(path):
self.logger.debug(f"BentoML path not found: {path}")
return None
if tag is not None:
return os.path.join(path, tag)
else:
return path
def _get_bundle_location(self, model_id):
tag = self._get_latest_bundle_tag(model_id)
path = os.path.join(self._bundles_dir, model_id)
if not os.path.exists(path):
self.logger.debug(f"Bundle path not found: {path}")
return None
if tag is not None:
return os.path.join(path, tag)
else:
return path
def _get_bento_location(self, model_id):
if self._resolve_pack_method_source(model_id) != "bentoml":
return None
cmd = ["bentoml", "get", f"{model_id}:latest", "--print-location", "--quiet"]
stdout, stderr, returncode = run_command(cmd, quiet=True)
if returncode != 0:
self.logger.error(f"BentoML command failed: {stderr}")
raise BentoMLException(f"BentoML error: {stderr}")
return stdout.strip()
def _is_ready(self, model_id):
"""Check whether a model exists in the local computer"""
try:
self._get_latest_bundle_tag(model_id)
except Exception as e:
self.logger.debug(f"Model {model_id} not ready: {str(e)}")
return False
path = os.path.join(self._abs_path(self._dest_dir), model_id)
if not os.path.exists(path):
return False
return True
def _has_credentials(self):
if self.cred is None:
self.logger.warning("No credentials found.")
return False
return True
def _resolve_pack_method_source(self, model_id):
bundle_path = self._get_bundle_location(model_id)
if os.path.exists(os.path.join(bundle_path, "installs", "install.sh")):
return PACK_METHOD_FASTAPI
elif os.path.exists(os.path.join(bundle_path, "bentoml.yml")):
return PACK_METHOD_BENTOML
self.logger.warning(
"Could not resolve pack method by simply looking at the bundle path"
)
return None