fundamental-client 0.2.3__tar.gz → 0.2.5__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.
- fundamental_client-0.2.5/.release-please-manifest.json +3 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/CHANGELOG.md +15 -0
- fundamental_client-0.2.5/CONTRIBUTING.md +156 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/PKG-INFO +423 -4
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/README.md +43 -136
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/pyproject.toml +4 -3
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/scripts/bootstrap +1 -1
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/__init__.py +8 -3
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/clients/__init__.py +2 -2
- fundamental_client-0.2.3/src/fundamental/clients/ec2.py → fundamental_client-0.2.5/src/fundamental/clients/aws_marketplace.py +5 -5
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/config.py +3 -3
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/constants.py +1 -1
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/utils/http.py +3 -3
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/uv.lock +7 -7
- fundamental_client-0.2.3/.release-please-manifest.json +0 -3
- fundamental_client-0.2.3/CONTRIBUTING.md +0 -74
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/dependabot.yml +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/labeler.yml +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/settings.yml +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/ci.yml +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/e2e-pr-comment.yml +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/integration-tests.yml +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/labeler.yml +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/pr-name-validation.yml +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/publish-codeartifact-dev.yml +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/publish-codeartifact.yml +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/publish-pypi.yml +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/publish-testpypi.yml +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/release-please.yml +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.gitignore +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.pre-commit-config.yaml +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.yamllint +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/CODEOWNERS +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/LICENSE +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/noxfile.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/release-please-config.json +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/scripts/format +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/scripts/generate-models +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/scripts/integration-tests +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/scripts/lint +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/scripts/test +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/scripts/unit-tests +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/clients/base.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/clients/fundamental.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/deprecated.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/estimator/__init__.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/estimator/base.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/estimator/classification.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/estimator/nexus_estimator.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/estimator/regression.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/exceptions.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/models/__init__.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/models/generated.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/services/__init__.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/services/feature_importance.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/services/inference.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/services/models.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/utils/__init__.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/utils/data.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/utils/polling.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/utils/safetensors_deserialize.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/conftest.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/integration/__init__.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/integration/test_classification.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/integration/test_regression.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/unit/__init__.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/unit/conftest.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/unit/test_backward_compatibility.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/unit/test_config.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/unit/test_data_utils.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/unit/test_estimators.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/unit/test_safetensors_deserialize.py +0 -0
- {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/unit/test_sklearn_compliance.py +0 -0
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- version list -->
|
|
4
4
|
|
|
5
|
+
## [0.2.5](https://github.com/Fundamental-Technologies/fundamental-client/compare/0.2.4...0.2.5) (2026-02-05)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* improve README and version reporting (ENG-594) ([#68](https://github.com/Fundamental-Technologies/fundamental-client/issues/68)) ([2c1bfc5](https://github.com/Fundamental-Technologies/fundamental-client/commit/2c1bfc5795203ef70cc066352d35f1b775e92b65))
|
|
11
|
+
|
|
12
|
+
## [0.2.4](https://github.com/Fundamental-Technologies/fundamental-client/compare/0.2.3...0.2.4) (2026-02-04)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* eng-575-user-facing-readme ([#64](https://github.com/Fundamental-Technologies/fundamental-client/issues/64)) ([591bcce](https://github.com/Fundamental-Technologies/fundamental-client/commit/591bccefed4abeaeddca9b8a03d81044d2d4bb25))
|
|
18
|
+
* update documentation URL in pyproject.toml ([#66](https://github.com/Fundamental-Technologies/fundamental-client/issues/66)) ([1d21409](https://github.com/Fundamental-Technologies/fundamental-client/commit/1d214095abdb61a47abaecde66e5cee9a69a7ba3))
|
|
19
|
+
|
|
5
20
|
## [0.2.3](https://github.com/Fundamental-Technologies/fundamental-client/compare/0.2.2...0.2.3) (2026-02-03)
|
|
6
21
|
|
|
7
22
|
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Contributing to Fundamental Python SDK
|
|
2
|
+
|
|
3
|
+
We welcome contributions to the Fundamental Python SDK! Whether it's a bug fix, documentation improvement, or additional tests, your help is appreciated.
|
|
4
|
+
|
|
5
|
+
## Reporting Issues
|
|
6
|
+
|
|
7
|
+
Go to this repository's [issues page](https://github.com/Fundamental-Technologies/fundamental-client/issues) and click "New Issue". Please check if the issue has already been reported before creating a new one.
|
|
8
|
+
|
|
9
|
+
Include the following information:
|
|
10
|
+
|
|
11
|
+
- Describe what you expected to happen
|
|
12
|
+
- If possible, include a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example)
|
|
13
|
+
- Describe what actually happened, including the full traceback if there was an exception
|
|
14
|
+
- List your Python version and SDK version
|
|
15
|
+
|
|
16
|
+
## Development Setup
|
|
17
|
+
|
|
18
|
+
Fork the repository and clone it locally:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
git clone https://github.com/YOUR-USERNAME/fundamental-client
|
|
22
|
+
cd fundamental-client
|
|
23
|
+
git checkout -b my-feature-branch main
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Quick Setup
|
|
27
|
+
|
|
28
|
+
We recommend using our bootstrap script for easy setup:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
./scripts/bootstrap
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Manual Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Install with development dependencies using uv (recommended)
|
|
38
|
+
uv sync --extra dev
|
|
39
|
+
|
|
40
|
+
# Or (pip-compatible) install in editable mode
|
|
41
|
+
uv pip install -e ".[dev]"
|
|
42
|
+
|
|
43
|
+
# Or with pip
|
|
44
|
+
pip install -e ".[dev]"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Making Changes
|
|
48
|
+
|
|
49
|
+
1. Make your changes
|
|
50
|
+
2. Format code: `./scripts/format`
|
|
51
|
+
3. Check linting: `./scripts/lint`
|
|
52
|
+
4. Run tests: `./scripts/test`
|
|
53
|
+
|
|
54
|
+
## Testing
|
|
55
|
+
|
|
56
|
+
We use [pytest](https://docs.pytest.org/) for testing. To run tests:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Run all tests using the test script
|
|
60
|
+
./scripts/test
|
|
61
|
+
|
|
62
|
+
# Or run directly with nox for all Python versions
|
|
63
|
+
uv run nox -s tests
|
|
64
|
+
|
|
65
|
+
# Run tests for specific Python version
|
|
66
|
+
uv run nox -s tests-3.10
|
|
67
|
+
|
|
68
|
+
# Run tests with minimum dependencies
|
|
69
|
+
uv run nox -s tests-3.10 -- minimum
|
|
70
|
+
|
|
71
|
+
# Run specific test file directly
|
|
72
|
+
uv run pytest tests/unit/test_estimators.py -v
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
When adding new tests, place them in the `tests/` directory following the same structure as the source code.
|
|
76
|
+
|
|
77
|
+
## Code Quality
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Format code using the format script
|
|
81
|
+
./scripts/format
|
|
82
|
+
|
|
83
|
+
# Run all linting checks using the lint script
|
|
84
|
+
./scripts/lint
|
|
85
|
+
|
|
86
|
+
# Or run individual checks:
|
|
87
|
+
# Ruff check
|
|
88
|
+
uv run ruff check .
|
|
89
|
+
|
|
90
|
+
# Type checking with pyright
|
|
91
|
+
uv run pyright
|
|
92
|
+
|
|
93
|
+
# Type checking with mypy
|
|
94
|
+
uv run mypy .
|
|
95
|
+
|
|
96
|
+
# Run all pre-commit hooks
|
|
97
|
+
uv run pre-commit run --all-files
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Generating API Models
|
|
101
|
+
|
|
102
|
+
The SDK uses auto-generated Pydantic models from the Fundamental API's OpenAPI specification. This ensures type safety and keeps the client in sync with the API.
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# Regenerate models from the OpenAPI spec
|
|
106
|
+
./scripts/generate-models
|
|
107
|
+
|
|
108
|
+
# Use a different OpenAPI URL (e.g., production)
|
|
109
|
+
OPENAPI_URL=https://api.fundamental-dev.tech/openapi.json ./scripts/generate-models
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Generated models are placed in `src/fundamental/models/generated.py` and can be imported from `fundamental.models`:
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
from fundamental.models import (
|
|
116
|
+
FitRequest,
|
|
117
|
+
FitResponse,
|
|
118
|
+
TaskStatus,
|
|
119
|
+
TaskStatusResponse,
|
|
120
|
+
)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
When the API changes, simply re-run the generation script to update the models.
|
|
124
|
+
|
|
125
|
+
## Versioning and Release Flow
|
|
126
|
+
|
|
127
|
+
This package follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions. We use [Release Please](https://github.com/googleapis/release-please) for automated versioning and changelog generation.
|
|
128
|
+
|
|
129
|
+
**Main Branch (Stable Releases):**
|
|
130
|
+
1. Push to `main` triggers Release Please to create/update a Release PR
|
|
131
|
+
2. Merging the Release PR creates a GitHub Release
|
|
132
|
+
3. The GitHub Release triggers publishing to CodeArtifact and TestPyPI
|
|
133
|
+
|
|
134
|
+
**Feature Branches (Dev Releases):**
|
|
135
|
+
1. Push to any non-main branch publishes a dev version to CodeArtifact
|
|
136
|
+
2. Dev version format: `X.Y.Z.dev0+<commit-hash>`
|
|
137
|
+
|
|
138
|
+
> **Note:** CodeArtifact may show dev versions as "Latest", but `pip install fundamental-client` will install the stable version. Use `--pre` to install dev versions.
|
|
139
|
+
|
|
140
|
+
## Opening a Pull Request
|
|
141
|
+
|
|
142
|
+
Push your branch and open a pull request against the `main` branch. Include:
|
|
143
|
+
|
|
144
|
+
- Clear title following Conventional Commits format
|
|
145
|
+
- Description of what you changed and why
|
|
146
|
+
- Reference any related issues
|
|
147
|
+
|
|
148
|
+
Make sure all CI checks pass before requesting review.
|
|
149
|
+
|
|
150
|
+
## Getting Help
|
|
151
|
+
|
|
152
|
+
- **Issues**: [GitHub Issues](https://github.com/Fundamental-Technologies/fundamental-client/issues) for bugs and feature requests
|
|
153
|
+
- **Email**: support@fundamental.tech for questions
|
|
154
|
+
- **Documentation**: See README.md for usage examples
|
|
155
|
+
|
|
156
|
+
We appreciate all contributions and will provide constructive feedback on pull requests. Thank you for helping improve the Fundamental Python SDK!
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fundamental-client
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Summary: Scikit-learn–compatible client SDK for NEXUS, Fundamental's large model for tabular data
|
|
5
|
-
Project-URL: documentation, https://fundamental.tech/docs
|
|
5
|
+
Project-URL: documentation, https://launch.fundamental.tech/docs/guides/sdk/user-guide
|
|
6
6
|
Author-email: Fundamental Tech <support@fundamental.tech>
|
|
7
7
|
License: Apache License
|
|
8
8
|
Version 2.0, January 2004
|
|
@@ -225,6 +225,8 @@ Requires-Dist: pyarrow>=19.0.0
|
|
|
225
225
|
Requires-Dist: pydantic<3.0.0,>=2.10.0
|
|
226
226
|
Requires-Dist: safetensors>=0.5.0
|
|
227
227
|
Requires-Dist: scikit-learn<2.0.0,>=1.5.0
|
|
228
|
+
Provides-Extra: aws-marketplace
|
|
229
|
+
Requires-Dist: boto3>=1.34.0; extra == 'aws-marketplace'
|
|
228
230
|
Provides-Extra: dev
|
|
229
231
|
Requires-Dist: datamodel-code-generator[http]>=0.26.0; extra == 'dev'
|
|
230
232
|
Requires-Dist: minimum-dependencies; extra == 'dev'
|
|
@@ -237,5 +239,422 @@ Requires-Dist: pytest-mock>=3.15.1; extra == 'dev'
|
|
|
237
239
|
Requires-Dist: pytest>=8.4.2; extra == 'dev'
|
|
238
240
|
Requires-Dist: python-dotenv>=1.0.0; extra == 'dev'
|
|
239
241
|
Requires-Dist: ruff>=0.13.1; extra == 'dev'
|
|
240
|
-
|
|
241
|
-
|
|
242
|
+
Description-Content-Type: text/markdown
|
|
243
|
+
|
|
244
|
+
# Fundamental Python SDK
|
|
245
|
+
|
|
246
|
+
[](https://pypi.org/project/fundamental-client/)
|
|
247
|
+
[](https://pypi.org/project/fundamental-client)
|
|
248
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
249
|
+
|
|
250
|
+
A scikit-learn compatible Python SDK for NEXUS, Fundamental's large model for tabular data.
|
|
251
|
+
|
|
252
|
+
## Table of Contents
|
|
253
|
+
|
|
254
|
+
- [Installation](#installation)
|
|
255
|
+
- [Usage](#usage)
|
|
256
|
+
- [Quick Start](#quick-start)
|
|
257
|
+
- [Using Pre-trained Models](#using-pre-trained-models)
|
|
258
|
+
- [Async Training](#async-training)
|
|
259
|
+
- [Model Management](#model-management)
|
|
260
|
+
- [Explainability & Insights](#explainability--insights)
|
|
261
|
+
- [Feature Importance](#feature-importance)
|
|
262
|
+
- [Configuration](#configuration)
|
|
263
|
+
- [Client Configuration](#client-configuration)
|
|
264
|
+
- [API Key](#api-key)
|
|
265
|
+
- [AWS Marketplace](#aws-marketplace)
|
|
266
|
+
- [Timeouts and Retries](#timeouts-and-retries)
|
|
267
|
+
- [Model Configuration](#model-configuration)
|
|
268
|
+
- [Mode](#mode)
|
|
269
|
+
- [Supported Data Types](#supported-data-types)
|
|
270
|
+
- [Handling Errors](#handling-errors)
|
|
271
|
+
- [Diagnostics and Support Information](#diagnostics-and-support-information)
|
|
272
|
+
- [Exception Types](#exception-types)
|
|
273
|
+
- [Troubleshooting](#troubleshooting)
|
|
274
|
+
- [Versioning](#versioning)
|
|
275
|
+
- [Requirements](#requirements)
|
|
276
|
+
- [License](#license)
|
|
277
|
+
- [Security](#security)
|
|
278
|
+
- [Support](#support)
|
|
279
|
+
|
|
280
|
+
## Installation
|
|
281
|
+
|
|
282
|
+
```sh
|
|
283
|
+
# install from PyPI
|
|
284
|
+
pip install fundamental-client
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Usage
|
|
288
|
+
|
|
289
|
+
The Fundamental SDK provides scikit-learn compatible estimators for classification and regression tasks, along with a flexible client for API interactions.
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
### Quick Start
|
|
293
|
+
|
|
294
|
+
Make sure `FUNDAMENTAL_API_KEY` is set (or call `fundamental.set_client(...)`) before running the examples below.
|
|
295
|
+
|
|
296
|
+
```python
|
|
297
|
+
from sklearn.datasets import load_breast_cancer, load_diabetes
|
|
298
|
+
from sklearn.model_selection import train_test_split
|
|
299
|
+
from fundamental import NEXUSClassifier, NEXUSRegressor
|
|
300
|
+
|
|
301
|
+
# Load classification data
|
|
302
|
+
X, y = load_breast_cancer(return_X_y=True)
|
|
303
|
+
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=42)
|
|
304
|
+
|
|
305
|
+
# Classification
|
|
306
|
+
classifier = NEXUSClassifier()
|
|
307
|
+
classifier.fit(X_train, y_train)
|
|
308
|
+
|
|
309
|
+
# After fitting, the model ID can be saved and used later
|
|
310
|
+
print(f"Trained model ID: {classifier.trained_model_id_}")
|
|
311
|
+
|
|
312
|
+
predictions = classifier.predict(X_test)
|
|
313
|
+
probabilities = classifier.predict_proba(X_test)
|
|
314
|
+
|
|
315
|
+
# Load regression data
|
|
316
|
+
X, y = load_diabetes(return_X_y=True)
|
|
317
|
+
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=42)
|
|
318
|
+
|
|
319
|
+
# Regression
|
|
320
|
+
regressor = NEXUSRegressor()
|
|
321
|
+
regressor.fit(X_train, y_train)
|
|
322
|
+
predictions = regressor.predict(X_test)
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Using Pre-trained Models
|
|
326
|
+
|
|
327
|
+
If you have a trained model from a previous session, you can use it directly without retraining:
|
|
328
|
+
|
|
329
|
+
```python
|
|
330
|
+
from fundamental import NEXUSClassifier, NEXUSRegressor
|
|
331
|
+
|
|
332
|
+
classifier = NEXUSClassifier().load_model(trained_model_id="model_abc123")
|
|
333
|
+
predictions = classifier.predict(X_test)
|
|
334
|
+
probabilities = classifier.predict_proba(X_test)
|
|
335
|
+
|
|
336
|
+
regressor = NEXUSRegressor().load_model(trained_model_id="model_def456")
|
|
337
|
+
predictions = regressor.predict(X_test)
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Async Training
|
|
341
|
+
|
|
342
|
+
Model training is often a long-running operation. To support non-blocking workflows, you can submit training via `submit_fit_task()` and poll for completion. Once submitted, the training job runs in the background and its status can be queried at any time.
|
|
343
|
+
|
|
344
|
+
```python
|
|
345
|
+
from fundamental import NEXUSClassifier
|
|
346
|
+
import time
|
|
347
|
+
|
|
348
|
+
classifier = NEXUSClassifier()
|
|
349
|
+
|
|
350
|
+
# Submit training task without waiting
|
|
351
|
+
task_id = classifier.submit_fit_task(X_train, y_train)
|
|
352
|
+
print(f"Training task submitted: {task_id}")
|
|
353
|
+
|
|
354
|
+
# Poll status periodically
|
|
355
|
+
result = None
|
|
356
|
+
while result is None:
|
|
357
|
+
result = classifier.poll_fit_result(task_id)
|
|
358
|
+
if result is None:
|
|
359
|
+
print("Training in progress...")
|
|
360
|
+
time.sleep(10) # Wait before polling again
|
|
361
|
+
|
|
362
|
+
# Model is now fitted and ready for predictions
|
|
363
|
+
predictions = classifier.predict(X_test)
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Model Management
|
|
367
|
+
|
|
368
|
+
The client provides methods for managing your trained models:
|
|
369
|
+
|
|
370
|
+
```python
|
|
371
|
+
from fundamental import Fundamental
|
|
372
|
+
|
|
373
|
+
# Create a client
|
|
374
|
+
client = Fundamental()
|
|
375
|
+
|
|
376
|
+
# List all available models
|
|
377
|
+
models = client.models.list()
|
|
378
|
+
print(f"Available models: {models}")
|
|
379
|
+
|
|
380
|
+
# Get information about a specific model
|
|
381
|
+
model_info = client.models.get("model_id_123")
|
|
382
|
+
print(f"Model info: {model_info}")
|
|
383
|
+
print(f"Attributes: {model_info.attributes}")
|
|
384
|
+
|
|
385
|
+
# Delete a model
|
|
386
|
+
client.models.delete("model_id_123")
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
#### Model Attributes
|
|
390
|
+
|
|
391
|
+
You can set attributes on your models to help organize and identify them.
|
|
392
|
+
We recommend always setting a `name` attribute; if omitted, the name will default to
|
|
393
|
+
`<model_version> [id:<model_id_suffix>]`.
|
|
394
|
+
|
|
395
|
+
```python
|
|
396
|
+
# Set attributes directly on a fitted model
|
|
397
|
+
classifier.set_attributes({"name": "Breast Cancer Classifier", "stage": "prod"})
|
|
398
|
+
|
|
399
|
+
# Or using the client
|
|
400
|
+
client.models.set_attributes(
|
|
401
|
+
"model_id_123",
|
|
402
|
+
attributes={"name": "Breast Cancer Classifier", "description": "Production model v1"}
|
|
403
|
+
)
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### Explainability & Insights
|
|
407
|
+
|
|
408
|
+
#### Feature Importance
|
|
409
|
+
|
|
410
|
+
After fitting a model, you can compute feature importance to quantify the contribution of each input feature to the model's output:
|
|
411
|
+
|
|
412
|
+
```python
|
|
413
|
+
from sklearn.datasets import load_breast_cancer
|
|
414
|
+
from sklearn.model_selection import train_test_split
|
|
415
|
+
from fundamental import NEXUSClassifier
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
# Load data
|
|
419
|
+
X, y = load_breast_cancer(return_X_y=True)
|
|
420
|
+
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.5, random_state=42)
|
|
421
|
+
# Fit the model
|
|
422
|
+
classifier = NEXUSClassifier()
|
|
423
|
+
classifier.fit(X_train, y_train)
|
|
424
|
+
# Get feature importance (waits for computation to complete)
|
|
425
|
+
feature_importance = classifier.get_feature_importance(X_val)
|
|
426
|
+
print(f"Feature importance: {feature_importance}")
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
Feature importance computation can take a significant amount of time. If you prefer to submit the task and check its status periodically, you can use the asynchronous approach:
|
|
430
|
+
|
|
431
|
+
```python
|
|
432
|
+
# Submit task without waiting
|
|
433
|
+
task_id = classifier.submit_feature_importance_task(X_val)
|
|
434
|
+
|
|
435
|
+
# Poll status later
|
|
436
|
+
result = classifier.poll_feature_importance_result(task_id)
|
|
437
|
+
if result is not None:
|
|
438
|
+
print(f"Feature importance: {result}")
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
## Configuration
|
|
442
|
+
|
|
443
|
+
### Client Configuration
|
|
444
|
+
|
|
445
|
+
Configure the SDK client through environment variables or programmatically.
|
|
446
|
+
|
|
447
|
+
#### API Key
|
|
448
|
+
|
|
449
|
+
You can provide your API key in two ways:
|
|
450
|
+
|
|
451
|
+
```python
|
|
452
|
+
# 1. Programmatic
|
|
453
|
+
import fundamental
|
|
454
|
+
from fundamental import Fundamental, NEXUSClassifier
|
|
455
|
+
|
|
456
|
+
fundamental.set_client(Fundamental(api_key="your_api_key_here"))
|
|
457
|
+
classifier = NEXUSClassifier()
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
```bash
|
|
461
|
+
# 2. Environment variable
|
|
462
|
+
export FUNDAMENTAL_API_KEY="your_api_key_here"
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
#### AWS Marketplace
|
|
466
|
+
|
|
467
|
+
For AWS Marketplace deployments, use the `FundamentalAWSMarketplaceClient` which authenticates using AWS IAM roles via SigV4 signing instead of API keys:
|
|
468
|
+
|
|
469
|
+
```python
|
|
470
|
+
import fundamental
|
|
471
|
+
from fundamental import FundamentalAWSMarketplaceClient, NEXUSClassifier
|
|
472
|
+
|
|
473
|
+
# Set the AWS Marketplace client with your deployment URL and AWS region
|
|
474
|
+
fundamental.set_client(FundamentalAWSMarketplaceClient(
|
|
475
|
+
aws_region="us-west-2", # Required
|
|
476
|
+
api_url="http://your-private-server:8000"
|
|
477
|
+
))
|
|
478
|
+
|
|
479
|
+
# Use the SDK as normal
|
|
480
|
+
classifier = NEXUSClassifier()
|
|
481
|
+
classifier.fit(X_train, y_train)
|
|
482
|
+
predictions = classifier.predict(X_test)
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
The `FundamentalAWSMarketplaceClient` automatically uses AWS credentials from the environment (IAM role, environment variables, or AWS config file) to sign requests. No API key is needed.
|
|
486
|
+
|
|
487
|
+
You can also configure using environment variables:
|
|
488
|
+
|
|
489
|
+
```bash
|
|
490
|
+
export FUNDAMENTAL_API_URL="http://your-private-server:8000"
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
```python
|
|
494
|
+
fundamental.set_client(
|
|
495
|
+
FundamentalAWSMarketplaceClient(
|
|
496
|
+
aws_region="us-west-2", # Required
|
|
497
|
+
# api_url="http://your-private-server:8000", # Optional; overrides FUNDAMENTAL_API_URL
|
|
498
|
+
)
|
|
499
|
+
)
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
#### Timeouts and Retries
|
|
503
|
+
|
|
504
|
+
Configure timeouts and retries when creating a client:
|
|
505
|
+
|
|
506
|
+
> **Note**: Timeouts apply only to the processing phase, starting after the dataset upload has completed.
|
|
507
|
+
|
|
508
|
+
```python
|
|
509
|
+
import fundamental
|
|
510
|
+
from fundamental import Fundamental, NEXUSClassifier
|
|
511
|
+
|
|
512
|
+
# Create and set a client with custom timeouts and retries
|
|
513
|
+
fundamental.set_client(Fundamental(
|
|
514
|
+
fit_timeout=600, # 10 minutes for training (default: 3 hours)
|
|
515
|
+
predict_timeout=30, # 30 seconds for predictions (default: 1 hour)
|
|
516
|
+
retries=0 # Number of retries (default: 1)
|
|
517
|
+
))
|
|
518
|
+
|
|
519
|
+
# Estimators will use the global client
|
|
520
|
+
classifier = NEXUSClassifier()
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
### Model Configuration
|
|
524
|
+
|
|
525
|
+
Configure model behavior and training parameters.
|
|
526
|
+
|
|
527
|
+
#### Mode
|
|
528
|
+
|
|
529
|
+
NEXUS offers two training modes to balance between speed and accuracy:
|
|
530
|
+
|
|
531
|
+
- **`quality` mode (default)**: Optimizes for the highest accuracy. This mode uses more comprehensive training processes and may take longer to complete.
|
|
532
|
+
- **`speed` mode**: Optimizes for faster training times while maintaining good accuracy.
|
|
533
|
+
|
|
534
|
+
```python
|
|
535
|
+
import fundamental
|
|
536
|
+
from fundamental import NEXUSClassifier, NEXUSRegressor
|
|
537
|
+
|
|
538
|
+
# Use quality mode (default)
|
|
539
|
+
classifier = NEXUSClassifier(mode="quality")
|
|
540
|
+
classifier.fit(X_train, y_train)
|
|
541
|
+
|
|
542
|
+
# Use speed mode for faster training
|
|
543
|
+
classifier_fast = NEXUSClassifier(mode="speed")
|
|
544
|
+
classifier_fast.fit(X_train, y_train)
|
|
545
|
+
|
|
546
|
+
# Same for regression
|
|
547
|
+
regressor = NEXUSRegressor(mode="speed")
|
|
548
|
+
regressor.fit(X_train, y_train)
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
## Supported Data Types
|
|
552
|
+
|
|
553
|
+
The SDK supports flexible input formats:
|
|
554
|
+
|
|
555
|
+
- **Input features (X)**:
|
|
556
|
+
- `pandas.DataFrame`
|
|
557
|
+
- `numpy.ndarray`
|
|
558
|
+
|
|
559
|
+
- **Target values (y)**:
|
|
560
|
+
- `numpy.ndarray`
|
|
561
|
+
- `pandas.Series`
|
|
562
|
+
|
|
563
|
+
> **Note**: Data must be serializable to Parquet via PyArrow. If you hit a serialization error, ensure columns have consistent numeric or string dtypes; complex numbers are not supported.
|
|
564
|
+
|
|
565
|
+
## Handling Errors
|
|
566
|
+
|
|
567
|
+
The SDK provides detailed error handling with specific exception types:
|
|
568
|
+
|
|
569
|
+
```python
|
|
570
|
+
from fundamental import NEXUSClassifier
|
|
571
|
+
from fundamental.exceptions import (
|
|
572
|
+
NEXUSError,
|
|
573
|
+
ValidationError,
|
|
574
|
+
AuthenticationError,
|
|
575
|
+
RateLimitError,
|
|
576
|
+
ServerError
|
|
577
|
+
)
|
|
578
|
+
|
|
579
|
+
classifier = NEXUSClassifier()
|
|
580
|
+
|
|
581
|
+
try:
|
|
582
|
+
classifier.fit(X_train, y_train)
|
|
583
|
+
except ValidationError as e:
|
|
584
|
+
print(f"Invalid input data: {e}")
|
|
585
|
+
print(f"Status code: {e.status_code}")
|
|
586
|
+
except AuthenticationError as e:
|
|
587
|
+
print("Authentication failed - check your API key")
|
|
588
|
+
except RateLimitError as e:
|
|
589
|
+
print("Rate limit exceeded - please wait before retrying")
|
|
590
|
+
except ServerError as e:
|
|
591
|
+
print("Server error - please try again later")
|
|
592
|
+
except NEXUSError as e:
|
|
593
|
+
print(f"An error occurred: {e}")
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### Diagnostics and Support Information
|
|
597
|
+
|
|
598
|
+
All exceptions include a `trace_id` attribute that you can share with Fundamental support to help diagnose issues more quickly.
|
|
599
|
+
|
|
600
|
+
```python
|
|
601
|
+
except ServerError as e:
|
|
602
|
+
if e.trace_id:
|
|
603
|
+
print(f"Error trace_id: {e.trace_id}")
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
### Exception Types
|
|
607
|
+
|
|
608
|
+
| Error Type | Description | Status Code |
|
|
609
|
+
| ---------- | ----------- | ----------- |
|
|
610
|
+
| `ValidationError` | Input validation failed (bad request) | 400 |
|
|
611
|
+
| `AuthenticationError` | Authentication failed (missing/invalid API key) | 401 |
|
|
612
|
+
| `AuthorizationError` | Authorization failed (insufficient permissions) | 403 |
|
|
613
|
+
| `NotFoundError` | Resource not found | 404 |
|
|
614
|
+
| `RateLimitError` | API rate limit exceeded | 429 |
|
|
615
|
+
| `ServerError` | Server-side error | 500+ |
|
|
616
|
+
| `NetworkError` | Network connectivity issues | 503 |
|
|
617
|
+
| `RequestTimeoutError` | Request timed out | 504 |
|
|
618
|
+
|
|
619
|
+
## Troubleshooting
|
|
620
|
+
|
|
621
|
+
- **Missing API key** (`ValueError: API key is required...`): set `FUNDAMENTAL_API_KEY` or configure a client via `fundamental.set_client(...)`.
|
|
622
|
+
- **Serialization errors (PyArrow)**: ensure `X`/`y` contain consistent numeric or string types; avoid mixed-type/object columns.
|
|
623
|
+
- **Large datasets / memory use**: datasets are serialized to Parquet in-memory before upload. If you run into memory or upload issues, try sampling, reducing columns, or using batching.
|
|
624
|
+
|
|
625
|
+
To enable debug logs:
|
|
626
|
+
|
|
627
|
+
```python
|
|
628
|
+
import logging
|
|
629
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
## Versioning
|
|
633
|
+
|
|
634
|
+
This package follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions.
|
|
635
|
+
|
|
636
|
+
To check the installed version:
|
|
637
|
+
|
|
638
|
+
```python
|
|
639
|
+
import fundamental
|
|
640
|
+
print(fundamental.__version__)
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
## Requirements
|
|
644
|
+
|
|
645
|
+
- Python 3.10 or higher
|
|
646
|
+
- See [pyproject.toml](pyproject.toml) for full dependency list
|
|
647
|
+
|
|
648
|
+
## License
|
|
649
|
+
|
|
650
|
+
This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
|
|
651
|
+
|
|
652
|
+
## Security
|
|
653
|
+
|
|
654
|
+
If you believe you’ve found a security vulnerability, please email [support@fundamental.tech](mailto:support@fundamental.tech) and include a minimal reproduction. Please do not open a public GitHub issue.
|
|
655
|
+
|
|
656
|
+
## Support
|
|
657
|
+
|
|
658
|
+
- **SDK docs**: [SDK User Guide](https://launch.fundamental.tech/docs/guides/sdk/user-guide)
|
|
659
|
+
- **Issues**: [GitHub Issues](https://github.com/Fundamental-Technologies/fundamental-client/issues)
|
|
660
|
+
- **Email**: [support@fundamental.tech](mailto:support@fundamental.tech)
|