workbench 0.8.198__py3-none-any.whl → 0.8.203__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 (53) hide show
  1. workbench/algorithms/dataframe/proximity.py +11 -4
  2. workbench/api/__init__.py +2 -1
  3. workbench/api/df_store.py +17 -108
  4. workbench/api/feature_set.py +48 -11
  5. workbench/api/model.py +1 -1
  6. workbench/api/parameter_store.py +3 -52
  7. workbench/core/artifacts/__init__.py +11 -2
  8. workbench/core/artifacts/artifact.py +5 -5
  9. workbench/core/artifacts/df_store_core.py +114 -0
  10. workbench/core/artifacts/endpoint_core.py +261 -78
  11. workbench/core/artifacts/feature_set_core.py +69 -1
  12. workbench/core/artifacts/model_core.py +48 -14
  13. workbench/core/artifacts/parameter_store_core.py +98 -0
  14. workbench/core/transforms/features_to_model/features_to_model.py +50 -33
  15. workbench/core/transforms/pandas_transforms/pandas_to_features.py +11 -2
  16. workbench/core/views/view.py +2 -2
  17. workbench/model_scripts/chemprop/chemprop.template +933 -0
  18. workbench/model_scripts/chemprop/generated_model_script.py +933 -0
  19. workbench/model_scripts/chemprop/requirements.txt +11 -0
  20. workbench/model_scripts/custom_models/chem_info/fingerprints.py +134 -0
  21. workbench/model_scripts/custom_models/chem_info/morgan_fingerprints.py +1 -1
  22. workbench/model_scripts/custom_models/proximity/proximity.py +11 -4
  23. workbench/model_scripts/custom_models/uq_models/ensemble_xgb.template +11 -5
  24. workbench/model_scripts/custom_models/uq_models/meta_uq.template +11 -5
  25. workbench/model_scripts/custom_models/uq_models/ngboost.template +11 -5
  26. workbench/model_scripts/custom_models/uq_models/proximity.py +11 -4
  27. workbench/model_scripts/ensemble_xgb/ensemble_xgb.template +11 -5
  28. workbench/model_scripts/pytorch_model/generated_model_script.py +365 -173
  29. workbench/model_scripts/pytorch_model/pytorch.template +362 -170
  30. workbench/model_scripts/scikit_learn/generated_model_script.py +302 -0
  31. workbench/model_scripts/script_generation.py +10 -7
  32. workbench/model_scripts/uq_models/generated_model_script.py +43 -27
  33. workbench/model_scripts/uq_models/mapie.template +40 -24
  34. workbench/model_scripts/xgb_model/generated_model_script.py +36 -7
  35. workbench/model_scripts/xgb_model/xgb_model.template +36 -7
  36. workbench/repl/workbench_shell.py +14 -5
  37. workbench/resources/open_source_api.key +1 -1
  38. workbench/scripts/endpoint_test.py +162 -0
  39. workbench/scripts/{lambda_launcher.py → lambda_test.py} +10 -0
  40. workbench/utils/chemprop_utils.py +761 -0
  41. workbench/utils/pytorch_utils.py +527 -0
  42. workbench/utils/xgboost_model_utils.py +10 -5
  43. workbench/web_interface/components/model_plot.py +7 -1
  44. {workbench-0.8.198.dist-info → workbench-0.8.203.dist-info}/METADATA +3 -3
  45. {workbench-0.8.198.dist-info → workbench-0.8.203.dist-info}/RECORD +49 -43
  46. {workbench-0.8.198.dist-info → workbench-0.8.203.dist-info}/entry_points.txt +2 -1
  47. workbench/core/cloud_platform/aws/aws_df_store.py +0 -404
  48. workbench/core/cloud_platform/aws/aws_parameter_store.py +0 -280
  49. workbench/model_scripts/__pycache__/script_generation.cpython-312.pyc +0 -0
  50. workbench/model_scripts/__pycache__/script_generation.cpython-313.pyc +0 -0
  51. {workbench-0.8.198.dist-info → workbench-0.8.203.dist-info}/WHEEL +0 -0
  52. {workbench-0.8.198.dist-info → workbench-0.8.203.dist-info}/licenses/LICENSE +0 -0
  53. {workbench-0.8.198.dist-info → workbench-0.8.203.dist-info}/top_level.txt +0 -0
