Skip to content

Commit 62dca37

Browse files
authored
bugfix/ODSC-43563/entryscript_mounted_as_directory (#218)
1 parent e008fad commit 62dca37

File tree

3 files changed

+43
-29
lines changed

3 files changed

+43
-29
lines changed

ads/opctl/backend/local.py

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
from ads.common.oci_client import OCIClientFactory
5555
from ads.config import NO_CONTAINER
5656

57+
5758
class CondaPackNotFound(Exception): # pragma: no cover
5859
pass
5960

@@ -219,7 +220,9 @@ def _run_with_conda_pack(
219220
)
220221
if os.path.exists(os.path.join(conda_pack_path, "spark-defaults.conf")):
221222
env_vars["SPARK_CONF_DIR"] = os.path.join(DEFAULT_IMAGE_CONDA_DIR, slug)
222-
logger.info(f"Running with conda pack in a container with command {command}")
223+
logger.info(
224+
f"Running with conda pack in a container with command {command}"
225+
)
223226
return self._activate_conda_env_and_run(
224227
image, slug, command, bind_volumes, env_vars
225228
)
@@ -419,8 +422,7 @@ def _activate_conda_env_and_run(
419422
build_image("job-local", gpu=False)
420423
else:
421424
build_image("job-local", gpu=True)
422-
423-
with tempfile.TemporaryDirectory() as td:
425+
with tempfile.TemporaryDirectory(dir=os.path.expanduser("~")) as td:
424426
with open(os.path.join(td, "entryscript.sh"), "w") as f:
425427
f.write(
426428
f"""
@@ -681,11 +683,11 @@ def predict(self) -> None:
681683
None
682684
Nothing.
683685
"""
684-
686+
685687
# model artifact in artifact directory
686688
artifact_directory = self.config["execution"].get("artifact_directory")
687689
ocid = self.config["execution"].get("ocid")
688-
690+
689691
model_folder = os.path.expanduser(
690692
self.config["execution"].get("model_save_folder", DEFAULT_MODEL_FOLDER)
691693
)
@@ -711,20 +713,23 @@ def predict(self) -> None:
711713
timeout=timeout,
712714
force_overwrite=True,
713715
)
714-
716+
715717
# conda
716-
conda_slug, conda_path = self.config["execution"].get("conda_slug"), self.config["execution"].get("conda_path")
718+
conda_slug = self.config["execution"].get("conda_slug")
719+
conda_path = self.config["execution"].get("conda_path")
717720
if not conda_slug and not conda_path and ocid:
718721
conda_slug, conda_path = self._get_conda_info_from_custom_metadata(ocid)
719722
if not conda_slug and not conda_path:
720723
conda_slug, conda_path = self._get_conda_info_from_runtime(
721724
artifact_dir=artifact_directory
722725
)
723-
if 'conda_slug' not in self.config["execution"]:
724-
self.config["execution"]["conda_slug"] = conda_path.split("/")[-1] if conda_path else conda_slug
726+
if "conda_slug" not in self.config["execution"]:
727+
self.config["execution"]["conda_slug"] = (
728+
conda_path.split("/")[-1] if conda_path else conda_slug
729+
)
725730

726731
self.config["execution"]["image"] = ML_JOB_IMAGE
727-
732+
728733
# bind_volumnes
729734
bind_volumes = {}
730735
SCRIPT = "script.py"
@@ -735,39 +740,45 @@ def predict(self) -> None:
735740
os.path.dirname(self.config["execution"]["oci_config"])
736741
): {"bind": os.path.join(DEFAULT_IMAGE_HOME_DIR, ".oci")}
737742
}
738-
743+
739744
self.config["execution"]["source_folder"] = os.path.abspath(
740745
os.path.join(dir_path, "..")
741746
)
742747
self.config["execution"]["entrypoint"] = SCRIPT
743748
bind_volumes[artifact_directory] = {"bind": DEFAULT_MODEL_DEPLOYMENT_FOLDER}
744-
749+
745750
# extra cmd
746751
data = self.config["execution"].get("payload")
747752
extra_cmd = f"--payload '{data}' " + f"--auth {self.auth_type} "
748753
if self.auth_type != "resource_principal":
749754
extra_cmd += f"--profile {self.profile}"
750-
755+
751756
if is_in_notebook_session() or NO_CONTAINER:
752757
# _run_with_conda_pack has code to handle notebook session case,
753-
# however, it activate the conda pack and then run the script.
758+
# however, it activate the conda pack and then run the script.
754759
# For the deployment, we just take the current conda env and run it.
755760
# Hence we just handle the notebook case directly here.
756761
script_path = os.path.join(os.path.join(dir_path, ".."), SCRIPT)
757-
cmd = f"python {script_path} " + f"--artifact-directory {artifact_directory} " + extra_cmd
762+
cmd = (
763+
f"python {script_path} "
764+
+ f"--artifact-directory {artifact_directory} "
765+
+ extra_cmd
766+
)
758767
logger.info(f"Running in a notebook or NO_CONTAINER with command {cmd}")
759768
run_command(cmd=cmd, shell=True)
760769
else:
761-
extra_cmd = f"--artifact-directory {DEFAULT_MODEL_DEPLOYMENT_FOLDER} "+ extra_cmd
770+
extra_cmd = (
771+
f"--artifact-directory {DEFAULT_MODEL_DEPLOYMENT_FOLDER} " + extra_cmd
772+
)
762773
exit_code = self._run_with_conda_pack(
763-
bind_volumes, extra_cmd, install=True, conda_uri=conda_path
764-
)
774+
bind_volumes, extra_cmd, install=True, conda_uri=conda_path
775+
)
765776
if exit_code != 0:
766777
raise RuntimeError(
767778
f"`predict` did not complete successfully. Exit code: {exit_code}. "
768779
f"Run with the --debug argument to view container logs."
769780
)
770-
781+
771782
def _get_conda_info_from_custom_metadata(self, ocid):
772783
"""
773784
Get conda env info from custom metadata from model catalog.

ads/opctl/cli.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,12 @@
3030
from ads.opctl.cmds import run_diagnostics as run_diagnostics_cmd
3131
from ads.opctl.cmds import watch as watch_cmd
3232
from ads.opctl.config.merger import ConfigMerger
33-
from ads.opctl.constants import (BACKEND_NAME, DEFAULT_MODEL_FOLDER,
34-
RESOURCE_TYPE, RUNTIME_TYPE)
33+
from ads.opctl.constants import (
34+
BACKEND_NAME,
35+
DEFAULT_MODEL_FOLDER,
36+
RESOURCE_TYPE,
37+
RUNTIME_TYPE,
38+
)
3539
from ads.opctl.utils import build_image as build_image_cmd
3640
from ads.opctl.utils import publish_image as publish_image_cmd
3741
from ads.opctl.utils import suppress_traceback

docs/source/user_guide/cli/opctl/localdev/local_deployment.rst

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ This example below demonstrates how to run a local predict using an installed co
3434

3535
.. code-block:: shell
3636
37-
ads opctl predict --artifact-directory /folder/your/model/artifacts/are/stored --payload '[[-1.68671955,2.25814541,-0.5068027,0.25248417,0.62665134,0.23441123]]' --conda-slug myconda_p38_cpu_v1
37+
ads opctl predict --ocid "ocid1.datasciencemodel.oc1.iad.<unique_ID>" --payload '[[-1.68671955,2.25814541,-0.5068027,0.25248417,0.62665134,0.23441123]]' --conda-slug myconda_p38_cpu_v1
3838
3939
Parameter explanation:
40-
- ``--ocid ocid1.datasciencemodel.oc1.iad.******``: Run the predict locally in a docker container when you pass in a model id. If you pass in a deployment id, e.g. ``ocid1.datasciencemodeldeployment.oc1.iad.``, it will actually predict against the remote endpoint. In that case, only ``--ocid`` and ``--payload`` are needed.
41-
- ``--conda-slug myconda_p38_cpu_v1``: Use the ``myconda_p38_cpu_v1`` conda environment. Note that you must publish this conda environment to you own bucket first if you are actually using a service conda pack for your real deployment. However, you dont have to install it locally. We will find to auto detect the conda information from the custom metadata, then the runtime.yaml from your model artifact if --conda-slug and --conda-path is not provided. However, if detected conda are service packs, we will throw an error asking you to publish it first. You can also provide the conda information directly through --conda-slug or --conda-path. Note, in order to test whether deployemnt will work, you should provide the slug that you will use in real deployment. The local conda environment directory will be automatically mounted into the container and activated before the entrypoint is executed.
42-
- ``--payload``: the payload to be passed to your model.
43-
- ``--bucket-uri``: is used to download large model artifact to your local machine. Extra policy needs to be placed for this bucket. Check this :doc:`link <./user_guide/model_registration/model_load.html#large-model-artifacts>` for more details. Small artifact does not require this.
40+
- ``--ocid``: Run the predict locally in a docker container when you pass in a model id. If you pass in a deployment id, e.g. ``ocid1.datasciencemodeldeployment.oc1.iad.``, it will actually predict against the remote endpoint. In that case, only ``--ocid`` and ``--payload`` are needed.
41+
- ``--conda-slug myconda_p38_cpu_v1``: Use the ``myconda_p38_cpu_v1`` conda environment. The environment should be installed in your local already. If you haven't installed it, you can provide the path by ``--conda-path``, for example, ``--conda-path "oci://my-bucket@mytenancy/.../myconda_p38_cpu_v1"``, it will download and install the conda environment in your local. Note that you must publish this conda environment to you own bucket first if you are actually using a service conda pack for your real deployment. We will find to auto detect the conda information from the custom metadata, then the runtime.yaml from your model artifact if ``--conda-slug`` and ``--conda-path`` is not provided. However, if detected conda are service packs, we will throw an error asking you to publish it first. Note, in order to test whether deployemnt will work, you should provide the slug that you will use in real deployment. The local conda environment directory will be automatically mounted into the container and activated before the entrypoint is executed.
42+
- ``--payload``: The payload to be passed to your model.
43+
- ``--bucket-uri``: Used to download large model artifact to your local machine. Extra policy needs to be placed for this bucket. Check this :doc:`link <./user_guide/model_registration/model_load.html#large-model-artifacts>` for more details. Small artifact does not require this.
4444

4545
.. code-block:: shell
4646
@@ -54,10 +54,9 @@ Running your Predict Against the Deployment Endpoint
5454
----------------------------------------------------
5555
.. code-block:: shell
5656
57-
ads opctl predict ocid1.datasciencemodeldeployment.oc1.iad.***** --payload '[[-1.68671955,2.25814541,-0.5068027,0.25248417,0.62665134,0.23441123]]'
57+
ads opctl predict --ocid "ocid1.datasciencemodeldeployment.oc1.iad.<unique_ID>" --payload '[[-1.68671955,2.25814541,-0.5068027,0.25248417,0.62665134,0.23441123]]'
5858
5959
6060
Parameter explanation:
61-
- ``--ocid ocid1.datasciencemodeldeployment.oc1.iad.******``: Run the predict remotely against the remote endpoint.
61+
- ``--ocid``: Run the predict remotely against the remote endpoint.
6262
- ``--payload``: The payload to be passed to your model.
63-

0 commit comments

Comments
 (0)