lightning-sdk 0.2.7__py3-none-any.whl → 0.2.8__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/lit_container_api.py +3 -10
- lightning_sdk/cli/serve.py +40 -17
- lightning_sdk/serve.py +23 -26
- {lightning_sdk-0.2.7.dist-info → lightning_sdk-0.2.8.dist-info}/METADATA +1 -1
- {lightning_sdk-0.2.7.dist-info → lightning_sdk-0.2.8.dist-info}/RECORD +10 -10
- {lightning_sdk-0.2.7.dist-info → lightning_sdk-0.2.8.dist-info}/LICENSE +0 -0
- {lightning_sdk-0.2.7.dist-info → lightning_sdk-0.2.8.dist-info}/WHEEL +0 -0
- {lightning_sdk-0.2.7.dist-info → lightning_sdk-0.2.8.dist-info}/entry_points.txt +0 -0
- {lightning_sdk-0.2.7.dist-info → lightning_sdk-0.2.8.dist-info}/top_level.txt +0 -0
lightning_sdk/__init__.py
CHANGED
|
@@ -7,7 +7,6 @@ import requests
|
|
|
7
7
|
from rich.console import Console
|
|
8
8
|
|
|
9
9
|
from lightning_sdk.api.utils import _get_registry_url
|
|
10
|
-
from lightning_sdk.lightning_cloud.env import LIGHTNING_CLOUD_URL
|
|
11
10
|
from lightning_sdk.lightning_cloud.openapi.models import V1DeleteLitRepositoryResponse
|
|
12
11
|
from lightning_sdk.lightning_cloud.rest_client import LightningClient
|
|
13
12
|
from lightning_sdk.teamspace import Teamspace
|
|
@@ -103,10 +102,11 @@ class LitContainerApi:
|
|
|
103
102
|
"""Lists containers of the project ID.
|
|
104
103
|
|
|
105
104
|
:param project_id: The non-human readable project ID used internally to identify projects.
|
|
105
|
+
:param cloud_account: The cluster ID of the cloud account. If None, will use the default cluster.
|
|
106
106
|
:return:
|
|
107
107
|
"""
|
|
108
108
|
project = self._client.lit_registry_service_get_lit_project_registry(
|
|
109
|
-
project_id, cluster_id=cloud_account
|
|
109
|
+
project_id, cluster_id="" if cloud_account is None else cloud_account
|
|
110
110
|
) # cloud account on the CLI is cluster_id
|
|
111
111
|
return project.repositories
|
|
112
112
|
|
|
@@ -138,7 +138,7 @@ class LitContainerApi:
|
|
|
138
138
|
Named cloud-account in the CLI options.
|
|
139
139
|
:param platform: If empty will be linux/amd64. This is important because our entire deployment infra runs on
|
|
140
140
|
linux/amd64. Will show user a warning otherwise.
|
|
141
|
-
:return: Generator[dict, None,
|
|
141
|
+
:return: Generator[dict, None, dict]
|
|
142
142
|
"""
|
|
143
143
|
try:
|
|
144
144
|
self._docker_client.images.get(f"{container}:{tag}")
|
|
@@ -164,13 +164,6 @@ class LitContainerApi:
|
|
|
164
164
|
raise ValueError(f"Could not tag container {container}:{tag} with {repository}:{tag}")
|
|
165
165
|
yield from self._push_with_retry(repository, tag=tag)
|
|
166
166
|
|
|
167
|
-
yield {
|
|
168
|
-
"finish": True,
|
|
169
|
-
"url": f"{LIGHTNING_CLOUD_URL}/{teamspace.owner.name}/{teamspace.name}/containers/{container_basename}"
|
|
170
|
-
f"{f'?clusterId={cloud_account}' if cloud_account is not None else ''}",
|
|
171
|
-
"repository": repository,
|
|
172
|
-
}
|
|
173
|
-
|
|
174
167
|
def _push_with_retry(self, repository: str, tag: str, max_retries: int = 3) -> Iterator[Dict[str, Any]]:
|
|
175
168
|
def is_auth_error(error_msg: str) -> bool:
|
|
176
169
|
auth_errors = ["unauthorized", "authentication required", "unauth"]
|
lightning_sdk/cli/serve.py
CHANGED
|
@@ -17,17 +17,26 @@ from lightning_sdk.serve import _LitServeDeployer, authenticate
|
|
|
17
17
|
_MACHINE_VALUES = tuple([machine.name for machine in Machine.__dict__.values() if isinstance(machine, Machine)])
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
class _ServeGroup(click.Group):
|
|
21
|
+
def parse_args(self, ctx: click.Context, args: list) -> click.Group:
|
|
22
|
+
# Check if first arg is a file path and not a command name
|
|
23
|
+
if args and os.path.exists(args[0]) and args[0] not in self.commands:
|
|
24
|
+
# Insert the 'api' command before the file path
|
|
25
|
+
args.insert(0, "api")
|
|
26
|
+
return super().parse_args(ctx, args)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@click.group("serve", cls=_ServeGroup)
|
|
21
30
|
def serve() -> None:
|
|
22
31
|
"""Serve a LitServe model.
|
|
23
32
|
|
|
24
33
|
Example:
|
|
25
|
-
lightning serve
|
|
34
|
+
lightning serve server.py # serve locally
|
|
26
35
|
|
|
27
36
|
Example:
|
|
28
|
-
lightning serve
|
|
37
|
+
lightning serve server.py --cloud # deploy to the cloud
|
|
29
38
|
|
|
30
|
-
You can deploy the API to the cloud by running `lightning serve
|
|
39
|
+
You can deploy the API to the cloud by running `lightning serve server.py --cloud`.
|
|
31
40
|
This will build a docker container for the server.py script and deploy it to the Lightning AI platform.
|
|
32
41
|
"""
|
|
33
42
|
|
|
@@ -42,11 +51,11 @@ def serve() -> None:
|
|
|
42
51
|
help="Generate a client for the model",
|
|
43
52
|
)
|
|
44
53
|
@click.option(
|
|
45
|
-
"--
|
|
54
|
+
"--local",
|
|
46
55
|
is_flag=True,
|
|
47
56
|
default=False,
|
|
48
57
|
flag_value=True,
|
|
49
|
-
help="
|
|
58
|
+
help="Run the model locally",
|
|
50
59
|
)
|
|
51
60
|
@click.option("--name", default=None, help="Name of the deployed API (e.g., 'classification-api', 'Llama-api')")
|
|
52
61
|
@click.option(
|
|
@@ -107,7 +116,7 @@ def serve() -> None:
|
|
|
107
116
|
def api(
|
|
108
117
|
script_path: str,
|
|
109
118
|
easy: bool,
|
|
110
|
-
|
|
119
|
+
local: bool,
|
|
111
120
|
name: Optional[str],
|
|
112
121
|
non_interactive: bool,
|
|
113
122
|
machine: str,
|
|
@@ -126,7 +135,7 @@ def api(
|
|
|
126
135
|
return api_impl(
|
|
127
136
|
script_path=script_path,
|
|
128
137
|
easy=easy,
|
|
129
|
-
|
|
138
|
+
local=local,
|
|
130
139
|
repository=name,
|
|
131
140
|
non_interactive=non_interactive,
|
|
132
141
|
machine=machine,
|
|
@@ -146,7 +155,7 @@ def api(
|
|
|
146
155
|
def api_impl(
|
|
147
156
|
script_path: Union[str, Path],
|
|
148
157
|
easy: bool = False,
|
|
149
|
-
|
|
158
|
+
local: bool = False,
|
|
150
159
|
repository: [str] = None,
|
|
151
160
|
tag: Optional[str] = None,
|
|
152
161
|
non_interactive: bool = False,
|
|
@@ -176,7 +185,7 @@ def api_impl(
|
|
|
176
185
|
timestr = datetime.now().strftime("%b-%d-%H_%M")
|
|
177
186
|
repository = f"litserve-{timestr}".lower()
|
|
178
187
|
|
|
179
|
-
if
|
|
188
|
+
if not local:
|
|
180
189
|
repository = repository or "litserve-model"
|
|
181
190
|
machine = Machine.from_str(machine)
|
|
182
191
|
return _handle_cloud(
|
|
@@ -263,17 +272,31 @@ def _handle_cloud(
|
|
|
263
272
|
transient=True,
|
|
264
273
|
) as progress:
|
|
265
274
|
try:
|
|
266
|
-
#
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
275
|
+
# Build the container
|
|
276
|
+
build_task = progress.add_task("Building Docker image", total=None)
|
|
277
|
+
for line in ls_deployer.build_container(path, repository, tag):
|
|
278
|
+
console.print(line.strip())
|
|
279
|
+
progress.update(build_task, advance=1)
|
|
280
|
+
progress.update(build_task, description="[green]Build completed![/green]", completed=1.0)
|
|
281
|
+
progress.remove_task(build_task)
|
|
282
|
+
|
|
283
|
+
# Push the container to the registry
|
|
284
|
+
console.print("\nPushing image to registry. It may take a while...", style="bold")
|
|
285
|
+
push_task = progress.add_task("Pushing to registry", total=None)
|
|
286
|
+
push_status = {}
|
|
287
|
+
for line in ls_deployer.push_container(
|
|
288
|
+
repository, tag, resolved_teamspace, lit_cr, cloud_account=cloud_account
|
|
289
|
+
):
|
|
290
|
+
push_status = line
|
|
291
|
+
progress.update(push_task, advance=1)
|
|
292
|
+
if not ("Pushing" in line["status"] or "Waiting" in line["status"]):
|
|
293
|
+
console.print(line["status"])
|
|
294
|
+
progress.update(push_task, description="[green]Push completed![/green]")
|
|
271
295
|
except Exception as e:
|
|
272
296
|
console.print(f"❌ Deployment failed: {e}", style="red")
|
|
273
297
|
return
|
|
274
298
|
console.print(f"\n✅ Image pushed to {repository}:{tag}")
|
|
275
|
-
|
|
276
|
-
image = push_status.get("repository")
|
|
299
|
+
image = push_status.get("image")
|
|
277
300
|
|
|
278
301
|
deployment_status = ls_deployer.run_on_cloud(
|
|
279
302
|
deployment_name=deployment_name,
|
lightning_sdk/serve.py
CHANGED
|
@@ -7,13 +7,13 @@ from urllib.parse import urlencode
|
|
|
7
7
|
|
|
8
8
|
import docker
|
|
9
9
|
from rich.console import Console
|
|
10
|
-
from rich.progress import Progress
|
|
11
10
|
|
|
12
11
|
from lightning_sdk import Deployment, Machine, Teamspace
|
|
13
12
|
from lightning_sdk.api.deployment_api import AutoScaleConfig, DeploymentApi, Env, Secret
|
|
14
13
|
from lightning_sdk.api.lit_container_api import LitContainerApi
|
|
15
|
-
from lightning_sdk.api.utils import _get_cloud_url
|
|
14
|
+
from lightning_sdk.api.utils import _get_cloud_url, _get_registry_url
|
|
16
15
|
from lightning_sdk.lightning_cloud import env
|
|
16
|
+
from lightning_sdk.lightning_cloud.env import LIGHTNING_CLOUD_URL
|
|
17
17
|
from lightning_sdk.lightning_cloud.login import Auth, AuthServer
|
|
18
18
|
|
|
19
19
|
_DOCKER_NOT_RUNNING_MSG = (
|
|
@@ -182,22 +182,14 @@ Update [underline]{os.path.abspath("Dockerfile")}[/underline] to add any additio
|
|
|
182
182
|
|
|
183
183
|
return log_generator()
|
|
184
184
|
|
|
185
|
-
def build_container(self, path: str, repository: str, tag: str
|
|
186
|
-
build_task = progress.add_task("Building Docker image", total=None)
|
|
185
|
+
def build_container(self, path: str, repository: str, tag: str) -> Generator[str, None, None]:
|
|
187
186
|
build_logs = self._docker_build_with_logs(path, repository, tag=tag)
|
|
188
187
|
|
|
189
188
|
for line in build_logs:
|
|
190
189
|
if "error" in line:
|
|
191
|
-
progress.stop()
|
|
192
|
-
console.print(f"\n[red]{line}[/red]")
|
|
193
190
|
raise RuntimeError(f"Failed to build image: {line}")
|
|
194
191
|
else:
|
|
195
|
-
|
|
196
|
-
line.strip(),
|
|
197
|
-
)
|
|
198
|
-
progress.update(build_task, description="Building Docker image")
|
|
199
|
-
|
|
200
|
-
progress.update(build_task, description="[green]Build completed![/green]")
|
|
192
|
+
yield line.strip()
|
|
201
193
|
|
|
202
194
|
def push_container(
|
|
203
195
|
self,
|
|
@@ -205,26 +197,31 @@ Update [underline]{os.path.abspath("Dockerfile")}[/underline] to add any additio
|
|
|
205
197
|
tag: str,
|
|
206
198
|
teamspace: Teamspace,
|
|
207
199
|
lit_cr: LitContainerApi,
|
|
208
|
-
progress: Progress,
|
|
209
200
|
cloud_account: str,
|
|
210
|
-
) -> dict:
|
|
211
|
-
console = self._console
|
|
212
|
-
push_task = progress.add_task("Pushing to registry", total=None)
|
|
213
|
-
console.print("\nPushing image...", style="bold blue")
|
|
201
|
+
) -> Generator[dict, None, dict]:
|
|
214
202
|
lit_cr.authenticate()
|
|
215
|
-
push_status = lit_cr.upload_container(
|
|
216
|
-
|
|
203
|
+
push_status = lit_cr.upload_container(
|
|
204
|
+
repository, teamspace, tag=tag, cloud_account=cloud_account, platform=None
|
|
205
|
+
)
|
|
217
206
|
for line in push_status:
|
|
218
|
-
last_status = line
|
|
219
207
|
if "error" in line:
|
|
220
|
-
progress.stop()
|
|
221
|
-
console.print(f"\n[red]{line}[/red]")
|
|
222
208
|
raise RuntimeError(f"Failed to push image: {line}")
|
|
223
209
|
if "status" in line:
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
210
|
+
yield {"status": line["status"].strip()}
|
|
211
|
+
|
|
212
|
+
registry_url = _get_registry_url()
|
|
213
|
+
container_basename = repository.split("/")[-1]
|
|
214
|
+
repository = (
|
|
215
|
+
f"{registry_url}/lit-container{f'-{cloud_account}' if cloud_account is not None else ''}/"
|
|
216
|
+
f"{teamspace.owner.name}/{teamspace.name}/{container_basename}"
|
|
217
|
+
)
|
|
218
|
+
yield {
|
|
219
|
+
"finish": True,
|
|
220
|
+
"status": "Container pushed successfully",
|
|
221
|
+
"url": f"{LIGHTNING_CLOUD_URL}/{teamspace.owner.name}/{teamspace.name}/containers/{container_basename}"
|
|
222
|
+
f"{f'?clusterId={cloud_account}' if cloud_account is not None else ''}",
|
|
223
|
+
"image": repository,
|
|
224
|
+
}
|
|
228
225
|
|
|
229
226
|
def _update_deployment(
|
|
230
227
|
self,
|
|
@@ -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=pERZUbSd9UKX5PCO6GMnFKZFWbSw_05kILfckZAZGxo,1104
|
|
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/constants.py,sha256=ztl1PTUBULnqTf3DyKUSJaV_O20hNtUYT6XvAYIrmIk,749
|
|
@@ -10,7 +10,7 @@ lightning_sdk/models.py,sha256=5DCfv2M0b8iYKj8tAMIX7gIUXrk2CgALANX14N5OFgo,6255
|
|
|
10
10
|
lightning_sdk/organization.py,sha256=WCfzdgjtvY1_A07DnxOpp74V2JR2gQwtXbIEcFDnoVU,1232
|
|
11
11
|
lightning_sdk/owner.py,sha256=t5svD2it4C9pbSpVuG9WJL46CYi37JXNziwnXxhiU5U,1361
|
|
12
12
|
lightning_sdk/plugin.py,sha256=_K0m-PSyXE86B-SFQVQm0JEvfdIVXeARmnlATCAiMdo,14632
|
|
13
|
-
lightning_sdk/serve.py,sha256=
|
|
13
|
+
lightning_sdk/serve.py,sha256=yuBPy4w8n2Es7O2dlQStUZ-HcI8H12pB16ZY8SFe4WA,12139
|
|
14
14
|
lightning_sdk/status.py,sha256=lLGAuSvXBoXQFEEsEYwdCi0RcSNatUn5OPjJVjDtoM0,386
|
|
15
15
|
lightning_sdk/studio.py,sha256=hyvAiVhkETAtbu0RRF1Aw6F8Y__E1SSAmsB8PHfmqHo,19935
|
|
16
16
|
lightning_sdk/teamspace.py,sha256=EqMDDXtePCDD3JZHzx_qx7xn2tSxtH-LqwSc1JtIwEM,15073
|
|
@@ -20,7 +20,7 @@ lightning_sdk/api/agents_api.py,sha256=G47TbFo9kYqnBMqdw2RW-lfS1VAUBSXDmzs6fpIEM
|
|
|
20
20
|
lightning_sdk/api/ai_hub_api.py,sha256=azqDZ-PzasVAcoQHno7k7OO_xFOHQ4NDozxF8jEh83Y,7864
|
|
21
21
|
lightning_sdk/api/deployment_api.py,sha256=z_D7ZZAnsVe3Q_ZVx1azcLK2_pP5xj63tmU97qhgyOw,22583
|
|
22
22
|
lightning_sdk/api/job_api.py,sha256=_mMAI_BG_48i-BLwCP_U72zgmM5zYa2KUZ7u66HWkIc,13568
|
|
23
|
-
lightning_sdk/api/lit_container_api.py,sha256=
|
|
23
|
+
lightning_sdk/api/lit_container_api.py,sha256=m8X2uiM6Ze6qxuoAkfMgZEUNUyc93m8SnO0xDWt3O9E,10509
|
|
24
24
|
lightning_sdk/api/mmt_api.py,sha256=-v7ATab-ThAM-HRClS92Ehxuu9MlBfdKWWFCGvVUHiM,8962
|
|
25
25
|
lightning_sdk/api/org_api.py,sha256=Ze3z_ATVrukobujV5YdC42DKj45Vuwl7X52q_Vr-o3U,803
|
|
26
26
|
lightning_sdk/api/pipeline_api.py,sha256=P5P9C6qOpyBGU0t5N68h1LuFAsAKmPPgkac6uObrYKw,1676
|
|
@@ -47,7 +47,7 @@ lightning_sdk/cli/list.py,sha256=dAZ94QPvE4IkH6GfL7171TMrMfcuWB53cvW6wk2eL4w,101
|
|
|
47
47
|
lightning_sdk/cli/mmts_menu.py,sha256=HUXo3ZoZ3fWOCNWTQWoJgUlFXYq5uVm_6uFjAq7BDe8,2219
|
|
48
48
|
lightning_sdk/cli/open.py,sha256=sgMLWBnkXdIq8H9XK_rph2bye3b07AKTJBQIk9fCGVc,1937
|
|
49
49
|
lightning_sdk/cli/run.py,sha256=8JZiDrKwDhlaTOJd6qq2mCWJRqKm6shCWLzpbmFYIkE,13929
|
|
50
|
-
lightning_sdk/cli/serve.py,sha256=
|
|
50
|
+
lightning_sdk/cli/serve.py,sha256=kpegDpQVfBccXPR7Zhs0IG8A1CMx9ch17NFmcNLPk1s,10750
|
|
51
51
|
lightning_sdk/cli/start.py,sha256=jUk52lkEFC_fqiEPkwM8GwE68WMNEtzBuzjkvr3POd0,1840
|
|
52
52
|
lightning_sdk/cli/stop.py,sha256=5nCrUe1BONpX1nKNhbSFqLaXXKaRhSO7PvM1BVYLgn4,2864
|
|
53
53
|
lightning_sdk/cli/studios_menu.py,sha256=TA9rO6_fFHGMz0Nt4rJ6iV80X5pZE4xShrSiyXoU-oQ,4129
|
|
@@ -992,9 +992,9 @@ lightning_sdk/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
|
|
|
992
992
|
lightning_sdk/utils/dynamic.py,sha256=glUTO1JC9APtQ6Gr9SO02a3zr56-sPAXM5C3NrTpgyQ,1959
|
|
993
993
|
lightning_sdk/utils/enum.py,sha256=h2JRzqoBcSlUdanFHmkj_j5DleBHAu1esQYUsdNI-hU,4106
|
|
994
994
|
lightning_sdk/utils/resolve.py,sha256=uYAMAZ-emtFnjdg_sXbKRo3VTe5YWx7WEgCpNlHhHG8,6462
|
|
995
|
-
lightning_sdk-0.2.
|
|
996
|
-
lightning_sdk-0.2.
|
|
997
|
-
lightning_sdk-0.2.
|
|
998
|
-
lightning_sdk-0.2.
|
|
999
|
-
lightning_sdk-0.2.
|
|
1000
|
-
lightning_sdk-0.2.
|
|
995
|
+
lightning_sdk-0.2.8.dist-info/LICENSE,sha256=uFIuZwj5z-4TeF2UuacPZ1o17HkvKObT8fY50qN84sg,1064
|
|
996
|
+
lightning_sdk-0.2.8.dist-info/METADATA,sha256=8arXcOw6kN0kchU9glNKNiLzAe0vuUrdjIPdl90C52k,3991
|
|
997
|
+
lightning_sdk-0.2.8.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
|
|
998
|
+
lightning_sdk-0.2.8.dist-info/entry_points.txt,sha256=msB9PJWIJ784dX-OP8by51d4IbKYH3Fj1vCuA9oXjHY,68
|
|
999
|
+
lightning_sdk-0.2.8.dist-info/top_level.txt,sha256=ps8doKILFXmN7F1mHncShmnQoTxKBRPIcchC8TpoBw4,19
|
|
1000
|
+
lightning_sdk-0.2.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|