supervisely 6.73.412__py3-none-any.whl → 6.73.414__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.
@@ -703,6 +703,8 @@ class ApiField:
703
703
  """"""
704
704
  ERROR_MESSAGE = "errorMessage"
705
705
  """"""
706
+ UNIQUE_ITEMS = "uniqueItems"
707
+ """"""
706
708
 
707
709
 
708
710
  def _get_single_item(items):
@@ -2455,6 +2455,7 @@ class ProjectApi(CloneableModuleApi, UpdateableModule, RemoveableModuleApi):
2455
2455
  request_body = {
2456
2456
  ApiField.PROJECT_ID: project_id,
2457
2457
  ApiField.LIMIT: limit,
2458
+ ApiField.UNIQUE_ITEMS: limit, # the same as limit, but for diverse search
2458
2459
  }
2459
2460
 
2460
2461
  if dataset_id is not None:
@@ -3,7 +3,9 @@ import json
3
3
  import os
4
4
  import signal
5
5
  import sys
6
+ import time
6
7
  from contextlib import suppress
8
+ from contextvars import ContextVar
7
9
  from functools import wraps
8
10
  from pathlib import Path
9
11
  from threading import Event as ThreadingEvent
@@ -61,6 +63,10 @@ SUPERVISELY_SERVER_PATH_PREFIX = sly_env.supervisely_server_path_prefix()
61
63
  if SUPERVISELY_SERVER_PATH_PREFIX and not SUPERVISELY_SERVER_PATH_PREFIX.startswith("/"):
62
64
  SUPERVISELY_SERVER_PATH_PREFIX = f"/{SUPERVISELY_SERVER_PATH_PREFIX}"
63
65
 
66
+ HEALTH_ENDPOINTS = ["/health", "/is_ready"]
67
+
68
+ # Context variable for response time
69
+ response_time_ctx: ContextVar[float] = ContextVar("response_time", default=None)
64
70
 
65
71
  class ReadyzFilter(logging.Filter):
66
72
  def filter(self, record):
@@ -70,11 +76,22 @@ class ReadyzFilter(logging.Filter):
70
76
  return True
71
77
 
72
78
 
79
+ class ResponseTimeFilter(logging.Filter):
80
+ def filter(self, record):
81
+ # Check if this is an HTTP access log line by logger name
82
+ if getattr(record, "name", "") == "uvicorn.access":
83
+ response_time = response_time_ctx.get(None)
84
+ if response_time is not None:
85
+ record.responseTime = f"{round(response_time, 2)}ms"
86
+ return True
87
+
88
+
73
89
  def _init_uvicorn_logger():
74
90
  uvicorn_logger = logging.getLogger("uvicorn.access")
75
91
  for handler in uvicorn_logger.handlers:
76
92
  handler.setFormatter(create_formatter())
77
93
  uvicorn_logger.addFilter(ReadyzFilter())
94
+ uvicorn_logger.addFilter(ResponseTimeFilter())
78
95
 
79
96
 
80
97
  _init_uvicorn_logger()
@@ -794,6 +811,8 @@ def _init(
794
811
 
795
812
  @app.middleware("http")
796
813
  async def get_state_from_request(request: Request, call_next):
814
+ # Start timer for response time measurement
815
+ start_time = time.perf_counter()
797
816
  if headless is False:
798
817
  await StateJson.from_request(request)
799
818
 
@@ -829,6 +848,9 @@ def _init(
829
848
  except Exception as exc:
830
849
  need_to_handle_error = is_production()
831
850
  response = await process_server_error(request, exc, need_to_handle_error)
851
+ # Calculate response time and set it for uvicorn logger in ms
852
+ elapsed_ms = (time.perf_counter() - start_time) * 1000
853
+ response_time_ctx.set(elapsed_ms)
832
854
  return response
833
855
 
834
856
  def verify_localhost(request: Request):
@@ -905,7 +927,33 @@ class Application(metaclass=Singleton):
905
927
  Callable
906
928
  ] = None, # function to check if the app is ready for requests (e.g serving app: model is served and ready)
907
929
  show_header: bool = True,
930
+ hide_health_check_logs: bool = True, # whether to hide health check logs in info level
931
+ health_check_endpoints: Optional[List[str]] = None, # endpoints to check health of the app
908
932
  ):
