gmicloud 0.1.2__py3-none-any.whl → 0.1.4__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.
- gmicloud/_internal/_client/_artifact_client.py +11 -46
- gmicloud/_internal/_client/_http_client.py +1 -1
- gmicloud/_internal/_client/_iam_client.py +40 -8
- gmicloud/_internal/_client/_task_client.py +8 -42
- gmicloud/_internal/_constants.py +1 -0
- gmicloud/_internal/_models.py +26 -1
- {gmicloud-0.1.2.dist-info → gmicloud-0.1.4.dist-info}/METADATA +83 -45
- {gmicloud-0.1.2.dist-info → gmicloud-0.1.4.dist-info}/RECORD +10 -10
- {gmicloud-0.1.2.dist-info → gmicloud-0.1.4.dist-info}/WHEEL +0 -0
- {gmicloud-0.1.2.dist-info → gmicloud-0.1.4.dist-info}/top_level.txt +0 -0
@@ -5,7 +5,6 @@ from ._iam_client import IAMClient
|
|
5
5
|
from ._decorator import handle_refresh_token
|
6
6
|
from .._models import *
|
7
7
|
from .._config import ARTIFACT_SERVICE_BASE_URL
|
8
|
-
from .._constants import ACCESS_TOKEN_HEADER, CLIENT_ID_HEADER
|
9
8
|
|
10
9
|
|
11
10
|
class ArtifactClient:
|
@@ -33,11 +32,7 @@ class ArtifactClient:
|
|
33
32
|
:return: The Artifact object.
|
34
33
|
:rtype: Artifact
|
35
34
|
"""
|
36
|
-
|
37
|
-
ACCESS_TOKEN_HEADER: self.iam_client.get_access_token(),
|
38
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
39
|
-
}
|
40
|
-
result = self.client.get(f"/get_artifact", custom_headers, {"artifact_id": artifact_id})
|
35
|
+
result = self.client.get(f"/get_artifact", self.iam_client.get_custom_headers(), {"artifact_id": artifact_id})
|
41
36
|
|
42
37
|
return Artifact.model_validate(result)
|
43
38
|
|
@@ -49,11 +44,7 @@ class ArtifactClient:
|
|
49
44
|
:return: A list of Artifact objects.
|
50
45
|
:rtype: List[Artifact]
|
51
46
|
"""
|
52
|
-
|
53
|
-
ACCESS_TOKEN_HEADER: self.iam_client.get_access_token(),
|
54
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
55
|
-
}
|
56
|
-
result = self.client.get("/get_all_artifacts", custom_headers)
|
47
|
+
result = self.client.get("/get_all_artifacts", self.iam_client.get_custom_headers())
|
57
48
|
if not result:
|
58
49
|
return []
|
59
50
|
return [Artifact.model_validate(item) for item in result]
|
@@ -67,11 +58,7 @@ class ArtifactClient:
|
|
67
58
|
:return: The response object containing the created artifact details.
|
68
59
|
:rtype: CreateArtifactResponse
|
69
60
|
"""
|
70
|
-
|
71
|
-
ACCESS_TOKEN_HEADER: self.iam_client.get_access_token(),
|
72
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
73
|
-
}
|
74
|
-
result = self.client.post("/create_artifact", custom_headers, request.model_dump())
|
61
|
+
result = self.client.post("/create_artifact", self.iam_client.get_custom_headers(), request.model_dump())
|
75
62
|
|
76
63
|
return CreateArtifactResponse.model_validate(result)
|
77
64
|
|
@@ -84,11 +71,7 @@ class ArtifactClient:
|
|
84
71
|
:return: The response object containing the created artifact details.
|
85
72
|
:rtype: CreateArtifactFromTemplateResponse
|
86
73
|
"""
|
87
|
-
|
88
|
-
ACCESS_TOKEN_HEADER: self.iam_client.get_access_token(),
|
89
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
90
|
-
}
|
91
|
-
result = self.client.post("/create_artifact_from_template", custom_headers,
|
74
|
+
result = self.client.post("/create_artifact_from_template", self.iam_client.get_custom_headers(),
|
92
75
|
{"artifact_template_id": artifact_template_id})
|
93
76
|
|
94
77
|
return CreateArtifactFromTemplateResponse.model_validate(result)
|
@@ -102,11 +85,8 @@ class ArtifactClient:
|
|
102
85
|
:return: The response object containing the rebuilt artifact details.
|
103
86
|
:rtype: RebuildArtifactResponse
|
104
87
|
"""
|
105
|
-
|
106
|
-
|
107
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
108
|
-
}
|
109
|
-
result = self.client.post("/rebuild_artifact", custom_headers, {"artifact_id": artifact_id})
|
88
|
+
result = self.client.post("/rebuild_artifact", self.iam_client.get_custom_headers(),
|
89
|
+
{"artifact_id": artifact_id})
|
110
90
|
|
111
91
|
return CreateArtifactResponse.model_validate(result)
|
112
92
|
|
@@ -119,11 +99,8 @@ class ArtifactClient:
|
|
119
99
|
:return: The response object containing the deleted artifact details.
|
120
100
|
:rtype: DeleteArtifactResponse
|
121
101
|
"""
|
122
|
-
|
123
|
-
|
124
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
125
|
-
}
|
126
|
-
result = self.client.delete("/delete_artifact", custom_headers, {"artifact_id": artifact_id})
|
102
|
+
result = self.client.delete("/delete_artifact", self.iam_client.get_custom_headers(),
|
103
|
+
{"artifact_id": artifact_id})
|
127
104
|
|
128
105
|
return DeleteArtifactResponse.model_validate(result)
|
129
106
|
|
@@ -136,11 +113,7 @@ class ArtifactClient:
|
|
136
113
|
:return: The response object containing the pre-signed URL and upload details.
|
137
114
|
:rtype: GetBigFileUploadUrlResponse
|
138
115
|
"""
|
139
|
-
|
140
|
-
ACCESS_TOKEN_HEADER: self.iam_client.get_access_token(),
|
141
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
142
|
-
}
|
143
|
-
result = self.client.post("/get_bigfile_upload_url", custom_headers, request.model_dump())
|
116
|
+
result = self.client.post("/get_bigfile_upload_url", self.iam_client.get_custom_headers(), request.model_dump())
|
144
117
|
|
145
118
|
return GetBigFileUploadUrlResponse.model_validate(result)
|
146
119
|
|
@@ -153,11 +126,7 @@ class ArtifactClient:
|
|
153
126
|
:return: The response object containing the deletion status.
|
154
127
|
:rtype: DeleteBigfileResponse
|
155
128
|
"""
|
156
|
-
|
157
|
-
ACCESS_TOKEN_HEADER: self.iam_client.get_access_token(),
|
158
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
159
|
-
}
|
160
|
-
result = self.client.delete("/delete_bigfile", custom_headers, request.dict())
|
129
|
+
result = self.client.delete("/delete_bigfile", self.iam_client.get_custom_headers(), request.dict())
|
161
130
|
|
162
131
|
return DeleteBigfileResponse.model_validate(result)
|
163
132
|
|
@@ -169,9 +138,5 @@ class ArtifactClient:
|
|
169
138
|
:return: A list of ArtifactTemplate objects.
|
170
139
|
:rtype: List[ArtifactTemplate]
|
171
140
|
"""
|
172
|
-
|
173
|
-
ACCESS_TOKEN_HEADER: self.iam_client.get_access_token(),
|
174
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
175
|
-
}
|
176
|
-
result = self.client.get("/get_artifact_templates", custom_headers)
|
141
|
+
result = self.client.get("/get_artifact_templates", self.iam_client.get_custom_headers())
|
177
142
|
return GetArtifactTemplatesResponse.model_validate(result)
|
@@ -2,7 +2,6 @@ import requests
|
|
2
2
|
from .._exceptions import APIError
|
3
3
|
from .._exceptions import UnauthorizedError
|
4
4
|
from .._constants import *
|
5
|
-
from .._config import *
|
6
5
|
|
7
6
|
|
8
7
|
class HTTPClient:
|
@@ -62,6 +61,7 @@ class HTTPClient:
|
|
62
61
|
raise APIError(f"HTTP Request failed: {error_message}")
|
63
62
|
# Raise for HTTP errors
|
64
63
|
response.raise_for_status()
|
64
|
+
print(response.text)
|
65
65
|
|
66
66
|
except requests.exceptions.RequestException as e:
|
67
67
|
raise APIError(f"HTTP Request failed: {str(e)}")
|
@@ -3,7 +3,7 @@ import jwt
|
|
3
3
|
from ._http_client import HTTPClient
|
4
4
|
from .._config import IAM_SERVICE_BASE_URL
|
5
5
|
from .._models import *
|
6
|
-
from .._constants import CLIENT_ID_HEADER
|
6
|
+
from .._constants import CLIENT_ID_HEADER, AUTHORIZATION_HEADER
|
7
7
|
|
8
8
|
|
9
9
|
class IAMClient:
|
@@ -34,12 +34,35 @@ class IAMClient:
|
|
34
34
|
custom_headers = {
|
35
35
|
CLIENT_ID_HEADER: self._client_id
|
36
36
|
}
|
37
|
-
req =
|
38
|
-
|
37
|
+
req = AuthTokenRequest(email=self._email, password=self._password)
|
38
|
+
auth_tokens_result = self.client.post("/me/auth-tokens", custom_headers, req.model_dump())
|
39
|
+
auth_tokens_resp = AuthTokenResponse.model_validate(auth_tokens_result)
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
create_session_result = None
|
42
|
+
if auth_tokens_resp.is2FARequired:
|
43
|
+
max_attempts = 3
|
44
|
+
for attempt in range(max_attempts):
|
45
|
+
code = input(f"Attempt {attempt + 1}/{max_attempts}: Please enter the 2FA code: ")
|
46
|
+
|
47
|
+
create_session_req = CreateSessionRequest(
|
48
|
+
type="native", authToken=auth_tokens_resp.authToken, otpCode=code
|
49
|
+
)
|
50
|
+
try:
|
51
|
+
create_session_result = self.client.post(
|
52
|
+
"/me/sessions", custom_headers, create_session_req.model_dump()
|
53
|
+
)
|
54
|
+
break
|
55
|
+
except Exception as e:
|
56
|
+
print("Invalid 2FA code, please try again.")
|
57
|
+
if attempt == max_attempts - 1:
|
58
|
+
raise Exception("Failed to create session after 3 incorrect 2FA attempts.") from e
|
59
|
+
else:
|
60
|
+
create_session_req = CreateSessionRequest(type="native", authToken=auth_tokens_resp.authToken, otpCode=None)
|
61
|
+
create_session_result = self.client.post("/me/sessions", custom_headers, create_session_req.model_dump())
|
62
|
+
|
63
|
+
create_session_resp = CreateSessionResponse.model_validate(create_session_result)
|
64
|
+
self._access_token = create_session_resp.accessToken
|
65
|
+
self._refresh_token = create_session_resp.refreshToken
|
43
66
|
self._user_id = self.parse_user_id()
|
44
67
|
|
45
68
|
def refresh_token(self):
|
@@ -49,9 +72,9 @@ class IAMClient:
|
|
49
72
|
custom_headers = {
|
50
73
|
CLIENT_ID_HEADER: self._client_id
|
51
74
|
}
|
52
|
-
result = self.client.patch("/me/sessions", custom_headers, {"refreshToken": self.
|
75
|
+
result = self.client.patch("/me/sessions", custom_headers, {"refreshToken": self._refresh_token})
|
53
76
|
|
54
|
-
resp =
|
77
|
+
resp = CreateSessionResponse.model_validate(result)
|
55
78
|
self._access_token = resp.accessToken
|
56
79
|
self._refresh_token = resp.refreshToken
|
57
80
|
|
@@ -90,3 +113,12 @@ class IAMClient:
|
|
90
113
|
Gets the current client ID.
|
91
114
|
"""
|
92
115
|
return self._client_id
|
116
|
+
|
117
|
+
def get_custom_headers(self) -> dict:
|
118
|
+
"""
|
119
|
+
Gets the custom headers for the IAM client.
|
120
|
+
"""
|
121
|
+
return {
|
122
|
+
AUTHORIZATION_HEADER: f'Bearer {self._access_token}',
|
123
|
+
CLIENT_ID_HEADER: self._client_id
|
124
|
+
}
|
@@ -3,7 +3,6 @@ from ._decorator import handle_refresh_token
|
|
3
3
|
from ._iam_client import IAMClient
|
4
4
|
from .._config import TASK_SERVICE_BASE_URL
|
5
5
|
from .._models import *
|
6
|
-
from .._constants import ACCESS_TOKEN_HEADER, CLIENT_ID_HEADER
|
7
6
|
|
8
7
|
|
9
8
|
class TaskClient:
|
@@ -30,11 +29,7 @@ class TaskClient:
|
|
30
29
|
:return: An instance of Task containing the details of the retrieved task.
|
31
30
|
:rtype: Task
|
32
31
|
"""
|
33
|
-
|
34
|
-
ACCESS_TOKEN_HEADER: self.iam_client.get_access_token(),
|
35
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
36
|
-
}
|
37
|
-
result = self.client.get("/get_task", custom_headers, {"task_id": task_id})
|
32
|
+
result = self.client.get("/get_task", self.iam_client.get_custom_headers(), {"task_id": task_id})
|
38
33
|
|
39
34
|
return Task.model_validate(result)
|
40
35
|
|
@@ -46,11 +41,7 @@ class TaskClient:
|
|
46
41
|
:return: An instance of GetAllTasksResponse containing the retrieved tasks.
|
47
42
|
:rtype: GetAllTasksResponse
|
48
43
|
"""
|
49
|
-
|
50
|
-
ACCESS_TOKEN_HEADER: self.iam_client.get_access_token(),
|
51
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
52
|
-
}
|
53
|
-
result = self.client.get("/get_tasks", custom_headers)
|
44
|
+
result = self.client.get("/get_tasks", self.iam_client.get_custom_headers())
|
54
45
|
if not result:
|
55
46
|
return GetAllTasksResponse(tasks=[])
|
56
47
|
|
@@ -63,12 +54,7 @@ class TaskClient:
|
|
63
54
|
|
64
55
|
:param task: The Task object containing the details of the task to be created.
|
65
56
|
"""
|
66
|
-
|
67
|
-
ACCESS_TOKEN_HEADER: self.iam_client.get_access_token(),
|
68
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
69
|
-
}
|
70
|
-
|
71
|
-
result = self.client.post("/create_task", custom_headers, task.model_dump())
|
57
|
+
result = self.client.post("/create_task", self.iam_client.get_custom_headers(), task.model_dump())
|
72
58
|
|
73
59
|
return CreateTaskResponse.model_validate(result)
|
74
60
|
|
@@ -79,11 +65,7 @@ class TaskClient:
|
|
79
65
|
|
80
66
|
:param task: The Task object containing the updated task details.
|
81
67
|
"""
|
82
|
-
|
83
|
-
ACCESS_TOKEN_HEADER: self.iam_client.get_access_token(),
|
84
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
85
|
-
}
|
86
|
-
self.client.put("/update_schedule", custom_headers, task.model_dump())
|
68
|
+
self.client.put("/update_schedule", self.iam_client.get_custom_headers(), task.model_dump())
|
87
69
|
|
88
70
|
@handle_refresh_token
|
89
71
|
def start_task(self, task_id: str):
|
@@ -92,11 +74,7 @@ class TaskClient:
|
|
92
74
|
|
93
75
|
:param task_id: The ID of the task to be started.
|
94
76
|
"""
|
95
|
-
|
96
|
-
ACCESS_TOKEN_HEADER: self.iam_client.get_access_token(),
|
97
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
98
|
-
}
|
99
|
-
self.client.post("/start_task", custom_headers, {"task_id": task_id})
|
77
|
+
self.client.post("/start_task", self.iam_client.get_custom_headers(), {"task_id": task_id})
|
100
78
|
|
101
79
|
@handle_refresh_token
|
102
80
|
def stop_task(self, task_id: str):
|
@@ -105,11 +83,7 @@ class TaskClient:
|
|
105
83
|
|
106
84
|
:param task_id: The ID of the task to be stopped.
|
107
85
|
"""
|
108
|
-
|
109
|
-
ACCESS_TOKEN_HEADER: self.iam_client.get_access_token(),
|
110
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
111
|
-
}
|
112
|
-
self.client.post("/stop_task", custom_headers, {"task_id": task_id})
|
86
|
+
self.client.post("/stop_task", self.iam_client.get_custom_headers(), {"task_id": task_id})
|
113
87
|
|
114
88
|
@handle_refresh_token
|
115
89
|
def get_usage_data(self, start_timestamp: str, end_timestamp: str) -> GetUsageDataResponse:
|
@@ -119,11 +93,7 @@ class TaskClient:
|
|
119
93
|
:param start_timestamp: The start timestamp of the usage data.
|
120
94
|
:param end_timestamp: The end timestamp of the usage data.
|
121
95
|
"""
|
122
|
-
|
123
|
-
ACCESS_TOKEN_HEADER: self.iam_client.get_access_token(),
|
124
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
125
|
-
}
|
126
|
-
result = self.client.get("/get_usage_data", custom_headers,
|
96
|
+
result = self.client.get("/get_usage_data", self.iam_client.get_custom_headers(),
|
127
97
|
{"start_timestamp": start_timestamp, "end_timestamp": end_timestamp})
|
128
98
|
|
129
99
|
return result
|
@@ -135,8 +105,4 @@ class TaskClient:
|
|
135
105
|
|
136
106
|
:param task_id: The ID of the task to be archived.
|
137
107
|
"""
|
138
|
-
|
139
|
-
ACCESS_TOKEN_HEADER: self.iam_client.get_access_token(),
|
140
|
-
CLIENT_ID_HEADER: self.iam_client.get_client_id()
|
141
|
-
}
|
142
|
-
self.client.post("/archive_task", custom_headers, {"task_id": task_id})
|
108
|
+
self.client.post("/archive_task", self.iam_client.get_custom_headers(), {"task_id": task_id})
|
gmicloud/_internal/_constants.py
CHANGED
gmicloud/_internal/_models.py
CHANGED
@@ -307,10 +307,35 @@ class CreateTaskResponse(BaseModel):
|
|
307
307
|
upload_link: str # URL to upload the task data.
|
308
308
|
|
309
309
|
|
310
|
-
class
|
310
|
+
class AuthTokenRequest(BaseModel):
|
311
|
+
"""
|
312
|
+
Request object for user login.
|
313
|
+
"""
|
314
|
+
email: str # User email.
|
315
|
+
password: str # User password.
|
316
|
+
|
317
|
+
|
318
|
+
class AuthTokenResponse(BaseModel):
|
311
319
|
"""
|
312
320
|
Response object for user login.
|
313
321
|
"""
|
322
|
+
authToken: str # Access token for the user session.
|
323
|
+
is2FARequired: bool # Indicates if 2FA is required for the user.
|
324
|
+
|
325
|
+
|
326
|
+
class CreateSessionRequest(BaseModel):
|
327
|
+
"""
|
328
|
+
Request object for creating a user session.
|
329
|
+
"""
|
330
|
+
type: str # Type of the session (e.g., native).
|
331
|
+
authToken: str # Access token for the user session.
|
332
|
+
otpCode: Optional[str] # 2FA code for the user session.
|
333
|
+
|
334
|
+
|
335
|
+
class CreateSessionResponse(BaseModel):
|
336
|
+
"""
|
337
|
+
Response object for creating a user session.
|
338
|
+
"""
|
314
339
|
accessToken: str # Access token for the user session.
|
315
340
|
refreshToken: str # Refresh token for the user session.
|
316
341
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: gmicloud
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.4
|
4
4
|
Summary: GMI Cloud Python SDK
|
5
5
|
Author-email: GMI <gmi@gmitec.net>
|
6
6
|
License: MIT
|
@@ -10,10 +10,13 @@ Classifier: Operating System :: OS Independent
|
|
10
10
|
Requires-Python: >=3.6
|
11
11
|
Description-Content-Type: text/markdown
|
12
12
|
|
13
|
-
# GMICloud SDK
|
13
|
+
# GMICloud SDK (Beta)
|
14
14
|
|
15
15
|
## Overview
|
16
16
|
|
17
|
+
Before you start: Our service and GPU resource is currenly invite-only so please contact our team (
|
18
|
+
getstarted@gmicloud.ai) to get invited if you don't have one yet.
|
19
|
+
|
17
20
|
The GMI Inference Engine SDK provides a Python interface for deploying and managing machine learning models in
|
18
21
|
production environments. It allows users to create model artifacts, schedule tasks for serving models, and call
|
19
22
|
inference APIs easily.
|
@@ -62,7 +65,18 @@ client = Client(client_id="<YOUR_CLIENT_ID>", email="<YOUR_EMAIL>", password="<Y
|
|
62
65
|
|
63
66
|
## Quick Start
|
64
67
|
|
65
|
-
### 1.
|
68
|
+
### 1. How to run the code in the example folder
|
69
|
+
```bash
|
70
|
+
cd path/to/gmicloud-sdk
|
71
|
+
# Create a virtual environment
|
72
|
+
python -m venv venv
|
73
|
+
source venv/bin/activate
|
74
|
+
|
75
|
+
pip install -r requirements.txt
|
76
|
+
python -m examples.<example_name>
|
77
|
+
```
|
78
|
+
|
79
|
+
### 2. Create a Task from an Artifact Template
|
66
80
|
|
67
81
|
This is the simplest example to deploy an existing artifact template:
|
68
82
|
|
@@ -91,24 +105,30 @@ response = call_chat_completion(client, task.task_id)
|
|
91
105
|
print(response)
|
92
106
|
```
|
93
107
|
|
94
|
-
###
|
108
|
+
### 3. Step-by-Step Example: Create Artifact, Task, and Query the Endpoint
|
95
109
|
|
96
110
|
#### (a) Create an Artifact from a Template
|
97
111
|
|
98
112
|
First, you’ll retrieve all templates and create an artifact based on the desired template (e.g., "Llama3.1 8B"):
|
99
113
|
|
100
114
|
```python
|
101
|
-
|
115
|
+
from gmicloud import *
|
116
|
+
|
117
|
+
def create_artifact_from_template(client: Client) -> str:
|
102
118
|
artifact_manager = client.artifact_manager
|
103
119
|
|
104
|
-
#
|
120
|
+
# Get all artifact templates
|
105
121
|
templates = artifact_manager.get_artifact_templates()
|
106
122
|
for template in templates:
|
107
123
|
if template.artifact_template_id == "qwen_2.5_14b_instruct_template_001":
|
108
|
-
|
109
|
-
|
124
|
+
# Create an artifact from a template
|
125
|
+
artifact_id = artifact_manager.create_artifact_from_template(
|
126
|
+
artifact_template_id=template.artifact_template_id,
|
110
127
|
)
|
111
|
-
|
128
|
+
|
129
|
+
return artifact_id
|
130
|
+
|
131
|
+
return ""
|
112
132
|
```
|
113
133
|
|
114
134
|
#### (b) Create a Task from the Artifact
|
@@ -116,43 +136,55 @@ def create_artifact_from_template(client):
|
|
116
136
|
Wait until the artifact becomes "ready" and then deploy it using task scheduling:
|
117
137
|
|
118
138
|
```python
|
119
|
-
|
120
|
-
|
139
|
+
from gmicloud import *
|
140
|
+
import time
|
141
|
+
from datetime import datetime
|
121
142
|
|
122
|
-
|
143
|
+
def create_task_and_start(client: Client, artifact_id: str) -> str:
|
144
|
+
artifact_manager = client.artifact_manager
|
145
|
+
# Wait for the artifact to be ready
|
123
146
|
while True:
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
147
|
+
try:
|
148
|
+
artifact = artifact_manager.get_artifact(artifact_id)
|
149
|
+
print(f"Artifact status: {artifact.build_status}")
|
150
|
+
# Wait until the artifact is ready
|
151
|
+
if artifact.build_status == BuildStatus.SUCCESS:
|
152
|
+
break
|
153
|
+
except Exception as e:
|
154
|
+
raise e
|
155
|
+
# Wait for 2 seconds
|
128
156
|
time.sleep(2)
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
157
|
+
try:
|
158
|
+
task_manager = client.task_manager
|
159
|
+
# Create a task
|
160
|
+
task = task_manager.create_task(Task(
|
161
|
+
config=TaskConfig(
|
162
|
+
ray_task_config=RayTaskConfig(
|
163
|
+
ray_version="2.40.0-py310-gpu",
|
164
|
+
file_path="serve",
|
165
|
+
artifact_id=artifact_id,
|
166
|
+
deployment_name="app",
|
167
|
+
replica_resource=ReplicaResource(
|
168
|
+
cpu=10,
|
169
|
+
ram_gb=100,
|
170
|
+
gpu=1,
|
171
|
+
),
|
172
|
+
),
|
173
|
+
task_scheduling=TaskScheduling(
|
174
|
+
scheduling_oneoff=OneOffScheduling(
|
175
|
+
trigger_timestamp=int(datetime.now().timestamp()) + 10,
|
176
|
+
min_replicas=1,
|
177
|
+
max_replicas=10,
|
178
|
+
)
|
143
179
|
),
|
144
180
|
),
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
),
|
152
|
-
),
|
153
|
-
))
|
181
|
+
))
|
182
|
+
|
183
|
+
# Start the task
|
184
|
+
task_manager.start_task(task.task_id)
|
185
|
+
except Exception as e:
|
186
|
+
raise e
|
154
187
|
|
155
|
-
task_manager.start_task(task.task_id)
|
156
188
|
return task.task_id
|
157
189
|
```
|
158
190
|
|
@@ -161,14 +193,20 @@ def create_task_and_start(client, artifact_id):
|
|
161
193
|
Once the task is running, use the endpoint for inference:
|
162
194
|
|
163
195
|
```python
|
196
|
+
from gmicloud import *
|
164
197
|
from examples.completion import call_chat_completion
|
165
198
|
|
166
|
-
|
167
|
-
|
168
|
-
task_id = create_task_and_start(client, artifact_id)
|
199
|
+
# Initialize the Client
|
200
|
+
cli = Client()
|
169
201
|
|
170
|
-
|
171
|
-
|
202
|
+
# Create an artifact from a template
|
203
|
+
artifact_id = create_artifact_from_template(cli)
|
204
|
+
|
205
|
+
# Create a task and start it
|
206
|
+
task_id = create_task_and_start(cli, artifact_id)
|
207
|
+
|
208
|
+
# Call chat completion
|
209
|
+
print(call_chat_completion(cli, task_id))
|
172
210
|
```
|
173
211
|
|
174
212
|
## API Reference
|
@@ -2,17 +2,17 @@ gmicloud/__init__.py,sha256=AJP9Z3Ba-AClp5P49YL32qH5-XzDTbEXhWZFF1iLP8Q,750
|
|
2
2
|
gmicloud/client.py,sha256=G3sgH7zzODhdW_Ad56xgomDWXKAhnjzZuj1_mEBGYCI,4733
|
3
3
|
gmicloud/_internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
gmicloud/_internal/_config.py,sha256=qIH76TSyS3MQWe62LHI46RJhDnklNFisdajY75oUAqE,218
|
5
|
-
gmicloud/_internal/_constants.py,sha256=
|
5
|
+
gmicloud/_internal/_constants.py,sha256=Y085dwFlqdFkCf39iBfxz39QiiB7lX59ayNJjB86_m4,378
|
6
6
|
gmicloud/_internal/_enums.py,sha256=C4oy6Ps7OGdYd3tK-Wcpi6uXMyAKbOZW8_KykYAKsgw,510
|
7
7
|
gmicloud/_internal/_exceptions.py,sha256=hScBq7n2fOit4_umlkabZJchY8zVbWSRfWM2Y0rLCbw,306
|
8
|
-
gmicloud/_internal/_models.py,sha256=
|
8
|
+
gmicloud/_internal/_models.py,sha256=4YT1MI2V1YEBWBFEvrA6pRcmxkZCgi6rzTxYMRgfeWs,13880
|
9
9
|
gmicloud/_internal/_client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
|
-
gmicloud/_internal/_client/_artifact_client.py,sha256=
|
10
|
+
gmicloud/_internal/_client/_artifact_client.py,sha256=py6SQ1tVoK365hIIxnla433mpCapActZ6KE6Yakds-8,5588
|
11
11
|
gmicloud/_internal/_client/_decorator.py,sha256=sy4gxzsUB6ORXHw5pqmMf7TTlK41Nmu1fhIhK2AIsbY,670
|
12
12
|
gmicloud/_internal/_client/_file_upload_client.py,sha256=1JRs4X57S3EScPIP9w2DC1Uo6_Wbcjumcw3nVM7uIGM,4667
|
13
|
-
gmicloud/_internal/_client/_http_client.py,sha256=
|
14
|
-
gmicloud/_internal/_client/_iam_client.py,sha256=
|
15
|
-
gmicloud/_internal/_client/_task_client.py,sha256=
|
13
|
+
gmicloud/_internal/_client/_http_client.py,sha256=JZvw7HnCwyk6_5-Ja-KZuYY0JBJApx9I3jZ0G_J2kWw,5680
|
14
|
+
gmicloud/_internal/_client/_iam_client.py,sha256=xEDiwwpj1dAHmAOzcu9Jz7x1F3TRJLrCAqNXPQ-wyoU,4310
|
15
|
+
gmicloud/_internal/_client/_task_client.py,sha256=JgYewfDy2iblRVrc9sdA8RbcooXyAho79ESuCK8PRWI,3842
|
16
16
|
gmicloud/_internal/_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
17
|
gmicloud/_internal/_manager/_artifact_manager.py,sha256=cc367Kd-W9Zn2d_wUcG6tT06544HRItIZ5IsFfA5_RQ,12201
|
18
18
|
gmicloud/_internal/_manager/_task_manager.py,sha256=QQfpYXFKAAI_FSI--Nxvjlgf_jeVZuVnTuRGTQzrZso,8034
|
@@ -20,7 +20,7 @@ gmicloud/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
20
|
gmicloud/tests/test_artifacts.py,sha256=YiC1HBMS7g491Ra4acTLI9AdwyjXZfnY9f-fNKn2azQ,17108
|
21
21
|
gmicloud/tests/test_tasks.py,sha256=AY90zTJdsXk1cxn6Jxhi4TDdwXRiGxz_r_aRk_Jkl8Y,10956
|
22
22
|
gmicloud/utils/uninstall_packages.py,sha256=zzuuaJPf39oTXWZ_7tUAGseoxocuCbbkoglJSD5yDrE,1127
|
23
|
-
gmicloud-0.1.
|
24
|
-
gmicloud-0.1.
|
25
|
-
gmicloud-0.1.
|
26
|
-
gmicloud-0.1.
|
23
|
+
gmicloud-0.1.4.dist-info/METADATA,sha256=hwFbxM2blSJZQnRT-9x6y-ilfcgFL6_tdQP2f12TloQ,7689
|
24
|
+
gmicloud-0.1.4.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
25
|
+
gmicloud-0.1.4.dist-info/top_level.txt,sha256=AZimLw3y0WPpLiSiOidZ1gD0dxALh-jQNk4fxC05hYE,9
|
26
|
+
gmicloud-0.1.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|