lightning-sdk 2025.7.17__py3-none-any.whl → 2025.7.22__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 (68) hide show
  1. lightning_sdk/__init__.py +3 -2
  2. lightning_sdk/api/cloud_account_api.py +154 -0
  3. lightning_sdk/api/deployment_api.py +11 -0
  4. lightning_sdk/api/job_api.py +9 -0
  5. lightning_sdk/api/mmt_api.py +9 -0
  6. lightning_sdk/api/pipeline_api.py +4 -3
  7. lightning_sdk/api/studio_api.py +19 -5
  8. lightning_sdk/cli/clusters_menu.py +3 -3
  9. lightning_sdk/cli/create.py +22 -10
  10. lightning_sdk/cli/deploy/_auth.py +19 -3
  11. lightning_sdk/cli/deploy/serve.py +18 -4
  12. lightning_sdk/cli/entrypoint.py +1 -1
  13. lightning_sdk/cli/start.py +37 -7
  14. lightning_sdk/deployment/deployment.py +8 -0
  15. lightning_sdk/job/base.py +27 -3
  16. lightning_sdk/job/job.py +28 -4
  17. lightning_sdk/job/v1.py +10 -1
  18. lightning_sdk/job/v2.py +15 -1
  19. lightning_sdk/lightning_cloud/openapi/__init__.py +9 -1
  20. lightning_sdk/lightning_cloud/openapi/api/assistants_service_api.py +335 -0
  21. lightning_sdk/lightning_cloud/openapi/api/billing_service_api.py +153 -48
  22. lightning_sdk/lightning_cloud/openapi/models/__init__.py +9 -1
  23. lightning_sdk/lightning_cloud/openapi/models/blogposts_id_body.py +53 -1
  24. lightning_sdk/lightning_cloud/openapi/models/conversations_id_body1.py +123 -0
  25. lightning_sdk/lightning_cloud/openapi/models/messages_id_body.py +123 -0
  26. lightning_sdk/lightning_cloud/openapi/models/project_id_schedules_body.py +29 -3
  27. lightning_sdk/lightning_cloud/openapi/models/schedules_id_body.py +27 -1
  28. lightning_sdk/lightning_cloud/openapi/models/user_id_upgradetrigger_body.py +175 -0
  29. lightning_sdk/lightning_cloud/openapi/models/v1_blog_post.py +53 -1
  30. lightning_sdk/lightning_cloud/openapi/models/v1_conversation.py +27 -1
  31. lightning_sdk/lightning_cloud/openapi/models/v1_create_billing_upgrade_trigger_record_response.py +97 -0
  32. lightning_sdk/lightning_cloud/openapi/models/v1_create_blog_post_request.py +53 -1
  33. lightning_sdk/lightning_cloud/openapi/models/v1_create_checkout_session_request.py +27 -1
  34. lightning_sdk/lightning_cloud/openapi/models/v1_create_subscription_checkout_session_request.py +29 -3
  35. lightning_sdk/lightning_cloud/openapi/models/{v1_get_clickhouse_assistant_session_daily_aggregated_response.py → v1_get_assistant_session_daily_aggregated_response.py} +22 -22
  36. lightning_sdk/lightning_cloud/openapi/models/v1_kubernetes_direct_v1.py +79 -1
  37. lightning_sdk/lightning_cloud/openapi/models/v1_like_status.py +104 -0
  38. lightning_sdk/lightning_cloud/openapi/models/v1_list_published_managed_endpoint_models_response.py +123 -0
  39. lightning_sdk/lightning_cloud/openapi/models/v1_message.py +27 -1
  40. lightning_sdk/lightning_cloud/openapi/models/v1_quote_subscription_response.py +27 -1
  41. lightning_sdk/lightning_cloud/openapi/models/v1_schedule.py +27 -1
  42. lightning_sdk/lightning_cloud/openapi/models/v1_update_conversation_like_response.py +149 -0
  43. lightning_sdk/lightning_cloud/openapi/models/v1_update_conversation_message_like_response.py +149 -0
  44. lightning_sdk/lightning_cloud/openapi/models/v1_user_features.py +1 -261
  45. lightning_sdk/llm/llm.py +29 -5
  46. lightning_sdk/machine.py +12 -0
  47. lightning_sdk/mmt/base.py +20 -2
  48. lightning_sdk/mmt/mmt.py +25 -3
  49. lightning_sdk/mmt/v1.py +7 -1
  50. lightning_sdk/mmt/v2.py +21 -2
  51. lightning_sdk/organization.py +4 -0
  52. lightning_sdk/pipeline/pipeline.py +16 -5
  53. lightning_sdk/pipeline/printer.py +5 -3
  54. lightning_sdk/pipeline/schedule.py +844 -1
  55. lightning_sdk/pipeline/steps.py +19 -4
  56. lightning_sdk/sandbox.py +4 -1
  57. lightning_sdk/serve.py +2 -0
  58. lightning_sdk/studio.py +79 -39
  59. lightning_sdk/teamspace.py +14 -8
  60. lightning_sdk/utils/resolve.py +29 -2
  61. {lightning_sdk-2025.7.17.dist-info → lightning_sdk-2025.7.22.dist-info}/METADATA +1 -1
  62. {lightning_sdk-2025.7.17.dist-info → lightning_sdk-2025.7.22.dist-info}/RECORD +67 -59
  63. lightning_sdk/api/cluster_api.py +0 -119
  64. /lightning_sdk/cli/{inspect.py → inspection.py} +0 -0
  65. {lightning_sdk-2025.7.17.dist-info → lightning_sdk-2025.7.22.dist-info}/LICENSE +0 -0
  66. {lightning_sdk-2025.7.17.dist-info → lightning_sdk-2025.7.22.dist-info}/WHEEL +0 -0
  67. {lightning_sdk-2025.7.17.dist-info → lightning_sdk-2025.7.22.dist-info}/entry_points.txt +0 -0
  68. {lightning_sdk-2025.7.17.dist-info → lightning_sdk-2025.7.22.dist-info}/top_level.txt +0 -0