933
+ """Initialize the Supervisely Application.
934
+
935
+ :param layout: Main layout of the application.
936
+ :type layout: Widget
937
+ :param templates_dir: Directory with Jinja2 templates. It is preferred to use `layout` instead of `templates_dir`.
938
+ :type templates_dir: str, optional
939
+ :param static_dir: Directory with static files (e.g. CSS, JS), used for serving static content.
940
+ :type static_dir: str, optional
941
+ :param hot_reload: Whether to enable hot reload during development (default is False).
942
+ :type hot_reload: bool, optional
943
+ :param session_info_extra_content: Additional content to be displayed in the session info area.
944
+ :type session_info_extra_content: Widget, optional
945
+ :param session_info_solid: Whether to use solid background for the session info area.
946
+ :type session_info_solid: bool, optional
947
+ :param ready_check_function: Function to check if the app is ready for requests.
948
+ :type ready_check_function: Callable, optional
949
+ :param show_header: Whether to show the header in the application.
950
+ :type show_header: bool, optional
951
+ :param hide_health_check_logs: Whether to hide health check logs in info level.
952
+ :type hide_health_check_logs: bool, optional
953
+ :param health_check_endpoints: List of additional endpoints to check health of the app.
954
+ Add your custom endpoints here to be able to manage logging of health check requests on info level with `hide_health_check_logs`.
955
+ :type health_check_endpoints: List[str], optional
956
+ """
909
957
  self._favicon = os.environ.get("icon", "https://cdn.supervisely.com/favicon.ico")
910
958
  JinjaWidgets().context["__favicon__"] = self._favicon
911
959
  JinjaWidgets().context["__no_html_mode__"] = True
@@ -980,6 +1028,17 @@ class Application(metaclass=Singleton):
980
1028
  hot_reload=hot_reload,
981
1029
  before_shutdown_callbacks=self._before_shutdown_callbacks,
982
1030
  )
1031
+
1032
+ # add filter to hide health check logs for info level
1033
+ if health_check_endpoints is None or len(health_check_endpoints) == 0:
1034
+ self._health_check_endpoints = HEALTH_ENDPOINTS
1035
+ else:
1036
+ health_check_endpoints = [endpoint.strip() for endpoint in health_check_endpoints]
1037
+ self._health_check_endpoints = HEALTH_ENDPOINTS + health_check_endpoints
1038
+
1039
+ if hide_health_check_logs:
1040
+ self._setup_health_check_filter()
1041
+
983
1042
  self.test_client = TestClient(self._fastapi)
984
1043
 
985
1044
  if not headless:
@@ -1126,6 +1185,34 @@ class Application(metaclass=Singleton):
1126
1185
  def set_ready_check_function(self, func: Callable):
1127
1186
  self._ready_check_function = func
1128
1187
 
1188
+ def _setup_health_check_filter(self):
1189
+ """Setup filter to hide health check logs for info level."""
1190
+
1191
+ class HealthCheckFilter(logging.Filter):
1192
+ def __init__(self, app_instance):
1193
+ super().__init__()
1194
+ self.app: Application = app_instance
1195
+
1196
+ def filter(self, record):
1197
+ # Hide health check requests if NOT in debug mode
1198
+ if not self.app._fastapi.debug and hasattr(record, "getMessage"):
1199
+ message = record.getMessage()
1200
+ # Check if the message contains health check paths
1201
+ if any(path in message for path in self.app._health_check_endpoints):
1202
+ return False
1203
+ return True
1204
+
1205
+ # Apply filter to uvicorn access logger
1206
+ health_filter = HealthCheckFilter(self)
1207
+ uvicorn_logger = logging.getLogger("uvicorn.access")
1208
+
1209
+ # Remove old filters of this type, if any (for safety)
1210
+ uvicorn_logger.filters = [
1211
+ f for f in uvicorn_logger.filters if not isinstance(f, HealthCheckFilter)
1212
+ ]
1213
+
1214
+ uvicorn_logger.addFilter(health_filter)
1215
+
1129
1216
 
