diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 3c66f3f..5f7e5a8 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -26,5 +26,12 @@
"workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind",
"mounts": [
"source=${localEnv:HOME}/.cache/pip,target=/home/vscode/.cache/pip,type=bind"
- ]
+ ],
+ "customizations": {
+ "vscode": {
+ "extensions": [
+ "charliermarsh.ruff"
+ ]
+ }
+ }
}
diff --git a/.dockerignore b/.dockerignore
index adc4220..8850973 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,10 +1,101 @@
.DS_Store
-.idea
-__pycache__
-venv
-venv-test
tmp_cat.log
# skip the custom envs
#envs
# skip the models directory
-models
\ No newline at end of file
+models
+!models/examples
+models/examples/example-medcat-v1-model-pack
+
+## Default Python .dockerignore
+# Git
+.git
+.gitignore
+.gitattributes
+
+
+# CI
+.codeclimate.yml
+.travis.yml
+.taskcluster.yml
+
+# Docker
+docker/
+docker-compose.yml
+Dockerfile
+.docker
+.dockerignore
+
+# Byte-compiled / optimized / DLL files
+**/__pycache__/
+**/*.py[cod]
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.cache
+nosetests.xml
+coverage.xml
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Virtual environment
+.env
+.venv/
+venv/
+
+# PyCharm
+.idea
+
+# Python mode for VIM
+.ropeproject
+**/.ropeproject
+
+# Vim swap files
+**/*.swp
+
+# VS Code
+.vscode/
+.devcontainer
\ No newline at end of file
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 7978135..476d36a 100755
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -15,6 +15,8 @@ on:
jobs:
build:
runs-on: ubuntu-latest
+ outputs:
+ image_version: ${{ steps.meta.outputs.version }}
steps:
- name: Log in to Docker Hub
uses: docker/login-action@v1
@@ -79,4 +81,27 @@ jobs:
cache-to: type=registry,ref=cogstacksystems/medcat-service-gpu:buildcache,mode=max
- name: Image digest
- run: echo ${{ steps.docker_build.outputs.digest }}
\ No newline at end of file
+ run: echo ${{ steps.docker_build.outputs.digest }}
+ integration_test:
+ runs-on: ubuntu-latest
+ needs: build
+ steps:
+ - name: Check out code
+ uses: actions/checkout@v4
+
+ - name: Run Test with example model pack
+ run: |
+ echo "๐งช Running Examples test..."
+ export IMAGE_TAG=${{ needs.build.outputs.image_version }} # Improve by running exact digest instead
+ echo "Running with image tag ${IMAGE_TAG}"
+ bash scripts/test_examples.sh
+
+ - name: Report test result
+ if: always()
+ run: |
+ if [ $? -eq 0 ]; then
+ echo "โ
Integration test PASSED"
+ else
+ echo "โ Integration test FAILED"
+ exit 1
+ fi
diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml
index 45541eb..fb6f16b 100755
--- a/.github/workflows/run_tests.yml
+++ b/.github/workflows/run_tests.yml
@@ -27,18 +27,26 @@ jobs:
- name: checkout repo
uses: actions/checkout@v2
+ - name: Cache MedMen Model
+ id: cache-medmen
+ uses: actions/cache@v4
+ with:
+ path: models/medmen
+ key: medmen-${{ hashFiles('scripts/download_medmen.sh') }}
+
- name: Install Python 3
- uses: actions/setup-python@v1
+ uses: actions/setup-python@v5
with:
python-version: 3.9
+ cache: 'pip' # caching pip dependencies
- name: Install dependencies
run: |
sudo apt-get install -y isort flake8
python -m pip install --upgrade pip
python -m pip install virtualenv setuptools
- python -m pip install isort flake8 mypy stubs types-Flask types-simplejson types-setuptools
- python -m pip install -r ./requirements.txt
+ python -m pip install isort flake8 mypy stubs types-Flask types-simplejson types-setuptools types-requests
+ python -m pip install -r ./requirements.txt --extra-index-url https://download.pytorch.org/whl/cpu/;
- name: Check linting and types
run: |
diff --git a/.gitignore b/.gitignore
index 4dd9bc4..4e37395 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,8 @@ __pycache__
# skip the models directory
models/*
!models/*.sh
+!models/examples
+models/examples/example-medcat-v1-model-pack
# tmp folder
tmp/*
diff --git a/.ruff.toml b/.ruff.toml
new file mode 100644
index 0000000..4a52c44
--- /dev/null
+++ b/.ruff.toml
@@ -0,0 +1,19 @@
+line-length = 120
+indent-width = 4
+
+[lint]
+# 1. Enable flake8-bugbear (`B`) rules, in addition to the defaults.
+select = [
+ # pycodestyle
+ "E",
+ # Pyflakes
+ "F",
+ # pyupgrade
+ "UP",
+ # flake8-bugbear
+ "B",
+ # flake8-simplify
+ "SIM",
+ # isort
+ "I",
+]
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index 79b2608..cbb779b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -5,14 +5,22 @@ ENV CRYPTOGRAPHY_DONT_BUILD_RUST=1
# Set the python path and preapre the base layer
WORKDIR /cat
COPY ./requirements.txt /cat
-RUN pip install --upgrade pip
-# Install requirements for the app
-RUN pip3 install --no-cache-dir -r requirements.txt
+# Install Python dependencies
+ARG USE_CPU_TORCH=true
+# NOTE: Allow building without GPU so as to lower image size (GPU is disabled by default)
+RUN pip install -U pip && \
+ if [ "${USE_CPU_TORCH}" = "true" ]; then \
+ echo "Installing Torch for CPU, without GPU support " && \
+ pip install --no-cache-dir -r requirements.txt --extra-index-url https://download.pytorch.org/whl/cpu/; \
+ else \
+ echo "Installing Torch with GPU support" && \
+ pip install --no-cache-dir -r requirements.txt; \
+ fi
# Get the spacy model
ARG SPACY_MODELS="en_core_web_sm en_core_web_md en_core_web_lg"
-RUN for spacy_model in ${SPACY_MODELS}; do python -m spacy download $spacy_model; done
+RUN for spacy_model in $SPACY_MODELS; do python -m spacy download $spacy_model; done
# Copy the remaining files
COPY . /cat
diff --git a/Dockerfile_gpu b/Dockerfile_gpu
index aa738f9..2638ca7 100644
--- a/Dockerfile_gpu
+++ b/Dockerfile_gpu
@@ -41,7 +41,7 @@ RUN pip install --no-cache-dir -r requirements.txt
# Get the spacy model
ARG SPACY_MODELS="en_core_web_sm en_core_web_md en_core_web_lg"
-RUN for spacy_model in ${SPACY_MODELS}; do python -m spacy download $spacy_model; done
+RUN for spacy_model in $SPACY_MODELS; do python -m spacy download $spacy_model; done
# Copy the remaining files
COPY . /cat
diff --git a/README.md b/README.md
index 90d56e2..c275978 100644
--- a/README.md
+++ b/README.md
@@ -35,7 +35,7 @@ There are two scripts provided implementing starting the application:
## Running in a Docker container
The recommended way to run the application is to use the provided Docker image. The Docker image can be either downloaded from the Docker Hub (`cogstacksystems/medcat-service:latest`) or build manually using the provided `Dockerfile`.
-Please note that by default the built docker image will run the Flask application in 'production' mode running `start-service-prod.sh` script.
+Please note that by default the built docker image will run the Flask application in 'production' mode running `start_service_production.sh` script.
To build the Docker image manually:
@@ -59,7 +59,7 @@ If you have a gpu and wish to use it, please change the `docker/docker-compose.y
### IMPORTANT !
If you wish to run this docker service manually, use the docker/docker-compose.yml file, execute `docker compose up -d` whilst in the `docker` folder.
-Alternatively, an example script `./docker/run_example_medmen.sh` was provided to run the Docker container with MedCAT service. The script will download an example model (using the `./models/download_medmen.sh` script),it will use an example environment configuration, then it will build and start the service using the provided Docker Compose file, the service WONT WORK without the model being present.
+Alternatively, an example script `./docker/run_example_medmen.sh` was provided to run the Docker container with MedCAT service. The script will download an example model (using the `./scripts/download_medmen.sh` script),it will use an example environment configuration, then it will build and start the service using the provided Docker Compose file, the service WONT WORK without the model being present.
All models should be mounted from the `models/` folder.
diff --git a/docker/docker-compose-example-medmen.yml b/docker/docker-compose-example-medmen.yml
index 848a6d1..75563b8 100755
--- a/docker/docker-compose-example-medmen.yml
+++ b/docker/docker-compose-example-medmen.yml
@@ -10,6 +10,11 @@ services:
- http_proxy=$HTTP_PROXY
- https_proxy=$HTTPS_PROXY
- no_proxy=$no_proxy
+ - ENABLE_MODEL_DOWNLOAD=true
+ - MODEL_NAME=medmen
+ - MODEL_VOCAB_URL=https://cogstack-medcat-example-models.s3.eu-west-2.amazonaws.com/medcat-example-models/vocab.dat
+ - MODEL_CDB_URL=https://cogstack-medcat-example-models.s3.eu-west-2.amazonaws.com/medcat-example-models/cdb-medmen-v1.dat
+ - MODEL_META_URL=https://cogstack-medcat-example-models.s3.eu-west-2.amazonaws.com/medcat-example-models/mc_status.zip
env_file:
- ../env/app.env
- ../env/medcat.env
@@ -21,27 +26,7 @@ services:
networks:
- cognet
- nlp-medcat-service-production-deid:
- ### Multiple images available:
- ## default image, only CPU support: cogstacksystems/medcat-service:latest
- ## GPU support: cogstacksystems/medcat-service-gpu:latest
- image: cogstacksystems/medcat-service:latest
- restart: always
- environment:
- - http_proxy=$HTTP_PROXY
- - https_proxy=$HTTPS_PROXY
- - no_proxy=$no_proxy
- env_file:
- - ../env/app_deid.env
- - ../env/medcat_deid.env
- volumes:
- - ../models:/cat/models/
- ports:
- - "5556:5000"
- networks:
- - cognet
-
+
networks:
cognet:
- driver: bridge
name: cogstack-net
diff --git a/docker/docker-compose.example.yml b/docker/docker-compose.example.yml
new file mode 100644
index 0000000..9af029f
--- /dev/null
+++ b/docker/docker-compose.example.yml
@@ -0,0 +1,10 @@
+name: cogstack-medcat-service
+services:
+ medcat-service:
+ image: cogstacksystems/medcat-service:${IMAGE_TAG-latest}
+ restart: unless-stopped
+ environment:
+ # Uses a preloaded model pack example inside the image
+ - APP_MEDCAT_MODEL_PACK=/cat/models/examples/example-medcat-v1-model-pack.zip
+ ports:
+ - "5555:5000"
diff --git a/docker/run_example_medmen.sh b/docker/run_example_medmen.sh
index 98831ea..5aa6f41 100755
--- a/docker/run_example_medmen.sh
+++ b/docker/run_example_medmen.sh
@@ -1,43 +1,12 @@
#!/usr/bin/env bash
-
-( cd ../models && bash download_medmen.sh )
-
-echo "Running docker-compose"
-DOCKER_COMPOSE_FILE="docker-compose-example-medmen.yml"
-docker compose -f ${DOCKER_COMPOSE_FILE} up -d
-
+DOCKER_COMPOSE_FILE="docker-compose.example-medmen.yml"
# To run in a container run "export LOCALHOST_NAME=host.docker.internal"
LOCALHOST_NAME=${LOCALHOST_NAME:-localhost}
-API="http://${LOCALHOST_NAME}:5555/api/info"
-
-MAX_RETRIES=12
-RETRY_DELAY=5
-COUNT=0
-
-while [ $COUNT -lt $MAX_RETRIES ]; do
- echo "Checking service health on $API (Attempt $((COUNT+1))/$MAX_RETRIES)"
- sleep $RETRY_DELAY
- IS_READY=$(curl -s -o /dev/null -w "%{http_code}" $API)
-
- if [ "$IS_READY" = "200" ]; then
- echo "Service is ready!"
- break
- else
- echo "Attempt $((COUNT+1))/$MAX_RETRIES: Not ready (HTTP $IS_READY)."
- docker compose -f ${DOCKER_COMPOSE_FILE} logs
- COUNT=$((COUNT+1))
- fi
-done
-
-if [ $COUNT -eq $MAX_RETRIES ]; then
- echo "โ Service did not become ready after $MAX_RETRIES attempts."
- exit 1
-fi
+echo "Running docker-compose"
+docker compose -f ${DOCKER_COMPOSE_FILE} up -d
-cat < $MODEL_VCB
- curl https://cogstack-medcat-example-models.s3.eu-west-2.amazonaws.com/medcat-example-models/cdb-medmen-v1.dat > $MODEL_CDB
-else
- echo "MedMentions model already present -- skipping download"
-fi
-
-if [[ ! -d "$MODEL_META" ]]; then
- echo "Downloading meta model: status"
- curl https://cogstack-medcat-example-models.s3.eu-west-2.amazonaws.com/medcat-example-models/mc_status.zip > $MEDMEN_DIR/mc_status.zip && \
- (cd $MEDMEN_DIR && unzip mc_status.zip) && \
- rm $MEDMEN_DIR/mc_status.zip
-else
- echo "Meta model already present -- skipping download"
-fi
diff --git a/models/examples/example-medcat-v1-model-pack.zip b/models/examples/example-medcat-v1-model-pack.zip
new file mode 100644
index 0000000..1ff6e84
Binary files /dev/null and b/models/examples/example-medcat-v1-model-pack.zip differ
diff --git a/models/examples/examples.md b/models/examples/examples.md
new file mode 100644
index 0000000..fca65ee
--- /dev/null
+++ b/models/examples/examples.md
@@ -0,0 +1,8 @@
+# Example Model Packs
+
+## [example-medcat-v1-model-pack][(models/examples/example-medcat-v1-model-pack.zip)
+- This model pack is built by running the MedCAT V1 Tutorial Part 3.1.
+- https://github.com/CogStack/MedCATtutorials/blob/5a07e4d77da404631cc16b47d3f1c6bd028de396/notebooks/introductory/Part_3_1_Building_a_Concept_Database_and_Vocabulary.ipynb
+
+It isn't a trained model, but has the concepts "Kidney Failure" and "Failure of Kidneys" built in
+
diff --git a/requirements.txt b/requirements.txt
index 65bade2..7ff331a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,4 +8,5 @@ werkzeug==3.1.3
setuptools-rust==1.11.0
medcat==1.16.0
# pinned because of issues with de-id models and past models (it will not do any de-id)
-transformers>=4.34.0,<5.0.0
\ No newline at end of file
+transformers>=4.34.0,<5.0.0
+requests==2.32.4
\ No newline at end of file
diff --git a/run_tests.sh b/run_tests.sh
index 8a6ed9e..bf0e9e3 100644
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -2,13 +2,13 @@
set -e
# download the sci-scpacy language model
-python3 -m pip install -r ./requirements.txt
+python3 -m pip install -r ./requirements.txt --extra-index-url https://download.pytorch.org/whl/cpu/;
python3 -m spacy download en_core_web_sm
python3 -m spacy download en_core_web_md
python3 -m spacy download en_core_web_lg
# download the test MedCAT model
-( cd ./models && bash download_medmen.sh )
+bash ./scripts/download_medmen.sh
export APP_CDB_MODEL="$PWD/models/medmen/cdb.dat"
export APP_VOCAB_MODEL="$PWD/models/medmen/vocab.dat"
diff --git a/scripts/download_medmen.sh b/scripts/download_medmen.sh
new file mode 100644
index 0000000..4ea1d1c
--- /dev/null
+++ b/scripts/download_medmen.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+set -e
+
+export MODEL_NAME=medmen
+export MODEL_VOCAB_URL=https://cogstack-medcat-example-models.s3.eu-west-2.amazonaws.com/medcat-example-models/vocab.dat
+export MODEL_CDB_URL=https://cogstack-medcat-example-models.s3.eu-west-2.amazonaws.com/medcat-example-models/cdb-medmen-v1.dat
+export MODEL_META_URL=https://cogstack-medcat-example-models.s3.eu-west-2.amazonaws.com/medcat-example-models/mc_status.zip
+
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+python ${SCRIPT_DIR}/download_model.py
\ No newline at end of file
diff --git a/scripts/download_model.py b/scripts/download_model.py
new file mode 100644
index 0000000..83bf47e
--- /dev/null
+++ b/scripts/download_model.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python3
+import logging
+import os
+import sys
+from pathlib import Path
+from zipfile import ZipFile
+
+import requests
+
+# Required environment variables
+required_vars = {
+ "MODEL_NAME": "name of the model",
+ "MODEL_VOCAB_URL": "URL to vocab file",
+ "MODEL_CDB_URL": "URL to CDB file",
+ "MODEL_META_URL": "URL to meta file",
+}
+
+# Setup logging
+logging.basicConfig(
+ format="[%(asctime)s] [%(levelname)s] %(name)s: %(message)s",
+ level=logging.INFO,
+)
+log = logging.getLogger()
+
+log.info("Running MedCAT Model Downloader")
+
+# Check for missing env vars
+missing = [var for var in required_vars if not os.getenv(var)]
+if missing:
+ log.error("Missing Required environment variables:")
+ for var in missing:
+ log.error(f" {var}")
+ log.info("Usage: set these environment variables before running the script:")
+ for var, desc in required_vars.items():
+ log.info(f" {var:<16} - {desc}")
+
+ sys.exit(1)
+
+# Load env vars
+model_name = os.environ["MODEL_NAME"]
+vocab_url = os.environ["MODEL_VOCAB_URL"]
+cdb_url = os.environ["MODEL_CDB_URL"]
+meta_url = os.environ["MODEL_META_URL"]
+
+# Prepare paths
+script_dir = Path(__file__).resolve().parent
+model_dir = script_dir.parent / "models" / model_name
+model_dir.mkdir(parents=True, exist_ok=True)
+
+vocab_file = model_dir / "vocab.dat"
+cdb_file = model_dir / "cdb.dat"
+meta_zip = model_dir / "mc_status.zip"
+meta_dir = model_dir / "Status"
+
+
+def download_file(url, dest_path):
+ log.info(f"Downloading from {url} to {dest_path}")
+ resp = requests.get(url, stream=True)
+ resp.raise_for_status()
+ total = int(resp.headers.get("content-length", 0))
+ downloaded = 0
+ chunk_size = 8192
+ last_logged_percent = 0
+
+ with open(dest_path, "wb") as f:
+ # Print status bar to the console
+ for chunk in resp.iter_content(chunk_size):
+ if chunk:
+ f.write(chunk)
+ downloaded += len(chunk)
+ if total:
+ percent = int(downloaded * 100 / total)
+ if percent - last_logged_percent >= 10 or percent == 100:
+ last_logged_percent = percent
+ done = int(50 * percent / 100)
+ downloaded_mb = downloaded / (1024 * 1024)
+ total_mb = total / (1024 * 1024)
+ log.info(f"[{'=' * done:<50}] {percent:3d}% {downloaded_mb:.2f} MB / {total_mb:.2f} MB")
+ os.chmod(dest_path, 0o644)
+ log.info(f"Download complete to {dest_path}")
+
+
+# Download vocab and cdb if missing
+if vocab_file.exists() and cdb_file.exists():
+ log.info(
+ f"{model_name} model already present with Vocabulary: '{vocab_file}' and CDB: '{cdb_file}'. Skipping download"
+ )
+else:
+ log.info(f"Starting download of MedCAT Model '{model_name}'")
+ if not vocab_file.exists():
+ download_file(vocab_url, vocab_file)
+ if not cdb_file.exists():
+ download_file(cdb_url, cdb_file)
+
+# Download and unzip meta if missing
+if not meta_dir.exists():
+ log.info("Downloading meta model: status")
+ download_file(meta_url, meta_zip)
+ with ZipFile(meta_zip, "r") as zip_ref:
+ zip_ref.extractall(model_dir)
+ meta_zip.unlink()
+else:
+ log.info(f"Meta model already present in {meta_dir} -- skipping download")
+
+log.info(f"Completed downloading model '{model_name}'")
diff --git a/scripts/integration_test_functions.sh b/scripts/integration_test_functions.sh
new file mode 100644
index 0000000..9feaea3
--- /dev/null
+++ b/scripts/integration_test_functions.sh
@@ -0,0 +1,66 @@
+smoketest_medcat_service() {
+ local localhost_name="$1"
+ local docker_compose_file="$2"
+
+ if [ -z "$localhost_name" ] || [ -z "$docker_compose_file" ]; then
+ echo "Invalid arguments. Usage: health_check " >&2
+ return 1
+ fi
+
+ API="http://${localhost_name}:5555/api/info"
+
+ MAX_RETRIES=12
+ RETRY_DELAY=5
+ COUNT=0
+
+ while [ $COUNT -lt $MAX_RETRIES ]; do
+ echo "Checking service health on $API (Attempt $((COUNT+1))/$MAX_RETRIES)"
+ sleep $RETRY_DELAY
+ IS_READY=$(curl -s -o /dev/null -w "%{http_code}" $API)
+
+ if [ "$IS_READY" = "200" ]; then
+ echo "Service is ready!"
+ break
+ else
+ echo "Attempt $((COUNT+1))/$MAX_RETRIES: Not ready (HTTP $IS_READY)."
+ docker compose -f ${DOCKER_COMPOSE_FILE} logs
+ COUNT=$((COUNT+1))
+ fi
+ done
+
+ if [ $COUNT -eq $MAX_RETRIES ]; then
+ echo "โ Service did not become ready after $MAX_RETRIES attempts."
+ exit 1
+ fi
+
+ echo "Service passed basic smoke test"
+
+}
+
+
+integration_test_medcat_service() {
+ local localhost_name=$1
+ local api="http://${localhost_name}:5555/api/process"
+ local input_text="The patient was diagnosed with Kidney Failure"
+ local input_payload="{\"content\":{\"text\":\"${input_text}\"}}"
+ local expected_annotation="Kidney Failure"
+
+ echo "Calling POST $api with payload '$input_payload'"
+ local actual
+ actual=$(curl -s -X POST $api \
+ -H 'Content-Type: application/json' \
+ -d "$input_payload")
+
+ echo "Recieved result '$actual'"
+
+ local actual_annotation
+ actual_annotation=$(echo "$actual" | jq -r '.result.annotations[0]["0"].pretty_name')
+
+ if [[ "$actual_annotation" == "$expected_annotation" ]]; then
+ echo "Service working and extracting annotations"
+ else
+ echo "Expected: $expected_annotation, Got: $actual_annotation"
+ echo -e "Actual response was:\n${actual}"
+ exit 1
+ fi
+}
\ No newline at end of file
diff --git a/scripts/test_examples.sh b/scripts/test_examples.sh
new file mode 100644
index 0000000..0c2bfa1
--- /dev/null
+++ b/scripts/test_examples.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# Integration test of medcat service docker image
+echo "Running integration test of medcat service"
+
+if [ -n "$IMAGE_TAG" ]; then
+ echo "Testing image tag $IMAGE_TAG"
+fi
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+
+cd ${SCRIPT_DIR}/../docker
+bash run_example_simple.sh
+
+# Check if health check was successful
+if [ $? -eq 0 ]; then
+ echo "โ
Success! Medcat service passed integration tests"
+ docker compose -f docker-compose.example.yml down
+ exit 0
+else
+ echo "โ Failure. Medcat service failed tests"
+ exit 1
+fi
+
diff --git a/start_service_production.sh b/start_service_production.sh
index ef8fbd9..2c20dec 100644
--- a/start_service_production.sh
+++ b/start_service_production.sh
@@ -1,4 +1,10 @@
#!/bin/bash
+echo "Starting MedCAT Service"
+
+# Optionally download model before server startup
+if [[ "$ENABLE_MODEL_DOWNLOAD" == "true" ]]; then
+ python -u /cat/scripts/download_model.py
+fi
# check the gunicorn config params
#