Token Classification
Transformers
Safetensors
English
ultrabert
information-extraction
extractive-qa
ner
span-extraction
tasksource
custom_code
Instructions to use tasksource/UltraBERT-380M-clairic-extraction with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use tasksource/UltraBERT-380M-clairic-extraction with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("token-classification", model="tasksource/UltraBERT-380M-clairic-extraction", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForTokenClassification tokenizer = AutoTokenizer.from_pretrained("tasksource/UltraBERT-380M-clairic-extraction", trust_remote_code=True) model = AutoModelForTokenClassification.from_pretrained("tasksource/UltraBERT-380M-clairic-extraction", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
UltraBERT-380M-clairic-extraction
Browse files- README.md +108 -0
- config.json +104 -0
- configuration_ultrabert.py +67 -0
- model.safetensors +3 -0
- modeling_ultrabert.py +766 -0
- tokenizer.json +0 -0
- tokenizer_config.json +36 -0
README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
library_name: transformers
|
| 3 |
+
base_model:
|
| 4 |
+
- dmis-lab/UltraBERT-380M
|
| 5 |
+
license: apache-2.0
|
| 6 |
+
language:
|
| 7 |
+
- en
|
| 8 |
+
pipeline_tag: token-classification
|
| 9 |
+
datasets:
|
| 10 |
+
- tasksource/tasksource-jev-typed-decisions
|
| 11 |
+
tags:
|
| 12 |
+
- information-extraction
|
| 13 |
+
- extractive-qa
|
| 14 |
+
- ner
|
| 15 |
+
- span-extraction
|
| 16 |
+
- tasksource
|
| 17 |
+
---
|
| 18 |
+
|
| 19 |
+
# UltraBERT-380M-clairic-extraction
|
| 20 |
+
|
| 21 |
+
A 380M-parameter extractor for Clairic-style requests: give it a text and a set of fields, each described by a short instruction, and it returns the matching spans for each field (one answer, a list, or nothing when the text has no answer). Fields can be questions ("What is the total due?") or entity types ("Every company mentioned in the text"), so one model covers extractive question answering and named-entity recognition.
|
| 22 |
+
|
| 23 |
+
[UltraBERT-380M](https://huggingface.co/dmis-lab/UltraBERT-380M) trained on the `extraction` config of [tasksource-jev-typed-decisions](https://huggingface.co/datasets/tasksource/tasksource-jev-typed-decisions) (release v2026.10.24.1, 1M instruction/text pairs, 60k steps): extractive QA and span-tagging datasets from [tasksource](https://github.com/sileod/tasksource), rewritten as (instruction, text, spans) pairs. The model tags the answer tokens of the text (B/I/O) conditioned on the instruction. Inputs up to 2048 tokens.
|
| 24 |
+
|
| 25 |
+
It is the larger sibling of [UltraBERT-150M-clairic-extraction](https://huggingface.co/tasksource/UltraBERT-150M-clairic-extraction), with the same interface: more accurate, especially on list fields, and better at leaving a field empty when the text has no answer, for about 2.5x the compute.
|
| 26 |
+
|
| 27 |
+
Not affiliated with Cloudflare; "Clairic-style" refers to the request format.
|
| 28 |
+
|
| 29 |
+
## Usage
|
| 30 |
+
|
| 31 |
+
```python
|
| 32 |
+
import torch
|
| 33 |
+
from transformers import AutoModelForTokenClassification, AutoTokenizer
|
| 34 |
+
|
| 35 |
+
name = "tasksource/UltraBERT-380M-clairic-extraction"
|
| 36 |
+
tok = AutoTokenizer.from_pretrained(name)
|
| 37 |
+
model = AutoModelForTokenClassification.from_pretrained(name, trust_remote_code=True).eval()
|
| 38 |
+
|
| 39 |
+
def extract(text, fields):
|
| 40 |
+
"""fields: {name: instruction}. Returns {name: [extracted spans]}, [] when the text has no answer."""
|
| 41 |
+
enc = tok(list(fields.values()), [text] * len(fields), truncation="only_second", max_length=2048,
|
| 42 |
+
padding=True, return_offsets_mapping=True, return_tensors="pt")
|
| 43 |
+
offsets = enc.pop("offset_mapping")
|
| 44 |
+
with torch.no_grad():
|
| 45 |
+
tags = model(**enc).logits.argmax(-1).tolist() # 0 = O, 1 = B, 2 = I
|
| 46 |
+
out = {}
|
| 47 |
+
for f, field in enumerate(fields):
|
| 48 |
+
spans, start, seq = [], None, enc.sequence_ids(f) + [None]
|
| 49 |
+
for i, tag in enumerate(tags[f] + [0]):
|
| 50 |
+
if start is not None and (seq[i] != 1 or tag != 2):
|
| 51 |
+
spans.append(text[offsets[f][start][0]:offsets[f][i - 1][1]].strip().rstrip(",;:"))
|
| 52 |
+
start = None
|
| 53 |
+
if seq[i] == 1 and tag in (1, 2) and start is None:
|
| 54 |
+
start = i
|
| 55 |
+
out[field] = spans
|
| 56 |
+
return out
|
| 57 |
+
|
| 58 |
+
text = "Invoice INV-2291 from Acme Corp to Globex, issued 3 March 2025. Total due: $1,240.50. Contact: billing@acme.com."
|
| 59 |
+
print(extract(text, {
|
| 60 |
+
"invoice_number": "The invoice number.",
|
| 61 |
+
"companies": "Every company mentioned in the text, as written.",
|
| 62 |
+
"total": "The total amount due.",
|
| 63 |
+
"phone": "The contact phone number.",
|
| 64 |
+
}))
|
| 65 |
+
# {'invoice_number': ['INV-2291'], 'companies': ['Acme Corp', 'Globex'], 'total': ['$1,240.50'], 'phone': []}
|
| 66 |
+
```
|
| 67 |
+
|
| 68 |
+
`trust_remote_code=True` is needed for the UltraBERT architecture.
|
| 69 |
+
|
| 70 |
+
## Evaluation
|
| 71 |
+
|
| 72 |
+
Test split of the extraction config (revision v2026.10.20.7), 100 rows per source, procedurally generated sources excluded. *text* fields (one answer or none) are scored by SQuAD F1, the empty answer counting as an answer. *list* fields (every span of a kind) are scored by micro F1 over normalized values. Scores are means over sources.
|
| 73 |
+
|
| 74 |
+
| Model | Params | QA (F1) | NER / span lists (F1) |
|
| 75 |
+
|---|---|---|---|
|
| 76 |
+
| **UltraBERT-380M-clairic-extraction** | 380M | **0.756** | **0.750** |
|
| 77 |
+
| [UltraBERT-150M-clairic-extraction](https://huggingface.co/tasksource/UltraBERT-150M-clairic-extraction) | 150M | 0.720 | 0.702 |
|
| 78 |
+
| [gliner-multitask-large-v0.5](https://huggingface.co/knowledgator/gliner-multitask-large-v0.5) | 440M | 0.474 | 0.408 |
|
| 79 |
+
| [deberta-v3-base-squad2](https://huggingface.co/deepset/deberta-v3-base-squad2) | 184M | 0.498 | 0.060 |
|
| 80 |
+
|
| 81 |
+
The test sources are the training sources (their test splits), while the baselines see most of them zero-shot, so this measures performance on these tasks rather than on unseen ones.
|
| 82 |
+
|
| 83 |
+
Out of domain (MRQA test sets the model never trained on, plus FinEntity), F1:
|
| 84 |
+
|
| 85 |
+
| Model | BioASQ | RACE | RelationExtraction | TextbookQA | FinEntity | Mean |
|
| 86 |
+
|---|---|---|---|---|---|---|
|
| 87 |
+
| **UltraBERT-380M-clairic-extraction** | 0.626 | 0.412 | 0.870 | 0.482 | 0.717 | 0.622 |
|
| 88 |
+
| [gliner-multitask-large-v0.5](https://huggingface.co/knowledgator/gliner-multitask-large-v0.5) | **0.643** | **0.458** | **0.899** | **0.545** | **0.913** | **0.692** |
|
| 89 |
+
|
| 90 |
+
GLiNER-multitask stays ahead out of domain.
|
| 91 |
+
|
| 92 |
+
## Training data
|
| 93 |
+
|
| 94 |
+
The extraction config gathers extractive QA (SQuAD 2.0, Natural Questions, HotpotQA, NewsQA, DuoRC, QuAC, CUAD, Qasper, TimeQA, WebSRC, SWDE, and others) and span tagging (CoNLL-2003, OntoNotes, Few-NERD, WNUT, CrossNER, biomedical, legal and financial NER, skills, aspects, keyphrases, and others), plus procedurally generated documents. A few sources (e.g. GUM, PreCo) are licensed for non-commercial use only; check the dataset card for per-source licenses.
|
| 95 |
+
|
| 96 |
+
## Citation
|
| 97 |
+
|
| 98 |
+
```bibtex
|
| 99 |
+
@inproceedings{sileo-2024-tasksource,
|
| 100 |
+
title = "tasksource: A Large Collection of {NLP} tasks with a Structured Dataset Preprocessing Framework",
|
| 101 |
+
author = "Sileo, Damien",
|
| 102 |
+
booktitle = "Proceedings of the 2024 Joint International Conference on Computational Linguistics, Language Resources and Evaluation (LREC-COLING 2024)",
|
| 103 |
+
year = "2024",
|
| 104 |
+
address = "Torino, Italia",
|
| 105 |
+
pages = "15655--15684",
|
| 106 |
+
url = "https://aclanthology.org/2024.lrec-main.1361",
|
| 107 |
+
}
|
| 108 |
+
```
|
config.json
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"UltrabertForTokenClassification"
|
| 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 |
+
"classifiers_size": [
|
| 44 |
+
3
|
| 45 |
+
],
|
| 46 |
+
"dtype": "float32",
|
| 47 |
+
"eos_token_id": 0,
|
| 48 |
+
"head_dim": 128,
|
| 49 |
+
"hidden_act": "silu",
|
| 50 |
+
"hidden_size": 1024,
|
| 51 |
+
"id2label": {
|
| 52 |
+
"0": "O",
|
| 53 |
+
"1": "B-answer",
|
| 54 |
+
"2": "I-answer"
|
| 55 |
+
},
|
| 56 |
+
"initializer_range": 0.02,
|
| 57 |
+
"intermediate_size": 3072,
|
| 58 |
+
"label2id": {
|
| 59 |
+
"B-answer": 1,
|
| 60 |
+
"I-answer": 2,
|
| 61 |
+
"O": 0
|
| 62 |
+
},
|
| 63 |
+
"max_position_embeddings": 2048,
|
| 64 |
+
"mlp_bias": false,
|
| 65 |
+
"model_type": "ultrabert",
|
| 66 |
+
"num_attention_heads": 8,
|
| 67 |
+
"num_hidden_layers": 24,
|
| 68 |
+
"num_key_value_heads": 8,
|
| 69 |
+
"pad_token_id": 0,
|
| 70 |
+
"prediction_head_size": 1024,
|
| 71 |
+
"rms_norm_eps": 1e-06,
|
| 72 |
+
"rope_theta": [
|
| 73 |
+
10000.0,
|
| 74 |
+
10000.0,
|
| 75 |
+
2560000.0,
|
| 76 |
+
10000.0,
|
| 77 |
+
10000.0,
|
| 78 |
+
2560000.0,
|
| 79 |
+
10000.0,
|
| 80 |
+
10000.0,
|
| 81 |
+
2560000.0,
|
| 82 |
+
10000.0,
|
| 83 |
+
10000.0,
|
| 84 |
+
2560000.0,
|
| 85 |
+
10000.0,
|
| 86 |
+
10000.0,
|
| 87 |
+
2560000.0,
|
| 88 |
+
10000.0,
|
| 89 |
+
10000.0,
|
| 90 |
+
2560000.0,
|
| 91 |
+
10000.0,
|
| 92 |
+
10000.0,
|
| 93 |
+
2560000.0,
|
| 94 |
+
10000.0,
|
| 95 |
+
10000.0,
|
| 96 |
+
2560000.0
|
| 97 |
+
],
|
| 98 |
+
"tasks": [
|
| 99 |
+
"jev-extraction"
|
| 100 |
+
],
|
| 101 |
+
"tie_word_embeddings": false,
|
| 102 |
+
"transformers_version": "5.17.0",
|
| 103 |
+
"vocab_size": 49152
|
| 104 |
+
}
|
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
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:188edece3e65295207c3137de5af06c4011afbe1f81c7091ca049ce0048b3ce3
|
| 3 |
+
size 1510188284
|
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 |
+
)
|
tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_prefix_space": false,
|
| 3 |
+
"backend": "tokenizers",
|
| 4 |
+
"bos_token": "<|endoftext|>",
|
| 5 |
+
"clean_up_tokenization_spaces": false,
|
| 6 |
+
"eos_token": "<|endoftext|>",
|
| 7 |
+
"errors": "replace",
|
| 8 |
+
"extra_special_tokens": [
|
| 9 |
+
"<|endoftext|>",
|
| 10 |
+
"<|im_start|>",
|
| 11 |
+
"<|im_end|>",
|
| 12 |
+
"<repo_name>",
|
| 13 |
+
"<reponame>",
|
| 14 |
+
"<file_sep>",
|
| 15 |
+
"<filename>",
|
| 16 |
+
"<gh_stars>",
|
| 17 |
+
"<issue_start>",
|
| 18 |
+
"<issue_comment>",
|
| 19 |
+
"<issue_closed>",
|
| 20 |
+
"<jupyter_start>",
|
| 21 |
+
"<jupyter_text>",
|
| 22 |
+
"<jupyter_code>",
|
| 23 |
+
"<jupyter_output>",
|
| 24 |
+
"<|sep|>",
|
| 25 |
+
"<|mask|>"
|
| 26 |
+
],
|
| 27 |
+
"is_local": false,
|
| 28 |
+
"local_files_only": false,
|
| 29 |
+
"mask_token": "<|mask|>",
|
| 30 |
+
"model_max_length": 32768,
|
| 31 |
+
"pad_token": "<|endoftext|>",
|
| 32 |
+
"sep_token": "<|sep|>",
|
| 33 |
+
"tokenizer_class": "GPT2Tokenizer",
|
| 34 |
+
"unk_token": "<|endoftext|>",
|
| 35 |
+
"vocab_size": 49152
|
| 36 |
+
}
|