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.
Files changed (76) hide show
  1. fundamental_client-0.2.5/.release-please-manifest.json +3 -0
  2. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/CHANGELOG.md +15 -0
  3. fundamental_client-0.2.5/CONTRIBUTING.md +156 -0
  4. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/PKG-INFO +423 -4
  5. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/README.md +43 -136
  6. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/pyproject.toml +4 -3
  7. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/scripts/bootstrap +1 -1
  8. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/__init__.py +8 -3
  9. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/clients/__init__.py +2 -2
  10. fundamental_client-0.2.3/src/fundamental/clients/ec2.py → fundamental_client-0.2.5/src/fundamental/clients/aws_marketplace.py +5 -5
  11. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/config.py +3 -3
  12. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/constants.py +1 -1
  13. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/utils/http.py +3 -3
  14. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/uv.lock +7 -7
  15. fundamental_client-0.2.3/.release-please-manifest.json +0 -3
  16. fundamental_client-0.2.3/CONTRIBUTING.md +0 -74
  17. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  18. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  19. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  20. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/dependabot.yml +0 -0
  21. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/labeler.yml +0 -0
  22. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/settings.yml +0 -0
  23. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/ci.yml +0 -0
  24. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/e2e-pr-comment.yml +0 -0
  25. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/integration-tests.yml +0 -0
  26. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/labeler.yml +0 -0
  27. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/pr-name-validation.yml +0 -0
  28. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/publish-codeartifact-dev.yml +0 -0
  29. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/publish-codeartifact.yml +0 -0
  30. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/publish-pypi.yml +0 -0
  31. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/publish-testpypi.yml +0 -0
  32. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.github/workflows/release-please.yml +0 -0
  33. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.gitignore +0 -0
  34. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.pre-commit-config.yaml +0 -0
  35. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/.yamllint +0 -0
  36. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/CODEOWNERS +0 -0
  37. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/LICENSE +0 -0
  38. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/noxfile.py +0 -0
  39. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/release-please-config.json +0 -0
  40. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/scripts/format +0 -0
  41. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/scripts/generate-models +0 -0
  42. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/scripts/integration-tests +0 -0
  43. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/scripts/lint +0 -0
  44. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/scripts/test +0 -0
  45. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/scripts/unit-tests +0 -0
  46. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/clients/base.py +0 -0
  47. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/clients/fundamental.py +0 -0
  48. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/deprecated.py +0 -0
  49. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/estimator/__init__.py +0 -0
  50. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/estimator/base.py +0 -0
  51. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/estimator/classification.py +0 -0
  52. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/estimator/nexus_estimator.py +0 -0
  53. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/estimator/regression.py +0 -0
  54. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/exceptions.py +0 -0
  55. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/models/__init__.py +0 -0
  56. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/models/generated.py +0 -0
  57. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/services/__init__.py +0 -0
  58. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/services/feature_importance.py +0 -0
  59. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/services/inference.py +0 -0
  60. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/services/models.py +0 -0
  61. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/utils/__init__.py +0 -0
  62. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/utils/data.py +0 -0
  63. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/utils/polling.py +0 -0
  64. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/src/fundamental/utils/safetensors_deserialize.py +0 -0
  65. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/conftest.py +0 -0
  66. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/integration/__init__.py +0 -0
  67. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/integration/test_classification.py +0 -0
  68. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/integration/test_regression.py +0 -0
  69. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/unit/__init__.py +0 -0
  70. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/unit/conftest.py +0 -0
  71. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/unit/test_backward_compatibility.py +0 -0
  72. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/unit/test_config.py +0 -0
  73. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/unit/test_data_utils.py +0 -0
  74. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/unit/test_estimators.py +0 -0
  75. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/unit/test_safetensors_deserialize.py +0 -0
  76. {fundamental_client-0.2.3 → fundamental_client-0.2.5}/tests/unit/test_sklearn_compliance.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.2.5"
3
+ }
@@ -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
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
- Provides-Extra: ec2
241
- Requires-Dist: boto3>=1.34.0; extra == 'ec2'
242
+ Description-Content-Type: text/markdown
243
+
244
+ # Fundamental Python SDK
245
+
246
+ [![PyPI version](https://img.shields.io/pypi/v/fundamental-client.svg?label=pypi%20package)](https://pypi.org/project/fundamental-client/)
247
+ [![Python Versions](https://img.shields.io/pypi/pyversions/fundamental-client?color=%2334D058)](https://pypi.org/project/fundamental-client)
248
+ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](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)