snowflake-ml-python 1.6.1__py3-none-any.whl → 1.6.3__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 (284) hide show
  1. snowflake/cortex/__init__.py +4 -0
  2. snowflake/cortex/_classify_text.py +2 -2
  3. snowflake/cortex/_embed_text_1024.py +37 -0
  4. snowflake/cortex/_embed_text_768.py +37 -0
  5. snowflake/cortex/_extract_answer.py +2 -2
  6. snowflake/cortex/_sentiment.py +2 -2
  7. snowflake/cortex/_summarize.py +2 -2
  8. snowflake/cortex/_translate.py +2 -2
  9. snowflake/cortex/_util.py +4 -4
  10. snowflake/ml/_internal/env_utils.py +5 -5
  11. snowflake/ml/_internal/exceptions/error_codes.py +2 -0
  12. snowflake/ml/_internal/telemetry.py +142 -20
  13. snowflake/ml/_internal/utils/db_utils.py +50 -0
  14. snowflake/ml/_internal/utils/identifier.py +48 -11
  15. snowflake/ml/_internal/utils/service_logger.py +63 -0
  16. snowflake/ml/_internal/utils/snowflake_env.py +23 -13
  17. snowflake/ml/_internal/utils/sql_identifier.py +26 -2
  18. snowflake/ml/_internal/utils/table_manager.py +19 -1
  19. snowflake/ml/data/_internal/arrow_ingestor.py +1 -11
  20. snowflake/ml/data/data_connector.py +33 -7
  21. snowflake/ml/data/ingestor_utils.py +20 -10
  22. snowflake/ml/data/torch_utils.py +68 -0
  23. snowflake/ml/dataset/dataset.py +1 -3
  24. snowflake/ml/feature_store/access_manager.py +3 -3
  25. snowflake/ml/feature_store/feature_store.py +60 -19
  26. snowflake/ml/feature_store/feature_view.py +84 -30
  27. snowflake/ml/fileset/embedded_stage_fs.py +1 -1
  28. snowflake/ml/fileset/fileset.py +1 -1
  29. snowflake/ml/fileset/sfcfs.py +9 -3
  30. snowflake/ml/fileset/stage_fs.py +2 -1
  31. snowflake/ml/lineage/lineage_node.py +7 -2
  32. snowflake/ml/model/__init__.py +1 -2
  33. snowflake/ml/model/_client/model/model_version_impl.py +96 -12
  34. snowflake/ml/model/_client/ops/model_ops.py +124 -6
  35. snowflake/ml/model/_client/ops/service_ops.py +309 -9
  36. snowflake/ml/model/_client/service/model_deployment_spec.py +8 -5
  37. snowflake/ml/model/_client/service/model_deployment_spec_schema.py +2 -2
  38. snowflake/ml/model/_client/sql/_base.py +5 -0
  39. snowflake/ml/model/_client/sql/model.py +1 -0
  40. snowflake/ml/model/_client/sql/model_version.py +9 -5
  41. snowflake/ml/model/_client/sql/service.py +121 -20
  42. snowflake/ml/model/_model_composer/model_composer.py +11 -39
  43. snowflake/ml/model/_model_composer/model_manifest/model_manifest.py +31 -11
  44. snowflake/ml/model/_packager/model_env/model_env.py +4 -38
  45. snowflake/ml/model/_packager/model_handlers/_utils.py +134 -28
  46. snowflake/ml/model/_packager/model_handlers/catboost.py +31 -30
  47. snowflake/ml/model/_packager/model_handlers/huggingface_pipeline.py +26 -18
  48. snowflake/ml/model/_packager/model_handlers/lightgbm.py +31 -58
  49. snowflake/ml/model/_packager/model_handlers/mlflow.py +3 -5
  50. snowflake/ml/model/_packager/model_handlers/model_objective_utils.py +169 -0
  51. snowflake/ml/model/_packager/model_handlers/sentence_transformers.py +15 -8
  52. snowflake/ml/model/_packager/model_handlers/sklearn.py +56 -60
  53. snowflake/ml/model/_packager/model_handlers/snowmlmodel.py +141 -9
  54. snowflake/ml/model/_packager/model_handlers/torchscript.py +2 -2
  55. snowflake/ml/model/_packager/model_handlers/xgboost.py +63 -48
  56. snowflake/ml/model/_packager/model_meta/model_meta.py +16 -42
  57. snowflake/ml/model/_packager/model_meta/model_meta_schema.py +1 -14
  58. snowflake/ml/model/_packager/model_packager.py +14 -8
  59. snowflake/ml/model/_packager/model_runtime/model_runtime.py +11 -0
  60. snowflake/ml/model/_signatures/pytorch_handler.py +1 -1
  61. snowflake/ml/model/_signatures/snowpark_handler.py +3 -2
  62. snowflake/ml/model/_signatures/utils.py +9 -0
  63. snowflake/ml/model/type_hints.py +12 -145
  64. snowflake/ml/modeling/_internal/constants.py +1 -0
  65. snowflake/ml/modeling/_internal/local_implementations/pandas_handlers.py +5 -5
  66. snowflake/ml/modeling/_internal/local_implementations/pandas_trainer.py +9 -6
  67. snowflake/ml/modeling/_internal/model_specifications.py +2 -0
  68. snowflake/ml/modeling/_internal/model_trainer.py +1 -0
  69. snowflake/ml/modeling/_internal/snowpark_implementations/distributed_hpo_trainer.py +2 -4
  70. snowflake/ml/modeling/_internal/snowpark_implementations/snowpark_handlers.py +5 -5
  71. snowflake/ml/modeling/_internal/snowpark_implementations/snowpark_trainer.py +130 -166
  72. snowflake/ml/modeling/_internal/snowpark_implementations/xgboost_external_memory_trainer.py +0 -1
  73. snowflake/ml/modeling/calibration/calibrated_classifier_cv.py +61 -21
  74. snowflake/ml/modeling/cluster/affinity_propagation.py +61 -21
  75. snowflake/ml/modeling/cluster/agglomerative_clustering.py +61 -21
  76. snowflake/ml/modeling/cluster/birch.py +61 -21
  77. snowflake/ml/modeling/cluster/bisecting_k_means.py +61 -21
  78. snowflake/ml/modeling/cluster/dbscan.py +61 -21
  79. snowflake/ml/modeling/cluster/feature_agglomeration.py +61 -21
  80. snowflake/ml/modeling/cluster/k_means.py +61 -21
  81. snowflake/ml/modeling/cluster/mean_shift.py +61 -21
  82. snowflake/ml/modeling/cluster/mini_batch_k_means.py +61 -21
  83. snowflake/ml/modeling/cluster/optics.py +61 -21
  84. snowflake/ml/modeling/cluster/spectral_biclustering.py +61 -21
  85. snowflake/ml/modeling/cluster/spectral_clustering.py +61 -21
  86. snowflake/ml/modeling/cluster/spectral_coclustering.py +61 -21
  87. snowflake/ml/modeling/compose/column_transformer.py +61 -21
  88. snowflake/ml/modeling/compose/transformed_target_regressor.py +61 -21
  89. snowflake/ml/modeling/covariance/elliptic_envelope.py +61 -21
  90. snowflake/ml/modeling/covariance/empirical_covariance.py +61 -21
  91. snowflake/ml/modeling/covariance/graphical_lasso.py +61 -21
  92. snowflake/ml/modeling/covariance/graphical_lasso_cv.py +61 -21
  93. snowflake/ml/modeling/covariance/ledoit_wolf.py +61 -21
  94. snowflake/ml/modeling/covariance/min_cov_det.py +61 -21
  95. snowflake/ml/modeling/covariance/oas.py +61 -21
  96. snowflake/ml/modeling/covariance/shrunk_covariance.py +61 -21
  97. snowflake/ml/modeling/decomposition/dictionary_learning.py +61 -21
  98. snowflake/ml/modeling/decomposition/factor_analysis.py +61 -21
  99. snowflake/ml/modeling/decomposition/fast_ica.py +61 -21
  100. snowflake/ml/modeling/decomposition/incremental_pca.py +61 -21
  101. snowflake/ml/modeling/decomposition/kernel_pca.py +61 -21
  102. snowflake/ml/modeling/decomposition/mini_batch_dictionary_learning.py +61 -21
  103. snowflake/ml/modeling/decomposition/mini_batch_sparse_pca.py +61 -21
  104. snowflake/ml/modeling/decomposition/pca.py +61 -21
  105. snowflake/ml/modeling/decomposition/sparse_pca.py +61 -21
  106. snowflake/ml/modeling/decomposition/truncated_svd.py +61 -21
  107. snowflake/ml/modeling/discriminant_analysis/linear_discriminant_analysis.py +61 -21
  108. snowflake/ml/modeling/discriminant_analysis/quadratic_discriminant_analysis.py +61 -21
  109. snowflake/ml/modeling/ensemble/ada_boost_classifier.py +61 -21
  110. snowflake/ml/modeling/ensemble/ada_boost_regressor.py +61 -21
  111. snowflake/ml/modeling/ensemble/bagging_classifier.py +61 -21
  112. snowflake/ml/modeling/ensemble/bagging_regressor.py +61 -21
  113. snowflake/ml/modeling/ensemble/extra_trees_classifier.py +61 -21
  114. snowflake/ml/modeling/ensemble/extra_trees_regressor.py +61 -21
  115. snowflake/ml/modeling/ensemble/gradient_boosting_classifier.py +61 -21
  116. snowflake/ml/modeling/ensemble/gradient_boosting_regressor.py +61 -21
  117. snowflake/ml/modeling/ensemble/hist_gradient_boosting_classifier.py +61 -21
  118. snowflake/ml/modeling/ensemble/hist_gradient_boosting_regressor.py +61 -21
  119. snowflake/ml/modeling/ensemble/isolation_forest.py +61 -21
  120. snowflake/ml/modeling/ensemble/random_forest_classifier.py +61 -21
  121. snowflake/ml/modeling/ensemble/random_forest_regressor.py +61 -21
  122. snowflake/ml/modeling/ensemble/stacking_regressor.py +61 -21
  123. snowflake/ml/modeling/ensemble/voting_classifier.py +61 -21
  124. snowflake/ml/modeling/ensemble/voting_regressor.py +61 -21
  125. snowflake/ml/modeling/feature_selection/generic_univariate_select.py +61 -21
  126. snowflake/ml/modeling/feature_selection/select_fdr.py +61 -21
  127. snowflake/ml/modeling/feature_selection/select_fpr.py +61 -21
  128. snowflake/ml/modeling/feature_selection/select_fwe.py +61 -21
  129. snowflake/ml/modeling/feature_selection/select_k_best.py +61 -21
  130. snowflake/ml/modeling/feature_selection/select_percentile.py +61 -21
  131. snowflake/ml/modeling/feature_selection/sequential_feature_selector.py +61 -21
  132. snowflake/ml/modeling/feature_selection/variance_threshold.py +61 -21
  133. snowflake/ml/modeling/gaussian_process/gaussian_process_classifier.py +61 -21
  134. snowflake/ml/modeling/gaussian_process/gaussian_process_regressor.py +61 -21
  135. snowflake/ml/modeling/impute/iterative_imputer.py +61 -21
  136. snowflake/ml/modeling/impute/knn_imputer.py +61 -21
  137. snowflake/ml/modeling/impute/missing_indicator.py +61 -21
  138. snowflake/ml/modeling/kernel_approximation/additive_chi2_sampler.py +61 -21
  139. snowflake/ml/modeling/kernel_approximation/nystroem.py +61 -21
  140. snowflake/ml/modeling/kernel_approximation/polynomial_count_sketch.py +61 -21
  141. snowflake/ml/modeling/kernel_approximation/rbf_sampler.py +61 -21
  142. snowflake/ml/modeling/kernel_approximation/skewed_chi2_sampler.py +61 -21
  143. snowflake/ml/modeling/kernel_ridge/kernel_ridge.py +61 -21
  144. snowflake/ml/modeling/lightgbm/lgbm_classifier.py +61 -21
  145. snowflake/ml/modeling/lightgbm/lgbm_regressor.py +61 -21
  146. snowflake/ml/modeling/linear_model/ard_regression.py +61 -21
  147. snowflake/ml/modeling/linear_model/bayesian_ridge.py +61 -21
  148. snowflake/ml/modeling/linear_model/elastic_net.py +61 -21
  149. snowflake/ml/modeling/linear_model/elastic_net_cv.py +61 -21
  150. snowflake/ml/modeling/linear_model/gamma_regressor.py +61 -21
  151. snowflake/ml/modeling/linear_model/huber_regressor.py +61 -21
  152. snowflake/ml/modeling/linear_model/lars.py +61 -21
  153. snowflake/ml/modeling/linear_model/lars_cv.py +61 -21
  154. snowflake/ml/modeling/linear_model/lasso.py +61 -21
  155. snowflake/ml/modeling/linear_model/lasso_cv.py +61 -21
  156. snowflake/ml/modeling/linear_model/lasso_lars.py +61 -21
  157. snowflake/ml/modeling/linear_model/lasso_lars_cv.py +61 -21
  158. snowflake/ml/modeling/linear_model/lasso_lars_ic.py +61 -21
  159. snowflake/ml/modeling/linear_model/linear_regression.py +61 -21
  160. snowflake/ml/modeling/linear_model/logistic_regression.py +61 -21
  161. snowflake/ml/modeling/linear_model/logistic_regression_cv.py +61 -21
  162. snowflake/ml/modeling/linear_model/multi_task_elastic_net.py +61 -21
  163. snowflake/ml/modeling/linear_model/multi_task_elastic_net_cv.py +61 -21
  164. snowflake/ml/modeling/linear_model/multi_task_lasso.py +61 -21
  165. snowflake/ml/modeling/linear_model/multi_task_lasso_cv.py +61 -21
  166. snowflake/ml/modeling/linear_model/orthogonal_matching_pursuit.py +61 -21
  167. snowflake/ml/modeling/linear_model/passive_aggressive_classifier.py +61 -21
  168. snowflake/ml/modeling/linear_model/passive_aggressive_regressor.py +61 -21
  169. snowflake/ml/modeling/linear_model/perceptron.py +61 -21
  170. snowflake/ml/modeling/linear_model/poisson_regressor.py +61 -21
  171. snowflake/ml/modeling/linear_model/ransac_regressor.py +61 -21
  172. snowflake/ml/modeling/linear_model/ridge.py +61 -21
  173. snowflake/ml/modeling/linear_model/ridge_classifier.py +61 -21
  174. snowflake/ml/modeling/linear_model/ridge_classifier_cv.py +61 -21
  175. snowflake/ml/modeling/linear_model/ridge_cv.py +61 -21
  176. snowflake/ml/modeling/linear_model/sgd_classifier.py +61 -21
  177. snowflake/ml/modeling/linear_model/sgd_one_class_svm.py +61 -21
  178. snowflake/ml/modeling/linear_model/sgd_regressor.py +61 -21
  179. snowflake/ml/modeling/linear_model/theil_sen_regressor.py +61 -21
  180. snowflake/ml/modeling/linear_model/tweedie_regressor.py +61 -21
  181. snowflake/ml/modeling/manifold/isomap.py +61 -21
  182. snowflake/ml/modeling/manifold/mds.py +61 -21
  183. snowflake/ml/modeling/manifold/spectral_embedding.py +61 -21
  184. snowflake/ml/modeling/manifold/tsne.py +61 -21
  185. snowflake/ml/modeling/metrics/metrics_utils.py +2 -2
  186. snowflake/ml/modeling/metrics/ranking.py +0 -3
  187. snowflake/ml/modeling/metrics/regression.py +0 -3
  188. snowflake/ml/modeling/mixture/bayesian_gaussian_mixture.py +61 -21
  189. snowflake/ml/modeling/mixture/gaussian_mixture.py +61 -21
  190. snowflake/ml/modeling/multiclass/one_vs_one_classifier.py +61 -21
  191. snowflake/ml/modeling/multiclass/one_vs_rest_classifier.py +61 -21
  192. snowflake/ml/modeling/multiclass/output_code_classifier.py +61 -21
  193. snowflake/ml/modeling/naive_bayes/bernoulli_nb.py +61 -21
  194. snowflake/ml/modeling/naive_bayes/categorical_nb.py +61 -21
  195. snowflake/ml/modeling/naive_bayes/complement_nb.py +61 -21
  196. snowflake/ml/modeling/naive_bayes/gaussian_nb.py +61 -21
  197. snowflake/ml/modeling/naive_bayes/multinomial_nb.py +61 -21
  198. snowflake/ml/modeling/neighbors/k_neighbors_classifier.py +61 -21
  199. snowflake/ml/modeling/neighbors/k_neighbors_regressor.py +61 -21
  200. snowflake/ml/modeling/neighbors/kernel_density.py +61 -21
  201. snowflake/ml/modeling/neighbors/local_outlier_factor.py +61 -21
  202. snowflake/ml/modeling/neighbors/nearest_centroid.py +61 -21
  203. snowflake/ml/modeling/neighbors/nearest_neighbors.py +61 -21
  204. snowflake/ml/modeling/neighbors/neighborhood_components_analysis.py +61 -21
  205. snowflake/ml/modeling/neighbors/radius_neighbors_classifier.py +61 -21
  206. snowflake/ml/modeling/neighbors/radius_neighbors_regressor.py +61 -21
  207. snowflake/ml/modeling/neural_network/bernoulli_rbm.py +61 -21
  208. snowflake/ml/modeling/neural_network/mlp_classifier.py +61 -21
  209. snowflake/ml/modeling/neural_network/mlp_regressor.py +61 -21
  210. snowflake/ml/modeling/parameters/disable_model_tracer.py +5 -0
  211. snowflake/ml/modeling/pipeline/pipeline.py +1 -13
  212. snowflake/ml/modeling/preprocessing/polynomial_features.py +61 -21
  213. snowflake/ml/modeling/semi_supervised/label_propagation.py +61 -21
  214. snowflake/ml/modeling/semi_supervised/label_spreading.py +61 -21
  215. snowflake/ml/modeling/svm/linear_svc.py +61 -21
  216. snowflake/ml/modeling/svm/linear_svr.py +61 -21
  217. snowflake/ml/modeling/svm/nu_svc.py +61 -21
  218. snowflake/ml/modeling/svm/nu_svr.py +61 -21
  219. snowflake/ml/modeling/svm/svc.py +61 -21
  220. snowflake/ml/modeling/svm/svr.py +61 -21
  221. snowflake/ml/modeling/tree/decision_tree_classifier.py +61 -21
  222. snowflake/ml/modeling/tree/decision_tree_regressor.py +61 -21
  223. snowflake/ml/modeling/tree/extra_tree_classifier.py +61 -21
  224. snowflake/ml/modeling/tree/extra_tree_regressor.py +61 -21
  225. snowflake/ml/modeling/xgboost/xgb_classifier.py +64 -23
  226. snowflake/ml/modeling/xgboost/xgb_regressor.py +64 -23
  227. snowflake/ml/modeling/xgboost/xgbrf_classifier.py +64 -23
  228. snowflake/ml/modeling/xgboost/xgbrf_regressor.py +64 -23
  229. snowflake/ml/monitoring/_client/model_monitor.py +126 -0
  230. snowflake/ml/monitoring/_client/model_monitor_manager.py +361 -0
  231. snowflake/ml/monitoring/_client/model_monitor_version.py +1 -0
  232. snowflake/ml/monitoring/_client/monitor_sql_client.py +1335 -0
  233. snowflake/ml/monitoring/_client/queries/record_count.ssql +14 -0
  234. snowflake/ml/monitoring/_client/queries/rmse.ssql +28 -0
  235. snowflake/ml/monitoring/entities/model_monitor_config.py +28 -0
  236. snowflake/ml/monitoring/entities/model_monitor_interval.py +46 -0
  237. snowflake/ml/monitoring/entities/output_score_type.py +90 -0
  238. snowflake/ml/registry/_manager/model_manager.py +4 -0
  239. snowflake/ml/registry/registry.py +166 -8
  240. snowflake/ml/version.py +1 -1
  241. {snowflake_ml_python-1.6.1.dist-info → snowflake_ml_python-1.6.3.dist-info}/METADATA +43 -9
  242. snowflake_ml_python-1.6.3.dist-info/RECORD +400 -0
  243. {snowflake_ml_python-1.6.1.dist-info → snowflake_ml_python-1.6.3.dist-info}/WHEEL +1 -1
  244. snowflake/ml/_internal/container_services/image_registry/credential.py +0 -84
  245. snowflake/ml/_internal/container_services/image_registry/http_client.py +0 -127
  246. snowflake/ml/_internal/container_services/image_registry/imagelib.py +0 -400
  247. snowflake/ml/_internal/container_services/image_registry/registry_client.py +0 -212
  248. snowflake/ml/_internal/utils/log_stream_processor.py +0 -30
  249. snowflake/ml/_internal/utils/session_token_manager.py +0 -46
  250. snowflake/ml/_internal/utils/spcs_attribution_utils.py +0 -122
  251. snowflake/ml/_internal/utils/uri.py +0 -77
  252. snowflake/ml/data/torch_dataset.py +0 -33
  253. snowflake/ml/model/_api.py +0 -568
  254. snowflake/ml/model/_deploy_client/image_builds/base_image_builder.py +0 -12
  255. snowflake/ml/model/_deploy_client/image_builds/client_image_builder.py +0 -249
  256. snowflake/ml/model/_deploy_client/image_builds/docker_context.py +0 -130
  257. snowflake/ml/model/_deploy_client/image_builds/gunicorn_run.sh +0 -36
  258. snowflake/ml/model/_deploy_client/image_builds/inference_server/main.py +0 -268
  259. snowflake/ml/model/_deploy_client/image_builds/server_image_builder.py +0 -215
  260. snowflake/ml/model/_deploy_client/image_builds/templates/dockerfile_template +0 -53
  261. snowflake/ml/model/_deploy_client/image_builds/templates/image_build_job_spec_template +0 -38
  262. snowflake/ml/model/_deploy_client/image_builds/templates/kaniko_shell_script_template +0 -105
  263. snowflake/ml/model/_deploy_client/snowservice/deploy.py +0 -611
  264. snowflake/ml/model/_deploy_client/snowservice/deploy_options.py +0 -116
  265. snowflake/ml/model/_deploy_client/snowservice/instance_types.py +0 -10
  266. snowflake/ml/model/_deploy_client/snowservice/templates/service_spec_template +0 -28
  267. snowflake/ml/model/_deploy_client/snowservice/templates/service_spec_template_with_model +0 -21
  268. snowflake/ml/model/_deploy_client/utils/constants.py +0 -48
  269. snowflake/ml/model/_deploy_client/utils/snowservice_client.py +0 -280
  270. snowflake/ml/model/_deploy_client/warehouse/deploy.py +0 -202
  271. snowflake/ml/model/_deploy_client/warehouse/infer_template.py +0 -99
  272. snowflake/ml/model/_packager/model_handlers/llm.py +0 -267
  273. snowflake/ml/model/_packager/model_meta/_core_requirements.py +0 -11
  274. snowflake/ml/model/deploy_platforms.py +0 -6
  275. snowflake/ml/model/models/llm.py +0 -104
  276. snowflake/ml/monitoring/monitor.py +0 -203
  277. snowflake/ml/registry/_initial_schema.py +0 -142
  278. snowflake/ml/registry/_schema.py +0 -82
  279. snowflake/ml/registry/_schema_upgrade_plans.py +0 -116
  280. snowflake/ml/registry/_schema_version_manager.py +0 -163
  281. snowflake/ml/registry/model_registry.py +0 -2048
  282. snowflake_ml_python-1.6.1.dist-info/RECORD +0 -422
  283. {snowflake_ml_python-1.6.1.dist-info → snowflake_ml_python-1.6.3.dist-info}/LICENSE.txt +0 -0
  284. {snowflake_ml_python-1.6.1.dist-info → snowflake_ml_python-1.6.3.dist-info}/top_level.txt +0 -0
