lightning-sdk 2025.7.22__py3-none-any.whl → 2025.7.31__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.
- lightning_sdk/__init__.py +1 -1
- lightning_sdk/api/cloud_account_api.py +58 -8
- lightning_sdk/api/job_api.py +74 -11
- lightning_sdk/api/llm_api.py +1 -1
- lightning_sdk/api/mmt_api.py +35 -5
- lightning_sdk/api/studio_api.py +32 -3
- lightning_sdk/api/utils.py +6 -2
- lightning_sdk/cli/create.py +3 -1
- lightning_sdk/cli/deploy/serve.py +3 -1
- lightning_sdk/cli/download.py +25 -1
- lightning_sdk/cli/entrypoint.py +3 -1
- lightning_sdk/cli/list.py +5 -1
- lightning_sdk/cli/run.py +3 -1
- lightning_sdk/cli/start.py +3 -1
- lightning_sdk/cli/switch.py +3 -1
- lightning_sdk/job/v2.py +7 -1
- lightning_sdk/job/work.py +5 -1
- lightning_sdk/lightning_cloud/openapi/__init__.py +6 -1
- lightning_sdk/lightning_cloud/openapi/api/assistants_service_api.py +106 -13
- lightning_sdk/lightning_cloud/openapi/api/cloudy_service_api.py +295 -0
- lightning_sdk/lightning_cloud/openapi/api/cluster_service_api.py +93 -0
- lightning_sdk/lightning_cloud/openapi/models/__init__.py +6 -1
- lightning_sdk/lightning_cloud/openapi/models/agentmanagedendpoints_id_body.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/metricsstream_id_body.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/project_id_schedules_body.py +53 -1
- lightning_sdk/lightning_cloud/openapi/models/schedules_id_body.py +53 -1
- lightning_sdk/lightning_cloud/openapi/models/user_id_upgradetrigger_body.py +29 -3
- lightning_sdk/lightning_cloud/openapi/models/user_user_id_body.py +201 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_billing_subscription.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_cloudy_settings.py +227 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_cluster_spec.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_conversation_response_chunk.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_create_subscription_checkout_session_request.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_function_call.py +149 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_get_cluster_health_response.py +149 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_get_user_response.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_job_spec.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_kubernetes_direct_v1.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/{v1_list_published_managed_endpoint_models_response.py → v1_list_published_managed_endpoints_response.py} +23 -23
- lightning_sdk/lightning_cloud/openapi/models/v1_managed_endpoint.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_managed_model.py +95 -17
- lightning_sdk/lightning_cloud/openapi/models/v1_resource_visibility.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_response_choice.py +29 -3
- lightning_sdk/lightning_cloud/openapi/models/v1_schedule.py +53 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_service_health.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_slurm_v1.py +79 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_slurm_v1_status.py +79 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_tool_call.py +175 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_user_features.py +79 -53
- lightning_sdk/lightning_cloud/openapi/models/v1_volume_state.py +1 -0
- lightning_sdk/llm/llm.py +41 -7
- lightning_sdk/llm/public_assistants.json +32 -8
- lightning_sdk/machine.py +139 -43
- lightning_sdk/mmt/v2.py +6 -1
- lightning_sdk/models.py +1 -1
- lightning_sdk/studio.py +12 -5
- lightning_sdk/teamspace.py +5 -2
- lightning_sdk/utils/resolve.py +8 -0
- {lightning_sdk-2025.7.22.dist-info → lightning_sdk-2025.7.31.dist-info}/METADATA +7 -5
- {lightning_sdk-2025.7.22.dist-info → lightning_sdk-2025.7.31.dist-info}/RECORD +64 -59
- {lightning_sdk-2025.7.22.dist-info → lightning_sdk-2025.7.31.dist-info}/LICENSE +0 -0
- {lightning_sdk-2025.7.22.dist-info → lightning_sdk-2025.7.31.dist-info}/WHEEL +0 -0
- {lightning_sdk-2025.7.22.dist-info → lightning_sdk-2025.7.31.dist-info}/entry_points.txt +0 -0
- {lightning_sdk-2025.7.22.dist-info → lightning_sdk-2025.7.31.dist-info}/top_level.txt +0 -0
lightning_sdk/machine.py
CHANGED
|
@@ -13,60 +13,101 @@ class CloudProvider(Enum):
|
|
|
13
13
|
NEBIUS = "NEBIUS"
|
|
14
14
|
LIGHTNING = "LIGHTNING"
|
|
15
15
|
|
|
16
|
+
def __str__(self) -> str:
|
|
17
|
+
"""Converts the CloudProvider to a str."""
|
|
18
|
+
return self.value
|
|
19
|
+
|
|
16
20
|
|
|
17
21
|
@dataclass(frozen=True)
|
|
18
22
|
class Machine:
|
|
19
|
-
#
|
|
20
|
-
|
|
23
|
+
# supported CPU variations
|
|
24
|
+
CPU_X_2: ClassVar["Machine"]
|
|
25
|
+
CPU_X_4: ClassVar["Machine"]
|
|
26
|
+
CPU_X_8: ClassVar["Machine"]
|
|
27
|
+
CPU_X_16: ClassVar["Machine"]
|
|
28
|
+
# default CPU machines
|
|
21
29
|
CPU_SMALL: ClassVar["Machine"]
|
|
30
|
+
CPU: ClassVar["Machine"]
|
|
31
|
+
# supported data-prep variations (big disk)
|
|
22
32
|
DATA_PREP: ClassVar["Machine"]
|
|
23
33
|
DATA_PREP_MAX: ClassVar["Machine"]
|
|
24
34
|
DATA_PREP_ULTRA: ClassVar["Machine"]
|
|
35
|
+
|
|
36
|
+
# supported GPU types
|
|
37
|
+
# supported T4 variations
|
|
25
38
|
T4: ClassVar["Machine"]
|
|
39
|
+
T4_X_2: ClassVar["Machine"]
|
|
26
40
|
T4_X_4: ClassVar["Machine"]
|
|
41
|
+
T4_X_8: ClassVar["Machine"]
|
|
42
|
+
# supported L4 variations
|
|
27
43
|
L4: ClassVar["Machine"]
|
|
28
44
|
L4_X_2: ClassVar["Machine"]
|
|
29
45
|
L4_X_4: ClassVar["Machine"]
|
|
30
46
|
L4_X_8: ClassVar["Machine"]
|
|
31
|
-
|
|
32
|
-
A10G_X_4: ClassVar["Machine"]
|
|
33
|
-
A10G_X_8: ClassVar["Machine"]
|
|
47
|
+
# supported L40S variations
|
|
34
48
|
L40S: ClassVar["Machine"]
|
|
49
|
+
L40S_X_2: ClassVar["Machine"]
|
|
35
50
|
L40S_X_4: ClassVar["Machine"]
|
|
36
51
|
L40S_X_8: ClassVar["Machine"]
|
|
52
|
+
# supported A100 variations
|
|
53
|
+
# defaults, can be either A100 type depending on cloud provider availability
|
|
54
|
+
A100: ClassVar["Machine"]
|
|
37
55
|
A100_X_2: ClassVar["Machine"]
|
|
38
56
|
A100_X_4: ClassVar["Machine"]
|
|
39
57
|
A100_X_8: ClassVar["Machine"]
|
|
40
|
-
|
|
58
|
+
# A100 40GB versions
|
|
59
|
+
A100_40GB: ClassVar["Machine"]
|
|
60
|
+
A100_40GB_X_2: ClassVar["Machine"]
|
|
61
|
+
A100_40GB_X_4: ClassVar["Machine"]
|
|
62
|
+
A100_40GB_X_8: ClassVar["Machine"]
|
|
63
|
+
# A100 80GB versions
|
|
64
|
+
A100_80GB: ClassVar["Machine"]
|
|
65
|
+
A100_80GB_X_2: ClassVar["Machine"]
|
|
66
|
+
A100_80GB_X_4: ClassVar["Machine"]
|
|
67
|
+
A100_80GB_X_8: ClassVar["Machine"]
|
|
68
|
+
|
|
69
|
+
H100: ClassVar["Machine"]
|
|
70
|
+
H100_X_2: ClassVar["Machine"]
|
|
71
|
+
H100_X_4: ClassVar["Machine"]
|
|
41
72
|
H100_X_8: ClassVar["Machine"]
|
|
73
|
+
|
|
74
|
+
H200: ClassVar["Machine"]
|
|
42
75
|
H200_X_8: ClassVar["Machine"]
|
|
76
|
+
B200_X_8: ClassVar["Machine"]
|
|
77
|
+
|
|
78
|
+
# Specialized Machines
|
|
43
79
|
|
|
44
80
|
name: str
|
|
45
|
-
|
|
81
|
+
slug: str
|
|
82
|
+
instance_type: Optional[str] = None
|
|
83
|
+
family: Optional[str] = None
|
|
84
|
+
accelerator_count: Optional[int] = None
|
|
46
85
|
cost: Optional[float] = None
|
|
47
86
|
interruptible_cost: Optional[float] = None
|
|
48
87
|
wait_time: Optional[float] = None
|
|
49
88
|
interruptible_wait_time: Optional[float] = None
|
|
89
|
+
_include_in_cli: bool = True
|
|
50
90
|
|
|
51
91
|
def __str__(self) -> str:
|
|
52
92
|
"""String representation of the Machine."""
|
|
53
|
-
return str(self.name) if self.name else str(self.instance_type)
|
|
93
|
+
return str(self.name) if self.name else (self.slug if self.slug else str(self.instance_type))
|
|
54
94
|
|
|
55
95
|
def __eq__(self, other: object) -> bool:
|
|
56
96
|
"""Machines are equal if the instance type is equal."""
|
|
57
97
|
if isinstance(other, Machine):
|
|
58
|
-
return
|
|
98
|
+
return (
|
|
99
|
+
# equality based on raw instance type (provider specific)
|
|
100
|
+
(self.instance_type and self.instance_type == other.instance_type)
|
|
101
|
+
# equality based on slug (provider agnostic)
|
|
102
|
+
or self.slug == other.slug
|
|
103
|
+
# equality based on machine specs (e.g. A100_80GB_X_8 == A100_X_8)
|
|
104
|
+
or (self.family == other.family and self.accelerator_count == other.accelerator_count)
|
|
105
|
+
)
|
|
59
106
|
return False
|
|
60
107
|
|
|
61
108
|
def is_cpu(self) -> bool:
|
|
62
109
|
"""Whether the machine is a CPU."""
|
|
63
|
-
return (
|
|
64
|
-
self == Machine.CPU
|
|
65
|
-
or self == Machine.CPU_SMALL
|
|
66
|
-
or self == Machine.DATA_PREP
|
|
67
|
-
or self == Machine.DATA_PREP_MAX
|
|
68
|
-
or self == Machine.DATA_PREP_ULTRA
|
|
69
|
-
)
|
|
110
|
+
return self.family in ("CPU", "DATA_PREP")
|
|
70
111
|
|
|
71
112
|
@classmethod
|
|
72
113
|
def from_str(cls, machine: str, *additional_machine_ids: Any) -> "Machine":
|
|
@@ -75,34 +116,89 @@ class Machine:
|
|
|
75
116
|
)
|
|
76
117
|
for m in possible_values:
|
|
77
118
|
for machine_id in [machine, *additional_machine_ids]:
|
|
78
|
-
if machine_id in (
|
|
119
|
+
if machine_id in (
|
|
120
|
+
getattr(m, "name", None),
|
|
121
|
+
getattr(m, "instance_type", None),
|
|
122
|
+
getattr(m, "slug", None),
|
|
123
|
+
):
|
|
79
124
|
return m
|
|
80
125
|
|
|
81
126
|
if additional_machine_ids:
|
|
82
127
|
return cls(machine, *additional_machine_ids)
|
|
83
|
-
return cls(machine, machine)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
Machine.
|
|
89
|
-
Machine.
|
|
90
|
-
|
|
91
|
-
Machine.
|
|
92
|
-
Machine.
|
|
93
|
-
Machine.
|
|
94
|
-
Machine.
|
|
95
|
-
|
|
96
|
-
Machine.
|
|
97
|
-
Machine.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
Machine.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
Machine.
|
|
107
|
-
Machine.
|
|
108
|
-
Machine.
|
|
128
|
+
return cls(machine, machine, machine)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# CPU machines
|
|
132
|
+
# default CPU machines
|
|
133
|
+
Machine.CPU_SMALL = Machine(name="CPU_SMALL", slug="cpu-2", family="CPU", accelerator_count=2)
|
|
134
|
+
Machine.CPU = Machine(name="CPU", slug="cpu-4", family="CPU", accelerator_count=4)
|
|
135
|
+
# available CPU variations
|
|
136
|
+
Machine.CPU_X_2 = Machine(name="CPU_X_2", slug="cpu-2", family="CPU", accelerator_count=2)
|
|
137
|
+
Machine.CPU_X_4 = Machine(name="CPU_X_4", slug="cpu-4", family="CPU", accelerator_count=4)
|
|
138
|
+
Machine.CPU_X_8 = Machine(name="CPU_X_8", slug="cpu-8", family="CPU", accelerator_count=8)
|
|
139
|
+
Machine.CPU_X_16 = Machine(name="CPU_X_16", slug="cpu-16", family="CPU", accelerator_count=16)
|
|
140
|
+
# available data-prep (big disk) machines
|
|
141
|
+
Machine.DATA_PREP = Machine(name="DATA_PREP", slug="data-prep-mid", family="DATA_PREP", accelerator_count=32)
|
|
142
|
+
Machine.DATA_PREP_MAX = Machine(
|
|
143
|
+
name="DATA_PREP_MAX", slug="data-prep-max-large", family="DATA_PREP", accelerator_count=64
|
|
144
|
+
)
|
|
145
|
+
Machine.DATA_PREP_ULTRA = Machine(
|
|
146
|
+
name="DATA_PREP_ULTRA", slug="data-prep-ultra-extra-large", family="DATA_PREP", accelerator_count=96
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
# GPU machines
|
|
150
|
+
# available T4 machines
|
|
151
|
+
Machine.T4 = Machine(name="T4", slug="lit-t4-1", family="T4", accelerator_count=1)
|
|
152
|
+
Machine.T4_X_2 = Machine(name="T4_X_2", slug="lit-t4-2", family="T4", accelerator_count=2)
|
|
153
|
+
Machine.T4_X_4 = Machine(name="T4_X_4", slug="lit-t4-4", family="T4", accelerator_count=4)
|
|
154
|
+
Machine.T4_X_8 = Machine(name="T4_X_8", slug="lit-t4-8", family="T4", accelerator_count=8)
|
|
155
|
+
# available L4 machines
|
|
156
|
+
Machine.L4 = Machine(name="L4", slug="lit-l4-1", family="L4", accelerator_count=1)
|
|
157
|
+
Machine.L4_X_2 = Machine(name="L4_X_2", slug="lit-l4-2", family="L4", accelerator_count=2)
|
|
158
|
+
Machine.L4_X_4 = Machine(name="L4_X_4", slug="lit-l4-4", family="L4", accelerator_count=4)
|
|
159
|
+
Machine.L4_X_8 = Machine(name="L4_X_8", slug="lit-l4-8", family="L4", accelerator_count=8)
|
|
160
|
+
# available L40S machines
|
|
161
|
+
Machine.L40S = Machine(name="L40S", slug="lit-l40s-1", family="L40S", accelerator_count=1)
|
|
162
|
+
Machine.L40S_X_2 = Machine(name="L40S_X_2", slug="lit-l40s-2", family="L40S", accelerator_count=2)
|
|
163
|
+
Machine.L40S_X_4 = Machine(name="L40S_X_4", slug="lit-l40s-4", family="L40S", accelerator_count=4)
|
|
164
|
+
Machine.L40S_X_8 = Machine(name="L40S_X_8", slug="lit-l40s-8", family="L40S", accelerator_count=8)
|
|
165
|
+
# available A100 Machines
|
|
166
|
+
Machine.A100 = Machine(name="A100", slug="lit-a100-1", family="A100", accelerator_count=1)
|
|
167
|
+
Machine.A100_X_2 = Machine(name="A100_X_2", slug="lit-a100-2", family="A100", accelerator_count=2)
|
|
168
|
+
Machine.A100_X_4 = Machine(name="A100_X_4", slug="lit-a100-4", family="A100", accelerator_count=4)
|
|
169
|
+
Machine.A100_X_8 = Machine(name="A100_X_8", slug="lit-a100-8", family="A100", accelerator_count=8)
|
|
170
|
+
# don't include variants in cli, only default types that can match for all variants
|
|
171
|
+
Machine.A100_40GB = Machine(
|
|
172
|
+
name="A100_40GB", slug="lit-a100-40gb-1", family="A100", accelerator_count=1, _include_in_cli=False
|
|
173
|
+
)
|
|
174
|
+
Machine.A100_40GB_X_2 = Machine(
|
|
175
|
+
name="A100_40GB_X_2", slug="lit-a100-40gb-2", family="A100", accelerator_count=2, _include_in_cli=False
|
|
176
|
+
)
|
|
177
|
+
Machine.A100_40GB_X_4 = Machine(
|
|
178
|
+
name="A100_40GB_X_4", slug="lit-a100-40gb-4", family="A100", accelerator_count=4, _include_in_cli=False
|
|
179
|
+
)
|
|
180
|
+
Machine.A100_40GB_X_8 = Machine(
|
|
181
|
+
name="A100_40GB_X_8", slug="lit-a100-40gb-8", family="A100", accelerator_count=8, _include_in_cli=False
|
|
182
|
+
)
|
|
183
|
+
Machine.A100_80GB = Machine(
|
|
184
|
+
name="A100_80GB", slug="lit-a100-80gb-1", family="A100", accelerator_count=1, _include_in_cli=False
|
|
185
|
+
)
|
|
186
|
+
Machine.A100_80GB_X_2 = Machine(
|
|
187
|
+
name="A100_80GB_X_2", slug="lit-a100-80gb-2", family="A100", accelerator_count=2, _include_in_cli=False
|
|
188
|
+
)
|
|
189
|
+
Machine.A100_80GB_X_4 = Machine(
|
|
190
|
+
name="A100_80GB_X_4", slug="lit-a100-80gb-4", family="A100", accelerator_count=4, _include_in_cli=False
|
|
191
|
+
)
|
|
192
|
+
Machine.A100_80GB_X_8 = Machine(
|
|
193
|
+
name="A100_80GB_X_8", slug="lit-a100-80gb-8", family="A100", accelerator_count=8, _include_in_cli=False
|
|
194
|
+
)
|
|
195
|
+
# available H100 machines
|
|
196
|
+
Machine.H100 = Machine(name="H100", slug="lit-h100-1", family="H100", accelerator_count=1)
|
|
197
|
+
Machine.H100_X_2 = Machine(name="H100_X_2", slug="lit-h100-2", family="H100", accelerator_count=2)
|
|
198
|
+
Machine.H100_X_4 = Machine(name="H100_X_4", slug="lit-h100-4", family="H100", accelerator_count=4)
|
|
199
|
+
Machine.H100_X_8 = Machine(name="H100_X_8", slug="lit-h100-8", family="H100", accelerator_count=8)
|
|
200
|
+
# available H200 machines
|
|
201
|
+
Machine.H200 = Machine(name="H200", slug="lit-h200x-1", family="H200", accelerator_count=1)
|
|
202
|
+
Machine.H200_X_8 = Machine(name="H200_X_8", slug="lit-h200x-8", family="H200", accelerator_count=8)
|
|
203
|
+
# available B200 machines
|
|
204
|
+
Machine.B200_X_8 = Machine(name="B200_X_8", slug="lit-b200x-8", family="B200", accelerator_count=8)
|
lightning_sdk/mmt/v2.py
CHANGED
|
@@ -3,6 +3,7 @@ from typing import TYPE_CHECKING, Dict, Optional, Tuple, Union
|
|
|
3
3
|
from lightning_sdk.api.mmt_api import MMTApiV2
|
|
4
4
|
from lightning_sdk.api.utils import _get_cloud_url
|
|
5
5
|
from lightning_sdk.status import Status
|
|
6
|
+
from lightning_sdk.utils.resolve import _get_org_id
|
|
6
7
|
|
|
7
8
|
if TYPE_CHECKING:
|
|
8
9
|
from lightning_sdk.job.job import Job
|
|
@@ -191,7 +192,11 @@ class _MMTV2(_BaseMMT):
|
|
|
191
192
|
@property
|
|
192
193
|
def machine(self) -> Union["Machine", str]:
|
|
193
194
|
"""Returns the machine type this job is running on."""
|
|
194
|
-
return self._job_api._get_job_machine_from_spec(
|
|
195
|
+
return self._job_api._get_job_machine_from_spec(
|
|
196
|
+
self._guaranteed_job.spec,
|
|
197
|
+
self.teamspace.id,
|
|
198
|
+
_get_org_id(self.teamspace),
|
|
199
|
+
)
|
|
195
200
|
|
|
196
201
|
def _update_internal_job(self) -> None:
|
|
197
202
|
if getattr(self, "_job", None) is None:
|
lightning_sdk/models.py
CHANGED
|
@@ -127,7 +127,7 @@ def download_model(
|
|
|
127
127
|
return api.download_model_files(
|
|
128
128
|
name=model_name,
|
|
129
129
|
version=version,
|
|
130
|
-
download_dir=Path(download_dir),
|
|
130
|
+
download_dir=Path(download_dir).expanduser().resolve(),
|
|
131
131
|
teamspace_name=teamspace_name,
|
|
132
132
|
teamspace_owner_name=teamspace_owner_name,
|
|
133
133
|
progress_bar=progress_bar,
|
lightning_sdk/studio.py
CHANGED
|
@@ -7,7 +7,6 @@ from tqdm.auto import tqdm
|
|
|
7
7
|
|
|
8
8
|
from lightning_sdk.api.cloud_account_api import CloudAccountApi
|
|
9
9
|
from lightning_sdk.api.studio_api import StudioApi
|
|
10
|
-
from lightning_sdk.api.utils import _machine_to_compute_name
|
|
11
10
|
from lightning_sdk.constants import _LIGHTNING_DEBUG
|
|
12
11
|
from lightning_sdk.machine import CloudProvider, Machine
|
|
13
12
|
from lightning_sdk.organization import Organization
|
|
@@ -16,6 +15,7 @@ from lightning_sdk.status import Status
|
|
|
16
15
|
from lightning_sdk.teamspace import Teamspace
|
|
17
16
|
from lightning_sdk.user import User
|
|
18
17
|
from lightning_sdk.utils.resolve import (
|
|
18
|
+
_get_org_id,
|
|
19
19
|
_resolve_deprecated_cluster,
|
|
20
20
|
_resolve_deprecated_provider,
|
|
21
21
|
_resolve_teamspace,
|
|
@@ -176,7 +176,12 @@ class Studio:
|
|
|
176
176
|
"""Returns the current machine type the Studio is running on."""
|
|
177
177
|
if self.status != Status.Running:
|
|
178
178
|
return None
|
|
179
|
-
return self._studio_api.get_machine(
|
|
179
|
+
return self._studio_api.get_machine(
|
|
180
|
+
self._studio.id,
|
|
181
|
+
self._teamspace.id,
|
|
182
|
+
self.cloud_account,
|
|
183
|
+
_get_org_id(self._teamspace),
|
|
184
|
+
)
|
|
180
185
|
|
|
181
186
|
@property
|
|
182
187
|
def interruptible(self) -> bool:
|
|
@@ -223,10 +228,12 @@ class Studio:
|
|
|
223
228
|
interruptible = self.teamspace.start_studios_on_interruptible
|
|
224
229
|
|
|
225
230
|
if status == Status.Running:
|
|
226
|
-
|
|
227
|
-
if
|
|
231
|
+
new_machine = machine
|
|
232
|
+
if not isinstance(machine, Machine):
|
|
233
|
+
new_machine = Machine.from_str(machine)
|
|
234
|
+
if new_machine != self.machine:
|
|
228
235
|
raise RuntimeError(
|
|
229
|
-
f"Requested to start studio on {
|
|
236
|
+
f"Requested to start studio on {new_machine}, but studio is already running on {self.machine}."
|
|
230
237
|
" Consider switching instead!"
|
|
231
238
|
)
|
|
232
239
|
_logger.info(f"Studio {self.name} is already running")
|
lightning_sdk/teamspace.py
CHANGED
|
@@ -205,8 +205,11 @@ class Teamspace:
|
|
|
205
205
|
cloud_machines = self._teamspace_api.list_machines(self.id, cloud_account=cloud_account)
|
|
206
206
|
return [
|
|
207
207
|
Machine(
|
|
208
|
-
cluster_machine.instance_id,
|
|
209
|
-
cluster_machine.
|
|
208
|
+
name=cluster_machine.instance_id,
|
|
209
|
+
slug=cluster_machine.slug_multi_cloud,
|
|
210
|
+
instance_type=cluster_machine.instance_id,
|
|
211
|
+
family=cluster_machine.family,
|
|
212
|
+
accelerator_count=cluster_machine.resources.gpu or cluster_machine.resources.cpu,
|
|
210
213
|
cost=cluster_machine.cost,
|
|
211
214
|
interruptible_cost=cluster_machine.spot_price,
|
|
212
215
|
wait_time=float(cluster_machine.available_in_seconds) if cluster_machine.available_in_seconds else None,
|
lightning_sdk/utils/resolve.py
CHANGED
|
@@ -240,3 +240,11 @@ def _get_studio_url(studio: "Studio", turn_on: bool = False) -> str:
|
|
|
240
240
|
if turn_on:
|
|
241
241
|
return f"{base_url}?turnOn=true"
|
|
242
242
|
return base_url
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def _get_org_id(teamspace: "Teamspace") -> str:
|
|
246
|
+
from lightning_sdk.organization import Organization
|
|
247
|
+
|
|
248
|
+
if isinstance(teamspace.owner, Organization):
|
|
249
|
+
return teamspace.owner.id
|
|
250
|
+
return ""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lightning_sdk
|
|
3
|
-
Version: 2025.7.
|
|
3
|
+
Version: 2025.7.31
|
|
4
4
|
Summary: SDK to develop using Lightning AI Studios
|
|
5
5
|
Author-email: Lightning-AI <justus@lightning.ai>
|
|
6
6
|
License: MIT License
|
|
@@ -25,6 +25,8 @@ License: MIT License
|
|
|
25
25
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
26
|
SOFTWARE.
|
|
27
27
|
|
|
28
|
+
Project-URL: Homepage, https://lightning.ai
|
|
29
|
+
Project-URL: Documentation, https://lightning.ai/docs/overview/sdk-reference
|
|
28
30
|
Keywords: deep learning,machine learning,pytorch,AI
|
|
29
31
|
Classifier: Programming Language :: Python :: 3
|
|
30
32
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -79,11 +81,11 @@ s.start()
|
|
|
79
81
|
# prints Machine.CPU-4
|
|
80
82
|
print(s.machine)
|
|
81
83
|
|
|
82
|
-
# or start directly on this machine with s.start(Machine.
|
|
84
|
+
# or start directly on this machine with s.start(Machine.L4)
|
|
83
85
|
print("switching Studio machine...")
|
|
84
|
-
s.switch_machine(Machine.
|
|
86
|
+
s.switch_machine(Machine.L4)
|
|
85
87
|
|
|
86
|
-
# prints Machine.
|
|
88
|
+
# prints Machine.L4
|
|
87
89
|
print(s.machine)
|
|
88
90
|
|
|
89
91
|
# prints Status.Running
|
|
@@ -96,7 +98,7 @@ s.install_plugin("jobs")
|
|
|
96
98
|
s.install_plugin("multi-machine-training")
|
|
97
99
|
|
|
98
100
|
# run the resulting plugins to start 1 job and 1 multi-machine training
|
|
99
|
-
s.installed_plugins["jobs"].run("python my_dummy_file", name="my_first_job", machine=Machine.
|
|
101
|
+
s.installed_plugins["jobs"].run("python my_dummy_file", name="my_first_job", machine=Machine.L4)
|
|
100
102
|
s.installed_plugins["multi-machine-training"].run("python my_dummy_file", name="my_first_mmt", machine=Machine.T4, num_instances=42)
|
|
101
103
|
|
|
102
104
|
print("Stopping Studio")
|