From e1166ab0622c13f08091a0ee6ce753071f47fbcc Mon Sep 17 00:00:00 2001 From: blaise-muhirwa Date: Tue, 3 Oct 2023 23:02:55 +0000 Subject: [PATCH 01/19] adding container to update models on a schedule --- deploy/bin/build-push-model-updater.sh | 46 +++++++++++++++++++ .../k3s/edge_deployment/edge_deployment.yaml | 21 ++++++++- model_updater/Dockerfile | 39 ++++++++++++++++ model_updater/__init__.py | 0 model_updater/update_models.py | 40 ++++++++++++++++ pyproject.toml | 11 +++++ 6 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 deploy/bin/build-push-model-updater.sh create mode 100644 model_updater/Dockerfile create mode 100644 model_updater/__init__.py create mode 100644 model_updater/update_models.py diff --git a/deploy/bin/build-push-model-updater.sh b/deploy/bin/build-push-model-updater.sh new file mode 100644 index 00000000..07d52c0a --- /dev/null +++ b/deploy/bin/build-push-model-updater.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +set -ex + + +# Ensure that you're in the same directory as this script before running it +cd "$(dirname "$0")" + +TAG=$(./git-tag-name.sh) + +# Authenticate docker to ECR +aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin 723181461334.dkr.ecr.us-west-2.amazonaws.com + +# We use docker buildx to build the image for multiple platforms. buildx comes +# installed with Docker Engine when installed via Docker Desktop. If you're +# on a Linux machine with an old version of Docker Engine, you may need to +# install buildx manually. Follow these instructions to install docker-buildx-plugin: +# https://docs.docker.com/engine/install/ubuntu/ + +# Install QEMU, a generic and open-source machine emulator and virtualizer +docker run --rm --privileged linuxkit/binfmt:af88a591f9cc896a52ce596b9cf7ca26a061ef97 + +# Check if tempbuilder already exists +if ! docker buildx ls | grep -q tempmodelupdaterbuilder; then + # Prep for multiplatform build - the build is done INSIDE a docker container + docker buildx create --name tempmodelupdaterbuilder --use +else + # If tempbuilder exists, set it as the current builder + docker buildx use tempmodelupdaterbuilder +fi + +# Ensure that the tempbuilder container is running +docker buildx inspect tempmodelupdaterbuilder --bootstrap + +# Temporarily copy the pyproject.toml file to the model_updater directory +# to bring it into the build context +cp ../../pyproject.toml ../../model_updater/ + +# Build model updater image for amd64 and arm64 +docker buildx build \ + --platform linux/arm64,linux/amd64 \ + --tag 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:${TAG} \ + ../../model_updater --push + +# Remove the temporary pyproject.toml file +rm ../../model_updater/pyproject.toml \ No newline at end of file diff --git a/deploy/k3s/edge_deployment/edge_deployment.yaml b/deploy/k3s/edge_deployment/edge_deployment.yaml index 031fe4eb..0e23567c 100644 --- a/deploy/k3s/edge_deployment/edge_deployment.yaml +++ b/deploy/k3s/edge_deployment/edge_deployment.yaml @@ -56,12 +56,31 @@ spec: key: api-token volumeMounts: - name: edge-config-volume - # This is a path inside the container not the host mountPath: /etc/groundlight/edge-config - name: inference-deployment-template-volume mountPath: /etc/groundlight/inference-deployment - name: model-repo mountPath: /mnt/models + + - name: inference-model-updater + image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:model-updating-cronjob-6fdf21e85-dirty-baf903f1357322c + imagePullPolicy: IfNotPresent + env: + - name: LOG_LEVEL + value: "INFO" + - name: DEPLOY_DETECTOR_LEVEL_INFERENCE + value: "True" + - name: GROUNDLIGHT_API_TOKEN + valueFrom: + secretKeyRef: + name: groundlight-secrets + key: api-token + volumeMounts: + - name: edge-config-volume + mountPath: /etc/groundlight/edge-config + - name: model-repo + mountPath: /mnt/models + imagePullSecrets: - name: registry-credentials volumes: diff --git a/model_updater/Dockerfile b/model_updater/Dockerfile new file mode 100644 index 00000000..bbfb3cbd --- /dev/null +++ b/model_updater/Dockerfile @@ -0,0 +1,39 @@ +# Build args +ARG APP_ROOT="/model_updater" +ARG POETRY_HOME="/opt/poetry" +ARG POETRY_VERSION=1.5.1 + +FROM python:3.11-slim-bullseye + +# Args that are needed in this stage +ARG APP_ROOT +ARG POETRY_HOME +ARG POETRY_VERSION + +# Install required dependencies and tools +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + bash \ + curl \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && curl -sSL https://install.python-poetry.org | python - + +# Set Python and Poetry ENV vars +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + POETRY_HOME=${POETRY_HOME} \ + POETRY_VERSION=${POETRY_VERSION} \ + PATH=${POETRY_HOME}/bin:$PATH + +COPY update_models.py ${APP_ROOT}/ + +COPY ./pyproject.toml ${APP_ROOT}/ + +WORKDIR ${APP_ROOT} + +# Install production dependencies only +RUN poetry install --only model_updater --no-interaction --no-root + +# Entry command +CMD ["poetry", "run", "python", "-m", "model_updater.update_models"] \ No newline at end of file diff --git a/model_updater/__init__.py b/model_updater/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/model_updater/update_models.py b/model_updater/update_models.py new file mode 100644 index 00000000..fabc355b --- /dev/null +++ b/model_updater/update_models.py @@ -0,0 +1,40 @@ +import os +import logging +import time +from app.core.app_state import load_edge_config +from app.core.configs import RootEdgeConfig +from app.core.edge_inference import EdgeInferenceManager +from fastapi import HTTPException + + +log_level = os.environ.get("LOG_LEVEL", "INFO").upper() +logging.basicConfig(level=log_level) + + +def update_models(): + # if not os.environ.get("DEPLOY_DETECTOR_LEVEL_INFERENCE", None): + # return + + edge_config: RootEdgeConfig = load_edge_config() + + edge_inference_templates = edge_config.local_inference_templates + inference_config = { + detector.detector_id: edge_inference_templates[detector.local_inference_template] + for detector in edge_config.detectors + } + + logging.info(f" inference_config: {inference_config}") + edge_inference_manager = EdgeInferenceManager(config=edge_config.local_inference_templates, verbose=True) + + for detector_id, inference_config in inference_config.items(): + if inference_config.enabled: + try: + edge_inference_manager.update_model(detector_id=detector_id) + except Exception as e: + logging.error(f"Failed to update model for {detector_id}. {e}", exc_info=True) + + +if __name__ == "__main__": + while True: + update_models() + time.sleep(3600) \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index f95734bc..5734010e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,17 @@ tritonclient = {extras = ["all"], version = "2.36.0"} kubernetes = "^27.2.0" jinja2 = "^3.1.2" +[tool.poetry.group.model_updater.dependencies] +python = "^3.9" +fastapi = "^0.88.0" +pydantic = "^1.10.2" +pillow = "^9.5.0" +pyyaml = "^6.0" +svix-ksuid = "^0.6.2" +tritonclient = {extras = ["all"], version = "^2.36.0"} +jinja2 = "^3.1.2" + + [tool.poetry.group.dev.dependencies] pytest = "^7.2.0" pytest-cov = "^4.0.0" From 1eccf361d0098bd0c61f7fd09967ddbc496e9b71 Mon Sep 17 00:00:00 2001 From: Auto-format Bot Date: Tue, 3 Oct 2023 23:05:56 +0000 Subject: [PATCH 02/19] Automatically reformatting code with black and isort --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5734010e..d19ed50f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,6 @@ svix-ksuid = "^0.6.2" tritonclient = {extras = ["all"], version = "^2.36.0"} jinja2 = "^3.1.2" - [tool.poetry.group.dev.dependencies] pytest = "^7.2.0" pytest-cov = "^4.0.0" From cfa04e25b61a86c1c492766dc03aeb839e52f0ef Mon Sep 17 00:00:00 2001 From: blaise-muhirwa Date: Tue, 3 Oct 2023 23:19:17 +0000 Subject: [PATCH 03/19] dockerfile --- model_updater/Dockerfile | 3 ++- model_updater/update_models.py | 2 -- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/model_updater/Dockerfile b/model_updater/Dockerfile index bbfb3cbd..917c4637 100644 --- a/model_updater/Dockerfile +++ b/model_updater/Dockerfile @@ -36,4 +36,5 @@ WORKDIR ${APP_ROOT} RUN poetry install --only model_updater --no-interaction --no-root # Entry command -CMD ["poetry", "run", "python", "-m", "model_updater.update_models"] \ No newline at end of file +# CMD ["poetry", "run", "python", "-m", "model_updater.update_models"] +CMD poetry run python -m update_models \ No newline at end of file diff --git a/model_updater/update_models.py b/model_updater/update_models.py index fabc355b..020c747c 100644 --- a/model_updater/update_models.py +++ b/model_updater/update_models.py @@ -4,8 +4,6 @@ from app.core.app_state import load_edge_config from app.core.configs import RootEdgeConfig from app.core.edge_inference import EdgeInferenceManager -from fastapi import HTTPException - log_level = os.environ.get("LOG_LEVEL", "INFO").upper() logging.basicConfig(level=log_level) diff --git a/pyproject.toml b/pyproject.toml index 5734010e..b259d831 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ pydantic = "^1.10.2" pillow = "^9.5.0" pyyaml = "^6.0" svix-ksuid = "^0.6.2" -tritonclient = {extras = ["all"], version = "^2.36.0"} +tritonclient = {extras = ["all"], version = "2.36.0"} jinja2 = "^3.1.2" From 4526476fbd850a7c12ffa5704872ed040830821f Mon Sep 17 00:00:00 2001 From: blaise-muhirwa Date: Wed, 4 Oct 2023 17:58:14 +0000 Subject: [PATCH 04/19] clean up --- Dockerfile => Dockerfile.app | 0 Dockerfile.model_updater | 42 +++++++++++++++++++ app/core/app_state.py | 25 +---------- app/core/utils.py | 32 ++++++++++++++ app/main.py | 16 ------- deploy/bin/build-push-edge-endpoint-image.sh | 1 + deploy/bin/build-push-model-updater.sh | 10 +---- .../k3s/edge_deployment/edge_deployment.yaml | 2 +- model_updater/Dockerfile | 1 + model_updater/update_models.py | 9 ++-- pyproject.toml | 1 + 11 files changed, 85 insertions(+), 54 deletions(-) rename Dockerfile => Dockerfile.app (100%) create mode 100644 Dockerfile.model_updater mode change 100644 => 100755 deploy/bin/build-push-model-updater.sh diff --git a/Dockerfile b/Dockerfile.app similarity index 100% rename from Dockerfile rename to Dockerfile.app diff --git a/Dockerfile.model_updater b/Dockerfile.model_updater new file mode 100644 index 00000000..02fe3ff1 --- /dev/null +++ b/Dockerfile.model_updater @@ -0,0 +1,42 @@ +# Build args +ARG APP_ROOT="/model_updater" +ARG POETRY_HOME="/opt/poetry" +ARG POETRY_VERSION=1.5.1 + +FROM python:3.11-slim-bullseye + +# Args that are needed in this stage +ARG APP_ROOT +ARG POETRY_HOME +ARG POETRY_VERSION + +# Install required dependencies and tools +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + bash \ + curl \ + libglib2.0-0 \ + libgl1-mesa-glx \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && curl -sSL https://install.python-poetry.org | python - + +# Set Python and Poetry ENV vars +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + POETRY_HOME=${POETRY_HOME} \ + POETRY_VERSION=${POETRY_VERSION} \ + PATH=${POETRY_HOME}/bin:$PATH + +COPY model_updater ${APP_ROOT}/model_updater +COPY app/core ${APP_ROOT}/app/core + +COPY ./pyproject.toml ${APP_ROOT}/ + +WORKDIR ${APP_ROOT} + +# Install production dependencies only +RUN poetry install --only model_updater --no-interaction --no-root + +# Entry command +CMD poetry run python -m model_updater.update_models \ No newline at end of file diff --git a/app/core/app_state.py b/app/core/app_state.py index bb33d710..389d6761 100644 --- a/app/core/app_state.py +++ b/app/core/app_state.py @@ -13,7 +13,7 @@ from model import Detector from app.core.utils import safe_call_api - +from .utils import load_edge_config from .configs import LocalInferenceConfig, MotionDetectionConfig, RootEdgeConfig from .edge_inference import EdgeInferenceManager from .file_paths import DEFAULT_EDGE_CONFIG_PATH, INFERENCE_DEPLOYMENT_TEMPLATE_PATH @@ -27,29 +27,6 @@ TTL_TIME = 3600 # 1 hour -def load_edge_config() -> RootEdgeConfig: - """ - Reads the edge config from the EDGE_CONFIG environment variable if it exists. - If EDGE_CONFIG is not set, reads the default edge config file. - """ - yaml_config = os.environ.get("EDGE_CONFIG", "").strip() - if yaml_config: - config = yaml.safe_load(yaml_config) - return RootEdgeConfig(**config) - - logger.warning("EDGE_CONFIG environment variable not set. Checking default locations.") - - default_paths = [DEFAULT_EDGE_CONFIG_PATH, "configs/edge-config.yaml"] - - for path in default_paths: - if os.path.exists(path): - logger.info(f"Loading edge config from {path}") - config = yaml.safe_load(open(path, "r")) - return RootEdgeConfig(**config) - - raise FileNotFoundError(f"Could not find edge config file in default locations: {default_paths}") - - @lru_cache(maxsize=MAX_SDK_INSTANCES_CACHE_SIZE) def _get_groundlight_sdk_instance_internal(api_token: str): return Groundlight(api_token=api_token) diff --git a/app/core/utils.py b/app/core/utils.py index 67fd223a..52c18ff9 100644 --- a/app/core/utils.py +++ b/app/core/utils.py @@ -4,6 +4,38 @@ import ksuid from fastapi import HTTPException from PIL import Image +from .configs import RootEdgeConfig +import os +import yaml +from .file_paths import DEFAULT_EDGE_CONFIG_PATH + +import logging + + +logger = logging.getLogger(__name__) + + +def load_edge_config() -> RootEdgeConfig: + """ + Reads the edge config from the EDGE_CONFIG environment variable if it exists. + If EDGE_CONFIG is not set, reads the default edge config file. + """ + yaml_config = os.environ.get("EDGE_CONFIG", "").strip() + if yaml_config: + config = yaml.safe_load(yaml_config) + return RootEdgeConfig(**config) + + logger.warning("EDGE_CONFIG environment variable not set. Checking default locations.") + + default_paths = [DEFAULT_EDGE_CONFIG_PATH, "configs/edge-config.yaml"] + + for path in default_paths: + if os.path.exists(path): + logger.info(f"Loading edge config from {path}") + config = yaml.safe_load(open(path, "r")) + return RootEdgeConfig(**config) + + raise FileNotFoundError(f"Could not find edge config file in default locations: {default_paths}") def safe_call_api(api_method: Callable, **kwargs): diff --git a/app/main.py b/app/main.py index d882152c..0f4ec843 100644 --- a/app/main.py +++ b/app/main.py @@ -18,19 +18,3 @@ app.include_router(router=ping_router) app.state.app_state = AppState() - - -@app.on_event("startup") -async def on_startup(): - """ - On startup, update edge inference models. - """ - if not os.environ.get("DEPLOY_DETECTOR_LEVEL_INFERENCE", None): - return - - for detector_id, inference_config in app.state.app_state.edge_inference_manager.inference_config.items(): - if inference_config.enabled: - try: - app.state.app_state.edge_inference_manager.update_model(detector_id) - except Exception: - logging.error(f"Failed to update model for {detector_id}", exc_info=True) diff --git a/deploy/bin/build-push-edge-endpoint-image.sh b/deploy/bin/build-push-edge-endpoint-image.sh index 9e846e46..941e468b 100755 --- a/deploy/bin/build-push-edge-endpoint-image.sh +++ b/deploy/bin/build-push-edge-endpoint-image.sh @@ -38,4 +38,5 @@ docker buildx inspect tempgroundlightedgebuilder --bootstrap docker buildx build \ --platform linux/arm64,linux/amd64 \ --tag 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:${TAG} \ + -f ../../Dockerfile.app \ ../.. --push diff --git a/deploy/bin/build-push-model-updater.sh b/deploy/bin/build-push-model-updater.sh old mode 100644 new mode 100755 index 07d52c0a..0d296189 --- a/deploy/bin/build-push-model-updater.sh +++ b/deploy/bin/build-push-model-updater.sh @@ -32,15 +32,9 @@ fi # Ensure that the tempbuilder container is running docker buildx inspect tempmodelupdaterbuilder --bootstrap -# Temporarily copy the pyproject.toml file to the model_updater directory -# to bring it into the build context -cp ../../pyproject.toml ../../model_updater/ - # Build model updater image for amd64 and arm64 docker buildx build \ --platform linux/arm64,linux/amd64 \ --tag 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:${TAG} \ - ../../model_updater --push - -# Remove the temporary pyproject.toml file -rm ../../model_updater/pyproject.toml \ No newline at end of file + -f ../../Dockerfile.model_updater \ + ../.. --push diff --git a/deploy/k3s/edge_deployment/edge_deployment.yaml b/deploy/k3s/edge_deployment/edge_deployment.yaml index 0e23567c..8a03c061 100644 --- a/deploy/k3s/edge_deployment/edge_deployment.yaml +++ b/deploy/k3s/edge_deployment/edge_deployment.yaml @@ -63,7 +63,7 @@ spec: mountPath: /mnt/models - name: inference-model-updater - image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:model-updating-cronjob-6fdf21e85-dirty-baf903f1357322c + image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:model-updater-cfa04e25b-dirty-47f8cbce0dea767 imagePullPolicy: IfNotPresent env: - name: LOG_LEVEL diff --git a/model_updater/Dockerfile b/model_updater/Dockerfile index 917c4637..37d64e57 100644 --- a/model_updater/Dockerfile +++ b/model_updater/Dockerfile @@ -27,6 +27,7 @@ ENV PYTHONUNBUFFERED=1 \ PATH=${POETRY_HOME}/bin:$PATH COPY update_models.py ${APP_ROOT}/ +COPY app ${APP_ROOT}/app COPY ./pyproject.toml ${APP_ROOT}/ diff --git a/model_updater/update_models.py b/model_updater/update_models.py index 020c747c..285102eb 100644 --- a/model_updater/update_models.py +++ b/model_updater/update_models.py @@ -1,7 +1,7 @@ import os import logging import time -from app.core.app_state import load_edge_config +from app.core.utils import load_edge_config from app.core.configs import RootEdgeConfig from app.core.edge_inference import EdgeInferenceManager @@ -10,8 +10,8 @@ def update_models(): - # if not os.environ.get("DEPLOY_DETECTOR_LEVEL_INFERENCE", None): - # return + if not os.environ.get("DEPLOY_DETECTOR_LEVEL_INFERENCE", None): + return edge_config: RootEdgeConfig = load_edge_config() @@ -21,7 +21,6 @@ def update_models(): for detector in edge_config.detectors } - logging.info(f" inference_config: {inference_config}") edge_inference_manager = EdgeInferenceManager(config=edge_config.local_inference_templates, verbose=True) for detector_id, inference_config in inference_config.items(): @@ -35,4 +34,4 @@ def update_models(): if __name__ == "__main__": while True: update_models() - time.sleep(3600) \ No newline at end of file + time.sleep(3600) diff --git a/pyproject.toml b/pyproject.toml index b259d831..1281eb33 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,7 @@ pyyaml = "^6.0" svix-ksuid = "^0.6.2" tritonclient = {extras = ["all"], version = "2.36.0"} jinja2 = "^3.1.2" +requests = "^2.28.1" [tool.poetry.group.dev.dependencies] From 953306448f590dd08d10ed5118a3b94c7e9f5a79 Mon Sep 17 00:00:00 2001 From: blaise-muhirwa Date: Wed, 4 Oct 2023 18:15:35 +0000 Subject: [PATCH 05/19] update deployment --- deploy/k3s/edge_deployment/edge_deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/k3s/edge_deployment/edge_deployment.yaml b/deploy/k3s/edge_deployment/edge_deployment.yaml index 8a03c061..1078eabf 100644 --- a/deploy/k3s/edge_deployment/edge_deployment.yaml +++ b/deploy/k3s/edge_deployment/edge_deployment.yaml @@ -40,7 +40,7 @@ spec: serviceAccountName: edge-endpoint-service-account containers: - name: edge-endpoint - image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:13361241c-state-management-via-k3s + image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:4526476fb-model-updater imagePullPolicy: IfNotPresent ports: - containerPort: 6717 From 707f045a650d0c0e7d8d770541bbf0df32314544 Mon Sep 17 00:00:00 2001 From: blaise-muhirwa Date: Wed, 4 Oct 2023 18:17:03 +0000 Subject: [PATCH 06/19] udpate images --- deploy/k3s/edge_deployment/edge_deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/k3s/edge_deployment/edge_deployment.yaml b/deploy/k3s/edge_deployment/edge_deployment.yaml index 1078eabf..aca03e1d 100644 --- a/deploy/k3s/edge_deployment/edge_deployment.yaml +++ b/deploy/k3s/edge_deployment/edge_deployment.yaml @@ -63,7 +63,7 @@ spec: mountPath: /mnt/models - name: inference-model-updater - image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:model-updater-cfa04e25b-dirty-47f8cbce0dea767 + image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:953306448-model-updater imagePullPolicy: IfNotPresent env: - name: LOG_LEVEL From 5d2ac52ef841007ad7b859c688bad8989aa0a197 Mon Sep 17 00:00:00 2001 From: Auto-format Bot Date: Wed, 4 Oct 2023 18:18:53 +0000 Subject: [PATCH 07/19] Automatically reformatting code with black and isort --- app/core/app_state.py | 7 ++++--- app/core/utils.py | 9 ++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/core/app_state.py b/app/core/app_state.py index 389d6761..c1cba097 100644 --- a/app/core/app_state.py +++ b/app/core/app_state.py @@ -13,12 +13,13 @@ from model import Detector from app.core.utils import safe_call_api -from .utils import load_edge_config -from .configs import LocalInferenceConfig, MotionDetectionConfig, RootEdgeConfig + +from .configs import LocalInferenceConfig, MotionDetectionConfig from .edge_inference import EdgeInferenceManager -from .file_paths import DEFAULT_EDGE_CONFIG_PATH, INFERENCE_DEPLOYMENT_TEMPLATE_PATH +from .file_paths import INFERENCE_DEPLOYMENT_TEMPLATE_PATH from .iqe_cache import IQECache from .motion_detection import MotionDetectionManager +from .utils import load_edge_config logger = logging.getLogger(__name__) diff --git a/app/core/utils.py b/app/core/utils.py index 52c18ff9..e6d28dbc 100644 --- a/app/core/utils.py +++ b/app/core/utils.py @@ -1,17 +1,16 @@ +import logging +import os from io import BytesIO from typing import Callable import ksuid +import yaml from fastapi import HTTPException from PIL import Image + from .configs import RootEdgeConfig -import os -import yaml from .file_paths import DEFAULT_EDGE_CONFIG_PATH -import logging - - logger = logging.getLogger(__name__) From 2cef6a7181fa7f6232877afec14c798acd743ad9 Mon Sep 17 00:00:00 2001 From: blaise-muhirwa Date: Wed, 4 Oct 2023 18:26:04 +0000 Subject: [PATCH 08/19] update cicd --- .github/workflows/pipeline.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pipeline.yaml b/.github/workflows/pipeline.yaml index 9d63bad3..ef83540d 100644 --- a/.github/workflows/pipeline.yaml +++ b/.github/workflows/pipeline.yaml @@ -66,7 +66,7 @@ jobs: sudo apt-get update sudo apt-get install docker-ce - name: Build Docker Image - run: docker build --tag groundlight-edge . + run: docker build -f Dockerfile.app --tag groundlight-edge . - name: Start Docker Container id: start_container @@ -136,7 +136,7 @@ jobs: sudo apt-get update sudo apt-get install docker-ce - name: Build Docker Image - run: docker build --tag groundlight-edge . + run: docker build -f Dockerfile.app --tag groundlight-edge . - name: Start Docker Container id: start_container From b86cb9703ffa066b6a8eecc1a2505c4f82c1ac24 Mon Sep 17 00:00:00 2001 From: blaise-muhirwa Date: Wed, 4 Oct 2023 18:28:35 +0000 Subject: [PATCH 09/19] clean up --- model_updater/Dockerfile | 41 ---------------------------------------- 1 file changed, 41 deletions(-) delete mode 100644 model_updater/Dockerfile diff --git a/model_updater/Dockerfile b/model_updater/Dockerfile deleted file mode 100644 index 37d64e57..00000000 --- a/model_updater/Dockerfile +++ /dev/null @@ -1,41 +0,0 @@ -# Build args -ARG APP_ROOT="/model_updater" -ARG POETRY_HOME="/opt/poetry" -ARG POETRY_VERSION=1.5.1 - -FROM python:3.11-slim-bullseye - -# Args that are needed in this stage -ARG APP_ROOT -ARG POETRY_HOME -ARG POETRY_VERSION - -# Install required dependencies and tools -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - bash \ - curl \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* \ - && curl -sSL https://install.python-poetry.org | python - - -# Set Python and Poetry ENV vars -ENV PYTHONUNBUFFERED=1 \ - PYTHONDONTWRITEBYTECODE=1 \ - POETRY_HOME=${POETRY_HOME} \ - POETRY_VERSION=${POETRY_VERSION} \ - PATH=${POETRY_HOME}/bin:$PATH - -COPY update_models.py ${APP_ROOT}/ -COPY app ${APP_ROOT}/app - -COPY ./pyproject.toml ${APP_ROOT}/ - -WORKDIR ${APP_ROOT} - -# Install production dependencies only -RUN poetry install --only model_updater --no-interaction --no-root - -# Entry command -# CMD ["poetry", "run", "python", "-m", "model_updater.update_models"] -CMD poetry run python -m update_models \ No newline at end of file From 169abe373fbd637f9c3f030592b23a317cfbd7f3 Mon Sep 17 00:00:00 2001 From: blaise-muhirwa Date: Wed, 4 Oct 2023 19:26:41 +0000 Subject: [PATCH 10/19] pr feedback --- .github/workflows/pipeline.yaml | 4 +- Dockerfile.app => Dockerfile | 3 ++ Dockerfile.model_updater | 42 ------------------- deploy/bin/build-push-edge-endpoint-image.sh | 1 - deploy/bin/build-push-model-updater.sh | 40 ------------------ .../k3s/edge_deployment/edge_deployment.yaml | 6 ++- pyproject.toml | 11 ----- 7 files changed, 9 insertions(+), 98 deletions(-) rename Dockerfile.app => Dockerfile (97%) delete mode 100644 Dockerfile.model_updater delete mode 100755 deploy/bin/build-push-model-updater.sh diff --git a/.github/workflows/pipeline.yaml b/.github/workflows/pipeline.yaml index ef83540d..9d63bad3 100644 --- a/.github/workflows/pipeline.yaml +++ b/.github/workflows/pipeline.yaml @@ -66,7 +66,7 @@ jobs: sudo apt-get update sudo apt-get install docker-ce - name: Build Docker Image - run: docker build -f Dockerfile.app --tag groundlight-edge . + run: docker build --tag groundlight-edge . - name: Start Docker Container id: start_container @@ -136,7 +136,7 @@ jobs: sudo apt-get update sudo apt-get install docker-ce - name: Build Docker Image - run: docker build -f Dockerfile.app --tag groundlight-edge . + run: docker build --tag groundlight-edge . - name: Start Docker Container id: start_container diff --git a/Dockerfile.app b/Dockerfile similarity index 97% rename from Dockerfile.app rename to Dockerfile index 92e5d0b8..7c2ba38d 100644 --- a/Dockerfile.app +++ b/Dockerfile @@ -55,6 +55,9 @@ RUN mkdir /etc/groundlight/edge-config && \ # Copy configs COPY configs ${APP_ROOT}/configs +# Copy model updating code +COPY model_updater ${APP_ROOT}/model_updater + COPY deploy/k3s/inference_deployment/inference_deployment_template.yaml \ /etc/groundlight/inference-deployment/ diff --git a/Dockerfile.model_updater b/Dockerfile.model_updater deleted file mode 100644 index 02fe3ff1..00000000 --- a/Dockerfile.model_updater +++ /dev/null @@ -1,42 +0,0 @@ -# Build args -ARG APP_ROOT="/model_updater" -ARG POETRY_HOME="/opt/poetry" -ARG POETRY_VERSION=1.5.1 - -FROM python:3.11-slim-bullseye - -# Args that are needed in this stage -ARG APP_ROOT -ARG POETRY_HOME -ARG POETRY_VERSION - -# Install required dependencies and tools -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - bash \ - curl \ - libglib2.0-0 \ - libgl1-mesa-glx \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* \ - && curl -sSL https://install.python-poetry.org | python - - -# Set Python and Poetry ENV vars -ENV PYTHONUNBUFFERED=1 \ - PYTHONDONTWRITEBYTECODE=1 \ - POETRY_HOME=${POETRY_HOME} \ - POETRY_VERSION=${POETRY_VERSION} \ - PATH=${POETRY_HOME}/bin:$PATH - -COPY model_updater ${APP_ROOT}/model_updater -COPY app/core ${APP_ROOT}/app/core - -COPY ./pyproject.toml ${APP_ROOT}/ - -WORKDIR ${APP_ROOT} - -# Install production dependencies only -RUN poetry install --only model_updater --no-interaction --no-root - -# Entry command -CMD poetry run python -m model_updater.update_models \ No newline at end of file diff --git a/deploy/bin/build-push-edge-endpoint-image.sh b/deploy/bin/build-push-edge-endpoint-image.sh index 941e468b..9e846e46 100755 --- a/deploy/bin/build-push-edge-endpoint-image.sh +++ b/deploy/bin/build-push-edge-endpoint-image.sh @@ -38,5 +38,4 @@ docker buildx inspect tempgroundlightedgebuilder --bootstrap docker buildx build \ --platform linux/arm64,linux/amd64 \ --tag 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:${TAG} \ - -f ../../Dockerfile.app \ ../.. --push diff --git a/deploy/bin/build-push-model-updater.sh b/deploy/bin/build-push-model-updater.sh deleted file mode 100755 index 0d296189..00000000 --- a/deploy/bin/build-push-model-updater.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash - -set -ex - - -# Ensure that you're in the same directory as this script before running it -cd "$(dirname "$0")" - -TAG=$(./git-tag-name.sh) - -# Authenticate docker to ECR -aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin 723181461334.dkr.ecr.us-west-2.amazonaws.com - -# We use docker buildx to build the image for multiple platforms. buildx comes -# installed with Docker Engine when installed via Docker Desktop. If you're -# on a Linux machine with an old version of Docker Engine, you may need to -# install buildx manually. Follow these instructions to install docker-buildx-plugin: -# https://docs.docker.com/engine/install/ubuntu/ - -# Install QEMU, a generic and open-source machine emulator and virtualizer -docker run --rm --privileged linuxkit/binfmt:af88a591f9cc896a52ce596b9cf7ca26a061ef97 - -# Check if tempbuilder already exists -if ! docker buildx ls | grep -q tempmodelupdaterbuilder; then - # Prep for multiplatform build - the build is done INSIDE a docker container - docker buildx create --name tempmodelupdaterbuilder --use -else - # If tempbuilder exists, set it as the current builder - docker buildx use tempmodelupdaterbuilder -fi - -# Ensure that the tempbuilder container is running -docker buildx inspect tempmodelupdaterbuilder --bootstrap - -# Build model updater image for amd64 and arm64 -docker buildx build \ - --platform linux/arm64,linux/amd64 \ - --tag 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:${TAG} \ - -f ../../Dockerfile.model_updater \ - ../.. --push diff --git a/deploy/k3s/edge_deployment/edge_deployment.yaml b/deploy/k3s/edge_deployment/edge_deployment.yaml index aca03e1d..961503f0 100644 --- a/deploy/k3s/edge_deployment/edge_deployment.yaml +++ b/deploy/k3s/edge_deployment/edge_deployment.yaml @@ -40,7 +40,7 @@ spec: serviceAccountName: edge-endpoint-service-account containers: - name: edge-endpoint - image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:4526476fb-model-updater + image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:model-updater-b86cb9703-dirty-14d92e2791bb10d imagePullPolicy: IfNotPresent ports: - containerPort: 6717 @@ -63,8 +63,10 @@ spec: mountPath: /mnt/models - name: inference-model-updater - image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:953306448-model-updater + image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:model-updater-b86cb9703-dirty-14d92e2791bb10d imagePullPolicy: IfNotPresent + command: ["/bin/bash", "-c"] + args: ["poetry run python -m model_updater.update_models"] env: - name: LOG_LEVEL value: "INFO" diff --git a/pyproject.toml b/pyproject.toml index 8aaac1bb..f95734bc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,17 +21,6 @@ tritonclient = {extras = ["all"], version = "2.36.0"} kubernetes = "^27.2.0" jinja2 = "^3.1.2" -[tool.poetry.group.model_updater.dependencies] -python = "^3.9" -fastapi = "^0.88.0" -pydantic = "^1.10.2" -pillow = "^9.5.0" -pyyaml = "^6.0" -svix-ksuid = "^0.6.2" -tritonclient = {extras = ["all"], version = "2.36.0"} -jinja2 = "^3.1.2" -requests = "^2.28.1" - [tool.poetry.group.dev.dependencies] pytest = "^7.2.0" pytest-cov = "^4.0.0" From 6a322f22645e271da095fd7aca25c04625ddc080 Mon Sep 17 00:00:00 2001 From: blaise-muhirwa Date: Wed, 4 Oct 2023 21:13:52 +0000 Subject: [PATCH 11/19] reorganize stuff --- Dockerfile | 7 ++++--- app/core/app_state.py | 28 +++++++++++++++++++++++--- app/core/configs.py | 8 ++++---- app/core/utils.py | 29 --------------------------- configs/edge-config.yaml | 6 +----- model_updater/update_models.py | 34 +++++++++++++++++--------------- test/setup_inference_test_env.sh | 1 + 7 files changed, 53 insertions(+), 60 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7c2ba38d..953c6cff 100644 --- a/Dockerfile +++ b/Dockerfile @@ -55,9 +55,6 @@ RUN mkdir /etc/groundlight/edge-config && \ # Copy configs COPY configs ${APP_ROOT}/configs -# Copy model updating code -COPY model_updater ${APP_ROOT}/model_updater - COPY deploy/k3s/inference_deployment/inference_deployment_template.yaml \ /etc/groundlight/inference-deployment/ @@ -77,6 +74,10 @@ WORKDIR ${APP_ROOT} # Copy the remaining files COPY /app ${APP_ROOT}/app/ + +# Copy model updating code +COPY model_updater ${APP_ROOT}/model_updater + COPY --from=production-dependencies-build-stage ${APP_ROOT}/configs/nginx.conf /etc/nginx/nginx.conf # Remove default nginx config diff --git a/app/core/app_state.py b/app/core/app_state.py index c1cba097..416bb968 100644 --- a/app/core/app_state.py +++ b/app/core/app_state.py @@ -14,12 +14,11 @@ from app.core.utils import safe_call_api -from .configs import LocalInferenceConfig, MotionDetectionConfig +from .configs import LocalInferenceConfig, MotionDetectionConfig, RootEdgeConfig from .edge_inference import EdgeInferenceManager -from .file_paths import INFERENCE_DEPLOYMENT_TEMPLATE_PATH +from .file_paths import INFERENCE_DEPLOYMENT_TEMPLATE_PATH, DEFAULT_EDGE_CONFIG_PATH from .iqe_cache import IQECache from .motion_detection import MotionDetectionManager -from .utils import load_edge_config logger = logging.getLogger(__name__) @@ -28,6 +27,29 @@ TTL_TIME = 3600 # 1 hour +def load_edge_config() -> RootEdgeConfig: + """ + Reads the edge config from the EDGE_CONFIG environment variable if it exists. + If EDGE_CONFIG is not set, reads the default edge config file. + """ + yaml_config = os.environ.get("EDGE_CONFIG", "").strip() + if yaml_config: + config = yaml.safe_load(yaml_config) + return RootEdgeConfig(**config) + + logger.warning("EDGE_CONFIG environment variable not set. Checking default locations.") + + default_paths = [DEFAULT_EDGE_CONFIG_PATH, "configs/edge-config.yaml"] + + for path in default_paths: + if os.path.exists(path): + logger.info(f"Loading edge config from {path}") + config = yaml.safe_load(open(path, "r")) + return RootEdgeConfig(**config) + + raise FileNotFoundError(f"Could not find edge config file in default locations: {default_paths}") + + @lru_cache(maxsize=MAX_SDK_INSTANCES_CACHE_SIZE) def _get_groundlight_sdk_instance_internal(api_token: str): return Groundlight(api_token=api_token) diff --git a/app/core/configs.py b/app/core/configs.py index 28f229fe..1d0c6e8f 100644 --- a/app/core/configs.py +++ b/app/core/configs.py @@ -32,11 +32,11 @@ class LocalInferenceConfig(BaseModel): """ enabled: bool = Field(False, description="Determines if local edge inference is enabled for a specific detector.") - refresh_every: float = Field( - 3600.0, + refresh_rate: float = Field( + 120.0, description=( "The refresh rate for the inference server (in seconds). This means how often to check for an updated model" - " binary (currently unused)." + " binary." ), ) @@ -80,7 +80,7 @@ def validate_templates( 'local_inference_templates': { 'default': LocalInferenceConfig( enabled=True, - refresh_every=3600.0 + refresh_rate=120.0 ) } } diff --git a/app/core/utils.py b/app/core/utils.py index e6d28dbc..4bf95b26 100644 --- a/app/core/utils.py +++ b/app/core/utils.py @@ -4,38 +4,9 @@ from typing import Callable import ksuid -import yaml from fastapi import HTTPException from PIL import Image -from .configs import RootEdgeConfig -from .file_paths import DEFAULT_EDGE_CONFIG_PATH - -logger = logging.getLogger(__name__) - - -def load_edge_config() -> RootEdgeConfig: - """ - Reads the edge config from the EDGE_CONFIG environment variable if it exists. - If EDGE_CONFIG is not set, reads the default edge config file. - """ - yaml_config = os.environ.get("EDGE_CONFIG", "").strip() - if yaml_config: - config = yaml.safe_load(yaml_config) - return RootEdgeConfig(**config) - - logger.warning("EDGE_CONFIG environment variable not set. Checking default locations.") - - default_paths = [DEFAULT_EDGE_CONFIG_PATH, "configs/edge-config.yaml"] - - for path in default_paths: - if os.path.exists(path): - logger.info(f"Loading edge config from {path}") - config = yaml.safe_load(open(path, "r")) - return RootEdgeConfig(**config) - - raise FileNotFoundError(f"Could not find edge config file in default locations: {default_paths}") - def safe_call_api(api_method: Callable, **kwargs): """ diff --git a/configs/edge-config.yaml b/configs/edge-config.yaml index d28a526c..ed361a05 100644 --- a/configs/edge-config.yaml +++ b/configs/edge-config.yaml @@ -26,11 +26,7 @@ local_inference_templates: default: enabled: true # How often to fetch a new model binary (in seconds) - refresh_every: 3600 - - super-fast-refresh: - enabled: true - refresh_every: 60 + refresh_rate: 120 disabled: enabled: false diff --git a/model_updater/update_models.py b/model_updater/update_models.py index 285102eb..f0e3faa9 100644 --- a/model_updater/update_models.py +++ b/model_updater/update_models.py @@ -9,29 +9,31 @@ logging.basicConfig(level=log_level) -def update_models(): +def update_models(edge_inference_manager: EdgeInferenceManager): if not os.environ.get("DEPLOY_DETECTOR_LEVEL_INFERENCE", None): return - edge_config: RootEdgeConfig = load_edge_config() + inference_config = edge_inference_manager.inference_config + refresh_rate = inference_config.refresh_rate + + while True: + for detector_id, inference_config in inference_config.items(): + if inference_config.enabled: + try: + edge_inference_manager.update_model(detector_id=detector_id) + except Exception as e: + logging.error(f"Failed to update model for {detector_id}. {e}", exc_info=True) + time.sleep(refresh_rate) + + +if __name__ == "__main__": + edge_config: RootEdgeConfig = load_edge_config() edge_inference_templates = edge_config.local_inference_templates inference_config = { detector.detector_id: edge_inference_templates[detector.local_inference_template] for detector in edge_config.detectors } + edge_inference_manager = EdgeInferenceManager(config=inference_config, verbose=True) - edge_inference_manager = EdgeInferenceManager(config=edge_config.local_inference_templates, verbose=True) - - for detector_id, inference_config in inference_config.items(): - if inference_config.enabled: - try: - edge_inference_manager.update_model(detector_id=detector_id) - except Exception as e: - logging.error(f"Failed to update model for {detector_id}. {e}", exc_info=True) - - -if __name__ == "__main__": - while True: - update_models() - time.sleep(3600) + update_models(edge_inference_manager=edge_inference_manager) diff --git a/test/setup_inference_test_env.sh b/test/setup_inference_test_env.sh index 0cc26b52..9cc443a1 100755 --- a/test/setup_inference_test_env.sh +++ b/test/setup_inference_test_env.sh @@ -20,6 +20,7 @@ motion_detection_templates: local_inference_templates: default: enabled: true + refresh_rate: 120 disabled: enabled: false From 86696c35f7f22306ee8033845fd3092aff0bd6f5 Mon Sep 17 00:00:00 2001 From: blaise-muhirwa Date: Wed, 4 Oct 2023 21:24:14 +0000 Subject: [PATCH 12/19] update image --- deploy/k3s/edge_deployment/edge_deployment.yaml | 4 ++-- model_updater/update_models.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy/k3s/edge_deployment/edge_deployment.yaml b/deploy/k3s/edge_deployment/edge_deployment.yaml index 961503f0..0ee8eda2 100644 --- a/deploy/k3s/edge_deployment/edge_deployment.yaml +++ b/deploy/k3s/edge_deployment/edge_deployment.yaml @@ -40,7 +40,7 @@ spec: serviceAccountName: edge-endpoint-service-account containers: - name: edge-endpoint - image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:model-updater-b86cb9703-dirty-14d92e2791bb10d + image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:6a322f226-model-updater imagePullPolicy: IfNotPresent ports: - containerPort: 6717 @@ -63,7 +63,7 @@ spec: mountPath: /mnt/models - name: inference-model-updater - image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:model-updater-b86cb9703-dirty-14d92e2791bb10d + image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:6a322f226-model-updater imagePullPolicy: IfNotPresent command: ["/bin/bash", "-c"] args: ["poetry run python -m model_updater.update_models"] diff --git a/model_updater/update_models.py b/model_updater/update_models.py index f0e3faa9..e90c971d 100644 --- a/model_updater/update_models.py +++ b/model_updater/update_models.py @@ -1,7 +1,7 @@ import os import logging import time -from app.core.utils import load_edge_config +from app.core.app_state import load_edge_config from app.core.configs import RootEdgeConfig from app.core.edge_inference import EdgeInferenceManager From 53f4a52e69477940faad0fefecd541c99bfb5d30 Mon Sep 17 00:00:00 2001 From: blaise-muhirwa Date: Wed, 4 Oct 2023 21:33:30 +0000 Subject: [PATCH 13/19] try/except block --- deploy/k3s/edge_deployment/edge_deployment.yaml | 4 ++-- model_updater/update_models.py | 14 ++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/deploy/k3s/edge_deployment/edge_deployment.yaml b/deploy/k3s/edge_deployment/edge_deployment.yaml index 0ee8eda2..03d8d12e 100644 --- a/deploy/k3s/edge_deployment/edge_deployment.yaml +++ b/deploy/k3s/edge_deployment/edge_deployment.yaml @@ -40,7 +40,7 @@ spec: serviceAccountName: edge-endpoint-service-account containers: - name: edge-endpoint - image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:6a322f226-model-updater + image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:86696c35f-model-updater imagePullPolicy: IfNotPresent ports: - containerPort: 6717 @@ -63,7 +63,7 @@ spec: mountPath: /mnt/models - name: inference-model-updater - image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:6a322f226-model-updater + image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:86696c35f-model-updater imagePullPolicy: IfNotPresent command: ["/bin/bash", "-c"] args: ["poetry run python -m model_updater.update_models"] diff --git a/model_updater/update_models.py b/model_updater/update_models.py index e90c971d..4c5de4ac 100644 --- a/model_updater/update_models.py +++ b/model_updater/update_models.py @@ -10,15 +10,21 @@ def update_models(edge_inference_manager: EdgeInferenceManager): - if not os.environ.get("DEPLOY_DETECTOR_LEVEL_INFERENCE", None): + if not os.environ.get("DEPLOY_DETECTOR_LEVEL_INFERENCE", None) or not edge_inference_manager.inference_config: return inference_config = edge_inference_manager.inference_config - refresh_rate = inference_config.refresh_rate + + try: + # All detectors should have the same refresh rate. + refresh_rate = list(inference_config.value())[0].refresh_rate + except Exception as e: + logging.error(f"Failed to get refresh rate. {e}", exc_info=True) + return while True: - for detector_id, inference_config in inference_config.items(): - if inference_config.enabled: + for detector_id, config in inference_config.items(): + if config.enabled: try: edge_inference_manager.update_model(detector_id=detector_id) except Exception as e: From d93e584937804820f032606a34b9a7971af70978 Mon Sep 17 00:00:00 2001 From: blaise-muhirwa Date: Wed, 4 Oct 2023 21:36:00 +0000 Subject: [PATCH 14/19] dict method error solved --- deploy/k3s/edge_deployment/edge_deployment.yaml | 4 ++-- model_updater/update_models.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy/k3s/edge_deployment/edge_deployment.yaml b/deploy/k3s/edge_deployment/edge_deployment.yaml index 03d8d12e..b3257dff 100644 --- a/deploy/k3s/edge_deployment/edge_deployment.yaml +++ b/deploy/k3s/edge_deployment/edge_deployment.yaml @@ -40,7 +40,7 @@ spec: serviceAccountName: edge-endpoint-service-account containers: - name: edge-endpoint - image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:86696c35f-model-updater + image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:53f4a52e6-model-updater imagePullPolicy: IfNotPresent ports: - containerPort: 6717 @@ -63,7 +63,7 @@ spec: mountPath: /mnt/models - name: inference-model-updater - image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:86696c35f-model-updater + image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:53f4a52e6-model-updater imagePullPolicy: IfNotPresent command: ["/bin/bash", "-c"] args: ["poetry run python -m model_updater.update_models"] diff --git a/model_updater/update_models.py b/model_updater/update_models.py index 4c5de4ac..96948691 100644 --- a/model_updater/update_models.py +++ b/model_updater/update_models.py @@ -17,7 +17,7 @@ def update_models(edge_inference_manager: EdgeInferenceManager): try: # All detectors should have the same refresh rate. - refresh_rate = list(inference_config.value())[0].refresh_rate + refresh_rate = list(inference_config.values())[0].refresh_rate except Exception as e: logging.error(f"Failed to get refresh rate. {e}", exc_info=True) return From a85b32a3d00bf03369edcc9c3ddf82152eb9da8d Mon Sep 17 00:00:00 2001 From: blaise-muhirwa Date: Wed, 4 Oct 2023 21:37:29 +0000 Subject: [PATCH 15/19] new image --- deploy/k3s/edge_deployment/edge_deployment.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/k3s/edge_deployment/edge_deployment.yaml b/deploy/k3s/edge_deployment/edge_deployment.yaml index b3257dff..c532c319 100644 --- a/deploy/k3s/edge_deployment/edge_deployment.yaml +++ b/deploy/k3s/edge_deployment/edge_deployment.yaml @@ -40,7 +40,7 @@ spec: serviceAccountName: edge-endpoint-service-account containers: - name: edge-endpoint - image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:53f4a52e6-model-updater + image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:d93e58493-model-updater imagePullPolicy: IfNotPresent ports: - containerPort: 6717 @@ -63,7 +63,7 @@ spec: mountPath: /mnt/models - name: inference-model-updater - image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:53f4a52e6-model-updater + image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:d93e58493-model-updater imagePullPolicy: IfNotPresent command: ["/bin/bash", "-c"] args: ["poetry run python -m model_updater.update_models"] From 11c818f8ab38d91cc488e01aaca368ef7f0be860 Mon Sep 17 00:00:00 2001 From: Auto-format Bot Date: Wed, 4 Oct 2023 21:39:03 +0000 Subject: [PATCH 16/19] Automatically reformatting code with black and isort --- app/core/app_state.py | 2 +- app/core/utils.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/core/app_state.py b/app/core/app_state.py index 416bb968..bb33d710 100644 --- a/app/core/app_state.py +++ b/app/core/app_state.py @@ -16,7 +16,7 @@ from .configs import LocalInferenceConfig, MotionDetectionConfig, RootEdgeConfig from .edge_inference import EdgeInferenceManager -from .file_paths import INFERENCE_DEPLOYMENT_TEMPLATE_PATH, DEFAULT_EDGE_CONFIG_PATH +from .file_paths import DEFAULT_EDGE_CONFIG_PATH, INFERENCE_DEPLOYMENT_TEMPLATE_PATH from .iqe_cache import IQECache from .motion_detection import MotionDetectionManager diff --git a/app/core/utils.py b/app/core/utils.py index 4bf95b26..67fd223a 100644 --- a/app/core/utils.py +++ b/app/core/utils.py @@ -1,5 +1,3 @@ -import logging -import os from io import BytesIO from typing import Callable From e228ffcef4445811fcc87c07f5e56f983b411fc3 Mon Sep 17 00:00:00 2001 From: blaise-muhirwa Date: Wed, 4 Oct 2023 21:39:43 +0000 Subject: [PATCH 17/19] remove unnecessary change --- app/core/app_state.py | 2 +- app/core/utils.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/core/app_state.py b/app/core/app_state.py index 416bb968..bb33d710 100644 --- a/app/core/app_state.py +++ b/app/core/app_state.py @@ -16,7 +16,7 @@ from .configs import LocalInferenceConfig, MotionDetectionConfig, RootEdgeConfig from .edge_inference import EdgeInferenceManager -from .file_paths import INFERENCE_DEPLOYMENT_TEMPLATE_PATH, DEFAULT_EDGE_CONFIG_PATH +from .file_paths import DEFAULT_EDGE_CONFIG_PATH, INFERENCE_DEPLOYMENT_TEMPLATE_PATH from .iqe_cache import IQECache from .motion_detection import MotionDetectionManager diff --git a/app/core/utils.py b/app/core/utils.py index 4bf95b26..67fd223a 100644 --- a/app/core/utils.py +++ b/app/core/utils.py @@ -1,5 +1,3 @@ -import logging -import os from io import BytesIO from typing import Callable From 6ef532de5dc2335ac1b248e3b187253ab36b4e89 Mon Sep 17 00:00:00 2001 From: blaise-muhirwa Date: Thu, 5 Oct 2023 16:17:11 +0000 Subject: [PATCH 18/19] error log if refresh rates are different --- model_updater/update_models.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/model_updater/update_models.py b/model_updater/update_models.py index 96948691..522d34e2 100644 --- a/model_updater/update_models.py +++ b/model_updater/update_models.py @@ -15,12 +15,12 @@ def update_models(edge_inference_manager: EdgeInferenceManager): inference_config = edge_inference_manager.inference_config - try: - # All detectors should have the same refresh rate. - refresh_rate = list(inference_config.values())[0].refresh_rate - except Exception as e: - logging.error(f"Failed to get refresh rate. {e}", exc_info=True) - return + # All detectors should have the same refresh rate. + refresh_rates = [config.refresh_rate for config in inference_config.values()] + if set(refresh_rates) != 1: + logging.error(f"Detectors have different refresh rates.") + + refresh_rate = refresh_rates[0] while True: for detector_id, config in inference_config.items(): From 9ac008fcfd5951ebbe8fef12d7cbb80f53da9ca8 Mon Sep 17 00:00:00 2001 From: blaise-muhirwa Date: Thu, 5 Oct 2023 16:21:31 +0000 Subject: [PATCH 19/19] update image --- deploy/k3s/edge_deployment/edge_deployment.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/k3s/edge_deployment/edge_deployment.yaml b/deploy/k3s/edge_deployment/edge_deployment.yaml index c532c319..6d75121d 100644 --- a/deploy/k3s/edge_deployment/edge_deployment.yaml +++ b/deploy/k3s/edge_deployment/edge_deployment.yaml @@ -40,7 +40,7 @@ spec: serviceAccountName: edge-endpoint-service-account containers: - name: edge-endpoint - image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:d93e58493-model-updater + image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:6ef532de5-model-updater imagePullPolicy: IfNotPresent ports: - containerPort: 6717 @@ -63,7 +63,7 @@ spec: mountPath: /mnt/models - name: inference-model-updater - image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:d93e58493-model-updater + image: 723181461334.dkr.ecr.us-west-2.amazonaws.com/edge-endpoint:6ef532de5-model-updater imagePullPolicy: IfNotPresent command: ["/bin/bash", "-c"] args: ["poetry run python -m model_updater.update_models"]