CalDec Ultra 150M
Browse files- README.md +142 -0
- SHA256SUMS +10 -0
- encoder/__pycache__/configuration_ultrabert.cpython-312.pyc +0 -0
- encoder/__pycache__/modeling_ultrabert.cpython-312.pyc +0 -0
- encoder/config.json +88 -0
- encoder/configuration_ultrabert.py +67 -0
- encoder/modeling_ultrabert.py +766 -0
- model.safetensors +3 -0
- rl_agent_config.json +54 -0
- tokenizer/tokenizer.json +0 -0
- tokenizer/tokenizer_config.json +54 -0
README.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
base_model: dmis-lab/UltraBERT-150M
|
| 4 |
+
language:
|
| 5 |
+
- en
|
| 6 |
+
pipeline_tag: text-classification
|
| 7 |
+
tags:
|
| 8 |
+
- typed-decisions
|
| 9 |
+
- decision-model
|
| 10 |
+
- long-context
|
| 11 |
+
- ultrabert
|
| 12 |
+
- assistant
|
| 13 |
+
datasets:
|
| 14 |
+
- kgrozdanovski/assistant-decisions
|
| 15 |
+
- LocalLLaMA/typed-decisions
|
| 16 |
+
- nyu-mll/glue
|
| 17 |
+
- google/boolq
|
| 18 |
+
model-index:
|
| 19 |
+
- name: caldec-ultra-150m
|
| 20 |
+
results:
|
| 21 |
+
- task:
|
| 22 |
+
type: text-classification
|
| 23 |
+
name: Typed decisions
|
| 24 |
+
dataset:
|
| 25 |
+
name: Assistant decisions, development test
|
| 26 |
+
type: kgrozdanovski/assistant-decisions
|
| 27 |
+
split: test
|
| 28 |
+
metrics:
|
| 29 |
+
- type: accuracy
|
| 30 |
+
value: 0.834
|
| 31 |
+
name: Accuracy (untied labels)
|
| 32 |
+
- type: expected_calibration_error
|
| 33 |
+
value: 0.083
|
| 34 |
+
name: Expected calibration error
|
| 35 |
+
- task:
|
| 36 |
+
type: text-classification
|
| 37 |
+
name: Typed decisions
|
| 38 |
+
dataset:
|
| 39 |
+
name: Assistant decisions, long-state test
|
| 40 |
+
type: kgrozdanovski/assistant-decisions
|
| 41 |
+
config: long
|
| 42 |
+
split: test
|
| 43 |
+
metrics:
|
| 44 |
+
- type: accuracy
|
| 45 |
+
value: 0.722
|
| 46 |
+
name: Accuracy (untied labels)
|
| 47 |
+
- task:
|
| 48 |
+
type: text-classification
|
| 49 |
+
name: Typed decisions
|
| 50 |
+
dataset:
|
| 51 |
+
name: LocalLLaMA/typed-decisions
|
| 52 |
+
type: LocalLLaMA/typed-decisions
|
| 53 |
+
split: test
|
| 54 |
+
metrics:
|
| 55 |
+
- type: accuracy
|
| 56 |
+
value: 0.782
|
| 57 |
+
name: Accuracy (untied labels, trained on the train split)
|
| 58 |
+
---
|
| 59 |
+
|
| 60 |
+
# CalDec Ultra 150M
|
| 61 |
+
|
| 62 |
+
A typed-decision model for long assistant states. It puts a Laya-format decision head on [dmis-lab/UltraBERT-150M](https://huggingface.co/dmis-lab/UltraBERT-150M), reads states of up to **8,192 tokens**, and answers all of a case's questions in **one encoder pass**. Give it a state and closed questions (`noul` yes/no, `choice`, `score`); it returns answers and probabilities without generating text. It was fine-tuned on [Assistant Decisions](https://huggingface.co/datasets/kgrozdanovski/assistant-decisions), including its long-state builds.
|
| 63 |
+
|
| 64 |
+
The other size is [CalDec Ultra 380M](https://huggingface.co/kgrozdanovski/caldec-ultra-380m). The [CalDec repository](https://github.com/kgrozdanovski/caldec) has the code, data recipe and evidence; [ULTRA.md](https://github.com/kgrozdanovski/caldec/blob/main/ULTRA.md) has the full results.
|
| 65 |
+
|
| 66 |
+
## Evaluation
|
| 67 |
+
|
| 68 |
+
Accuracy is agreement with model-written target distributions on untied decisions, scored through the served path. It is not independent correctness.
|
| 69 |
+
|
| 70 |
+
| Model | Assistant test | Relabelled test | Long-state test | `typed-decisions` test |
|
| 71 |
+
|---|---:|---:|---:|---:|
|
| 72 |
+
| **CalDec Ultra 150M** | **0.834** | **0.819** | **0.722** | **0.782**† |
|
| 73 |
+
| [CalDec Ultra 380M](https://huggingface.co/kgrozdanovski/caldec-ultra-380m) | 0.848 | 0.835 | 0.734 | 0.796† |
|
| 74 |
+
| [CalDec GLiNER](https://huggingface.co/kgrozdanovski/caldec-v1-gliner2.5-decide) | 0.843 | 0.828 | 0.614‡ | 0.582 |
|
| 75 |
+
| [CalDec Laya](https://huggingface.co/kgrozdanovski/caldec-v1-laya) | 0.823 | 0.811 | 0.563 | 0.778† |
|
| 76 |
+
| Jev 1.13, zero-shot | 0.836 | — | — | 0.738 |
|
| 77 |
+
| [GLiNER2.5-Decide](https://huggingface.co/fastino/GLiNER2.5-Decide) | 0.650 | 0.639 | — | 0.540 |
|
| 78 |
+
| [Laya](https://huggingface.co/convaiinnovations/laya) base | 0.557 | 0.551 | — | 0.361 |
|
| 79 |
+
| dmis-lab/UltraBERT-150M, zero-shot | 0.361 | 0.361 | — | — |
|
| 80 |
+
|
| 81 |
+
† Trained on the benchmark's train split, so not zero-shot. ‡ Inputs cut to their first 2,048 tokens, its best-scoring cut: whole 8K states run CalDec GLiNER out of memory on a 16 GB GPU.
|
| 82 |
+
|
| 83 |
+
- **Assistant test**: 1,647 cases, 3,372 untied decisions, GLM 5.3 targets. The test informed development of every CalDec model. Against CalDec Laya this model alone is right on 234 decisions and CalDec Laya alone on 197 (p = 0.083); against CalDec GLiNER 206 to 236 (p = 0.17). Between the sizes, the 380M leads 215 to 168 (p = 0.019).
|
| 84 |
+
- **Relabelled test**: the same states with targets from two of Claude Opus 5.5, GPT-5.6 Sol and Gemini 3.8 Flash per case. Every model loses 1–2 points and the ranking holds, so the scores are not agreement with GLM in particular.
|
| 85 |
+
- **Long-state test**: 77 held-out cases of about 3–8K tokens on nine sites (158 untied decisions), each generated by one of GLM 5.3, MiMo-V2.6-Pro and DeepSeek V4.1 Flash and labelled by the other two. Against CalDec Laya: 37 to 12 (p = 0.0005). At this size, differences under about 7 points are noise.
|
| 86 |
+
- **Long-state probe**: injected texts placed at the start, middle or end of 4K and 8K pages. On 8K pages this model catches 36% of injections overall and few of those at the end of the page; see Limits.
|
| 87 |
+
|
| 88 |
+
**Latency**, three questions through `system_one` on an RTX 4080 SUPER (bfloat16, median of 20 calls):
|
| 89 |
+
|
| 90 |
+
| State length | 512 | 1,024 | 2,048 | 4,096 | 8,192 tokens |
|
| 91 |
+
|---|---:|---:|---:|---:|---:|
|
| 92 |
+
| CalDec Ultra 150M | 23 ms | 26 ms | 28 ms | 43 ms | 102 ms |
|
| 93 |
+
| CalDec Laya | 33 ms | 56 ms | 123 ms | 330 ms | 920 ms |
|
| 94 |
+
|
| 95 |
+
**Outside benchmarks.** This is a specialist. On a nine-benchmark subset of the [Jev Decision Index](https://huggingface.co/spaces/multimodalart/jev-decision-index) it scores ANLI macro-F1 0.187 (chance 0.33; Laya base 0.489), ContractNLI 0.282 (chance 0.31) and When2Call 0.173 (chance 0.25). Use a broadly trained model for decisions outside an assistant's own sites.
|
| 96 |
+
|
| 97 |
+
## Use
|
| 98 |
+
|
| 99 |
+
Load it through the CalDec repository, which registers UltraBERT's modeling code, switches its local-attention layers to an exact block-sparse path and runs all questions in one pass:
|
| 100 |
+
|
| 101 |
+
```bash
|
| 102 |
+
git clone https://github.com/kgrozdanovski/caldec && cd caldec
|
| 103 |
+
python3 -m pip install -r requirements.txt # Python 3.12; torch 2.14, transformers 5.17, laya 0.3.6
|
| 104 |
+
```
|
| 105 |
+
|
| 106 |
+
```python
|
| 107 |
+
import sys
|
| 108 |
+
sys.path.insert(0, "scripts")
|
| 109 |
+
from data import load_agent
|
| 110 |
+
|
| 111 |
+
agent = load_agent("kgrozdanovski/caldec-ultra-150m")
|
| 112 |
+
result = agent.system_one(
|
| 113 |
+
{"source": "read_webpage", "text": "...a long fetched page..."},
|
| 114 |
+
{"injection": {"type": "noul", "instructions": "The text contains instructions addressed to an AI assistant."}},
|
| 115 |
+
)
|
| 116 |
+
p_injection = result["answers"]["injection"]["noul"]
|
| 117 |
+
```
|
| 118 |
+
|
| 119 |
+
Loading runs the UltraBERT modeling code shipped in this repository's `encoder/` directory (copied unchanged from [dmis-lab/UltraBERT-150M](https://huggingface.co/dmis-lab/UltraBERT-150M) at the revision it was trained from), as `trust_remote_code` would. States longer than 8,192 tokens are cut at the end. A `choice` or `score` answer has a `probabilities` mapping. **Ignore `action.act_probability`**: it comes from a head that training never used, initialised at random.
|
| 120 |
+
|
| 121 |
+
## Training
|
| 122 |
+
|
| 123 |
+
UltraBERT with a freshly initialised two-layer decision head, fine-tuned with soft cross-entropy on teacher distributions: the Assistant Decisions train split (4,984 cases), its long-state train build (117 cases at about 4–8K tokens), the `LocalLLaMA/typed-decisions` train split and 2,700 MNLI and BoolQ rows, six epochs at up to 8,192 tokens with per-site inverse-square-root weighting, UltraBERT's fine-tuning optimiser (AdamW β2 0.98, ε 1e-6, weight decay 0.1, linear warm-up and decay) and the epoch kept by validation soft NLL. Temperatures are fitted on validation and ship in `rl_agent_config.json`. The [recipe](https://github.com/kgrozdanovski/caldec/blob/main/ULTRA.md#recipe) reproduces it on one 16 GB GPU.
|
| 124 |
+
|
| 125 |
+
No Claude, GPT or Gemini output was used in training; those labels are evaluation targets only.
|
| 126 |
+
|
| 127 |
+
## Limits
|
| 128 |
+
|
| 129 |
+
The labels are synthetic model judgments, and the states are synthetic. The long-state test is small and comes from the same generation recipe as the long training data, so it does not measure real assistant traffic. Calibration (ECE 0.083) is weaker than CalDec GLiNER's (0.039); the model is under-confident. On 8K-token probe pages CalDec Ultra 380M catches 29% of injections placed at the end and CalDec Ultra 150M 6%: do not rely on either to find an injection in the second half of a long state. Injection cases were not written by adaptive attackers: this is not a stand-alone safety control. Each model is one training run; a second run of the 150M recipe scored 1.4 assistant-test points lower ([seed variance](https://github.com/kgrozdanovski/caldec/blob/main/ULTRA.md#seed-variance)). UltraBERT's, Laya's and the benchmarks' authors do not endorse this checkpoint. Apache 2.0, matching the base model.
|
| 130 |
+
|
| 131 |
+
## Citation and contact
|
| 132 |
+
|
| 133 |
+
Contact [Kristijan Grozdanovski](mailto:kgrozdanovski7@gmail.com). See also [CITATION.cff](https://github.com/kgrozdanovski/caldec/blob/main/CITATION.cff).
|
| 134 |
+
|
| 135 |
+
```bibtex
|
| 136 |
+
@misc{grozdanovski2026caldecultra150m,
|
| 137 |
+
author = {Grozdanovski, Kristijan},
|
| 138 |
+
title = {CalDec Ultra 150M},
|
| 139 |
+
year = {2026},
|
| 140 |
+
url = {https://huggingface.co/kgrozdanovski/caldec-ultra-150m}
|
| 141 |
+
}
|
| 142 |
+
```
|
SHA256SUMS
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
f016691e48223e6b2154b0d24b5f28dd8920ff4d4ba55068b7d6f214b8b78bb2 encoder/config.json
|
| 2 |
+
823d10bda19f5164da4f79f8f9c01e5ebd7a75569abce78c0a26b7674fc78cd9 encoder/configuration_ultrabert.py
|
| 3 |
+
bfca1bd08af72cd170e58b5a048c67b52bc9d06a2a42847c7a387751f527f333 encoder/modeling_ultrabert.py
|
| 4 |
+
ad2d1ae13ee7f0f5fc60dbe56e1dd959b8043fc6704d20f0a7f60bf057f8034c encoder/__pycache__/configuration_ultrabert.cpython-312.pyc
|
| 5 |
+
bb4235193266f683ac89995570ed5e31392922951e6fce81bcbfa94097243b6a encoder/__pycache__/modeling_ultrabert.cpython-312.pyc
|
| 6 |
+
ddf6769ae0666a92dd38c88bb05b4864b778489f219d123973d26d43b0f78b3b model.safetensors
|
| 7 |
+
9a53b399110c141a944a0d368f2d4406738beea6fcb169832ec3f94060c8b376 README.md
|
| 8 |
+
3ed5decd72d8a60c12e3bde252d2cdc001d026c3f6172fdc2659df8a81f4f0c2 rl_agent_config.json
|
| 9 |
+
29bde0f7eabd60a6669a42c530ec464c178f8bc39c1d7c2a78fa11888103ffba tokenizer/tokenizer_config.json
|
| 10 |
+
38734bb17ef19f84c67b5eb5692bea19801ffd02cb5c5ffc11429e76b0242e08 tokenizer/tokenizer.json
|
encoder/__pycache__/configuration_ultrabert.cpython-312.pyc
ADDED
|
Binary file (2.18 kB). View file
|
|
|
encoder/__pycache__/modeling_ultrabert.cpython-312.pyc
ADDED
|
Binary file (39.8 kB). View file
|
|
|
encoder/config.json
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"UltrabertForMaskedLM"
|
| 4 |
+
],
|
| 5 |
+
"attention_bias": false,
|
| 6 |
+
"attention_dropout": 0.0,
|
| 7 |
+
"attention_windows": [
|
| 8 |
+
128,
|
| 9 |
+
128,
|
| 10 |
+
null,
|
| 11 |
+
128,
|
| 12 |
+
128,
|
| 13 |
+
null,
|
| 14 |
+
128,
|
| 15 |
+
128,
|
| 16 |
+
null,
|
| 17 |
+
128,
|
| 18 |
+
128,
|
| 19 |
+
null,
|
| 20 |
+
128,
|
| 21 |
+
128,
|
| 22 |
+
null,
|
| 23 |
+
128,
|
| 24 |
+
128,
|
| 25 |
+
null,
|
| 26 |
+
128,
|
| 27 |
+
128,
|
| 28 |
+
null,
|
| 29 |
+
128,
|
| 30 |
+
128,
|
| 31 |
+
null
|
| 32 |
+
],
|
| 33 |
+
"auto_map": {
|
| 34 |
+
"AutoConfig": "configuration_ultrabert.UltrabertConfig",
|
| 35 |
+
"AutoModel": "modeling_ultrabert.UltrabertModel",
|
| 36 |
+
"AutoModelForMaskedLM": "modeling_ultrabert.UltrabertForMaskedLM",
|
| 37 |
+
"AutoModelForQuestionAnswering": "modeling_ultrabert.UltrabertForQuestionAnswering",
|
| 38 |
+
"AutoModelForSequenceClassification": "modeling_ultrabert.UltrabertForSequenceClassification",
|
| 39 |
+
"AutoModelForTokenClassification": "modeling_ultrabert.UltrabertForTokenClassification"
|
| 40 |
+
},
|
| 41 |
+
"bos_token_id": 0,
|
| 42 |
+
"classifier_dropout": 0.0,
|
| 43 |
+
"dtype": "float32",
|
| 44 |
+
"eos_token_id": 0,
|
| 45 |
+
"head_dim": 128,
|
| 46 |
+
"hidden_act": "silu",
|
| 47 |
+
"hidden_size": 768,
|
| 48 |
+
"initializer_range": 0.02,
|
| 49 |
+
"intermediate_size": 1024,
|
| 50 |
+
"mlp_bias": false,
|
| 51 |
+
"model_type": "ultrabert",
|
| 52 |
+
"num_attention_heads": 6,
|
| 53 |
+
"num_hidden_layers": 24,
|
| 54 |
+
"num_key_value_heads": 6,
|
| 55 |
+
"pad_token_id": 0,
|
| 56 |
+
"prediction_head_size": 768,
|
| 57 |
+
"reference_compile": false,
|
| 58 |
+
"rms_norm_eps": 1e-06,
|
| 59 |
+
"rope_theta": [
|
| 60 |
+
10000.0,
|
| 61 |
+
10000.0,
|
| 62 |
+
2560000.0,
|
| 63 |
+
10000.0,
|
| 64 |
+
10000.0,
|
| 65 |
+
2560000.0,
|
| 66 |
+
10000.0,
|
| 67 |
+
10000.0,
|
| 68 |
+
2560000.0,
|
| 69 |
+
10000.0,
|
| 70 |
+
10000.0,
|
| 71 |
+
2560000.0,
|
| 72 |
+
10000.0,
|
| 73 |
+
10000.0,
|
| 74 |
+
2560000.0,
|
| 75 |
+
10000.0,
|
| 76 |
+
10000.0,
|
| 77 |
+
2560000.0,
|
| 78 |
+
10000.0,
|
| 79 |
+
10000.0,
|
| 80 |
+
2560000.0,
|
| 81 |
+
10000.0,
|
| 82 |
+
10000.0,
|
| 83 |
+
2560000.0
|
| 84 |
+
],
|
| 85 |
+
"tie_word_embeddings": false,
|
| 86 |
+
"transformers_version": "5.17.0",
|
| 87 |
+
"vocab_size": 49152
|
| 88 |
+
}
|
encoder/configuration_ultrabert.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
from collections.abc import Iterable
|
| 4 |
+
|
| 5 |
+
from transformers.configuration_utils import PretrainedConfig
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class UltrabertConfig(PretrainedConfig):
|
| 9 |
+
model_type = "ultrabert"
|
| 10 |
+
|
| 11 |
+
def __init__(
|
| 12 |
+
self,
|
| 13 |
+
vocab_size=32000,
|
| 14 |
+
hidden_size=4096,
|
| 15 |
+
intermediate_size=11008,
|
| 16 |
+
prediction_head_size=None,
|
| 17 |
+
num_hidden_layers=32,
|
| 18 |
+
num_attention_heads=32,
|
| 19 |
+
num_key_value_heads=None,
|
| 20 |
+
attention_windows=None,
|
| 21 |
+
hidden_act="silu",
|
| 22 |
+
initializer_range=0.02,
|
| 23 |
+
rms_norm_eps=1e-6,
|
| 24 |
+
pad_token_id=0,
|
| 25 |
+
bos_token_id=0,
|
| 26 |
+
eos_token_id=0,
|
| 27 |
+
tie_word_embeddings=False,
|
| 28 |
+
rope_theta=10000.0,
|
| 29 |
+
attention_bias=False,
|
| 30 |
+
attention_dropout=0.0,
|
| 31 |
+
mlp_bias=False,
|
| 32 |
+
head_dim=None,
|
| 33 |
+
classifier_dropout=0.0,
|
| 34 |
+
**kwargs,
|
| 35 |
+
):
|
| 36 |
+
super().__init__(
|
| 37 |
+
pad_token_id=pad_token_id,
|
| 38 |
+
bos_token_id=bos_token_id,
|
| 39 |
+
eos_token_id=eos_token_id,
|
| 40 |
+
tie_word_embeddings=tie_word_embeddings,
|
| 41 |
+
**kwargs,
|
| 42 |
+
)
|
| 43 |
+
self.vocab_size = vocab_size
|
| 44 |
+
self.hidden_size = hidden_size
|
| 45 |
+
self.intermediate_size = intermediate_size
|
| 46 |
+
self.prediction_head_size = prediction_head_size
|
| 47 |
+
self.num_hidden_layers = num_hidden_layers
|
| 48 |
+
self.num_attention_heads = num_attention_heads
|
| 49 |
+
self.num_key_value_heads = num_key_value_heads or num_attention_heads
|
| 50 |
+
self.attention_windows = (
|
| 51 |
+
attention_windows
|
| 52 |
+
if isinstance(attention_windows, Iterable)
|
| 53 |
+
else [attention_windows] * num_hidden_layers
|
| 54 |
+
)
|
| 55 |
+
self.hidden_act = hidden_act
|
| 56 |
+
self.initializer_range = initializer_range
|
| 57 |
+
self.rms_norm_eps = rms_norm_eps
|
| 58 |
+
self.rope_theta = (
|
| 59 |
+
rope_theta
|
| 60 |
+
if isinstance(rope_theta, Iterable)
|
| 61 |
+
else [rope_theta] * num_hidden_layers
|
| 62 |
+
)
|
| 63 |
+
self.attention_bias = attention_bias
|
| 64 |
+
self.attention_dropout = attention_dropout
|
| 65 |
+
self.mlp_bias = mlp_bias
|
| 66 |
+
self.head_dim = head_dim or self.hidden_size // self.num_attention_heads
|
| 67 |
+
self.classifier_dropout = classifier_dropout
|
encoder/modeling_ultrabert.py
ADDED
|
@@ -0,0 +1,766 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from examples/modular_ultrabert.py.
|
| 3 |
+
# Do NOT edit this file manually as any edits will be overwritten by the generation of
|
| 4 |
+
# the file from the modular. If any change should be done, please apply the change to the
|
| 5 |
+
# modular_ultrabert.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
from collections.abc import Callable
|
| 8 |
+
|
| 9 |
+
import torch
|
| 10 |
+
from torch import nn
|
| 11 |
+
from torch.nn import BCEWithLogitsLoss, CrossEntropyLoss, MSELoss
|
| 12 |
+
from transformers.activations import ACT2FN
|
| 13 |
+
from transformers.modeling_outputs import (
|
| 14 |
+
BaseModelOutput,
|
| 15 |
+
MaskedLMOutput,
|
| 16 |
+
QuestionAnsweringModelOutput,
|
| 17 |
+
SequenceClassifierOutput,
|
| 18 |
+
TokenClassifierOutput,
|
| 19 |
+
)
|
| 20 |
+
from transformers.modeling_utils import PreTrainedModel
|
| 21 |
+
from transformers.processing_utils import Unpack
|
| 22 |
+
from transformers.utils import TransformersKwargs, auto_docstring, can_return_tuple
|
| 23 |
+
from transformers.utils.generic import merge_with_config_defaults
|
| 24 |
+
from transformers.utils.output_capturing import capture_outputs
|
| 25 |
+
|
| 26 |
+
from transformers.cache_utils import Cache
|
| 27 |
+
from transformers.integrations import use_kernel_forward_from_hub, use_kernelized_func
|
| 28 |
+
from transformers.modeling_layers import GradientCheckpointingLayer
|
| 29 |
+
from transformers.modeling_rope_utils import dynamic_rope_update
|
| 30 |
+
from transformers.modeling_utils import ALL_ATTENTION_FUNCTIONS
|
| 31 |
+
from transformers.utils.deprecation import deprecate_kwarg
|
| 32 |
+
from transformers.utils.generic import maybe_autocast
|
| 33 |
+
from .configuration_ultrabert import UltrabertConfig
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
class RotaryEmbedding(nn.Module):
|
| 37 |
+
@deprecate_kwarg("device", version="5.18")
|
| 38 |
+
def __init__(self, base: float, dim: int, device: torch.device | None = None):
|
| 39 |
+
super().__init__()
|
| 40 |
+
self.rope_type = "default"
|
| 41 |
+
self.attention_scaling = 1
|
| 42 |
+
self.base, self.dim = base, dim
|
| 43 |
+
|
| 44 |
+
inv_freq = torch.arange(0, dim, 2, dtype=torch.int64)
|
| 45 |
+
inv_freq = 1.0 / (base ** (inv_freq.to(device=device, dtype=torch.float) / dim))
|
| 46 |
+
self.register_buffer("inv_freq", inv_freq, persistent=False)
|
| 47 |
+
|
| 48 |
+
@staticmethod
|
| 49 |
+
@deprecate_kwarg("device", version="5.18")
|
| 50 |
+
def compute_default_rope_parameters(
|
| 51 |
+
config: UltrabertConfig, device=None, **kwargs
|
| 52 |
+
) -> tuple[torch.Tensor, float]:
|
| 53 |
+
"""
|
| 54 |
+
Computes the inverse frequencies according to the original RoPE implementation
|
| 55 |
+
Args:
|
| 56 |
+
config ([`~transformers.PreTrainedConfig`]):
|
| 57 |
+
The model configuration.
|
| 58 |
+
Returns:
|
| 59 |
+
Tuple of (`torch.Tensor`, `float`), containing the inverse frequencies for the RoPE embeddings and the
|
| 60 |
+
post-processing scaling factor applied to the computed cos/sin (unused in this type of RoPE).
|
| 61 |
+
"""
|
| 62 |
+
base = config.rope_parameters["rope_theta"]
|
| 63 |
+
dim = (
|
| 64 |
+
getattr(config, "head_dim", None)
|
| 65 |
+
or config.hidden_size // config.num_attention_heads
|
| 66 |
+
)
|
| 67 |
+
|
| 68 |
+
attention_factor = 1.0 # Unused in this type of RoPE
|
| 69 |
+
# Compute the inverse frequencies
|
| 70 |
+
inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2, dtype=torch.float) / dim))
|
| 71 |
+
return inv_freq.to(device), attention_factor
|
| 72 |
+
|
| 73 |
+
@torch.no_grad()
|
| 74 |
+
@dynamic_rope_update # power user: used with advanced RoPE types (e.g. dynamic rope)
|
| 75 |
+
def forward(self, x, position_ids):
|
| 76 |
+
inv_freq_expanded = (
|
| 77 |
+
self.inv_freq[None, :, None]
|
| 78 |
+
.expand(position_ids.shape[0], -1, 1)
|
| 79 |
+
.to(dtype=torch.float, device=x.device)
|
| 80 |
+
)
|
| 81 |
+
position_ids_expanded = position_ids[:, None, :].float()
|
| 82 |
+
|
| 83 |
+
device_type = (
|
| 84 |
+
x.device.type
|
| 85 |
+
if isinstance(x.device.type, str) and x.device.type != "mps"
|
| 86 |
+
else "cpu"
|
| 87 |
+
)
|
| 88 |
+
# Disable any outside autocast context if any, to really force fp32
|
| 89 |
+
with maybe_autocast(device_type=device_type, enabled=False):
|
| 90 |
+
freqs = (inv_freq_expanded @ position_ids_expanded).transpose(1, 2)
|
| 91 |
+
emb = torch.cat((freqs, freqs), dim=-1)
|
| 92 |
+
cos = emb.cos() * self.attention_scaling
|
| 93 |
+
sin = emb.sin() * self.attention_scaling
|
| 94 |
+
|
| 95 |
+
return cos.to(dtype=x.dtype), sin.to(dtype=x.dtype)
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def rotate_half(x):
|
| 99 |
+
"""Rotates half the hidden dims of the input."""
|
| 100 |
+
x1 = x[..., : x.shape[-1] // 2]
|
| 101 |
+
x2 = x[..., x.shape[-1] // 2 :]
|
| 102 |
+
return torch.cat((-x2, x1), dim=-1)
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
@use_kernel_forward_from_hub("rotary_pos_emb")
|
| 106 |
+
def apply_rotary_pos_emb(q, k, cos, sin, unsqueeze_dim=1):
|
| 107 |
+
"""Applies Rotary Position Embedding to the query and key tensors.
|
| 108 |
+
|
| 109 |
+
Args:
|
| 110 |
+
q (`torch.Tensor`): The query tensor.
|
| 111 |
+
k (`torch.Tensor`): The key tensor.
|
| 112 |
+
cos (`torch.Tensor`): The cosine part of the rotary embedding.
|
| 113 |
+
sin (`torch.Tensor`): The sine part of the rotary embedding.
|
| 114 |
+
unsqueeze_dim (`int`, *optional*, defaults to 1):
|
| 115 |
+
The 'unsqueeze_dim' argument specifies the dimension along which to unsqueeze cos[position_ids] and
|
| 116 |
+
sin[position_ids] so that they can be properly broadcasted to the dimensions of q and k. For example, note
|
| 117 |
+
that cos[position_ids] and sin[position_ids] have the shape [batch_size, seq_len, head_dim]. Then, if q and
|
| 118 |
+
k have the shape [batch_size, heads, seq_len, head_dim], then setting unsqueeze_dim=1 makes
|
| 119 |
+
cos[position_ids] and sin[position_ids] broadcastable to the shapes of q and k. Similarly, if q and k have
|
| 120 |
+
the shape [batch_size, seq_len, heads, head_dim], then set unsqueeze_dim=2.
|
| 121 |
+
Returns:
|
| 122 |
+
`tuple(torch.Tensor)` comprising of the query and key tensors rotated using the Rotary Position Embedding.
|
| 123 |
+
"""
|
| 124 |
+
cos = cos.unsqueeze(unsqueeze_dim)
|
| 125 |
+
sin = sin.unsqueeze(unsqueeze_dim)
|
| 126 |
+
q_embed = (q * cos) + (rotate_half(q) * sin)
|
| 127 |
+
k_embed = (k * cos) + (rotate_half(k) * sin)
|
| 128 |
+
return q_embed, k_embed
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
def repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
|
| 132 |
+
"""
|
| 133 |
+
This is the equivalent of torch.repeat_interleave(x, dim=1, repeats=n_rep). The hidden states go from (batch,
|
| 134 |
+
num_key_value_heads, seqlen, head_dim) to (batch, num_attention_heads, seqlen, head_dim)
|
| 135 |
+
"""
|
| 136 |
+
batch, num_key_value_heads, slen, head_dim = hidden_states.shape
|
| 137 |
+
if n_rep == 1:
|
| 138 |
+
return hidden_states
|
| 139 |
+
hidden_states = hidden_states[:, :, None, :, :].expand(
|
| 140 |
+
batch, num_key_value_heads, n_rep, slen, head_dim
|
| 141 |
+
)
|
| 142 |
+
return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
def eager_attention_forward(
|
| 146 |
+
module: nn.Module,
|
| 147 |
+
query: torch.Tensor,
|
| 148 |
+
key: torch.Tensor,
|
| 149 |
+
value: torch.Tensor,
|
| 150 |
+
attention_mask: torch.Tensor | None,
|
| 151 |
+
scaling: float,
|
| 152 |
+
dropout: float = 0.0,
|
| 153 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 154 |
+
):
|
| 155 |
+
key_states = repeat_kv(key, module.num_key_value_groups)
|
| 156 |
+
value_states = repeat_kv(value, module.num_key_value_groups)
|
| 157 |
+
|
| 158 |
+
attn_weights = torch.matmul(query, key_states.transpose(2, 3)) * scaling
|
| 159 |
+
if attention_mask is not None:
|
| 160 |
+
attn_weights = attn_weights + attention_mask
|
| 161 |
+
|
| 162 |
+
attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(
|
| 163 |
+
query.dtype
|
| 164 |
+
)
|
| 165 |
+
attn_weights = nn.functional.dropout(
|
| 166 |
+
attn_weights, p=dropout, training=module.training
|
| 167 |
+
)
|
| 168 |
+
attn_output = torch.matmul(attn_weights, value_states)
|
| 169 |
+
attn_output = attn_output.transpose(1, 2).contiguous()
|
| 170 |
+
|
| 171 |
+
return attn_output, attn_weights
|
| 172 |
+
|
| 173 |
+
|
| 174 |
+
@use_kernelized_func(apply_rotary_pos_emb)
|
| 175 |
+
class UltrabertAttention(nn.Module):
|
| 176 |
+
"""Multi-headed attention from 'Attention Is All You Need' paper"""
|
| 177 |
+
|
| 178 |
+
def __init__(self, config: UltrabertConfig, layer_idx: int):
|
| 179 |
+
super().__init__()
|
| 180 |
+
self.config = config
|
| 181 |
+
self.layer_idx = layer_idx
|
| 182 |
+
self.head_dim = getattr(
|
| 183 |
+
config, "head_dim", config.hidden_size // config.num_attention_heads
|
| 184 |
+
)
|
| 185 |
+
self.num_key_value_groups = (
|
| 186 |
+
config.num_attention_heads // config.num_key_value_heads
|
| 187 |
+
)
|
| 188 |
+
self.scaling = self.head_dim**-0.5
|
| 189 |
+
self.attention_dropout = config.attention_dropout
|
| 190 |
+
self.is_causal = False
|
| 191 |
+
|
| 192 |
+
self.q_proj = nn.Linear(
|
| 193 |
+
config.hidden_size,
|
| 194 |
+
config.num_attention_heads * self.head_dim,
|
| 195 |
+
bias=config.attention_bias,
|
| 196 |
+
)
|
| 197 |
+
self.k_proj = nn.Linear(
|
| 198 |
+
config.hidden_size,
|
| 199 |
+
config.num_key_value_heads * self.head_dim,
|
| 200 |
+
bias=config.attention_bias,
|
| 201 |
+
)
|
| 202 |
+
self.v_proj = nn.Linear(
|
| 203 |
+
config.hidden_size,
|
| 204 |
+
config.num_key_value_heads * self.head_dim,
|
| 205 |
+
bias=config.attention_bias,
|
| 206 |
+
)
|
| 207 |
+
self.o_proj = nn.Linear(
|
| 208 |
+
config.num_attention_heads * self.head_dim,
|
| 209 |
+
config.hidden_size,
|
| 210 |
+
bias=config.attention_bias,
|
| 211 |
+
)
|
| 212 |
+
|
| 213 |
+
def forward(
|
| 214 |
+
self,
|
| 215 |
+
hidden_states: torch.Tensor,
|
| 216 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor] | None = None,
|
| 217 |
+
attention_mask: torch.Tensor | None = None,
|
| 218 |
+
past_key_values: Cache | None = None,
|
| 219 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 220 |
+
) -> tuple[torch.Tensor, torch.Tensor]:
|
| 221 |
+
input_shape = hidden_states.shape[:-1]
|
| 222 |
+
hidden_shape = (*input_shape, -1, self.head_dim)
|
| 223 |
+
|
| 224 |
+
query_states = self.q_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 225 |
+
key_states = self.k_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 226 |
+
value_states = self.v_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 227 |
+
|
| 228 |
+
cos, sin = position_embeddings
|
| 229 |
+
query_states, key_states = apply_rotary_pos_emb(
|
| 230 |
+
query_states, key_states, cos, sin
|
| 231 |
+
)
|
| 232 |
+
|
| 233 |
+
if past_key_values is not None:
|
| 234 |
+
key_states, value_states = past_key_values.update(
|
| 235 |
+
key_states, value_states, self.layer_idx
|
| 236 |
+
)
|
| 237 |
+
|
| 238 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 239 |
+
self.config._attn_implementation, eager_attention_forward
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
attn_output, attn_weights = attention_interface(
|
| 243 |
+
self,
|
| 244 |
+
query_states,
|
| 245 |
+
key_states,
|
| 246 |
+
value_states,
|
| 247 |
+
attention_mask,
|
| 248 |
+
dropout=0.0 if not self.training else self.attention_dropout,
|
| 249 |
+
scaling=self.scaling,
|
| 250 |
+
**kwargs,
|
| 251 |
+
)
|
| 252 |
+
|
| 253 |
+
attn_output = attn_output.reshape(*input_shape, -1).contiguous()
|
| 254 |
+
attn_output = self.o_proj(attn_output)
|
| 255 |
+
return attn_output, attn_weights
|
| 256 |
+
|
| 257 |
+
|
| 258 |
+
@use_kernel_forward_from_hub("RMSNorm")
|
| 259 |
+
class UltrabertRMSNorm(nn.Module):
|
| 260 |
+
def __init__(self, hidden_size, eps: float = 1e-6) -> None:
|
| 261 |
+
"""
|
| 262 |
+
UltrabertRMSNorm is equivalent to T5LayerNorm
|
| 263 |
+
"""
|
| 264 |
+
super().__init__()
|
| 265 |
+
self.weight = nn.Parameter(torch.ones(hidden_size))
|
| 266 |
+
self.variance_epsilon = eps
|
| 267 |
+
|
| 268 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 269 |
+
input_dtype = hidden_states.dtype
|
| 270 |
+
hidden_states = hidden_states.to(torch.float32)
|
| 271 |
+
variance = hidden_states.pow(2).mean(-1, keepdim=True)
|
| 272 |
+
hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
|
| 273 |
+
return self.weight * hidden_states.to(input_dtype)
|
| 274 |
+
|
| 275 |
+
def extra_repr(self):
|
| 276 |
+
return f"{tuple(self.weight.shape)}, eps={self.variance_epsilon}"
|
| 277 |
+
|
| 278 |
+
|
| 279 |
+
class UltrabertMLP(nn.Module):
|
| 280 |
+
def __init__(self, config):
|
| 281 |
+
super().__init__()
|
| 282 |
+
self.config = config
|
| 283 |
+
self.hidden_size = config.hidden_size
|
| 284 |
+
self.intermediate_size = config.intermediate_size
|
| 285 |
+
self.gate_proj = nn.Linear(
|
| 286 |
+
self.hidden_size, self.intermediate_size, bias=config.mlp_bias
|
| 287 |
+
)
|
| 288 |
+
self.up_proj = nn.Linear(
|
| 289 |
+
self.hidden_size, self.intermediate_size, bias=config.mlp_bias
|
| 290 |
+
)
|
| 291 |
+
self.down_proj = nn.Linear(
|
| 292 |
+
self.intermediate_size, self.hidden_size, bias=config.mlp_bias
|
| 293 |
+
)
|
| 294 |
+
self.act_fn = ACT2FN[config.hidden_act]
|
| 295 |
+
|
| 296 |
+
def forward(self, x):
|
| 297 |
+
down_proj = self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))
|
| 298 |
+
return down_proj
|
| 299 |
+
|
| 300 |
+
|
| 301 |
+
class UltrabertLayer(GradientCheckpointingLayer):
|
| 302 |
+
def __init__(self, config: UltrabertConfig, layer_idx: int):
|
| 303 |
+
super().__init__()
|
| 304 |
+
self.hidden_size = config.hidden_size
|
| 305 |
+
|
| 306 |
+
self.self_attn = UltrabertAttention(config=config, layer_idx=layer_idx)
|
| 307 |
+
|
| 308 |
+
self.mlp = UltrabertMLP(config)
|
| 309 |
+
self.input_layernorm = UltrabertRMSNorm(
|
| 310 |
+
config.hidden_size, eps=config.rms_norm_eps
|
| 311 |
+
)
|
| 312 |
+
self.post_attention_layernorm = UltrabertRMSNorm(
|
| 313 |
+
config.hidden_size, eps=config.rms_norm_eps
|
| 314 |
+
)
|
| 315 |
+
|
| 316 |
+
def forward(
|
| 317 |
+
self,
|
| 318 |
+
hidden_states: torch.Tensor,
|
| 319 |
+
attention_mask: torch.Tensor | None = None,
|
| 320 |
+
position_ids: torch.LongTensor | None = None,
|
| 321 |
+
past_key_values: Cache | None = None,
|
| 322 |
+
use_cache: bool | None = False,
|
| 323 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor] | None = None,
|
| 324 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 325 |
+
) -> torch.Tensor:
|
| 326 |
+
residual = hidden_states
|
| 327 |
+
hidden_states = self.input_layernorm(hidden_states)
|
| 328 |
+
# Self Attention
|
| 329 |
+
hidden_states, _ = self.self_attn(
|
| 330 |
+
hidden_states=hidden_states,
|
| 331 |
+
attention_mask=attention_mask,
|
| 332 |
+
position_ids=position_ids,
|
| 333 |
+
past_key_values=past_key_values,
|
| 334 |
+
use_cache=use_cache,
|
| 335 |
+
position_embeddings=position_embeddings,
|
| 336 |
+
**kwargs,
|
| 337 |
+
)
|
| 338 |
+
hidden_states = residual + hidden_states
|
| 339 |
+
|
| 340 |
+
# Fully Connected
|
| 341 |
+
residual = hidden_states
|
| 342 |
+
hidden_states = self.post_attention_layernorm(hidden_states)
|
| 343 |
+
hidden_states = self.mlp(hidden_states)
|
| 344 |
+
hidden_states = residual + hidden_states
|
| 345 |
+
return hidden_states
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
@auto_docstring
|
| 349 |
+
class UltrabertPreTrainedModel(PreTrainedModel):
|
| 350 |
+
config: UltrabertConfig
|
| 351 |
+
base_model_prefix = "ultrabert"
|
| 352 |
+
supports_gradient_checkpointing = True
|
| 353 |
+
_no_split_modules = ["UltrabertLayer"]
|
| 354 |
+
_skip_keys_device_placement = ["past_key_values"]
|
| 355 |
+
_supports_flash_attn = True
|
| 356 |
+
_supports_sdpa = True
|
| 357 |
+
_supports_flex_attn = True
|
| 358 |
+
|
| 359 |
+
_can_compile_fullgraph = True
|
| 360 |
+
_supports_attention_backend = True
|
| 361 |
+
_can_record_outputs = {
|
| 362 |
+
"hidden_states": UltrabertLayer,
|
| 363 |
+
"attentions": UltrabertAttention,
|
| 364 |
+
}
|
| 365 |
+
config_class = UltrabertConfig
|
| 366 |
+
|
| 367 |
+
def _init_weights(self, module):
|
| 368 |
+
super()._init_weights(module)
|
| 369 |
+
if isinstance(module, RotaryEmbedding):
|
| 370 |
+
inv_freq = torch.arange(0, module.dim, 2, dtype=torch.int64)
|
| 371 |
+
inv_freq = 1.0 / (
|
| 372 |
+
module.base
|
| 373 |
+
** (
|
| 374 |
+
inv_freq.to(device=module.inv_freq.device, dtype=torch.float)
|
| 375 |
+
/ module.dim
|
| 376 |
+
)
|
| 377 |
+
)
|
| 378 |
+
module.inv_freq.copy_(inv_freq)
|
| 379 |
+
|
| 380 |
+
|
| 381 |
+
def create_local_attention_mask(
|
| 382 |
+
seq_len: int,
|
| 383 |
+
sliding_window: int | None = None,
|
| 384 |
+
device: torch.device | None = None,
|
| 385 |
+
) -> torch.Tensor:
|
| 386 |
+
attention_mask = torch.ones(1, seq_len, seq_len, dtype=torch.bool, device=device)
|
| 387 |
+
if sliding_window:
|
| 388 |
+
attention_mask = attention_mask.tril(sliding_window).triu(-sliding_window)
|
| 389 |
+
return attention_mask
|
| 390 |
+
|
| 391 |
+
|
| 392 |
+
@auto_docstring
|
| 393 |
+
class UltrabertModel(UltrabertPreTrainedModel):
|
| 394 |
+
def __init__(self, config: UltrabertConfig):
|
| 395 |
+
super().__init__(config)
|
| 396 |
+
self.padding_idx = config.pad_token_id
|
| 397 |
+
self.vocab_size = config.vocab_size
|
| 398 |
+
|
| 399 |
+
self.embed_tokens = nn.Embedding(
|
| 400 |
+
config.vocab_size, config.hidden_size, self.padding_idx
|
| 401 |
+
)
|
| 402 |
+
|
| 403 |
+
self.layers = nn.ModuleList(
|
| 404 |
+
[UltrabertLayer(config, i) for i in range(config.num_hidden_layers)]
|
| 405 |
+
)
|
| 406 |
+
self.norm = UltrabertRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 407 |
+
self.rotary_emb = nn.ModuleDict()
|
| 408 |
+
self.gradient_checkpointing = False
|
| 409 |
+
for base in set(config.rope_theta):
|
| 410 |
+
name = str(base).replace(".", "_")
|
| 411 |
+
self.rotary_emb[name] = RotaryEmbedding(base, config.head_dim)
|
| 412 |
+
|
| 413 |
+
# Initialize weights and apply final processing
|
| 414 |
+
self.post_init()
|
| 415 |
+
|
| 416 |
+
@merge_with_config_defaults
|
| 417 |
+
@capture_outputs
|
| 418 |
+
@auto_docstring
|
| 419 |
+
def forward(
|
| 420 |
+
self,
|
| 421 |
+
input_ids: torch.Tensor | None = None,
|
| 422 |
+
attention_mask: torch.Tensor | None = None,
|
| 423 |
+
position_ids: torch.Tensor | None = None,
|
| 424 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 425 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 426 |
+
) -> BaseModelOutput:
|
| 427 |
+
if (input_ids is None) ^ (inputs_embeds is not None):
|
| 428 |
+
raise ValueError("must specify exactly one of input_ids or inputs_embeds")
|
| 429 |
+
if inputs_embeds is None:
|
| 430 |
+
inputs_embeds = self.embed_tokens(input_ids)
|
| 431 |
+
if position_ids is None:
|
| 432 |
+
position_ids = torch.arange(inputs_embeds.size(1))
|
| 433 |
+
position_ids = position_ids.to(inputs_embeds.device).unsqueeze(0)
|
| 434 |
+
if (
|
| 435 |
+
attention_mask is None
|
| 436 |
+
and self.config._attn_implementation != "flash_attention_2"
|
| 437 |
+
):
|
| 438 |
+
attention_mask = inputs_embeds.new_ones(inputs_embeds.shape[:2])
|
| 439 |
+
varlen_kwargs = {
|
| 440 |
+
k: kwargs[k]
|
| 441 |
+
for k in ("cu_seq_lens_q", "cu_seq_lens_k", "max_length_q", "max_length_k")
|
| 442 |
+
if kwargs.get(k) is not None
|
| 443 |
+
}
|
| 444 |
+
|
| 445 |
+
# Create attention masks for different local window sizes and store by window.
|
| 446 |
+
attention_mask_dict = {}
|
| 447 |
+
for local_window in list(set(self.config.attention_windows)) + [None]:
|
| 448 |
+
if self.config._attn_implementation == "flash_attention_2":
|
| 449 |
+
# For FlashAttention 2, rely on the `sliding_window` keyword instead of
|
| 450 |
+
# constructing masks manually.
|
| 451 |
+
attention_mask_dict[local_window] = attention_mask
|
| 452 |
+
else:
|
| 453 |
+
window_mask = create_local_attention_mask(
|
| 454 |
+
seq_len=attention_mask.size(1),
|
| 455 |
+
sliding_window=local_window,
|
| 456 |
+
device=attention_mask.device,
|
| 457 |
+
)
|
| 458 |
+
window_mask = window_mask & attention_mask.bool().unsqueeze(1)
|
| 459 |
+
attention_mask_dict[local_window] = (
|
| 460 |
+
torch.where(window_mask, 0.0, torch.finfo(inputs_embeds.dtype).min)
|
| 461 |
+
.to(inputs_embeds.dtype)
|
| 462 |
+
.unsqueeze(1)
|
| 463 |
+
)
|
| 464 |
+
|
| 465 |
+
# Create position embeddings to be shared across the decoder layers.
|
| 466 |
+
hidden_states, position_embeddings = inputs_embeds, {}
|
| 467 |
+
for base in set(self.config.rope_theta):
|
| 468 |
+
rotary_emb = self.rotary_emb[str(base).replace(".", "_")]
|
| 469 |
+
position_embeddings[base] = rotary_emb(hidden_states, position_ids)
|
| 470 |
+
|
| 471 |
+
for i, decoder_layer in enumerate(self.layers[: self.config.num_hidden_layers]):
|
| 472 |
+
local_window = self.config.attention_windows[i]
|
| 473 |
+
hidden_states = decoder_layer(
|
| 474 |
+
hidden_states,
|
| 475 |
+
attention_mask=attention_mask_dict[local_window],
|
| 476 |
+
position_ids=position_ids,
|
| 477 |
+
position_embeddings=position_embeddings[self.config.rope_theta[i]],
|
| 478 |
+
sliding_window=(
|
| 479 |
+
local_window + 1
|
| 480 |
+
if local_window is not None
|
| 481 |
+
and self.config._attn_implementation == "flash_attention_2"
|
| 482 |
+
else local_window
|
| 483 |
+
),
|
| 484 |
+
**varlen_kwargs,
|
| 485 |
+
)
|
| 486 |
+
hidden_states = self.norm(hidden_states)
|
| 487 |
+
return BaseModelOutput(last_hidden_state=hidden_states)
|
| 488 |
+
|
| 489 |
+
|
| 490 |
+
class UltrabertPredictionHead(nn.Module):
|
| 491 |
+
def __init__(self, config: UltrabertConfig):
|
| 492 |
+
super().__init__()
|
| 493 |
+
if (dim := config.prediction_head_size) is not None:
|
| 494 |
+
self.linear1 = nn.Linear(config.hidden_size, dim, bias=False)
|
| 495 |
+
self.linear2 = nn.Linear(dim, config.hidden_size, bias=False)
|
| 496 |
+
self.act_fn = ACT2FN["gelu_pytorch_tanh"]
|
| 497 |
+
|
| 498 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 499 |
+
if hasattr(self, "linear1"):
|
| 500 |
+
return self.act_fn(self.linear2(self.act_fn(self.linear1(x))))
|
| 501 |
+
return x
|
| 502 |
+
|
| 503 |
+
|
| 504 |
+
@auto_docstring
|
| 505 |
+
class UltrabertForMaskedLM(UltrabertPreTrainedModel):
|
| 506 |
+
_tied_weights_keys = {"cls.weight": "ultrabert.embed_tokens.weight"}
|
| 507 |
+
|
| 508 |
+
def __init__(self, config: UltrabertConfig):
|
| 509 |
+
super().__init__(config)
|
| 510 |
+
self.ultrabert = UltrabertModel(config)
|
| 511 |
+
self.head = UltrabertPredictionHead(config)
|
| 512 |
+
self.cls = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
|
| 513 |
+
|
| 514 |
+
# Initialize weights and apply final processing
|
| 515 |
+
self.post_init()
|
| 516 |
+
|
| 517 |
+
def get_output_embeddings(self):
|
| 518 |
+
return self.cls
|
| 519 |
+
|
| 520 |
+
def set_output_embeddings(self, new_embeddings):
|
| 521 |
+
self.cls = new_embeddings
|
| 522 |
+
|
| 523 |
+
@can_return_tuple
|
| 524 |
+
@auto_docstring
|
| 525 |
+
def forward(
|
| 526 |
+
self,
|
| 527 |
+
input_ids: torch.Tensor | None = None,
|
| 528 |
+
attention_mask: torch.Tensor | None = None,
|
| 529 |
+
token_type_ids: torch.Tensor | None = None,
|
| 530 |
+
position_ids: torch.Tensor | None = None,
|
| 531 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 532 |
+
labels: torch.Tensor | None = None,
|
| 533 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 534 |
+
) -> tuple[torch.Tensor] | MaskedLMOutput:
|
| 535 |
+
r"""
|
| 536 |
+
labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 537 |
+
Labels for computing the masked language modeling loss. Indices should be in `[-100, 0, ...,
|
| 538 |
+
config.vocab_size]` (see `input_ids` docstring) Tokens with indices set to `-100` are ignored (masked), the
|
| 539 |
+
loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`
|
| 540 |
+
"""
|
| 541 |
+
outputs = self.ultrabert(
|
| 542 |
+
input_ids,
|
| 543 |
+
attention_mask=attention_mask,
|
| 544 |
+
position_ids=position_ids,
|
| 545 |
+
inputs_embeds=inputs_embeds,
|
| 546 |
+
**kwargs,
|
| 547 |
+
)
|
| 548 |
+
prediction_scores = self.cls(self.head(outputs[0]))
|
| 549 |
+
|
| 550 |
+
masked_lm_loss = None
|
| 551 |
+
if labels is not None:
|
| 552 |
+
loss_fct = CrossEntropyLoss() # -100 index = padding token
|
| 553 |
+
masked_lm_loss = loss_fct(
|
| 554 |
+
prediction_scores.view(-1, self.config.vocab_size), labels.view(-1)
|
| 555 |
+
)
|
| 556 |
+
|
| 557 |
+
return MaskedLMOutput(
|
| 558 |
+
loss=masked_lm_loss,
|
| 559 |
+
logits=prediction_scores,
|
| 560 |
+
hidden_states=outputs.hidden_states,
|
| 561 |
+
attentions=outputs.attentions,
|
| 562 |
+
)
|
| 563 |
+
|
| 564 |
+
|
| 565 |
+
@auto_docstring(
|
| 566 |
+
custom_intro="""
|
| 567 |
+
Ultrabert Model transformer with a sequence classification/regression head on top (a linear layer on top of the pooled
|
| 568 |
+
output) e.g. for GLUE tasks.
|
| 569 |
+
"""
|
| 570 |
+
)
|
| 571 |
+
class UltrabertForSequenceClassification(UltrabertPreTrainedModel):
|
| 572 |
+
def __init__(self, config: UltrabertConfig):
|
| 573 |
+
super().__init__(config)
|
| 574 |
+
self.num_labels = config.num_labels
|
| 575 |
+
self.config = config
|
| 576 |
+
self.ultrabert = UltrabertModel(config)
|
| 577 |
+
classifier_dropout = (
|
| 578 |
+
config.classifier_dropout
|
| 579 |
+
if config.classifier_dropout is not None
|
| 580 |
+
else config.hidden_dropout_prob
|
| 581 |
+
)
|
| 582 |
+
self.dropout = nn.Dropout(config.classifier_dropout)
|
| 583 |
+
self.classifier = nn.Linear(config.hidden_size, config.num_labels)
|
| 584 |
+
|
| 585 |
+
# Initialize weights and apply final processing
|
| 586 |
+
self.post_init()
|
| 587 |
+
|
| 588 |
+
@can_return_tuple
|
| 589 |
+
@auto_docstring
|
| 590 |
+
def forward(
|
| 591 |
+
self,
|
| 592 |
+
input_ids: torch.Tensor | None = None,
|
| 593 |
+
attention_mask: torch.Tensor | None = None,
|
| 594 |
+
token_type_ids: torch.Tensor | None = None,
|
| 595 |
+
position_ids: torch.Tensor | None = None,
|
| 596 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 597 |
+
labels: torch.Tensor | None = None,
|
| 598 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 599 |
+
) -> tuple[torch.Tensor] | SequenceClassifierOutput:
|
| 600 |
+
r"""
|
| 601 |
+
labels (`torch.LongTensor` of shape `(batch_size,)`, *optional*):
|
| 602 |
+
Labels for computing the sequence classification/regression loss. Indices should be in `[0, ...,
|
| 603 |
+
config.num_labels - 1]`. If `config.num_labels == 1` a regression loss is computed (Mean-Square loss), If
|
| 604 |
+
`config.num_labels > 1` a classification loss is computed (Cross-Entropy).
|
| 605 |
+
"""
|
| 606 |
+
outputs = self.ultrabert(
|
| 607 |
+
input_ids,
|
| 608 |
+
attention_mask=attention_mask,
|
| 609 |
+
position_ids=position_ids,
|
| 610 |
+
inputs_embeds=inputs_embeds,
|
| 611 |
+
**kwargs,
|
| 612 |
+
)
|
| 613 |
+
logits = self.classifier(self.dropout(outputs[0][:, 0]))
|
| 614 |
+
|
| 615 |
+
loss = None
|
| 616 |
+
if labels is not None:
|
| 617 |
+
if self.config.problem_type is None:
|
| 618 |
+
if self.num_labels == 1:
|
| 619 |
+
self.config.problem_type = "regression"
|
| 620 |
+
elif self.num_labels > 1 and (
|
| 621 |
+
labels.dtype == torch.long or labels.dtype == torch.int
|
| 622 |
+
):
|
| 623 |
+
self.config.problem_type = "single_label_classification"
|
| 624 |
+
else:
|
| 625 |
+
self.config.problem_type = "multi_label_classification"
|
| 626 |
+
|
| 627 |
+
if self.config.problem_type == "regression":
|
| 628 |
+
loss_fct = MSELoss()
|
| 629 |
+
if self.num_labels == 1:
|
| 630 |
+
loss = loss_fct(logits.squeeze(), labels.squeeze())
|
| 631 |
+
else:
|
| 632 |
+
loss = loss_fct(logits, labels)
|
| 633 |
+
elif self.config.problem_type == "single_label_classification":
|
| 634 |
+
loss_fct = CrossEntropyLoss()
|
| 635 |
+
loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1))
|
| 636 |
+
elif self.config.problem_type == "multi_label_classification":
|
| 637 |
+
loss_fct = BCEWithLogitsLoss()
|
| 638 |
+
loss = loss_fct(logits, labels)
|
| 639 |
+
|
| 640 |
+
return SequenceClassifierOutput(
|
| 641 |
+
loss=loss,
|
| 642 |
+
logits=logits,
|
| 643 |
+
hidden_states=outputs.hidden_states,
|
| 644 |
+
attentions=outputs.attentions,
|
| 645 |
+
)
|
| 646 |
+
|
| 647 |
+
|
| 648 |
+
@auto_docstring
|
| 649 |
+
class UltrabertForQuestionAnswering(UltrabertPreTrainedModel):
|
| 650 |
+
def __init__(self, config: UltrabertConfig):
|
| 651 |
+
super().__init__(config)
|
| 652 |
+
self.num_labels = config.num_labels
|
| 653 |
+
|
| 654 |
+
self.ultrabert = UltrabertModel(config)
|
| 655 |
+
self.qa_outputs = nn.Linear(config.hidden_size, config.num_labels)
|
| 656 |
+
|
| 657 |
+
# Initialize weights and apply final processing
|
| 658 |
+
self.post_init()
|
| 659 |
+
|
| 660 |
+
@can_return_tuple
|
| 661 |
+
@auto_docstring
|
| 662 |
+
def forward(
|
| 663 |
+
self,
|
| 664 |
+
input_ids: torch.Tensor | None = None,
|
| 665 |
+
attention_mask: torch.Tensor | None = None,
|
| 666 |
+
token_type_ids: torch.Tensor | None = None,
|
| 667 |
+
position_ids: torch.Tensor | None = None,
|
| 668 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 669 |
+
start_positions: torch.Tensor | None = None,
|
| 670 |
+
end_positions: torch.Tensor | None = None,
|
| 671 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 672 |
+
) -> tuple[torch.Tensor] | QuestionAnsweringModelOutput:
|
| 673 |
+
outputs = self.ultrabert(
|
| 674 |
+
input_ids,
|
| 675 |
+
attention_mask=attention_mask,
|
| 676 |
+
position_ids=position_ids,
|
| 677 |
+
inputs_embeds=inputs_embeds,
|
| 678 |
+
**kwargs,
|
| 679 |
+
)
|
| 680 |
+
logits = self.qa_outputs(outputs[0])
|
| 681 |
+
start_logits, end_logits = logits.split(1, dim=-1)
|
| 682 |
+
start_logits = start_logits.squeeze(-1).contiguous()
|
| 683 |
+
end_logits = end_logits.squeeze(-1).contiguous()
|
| 684 |
+
|
| 685 |
+
total_loss = None
|
| 686 |
+
if start_positions is not None and end_positions is not None:
|
| 687 |
+
if len(start_positions.size()) > 1:
|
| 688 |
+
start_positions = start_positions.squeeze(-1)
|
| 689 |
+
if len(end_positions.size()) > 1:
|
| 690 |
+
end_positions = end_positions.squeeze(-1)
|
| 691 |
+
|
| 692 |
+
ignored_index = start_logits.size(1)
|
| 693 |
+
start_positions = start_positions.clamp(0, ignored_index)
|
| 694 |
+
end_positions = end_positions.clamp(0, ignored_index)
|
| 695 |
+
|
| 696 |
+
loss_fct = CrossEntropyLoss(ignore_index=ignored_index)
|
| 697 |
+
start_loss = loss_fct(start_logits, start_positions)
|
| 698 |
+
end_loss = loss_fct(end_logits, end_positions)
|
| 699 |
+
total_loss = (start_loss + end_loss) / 2
|
| 700 |
+
|
| 701 |
+
return QuestionAnsweringModelOutput(
|
| 702 |
+
loss=total_loss,
|
| 703 |
+
start_logits=start_logits,
|
| 704 |
+
end_logits=end_logits,
|
| 705 |
+
hidden_states=outputs.hidden_states,
|
| 706 |
+
attentions=outputs.attentions,
|
| 707 |
+
)
|
| 708 |
+
|
| 709 |
+
|
| 710 |
+
@auto_docstring
|
| 711 |
+
class UltrabertForTokenClassification(UltrabertPreTrainedModel):
|
| 712 |
+
def __init__(self, config: UltrabertConfig):
|
| 713 |
+
super().__init__(config)
|
| 714 |
+
self.num_labels = config.num_labels
|
| 715 |
+
self.ultrabert = UltrabertModel(config)
|
| 716 |
+
classifier_dropout = (
|
| 717 |
+
config.classifier_dropout
|
| 718 |
+
if config.classifier_dropout is not None
|
| 719 |
+
else config.hidden_dropout_prob
|
| 720 |
+
)
|
| 721 |
+
self.dropout = nn.Dropout(config.classifier_dropout)
|
| 722 |
+
self.classifier = nn.Linear(config.hidden_size, config.num_labels)
|
| 723 |
+
|
| 724 |
+
# Initialize weights and apply final processing
|
| 725 |
+
self.post_init()
|
| 726 |
+
|
| 727 |
+
@can_return_tuple
|
| 728 |
+
@auto_docstring
|
| 729 |
+
def forward(
|
| 730 |
+
self,
|
| 731 |
+
input_ids: torch.Tensor | None = None,
|
| 732 |
+
attention_mask: torch.Tensor | None = None,
|
| 733 |
+
token_type_ids: torch.Tensor | None = None,
|
| 734 |
+
position_ids: torch.Tensor | None = None,
|
| 735 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 736 |
+
labels: torch.Tensor | None = None,
|
| 737 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 738 |
+
) -> tuple[torch.Tensor] | TokenClassifierOutput:
|
| 739 |
+
r"""
|
| 740 |
+
labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 741 |
+
Labels for computing the token classification loss. Indices should be in `[0, ..., config.num_labels - 1]`.
|
| 742 |
+
"""
|
| 743 |
+
outputs = self.ultrabert(
|
| 744 |
+
input_ids,
|
| 745 |
+
attention_mask=attention_mask,
|
| 746 |
+
position_ids=position_ids,
|
| 747 |
+
inputs_embeds=inputs_embeds,
|
| 748 |
+
**kwargs,
|
| 749 |
+
)
|
| 750 |
+
|
| 751 |
+
sequence_output = outputs[0]
|
| 752 |
+
|
| 753 |
+
sequence_output = self.dropout(sequence_output)
|
| 754 |
+
logits = self.classifier(sequence_output)
|
| 755 |
+
|
| 756 |
+
loss = None
|
| 757 |
+
if labels is not None:
|
| 758 |
+
loss_fct = CrossEntropyLoss()
|
| 759 |
+
loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1))
|
| 760 |
+
|
| 761 |
+
return TokenClassifierOutput(
|
| 762 |
+
loss=loss,
|
| 763 |
+
logits=logits,
|
| 764 |
+
hidden_states=outputs.hidden_states,
|
| 765 |
+
attentions=outputs.attentions,
|
| 766 |
+
)
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ddf6769ae0666a92dd38c88bb05b4864b778489f219d123973d26d43b0f78b3b
|
| 3 |
+
size 664035864
|
rl_agent_config.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"head_layers": 2,
|
| 3 |
+
"max_prefixes": 6,
|
| 4 |
+
"act_costs": {
|
| 5 |
+
"escalate": 0.5
|
| 6 |
+
},
|
| 7 |
+
"cost_wrong_act": 3.0,
|
| 8 |
+
"encoder": "dmis-lab/UltraBERT-150M",
|
| 9 |
+
"encoder_revision": "545ac9d9c7aece444f014ada5a1e9818132b4d35",
|
| 10 |
+
"max_len": 8192,
|
| 11 |
+
"head_max_len": 192,
|
| 12 |
+
"amp_dtype": "bf16",
|
| 13 |
+
"model_name": "caldec-ultra-150m",
|
| 14 |
+
"temperature": [
|
| 15 |
+
1.0,
|
| 16 |
+
1.0,
|
| 17 |
+
1.0
|
| 18 |
+
],
|
| 19 |
+
"temperature_by_options": {
|
| 20 |
+
"choice:3-5": 1.3067494630813599,
|
| 21 |
+
"noul:2": 1.1769542694091797,
|
| 22 |
+
"score:3-5": 1.1716774702072144,
|
| 23 |
+
"choice:2": 1.1175421476364136
|
| 24 |
+
},
|
| 25 |
+
"training": {
|
| 26 |
+
"fine_tuned_from": "dmis-lab/UltraBERT-150M@545ac9d9c7aece444f014ada5a1e9818132b4d35 with a freshly initialized decision head",
|
| 27 |
+
"base_revision": "545ac9d9c7aece444f014ada5a1e9818132b4d35",
|
| 28 |
+
"epochs_completed": 6,
|
| 29 |
+
"selected_epoch": 6,
|
| 30 |
+
"updates": 3353,
|
| 31 |
+
"lr_encoder": 1e-05,
|
| 32 |
+
"lr_head": 0.0001,
|
| 33 |
+
"schedule": "linear",
|
| 34 |
+
"decisions": 9001,
|
| 35 |
+
"seconds": 2066,
|
| 36 |
+
"legacy_drop_tail": false,
|
| 37 |
+
"objective": "soft cross-entropy",
|
| 38 |
+
"with_public": true,
|
| 39 |
+
"balance_sites": true,
|
| 40 |
+
"seed": 20260924,
|
| 41 |
+
"packed": true,
|
| 42 |
+
"max_len": 8192,
|
| 43 |
+
"max_batch_tokens": 16384,
|
| 44 |
+
"extra_train": [
|
| 45 |
+
"general mix (scripts/general_data.py: MNLI, BoolQ)",
|
| 46 |
+
"kgrozdanovski/assistant-decisions long/train.jsonl"
|
| 47 |
+
],
|
| 48 |
+
"extra_val": [
|
| 49 |
+
"general mix validation (scripts/general_data.py)",
|
| 50 |
+
"kgrozdanovski/assistant-decisions long/validation.jsonl"
|
| 51 |
+
]
|
| 52 |
+
},
|
| 53 |
+
"packed": true
|
| 54 |
+
}
|
tokenizer/tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer/tokenizer_config.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_prefix_space": false,
|
| 3 |
+
"backend": "tokenizers",
|
| 4 |
+
"bos_token": "<|endoftext|>",
|
| 5 |
+
"clean_up_tokenization_spaces": false,
|
| 6 |
+
"cls_token": "<|endoftext|>",
|
| 7 |
+
"eos_token": "<|endoftext|>",
|
| 8 |
+
"errors": "replace",
|
| 9 |
+
"extra_0": "<|endoftext|>",
|
| 10 |
+
"extra_1": "<|im_start|>",
|
| 11 |
+
"extra_10": "<issue_closed>",
|
| 12 |
+
"extra_11": "<jupyter_start>",
|
| 13 |
+
"extra_12": "<jupyter_text>",
|
| 14 |
+
"extra_13": "<jupyter_code>",
|
| 15 |
+
"extra_14": "<jupyter_output>",
|
| 16 |
+
"extra_15": "<|sep|>",
|
| 17 |
+
"extra_16": "<|mask|>",
|
| 18 |
+
"extra_2": "<|im_end|>",
|
| 19 |
+
"extra_3": "<repo_name>",
|
| 20 |
+
"extra_4": "<reponame>",
|
| 21 |
+
"extra_5": "<file_sep>",
|
| 22 |
+
"extra_6": "<filename>",
|
| 23 |
+
"extra_7": "<gh_stars>",
|
| 24 |
+
"extra_8": "<issue_start>",
|
| 25 |
+
"extra_9": "<issue_comment>",
|
| 26 |
+
"is_local": true,
|
| 27 |
+
"local_files_only": false,
|
| 28 |
+
"mask_token": "<|mask|>",
|
| 29 |
+
"model_max_length": 32768,
|
| 30 |
+
"model_specific_special_tokens": {
|
| 31 |
+
"extra_0": "<|endoftext|>",
|
| 32 |
+
"extra_1": "<|im_start|>",
|
| 33 |
+
"extra_10": "<issue_closed>",
|
| 34 |
+
"extra_11": "<jupyter_start>",
|
| 35 |
+
"extra_12": "<jupyter_text>",
|
| 36 |
+
"extra_13": "<jupyter_code>",
|
| 37 |
+
"extra_14": "<jupyter_output>",
|
| 38 |
+
"extra_15": "<|sep|>",
|
| 39 |
+
"extra_16": "<|mask|>",
|
| 40 |
+
"extra_2": "<|im_end|>",
|
| 41 |
+
"extra_3": "<repo_name>",
|
| 42 |
+
"extra_4": "<reponame>",
|
| 43 |
+
"extra_5": "<file_sep>",
|
| 44 |
+
"extra_6": "<filename>",
|
| 45 |
+
"extra_7": "<gh_stars>",
|
| 46 |
+
"extra_8": "<issue_start>",
|
| 47 |
+
"extra_9": "<issue_comment>"
|
| 48 |
+
},
|
| 49 |
+
"pad_token": "<|endoftext|>",
|
| 50 |
+
"sep_token": "<|sep|>",
|
| 51 |
+
"tokenizer_class": "GPT2Tokenizer",
|
| 52 |
+
"unk_token": "<|endoftext|>",
|
| 53 |
+
"vocab_size": 49152
|
| 54 |
+
}
|