1010import traceback
1111import venv
1212
13+ import platformdirs
1314from clarifai_grpc .grpc .api import resources_pb2 , service_pb2
1415from 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