Upload folder using huggingface_hub
Browse files- .gitattributes +1 -0
- README.md +242 -0
- chat_template.jinja +154 -0
- config.json +97 -0
- decider/__init__.py +0 -0
- decider/engine.py +202 -0
- decider/fp8.py +54 -0
- decider/infer.py +262 -0
- decider/metrics.py +37 -0
- decider/model.py +47 -0
- decider/prompt.py +157 -0
- decider/schema_engine.py +143 -0
- decider/serve.py +289 -0
- decider/systemone.py +139 -0
- decider_config.json +13 -0
- eval_results.json +1298 -0
- generation_config.json +6 -0
- model-00001-of-00015.safetensors +3 -0
- model-00002-of-00015.safetensors +3 -0
- model-00003-of-00015.safetensors +3 -0
- model-00004-of-00015.safetensors +3 -0
- model-00005-of-00015.safetensors +3 -0
- model-00006-of-00015.safetensors +3 -0
- model-00007-of-00015.safetensors +3 -0
- model-00008-of-00015.safetensors +3 -0
- model-00009-of-00015.safetensors +3 -0
- model-00010-of-00015.safetensors +3 -0
- model-00011-of-00015.safetensors +3 -0
- model-00012-of-00015.safetensors +3 -0
- model-00013-of-00015.safetensors +3 -0
- model-00014-of-00015.safetensors +3 -0
- model-00015-of-00015.safetensors +3 -0
- model.safetensors.index.json +0 -0
- tokenizer.json +3 -0
- tokenizer_config.json +32 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
tokenizer.json filter=lfs diff=lfs merge=lfs -text
|
README.md
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
base_model: Qwen/Qwen3.5-35B-A3B-Base
|
| 4 |
+
language: [en]
|
| 5 |
+
pipeline_tag: text-classification
|
| 6 |
+
tags: [decision-model, calibrated, structured-output, multi-task, system-one, one-pass, mixture-of-experts]
|
| 7 |
+
---
|
| 8 |
+
|
| 9 |
+
# decider-35b-a3b: typed decisions with calibrated probabilities in one forward pass, 35B mixture of experts
|
| 10 |
+
|
| 11 |
+
A language model that does not generate text. It reads a state and one or more typed questions, each with an explicit option
|
| 12 |
+
list, and returns a probability distribution over the options for every question from one forward pass. There is no decoding,
|
| 13 |
+
no parsing and no output outside the options you defined. It is called from software, not chatted with. It is an open
|
| 14 |
+
reproduction of the "System One" model class (TypeSafe AI's Jev).
|
| 15 |
+
|
| 16 |
+
Base model: [Qwen/Qwen3.5-35B-A3B-Base](https://huggingface.co/Qwen/Qwen3.5-35B-A3B-Base): 34.7B parameters, of which 3B
|
| 17 |
+
are active per token (256 routed experts, 8 active, plus a shared expert; 40 layers, 10 with full attention and 30 with
|
| 18 |
+
gated delta-net linear attention). The supervised recipe of [decider-2b](https://huggingface.co/Mapika/decider-2b) (one epoch of
|
| 19 |
+
cross-entropy on the slot readout over the public decision mixture) was applied to it with the routed experts frozen and the
|
| 20 |
+
Muon optimizer on the block matrices. **This repository holds v1**, the bf16 weights (65 GB). An NVFP4 checkpoint of the
|
| 21 |
+
same weights for vLLM and TensorRT-LLM is at
|
| 22 |
+
[Mapika/decider-35b-a3b-nvfp4](https://huggingface.co/Mapika/decider-35b-a3b-nvfp4). Code, data registry, training
|
| 23 |
+
scripts and the recipe are at https://github.com/Mapika/decider; `decider/` in this repository is the inference subset of that
|
| 24 |
+
package.
|
| 25 |
+
|
| 26 |
+
Against decider-2b v10 on the same rows: accuracy is higher on 93 of the 95 regression tasks (in-task 0.855 against 0.805,
|
| 27 |
+
held-out 0.810 against 0.755), +6.7 points on the 847 validation rows, +5.0 on OpenJev, +6.9 on Mind2Web, +5.9 on the
|
| 28 |
+
TypeSafe workflow rows, JevBench hard tier 0.676 against 0.459, Bespoke's public suite 0.774 against 0.704 macro. Negative
|
| 29 |
+
log-likelihood drops by 0.12 to 0.24 nats on every fixture. The model was not RL-trained: on live browser tasks its greedy
|
| 30 |
+
play beats v10 (97.2% against 90.9%) and its sampled play is behind (86.4% against 93.2%). Details under Evaluation.
|
| 31 |
+
|
| 32 |
+
## Usage
|
| 33 |
+
|
| 34 |
+
```python
|
| 35 |
+
from decider.infer import Decider # decider/ is included in this repo
|
| 36 |
+
d = Decider("Mapika/decider-35b-a3b", use_graphs=False)
|
| 37 |
+
d.decide("My card was charged twice for the same purchase.",
|
| 38 |
+
[{"question": "Which department should handle this?", "options": ["billing", "technical support", "sales"]},
|
| 39 |
+
{"question": "Does this need a refund action?", "options": ["no", "yes"]}])
|
| 40 |
+
# [{'choice': 'billing', 'confidence': 0.99, 'probs': {...}}, {'choice': 'yes', 'confidence': 0.98, 'probs': {...}}]
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
The API is the same as decider-2b's: `decide_batch` scores many states with many questions in one call, `abstain_below=t`
|
| 44 |
+
returns `None` under a confidence threshold, a question can have 2 to 255 options, and `system_one` / `decider.serve` accept
|
| 45 |
+
TypeSafe's `POST /v1/systemone` request shape (the official `typesafe-sdk` works with `TYPESAFE_BASE_URL` pointing at the
|
| 46 |
+
server). Every question and every Score level is scored in its own row. The state may be a string, object or array of up to
|
| 47 |
+
32k tokens. See the decider-2b card for the full description of the request shape, field types and the schema cache.
|
| 48 |
+
|
| 49 |
+
Requirements: one GPU with at least 80 GB of memory (the weights take 65 GB in bf16), `torch>=2.14`, `transformers>=5.17`
|
| 50 |
+
and `flash-linear-attention`. `config.json` sets `experts_implementation: grouped_mm`, which runs the 256 experts of a layer
|
| 51 |
+
as one grouped matrix multiplication; the eager expert loop that `transformers` falls back to on older versions is about
|
| 52 |
+
13x slower. `use_graphs=False` is required: the CUDA-graph engine and the FP8 path of the helper package were built for the
|
| 53 |
+
dense models and are untested with this architecture. Loading takes about 25 seconds from local disk.
|
| 54 |
+
|
| 55 |
+
Without the helper package, the same computation in plain `transformers`:
|
| 56 |
+
|
| 57 |
+
```python
|
| 58 |
+
import torch
|
| 59 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM
|
| 60 |
+
tok = AutoTokenizer.from_pretrained(REPO); m = AutoModelForCausalLM.from_pretrained(REPO, dtype=torch.bfloat16).cuda().eval()
|
| 61 |
+
prompt = ("Context:\nMy card was charged twice for the same purchase.\n\n"
|
| 62 |
+
"Question: Which department should handle this?\nOptions:\n(A) billing\n(B) technical support\n(C) sales\nAnswer: (")
|
| 63 |
+
ids = tok(prompt, return_tensors="pt").to("cuda")
|
| 64 |
+
with torch.no_grad():
|
| 65 |
+
logits = m(**ids).logits[0, -1]
|
| 66 |
+
letters = [tok.encode(L, add_special_tokens=False)[0] for L in "ABC"]
|
| 67 |
+
probs = torch.softmax(logits[letters].float() / 1.08, -1) # 1.08 is the stored temperature
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
## How it works
|
| 71 |
+
|
| 72 |
+
The prompt is `Context: ...` followed by, for each question, the question text, the lettered options `(A) ... (B) ...` and an
|
| 73 |
+
answer slot `Answer k: (`. The hidden state at each slot is projected with the option-letter rows of the LM head and softmaxed
|
| 74 |
+
over the valid letters, divided by the temperature in `decider_config.json`. Letters are never generated, so all slots are read
|
| 75 |
+
from one pass. Large label sets were sub-sampled to at most 10 options per training example (gold always kept, order shuffled),
|
| 76 |
+
so the model conditions on the supplied candidates rather than on a fixed head.
|
| 77 |
+
|
| 78 |
+
## Training
|
| 79 |
+
|
| 80 |
+
One epoch of the public supervised mixture of the GitHub repository (`scripts/train.sh full`: about 95 public decision
|
| 81 |
+
datasets, agent trajectories, Mind2Web element choice, game states, teacher-written custom questions, Jev's input shapes,
|
| 82 |
+
two prompt layouts, isolated Score levels, 10% abstention rows). 1,543,567 items, 463M tokens, pre-tokenized once and read in
|
| 83 |
+
the same order by every rank.
|
| 84 |
+
|
| 85 |
+
| | |
|
| 86 |
+
|---|---|
|
| 87 |
+
| trainable parameters | 2.45B: attention, delta-net, shared experts, routers, norms, embeddings, LM head. The 256 routed experts of every layer (32.2B parameters) stay at the base weights. |
|
| 88 |
+
| optimizer | Muon on the 250 block matrices (1.41B parameters): momentum 0.95, Nesterov, 5 Newton-Schulz steps, update scaled by 0.2 sqrt(max(rows, cols)) so the AdamW learning-rate schedule applies. AdamW (betas 0.9 / 0.95) on embeddings, head, norms, routers, shared-expert gates, convolutions and 1-D parameters (1.04B). FP32 master weights, bf16 forward. |
|
| 89 |
+
| schedule | peak learning rate 1e-5, 150 warm-up steps, cosine to zero, 16,287 steps of 32,768 tokens, gradient clip 1.0, no weight decay |
|
| 90 |
+
| hardware | 4 NVIDIA B300, data parallel, 8,192-token micro-batches per GPU, gradient checkpointing, grouped-GEMM experts; 394 minutes at 22,000 to 25,000 tokens per second, 100 GB peak per GPU |
|
| 91 |
+
| training cross-entropy | 0.93 over the first 200 steps, 0.50 at 25%, 0.46 at 50%, 0.43 over the last 300 steps |
|
| 92 |
+
|
| 93 |
+
Muon was chosen over AdamW on a same-data comparison stopped at 11% of the epoch: at every logged step both optimizers had
|
| 94 |
+
seen identical examples, and Muon's cross-entropy was lower in 75 of 94 logged windows, 0.537 against 0.605 at step 1,880
|
| 95 |
+
(mean over steps 1,500 to 1,880: 0.557 against 0.614). No AdamW model was trained to the end, so there is no AdamW row in the
|
| 96 |
+
evaluation tables. The temperature 1.08 was fitted on the in-task half of the regression set. No reinforcement-learning stage
|
| 97 |
+
was run on this model; the RL recipe of decider-2b v10 is documented in `docs/RL.md` of the GitHub repository.
|
| 98 |
+
|
| 99 |
+
## Evaluation
|
| 100 |
+
|
| 101 |
+
**Public regression set**, rebuilt on this machine (95 tasks: 67 in-task, 28 held-out; large label sets sub-sampled to 10
|
| 102 |
+
options; one temperature per model fitted on in-task data). The decider-2b rows are the same set, same rows. ECE is the
|
| 103 |
+
expected calibration error with 15 bins.
|
| 104 |
+
|
| 105 |
+
| model | in-task acc / NLL / ECE (67 tasks) | held-out acc / NLL / ECE (28 tasks) |
|
| 106 |
+
|---|---|---|
|
| 107 |
+
| Qwen3.5-35B-A3B-Base, zero-shot, T=1.27 | 0.732 / 0.693 / 0.096 | 0.749 / 0.650 / 0.082 |
|
| 108 |
+
| after 25% of the epoch, T=0.96 | 0.839 / 0.399 / 0.032 | 0.803 / 0.522 / 0.073 |
|
| 109 |
+
| after 50%, T=1.08 | 0.850 / 0.370 / 0.028 | 0.813 / 0.488 / 0.064 |
|
| 110 |
+
| **decider-35b-a3b v1 (this repository), T=1.08** | **0.855 / 0.357 / 0.026** | **0.810 / 0.497 / 0.069** |
|
| 111 |
+
| decider-2b v10, T=1.30 | 0.805 / 0.474 / 0.037 | 0.755 / 0.622 / 0.084 |
|
| 112 |
+
| decider-2b v8, T=1.30 | 0.806 / 0.473 / 0.038 | 0.757 / 0.622 / 0.083 |
|
| 113 |
+
|
| 114 |
+
Half the epoch reaches 99% of the final in-task accuracy; held-out accuracy is flat from 50% to 100%. Accuracy is above v10 on
|
| 115 |
+
93 of the 95 tasks and 0.6 points below on two (counterfactual detection, offensive-tweet detection). The largest gains are
|
| 116 |
+
on knowledge and reasoning tasks: MedQA +31 points, MedMCQA +24, TruthfulQA +22, Winogrande +20, MMLU +19, StrategyQA +19.
|
| 117 |
+
|
| 118 |
+
Per-task accuracy / ECE on the held-out datasets, v10 against this model:
|
| 119 |
+
|
| 120 |
+
| task | decider-2b v10 | decider-35b-a3b |
|
| 121 |
+
|---|---|---|
|
| 122 |
+
| abstain_probe | 0.606 / 0.134 | 0.622 / 0.085 |
|
| 123 |
+
| ade | 0.817 / 0.038 | 0.837 / 0.035 |
|
| 124 |
+
| arena_pref | 0.483 / 0.189 | 0.521 / 0.121 |
|
| 125 |
+
| bbc_news | 0.927 / 0.013 | 0.944 / 0.027 |
|
| 126 |
+
| cb | 0.857 / 0.093 | 0.893 / 0.084 |
|
| 127 |
+
| cr_reviews | 0.903 / 0.031 | 0.914 / 0.032 |
|
| 128 |
+
| dbpedia_l2 | 0.950 / 0.018 | 0.961 / 0.010 |
|
| 129 |
+
| dbpedia_l3 | 0.987 / 0.005 | 0.992 / 0.004 |
|
| 130 |
+
| dolly_category | 0.299 / 0.203 | 0.354 / 0.098 |
|
| 131 |
+
| fin_phrasebank | 0.694 / 0.042 | 0.759 / 0.110 |
|
| 132 |
+
| fin_sentiment | 0.793 / 0.058 | 0.839 / 0.136 |
|
| 133 |
+
| hermes_tools | 0.723 / 0.208 | 0.799 / 0.085 |
|
| 134 |
+
| hwu64 | 0.961 / 0.030 | 0.975 / 0.022 |
|
| 135 |
+
| massive_scenario | 0.756 / 0.041 | 0.799 / 0.028 |
|
| 136 |
+
| offtopic_probe | 0.841 / 0.027 | 0.870 / 0.038 |
|
| 137 |
+
| paws | 0.724 / 0.145 | 0.729 / 0.168 |
|
| 138 |
+
| pubmedqa | 0.756 / 0.085 | 0.820 / 0.078 |
|
| 139 |
+
| quality | 0.494 / 0.233 | 0.632 / 0.096 |
|
| 140 |
+
| quality_full | 0.508 / 0.198 | 0.565 / 0.112 |
|
| 141 |
+
| reward_bench | 0.819 / 0.045 | 0.919 / 0.024 |
|
| 142 |
+
| sciq | 0.982 / 0.024 | 0.993 / 0.011 |
|
| 143 |
+
| social_iqa | 0.708 / 0.077 | 0.823 / 0.025 |
|
| 144 |
+
| strategyqa | 0.552 / 0.138 | 0.739 / 0.036 |
|
| 145 |
+
| student_questions | 0.925 / 0.045 | 0.954 / 0.090 |
|
| 146 |
+
| trec | 0.784 / 0.066 | 0.832 / 0.160 |
|
| 147 |
+
| truthfulqa | 0.537 / 0.090 | 0.754 / 0.068 |
|
| 148 |
+
| tweet_irony | 0.795 / 0.052 | 0.861 / 0.129 |
|
| 149 |
+
| xstory_cloze | 0.962 / 0.017 | 0.995 / 0.016 |
|
| 150 |
+
|
| 151 |
+
**On the same rows as decider-2b.** Every row below is scored by both models on identical inputs and seeds. Intervals are
|
| 152 |
+
95% paired bootstrap intervals.
|
| 153 |
+
|
| 154 |
+
| | decider-2b v10 | decider-35b-a3b | difference |
|
| 155 |
+
|---|---|---|---|
|
| 156 |
+
| 847 in-task validation rows, accuracy / NLL | 83.2% / 0.444 | 90.0% / 0.329 | +6.7 (+4.5 to +9.0) |
|
| 157 |
+
| OpenJev, 5,252 rows, accuracy / NLL | 63.3% / 0.916 | 68.3% / 0.752 | +5.0 (+3.8 to +6.2) |
|
| 158 |
+
| Mind2Web element and action choice, 1,770 rows | 82.7% / 0.543 | 89.6% / 0.316 | +6.9 (+5.1 to +8.7) |
|
| 159 |
+
| TypeSafe workflow decisions, 102 rows, accuracy / NLL | 80.4% / 0.585 | 86.3% / 0.342 | +5.9 (−2.0 to +13.7) |
|
| 160 |
+
| Bespoke's public suite, 13 subsets, macro / micro | 0.704 / 0.711 | 0.774 / 0.787 | |
|
| 161 |
+
| JevBench public items, easy / standard / hard accuracy | 1.000 / 0.847 / 0.459 | 1.000 / 0.972 / 0.676 | |
|
| 162 |
+
| live MiniWoB++ click tasks, 22 tasks x 8 seeds, greedy play | 90.9% | 97.2% | +6.2 (+1.7 to +10.8) |
|
| 163 |
+
| the same, 6 tasks v10 never used for reward, greedy | 91.7% | 97.9% | +6.2 (0.0 to +14.6) |
|
| 164 |
+
| live MiniWoB++ click tasks, sampled play | 93.2% | 86.4% | −6.8 (−12.5 to −1.7) |
|
| 165 |
+
| the same, 6 held-out tasks, sampled | 91.7% | 79.2% | −12.5 (−25.0 to −2.1) |
|
| 166 |
+
| zero-shot games, win rate, greedy play (234 boards) | 26.5% | 37.2% | +10.7 (+5.6 to +15.8) |
|
| 167 |
+
| zero-shot games, sampled play | 23.7% | 24.1% | +0.4 (−2.4 to +3.3) |
|
| 168 |
+
|
| 169 |
+
The browser rows show what the RL stage of v10 does and this model lacks: v10's sampled play matches its greedy play because
|
| 170 |
+
RL sharpened the served distribution on those tasks; this model's argmax is right more often, but its distribution still puts
|
| 171 |
+
mass on wrong elements (its sampled play is +3.4 points against v8, which had no RL either). Among the games, the largest
|
| 172 |
+
greedy gains are on the slippery grid (+17 points) and tic-tac-toe (+14); minesweeper stays near zero for every model.
|
| 173 |
+
|
| 174 |
+
**JevBench public items** (231 items of [Benchmark Heaven](https://benchmarkheaven.com/jev-models); argmax over the exact
|
| 175 |
+
label set with the request the harness's TypeSafe adapter builds). Jev 1.13.0 is at 1.000 / 0.986 / 0.730, djev at 1.000 /
|
| 176 |
+
0.986 / 0.676, SemIf 4B at 1.000 / 0.986 / 0.613 on the same items, from their published per-item outcomes. This model's
|
| 177 |
+
hard-tier misses are on temporal-numeric items (0.33), long policies (0.63) and judge-hard items (0.65); adversarial, trap
|
| 178 |
+
and hard routing items are all correct. Top-label ECE is 0.001 / 0.059 / 0.151 by tier: the model is overconfident on the
|
| 179 |
+
hard tier.
|
| 180 |
+
|
| 181 |
+
**Bespoke's public suite** (13 human-labelled subsets, 3,880 records in Jev's wire format, answered through `system_one` as
|
| 182 |
+
shipped). Nimble-9B and Jev 1.13.0 numbers are copied from Bespoke's report.
|
| 183 |
+
|
| 184 |
+
| subset (type) | decider-2b v10 | decider-35b-a3b | Nimble-9B | Jev 1.13.0 |
|
| 185 |
+
|---|---|---|---|---|
|
| 186 |
+
| vitaminc-dev (choice) | 0.639 | 0.795 | 0.766 | 0.801 |
|
| 187 |
+
| massive-en-US (choice; trained) | 0.823 | 0.880 | 0.869 | 0.874 |
|
| 188 |
+
| massive-de-DE (choice, German) | 0.797 | 0.869 | 0.834 | 0.869 |
|
| 189 |
+
| boolq (noul; trained) | 0.803 | 0.887 | 0.860 | 0.897 |
|
| 190 |
+
| squad2 (noul) | 0.776 | 0.749 | 0.806 | 0.829 |
|
| 191 |
+
| paws (noul; trained) | 0.720 | 0.768 | 0.828 | 0.892 |
|
| 192 |
+
| multinli (choice; trained) | 0.856 | 0.910 | 0.853 | 0.829 |
|
| 193 |
+
| civil_comments (noul; trained) | 0.840 | 0.907 | 0.703 | 0.810 |
|
| 194 |
+
| aegis2 (noul) | 0.728 | 0.808 | 0.812 | 0.804 |
|
| 195 |
+
| helpsteer2 (score; trained) | 0.426 | 0.478 | 0.390 | 0.341 |
|
| 196 |
+
| summeval-relevance (score) | 0.354 | 0.483 | 0.492 | 0.350 |
|
| 197 |
+
| summeval-consistency (score) | 0.660 | 0.757 | 0.757 | 0.812 |
|
| 198 |
+
| pubmedqa (choice; trained) | 0.724 | 0.768 | 0.756 | 0.772 |
|
| 199 |
+
| **macro / micro** | 0.704 / 0.711 | **0.774 / 0.787** | 0.748 / 0.759 | 0.760 / 0.773 |
|
| 200 |
+
|
| 201 |
+
On the six subsets whose training split is not in the mixture the macro accuracy is 0.744. The model is behind Jev where a
|
| 202 |
+
claim has to be checked against evidence that nearly matches it (PAWS, SummEval consistency) and on SQuAD2 answerability.
|
| 203 |
+
|
| 204 |
+
**Behaviour probes** (teacher-labelled, same probes as the 2B releases): generic-versus-specific bucket choice 1.00 / 1.00,
|
| 205 |
+
catch-all when nothing fits 0.95; command-risk classification 0.933 with no destructive command called safe; browser-agent
|
| 206 |
+
element and action choice 0.938 / 0.938. Scoring a Score level alone against scoring it with its neighbours changes accuracy
|
| 207 |
+
by at most 2 points on five rating datasets, and the per-level fits sum to between 0.92 and 1.07.
|
| 208 |
+
|
| 209 |
+
## Speed
|
| 210 |
+
|
| 211 |
+
One NVIDIA B300, bf16, eager PyTorch (`use_graphs=False`), grouped-GEMM experts. A 92-token support ticket with three typed
|
| 212 |
+
questions, and a 5-token chat message with one question:
|
| 213 |
+
|
| 214 |
+
| setting | latency | throughput |
|
| 215 |
+
|---|---|---|
|
| 216 |
+
| single ticket request, 3 questions | 47 ms | |
|
| 217 |
+
| batch of 64 tickets, 3 questions each | 368 ms | 174 states/s, 522 decisions/s |
|
| 218 |
+
| batch of 64 short messages, 1 question | 111 ms | 575 decisions/s |
|
| 219 |
+
|
| 220 |
+
decider-2b serves the same tickets at 4 ms with CUDA graphs and about 1,400 to 2,100 decisions/s; this model is for
|
| 221 |
+
workloads where the accuracy gain is worth 3 to 4 times the cost per decision, and for the NVFP4 build on Blackwell (see the
|
| 222 |
+
`-nvfp4` repository).
|
| 223 |
+
|
| 224 |
+
## Limitations
|
| 225 |
+
|
| 226 |
+
* No reinforcement-learning stage: stated beliefs about action outcomes were not trained against exact laws, and the served
|
| 227 |
+
distribution on live browser tasks is less sharp than decider-2b v10's (sampled play 86% against 93%).
|
| 228 |
+
* 65 GB of bf16 weights; one 80 GB GPU is the minimum, and the CUDA-graph and FP8 paths of the helper are untested here.
|
| 229 |
+
* Overconfident on the hardest external items (JevBench hard-tier ECE 0.15) and on some held-out classification sets
|
| 230 |
+
(TREC 0.16, financial sentiment 0.14) although the aggregate ECE is 0.03 / 0.07.
|
| 231 |
+
* English only. Calibration is measured on public datasets and teacher-labelled probes, not on your traffic. Check it on your
|
| 232 |
+
own labels before using confidence for routing.
|
| 233 |
+
* The routed experts are the base model's: the fine-tuning changed 2.45B of the 34.7B parameters.
|
| 234 |
+
* Everything else in the decider-2b card's limitations (packed questions see each other, long JSON arrays by position, full
|
| 235 |
+
label sets against sampled options, abstention wording) applies; those shapes were not re-measured at this size.
|
| 236 |
+
|
| 237 |
+
## Reproduction
|
| 238 |
+
|
| 239 |
+
Code, data registry, training and evaluation scripts and the per-version history: https://github.com/Mapika/decider
|
| 240 |
+
(`docs/HISTORY.md`, section "decider-35b-a3b"). The training code for the frozen-expert Muon run is in the repository's
|
| 241 |
+
history document; the merged checkpoint is this repository. Staged with `scripts/stage_release.py` and uploaded with
|
| 242 |
+
`scripts/upload_hf.py`.
|
chat_template.jinja
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{%- set image_count = namespace(value=0) %}
|
| 2 |
+
{%- set video_count = namespace(value=0) %}
|
| 3 |
+
{%- macro render_content(content, do_vision_count, is_system_content=false) %}
|
| 4 |
+
{%- if content is string %}
|
| 5 |
+
{{- content }}
|
| 6 |
+
{%- elif content is iterable and content is not mapping %}
|
| 7 |
+
{%- for item in content %}
|
| 8 |
+
{%- if 'image' in item or 'image_url' in item or item.type == 'image' %}
|
| 9 |
+
{%- if is_system_content %}
|
| 10 |
+
{{- raise_exception('System message cannot contain images.') }}
|
| 11 |
+
{%- endif %}
|
| 12 |
+
{%- if do_vision_count %}
|
| 13 |
+
{%- set image_count.value = image_count.value + 1 %}
|
| 14 |
+
{%- endif %}
|
| 15 |
+
{%- if add_vision_id %}
|
| 16 |
+
{{- 'Picture ' ~ image_count.value ~ ': ' }}
|
| 17 |
+
{%- endif %}
|
| 18 |
+
{{- '<|vision_start|><|image_pad|><|vision_end|>' }}
|
| 19 |
+
{%- elif 'video' in item or item.type == 'video' %}
|
| 20 |
+
{%- if is_system_content %}
|
| 21 |
+
{{- raise_exception('System message cannot contain videos.') }}
|
| 22 |
+
{%- endif %}
|
| 23 |
+
{%- if do_vision_count %}
|
| 24 |
+
{%- set video_count.value = video_count.value + 1 %}
|
| 25 |
+
{%- endif %}
|
| 26 |
+
{%- if add_vision_id %}
|
| 27 |
+
{{- 'Video ' ~ video_count.value ~ ': ' }}
|
| 28 |
+
{%- endif %}
|
| 29 |
+
{{- '<|vision_start|><|video_pad|><|vision_end|>' }}
|
| 30 |
+
{%- elif 'text' in item %}
|
| 31 |
+
{{- item.text }}
|
| 32 |
+
{%- else %}
|
| 33 |
+
{{- raise_exception('Unexpected item type in content.') }}
|
| 34 |
+
{%- endif %}
|
| 35 |
+
{%- endfor %}
|
| 36 |
+
{%- elif content is none or content is undefined %}
|
| 37 |
+
{{- '' }}
|
| 38 |
+
{%- else %}
|
| 39 |
+
{{- raise_exception('Unexpected content type.') }}
|
| 40 |
+
{%- endif %}
|
| 41 |
+
{%- endmacro %}
|
| 42 |
+
{%- if not messages %}
|
| 43 |
+
{{- raise_exception('No messages provided.') }}
|
| 44 |
+
{%- endif %}
|
| 45 |
+
{%- if tools and tools is iterable and tools is not mapping %}
|
| 46 |
+
{{- '<|im_start|>system\n' }}
|
| 47 |
+
{{- "# Tools\n\nYou have access to the following functions:\n\n<tools>" }}
|
| 48 |
+
{%- for tool in tools %}
|
| 49 |
+
{{- "\n" }}
|
| 50 |
+
{{- tool | tojson }}
|
| 51 |
+
{%- endfor %}
|
| 52 |
+
{{- "\n</tools>" }}
|
| 53 |
+
{{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }}
|
| 54 |
+
{%- if messages[0].role == 'system' %}
|
| 55 |
+
{%- set content = render_content(messages[0].content, false, true)|trim %}
|
| 56 |
+
{%- if content %}
|
| 57 |
+
{{- '\n\n' + content }}
|
| 58 |
+
{%- endif %}
|
| 59 |
+
{%- endif %}
|
| 60 |
+
{{- '<|im_end|>\n' }}
|
| 61 |
+
{%- else %}
|
| 62 |
+
{%- if messages[0].role == 'system' %}
|
| 63 |
+
{%- set content = render_content(messages[0].content, false, true)|trim %}
|
| 64 |
+
{{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}
|
| 65 |
+
{%- endif %}
|
| 66 |
+
{%- endif %}
|
| 67 |
+
{%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
|
| 68 |
+
{%- for message in messages[::-1] %}
|
| 69 |
+
{%- set index = (messages|length - 1) - loop.index0 %}
|
| 70 |
+
{%- if ns.multi_step_tool and message.role == "user" %}
|
| 71 |
+
{%- set content = render_content(message.content, false)|trim %}
|
| 72 |
+
{%- if not(content.startswith('<tool_response>') and content.endswith('</tool_response>')) %}
|
| 73 |
+
{%- set ns.multi_step_tool = false %}
|
| 74 |
+
{%- set ns.last_query_index = index %}
|
| 75 |
+
{%- endif %}
|
| 76 |
+
{%- endif %}
|
| 77 |
+
{%- endfor %}
|
| 78 |
+
{%- if ns.multi_step_tool %}
|
| 79 |
+
{{- raise_exception('No user query found in messages.') }}
|
| 80 |
+
{%- endif %}
|
| 81 |
+
{%- for message in messages %}
|
| 82 |
+
{%- set content = render_content(message.content, true)|trim %}
|
| 83 |
+
{%- if message.role == "system" %}
|
| 84 |
+
{%- if not loop.first %}
|
| 85 |
+
{{- raise_exception('System message must be at the beginning.') }}
|
| 86 |
+
{%- endif %}
|
| 87 |
+
{%- elif message.role == "user" %}
|
| 88 |
+
{{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
|
| 89 |
+
{%- elif message.role == "assistant" %}
|
| 90 |
+
{%- set reasoning_content = '' %}
|
| 91 |
+
{%- if message.reasoning_content is string %}
|
| 92 |
+
{%- set reasoning_content = message.reasoning_content %}
|
| 93 |
+
{%- else %}
|
| 94 |
+
{%- if '</think>' in content %}
|
| 95 |
+
{%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
|
| 96 |
+
{%- set content = content.split('</think>')[-1].lstrip('\n') %}
|
| 97 |
+
{%- endif %}
|
| 98 |
+
{%- endif %}
|
| 99 |
+
{%- set reasoning_content = reasoning_content|trim %}
|
| 100 |
+
{%- if loop.index0 > ns.last_query_index %}
|
| 101 |
+
{{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content + '\n</think>\n\n' + content }}
|
| 102 |
+
{%- else %}
|
| 103 |
+
{{- '<|im_start|>' + message.role + '\n' + content }}
|
| 104 |
+
{%- endif %}
|
| 105 |
+
{%- if message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}
|
| 106 |
+
{%- for tool_call in message.tool_calls %}
|
| 107 |
+
{%- if tool_call.function is defined %}
|
| 108 |
+
{%- set tool_call = tool_call.function %}
|
| 109 |
+
{%- endif %}
|
| 110 |
+
{%- if loop.first %}
|
| 111 |
+
{%- if content|trim %}
|
| 112 |
+
{{- '\n\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
|
| 113 |
+
{%- else %}
|
| 114 |
+
{{- '<tool_call>\n<function=' + tool_call.name + '>\n' }}
|
| 115 |
+
{%- endif %}
|
| 116 |
+
{%- else %}
|
| 117 |
+
{{- '\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
|
| 118 |
+
{%- endif %}
|
| 119 |
+
{%- if tool_call.arguments is defined %}
|
| 120 |
+
{%- for args_name, args_value in tool_call.arguments|items %}
|
| 121 |
+
{{- '<parameter=' + args_name + '>\n' }}
|
| 122 |
+
{%- set args_value = args_value | tojson | safe if args_value is mapping or (args_value is sequence and args_value is not string) else args_value | string %}
|
| 123 |
+
{{- args_value }}
|
| 124 |
+
{{- '\n</parameter>\n' }}
|
| 125 |
+
{%- endfor %}
|
| 126 |
+
{%- endif %}
|
| 127 |
+
{{- '</function>\n</tool_call>' }}
|
| 128 |
+
{%- endfor %}
|
| 129 |
+
{%- endif %}
|
| 130 |
+
{{- '<|im_end|>\n' }}
|
| 131 |
+
{%- elif message.role == "tool" %}
|
| 132 |
+
{%- if loop.previtem and loop.previtem.role != "tool" %}
|
| 133 |
+
{{- '<|im_start|>user' }}
|
| 134 |
+
{%- endif %}
|
| 135 |
+
{{- '\n<tool_response>\n' }}
|
| 136 |
+
{{- content }}
|
| 137 |
+
{{- '\n</tool_response>' }}
|
| 138 |
+
{%- if not loop.last and loop.nextitem.role != "tool" %}
|
| 139 |
+
{{- '<|im_end|>\n' }}
|
| 140 |
+
{%- elif loop.last %}
|
| 141 |
+
{{- '<|im_end|>\n' }}
|
| 142 |
+
{%- endif %}
|
| 143 |
+
{%- else %}
|
| 144 |
+
{{- raise_exception('Unexpected message role.') }}
|
| 145 |
+
{%- endif %}
|
| 146 |
+
{%- endfor %}
|
| 147 |
+
{%- if add_generation_prompt %}
|
| 148 |
+
{{- '<|im_start|>assistant\n' }}
|
| 149 |
+
{%- if enable_thinking is defined and enable_thinking is false %}
|
| 150 |
+
{{- '<think>\n\n</think>\n\n' }}
|
| 151 |
+
{%- else %}
|
| 152 |
+
{{- '<think>\n' }}
|
| 153 |
+
{%- endif %}
|
| 154 |
+
{%- endif %}
|
config.json
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"Qwen3_5MoeForCausalLM"
|
| 4 |
+
],
|
| 5 |
+
"attention_bias": false,
|
| 6 |
+
"attention_dropout": 0.0,
|
| 7 |
+
"attn_output_gate": true,
|
| 8 |
+
"bos_token_id": null,
|
| 9 |
+
"dtype": "bfloat16",
|
| 10 |
+
"eos_token_id": 248044,
|
| 11 |
+
"full_attention_interval": 4,
|
| 12 |
+
"head_dim": 256,
|
| 13 |
+
"hidden_act": "silu",
|
| 14 |
+
"hidden_size": 2048,
|
| 15 |
+
"initializer_range": 0.02,
|
| 16 |
+
"layer_types": [
|
| 17 |
+
"linear_attention",
|
| 18 |
+
"linear_attention",
|
| 19 |
+
"linear_attention",
|
| 20 |
+
"full_attention",
|
| 21 |
+
"linear_attention",
|
| 22 |
+
"linear_attention",
|
| 23 |
+
"linear_attention",
|
| 24 |
+
"full_attention",
|
| 25 |
+
"linear_attention",
|
| 26 |
+
"linear_attention",
|
| 27 |
+
"linear_attention",
|
| 28 |
+
"full_attention",
|
| 29 |
+
"linear_attention",
|
| 30 |
+
"linear_attention",
|
| 31 |
+
"linear_attention",
|
| 32 |
+
"full_attention",
|
| 33 |
+
"linear_attention",
|
| 34 |
+
"linear_attention",
|
| 35 |
+
"linear_attention",
|
| 36 |
+
"full_attention",
|
| 37 |
+
"linear_attention",
|
| 38 |
+
"linear_attention",
|
| 39 |
+
"linear_attention",
|
| 40 |
+
"full_attention",
|
| 41 |
+
"linear_attention",
|
| 42 |
+
"linear_attention",
|
| 43 |
+
"linear_attention",
|
| 44 |
+
"full_attention",
|
| 45 |
+
"linear_attention",
|
| 46 |
+
"linear_attention",
|
| 47 |
+
"linear_attention",
|
| 48 |
+
"full_attention",
|
| 49 |
+
"linear_attention",
|
| 50 |
+
"linear_attention",
|
| 51 |
+
"linear_attention",
|
| 52 |
+
"full_attention",
|
| 53 |
+
"linear_attention",
|
| 54 |
+
"linear_attention",
|
| 55 |
+
"linear_attention",
|
| 56 |
+
"full_attention"
|
| 57 |
+
],
|
| 58 |
+
"linear_conv_kernel_dim": 4,
|
| 59 |
+
"linear_key_head_dim": 128,
|
| 60 |
+
"linear_num_key_heads": 16,
|
| 61 |
+
"linear_num_value_heads": 32,
|
| 62 |
+
"linear_value_head_dim": 128,
|
| 63 |
+
"mamba_ssm_dtype": "float32",
|
| 64 |
+
"max_position_embeddings": 262144,
|
| 65 |
+
"mlp_only_layers": [],
|
| 66 |
+
"model_type": "qwen3_5_moe_text",
|
| 67 |
+
"moe_intermediate_size": 512,
|
| 68 |
+
"mtp_num_hidden_layers": 1,
|
| 69 |
+
"mtp_use_dedicated_embeddings": false,
|
| 70 |
+
"num_attention_heads": 16,
|
| 71 |
+
"num_experts": 256,
|
| 72 |
+
"num_experts_per_tok": 8,
|
| 73 |
+
"num_hidden_layers": 40,
|
| 74 |
+
"num_key_value_heads": 2,
|
| 75 |
+
"output_router_logits": false,
|
| 76 |
+
"pad_token_id": null,
|
| 77 |
+
"partial_rotary_factor": 0.25,
|
| 78 |
+
"rms_norm_eps": 1e-06,
|
| 79 |
+
"rope_parameters": {
|
| 80 |
+
"mrope_interleaved": true,
|
| 81 |
+
"mrope_section": [
|
| 82 |
+
11,
|
| 83 |
+
11,
|
| 84 |
+
10
|
| 85 |
+
],
|
| 86 |
+
"partial_rotary_factor": 0.25,
|
| 87 |
+
"rope_theta": 10000000,
|
| 88 |
+
"rope_type": "default"
|
| 89 |
+
},
|
| 90 |
+
"router_aux_loss_coef": 0.001,
|
| 91 |
+
"shared_expert_intermediate_size": 512,
|
| 92 |
+
"tie_word_embeddings": false,
|
| 93 |
+
"transformers_version": "5.17.0",
|
| 94 |
+
"use_cache": true,
|
| 95 |
+
"vocab_size": 248320,
|
| 96 |
+
"experts_implementation": "grouped_mm"
|
| 97 |
+
}
|
decider/__init__.py
ADDED
|
File without changes
|
decider/engine.py
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Low-latency inference engine: shape-bucketed CUDA graphs over the one-pass decision model.
|
| 2 |
+
|
| 3 |
+
Right padding + causal layers => pad positions never influence earlier slots, so no attention
|
| 4 |
+
mask is needed and every (B, T) bucket can be captured once and replayed. The graph outputs
|
| 5 |
+
option-letter logits for all positions [B, T, K]; slots are gathered outside.
|
| 6 |
+
"""
|
| 7 |
+
import time, torch, torch._dynamo, torch.nn.functional as F
|
| 8 |
+
from decider.model import DecisionModel, collate
|
| 9 |
+
from decider.prompt import build, MAX_OPTIONS
|
| 10 |
+
|
| 11 |
+
T_BUCKETS = [64, 128, 192, 256, 320, 384, 512, 640, 768, 1024, 1280, 1536, 2048]
|
| 12 |
+
B_BUCKETS = [1, 2, 4, 8, 16, 32, 64]
|
| 13 |
+
GRAPH_MAX_T = 2048 # longer inputs (up to the 32k request budget) run eagerly: compute dominates there, and one graph
|
| 14 |
+
LONG_STEP = 1024 # per (B, T) shape would cost a compile + capture for every new length
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def _bucket(x, buckets):
|
| 18 |
+
for b in buckets:
|
| 19 |
+
if x <= b:
|
| 20 |
+
return b
|
| 21 |
+
return None
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def fused_causal_conv1d_fn(hidden_states, weight, bias=None, activation=None, **kwargs):
|
| 25 |
+
"""Depthwise causal conv (kernel k) as k shifted multiply-adds: fuses under torch.compile,
|
| 26 |
+
unlike the cuDNN grouped conv fallback (which was ~11% of batched GPU time)."""
|
| 27 |
+
B, C, T = hidden_states.shape; k = weight.shape[-1]
|
| 28 |
+
x = F.pad(hidden_states.to(weight.dtype), (k - 1, 0))
|
| 29 |
+
out = x[:, :, k - 1:k - 1 + T] * weight[:, k - 1][None, :, None]
|
| 30 |
+
for j in range(k - 1):
|
| 31 |
+
out = out + x[:, :, j:j + T] * weight[:, j][None, :, None]
|
| 32 |
+
if bias is not None:
|
| 33 |
+
out = out + bias[None, :, None]
|
| 34 |
+
if activation == "silu":
|
| 35 |
+
out = F.silu(out)
|
| 36 |
+
elif activation is not None:
|
| 37 |
+
from transformers.activations import ACT2FN
|
| 38 |
+
out = ACT2FN[activation](out)
|
| 39 |
+
return out.to(hidden_states.dtype)
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def patch_conv():
|
| 43 |
+
from transformers.models.qwen3_5 import modeling_qwen3_5 as mq
|
| 44 |
+
mq.causal_conv1d_fn = fused_causal_conv1d_fn
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def read_slots(out, rows, slots, nopts, temperature, n_per_item):
|
| 48 |
+
"""One gather + one softmax + one device-to-host copy for the whole batch (was: three small kernels and a sync per item).
|
| 49 |
+
out [B, T, K] logits; rows/slots/nopts: flat python lists, one entry per question; n_per_item: questions per item."""
|
| 50 |
+
dev = out.device; idx = torch.tensor([rows, slots, nopts], dtype=torch.long).to(dev, non_blocking=True)
|
| 51 |
+
lg = out[idx[0], idx[1]] # [N, K]
|
| 52 |
+
lg = lg.masked_fill(torch.arange(lg.shape[1], device=dev)[None, :] >= idx[2][:, None], float("-inf"))
|
| 53 |
+
p = torch.softmax(lg / temperature, -1).cpu()
|
| 54 |
+
return list(torch.split(p, n_per_item))
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def fill_ids(items_ids, B, T, pad):
|
| 58 |
+
import numpy as np
|
| 59 |
+
a = np.full((B, T), pad, dtype=np.int64)
|
| 60 |
+
for b, x in enumerate(items_ids): a[b, :len(x)] = x
|
| 61 |
+
return torch.from_numpy(a)
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
class Engine:
|
| 65 |
+
"""compile: torch.compile the forward (needs use_cache=False; ~1.4x batched, fuses elementwise work).
|
| 66 |
+
fp8: e4m3 weights + per-token activation scaling on the big linears (Hopper tensor cores).
|
| 67 |
+
conv_patch: fusable depthwise causal conv instead of the cuDNN fallback."""
|
| 68 |
+
def __init__(self, path, device="cuda", dtype=torch.bfloat16, use_graphs=True, max_ctx_tokens=1536,
|
| 69 |
+
compile=True, fp8=False, conv_patch=True):
|
| 70 |
+
if conv_patch:
|
| 71 |
+
patch_conv()
|
| 72 |
+
self.m = DecisionModel(path, dtype=dtype, grad_ckpt=False).to(device).eval()
|
| 73 |
+
self.tok = self.m.tok; self.dev = device; self.use_graphs = use_graphs; self.max_ctx = max_ctx_tokens
|
| 74 |
+
self.core, self.W = self.m.lm.model, self.m.lm.lm_head.weight[self.m.letters].detach().clone()
|
| 75 |
+
self.cfg = dict(compile=compile, fp8=fp8, conv_patch=conv_patch, graphs=use_graphs)
|
| 76 |
+
if fp8:
|
| 77 |
+
from decider.fp8 import convert_to_fp8
|
| 78 |
+
self.cfg["fp8_layers"] = convert_to_fp8(self.core)
|
| 79 |
+
if compile:
|
| 80 |
+
torch._dynamo.config.cache_size_limit = 128
|
| 81 |
+
self._fwd_impl = torch.compile(self._fwd_eager, dynamic=False)
|
| 82 |
+
else:
|
| 83 |
+
self._fwd_impl = self._fwd_eager
|
| 84 |
+
self.graphs = {} # (B, T) -> (static_ids, static_out, graph)
|
| 85 |
+
self.pool = torch.cuda.graph_pool_handle() if use_graphs else None
|
| 86 |
+
self.stats = dict(graph_captures=0, forwards=0)
|
| 87 |
+
|
| 88 |
+
def _fwd_eager(self, ids):
|
| 89 |
+
h = self.core(input_ids=ids, use_cache=False).last_hidden_state
|
| 90 |
+
return F.linear(h, self.W).float() # [B, T, K]
|
| 91 |
+
|
| 92 |
+
@torch.no_grad()
|
| 93 |
+
def _fwd(self, ids):
|
| 94 |
+
return self._fwd_impl(ids)
|
| 95 |
+
|
| 96 |
+
def _capture(self, B, T):
|
| 97 |
+
s_ids = torch.full((B, T), self.tok.pad_token_id, dtype=torch.long, device=self.dev)
|
| 98 |
+
st = torch.cuda.Stream(); st.wait_stream(torch.cuda.current_stream())
|
| 99 |
+
with torch.cuda.stream(st):
|
| 100 |
+
for _ in range(3): self._fwd(s_ids) # warm-up: compile / triton autotune
|
| 101 |
+
torch.cuda.current_stream().wait_stream(st)
|
| 102 |
+
g = torch.cuda.CUDAGraph()
|
| 103 |
+
with torch.cuda.graph(g, pool=self.pool):
|
| 104 |
+
s_out = self._fwd(s_ids)
|
| 105 |
+
self.stats["graph_captures"] += 1
|
| 106 |
+
return s_ids, s_out, g
|
| 107 |
+
|
| 108 |
+
@torch.no_grad()
|
| 109 |
+
def logits_all(self, ids):
|
| 110 |
+
"""ids: [B, T] long on device (already right-padded to a bucket). Returns [B, T, K] float."""
|
| 111 |
+
B, T = ids.shape; self.stats["forwards"] += 1
|
| 112 |
+
if T > GRAPH_MAX_T:
|
| 113 |
+
self.stats["long_forwards"] = self.stats.get("long_forwards", 0) + 1
|
| 114 |
+
return self._fwd_eager(ids)
|
| 115 |
+
if not self.use_graphs:
|
| 116 |
+
return self._fwd(ids)
|
| 117 |
+
key = (B, T)
|
| 118 |
+
if key not in self.graphs:
|
| 119 |
+
self.graphs[key] = self._capture(B, T)
|
| 120 |
+
s_ids, s_out, g = self.graphs[key]
|
| 121 |
+
s_ids.copy_(ids); g.replay()
|
| 122 |
+
return s_out
|
| 123 |
+
|
| 124 |
+
@torch.no_grad()
|
| 125 |
+
def score_items(self, items, temperature=1.0):
|
| 126 |
+
"""items: list of dicts from prompt.build. Returns list of [n_q, MAX_OPTIONS] prob tensors (cpu)."""
|
| 127 |
+
Tmax = max(len(it["ids"]) for it in items)
|
| 128 |
+
T = _bucket(Tmax, T_BUCKETS) or -(-Tmax // LONG_STEP) * LONG_STEP
|
| 129 |
+
B = (_bucket(len(items), B_BUCKETS) or len(items)) if T <= GRAPH_MAX_T else len(items)
|
| 130 |
+
ids = fill_ids([it["ids"] for it in items], B, T, self.tok.pad_token_id)
|
| 131 |
+
out = self.logits_all(ids.to(self.dev, non_blocking=True))
|
| 132 |
+
return read_slots(out, [b for b, it in enumerate(items) for _ in it["slots"]], [s for it in items for s in it["slots"]],
|
| 133 |
+
[n for it in items for n in it["nopts"]], temperature, [len(it["slots"]) for it in items])
|
| 134 |
+
|
| 135 |
+
@torch.no_grad()
|
| 136 |
+
def score_shared(self, items, temperature=1.0, min_prefix=192):
|
| 137 |
+
"""Rows that start with the same tokens (one state, one question per row): run the shared prefix once, fork its
|
| 138 |
+
cache (attention KV + delta-net conv/recurrent states) to every row, and run only the question suffixes.
|
| 139 |
+
Same answers as score_items up to kernel round-off; cost ~ state + sum(questions) instead of n * state."""
|
| 140 |
+
ids = [it["ids"] for it in items]; n = len(ids)
|
| 141 |
+
lcp = 0; short = min(len(x) for x in ids) - 1
|
| 142 |
+
while lcp < short and all(x[lcp] == ids[0][lcp] for x in ids): lcp += 1
|
| 143 |
+
if n < 2 or lcp < min_prefix:
|
| 144 |
+
return self.score_items(items, temperature)
|
| 145 |
+
self.stats["shared_prefix_calls"] = self.stats.get("shared_prefix_calls", 0) + 1
|
| 146 |
+
pre = torch.tensor(ids[0][:lcp], device=self.dev)[None]
|
| 147 |
+
cache = self.core(input_ids=pre, use_cache=True).past_key_values
|
| 148 |
+
cache.reorder_cache(torch.zeros(n, dtype=torch.long, device=self.dev)) # fork: every row gets a copy of row 0
|
| 149 |
+
Ts = max(len(x) for x in ids) - lcp
|
| 150 |
+
suf = fill_ids([x[lcp:] for x in ids], n, Ts, self.tok.pad_token_id)
|
| 151 |
+
h = self.core(input_ids=suf.to(self.dev), past_key_values=cache, use_cache=True).last_hidden_state
|
| 152 |
+
rows = [b for b, it in enumerate(items) for _ in it["slots"]]; sl = [s - lcp for it in items for s in it["slots"]]
|
| 153 |
+
idx = torch.tensor([rows, sl], device=self.dev)
|
| 154 |
+
return read_slots(F.linear(h[idx[0], idx[1]], self.W).float()[:, None, :], list(range(len(rows))), [0] * len(rows),
|
| 155 |
+
[n for it in items for n in it["nopts"]], temperature, [len(it["slots"]) for it in items])
|
| 156 |
+
|
| 157 |
+
def warmup(self, shapes=((1, 128), (1, 256), (1, 384), (1, 512), (8, 256), (8, 512), (32, 256), (32, 512))):
|
| 158 |
+
t = time.time()
|
| 159 |
+
for B, T in shapes:
|
| 160 |
+
self.logits_all(torch.full((B, T), self.tok.pad_token_id, dtype=torch.long, device=self.dev))
|
| 161 |
+
torch.cuda.synchronize(); return time.time() - t
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
if __name__ == "__main__":
|
| 165 |
+
import sys, random, numpy as np
|
| 166 |
+
from decider import data as D
|
| 167 |
+
from decider.infer import Decider
|
| 168 |
+
path = sys.argv[1] if len(sys.argv) > 1 else "runs/r3_v2/model"
|
| 169 |
+
cfg = dict(compile="nocompile" not in sys.argv[2:], fp8="fp8" in sys.argv[2:], conv_patch="noconv" not in sys.argv[2:])
|
| 170 |
+
_, evals = D.load_cache("data/tasks.pkl")
|
| 171 |
+
eng = Engine(path, **cfg); print("engine cfg", eng.cfg)
|
| 172 |
+
rng = random.Random(0)
|
| 173 |
+
exs = evals["support_tickets"][:64] + evals["clinc_oos"][:64] + evals["race"][:32]
|
| 174 |
+
items = [build(e, eng.tok, rng, max_ctx_tokens=1536) for e in exs]
|
| 175 |
+
# correctness vs eager masked forward (DecisionModel.slot_logits)
|
| 176 |
+
ref = []
|
| 177 |
+
with torch.no_grad():
|
| 178 |
+
for i in range(0, len(items), 16):
|
| 179 |
+
b = collate(items[i:i + 16], eng.tok.pad_token_id)
|
| 180 |
+
lg = eng.m.slot_logits(b["input_ids"].cuda(), b["attention_mask"].cuda(), b["slot_idx"].cuda(), b["slot_batch"].cuda(), b["nopts"].cuda())
|
| 181 |
+
ref.append(torch.softmax(lg, -1).cpu())
|
| 182 |
+
ref = torch.cat(ref)
|
| 183 |
+
got = torch.cat(eng.score_items(items))
|
| 184 |
+
print(f"max |p_graph - p_eager| = {(ref - got).abs().max():.4f} over {len(ref)} questions; argmax agreement {(ref.argmax(1) == got.argmax(1)).float().mean():.4f}")
|
| 185 |
+
print(f"warmup capture of 8 buckets: {eng.warmup():.1f}s; captures so far {eng.stats['graph_captures']}")
|
| 186 |
+
# latency: single real requests
|
| 187 |
+
for name, pool in [("support_tickets", exs[:64]), ("clinc_oos", exs[64:128]), ("race", exs[128:])]:
|
| 188 |
+
its = [build(e, eng.tok, rng) for e in pool]
|
| 189 |
+
ts = []
|
| 190 |
+
for it in its[:40]:
|
| 191 |
+
torch.cuda.synchronize(); t = time.time(); eng.score_items([it]); torch.cuda.synchronize(); ts.append(time.time() - t)
|
| 192 |
+
ts = np.array(ts[5:]) * 1000
|
| 193 |
+
print(f"single request {name:16s}: p50 {np.median(ts):5.1f} ms p90 {np.percentile(ts, 90):5.1f} ms (avg {np.mean([len(i['ids']) for i in its]):.0f} tok, {len(its[0]['slots'])} q)")
|
| 194 |
+
for bs in (8, 32):
|
| 195 |
+
ts = []
|
| 196 |
+
for i in range(0, min(len(its), bs * 6), bs):
|
| 197 |
+
chunk = its[i:i + bs]
|
| 198 |
+
if len(chunk) < bs: break
|
| 199 |
+
torch.cuda.synchronize(); t = time.time(); eng.score_items(chunk); torch.cuda.synchronize(); ts.append(time.time() - t)
|
| 200 |
+
ts = np.array(ts[1:]) * 1000
|
| 201 |
+
print(f" batch {bs:2d}: p50 {np.median(ts):6.1f} ms -> {bs/np.median(ts)*1000:6.0f} ctx/s, {bs*len(its[0]['slots'])/np.median(ts)*1000:6.0f} decisions/s")
|
| 202 |
+
print("stats", eng.stats, "graphs", len(eng.graphs), f"mem {torch.cuda.memory_reserved()/1e9:.1f} GB")
|
decider/fp8.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""FP8 (e4m3) linear layers for Hopper via torch._scaled_mm.
|
| 2 |
+
Weights: per-output-channel scales, quantised once. Activations: per-token dynamic scales.
|
| 3 |
+
Under torch.compile the quantisation ops fuse into the surrounding elementwise work."""
|
| 4 |
+
import torch, torch.nn as nn
|
| 5 |
+
|
| 6 |
+
E4M3_MAX = 448.0
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def _quant_rowwise(x):
|
| 10 |
+
s = x.abs().amax(dim=-1, keepdim=True).float().clamp(min=1e-12) / E4M3_MAX
|
| 11 |
+
return (x.float() / s).clamp(-E4M3_MAX, E4M3_MAX).to(torch.float8_e4m3fn), s
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
class FP8Linear(nn.Module):
|
| 15 |
+
def __init__(self, lin: nn.Linear):
|
| 16 |
+
super().__init__()
|
| 17 |
+
wq, sw = _quant_rowwise(lin.weight.detach()) # [N,K] fp8, [N,1]
|
| 18 |
+
self.register_buffer("wq", wq.contiguous()) # [N,K]; passed as wq.t() -> [K,N] column-major, as _scaled_mm wants
|
| 19 |
+
self.register_buffer("sw_t", sw.t().contiguous()) # [1,N]
|
| 20 |
+
self.bias = None if lin.bias is None else nn.Parameter(lin.bias.detach().clone(), requires_grad=False)
|
| 21 |
+
self.in_features, self.out_features = lin.in_features, lin.out_features
|
| 22 |
+
self.out_dtype = lin.weight.dtype
|
| 23 |
+
|
| 24 |
+
def forward(self, x):
|
| 25 |
+
shp = x.shape[:-1]
|
| 26 |
+
x2 = x.reshape(-1, self.in_features)
|
| 27 |
+
xq, sx = _quant_rowwise(x2)
|
| 28 |
+
y = torch._scaled_mm(xq, self.wq.t(), scale_a=sx, scale_b=self.sw_t, bias=self.bias, out_dtype=self.out_dtype)
|
| 29 |
+
return y.reshape(*shp, self.out_features)
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def convert_to_fp8(model, skip=("lm_head",), min_dim=1024):
|
| 33 |
+
"""Replace nn.Linear (with in/out >= min_dim) by FP8Linear in place. Returns count."""
|
| 34 |
+
n = 0
|
| 35 |
+
for name, mod in list(model.named_modules()):
|
| 36 |
+
for cname, child in list(mod.named_children()):
|
| 37 |
+
full = f"{name}.{cname}" if name else cname
|
| 38 |
+
if isinstance(child, nn.Linear) and not any(s in full for s in skip) and min(child.in_features, child.out_features) >= min_dim:
|
| 39 |
+
setattr(mod, cname, FP8Linear(child)); n += 1
|
| 40 |
+
return n
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
if __name__ == "__main__":
|
| 44 |
+
import time
|
| 45 |
+
lin = nn.Linear(2048, 6144, bias=False).cuda().to(torch.bfloat16)
|
| 46 |
+
f8 = FP8Linear(lin)
|
| 47 |
+
x = torch.randn(8192, 2048, device="cuda", dtype=torch.bfloat16)
|
| 48 |
+
ref = lin(x); got = f8(x)
|
| 49 |
+
print("rel err", ((ref.float() - got.float()).abs().mean() / ref.float().abs().mean()).item())
|
| 50 |
+
for f, name in [(lin, "bf16 linear"), (f8, "fp8 linear (eager)"), (torch.compile(f8), "fp8 linear (compiled)")]:
|
| 51 |
+
for _ in range(3): f(x)
|
| 52 |
+
torch.cuda.synchronize(); t = time.time()
|
| 53 |
+
for _ in range(20): f(x)
|
| 54 |
+
torch.cuda.synchronize(); print(f"{name:24s} {(time.time()-t)/20*1000:.3f} ms")
|
decider/infer.py
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Usable inference API: typed decisions with probabilities, all from one forward pass.
|
| 2 |
+
|
| 3 |
+
from decider.infer import Decider
|
| 4 |
+
d = Decider("runs/r2_full/model")
|
| 5 |
+
out = d.decide("My card was charged twice for the same purchase.",
|
| 6 |
+
[{"question": "Which department should handle this?", "options": ["billing", "technical", "sales"]},
|
| 7 |
+
{"question": "How urgent is this?", "options": ["low", "medium", "high"]}])
|
| 8 |
+
# -> [{'choice': 'billing', 'confidence': 0.97, 'probs': {...}}, {...}]
|
| 9 |
+
"""
|
| 10 |
+
import torch
|
| 11 |
+
from decider.model import DecisionModel, collate
|
| 12 |
+
from decider.prompt import build, MAX_OPTIONS
|
| 13 |
+
from dataclasses import dataclass
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
@dataclass
|
| 17 |
+
class Q:
|
| 18 |
+
text: str; options: list; gold: int = 0
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
@dataclass
|
| 22 |
+
class Example:
|
| 23 |
+
context: str; qs: list; task: str = "infer"; image: bytes = None
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
NEUTRAL_NONE = "not listed here"
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def neutralize_options(options):
|
| 30 |
+
"""The training augmentation used the literal 'none of the above', and the model learned that exact string as an
|
| 31 |
+
abstain signal (it abstains even on clear cases when the string is offered). Any option that reads like it is
|
| 32 |
+
rewritten to a neutral phrasing for the model and mapped back in the output."""
|
| 33 |
+
out, back = [], {}
|
| 34 |
+
for o in options:
|
| 35 |
+
key = o.strip().lower()
|
| 36 |
+
if key.startswith("none of the above") or key in ("none of the above", "none", "n/a", "none of these"):
|
| 37 |
+
out.append(NEUTRAL_NONE); back[NEUTRAL_NONE] = o
|
| 38 |
+
else:
|
| 39 |
+
out.append(o)
|
| 40 |
+
return out, back
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
class CompiledSchema:
|
| 44 |
+
def __init__(self, d, rqs, h, index): self.d, self.rqs, self.h, self.index = d, rqs, h, index
|
| 45 |
+
|
| 46 |
+
def batch(self, states, max_state_tokens=32768):
|
| 47 |
+
from decider.systemone import render_state, assemble
|
| 48 |
+
probs = self.d._se.score(self.h, [render_state(s) for s in states], temperature=self.d.T_schema, max_ctx_tokens=max_state_tokens)
|
| 49 |
+
return [{"model": self.d.name, "answers": assemble(self.rqs, self.index, [p.tolist() for p in pr])} for pr in probs]
|
| 50 |
+
|
| 51 |
+
def __call__(self, state, max_state_tokens=32768):
|
| 52 |
+
return self.batch([state], max_state_tokens)[0]
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
class Decider:
|
| 56 |
+
"""use_graphs=True (default on CUDA) routes scoring through decider.engine.Engine: shape-bucketed
|
| 57 |
+
CUDA graphs, ~7x lower single-request latency than eager. Set False for CPU or debugging."""
|
| 58 |
+
def __init__(self, path, device="cuda", dtype=torch.bfloat16, temperature=None, abstain_below=0.0, use_graphs=None):
|
| 59 |
+
import json, os
|
| 60 |
+
cfg = {}
|
| 61 |
+
try: # model folder may carry decider_config.json (temperature, flags)
|
| 62 |
+
from huggingface_hub import hf_hub_download
|
| 63 |
+
cfg_path = os.path.join(path, "decider_config.json") if os.path.isdir(path) else hf_hub_download(path, "decider_config.json")
|
| 64 |
+
cfg = json.load(open(cfg_path))
|
| 65 |
+
except Exception:
|
| 66 |
+
pass
|
| 67 |
+
if temperature is None:
|
| 68 |
+
temperature = float(cfg.get("temperature", 1.0))
|
| 69 |
+
self.neutralize_none = bool(cfg.get("neutralize_none", True)) # v4 and earlier learned the literal string as an abstain signal
|
| 70 |
+
if use_graphs is None:
|
| 71 |
+
use_graphs = str(device).startswith("cuda")
|
| 72 |
+
if use_graphs:
|
| 73 |
+
from decider.engine import Engine
|
| 74 |
+
self.eng = Engine(path, device=device, dtype=dtype); self.m = self.eng.m
|
| 75 |
+
else:
|
| 76 |
+
self.eng = None; self.m = DecisionModel(path, dtype=dtype, grad_ckpt=False).to(device).eval()
|
| 77 |
+
self.dev = device; self.T = temperature; self.abstain_below = abstain_below
|
| 78 |
+
self.name = "decider-" + str(cfg.get("version", "dev"))
|
| 79 |
+
self.schema_first = bool(cfg.get("schema_first", False)) and self.eng is not None # default layout. Questions-first (the cacheable one) costs accuracy
|
| 80 |
+
self.T_schema = float(cfg.get("temperature_schema_first", temperature)) # (about 1.5 points on fixed label sets, more elsewhere): opt in with schema()
|
| 81 |
+
self.isolated_levels = bool(cfg.get("isolated_levels", False)) # Score levels judged one per row (v8+)
|
| 82 |
+
self._se = None; self._schemas = {}
|
| 83 |
+
|
| 84 |
+
@torch.no_grad()
|
| 85 |
+
def decide_batch(self, requests, max_ctx_tokens=1536):
|
| 86 |
+
"""requests: list of (context:str, questions:list[dict(question, options)]). One forward pass for everything."""
|
| 87 |
+
exs, meta = [], []
|
| 88 |
+
if self.neutralize_none:
|
| 89 |
+
requests = [(context, [dict(q, options=neutralize_options(q["options"])[0], _back=neutralize_options(q["options"])[1]) for q in qs]) for context, qs in requests]
|
| 90 |
+
for context, qs in requests:
|
| 91 |
+
for q in qs:
|
| 92 |
+
assert 2 <= len(q["options"]) <= MAX_OPTIONS, f"2..{MAX_OPTIONS} options required"
|
| 93 |
+
exs.append(Example(context, [Q(q["question"], list(q["options"]), 0) for q in qs], "infer"))
|
| 94 |
+
class _NoShuffle: # keep option order as given
|
| 95 |
+
def shuffle(self, x): pass
|
| 96 |
+
def sample(self, xs, k): return xs[:k]
|
| 97 |
+
items = [build(e, self.m.tok, _NoShuffle(), max_options=MAX_OPTIONS, max_ctx_tokens=max_ctx_tokens) for e in exs]
|
| 98 |
+
if self.eng is not None:
|
| 99 |
+
probs = torch.cat(self.eng.score_items(items, temperature=self.T))
|
| 100 |
+
else:
|
| 101 |
+
b = collate(items, self.m.tok.pad_token_id)
|
| 102 |
+
logits = self.m.slot_logits(b["input_ids"].to(self.dev), b["attention_mask"].to(self.dev), b["slot_idx"].to(self.dev),
|
| 103 |
+
b["slot_batch"].to(self.dev), b["nopts"].to(self.dev))
|
| 104 |
+
probs = torch.softmax(logits / self.T, -1).cpu()
|
| 105 |
+
out, k = [], 0
|
| 106 |
+
for context, qs in requests:
|
| 107 |
+
res = []
|
| 108 |
+
for q in qs:
|
| 109 |
+
p = probs[k, :len(q["options"])].tolist(); k += 1
|
| 110 |
+
j = max(range(len(p)), key=p.__getitem__); back = q.get("_back", {})
|
| 111 |
+
names = [back.get(o, o) for o in q["options"]]
|
| 112 |
+
res.append(dict(choice=names[j] if p[j] >= self.abstain_below else None, confidence=p[j],
|
| 113 |
+
probs={o: pi for o, pi in zip(names, p)}, probs_list=p))
|
| 114 |
+
out.append(res)
|
| 115 |
+
return out
|
| 116 |
+
|
| 117 |
+
def decide(self, context, questions, **kw):
|
| 118 |
+
return self.decide_batch([(context, questions)], **kw)[0]
|
| 119 |
+
|
| 120 |
+
# ---- Jev-shaped interface (decider.systemone): state + {id: Choice | Score | Noul with criteria}
|
| 121 |
+
# ---- schema cache (v7+): the questions are run once, requests only run the state (decider.schema_engine)
|
| 122 |
+
def schema(self, questions, independent=True, isolated=None, compile=False):
|
| 123 |
+
"""Compile a fixed set of Jev-shaped questions: schema(state) -> answers; schema.batch([state, ...]) -> [answers]."""
|
| 124 |
+
import json
|
| 125 |
+
from decider.schema_engine import SchemaEngine
|
| 126 |
+
from decider.systemone import render_question
|
| 127 |
+
isolated = self.isolated_levels if isolated is None else isolated
|
| 128 |
+
key = (json.dumps(questions, sort_keys=True, ensure_ascii=False), independent, isolated)
|
| 129 |
+
if key not in self._schemas:
|
| 130 |
+
if self._se is None: self._se = SchemaEngine(self.eng)
|
| 131 |
+
if len(self._schemas) >= 64: # drop the oldest schema and its graphs
|
| 132 |
+
old = next(iter(self._schemas)); hid = self._schemas.pop(old)[1].id
|
| 133 |
+
for k in [k for k in self._se.graphs if k[0] == hid]: del self._se.graphs[k]
|
| 134 |
+
from decider.systemone import plan_rows
|
| 135 |
+
rqs = {k: render_question(v) for k, v in questions.items()}
|
| 136 |
+
rows, index = plan_rows(rqs, isolated and independent)
|
| 137 |
+
h = self._se.prepare(rows, independent=independent, compile=compile) # compile=True: ~25 s per (batch, length) shape, 1.6x faster after
|
| 138 |
+
self._schemas[key] = (rqs, h, index)
|
| 139 |
+
return CompiledSchema(self, *self._schemas[key])
|
| 140 |
+
|
| 141 |
+
def system_one(self, state, questions, independent=True, max_state_tokens=32768, max_fwd_tokens=65536, layout=None, isolated=None):
|
| 142 |
+
layout = layout or ("schema_first" if self.schema_first else "state_first")
|
| 143 |
+
isolated = (self.isolated_levels if isolated is None else isolated) and independent
|
| 144 |
+
if layout == "schema_first" and self.eng is not None:
|
| 145 |
+
return self.schema(questions, independent, isolated)(state, max_state_tokens)
|
| 146 |
+
"""independent=True scores every question in its own row (state + that question only), so adding, removing or
|
| 147 |
+
reordering questions cannot change any other answer; the state is run once and its cache forked to every
|
| 148 |
+
question (Engine.score_shared). independent=False packs all questions behind one copy of the state in one row
|
| 149 |
+
(later questions can then see earlier question texts)."""
|
| 150 |
+
from decider.systemone import render_state, render_question, unique_tokens, plan_rows, assemble
|
| 151 |
+
ctx = render_state(state); rqs = {k: render_question(v) for k, v in questions.items()}
|
| 152 |
+
opts = (lambda r: neutralize_options(r["options"])[0]) if self.neutralize_none else (lambda r: list(r["options"]))
|
| 153 |
+
flat, index = plan_rows(rqs, isolated)
|
| 154 |
+
rows = [[r] for r in flat] if independent else [flat]
|
| 155 |
+
class _Keep:
|
| 156 |
+
def shuffle(self, x): pass
|
| 157 |
+
def sample(self, xs, k): return xs[:k]
|
| 158 |
+
items = [build(Example(ctx, [Q(r["question"], opts(r), 0) for r in row]), self.m.tok, _Keep(), max_options=MAX_OPTIONS,
|
| 159 |
+
max_ctx_tokens=max_state_tokens, layout=layout) for row in rows]
|
| 160 |
+
with torch.no_grad():
|
| 161 |
+
if self.eng is not None and len(items) > 1 and layout == "state_first":
|
| 162 |
+
probs = self.eng.score_shared(items, temperature=self.T)
|
| 163 |
+
else:
|
| 164 |
+
probs = []; per = max(1, max_fwd_tokens // max(len(it["ids"]) for it in items))
|
| 165 |
+
for i in range(0, len(items), per):
|
| 166 |
+
if self.eng is not None:
|
| 167 |
+
probs += self.eng.score_items(items[i:i + per], temperature=self.T)
|
| 168 |
+
else:
|
| 169 |
+
bt = collate(items[i:i + per], self.m.tok.pad_token_id)
|
| 170 |
+
lg = self.m.slot_logits(*[bt[k].to(self.dev) for k in ("input_ids", "attention_mask", "slot_idx", "slot_batch", "nopts")])
|
| 171 |
+
pr = torch.softmax(lg / self.T, -1).cpu(); c = 0
|
| 172 |
+
for it in items[i:i + per]:
|
| 173 |
+
probs.append(pr[c:c + len(it["slots"])]); c += len(it["slots"])
|
| 174 |
+
flatp = [p.tolist() for ps in probs for p in ps]
|
| 175 |
+
return {"model": self.name, "answers": assemble(rqs, index, flatp),
|
| 176 |
+
"usage": {"input_tokens": unique_tokens(items), "output_tokens": 0}}
|
| 177 |
+
|
| 178 |
+
# ---- typed schema interface: {question: {"type": "bool"} | {"type": "choice", "options": [...]}
|
| 179 |
+
# | {"type": "scale", "legend": {"0": "none", "1": "low", ...}}}
|
| 180 |
+
@staticmethod
|
| 181 |
+
def _schema_to_questions(schema):
|
| 182 |
+
qs = []
|
| 183 |
+
for qtext, spec in schema.items():
|
| 184 |
+
t = spec.get("type", "choice")
|
| 185 |
+
if t == "bool":
|
| 186 |
+
qs.append(dict(question=qtext, options=["no", "yes"]))
|
| 187 |
+
elif t == "choice":
|
| 188 |
+
qs.append(dict(question=qtext, options=list(spec["options"])))
|
| 189 |
+
elif t == "scale":
|
| 190 |
+
leg = spec["legend"]
|
| 191 |
+
keys = sorted(leg, key=lambda k: float(k)) if isinstance(leg, dict) else list(range(len(leg)))
|
| 192 |
+
labels = [f"{k}: {leg[k]}" if isinstance(leg, dict) else f"{i}: {leg[i]}" for i, k in enumerate(keys)]
|
| 193 |
+
qs.append(dict(question=qtext, options=labels, _keys=keys, _legend=leg))
|
| 194 |
+
else:
|
| 195 |
+
raise ValueError(f"unknown field type {t}")
|
| 196 |
+
return qs
|
| 197 |
+
|
| 198 |
+
def decide_json_batch(self, requests, **kw):
|
| 199 |
+
"""requests: list of (context, schema). Returns one dict per context keyed by question."""
|
| 200 |
+
qss = [self._schema_to_questions(schema) for _, schema in requests]
|
| 201 |
+
raw = self.decide_batch([(ctx, qs) for (ctx, _), qs in zip(requests, qss)], **kw)
|
| 202 |
+
out = []
|
| 203 |
+
for (ctx, schema), qs, res in zip(requests, qss, raw):
|
| 204 |
+
o = {}
|
| 205 |
+
for (qtext, spec), q, r in zip(schema.items(), qs, res):
|
| 206 |
+
t = spec.get("type", "choice")
|
| 207 |
+
if t == "bool":
|
| 208 |
+
o[qtext] = {"noul": round(r["probs"]["yes"], 4), "type": "noul"}
|
| 209 |
+
elif t == "choice":
|
| 210 |
+
o[qtext] = {"choice": r["choice"], "confidence": round(r["confidence"], 4), "type": "choice",
|
| 211 |
+
"probabilities": {k: round(v, 4) for k, v in r["probs"].items()}}
|
| 212 |
+
else:
|
| 213 |
+
p = [r["probs"][lab] for lab in q["options"]]
|
| 214 |
+
keys = q["_keys"]; n = len(p)
|
| 215 |
+
score = sum(float(k) * pi for k, pi in zip(keys, p)) # expected level on the legend scale
|
| 216 |
+
j = max(range(n), key=p.__getitem__)
|
| 217 |
+
o[qtext] = {"score": round(score, 2), "confidence": round(p[j], 4), "type": "scale", "legend": q["_legend"],
|
| 218 |
+
"probabilities": {str(keys[i]): round(pi, 4) for i, pi in enumerate(p)}}
|
| 219 |
+
out.append(o)
|
| 220 |
+
return out
|
| 221 |
+
|
| 222 |
+
def decide_json(self, context, schema, **kw):
|
| 223 |
+
return self.decide_json_batch([(context, schema)], **kw)[0]
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
if __name__ == "__main__":
|
| 227 |
+
import sys, json, time
|
| 228 |
+
d = Decider(sys.argv[1] if len(sys.argv) > 1 else "runs/r1_200k/model")
|
| 229 |
+
demo = [
|
| 230 |
+
("My card was charged twice for the same purchase and I want the extra charge refunded.",
|
| 231 |
+
[{"question": "Which department should handle this?", "options": ["billing", "technical support", "sales"]},
|
| 232 |
+
{"question": "What is the customer's sentiment?", "options": ["angry", "neutral", "happy"]},
|
| 233 |
+
{"question": "Does this need a refund action?", "options": ["no", "yes"]}]),
|
| 234 |
+
("hey can u turn the lights off in the kitchen",
|
| 235 |
+
[{"question": "What is the intent?", "options": ["smart home control", "set alarm", "play music", "none of the above"]},
|
| 236 |
+
{"question": "Is this request toxic?", "options": ["no", "yes"]}]),
|
| 237 |
+
("The quarterly report shows revenue fell 12% while costs rose sharply.",
|
| 238 |
+
[{"question": "What is the financial sentiment?", "options": ["bearish", "neutral", "bullish"]}]),
|
| 239 |
+
]
|
| 240 |
+
t = time.time(); res = d.decide_batch(demo); dt = time.time() - t
|
| 241 |
+
for (ctx, qs), r in zip(demo, res):
|
| 242 |
+
print("\n>>", ctx)
|
| 243 |
+
for q, a in zip(qs, r):
|
| 244 |
+
print(f" {q['question']:45s} -> {a['choice']!s:22s} p={a['confidence']:.2f} " + " ".join(f"{o}:{p:.2f}" for o, p in a['probs'].items()))
|
| 245 |
+
print(f"\n{sum(len(q) for _, q in demo)} decisions in {dt*1000:.0f} ms (one forward pass)")
|
| 246 |
+
schema = {
|
| 247 |
+
"Revenue currently impacted?": {"type": "bool"},
|
| 248 |
+
"What business impact?": {"type": "choice", "options": ["none", "degraded", "outage"]},
|
| 249 |
+
"Integration issue present?": {"type": "bool"},
|
| 250 |
+
"Account health status?": {"type": "choice", "options": ["healthy", "watch", "at risk"]},
|
| 251 |
+
"Which incident scope?": {"type": "choice", "options": ["single_account", "multi_account", "platform_wide"]},
|
| 252 |
+
"Security concern present?": {"type": "bool"},
|
| 253 |
+
"Duplicate charge reported?": {"type": "bool"},
|
| 254 |
+
"Churn likelihood level?": {"type": "scale", "legend": {"0": "none", "1": "low", "2": "medium", "3": "high"}},
|
| 255 |
+
"Human attention needed?": {"type": "bool"},
|
| 256 |
+
"Immediate feature request?": {"type": "bool"},
|
| 257 |
+
}
|
| 258 |
+
ctx = ("Hi, since this morning our Stripe webhook integration stopped firing and our checkout is down for all customers. "
|
| 259 |
+
"We are losing orders every minute and our partner launch is on Thursday. Also I think we got billed twice last week. "
|
| 260 |
+
"If this is not fixed today we will have to look at other providers.")
|
| 261 |
+
t = time.time(); js = d.decide_json(ctx, schema); dt = time.time() - t
|
| 262 |
+
print(f"\n>> {ctx[:80]}...\n" + json.dumps(js, indent=1)[:3000]); print(f"{len(schema)} typed fields in {dt*1000:.0f} ms (one forward pass)")
|
decider/metrics.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def ece(conf, correct, bins=15):
|
| 5 |
+
conf = np.asarray(conf); correct = np.asarray(correct, dtype=float)
|
| 6 |
+
edges = np.linspace(0, 1, bins + 1); e = 0.0
|
| 7 |
+
for lo, hi in zip(edges[:-1], edges[1:]):
|
| 8 |
+
m = (conf > lo) & (conf <= hi)
|
| 9 |
+
if m.any():
|
| 10 |
+
e += m.mean() * abs(conf[m].mean() - correct[m].mean())
|
| 11 |
+
return float(e)
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def aurc(conf, correct):
|
| 15 |
+
"""Area under risk-coverage curve (lower is better)."""
|
| 16 |
+
order = np.argsort(-np.asarray(conf)); c = np.asarray(correct, dtype=float)[order]
|
| 17 |
+
risk = np.cumsum(1 - c) / np.arange(1, len(c) + 1)
|
| 18 |
+
return float(risk.mean())
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def sel_acc(conf, correct, coverage):
|
| 22 |
+
order = np.argsort(-np.asarray(conf)); c = np.asarray(correct, dtype=float)[order]
|
| 23 |
+
n = max(1, int(round(coverage * len(c))))
|
| 24 |
+
return float(c[:n].mean())
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def summarize(probs, golds, nopts):
|
| 28 |
+
"""probs [N,K] (masked entries 0), golds [N], nopts [N]."""
|
| 29 |
+
probs = np.asarray(probs); golds = np.asarray(golds); nopts = np.asarray(nopts)
|
| 30 |
+
pred = probs.argmax(1); conf = probs.max(1); correct = (pred == golds)
|
| 31 |
+
p_gold = probs[np.arange(len(golds)), golds]
|
| 32 |
+
nll = -np.log(np.clip(p_gold, 1e-12, 1)).mean()
|
| 33 |
+
onehot = np.zeros_like(probs); onehot[np.arange(len(golds)), golds] = 1
|
| 34 |
+
brier = ((probs - onehot) ** 2).sum(1).mean()
|
| 35 |
+
return dict(n=int(len(golds)), acc=float(correct.mean()), nll=float(nll), brier=float(brier), ece=ece(conf, correct),
|
| 36 |
+
aurc=aurc(conf, correct), acc_at_80=sel_acc(conf, correct, 0.8), acc_at_50=sel_acc(conf, correct, 0.5),
|
| 37 |
+
chance=float((1.0 / nopts).mean()), mean_conf=float(conf.mean()))
|
decider/model.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Backbone -> slot hidden states -> restricted logits over option letters."""
|
| 2 |
+
import torch, torch.nn as nn, torch.nn.functional as F
|
| 3 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 4 |
+
from decider.prompt import letter_ids, MAX_OPTIONS
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class DecisionModel(nn.Module):
|
| 8 |
+
def __init__(self, name, dtype=torch.bfloat16, grad_ckpt=True):
|
| 9 |
+
super().__init__()
|
| 10 |
+
self.tok = AutoTokenizer.from_pretrained(name)
|
| 11 |
+
self.lm = AutoModelForCausalLM.from_pretrained(name, dtype=dtype)
|
| 12 |
+
if grad_ckpt:
|
| 13 |
+
self.lm.gradient_checkpointing_enable()
|
| 14 |
+
self.register_buffer("letters", torch.tensor(letter_ids(self.tok)), persistent=False)
|
| 15 |
+
|
| 16 |
+
def slot_logits(self, input_ids, attention_mask, slot_idx, slot_batch, nopts):
|
| 17 |
+
"""input_ids [B,T]; slot_idx/slot_batch [N] flat slot positions; nopts [N].
|
| 18 |
+
Returns [N, MAX_OPTIONS] logits with invalid options masked to -inf."""
|
| 19 |
+
h = self.lm.model(input_ids=input_ids, attention_mask=attention_mask).last_hidden_state
|
| 20 |
+
hs = h[slot_batch, slot_idx] # [N,H]
|
| 21 |
+
W = self.lm.lm_head.weight[self.letters] # [K,H]
|
| 22 |
+
logits = F.linear(hs, W).float() # [N,K]
|
| 23 |
+
ar = torch.arange(MAX_OPTIONS, device=logits.device)[None, :]
|
| 24 |
+
logits = logits.masked_fill(ar >= nopts[:, None], float("-inf"))
|
| 25 |
+
return logits
|
| 26 |
+
|
| 27 |
+
def forward(self, batch):
|
| 28 |
+
return self.slot_logits(batch["input_ids"], batch["attention_mask"], batch["slot_idx"], batch["slot_batch"], batch["nopts"])
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def collate(items, pad_id):
|
| 32 |
+
"""items: list of dicts from prompt.build (+ 'task', 'ex_id'). Right-pad."""
|
| 33 |
+
T = max(len(it["ids"]) for it in items)
|
| 34 |
+
T = ((T + 63) // 64) * 64 # few distinct shapes -> fewer kernel (re)compiles
|
| 35 |
+
B = len(items)
|
| 36 |
+
input_ids = torch.full((B, T), pad_id, dtype=torch.long)
|
| 37 |
+
attn = torch.zeros((B, T), dtype=torch.long)
|
| 38 |
+
slot_idx, slot_batch, golds, nopts, tasks, qidx = [], [], [], [], [], []
|
| 39 |
+
for b, it in enumerate(items):
|
| 40 |
+
n = len(it["ids"])
|
| 41 |
+
input_ids[b, :n] = torch.tensor(it["ids"])
|
| 42 |
+
attn[b, :n] = 1
|
| 43 |
+
for k, s in enumerate(it["slots"]):
|
| 44 |
+
slot_idx.append(s); slot_batch.append(b); golds.append(it["golds"][k]); nopts.append(it["nopts"][k])
|
| 45 |
+
tasks.append(it.get("task", "")); qidx.append(k)
|
| 46 |
+
return dict(input_ids=input_ids, attention_mask=attn, slot_idx=torch.tensor(slot_idx), slot_batch=torch.tensor(slot_batch),
|
| 47 |
+
golds=torch.tensor(golds), nopts=torch.tensor(nopts), tasks=tasks, qidx=qidx)
|
decider/prompt.py
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Prompt construction. One context, N typed questions, N answer slots.
|
| 2 |
+
|
| 3 |
+
All N decisions are read from a single forward pass: the logits at each
|
| 4 |
+
"Answer k: (" slot are restricted to the option-letter tokens. No answer
|
| 5 |
+
letters are ever inserted, so slot k sees the context and all questions but
|
| 6 |
+
no earlier answers (the decisions are conditionally independent given input).
|
| 7 |
+
"""
|
| 8 |
+
import random
|
| 9 |
+
|
| 10 |
+
LETTERS = "ABCDEFGHIJ"
|
| 11 |
+
NARROW = len(LETTERS) # <= NARROW options: the original "(A) .. (J)" rendering, tokenized as a string (unchanged since v1)
|
| 12 |
+
MAX_OPTIONS = 255 # width of the label head. > NARROW options: "wide" rendering, one label token per option:
|
| 13 |
+
# A..Z then the first 229 two-letter upper-case strings that are single tokens (AA, AB, ...)
|
| 14 |
+
ABSTAIN_PREFIXES = ("none of the above", "none of these", "not listed", "no suitable", "does not apply", "cannot tell")
|
| 15 |
+
ABSTAIN_EXACT = ("other", "unsure", "something else", "neither of these", "other / not covered")
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def is_abstain_option(o):
|
| 19 |
+
o = o.strip().lower()
|
| 20 |
+
return o.startswith(ABSTAIN_PREFIXES) or o in ABSTAIN_EXACT
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
_LABELS = {}
|
| 24 |
+
_OPT_CACHE = {}
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def _enc_opt(tok, text):
|
| 28 |
+
"""Token ids of ") <option text>" (cached: fixed label sets repeat the same strings millions of times)."""
|
| 29 |
+
key = (id(tok), text)
|
| 30 |
+
v = _OPT_CACHE.get(key)
|
| 31 |
+
if v is None:
|
| 32 |
+
v = tok.encode(f") {text}", add_special_tokens=False)
|
| 33 |
+
if len(_OPT_CACHE) < 2_000_000:
|
| 34 |
+
_OPT_CACHE[key] = v
|
| 35 |
+
return v
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def label_table(tok):
|
| 39 |
+
"""(label strings, label token ids), MAX_OPTIONS entries; the first NARROW are A..J so narrow questions are unchanged."""
|
| 40 |
+
key = id(tok)
|
| 41 |
+
if key not in _LABELS:
|
| 42 |
+
import string
|
| 43 |
+
U = string.ascii_uppercase
|
| 44 |
+
names = list(U) + [a + b for a in U for b in U]
|
| 45 |
+
out = []
|
| 46 |
+
for n in names:
|
| 47 |
+
t = tok.encode(n, add_special_tokens=False)
|
| 48 |
+
if len(t) == 1:
|
| 49 |
+
out.append((n, t[0]))
|
| 50 |
+
if len(out) == MAX_OPTIONS:
|
| 51 |
+
break
|
| 52 |
+
assert len(out) == MAX_OPTIONS and len({i for _, i in out}) == MAX_OPTIONS
|
| 53 |
+
_LABELS[key] = ([n for n, _ in out], [i for _, i in out],
|
| 54 |
+
tok.encode("\n(", add_special_tokens=False))
|
| 55 |
+
return _LABELS[key]
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def _select(q, rng, max_options):
|
| 59 |
+
opts = list(range(len(q.options)))
|
| 60 |
+
if len(opts) > max_options:
|
| 61 |
+
# always keep the gold and any abstain-style option (its mere presence must not carry information)
|
| 62 |
+
forced = {q.gold} | {i for i, o in enumerate(q.options) if is_abstain_option(o)}
|
| 63 |
+
others = [i for i in opts if i not in forced]
|
| 64 |
+
opts = rng.sample(others, max_options - len(forced)) + list(forced)
|
| 65 |
+
rng.shuffle(opts)
|
| 66 |
+
return opts
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def _options_ids(tok, q, opts):
|
| 70 |
+
if len(opts) <= NARROW:
|
| 71 |
+
return tok.encode("".join(f"\n({LETTERS[j]}) {q.options[oi]}" for j, oi in enumerate(opts)), add_special_tokens=False)
|
| 72 |
+
_, lab_ids, open_ids = label_table(tok); out = []
|
| 73 |
+
for j, oi in enumerate(opts):
|
| 74 |
+
out += open_ids + [lab_ids[j]] + _enc_opt(tok, q.options[oi])
|
| 75 |
+
return out
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def build_schema_first(example, tok, rng=None, max_options=NARROW, max_ctx_tokens=1536):
|
| 79 |
+
"""Schema-first layout: all question/option blocks, then the context, then one answer slot per question.
|
| 80 |
+
|
| 81 |
+
Question 1: ...\nOptions:\n(A) ... <- prefix: depends only on the questions, so its cache (attention KV and
|
| 82 |
+
\n\nQuestion 2: ... delta-net states) is computed once per schema and reused for every state
|
| 83 |
+
\n\nContext:\n<state>\n\nAnswer 1: (\nAnswer 2: (
|
| 84 |
+
|
| 85 |
+
The three parts are tokenized separately, so `ids[:prefix_len]` is identical for every state."""
|
| 86 |
+
rng = rng or random
|
| 87 |
+
perms = [_select(q, rng, max_options) for q in example.qs]
|
| 88 |
+
pre = schema_prefix_ids(tok, example.qs, perms)
|
| 89 |
+
suf, slots = schema_suffix_ids(tok, example.context, len(example.qs), max_ctx_tokens)
|
| 90 |
+
return dict(ids=pre + suf, slots=[len(pre) + s for s in slots], golds=[p.index(q.gold) if q.gold in p else -1 for p, q in zip(perms, example.qs)],
|
| 91 |
+
nopts=[len(p) for p in perms], perms=perms, prefix_len=len(pre))
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def schema_prefix_ids(tok, qs, perms=None):
|
| 95 |
+
"""Token ids of the question/option blocks (the cacheable part of the schema-first layout)."""
|
| 96 |
+
multi = len(qs) > 1; pre = []
|
| 97 |
+
for k, q in enumerate(qs):
|
| 98 |
+
opts = perms[k] if perms is not None else list(range(len(q.options)))
|
| 99 |
+
pre += tok.encode(f"{chr(10) * 2 if k else ''}Question{' ' + str(k + 1) if multi else ''}: {q.text}\nOptions:", add_special_tokens=False) + _options_ids(tok, q, opts)
|
| 100 |
+
return pre
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
def schema_suffix_ids(tok, context, n_q, max_ctx_tokens=1536):
|
| 104 |
+
"""Token ids after the schema prefix: the context and one answer slot per question. Returns (ids, slot positions in ids)."""
|
| 105 |
+
ids = tok.encode("\n\nContext:\n", add_special_tokens=False) + tok.encode(context, add_special_tokens=False)[:max_ctx_tokens]; slots = []
|
| 106 |
+
for k in range(n_q):
|
| 107 |
+
ids += tok.encode(f"{chr(10) * 2 if k == 0 else chr(10)}Answer{' ' + str(k + 1) if n_q > 1 else ''}: (", add_special_tokens=False); slots.append(len(ids) - 1)
|
| 108 |
+
return ids, slots
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
def build(example, tok, rng=None, max_options=NARROW, max_ctx_tokens=1536, layout="state_first"):
|
| 112 |
+
"""Returns dict(ids=list[int], slots=list[int], golds=list[int], nopts=list[int], perms=list[list[int]])."""
|
| 113 |
+
if layout == "schema_first":
|
| 114 |
+
return build_schema_first(example, tok, rng, max_options, max_ctx_tokens)
|
| 115 |
+
rng = rng or random
|
| 116 |
+
ctx_ids = tok.encode("Context:\n" + example.context, add_special_tokens=False)[:max_ctx_tokens]
|
| 117 |
+
ids = list(ctx_ids)
|
| 118 |
+
slots, golds, nopts, perms = [], [], [], []
|
| 119 |
+
multi = len(example.qs) > 1
|
| 120 |
+
for k, q in enumerate(example.qs):
|
| 121 |
+
opts = list(range(len(q.options)))
|
| 122 |
+
if len(opts) > max_options:
|
| 123 |
+
# always keep the gold and any abstain-style option (its mere presence must not carry information)
|
| 124 |
+
forced = {q.gold} | {i for i, o in enumerate(q.options) if is_abstain_option(o)}
|
| 125 |
+
others = [i for i in opts if i not in forced]
|
| 126 |
+
keep = rng.sample(others, max_options - len(forced)) + list(forced)
|
| 127 |
+
opts = keep
|
| 128 |
+
rng.shuffle(opts)
|
| 129 |
+
head = f"\n\nQuestion{' ' + str(k + 1) if multi else ''}: {q.text}\nOptions:"
|
| 130 |
+
tail = f"\nAnswer{' ' + str(k + 1) if multi else ''}: ("
|
| 131 |
+
if len(opts) <= NARROW:
|
| 132 |
+
lines = [head] + [f"\n({LETTERS[j]}) {q.options[oi]}" for j, oi in enumerate(opts)] + [tail]
|
| 133 |
+
piece = tok.encode("".join(lines), add_special_tokens=False)
|
| 134 |
+
else: # wide: "\n(" + <label token> + ") text", built from ids so every label is one token
|
| 135 |
+
_, lab_ids, open_ids = label_table(tok)
|
| 136 |
+
piece = tok.encode(head, add_special_tokens=False)
|
| 137 |
+
for j, oi in enumerate(opts):
|
| 138 |
+
piece += open_ids + [lab_ids[j]] + _enc_opt(tok, q.options[oi])
|
| 139 |
+
piece += tok.encode(tail, add_special_tokens=False)
|
| 140 |
+
ids.extend(piece)
|
| 141 |
+
slots.append(len(ids) - 1) # position of " (" token
|
| 142 |
+
golds.append(opts.index(q.gold) if q.gold in opts else -1)
|
| 143 |
+
nopts.append(len(opts))
|
| 144 |
+
perms.append(opts)
|
| 145 |
+
return dict(ids=ids, slots=slots, golds=golds, nopts=nopts, perms=perms)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def letter_ids(tok):
|
| 149 |
+
ids = label_table(tok)[1]
|
| 150 |
+
for j, L in enumerate(LETTERS):
|
| 151 |
+
assert tok.encode(L, add_special_tokens=False) == [ids[j]], L
|
| 152 |
+
return ids
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
def render(example, tok, **kw):
|
| 156 |
+
b = build(example, tok, **kw)
|
| 157 |
+
return tok.decode(b["ids"])
|
decider/schema_engine.py
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Schema cache: compute a question schema once, then score states against it.
|
| 2 |
+
|
| 3 |
+
In production the questions are fixed and only the state changes. With the schema-first prompt layout
|
| 4 |
+
(prompt.build_schema_first) the question/option blocks are a prefix that does not depend on the state, so their
|
| 5 |
+
cache - attention K/V for the 6 full-attention layers, conv + recurrent state for the 18 delta-net layers - is computed
|
| 6 |
+
once (`prepare`). A request then runs only "Context: <state>" plus one answer slot per question, as a CUDA graph per
|
| 7 |
+
(batch, length) bucket. The prefix cache is read-only during a request (nothing is written back), so one copy serves
|
| 8 |
+
every batch and every graph.
|
| 9 |
+
|
| 10 |
+
se = SchemaEngine(engine); h = se.prepare([{"question": ..., "options": [...]}, ...])
|
| 11 |
+
probs = se.score(h, ["state 1", "state 2", ...]) # list of [n_questions, MAX_OPTIONS] tensors
|
| 12 |
+
"""
|
| 13 |
+
import time, types, torch, torch.nn.functional as F
|
| 14 |
+
from decider.prompt import schema_prefix_ids, schema_suffix_ids, MAX_OPTIONS
|
| 15 |
+
from decider.engine import read_slots, fill_ids
|
| 16 |
+
|
| 17 |
+
TS_BUCKETS = [32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024]
|
| 18 |
+
B_BUCKETS = [1, 2, 4, 8, 16, 32, 64]
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
class _Q:
|
| 22 |
+
def __init__(self, text, options): self.text, self.options = text, options
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
class PrefixCache:
|
| 26 |
+
"""Duck-typed transformers Cache over fixed, read-only prefixes, for one suffix forward pass.
|
| 27 |
+
A handle holds P prefixes (P = 1: all questions packed in one prefix; P = n_questions: one prefix per question, so every
|
| 28 |
+
question is scored independently). A batch of R states has R * P rows; row r * P + p continues prefix p."""
|
| 29 |
+
def __init__(self, h, R):
|
| 30 |
+
rep = (lambda t: t.expand(R, *t.shape[1:])) if h.P == 1 else (lambda t: t.repeat(R, *([1] * (t.dim() - 1))))
|
| 31 |
+
self.tp = h.tpmax; self.k = {i: rep(k) for i, k in h.k.items()}; self.v = {i: rep(v) for i, v in h.v.items()}
|
| 32 |
+
self.conv = {i: rep(c).contiguous() for i, c in h.conv.items()}
|
| 33 |
+
self.layers = {i: types.SimpleNamespace(record_past=False, recurrent_states={0: rep(r).contiguous()}) for i, r in h.rec.items()}
|
| 34 |
+
|
| 35 |
+
def has_previous_state(self, layer_idx=None, state_idx=None): return True
|
| 36 |
+
def get_seq_length(self, *a, **k): return self.tp
|
| 37 |
+
def update(self, key, value, layer_idx, *a, **k): return torch.cat([self.k[layer_idx], key], 2), torch.cat([self.v[layer_idx], value], 2)
|
| 38 |
+
def update_conv_state(self, x, layer_idx, **k): return torch.cat([self.conv[layer_idx].to(x.dtype), x], -1)
|
| 39 |
+
def update_recurrent_state(self, s, layer_idx, **k): return s
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
class SchemaEngine:
|
| 43 |
+
def __init__(self, engine, use_graphs=True):
|
| 44 |
+
self.e = engine; self.core = engine.core; self.W = engine.W; self.tok = engine.tok; self.dev = engine.dev
|
| 45 |
+
self.use_graphs = use_graphs and engine.use_graphs; self.graphs = {}; self.stats = dict(prepared=0, captures=0, replays=0, eager=0)
|
| 46 |
+
self.compile = bool(engine.cfg.get("compile")); self._compiled = {}
|
| 47 |
+
if self.compile: # every compiled schema graph specialises the model frames again (its cache tensors are constants)
|
| 48 |
+
import torch._dynamo
|
| 49 |
+
torch._dynamo.config.cache_size_limit = 4096; torch._dynamo.config.accumulated_cache_size_limit = 1 << 16
|
| 50 |
+
|
| 51 |
+
@torch.no_grad()
|
| 52 |
+
def prepare(self, questions, independent=False, compile=False):
|
| 53 |
+
"""questions: [{"question": str, "options": [str]}] in the order answers are wanted. Runs the prefix(es) once.
|
| 54 |
+
independent=False: one prefix holding every question (cheapest: a request costs state + n slots).
|
| 55 |
+
independent=True: one prefix per question, one row per question (a request costs n * (state + 1 slot); no question
|
| 56 |
+
can influence another)."""
|
| 57 |
+
qs = [_Q(q["question"], list(q["options"])) for q in questions]
|
| 58 |
+
groups = [[q] for q in qs] if independent else [qs]; pres = [schema_prefix_ids(self.tok, g) for g in groups]
|
| 59 |
+
h = types.SimpleNamespace(P=len(groups), nq=len(qs), slots_per_row=1 if independent else len(qs), nopts=[len(q.options) for q in qs], tps=[len(p) for p in pres],
|
| 60 |
+
tpmax=max(len(p) for p in pres), k={}, v={}, conv={}, rec={}, id=self.stats["prepared"],
|
| 61 |
+
compile=bool(compile and self.compile))
|
| 62 |
+
parts = []
|
| 63 |
+
for pre in pres:
|
| 64 |
+
out = self.core(input_ids=torch.tensor(pre, device=self.dev)[None], use_cache=True).past_key_values; d = dict(k={}, v={}, conv={}, rec={})
|
| 65 |
+
for i, layer in enumerate(out.layers):
|
| 66 |
+
if getattr(layer, "recurrent_states", None) is not None and layer.recurrent_states.get(0) is not None:
|
| 67 |
+
d["conv"][i] = layer.conv_states[0]; d["rec"][i] = layer.recurrent_states[0]
|
| 68 |
+
else: # right-pad every prefix's K/V to the longest; the mask hides the padding
|
| 69 |
+
pad = (0, 0, 0, h.tpmax - len(pre)); d["k"][i] = F.pad(layer.keys, pad); d["v"][i] = F.pad(layer.values, pad)
|
| 70 |
+
parts.append(d)
|
| 71 |
+
for name in ("k", "v", "conv", "rec"):
|
| 72 |
+
getattr(h, name).update({i: torch.cat([d[name][i] for d in parts], 0).clone() for i in parts[0][name]})
|
| 73 |
+
self.stats["prepared"] += 1
|
| 74 |
+
return h
|
| 75 |
+
|
| 76 |
+
def _fwd(self, ids, cache, mask, pos):
|
| 77 |
+
hs = self.core(input_ids=ids, past_key_values=cache, attention_mask={"full_attention": mask, "linear_attention": None}, position_ids=pos, use_cache=True).last_hidden_state
|
| 78 |
+
return F.linear(hs, self.W).float()
|
| 79 |
+
|
| 80 |
+
def _static(self, h, R, Ts):
|
| 81 |
+
"""R request slots -> R * P rows. Mask: a row sees its own prefix (not the padding up to tpmax) and the causal suffix."""
|
| 82 |
+
ar = torch.arange(Ts, device=self.dev); tps = torch.tensor(h.tps, device=self.dev).repeat(R) # [R*P]
|
| 83 |
+
pre = (torch.arange(h.tpmax, device=self.dev)[None, :] < tps[:, None])[:, None, None, :].expand(-1, 1, Ts, -1) # [B,1,Ts,tpmax]
|
| 84 |
+
mask = torch.cat([pre, (ar[:, None] >= ar[None, :])[None, None].expand(len(tps), 1, -1, -1)], 3).contiguous()
|
| 85 |
+
return PrefixCache(h, R), mask, (tps[:, None] + ar[None, :]).contiguous()
|
| 86 |
+
|
| 87 |
+
def _capture(self, h, R, Ts):
|
| 88 |
+
B = R * h.P
|
| 89 |
+
ids = torch.full((B, Ts), self.tok.pad_token_id, dtype=torch.long, device=self.dev); cache, mask, pos = self._static(h, R, Ts)
|
| 90 |
+
fwd = self._fwd
|
| 91 |
+
if h.compile: # one compiled function per graph (20-30 s each: only for preloaded schemas): the cache tensors are constants of that graph
|
| 92 |
+
fwd = torch.compile(lambda i: self._fwd(i, cache, mask, pos), dynamic=False)
|
| 93 |
+
call = lambda: fwd(ids)
|
| 94 |
+
else:
|
| 95 |
+
call = lambda: fwd(ids, cache, mask, pos)
|
| 96 |
+
st = torch.cuda.Stream(); st.wait_stream(torch.cuda.current_stream())
|
| 97 |
+
with torch.cuda.stream(st):
|
| 98 |
+
for _ in range(3): call()
|
| 99 |
+
torch.cuda.current_stream().wait_stream(st)
|
| 100 |
+
g = torch.cuda.CUDAGraph()
|
| 101 |
+
with torch.cuda.graph(g, pool=self.e.pool):
|
| 102 |
+
out = call()
|
| 103 |
+
self.stats["captures"] += 1
|
| 104 |
+
return ids, out, g, (cache, mask, pos)
|
| 105 |
+
|
| 106 |
+
def warmup(self, h, batch_sizes=(1, 8, 32), state_tokens=(64, 128, 256)):
|
| 107 |
+
"""Capture (and, for a compiled schema, compile) the graphs for these request-batch sizes and suffix lengths ahead of traffic."""
|
| 108 |
+
t = time.time()
|
| 109 |
+
for R in batch_sizes:
|
| 110 |
+
for Ts in state_tokens:
|
| 111 |
+
Ts = next((x for x in TS_BUCKETS if x >= Ts), TS_BUCKETS[-1])
|
| 112 |
+
if (h.id, R, Ts) not in self.graphs: self.graphs[(h.id, R, Ts)] = self._capture(h, R, Ts)
|
| 113 |
+
torch.cuda.synchronize(); return time.time() - t
|
| 114 |
+
|
| 115 |
+
def tokenize(self, h, context, max_ctx_tokens=1536):
|
| 116 |
+
"""CPU part of a request (do it outside any GPU lock): -> (suffix ids, slot positions)."""
|
| 117 |
+
return schema_suffix_ids(self.tok, context, h.slots_per_row, max_ctx_tokens)
|
| 118 |
+
|
| 119 |
+
@staticmethod
|
| 120 |
+
def bucket(n_tokens):
|
| 121 |
+
return next((t for t in TS_BUCKETS if t >= n_tokens), -(-n_tokens // 256) * 256)
|
| 122 |
+
|
| 123 |
+
def score(self, h, contexts, temperature=1.0, max_ctx_tokens=1536):
|
| 124 |
+
"""-> one [n_questions, MAX_OPTIONS] probability tensor per context."""
|
| 125 |
+
return self.score_rows(h, [self.tokenize(h, c, max_ctx_tokens) for c in contexts], temperature)
|
| 126 |
+
|
| 127 |
+
@torch.no_grad()
|
| 128 |
+
def score_rows(self, h, rows, temperature=1.0):
|
| 129 |
+
"""rows: [(suffix ids, slots)] from tokenize()."""
|
| 130 |
+
Tmax = max(len(r[0]) for r in rows); Ts = next((t for t in TS_BUCKETS if t >= Tmax), None); n = len(rows)
|
| 131 |
+
R = next((b for b in B_BUCKETS if b >= n), n) if Ts else n; Ts = Ts or -(-Tmax // 256) * 256
|
| 132 |
+
ids = fill_ids([x for x, _ in rows for _ in range(h.P)], R * h.P, Ts, self.tok.pad_token_id).to(self.dev, non_blocking=True)
|
| 133 |
+
if self.use_graphs and Ts <= TS_BUCKETS[-1]:
|
| 134 |
+
key = (h.id, R, Ts)
|
| 135 |
+
if key not in self.graphs: self.graphs[key] = self._capture(h, R, Ts)
|
| 136 |
+
s_ids, s_out, g, _ = self.graphs[key]; s_ids.copy_(ids); g.replay(); out = s_out; self.stats["replays"] += 1
|
| 137 |
+
else:
|
| 138 |
+
out = self._fwd(ids, *self._static(h, R, Ts)); self.stats["eager"] += 1
|
| 139 |
+
if h.P == 1: # packed: n slots in one row per request
|
| 140 |
+
rws = [r for r in range(n) for _ in range(h.nq)]; sls = [x for _, sl in rows for x in sl]
|
| 141 |
+
else: # independent: one slot in each of the request's P rows
|
| 142 |
+
rws = [r * h.P + p for r in range(n) for p in range(h.P)]; sls = [sl[0] for _, sl in rows for _ in range(h.P)]
|
| 143 |
+
return read_slots(out, rws, sls, h.nopts * n, temperature, [h.nq] * n)
|
decider/serve.py
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Micro-batching HTTP server.
|
| 2 |
+
POST /decide {"context": str, "schema": {...}} -> typed JSON decisions (all questions packed in one row)
|
| 3 |
+
POST /v1/systemone {"state": str|object|array, "questions": {id: {...}}} -> the TypeSafe/Jev wire format (decider.systemone):
|
| 4 |
+
Choice (up to 255 described options), Score, Noul; every question is scored in its own row, so answers
|
| 5 |
+
are independent of each other ("independent": false packs them behind one copy of the state instead).
|
| 6 |
+
Requests arriving within `max_wait_ms` are scored in one forward pass (grouped by length bucket).
|
| 7 |
+
uvicorn decider.serve:app --host 0.0.0.0 --port 8000 (env: DECIDER_MODEL, DECIDER_MAX_BATCH, DECIDER_MAX_WAIT_MS)
|
| 8 |
+
"""
|
| 9 |
+
import asyncio, os, random, time, threading
|
| 10 |
+
from fastapi import FastAPI, HTTPException
|
| 11 |
+
from pydantic import BaseModel
|
| 12 |
+
from decider.engine import Engine, T_BUCKETS, _bucket
|
| 13 |
+
from decider.prompt import build, MAX_OPTIONS
|
| 14 |
+
from decider.infer import Decider, Example, Q, neutralize_options
|
| 15 |
+
from decider import systemone as S1
|
| 16 |
+
|
| 17 |
+
MODEL = os.environ.get("DECIDER_MODEL", "runs/r3_v2/model")
|
| 18 |
+
MAX_BATCH = int(os.environ.get("DECIDER_MAX_BATCH", "32"))
|
| 19 |
+
MAX_WAIT_MS = float(os.environ.get("DECIDER_MAX_WAIT_MS", "8"))
|
| 20 |
+
BATCH_WAIT_MS = float(os.environ.get("DECIDER_BATCH_WAIT_MS", "0"))
|
| 21 |
+
MAX_STATE_TOKENS = int(os.environ.get("DECIDER_MAX_STATE_TOKENS", "32768"))
|
| 22 |
+
MAX_FWD_TOKENS = int(os.environ.get("DECIDER_MAX_FWD_TOKENS", "65536")) # padded tokens per forward pass
|
| 23 |
+
COMPILE = os.environ.get("DECIDER_COMPILE", "1") == "1"
|
| 24 |
+
FP8 = os.environ.get("DECIDER_FP8", "1") == "1"
|
| 25 |
+
app = FastAPI(title="decider")
|
| 26 |
+
MODEL_NAME = "decider"; TEMP = 1.0; TEMP_SCHEMA = 1.0; RELEASE_DATE = "2026-09-17"
|
| 27 |
+
gpu_lock = threading.Lock() # one GPU job at a time: batched graph replays and shared-prefix requests must not interleave
|
| 28 |
+
SHARED_MIN_TOKENS = int(os.environ.get("DECIDER_SHARED_MIN_TOKENS", "768")) # independent rows over a state this long share one prefix pass
|
| 29 |
+
eng = None; queue = None; stats = dict(requests=0, batches=0, decisions=0, batch_hist={})
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
class Req(BaseModel):
|
| 33 |
+
context: str
|
| 34 |
+
schema_: dict = None
|
| 35 |
+
model_config = {"populate_by_name": True}
|
| 36 |
+
def __init__(self, **kw):
|
| 37 |
+
if "schema" in kw: kw["schema_"] = kw.pop("schema")
|
| 38 |
+
super().__init__(**kw)
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
class _NoShuffle:
|
| 42 |
+
def shuffle(self, x): pass
|
| 43 |
+
def sample(self, xs, k): return xs[:k]
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def _prepare(context, schema):
|
| 47 |
+
qs = Decider._schema_to_questions(schema)
|
| 48 |
+
for q in qs:
|
| 49 |
+
if getattr(eng, "neutralize_none", True):
|
| 50 |
+
q["options"], q["_back"] = neutralize_options(q["options"])
|
| 51 |
+
ex = Example(context, [Q(q["question"], list(q["options"]), 0) for q in qs])
|
| 52 |
+
it = build(ex, eng.tok, _NoShuffle(), max_options=MAX_OPTIONS, max_ctx_tokens=eng.max_ctx)
|
| 53 |
+
return qs, it
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def _format(schema, qs, probs):
|
| 57 |
+
o = {}
|
| 58 |
+
for (qtext, spec), q, p in zip(schema.items(), qs, probs):
|
| 59 |
+
p = p[:len(q["options"])].tolist(); t = spec.get("type", "choice"); j = max(range(len(p)), key=p.__getitem__)
|
| 60 |
+
back = q.get("_back", {}); names = [back.get(x, x) for x in q["options"]]
|
| 61 |
+
if t == "bool":
|
| 62 |
+
o[qtext] = {"noul": round(p[1], 4), "type": "noul"}
|
| 63 |
+
elif t == "choice":
|
| 64 |
+
o[qtext] = {"choice": names[j], "confidence": round(p[j], 4), "type": "choice",
|
| 65 |
+
"probabilities": {k: round(v, 4) for k, v in zip(names, p)}}
|
| 66 |
+
else:
|
| 67 |
+
keys = q["_keys"]; score = sum(float(k) * pi for k, pi in zip(keys, p))
|
| 68 |
+
o[qtext] = {"score": round(score, 2), "confidence": round(p[j], 4), "type": "scale", "legend": q["_legend"],
|
| 69 |
+
"probabilities": {str(keys[i]): round(pi, 4) for i, pi in enumerate(p)}}
|
| 70 |
+
return o
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
async def _collect(q):
|
| 74 |
+
"""Continuous batching: take what is already queued and go. While a forward pass runs, new requests pile up and form the
|
| 75 |
+
next batch, so there is no fixed wait at low load (it cost 1.5 ms per request) and full batches at high load.
|
| 76 |
+
DECIDER_BATCH_WAIT_MS > 0 restores a short collection window."""
|
| 77 |
+
batch = [await q.get()]; deadline = time.monotonic() + BATCH_WAIT_MS / 1000
|
| 78 |
+
while len(batch) < MAX_BATCH:
|
| 79 |
+
try:
|
| 80 |
+
batch.append(q.get_nowait())
|
| 81 |
+
except asyncio.QueueEmpty:
|
| 82 |
+
timeout = deadline - time.monotonic()
|
| 83 |
+
if timeout <= 0: break
|
| 84 |
+
try: batch.append(await asyncio.wait_for(q.get(), timeout))
|
| 85 |
+
except asyncio.TimeoutError: break
|
| 86 |
+
return batch
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
async def batcher():
|
| 90 |
+
loop = asyncio.get_running_loop()
|
| 91 |
+
while True:
|
| 92 |
+
batch = await _collect(queue)
|
| 93 |
+
# sort by length; split into at most two groups when the spread is large (keeps padding small)
|
| 94 |
+
batch.sort(key=lambda x: len(x[2]["ids"]))
|
| 95 |
+
groups = [batch]
|
| 96 |
+
if len(batch) >= 4:
|
| 97 |
+
lo, hi = len(batch[0][2]["ids"]), len(batch[-1][2]["ids"])
|
| 98 |
+
if _bucket(hi, T_BUCKETS) != _bucket(lo, T_BUCKETS) and hi > 1.5 * lo:
|
| 99 |
+
cut = len(batch) // 2; groups = [batch[:cut], batch[cut:]]
|
| 100 |
+
capped = [] # long rows: keep every forward under MAX_FWD_TOKENS padded tokens
|
| 101 |
+
for g in groups:
|
| 102 |
+
cur = []
|
| 103 |
+
for x in g:
|
| 104 |
+
if cur and (len(cur) + 1) * len(x[2]["ids"]) > MAX_FWD_TOKENS:
|
| 105 |
+
capped.append(cur); cur = []
|
| 106 |
+
cur.append(x)
|
| 107 |
+
capped.append(cur)
|
| 108 |
+
for g in capped:
|
| 109 |
+
items = [it for _, _, it in g]
|
| 110 |
+
try:
|
| 111 |
+
probs = await loop.run_in_executor(None, _locked, eng.score_items, items)
|
| 112 |
+
for (fut, qs, it), p in zip(g, probs):
|
| 113 |
+
if not fut.done(): fut.set_result(p)
|
| 114 |
+
except Exception as e:
|
| 115 |
+
for fut, _, _ in g:
|
| 116 |
+
if not fut.done(): fut.set_exception(e)
|
| 117 |
+
stats["batches"] += 1; stats["batch_hist"][len(g)] = stats["batch_hist"].get(len(g), 0) + 1
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
@app.on_event("startup")
|
| 121 |
+
async def _start():
|
| 122 |
+
global eng, queue
|
| 123 |
+
eng = Engine(MODEL, compile=COMPILE, fp8=FP8, conv_patch=COMPILE); print("[serve] engine", eng.cfg, flush=True)
|
| 124 |
+
import json
|
| 125 |
+
global MODEL_NAME, TEMP
|
| 126 |
+
try: cfg = json.load(open(os.path.join(MODEL, "decider_config.json")))
|
| 127 |
+
except Exception: cfg = {}
|
| 128 |
+
eng.neutralize_none = bool(cfg.get("neutralize_none", True)); MODEL_NAME = "decider-" + str(cfg.get("version", "dev"))
|
| 129 |
+
TEMP = float(os.environ.get("DECIDER_TEMPERATURE", cfg.get("temperature", 1.0)))
|
| 130 |
+
global RELEASE_DATE; RELEASE_DATE = str(cfg.get("release_date", RELEASE_DATE))
|
| 131 |
+
global SCHEMA_FIRST, se, squeue, ISOLATED
|
| 132 |
+
ISOLATED = bool(cfg.get("isolated_levels", False))
|
| 133 |
+
# the schema cache needs the questions-first layout, which costs accuracy (about 1.5 points on fixed label sets, more on large
|
| 134 |
+
# label sets and long states): on when the model's config makes it the default, or with DECIDER_SCHEMA_CACHE=1
|
| 135 |
+
trained = bool(cfg.get("schema_first", False) or cfg.get("schema_first_trained", False))
|
| 136 |
+
SCHEMA_FIRST = trained and (bool(cfg.get("schema_first", False)) or os.environ.get("DECIDER_SCHEMA_CACHE", "0") == "1")
|
| 137 |
+
global TEMP_SCHEMA; TEMP_SCHEMA = float(cfg.get("temperature_schema_first", TEMP))
|
| 138 |
+
if SCHEMA_FIRST:
|
| 139 |
+
from decider.schema_engine import SchemaEngine
|
| 140 |
+
se = SchemaEngine(eng); squeue = asyncio.Queue(); asyncio.create_task(schema_batcher()); print("[serve] schema cache on", flush=True)
|
| 141 |
+
pre = os.environ.get("DECIDER_SCHEMAS") # JSON file: [{"questions": {...}, "independent": true, "batch_sizes": [1, 8, 32], "state_tokens": [64, 256]}]
|
| 142 |
+
for spec in (json.load(open(pre)) if pre else []): # known schemas: prefix computed, graphs compiled and captured before traffic
|
| 143 |
+
_, h, _ = _schema_handle(spec["questions"], spec.get("independent", True), compile=COMPILE)
|
| 144 |
+
t = se.warmup(h, spec.get("batch_sizes", (1, 8, 32)), spec.get("state_tokens", (64, 128, 256)))
|
| 145 |
+
print(f"[serve] preloaded schema with {h.nq} rows, prefix {sum(h.tps)} tokens, graphs ready in {t:.0f}s", flush=True)
|
| 146 |
+
shapes = [(B, T) for B in (1, 2, 4, 8, 16, 32) for T in T_BUCKETS if T <= eng.max_ctx + 256]
|
| 147 |
+
if MAX_BATCH > 32: shapes += [(64, T) for T in T_BUCKETS if T <= 512]
|
| 148 |
+
t = eng.warmup(shapes); print(f"[serve] captured {len(shapes)} graphs in {t:.0f}s", flush=True)
|
| 149 |
+
queue = asyncio.Queue()
|
| 150 |
+
asyncio.create_task(batcher())
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
@app.post("/decide")
|
| 154 |
+
async def decide(r: Req):
|
| 155 |
+
qs, it = await asyncio.get_running_loop().run_in_executor(None, _prepare, r.context, r.schema_)
|
| 156 |
+
fut = asyncio.get_running_loop().create_future()
|
| 157 |
+
await queue.put((fut, qs, it))
|
| 158 |
+
probs = await fut
|
| 159 |
+
stats["requests"] += 1; stats["decisions"] += len(qs)
|
| 160 |
+
return _format(r.schema_, qs, probs)
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
SCHEMA_FIRST = False; se = None; squeue = None; schemas = {} # schema cache (models trained on the questions-first layout, v7+)
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
ISOLATED = False
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
def _schema_handle(questions, independent, compile=False):
|
| 170 |
+
"""Compile (or look up) the question schema: its prefix is run once, requests then only run the state."""
|
| 171 |
+
import json
|
| 172 |
+
key = (json.dumps(questions, sort_keys=True, ensure_ascii=False), independent)
|
| 173 |
+
if key not in schemas:
|
| 174 |
+
rqs = {k: S1.render_question(v) for k, v in questions.items()}; rows, index = S1.plan_rows(rqs, ISOLATED and independent)
|
| 175 |
+
with gpu_lock:
|
| 176 |
+
if len(schemas) >= 128:
|
| 177 |
+
old = next(iter(schemas)); hid = schemas.pop(old)[1].id
|
| 178 |
+
for k in [k for k in se.graphs if k[0] == hid]: del se.graphs[k]
|
| 179 |
+
h = se.prepare(rows, independent=independent, compile=compile)
|
| 180 |
+
schemas[key] = (rqs, h, index)
|
| 181 |
+
return schemas[key]
|
| 182 |
+
|
| 183 |
+
|
| 184 |
+
seen = {}
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
def _worth_caching(questions, independent):
|
| 188 |
+
"""A schema gets a cached prefix and CUDA graphs from its second request on: one-off schemas go through the generic
|
| 189 |
+
state-first engine, whose graphs do not depend on the questions, so ad-hoc traffic cannot thrash graph captures."""
|
| 190 |
+
import json
|
| 191 |
+
key = (json.dumps(questions, sort_keys=True, ensure_ascii=False), independent)
|
| 192 |
+
if key in schemas: return True
|
| 193 |
+
if len(seen) > 50000: seen.clear()
|
| 194 |
+
seen[key] = seen.get(key, 0) + 1
|
| 195 |
+
return seen[key] >= int(os.environ.get("DECIDER_SCHEMA_MIN_SEEN", "2"))
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
def _score_schema(h, rows):
|
| 199 |
+
with gpu_lock:
|
| 200 |
+
return se.score_rows(h, rows, temperature=TEMP_SCHEMA)
|
| 201 |
+
|
| 202 |
+
|
| 203 |
+
async def schema_batcher():
|
| 204 |
+
"""Requests that share a schema and arrive within the window are scored in one forward pass over their states."""
|
| 205 |
+
loop = asyncio.get_running_loop()
|
| 206 |
+
while True:
|
| 207 |
+
batch = await _collect(squeue)
|
| 208 |
+
groups = {} # one forward per (schema, length bucket): short states are not padded to long ones
|
| 209 |
+
for fut, h, row in batch: groups.setdefault((h.id, se.bucket(len(row[0]))), (h, []))[1].append((fut, row))
|
| 210 |
+
for h, items in groups.values():
|
| 211 |
+
step = max(1, MAX_BATCH // h.P)
|
| 212 |
+
for i in range(0, len(items), step):
|
| 213 |
+
chunk = items[i:i + step]
|
| 214 |
+
try:
|
| 215 |
+
probs = await loop.run_in_executor(None, _score_schema, h, [c for _, c in chunk])
|
| 216 |
+
for (fut, _), p in zip(chunk, probs):
|
| 217 |
+
if not fut.done(): fut.set_result(p)
|
| 218 |
+
except Exception as e:
|
| 219 |
+
for fut, _ in chunk:
|
| 220 |
+
if not fut.done(): fut.set_exception(e)
|
| 221 |
+
stats["schema_batches"] = stats.get("schema_batches", 0) + 1
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
def _locked(fn, items):
|
| 225 |
+
with gpu_lock:
|
| 226 |
+
return fn(items, temperature=TEMP) # fitted temperature from decider_config.json
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
class S1Req(BaseModel):
|
| 230 |
+
state: object
|
| 231 |
+
questions: dict
|
| 232 |
+
model: str | None = None
|
| 233 |
+
independent: bool = True
|
| 234 |
+
layout: str | None = None # "state_first" forces the uncached layout on a schema-first model
|
| 235 |
+
|
| 236 |
+
|
| 237 |
+
def _prepare_s1(state, questions, independent):
|
| 238 |
+
ctx = S1.render_state(state); rqs = {k: S1.render_question(v) for k, v in questions.items()}
|
| 239 |
+
flat, index = S1.plan_rows(rqs, ISOLATED and independent)
|
| 240 |
+
rows = [[r] for r in flat] if independent else [flat]
|
| 241 |
+
items = [build(Example(ctx, [Q(r["question"], list(r["options"]), 0) for r in row]), eng.tok, _NoShuffle(), max_options=MAX_OPTIONS,
|
| 242 |
+
max_ctx_tokens=MAX_STATE_TOKENS) for row in rows]
|
| 243 |
+
return (rqs, index), items
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
@app.post("/v1/systemone")
|
| 247 |
+
async def systemone(r: S1Req):
|
| 248 |
+
loop = asyncio.get_running_loop()
|
| 249 |
+
if SCHEMA_FIRST and r.layout != "state_first" and _worth_caching(r.questions, r.independent):
|
| 250 |
+
try:
|
| 251 |
+
rqs, h, index = await loop.run_in_executor(None, _schema_handle, r.questions, r.independent)
|
| 252 |
+
except ValueError as e:
|
| 253 |
+
raise HTTPException(422, str(e))
|
| 254 |
+
row = await loop.run_in_executor(None, lambda: se.tokenize(h, S1.render_state(r.state), MAX_STATE_TOKENS)) # CPU work stays off the GPU lock
|
| 255 |
+
fut = loop.create_future(); await squeue.put((fut, h, row)); p = await fut
|
| 256 |
+
stats["requests"] += 1; stats["decisions"] += len(rqs); stats["schema_requests"] = stats.get("schema_requests", 0) + 1
|
| 257 |
+
return {"model": MODEL_NAME, "answers": S1.assemble(rqs, index, [pk.tolist() for pk in p]),
|
| 258 |
+
"usage": {"input_tokens": len(row[0]) * h.P, "cached_tokens": sum(h.tps), "output_tokens": 0}}
|
| 259 |
+
try:
|
| 260 |
+
(rqs, index), items = await loop.run_in_executor(None, _prepare_s1, r.state, r.questions, r.independent)
|
| 261 |
+
except ValueError as e:
|
| 262 |
+
raise HTTPException(422, str(e))
|
| 263 |
+
if len(items) > 1 and min(len(it["ids"]) for it in items) >= SHARED_MIN_TOKENS:
|
| 264 |
+
res = await loop.run_in_executor(None, _locked, eng.score_shared, items) # long state: run it once, fork the cache per question
|
| 265 |
+
stats["shared_prefix_requests"] = stats.get("shared_prefix_requests", 0) + 1
|
| 266 |
+
else:
|
| 267 |
+
futs = []
|
| 268 |
+
for it in items:
|
| 269 |
+
f = loop.create_future(); futs.append(f); await queue.put((f, None, it))
|
| 270 |
+
res = await asyncio.gather(*futs)
|
| 271 |
+
probs = [p for ps in res for p in ps] # one prob row per question, request order
|
| 272 |
+
stats["requests"] += 1; stats["decisions"] += len(rqs)
|
| 273 |
+
return {"model": MODEL_NAME, "answers": S1.assemble(rqs, index, [p.tolist() for p in probs]),
|
| 274 |
+
"usage": {"input_tokens": S1.unique_tokens(items), "output_tokens": 0}}
|
| 275 |
+
|
| 276 |
+
|
| 277 |
+
@app.get("/v1/models")
|
| 278 |
+
async def models():
|
| 279 |
+
return {"models": [{"name": MODEL_NAME, "description": "decider: one-pass typed decisions with calibrated probabilities", "release_date": RELEASE_DATE}]}
|
| 280 |
+
|
| 281 |
+
|
| 282 |
+
@app.get("/health")
|
| 283 |
+
async def health():
|
| 284 |
+
return {"ok": eng is not None, "model": MODEL}
|
| 285 |
+
|
| 286 |
+
|
| 287 |
+
@app.get("/stats")
|
| 288 |
+
async def get_stats():
|
| 289 |
+
return dict(stats, engine=eng.stats if eng else None, graphs=len(eng.graphs) if eng else 0)
|
decider/systemone.py
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Jev-shaped requests on top of the decider prompt format (same wire format as TypeSafe's POST /v1/systemone).
|
| 2 |
+
|
| 3 |
+
state str | dict | list JSON state is serialised compactly; questions may name a part by path (`ticket.messages[0].text`)
|
| 4 |
+
questions {id: {"type": "choice", "instructions": ..., "criteria": {name: description | {...} | [...] | None}} up to 255 options
|
| 5 |
+
{"type": "score", "instructions": ..., "criteria": [level 0 description, level 1 description, ...]} 2..10 levels
|
| 6 |
+
{"type": "noul", "instructions": ..., "criteria": {"true": ..., "false": ...} (optional)}}
|
| 7 |
+
ids are never shown to the model. `instructions` and every description may be a string or any JSON value.
|
| 8 |
+
"""
|
| 9 |
+
import json, math
|
| 10 |
+
|
| 11 |
+
MAX_CHOICE, MAX_LEVELS = 255, 10
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def _txt(v):
|
| 15 |
+
return v if isinstance(v, str) else json.dumps(v, ensure_ascii=False)
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
ANNOTATE_MIN = 8
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def annotate_indices(x, min_len=ANNOTATE_MIN):
|
| 22 |
+
"""Write each element's position into long arrays ({"_index": i, ...}). A path such as `records[47].text` otherwise makes
|
| 23 |
+
the model count 47 elements; with the index written down it is a lookup (json_k64 probe: 0.49 -> 0.57 accuracy)."""
|
| 24 |
+
if isinstance(x, list):
|
| 25 |
+
if len(x) >= min_len:
|
| 26 |
+
return [({"_index": i, **annotate_indices(v, min_len)} if isinstance(v, dict) else {"_index": i, "value": annotate_indices(v, min_len)}) for i, v in enumerate(x)]
|
| 27 |
+
return [annotate_indices(v, min_len) for v in x]
|
| 28 |
+
if isinstance(x, dict):
|
| 29 |
+
return {k: annotate_indices(v, min_len) for k, v in x.items()}
|
| 30 |
+
return x
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def render_state(state, index_arrays=True):
|
| 34 |
+
if isinstance(state, str):
|
| 35 |
+
return state
|
| 36 |
+
return json.dumps(annotate_indices(state) if index_arrays else state, ensure_ascii=False)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def render_question(spec):
|
| 40 |
+
"""-> dict(question=str, options=[str], type=..., names=[...]) (names: what the answer reports for each option)"""
|
| 41 |
+
t = spec.get("type", "choice"); ins = _txt(spec.get("instructions", spec.get("question", ""))); crit = spec.get("criteria", spec.get("options"))
|
| 42 |
+
if not ins:
|
| 43 |
+
raise ValueError("question without instructions")
|
| 44 |
+
if t == "choice":
|
| 45 |
+
if isinstance(crit, (list, tuple)):
|
| 46 |
+
crit = {str(c): None for c in crit}
|
| 47 |
+
if not isinstance(crit, dict) or not 2 <= len(crit) <= MAX_CHOICE:
|
| 48 |
+
raise ValueError(f"choice criteria: a map of 2..{MAX_CHOICE} options")
|
| 49 |
+
names = list(crit); opts = [n if crit[n] in (None, "") else f"{n}: {_txt(crit[n])}" for n in names]
|
| 50 |
+
elif t == "score":
|
| 51 |
+
if isinstance(crit, dict): # legend form {"0": "...", "1": "..."}
|
| 52 |
+
crit = [crit[k] for k in sorted(crit, key=float)]
|
| 53 |
+
if not isinstance(crit, (list, tuple)) or not 2 <= len(crit) <= MAX_LEVELS:
|
| 54 |
+
raise ValueError(f"score criteria: an ordered list of 2..{MAX_LEVELS} level descriptions")
|
| 55 |
+
names = list(range(len(crit))); opts = [f"{i}: {_txt(c)}" for i, c in enumerate(crit)]
|
| 56 |
+
elif t in ("noul", "bool"):
|
| 57 |
+
names = [False, True]; c = crit or {}
|
| 58 |
+
f, tr = c.get("false", c.get(False)), c.get("true", c.get(True))
|
| 59 |
+
opts = ["no" if f in (None, "") else f"no: {_txt(f)}", "yes" if tr in (None, "") else f"yes: {_txt(tr)}"]
|
| 60 |
+
else:
|
| 61 |
+
raise ValueError(f"unknown question type {t!r}")
|
| 62 |
+
return dict(question=ins, options=opts, type="noul" if t == "bool" else t, names=names, legend=[_txt(c) for c in crit] if t == "score" else None,
|
| 63 |
+
isolated=bool(spec.get("isolated", True)))
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
# ---- isolated levels: every Score level is judged in its own row, without its number or its neighbours
|
| 67 |
+
ISOLATED = "{q}\nProposed answer: {level}\nDoes the proposed answer fit?"
|
| 68 |
+
_NUM = None
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
def strip_level_number(text):
|
| 72 |
+
""""2: somewhat" -> "somewhat" (dataset legends carry the number; an isolated level must not)."""
|
| 73 |
+
import re
|
| 74 |
+
return re.sub(r"^\s*-?\d+\s*:\s*", "", text)
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def isolated_rows(question, levels):
|
| 78 |
+
"""-> one yes/no question per level: [(question text, ["no", "yes"])]."""
|
| 79 |
+
return [(ISOLATED.format(q=question, level=strip_level_number(l)), ["no", "yes"]) for l in levels]
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def combine_isolated(p_yes):
|
| 83 |
+
"""Per-level P(fits), each computed without reference to any other level -> a distribution over levels.
|
| 84 |
+
Also returns the unnormalised mass: near 1 when exactly one level fits, low when none does, high when several do."""
|
| 85 |
+
tot = sum(p_yes) or 1e-9
|
| 86 |
+
return [x / tot for x in p_yes], tot
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
def plan_rows(rqs, isolated=True):
|
| 90 |
+
"""One scoring row per question; a Score question with isolated levels becomes one yes/no row per level.
|
| 91 |
+
-> (rows [{"question", "options"}], index [(id, "iso" | "list", first row, n rows)])"""
|
| 92 |
+
rows, index = [], []
|
| 93 |
+
for k, r in rqs.items():
|
| 94 |
+
if isolated and r["type"] == "score" and r.get("isolated", True):
|
| 95 |
+
rws = isolated_rows(r["question"], r["legend"]); index.append((k, "iso", len(rows), len(rws))); rows += [dict(question=t, options=o) for t, o in rws]
|
| 96 |
+
else:
|
| 97 |
+
index.append((k, "list", len(rows), 1)); rows.append(dict(question=r["question"], options=r["options"]))
|
| 98 |
+
return rows, index
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
def assemble(rqs, index, probs):
|
| 102 |
+
"""probs: one probability list per row (plan_rows order) -> {id: answer}."""
|
| 103 |
+
out = {}
|
| 104 |
+
for k, kind, s, n in index:
|
| 105 |
+
if kind == "iso":
|
| 106 |
+
fit = [float(probs[s + j][1]) for j in range(n)]; p, mass = combine_isolated(fit); a = format_answer(rqs[k], p)
|
| 107 |
+
a["level_fit"] = {str(j): round(x, 4) for j, x in enumerate(fit)}; a["fit_mass"] = round(mass, 4); out[k] = a
|
| 108 |
+
else:
|
| 109 |
+
out[k] = format_answer(rqs[k], probs[s])
|
| 110 |
+
return out
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def certainty(p):
|
| 114 |
+
"""1 - normalised entropy: 1 when all mass is on one option, 0 when the distribution is flat."""
|
| 115 |
+
h = -sum(x * math.log(x) for x in p if x > 0)
|
| 116 |
+
return max(0.0, 1.0 - h / math.log(len(p))) if len(p) > 1 else 1.0
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
def format_answer(rq, p, nd=4):
|
| 120 |
+
"""rq: render_question output; p: probabilities in option order."""
|
| 121 |
+
p = [float(x) for x in p[:len(rq["options"])]]; s = sum(p) or 1.0; p = [x / s for x in p]
|
| 122 |
+
j = max(range(len(p)), key=p.__getitem__)
|
| 123 |
+
if rq["type"] == "noul":
|
| 124 |
+
return {"type": "noul", "noul": round(p[1], nd)}
|
| 125 |
+
if rq["type"] == "choice":
|
| 126 |
+
return {"type": "choice", "choice": rq["names"][j], "confidence": round(p[j], nd), "certainty": round(certainty(p), nd),
|
| 127 |
+
"probabilities": {n: round(x, nd) for n, x in zip(rq["names"], p)}}
|
| 128 |
+
return {"type": "score", "score": round(sum(i * x for i, x in enumerate(p)), 2), "confidence": round(p[j], nd), "certainty": round(certainty(p), nd),
|
| 129 |
+
"legend": {str(i): d for i, d in enumerate(rq["legend"])}, "probabilities": {str(i): round(x, nd) for i, x in enumerate(p)}}
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
def unique_tokens(items):
|
| 133 |
+
"""Input tokens of a request whose rows share a prefix (the state): the prefix counts once."""
|
| 134 |
+
ids = [it["ids"] for it in items]
|
| 135 |
+
if len(ids) < 2:
|
| 136 |
+
return sum(len(x) for x in ids)
|
| 137 |
+
lcp = 0; short = min(len(x) for x in ids)
|
| 138 |
+
while lcp < short and all(x[lcp] == ids[0][lcp] for x in ids): lcp += 1
|
| 139 |
+
return lcp + sum(len(x) - lcp for x in ids)
|
decider_config.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"temperature": 1.08,
|
| 3 |
+
"neutralize_none": false,
|
| 4 |
+
"version": "35b-a3b-v1",
|
| 5 |
+
"base": "Qwen/Qwen3.5-35B-A3B-Base",
|
| 6 |
+
"max_options": 255,
|
| 7 |
+
"max_state_tokens": 32768,
|
| 8 |
+
"schema_first": false,
|
| 9 |
+
"schema_first_trained": true,
|
| 10 |
+
"isolated_levels": true,
|
| 11 |
+
"release_date": "2026-09-20",
|
| 12 |
+
"stage": "one public-mixture epoch (463M tokens) with Muon, routed experts frozen; runs/moe_optimizer_ab_v1/muon step 16287; temperature fitted on the in-task regression half"
|
| 13 |
+
}
|
eval_results.json
ADDED
|
@@ -0,0 +1,1298 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model": "decider-35b-a3b v1",
|
| 3 |
+
"temperature": 1.075,
|
| 4 |
+
"protocol": "public regression set rebuilt on this machine: eval half of data/mixture_full.pkl, 95 tasks (67 in-task / 28 held-out), state-first layout, max_ctx 1536, large label sets sub-sampled to 10 options; metrics at the stored temperature",
|
| 5 |
+
"aggregate": {
|
| 6 |
+
"in_task": {
|
| 7 |
+
"acc": 0.8551758035695551,
|
| 8 |
+
"nll": 0.3571210244530074,
|
| 9 |
+
"ece": 0.026005523425337858
|
| 10 |
+
},
|
| 11 |
+
"heldout": {
|
| 12 |
+
"acc": 0.8104967349952829,
|
| 13 |
+
"nll": 0.4970387108931333,
|
| 14 |
+
"ece": 0.06886512604372556
|
| 15 |
+
}
|
| 16 |
+
},
|
| 17 |
+
"results": {
|
| 18 |
+
"clinc_oos": {
|
| 19 |
+
"n": 1500,
|
| 20 |
+
"heldout": false,
|
| 21 |
+
"acc": 0.9826666666666667,
|
| 22 |
+
"nll": 0.06116773560643196,
|
| 23 |
+
"brier": 0.026913650333881378,
|
| 24 |
+
"ece": 0.004699912309646655,
|
| 25 |
+
"aurc": 0.001413522036819675,
|
| 26 |
+
"acc_at_80": 0.9975,
|
| 27 |
+
"acc_at_50": 1.0,
|
| 28 |
+
"chance": 0.1,
|
| 29 |
+
"mean_conf": 0.9831148982048035
|
| 30 |
+
},
|
| 31 |
+
"banking77": {
|
| 32 |
+
"n": 1500,
|
| 33 |
+
"heldout": false,
|
| 34 |
+
"acc": 0.9866666666666667,
|
| 35 |
+
"nll": 0.051965903490781784,
|
| 36 |
+
"brier": 0.022627051919698715,
|
| 37 |
+
"ece": 0.016074508627255804,
|
| 38 |
+
"aurc": 0.0006460488654478452,
|
| 39 |
+
"acc_at_80": 0.9991666666666666,
|
| 40 |
+
"acc_at_50": 1.0,
|
| 41 |
+
"chance": 0.1,
|
| 42 |
+
"mean_conf": 0.9768534898757935
|
| 43 |
+
},
|
| 44 |
+
"massive_intent": {
|
| 45 |
+
"n": 1500,
|
| 46 |
+
"heldout": false,
|
| 47 |
+
"acc": 0.9633333333333334,
|
| 48 |
+
"nll": 0.11785730719566345,
|
| 49 |
+
"brier": 0.0557381696999073,
|
| 50 |
+
"ece": 0.008312105695406588,
|
| 51 |
+
"aurc": 0.0031118976074550235,
|
| 52 |
+
"acc_at_80": 0.9966666666666667,
|
| 53 |
+
"acc_at_50": 0.9986666666666667,
|
| 54 |
+
"chance": 0.1,
|
| 55 |
+
"mean_conf": 0.9660524129867554
|
| 56 |
+
},
|
| 57 |
+
"massive_scenario": {
|
| 58 |
+
"n": 1500,
|
| 59 |
+
"heldout": true,
|
| 60 |
+
"acc": 0.7993333333333333,
|
| 61 |
+
"nll": 0.5332828760147095,
|
| 62 |
+
"brier": 0.271218866109848,
|
| 63 |
+
"ece": 0.02829863039652506,
|
| 64 |
+
"aurc": 0.055478553769578394,
|
| 65 |
+
"acc_at_80": 0.8808333333333334,
|
| 66 |
+
"acc_at_50": 0.9733333333333334,
|
| 67 |
+
"chance": 0.1,
|
| 68 |
+
"mean_conf": 0.7986482977867126
|
| 69 |
+
},
|
| 70 |
+
"bitext_support": {
|
| 71 |
+
"n": 3000,
|
| 72 |
+
"heldout": false,
|
| 73 |
+
"acc": 0.9993333333333333,
|
| 74 |
+
"nll": 0.0021056807599961758,
|
| 75 |
+
"brier": 0.0011287310626357794,
|
| 76 |
+
"ece": 0.0003376175860563954,
|
| 77 |
+
"aurc": 1.1120011870401867e-06,
|
| 78 |
+
"acc_at_80": 1.0,
|
| 79 |
+
"acc_at_50": 1.0,
|
| 80 |
+
"chance": 0.09999999999999998,
|
| 81 |
+
"mean_conf": 0.9992170333862305
|
| 82 |
+
},
|
| 83 |
+
"support_tickets": {
|
| 84 |
+
"n": 4500,
|
| 85 |
+
"heldout": false,
|
| 86 |
+
"acc": 0.5933333333333334,
|
| 87 |
+
"nll": 0.9494668245315552,
|
| 88 |
+
"brier": 0.5020924210548401,
|
| 89 |
+
"ece": 0.017903674913777236,
|
| 90 |
+
"aurc": 0.20277115689216718,
|
| 91 |
+
"acc_at_80": 0.6583333333333333,
|
| 92 |
+
"acc_at_50": 0.7777777777777778,
|
| 93 |
+
"chance": 0.22777777777777777,
|
| 94 |
+
"mean_conf": 0.5856716632843018
|
| 95 |
+
},
|
| 96 |
+
"ag_news": {
|
| 97 |
+
"n": 1500,
|
| 98 |
+
"heldout": false,
|
| 99 |
+
"acc": 0.9346666666666666,
|
| 100 |
+
"nll": 0.20106011629104614,
|
| 101 |
+
"brier": 0.10288789123296738,
|
| 102 |
+
"ece": 0.010400939603646572,
|
| 103 |
+
"aurc": 0.013618430266727854,
|
| 104 |
+
"acc_at_80": 0.9783333333333334,
|
| 105 |
+
"acc_at_50": 0.9893333333333333,
|
| 106 |
+
"chance": 0.25,
|
| 107 |
+
"mean_conf": 0.9317083358764648
|
| 108 |
+
},
|
| 109 |
+
"dbpedia": {
|
| 110 |
+
"n": 1500,
|
| 111 |
+
"heldout": false,
|
| 112 |
+
"acc": 0.9926666666666667,
|
| 113 |
+
"nll": 0.019056648015975952,
|
| 114 |
+
"brier": 0.010244570672512054,
|
| 115 |
+
"ece": 0.00390036821365361,
|
| 116 |
+
"aurc": 6.964876547762933e-05,
|
| 117 |
+
"acc_at_80": 1.0,
|
| 118 |
+
"acc_at_50": 1.0,
|
| 119 |
+
"chance": 0.1,
|
| 120 |
+
"mean_conf": 0.9953445792198181
|
| 121 |
+
},
|
| 122 |
+
"yahoo_topics": {
|
| 123 |
+
"n": 1500,
|
| 124 |
+
"heldout": false,
|
| 125 |
+
"acc": 0.7726666666666666,
|
| 126 |
+
"nll": 0.6962489485740662,
|
| 127 |
+
"brier": 0.3215087354183197,
|
| 128 |
+
"ece": 0.04092799503604572,
|
| 129 |
+
"aurc": 0.07648607099774656,
|
| 130 |
+
"acc_at_80": 0.86,
|
| 131 |
+
"acc_at_50": 0.944,
|
| 132 |
+
"chance": 0.1,
|
| 133 |
+
"mean_conf": 0.7425376176834106
|
| 134 |
+
},
|
| 135 |
+
"newsgroups": {
|
| 136 |
+
"n": 1462,
|
| 137 |
+
"heldout": false,
|
| 138 |
+
"acc": 0.8502051983584131,
|
| 139 |
+
"nll": 0.449008584022522,
|
| 140 |
+
"brier": 0.21066278219223022,
|
| 141 |
+
"ece": 0.03997525807199984,
|
| 142 |
+
"aurc": 0.026273657246117587,
|
| 143 |
+
"acc_at_80": 0.9435897435897436,
|
| 144 |
+
"acc_at_50": 0.9931600547195623,
|
| 145 |
+
"chance": 0.09999999999999999,
|
| 146 |
+
"mean_conf": 0.88435298204422
|
| 147 |
+
},
|
| 148 |
+
"bbc_news": {
|
| 149 |
+
"n": 1000,
|
| 150 |
+
"heldout": true,
|
| 151 |
+
"acc": 0.944,
|
| 152 |
+
"nll": 0.13256792724132538,
|
| 153 |
+
"brier": 0.07240951806306839,
|
| 154 |
+
"ece": 0.027219559907913193,
|
| 155 |
+
"aurc": 0.004171691057266529,
|
| 156 |
+
"acc_at_80": 0.995,
|
| 157 |
+
"acc_at_50": 1.0,
|
| 158 |
+
"chance": 0.20000000000000004,
|
| 159 |
+
"mean_conf": 0.9385547637939453
|
| 160 |
+
},
|
| 161 |
+
"trec": {
|
| 162 |
+
"n": 500,
|
| 163 |
+
"heldout": true,
|
| 164 |
+
"acc": 0.832,
|
| 165 |
+
"nll": 0.587404727935791,
|
| 166 |
+
"brier": 0.28857845067977905,
|
| 167 |
+
"ece": 0.1598434355854988,
|
| 168 |
+
"aurc": 0.06672534257121955,
|
| 169 |
+
"acc_at_80": 0.8925,
|
| 170 |
+
"acc_at_50": 0.952,
|
| 171 |
+
"chance": 0.16666666666666663,
|
| 172 |
+
"mean_conf": 0.6734781265258789
|
| 173 |
+
},
|
| 174 |
+
"student_questions": {
|
| 175 |
+
"n": 1500,
|
| 176 |
+
"heldout": true,
|
| 177 |
+
"acc": 0.954,
|
| 178 |
+
"nll": 0.2031065672636032,
|
| 179 |
+
"brier": 0.08712532371282578,
|
| 180 |
+
"ece": 0.08987796316544214,
|
| 181 |
+
"aurc": 0.006595183463977914,
|
| 182 |
+
"acc_at_80": 0.9916666666666667,
|
| 183 |
+
"acc_at_50": 0.9933333333333333,
|
| 184 |
+
"chance": 0.25,
|
| 185 |
+
"mean_conf": 0.865302562713623
|
| 186 |
+
},
|
| 187 |
+
"dolly_category": {
|
| 188 |
+
"n": 1500,
|
| 189 |
+
"heldout": true,
|
| 190 |
+
"acc": 0.354,
|
| 191 |
+
"nll": 1.631442666053772,
|
| 192 |
+
"brier": 0.7210286259651184,
|
| 193 |
+
"ece": 0.09806547661622367,
|
| 194 |
+
"aurc": 0.4519247410276184,
|
| 195 |
+
"acc_at_80": 0.38666666666666666,
|
| 196 |
+
"acc_at_50": 0.47333333333333333,
|
| 197 |
+
"chance": 0.125,
|
| 198 |
+
"mean_conf": 0.4256460666656494
|
| 199 |
+
},
|
| 200 |
+
"imdb": {
|
| 201 |
+
"n": 1500,
|
| 202 |
+
"heldout": false,
|
| 203 |
+
"acc": 0.9706666666666667,
|
| 204 |
+
"nll": 0.0796746090054512,
|
| 205 |
+
"brier": 0.04415109381079674,
|
| 206 |
+
"ece": 0.009556351860364288,
|
| 207 |
+
"aurc": 0.0021247781519913296,
|
| 208 |
+
"acc_at_80": 0.9966666666666667,
|
| 209 |
+
"acc_at_50": 1.0,
|
| 210 |
+
"chance": 0.5,
|
| 211 |
+
"mean_conf": 0.9738101959228516
|
| 212 |
+
},
|
| 213 |
+
"sst2": {
|
| 214 |
+
"n": 872,
|
| 215 |
+
"heldout": false,
|
| 216 |
+
"acc": 0.963302752293578,
|
| 217 |
+
"nll": 0.1075686514377594,
|
| 218 |
+
"brier": 0.058069903403520584,
|
| 219 |
+
"ece": 0.007435061174248355,
|
| 220 |
+
"aurc": 0.004894615707237302,
|
| 221 |
+
"acc_at_80": 0.9914040114613181,
|
| 222 |
+
"acc_at_50": 0.9977064220183486,
|
| 223 |
+
"chance": 0.5,
|
| 224 |
+
"mean_conf": 0.9640254974365234
|
| 225 |
+
},
|
| 226 |
+
"sst5": {
|
| 227 |
+
"n": 1500,
|
| 228 |
+
"heldout": false,
|
| 229 |
+
"acc": 0.6326666666666667,
|
| 230 |
+
"nll": 0.8465693593025208,
|
| 231 |
+
"brier": 0.5005199313163757,
|
| 232 |
+
"ece": 0.02862738460302352,
|
| 233 |
+
"aurc": 0.30424582658146127,
|
| 234 |
+
"acc_at_80": 0.6608333333333334,
|
| 235 |
+
"acc_at_50": 0.6973333333333334,
|
| 236 |
+
"chance": 0.2,
|
| 237 |
+
"mean_conf": 0.6309818625450134
|
| 238 |
+
},
|
| 239 |
+
"yelp": {
|
| 240 |
+
"n": 1500,
|
| 241 |
+
"heldout": false,
|
| 242 |
+
"acc": 0.7266666666666667,
|
| 243 |
+
"nll": 0.6343568563461304,
|
| 244 |
+
"brier": 0.37920209765434265,
|
| 245 |
+
"ece": 0.04076567333936691,
|
| 246 |
+
"aurc": 0.13746089140338316,
|
| 247 |
+
"acc_at_80": 0.7716666666666666,
|
| 248 |
+
"acc_at_50": 0.8533333333333334,
|
| 249 |
+
"chance": 0.2,
|
| 250 |
+
"mean_conf": 0.739836573600769
|
| 251 |
+
},
|
| 252 |
+
"amazon_stars": {
|
| 253 |
+
"n": 1500,
|
| 254 |
+
"heldout": false,
|
| 255 |
+
"acc": 0.6213333333333333,
|
| 256 |
+
"nll": 0.8520724177360535,
|
| 257 |
+
"brier": 0.4818972945213318,
|
| 258 |
+
"ece": 0.03010182730356851,
|
| 259 |
+
"aurc": 0.21266833331300722,
|
| 260 |
+
"acc_at_80": 0.6741666666666667,
|
| 261 |
+
"acc_at_50": 0.7693333333333333,
|
| 262 |
+
"chance": 0.2,
|
| 263 |
+
"mean_conf": 0.6432384252548218
|
| 264 |
+
},
|
| 265 |
+
"emotion": {
|
| 266 |
+
"n": 1500,
|
| 267 |
+
"heldout": false,
|
| 268 |
+
"acc": 0.9086666666666666,
|
| 269 |
+
"nll": 0.22119809687137604,
|
| 270 |
+
"brier": 0.12285951524972916,
|
| 271 |
+
"ece": 0.015565859278043073,
|
| 272 |
+
"aurc": 0.012805207153182863,
|
| 273 |
+
"acc_at_80": 0.9808333333333333,
|
| 274 |
+
"acc_at_50": 0.9973333333333333,
|
| 275 |
+
"chance": 0.16666666666666666,
|
| 276 |
+
"mean_conf": 0.9207584857940674
|
| 277 |
+
},
|
| 278 |
+
"go_emotions": {
|
| 279 |
+
"n": 1500,
|
| 280 |
+
"heldout": false,
|
| 281 |
+
"acc": 0.794,
|
| 282 |
+
"nll": 0.5889915227890015,
|
| 283 |
+
"brier": 0.28999069333076477,
|
| 284 |
+
"ece": 0.029260090112686165,
|
| 285 |
+
"aurc": 0.0672639072365525,
|
| 286 |
+
"acc_at_80": 0.8775,
|
| 287 |
+
"acc_at_50": 0.9533333333333334,
|
| 288 |
+
"chance": 0.1,
|
| 289 |
+
"mean_conf": 0.7891288995742798
|
| 290 |
+
},
|
| 291 |
+
"tweet_sentiment": {
|
| 292 |
+
"n": 1500,
|
| 293 |
+
"heldout": false,
|
| 294 |
+
"acc": 0.7393333333333333,
|
| 295 |
+
"nll": 0.5619461536407471,
|
| 296 |
+
"brier": 0.3484695255756378,
|
| 297 |
+
"ece": 0.053492017388343804,
|
| 298 |
+
"aurc": 0.12272191307348365,
|
| 299 |
+
"acc_at_80": 0.8075,
|
| 300 |
+
"acc_at_50": 0.8733333333333333,
|
| 301 |
+
"chance": 0.3333333333333333,
|
| 302 |
+
"mean_conf": 0.706974446773529
|
| 303 |
+
},
|
| 304 |
+
"tweet_emotion": {
|
| 305 |
+
"n": 1421,
|
| 306 |
+
"heldout": false,
|
| 307 |
+
"acc": 0.8648838845883181,
|
| 308 |
+
"nll": 0.3760232925415039,
|
| 309 |
+
"brier": 0.19416743516921997,
|
| 310 |
+
"ece": 0.048255335898738254,
|
| 311 |
+
"aurc": 0.027839586844617643,
|
| 312 |
+
"acc_at_80": 0.9481090589270009,
|
| 313 |
+
"acc_at_50": 0.9887323943661972,
|
| 314 |
+
"chance": 0.25,
|
| 315 |
+
"mean_conf": 0.8190691471099854
|
| 316 |
+
},
|
| 317 |
+
"tweet_irony": {
|
| 318 |
+
"n": 784,
|
| 319 |
+
"heldout": true,
|
| 320 |
+
"acc": 0.860969387755102,
|
| 321 |
+
"nll": 0.3990391194820404,
|
| 322 |
+
"brier": 0.24129782617092133,
|
| 323 |
+
"ece": 0.12924721418898932,
|
| 324 |
+
"aurc": 0.04448957010495625,
|
| 325 |
+
"acc_at_80": 0.9202551834130781,
|
| 326 |
+
"acc_at_50": 0.9642857142857143,
|
| 327 |
+
"chance": 0.5,
|
| 328 |
+
"mean_conf": 0.7329258322715759
|
| 329 |
+
},
|
| 330 |
+
"fin_sentiment": {
|
| 331 |
+
"n": 1500,
|
| 332 |
+
"heldout": true,
|
| 333 |
+
"acc": 0.8386666666666667,
|
| 334 |
+
"nll": 0.46592089533805847,
|
| 335 |
+
"brier": 0.27144962549209595,
|
| 336 |
+
"ece": 0.13573047741254168,
|
| 337 |
+
"aurc": 0.06709094165414199,
|
| 338 |
+
"acc_at_80": 0.8941666666666667,
|
| 339 |
+
"acc_at_50": 0.9466666666666667,
|
| 340 |
+
"chance": 0.3333333333333333,
|
| 341 |
+
"mean_conf": 0.7034342288970947
|
| 342 |
+
},
|
| 343 |
+
"cr_reviews": {
|
| 344 |
+
"n": 753,
|
| 345 |
+
"heldout": true,
|
| 346 |
+
"acc": 0.9136786188579017,
|
| 347 |
+
"nll": 0.1997925043106079,
|
| 348 |
+
"brier": 0.12444894015789032,
|
| 349 |
+
"ece": 0.032485922019320164,
|
| 350 |
+
"aurc": 0.013022305207380291,
|
| 351 |
+
"acc_at_80": 0.978405315614618,
|
| 352 |
+
"acc_at_50": 0.9973404255319149,
|
| 353 |
+
"chance": 0.5,
|
| 354 |
+
"mean_conf": 0.940420389175415
|
| 355 |
+
},
|
| 356 |
+
"counterfactual": {
|
| 357 |
+
"n": 1500,
|
| 358 |
+
"heldout": false,
|
| 359 |
+
"acc": 0.948,
|
| 360 |
+
"nll": 0.12409600615501404,
|
| 361 |
+
"brier": 0.07306990027427673,
|
| 362 |
+
"ece": 0.015566750446955315,
|
| 363 |
+
"aurc": 0.005129710883211171,
|
| 364 |
+
"acc_at_80": 0.995,
|
| 365 |
+
"acc_at_50": 0.9986666666666667,
|
| 366 |
+
"chance": 0.5,
|
| 367 |
+
"mean_conf": 0.9607836008071899
|
| 368 |
+
},
|
| 369 |
+
"subjectivity": {
|
| 370 |
+
"n": 1500,
|
| 371 |
+
"heldout": false,
|
| 372 |
+
"acc": 0.9773333333333334,
|
| 373 |
+
"nll": 0.06512857228517532,
|
| 374 |
+
"brier": 0.03518040478229523,
|
| 375 |
+
"ece": 0.006610139727592426,
|
| 376 |
+
"aurc": 0.001447138121234917,
|
| 377 |
+
"acc_at_80": 0.9983333333333333,
|
| 378 |
+
"acc_at_50": 1.0,
|
| 379 |
+
"chance": 0.5,
|
| 380 |
+
"mean_conf": 0.9769946336746216
|
| 381 |
+
},
|
| 382 |
+
"tweet_offensive": {
|
| 383 |
+
"n": 860,
|
| 384 |
+
"heldout": false,
|
| 385 |
+
"acc": 0.8511627906976744,
|
| 386 |
+
"nll": 0.3344406485557556,
|
| 387 |
+
"brier": 0.20971718430519104,
|
| 388 |
+
"ece": 0.039765768203624464,
|
| 389 |
+
"aurc": 0.041883052711596785,
|
| 390 |
+
"acc_at_80": 0.9171511627906976,
|
| 391 |
+
"acc_at_50": 0.9767441860465116,
|
| 392 |
+
"chance": 0.5,
|
| 393 |
+
"mean_conf": 0.8272612690925598
|
| 394 |
+
},
|
| 395 |
+
"tweet_hate": {
|
| 396 |
+
"n": 1500,
|
| 397 |
+
"heldout": false,
|
| 398 |
+
"acc": 0.564,
|
| 399 |
+
"nll": 1.0489171743392944,
|
| 400 |
+
"brier": 0.6417430639266968,
|
| 401 |
+
"ece": 0.2539481555223465,
|
| 402 |
+
"aurc": 0.3877638717389759,
|
| 403 |
+
"acc_at_80": 0.5816666666666667,
|
| 404 |
+
"acc_at_50": 0.5893333333333334,
|
| 405 |
+
"chance": 0.5,
|
| 406 |
+
"mean_conf": 0.8179481625556946
|
| 407 |
+
},
|
| 408 |
+
"hate_offensive": {
|
| 409 |
+
"n": 1500,
|
| 410 |
+
"heldout": false,
|
| 411 |
+
"acc": 0.9266666666666666,
|
| 412 |
+
"nll": 0.2252429574728012,
|
| 413 |
+
"brier": 0.11920014768838882,
|
| 414 |
+
"ece": 0.018018441379070264,
|
| 415 |
+
"aurc": 0.016734557157267283,
|
| 416 |
+
"acc_at_80": 0.9741666666666666,
|
| 417 |
+
"acc_at_50": 0.9906666666666667,
|
| 418 |
+
"chance": 0.3333333333333333,
|
| 419 |
+
"mean_conf": 0.9164168238639832
|
| 420 |
+
},
|
| 421 |
+
"civil_comments": {
|
| 422 |
+
"n": 7500,
|
| 423 |
+
"heldout": false,
|
| 424 |
+
"acc": 0.9409333333333333,
|
| 425 |
+
"nll": 0.14164941012859344,
|
| 426 |
+
"brier": 0.08587079495191574,
|
| 427 |
+
"ece": 0.0033977080663044872,
|
| 428 |
+
"aurc": 0.0068072070084911175,
|
| 429 |
+
"acc_at_80": 0.9895,
|
| 430 |
+
"acc_at_50": 0.9994666666666666,
|
| 431 |
+
"chance": 0.5,
|
| 432 |
+
"mean_conf": 0.9395306706428528
|
| 433 |
+
},
|
| 434 |
+
"toxic_chat": {
|
| 435 |
+
"n": 3000,
|
| 436 |
+
"heldout": false,
|
| 437 |
+
"acc": 0.9843333333333333,
|
| 438 |
+
"nll": 0.04290607571601868,
|
| 439 |
+
"brier": 0.023861009627580643,
|
| 440 |
+
"ece": 0.005654305239518452,
|
| 441 |
+
"aurc": 0.0006420751251156756,
|
| 442 |
+
"acc_at_80": 0.9995833333333334,
|
| 443 |
+
"acc_at_50": 1.0,
|
| 444 |
+
"chance": 0.5,
|
| 445 |
+
"mean_conf": 0.9809242486953735
|
| 446 |
+
},
|
| 447 |
+
"sms_spam": {
|
| 448 |
+
"n": 1000,
|
| 449 |
+
"heldout": false,
|
| 450 |
+
"acc": 0.994,
|
| 451 |
+
"nll": 0.02838769368827343,
|
| 452 |
+
"brier": 0.01269171480089426,
|
| 453 |
+
"ece": 0.0056210076212883115,
|
| 454 |
+
"aurc": 0.00042434280645942466,
|
| 455 |
+
"acc_at_80": 0.99875,
|
| 456 |
+
"acc_at_50": 1.0,
|
| 457 |
+
"chance": 0.5,
|
| 458 |
+
"mean_conf": 0.9934377670288086
|
| 459 |
+
},
|
| 460 |
+
"enron_spam": {
|
| 461 |
+
"n": 1500,
|
| 462 |
+
"heldout": false,
|
| 463 |
+
"acc": 0.9953333333333333,
|
| 464 |
+
"nll": 0.014212104491889477,
|
| 465 |
+
"brier": 0.008566728793084621,
|
| 466 |
+
"ece": 0.004383029421170538,
|
| 467 |
+
"aurc": 6.272064980121389e-05,
|
| 468 |
+
"acc_at_80": 1.0,
|
| 469 |
+
"acc_at_50": 1.0,
|
| 470 |
+
"chance": 0.5,
|
| 471 |
+
"mean_conf": 0.994971513748169
|
| 472 |
+
},
|
| 473 |
+
"insincere_questions": {
|
| 474 |
+
"n": 1500,
|
| 475 |
+
"heldout": false,
|
| 476 |
+
"acc": 0.958,
|
| 477 |
+
"nll": 0.09950008988380432,
|
| 478 |
+
"brier": 0.058815646916627884,
|
| 479 |
+
"ece": 0.009067946950594569,
|
| 480 |
+
"aurc": 0.0033202849523762314,
|
| 481 |
+
"acc_at_80": 0.9966666666666667,
|
| 482 |
+
"acc_at_50": 1.0,
|
| 483 |
+
"chance": 0.5,
|
| 484 |
+
"mean_conf": 0.9590474963188171
|
| 485 |
+
},
|
| 486 |
+
"ade": {
|
| 487 |
+
"n": 1500,
|
| 488 |
+
"heldout": true,
|
| 489 |
+
"acc": 0.8373333333333334,
|
| 490 |
+
"nll": 0.3693406283855438,
|
| 491 |
+
"brier": 0.23190657794475555,
|
| 492 |
+
"ece": 0.035113215565681456,
|
| 493 |
+
"aurc": 0.054497040404324716,
|
| 494 |
+
"acc_at_80": 0.8941666666666667,
|
| 495 |
+
"acc_at_50": 0.96,
|
| 496 |
+
"chance": 0.5,
|
| 497 |
+
"mean_conf": 0.807280421257019
|
| 498 |
+
},
|
| 499 |
+
"snli": {
|
| 500 |
+
"n": 1476,
|
| 501 |
+
"heldout": false,
|
| 502 |
+
"acc": 0.9376693766937669,
|
| 503 |
+
"nll": 0.18385177850723267,
|
| 504 |
+
"brier": 0.0963604748249054,
|
| 505 |
+
"ece": 0.02269113342451853,
|
| 506 |
+
"aurc": 0.011467612685230727,
|
| 507 |
+
"acc_at_80": 0.9856054191363252,
|
| 508 |
+
"acc_at_50": 0.9932249322493225,
|
| 509 |
+
"chance": 0.3333333333333333,
|
| 510 |
+
"mean_conf": 0.9178707599639893
|
| 511 |
+
},
|
| 512 |
+
"mnli": {
|
| 513 |
+
"n": 1500,
|
| 514 |
+
"heldout": false,
|
| 515 |
+
"acc": 0.92,
|
| 516 |
+
"nll": 0.22414781153202057,
|
| 517 |
+
"brier": 0.12338652461767197,
|
| 518 |
+
"ece": 0.017153067986170414,
|
| 519 |
+
"aurc": 0.01603407033360699,
|
| 520 |
+
"acc_at_80": 0.9716666666666667,
|
| 521 |
+
"acc_at_50": 0.992,
|
| 522 |
+
"chance": 0.3333333333333333,
|
| 523 |
+
"mean_conf": 0.9121871590614319
|
| 524 |
+
},
|
| 525 |
+
"rte": {
|
| 526 |
+
"n": 277,
|
| 527 |
+
"heldout": false,
|
| 528 |
+
"acc": 0.9350180505415162,
|
| 529 |
+
"nll": 0.18287278711795807,
|
| 530 |
+
"brier": 0.10617374628782272,
|
| 531 |
+
"ece": 0.017879047118369462,
|
| 532 |
+
"aurc": 0.014183728145915892,
|
| 533 |
+
"acc_at_80": 0.9774774774774775,
|
| 534 |
+
"acc_at_50": 0.9927536231884058,
|
| 535 |
+
"chance": 0.5,
|
| 536 |
+
"mean_conf": 0.9323904514312744
|
| 537 |
+
},
|
| 538 |
+
"qnli": {
|
| 539 |
+
"n": 1500,
|
| 540 |
+
"heldout": false,
|
| 541 |
+
"acc": 0.9693333333333334,
|
| 542 |
+
"nll": 0.10291172564029694,
|
| 543 |
+
"brier": 0.05302723869681358,
|
| 544 |
+
"ece": 0.025760468522707608,
|
| 545 |
+
"aurc": 0.0035364855733933526,
|
| 546 |
+
"acc_at_80": 0.9975,
|
| 547 |
+
"acc_at_50": 0.9986666666666667,
|
| 548 |
+
"chance": 0.5,
|
| 549 |
+
"mean_conf": 0.9482638239860535
|
| 550 |
+
},
|
| 551 |
+
"qqp": {
|
| 552 |
+
"n": 1500,
|
| 553 |
+
"heldout": false,
|
| 554 |
+
"acc": 0.8553333333333333,
|
| 555 |
+
"nll": 0.29866960644721985,
|
| 556 |
+
"brier": 0.19174186885356903,
|
| 557 |
+
"ece": 0.02773328121503195,
|
| 558 |
+
"aurc": 0.033885104827278134,
|
| 559 |
+
"acc_at_80": 0.9275,
|
| 560 |
+
"acc_at_50": 0.9826666666666667,
|
| 561 |
+
"chance": 0.5,
|
| 562 |
+
"mean_conf": 0.8796607851982117
|
| 563 |
+
},
|
| 564 |
+
"mrpc": {
|
| 565 |
+
"n": 408,
|
| 566 |
+
"heldout": false,
|
| 567 |
+
"acc": 0.8872549019607843,
|
| 568 |
+
"nll": 0.26749035716056824,
|
| 569 |
+
"brier": 0.16417920589447021,
|
| 570 |
+
"ece": 0.022229443724248905,
|
| 571 |
+
"aurc": 0.027313885803315112,
|
| 572 |
+
"acc_at_80": 0.941717791411043,
|
| 573 |
+
"acc_at_50": 0.9852941176470589,
|
| 574 |
+
"chance": 0.5,
|
| 575 |
+
"mean_conf": 0.8898838758468628
|
| 576 |
+
},
|
| 577 |
+
"paws": {
|
| 578 |
+
"n": 1500,
|
| 579 |
+
"heldout": true,
|
| 580 |
+
"acc": 0.7293333333333333,
|
| 581 |
+
"nll": 0.7380470633506775,
|
| 582 |
+
"brier": 0.4195193648338318,
|
| 583 |
+
"ece": 0.16848981821537015,
|
| 584 |
+
"aurc": 0.15006823722693508,
|
| 585 |
+
"acc_at_80": 0.7791666666666667,
|
| 586 |
+
"acc_at_50": 0.8613333333333333,
|
| 587 |
+
"chance": 0.5,
|
| 588 |
+
"mean_conf": 0.8978231549263
|
| 589 |
+
},
|
| 590 |
+
"cola": {
|
| 591 |
+
"n": 1043,
|
| 592 |
+
"heldout": false,
|
| 593 |
+
"acc": 0.8609779482262704,
|
| 594 |
+
"nll": 0.30430471897125244,
|
| 595 |
+
"brier": 0.1895570456981659,
|
| 596 |
+
"ece": 0.03202069451459189,
|
| 597 |
+
"aurc": 0.035469170008069956,
|
| 598 |
+
"acc_at_80": 0.9268585131894485,
|
| 599 |
+
"acc_at_50": 0.975095785440613,
|
| 600 |
+
"chance": 0.5,
|
| 601 |
+
"mean_conf": 0.8630536794662476
|
| 602 |
+
},
|
| 603 |
+
"boolq": {
|
| 604 |
+
"n": 1500,
|
| 605 |
+
"heldout": false,
|
| 606 |
+
"acc": 0.9206666666666666,
|
| 607 |
+
"nll": 0.21292415261268616,
|
| 608 |
+
"brier": 0.12108734250068665,
|
| 609 |
+
"ece": 0.015688150127728763,
|
| 610 |
+
"aurc": 0.01887893970259577,
|
| 611 |
+
"acc_at_80": 0.965,
|
| 612 |
+
"acc_at_50": 0.988,
|
| 613 |
+
"chance": 0.5,
|
| 614 |
+
"mean_conf": 0.9252172112464905
|
| 615 |
+
},
|
| 616 |
+
"strategyqa": {
|
| 617 |
+
"n": 687,
|
| 618 |
+
"heldout": true,
|
| 619 |
+
"acc": 0.7394468704512372,
|
| 620 |
+
"nll": 0.518520712852478,
|
| 621 |
+
"brier": 0.34887009859085083,
|
| 622 |
+
"ece": 0.03629209233510271,
|
| 623 |
+
"aurc": 0.13807672950510763,
|
| 624 |
+
"acc_at_80": 0.78,
|
| 625 |
+
"acc_at_50": 0.8604651162790697,
|
| 626 |
+
"chance": 0.5,
|
| 627 |
+
"mean_conf": 0.7302948236465454
|
| 628 |
+
},
|
| 629 |
+
"pubmedqa": {
|
| 630 |
+
"n": 500,
|
| 631 |
+
"heldout": true,
|
| 632 |
+
"acc": 0.82,
|
| 633 |
+
"nll": 0.5464581251144409,
|
| 634 |
+
"brier": 0.29492902755737305,
|
| 635 |
+
"ece": 0.07814770770072936,
|
| 636 |
+
"aurc": 0.07736585822989323,
|
| 637 |
+
"acc_at_80": 0.8725,
|
| 638 |
+
"acc_at_50": 0.916,
|
| 639 |
+
"chance": 0.33333333333333326,
|
| 640 |
+
"mean_conf": 0.7438270449638367
|
| 641 |
+
},
|
| 642 |
+
"arc": {
|
| 643 |
+
"n": 1172,
|
| 644 |
+
"heldout": false,
|
| 645 |
+
"acc": 0.9641638225255973,
|
| 646 |
+
"nll": 0.11465426534414291,
|
| 647 |
+
"brier": 0.052921112626791,
|
| 648 |
+
"ece": 0.028441500261985424,
|
| 649 |
+
"aurc": 0.0038676297457262325,
|
| 650 |
+
"acc_at_80": 0.9936034115138592,
|
| 651 |
+
"acc_at_50": 0.9982935153583617,
|
| 652 |
+
"chance": 0.25015642775881686,
|
| 653 |
+
"mean_conf": 0.9453142881393433
|
| 654 |
+
},
|
| 655 |
+
"commonsense_qa": {
|
| 656 |
+
"n": 1221,
|
| 657 |
+
"heldout": false,
|
| 658 |
+
"acc": 0.8705978705978706,
|
| 659 |
+
"nll": 0.33728107810020447,
|
| 660 |
+
"brier": 0.18371696770191193,
|
| 661 |
+
"ece": 0.022902015874270598,
|
| 662 |
+
"aurc": 0.027533759986903508,
|
| 663 |
+
"acc_at_80": 0.9437052200614124,
|
| 664 |
+
"acc_at_50": 0.9836065573770492,
|
| 665 |
+
"chance": 0.19999999999999998,
|
| 666 |
+
"mean_conf": 0.8542661666870117
|
| 667 |
+
},
|
| 668 |
+
"qasc": {
|
| 669 |
+
"n": 926,
|
| 670 |
+
"heldout": false,
|
| 671 |
+
"acc": 0.9146868250539957,
|
| 672 |
+
"nll": 0.28406572341918945,
|
| 673 |
+
"brier": 0.13141772150993347,
|
| 674 |
+
"ece": 0.05652497216383276,
|
| 675 |
+
"aurc": 0.011926056294752855,
|
| 676 |
+
"acc_at_80": 0.9811066126855601,
|
| 677 |
+
"acc_at_50": 0.9978401727861771,
|
| 678 |
+
"chance": 0.125,
|
| 679 |
+
"mean_conf": 0.8592483401298523
|
| 680 |
+
},
|
| 681 |
+
"openbookqa": {
|
| 682 |
+
"n": 500,
|
| 683 |
+
"heldout": false,
|
| 684 |
+
"acc": 0.962,
|
| 685 |
+
"nll": 0.15028874576091766,
|
| 686 |
+
"brier": 0.062103498727083206,
|
| 687 |
+
"ece": 0.029689819455146767,
|
| 688 |
+
"aurc": 0.008756976491078847,
|
| 689 |
+
"acc_at_80": 0.9825,
|
| 690 |
+
"acc_at_50": 0.996,
|
| 691 |
+
"chance": 0.25,
|
| 692 |
+
"mean_conf": 0.9473608136177063
|
| 693 |
+
},
|
| 694 |
+
"sciq": {
|
| 695 |
+
"n": 1000,
|
| 696 |
+
"heldout": true,
|
| 697 |
+
"acc": 0.993,
|
| 698 |
+
"nll": 0.026743656024336815,
|
| 699 |
+
"brier": 0.011477932333946228,
|
| 700 |
+
"ece": 0.010730246603488931,
|
| 701 |
+
"aurc": 0.00012297224385520662,
|
| 702 |
+
"acc_at_80": 1.0,
|
| 703 |
+
"acc_at_50": 1.0,
|
| 704 |
+
"chance": 0.25,
|
| 705 |
+
"mean_conf": 0.9845147132873535
|
| 706 |
+
},
|
| 707 |
+
"hellaswag": {
|
| 708 |
+
"n": 1500,
|
| 709 |
+
"heldout": false,
|
| 710 |
+
"acc": 0.9693333333333334,
|
| 711 |
+
"nll": 0.07776311039924622,
|
| 712 |
+
"brier": 0.042344722896814346,
|
| 713 |
+
"ece": 0.006844995915889716,
|
| 714 |
+
"aurc": 0.0013723910741853661,
|
| 715 |
+
"acc_at_80": 1.0,
|
| 716 |
+
"acc_at_50": 1.0,
|
| 717 |
+
"chance": 0.25,
|
| 718 |
+
"mean_conf": 0.9741500616073608
|
| 719 |
+
},
|
| 720 |
+
"piqa": {
|
| 721 |
+
"n": 1500,
|
| 722 |
+
"heldout": false,
|
| 723 |
+
"acc": 0.954,
|
| 724 |
+
"nll": 0.12870272994041443,
|
| 725 |
+
"brier": 0.07193071395158768,
|
| 726 |
+
"ece": 0.014045794884363829,
|
| 727 |
+
"aurc": 0.006066841189670484,
|
| 728 |
+
"acc_at_80": 0.9891666666666666,
|
| 729 |
+
"acc_at_50": 0.9986666666666667,
|
| 730 |
+
"chance": 0.5,
|
| 731 |
+
"mean_conf": 0.9444655179977417
|
| 732 |
+
},
|
| 733 |
+
"social_iqa": {
|
| 734 |
+
"n": 1500,
|
| 735 |
+
"heldout": true,
|
| 736 |
+
"acc": 0.8233333333333334,
|
| 737 |
+
"nll": 0.4479636251926422,
|
| 738 |
+
"brier": 0.2568584680557251,
|
| 739 |
+
"ece": 0.02492147314548492,
|
| 740 |
+
"aurc": 0.06027574211898331,
|
| 741 |
+
"acc_at_80": 0.8875,
|
| 742 |
+
"acc_at_50": 0.9493333333333334,
|
| 743 |
+
"chance": 0.3333333333333333,
|
| 744 |
+
"mean_conf": 0.817057192325592
|
| 745 |
+
},
|
| 746 |
+
"winogrande": {
|
| 747 |
+
"n": 1267,
|
| 748 |
+
"heldout": false,
|
| 749 |
+
"acc": 0.8918705603788477,
|
| 750 |
+
"nll": 0.2955634295940399,
|
| 751 |
+
"brier": 0.16731061041355133,
|
| 752 |
+
"ece": 0.0350758349603805,
|
| 753 |
+
"aurc": 0.03663538162242224,
|
| 754 |
+
"acc_at_80": 0.9447731755424064,
|
| 755 |
+
"acc_at_50": 0.973186119873817,
|
| 756 |
+
"chance": 0.5,
|
| 757 |
+
"mean_conf": 0.9254278540611267
|
| 758 |
+
},
|
| 759 |
+
"race": {
|
| 760 |
+
"n": 1500,
|
| 761 |
+
"heldout": false,
|
| 762 |
+
"acc": 0.932,
|
| 763 |
+
"nll": 0.229837566614151,
|
| 764 |
+
"brier": 0.10741978138685226,
|
| 765 |
+
"ece": 0.012891520102818818,
|
| 766 |
+
"aurc": 0.015083615590388144,
|
| 767 |
+
"acc_at_80": 0.9783333333333334,
|
| 768 |
+
"acc_at_50": 0.9906666666666667,
|
| 769 |
+
"chance": 0.25,
|
| 770 |
+
"mean_conf": 0.935739278793335
|
| 771 |
+
},
|
| 772 |
+
"mmlu": {
|
| 773 |
+
"n": 1500,
|
| 774 |
+
"heldout": false,
|
| 775 |
+
"acc": 0.82,
|
| 776 |
+
"nll": 0.49843254685401917,
|
| 777 |
+
"brier": 0.24768584966659546,
|
| 778 |
+
"ece": 0.02976374606291451,
|
| 779 |
+
"aurc": 0.05049327310892201,
|
| 780 |
+
"acc_at_80": 0.91,
|
| 781 |
+
"acc_at_50": 0.9693333333333334,
|
| 782 |
+
"chance": 0.25,
|
| 783 |
+
"mean_conf": 0.8007211685180664
|
| 784 |
+
},
|
| 785 |
+
"medqa": {
|
| 786 |
+
"n": 1273,
|
| 787 |
+
"heldout": false,
|
| 788 |
+
"acc": 0.8546739984289081,
|
| 789 |
+
"nll": 0.39887696504592896,
|
| 790 |
+
"brier": 0.20918008685112,
|
| 791 |
+
"ece": 0.019769610706877737,
|
| 792 |
+
"aurc": 0.034844860161640345,
|
| 793 |
+
"acc_at_80": 0.9322200392927309,
|
| 794 |
+
"acc_at_50": 0.9874213836477987,
|
| 795 |
+
"chance": 0.25,
|
| 796 |
+
"mean_conf": 0.8520532846450806
|
| 797 |
+
},
|
| 798 |
+
"truthfulqa": {
|
| 799 |
+
"n": 817,
|
| 800 |
+
"heldout": true,
|
| 801 |
+
"acc": 0.7539779681762546,
|
| 802 |
+
"nll": 0.8089373111724854,
|
| 803 |
+
"brier": 0.364557683467865,
|
| 804 |
+
"ece": 0.06832761250919638,
|
| 805 |
+
"aurc": 0.08947353158858118,
|
| 806 |
+
"acc_at_80": 0.8425076452599388,
|
| 807 |
+
"acc_at_50": 0.9387254901960784,
|
| 808 |
+
"chance": 0.22622350449767833,
|
| 809 |
+
"mean_conf": 0.696648895740509
|
| 810 |
+
},
|
| 811 |
+
"fin_phrasebank": {
|
| 812 |
+
"n": 970,
|
| 813 |
+
"heldout": true,
|
| 814 |
+
"acc": 0.7587628865979381,
|
| 815 |
+
"nll": 0.6080690026283264,
|
| 816 |
+
"brier": 0.3605556786060333,
|
| 817 |
+
"ece": 0.10978183436025048,
|
| 818 |
+
"aurc": 0.11749813303878813,
|
| 819 |
+
"acc_at_80": 0.8195876288659794,
|
| 820 |
+
"acc_at_50": 0.8886597938144329,
|
| 821 |
+
"chance": 0.33333333333333326,
|
| 822 |
+
"mean_conf": 0.6539795398712158
|
| 823 |
+
},
|
| 824 |
+
"bias_in_bios": {
|
| 825 |
+
"n": 3000,
|
| 826 |
+
"heldout": false,
|
| 827 |
+
"acc": 0.9666666666666667,
|
| 828 |
+
"nll": 0.09920930117368698,
|
| 829 |
+
"brier": 0.04930334910750389,
|
| 830 |
+
"ece": 0.008911347289880108,
|
| 831 |
+
"aurc": 0.00193519783058256,
|
| 832 |
+
"acc_at_80": 0.9991666666666666,
|
| 833 |
+
"acc_at_50": 1.0,
|
| 834 |
+
"chance": 0.30000000000000004,
|
| 835 |
+
"mean_conf": 0.9638564586639404
|
| 836 |
+
},
|
| 837 |
+
"helpsteer2": {
|
| 838 |
+
"n": 5190,
|
| 839 |
+
"heldout": false,
|
| 840 |
+
"acc": 0.6163776493256262,
|
| 841 |
+
"nll": 0.8915571570396423,
|
| 842 |
+
"brier": 0.49822765588760376,
|
| 843 |
+
"ece": 0.01934157278037023,
|
| 844 |
+
"aurc": 0.2413207825095569,
|
| 845 |
+
"acc_at_80": 0.6763005780346821,
|
| 846 |
+
"acc_at_50": 0.7533718689788054,
|
| 847 |
+
"chance": 0.2,
|
| 848 |
+
"mean_conf": 0.620047390460968
|
| 849 |
+
},
|
| 850 |
+
"helpsteer3_pref": {
|
| 851 |
+
"n": 1176,
|
| 852 |
+
"heldout": false,
|
| 853 |
+
"acc": 0.5518707482993197,
|
| 854 |
+
"nll": 1.2033027410507202,
|
| 855 |
+
"brier": 0.5932223796844482,
|
| 856 |
+
"ece": 0.025830757785208366,
|
| 857 |
+
"aurc": 0.30366389562151924,
|
| 858 |
+
"acc_at_80": 0.6068012752391073,
|
| 859 |
+
"acc_at_50": 0.6768707482993197,
|
| 860 |
+
"chance": 0.14285714285714282,
|
| 861 |
+
"mean_conf": 0.5695160031318665
|
| 862 |
+
},
|
| 863 |
+
"hate_speech_scales": {
|
| 864 |
+
"n": 7500,
|
| 865 |
+
"heldout": false,
|
| 866 |
+
"acc": 0.5805333333333333,
|
| 867 |
+
"nll": 0.9507390856742859,
|
| 868 |
+
"brier": 0.528562068939209,
|
| 869 |
+
"ece": 0.013830039529005684,
|
| 870 |
+
"aurc": 0.2502365025510708,
|
| 871 |
+
"acc_at_80": 0.6266666666666667,
|
| 872 |
+
"acc_at_50": 0.7202666666666667,
|
| 873 |
+
"chance": 0.22666666666666674,
|
| 874 |
+
"mean_conf": 0.5702805519104004
|
| 875 |
+
},
|
| 876 |
+
"liar2": {
|
| 877 |
+
"n": 1500,
|
| 878 |
+
"heldout": false,
|
| 879 |
+
"acc": 0.422,
|
| 880 |
+
"nll": 1.3505219221115112,
|
| 881 |
+
"brier": 0.6785846948623657,
|
| 882 |
+
"ece": 0.028518199036518737,
|
| 883 |
+
"aurc": 0.4162147525556497,
|
| 884 |
+
"acc_at_80": 0.4708333333333333,
|
| 885 |
+
"acc_at_50": 0.5653333333333334,
|
| 886 |
+
"chance": 0.16666666666666666,
|
| 887 |
+
"mean_conf": 0.41971758008003235
|
| 888 |
+
},
|
| 889 |
+
"prosocial_safety": {
|
| 890 |
+
"n": 1500,
|
| 891 |
+
"heldout": false,
|
| 892 |
+
"acc": 0.528,
|
| 893 |
+
"nll": 1.1013150215148926,
|
| 894 |
+
"brier": 0.5662647485733032,
|
| 895 |
+
"ece": 0.030879737019538868,
|
| 896 |
+
"aurc": 0.2518870991484317,
|
| 897 |
+
"acc_at_80": 0.5991666666666666,
|
| 898 |
+
"acc_at_50": 0.7213333333333334,
|
| 899 |
+
"chance": 0.2,
|
| 900 |
+
"mean_conf": 0.518919050693512
|
| 901 |
+
},
|
| 902 |
+
"ultrafeedback_pref": {
|
| 903 |
+
"n": 1500,
|
| 904 |
+
"heldout": false,
|
| 905 |
+
"acc": 0.784,
|
| 906 |
+
"nll": 0.43619513511657715,
|
| 907 |
+
"brier": 0.28585085272789,
|
| 908 |
+
"ece": 0.03089568722248076,
|
| 909 |
+
"aurc": 0.08515379420314682,
|
| 910 |
+
"acc_at_80": 0.8475,
|
| 911 |
+
"acc_at_50": 0.9266666666666666,
|
| 912 |
+
"chance": 0.5,
|
| 913 |
+
"mean_conf": 0.8054375648498535
|
| 914 |
+
},
|
| 915 |
+
"shp": {
|
| 916 |
+
"n": 1500,
|
| 917 |
+
"heldout": false,
|
| 918 |
+
"acc": 0.79,
|
| 919 |
+
"nll": 0.44603705406188965,
|
| 920 |
+
"brier": 0.2889350950717926,
|
| 921 |
+
"ece": 0.02012235975265503,
|
| 922 |
+
"aurc": 0.09319282571857365,
|
| 923 |
+
"acc_at_80": 0.8491666666666666,
|
| 924 |
+
"acc_at_50": 0.9146666666666666,
|
| 925 |
+
"chance": 0.5,
|
| 926 |
+
"mean_conf": 0.7964972257614136
|
| 927 |
+
},
|
| 928 |
+
"hh_rlhf": {
|
| 929 |
+
"n": 1488,
|
| 930 |
+
"heldout": false,
|
| 931 |
+
"acc": 0.6901881720430108,
|
| 932 |
+
"nll": 0.5672697424888611,
|
| 933 |
+
"brier": 0.38868722319602966,
|
| 934 |
+
"ece": 0.018854505592776898,
|
| 935 |
+
"aurc": 0.18054136093942436,
|
| 936 |
+
"acc_at_80": 0.7361344537815127,
|
| 937 |
+
"acc_at_50": 0.8077956989247311,
|
| 938 |
+
"chance": 0.5,
|
| 939 |
+
"mean_conf": 0.7015084028244019
|
| 940 |
+
},
|
| 941 |
+
"arena_pref": {
|
| 942 |
+
"n": 1500,
|
| 943 |
+
"heldout": true,
|
| 944 |
+
"acc": 0.5206666666666667,
|
| 945 |
+
"nll": 1.0640077590942383,
|
| 946 |
+
"brier": 0.6215369701385498,
|
| 947 |
+
"ece": 0.1206609118382136,
|
| 948 |
+
"aurc": 0.36246136582814387,
|
| 949 |
+
"acc_at_80": 0.55,
|
| 950 |
+
"acc_at_50": 0.616,
|
| 951 |
+
"chance": 0.3333333333333333,
|
| 952 |
+
"mean_conf": 0.6390127539634705
|
| 953 |
+
},
|
| 954 |
+
"reward_bench": {
|
| 955 |
+
"n": 1500,
|
| 956 |
+
"heldout": true,
|
| 957 |
+
"acc": 0.9186666666666666,
|
| 958 |
+
"nll": 0.2031487673521042,
|
| 959 |
+
"brier": 0.12078241258859634,
|
| 960 |
+
"ece": 0.023855606953302997,
|
| 961 |
+
"aurc": 0.014145065893525021,
|
| 962 |
+
"acc_at_80": 0.9758333333333333,
|
| 963 |
+
"acc_at_50": 0.9946666666666667,
|
| 964 |
+
"chance": 0.5,
|
| 965 |
+
"mean_conf": 0.8953665494918823
|
| 966 |
+
},
|
| 967 |
+
"glaive_tools": {
|
| 968 |
+
"n": 1348,
|
| 969 |
+
"heldout": false,
|
| 970 |
+
"acc": 0.9532640949554896,
|
| 971 |
+
"nll": 0.14300261437892914,
|
| 972 |
+
"brier": 0.07691621780395508,
|
| 973 |
+
"ece": 0.02094891802228167,
|
| 974 |
+
"aurc": 0.007086222936904486,
|
| 975 |
+
"acc_at_80": 0.9860853432282004,
|
| 976 |
+
"acc_at_50": 0.9985163204747775,
|
| 977 |
+
"chance": 0.16666666666666666,
|
| 978 |
+
"mean_conf": 0.9427018165588379
|
| 979 |
+
},
|
| 980 |
+
"toolace": {
|
| 981 |
+
"n": 1000,
|
| 982 |
+
"heldout": false,
|
| 983 |
+
"acc": 0.94,
|
| 984 |
+
"nll": 0.1773465871810913,
|
| 985 |
+
"brier": 0.08758451044559479,
|
| 986 |
+
"ece": 0.019288902848959,
|
| 987 |
+
"aurc": 0.01419978829962143,
|
| 988 |
+
"acc_at_80": 0.98125,
|
| 989 |
+
"acc_at_50": 0.992,
|
| 990 |
+
"chance": 0.12470555555555554,
|
| 991 |
+
"mean_conf": 0.9342852830886841
|
| 992 |
+
},
|
| 993 |
+
"hermes_tools": {
|
| 994 |
+
"n": 1500,
|
| 995 |
+
"heldout": true,
|
| 996 |
+
"acc": 0.7986666666666666,
|
| 997 |
+
"nll": 0.36825039982795715,
|
| 998 |
+
"brier": 0.23031076788902283,
|
| 999 |
+
"ece": 0.08474178238709767,
|
| 1000 |
+
"aurc": 0.04541348669345317,
|
| 1001 |
+
"acc_at_80": 0.8966666666666666,
|
| 1002 |
+
"acc_at_50": 0.988,
|
| 1003 |
+
"chance": 0.125,
|
| 1004 |
+
"mean_conf": 0.8443251848220825
|
| 1005 |
+
},
|
| 1006 |
+
"copa": {
|
| 1007 |
+
"n": 100,
|
| 1008 |
+
"heldout": false,
|
| 1009 |
+
"acc": 1.0,
|
| 1010 |
+
"nll": 0.018447600305080414,
|
| 1011 |
+
"brier": 0.004432467743754387,
|
| 1012 |
+
"ece": 0.017155210971832275,
|
| 1013 |
+
"aurc": 0.0,
|
| 1014 |
+
"acc_at_80": 1.0,
|
| 1015 |
+
"acc_at_50": 1.0,
|
| 1016 |
+
"chance": 0.5,
|
| 1017 |
+
"mean_conf": 0.9828447699546814
|
| 1018 |
+
},
|
| 1019 |
+
"wic": {
|
| 1020 |
+
"n": 638,
|
| 1021 |
+
"heldout": false,
|
| 1022 |
+
"acc": 0.7727272727272727,
|
| 1023 |
+
"nll": 0.47851547598838806,
|
| 1024 |
+
"brier": 0.3126711845397949,
|
| 1025 |
+
"ece": 0.06492637840557994,
|
| 1026 |
+
"aurc": 0.10600177937132382,
|
| 1027 |
+
"acc_at_80": 0.8352941176470589,
|
| 1028 |
+
"acc_at_50": 0.8996865203761756,
|
| 1029 |
+
"chance": 0.5,
|
| 1030 |
+
"mean_conf": 0.828840970993042
|
| 1031 |
+
},
|
| 1032 |
+
"multirc": {
|
| 1033 |
+
"n": 1500,
|
| 1034 |
+
"heldout": false,
|
| 1035 |
+
"acc": 0.918,
|
| 1036 |
+
"nll": 0.23172627389431,
|
| 1037 |
+
"brier": 0.1296291947364807,
|
| 1038 |
+
"ece": 0.02276274232069647,
|
| 1039 |
+
"aurc": 0.02589494647653243,
|
| 1040 |
+
"acc_at_80": 0.965,
|
| 1041 |
+
"acc_at_50": 0.9773333333333334,
|
| 1042 |
+
"chance": 0.5,
|
| 1043 |
+
"mean_conf": 0.9249215722084045
|
| 1044 |
+
},
|
| 1045 |
+
"cb": {
|
| 1046 |
+
"n": 56,
|
| 1047 |
+
"heldout": true,
|
| 1048 |
+
"acc": 0.8928571428571429,
|
| 1049 |
+
"nll": 0.2884705662727356,
|
| 1050 |
+
"brier": 0.15287914872169495,
|
| 1051 |
+
"ece": 0.08375836323414529,
|
| 1052 |
+
"aurc": 0.01340165852858295,
|
| 1053 |
+
"acc_at_80": 0.9777777777777777,
|
| 1054 |
+
"acc_at_50": 1.0,
|
| 1055 |
+
"chance": 0.3333333333333333,
|
| 1056 |
+
"mean_conf": 0.8508859276771545
|
| 1057 |
+
},
|
| 1058 |
+
"fever": {
|
| 1059 |
+
"n": 1500,
|
| 1060 |
+
"heldout": false,
|
| 1061 |
+
"acc": 0.91,
|
| 1062 |
+
"nll": 0.2639821767807007,
|
| 1063 |
+
"brier": 0.1403927505016327,
|
| 1064 |
+
"ece": 0.01887864359219866,
|
| 1065 |
+
"aurc": 0.021236299620246823,
|
| 1066 |
+
"acc_at_80": 0.9666666666666667,
|
| 1067 |
+
"acc_at_50": 0.9866666666666667,
|
| 1068 |
+
"chance": 0.3333333333333333,
|
| 1069 |
+
"mean_conf": 0.911332368850708
|
| 1070 |
+
},
|
| 1071 |
+
"wiki_qa": {
|
| 1072 |
+
"n": 879,
|
| 1073 |
+
"heldout": false,
|
| 1074 |
+
"acc": 0.9089874857792947,
|
| 1075 |
+
"nll": 0.22839467227458954,
|
| 1076 |
+
"brier": 0.13368310034275055,
|
| 1077 |
+
"ece": 0.023650864081984878,
|
| 1078 |
+
"aurc": 0.020796820711007552,
|
| 1079 |
+
"acc_at_80": 0.9644381223328592,
|
| 1080 |
+
"acc_at_50": 0.9886363636363636,
|
| 1081 |
+
"chance": 0.5,
|
| 1082 |
+
"mean_conf": 0.8948045372962952
|
| 1083 |
+
},
|
| 1084 |
+
"msmarco_rel": {
|
| 1085 |
+
"n": 1446,
|
| 1086 |
+
"heldout": false,
|
| 1087 |
+
"acc": 0.6970954356846473,
|
| 1088 |
+
"nll": 0.5717816352844238,
|
| 1089 |
+
"brier": 0.39096301794052124,
|
| 1090 |
+
"ece": 0.03819479437784535,
|
| 1091 |
+
"aurc": 0.18340211744146934,
|
| 1092 |
+
"acc_at_80": 0.7303370786516854,
|
| 1093 |
+
"acc_at_50": 0.8091286307053942,
|
| 1094 |
+
"chance": 0.5,
|
| 1095 |
+
"mean_conf": 0.7234166860580444
|
| 1096 |
+
},
|
| 1097 |
+
"medmcqa": {
|
| 1098 |
+
"n": 1500,
|
| 1099 |
+
"heldout": false,
|
| 1100 |
+
"acc": 0.742,
|
| 1101 |
+
"nll": 0.6534839272499084,
|
| 1102 |
+
"brier": 0.3494548797607422,
|
| 1103 |
+
"ece": 0.04476275533437729,
|
| 1104 |
+
"aurc": 0.09236420121984344,
|
| 1105 |
+
"acc_at_80": 0.8175,
|
| 1106 |
+
"acc_at_50": 0.932,
|
| 1107 |
+
"chance": 0.25,
|
| 1108 |
+
"mean_conf": 0.7632542848587036
|
| 1109 |
+
},
|
| 1110 |
+
"quality": {
|
| 1111 |
+
"n": 1500,
|
| 1112 |
+
"heldout": true,
|
| 1113 |
+
"acc": 0.632,
|
| 1114 |
+
"nll": 0.9736621379852295,
|
| 1115 |
+
"brier": 0.5085250735282898,
|
| 1116 |
+
"ece": 0.09598391598463062,
|
| 1117 |
+
"aurc": 0.20000924342798884,
|
| 1118 |
+
"acc_at_80": 0.69,
|
| 1119 |
+
"acc_at_50": 0.7893333333333333,
|
| 1120 |
+
"chance": 0.25,
|
| 1121 |
+
"mean_conf": 0.726018488407135
|
| 1122 |
+
},
|
| 1123 |
+
"xstory_cloze": {
|
| 1124 |
+
"n": 1500,
|
| 1125 |
+
"heldout": true,
|
| 1126 |
+
"acc": 0.9946666666666667,
|
| 1127 |
+
"nll": 0.026280736550688744,
|
| 1128 |
+
"brier": 0.011265838518738747,
|
| 1129 |
+
"ece": 0.015819201707839965,
|
| 1130 |
+
"aurc": 8.187136167601649e-05,
|
| 1131 |
+
"acc_at_80": 1.0,
|
| 1132 |
+
"acc_at_50": 1.0,
|
| 1133 |
+
"chance": 0.5,
|
| 1134 |
+
"mean_conf": 0.9801904559135437
|
| 1135 |
+
},
|
| 1136 |
+
"abstain_probe": {
|
| 1137 |
+
"n": 1620,
|
| 1138 |
+
"heldout": true,
|
| 1139 |
+
"acc": 0.6222222222222222,
|
| 1140 |
+
"nll": 1.1009931564331055,
|
| 1141 |
+
"brier": 0.5079091191291809,
|
| 1142 |
+
"ece": 0.08518773355969675,
|
| 1143 |
+
"aurc": 0.17190129595658887,
|
| 1144 |
+
"acc_at_80": 0.7106481481481481,
|
| 1145 |
+
"acc_at_50": 0.8222222222222222,
|
| 1146 |
+
"chance": 0.17897217323143252,
|
| 1147 |
+
"mean_conf": 0.7074099779129028
|
| 1148 |
+
},
|
| 1149 |
+
"agenttraj": {
|
| 1150 |
+
"n": 1500,
|
| 1151 |
+
"heldout": false,
|
| 1152 |
+
"acc": 0.9366666666666666,
|
| 1153 |
+
"nll": 0.15657173097133636,
|
| 1154 |
+
"brier": 0.08615637570619583,
|
| 1155 |
+
"ece": 0.018042015492916074,
|
| 1156 |
+
"aurc": 0.004964706283705984,
|
| 1157 |
+
"acc_at_80": 0.9958333333333333,
|
| 1158 |
+
"acc_at_50": 0.9986666666666667,
|
| 1159 |
+
"chance": 0.2,
|
| 1160 |
+
"mean_conf": 0.9253047108650208
|
| 1161 |
+
},
|
| 1162 |
+
"mind2web": {
|
| 1163 |
+
"n": 1500,
|
| 1164 |
+
"heldout": false,
|
| 1165 |
+
"acc": 0.8853333333333333,
|
| 1166 |
+
"nll": 0.33396658301353455,
|
| 1167 |
+
"brier": 0.1709548383951187,
|
| 1168 |
+
"ece": 0.015519337852795898,
|
| 1169 |
+
"aurc": 0.02253901936947198,
|
| 1170 |
+
"acc_at_80": 0.9558333333333333,
|
| 1171 |
+
"acc_at_50": 0.9933333333333333,
|
| 1172 |
+
"chance": 0.16666666666666666,
|
| 1173 |
+
"mean_conf": 0.885744035243988
|
| 1174 |
+
},
|
| 1175 |
+
"synth": {
|
| 1176 |
+
"n": 300,
|
| 1177 |
+
"heldout": false,
|
| 1178 |
+
"acc": 0.8466666666666667,
|
| 1179 |
+
"nll": 0.39028388261795044,
|
| 1180 |
+
"brier": 0.21442179381847382,
|
| 1181 |
+
"ece": 0.03632553676764172,
|
| 1182 |
+
"aurc": 0.041584943277947255,
|
| 1183 |
+
"acc_at_80": 0.9166666666666666,
|
| 1184 |
+
"acc_at_50": 0.9733333333333334,
|
| 1185 |
+
"chance": 0.37149999999999994,
|
| 1186 |
+
"mean_conf": 0.8786032199859619
|
| 1187 |
+
},
|
| 1188 |
+
"offtopic_probe": {
|
| 1189 |
+
"n": 1620,
|
| 1190 |
+
"heldout": true,
|
| 1191 |
+
"acc": 0.8697530864197531,
|
| 1192 |
+
"nll": 0.3856513202190399,
|
| 1193 |
+
"brier": 0.17581190168857574,
|
| 1194 |
+
"ece": 0.037777107972421745,
|
| 1195 |
+
"aurc": 0.018382871739502517,
|
| 1196 |
+
"acc_at_80": 0.9683641975308642,
|
| 1197 |
+
"acc_at_50": 0.9950617283950617,
|
| 1198 |
+
"chance": 0.17979423868312755,
|
| 1199 |
+
"mean_conf": 0.8545409440994263
|
| 1200 |
+
},
|
| 1201 |
+
"hwu64": {
|
| 1202 |
+
"n": 1076,
|
| 1203 |
+
"heldout": true,
|
| 1204 |
+
"acc": 0.974907063197026,
|
| 1205 |
+
"nll": 0.08065392076969147,
|
| 1206 |
+
"brier": 0.04049574211239815,
|
| 1207 |
+
"ece": 0.021740955629534923,
|
| 1208 |
+
"aurc": 0.0012811690911756525,
|
| 1209 |
+
"acc_at_80": 1.0,
|
| 1210 |
+
"acc_at_50": 1.0,
|
| 1211 |
+
"chance": 0.09999999999999999,
|
| 1212 |
+
"mean_conf": 0.9563130140304565
|
| 1213 |
+
},
|
| 1214 |
+
"dbpedia_l2": {
|
| 1215 |
+
"n": 1500,
|
| 1216 |
+
"heldout": true,
|
| 1217 |
+
"acc": 0.9606666666666667,
|
| 1218 |
+
"nll": 0.11009299755096436,
|
| 1219 |
+
"brier": 0.060155414044857025,
|
| 1220 |
+
"ece": 0.01014547139406203,
|
| 1221 |
+
"aurc": 0.003270819231754314,
|
| 1222 |
+
"acc_at_80": 0.9958333333333333,
|
| 1223 |
+
"acc_at_50": 1.0,
|
| 1224 |
+
"chance": 0.1,
|
| 1225 |
+
"mean_conf": 0.9609081149101257
|
| 1226 |
+
},
|
| 1227 |
+
"dbpedia_l3": {
|
| 1228 |
+
"n": 1500,
|
| 1229 |
+
"heldout": true,
|
| 1230 |
+
"acc": 0.992,
|
| 1231 |
+
"nll": 0.02752424031496048,
|
| 1232 |
+
"brier": 0.013588163070380688,
|
| 1233 |
+
"ece": 0.0035614574154217704,
|
| 1234 |
+
"aurc": 0.000210942320122308,
|
| 1235 |
+
"acc_at_80": 1.0,
|
| 1236 |
+
"acc_at_50": 1.0,
|
| 1237 |
+
"chance": 0.1,
|
| 1238 |
+
"mean_conf": 0.9927933216094971
|
| 1239 |
+
},
|
| 1240 |
+
"quality_full": {
|
| 1241 |
+
"n": 600,
|
| 1242 |
+
"heldout": true,
|
| 1243 |
+
"acc": 0.565,
|
| 1244 |
+
"nll": 1.071710467338562,
|
| 1245 |
+
"brier": 0.5663425922393799,
|
| 1246 |
+
"ece": 0.11241838062802949,
|
| 1247 |
+
"aurc": 0.2527098290509578,
|
| 1248 |
+
"acc_at_80": 0.6270833333333333,
|
| 1249 |
+
"acc_at_50": 0.7366666666666667,
|
| 1250 |
+
"chance": 0.25,
|
| 1251 |
+
"mean_conf": 0.6741220951080322
|
| 1252 |
+
}
|
| 1253 |
+
},
|
| 1254 |
+
"other_sets": {
|
| 1255 |
+
"general_validation_847": {
|
| 1256 |
+
"acc": 0.8996,
|
| 1257 |
+
"nll": 0.3285,
|
| 1258 |
+
"ece": 0.0442
|
| 1259 |
+
},
|
| 1260 |
+
"typesafe_102": {
|
| 1261 |
+
"acc": 0.8627,
|
| 1262 |
+
"nll": 0.3415,
|
| 1263 |
+
"ece": 0.065,
|
| 1264 |
+
"tv_to_reference": 0.1648
|
| 1265 |
+
},
|
| 1266 |
+
"openjev_5252": {
|
| 1267 |
+
"acc": 0.6828,
|
| 1268 |
+
"macro_f1": 0.8567,
|
| 1269 |
+
"nll": 0.7523,
|
| 1270 |
+
"ece": 0.0491
|
| 1271 |
+
},
|
| 1272 |
+
"mind2web_1770": {
|
| 1273 |
+
"acc": 0.8955,
|
| 1274 |
+
"nll": 0.3159,
|
| 1275 |
+
"ece": 0.0571
|
| 1276 |
+
},
|
| 1277 |
+
"jevbench_public_items": {
|
| 1278 |
+
"easy": 1.0,
|
| 1279 |
+
"standard": 0.9722,
|
| 1280 |
+
"hard": 0.6757
|
| 1281 |
+
},
|
| 1282 |
+
"bespoke_public_suite": {
|
| 1283 |
+
"macro": 0.7737,
|
| 1284 |
+
"micro": 0.7866,
|
| 1285 |
+
"macro_untrained": 0.7435
|
| 1286 |
+
},
|
| 1287 |
+
"miniwob_live_22x8": {
|
| 1288 |
+
"sampled": 0.8636,
|
| 1289 |
+
"sampled_held_out": 0.7917,
|
| 1290 |
+
"greedy": 0.9716,
|
| 1291 |
+
"greedy_held_out": 0.9792
|
| 1292 |
+
},
|
| 1293 |
+
"zero_shot_games_win_rate": {
|
| 1294 |
+
"sampled_all": 0.2415,
|
| 1295 |
+
"greedy_all": 0.3718
|
| 1296 |
+
}
|
| 1297 |
+
}
|
| 1298 |
+
}
|
generation_config.json
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"_from_model_config": true,
|
| 3 |
+
"eos_token_id": 248044,
|
| 4 |
+
"transformers_version": "5.17.0",
|
| 5 |
+
"use_cache": true
|
| 6 |
+
}
|
model-00001-of-00015.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c230ef13988becedf0c3f81c76628283663007466d8bfcead27bd2d85a297935
|
| 3 |
+
size 4861004088
|
model-00002-of-00015.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4eaeb99c73f9d075d6aff9f2245fe88b7e3b5faf546b4c110316174fa61e77f5
|
| 3 |
+
size 4506714376
|
model-00003-of-00015.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f31fa5d8cd003aed7b8fb2b428d90ba9d3d7e12071fc0c07b17b0f67bbdee140
|
| 3 |
+
size 4989093232
|
model-00004-of-00015.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4407b99000e95cc906268010703e0036976fe015425fbd160b28c56f7008bfed
|
| 3 |
+
size 4574152520
|
model-00005-of-00015.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5e5eed694729abdf8dc0eb22580ee724501040e71ab65c5b688f125c1ecf0006
|
| 3 |
+
size 4976513672
|
model-00006-of-00015.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ee091bd7107b1e5c347153bc116ba385816c2b67f045c6ab59f38ae18d266280
|
| 3 |
+
size 4990860936
|
model-00007-of-00015.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:0d540f11b3df3134db58830f8d8c6979a5504c89e48c0ebc90928f321184e26d
|
| 3 |
+
size 4564708264
|
model-00008-of-00015.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5a7062793d00efb2d8904198968d52159cc2c2bbad03886020395db0aae0c136
|
| 3 |
+
size 4506716424
|
model-00009-of-00015.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d806e89b85bf1a360b9c576f6de907e67f41b4443034d261889b65ba478efaf4
|
| 3 |
+
size 4506716432
|
model-00010-of-00015.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ceebc6759cae88ad2fa75c0d4f67a3c83bfb23c540ec546a6d661193388d7cba
|
| 3 |
+
size 4989095576
|
model-00011-of-00015.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5a329b4b880be2bd3526214c8c068d9dad3b32d5ba497e054444e761951f0334
|
| 3 |
+
size 4499363680
|
model-00012-of-00015.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4a49900cb63a3bd7a1e8a9d4fb127d5283e5243a8a32aef92326e456ad9d0677
|
| 3 |
+
size 4506716472
|
model-00013-of-00015.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:8dde20ac69c397bbdfafc78355032278878d60c860ecd1622e74c37676cbe628
|
| 3 |
+
size 4989095576
|
model-00014-of-00015.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:3ec1e988ee302b3e5bd282f93e18a741c69fec77f2021b397f2478145cdc89b9
|
| 3 |
+
size 4574154552
|
model-00015-of-00015.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1aa8bef406b36ed1479c2e50adb568a1367de94d0bc622a3b8809b4625494cbb
|
| 3 |
+
size 3290673624
|
model.safetensors.index.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:06b9509352d2af50381ab2247e083b80d32d5c0aba91c272ca9ff729b6a0e523
|
| 3 |
+
size 19989325
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_prefix_space": false,
|
| 3 |
+
"audio_bos_token": "<|audio_start|>",
|
| 4 |
+
"audio_eos_token": "<|audio_end|>",
|
| 5 |
+
"audio_token": "<|audio_pad|>",
|
| 6 |
+
"backend": "tokenizers",
|
| 7 |
+
"bos_token": null,
|
| 8 |
+
"clean_up_tokenization_spaces": false,
|
| 9 |
+
"eos_token": "<|endoftext|>",
|
| 10 |
+
"errors": "replace",
|
| 11 |
+
"image_token": "<|image_pad|>",
|
| 12 |
+
"is_local": true,
|
| 13 |
+
"local_files_only": true,
|
| 14 |
+
"model_max_length": 262144,
|
| 15 |
+
"model_specific_special_tokens": {
|
| 16 |
+
"audio_bos_token": "<|audio_start|>",
|
| 17 |
+
"audio_eos_token": "<|audio_end|>",
|
| 18 |
+
"audio_token": "<|audio_pad|>",
|
| 19 |
+
"image_token": "<|image_pad|>",
|
| 20 |
+
"video_token": "<|video_pad|>",
|
| 21 |
+
"vision_bos_token": "<|vision_start|>",
|
| 22 |
+
"vision_eos_token": "<|vision_end|>"
|
| 23 |
+
},
|
| 24 |
+
"pad_token": "<|endoftext|>",
|
| 25 |
+
"pretokenize_regex": "(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\\r\\n\\p{L}\\p{N}]?[\\p{L}\\p{M}]+|\\p{N}| ?[^\\s\\p{L}\\p{M}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+",
|
| 26 |
+
"split_special_tokens": false,
|
| 27 |
+
"tokenizer_class": "Qwen2Tokenizer",
|
| 28 |
+
"unk_token": null,
|
| 29 |
+
"video_token": "<|video_pad|>",
|
| 30 |
+
"vision_bos_token": "<|vision_start|>",
|
| 31 |
+
"vision_eos_token": "<|vision_end|>"
|
| 32 |
+
}
|