Skip to content

Commit 5e96b5c

Browse files
author
David Eigen
committed
maintain venv in user cache dir and add pdb flags
1 parent 33bac1b commit 5e96b5c

File tree

2 files changed

+53
-30
lines changed

2 files changed

+53
-30
lines changed

clarifai/cli/model.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,11 @@ def download_checkpoints(model_path, out_path):
6868
help=
6969
'Specify how to test the model locally: "env" for virtual environment or "container" for Docker container. Defaults to "env".'
7070
)
71+
@click.option('--pdb', is_flag=True, help='Enable PDB debugging when testing the model locally.')
7172
@click.option(
7273
'--keep_env',
7374
is_flag=True,
75+
default=True,
7476
help=
7577
'Keep the virtual environment after testing the model locally (applicable for virtualenv mode). Defaults to False.'
7678
)
@@ -80,7 +82,7 @@ def download_checkpoints(model_path, out_path):
8082
help=
8183
'Keep the Docker image after testing the model locally (applicable for container mode). Defaults to False.'
8284
)
83-
def test_locally(model_path, keep_env=False, keep_image=False, mode='env'):
85+
def test_locally(model_path, pdb=False, keep_env=False, keep_image=False, mode='env'):
8486
"""Test model locally."""
8587
try:
8688
from clarifai.runners.models import model_run_locally
@@ -89,9 +91,12 @@ def test_locally(model_path, keep_env=False, keep_image=False, mode='env'):
8991
if mode == 'container' and keep_env:
9092
raise ValueError("'keep_env' is applicable only for 'env' mode")
9193

94+
if pdb and mode == "container":
95+
raise ValueError("PDB debugging is not supported in container mode.")
96+
9297
if mode == "env":
9398
click.echo("Testing model locally in a virtual environment...")
94-
model_run_locally.main(model_path, run_model_server=False, keep_env=keep_env)
99+
model_run_locally.main(model_path, run_model_server=False, keep_env=keep_env, use_pdb=pdb)
95100
elif mode == "container":
96101
click.echo("Testing model locally inside a container...")
97102
model_run_locally.main(
@@ -125,6 +130,7 @@ def test_locally(model_path, keep_env=False, keep_image=False, mode='env'):
125130
@click.option(
126131
'--keep_env',
127132
is_flag=True,
133+
default=True,
128134
help=
129135
'Keep the virtual environment after testing the model locally (applicable for virtualenv mode). Defaults to False.'
130136
)

clarifai/runners/models/model_run_locally.py

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import traceback
1111
import venv
1212

13+
import platformdirs
1314
from clarifai_grpc.grpc.api import resources_pb2, service_pb2
1415
from clarifai_grpc.grpc.api.status import status_code_pb2, status_pb2
1516

@@ -52,37 +53,42 @@ def _get_env_executable(self):
5253

5354
def create_temp_venv(self):
5455
"""Create a temporary virtual environment."""
55-
requirements_hash = self._requirements_hash()
56-
57-
temp_dir = os.path.join(tempfile.gettempdir(), str(requirements_hash))
56+
venv_key = hashlib.md5(self.model_path.encode('utf-8')).hexdigest()
57+
temp_dir = os.path.join(platformdirs.user_cache_dir('clarifai', 'clarifai'), 'venvs', venv_key)
5858
venv_dir = os.path.join(temp_dir, "venv")
5959

6060
if os.path.exists(temp_dir):
61-
logger.info(f"Using previous virtual environment at {temp_dir}")
62-
use_existing_venv = True
61+
logger.info(f"Using previous virtual environment at {venv_dir}")
6362
else:
64-
logger.info("Creating temporary virtual environment...")
65-
use_existing_venv = False
63+
logger.info("Creating virtual environment...")
6664
venv.create(venv_dir, with_pip=True)
6765
logger.info(f"Created temporary virtual environment at {venv_dir}")
6866

6967
self.venv_dir = venv_dir
7068
self.temp_dir = temp_dir
7169
self.python_executable, self.pip_executable = self._get_env_executable()
7270

73-
return use_existing_venv
74-
7571
def install_requirements(self):
7672
"""Install the dependencies from requirements.txt and Clarifai."""
73+
if os.path.exists(os.path.join(self.temp_dir, "requirements.txt")):
74+
requirements = open(self.requirements_file).read()
75+
installed_requirements = open(os.path.join(self.temp_dir, "requirements.txt")).read()
76+
if requirements == installed_requirements:
77+
logger.info("Requirements already installed.")
78+
return
7779
_, pip_executable = self._get_env_executable()
7880
try:
7981
logger.info(
8082
f"Installing requirements from {self.requirements_file}... in the virtual environment {self.venv_dir}"
8183
)
82-
subprocess.check_call([pip_executable, "install", "-r", self.requirements_file])
8384
logger.info("Installing Clarifai package...")
84-
subprocess.check_call([pip_executable, "install", "clarifai"])
85+
subprocess.check_call(
86+
[pip_executable, "install", "clarifai==" + __import__("clarifai").__version__])
87+
logger.info("Installing model requirements...")
88+
subprocess.check_call([pip_executable, "install", "-r", self.requirements_file])
8589
logger.info("Requirements installed successfully!")
90+
with open(os.path.join(self.temp_dir, "requirements.txt"), "w") as f:
91+
f.write(open(self.requirements_file).read())
8692
except subprocess.CalledProcessError as e:
8793
logger.error(f"Error installing requirements: {e}")
8894
self.clean_up()
@@ -177,9 +183,12 @@ def _run_model_inference(self, model):
177183
))
178184

