lightning-sdk 0.2.21rc0__py3-none-any.whl → 0.2.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 (40) hide show
  1. lightning_sdk/__init__.py +1 -1
  2. lightning_sdk/api/deployment_api.py +7 -2
  3. lightning_sdk/api/license_api.py +1 -1
  4. lightning_sdk/api/llm_api.py +67 -27
  5. lightning_sdk/api/pipeline_api.py +48 -9
  6. lightning_sdk/cli/configure.py +34 -27
  7. lightning_sdk/cli/connect.py +2 -2
  8. lightning_sdk/cli/download.py +38 -2
  9. lightning_sdk/deployment/deployment.py +17 -3
  10. lightning_sdk/lightning_cloud/openapi/__init__.py +1 -0
  11. lightning_sdk/lightning_cloud/openapi/api/cluster_service_api.py +1 -5
  12. lightning_sdk/lightning_cloud/openapi/api/lit_registry_service_api.py +113 -0
  13. lightning_sdk/lightning_cloud/openapi/api/schedules_service_api.py +5 -1
  14. lightning_sdk/lightning_cloud/openapi/configuration.py +1 -1
  15. lightning_sdk/lightning_cloud/openapi/models/__init__.py +1 -0
  16. lightning_sdk/lightning_cloud/openapi/models/project_id_pipelines_body.py +27 -1
  17. lightning_sdk/lightning_cloud/openapi/models/project_id_schedules_body.py +27 -1
  18. lightning_sdk/lightning_cloud/openapi/models/schedules_id_body.py +27 -1
  19. lightning_sdk/lightning_cloud/openapi/models/v1_delete_lit_registry_repository_image_artifact_version_by_digest_response.py +97 -0
  20. lightning_sdk/lightning_cloud/openapi/models/v1_get_project_storage_metadata_response.py +27 -1
  21. lightning_sdk/lightning_cloud/openapi/models/v1_get_user_response.py +79 -1
  22. lightning_sdk/lightning_cloud/openapi/models/v1_get_user_storage_breakdown_response.py +53 -1
  23. lightning_sdk/lightning_cloud/openapi/models/v1_schedule.py +27 -1
  24. lightning_sdk/lightning_cloud/openapi/models/v1_update_user_request.py +79 -1
  25. lightning_sdk/lightning_cloud/openapi/models/v1_user_features.py +1 -105
  26. lightning_sdk/llm/__init__.py +1 -2
  27. lightning_sdk/llm/llm.py +52 -1
  28. lightning_sdk/pipeline/__init__.py +2 -1
  29. lightning_sdk/pipeline/pipeline.py +23 -6
  30. lightning_sdk/pipeline/printer.py +102 -0
  31. lightning_sdk/pipeline/schedule.py +7 -0
  32. lightning_sdk/pipeline/types.py +3 -3
  33. lightning_sdk/pipeline/utils.py +1 -16
  34. {lightning_sdk-0.2.21rc0.dist-info → lightning_sdk-0.2.22.dist-info}/METADATA +1 -1
  35. {lightning_sdk-0.2.21rc0.dist-info → lightning_sdk-0.2.22.dist-info}/RECORD +39 -37
  36. lightning_sdk/llm/asyncllm.py +0 -48
  37. {lightning_sdk-0.2.21rc0.dist-info → lightning_sdk-0.2.22.dist-info}/LICENSE +0 -0
  38. {lightning_sdk-0.2.21rc0.dist-info → lightning_sdk-0.2.22.dist-info}/WHEEL +0 -0
  39. {lightning_sdk-0.2.21rc0.dist-info → lightning_sdk-0.2.22.dist-info}/entry_points.txt +0 -0
  40. {lightning_sdk-0.2.21rc0.dist-info → lightning_sdk-0.2.22.dist-info}/top_level.txt +0 -0
