snowflake-ml-python 1.53.0__py3-none-any.whl → 2.0.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 +13 -3
- snowflake/ml/_internal/platform_capabilities.py +1 -1
- snowflake/ml/_internal/telemetry.py +9 -5
- snowflake/ml/experiment/_source_info.py +30 -3
- snowflake/ml/experiment/experiment_tracking.py +4 -3
- snowflake/ml/feature_store/aggregation.py +26 -1
- snowflake/ml/feature_store/feature.py +1 -1
- snowflake/ml/feature_store/feature_store.py +374 -263
- snowflake/ml/feature_store/feature_view.py +24 -22
- snowflake/ml/feature_store/metadata_manager.py +21 -6
- snowflake/ml/feature_store/online_service.py +118 -46
- snowflake/ml/feature_store/stream_config.py +10 -3
- snowflake/ml/feature_store/streaming_registration.py +42 -4
- snowflake/ml/feature_store/tile_sql_generator.py +29 -9
- snowflake/ml/fileset/sfcfs.py +7 -8
- snowflake/ml/jobs/_interop/results.py +2 -5
- snowflake/ml/jobs/_utils/scripts/get_instance_ip.py +4 -8
- snowflake/ml/jobs/_utils/scripts/mljob_launcher.py +12 -15
- snowflake/ml/jobs/_utils/type_utils.py +22 -21
- snowflake/ml/jobs/decorators.py +6 -4
- snowflake/ml/jobs/job.py +67 -62
- snowflake/ml/jobs/job_definition.py +45 -26
- snowflake/ml/jobs/manager.py +48 -41
- snowflake/ml/model/__init__.py +2 -19
- snowflake/ml/model/_client/model/_loaded_model_telemetry.py +152 -0
- snowflake/ml/model/_client/model/batch_inference_task.py +93 -170
- snowflake/ml/model/_client/model/inference_engine_utils.py +3 -39
- snowflake/ml/model/_client/model/model_version_impl.py +162 -380
- snowflake/ml/model/_client/model_spec/legacy_model_spec.py +74 -0
- snowflake/ml/model/_client/model_spec/model_extension_spec.py +171 -0
- snowflake/ml/model/_client/model_spec/model_extension_spec_schema.py +113 -0
- snowflake/ml/model/_client/model_spec/model_spec.py +71 -0
- snowflake/ml/model/_client/model_spec/model_spec_parser.py +38 -0
- snowflake/ml/model/_client/ops/model_ops.py +187 -185
- snowflake/ml/model/_client/ops/service_ops.py +95 -290
- snowflake/ml/model/_client/service/model_deployment_spec.py +49 -183
- snowflake/ml/model/_client/service/model_deployment_spec_schema.py +29 -69
- snowflake/ml/model/_client/sql/model.py +63 -37
- snowflake/ml/model/_client/sql/model_version.py +49 -10
- snowflake/ml/model/_model_composer/model_method/function_generator.py +6 -1
- snowflake/ml/model/_model_composer/model_method/model_method.py +8 -2
- snowflake/ml/model/_model_composer/model_method/utils.py +14 -4
- snowflake/ml/model/_packager/model_env/model_env.py +4 -1
- snowflake/ml/model/_packager/model_handlers/peft_adapter.py +224 -0
- snowflake/ml/model/_packager/model_handlers/snowmlmodel.py +14 -8
- snowflake/ml/model/_packager/model_meta/model_meta.py +17 -5
- snowflake/ml/model/_packager/model_meta/model_meta_schema.py +11 -0
- snowflake/ml/model/_packager/model_packager.py +12 -8
- snowflake/ml/model/_packager/model_runtime/_snowml_inference_alternative_requirements.py +1 -5
- snowflake/ml/model/_packager/model_save_options.py +1 -0
- snowflake/ml/model/batch_inference/__init__.py +1 -1
- snowflake/ml/model/models/huggingface.py +88 -1
- snowflake/ml/model/models/huggingface_pipeline.py +24 -31
- snowflake/ml/model/openai_signatures.py +2 -0
- snowflake/ml/model/type_hints.py +22 -0
- snowflake/ml/model/volatility.py +1 -0
- snowflake/ml/modeling/_internal/optional_dependency.py +133 -0
- snowflake/ml/modeling/calibration/__init__.py +9 -1
- snowflake/ml/modeling/cluster/__init__.py +9 -1
- snowflake/ml/modeling/compose/__init__.py +9 -1
- snowflake/ml/modeling/covariance/__init__.py +9 -1
- snowflake/ml/modeling/decomposition/__init__.py +9 -1
- snowflake/ml/modeling/discriminant_analysis/__init__.py +9 -1
- snowflake/ml/modeling/ensemble/__init__.py +9 -1
- snowflake/ml/modeling/feature_selection/__init__.py +9 -1
- snowflake/ml/modeling/gaussian_process/__init__.py +9 -1
- snowflake/ml/modeling/impute/__init__.py +7 -1
- snowflake/ml/modeling/kernel_approximation/__init__.py +9 -1
- snowflake/ml/modeling/kernel_ridge/__init__.py +9 -1
- snowflake/ml/modeling/lightgbm/__init__.py +9 -1
- snowflake/ml/modeling/linear_model/__init__.py +9 -1
- snowflake/ml/modeling/manifold/__init__.py +9 -1
- snowflake/ml/modeling/metrics/__init__.py +8 -1
- snowflake/ml/modeling/mixture/__init__.py +9 -1
- snowflake/ml/modeling/model_selection/__init__.py +7 -1
- snowflake/ml/modeling/multiclass/__init__.py +9 -1
- snowflake/ml/modeling/naive_bayes/__init__.py +9 -1
- snowflake/ml/modeling/neighbors/__init__.py +9 -1
- snowflake/ml/modeling/neural_network/__init__.py +9 -1
- snowflake/ml/modeling/pipeline/__init__.py +7 -1
- snowflake/ml/modeling/preprocessing/__init__.py +7 -1
- snowflake/ml/modeling/semi_supervised/__init__.py +9 -1
- snowflake/ml/modeling/svm/__init__.py +9 -1
- snowflake/ml/modeling/tree/__init__.py +9 -1
- snowflake/ml/modeling/xgboost/__init__.py +9 -1
- snowflake/ml/registry/_manager/model_manager.py +299 -85
- snowflake/ml/registry/_manager/model_parameter_reconciler.py +34 -29
- snowflake/ml/registry/registry.py +14 -0
- snowflake/ml/version.py +1 -1
- {snowflake_ml_python-1.53.0.dist-info → snowflake_ml_python-2.0.0.dist-info}/METADATA +132 -10
- {snowflake_ml_python-1.53.0.dist-info → snowflake_ml_python-2.0.0.dist-info}/RECORD +94 -91
- snowflake/ml/model/_client/model/batch_inference_serialization.py +0 -58
- snowflake/ml/model/_client/model/batch_inference_specs.py +0 -153
- snowflake/ml/model/_client/model/batch_inference_task_v2.py +0 -156
- snowflake/ml/model/batch/__init__.py +0 -23
- snowflake/ml/utils/connection_params.py +0 -205
- {snowflake_ml_python-1.53.0.dist-info → snowflake_ml_python-2.0.0.dist-info}/WHEEL +0 -0
- {snowflake_ml_python-1.53.0.dist-info → snowflake_ml_python-2.0.0.dist-info}/licenses/LICENSE.txt +0 -0
- {snowflake_ml_python-1.53.0.dist-info → snowflake_ml_python-2.0.0.dist-info}/top_level.txt +0 -0
|
@@ -689,22 +689,30 @@ def save_requirements_file(
|
|
|
689
689
|
path: pathlib.Path,
|
|
690
690
|
pip_deps: list[requirements.Requirement],
|
|
691
691
|
cuda_version: Optional[str] = None,
|
|
692
|
-
) ->
|
|
692
|
+
) -> list[str]:
|
|
693
693
|
"""Generate Python requirements.txt file in the given directory path.
|
|
694
694
|
|
|
695
695
|
Args:
|
|
696
696
|
path: Path to the requirements.txt file.
|
|
697
697
|
pip_deps: List of dependencies after validation.
|
|
698
698
|
cuda_version: Optional CUDA version for GPU models. If provided and torch is in
|
|
699
|
-
dependencies,
|
|
699
|
+
dependencies, pins torch to CUDA variant.
|
|
700
|
+
|
|
701
|
+
Returns:
|
|
702
|
+
List of extra pip index URLs (e.g. ``["https://download.pytorch.org/whl/cu124"]``)
|
|
703
|
+
that were NOT written to requirements.txt because SPCS rejects non-PEP-508 lines.
|
|
704
|
+
Callers should persist these via model metadata so the build step can apply them.
|
|
700
705
|
"""
|
|
701
706
|
assert path.suffix in [".txt"], "PIP requirement file should have extension of txt."
|
|
702
707
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
703
708
|
|
|
704
709
|
lines: list[str] = []
|
|
710
|
+
pip_extra_index_urls: list[str] = []
|
|
705
711
|
|
|
706
712
|
if cuda_version and _has_torch_dependency(pip_deps):
|
|
707
|
-
|
|
713
|
+
# Strip the "--extra-index-url " prefix to store just the URL.
|
|
714
|
+
raw = _get_pytorch_cuda_index_url(cuda_version)
|
|
715
|
+
pip_extra_index_urls.append(raw.removeprefix("--extra-index-url "))
|
|
708
716
|
pip_deps = _pin_torch_to_cuda_variant(pip_deps, cuda_version)
|
|
709
717
|
|
|
710
718
|
lines.extend(map(str, pip_deps))
|
|
@@ -712,6 +720,8 @@ def save_requirements_file(
|
|
|
712
720
|
with open(path, "w", encoding="utf-8") as out:
|
|
713
721
|
out.write("\n".join(lines))
|
|
714
722
|
|
|
723
|
+
return pip_extra_index_urls
|
|
724
|
+
|
|
715
725
|
|
|
716
726
|
def load_conda_env_file(
|
|
717
727
|
path: pathlib.Path,
|
|
@@ -84,7 +84,7 @@ class PlatformCapabilities:
|
|
|
84
84
|
return self._get_bool_feature(LIVE_COMMIT_PARAMETER, False)
|
|
85
85
|
|
|
86
86
|
def is_hidden_live_commit_enabled(self) -> bool:
|
|
87
|
-
return False
|
|
87
|
+
return self._get_bool_feature(HIDDEN_LIVE_COMMIT_PARAMETER, False)
|
|
88
88
|
|
|
89
89
|
def is_model_method_signature_parameters_enabled(self) -> bool:
|
|
90
90
|
return self._get_bool_feature(ENABLE_MODEL_METHOD_SIGNATURE_PARAMETERS, False)
|
|
@@ -9,7 +9,8 @@ import sys
|
|
|
9
9
|
import time
|
|
10
10
|
import traceback
|
|
11
11
|
import types
|
|
12
|
-
from
|
|
12
|
+
from collections.abc import Iterable, Mapping
|
|
13
|
+
from typing import Any, Callable, Optional, TypeVar, Union, cast
|
|
13
14
|
|
|
14
15
|
from typing_extensions import ParamSpec
|
|
15
16
|
|
|
@@ -119,6 +120,7 @@ class TelemetryField(enum.Enum):
|
|
|
119
120
|
TYPE_FUNCTION_USAGE = "function_usage"
|
|
120
121
|
TYPE_SNOWML_SPCS_USAGE = "snowml_spcs_usage"
|
|
121
122
|
TYPE_SNOWML_PIPELINE_USAGE = "snowml_pipeline_usage"
|
|
123
|
+
TYPE_SNOWML_LOADED_MODEL_USAGE = "snowml_loaded_model_usage"
|
|
122
124
|
# message keys for telemetry
|
|
123
125
|
KEY_PROJECT = "project"
|
|
124
126
|
KEY_SUBPROJECT = "subproject"
|
|
@@ -717,6 +719,12 @@ def _extract_arg_value(field: str, sig: inspect.Signature, args: Any, kwargs: An
|
|
|
717
719
|
Tuple: First value indicates if `field` exists.
|
|
718
720
|
Second value is the extracted value if existed.
|
|
719
721
|
"""
|
|
722
|
+
# Check keyword arguments first. The field may have no named parameter of its own and instead be
|
|
723
|
+
# absorbed by a variadic keyword parameter (**kwargs), in which case the signature lookup below
|
|
724
|
+
# would not find it even though the caller passed a value.
|
|
725
|
+
if field in kwargs:
|
|
726
|
+
return True, kwargs[field]
|
|
727
|
+
|
|
720
728
|
if field not in sig.parameters:
|
|
721
729
|
return False, None
|
|
722
730
|
|
|
@@ -729,10 +737,6 @@ def _extract_arg_value(field: str, sig: inspect.Signature, args: Any, kwargs: An
|
|
|
729
737
|
if idx < len(args):
|
|
730
738
|
return True, args[idx]
|
|
731
739
|
|
|
732
|
-
# Check if value was passed as keyword argument
|
|
733
|
-
if field in kwargs:
|
|
734
|
-
return True, kwargs[field]
|
|
735
|
-
|
|
736
740
|
# Fall back to default value if available
|
|
737
741
|
if param.default is not inspect.Parameter.empty:
|
|
738
742
|
return True, param.default
|
|
@@ -44,6 +44,11 @@ _SNOWFLAKE_FILE_DOMAIN_TYPE_ENV = "SNOWFLAKE_FILE_DOMAIN_TYPE"
|
|
|
44
44
|
_SNOWFLAKE_FILE_DOMAIN_NAME_ENV = "SNOWFLAKE_FILE_DOMAIN_NAME"
|
|
45
45
|
_SNOWFLAKE_MAIN_FILE_PATH_ENV = "SNOWFLAKE_MAIN_FILE_PATH"
|
|
46
46
|
|
|
47
|
+
# Environment variable Snowflake injects into an ML job's container, carrying the
|
|
48
|
+
# job's fully-qualified id. Its presence is how we recognize that the run was
|
|
49
|
+
# created from inside an ML job.
|
|
50
|
+
_ML_JOB_ID_ENV = "MLRS_JOB_ID"
|
|
51
|
+
|
|
47
52
|
|
|
48
53
|
@dataclasses.dataclass(frozen=True)
|
|
49
54
|
class GitInfo:
|
|
@@ -72,6 +77,9 @@ class SourceInfo:
|
|
|
72
77
|
# ``entry_point``, not duplicated here.
|
|
73
78
|
snowflake_file_domain_type: Optional[str] = None
|
|
74
79
|
snowflake_file_domain_name: Optional[str] = None
|
|
80
|
+
# The fully-qualified id of the ML job this run was created from, taken from
|
|
81
|
+
# the environment. ``None`` when not running inside an ML job.
|
|
82
|
+
ml_job_id: Optional[str] = None
|
|
75
83
|
|
|
76
84
|
def is_empty(self) -> bool:
|
|
77
85
|
"""Return True when there is nothing useful to send."""
|
|
@@ -80,6 +88,7 @@ class SourceInfo:
|
|
|
80
88
|
and (self.git is None or self.git.is_empty())
|
|
81
89
|
and self.snowflake_file_domain_type is None
|
|
82
90
|
and self.snowflake_file_domain_name is None
|
|
91
|
+
and self.ml_job_id is None
|
|
83
92
|
)
|
|
84
93
|
|
|
85
94
|
def to_json_dict(self) -> dict[str, Any]:
|
|
@@ -92,8 +101,9 @@ class SourceInfo:
|
|
|
92
101
|
|
|
93
102
|
Returns:
|
|
94
103
|
A JSON-serializable dict whose keys (``entry_point``, ``git``,
|
|
95
|
-
``snowflake_file_domain_type``, ``snowflake_file_domain_name
|
|
96
|
-
included only when resolved. May be empty when
|
|
104
|
+
``snowflake_file_domain_type``, ``snowflake_file_domain_name``,
|
|
105
|
+
``ml_job_id``) are included only when resolved. May be empty when
|
|
106
|
+
nothing was collected.
|
|
97
107
|
"""
|
|
98
108
|
out: dict[str, Any] = {}
|
|
99
109
|
if self.entry_point is not None and "$$" not in self.entry_point:
|
|
@@ -110,6 +120,8 @@ class SourceInfo:
|
|
|
110
120
|
out["snowflake_file_domain_type"] = self.snowflake_file_domain_type
|
|
111
121
|
if self.snowflake_file_domain_name is not None and "$$" not in self.snowflake_file_domain_name:
|
|
112
122
|
out["snowflake_file_domain_name"] = self.snowflake_file_domain_name
|
|
123
|
+
if self.ml_job_id is not None and "$$" not in self.ml_job_id:
|
|
124
|
+
out["ml_job_id"] = self.ml_job_id
|
|
113
125
|
return out
|
|
114
126
|
|
|
115
127
|
@classmethod
|
|
@@ -121,24 +133,39 @@ class SourceInfo:
|
|
|
121
133
|
be resolved or collection failed.
|
|
122
134
|
"""
|
|
123
135
|
try:
|
|
136
|
+
# An ML job id is orthogonal to how the entry point is described, so
|
|
137
|
+
# it is resolved once and attached to whichever shape is returned.
|
|
138
|
+
ml_job_id = _collect_ml_job_id()
|
|
139
|
+
|
|
124
140
|
# Snowflake-managed files (notebooks or .py workspace files) describe
|
|
125
141
|
# the running file via environment variables rather than a resolvable
|
|
126
142
|
# local path, so they are handled first and independently of the
|
|
127
143
|
# git/notebook-path machinery.
|
|
128
144
|
snowflake_file = _collect_snowflake_file()
|
|
129
145
|
if snowflake_file is not None:
|
|
130
|
-
return snowflake_file
|
|
146
|
+
return dataclasses.replace(snowflake_file, ml_job_id=ml_job_id)
|
|
131
147
|
|
|
132
148
|
# Resolve the notebook once so entry-point and git agree on the same file.
|
|
133
149
|
notebook_path = _resolve_notebook_path() if _in_ipython_kernel() else None
|
|
134
150
|
return cls(
|
|
135
151
|
entry_point=_detect_entry_point(notebook_path),
|
|
136
152
|
git=_collect_git(notebook_path),
|
|
153
|
+
ml_job_id=ml_job_id,
|
|
137
154
|
)
|
|
138
155
|
except Exception:
|
|
139
156
|
return cls()
|
|
140
157
|
|
|
141
158
|
|
|
159
|
+
def _collect_ml_job_id() -> Optional[str]:
|
|
160
|
+
"""Collect the fully-qualified id of the enclosing ML job.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
The ML job id from the environment, or ``None`` when not running inside
|
|
164
|
+
an ML job (or when the server does not expose the id).
|
|
165
|
+
"""
|
|
166
|
+
return os.environ.get(_ML_JOB_ID_ENV) or None
|
|
167
|
+
|
|
168
|
+
|
|
142
169
|
def _collect_snowflake_file() -> Optional[SourceInfo]:
|
|
143
170
|
"""Collect source info when running inside a Snowflake-managed file.
|
|
144
171
|
|
|
@@ -63,9 +63,10 @@ class ExperimentTracking:
|
|
|
63
63
|
schema_name: The name of the schema. If None, the current schema of the session
|
|
64
64
|
will be used. If there is no active schema, the PUBLIC schema will be used. Defaults to None.
|
|
65
65
|
capture_source_info: If True, each new run records best-effort source provenance — the
|
|
66
|
-
entry-point filename
|
|
67
|
-
|
|
68
|
-
run creation. Defaults to
|
|
66
|
+
entry-point filename, any surrounding git commit, branch, and remote URL, and the id
|
|
67
|
+
of the enclosing ML job when running inside one. Set to False to skip collection
|
|
68
|
+
entirely. Collection is always non-fatal and never blocks run creation. Defaults to
|
|
69
|
+
True.
|
|
69
70
|
|
|
70
71
|
Raises:
|
|
71
72
|
ValueError: If no database is provided and no active database exists in the session.
|
|
@@ -33,6 +33,12 @@ class AggregationType(Enum):
|
|
|
33
33
|
- Sketch aggregations (APPROX_COUNT_DISTINCT, APPROX_PERCENTILE): Stored as mergeable state in tiles
|
|
34
34
|
- List aggregations (LAST_N, LAST_DISTINCT_N, FIRST_N, FIRST_DISTINCT_N): Stored as arrays in tiles
|
|
35
35
|
- Secondary-key array (_SECONDARY_KEY_ARRAY): Internal-only ARRAY_AGG of the secondary-key column
|
|
36
|
+
|
|
37
|
+
Each value is the short function token used in the imperative metadata
|
|
38
|
+
tag / FeatureView JSON and in auto-generated output column names. Snowflake
|
|
39
|
+
``DESCRIBE ... TYPE = SPECIFICATION`` reports its own SQL spelling for some
|
|
40
|
+
functions (e.g. ``stddev`` for ``STD``); the declarative layer reconciles
|
|
41
|
+
that spelling on read/hash rather than changing these values.
|
|
36
42
|
"""
|
|
37
43
|
|
|
38
44
|
SUM = "sum"
|
|
@@ -50,6 +56,25 @@ class AggregationType(Enum):
|
|
|
50
56
|
FIRST_DISTINCT_N = "first_distinct_n"
|
|
51
57
|
_SECONDARY_KEY_ARRAY = "secondary_key_array"
|
|
52
58
|
|
|
59
|
+
@classmethod
|
|
60
|
+
def _missing_(cls, value: object) -> AggregationType | None:
|
|
61
|
+
"""Accept Snowflake's SPECIFICATION spelling ``stddev`` as ``STD``.
|
|
62
|
+
|
|
63
|
+
The imperative wire token stays ``"std"``; ``DESCRIBE ... TYPE =
|
|
64
|
+
SPECIFICATION`` reports ``"stddev"`` for the same function, so reads of
|
|
65
|
+
the applied spec must resolve that spelling back to ``STD``.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
value: The raw value that failed direct enum lookup.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
``STD`` when ``value`` is the string ``"stddev"`` (case-insensitive),
|
|
72
|
+
otherwise ``None`` to preserve the standard ``ValueError``.
|
|
73
|
+
"""
|
|
74
|
+
if isinstance(value, str) and value.lower() == "stddev":
|
|
75
|
+
return cls.STD
|
|
76
|
+
return None
|
|
77
|
+
|
|
53
78
|
def is_simple(self) -> bool:
|
|
54
79
|
"""Check if this is a simple aggregation (scalar result per tile).
|
|
55
80
|
|
|
@@ -223,7 +248,7 @@ class AggregationSpec:
|
|
|
223
248
|
AggregationType.VAR,
|
|
224
249
|
)
|
|
225
250
|
if self.function not in supported_lifetime_types:
|
|
226
|
-
supported_names = ", ".join(t.
|
|
251
|
+
supported_names = ", ".join(t.name for t in supported_lifetime_types)
|
|
227
252
|
raise ValueError(
|
|
228
253
|
f"Lifetime window is not supported for {self.function.value} aggregation "
|
|
229
254
|
f"'{self.output_column}'. Lifetime is only supported for: {supported_names}."
|