xrtm-data 0.2.6__tar.gz → 0.3.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.
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/PKG-INFO +20 -15
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/README.md +19 -10
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/pyproject.toml +2 -8
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/src/xrtm/data/__init__.py +8 -1
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/src/xrtm/data/core/schemas/__init__.py +8 -0
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/src/xrtm/data/core/schemas/forecast.py +202 -37
- xrtm_data-0.3.0/src/xrtm/data/corpora/__init__.py +56 -0
- xrtm_data-0.3.0/src/xrtm/data/corpora/_builtin_corpora.py +61 -0
- {xrtm_data-0.2.6/src/xrtm/data/providers/local → xrtm_data-0.3.0/src/xrtm/data/providers}/__init__.py +1 -5
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/src/xrtm/data/providers/online/__init__.py +3 -2
- xrtm_data-0.3.0/src/xrtm/data/providers/online/metaculus.py +155 -0
- xrtm_data-0.3.0/src/xrtm/data/providers/online/polymarket.py +161 -0
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/src/xrtm/data/version.py +1 -1
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/src/xrtm_data.egg-info/PKG-INFO +20 -15
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/src/xrtm_data.egg-info/SOURCES.txt +1 -20
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/src/xrtm_data.egg-info/requires.txt +0 -4
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/tests/test_corpus_registry.py +0 -45
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/tests/test_schemas.py +34 -10
- xrtm_data-0.2.6/src/xrtm/data/cli/__init__.py +0 -330
- xrtm_data-0.2.6/src/xrtm/data/corpora/__init__.py +0 -99
- xrtm_data-0.2.6/src/xrtm/data/corpora/_builtin_corpora.py +0 -185
- xrtm_data-0.2.6/src/xrtm/data/corpora/forecast_importer.py +0 -517
- xrtm_data-0.2.6/src/xrtm/data/corpora/importers.py +0 -296
- xrtm_data-0.2.6/src/xrtm/data/corpora/splits.py +0 -261
- xrtm_data-0.2.6/src/xrtm/data/kit/__init__.py +0 -33
- xrtm_data-0.2.6/src/xrtm/data/kit/processors/__init__.py +0 -212
- xrtm_data-0.2.6/src/xrtm/data/providers/__init__.py +0 -28
- xrtm_data-0.2.6/src/xrtm/data/providers/local/csv.py +0 -176
- xrtm_data-0.2.6/src/xrtm/data/providers/online/polymarket.py +0 -256
- xrtm_data-0.2.6/src/xrtm/data/providers/subgraph/__init__.py +0 -25
- xrtm_data-0.2.6/src/xrtm/data/providers/subgraph/polymarket.py +0 -357
- xrtm_data-0.2.6/src/xrtm_data.egg-info/entry_points.txt +0 -2
- xrtm_data-0.2.6/tests/test_beta_fitter.py +0 -147
- xrtm_data-0.2.6/tests/test_cli_loading.py +0 -42
- xrtm_data-0.2.6/tests/test_cli_ux.py +0 -41
- xrtm_data-0.2.6/tests/test_corpus_importers.py +0 -270
- xrtm_data-0.2.6/tests/test_corpus_splits.py +0 -278
- xrtm_data-0.2.6/tests/test_forecast_importer.py +0 -302
- xrtm_data-0.2.6/tests/test_local_datasource.py +0 -214
- xrtm_data-0.2.6/tests/test_polymarket_source.py +0 -150
- xrtm_data-0.2.6/tests/test_polymarket_subgraph.py +0 -286
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/LICENSE +0 -0
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/setup.cfg +0 -0
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/src/xrtm/data/core/__init__.py +0 -0
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/src/xrtm/data/core/interfaces.py +0 -0
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/src/xrtm/data/core/schemas/prior.py +0 -0
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/src/xrtm/data/core/schemas/trade.py +0 -0
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/src/xrtm/data/corpora/real_binary.py +0 -0
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/src/xrtm/data/corpora/registry.py +0 -0
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/src/xrtm_data.egg-info/dependency_links.txt +0 -0
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/src/xrtm_data.egg-info/top_level.txt +0 -0
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/tests/test_prior_schemas.py +0 -0
- {xrtm_data-0.2.6 → xrtm_data-0.3.0}/tests/test_real_binary_corpus.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xrtm-data
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: The Snapshot Vault for XRTM.
|
|
5
5
|
Author-email: XRTM Team <moy@xrtm.org>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -8,11 +8,7 @@ Requires-Python: <3.13,>=3.11
|
|
|
8
8
|
Description-Content-Type: text/markdown
|
|
9
9
|
License-File: LICENSE
|
|
10
10
|
Requires-Dist: pydantic>=2.0.0
|
|
11
|
-
Requires-Dist: aiohttp>=3.9.0
|
|
12
11
|
Requires-Dist: scipy>=1.11.0
|
|
13
|
-
Requires-Dist: click>=8.0.0
|
|
14
|
-
Requires-Dist: rich>=13.0.0
|
|
15
|
-
Requires-Dist: pyarrow>=14.0.0
|
|
16
12
|
Provides-Extra: dev
|
|
17
13
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
18
14
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
@@ -51,19 +47,28 @@ pip install xrtm-data
|
|
|
51
47
|
## Core Primitives
|
|
52
48
|
|
|
53
49
|
### 1. The Forecast Object Standard
|
|
54
|
-
Adhering to strict
|
|
50
|
+
Adhering to strict Governance, the canonical runtime schema is
|
|
51
|
+
`ForecastResult` (legacy alias: `ForecastOutput`). Every forecast result carries
|
|
52
|
+
`forecast_request_id`, `probability`, a `reasoning_trace`, and an optional
|
|
53
|
+
`execution_trace`. Legacy `question_id`, `reasoning`, `logical_trace`,
|
|
54
|
+
`logical_edges`, and `structural_trace` inputs remain accepted for compatibility.
|
|
55
55
|
|
|
56
56
|
```python
|
|
57
|
-
from xrtm.data import
|
|
57
|
+
from xrtm.data import ForecastResult, CausalNode
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
forecast_result = ForecastResult(
|
|
60
|
+
forecast_request_id="q_123",
|
|
61
61
|
probability=0.75,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
reasoning_trace={
|
|
63
|
+
"narrative": "Base rate analysis suggests...",
|
|
64
|
+
"causal_graph": {
|
|
65
|
+
"nodes": [
|
|
66
|
+
CausalNode(event="Inflation rises", probability=0.8),
|
|
67
|
+
CausalNode(event="Fed cuts rates", probability=0.4),
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
execution_trace=["ingestion", "forecast"],
|
|
67
72
|
)
|
|
68
73
|
```
|
|
69
74
|
|
|
@@ -76,7 +81,7 @@ The `MetadataBase` enforces a strict `snapshot_time`. This timestamp represents
|
|
|
76
81
|
src/xrtm/data/
|
|
77
82
|
├── core/ # Interfaces & Schemas (domain-agnostic)
|
|
78
83
|
│ ├── interfaces.py # DataSource protocol
|
|
79
|
-
│ └── schemas/ #
|
|
84
|
+
│ └── schemas/ # ForecastRequest, ForecastResult, etc.
|
|
80
85
|
├── kit/ # Composable utilities (processors)
|
|
81
86
|
└── providers/ # External data source implementations
|
|
82
87
|
├── local/ # LocalDataSource (JSON files)
|
|
@@ -28,19 +28,28 @@ pip install xrtm-data
|
|
|
28
28
|
## Core Primitives
|
|
29
29
|
|
|
30
30
|
### 1. The Forecast Object Standard
|
|
31
|
-
Adhering to strict
|
|
31
|
+
Adhering to strict Governance, the canonical runtime schema is
|
|
32
|
+
`ForecastResult` (legacy alias: `ForecastOutput`). Every forecast result carries
|
|
33
|
+
`forecast_request_id`, `probability`, a `reasoning_trace`, and an optional
|
|
34
|
+
`execution_trace`. Legacy `question_id`, `reasoning`, `logical_trace`,
|
|
35
|
+
`logical_edges`, and `structural_trace` inputs remain accepted for compatibility.
|
|
32
36
|
|
|
33
37
|
```python
|
|
34
|
-
from xrtm.data import
|
|
38
|
+
from xrtm.data import ForecastResult, CausalNode
|
|
35
39
|
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
forecast_result = ForecastResult(
|
|
41
|
+
forecast_request_id="q_123",
|
|
38
42
|
probability=0.75,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
reasoning_trace={
|
|
44
|
+
"narrative": "Base rate analysis suggests...",
|
|
45
|
+
"causal_graph": {
|
|
46
|
+
"nodes": [
|
|
47
|
+
CausalNode(event="Inflation rises", probability=0.8),
|
|
48
|
+
CausalNode(event="Fed cuts rates", probability=0.4),
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
execution_trace=["ingestion", "forecast"],
|
|
44
53
|
)
|
|
45
54
|
```
|
|
46
55
|
|
|
@@ -53,7 +62,7 @@ The `MetadataBase` enforces a strict `snapshot_time`. This timestamp represents
|
|
|
53
62
|
src/xrtm/data/
|
|
54
63
|
├── core/ # Interfaces & Schemas (domain-agnostic)
|
|
55
64
|
│ ├── interfaces.py # DataSource protocol
|
|
56
|
-
│ └── schemas/ #
|
|
65
|
+
│ └── schemas/ # ForecastRequest, ForecastResult, etc.
|
|
57
66
|
├── kit/ # Composable utilities (processors)
|
|
58
67
|
└── providers/ # External data source implementations
|
|
59
68
|
├── local/ # LocalDataSource (JSON files)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "xrtm-data"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.0"
|
|
8
8
|
description = "The Snapshot Vault for XRTM."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11,<3.13"
|
|
@@ -14,11 +14,7 @@ authors = [
|
|
|
14
14
|
]
|
|
15
15
|
dependencies = [
|
|
16
16
|
"pydantic>=2.0.0",
|
|
17
|
-
"aiohttp>=3.9.0",
|
|
18
17
|
"scipy>=1.11.0",
|
|
19
|
-
"click>=8.0.0",
|
|
20
|
-
"rich>=13.0.0",
|
|
21
|
-
"pyarrow>=14.0.0",
|
|
22
18
|
]
|
|
23
19
|
|
|
24
20
|
[project.optional-dependencies]
|
|
@@ -30,9 +26,6 @@ dev = [
|
|
|
30
26
|
"mypy>=1.0.0",
|
|
31
27
|
]
|
|
32
28
|
|
|
33
|
-
[project.scripts]
|
|
34
|
-
xrtm-data = "xrtm.data.cli:main"
|
|
35
|
-
|
|
36
29
|
[tool.setuptools]
|
|
37
30
|
package-dir = {"" = "src"}
|
|
38
31
|
packages = {find = {where = ["src"], include = ["xrtm*"], namespaces = true}}
|
|
@@ -55,3 +48,4 @@ python_version = "3.11"
|
|
|
55
48
|
ignore_missing_imports = true
|
|
56
49
|
strict = false
|
|
57
50
|
explicit_package_bases = true
|
|
51
|
+
exclude = ["build/", "dist/"]
|
|
@@ -27,7 +27,6 @@ Structure:
|
|
|
27
27
|
|
|
28
28
|
Example:
|
|
29
29
|
>>> from xrtm.data import ForecastQuestion, DataSource
|
|
30
|
-
>>> from xrtm.data.providers import LocalDataSource
|
|
31
30
|
"""
|
|
32
31
|
|
|
33
32
|
# Core interfaces
|
|
@@ -36,11 +35,15 @@ from xrtm.data.core import DataSource, DataSourceError, SourceFetchError, Source
|
|
|
36
35
|
# Core schemas (public API)
|
|
37
36
|
from xrtm.data.core.schemas import (
|
|
38
37
|
CausalEdge,
|
|
38
|
+
CausalGraph,
|
|
39
39
|
CausalNode,
|
|
40
40
|
ConfidenceInterval,
|
|
41
41
|
ForecastOutput,
|
|
42
42
|
ForecastQuestion,
|
|
43
|
+
ForecastRequest,
|
|
44
|
+
ForecastResult,
|
|
43
45
|
MetadataBase,
|
|
46
|
+
ReasoningTrace,
|
|
44
47
|
)
|
|
45
48
|
|
|
46
49
|
__all__ = [
|
|
@@ -52,8 +55,12 @@ __all__ = [
|
|
|
52
55
|
# Schemas
|
|
53
56
|
"MetadataBase",
|
|
54
57
|
"ForecastQuestion",
|
|
58
|
+
"ForecastRequest",
|
|
55
59
|
"ForecastOutput",
|
|
60
|
+
"ForecastResult",
|
|
56
61
|
"CausalNode",
|
|
57
62
|
"CausalEdge",
|
|
63
|
+
"CausalGraph",
|
|
64
|
+
"ReasoningTrace",
|
|
58
65
|
"ConfidenceInterval",
|
|
59
66
|
]
|
|
@@ -21,11 +21,15 @@ This module exports all Pydantic schemas used across the xrtm ecosystem.
|
|
|
21
21
|
|
|
22
22
|
from xrtm.data.core.schemas.forecast import (
|
|
23
23
|
CausalEdge,
|
|
24
|
+
CausalGraph,
|
|
24
25
|
CausalNode,
|
|
25
26
|
ConfidenceInterval,
|
|
26
27
|
ForecastOutput,
|
|
27
28
|
ForecastQuestion,
|
|
29
|
+
ForecastRequest,
|
|
30
|
+
ForecastResult,
|
|
28
31
|
MetadataBase,
|
|
32
|
+
ReasoningTrace,
|
|
29
33
|
)
|
|
30
34
|
from xrtm.data.core.schemas.prior import BetaPrior, PriorState
|
|
31
35
|
from xrtm.data.core.schemas.trade import TradeEvent, TradeWindow
|
|
@@ -34,9 +38,13 @@ __all__ = [
|
|
|
34
38
|
# Forecast schemas
|
|
35
39
|
"MetadataBase",
|
|
36
40
|
"ForecastQuestion",
|
|
41
|
+
"ForecastRequest",
|
|
37
42
|
"ForecastOutput",
|
|
43
|
+
"ForecastResult",
|
|
38
44
|
"CausalNode",
|
|
39
45
|
"CausalEdge",
|
|
46
|
+
"CausalGraph",
|
|
47
|
+
"ReasoningTrace",
|
|
40
48
|
"ConfidenceInterval",
|
|
41
49
|
# Prior schemas
|
|
42
50
|
"BetaPrior",
|
|
@@ -25,8 +25,9 @@ Example:
|
|
|
25
25
|
>>> q = ForecastQuestion(id="q1", title="Will it rain tomorrow?")
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
|
+
from collections.abc import ItemsView, KeysView, ValuesView
|
|
28
29
|
from datetime import datetime, timezone
|
|
29
|
-
from typing import Any, Dict, List, Optional
|
|
30
|
+
from typing import Any, Dict, Generator, List, Optional
|
|
30
31
|
|
|
31
32
|
from pydantic import AliasChoices, BaseModel, ConfigDict, Field, field_validator, model_validator
|
|
32
33
|
|
|
@@ -118,6 +119,9 @@ class ForecastQuestion(BaseModel):
|
|
|
118
119
|
return self.description
|
|
119
120
|
|
|
120
121
|
|
|
122
|
+
ForecastRequest = ForecastQuestion
|
|
123
|
+
|
|
124
|
+
|
|
121
125
|
class CausalNode(BaseModel):
|
|
122
126
|
r"""
|
|
123
127
|
Represents a single step in a logical reasoning chain.
|
|
@@ -151,7 +155,7 @@ class CausalEdge(BaseModel):
|
|
|
151
155
|
|
|
152
156
|
source: str = Field(..., description="ID of the source node")
|
|
153
157
|
target: str = Field(..., description="ID of the target node")
|
|
154
|
-
weight: float = Field(default=1.0, ge
|
|
158
|
+
weight: float = Field(default=1.0, ge=-1, le=1, description="Strength of causal relationship (negative = inhibitory)")
|
|
155
159
|
description: Optional[str] = Field(None, description="Context for this causal link")
|
|
156
160
|
|
|
157
161
|
|
|
@@ -170,6 +174,76 @@ class ConfidenceInterval(BaseModel):
|
|
|
170
174
|
level: float = Field(0.9, ge=0, le=1, description="Confidence level")
|
|
171
175
|
|
|
172
176
|
|
|
177
|
+
class MappingCompatibleModel(BaseModel):
|
|
178
|
+
r"""Base model with lightweight dict-style compatibility helpers."""
|
|
179
|
+
|
|
180
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
181
|
+
r"""Provide dict-style access for compatibility shims."""
|
|
182
|
+
return getattr(self, key, default)
|
|
183
|
+
|
|
184
|
+
def __getitem__(self, key: str) -> Any:
|
|
185
|
+
return getattr(self, key)
|
|
186
|
+
|
|
187
|
+
def __contains__(self, key: object) -> bool:
|
|
188
|
+
return isinstance(key, str) and hasattr(self, key)
|
|
189
|
+
|
|
190
|
+
def items(self) -> ItemsView[str, Any]:
|
|
191
|
+
return self.model_dump(exclude_none=True).items()
|
|
192
|
+
|
|
193
|
+
def keys(self) -> KeysView[str]:
|
|
194
|
+
return self.model_dump(exclude_none=True).keys()
|
|
195
|
+
|
|
196
|
+
def values(self) -> ValuesView[Any]:
|
|
197
|
+
return self.model_dump(exclude_none=True).values()
|
|
198
|
+
|
|
199
|
+
def __iter__(self) -> Generator[tuple[str, Any], None, None]:
|
|
200
|
+
for item in self.model_dump(exclude_none=True).items():
|
|
201
|
+
yield item
|
|
202
|
+
|
|
203
|
+
def __len__(self) -> int:
|
|
204
|
+
return len(self.model_dump(exclude_none=True))
|
|
205
|
+
|
|
206
|
+
def __eq__(self, other: object) -> bool:
|
|
207
|
+
if isinstance(other, dict):
|
|
208
|
+
return self.model_dump(exclude_none=True) == other
|
|
209
|
+
return super().__eq__(other)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
class CausalGraph(MappingCompatibleModel):
|
|
213
|
+
r"""Qualified causal graph embedded inside a reasoning trace."""
|
|
214
|
+
|
|
215
|
+
nodes: List[CausalNode] = Field(
|
|
216
|
+
default_factory=list,
|
|
217
|
+
description="Ordered forecast-path nodes inside the qualified causal graph",
|
|
218
|
+
)
|
|
219
|
+
edges: List[CausalEdge] = Field(
|
|
220
|
+
default_factory=list,
|
|
221
|
+
description="Qualified causal graph edges connecting forecast-path nodes",
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
class ReasoningTrace(MappingCompatibleModel):
|
|
226
|
+
r"""Canonical reasoning trace payload for a forecast result."""
|
|
227
|
+
|
|
228
|
+
narrative: str = Field("", description="Narrative reasoning for the forecast result")
|
|
229
|
+
causal_graph: CausalGraph = Field(
|
|
230
|
+
default_factory=CausalGraph,
|
|
231
|
+
description="Qualified causal graph for structured forecast-path reasoning",
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
@property
|
|
235
|
+
def forecast_path(self) -> List[CausalNode]:
|
|
236
|
+
r"""Canonical alias for ordered reasoning nodes."""
|
|
237
|
+
return self.causal_graph.nodes
|
|
238
|
+
|
|
239
|
+
@forecast_path.setter
|
|
240
|
+
def forecast_path(self, value: List[CausalNode] | List[Dict[str, Any]]) -> None:
|
|
241
|
+
r"""Backward-compatible setter for forecast-path nodes."""
|
|
242
|
+
self.causal_graph.nodes = [
|
|
243
|
+
node if isinstance(node, CausalNode) else CausalNode.model_validate(node) for node in value
|
|
244
|
+
]
|
|
245
|
+
|
|
246
|
+
|
|
173
247
|
class ForecastOutput(BaseModel):
|
|
174
248
|
r"""
|
|
175
249
|
The structured result of an agent's forecasting reasoning.
|
|
@@ -178,19 +252,23 @@ class ForecastOutput(BaseModel):
|
|
|
178
252
|
complete reasoning chain that led to it, enabling audit and calibration.
|
|
179
253
|
|
|
180
254
|
Attributes:
|
|
181
|
-
|
|
255
|
+
forecast_request_id: Reference to the input forecast request.
|
|
182
256
|
probability: The assigned probability of the primary outcome.
|
|
183
257
|
uncertainty: Optional measure of forecast uncertainty.
|
|
184
258
|
confidence_interval: Range for calibration.
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
logical_edges: Causal dependencies between nodes.
|
|
188
|
-
structural_trace: Order of graph nodes executed.
|
|
259
|
+
reasoning_trace: Narrative reasoning plus a qualified causal graph.
|
|
260
|
+
execution_trace: Ordered workflow stages executed to produce the result.
|
|
189
261
|
calibration_metrics: Performance metrics.
|
|
190
262
|
metadata: Associated temporal and source metadata.
|
|
191
263
|
"""
|
|
192
264
|
|
|
193
|
-
|
|
265
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
266
|
+
|
|
267
|
+
forecast_request_id: str = Field(
|
|
268
|
+
...,
|
|
269
|
+
validation_alias=AliasChoices("forecast_request_id", "question_id"),
|
|
270
|
+
description="Reference to the input forecast request",
|
|
271
|
+
)
|
|
194
272
|
probability: float = Field(
|
|
195
273
|
...,
|
|
196
274
|
alias="confidence",
|
|
@@ -201,49 +279,76 @@ class ForecastOutput(BaseModel):
|
|
|
201
279
|
)
|
|
202
280
|
uncertainty: Optional[float] = Field(None, ge=0, le=1, description="Measure of forecast uncertainty")
|
|
203
281
|
confidence_interval: Optional[ConfidenceInterval] = None
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
282
|
+
reasoning_trace: ReasoningTrace = Field(
|
|
283
|
+
...,
|
|
284
|
+
description="Narrative reasoning trace with a qualified causal graph",
|
|
285
|
+
)
|
|
286
|
+
execution_trace: List[str] = Field(
|
|
287
|
+
default_factory=list,
|
|
288
|
+
validation_alias=AliasChoices("execution_trace", "structural_trace"),
|
|
289
|
+
description="Ordered workflow stages executed for this forecast result",
|
|
207
290
|
)
|
|
208
|
-
logical_edges: List[CausalEdge] = Field(default_factory=list, description="Causal dependencies between nodes")
|
|
209
|
-
structural_trace: List[str] = Field(default_factory=list, description="Order of graph nodes executed")
|
|
210
291
|
calibration_metrics: Dict[str, Any] = Field(default_factory=dict, description="Performance metrics")
|
|
211
292
|
metadata: MetadataBase = Field(default_factory=MetadataBase) # type: ignore[arg-type]
|
|
212
293
|
|
|
213
294
|
@model_validator(mode="before")
|
|
214
295
|
@classmethod
|
|
215
|
-
def
|
|
216
|
-
r"""
|
|
217
|
-
if not isinstance(data, dict)
|
|
296
|
+
def _normalize_runtime_aliases(cls, data: Any) -> Any:
|
|
297
|
+
r"""Normalize legacy runtime aliases into the canonical result vocabulary."""
|
|
298
|
+
if not isinstance(data, dict):
|
|
218
299
|
return data
|
|
219
300
|
|
|
220
|
-
trace = data["reasoning_trace"]
|
|
221
301
|
updated = dict(data)
|
|
222
|
-
if
|
|
223
|
-
|
|
224
|
-
|
|
302
|
+
if "question_id" in updated and "forecast_request_id" not in updated:
|
|
303
|
+
updated["forecast_request_id"] = updated["question_id"]
|
|
304
|
+
if "structural_trace" in updated and "execution_trace" not in updated:
|
|
305
|
+
updated["execution_trace"] = updated["structural_trace"]
|
|
306
|
+
|
|
307
|
+
trace = updated.get("reasoning_trace")
|
|
308
|
+
if isinstance(trace, list):
|
|
309
|
+
trace = {
|
|
310
|
+
"narrative": str(updated.get("reasoning", "")),
|
|
311
|
+
"causal_graph": {
|
|
312
|
+
"nodes": trace,
|
|
313
|
+
"edges": updated.get("logical_edges", []),
|
|
314
|
+
},
|
|
315
|
+
}
|
|
316
|
+
updated["reasoning_trace"] = trace
|
|
225
317
|
|
|
318
|
+
if isinstance(trace, dict):
|
|
319
|
+
trace_dict = dict(trace)
|
|
320
|
+
if "narrative" not in trace_dict and isinstance(updated.get("reasoning"), str):
|
|
321
|
+
trace_dict["narrative"] = updated["reasoning"]
|
|
226
322
|
causal_graph = trace.get("causal_graph")
|
|
227
|
-
if isinstance(causal_graph, dict):
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
323
|
+
if not isinstance(causal_graph, dict):
|
|
324
|
+
causal_graph = {}
|
|
325
|
+
causal_graph = dict(causal_graph)
|
|
326
|
+
if "nodes" not in causal_graph and "logical_trace" in updated:
|
|
327
|
+
causal_graph["nodes"] = updated["logical_trace"]
|
|
328
|
+
if "edges" not in causal_graph and "logical_edges" in updated:
|
|
329
|
+
causal_graph["edges"] = updated["logical_edges"]
|
|
330
|
+
trace_dict["causal_graph"] = causal_graph
|
|
331
|
+
updated["reasoning_trace"] = trace_dict
|
|
332
|
+
elif any(key in updated for key in ("reasoning", "logical_trace", "logical_edges")):
|
|
333
|
+
updated["reasoning_trace"] = {
|
|
334
|
+
"narrative": str(updated.get("reasoning", "")),
|
|
335
|
+
"causal_graph": {
|
|
336
|
+
"nodes": updated.get("logical_trace", []),
|
|
337
|
+
"edges": updated.get("logical_edges", []),
|
|
338
|
+
},
|
|
339
|
+
}
|
|
234
340
|
|
|
235
341
|
return updated
|
|
236
342
|
|
|
237
343
|
@property
|
|
238
|
-
def
|
|
239
|
-
r"""
|
|
240
|
-
return
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
344
|
+
def question_id(self) -> str:
|
|
345
|
+
r"""Backward compatibility alias for ``forecast_request_id``."""
|
|
346
|
+
return self.forecast_request_id
|
|
347
|
+
|
|
348
|
+
@question_id.setter
|
|
349
|
+
def question_id(self, value: str) -> None:
|
|
350
|
+
r"""Backward compatibility setter for ``forecast_request_id``."""
|
|
351
|
+
self.forecast_request_id = value
|
|
247
352
|
|
|
248
353
|
@property
|
|
249
354
|
def confidence(self) -> float:
|
|
@@ -255,9 +360,63 @@ class ForecastOutput(BaseModel):
|
|
|
255
360
|
r"""Backward compatibility setter for probability."""
|
|
256
361
|
self.probability = value
|
|
257
362
|
|
|
363
|
+
@property
|
|
364
|
+
def reasoning(self) -> str:
|
|
365
|
+
r"""Backward compatibility alias for ``reasoning_trace.narrative``."""
|
|
366
|
+
return self.reasoning_trace.narrative
|
|
367
|
+
|
|
368
|
+
@reasoning.setter
|
|
369
|
+
def reasoning(self, value: str) -> None:
|
|
370
|
+
r"""Backward compatibility setter for ``reasoning_trace.narrative``."""
|
|
371
|
+
self.reasoning_trace.narrative = value
|
|
372
|
+
|
|
373
|
+
@property
|
|
374
|
+
def logical_trace(self) -> List[CausalNode]:
|
|
375
|
+
r"""Backward compatibility alias for reasoning-trace nodes."""
|
|
376
|
+
return self.reasoning_trace.causal_graph.nodes
|
|
377
|
+
|
|
378
|
+
@logical_trace.setter
|
|
379
|
+
def logical_trace(self, value: List[CausalNode] | List[Dict[str, Any]]) -> None:
|
|
380
|
+
r"""Backward compatibility setter for reasoning-trace nodes."""
|
|
381
|
+
self.reasoning_trace.causal_graph.nodes = [
|
|
382
|
+
node if isinstance(node, CausalNode) else CausalNode.model_validate(node) for node in value
|
|
383
|
+
]
|
|
384
|
+
|
|
385
|
+
@property
|
|
386
|
+
def logical_edges(self) -> List[CausalEdge]:
|
|
387
|
+
r"""Backward compatibility alias for reasoning-trace edges."""
|
|
388
|
+
return self.reasoning_trace.causal_graph.edges
|
|
389
|
+
|
|
390
|
+
@logical_edges.setter
|
|
391
|
+
def logical_edges(self, value: List[CausalEdge] | List[Dict[str, Any]]) -> None:
|
|
392
|
+
r"""Backward compatibility setter for reasoning-trace edges."""
|
|
393
|
+
self.reasoning_trace.causal_graph.edges = [
|
|
394
|
+
edge if isinstance(edge, CausalEdge) else CausalEdge.model_validate(edge) for edge in value
|
|
395
|
+
]
|
|
396
|
+
|
|
397
|
+
@property
|
|
398
|
+
def forecast_path(self) -> List[CausalNode]:
|
|
399
|
+
r"""Canonical alias for the ordered reasoning path."""
|
|
400
|
+
return self.reasoning_trace.forecast_path
|
|
401
|
+
|
|
402
|
+
@forecast_path.setter
|
|
403
|
+
def forecast_path(self, value: List[CausalNode] | List[Dict[str, Any]]) -> None:
|
|
404
|
+
r"""Canonical setter for the ordered reasoning path."""
|
|
405
|
+
self.reasoning_trace.forecast_path = value
|
|
406
|
+
|
|
407
|
+
@property
|
|
408
|
+
def structural_trace(self) -> List[str]:
|
|
409
|
+
r"""Backward compatibility alias for ``execution_trace``."""
|
|
410
|
+
return self.execution_trace
|
|
411
|
+
|
|
412
|
+
@structural_trace.setter
|
|
413
|
+
def structural_trace(self, value: List[str]) -> None:
|
|
414
|
+
r"""Backward compatibility setter for ``execution_trace``."""
|
|
415
|
+
self.execution_trace = list(value)
|
|
416
|
+
|
|
258
417
|
def to_networkx(self) -> Any:
|
|
259
418
|
r"""
|
|
260
|
-
Convert the
|
|
419
|
+
Convert the reasoning trace to a NetworkX directed graph.
|
|
261
420
|
|
|
262
421
|
Returns:
|
|
263
422
|
A NetworkX DiGraph representing the reasoning chain.
|
|
@@ -287,8 +446,14 @@ class ForecastOutput(BaseModel):
|
|
|
287
446
|
__all__ = [
|
|
288
447
|
"MetadataBase",
|
|
289
448
|
"ForecastQuestion",
|
|
449
|
+
"ForecastRequest",
|
|
290
450
|
"CausalNode",
|
|
291
451
|
"CausalEdge",
|
|
452
|
+
"CausalGraph",
|
|
292
453
|
"ConfidenceInterval",
|
|
454
|
+
"ReasoningTrace",
|
|
293
455
|
"ForecastOutput",
|
|
456
|
+
"ForecastResult",
|
|
294
457
|
]
|
|
458
|
+
|
|
459
|
+
ForecastResult = ForecastOutput
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
# Copyright 2026 XRTM Team. All rights reserved.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
r"""Public entry points for XRTM corpora."""
|
|
17
|
+
|
|
18
|
+
from xrtm.data.corpora.real_binary import (
|
|
19
|
+
REAL_BINARY_CORPUS_ID,
|
|
20
|
+
RealBinaryCorpusSource,
|
|
21
|
+
RealBinaryQuestionRecord,
|
|
22
|
+
load_real_binary_corpus,
|
|
23
|
+
load_real_binary_questions,
|
|
24
|
+
load_real_binary_resolved_outcomes,
|
|
25
|
+
validate_real_binary_corpus,
|
|
26
|
+
)
|
|
27
|
+
from xrtm.data.corpora.registry import (
|
|
28
|
+
CorpusManifest,
|
|
29
|
+
CorpusMetadata,
|
|
30
|
+
CorpusRegistry,
|
|
31
|
+
CorpusSplit,
|
|
32
|
+
CorpusTier,
|
|
33
|
+
LicenseType,
|
|
34
|
+
get_corpus,
|
|
35
|
+
get_corpus_metadata,
|
|
36
|
+
list_available_corpora,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
__all__ = [
|
|
40
|
+
"REAL_BINARY_CORPUS_ID",
|
|
41
|
+
"RealBinaryQuestionRecord",
|
|
42
|
+
"RealBinaryCorpusSource",
|
|
43
|
+
"load_real_binary_corpus",
|
|
44
|
+
"load_real_binary_questions",
|
|
45
|
+
"load_real_binary_resolved_outcomes",
|
|
46
|
+
"validate_real_binary_corpus",
|
|
47
|
+
"CorpusRegistry",
|
|
48
|
+
"CorpusMetadata",
|
|
49
|
+
"CorpusManifest",
|
|
50
|
+
"CorpusTier",
|
|
51
|
+
"LicenseType",
|
|
52
|
+
"CorpusSplit",
|
|
53
|
+
"get_corpus",
|
|
54
|
+
"get_corpus_metadata",
|
|
55
|
+
"list_available_corpora",
|
|
56
|
+
]
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
# Copyright 2026 XRTM Team. All rights reserved.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
r"""Concrete built-in corpus registrations."""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
from typing import List
|
|
21
|
+
|
|
22
|
+
from xrtm.data.corpora.real_binary import REAL_BINARY_CORPUS_ID, RealBinaryCorpusSource
|
|
23
|
+
from xrtm.data.corpora.registry import (
|
|
24
|
+
CorpusManifest,
|
|
25
|
+
CorpusMetadata,
|
|
26
|
+
CorpusSplit,
|
|
27
|
+
CorpusTier,
|
|
28
|
+
LicenseType,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def build_builtin_manifests() -> List[CorpusManifest]:
|
|
33
|
+
"""Build manifests for the corpora shipped with the registry bootstrap."""
|
|
34
|
+
return [
|
|
35
|
+
_build_real_binary_manifest(),
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _build_real_binary_manifest() -> CorpusManifest:
|
|
40
|
+
real_binary_metadata = CorpusMetadata(
|
|
41
|
+
corpus_id=REAL_BINARY_CORPUS_ID,
|
|
42
|
+
name="XRTM Real Binary v1",
|
|
43
|
+
tier=CorpusTier.TIER_1,
|
|
44
|
+
license_type=LicenseType.APACHE_2_0,
|
|
45
|
+
description="Minimal deterministic real-world binary question corpus for CI smoke tests",
|
|
46
|
+
version="1.0",
|
|
47
|
+
release_gate_approved=True,
|
|
48
|
+
bundled=True,
|
|
49
|
+
size_estimate=25,
|
|
50
|
+
tags=["binary", "deterministic", "embedded", "seed-corpus"],
|
|
51
|
+
provenance_url="https://github.com/xrtm/xrtm",
|
|
52
|
+
license_url="https://www.apache.org/licenses/LICENSE-2.0",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
return CorpusManifest(
|
|
56
|
+
corpus_id=REAL_BINARY_CORPUS_ID,
|
|
57
|
+
metadata=real_binary_metadata,
|
|
58
|
+
loader_fn=lambda: RealBinaryCorpusSource(),
|
|
59
|
+
available_splits=[CorpusSplit.FULL],
|
|
60
|
+
default_split=CorpusSplit.FULL,
|
|
61
|
+
)
|
|
@@ -13,8 +13,4 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
-
r"""
|
|
17
|
-
|
|
18
|
-
from xrtm.data.providers.local.csv import LocalDataSource
|
|
19
|
-
|
|
20
|
-
__all__ = ["LocalDataSource"]
|
|
16
|
+
r"""External data providers implementing the DataSource ABC."""
|