coreplexml 0.1.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.
- coreplexml-0.1.1/LICENSE +28 -0
- coreplexml-0.1.1/MANIFEST.in +2 -0
- coreplexml-0.1.1/PKG-INFO +156 -0
- coreplexml-0.1.1/README.md +114 -0
- coreplexml-0.1.1/coreplexml/__init__.py +21 -0
- coreplexml-0.1.1/coreplexml/_http.py +157 -0
- coreplexml-0.1.1/coreplexml/client.py +76 -0
- coreplexml-0.1.1/coreplexml/datasets.py +145 -0
- coreplexml-0.1.1/coreplexml/deployments.py +163 -0
- coreplexml-0.1.1/coreplexml/exceptions.py +57 -0
- coreplexml-0.1.1/coreplexml/experiments.py +126 -0
- coreplexml-0.1.1/coreplexml/models.py +108 -0
- coreplexml-0.1.1/coreplexml/privacy.py +198 -0
- coreplexml-0.1.1/coreplexml/projects.py +161 -0
- coreplexml-0.1.1/coreplexml/reports.py +118 -0
- coreplexml-0.1.1/coreplexml/studio.py +115 -0
- coreplexml-0.1.1/coreplexml/synthgen.py +171 -0
- coreplexml-0.1.1/coreplexml.egg-info/PKG-INFO +156 -0
- coreplexml-0.1.1/coreplexml.egg-info/SOURCES.txt +24 -0
- coreplexml-0.1.1/coreplexml.egg-info/dependency_links.txt +1 -0
- coreplexml-0.1.1/coreplexml.egg-info/requires.txt +1 -0
- coreplexml-0.1.1/coreplexml.egg-info/top_level.txt +1 -0
- coreplexml-0.1.1/pyproject.toml +3 -0
- coreplexml-0.1.1/setup.cfg +4 -0
- coreplexml-0.1.1/setup.py +39 -0
- coreplexml-0.1.1/tests/test_client.py +46 -0
coreplexml-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Business Source License 1.1 (BUSL-1.1)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Rodrigo Henríquez and Intellicore TI SpA
|
|
4
|
+
|
|
5
|
+
Use Limitation:
|
|
6
|
+
This Licensed Work may only be used, copied, modified, or distributed for non-commercial purposes, including academic study, personal experimentation, and non-commercial research.
|
|
7
|
+
|
|
8
|
+
Prohibited Uses:
|
|
9
|
+
You may NOT use the Licensed Work or any derivative works for any commercial purpose, including offering a service to third parties, developing commercial products, or any internal commercial advantage, without explicit, written permission from Intellicore TI SpA.
|
|
10
|
+
|
|
11
|
+
Change Date:
|
|
12
|
+
There is currently no planned change date where this code will automatically switch to a more permissive license.
|
|
13
|
+
|
|
14
|
+
Licensor:
|
|
15
|
+
Intellicore TI SpA (contact@intellicore.cl)
|
|
16
|
+
|
|
17
|
+
Primary Author:
|
|
18
|
+
Rodrigo Henríquez (rodrigo@intellicore.cl)
|
|
19
|
+
|
|
20
|
+
License Terms:
|
|
21
|
+
The complete terms of the Business Source License 1.1 apply, as published by MariaDB Corporation Ab.
|
|
22
|
+
|
|
23
|
+
A copy of the full license text can be found at:
|
|
24
|
+
https://mariadb.com/bsl11
|
|
25
|
+
|
|
26
|
+
Summary:
|
|
27
|
+
You can use, view, modify, and share the code for non-commercial purposes freely. Commercial use requires obtaining a commercial license from Intellicore TI SpA.
|
|
28
|
+
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: coreplexml
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Python SDK for CorePlexML AutoML & MLOps platform
|
|
5
|
+
Home-page: https://coreplexml.io
|
|
6
|
+
Author: Rodrigo Henríquez M. - Intellicore
|
|
7
|
+
Author-email: r@coreplexml.io
|
|
8
|
+
License: BUSL-1.1
|
|
9
|
+
Project-URL: Platform, https://platform.coreplexml.io
|
|
10
|
+
Project-URL: Documentation, https://platform.coreplexml.io/docs/site/
|
|
11
|
+
Project-URL: Source, https://platform.coreplexml.io/sdk
|
|
12
|
+
Keywords: automl mlops machine-learning h2o deployment monitoring
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
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: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: License :: Other/Proprietary License
|
|
24
|
+
Classifier: Operating System :: OS Independent
|
|
25
|
+
Requires-Python: >=3.9
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: requests>=2.28
|
|
29
|
+
Dynamic: author
|
|
30
|
+
Dynamic: author-email
|
|
31
|
+
Dynamic: classifier
|
|
32
|
+
Dynamic: description
|
|
33
|
+
Dynamic: description-content-type
|
|
34
|
+
Dynamic: home-page
|
|
35
|
+
Dynamic: keywords
|
|
36
|
+
Dynamic: license
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
Dynamic: project-url
|
|
39
|
+
Dynamic: requires-dist
|
|
40
|
+
Dynamic: requires-python
|
|
41
|
+
Dynamic: summary
|
|
42
|
+
|
|
43
|
+
# CorePlexML Python SDK
|
|
44
|
+
|
|
45
|
+
Official Python client for the [CorePlexML](https://coreplexml.io) AutoML & MLOps platform.
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install coreplexml
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from coreplexml import CorePlexMLClient
|
|
57
|
+
|
|
58
|
+
client = CorePlexMLClient(
|
|
59
|
+
base_url="https://platform.coreplexml.io",
|
|
60
|
+
api_key="your-api-key"
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# List projects
|
|
64
|
+
projects = client.projects.list()
|
|
65
|
+
|
|
66
|
+
# Create a project
|
|
67
|
+
project = client.projects.create(name="My ML Project")
|
|
68
|
+
|
|
69
|
+
# Upload a dataset
|
|
70
|
+
dataset = client.datasets.upload(
|
|
71
|
+
project_id=project["id"],
|
|
72
|
+
file_path="data.csv",
|
|
73
|
+
name="Training Data"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Run an AutoML experiment
|
|
77
|
+
experiment = client.experiments.create(
|
|
78
|
+
project_id=project["id"],
|
|
79
|
+
dataset_version_id=dataset["version_id"],
|
|
80
|
+
target_column="label",
|
|
81
|
+
problem_type="classification"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Get the best model
|
|
85
|
+
models = client.models.list(project_id=project["id"])
|
|
86
|
+
best = models["items"][0]
|
|
87
|
+
|
|
88
|
+
# Deploy
|
|
89
|
+
deployment = client.deployments.create(
|
|
90
|
+
project_id=project["id"],
|
|
91
|
+
model_id=best["id"],
|
|
92
|
+
name="production-v1"
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# Predict
|
|
96
|
+
result = client.deployments.predict(
|
|
97
|
+
deployment_id=deployment["id"],
|
|
98
|
+
inputs={"feature1": 1.0, "feature2": "A"}
|
|
99
|
+
)
|
|
100
|
+
print(result["predictions"])
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Resources
|
|
104
|
+
|
|
105
|
+
The client provides access to all platform resources:
|
|
106
|
+
|
|
107
|
+
| Resource | Description |
|
|
108
|
+
|----------|-------------|
|
|
109
|
+
| `client.projects` | Project CRUD |
|
|
110
|
+
| `client.datasets` | Dataset upload, versions, columns |
|
|
111
|
+
| `client.experiments` | AutoML experiment management |
|
|
112
|
+
| `client.models` | Model listing, metrics, explainability |
|
|
113
|
+
| `client.deployments` | Deploy models, predict, A/B tests |
|
|
114
|
+
| `client.reports` | Generate PDF/HTML reports |
|
|
115
|
+
| `client.privacy` | Privacy Suite (PII detection, compliance) |
|
|
116
|
+
| `client.synthgen` | Synthetic data generation (CTGAN, TVAE) |
|
|
117
|
+
| `client.studio` | What-If analysis sessions |
|
|
118
|
+
|
|
119
|
+
## Authentication
|
|
120
|
+
|
|
121
|
+
Create an API key from **Profile > API Keys** in the platform, then:
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
client = CorePlexMLClient(
|
|
125
|
+
base_url="https://platform.coreplexml.io",
|
|
126
|
+
api_key="cpx_your_api_key_here"
|
|
127
|
+
)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Error Handling
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
from coreplexml import CorePlexMLClient, NotFoundError, ValidationError
|
|
134
|
+
|
|
135
|
+
try:
|
|
136
|
+
client.projects.get("nonexistent-id")
|
|
137
|
+
except NotFoundError:
|
|
138
|
+
print("Project not found")
|
|
139
|
+
except ValidationError as e:
|
|
140
|
+
print(f"Validation error: {e}")
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Requirements
|
|
144
|
+
|
|
145
|
+
- Python >= 3.9
|
|
146
|
+
- `requests` >= 2.28
|
|
147
|
+
|
|
148
|
+
## Links
|
|
149
|
+
|
|
150
|
+
- [Platform](https://platform.coreplexml.io)
|
|
151
|
+
- [API Documentation](https://platform.coreplexml.io/docs/site/)
|
|
152
|
+
- [Website](https://coreplexml.io)
|
|
153
|
+
|
|
154
|
+
## License
|
|
155
|
+
|
|
156
|
+
Business Source License 1.1
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# CorePlexML Python SDK
|
|
2
|
+
|
|
3
|
+
Official Python client for the [CorePlexML](https://coreplexml.io) AutoML & MLOps platform.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install coreplexml
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from coreplexml import CorePlexMLClient
|
|
15
|
+
|
|
16
|
+
client = CorePlexMLClient(
|
|
17
|
+
base_url="https://platform.coreplexml.io",
|
|
18
|
+
api_key="your-api-key"
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# List projects
|
|
22
|
+
projects = client.projects.list()
|
|
23
|
+
|
|
24
|
+
# Create a project
|
|
25
|
+
project = client.projects.create(name="My ML Project")
|
|
26
|
+
|
|
27
|
+
# Upload a dataset
|
|
28
|
+
dataset = client.datasets.upload(
|
|
29
|
+
project_id=project["id"],
|
|
30
|
+
file_path="data.csv",
|
|
31
|
+
name="Training Data"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Run an AutoML experiment
|
|
35
|
+
experiment = client.experiments.create(
|
|
36
|
+
project_id=project["id"],
|
|
37
|
+
dataset_version_id=dataset["version_id"],
|
|
38
|
+
target_column="label",
|
|
39
|
+
problem_type="classification"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Get the best model
|
|
43
|
+
models = client.models.list(project_id=project["id"])
|
|
44
|
+
best = models["items"][0]
|
|
45
|
+
|
|
46
|
+
# Deploy
|
|
47
|
+
deployment = client.deployments.create(
|
|
48
|
+
project_id=project["id"],
|
|
49
|
+
model_id=best["id"],
|
|
50
|
+
name="production-v1"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# Predict
|
|
54
|
+
result = client.deployments.predict(
|
|
55
|
+
deployment_id=deployment["id"],
|
|
56
|
+
inputs={"feature1": 1.0, "feature2": "A"}
|
|
57
|
+
)
|
|
58
|
+
print(result["predictions"])
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Resources
|
|
62
|
+
|
|
63
|
+
The client provides access to all platform resources:
|
|
64
|
+
|
|
65
|
+
| Resource | Description |
|
|
66
|
+
|----------|-------------|
|
|
67
|
+
| `client.projects` | Project CRUD |
|
|
68
|
+
| `client.datasets` | Dataset upload, versions, columns |
|
|
69
|
+
| `client.experiments` | AutoML experiment management |
|
|
70
|
+
| `client.models` | Model listing, metrics, explainability |
|
|
71
|
+
| `client.deployments` | Deploy models, predict, A/B tests |
|
|
72
|
+
| `client.reports` | Generate PDF/HTML reports |
|
|
73
|
+
| `client.privacy` | Privacy Suite (PII detection, compliance) |
|
|
74
|
+
| `client.synthgen` | Synthetic data generation (CTGAN, TVAE) |
|
|
75
|
+
| `client.studio` | What-If analysis sessions |
|
|
76
|
+
|
|
77
|
+
## Authentication
|
|
78
|
+
|
|
79
|
+
Create an API key from **Profile > API Keys** in the platform, then:
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
client = CorePlexMLClient(
|
|
83
|
+
base_url="https://platform.coreplexml.io",
|
|
84
|
+
api_key="cpx_your_api_key_here"
|
|
85
|
+
)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Error Handling
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from coreplexml import CorePlexMLClient, NotFoundError, ValidationError
|
|
92
|
+
|
|
93
|
+
try:
|
|
94
|
+
client.projects.get("nonexistent-id")
|
|
95
|
+
except NotFoundError:
|
|
96
|
+
print("Project not found")
|
|
97
|
+
except ValidationError as e:
|
|
98
|
+
print(f"Validation error: {e}")
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Requirements
|
|
102
|
+
|
|
103
|
+
- Python >= 3.9
|
|
104
|
+
- `requests` >= 2.28
|
|
105
|
+
|
|
106
|
+
## Links
|
|
107
|
+
|
|
108
|
+
- [Platform](https://platform.coreplexml.io)
|
|
109
|
+
- [API Documentation](https://platform.coreplexml.io/docs/site/)
|
|
110
|
+
- [Website](https://coreplexml.io)
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
Business Source License 1.1
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""CorePlexML Python SDK.
|
|
2
|
+
|
|
3
|
+
A Python client for the CorePlexML AutoML & MLOps platform.
|
|
4
|
+
Provides typed access to projects, datasets, experiments, models,
|
|
5
|
+
deployments, reports, privacy suite, synthetic data generation,
|
|
6
|
+
and what-if analysis.
|
|
7
|
+
|
|
8
|
+
Quick start::
|
|
9
|
+
|
|
10
|
+
from coreplexml import CorePlexMLClient
|
|
11
|
+
|
|
12
|
+
client = CorePlexMLClient("https://your-domain.com", api_key="your-key")
|
|
13
|
+
projects = client.projects.list()
|
|
14
|
+
|
|
15
|
+
Version: 0.1.1
|
|
16
|
+
"""
|
|
17
|
+
from coreplexml.client import CorePlexMLClient
|
|
18
|
+
from coreplexml.exceptions import CorePlexMLError, AuthenticationError, NotFoundError, ValidationError
|
|
19
|
+
|
|
20
|
+
__version__ = "0.1.1"
|
|
21
|
+
__all__ = ["CorePlexMLClient", "CorePlexMLError", "AuthenticationError", "NotFoundError", "ValidationError", "__version__"]
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""HTTP transport layer for the CorePlexML Python SDK.
|
|
4
|
+
|
|
5
|
+
Provides low-level HTTP methods with automatic error handling,
|
|
6
|
+
authentication, retry logic, and job polling support.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import time
|
|
10
|
+
import logging
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
import requests
|
|
14
|
+
from requests.adapters import HTTPAdapter
|
|
15
|
+
from urllib3.util.retry import Retry
|
|
16
|
+
|
|
17
|
+
from coreplexml.exceptions import CorePlexMLError, AuthenticationError, NotFoundError, ValidationError
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
_SDK_VERSION = "0.1.1"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class HTTPClient:
|
|
25
|
+
"""Low-level HTTP client with error handling, retries, and job polling."""
|
|
26
|
+
|
|
27
|
+
def __init__(self, base_url: str, api_key: str | None = None, timeout: int = 30):
|
|
28
|
+
self.base_url = base_url.rstrip("/")
|
|
29
|
+
self.timeout = timeout
|
|
30
|
+
self.session = requests.Session()
|
|
31
|
+
self.session.headers["User-Agent"] = f"coreplexml-python/{_SDK_VERSION}"
|
|
32
|
+
self.session.headers["Content-Type"] = "application/json"
|
|
33
|
+
if api_key:
|
|
34
|
+
self.session.headers["Authorization"] = f"Bearer {api_key}"
|
|
35
|
+
|
|
36
|
+
# Retry transient failures with exponential backoff
|
|
37
|
+
retry = Retry(
|
|
38
|
+
total=3,
|
|
39
|
+
backoff_factor=0.5,
|
|
40
|
+
status_forcelist=[429, 500, 502, 503, 504],
|
|
41
|
+
allowed_methods=["GET", "PUT", "DELETE", "HEAD", "OPTIONS"],
|
|
42
|
+
)
|
|
43
|
+
adapter = HTTPAdapter(max_retries=retry)
|
|
44
|
+
self.session.mount("http://", adapter)
|
|
45
|
+
self.session.mount("https://", adapter)
|
|
46
|
+
|
|
47
|
+
def close(self) -> None:
|
|
48
|
+
"""Close the underlying HTTP session and release connections."""
|
|
49
|
+
self.session.close()
|
|
50
|
+
|
|
51
|
+
def __repr__(self) -> str:
|
|
52
|
+
return f"HTTPClient(base_url={self.base_url!r})"
|
|
53
|
+
|
|
54
|
+
def _url(self, path: str) -> str:
|
|
55
|
+
return f"{self.base_url}{path}"
|
|
56
|
+
|
|
57
|
+
def _request(self, method: str, path: str, **kwargs) -> requests.Response:
|
|
58
|
+
"""Execute HTTP request with connection error wrapping."""
|
|
59
|
+
kwargs.setdefault("timeout", self.timeout)
|
|
60
|
+
try:
|
|
61
|
+
return self.session.request(method, self._url(path), **kwargs)
|
|
62
|
+
except requests.exceptions.Timeout as e:
|
|
63
|
+
raise CorePlexMLError(f"Request timed out: {e}") from e
|
|
64
|
+
except requests.exceptions.ConnectionError as e:
|
|
65
|
+
raise CorePlexMLError(f"Connection failed: {e}") from e
|
|
66
|
+
except requests.exceptions.RequestException as e:
|
|
67
|
+
raise CorePlexMLError(f"Request failed: {e}") from e
|
|
68
|
+
|
|
69
|
+
def _handle_response(self, resp: requests.Response) -> dict:
|
|
70
|
+
"""Process HTTP response and raise typed exceptions on errors."""
|
|
71
|
+
if resp.status_code == 204:
|
|
72
|
+
return {}
|
|
73
|
+
try:
|
|
74
|
+
data = resp.json()
|
|
75
|
+
except Exception:
|
|
76
|
+
text = resp.text[:500] if resp.text else "No response body"
|
|
77
|
+
data = {"detail": text}
|
|
78
|
+
|
|
79
|
+
if resp.status_code >= 400:
|
|
80
|
+
detail = data.get("detail", str(data)) if isinstance(data, dict) else str(data)
|
|
81
|
+
msg = f"HTTP {resp.status_code}: {detail}"
|
|
82
|
+
if resp.status_code in (401, 403):
|
|
83
|
+
raise AuthenticationError(msg, resp.status_code, detail)
|
|
84
|
+
elif resp.status_code == 404:
|
|
85
|
+
raise NotFoundError(msg, resp.status_code, detail)
|
|
86
|
+
elif resp.status_code == 422:
|
|
87
|
+
raise ValidationError(msg, resp.status_code, detail)
|
|
88
|
+
else:
|
|
89
|
+
raise CorePlexMLError(msg, resp.status_code, detail)
|
|
90
|
+
return data
|
|
91
|
+
|
|
92
|
+
def get(self, path: str, params: dict | None = None) -> dict:
|
|
93
|
+
"""Send GET request."""
|
|
94
|
+
resp = self._request("GET", path, params=params)
|
|
95
|
+
return self._handle_response(resp)
|
|
96
|
+
|
|
97
|
+
def post(self, path: str, json: dict | None = None, files: dict | None = None) -> dict:
|
|
98
|
+
"""Send POST request."""
|
|
99
|
+
if files:
|
|
100
|
+
saved_ct = self.session.headers.pop("Content-Type", None)
|
|
101
|
+
try:
|
|
102
|
+
resp = self._request("POST", path, data=json, files=files)
|
|
103
|
+
finally:
|
|
104
|
+
if saved_ct:
|
|
105
|
+
self.session.headers["Content-Type"] = saved_ct
|
|
106
|
+
else:
|
|
107
|
+
resp = self._request("POST", path, json=json)
|
|
108
|
+
return self._handle_response(resp)
|
|
109
|
+
|
|
110
|
+
def put(self, path: str, json: dict | None = None) -> dict:
|
|
111
|
+
"""Send PUT request."""
|
|
112
|
+
resp = self._request("PUT", path, json=json)
|
|
113
|
+
return self._handle_response(resp)
|
|
114
|
+
|
|
115
|
+
def patch(self, path: str, json: dict | None = None) -> dict:
|
|
116
|
+
"""Send PATCH request."""
|
|
117
|
+
resp = self._request("PATCH", path, json=json)
|
|
118
|
+
return self._handle_response(resp)
|
|
119
|
+
|
|
120
|
+
def delete(self, path: str) -> dict:
|
|
121
|
+
"""Send DELETE request."""
|
|
122
|
+
resp = self._request("DELETE", path)
|
|
123
|
+
return self._handle_response(resp)
|
|
124
|
+
|
|
125
|
+
def download(self, path: str, output_path: str, params: dict | None = None) -> str:
|
|
126
|
+
"""Download a file from the API.
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
The output_path where the file was saved.
|
|
130
|
+
"""
|
|
131
|
+
resp = self._request("GET", path, params=params, stream=True)
|
|
132
|
+
if resp.status_code >= 400:
|
|
133
|
+
self._handle_response(resp) # raises typed exception
|
|
134
|
+
with open(output_path, "wb") as f:
|
|
135
|
+
for chunk in resp.iter_content(chunk_size=8192):
|
|
136
|
+
f.write(chunk)
|
|
137
|
+
return output_path
|
|
138
|
+
|
|
139
|
+
def poll_job(self, job_id: str, interval: float = 3.0, timeout: float = 600.0) -> dict:
|
|
140
|
+
"""Poll a job until completion or timeout."""
|
|
141
|
+
start = time.time()
|
|
142
|
+
while time.time() - start < timeout:
|
|
143
|
+
data = self.get(f"/api/jobs/{job_id}")
|
|
144
|
+
job = data.get("job", data) if isinstance(data, dict) else {}
|
|
145
|
+
status = job.get("status", "") if isinstance(job, dict) else ""
|
|
146
|
+
if status in ("succeeded", "completed", "failed", "error"):
|
|
147
|
+
return job if isinstance(job, dict) else data
|
|
148
|
+
time.sleep(interval)
|
|
149
|
+
raise CorePlexMLError(f"Job {job_id} timed out after {timeout}s")
|
|
150
|
+
|
|
151
|
+
def upload(self, path: str, file_path: str, fields: dict | None = None) -> dict:
|
|
152
|
+
"""Upload a file via multipart form."""
|
|
153
|
+
import os
|
|
154
|
+
filename = os.path.basename(file_path)
|
|
155
|
+
with open(file_path, "rb") as f:
|
|
156
|
+
files = {"file": (filename, f)}
|
|
157
|
+
return self.post(path, json=fields, files=files)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""Main CorePlexML client."""
|
|
4
|
+
|
|
5
|
+
from coreplexml._http import HTTPClient
|
|
6
|
+
from coreplexml.projects import ProjectsResource
|
|
7
|
+
from coreplexml.datasets import DatasetsResource
|
|
8
|
+
from coreplexml.experiments import ExperimentsResource
|
|
9
|
+
from coreplexml.models import ModelsResource
|
|
10
|
+
from coreplexml.deployments import DeploymentsResource
|
|
11
|
+
from coreplexml.reports import ReportsResource
|
|
12
|
+
from coreplexml.privacy import PrivacyResource
|
|
13
|
+
from coreplexml.synthgen import SynthGenResource
|
|
14
|
+
from coreplexml.studio import StudioResource
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class CorePlexMLClient:
|
|
18
|
+
"""Top-level client for the CorePlexML Python SDK.
|
|
19
|
+
|
|
20
|
+
Provides access to all API resources through typed sub-clients.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
base_url: CorePlexML server URL (default ``http://localhost:8888``).
|
|
24
|
+
api_key: Bearer token for API authentication.
|
|
25
|
+
timeout: Request timeout in seconds (default 30).
|
|
26
|
+
|
|
27
|
+
Example::
|
|
28
|
+
|
|
29
|
+
from coreplexml import CorePlexMLClient
|
|
30
|
+
|
|
31
|
+
client = CorePlexMLClient("https://your-domain.com", api_key="your-key")
|
|
32
|
+
projects = client.projects.list()
|
|
33
|
+
|
|
34
|
+
Attributes:
|
|
35
|
+
projects: Manage projects.
|
|
36
|
+
datasets: Upload, list, and manage datasets.
|
|
37
|
+
experiments: Create and monitor AutoML experiments.
|
|
38
|
+
models: Get model info and make predictions.
|
|
39
|
+
deployments: Deploy models and manage production endpoints.
|
|
40
|
+
reports: Generate and download reports.
|
|
41
|
+
privacy: Privacy Suite -- PII detection and data transformation.
|
|
42
|
+
synthgen: Synthetic data generation with CTGAN/CopulaGAN/TVAE/Gaussian Copula.
|
|
43
|
+
studio: What-If Analysis -- scenario comparison.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def __init__(self, base_url: str = "http://localhost:8888", api_key: str | None = None, timeout: int = 30):
|
|
47
|
+
"""Initialize the CorePlexML client.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
base_url: Server URL (default ``http://localhost:8888``).
|
|
51
|
+
api_key: API key for Bearer authentication.
|
|
52
|
+
timeout: Request timeout in seconds.
|
|
53
|
+
"""
|
|
54
|
+
self._http = HTTPClient(base_url, api_key=api_key, timeout=timeout)
|
|
55
|
+
self.projects = ProjectsResource(self._http)
|
|
56
|
+
self.datasets = DatasetsResource(self._http)
|
|
57
|
+
self.experiments = ExperimentsResource(self._http)
|
|
58
|
+
self.models = ModelsResource(self._http)
|
|
59
|
+
self.deployments = DeploymentsResource(self._http)
|
|
60
|
+
self.reports = ReportsResource(self._http)
|
|
61
|
+
self.privacy = PrivacyResource(self._http)
|
|
62
|
+
self.synthgen = SynthGenResource(self._http)
|
|
63
|
+
self.studio = StudioResource(self._http)
|
|
64
|
+
|
|
65
|
+
def close(self) -> None:
|
|
66
|
+
"""Close the underlying HTTP session and release connections."""
|
|
67
|
+
self._http.close()
|
|
68
|
+
|
|
69
|
+
def __enter__(self):
|
|
70
|
+
return self
|
|
71
|
+
|
|
72
|
+
def __exit__(self, *args):
|
|
73
|
+
self.close()
|
|
74
|
+
|
|
75
|
+
def __repr__(self) -> str:
|
|
76
|
+
return f"CorePlexMLClient(base_url={self._http.base_url!r})"
|