diff --git a/bundles/modal/README.md b/bundles/modal/README.md index 540e8cc..6251bdc 100644 --- a/bundles/modal/README.md +++ b/bundles/modal/README.md @@ -5,6 +5,7 @@ Deploy align-app as a serverless GPU application on Modal with scale-to-zero. ## Prerequisites 1. Install Modal CLI: + ```bash pip install modal modal setup # authenticate with Modal @@ -42,6 +43,12 @@ Edit `app.py` to adjust: - `timeout=30 * MINUTES` - Max request duration - `startup_timeout=5 * MINUTES` - Max time for container to start +Experiment data is baked into the image and passed to `align-app` at startup: + +- `EXPERIMENTS` - Local path copied into the image at `/app/experiments`. + If it is a directory, it is copied directly. + If it is a `.zip`, it is unpacked into `/app` during the build. + ## Costs - **L4 GPU**: ~$0.76/hour (billed per second) diff --git a/bundles/modal/app.py b/bundles/modal/app.py index b28d157..cb311c9 100644 --- a/bundles/modal/app.py +++ b/bundles/modal/app.py @@ -7,7 +7,8 @@ PORT = 8080 REPO_ROOT = Path(__file__).parent.parent.parent -EXPERIMENTS_ZIP = os.environ.get("ALIGN_EXPERIMENTS_ZIP") +EXPERIMENTS = os.environ.get("EXPERIMENTS") +EXPERIMENTS_PATH = Path(EXPERIMENTS) if EXPERIMENTS else None app = modal.App("align-app") @@ -36,25 +37,30 @@ def download_models(): .workdir("/app") ) -if EXPERIMENTS_ZIP: - image = ( - base_image.add_local_file(EXPERIMENTS_ZIP, "/app/experiments.zip", copy=True) - .run_commands( - "poetry config virtualenvs.create false && poetry install --only main", - "unzip experiments.zip -d /app && rm experiments.zip", +image = base_image + +if EXPERIMENTS_PATH and EXPERIMENTS_PATH.exists(): + if EXPERIMENTS_PATH.is_dir(): + image = image.add_local_dir( + str(EXPERIMENTS_PATH), "/app/experiments", copy=True ) - .run_function( - download_models, - secrets=[modal.Secret.from_name("huggingface")], + elif EXPERIMENTS_PATH.suffix.lower() == ".zip": + image = image.add_local_file( + str(EXPERIMENTS_PATH), "/app/experiments.zip", copy=True ) - ) -else: - image = base_image.run_commands( - "poetry config virtualenvs.create false && poetry install --only main" - ).run_function( - download_models, - secrets=[modal.Secret.from_name("huggingface")], - ) + +install_commands = [ + "poetry config virtualenvs.create false && poetry install --only main", +] + +if EXPERIMENTS_PATH and EXPERIMENTS_PATH.exists(): + if EXPERIMENTS_PATH.is_file() and EXPERIMENTS_PATH.suffix.lower() == ".zip": + install_commands.append("unzip experiments.zip -d /app && rm experiments.zip") + +image = image.run_commands(*install_commands).run_function( + download_models, + secrets=[modal.Secret.from_name("huggingface")], +) @app.function(