outerproduct 0.3.0__tar.gz → 0.3.2__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.
- outerproduct-0.3.2/.gitignore +5 -0
- {outerproduct-0.3.0 → outerproduct-0.3.2}/PKG-INFO +3 -5
- {outerproduct-0.3.0 → outerproduct-0.3.2}/pyproject.toml +13 -21
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/__init__.py +30 -21
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/agentic/documents.py +5 -5
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/client/apis.py +183 -20
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/dataset/__init__.py +24 -9
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/job.py +1 -2
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/model.py +12 -7
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/reasoning/__init__.py +18 -12
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/reasoning/pattern_tracker.py +2 -2
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/trainer.py +13 -12
- outerproduct-0.3.0/.gitignore +0 -16
- {outerproduct-0.3.0 → outerproduct-0.3.2}/LICENSE +0 -0
- {outerproduct-0.3.0 → outerproduct-0.3.2}/README.md +0 -0
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/agentic/__init__.py +0 -0
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/client/__init__.py +0 -0
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/client/_http.py +0 -0
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/client/client.py +0 -0
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/client/exceptions.py +0 -0
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/connector.py +0 -0
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/dataset/datatypes.py +0 -0
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/expr.py +0 -0
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/id.py +0 -0
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/job_result.py +0 -0
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/py.typed +0 -0
- {outerproduct-0.3.0 → outerproduct-0.3.2}/src/outerproduct/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: outerproduct
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Python SDK for the OuterProduct API
|
|
5
5
|
Project-URL: Documentation, https://docs.outerproduct.com
|
|
6
6
|
Project-URL: Homepage, https://outerproduct.com
|
|
@@ -23,17 +23,15 @@ Requires-Python: >=3.12
|
|
|
23
23
|
Requires-Dist: httpx~=0.27
|
|
24
24
|
Requires-Dist: narwhals>=1.13
|
|
25
25
|
Requires-Dist: numpy~=1.23
|
|
26
|
-
Requires-Dist: outerproduct-http-types
|
|
26
|
+
Requires-Dist: outerproduct-http-types>=0.7.3
|
|
27
27
|
Requires-Dist: pandas~=2.0
|
|
28
28
|
Requires-Dist: polars<=1.41.0
|
|
29
|
+
Requires-Dist: pyarrow>=14.0
|
|
29
30
|
Requires-Dist: pydantic<3,>=2.0
|
|
30
31
|
Provides-Extra: dev
|
|
31
32
|
Requires-Dist: anyio; extra == 'dev'
|
|
32
|
-
Requires-Dist: pyarrow>=14.0; extra == 'dev'
|
|
33
33
|
Requires-Dist: pytest; extra == 'dev'
|
|
34
34
|
Requires-Dist: respx; extra == 'dev'
|
|
35
|
-
Provides-Extra: parquet
|
|
36
|
-
Requires-Dist: pyarrow>=14.0; extra == 'parquet'
|
|
37
35
|
Description-Content-Type: text/markdown
|
|
38
36
|
|
|
39
37
|
# outerproduct-sdk
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "outerproduct"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.2"
|
|
4
4
|
description = "Python SDK for the OuterProduct API"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
@@ -27,9 +27,12 @@ dependencies = [
|
|
|
27
27
|
"httpx~=0.27",
|
|
28
28
|
"narwhals>=1.13",
|
|
29
29
|
"numpy~=1.23",
|
|
30
|
-
|
|
30
|
+
# Joint Python package releases raise this floor to the http-types version
|
|
31
|
+
# published with the SDK; in-repo builds resolve it from the path source below.
|
|
32
|
+
"outerproduct-http-types>=0.7.3",
|
|
31
33
|
"pandas~=2.0",
|
|
32
34
|
"polars<=1.41.0",
|
|
35
|
+
"pyarrow>=14.0",
|
|
33
36
|
"pydantic>=2.0,<3",
|
|
34
37
|
]
|
|
35
38
|
|
|
@@ -38,14 +41,12 @@ Documentation = "https://docs.outerproduct.com"
|
|
|
38
41
|
Homepage = "https://outerproduct.com"
|
|
39
42
|
|
|
40
43
|
[project.optional-dependencies]
|
|
41
|
-
dev = ["anyio", "pytest", "respx"
|
|
42
|
-
parquet = ["pyarrow>=14.0"]
|
|
44
|
+
dev = ["anyio", "pytest", "respx"]
|
|
43
45
|
|
|
44
46
|
[dependency-groups]
|
|
45
47
|
dev = [
|
|
46
48
|
"anyio>=4.0",
|
|
47
49
|
"prek>=0.3.11",
|
|
48
|
-
"pyarrow>=14.0",
|
|
49
50
|
"pytest>=9.0.3",
|
|
50
51
|
"respx>=0.23.1",
|
|
51
52
|
"ruff>=0.15.12",
|
|
@@ -69,7 +70,7 @@ include = [
|
|
|
69
70
|
]
|
|
70
71
|
|
|
71
72
|
[tool.hatch.envs.hatch-test]
|
|
72
|
-
extra-dependencies = ["anyio", "respx"
|
|
73
|
+
extra-dependencies = ["anyio", "respx"]
|
|
73
74
|
|
|
74
75
|
[[tool.hatch.envs.hatch-test.matrix]]
|
|
75
76
|
python = ["3.12", "3.13", "3.14"]
|
|
@@ -111,18 +112,9 @@ exclude = [".agents/**", ".ruff_cache/**", ".venv/**"]
|
|
|
111
112
|
[tool.ty.src]
|
|
112
113
|
include = ["src"]
|
|
113
114
|
|
|
114
|
-
#
|
|
115
|
-
#
|
|
116
|
-
#
|
|
117
|
-
#
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
# setting that is stripped at build time, so it never affects the published
|
|
121
|
-
# wheel. NOTE: with the git form, check-main-pins.py requires `branch = "main"`
|
|
122
|
-
# on merges to main — don't commit a non-main pin (or the local path) to main.
|
|
123
|
-
#
|
|
124
|
-
# [tool.uv.sources]
|
|
125
|
-
# # tip of http-types' default branch (CI git-auth is set up for this private repo):
|
|
126
|
-
# outerproduct-http-types = { git = "https://github.com/OuterProduct-ai/outerproduct-http-types.git", branch = "main" }
|
|
127
|
-
# # ...or a local editable checkout for live co-editing:
|
|
128
|
-
# outerproduct-http-types = { path = "../outerproduct-http-types", editable = true }
|
|
115
|
+
# In the monorepo the wire-types package is a sibling under packages/. Resolve
|
|
116
|
+
# it from source so the SDK and its consumers share one copy of http-types.
|
|
117
|
+
# This [tool.uv.sources] override is uv-only and stripped at build time, so the
|
|
118
|
+
# published wheel keeps the PyPI lower bound above.
|
|
119
|
+
[tool.uv.sources]
|
|
120
|
+
outerproduct-http-types = { path = "../http-types" }
|
|
@@ -34,8 +34,8 @@ Quickstart
|
|
|
34
34
|
|
|
35
35
|
op.init(api_key="...")
|
|
36
36
|
dataset = op.LocalDataset.from_csv("customers.csv").upload()
|
|
37
|
-
reasoning_model = op.reasoning.fit(dataset, task=op.
|
|
38
|
-
test_dataset = op.
|
|
37
|
+
reasoning_model = op.reasoning.fit(dataset, task=op.Binclass(label_column="churn"))
|
|
38
|
+
test_dataset = op.LocalDataset.from_pandas(X_new).upload()
|
|
39
39
|
predictions = reasoning_model.predict(test_dataset)
|
|
40
40
|
reasoning = reasoning_model.explain(test_dataset)
|
|
41
41
|
"""
|
|
@@ -49,17 +49,19 @@ from importlib.metadata import version as _pkg_version
|
|
|
49
49
|
from typing import TYPE_CHECKING, Generator
|
|
50
50
|
|
|
51
51
|
from outerproduct_http_types import (
|
|
52
|
-
|
|
52
|
+
Binclass,
|
|
53
53
|
ConnectorType,
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
Forecasting,
|
|
55
|
+
Multiclass,
|
|
56
|
+
Regression,
|
|
57
|
+
SequenceBinclass,
|
|
58
|
+
SequenceMulticlass,
|
|
59
|
+
SequenceRegression,
|
|
60
|
+
Task,
|
|
59
61
|
TaskKind,
|
|
60
62
|
)
|
|
61
63
|
|
|
62
|
-
from outerproduct import agentic
|
|
64
|
+
from outerproduct import agentic, reasoning
|
|
63
65
|
from outerproduct.connector import (
|
|
64
66
|
Connector,
|
|
65
67
|
DatabricksConnector,
|
|
@@ -73,7 +75,13 @@ from outerproduct.dataset import (
|
|
|
73
75
|
LocalDataset,
|
|
74
76
|
)
|
|
75
77
|
from outerproduct.expr import Expr, col
|
|
76
|
-
from outerproduct.job import
|
|
78
|
+
from outerproduct.job import (
|
|
79
|
+
Job,
|
|
80
|
+
JobFailed,
|
|
81
|
+
JobNotReady,
|
|
82
|
+
ReasoningFitJob,
|
|
83
|
+
TrainerJob,
|
|
84
|
+
)
|
|
77
85
|
from outerproduct.job_result import JobResult
|
|
78
86
|
from outerproduct.model import (
|
|
79
87
|
DiffModel,
|
|
@@ -81,15 +89,14 @@ from outerproduct.model import (
|
|
|
81
89
|
ReasoningModel,
|
|
82
90
|
SequenceReasoningModel,
|
|
83
91
|
)
|
|
84
|
-
from outerproduct import reasoning
|
|
85
92
|
from outerproduct.reasoning import (
|
|
86
93
|
Change,
|
|
87
94
|
Counterfactual,
|
|
88
95
|
QueryResult,
|
|
89
96
|
Reasoning,
|
|
90
97
|
ScenarioResult,
|
|
98
|
+
pattern_tracker, # noqa: F401 — makes op.reasoning.pattern_tracker accessible
|
|
91
99
|
)
|
|
92
|
-
from outerproduct.reasoning import pattern_tracker # noqa: F401 — makes op.reasoning.pattern_tracker accessible
|
|
93
100
|
from outerproduct.trainer import (
|
|
94
101
|
Metric,
|
|
95
102
|
Trainer,
|
|
@@ -251,7 +258,7 @@ def get_datasets() -> list[Dataset]:
|
|
|
251
258
|
out: list[Dataset] = []
|
|
252
259
|
for entry in response.datasets:
|
|
253
260
|
dataset = Dataset(entry.connection_config, client, entry.columns)
|
|
254
|
-
dataset.
|
|
261
|
+
dataset._set_id(entry.id)
|
|
255
262
|
out.append(dataset)
|
|
256
263
|
return out
|
|
257
264
|
|
|
@@ -272,7 +279,7 @@ def get_dataset(dataset_id: str) -> Dataset:
|
|
|
272
279
|
client = _resolve_client()
|
|
273
280
|
entry = client.datasets_api.get(dataset_id)
|
|
274
281
|
dataset = Dataset(entry.connection_config, client, entry.columns)
|
|
275
|
-
dataset.
|
|
282
|
+
dataset._set_id(entry.id)
|
|
276
283
|
return dataset
|
|
277
284
|
|
|
278
285
|
|
|
@@ -343,14 +350,16 @@ __all__ = [
|
|
|
343
350
|
# Trainer
|
|
344
351
|
"Trainer",
|
|
345
352
|
"Metric",
|
|
346
|
-
# Task
|
|
347
|
-
"
|
|
353
|
+
# Task
|
|
354
|
+
"Task",
|
|
348
355
|
"TaskKind",
|
|
349
|
-
"
|
|
350
|
-
"
|
|
351
|
-
"
|
|
352
|
-
"
|
|
353
|
-
"
|
|
356
|
+
"Regression",
|
|
357
|
+
"Binclass",
|
|
358
|
+
"Multiclass",
|
|
359
|
+
"Forecasting",
|
|
360
|
+
"SequenceRegression",
|
|
361
|
+
"SequenceBinclass",
|
|
362
|
+
"SequenceMulticlass",
|
|
354
363
|
# Connector
|
|
355
364
|
"Connector",
|
|
356
365
|
"ConnectorType",
|
|
@@ -339,7 +339,7 @@ class DocumentDataset(Dataset):
|
|
|
339
339
|
DatasetColumn(name=q.id, datatype=_ANSWER_TYPE_TO_DATATYPE[q.answer_type])
|
|
340
340
|
for q in schema.questions
|
|
341
341
|
]
|
|
342
|
-
self._id = dataset_id #
|
|
342
|
+
self._id = dataset_id # TODO: deferred DocumentDataset port
|
|
343
343
|
self._connection_config = None
|
|
344
344
|
self._remote_only = True
|
|
345
345
|
self._schema = schema
|
|
@@ -486,7 +486,7 @@ def induce_schema(
|
|
|
486
486
|
submission = op.agentic_documents_api.induce_schema(
|
|
487
487
|
InduceSchemaRequest(documents=refs, use_case=use_case, skill=skill)
|
|
488
488
|
)
|
|
489
|
-
op.wait_for(submission.job_id)
|
|
489
|
+
op.wait_for(str(submission.job_id))
|
|
490
490
|
result = op.agentic_documents_api.get_schema(submission.schema_id)
|
|
491
491
|
return _schema_from_payload(result.schema_)
|
|
492
492
|
|
|
@@ -521,12 +521,12 @@ def tabularize(
|
|
|
521
521
|
}
|
|
522
522
|
)
|
|
523
523
|
)
|
|
524
|
-
op.wait_for(submission.job_id)
|
|
525
|
-
result = op.agentic_documents_api.get_table(submission.dataset_id)
|
|
524
|
+
op.wait_for(str(submission.job_id))
|
|
525
|
+
result = op.agentic_documents_api.get_table(str(submission.dataset_id))
|
|
526
526
|
return DocumentDataset(
|
|
527
527
|
schema=_schema_from_payload(result.schema_),
|
|
528
528
|
document_ids=list(result.document_ids),
|
|
529
|
-
dataset_id=result.dataset_id,
|
|
529
|
+
dataset_id=str(result.dataset_id),
|
|
530
530
|
label_column=label_column,
|
|
531
531
|
)
|
|
532
532
|
|
|
@@ -9,8 +9,10 @@ ergonomic method names without duplicating any type machinery.
|
|
|
9
9
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
|
-
from typing import TYPE_CHECKING, cast
|
|
12
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
13
13
|
|
|
14
|
+
import httpx
|
|
15
|
+
from pydantic import TypeAdapter
|
|
14
16
|
from outerproduct_http_types import (
|
|
15
17
|
CreateDatasetRequest,
|
|
16
18
|
CreateDatasetResponse,
|
|
@@ -24,6 +26,8 @@ from outerproduct_http_types import (
|
|
|
24
26
|
GlobalDriversResponse,
|
|
25
27
|
InduceSchemaJobResponse,
|
|
26
28
|
InduceSchemaRequest,
|
|
29
|
+
JobResultResponse,
|
|
30
|
+
JobResponse,
|
|
27
31
|
ListDatasetEntry,
|
|
28
32
|
ListDatasetsResponse,
|
|
29
33
|
ListModelsResponse,
|
|
@@ -86,6 +90,91 @@ if TYPE_CHECKING:
|
|
|
86
90
|
)
|
|
87
91
|
|
|
88
92
|
|
|
93
|
+
INFERENCE_RESULT_DOWNLOAD_TIMEOUT_SECONDS = 60.0
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def inference_result_download_url(result: JobResultResponse) -> str:
|
|
97
|
+
data = result.result_data or {}
|
|
98
|
+
url = data.get("presigned_url")
|
|
99
|
+
if not isinstance(url, str) or not url:
|
|
100
|
+
raise RuntimeError(
|
|
101
|
+
f"Inference job {result.job_id} result did not include a presigned_url"
|
|
102
|
+
)
|
|
103
|
+
return url
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def parse_inference_payload(
|
|
107
|
+
job_id: str, payload: object, response_type: Any
|
|
108
|
+
) -> Any:
|
|
109
|
+
if not isinstance(payload, dict):
|
|
110
|
+
raise RuntimeError(
|
|
111
|
+
f"Inference job {job_id} result payload was not a JSON object"
|
|
112
|
+
)
|
|
113
|
+
return TypeAdapter(response_type).validate_python(payload)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def assert_inference_payload_object(job_id: str, payload: object) -> dict[str, Any]:
|
|
117
|
+
if not isinstance(payload, dict):
|
|
118
|
+
raise RuntimeError(
|
|
119
|
+
f"Inference job {job_id} result payload was not a JSON object"
|
|
120
|
+
)
|
|
121
|
+
return cast(dict[str, Any], payload)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def download_inference_result(result: JobResultResponse) -> dict[str, Any]:
|
|
125
|
+
response = httpx.get(
|
|
126
|
+
inference_result_download_url(result),
|
|
127
|
+
timeout=INFERENCE_RESULT_DOWNLOAD_TIMEOUT_SECONDS,
|
|
128
|
+
)
|
|
129
|
+
response.raise_for_status()
|
|
130
|
+
return assert_inference_payload_object(str(result.job_id), response.json())
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
async def async_download_inference_result(
|
|
134
|
+
result: JobResultResponse,
|
|
135
|
+
) -> dict[str, Any]:
|
|
136
|
+
async with httpx.AsyncClient(
|
|
137
|
+
timeout=INFERENCE_RESULT_DOWNLOAD_TIMEOUT_SECONDS
|
|
138
|
+
) as client:
|
|
139
|
+
response = await client.get(inference_result_download_url(result))
|
|
140
|
+
response.raise_for_status()
|
|
141
|
+
return assert_inference_payload_object(str(result.job_id), response.json())
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def submit_inference_job(
|
|
145
|
+
client: OuterProductClient,
|
|
146
|
+
endpoint: Any,
|
|
147
|
+
request: Any,
|
|
148
|
+
*,
|
|
149
|
+
model_id: str,
|
|
150
|
+
response_type: Any,
|
|
151
|
+
) -> Any:
|
|
152
|
+
response = cast(JobResponse, client._post(endpoint, request, model_id=model_id))
|
|
153
|
+
job_id = str(response.job_id)
|
|
154
|
+
client.wait_for(job_id)
|
|
155
|
+
result = client.results(job_id)
|
|
156
|
+
payload = download_inference_result(result)
|
|
157
|
+
return TypeAdapter(response_type).validate_python(payload)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
async def async_submit_inference_job(
|
|
161
|
+
client: AsyncOuterProductClient,
|
|
162
|
+
endpoint: Any,
|
|
163
|
+
request: Any,
|
|
164
|
+
*,
|
|
165
|
+
model_id: str,
|
|
166
|
+
response_type: Any,
|
|
167
|
+
) -> Any:
|
|
168
|
+
response = cast(
|
|
169
|
+
JobResponse, await client._post(endpoint, request, model_id=model_id)
|
|
170
|
+
)
|
|
171
|
+
job_id = str(response.job_id)
|
|
172
|
+
await client.wait_for(job_id)
|
|
173
|
+
result = await client.results(job_id)
|
|
174
|
+
payload = await async_download_inference_result(result)
|
|
175
|
+
return TypeAdapter(response_type).validate_python(payload)
|
|
176
|
+
|
|
177
|
+
|
|
89
178
|
class UploadsAPI:
|
|
90
179
|
"""``POST /v1/uploads`` — request a presigned upload URL."""
|
|
91
180
|
|
|
@@ -178,7 +267,12 @@ class ModelsAPI:
|
|
|
178
267
|
|
|
179
268
|
|
|
180
269
|
class InferenceAPI:
|
|
181
|
-
"""
|
|
270
|
+
"""Inference on ``/v1/models/{model_id}/...``.
|
|
271
|
+
|
|
272
|
+
The API runs inference as a job, but this SDK surface preserves the
|
|
273
|
+
synchronous inference contract: each method waits for the job and returns
|
|
274
|
+
the typed inference response.
|
|
275
|
+
"""
|
|
182
276
|
|
|
183
277
|
def __init__(self, client: OuterProductClient) -> None:
|
|
184
278
|
self._client = client
|
|
@@ -186,11 +280,15 @@ class InferenceAPI:
|
|
|
186
280
|
def predict(
|
|
187
281
|
self, model_id: str, request: PredictRequest
|
|
188
282
|
) -> PredictResponse | SequencePredictResponse:
|
|
189
|
-
# cast: the PREDICT endpoint's response_type is this union, but ty
|
|
190
|
-
# can't bind the generic RespT through it; the cast keeps it ty-clean.
|
|
191
283
|
return cast(
|
|
192
284
|
"PredictResponse | SequencePredictResponse",
|
|
193
|
-
|
|
285
|
+
submit_inference_job(
|
|
286
|
+
self._client,
|
|
287
|
+
PREDICT,
|
|
288
|
+
request,
|
|
289
|
+
model_id=model_id,
|
|
290
|
+
response_type=SequencePredictResponse | PredictResponse,
|
|
291
|
+
),
|
|
194
292
|
)
|
|
195
293
|
|
|
196
294
|
def explain(
|
|
@@ -198,23 +296,54 @@ class InferenceAPI:
|
|
|
198
296
|
) -> ExplainResponse | SequenceExplainResponse:
|
|
199
297
|
return cast(
|
|
200
298
|
"ExplainResponse | SequenceExplainResponse",
|
|
201
|
-
|
|
299
|
+
submit_inference_job(
|
|
300
|
+
self._client,
|
|
301
|
+
EXPLAIN,
|
|
302
|
+
request,
|
|
303
|
+
model_id=model_id,
|
|
304
|
+
response_type=SequenceExplainResponse | ExplainResponse,
|
|
305
|
+
),
|
|
202
306
|
)
|
|
203
307
|
|
|
204
308
|
def predict_and_explain(
|
|
205
309
|
self, model_id: str, request: PredictAndExplainRequest
|
|
206
310
|
) -> PredictAndExplainResponse:
|
|
207
|
-
return
|
|
311
|
+
return cast(
|
|
312
|
+
"PredictAndExplainResponse",
|
|
313
|
+
submit_inference_job(
|
|
314
|
+
self._client,
|
|
315
|
+
PREDICT_AND_EXPLAIN,
|
|
316
|
+
request,
|
|
317
|
+
model_id=model_id,
|
|
318
|
+
response_type=PredictAndExplainResponse,
|
|
319
|
+
),
|
|
320
|
+
)
|
|
208
321
|
|
|
209
322
|
def get_global_drivers(
|
|
210
323
|
self, model_id: str, request: GlobalDriversRequest | None = None
|
|
211
324
|
) -> GlobalDriversResponse:
|
|
212
|
-
return
|
|
213
|
-
|
|
325
|
+
return cast(
|
|
326
|
+
"GlobalDriversResponse",
|
|
327
|
+
submit_inference_job(
|
|
328
|
+
self._client,
|
|
329
|
+
GLOBAL_DRIVERS,
|
|
330
|
+
request or GlobalDriversRequest(),
|
|
331
|
+
model_id=model_id,
|
|
332
|
+
response_type=GlobalDriversResponse,
|
|
333
|
+
),
|
|
214
334
|
)
|
|
215
335
|
|
|
216
336
|
def scenario(self, model_id: str, request: ScenarioRequest) -> ScenarioResponse:
|
|
217
|
-
return
|
|
337
|
+
return cast(
|
|
338
|
+
"ScenarioResponse",
|
|
339
|
+
submit_inference_job(
|
|
340
|
+
self._client,
|
|
341
|
+
SCENARIO,
|
|
342
|
+
request,
|
|
343
|
+
model_id=model_id,
|
|
344
|
+
response_type=ScenarioResponse,
|
|
345
|
+
),
|
|
346
|
+
)
|
|
218
347
|
|
|
219
348
|
|
|
220
349
|
class PatternTrackerAPI:
|
|
@@ -369,7 +498,7 @@ class AsyncModelsAPI:
|
|
|
369
498
|
|
|
370
499
|
|
|
371
500
|
class AsyncInferenceAPI:
|
|
372
|
-
"""
|
|
501
|
+
"""Inference on ``/v1/models/{model_id}/...`` for the async client."""
|
|
373
502
|
|
|
374
503
|
def __init__(self, client: AsyncOuterProductClient) -> None:
|
|
375
504
|
self._client = client
|
|
@@ -377,12 +506,15 @@ class AsyncInferenceAPI:
|
|
|
377
506
|
async def predict(
|
|
378
507
|
self, model_id: str, request: PredictRequest
|
|
379
508
|
) -> PredictResponse | SequencePredictResponse:
|
|
380
|
-
# cast: the PREDICT endpoint's response_type is this union, but ty
|
|
381
|
-
# can't bind the generic RespT through it (same limitation the sync
|
|
382
|
-
# InferenceAPI.predict hits); the cast keeps the async twin ty-clean.
|
|
383
509
|
return cast(
|
|
384
510
|
"PredictResponse | SequencePredictResponse",
|
|
385
|
-
await
|
|
511
|
+
await async_submit_inference_job(
|
|
512
|
+
self._client,
|
|
513
|
+
PREDICT,
|
|
514
|
+
request,
|
|
515
|
+
model_id=model_id,
|
|
516
|
+
response_type=SequencePredictResponse | PredictResponse,
|
|
517
|
+
),
|
|
386
518
|
)
|
|
387
519
|
|
|
388
520
|
async def explain(
|
|
@@ -390,25 +522,56 @@ class AsyncInferenceAPI:
|
|
|
390
522
|
) -> ExplainResponse | SequenceExplainResponse:
|
|
391
523
|
return cast(
|
|
392
524
|
"ExplainResponse | SequenceExplainResponse",
|
|
393
|
-
await
|
|
525
|
+
await async_submit_inference_job(
|
|
526
|
+
self._client,
|
|
527
|
+
EXPLAIN,
|
|
528
|
+
request,
|
|
529
|
+
model_id=model_id,
|
|
530
|
+
response_type=SequenceExplainResponse | ExplainResponse,
|
|
531
|
+
),
|
|
394
532
|
)
|
|
395
533
|
|
|
396
534
|
async def predict_and_explain(
|
|
397
535
|
self, model_id: str, request: PredictAndExplainRequest
|
|
398
536
|
) -> PredictAndExplainResponse:
|
|
399
|
-
return
|
|
537
|
+
return cast(
|
|
538
|
+
"PredictAndExplainResponse",
|
|
539
|
+
await async_submit_inference_job(
|
|
540
|
+
self._client,
|
|
541
|
+
PREDICT_AND_EXPLAIN,
|
|
542
|
+
request,
|
|
543
|
+
model_id=model_id,
|
|
544
|
+
response_type=PredictAndExplainResponse,
|
|
545
|
+
),
|
|
546
|
+
)
|
|
400
547
|
|
|
401
548
|
async def get_global_drivers(
|
|
402
549
|
self, model_id: str, request: GlobalDriversRequest | None = None
|
|
403
550
|
) -> GlobalDriversResponse:
|
|
404
|
-
return
|
|
405
|
-
|
|
551
|
+
return cast(
|
|
552
|
+
"GlobalDriversResponse",
|
|
553
|
+
await async_submit_inference_job(
|
|
554
|
+
self._client,
|
|
555
|
+
GLOBAL_DRIVERS,
|
|
556
|
+
request or GlobalDriversRequest(),
|
|
557
|
+
model_id=model_id,
|
|
558
|
+
response_type=GlobalDriversResponse,
|
|
559
|
+
),
|
|
406
560
|
)
|
|
407
561
|
|
|
408
562
|
async def scenario(
|
|
409
563
|
self, model_id: str, request: ScenarioRequest
|
|
410
564
|
) -> ScenarioResponse:
|
|
411
|
-
return
|
|
565
|
+
return cast(
|
|
566
|
+
"ScenarioResponse",
|
|
567
|
+
await async_submit_inference_job(
|
|
568
|
+
self._client,
|
|
569
|
+
SCENARIO,
|
|
570
|
+
request,
|
|
571
|
+
model_id=model_id,
|
|
572
|
+
response_type=ScenarioResponse,
|
|
573
|
+
),
|
|
574
|
+
)
|
|
412
575
|
|
|
413
576
|
|
|
414
577
|
class AsyncPatternTrackerAPI:
|
|
@@ -24,7 +24,6 @@ from typing import TYPE_CHECKING, Any, cast
|
|
|
24
24
|
from outerproduct_http_types import (
|
|
25
25
|
ConnectionConfig,
|
|
26
26
|
DatasetColumn,
|
|
27
|
-
FileUploadConnectionConfig,
|
|
28
27
|
)
|
|
29
28
|
from outerproduct_http_types import Dataset as CreateDatasetRequestBody
|
|
30
29
|
from outerproduct_http_types import FilterExpr as WireFilterExpr
|
|
@@ -41,6 +40,7 @@ from outerproduct.dataset.datatypes import Datatype, coerce, from_narwhals_dtype
|
|
|
41
40
|
if TYPE_CHECKING:
|
|
42
41
|
import numpy as np
|
|
43
42
|
import pandas as pd
|
|
43
|
+
import polars as pl
|
|
44
44
|
from narwhals.stable.v1 import DataFrame as Frame
|
|
45
45
|
from narwhals.stable.v1.typing import IntoDataFrame
|
|
46
46
|
|
|
@@ -82,7 +82,7 @@ class LocalDataset(BaseModel):
|
|
|
82
82
|
return LocalDataset._from_data(df)
|
|
83
83
|
|
|
84
84
|
@staticmethod
|
|
85
|
-
def from_polars(df:
|
|
85
|
+
def from_polars(df: pl.DataFrame) -> LocalDataset:
|
|
86
86
|
return LocalDataset._from_data(df)
|
|
87
87
|
|
|
88
88
|
@staticmethod
|
|
@@ -205,7 +205,15 @@ class LocalDataset(BaseModel):
|
|
|
205
205
|
# ------------------------------------------------------------------
|
|
206
206
|
|
|
207
207
|
def upload(self, client: OuterProductClient | None = None) -> Dataset:
|
|
208
|
-
"""Serialize the rows to Parquet, PUT them,
|
|
208
|
+
"""Serialize the rows to Parquet, PUT them, register the dataset, and
|
|
209
|
+
return a fully-registered :class:`Dataset`.
|
|
210
|
+
|
|
211
|
+
Three server round-trips: ``POST /v1/uploads`` mints the upload's
|
|
212
|
+
connection-config row and presigned PUT, the bytes are PUT to S3, then
|
|
213
|
+
``POST /v1/datasets`` registers the dataset over that config — which
|
|
214
|
+
HEAD-verifies the upload landed and mints the Postgres dataset id. The
|
|
215
|
+
returned handle is registered (``_id`` set), so downstream fit/predict
|
|
216
|
+
calls reuse it without re-registering.
|
|
209
217
|
|
|
210
218
|
``client`` defaults to the one configured via :func:`outerproduct.init`.
|
|
211
219
|
This is the real implementation (the underlying client is synchronous);
|
|
@@ -225,16 +233,23 @@ class LocalDataset(BaseModel):
|
|
|
225
233
|
f"upload cap is {MAX_UPLOAD_BYTES / 1e9:.0f} GB. For larger datasets, "
|
|
226
234
|
"register an external connector (S3, Snowflake, Databricks) instead."
|
|
227
235
|
)
|
|
228
|
-
|
|
236
|
+
upload_response = client.uploads_api.create(
|
|
237
|
+
CreateUploadRequest(file_format="parquet")
|
|
238
|
+
)
|
|
229
239
|
with httpx.Client() as http:
|
|
230
240
|
put_resp = http.put(
|
|
231
|
-
|
|
241
|
+
upload_response.upload_url,
|
|
232
242
|
content=body,
|
|
233
|
-
headers={"Content-Type":
|
|
243
|
+
headers={"Content-Type": upload_response.content_type},
|
|
234
244
|
)
|
|
235
245
|
put_resp.raise_for_status()
|
|
236
|
-
|
|
237
|
-
|
|
246
|
+
# The server minted the file_upload_connection_config row and returned
|
|
247
|
+
# it as ``connection_config`` (the upload URI is no longer the id).
|
|
248
|
+
# Register the dataset now so the Postgres-generated id is assigned and
|
|
249
|
+
# the upload is verified server-side before returning.
|
|
250
|
+
ds = Dataset(upload_response.connection_config, client, self.columns)
|
|
251
|
+
ds._ensure_registered()
|
|
252
|
+
return ds
|
|
238
253
|
|
|
239
254
|
async def aupload(self, client: OuterProductClient | None = None) -> Dataset:
|
|
240
255
|
"""Async :meth:`upload`.
|
|
@@ -297,7 +312,7 @@ class Dataset(BaseModel):
|
|
|
297
312
|
connection_config, _resolve_client(), columns if columns is not None else []
|
|
298
313
|
)
|
|
299
314
|
|
|
300
|
-
def
|
|
315
|
+
def _set_id(self, dataset_id: ID) -> None:
|
|
301
316
|
"""Cache the server-assigned id from a fit/predict response."""
|
|
302
317
|
self._id = dataset_id
|
|
303
318
|
|
|
@@ -30,7 +30,6 @@ from outerproduct.utils import _client
|
|
|
30
30
|
if TYPE_CHECKING:
|
|
31
31
|
from outerproduct.model import Model, ReasoningModel, SequenceReasoningModel
|
|
32
32
|
|
|
33
|
-
|
|
34
33
|
class JobFailed(RuntimeError):
|
|
35
34
|
"""Raised by :meth:`Job.results` when the server reports status='failed'."""
|
|
36
35
|
|
|
@@ -90,7 +89,7 @@ class Job:
|
|
|
90
89
|
if body.status == "failed":
|
|
91
90
|
raise JobFailed(body.error_message or f"job {self._job_id} failed")
|
|
92
91
|
return JobResult(
|
|
93
|
-
job_id=body.job_id,
|
|
92
|
+
job_id=str(body.job_id),
|
|
94
93
|
result_uri=body.result_uri,
|
|
95
94
|
completed_at=body.completed_at,
|
|
96
95
|
raw=dict(body.result_data or {}),
|
|
@@ -15,8 +15,8 @@ End-to-end shape:
|
|
|
15
15
|
|
|
16
16
|
import outerproduct as op
|
|
17
17
|
dataset = op.LocalDataset.from_csv("data.csv").upload()
|
|
18
|
-
reasoning_model = op.reasoning.fit(dataset, label_column="churn")
|
|
19
|
-
test_dataset = op.
|
|
18
|
+
reasoning_model = op.reasoning.fit(dataset, task=op.Binclass(label_column="churn"))
|
|
19
|
+
test_dataset = op.LocalDataset.from_pandas(test_df).upload()
|
|
20
20
|
predictions = reasoning_model.predict(test_dataset)
|
|
21
21
|
reasoning = reasoning_model.explain(test_dataset)
|
|
22
22
|
"""
|
|
@@ -31,6 +31,7 @@ if TYPE_CHECKING:
|
|
|
31
31
|
import numpy as np
|
|
32
32
|
from outerproduct_http_types import Dataset as WireDataset
|
|
33
33
|
from outerproduct_http_types import ExplainResponse
|
|
34
|
+
from outerproduct_http_types import SequenceExplainResponse
|
|
34
35
|
|
|
35
36
|
from outerproduct.dataset import Dataset, DatasetColumn
|
|
36
37
|
from outerproduct.reasoning import Reasoning, ScenarioResult
|
|
@@ -209,9 +210,9 @@ class Model:
|
|
|
209
210
|
Parameters
|
|
210
211
|
----------
|
|
211
212
|
dataset : :class:`~outerproduct.dataset.Dataset`
|
|
212
|
-
Input features.
|
|
213
|
-
``
|
|
214
|
-
|
|
213
|
+
Input features. Build one with
|
|
214
|
+
``op.LocalDataset.from_*(...).upload()`` (or a connector) — the
|
|
215
|
+
SDK does not accept a raw DataFrame / ndarray.
|
|
215
216
|
|
|
216
217
|
Returns
|
|
217
218
|
-------
|
|
@@ -574,7 +575,8 @@ class SequenceReasoningModel(Model):
|
|
|
574
575
|
"""A sequence-task model: ``predict`` + per-entity ``explain`` only.
|
|
575
576
|
|
|
576
577
|
Returned by :func:`~outerproduct.reasoning.fit` when the task is a
|
|
577
|
-
:class:`~outerproduct_http_types.
|
|
578
|
+
sequence variant (:class:`~outerproduct_http_types.SequenceBinclass` /
|
|
579
|
+
:class:`~outerproduct_http_types.SequenceMulticlass`). Inherits ``predict``
|
|
578
580
|
(one prediction per entity). ``explain`` returns the per-entity attribution
|
|
579
581
|
tensor. The flat-reasoning surfaces (``scenario``, ``get_global_drivers``,
|
|
580
582
|
``predict_and_explain``, and ``PatternTracker``) do not apply to sequence
|
|
@@ -597,7 +599,10 @@ class SequenceReasoningModel(Model):
|
|
|
597
599
|
|
|
598
600
|
spec = _dataset_spec(dataset, "SequenceReasoningModel.explain")
|
|
599
601
|
with _client() as c:
|
|
600
|
-
resp =
|
|
602
|
+
resp = cast(
|
|
603
|
+
"SequenceExplainResponse",
|
|
604
|
+
c.inference_api.explain(self._id, ExplainRequest(dataset=spec)),
|
|
605
|
+
)
|
|
601
606
|
return Reasoning(feature_names=[], attributions=np.asarray(resp.attributions))
|
|
602
607
|
|
|
603
608
|
@staticmethod
|
|
@@ -19,8 +19,8 @@ Examples
|
|
|
19
19
|
import outerproduct as op
|
|
20
20
|
|
|
21
21
|
dataset = op.LocalDataset.from_csv("data.csv").upload()
|
|
22
|
-
rm = op.reasoning.fit(dataset, task=op.
|
|
23
|
-
reasoning = rm.explain(op.
|
|
22
|
+
rm = op.reasoning.fit(dataset, task=op.Binclass(label_column="churn"))
|
|
23
|
+
reasoning = rm.explain(op.LocalDataset.from_pandas(X).upload())
|
|
24
24
|
reasoning.feature_names[:3]
|
|
25
25
|
"""
|
|
26
26
|
|
|
@@ -31,7 +31,7 @@ from typing import TYPE_CHECKING, Any
|
|
|
31
31
|
|
|
32
32
|
if TYPE_CHECKING:
|
|
33
33
|
import numpy as np
|
|
34
|
-
from outerproduct_http_types import
|
|
34
|
+
from outerproduct_http_types import Task
|
|
35
35
|
|
|
36
36
|
from outerproduct.dataset import Dataset
|
|
37
37
|
from outerproduct.job import ReasoningFitJob
|
|
@@ -155,7 +155,7 @@ class ScenarioResult:
|
|
|
155
155
|
def fit(
|
|
156
156
|
dataset: Dataset,
|
|
157
157
|
*,
|
|
158
|
-
task:
|
|
158
|
+
task: Task | None = None,
|
|
159
159
|
teacher: Model | Predictor | None = None,
|
|
160
160
|
model_types: list[str] | None = None,
|
|
161
161
|
metric: Metric | list[Metric] | None = None,
|
|
@@ -188,7 +188,7 @@ def fit(
|
|
|
188
188
|
dataset = op.LocalDataset.from_csv("customers.csv").upload()
|
|
189
189
|
|
|
190
190
|
# Supervised: train against labels.
|
|
191
|
-
rm = op.reasoning.fit(dataset, task=op.
|
|
191
|
+
rm = op.reasoning.fit(dataset, task=op.Binclass(label_column="churn")).wait()
|
|
192
192
|
|
|
193
193
|
# Distill an external prediction API.
|
|
194
194
|
teacher = op.model.Predictor(
|
|
@@ -199,7 +199,7 @@ def fit(
|
|
|
199
199
|
|
|
200
200
|
# Distill an existing OuterProduct-trained model.
|
|
201
201
|
trained = op.Trainer.configure(
|
|
202
|
-
dataset, task=op.
|
|
202
|
+
dataset, task=op.Binclass(label_column="churn")
|
|
203
203
|
).run().wait()
|
|
204
204
|
rm_wrapped = op.reasoning.fit(dataset, teacher=trained).wait()
|
|
205
205
|
|
|
@@ -207,9 +207,9 @@ def fit(
|
|
|
207
207
|
----------
|
|
208
208
|
dataset : :class:`~outerproduct.dataset.Dataset`
|
|
209
209
|
Training data.
|
|
210
|
-
task : :class:`~outerproduct_http_types.
|
|
210
|
+
task : :class:`~outerproduct_http_types.Task`, optional
|
|
211
211
|
The learning task and its target columns (e.g.
|
|
212
|
-
``op.
|
|
212
|
+
``op.Regression(label_column=...)``). Required for supervised
|
|
213
213
|
fits; ignored when ``teacher`` is set (the teacher provides the
|
|
214
214
|
training target).
|
|
215
215
|
teacher : :class:`~outerproduct.model.Model` or :class:`~outerproduct.model.Predictor`, optional
|
|
@@ -288,13 +288,19 @@ def fit(
|
|
|
288
288
|
|
|
289
289
|
with _client() as client:
|
|
290
290
|
resp = client.reasoning_api.fit(request)
|
|
291
|
-
dataset.
|
|
291
|
+
dataset._set_id(resp.dataset_id)
|
|
292
292
|
|
|
293
|
-
from outerproduct_http_types import
|
|
293
|
+
from outerproduct_http_types import (
|
|
294
|
+
SequenceBinclass,
|
|
295
|
+
SequenceMulticlass,
|
|
296
|
+
SequenceRegression,
|
|
297
|
+
)
|
|
294
298
|
|
|
295
299
|
return ReasoningFitJob(
|
|
296
|
-
resp.job_id,
|
|
300
|
+
str(resp.job_id),
|
|
297
301
|
feature_names=ds_feature_names,
|
|
298
302
|
label_column=label_column,
|
|
299
|
-
is_sequence=isinstance(
|
|
303
|
+
is_sequence=isinstance(
|
|
304
|
+
task, (SequenceRegression, SequenceBinclass, SequenceMulticlass)
|
|
305
|
+
),
|
|
300
306
|
)
|
|
@@ -10,7 +10,7 @@ Quickstart
|
|
|
10
10
|
|
|
11
11
|
op.init(api_key="...")
|
|
12
12
|
ds = op.LocalDataset.from_csv("data.csv").upload()
|
|
13
|
-
rm = op.reasoning.fit(ds, task=op.
|
|
13
|
+
rm = op.reasoning.fit(ds, task=op.Binclass(label_column="churn"))
|
|
14
14
|
pt = op.reasoning.pattern_tracker.fit(rm, ds, target_range=(0.5, None))
|
|
15
15
|
|
|
16
16
|
pt.patterns # tuple[FilterPattern, ...]
|
|
@@ -254,7 +254,7 @@ def fit(
|
|
|
254
254
|
resp = c.pattern_tracker_api.create_fit(reasoning_model.id, request)
|
|
255
255
|
|
|
256
256
|
return PatternTrackerJob(
|
|
257
|
-
job_id=resp.job_id,
|
|
257
|
+
job_id=str(resp.job_id),
|
|
258
258
|
model_id=reasoning_model.id,
|
|
259
259
|
tracker_id=resp.tracker_id,
|
|
260
260
|
)
|
|
@@ -33,12 +33,12 @@ Examples
|
|
|
33
33
|
dataset = op.LocalDataset.from_csv("data.csv").upload()
|
|
34
34
|
trainer = op.Trainer.configure(
|
|
35
35
|
dataset,
|
|
36
|
-
task=op.
|
|
36
|
+
task=op.Binclass(label_column="churn"),
|
|
37
37
|
model_types=["tabm", "xgboost"],
|
|
38
38
|
)
|
|
39
39
|
job = trainer.run(strategy="optuna")
|
|
40
40
|
model = job.wait()
|
|
41
|
-
predictions = model.predict(op.
|
|
41
|
+
predictions = model.predict(op.LocalDataset.from_pandas(X).upload())
|
|
42
42
|
"""
|
|
43
43
|
|
|
44
44
|
from __future__ import annotations
|
|
@@ -48,7 +48,7 @@ from dataclasses import dataclass
|
|
|
48
48
|
from typing import TYPE_CHECKING, Any
|
|
49
49
|
|
|
50
50
|
if TYPE_CHECKING:
|
|
51
|
-
from outerproduct_http_types import
|
|
51
|
+
from outerproduct_http_types import Task, TrainerRunRequest
|
|
52
52
|
|
|
53
53
|
from outerproduct.dataset import Dataset
|
|
54
54
|
from outerproduct.job import TrainerJob
|
|
@@ -105,7 +105,7 @@ class Trainer:
|
|
|
105
105
|
self,
|
|
106
106
|
dataset: Dataset,
|
|
107
107
|
*,
|
|
108
|
-
task:
|
|
108
|
+
task: Task | None,
|
|
109
109
|
model_types: list[str] | None,
|
|
110
110
|
metric: Metric | list[Metric] | None,
|
|
111
111
|
teacher: Model | Predictor | None,
|
|
@@ -121,7 +121,7 @@ class Trainer:
|
|
|
121
121
|
cls,
|
|
122
122
|
dataset: Dataset,
|
|
123
123
|
*,
|
|
124
|
-
task:
|
|
124
|
+
task: Task | None = None,
|
|
125
125
|
model_types: list[str] | None = None,
|
|
126
126
|
metric: Metric | list[Metric] | None = None,
|
|
127
127
|
teacher: Model | Predictor | None = None,
|
|
@@ -132,13 +132,14 @@ class Trainer:
|
|
|
132
132
|
----------
|
|
133
133
|
dataset : :class:`~outerproduct.dataset.Dataset`
|
|
134
134
|
Training data.
|
|
135
|
-
task : :class:`~outerproduct_http_types.
|
|
135
|
+
task : :class:`~outerproduct_http_types.Task`, optional
|
|
136
136
|
The learning task and its target columns — one of
|
|
137
|
-
``
|
|
138
|
-
``
|
|
139
|
-
``label_column``; the
|
|
140
|
-
|
|
141
|
-
``
|
|
137
|
+
``Regression``, ``Binclass``, ``Multiclass``, ``Forecasting``,
|
|
138
|
+
``SequenceRegression``, ``SequenceBinclass``, or
|
|
139
|
+
``SequenceMulticlass`` (each carries ``label_column``; the
|
|
140
|
+
time-series / sequence variants also carry ``id_column`` /
|
|
141
|
+
``timestamp_column``). Required unless a ``teacher`` is given
|
|
142
|
+
(the teacher then supplies the target).
|
|
142
143
|
model_types : list of str, optional
|
|
143
144
|
Candidate model-family identifiers (e.g. ``["tabm",
|
|
144
145
|
"xgboost"]``). Resolved server-side. Defaults to a curated
|
|
@@ -221,7 +222,7 @@ class Trainer:
|
|
|
221
222
|
|
|
222
223
|
with _client() as client:
|
|
223
224
|
resp = client.trainer_api.run(request)
|
|
224
|
-
self._dataset.
|
|
225
|
+
self._dataset._set_id(resp.dataset_id)
|
|
225
226
|
|
|
226
227
|
label_column = self._task.label_column if self._task is not None else None
|
|
227
228
|
|
outerproduct-0.3.0/.gitignore
DELETED
|
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
|