outerproduct 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ __pycache__/
2
+ *.egg-info/
3
+ .venv/
4
+ .vscode/
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ .claude/
8
+
9
+ .DS_Store
10
+ .agents/
11
+ skills-lock.json
12
+ dist/
13
+ site/
14
+
15
+ # Solve OUT-294
16
+ uv.lock
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OuterProduct
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: outerproduct
3
+ Version: 0.1.0
4
+ Summary: Python SDK for the OuterProduct API
5
+ Project-URL: Documentation, https://docs.outerproduct.com
6
+ Project-URL: Homepage, https://outerproduct.com
7
+ Author: OuterProduct, Inc.
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: explainability,machine-learning,outerproduct,sdk,xai
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.12
23
+ Requires-Dist: httpx~=0.27
24
+ Requires-Dist: numpy~=1.23
25
+ Requires-Dist: outerproduct-http-types~=0.1
26
+ Requires-Dist: pandas~=2.0
27
+ Requires-Dist: pydantic<3,>=2.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: pyarrow>=14.0; extra == 'dev'
30
+ Requires-Dist: pytest; extra == 'dev'
31
+ Requires-Dist: respx; extra == 'dev'
32
+ Provides-Extra: parquet
33
+ Requires-Dist: pyarrow>=14.0; extra == 'parquet'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # outerproduct-sdk
37
+ Python SDK for training and explaining tabular ML models with the OuterProduct API.
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ pip install outerproduct
43
+ ```
44
+
45
+ ## Quick Start
46
+
47
+ ```python
48
+ import outerproduct as op
49
+
50
+ # 1. Initialize the SDK
51
+ op.init(api_key="op_live_...")
52
+
53
+ # 2. Upload data
54
+ connector = op.FileUploadConnector()
55
+ dataset = connector.upload("credit.csv", label_column="default")
56
+
57
+ # 3. Train a reasoning model
58
+ rm = op.reasoning.fit(dataset)
59
+
60
+ # 4. Predict
61
+ predictions = rm.predict(X_new)
62
+
63
+ # 5. Explain
64
+ reasoning = rm.explain(X_new)
65
+ print(reasoning.feature_names[:3])
66
+ print(reasoning.attributions)
67
+ ```
68
+
69
+ You can also set `OUTERPRODUCT_API_KEY` as an environment variable and call `op.init()` with no arguments.
70
+
71
+ ## Usage
72
+
73
+ ### Build a Dataset from Code
74
+
75
+ ```python
76
+ import pandas as pd
77
+ import outerproduct as op
78
+
79
+ df = pd.read_csv("credit.csv")
80
+ dataset = op.Dataset.from_pandas(df, label_column="default")
81
+ ```
82
+
83
+ ### Train a Plain Model (No Explanations)
84
+
85
+ ```python
86
+ trainer = op.Trainer.configure(dataset, model_types=["tabm", "xgboost"])
87
+ model = trainer.run(strategy="random")
88
+ predictions = model.predict(X_new)
89
+ ```
90
+
91
+ ### Distill a Black-Box Model
92
+
93
+ ```python
94
+ # Wrap an external prediction endpoint
95
+ teacher = op.model.Predictor(
96
+ "https://your-model-server.com/predict",
97
+ headers={"Authorization": "Bearer ..."},
98
+ )
99
+
100
+ # Distill into a reasoning model
101
+ rm = op.reasoning.fit(dataset, teacher=teacher)
102
+ ```
103
+
104
+ You can also distill an existing OuterProduct-trained model:
105
+
106
+ ```python
107
+ trained = op.Trainer.configure(dataset).run()
108
+ rm = op.reasoning.fit(dataset, teacher=trained)
109
+ ```
110
+
111
+ ### Reasoning Model Operations
112
+
113
+ ```python
114
+ # Per-sample explanations
115
+ reasoning = rm.explain(X)
116
+
117
+ # Predict + explain in one call
118
+ predictions, reasoning = rm.predict_and_explain(X)
119
+
120
+ # Global feature importance
121
+ reasoning = rm.interpret()
122
+
123
+ # Counterfactual scenario search
124
+ trace = rm.scenario(X, target_class=1, max_steps=10)
125
+
126
+ # Model-aware segmentation
127
+ trace = rm.segment(X, n_clusters=3)
128
+ ```
129
+
130
+ ### Non-Blocking Jobs
131
+
132
+ `reasoning.fit()` blocks until training completes by default. To return immediately:
133
+
134
+ ```python
135
+ rm = op.reasoning.fit(dataset, non_blocking=True)
136
+ ```
137
+
138
+ ### Configuration
139
+
140
+ ```python
141
+ import outerproduct as op
142
+
143
+ # Reads OUTERPRODUCT_API_KEY from environment
144
+ op.init()
145
+
146
+ # All options
147
+ op.init(
148
+ api_key="op_live_...",
149
+ base_url="https://api.outerproduct.ai",
150
+ hardware=op.ModalHardware(),
151
+ )
152
+ ```
153
+
@@ -0,0 +1,118 @@
1
+ # outerproduct-sdk
2
+ Python SDK for training and explaining tabular ML models with the OuterProduct API.
3
+
4
+ ## Installation
5
+
6
+ ```bash
7
+ pip install outerproduct
8
+ ```
9
+
10
+ ## Quick Start
11
+
12
+ ```python
13
+ import outerproduct as op
14
+
15
+ # 1. Initialize the SDK
16
+ op.init(api_key="op_live_...")
17
+
18
+ # 2. Upload data
19
+ connector = op.FileUploadConnector()
20
+ dataset = connector.upload("credit.csv", label_column="default")
21
+
22
+ # 3. Train a reasoning model
23
+ rm = op.reasoning.fit(dataset)
24
+
25
+ # 4. Predict
26
+ predictions = rm.predict(X_new)
27
+
28
+ # 5. Explain
29
+ reasoning = rm.explain(X_new)
30
+ print(reasoning.feature_names[:3])
31
+ print(reasoning.attributions)
32
+ ```
33
+
34
+ You can also set `OUTERPRODUCT_API_KEY` as an environment variable and call `op.init()` with no arguments.
35
+
36
+ ## Usage
37
+
38
+ ### Build a Dataset from Code
39
+
40
+ ```python
41
+ import pandas as pd
42
+ import outerproduct as op
43
+
44
+ df = pd.read_csv("credit.csv")
45
+ dataset = op.Dataset.from_pandas(df, label_column="default")
46
+ ```
47
+
48
+ ### Train a Plain Model (No Explanations)
49
+
50
+ ```python
51
+ trainer = op.Trainer.configure(dataset, model_types=["tabm", "xgboost"])
52
+ model = trainer.run(strategy="random")
53
+ predictions = model.predict(X_new)
54
+ ```
55
+
56
+ ### Distill a Black-Box Model
57
+
58
+ ```python
59
+ # Wrap an external prediction endpoint
60
+ teacher = op.model.Predictor(
61
+ "https://your-model-server.com/predict",
62
+ headers={"Authorization": "Bearer ..."},
63
+ )
64
+
65
+ # Distill into a reasoning model
66
+ rm = op.reasoning.fit(dataset, teacher=teacher)
67
+ ```
68
+
69
+ You can also distill an existing OuterProduct-trained model:
70
+
71
+ ```python
72
+ trained = op.Trainer.configure(dataset).run()
73
+ rm = op.reasoning.fit(dataset, teacher=trained)
74
+ ```
75
+
76
+ ### Reasoning Model Operations
77
+
78
+ ```python
79
+ # Per-sample explanations
80
+ reasoning = rm.explain(X)
81
+
82
+ # Predict + explain in one call
83
+ predictions, reasoning = rm.predict_and_explain(X)
84
+
85
+ # Global feature importance
86
+ reasoning = rm.interpret()
87
+
88
+ # Counterfactual scenario search
89
+ trace = rm.scenario(X, target_class=1, max_steps=10)
90
+
91
+ # Model-aware segmentation
92
+ trace = rm.segment(X, n_clusters=3)
93
+ ```
94
+
95
+ ### Non-Blocking Jobs
96
+
97
+ `reasoning.fit()` blocks until training completes by default. To return immediately:
98
+
99
+ ```python
100
+ rm = op.reasoning.fit(dataset, non_blocking=True)
101
+ ```
102
+
103
+ ### Configuration
104
+
105
+ ```python
106
+ import outerproduct as op
107
+
108
+ # Reads OUTERPRODUCT_API_KEY from environment
109
+ op.init()
110
+
111
+ # All options
112
+ op.init(
113
+ api_key="op_live_...",
114
+ base_url="https://api.outerproduct.ai",
115
+ hardware=op.ModalHardware(),
116
+ )
117
+ ```
118
+
@@ -0,0 +1,109 @@
1
+ [project]
2
+ name = "outerproduct"
3
+ version = "0.1.0"
4
+ description = "Python SDK for the OuterProduct API"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ license = "MIT"
8
+ license-files = ["LICENSE"]
9
+ authors = [
10
+ { name = "OuterProduct, Inc." },
11
+ ]
12
+ keywords = ["explainability", "machine-learning", "outerproduct", "sdk", "xai"]
13
+ classifiers = [
14
+ "Development Status :: 4 - Beta",
15
+ "Intended Audience :: Developers",
16
+ "Intended Audience :: Science/Research",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Operating System :: OS Independent",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Programming Language :: Python :: 3.13",
22
+ "Programming Language :: Python :: 3.14",
23
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
24
+ "Typing :: Typed",
25
+ ]
26
+ dependencies = [
27
+ "httpx~=0.27",
28
+ "numpy~=1.23",
29
+ "outerproduct-http-types~=0.1",
30
+ "pandas~=2.0",
31
+ "pydantic>=2.0,<3"
32
+ ]
33
+
34
+ [project.urls]
35
+ Documentation = "https://docs.outerproduct.com"
36
+ Homepage = "https://outerproduct.com"
37
+
38
+ [project.optional-dependencies]
39
+ dev = ["pytest", "respx", "pyarrow>=14.0"]
40
+ parquet = ["pyarrow>=14.0"]
41
+
42
+ [dependency-groups]
43
+ dev = [
44
+ "prek>=0.3.11",
45
+ "pyarrow>=14.0",
46
+ "pytest>=9.0.3",
47
+ "respx>=0.23.1",
48
+ "ruff>=0.15.12",
49
+ "tombi>=0.9.26",
50
+ "ty>=0.0.33",
51
+ ]
52
+
53
+ [build-system]
54
+ requires = ["hatchling"]
55
+ build-backend = "hatchling.build"
56
+
57
+ [tool.hatch.build.targets.wheel]
58
+ packages = ["src/outerproduct"]
59
+
60
+ [tool.hatch.build.targets.sdist]
61
+ include = [
62
+ "src/outerproduct/**",
63
+ "README.md",
64
+ "LICENSE",
65
+ "pyproject.toml",
66
+ ]
67
+
68
+ [tool.hatch.envs.hatch-test]
69
+ extra-dependencies = ["respx", "pyarrow>=14.0"]
70
+
71
+ [[tool.hatch.envs.hatch-test.matrix]]
72
+ python = ["3.12", "3.13", "3.14"]
73
+
74
+ [tool.ruff]
75
+ include = [
76
+ "benchmarks/**/*.py",
77
+ "benchmarks/**/*.pyi",
78
+ "examples/**/*.py",
79
+ "examples/**/*.pyi",
80
+ "pyproject.toml",
81
+ "scripts/**/*.py",
82
+ "scripts/**/*.pyi",
83
+ "src/**/*.py",
84
+ "src/**/*.pyi",
85
+ "tests/**/*.py",
86
+ "tests/**/*.pyi",
87
+ ]
88
+ extend-exclude = [".agents"]
89
+ force-exclude = true
90
+
91
+ [tool.ruff.lint]
92
+ # Add specific rules you want to disable here
93
+ ignore = [
94
+ "N802", # invalid-function-name (sample_X is ML convention)
95
+ "N803", # invalid-argument-name (X, y are ML convention)
96
+ "N806", # non-lowercase-variable-in-function (same)
97
+ "EM101", # raw-string-in-exception
98
+ "EM102", # f-string-in-exception
99
+ "TRY003", # raise-vanilla-args
100
+ "INP001", # implicit-namespace-package
101
+ "PT006" # pytest-parametrize-names-wrong-type
102
+ ]
103
+
104
+ [tool.tombi.files]
105
+ include = ["*.toml", "**/*.toml"]
106
+ exclude = [".agents/**", ".ruff_cache/**", ".venv/**"]
107
+
108
+ [tool.ty.src]
109
+ include = ["src"]
@@ -0,0 +1,153 @@
1
+ """OuterProduct — a Python SDK for training and explaining tabular ML models.
2
+
3
+ The package exposes a small, flat surface organised around the following
4
+ core concepts:
5
+
6
+ - :class:`~outerproduct.dataset.Dataset` — a tabular dataset with an optional label column and
7
+ per-column schema (:class:`~outerproduct.dataset.Column`).
8
+ - :class:`~outerproduct.connector.Connector` — a source of data (:class:`~outerproduct.connector.FileUploadConnector`,
9
+ :class:`~outerproduct.connector.S3Connector`, …) that produces a :class:`~outerproduct.dataset.Dataset`.
10
+ - :class:`~outerproduct.trainer.Trainer` — orchestrates general-purpose training and
11
+ returns a :class:`~outerproduct.model.Model` via :meth:`~outerproduct.trainer.Trainer.configure` and
12
+ :meth:`~outerproduct.trainer.Trainer.run`.
13
+ - :class:`~outerproduct.model.Model` — a trained predictor with :meth:`~outerproduct.model.Model.predict`.
14
+ - :class:`~outerproduct.model.Predictor` — a duck-typed wrapper around an external
15
+ prediction endpoint, used to hand black-box models into
16
+ :func:`~outerproduct.reasoning.fit` for distillation.
17
+ - :class:`~outerproduct.model.ReasoningModel` — a :class:`~outerproduct.model.Model` that also supports
18
+ :meth:`~outerproduct.model.ReasoningModel.explain`, :meth:`~outerproduct.model.ReasoningModel.interpret`,
19
+ :meth:`~outerproduct.model.ReasoningModel.scenario`, and :meth:`~outerproduct.model.ReasoningModel.segment`.
20
+ Produced by :func:`~outerproduct.reasoning.fit`.
21
+ - :class:`~outerproduct.reasoning.Reasoning` / :class:`~outerproduct.reasoning.ReasoningTrace` — the typed results of
22
+ reasoning calls.
23
+
24
+ Quickstart
25
+ ----------
26
+ .. code-block:: python
27
+
28
+ import outerproduct as op
29
+
30
+ op.init(api_key="...")
31
+ connector = op.FileUploadConnector()
32
+ dataset = connector.upload("customers.csv", label_column="churn")
33
+ reasoning_model = op.reasoning.fit(dataset)
34
+ predictions = reasoning_model.predict(X_new)
35
+ reasoning = reasoning_model.explain(X_new)
36
+ """
37
+
38
+ from __future__ import annotations
39
+
40
+ from dataclasses import dataclass, field
41
+ from importlib.metadata import version as _pkg_version
42
+
43
+ from outerproduct_http_types import ConnectorType
44
+
45
+ from outerproduct import agentic
46
+ from outerproduct.connector import (
47
+ Connector,
48
+ DatabricksConnector,
49
+ FileUploadConnector,
50
+ S3Connector,
51
+ SnowflakeConnector,
52
+ )
53
+ from outerproduct.dataset import Column, Dataset
54
+ from outerproduct.job import Job, ReasoningJob, TrainerJob
55
+ from outerproduct.model import Model, ReasoningModel, predict
56
+ from outerproduct.reasoning import Reasoning, ReasoningTrace
57
+ from outerproduct.trainer import (
58
+ Hardware,
59
+ Metric,
60
+ ModalHardware,
61
+ Trainer,
62
+ )
63
+
64
+ try:
65
+ __version__ = _pkg_version("outerproduct")
66
+ except Exception:
67
+ __version__ = "unknown"
68
+
69
+
70
+ @dataclass
71
+ class _GlobalState:
72
+ """Module-level state populated by :func:`~outerproduct.init`. Internal."""
73
+
74
+ api_key: str | None = None
75
+ base_url: str | None = None
76
+ hardware: Hardware | None = None
77
+ extra: dict[str, object] = field(default_factory=dict)
78
+
79
+
80
+ _state = _GlobalState()
81
+
82
+
83
+ def init(
84
+ api_key: str | None = None,
85
+ *,
86
+ base_url: str | None = None,
87
+ hardware: Hardware | None = None,
88
+ ) -> None:
89
+ """Configure the OuterProduct SDK for the current Python process.
90
+
91
+ Call once near the top of your program. Subsequent operations
92
+ (training, prediction, uploads) read credentials, the API base URL,
93
+ and the default execution backend from the state recorded here.
94
+
95
+ Examples
96
+ --------
97
+ .. code-block:: python
98
+
99
+ import outerproduct as op
100
+ op.init(api_key="op_live_...", hardware=op.ModalHardware())
101
+
102
+ Parameters
103
+ ----------
104
+ api_key : str, optional
105
+ Bearer token used to authenticate against the OuterProduct API.
106
+ If omitted, the ``OUTERPRODUCT_API_KEY`` environment variable is
107
+ consulted at use time.
108
+ base_url : str, optional
109
+ Override for the API base URL. If omitted, the SDK uses the
110
+ production endpoint.
111
+ hardware : Hardware, optional
112
+ Default execution backend used by :class:`~outerproduct.trainer.Trainer`
113
+ and :func:`~outerproduct.reasoning.fit`. If omitted, the API
114
+ server falls back to a managed Modal worker.
115
+ """
116
+ _state.api_key = api_key
117
+ _state.base_url = base_url
118
+ _state.hardware = hardware
119
+
120
+
121
+ __all__ = [
122
+ # Bootstrap
123
+ "init",
124
+ "__version__",
125
+ # Dataset
126
+ "Dataset",
127
+ "Column",
128
+ # Jobs
129
+ "Job",
130
+ "TrainerJob",
131
+ "ReasoningJob",
132
+ # Model
133
+ "Model",
134
+ "ReasoningModel",
135
+ "predict",
136
+ # Reasoning
137
+ "Reasoning",
138
+ "ReasoningTrace",
139
+ # Trainer
140
+ "Trainer",
141
+ "Hardware",
142
+ "ModalHardware",
143
+ "Metric",
144
+ # Connector
145
+ "Connector",
146
+ "ConnectorType",
147
+ "FileUploadConnector",
148
+ "S3Connector",
149
+ "SnowflakeConnector",
150
+ "DatabricksConnector",
151
+ # Agentic feature sourcing (submodule, accessed as op.agentic.*)
152
+ "agentic",
153
+ ]
@@ -0,0 +1,16 @@
1
+ """Agent-driven feature sourcing.
2
+
3
+ Everything under :mod:`outerproduct.agentic` is part of an agent-driven flow
4
+ that turns unstructured or semi-structured sources into typed tabular
5
+ features. The boundary is the *flow*, not whether each individual function
6
+ makes an LLM call — deterministic helpers (PDF parsing, batching, schema
7
+ persistence) live here too because they support the same contract.
8
+
9
+ Submodules
10
+ ----------
11
+ - :mod:`outerproduct.agentic.documents` — files (PDF, image, text).
12
+ """
13
+
14
+ from outerproduct.agentic import documents
15
+
16
+ __all__ = ["documents"]