podstack 1.2.0__tar.gz → 1.2.1__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.
- podstack-1.2.1/PKG-INFO +467 -0
- podstack-1.2.1/README.md +415 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack/__init__.py +1 -1
- {podstack-1.2.0 → podstack-1.2.1}/podstack/client.py +2 -2
- podstack-1.2.1/podstack.egg-info/PKG-INFO +467 -0
- {podstack-1.2.0 → podstack-1.2.1}/pyproject.toml +4 -4
- podstack-1.2.0/PKG-INFO +0 -299
- podstack-1.2.0/README.md +0 -247
- podstack-1.2.0/podstack.egg-info/PKG-INFO +0 -299
- {podstack-1.2.0 → podstack-1.2.1}/LICENSE +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack/annotations.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack/exceptions.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack/execution.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack/gpu_runner.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack/models.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack/notebook.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack/registry/__init__.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack/registry/client.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack/registry/exceptions.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack/registry/experiment.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack/registry/model.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack/registry/model_utils.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack.egg-info/SOURCES.txt +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack.egg-info/dependency_links.txt +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack.egg-info/requires.txt +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack.egg-info/top_level.txt +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack_gpu/__init__.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack_gpu/app.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack_gpu/exceptions.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack_gpu/image.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack_gpu/runner.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack_gpu/secret.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack_gpu/utils.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/podstack_gpu/volume.py +0 -0
- {podstack-1.2.0 → podstack-1.2.1}/setup.cfg +0 -0
podstack-1.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: podstack
|
|
3
|
+
Version: 1.2.1
|
|
4
|
+
Summary: Official Python SDK for Podstack GPU Notebook Platform
|
|
5
|
+
Author-email: Podstack <support@podstack.ai>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://podstack.ai
|
|
8
|
+
Project-URL: Documentation, https://docs.podstack.ai
|
|
9
|
+
Project-URL: Repository, https://github.com/podstack/podstack-python
|
|
10
|
+
Project-URL: Issues, https://github.com/podstack/podstack-python/issues
|
|
11
|
+
Keywords: gpu,notebook,machine-learning,deep-learning,cloud,jupyter
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
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
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Python: >=3.8
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: httpx>=0.24.0
|
|
28
|
+
Requires-Dist: requests>=2.28.0
|
|
29
|
+
Provides-Extra: torch
|
|
30
|
+
Requires-Dist: torch; extra == "torch"
|
|
31
|
+
Provides-Extra: tensorflow
|
|
32
|
+
Requires-Dist: tensorflow; extra == "tensorflow"
|
|
33
|
+
Provides-Extra: sklearn
|
|
34
|
+
Requires-Dist: scikit-learn; extra == "sklearn"
|
|
35
|
+
Provides-Extra: huggingface
|
|
36
|
+
Requires-Dist: transformers; extra == "huggingface"
|
|
37
|
+
Requires-Dist: safetensors; extra == "huggingface"
|
|
38
|
+
Provides-Extra: all
|
|
39
|
+
Requires-Dist: torch; extra == "all"
|
|
40
|
+
Requires-Dist: tensorflow; extra == "all"
|
|
41
|
+
Requires-Dist: scikit-learn; extra == "all"
|
|
42
|
+
Requires-Dist: transformers; extra == "all"
|
|
43
|
+
Requires-Dist: safetensors; extra == "all"
|
|
44
|
+
Provides-Extra: dev
|
|
45
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
46
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
47
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
48
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
49
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
50
|
+
Requires-Dist: ruff>=0.0.270; extra == "dev"
|
|
51
|
+
Dynamic: license-file
|
|
52
|
+
|
|
53
|
+
# Podstack Python SDK
|
|
54
|
+
|
|
55
|
+
Official Python SDK for the Podstack GPU Platform. Run ML workloads on remote GPUs with simple decorators, track experiments, and manage models.
|
|
56
|
+
|
|
57
|
+
## Installation
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install podstack
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
With optional dependencies:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pip install podstack[torch] # PyTorch support
|
|
67
|
+
pip install podstack[huggingface] # HuggingFace Transformers
|
|
68
|
+
pip install podstack[all] # All ML frameworks
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Quick Start
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
import podstack
|
|
75
|
+
|
|
76
|
+
# Initialize the SDK
|
|
77
|
+
podstack.init(
|
|
78
|
+
api_key="your-api-key",
|
|
79
|
+
project_id="your-project-id"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# Run a function on a remote GPU with a single decorator
|
|
83
|
+
@podstack.gpu(type="L40S", fraction=100)
|
|
84
|
+
def train():
|
|
85
|
+
import torch
|
|
86
|
+
print(f"GPU: {torch.cuda.get_device_name(0)}")
|
|
87
|
+
return {"status": "done"}
|
|
88
|
+
|
|
89
|
+
result = train() # Executes on remote GPU!
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Decorators & Annotations
|
|
93
|
+
|
|
94
|
+
Podstack provides decorators that turn any Python function into a remote GPU workload with built-in experiment tracking.
|
|
95
|
+
|
|
96
|
+
### `@podstack.gpu` - Remote GPU Execution
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
import podstack
|
|
100
|
+
|
|
101
|
+
# Basic GPU execution
|
|
102
|
+
@podstack.gpu(type="L40S")
|
|
103
|
+
def train_model():
|
|
104
|
+
import torch
|
|
105
|
+
model = torch.nn.Linear(768, 10).cuda()
|
|
106
|
+
return {"params": sum(p.numel() for p in model.parameters())}
|
|
107
|
+
|
|
108
|
+
result = train_model()
|
|
109
|
+
|
|
110
|
+
# Specify GPU type, count, and fraction
|
|
111
|
+
@podstack.gpu(type="A100-80G", count=2, fraction=100)
|
|
112
|
+
def train_large_model():
|
|
113
|
+
import torch
|
|
114
|
+
print(f"GPUs available: {torch.cuda.device_count()}")
|
|
115
|
+
|
|
116
|
+
# Install pip packages on the fly
|
|
117
|
+
@podstack.gpu(type="L40S", pip=["transformers", "datasets", "accelerate"])
|
|
118
|
+
def finetune_llm():
|
|
119
|
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
|
120
|
+
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf")
|
|
121
|
+
...
|
|
122
|
+
|
|
123
|
+
# Use uv for faster package installation
|
|
124
|
+
@podstack.gpu(type="L40S", uv=["torch", "transformers"])
|
|
125
|
+
def fast_setup():
|
|
126
|
+
...
|
|
127
|
+
|
|
128
|
+
# Install from requirements.txt
|
|
129
|
+
@podstack.gpu(type="L40S", requirements="requirements.txt", use_uv=True)
|
|
130
|
+
def train_with_deps():
|
|
131
|
+
...
|
|
132
|
+
|
|
133
|
+
# Use conda packages
|
|
134
|
+
@podstack.gpu(type="L40S", conda="cudatoolkit=11.8")
|
|
135
|
+
def train_with_conda():
|
|
136
|
+
...
|
|
137
|
+
|
|
138
|
+
# Use a pre-built environment
|
|
139
|
+
@podstack.gpu(type="L40S", env="nlp")
|
|
140
|
+
def nlp_task():
|
|
141
|
+
...
|
|
142
|
+
|
|
143
|
+
# Set execution timeout (default: 3600s)
|
|
144
|
+
@podstack.gpu(type="L40S", timeout=7200)
|
|
145
|
+
def long_training():
|
|
146
|
+
...
|
|
147
|
+
|
|
148
|
+
# Disable remote execution (run locally for debugging)
|
|
149
|
+
@podstack.gpu(type="L40S", remote=False)
|
|
150
|
+
def debug_locally():
|
|
151
|
+
print("This runs on your local machine")
|
|
152
|
+
|
|
153
|
+
# Use as a context manager
|
|
154
|
+
with podstack.gpu(type="A100-80G", count=2) as cfg:
|
|
155
|
+
print(f"GPU config set: {cfg.type}")
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Available GPU types:** `T4`, `L4`, `A10`, `L40S`, `A100-40G`, `A100-80G`, `H100`
|
|
159
|
+
|
|
160
|
+
**Available environments:** `ml`, `nlp`, `cv`, `audio`, `tabular`, `rl`, `scientific`
|
|
161
|
+
|
|
162
|
+
### `@podstack.experiment` - Experiment Tracking
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
import podstack
|
|
166
|
+
|
|
167
|
+
# As a decorator
|
|
168
|
+
@podstack.experiment(name="transformer-experiments")
|
|
169
|
+
def run_experiment():
|
|
170
|
+
...
|
|
171
|
+
|
|
172
|
+
# As a context manager
|
|
173
|
+
with podstack.experiment(name="transformer-experiments") as exp:
|
|
174
|
+
print(f"Experiment ID: {exp.id}")
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### `@podstack.run` - Run Tracking
|
|
178
|
+
|
|
179
|
+
Automatically tracks execution time and GPU configuration.
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
import podstack
|
|
183
|
+
|
|
184
|
+
# As a decorator
|
|
185
|
+
@podstack.experiment(name="my-experiment")
|
|
186
|
+
@podstack.run(name="training-v1", track_gpu=True)
|
|
187
|
+
def train():
|
|
188
|
+
podstack.registry.log_params({"lr": 0.001, "batch_size": 32})
|
|
189
|
+
for epoch in range(10):
|
|
190
|
+
loss = 1.0 / (epoch + 1)
|
|
191
|
+
podstack.registry.log_metrics({"loss": loss}, step=epoch)
|
|
192
|
+
|
|
193
|
+
# As a context manager
|
|
194
|
+
with podstack.run(name="training-v1") as run:
|
|
195
|
+
podstack.registry.log_params({"lr": 0.001})
|
|
196
|
+
podstack.registry.log_metrics({"loss": 0.5}, step=1)
|
|
197
|
+
print(f"Run ID: {run.id}")
|
|
198
|
+
|
|
199
|
+
# With tags
|
|
200
|
+
@podstack.run(name="ablation-study", tags={"variant": "no-dropout"})
|
|
201
|
+
def ablation():
|
|
202
|
+
...
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### `@podstack.model` - Model Registration
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
import podstack
|
|
209
|
+
|
|
210
|
+
# Register model after function completes
|
|
211
|
+
@podstack.experiment(name="my-experiment")
|
|
212
|
+
@podstack.run(name="training-v1")
|
|
213
|
+
@podstack.model.register(name="my-classifier")
|
|
214
|
+
def train_and_save():
|
|
215
|
+
import torch
|
|
216
|
+
model = torch.nn.Linear(768, 10)
|
|
217
|
+
torch.save(model.state_dict(), "model.pt")
|
|
218
|
+
podstack.registry.log_artifact("model.pt", "model")
|
|
219
|
+
|
|
220
|
+
# Promote model to production after validation
|
|
221
|
+
@podstack.model.promote(name="my-classifier", version=1, stage="production")
|
|
222
|
+
def validate_and_promote():
|
|
223
|
+
# Run validation checks
|
|
224
|
+
accuracy = 0.95
|
|
225
|
+
assert accuracy > 0.90, "Model doesn't meet threshold"
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Combining Decorators
|
|
229
|
+
|
|
230
|
+
Stack decorators for a complete ML workflow:
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
import podstack
|
|
234
|
+
|
|
235
|
+
podstack.init(api_key="your-api-key", project_id="your-project-id")
|
|
236
|
+
|
|
237
|
+
@podstack.gpu(type="L40S", pip=["transformers", "datasets"])
|
|
238
|
+
@podstack.experiment(name="sentiment-analysis")
|
|
239
|
+
@podstack.run(name="bert-finetune-v1", track_gpu=True)
|
|
240
|
+
@podstack.model.register(name="sentiment-bert")
|
|
241
|
+
def full_pipeline():
|
|
242
|
+
from transformers import AutoModelForSequenceClassification, Trainer
|
|
243
|
+
|
|
244
|
+
model = AutoModelForSequenceClassification.from_pretrained("bert-base-uncased")
|
|
245
|
+
|
|
246
|
+
# Log hyperparameters
|
|
247
|
+
podstack.registry.log_params({
|
|
248
|
+
"model": "bert-base-uncased",
|
|
249
|
+
"learning_rate": 2e-5,
|
|
250
|
+
"epochs": 3
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
# Train...
|
|
254
|
+
podstack.registry.log_metrics({"accuracy": 0.92, "f1": 0.89})
|
|
255
|
+
|
|
256
|
+
return {"accuracy": 0.92}
|
|
257
|
+
|
|
258
|
+
result = full_pipeline() # Runs on remote L40S GPU with full tracking
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Registry - Experiment Tracking & Model Management
|
|
262
|
+
|
|
263
|
+
### Initialize
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
from podstack import registry
|
|
267
|
+
|
|
268
|
+
registry.init(
|
|
269
|
+
api_key="your-api-key",
|
|
270
|
+
project_id="your-project-id"
|
|
271
|
+
)
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Track Experiments and Runs
|
|
275
|
+
|
|
276
|
+
```python
|
|
277
|
+
from podstack import registry
|
|
278
|
+
|
|
279
|
+
# Set experiment
|
|
280
|
+
registry.set_experiment("my-experiment")
|
|
281
|
+
|
|
282
|
+
# Start a tracked run
|
|
283
|
+
with registry.start_run(name="training-v1") as run:
|
|
284
|
+
# Log hyperparameters
|
|
285
|
+
registry.log_params({
|
|
286
|
+
"learning_rate": 0.001,
|
|
287
|
+
"batch_size": 32,
|
|
288
|
+
"epochs": 10,
|
|
289
|
+
"optimizer": "adam"
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
# Log metrics at each step
|
|
293
|
+
for epoch in range(10):
|
|
294
|
+
loss = train_epoch()
|
|
295
|
+
accuracy = evaluate()
|
|
296
|
+
registry.log_metrics({"loss": loss, "accuracy": accuracy}, step=epoch)
|
|
297
|
+
|
|
298
|
+
# Set tags
|
|
299
|
+
registry.set_tag("framework", "pytorch")
|
|
300
|
+
|
|
301
|
+
# Log artifacts
|
|
302
|
+
registry.log_artifact("model.pt", "model")
|
|
303
|
+
registry.log_artifact("training_curves.png", "plots")
|
|
304
|
+
|
|
305
|
+
# Log dataset metadata
|
|
306
|
+
registry.log_dataset(
|
|
307
|
+
name="imdb-reviews",
|
|
308
|
+
path="s3://datasets/imdb",
|
|
309
|
+
num_rows=50000,
|
|
310
|
+
num_features=2
|
|
311
|
+
)
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Log and Load Models
|
|
315
|
+
|
|
316
|
+
```python
|
|
317
|
+
from podstack import registry
|
|
318
|
+
|
|
319
|
+
# Log a model object (auto-detects framework)
|
|
320
|
+
registry.log_model(model, artifact_path="model", framework="pytorch")
|
|
321
|
+
|
|
322
|
+
# Register in model registry
|
|
323
|
+
registry.register_model(
|
|
324
|
+
name="my-classifier",
|
|
325
|
+
run_id=run.id,
|
|
326
|
+
description="BERT sentiment classifier"
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
# Promote to production
|
|
330
|
+
registry.set_model_stage("my-classifier", version=1, stage="production")
|
|
331
|
+
|
|
332
|
+
# Set aliases
|
|
333
|
+
registry.set_model_alias("my-classifier", alias="champion", version=1)
|
|
334
|
+
|
|
335
|
+
# Load model from registry
|
|
336
|
+
model = registry.load_model("my-classifier", stage="production")
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Compare Runs
|
|
340
|
+
|
|
341
|
+
```python
|
|
342
|
+
from podstack import registry
|
|
343
|
+
|
|
344
|
+
# Compare multiple runs
|
|
345
|
+
comparison = registry.compare_runs(
|
|
346
|
+
run_ids=["run-id-1", "run-id-2", "run-id-3"],
|
|
347
|
+
metric_keys=["loss", "accuracy"]
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
# Get metric history for a run
|
|
351
|
+
history = registry.get_metric_history("run-id-1", "loss")
|
|
352
|
+
for point in history:
|
|
353
|
+
print(f"Step {point.step}: {point.value}")
|
|
354
|
+
|
|
355
|
+
# Search runs
|
|
356
|
+
runs = registry.search_runs(
|
|
357
|
+
experiment_id="exp-id",
|
|
358
|
+
status="completed",
|
|
359
|
+
max_results=50
|
|
360
|
+
)
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### List and Browse
|
|
364
|
+
|
|
365
|
+
```python
|
|
366
|
+
from podstack import registry
|
|
367
|
+
|
|
368
|
+
# List experiments
|
|
369
|
+
experiments = registry.list_experiments()
|
|
370
|
+
|
|
371
|
+
# List models
|
|
372
|
+
models = registry.list_models()
|
|
373
|
+
|
|
374
|
+
# Download artifacts
|
|
375
|
+
registry.download_artifact("run-id", "model/model.pt", "./downloads/")
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## GPU Runner - Direct Code Execution
|
|
379
|
+
|
|
380
|
+
For running code strings directly on GPUs without decorators:
|
|
381
|
+
|
|
382
|
+
```python
|
|
383
|
+
import podstack
|
|
384
|
+
|
|
385
|
+
podstack.init(api_key="your-api-key", project_id="your-project-id")
|
|
386
|
+
|
|
387
|
+
# Run code on a remote GPU
|
|
388
|
+
result = podstack.run_on_gpu('''
|
|
389
|
+
import torch
|
|
390
|
+
print(f"GPU: {torch.cuda.get_device_name(0)}")
|
|
391
|
+
print(f"Memory: {torch.cuda.get_device_properties(0).total_mem / 1e9:.1f} GB")
|
|
392
|
+
''', gpu="L40S")
|
|
393
|
+
|
|
394
|
+
print(result.output)
|
|
395
|
+
print(f"Success: {result.success}")
|
|
396
|
+
print(f"Duration: {result.duration_seconds}s")
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
## Client API
|
|
400
|
+
|
|
401
|
+
For direct API access to notebooks and executions:
|
|
402
|
+
|
|
403
|
+
```python
|
|
404
|
+
from podstack import Client
|
|
405
|
+
|
|
406
|
+
client = Client(api_key="your-api-key")
|
|
407
|
+
|
|
408
|
+
# Create a notebook
|
|
409
|
+
notebook = client.sync_create_notebook(name="experiment", gpu_type="L40S")
|
|
410
|
+
print(f"JupyterLab: {notebook.jupyter_url}")
|
|
411
|
+
|
|
412
|
+
# Run code
|
|
413
|
+
result = client.sync_run("print('Hello GPU!')", gpu_type="L40S")
|
|
414
|
+
print(result.output)
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
## Error Handling
|
|
418
|
+
|
|
419
|
+
```python
|
|
420
|
+
from podstack import (
|
|
421
|
+
PodstackError,
|
|
422
|
+
AuthenticationError,
|
|
423
|
+
GPUNotAvailableError,
|
|
424
|
+
RateLimitError,
|
|
425
|
+
ExecutionTimeoutError
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
try:
|
|
429
|
+
result = train()
|
|
430
|
+
except AuthenticationError:
|
|
431
|
+
print("Invalid API key")
|
|
432
|
+
except GPUNotAvailableError as e:
|
|
433
|
+
print(f"GPU not available")
|
|
434
|
+
except RateLimitError as e:
|
|
435
|
+
print(f"Rate limited, retry after {e.retry_after}s")
|
|
436
|
+
except ExecutionTimeoutError as e:
|
|
437
|
+
print(f"Execution timed out: {e.execution_id}")
|
|
438
|
+
except PodstackError as e:
|
|
439
|
+
print(f"Error: {e.message}")
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
## Configuration
|
|
443
|
+
|
|
444
|
+
```python
|
|
445
|
+
import podstack
|
|
446
|
+
|
|
447
|
+
# Option 1: Initialize explicitly
|
|
448
|
+
podstack.init(
|
|
449
|
+
api_key="your-api-key",
|
|
450
|
+
project_id="your-project-id",
|
|
451
|
+
api_url="https://api.podstack.ai/v1", # optional
|
|
452
|
+
registry_url="https://registry.podstack.ai" # optional
|
|
453
|
+
)
|
|
454
|
+
|
|
455
|
+
# Option 2: Environment variables
|
|
456
|
+
# PODSTACK_API_KEY=your-api-key
|
|
457
|
+
# PODSTACK_PROJECT_ID=your-project-id
|
|
458
|
+
# PODSTACK_API_URL=https://api.podstack.ai/v1
|
|
459
|
+
# PODSTACK_REGISTRY_URL=https://registry.podstack.ai
|
|
460
|
+
|
|
461
|
+
# Option 3: Auto-init (set PODSTACK_AUTO_INIT=1)
|
|
462
|
+
# SDK auto-initializes from env vars at import time
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
## License
|
|
466
|
+
|
|
467
|
+
MIT License - see LICENSE for details.
|