lightning_sdk/mmt/mmt.py CHANGED
@@ -1,12 +1,13 @@
1
1
  from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Union
2
2
 
3
+ from lightning_sdk.api.cloud_account_api import CloudAccountApi
3
4
  from lightning_sdk.mmt.base import MMTMachine, _BaseMMT
4
5
  from lightning_sdk.mmt.v1 import _MMTV1
5
6
  from lightning_sdk.mmt.v2 import _MMTV2
6
7
  from lightning_sdk.utils.resolve import _setup_logger
7
8
 
8
9
  if TYPE_CHECKING:
9
- from lightning_sdk.machine import Machine
10
+ from lightning_sdk.machine import CloudProvider, Machine
10
11
  from lightning_sdk.organization import Organization
11
12
  from lightning_sdk.status import Status
12
13
  from lightning_sdk.studio import Studio
@@ -75,6 +76,7 @@ class MMT(_BaseMMT):
75
76
  )
76
77
 
77
78
  self._internal_mmt = mmt
79
+ self._cloud_account_api = CloudAccountApi()
78
80
 
79
81
  @classmethod
80
82
  def run(
@@ -89,12 +91,14 @@ class MMT(_BaseMMT):
89
91
  org: Union[str, "Organization", None] = None,
90
92
  user: Union[str, "User", None] = None,
91
93
  cloud_account: Optional[str] = None,
94
+ cloud_provider: Optional[Union["CloudProvider", str]] = None,
92
95
  env: Optional[Dict[str, str]] = None,
93
96
  interruptible: bool = False,
94
97
  image_credentials: Optional[str] = None,
95
98
  cloud_account_auth: bool = False,
96
99
  entrypoint: str = "sh -c",
97
100
  path_mappings: Optional[Dict[str, str]] = None,
101
+ max_runtime: Optional[int] = None,
98
102
  artifacts_local: Optional[str] = None,
99
103
  artifacts_remote: Optional[str] = None,
100
104
  cluster: Optional[str] = None, # deprecated in favor of cloud_account
@@ -114,7 +118,11 @@ class MMT(_BaseMMT):
114
118
  user: The user owning the teamspace (if any). Defaults to the current user.
115
119
  cloud_account: The cloud account to run the job on.
116
120
  Defaults to the studio cloud account if running with studio compute env.
117
- If not provided will fall back to the teamspaces default cloud account.
121
+ If not provided and `cloud_account_provider` is set, will resolve cluster from this, else
122
+ will fall back to the teamspaces default cloud account.
123
+ cloud_account_provider: The provider to select the cloud-account from.
124
+ If set, must be in agreement with the provider from the cloud_account (if specified).
125
+ If not specified, falls backto the teamspace default cloud account.
118
126
  env: Environment variables to set inside the job.
119
127
  interruptible: Whether the job should run on interruptible instances. They are cheaper but can be preempted.
120
128
  image_credentials: The credentials used to pull the image. Required if the image is private.
@@ -145,6 +153,7 @@ class MMT(_BaseMMT):
145
153
  org=org,
146
154
  user=user,
147
155
  cloud_account=cloud_account,
156
+ cloud_provider=cloud_provider,
148
157
  env=env,
149
158
  interruptible=interruptible,
150
159
  image_credentials=image_credentials,
@@ -154,6 +163,7 @@ class MMT(_BaseMMT):
154
163
  artifacts_local=artifacts_local,
155
164
  artifacts_remote=artifacts_remote,
156
165
  cluster=cluster, # deprecated in favor of cloud_account
166
+ max_runtime=max_runtime,
157
167
  )
