snowflake-ml-python 1.19.0__py3-none-any.whl → 1.21.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 +16 -0
- snowflake/ml/_internal/platform_capabilities.py +36 -0
- snowflake/ml/_internal/telemetry.py +56 -7
- snowflake/ml/data/_internal/arrow_ingestor.py +67 -2
- snowflake/ml/data/data_connector.py +103 -1
- snowflake/ml/experiment/_client/experiment_tracking_sql_client.py +8 -2
- snowflake/ml/experiment/_entities/run.py +15 -0
- snowflake/ml/experiment/callback/keras.py +25 -2
- snowflake/ml/experiment/callback/lightgbm.py +27 -2
- snowflake/ml/experiment/callback/xgboost.py +25 -2
- snowflake/ml/experiment/experiment_tracking.py +123 -13
- snowflake/ml/experiment/utils.py +6 -0
- snowflake/ml/feature_store/access_manager.py +1 -0
- snowflake/ml/feature_store/feature_store.py +1 -1
- snowflake/ml/feature_store/feature_view.py +34 -24
- snowflake/ml/jobs/_interop/protocols.py +3 -0
- snowflake/ml/jobs/_utils/feature_flags.py +1 -0
- snowflake/ml/jobs/_utils/payload_utils.py +360 -357
- snowflake/ml/jobs/_utils/scripts/mljob_launcher.py +95 -8
- snowflake/ml/jobs/_utils/scripts/start_mlruntime.sh +92 -0
- snowflake/ml/jobs/_utils/scripts/startup.sh +112 -0
- snowflake/ml/jobs/_utils/spec_utils.py +2 -406
- snowflake/ml/jobs/_utils/stage_utils.py +22 -1
- snowflake/ml/jobs/_utils/types.py +14 -7
- snowflake/ml/jobs/job.py +8 -9
- snowflake/ml/jobs/manager.py +64 -129
- snowflake/ml/model/_client/model/inference_engine_utils.py +8 -4
- snowflake/ml/model/_client/model/model_version_impl.py +109 -28
- snowflake/ml/model/_client/ops/model_ops.py +32 -6
- snowflake/ml/model/_client/ops/service_ops.py +9 -4
- snowflake/ml/model/_client/sql/service.py +69 -2
- snowflake/ml/model/_packager/model_handler.py +8 -2
- snowflake/ml/model/_packager/model_handlers/{huggingface_pipeline.py → huggingface.py} +203 -76
- snowflake/ml/model/_packager/model_handlers/mlflow.py +6 -1
- snowflake/ml/model/_packager/model_runtime/_snowml_inference_alternative_requirements.py +1 -1
- snowflake/ml/model/_signatures/core.py +305 -8
- snowflake/ml/model/_signatures/utils.py +13 -4
- snowflake/ml/model/compute_pool.py +2 -0
- snowflake/ml/model/models/huggingface.py +285 -0
- snowflake/ml/model/models/huggingface_pipeline.py +25 -215
- snowflake/ml/model/type_hints.py +5 -1
- snowflake/ml/modeling/_internal/snowpark_implementations/distributed_hpo_trainer.py +2 -2
- snowflake/ml/monitoring/_client/model_monitor_sql_client.py +12 -0
- snowflake/ml/monitoring/_manager/model_monitor_manager.py +12 -0
- snowflake/ml/monitoring/entities/model_monitor_config.py +5 -0
- snowflake/ml/utils/html_utils.py +67 -1
- snowflake/ml/version.py +1 -1
- {snowflake_ml_python-1.19.0.dist-info → snowflake_ml_python-1.21.0.dist-info}/METADATA +94 -7
- {snowflake_ml_python-1.19.0.dist-info → snowflake_ml_python-1.21.0.dist-info}/RECORD +52 -48
- {snowflake_ml_python-1.19.0.dist-info → snowflake_ml_python-1.21.0.dist-info}/WHEEL +0 -0
- {snowflake_ml_python-1.19.0.dist-info → snowflake_ml_python-1.21.0.dist-info}/licenses/LICENSE.txt +0 -0
- {snowflake_ml_python-1.19.0.dist-info → snowflake_ml_python-1.21.0.dist-info}/top_level.txt +0 -0
|
@@ -481,10 +481,280 @@ class FeatureGroupSpec(BaseFeatureSpec):
|
|
|
481
481
|
return FeatureGroupSpec(name=input_dict["name"], specs=specs, shape=shape)
|
|
482
482
|
|
|
483
483
|
|
|
484
|
+
class BaseParamSpec(ABC):
|
|
485
|
+
"""Abstract Class for specification of a parameter."""
|
|
486
|
+
|
|
487
|
+
def __init__(self, name: str, shape: Optional[tuple[int, ...]] = None) -> None:
|
|
488
|
+
self._name = name
|
|
489
|
+
|
|
490
|
+
if shape is not None and not isinstance(shape, tuple):
|
|
491
|
+
raise snowml_exceptions.SnowflakeMLException(
|
|
492
|
+
error_code=error_codes.INVALID_TYPE,
|
|
493
|
+
original_exception=TypeError("Shape should be a tuple if presented."),
|
|
494
|
+
)
|
|
495
|
+
self._shape = shape
|
|
496
|
+
|
|
497
|
+
@final
|
|
498
|
+
@property
|
|
499
|
+
def name(self) -> str:
|
|
500
|
+
"""Name of the parameter."""
|
|
501
|
+
return self._name
|
|
502
|
+
|
|
503
|
+
@final
|
|
504
|
+
@property
|
|
505
|
+
def shape(self) -> Optional[tuple[int, ...]]:
|
|
506
|
+
"""Shape of the parameter. None means scalar."""
|
|
507
|
+
return self._shape
|
|
508
|
+
|
|
509
|
+
@abstractmethod
|
|
510
|
+
def to_dict(self) -> dict[str, Any]:
|
|
511
|
+
"""Serialization"""
|
|
512
|
+
|
|
513
|
+
@classmethod
|
|
514
|
+
@abstractmethod
|
|
515
|
+
def from_dict(cls, input_dict: dict[str, Any]) -> "BaseParamSpec":
|
|
516
|
+
"""Deserialization"""
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
class ParamSpec(BaseParamSpec):
|
|
520
|
+
"""Specification of a parameter in Snowflake native model packaging."""
|
|
521
|
+
|
|
522
|
+
def __init__(
|
|
523
|
+
self,
|
|
524
|
+
name: str,
|
|
525
|
+
dtype: DataType,
|
|
526
|
+
default_value: Any,
|
|
527
|
+
shape: Optional[tuple[int, ...]] = None,
|
|
528
|
+
) -> None:
|
|
529
|
+
"""Initialize a parameter.
|
|
530
|
+
|
|
531
|
+
Args:
|
|
532
|
+
name: Name of the parameter.
|
|
533
|
+
dtype: Type of the parameter.
|
|
534
|
+
default_value: Default value of the parameter.
|
|
535
|
+
shape: Shape of the parameter. None means scalar, otherwise a tuple
|
|
536
|
+
representing dimensions. Use -1 for variable length dimensions.
|
|
537
|
+
"""
|
|
538
|
+
super().__init__(name=name, shape=shape)
|
|
539
|
+
|
|
540
|
+
self._validate_default_value(dtype, default_value, shape)
|
|
541
|
+
self._dtype = dtype
|
|
542
|
+
self._default_value = default_value
|
|
543
|
+
|
|
544
|
+
@staticmethod
|
|
545
|
+
def _validate_default_value(dtype: DataType, default_value: Any, shape: Optional[tuple[int, ...]]) -> None:
|
|
546
|
+
"""Validate that default_value is compatible with dtype and shape.
|
|
547
|
+
|
|
548
|
+
Args:
|
|
549
|
+
dtype: The expected data type.
|
|
550
|
+
default_value: The default value to validate. None is allowed and means no default.
|
|
551
|
+
shape: The expected shape. None means scalar.
|
|
552
|
+
|
|
553
|
+
Raises:
|
|
554
|
+
SnowflakeMLException: ValueError: When the default_value is not compatible with dtype/shape.
|
|
555
|
+
"""
|
|
556
|
+
if default_value is None:
|
|
557
|
+
return
|
|
558
|
+
|
|
559
|
+
try:
|
|
560
|
+
arr = np.array(default_value, dtype=dtype._numpy_type)
|
|
561
|
+
|
|
562
|
+
# Validate shape compatibility
|
|
563
|
+
if shape is None:
|
|
564
|
+
# Scalar expected
|
|
565
|
+
if arr.ndim != 0:
|
|
566
|
+
raise snowml_exceptions.SnowflakeMLException(
|
|
567
|
+
error_code=error_codes.INVALID_ARGUMENT,
|
|
568
|
+
original_exception=ValueError(f"Expected scalar value, got array with shape {arr.shape}"),
|
|
569
|
+
)
|
|
570
|
+
else:
|
|
571
|
+
# Non-scalar expected
|
|
572
|
+
if arr.ndim != len(shape):
|
|
573
|
+
raise snowml_exceptions.SnowflakeMLException(
|
|
574
|
+
error_code=error_codes.INVALID_ARGUMENT,
|
|
575
|
+
original_exception=ValueError(
|
|
576
|
+
f"Expected {len(shape)}-dimensional value, got {arr.ndim}-dimensional"
|
|
577
|
+
),
|
|
578
|
+
)
|
|
579
|
+
# Check each dimension (-1 means variable length)
|
|
580
|
+
for i, (expected, actual) in enumerate(zip(shape, arr.shape)):
|
|
581
|
+
if expected != -1 and expected != actual:
|
|
582
|
+
raise snowml_exceptions.SnowflakeMLException(
|
|
583
|
+
error_code=error_codes.INVALID_ARGUMENT,
|
|
584
|
+
original_exception=ValueError(f"Dimension {i}: expected {expected}, got {actual}"),
|
|
585
|
+
)
|
|
586
|
+
|
|
587
|
+
except (ValueError, TypeError, OverflowError) as e:
|
|
588
|
+
raise snowml_exceptions.SnowflakeMLException(
|
|
589
|
+
error_code=error_codes.INVALID_ARGUMENT,
|
|
590
|
+
original_exception=ValueError(
|
|
591
|
+
f"Default value {repr(default_value)} (type: {type(default_value).__name__}) "
|
|
592
|
+
f"is not compatible with dtype {dtype} and shape {shape}. {str(e)}"
|
|
593
|
+
),
|
|
594
|
+
)
|
|
595
|
+
|
|
596
|
+
@property
|
|
597
|
+
def dtype(self) -> DataType:
|
|
598
|
+
"""Type of the parameter."""
|
|
599
|
+
return self._dtype
|
|
600
|
+
|
|
601
|
+
@property
|
|
602
|
+
def default_value(self) -> Any:
|
|
603
|
+
"""Default value of the parameter."""
|
|
604
|
+
return self._default_value
|
|
605
|
+
|
|
606
|
+
def to_dict(self) -> dict[str, Any]:
|
|
607
|
+
"""Serialize the parameter specification into a dict.
|
|
608
|
+
|
|
609
|
+
Returns:
|
|
610
|
+
A dict that serializes the parameter specification.
|
|
611
|
+
"""
|
|
612
|
+
result: dict[str, Any] = {
|
|
613
|
+
"name": self._name,
|
|
614
|
+
"dtype": self._dtype.name,
|
|
615
|
+
"default_value": self._default_value,
|
|
616
|
+
}
|
|
617
|
+
if self._shape is not None:
|
|
618
|
+
result["shape"] = self._shape
|
|
619
|
+
return result
|
|
620
|
+
|
|
621
|
+
@classmethod
|
|
622
|
+
def from_dict(cls, input_dict: dict[str, Any]) -> "ParamSpec":
|
|
623
|
+
"""Deserialize the parameter specification from a dict.
|
|
624
|
+
|
|
625
|
+
Args:
|
|
626
|
+
input_dict: The dict containing information of the parameter specification.
|
|
627
|
+
|
|
628
|
+
Returns:
|
|
629
|
+
ParamSpec: The deserialized parameter specification.
|
|
630
|
+
"""
|
|
631
|
+
shape = input_dict.get("shape", None)
|
|
632
|
+
if shape is not None:
|
|
633
|
+
shape = tuple(shape)
|
|
634
|
+
return ParamSpec(
|
|
635
|
+
name=input_dict["name"],
|
|
636
|
+
dtype=DataType[input_dict["dtype"]],
|
|
637
|
+
default_value=input_dict["default_value"],
|
|
638
|
+
shape=shape,
|
|
639
|
+
)
|
|
640
|
+
|
|
641
|
+
def __eq__(self, other: object) -> bool:
|
|
642
|
+
if isinstance(other, ParamSpec):
|
|
643
|
+
return (
|
|
644
|
+
self._name == other._name
|
|
645
|
+
and self._dtype == other._dtype
|
|
646
|
+
and np.array_equal(self._default_value, other._default_value)
|
|
647
|
+
and self._shape == other._shape
|
|
648
|
+
)
|
|
649
|
+
else:
|
|
650
|
+
return False
|
|
651
|
+
|
|
652
|
+
def __repr__(self) -> str:
|
|
653
|
+
shape_str = f", shape={repr(self._shape)}" if self._shape else ""
|
|
654
|
+
return (
|
|
655
|
+
f"ParamSpec(name={repr(self._name)}, dtype={repr(self._dtype)}, "
|
|
656
|
+
f"default_value={repr(self._default_value)}{shape_str})"
|
|
657
|
+
)
|
|
658
|
+
|
|
659
|
+
@classmethod
|
|
660
|
+
def from_mlflow_spec(cls, param_spec: "mlflow.types.ParamSpec") -> "ParamSpec":
|
|
661
|
+
return ParamSpec(
|
|
662
|
+
name=param_spec.name,
|
|
663
|
+
dtype=DataType.from_numpy_type(param_spec.dtype.to_numpy()),
|
|
664
|
+
default_value=param_spec.default,
|
|
665
|
+
)
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
class ParamGroupSpec(BaseParamSpec):
|
|
669
|
+
"""Specification of a group of parameters in Snowflake native model packaging."""
|
|
670
|
+
|
|
671
|
+
def __init__(
|
|
672
|
+
self,
|
|
673
|
+
name: str,
|
|
674
|
+
specs: list[BaseParamSpec],
|
|
675
|
+
shape: Optional[tuple[int, ...]] = None,
|
|
676
|
+
) -> None:
|
|
677
|
+
"""Initialize a parameter group.
|
|
678
|
+
|
|
679
|
+
Args:
|
|
680
|
+
name: Name of the parameter group.
|
|
681
|
+
specs: A list of parameter specifications that composes the group.
|
|
682
|
+
shape: Shape of the parameter group. None means scalar, otherwise a tuple
|
|
683
|
+
representing dimensions. Use -1 for variable length dimensions.
|
|
684
|
+
"""
|
|
685
|
+
super().__init__(name=name, shape=shape)
|
|
686
|
+
self._specs = specs
|
|
687
|
+
self._validate()
|
|
688
|
+
|
|
689
|
+
def _validate(self) -> None:
|
|
690
|
+
if len(self._specs) == 0:
|
|
691
|
+
raise snowml_exceptions.SnowflakeMLException(
|
|
692
|
+
error_code=error_codes.INVALID_ARGUMENT, original_exception=ValueError("No children param specs.")
|
|
693
|
+
)
|
|
694
|
+
|
|
695
|
+
@property
|
|
696
|
+
def specs(self) -> list[BaseParamSpec]:
|
|
697
|
+
"""List of parameter specifications in the group."""
|
|
698
|
+
return self._specs
|
|
699
|
+
|
|
700
|
+
def __eq__(self, other: object) -> bool:
|
|
701
|
+
if isinstance(other, ParamGroupSpec):
|
|
702
|
+
return self._name == other._name and self._specs == other._specs and self._shape == other._shape
|
|
703
|
+
return False
|
|
704
|
+
|
|
705
|
+
def __repr__(self) -> str:
|
|
706
|
+
spec_strs = ",\n\t\t".join(repr(spec) for spec in self._specs)
|
|
707
|
+
shape_str = f",\nshape={repr(self._shape)}" if self._shape else ""
|
|
708
|
+
return textwrap.dedent(
|
|
709
|
+
f"""ParamGroupSpec(
|
|
710
|
+
name={repr(self._name)},
|
|
711
|
+
specs=[
|
|
712
|
+
{spec_strs}
|
|
713
|
+
]{shape_str}
|
|
714
|
+
)
|
|
715
|
+
"""
|
|
716
|
+
)
|
|
717
|
+
|
|
718
|
+
def to_dict(self) -> dict[str, Any]:
|
|
719
|
+
"""Serialize the parameter group into a dict.
|
|
720
|
+
|
|
721
|
+
Returns:
|
|
722
|
+
A dict that serializes the parameter group.
|
|
723
|
+
"""
|
|
724
|
+
result: dict[str, Any] = {"name": self._name, "specs": [s.to_dict() for s in self._specs]}
|
|
725
|
+
if self._shape is not None:
|
|
726
|
+
result["shape"] = self._shape
|
|
727
|
+
return result
|
|
728
|
+
|
|
729
|
+
@classmethod
|
|
730
|
+
def from_dict(cls, input_dict: dict[str, Any]) -> "ParamGroupSpec":
|
|
731
|
+
"""Deserialize the parameter group from a dict.
|
|
732
|
+
|
|
733
|
+
Args:
|
|
734
|
+
input_dict: The dict containing information of the parameter group.
|
|
735
|
+
|
|
736
|
+
Returns:
|
|
737
|
+
A parameter group instance deserialized and created from the dict.
|
|
738
|
+
"""
|
|
739
|
+
specs: list[BaseParamSpec] = []
|
|
740
|
+
for e in input_dict["specs"]:
|
|
741
|
+
spec: BaseParamSpec = ParamGroupSpec.from_dict(e) if "specs" in e else ParamSpec.from_dict(e)
|
|
742
|
+
specs.append(spec)
|
|
743
|
+
shape = input_dict.get("shape", None)
|
|
744
|
+
if shape is not None:
|
|
745
|
+
shape = tuple(shape)
|
|
746
|
+
return ParamGroupSpec(name=input_dict["name"], specs=specs, shape=shape)
|
|
747
|
+
|
|
748
|
+
|
|
484
749
|
class ModelSignature:
|
|
485
750
|
"""Signature of a model that specifies the input and output of a model."""
|
|
486
751
|
|
|
487
|
-
def __init__(
|
|
752
|
+
def __init__(
|
|
753
|
+
self,
|
|
754
|
+
inputs: Sequence[BaseFeatureSpec],
|
|
755
|
+
outputs: Sequence[BaseFeatureSpec],
|
|
756
|
+
params: Optional[Sequence[BaseParamSpec]] = None,
|
|
757
|
+
) -> None:
|
|
488
758
|
"""Initialize a model signature.
|
|
489
759
|
|
|
490
760
|
Args:
|
|
@@ -492,9 +762,12 @@ class ModelSignature:
|
|
|
492
762
|
the input of the model.
|
|
493
763
|
outputs: A sequence of feature specifications and feature group specifications that will compose
|
|
494
764
|
the output of the model.
|
|
765
|
+
params: A sequence of parameter specifications and parameter group specifications that will compose
|
|
766
|
+
the parameters of the model. Defaults to None.
|
|
495
767
|
"""
|
|
496
768
|
self._inputs = inputs
|
|
497
769
|
self._outputs = outputs
|
|
770
|
+
self._params = params or []
|
|
498
771
|
|
|
499
772
|
@property
|
|
500
773
|
def inputs(self) -> Sequence[BaseFeatureSpec]:
|
|
@@ -506,9 +779,18 @@ class ModelSignature:
|
|
|
506
779
|
"""Outputs of the model, containing a sequence of feature specifications and feature group specifications."""
|
|
507
780
|
return self._outputs
|
|
508
781
|
|
|
782
|
+
@property
|
|
783
|
+
def params(self) -> Sequence[BaseParamSpec]:
|
|
784
|
+
"""Parameters of the model, containing a sequence of parameter specifications."""
|
|
785
|
+
return self._params
|
|
786
|
+
|
|
509
787
|
def __eq__(self, other: object) -> bool:
|
|
510
788
|
if isinstance(other, ModelSignature):
|
|
511
|
-
return
|
|
789
|
+
return (
|
|
790
|
+
self._inputs == other._inputs
|
|
791
|
+
and self._outputs == other._outputs
|
|
792
|
+
and getattr(other, "_params", []) == self._params # handles backward compatibility
|
|
793
|
+
)
|
|
512
794
|
else:
|
|
513
795
|
return False
|
|
514
796
|
|
|
@@ -522,6 +804,7 @@ class ModelSignature:
|
|
|
522
804
|
return {
|
|
523
805
|
"inputs": [spec.to_dict() for spec in self._inputs],
|
|
524
806
|
"outputs": [spec.to_dict() for spec in self._outputs],
|
|
807
|
+
"params": [spec.to_dict() for spec in self._params],
|
|
525
808
|
}
|
|
526
809
|
|
|
527
810
|
@classmethod
|
|
@@ -536,18 +819,26 @@ class ModelSignature:
|
|
|
536
819
|
"""
|
|
537
820
|
sig_outs = loaded["outputs"]
|
|
538
821
|
sig_inputs = loaded["inputs"]
|
|
822
|
+
# If parameters is not provided, default to empty list for backward compatibility.
|
|
823
|
+
sig_params = loaded.get("params", [])
|
|
539
824
|
|
|
540
825
|
deserialize_spec: Callable[[dict[str, Any]], BaseFeatureSpec] = lambda sig_spec: (
|
|
541
826
|
FeatureGroupSpec.from_dict(sig_spec) if "specs" in sig_spec else FeatureSpec.from_dict(sig_spec)
|
|
542
827
|
)
|
|
828
|
+
deserialize_param: Callable[[dict[str, Any]], BaseParamSpec] = lambda sig_param: (
|
|
829
|
+
ParamGroupSpec.from_dict(sig_param) if "specs" in sig_param else ParamSpec.from_dict(sig_param)
|
|
830
|
+
)
|
|
543
831
|
|
|
544
832
|
return ModelSignature(
|
|
545
|
-
inputs=[deserialize_spec(s) for s in sig_inputs],
|
|
833
|
+
inputs=[deserialize_spec(s) for s in sig_inputs],
|
|
834
|
+
outputs=[deserialize_spec(s) for s in sig_outs],
|
|
835
|
+
params=[deserialize_param(s) for s in sig_params],
|
|
546
836
|
)
|
|
547
837
|
|
|
548
838
|
def __repr__(self) -> str:
|
|
549
839
|
inputs_spec_strs = ",\n\t\t".join(repr(spec) for spec in self._inputs)
|
|
550
840
|
outputs_spec_strs = ",\n\t\t".join(repr(spec) for spec in self._outputs)
|
|
841
|
+
params_spec_strs = ",\n\t\t".join(repr(spec) for spec in self._params)
|
|
551
842
|
return textwrap.dedent(
|
|
552
843
|
f"""ModelSignature(
|
|
553
844
|
inputs=[
|
|
@@ -555,6 +846,9 @@ class ModelSignature:
|
|
|
555
846
|
],
|
|
556
847
|
outputs=[
|
|
557
848
|
{outputs_spec_strs}
|
|
849
|
+
],
|
|
850
|
+
params=[
|
|
851
|
+
{params_spec_strs}
|
|
558
852
|
]
|
|
559
853
|
)"""
|
|
560
854
|
)
|
|
@@ -570,15 +864,17 @@ class ModelSignature:
|
|
|
570
864
|
# Create collapsible sections for inputs and outputs
|
|
571
865
|
inputs_content = html_utils.create_features_html(self.inputs, "Input")
|
|
572
866
|
outputs_content = html_utils.create_features_html(self.outputs, "Output")
|
|
573
|
-
|
|
867
|
+
params_content = html_utils.create_parameters_html(self.params, "Parameter")
|
|
574
868
|
inputs_section = html_utils.create_collapsible_section("Inputs", inputs_content, open_by_default=True)
|
|
575
869
|
outputs_section = html_utils.create_collapsible_section("Outputs", outputs_content, open_by_default=True)
|
|
870
|
+
params_section = html_utils.create_collapsible_section("Parameters", params_content, open_by_default=True)
|
|
576
871
|
|
|
577
872
|
content = f"""
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
873
|
+
<div style="margin-top: 10px;">
|
|
874
|
+
{inputs_section}
|
|
875
|
+
{outputs_section}
|
|
876
|
+
{params_section}
|
|
877
|
+
</div>
|
|
582
878
|
"""
|
|
583
879
|
|
|
584
880
|
return html_utils.create_base_container("Model Signature", content)
|
|
@@ -593,4 +889,5 @@ class ModelSignature:
|
|
|
593
889
|
FeatureSpec.from_mlflow_spec(spec, f"output_feature_{idx}")
|
|
594
890
|
for idx, spec in enumerate(mlflow_sig.outputs)
|
|
595
891
|
],
|
|
892
|
+
params=[ParamSpec.from_mlflow_spec(spec) for spec in mlflow_sig.params or []],
|
|
596
893
|
)
|
|
@@ -20,15 +20,21 @@ def convert_list_to_ndarray(data: list[Any]) -> npt.NDArray[Any]:
|
|
|
20
20
|
|
|
21
21
|
Raises:
|
|
22
22
|
SnowflakeMLException: ValueError: Raised when ragged nested list or list containing non-basic type confronted.
|
|
23
|
-
SnowflakeMLException: ValueError: Raised when ragged nested list or list containing non-basic type confronted.
|
|
24
23
|
|
|
25
24
|
Returns:
|
|
26
25
|
The converted numpy array.
|
|
27
26
|
"""
|
|
28
|
-
|
|
27
|
+
# VisibleDeprecationWarning was removed in numpy>2
|
|
28
|
+
visible_deprecation_warning = getattr(np, "VisibleDeprecationWarning", None)
|
|
29
|
+
exception_types = (ValueError,)
|
|
30
|
+
|
|
31
|
+
if visible_deprecation_warning is not None:
|
|
32
|
+
warnings.filterwarnings("error", category=visible_deprecation_warning)
|
|
33
|
+
exception_types = (visible_deprecation_warning, ValueError) # type: ignore[assignment]
|
|
34
|
+
|
|
29
35
|
try:
|
|
30
36
|
arr = np.array(data)
|
|
31
|
-
except
|
|
37
|
+
except exception_types:
|
|
32
38
|
# In recent version of numpy, this warning should be raised when bad list provided.
|
|
33
39
|
raise snowml_exceptions.SnowflakeMLException(
|
|
34
40
|
error_code=error_codes.INVALID_DATA,
|
|
@@ -36,7 +42,10 @@ def convert_list_to_ndarray(data: list[Any]) -> npt.NDArray[Any]:
|
|
|
36
42
|
f"Unable to construct signature: Ragged nested or Unsupported list-like data {data} confronted."
|
|
37
43
|
),
|
|
38
44
|
)
|
|
39
|
-
|
|
45
|
+
finally:
|
|
46
|
+
if visible_deprecation_warning is not None:
|
|
47
|
+
warnings.filterwarnings("default", category=visible_deprecation_warning)
|
|
48
|
+
|
|
40
49
|
if arr.dtype == object:
|
|
41
50
|
# If not raised, then a array of object would be created.
|
|
42
51
|
raise snowml_exceptions.SnowflakeMLException(
|