craft-ai-sdk 0.51.0__tar.gz → 0.52.0__tar.gz

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.

Potentially problematic release.


This version of craft-ai-sdk might be problematic. Click here for more details.

Files changed (23) hide show
  1. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/PKG-INFO +1 -1
  2. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/__init__.py +1 -1
  3. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/core/deployments.py +99 -21
  4. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/core/endpoints.py +8 -4
  5. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/core/pipeline_executions.py +15 -6
  6. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/core/pipelines.py +10 -3
  7. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/core/steps.py +9 -3
  8. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/sdk.py +1 -1
  9. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/documentation.pdf +0 -0
  10. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/pyproject.toml +1 -1
  11. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/setup.py +1 -1
  12. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/LICENSE +0 -0
  13. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/README.md +0 -0
  14. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/constants.py +0 -0
  15. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/core/data_store.py +0 -0
  16. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/core/environment_variables.py +0 -0
  17. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/core/pipeline_metrics.py +0 -0
  18. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/core/resource_metrics.py +0 -0
  19. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/core/users.py +0 -0
  20. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/exceptions.py +0 -0
  21. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/io.py +0 -0
  22. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/utils.py +0 -0
  23. {craft_ai_sdk-0.51.0 → craft_ai_sdk-0.52.0}/craft_ai_sdk/warnings.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: craft-ai-sdk
3
- Version: 0.51.0
3
+ Version: 0.52.0
4
4
  Summary: Craft AI MLOps platform SDK
5
5
  Home-page: https://www.craft.ai/
6
6
  License: Apache-2.0
@@ -14,4 +14,4 @@ from .io import ( # noqa: F401
14
14
  )
15
15
 
16
16
 
17
- __version__ = "0.51.0"
17
+ __version__ = "0.52.0"
@@ -1,10 +1,7 @@
1
- import time
2
-
3
1
  from ..constants import (
4
2
  DEPLOYMENT_EXECUTION_RULES,
5
3
  DEPLOYMENT_MODES,
6
4
  DEPLOYMENT_STATUS,
7
- CREATION_REQUESTS_RETRY_INTERVAL,
8
5
  )
9
6
  from ..io import InputSource, OutputDestination
10
7
  from ..sdk import BaseCraftAiSdk
