lightning-sdk 2025.7.9__py3-none-any.whl → 2025.7.10__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/llm_api.py +4 -0
- lightning_sdk/job/base.py +21 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_user_features.py +27 -53
- lightning_sdk/lightning_cloud/utils/data_connection.py +57 -3
- lightning_sdk/llm/llm.py +29 -8
- {lightning_sdk-2025.7.9.dist-info → lightning_sdk-2025.7.10.dist-info}/METADATA +1 -1
- {lightning_sdk-2025.7.9.dist-info → lightning_sdk-2025.7.10.dist-info}/RECORD +12 -12
- {lightning_sdk-2025.7.9.dist-info → lightning_sdk-2025.7.10.dist-info}/LICENSE +0 -0
- {lightning_sdk-2025.7.9.dist-info → lightning_sdk-2025.7.10.dist-info}/WHEEL +0 -0
- {lightning_sdk-2025.7.9.dist-info → lightning_sdk-2025.7.10.dist-info}/entry_points.txt +0 -0
- {lightning_sdk-2025.7.9.dist-info → lightning_sdk-2025.7.10.dist-info}/top_level.txt +0 -0
lightning_sdk/__init__.py
CHANGED
lightning_sdk/api/llm_api.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import base64
|
|
3
|
+
import datetime
|
|
3
4
|
import json
|
|
4
5
|
import os
|
|
5
6
|
import threading
|
|
@@ -46,6 +47,8 @@ class LLMApi:
|
|
|
46
47
|
executable=result_data.get("executable"),
|
|
47
48
|
id=result_data.get("id"),
|
|
48
49
|
throughput=result_data.get("throughput"),
|
|
50
|
+
stats=result_data.get("stats"),
|
|
51
|
+
usage=result_data.get("usage"),
|
|
49
52
|
)
|
|
50
53
|
except json.JSONDecodeError:
|
|
51
54
|
warnings.warn("Error decoding JSON:", decoded_line)
|
|
@@ -158,6 +161,7 @@ class LLMApi:
|
|
|
158
161
|
"ephemeral": ephemeral,
|
|
159
162
|
"parent_conversation_id": kwargs.get("parent_conversation_id", ""),
|
|
160
163
|
"parent_message_id": kwargs.get("parent_message_id", ""),
|
|
164
|
+
"sent_at": datetime.datetime.now(datetime.timezone.utc).isoformat(timespec="microseconds"),
|
|
161
165
|
}
|
|
162
166
|
if images:
|
|
163
167
|
for image in images:
|
lightning_sdk/job/base.py
CHANGED
|
@@ -296,6 +296,27 @@ class _BaseJob(ABC):
|
|
|
296
296
|
|
|
297
297
|
time.sleep(interval)
|
|
298
298
|
|
|
299
|
+
async def async_wait(self, interval: float = 5.0, timeout: Optional[float] = None) -> None:
|
|
300
|
+
"""Waits for the job to be either completed, manually stopped or failed.
|
|
301
|
+
|
|
302
|
+
Args:
|
|
303
|
+
interval: The number of seconds to spend in-between status checks.
|
|
304
|
+
timeout: The maximum number of seconds to wait before raising an error. If None, waits forever.
|
|
305
|
+
"""
|
|
306
|
+
import asyncio
|
|
307
|
+
|
|
308
|
+
from lightning_sdk.status import Status
|
|
309
|
+
|
|
310
|
+
start = asyncio.get_event_loop().time()
|
|
311
|
+
while True:
|
|
312
|
+
if self.status in (Status.Completed, Status.Stopped, Status.Failed):
|
|
313
|
+
break
|
|
314
|
+
|
|
315
|
+
if timeout is not None and asyncio.get_event_loop().time() - start > timeout:
|
|
316
|
+
raise TimeoutError("Job didn't finish within the provided timeout.")
|
|
317
|
+
|
|
318
|
+
await asyncio.sleep(interval)
|
|
319
|
+
|
|
299
320
|
@property
|
|
300
321
|
@abstractmethod
|
|
301
322
|
def status(self) -> "Status":
|
|
@@ -42,7 +42,6 @@ class V1UserFeatures(object):
|
|
|
42
42
|
"""
|
|
43
43
|
swagger_types = {
|
|
44
44
|
'academic_tier': 'bool',
|
|
45
|
-
'accurate_billing': 'bool',
|
|
46
45
|
'add_data_v2': 'bool',
|
|
47
46
|
'affiliate_links': 'bool',
|
|
48
47
|
'agents_v2': 'bool',
|
|
@@ -59,7 +58,6 @@ class V1UserFeatures(object):
|
|
|
59
58
|
'cloudy_vibe_code': 'bool',
|
|
60
59
|
'code_tab': 'bool',
|
|
61
60
|
'collab_screen_sharing': 'bool',
|
|
62
|
-
'concurrent_gpu_limit': 'bool',
|
|
63
61
|
'control_center_monitoring': 'bool',
|
|
64
62
|
'cost_attribution_settings': 'bool',
|
|
65
63
|
'custom_app_domain': 'bool',
|
|
@@ -76,6 +74,7 @@ class V1UserFeatures(object):
|
|
|
76
74
|
'gcs_fuse': 'bool',
|
|
77
75
|
'instant_capacity_reservation': 'bool',
|
|
78
76
|
'job_artifacts_v2': 'bool',
|
|
77
|
+
'kubernetes_cluster_ui': 'bool',
|
|
79
78
|
'kubernetes_clusters': 'bool',
|
|
80
79
|
'lambda_labs': 'bool',
|
|
81
80
|
'lambda_labs_studios': 'bool',
|
|
@@ -136,7 +135,6 @@ class V1UserFeatures(object):
|
|
|
136
135
|
|
|
137
136
|
attribute_map = {
|
|
138
137
|
'academic_tier': 'academicTier',
|
|
139
|
-
'accurate_billing': 'accurateBilling',
|
|
140
138
|
'add_data_v2': 'addDataV2',
|
|
141
139
|
'affiliate_links': 'affiliateLinks',
|
|
142
140
|
'agents_v2': 'agentsV2',
|
|
@@ -153,7 +151,6 @@ class V1UserFeatures(object):
|
|
|
153
151
|
'cloudy_vibe_code': 'cloudyVibeCode',
|
|
154
152
|
'code_tab': 'codeTab',
|
|
155
153
|
'collab_screen_sharing': 'collabScreenSharing',
|
|
156
|
-
'concurrent_gpu_limit': 'concurrentGpuLimit',
|
|
157
154
|
'control_center_monitoring': 'controlCenterMonitoring',
|
|
158
155
|
'cost_attribution_settings': 'costAttributionSettings',
|
|
159
156
|
'custom_app_domain': 'customAppDomain',
|
|
@@ -170,6 +167,7 @@ class V1UserFeatures(object):
|
|
|
170
167
|
'gcs_fuse': 'gcsFuse',
|
|
171
168
|
'instant_capacity_reservation': 'instantCapacityReservation',
|
|
172
169
|
'job_artifacts_v2': 'jobArtifactsV2',
|
|
170
|
+
'kubernetes_cluster_ui': 'kubernetesClusterUi',
|
|
173
171
|
'kubernetes_clusters': 'kubernetesClusters',
|
|
174
172
|
'lambda_labs': 'lambdaLabs',
|
|
175
173
|
'lambda_labs_studios': 'lambdaLabsStudios',
|
|
@@ -228,10 +226,9 @@ class V1UserFeatures(object):
|
|
|
228
226
|
'writable_s3_connections': 'writableS3Connections'
|
|
229
227
|
}
|
|
230
228
|
|
|
231
|
-
def __init__(self, academic_tier: 'bool' =None,
|
|
229
|
+
def __init__(self, academic_tier: 'bool' =None, add_data_v2: '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, 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, cloudspace_schedules: 'bool' =None, cloudy_vibe_code: 'bool' =None, code_tab: 'bool' =None, collab_screen_sharing: 'bool' =None, control_center_monitoring: 'bool' =None, cost_attribution_settings: 'bool' =None, custom_app_domain: 'bool' =None, data_connection_flushing_v2: '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_connections_optimized: 'bool' =None, gcs_folders: 'bool' =None, gcs_fuse: 'bool' =None, instant_capacity_reservation: 'bool' =None, job_artifacts_v2: 'bool' =None, kubernetes_cluster_ui: 'bool' =None, kubernetes_clusters: 'bool' =None, lambda_labs: 'bool' =None, lambda_labs_studios: 'bool' =None, landing_studios: 'bool' =None, lit_logger: 'bool' =None, machine_selector_v2: 'bool' =None, marketplace: 'bool' =None, mmt_fault_tolerance: 'bool' =None, mmt_strategy_selector: 'bool' =None, model_api_dashboard: 'bool' =None, model_api_dashboard_clickhouse: '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, onboarding_v2: 'bool' =None, org_level_member_permissions: 'bool' =None, org_usage_limits: 'bool' =None, paygo_free_storage_limit_check: 'bool' =None, persistent_disk: '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, specialised_studios: 'bool' =None, storage_overuse_deletion: 'bool' =None, studio_config: 'bool' =None, studio_sharing_v2: 'bool' =None, studio_version_visibility: 'bool' =None, trainium2: 'bool' =None, use_internal_data_connection_mounts: 'bool' =None, use_rclone_mounts_only: 'bool' =None, voltage_park: 'bool' =None, voltage_park_studios: 'bool' =None, vultr: 'bool' =None, weka: 'bool' =None, writable_s3_connections: 'bool' =None): # noqa: E501
|
|
232
230
|
"""V1UserFeatures - a model defined in Swagger""" # noqa: E501
|
|
233
231
|
self._academic_tier = None
|
|
234
|
-
self._accurate_billing = None
|
|
235
232
|
self._add_data_v2 = None
|
|
236
233
|
self._affiliate_links = None
|
|
237
234
|
self._agents_v2 = None
|
|
@@ -248,7 +245,6 @@ class V1UserFeatures(object):
|
|
|
248
245
|
self._cloudy_vibe_code = None
|
|
249
246
|
self._code_tab = None
|
|
250
247
|
self._collab_screen_sharing = None
|
|
251
|
-
self._concurrent_gpu_limit = None
|
|
252
248
|
self._control_center_monitoring = None
|
|
253
249
|
self._cost_attribution_settings = None
|
|
254
250
|
self._custom_app_domain = None
|
|
@@ -265,6 +261,7 @@ class V1UserFeatures(object):
|
|
|
265
261
|
self._gcs_fuse = None
|
|
266
262
|
self._instant_capacity_reservation = None
|
|
267
263
|
self._job_artifacts_v2 = None
|
|
264
|
+
self._kubernetes_cluster_ui = None
|
|
268
265
|
self._kubernetes_clusters = None
|
|
269
266
|
self._lambda_labs = None
|
|
270
267
|
self._lambda_labs_studios = None
|
|
@@ -324,8 +321,6 @@ class V1UserFeatures(object):
|
|
|
324
321
|
self.discriminator = None
|
|
325
322
|
if academic_tier is not None:
|
|
326
323
|
self.academic_tier = academic_tier
|
|
327
|
-
if accurate_billing is not None:
|
|
328
|
-
self.accurate_billing = accurate_billing
|
|
329
324
|
if add_data_v2 is not None:
|
|
330
325
|
self.add_data_v2 = add_data_v2
|
|
331
326
|
if affiliate_links is not None:
|
|
@@ -358,8 +353,6 @@ class V1UserFeatures(object):
|
|
|
358
353
|
self.code_tab = code_tab
|
|
359
354
|
if collab_screen_sharing is not None:
|
|
360
355
|
self.collab_screen_sharing = collab_screen_sharing
|
|
361
|
-
if concurrent_gpu_limit is not None:
|
|
362
|
-
self.concurrent_gpu_limit = concurrent_gpu_limit
|
|
363
356
|
if control_center_monitoring is not None:
|
|
364
357
|
self.control_center_monitoring = control_center_monitoring
|
|
365
358
|
if cost_attribution_settings is not None:
|
|
@@ -392,6 +385,8 @@ class V1UserFeatures(object):
|
|
|
392
385
|
self.instant_capacity_reservation = instant_capacity_reservation
|
|
393
386
|
if job_artifacts_v2 is not None:
|
|
394
387
|
self.job_artifacts_v2 = job_artifacts_v2
|
|
388
|
+
if kubernetes_cluster_ui is not None:
|
|
389
|
+
self.kubernetes_cluster_ui = kubernetes_cluster_ui
|
|
395
390
|
if kubernetes_clusters is not None:
|
|
396
391
|
self.kubernetes_clusters = kubernetes_clusters
|
|
397
392
|
if lambda_labs is not None:
|
|
@@ -526,27 +521,6 @@ class V1UserFeatures(object):
|
|
|
526
521
|
|
|
527
522
|
self._academic_tier = academic_tier
|
|
528
523
|
|
|
529
|
-
@property
|
|
530
|
-
def accurate_billing(self) -> 'bool':
|
|
531
|
-
"""Gets the accurate_billing of this V1UserFeatures. # noqa: E501
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
:return: The accurate_billing of this V1UserFeatures. # noqa: E501
|
|
535
|
-
:rtype: bool
|
|
536
|
-
"""
|
|
537
|
-
return self._accurate_billing
|
|
538
|
-
|
|
539
|
-
@accurate_billing.setter
|
|
540
|
-
def accurate_billing(self, accurate_billing: 'bool'):
|
|
541
|
-
"""Sets the accurate_billing of this V1UserFeatures.
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
:param accurate_billing: The accurate_billing of this V1UserFeatures. # noqa: E501
|
|
545
|
-
:type: bool
|
|
546
|
-
"""
|
|
547
|
-
|
|
548
|
-
self._accurate_billing = accurate_billing
|
|
549
|
-
|
|
550
524
|
@property
|
|
551
525
|
def add_data_v2(self) -> 'bool':
|
|
552
526
|
"""Gets the add_data_v2 of this V1UserFeatures. # noqa: E501
|
|
@@ -883,27 +857,6 @@ class V1UserFeatures(object):
|
|
|
883
857
|
|
|
884
858
|
self._collab_screen_sharing = collab_screen_sharing
|
|
885
859
|
|
|
886
|
-
@property
|
|
887
|
-
def concurrent_gpu_limit(self) -> 'bool':
|
|
888
|
-
"""Gets the concurrent_gpu_limit of this V1UserFeatures. # noqa: E501
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
:return: The concurrent_gpu_limit of this V1UserFeatures. # noqa: E501
|
|
892
|
-
:rtype: bool
|
|
893
|
-
"""
|
|
894
|
-
return self._concurrent_gpu_limit
|
|
895
|
-
|
|
896
|
-
@concurrent_gpu_limit.setter
|
|
897
|
-
def concurrent_gpu_limit(self, concurrent_gpu_limit: 'bool'):
|
|
898
|
-
"""Sets the concurrent_gpu_limit of this V1UserFeatures.
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
:param concurrent_gpu_limit: The concurrent_gpu_limit of this V1UserFeatures. # noqa: E501
|
|
902
|
-
:type: bool
|
|
903
|
-
"""
|
|
904
|
-
|
|
905
|
-
self._concurrent_gpu_limit = concurrent_gpu_limit
|
|
906
|
-
|
|
907
860
|
@property
|
|
908
861
|
def control_center_monitoring(self) -> 'bool':
|
|
909
862
|
"""Gets the control_center_monitoring of this V1UserFeatures. # noqa: E501
|
|
@@ -1240,6 +1193,27 @@ class V1UserFeatures(object):
|
|
|
1240
1193
|
|
|
1241
1194
|
self._job_artifacts_v2 = job_artifacts_v2
|
|
1242
1195
|
|
|
1196
|
+
@property
|
|
1197
|
+
def kubernetes_cluster_ui(self) -> 'bool':
|
|
1198
|
+
"""Gets the kubernetes_cluster_ui of this V1UserFeatures. # noqa: E501
|
|
1199
|
+
|
|
1200
|
+
|
|
1201
|
+
:return: The kubernetes_cluster_ui of this V1UserFeatures. # noqa: E501
|
|
1202
|
+
:rtype: bool
|
|
1203
|
+
"""
|
|
1204
|
+
return self._kubernetes_cluster_ui
|
|
1205
|
+
|
|
1206
|
+
@kubernetes_cluster_ui.setter
|
|
1207
|
+
def kubernetes_cluster_ui(self, kubernetes_cluster_ui: 'bool'):
|
|
1208
|
+
"""Sets the kubernetes_cluster_ui of this V1UserFeatures.
|
|
1209
|
+
|
|
1210
|
+
|
|
1211
|
+
:param kubernetes_cluster_ui: The kubernetes_cluster_ui of this V1UserFeatures. # noqa: E501
|
|
1212
|
+
:type: bool
|
|
1213
|
+
"""
|
|
1214
|
+
|
|
1215
|
+
self._kubernetes_cluster_ui = kubernetes_cluster_ui
|
|
1216
|
+
|
|
1243
1217
|
@property
|
|
1244
1218
|
def kubernetes_clusters(self) -> 'bool':
|
|
1245
1219
|
"""Gets the kubernetes_clusters of this V1UserFeatures. # noqa: E501
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from time import sleep, time
|
|
3
3
|
from lightning_sdk.lightning_cloud import rest_client
|
|
4
|
-
from lightning_sdk.lightning_cloud.openapi import Create, V1AwsDataConnection, V1S3FolderDataConnection, V1EfsConfig
|
|
4
|
+
from lightning_sdk.lightning_cloud.openapi import Create, V1AwsDataConnection, V1S3FolderDataConnection, V1EfsConfig, V1GcpDataConnection
|
|
5
5
|
from lightning_sdk.lightning_cloud.openapi.rest import ApiException
|
|
6
6
|
import urllib3
|
|
7
|
-
import os
|
|
8
7
|
|
|
9
8
|
def add_s3_connection(bucket_name: str, region: str = "us-east-1", create_timeout: int = 15) -> None:
|
|
10
9
|
"""Utility to add a data connection."""
|
|
@@ -217,6 +216,62 @@ def add_efs_connection(name: str, filesystem_id: str, region: str = "us-east-1",
|
|
|
217
216
|
|
|
218
217
|
return
|
|
219
218
|
|
|
219
|
+
def add_gcs_connection(connection_name: str, bucket_name: str, create_timeout: int = 15) -> None:
|
|
220
|
+
"""
|
|
221
|
+
Utility function to add a GCS data connection.
|
|
222
|
+
|
|
223
|
+
Parameters:
|
|
224
|
+
1. connection_name (str): The name of the data connection.
|
|
225
|
+
2. bucket_name (str): The name of the bucket to attach.
|
|
226
|
+
3. create_timeout (int): The timeout for the data connectio creation.
|
|
227
|
+
Returns:
|
|
228
|
+
None
|
|
229
|
+
"""
|
|
230
|
+
|
|
231
|
+
client = rest_client.LightningClient(retry=False)
|
|
232
|
+
|
|
233
|
+
project_id = os.getenv("LIGHTNING_CLOUD_PROJECT_ID")
|
|
234
|
+
cluster_id = os.getenv("LIGHTNING_CLUSTER_ID")
|
|
235
|
+
|
|
236
|
+
# Get existing data connections and ensure there is no an existing one with the same name and type
|
|
237
|
+
data_connections = client.data_connection_service_list_data_connections(project_id).data_connections
|
|
238
|
+
|
|
239
|
+
for connection in data_connections:
|
|
240
|
+
existing_connection_name = getattr(connection, 'name', None)
|
|
241
|
+
isGCSConnection = getattr(connection, 'gcp', None) is not None
|
|
242
|
+
|
|
243
|
+
# Same name and type already exists
|
|
244
|
+
if existing_connection_name == connection_name and isGCSConnection:
|
|
245
|
+
return
|
|
246
|
+
|
|
247
|
+
body = Create(
|
|
248
|
+
name=connection_name,
|
|
249
|
+
create_index=True,
|
|
250
|
+
cluster_id=cluster_id,
|
|
251
|
+
access_cluster_ids=[cluster_id],
|
|
252
|
+
gcp=V1GcpDataConnection(
|
|
253
|
+
source=f"gs://{bucket_name}",
|
|
254
|
+
))
|
|
255
|
+
try:
|
|
256
|
+
client.data_connection_service_create_data_connection(body, project_id)
|
|
257
|
+
except (ApiException, urllib3.exceptions.HTTPError) as ex:
|
|
258
|
+
# Note: This function can be called in a distributed way.
|
|
259
|
+
# There is a race condition where one machine might create the entry before another machine
|
|
260
|
+
# and this request would fail with duplicated key
|
|
261
|
+
# In this case, it is fine not to raise
|
|
262
|
+
if isinstance(ex, ApiException) and 'duplicate key value violates unique constraint' in str(ex.body):
|
|
263
|
+
pass
|
|
264
|
+
else:
|
|
265
|
+
raise ex
|
|
266
|
+
|
|
267
|
+
# Wait for the filesystem picks up the newly added GCS data connection
|
|
268
|
+
start = time()
|
|
269
|
+
|
|
270
|
+
while not os.path.isdir(f"/teamspace/gcs_connections/{bucket_name}") and (time() - start) < create_timeout:
|
|
271
|
+
sleep(1)
|
|
272
|
+
|
|
273
|
+
return
|
|
274
|
+
|
|
220
275
|
def delete_data_connection(name: str):
|
|
221
276
|
"""Utility to delete a data connection
|
|
222
277
|
|
|
@@ -249,4 +304,3 @@ def delete_data_connection(name: str):
|
|
|
249
304
|
# for now it's best to actually stop the studio and all other things where the connection
|
|
250
305
|
# is mounted before trying to delete it
|
|
251
306
|
raise e from None
|
|
252
|
-
|
lightning_sdk/llm/llm.py
CHANGED
|
@@ -169,21 +169,33 @@ class LLM:
|
|
|
169
169
|
self._conversations[conversation.name] = conversation.id
|
|
170
170
|
|
|
171
171
|
def _stream_chat_response(
|
|
172
|
-
self,
|
|
172
|
+
self,
|
|
173
|
+
result: Generator[V1ConversationResponseChunk, None, None],
|
|
174
|
+
conversation: Optional[str] = None,
|
|
175
|
+
full_response: bool = False,
|
|
173
176
|
) -> Generator[str, None, None]:
|
|
174
177
|
first_line = next(result, None)
|
|
175
178
|
if first_line:
|
|
176
179
|
if conversation and first_line.conversation_id:
|
|
177
180
|
self._conversations[conversation] = first_line.conversation_id
|
|
178
|
-
|
|
181
|
+
if full_response:
|
|
182
|
+
yield first_line
|
|
183
|
+
else:
|
|
184
|
+
yield first_line.choices[0].delta.content
|
|
179
185
|
|
|
180
186
|
for line in result:
|
|
181
|
-
|
|
187
|
+
if full_response:
|
|
188
|
+
yield line
|
|
189
|
+
else:
|
|
190
|
+
yield line.choices[0].delta.content
|
|
182
191
|
|
|
183
|
-
async def _async_stream_text(self, output: str) -> AsyncGenerator[str, None]:
|
|
192
|
+
async def _async_stream_text(self, output: str, full_response: bool = False) -> AsyncGenerator[str, None]:
|
|
184
193
|
async for chunk in output:
|
|
185
194
|
if chunk.choices and chunk.choices[0].delta:
|
|
186
|
-
|
|
195
|
+
if full_response:
|
|
196
|
+
yield chunk
|
|
197
|
+
else:
|
|
198
|
+
yield chunk.choices[0].delta.content
|
|
187
199
|
|
|
188
200
|
async def _async_chat(
|
|
189
201
|
self,
|
|
@@ -194,6 +206,7 @@ class LLM:
|
|
|
194
206
|
conversation: Optional[str] = None,
|
|
195
207
|
metadata: Optional[Dict[str, str]] = None,
|
|
196
208
|
stream: bool = False,
|
|
209
|
+
full_response: bool = False,
|
|
197
210
|
**kwargs: Any,
|
|
198
211
|
) -> Union[str, AsyncGenerator[str, None]]:
|
|
199
212
|
conversation_id = self._conversations.get(conversation) if conversation else None
|
|
@@ -213,8 +226,10 @@ class LLM:
|
|
|
213
226
|
if not stream:
|
|
214
227
|
if conversation and not conversation_id:
|
|
215
228
|
self._conversations[conversation] = output.conversation_id
|
|
229
|
+
if full_response:
|
|
230
|
+
return output
|
|
216
231
|
return output.choices[0].delta.content
|
|
217
|
-
return self._async_stream_text(output)
|
|
232
|
+
return self._async_stream_text(output, full_response)
|
|
218
233
|
|
|
219
234
|
def chat(
|
|
220
235
|
self,
|
|
@@ -225,8 +240,11 @@ class LLM:
|
|
|
225
240
|
conversation: Optional[str] = None,
|
|
226
241
|
metadata: Optional[Dict[str, str]] = None,
|
|
227
242
|
stream: bool = False,
|
|
243
|
+
full_response: bool = False,
|
|
228
244
|
**kwargs: Any,
|
|
229
|
-
) -> Union[
|
|
245
|
+
) -> Union[
|
|
246
|
+
V1ConversationResponseChunk, Generator[V1ConversationResponseChunk, None, None], str, Generator[str, None, None]
|
|
247
|
+
]:
|
|
230
248
|
if conversation and conversation not in self._conversations:
|
|
231
249
|
self._get_conversations()
|
|
232
250
|
|
|
@@ -248,6 +266,7 @@ class LLM:
|
|
|
248
266
|
conversation,
|
|
249
267
|
metadata,
|
|
250
268
|
stream,
|
|
269
|
+
full_response,
|
|
251
270
|
**kwargs,
|
|
252
271
|
)
|
|
253
272
|
|
|
@@ -267,8 +286,10 @@ class LLM:
|
|
|
267
286
|
if not stream:
|
|
268
287
|
if conversation and not conversation_id:
|
|
269
288
|
self._conversations[conversation] = output.conversation_id
|
|
289
|
+
if full_response:
|
|
290
|
+
return output
|
|
270
291
|
return output.choices[0].delta.content
|
|
271
|
-
return self._stream_chat_response(output, conversation=conversation)
|
|
292
|
+
return self._stream_chat_response(output, conversation=conversation, full_response=full_response)
|
|
272
293
|
|
|
273
294
|
def list_conversations(self) -> List[Dict]:
|
|
274
295
|
self._get_conversations()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
docs/source/conf.py,sha256=r8yX20eC-4mHhMTd0SbQb5TlSWHhO6wnJ0VJ_FBFpag,13249
|
|
2
|
-
lightning_sdk/__init__.py,sha256=
|
|
2
|
+
lightning_sdk/__init__.py,sha256=fG3HKc1WBcAYah6nhvTOh7OxcQrKdc47OVufxrxpbbE,1109
|
|
3
3
|
lightning_sdk/agents.py,sha256=ly6Ma1j0ZgGPFyvPvMN28JWiB9dATIstFa5XM8pMi6I,1577
|
|
4
4
|
lightning_sdk/ai_hub.py,sha256=iI1vNhgcz_Ff1c3rN1ogN7dK-r-HXRj6NMtS2cA14UA,6925
|
|
5
5
|
lightning_sdk/base_studio.py,sha256=_Pwwl37R9GRd7t-f2kO5aQXiLNrP4sUtUNht2ZkP8LE,3678
|
|
@@ -26,7 +26,7 @@ lightning_sdk/api/deployment_api.py,sha256=KvBwGaG896q7WS1OPMOIjFUh05W2g7S1djS2X
|
|
|
26
26
|
lightning_sdk/api/job_api.py,sha256=_mMAI_BG_48i-BLwCP_U72zgmM5zYa2KUZ7u66HWkIc,13568
|
|
27
27
|
lightning_sdk/api/license_api.py,sha256=XV3RhefyPQDYjwY9AaBZe4rByZTEAnsvLDxcdm9q0Wo,2438
|
|
28
28
|
lightning_sdk/api/lit_container_api.py,sha256=jCJVwd-3MNjejL9FyvH89pzt-SeG3G8qCJD16iTMJAQ,11454
|
|
29
|
-
lightning_sdk/api/llm_api.py,sha256=
|
|
29
|
+
lightning_sdk/api/llm_api.py,sha256=ngumhZrGk_XRjgN-JXHN2ksXJMwEXfadcg9p6re4Efk,9316
|
|
30
30
|
lightning_sdk/api/mmt_api.py,sha256=-v7ATab-ThAM-HRClS92Ehxuu9MlBfdKWWFCGvVUHiM,8962
|
|
31
31
|
lightning_sdk/api/org_api.py,sha256=Ze3z_ATVrukobujV5YdC42DKj45Vuwl7X52q_Vr-o3U,803
|
|
32
32
|
lightning_sdk/api/pipeline_api.py,sha256=oS0WIBB748SLD7bqkEQ8rnkixrsAML_M01OUunmLFSQ,4470
|
|
@@ -67,7 +67,7 @@ lightning_sdk/cli/deploy/serve.py,sha256=qqml7oYf4IPcoiL13P2ly247_PQ8IGv-8hM2NBW
|
|
|
67
67
|
lightning_sdk/deployment/__init__.py,sha256=dXsa4psDzFYFklsq3JC-2V_L4FQjGZnQAf-ZiVlqG9c,545
|
|
68
68
|
lightning_sdk/deployment/deployment.py,sha256=kD3P3uonV7Vr33BVnyD-HkxdUuQs0F2nt0GYoWb3Wx4,21057
|
|
69
69
|
lightning_sdk/job/__init__.py,sha256=1MxjQ6rHkyUHCypSW9RuXuVMVH11WiqhIXcU2LCFMwE,64
|
|
70
|
-
lightning_sdk/job/base.py,sha256=
|
|
70
|
+
lightning_sdk/job/base.py,sha256=u6d_Q56zzM_nzKGPvjVqR2MKEYzFawEGoaSsD747ZHQ,18603
|
|
71
71
|
lightning_sdk/job/job.py,sha256=1Xf0ne4wwXpkb_GJgWD8mfueJZoKR8G4lC5T6OXijlw,13075
|
|
72
72
|
lightning_sdk/job/v1.py,sha256=zgdZFnlyhzOBlbwdwx6Ob9YKBrzMnJflzLXy4qyb4So,9070
|
|
73
73
|
lightning_sdk/job/v2.py,sha256=9O31CwIQjwm6qZSEZtFBWbZyBuCSmyFMsHCRbQvJdBU,10283
|
|
@@ -1027,7 +1027,7 @@ lightning_sdk/lightning_cloud/openapi/models/v1_upstream_open_ai.py,sha256=jt1qQ
|
|
|
1027
1027
|
lightning_sdk/lightning_cloud/openapi/models/v1_usage.py,sha256=ozMzoGD9mfZGYy4J5j50Dps19Y6o8cn-aYW_oRMZMy8,16865
|
|
1028
1028
|
lightning_sdk/lightning_cloud/openapi/models/v1_usage_details.py,sha256=U7qC698Xj5tb3D93ZskG6sDf3lTXE13UTlGeDTvtRU4,14062
|
|
1029
1029
|
lightning_sdk/lightning_cloud/openapi/models/v1_usage_report.py,sha256=k9pDp9UIaOEEWz6bTNWF_KMfcNCOp-F67N-IZ9MO2Rs,8304
|
|
1030
|
-
lightning_sdk/lightning_cloud/openapi/models/v1_user_features.py,sha256=
|
|
1030
|
+
lightning_sdk/lightning_cloud/openapi/models/v1_user_features.py,sha256=Bm5XX7YRf4skZnQVnKSMfaHGGnErXYcXNwhgFMAlMDg,81783
|
|
1031
1031
|
lightning_sdk/lightning_cloud/openapi/models/v1_user_requested_compute_config.py,sha256=0fnZpdhxNRXGNyILHtfm3rVztfHpSF4kXGc5kTt4zls,13960
|
|
1032
1032
|
lightning_sdk/lightning_cloud/openapi/models/v1_user_requested_flow_compute_config.py,sha256=3WpZ-lf7xPwuYyQDMdP7Uc6-dh3vf5TaaUlcMfesfMk,5208
|
|
1033
1033
|
lightning_sdk/lightning_cloud/openapi/models/v1_user_slurm_job_action_response.py,sha256=BdNzXH8Vsf5PHjl9Rd-TVkpAgx1YC9rf8LD0js-ba20,3058
|
|
@@ -1065,12 +1065,12 @@ lightning_sdk/lightning_cloud/source_code/logs_socket_api.py,sha256=fXuRQfnRLNkY
|
|
|
1065
1065
|
lightning_sdk/lightning_cloud/source_code/tar.py,sha256=mSKRWEX1SIAbXFcESNrQAqWSVULv4G0jgcvR_o2KJ5g,5813
|
|
1066
1066
|
lightning_sdk/lightning_cloud/source_code/uploader.py,sha256=CQrWV6JNDiglyRfhc42ht4GWFtgRz_fBxw4tOCERzco,3207
|
|
1067
1067
|
lightning_sdk/lightning_cloud/utils/__init__.py,sha256=kSNKoybELDJHs9WeCf279V5JtzOf1VqfKODlKYr9uRo,115
|
|
1068
|
-
lightning_sdk/lightning_cloud/utils/data_connection.py,sha256=
|
|
1068
|
+
lightning_sdk/lightning_cloud/utils/data_connection.py,sha256=WeC7HWpQL2HxSEuX-7iB0mjoQN_YNr5dgfSkPtCGlds,11448
|
|
1069
1069
|
lightning_sdk/lightning_cloud/utils/dataset.py,sha256=4nUspe8iAaRPgSYpXA2uAQCgydm78kJzhOIx3C9qKls,2011
|
|
1070
1070
|
lightning_sdk/lightning_cloud/utils/name_generator.py,sha256=MkciuA10332V0mcE2PxLIiwWomWE0Fm_gNGK01vwRr4,58046
|
|
1071
1071
|
lightning_sdk/lightning_cloud/utils/network.py,sha256=axPgl8rhyPcPjxiztDxyksfxax3VNg2OXL5F5Uc81b4,406
|
|
1072
1072
|
lightning_sdk/llm/__init__.py,sha256=ErZva0HqN2iPtK_6hI6GN7A_HPGNrHo3wYh7vyFdO3Q,57
|
|
1073
|
-
lightning_sdk/llm/llm.py,sha256=
|
|
1073
|
+
lightning_sdk/llm/llm.py,sha256=M43OQli7cRqTtHUB484-OOdWs-jiwJv8j1LV-jFUolY,13038
|
|
1074
1074
|
lightning_sdk/llm/public_assistants.json,sha256=PFbA1p2J6XFRafuW0zfaz8tu_Ac4iI2hNeh94_PNoUQ,374
|
|
1075
1075
|
lightning_sdk/mmt/__init__.py,sha256=ExMu90-96bGBnyp5h0CErQszUGB1-PcjC4-R8_NYbeY,117
|
|
1076
1076
|
lightning_sdk/mmt/base.py,sha256=B3HC-c82bPHprEZh1mhLCPCrCE8BOKqwIhY7xCF9CXg,15152
|
|
@@ -1092,9 +1092,9 @@ lightning_sdk/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
|
|
|
1092
1092
|
lightning_sdk/utils/dynamic.py,sha256=glUTO1JC9APtQ6Gr9SO02a3zr56-sPAXM5C3NrTpgyQ,1959
|
|
1093
1093
|
lightning_sdk/utils/enum.py,sha256=h2JRzqoBcSlUdanFHmkj_j5DleBHAu1esQYUsdNI-hU,4106
|
|
1094
1094
|
lightning_sdk/utils/resolve.py,sha256=6qlBUkOmcFTjhQx_CAGfnvWBbMYp6XrCV_sX_IqplLE,6748
|
|
1095
|
-
lightning_sdk-2025.7.
|
|
1096
|
-
lightning_sdk-2025.7.
|
|
1097
|
-
lightning_sdk-2025.7.
|
|
1098
|
-
lightning_sdk-2025.7.
|
|
1099
|
-
lightning_sdk-2025.7.
|
|
1100
|
-
lightning_sdk-2025.7.
|
|
1095
|
+
lightning_sdk-2025.7.10.dist-info/LICENSE,sha256=uFIuZwj5z-4TeF2UuacPZ1o17HkvKObT8fY50qN84sg,1064
|
|
1096
|
+
lightning_sdk-2025.7.10.dist-info/METADATA,sha256=TH70L4MhS7ZbK7lPcmMB6QftgtEp4tGo5wUlOuwAS78,3995
|
|
1097
|
+
lightning_sdk-2025.7.10.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
|
|
1098
|
+
lightning_sdk-2025.7.10.dist-info/entry_points.txt,sha256=msB9PJWIJ784dX-OP8by51d4IbKYH3Fj1vCuA9oXjHY,68
|
|
1099
|
+
lightning_sdk-2025.7.10.dist-info/top_level.txt,sha256=ps8doKILFXmN7F1mHncShmnQoTxKBRPIcchC8TpoBw4,19
|
|
1100
|
+
lightning_sdk-2025.7.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|