158
168
  # required for typing with "MMT"
159
169
  assert isinstance(ret_val, cls)
@@ -173,10 +183,12 @@ class MMT(_BaseMMT):
173
183
  env: Optional[Dict[str, str]] = None,
174
184
  interruptible: bool = False,
175
185
  cloud_account: Optional[str] = None,
186
+ cloud_provider: Optional[Union["CloudProvider", str]] = None,
176
187
  image_credentials: Optional[str] = None,
177
188
  cloud_account_auth: bool = False,
178
189
  entrypoint: str = "sh -c",
179
190
  path_mappings: Optional[Dict[str, str]] = None,
191
+ max_runtime: Optional[int] = None,
180
192
  artifacts_local: Optional[str] = None, # deprecated in favor of path_mappings
181
193
  artifacts_remote: Optional[str] = None, # deprecated in favor of path_mappings
182
194
  ) -> "MMT":
@@ -193,7 +205,11 @@ class MMT(_BaseMMT):
193
205
  interruptible: Whether the job should run on interruptible instances. They are cheaper but can be preempted.
194
206
  cloud_account: The cloud account to run the job on.
195
207
  Defaults to the studio cloud account if running with studio compute env.
196
- If not provided will fall back to the teamspaces default cloud account.
208
+ If not provided and `cloud_account_provider` is set, will resolve cluster from this, else
209
+ will fall back to the teamspaces default cloud account.
210
+ cloud_account_provider: The provider to select the cloud-account from.
211
+ If set, must be in agreement with the provider from the cloud_account (if specified).
212
+ If not specified, falls backto the teamspace default cloud account.
197
213
  image_credentials: The credentials used to pull the image. Required if the image is private.
198
214
  This should be the name of the respective credentials secret created on the Lightning AI platform.
199
215
  cloud_account_auth: Whether to authenticate with the cloud account to pull the image.
@@ -211,11 +227,16 @@ class MMT(_BaseMMT):
211
227
  }
212
228
  If the path inside the connection is omitted it's assumed to be the root path of that connection.
213
229
  Only applicable when submitting docker jobs.