@@ -156,14 +153,96 @@ def create_deployment(
156
153
  following keys:
157
154
 
158
155
  * ``"name"`` (:obj:`str`): Name of the deployment.
159
- * ``"endpoint_token"`` (:obj:`str`): Token of the endpoint used to
160
- trigger the deployment. Note that this token is only returned if
161
- ``execution_rule`` is ``"endpoint"``.
162
- * ``"schedule"`` (:obj:`str`): Schedule of the deployment. Note that
163
- this schedule is only returned if ``execution_rule`` is ``"periodic"``.
164
- * ``"human_readable_schedule"`` (:obj:`str`): Human readable schedule
165
- of the deployment. Note that this schedule is only returned if
166
- ``execution_rule`` is ``"periodic"``.
156
+ * ``"mode"`` (:obj:`str`): The deployment mode. Can be
157
+ ``"elastic"`` or ``"low_latency"``.
158
+ * ``"pipeline"`` (:obj:`dict`): Pipeline associated to the deployment
159
+ represented as :obj:`dict` with the following keys:
160
+
161
+ * ``"name"`` (:obj:`str`): Name of the pipeline.
162
+
163
+ * ``"inputs_mapping"`` (:obj:`list` of :obj:`dict`): List of inputs
164
+ mapping represented as :obj:`dict` with the following keys:
165
+
166
+ * ``"pipeline_input_name"`` (:obj:`str`): Name of the step input.
167
+ * ``"data_type"`` (:obj:`str`): Data type of the step input.
168
+ * ``"description"`` (:obj:`str`): Description of the step input.
169
+ * ``"constant_value"`` (:obj:`str`): Constant value of the step input.
170
+ Note that this key is only returned if the step input is mapped to a
171
+ constant value.
172
+ * ``"environment_variable_name"`` (:obj:`str`): Name of the environment
173
+ variable. Note that this key is only returned if the step input is
174
+ mapped to an environment variable.
175
+ * ``"endpoint_input_name"`` (:obj:`str`): Name of the endpoint input.
176
+ Note that this key is only returned if the step input is mapped to an
177
+ endpoint input.
178
+ * ``"is_null"`` (:obj:`bool`): Whether the step input is mapped to null.
179
+ Note that this key is only returned if the step input is mapped to
180
+ null.
181
+ * ``"datastore_path"`` (:obj:`str`): Datastore path of the step input.
182
+ Note that this key is only returned if the step input is mapped to the
183
+ datastore.
184
+ * ``"is_required"`` (:obj:`bool`): Whether the step input is required.
185
+ Note that this key is only returned if the step input is required.
186
+ * ``"default_value"`` (:obj:`str`): Default value of the step input.
187
+ Note that this key is only returned if the step input has a default
188
+ value.
189
+
190
+ * ``"outputs_mapping"`` (:obj:`list` of :obj:`dict`): List of outputs
191
+ mapping represented as :obj:`dict` with the following keys:
192
+
193
+ * ``"pipeline_output_name"`` (:obj:`str`): Name of the step output.
194
+ * ``"data_type"`` (:obj:`str`): Data type of the step output.
195
+ * ``"description"`` (:obj:`str`): Description of the step output.
196
+ * ``"endpoint_output_name"`` (:obj:`str`): Name of the endpoint output.
197
+ Note that this key is only returned if the step output is mapped to an
198
+ endpoint output.
199
+ * ``"is_null"`` (:obj:`bool`): Whether the step output is mapped to null.
200
+ Note that this key is only returned if the step output is mapped to
201
+ null.
202
+ * ``"datastore_path"`` (:obj:`str`): Datastore path of the step output.
203
+ Note that this key is only returned if the step output is mapped to
204
+ the datastore.
205
+
206
+ * ``"endpoint_token"`` (:obj:`str`): Token of the endpoint. Note that this
207
+ key is only returned if the deployment is an endpoint.
208
+ * ``"schedule"`` (:obj:`str`): Schedule of the deployment. Note that this key is
209
+ only returned if the ``execution_rule``of the deployment is ``"periodic"``.
210
+ * ``"human_readable_schedule"`` (:obj:`str`): Human readable schedule of the
211
+ deployment. Note that this key is only returned if the ``execution_rule`` of
212
+ the deployment is ``"periodic"``.
213
+ * ``"created_at"`` (:obj:`str`): Date of creation of the deployment.
214
+ * ``"created_by"`` (:obj:`str`): ID of the user who created the deployment.
215
+ * ``"updated_at"`` (:obj:`str`): Date of last update of the deployment.
216
+ * ``"updated_by"`` (:obj:`str`): ID of the user who last updated the
217
+ deployment.
218
+ * ``"last_execution_id"`` (:obj:`str`): ID of the last execution of the
219
+ deployment.
220
+ * ``"is_enabled"`` (:obj:`bool`): Whether the deployment is enabled.
221
+ * ``"description"`` (:obj:`str`): Description of the deployment.
222
+ * ``"execution_rule"`` (:obj:`str`): Execution rule of the deployment.
223
+ * ``"status"`` (:obj:`str`): The deployment status. Can be
224
+ ``"creation_pending"``, ``"up"``, ``"creation_failed"``, ``"down_retrying"``
225
+ or ``"standby"``.
226
+ * ``"enable_parallel_executions"`` (:obj:`bool`):
227
+ Indicates whether multiple executions can run concurrently within the same
228
+ pod. This key is only returned if the deployment mode is ``"low_latency"``.
229
+ For more detailed information, see
230
+ :ref:`enable_parallel_executions <enable_parallel_executions>` parameter
231
+ of :func:`create_deployment` method.
232
+ * ``"max_parallel_executions_per_pod"`` (:obj:`int`): Maximum number of
233
+ executions that can run at the same time on a deployment's pod in
234
+ ``"low_latency"`` mode. This key is only returned if the deployment mode is
235
+ ``"low_latency"`` and if ``"enable_parallel_executions"`` is ``True``. For
236
+ more detailed information, see
237
+ :ref:`max_parallel_executions_per_pod <max_parallel_executions_per_pod>`
238
+ parameter of :func:`create_deployment` method.
239
+ * ``"pods"`` (:obj:`list` of :obj:`dict`): List of pods associated with the
240
+ low latency deployment. Note that this key is only returned if the
241
+ deployment is in low latency mode. Each pod is represented as :obj:`dict`
242
+ with the following keys:
243
+
244
+ * ``pod_id`` (:obj:`str`): ID of the pod.
245
+ * ``status`` (:obj:`str`): Status of the pod.
167
246
 
168
247
  Note:
169
248
  When ``execution_rule`` is ``"endpoint"``:
@@ -305,10 +384,7 @@ def create_deployment(
305
384
  )
306
385
 
307
386
  start_time = sdk._get_time()
308
- created_deployment, response = sdk._post(url, json=data, get_response=True)
309
-
310
- if response.status_code != 206:
311
- return created_deployment
387
+ sdk._post(url, json=data, get_response=True, allow_redirects=False)
312
388
 
313
389
  # The deployment is not ready. Keep checking its status until it is ready
314
390
  elapsed_time = sdk._get_time() - start_time
@@ -322,8 +398,9 @@ def create_deployment(
322
398
  ]
323
399
  and elapsed_time < timeout_s
324
400
  ):