@@ -42,6 +42,9 @@ class V1UpdateUserRequest(object):
42
42
  """
43
43
  swagger_types = {
44
44
  'agree_to_terms_and_conditions': 'bool',
45
+ 'allow_credits_auto_replenish': 'bool',
46
+ 'auto_replenish_amount': 'float',
47
+ 'auto_replenish_threshold': 'float',
45
48
  'complete_sign_up': 'bool',
46
49
  'completed_project_onboarding': 'bool',
47
50
  'country': 'str',
@@ -69,6 +72,9 @@ class V1UpdateUserRequest(object):
69
72
 
70
73
  attribute_map = {
71
74
  'agree_to_terms_and_conditions': 'agreeToTermsAndConditions',
75
+ 'allow_credits_auto_replenish': 'allowCreditsAutoReplenish',
76
+ 'auto_replenish_amount': 'autoReplenishAmount',
77
+ 'auto_replenish_threshold': 'autoReplenishThreshold',
72
78
  'complete_sign_up': 'completeSignUp',
73
79
  'completed_project_onboarding': 'completedProjectOnboarding',
74
80
  'country': 'country',
@@ -94,9 +100,12 @@ class V1UpdateUserRequest(object):
94
100
  'website': 'website'
95
101
  }
96
102
 
97
- def __init__(self, agree_to_terms_and_conditions: 'bool' =None, complete_sign_up: 'bool' =None, completed_project_onboarding: 'bool' =None, country: 'str' =None, discounted_pro_plan: 'bool' =None, email: 'str' =None, experimentation_id: 'str' =None, first_name: 'str' =None, general_audience_mode: 'bool' =None, last_name: 'str' =None, non_developer_mode: 'bool' =None, opted_in_marketing_emails: 'bool' =None, organization: 'str' =None, preferred_color_scheme: 'str' =None, preferred_ide: 'str' =None, preferred_shell: 'str' =None, preferred_vscode_marketplace: 'str' =None, role: 'str' =None, saw_create_first_project_dialog: 'bool' =None, saw_forums_login_merge_dialog: 'bool' =None, saw_free_credits_notification: 'bool' =None, user_metadata: 'str' =None, username: 'str' =None, website: 'str' =None): # noqa: E501
103
+ def __init__(self, agree_to_terms_and_conditions: 'bool' =None, allow_credits_auto_replenish: 'bool' =None, auto_replenish_amount: 'float' =None, auto_replenish_threshold: 'float' =None, complete_sign_up: 'bool' =None, completed_project_onboarding: 'bool' =None, country: 'str' =None, discounted_pro_plan: 'bool' =None, email: 'str' =None, experimentation_id: 'str' =None, first_name: 'str' =None, general_audience_mode: 'bool' =None, last_name: 'str' =None, non_developer_mode: 'bool' =None, opted_in_marketing_emails: 'bool' =None, organization: 'str' =None, preferred_color_scheme: 'str' =None, preferred_ide: 'str' =None, preferred_shell: 'str' =None, preferred_vscode_marketplace: 'str' =None, role: 'str' =None, saw_create_first_project_dialog: 'bool' =None, saw_forums_login_merge_dialog: 'bool' =None, saw_free_credits_notification: 'bool' =None, user_metadata: 'str' =None, username: 'str' =None, website: 'str' =None): # noqa: E501
98
104
  """V1UpdateUserRequest - a model defined in Swagger""" # noqa: E501
99
105
  self._agree_to_terms_and_conditions = None
106
+ self._allow_credits_auto_replenish = None
107
+ self._auto_replenish_amount = None
108
+ self._auto_replenish_threshold = None
100
109
  self._complete_sign_up = None
101
110
  self._completed_project_onboarding = None
102
111
  self._country = None
@@ -123,6 +132,12 @@ class V1UpdateUserRequest(object):
123
132
  self.discriminator = None
124
133
  if agree_to_terms_and_conditions is not None:
125
134
  self.agree_to_terms_and_conditions = agree_to_terms_and_conditions
135
+ if allow_credits_auto_replenish is not None:
136
+ self.allow_credits_auto_replenish = allow_credits_auto_replenish
137
+ if auto_replenish_amount is not None:
138
+ self.auto_replenish_amount = auto_replenish_amount
139
+ if auto_replenish_threshold is not None:
140
+ self.auto_replenish_threshold = auto_replenish_threshold
126
141
  if complete_sign_up is not None:
127
142
  self.complete_sign_up = complete_sign_up
128
143
  if completed_project_onboarding is not None:
@@ -191,6 +206,69 @@ class V1UpdateUserRequest(object):
191
206
 
192
207
  self._agree_to_terms_and_conditions = agree_to_terms_and_conditions
193
208
 
209
+ @property
210
+ def allow_credits_auto_replenish(self) -> 'bool':
211
+ """Gets the allow_credits_auto_replenish of this V1UpdateUserRequest. # noqa: E501
212
+
213
+
214
+ :return: The allow_credits_auto_replenish of this V1UpdateUserRequest. # noqa: E501
215
+ :rtype: bool
216
+ """
217
+ return self._allow_credits_auto_replenish
218
+
219
+ @allow_credits_auto_replenish.setter
220
+ def allow_credits_auto_replenish(self, allow_credits_auto_replenish: 'bool'):
221
+ """Sets the allow_credits_auto_replenish of this V1UpdateUserRequest.
222
+
223
+
224
+ :param allow_credits_auto_replenish: The allow_credits_auto_replenish of this V1UpdateUserRequest. # noqa: E501
225
+ :type: bool
226
+ """
227
+
228
+ self._allow_credits_auto_replenish = allow_credits_auto_replenish
229
+
230
+ @property
231
+ def auto_replenish_amount(self) -> 'float':
232
+ """Gets the auto_replenish_amount of this V1UpdateUserRequest. # noqa: E501
233
+
234
+
235
+ :return: The auto_replenish_amount of this V1UpdateUserRequest. # noqa: E501
236
+ :rtype: float
237
+ """
238
+ return self._auto_replenish_amount
239
+
240
+ @auto_replenish_amount.setter
241
+ def auto_replenish_amount(self, auto_replenish_amount: 'float'):
242
+ """Sets the auto_replenish_amount of this V1UpdateUserRequest.
243
+
244
+
245
+ :param auto_replenish_amount: The auto_replenish_amount of this V1UpdateUserRequest. # noqa: E501
246
+ :type: float
247
+ """
248
+
249
+ self._auto_replenish_amount = auto_replenish_amount
250
+
251
+ @property
252
+ def auto_replenish_threshold(self) -> 'float':
253
+ """Gets the auto_replenish_threshold of this V1UpdateUserRequest. # noqa: E501
254
+
255
+
256
+ :return: The auto_replenish_threshold of this V1UpdateUserRequest. # noqa: E501
257
+ :rtype: float
258
+ """
259
+ return self._auto_replenish_threshold
260
+
261
+ @auto_replenish_threshold.setter
262
+ def auto_replenish_threshold(self, auto_replenish_threshold: 'float'):
263
+ """Sets the auto_replenish_threshold of this V1UpdateUserRequest.
264
+
265
+
266
+ :param auto_replenish_threshold: The auto_replenish_threshold of this V1UpdateUserRequest. # noqa: E501
267
+ :type: float
268
+ """
269
+
270
+ self._auto_replenish_threshold = auto_replenish_threshold
271
+
194
272
  @property
195
273
  def complete_sign_up(self) -> 'bool':
196
274
  """Gets the complete_sign_up of this V1UpdateUserRequest. # noqa: E501
