sagemaker-mlp-sdk 0.1.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.
- mlp_sdk/__init__.py +18 -0
- mlp_sdk/config.py +630 -0
- mlp_sdk/exceptions.py +421 -0
- mlp_sdk/models.py +62 -0
- mlp_sdk/session.py +1160 -0
- mlp_sdk/wrappers/__init__.py +11 -0
- mlp_sdk/wrappers/deployment.py +459 -0
- mlp_sdk/wrappers/feature_store.py +308 -0
- mlp_sdk/wrappers/pipeline.py +452 -0
- mlp_sdk/wrappers/processing.py +381 -0
- mlp_sdk/wrappers/training.py +492 -0
- sagemaker_mlp_sdk-0.1.0.dist-info/METADATA +569 -0
- sagemaker_mlp_sdk-0.1.0.dist-info/RECORD +16 -0
- sagemaker_mlp_sdk-0.1.0.dist-info/WHEEL +5 -0
- sagemaker_mlp_sdk-0.1.0.dist-info/licenses/LICENSE +21 -0
- sagemaker_mlp_sdk-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Feature Store wrapper for mlp_sdk
|
|
3
|
+
Provides simplified feature group creation with configuration-driven defaults
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Optional, Dict, Any, List
|
|
7
|
+
from ..exceptions import MLPSDKError, ValidationError, AWSServiceError, MLPLogger
|
|
8
|
+
from ..config import ConfigurationManager
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class FeatureStoreWrapper:
|
|
12
|
+
"""
|
|
13
|
+
Wrapper for SageMaker Feature Store operations.
|
|
14
|
+
Applies default configurations from ConfigurationManager.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, config_manager: ConfigurationManager, logger: Optional[MLPLogger] = None):
|
|
18
|
+
"""
|
|
19
|
+
Initialize Feature Store wrapper.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
config_manager: Configuration manager instance
|
|
23
|
+
logger: Optional logger instance
|
|
24
|
+
"""
|
|
25
|
+
self.config_manager = config_manager
|
|
26
|
+
self.logger = logger or MLPLogger("mlp_sdk.feature_store")
|
|
27
|
+
|
|
28
|
+
def create_feature_group(self,
|
|
29
|
+
sagemaker_session,
|
|
30
|
+
feature_group_name: str,
|
|
31
|
+
record_identifier_name: str,
|
|
32
|
+
event_time_feature_name: str,
|
|
33
|
+
feature_definitions: List[Dict[str, str]],
|
|
34
|
+
**kwargs) -> Any:
|
|
35
|
+
"""
|
|
36
|
+
Create a feature group with default configurations.
|
|
37
|
+
|
|
38
|
+
Applies defaults from configuration for:
|
|
39
|
+
- Offline store S3 URI
|
|
40
|
+
- Online store enablement
|
|
41
|
+
- Security group IDs
|
|
42
|
+
- Subnets
|
|
43
|
+
- KMS key ID
|
|
44
|
+
- IAM role
|
|
45
|
+
|
|
46
|
+
Runtime parameters override configuration defaults.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
sagemaker_session: SageMaker session object
|
|
50
|
+
feature_group_name: Name of the feature group
|
|
51
|
+
record_identifier_name: Name of the record identifier feature
|
|
52
|
+
event_time_feature_name: Name of the event time feature
|
|
53
|
+
feature_definitions: List of feature definitions
|
|
54
|
+
**kwargs: Additional parameters that override defaults
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
FeatureGroup object
|
|
58
|
+
|
|
59
|
+
Raises:
|
|
60
|
+
ValidationError: If required parameters are missing or invalid
|
|
61
|
+
AWSServiceError: If feature group creation fails
|
|
62
|
+
"""
|
|
63
|
+
self.logger.info("Creating feature group", name=feature_group_name)
|
|
64
|
+
|
|
65
|
+
# Validate required parameters
|
|
66
|
+
if not feature_group_name:
|
|
67
|
+
raise ValidationError("feature_group_name is required")
|
|
68
|
+
if not record_identifier_name:
|
|
69
|
+
raise ValidationError("record_identifier_name is required")
|
|
70
|
+
if not event_time_feature_name:
|
|
71
|
+
raise ValidationError("event_time_feature_name is required")
|
|
72
|
+
if not feature_definitions:
|
|
73
|
+
raise ValidationError("feature_definitions is required and cannot be empty")
|
|
74
|
+
|
|
75
|
+
# Validate runtime parameter overrides
|
|
76
|
+
self.validate_parameter_override(kwargs)
|
|
77
|
+
|
|
78
|
+
try:
|
|
79
|
+
from sagemaker.feature_store.feature_group import FeatureGroup
|
|
80
|
+
except ImportError as e:
|
|
81
|
+
raise MLPSDKError(
|
|
82
|
+
"SageMaker SDK not installed. Install with: pip install sagemaker>=3.0.0"
|
|
83
|
+
) from e
|
|
84
|
+
|
|
85
|
+
# Build configuration with defaults
|
|
86
|
+
config = self._build_feature_group_config(kwargs)
|
|
87
|
+
|
|
88
|
+
# Create FeatureGroup object
|
|
89
|
+
feature_group = FeatureGroup(
|
|
90
|
+
name=feature_group_name,
|
|
91
|
+
sagemaker_session=sagemaker_session
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Load feature definitions
|
|
95
|
+
feature_group.load_feature_definitions(feature_definitions)
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
# Create the feature group with merged configuration
|
|
99
|
+
self.logger.debug("Creating feature group with config",
|
|
100
|
+
name=feature_group_name,
|
|
101
|
+
has_online_store=config.get('enable_online_store', False),
|
|
102
|
+
has_offline_store=bool(config.get('offline_store_config')))
|
|
103
|
+
|
|
104
|
+
# Build create parameters
|
|
105
|
+
create_params = {
|
|
106
|
+
'record_identifier_name': record_identifier_name,
|
|
107
|
+
'event_time_feature_name': event_time_feature_name,
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# Add role ARN if available
|
|
111
|
+
if config.get('role_arn'):
|
|
112
|
+
create_params['role_arn'] = config['role_arn']
|
|
113
|
+
|
|
114
|
+
# Add online store config if enabled
|
|
115
|
+
if config.get('enable_online_store'):
|
|
116
|
+
online_store_config = {'EnableOnlineStore': True}
|
|
117
|
+
|
|
118
|
+
# Add security config if available
|
|
119
|
+
if config.get('online_store_security_config'):
|
|
120
|
+
online_store_config['SecurityConfig'] = config['online_store_security_config']
|
|
121
|
+
|
|
122
|
+
create_params['online_store_config'] = online_store_config
|
|
123
|
+
|
|
124
|
+
# Add offline store config if available
|
|
125
|
+
if config.get('offline_store_config'):
|
|
126
|
+
create_params['offline_store_config'] = config['offline_store_config']
|
|
127
|
+
|
|
128
|
+
# Add description if provided
|
|
129
|
+
if config.get('description'):
|
|
130
|
+
create_params['description'] = config['description']
|
|
131
|
+
|
|
132
|
+
# Add tags if provided
|
|
133
|
+
if config.get('tags'):
|
|
134
|
+
create_params['tags'] = config['tags']
|
|
135
|
+
|
|
136
|
+
# Create the feature group
|
|
137
|
+
feature_group.create(**create_params)
|
|
138
|
+
|
|
139
|
+
self.logger.info("Feature group created successfully", name=feature_group_name)
|
|
140
|
+
return feature_group
|
|
141
|
+
|
|
142
|
+
except Exception as e:
|
|
143
|
+
self.logger.error("Failed to create feature group",
|
|
144
|
+
name=feature_group_name,
|
|
145
|
+
error=e)
|
|
146
|
+
raise AWSServiceError(
|
|
147
|
+
f"Failed to create feature group '{feature_group_name}': {e}",
|
|
148
|
+
aws_error=e
|
|
149
|
+
) from e
|
|
150
|
+
|
|
151
|
+
def _build_feature_group_config(self, runtime_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
152
|
+
"""
|
|
153
|
+
Build feature group configuration by merging defaults with runtime parameters.
|
|
154
|
+
|
|
155
|
+
Parameter precedence: runtime > config > SageMaker defaults
|
|
156
|
+
|
|
157
|
+
This implements the parameter override behavior specified in Requirements 3.5 and 8.2:
|
|
158
|
+
- Runtime parameters always take precedence over configuration defaults
|
|
159
|
+
- Configuration defaults take precedence over SageMaker SDK defaults
|
|
160
|
+
- SageMaker SDK defaults are used when neither runtime nor config provide values
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
runtime_params: Runtime parameters provided by user
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
Merged configuration dictionary
|
|
167
|
+
"""
|
|
168
|
+
config = {}
|
|
169
|
+
|
|
170
|
+
# Get configuration objects
|
|
171
|
+
feature_store_config = self.config_manager.get_feature_store_config()
|
|
172
|
+
networking_config = self.config_manager.get_networking_config()
|
|
173
|
+
iam_config = self.config_manager.get_iam_config()
|
|
174
|
+
kms_config = self.config_manager.get_kms_config()
|
|
175
|
+
|
|
176
|
+
# Apply offline store defaults (runtime > config)
|
|
177
|
+
if feature_store_config:
|
|
178
|
+
# Offline store configuration
|
|
179
|
+
if 'offline_store_config' in runtime_params:
|
|
180
|
+
# Runtime parameter takes precedence
|
|
181
|
+
config['offline_store_config'] = runtime_params['offline_store_config']
|
|
182
|
+
self.logger.debug("Using runtime offline_store_config")
|
|
183
|
+
else:
|
|
184
|
+
# Use config default
|
|
185
|
+
offline_store_config = {
|
|
186
|
+
'S3StorageConfig': {
|
|
187
|
+
'S3Uri': feature_store_config.offline_store_s3_uri
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
# Add KMS key if available
|
|
192
|
+
if kms_config and kms_config.key_id:
|
|
193
|
+
offline_store_config['S3StorageConfig']['KmsKeyId'] = kms_config.key_id
|
|
194
|
+
|
|
195
|
+
config['offline_store_config'] = offline_store_config
|
|
196
|
+
self.logger.debug("Using config offline_store_config",
|
|
197
|
+
s3_uri=feature_store_config.offline_store_s3_uri)
|
|
198
|
+
|
|
199
|
+
# Online store enablement (runtime > config)
|
|
200
|
+
if 'enable_online_store' in runtime_params:
|
|
201
|
+
config['enable_online_store'] = runtime_params['enable_online_store']
|
|
202
|
+
self.logger.debug("Using runtime enable_online_store",
|
|
203
|
+
value=runtime_params['enable_online_store'])
|
|
204
|
+
else:
|
|
205
|
+
config['enable_online_store'] = feature_store_config.enable_online_store
|
|
206
|
+
self.logger.debug("Using config enable_online_store",
|
|
207
|
+
value=feature_store_config.enable_online_store)
|
|
208
|
+
|
|
209
|
+
# Apply networking defaults for online store (runtime > config)
|
|
210
|
+
if config.get('enable_online_store'):
|
|
211
|
+
if 'online_store_security_config' in runtime_params:
|
|
212
|
+
config['online_store_security_config'] = runtime_params['online_store_security_config']
|
|
213
|
+
self.logger.debug("Using runtime online_store_security_config")
|
|
214
|
+
elif kms_config and kms_config.key_id:
|
|
215
|
+
config['online_store_security_config'] = {
|
|
216
|
+
'KmsKeyId': kms_config.key_id
|
|
217
|
+
}
|
|
218
|
+
self.logger.debug("Using config online_store_security_config")
|
|
219
|
+
|
|
220
|
+
# Apply IAM role default (runtime > config)
|
|
221
|
+
if 'role_arn' in runtime_params:
|
|
222
|
+
config['role_arn'] = runtime_params['role_arn']
|
|
223
|
+
self.logger.debug("Using runtime role_arn")
|
|
224
|
+
elif iam_config:
|
|
225
|
+
config['role_arn'] = iam_config.execution_role
|
|
226
|
+
self.logger.debug("Using config role_arn", role=iam_config.execution_role)
|
|
227
|
+
|
|
228
|
+
# Apply any remaining runtime parameters (these override everything)
|
|
229
|
+
for key, value in runtime_params.items():
|
|
230
|
+
if key not in ['offline_store_config', 'enable_online_store',
|
|
231
|
+
'online_store_security_config', 'role_arn']:
|
|
232
|
+
config[key] = value
|
|
233
|
+
self.logger.debug(f"Using runtime parameter: {key}")
|
|
234
|
+
|
|
235
|
+
return config
|
|
236
|
+
|
|
237
|
+
def _validate_feature_definitions(self, feature_definitions: List[Dict[str, str]]) -> None:
|
|
238
|
+
"""
|
|
239
|
+
Validate feature definitions format.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
feature_definitions: List of feature definitions
|
|
243
|
+
|
|
244
|
+
Raises:
|
|
245
|
+
ValidationError: If feature definitions are invalid
|
|
246
|
+
"""
|
|
247
|
+
if not isinstance(feature_definitions, list):
|
|
248
|
+
raise ValidationError("feature_definitions must be a list")
|
|
249
|
+
|
|
250
|
+
if not feature_definitions:
|
|
251
|
+
raise ValidationError("feature_definitions cannot be empty")
|
|
252
|
+
|
|
253
|
+
for idx, feature_def in enumerate(feature_definitions):
|
|
254
|
+
if not isinstance(feature_def, dict):
|
|
255
|
+
raise ValidationError(f"Feature definition at index {idx} must be a dictionary")
|
|
256
|
+
|
|
257
|
+
if 'FeatureName' not in feature_def:
|
|
258
|
+
raise ValidationError(f"Feature definition at index {idx} missing 'FeatureName'")
|
|
259
|
+
|
|
260
|
+
if 'FeatureType' not in feature_def:
|
|
261
|
+
raise ValidationError(f"Feature definition at index {idx} missing 'FeatureType'")
|
|
262
|
+
|
|
263
|
+
def validate_parameter_override(self, runtime_params: Dict[str, Any]) -> None:
|
|
264
|
+
"""
|
|
265
|
+
Validate runtime parameter overrides.
|
|
266
|
+
|
|
267
|
+
This ensures that runtime parameters are valid and compatible with the configuration.
|
|
268
|
+
Implements validation requirements from Requirements 3.5 and 8.2.
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
runtime_params: Runtime parameters to validate
|
|
272
|
+
|
|
273
|
+
Raises:
|
|
274
|
+
ValidationError: If runtime parameters are invalid
|
|
275
|
+
"""
|
|
276
|
+
# Validate offline_store_config structure if provided
|
|
277
|
+
if 'offline_store_config' in runtime_params:
|
|
278
|
+
offline_config = runtime_params['offline_store_config']
|
|
279
|
+
if not isinstance(offline_config, dict):
|
|
280
|
+
raise ValidationError("offline_store_config must be a dictionary")
|
|
281
|
+
|
|
282
|
+
if 'S3StorageConfig' in offline_config:
|
|
283
|
+
s3_config = offline_config['S3StorageConfig']
|
|
284
|
+
if not isinstance(s3_config, dict):
|
|
285
|
+
raise ValidationError("S3StorageConfig must be a dictionary")
|
|
286
|
+
|
|
287
|
+
if 'S3Uri' not in s3_config:
|
|
288
|
+
raise ValidationError("S3StorageConfig must contain 'S3Uri'")
|
|
289
|
+
|
|
290
|
+
# Validate enable_online_store type if provided
|
|
291
|
+
if 'enable_online_store' in runtime_params:
|
|
292
|
+
if not isinstance(runtime_params['enable_online_store'], bool):
|
|
293
|
+
raise ValidationError("enable_online_store must be a boolean")
|
|
294
|
+
|
|
295
|
+
# Validate role_arn format if provided
|
|
296
|
+
if 'role_arn' in runtime_params:
|
|
297
|
+
role_arn = runtime_params['role_arn']
|
|
298
|
+
if not isinstance(role_arn, str):
|
|
299
|
+
raise ValidationError("role_arn must be a string")
|
|
300
|
+
|
|
301
|
+
if not role_arn.startswith('arn:aws:iam::'):
|
|
302
|
+
raise ValidationError(f"Invalid IAM role ARN format: {role_arn}")
|
|
303
|
+
|
|
304
|
+
# Validate online_store_security_config if provided
|
|
305
|
+
if 'online_store_security_config' in runtime_params:
|
|
306
|
+
security_config = runtime_params['online_store_security_config']
|
|
307
|
+
if not isinstance(security_config, dict):
|
|
308
|
+
raise ValidationError("online_store_security_config must be a dictionary")
|