325
- time.sleep(CREATION_REQUESTS_RETRY_INTERVAL)
326
- created_deployment = get_deployment(sdk, deployment_name)
401
+ created_deployment = get_deployment(
402
+ sdk, deployment_name, wait_for_completion=True
403
+ )
327
404
 
328
405
  if created_deployment is None:
329
406
  raise SdkException(
@@ -345,7 +422,7 @@ this function stopped trying. Please check its status with "get_deployment".',
345
422
  return created_deployment
346
423
 
347
424
 
348
- def get_deployment(sdk: BaseCraftAiSdk, deployment_name):
425
+ def get_deployment(sdk: BaseCraftAiSdk, deployment_name, **kwargs):
349
426
  """Get information of a deployment.
350
427
 
351
428
  Args:
@@ -447,9 +524,10 @@ def get_deployment(sdk: BaseCraftAiSdk, deployment_name):
447
524
  * ``pod_id`` (:obj:`str`): ID of the pod.
448
525
  * ``status`` (:obj:`str`): Status of the pod.
449
526
  """
450
-
451
- url = f"{sdk.base_environment_api_url}/deployments/{deployment_name}"
452
- deployment = sdk._get(url)
527
+ wait_for_completion = kwargs.get("wait_for_completion", False)
528
+ url = f"{sdk.base_environment_api_url}/deployments/{deployment_name}\
529
+ {'' if not wait_for_completion else '?wait_for_completion=true'}"
530
+ deployment = sdk._get(url, allow_redirects=False)
453
531
  if deployment is not None:
454
532
  latest_execution = sdk._get(
455
533
  f"\
@@ -8,7 +8,11 @@ from ..sdk import BaseCraftAiSdk
8
8
 
9
9
  @log_func_result("Endpoint trigger")
10
10
  def trigger_endpoint(
11
- sdk: BaseCraftAiSdk, endpoint_name, endpoint_token, inputs={}, wait_for_results=True
11
+ sdk: BaseCraftAiSdk,
12
+ endpoint_name,
13
+ endpoint_token,
14
+ inputs={},
15
+ wait_for_completion=True,
12
16
  ):
13
17
  """Trigger an endpoint.
14
18
 
@@ -21,7 +25,7 @@ def trigger_endpoint(
21
25
  For json, string, number, boolean and array inputs, the size of all values
22
26
  should be less than 0.06MB.
23
27
  Defaults to {}.
24
- wait_for_results (:obj:`bool`, optional): Automatically call
28
+ wait_for_completion (:obj:`bool`, optional): Automatically call
25
29
  `retrieve_endpoint_results` and returns the execution result.
26
30
  Defaults to `True`.
27
31
 
@@ -32,7 +36,7 @@ def trigger_endpoint(
32
36
  * ``"execution_id"`` (:obj:`str`): ID of the execution.
33
37
  * ``"outputs"`` (:obj:`dict`): Dictionary of outputs of the pipeline with
34
38
  output names as keys and corresponding values as values. Note that this
35
- key is only returned if ``wait_for_results`` is `True`.
39
+ key is only returned if ``wait_for_completion`` is `True`.
36
40
  """
37
41
 
38
42
  body = {}
@@ -56,7 +60,7 @@ def trigger_endpoint(
56
60
  )
57
61
  handle_http_response(post_result)
58
62
  execution_id = post_result.headers.get("Craft-Ai-Execution-Id", "")
59
- if wait_for_results and 200 <= post_result.status_code < 400:
63
+ if wait_for_completion and 200 <= post_result.status_code < 400:
60
64
  return retrieve_endpoint_results(
61
65
  sdk, endpoint_name, execution_id, endpoint_token
62
66
  )
@@ -1,6 +1,7 @@
1
1
  import json
2
2
  import io
3
3
 
4
+
4
5
  from ..exceptions import SdkException
5
6
  from ..io import (
6
7
  INPUT_OUTPUT_TYPES,
@@ -26,6 +27,7 @@ def run_pipeline(
26
27
  inputs=None,
27
28
  inputs_mapping=None,
28
29
  outputs_mapping=None,
30
+ wait_for_completion=True,
29
31
  ):
30
32
  """Run a pipeline.
31
33
 
@@ -46,6 +48,9 @@ def run_pipeline(
46
48
  List of output mappings, to map pipeline outputs to different
47
49
  destinations (is_null or datastore_path). See
48
50
  :class:`OutputDestination` for more details.
51
+ wait_for_completion (:obj:`bool`, optional): Wait for the end of the execution
52
+ and returns the execution result.
53
+ Defaults to `True`.
49
54
 
50
55
  Returns:
51
56
  :obj:`dict`: Pipeline execution outputs represented as a :obj:`dict` with
@@ -53,7 +58,8 @@ def run_pipeline(
53
58
 
54
59
  * ``"execution_id"`` (:obj:`str`): Name of the pipeline execution.
55
60
  * ``"outputs"`` (:obj:`dict`): Pipeline execution outputs with output
56
- names as keys and corresponding values as values.
61
+ names as keys and corresponding values as values. Note that this
62
+ key is only returned if ``wait_for_completion`` is `True`.
57
63
  """
58
64
  if inputs is None:
59
65
  inputs = {}
@@ -110,25 +116,28 @@ OutputDestination."
110
116
  # Execute pipeline
111
117
  url = f"{sdk.base_environment_api_url}/pipelines/{pipeline_name}/run"
112
118
  post_result = sdk._post(url, data=data, files=files, allow_redirects=False)
119
+ execution_id = post_result["execution_id"]
120
+
113
121
  for file in files.values():
114
122
  file.close()
115
123
  log_action(
116
124
  sdk,
117
- f"The pipeline execution may take a while, \
125
+ f'The pipeline execution may take a while, \
118
126
  you can check its status and get information on the Executions page of the front-end.\n\
119
- Its execution ID is \"{post_result['execution_id']}\".",
127
+ Its execution ID is "{execution_id}".',
120
128
  )
121
129
 
122
130
  # Wait for pipeline execution to finish
123
- execution_id = post_result["execution_id"]
124
- return _retrieve_pipeline_execution_outputs(sdk, execution_id)
131
+ if wait_for_completion:
132
+ return _retrieve_pipeline_execution_outputs(sdk, execution_id)
133
+ return {"execution_id": execution_id}
125
134
 
126
135
 
127
136
  @log_func_result("Pipeline execution results retrieval")
128
137
  def _retrieve_pipeline_execution_outputs(sdk: BaseCraftAiSdk, execution_id):
129
138
  url = (
130
139
  f"{sdk.base_environment_api_url}"
131
- f"/executions/{execution_id}/outputs?wait_for_results=true"
140
+ f"/executions/{execution_id}/outputs?wait_for_completion=true"
132
141
  )
133
142
 
134
143
  do_get = use_authentication(
@@ -197,12 +197,19 @@ def create_pipeline(
197
197
  return _create_pipeline_with_step(sdk, pipeline_name, function_path)
198
198
 
199
199
  # or with create_pipeline(:pipeline_name:, step_name=:step_name:).
200
- if args_are_none and function_path is None and kwargs.keys() == {"step_name"}:
200
+ if "step_name" in kwargs:
201
+ if not args_are_none or function_path is not None or len(kwargs) > 1:
202
+ raise ValueError(
203
+ "create_pipeline() got unexpected arguments. When specifying the"
204
+ "'step_name' keyword argument, no other argument than 'pipeline_name'"
205
+ "should be provided."
206
+ )
207
+
201
208
  return _create_pipeline_with_step(sdk, pipeline_name, kwargs["step_name"])
202
209
 
203
210
  if len(kwargs) != 0:
204
211
  raise ValueError(
205
- f"create_pipeline() got an unexpected keyword argument {kwargs.keys()[0]}"
212
+ f"create_pipeline() got unexpected keyword arguments: {kwargs}"
206
213
  )
207
214
 
208
215
  # Otherwise, the pipeline is created with a "hidden" step
@@ -244,7 +251,7 @@ def create_pipeline(
244
251
 
245
252
  # The pipeline is still building. Keep checking its status until it is ready
246
253
  return _wait_create_until_ready(
247
- sdk, pipeline_name, get_pipeline, timeout_s, start_time
254
+ sdk, pipeline_name, get_pipeline, timeout_s, start_time, get_pipeline_logs
248
255
  )
249
256
 
250
257
 
@@ -120,10 +120,10 @@ def _remove_id_from_step(step):
120
120
  return step
121
121
 
122
122
 
123
- def _wait_create_until_ready(sdk, name, get_func, timeout_s, start_time):
123
+ def _wait_create_until_ready(sdk, name, get_func, timeout_s, start_time, get_log_func):
124
124
  elapsed_time = sdk._get_time() - start_time
125
125
  status = "creation_pending"
126
- while status != "ready" and elapsed_time < timeout_s:
126
+ while status == "creation_pending" and elapsed_time < timeout_s:
127
127
  time.sleep(CREATION_REQUESTS_RETRY_INTERVAL)
128
128
  created_obj = get_func(sdk, name)
129
129
  if created_obj is None:
@@ -136,6 +136,12 @@ def _wait_create_until_ready(sdk, name, get_func, timeout_s, start_time):
136
136
  status = created_obj.get("creation_info", {}).get("status", None)
137
137
  elapsed_time = sdk._get_time() - start_time
138
138
 
139
+ if status == "creation_failed":
140
+ raise SdkException(
141
+ f'The creation of "{name}" has failed. You can check the logs with '
142
+ f'the "{get_log_func.__name__}" function.',
143
+ name="CreationFailed",
144
+ )
139
145
  if status != "ready":
140
146
  raise SdkException(
141
147
  f'The creation of "{name}" was not ready in time. It is still being '
@@ -324,7 +330,7 @@ def create_step(
324
330
 
325
331
  # The step is still building. Keep checking its status until it is ready
326
332
  created_step = _wait_create_until_ready(
327
- sdk, step_name, get_step, timeout_s, start_time
333
+ sdk, step_name, get_step, timeout_s, start_time, get_step_logs
328
334
  )
329
335
  return _remove_id_from_step(created_step)
330
336
 
@@ -130,7 +130,7 @@ class CraftAiSdk(BaseCraftAiSdk):
130
130
  os.environ.get("CRAFT_AI__MULTIPART_PART_SIZE__B", str(38 * 256 * 1024))
131
131
  )
132
132
  _access_token_margin = timedelta(seconds=30)
133
- _version = "0.51.0" # Would be better to share it somewhere
133
+ _version = "0.52.0" # Would be better to share it somewhere
134
134
 
135
135
  def __init__(
136
136
  self,
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "craft-ai-sdk"
3
- version = "0.51.0"
3
+ version = "0.52.0"
4
4
  description = "Craft AI MLOps platform SDK"
5
5
  license = "Apache-2.0"
6
6
  authors = ["Craft AI <contact@craft.ai>"]
@@ -24,7 +24,7 @@ entry_points = \
24
24
 
25
25
  setup_kwargs = {
26
26
  'name': 'craft-ai-sdk',
27
- 'version': '0.51.0',
27
+ 'version': '0.52.0',
28
28
  'description': 'Craft AI MLOps platform SDK',
29
29
  'long_description': '# Craft AI Python SDK\n\nThis Python SDK lets you interact with Craft AI MLOps Platform.\n\n## Installation\nThis project relies on **Python 3.8+**. Once a supported version of Python is installed, you can install `craft-ai-sdk` from PyPI with:\n\n```console\npip install craft-ai-sdk\n```\n\n## Basic usage\nYou can configure the SDK by instantiating the `CraftAiSdk` class in this way:\n\n```python\nfrom craft_ai_sdk import CraftAiSdk\n\nCRAFT_AI_SDK_TOKEN = # your access key obtained from your settings page\nCRAFT_AI_ENVIRONMENT_URL = # url to your environment\n\nsdk = CraftAiSdk(sdk_token=CRAFT_AI_SDK_TOKEN, environment_url=CRAFT_AI_ENVIRONMENT_URL)\n```\n\nIf using the SDK in interactive mode, some additional feedbacks will be printed. You can force disable or enable those logs by either\n* Setting the `verbose_log` SDK parameter\n* Or setting the `SDK_VERBOSE_LOG` env var\n',
30
30
  'author': 'Craft AI',
File without changes
File without changes