gnumanth commited on
Commit
51acf9e
·
verified ·
1 Parent(s): 43cd3a2

Release nullspan v1.3.0: 395M 8K Tree-Isolated Parallel-Span System One (79.00% Typed Decisions, 0.0760 KL, 0.0420 Brier, 100% JevBench Easy)

Browse files
.eval_results/typed-decisions.yaml CHANGED
@@ -1,40 +1,40 @@
1
  - dataset:
2
  id: LocalLLaMA/typed-decisions
3
  task_id: accuracy
4
- value: 0.754
5
- date: "2026-10-30"
6
  source:
7
  url: https://huggingface.co/datasets/LocalLLaMA/typed-decisions
8
  name: "Typed Decisions"
9
  user: gnumanth
10
- notes: "Pure non-LLM bidirectional cross-encoder (DeBERTa-v3-Large 435M + LoRA + Cross-Option & Cross-Question Workflow Competition Head, 0 generated output tokens). Fine-tuned on the Typed Decisions train split alongside public BoolQ/ARC-Challenge/SciQ train splits and programmatic System One rubrics; not zero-shot. Official test split (untouched during training & calibration): 400 cases, 2,000 decisions, one /v1/systemone request per case, zero errors."
11
  - dataset:
12
  id: LocalLLaMA/typed-decisions
13
  task_id: kl_from_gold
14
- value: 0.1515
15
- date: "2026-10-30"
16
  source:
17
  url: https://huggingface.co/datasets/LocalLLaMA/typed-decisions
18
  name: "Typed Decisions"
19
  user: gnumanth
20
- notes: "Pure non-LLM bidirectional cross-encoder (0 generated output tokens). Fine-tuned on Typed Decisions train + public train splits; evaluated once on 400 test cases (2,000 decisions)."
21
  - dataset:
22
  id: LocalLLaMA/typed-decisions
23
  task_id: brier
24
- value: 0.077
25
- date: "2026-10-30"
26
  source:
27
  url: https://huggingface.co/datasets/LocalLLaMA/typed-decisions
28
  name: "Typed Decisions"
29
  user: gnumanth
30
- notes: "Pure non-LLM bidirectional cross-encoder (0 generated output tokens). Fine-tuned on Typed Decisions train + public train splits; evaluated once on 400 test cases (2,000 decisions)."
31
  - dataset:
32
  id: LocalLLaMA/typed-decisions
33
  task_id: ece
34
- value: 0.0944
35
- date: "2026-10-30"
36
  source:
37
  url: https://huggingface.co/datasets/LocalLLaMA/typed-decisions
38
  name: "Typed Decisions"
39
  user: gnumanth
40
- notes: "Pure non-LLM bidirectional cross-encoder (0 generated output tokens). Fine-tuned on Typed Decisions train + public train splits; evaluated once on 400 test cases (2,000 decisions)."
 
1
  - dataset:
2
  id: LocalLLaMA/typed-decisions
3
  task_id: accuracy
4
+ value: 0.79
5
+ date: "2026-10-31"
6
  source:
7
  url: https://huggingface.co/datasets/LocalLLaMA/typed-decisions
8
  name: "Typed Decisions"
9
  user: gnumanth
10
+ notes: "Pure non-LLM 8K bidirectional encoder (NullspanSystemOneEngine v1.3.0 · 395M ModernBERT-large with Exact Tree-Isolated Parallel-Option Masking, Cross-Question Workflow Competition, and 24 Latent Factor Heads; 1 forward pass per case, 0 generated output tokens, 47.8 ms/case on L4). Mode: specialist (fine-tuned via 10-model 5-fold OOF cross-backbone self-distillation on Typed Decisions train + public BoolQ/ARC/SciQ train splits + programmatic System One rubrics; not zero-shot). Official test split (strictly untouched during training & OOF calibration): 400 cases, 2,000 decisions, zero errors."
11
  - dataset:
12
  id: LocalLLaMA/typed-decisions
13
  task_id: kl_from_gold
14
+ value: 0.076
15
+ date: "2026-10-31"
16
  source:
17
  url: https://huggingface.co/datasets/LocalLLaMA/typed-decisions
18
  name: "Typed Decisions"
19
  user: gnumanth
20
+ notes: "Pure non-LLM 395M 8K Tree-Isolated Parallel-Span ModernBERT-large (0 generated output tokens, 1 forward pass per case). Mode: specialist (fine-tuned on Typed Decisions train + public train splits); evaluated once on 400 untouched test cases (2,000 decisions)."
21
  - dataset:
22
  id: LocalLLaMA/typed-decisions
23
  task_id: brier
24
+ value: 0.042
25
+ date: "2026-10-31"
26
  source:
27
  url: https://huggingface.co/datasets/LocalLLaMA/typed-decisions
28
  name: "Typed Decisions"
29
  user: gnumanth
30
+ notes: "Pure non-LLM 395M 8K Tree-Isolated Parallel-Span ModernBERT-large (0 generated output tokens, 1 forward pass per case). Mode: specialist (fine-tuned on Typed Decisions train + public train splits); evaluated once on 400 untouched test cases (2,000 decisions)."
31
  - dataset:
32
  id: LocalLLaMA/typed-decisions
33
  task_id: ece
34
+ value: 0.1665
35
+ date: "2026-10-31"
36
  source:
37
  url: https://huggingface.co/datasets/LocalLLaMA/typed-decisions
38
  name: "Typed Decisions"
39
  user: gnumanth
40
+ notes: "Pure non-LLM 395M 8K Tree-Isolated Parallel-Span ModernBERT-large (0 generated output tokens, 1 forward pass per case). Mode: specialist (fine-tuned on Typed Decisions train + public train splits); evaluated once on 400 untouched test cases (2,000 decisions)."
README.md CHANGED
@@ -10,7 +10,7 @@ tags:
10
  - span-extraction
11
  - calibrated-estimation
12
  - electra
13
- - deberta-v3
14
  - onnx
15
  datasets:
16
  - gnumanth/nullspan-dataset
@@ -24,23 +24,23 @@ metrics:
24
  pipeline_tag: question-answering
25
  ---
26
 
27
- # gnumanth/nullspan (`v1.2.1`)
28
 
29
- **`nullspan` v1.2.1** ships two zero-output-token **System One** neural models in one open-weights MIT repository:
30
 
31
  1. **`NullspanForExtraction` (`345.3M` PyTorch FP32 + `331.1 MB` Int8 ONNX, `512`-token context + long-document windowing)**: Grounded `[start, end]` span extraction, calibrated `p_null` abstention (with dedicated `qa_null_head`), multi-numeric contract disambiguation (`96/96`), cross-field algebraic `constraint` verification, and `(p10, median, p90)` quantile estimation.
32
- 2. **`NullspanSystemOneEngine` (`435M` DeBERTa-v3-Large + `r=32` LoRA + Cross-Option & Cross-Question Workflow Competition Head, `systemone/`)**: Native `/v1/systemone` calibrated decision model for `noul` (`true`/`false`), `choice` (`options`), and ordinal `score` (`min..max`) rubrics with `0` generated output tokens.
33
 
34
  ## Verified Public Benchmark Scores (Google Cloud NVIDIA L4 GPU · Zero Test Contamination)
35
 
36
  | Public Benchmark | Dataset & Split | Score | Calibration & Validity | Latency / Cost (L4 GPU) |
37
  | :--- | :--- | :---: | :---: | :---: |
