snowflake-ml-python 1.3.0__py3-none-any.whl → 1.4.0__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.
Files changed (211) hide show
  1. snowflake/ml/_internal/file_utils.py +3 -3
  2. snowflake/ml/_internal/human_readable_id/adjectives.txt +128 -0
  3. snowflake/ml/_internal/human_readable_id/animals.txt +128 -0
  4. snowflake/ml/_internal/human_readable_id/hrid_generator.py +40 -0
  5. snowflake/ml/_internal/human_readable_id/hrid_generator_base.py +135 -0
  6. snowflake/ml/_internal/telemetry.py +11 -2
  7. snowflake/ml/_internal/utils/formatting.py +1 -1
  8. snowflake/ml/feature_store/feature_store.py +15 -106
  9. snowflake/ml/fileset/sfcfs.py +4 -3
  10. snowflake/ml/fileset/stage_fs.py +18 -0
  11. snowflake/ml/model/_api.py +9 -9
  12. snowflake/ml/model/_client/model/model_version_impl.py +20 -15
  13. snowflake/ml/model/_deploy_client/image_builds/docker_context.py +3 -9
  14. snowflake/ml/model/_deploy_client/image_builds/server_image_builder.py +3 -5
  15. snowflake/ml/model/_deploy_client/snowservice/deploy.py +7 -6
  16. snowflake/ml/model/_model_composer/model_composer.py +10 -8
  17. snowflake/ml/model/_model_composer/model_method/function_generator.py +1 -1
  18. snowflake/ml/model/_model_composer/model_method/infer_table_function.py_template +2 -1
  19. snowflake/ml/model/_model_composer/model_method/model_method.py +2 -2
  20. snowflake/ml/model/_model_composer/model_runtime/_runtime_requirements.py +1 -1
  21. snowflake/ml/model/_packager/model_handlers/_base.py +2 -2
  22. snowflake/ml/model/_packager/model_handlers/_utils.py +5 -5
  23. snowflake/ml/model/_packager/model_handlers/custom.py +7 -7
  24. snowflake/ml/model/_packager/model_handlers/huggingface_pipeline.py +2 -2
  25. snowflake/ml/model/_packager/model_handlers/llm.py +1 -1
  26. snowflake/ml/model/_packager/model_handlers/mlflow.py +1 -1
  27. snowflake/ml/model/_packager/model_handlers/pytorch.py +13 -10
  28. snowflake/ml/model/_packager/model_handlers/sentence_transformers.py +214 -0
  29. snowflake/ml/model/_packager/model_handlers/sklearn.py +6 -6
  30. snowflake/ml/model/_packager/model_handlers/snowmlmodel.py +15 -3
  31. snowflake/ml/model/_packager/model_handlers/tensorflow.py +8 -8
  32. snowflake/ml/model/_packager/model_handlers/torchscript.py +7 -7
  33. snowflake/ml/model/_packager/model_handlers/xgboost.py +8 -8
  34. snowflake/ml/model/_packager/model_meta/_core_requirements.py +1 -1
  35. snowflake/ml/model/_packager/model_packager.py +8 -6
  36. snowflake/ml/model/custom_model.py +3 -1
  37. snowflake/ml/model/type_hints.py +13 -0
  38. snowflake/ml/modeling/_internal/estimator_utils.py +61 -1
  39. snowflake/ml/modeling/_internal/local_implementations/pandas_handlers.py +4 -43
  40. snowflake/ml/modeling/_internal/local_implementations/pandas_trainer.py +4 -4
  41. snowflake/ml/modeling/_internal/ml_runtime_implementations/ml_runtime_handlers.py +21 -17
  42. snowflake/ml/modeling/_internal/model_specifications.py +3 -1
  43. snowflake/ml/modeling/_internal/model_trainer.py +2 -2
  44. snowflake/ml/modeling/_internal/snowpark_implementations/distributed_hpo_trainer.py +547 -1
  45. snowflake/ml/modeling/_internal/snowpark_implementations/snowpark_handlers.py +67 -114
  46. snowflake/ml/modeling/_internal/snowpark_implementations/snowpark_trainer.py +9 -9
  47. snowflake/ml/modeling/_internal/transformer_protocols.py +2 -3
  48. snowflake/ml/modeling/calibration/calibrated_classifier_cv.py +33 -61
  49. snowflake/ml/modeling/cluster/affinity_propagation.py +33 -61
  50. snowflake/ml/modeling/cluster/agglomerative_clustering.py +33 -61
  51. snowflake/ml/modeling/cluster/birch.py +33 -61
  52. snowflake/ml/modeling/cluster/bisecting_k_means.py +33 -61
  53. snowflake/ml/modeling/cluster/dbscan.py +33 -61
  54. snowflake/ml/modeling/cluster/feature_agglomeration.py +33 -61
  55. snowflake/ml/modeling/cluster/k_means.py +33 -61
  56. snowflake/ml/modeling/cluster/mean_shift.py +33 -61
  57. snowflake/ml/modeling/cluster/mini_batch_k_means.py +33 -61
  58. snowflake/ml/modeling/cluster/optics.py +33 -61
  59. snowflake/ml/modeling/cluster/spectral_biclustering.py +33 -61
  60. snowflake/ml/modeling/cluster/spectral_clustering.py +33 -61
  61. snowflake/ml/modeling/cluster/spectral_coclustering.py +33 -61
  62. snowflake/ml/modeling/compose/column_transformer.py +33 -61
  63. snowflake/ml/modeling/compose/transformed_target_regressor.py +33 -61
  64. snowflake/ml/modeling/covariance/elliptic_envelope.py +33 -61
  65. snowflake/ml/modeling/covariance/empirical_covariance.py +33 -61
  66. snowflake/ml/modeling/covariance/graphical_lasso.py +33 -61
  67. snowflake/ml/modeling/covariance/graphical_lasso_cv.py +33 -61
  68. snowflake/ml/modeling/covariance/ledoit_wolf.py +33 -61
  69. snowflake/ml/modeling/covariance/min_cov_det.py +33 -61
  70. snowflake/ml/modeling/covariance/oas.py +33 -61
  71. snowflake/ml/modeling/covariance/shrunk_covariance.py +33 -61
  72. snowflake/ml/modeling/decomposition/dictionary_learning.py +33 -61
  73. snowflake/ml/modeling/decomposition/factor_analysis.py +33 -61
  74. snowflake/ml/modeling/decomposition/fast_ica.py +33 -61
  75. snowflake/ml/modeling/decomposition/incremental_pca.py +33 -61
  76. snowflake/ml/modeling/decomposition/kernel_pca.py +33 -61
  77. snowflake/ml/modeling/decomposition/mini_batch_dictionary_learning.py +33 -61
  78. snowflake/ml/modeling/decomposition/mini_batch_sparse_pca.py +33 -61
  79. snowflake/ml/modeling/decomposition/pca.py +33 -61
  80. snowflake/ml/modeling/decomposition/sparse_pca.py +33 -61
  81. snowflake/ml/modeling/decomposition/truncated_svd.py +33 -61
  82. snowflake/ml/modeling/discriminant_analysis/linear_discriminant_analysis.py +33 -61
  83. snowflake/ml/modeling/discriminant_analysis/quadratic_discriminant_analysis.py +33 -61
  84. snowflake/ml/modeling/ensemble/ada_boost_classifier.py +33 -61
  85. snowflake/ml/modeling/ensemble/ada_boost_regressor.py +33 -61
  86. snowflake/ml/modeling/ensemble/bagging_classifier.py +33 -61
  87. snowflake/ml/modeling/ensemble/bagging_regressor.py +33 -61
  88. snowflake/ml/modeling/ensemble/extra_trees_classifier.py +33 -61
  89. snowflake/ml/modeling/ensemble/extra_trees_regressor.py +33 -61
  90. snowflake/ml/modeling/ensemble/gradient_boosting_classifier.py +33 -61
  91. snowflake/ml/modeling/ensemble/gradient_boosting_regressor.py +33 -61
  92. snowflake/ml/modeling/ensemble/hist_gradient_boosting_classifier.py +33 -61
  93. snowflake/ml/modeling/ensemble/hist_gradient_boosting_regressor.py +33 -61
  94. snowflake/ml/modeling/ensemble/isolation_forest.py +33 -61
  95. snowflake/ml/modeling/ensemble/random_forest_classifier.py +33 -61
  96. snowflake/ml/modeling/ensemble/random_forest_regressor.py +33 -61
  97. snowflake/ml/modeling/ensemble/stacking_regressor.py +33 -61
  98. snowflake/ml/modeling/ensemble/voting_classifier.py +33 -61
  99. snowflake/ml/modeling/ensemble/voting_regressor.py +33 -61
  100. snowflake/ml/modeling/feature_selection/generic_univariate_select.py +33 -61
  101. snowflake/ml/modeling/feature_selection/select_fdr.py +33 -61
  102. snowflake/ml/modeling/feature_selection/select_fpr.py +33 -61
  103. snowflake/ml/modeling/feature_selection/select_fwe.py +33 -61
  104. snowflake/ml/modeling/feature_selection/select_k_best.py +33 -61
  105. snowflake/ml/modeling/feature_selection/select_percentile.py +33 -61
  106. snowflake/ml/modeling/feature_selection/sequential_feature_selector.py +33 -61
  107. snowflake/ml/modeling/feature_selection/variance_threshold.py +33 -61
  108. snowflake/ml/modeling/framework/base.py +55 -5
  109. snowflake/ml/modeling/gaussian_process/gaussian_process_classifier.py +33 -61
  110. snowflake/ml/modeling/gaussian_process/gaussian_process_regressor.py +33 -61
  111. snowflake/ml/modeling/impute/iterative_imputer.py +33 -61
  112. snowflake/ml/modeling/impute/knn_imputer.py +33 -61
  113. snowflake/ml/modeling/impute/missing_indicator.py +33 -61
  114. snowflake/ml/modeling/impute/simple_imputer.py +4 -15
  115. snowflake/ml/modeling/kernel_approximation/additive_chi2_sampler.py +33 -61
  116. snowflake/ml/modeling/kernel_approximation/nystroem.py +33 -61
  117. snowflake/ml/modeling/kernel_approximation/polynomial_count_sketch.py +33 -61
  118. snowflake/ml/modeling/kernel_approximation/rbf_sampler.py +33 -61
  119. snowflake/ml/modeling/kernel_approximation/skewed_chi2_sampler.py +33 -61
  120. snowflake/ml/modeling/kernel_ridge/kernel_ridge.py +33 -61
  121. snowflake/ml/modeling/lightgbm/lgbm_classifier.py +36 -63
  122. snowflake/ml/modeling/lightgbm/lgbm_regressor.py +36 -63
  123. snowflake/ml/modeling/linear_model/ard_regression.py +33 -61
  124. snowflake/ml/modeling/linear_model/bayesian_ridge.py +33 -61
  125. snowflake/ml/modeling/linear_model/elastic_net.py +33 -61
  126. snowflake/ml/modeling/linear_model/elastic_net_cv.py +33 -61
  127. snowflake/ml/modeling/linear_model/gamma_regressor.py +33 -61
  128. snowflake/ml/modeling/linear_model/huber_regressor.py +33 -61
  129. snowflake/ml/modeling/linear_model/lars.py +33 -61
  130. snowflake/ml/modeling/linear_model/lars_cv.py +33 -61
  131. snowflake/ml/modeling/linear_model/lasso.py +33 -61
  132. snowflake/ml/modeling/linear_model/lasso_cv.py +33 -61
  133. snowflake/ml/modeling/linear_model/lasso_lars.py +33 -61
  134. snowflake/ml/modeling/linear_model/lasso_lars_cv.py +33 -61
  135. snowflake/ml/modeling/linear_model/lasso_lars_ic.py +33 -61
  136. snowflake/ml/modeling/linear_model/linear_regression.py +33 -61
  137. snowflake/ml/modeling/linear_model/logistic_regression.py +33 -61
  138. snowflake/ml/modeling/linear_model/logistic_regression_cv.py +33 -61
  139. snowflake/ml/modeling/linear_model/multi_task_elastic_net.py +33 -61
  140. snowflake/ml/modeling/linear_model/multi_task_elastic_net_cv.py +33 -61
  141. snowflake/ml/modeling/linear_model/multi_task_lasso.py +33 -61
  142. snowflake/ml/modeling/linear_model/multi_task_lasso_cv.py +33 -61
  143. snowflake/ml/modeling/linear_model/orthogonal_matching_pursuit.py +33 -61
  144. snowflake/ml/modeling/linear_model/passive_aggressive_classifier.py +33 -61
  145. snowflake/ml/modeling/linear_model/passive_aggressive_regressor.py +33 -61
  146. snowflake/ml/modeling/linear_model/perceptron.py +33 -61
  147. snowflake/ml/modeling/linear_model/poisson_regressor.py +33 -61
  148. snowflake/ml/modeling/linear_model/ransac_regressor.py +33 -61
  149. snowflake/ml/modeling/linear_model/ridge.py +33 -61
  150. snowflake/ml/modeling/linear_model/ridge_classifier.py +33 -61
  151. snowflake/ml/modeling/linear_model/ridge_classifier_cv.py +33 -61
  152. snowflake/ml/modeling/linear_model/ridge_cv.py +33 -61
  153. snowflake/ml/modeling/linear_model/sgd_classifier.py +33 -61
  154. snowflake/ml/modeling/linear_model/sgd_one_class_svm.py +33 -61
  155. snowflake/ml/modeling/linear_model/sgd_regressor.py +33 -61
  156. snowflake/ml/modeling/linear_model/theil_sen_regressor.py +33 -61
  157. snowflake/ml/modeling/linear_model/tweedie_regressor.py +33 -61
  158. snowflake/ml/modeling/manifold/isomap.py +33 -61
  159. snowflake/ml/modeling/manifold/mds.py +33 -61
  160. snowflake/ml/modeling/manifold/spectral_embedding.py +33 -61
  161. snowflake/ml/modeling/manifold/tsne.py +33 -61
  162. snowflake/ml/modeling/mixture/bayesian_gaussian_mixture.py +33 -61
  163. snowflake/ml/modeling/mixture/gaussian_mixture.py +33 -61
  164. snowflake/ml/modeling/model_selection/grid_search_cv.py +39 -57
  165. snowflake/ml/modeling/model_selection/randomized_search_cv.py +26 -57
  166. snowflake/ml/modeling/multiclass/one_vs_one_classifier.py +33 -61
  167. snowflake/ml/modeling/multiclass/one_vs_rest_classifier.py +33 -61
  168. snowflake/ml/modeling/multiclass/output_code_classifier.py +33 -61
  169. snowflake/ml/modeling/naive_bayes/bernoulli_nb.py +33 -61
  170. snowflake/ml/modeling/naive_bayes/categorical_nb.py +33 -61
  171. snowflake/ml/modeling/naive_bayes/complement_nb.py +33 -61
  172. snowflake/ml/modeling/naive_bayes/gaussian_nb.py +33 -61
  173. snowflake/ml/modeling/naive_bayes/multinomial_nb.py +33 -61
  174. snowflake/ml/modeling/neighbors/k_neighbors_classifier.py +33 -61
  175. snowflake/ml/modeling/neighbors/k_neighbors_regressor.py +33 -61
  176. snowflake/ml/modeling/neighbors/kernel_density.py +33 -61
  177. snowflake/ml/modeling/neighbors/local_outlier_factor.py +33 -61
  178. snowflake/ml/modeling/neighbors/nearest_centroid.py +33 -61
  179. snowflake/ml/modeling/neighbors/nearest_neighbors.py +33 -61
  180. snowflake/ml/modeling/neighbors/neighborhood_components_analysis.py +33 -61
  181. snowflake/ml/modeling/neighbors/radius_neighbors_classifier.py +33 -61
  182. snowflake/ml/modeling/neighbors/radius_neighbors_regressor.py +33 -61
  183. snowflake/ml/modeling/neural_network/bernoulli_rbm.py +33 -61
  184. snowflake/ml/modeling/neural_network/mlp_classifier.py +33 -61
  185. snowflake/ml/modeling/neural_network/mlp_regressor.py +33 -61
  186. snowflake/ml/modeling/preprocessing/polynomial_features.py +33 -61
  187. snowflake/ml/modeling/semi_supervised/label_propagation.py +33 -61
  188. snowflake/ml/modeling/semi_supervised/label_spreading.py +33 -61
  189. snowflake/ml/modeling/svm/linear_svc.py +33 -61
  190. snowflake/ml/modeling/svm/linear_svr.py +33 -61
  191. snowflake/ml/modeling/svm/nu_svc.py +33 -61
  192. snowflake/ml/modeling/svm/nu_svr.py +33 -61
  193. snowflake/ml/modeling/svm/svc.py +33 -61
  194. snowflake/ml/modeling/svm/svr.py +33 -61
  195. snowflake/ml/modeling/tree/decision_tree_classifier.py +33 -61
  196. snowflake/ml/modeling/tree/decision_tree_regressor.py +33 -61
  197. snowflake/ml/modeling/tree/extra_tree_classifier.py +33 -61
  198. snowflake/ml/modeling/tree/extra_tree_regressor.py +33 -61
  199. snowflake/ml/modeling/xgboost/xgb_classifier.py +33 -61
  200. snowflake/ml/modeling/xgboost/xgb_regressor.py +33 -61
  201. snowflake/ml/modeling/xgboost/xgbrf_classifier.py +33 -61
  202. snowflake/ml/modeling/xgboost/xgbrf_regressor.py +33 -61
  203. snowflake/ml/registry/_manager/model_manager.py +6 -2
  204. snowflake/ml/registry/model_registry.py +100 -27
  205. snowflake/ml/registry/registry.py +6 -2
  206. snowflake/ml/version.py +1 -1
  207. {snowflake_ml_python-1.3.0.dist-info → snowflake_ml_python-1.4.0.dist-info}/METADATA +43 -7
  208. {snowflake_ml_python-1.3.0.dist-info → snowflake_ml_python-1.4.0.dist-info}/RECORD +211 -206
  209. {snowflake_ml_python-1.3.0.dist-info → snowflake_ml_python-1.4.0.dist-info}/LICENSE.txt +0 -0
  210. {snowflake_ml_python-1.3.0.dist-info → snowflake_ml_python-1.4.0.dist-info}/WHEEL +0 -0
  211. {snowflake_ml_python-1.3.0.dist-info → snowflake_ml_python-1.4.0.dist-info}/top_level.txt +0 -0
