snowflake-ml-python 1.4.0__py3-none-any.whl → 1.5.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.
- snowflake/ml/_internal/env_utils.py +77 -32
- snowflake/ml/_internal/exceptions/dataset_error_messages.py +5 -0
- snowflake/ml/_internal/exceptions/dataset_errors.py +24 -0
- snowflake/ml/_internal/exceptions/error_codes.py +3 -0
- snowflake/ml/_internal/lineage/data_source.py +10 -0
- snowflake/ml/_internal/lineage/dataset_dataframe.py +44 -0
- snowflake/ml/_internal/utils/identifier.py +3 -1
- snowflake/ml/_internal/utils/sql_identifier.py +2 -6
- snowflake/ml/dataset/__init__.py +10 -0
- snowflake/ml/dataset/dataset.py +454 -129
- snowflake/ml/dataset/dataset_factory.py +53 -0
- snowflake/ml/dataset/dataset_metadata.py +103 -0
- snowflake/ml/dataset/dataset_reader.py +202 -0
- snowflake/ml/feature_store/feature_store.py +531 -332
- snowflake/ml/feature_store/feature_view.py +40 -23
- snowflake/ml/fileset/embedded_stage_fs.py +146 -0
- snowflake/ml/fileset/sfcfs.py +56 -54
- snowflake/ml/fileset/snowfs.py +159 -0
- snowflake/ml/fileset/stage_fs.py +49 -17
- snowflake/ml/model/__init__.py +2 -2
- snowflake/ml/model/_api.py +16 -1
- snowflake/ml/model/_client/model/model_impl.py +27 -0
- snowflake/ml/model/_client/model/model_version_impl.py +137 -50
- snowflake/ml/model/_client/ops/model_ops.py +159 -40
- snowflake/ml/model/_client/sql/model.py +25 -2
- snowflake/ml/model/_client/sql/model_version.py +131 -2
- snowflake/ml/model/_deploy_client/image_builds/server_image_builder.py +5 -1
- snowflake/ml/model/_deploy_client/image_builds/templates/dockerfile_template +1 -0
- snowflake/ml/model/_deploy_client/snowservice/deploy.py +2 -0
- snowflake/ml/model/_deploy_client/utils/constants.py +0 -5
- snowflake/ml/model/_deploy_client/utils/snowservice_client.py +21 -50
- snowflake/ml/model/_model_composer/model_composer.py +22 -1
- snowflake/ml/model/_model_composer/model_manifest/model_manifest.py +38 -51
- snowflake/ml/model/_model_composer/model_manifest/model_manifest_schema.py +19 -1
- snowflake/ml/model/_model_composer/model_method/model_method.py +6 -10
- snowflake/ml/model/_packager/model_env/model_env.py +41 -0
- snowflake/ml/model/_packager/model_handlers/catboost.py +206 -0
- snowflake/ml/model/_packager/model_handlers/lightgbm.py +218 -0
- snowflake/ml/model/_packager/model_handlers/sklearn.py +3 -0
- snowflake/ml/model/_packager/model_meta/_core_requirements.py +1 -1
- snowflake/ml/model/_packager/model_meta/model_meta.py +37 -11
- snowflake/ml/model/_packager/model_meta/model_meta_schema.py +20 -1
- snowflake/ml/model/_packager/model_meta_migrator/migrator_plans.py +3 -1
- snowflake/ml/model/_packager/model_packager.py +2 -5
- snowflake/ml/model/{_model_composer/model_runtime/_runtime_requirements.py → _packager/model_runtime/_snowml_inference_alternative_requirements.py} +1 -1
- snowflake/ml/model/_packager/model_runtime/model_runtime.py +137 -0
- snowflake/ml/model/type_hints.py +21 -2
- snowflake/ml/modeling/_internal/estimator_utils.py +16 -11
- snowflake/ml/modeling/_internal/local_implementations/pandas_handlers.py +4 -1
- snowflake/ml/modeling/_internal/local_implementations/pandas_trainer.py +55 -3
- snowflake/ml/modeling/_internal/ml_runtime_implementations/ml_runtime_handlers.py +34 -18
- snowflake/ml/modeling/_internal/model_trainer.py +7 -0
- snowflake/ml/modeling/_internal/model_trainer_builder.py +42 -9
- snowflake/ml/modeling/_internal/snowpark_implementations/distributed_hpo_trainer.py +13 -14
- snowflake/ml/modeling/_internal/snowpark_implementations/snowpark_handlers.py +29 -7
- snowflake/ml/modeling/_internal/snowpark_implementations/snowpark_trainer.py +261 -16
- snowflake/ml/modeling/calibration/calibrated_classifier_cv.py +246 -175
- snowflake/ml/modeling/cluster/affinity_propagation.py +246 -175
- snowflake/ml/modeling/cluster/agglomerative_clustering.py +246 -175
- snowflake/ml/modeling/cluster/birch.py +248 -175
- snowflake/ml/modeling/cluster/bisecting_k_means.py +248 -175
- snowflake/ml/modeling/cluster/dbscan.py +246 -175
- snowflake/ml/modeling/cluster/feature_agglomeration.py +248 -175
- snowflake/ml/modeling/cluster/k_means.py +248 -175
- snowflake/ml/modeling/cluster/mean_shift.py +246 -175
- snowflake/ml/modeling/cluster/mini_batch_k_means.py +248 -175
- snowflake/ml/modeling/cluster/optics.py +246 -175
- snowflake/ml/modeling/cluster/spectral_biclustering.py +246 -175
- snowflake/ml/modeling/cluster/spectral_clustering.py +246 -175
- snowflake/ml/modeling/cluster/spectral_coclustering.py +246 -175
- snowflake/ml/modeling/compose/column_transformer.py +248 -175
- snowflake/ml/modeling/compose/transformed_target_regressor.py +246 -175
- snowflake/ml/modeling/covariance/elliptic_envelope.py +246 -175
- snowflake/ml/modeling/covariance/empirical_covariance.py +246 -175
- snowflake/ml/modeling/covariance/graphical_lasso.py +246 -175
- snowflake/ml/modeling/covariance/graphical_lasso_cv.py +246 -175
- snowflake/ml/modeling/covariance/ledoit_wolf.py +246 -175
- snowflake/ml/modeling/covariance/min_cov_det.py +246 -175
- snowflake/ml/modeling/covariance/oas.py +246 -175
- snowflake/ml/modeling/covariance/shrunk_covariance.py +246 -175
- snowflake/ml/modeling/decomposition/dictionary_learning.py +248 -175
- snowflake/ml/modeling/decomposition/factor_analysis.py +248 -175
- snowflake/ml/modeling/decomposition/fast_ica.py +248 -175
- snowflake/ml/modeling/decomposition/incremental_pca.py +248 -175
- snowflake/ml/modeling/decomposition/kernel_pca.py +248 -175
- snowflake/ml/modeling/decomposition/mini_batch_dictionary_learning.py +248 -175
- snowflake/ml/modeling/decomposition/mini_batch_sparse_pca.py +248 -175
- snowflake/ml/modeling/decomposition/pca.py +248 -175
- snowflake/ml/modeling/decomposition/sparse_pca.py +248 -175
- snowflake/ml/modeling/decomposition/truncated_svd.py +248 -175
- snowflake/ml/modeling/discriminant_analysis/linear_discriminant_analysis.py +248 -175
- snowflake/ml/modeling/discriminant_analysis/quadratic_discriminant_analysis.py +246 -175
- snowflake/ml/modeling/ensemble/ada_boost_classifier.py +246 -175
- snowflake/ml/modeling/ensemble/ada_boost_regressor.py +246 -175
- snowflake/ml/modeling/ensemble/bagging_classifier.py +246 -175
- snowflake/ml/modeling/ensemble/bagging_regressor.py +246 -175
- snowflake/ml/modeling/ensemble/extra_trees_classifier.py +246 -175
- snowflake/ml/modeling/ensemble/extra_trees_regressor.py +246 -175
- snowflake/ml/modeling/ensemble/gradient_boosting_classifier.py +246 -175
- snowflake/ml/modeling/ensemble/gradient_boosting_regressor.py +246 -175
- snowflake/ml/modeling/ensemble/hist_gradient_boosting_classifier.py +246 -175
- snowflake/ml/modeling/ensemble/hist_gradient_boosting_regressor.py +246 -175
- snowflake/ml/modeling/ensemble/isolation_forest.py +246 -175
- snowflake/ml/modeling/ensemble/random_forest_classifier.py +246 -175
- snowflake/ml/modeling/ensemble/random_forest_regressor.py +246 -175
- snowflake/ml/modeling/ensemble/stacking_regressor.py +248 -175
- snowflake/ml/modeling/ensemble/voting_classifier.py +248 -175
- snowflake/ml/modeling/ensemble/voting_regressor.py +248 -175
- snowflake/ml/modeling/feature_selection/generic_univariate_select.py +248 -175
- snowflake/ml/modeling/feature_selection/select_fdr.py +248 -175
- snowflake/ml/modeling/feature_selection/select_fpr.py +248 -175
- snowflake/ml/modeling/feature_selection/select_fwe.py +248 -175
- snowflake/ml/modeling/feature_selection/select_k_best.py +248 -175
- snowflake/ml/modeling/feature_selection/select_percentile.py +248 -175
- snowflake/ml/modeling/feature_selection/sequential_feature_selector.py +248 -175
- snowflake/ml/modeling/feature_selection/variance_threshold.py +248 -175
- snowflake/ml/modeling/framework/_utils.py +8 -1
- snowflake/ml/modeling/framework/base.py +72 -37
- snowflake/ml/modeling/gaussian_process/gaussian_process_classifier.py +246 -175
- snowflake/ml/modeling/gaussian_process/gaussian_process_regressor.py +246 -175
- snowflake/ml/modeling/impute/iterative_imputer.py +248 -175
- snowflake/ml/modeling/impute/knn_imputer.py +248 -175
- snowflake/ml/modeling/impute/missing_indicator.py +248 -175
- snowflake/ml/modeling/kernel_approximation/additive_chi2_sampler.py +248 -175
- snowflake/ml/modeling/kernel_approximation/nystroem.py +248 -175
- snowflake/ml/modeling/kernel_approximation/polynomial_count_sketch.py +248 -175
- snowflake/ml/modeling/kernel_approximation/rbf_sampler.py +248 -175
- snowflake/ml/modeling/kernel_approximation/skewed_chi2_sampler.py +248 -175
- snowflake/ml/modeling/kernel_ridge/kernel_ridge.py +246 -175
- snowflake/ml/modeling/lightgbm/lgbm_classifier.py +246 -175
- snowflake/ml/modeling/lightgbm/lgbm_regressor.py +246 -175
- snowflake/ml/modeling/linear_model/ard_regression.py +246 -175
- snowflake/ml/modeling/linear_model/bayesian_ridge.py +246 -175
- snowflake/ml/modeling/linear_model/elastic_net.py +246 -175
- snowflake/ml/modeling/linear_model/elastic_net_cv.py +246 -175
- snowflake/ml/modeling/linear_model/gamma_regressor.py +246 -175
- snowflake/ml/modeling/linear_model/huber_regressor.py +246 -175
- snowflake/ml/modeling/linear_model/lars.py +246 -175
- snowflake/ml/modeling/linear_model/lars_cv.py +246 -175
- snowflake/ml/modeling/linear_model/lasso.py +246 -175
- snowflake/ml/modeling/linear_model/lasso_cv.py +246 -175
- snowflake/ml/modeling/linear_model/lasso_lars.py +246 -175
- snowflake/ml/modeling/linear_model/lasso_lars_cv.py +246 -175
- snowflake/ml/modeling/linear_model/lasso_lars_ic.py +246 -175
- snowflake/ml/modeling/linear_model/linear_regression.py +246 -175
- snowflake/ml/modeling/linear_model/logistic_regression.py +246 -175
- snowflake/ml/modeling/linear_model/logistic_regression_cv.py +246 -175
- snowflake/ml/modeling/linear_model/multi_task_elastic_net.py +246 -175
- snowflake/ml/modeling/linear_model/multi_task_elastic_net_cv.py +246 -175
- snowflake/ml/modeling/linear_model/multi_task_lasso.py +246 -175
- snowflake/ml/modeling/linear_model/multi_task_lasso_cv.py +246 -175
- snowflake/ml/modeling/linear_model/orthogonal_matching_pursuit.py +246 -175
- snowflake/ml/modeling/linear_model/passive_aggressive_classifier.py +246 -175
- snowflake/ml/modeling/linear_model/passive_aggressive_regressor.py +246 -175
- snowflake/ml/modeling/linear_model/perceptron.py +246 -175
- snowflake/ml/modeling/linear_model/poisson_regressor.py +246 -175
- snowflake/ml/modeling/linear_model/ransac_regressor.py +246 -175
- snowflake/ml/modeling/linear_model/ridge.py +246 -175
- snowflake/ml/modeling/linear_model/ridge_classifier.py +246 -175
- snowflake/ml/modeling/linear_model/ridge_classifier_cv.py +246 -175
- snowflake/ml/modeling/linear_model/ridge_cv.py +246 -175
- snowflake/ml/modeling/linear_model/sgd_classifier.py +246 -175
- snowflake/ml/modeling/linear_model/sgd_one_class_svm.py +246 -175
- snowflake/ml/modeling/linear_model/sgd_regressor.py +246 -175
- snowflake/ml/modeling/linear_model/theil_sen_regressor.py +246 -175
- snowflake/ml/modeling/linear_model/tweedie_regressor.py +246 -175
- snowflake/ml/modeling/manifold/isomap.py +248 -175
- snowflake/ml/modeling/manifold/mds.py +248 -175
- snowflake/ml/modeling/manifold/spectral_embedding.py +248 -175
- snowflake/ml/modeling/manifold/tsne.py +248 -175
- snowflake/ml/modeling/mixture/bayesian_gaussian_mixture.py +246 -175
- snowflake/ml/modeling/mixture/gaussian_mixture.py +246 -175
- snowflake/ml/modeling/model_selection/grid_search_cv.py +63 -41
- snowflake/ml/modeling/model_selection/randomized_search_cv.py +80 -38
- snowflake/ml/modeling/multiclass/one_vs_one_classifier.py +246 -175
- snowflake/ml/modeling/multiclass/one_vs_rest_classifier.py +246 -175
- snowflake/ml/modeling/multiclass/output_code_classifier.py +246 -175
- snowflake/ml/modeling/naive_bayes/bernoulli_nb.py +246 -175
- snowflake/ml/modeling/naive_bayes/categorical_nb.py +246 -175
- snowflake/ml/modeling/naive_bayes/complement_nb.py +246 -175
- snowflake/ml/modeling/naive_bayes/gaussian_nb.py +246 -175
- snowflake/ml/modeling/naive_bayes/multinomial_nb.py +246 -175
- snowflake/ml/modeling/neighbors/k_neighbors_classifier.py +246 -175
- snowflake/ml/modeling/neighbors/k_neighbors_regressor.py +246 -175
- snowflake/ml/modeling/neighbors/kernel_density.py +246 -175
- snowflake/ml/modeling/neighbors/local_outlier_factor.py +246 -175
- snowflake/ml/modeling/neighbors/nearest_centroid.py +246 -175
- snowflake/ml/modeling/neighbors/nearest_neighbors.py +246 -175
- snowflake/ml/modeling/neighbors/neighborhood_components_analysis.py +248 -175
- snowflake/ml/modeling/neighbors/radius_neighbors_classifier.py +246 -175
- snowflake/ml/modeling/neighbors/radius_neighbors_regressor.py +246 -175
- snowflake/ml/modeling/neural_network/bernoulli_rbm.py +248 -175
- snowflake/ml/modeling/neural_network/mlp_classifier.py +246 -175
- snowflake/ml/modeling/neural_network/mlp_regressor.py +246 -175
- snowflake/ml/modeling/pipeline/pipeline.py +517 -35
- snowflake/ml/modeling/preprocessing/binarizer.py +1 -5
- snowflake/ml/modeling/preprocessing/k_bins_discretizer.py +1 -5
- snowflake/ml/modeling/preprocessing/label_encoder.py +1 -5
- snowflake/ml/modeling/preprocessing/max_abs_scaler.py +1 -5
- snowflake/ml/modeling/preprocessing/min_max_scaler.py +10 -12
- snowflake/ml/modeling/preprocessing/normalizer.py +1 -5
- snowflake/ml/modeling/preprocessing/one_hot_encoder.py +13 -5
- snowflake/ml/modeling/preprocessing/ordinal_encoder.py +1 -5
- snowflake/ml/modeling/preprocessing/polynomial_features.py +248 -175
- snowflake/ml/modeling/preprocessing/robust_scaler.py +1 -5
- snowflake/ml/modeling/preprocessing/standard_scaler.py +11 -11
- snowflake/ml/modeling/semi_supervised/label_propagation.py +246 -175
- snowflake/ml/modeling/semi_supervised/label_spreading.py +246 -175
- snowflake/ml/modeling/svm/linear_svc.py +246 -175
- snowflake/ml/modeling/svm/linear_svr.py +246 -175
- snowflake/ml/modeling/svm/nu_svc.py +246 -175
- snowflake/ml/modeling/svm/nu_svr.py +246 -175
- snowflake/ml/modeling/svm/svc.py +246 -175
- snowflake/ml/modeling/svm/svr.py +246 -175
- snowflake/ml/modeling/tree/decision_tree_classifier.py +246 -175
- snowflake/ml/modeling/tree/decision_tree_regressor.py +246 -175
- snowflake/ml/modeling/tree/extra_tree_classifier.py +246 -175
- snowflake/ml/modeling/tree/extra_tree_regressor.py +246 -175
- snowflake/ml/modeling/xgboost/xgb_classifier.py +246 -175
- snowflake/ml/modeling/xgboost/xgb_regressor.py +246 -175
- snowflake/ml/modeling/xgboost/xgbrf_classifier.py +246 -175
- snowflake/ml/modeling/xgboost/xgbrf_regressor.py +246 -175
- snowflake/ml/registry/model_registry.py +3 -149
- snowflake/ml/registry/registry.py +1 -1
- snowflake/ml/version.py +1 -1
- {snowflake_ml_python-1.4.0.dist-info → snowflake_ml_python-1.5.0.dist-info}/METADATA +129 -57
- snowflake_ml_python-1.5.0.dist-info/RECORD +380 -0
- snowflake/ml/model/_model_composer/model_runtime/model_runtime.py +0 -97
- snowflake/ml/registry/_artifact_manager.py +0 -156
- snowflake/ml/registry/artifact.py +0 -46
- snowflake_ml_python-1.4.0.dist-info/RECORD +0 -370
- {snowflake_ml_python-1.4.0.dist-info → snowflake_ml_python-1.5.0.dist-info}/LICENSE.txt +0 -0
- {snowflake_ml_python-1.4.0.dist-info → snowflake_ml_python-1.5.0.dist-info}/WHEEL +0 -0
- {snowflake_ml_python-1.4.0.dist-info → snowflake_ml_python-1.5.0.dist-info}/top_level.txt +0 -0
snowflake/ml/fileset/stage_fs.py
CHANGED
@@ -8,7 +8,7 @@ import fsspec
|
|
8
8
|
from fsspec.implementations import http as httpfs
|
9
9
|
|
10
10
|
from snowflake import snowpark
|
11
|
-
from snowflake.connector import connection
|
11
|
+
from snowflake.connector import connection, errorcode
|
12
12
|
from snowflake.ml._internal import telemetry
|
13
13
|
from snowflake.ml._internal.exceptions import (
|
14
14
|
error_codes,
|
@@ -17,6 +17,7 @@ from snowflake.ml._internal.exceptions import (
|
|
17
17
|
fileset_errors,
|
18
18
|
)
|
19
19
|
from snowflake.snowpark import exceptions as snowpark_exceptions
|
20
|
+
from snowflake.snowpark._internal import utils as snowpark_utils
|
20
21
|
|
21
22
|
# The default length of how long a presigned url stays active in seconds.
|
22
23
|
# Presigned url here is used to fetch file objects from Snowflake when SFStageFileSystem.open() is called.
|
@@ -79,7 +80,9 @@ class SFStageFileSystem(fsspec.AbstractFileSystem):
|
|
79
80
|
# None -> Try pre-signed URL access, fall back to file download
|
80
81
|
# True -> Use file download path without trying pre-signed URL access
|
81
82
|
# False -> Use pre-signed URL access, skip download fallback on failure
|
82
|
-
_USE_FALLBACK_FILE_ACCESS =
|
83
|
+
_USE_FALLBACK_FILE_ACCESS = (
|
84
|
+
True if snowpark_utils.is_in_stored_procedure() else None # type: ignore[no-untyped-call]
|
85
|
+
)
|
83
86
|
|
84
87
|
def __init__(
|
85
88
|
self,
|
@@ -141,7 +144,6 @@ class SFStageFileSystem(fsspec.AbstractFileSystem):
|
|
141
144
|
project=_PROJECT,
|
142
145
|
func_params_to_log=["detail"],
|
143
146
|
)
|
144
|
-
@snowpark._internal.utils.private_preview(version="0.2.0")
|
145
147
|
def ls(self, path: str, detail: bool = False) -> Union[List[str], List[Dict[str, Any]]]:
|
146
148
|
"""Override fsspec `ls` method. List single "directory" with or without details.
|
147
149
|
|
@@ -164,7 +166,8 @@ class SFStageFileSystem(fsspec.AbstractFileSystem):
|
|
164
166
|
"""
|
165
167
|
try:
|
166
168
|
loc = self.stage_name
|
167
|
-
|
169
|
+
path = path.lstrip("/")
|
170
|
+
objects = self._session.sql(f"LIST '{loc}/{path}'").collect()
|
168
171
|
except snowpark_exceptions.SnowparkClientException as e:
|
169
172
|
if e.message.startswith(fileset_errors.ERRNO_DOMAIN_NOT_EXIST):
|
170
173
|
raise snowml_exceptions.SnowflakeMLException(
|
@@ -187,7 +190,6 @@ class SFStageFileSystem(fsspec.AbstractFileSystem):
|
|
187
190
|
@telemetry.send_api_usage_telemetry(
|
188
191
|
project=_PROJECT,
|
189
192
|
)
|
190
|
-
@snowpark._internal.utils.private_preview(version="0.2.0")
|
191
193
|
def optimize_read(self, files: Optional[List[str]] = None) -> None:
|
192
194
|
"""Prefetch and cache the presigned urls for all the given files to speed up the read performance.
|
193
195
|
|
@@ -214,7 +216,6 @@ class SFStageFileSystem(fsspec.AbstractFileSystem):
|
|
214
216
|
@telemetry.send_api_usage_telemetry(
|
215
217
|
project=_PROJECT,
|
216
218
|
)
|
217
|
-
@snowpark._internal.utils.private_preview(version="0.2.0")
|
218
219
|
def _open(self, path: str, mode: str = "rb", **kwargs: Any) -> fsspec.spec.AbstractBufferedFile:
|
219
220
|
"""Override fsspec `_open` method. Open a file for reading.
|
220
221
|
|
@@ -234,7 +235,7 @@ class SFStageFileSystem(fsspec.AbstractFileSystem):
|
|
234
235
|
"""
|
235
236
|
path = path.lstrip("/")
|
236
237
|
if self._USE_FALLBACK_FILE_ACCESS:
|
237
|
-
return self.
|
238
|
+
return self._open_with_snowpark(path)
|
238
239
|
cached_presigned_url = self._url_cache.get(path, None)
|
239
240
|
if not cached_presigned_url:
|
240
241
|
res = self._fetch_presigned_urls([path])
|
@@ -252,19 +253,42 @@ class SFStageFileSystem(fsspec.AbstractFileSystem):
|
|
252
253
|
except FileNotFoundError:
|
253
254
|
# Enable fallback if _USE_FALLBACK_FILE_ACCESS is True or None; set to False to disable
|
254
255
|
if self._USE_FALLBACK_FILE_ACCESS != False: # noqa: E712
|
255
|
-
|
256
|
-
|
257
|
-
|
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
|
256
|
+
content = self._open_with_snowpark(path)
|
257
|
+
self._USE_FALLBACK_FILE_ACCESS = True
|
258
|
+
return content
|
263
259
|
raise snowml_exceptions.SnowflakeMLException(
|
264
260
|
error_code=error_codes.SNOWML_NOT_FOUND,
|
265
261
|
original_exception=fileset_errors.StageFileNotFoundError(f"Stage file {path} doesn't exist."),
|
266
262
|
)
|
267
263
|
|
264
|
+
def _open_with_snowpark(self, path: str, **kwargs: Dict[str, Any]) -> fsspec.spec.AbstractBufferedFile:
|
265
|
+
"""Open the a file for reading using snowflake.snowpark.file_operation
|
266
|
+
|
267
|
+
Args:
|
268
|
+
path: Path of file in Snowflake stage.
|
269
|
+
**kwargs: Extra options to pass to snowflake.snowpark.file_operation.get_stream
|
270
|
+
|
271
|
+
Returns:
|
272
|
+
A fsspec file-like object.
|
273
|
+
|
274
|
+
Raises:
|
275
|
+
SnowflakeMLException: An error occurred when the given path points to a file that cannot be found.
|
276
|
+
SnowflakeMLException: An unknown Snowpark error occurred during file read.
|
277
|
+
"""
|
278
|
+
try:
|
279
|
+
return self._session.file.get_stream(f"{self.stage_name}/{path}", **kwargs)
|
280
|
+
except snowpark_exceptions.SnowparkSQLException as e:
|
281
|
+
if _match_error_code(e, errorcode.ER_FILE_NOT_EXISTS):
|
282
|
+
raise snowml_exceptions.SnowflakeMLException(
|
283
|
+
error_code=error_codes.SNOWML_NOT_FOUND,
|
284
|
+
original_exception=fileset_errors.StageFileNotFoundError(f"Stage file {path} doesn't exist."),
|
285
|
+
)
|
286
|
+
else:
|
287
|
+
raise snowml_exceptions.SnowflakeMLException(
|
288
|
+
error_code=error_codes.INTERNAL_SNOWPARK_ERROR,
|
289
|
+
original_exception=e,
|
290
|
+
)
|
291
|
+
|
268
292
|
def _parse_list_result(
|
269
293
|
self, list_result: List[Tuple[str, int, str, str]], search_path: str
|
270
294
|
) -> List[Dict[str, Any]]:
|
@@ -352,7 +376,7 @@ class SFStageFileSystem(fsspec.AbstractFileSystem):
|
|
352
376
|
file_df = self._session.create_dataframe(files).to_df("name")
|
353
377
|
try:
|
354
378
|
presigned_urls: List[Tuple[str, str]] = file_df.select_expr(
|
355
|
-
f"name, get_presigned_url({self.stage_name}, name, {url_lifetime}) as url"
|
379
|
+
f"name, get_presigned_url('{self.stage_name}', name, {url_lifetime}) as url"
|
356
380
|
).collect(
|
357
381
|
statement_params=telemetry.get_function_usage_statement_params(
|
358
382
|
project=_PROJECT,
|
@@ -363,7 +387,9 @@ class SFStageFileSystem(fsspec.AbstractFileSystem):
|
|
363
387
|
),
|
364
388
|
)
|
365
389
|
except snowpark_exceptions.SnowparkClientException as e:
|
366
|
-
if e.message.startswith(fileset_errors.
|
390
|
+
if e.message.startswith(fileset_errors.ERRNO_DOMAIN_NOT_EXIST) or e.message.startswith(
|
391
|
+
fileset_errors.ERRNO_STAGE_NOT_EXIST
|
392
|
+
):
|
367
393
|
raise snowml_exceptions.SnowflakeMLException(
|
368
394
|
error_code=error_codes.SNOWML_NOT_FOUND,
|
369
395
|
original_exception=fileset_errors.StageNotFoundError(
|
@@ -376,3 +402,9 @@ class SFStageFileSystem(fsspec.AbstractFileSystem):
|
|
376
402
|
original_exception=fileset_errors.FileSetError(str(e)),
|
377
403
|
)
|
378
404
|
return presigned_urls
|
405
|
+
|
406
|
+
|
407
|
+
def _match_error_code(ex: snowpark_exceptions.SnowparkSQLException, error_code: int) -> bool:
|
408
|
+
# Snowpark writes error code to message instead of populating e.error_code
|
409
|
+
error_code_str = str(error_code)
|
410
|
+
return ex.error_code == error_code_str or error_code_str in ex.message
|
snowflake/ml/model/__init__.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
from snowflake.ml.model._client.model.model_impl import Model
|
2
|
-
from snowflake.ml.model._client.model.model_version_impl import ModelVersion
|
2
|
+
from snowflake.ml.model._client.model.model_version_impl import ExportMode, ModelVersion
|
3
3
|
from snowflake.ml.model.models.huggingface_pipeline import HuggingFacePipelineModel
|
4
4
|
from snowflake.ml.model.models.llm import LLM, LLMOptions
|
5
5
|
|
6
|
-
__all__ = ["Model", "ModelVersion", "HuggingFacePipelineModel", "LLM", "LLMOptions"]
|
6
|
+
__all__ = ["Model", "ModelVersion", "ExportMode", "HuggingFacePipelineModel", "LLM", "LLMOptions"]
|
snowflake/ml/model/_api.py
CHANGED
@@ -2,6 +2,7 @@ from types import ModuleType
|
|
2
2
|
from typing import Any, Dict, List, Literal, Optional, Union, cast, overload
|
3
3
|
|
4
4
|
import pandas as pd
|
5
|
+
from typing_extensions import deprecated
|
5
6
|
|
6
7
|
from snowflake.ml._internal.exceptions import (
|
7
8
|
error_codes,
|
@@ -23,6 +24,7 @@ from snowflake.ml.model._signatures import snowpark_handler
|
|
23
24
|
from snowflake.snowpark import DataFrame as SnowparkDataFrame, Session, functions as F
|
24
25
|
|
25
26
|
|
27
|
+
@deprecated("Only used by PrPr model registry.")
|
26
28
|
@overload
|
27
29
|
def save_model(
|
28
30
|
*,
|
@@ -61,6 +63,7 @@ def save_model(
|
|
61
63
|
...
|
62
64
|
|
63
65
|
|
66
|
+
@deprecated("Only used by PrPr model registry.")
|
64
67
|
@overload
|
65
68
|
def save_model(
|
66
69
|
*,
|
@@ -101,6 +104,7 @@ def save_model(
|
|
101
104
|
...
|
102
105
|
|
103
106
|
|
107
|
+
@deprecated("Only used by PrPr model registry.")
|
104
108
|
@overload
|
105
109
|
def save_model(
|
106
110
|
*,
|
@@ -142,6 +146,7 @@ def save_model(
|
|
142
146
|
...
|
143
147
|
|
144
148
|
|
149
|
+
@deprecated("Only used by PrPr model registry.")
|
145
150
|
def save_model(
|
146
151
|
*,
|
147
152
|
name: str,
|
@@ -208,6 +213,7 @@ def save_model(
|
|
208
213
|
return m
|
209
214
|
|
210
215
|
|
216
|
+
@deprecated("Only used by PrPr model registry.")
|
211
217
|
@overload
|
212
218
|
def load_model(*, session: Session, stage_path: str) -> model_composer.ModelComposer:
|
213
219
|
"""Load the model into memory from a zip file in the stage.
|
@@ -219,6 +225,7 @@ def load_model(*, session: Session, stage_path: str) -> model_composer.ModelComp
|
|
219
225
|
...
|
220
226
|
|
221
227
|
|
228
|
+
@deprecated("Only used by PrPr model registry.")
|
222
229
|
@overload
|
223
230
|
def load_model(*, session: Session, stage_path: str, meta_only: Literal[False]) -> model_composer.ModelComposer:
|
224
231
|
"""Load the model into memory from a zip file in the stage.
|
@@ -231,6 +238,7 @@ def load_model(*, session: Session, stage_path: str, meta_only: Literal[False])
|
|
231
238
|
...
|
232
239
|
|
233
240
|
|
241
|
+
@deprecated("Only used by PrPr model registry.")
|
234
242
|
@overload
|
235
243
|
def load_model(*, session: Session, stage_path: str, meta_only: Literal[True]) -> model_composer.ModelComposer:
|
236
244
|
"""Load the model into memory from a zip file in the stage with metadata only.
|
@@ -243,6 +251,7 @@ def load_model(*, session: Session, stage_path: str, meta_only: Literal[True]) -
|
|
243
251
|
...
|
244
252
|
|
245
253
|
|
254
|
+
@deprecated("Only used by PrPr model registry.")
|
246
255
|
def load_model(
|
247
256
|
*,
|
248
257
|
session: Session,
|
@@ -261,10 +270,11 @@ def load_model(
|
|
261
270
|
Loaded model.
|
262
271
|
"""
|
263
272
|
m = model_composer.ModelComposer(session=session, stage_path=stage_path)
|
264
|
-
m.
|
273
|
+
m.legacy_load(meta_only=meta_only)
|
265
274
|
return m
|
266
275
|
|
267
276
|
|
277
|
+
@deprecated("Only used by PrPr model registry.")
|
268
278
|
@overload
|
269
279
|
def deploy(
|
270
280
|
session: Session,
|
@@ -290,6 +300,7 @@ def deploy(
|
|
290
300
|
...
|
291
301
|
|
292
302
|
|
303
|
+
@deprecated("Only used by PrPr model registry.")
|
293
304
|
@overload
|
294
305
|
def deploy(
|
295
306
|
session: Session,
|
@@ -319,6 +330,7 @@ def deploy(
|
|
319
330
|
...
|
320
331
|
|
321
332
|
|
333
|
+
@deprecated("Only used by PrPr model registry.")
|
322
334
|
def deploy(
|
323
335
|
session: Session,
|
324
336
|
*,
|
@@ -423,6 +435,7 @@ def deploy(
|
|
423
435
|
return info
|
424
436
|
|
425
437
|
|
438
|
+
@deprecated("Only used by PrPr model registry.")
|
426
439
|
@overload
|
427
440
|
def predict(
|
428
441
|
session: Session,
|
@@ -443,6 +456,7 @@ def predict(
|
|
443
456
|
...
|
444
457
|
|
445
458
|
|
459
|
+
@deprecated("Only used by PrPr model registry.")
|
446
460
|
@overload
|
447
461
|
def predict(
|
448
462
|
session: Session,
|
@@ -462,6 +476,7 @@ def predict(
|
|
462
476
|
...
|
463
477
|
|
464
478
|
|
479
|
+
@deprecated("Only used by PrPr model registry.")
|
465
480
|
def predict(
|
466
481
|
session: Session,
|
467
482
|
*,
|
@@ -350,3 +350,30 @@ class Model:
|
|
350
350
|
tag_name=tag_name_id,
|
351
351
|
statement_params=statement_params,
|
352
352
|
)
|
353
|
+
|
354
|
+
@telemetry.send_api_usage_telemetry(
|
355
|
+
project=_TELEMETRY_PROJECT,
|
356
|
+
subproject=_TELEMETRY_SUBPROJECT,
|
357
|
+
)
|
358
|
+
def rename(self, model_name: str) -> None:
|
359
|
+
"""Rename a model. Can be used to move a model when a fully qualified name is provided.
|
360
|
+
|
361
|
+
Args:
|
362
|
+
model_name: The new model name.
|
363
|
+
"""
|
364
|
+
statement_params = telemetry.get_statement_params(
|
365
|
+
project=_TELEMETRY_PROJECT,
|
366
|
+
subproject=_TELEMETRY_SUBPROJECT,
|
367
|
+
)
|
368
|
+
db, schema, model, _ = identifier.parse_schema_level_object_identifier(model_name)
|
369
|
+
new_model_db = sql_identifier.SqlIdentifier(db) if db else None
|
370
|
+
new_model_schema = sql_identifier.SqlIdentifier(schema) if schema else None
|
371
|
+
new_model_id = sql_identifier.SqlIdentifier(model)
|
372
|
+
self._model_ops.rename(
|
373
|
+
model_name=self._model_name,
|
374
|
+
new_model_db=new_model_db,
|
375
|
+
new_model_schema=new_model_schema,
|
376
|
+
new_model_name=new_model_id,
|
377
|
+
statement_params=statement_params,
|
378
|
+
)
|
379
|
+
self._model_name = new_model_id
|
@@ -1,20 +1,29 @@
|
|
1
|
-
import
|
1
|
+
import enum
|
2
|
+
import pathlib
|
3
|
+
import tempfile
|
4
|
+
import warnings
|
2
5
|
from typing import Any, Callable, Dict, List, Optional, Union
|
3
6
|
|
4
7
|
import pandas as pd
|
5
8
|
|
6
|
-
from snowflake import connector
|
7
9
|
from snowflake.ml._internal import telemetry
|
8
10
|
from snowflake.ml._internal.utils import sql_identifier
|
9
|
-
from snowflake.ml.model import
|
11
|
+
from snowflake.ml.model import type_hints as model_types
|
10
12
|
from snowflake.ml.model._client.ops import metadata_ops, model_ops
|
13
|
+
from snowflake.ml.model._model_composer import model_composer
|
11
14
|
from snowflake.ml.model._model_composer.model_manifest import model_manifest_schema
|
15
|
+
from snowflake.ml.model._packager.model_handlers import snowmlmodel
|
12
16
|
from snowflake.snowpark import dataframe
|
13
17
|
|
14
18
|
_TELEMETRY_PROJECT = "MLOps"
|
15
19
|
_TELEMETRY_SUBPROJECT = "ModelManagement"
|
16
20
|
|
17
21
|
|
22
|
+
class ExportMode(enum.Enum):
|
23
|
+
MODEL = "model"
|
24
|
+
FULL = "full"
|
25
|
+
|
26
|
+
|
18
27
|
class ModelVersion:
|
19
28
|
"""Model Version Object representing a specific version of the model that could be run."""
|
20
29
|
|
@@ -207,61 +216,16 @@ class ModelVersion:
|
|
207
216
|
statement_params=statement_params,
|
208
217
|
)
|
209
218
|
|
210
|
-
|
211
|
-
def _legacy_show_functions(self) -> List[model_manifest_schema.ModelFunctionInfo]:
|
219
|
+
def _get_functions(self) -> List[model_manifest_schema.ModelFunctionInfo]:
|
212
220
|
statement_params = telemetry.get_statement_params(
|
213
221
|
project=_TELEMETRY_PROJECT,
|
214
222
|
subproject=_TELEMETRY_SUBPROJECT,
|
215
223
|
)
|
216
|
-
|
217
|
-
model_name=self._model_name,
|
218
|
-
version_name=self._version_name,
|
219
|
-
statement_params=statement_params,
|
220
|
-
)
|
221
|
-
model_meta = self._model_ops.get_model_version_native_packing_meta(
|
224
|
+
return self._model_ops.get_functions(
|
222
225
|
model_name=self._model_name,
|
223
226
|
version_name=self._version_name,
|
224
227
|
statement_params=statement_params,
|
225
228
|
)
|
226
|
-
return_functions_info: List[model_manifest_schema.ModelFunctionInfo] = []
|
227
|
-
for method in manifest["methods"]:
|
228
|
-
# Method's name is resolved so we need to use case_sensitive as True to get the user-facing identifier.
|
229
|
-
method_name = sql_identifier.SqlIdentifier(method["name"], case_sensitive=True).identifier()
|
230
|
-
# Method's handler is `functions.<target_method>.infer`
|
231
|
-
assert re.match(
|
232
|
-
r"^functions\.([^\d\W]\w*)\.infer$", method["handler"]
|
233
|
-
), f"Get unexpected handler name {method['handler']}"
|
234
|
-
target_method = method["handler"].split(".")[1]
|
235
|
-
signature_dict = model_meta["signatures"][target_method]
|
236
|
-
fi = model_manifest_schema.ModelFunctionInfo(
|
237
|
-
name=method_name,
|
238
|
-
target_method=target_method,
|
239
|
-
signature=model_signature.ModelSignature.from_dict(signature_dict),
|
240
|
-
)
|
241
|
-
return_functions_info.append(fi)
|
242
|
-
return return_functions_info
|
243
|
-
|
244
|
-
def _get_functions(self) -> List[model_manifest_schema.ModelFunctionInfo]:
|
245
|
-
statement_params = telemetry.get_statement_params(
|
246
|
-
project=_TELEMETRY_PROJECT,
|
247
|
-
subproject=_TELEMETRY_SUBPROJECT,
|
248
|
-
)
|
249
|
-
try:
|
250
|
-
client_data = self._model_ops.get_client_data_in_user_data(
|
251
|
-
model_name=self._model_name,
|
252
|
-
version_name=self._version_name,
|
253
|
-
statement_params=statement_params,
|
254
|
-
)
|
255
|
-
return [
|
256
|
-
model_manifest_schema.ModelFunctionInfo(
|
257
|
-
name=fi["name"],
|
258
|
-
target_method=fi["target_method"],
|
259
|
-
signature=model_signature.ModelSignature.from_dict(fi["signature"]),
|
260
|
-
)
|
261
|
-
for fi in client_data["functions"]
|
262
|
-
]
|
263
|
-
except (NotImplementedError, ValueError, connector.DataError):
|
264
|
-
return self._legacy_show_functions()
|
265
229
|
|
266
230
|
@telemetry.send_api_usage_telemetry(
|
267
231
|
project=_TELEMETRY_PROJECT,
|
@@ -288,6 +252,7 @@ class ModelVersion:
|
|
288
252
|
X: Union[pd.DataFrame, dataframe.DataFrame],
|
289
253
|
*,
|
290
254
|
function_name: Optional[str] = None,
|
255
|
+
partition_column: Optional[str] = None,
|
291
256
|
strict_input_validation: bool = False,
|
292
257
|
) -> Union[pd.DataFrame, dataframe.DataFrame]:
|
293
258
|
"""Invoke a method in a model version object.
|
@@ -296,12 +261,14 @@ class ModelVersion:
|
|
296
261
|
X: The input data, which could be a pandas DataFrame or Snowpark DataFrame.
|
297
262
|
function_name: The function name to run. It is the name used to call a function in SQL.
|
298
263
|
Defaults to None. It can only be None if there is only 1 method.
|
264
|
+
partition_column: The partition column name to partition by.
|
299
265
|
strict_input_validation: Enable stricter validation for the input data. This will result value range based
|
300
266
|
type validation to make sure your input data won't overflow when providing to the model.
|
301
267
|
|
302
268
|
Raises:
|
303
269
|
ValueError: When no method with the corresponding name is available.
|
304
270
|
ValueError: When there are more than 1 target methods available in the model but no function name specified.
|
271
|
+
ValueError: When the partition column is not a valid Snowflake identifier.
|
305
272
|
|
306
273
|
Returns:
|
307
274
|
The prediction data. It would be the same type dataframe as your input.
|
@@ -311,6 +278,10 @@ class ModelVersion:
|
|
311
278
|
subproject=_TELEMETRY_SUBPROJECT,
|
312
279
|
)
|
313
280
|
|
281
|
+
if partition_column is not None:
|
282
|
+
# Partition column must be a valid identifier
|
283
|
+
partition_column = sql_identifier.SqlIdentifier(partition_column)
|
284
|
+
|
314
285
|
functions: List[model_manifest_schema.ModelFunctionInfo] = self._functions
|
315
286
|
if function_name:
|
316
287
|
req_method_name = sql_identifier.SqlIdentifier(function_name).identifier()
|
@@ -335,10 +306,126 @@ class ModelVersion:
|
|
335
306
|
target_function_info = functions[0]
|
336
307
|
return self._model_ops.invoke_method(
|
337
308
|
method_name=sql_identifier.SqlIdentifier(target_function_info["name"]),
|
309
|
+
method_function_type=target_function_info["target_method_function_type"],
|
338
310
|
signature=target_function_info["signature"],
|
339
311
|
X=X,
|
340
312
|
model_name=self._model_name,
|
341
313
|
version_name=self._version_name,
|
342
314
|
strict_input_validation=strict_input_validation,
|
315
|
+
partition_column=partition_column,
|
316
|
+
statement_params=statement_params,
|
317
|
+
)
|
318
|
+
|
319
|
+
@telemetry.send_api_usage_telemetry(
|
320
|
+
project=_TELEMETRY_PROJECT, subproject=_TELEMETRY_SUBPROJECT, func_params_to_log=["export_mode"]
|
321
|
+
)
|
322
|
+
def export(self, target_path: str, *, export_mode: ExportMode = ExportMode.MODEL) -> None:
|
323
|
+
"""Export model files to a local directory.
|
324
|
+
|
325
|
+
Args:
|
326
|
+
target_path: Path to a local directory to export files to. A directory will be created if does not exist.
|
327
|
+
export_mode: The mode to export the model. Defaults to ExportMode.MODEL.
|
328
|
+
ExportMode.MODEL: All model files including environment to load the model and model weights.
|
329
|
+
ExportMode.FULL: Additional files to run the model in Warehouse, besides all files in MODEL mode,
|
330
|
+
|
331
|
+
Raises:
|
332
|
+
ValueError: Raised when the target path is a file or an non-empty folder.
|
333
|
+
"""
|
334
|
+
target_local_path = pathlib.Path(target_path)
|
335
|
+
if target_local_path.is_file() or any(target_local_path.iterdir()):
|
336
|
+
raise ValueError(f"Target path {target_local_path} is a file or an non-empty folder.")
|
337
|
+
|
338
|
+
target_local_path.mkdir(parents=False, exist_ok=True)
|
339
|
+
statement_params = telemetry.get_statement_params(
|
340
|
+
project=_TELEMETRY_PROJECT,
|
341
|
+
subproject=_TELEMETRY_SUBPROJECT,
|
342
|
+
)
|
343
|
+
self._model_ops.download_files(
|
344
|
+
model_name=self._model_name,
|
345
|
+
version_name=self._version_name,
|
346
|
+
target_path=target_local_path,
|
347
|
+
mode=export_mode.value,
|
343
348
|
statement_params=statement_params,
|
344
349
|
)
|
350
|
+
|
351
|
+
@telemetry.send_api_usage_telemetry(
|
352
|
+
project=_TELEMETRY_PROJECT, subproject=_TELEMETRY_SUBPROJECT, func_params_to_log=["force", "options"]
|
353
|
+
)
|
354
|
+
def load(
|
355
|
+
self,
|
356
|
+
*,
|
357
|
+
force: bool = False,
|
358
|
+
options: Optional[model_types.ModelLoadOption] = None,
|
359
|
+
) -> model_types.SupportedModelType:
|
360
|
+
"""Load the underlying original Python object back from a model.
|
361
|
+
This operation requires to have the exact the same environment as the one when logging the model, otherwise,
|
362
|
+
the model might be not functional or some other problems might occur.
|
363
|
+
|
364
|
+
Args:
|
365
|
+
force: Bypass the best-effort environment validation. Defaults to False.
|
366
|
+
options: Options to specify when loading the model, check `snowflake.ml.model.type_hints` for available
|
367
|
+
options. Defaults to None.
|
368
|
+
|
369
|
+
Raises:
|
370
|
+
ValueError: Raised when the best-effort environment validation fails.
|
371
|
+
|
372
|
+
Returns:
|
373
|
+
The original Python object loaded from the model object.
|
374
|
+
"""
|
375
|
+
statement_params = telemetry.get_statement_params(
|
376
|
+
project=_TELEMETRY_PROJECT,
|
377
|
+
subproject=_TELEMETRY_SUBPROJECT,
|
378
|
+
)
|
379
|
+
if not force:
|
380
|
+
with tempfile.TemporaryDirectory() as tmp_workspace_for_validation:
|
381
|
+
ws_path_for_validation = pathlib.Path(tmp_workspace_for_validation)
|
382
|
+
self._model_ops.download_files(
|
383
|
+
model_name=self._model_name,
|
384
|
+
version_name=self._version_name,
|
385
|
+
target_path=ws_path_for_validation,
|
386
|
+
mode="minimal",
|
387
|
+
statement_params=statement_params,
|
388
|
+
)
|
389
|
+
pk_for_validation = model_composer.ModelComposer.load(
|
390
|
+
ws_path_for_validation, meta_only=True, options=options
|
391
|
+
)
|
392
|
+
assert pk_for_validation.meta, (
|
393
|
+
"Unable to load model metadata for validation. "
|
394
|
+
f"model_name={self._model_name}, version_name={self._version_name}"
|
395
|
+
)
|
396
|
+
|
397
|
+
validation_errors = pk_for_validation.meta.env.validate_with_local_env(
|
398
|
+
check_snowpark_ml_version=(
|
399
|
+
pk_for_validation.meta.model_type == snowmlmodel.SnowMLModelHandler.HANDLER_TYPE
|
400
|
+
)
|
401
|
+
)
|
402
|
+
if validation_errors:
|
403
|
+
raise ValueError(
|
404
|
+
f"Unable to load this model due to following validation errors: {validation_errors}. "
|
405
|
+
"Make sure your local environment is the same as that when you logged the model, "
|
406
|
+
"or if you believe it should work, specify `force=True` to bypass this check."
|
407
|
+
)
|
408
|
+
|
409
|
+
warnings.warn(
|
410
|
+
"Loading model requires to have the exact the same environment as the one when "
|
411
|
+
"logging the model, otherwise, the model might be not functional or "
|
412
|
+
"some other problems might occur.",
|
413
|
+
category=RuntimeWarning,
|
414
|
+
stacklevel=2,
|
415
|
+
)
|
416
|
+
|
417
|
+
# We need the folder to be existed.
|
418
|
+
workspace = pathlib.Path(tempfile.mkdtemp())
|
419
|
+
self._model_ops.download_files(
|
420
|
+
model_name=self._model_name,
|
421
|
+
version_name=self._version_name,
|
422
|
+
target_path=workspace,
|
423
|
+
mode="model",
|
424
|
+
statement_params=statement_params,
|
425
|
+
)
|
426
|
+
pk = model_composer.ModelComposer.load(workspace, meta_only=False, options=options)
|
427
|
+
assert pk.model, (
|
428
|
+
"Unable to load model. "
|
429
|
+
f"model_name={self._model_name}, version_name={self._version_name}, metadata={pk.meta}"
|
430
|
+
)
|
431
|
+
return pk.model
|