230
+ max_runtime: the duration (in seconds) for which to allocate the machine.
231
+ Irrelevant for most machines, required for some of the top-end machines on GCP.
232
+ If in doubt, set it. Won't have an effect on machines not requiring it.
233
+ Defaults to 3h
214
234
  """
215
235
  self._job = self._internal_mmt._submit(
216
236
  num_machines=num_machines,
217
237
  machine=machine,
218
238
  cloud_account=cloud_account,
239
+ cloud_provider=cloud_provider,
219
240
  command=command,
220
241
  studio=studio,
221
242
  image=image,
@@ -227,6 +248,7 @@ class MMT(_BaseMMT):
227
248
  path_mappings=path_mappings,
228
249
  artifacts_local=artifacts_local,
229
250
  artifacts_remote=artifacts_remote,
251
+ max_runtime=max_runtime,
230
252
  )
231
253
  return self
232
254
 
lightning_sdk/mmt/v1.py CHANGED
@@ -7,7 +7,7 @@ from lightning_sdk.job.work import Work
7
7
  from lightning_sdk.status import Status
8
8
 
9
9
  if TYPE_CHECKING:
10
- from lightning_sdk.machine import Machine
10
+ from lightning_sdk.machine import CloudProvider, Machine
11
11
  from lightning_sdk.organization import Organization
12
12
  from lightning_sdk.studio import Studio
13
13
  from lightning_sdk.teamspace import Teamspace
@@ -50,10 +50,12 @@ class _MMTV1(_BaseMMT):
50
50
  env: Optional[Dict[str, str]] = None,
51
51
  interruptible: bool = False,
52
52
  cloud_account: Optional[str] = None,
53
+ cloud_provider: Optional[Union["CloudProvider", str]] = None,
53
54
  image_credentials: Optional[str] = None,
54
55
  cloud_account_auth: bool = False,
55
56
  entrypoint: str = "sh -c",
56
57
  path_mappings: Optional[Dict[str, str]] = None,
58
+ max_runtime: Optional[int] = None,
57
59
  artifacts_local: Optional[str] = None,
58
60
  artifacts_remote: Optional[str] = None,
59
61
  ) -> "_MMTV1":
@@ -90,6 +92,10 @@ class _MMTV1(_BaseMMT):
90
92
  To use the pre-defined entrypoint of the provided image, set this to an empty string.
91
93
  Only applicable when submitting docker jobs.
92
94
  path_mappings: The mappings from data connection inside your container (not supported)
95
+ max_runtime: the duration (in seconds) for which to allocate the machine.
96
+ Irrelevant for most machines, required for some of the top-end machines on GCP.
97
+ If in doubt, set it. Won't have an effect on machines not requiring it.
98
+ Defaults to 3h
93
99
 
94
100
  """
95
101
  raise NotImplementedError("Cannot submit new mmts with MMTV1!")
lightning_sdk/mmt/v2.py CHANGED
@@ -6,7 +6,7 @@ from lightning_sdk.status import Status
6
6
 
7
7
  if TYPE_CHECKING:
8
8
  from lightning_sdk.job.job import Job
9
- from lightning_sdk.machine import Machine
9
+ from lightning_sdk.machine import CloudProvider, Machine
10
10
  from lightning_sdk.organization import Organization
11
11
  from lightning_sdk.studio import Studio
12
12
  from lightning_sdk.teamspace import Teamspace
@@ -49,10 +49,12 @@ class _MMTV2(_BaseMMT):
49
49
  env: Optional[Dict[str, str]] = None,
50
50
  interruptible: bool = False,
51
51
  cloud_account: Optional[str] = None,
52
+ cloud_provider: Optional[Union["CloudProvider", str]] = None,
52
53
  image_credentials: Optional[str] = None,
53
54
  cloud_account_auth: bool = False,
54
55
  entrypoint: str = "sh -c",
55
56
  path_mappings: Optional[Dict[str, str]] = None,
