invariantone 1.0.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.
- invariantone-1.0.0/LICENSE +21 -0
- invariantone-1.0.0/PKG-INFO +263 -0
- invariantone-1.0.0/README.md +226 -0
- invariantone-1.0.0/cli/__init__.py +7 -0
- invariantone-1.0.0/cli/invariantone_cli.py +225 -0
- invariantone-1.0.0/invariantone/__init__.py +45 -0
- invariantone-1.0.0/invariantone/architectures/__init__.py +17 -0
- invariantone-1.0.0/invariantone/architectures/c0_joint_scorer.py +230 -0
- invariantone-1.0.0/invariantone/architectures/c1_comparative.py +238 -0
- invariantone-1.0.0/invariantone/architectures/deep_equivariant_fusion.py +313 -0
- invariantone-1.0.0/invariantone/architectures/direct_comparative.py +165 -0
- invariantone-1.0.0/invariantone/architectures/direct_comparative_head.py +162 -0
- invariantone-1.0.0/invariantone/architectures/direct_set_scorer.py +175 -0
- invariantone-1.0.0/invariantone/architectures/direct_token_readout.py +160 -0
- invariantone-1.0.0/invariantone/architectures/lora_backbone.py +265 -0
- invariantone-1.0.0/invariantone/architectures/pairwise_token_interaction.py +168 -0
- invariantone-1.0.0/invariantone/backbone/pooling.py +69 -0
- invariantone-1.0.0/invariantone/backbone/qwen.py +160 -0
- invariantone-1.0.0/invariantone/baselines/autoregressive.py +146 -0
- invariantone-1.0.0/invariantone/baselines/base.py +48 -0
- invariantone-1.0.0/invariantone/baselines/bi_encoder.py +212 -0
- invariantone-1.0.0/invariantone/baselines/direct_logit.py +212 -0
- invariantone-1.0.0/invariantone/baselines/trained_scorer.py +235 -0
- invariantone-1.0.0/invariantone/benchmarks/manifest.py +77 -0
- invariantone-1.0.0/invariantone/benchmarks/padding_investigation.py +188 -0
- invariantone-1.0.0/invariantone/benchmarks/runner.py +239 -0
- invariantone-1.0.0/invariantone/calibration.py +76 -0
- invariantone-1.0.0/invariantone/cli.py +9 -0
- invariantone-1.0.0/invariantone/config.py +107 -0
- invariantone-1.0.0/invariantone/data/cross_generalization.py +261 -0
- invariantone-1.0.0/invariantone/data/dataset.py +290 -0
- invariantone-1.0.0/invariantone/data/extract_representations.py +152 -0
- invariantone-1.0.0/invariantone/data/final_holdout.py +535 -0
- invariantone-1.0.0/invariantone/data/permutation.py +75 -0
- invariantone-1.0.0/invariantone/data/relational_dataset.py +668 -0
- invariantone-1.0.0/invariantone/data/schema.py +38 -0
- invariantone-1.0.0/invariantone/data/source_datasets.py +381 -0
- invariantone-1.0.0/invariantone/ensemble.py +393 -0
- invariantone-1.0.0/invariantone/eval/jevchaos_adapter.py +79 -0
- invariantone-1.0.0/invariantone/formatting.py +112 -0
- invariantone-1.0.0/invariantone/loading/__init__.py +27 -0
- invariantone-1.0.0/invariantone/loading/checkpoint_loader.py +216 -0
- invariantone-1.0.0/invariantone/loading/hash_verification.py +119 -0
- invariantone-1.0.0/invariantone/metrics/calibration.py +120 -0
- invariantone-1.0.0/invariantone/metrics/calibration_diagnostics.py +240 -0
- invariantone-1.0.0/invariantone/metrics/classification.py +66 -0
- invariantone-1.0.0/invariantone/metrics/invariance.py +56 -0
- invariantone-1.0.0/invariantone/model.py +372 -0
- invariantone-1.0.0/invariantone/options/base.py +36 -0
- invariantone-1.0.0/invariantone/options/contextual.py +94 -0
- invariantone-1.0.0/invariantone/options/lexical.py +51 -0
- invariantone-1.0.0/invariantone/profiles.py +129 -0
- invariantone-1.0.0/invariantone/result.py +341 -0
- invariantone-1.0.0/invariantone/runtime/__init__.py +12 -0
- invariantone-1.0.0/invariantone/runtime/batching.py +72 -0
- invariantone-1.0.0/invariantone/runtime/device.py +56 -0
- invariantone-1.0.0/invariantone/server/__init__.py +13 -0
- invariantone-1.0.0/invariantone/server/app.py +84 -0
- invariantone-1.0.0/invariantone/server/schemas.py +57 -0
- invariantone-1.0.0/invariantone/weights/adapter_model.pt +0 -0
- invariantone-1.0.0/invariantone/weights/adapter_model_seed42.pt +0 -0
- invariantone-1.0.0/invariantone/weights/adapter_model_seed43.pt +0 -0
- invariantone-1.0.0/invariantone/weights/adapter_model_seed44.pt +0 -0
- invariantone-1.0.0/invariantone/weights/config.json +27 -0
- invariantone-1.0.0/invariantone/weights/head.pt +0 -0
- invariantone-1.0.0/invariantone/weights/head_seed42.pt +0 -0
- invariantone-1.0.0/invariantone/weights/head_seed43.pt +0 -0
- invariantone-1.0.0/invariantone/weights/head_seed44.pt +0 -0
- invariantone-1.0.0/invariantone/weights/invariantone_config.json +26 -0
- invariantone-1.0.0/invariantone.egg-info/PKG-INFO +263 -0
- invariantone-1.0.0/invariantone.egg-info/SOURCES.txt +109 -0
- invariantone-1.0.0/invariantone.egg-info/dependency_links.txt +1 -0
- invariantone-1.0.0/invariantone.egg-info/entry_points.txt +2 -0
- invariantone-1.0.0/invariantone.egg-info/requires.txt +18 -0
- invariantone-1.0.0/invariantone.egg-info/top_level.txt +2 -0
- invariantone-1.0.0/pyproject.toml +73 -0
- invariantone-1.0.0/setup.cfg +4 -0
- invariantone-1.0.0/tests/test_b1_sequence_scoring.py +38 -0
- invariantone-1.0.0/tests/test_b2_plus.py +78 -0
- invariantone-1.0.0/tests/test_baselines.py +51 -0
- invariantone-1.0.0/tests/test_c0_joint_scorer.py +144 -0
- invariantone-1.0.0/tests/test_c1_comparative.py +184 -0
- invariantone-1.0.0/tests/test_cache.py +51 -0
- invariantone-1.0.0/tests/test_calibration.py +40 -0
- invariantone-1.0.0/tests/test_calibration_diagnostics.py +50 -0
- invariantone-1.0.0/tests/test_cli.py +53 -0
- invariantone-1.0.0/tests/test_d3_permutation_equivariance.py +130 -0
- invariantone-1.0.0/tests/test_d4a_properties.py +204 -0
- invariantone-1.0.0/tests/test_d4b_properties.py +121 -0
- invariantone-1.0.0/tests/test_d5_properties.py +205 -0
- invariantone-1.0.0/tests/test_d6_properties.py +276 -0
- invariantone-1.0.0/tests/test_dataset.py +40 -0
- invariantone-1.0.0/tests/test_dataset_lineage.py +44 -0
- invariantone-1.0.0/tests/test_direct_comparative.py +99 -0
- invariantone-1.0.0/tests/test_dynamic_k.py +96 -0
- invariantone-1.0.0/tests/test_equivariance.py +107 -0
- invariantone-1.0.0/tests/test_invariance_metrics.py +30 -0
- invariantone-1.0.0/tests/test_jevchaos_integration.py +39 -0
- invariantone-1.0.0/tests/test_live_typesafe.py +45 -0
- invariantone-1.0.0/tests/test_metrics.py +79 -0
- invariantone-1.0.0/tests/test_minimizer.py +109 -0
- invariantone-1.0.0/tests/test_model_loading.py +77 -0
- invariantone-1.0.0/tests/test_mutations.py +128 -0
- invariantone-1.0.0/tests/test_permutation_equivariance.py +69 -0
- invariantone-1.0.0/tests/test_probability_properties.py +88 -0
- invariantone-1.0.0/tests/test_properties.py +106 -0
- invariantone-1.0.0/tests/test_relational_dataset.py +47 -0
- invariantone-1.0.0/tests/test_research_reproduction.py +99 -0
- invariantone-1.0.0/tests/test_server.py +106 -0
- invariantone-1.0.0/tests/test_specs.py +64 -0
- invariantone-1.0.0/tests/test_uncertainty.py +299 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 JevChaos Contributors
|
|
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,263 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: invariantone
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: InvariantOne: High-Assurance Permutation-Equivariant Natural-Language Decision Model
|
|
5
|
+
Author: InvariantOne Team
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Keywords: decision-model,permutation-equivariance,qwen,lora,machine-learning,nlp
|
|
8
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: torch>=2.1.0
|
|
21
|
+
Requires-Dist: transformers>=4.45.0
|
|
22
|
+
Requires-Dist: accelerate>=0.30.0
|
|
23
|
+
Requires-Dist: pydantic>=2.0.0
|
|
24
|
+
Requires-Dist: numpy>=1.24.0
|
|
25
|
+
Requires-Dist: scipy>=1.10.0
|
|
26
|
+
Requires-Dist: rich>=13.0.0
|
|
27
|
+
Provides-Extra: server
|
|
28
|
+
Requires-Dist: fastapi>=0.100.0; extra == "server"
|
|
29
|
+
Requires-Dist: uvicorn>=0.20.0; extra == "server"
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
|
|
33
|
+
Requires-Dist: fastapi>=0.100.0; extra == "dev"
|
|
34
|
+
Requires-Dist: uvicorn>=0.20.0; extra == "dev"
|
|
35
|
+
Requires-Dist: httpx>=0.25.0; extra == "dev"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# InvariantOne
|
|
39
|
+
|
|
40
|
+
**InvariantOne is a natural-language decision model that scores runtime-defined options directly rather than generating an answer token-by-token.**
|
|
41
|
+
|
|
42
|
+
[](https://www.python.org/)
|
|
43
|
+
[](LICENSE)
|
|
44
|
+
[](model_card/MODEL_CARD.md)
|
|
45
|
+
[](model_card/MODEL_CARD.md)
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Overview
|
|
50
|
+
|
|
51
|
+
Traditional generative language models make decisions by auto-regressively generating candidate tokens (`"A"`, `"B"`, `"Option 1"`). This causes:
|
|
52
|
+
- **Severe Order Sensitivity:** Changing option order alters probabilities and flips decisions.
|
|
53
|
+
- **Cross-Option Attention Interference:** Later candidates attend to earlier candidates in the prompt.
|
|
54
|
+
- **High Latency Overhead:** Enforcing order-invariance requires permutation averaging (e.g. evaluating $4! = 24$ prompt variants).
|
|
55
|
+
|
|
56
|
+
**InvariantOne** resolves these problems architecturally:
|
|
57
|
+
1. **Independent Branch Encoding:** Each candidate choice $[S, Q, O_k]$ is processed independently through an adapted `Qwen/Qwen3.5-4B-Base` backbone.
|
|
58
|
+
2. **Exact Distributional Permutation Equivariance:** Pooled option representations pass into a direct comparative head ($d=2560 \to 256 \to 1$), guaranteeing $\text{TVD} = 0.000000$ across all option permutations.
|
|
59
|
+
3. **Calibrated Confidence:** Output probabilities are normalized with a frozen temperature parameter ($\tau^* = 1.0091$).
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Installation
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# From repository
|
|
67
|
+
git clone https://github.com/invariantone/invariantone.git
|
|
68
|
+
cd invariantone
|
|
69
|
+
pip install -e .
|
|
70
|
+
|
|
71
|
+
# With optional HTTP server support
|
|
72
|
+
pip install -e ".[server]"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Quickstart
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from invariantone import InvariantOne
|
|
81
|
+
|
|
82
|
+
# Load frozen v1 checkpoint (auto-detects CUDA / Apple MPS / CPU)
|
|
83
|
+
model = InvariantOne.from_pretrained("invariantone-v1")
|
|
84
|
+
|
|
85
|
+
result = model.decide(
|
|
86
|
+
state="Pressure is rising above the safe operating range.",
|
|
87
|
+
question="What action should the controller take?",
|
|
88
|
+
options=[
|
|
89
|
+
"Close the inlet valve",
|
|
90
|
+
"Increase feed pressure",
|
|
91
|
+
"Maintain the current state",
|
|
92
|
+
"Disable monitoring",
|
|
93
|
+
],
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
print(f"Selected: {result.choice}")
|
|
97
|
+
print(f"Index: {result.choice_index}")
|
|
98
|
+
print(f"Probabilities: {[round(p, 4) for p in result.probabilities]}")
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Output:
|
|
102
|
+
```text
|
|
103
|
+
Selected: Close the inlet valve
|
|
104
|
+
Index: 0
|
|
105
|
+
Probabilities: [0.7952, 0.0389, 0.1547, 0.0112]
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Dynamic Options Count ($K \ge 2$)
|
|
111
|
+
|
|
112
|
+
> **Scope Note on Candidate Options Count ($K$):**
|
|
113
|
+
> The runtime supports arbitrary $K \ge 2$; the reported scientific evaluation results are for $K=4$ unless otherwise stated. Experimental generalization to arbitrary $K$ has not been independently established in the scientific benchmarks.
|
|
114
|
+
|
|
115
|
+
InvariantOne supports arbitrary numbers of runtime options:
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
# Binary decision (K=2)
|
|
119
|
+
binary_res = model.decide(
|
|
120
|
+
state="High packet loss observed on eth0.",
|
|
121
|
+
question="Should traffic fail over to eth1?",
|
|
122
|
+
options=["Fail over to eth1", "Stay on eth0"],
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# Multi-way decision (K=5)
|
|
126
|
+
multi_res = model.decide(
|
|
127
|
+
state="Temperature at 520 C, cooling loop nominal.",
|
|
128
|
+
question="Select operational mode:",
|
|
129
|
+
options=[
|
|
130
|
+
"SCRAM shutdown",
|
|
131
|
+
"Engage loop B",
|
|
132
|
+
"Adjust control rods",
|
|
133
|
+
"Vent steam",
|
|
134
|
+
"Maintain baseline",
|
|
135
|
+
],
|
|
136
|
+
)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Batch Decisions
|
|
142
|
+
|
|
143
|
+
Evaluate workloads with heterogeneous option counts:
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
results = model.decide_batch([
|
|
147
|
+
{
|
|
148
|
+
"state": "Disk usage at 98%.",
|
|
149
|
+
"question": "Action:",
|
|
150
|
+
"options": ["Purge logs", "Extend disk", "Ignore"],
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"state": "CPU nominal.",
|
|
154
|
+
"question": "Action:",
|
|
155
|
+
"options": ["Scale down", "Maintain size"],
|
|
156
|
+
},
|
|
157
|
+
])
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Command-Line Interface (CLI)
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
# Single decision (human-readable table)
|
|
166
|
+
invariantone decide \
|
|
167
|
+
--state "Pressure is above limit" \
|
|
168
|
+
--question "What should the system do?" \
|
|
169
|
+
--option "Close inlet valve" \
|
|
170
|
+
--option "Increase pressure" \
|
|
171
|
+
--option "Maintain current state" \
|
|
172
|
+
--option "Disable monitoring"
|
|
173
|
+
|
|
174
|
+
# Machine-readable JSON output
|
|
175
|
+
invariantone decide \
|
|
176
|
+
--state "Pressure is above limit" \
|
|
177
|
+
--question "What should the system do?" \
|
|
178
|
+
--option "Close inlet valve" \
|
|
179
|
+
--option "Increase pressure" \
|
|
180
|
+
--json
|
|
181
|
+
|
|
182
|
+
# Verify checkpoint cryptographic integrity
|
|
183
|
+
invariantone verify
|
|
184
|
+
|
|
185
|
+
# Inspect model metadata
|
|
186
|
+
invariantone info
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## HTTP Inference Service
|
|
192
|
+
|
|
193
|
+
Run the local API service:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
invariantone serve --port 8000
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Execute inference via REST:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
curl -X POST http://127.0.0.1:8000/v1/decide \
|
|
203
|
+
-H "Content-Type: application/json" \
|
|
204
|
+
-d '{
|
|
205
|
+
"state": "Pressure is rising above the safe operating range.",
|
|
206
|
+
"question": "What action should the controller take?",
|
|
207
|
+
"options": [
|
|
208
|
+
"Close the inlet valve",
|
|
209
|
+
"Increase feed pressure",
|
|
210
|
+
"Maintain the current state",
|
|
211
|
+
"Disable monitoring"
|
|
212
|
+
]
|
|
213
|
+
}'
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Benchmark Performance Summary
|
|
219
|
+
|
|
220
|
+
Evaluated on `FINAL-HOLDOUT-V2` ($1,536$ four-choice items) under strict preregistered one-shot governance:
|
|
221
|
+
|
|
222
|
+
> **Benchmark Provenance Note:**
|
|
223
|
+
> A100 performance figures are from the frozen FINAL-HOLDOUT-V2 benchmarking run; release-wheel functionality was independently smoke-tested in a fresh Python 3.12 environment.
|
|
224
|
+
|
|
225
|
+
| Evaluation Stratum | Focus | Unadapted $D_0$ | $B_1$-Raw | $B_1$-Sym ($24$-Perm) | **InvariantOne-v1** (Seed 42) |
|
|
226
|
+
| :--- | :--- | :---: | :---: | :---: | :---: |
|
|
227
|
+
| **`FINAL-REAL`** | Real operational control tasks ($N=256$) | 89.45% | 91.41% | 92.58% | **94.14%** |
|
|
228
|
+
| **`FINAL-L1`** | Familiar-Operator Compositional Recombination ($N=256$) | 32.81% | 38.28% | 43.75% | **89.84%** |
|
|
229
|
+
| **`FINAL-L2a`** | Semantic Extrapolation ($N=256$) | 28.12% | 45.31% | 50.39% | **86.33%** |
|
|
230
|
+
| **`FINAL-L2b`** | Relational Extrapolation ($N=256$) | 22.27% | 62.50% | **65.23%** | 55.08% |
|
|
231
|
+
| **`FINAL-L3`** | Double Extrapolation ($N=512$) | 25.20% | 60.94% | **65.43%** | 56.84% |
|
|
232
|
+
| **`Aggregate`** | Total locked holdout pool ($N=1,536$) | 37.17% | 59.90% | 63.80% | **73.18%** (1,124/1,536) |
|
|
233
|
+
|
|
234
|
+
*Multi-seed aggregate mean across Seeds 42, 43, 44 is **71.74%** ($\pm 1.97\%$).*
|
|
235
|
+
|
|
236
|
+
**Permutation Equivariance:** $\text{TVD} = 0.000000$ across all 24 permutations.
|
|
237
|
+
**Inference Speedup:** $5.08\times$ faster than 24-permutation symmetrized causal baseline ($83.71\text{ ms}$ vs $425.31\text{ ms}$ on A100).
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Known Boundaries & Model Limitations
|
|
242
|
+
|
|
243
|
+
1. **Dynamic-$K$ Scientific Generalization:** While the runtime supports arbitrary $K \ge 2$ and exact permutation equivariance holds algebraically, empirical benchmark accuracy ($94.14\%$, $89.84\%$, etc.) was evaluated on 4-choice tasks ($K=4$). Experimental generalization to arbitrary $K$ has not been independently established in the scientific benchmarks.
|
|
244
|
+
2. **Novel Relational Operators:** InvariantOne excels at familiar-operator recombination ($89.84\%$) and semantic domain transfer ($86.33\%$). However, completely unseen operator grammars drop to $55.08\%$ ($L_{2b}$) and $56.84\%$ ($L_3$), where 24-permutation causal averaging remains stronger ($65.43\%$).
|
|
245
|
+
3. **Top-1 Argmax Tie Breaking:** While the output probability distribution is strictly permutation-equivariant ($\text{TVD} = 0.000000$), argmax top-1 selection exhibits a $1.56\%$ flip rate under exact floating-point ties.
|
|
246
|
+
4. **No Generative Explanations:** InvariantOne is a dedicated decision model; it does not produce token-by-token natural-language rationales.
|
|
247
|
+
5. **Confidence Estimates:** Probabilities represent model confidence estimates and are not safety-critical certification guarantees.
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Documentation & Research
|
|
252
|
+
|
|
253
|
+
- **Model Card:** [`model_card/MODEL_CARD.md`](model_card/MODEL_CARD.md)
|
|
254
|
+
- **Academic Paper:** [`paper/main.pdf`](paper/main.pdf)
|
|
255
|
+
- **Release Manifest:** [`INVARIANTONE_V1_RELEASE_MANIFEST.json`](INVARIANTONE_V1_RELEASE_MANIFEST.json)
|
|
256
|
+
- **License Audit:** [`RELEASE_LICENSE_AUDIT.md`](RELEASE_LICENSE_AUDIT.md)
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## License
|
|
261
|
+
|
|
262
|
+
InvariantOne is licensed under the [Apache 2.0 License](LICENSE).
|
|
263
|
+
Base foundation model weights are licensed under the upstream Apache 2.0 license by Alibaba Cloud.
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# InvariantOne
|
|
2
|
+
|
|
3
|
+
**InvariantOne is a natural-language decision model that scores runtime-defined options directly rather than generating an answer token-by-token.**
|
|
4
|
+
|
|
5
|
+
[](https://www.python.org/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](model_card/MODEL_CARD.md)
|
|
8
|
+
[](model_card/MODEL_CARD.md)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
Traditional generative language models make decisions by auto-regressively generating candidate tokens (`"A"`, `"B"`, `"Option 1"`). This causes:
|
|
15
|
+
- **Severe Order Sensitivity:** Changing option order alters probabilities and flips decisions.
|
|
16
|
+
- **Cross-Option Attention Interference:** Later candidates attend to earlier candidates in the prompt.
|
|
17
|
+
- **High Latency Overhead:** Enforcing order-invariance requires permutation averaging (e.g. evaluating $4! = 24$ prompt variants).
|
|
18
|
+
|
|
19
|
+
**InvariantOne** resolves these problems architecturally:
|
|
20
|
+
1. **Independent Branch Encoding:** Each candidate choice $[S, Q, O_k]$ is processed independently through an adapted `Qwen/Qwen3.5-4B-Base` backbone.
|
|
21
|
+
2. **Exact Distributional Permutation Equivariance:** Pooled option representations pass into a direct comparative head ($d=2560 \to 256 \to 1$), guaranteeing $\text{TVD} = 0.000000$ across all option permutations.
|
|
22
|
+
3. **Calibrated Confidence:** Output probabilities are normalized with a frozen temperature parameter ($\tau^* = 1.0091$).
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# From repository
|
|
30
|
+
git clone https://github.com/invariantone/invariantone.git
|
|
31
|
+
cd invariantone
|
|
32
|
+
pip install -e .
|
|
33
|
+
|
|
34
|
+
# With optional HTTP server support
|
|
35
|
+
pip install -e ".[server]"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Quickstart
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from invariantone import InvariantOne
|
|
44
|
+
|
|
45
|
+
# Load frozen v1 checkpoint (auto-detects CUDA / Apple MPS / CPU)
|
|
46
|
+
model = InvariantOne.from_pretrained("invariantone-v1")
|
|
47
|
+
|
|
48
|
+
result = model.decide(
|
|
49
|
+
state="Pressure is rising above the safe operating range.",
|
|
50
|
+
question="What action should the controller take?",
|
|
51
|
+
options=[
|
|
52
|
+
"Close the inlet valve",
|
|
53
|
+
"Increase feed pressure",
|
|
54
|
+
"Maintain the current state",
|
|
55
|
+
"Disable monitoring",
|
|
56
|
+
],
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
print(f"Selected: {result.choice}")
|
|
60
|
+
print(f"Index: {result.choice_index}")
|
|
61
|
+
print(f"Probabilities: {[round(p, 4) for p in result.probabilities]}")
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Output:
|
|
65
|
+
```text
|
|
66
|
+
Selected: Close the inlet valve
|
|
67
|
+
Index: 0
|
|
68
|
+
Probabilities: [0.7952, 0.0389, 0.1547, 0.0112]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Dynamic Options Count ($K \ge 2$)
|
|
74
|
+
|
|
75
|
+
> **Scope Note on Candidate Options Count ($K$):**
|
|
76
|
+
> The runtime supports arbitrary $K \ge 2$; the reported scientific evaluation results are for $K=4$ unless otherwise stated. Experimental generalization to arbitrary $K$ has not been independently established in the scientific benchmarks.
|
|
77
|
+
|
|
78
|
+
InvariantOne supports arbitrary numbers of runtime options:
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
# Binary decision (K=2)
|
|
82
|
+
binary_res = model.decide(
|
|
83
|
+
state="High packet loss observed on eth0.",
|
|
84
|
+
question="Should traffic fail over to eth1?",
|
|
85
|
+
options=["Fail over to eth1", "Stay on eth0"],
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# Multi-way decision (K=5)
|
|
89
|
+
multi_res = model.decide(
|
|
90
|
+
state="Temperature at 520 C, cooling loop nominal.",
|
|
91
|
+
question="Select operational mode:",
|
|
92
|
+
options=[
|
|
93
|
+
"SCRAM shutdown",
|
|
94
|
+
"Engage loop B",
|
|
95
|
+
"Adjust control rods",
|
|
96
|
+
"Vent steam",
|
|
97
|
+
"Maintain baseline",
|
|
98
|
+
],
|
|
99
|
+
)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Batch Decisions
|
|
105
|
+
|
|
106
|
+
Evaluate workloads with heterogeneous option counts:
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
results = model.decide_batch([
|
|
110
|
+
{
|
|
111
|
+
"state": "Disk usage at 98%.",
|
|
112
|
+
"question": "Action:",
|
|
113
|
+
"options": ["Purge logs", "Extend disk", "Ignore"],
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"state": "CPU nominal.",
|
|
117
|
+
"question": "Action:",
|
|
118
|
+
"options": ["Scale down", "Maintain size"],
|
|
119
|
+
},
|
|
120
|
+
])
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Command-Line Interface (CLI)
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
# Single decision (human-readable table)
|
|
129
|
+
invariantone decide \
|
|
130
|
+
--state "Pressure is above limit" \
|
|
131
|
+
--question "What should the system do?" \
|
|
132
|
+
--option "Close inlet valve" \
|
|
133
|
+
--option "Increase pressure" \
|
|
134
|
+
--option "Maintain current state" \
|
|
135
|
+
--option "Disable monitoring"
|
|
136
|
+
|
|
137
|
+
# Machine-readable JSON output
|
|
138
|
+
invariantone decide \
|
|
139
|
+
--state "Pressure is above limit" \
|
|
140
|
+
--question "What should the system do?" \
|
|
141
|
+
--option "Close inlet valve" \
|
|
142
|
+
--option "Increase pressure" \
|
|
143
|
+
--json
|
|
144
|
+
|
|
145
|
+
# Verify checkpoint cryptographic integrity
|
|
146
|
+
invariantone verify
|
|
147
|
+
|
|
148
|
+
# Inspect model metadata
|
|
149
|
+
invariantone info
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## HTTP Inference Service
|
|
155
|
+
|
|
156
|
+
Run the local API service:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
invariantone serve --port 8000
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Execute inference via REST:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
curl -X POST http://127.0.0.1:8000/v1/decide \
|
|
166
|
+
-H "Content-Type: application/json" \
|
|
167
|
+
-d '{
|
|
168
|
+
"state": "Pressure is rising above the safe operating range.",
|
|
169
|
+
"question": "What action should the controller take?",
|
|
170
|
+
"options": [
|
|
171
|
+
"Close the inlet valve",
|
|
172
|
+
"Increase feed pressure",
|
|
173
|
+
"Maintain the current state",
|
|
174
|
+
"Disable monitoring"
|
|
175
|
+
]
|
|
176
|
+
}'
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Benchmark Performance Summary
|
|
182
|
+
|
|
183
|
+
Evaluated on `FINAL-HOLDOUT-V2` ($1,536$ four-choice items) under strict preregistered one-shot governance:
|
|
184
|
+
|
|
185
|
+
> **Benchmark Provenance Note:**
|
|
186
|
+
> A100 performance figures are from the frozen FINAL-HOLDOUT-V2 benchmarking run; release-wheel functionality was independently smoke-tested in a fresh Python 3.12 environment.
|
|
187
|
+
|
|
188
|
+
| Evaluation Stratum | Focus | Unadapted $D_0$ | $B_1$-Raw | $B_1$-Sym ($24$-Perm) | **InvariantOne-v1** (Seed 42) |
|
|
189
|
+
| :--- | :--- | :---: | :---: | :---: | :---: |
|
|
190
|
+
| **`FINAL-REAL`** | Real operational control tasks ($N=256$) | 89.45% | 91.41% | 92.58% | **94.14%** |
|
|
191
|
+
| **`FINAL-L1`** | Familiar-Operator Compositional Recombination ($N=256$) | 32.81% | 38.28% | 43.75% | **89.84%** |
|
|
192
|
+
| **`FINAL-L2a`** | Semantic Extrapolation ($N=256$) | 28.12% | 45.31% | 50.39% | **86.33%** |
|
|
193
|
+
| **`FINAL-L2b`** | Relational Extrapolation ($N=256$) | 22.27% | 62.50% | **65.23%** | 55.08% |
|
|
194
|
+
| **`FINAL-L3`** | Double Extrapolation ($N=512$) | 25.20% | 60.94% | **65.43%** | 56.84% |
|
|
195
|
+
| **`Aggregate`** | Total locked holdout pool ($N=1,536$) | 37.17% | 59.90% | 63.80% | **73.18%** (1,124/1,536) |
|
|
196
|
+
|
|
197
|
+
*Multi-seed aggregate mean across Seeds 42, 43, 44 is **71.74%** ($\pm 1.97\%$).*
|
|
198
|
+
|
|
199
|
+
**Permutation Equivariance:** $\text{TVD} = 0.000000$ across all 24 permutations.
|
|
200
|
+
**Inference Speedup:** $5.08\times$ faster than 24-permutation symmetrized causal baseline ($83.71\text{ ms}$ vs $425.31\text{ ms}$ on A100).
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Known Boundaries & Model Limitations
|
|
205
|
+
|
|
206
|
+
1. **Dynamic-$K$ Scientific Generalization:** While the runtime supports arbitrary $K \ge 2$ and exact permutation equivariance holds algebraically, empirical benchmark accuracy ($94.14\%$, $89.84\%$, etc.) was evaluated on 4-choice tasks ($K=4$). Experimental generalization to arbitrary $K$ has not been independently established in the scientific benchmarks.
|
|
207
|
+
2. **Novel Relational Operators:** InvariantOne excels at familiar-operator recombination ($89.84\%$) and semantic domain transfer ($86.33\%$). However, completely unseen operator grammars drop to $55.08\%$ ($L_{2b}$) and $56.84\%$ ($L_3$), where 24-permutation causal averaging remains stronger ($65.43\%$).
|
|
208
|
+
3. **Top-1 Argmax Tie Breaking:** While the output probability distribution is strictly permutation-equivariant ($\text{TVD} = 0.000000$), argmax top-1 selection exhibits a $1.56\%$ flip rate under exact floating-point ties.
|
|
209
|
+
4. **No Generative Explanations:** InvariantOne is a dedicated decision model; it does not produce token-by-token natural-language rationales.
|
|
210
|
+
5. **Confidence Estimates:** Probabilities represent model confidence estimates and are not safety-critical certification guarantees.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Documentation & Research
|
|
215
|
+
|
|
216
|
+
- **Model Card:** [`model_card/MODEL_CARD.md`](model_card/MODEL_CARD.md)
|
|
217
|
+
- **Academic Paper:** [`paper/main.pdf`](paper/main.pdf)
|
|
218
|
+
- **Release Manifest:** [`INVARIANTONE_V1_RELEASE_MANIFEST.json`](INVARIANTONE_V1_RELEASE_MANIFEST.json)
|
|
219
|
+
- **License Audit:** [`RELEASE_LICENSE_AUDIT.md`](RELEASE_LICENSE_AUDIT.md)
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## License
|
|
224
|
+
|
|
225
|
+
InvariantOne is licensed under the [Apache 2.0 License](LICENSE).
|
|
226
|
+
Base foundation model weights are licensed under the upstream Apache 2.0 license by Alibaba Cloud.
|