@@ -75,6 +75,12 @@ class SFStageFileSystem(fsspec.AbstractFileSystem):
75
75
  -74.00688,40.73049,-74.00563,40.70676,2\n'
76
76
  """
77
77
 
78
+ # Cached state marking whether we should use Snowpark file download instead of pre-signed URLs:
79
+ # None -> Try pre-signed URL access, fall back to file download
80
+ # True -> Use file download path without trying pre-signed URL access
81
+ # False -> Use pre-signed URL access, skip download fallback on failure
82
+ _USE_FALLBACK_FILE_ACCESS = None
83
+
78
84
  def __init__(
79
85
  self,
80
86
  *,
@@ -227,6 +233,8 @@ class SFStageFileSystem(fsspec.AbstractFileSystem):
227
233
  SnowflakeMLException: An error occurred when the given path points to a file that cannot be found.
228
234
  """
229
235
  path = path.lstrip("/")
236
+ if self._USE_FALLBACK_FILE_ACCESS:
237
+ return self._session.file.get_stream(f"{self.stage_name}/{path}")
230
238
  cached_presigned_url = self._url_cache.get(path, None)
231
239
  if not cached_presigned_url:
232
240
  res = self._fetch_presigned_urls([path])
@@ -242,6 +250,16 @@ class SFStageFileSystem(fsspec.AbstractFileSystem):
242
250
  try:
243
251
  return self._fs._open(url, mode=mode, **kwargs)
244
252
  except FileNotFoundError:
253
+ # Enable fallback if _USE_FALLBACK_FILE_ACCESS is True or None; set to False to disable
254
+ if self._USE_FALLBACK_FILE_ACCESS != False: # noqa: E712
255
+ try:
256
+ # Try falling back to Snowpark file read if presigned URL access failed
257
+ # If fallback is successful, most likely in sproc without External Access Integration
258
+ content = self._session.file.get_stream(f"{self.stage_name}/{path}")
259
+ self._USE_FALLBACK_FILE_ACCESS = True
260
+ return content
261
+ except Exception:
262
+ pass
245
263
  raise snowml_exceptions.SnowflakeMLException(
246
264
  error_code=error_codes.SNOWML_NOT_FOUND,
247
265
  original_exception=fileset_errors.StageFileNotFoundError(f"Stage file {path} doesn't exist."),
@@ -108,7 +108,7 @@ def save_model(
108
108
  model: model_types.SupportedRequireSignatureModelType,
109
109
  session: Session,
110
110
  stage_path: str,
111
- sample_input: model_types.SupportedDataType,
111
+ sample_input_data: model_types.SupportedDataType,
112
112
  metadata: Optional[Dict[str, str]] = None,
113
113
  conda_dependencies: Optional[List[str]] = None,
114
114
  pip_requirements: Optional[List[str]] = None,
@@ -125,7 +125,7 @@ def save_model(
125
125
  model: Model object.
126
126
  session: Snowpark connection session.
127
127
  stage_path: Path to the stage where model will be saved.
128
- sample_input: Sample input data to infer the model signatures from.
128
+ sample_input_data: Sample input data to infer the model signatures from.
129
129
  metadata: Model metadata.
130
130
  conda_dependencies: List of Conda package specs. Use "[channel::]package [operator version]" syntax to specify
131
131
  a dependency. It is a recommended way to specify your dependencies using conda. When channel is not
@@ -149,7 +149,7 @@ def save_model(
149
149
  session: Session,
150
150
  stage_path: str,
151
151
  signatures: Optional[Dict[str, model_signature.ModelSignature]] = None,
152
- sample_input: Optional[model_types.SupportedDataType] = None,
152
+ sample_input_data: Optional[model_types.SupportedDataType] = None,
153
153
  metadata: Optional[Dict[str, str]] = None,
154
154
  conda_dependencies: Optional[List[str]] = None,
155
155
  pip_requirements: Optional[List[str]] = None,
@@ -165,11 +165,11 @@ def save_model(
165
165
  model: Model object.
166
166
  session: Snowpark connection session.
167
167
  stage_path: Path to the stage where model will be saved.
168
- signatures: Model data signatures for inputs and output for every target methods. If it is None, sample_input
169
- would be used to infer the signatures if it is a local (non-SnowML modeling model).
170
- If not None, sample_input should not be specified. Defaults to None.
171
- sample_input: Sample input data to infer the model signatures from. If it is None, signatures must be specified
172
- if it is a local (non-SnowML modeling model). If not None, signatures should not be specified.
168
+ signatures: Model data signatures for inputs and output for every target methods. If it is None,
169
+ sample_input_data would be used to infer the signatures if it is a local (non-SnowML modeling model).
170
+ If not None, sample_input_data should not be specified. Defaults to None.
171
+ sample_input_data: Sample input data to infer the model signatures from. If it is None, signatures must be
172
+ specified if it is a local (non-SnowML modeling model). If not None, signatures should not be specified.
173
173
  Defaults to None.
174
174
  metadata: Model metadata.
175
175
  conda_dependencies: List of Conda package specs. Use "[channel::]package [operator version]" syntax to specify
@@ -196,7 +196,7 @@ def save_model(
196
196
  name=name,
197
197
  model=model,
198
198
  signatures=signatures,
199
- sample_input=sample_input,
199
+ sample_input_data=sample_input_data,
200
200
  metadata=metadata,
201
201
  conda_dependencies=conda_dependencies,
202
202
  pip_requirements=pip_requirements,
@@ -21,6 +21,7 @@ class ModelVersion:
21
21
  _model_ops: model_ops.ModelOperator
22
22
  _model_name: sql_identifier.SqlIdentifier
23
23
  _version_name: sql_identifier.SqlIdentifier
24
+ _functions: List[model_manifest_schema.ModelFunctionInfo]
24
25
 
25
26
  def __init__(self) -> None:
26
27
  raise RuntimeError("ModelVersion's initializer is not meant to be used. Use `version` from model instead.")
@@ -37,6 +38,7 @@ class ModelVersion:
37
38
  self._model_ops = model_ops
38
39
  self._model_name = model_name
39
40
  self._version_name = version_name
41
+ self._functions = self._get_functions()
40
42
  return self
41
43
 
42
44
  def __eq__(self, __value: object) -> bool:
@@ -239,20 +241,7 @@ class ModelVersion:
239
241
  return_functions_info.append(fi)
240
242
  return return_functions_info
241
243
 
242
- @telemetry.send_api_usage_telemetry(
243
- project=_TELEMETRY_PROJECT,
244
- subproject=_TELEMETRY_SUBPROJECT,
245
- )
246
- def show_functions(self) -> List[model_manifest_schema.ModelFunctionInfo]:
247
- """Show all functions information in a model version that is callable.
248
-
249
- Returns:
250
- A list of ModelFunctionInfo objects containing the following information:
251
-
252
- - name: The name of the function to be called (both in SQL and in Python SDK).
253
- - target_method: The original method name in the logged Python object.
254
- - signature: Python signature of the original method.
255
- """
244
+ def _get_functions(self) -> List[model_manifest_schema.ModelFunctionInfo]:
256
245
  statement_params = telemetry.get_statement_params(
257
246
  project=_TELEMETRY_PROJECT,
258
247
  subproject=_TELEMETRY_SUBPROJECT,
@@ -274,6 +263,22 @@ class ModelVersion:
274
263
  except (NotImplementedError, ValueError, connector.DataError):
275
264
  return self._legacy_show_functions()
276
265
 
266
+ @telemetry.send_api_usage_telemetry(
267
+ project=_TELEMETRY_PROJECT,
268
+ subproject=_TELEMETRY_SUBPROJECT,
269
+ )
270
+ def show_functions(self) -> List[model_manifest_schema.ModelFunctionInfo]:
271
+ """Show all functions information in a model version that is callable.
272
+
273
+ Returns:
274
+ A list of ModelFunctionInfo objects containing the following information:
275
+
276
+ - name: The name of the function to be called (both in SQL and in Python SDK).
277
+ - target_method: The original method name in the logged Python object.
278
+ - signature: Python signature of the original method.
279
+ """
280
+ return self._functions
281
+
277
282
  @telemetry.send_api_usage_telemetry(
278
283
  project=_TELEMETRY_PROJECT,
279
284
  subproject=_TELEMETRY_SUBPROJECT,
@@ -306,7 +311,7 @@ class ModelVersion:
306
311
  subproject=_TELEMETRY_SUBPROJECT,
307
312
  )
308
313
 
309
- functions: List[model_manifest_schema.ModelFunctionInfo] = self.show_functions()
314
+ functions: List[model_manifest_schema.ModelFunctionInfo] = self._functions
310
315
  if function_name:
311
316
  req_method_name = sql_identifier.SqlIdentifier(function_name).identifier()
312
317
  find_method: Callable[[model_manifest_schema.ModelFunctionInfo], bool] = (
@@ -52,9 +52,7 @@ class DockerContext:
52
52
 
53
53
  def _copy_entrypoint_script_to_docker_context(self) -> None:
54
54
  """Copy gunicorn_run.sh entrypoint to docker context directory."""
55
- script_path = importlib_resources.files(image_builds).joinpath( # type: ignore[no-untyped-call]
56
- constants.ENTRYPOINT_SCRIPT
57
- )
55
+ script_path = importlib_resources.files(image_builds).joinpath(constants.ENTRYPOINT_SCRIPT)
58
56
  target_path = os.path.join(self.context_dir, constants.ENTRYPOINT_SCRIPT)
59
57
 
60
58
  with open(script_path, encoding="utf-8") as source_file, file_utils.open_file(target_path, "w") as target_file:
@@ -72,9 +70,7 @@ class DockerContext:
72
70
  """
73
71
  docker_file_path = os.path.join(self.context_dir, "Dockerfile")
74
72
  docker_file_template = (
75
- importlib_resources.files(image_builds)
76
- .joinpath("templates/dockerfile_template") # type: ignore[no-untyped-call]
77
- .read_text("utf-8")
73
+ importlib_resources.files(image_builds).joinpath("templates/dockerfile_template").read_text("utf-8")
78
74
  )
79
75
 
80
76
  if self.model_zip_stage_path is not None:
@@ -123,9 +119,7 @@ class DockerContext:
123
119
  server code.
124
120
  """
125
121
  with importlib_resources.as_file(
126
- importlib_resources.files(image_builds).joinpath( # type: ignore[no-untyped-call]
127
- constants.INFERENCE_SERVER_DIR
128
- )
122
+ importlib_resources.files(image_builds).joinpath(constants.INFERENCE_SERVER_DIR)
129
123
  ) as inference_server_folder_path:
130
124
  destination_folder_path = os.path.join(self.context_dir, constants.INFERENCE_SERVER_DIR)
131
125
  ignore_patterns = shutil.ignore_patterns("BUILD.bazel", "*test.py", "*.\\.*", "__pycache__")
@@ -114,7 +114,7 @@ class ServerImageBuilder(base_image_builder.ImageBuilder):
114
114
  """
115
115
  kaniko_shell_script_template = (
116
116
  importlib_resources.files(image_builds)
117
- .joinpath(f"templates/{constants.KANIKO_SHELL_SCRIPT_TEMPLATE}") # type: ignore[no-untyped-call]
117
+ .joinpath(f"templates/{constants.KANIKO_SHELL_SCRIPT_TEMPLATE}")
118
118
  .read_text("utf-8")
119
119
  )
120
120
 
@@ -170,13 +170,11 @@ class ServerImageBuilder(base_image_builder.ImageBuilder):
170
170
 
171
171
  spec_template = (
172
172
  importlib_resources.files(image_builds)
173
- .joinpath(f"templates/{constants.IMAGE_BUILD_JOB_SPEC_TEMPLATE}") # type: ignore[no-untyped-call]
173
+ .joinpath(f"templates/{constants.IMAGE_BUILD_JOB_SPEC_TEMPLATE}")
174
174
  .read_text("utf-8")
175
175
  )
176
176
 
177
- spec_file_path = os.path.join(
178
- os.path.dirname(self.context_dir), f"{constants.IMAGE_BUILD_JOB_SPEC_TEMPLATE}.yaml"
179
- )
177
+ spec_file_path = os.path.join(self.context_dir, f"{constants.IMAGE_BUILD_JOB_SPEC_TEMPLATE}.yaml")
180
178
 
181
179
  with file_utils.open_file(spec_file_path, "w+") as spec_file:
182
180
  assert self.artifact_stage_location.startswith("@")
@@ -239,14 +239,17 @@ def _validate_compute_pool(session: Session, *, options: deploy_options.SnowServ
239
239
  ),
240
240
  )
241
241
 
242
- elif state not in ["ACTIVE", "IDLE"]:
242
+ elif state not in ["STARTING", "ACTIVE", "IDLE"]:
243
243
  raise snowml_exceptions.SnowflakeMLException(
244
244
  error_code=error_codes.INVALID_SNOWPARK_COMPUTE_POOL,
245
245
  original_exception=RuntimeError(
246
- "The compute pool you are requesting to use is not in the ACTIVE/IDLE status."
246
+ "The compute pool you are requesting to use is not in the ACTIVE/IDLE/STARTING status."
247
247
  ),
248
248
  )
249
249
 
250
+ if state in ["SUSPENDED", "STARTING"]:
251
+ logger.warning(f"The compute pool you are requesting is in {state} state. We are waiting it to be ready.")
252
+
250
253
  if options.use_gpu:
251
254
  assert options.num_gpus is not None
252
255
  request_gpus = options.num_gpus
@@ -482,14 +485,12 @@ class SnowServiceDeployment:
482
485
  if self.options.model_in_image:
483
486
  spec_template = (
484
487
  importlib_resources.files(snowservice)
485
- .joinpath("templates/service_spec_template_with_model") # type: ignore[no-untyped-call]
488
+ .joinpath("templates/service_spec_template_with_model")
486
489
  .read_text("utf-8")
487
490
  )
488
491
  else:
489
492
  spec_template = (
490
- importlib_resources.files(snowservice)
491
- .joinpath("templates/service_spec_template") # type: ignore[no-untyped-call]
492
- .read_text("utf-8")
493
+ importlib_resources.files(snowservice).joinpath("templates/service_spec_template").read_text("utf-8")
493
494
  )
494
495
 
495
496
  with _debug_aware_tmp_directory(self.debug_dir) as dir_path:
@@ -1,6 +1,7 @@
1
1
  import glob
2
2
  import pathlib
3
3
  import tempfile
4
+ import uuid
4
5
  import zipfile
5
6
  from types import ModuleType
6
7
  from typing import Any, Dict, List, Optional
@@ -28,10 +29,9 @@ class ModelComposer:
28
29
  packager: A ModelPackager object managing the (un)packaging of a Snowflake Native Model in the MODEL object.
29
30
 
30
31
  _packager_workspace_path: A local path created from packager where it will dump all files there and ModelModel
31
- will zip it. This would not required if we make directory import work.
32
+ will zip it. This would not be required if we make directory import work.
32
33
  """
33
34
 
34
- MODEL_FILE_REL_PATH = "model.zip"
35
35
  MODEL_DIR_REL_PATH = "model"
36
36
 
37
37
  def __init__(
@@ -50,6 +50,8 @@ class ModelComposer:
50
50
  self.packager = model_packager.ModelPackager(local_dir_path=str(self._packager_workspace_path))
51
51
  self.manifest = model_manifest.ModelManifest(workspace_path=self.workspace_path)
52
52
 
53
+ self.model_file_rel_path = f"model-{uuid.uuid4().hex}.zip"
54
+
53
55
  self._statement_params = statement_params
54
56
 
55
57
  def __del__(self) -> None:
@@ -66,11 +68,11 @@ class ModelComposer:
66
68
 
67
69
  @property
68
70
  def model_stage_path(self) -> str:
69
- return (self.stage_path / ModelComposer.MODEL_FILE_REL_PATH).as_posix()
71
+ return (self.stage_path / self.model_file_rel_path).as_posix()
70
72
 
71
73
  @property
72
74
  def model_local_path(self) -> str:
73
- return str(self.workspace_path / ModelComposer.MODEL_FILE_REL_PATH)
75
+ return str(self.workspace_path / self.model_file_rel_path)
74
76
 
75
77
  def save(
76
78
  self,
@@ -78,7 +80,7 @@ class ModelComposer:
78
80
  name: str,
79
81
  model: model_types.SupportedModelType,
80
82
  signatures: Optional[Dict[str, model_signature.ModelSignature]] = None,
81
- sample_input: Optional[model_types.SupportedDataType] = None,
83
+ sample_input_data: Optional[model_types.SupportedDataType] = None,
82
84
  metadata: Optional[Dict[str, str]] = None,
83
85
  conda_dependencies: Optional[List[str]] = None,
84
86
  pip_requirements: Optional[List[str]] = None,
@@ -106,7 +108,7 @@ class ModelComposer:
106
108
  name=name,
107
109
  model=model,
108
110
  signatures=signatures,
109
- sample_input=sample_input,
111
+ sample_input_data=sample_input_data,
110
112
  metadata=metadata,
111
113
  conda_dependencies=conda_dependencies,
112
114
  pip_requirements=pip_requirements,
@@ -130,7 +132,7 @@ class ModelComposer:
130
132
  self.manifest.save(
131
133
  session=self.session,
132
134
  model_meta=self.packager.meta,
133
- model_file_rel_path=pathlib.PurePosixPath(ModelComposer.MODEL_FILE_REL_PATH),
135
+ model_file_rel_path=pathlib.PurePosixPath(self.model_file_rel_path),
134
136
  options=options,
135
137
  )
136
138
 
@@ -156,7 +158,7 @@ class ModelComposer:
156
158
 
157
159
  # TODO (Server-side Model Rollout): Remove this section.
158
160
  model_zip_path = pathlib.Path(glob.glob(str(self.workspace_path / "*.zip"))[0])
159
- ModelComposer.MODEL_FILE_REL_PATH = str(model_zip_path.relative_to(self.workspace_path))
161
+ self.model_file_rel_path = str(model_zip_path.relative_to(self.workspace_path))
160
162
 
161
163
  with zipfile.ZipFile(self.model_local_path, mode="r", compression=zipfile.ZIP_DEFLATED) as zf:
162
164
  zf.extractall(path=self._packager_workspace_path)
@@ -46,7 +46,7 @@ class FunctionGenerator:
46
46
 
47
47
  function_template = (
48
48
  importlib_resources.files("snowflake.ml.model._model_composer.model_method")
49
- .joinpath(template_filename) # type: ignore[no-untyped-call]
49
+ .joinpath(template_filename)
50
50
  .read_text()
51
51
  )
52
52
 
@@ -72,5 +72,6 @@ dtype_map = {{feature.name: feature.as_dtype() for feature in features}}
72
72
 
73
73
  # Actual table function
74
74
  class {function_name}:
75
- def end_partition(df: pd.DataFrame) -> pd.DataFrame:
75
+ @vectorized(input=pd.DataFrame)
76
+ def end_partition(self, df: pd.DataFrame) -> pd.DataFrame:
76
77
  return runner(df)
@@ -33,8 +33,8 @@ def get_model_method_options_from_options(
33
33
  options: type_hints.ModelSaveOption, target_method: str
34
34
  ) -> ModelMethodOptions:
35
35
  method_option = options.get("method_options", {}).get(target_method, {})
36
-
37
- function_type = method_option.get("function_type", ModelMethodFunctionTypes.FUNCTION.value)
36
+ global_function_type = options.get("function_type", ModelMethodFunctionTypes.FUNCTION.value)
37
+ function_type = method_option.get("function_type", global_function_type)
38
38
  if function_type not in [function_type.value for function_type in ModelMethodFunctionTypes]:
39
39
  raise NotImplementedError
40
40
 
@@ -5,6 +5,6 @@ REQUIREMENTS = [
5
5
  "packaging>=20.9,<24",
6
6
  "pandas>=1.0.0,<2",
7
7
  "pyyaml>=6.0,<7",
8
- "snowflake-snowpark-python>=1.8.0,<2,!=1.12.0",
8
+ "snowflake-snowpark-python>=1.11.1,<2,!=1.12.0",
9
9
  "typing-extensions>=4.1.0,<5"
10
10
  ]
@@ -48,7 +48,7 @@ class _BaseModelHandlerProtocol(Protocol[model_types._ModelType]):
48
48
  model: model_types._ModelType,
49
49
  model_meta: model_meta.ModelMetadata,
50
50
  model_blobs_dir_path: str,
51
- sample_input: Optional[model_types.SupportedDataType] = None,
51
+ sample_input_data: Optional[model_types.SupportedDataType] = None,
52
52
  is_sub_model: Optional[bool] = False,
53
53
  **kwargs: Unpack[model_types.BaseModelSaveOption],
54
54
  ) -> None:
@@ -59,7 +59,7 @@ class _BaseModelHandlerProtocol(Protocol[model_types._ModelType]):
59
59
  model: The model object.
60
60
  model_meta: The model metadata.
61
61
  model_blobs_dir_path: Directory path to the model.
62
- sample_input: Sample input to infer the signatures from.
62
+ sample_input_data: Sample input to infer the signatures from.
63
63
  is_sub_model: Flag to show if it is a sub model, a sub model does not need signature.
64
64
  kwargs: Additional saving options.
65
65
 
@@ -14,19 +14,19 @@ def validate_signature(
14
14
  model: model_types.SupportedRequireSignatureModelType,
15
15
  model_meta: model_meta.ModelMetadata,
16
16
  target_methods: Iterable[str],
17
- sample_input: Optional[model_types.SupportedDataType],
17
+ sample_input_data: Optional[model_types.SupportedDataType],
18
18
  get_prediction_fn: Callable[[str, model_types.SupportedLocalDataType], model_types.SupportedLocalDataType],
19
19
  ) -> model_meta.ModelMetadata:
20
20
  if model_meta.signatures:
21
21
  validate_target_methods(model, list(model_meta.signatures.keys()))
22
22
  return model_meta
23
23
 
24
- # In this case sample_input should be available, because of the check in save_model.
24
+ # In this case sample_input_data should be available, because of the check in save_model.
25
25
  assert (
26
- sample_input is not None
26
+ sample_input_data is not None
27
27
  ), "Model signature and sample input are None at the same time. This should not happen with local model."
28
- trunc_sample_input = model_signature._truncate_data(sample_input)
29
- if isinstance(sample_input, SnowparkDataFrame):
28
+ trunc_sample_input = model_signature._truncate_data(sample_input_data)
29
+ if isinstance(sample_input_data, SnowparkDataFrame):
30
30
  # Added because of Any from missing stubs.
31
31
  trunc_sample_input = cast(SnowparkDataFrame, trunc_sample_input)
32
32
  local_sample_input = snowpark_handler.SnowparkDataFrameHandler.convert_to_df(trunc_sample_input)
@@ -45,27 +45,27 @@ class CustomModelHandler(_base.BaseModelHandler["custom_model.CustomModel"]):
45
45
  model: "custom_model.CustomModel",
46
46
  model_meta: model_meta_api.ModelMetadata,
47
47
  model_blobs_dir_path: str,
48
- sample_input: Optional[model_types.SupportedDataType] = None,
48
+ sample_input_data: Optional[model_types.SupportedDataType] = None,
49
49
  is_sub_model: Optional[bool] = False,
50
50
  **kwargs: Unpack[model_types.CustomModelSaveOption],
51
51
  ) -> None:
52
52
  assert isinstance(model, custom_model.CustomModel)
53
53
 
54
54
  def get_prediction(
55
- target_method_name: str, sample_input: model_types.SupportedLocalDataType
55
+ target_method_name: str, sample_input_data: model_types.SupportedLocalDataType
56
56
  ) -> model_types.SupportedLocalDataType:
57
57
  target_method = getattr(model, target_method_name, None)
58
58
  assert callable(target_method) and inspect.ismethod(target_method)
59
59
  target_method = target_method.__func__
60
60
 
61
- if not isinstance(sample_input, pd.DataFrame):
62
- sample_input = model_signature._convert_local_data_to_df(sample_input)
61
+ if not isinstance(sample_input_data, pd.DataFrame):
62
+ sample_input_data = model_signature._convert_local_data_to_df(sample_input_data)
63
63
 
64
64
  if inspect.iscoroutinefunction(target_method):
65
65
  with anyio.start_blocking_portal() as portal:
66
- predictions_df = portal.call(target_method, model, sample_input)
66
+ predictions_df = portal.call(target_method, model, sample_input_data)
67
67
  else:
68
- predictions_df = target_method(model, sample_input)
68
+ predictions_df = target_method(model, sample_input_data)
69
69
  return predictions_df
70
70
 
71
71
  if not is_sub_model:
@@ -73,7 +73,7 @@ class CustomModelHandler(_base.BaseModelHandler["custom_model.CustomModel"]):
73
73
  model=model,
74
74
  model_meta=model_meta,
75
75
  target_methods=[method.__name__ for method in model._get_infer_methods()],
76
- sample_input=sample_input,
76
+ sample_input_data=sample_input_data,
77
77
  get_prediction_fn=get_prediction,
78
78
  )
79
79
 
@@ -128,7 +128,7 @@ class HuggingFacePipelineHandler(
128
128
  model: Union[huggingface_pipeline.HuggingFacePipelineModel, "transformers.Pipeline"],
129
129
  model_meta: model_meta_api.ModelMetadata,
130
130
  model_blobs_dir_path: str,
131
- sample_input: Optional[model_types.SupportedDataType] = None,
131
+ sample_input_data: Optional[model_types.SupportedDataType] = None,
132
132
  is_sub_model: Optional[bool] = False,
133
133
  **kwargs: Unpack[model_types.HuggingFaceSaveOptions],
134
134
  ) -> None:
@@ -174,7 +174,7 @@ class HuggingFacePipelineHandler(
174
174
  )
175
175
  else:
176
176
  handlers_utils.validate_target_methods(model, target_methods)
177
- if sample_input is not None:
177
+ if sample_input_data is not None:
178
178
  warnings.warn(
179
179
  "Inferring model signature from sample input for hugggingface pipeline is not supported. "
180
180
  + "Model signature will automatically be inferred from pipeline task. "
@@ -54,7 +54,7 @@ class LLMHandler(_base.BaseModelHandler[llm.LLM]):
54
54
  model: llm.LLM,
55
55
  model_meta: model_meta_api.ModelMetadata,
56
56
  model_blobs_dir_path: str,
57
- sample_input: Optional[model_types.SupportedDataType] = None,
57
+ sample_input_data: Optional[model_types.SupportedDataType] = None,
58
58
  is_sub_model: Optional[bool] = False,
59
59
  **kwargs: Unpack[model_types.LLMSaveOptions],
60
60
  ) -> None:
@@ -92,7 +92,7 @@ class MLFlowHandler(_base.BaseModelHandler["mlflow.pyfunc.PyFuncModel"]):
92
92
  model: "mlflow.pyfunc.PyFuncModel",
93
93
  model_meta: model_meta_api.ModelMetadata,
94
94
  model_blobs_dir_path: str,
95
- sample_input: Optional[model_types.SupportedDataType] = None,
95
+ sample_input_data: Optional[model_types.SupportedDataType] = None,
96
96
  is_sub_model: Optional[bool] = False,
97
97
  **kwargs: Unpack[model_types.MLFlowSaveOptions],
98
98
  ) -> None:
@@ -21,6 +21,7 @@ from snowflake.ml.model._signatures import (
21
21
  )
22
22
 
23
23
  if TYPE_CHECKING:
24
+ import sentence_transformers # noqa: F401
24
25
  import torch
25
26
 
26
27
 
@@ -44,9 +45,11 @@ class PyTorchHandler(_base.BaseModelHandler["torch.nn.Module"]):
44
45
  cls,
45
46
  model: model_types.SupportedModelType,
46
47
  ) -> TypeGuard["torch.nn.Module"]:
47
- return type_utils.LazyType("torch.nn.Module").isinstance(model) and not type_utils.LazyType(
48
- "torch.jit.ScriptModule"
49
- ).isinstance(model)
48
+ return (
49
+ type_utils.LazyType("torch.nn.Module").isinstance(model)
50
+ and not type_utils.LazyType("torch.jit.ScriptModule").isinstance(model)
51
+ and not type_utils.LazyType("sentence_transformers.SentenceTransformer").isinstance(model)
52
+ )
50
53
 
51
54
  @classmethod
52
55
  def cast_model(
@@ -66,7 +69,7 @@ class PyTorchHandler(_base.BaseModelHandler["torch.nn.Module"]):
66
69
  model: "torch.nn.Module",
67
70
  model_meta: model_meta_api.ModelMetadata,
68
71
  model_blobs_dir_path: str,
69
- sample_input: Optional[model_types.SupportedDataType] = None,
72
+ sample_input_data: Optional[model_types.SupportedDataType] = None,
70
73
  is_sub_model: Optional[bool] = False,
71
74
  **kwargs: Unpack[model_types.PyTorchSaveOptions],
72
75
  ) -> None:
@@ -82,18 +85,18 @@ class PyTorchHandler(_base.BaseModelHandler["torch.nn.Module"]):
82
85
  )
83
86
 
84
87
  def get_prediction(
85
- target_method_name: str, sample_input: "model_types.SupportedLocalDataType"
88
+ target_method_name: str, sample_input_data: "model_types.SupportedLocalDataType"
86
89
  ) -> model_types.SupportedLocalDataType:
87
- if not pytorch_handler.SeqOfPyTorchTensorHandler.can_handle(sample_input):
88
- sample_input = pytorch_handler.SeqOfPyTorchTensorHandler.convert_from_df(
89
- model_signature._convert_local_data_to_df(sample_input)
90
+ if not pytorch_handler.SeqOfPyTorchTensorHandler.can_handle(sample_input_data):
91
+ sample_input_data = pytorch_handler.SeqOfPyTorchTensorHandler.convert_from_df(
92
+ model_signature._convert_local_data_to_df(sample_input_data)
90
93
  )
91
94
 
92
95
  model.eval()
93
96
  target_method = getattr(model, target_method_name, None)
94
97
  assert callable(target_method)
95
98
  with torch.no_grad():
96
- predictions_df = target_method(*sample_input)
99
+ predictions_df = target_method(*sample_input_data)
97
100
 
98
101
  if isinstance(predictions_df, torch.Tensor):
99
102
  predictions_df = [predictions_df]
@@ -103,7 +106,7 @@ class PyTorchHandler(_base.BaseModelHandler["torch.nn.Module"]):
103
106
  model=model,
104
107
  model_meta=model_meta,
105
108
  target_methods=target_methods,
106
- sample_input=sample_input,
109
+ sample_input_data=sample_input_data,
107
110
  get_prediction_fn=get_prediction,
108
111
  )
109
112