57
+ max_runtime: Optional[int] = None,
56
58
  artifacts_local: Optional[str] = None, # deprecated in favor of path_mappings
57
59
  artifacts_remote: Optional[str] = None, # deprecated in favor of path_mappings
58
60
  ) -> "_MMTV2":
@@ -69,7 +71,11 @@ class _MMTV2(_BaseMMT):
69
71
  interruptible: Whether the job should run on interruptible instances. They are cheaper but can be preempted.
70
72
  cloud_account: The cloud account to run the job on.
71
73
  Defaults to the studio cloud account if running with studio compute env.
72
- If not provided will fall back to the teamspaces default cloud account.
74
+ If not provided and `cloud_account_provider` is set, will resolve cluster from this, else
75
+ will fall back to the teamspaces default cloud account.
76
+ cloud_account_provider: The provider to select the cloud-account from.
77
+ If set, must be in agreement with the provider from the cloud_account (if specified).
78
+ If not specified, falls backto the teamspace default cloud account.
73
79
  image_credentials: The credentials used to pull the image. Required if the image is private.
74
80
  This should be the name of the respective credentials secret created on the Lightning AI platform.
75
81
  cloud_account_auth: Whether to authenticate with the cloud account to pull the image.
@@ -87,6 +93,10 @@ class _MMTV2(_BaseMMT):
87
93
  }
88
94
  If the path inside the connection is omitted it's assumed to be the root path of that connection.
89
95
  Only applicable when submitting docker jobs.
96
+ max_runtime: the duration (in seconds) for which to allocate the machine.
97
+ Irrelevant for most machines, required for some of the top-end machines on GCP.
98
+ If in doubt, set it. Won't have an effect on machines not requiring it.
99
+ Defaults to 3h
90
100
  """
91
101
  # Command is required if Studio is provided to know what to run
92
102
  # Image is mutually exclusive with Studio
@@ -104,6 +114,14 @@ class _MMTV2(_BaseMMT):
104
114
  studio_id = None
105
115
  if image is None:
106
116
  raise ValueError("either image or studio must be provided")
117
+
118
+ cloud_account = self._cloud_account_api.resolve_cloud_account(
119
+ self._teamspace.id,
120
+ cloud_account=cloud_account,
121
+ cloud_provider=cloud_provider,
122
+ default_cloud_account=self._teamspace.default_cloud_account,
123
+ )
124
+
107
125
  submitted = self._job_api.submit_job(
108
126
  name=self.name,
109
127
  num_machines=num_machines,
@@ -121,6 +139,7 @@ class _MMTV2(_BaseMMT):
121
139
  path_mappings=path_mappings,
122
140
  artifacts_local=artifacts_local,
123
141
  artifacts_remote=artifacts_remote,
142
+ max_runtime=max_runtime,
124
143
  )
125
144
  self._job = submitted
126
145
  self._name = submitted.name
@@ -40,6 +40,10 @@ class Organization(Owner):
40
40
  """The organization's ID."""
41
41
  return self._org.id
42
42
 
43
+ @property
44
+ def default_cloud_account(self) -> Optional[str]:
45
+ return self._org.preferred_cluster or None
46
+
43
47
  def __repr__(self) -> str:
44
48
  """Returns reader friendly representation."""
45
49
  return f"Organization(name={self.name})"
@@ -1,9 +1,12 @@
1
1
  import os
2
- from typing import TYPE_CHECKING, List, Optional, Union
2
+ from typing import List, Optional, Union
3
3
 
4
+ from lightning_sdk.api.cloud_account_api import CloudAccountApi
4
5
  from lightning_sdk.api.pipeline_api import PipelineApi
6
+ from lightning_sdk.machine import CloudProvider
5
7
  from lightning_sdk.organization import Organization
6
8
  from lightning_sdk.pipeline.printer import PipelinePrinter
