Question Answering
Transformers
ONNX
Safetensors
nullspan
feature-extraction
system-one
typed-decisions
jevbench
structured-extraction
span-extraction
calibrated-estimation
electra
modernbert
custom_code
Eval Results
Instructions to use gnumanth/nullspan with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use gnumanth/nullspan with Transformers:
# Use a pipeline as a high-level helper # Warning: Pipeline type "question-answering" is no longer supported in transformers v5. # You must load the model directly (see below) or downgrade to v4.x with: # pip install "transformers<5.0.0" from transformers import pipeline pipe = pipeline("question-answering", model="gnumanth/nullspan", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("gnumanth/nullspan", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
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 +12 -12
- README.md +10 -10
- eval_results.json +571 -0
- onnx/model.onnx +2 -2
- predictions_typed_decisions_test.jsonl +0 -0
- systemone/added_tokens.json +0 -3
- systemone/config.json +40 -31
- systemone/model.safetensors +2 -2
- systemone/special_tokens_map.json +1 -15
- systemone/spm.model +0 -3
- systemone/tokenizer.json +0 -0
- systemone/tokenizer_config.json +903 -21
- systemone_decision.pt +2 -2
- systemone_decision.py +771 -482
.eval_results/typed-decisions.yaml
CHANGED
|
@@ -1,40 +1,40 @@
|
|
| 1 |
- dataset:
|
| 2 |
id: LocalLLaMA/typed-decisions
|
| 3 |
task_id: accuracy
|
| 4 |
-
value: 0.
|
| 5 |
-
date: "2026-10-
|
| 6 |
source:
|
| 7 |
url: https://huggingface.co/datasets/LocalLLaMA/typed-decisions
|
| 8 |
name: "Typed Decisions"
|
| 9 |
user: gnumanth
|
| 10 |
-
notes: "Pure non-LLM bidirectional
|
| 11 |
- dataset:
|
| 12 |
id: LocalLLaMA/typed-decisions
|
| 13 |
task_id: kl_from_gold
|
| 14 |
-
value: 0.
|
| 15 |
-
date: "2026-10-
|
| 16 |
source:
|
| 17 |
url: https://huggingface.co/datasets/LocalLLaMA/typed-decisions
|
| 18 |
name: "Typed Decisions"
|
| 19 |
user: gnumanth
|
| 20 |
-
notes: "Pure non-LLM
|
| 21 |
- dataset:
|
| 22 |
id: LocalLLaMA/typed-decisions
|
| 23 |
task_id: brier
|
| 24 |
-
value: 0.
|
| 25 |
-
date: "2026-10-
|
| 26 |
source:
|
| 27 |
url: https://huggingface.co/datasets/LocalLLaMA/typed-decisions
|
| 28 |
name: "Typed Decisions"
|
| 29 |
user: gnumanth
|
| 30 |
-
notes: "Pure non-LLM
|
| 31 |
- dataset:
|
| 32 |
id: LocalLLaMA/typed-decisions
|
| 33 |
task_id: ece
|
| 34 |
-
value: 0.
|
| 35 |
-
date: "2026-10-
|
| 36 |
source:
|
| 37 |
url: https://huggingface.co/datasets/LocalLLaMA/typed-decisions
|
| 38 |
name: "Typed Decisions"
|
| 39 |
user: gnumanth
|
| 40 |
-
notes: "Pure non-LLM
|
|
|
|
| 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 |
-
-
|
| 14 |
- onnx
|
| 15 |
datasets:
|
| 16 |
- gnumanth/nullspan-dataset
|
|
@@ -24,23 +24,23 @@ metrics:
|
|
| 24 |
pipeline_tag: question-answering
|
| 25 |
---
|
| 26 |
|
| 27 |
-
# gnumanth/nullspan (`v1.
|
| 28 |
|
| 29 |
-
**`nullspan` v1.
|
| 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` (`
|
| 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) | **`
|
| 39 |
-
| **[Benchmark Heaven / `jevbench`](https://github.com/fstandhartinger/jevbench)** | Official Public Suite (`231` items via `/v1/systemone`) | **`100.0%` Easy (`48/48`)** · `
|
| 40 |
-
| **[Stanford `rajpurkar/squad_v2`](https://huggingface.co/datasets/rajpurkar/squad_v2)** | Zero-overlap `validation` (`N = 500`: `250` HasAns + `250` NoAns) | **`87.
|
| 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
|
| 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
|
| 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` (`
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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 |
-
"
|
| 4 |
],
|
| 5 |
-
"
|
| 6 |
-
"
|
| 7 |
-
"
|
| 8 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
"hidden_size": 1024,
|
| 10 |
"id2label": {
|
| 11 |
"0": "entailment",
|
| 12 |
-
"1": "
|
| 13 |
-
"2": "contradiction"
|
| 14 |
},
|
|
|
|
| 15 |
"initializer_range": 0.02,
|
| 16 |
-
"intermediate_size":
|
| 17 |
"label2id": {
|
| 18 |
-
"contradiction": 2,
|
| 19 |
"entailment": 0,
|
| 20 |
-
"
|
| 21 |
},
|
| 22 |
-
"layer_norm_eps": 1e-
|
| 23 |
-
"
|
| 24 |
-
"
|
| 25 |
-
"
|
| 26 |
-
"
|
| 27 |
-
"
|
|
|
|
|
|
|
|
|
|
| 28 |
"num_attention_heads": 16,
|
| 29 |
-
"num_hidden_layers":
|
| 30 |
-
"pad_token_id":
|
| 31 |
-
"
|
| 32 |
-
"
|
| 33 |
-
"
|
| 34 |
-
"
|
| 35 |
-
|
| 36 |
-
|
| 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 |
-
"
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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":
|
| 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": "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
"lstrip": false,
|
| 6 |
"normalized": false,
|
| 7 |
"rstrip": false,
|
| 8 |
"single_word": false,
|
| 9 |
"special": true
|
| 10 |
},
|
| 11 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
"content": "[CLS]",
|
| 13 |
"lstrip": false,
|
| 14 |
"normalized": false,
|
|
@@ -16,7 +240,7 @@
|
|
| 16 |
"single_word": false,
|
| 17 |
"special": true
|
| 18 |
},
|
| 19 |
-
"
|
| 20 |
"content": "[SEP]",
|
| 21 |
"lstrip": false,
|
| 22 |
"normalized": false,
|
|
@@ -24,40 +248,698 @@
|
|
| 24 |
"single_word": false,
|
| 25 |
"special": true
|
| 26 |
},
|
| 27 |
-
"
|
| 28 |
-
"content": "[
|
| 29 |
"lstrip": false,
|
| 30 |
"normalized": false,
|
| 31 |
"rstrip": false,
|
| 32 |
"single_word": false,
|
| 33 |
"special": true
|
| 34 |
},
|
| 35 |
-
"
|
| 36 |
"content": "[MASK]",
|
| 37 |
-
"lstrip":
|
| 38 |
"normalized": false,
|
| 39 |
"rstrip": false,
|
| 40 |
"single_word": false,
|
| 41 |
"special": true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
}
|
| 43 |
},
|
| 44 |
-
"
|
| 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 |
-
"
|
| 52 |
-
|
|
|
|
|
|
|
|
|
|
| 53 |
"pad_token": "[PAD]",
|
| 54 |
"sep_token": "[SEP]",
|
| 55 |
-
"
|
| 56 |
-
"
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
1. Schema-Agnostic Symbolic
|
| 5 |
-
Deterministically surfaces
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 &
|
| 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 |
-
|
| 111 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 205 |
else:
|
| 206 |
s_val = str(obj)
|
| 207 |
lines.append(f"{prefix}: {s_val}")
|
| 208 |
-
if 1 <= len(s_val) <=
|
| 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 |
-
|
| 225 |
-
pct = 100.0 * diff /
|
| 226 |
eq = abs(diff) < 1e-6
|
| 227 |
derived.append(
|
| 228 |
-
f"_compare.{p1}_vs_{p2}: exact_equal={eq}, diff={diff:+.4g},
|
| 229 |
)
|
| 230 |
|
| 231 |
-
# Cross-subtree short string identifier comparisons
|
| 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 |
-
|
|
|
|
| 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[:
|
| 267 |
|
| 268 |
return body_txt
|
| 269 |
|
| 270 |
|
| 271 |
-
|
| 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 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 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
|
| 362 |
-
"""
|
| 363 |
|
| 364 |
-
def __init__(self, hidden_size: int = 1024, comp_dim: int = 512, dropout: float = 0.1) -> None:
|
| 365 |
super().__init__()
|
| 366 |
-
|
| 367 |
-
self.
|
| 368 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
| 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 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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,
|
| 400 |
-
|
|
|
|
| 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
|
| 405 |
self,
|
| 406 |
seq_out: torch.Tensor,
|
| 407 |
-
|
| 408 |
-
|
| 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 |
-
|
| 445 |
-
|
| 446 |
-
|
| 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 |
-
|
| 454 |
-
|
| 455 |
-
|
| 456 |
-
|
| 457 |
-
|
| 458 |
-
|
| 459 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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(
|
| 465 |
-
qw = qkv[:, 0].transpose(0, 1)
|
| 466 |
kw = qkv[:, 1].transpose(0, 1)
|
| 467 |
vw = qkv[:, 2].transpose(0, 1)
|
| 468 |
-
|
| 469 |
-
|
| 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(
|
| 475 |
x = x + self.wf_out(wf_ctx).unsqueeze(1)
|
| 476 |
|
| 477 |
-
x = self.blocks[1](x,
|
| 478 |
|
| 479 |
-
|
| 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 |
-
|
| 484 |
-
|
| 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)
|
| 495 |
-
logits =
|
| 496 |
|
| 497 |
if apply_temp:
|
| 498 |
-
temps = torch.exp(self.log_temps[
|
| 499 |
logits = logits / temps
|
| 500 |
-
return logits
|
| 501 |
|
| 502 |
|
| 503 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 525 |
-
|
| 526 |
-
|
| 527 |
-
|
| 528 |
-
|
| 529 |
-
|
| 530 |
-
|
| 531 |
-
|
| 532 |
-
|
| 533 |
-
|
| 534 |
-
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
|
| 538 |
-
|
| 539 |
-
|
| 540 |
-
|
| 541 |
-
|
| 542 |
-
|
| 543 |
-
|
| 544 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 545 |
else:
|
| 546 |
-
|
| 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 |
-
|
| 624 |
-
|
| 625 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 626 |
|
| 627 |
|
| 628 |
-
|
| 629 |
-
|
| 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 |
-
|
| 676 |
-
|
| 677 |
-
|
| 678 |
-
|
| 679 |
-
|
| 680 |
-
|
| 681 |
-
|
| 682 |
-
|
| 683 |
-
|
| 684 |
-
|
| 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:
|
| 696 |
device: str = "cpu",
|
| 697 |
-
max_length: int =
|
|
|
|
| 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
|
| 706 |
-
self.nli_backbone.
|
| 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/
|
| 740 |
)
|
| 741 |
|
| 742 |
-
|
| 743 |
-
|
| 744 |
-
|
| 745 |
-
|
| 746 |
-
|
| 747 |
-
|
| 748 |
-
|
| 749 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 750 |
)
|
| 751 |
-
|
| 752 |
-
|
| 753 |
-
nli_model.load_state_dict(ckpt["classifier_state_dict"], strict=False)
|
| 754 |
|
| 755 |
-
|
| 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=
|
|
|
|
| 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 |
-
|
| 773 |
-
qids = list(questions.keys())
|
| 774 |
state_str = compact_state_text(state)
|
| 775 |
-
|
| 776 |
-
|
| 777 |
-
|
| 778 |
-
|
| 779 |
-
|
| 780 |
-
|
| 781 |
-
|
| 782 |
-
|
| 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 |
-
|
| 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 |
-
|
| 870 |
-
|
| 871 |
-
|
|
|
|
|
|
|
| 872 |
K = len(keys)
|
| 873 |
-
|
| 874 |
-
|
| 875 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 876 |
best_idx = max(range(K), key=lambda idx: probs[idx])
|
| 877 |
-
|
| 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)
|