179185
if stream_response:
180-
stream_first_res = next(stream_response)
181-
if stream_first_res.outputs[0].status.code != status_code_pb2.SUCCESS:
182-
logger.error(f"Moddel Prediction failed: {stream_first_res}")
186+
try:
187+
stream_first_res = next(stream_response)
188+
except StopIteration:
189+
stream_first_res = None
190+
if stream_first_res is None or stream_first_res.outputs[0].status.code != status_code_pb2.SUCCESS:
191+
logger.error(f"Model stream failed: {stream_first_res}")
183192
else:
184193
logger.info(
185194
f"Model Prediction succeeded for stream and first response: {stream_first_res}")
@@ -191,7 +200,7 @@ def _run_test(self):
191200
# send an inference.
192201
self._run_model_inference(model)
193202

194-
def test_model(self):
203+
def test_model(self, use_pdb=False):
195204
"""Test the model by running it locally in the virtual environment."""
196205

197206
import_path = repr(os.path.dirname(os.path.abspath(__file__)))
@@ -201,8 +210,12 @@ def test_model(self):
201210
f"sys.path.append({import_path}); "
202211
f"from model_run_locally import ModelRunLocally; "
203212
f"ModelRunLocally({model_path})._run_test()")
213+
main_file = tempfile.NamedTemporaryFile(mode="w")
214+
with open(main_file.name, "w") as f:
215+
f.write(command_string)
204216

205-
command = [self.python_executable, "-c", command_string]
217+
pdb_args = ["-m", "pdb"] if use_pdb else []
218+
command = [self.python_executable, *pdb_args, main_file.name]
206219
process = None
207220
try:
208221
logger.info("Testing the model locally...")
@@ -232,12 +245,13 @@ def test_model(self):
232245
process.kill()
233246

234247
# run the model server
235-
def run_model_server(self, port=8080):
248+
def run_model_server(self, port=8080, use_pdb=False):
236249
"""Run the Clarifai Runners's model server."""
237250

251+
pdb_args = ["-m", "pdb"] if use_pdb else []
238252
command = [
239-
self.python_executable, "-m", "clarifai.runners.server", "--model_path", self.model_path,
240-
"--grpc", "--port",
253+
self.python_executable, *pdb_args, "-m", "clarifai.runners.server", "--model_path",
254+
self.model_path, "--grpc", "--port",
241255
str(port)
242256
]
243257
try:
@@ -462,16 +476,19 @@ def remove_docker_image(self, image_name):
462476
def clean_up(self):
463477
"""Clean up the temporary virtual environment."""
464478
if os.path.exists(self.temp_dir):
465-
logger.info("Cleaning up temporary virtual environment...")
479+
logger.info("Cleaning up virtual environment...")
466480
shutil.rmtree(self.temp_dir)
467481

468482

469-
def main(model_path,
470-
run_model_server=False,
471-
inside_container=False,
472-
port=8080,
473-
keep_env=False,
474-
keep_image=False):
483+
def main(
484+
model_path,
485+
run_model_server=False,
486+
inside_container=False,
487+
port=8080,
488+
keep_env=True,
489+
keep_image=False,
490+
use_pdb=False,
491+
):
475492

476493
if not os.environ['CLARIFAI_PAT']:
477494
logger.error(
@@ -513,9 +530,9 @@ def main(model_path,
513530
if not use_existing_env:
514531
manager.install_requirements()
515532
if run_model_server:
516-
manager.run_model_server(port)
533+
manager.run_model_server(port, use_pdb=use_pdb)
517534
else:
518-
manager.test_model()
535+
manager.test_model(use_pdb=use_pdb)
519536
finally:
520537
if not keep_env:
521538
manager.clean_up()

0 commit comments

Comments
 (0)