@@ -1,280 +0,0 @@
1
- """AWSParameterStore: Manages Workbench parameters in AWS Systems Manager Parameter Store."""
2
-
3
- from typing import Union
4
- import logging
5
- import json
6
- import zlib
7
- import base64
8
- from botocore.exceptions import ClientError
9
-
10
- # Workbench Imports
11
- from workbench.core.cloud_platform.aws.aws_session import AWSSession
12
- from workbench.utils.json_utils import CustomEncoder
13
-
14
-
15
- class AWSParameterStore:
16
- """AWSParameterStore: Manages Workbench parameters in AWS Systems Manager Parameter Store.
17
-
18
- Common Usage:
19
- ```python
20
- params = AWSParameterStore()
21
-
22
- # List Parameters
23
- params.list()
24
-
25
- ['/workbench/abalone_info',
26
- '/workbench/my_data',
27
- '/workbench/test',
28
- '/workbench/pipelines/my_pipeline']
29
-
30
- # Add Key
31
- params.upsert("key", "value")
32
- value = params.get("key")
33
-
34
- # Add any data (lists, dictionaries, etc..)
35
- my_data = {"key": "value", "number": 4.2, "list": [1,2,3]}
36
- params.upsert("my_data", my_data)
37
-
38
- # Retrieve data
39
- return_value = params.get("my_data")
40
- pprint(return_value)
41
-
42
- {'key': 'value', 'list': [1, 2, 3], 'number': 4.2}
43
-
44
- # Delete parameters
45
- param_store.delete("my_data")
46
- ```
47
- """
48
-
49
- def __init__(self):
50
- """AWSParameterStore Init Method"""
51
- self.log = logging.getLogger("workbench")
52
-
53
- # Initialize a Workbench Session (to assume the Workbench ExecutionRole)
54
- self.boto3_session = AWSSession().boto3_session
55
-
56
- # Create a Systems Manager (SSM) client for Parameter Store operations
57
- self.ssm_client = self.boto3_session.client("ssm")
58
-
59
- def list(self, prefix: str = None) -> list:
60
- """List all parameters in the AWS Parameter Store, optionally filtering by a prefix.
61
-
62
- Args:
63
- prefix (str, optional): A prefix to filter the parameters by. Defaults to None.
64
-
65
- Returns:
66
- list: A list of parameter names and details.
67
- """
68
- try:
69
- # Set up parameters for the query
70
- params = {"MaxResults": 50}
71
-
72
- # If a prefix is provided, add the 'ParameterFilters' for optimization
73
- if prefix:
74
- params["ParameterFilters"] = [{"Key": "Name", "Option": "BeginsWith", "Values": [prefix]}]
75
-
76
- # Initialize the list to collect parameter names
77
- all_parameters = []
78
-
79
- # Make the initial call to describe parameters
80
- response = self.ssm_client.describe_parameters(**params)
81
-
82
- # Aggregate the names from the initial response
83
- all_parameters.extend(param["Name"] for param in response["Parameters"])
84
-
85
- # Continue to paginate if there's a NextToken
86
- while "NextToken" in response:
87
- # Update the parameters with the NextToken for subsequent calls
88
- params["NextToken"] = response["NextToken"]
89
- response = self.ssm_client.describe_parameters(**params)
90
-
91
- # Aggregate the names from the subsequent responses
92
- all_parameters.extend(param["Name"] for param in response["Parameters"])
93
-
94
- except Exception as e:
95
- self.log.error(f"Failed to list parameters: {e}")
96
- return []
97
-
98
- # Return the aggregated list of parameter names
99
- return all_parameters
100
-
101
- def get(self, name: str, warn: bool = True, decrypt: bool = True) -> Union[str, list, dict, None]:
102
- """Retrieve a parameter value from the AWS Parameter Store.
103
-
104
- Args:
105
- name (str): The name of the parameter to retrieve.
106
- warn (bool): Whether to log a warning if the parameter is not found.
107
- decrypt (bool): Whether to decrypt secure string parameters.
108
-
109
- Returns:
110
- Union[str, list, dict, None]: The value of the parameter or None if not found.
111
- """
112
- try:
113
- # Retrieve the parameter from Parameter Store
114
- response = self.ssm_client.get_parameter(Name=name, WithDecryption=decrypt)
115
- value = response["Parameter"]["Value"]
116
-
117
- # Auto-detect and decompress if needed
118
- if value.startswith("COMPRESSED:"):
119
- # Base64 decode and decompress
120
- self.log.important(f"Decompressing parameter '{name}'...")
121
- compressed_value = base64.b64decode(value[len("COMPRESSED:") :])
122
- value = zlib.decompress(compressed_value).decode("utf-8")
123
-
124
- # Attempt to parse the value back to its original type
125
- try:
126
- parsed_value = json.loads(value)
127
- return parsed_value
128
- except (json.JSONDecodeError, TypeError):
129
- # If parsing fails, return the value as is "hope for the best"
130
- return value
131
-
132
- except ClientError as e:
133
- if e.response["Error"]["Code"] == "ParameterNotFound":
134
- if warn:
135
- self.log.warning(f"Parameter '{name}' not found")
136
- else:
137
- self.log.error(f"Failed to get parameter '{name}': {e}")
138
- return None
139
-
140
- def upsert(self, name: str, value, precision: int = 3):
141
- """Insert or update a parameter in the AWS Parameter Store.
142
-
143
- Args:
144
- name (str): The name of the parameter.
145
- value (str | list | dict): The value of the parameter.
146
- precision (int): The precision for float values in the JSON encoding.
147
- """
148
- try:
149
- # Convert to JSON and check if compression is needed
150
- json_value = json.dumps(value, cls=CustomEncoder, precision=precision)
151
- if len(json_value) <= 4096:
152
- # Store normally if under 4KB
153
- self._store_parameter(name, json_value)
154
- return
155
-
156
- # Need compression - log warning
157
- self.log.important(
158
- f"Parameter {name} exceeds 4KB ({len(json_value)} bytes): compressing and reducing precision..."
159
- )
160
-
161
- # Try compression with precision reduction
162
- compressed_value = self._compress_value(value)
163
-
164
- if len(compressed_value) <= 4096:
165
- self._store_parameter(name, compressed_value)
166
- return
167
-
168
- # Try clipping the data
169
- clipped_value = self._clip_data(value)
170
- compressed_clipped = self._compress_value(clipped_value)
171
-
172
- if len(compressed_clipped) <= 4096:
173
- self.log.warning(
174
- f"Parameter {name} data clipped to 100 items/elements: ({len(compressed_clipped)} bytes)"
175
- )
176
- self._store_parameter(name, compressed_clipped)
177
- return
178
-
179
- # Still too large - give up
180
- self._handle_oversized_data(name, len(compressed_clipped))
181
-
182
- except Exception as e:
183
- self.log.critical(f"Failed to add/update parameter '{name}': {e}")
184
- raise
185
-
186
- @staticmethod
187
- def _compress_value(value) -> str:
188
- """Compress a value with precision reduction."""
189
- json_value = json.dumps(value, cls=CustomEncoder, precision=3)
190
- compressed = zlib.compress(json_value.encode("utf-8"), level=9)
191
- return "COMPRESSED:" + base64.b64encode(compressed).decode("utf-8")
192
-
193
- @staticmethod
194
- def _clip_data(value):
195
- """Clip data to reduce size, clip to first 100 items/elements."""
196
- if isinstance(value, dict):
197
- return dict(list(value.items())[:100])
198
- elif isinstance(value, list):
199
- return value[:100]
200
- return value
201
-
202
- def _store_parameter(self, name: str, value: str):
203
- """Store parameter in AWS Parameter Store."""
204
- self.ssm_client.put_parameter(Name=name, Value=value, Type="String", Overwrite=True)
205
- self.log.info(f"Parameter '{name}' added/updated successfully.")
206
-
207
- def _handle_oversized_data(self, name: str, size: int):
208
- """Handle data that's too large even after compression and clipping."""
209
- doc_link = "https://supercowpowers.github.io/workbench/api_classes/df_store"
210
- self.log.error(f"Compressed size {size} bytes, cannot store > 4KB")
211
- self.log.error(f"For larger data use the DFStore() class ({doc_link})")
212
-
213
- def delete(self, name: str):
214
- """Delete a parameter from the AWS Parameter Store.
215
-
216
- Args:
217
- name (str): The name of the parameter to delete.
218
- """
219
- try:
220
- # Delete the parameter from Parameter Store
221
- self.ssm_client.delete_parameter(Name=name)
222
- self.log.info(f"Parameter '{name}' deleted successfully.")
223
- except Exception as e:
224
- self.log.error(f"Failed to delete parameter '{name}': {e}")
225
-
226
- def delete_recursive(self, prefix: str):
227
- """Delete all parameters with a given prefix from the AWS Parameter Store.
228
-
229
- Args:
230
- prefix (str): The prefix of the parameters to delete.
231
- """
232
- # List all parameters with the given prefix
233
- parameters = self.list(prefix=prefix)
234
- for param in parameters:
235
- self.delete(param)
236
-
237
- def __repr__(self):
238
- """Return a string representation of the AWSParameterStore object."""
239
- return "\n".join(self.list())
240
-
241
-
242
- if __name__ == "__main__":
243
- """Exercise the AWSParameterStore Class"""
244
-
245
- # Create a AWSParameterStore manager
246
- param_store = AWSParameterStore()
247
-
248
- # List the parameters
249
- print("Listing Parameters...")
250
- print(param_store.list())
251
-
252
- # Add a new parameter
253
- param_store.upsert("/workbench/test", "value")
254
-
255
- # Get the parameter
256
- print(f"Getting parameter 'test': {param_store.get('/workbench/test')}")
257
-
258
- # Add a dictionary as a parameter
259
- sample_dict = {"key": "str_value", "awesome_value": 4.2}
260
- param_store.upsert("/workbench/my_data", sample_dict)
261
-
262
- # Retrieve the parameter as a dictionary
263
- retrieved_value = param_store.get("/workbench/my_data")
264
- print("Retrieved value:", retrieved_value)
265
-
266
- # List the parameters
267
- print("Listing Parameters...")
268
- print(param_store.list())
269
-
270
- # List the parameters with a prefix
271
- print("Listing Parameters with prefix '/workbench':")
272
- print(param_store.list("/workbench"))
273
-
274
- # Delete the parameters
275
- param_store.delete("/workbench/test")
276
- param_store.delete("/workbench/my_data")
277
-
278
- # Out of scope tests
279
- param_store.upsert("test", "value")
280
- param_store.delete("test")