lightning-sdk 0.1.38__py3-none-any.whl → 0.1.40__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/_mmt/__init__.py +3 -0
- lightning_sdk/_mmt/base.py +180 -0
- lightning_sdk/_mmt/mmt.py +161 -0
- lightning_sdk/_mmt/v1.py +69 -0
- lightning_sdk/_mmt/v2.py +141 -0
- lightning_sdk/api/deployment_api.py +0 -2
- lightning_sdk/api/job_api.py +4 -0
- lightning_sdk/api/mmt_api.py +147 -0
- lightning_sdk/api/teamspace_api.py +4 -11
- lightning_sdk/api/utils.py +6 -3
- lightning_sdk/cli/download.py +3 -5
- lightning_sdk/cli/mmt.py +137 -0
- lightning_sdk/cli/run.py +16 -0
- lightning_sdk/cli/upload.py +3 -10
- lightning_sdk/job/base.py +24 -3
- lightning_sdk/job/job.py +10 -1
- lightning_sdk/job/v1.py +7 -1
- lightning_sdk/job/v2.py +18 -9
- lightning_sdk/lightning_cloud/openapi/__init__.py +7 -3
- lightning_sdk/lightning_cloud/openapi/api/assistants_service_api.py +90 -284
- lightning_sdk/lightning_cloud/openapi/api/data_connection_service_api.py +6 -1
- lightning_sdk/lightning_cloud/openapi/api/models_store_api.py +235 -1
- lightning_sdk/lightning_cloud/openapi/models/__init__.py +7 -3
- lightning_sdk/lightning_cloud/openapi/models/deployments_id_body.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/id_start_body.py +29 -3
- lightning_sdk/lightning_cloud/openapi/models/model_id_visibility_body.py +123 -0
- lightning_sdk/lightning_cloud/openapi/models/project_id_cloudspaces_body.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_aws_direct_v1.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/{project_id_agentmanagedmodels_body.py → v1_body.py} +21 -47
- lightning_sdk/lightning_cloud/openapi/models/v1_data_path.py +29 -3
- lightning_sdk/lightning_cloud/openapi/models/v1_deployment.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_deployment_api.py +201 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_get_model_files_response.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_job_spec.py +53 -53
- lightning_sdk/lightning_cloud/openapi/models/v1_managed_model.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_managed_model_abilities.py +175 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_model.py +29 -3
- lightning_sdk/lightning_cloud/openapi/models/v1_multi_machine_job.py +53 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_multi_machine_job_state.py +1 -2
- lightning_sdk/lightning_cloud/openapi/models/v1_query_param.py +175 -0
- lightning_sdk/lightning_cloud/openapi/models/{v1_list_managed_models_response.py → v1_resource_visibility.py} +23 -23
- lightning_sdk/lightning_cloud/openapi/models/{v1_delete_managed_model_response.py → v1_update_model_visibility_response.py} +6 -6
- lightning_sdk/lightning_cloud/openapi/models/v1_user_features.py +27 -1
- lightning_sdk/models.py +153 -0
- lightning_sdk/teamspace.py +15 -11
- {lightning_sdk-0.1.38.dist-info → lightning_sdk-0.1.40.dist-info}/METADATA +1 -1
- {lightning_sdk-0.1.38.dist-info → lightning_sdk-0.1.40.dist-info}/RECORD +52 -41
- {lightning_sdk-0.1.38.dist-info → lightning_sdk-0.1.40.dist-info}/entry_points.txt +1 -0
- lightning_sdk/cli/models.py +0 -68
- {lightning_sdk-0.1.38.dist-info → lightning_sdk-0.1.40.dist-info}/LICENSE +0 -0
- {lightning_sdk-0.1.38.dist-info → lightning_sdk-0.1.40.dist-info}/WHEEL +0 -0
- {lightning_sdk-0.1.38.dist-info → lightning_sdk-0.1.40.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
external/v1/auth_service.proto
|
|
5
|
+
|
|
6
|
+
No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) # noqa: E501
|
|
7
|
+
|
|
8
|
+
OpenAPI spec version: version not set
|
|
9
|
+
|
|
10
|
+
Generated by: https://github.com/swagger-api/swagger-codegen.git
|
|
11
|
+
|
|
12
|
+
NOTE
|
|
13
|
+
----
|
|
14
|
+
standard swagger-codegen-cli for this python client has been modified
|
|
15
|
+
by custom templates. The purpose of these templates is to include
|
|
16
|
+
typing information in the API and Model code. Please refer to the
|
|
17
|
+
main grid repository for more info
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import pprint
|
|
21
|
+
import re # noqa: F401
|
|
22
|
+
|
|
23
|
+
from typing import TYPE_CHECKING
|
|
24
|
+
|
|
25
|
+
import six
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from datetime import datetime
|
|
29
|
+
from lightning_sdk.lightning_cloud.openapi.models import *
|
|
30
|
+
|
|
31
|
+
class V1QueryParam(object):
|
|
32
|
+
"""NOTE: This class is auto generated by the swagger code generator program.
|
|
33
|
+
|
|
34
|
+
Do not edit the class manually.
|
|
35
|
+
"""
|
|
36
|
+
"""
|
|
37
|
+
Attributes:
|
|
38
|
+
swagger_types (dict): The key is attribute name
|
|
39
|
+
and the value is attribute type.
|
|
40
|
+
attribute_map (dict): The key is attribute name
|
|
41
|
+
and the value is json key in definition.
|
|
42
|
+
"""
|
|
43
|
+
swagger_types = {
|
|
44
|
+
'description': 'str',
|
|
45
|
+
'key': 'str',
|
|
46
|
+
'value': 'str'
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
attribute_map = {
|
|
50
|
+
'description': 'description',
|
|
51
|
+
'key': 'key',
|
|
52
|
+
'value': 'value'
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
def __init__(self, description: 'str' =None, key: 'str' =None, value: 'str' =None): # noqa: E501
|
|
56
|
+
"""V1QueryParam - a model defined in Swagger""" # noqa: E501
|
|
57
|
+
self._description = None
|
|
58
|
+
self._key = None
|
|
59
|
+
self._value = None
|
|
60
|
+
self.discriminator = None
|
|
61
|
+
if description is not None:
|
|
62
|
+
self.description = description
|
|
63
|
+
if key is not None:
|
|
64
|
+
self.key = key
|
|
65
|
+
if value is not None:
|
|
66
|
+
self.value = value
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def description(self) -> 'str':
|
|
70
|
+
"""Gets the description of this V1QueryParam. # noqa: E501
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
:return: The description of this V1QueryParam. # noqa: E501
|
|
74
|
+
:rtype: str
|
|
75
|
+
"""
|
|
76
|
+
return self._description
|
|
77
|
+
|
|
78
|
+
@description.setter
|
|
79
|
+
def description(self, description: 'str'):
|
|
80
|
+
"""Sets the description of this V1QueryParam.
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
:param description: The description of this V1QueryParam. # noqa: E501
|
|
84
|
+
:type: str
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
self._description = description
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def key(self) -> 'str':
|
|
91
|
+
"""Gets the key of this V1QueryParam. # noqa: E501
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
:return: The key of this V1QueryParam. # noqa: E501
|
|
95
|
+
:rtype: str
|
|
96
|
+
"""
|
|
97
|
+
return self._key
|
|
98
|
+
|
|
99
|
+
@key.setter
|
|
100
|
+
def key(self, key: 'str'):
|
|
101
|
+
"""Sets the key of this V1QueryParam.
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
:param key: The key of this V1QueryParam. # noqa: E501
|
|
105
|
+
:type: str
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
self._key = key
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def value(self) -> 'str':
|
|
112
|
+
"""Gets the value of this V1QueryParam. # noqa: E501
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
:return: The value of this V1QueryParam. # noqa: E501
|
|
116
|
+
:rtype: str
|
|
117
|
+
"""
|
|
118
|
+
return self._value
|
|
119
|
+
|
|
120
|
+
@value.setter
|
|
121
|
+
def value(self, value: 'str'):
|
|
122
|
+
"""Sets the value of this V1QueryParam.
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
:param value: The value of this V1QueryParam. # noqa: E501
|
|
126
|
+
:type: str
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
self._value = value
|
|
130
|
+
|
|
131
|
+
def to_dict(self) -> dict:
|
|
132
|
+
"""Returns the model properties as a dict"""
|
|
133
|
+
result = {}
|
|
134
|
+
|
|
135
|
+
for attr, _ in six.iteritems(self.swagger_types):
|
|
136
|
+
value = getattr(self, attr)
|
|
137
|
+
if isinstance(value, list):
|
|
138
|
+
result[attr] = list(map(
|
|
139
|
+
lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
|
|
140
|
+
value
|
|
141
|
+
))
|
|
142
|
+
elif hasattr(value, "to_dict"):
|
|
143
|
+
result[attr] = value.to_dict()
|
|
144
|
+
elif isinstance(value, dict):
|
|
145
|
+
result[attr] = dict(map(
|
|
146
|
+
lambda item: (item[0], item[1].to_dict())
|
|
147
|
+
if hasattr(item[1], "to_dict") else item,
|
|
148
|
+
value.items()
|
|
149
|
+
))
|
|
150
|
+
else:
|
|
151
|
+
result[attr] = value
|
|
152
|
+
if issubclass(V1QueryParam, dict):
|
|
153
|
+
for key, value in self.items():
|
|
154
|
+
result[key] = value
|
|
155
|
+
|
|
156
|
+
return result
|
|
157
|
+
|
|
158
|
+
def to_str(self) -> str:
|
|
159
|
+
"""Returns the string representation of the model"""
|
|
160
|
+
return pprint.pformat(self.to_dict())
|
|
161
|
+
|
|
162
|
+
def __repr__(self) -> str:
|
|
163
|
+
"""For `print` and `pprint`"""
|
|
164
|
+
return self.to_str()
|
|
165
|
+
|
|
166
|
+
def __eq__(self, other: 'V1QueryParam') -> bool:
|
|
167
|
+
"""Returns true if both objects are equal"""
|
|
168
|
+
if not isinstance(other, V1QueryParam):
|
|
169
|
+
return False
|
|
170
|
+
|
|
171
|
+
return self.__dict__ == other.__dict__
|
|
172
|
+
|
|
173
|
+
def __ne__(self, other: 'V1QueryParam') -> bool:
|
|
174
|
+
"""Returns true if both objects are not equal"""
|
|
175
|
+
return not self == other
|
|
@@ -28,7 +28,7 @@ if TYPE_CHECKING:
|
|
|
28
28
|
from datetime import datetime
|
|
29
29
|
from lightning_sdk.lightning_cloud.openapi.models import *
|
|
30
30
|
|
|
31
|
-
class
|
|
31
|
+
class V1ResourceVisibility(object):
|
|
32
32
|
"""NOTE: This class is auto generated by the swagger code generator program.
|
|
33
33
|
|
|
34
34
|
Do not edit the class manually.
|
|
@@ -41,40 +41,40 @@ class V1ListManagedModelsResponse(object):
|
|
|
41
41
|
and the value is json key in definition.
|
|
42
42
|
"""
|
|
43
43
|
swagger_types = {
|
|
44
|
-
'
|
|
44
|
+
'all_users': 'bool'
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
attribute_map = {
|
|
48
|
-
'
|
|
48
|
+
'all_users': 'allUsers'
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
def __init__(self,
|
|
52
|
-
"""
|
|
53
|
-
self.
|
|
51
|
+
def __init__(self, all_users: 'bool' =None): # noqa: E501
|
|
52
|
+
"""V1ResourceVisibility - a model defined in Swagger""" # noqa: E501
|
|
53
|
+
self._all_users = None
|
|
54
54
|
self.discriminator = None
|
|
55
|
-
if
|
|
56
|
-
self.
|
|
55
|
+
if all_users is not None:
|
|
56
|
+
self.all_users = all_users
|
|
57
57
|
|
|
58
58
|
@property
|
|
59
|
-
def
|
|
60
|
-
"""Gets the
|
|
59
|
+
def all_users(self) -> 'bool':
|
|
60
|
+
"""Gets the all_users of this V1ResourceVisibility. # noqa: E501
|
|
61
61
|
|
|
62
62
|
|
|
63
|
-
:return: The
|
|
64
|
-
:rtype:
|
|
63
|
+
:return: The all_users of this V1ResourceVisibility. # noqa: E501
|
|
64
|
+
:rtype: bool
|
|
65
65
|
"""
|
|
66
|
-
return self.
|
|
66
|
+
return self._all_users
|
|
67
67
|
|
|
68
|
-
@
|
|
69
|
-
def
|
|
70
|
-
"""Sets the
|
|
68
|
+
@all_users.setter
|
|
69
|
+
def all_users(self, all_users: 'bool'):
|
|
70
|
+
"""Sets the all_users of this V1ResourceVisibility.
|
|
71
71
|
|
|
72
72
|
|
|
73
|
-
:param
|
|
74
|
-
:type:
|
|
73
|
+
:param all_users: The all_users of this V1ResourceVisibility. # noqa: E501
|
|
74
|
+
:type: bool
|
|
75
75
|
"""
|
|
76
76
|
|
|
77
|
-
self.
|
|
77
|
+
self._all_users = all_users
|
|
78
78
|
|
|
79
79
|
def to_dict(self) -> dict:
|
|
80
80
|
"""Returns the model properties as a dict"""
|
|
@@ -97,7 +97,7 @@ class V1ListManagedModelsResponse(object):
|
|
|
97
97
|
))
|
|
98
98
|
else:
|
|
99
99
|
result[attr] = value
|
|
100
|
-
if issubclass(
|
|
100
|
+
if issubclass(V1ResourceVisibility, dict):
|
|
101
101
|
for key, value in self.items():
|
|
102
102
|
result[key] = value
|
|
103
103
|
|
|
@@ -111,13 +111,13 @@ class V1ListManagedModelsResponse(object):
|
|
|
111
111
|
"""For `print` and `pprint`"""
|
|
112
112
|
return self.to_str()
|
|
113
113
|
|
|
114
|
-
def __eq__(self, other: '
|
|
114
|
+
def __eq__(self, other: 'V1ResourceVisibility') -> bool:
|
|
115
115
|
"""Returns true if both objects are equal"""
|
|
116
|
-
if not isinstance(other,
|
|
116
|
+
if not isinstance(other, V1ResourceVisibility):
|
|
117
117
|
return False
|
|
118
118
|
|
|
119
119
|
return self.__dict__ == other.__dict__
|
|
120
120
|
|
|
121
|
-
def __ne__(self, other: '
|
|
121
|
+
def __ne__(self, other: 'V1ResourceVisibility') -> bool:
|
|
122
122
|
"""Returns true if both objects are not equal"""
|
|
123
123
|
return not self == other
|
|
@@ -28,7 +28,7 @@ if TYPE_CHECKING:
|
|
|
28
28
|
from datetime import datetime
|
|
29
29
|
from lightning_sdk.lightning_cloud.openapi.models import *
|
|
30
30
|
|
|
31
|
-
class
|
|
31
|
+
class V1UpdateModelVisibilityResponse(object):
|
|
32
32
|
"""NOTE: This class is auto generated by the swagger code generator program.
|
|
33
33
|
|
|
34
34
|
Do not edit the class manually.
|
|
@@ -47,7 +47,7 @@ class V1DeleteManagedModelResponse(object):
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
def __init__(self): # noqa: E501
|
|
50
|
-
"""
|
|
50
|
+
"""V1UpdateModelVisibilityResponse - a model defined in Swagger""" # noqa: E501
|
|
51
51
|
self.discriminator = None
|
|
52
52
|
|
|
53
53
|
def to_dict(self) -> dict:
|
|
@@ -71,7 +71,7 @@ class V1DeleteManagedModelResponse(object):
|
|
|
71
71
|
))
|
|
72
72
|
else:
|
|
73
73
|
result[attr] = value
|
|
74
|
-
if issubclass(
|
|
74
|
+
if issubclass(V1UpdateModelVisibilityResponse, dict):
|
|
75
75
|
for key, value in self.items():
|
|
76
76
|
result[key] = value
|
|
77
77
|
|
|
@@ -85,13 +85,13 @@ class V1DeleteManagedModelResponse(object):
|
|
|
85
85
|
"""For `print` and `pprint`"""
|
|
86
86
|
return self.to_str()
|
|
87
87
|
|
|
88
|
-
def __eq__(self, other: '
|
|
88
|
+
def __eq__(self, other: 'V1UpdateModelVisibilityResponse') -> bool:
|
|
89
89
|
"""Returns true if both objects are equal"""
|
|
90
|
-
if not isinstance(other,
|
|
90
|
+
if not isinstance(other, V1UpdateModelVisibilityResponse):
|
|
91
91
|
return False
|
|
92
92
|
|
|
93
93
|
return self.__dict__ == other.__dict__
|
|
94
94
|
|
|
95
|
-
def __ne__(self, other: '
|
|
95
|
+
def __ne__(self, other: 'V1UpdateModelVisibilityResponse') -> bool:
|
|
96
96
|
"""Returns true if both objects are not equal"""
|
|
97
97
|
return not self == other
|
|
@@ -76,6 +76,7 @@ class V1UserFeatures(object):
|
|
|
76
76
|
'filesystem_optimisation': 'bool',
|
|
77
77
|
'gcp': 'bool',
|
|
78
78
|
'inference_job_deployment_plugin': 'bool',
|
|
79
|
+
'instant_capacity_reservation': 'bool',
|
|
79
80
|
'jobs_init': 'bool',
|
|
80
81
|
'jobs_v2': 'bool',
|
|
81
82
|
'landing_studios': 'bool',
|
|
@@ -160,6 +161,7 @@ class V1UserFeatures(object):
|
|
|
160
161
|
'filesystem_optimisation': 'filesystemOptimisation',
|
|
161
162
|
'gcp': 'gcp',
|
|
162
163
|
'inference_job_deployment_plugin': 'inferenceJobDeploymentPlugin',
|
|
164
|
+
'instant_capacity_reservation': 'instantCapacityReservation',
|
|
163
165
|
'jobs_init': 'jobsInit',
|
|
164
166
|
'jobs_v2': 'jobsV2',
|
|
165
167
|
'landing_studios': 'landingStudios',
|
|
@@ -208,7 +210,7 @@ class V1UserFeatures(object):
|
|
|
208
210
|
'writable_data_connections': 'writableDataConnections'
|
|
209
211
|
}
|
|
210
212
|
|
|
211
|
-
def __init__(self, advanced_deployment_autoscaling: 'bool' =None, affiliate_links: 'bool' =None, agents_v2: 'bool' =None, ai_hub_monetization: 'bool' =None, auto_fast_load: 'bool' =None, auto_join_orgs: 'bool' =None, aws_trainium: 'bool' =None, b2c_experience: 'bool' =None, cap_add: 'list[str]' =None, cap_drop: 'list[str]' =None, capacity_reservation: 'bool' =None, capacity_reservation_dry_run: 'bool' =None, cluster_proxy: 'bool' =None, code_tab: 'bool' =None, collab_screen_sharing: 'bool' =None, cost_attribution_settings: 'bool' =None, crypto_monitoring: 'bool' =None, custom_app_domain: 'bool' =None, custom_instance_types: 'bool' =None, default_one_cluster: 'bool' =None, deployment_customize_api: 'bool' =None, deployment_data_path: 'bool' =None, deployment_gallery: 'bool' =None, deployment_persistent_disk: 'bool' =None, deployment_version_visibility: 'bool' =None, docs_agent: 'bool' =None, drive_v2: 'bool' =None, dynamic_workload_scheduling: 'bool' =None, enable_crypto_crackdown: 'bool' =None, enable_efs: 'bool' =None, enable_storage_limits: 'bool' =None, featured_studios_admin: 'bool' =None, filesystem_optimisation: 'bool' =None, gcp: 'bool' =None, inference_job_deployment_plugin: 'bool' =None, jobs_init: 'bool' =None, jobs_v2: 'bool' =None, landing_studios: 'bool' =None, lightning_registry: 'bool' =None, lit_logger: 'bool' =None, lit_logger_storage_v2: 'bool' =None, mmt_fault_tolerance: 'bool' =None, mmt_strategy_selector: 'bool' =None, model_store: 'bool' =None, multiple_deployment_versions: 'bool' =None, multiple_studio_versions: 'bool' =None, org_level_member_permissions: 'bool' =None, plugin_biz_chat: 'bool' =None, plugin_distributed: 'bool' =None, plugin_fiftyone: 'bool' =None, plugin_inference: 'bool' =None, plugin_label_studio: 'bool' =None, plugin_langflow: 'bool' =None, plugin_lightning_apps: 'bool' =None, plugin_lightning_apps_distributed: 'bool' =None, plugin_mage_ai: 'bool' =None, plugin_milvus: 'bool' =None, plugin_python_profiler: 'bool' =None, plugin_react: 'bool' =None, plugin_service: 'bool' =None, plugin_sweeps: 'bool' =None, plugin_weviate: 'bool' =None, pricing_updates: 'bool' =None, product_generator: 'bool' =None, project_selector: 'bool' =None, restart_ide_on_hang: 'bool' =None, restartable_jobs: 'bool' =None, runnable_public_studio_page: 'bool' =None, s3_folders: 'bool' =None, show_dev_admin: 'bool' =None, slurm: 'bool' =None, slurm_machine_selector: 'bool' =None, snapshotter_service: 'bool' =None, snowflake_connection: 'bool' =None, spot_v2: 'bool' =None, studio_config: 'bool' =None, studio_on_stop: 'bool' =None, studio_version_visibility: 'bool' =None, teamspace_storage_tab: 'bool' =None, use_rclone_mounts_only: 'bool' =None, writable_data_connections: 'bool' =None): # noqa: E501
|
|
213
|
+
def __init__(self, advanced_deployment_autoscaling: 'bool' =None, affiliate_links: 'bool' =None, agents_v2: 'bool' =None, ai_hub_monetization: 'bool' =None, auto_fast_load: 'bool' =None, auto_join_orgs: 'bool' =None, aws_trainium: 'bool' =None, b2c_experience: 'bool' =None, cap_add: 'list[str]' =None, cap_drop: 'list[str]' =None, capacity_reservation: 'bool' =None, capacity_reservation_dry_run: 'bool' =None, cluster_proxy: 'bool' =None, code_tab: 'bool' =None, collab_screen_sharing: 'bool' =None, cost_attribution_settings: 'bool' =None, crypto_monitoring: 'bool' =None, custom_app_domain: 'bool' =None, custom_instance_types: 'bool' =None, default_one_cluster: 'bool' =None, deployment_customize_api: 'bool' =None, deployment_data_path: 'bool' =None, deployment_gallery: 'bool' =None, deployment_persistent_disk: 'bool' =None, deployment_version_visibility: 'bool' =None, docs_agent: 'bool' =None, drive_v2: 'bool' =None, dynamic_workload_scheduling: 'bool' =None, enable_crypto_crackdown: 'bool' =None, enable_efs: 'bool' =None, enable_storage_limits: 'bool' =None, featured_studios_admin: 'bool' =None, filesystem_optimisation: 'bool' =None, gcp: 'bool' =None, inference_job_deployment_plugin: 'bool' =None, instant_capacity_reservation: 'bool' =None, jobs_init: 'bool' =None, jobs_v2: 'bool' =None, landing_studios: 'bool' =None, lightning_registry: 'bool' =None, lit_logger: 'bool' =None, lit_logger_storage_v2: 'bool' =None, mmt_fault_tolerance: 'bool' =None, mmt_strategy_selector: 'bool' =None, model_store: 'bool' =None, multiple_deployment_versions: 'bool' =None, multiple_studio_versions: 'bool' =None, org_level_member_permissions: 'bool' =None, plugin_biz_chat: 'bool' =None, plugin_distributed: 'bool' =None, plugin_fiftyone: 'bool' =None, plugin_inference: 'bool' =None, plugin_label_studio: 'bool' =None, plugin_langflow: 'bool' =None, plugin_lightning_apps: 'bool' =None, plugin_lightning_apps_distributed: 'bool' =None, plugin_mage_ai: 'bool' =None, plugin_milvus: 'bool' =None, plugin_python_profiler: 'bool' =None, plugin_react: 'bool' =None, plugin_service: 'bool' =None, plugin_sweeps: 'bool' =None, plugin_weviate: 'bool' =None, pricing_updates: 'bool' =None, product_generator: 'bool' =None, project_selector: 'bool' =None, restart_ide_on_hang: 'bool' =None, restartable_jobs: 'bool' =None, runnable_public_studio_page: 'bool' =None, s3_folders: 'bool' =None, show_dev_admin: 'bool' =None, slurm: 'bool' =None, slurm_machine_selector: 'bool' =None, snapshotter_service: 'bool' =None, snowflake_connection: 'bool' =None, spot_v2: 'bool' =None, studio_config: 'bool' =None, studio_on_stop: 'bool' =None, studio_version_visibility: 'bool' =None, teamspace_storage_tab: 'bool' =None, use_rclone_mounts_only: 'bool' =None, writable_data_connections: 'bool' =None): # noqa: E501
|
|
212
214
|
"""V1UserFeatures - a model defined in Swagger""" # noqa: E501
|
|
213
215
|
self._advanced_deployment_autoscaling = None
|
|
214
216
|
self._affiliate_links = None
|
|
@@ -245,6 +247,7 @@ class V1UserFeatures(object):
|
|
|
245
247
|
self._filesystem_optimisation = None
|
|
246
248
|
self._gcp = None
|
|
247
249
|
self._inference_job_deployment_plugin = None
|
|
250
|
+
self._instant_capacity_reservation = None
|
|
248
251
|
self._jobs_init = None
|
|
249
252
|
self._jobs_v2 = None
|
|
250
253
|
self._landing_studios = None
|
|
@@ -362,6 +365,8 @@ class V1UserFeatures(object):
|
|
|
362
365
|
self.gcp = gcp
|
|
363
366
|
if inference_job_deployment_plugin is not None:
|
|
364
367
|
self.inference_job_deployment_plugin = inference_job_deployment_plugin
|
|
368
|
+
if instant_capacity_reservation is not None:
|
|
369
|
+
self.instant_capacity_reservation = instant_capacity_reservation
|
|
365
370
|
if jobs_init is not None:
|
|
366
371
|
self.jobs_init = jobs_init
|
|
367
372
|
if jobs_v2 is not None:
|
|
@@ -1190,6 +1195,27 @@ class V1UserFeatures(object):
|
|
|
1190
1195
|
|
|
1191
1196
|
self._inference_job_deployment_plugin = inference_job_deployment_plugin
|
|
1192
1197
|
|
|
1198
|
+
@property
|
|
1199
|
+
def instant_capacity_reservation(self) -> 'bool':
|
|
1200
|
+
"""Gets the instant_capacity_reservation of this V1UserFeatures. # noqa: E501
|
|
1201
|
+
|
|
1202
|
+
|
|
1203
|
+
:return: The instant_capacity_reservation of this V1UserFeatures. # noqa: E501
|
|
1204
|
+
:rtype: bool
|
|
1205
|
+
"""
|
|
1206
|
+
return self._instant_capacity_reservation
|
|
1207
|
+
|
|
1208
|
+
@instant_capacity_reservation.setter
|
|
1209
|
+
def instant_capacity_reservation(self, instant_capacity_reservation: 'bool'):
|
|
1210
|
+
"""Sets the instant_capacity_reservation of this V1UserFeatures.
|
|
1211
|
+
|
|
1212
|
+
|
|
1213
|
+
:param instant_capacity_reservation: The instant_capacity_reservation of this V1UserFeatures. # noqa: E501
|
|
1214
|
+
:type: bool
|
|
1215
|
+
"""
|
|
1216
|
+
|
|
1217
|
+
self._instant_capacity_reservation = instant_capacity_reservation
|
|
1218
|
+
|
|
1193
1219
|
@property
|
|
1194
1220
|
def jobs_init(self) -> 'bool':
|
|
1195
1221
|
"""Gets the jobs_init of this V1UserFeatures. # noqa: E501
|
lightning_sdk/models.py
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union
|
|
5
|
+
|
|
6
|
+
from lightning_sdk.api import OrgApi, TeamspaceApi, UserApi
|
|
7
|
+
from lightning_sdk.lightning_cloud.openapi.models import V1Membership, V1OwnerType
|
|
8
|
+
from lightning_sdk.lightning_cloud.openapi.rest import ApiException
|
|
9
|
+
from lightning_sdk.user import User
|
|
10
|
+
from lightning_sdk.utils.resolve import _get_authed_user
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from lightning_sdk.teamspace import Teamspace
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# TODO: Maybe just have a `Model` object?
|
|
17
|
+
@dataclass
|
|
18
|
+
class UploadedModelInfo:
|
|
19
|
+
name: str
|
|
20
|
+
version: str
|
|
21
|
+
teamspace: str
|
|
22
|
+
cloud_account: str
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _get_teamspace_and_path(
|
|
26
|
+
ts: V1Membership, org_api: OrgApi, user_api: UserApi, authed_user: User
|
|
27
|
+
) -> Tuple[str, Dict[str, Any]]:
|
|
28
|
+
if ts.owner_type == V1OwnerType.ORGANIZATION:
|
|
29
|
+
org = org_api._get_org_by_id(ts.owner_id)
|
|
30
|
+
return f"{org.name}/{ts.name}", {"name": ts.name, "org": org.name}
|
|
31
|
+
|
|
32
|
+
if ts.owner_type == V1OwnerType.USER and ts.owner_id != authed_user.id:
|
|
33
|
+
user = user_api._get_user_by_id(ts.owner_id) # todo: check also the name
|
|
34
|
+
return f"{user.username}/{ts.name}", {"name": ts.name, "user": User(name=user.username)}
|
|
35
|
+
|
|
36
|
+
if ts.owner_type == V1OwnerType.USER:
|
|
37
|
+
return f"{authed_user.name}/{ts.name}", {"name": ts.name, "user": authed_user}
|
|
38
|
+
|
|
39
|
+
raise RuntimeError(f"Unknown organization type {ts.owner_type}")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _list_teamspaces() -> List[str]:
|
|
43
|
+
org_api = OrgApi()
|
|
44
|
+
user_api = UserApi()
|
|
45
|
+
authed_user = _get_authed_user()
|
|
46
|
+
|
|
47
|
+
return [
|
|
48
|
+
_get_teamspace_and_path(ts, org_api, user_api, authed_user)[0]
|
|
49
|
+
for ts in user_api._get_all_teamspace_memberships("")
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _get_teamspace(name: str, organization: str) -> "Teamspace":
|
|
54
|
+
"""Get a Teamspace object from the SDK."""
|
|
55
|
+
from lightning_sdk.teamspace import Teamspace
|
|
56
|
+
|
|
57
|
+
org_api = OrgApi()
|
|
58
|
+
user_api = UserApi()
|
|
59
|
+
authed_user = _get_authed_user()
|
|
60
|
+
|
|
61
|
+
requested_teamspace = f"{organization}/{name}".lower()
|
|
62
|
+
|
|
63
|
+
for ts in user_api._get_all_teamspace_memberships(""):
|
|
64
|
+
if ts.name != name:
|
|
65
|
+
continue
|
|
66
|
+
|
|
67
|
+
teamspace_path, teamspace = _get_teamspace_and_path(ts, org_api, user_api, authed_user)
|
|
68
|
+
if requested_teamspace == teamspace_path:
|
|
69
|
+
return Teamspace(**teamspace)
|
|
70
|
+
|
|
71
|
+
options = f"{os.linesep}\t".join(_list_teamspaces())
|
|
72
|
+
raise RuntimeError(f"Teamspace `{requested_teamspace}` not found. Available teamspaces: {os.linesep}\t{options}")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _parse_model_name_and_version(name: str) -> Tuple[str, str, str, str]:
|
|
76
|
+
"""Parse the name argument into its components."""
|
|
77
|
+
try:
|
|
78
|
+
org_name, teamspace_name, model_name = name.split("/")
|
|
79
|
+
parts = model_name.split(":")
|
|
80
|
+
if len(parts) == 1:
|
|
81
|
+
return org_name, teamspace_name, parts[0], "latest"
|
|
82
|
+
if len(parts) == 2:
|
|
83
|
+
return org_name, teamspace_name, parts[0], parts[1]
|
|
84
|
+
# The rest of the validation for name and version happens in the backend
|
|
85
|
+
raise ValueError(
|
|
86
|
+
"Model version is expected to be in the format `entity/modelname:version` separated by a"
|
|
87
|
+
f" single colon, but got: {name}"
|
|
88
|
+
)
|
|
89
|
+
except ValueError as err:
|
|
90
|
+
raise ValueError(
|
|
91
|
+
f"Model name must be in the format 'organization/teamspace/model' but you provided '{name}'."
|
|
92
|
+
) from err
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def download_model(
|
|
96
|
+
name: str,
|
|
97
|
+
download_dir: Union[Path, str] = ".",
|
|
98
|
+
progress_bar: bool = True,
|
|
99
|
+
) -> List[str]:
|
|
100
|
+
"""Download a Model.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
name: The name of the Model you want to download.
|
|
104
|
+
This should have the format <ORGANIZATION-NAME>/<TEAMSPACE-NAME>/<MODEL-NAME>.
|
|
105
|
+
download_dir: The directory where the Model should be downloaded.
|
|
106
|
+
progress_bar: Whether to show a progress bar when downloading.
|
|
107
|
+
"""
|
|
108
|
+
teamspace_owner_name, teamspace_name, model_name, version = _parse_model_name_and_version(name)
|
|
109
|
+
|
|
110
|
+
download_dir = Path(download_dir)
|
|
111
|
+
|
|
112
|
+
api = TeamspaceApi()
|
|
113
|
+
|
|
114
|
+
try:
|
|
115
|
+
return api.download_model_files(
|
|
116
|
+
name=model_name,
|
|
117
|
+
version=version,
|
|
118
|
+
download_dir=download_dir,
|
|
119
|
+
teamspace_name=teamspace_name,
|
|
120
|
+
teamspace_owner_name=teamspace_owner_name,
|
|
121
|
+
progress_bar=progress_bar,
|
|
122
|
+
)
|
|
123
|
+
except ApiException as e:
|
|
124
|
+
# if we get an error, check if the teamspace actually exists (and print the list)
|
|
125
|
+
# TODO: ideally this would match a specific error about teamspace not being found
|
|
126
|
+
_ = _get_teamspace(name=teamspace_name, organization=teamspace_owner_name)
|
|
127
|
+
raise e
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def upload_model(
|
|
131
|
+
name: str,
|
|
132
|
+
path: Union[Path, str] = ".",
|
|
133
|
+
cloud_account: Optional[str] = None,
|
|
134
|
+
progress_bar: bool = True,
|
|
135
|
+
) -> UploadedModelInfo:
|
|
136
|
+
"""Upload a Model.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
name: The name of the Model you want to upload.
|
|
140
|
+
This should have the format <ORGANIZATION-NAME>/<TEAMSPACE-NAME>/<MODEL-NAME>.
|
|
141
|
+
path: The path to the file or directory you want to upload. Defaults to the current directory.
|
|
142
|
+
cloud_account: The name of the cloud account to store the Model in.
|
|
143
|
+
If not provided, the default cloud account for the Teamspace will be used.
|
|
144
|
+
progress_bar: Whether to show a progress bar for the upload.
|
|
145
|
+
"""
|
|
146
|
+
org_name, teamspace_name, model_name, _ = _parse_model_name_and_version(name)
|
|
147
|
+
teamspace = _get_teamspace(name=teamspace_name, organization=org_name)
|
|
148
|
+
return teamspace.upload_model(
|
|
149
|
+
path=path,
|
|
150
|
+
name=model_name,
|
|
151
|
+
cloud_account=cloud_account,
|
|
152
|
+
progress_bar=progress_bar,
|
|
153
|
+
)
|
lightning_sdk/teamspace.py
CHANGED
|
@@ -3,7 +3,7 @@ from typing import TYPE_CHECKING, List, Optional, Union
|
|
|
3
3
|
|
|
4
4
|
from lightning_sdk.agents import Agent
|
|
5
5
|
from lightning_sdk.api import TeamspaceApi
|
|
6
|
-
from lightning_sdk.
|
|
6
|
+
from lightning_sdk.models import UploadedModelInfo
|
|
7
7
|
from lightning_sdk.organization import Organization
|
|
8
8
|
from lightning_sdk.owner import Owner
|
|
9
9
|
from lightning_sdk.user import User
|
|
@@ -105,6 +105,10 @@ class Teamspace:
|
|
|
105
105
|
|
|
106
106
|
return studios
|
|
107
107
|
|
|
108
|
+
@property
|
|
109
|
+
def default_cluster(self) -> str:
|
|
110
|
+
return self._teamspace.project_settings.preferred_cluster
|
|
111
|
+
|
|
108
112
|
@property
|
|
109
113
|
def clusters(self) -> List[str]:
|
|
110
114
|
"""All clusters associated with that teamspace."""
|
|
@@ -153,20 +157,19 @@ class Teamspace:
|
|
|
153
157
|
|
|
154
158
|
def upload_model(
|
|
155
159
|
self,
|
|
156
|
-
path: str,
|
|
160
|
+
path: Union[str, Path],
|
|
157
161
|
name: str,
|
|
162
|
+
cloud_account: Optional[str] = None,
|
|
158
163
|
progress_bar: bool = True,
|
|
159
|
-
cluster_id: Optional[str] = None,
|
|
160
164
|
) -> UploadedModelInfo:
|
|
161
165
|
"""Upload a local checkpoint file to the model store.
|
|
162
166
|
|
|
163
167
|
Args:
|
|
164
168
|
path: Path to the model file or folder to upload.
|
|
165
169
|
name: Name tag of the model to upload.
|
|
170
|
+
cloud_account: The name of the cloud account to store the Model in.
|
|
171
|
+
If not provided, the default cloud account for the Teamspace will be used.
|
|
166
172
|
progress_bar: Whether to show a progress bar for the upload.
|
|
167
|
-
cluster_id: The name of the cluster to use. Only required if it can't be determined
|
|
168
|
-
automatically.
|
|
169
|
-
|
|
170
173
|
"""
|
|
171
174
|
if not path:
|
|
172
175
|
raise ValueError("No path provided to upload")
|
|
@@ -176,7 +179,7 @@ class Teamspace:
|
|
|
176
179
|
if not path.exists():
|
|
177
180
|
raise FileNotFoundError(str(path))
|
|
178
181
|
|
|
179
|
-
|
|
182
|
+
cloud_account = self._teamspace_api._determine_cluster_id(self.id) if cloud_account is None else cloud_account
|
|
180
183
|
filepaths = [path] if path.is_file() else [p for p in path.rglob("*") if p.is_file()]
|
|
181
184
|
|
|
182
185
|
if not filepaths:
|
|
@@ -196,14 +199,14 @@ class Teamspace:
|
|
|
196
199
|
metadata={"filenames": filenames},
|
|
197
200
|
private=True,
|
|
198
201
|
teamspace_id=self.id,
|
|
199
|
-
cluster_id=
|
|
202
|
+
cluster_id=cloud_account,
|
|
200
203
|
)
|
|
201
204
|
self._teamspace_api.upload_model_files(
|
|
202
205
|
model_id=model.model_id,
|
|
203
206
|
version=model.version,
|
|
204
207
|
root_path=root_path,
|
|
205
208
|
filepaths=filepaths,
|
|
206
|
-
cluster_id=
|
|
209
|
+
cluster_id=cloud_account,
|
|
207
210
|
teamspace_id=self.id,
|
|
208
211
|
progress_bar=progress_bar,
|
|
209
212
|
)
|
|
@@ -216,7 +219,7 @@ class Teamspace:
|
|
|
216
219
|
name=name,
|
|
217
220
|
version=model.version,
|
|
218
221
|
teamspace=self.name,
|
|
219
|
-
|
|
222
|
+
cloud_account=cloud_account,
|
|
220
223
|
)
|
|
221
224
|
|
|
222
225
|
def download_model(
|
|
@@ -254,7 +257,8 @@ class Teamspace:
|
|
|
254
257
|
name=name,
|
|
255
258
|
version=version,
|
|
256
259
|
download_dir=download_dir,
|
|
257
|
-
|
|
260
|
+
teamspace_name=self.name,
|
|
261
|
+
teamspace_owner_name=self.owner.name,
|
|
258
262
|
progress_bar=progress_bar,
|
|
259
263
|
)
|
|
260
264
|
|