@@ -66,7 +66,6 @@ class V1UserFeatures(object):
66
66
  'datasets': 'bool',
67
67
  'default_one_cluster': 'bool',
68
68
  'deployment_persistent_disk': 'bool',
69
- 'docs_agent': 'bool',
70
69
  'drive_v2': 'bool',
71
70
  'enterprise_compute_admin': 'bool',
72
71
  'fair_share': 'bool',
@@ -111,15 +110,12 @@ class V1UserFeatures(object):
111
110
  'restartable_jobs': 'bool',
112
111
  'runnable_public_studio_page': 'bool',
113
112
  'security_docs': 'bool',
114
- 'seoul_aws_region': 'bool',
115
113
  'show_dev_admin': 'bool',
116
114
  'single_wallet': 'bool',
117
115
  'slurm': 'bool',
118
- 'slurm_machine_selector': 'bool',
119
116
  'storage_overuse_deletion': 'bool',
120
117
  'studio_config': 'bool',
121
118
  'studio_version_visibility': 'bool',
122
- 'teamspace_storage_tab': 'bool',
123
119
  'trainium2': 'bool',
124
120
  'use_rclone_mounts_only': 'bool',
125
121
  'voltage_park': 'bool',
@@ -154,7 +150,6 @@ class V1UserFeatures(object):
154
150
  'datasets': 'datasets',
155
151
  'default_one_cluster': 'defaultOneCluster',
156
152
  'deployment_persistent_disk': 'deploymentPersistentDisk',
157
- 'docs_agent': 'docsAgent',
158
153
  'drive_v2': 'driveV2',
159
154
  'enterprise_compute_admin': 'enterpriseComputeAdmin',
160
155
  'fair_share': 'fairShare',
@@ -199,15 +194,12 @@ class V1UserFeatures(object):
199
194
  'restartable_jobs': 'restartableJobs',
200
195
  'runnable_public_studio_page': 'runnablePublicStudioPage',
201
196
  'security_docs': 'securityDocs',
202
- 'seoul_aws_region': 'seoulAwsRegion',
203
197
  'show_dev_admin': 'showDevAdmin',
204
198
  'single_wallet': 'singleWallet',
205
199
  'slurm': 'slurm',
206
- 'slurm_machine_selector': 'slurmMachineSelector',
207
200
  'storage_overuse_deletion': 'storageOveruseDeletion',
208
201
  'studio_config': 'studioConfig',
209
202
  'studio_version_visibility': 'studioVersionVisibility',
210
- 'teamspace_storage_tab': 'teamspaceStorageTab',
211
203
  'trainium2': 'trainium2',
212
204
  'use_rclone_mounts_only': 'useRcloneMountsOnly',
213
205
  'voltage_park': 'voltagePark',
@@ -216,7 +208,7 @@ class V1UserFeatures(object):
216
208
  'weka': 'weka'
217
209
  }
218
210
 