9
+ from lightning_sdk.pipeline.schedule import _TIMEZONES, Schedule
7
10
  from lightning_sdk.pipeline.steps import DeploymentStep, JobStep, MMTStep, _get_studio
8
11
  from lightning_sdk.pipeline.utils import prepare_steps
9
12
  from lightning_sdk.services.utilities import _get_cluster
@@ -12,9 +15,6 @@ from lightning_sdk.teamspace import Teamspace
12
15
  from lightning_sdk.user import User
13
16
  from lightning_sdk.utils.resolve import _resolve_teamspace
14
17
 
15
- if TYPE_CHECKING:
16
- from lightning_sdk.pipeline.schedule import Schedule
17
-
18
18
 
19
19
  class Pipeline:
20
20
  def __init__(
@@ -24,6 +24,7 @@ class Pipeline:
24
24
  org: Union[str, "Organization", None] = None,
25
25
  user: Union[str, "User", None] = None,
26
26
  cloud_account: Optional[str] = None,
27
+ cloud_provider: Optional[Union[CloudProvider, str]] = None,
27
28
  shared_filesystem: Optional[bool] = None,
28
29
  studio: Optional[Union[Studio, str]] = None,
29
30
  ) -> None:
@@ -45,9 +46,14 @@ class Pipeline:
45
46
  org=org,
46
47
  user=user,
47
48
  )
49
+ if self._teamspace is None:
50
+ raise RuntimeError("Could not resolve teamspace")
48
51
 
49
52
  self._pipeline_api = PipelineApi()
50
- self._cloud_account = cloud_account
53
+ self._cloud_account_api = CloudAccountApi()
54
+ self._cloud_account = self._cloud_account_api.resolve_cloud_account(
55
+ self._teamspace.id, cloud_account, cloud_provider, self._teamspace.default_cloud_account
56
+ )
51
57
  self._default_cluster = _get_cluster(
52
58
  client=self._pipeline_api._client, project_id=self._teamspace.id, cluster_id=cloud_account
53
59
  )
@@ -108,6 +114,11 @@ class Pipeline:
108
114
  if schedule.name is None:
109
115
  schedule.name = f"schedule-{schedule_idx}"
110
116
 
117
+ if schedule.timezone is not None and schedule.timezone not in _TIMEZONES:
118
+ raise ValueError(
119
+ f"The schedule {schedule.name} timezone isn't supported. Available list is {_TIMEZONES}. Found {schedule.timezone}." # noqa: E501
120
+ )
121
+
111
122
  parent_pipeline_id = None if self._pipeline is None else self._pipeline.id
112
123
 
113
124
  self._pipeline = self._pipeline_api.create_pipeline(
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  from typing import Any, ClassVar, Dict, List
3
3
 
4
- from lightning_sdk.lightning_cloud.openapi.models import V1Pipeline, V1PipelineStepType
4
+ from lightning_sdk.lightning_cloud.openapi.models import V1Pipeline, V1PipelineStepType, V1Schedule
5
5
  from lightning_sdk.pipeline.utils import _get_spec
6
6
 
7
7
 
@@ -21,7 +21,7 @@ class PipelinePrinter:
21
21
  pipeline: V1Pipeline,
22
22
  teamspace: Any,
23
23
  proto_steps: List[Any],
24
- schedules: List[Any],
24
+ schedules: List[V1Schedule],
25
25
  ) -> None:
26
26
  self._name = name
27
27
  self._initial = initial
@@ -78,7 +78,9 @@ class PipelinePrinter:
78
78
  return
79
79
 
80
80
  for schedule in self._schedules:
81
- self._print(f" - '{schedule.name}' runs on cron schedule: `{schedule.cron_expression}`")
81
+ self._print(
82
+ f" - '{schedule.name}' runs on cron schedule: `{schedule.cron_expression} in timezone {schedule.timezone or 'UTC'}`" # noqa: E501
83
+ )
82
84
 
83
85
  def _print_footer(self) -> None:
84
86
  """Prints the final link and closing message."""