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.
@@ -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
+
@@ -0,0 +1,9 @@
1
+ include README.md
2
+ include LICENSE
3
+ include pyproject.toml
4
+ recursive-include colabhive *.py
5
+ recursive-exclude tests *
6
+ recursive-exclude examples *
7
+ global-exclude __pycache__
8
+ global-exclude *.py[cod]
9
+
@@ -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()