frogml 1.2.49__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.
- frogml/__init__.py +1 -1
- frogml/core/clients/batch_job_management/client.py +269 -257
- frogml/core/clients/batch_job_management/executions_config.py +10 -3
- frogml/core/clients/build_orchestrator/build_model_request_getter.py +7 -1
- frogml/core/clients/build_orchestrator/client.py +108 -67
- frogml/core/clients/build_orchestrator/internal_client.py +42 -38
- frogml/core/clients/feature_store/management_client.py +58 -39
- frogml/core/clients/feature_store/operator_client.py +6 -4
- frogml/core/clients/model_group_management/client.py +5 -2
- frogml/core/clients/model_management/client.py +25 -8
- frogml/core/clients/model_version_manager/build_model_version_dto.py +4 -1
- frogml/core/clients/model_version_manager/client.py +67 -68
- frogml/core/exceptions/__init__.py +20 -2
- frogml/core/exceptions/frogml_exception.py +35 -5
- frogml/core/exceptions/frogml_general_build_exception.py +19 -11
- frogml/core/exceptions/frogml_grpc_address_exception.py +15 -4
- frogml/core/exceptions/frogml_http_exception.py +3 -1
- frogml/core/exceptions/frogml_login_exception.py +16 -5
- frogml/core/exceptions/frogml_not_found_exception.py +16 -3
- frogml/core/exceptions/frogml_remote_build_failed.py +1 -1
- frogml/core/exceptions/frogml_token_exception.py +17 -5
- frogml/core/exceptions/grpc_status_mapping.py +43 -0
- frogml/core/inner/build_logic/phases/phase_010_fetch_model/fetch_strategy_manager/strategy/git/git_strategy.py +10 -2
- frogml/core/inner/build_logic/phases/phase_010_fetch_model/pre_fetch_validation_step.py +3 -2
- frogml/core/inner/build_logic/phases/phase_020_remote_register_frogml_build/upload_step.py +13 -10
- frogml/core/inner/build_logic/run_handlers/programmatic_phase_run_handler.py +8 -3
- frogml/core/inner/build_logic/tools/files.py +1 -2
- frogml/core/inner/model_loggers_utils.py +21 -8
- frogml/core/inner/tool/auth/auth_client.py +1 -1
- frogml/core/inner/tool/grpc/grpc_try_wrapping.py +51 -72
- frogml/core/inner/tool/protobuf_factory.py +8 -2
- frogml/sdk/frogml_client/client.py +29 -10
- frogml/sdk/model/adapters/input_adapters/numpy_input_adapter.py +6 -1
- frogml/sdk/model/adapters/output_adapters/numpy_output_adapter.py +4 -1
- frogml/sdk/model/decorators/api.py +6 -1
- frogml/sdk/model/tools/adapters/output.py +6 -2
- frogml/sdk/model_version/catboost/__init__.py +4 -1
- frogml/sdk/model_version/huggingface/__init__.py +4 -1
- frogml/sdk/model_version/model_loggers/catboost_model_version_manager.py +4 -1
- frogml/sdk/model_version/model_loggers/huggingface_model_version_manager.py +10 -2
- frogml/sdk/model_version/model_loggers/onnx_model_version_manager.py +4 -1
- frogml/sdk/model_version/model_loggers/pytorch_model_version_manager.py +4 -1
- frogml/sdk/model_version/model_loggers/scikit_learn_model_version_manager.py +4 -1
- frogml/sdk/model_version/onnx/__init__.py +4 -1
- frogml/sdk/model_version/pytorch/__init__.py +4 -1
- frogml/sdk/model_version/scikit_learn/__init__.py +4 -1
- frogml/sdk/model_version/utils/jml/customer_client.py +1 -1
- frogml/sdk/model_version/utils/storage.py +4 -1
- frogml/sdk/model_version/utils/validations.py +10 -2
- {frogml-1.2.49.dist-info → frogml-2.0.0.dist-info}/METADATA +1 -1
- {frogml-1.2.49.dist-info → frogml-2.0.0.dist-info}/RECORD +58 -61
- frogml_services_mock/mocks/batch_job_manager_service.py +11 -9
- frogml_services_mock/mocks/build_orchestrator_service_api.py +4 -0
- frogml_services_mock/mocks/ecosystem_service_api.py +1 -2
- frogml_services_mock/mocks/model_group_management_service.py +20 -9
- frogml_services_mock/mocks/model_version_manager_service.py +3 -1
- frogml_services_mock/mocks/project_manager_service.py +6 -2
- frogml/core/exceptions/frogml_decode_exception.py +0 -7
- frogml/core/exceptions/frogml_external_exception.py +0 -11
- frogml/core/exceptions/frogml_load_model_failed_exception.py +0 -10
- frogml/core/exceptions/quiet_error.py +0 -22
- {frogml-1.2.49.dist-info → frogml-2.0.0.dist-info}/WHEEL +0 -0
|
@@ -1,34 +1,32 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
import inspect
|
|
3
|
+
from http import HTTPStatus
|
|
3
4
|
from inspect import BoundArguments, Signature
|
|
4
5
|
from typing import Any, Callable, Optional
|
|
5
6
|
|
|
6
7
|
import grpc
|
|
7
8
|
from frogml.core.exceptions import FrogmlException
|
|
9
|
+
from frogml.core.exceptions.grpc_status_mapping import grpc_to_http_status
|
|
8
10
|
from frogml.storage.logging import logger
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
def grpc_try_catch_wrapper(
|
|
12
|
-
|
|
13
|
-
reraise_non_grpc_error_original_exception: Optional[bool] = False,
|
|
14
|
+
error_message: str, operation: str = "FrogML Operation"
|
|
14
15
|
) -> Callable:
|
|
15
16
|
"""A decorator for handling exceptions in client methods.
|
|
16
17
|
|
|
17
18
|
This decorator wraps a function, catching any `grpc.RpcError` or other
|
|
18
|
-
`Exception
|
|
19
|
-
static string or a template formatted with the decorated function's
|
|
20
|
-
runtime arguments.
|
|
19
|
+
`Exception` and re-raises them as a `FrogmlException` with consistent formatting.
|
|
21
20
|
|
|
22
21
|
Parameters
|
|
23
22
|
----------
|
|
24
|
-
|
|
23
|
+
error_message : str
|
|
25
24
|
The error message template. This can be a static string or a format
|
|
26
25
|
string using placeholders that match the decorated function's
|
|
27
26
|
parameter names (e.g., "Failed on item {item_id}").
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
exceptions are wrapped in `FrogmlException`.
|
|
27
|
+
operation : str, optional
|
|
28
|
+
The operation name for error display (e.g., "Delete Model").
|
|
29
|
+
Defaults to "FrogML Operation".
|
|
32
30
|
|
|
33
31
|
Returns
|
|
34
32
|
-------
|
|
@@ -38,40 +36,16 @@ def grpc_try_catch_wrapper(
|
|
|
38
36
|
Raises
|
|
39
37
|
------
|
|
40
38
|
FrogmlException
|
|
41
|
-
Raised when the decorated function encounters any exception
|
|
42
|
-
`reraise_non_grpc_error_original_exception` is `True` and the error
|
|
43
|
-
is not a `grpc.RpcError`. The new exception's message is formatted
|
|
44
|
-
and includes details from the original error.
|
|
45
|
-
Exception
|
|
46
|
-
The original non-gRPC exception is re-raised if
|
|
47
|
-
`reraise_non_grpc_error_original_exception` is set to `True`.
|
|
39
|
+
Raised when the decorated function encounters any exception.
|
|
48
40
|
|
|
49
41
|
Usage
|
|
50
42
|
-----
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
Use placeholders matching the function's parameter names to create
|
|
56
|
-
context-specific error messages.
|
|
57
|
-
|
|
58
|
-
@grpc_try_catch_wrapper("Failed to delete version {version_number} for FeatureSet {featureset_name}")
|
|
43
|
+
@grpc_try_catch_wrapper(
|
|
44
|
+
error_message="Failed to delete version {version_number} for FeatureSet {featureset_name}",
|
|
45
|
+
operation="Delete FeatureSet Version"
|
|
46
|
+
)
|
|
59
47
|
def delete_featureset_version(self, featureset_name: str, version_number: int):
|
|
60
48
|
# ... gRPC call ...
|
|
61
|
-
|
|
62
|
-
If this function fails with a gRPC error, a `FrogmlException` is raised with a message like:
|
|
63
|
-
`"Failed to delete version 2 for FeatureSet customer_churn - <original gRPC error code> - <original gRPC error details>."`
|
|
64
|
-
|
|
65
|
-
**2. Static Error Messages**
|
|
66
|
-
|
|
67
|
-
When no dynamic context is needed, a simple string is sufficient.
|
|
68
|
-
|
|
69
|
-
@grpc_try_catch_wrapper("Failed to retrieve featuresets mapping")
|
|
70
|
-
def get_featuresets_mapping(self):
|
|
71
|
-
# ... gRPC call ...
|
|
72
|
-
|
|
73
|
-
If this fails, the `FrogmlException` message will be:
|
|
74
|
-
`"Failed to retrieve featuresets mapping - <original gRPC error code> - <original gRPC error details>."`
|
|
75
49
|
"""
|
|
76
50
|
|
|
77
51
|
def decorator(function: Callable):
|
|
@@ -79,51 +53,56 @@ def grpc_try_catch_wrapper(
|
|
|
79
53
|
def _inner_wrapper(*args, **kwargs):
|
|
80
54
|
try:
|
|
81
55
|
return function(*args, **kwargs)
|
|
82
|
-
except grpc.RpcError as e:
|
|
83
|
-
error_message: str = __get_error_msg(
|
|
84
|
-
exception_message=exception_message, e=e
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
formatted_message: str = __get_formatted_error_message(
|
|
88
|
-
exception_message=error_message,
|
|
89
|
-
function=function,
|
|
90
|
-
args=args,
|
|
91
|
-
kwargs=kwargs,
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
raise FrogmlException(formatted_message) from e
|
|
95
|
-
|
|
96
56
|
except Exception as e:
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
formatted_message = __get_formatted_error_message(
|
|
101
|
-
exception_message=exception_message,
|
|
102
|
-
function=function,
|
|
103
|
-
args=args,
|
|
104
|
-
kwargs=kwargs,
|
|
105
|
-
)
|
|
106
|
-
raise FrogmlException(f"{formatted_message}. Error is: {e}.") from e
|
|
57
|
+
raise _build_exception(
|
|
58
|
+
e, error_message, operation, function, args, kwargs
|
|
59
|
+
) from e
|
|
107
60
|
|
|
108
61
|
return _inner_wrapper
|
|
109
62
|
|
|
110
63
|
return decorator
|
|
111
64
|
|
|
112
65
|
|
|
113
|
-
def
|
|
114
|
-
|
|
115
|
-
|
|
66
|
+
def _build_exception(
|
|
67
|
+
e: Exception,
|
|
68
|
+
error_message: str,
|
|
69
|
+
operation: str,
|
|
70
|
+
function: Callable,
|
|
71
|
+
args: tuple,
|
|
72
|
+
kwargs: dict,
|
|
73
|
+
) -> FrogmlException:
|
|
74
|
+
"""Build a FrogmlException from the caught exception."""
|
|
75
|
+
if isinstance(e, grpc.RpcError):
|
|
76
|
+
message: str = __get_error_msg(error_message, e)
|
|
77
|
+
grpc_code: Optional[grpc.StatusCode] = e.code() if hasattr(e, "code") else None
|
|
78
|
+
status_code: int = grpc_to_http_status(grpc_code)
|
|
79
|
+
else:
|
|
80
|
+
exception_type: str = type(e).__name__ # e.g., "ValueError", "TypeError"
|
|
81
|
+
message = f"{error_message}: {exception_type}: {e}"
|
|
82
|
+
status_code = HTTPStatus.INTERNAL_SERVER_ERROR
|
|
83
|
+
|
|
84
|
+
formatted_message: str = __get_formatted_error_message(
|
|
85
|
+
message, function, args, kwargs
|
|
86
|
+
)
|
|
87
|
+
return FrogmlException(
|
|
88
|
+
error_message=formatted_message,
|
|
89
|
+
status_code=status_code,
|
|
90
|
+
operation=operation,
|
|
116
91
|
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def __get_error_msg(error_message: str, e: grpc.RpcError) -> str:
|
|
95
|
+
err_msg: str = error_message
|
|
117
96
|
if hasattr(e, "details") and e.details() is not None:
|
|
118
|
-
err_msg
|
|
97
|
+
err_msg = f"{err_msg}: {e.details()}"
|
|
119
98
|
elif hasattr(e, "debug_error_string"):
|
|
120
|
-
err_msg
|
|
99
|
+
err_msg = f"{err_msg}: {e.debug_error_string()}"
|
|
121
100
|
logger.debug(f"{err_msg}: {e}")
|
|
122
101
|
return err_msg
|
|
123
102
|
|
|
124
103
|
|
|
125
104
|
def __get_formatted_error_message(
|
|
126
|
-
|
|
105
|
+
error_message: str, function: Callable, args: tuple[Any], kwargs: dict[str, Any]
|
|
127
106
|
) -> str:
|
|
128
107
|
"""Formats an error message string with the runtime arguments of a function.
|
|
129
108
|
|
|
@@ -131,7 +110,7 @@ def __get_formatted_error_message(
|
|
|
131
110
|
to their parameter names, then uses them to format the message string.
|
|
132
111
|
|
|
133
112
|
Args:
|
|
134
|
-
|
|
113
|
+
error_message (str): The error message template with placeholders.
|
|
135
114
|
function (Callable): The decorated function.
|
|
136
115
|
args (tuple[Any]): The positional arguments passed to the function.
|
|
137
116
|
kwargs (dict[str, Any]): The keyword arguments passed to the function.
|
|
@@ -144,7 +123,7 @@ def __get_formatted_error_message(
|
|
|
144
123
|
bound_args: BoundArguments = sig.bind(*args, **kwargs)
|
|
145
124
|
bound_args.apply_defaults()
|
|
146
125
|
|
|
147
|
-
return
|
|
126
|
+
return error_message.format(**bound_args.arguments)
|
|
148
127
|
except (ValueError, KeyError, TypeError):
|
|
149
128
|
# Fallback if formatting fails (e.g., missing key in template)
|
|
150
|
-
return
|
|
129
|
+
return error_message
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from frogml.core.exceptions import FrogmlException
|
|
2
|
+
from http import HTTPStatus
|
|
2
3
|
|
|
3
4
|
|
|
4
5
|
def protobuf_factory(
|
|
@@ -12,13 +13,18 @@ def protobuf_factory(
|
|
|
12
13
|
unrecognized_fields = included_fields.difference(all_field_names)
|
|
13
14
|
if unrecognized_fields:
|
|
14
15
|
raise FrogmlException(
|
|
15
|
-
f"Unknown fields were included: {list(unrecognized_fields)}"
|
|
16
|
+
error_message=f"Unknown fields were included: {list(unrecognized_fields)}",
|
|
17
|
+
operation="Convert to Protobuf",
|
|
16
18
|
)
|
|
17
19
|
return included_fields.difference(excluded_fields)
|
|
18
20
|
|
|
19
21
|
def protofy_decorator(cls):
|
|
20
22
|
if not hasattr(cls, "__dataclass_fields__"):
|
|
21
|
-
raise FrogmlException(
|
|
23
|
+
raise FrogmlException(
|
|
24
|
+
error_message="Protofy must receive a dataclass",
|
|
25
|
+
status_code=HTTPStatus.BAD_REQUEST,
|
|
26
|
+
operation="Convert to Protobuf",
|
|
27
|
+
)
|
|
22
28
|
|
|
23
29
|
fields_mapping = mapping if mapping else {}
|
|
24
30
|
final_field_names = get_final_field_names(cls)
|
|
@@ -3,6 +3,7 @@ from functools import lru_cache
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from tempfile import TemporaryDirectory
|
|
5
5
|
from typing import TYPE_CHECKING, Dict, List, Optional, Union, Iterable
|
|
6
|
+
from http import HTTPStatus
|
|
6
7
|
|
|
7
8
|
import requests
|
|
8
9
|
from requests import Response
|
|
@@ -146,12 +147,14 @@ class FrogMLClient:
|
|
|
146
147
|
str: The build ID of the latest build according to the build status. None if no builds match the filter.
|
|
147
148
|
|
|
148
149
|
"""
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
valid_statuses = set(
|
|
151
|
+
DESCRIPTOR.enum_types_by_name["BuildStatus"].values_by_name.keys()
|
|
152
|
+
)
|
|
153
|
+
if build_status not in valid_statuses:
|
|
153
154
|
raise FrogmlException(
|
|
154
|
-
f"Invalid build status {build_status}. Valid options are
|
|
155
|
+
error_message=f"Invalid build status '{build_status}'. Valid options are: {valid_statuses}",
|
|
156
|
+
status_code=HTTPStatus.BAD_REQUEST,
|
|
157
|
+
operation="Get Latest Build",
|
|
155
158
|
)
|
|
156
159
|
|
|
157
160
|
model = self._get_model_management().get_model(model_id=model_id)
|
|
@@ -601,7 +604,9 @@ class FrogMLClient:
|
|
|
601
604
|
import pandas as pd
|
|
602
605
|
except ImportError:
|
|
603
606
|
raise FrogmlException(
|
|
604
|
-
"Missing Pandas dependency required for running an analytics query
|
|
607
|
+
error_message="Missing Pandas dependency required for running an analytics query",
|
|
608
|
+
status_code=HTTPStatus.BAD_REQUEST,
|
|
609
|
+
operation="Run Analytics Query",
|
|
605
610
|
)
|
|
606
611
|
client = self._get_analytics_engine()
|
|
607
612
|
url = client.get_analytics_data(query=query, timeout=timeout)
|
|
@@ -640,7 +645,11 @@ class FrogMLClient:
|
|
|
640
645
|
feature_set_def.feature_set.feature_set_definition.feature_set_id
|
|
641
646
|
)
|
|
642
647
|
else:
|
|
643
|
-
raise FrogmlException(
|
|
648
|
+
raise FrogmlException(
|
|
649
|
+
error_message=f"Feature set '{feature_set_name}' not found",
|
|
650
|
+
status_code=HTTPStatus.NOT_FOUND,
|
|
651
|
+
operation="Delete Feature Set",
|
|
652
|
+
)
|
|
644
653
|
|
|
645
654
|
def delete_featureset_version(self, featureset_name: str, version_number: int):
|
|
646
655
|
"""
|
|
@@ -686,7 +695,11 @@ class FrogMLClient:
|
|
|
686
695
|
data_source_def.data_source.data_source_definition.data_source_id
|
|
687
696
|
)
|
|
688
697
|
else:
|
|
689
|
-
raise FrogmlException(
|
|
698
|
+
raise FrogmlException(
|
|
699
|
+
error_message=f"Data source '{data_source_name}' not found",
|
|
700
|
+
status_code=HTTPStatus.NOT_FOUND,
|
|
701
|
+
operation="Delete Feature Store Data Source",
|
|
702
|
+
)
|
|
690
703
|
|
|
691
704
|
def delete_entity(self, entity_name: str):
|
|
692
705
|
"""
|
|
@@ -700,7 +713,11 @@ class FrogMLClient:
|
|
|
700
713
|
if entity_def:
|
|
701
714
|
client.delete_entity(entity_def.entity.entity_definition.entity_id)
|
|
702
715
|
else:
|
|
703
|
-
raise FrogmlException(
|
|
716
|
+
raise FrogmlException(
|
|
717
|
+
error_message=f"Entity '{entity_name}' not found",
|
|
718
|
+
status_code=HTTPStatus.NOT_FOUND,
|
|
719
|
+
operation="Delete Feature Store Entity",
|
|
720
|
+
)
|
|
704
721
|
|
|
705
722
|
def trigger_batch_feature_set(self, feature_set_name):
|
|
706
723
|
"""
|
|
@@ -723,7 +740,9 @@ class FrogMLClient:
|
|
|
723
740
|
automation = client.get_automation_by_name(automation_name=automation_name)
|
|
724
741
|
if not automation:
|
|
725
742
|
raise FrogmlException(
|
|
726
|
-
f"Could not find automation with given name '{automation_name}'"
|
|
743
|
+
error_message=f"Could not find automation with given name '{automation_name}'",
|
|
744
|
+
status_code=HTTPStatus.NOT_FOUND,
|
|
745
|
+
operation="Trigger Automation",
|
|
727
746
|
)
|
|
728
747
|
client.run_automation(automation_id=automation.id)
|
|
729
748
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import typing as t
|
|
3
|
+
from http import HTTPStatus
|
|
3
4
|
|
|
4
5
|
from frogml.core.exceptions import FrogmlException
|
|
5
6
|
|
|
@@ -47,7 +48,11 @@ class NumpyInputAdapter(BaseInputAdapter):
|
|
|
47
48
|
try:
|
|
48
49
|
dtype = np.dtype(dtype)
|
|
49
50
|
except TypeError as e:
|
|
50
|
-
raise FrogmlException(
|
|
51
|
+
raise FrogmlException(
|
|
52
|
+
error_message=f'NumpyNdarray: Invalid dtype "{dtype}": {e}',
|
|
53
|
+
status_code=HTTPStatus.BAD_REQUEST,
|
|
54
|
+
operation="Initialize Model Input Adapter",
|
|
55
|
+
)
|
|
51
56
|
|
|
52
57
|
self._dtype = dtype
|
|
53
58
|
self._shape = shape
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import io
|
|
2
|
+
from http import HTTPStatus
|
|
2
3
|
|
|
3
4
|
from frogml.core.exceptions import FrogmlException
|
|
4
5
|
|
|
@@ -21,7 +22,9 @@ class NumpyOutputAdapter(BaseOutputAdapter):
|
|
|
21
22
|
def pack_user_func_return_value(return_result) -> bytes:
|
|
22
23
|
if not isinstance(return_result, np.ndarray):
|
|
23
24
|
raise FrogmlException(
|
|
24
|
-
"
|
|
25
|
+
error_message="NumpyOutputAdapter can only work with numpy.ndarray type",
|
|
26
|
+
status_code=HTTPStatus.BAD_REQUEST,
|
|
27
|
+
operation="Pack Model Output",
|
|
25
28
|
)
|
|
26
29
|
try:
|
|
27
30
|
results_buffer = io.BytesIO()
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from typing import Callable
|
|
2
|
+
from http import HTTPStatus
|
|
2
3
|
|
|
3
4
|
from dependency_injector.wiring import Provide, inject
|
|
4
5
|
|
|
@@ -63,4 +64,8 @@ def api_decorator(
|
|
|
63
64
|
)
|
|
64
65
|
except TypeError as e:
|
|
65
66
|
if "__call__() takes 1" in str(e):
|
|
66
|
-
raise FrogmlException(
|
|
67
|
+
raise FrogmlException(
|
|
68
|
+
error_message=API_NOT_CONFIGURED_ERROR_MESSAGE,
|
|
69
|
+
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
|
|
70
|
+
operation="Configure API",
|
|
71
|
+
)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from typing import Any
|
|
2
|
+
from http import HTTPStatus
|
|
2
3
|
|
|
3
4
|
from frogml.core.exceptions import FrogmlException, FrogmlHTTPException
|
|
4
5
|
from frogml.sdk.model.adapters import (
|
|
@@ -71,5 +72,8 @@ def get_output_adapter(
|
|
|
71
72
|
):
|
|
72
73
|
return runtime_impl(output_orient=adapter.output_orient)
|
|
73
74
|
return runtime_impl()
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
raise FrogmlException(
|
|
76
|
+
error_message="No output adapter selected",
|
|
77
|
+
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
|
|
78
|
+
operation="Get Output Adapter",
|
|
79
|
+
)
|
|
@@ -113,4 +113,7 @@ def load_model(repository: str, model_name: str, version: str):
|
|
|
113
113
|
logging.error(
|
|
114
114
|
f"Failed to load Model. Model was serialized with Catboost version: {framework_runtime_version}"
|
|
115
115
|
)
|
|
116
|
-
raise FrogmlException(
|
|
116
|
+
raise FrogmlException(
|
|
117
|
+
error_message=f"Failed to deserialize model: {e}",
|
|
118
|
+
operation="Load Model Version",
|
|
119
|
+
)
|
|
@@ -214,4 +214,7 @@ def load_model(repository: str, model_name: str, version: str):
|
|
|
214
214
|
logging.error(
|
|
215
215
|
f"Failed to load Model. Model was serialized with transformers using DistilBert version: {framework_runtime_version}"
|
|
216
216
|
)
|
|
217
|
-
raise FrogmlException(
|
|
217
|
+
raise FrogmlException(
|
|
218
|
+
error_message=f"Failed to deserialize model: {e}",
|
|
219
|
+
operation="Load Model Version",
|
|
220
|
+
)
|
|
@@ -28,7 +28,10 @@ class CatboostModelVersionManager(BaseModelVersionManager):
|
|
|
28
28
|
|
|
29
29
|
return catboost.__version__
|
|
30
30
|
except Exception as e:
|
|
31
|
-
raise FrogmlException(
|
|
31
|
+
raise FrogmlException(
|
|
32
|
+
error_message=f"Failed to get catboost version: {e}",
|
|
33
|
+
operation="Get Model Version Framework Version",
|
|
34
|
+
)
|
|
32
35
|
|
|
33
36
|
@override
|
|
34
37
|
def _save_model(self: Self, model: Any, config: ModelLogConfig):
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from http import HTTPStatus
|
|
1
2
|
from typing import Any
|
|
2
3
|
|
|
3
4
|
from typing_extensions import Self, override
|
|
@@ -31,12 +32,19 @@ class HuggingfaceModelVersionManager(BaseModelVersionManager):
|
|
|
31
32
|
|
|
32
33
|
return transformers.__version__
|
|
33
34
|
except Exception as e:
|
|
34
|
-
raise FrogmlException(
|
|
35
|
+
raise FrogmlException(
|
|
36
|
+
error_message=f"Failed to get transformers version: {e}",
|
|
37
|
+
operation="Get Model Version Framework Version",
|
|
38
|
+
)
|
|
35
39
|
|
|
36
40
|
@override
|
|
37
41
|
def _save_model(self: Self, model: Any, config: ModelLogConfig):
|
|
38
42
|
if not isinstance(model, tuple):
|
|
39
|
-
raise FrogmlException(
|
|
43
|
+
raise FrogmlException(
|
|
44
|
+
error_message="Model must be a tuple containing (model, tokenizer)",
|
|
45
|
+
status_code=HTTPStatus.BAD_REQUEST,
|
|
46
|
+
operation="Save Model Version",
|
|
47
|
+
)
|
|
40
48
|
|
|
41
49
|
model_obj, tokenizer = model # Assuming model is a tuple of (model, tokenizer)
|
|
42
50
|
model_obj.save_pretrained(config.full_model_path)
|
|
@@ -28,7 +28,10 @@ class OnnxModelVersionManager(BaseModelVersionManager):
|
|
|
28
28
|
|
|
29
29
|
return onnx.__version__
|
|
30
30
|
except Exception as e:
|
|
31
|
-
raise FrogmlException(
|
|
31
|
+
raise FrogmlException(
|
|
32
|
+
error_message=f"Failed to get onnx version: {e}",
|
|
33
|
+
operation="Get Model Version Framework Version",
|
|
34
|
+
)
|
|
32
35
|
|
|
33
36
|
@override
|
|
34
37
|
def _save_model(self: Self, model: Any, config: ModelLogConfig):
|
|
@@ -28,7 +28,10 @@ class PytorchModelVersionManager(BaseModelVersionManager):
|
|
|
28
28
|
|
|
29
29
|
return torch.__version__
|
|
30
30
|
except Exception as e:
|
|
31
|
-
raise FrogmlException(
|
|
31
|
+
raise FrogmlException(
|
|
32
|
+
error_message=f"Failed to get torch version: {e}",
|
|
33
|
+
operation="Get Model Version Framework Version",
|
|
34
|
+
)
|
|
32
35
|
|
|
33
36
|
@override
|
|
34
37
|
def _save_model(self: Self, model: Any, config: ModelLogConfig):
|
|
@@ -32,7 +32,10 @@ class ScikitLearnModelVersionManager(BaseModelVersionManager):
|
|
|
32
32
|
|
|
33
33
|
return sklearn.__version__
|
|
34
34
|
except Exception as e:
|
|
35
|
-
raise FrogmlException(
|
|
35
|
+
raise FrogmlException(
|
|
36
|
+
error_message=f"Failed to get sklearn version: {e}",
|
|
37
|
+
operation="Get Model Version Framework Version",
|
|
38
|
+
)
|
|
36
39
|
|
|
37
40
|
@override
|
|
38
41
|
def _save_model(self: Self, model: Any, config: ModelLogConfig):
|
|
@@ -121,4 +121,7 @@ def load_model(repository: str, model_name: str, version: str):
|
|
|
121
121
|
logging.error(
|
|
122
122
|
f"Failed to load Model. Model was serialized with onnx version: {framework_runtime_version}"
|
|
123
123
|
)
|
|
124
|
-
raise FrogmlException(
|
|
124
|
+
raise FrogmlException(
|
|
125
|
+
error_message=f"Failed to deserialize model: {e}",
|
|
126
|
+
operation="Load Model Version",
|
|
127
|
+
)
|
|
@@ -113,4 +113,7 @@ def load_model(repository: str, model_name: str, version: str):
|
|
|
113
113
|
logging.error(
|
|
114
114
|
f"Failed to load Model. Model was serialized with Pytorch version: {framework_runtime_version}"
|
|
115
115
|
)
|
|
116
|
-
raise FrogmlException(
|
|
116
|
+
raise FrogmlException(
|
|
117
|
+
error_message=f"Failed to deserialize model: {e}",
|
|
118
|
+
operation="Load Model Version",
|
|
119
|
+
)
|
|
@@ -126,4 +126,7 @@ def load_model(repository: str, model_name: str, version: str):
|
|
|
126
126
|
logging.error(
|
|
127
127
|
f"Failed to load Model. Model was serialized with scikit-learn version: {framework_runtime_version}"
|
|
128
128
|
)
|
|
129
|
-
raise FrogmlException(
|
|
129
|
+
raise FrogmlException(
|
|
130
|
+
error_message=f"Failed to deserialize model: {e}",
|
|
131
|
+
operation="Load Model Version",
|
|
132
|
+
)
|
|
@@ -130,6 +130,6 @@ class JmlCustomerClient:
|
|
|
130
130
|
"Failed to create model version %s in JFML due to this following error: '%s'\n\n"
|
|
131
131
|
"Before retrying, please delete the uploaded artifact from Artifactory",
|
|
132
132
|
model_version_name,
|
|
133
|
-
e.
|
|
133
|
+
e.error_message,
|
|
134
134
|
)
|
|
135
135
|
raise e
|
|
@@ -214,7 +214,10 @@ def build_zip_code_path(
|
|
|
214
214
|
root_dir=parent_dir_path, dir_to_zip=filtered_copied_dir_path
|
|
215
215
|
)
|
|
216
216
|
except Exception as e:
|
|
217
|
-
raise FrogmlException(
|
|
217
|
+
raise FrogmlException(
|
|
218
|
+
error_message=f"Failed to zip code directory: {e}",
|
|
219
|
+
operation="Prepare Model Version Code Package",
|
|
220
|
+
) from e
|
|
218
221
|
finally:
|
|
219
222
|
_remove_dir(filtered_copied_dir_path)
|
|
220
223
|
_remove_dir(template_file_dir)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from http import HTTPStatus
|
|
2
|
+
|
|
1
3
|
from frogml.core.exceptions import FrogmlException
|
|
2
4
|
from frogml.sdk.model_version.constants import ModelFramework
|
|
3
5
|
|
|
@@ -9,7 +11,11 @@ def _validate_string(s: str) -> None:
|
|
|
9
11
|
:return: None if validation pass successfully else raise error
|
|
10
12
|
"""
|
|
11
13
|
if not s:
|
|
12
|
-
raise FrogmlException(
|
|
14
|
+
raise FrogmlException(
|
|
15
|
+
error_message="String cannot be empty",
|
|
16
|
+
status_code=HTTPStatus.BAD_REQUEST,
|
|
17
|
+
operation="Validate Model Version Input",
|
|
18
|
+
)
|
|
13
19
|
|
|
14
20
|
|
|
15
21
|
def _validate_load_model(
|
|
@@ -35,5 +41,7 @@ def _validate_load_model(
|
|
|
35
41
|
_validate_string(version)
|
|
36
42
|
if model_framework_stored != model_framework.value:
|
|
37
43
|
raise FrogmlException(
|
|
38
|
-
f"
|
|
44
|
+
error_message=f"Model '{model_name}' in repository '{repository}' is not a {model_framework} model",
|
|
45
|
+
status_code=HTTPStatus.BAD_REQUEST,
|
|
46
|
+
operation="Load Model Version",
|
|
39
47
|
)
|