6
6
import java .io .IOException ;
7
7
import java .io .InputStreamReader ;
8
8
import java .net .HttpURLConnection ;
9
+ import java .nio .file .Files ;
9
10
import java .nio .file .Path ;
10
11
import java .nio .file .Paths ;
11
12
import java .util .ArrayList ;
@@ -99,6 +100,8 @@ public void registerAndUpdateModel(String modelName, JsonObject modelInfo)
99
100
100
101
createVersionedModel (tempModel , versionId );
101
102
103
+ setupModelVenv (tempModel );
104
+
102
105
setupModelDependencies (tempModel );
103
106
if (defaultVersion ) {
104
107
modelManager .setDefaultVersion (modelName , versionId );
@@ -152,6 +155,8 @@ public ModelArchive registerModel(
152
155
}
153
156
}
154
157
158
+ setupModelVenv (tempModel );
159
+
155
160
setupModelDependencies (tempModel );
156
161
157
162
logger .info ("Model {} loaded." , tempModel .getModelName ());
@@ -206,9 +211,16 @@ private ModelArchive createModelArchive(
206
211
207
212
private void setupModelVenv (Model model )
208
213
throws IOException , InterruptedException , ModelException {
214
+ ModelConfig modelConfig = model .getModelArchive ().getModelConfig ();
215
+ if (model .getModelArchive ().getManifest ().getRuntime () != Manifest .RuntimeType .PYTHON
216
+ || modelConfig == null
217
+ || modelConfig .getUseVenv () != true ) {
218
+ return ;
219
+ }
220
+
209
221
String venvPath = EnvironmentUtils .getPythonVenvPath (model );
210
222
List <String > commandParts = new ArrayList <>();
211
- commandParts .add (EnvironmentUtils . getPythonRunTime ( model ));
223
+ commandParts .add (configManager . getPythonExecutable ( ));
212
224
commandParts .add ("-m" );
213
225
commandParts .add ("venv" );
214
226
commandParts .add ("--clear" );
@@ -217,7 +229,7 @@ private void setupModelVenv(Model model)
217
229
218
230
ProcessBuilder processBuilder = new ProcessBuilder (commandParts );
219
231
220
- if (isValidVenvPath (venvPath )) {
232
+ if (isValidDependencyPath (venvPath )) {
221
233
processBuilder .directory (Paths .get (venvPath ).toFile ().getParentFile ());
222
234
} else {
223
235
throw new ModelException (
@@ -266,20 +278,29 @@ private void setupModelDependencies(Model model)
266
278
String requirementsFile =
267
279
model .getModelArchive ().getManifest ().getModel ().getRequirementsFile ();
268
280
269
- if (configManager .getInstallPyDepPerModel () && requirementsFile != null ) {
270
- setupModelVenv (model );
271
- String pythonRuntime = EnvironmentUtils .getPythonRunTime (model );
272
- if (!isValidVenvPath (pythonRuntime )) {
281
+ if (!configManager .getInstallPyDepPerModel () || requirementsFile == null ) {
282
+ return ;
283
+ }
284
+
285
+ ModelConfig modelConfig = model .getModelArchive ().getModelConfig ();
286
+ String pythonRuntime = EnvironmentUtils .getPythonRunTime (model );
287
+ Path requirementsFilePath =
288
+ Paths .get (model .getModelDir ().getAbsolutePath (), requirementsFile );
289
+ List <String > commandParts = new ArrayList <>();
290
+ ProcessBuilder processBuilder = new ProcessBuilder ();
291
+
292
+ if (modelConfig != null && modelConfig .getUseVenv () == true ) {
293
+ if (!isValidDependencyPath (pythonRuntime )) {
273
294
throw new ModelException (
274
295
"Invalid python venv runtime path for model "
275
296
+ model .getModelName ()
276
297
+ ": "
277
298
+ pythonRuntime );
278
299
}
279
300
280
- Path requirementsFilePath =
281
- Paths .get (model . getModelDir ().getAbsolutePath (), requirementsFile );
282
- List < String > commandParts = new ArrayList <>();
301
+ processBuilder . directory (
302
+ Paths .get (EnvironmentUtils . getPythonVenvPath ( model )). toFile ().getParentFile () );
303
+
283
304
commandParts .add (pythonRuntime );
284
305
commandParts .add ("-m" );
285
306
commandParts .add ("pip" );
@@ -289,54 +310,72 @@ private void setupModelDependencies(Model model)
289
310
commandParts .add ("only-if-needed" );
290
311
commandParts .add ("-r" );
291
312
commandParts .add (requirementsFilePath .toString ());
292
-
293
- ProcessBuilder processBuilder = new ProcessBuilder (commandParts );
294
-
295
- String [] envp =
296
- EnvironmentUtils .getEnvString (
297
- configManager .getModelServerHome (),
298
- model .getModelDir ().getAbsolutePath (),
299
- null );
300
- Map <String , String > environment = processBuilder .environment ();
301
- for (String envVar : envp ) {
302
- String [] parts = envVar .split ("=" , 2 );
303
- if (parts .length == 2 ) {
304
- environment .put (parts [0 ], parts [1 ]);
305
- }
313
+ } else {
314
+ File dependencyPath = model .getModelDir ();
315
+ if (Files .isSymbolicLink (dependencyPath .toPath ())) {
316
+ dependencyPath = dependencyPath .getParentFile ();
317
+ }
318
+ if (!isValidDependencyPath (dependencyPath .getPath ())) {
319
+ throw new ModelException (
320
+ "Invalid 3rd party package installation path "
321
+ + dependencyPath .getCanonicalPath ());
306
322
}
307
- processBuilder .directory (
308
- Paths .get (EnvironmentUtils .getPythonVenvPath (model )).toFile ().getParentFile ());
309
- processBuilder .redirectErrorStream (true );
310
323
311
- Process process = processBuilder .start ( );
324
+ processBuilder .directory ( dependencyPath );
312
325
313
- int exitCode = process .waitFor ();
314
- String line ;
315
- StringBuilder outputString = new StringBuilder ();
316
- BufferedReader brdr =
317
- new BufferedReader (new InputStreamReader (process .getInputStream ()));
318
- while ((line = brdr .readLine ()) != null ) {
319
- outputString .append (line + "\n " );
320
- }
326
+ commandParts .add (pythonRuntime );
327
+ commandParts .add ("-m" );
328
+ commandParts .add ("pip" );
329
+ commandParts .add ("install" );
330
+ commandParts .add ("-U" );
331
+ commandParts .add ("-t" );
332
+ commandParts .add (dependencyPath .getAbsolutePath ());
333
+ commandParts .add ("-r" );
334
+ commandParts .add (requirementsFilePath .toString ());
335
+ }
321
336
322
- if (exitCode == 0 ) {
323
- logger .info (
324
- "Installed custom pip packages for model {}:\n {}" ,
325
- model .getModelName (),
326
- outputString .toString ());
327
- } else {
328
- logger .error (
329
- "Custom pip package installation failed for model {}:\n {}" ,
330
- model .getModelName (),
331
- outputString .toString ());
332
- throw new ModelException (
333
- "Custom pip package installation failed for model " + model .getModelName ());
337
+ processBuilder .command (commandParts );
338
+ String [] envp =
339
+ EnvironmentUtils .getEnvString (
340
+ configManager .getModelServerHome (),
341
+ model .getModelDir ().getAbsolutePath (),
342
+ null );
343
+ Map <String , String > environment = processBuilder .environment ();
344
+ for (String envVar : envp ) {
345
+ String [] parts = envVar .split ("=" , 2 );
346
+ if (parts .length == 2 ) {
347
+ environment .put (parts [0 ], parts [1 ]);
334
348
}
335
349
}
350
+ processBuilder .redirectErrorStream (true );
351
+
352
+ Process process = processBuilder .start ();
353
+
354
+ int exitCode = process .waitFor ();
355
+ String line ;
356
+ StringBuilder outputString = new StringBuilder ();
357
+ BufferedReader brdr = new BufferedReader (new InputStreamReader (process .getInputStream ()));
358
+ while ((line = brdr .readLine ()) != null ) {
359
+ outputString .append (line + "\n " );
360
+ }
361
+
362
+ if (exitCode == 0 ) {
363
+ logger .info (
364
+ "Installed custom pip packages for model {}:\n {}" ,
365
+ model .getModelName (),
366
+ outputString .toString ());
367
+ } else {
368
+ logger .error (
369
+ "Custom pip package installation failed for model {}:\n {}" ,
370
+ model .getModelName (),
371
+ outputString .toString ());
372
+ throw new ModelException (
373
+ "Custom pip package installation failed for model " + model .getModelName ());
374
+ }
336
375
}
337
376
338
- private boolean isValidVenvPath (String venvPath ) {
339
- if (Paths .get (venvPath )
377
+ private boolean isValidDependencyPath (String dependencyPath ) {
378
+ if (Paths .get (dependencyPath )
340
379
.normalize ()
341
380
.startsWith (FileUtils .getTempDirectory ().toPath ().normalize ())) {
342
381
return true ;
0 commit comments