colabhive 0.5.0__tar.gz
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.
- colabhive-0.5.0/LICENSE +22 -0
- colabhive-0.5.0/MANIFEST.in +9 -0
- colabhive-0.5.0/PKG-INFO +235 -0
- colabhive-0.5.0/README.md +202 -0
- colabhive-0.5.0/colabhive/__init__.py +34 -0
- colabhive-0.5.0/colabhive/actions.py +192 -0
- colabhive-0.5.0/colabhive/client.py +99 -0
- colabhive-0.5.0/colabhive/datasets.py +274 -0
- colabhive-0.5.0/colabhive/endpoints.py +318 -0
- colabhive-0.5.0/colabhive/exceptions.py +62 -0
- colabhive-0.5.0/colabhive/hf.py +490 -0
- colabhive-0.5.0/colabhive/models.py +330 -0
- colabhive-0.5.0/colabhive/system.py +91 -0
- colabhive-0.5.0/colabhive/training.py +793 -0
- colabhive-0.5.0/colabhive/types.py +472 -0
- colabhive-0.5.0/colabhive/users.py +165 -0
- colabhive-0.5.0/colabhive.egg-info/PKG-INFO +235 -0
- colabhive-0.5.0/colabhive.egg-info/SOURCES.txt +22 -0
- colabhive-0.5.0/colabhive.egg-info/dependency_links.txt +1 -0
- colabhive-0.5.0/colabhive.egg-info/requires.txt +9 -0
- colabhive-0.5.0/colabhive.egg-info/top_level.txt +1 -0
- colabhive-0.5.0/pyproject.toml +61 -0
- colabhive-0.5.0/setup.cfg +4 -0
- colabhive-0.5.0/setup.py +55 -0
colabhive-0.5.0/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 ColabHive
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
colabhive-0.5.0/PKG-INFO
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: colabhive
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: Official Python SDK for ColabHive Builder APIs
|
|
5
|
+
Home-page: https://github.com/colabhive/colabhive-sdk-python
|
|
6
|
+
Author: ColabHive Team
|
|
7
|
+
Author-email: ColabHive Team <support@colabhive.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://colabhive.com
|
|
10
|
+
Project-URL: Documentation, https://docs.colabhive.com
|
|
11
|
+
Project-URL: Repository, https://github.com/colabhive/colabhive-sdk-python
|
|
12
|
+
Project-URL: Issues, https://github.com/colabhive/colabhive-sdk-python/issues
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Requires-Python: >=3.8
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: httpx>=0.24.0
|
|
26
|
+
Requires-Dist: pydantic>=2.0.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
31
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
32
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
33
|
+
|
|
34
|
+
# ColabHive Python SDK
|
|
35
|
+
|
|
36
|
+
Official Python client for ColabHive Builder APIs.
|
|
37
|
+
|
|
38
|
+
Train machine learning models on distributed GPUs without managing infrastructure.
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install colabhive
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quick Start
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
from colabhive import ColabHive
|
|
50
|
+
|
|
51
|
+
# Initialize client
|
|
52
|
+
client = ColabHive(
|
|
53
|
+
api_key="your_api_key_here",
|
|
54
|
+
account_id="your_account_id_here"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# Upload dataset
|
|
58
|
+
dataset = client.datasets.upload(
|
|
59
|
+
name="my_training_data",
|
|
60
|
+
file="./data.csv"
|
|
61
|
+
)
|
|
62
|
+
print(f"Dataset uploaded: {dataset.id}")
|
|
63
|
+
|
|
64
|
+
# Train model
|
|
65
|
+
job = client.training.create(
|
|
66
|
+
model="xgboost-regression",
|
|
67
|
+
dataset_id=dataset.id,
|
|
68
|
+
job_name="My First Model"
|
|
69
|
+
)
|
|
70
|
+
print(f"Training started: {job.id}")
|
|
71
|
+
|
|
72
|
+
# Wait for completion
|
|
73
|
+
job.wait()
|
|
74
|
+
|
|
75
|
+
if job.status == "completed":
|
|
76
|
+
print("Training complete!")
|
|
77
|
+
print(f"Metrics: {job.metrics}")
|
|
78
|
+
else:
|
|
79
|
+
print(f"Training failed: {job.error_message}")
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Authentication
|
|
83
|
+
|
|
84
|
+
Get your API key and account ID from [console.colabhive.com](https://console.colabhive.com/api-keys).
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
client = ColabHive(
|
|
88
|
+
api_key="colabhive_sk_...",
|
|
89
|
+
account_id="0914e1c6-..."
|
|
90
|
+
)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Features
|
|
94
|
+
|
|
95
|
+
### Datasets
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
# Upload
|
|
99
|
+
dataset = client.datasets.upload(name="data", file="./train.csv")
|
|
100
|
+
|
|
101
|
+
# List
|
|
102
|
+
datasets = client.datasets.list(limit=10)
|
|
103
|
+
|
|
104
|
+
# Get
|
|
105
|
+
dataset = client.datasets.get("dataset-id")
|
|
106
|
+
|
|
107
|
+
# Delete
|
|
108
|
+
client.datasets.delete("dataset-id")
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Training
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
# Create training job
|
|
115
|
+
job = client.training.create(
|
|
116
|
+
model="xgboost-regression",
|
|
117
|
+
dataset_id="dataset-id",
|
|
118
|
+
job_name="Experiment 1",
|
|
119
|
+
hyperparameters={
|
|
120
|
+
"n_estimators": 100,
|
|
121
|
+
"max_depth": 6
|
|
122
|
+
}
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# List jobs
|
|
126
|
+
jobs = client.training.list(limit=10, status="running")
|
|
127
|
+
|
|
128
|
+
# Get job
|
|
129
|
+
job = client.training.get("run-id")
|
|
130
|
+
|
|
131
|
+
# Wait for completion
|
|
132
|
+
job.wait(poll_interval=5, timeout=3600, verbose=True)
|
|
133
|
+
|
|
134
|
+
# Get metrics
|
|
135
|
+
metrics = job.metrics
|
|
136
|
+
print(metrics)
|
|
137
|
+
|
|
138
|
+
# Delete job
|
|
139
|
+
client.training.delete("run-id")
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Models
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
# List models
|
|
146
|
+
models = client.models.list()
|
|
147
|
+
|
|
148
|
+
# Get model
|
|
149
|
+
model = client.models.get("model-id")
|
|
150
|
+
|
|
151
|
+
# Download model
|
|
152
|
+
path = client.models.download("model-id", "./my_model.pkl")
|
|
153
|
+
|
|
154
|
+
# Delete model
|
|
155
|
+
client.models.delete("model-id")
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Model Configurations
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
# List available model configs
|
|
162
|
+
configs = client.training.model_configs(category="ml_classical")
|
|
163
|
+
|
|
164
|
+
for config in configs:
|
|
165
|
+
print(config.model_name, config.display_name)
|
|
166
|
+
print(config.default_hyperparameters)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Advanced Usage
|
|
170
|
+
|
|
171
|
+
### Context Manager
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
with ColabHive(api_key="...", account_id="...") as client:
|
|
175
|
+
dataset = client.datasets.upload("data", "./train.csv")
|
|
176
|
+
job = client.training.create("xgboost-regression", dataset.id)
|
|
177
|
+
job.wait()
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Custom Base URL
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
# For production
|
|
184
|
+
client = ColabHive(
|
|
185
|
+
api_key="...",
|
|
186
|
+
account_id="...",
|
|
187
|
+
base_url="https://api.colabhive.com"
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# For local development
|
|
191
|
+
client = ColabHive(
|
|
192
|
+
api_key="...",
|
|
193
|
+
account_id="...",
|
|
194
|
+
base_url="http://localhost:8014"
|
|
195
|
+
)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Error Handling
|
|
199
|
+
|
|
200
|
+
```python
|
|
201
|
+
from colabhive import ColabHive, ValidationError, NotFoundError, APIError
|
|
202
|
+
|
|
203
|
+
client = ColabHive(api_key="...", account_id="...")
|
|
204
|
+
|
|
205
|
+
try:
|
|
206
|
+
dataset = client.datasets.upload("data", "./nonexistent.csv")
|
|
207
|
+
except ValidationError as e:
|
|
208
|
+
print(f"Invalid request: {e.message}")
|
|
209
|
+
except NotFoundError as e:
|
|
210
|
+
print(f"Not found: {e.message}")
|
|
211
|
+
except APIError as e:
|
|
212
|
+
print(f"API error: {e.message} (status: {e.status_code})")
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Requirements
|
|
216
|
+
|
|
217
|
+
- Python 3.8+
|
|
218
|
+
- httpx >= 0.24.0
|
|
219
|
+
- pydantic >= 2.0.0
|
|
220
|
+
|
|
221
|
+
## Documentation
|
|
222
|
+
|
|
223
|
+
- [Full Documentation](https://docs.colabhive.com)
|
|
224
|
+
- [API Reference](https://docs.colabhive.com/api)
|
|
225
|
+
- [Examples](https://docs.colabhive.com/examples)
|
|
226
|
+
|
|
227
|
+
## Support
|
|
228
|
+
|
|
229
|
+
- **Discord**: [discord.gg/colabhive](https://discord.gg/colabhive)
|
|
230
|
+
- **Email**: support@colabhive.com
|
|
231
|
+
- **Issues**: [GitHub Issues](https://github.com/colabhive/colabhive-sdk-python/issues)
|
|
232
|
+
|
|
233
|
+
## License
|
|
234
|
+
|
|
235
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# ColabHive Python SDK
|
|
2
|
+
|
|
3
|
+
Official Python client for ColabHive Builder APIs.
|
|
4
|
+
|
|
5
|
+
Train machine learning models on distributed GPUs without managing infrastructure.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install colabhive
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from colabhive import ColabHive
|
|
17
|
+
|
|
18
|
+
# Initialize client
|
|
19
|
+
client = ColabHive(
|
|
20
|
+
api_key="your_api_key_here",
|
|
21
|
+
account_id="your_account_id_here"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Upload dataset
|
|
25
|
+
dataset = client.datasets.upload(
|
|
26
|
+
name="my_training_data",
|
|
27
|
+
file="./data.csv"
|
|
28
|
+
)
|
|
29
|
+
print(f"Dataset uploaded: {dataset.id}")
|
|
30
|
+
|
|
31
|
+
# Train model
|
|
32
|
+
job = client.training.create(
|
|
33
|
+
model="xgboost-regression",
|
|
34
|
+
dataset_id=dataset.id,
|
|
35
|
+
job_name="My First Model"
|
|
36
|
+
)
|
|
37
|
+
print(f"Training started: {job.id}")
|
|
38
|
+
|
|
39
|
+
# Wait for completion
|
|
40
|
+
job.wait()
|
|
41
|
+
|
|
42
|
+
if job.status == "completed":
|
|
43
|
+
print("Training complete!")
|
|
44
|
+
print(f"Metrics: {job.metrics}")
|
|
45
|
+
else:
|
|
46
|
+
print(f"Training failed: {job.error_message}")
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Authentication
|
|
50
|
+
|
|
51
|
+
Get your API key and account ID from [console.colabhive.com](https://console.colabhive.com/api-keys).
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
client = ColabHive(
|
|
55
|
+
api_key="colabhive_sk_...",
|
|
56
|
+
account_id="0914e1c6-..."
|
|
57
|
+
)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Features
|
|
61
|
+
|
|
62
|
+
### Datasets
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
# Upload
|
|
66
|
+
dataset = client.datasets.upload(name="data", file="./train.csv")
|
|
67
|
+
|
|
68
|
+
# List
|
|
69
|
+
datasets = client.datasets.list(limit=10)
|
|
70
|
+
|
|
71
|
+
# Get
|
|
72
|
+
dataset = client.datasets.get("dataset-id")
|
|
73
|
+
|
|
74
|
+
# Delete
|
|
75
|
+
client.datasets.delete("dataset-id")
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Training
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
# Create training job
|
|
82
|
+
job = client.training.create(
|
|
83
|
+
model="xgboost-regression",
|
|
84
|
+
dataset_id="dataset-id",
|
|
85
|
+
job_name="Experiment 1",
|
|
86
|
+
hyperparameters={
|
|
87
|
+
"n_estimators": 100,
|
|
88
|
+
"max_depth": 6
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# List jobs
|
|
93
|
+
jobs = client.training.list(limit=10, status="running")
|
|
94
|
+
|
|
95
|
+
# Get job
|
|
96
|
+
job = client.training.get("run-id")
|
|
97
|
+
|
|
98
|
+
# Wait for completion
|
|
99
|
+
job.wait(poll_interval=5, timeout=3600, verbose=True)
|
|
100
|
+
|
|
101
|
+
# Get metrics
|
|
102
|
+
metrics = job.metrics
|
|
103
|
+
print(metrics)
|
|
104
|
+
|
|
105
|
+
# Delete job
|
|
106
|
+
client.training.delete("run-id")
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Models
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
# List models
|
|
113
|
+
models = client.models.list()
|
|
114
|
+
|
|
115
|
+
# Get model
|
|
116
|
+
model = client.models.get("model-id")
|
|
117
|
+
|
|
118
|
+
# Download model
|
|
119
|
+
path = client.models.download("model-id", "./my_model.pkl")
|
|
120
|
+
|
|
121
|
+
# Delete model
|
|
122
|
+
client.models.delete("model-id")
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Model Configurations
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
# List available model configs
|
|
129
|
+
configs = client.training.model_configs(category="ml_classical")
|
|
130
|
+
|
|
131
|
+
for config in configs:
|
|
132
|
+
print(config.model_name, config.display_name)
|
|
133
|
+
print(config.default_hyperparameters)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Advanced Usage
|
|
137
|
+
|
|
138
|
+
### Context Manager
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
with ColabHive(api_key="...", account_id="...") as client:
|
|
142
|
+
dataset = client.datasets.upload("data", "./train.csv")
|
|
143
|
+
job = client.training.create("xgboost-regression", dataset.id)
|
|
144
|
+
job.wait()
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Custom Base URL
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
# For production
|
|
151
|
+
client = ColabHive(
|
|
152
|
+
api_key="...",
|
|
153
|
+
account_id="...",
|
|
154
|
+
base_url="https://api.colabhive.com"
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# For local development
|
|
158
|
+
client = ColabHive(
|
|
159
|
+
api_key="...",
|
|
160
|
+
account_id="...",
|
|
161
|
+
base_url="http://localhost:8014"
|
|
162
|
+
)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Error Handling
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
from colabhive import ColabHive, ValidationError, NotFoundError, APIError
|
|
169
|
+
|
|
170
|
+
client = ColabHive(api_key="...", account_id="...")
|
|
171
|
+
|
|
172
|
+
try:
|
|
173
|
+
dataset = client.datasets.upload("data", "./nonexistent.csv")
|
|
174
|
+
except ValidationError as e:
|
|
175
|
+
print(f"Invalid request: {e.message}")
|
|
176
|
+
except NotFoundError as e:
|
|
177
|
+
print(f"Not found: {e.message}")
|
|
178
|
+
except APIError as e:
|
|
179
|
+
print(f"API error: {e.message} (status: {e.status_code})")
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Requirements
|
|
183
|
+
|
|
184
|
+
- Python 3.8+
|
|
185
|
+
- httpx >= 0.24.0
|
|
186
|
+
- pydantic >= 2.0.0
|
|
187
|
+
|
|
188
|
+
## Documentation
|
|
189
|
+
|
|
190
|
+
- [Full Documentation](https://docs.colabhive.com)
|
|
191
|
+
- [API Reference](https://docs.colabhive.com/api)
|
|
192
|
+
- [Examples](https://docs.colabhive.com/examples)
|
|
193
|
+
|
|
194
|
+
## Support
|
|
195
|
+
|
|
196
|
+
- **Discord**: [discord.gg/colabhive](https://discord.gg/colabhive)
|
|
197
|
+
- **Email**: support@colabhive.com
|
|
198
|
+
- **Issues**: [GitHub Issues](https://github.com/colabhive/colabhive-sdk-python/issues)
|
|
199
|
+
|
|
200
|
+
## License
|
|
201
|
+
|
|
202
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""ColabHive Python SDK
|
|
2
|
+
|
|
3
|
+
Official Python client for ColabHive Builder APIs.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
__version__ = "0.5.0"
|
|
7
|
+
|
|
8
|
+
from .client import ColabHive
|
|
9
|
+
from .types import Dataset, TrainingJob, Model, Endpoint, Artifact, ArtifactRef
|
|
10
|
+
from .exceptions import (
|
|
11
|
+
ColabHiveError,
|
|
12
|
+
AuthenticationError,
|
|
13
|
+
NotFoundError,
|
|
14
|
+
ValidationError,
|
|
15
|
+
RateLimitError,
|
|
16
|
+
APIError,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"ColabHive",
|
|
21
|
+
"Dataset",
|
|
22
|
+
"TrainingJob",
|
|
23
|
+
"Model",
|
|
24
|
+
"Endpoint",
|
|
25
|
+
"Artifact",
|
|
26
|
+
"ArtifactRef",
|
|
27
|
+
"ColabHiveError",
|
|
28
|
+
"AuthenticationError",
|
|
29
|
+
"NotFoundError",
|
|
30
|
+
"ValidationError",
|
|
31
|
+
"RateLimitError",
|
|
32
|
+
"APIError",
|
|
33
|
+
]
|
|
34
|
+
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"""Actions API — the unified, plugin-ready invocation surface.
|
|
2
|
+
|
|
3
|
+
The Actions surface is computed by the Builder Gateway from existing
|
|
4
|
+
``inference_endpoints`` + ``model_configs`` + ``training_jobs`` (no new tables):
|
|
5
|
+
every visible base model, tool, specialist and user-trained endpoint is exposed
|
|
6
|
+
as a single "action" addressable by a stable ``slug`` (its endpoint name). This
|
|
7
|
+
lets you discover and invoke *any* capability through one uniform contract
|
|
8
|
+
instead of special-casing per model.
|
|
9
|
+
|
|
10
|
+
Access via: ``client.actions``
|
|
11
|
+
|
|
12
|
+
Routes wrapped (all under ``/api/builder/v1``):
|
|
13
|
+
|
|
14
|
+
- ``GET /actions`` -> :meth:`ActionsAPI.list`
|
|
15
|
+
- ``GET /actions/{slug}`` -> :meth:`ActionsAPI.get`
|
|
16
|
+
- ``POST /actions/{slug}:invoke`` -> :meth:`ActionsAPI.invoke`
|
|
17
|
+
- ``GET /invocations/{id}`` -> :meth:`ActionsAPI.poll`
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from typing import Any, Dict, List, Optional
|
|
21
|
+
|
|
22
|
+
from .exceptions import raise_for_status
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ActionsAPI:
|
|
26
|
+
"""API for the unified action surface (discover + invoke by slug)."""
|
|
27
|
+
|
|
28
|
+
def __init__(self, client):
|
|
29
|
+
self.client = client
|
|
30
|
+
|
|
31
|
+
def list(
|
|
32
|
+
self,
|
|
33
|
+
kind: Optional[str] = None,
|
|
34
|
+
task_type: Optional[str] = None,
|
|
35
|
+
search: Optional[str] = None,
|
|
36
|
+
base_only: Optional[bool] = None,
|
|
37
|
+
limit: int = 50,
|
|
38
|
+
offset: int = 0,
|
|
39
|
+
) -> List[Dict[str, Any]]:
|
|
40
|
+
"""
|
|
41
|
+
Discover all invocable actions visible to your account.
|
|
42
|
+
|
|
43
|
+
Returns base models (LLMs, specialists, tools), generative models and
|
|
44
|
+
your own trained endpoints, each enriched with an auto-generated
|
|
45
|
+
``input_schema`` and, for trained models, training lineage.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
kind: Filter by kind (llm, specialist, tool, trained_model, generative, model)
|
|
49
|
+
task_type: Filter by task type (chat, classification, regression,
|
|
50
|
+
forecasting, embeddings, ...)
|
|
51
|
+
search: Free-text search over slug, display name and description
|
|
52
|
+
base_only: True = only base models, False = only trained models,
|
|
53
|
+
None = both (default)
|
|
54
|
+
limit: Maximum number of actions to return (1-200, default: 50)
|
|
55
|
+
offset: Pagination offset (default: 0)
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
List of action dicts. Each has ``slug``, ``display_name``,
|
|
59
|
+
``description``, ``kind``, ``task_type``, ``input_schema``,
|
|
60
|
+
``output_schema``, ``invoke_url`` and (for trained models)
|
|
61
|
+
``training`` lineage.
|
|
62
|
+
|
|
63
|
+
Example:
|
|
64
|
+
>>> # Find every chat-capable action I can invoke
|
|
65
|
+
>>> actions = client.actions.list(kind="llm", task_type="chat")
|
|
66
|
+
>>> for a in actions:
|
|
67
|
+
... print(a["slug"], "-", a["display_name"])
|
|
68
|
+
"""
|
|
69
|
+
params: Dict[str, Any] = {"limit": limit, "offset": offset}
|
|
70
|
+
if kind is not None:
|
|
71
|
+
params["kind"] = kind
|
|
72
|
+
if task_type is not None:
|
|
73
|
+
params["task_type"] = task_type
|
|
74
|
+
if search is not None:
|
|
75
|
+
params["search"] = search
|
|
76
|
+
if base_only is not None:
|
|
77
|
+
params["base_only"] = base_only
|
|
78
|
+
|
|
79
|
+
response = self.client._http.get(
|
|
80
|
+
f"{self.client.base_url}/api/builder/v1/actions",
|
|
81
|
+
params=params,
|
|
82
|
+
)
|
|
83
|
+
raise_for_status(response)
|
|
84
|
+
return response.json().get("actions", [])
|
|
85
|
+
|
|
86
|
+
def get(self, slug: str) -> Dict[str, Any]:
|
|
87
|
+
"""
|
|
88
|
+
Get a single action's detail by slug.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
slug: The action slug (the endpoint name, e.g. "mistral-7b-instruct-public")
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
Action dict (same shape as an element of :meth:`list`).
|
|
95
|
+
|
|
96
|
+
Example:
|
|
97
|
+
>>> action = client.actions.get("mistral-7b-instruct-public")
|
|
98
|
+
>>> print(action["input_schema"])
|
|
99
|
+
"""
|
|
100
|
+
response = self.client._http.get(
|
|
101
|
+
f"{self.client.base_url}/api/builder/v1/actions/{slug}"
|
|
102
|
+
)
|
|
103
|
+
raise_for_status(response)
|
|
104
|
+
return response.json()
|
|
105
|
+
|
|
106
|
+
def invoke(
|
|
107
|
+
self,
|
|
108
|
+
slug: str,
|
|
109
|
+
input_data: Dict[str, Any],
|
|
110
|
+
sync: bool = True,
|
|
111
|
+
sync_timeout: float = 30.0,
|
|
112
|
+
timeout: Optional[float] = None,
|
|
113
|
+
) -> Dict[str, Any]:
|
|
114
|
+
"""
|
|
115
|
+
Invoke an action by slug (the unified invocation entry point).
|
|
116
|
+
|
|
117
|
+
Resolves the slug to its endpoint and dispatches to the orchestrator —
|
|
118
|
+
the invocation body is the same contract as ``endpoints.infer``.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
slug: The action slug to invoke.
|
|
122
|
+
input_data: Input payload for the action (goes to the ``input`` field).
|
|
123
|
+
sync: If True (default) the server waits for the result; if False it
|
|
124
|
+
returns immediately with an ``invocation_id`` to poll.
|
|
125
|
+
sync_timeout: Max seconds the server blocks in sync mode (1-300, default: 30).
|
|
126
|
+
timeout: Optional HTTP client timeout override. Defaults to
|
|
127
|
+
``sync_timeout + 5`` in sync mode, else 30s.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
Invocation dict with ``invocation_id``, ``action_slug``, ``status``
|
|
131
|
+
and ``model_state``. In a completed sync call it also carries
|
|
132
|
+
``result``, ``error`` and ``metrics``; otherwise it carries a
|
|
133
|
+
``poll_url`` to use with :meth:`poll`.
|
|
134
|
+
|
|
135
|
+
Example:
|
|
136
|
+
>>> # Synchronous invocation
|
|
137
|
+
>>> resp = client.actions.invoke(
|
|
138
|
+
... "mistral-7b-instruct-public",
|
|
139
|
+
... {"messages": [{"role": "user", "content": "Say PASS"}]},
|
|
140
|
+
... )
|
|
141
|
+
>>> print(resp["result"])
|
|
142
|
+
>>>
|
|
143
|
+
>>> # Fire-and-poll
|
|
144
|
+
>>> resp = client.actions.invoke("sdxl-public", {"prompt": "a fox"}, sync=False)
|
|
145
|
+
>>> final = client.actions.poll(resp["invocation_id"])
|
|
146
|
+
"""
|
|
147
|
+
request_kwargs: Dict[str, Any] = {
|
|
148
|
+
"json": {
|
|
149
|
+
"input": input_data,
|
|
150
|
+
"sync": sync,
|
|
151
|
+
"sync_timeout_s": sync_timeout,
|
|
152
|
+
},
|
|
153
|
+
# Server blocks for sync, so set HTTP timeout = sync_timeout + buffer
|
|
154
|
+
"timeout": timeout or (sync_timeout + 5 if sync else 30),
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
response = self.client._http.post(
|
|
158
|
+
f"{self.client.base_url}/api/builder/v1/actions/{slug}:invoke",
|
|
159
|
+
**request_kwargs,
|
|
160
|
+
)
|
|
161
|
+
raise_for_status(response)
|
|
162
|
+
return response.json()
|
|
163
|
+
|
|
164
|
+
def poll(self, invocation_id: str) -> Dict[str, Any]:
|
|
165
|
+
"""
|
|
166
|
+
Poll the status/result of an invocation.
|
|
167
|
+
|
|
168
|
+
Use this with the ``invocation_id`` returned by an async
|
|
169
|
+
:meth:`invoke` (``sync=False``).
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
invocation_id: The invocation id to poll.
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
Invocation status dict with ``invocation_id``, ``status``,
|
|
176
|
+
``status_detail``, ``result``, ``error``, ``metrics`` and timestamps.
|
|
177
|
+
|
|
178
|
+
Example:
|
|
179
|
+
>>> resp = client.actions.invoke("sdxl-public", {"prompt": "a fox"}, sync=False)
|
|
180
|
+
>>> import time
|
|
181
|
+
>>> while True:
|
|
182
|
+
... inv = client.actions.poll(resp["invocation_id"])
|
|
183
|
+
... if inv["status"] in ("completed", "succeeded", "failed"):
|
|
184
|
+
... break
|
|
185
|
+
... time.sleep(1)
|
|
186
|
+
>>> print(inv["result"])
|
|
187
|
+
"""
|
|
188
|
+
response = self.client._http.get(
|
|
189
|
+
f"{self.client.base_url}/api/builder/v1/invocations/{invocation_id}"
|
|
190
|
+
)
|
|
191
|
+
raise_for_status(response)
|
|
192
|
+
return response.json()
|