usfbios 1.0.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.
- usfbios-1.0.0/.gitignore +67 -0
- usfbios-1.0.0/LICENSE +21 -0
- usfbios-1.0.0/PKG-INFO +297 -0
- usfbios-1.0.0/README.md +270 -0
- usfbios-1.0.0/pyproject.toml +40 -0
- usfbios-1.0.0/src/usfbios/__init__.py +97 -0
- usfbios-1.0.0/src/usfbios/_client.py +165 -0
- usfbios-1.0.0/src/usfbios/_types.py +616 -0
- usfbios-1.0.0/src/usfbios/datasets.py +187 -0
- usfbios-1.0.0/src/usfbios/gpu.py +84 -0
- usfbios-1.0.0/src/usfbios/models.py +93 -0
- usfbios-1.0.0/src/usfbios/training.py +205 -0
- usfbios-1.0.0/src/usfbios/wallet.py +33 -0
usfbios-1.0.0/.gitignore
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Environment
|
|
2
|
+
.env
|
|
3
|
+
.env.local
|
|
4
|
+
.env.*.local
|
|
5
|
+
!.env.example
|
|
6
|
+
|
|
7
|
+
# Per-service env files (contain secrets)
|
|
8
|
+
services/*/.env
|
|
9
|
+
services/*/.env.local
|
|
10
|
+
platform/*/.env
|
|
11
|
+
platform/*/.env.local
|
|
12
|
+
|
|
13
|
+
# Keep .env.example files tracked
|
|
14
|
+
!services/*/.env.example
|
|
15
|
+
!platform/*/.env.example
|
|
16
|
+
|
|
17
|
+
# Go
|
|
18
|
+
vendor/
|
|
19
|
+
main
|
|
20
|
+
*.exe
|
|
21
|
+
*.exe~
|
|
22
|
+
*.dll
|
|
23
|
+
*.so
|
|
24
|
+
*.dylib
|
|
25
|
+
*.test
|
|
26
|
+
*.out
|
|
27
|
+
go.work
|
|
28
|
+
go.work.sum
|
|
29
|
+
|
|
30
|
+
# Python
|
|
31
|
+
__pycache__/
|
|
32
|
+
*.py[cod]
|
|
33
|
+
*$py.class
|
|
34
|
+
*.so
|
|
35
|
+
.Python
|
|
36
|
+
env/
|
|
37
|
+
venv/
|
|
38
|
+
.venv/
|
|
39
|
+
*.egg-info/
|
|
40
|
+
dist/
|
|
41
|
+
build/
|
|
42
|
+
|
|
43
|
+
# Node
|
|
44
|
+
node_modules/
|
|
45
|
+
.next/
|
|
46
|
+
out/
|
|
47
|
+
.turbo/
|
|
48
|
+
|
|
49
|
+
# IDE
|
|
50
|
+
.idea/
|
|
51
|
+
.vscode/
|
|
52
|
+
*.swp
|
|
53
|
+
*.swo
|
|
54
|
+
*~
|
|
55
|
+
.DS_Store
|
|
56
|
+
|
|
57
|
+
# Docker
|
|
58
|
+
docker-compose.override.yml
|
|
59
|
+
|
|
60
|
+
# Logs
|
|
61
|
+
*.log
|
|
62
|
+
logs/
|
|
63
|
+
|
|
64
|
+
# Coverage
|
|
65
|
+
coverage/
|
|
66
|
+
*.cover
|
|
67
|
+
htmlcov/
|
usfbios-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 USF Inc
|
|
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.
|
usfbios-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: usfbios
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Official Python SDK for the USF BIOS fine-tuning platform API
|
|
5
|
+
Project-URL: Homepage, https://bios.us.com
|
|
6
|
+
Project-URL: Documentation, https://bios.us.com/docs
|
|
7
|
+
Author-email: USF Inc <bios@us.inc>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: fine-tuning,llm,machine-learning,sdk,usfbios
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.8
|
|
25
|
+
Requires-Dist: requests>=2.28.0
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# usfbios
|
|
29
|
+
|
|
30
|
+
Official Python SDK for the [USF BIOS](https://bios.us.com) fine-tuning platform API.
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install usfbios
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Quick Start
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from usfbios import USFBios
|
|
42
|
+
|
|
43
|
+
client = USFBios(api_key="sk_live_...")
|
|
44
|
+
|
|
45
|
+
# Search for models
|
|
46
|
+
result = client.models.search(query="llama", type="llm", limit=5)
|
|
47
|
+
for model in result["models"]:
|
|
48
|
+
print(f"{model['id']} -- {model['totalParams']}B params")
|
|
49
|
+
|
|
50
|
+
# Create a training job
|
|
51
|
+
job = client.training.create(
|
|
52
|
+
model="meta-llama/Llama-3.1-8B-Instruct",
|
|
53
|
+
dataset_id="ds_abc123",
|
|
54
|
+
method="sft",
|
|
55
|
+
adapter="lora",
|
|
56
|
+
epochs=3,
|
|
57
|
+
learning_rate=2e-4,
|
|
58
|
+
lora_rank=16,
|
|
59
|
+
)
|
|
60
|
+
print(f"Job {job['id']} created -- status: {job['status']}")
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Authentication
|
|
64
|
+
|
|
65
|
+
The SDK supports two authentication methods:
|
|
66
|
+
|
|
67
|
+
**API Key** (recommended):
|
|
68
|
+
```python
|
|
69
|
+
client = USFBios(api_key="sk_live_...")
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**JWT Access Token**:
|
|
73
|
+
```python
|
|
74
|
+
client = USFBios(
|
|
75
|
+
access_token="eyJhbG...",
|
|
76
|
+
org_id="org_abc123",
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Configuration
|
|
81
|
+
|
|
82
|
+
| Parameter | Type | Default | Description |
|
|
83
|
+
|---|---|---|---|
|
|
84
|
+
| `api_key` | `str` | `None` | API key for authentication (prefix: `sk_live_`) |
|
|
85
|
+
| `access_token` | `str` | `None` | JWT access token (alternative to API key) |
|
|
86
|
+
| `org_id` | `str` | `None` | Organization ID (required for JWT auth) |
|
|
87
|
+
| `workspace_id` | `str` | `None` | Workspace ID (optional, overrides key default) |
|
|
88
|
+
| `base_url` | `str` | `https://api-bios.us.inc` | API base URL |
|
|
89
|
+
| `timeout` | `float` | `30.0` | Request timeout in seconds |
|
|
90
|
+
|
|
91
|
+
## Resources
|
|
92
|
+
|
|
93
|
+
### Models
|
|
94
|
+
|
|
95
|
+
Search the HuggingFace model catalog, fetch training configs, and check adapter compatibility.
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
# Search models
|
|
99
|
+
result = client.models.search(query="llama", type="llm", limit=10)
|
|
100
|
+
|
|
101
|
+
# Get model config
|
|
102
|
+
config = client.models.get_config("meta-llama/Llama-3.1-8B")
|
|
103
|
+
print(f"{config['totalParams']}B params, MoE: {config['isMoE']}")
|
|
104
|
+
|
|
105
|
+
# Check adapter compatibility
|
|
106
|
+
compat = client.models.get_adapter_compatibility(
|
|
107
|
+
model_type="llama",
|
|
108
|
+
training_method="rlhf",
|
|
109
|
+
rlhf_algorithm="dpo",
|
|
110
|
+
)
|
|
111
|
+
usable = [a for a in compat["adapters"] if a["compatible"]]
|
|
112
|
+
print(f"{len(usable)} compatible adapters")
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Datasets
|
|
116
|
+
|
|
117
|
+
Upload, import, preview, and manage training datasets.
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
# List datasets
|
|
121
|
+
datasets = client.datasets.list()
|
|
122
|
+
|
|
123
|
+
# Upload a dataset
|
|
124
|
+
uploaded = client.datasets.upload(
|
|
125
|
+
file_path="./training_data.jsonl",
|
|
126
|
+
name="My SFT Dataset",
|
|
127
|
+
)
|
|
128
|
+
print(f"Uploaded: {uploaded['id']}")
|
|
129
|
+
|
|
130
|
+
# Import from HuggingFace
|
|
131
|
+
imported = client.datasets.import_from_huggingface(
|
|
132
|
+
repo_id="databricks/dolly-15k",
|
|
133
|
+
integration_id="int_abc123",
|
|
134
|
+
name="Dolly 15k",
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# Preview dataset rows
|
|
138
|
+
preview = client.datasets.preview("ds_abc123", page=1, page_size=5)
|
|
139
|
+
print(preview["columns"])
|
|
140
|
+
|
|
141
|
+
# Validate before uploading
|
|
142
|
+
result = client.datasets.validate("./data.jsonl")
|
|
143
|
+
if result["valid"]:
|
|
144
|
+
print(f"Valid {result['format']} with {result['row_count']} rows")
|
|
145
|
+
else:
|
|
146
|
+
print("Errors:", result["errors"])
|
|
147
|
+
|
|
148
|
+
# Search HuggingFace Hub
|
|
149
|
+
hub_results = client.datasets.search_hub(query="code instruct")
|
|
150
|
+
|
|
151
|
+
# Preview a Hub dataset
|
|
152
|
+
hub_preview = client.datasets.preview_hub(
|
|
153
|
+
dataset_id="databricks/dolly-15k",
|
|
154
|
+
split="train",
|
|
155
|
+
limit=5,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# Get format specs
|
|
159
|
+
specs = client.datasets.get_format_specs()
|
|
160
|
+
|
|
161
|
+
# Get storage usage
|
|
162
|
+
usage = client.datasets.get_storage_usage()
|
|
163
|
+
|
|
164
|
+
# Delete a dataset
|
|
165
|
+
client.datasets.delete("ds_abc123")
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Training
|
|
169
|
+
|
|
170
|
+
Create, monitor, stop, and resume fine-tuning jobs.
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
# Create a training job
|
|
174
|
+
job = client.training.create(
|
|
175
|
+
model="meta-llama/Llama-3.1-8B-Instruct",
|
|
176
|
+
dataset_id="ds_abc123",
|
|
177
|
+
method="sft",
|
|
178
|
+
adapter="lora",
|
|
179
|
+
epochs=3,
|
|
180
|
+
learning_rate=2e-4,
|
|
181
|
+
lora_rank=16,
|
|
182
|
+
lora_alpha=32,
|
|
183
|
+
gpu_type="A100_80GB",
|
|
184
|
+
gpu_count=1,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# List jobs
|
|
188
|
+
jobs = client.training.list(status="running")
|
|
189
|
+
|
|
190
|
+
# Get job details
|
|
191
|
+
job = client.training.get("job_abc123")
|
|
192
|
+
print(f"Status: {job['status']}, Progress: {job.get('progress', 0)}%")
|
|
193
|
+
|
|
194
|
+
# Get metrics
|
|
195
|
+
metrics = client.training.get_metrics("job_abc123")
|
|
196
|
+
print(f"Current loss: {metrics.get('current_loss')}")
|
|
197
|
+
|
|
198
|
+
# Get checkpoints
|
|
199
|
+
checkpoints = client.training.get_checkpoints("job_abc123")
|
|
200
|
+
for cp in checkpoints:
|
|
201
|
+
print(f"Step {cp['step']}: loss {cp.get('loss')}")
|
|
202
|
+
|
|
203
|
+
# Get logs
|
|
204
|
+
logs = client.training.get_logs("job_abc123")
|
|
205
|
+
for line in logs["logs"]:
|
|
206
|
+
print(line)
|
|
207
|
+
|
|
208
|
+
# Stop a job
|
|
209
|
+
client.training.stop("job_abc123", keep_data=True)
|
|
210
|
+
|
|
211
|
+
# Resume a stopped job
|
|
212
|
+
client.training.resume("job_abc123")
|
|
213
|
+
|
|
214
|
+
# Delete a checkpoint
|
|
215
|
+
client.training.delete_checkpoint("job_abc123", "cp_xyz789")
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Wallet
|
|
219
|
+
|
|
220
|
+
View wallet balance and transaction history.
|
|
221
|
+
|
|
222
|
+
```python
|
|
223
|
+
# Get balance
|
|
224
|
+
balance = client.wallet.get_balance()
|
|
225
|
+
print(f"Balance: ${balance['balance_cents'] / 100:.2f}")
|
|
226
|
+
print(f"Available: ${balance['available_cents'] / 100:.2f}")
|
|
227
|
+
|
|
228
|
+
# List transactions
|
|
229
|
+
txns = client.wallet.get_transactions(limit=20)
|
|
230
|
+
for t in txns:
|
|
231
|
+
print(f"{t['type']}: ${t['amount_cents'] / 100:.2f} -- {t.get('description')}")
|
|
232
|
+
|
|
233
|
+
# Get pricing
|
|
234
|
+
pricing = client.wallet.get_pricing()
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### GPU
|
|
238
|
+
|
|
239
|
+
View GPU pricing and get hardware recommendations.
|
|
240
|
+
|
|
241
|
+
```python
|
|
242
|
+
# Get all GPU pricing
|
|
243
|
+
pricing = client.gpu.get_pricing()
|
|
244
|
+
for gpu in pricing["gpus"]:
|
|
245
|
+
print(f"{gpu['display_name']}: {gpu['price_display']} -- {gpu['vram_gb']}GB VRAM")
|
|
246
|
+
|
|
247
|
+
# Get recommended GPU for a model
|
|
248
|
+
rec = client.gpu.get_recommended("meta-llama/Llama-3.1-8B-Instruct")
|
|
249
|
+
if rec:
|
|
250
|
+
print(f"Recommended: {rec['display_name']} x{rec['recommended_count']}")
|
|
251
|
+
print(f"Total VRAM: {rec['total_vram_gb']}GB")
|
|
252
|
+
print(f"Cost: ${rec['estimated_cost_per_hour_cents'] / 100:.2f}/hr")
|
|
253
|
+
print(f"Reason: {rec['reason']}")
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Introspect
|
|
257
|
+
|
|
258
|
+
Discover the permissions and scope of your API key.
|
|
259
|
+
|
|
260
|
+
```python
|
|
261
|
+
info = client.introspect()
|
|
262
|
+
print(f"Org: {info['org']['name']}")
|
|
263
|
+
print(f"Scopes: {', '.join(info['scopes'])}")
|
|
264
|
+
print(f"Allowed tools: {len(info['allowed_mcp_tools'])}")
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Error Handling
|
|
268
|
+
|
|
269
|
+
All API errors raise `ApiError` with `status`, `code`, `request_id`, and `message` attributes.
|
|
270
|
+
|
|
271
|
+
```python
|
|
272
|
+
from usfbios import USFBios, ApiError
|
|
273
|
+
|
|
274
|
+
client = USFBios(api_key="sk_live_...")
|
|
275
|
+
|
|
276
|
+
try:
|
|
277
|
+
job = client.training.get("bad_id")
|
|
278
|
+
except ApiError as e:
|
|
279
|
+
if e.status == 404:
|
|
280
|
+
print("Job not found")
|
|
281
|
+
elif e.status == 401:
|
|
282
|
+
print("Invalid API key")
|
|
283
|
+
elif e.status == 403:
|
|
284
|
+
print("Insufficient permissions")
|
|
285
|
+
else:
|
|
286
|
+
print(f"API error {e.status}: {e.message}")
|
|
287
|
+
if e.request_id:
|
|
288
|
+
print(f"Request ID: {e.request_id}")
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Python Version Support
|
|
292
|
+
|
|
293
|
+
- Python 3.8+
|
|
294
|
+
|
|
295
|
+
## License
|
|
296
|
+
|
|
297
|
+
MIT
|
usfbios-1.0.0/README.md
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# usfbios
|
|
2
|
+
|
|
3
|
+
Official Python SDK for the [USF BIOS](https://bios.us.com) fine-tuning platform API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install usfbios
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from usfbios import USFBios
|
|
15
|
+
|
|
16
|
+
client = USFBios(api_key="sk_live_...")
|
|
17
|
+
|
|
18
|
+
# Search for models
|
|
19
|
+
result = client.models.search(query="llama", type="llm", limit=5)
|
|
20
|
+
for model in result["models"]:
|
|
21
|
+
print(f"{model['id']} -- {model['totalParams']}B params")
|
|
22
|
+
|
|
23
|
+
# Create a training job
|
|
24
|
+
job = client.training.create(
|
|
25
|
+
model="meta-llama/Llama-3.1-8B-Instruct",
|
|
26
|
+
dataset_id="ds_abc123",
|
|
27
|
+
method="sft",
|
|
28
|
+
adapter="lora",
|
|
29
|
+
epochs=3,
|
|
30
|
+
learning_rate=2e-4,
|
|
31
|
+
lora_rank=16,
|
|
32
|
+
)
|
|
33
|
+
print(f"Job {job['id']} created -- status: {job['status']}")
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Authentication
|
|
37
|
+
|
|
38
|
+
The SDK supports two authentication methods:
|
|
39
|
+
|
|
40
|
+
**API Key** (recommended):
|
|
41
|
+
```python
|
|
42
|
+
client = USFBios(api_key="sk_live_...")
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**JWT Access Token**:
|
|
46
|
+
```python
|
|
47
|
+
client = USFBios(
|
|
48
|
+
access_token="eyJhbG...",
|
|
49
|
+
org_id="org_abc123",
|
|
50
|
+
)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Configuration
|
|
54
|
+
|
|
55
|
+
| Parameter | Type | Default | Description |
|
|
56
|
+
|---|---|---|---|
|
|
57
|
+
| `api_key` | `str` | `None` | API key for authentication (prefix: `sk_live_`) |
|
|
58
|
+
| `access_token` | `str` | `None` | JWT access token (alternative to API key) |
|
|
59
|
+
| `org_id` | `str` | `None` | Organization ID (required for JWT auth) |
|
|
60
|
+
| `workspace_id` | `str` | `None` | Workspace ID (optional, overrides key default) |
|
|
61
|
+
| `base_url` | `str` | `https://api-bios.us.inc` | API base URL |
|
|
62
|
+
| `timeout` | `float` | `30.0` | Request timeout in seconds |
|
|
63
|
+
|
|
64
|
+
## Resources
|
|
65
|
+
|
|
66
|
+
### Models
|
|
67
|
+
|
|
68
|
+
Search the HuggingFace model catalog, fetch training configs, and check adapter compatibility.
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
# Search models
|
|
72
|
+
result = client.models.search(query="llama", type="llm", limit=10)
|
|
73
|
+
|
|
74
|
+
# Get model config
|
|
75
|
+
config = client.models.get_config("meta-llama/Llama-3.1-8B")
|
|
76
|
+
print(f"{config['totalParams']}B params, MoE: {config['isMoE']}")
|
|
77
|
+
|
|
78
|
+
# Check adapter compatibility
|
|
79
|
+
compat = client.models.get_adapter_compatibility(
|
|
80
|
+
model_type="llama",
|
|
81
|
+
training_method="rlhf",
|
|
82
|
+
rlhf_algorithm="dpo",
|
|
83
|
+
)
|
|
84
|
+
usable = [a for a in compat["adapters"] if a["compatible"]]
|
|
85
|
+
print(f"{len(usable)} compatible adapters")
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Datasets
|
|
89
|
+
|
|
90
|
+
Upload, import, preview, and manage training datasets.
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
# List datasets
|
|
94
|
+
datasets = client.datasets.list()
|
|
95
|
+
|
|
96
|
+
# Upload a dataset
|
|
97
|
+
uploaded = client.datasets.upload(
|
|
98
|
+
file_path="./training_data.jsonl",
|
|
99
|
+
name="My SFT Dataset",
|
|
100
|
+
)
|
|
101
|
+
print(f"Uploaded: {uploaded['id']}")
|
|
102
|
+
|
|
103
|
+
# Import from HuggingFace
|
|
104
|
+
imported = client.datasets.import_from_huggingface(
|
|
105
|
+
repo_id="databricks/dolly-15k",
|
|
106
|
+
integration_id="int_abc123",
|
|
107
|
+
name="Dolly 15k",
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# Preview dataset rows
|
|
111
|
+
preview = client.datasets.preview("ds_abc123", page=1, page_size=5)
|
|
112
|
+
print(preview["columns"])
|
|
113
|
+
|
|
114
|
+
# Validate before uploading
|
|
115
|
+
result = client.datasets.validate("./data.jsonl")
|
|
116
|
+
if result["valid"]:
|
|
117
|
+
print(f"Valid {result['format']} with {result['row_count']} rows")
|
|
118
|
+
else:
|
|
119
|
+
print("Errors:", result["errors"])
|
|
120
|
+
|
|
121
|
+
# Search HuggingFace Hub
|
|
122
|
+
hub_results = client.datasets.search_hub(query="code instruct")
|
|
123
|
+
|
|
124
|
+
# Preview a Hub dataset
|
|
125
|
+
hub_preview = client.datasets.preview_hub(
|
|
126
|
+
dataset_id="databricks/dolly-15k",
|
|
127
|
+
split="train",
|
|
128
|
+
limit=5,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Get format specs
|
|
132
|
+
specs = client.datasets.get_format_specs()
|
|
133
|
+
|
|
134
|
+
# Get storage usage
|
|
135
|
+
usage = client.datasets.get_storage_usage()
|
|
136
|
+
|
|
137
|
+
# Delete a dataset
|
|
138
|
+
client.datasets.delete("ds_abc123")
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Training
|
|
142
|
+
|
|
143
|
+
Create, monitor, stop, and resume fine-tuning jobs.
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
# Create a training job
|
|
147
|
+
job = client.training.create(
|
|
148
|
+
model="meta-llama/Llama-3.1-8B-Instruct",
|
|
149
|
+
dataset_id="ds_abc123",
|
|
150
|
+
method="sft",
|
|
151
|
+
adapter="lora",
|
|
152
|
+
epochs=3,
|
|
153
|
+
learning_rate=2e-4,
|
|
154
|
+
lora_rank=16,
|
|
155
|
+
lora_alpha=32,
|
|
156
|
+
gpu_type="A100_80GB",
|
|
157
|
+
gpu_count=1,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# List jobs
|
|
161
|
+
jobs = client.training.list(status="running")
|
|
162
|
+
|
|
163
|
+
# Get job details
|
|
164
|
+
job = client.training.get("job_abc123")
|
|
165
|
+
print(f"Status: {job['status']}, Progress: {job.get('progress', 0)}%")
|
|
166
|
+
|
|
167
|
+
# Get metrics
|
|
168
|
+
metrics = client.training.get_metrics("job_abc123")
|
|
169
|
+
print(f"Current loss: {metrics.get('current_loss')}")
|
|
170
|
+
|
|
171
|
+
# Get checkpoints
|
|
172
|
+
checkpoints = client.training.get_checkpoints("job_abc123")
|
|
173
|
+
for cp in checkpoints:
|
|
174
|
+
print(f"Step {cp['step']}: loss {cp.get('loss')}")
|
|
175
|
+
|
|
176
|
+
# Get logs
|
|
177
|
+
logs = client.training.get_logs("job_abc123")
|
|
178
|
+
for line in logs["logs"]:
|
|
179
|
+
print(line)
|
|
180
|
+
|
|
181
|
+
# Stop a job
|
|
182
|
+
client.training.stop("job_abc123", keep_data=True)
|
|
183
|
+
|
|
184
|
+
# Resume a stopped job
|
|
185
|
+
client.training.resume("job_abc123")
|
|
186
|
+
|
|
187
|
+
# Delete a checkpoint
|
|
188
|
+
client.training.delete_checkpoint("job_abc123", "cp_xyz789")
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Wallet
|
|
192
|
+
|
|
193
|
+
View wallet balance and transaction history.
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
# Get balance
|
|
197
|
+
balance = client.wallet.get_balance()
|
|
198
|
+
print(f"Balance: ${balance['balance_cents'] / 100:.2f}")
|
|
199
|
+
print(f"Available: ${balance['available_cents'] / 100:.2f}")
|
|
200
|
+
|
|
201
|
+
# List transactions
|
|
202
|
+
txns = client.wallet.get_transactions(limit=20)
|
|
203
|
+
for t in txns:
|
|
204
|
+
print(f"{t['type']}: ${t['amount_cents'] / 100:.2f} -- {t.get('description')}")
|
|
205
|
+
|
|
206
|
+
# Get pricing
|
|
207
|
+
pricing = client.wallet.get_pricing()
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### GPU
|
|
211
|
+
|
|
212
|
+
View GPU pricing and get hardware recommendations.
|
|
213
|
+
|
|
214
|
+
```python
|
|
215
|
+
# Get all GPU pricing
|
|
216
|
+
pricing = client.gpu.get_pricing()
|
|
217
|
+
for gpu in pricing["gpus"]:
|
|
218
|
+
print(f"{gpu['display_name']}: {gpu['price_display']} -- {gpu['vram_gb']}GB VRAM")
|
|
219
|
+
|
|
220
|
+
# Get recommended GPU for a model
|
|
221
|
+
rec = client.gpu.get_recommended("meta-llama/Llama-3.1-8B-Instruct")
|
|
222
|
+
if rec:
|
|
223
|
+
print(f"Recommended: {rec['display_name']} x{rec['recommended_count']}")
|
|
224
|
+
print(f"Total VRAM: {rec['total_vram_gb']}GB")
|
|
225
|
+
print(f"Cost: ${rec['estimated_cost_per_hour_cents'] / 100:.2f}/hr")
|
|
226
|
+
print(f"Reason: {rec['reason']}")
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Introspect
|
|
230
|
+
|
|
231
|
+
Discover the permissions and scope of your API key.
|
|
232
|
+
|
|
233
|
+
```python
|
|
234
|
+
info = client.introspect()
|
|
235
|
+
print(f"Org: {info['org']['name']}")
|
|
236
|
+
print(f"Scopes: {', '.join(info['scopes'])}")
|
|
237
|
+
print(f"Allowed tools: {len(info['allowed_mcp_tools'])}")
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Error Handling
|
|
241
|
+
|
|
242
|
+
All API errors raise `ApiError` with `status`, `code`, `request_id`, and `message` attributes.
|
|
243
|
+
|
|
244
|
+
```python
|
|
245
|
+
from usfbios import USFBios, ApiError
|
|
246
|
+
|
|
247
|
+
client = USFBios(api_key="sk_live_...")
|
|
248
|
+
|
|
249
|
+
try:
|
|
250
|
+
job = client.training.get("bad_id")
|
|
251
|
+
except ApiError as e:
|
|
252
|
+
if e.status == 404:
|
|
253
|
+
print("Job not found")
|
|
254
|
+
elif e.status == 401:
|
|
255
|
+
print("Invalid API key")
|
|
256
|
+
elif e.status == 403:
|
|
257
|
+
print("Insufficient permissions")
|
|
258
|
+
else:
|
|
259
|
+
print(f"API error {e.status}: {e.message}")
|
|
260
|
+
if e.request_id:
|
|
261
|
+
print(f"Request ID: {e.request_id}")
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Python Version Support
|
|
265
|
+
|
|
266
|
+
- Python 3.8+
|
|
267
|
+
|
|
268
|
+
## License
|
|
269
|
+
|
|
270
|
+
MIT
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "usfbios"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Official Python SDK for the USF BIOS fine-tuning platform API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "USF Inc", email = "bios@us.inc" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["usfbios", "fine-tuning", "llm", "machine-learning", "sdk"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 5 - Production/Stable",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.8",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
28
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
29
|
+
"Typing :: Typed",
|
|
30
|
+
]
|
|
31
|
+
dependencies = [
|
|
32
|
+
"requests>=2.28.0",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.urls]
|
|
36
|
+
Homepage = "https://bios.us.com"
|
|
37
|
+
Documentation = "https://bios.us.com/docs"
|
|
38
|
+
|
|
39
|
+
[tool.hatch.build.targets.wheel]
|
|
40
|
+
packages = ["src/usfbios"]
|