1130
1217
  def set_autostart_flag_from_state(default: Optional[str] = None):
1131
1218
  """Set `autostart` flag recieved from task state. Env name: `modal.state.autostart`.
@@ -34,7 +34,6 @@ import supervisely.io.env as sly_env
34
34
  import supervisely.io.fs as sly_fs
35
35
  import supervisely.io.json as sly_json
36
36
  import supervisely.nn.inference.gui as GUI
37
- from supervisely.nn.experiments import ExperimentInfo
38
37
  from supervisely import DatasetInfo, batched
39
38
  from supervisely._utils import (
40
39
  add_callback,
@@ -69,13 +68,14 @@ from supervisely.decorators.inference import (
69
68
  from supervisely.geometry.any_geometry import AnyGeometry
70
69
  from supervisely.imaging.color import get_predefined_colors
71
70
  from supervisely.io.fs import list_files
71
+ from supervisely.nn.experiments import ExperimentInfo
72
72
  from supervisely.nn.inference.cache import InferenceImageCache
73
73
  from supervisely.nn.inference.inference_request import (
74
74
  InferenceRequest,
75
75
  InferenceRequestsManager,
76
76
  )
77
77
  from supervisely.nn.inference.uploader import Uploader
78
- from supervisely.nn.model.model_api import Prediction
78
+ from supervisely.nn.model.model_api import ModelAPI, Prediction
79
79
  from supervisely.nn.prediction_dto import Prediction as PredictionDTO
80
80
  from supervisely.nn.utils import (
81
81
  CheckpointInfo,
@@ -93,7 +93,6 @@ from supervisely.project.project_meta import ProjectMeta
93
93
  from supervisely.sly_logger import logger
94
94
  from supervisely.task.progress import Progress
95
95
  from supervisely.video.video import ALLOWED_VIDEO_EXTENSIONS, VideoFrameReader
96
- from supervisely.nn.model.model_api import ModelAPI
97
96
 
98
97
  try:
99
98
  from typing import Literal
@@ -383,7 +382,7 @@ class Inference:
383
382
  if m_name and m_name.lower() == model.lower():
384
383
  return m
385
384
  return None
386
-
385
+
387
386
  runtime = get_runtime(runtime)
388
387
  logger.debug(f"Runtime: {runtime}")
389
388
 
@@ -869,7 +868,7 @@ class Inference:
869
868
  """
870
869
  team_id = sly_env.team_id()
871
870
  local_model_files = {}
872
-
871
+
873
872
  # Sort files to download 'checkpoint' first
874
873
  files_order = sorted(model_files.keys(), key=lambda x: (0 if x == "checkpoint" else 1, x))
875
874
  for file in files_order:
@@ -910,12 +909,12 @@ class Inference:
910
909
  logger.debug("Model files will be downloaded from Team Files")
911
910
  local_model_files[file] = file_path
912
911
  continue
913
-
912
+
914
913
  local_model_files[file] = file_path
915
914
  if log_progress:
916
915
  self.gui.download_progress.hide()
917
916
  return local_model_files
918
-
917
+
919
918
  def _get_deploy_parameters_from_custom_checkpoint(self, checkpoint_path: str, device: str, runtime: str) -> dict:
920
919
  def _read_experiment_info(artifacts_dir: str) -> Optional[dict]:
921
920
  exp_path = os.path.join(artifacts_dir, "experiment_info.json")
@@ -1159,6 +1158,8 @@ class Inference:
1159
1158
  if model_source == ModelSource.CUSTOM:
1160
1159
  self._set_model_meta_custom_model(model_info)
1161
1160
  self._set_checkpoint_info_custom_model(deploy_params)
1161
+ elif model_source == ModelSource.PRETRAINED:
1162
+ self._set_checkpoint_info_pretrained(deploy_params)
1162
1163
 
1163
1164
  try:
1164
1165
  if is_production():
@@ -1232,6 +1233,19 @@ class Inference:
1232
1233
  model_source=ModelSource.CUSTOM,
1233
1234
  )
1234
1235
 
