supervisely 6.73.407__py3-none-any.whl → 6.73.408__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -182,6 +182,9 @@ class Inference:
182
182
  self.classes: List[str] = None
183
183
  self._model_dir = model_dir
184
184
  self._model_served = False
185
+ self._freeze_timer = None
186
+ self._model_frozen = False
187
+ self._inactivity_timeout = 3600 # 1 hour
185
188
  self._deploy_params: dict = None
186
189
  self._model_meta = None
187
190
  self._confidence = "confidence"
@@ -225,6 +228,7 @@ class Inference:
225
228
  deploy_params["model_files"] = local_model_files
226
229
  logger.debug("Loading model...")
227
230
  self._load_model_headless(**deploy_params)
231
+ self._schedule_freeze_on_inactivity()
228
232
 
229
233
  if self._use_gui:
230
234
  initialize_custom_gui_method = getattr(self, "initialize_custom_gui", None)
@@ -273,6 +277,7 @@ class Inference:
273
277
  self.device = device
274
278
  self.load_on_device(self._model_dir, device)
275
279
  gui.show_deployed_model_info(self)
280
+ self._schedule_freeze_on_inactivity()
276
281
 
277
282
  def on_change_model_callback(
278
283
  gui: Union[GUI.InferenceGUI, GUI.ServingGUI, GUI.ServingGUITemplate],
@@ -407,6 +412,7 @@ class Inference:
407
412
  deploy_params = self._get_deploy_parameters_from_custom_checkpoint(checkpoint_path, device, runtime)
408
413
  logger.debug(f"Deploying custom model '{checkpoint_name}'...")
409
414
  self._load_model_headless(**deploy_params)
415
+ self._schedule_freeze_on_inactivity()
410
416
  return self
411
417
 
412
418
  def get_batch_size(self):
@@ -1228,6 +1234,10 @@ class Inference:
1228
1234
 
1229
1235
  def shutdown_model(self):
1230
1236
  self._model_served = False
1237
+ self._model_frozen = False
1238
+ if self._freeze_timer is not None:
1239
+ self._freeze_timer.cancel()
1240
+ self._freeze_timer = None
1231
1241
  self.device = None
1232
1242
  self.runtime = None
1233
1243
  self.model_precision = None
@@ -1437,12 +1447,13 @@ class Inference:
1437
1447
  if api is None:
1438
1448
  api = self.api
1439
1449
  return api
1440
-
1450
+
1441
1451
  def _inference_auto(
1442
1452
  self,
1443
1453
  source: List[Union[str, np.ndarray]],
1444
1454
  settings: Dict[str, Any],
1445
1455
  ) -> Tuple[List[Annotation], List[dict]]:
1456
+ self._unfreeze_model()
1446
1457
  inference_mode = settings.get("inference_mode", "full_image")
1447
1458
  use_raw = (
1448
1459
  inference_mode == "sliding_window" and settings["sliding_window_mode"] == "advanced"
@@ -1453,9 +1464,11 @@ class Inference:
1453
1464
  if (not use_raw and self.is_batch_inference_supported()) or (
1454
1465
  use_raw and is_predict_batch_raw_implemented
1455
1466
  ):
1456
- return self._inference_batched_wrapper(source, settings)
1467
+ result = self._inference_batched_wrapper(source, settings)
1457
1468
  else:
1458
- return self._inference_one_by_one_wrapper(source, settings)
1469
+ result = self._inference_one_by_one_wrapper(source, settings)
1470
+ self._schedule_freeze_on_inactivity()
1471
+ return result
1459
1472
 
1460
1473
  def inference(
1461
1474
  self,
@@ -2432,9 +2445,7 @@ class Inference:
2432
2445
  def _check_serve_before_call(self, func):
2433
2446
  @wraps(func)
2434
2447
  def wrapper(*args, **kwargs):
2435
- if self._model_served is True:
2436
- return func(*args, **kwargs)
2437
- else:
2448
+ if self._model_served is False:
2438
2449
  msg = (
2439
2450
  "The model has not yet been deployed. "
2440
2451
  "Please select the appropriate model in the UI and press the 'Serve' button. "
@@ -2442,9 +2453,53 @@ class Inference:
2442
2453
  )
2443
2454
  # raise DialogWindowError(title="Call undeployed model.", description=msg)
2444
2455
  raise RuntimeError(msg)
2445
-
2456
+ return func(*args, **kwargs)
2446
2457
  return wrapper
2447
2458
 
2459
+ def _freeze_model(self):
2460
+ if self._model_frozen or not self._model_served:
2461
+ return
2462
+ logger.debug("Freezing model...")
2463
+ runtime = self._deploy_params.get("runtime")
2464
+ if runtime and runtime.lower() != RuntimeType.PYTORCH.lower():
2465
+ logger.debug("Model is not running in PyTorch runtime, cannot freeze.")
2466
+ return
2467
+ previous_device = self._deploy_params.get("device")
2468
+ if previous_device == "cpu":
2469
+ logger.debug("Model is already running on CPU, cannot freeze.")
2470
+ return
2471
+
2472
+ deploy_params = self._deploy_params.copy()
2473
+ deploy_params["device"] = "cpu"
2474
+ try:
2475
+ self._load_model(deploy_params)
2476
+ self._model_frozen = True
2477
+ logger.info(
2478
+ "Model has been re-deployed to CPU for resource optimization. "
2479
+ "It will be loaded back to the original device on the next inference request."
2480
+ )
2481
+ finally:
2482
+ self._deploy_params["device"] = previous_device
2483
+ clean_up_cuda()
2484
+
2485
+ def _unfreeze_model(self):
2486
+ if not self._model_frozen:
2487
+ return
2488
+ logger.debug("Unfreezing model...")
2489
+ self._model_frozen = False
2490
+ self._load_model(self._deploy_params)
2491
+ clean_up_cuda()
2492
+ logger.debug("Model is unfrozen and ready for inference.")
2493
+
2494
+ def _schedule_freeze_on_inactivity(self):
2495
+ if self._freeze_timer is not None:
2496
+ self._freeze_timer.cancel()
2497
+ timer = threading.Timer(self._inactivity_timeout, self._freeze_model)
2498
+ timer.daemon = True
2499
+ timer.start()
2500
+ self._freeze_timer = timer
2501
+ logger.debug("Model will be frozen in %s seconds due to inactivity.", self._inactivity_timeout)
2502
+
2448
2503
  def _set_served_callback(self):
2449
2504
  self._model_served = True
2450
2505
 
@@ -2506,6 +2561,7 @@ class Inference:
2506
2561
  # update to set correct device
2507
2562
  device = deploy_params.get("device", "cpu")
2508
2563
  self.gui.set_deployed(device)
2564
+ self._schedule_freeze_on_inactivity()
2509
2565
  return {"result": "model was successfully deployed"}
2510
2566
  except Exception as e:
2511
2567
  self.gui._success_label.hide()
@@ -3400,6 +3456,8 @@ class Inference:
3400
3456
  if self.gui is not None:
3401
3457
  self.gui._success_label.hide()
3402
3458
  raise e
3459
+ finally:
3460
+ self._schedule_freeze_on_inactivity()
3403
3461
 
3404
3462
  @server.post("/list_pretrained_models")
3405
3463
  def _list_pretrained_models():
@@ -3479,6 +3537,16 @@ class Inference:
3479
3537
  },
3480
3538
  }
3481
3539
 
3540
+ @server.post("/freeze_model")
3541
+ def _freeze_model(request: Request):
3542
+ if self._model_frozen:
3543
+ return {"message": "Model is already frozen."}
3544
+
3545
+ self._freeze_model()
3546
+ if not self._model_frozen:
3547
+ return {"message": "Failed to freeze model. Check the logs for details."}
3548
+ return {"message": "Model is frozen."}
3549
+
3482
3550
  # Local deploy without predict args
3483
3551
  if self._is_cli_deploy:
3484
3552
  self._run_server()
@@ -111,6 +111,12 @@ class ModelAPI:
111
111
  response = self._post("tasks.stop", {ApiField.ID: id})
112
112
  return TaskApi.Status(response[ApiField.STATUS])
113
113
 
114
+ def freeze_model(self):
115
+ """Freeze the model to free up resources."""
116
+ if self.task_id is not None:
117
+ return self.api.task.send_request(self.task_id, "freeze_model", {})
118
+ return self._post("freeze_model", {})
119
+
114
120
  # --------------------- #
115
121
 
116
122
  # region Load
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: supervisely
3
- Version: 6.73.407
3
+ Version: 6.73.408
4
4
  Summary: Supervisely Python SDK.
5
5
  Home-page: https://github.com/supervisely/supervisely
6
6
  Author: Supervisely
@@ -893,7 +893,7 @@ supervisely/nn/benchmark/visualization/widgets/table/__init__.py,sha256=47DEQpj8
893
893
  supervisely/nn/benchmark/visualization/widgets/table/table.py,sha256=atmDnF1Af6qLQBUjLhK18RMDKAYlxnsuVHMSEa5a-e8,4319
894
894
  supervisely/nn/inference/__init__.py,sha256=QFukX2ip-U7263aEPCF_UCFwj6EujbMnsgrXp5Bbt8I,1623
895
895
  supervisely/nn/inference/cache.py,sha256=rfmb1teJ9lNDfisUSh6bwDCVkPZocn8GMvDgLQktnbo,35023
896
- supervisely/nn/inference/inference.py,sha256=L14M8qGofz6EGrgJvGMcz0h3vsu-AnHPeL_iUO8Kf3Y,195721
896
+ supervisely/nn/inference/inference.py,sha256=7c2-GuG3MgI5H0muTyxoR-XgUzWpbP9if37CyRewobA,198528
897
897
  supervisely/nn/inference/inference_request.py,sha256=y6yw0vbaRRcEBS27nq3y0sL6Gmq2qLA_Bm0GrnJGegE,14267
898
898
  supervisely/nn/inference/session.py,sha256=dIg2F-OBl68pUzcmtmcI0YQIp1WWNnrJTVMjwFN91Q4,35824
899
899
  supervisely/nn/inference/uploader.py,sha256=21a9coOimCHhEqAbV-llZWcp12847DEMoQp3N16bpK0,5425
@@ -968,7 +968,7 @@ supervisely/nn/legacy/pytorch/weights.py,sha256=Zb9kcpUCg6ykr7seO53CkKSQa2K44wo8
968
968
  supervisely/nn/legacy/training/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
969
969
  supervisely/nn/legacy/training/eval_planner.py,sha256=zN9b0_CX7sWGdC8e6riTvD-NOUc3_Xduyhj00S7PEIo,1311
970
970
  supervisely/nn/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
971
- supervisely/nn/model/model_api.py,sha256=rIne6ymvL2aVwzSTJMGxAbevE0U-f-WKhDciqaneqRc,9666
971
+ supervisely/nn/model/model_api.py,sha256=rq-08BrQmWKqUxWnBB5yKBfnjxw8Lg88mhva848Ae2I,9911
972
972
  supervisely/nn/model/prediction.py,sha256=N3oO9s3NDiC5CFvW8utfU8rz3bfpCl37Sk4VEBH94Bc,11307
973
973
  supervisely/nn/model/prediction_session.py,sha256=sy0FSQaWSmT8i0RkR4J8oIn3Ek4IDVJNBR1Tg4mulkM,25523
974
974
  supervisely/nn/tracker/__init__.py,sha256=LiojByb5kGsTQ49lWuboEh7B4JUwM1vfz81J8kJlLYo,337
@@ -1114,9 +1114,9 @@ supervisely/worker_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
1114
1114
  supervisely/worker_proto/worker_api_pb2.py,sha256=VQfi5JRBHs2pFCK1snec3JECgGnua3Xjqw_-b3aFxuM,59142
1115
1115
  supervisely/worker_proto/worker_api_pb2_grpc.py,sha256=3BwQXOaP9qpdi0Dt9EKG--Lm8KGN0C5AgmUfRv77_Jk,28940
1116
1116
  supervisely_lib/__init__.py,sha256=7-3QnN8Zf0wj8NCr2oJmqoQWMKKPKTECvjH9pd2S5vY,159
1117
- supervisely-6.73.407.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1118
- supervisely-6.73.407.dist-info/METADATA,sha256=fIR2z5kCfeQzldtPPODSuq8z4QQhOoTVLgeZRZokLtU,35254
1119
- supervisely-6.73.407.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
1120
- supervisely-6.73.407.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1121
- supervisely-6.73.407.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1122
- supervisely-6.73.407.dist-info/RECORD,,
1117
+ supervisely-6.73.408.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1118
+ supervisely-6.73.408.dist-info/METADATA,sha256=C6yRG5xZiYpAXpe3RyAIimpbPRggSn--0fqKT00sSKI,35254
1119
+ supervisely-6.73.408.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
1120
+ supervisely-6.73.408.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1121
+ supervisely-6.73.408.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1122
+ supervisely-6.73.408.dist-info/RECORD,,