outerproduct-http-types 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.
- outerproduct_http_types-0.1.0/.gitignore +24 -0
- outerproduct_http_types-0.1.0/LICENSE +21 -0
- outerproduct_http_types-0.1.0/PKG-INFO +78 -0
- outerproduct_http_types-0.1.0/README.md +54 -0
- outerproduct_http_types-0.1.0/pyproject.toml +88 -0
- outerproduct_http_types-0.1.0/src/outerproduct_http_types/__init__.py +117 -0
- outerproduct_http_types-0.1.0/src/outerproduct_http_types/agentic_documents.py +239 -0
- outerproduct_http_types-0.1.0/src/outerproduct_http_types/common.py +49 -0
- outerproduct_http_types-0.1.0/src/outerproduct_http_types/connectors.py +115 -0
- outerproduct_http_types-0.1.0/src/outerproduct_http_types/inference.py +206 -0
- outerproduct_http_types-0.1.0/src/outerproduct_http_types/py.typed +1 -0
- outerproduct_http_types-0.1.0/src/outerproduct_http_types/reasoning.py +163 -0
- outerproduct_http_types-0.1.0/src/outerproduct_http_types/segment.py +59 -0
- outerproduct_http_types-0.1.0/src/outerproduct_http_types/trainer.py +197 -0
- outerproduct_http_types-0.1.0/src/outerproduct_http_types/uploads.py +34 -0
- outerproduct_http_types-0.1.0/src/outerproduct_http_types/workers.py +25 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
.DS_Store
|
|
2
|
+
|
|
3
|
+
# Python bytecode and caches
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.py[cod]
|
|
6
|
+
.pytest_cache/
|
|
7
|
+
.ruff_cache/
|
|
8
|
+
.ty/
|
|
9
|
+
|
|
10
|
+
# Python build artifacts
|
|
11
|
+
build/
|
|
12
|
+
dist/
|
|
13
|
+
*.egg-info/
|
|
14
|
+
|
|
15
|
+
# Local virtual environments
|
|
16
|
+
.venv/
|
|
17
|
+
|
|
18
|
+
# Local editor and environment files
|
|
19
|
+
.env
|
|
20
|
+
.env.*
|
|
21
|
+
!.env.example
|
|
22
|
+
.vscode/
|
|
23
|
+
.idea/
|
|
24
|
+
|
|
@@ -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,78 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: outerproduct-http-types
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Shared HTTP-facing type definitions for OuterProduct services and SDKs.
|
|
5
|
+
Project-URL: Homepage, https://outerproduct.com
|
|
6
|
+
Author: OuterProduct, Inc.
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Keywords: api,http,outerproduct,pydantic,sdk,wire-types
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.12
|
|
22
|
+
Requires-Dist: pydantic>=2.13.3
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# outerproduct-http-types
|
|
26
|
+
|
|
27
|
+
Shared HTTP-facing type definitions for the [OuterProduct](https://outerproduct.com) API.
|
|
28
|
+
|
|
29
|
+
This package contains the [Pydantic](https://docs.pydantic.dev) models that
|
|
30
|
+
describe the request and response shapes used across OuterProduct services and
|
|
31
|
+
SDKs. It is the source of truth for the wire contract between the OuterProduct
|
|
32
|
+
backend and any client (including the official Python SDK).
|
|
33
|
+
|
|
34
|
+
Most users should not depend on this package directly. Instead, install the
|
|
35
|
+
OuterProduct SDK, which re-exports the relevant types and provides a typed
|
|
36
|
+
client. Use this package only when you are building tooling that needs to
|
|
37
|
+
construct or parse OuterProduct API payloads independently of the SDK.
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install outerproduct-http-types
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Requires Python 3.12 or newer.
|
|
46
|
+
|
|
47
|
+
## Usage
|
|
48
|
+
|
|
49
|
+
Import the model that matches the endpoint you are working with and construct
|
|
50
|
+
or validate payloads as you would with any Pydantic model:
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from outerproduct_http_types import PredictRequest, PredictResponse
|
|
54
|
+
|
|
55
|
+
request = PredictRequest(
|
|
56
|
+
samples=[[1.0, "x"], [2.5, "y"]],
|
|
57
|
+
feature_names=["feature_a", "feature_b"],
|
|
58
|
+
)
|
|
59
|
+
payload = request.model_dump_json()
|
|
60
|
+
|
|
61
|
+
# ... POST `payload` to /v1/models/{model_id}/predict, then parse:
|
|
62
|
+
response = PredictResponse.model_validate_json(raw_response_body)
|
|
63
|
+
print(response.model_id, response.predictions)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The package ships with a `py.typed` marker, so type checkers (mypy, pyright,
|
|
67
|
+
ty) will pick up the type information automatically.
|
|
68
|
+
|
|
69
|
+
## Versioning
|
|
70
|
+
|
|
71
|
+
This package follows [semantic versioning](https://semver.org/). Breaking
|
|
72
|
+
changes to wire types are released as a new major version. Minor versions add
|
|
73
|
+
new endpoints or optional fields; patch versions are reserved for documentation
|
|
74
|
+
and non-behavioral fixes.
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
|
|
78
|
+
Licensed under the [MIT License](https://opensource.org/license/mit).
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# outerproduct-http-types
|
|
2
|
+
|
|
3
|
+
Shared HTTP-facing type definitions for the [OuterProduct](https://outerproduct.com) API.
|
|
4
|
+
|
|
5
|
+
This package contains the [Pydantic](https://docs.pydantic.dev) models that
|
|
6
|
+
describe the request and response shapes used across OuterProduct services and
|
|
7
|
+
SDKs. It is the source of truth for the wire contract between the OuterProduct
|
|
8
|
+
backend and any client (including the official Python SDK).
|
|
9
|
+
|
|
10
|
+
Most users should not depend on this package directly. Instead, install the
|
|
11
|
+
OuterProduct SDK, which re-exports the relevant types and provides a typed
|
|
12
|
+
client. Use this package only when you are building tooling that needs to
|
|
13
|
+
construct or parse OuterProduct API payloads independently of the SDK.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install outerproduct-http-types
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Requires Python 3.12 or newer.
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
Import the model that matches the endpoint you are working with and construct
|
|
26
|
+
or validate payloads as you would with any Pydantic model:
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from outerproduct_http_types import PredictRequest, PredictResponse
|
|
30
|
+
|
|
31
|
+
request = PredictRequest(
|
|
32
|
+
samples=[[1.0, "x"], [2.5, "y"]],
|
|
33
|
+
feature_names=["feature_a", "feature_b"],
|
|
34
|
+
)
|
|
35
|
+
payload = request.model_dump_json()
|
|
36
|
+
|
|
37
|
+
# ... POST `payload` to /v1/models/{model_id}/predict, then parse:
|
|
38
|
+
response = PredictResponse.model_validate_json(raw_response_body)
|
|
39
|
+
print(response.model_id, response.predictions)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The package ships with a `py.typed` marker, so type checkers (mypy, pyright,
|
|
43
|
+
ty) will pick up the type information automatically.
|
|
44
|
+
|
|
45
|
+
## Versioning
|
|
46
|
+
|
|
47
|
+
This package follows [semantic versioning](https://semver.org/). Breaking
|
|
48
|
+
changes to wire types are released as a new major version. Minor versions add
|
|
49
|
+
new endpoints or optional fields; patch versions are reserved for documentation
|
|
50
|
+
and non-behavioral fixes.
|
|
51
|
+
|
|
52
|
+
## License
|
|
53
|
+
|
|
54
|
+
Licensed under the [MIT License](https://opensource.org/license/mit).
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "outerproduct-http-types"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Shared HTTP-facing type definitions for OuterProduct services and SDKs."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.12"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "OuterProduct, Inc." },
|
|
10
|
+
]
|
|
11
|
+
keywords = [
|
|
12
|
+
"outerproduct",
|
|
13
|
+
"sdk",
|
|
14
|
+
"http",
|
|
15
|
+
"pydantic",
|
|
16
|
+
"wire-types",
|
|
17
|
+
"api",
|
|
18
|
+
]
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 4 - Beta",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
"Operating System :: OS Independent",
|
|
23
|
+
"Programming Language :: Python",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
26
|
+
"Programming Language :: Python :: 3.12",
|
|
27
|
+
"Programming Language :: Python :: 3.13",
|
|
28
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
29
|
+
"Topic :: Internet :: WWW/HTTP",
|
|
30
|
+
"Typing :: Typed",
|
|
31
|
+
]
|
|
32
|
+
license-files = ["LICENSE"]
|
|
33
|
+
dependencies = [
|
|
34
|
+
"pydantic>=2.13.3",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.urls]
|
|
38
|
+
Homepage = "https://outerproduct.com"
|
|
39
|
+
|
|
40
|
+
[dependency-groups]
|
|
41
|
+
dev = [
|
|
42
|
+
"prek>=0.3.11",
|
|
43
|
+
"pytest>=8.0",
|
|
44
|
+
"ruff>=0.15.12",
|
|
45
|
+
]
|
|
46
|
+
lsp = [
|
|
47
|
+
"ty>=0.0.32",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[build-system]
|
|
51
|
+
requires = ["hatchling>=1.27"]
|
|
52
|
+
build-backend = "hatchling.build"
|
|
53
|
+
|
|
54
|
+
[tool.hatch.build.targets.wheel]
|
|
55
|
+
packages = ["src/outerproduct_http_types"]
|
|
56
|
+
|
|
57
|
+
[tool.hatch.build.targets.sdist]
|
|
58
|
+
include = [
|
|
59
|
+
"src/outerproduct_http_types",
|
|
60
|
+
"README.md",
|
|
61
|
+
"LICENSE",
|
|
62
|
+
"pyproject.toml",
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
[tool.ruff]
|
|
66
|
+
line-length = 100
|
|
67
|
+
target-version = "py312"
|
|
68
|
+
src = ["src"]
|
|
69
|
+
extend-exclude = [".agents"]
|
|
70
|
+
force-exclude = true
|
|
71
|
+
|
|
72
|
+
[tool.ruff.lint]
|
|
73
|
+
select = ["E", "F", "I", "UP", "B", "RUF"]
|
|
74
|
+
|
|
75
|
+
[tool.ruff.lint.isort]
|
|
76
|
+
known-first-party = ["outerproduct_http_types"]
|
|
77
|
+
|
|
78
|
+
[tool.ty.environment]
|
|
79
|
+
python-version = "3.12"
|
|
80
|
+
|
|
81
|
+
[tool.ty.src]
|
|
82
|
+
include = ["src/**/*.py"]
|
|
83
|
+
exclude = [".agents/**"]
|
|
84
|
+
|
|
85
|
+
[tool.ty.terminal]
|
|
86
|
+
output-format = "full"
|
|
87
|
+
error-on-warning = false
|
|
88
|
+
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"""Shared HTTP-facing type definitions for OuterProduct services and SDKs."""
|
|
2
|
+
|
|
3
|
+
from .agentic_documents import (
|
|
4
|
+
AnswerType,
|
|
5
|
+
CreateDocumentUploadRequest,
|
|
6
|
+
CreateDocumentUploadResponse,
|
|
7
|
+
DocumentRef,
|
|
8
|
+
InduceSchemaJobResponse,
|
|
9
|
+
InduceSchemaRequest,
|
|
10
|
+
Question,
|
|
11
|
+
Schema,
|
|
12
|
+
SchemaResultResponse,
|
|
13
|
+
TabularizeJobResponse,
|
|
14
|
+
TabularizeRequest,
|
|
15
|
+
TabularizeResultResponse,
|
|
16
|
+
)
|
|
17
|
+
from .common import (
|
|
18
|
+
ErrorResponse,
|
|
19
|
+
FeatureImportance,
|
|
20
|
+
JobResponse,
|
|
21
|
+
JobStatus,
|
|
22
|
+
StatusResponse,
|
|
23
|
+
)
|
|
24
|
+
from .connectors import (
|
|
25
|
+
ConnectorResponse,
|
|
26
|
+
ConnectorType,
|
|
27
|
+
CreateConnectorRequest,
|
|
28
|
+
DeleteConnectorResponse,
|
|
29
|
+
ListConnectorsResponse,
|
|
30
|
+
ListTablesRequest,
|
|
31
|
+
ListTablesResponse,
|
|
32
|
+
ValidateConnectorResponse,
|
|
33
|
+
)
|
|
34
|
+
from .inference import (
|
|
35
|
+
ExplainRequest,
|
|
36
|
+
ExplainResponse,
|
|
37
|
+
FeatureConstraintSchema,
|
|
38
|
+
InterpretRequest,
|
|
39
|
+
InterpretResponse,
|
|
40
|
+
PredictAndExplainRequest,
|
|
41
|
+
PredictAndExplainResponse,
|
|
42
|
+
PredictRequest,
|
|
43
|
+
PredictResponse,
|
|
44
|
+
ScenarioCandidate,
|
|
45
|
+
ScenarioChange,
|
|
46
|
+
ScenarioRequest,
|
|
47
|
+
ScenarioResponse,
|
|
48
|
+
ScenarioResultItem,
|
|
49
|
+
)
|
|
50
|
+
from .reasoning import ReasoningFitRequest, ReasoningFitResponse
|
|
51
|
+
from .segment import ClusterPersonaSchema, SegmentRequest, SegmentResultResponse
|
|
52
|
+
from .trainer import (
|
|
53
|
+
HardwareSpec,
|
|
54
|
+
ModalHardwareSpec,
|
|
55
|
+
TrainerRunRequest,
|
|
56
|
+
TrainerRunResponse,
|
|
57
|
+
)
|
|
58
|
+
from .uploads import CreateUploadRequest, CreateUploadResponse
|
|
59
|
+
from .workers import WorkerJobRequest, WorkerJobResponse
|
|
60
|
+
|
|
61
|
+
__version__ = "0.1.0"
|
|
62
|
+
|
|
63
|
+
__all__ = [
|
|
64
|
+
"AnswerType",
|
|
65
|
+
"ClusterPersonaSchema",
|
|
66
|
+
"ConnectorResponse",
|
|
67
|
+
"ConnectorType",
|
|
68
|
+
"CreateConnectorRequest",
|
|
69
|
+
"CreateDocumentUploadRequest",
|
|
70
|
+
"CreateDocumentUploadResponse",
|
|
71
|
+
"CreateUploadRequest",
|
|
72
|
+
"CreateUploadResponse",
|
|
73
|
+
"DeleteConnectorResponse",
|
|
74
|
+
"DocumentRef",
|
|
75
|
+
"ErrorResponse",
|
|
76
|
+
"ExplainRequest",
|
|
77
|
+
"ExplainResponse",
|
|
78
|
+
"FeatureConstraintSchema",
|
|
79
|
+
"FeatureImportance",
|
|
80
|
+
"HardwareSpec",
|
|
81
|
+
"InduceSchemaJobResponse",
|
|
82
|
+
"InduceSchemaRequest",
|
|
83
|
+
"InterpretRequest",
|
|
84
|
+
"InterpretResponse",
|
|
85
|
+
"JobResponse",
|
|
86
|
+
"JobStatus",
|
|
87
|
+
"ListConnectorsResponse",
|
|
88
|
+
"ListTablesRequest",
|
|
89
|
+
"ListTablesResponse",
|
|
90
|
+
"ModalHardwareSpec",
|
|
91
|
+
"PredictAndExplainRequest",
|
|
92
|
+
"PredictAndExplainResponse",
|
|
93
|
+
"PredictRequest",
|
|
94
|
+
"PredictResponse",
|
|
95
|
+
"Question",
|
|
96
|
+
"ReasoningFitRequest",
|
|
97
|
+
"ReasoningFitResponse",
|
|
98
|
+
"ScenarioCandidate",
|
|
99
|
+
"ScenarioChange",
|
|
100
|
+
"ScenarioRequest",
|
|
101
|
+
"ScenarioResponse",
|
|
102
|
+
"ScenarioResultItem",
|
|
103
|
+
"Schema",
|
|
104
|
+
"SchemaResultResponse",
|
|
105
|
+
"SegmentRequest",
|
|
106
|
+
"SegmentResultResponse",
|
|
107
|
+
"StatusResponse",
|
|
108
|
+
"TabularizeJobResponse",
|
|
109
|
+
"TabularizeRequest",
|
|
110
|
+
"TabularizeResultResponse",
|
|
111
|
+
"TrainerRunRequest",
|
|
112
|
+
"TrainerRunResponse",
|
|
113
|
+
"ValidateConnectorResponse",
|
|
114
|
+
"WorkerJobRequest",
|
|
115
|
+
"WorkerJobResponse",
|
|
116
|
+
"__version__",
|
|
117
|
+
]
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"""Request/response schemas for the agentic-documents endpoints.
|
|
2
|
+
|
|
3
|
+
Wire format for ``outerproduct.agentic.documents``: per-file presigned
|
|
4
|
+
uploads, async ``induce_schema`` and ``tabularize`` jobs polled via the
|
|
5
|
+
shared ``GET /v1/models/{model_id}/status`` route, and result fetches
|
|
6
|
+
keyed by the same ``model_id``.
|
|
7
|
+
|
|
8
|
+
Endpoint summary:
|
|
9
|
+
|
|
10
|
+
- ``POST /v1/uploads/documents`` -> :class:`CreateDocumentUploadResponse`
|
|
11
|
+
- ``POST /v1/agentic/documents/induce_schema`` -> :class:`InduceSchemaJobResponse`
|
|
12
|
+
- ``GET /v1/agentic/documents/schemas/{model_id}`` -> :class:`SchemaResultResponse`
|
|
13
|
+
- ``POST /v1/agentic/documents/tabularize`` -> :class:`TabularizeJobResponse`
|
|
14
|
+
- ``GET /v1/agentic/documents/tables/{model_id}`` -> :class:`TabularizeResultResponse`
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from enum import StrEnum
|
|
18
|
+
from typing import Any, Literal
|
|
19
|
+
|
|
20
|
+
from pydantic import BaseModel, Field, model_validator
|
|
21
|
+
|
|
22
|
+
from .common import JobResponse
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class AnswerType(StrEnum):
|
|
26
|
+
"""The legal answer shapes for a :class:`Question`."""
|
|
27
|
+
|
|
28
|
+
BOOLEAN = "boolean"
|
|
29
|
+
NUMBER = "number"
|
|
30
|
+
INTEGER = "integer"
|
|
31
|
+
ENUM = "enum"
|
|
32
|
+
MULTI_ENUM = "multi_enum"
|
|
33
|
+
DATE = "date"
|
|
34
|
+
DATE_RANGE = "date_range"
|
|
35
|
+
STRING = "string"
|
|
36
|
+
TEXT = "text"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
_DOCUMENT_MEDIA_TYPES = Literal[
|
|
40
|
+
"application/pdf",
|
|
41
|
+
"image/png",
|
|
42
|
+
"image/jpeg",
|
|
43
|
+
"image/gif",
|
|
44
|
+
"image/webp",
|
|
45
|
+
"text/plain",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class Question(BaseModel):
|
|
50
|
+
"""One survey question in a :class:`Schema`."""
|
|
51
|
+
|
|
52
|
+
id: str = Field(
|
|
53
|
+
...,
|
|
54
|
+
description="Snake-case identifier, unique within the schema.",
|
|
55
|
+
pattern=r"^[a-z][a-z0-9_]*$",
|
|
56
|
+
)
|
|
57
|
+
question: str = Field(..., description="Natural-language prompt the agent answers.")
|
|
58
|
+
answer_type: AnswerType
|
|
59
|
+
rationale: str | None = Field(
|
|
60
|
+
None, description="Why this question is on the schema; surfaced to the agent."
|
|
61
|
+
)
|
|
62
|
+
unit: str | None = Field(
|
|
63
|
+
None, description="Unit string for numeric answers (e.g. 'USD', 'kg')."
|
|
64
|
+
)
|
|
65
|
+
enum: list[str] | None = Field(
|
|
66
|
+
None,
|
|
67
|
+
description="Allowed values when answer_type is 'enum' or 'multi_enum'.",
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
@model_validator(mode="after")
|
|
71
|
+
def _check_enum(self):
|
|
72
|
+
if self.answer_type in (AnswerType.ENUM, AnswerType.MULTI_ENUM):
|
|
73
|
+
if not self.enum:
|
|
74
|
+
raise ValueError(
|
|
75
|
+
f"Question {self.id!r}: answer_type={self.answer_type.value} "
|
|
76
|
+
"requires non-empty `enum`"
|
|
77
|
+
)
|
|
78
|
+
elif self.enum is not None:
|
|
79
|
+
raise ValueError(
|
|
80
|
+
f"Question {self.id!r}: `enum` is only valid for "
|
|
81
|
+
"answer_type='enum' or 'multi_enum'"
|
|
82
|
+
)
|
|
83
|
+
return self
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class Schema(BaseModel):
|
|
87
|
+
"""A frozen list of :class:`Question` for one document type and one use case."""
|
|
88
|
+
|
|
89
|
+
skill: str = Field(..., description="Skill slug (e.g. 'invoice', 'bank-statement').")
|
|
90
|
+
use_case: str = Field(..., description="Use-case description that drove induction.")
|
|
91
|
+
questions: list[Question]
|
|
92
|
+
metadata: dict[str, Any] = Field(default_factory=dict)
|
|
93
|
+
|
|
94
|
+
@model_validator(mode="after")
|
|
95
|
+
def _check_unique_ids(self):
|
|
96
|
+
seen: set[str] = set()
|
|
97
|
+
for q in self.questions:
|
|
98
|
+
if q.id in seen:
|
|
99
|
+
raise ValueError(f"Schema: duplicate question id {q.id!r}")
|
|
100
|
+
seen.add(q.id)
|
|
101
|
+
return self
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# --------------------------------------------------------------------------- #
|
|
105
|
+
# Per-document upload #
|
|
106
|
+
# --------------------------------------------------------------------------- #
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class CreateDocumentUploadRequest(BaseModel):
|
|
110
|
+
"""``POST /v1/uploads/documents`` -- request a presigned URL for one file."""
|
|
111
|
+
|
|
112
|
+
document_id: str = Field(
|
|
113
|
+
...,
|
|
114
|
+
description="Caller-chosen identifier; echoed back in subsequent requests.",
|
|
115
|
+
)
|
|
116
|
+
media_type: _DOCUMENT_MEDIA_TYPES = Field(
|
|
117
|
+
...,
|
|
118
|
+
description="MIME type of the bytes you will PUT to the returned URL.",
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class CreateDocumentUploadResponse(BaseModel):
|
|
123
|
+
document_id: str
|
|
124
|
+
upload_url: str
|
|
125
|
+
upload_key: str = Field(
|
|
126
|
+
...,
|
|
127
|
+
description="Reference to use as DocumentRef.upload_key in induce/tabularize.",
|
|
128
|
+
)
|
|
129
|
+
media_type: _DOCUMENT_MEDIA_TYPES
|
|
130
|
+
expires_in: int = Field(..., description="Seconds until the upload URL expires.")
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class DocumentRef(BaseModel):
|
|
134
|
+
"""One uploaded document, by reference."""
|
|
135
|
+
|
|
136
|
+
document_id: str
|
|
137
|
+
upload_key: str
|
|
138
|
+
media_type: _DOCUMENT_MEDIA_TYPES
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
# --------------------------------------------------------------------------- #
|
|
142
|
+
# induce_schema #
|
|
143
|
+
# --------------------------------------------------------------------------- #
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class InduceSchemaRequest(BaseModel):
|
|
147
|
+
"""``POST /v1/agentic/documents/induce_schema`` -- async schema induction job.
|
|
148
|
+
|
|
149
|
+
Runs the agent over the supplied document sample to produce a frozen
|
|
150
|
+
:class:`Schema`. Submit, poll ``GET /v1/models/{model_id}/status`` until
|
|
151
|
+
``status="completed"``, then fetch the result via
|
|
152
|
+
``GET /v1/agentic/documents/schemas/{model_id}``.
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
documents: list[DocumentRef] = Field(
|
|
156
|
+
...,
|
|
157
|
+
description="Sample of uploaded documents the agent inspects to draft the schema.",
|
|
158
|
+
min_length=1,
|
|
159
|
+
)
|
|
160
|
+
use_case: str = Field(
|
|
161
|
+
...,
|
|
162
|
+
description="Free-text description of what the resulting features will be used for.",
|
|
163
|
+
)
|
|
164
|
+
skill: str = Field(
|
|
165
|
+
...,
|
|
166
|
+
description="Skill slug; one of the values returned by GET /v1/agentic/documents/skills.",
|
|
167
|
+
)
|
|
168
|
+
model_id: str | None = Field(
|
|
169
|
+
None,
|
|
170
|
+
description="Custom model_id for the resulting schema; auto-generated if omitted.",
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class InduceSchemaJobResponse(JobResponse):
|
|
175
|
+
"""``POST /v1/agentic/documents/induce_schema`` -- async submission response."""
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class SchemaResultResponse(BaseModel):
|
|
179
|
+
"""``GET /v1/agentic/documents/schemas/{model_id}`` -- the produced schema."""
|
|
180
|
+
|
|
181
|
+
model_id: str
|
|
182
|
+
schema_: Schema = Field(..., alias="schema")
|
|
183
|
+
|
|
184
|
+
model_config = {"populate_by_name": True}
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
# --------------------------------------------------------------------------- #
|
|
188
|
+
# tabularize #
|
|
189
|
+
# --------------------------------------------------------------------------- #
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class TabularizeRequest(BaseModel):
|
|
193
|
+
"""``POST /v1/agentic/documents/tabularize`` -- async tabularization job.
|
|
194
|
+
|
|
195
|
+
Extracts every uploaded document against ``schema`` and assembles a row
|
|
196
|
+
per document. Submit, poll status, then fetch the result via
|
|
197
|
+
``GET /v1/agentic/documents/tables/{model_id}``.
|
|
198
|
+
"""
|
|
199
|
+
|
|
200
|
+
documents: list[DocumentRef] = Field(..., min_length=1)
|
|
201
|
+
schema_: Schema = Field(..., alias="schema")
|
|
202
|
+
web_augmentation: bool = Field(
|
|
203
|
+
False,
|
|
204
|
+
description="If true, allow the agent to issue web searches to corroborate answers.",
|
|
205
|
+
)
|
|
206
|
+
concurrency: int = Field(
|
|
207
|
+
1,
|
|
208
|
+
ge=1,
|
|
209
|
+
description="Number of documents to extract in parallel on the worker.",
|
|
210
|
+
)
|
|
211
|
+
model_id: str | None = Field(
|
|
212
|
+
None,
|
|
213
|
+
description="Custom model_id for the resulting table; auto-generated if omitted.",
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
model_config = {"populate_by_name": True}
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
class TabularizeJobResponse(JobResponse):
|
|
220
|
+
"""``POST /v1/agentic/documents/tabularize`` -- async submission response."""
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
class TabularizeResultResponse(BaseModel):
|
|
224
|
+
"""``GET /v1/agentic/documents/tables/{model_id}`` -- the tabularized result.
|
|
225
|
+
|
|
226
|
+
The tabularized rows themselves live in object storage under the
|
|
227
|
+
returned ``model_id`` (same path used by trainer.run / reasoning.fit
|
|
228
|
+
in their pre-uploaded mode), so this response is metadata-only:
|
|
229
|
+
enough to construct a :class:`outerproduct.agentic.documents.DocumentDataset`
|
|
230
|
+
handle without materializing rows on the client.
|
|
231
|
+
"""
|
|
232
|
+
|
|
233
|
+
model_id: str
|
|
234
|
+
schema_: Schema = Field(..., alias="schema")
|
|
235
|
+
document_ids: list[str]
|
|
236
|
+
|
|
237
|
+
model_config = {"populate_by_name": True}
|
|
238
|
+
|
|
239
|
+
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Shared types used across all endpoint schemas."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from enum import StrEnum
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class JobStatus(StrEnum):
|
|
11
|
+
PENDING = "pending"
|
|
12
|
+
RUNNING = "running"
|
|
13
|
+
COMPLETED = "completed"
|
|
14
|
+
FAILED = "failed"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ErrorResponse(BaseModel):
|
|
18
|
+
error: str
|
|
19
|
+
detail: str | None = None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class JobResponse(BaseModel):
|
|
23
|
+
"""Base response returned by async job-submission endpoints."""
|
|
24
|
+
|
|
25
|
+
model_id: str = Field(description="Unique identifier for this model")
|
|
26
|
+
status: JobStatus
|
|
27
|
+
message: str
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class StatusResponse(BaseModel):
|
|
31
|
+
"""Returned by GET /models/{model_id}/status."""
|
|
32
|
+
|
|
33
|
+
model_id: str
|
|
34
|
+
job_type: str = Field(description=("One of: trainer_run, reasoning_fit, segment."))
|
|
35
|
+
status: JobStatus
|
|
36
|
+
progress: dict[str, Any] | None = Field(
|
|
37
|
+
None, description='Progress info, e.g. {"step": 3, "total_steps": 5}'
|
|
38
|
+
)
|
|
39
|
+
error_message: str | None = None
|
|
40
|
+
created_at: datetime
|
|
41
|
+
updated_at: datetime
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class FeatureImportance(BaseModel):
|
|
45
|
+
"""A single feature's importance score with direction."""
|
|
46
|
+
|
|
47
|
+
feature_name: str
|
|
48
|
+
importance: float
|
|
49
|
+
direction: str | None = Field(None, description='"positive" or "negative"')
|