fundamental-client 0.2.4__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.4 → fundamental_client-0.2.5}/CHANGELOG.md +7 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/CONTRIBUTING.md +9 -6
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/PKG-INFO +422 -3
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/README.md +46 -20
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/pyproject.toml +3 -2
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/scripts/bootstrap +1 -1
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/__init__.py +8 -3
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/clients/__init__.py +2 -2
- fundamental_client-0.2.4/src/fundamental/clients/ec2.py → fundamental_client-0.2.5/src/fundamental/clients/aws_marketplace.py +5 -5
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/config.py +3 -3
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/constants.py +1 -1
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/utils/http.py +3 -3
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/uv.lock +7 -7
- fundamental_client-0.2.4/.release-please-manifest.json +0 -3
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/dependabot.yml +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/labeler.yml +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/settings.yml +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/workflows/ci.yml +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/workflows/e2e-pr-comment.yml +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/workflows/integration-tests.yml +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/workflows/labeler.yml +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/workflows/pr-name-validation.yml +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/workflows/publish-codeartifact-dev.yml +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/workflows/publish-codeartifact.yml +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/workflows/publish-pypi.yml +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/workflows/publish-testpypi.yml +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/workflows/release-please.yml +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.gitignore +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.pre-commit-config.yaml +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/.yamllint +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/CODEOWNERS +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/LICENSE +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/noxfile.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/release-please-config.json +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/scripts/format +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/scripts/generate-models +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/scripts/integration-tests +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/scripts/lint +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/scripts/test +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/scripts/unit-tests +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/clients/base.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/clients/fundamental.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/deprecated.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/estimator/__init__.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/estimator/base.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/estimator/classification.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/estimator/nexus_estimator.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/estimator/regression.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/exceptions.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/models/__init__.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/models/generated.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/services/__init__.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/services/feature_importance.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/services/inference.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/services/models.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/utils/__init__.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/utils/data.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/utils/polling.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/utils/safetensors_deserialize.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/tests/conftest.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/tests/integration/__init__.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/tests/integration/test_classification.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/tests/integration/test_regression.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/tests/unit/__init__.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/tests/unit/conftest.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/tests/unit/test_backward_compatibility.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/tests/unit/test_config.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/tests/unit/test_data_utils.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/tests/unit/test_estimators.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/tests/unit/test_safetensors_deserialize.py +0 -0
- {fundamental_client-0.2.4 → fundamental_client-0.2.5}/tests/unit/test_sklearn_compliance.py +0 -0
|
@@ -2,6 +2,13 @@
|
|
|
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
|
+
|
|
5
12
|
## [0.2.4](https://github.com/Fundamental-Technologies/fundamental-client/compare/0.2.3...0.2.4) (2026-02-04)
|
|
6
13
|
|
|
7
14
|
|
|
@@ -4,7 +4,7 @@ We welcome contributions to the Fundamental Python SDK! Whether it's a bug fix,
|
|
|
4
4
|
|
|
5
5
|
## Reporting Issues
|
|
6
6
|
|
|
7
|
-
Go to this repository's [issues page](https://github.com/
|
|
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
8
|
|
|
9
9
|
Include the following information:
|
|
10
10
|
|
|
@@ -18,8 +18,8 @@ Include the following information:
|
|
|
18
18
|
Fork the repository and clone it locally:
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
git clone https://github.com/YOUR-USERNAME/fundamental-
|
|
22
|
-
cd fundamental-
|
|
21
|
+
git clone https://github.com/YOUR-USERNAME/fundamental-client
|
|
22
|
+
cd fundamental-client
|
|
23
23
|
git checkout -b my-feature-branch main
|
|
24
24
|
```
|
|
25
25
|
|
|
@@ -34,8 +34,11 @@ We recommend using our bootstrap script for easy setup:
|
|
|
34
34
|
### Manual Installation
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
# Install with development dependencies using
|
|
38
|
-
uv sync --
|
|
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]"
|
|
39
42
|
|
|
40
43
|
# Or with pip
|
|
41
44
|
pip install -e ".[dev]"
|
|
@@ -146,7 +149,7 @@ Make sure all CI checks pass before requesting review.
|
|
|
146
149
|
|
|
147
150
|
## Getting Help
|
|
148
151
|
|
|
149
|
-
- **Issues**: [GitHub Issues](https://github.com/
|
|
152
|
+
- **Issues**: [GitHub Issues](https://github.com/Fundamental-Technologies/fundamental-client/issues) for bugs and feature requests
|
|
150
153
|
- **Email**: support@fundamental.tech for questions
|
|
151
154
|
- **Documentation**: See README.md for usage examples
|
|
152
155
|
|
|
@@ -1,6 +1,6 @@
|
|
|
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
5
|
Project-URL: documentation, https://launch.fundamental.tech/docs/guides/sdk/user-guide
|
|
6
6
|
Author-email: Fundamental Tech <support@fundamental.tech>
|
|
@@ -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)
|
|
@@ -19,7 +19,7 @@ A scikit-learn compatible Python SDK for NEXUS, Fundamental's large model for ta
|
|
|
19
19
|
- [Configuration](#configuration)
|
|
20
20
|
- [Client Configuration](#client-configuration)
|
|
21
21
|
- [API Key](#api-key)
|
|
22
|
-
- [
|
|
22
|
+
- [AWS Marketplace](#aws-marketplace)
|
|
23
23
|
- [Timeouts and Retries](#timeouts-and-retries)
|
|
24
24
|
- [Model Configuration](#model-configuration)
|
|
25
25
|
- [Mode](#mode)
|
|
@@ -27,9 +27,11 @@ A scikit-learn compatible Python SDK for NEXUS, Fundamental's large model for ta
|
|
|
27
27
|
- [Handling Errors](#handling-errors)
|
|
28
28
|
- [Diagnostics and Support Information](#diagnostics-and-support-information)
|
|
29
29
|
- [Exception Types](#exception-types)
|
|
30
|
+
- [Troubleshooting](#troubleshooting)
|
|
30
31
|
- [Versioning](#versioning)
|
|
31
32
|
- [Requirements](#requirements)
|
|
32
33
|
- [License](#license)
|
|
34
|
+
- [Security](#security)
|
|
33
35
|
- [Support](#support)
|
|
34
36
|
|
|
35
37
|
## Installation
|
|
@@ -46,12 +48,14 @@ The Fundamental SDK provides scikit-learn compatible estimators for classificati
|
|
|
46
48
|
|
|
47
49
|
### Quick Start
|
|
48
50
|
|
|
51
|
+
Make sure `FUNDAMENTAL_API_KEY` is set (or call `fundamental.set_client(...)`) before running the examples below.
|
|
52
|
+
|
|
49
53
|
```python
|
|
50
54
|
from sklearn.datasets import load_breast_cancer, load_diabetes
|
|
51
55
|
from sklearn.model_selection import train_test_split
|
|
52
|
-
from fundamental import
|
|
56
|
+
from fundamental import NEXUSClassifier, NEXUSRegressor
|
|
53
57
|
|
|
54
|
-
# Load
|
|
58
|
+
# Load classification data
|
|
55
59
|
X, y = load_breast_cancer(return_X_y=True)
|
|
56
60
|
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=42)
|
|
57
61
|
|
|
@@ -80,19 +84,19 @@ predictions = regressor.predict(X_test)
|
|
|
80
84
|
If you have a trained model from a previous session, you can use it directly without retraining:
|
|
81
85
|
|
|
82
86
|
```python
|
|
83
|
-
from fundamental import
|
|
87
|
+
from fundamental import NEXUSClassifier, NEXUSRegressor
|
|
84
88
|
|
|
85
89
|
classifier = NEXUSClassifier().load_model(trained_model_id="model_abc123")
|
|
86
90
|
predictions = classifier.predict(X_test)
|
|
87
91
|
probabilities = classifier.predict_proba(X_test)
|
|
88
92
|
|
|
89
|
-
regressor
|
|
93
|
+
regressor = NEXUSRegressor().load_model(trained_model_id="model_def456")
|
|
90
94
|
predictions = regressor.predict(X_test)
|
|
91
95
|
```
|
|
92
96
|
|
|
93
97
|
### Async Training
|
|
94
98
|
|
|
95
|
-
Model training is often a long-running operation. To support non-blocking workflows,
|
|
99
|
+
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.
|
|
96
100
|
|
|
97
101
|
```python
|
|
98
102
|
from fundamental import NEXUSClassifier
|
|
@@ -163,6 +167,8 @@ client.models.set_attributes(
|
|
|
163
167
|
After fitting a model, you can compute feature importance to quantify the contribution of each input feature to the model's output:
|
|
164
168
|
|
|
165
169
|
```python
|
|
170
|
+
from sklearn.datasets import load_breast_cancer
|
|
171
|
+
from sklearn.model_selection import train_test_split
|
|
166
172
|
from fundamental import NEXUSClassifier
|
|
167
173
|
|
|
168
174
|
|
|
@@ -213,27 +219,27 @@ classifier = NEXUSClassifier()
|
|
|
213
219
|
export FUNDAMENTAL_API_KEY="your_api_key_here"
|
|
214
220
|
```
|
|
215
221
|
|
|
216
|
-
####
|
|
222
|
+
#### AWS Marketplace
|
|
217
223
|
|
|
218
|
-
For
|
|
224
|
+
For AWS Marketplace deployments, use the `FundamentalAWSMarketplaceClient` which authenticates using AWS IAM roles via SigV4 signing instead of API keys:
|
|
219
225
|
|
|
220
226
|
```python
|
|
221
227
|
import fundamental
|
|
222
|
-
from fundamental import
|
|
228
|
+
from fundamental import FundamentalAWSMarketplaceClient, NEXUSClassifier
|
|
223
229
|
|
|
224
|
-
# Set the
|
|
225
|
-
fundamental.set_client(
|
|
230
|
+
# Set the AWS Marketplace client with your deployment URL and AWS region
|
|
231
|
+
fundamental.set_client(FundamentalAWSMarketplaceClient(
|
|
226
232
|
aws_region="us-west-2", # Required
|
|
227
233
|
api_url="http://your-private-server:8000"
|
|
228
234
|
))
|
|
229
235
|
|
|
230
236
|
# Use the SDK as normal
|
|
231
|
-
classifier =
|
|
237
|
+
classifier = NEXUSClassifier()
|
|
232
238
|
classifier.fit(X_train, y_train)
|
|
233
239
|
predictions = classifier.predict(X_test)
|
|
234
240
|
```
|
|
235
241
|
|
|
236
|
-
The `
|
|
242
|
+
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.
|
|
237
243
|
|
|
238
244
|
You can also configure using environment variables:
|
|
239
245
|
|
|
@@ -242,9 +248,12 @@ export FUNDAMENTAL_API_URL="http://your-private-server:8000"
|
|
|
242
248
|
```
|
|
243
249
|
|
|
244
250
|
```python
|
|
245
|
-
fundamental.set_client(
|
|
246
|
-
|
|
247
|
-
|
|
251
|
+
fundamental.set_client(
|
|
252
|
+
FundamentalAWSMarketplaceClient(
|
|
253
|
+
aws_region="us-west-2", # Required
|
|
254
|
+
# api_url="http://your-private-server:8000", # Optional; overrides FUNDAMENTAL_API_URL
|
|
255
|
+
)
|
|
256
|
+
)
|
|
248
257
|
```
|
|
249
258
|
|
|
250
259
|
#### Timeouts and Retries
|
|
@@ -259,9 +268,9 @@ from fundamental import Fundamental, NEXUSClassifier
|
|
|
259
268
|
|
|
260
269
|
# Create and set a client with custom timeouts and retries
|
|
261
270
|
fundamental.set_client(Fundamental(
|
|
262
|
-
fit_timeout=600, # 10 minutes for training (default:
|
|
271
|
+
fit_timeout=600, # 10 minutes for training (default: 3 hours)
|
|
263
272
|
predict_timeout=30, # 30 seconds for predictions (default: 1 hour)
|
|
264
|
-
retries=0 # Number of retries (default:
|
|
273
|
+
retries=0 # Number of retries (default: 1)
|
|
265
274
|
))
|
|
266
275
|
|
|
267
276
|
# Estimators will use the global client
|
|
@@ -308,7 +317,7 @@ The SDK supports flexible input formats:
|
|
|
308
317
|
- `numpy.ndarray`
|
|
309
318
|
- `pandas.Series`
|
|
310
319
|
|
|
311
|
-
> **Note**: Data must
|
|
320
|
+
> **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.
|
|
312
321
|
|
|
313
322
|
## Handling Errors
|
|
314
323
|
|
|
@@ -364,6 +373,18 @@ except ServerError as e:
|
|
|
364
373
|
| `NetworkError` | Network connectivity issues | 503 |
|
|
365
374
|
| `RequestTimeoutError` | Request timed out | 504 |
|
|
366
375
|
|
|
376
|
+
## Troubleshooting
|
|
377
|
+
|
|
378
|
+
- **Missing API key** (`ValueError: API key is required...`): set `FUNDAMENTAL_API_KEY` or configure a client via `fundamental.set_client(...)`.
|
|
379
|
+
- **Serialization errors (PyArrow)**: ensure `X`/`y` contain consistent numeric or string types; avoid mixed-type/object columns.
|
|
380
|
+
- **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.
|
|
381
|
+
|
|
382
|
+
To enable debug logs:
|
|
383
|
+
|
|
384
|
+
```python
|
|
385
|
+
import logging
|
|
386
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
387
|
+
```
|
|
367
388
|
|
|
368
389
|
## Versioning
|
|
369
390
|
|
|
@@ -385,7 +406,12 @@ print(fundamental.__version__)
|
|
|
385
406
|
|
|
386
407
|
This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
|
|
387
408
|
|
|
409
|
+
## Security
|
|
410
|
+
|
|
411
|
+
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.
|
|
412
|
+
|
|
388
413
|
## Support
|
|
389
414
|
|
|
390
|
-
- **
|
|
415
|
+
- **SDK docs**: [SDK User Guide](https://launch.fundamental.tech/docs/guides/sdk/user-guide)
|
|
416
|
+
- **Issues**: [GitHub Issues](https://github.com/Fundamental-Technologies/fundamental-client/issues)
|
|
391
417
|
- **Email**: [support@fundamental.tech](mailto:support@fundamental.tech)
|
|
@@ -4,8 +4,9 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "fundamental-client"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.5"
|
|
8
8
|
description = "Scikit-learn–compatible client SDK for NEXUS, Fundamental's large model for tabular data"
|
|
9
|
+
readme = {file = "README.md", content-type = "text/markdown"}
|
|
9
10
|
authors = [{name = "Fundamental Tech", email = "support@fundamental.tech"}]
|
|
10
11
|
license = {file = "LICENSE"}
|
|
11
12
|
requires-python = ">=3.10"
|
|
@@ -33,7 +34,7 @@ dependencies = [
|
|
|
33
34
|
]
|
|
34
35
|
|
|
35
36
|
[project.optional-dependencies]
|
|
36
|
-
|
|
37
|
+
aws-marketplace = [
|
|
37
38
|
"boto3>=1.34.0"
|
|
38
39
|
]
|
|
39
40
|
dev = [
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
"""Fundamental Python SDK for tabular machine learning."""
|
|
2
2
|
|
|
3
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
3
4
|
from typing import Optional
|
|
4
5
|
|
|
5
|
-
from fundamental.clients import BaseClient, Fundamental,
|
|
6
|
+
from fundamental.clients import BaseClient, Fundamental, FundamentalAWSMarketplaceClient
|
|
6
7
|
|
|
7
8
|
# Deprecated aliases
|
|
8
9
|
from fundamental.deprecated import FTMClassifier, FTMRegressor
|
|
9
10
|
from fundamental.estimator import NEXUSClassifier, NEXUSRegressor
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
try:
|
|
13
|
+
# Distribution name on PyPI is `fundamental-client` (import name is `fundamental`).
|
|
14
|
+
__version__ = version("fundamental-client")
|
|
15
|
+
except PackageNotFoundError: # pragma: no cover
|
|
16
|
+
__version__ = "unknown"
|
|
12
17
|
|
|
13
18
|
_global_client: Optional[BaseClient] = None
|
|
14
19
|
|
|
@@ -26,7 +31,7 @@ __all__ = [
|
|
|
26
31
|
"FTMClassifier",
|
|
27
32
|
"FTMRegressor",
|
|
28
33
|
"Fundamental",
|
|
29
|
-
"
|
|
34
|
+
"FundamentalAWSMarketplaceClient",
|
|
30
35
|
"NEXUSClassifier",
|
|
31
36
|
"NEXUSRegressor",
|
|
32
37
|
"get_client",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Client implementations for Fundamental API."""
|
|
2
2
|
|
|
3
|
+
from fundamental.clients.aws_marketplace import FundamentalAWSMarketplaceClient
|
|
3
4
|
from fundamental.clients.base import BaseClient
|
|
4
|
-
from fundamental.clients.ec2 import FundamentalEC2Client
|
|
5
5
|
from fundamental.clients.fundamental import Fundamental
|
|
6
6
|
|
|
7
|
-
__all__ = ["BaseClient", "Fundamental", "
|
|
7
|
+
__all__ = ["BaseClient", "Fundamental", "FundamentalAWSMarketplaceClient"]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Fundamental
|
|
1
|
+
"""Fundamental AWS Marketplace client with AWS SigV4 authentication."""
|
|
2
2
|
|
|
3
3
|
from typing import Any, Optional
|
|
4
4
|
|
|
@@ -6,10 +6,10 @@ from fundamental.clients.base import BaseClient
|
|
|
6
6
|
from fundamental.config import Config
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
class
|
|
10
|
-
"""Client for Fundamental API on
|
|
9
|
+
class FundamentalAWSMarketplaceClient(BaseClient):
|
|
10
|
+
"""Client for Fundamental API on AWS Marketplace deployments using AWS SigV4 authentication.
|
|
11
11
|
|
|
12
|
-
This client is
|
|
12
|
+
This client is designed for AWS Marketplace deployments where authentication
|
|
13
13
|
is done via AWS IAM roles instead of API keys. It uses SigV4 signing to
|
|
14
14
|
authenticate requests using the AWS credentials available in the environment.
|
|
15
15
|
"""
|
|
@@ -20,7 +20,7 @@ class FundamentalEC2Client(BaseClient):
|
|
|
20
20
|
api_url: Optional[str] = None,
|
|
21
21
|
**kwargs: Any, # noqa: ANN401
|
|
22
22
|
):
|
|
23
|
-
"""Initialize the Fundamental
|
|
23
|
+
"""Initialize the Fundamental AWS Marketplace client.
|
|
24
24
|
|
|
25
25
|
Args:
|
|
26
26
|
aws_region: AWS region for SigV4 signing (required)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
-
from importlib.metadata import version
|
|
5
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
6
6
|
from typing import Optional
|
|
7
7
|
|
|
8
8
|
from fundamental.constants import (
|
|
@@ -133,6 +133,6 @@ class Config:
|
|
|
133
133
|
def get_version(self) -> str:
|
|
134
134
|
"""Get the SDK version."""
|
|
135
135
|
try:
|
|
136
|
-
return version("fundamental")
|
|
137
|
-
except
|
|
136
|
+
return version("fundamental-client")
|
|
137
|
+
except PackageNotFoundError:
|
|
138
138
|
return "unknown"
|
|
@@ -40,9 +40,9 @@ def _sign_request_sigv4(
|
|
|
40
40
|
from botocore.awsrequest import AWSRequest # pyright: ignore[reportMissingImports]
|
|
41
41
|
except ImportError as e:
|
|
42
42
|
raise ImportError(
|
|
43
|
-
"boto3 is required for
|
|
44
|
-
'Install it with: pip install "fundamental-client[
|
|
45
|
-
'or: uv add "fundamental-client[
|
|
43
|
+
"boto3 is required for AWS Marketplace/SigV4 authentication."
|
|
44
|
+
'Install it with: pip install "fundamental-client[aws-marketplace]" '
|
|
45
|
+
'or: uv add "fundamental-client[aws-marketplace]"'
|
|
46
46
|
) from e
|
|
47
47
|
|
|
48
48
|
session = boto3.Session()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
version = 1
|
|
2
|
-
revision =
|
|
2
|
+
revision = 3
|
|
3
3
|
requires-python = ">=3.10"
|
|
4
4
|
resolution-markers = [
|
|
5
5
|
"python_full_version >= '3.13'",
|
|
@@ -398,7 +398,7 @@ wheels = [
|
|
|
398
398
|
|
|
399
399
|
[[package]]
|
|
400
400
|
name = "fundamental-client"
|
|
401
|
-
version = "0.2.
|
|
401
|
+
version = "0.2.4"
|
|
402
402
|
source = { editable = "." }
|
|
403
403
|
dependencies = [
|
|
404
404
|
{ name = "httpx" },
|
|
@@ -412,6 +412,9 @@ dependencies = [
|
|
|
412
412
|
]
|
|
413
413
|
|
|
414
414
|
[package.optional-dependencies]
|
|
415
|
+
aws-marketplace = [
|
|
416
|
+
{ name = "boto3" },
|
|
417
|
+
]
|
|
415
418
|
dev = [
|
|
416
419
|
{ name = "datamodel-code-generator", extra = ["http"] },
|
|
417
420
|
{ name = "minimum-dependencies" },
|
|
@@ -425,13 +428,10 @@ dev = [
|
|
|
425
428
|
{ name = "python-dotenv" },
|
|
426
429
|
{ name = "ruff" },
|
|
427
430
|
]
|
|
428
|
-
ec2 = [
|
|
429
|
-
{ name = "boto3" },
|
|
430
|
-
]
|
|
431
431
|
|
|
432
432
|
[package.metadata]
|
|
433
433
|
requires-dist = [
|
|
434
|
-
{ name = "boto3", marker = "extra == '
|
|
434
|
+
{ name = "boto3", marker = "extra == 'aws-marketplace'", specifier = ">=1.34.0" },
|
|
435
435
|
{ name = "datamodel-code-generator", extras = ["http"], marker = "extra == 'dev'", specifier = ">=0.26.0" },
|
|
436
436
|
{ name = "httpx", specifier = ">=0.25.2" },
|
|
437
437
|
{ name = "minimum-dependencies", marker = "extra == 'dev'" },
|
|
@@ -452,7 +452,7 @@ requires-dist = [
|
|
|
452
452
|
{ name = "safetensors", specifier = ">=0.5.0" },
|
|
453
453
|
{ name = "scikit-learn", specifier = ">=1.5.0,<2.0.0" },
|
|
454
454
|
]
|
|
455
|
-
provides-extras = ["
|
|
455
|
+
provides-extras = ["aws-marketplace", "dev"]
|
|
456
456
|
|
|
457
457
|
[[package]]
|
|
458
458
|
name = "genson"
|
|
File without changes
|
|
File without changes
|
{fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/ISSUE_TEMPLATE/feature_request.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/workflows/integration-tests.yml
RENAMED
|
File without changes
|
|
File without changes
|
{fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/workflows/pr-name-validation.yml
RENAMED
|
File without changes
|
{fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/workflows/publish-codeartifact-dev.yml
RENAMED
|
File without changes
|
{fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/workflows/publish-codeartifact.yml
RENAMED
|
File without changes
|
|
File without changes
|
{fundamental_client-0.2.4 → fundamental_client-0.2.5}/.github/workflows/publish-testpypi.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/clients/fundamental.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/estimator/classification.py
RENAMED
|
File without changes
|
{fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/estimator/nexus_estimator.py
RENAMED
|
File without changes
|
{fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/estimator/regression.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fundamental_client-0.2.4 → fundamental_client-0.2.5}/src/fundamental/services/feature_importance.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fundamental_client-0.2.4 → fundamental_client-0.2.5}/tests/integration/test_classification.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fundamental_client-0.2.4 → fundamental_client-0.2.5}/tests/unit/test_backward_compatibility.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fundamental_client-0.2.4 → fundamental_client-0.2.5}/tests/unit/test_safetensors_deserialize.py
RENAMED
|
File without changes
|
|
File without changes
|