@@ -1,611 +0,0 @@
1
- import copy
2
- import logging
3
- import os
4
- import posixpath
5
- import string
6
- import tempfile
7
- import time
8
- from contextlib import contextmanager
9
- from typing import Any, Dict, Generator, Optional, cast
10
-
11
- import importlib_resources
12
- import yaml
13
- from packaging import requirements
14
- from typing_extensions import Unpack
15
-
16
- from snowflake.ml._internal import env_utils, file_utils
17
- from snowflake.ml._internal.container_services.image_registry import (
18
- registry_client as image_registry_client,
19
- )
20
- from snowflake.ml._internal.exceptions import (
21
- error_codes,
22
- exceptions as snowml_exceptions,
23
- )
24
- from snowflake.ml._internal.utils import (
25
- identifier,
26
- query_result_checker,
27
- spcs_attribution_utils,
28
- )
29
- from snowflake.ml.model import type_hints
30
- from snowflake.ml.model._deploy_client import snowservice
31
- from snowflake.ml.model._deploy_client.image_builds import (
32
- base_image_builder,
33
- client_image_builder,
34
- docker_context,
35
- server_image_builder,
36
- )
37
- from snowflake.ml.model._deploy_client.snowservice import deploy_options, instance_types
38
- from snowflake.ml.model._deploy_client.utils import constants, snowservice_client
39
- from snowflake.ml.model._packager.model_meta import model_meta, model_meta_schema
40
- from snowflake.snowpark import Session
41
-
42
- logger = logging.getLogger(__name__)
43
-
44
-
45
- @contextmanager
46
- def _debug_aware_tmp_directory(debug_dir: Optional[str] = None) -> Generator[str, None, None]:
47
- """Debug-aware directory provider.
48
-
49
- Args:
50
- debug_dir: A folder for deploymement context.
51
-
52
- Yields:
53
- A directory path to write deployment artifacts
54
- """
55
- create_temp = False
56
- if debug_dir:
57
- directory_path = debug_dir
58
- else:
59
- temp_dir_context = tempfile.TemporaryDirectory()
60
- directory_path = temp_dir_context.name
61
- create_temp = True
62
- try:
63
- yield directory_path
64
- finally:
65
- if create_temp:
66
- temp_dir_context.cleanup()
67
-
68
-
69
- def _deploy(
70
- session: Session,
71
- *,
72
- model_id: str,
73
- model_meta: model_meta.ModelMetadata,
74
- service_func_name: str,
75
- model_zip_stage_path: str,
76
- deployment_stage_path: str,
77
- target_method: str,
78
- **kwargs: Unpack[type_hints.SnowparkContainerServiceDeployOptions],
79
- ) -> type_hints.SnowparkContainerServiceDeployDetails:
80
- """Entrypoint for model deployment to SnowService. This function will trigger a docker image build followed by
81
- workflow deployment to SnowService.
82
-
83
- Args:
84
- session: Snowpark session
85
- model_id: Unique hex string of length 32, provided by model registry.
86
- model_meta: Model Metadata.
87
- service_func_name: The service function name in SnowService associated with the created service.
88
- model_zip_stage_path: Path to model zip file in stage. Note that this path has a "@" prefix.
89
- deployment_stage_path: Path to stage containing deployment artifacts.
90
- target_method: The name of the target method to be deployed.
91
- **kwargs: various SnowService deployment options.
92
-
93
- Returns:
94
- Deployment details for SPCS.
95
-
96
- Raises:
97
- SnowflakeMLException: Raised when model_id is empty.
98
- SnowflakeMLException: Raised when service_func_name is empty.
99
- SnowflakeMLException: Raised when model_stage_file_path is empty.
100
- """
101
- snowpark_logger = logging.getLogger("snowflake.snowpark")
102
- snowflake_connector_logger = logging.getLogger("snowflake.connector")
103
- snowpark_log_level = snowpark_logger.level
104
- snowflake_connector_log_level = snowflake_connector_logger.level
105
-
106
- query_result = (
107
- query_result_checker.SqlResultValidator(
108
- session,
109
- query="SHOW PARAMETERS LIKE 'PYTHON_CONNECTOR_QUERY_RESULT_FORMAT' IN SESSION",
110
- )
111
- .has_dimensions(expected_rows=1)
112
- .validate()
113
- )
114
- prev_format = query_result[0].value
115
-
116
- try:
117
- # Setting appropriate log level to prevent console from being polluted by vast amount of snowpark and snowflake
118
- # connector logging.
119
- snowpark_logger.setLevel(logging.WARNING)
120
- snowflake_connector_logger.setLevel(logging.WARNING)
121
-
122
- # Query format change is needed to ensure session token obtained from the session object is valid.
123
- session.sql("ALTER SESSION SET PYTHON_CONNECTOR_QUERY_RESULT_FORMAT = 'json'").collect()
124
- if not model_id:
125
- raise snowml_exceptions.SnowflakeMLException(
126
- error_code=error_codes.INVALID_ARGUMENT,
127
- original_exception=ValueError(
128
- 'Must provide a non-empty string for "model_id" when deploying to Snowpark Container Services'
129
- ),
130
- )
131
- if not service_func_name:
132
- raise snowml_exceptions.SnowflakeMLException(
133
- error_code=error_codes.INVALID_ARGUMENT,
134
- original_exception=ValueError(
135
- 'Must provide a non-empty string for "service_func_name"'
136
- " when deploying to Snowpark Container Services"
137
- ),
138
- )
139
- if not model_zip_stage_path:
140
- raise snowml_exceptions.SnowflakeMLException(
141
- error_code=error_codes.INVALID_ARGUMENT,
142
- original_exception=ValueError(
143
- 'Must provide a non-empty string for "model_stage_file_path"'
144
- " when deploying to Snowpark Container Services"
145
- ),
146
- )
147
- if not deployment_stage_path:
148
- raise snowml_exceptions.SnowflakeMLException(
149
- error_code=error_codes.INVALID_ARGUMENT,
150
- original_exception=ValueError(
151
- 'Must provide a non-empty string for "deployment_stage_path"'
152
- " when deploying to Snowpark Container Services"
153
- ),
154
- )
155
-
156
- # Remove full qualified name to avoid double quotes corrupting the service spec
157
- model_zip_stage_path = model_zip_stage_path.replace('"', "")
158
- deployment_stage_path = deployment_stage_path.replace('"', "")
159
-
160
- assert model_zip_stage_path.startswith("@"), f"stage path should start with @, actual: {model_zip_stage_path}"
161
- assert deployment_stage_path.startswith("@"), f"stage path should start with @, actual: {deployment_stage_path}"
162
- options = deploy_options.SnowServiceDeployOptions.from_dict(cast(Dict[str, Any], kwargs))
163
-
164
- model_meta_deploy = copy.deepcopy(model_meta)
165
- # Set conda-forge as backup channel for SPCS deployment
166
- if "conda-forge" not in model_meta_deploy.env._conda_dependencies:
167
- model_meta_deploy.env._conda_dependencies["conda-forge"] = []
168
- # Snowflake connector needs pyarrow to work correctly.
169
- env_utils.append_conda_dependency(
170
- model_meta_deploy.env._conda_dependencies,
171
- (env_utils.DEFAULT_CHANNEL_NAME, requirements.Requirement("pyarrow")),
172
- )
173
- if options.use_gpu:
174
- # Make mypy happy
175
- assert options.num_gpus is not None
176
- if model_meta_deploy.env.cuda_version is None:
177
- raise snowml_exceptions.SnowflakeMLException(
178
- error_code=error_codes.INVALID_ARGUMENT,
179
- original_exception=ValueError(
180
- "You are requesting GPUs for models that do not use a GPU or does not have CUDA version set."
181
- ),
182
- )
183
- if model_meta.env.cuda_version:
184
- model_meta_deploy.env.generate_env_for_cuda()
185
- else:
186
- # If user does not need GPU, we set this copies cuda_version to None, thus when Image builder gets a
187
- # not-None cuda_version, it gets to know that GPU is required.
188
- model_meta_deploy.env._cuda_version = None
189
-
190
- _validate_compute_pool(session, options=options)
191
-
192
- # TODO[shchen]: SNOW-863701, Explore ways to prevent entire model zip being downloaded during deploy step
193
- # (for both warehouse and snowservice deployment)
194
- # One alternative is for model registry to duplicate the model metadata and env dependency storage from model
195
- # zip so that we don't have to pull down the entire model zip.
196
- ss_deployment = SnowServiceDeployment(
197
- session=session,
198
- model_id=model_id,
199
- model_meta=model_meta_deploy,
200
- service_func_name=service_func_name,
201
- model_zip_stage_path=model_zip_stage_path, # Pass down model_zip_stage_path for service spec file
202
- deployment_stage_path=deployment_stage_path,
203
- target_method=target_method,
204
- options=options,
205
- )
206
- return ss_deployment.deploy()
207
- finally:
208
- session.sql(f"ALTER SESSION SET PYTHON_CONNECTOR_QUERY_RESULT_FORMAT = '{prev_format}'").collect()
209
- # Preserve the original logging level.
210
- snowpark_logger.setLevel(snowpark_log_level)
211
- snowflake_connector_logger.setLevel(snowflake_connector_log_level)
212
-
213
-
214
- def _validate_compute_pool(session: Session, *, options: deploy_options.SnowServiceDeployOptions) -> None:
215
- # Remove full qualified name to avoid double quotes, which does not work well in desc compute pool syntax.
216
- compute_pool = options.compute_pool.replace('"', "")
217
- sql = f"DESC COMPUTE POOL {compute_pool}"
218
- result = (
219
- query_result_checker.SqlResultValidator(
220
- session=session,
221
- query=sql,
222
- )
223
- .has_column("instance_family")
224
- .has_column("state")
225
- .has_column("auto_resume")
226
- .has_dimensions(expected_rows=1)
227
- .validate()
228
- )
229
-
230
- state = result[0]["state"]
231
- auto_resume = bool(result[0]["auto_resume"])
232
-
233
- if state == "SUSPENDED":
234
- if not auto_resume:
235
- raise snowml_exceptions.SnowflakeMLException(
236
- error_code=error_codes.INVALID_SNOWPARK_COMPUTE_POOL,
237
- original_exception=RuntimeError(
238
- "The compute pool you are requesting to use is suspended without auto-resume enabled"
239
- ),
240
- )
241
-
242
- elif state not in ["STARTING", "ACTIVE", "IDLE"]:
243
- raise snowml_exceptions.SnowflakeMLException(
244
- error_code=error_codes.INVALID_SNOWPARK_COMPUTE_POOL,
245
- original_exception=RuntimeError(
246
- "The compute pool you are requesting to use is not in the ACTIVE/IDLE/STARTING status."
247
- ),
248
- )
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
-
253
- if options.use_gpu:
254
- assert options.num_gpus is not None
255
- request_gpus = options.num_gpus
256
- instance_family = result[0]["instance_family"]
257
- if instance_family in instance_types.INSTANCE_TYPE_TO_GPU_COUNT:
258
- gpu_capacity = instance_types.INSTANCE_TYPE_TO_GPU_COUNT[instance_family]
259
- if request_gpus > gpu_capacity:
260
- raise snowml_exceptions.SnowflakeMLException(
261
- error_code=error_codes.INVALID_SNOWPARK_COMPUTE_POOL,
262
- original_exception=RuntimeError(
263
- f"GPU request exceeds instance capability; {instance_family} instance type has total "
264
- f"capacity of {gpu_capacity} GPU, yet a request was made for {request_gpus} GPUs."
265
- ),
266
- )
267
- else:
268
- logger.warning(f"Unknown instance type: {instance_family}, skipping GPU validation")
269
-
270
-
271
- def _get_or_create_image_repo(session: Session, *, service_func_name: str, image_repo: Optional[str] = None) -> str:
272
- def _sanitize_dns_url(url: str) -> str:
273
- # Align with existing SnowService image registry url standard.
274
- return url.lower()
275
-
276
- if image_repo:
277
- return _sanitize_dns_url(image_repo)
278
-
279
- try:
280
- conn = session._conn._conn
281
- # We try to use the same db and schema as the service function locates, as we could retrieve those information
282
- # if that is a fully qualified one. If not we use the current session one.
283
- (_db, _schema, _, _) = identifier.parse_schema_level_object_identifier(service_func_name)
284
- db = _db if _db is not None else conn._database
285
- schema = _schema if _schema is not None else conn._schema
286
- assert isinstance(db, str) and isinstance(schema, str)
287
-
288
- client = snowservice_client.SnowServiceClient(session)
289
- client.create_image_repo(identifier.get_schema_level_object_identifier(db, schema, constants.SNOWML_IMAGE_REPO))
290
- sql = f"SHOW IMAGE REPOSITORIES LIKE '{constants.SNOWML_IMAGE_REPO}' IN SCHEMA {'.'.join([db, schema])}"
291
- result = (
292
- query_result_checker.SqlResultValidator(
293
- session=session,
294
- query=sql,
295
- )
296
- .has_column("repository_url")
297
- .has_dimensions(expected_rows=1)
298
- .validate()
299
- )
300
- repository_url = result[0]["repository_url"]
301
- return str(repository_url)
302
- except Exception as e:
303
- raise snowml_exceptions.SnowflakeMLException(
304
- error_code=error_codes.INTERNAL_SNOWPARK_CONTAINER_SERVICE_ERROR,
305
- original_exception=RuntimeError("Failed to retrieve image repo URL"),
306
- ) from e
307
-
308
-
309
- class SnowServiceDeployment:
310
- """
311
- Class implementation that encapsulates image build and workflow deployment to SnowService
312
- """
313
-
314
- def __init__(
315
- self,
316
- session: Session,
317
- model_id: str,
318
- model_meta: model_meta.ModelMetadata,
319
- service_func_name: str,
320
- model_zip_stage_path: str,
321
- deployment_stage_path: str,
322
- target_method: str,
323
- options: deploy_options.SnowServiceDeployOptions,
324
- ) -> None:
325
- """Initialization
326
-
327
- Args:
328
- session: Snowpark session
329
- model_id: Unique hex string of length 32, provided by model registry; if not provided, auto-generate one for
330
- resource naming.The model_id serves as an idempotent key throughout the deployment workflow.
331
- model_meta: Model Metadata.
332
- service_func_name: The service function name in SnowService associated with the created service.
333
- model_zip_stage_path: Path to model zip file in stage.
334
- deployment_stage_path: Path to stage containing deployment artifacts.
335
- target_method: The name of the target method to be deployed.
336
- options: A SnowServiceDeployOptions object containing deployment options.
337
- """
338
-
339
- self.session = session
340
- self.id = model_id
341
- self.model_meta = model_meta
342
- self.service_func_name = service_func_name
343
- self.model_zip_stage_path = model_zip_stage_path
344
- self.options = options
345
- self.target_method = target_method
346
- (db, schema, _, _) = identifier.parse_schema_level_object_identifier(service_func_name)
347
-
348
- self._service_name = identifier.get_schema_level_object_identifier(db, schema, f"service_{model_id}")
349
- self._job_name = identifier.get_schema_level_object_identifier(db, schema, f"build_{model_id}")
350
- # Spec file and future deployment related artifacts will be stored under {stage}/models/{model_id}
351
- self._model_artifact_stage_location = posixpath.join(deployment_stage_path, "models", self.id)
352
- self.debug_dir: Optional[str] = None
353
- if self.options.debug_mode:
354
- self.debug_dir = tempfile.mkdtemp()
355
- logger.warning(f"Debug model is enabled, deployment artifacts will be available in {self.debug_dir}")
356
-
357
- def deploy(self) -> type_hints.SnowparkContainerServiceDeployDetails:
358
- """
359
- This function triggers image build followed by workflow deployment to SnowService.
360
-
361
- Returns:
362
- Deployment details.
363
- """
364
- if self.options.prebuilt_snowflake_image:
365
- logger.warning(f"Skipped image build. Use prebuilt image: {self.options.prebuilt_snowflake_image}")
366
- service_function_sql = self._deploy_workflow(self.options.prebuilt_snowflake_image)
367
- else:
368
- with _debug_aware_tmp_directory(debug_dir=self.debug_dir) as context_dir:
369
- extra_kwargs = {}
370
- if self.options.model_in_image:
371
- extra_kwargs = {
372
- "session": self.session,
373
- "model_zip_stage_path": self.model_zip_stage_path,
374
- }
375
- dc = docker_context.DockerContext(
376
- context_dir=context_dir,
377
- model_meta=self.model_meta,
378
- **extra_kwargs, # type: ignore[arg-type]
379
- )
380
- dc.build()
381
- image_repo = _get_or_create_image_repo(
382
- self.session, service_func_name=self.service_func_name, image_repo=self.options.image_repo
383
- )
384
- full_image_name = self._get_full_image_name(image_repo=image_repo, context_dir=context_dir)
385
- registry_client = image_registry_client.ImageRegistryClient(self.session, full_image_name)
386
-
387
- if not self.options.force_image_build and registry_client.image_exists(full_image_name=full_image_name):
388
- logger.warning(
389
- f"Similar environment detected. Using existing image {full_image_name} to skip image "
390
- f"build. To disable this feature, set 'force_image_build=True' in deployment options"
391
- )
392
- else:
393
- logger.warning(
394
- "Building the Docker image and deploying to Snowpark Container Service. "
395
- "This process may take anywhere from a few minutes to a longer period for GPU-based models."
396
- )
397
- start = time.time()
398
- self._build_and_upload_image(
399
- context_dir=context_dir, image_repo=image_repo, full_image_name=full_image_name
400
- )
401
- end = time.time()
402
- logger.info(f"Time taken to build and upload image to registry: {end - start:.2f} seconds")
403
- logger.warning(
404
- f"Image successfully built! For future model deployments, the image will be reused if "
405
- f"possible, saving model deployment time. To enforce using the same image, include "
406
- f"'prebuilt_snowflake_image': '{full_image_name}' in the deploy() function's options."
407
- )
408
-
409
- # Adding the model name as an additional tag to the existing image, excluding the version to prevent
410
- # excessive tags and also due to version not available in current model metadata. This will allow
411
- # users to associate images with specific models and perform relevant image registry actions. In the
412
- # event that model dependencies change across versions, a new image hash will be computed, resulting in
413
- # a new image.
414
- try:
415
- registry_client.add_tag_to_remote_image(
416
- original_full_image_name=full_image_name, new_tag=self.model_meta.name
417
- )
418
- except Exception as e:
419
- # Proceed to the deployment with a warning message.
420
- logger.warning(f"Failed to add tag {self.model_meta.name} to image {full_image_name}: {str(e)}")
421
- service_function_sql = self._deploy_workflow(full_image_name)
422
-
423
- rows = self.session.sql(f"DESCRIBE SERVICE {self._service_name}").collect()
424
- service_info = rows[0].as_dict() if rows and rows[0] else None
425
- return type_hints.SnowparkContainerServiceDeployDetails(
426
- service_info=service_info,
427
- service_function_sql=service_function_sql,
428
- )
429
-
430
- def _get_full_image_name(self, image_repo: str, context_dir: str) -> str:
431
- """Return a valid full image name that consists of image name and tag. e.g
432
- org-account.registry.snowflakecomputing.com/db/schema/repo/image:latest
433
-
434
- Args:
435
- image_repo: image repo path, e.g. org-account.registry.snowflakecomputing.com/db/schema/repo
436
- context_dir: the local docker context directory, which consists everything needed to build the docker image.
437
-
438
- Returns:
439
- Full image name.
440
- """
441
- image_repo = _get_or_create_image_repo(
442
- self.session, service_func_name=self.service_func_name, image_repo=self.options.image_repo
443
- )
444
-
445
- # We skip "MODEL_METADATA_FILE" as it contains information that will always lead to cache misses. This isn't an
446
- # issue because model dependency is also captured in the model env/ folder, which will be hashed. The aim is to
447
- # reuse the same Docker image even if the user logs a similar model without new dependencies.
448
- docker_context_dir_hash = file_utils.hash_directory(
449
- context_dir, ignore_hidden=True, excluded_files=[model_meta.MODEL_METADATA_FILE]
450
- )
451
- # By default, we associate a 'latest' tag with each of our created images for easy existence checking.
452
- # Additional tags are added for readability.
453
- return f"{image_repo}/{docker_context_dir_hash}:{constants.LATEST_IMAGE_TAG}"
454
-
455
- def _build_and_upload_image(self, context_dir: str, image_repo: str, full_image_name: str) -> None:
456
- """Handles image build and upload to image registry.
457
-
458
- Args:
459
- context_dir: the local docker context directory, which consists everything needed to build the docker image.
460
- image_repo: image repo path, e.g. org-account.registry.snowflakecomputing.com/db/schema/repo
461
- full_image_name: Full image name consists of image name and image tag.
462
- """
463
- image_builder: base_image_builder.ImageBuilder
464
- if self.options.enable_remote_image_build:
465
- image_builder = server_image_builder.ServerImageBuilder(
466
- context_dir=context_dir,
467
- full_image_name=full_image_name,
468
- image_repo=image_repo,
469
- session=self.session,
470
- artifact_stage_location=self._model_artifact_stage_location,
471
- compute_pool=self.options.compute_pool,
472
- job_name=self._job_name,
473
- external_access_integrations=self.options.external_access_integrations,
474
- )
475
- else:
476
- image_builder = client_image_builder.ClientImageBuilder(
477
- context_dir=context_dir, full_image_name=full_image_name, image_repo=image_repo, session=self.session
478
- )
479
- image_builder.build_and_upload_image()
480
-
481
- def _prepare_and_upload_artifacts_to_stage(self, image: str) -> None:
482
- """Constructs and upload service spec to stage.
483
-
484
- Args:
485
- image: Name of the image to create SnowService container from.
486
- """
487
- if self.options.model_in_image:
488
- spec_template = (
489
- importlib_resources.files(snowservice)
490
- .joinpath("templates/service_spec_template_with_model")
491
- .read_text("utf-8")
492
- )
493
- else:
494
- spec_template = (
495
- importlib_resources.files(snowservice).joinpath("templates/service_spec_template").read_text("utf-8")
496
- )
497
-
498
- with _debug_aware_tmp_directory(self.debug_dir) as dir_path:
499
- spec_file_path = os.path.join(dir_path, f"{constants.SERVICE_SPEC}.yaml")
500
-
501
- with open(spec_file_path, "w+", encoding="utf-8") as spec_file:
502
- assert self.model_zip_stage_path.startswith("@")
503
- norm_stage_path = posixpath.normpath(identifier.remove_prefix(self.model_zip_stage_path, "@"))
504
- # Ensure model stage path has root prefix as stage mount will it mount it to root.
505
- absolute_model_stage_path = os.path.join("/", norm_stage_path)
506
- (db, schema, stage, path) = identifier.parse_schema_level_object_identifier(norm_stage_path)
507
- substitutes = {
508
- "image": image,
509
- "predict_endpoint_name": constants.PREDICT,
510
- "model_stage": identifier.get_schema_level_object_identifier(db, schema, stage),
511
- "model_zip_stage_path": absolute_model_stage_path,
512
- "inference_server_container_name": constants.INFERENCE_SERVER_CONTAINER,
513
- "target_method": self.target_method,
514
- "num_workers": self.options.num_workers,
515
- "use_gpu": self.options.use_gpu,
516
- "enable_ingress": self.options.enable_ingress,
517
- }
518
- if self.options.model_in_image:
519
- del substitutes["model_stage"]
520
- del substitutes["model_zip_stage_path"]
521
- content = string.Template(spec_template).substitute(substitutes)
522
- content_dict = yaml.safe_load(content)
523
- if self.options.use_gpu:
524
- container = content_dict["spec"]["container"][0]
525
- # TODO[shchen]: SNOW-871538, external dependency that only single GPU is supported on SnowService.
526
- # GPU limit has to be specified in order to trigger the workload to be run on GPU in SnowService.
527
- container["resources"] = {
528
- "limits": {"nvidia.com/gpu": self.options.num_gpus},
529
- "requests": {"nvidia.com/gpu": self.options.num_gpus},
530
- }
531
-
532
- # Make LLM use case sequential
533
- if any(
534
- model_blob_meta.model_type == "huggingface_pipeline" or model_blob_meta.model_type == "llm"
535
- for model_blob_meta in self.model_meta.models.values()
536
- ):
537
- container["env"]["_CONCURRENT_REQUESTS_MAX"] = 1
538
-
539
- yaml.dump(content_dict, spec_file)
540
- logger.debug("Create service spec: \n, %s", content_dict)
541
-
542
- self.session.file.put(
543
- local_file_name=spec_file_path,
544
- stage_location=self._model_artifact_stage_location,
545
- auto_compress=False,
546
- overwrite=True,
547
- )
548
- logger.debug(
549
- f"Uploaded spec file {os.path.basename(spec_file_path)} " f"to {self._model_artifact_stage_location}"
550
- )
551
-
552
- def _get_max_batch_rows(self) -> Optional[int]:
553
- # To avoid too large batch in HF LLM case
554
- max_batch_rows = None
555
- if self.options.use_gpu:
556
- for model_blob_meta in self.model_meta.models.values():
557
- batch_size = None
558
- if model_blob_meta.model_type == "huggingface_pipeline":
559
- model_blob_options_hf = cast(
560
- model_meta_schema.HuggingFacePipelineModelBlobOptions, model_blob_meta.options
561
- )
562
- batch_size = model_blob_options_hf["batch_size"]
563
- if model_blob_meta.model_type == "llm":
564
- model_blob_options_llm = cast(model_meta_schema.LLMModelBlobOptions, model_blob_meta.options)
565
- batch_size = model_blob_options_llm["batch_size"]
566
- if batch_size:
567
- if max_batch_rows is None:
568
- max_batch_rows = batch_size
569
- else:
570
- max_batch_rows = min(batch_size, max_batch_rows)
571
- return max_batch_rows
572
-
573
- def _deploy_workflow(self, image: str) -> str:
574
- """This function handles workflow deployment to SnowService with the given image.
575
-
576
- Args:
577
- image: Name of the image to create SnowService container from.
578
-
579
- Returns:
580
- service function sql
581
- """
582
-
583
- self._prepare_and_upload_artifacts_to_stage(image)
584
- client = snowservice_client.SnowServiceClient(self.session)
585
- spec_stage_location = posixpath.join(
586
- self._model_artifact_stage_location.rstrip("/"), f"{constants.SERVICE_SPEC}.yaml"
587
- )
588
- client.create_or_replace_service(
589
- service_name=self._service_name,
590
- compute_pool=self.options.compute_pool,
591
- spec_stage_location=spec_stage_location,
592
- min_instances=self.options.min_instances,
593
- max_instances=self.options.max_instances,
594
- external_access_integrations=self.options.external_access_integrations,
595
- )
596
- logger.info(f"Wait for service {self._service_name} to become ready...")
597
- client.block_until_resource_is_ready(
598
- resource_name=self._service_name, resource_type=constants.ResourceType.SERVICE
599
- )
600
- logger.info(f"Service {self._service_name} is ready. Creating service function...")
601
-
602
- spcs_attribution_utils.record_service_start(self.session, self._service_name)
603
-
604
- service_function_sql = client.create_or_replace_service_function(
605
- service_func_name=self.service_func_name,
606
- service_name=self._service_name,
607
- endpoint_name=constants.PREDICT,
608
- max_batch_rows=self._get_max_batch_rows(),
609
- )
610
- logger.info(f"Service function {self.service_func_name} is created. Deployment completed successfully!")
611
- return service_function_sql