diff --git a/.github/actions/build-application/action.yml b/.github/actions/build-application/action.yml new file mode 100644 index 0000000..8d891af --- /dev/null +++ b/.github/actions/build-application/action.yml @@ -0,0 +1,33 @@ + +name: Build application +description: This action builds the application + +runs: + + using: 'composite' + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Python 3.11 + uses: actions/setup-python@v5 + with: + python-version: 3.11 + + - name: Install Poetry + uses: snok/install-poetry@v1 + with: + virtualenvs-in-project: true # for caching dependencies + + - name: Load cached virtualenv + uses: actions/cache@v2 + id: cache-poetry-dependencies + with: + path: .venv + key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }} + + - name: Install dependencies using Poetry + if: steps.cache-poetry-dependencies.outputs.cache-hit != 'true' + run: poetry run make install + shell: bash diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..507c7b5 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,25 @@ + +name: Lint workflow + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +permissions: + contents: read + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Build application + uses: ./.github/actions/build-application + + - name: Lint with Flake8 + run: poetry run make check \ No newline at end of file diff --git a/Makefile b/Makefile index 4ecf11b..3cd3d67 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,11 @@ -.PHONY: run install check clean runner -.DEFAULT_GOAL := runner +.PHONY: run-builder run-inference install check clean runner-builder runner-inference +.DEFAULT_GOAL := runner-inference -run: install - cd src; poetry run python runner.py; +run-builder: install + cd src; poetry run python runner_builder.py; + +run-inference: install + cd src; poetry run python runner_inference.py; install: poetry install @@ -13,4 +16,6 @@ check: clean: rm -rf `find . -type d -name __pycache__` -runner: check run clean +runner-builder: check run-builder clean + +runner-inference: check run-inference clean \ No newline at end of file diff --git a/src/model/model_builder.py b/src/model/model_builder.py new file mode 100644 index 0000000..bf525e3 --- /dev/null +++ b/src/model/model_builder.py @@ -0,0 +1,18 @@ +from loguru import logger + +from config import model_settings +from model.pipeline.model import build_model + + +class ModelBuilderService: + + def __init__(self): + self.model_path = model_settings.model_path + self.model_name = model_settings.model_name + + def load_model(self): + logger.info( + f'Building the model file at ' + f'{self.model_path}/{self.model_name}', + ) + build_model() diff --git a/src/model/model_inference.py b/src/model/model_inference.py new file mode 100644 index 0000000..219195f --- /dev/null +++ b/src/model/model_inference.py @@ -0,0 +1,36 @@ +from pathlib import Path +import pickle as pkl + +from loguru import logger + +from config import model_settings + + +class ModelInferenceService: + + def __init__(self): + self.model = None + self.model_path = model_settings.model_path + self.model_name = model_settings.model_name + + def load_model(self): + logger.info( + f'Checking for existing model file at ' + f'{self.model_path}/{self.model_name}', + ) + model_path = Path( + f'{self.model_path}/{self.model_name}', + ) + + if not model_path.exists(): + raise FileNotFoundError( + f'Model file {self.model_name} does not exist!', + ) + + logger.info(f'Loading existing model -> {model_path}') + with open(model_path, 'rb') as model_file: + self.model = pkl.load(model_file) + + def predict(self, input_parameters): + logger.info('Making predictions') + return self.model.predict([input_parameters]) diff --git a/src/model/model_service.py b/src/model/model_service.py deleted file mode 100644 index d325f5c..0000000 --- a/src/model/model_service.py +++ /dev/null @@ -1,36 +0,0 @@ -from pathlib import Path -import pickle as pkl - -from loguru import logger - -from config import model_settings -from model.pipeline.model import build_model - - -class ModelService: - - def __init__(self): - self.model = None - - def load_model(self): - logger.info( - f'Loading model from ' - f'{model_settings.model_path}/{model_settings.model_name}', - ) - model_path = Path( - f'{model_settings.model_path}/{model_settings.model_name}', - ) - - if not model_path.exists(): - logger.warning( - f'Model not found at {model_path} ' - f'-> Building model {model_settings.model_name}', - ) - build_model() - - logger.info(f'Loading model from {model_path}') - self.model = pkl.load(open(model_path, 'rb')) - - def predict(self, input_parameters): - logger.info('Making predictions') - return self.model.predict([input_parameters]) diff --git a/src/runner_builder.py b/src/runner_builder.py new file mode 100644 index 0000000..7cf5870 --- /dev/null +++ b/src/runner_builder.py @@ -0,0 +1,14 @@ +from loguru import logger + +from model.model_builder import ModelBuilderService + + +@logger.catch +def main(): + logger.info('Running builder application') + ml_svc = ModelBuilderService() + ml_svc.train_model() + + +if __name__ == '__main__': + main() diff --git a/src/runner.py b/src/runner_inference.py similarity index 100% rename from src/runner.py rename to src/runner_inference.py