219
- def __init__(self, accurate_billing: '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, auto_top_up: 'bool' =None, auto_top_up_teamspace: 'bool' =None, b2c_experience: 'bool' =None, cap_add: 'list[str]' =None, cap_drop: 'list[str]' =None, capacity_reservation_byoc: 'bool' =None, capacity_reservation_dry_run: 'bool' =None, chat_models: 'bool' =None, cloud_space_environment_templates: 'bool' =None, cloudy_vibe_code: 'bool' =None, code_tab: 'bool' =None, collab_screen_sharing: 'bool' =None, concurrent_gpu_limit: 'bool' =None, control_center_monitoring: 'bool' =None, cost_attribution_settings: 'bool' =None, custom_app_domain: 'bool' =None, datasets: 'bool' =None, default_one_cluster: 'bool' =None, deployment_persistent_disk: 'bool' =None, docs_agent: 'bool' =None, drive_v2: 'bool' =None, enterprise_compute_admin: 'bool' =None, fair_share: 'bool' =None, featured_studios_admin: 'bool' =None, gcs_folders: 'bool' =None, instant_capacity_reservation: 'bool' =None, job_artifacts_v2: 'bool' =None, lambda_labs: 'bool' =None, lambda_labs_studios: 'bool' =None, landing_studios: 'bool' =None, lit_logger: 'bool' =None, marketplace: 'bool' =None, mmt_fault_tolerance: 'bool' =None, mmt_strategy_selector: 'bool' =None, model_api_dashboard: 'bool' =None, multicloud_folders: 'bool' =None, multicloud_saas: 'bool' =None, multiple_studio_versions: 'bool' =None, nebius: 'bool' =None, nebius_cpu_studios: 'bool' =None, nebius_gpu_studios: 'bool' =None, nerf_fs_nonpaying: 'bool' =None, org_level_member_permissions: 'bool' =None, org_usage_limits: 'bool' =None, paygo_free_storage_limit_check: 'bool' =None, pipelines: 'bool' =None, plg_control_center: 'bool' =None, plugin_distributed: 'bool' =None, plugin_inference: 'bool' =None, plugin_label_studio: 'bool' =None, plugin_langflow: 'bool' =None, plugin_python_profiler: 'bool' =None, plugin_service: 'bool' =None, plugin_sweeps: 'bool' =None, pricing_updates: 'bool' =None, product_generator: 'bool' =None, product_license: 'bool' =None, project_selector: 'bool' =None, publish_pipelines: 'bool' =None, r2_data_connections: 'bool' =None, reserved_machines_tab: 'bool' =None, restartable_jobs: 'bool' =None, runnable_public_studio_page: 'bool' =None, security_docs: 'bool' =None, seoul_aws_region: 'bool' =None, show_dev_admin: 'bool' =None, single_wallet: 'bool' =None, slurm: 'bool' =None, slurm_machine_selector: 'bool' =None, storage_overuse_deletion: 'bool' =None, studio_config: 'bool' =None, studio_version_visibility: 'bool' =None, teamspace_storage_tab: 'bool' =None, trainium2: 'bool' =None, use_rclone_mounts_only: 'bool' =None, voltage_park: 'bool' =None, voltage_park_studios: 'bool' =None, vultr: 'bool' =None, weka: 'bool' =None): # noqa: E501
211
+ def __init__(self, accurate_billing: '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, auto_top_up: 'bool' =None, auto_top_up_teamspace: 'bool' =None, b2c_experience: 'bool' =None, cap_add: 'list[str]' =None, cap_drop: 'list[str]' =None, capacity_reservation_byoc: 'bool' =None, capacity_reservation_dry_run: 'bool' =None, chat_models: 'bool' =None, cloud_space_environment_templates: 'bool' =None, cloudy_vibe_code: 'bool' =None, code_tab: 'bool' =None, collab_screen_sharing: 'bool' =None, concurrent_gpu_limit: 'bool' =None, control_center_monitoring: 'bool' =None, cost_attribution_settings: 'bool' =None, custom_app_domain: 'bool' =None, datasets: 'bool' =None, default_one_cluster: 'bool' =None, deployment_persistent_disk: 'bool' =None, drive_v2: 'bool' =None, enterprise_compute_admin: 'bool' =None, fair_share: 'bool' =None, featured_studios_admin: 'bool' =None, gcs_folders: 'bool' =None, instant_capacity_reservation: 'bool' =None, job_artifacts_v2: 'bool' =None, lambda_labs: 'bool' =None, lambda_labs_studios: 'bool' =None, landing_studios: 'bool' =None, lit_logger: 'bool' =None, marketplace: 'bool' =None, mmt_fault_tolerance: 'bool' =None, mmt_strategy_selector: 'bool' =None, model_api_dashboard: 'bool' =None, multicloud_folders: 'bool' =None, multicloud_saas: 'bool' =None, multiple_studio_versions: 'bool' =None, nebius: 'bool' =None, nebius_cpu_studios: 'bool' =None, nebius_gpu_studios: 'bool' =None, nerf_fs_nonpaying: 'bool' =None, org_level_member_permissions: 'bool' =None, org_usage_limits: 'bool' =None, paygo_free_storage_limit_check: 'bool' =None, pipelines: 'bool' =None, plg_control_center: 'bool' =None, plugin_distributed: 'bool' =None, plugin_inference: 'bool' =None, plugin_label_studio: 'bool' =None, plugin_langflow: 'bool' =None, plugin_python_profiler: 'bool' =None, plugin_service: 'bool' =None, plugin_sweeps: 'bool' =None, pricing_updates: 'bool' =None, product_generator: 'bool' =None, product_license: 'bool' =None, project_selector: 'bool' =None, publish_pipelines: 'bool' =None, r2_data_connections: 'bool' =None, reserved_machines_tab: 'bool' =None, restartable_jobs: 'bool' =None, runnable_public_studio_page: 'bool' =None, security_docs: 'bool' =None, show_dev_admin: 'bool' =None, single_wallet: 'bool' =None, slurm: 'bool' =None, storage_overuse_deletion: 'bool' =None, studio_config: 'bool' =None, studio_version_visibility: 'bool' =None, trainium2: 'bool' =None, use_rclone_mounts_only: 'bool' =None, voltage_park: 'bool' =None, voltage_park_studios: 'bool' =None, vultr: 'bool' =None, weka: 'bool' =None): # noqa: E501
220
212
  """V1UserFeatures - a model defined in Swagger""" # noqa: E501
221
213
  self._accurate_billing = None
222
214
  self._affiliate_links = None
@@ -243,7 +235,6 @@ class V1UserFeatures(object):
243
235
  self._datasets = None
244
236
  self._default_one_cluster = None
245
237
  self._deployment_persistent_disk = None
246
- self._docs_agent = None
247
238
  self._drive_v2 = None
248
239
  self._enterprise_compute_admin = None
249
240
  self._fair_share = None
@@ -288,15 +279,12 @@ class V1UserFeatures(object):
288
279
  self._restartable_jobs = None
289
280
  self._runnable_public_studio_page = None
290
281
  self._security_docs = None
291
- self._seoul_aws_region = None
292
282
  self._show_dev_admin = None
293
283
  self._single_wallet = None
294
284
  self._slurm = None
295
- self._slurm_machine_selector = None
296
285
  self._storage_overuse_deletion = None
297
286
  self._studio_config = None
298
287
  self._studio_version_visibility = None
299
- self._teamspace_storage_tab = None
300
288
  self._trainium2 = None
301
289
  self._use_rclone_mounts_only = None
302
290
  self._voltage_park = None
@@ -354,8 +342,6 @@ class V1UserFeatures(object):
354
342
  self.default_one_cluster = default_one_cluster
355
343
  if deployment_persistent_disk is not None:
356
344
  self.deployment_persistent_disk = deployment_persistent_disk
357
- if docs_agent is not None:
358
- self.docs_agent = docs_agent
359
345
  if drive_v2 is not None:
360
346
  self.drive_v2 = drive_v2
361
347
  if enterprise_compute_admin is not None:
@@ -444,24 +430,18 @@ class V1UserFeatures(object):
444
430
  self.runnable_public_studio_page = runnable_public_studio_page
445
431
  if security_docs is not None:
446
432
  self.security_docs = security_docs
447
- if seoul_aws_region is not None:
448
- self.seoul_aws_region = seoul_aws_region
449
433
  if show_dev_admin is not None:
450
434
  self.show_dev_admin = show_dev_admin
451
435
  if single_wallet is not None:
452
436
  self.single_wallet = single_wallet
453
437
  if slurm is not None:
454
438
  self.slurm = slurm
455
- if slurm_machine_selector is not None:
456
- self.slurm_machine_selector = slurm_machine_selector
457
439
  if storage_overuse_deletion is not None:
458
440
  self.storage_overuse_deletion = storage_overuse_deletion
459
441
  if studio_config is not None:
460
442
  self.studio_config = studio_config
461
443
  if studio_version_visibility is not None:
462
444
  self.studio_version_visibility = studio_version_visibility
463
- if teamspace_storage_tab is not None:
464
- self.teamspace_storage_tab = teamspace_storage_tab
465
445
  if trainium2 is not None:
466
446
  self.trainium2 = trainium2
467
447
  if use_rclone_mounts_only is not None:
@@ -1000,27 +980,6 @@ class V1UserFeatures(object):
1000
980
 
1001
981
  self._deployment_persistent_disk = deployment_persistent_disk
1002
982
 
1003
- @property
1004
- def docs_agent(self) -> 'bool':
1005
- """Gets the docs_agent of this V1UserFeatures. # noqa: E501
1006
-
1007
-
1008
- :return: The docs_agent of this V1UserFeatures. # noqa: E501
1009
- :rtype: bool
1010
- """
1011
- return self._docs_agent
1012
-
1013
- @docs_agent.setter
1014
- def docs_agent(self, docs_agent: 'bool'):
1015
- """Sets the docs_agent of this V1UserFeatures.
1016
-
1017
-
1018
- :param docs_agent: The docs_agent of this V1UserFeatures. # noqa: E501
1019
- :type: bool
1020
- """
1021
-
1022
- self._docs_agent = docs_agent
1023
-
1024
983
  @property
1025
984
  def drive_v2(self) -> 'bool':
1026
985
  """Gets the drive_v2 of this V1UserFeatures. # noqa: E501
@@ -1945,27 +1904,6 @@ class V1UserFeatures(object):
1945
1904
 
1946
1905
  self._security_docs = security_docs
1947
1906
 
1948
- @property
1949
- def seoul_aws_region(self) -> 'bool':
1950
- """Gets the seoul_aws_region of this V1UserFeatures. # noqa: E501
1951
-
1952
-
1953
- :return: The seoul_aws_region of this V1UserFeatures. # noqa: E501
1954
- :rtype: bool
1955
- """
1956
- return self._seoul_aws_region
1957
-
1958
- @seoul_aws_region.setter
1959
- def seoul_aws_region(self, seoul_aws_region: 'bool'):
1960
- """Sets the seoul_aws_region of this V1UserFeatures.
1961
-
1962
-
1963
- :param seoul_aws_region: The seoul_aws_region of this V1UserFeatures. # noqa: E501
1964
- :type: bool
1965
- """
1966
-
1967
- self._seoul_aws_region = seoul_aws_region
1968
-
1969
1907
  @property
1970
1908
  def show_dev_admin(self) -> 'bool':
1971
1909
  """Gets the show_dev_admin of this V1UserFeatures. # noqa: E501
@@ -2029,27 +1967,6 @@ class V1UserFeatures(object):
2029
1967
 
2030
1968
  self._slurm = slurm
2031
1969
 
2032
- @property
2033
- def slurm_machine_selector(self) -> 'bool':
2034
- """Gets the slurm_machine_selector of this V1UserFeatures. # noqa: E501
2035
-
2036
-
2037
- :return: The slurm_machine_selector of this V1UserFeatures. # noqa: E501
2038
- :rtype: bool
2039
- """
2040
- return self._slurm_machine_selector
2041
-
2042
- @slurm_machine_selector.setter
2043
- def slurm_machine_selector(self, slurm_machine_selector: 'bool'):
2044
- """Sets the slurm_machine_selector of this V1UserFeatures.
2045
-
2046
-
2047
- :param slurm_machine_selector: The slurm_machine_selector of this V1UserFeatures. # noqa: E501
2048
- :type: bool
2049
- """
2050
-
2051
- self._slurm_machine_selector = slurm_machine_selector
2052
-
2053
1970
  @property
2054
1971
  def storage_overuse_deletion(self) -> 'bool':
2055
1972
  """Gets the storage_overuse_deletion of this V1UserFeatures. # noqa: E501
@@ -2113,27 +2030,6 @@ class V1UserFeatures(object):
2113
2030
 
2114
2031
  self._studio_version_visibility = studio_version_visibility
2115
2032
 
2116
- @property
2117
- def teamspace_storage_tab(self) -> 'bool':
2118
- """Gets the teamspace_storage_tab of this V1UserFeatures. # noqa: E501
2119
-
2120
-
2121
- :return: The teamspace_storage_tab of this V1UserFeatures. # noqa: E501
2122
- :rtype: bool
2123
- """
2124
- return self._teamspace_storage_tab
2125
-
2126
- @teamspace_storage_tab.setter
2127
- def teamspace_storage_tab(self, teamspace_storage_tab: 'bool'):
2128
- """Sets the teamspace_storage_tab of this V1UserFeatures.
2129
-
2130
-
2131
- :param teamspace_storage_tab: The teamspace_storage_tab of this V1UserFeatures. # noqa: E501
2132
- :type: bool
2133
- """
2134
-
2135
- self._teamspace_storage_tab = teamspace_storage_tab
2136
-
2137
2033
  @property
2138
2034
  def trainium2(self) -> 'bool':
2139
2035
  """Gets the trainium2 of this V1UserFeatures. # noqa: E501
@@ -1,4 +1,3 @@
1
- from lightning_sdk.llm.asyncllm import AsyncLLM
2
1
  from lightning_sdk.llm.llm import LLM
3
2
 
4
- __all__ = ["LLM", "AsyncLLM"]
3
+ __all__ = ["LLM"]
lightning_sdk/llm/llm.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import os
2
2
  import warnings
3
- from typing import Dict, Generator, List, Optional, Set, Tuple, Union
3
+ from typing import AsyncGenerator, Dict, Generator, List, Optional, Set, Tuple, Union
4
4
 
5
5
  from lightning_sdk.api.llm_api import LLMApi
6
6
  from lightning_sdk.cli.teamspace_menu import _TeamspacesMenu
@@ -18,6 +18,7 @@ class LLM:
18
18
  self,
19
19
  name: str,
20
20
  teamspace: Optional[str] = None,
21
+ enable_async: Optional[bool] = False,
21
22
  ) -> None:
22
23
  """Initializes the LLM instance with teamspace information, which is required for billing purposes.
23
24
 
@@ -30,6 +31,7 @@ class LLM:
30
31
  name (str): The name of the model or resource.
31
32
  teamspace (Optional[str]): The specified teamspace for billing. If not provided, it will be resolved
32
33
  through the above methods.
34
+ enable_async (Optional[bool]): Enable async requests
33
35
 
34
36
  Raises:
35
37
  ValueError: If teamspace information cannot be resolved.
@@ -67,6 +69,7 @@ class LLM:
67
69
  self._model_provider, self._model_name = self._parse_model_name(name)
68
70
 
69
71
  self._llm_api = LLMApi()
72
+ self._enable_async = enable_async
70
73
 
71
74
  try:
72
75
  # check if it is a org model
@@ -174,6 +177,41 @@ class LLM:
174
177
  for line in result:
175
178
  yield line.choices[0].delta.content
176
179
 
180
+ async def _async_stream_text(self, output: str) -> AsyncGenerator[str, None]:
181
+ async for chunk in output:
182
+ if chunk.choices and chunk.choices[0].delta:
183
+ yield chunk.choices[0].delta.content
184
+
185
+ async def _async_chat(
186
+ self,
187
+ prompt: str,
188
+ system_prompt: Optional[str] = None,
189
+ max_completion_tokens: Optional[int] = 500,
190
+ images: Optional[Union[List[str], str]] = None,
191
+ conversation: Optional[str] = None,
192
+ metadata: Optional[Dict[str, str]] = None,
193
+ stream: bool = False,
194
+ upload_local_images: bool = False,
195
+ ) -> Union[str, AsyncGenerator[str, None]]:
196
+ conversation_id = self._conversations.get(conversation) if conversation else None
197
+ output = await self._llm_api.async_start_conversation(
198
+ prompt=prompt,
199
+ system_prompt=system_prompt,
200
+ max_completion_tokens=max_completion_tokens,
201
+ images=images,
202
+ assistant_id=self._model.id,
203
+ conversation_id=conversation_id,
204
+ billing_project_id=self._teamspace.id,
205
+ metadata=metadata,
206
+ name=conversation,
207
+ stream=stream,
208
+ )
209
+ if not stream:
210
+ if conversation and not conversation_id:
211
+ self._conversations[conversation] = output.conversation_id
212
+ return output.choices[0].delta.content
213
+ return self._async_stream_text(output)
214
+
177
215
  def chat(
178
216
  self,
179
217
  prompt: str,
@@ -198,6 +236,19 @@ class LLM:
198
236
  self._teamspace.upload_file(file_path=image, remote_path=f"images/{os.path.basename(image)}")
199
237
 
200
238
  conversation_id = self._conversations.get(conversation) if conversation else None
239
+
240
+ if self._enable_async:
241
+ return self._async_chat(
242
+ prompt,
243
+ system_prompt,
244
+ max_completion_tokens,
245
+ images,
246
+ conversation,
247
+ metadata,
248
+ stream,
249
+ upload_local_images,
250
+ )
251
+
201
252
  output = self._llm_api.start_conversation(
202
253
  prompt=prompt,
203
254
  system_prompt=system_prompt,
@@ -1,4 +1,5 @@
1
1
  from lightning_sdk.pipeline.pipeline import Pipeline
2
+ from lightning_sdk.pipeline.schedule import Schedule
2
3
  from lightning_sdk.pipeline.types import MMT, Deployment, Job
3
4
 
4
- __all__ = ["Pipeline", "Job", "MMT", "Deployment"]
5
+ __all__ = ["Pipeline", "Job", "MMT", "Deployment", "Schedule"]
@@ -1,9 +1,10 @@
1
- from typing import List, Optional, Union
1
+ from typing import TYPE_CHECKING, List, Optional, Union
2
2
 
3
3
  from lightning_sdk.api import UserApi
4
4
  from lightning_sdk.api.pipeline_api import PipelineApi
5
5
  from lightning_sdk.lightning_cloud.login import Auth
6
6
  from lightning_sdk.organization import Organization
7
+ from lightning_sdk.pipeline.printer import PipelinePrinter
7
8
  from lightning_sdk.pipeline.types import MMT, Deployment, Job
8
9
  from lightning_sdk.pipeline.utils import prepare_steps
9
10
  from lightning_sdk.services.utilities import _get_cluster
@@ -11,6 +12,9 @@ from lightning_sdk.teamspace import Teamspace
11
12
  from lightning_sdk.user import User
12
13
  from lightning_sdk.utils.resolve import _resolve_org, _resolve_teamspace, _resolve_user
13
14
 
15
+ if TYPE_CHECKING:
16
+ from lightning_sdk.pipeline.schedule import Schedule
17
+
14
18
 
15
19
  class Pipeline:
16
20
  def __init__(
@@ -62,15 +66,16 @@ class Pipeline:
62
66
 
63
67
  pipeline = None
64
68
 
65
- if name.startswith("pip_"):
66
- pipeline = self._pipeline_api.get_pipeline_by_id(name, self._teamspace.id)
69
+ pipeline = self._pipeline_api.get_pipeline_by_id(self._teamspace.id, name)
67
70
 
68
71
  if pipeline:
69
72
  self._name = pipeline.name
70
73
  self._is_created = True
71
74
  self._pipeline = pipeline
75
+ else:
76
+ self._pipeline = None
72
77
 
73
- def run(self, steps: List[Union[Job, Deployment, MMT]]) -> None:
78
+ def run(self, steps: List[Union[Job, Deployment, MMT]], schedules: Optional[List["Schedule"]] = None) -> None:
74
79
  if len(steps) == 0:
75
80
  raise ValueError("The provided steps is empty")
76
81
 
@@ -83,12 +88,24 @@ class Pipeline:
83
88
  for step in steps
84
89
  ]
85
90
 
91
+ proto_steps = prepare_steps(steps)
92
+ schedules = schedules or []
93
+
94
+ parent_pipeline_id = None if self._pipeline is None else self._pipeline.id
95
+
86
96
  self._pipeline = self._pipeline_api.create_pipeline(
87
97
  self._name,
88
98
  self._teamspace.id,
89
- prepare_steps(steps),
99
+ proto_steps,
90
100
  self._shared_filesystem or False,
101
+ schedules,
102
+ parent_pipeline_id,
103
+ )
104
+
105
+ printer = PipelinePrinter(
106
+ self._name, parent_pipeline_id is None, self._pipeline, self._teamspace, proto_steps, schedules
91
107
  )
108
+ printer.print_summary()
92
109
 
93
110
  def stop(self) -> None:
94
111
  if self._pipeline is None:
@@ -103,7 +120,7 @@ class Pipeline:
103
120
  self._pipeline_api.delete(self._teamspace.id, self._pipeline.id)
104
121
 
105
122
  @property
106
- def name(self) -> str:
123
+ def name(self) -> Optional[str]:
107
124
  if self._pipeline:
108
125
  return self._pipeline.name
109
126
  return None
@@ -0,0 +1,102 @@
1
+ import os
2
+ from typing import Any, ClassVar, Dict, List
3
+
4
+ from lightning_sdk.lightning_cloud.openapi.models import V1JobSpec, V1PipelineStepType
5
+
6
+
7
+ class PipelinePrinter:
8
+ """A helper class to print a formatted summary of a pipeline."""
9
+
10
+ STEP_TYPE_MAP: ClassVar[Dict[str, str]] = {
11
+ V1PipelineStepType.DEPLOYMENT: "Deployment",
12
+ V1PipelineStepType.JOB: "Job",
13
+ V1PipelineStepType.MMT: "MMT",
14
+ }
15
+
16
+ def __init__(
17
+ self, name: str, initial: bool, pipeline: Any, teamspace: Any, proto_steps: List[Any], schedules: List[Any]
18
+ ) -> None:
19
+ self._name = name
20
+ self._initial = initial
21
+ self._pipeline = pipeline
22
+ self._teamspace = teamspace
23
+ self._proto_steps = proto_steps
24
+ self._schedules = schedules
25
+
26
+ def print_summary(self) -> None:
27
+ """Prints the full, formatted summary of the created pipeline."""
28
+ self._print("\n" + "─" * 60)
29
+ self._print(f"✅ Pipeline '{self._name}' {'created' if self._initial else 'updated'} successfully!")
30
+ self._print("─" * 60)
31
+
32
+ self._print_steps()
33
+ self._print_schedules()
34
+ self._print_cloud_account()
35
+ self._print_footer()
36
+
37
+ def _print(self, value: str) -> None:
38
+ print(value)
39
+
40
+ def _print_steps(self) -> None:
41
+ """Prints the formatted list of pipeline steps."""
42
+ self._print("\nWorkflow Steps:")
43
+ if not self._proto_steps:
44
+ self._print(" - No steps defined.")
45
+ return
46
+
47
+ for i, step in enumerate(self._proto_steps):
48
+ step_type = self.STEP_TYPE_MAP.get(step.type, "Unknown Step")
49
+
50
+ # Format the 'wait_for' list for cleaner output
51
+ if not step.wait_for:
52
+ wait_for_str = "(runs first)"
53
+ else:
54
+ # e.g., "'step_a', 'step_b'"
55
+ wait_for_str = f" waits for {', '.join([f'{w}' for w in step.wait_for])}"
56
+
57
+ self._print(f" ➡️ {i+1}. {step_type} '{step.name}' - {wait_for_str}")
58
+
59
+ def _print_schedules(self) -> None:
60
+ """Prints the formatted list of schedules."""
61
+ self._print("\n🗓️ Schedules:")
62
+ if not self._schedules:
63
+ self._print(" - No schedules defined.")
64
+ return
65
+
66
+ for schedule in self._schedules:
67
+ self._print(f" - '{schedule.name}' runs on cron schedule: `{schedule.cron_expression}`")
68
+
69
+ def _print_footer(self) -> None:
70
+ """Prints the final link and closing message."""
71
+ cloud_url = os.getenv("LIGHTNING_CLOUD_URL", "https://lightning.ai").replace(":443", "")
72
+
73
+ # Using properties of assumed objects for a cleaner look
74
+ owner: str = self._teamspace.owner.name
75
+ team: str = self._teamspace.name
76
+ pipeline_name: str = self._name
77
+
78
+ pipeline_url = f"{cloud_url}/{owner}/{team}/pipelines/{pipeline_name}?app_id=pipeline&section=Graph"
79
+
80
+ self._print("\n" + "─" * 60)
81
+ self._print(f"🔗 View your pipeline in the browser:\n {pipeline_url}")
82
+ self._print("─" * 60 + "\n")
83
+
84
+ def _print_cloud_account(self) -> None:
85
+ if not self._proto_steps:
86
+ return
87
+
88
+ cluster_ids: set[str] = set()
89
+ for step in self._proto_steps:
90
+ job_spec = self._get_spec(step)
91
+ cluster_ids.add(job_spec.cluster_id)
92
+
93
+ self._print(f"\nCloud account{'s' if len(cluster_ids) > 1 else ''}:")
94
+ for cluster_id in sorted(cluster_ids):
95
+ self._print(f" - {cluster_id}")
96
+
97
+ def _get_spec(self, step: Any) -> V1JobSpec:
98
+ if step.type == V1PipelineStepType.DEPLOYMENT:
99
+ return step.deployment.spec
100
+ if step.type == V1PipelineStepType.MMT:
101
+ return step.mmt.spec
102
+ return step.job.spec
@@ -0,0 +1,7 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass
5
+ class Schedule:
6
+ name: str
7
+ cron_expression: str
@@ -55,7 +55,7 @@ class Deployment:
55
55
  cloud_account: Optional[str] = None,
56
56
  custom_domain: Optional[str] = None,
57
57
  quantity: Optional[int] = None,
58
- wait_for: Union[str, List[str]] = DEFAULT,
58
+ wait_for: Optional[Union[str, List[str]]] = DEFAULT,
59
59
  ) -> None:
60
60
  self.name = name
61
61
  self.machine = machine
@@ -132,7 +132,7 @@ class Job:
132
132
  cloud_account_auth: bool = False,
133
133
  entrypoint: str = "sh -c",
134
134
  path_mappings: Optional[Dict[str, str]] = None,
135
- wait_for: Union[str, List[str]] = DEFAULT,
135
+ wait_for: Union[str, List[str], None] = DEFAULT,
136
136
  ) -> None:
137
137
  self.name = name
138
138
  self.machine = machine
@@ -207,7 +207,7 @@ class MMT:
207
207
  cloud_account_auth: bool = False,
208
208
  entrypoint: str = "sh -c",
209
209
  path_mappings: Optional[Dict[str, str]] = None,
210
- wait_for: Union[str, List[str]] = DEFAULT,
210
+ wait_for: Optional[Union[str, List[str]]] = DEFAULT,
211
211
  ) -> None:
212
212
  self.machine = machine
213
213
  self.num_machines = num_machines