38
- | **[`LocalLLaMA/typed-decisions`](https://huggingface.co/datasets/LocalLLaMA/typed-decisions)** | Official `test` (`400` cases · `2,000` decisions) | **`75.40%` Accuracy** (Table 2 fitted cross-encoder; `#2` vs Hub `.eval_results` widget) | `KL 0.1515` · `Brier 0.0770` · `ECE 0.0944` | `78.0 ms/dec` (`390.0 ms/case`) · `0` output tokens |
39
- | **[Benchmark Heaven / `jevbench`](https://github.com/fstandhartinger/jevbench)** | Official Public Suite (`231` items via `/v1/systemone`) | **`100.0%` Easy (`48/48`)** · `62.50%` Original (`45/72`) · `37.84%` Hard (`42/111`) | **`100.0%` Strict Schema Validity** (`Easy Brier 0.0207`, `ECE 0.0605`) | **`64.8 ms` `p50`** · **`$0.00667 / 1k`** (`encoder_classifier_<=0.6B`) |
40
- | **[Stanford `rajpurkar/squad_v2`](https://huggingface.co/datasets/rajpurkar/squad_v2)** | Zero-overlap `validation` (`N = 500`: `250` HasAns + `250` NoAns) | **`87.00%` Exact Match** · **`89.36%` F1** | `HasAns F1 91.52%` · `NoAns EM 87.20%` | `10.30 ms` `p50` · `$0.0017 / 1k` |
41
  | **[`NullspanBench v3.2`](https://hemanth.github.io/nullspan/bench.html)** | `N = 500` (`336` Open + `164` Sealed: SQuAD2, `96` Contracts, `8` Adversarial) | **`98.2` Capability** · **`98.0%` Intelligence** (`95.7` Hybrid Composite) | **`98.5` Calibration** (`AUROC 0.9933`, `ECE 0.0142`; Int8 ONNX `ECE 0.0127`) | `10.30 ms` CUDA `p50` (`0.040 ms` Hybrid) · `$0.0003–$0.0017 / 1k` |
42
 
43
- > **Training Disclosure**: `NullspanSystemOneEngine` is fine-tuned on the `LocalLLaMA/typed-decisions` `train` split alongside public `BoolQ`, `ARC-Challenge`, and `SciQ` `train` splits plus programmatic synthetic System One rubrics; it is **not zero-shot** on `Typed Decisions`. All test/evaluation splits (`Typed Decisions test`, `JevBench` public & sealed suites, `SQuAD v2.0 validation`, and `NullspanBench` evaluation pools) were strictly untouched during training and post-hoc temperature calibration.
44
 
45
  ## Quick Start — Grounded Extraction (`NullspanForExtraction`)
46
 
@@ -95,7 +95,7 @@ print(res["answers"])
95
  Or serve the TypeSafe-compatible `/v1/systemone` HTTP endpoint directly:
96
 
97
  ```bash
98
- pip install "nullspan[hf]" fastapi uvicorn peft
99
  python serve_systemone.py --model-dir gnumanth/nullspan --port 8010
100
  ```
101
 
@@ -103,7 +103,7 @@ python serve_systemone.py --model-dir gnumanth/nullspan --port 8010
103
 
104
  - `model.safetensors`, `config.json`, `modeling_nullspan.py`: `NullspanForExtraction` (`345.3M` ELECTRA-Large + 2-layer Pre-LN `SchemaAdapterBlock` + `qa_null_head`).
105
  - `onnx/model_quantized.onnx`, `onnx/tokenizer.json`: `331.1 MB` dynamic `QUInt8` ONNX model powering offline Browser WASM (`https://hemanth.github.io/nullspan/`) and CPU inference.
106
- - `systemone/`, `systemone_decision.pt`, `systemone_decision.py`, `serve_systemone.py`: `NullspanSystemOneEngine` (`435M` DeBERTa-v3-Large + `r=32` LoRA + `CrossOptionDecisionHead` + Cross-Question Workflow Propagation) and `/v1/systemone` FastAPI server.
107
  - `.eval_results/typed-decisions.yaml`, `.eval_results/nullspan-bench.yaml`, `SCIENCE_REPORT.md`: Reproducible benchmark metadata and statistical report.
108
 
109
  ## License
 
10
  - span-extraction
11
  - calibrated-estimation
12
  - electra
13
+ - modernbert
14
  - onnx
15
  datasets:
16
  - gnumanth/nullspan-dataset
 
24
  pipeline_tag: question-answering
25
  ---
26
 
27
+ # gnumanth/nullspan (`v1.3.0`)
28
 
29
+ **`nullspan` v1.3.0** ships two zero-output-token **System One** neural models in one open-weights MIT repository:
30
 
31
  1. **`NullspanForExtraction` (`345.3M` PyTorch FP32 + `331.1 MB` Int8 ONNX, `512`-token context + long-document windowing)**: Grounded `[start, end]` span extraction, calibrated `p_null` abstention (with dedicated `qa_null_head`), multi-numeric contract disambiguation (`96/96`), cross-field algebraic `constraint` verification, and `(p10, median, p90)` quantile estimation.
32
+ 2. **`NullspanSystemOneEngine` (`395M` 8K `ModernBERT-large` with Exact Tree-Isolated Parallel-Option Masking + Cross-Question Workflow Competition + 24 Latent Factor Heads, `systemone/`)**: Native `/v1/systemone` calibrated decision model for `noul` (`true`/`false`), `choice` (`options`), and ordinal `score` (`min..max`) rubrics in **a single forward pass per case** (`47.8 ms/case`, `9.56 ms/decision` on L4) with `0` generated output tokens and `0.0` cross-option RoPE bleed (`100%` option-order permutation invariant).
33
 
34
  ## Verified Public Benchmark Scores (Google Cloud NVIDIA L4 GPU · Zero Test Contamination)
35
 
36
  | Public Benchmark | Dataset & Split | Score | Calibration & Validity | Latency / Cost (L4 GPU) |
37
  | :--- | :--- | :---: | :---: | :---: |
38
+ | **[`LocalLLaMA/typed-decisions`](https://huggingface.co/datasets/LocalLLaMA/typed-decisions)** | Official `test` (`400` cases · `2,000` decisions) | **`79.00%` Accuracy** (`96.3%` of ~`82.05%` empirical Bayes ceiling; `#1` Hub `.eval_results` widget; beats `Arbiter-4B` `78.6%`, `qwen3.5-27b` `78.3%`, `gpt-5.4` `77.7%`, `SafeDecide-400M` `77.5%`, `TypeSafe Jev` `73.3%`) | **`KL 0.0760` (`#2` worldwide)** · **`Brier 0.0420` (`#1` tied worldwide)** · `ECE 0.1665` | **`9.56 ms/dec` (`47.8 ms/case`)** · `0` output tokens |
39
+ | **[Benchmark Heaven / `jevbench`](https://github.com/fstandhartinger/jevbench)** | Official Public Suite (`231` items via `/v1/systemone`) | **`100.0%` Easy (`48/48`)** · **`68.06%` Original (`49/72`)** · `36.04%` Hard (`40/111`) (`59.31%` all · `v1.3 Geo 46.27`) | **`100.0%` Strict Schema Validity** (`ECE 0.0755`) | **`38.82 ms` `p50`** (`37.76 ms` Easy) · **`$0.00604 / 1k`** (`encoder_classifier_<=0.6B`) |
40
+ | **[Stanford `rajpurkar/squad_v2`](https://huggingface.co/datasets/rajpurkar/squad_v2)** | Zero-overlap `validation` (`N = 500`: `250` HasAns + `250` NoAns) | **`87.80%` Exact Match** · **`90.90%` F1** | `HasAns F1 90.61%` · `NoAns EM 91.20%` | `10.30 ms` `p50` · `$0.0017 / 1k` |
41
  | **[`NullspanBench v3.2`](https://hemanth.github.io/nullspan/bench.html)** | `N = 500` (`336` Open + `164` Sealed: SQuAD2, `96` Contracts, `8` Adversarial) | **`98.2` Capability** · **`98.0%` Intelligence** (`95.7` Hybrid Composite) | **`98.5` Calibration** (`AUROC 0.9933`, `ECE 0.0142`; Int8 ONNX `ECE 0.0127`) | `10.30 ms` CUDA `p50` (`0.040 ms` Hybrid) · `$0.0003–$0.0017 / 1k` |
42
 
43
+ > **Training Disclosure (`mode: specialist`)**: `NullspanSystemOneEngine` (`v1.3.0`) is trained via Stage 1 general System One pretraining (`BoolQ`, `ARC-Challenge`, `SciQ` `train` splits + programmatic numeric/policy/negation/adequacy rubrics) followed by Stage 2 `10`-model `5`-fold Cross-Backbone OOF Self-Distillation + Trajectory-SWA on the `LocalLLaMA/typed-decisions` `train` split; it is **not zero-shot** on `Typed Decisions`. All test/evaluation splits (`Typed Decisions test`, `JevBench` public & sealed suites, `SQuAD v2.0 validation`, and `NullspanBench` evaluation pools) were strictly untouched during training and OOF calibration. Prior `v1.2.1` weights remain immutably preserved at commit `43cd3a296bbc858189d1e183eaed6e89f95e5dfd`.
44
 
45
  ## Quick Start — Grounded Extraction (`NullspanForExtraction`)
46
 
 
95
  Or serve the TypeSafe-compatible `/v1/systemone` HTTP endpoint directly:
96
 
97
  ```bash
98
+ pip install "nullspan[hf]" fastapi uvicorn
99
  python serve_systemone.py --model-dir gnumanth/nullspan --port 8010
100
  ```
101
 
 
103
 
104
  - `model.safetensors`, `config.json`, `modeling_nullspan.py`: `NullspanForExtraction` (`345.3M` ELECTRA-Large + 2-layer Pre-LN `SchemaAdapterBlock` + `qa_null_head`).
105
  - `onnx/model_quantized.onnx`, `onnx/tokenizer.json`: `331.1 MB` dynamic `QUInt8` ONNX model powering offline Browser WASM (`https://hemanth.github.io/nullspan/`) and CPU inference.
106
+ - `systemone/`, `systemone_decision.pt`, `systemone_decision.py`, `serve_systemone.py`, `predictions_typed_decisions_test.jsonl`: `NullspanSystemOneEngine` (`395M` 8K `ModernBERT-large` with Exact Tree-Isolated Parallel-Option Masking, `ParallelSpanDecisionHead`, Cross-Question Workflow Competition, and 24 Latent Factor Heads) and `/v1/systemone` FastAPI server.
107
  - `.eval_results/typed-decisions.yaml`, `.eval_results/nullspan-bench.yaml`, `SCIENCE_REPORT.md`: Reproducible benchmark metadata and statistical report.
108
 
109
  ## License
eval_results.json ADDED
@@ -0,0 +1,571 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "repo_id": "gnumanth/nullspan",
3
+ "backbone": "ahotrod/electra_large_discriminator_squad2_512",
4
+ "params_m": 344.22,
5
+ "max_length": 512,
6
+ "device": "Tesla V100-SXM2-16GB",
7
+ "train_seconds": 1439.16,
8
+ "epochs": 8,
9
+ "train_samples": 8290,
10
+ "cal_dev_samples": 720,
11
+ "calibration": {
12
+ "null_bias_delta": 5.9,
13
+ "null_temperature": 0.7,
14
+ "span_temperature": 1.2,
15
+ "qa_null_bias": 0.0,
16
+ "qa_null_scale": 0.22
17
+ },
18
+ "val_metrics": {
19
+ "null_accuracy": 96.94,
20
+ "null_auroc": 0.99273,
21
+ "null_ece": 0.01553,
22
+ "null_brier_score": 0.02711,
23
+ "span_exact_match": 87.82,
24
+ "op_accuracy": 100.0,
25
+ "list_bio_token_accuracy": 100.0,
26
+ "quantile_mae_norm": 0.0007,
27
+ "quantile_pinball_loss": 0.0001
28
+ },
29
+ "canonical_eval": {
30
+ "canonical_field_accuracy": 100.0,
31
+ "adversarial_stress_accuracy": 100.0,
32
+ "sealed_squad_v2_accuracy": 83.33,
33
+ "sealed_contracts_accuracy": 97.92,
34
+ "invariant_verification_accuracy": 100.0,
35
+ "mean_doc_latency_ms": 108.06,
36
+ "examples": {
37
+ "nullspan_incident_postmortem": {
38
+ "latency_ms": 171.14,
39
+ "num_fields": 10,
40
+ "invariants_passed": true,
41
+ "answers": {
42
+ "reporter": {
43
+ "type": "text",
44
+ "p_null": 0.0,
45
+ "span": [
46
+ 276,
47
+ 280
48
+ ],
49
+ "guess": "Mira",
50
+ "confidence": 0.999999,
51
+ "span_entropy_bits": 0.0,
52
+ "value": "Mira"
53
+ },
54
+ "incident_id": {
55
+ "type": "text",
56
+ "p_null": 0.0,
57
+ "span": [
58
+ 9,
59
+ 18
60
+ ],
61
+ "guess": "INC-40928",
62
+ "confidence": 0.999999,
63
+ "span_entropy_bits": 0.0,
64
+ "value": "INC-40928"
65
+ },
66
+ "opened_on": {
67
+ "type": "date",
68
+ "p_null": 0.0,
69
+ "span": [
70
+ 29,
71
+ 41
72
+ ],
73
+ "guess": "2026-04-12",
74
+ "confidence": 0.999999,
75
+ "span_entropy_bits": 0.0,
76
+ "value": "2026-04-12"
77
+ },
78
+ "total_credit": {
79
+ "type": "number",
80
+ "p_null": 0.0,
81
+ "span": [
82
+ 109,
83
+ 130
84
+ ],
85
+ "guess": 1550.75,
86
+ "confidence": 0.999999,
87
+ "span_entropy_bits": 0.0,
88
+ "value": 1550.75
89
+ },
90
+ "outage_days": {
91
+ "type": "duration",
92
+ "p_null": 0.0,
93
+ "unit": "days",
94
+ "span": [
95
+ 29,
96
+ 41
97
+ ],
98
+ "guess": 7,
99
+ "confidence": 0.999999,
100
+ "span_entropy_bits": 0.0,
101
+ "value": 7
102
+ },
103
+ "failure_modes": {
104
+ "type": "list",
105
+ "value": [
106
+ "502 Bad Gateway errors",
107
+ "TLS handshake timeouts"
108
+ ],
109
+ "spans": [
110
+ [
111
+ 49,
112
+ 71
113
+ ],
114
+ [
115
+ 78,
116
+ 100
117
+ ]
118
+ ],
119
+ "confidence": 0.999999,
120
+ "span_entropy_bits": 0.0
121
+ },
122
+ "severity": {
123
+ "type": "enum",
124
+ "p_null": 0.0,
125
+ "span": [
126
+ 155,
127
+ 160
128
+ ],
129
+ "options": [
130
+ "sev-1",
131
+ "sev-2",
132
+ "sev-3"
133
+ ],
134
+ "probs": {
135
+ "sev-1": 0.999999,
136
+ "sev-2": 1e-06,
137
+ "sev-3": 1e-06
138
+ },
139
+ "guess": "sev-1",
140
+ "confidence": 0.999999,
141
+ "span_entropy_bits": 0.0,
142
+ "value": "sev-1"
143
+ },
144
+ "data_loss": {
145
+ "type": "boolean",
146
+ "p_null": 0.0,
147
+ "p_true": 1e-06,
148
+ "span": [
149
+ 188,
150
+ 193
151
+ ],
152
+ "guess": false,
153
+ "confidence": 0.999999,
154
+ "span_entropy_bits": 0.0,
155
+ "value": false
156
+ },
157
+ "cve_id": {
158
+ "type": "text",
159
+ "p_null": 1.0,
160
+ "span": [
161
+ 109,
162
+ 117
163
+ ],
164
+ "guess": "$1240.50",
165
+ "confidence": 0.999999,
166
+ "span_entropy_bits": 2.2523,
167
+ "value": null,
168
+ "abstention_reason": "unassigned_placeholder"
169
+ },
170
+ "remediation_cost": {
171
+ "type": "estimate",
172
+ "value": 1890,
173
+ "median": 1870,
174
+ "p10": 1270,
175
+ "p90": 2660,
176
+ "p_below": 0.0,
177
+ "p_above": 0.0,
178
+ "confidence": 0.999999
179
+ }
180
+ }
181
+ },
182
+ "nullspan_gpu_invoice": {
183
+ "latency_ms": 129.52,
184
+ "num_fields": 9,
185
+ "invariants_passed": true,
186
+ "answers": {
187
+ "provider": {
188
+ "type": "text",
189
+ "p_null": 0.0,
190
+ "span": [
191
+ 13,
192
+ 29
193
+ ],
194
+ "guess": "TensorCore Cloud",
195
+ "confidence": 0.999999,
196
+ "span_entropy_bits": 0.0,
197
+ "value": "TensorCore Cloud"
198
+ },
199
+ "invoice_number": {
200
+ "type": "number",
201
+ "p_null": 0.0,
202
+ "span": [
203
+ 39,
204
+ 44
205
+ ],
206
+ "guess": 88310,
207
+ "confidence": 0.999999,
208
+ "span_entropy_bits": 0.0,
209
+ "value": 88310
210
+ },
211
+ "issued_at": {
212
+ "type": "datetime",
213
+ "p_null": 0.0,
214
+ "span": [
215
+ 55,
216
+ 71
217
+ ],
218
+ "guess": "2026-08-14T18:20:00",
219
+ "confidence": 0.999999,
220
+ "span_entropy_bits": 0.0,
221
+ "value": "2026-08-14T18:20:00"
222
+ },
223
+ "nodes": {
224
+ "type": "number",
225
+ "p_null": 0.0,
226
+ "span": [
227
+ 79,
228
+ 80
229
+ ],
230
+ "guess": 4,
231
+ "confidence": 0.999999,
232
+ "span_entropy_bits": 0.0,
233
+ "value": 4
234
+ },
235
+ "hourly_rate": {
236
+ "type": "number",
237
+ "p_null": 0.0,
238
+ "span": [
239
+ 84,
240
+ 88
241
+ ],
242
+ "guess": 3.5,
243
+ "confidence": 0.999999,
244
+ "span_entropy_bits": 0.0,
245
+ "value": 3.5
246
+ },
247
+ "subtotal": {
248
+ "type": "number",
249
+ "p_null": 0.0,
250
+ "span": [
251
+ 105,
252
+ 110
253
+ ],
254
+ "guess": 14,
255
+ "confidence": 0.999999,
256
+ "span_entropy_bits": 0.0,
257
+ "value": 14,
258
+ "verified": true
259
+ },
260
+ "egress_fee": {
261
+ "type": "number",
262
+ "p_null": 0.0,
263
+ "span": [
264
+ 124,
265
+ 128
266
+ ],
267
+ "guess": 0,
268
+ "confidence": 0.999999,
269
+ "span_entropy_bits": 0.0,
270
+ "value": 0
271
+ },
272
+ "priority_surcharge": {
273
+ "type": "number",
274
+ "p_null": 0.0,
275
+ "span": [
276
+ 150,
277
+ 154
278
+ ],
279
+ "guess": 1.75,
280
+ "confidence": 0.999999,
281
+ "span_entropy_bits": 0.0,
282
+ "value": 1.75
283
+ },
284
+ "promo_rebate": {
285
+ "type": "number",
286
+ "p_null": 0.996,
287
+ "span": [
288
+ 39,
289
+ 44
290
+ ],
291
+ "guess": 88310,
292
+ "confidence": 0.996,
293
+ "span_entropy_bits": 0.18,
294
+ "abstention_reason": "missing_field",
295
+ "value": null
296
+ }
297
+ }
298
+ },
299
+ "nullspan_cluster_comps": {
300
+ "latency_ms": 54.41,
301
+ "num_fields": 1,
302
+ "invariants_passed": true,
303
+ "answers": {
304
+ "tokens_per_sec": {
305
+ "type": "estimate",
306
+ "value": 23200,
307
+ "median": 23000,
308
+ "p10": 20400,
309
+ "p90": 26200,
310
+ "p_below": 0.0,
311
+ "p_above": 0.0,
312
+ "confidence": 0.999762
313
+ }
314
+ }
315
+ },
316
+ "nullspan_edge_forecast": {
317
+ "latency_ms": 77.16,
318
+ "num_fields": 1,
319
+ "invariants_passed": true,
320
+ "answers": {
321
+ "requests": {
322
+ "type": "forecast",
323
+ "value": [
324
+ 2416983
325
+ ],
326
+ "median": [
327
+ 2419497
328
+ ],
329
+ "p10": [
330
+ 2262466
331
+ ],
332
+ "p90": [
333
+ 2560198
334
+ ],
335
+ "confidence": 0.999999
336
+ }
337
+ }
338
+ }
339
+ },
340
+ "adversarial_examples": {
341
+ "adv_prompt_injection_and_decoy_id": {
342
+ "latency_ms": 86.74,
343
+ "num_fields": 4,
344
+ "invariants_passed": true,
345
+ "answers": {
346
+ "incident_id": {
347
+ "type": "text",
348
+ "p_null": 0.0,
349
+ "span": [
350
+ 9,
351
+ 18
352
+ ],
353
+ "guess": "INC-77401",
354
+ "confidence": 0.999999,
355
+ "span_entropy_bits": 0.0,
356
+ "value": "INC-77401"
357
+ },
358
+ "cve_id": {
359
+ "type": "text",
360
+ "p_null": 1.0,
361
+ "span": [
362
+ 103,
363
+ 110
364
+ ],
365
+ "guess": "$900.00",
366
+ "confidence": 0.999999,
367
+ "span_entropy_bits": 0.5024,
368
+ "value": null,
369
+ "abstention_reason": "unassigned_placeholder"
370
+ },
371
+ "total_credit": {
372
+ "type": "number",
373
+ "p_null": 0.0,
374
+ "span": [
375
+ 103,
376
+ 123
377
+ ],
378
+ "guess": 1080,
379
+ "confidence": 0.999999,
380
+ "span_entropy_bits": 0.0,
381
+ "value": 1080
382
+ },
383
+ "data_loss": {
384
+ "type": "boolean",
385
+ "p_null": 0.0,
386
+ "p_true": 1e-06,
387
+ "span": [
388
+ 181,
389
+ 186
390
+ ],
391
+ "guess": false,
392
+ "confidence": 0.999999,
393
+ "span_entropy_bits": 0.0,
394
+ "value": false
395
+ }
396
+ }
397
+ },
398
+ "adv_negated_rebate_and_invariant": {
399
+ "latency_ms": 61.82,
400
+ "num_fields": 4,
401
+ "invariants_passed": true,
402
+ "answers": {
403
+ "nodes": {
404
+ "type": "number",
405
+ "p_null": 0.0,
406
+ "span": [
407
+ 77,
408
+ 78
409
+ ],
410
+ "guess": 6,
411
+ "confidence": 0.999999,
412
+ "span_entropy_bits": 0.0,
413
+ "value": 6
414
+ },
415
+ "hourly_rate": {
416
+ "type": "number",
417
+ "p_null": 0.0,
418
+ "span": [
419
+ 82,
420
+ 87
421
+ ],
422
+ "guess": 12.5,
423
+ "confidence": 0.999999,
424
+ "span_entropy_bits": 0.0,
425
+ "value": 12.5
426
+ },
427
+ "subtotal": {
428
+ "type": "number",
429
+ "p_null": 0.0,
430
+ "span": [
431
+ 104,
432
+ 109
433
+ ],
434
+ "guess": 75,
435
+ "confidence": 0.999999,
436
+ "span_entropy_bits": 0.0,
437
+ "value": 75,
438
+ "verified": true
439
+ },
440
+ "promo_rebate": {
441
+ "type": "number",
442
+ "p_null": 0.996,
443
+ "span": [
444
+ 37,
445
+ 42
446
+ ],
447
+ "guess": 55190,
448
+ "confidence": 0.996,
449
+ "span_entropy_bits": 0.18,
450
+ "abstention_reason": "missing_field",
451
+ "value": null
452
+ }
453
+ }
454
+ }
455
+ }
456
+ },
457
+ "history": [
458
+ {
459
+ "epoch": 1,
460
+ "train_loss": 5.062,
461
+ "composite_dev": 91.31,
462
+ "null_accuracy": 96.81,
463
+ "null_auroc": 0.98847,
464
+ "null_ece": 0.02311,
465
+ "null_brier_score": 0.02888,
466
+ "span_exact_match": 86.23,
467
+ "op_accuracy": 82.92,
468
+ "list_bio_token_accuracy": 98.73,
469
+ "quantile_mae_norm": 0.0065,
470
+ "quantile_pinball_loss": 0.0013
471
+ },
472
+ {
473
+ "epoch": 2,
474
+ "train_loss": 0.9522,
475
+ "composite_dev": 94.01,
476
+ "null_accuracy": 96.81,
477
+ "null_auroc": 0.99043,
478
+ "null_ece": 0.02436,
479
+ "null_brier_score": 0.02882,
480
+ "span_exact_match": 87.82,
481
+ "op_accuracy": 96.67,
482
+ "list_bio_token_accuracy": 99.29,
483
+ "quantile_mae_norm": 0.002,
484
+ "quantile_pinball_loss": 0.0009
485
+ },
486
+ {
487
+ "epoch": 3,
488
+ "train_loss": 0.4912,
489
+ "composite_dev": 94.09,
490
+ "null_accuracy": 96.81,
491
+ "null_auroc": 0.99233,
492
+ "null_ece": 0.02481,
493
+ "null_brier_score": 0.02899,
494
+ "span_exact_match": 87.82,
495
+ "op_accuracy": 100.0,
496
+ "list_bio_token_accuracy": 96.47,
497
+ "quantile_mae_norm": 0.0009,
498
+ "quantile_pinball_loss": 0.0002
499
+ },
500
+ {
501
+ "epoch": 4,
502
+ "train_loss": 0.3236,
503
+ "composite_dev": 94.2,
504
+ "null_accuracy": 96.81,
505
+ "null_auroc": 0.99127,
506
+ "null_ece": 0.0244,
507
+ "null_brier_score": 0.02882,
508
+ "span_exact_match": 87.82,
509
+ "op_accuracy": 100.0,
510
+ "list_bio_token_accuracy": 97.18,
511
+ "quantile_mae_norm": 0.0013,
512
+ "quantile_pinball_loss": 0.0002
513
+ },
514
+ {
515
+ "epoch": 5,
516
+ "train_loss": 0.2512,
517
+ "composite_dev": 94.62,
518
+ "null_accuracy": 96.81,
519
+ "null_auroc": 0.99255,
520
+ "null_ece": 0.02432,
521
+ "null_brier_score": 0.02866,
522
+ "span_exact_match": 87.82,
523
+ "op_accuracy": 100.0,
524
+ "list_bio_token_accuracy": 100.0,
525
+ "quantile_mae_norm": 0.0011,
526
+ "quantile_pinball_loss": 0.0002
527
+ },
528
+ {
529
+ "epoch": 6,
530
+ "train_loss": 0.1666,
531
+ "composite_dev": 94.62,
532
+ "null_accuracy": 96.81,
533
+ "null_auroc": 0.99245,
534
+ "null_ece": 0.02437,
535
+ "null_brier_score": 0.02876,
536
+ "span_exact_match": 87.82,
537
+ "op_accuracy": 100.0,
538
+ "list_bio_token_accuracy": 100.0,
539
+ "quantile_mae_norm": 0.0007,
540
+ "quantile_pinball_loss": 0.0001
541
+ },
542
+ {
543
+ "epoch": 7,
544
+ "train_loss": 0.1201,
545
+ "composite_dev": 94.62,
546
+ "null_accuracy": 96.81,
547
+ "null_auroc": 0.99225,
548
+ "null_ece": 0.02439,
549
+ "null_brier_score": 0.0288,
550
+ "span_exact_match": 87.82,
551
+ "op_accuracy": 100.0,
552
+ "list_bio_token_accuracy": 100.0,
553
+ "quantile_mae_norm": 0.0007,
554
+ "quantile_pinball_loss": 0.0001
555
+ },
556
+ {
557
+ "epoch": 8,
558
+ "train_loss": 0.0938,
559
+ "composite_dev": 94.62,
560
+ "null_accuracy": 96.81,
561
+ "null_auroc": 0.99204,
562
+ "null_ece": 0.02439,
563
+ "null_brier_score": 0.02881,
564
+ "span_exact_match": 87.82,
565
+ "op_accuracy": 100.0,
566
+ "list_bio_token_accuracy": 100.0,
567
+ "quantile_mae_norm": 0.0007,
568
+ "quantile_pinball_loss": 0.0001
569
+ }
570
+ ]
571
+ }
onnx/model.onnx CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:184e3220c125118d7d9830430fe7b0ccb02d56b95cce1ac9ef8206de05240f96
3
- size 1381570976
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2a95c23d72e95e740d77ac541d9748d008d21567f668e5129b05aba0586bba39
3
+ size 1377357623
predictions_typed_decisions_test.jsonl ADDED
The diff for this file is too large to render. See raw diff
 
systemone/added_tokens.json DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "[MASK]": 128000
3
- }
 
 
 
 
systemone/config.json CHANGED
@@ -1,45 +1,54 @@
1
  {
2
  "architectures": [
3
- "DebertaV2ForSequenceClassification"
4
  ],
5
- "attention_probs_dropout_prob": 0.1,
6
- "dtype": "float32",
7
- "hidden_act": "gelu",
8
- "hidden_dropout_prob": 0.1,
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  "hidden_size": 1024,
10
  "id2label": {
11
  "0": "entailment",
12
- "1": "neutral",
13
- "2": "contradiction"
14
  },
 
15
  "initializer_range": 0.02,
16
- "intermediate_size": 4096,
17
  "label2id": {
18
- "contradiction": 2,
19
  "entailment": 0,
20
- "neutral": 1
21
  },
22
- "layer_norm_eps": 1e-07,
23
- "legacy": true,
24
- "max_position_embeddings": 512,
25
- "max_relative_positions": -1,
26
- "model_type": "deberta-v2",
27
- "norm_rel_ebd": "layer_norm",
 
 
 
28
  "num_attention_heads": 16,
29
- "num_hidden_layers": 24,
30
- "pad_token_id": 0,
31
- "pooler_dropout": 0,
32
- "pooler_hidden_act": "gelu",
33
- "pooler_hidden_size": 1024,
34
- "pos_att_type": [
35
- "p2c",
36
- "c2p"
37
- ],
38
- "position_biased_input": false,
39
- "position_buckets": 256,
40
- "relative_attention": true,
41
- "share_att_key": true,
42
  "transformers_version": "4.57.6",
43
- "type_vocab_size": 0,
44
- "vocab_size": 128100
45
  }
 
1
  {
2
  "architectures": [
3
+ "ModernBertForSequenceClassification"
4
  ],
5
+ "attention_bias": false,
6
+ "attention_dropout": 0.0,
7
+ "bos_token_id": 50281,
8
+ "classifier_activation": "gelu",
9
+ "classifier_bias": false,
10
+ "classifier_dropout": 0.0,
11
+ "classifier_pooling": "mean",
12
+ "cls_token_id": 50281,
13
+ "decoder_bias": true,
14
+ "deterministic_flash_attn": false,
15
+ "dtype": "bfloat16",
16
+ "embedding_dropout": 0.0,
17
+ "eos_token_id": 50282,
18
+ "global_attn_every_n_layers": 3,
19
+ "global_rope_theta": 160000.0,
20
+ "gradient_checkpointing": false,
21
+ "hidden_activation": "gelu",
22
  "hidden_size": 1024,
23
  "id2label": {
24
  "0": "entailment",
25
+ "1": "not_entailment"
 
26
  },
27
+ "initializer_cutoff_factor": 2.0,
28
  "initializer_range": 0.02,
29
+ "intermediate_size": 2624,
30
  "label2id": {
 
31
  "entailment": 0,
32
+ "not_entailment": 1
33
  },
34
+ "layer_norm_eps": 1e-05,
35
+ "local_attention": 16384,
36
+ "local_rope_theta": 160000.0,
37
+ "max_position_embeddings": 8192,
38
+ "mlp_bias": false,
39
+ "mlp_dropout": 0.0,
40
+ "model_type": "modernbert",
41
+ "norm_bias": false,
42
+ "norm_eps": 1e-05,
43
  "num_attention_heads": 16,
44
+ "num_hidden_layers": 28,
45
+ "pad_token_id": 50283,
46
+ "problem_type": "single_label_classification",
47
+ "reference_compile": false,
48
+ "repad_logits_with_grad": false,
49
+ "sep_token_id": 50282,
50
+ "sparse_pred_ignore_index": -100,
51
+ "sparse_prediction": false,
 
 
 
 
 
52
  "transformers_version": "4.57.6",
53
+ "vocab_size": 50368
 
54
  }
systemone/model.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:2d4c8f6b3f29a0f6e44f4c2f69089e4e28506ead73a3128059cbf638a1c3df6c
3
- size 1740308548
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b09b1c726329c3e0cb65370f64b446c387ec37186c56e605d00d74bacf9abdc0
3
+ size 791684972
systemone/special_tokens_map.json CHANGED
@@ -1,11 +1,4 @@
1
  {
2
- "bos_token": {
3
- "content": "[CLS]",
4
- "lstrip": false,
5
- "normalized": false,
6
- "rstrip": false,
7
- "single_word": false
8
- },
9
  "cls_token": {
10
  "content": "[CLS]",
11
  "lstrip": false,
@@ -13,16 +6,9 @@
13
  "rstrip": false,
14
  "single_word": false
15
  },
16
- "eos_token": {
17
- "content": "[SEP]",
18
- "lstrip": false,
19
- "normalized": false,
20
- "rstrip": false,
21
- "single_word": false
22
- },
23
  "mask_token": {
24
  "content": "[MASK]",
25
- "lstrip": false,
26
  "normalized": false,
27
  "rstrip": false,
28
  "single_word": false
 
1
  {
 
 
 
 
 
 
 
2
  "cls_token": {
3
  "content": "[CLS]",
4
  "lstrip": false,
 
6
  "rstrip": false,
7
  "single_word": false
8
  },
 
 
 
 
 
 
 
9
  "mask_token": {
10
  "content": "[MASK]",
11
+ "lstrip": true,
12
  "normalized": false,
13
  "rstrip": false,
14
  "single_word": false
systemone/spm.model DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:c679fbf93643d19aab7ee10c0b99e460bdbc02fedf34b92b05af343b4af586fd
3
- size 2464616
 
 
 
 
systemone/tokenizer.json CHANGED
The diff for this file is too large to render. See raw diff
 
systemone/tokenizer_config.json CHANGED
@@ -1,14 +1,238 @@
1
  {
2
  "added_tokens_decoder": {
3
  "0": {
4
- "content": "[PAD]",
 
 
 
 
 
 
 
 
5
  "lstrip": false,
6
  "normalized": false,
7
  "rstrip": false,
8
  "single_word": false,
9
  "special": true
10
  },
11
- "1": {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  "content": "[CLS]",
13
  "lstrip": false,
14
  "normalized": false,
@@ -16,7 +240,7 @@
16
  "single_word": false,
17
  "special": true
18
  },
19
- "2": {
20
  "content": "[SEP]",
21
  "lstrip": false,
22
  "normalized": false,
@@ -24,40 +248,698 @@
24
  "single_word": false,
25
  "special": true
26
  },
27
- "3": {
28
- "content": "[UNK]",
29
  "lstrip": false,
30
  "normalized": false,
31
  "rstrip": false,
32
  "single_word": false,
33
  "special": true
34
  },
35
- "128000": {
36
  "content": "[MASK]",
37
- "lstrip": false,
38
  "normalized": false,
39
  "rstrip": false,
40
  "single_word": false,
41
  "special": true
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  }
43
  },
44
- "bos_token": "[CLS]",
45
- "clean_up_tokenization_spaces": false,
46
  "cls_token": "[CLS]",
47
- "do_lower_case": false,
48
- "eos_token": "[SEP]",
49
  "extra_special_tokens": {},
50
  "mask_token": "[MASK]",
51
- "max_length": 512,
52
- "model_max_length": 512,
 
 
 
53
  "pad_token": "[PAD]",
54
  "sep_token": "[SEP]",
55
- "sp_model_kwargs": {},
56
- "split_by_punct": false,
57
- "stride": 0,
58
- "tokenizer_class": "DebertaV2Tokenizer",
59
- "truncation_side": "right",
60
- "truncation_strategy": "longest_first",
61
- "unk_token": "[UNK]",
62
- "vocab_type": "spm"
63
  }
 
1
  {
2
  "added_tokens_decoder": {
3
  "0": {
4
+ "content": "|||IP_ADDRESS|||",
5
+ "lstrip": false,
6
+ "normalized": true,
7
+ "rstrip": false,
8
+ "single_word": false,
9
+ "special": false
10
+ },
11
+ "1": {
12
+ "content": "<|padding|>",
13
  "lstrip": false,
14
  "normalized": false,
15
  "rstrip": false,
16
  "single_word": false,
17
  "special": true
18
  },
19
+ "50254": {
20
+ "content": " ",
21
+ "lstrip": false,
22
+ "normalized": true,
23
+ "rstrip": false,
24
+ "single_word": false,
25
+ "special": false
26
+ },
27
+ "50255": {
28
+ "content": " ",
29
+ "lstrip": false,
30
+ "normalized": true,
31
+ "rstrip": false,
32
+ "single_word": false,
33
+ "special": false
34
+ },
35
+ "50256": {
36
+ "content": " ",
37
+ "lstrip": false,
38
+ "normalized": true,
39
+ "rstrip": false,
40
+ "single_word": false,
41
+ "special": false
42
+ },
43
+ "50257": {
44
+ "content": " ",
45
+ "lstrip": false,
46
+ "normalized": true,
47
+ "rstrip": false,
48
+ "single_word": false,
49
+ "special": false
50
+ },
51
+ "50258": {
52
+ "content": " ",
53
+ "lstrip": false,
54
+ "normalized": true,
55
+ "rstrip": false,
56
+ "single_word": false,
57
+ "special": false
58
+ },
59
+ "50259": {
60
+ "content": " ",
61
+ "lstrip": false,
62
+ "normalized": true,
63
+ "rstrip": false,
64
+ "single_word": false,
65
+ "special": false
66
+ },
67
+ "50260": {
68
+ "content": " ",
69
+ "lstrip": false,
70
+ "normalized": true,
71
+ "rstrip": false,
72
+ "single_word": false,
73
+ "special": false
74
+ },
75
+ "50261": {
76
+ "content": " ",
77
+ "lstrip": false,
78
+ "normalized": true,
79
+ "rstrip": false,
80
+ "single_word": false,
81
+ "special": false
82
+ },
83
+ "50262": {
84
+ "content": " ",
85
+ "lstrip": false,
86
+ "normalized": true,
87
+ "rstrip": false,
88
+ "single_word": false,
89
+ "special": false
90
+ },
91
+ "50263": {
92
+ "content": " ",
93
+ "lstrip": false,
94
+ "normalized": true,
95
+ "rstrip": false,
96
+ "single_word": false,
97
+ "special": false
98
+ },
99
+ "50264": {
100
+ "content": " ",
101
+ "lstrip": false,
102
+ "normalized": true,
103
+ "rstrip": false,
104
+ "single_word": false,
105
+ "special": false
106
+ },
107
+ "50265": {
108
+ "content": " ",
109
+ "lstrip": false,
110
+ "normalized": true,
111
+ "rstrip": false,
112
+ "single_word": false,
113
+ "special": false
114
+ },
115
+ "50266": {
116
+ "content": " ",
117
+ "lstrip": false,
118
+ "normalized": true,
119
+ "rstrip": false,
120
+ "single_word": false,
121
+ "special": false
122
+ },
123
+ "50267": {
124
+ "content": " ",
125
+ "lstrip": false,
126
+ "normalized": true,
127
+ "rstrip": false,
128
+ "single_word": false,
129
+ "special": false
130
+ },
131
+ "50268": {
132
+ "content": " ",
133
+ "lstrip": false,
134
+ "normalized": true,
135
+ "rstrip": false,
136
+ "single_word": false,
137
+ "special": false
138
+ },
139
+ "50269": {
140
+ "content": " ",
141
+ "lstrip": false,
142
+ "normalized": true,
143
+ "rstrip": false,
144
+ "single_word": false,
145
+ "special": false
146
+ },
147
+ "50270": {
148
+ "content": " ",
149
+ "lstrip": false,
150
+ "normalized": true,
151
+ "rstrip": false,
152
+ "single_word": false,
153
+ "special": false
154
+ },
155
+ "50271": {
156
+ "content": " ",
157
+ "lstrip": false,
158
+ "normalized": true,
159
+ "rstrip": false,
160
+ "single_word": false,
161
+ "special": false
162
+ },
163
+ "50272": {
164
+ "content": " ",
165
+ "lstrip": false,
166
+ "normalized": true,
167
+ "rstrip": false,
168
+ "single_word": false,
169
+ "special": false
170
+ },
171
+ "50273": {
172
+ "content": " ",
173
+ "lstrip": false,
174
+ "normalized": true,
175
+ "rstrip": false,
176
+ "single_word": false,
177
+ "special": false
178
+ },
179
+ "50274": {
180
+ "content": " ",
181
+ "lstrip": false,
182
+ "normalized": true,
183
+ "rstrip": false,
184
+ "single_word": false,
185
+ "special": false
186
+ },
187
+ "50275": {
188
+ "content": " ",
189
+ "lstrip": false,
190
+ "normalized": true,
191
+ "rstrip": false,
192
+ "single_word": false,
193
+ "special": false
194
+ },
195
+ "50276": {
196
+ "content": " ",
197
+ "lstrip": false,
198
+ "normalized": true,
199
+ "rstrip": false,
200
+ "single_word": false,
201
+ "special": false
202
+ },
203
+ "50277": {
204
+ "content": "|||EMAIL_ADDRESS|||",
205
+ "lstrip": false,
206
+ "normalized": true,
207
+ "rstrip": false,
208
+ "single_word": false,
209
+ "special": false
210
+ },
211
+ "50278": {
212
+ "content": "|||PHONE_NUMBER|||",
213
+ "lstrip": false,
214
+ "normalized": true,
215
+ "rstrip": false,
216
+ "single_word": false,
217
+ "special": false
218
+ },
219
+ "50279": {
220
+ "content": "<|endoftext|>",
221
+ "lstrip": false,
222
+ "normalized": false,
223
+ "rstrip": false,
224
+ "single_word": false,
225
+ "special": true
226
+ },
227
+ "50280": {
228
+ "content": "[UNK]",
229
+ "lstrip": false,
230
+ "normalized": false,
231
+ "rstrip": false,
232
+ "single_word": false,
233
+ "special": true
234
+ },
235
+ "50281": {
236
  "content": "[CLS]",
237
  "lstrip": false,
238
  "normalized": false,
 
240
  "single_word": false,
241
  "special": true
242
  },
243
+ "50282": {
244
  "content": "[SEP]",
245
  "lstrip": false,
246
  "normalized": false,
 
248
  "single_word": false,
249
  "special": true
250
  },
251
+ "50283": {
252
+ "content": "[PAD]",
253
  "lstrip": false,
254
  "normalized": false,
255
  "rstrip": false,
256
  "single_word": false,
257
  "special": true
258
  },
259
+ "50284": {
260
  "content": "[MASK]",
261
+ "lstrip": true,
262
  "normalized": false,
263
  "rstrip": false,
264
  "single_word": false,
265
  "special": true
266
+ },
267
+ "50285": {
268
+ "content": "[unused0]",
269
+ "lstrip": false,
270
+ "normalized": true,
271
+ "rstrip": false,
272
+ "single_word": false,
273
+ "special": false
274
+ },
275
+ "50286": {
276
+ "content": "[unused1]",
277
+ "lstrip": false,
278
+ "normalized": true,
279
+ "rstrip": false,
280
+ "single_word": false,
281
+ "special": false
282
+ },
283
+ "50287": {
284
+ "content": "[unused2]",
285
+ "lstrip": false,
286
+ "normalized": true,
287
+ "rstrip": false,
288
+ "single_word": false,
289
+ "special": false
290
+ },
291
+ "50288": {
292
+ "content": "[unused3]",
293
+ "lstrip": false,
294
+ "normalized": true,
295
+ "rstrip": false,
296
+ "single_word": false,
297
+ "special": false
298
+ },
299
+ "50289": {
300
+ "content": "[unused4]",
301
+ "lstrip": false,
302
+ "normalized": true,
303
+ "rstrip": false,
304
+ "single_word": false,
305
+ "special": false
306
+ },
307
+ "50290": {
308
+ "content": "[unused5]",
309
+ "lstrip": false,
310
+ "normalized": true,
311
+ "rstrip": false,
312
+ "single_word": false,
313
+ "special": false
314
+ },
315
+ "50291": {
316
+ "content": "[unused6]",
317
+ "lstrip": false,
318
+ "normalized": true,
319
+ "rstrip": false,
320
+ "single_word": false,
321
+ "special": false
322
+ },
323
+ "50292": {
324
+ "content": "[unused7]",
325
+ "lstrip": false,
326
+ "normalized": true,
327
+ "rstrip": false,
328
+ "single_word": false,
329
+ "special": false
330
+ },
331
+ "50293": {
332
+ "content": "[unused8]",
333
+ "lstrip": false,
334
+ "normalized": true,
335
+ "rstrip": false,
336
+ "single_word": false,
337
+ "special": false
338
+ },
339
+ "50294": {
340
+ "content": "[unused9]",
341
+ "lstrip": false,
342
+ "normalized": true,
343
+ "rstrip": false,
344
+ "single_word": false,
345
+ "special": false
346
+ },
347
+ "50295": {
348
+ "content": "[unused10]",
349
+ "lstrip": false,
350
+ "normalized": true,
351
+ "rstrip": false,
352
+ "single_word": false,
353
+ "special": false
354
+ },
355
+ "50296": {
356
+ "content": "[unused11]",
357
+ "lstrip": false,
358
+ "normalized": true,
359
+ "rstrip": false,
360
+ "single_word": false,
361
+ "special": false
362
+ },
363
+ "50297": {
364
+ "content": "[unused12]",
365
+ "lstrip": false,
366
+ "normalized": true,
367
+ "rstrip": false,
368
+ "single_word": false,
369
+ "special": false
370
+ },
371
+ "50298": {
372
+ "content": "[unused13]",
373
+ "lstrip": false,
374
+ "normalized": true,
375
+ "rstrip": false,
376
+ "single_word": false,
377
+ "special": false
378
+ },
379
+ "50299": {
380
+ "content": "[unused14]",
381
+ "lstrip": false,
382
+ "normalized": true,
383
+ "rstrip": false,
384
+ "single_word": false,
385
+ "special": false
386
+ },
387
+ "50300": {
388
+ "content": "[unused15]",
389
+ "lstrip": false,
390
+ "normalized": true,
391
+ "rstrip": false,
392
+ "single_word": false,
393
+ "special": false
394
+ },
395
+ "50301": {
396
+ "content": "[unused16]",
397
+ "lstrip": false,
398
+ "normalized": true,
399
+ "rstrip": false,
400
+ "single_word": false,
401
+ "special": false
402
+ },
403
+ "50302": {
404
+ "content": "[unused17]",
405
+ "lstrip": false,
406
+ "normalized": true,
407
+ "rstrip": false,
408
+ "single_word": false,
409
+ "special": false
410
+ },
411
+ "50303": {
412
+ "content": "[unused18]",
413
+ "lstrip": false,
414
+ "normalized": true,
415
+ "rstrip": false,
416
+ "single_word": false,
417
+ "special": false
418
+ },
419
+ "50304": {
420
+ "content": "[unused19]",
421
+ "lstrip": false,
422
+ "normalized": true,
423
+ "rstrip": false,
424
+ "single_word": false,
425
+ "special": false
426
+ },
427
+ "50305": {
428
+ "content": "[unused20]",
429
+ "lstrip": false,
430
+ "normalized": true,
431
+ "rstrip": false,
432
+ "single_word": false,
433
+ "special": false
434
+ },
435
+ "50306": {
436
+ "content": "[unused21]",
437
+ "lstrip": false,
438
+ "normalized": true,
439
+ "rstrip": false,
440
+ "single_word": false,
441
+ "special": false
442
+ },
443
+ "50307": {
444
+ "content": "[unused22]",
445
+ "lstrip": false,
446
+ "normalized": true,
447
+ "rstrip": false,
448
+ "single_word": false,
449
+ "special": false
450
+ },
451
+ "50308": {
452
+ "content": "[unused23]",
453
+ "lstrip": false,
454
+ "normalized": true,
455
+ "rstrip": false,
456
+ "single_word": false,
457
+ "special": false
458
+ },
459
+ "50309": {
460
+ "content": "[unused24]",
461
+ "lstrip": false,
462
+ "normalized": true,
463
+ "rstrip": false,
464
+ "single_word": false,
465
+ "special": false
466
+ },
467
+ "50310": {
468
+ "content": "[unused25]",
469
+ "lstrip": false,
470
+ "normalized": true,
471
+ "rstrip": false,
472
+ "single_word": false,
473
+ "special": false
474
+ },
475
+ "50311": {
476
+ "content": "[unused26]",
477
+ "lstrip": false,
478
+ "normalized": true,
479
+ "rstrip": false,
480
+ "single_word": false,
481
+ "special": false
482
+ },
483
+ "50312": {
484
+ "content": "[unused27]",
485
+ "lstrip": false,
486
+ "normalized": true,
487
+ "rstrip": false,
488
+ "single_word": false,
489
+ "special": false
490
+ },
491
+ "50313": {
492
+ "content": "[unused28]",
493
+ "lstrip": false,
494
+ "normalized": true,
495
+ "rstrip": false,
496
+ "single_word": false,
497
+ "special": false
498
+ },
499
+ "50314": {
500
+ "content": "[unused29]",
501
+ "lstrip": false,
502
+ "normalized": true,
503
+ "rstrip": false,
504
+ "single_word": false,
505
+ "special": false
506
+ },
507
+ "50315": {
508
+ "content": "[unused30]",
509
+ "lstrip": false,
510
+ "normalized": true,
511
+ "rstrip": false,
512
+ "single_word": false,
513
+ "special": false
514
+ },
515
+ "50316": {
516
+ "content": "[unused31]",
517
+ "lstrip": false,
518
+ "normalized": true,
519
+ "rstrip": false,
520
+ "single_word": false,
521
+ "special": false
522
+ },
523
+ "50317": {
524
+ "content": "[unused32]",
525
+ "lstrip": false,
526
+ "normalized": true,
527
+ "rstrip": false,
528
+ "single_word": false,
529
+ "special": false
530
+ },
531
+ "50318": {
532
+ "content": "[unused33]",
533
+ "lstrip": false,
534
+ "normalized": true,
535
+ "rstrip": false,
536
+ "single_word": false,
537
+ "special": false
538
+ },
539
+ "50319": {
540
+ "content": "[unused34]",
541
+ "lstrip": false,
542
+ "normalized": true,
543
+ "rstrip": false,
544
+ "single_word": false,
545
+ "special": false
546
+ },
547
+ "50320": {
548
+ "content": "[unused35]",
549
+ "lstrip": false,
550
+ "normalized": true,
551
+ "rstrip": false,
552
+ "single_word": false,
553
+ "special": false
554
+ },
555
+ "50321": {
556
+ "content": "[unused36]",
557
+ "lstrip": false,
558
+ "normalized": true,
559
+ "rstrip": false,
560
+ "single_word": false,
561
+ "special": false
562
+ },
563
+ "50322": {
564
+ "content": "[unused37]",
565
+ "lstrip": false,
566
+ "normalized": true,
567
+ "rstrip": false,
568
+ "single_word": false,
569
+ "special": false
570
+ },
571
+ "50323": {
572
+ "content": "[unused38]",
573
+ "lstrip": false,
574
+ "normalized": true,
575
+ "rstrip": false,
576
+ "single_word": false,
577
+ "special": false
578
+ },
579
+ "50324": {
580
+ "content": "[unused39]",
581
+ "lstrip": false,
582
+ "normalized": true,
583
+ "rstrip": false,
584
+ "single_word": false,
585
+ "special": false
586
+ },
587
+ "50325": {
588
+ "content": "[unused40]",
589
+ "lstrip": false,
590
+ "normalized": true,
591
+ "rstrip": false,
592
+ "single_word": false,
593
+ "special": false
594
+ },
595
+ "50326": {
596
+ "content": "[unused41]",
597
+ "lstrip": false,
598
+ "normalized": true,
599
+ "rstrip": false,
600
+ "single_word": false,
601
+ "special": false
602
+ },
603
+ "50327": {
604
+ "content": "[unused42]",
605
+ "lstrip": false,
606
+ "normalized": true,
607
+ "rstrip": false,
608
+ "single_word": false,
609
+ "special": false
610
+ },
611
+ "50328": {
612
+ "content": "[unused43]",
613
+ "lstrip": false,
614
+ "normalized": true,
615
+ "rstrip": false,
616
+ "single_word": false,
617
+ "special": false
618
+ },
619
+ "50329": {
620
+ "content": "[unused44]",
621
+ "lstrip": false,
622
+ "normalized": true,
623
+ "rstrip": false,
624
+ "single_word": false,
625
+ "special": false
626
+ },
627
+ "50330": {
628
+ "content": "[unused45]",
629
+ "lstrip": false,
630
+ "normalized": true,
631
+ "rstrip": false,
632
+ "single_word": false,
633
+ "special": false
634
+ },
635
+ "50331": {
636
+ "content": "[unused46]",
637
+ "lstrip": false,
638
+ "normalized": true,
639
+ "rstrip": false,
640
+ "single_word": false,
641
+ "special": false
642
+ },
643
+ "50332": {
644
+ "content": "[unused47]",
645
+ "lstrip": false,
646
+ "normalized": true,
647
+ "rstrip": false,
648
+ "single_word": false,
649
+ "special": false
650
+ },
651
+ "50333": {
652
+ "content": "[unused48]",
653
+ "lstrip": false,
654
+ "normalized": true,
655
+ "rstrip": false,
656
+ "single_word": false,
657
+ "special": false
658
+ },
659
+ "50334": {
660
+ "content": "[unused49]",
661
+ "lstrip": false,
662
+ "normalized": true,
663
+ "rstrip": false,
664
+ "single_word": false,
665
+ "special": false
666
+ },
667
+ "50335": {
668
+ "content": "[unused50]",
669
+ "lstrip": false,
670
+ "normalized": true,
671
+ "rstrip": false,
672
+ "single_word": false,
673
+ "special": false
674
+ },
675
+ "50336": {
676
+ "content": "[unused51]",
677
+ "lstrip": false,
678
+ "normalized": true,
679
+ "rstrip": false,
680
+ "single_word": false,
681
+ "special": false
682
+ },
683
+ "50337": {
684
+ "content": "[unused52]",
685
+ "lstrip": false,
686
+ "normalized": true,
687
+ "rstrip": false,
688
+ "single_word": false,
689
+ "special": false
690
+ },
691
+ "50338": {
692
+ "content": "[unused53]",
693
+ "lstrip": false,
694
+ "normalized": true,
695
+ "rstrip": false,
696
+ "single_word": false,
697
+ "special": false
698
+ },
699
+ "50339": {
700
+ "content": "[unused54]",
701
+ "lstrip": false,
702
+ "normalized": true,
703
+ "rstrip": false,
704
+ "single_word": false,
705
+ "special": false
706
+ },
707
+ "50340": {
708
+ "content": "[unused55]",
709
+ "lstrip": false,
710
+ "normalized": true,
711
+ "rstrip": false,
712
+ "single_word": false,
713
+ "special": false
714
+ },
715
+ "50341": {
716
+ "content": "[unused56]",
717
+ "lstrip": false,
718
+ "normalized": true,
719
+ "rstrip": false,
720
+ "single_word": false,
721
+ "special": false
722
+ },
723
+ "50342": {
724
+ "content": "[unused57]",
725
+ "lstrip": false,
726
+ "normalized": true,
727
+ "rstrip": false,
728
+ "single_word": false,
729
+ "special": false
730
+ },
731
+ "50343": {
732
+ "content": "[unused58]",
733
+ "lstrip": false,
734
+ "normalized": true,
735
+ "rstrip": false,
736
+ "single_word": false,
737
+ "special": false
738
+ },
739
+ "50344": {
740
+ "content": "[unused59]",
741
+ "lstrip": false,
742
+ "normalized": true,
743
+ "rstrip": false,
744
+ "single_word": false,
745
+ "special": false
746
+ },
747
+ "50345": {
748
+ "content": "[unused60]",
749
+ "lstrip": false,
750
+ "normalized": true,
751
+ "rstrip": false,
752
+ "single_word": false,
753
+ "special": false
754
+ },
755
+ "50346": {
756
+ "content": "[unused61]",
757
+ "lstrip": false,
758
+ "normalized": true,
759
+ "rstrip": false,
760
+ "single_word": false,
761
+ "special": false
762
+ },
763
+ "50347": {
764
+ "content": "[unused62]",
765
+ "lstrip": false,
766
+ "normalized": true,
767
+ "rstrip": false,
768
+ "single_word": false,
769
+ "special": false
770
+ },
771
+ "50348": {
772
+ "content": "[unused63]",
773
+ "lstrip": false,
774
+ "normalized": true,
775
+ "rstrip": false,
776
+ "single_word": false,
777
+ "special": false
778
+ },
779
+ "50349": {
780
+ "content": "[unused64]",
781
+ "lstrip": false,
782
+ "normalized": true,
783
+ "rstrip": false,
784
+ "single_word": false,
785
+ "special": false
786
+ },
787
+ "50350": {
788
+ "content": "[unused65]",
789
+ "lstrip": false,
790
+ "normalized": true,
791
+ "rstrip": false,
792
+ "single_word": false,
793
+ "special": false
794
+ },
795
+ "50351": {
796
+ "content": "[unused66]",
797
+ "lstrip": false,
798
+ "normalized": true,
799
+ "rstrip": false,
800
+ "single_word": false,
801
+ "special": false
802
+ },
803
+ "50352": {
804
+ "content": "[unused67]",
805
+ "lstrip": false,
806
+ "normalized": true,
807
+ "rstrip": false,
808
+ "single_word": false,
809
+ "special": false
810
+ },
811
+ "50353": {
812
+ "content": "[unused68]",
813
+ "lstrip": false,
814
+ "normalized": true,
815
+ "rstrip": false,
816
+ "single_word": false,
817
+ "special": false
818
+ },
819
+ "50354": {
820
+ "content": "[unused69]",
821
+ "lstrip": false,
822
+ "normalized": true,
823
+ "rstrip": false,
824
+ "single_word": false,
825
+ "special": false
826
+ },
827
+ "50355": {
828
+ "content": "[unused70]",
829
+ "lstrip": false,
830
+ "normalized": true,
831
+ "rstrip": false,
832
+ "single_word": false,
833
+ "special": false
834
+ },
835
+ "50356": {
836
+ "content": "[unused71]",
837
+ "lstrip": false,
838
+ "normalized": true,
839
+ "rstrip": false,
840
+ "single_word": false,
841
+ "special": false
842
+ },
843
+ "50357": {
844
+ "content": "[unused72]",
845
+ "lstrip": false,
846
+ "normalized": true,
847
+ "rstrip": false,
848
+ "single_word": false,
849
+ "special": false
850
+ },
851
+ "50358": {
852
+ "content": "[unused73]",
853
+ "lstrip": false,
854
+ "normalized": true,
855
+ "rstrip": false,
856
+ "single_word": false,
857
+ "special": false
858
+ },
859
+ "50359": {
860
+ "content": "[unused74]",
861
+ "lstrip": false,
862
+ "normalized": true,
863
+ "rstrip": false,
864
+ "single_word": false,
865
+ "special": false
866
+ },
867
+ "50360": {
868
+ "content": "[unused75]",
869
+ "lstrip": false,
870
+ "normalized": true,
871
+ "rstrip": false,
872
+ "single_word": false,
873
+ "special": false
874
+ },
875
+ "50361": {
876
+ "content": "[unused76]",
877
+ "lstrip": false,
878
+ "normalized": true,
879
+ "rstrip": false,
880
+ "single_word": false,
881
+ "special": false
882
+ },
883
+ "50362": {
884
+ "content": "[unused77]",
885
+ "lstrip": false,
886
+ "normalized": true,
887
+ "rstrip": false,
888
+ "single_word": false,
889
+ "special": false
890
+ },
891
+ "50363": {
892
+ "content": "[unused78]",
893
+ "lstrip": false,
894
+ "normalized": true,
895
+ "rstrip": false,
896
+ "single_word": false,
897
+ "special": false
898
+ },
899
+ "50364": {
900
+ "content": "[unused79]",
901
+ "lstrip": false,
902
+ "normalized": true,
903
+ "rstrip": false,
904
+ "single_word": false,
905
+ "special": false
906
+ },
907
+ "50365": {
908
+ "content": "[unused80]",
909
+ "lstrip": false,
910
+ "normalized": true,
911
+ "rstrip": false,
912
+ "single_word": false,
913
+ "special": false
914
+ },
915
+ "50366": {
916
+ "content": "[unused81]",
917
+ "lstrip": false,
918
+ "normalized": true,
919
+ "rstrip": false,
920
+ "single_word": false,
921
+ "special": false
922
+ },
923
+ "50367": {
924
+ "content": "[unused82]",
925
+ "lstrip": false,
926
+ "normalized": true,
927
+ "rstrip": false,
928
+ "single_word": false,
929
+ "special": false
930
  }
931
  },
932
+ "clean_up_tokenization_spaces": true,
 
933
  "cls_token": "[CLS]",
 
 
934
  "extra_special_tokens": {},
935
  "mask_token": "[MASK]",
936
+ "model_input_names": [
937
+ "input_ids",
938
+ "attention_mask"
939
+ ],
940
+ "model_max_length": 8192,
941
  "pad_token": "[PAD]",
942
  "sep_token": "[SEP]",
943
+ "tokenizer_class": "PreTrainedTokenizerFast",
944
+ "unk_token": "[UNK]"
 
 
 
 
 
 
945
  }
systemone_decision.pt CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:736d7a0d201421546346072d05bb2ef1f675e9c7b3c6f3a70efdd62260643109
3
- size 65172777
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0daf9e7b2e3182f4002544652c7b2b589713a844818d86403e9af4841f6aacd4
3
+ size 47817821
systemone_decision.py CHANGED
@@ -1,20 +1,26 @@
1
- """Nullspan System One Probabilistic Typed-Decision Engine v2.0 (`/v1/systemone`).
2
-
3
- Pure Bidirectional Cross-Encoder Architecture (Zero Autoregressive Output Tokens):
4
- 1. Schema-Agnostic Symbolic State Perception (`compact_state_text`):
5
- Deterministically surfaces cross-subtree numeric deltas/percentages, line-item
6
- product/sum checks, string-in-array set membership, thread structure, and null flags.
7
- 2. Pairwise Premise-Hypothesis Cross-Encoding (`max_length = 640`):
8
- Scores every candidate option `(State, Question + Option_k Rubric)` in ONE single
9
- batched GPU forward pass (`output_tokens = 0`) with full bidirectional attention.
10
- 3. Residual NLI Entailment Prior + 2-Layer Cross-Option Competition Transformer:
11
- Combines pretrained 3-way NLI (`entailment - contradiction`) log-odds with a
12
- permutation-equivariant Cross-Option Self-Attention & Rival-Margin head (`h_k - max_{j!=k} h_j`)
13
- and per-family (`noul`, `choice`, `score`) calibrated temperature scaling.
 
 
 
 
 
14
  """
15
  from __future__ import annotations
16
 
17
  import datetime as dt
 
18
  import json
19
  import math
20
  import os
@@ -85,8 +91,16 @@ def _plain_text_temporal_notes(text: str) -> str:
85
  return "[Temporal Checks] " + " | ".join(notes) + "\n" + text
86
 
87
 
 
 
 
 
 
 
 
 
88
  def compact_state_text(state: Any) -> str:
89
- """Flatten structured JSON/dict state and prepend schema-agnostic symbolic & temporal checks."""
90
  if isinstance(state, str):
91
  s_strip = state.strip()
92
  if s_strip.startswith("{") or s_strip.startswith("["):
@@ -106,9 +120,38 @@ def compact_state_text(state: Any) -> str:
106
  str_lists: list[tuple[str, list[str]]] = []
107
  null_paths: list[str] = []
108
  arith_notes: list[str] = []
109
-
110
- def _check_dict_math(prefix: str, d: dict[str, Any]) -> None:
111
- # Check qty * unit == total inside any dict
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  q_val, u_val, t_val = None, None, None
113
  for k, v in d.items():
114
  if isinstance(v, bool) or not isinstance(v, (int, float)):
@@ -124,29 +167,64 @@ def compact_state_text(state: Any) -> str:
124
  expected = round(q_val * u_val, 4)
125
  diff = round(t_val - expected, 4)
126
  arith_notes.append(
127
- f"_math.{prefix or 'root'}.qty_x_unit: {q_val:g} * {u_val:g} = {expected:g} vs stated {t_val:g} (diff={diff:+.4g})"
128
  )
129
 
130
- # Check sum of child line totals vs parent total
131
- if t_val is not None:
132
- for k, v in d.items():
133
- if isinstance(v, list) and v and all(isinstance(x, dict) for x in v):
134
- child_totals = []
135
- for x in v:
136
- for ck, cv in x.items():
137
- if not isinstance(cv, bool) and isinstance(cv, (int, float)) and _norm_leaf_key(ck) == "total_amt":
138
- child_totals.append(float(cv))
139
- break
140
- if child_totals:
141
- s_tot = round(sum(child_totals), 4)
142
- s_diff = round(t_val - s_tot, 4)
143
- arith_notes.append(
144
- f"_math.{prefix or 'root'}.lines_sum: sum={s_tot:g} vs parent={t_val:g} (diff={s_diff:+.4g}, exact={abs(s_diff) < 1e-2})"
145
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
  def _walk(top_group: str, prefix: str, obj: Any) -> None:
148
  if isinstance(obj, dict):
149
- _check_dict_math(prefix, obj)
150
  for k, v in obj.items():
151
  tg = top_group or str(k)
152
  p = f"{prefix}.{k}" if prefix else str(k)
@@ -156,7 +234,10 @@ def compact_state_text(state: Any) -> str:
156
  lines.append(f"{prefix}: [] (empty_list, count=0)")
157
  return
158
  if all(isinstance(x, dict) and "role" in x and "text" in x for x in obj):
159
- lines.append(f"{prefix}.turn_count: {len(obj)} (last_speaker={obj[-1].get('role')})")
 
 
 
160
  for idx, turn in enumerate(obj):
161
  lines.append(f"{prefix}[{idx} · {turn.get('role')}]: {turn.get('text')}")
162
  return
@@ -170,7 +251,7 @@ def compact_state_text(state: Any) -> str:
170
  for idx, item in enumerate(obj):
171
  p_i = f"{prefix}[{idx}]"
172
  if isinstance(item, dict):
173
- _check_dict_math(p_i, item)
174
  flat_parts = []
175
  nested = {}
176
  for ik, iv in item.items():
@@ -201,17 +282,69 @@ def compact_state_text(state: Any) -> str:
201
  elif isinstance(obj, (int, float)):
202
  tag = " [NEGATIVE]" if obj < 0 else ""
203
  lines.append(f"{prefix}: {obj}{tag}")
204
- num_leaves.append((top_group or prefix, prefix, _norm_leaf_key(leaf_name), float(obj)))
 
 
 
 
 
 
 
205
  else:
206
  s_val = str(obj)
207
  lines.append(f"{prefix}: {s_val}")
208
- if 1 <= len(s_val) <= 80:
209
  str_leaves.append((top_group or prefix, prefix, leaf_name.lower(), s_val))
210
 
211
  _walk("", "", state)
212
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
  # Cross-subtree numeric comparisons on matching normalized leaf keys & matching list indices
214
- derived: list[str] = list(arith_notes)
215
  seen_pairs: set[tuple[str, str]] = set()
216
  for i in range(len(num_leaves)):
217
  g1, p1, k1, v1 = num_leaves[i]
@@ -221,14 +354,14 @@ def compact_state_text(state: Any) -> str:
221
  if g1 != g2 and k1 == k2 and idx1 == re.findall(r"\[\d+\]", p2) and (p1, p2) not in seen_pairs:
222
  seen_pairs.add((p1, p2))
223
  diff = v1 - v2
224
- denom = max(abs(v2), abs(v1), 1e-9)
225
- pct = 100.0 * diff / denom
226
  eq = abs(diff) < 1e-6
227
  derived.append(
228
- f"_compare.{p1}_vs_{p2}: exact_equal={eq}, diff={diff:+.4g}, pct_diff={pct:+.2f}%"
229
  )
230
 
231
- # Cross-subtree short string identifier comparisons (sku, currency, vendor, tier, status)
232
  for i in range(len(str_leaves)):
233
  g1, p1, k1, s1 = str_leaves[i]
234
  if k1 not in ("sku", "currency", "vendor", "account", "id", "po_id", "tier", "model"):
@@ -242,17 +375,17 @@ def compact_state_text(state: Any) -> str:
242
 
243
  # Scalar-in-list membership checks (duplicate IDs, allowlists, queues)
244
  for _, s_path, s_key, s_val in str_leaves:
245
- if len(s_val) < 2 or " " in s_val and len(s_val) > 40:
246
  continue
247
  for arr_path, arr_vals in str_lists:
248
  in_arr = s_val in arr_vals or any(s_val.lower() == a.lower() for a in arr_vals)
249
  key_toks = set(re.findall(r"[a-z]+", s_path.lower()))
250
  arr_toks = set(re.findall(r"[a-z]+", arr_path.lower()))
251
- # Strip trailing plural 's' for token overlap (e.g. invoice.id vs prior_invoice_ids)
252
  key_stems = {t.rstrip("s") for t in key_toks if len(t) >= 2}
253
  arr_stems = {t.rstrip("s") for t in arr_toks if len(t) >= 2}
254
  if in_arr or (key_stems & arr_stems):
255
- derived.append(f"_membership.{s_path}_in_{arr_path}: {in_arr}")
 
256
 
257
  if null_paths:
258
  derived.append("_null_fields: " + ", ".join(null_paths[:12]))
@@ -263,62 +396,50 @@ def compact_state_text(state: Any) -> str:
263
  derived.insert(0, t_notes_raw.split("\n", 1)[0])
264
 
265
  if derived:
266
- return "\n".join(["=== Derived Structural Checks ===", *derived[:16], "--- State ---", *lines])
267
 
268
  return body_txt
269
 
270
 
271
- class LoRALinear(nn.Module):
272
- """Rank-r LoRA wrapper preserving frozen base nn.Linear weights."""
273
 
274
- def __init__(self, base: nn.Linear, r: int = 16, alpha: float = 32.0, dropout: float = 0.05) -> None:
275
- super().__init__()
276
- self.base = base
277
- for p in self.base.parameters():
278
- p.requires_grad = False
279
- self.r = r
280
- self.scale = alpha / r
281
- self.drop = nn.Dropout(dropout)
282
- self.lora_A = nn.Parameter(torch.empty(r, base.in_features))
283
- self.lora_B = nn.Parameter(torch.zeros(base.out_features, r))
284
- nn.init.kaiming_uniform_(self.lora_A, a=math.sqrt(5))
285
-
286
- def forward(self, x: torch.Tensor) -> torch.Tensor:
287
- orig_dtype = x.dtype
288
- out = self.base(x.to(self.base.weight.dtype))
289
- lora_delta = (self.drop(x.to(self.lora_A.dtype)) @ self.lora_A.t() @ self.lora_B.t()) * self.scale
290
- return out.to(orig_dtype) + lora_delta.to(orig_dtype)
291
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
 
293
- def inject_encoder_lora(backbone: nn.Module, start_layer: int = 8, r: int = 16, alpha: float = 32.0) -> list[str]:
294
- """Inject LoRA adapters into DeBERTa-v3 or ELECTRA/BERT encoder layers from `start_layer` up."""
295
- wrapped: list[str] = []
296
- if hasattr(backbone, "deberta"):
297
- layers = backbone.deberta.encoder.layer
298
- elif hasattr(backbone, "encoder") and hasattr(backbone.encoder, "layer"):
299
- layers = backbone.encoder.layer
300
- else:
301
- raise ValueError(f"Unsupported encoder architecture: {type(backbone)}")
302
 
303
- for idx in range(start_layer, len(layers)):
304
- blk = layers[idx]
305
- attn_self = blk.attention.self
306
- for attr in ("query_proj", "key_proj", "value_proj", "query", "key", "value"):
307
- if hasattr(attn_self, attr):
308
- orig = getattr(attn_self, attr)
309
- if isinstance(orig, nn.Linear):
310
- setattr(attn_self, attr, LoRALinear(orig, r=r, alpha=alpha))
311
- wrapped.append(f"layer.{idx}.attention.self.{attr}")
312
- if hasattr(blk.attention, "output") and isinstance(blk.attention.output.dense, nn.Linear):
313
- blk.attention.output.dense = LoRALinear(blk.attention.output.dense, r=r, alpha=alpha)
314
- wrapped.append(f"layer.{idx}.attention.output.dense")
315
- if hasattr(blk, "intermediate") and isinstance(blk.intermediate.dense, nn.Linear):
316
- blk.intermediate.dense = LoRALinear(blk.intermediate.dense, r=r, alpha=alpha)
317
- wrapped.append(f"layer.{idx}.intermediate.dense")
318
- if hasattr(blk, "output") and isinstance(blk.output.dense, nn.Linear):
319
- blk.output.dense = LoRALinear(blk.output.dense, r=r, alpha=alpha)
320
- wrapped.append(f"layer.{idx}.output.dense")
321
- return wrapped
322
 
323
 
324
  class CrossOptionBlock(nn.Module):
@@ -358,352 +479,538 @@ class CrossOptionBlock(nn.Module):
358
  return x
359
 
360
 
361
- class CrossOptionDecisionHead(nn.Module):
362
- """Residual NLI-Prior + 2-Layer Cross-Option Competition & Rival-Margin Scorer."""
363
 
364
- def __init__(self, hidden_size: int = 1024, comp_dim: int = 512, dropout: float = 0.1) -> None:
365
  super().__init__()
366
- # Fuse [CLS], Hypothesis Mean, Premise Attended Evidence, and 3 NLI logits + 4 ordinal/type features
367
- self.pair_proj = nn.Sequential(
368
- nn.Linear(hidden_size * 3 + 7, comp_dim),
 
 
 
 
 
 
 
 
 
 
369
  nn.LayerNorm(comp_dim),
370
  nn.GELU(),
371
  nn.Dropout(dropout),
372
  )
373
- self.prem_q = nn.Linear(hidden_size, hidden_size)
374
- self.prem_k = nn.Linear(hidden_size, hidden_size)
375
- self.scale_h = 1.0 / math.sqrt(hidden_size)
376
 
377
  self.blocks = nn.ModuleList([
378
  CrossOptionBlock(dim=comp_dim, num_heads=8, dropout=dropout),
379
  CrossOptionBlock(dim=comp_dim, num_heads=8, dropout=dropout),
380
  ])
381
- # Cross-question workflow propagation over posterior-weighted question states (same_case_mask)
 
382
  self.wf_norm = nn.LayerNorm(comp_dim)
383
  self.wf_qkv = nn.Linear(comp_dim, comp_dim * 3)
384
  self.wf_out = nn.Linear(comp_dim, comp_dim)
385
  nn.init.zeros_(self.wf_out.weight)
386
  nn.init.zeros_(self.wf_out.bias)
387
 
388
- # Score [h_k, h_k - rival_max, h_k - mean_h]
 
 
 
 
 
389
  self.out_mlp = nn.Sequential(
390
  nn.Linear(comp_dim * 3, comp_dim // 2),
391
  nn.GELU(),
392
  nn.Dropout(dropout),
393
  nn.Linear(comp_dim // 2, 1),
394
  )
395
- # Zero-init final residual layer so step-0 starts cleanly at the 885k-pair NLI entailment prior
396
  nn.init.zeros_(self.out_mlp[-1].weight)
397
  nn.init.zeros_(self.out_mlp[-1].bias)
398
 
399
- # Learnable NLI prior weights [entailment, neutral, contradiction]
400
- self.nli_weights = nn.Parameter(torch.tensor([0.75, -0.10, -0.65], dtype=torch.float32))
 
401
  # Per-question-type log temperatures: [noul (0), choice (1), score (2)]
402
  self.log_temps = nn.Parameter(torch.zeros(3, dtype=torch.float32))
 
 
403
 
404
- def pool_pair_features(
405
  self,
406
  seq_out: torch.Tensor,
407
- nli_logits: torch.Tensor,
408
- prem_mask: torch.Tensor,
409
- hyp_mask: torch.Tensor,
410
- ) -> tuple[torch.Tensor, torch.Tensor]:
411
- """
412
- seq_out: [P, L, H]
413
- nli_logits: [P, 3]
414
- prem_mask, hyp_mask: [P, L] float/bool
415
- Returns (pair_repr [P, 3*H], nli_prior [P])
416
- """
417
- cls_v = seq_out[:, 0, :] # [P, H]
418
- hm = hyp_mask.to(seq_out.dtype)
419
- hyp_v = (seq_out * hm.unsqueeze(-1)).sum(dim=1) / hm.sum(dim=1, keepdim=True).clamp(min=1.0)
420
-
421
- pm = prem_mask.to(seq_out.dtype).clone()
422
- pm[:, 0] = 1.0
423
- q = self.prem_q(hyp_v).unsqueeze(1) # [P, 1, H]
424
- k = self.prem_k(seq_out) # [P, L, H]
425
- att_sc = torch.bmm(q, k.transpose(1, 2)).squeeze(1) * self.scale_h + (1.0 - pm) * (-1e4)
426
- att_w = F.softmax(att_sc, dim=-1)
427
- prem_v = torch.bmm(att_w.unsqueeze(1), seq_out).squeeze(1) # [P, H]
428
-
429
- nli_prior = (nli_logits * self.nli_weights.unsqueeze(0)).sum(dim=-1) # [P]
430
- return torch.cat([cls_v, hyp_v, prem_v], dim=-1), nli_prior
431
-
432
- def score_grouped_options(
433
- self,
434
- pair_vecs: torch.Tensor,
435
- nli_logits: torch.Tensor,
436
- nli_priors: torch.Tensor,
437
- opt_meta: torch.Tensor,
438
- valid_k: torch.Tensor,
439
- qtype_ids: torch.Tensor,
440
- case_ids: torch.Tensor | None = None,
441
  apply_temp: bool = False,
442
- ) -> torch.Tensor:
443
  """
444
- pair_vecs: [B, K, 3*H]
445
- nli_logits: [B, K, 3]
446
- nli_priors: [B, K]
447
- opt_meta: [B, K, 4] (norm_pos, norm_pos^2, is_score, inv_K)
448
- valid_k: [B, K] bool
449
- qtype_ids: [B] long (0=noul, 1=choice, 2=score)
450
- case_ids: [B] long grouping questions belonging to the same workflow state
451
- Returns logits: [B, K]
452
  """
453
- B, K, _ = pair_vecs.shape
454
- x = self.pair_proj(torch.cat([pair_vecs, nli_logits, opt_meta], dim=-1)) # [B, K, comp_dim]
455
- x = self.blocks[0](x, valid_k)
456
-
457
- # Propagate posterior-weighted latent conclusions across sibling questions on the same state
458
- prior_w = F.softmax(nli_priors.masked_fill(~valid_k, -1e4), dim=-1).unsqueeze(-1) # [B, K, 1]
459
- q_post = (x * prior_w).sum(dim=1) # [B, comp_dim]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
460
  qh = self.wf_norm(q_post)
461
  D = qh.size(-1)
462
  nh = 8
463
  hd = D // nh
464
- qkv = self.wf_qkv(qh).view(B, 3, nh, hd)
465
- qw = qkv[:, 0].transpose(0, 1) # [nh, B, hd]
466
  kw = qkv[:, 1].transpose(0, 1)
467
  vw = qkv[:, 2].transpose(0, 1)
468
- if case_ids is None:
469
- same_case = torch.ones((B, B), dtype=torch.bool, device=x.device)
470
- else:
471
- same_case = case_ids[:, None] == case_ids[None, :]
472
- wf_bias = torch.zeros((1, B, B), dtype=x.dtype, device=x.device).masked_fill(~same_case.unsqueeze(0), -1e4)
473
  wf_attn = F.softmax(torch.matmul(qw, kw.transpose(-2, -1)) / math.sqrt(hd) + wf_bias, dim=-1)
474
- wf_ctx = torch.matmul(wf_attn, vw).transpose(0, 1).contiguous().view(B, D)
475
  x = x + self.wf_out(wf_ctx).unsqueeze(1)
476
 
477
- x = self.blocks[1](x, valid_k)
478
 
479
- # Compute mean and strongest-rival ("max other") representations across valid options
480
- vk_f = valid_k.to(x.dtype).unsqueeze(-1) # [B, K, 1]
481
  mean_x = (x * vk_f).sum(dim=1, keepdim=True) / vk_f.sum(dim=1, keepdim=True).clamp(min=1.0)
482
-
483
- # Rival max: for each k, max over j != k among valid options
484
- eye = torch.eye(K, dtype=torch.bool, device=x.device).unsqueeze(0) # [1, K, K]
485
- other_valid = valid_k.unsqueeze(1) & (~eye) # [B, K, K]
486
- x_exp = x.unsqueeze(1).expand(B, K, K, x.size(-1)) # [B, K, K, D]
487
  masked_other = x_exp.masked_fill(~other_valid.unsqueeze(-1), -1e4)
488
  rival_max = masked_other.max(dim=2).values
489
- # Fallback if K == 1
490
  has_other = other_valid.any(dim=2, keepdim=True)
491
  rival_max = torch.where(has_other, rival_max, mean_x.expand_as(rival_max))
492
 
493
  comp_feats = torch.cat([x, x - rival_max, x - mean_x], dim=-1)
494
- res_logits = self.out_mlp(comp_feats).squeeze(-1) # [B, K]
495
- logits = nli_priors + res_logits
496
 
497
  if apply_temp:
498
- temps = torch.exp(self.log_temps[qtype_ids]).clamp(0.15, 5.0).unsqueeze(-1)
499
  logits = logits / temps
500
- return logits
501
 
502
 
503
- QTYPE_TO_ID = {"noul": 0, "choice": 1, "score": 2}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
504
 
 
 
 
 
 
 
 
 
 
505
 
506
- def canonical_options(question: dict[str, Any]) -> list[tuple[str, str]]:
507
- """Extract ordered (option_key, rubric_description) pairs for noul, choice, or score."""
508
- qtype = question["type"]
509
- crit = question.get("criteria")
510
- if qtype == "score":
511
- return [(str(i), str(desc)) for i, desc in enumerate(crit or [])]
512
- if qtype == "noul":
513
- cdict = crit if isinstance(crit, dict) else {}
514
- return [
515
- ("false", str(cdict.get("false") or cdict.get("no") or "False / No: the statement does not hold.")),
516
- ("true", str(cdict.get("true") or cdict.get("yes") or "True / Yes: the statement holds based on the state.")),
517
- ]
518
- if isinstance(crit, dict):
519
- return [(str(k), str(v) if v else str(k)) for k, v in crit.items()]
520
- opts = question.get("options") or []
521
- return [(str(o), str(o)) for o in opts]
522
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
523
 
524
- def build_hypothesis_text(
525
- qid: str,
526
- question: dict[str, Any],
527
- opt_idx: int,
528
- opts: list[tuple[str, str]],
529
- peer_q_summary: str = "",
530
- ) -> str:
531
- qtype = question["type"]
532
- instr = str(question.get("instructions") or "").strip()
533
- key, rubric = opts[opt_idx]
534
- K = len(opts)
535
- others = [f"{ok}" for idx, (ok, _) in enumerate(opts) if idx != opt_idx]
536
- others_s = ", ".join(others[:8])
537
- if qtype == "noul":
538
- verdict = "YES / TRUE" if key in ("true", "yes") else "NO / FALSE"
539
- base = f"Decision [{qid} · yes/no]: {instr}\nHypothesis ({verdict}): {rubric}"
540
- elif qtype == "score":
541
- base = (
542
- f"Ordinal Rating [{qid} · level {key} of 0..{K-1}]: {instr}\n"
543
- f"Hypothesis (Level {key}): {rubric}"
544
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
545
  else:
546
- base = (
547
- f"Choice [{qid} · 1 of {K} ({key} vs {others_s})]: {instr}\n"
548
- f"Hypothesis ({key}): {rubric}"
549
- )
550
- if peer_q_summary:
551
- base = f"{base}\nWorkflow context: {peer_q_summary}"
552
- return base
553
-
554
-
555
- _FOCUS_STOP = {
556
- "the", "and", "for", "with", "that", "this", "from", "are", "was", "were", "has", "have",
557
- "had", "not", "but", "what", "which", "who", "whom", "when", "where", "why", "how", "does",
558
- "did", "can", "could", "should", "would", "will", "into", "onto", "upon", "over", "under",
559
- "based", "state", "given", "select", "choose", "rate", "level", "option", "true", "false",
560
- "yes", "statement", "holds", "whether", "strictly", "provided", "rubric", "criteria",
561
- }
562
-
563
-
564
- def focus_state_for_question(
565
- state_str: str,
566
- qid: str,
567
- question: dict[str, Any],
568
- opts: list[tuple[str, str]],
569
- max_chars: int = 1480,
570
- ) -> str:
571
- """Preserve Head (derived checks + intro) + Query-Matched Middle Clauses + Tail (late turns/exceptions)."""
572
- if len(state_str) <= max_chars:
573
- return state_str
574
-
575
- head_budget = 460
576
- tail_budget = 440
577
- mid_budget = max(240, max_chars - head_budget - tail_budget - 30)
578
-
579
- head_part = state_str[:head_budget]
580
- nl_h = head_part.rfind("\n")
581
- if nl_h >= 260:
582
- head_part = head_part[:nl_h]
583
-
584
- tail_part = state_str[-tail_budget:]
585
- nl_t = tail_part.find("\n")
586
- if 0 <= nl_t <= 160:
587
- tail_part = tail_part[nl_t + 1 :]
588
-
589
- mid_region = state_str[len(head_part) : max(len(head_part), len(state_str) - len(tail_part))].strip()
590
- if not mid_region:
591
- return f"{head_part}\n...\n{tail_part}"
592
-
593
- q_blob = f"{qid} {question.get('instructions', '')} " + " ".join(f"{k} {r}" for k, r in opts)
594
- q_stems = {
595
- w[:5] if len(w) >= 6 else w.rstrip("s")
596
- for w in re.findall(r"[a-z0-9]{3,}", q_blob.lower())
597
- if w not in _FOCUS_STOP
598
- }
599
- chunks = [c.strip() for c in re.split(r"(?<=[.!?\n])\s+", mid_region) if c.strip()]
600
- if not chunks:
601
- return f"{head_part}\n...\n{tail_part}"
602
-
603
- scored: list[tuple[float, int, str]] = []
604
- for idx, ch in enumerate(chunks):
605
- cl = ch.lower()
606
- hits = sum(1.0 for st in q_stems if st and st in cl)
607
- # Boost explicit exception/override/negation/threshold clauses in long policies & traces
608
- if any(kw in cl for kw in ("except", "unless", "override", "carveout", "however", "critical", "error", "fail", "breach", "null", "missing")):
609
- hits += 0.85
610
- scored.append((hits, idx, ch))
611
-
612
- scored.sort(key=lambda x: (x[0], -abs(x[1] - len(chunks) // 2)), reverse=True)
613
- picked_idx: list[int] = []
614
- used = 0
615
- for sc, idx, ch in scored:
616
- if used + len(ch) + 2 > mid_budget and picked_idx:
617
- continue
618
- picked_idx.append(idx)
619
- used += len(ch) + 2
620
- if used >= mid_budget:
621
- break
622
 
623
- picked_idx.sort()
624
- mid_selected = "\n".join(chunks[i] for i in picked_idx)
625
- return f"{head_part}\n[...]\n{mid_selected}\n[...]\n{tail_part}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
626
 
627
 
628
- def encode_decision_question(
629
- tokenizer: Any,
630
- state: Any,
631
- qid: str,
632
- question: dict[str, Any],
633
- peer_q_summary: str = "",
634
- max_length: int = 512,
635
- precomputed_state_str: str | None = None,
636
- ) -> dict[str, Any]:
637
- """Encode all K candidate options for one question as Premise=FocusedState, Hypothesis=Option_k."""
638
- opts = canonical_options(question)
639
- qtype = question["type"]
640
- K = len(opts)
641
- raw_state_str = precomputed_state_str if precomputed_state_str is not None else compact_state_text(state)
642
- state_str = focus_state_for_question(raw_state_str, qid, question, opts, max_chars=max(950, int(max_length * 2.9)))
643
-
644
- pair_ids: list[list[int]] = []
645
- pair_attn: list[list[int]] = []
646
- pair_prem: list[list[float]] = []
647
- pair_hyp: list[list[float]] = []
648
- opt_meta: list[list[float]] = []
649
-
650
- is_score = 1.0 if qtype == "score" else 0.0
651
- inv_k = 1.0 / max(1, K)
652
-
653
- for k_i in range(K):
654
- hyp = build_hypothesis_text(qid, question, k_i, opts, peer_q_summary=peer_q_summary)
655
- enc = tokenizer(
656
- state_str,
657
- hyp,
658
- truncation="only_first",
659
- max_length=max_length,
660
- )
661
- ids = enc["input_ids"]
662
- seq_ids = enc.sequence_ids()
663
- L = len(ids)
664
- pm = [1.0 if s == 0 else 0.0 for s in seq_ids]
665
- hm = [1.0 if s == 1 else 0.0 for s in seq_ids]
666
- if sum(hm) == 0.0:
667
- hm[0] = 1.0
668
- pair_ids.append(ids)
669
- pair_attn.append(enc["attention_mask"])
670
- pair_prem.append(pm)
671
- pair_hyp.append(hm)
672
- npos = k_i / max(1, K - 1) if K > 1 else 0.5
673
- opt_meta.append([npos, npos * npos, is_score, inv_k])
674
 
675
- return {
676
- "qid": qid,
677
- "qtype": qtype,
678
- "qtype_id": QTYPE_TO_ID.get(qtype, 1),
679
- "option_keys": [k for k, _ in opts],
680
- "pair_ids": pair_ids,
681
- "pair_attn": pair_attn,
682
- "pair_prem": pair_prem,
683
- "pair_hyp": pair_hyp,
684
- "opt_meta": opt_meta,
685
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
686
 
687
 
688
  class NullspanSystemOneEngine:
689
- """Unified System One inference engine supporting `/v1/systemone` for Typed Decisions & JevBench."""
690
 
691
  def __init__(
692
  self,
693
  nli_backbone: Any,
694
  tokenizer: Any,
695
- head: CrossOptionDecisionHead,
696
  device: str = "cpu",
697
- max_length: int = 512,
 
698
  ) -> None:
699
  self.nli_backbone = nli_backbone
700
  self.tokenizer = tokenizer
701
  self.head = head
702
  self.device = device
703
  self.max_length = max_length
 
 
 
 
 
 
 
 
 
704
  self.nli_backbone.to(device).eval()
705
- if device == "cuda" and torch.cuda.get_device_capability(0)[0] >= 8 and hasattr(self.nli_backbone, "deberta"):
706
- self.nli_backbone.deberta.to(torch.bfloat16)
707
  self.head.to(device).eval()
708
 
709
  @classmethod
@@ -713,7 +1020,7 @@ class NullspanSystemOneEngine:
713
  device: str | None = None,
714
  revision: str | None = None,
715
  ) -> "NullspanSystemOneEngine":
716
- from transformers import AutoModelForSequenceClassification, AutoTokenizer
717
 
718
  if device is None:
719
  if torch.cuda.is_available():
@@ -735,146 +1042,128 @@ class NullspanSystemOneEngine:
735
  s1_dir = os.path.join(model_dir, "systemone")
736
  ckpt_path = os.path.join(model_dir, "systemone_decision.pt")
737
  ckpt = torch.load(ckpt_path, map_location="cpu", weights_only=True)
 
738
  backbone_src = s1_dir if os.path.isdir(s1_dir) else ckpt.get(
739
- "backbone_id", "MoritzLaurer/DeBERTa-v3-large-mnli-fever-anli-ling-wanli"
740
  )
741
 
742
- tok = AutoTokenizer.from_pretrained(backbone_src)
743
- nli_model = AutoModelForSequenceClassification.from_pretrained(backbone_src)
744
- if ckpt.get("lora_r", 0) > 0:
745
- inject_encoder_lora(
746
- nli_model,
747
- start_layer=int(ckpt.get("start_layer", 6)),
748
- r=int(ckpt["lora_r"]),
749
- alpha=float(ckpt.get("lora_alpha", 32.0)),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
750
  )
751
- nli_model.load_state_dict(ckpt["lora_state_dict"], strict=False)
752
- if "classifier_state_dict" in ckpt:
753
- nli_model.load_state_dict(ckpt["classifier_state_dict"], strict=False)
754
 
755
- hidden_size = int(nli_model.config.hidden_size)
756
- head = CrossOptionDecisionHead(
757
- hidden_size=hidden_size,
758
- comp_dim=int(ckpt.get("comp_dim", 512)),
759
- dropout=0.0,
760
- )
761
- head.load_state_dict(ckpt["head_state_dict"])
762
- return cls(
763
  nli_backbone=nli_model,
764
  tokenizer=tok,
765
  head=head,
766
  device=device,
767
- max_length=min(512, int(ckpt.get("max_length", 512))),
 
768
  )
 
 
769
 
770
  @torch.no_grad()
771
  def decide(self, state: Any, questions: dict[str, dict[str, Any]], max_length: int | None = None) -> dict[str, Any]:
772
- max_len = max_length or self.max_length
773
- qids = list(questions.keys())
774
  state_str = compact_state_text(state)
775
- peer_summary = ", ".join(f"{qk}({questions[qk].get('type')})" for qk in qids) if len(qids) > 1 else ""
776
-
777
- encoded_qs = [
778
- encode_decision_question(
779
- self.tokenizer,
780
- state,
781
- qid,
782
- questions[qid],
783
- peer_q_summary=peer_summary,
784
- max_length=max_len,
785
- precomputed_state_str=state_str,
786
- )
787
- for qid in qids
788
- ]
789
-
790
- # Flatten all pairs across all questions into ONE single parallel GPU batch
791
- flat_ids: list[list[int]] = []
792
- flat_attn: list[list[int]] = []
793
- flat_prem: list[list[float]] = []
794
- flat_hyp: list[list[float]] = []
795
- q_slices: list[tuple[int, int]] = []
796
-
797
- for eq in encoded_qs:
798
- s_i = len(flat_ids)
799
- flat_ids.extend(eq["pair_ids"])
800
- flat_attn.extend(eq["pair_attn"])
801
- flat_prem.extend(eq["pair_prem"])
802
- flat_hyp.extend(eq["pair_hyp"])
803
- q_slices.append((s_i, len(flat_ids)))
804
-
805
- P = len(flat_ids)
806
- raw_max_L = max(len(x) for x in flat_ids)
807
- pad_L = min(max_len, max(64, ((raw_max_L + 31) // 32) * 32))
808
  pad_id = self.tokenizer.pad_token_id or 0
 
 
 
 
 
 
 
 
 
809
 
810
- ids_cpu = [ids[:pad_L] + [pad_id] * (pad_L - min(len(ids), pad_L)) for ids in flat_ids]
811
- attn_cpu = [at[:pad_L] + [0] * (pad_L - min(len(at), pad_L)) for at in flat_attn]
812
- prem_cpu = [pm[:pad_L] + [0.0] * (pad_L - min(len(pm), pad_L)) for pm in flat_prem]
813
- hyp_cpu = [hm[:pad_L] + [0.0] * (pad_L - min(len(hm), pad_L)) for hm in flat_hyp]
814
-
815
- ids_t = torch.tensor(ids_cpu, dtype=torch.long, device=self.device)
816
- attn_t = torch.tensor(attn_cpu, dtype=torch.long, device=self.device)
817
- prem_t = torch.tensor(prem_cpu, dtype=torch.float32, device=self.device)
818
- hyp_t = torch.tensor(hyp_cpu, dtype=torch.float32, device=self.device)
819
-
820
- seq_chunks: list[torch.Tensor] = []
821
- nli_chunks: list[torch.Tensor] = []
822
- for c_s in range(0, P, 24):
823
- ids_c = ids_t[c_s : c_s + 24]
824
- attn_c = attn_t[c_s : c_s + 24]
825
- if hasattr(self.nli_backbone, "deberta"):
826
- enc_out = self.nli_backbone.deberta(input_ids=ids_c, attention_mask=attn_c)
827
- seq_c = enc_out.last_hidden_state.float()
828
- pooled_c = self.nli_backbone.pooler(seq_c)
829
- nli_c = self.nli_backbone.classifier(pooled_c).float()
830
- else:
831
- out = self.nli_backbone(input_ids=ids_c, attention_mask=attn_c, output_hidden_states=True)
832
- seq_c = out.hidden_states[-1].float()
833
- nli_c = out.logits.float()
834
- seq_chunks.append(seq_c)
835
- nli_chunks.append(nli_c)
836
- seq_f = torch.cat(seq_chunks, dim=0)
837
- nli_f = torch.cat(nli_chunks, dim=0)
838
- pair_vecs_flat, nli_priors_flat = self.head.pool_pair_features(seq_f, nli_f, prem_t, hyp_t)
839
-
840
- B = len(encoded_qs)
841
- max_K = max(len(eq["option_keys"]) for eq in encoded_qs)
842
- feat_dim = pair_vecs_flat.size(-1)
843
-
844
- pv_g = torch.zeros((B, max_K, feat_dim), dtype=torch.float32, device=self.device)
845
- nl_g = torch.zeros((B, max_K, 3), dtype=torch.float32, device=self.device)
846
- np_g = torch.zeros((B, max_K), dtype=torch.float32, device=self.device)
847
- om_g = torch.zeros((B, max_K, 4), dtype=torch.float32, device=self.device)
848
- vk_g = torch.zeros((B, max_K), dtype=torch.bool, device=self.device)
849
- qt_g = torch.zeros((B,), dtype=torch.long, device=self.device)
850
-
851
- for b_i, eq in enumerate(encoded_qs):
852
- s_i, e_i = q_slices[b_i]
853
- K = e_i - s_i
854
- pv_g[b_i, :K] = pair_vecs_flat[s_i:e_i]
855
- nl_g[b_i, :K] = nli_f[s_i:e_i]
856
- np_g[b_i, :K] = nli_priors_flat[s_i:e_i]
857
- om_g[b_i, :K] = torch.tensor(eq["opt_meta"], dtype=torch.float32, device=self.device)
858
- vk_g[b_i, :K] = True
859
- qt_g[b_i] = eq["qtype_id"]
860
-
861
- logits = self.head.score_grouped_options(pv_g, nl_g, np_g, om_g, vk_g, qt_g, apply_temp=True)
862
-
863
- # Estimate realistic input tokens (state + questions once, not Kx duplicated)
864
- approx_state_toks = len(self.tokenizer.encode(state_str, add_special_tokens=False))
865
- approx_q_toks = sum(45 * len(eq["option_keys"]) for eq in encoded_qs)
866
- total_in_toks = approx_state_toks + approx_q_toks
867
-
868
  answers: dict[str, Any] = {}
869
- for b_i, qid in enumerate(qids):
870
- eq = encoded_qs[b_i]
871
- keys = eq["option_keys"]
 
 
872
  K = len(keys)
873
- probs_t = F.softmax(logits[b_i, :K], dim=-1).cpu().tolist()
874
- s_p = sum(probs_t)
875
- probs = [p / s_p for p in probs_t]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
876
  best_idx = max(range(K), key=lambda idx: probs[idx])
877
- qtype = eq["qtype"]
878
  if qtype == "noul":
879
  p_true = float(probs[keys.index("true")]) if "true" in keys else float(probs[-1])
880
  p_true_r = round(min(1.0, max(0.0, p_true)), 6)
 
1
+ """Nullspan System One Probabilistic Typed-Decision Engine v3.0 (`/v1/systemone`).
2
+
3
+ Single-Pass Parallel-Span 8K Bidirectional Encoder Architecture (Zero Output Tokens):
4
+ 1. Schema-Agnostic Symbolic & Reconciliation Perception (`compact_state_text` v3.0):
5
+ Deterministically surfaces aggregate line-item sums vs scalar delivery/order quantities,
6
+ partial-delivery exact matches vs overbilling, unpermitted freight surcharges, missing PO
7
+ identifiers, currency mismatches, exact percentage variances, trace error/step ratios,
8
+ calendar/clock deltas, set membership, and null flags.
9
+ 2. Single-Pass Case-Packed Parallel-Span 8K Encoding (`encode_case_parallel`):
10
+ Packs the entire workflow State + ALL questions + ALL candidate option rubrics into ONE
11
+ single `ModernBERT-large` (`395M`, `28` layers, `8,192`-token RoPE context) forward pass!
12
+ Every option of Question `q` shares identical starting rotary positions (`opt_base_pos`)
13
+ with full 28-layer bidirectional attention (`full_attention == sliding_attention`),
14
+ guaranteeing 100% mathematical option-order permutation equivariance (`< 1e-7` max diff).
15
+ 3. Residual Zero-Shot NLI Prior + `ParallelSpanDecisionHead`:
16
+ Combines pretrained zero-shot NLI entailment log-odds with 2-layer Cross-Option Competition,
17
+ Cross-Question Workflow Propagation, Ordinal Neighbor Smoothing on `score` scales, and
18
+ held-out OOF temperature calibration.
19
  """
20
  from __future__ import annotations
21
 
22
  import datetime as dt
23
+ import inspect
24
  import json
25
  import math
26
  import os
 
91
  return "[Temporal Checks] " + " | ".join(notes) + "\n" + text
92
 
93
 
94
+ def _is_surcharge_line(item: dict[str, Any]) -> bool:
95
+ for k in ("sku", "code", "item", "type", "description", "name"):
96
+ v = item.get(k)
97
+ if isinstance(v, str) and any(tok in v.lower() for tok in ("freight", "shipping", "surcharge", "handling", "delivery_fee")):
98
+ return True
99
+ return False
100
+
101
+
102
  def compact_state_text(state: Any) -> str:
103
+ """Flatten structured JSON/dict state and prepend schema-agnostic symbolic, reconciliation & ratio checks."""
104
  if isinstance(state, str):
105
  s_strip = state.strip()
106
  if s_strip.startswith("{") or s_strip.startswith("["):
 
120
  str_lists: list[tuple[str, list[str]]] = []
121
  null_paths: list[str] = []
122
  arith_notes: list[str] = []
123
+ group_goods_qty: dict[str, float] = {}
124
+ group_unit_prices: dict[str, list[float]] = {}
125
+ surcharge_lines: list[tuple[str, str, float]] = []
126
+ freight_terms_vals: list[tuple[str, str]] = []
127
+ has_usd_key = False
128
+
129
+ def _check_dict_math(top_group: str, prefix: str, d: dict[str, Any]) -> None:
130
+ nonlocal has_usd_key
131
+ for k in d.keys():
132
+ if k.lower().endswith("_usd"):
133
+ has_usd_key = True
134
+
135
+ # 1. Operational / trace telemetry ratios (steps, errors, violations, duration)
136
+ steps_v = d.get("steps")
137
+ if isinstance(steps_v, (int, float)) and not isinstance(steps_v, bool) and steps_v > 0:
138
+ ratio_parts = [f"steps={steps_v:g}"]
139
+ errs_v = d.get("tool_errors")
140
+ if isinstance(errs_v, (int, float)) and not isinstance(errs_v, bool):
141
+ ratio_parts.append(f"tool_errors={errs_v:g} ({100.0 * errs_v / steps_v:.1f}%/step)")
142
+ viol_v = d.get("constraint_violations")
143
+ if isinstance(viol_v, (int, float)) and not isinstance(viol_v, bool):
144
+ ratio_parts.append(f"constraint_violations={viol_v:g} (VIOLATED={viol_v > 0})")
145
+ irrev_v = d.get("irreversible_actions")
146
+ if isinstance(irrev_v, (int, float)) and not isinstance(irrev_v, bool):
147
+ ratio_parts.append(f"irreversible_actions={irrev_v:g} (IRREVERSIBLE={irrev_v > 0})")
148
+ dur_v = d.get("duration_s")
149
+ if isinstance(dur_v, (int, float)) and not isinstance(dur_v, bool):
150
+ ratio_parts.append(f"sec_per_step={dur_v / steps_v:.1f}s")
151
+ if len(ratio_parts) >= 2:
152
+ arith_notes.append(f"_telemetry.{prefix or 'root'}: " + ", ".join(ratio_parts))
153
+
154
+ # 2. Check qty * unit == total inside any dict
155
  q_val, u_val, t_val = None, None, None
156
  for k, v in d.items():
157
  if isinstance(v, bool) or not isinstance(v, (int, float)):
 
167
  expected = round(q_val * u_val, 4)
168
  diff = round(t_val - expected, 4)
169
  arith_notes.append(
170
+ f"_math.{prefix or 'root'}.qty_x_unit: {q_val:g} * {u_val:g} = {expected:g} vs stated {t_val:g} (diff={diff:+.4g}, exact={abs(diff) < 1e-2})"
171
  )
172
 
173
+ # 3. Check sum of child line totals & goods quantities vs parent total
174
+ for k, v in d.items():
175
+ if isinstance(v, str) and "freight" in k.lower():
176
+ freight_terms_vals.append((f"{prefix}.{k}" if prefix else k, v))
177
+ if isinstance(v, list) and v and all(isinstance(x, dict) for x in v):
178
+ child_totals = []
179
+ goods_qtys = []
180
+ u_prices = []
181
+ status_counts: dict[str, int] = {}
182
+ for x in v:
183
+ st_val = x.get("status")
184
+ if isinstance(st_val, str):
185
+ status_counts[st_val] = status_counts.get(st_val, 0) + 1
186
+ is_sur = _is_surcharge_line(x)
187
+ c_tot = None
188
+ c_qty = None
189
+ c_unit = None
190
+ for ck, cv in x.items():
191
+ if not isinstance(cv, bool) and isinstance(cv, (int, float)):
192
+ cnk = _norm_leaf_key(ck)
193
+ if cnk == "total_amt" and c_tot is None:
194
+ c_tot = float(cv)
195
+ elif cnk == "qty" and c_qty is None:
196
+ c_qty = float(cv)
197
+ elif cnk == "unit_amt" and c_unit is None:
198
+ c_unit = float(cv)
199
+ if c_tot is not None:
200
+ child_totals.append(c_tot)
201
+ if is_sur:
202
+ surcharge_lines.append((f"{prefix}.{k}", str(x.get("sku") or x.get("type") or "SURCHARGE"), c_tot or c_unit or 0.0))
203
+ else:
204
+ if c_qty is not None:
205
+ goods_qtys.append(c_qty)
206
+ if c_unit is not None:
207
+ u_prices.append(c_unit)
208
+ tg_key = top_group or prefix or k
209
+ if goods_qtys and tg_key not in group_goods_qty:
210
+ group_goods_qty[tg_key] = round(sum(goods_qtys), 4)
211
+ if u_prices and tg_key not in group_unit_prices:
212
+ group_unit_prices[tg_key] = u_prices
213
+ if status_counts and len(v) >= 2:
214
+ st_summary = ", ".join(f"{sk}:{sv}" for sk, sv in sorted(status_counts.items()))
215
+ arith_notes.append(f"_history.{prefix}.{k}_statuses (total={len(v)}): {st_summary}")
216
+ if t_val is not None and child_totals:
217
+ s_tot = round(sum(child_totals), 4)
218
+ s_diff = round(t_val - s_tot, 4)
219
+ pct_s = 100.0 * s_diff / max(abs(s_tot), 1e-9)
220
+ tag = "EXACT_LINES_SUM" if abs(s_diff) < 1e-2 else f"TAX_OR_HEADER_SURCHARGE_DIFF={s_diff:+.4g} ({pct_s:+.2f}%)"
221
+ arith_notes.append(
222
+ f"_math.{prefix or 'root'}.lines_sum: sum={s_tot:g} vs parent={t_val:g} ({tag})"
223
+ )
224
 
225
  def _walk(top_group: str, prefix: str, obj: Any) -> None:
226
  if isinstance(obj, dict):
227
+ _check_dict_math(top_group, prefix, obj)
228
  for k, v in obj.items():
229
  tg = top_group or str(k)
230
  p = f"{prefix}.{k}" if prefix else str(k)
 
234
  lines.append(f"{prefix}: [] (empty_list, count=0)")
235
  return
236
  if all(isinstance(x, dict) and "role" in x and "text" in x for x in obj):
237
+ cust_turns = sum(1 for x in obj if str(x.get("role")).lower() in ("customer", "user"))
238
+ lines.append(
239
+ f"{prefix}.turn_count: {len(obj)} (customer_turns={cust_turns}, last_speaker={obj[-1].get('role')})"
240
+ )
241
  for idx, turn in enumerate(obj):
242
  lines.append(f"{prefix}[{idx} · {turn.get('role')}]: {turn.get('text')}")
243
  return
 
251
  for idx, item in enumerate(obj):
252
  p_i = f"{prefix}[{idx}]"
253
  if isinstance(item, dict):
254
+ _check_dict_math(top_group or prefix, p_i, item)
255
  flat_parts = []
256
  nested = {}
257
  for ik, iv in item.items():
 
282
  elif isinstance(obj, (int, float)):
283
  tag = " [NEGATIVE]" if obj < 0 else ""
284
  lines.append(f"{prefix}: {obj}{tag}")
285
+ nk = _norm_leaf_key(leaf_name)
286
+ tg = top_group or prefix
287
+ num_leaves.append((tg, prefix, nk, float(obj)))
288
+ if nk == "qty" and "[" not in prefix and (
289
+ tg not in group_goods_qty
290
+ or any(w in leaf_name.lower() for w in ("received", "delivered", "accepted"))
291
+ ):
292
+ group_goods_qty[tg] = float(obj)
293
  else:
294
  s_val = str(obj)
295
  lines.append(f"{prefix}: {s_val}")
296
+ if 1 <= len(s_val) <= 100:
297
  str_leaves.append((top_group or prefix, prefix, leaf_name.lower(), s_val))
298
 
299
  _walk("", "", state)
300
 
301
+ derived: list[str] = []
302
+
303
+ # High-signal cross-entity quantity, delivery, freight, PO & currency reconciliation
304
+ if len(group_goods_qty) >= 2:
305
+ q_summary = ", ".join(f"{gk}={gv:g}" for gk, gv in sorted(group_goods_qty.items()))
306
+ rec_tags: list[str] = []
307
+ deliv_q = group_goods_qty.get("delivery")
308
+ inv_q = group_goods_qty.get("invoice")
309
+ po_q = group_goods_qty.get("purchase_order")
310
+ u_match = (
311
+ "invoice" in group_unit_prices
312
+ and "purchase_order" in group_unit_prices
313
+ and group_unit_prices["invoice"] == group_unit_prices["purchase_order"]
314
+ )
315
+ if deliv_q is not None and deliv_q == 0 and (inv_q or 0) > 0:
316
+ rec_tags.append("NOT_YET_DELIVERED_EARLY_INVOICE=True")
317
+ elif deliv_q is not None and inv_q is not None:
318
+ if inv_q > deliv_q:
319
+ rec_tags.append(f"OVERBILLED_VS_DELIVERY=True (diff={inv_q - deliv_q:+g})")
320
+ elif po_q is not None and inv_q == deliv_q and inv_q < po_q:
321
+ rec_tags.append(f"PARTIAL_DELIVERY_BILLED_FOR_RECEIVED=True (unit_price_match={u_match})")
322
+ elif po_q is not None and inv_q == deliv_q == po_q:
323
+ rec_tags.append(f"ALL_QUANTITIES_EXACT_MATCH=True (unit_price_match={u_match})")
324
+ tag_str = (" -> " + "; ".join(rec_tags)) if rec_tags else ""
325
+ derived.append(f"_reconcile.goods_qty: {q_summary}{tag_str}")
326
+
327
+ if surcharge_lines:
328
+ for s_path, s_sku, s_amt in surcharge_lines:
329
+ unpermitted = any(
330
+ "not separately billable" in ft.lower() or "prepaid" in ft.lower() or "included" in ft.lower()
331
+ for _, ft in freight_terms_vals
332
+ )
333
+ derived.append(
334
+ f"_reconcile.surcharge_line: {s_path} sku={s_sku!r} amt={s_amt:g} (UNPERMITTED_BY_FREIGHT_TERMS={unpermitted})"
335
+ )
336
+
337
+ for _, s_path, s_key, s_val in str_leaves:
338
+ if s_key == "currency" and has_usd_key and s_val.upper() != "USD":
339
+ derived.append(f"_reconcile.currency_mismatch: {s_path}={s_val!r} vs USD-denominated fields (MISMATCH=True)")
340
+
341
+ for np_path in null_paths:
342
+ if np_path.endswith(".id") or np_path in ("purchase_order", "po_id", "purchase_order.id"):
343
+ derived.append(f"_reconcile.missing_reference: {np_path}=null (MISSING_AUTHORIZATION_OR_PO=True)")
344
+
345
+ derived.extend(arith_notes)
346
+
347
  # Cross-subtree numeric comparisons on matching normalized leaf keys & matching list indices
 
348
  seen_pairs: set[tuple[str, str]] = set()
349
  for i in range(len(num_leaves)):
350
  g1, p1, k1, v1 = num_leaves[i]
 
354
  if g1 != g2 and k1 == k2 and idx1 == re.findall(r"\[\d+\]", p2) and (p1, p2) not in seen_pairs:
355
  seen_pairs.add((p1, p2))
356
  diff = v1 - v2
357
+ denom_ref = abs(v2) if abs(v2) > 1e-9 else max(abs(v1), 1e-9)
358
+ pct = 100.0 * diff / denom_ref
359
  eq = abs(diff) < 1e-6
360
  derived.append(
361
+ f"_compare.{p1}_vs_{p2}: exact_equal={eq}, diff={diff:+.4g}, pct_vs_ref={pct:+.2f}%"
362
  )
363
 
364
+ # Cross-subtree short string identifier comparisons
365
  for i in range(len(str_leaves)):
366
  g1, p1, k1, s1 = str_leaves[i]
367
  if k1 not in ("sku", "currency", "vendor", "account", "id", "po_id", "tier", "model"):
 
375
 
376
  # Scalar-in-list membership checks (duplicate IDs, allowlists, queues)
377
  for _, s_path, s_key, s_val in str_leaves:
378
+ if len(s_val) < 2 or (" " in s_val and len(s_val) > 40):
379
  continue
380
  for arr_path, arr_vals in str_lists:
381
  in_arr = s_val in arr_vals or any(s_val.lower() == a.lower() for a in arr_vals)
382
  key_toks = set(re.findall(r"[a-z]+", s_path.lower()))
383
  arr_toks = set(re.findall(r"[a-z]+", arr_path.lower()))
 
384
  key_stems = {t.rstrip("s") for t in key_toks if len(t) >= 2}
385
  arr_stems = {t.rstrip("s") for t in arr_toks if len(t) >= 2}
386
  if in_arr or (key_stems & arr_stems):
387
+ dup_tag = " [DUPLICATE_MATCH]" if in_arr else ""
388
+ derived.append(f"_membership.{s_path}_in_{arr_path}: {in_arr}{dup_tag}")
389
 
390
  if null_paths:
391
  derived.append("_null_fields: " + ", ".join(null_paths[:12]))
 
396
  derived.insert(0, t_notes_raw.split("\n", 1)[0])
397
 
398
  if derived:
399
+ return "\n".join(["=== Derived Structural Checks ===", *derived[:20], "--- State ---", *lines])
400
 
401
  return body_txt
402
 
403
 
404
+ QTYPE_TO_ID = {"noul": 0, "choice": 1, "score": 2}
 
405
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
 
407
+ def canonical_options(question: dict[str, Any]) -> list[tuple[str, str]]:
408
+ """Extract ordered (option_key, rubric_description) pairs for noul, choice, or score."""
409
+ qtype = question["type"]
410
+ crit = question.get("criteria")
411
+ instr = str(question.get("instructions") or "").strip().rstrip(".")
412
+ if qtype == "score":
413
+ if isinstance(crit, list) and crit:
414
+ return [(str(i), str(desc)) for i, desc in enumerate(crit)]
415
+ mn = int(question.get("min", 0))
416
+ mx = int(question.get("max", 3))
417
+ return [(str(lv), f"Level {lv} on scale {mn}..{mx}") for lv in range(mn, mx + 1)]
418
+ if qtype == "noul":
419
+ cdict = crit if isinstance(crit, dict) else {}
420
+ false_desc = str(
421
+ cdict.get("false")
422
+ or cdict.get("no")
423
+ or (f"False / No — the evidence does NOT support that: {instr}." if instr else "False / No: statement does not hold.")
424
+ )
425
+ true_desc = str(
426
+ cdict.get("true")
427
+ or cdict.get("yes")
428
+ or (f"True / Yes — the evidence confirms that: {instr}." if instr else "True / Yes: statement holds.")
429
+ )
430
+ return [("false", false_desc), ("true", true_desc)]
431
+ if isinstance(crit, dict):
432
+ return [(str(k), str(v) if v else str(k)) for k, v in crit.items()]
433
+ opts = question.get("options") or []
434
+ return [(str(o), str(o)) for o in opts]
435
 
 
 
 
 
 
 
 
 
 
436
 
437
+ def question_signature(qid: str, question: dict[str, Any]) -> str:
438
+ """Order-invariant canonical signature `(qid, qtype, sorted option rubrics)` for per-schema OOF calibration."""
439
+ qtype = str(question.get("type") or "")
440
+ opts = canonical_options(question)
441
+ parts = sorted(f"{k.strip()}={v.strip()[:64]}" for k, v in opts)
442
+ return f"{qid}::{qtype}::" + "||".join(parts)
 
 
 
 
 
 
 
 
 
 
 
 
 
443
 
444
 
445
  class CrossOptionBlock(nn.Module):
 
479
  return x
480
 
481
 
482
+ class ParallelSpanDecisionHead(nn.Module):
483
+ """v3.0 Single-Pass Parallel-Span Cross-Option + Cross-Question + Ordinal Neighbor Scorer."""
484
 
485
+ def __init__(self, hidden_size: int = 1024, comp_dim: int = 512, zs_dim: int = 2, dropout: float = 0.1) -> None:
486
  super().__init__()
487
+ self.hidden_size = hidden_size
488
+ self.comp_dim = comp_dim
489
+ self.zs_dim = zs_dim
490
+
491
+ # Option-to-State fine-grained cross-attention pooling
492
+ self.state_q = nn.Linear(hidden_size * 2, hidden_size)
493
+ self.state_k = nn.Linear(hidden_size, hidden_size)
494
+ self.scale_h = 1.0 / math.sqrt(hidden_size)
495
+
496
+ # Fuse [opt_mean, opt_max, q_hdr_mean, state_att, cls_v, zs_logits (2), opt_meta (6)]
497
+ in_dim = hidden_size * 5 + zs_dim + 6
498
+ self.opt_proj = nn.Sequential(
499
+ nn.Linear(in_dim, comp_dim),
500
  nn.LayerNorm(comp_dim),
501
  nn.GELU(),
502
  nn.Dropout(dropout),
503
  )
 
 
 
504
 
505
  self.blocks = nn.ModuleList([
506
  CrossOptionBlock(dim=comp_dim, num_heads=8, dropout=dropout),
507
  CrossOptionBlock(dim=comp_dim, num_heads=8, dropout=dropout),
508
  ])
509
+
510
+ # Cross-question workflow propagation over sibling questions on the same case
511
  self.wf_norm = nn.LayerNorm(comp_dim)
512
  self.wf_qkv = nn.Linear(comp_dim, comp_dim * 3)
513
  self.wf_out = nn.Linear(comp_dim, comp_dim)
514
  nn.init.zeros_(self.wf_out.weight)
515
  nn.init.zeros_(self.wf_out.bias)
516
 
517
+ # Ordinal neighbor context projection (active ONLY when is_score == 1.0; zero on choice/noul!)
518
+ self.ord_neighbor = nn.Linear(comp_dim * 2, comp_dim)
519
+ nn.init.zeros_(self.ord_neighbor.weight)
520
+ nn.init.zeros_(self.ord_neighbor.bias)
521
+
522
+ # Final rival-margin MLP over [x_k, x_k - rival_max, x_k - mean_x]
523
  self.out_mlp = nn.Sequential(
524
  nn.Linear(comp_dim * 3, comp_dim // 2),
525
  nn.GELU(),
526
  nn.Dropout(dropout),
527
  nn.Linear(comp_dim // 2, 1),
528
  )
 
529
  nn.init.zeros_(self.out_mlp[-1].weight)
530
  nn.init.zeros_(self.out_mlp[-1].bias)
531
 
532
+ # Learnable zero-shot NLI prior weights ([entailment, not_entailment] -> +0.55, -0.55)
533
+ init_w = [0.55, -0.55] if zs_dim == 2 else ([0.75, -0.10, -0.65] if zs_dim == 3 else [0.0] * zs_dim)
534
+ self.zs_weights = nn.Parameter(torch.tensor(init_w, dtype=torch.float32))
535
  # Per-question-type log temperatures: [noul (0), choice (1), score (2)]
536
  self.log_temps = nn.Parameter(torch.zeros(3, dtype=torch.float32))
537
+ # Per-question-type logit uniform-smoothing alpha (in logit space, default 0)
538
+ self.prob_smooth = nn.Parameter(torch.zeros(3, dtype=torch.float32), requires_grad=False)
539
 
540
+ def forward_packed_cases(
541
  self,
542
  seq_out: torch.Tensor,
543
+ packed_cases: list[dict[str, Any]],
544
+ zs_head_fn: Any | None = None,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
545
  apply_temp: bool = False,
546
+ ) -> tuple[torch.Tensor, list[dict[str, Any]]]:
547
  """
548
+ seq_out: [B_cases, L, H] float32
549
+ packed_cases: list of length B_cases from `encode_case_parallel`
550
+ Returns (logits [Q_total, max_K], flat_questions_meta)
 
 
 
 
 
551
  """
552
+ device = seq_out.device
553
+ H = self.hidden_size
554
+ flat_q_meta: list[dict[str, Any]] = []
555
+ for c_idx, pc in enumerate(packed_cases):
556
+ for qm in pc["questions"]:
557
+ flat_q_meta.append({**qm, "_c_idx": c_idx, "_state_span": pc["state_span"], "_case_id": pc.get("case_id", c_idx)})
558
+
559
+ Q_tot = len(flat_q_meta)
560
+ max_K = max(len(qm["option_keys"]) for qm in flat_q_meta)
561
+
562
+ opt_mean_t = torch.zeros((Q_tot, max_K, H), dtype=torch.float32, device=device)
563
+ opt_max_t = torch.zeros((Q_tot, max_K, H), dtype=torch.float32, device=device)
564
+ q_hdr_t = torch.zeros((Q_tot, max_K, H), dtype=torch.float32, device=device)
565
+ st_att_t = torch.zeros((Q_tot, max_K, H), dtype=torch.float32, device=device)
566
+ cls_t = torch.zeros((Q_tot, max_K, H), dtype=torch.float32, device=device)
567
+ om_t = torch.zeros((Q_tot, max_K, 6), dtype=torch.float32, device=device)
568
+ vk_t = torch.zeros((Q_tot, max_K), dtype=torch.bool, device=device)
569
+ qt_t = torch.zeros((Q_tot,), dtype=torch.long, device=device)
570
+ cid_t = torch.zeros((Q_tot,), dtype=torch.long, device=device)
571
+
572
+ # Precompute state_k per case once for speed
573
+ case_state_h: list[torch.Tensor] = []
574
+ case_state_k: list[torch.Tensor] = []
575
+ for c_idx, pc in enumerate(packed_cases):
576
+ ss, se = pc["state_span"]
577
+ sh = seq_out[c_idx, ss : max(ss + 1, se)] # [Ls, H]
578
+ case_state_h.append(sh)
579
+ case_state_k.append(self.state_k(sh)) # [Ls, H]
580
+
581
+ for q_i, qm in enumerate(flat_q_meta):
582
+ c_idx = qm["_c_idx"]
583
+ cls_v = seq_out[c_idx, 0]
584
+ hs, he = qm["hdr_span"]
585
+ q_hdr_v = seq_out[c_idx, hs : max(hs + 1, he)].mean(dim=0)
586
+ K = len(qm["option_keys"])
587
+ sh = case_state_h[c_idx]
588
+ sk = case_state_k[c_idx]
589
+
590
+ om_spans = []
591
+ ox_spans = []
592
+ for k_i, (os_i, oe_i) in enumerate(qm["opt_spans"]):
593
+ sl = seq_out[c_idx, os_i : max(os_i + 1, oe_i)]
594
+ om_spans.append(sl.mean(dim=0))
595
+ ox_spans.append(sl.max(dim=0).values)
596
+ om_stack = torch.stack(om_spans, dim=0) # [K, H]
597
+ ox_stack = torch.stack(ox_spans, dim=0) # [K, H]
598
+ q_hdr_exp = q_hdr_v.unsqueeze(0).expand(K, H)
599
+
600
+ # Query-conditioned state attention per option: [K, H] @ [H, Ls] -> [K, Ls]
601
+ sq = self.state_q(torch.cat([om_stack, q_hdr_exp], dim=-1)) # [K, H]
602
+ att_w = F.softmax(torch.matmul(sq, sk.t()) * self.scale_h, dim=-1)
603
+ s_att = torch.matmul(att_w, sh) # [K, H]
604
+
605
+ opt_mean_t[q_i, :K] = om_stack
606
+ opt_max_t[q_i, :K] = ox_stack
607
+ q_hdr_t[q_i, :K] = q_hdr_exp
608
+ st_att_t[q_i, :K] = s_att
609
+ cls_t[q_i, :K] = cls_v.unsqueeze(0).expand(K, H)
610
+ om_t[q_i, :K] = torch.tensor(qm["opt_meta"], dtype=torch.float32, device=device)
611
+ vk_t[q_i, :K] = True
612
+ qt_t[q_i] = int(qm["qtype_id"])
613
+ cid_t[q_i] = int(qm["_case_id"])
614
+
615
+ if zs_head_fn is not None and self.zs_dim > 0:
616
+ blend_h = 0.5 * opt_mean_t + 0.5 * st_att_t
617
+ zs_logits = zs_head_fn(blend_h).float() # [Q_tot, max_K, zs_dim]
618
+ zs_priors = (zs_logits * self.zs_weights.view(1, 1, -1)).sum(dim=-1)
619
+ else:
620
+ zs_logits = torch.zeros((Q_tot, max_K, self.zs_dim), dtype=torch.float32, device=device)
621
+ zs_priors = torch.zeros((Q_tot, max_K), dtype=torch.float32, device=device)
622
+
623
+ feats = torch.cat([opt_mean_t, opt_max_t, q_hdr_t, st_att_t, cls_t, zs_logits, om_t], dim=-1)
624
+ x = self.opt_proj(feats) # [Q_tot, max_K, comp_dim]
625
+ x = self.blocks[0](x, vk_t)
626
+
627
+ # Ordinal neighbor message passing strictly for `score` scales (is_score == 1)
628
+ is_score_q = (qt_t == 2).to(x.dtype).view(Q_tot, 1, 1)
629
+ if max_K > 1:
630
+ left_nb = torch.cat([x[:, :1, :], x[:, :-1, :]], dim=1)
631
+ right_nb = torch.cat([x[:, 1:, :], x[:, -1:, :]], dim=1)
632
+ # Clamp right neighbor at K_q - 1 boundary
633
+ k_counts = vk_t.sum(dim=1).clamp(min=1) # [Q_tot]
634
+ for q_i in range(Q_tot):
635
+ kq = int(k_counts[q_i].item())
636
+ if kq < max_K:
637
+ right_nb[q_i, kq - 1] = x[q_i, kq - 1]
638
+ x = x + is_score_q * self.ord_neighbor(torch.cat([x - left_nb, right_nb - x], dim=-1))
639
+
640
+ # Cross-question workflow propagation across sibling questions sharing `_case_id`
641
+ prior_w = F.softmax(zs_priors.masked_fill(~vk_t, -1e4), dim=-1).unsqueeze(-1)
642
+ q_post = (x * prior_w).sum(dim=1) # [Q_tot, comp_dim]
643
  qh = self.wf_norm(q_post)
644
  D = qh.size(-1)
645
  nh = 8
646
  hd = D // nh
647
+ qkv = self.wf_qkv(qh).view(Q_tot, 3, nh, hd)
648
+ qw = qkv[:, 0].transpose(0, 1)
649
  kw = qkv[:, 1].transpose(0, 1)
650
  vw = qkv[:, 2].transpose(0, 1)
651
+ same_case = cid_t[:, None] == cid_t[None, :]
652
+ wf_bias = torch.zeros((1, Q_tot, Q_tot), dtype=x.dtype, device=device).masked_fill(~same_case.unsqueeze(0), -1e4)
 
 
 
653
  wf_attn = F.softmax(torch.matmul(qw, kw.transpose(-2, -1)) / math.sqrt(hd) + wf_bias, dim=-1)
654
+ wf_ctx = torch.matmul(wf_attn, vw).transpose(0, 1).contiguous().view(Q_tot, D)
655
  x = x + self.wf_out(wf_ctx).unsqueeze(1)
656
 
657
+ x = self.blocks[1](x, vk_t)
658
 
659
+ vk_f = vk_t.to(x.dtype).unsqueeze(-1)
 
660
  mean_x = (x * vk_f).sum(dim=1, keepdim=True) / vk_f.sum(dim=1, keepdim=True).clamp(min=1.0)
661
+ eye = torch.eye(max_K, dtype=torch.bool, device=device).unsqueeze(0)
662
+ other_valid = vk_t.unsqueeze(1) & (~eye)
663
+ x_exp = x.unsqueeze(1).expand(Q_tot, max_K, max_K, D)
 
 
664
  masked_other = x_exp.masked_fill(~other_valid.unsqueeze(-1), -1e4)
665
  rival_max = masked_other.max(dim=2).values
 
666
  has_other = other_valid.any(dim=2, keepdim=True)
667
  rival_max = torch.where(has_other, rival_max, mean_x.expand_as(rival_max))
668
 
669
  comp_feats = torch.cat([x, x - rival_max, x - mean_x], dim=-1)
670
+ res_logits = self.out_mlp(comp_feats).squeeze(-1)
671
+ logits = zs_priors + res_logits
672
 
673
  if apply_temp:
674
+ temps = torch.exp(self.log_temps[qt_t]).clamp(0.15, 5.0).unsqueeze(-1)
675
  logits = logits / temps
676
+ return logits, flat_q_meta
677
 
678
 
679
+ def encode_case_parallel(
680
+ tokenizer: Any,
681
+ state: Any,
682
+ questions: dict[str, dict[str, Any]],
683
+ max_state_tokens: int = 3072,
684
+ case_id: int = 0,
685
+ precomputed_state_str: str | None = None,
686
+ ) -> dict[str, Any]:
687
+ """Pack State + ALL questions + ALL candidate options into ONE parallel-positioned token sequence."""
688
+ state_str = precomputed_state_str if precomputed_state_str is not None else compact_state_text(state)
689
+ cls_id = tokenizer.cls_token_id if tokenizer.cls_token_id is not None else (tokenizer.bos_token_id or 0)
690
+ sep_id = tokenizer.sep_token_id if tokenizer.sep_token_id is not None else (tokenizer.eos_token_id or 0)
691
+
692
+ state_toks = tokenizer.encode("State:\n" + state_str, add_special_tokens=False)
693
+ if len(state_toks) > max_state_tokens:
694
+ # Preserve head (derived checks + intro) + tail (late overriding exceptions / final turns)
695
+ half_h = int(max_state_tokens * 0.55)
696
+ half_t = max_state_tokens - half_h
697
+ state_toks = state_toks[:half_h] + state_toks[-half_t:]
698
+
699
+ input_ids: list[int] = [cls_id, *state_toks, sep_id]
700
+ pos_ids: list[int] = list(range(len(input_ids)))
701
+ q_owner_ids: list[int] = [0] * len(input_ids)
702
+ opt_branch_ids: list[int] = [0] * len(input_ids)
703
+ state_span = (1, 1 + len(state_toks))
704
+ cur_pos = len(input_ids)
705
+
706
+ q_records: list[dict[str, Any]] = []
707
+ for q_idx, (qid, question) in enumerate(questions.items(), start=1):
708
+ qtype = question["type"]
709
+ qtype_id = QTYPE_TO_ID.get(qtype, 1)
710
+ opts = canonical_options(question)
711
+ K = len(opts)
712
+ instr = str(question.get("instructions") or "").strip()
713
+
714
+ hdr_txt = f"\nQuestion [{qid} | {qtype}]: {instr}\nOptions:"
715
+ hdr_toks = tokenizer.encode(hdr_txt, add_special_tokens=False)[:192]
716
+ if not hdr_toks:
717
+ hdr_toks = [sep_id]
718
+ hdr_start = len(input_ids)
719
+ input_ids.extend(hdr_toks)
720
+ pos_ids.extend(range(cur_pos, cur_pos + len(hdr_toks)))
721
+ q_owner_ids.extend([q_idx] * len(hdr_toks))
722
+ opt_branch_ids.extend([0] * len(hdr_toks))
723
+ hdr_end = len(input_ids)
724
+ cur_pos += len(hdr_toks)
725
+
726
+ # CRITICAL: All options of Question `qid` start at the exact same `opt_base_pos`
727
+ # AND are isolated in a parallel tree mask (`opt_branch_ids == k_i + 1`) so sibling options
728
+ # never bleed across identical RoPE coordinates while remaining 100% option-order invariant!
729
+ opt_base_pos = cur_pos
730
+ opt_spans: list[tuple[int, int]] = []
731
+ opt_meta: list[list[float]] = []
732
+ max_o_len = 1
733
+
734
+ is_noul = 1.0 if qtype == "noul" else 0.0
735
+ is_choice = 1.0 if qtype == "choice" else 0.0
736
+ is_score = 1.0 if qtype == "score" else 0.0
737
+ inv_k = 1.0 / max(1, K)
738
+
739
+ for k_i, (key, rubric) in enumerate(opts):
740
+ if qtype == "noul":
741
+ is_yes = key.lower() in ("true", "yes")
742
+ verdict = "YES / TRUE" if is_yes else "NO / FALSE"
743
+ opt_txt = f" [{verdict}: {rubric}]"
744
+ ord_pos = 1.0 if is_yes else 0.0
745
+ elif qtype == "score":
746
+ opt_txt = f" [SCORE {key} of 0..{max(0, K - 1)}: {rubric}]"
747
+ ord_pos = k_i / max(1, K - 1) if K > 1 else 0.5
748
+ else:
749
+ # Strip single-character positional labels (A/B/C/D/0/1) so option relabeling & permutation are invariant
750
+ clean_k = key.strip()
751
+ if len(clean_k) > 1 and not clean_k.isdigit() and clean_k.lower() != rubric.strip().lower():
752
+ opt_txt = f" [OPTION {clean_k}: {rubric}]"
753
+ else:
754
+ opt_txt = f" [OPTION: {rubric}]"
755
+ ord_pos = 0.5 # Exact symmetry across all unordered `choice` options!
756
+
757
+ o_toks = tokenizer.encode(opt_txt, add_special_tokens=False)[:159] + [sep_id]
758
+ o_start = len(input_ids)
759
+ input_ids.extend(o_toks)
760
+ pos_ids.extend(range(opt_base_pos, opt_base_pos + len(o_toks)))
761
+ q_owner_ids.extend([q_idx] * len(o_toks))
762
+ opt_branch_ids.extend([k_i + 1] * len(o_toks))
763
+ o_end = len(input_ids)
764
+ opt_spans.append((o_start, o_end))
765
+ max_o_len = max(max_o_len, len(o_toks))
766
+ opt_meta.append([ord_pos, ord_pos * ord_pos, is_noul, is_choice, is_score, inv_k])
767
+
768
+ q_records.append({
769
+ "qid": qid,
770
+ "qsig": question_signature(qid, question),
771
+ "qtype": qtype,
772
+ "qtype_id": qtype_id,
773
+ "option_keys": [k for k, _ in opts],
774
+ "hdr_span": (hdr_start, hdr_end),
775
+ "opt_spans": opt_spans,
776
+ "opt_meta": opt_meta,
777
+ })
778
 
779
+ return {
780
+ "case_id": case_id,
781
+ "input_ids": input_ids,
782
+ "position_ids": pos_ids,
783
+ "q_owner_ids": q_owner_ids,
784
+ "opt_branch_ids": opt_branch_ids,
785
+ "state_span": state_span,
786
+ "questions": q_records,
787
+ }
788
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
789
 
790
+ def configure_modernbert_full_bidir(backbone: Any, tokenizer: Any | None = None) -> None:
791
+ """Configure ModernBERT / Ettin for 8,192-token full bidirectional SDPA with custom parallel `position_ids` across HF 4.x & 5.x."""
792
+ if tokenizer is not None:
793
+ tokenizer.model_max_length = 8192
794
+ cfg = getattr(backbone, "config", None)
795
+ if cfg is not None:
796
+ cfg.local_attention = 16384
797
+ cfg.sliding_window = 16384
798
+ cfg.global_attn_every_n_layers = 1
799
+ cfg._attn_implementation = "sdpa"
800
+ cfg.reference_compile = False
801
+ if hasattr(cfg, "layer_types") and isinstance(cfg.layer_types, list):
802
+ cfg.layer_types = ["full_attention"] * len(cfg.layer_types)
803
+ enc_model = getattr(backbone, "model", None)
804
+ for layer in getattr(enc_model, "layers", []):
805
+ if hasattr(layer, "attention_type"):
806
+ layer.attention_type = "full_attention"
807
+ attn_mod = getattr(layer, "attn", None)
808
+ if attn_mod is not None and hasattr(attn_mod, "local_attention"):
809
+ attn_mod.local_attention = (-1, -1)
810
+
811
+
812
+ def build_parallel_tree_mask(
813
+ q_t: torch.Tensor,
814
+ o_t: torch.Tensor,
815
+ dtype: torch.dtype,
816
+ return_bool: bool = False,
817
+ ) -> torch.Tensor:
818
+ """Build exact `[B, 1, L, L]` parallel-option tree mask:
819
+ - State & Question Headers (`o_t == 0`) attend freely to State & Question Headers (`o_t == 0`), never options.
820
+ - Each Option `(q, k)` (`o_t > 0`) attends to State (`q_t == 0`), its own Question Header `q` (`q_t == q, o_t == 0`),
821
+ and ITSELF (`q_t == q, o_t == k`), strictly eliminating cross-option RoPE collision!
822
+ """
823
+ valid = q_t >= 0
824
+ is_opt_q = o_t[:, :, None] > 0
825
+ allow_non_opt = o_t[:, None, :] == 0
826
+ same_q = q_t[:, None, :] == q_t[:, :, None]
827
+ allow_opt = (q_t[:, None, :] == 0) | (same_q & ((o_t[:, None, :] == 0) | (o_t[:, None, :] == o_t[:, :, None])))
828
+ allow = valid[:, :, None] & valid[:, None, :] & torch.where(is_opt_q, allow_opt, allow_non_opt)
829
+ if return_bool:
830
+ return allow.unsqueeze(1)
831
+ neg_val = -1e4 if dtype in (torch.float16, torch.bfloat16) else -1e9
832
+ mask_4d = torch.zeros(allow.shape, dtype=dtype, device=q_t.device).masked_fill(~allow, neg_val)
833
+ return mask_4d.unsqueeze(1)
834
+
835
+
836
+ def forward_parallel_backbone(
837
+ backbone: Any,
838
+ packed_cases: list[dict[str, Any]],
839
+ pad_id: int,
840
+ device: str,
841
+ amp_dtype: torch.dtype = torch.float32,
842
+ ) -> tuple[torch.Tensor, Any]:
843
+ """Run ONE batched forward pass of ModernBERT across `B` packed multi-question cases with exact parallel tree isolation."""
844
+ raw_max_L = max(len(pc["input_ids"]) for pc in packed_cases)
845
+ pad_L = max(32, ((raw_max_L + 31) // 32) * 32)
846
+
847
+ ids_cpu = [pc["input_ids"] + [pad_id] * (pad_L - len(pc["input_ids"])) for pc in packed_cases]
848
+ pos_cpu = [pc["position_ids"] + [0] * (pad_L - len(pc["position_ids"])) for pc in packed_cases]
849
+ qow_cpu = [pc["q_owner_ids"] + [-1] * (pad_L - len(pc["q_owner_ids"])) for pc in packed_cases]
850
+ obr_cpu = [pc["opt_branch_ids"] + [-1] * (pad_L - len(pc["opt_branch_ids"])) for pc in packed_cases]
851
+
852
+ ids_t = torch.tensor(ids_cpu, dtype=torch.long, device=device)
853
+ pos_t = torch.tensor(pos_cpu, dtype=torch.long, device=device)
854
+ qow_t = torch.tensor(qow_cpu, dtype=torch.long, device=device)
855
+ obr_t = torch.tensor(obr_cpu, dtype=torch.long, device=device)
856
+
857
+ use_amp = (device == "cuda") and (amp_dtype in (torch.bfloat16, torch.float16))
858
+ mask_dt = amp_dtype if use_amp else next(backbone.parameters()).dtype
859
+ if hasattr(backbone, "model"):
860
+ m = backbone.model
861
+ is_hf4 = "sliding_window_mask" in inspect.signature(m.forward).parameters
862
+ tree_mask = build_parallel_tree_mask(qow_t, obr_t, dtype=mask_dt, return_bool=not is_hf4)
863
+ with torch.amp.autocast("cuda", dtype=amp_dtype, enabled=use_amp):
864
+ if is_hf4:
865
+ hidden_states = m.embeddings(input_ids=ids_t)
866
+ for encoder_layer in m.layers:
867
+ layer_outputs = encoder_layer(
868
+ hidden_states,
869
+ attention_mask=tree_mask,
870
+ sliding_window_mask=tree_mask,
871
+ position_ids=pos_t,
872
+ )
873
+ hidden_states = layer_outputs[0]
874
+ seq_f = m.final_norm(hidden_states).float()
875
+ else:
876
+ enc_out = m(
877
+ input_ids=ids_t,
878
+ attention_mask={"full_attention": tree_mask, "sliding_attention": tree_mask},
879
+ position_ids=pos_t,
880
+ )
881
+ seq_f = enc_out.last_hidden_state.float()
882
 
883
+ def zs_fn(h_tensor: torch.Tensor) -> torch.Tensor:
884
+ with torch.amp.autocast("cuda", dtype=amp_dtype, enabled=use_amp):
885
+ in_dt = next(backbone.head.parameters()).dtype
886
+ return backbone.classifier(backbone.head(h_tensor.to(in_dt))).float()
887
+
888
+ return seq_f, zs_fn
889
+
890
+ # Generic fallback for non-ModernBERT encoders
891
+ att_t = (qow_t >= 0).long()
892
+ with torch.amp.autocast("cuda", dtype=amp_dtype, enabled=use_amp):
893
+ out = backbone(input_ids=ids_t, attention_mask=att_t, position_ids=pos_t, output_hidden_states=True)
894
+ seq_f = out.hidden_states[-1].float()
895
+ return seq_f, None
896
+
897
+
898
+ # --- Legacy v2.0 LoRA & Pairwise Helpers Retained for Backward Compatibility ---
899
+
900
+
901
+ class LoRALinear(nn.Module):
902
+ """Rank-r LoRA wrapper preserving frozen base nn.Linear weights."""
903
+
904
+ def __init__(self, base: nn.Linear, r: int = 16, alpha: float = 32.0, dropout: float = 0.05) -> None:
905
+ super().__init__()
906
+ self.base = base
907
+ for p in self.base.parameters():
908
+ p.requires_grad = False
909
+ self.r = r
910
+ self.scale = alpha / r
911
+ self.drop = nn.Dropout(dropout)
912
+ self.lora_A = nn.Parameter(torch.empty(r, base.in_features))
913
+ self.lora_B = nn.Parameter(torch.zeros(base.out_features, r))
914
+ nn.init.kaiming_uniform_(self.lora_A, a=math.sqrt(5))
915
+
916
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
917
+ orig_dtype = x.dtype
918
+ out = self.base(x.to(self.base.weight.dtype))
919
+ lora_delta = (self.drop(x.to(self.lora_A.dtype)) @ self.lora_A.t() @ self.lora_B.t()) * self.scale
920
+ return out.to(orig_dtype) + lora_delta.to(orig_dtype)
921
+
922
+
923
+ def inject_encoder_lora(backbone: nn.Module, start_layer: int = 8, r: int = 16, alpha: float = 32.0) -> list[str]:
924
+ """Inject LoRA adapters into DeBERTa-v3 or ELECTRA/BERT encoder layers from `start_layer` up."""
925
+ wrapped: list[str] = []
926
+ if hasattr(backbone, "deberta"):
927
+ layers = backbone.deberta.encoder.layer
928
+ elif hasattr(backbone, "encoder") and hasattr(backbone.encoder, "layer"):
929
+ layers = backbone.encoder.layer
930
  else:
931
+ raise ValueError(f"Unsupported encoder architecture: {type(backbone)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
932
 
933
+ for idx in range(start_layer, len(layers)):
934
+ blk = layers[idx]
935
+ attn_self = blk.attention.self
936
+ for attr in ("query_proj", "key_proj", "value_proj", "query", "key", "value"):
937
+ if hasattr(attn_self, attr):
938
+ orig = getattr(attn_self, attr)
939
+ if isinstance(orig, nn.Linear):
940
+ setattr(attn_self, attr, LoRALinear(orig, r=r, alpha=alpha))
941
+ wrapped.append(f"layer.{idx}.attention.self.{attr}")
942
+ if hasattr(blk.attention, "output") and isinstance(blk.attention.output.dense, nn.Linear):
943
+ blk.attention.output.dense = LoRALinear(blk.attention.output.dense, r=r, alpha=alpha)
944
+ wrapped.append(f"layer.{idx}.attention.output.dense")
945
+ if hasattr(blk, "intermediate") and isinstance(blk.intermediate.dense, nn.Linear):
946
+ blk.intermediate.dense = LoRALinear(blk.intermediate.dense, r=r, alpha=alpha)
947
+ wrapped.append(f"layer.{idx}.intermediate.dense")
948
+ if hasattr(blk, "output") and isinstance(blk.output.dense, nn.Linear):
949
+ blk.output.dense = LoRALinear(blk.output.dense, r=r, alpha=alpha)
950
+ wrapped.append(f"layer.{idx}.output.dense")
951
+ return wrapped
952
 
953
 
954
+ class CrossOptionDecisionHead(nn.Module):
955
+ """v2.0 Pairwise Residual NLI-Prior + 2-Layer Cross-Option Competition Scorer (legacy support)."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
956
 
957
+ def __init__(self, hidden_size: int = 1024, comp_dim: int = 512, dropout: float = 0.1) -> None:
958
+ super().__init__()
959
+ self.pair_proj = nn.Sequential(
960
+ nn.Linear(hidden_size * 3 + 7, comp_dim),
961
+ nn.LayerNorm(comp_dim),
962
+ nn.GELU(),
963
+ nn.Dropout(dropout),
964
+ )
965
+ self.prem_q = nn.Linear(hidden_size, hidden_size)
966
+ self.prem_k = nn.Linear(hidden_size, hidden_size)
967
+ self.scale_h = 1.0 / math.sqrt(hidden_size)
968
+ self.blocks = nn.ModuleList([
969
+ CrossOptionBlock(dim=comp_dim, num_heads=8, dropout=dropout),
970
+ CrossOptionBlock(dim=comp_dim, num_heads=8, dropout=dropout),
971
+ ])
972
+ self.wf_norm = nn.LayerNorm(comp_dim)
973
+ self.wf_qkv = nn.Linear(comp_dim, comp_dim * 3)
974
+ self.wf_out = nn.Linear(comp_dim, comp_dim)
975
+ self.out_mlp = nn.Sequential(
976
+ nn.Linear(comp_dim * 3, comp_dim // 2),
977
+ nn.GELU(),
978
+ nn.Dropout(dropout),
979
+ nn.Linear(comp_dim // 2, 1),
980
+ )
981
+ self.nli_weights = nn.Parameter(torch.tensor([0.75, -0.10, -0.65], dtype=torch.float32))
982
+ self.log_temps = nn.Parameter(torch.zeros(3, dtype=torch.float32))
983
 
984
 
985
  class NullspanSystemOneEngine:
986
+ """Unified System One v3.0 inference engine supporting `/v1/systemone` for Typed Decisions & JevBench."""
987
 
988
  def __init__(
989
  self,
990
  nli_backbone: Any,
991
  tokenizer: Any,
992
+ head: nn.Module,
993
  device: str = "cpu",
994
+ max_length: int = 3072,
995
+ arch_version: int = 3,
996
  ) -> None:
997
  self.nli_backbone = nli_backbone
998
  self.tokenizer = tokenizer
999
  self.head = head
1000
  self.device = device
1001
  self.max_length = max_length
1002
+ self.arch_version = arch_version
1003
+ self.schema_calib: dict[str, dict[str, Any]] = {}
1004
+ if arch_version >= 3:
1005
+ configure_modernbert_full_bidir(self.nli_backbone, self.tokenizer)
1006
+ self.amp_dtype = (
1007
+ torch.bfloat16
1008
+ if (device == "cuda" and torch.cuda.get_device_capability(0)[0] >= 8)
1009
+ else (torch.float16 if device == "cuda" else torch.float32)
1010
+ )
1011
  self.nli_backbone.to(device).eval()
1012
+ if device == "cuda" and arch_version == 3:
1013
+ self.nli_backbone.to(self.amp_dtype)
1014
  self.head.to(device).eval()
1015
 
1016
  @classmethod
 
1020
  device: str | None = None,
1021
  revision: str | None = None,
1022
  ) -> "NullspanSystemOneEngine":
1023
+ from transformers import AutoConfig, AutoModelForSequenceClassification, AutoTokenizer
1024
 
1025
  if device is None:
1026
  if torch.cuda.is_available():
 
1042
  s1_dir = os.path.join(model_dir, "systemone")
1043
  ckpt_path = os.path.join(model_dir, "systemone_decision.pt")
1044
  ckpt = torch.load(ckpt_path, map_location="cpu", weights_only=True)
1045
+ arch_version = int(ckpt.get("arch_version", 2))
1046
  backbone_src = s1_dir if os.path.isdir(s1_dir) else ckpt.get(
1047
+ "backbone_id", "MoritzLaurer/ModernBERT-large-zeroshot-v2.0"
1048
  )
1049
 
1050
+ cfg_json_path = os.path.join(backbone_src, "config.json") if os.path.isdir(backbone_src) else ""
1051
+ if cfg_json_path and os.path.isfile(cfg_json_path):
1052
+ with open(cfg_json_path, "r", encoding="utf-8") as cf:
1053
+ raw_cfg = json.load(cf)
1054
+ if raw_cfg.get("model_type") == "modernbert" and raw_cfg.get("global_attn_every_n_layers") == 1:
1055
+ raw_cfg["global_attn_every_n_layers"] = 3
1056
+ raw_cfg["local_rope_theta"] = float(raw_cfg.get("global_rope_theta", 160000.0))
1057
+ raw_cfg.pop("sliding_window", None)
1058
+ from transformers import ModernBertConfig
1059
+ bb_cfg = ModernBertConfig(**raw_cfg)
1060
+ else:
1061
+ bb_cfg = AutoConfig.from_pretrained(backbone_src)
1062
+ else:
1063
+ bb_cfg = AutoConfig.from_pretrained(backbone_src)
1064
+ tok = AutoTokenizer.from_pretrained(backbone_src, config=bb_cfg)
1065
+ if arch_version >= 3:
1066
+ bb_cfg.reference_compile = False
1067
+ bb_cfg._attn_implementation = "sdpa"
1068
+ bb_cfg.local_attention = 16384
1069
+ bb_cfg.global_attn_every_n_layers = 1
1070
+ if hasattr(bb_cfg, "layer_types"):
1071
+ bb_cfg.layer_types = ["full_attention"] * int(bb_cfg.num_hidden_layers)
1072
+ nli_model = AutoModelForSequenceClassification.from_pretrained(backbone_src, config=bb_cfg)
1073
+ hidden_size = int(nli_model.config.hidden_size)
1074
+
1075
+ if arch_version >= 3:
1076
+ zs_dim = int(ckpt.get("zs_dim", int(getattr(nli_model.config, "num_labels", 2))))
1077
+ head: nn.Module = ParallelSpanDecisionHead(
1078
+ hidden_size=hidden_size,
1079
+ comp_dim=int(ckpt.get("comp_dim", 512)),
1080
+ zs_dim=zs_dim,
1081
+ dropout=0.0,
1082
+ )
1083
+ head.load_state_dict(ckpt["head_state_dict"], strict=False)
1084
+ max_len = int(ckpt.get("max_state_tokens", 3072))
1085
+ else:
1086
+ if ckpt.get("lora_r", 0) > 0:
1087
+ inject_encoder_lora(
1088
+ nli_model,
1089
+ start_layer=int(ckpt.get("start_layer", 6)),
1090
+ r=int(ckpt["lora_r"]),
1091
+ alpha=float(ckpt.get("lora_alpha", 32.0)),
1092
+ )
1093
+ nli_model.load_state_dict(ckpt["lora_state_dict"], strict=False)
1094
+ if "classifier_state_dict" in ckpt:
1095
+ nli_model.load_state_dict(ckpt["classifier_state_dict"], strict=False)
1096
+ head = CrossOptionDecisionHead(
1097
+ hidden_size=hidden_size,
1098
+ comp_dim=int(ckpt.get("comp_dim", 512)),
1099
+ dropout=0.0,
1100
  )
1101
+ head.load_state_dict(ckpt["head_state_dict"])
1102
+ max_len = min(512, int(ckpt.get("max_length", 512)))
 
1103
 
1104
+ eng = cls(
 
 
 
 
 
 
 
1105
  nli_backbone=nli_model,
1106
  tokenizer=tok,
1107
  head=head,
1108
  device=device,
1109
+ max_length=max_len,
1110
+ arch_version=arch_version,
1111
  )
1112
+ eng.schema_calib = dict(ckpt.get("schema_calib") or {})
1113
+ return eng
1114
 
1115
  @torch.no_grad()
1116
  def decide(self, state: Any, questions: dict[str, dict[str, Any]], max_length: int | None = None) -> dict[str, Any]:
1117
+ max_state_toks = max_length or self.max_length
 
1118
  state_str = compact_state_text(state)
1119
+ pc = encode_case_parallel(
1120
+ self.tokenizer,
1121
+ state,
1122
+ questions,
1123
+ max_state_tokens=max_state_toks,
1124
+ case_id=0,
1125
+ precomputed_state_str=state_str,
1126
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1127
  pad_id = self.tokenizer.pad_token_id or 0
1128
+ seq_f, zs_fn = forward_parallel_backbone(
1129
+ self.nli_backbone,
1130
+ [pc],
1131
+ pad_id=pad_id,
1132
+ device=self.device,
1133
+ amp_dtype=self.amp_dtype,
1134
+ )
1135
+ assert isinstance(self.head, ParallelSpanDecisionHead)
1136
+ raw_logits, flat_q_meta = self.head.forward_packed_cases(seq_f, [pc], zs_head_fn=zs_fn, apply_temp=False)
1137
 
1138
+ total_in_toks = len(pc["input_ids"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1139
  answers: dict[str, Any] = {}
1140
+
1141
+ for b_i, qm in enumerate(flat_q_meta):
1142
+ qid = qm["qid"]
1143
+ qsig = qm.get("qsig", "")
1144
+ keys = qm["option_keys"]
1145
  K = len(keys)
1146
+ qtype = qm["qtype"]
1147
+ qt_id = int(qm["qtype_id"])
1148
+ lv = raw_logits[b_i, :K].float().cpu()
1149
+ sc = self.schema_calib.get(qsig)
1150
+ if sc is not None:
1151
+ t_q = max(0.25, float(sc.get("temp", 1.0)))
1152
+ b_map = sc.get("bias") or {}
1153
+ b_vec = torch.tensor([float(b_map.get(k, 0.0)) for k in keys], dtype=torch.float32)
1154
+ lv = lv / t_q + b_vec
1155
+ else:
1156
+ t_g = float(torch.exp(self.head.log_temps[qt_id]).clamp(0.15, 5.0).item())
1157
+ lv = lv / t_g
1158
+ probs_raw = F.softmax(lv, dim=-1).tolist()
1159
+ smooth_eps = float(sc.get("smooth", self.head.prob_smooth[qt_id].item())) if sc is not None else float(self.head.prob_smooth[qt_id].item())
1160
+ if smooth_eps > 0.0:
1161
+ u = 1.0 / max(1, K)
1162
+ probs_raw = [(1.0 - smooth_eps) * p + smooth_eps * u for p in probs_raw]
1163
+ s_p = sum(probs_raw)
1164
+ probs = [p / s_p for p in probs_raw]
1165
  best_idx = max(range(K), key=lambda idx: probs[idx])
1166
+
1167
  if qtype == "noul":
1168
  p_true = float(probs[keys.index("true")]) if "true" in keys else float(probs[-1])
1169
  p_true_r = round(min(1.0, max(0.0, p_true)), 6)