1236
+ def _set_checkpoint_info_pretrained(self, deploy_params: dict):
1237
+ checkpoint_name = os.path.basename(deploy_params["model_files"]["checkpoint"])
1238
+ model_name = deploy_params["model_info"]["model_name"]
1239
+ checkpoint_url = deploy_params["model_info"]["meta"]["model_files"]["checkpoint"]
1240
+ model_source = ModelSource.PRETRAINED
1241
+ self.checkpoint_info = CheckpointInfo(
1242
+ checkpoint_name=checkpoint_name,
1243
+ model_name=model_name,
1244
+ architecture=self.FRAMEWORK_NAME,
1245
+ checkpoint_url=checkpoint_url,
1246
+ model_source=model_source,
1247
+ )
1248
+
1235
1249
  def shutdown_model(self):
1236
1250
  self._model_served = False
1237
1251
  self._model_frozen = False
@@ -1447,7 +1461,7 @@ class Inference:
1447
1461
  if api is None:
1448
1462
  api = self.api
1449
1463
  return api
1450
-
1464
+
1451
1465
  def _inference_auto(
1452
1466
  self,
1453
1467
  source: List[Union[str, np.ndarray]],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: supervisely
3
- Version: 6.73.412
3
+ Version: 6.73.414
4
4
  Summary: Supervisely Python SDK.
5
5
  Home-page: https://github.com/supervisely/supervisely
6
6
  Author: Supervisely
@@ -36,10 +36,10 @@ supervisely/api/import_storage_api.py,sha256=BDCgmR0Hv6OoiRHLCVPKt3iDxSVlQp1WrnK
36
36
  supervisely/api/issues_api.py,sha256=BqDJXmNoTzwc3xe6_-mA7FDFC5QQ-ahGbXk_HmpkSeQ,17925
37
37
  supervisely/api/labeling_job_api.py,sha256=G2_BV_WtA2lAhfw_nAQmWmv1P-pwimD0ba9GVKoGjiA,55537
38
38
  supervisely/api/labeling_queue_api.py,sha256=ilNjAL1d9NSa9yabQn6E-W26YdtooT3ZGXIFZtGnAvY,30158
39
- supervisely/api/module_api.py,sha256=vqojLHCC-uCNVnqB2FUMCJdXAElg5FON3BZTr8AkiiE,46340
39
+ supervisely/api/module_api.py,sha256=-PVLcsicG47hVj_4vN8cuc0X-gqadsBJTj0ZxQOcO9g,46384
40
40
  supervisely/api/object_class_api.py,sha256=7-npNFMYjWNtSXYZg6syc6bX56_oCzDU2kFRPGQWCwA,10399
41
41
  supervisely/api/plugin_api.py,sha256=SFm0IlTTOjuHBLUMgG4d4k6U3cWJocE-SVb-f08fwMQ,5286
42
- supervisely/api/project_api.py,sha256=ZTmPEqWUQgYv5s5nEvnb2qobaiYxHFxibYZrtsJ-QAs,96362
42
+ supervisely/api/project_api.py,sha256=5WR4bNIq3eUlAkJga8DP_rYFIXKIU-myDlKNv911ssA,96449
43
43
  supervisely/api/project_class_api.py,sha256=5cyjdGPPb2tpttu5WmYoOxUNiDxqiojschkhZumF0KM,1426
44
44
  supervisely/api/remote_storage_api.py,sha256=1O4rTIwW8s9gxC00yvFuKbEMGNsa7YSRlZ8j494ARwY,17793
45
45
  supervisely/api/report_api.py,sha256=Om7CGulUbQ4BuJ16eDtz7luLe0JQNqab-LoLpUXu7YE,7123
@@ -99,7 +99,7 @@ supervisely/app/fastapi/index.html,sha256=dz_e-0RE5ZbOU0ToUaEHe1ROI6Tc3SPL-mHt1C
99
99
  supervisely/app/fastapi/no_html_main.html,sha256=NhQP7noyORBx72lFh1CQKgBRupkWjiq6Gaw-9Hkvg7c,37
100
100
  supervisely/app/fastapi/offline.py,sha256=CwMMkJ1frD6wiZS-SEoNDtQ1UJcJe1Ob6ohE3r4CQL8,7414
101
101
  supervisely/app/fastapi/request.py,sha256=NU7rKmxJ1pfkDZ7_yHckRcRAueJRQIqCor11UO2OHr8,766
102
- supervisely/app/fastapi/subapp.py,sha256=B4lU0B1nlhijiyMpwdsX_xrf7oITRL3_sv4XADo0kEc,45782
102
+ supervisely/app/fastapi/subapp.py,sha256=mhmXs64qDWBOBN1lfgeoxOHkelAdQwfM0CoD4sr-xB0,50132
103
103
  supervisely/app/fastapi/templating.py,sha256=pcghBW2OWVrNtplZuYa-mx04ektLiSvnBg-mhmyCoJc,2929
104
104
  supervisely/app/fastapi/utils.py,sha256=t_UquzlFrdkKtAJmH6eJ279pE8Aa3BaIu4XjX-SEaIE,946
105
105
  supervisely/app/fastapi/websocket.py,sha256=TlRSPOAhRItTv1HGvdukK1ZvhRjMUxRa-lJlsRR9rJw,1308
@@ -894,7 +894,7 @@ supervisely/nn/benchmark/visualization/widgets/table/__init__.py,sha256=47DEQpj8
894
894
  supervisely/nn/benchmark/visualization/widgets/table/table.py,sha256=atmDnF1Af6qLQBUjLhK18RMDKAYlxnsuVHMSEa5a-e8,4319
895
895
  supervisely/nn/inference/__init__.py,sha256=QFukX2ip-U7263aEPCF_UCFwj6EujbMnsgrXp5Bbt8I,1623
896
896
  supervisely/nn/inference/cache.py,sha256=rfmb1teJ9lNDfisUSh6bwDCVkPZocn8GMvDgLQktnbo,35023
897
- supervisely/nn/inference/inference.py,sha256=7c2-GuG3MgI5H0muTyxoR-XgUzWpbP9if37CyRewobA,198528
897
+ supervisely/nn/inference/inference.py,sha256=QTdx7RLekCs5JksRSc2skOlA9buNl05FtB6j9LcgKMQ,199183
898
898
  supervisely/nn/inference/inference_request.py,sha256=y6yw0vbaRRcEBS27nq3y0sL6Gmq2qLA_Bm0GrnJGegE,14267
899
899
  supervisely/nn/inference/session.py,sha256=dIg2F-OBl68pUzcmtmcI0YQIp1WWNnrJTVMjwFN91Q4,35824
900
900
  supervisely/nn/inference/uploader.py,sha256=21a9coOimCHhEqAbV-llZWcp12847DEMoQp3N16bpK0,5425
@@ -1115,9 +1115,9 @@ supervisely/worker_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
1115
1115
  supervisely/worker_proto/worker_api_pb2.py,sha256=VQfi5JRBHs2pFCK1snec3JECgGnua3Xjqw_-b3aFxuM,59142
1116
1116
  supervisely/worker_proto/worker_api_pb2_grpc.py,sha256=3BwQXOaP9qpdi0Dt9EKG--Lm8KGN0C5AgmUfRv77_Jk,28940
1117
1117
  supervisely_lib/__init__.py,sha256=7-3QnN8Zf0wj8NCr2oJmqoQWMKKPKTECvjH9pd2S5vY,159
1118
- supervisely-6.73.412.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1119
- supervisely-6.73.412.dist-info/METADATA,sha256=48ufWdiEor7nRHpV9wZcI8Rcn-RmPmGfMcHgv7aMciA,35254
1120
- supervisely-6.73.412.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
1121
- supervisely-6.73.412.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1122
- supervisely-6.73.412.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1123
- supervisely-6.73.412.dist-info/RECORD,,
1118
+ supervisely-6.73.414.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1119
+ supervisely-6.73.414.dist-info/METADATA,sha256=SzMumx5iuDhjBRPoWi8EcGKiaIIhxoVUvBJXPiED05Q,35254
1120
+ supervisely-6.73.414.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
1121
+ supervisely-6.73.414.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1122
+ supervisely-6.73.414.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1123
+ supervisely-6.73.414.dist-info/RECORD,,