Taykhoom commited on
Commit
1a972eb
·
0 Parent(s):

Initial gLM2 HF port

Browse files
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: transformers
3
+ tags:
4
+ - biology
5
+ - genomics
6
+ - protein
7
+ - dna
8
+ - language-model
9
+ license: apache-2.0
10
+ datasets:
11
+ - tattabio/OMG
12
+ ---
13
+
14
+ # gLM-150M
15
+
16
+ Minimal HuggingFace port of the **150M** parameter variant of
17
+ [gLM2](https://huggingface.co/tattabio/gLM2_150M) -- a mixed-modality genomic
18
+ language model that encodes a genomic scaffold using both amino-acid and DNA
19
+ tokens. Pretrained with masked language modeling on the
20
+ [OMG dataset](https://huggingface.co/datasets/tattabio/OMG).
21
+
22
+ ## Architecture
23
+
24
+ | Parameter | Value |
25
+ |---|---|
26
+ | Layers | 30 |
27
+ | Attention heads | 10 |
28
+ | Embedding dimension | 640 |
29
+ | FFN hidden dimension | 1792 (SwiGLU, multiple_of=256) |
30
+ | Vocabulary size | 37 |
31
+ | Positional encoding | RoPE (base=10000, non-interleaved) |
32
+ | Normalization | RMSNorm |
33
+ | Architecture | Pre-LN Transformer with SwiGLU FFN |
34
+ | Max sequence length | 4096 |
35
+
36
+ **Vocabulary:** `<cls>`, `<pad>`, `<eos>`, `<unk>`, the 26 IUPAC amino-acid
37
+ letters (`L A G V S E R T I D P K Q N F Y M H W C X B U Z O`, uppercase),
38
+ the 4 DNA nucleotides (`a t c g`, lowercase), strand markers `<+>` / `<->`,
39
+ and `<mask>` / `<sep>`. Amino-acid and nucleotide tokens share the alphabet
40
+ by case (uppercase = amino acid, lowercase = nucleotide).
41
+
42
+ ## Pretraining
43
+
44
+ - **Objective:** Masked language modeling (30% mask rate)
45
+ - **Data:** [OMG dataset](https://huggingface.co/datasets/tattabio/OMG) (open
46
+ metagenomic corpus, semantically-deduplicated)
47
+ - **Pretraining tokens:** 315B (bfloat16, context length 4096)
48
+ - **Source checkpoint:** `tattabio/gLM2_150M`
49
+
50
+ ## Parity Verification
51
+
52
+ All 31 representation levels (embedding + 30 transformer blocks) verified to
53
+ be bit-exact (max abs diff = 0.00) against the original `tattabio/gLM2_150M`
54
+ weights with `attn_implementation="sdpa"`. The added eager and
55
+ `flash_attention_2` backends agree within fp32 kernel drift (atol = 1e-3) and
56
+ bf16 cosine similarity >= 0.999 respectively. Verified on GPU with PyTorch
57
+ 2.7 / CUDA 12.
58
+
59
+ ## Related Models
60
+
61
+ See the full [gLM2 collection](https://huggingface.co/collections/Taykhoom/glm2-6a2e19be671ba44c163c617f).
62
+
63
+ | Model | Parameters | Notes |
64
+ |---|---|---|
65
+ | **[gLM-150M](https://huggingface.co/Taykhoom/gLM-150M)** | 150M | This model |
66
+ | [gLM-650M](https://huggingface.co/Taykhoom/gLM-650M) | 650M | Larger variant |
67
+
68
+ ## Usage
69
+
70
+ ### Embedding generation
71
+
72
+ ```python
73
+ import torch
74
+ from transformers import AutoTokenizer, AutoModel
75
+
76
+ tokenizer = AutoTokenizer.from_pretrained("Taykhoom/gLM-150M", trust_remote_code=True)
77
+ model = AutoModel.from_pretrained("Taykhoom/gLM-150M", trust_remote_code=True)
78
+ model.eval()
79
+
80
+ # Canonical gLM2 input: amino acids (uppercase) + DNA (lowercase) + strand markers.
81
+ sequence = (
82
+ "<+>MALTKVEKRNRIKRRVRGKISGTQASPRLSVYKSNK"
83
+ "<+>aatttaaggaa"
84
+ "<->MLGIDNIERVKPGGLELVDRLVAVNRVTKVTKGGRAFGFSAIVVVGNED"
85
+ )
86
+ enc = tokenizer([sequence], return_tensors="pt")
87
+
88
+ with torch.no_grad():
89
+ out = model(**enc)
90
+
91
+ cls_emb = out.last_hidden_state[:, 0, :] # (batch, 640) -- CLS token
92
+ token_emb = out.last_hidden_state # (batch, seq_len, 640)
93
+
94
+ # Intermediate layers
95
+ out_all = model(**enc, output_hidden_states=True)
96
+ layer15_emb = out_all.hidden_states[15] # after block 15
97
+ ```
98
+
99
+ The tokenizer also accepts plain DNA strings (no strand marker) and
100
+ auto-prepares them by lowercasing, replacing `U`/`u` with `t`, and prepending
101
+ `<+>`. The three calls below produce identical token sequences:
102
+
103
+ ```python
104
+ tokenizer(["ATCGATCG", "atcgatcg", "AUCGAUCG"], return_tensors="pt")
105
+ ```
106
+
107
+ ### MLM logits
108
+
109
+ ```python
110
+ from transformers import AutoTokenizer, AutoModelForMaskedLM
111
+
112
+ tokenizer = AutoTokenizer.from_pretrained("Taykhoom/gLM-150M", trust_remote_code=True)
113
+ model = AutoModelForMaskedLM.from_pretrained("Taykhoom/gLM-150M", trust_remote_code=True)
114
+ model.eval()
115
+
116
+ enc = tokenizer(["<+>MA<mask>K"], return_tensors="pt")
117
+ with torch.no_grad():
118
+ logits = model(**enc).logits # (1, seq_len, 37)
119
+ ```
120
+
121
+ ### Faster attention backends
122
+
123
+ ```python
124
+ # SDPA (PyTorch 2.0+, default upstream backend) -- recommended for fp32
125
+ model = AutoModel.from_pretrained("Taykhoom/gLM-150M", trust_remote_code=True,
126
+ attn_implementation="sdpa")
127
+
128
+ # Flash Attention 2 (requires flash-attn package) -- fastest on long sequences
129
+ model = AutoModel.from_pretrained("Taykhoom/gLM-150M", trust_remote_code=True,
130
+ attn_implementation="flash_attention_2",
131
+ dtype=torch.bfloat16)
132
+ ```
133
+
134
+ ### Fine-tuning
135
+
136
+ Standard HF conventions. For sequence-level tasks, pool over non-padding
137
+ positions or use the CLS token embedding as input to a prediction head.
138
+
139
+ ## Implementation Notes
140
+
141
+ The original gLM2 implementation uses PyTorch SDPA as the only attention
142
+ backend. This HF port adds eager and `flash_attention_2` as separate
143
+ implementations selectable via `attn_implementation`, with eager falling back
144
+ automatically when `output_attentions=True` is requested.
145
+
146
+ The eager kernel computes the QK matmul and softmax in fp32 even when the
147
+ model is loaded in bf16, matching the numerical behaviour of SDPA and
148
+ `flash_attention_2` in mixed precision.
149
+
150
+ ## Citation
151
+
152
+ ```bibtex
153
+ @article{cornman2024_glm2,
154
+ title = {The {OMG} dataset: An Open MetaGenomic corpus for mixed-modality genomic language modeling},
155
+ author = {Cornman, Andre and West-Roberts, Jacob and Camargo, Antonio Pedro and Roux, Simon and Beracochea, Martin and Mirdita, Milot and Ovchinnikov, Sergey and Hwang, Yunha},
156
+ journal = {bioRxiv},
157
+ year = {2024},
158
+ doi = {10.1101/2024.08.14.607850}
159
+ }
160
+ ```
161
+
162
+ ## Credits
163
+
164
+ Original model and code by Cornman et al. (Tatta Bio). Source:
165
+ [GitHub](https://github.com/TattaBio/gLM2),
166
+ [`tattabio/gLM2_150M` on the Hub](https://huggingface.co/tattabio/gLM2_150M).
167
+ The HF conversion code was authored primarily by [Claude Code](https://claude.ai/code)
168
+ and reviewed manually by Taykhoom Dalal.
169
+
170
+ ## License
171
+
172
+ Apache 2.0, following the original repository.
config.json ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "gLM2ForMaskedLM"
4
+ ],
5
+ "auto_map": {
6
+ "AutoConfig": "configuration_glm2.gLM2Config",
7
+ "AutoModel": "modeling_glm2.gLM2Model",
8
+ "AutoModelForMaskedLM": "modeling_glm2.gLM2ForMaskedLM"
9
+ },
10
+ "cls_token_id": 0,
11
+ "depth": 30,
12
+ "dim": 640,
13
+ "dtype": "float32",
14
+ "eos_token_id": 2,
15
+ "ffn_dim_multiplier": null,
16
+ "heads": 10,
17
+ "initializer_range": 0.02,
18
+ "mask_token_id": 35,
19
+ "max_position_embeddings": 4096,
20
+ "model_type": "gLM2",
21
+ "norm_eps": 1e-05,
22
+ "pad_token_id": 1,
23
+ "swiglu_multiple_of": 256,
24
+ "tie_word_embeddings": false,
25
+ "transformers_version": "4.57.6",
26
+ "vocab_size": 37
27
+ }
configuration_glm2.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """gLM2 model configuration."""
2
+
3
+ from typing import Optional
4
+
5
+ from transformers import PretrainedConfig
6
+ from transformers.utils import logging
7
+
8
+ logger = logging.get_logger(__name__)
9
+
10
+
11
+ class gLM2Config(PretrainedConfig):
12
+ """Configuration class for gLM2.
13
+
14
+ Mirrors the hyperparameters in the official `tattabio/gLM2_*` checkpoints
15
+ plus the standard HuggingFace `PretrainedConfig` knobs.
16
+ """
17
+
18
+ model_type = "gLM2"
19
+
20
+ def __init__(
21
+ self,
22
+ dim: int = 640,
23
+ depth: int = 30,
24
+ heads: int = 10,
25
+ vocab_size: int = 37,
26
+ swiglu_multiple_of: int = 256,
27
+ ffn_dim_multiplier: Optional[float] = None,
28
+ norm_eps: float = 1e-5,
29
+ pad_token_id: int = 1,
30
+ cls_token_id: int = 0,
31
+ eos_token_id: int = 2,
32
+ mask_token_id: int = 35,
33
+ max_position_embeddings: int = 4096,
34
+ initializer_range: float = 0.02,
35
+ tie_word_embeddings: bool = False,
36
+ **kwargs,
37
+ ):
38
+ super().__init__(
39
+ pad_token_id=pad_token_id,
40
+ tie_word_embeddings=tie_word_embeddings,
41
+ **kwargs,
42
+ )
43
+ self.dim = dim
44
+ self.depth = depth
45
+ self.heads = heads
46
+ self.vocab_size = vocab_size
47
+ self.swiglu_multiple_of = swiglu_multiple_of
48
+ self.ffn_dim_multiplier = ffn_dim_multiplier
49
+ self.norm_eps = norm_eps
50
+ self.cls_token_id = cls_token_id
51
+ self.eos_token_id = eos_token_id
52
+ self.mask_token_id = mask_token_id
53
+ self.max_position_embeddings = max_position_embeddings
54
+ self.initializer_range = initializer_range
55
+
56
+ self.auto_map = {
57
+ "AutoConfig": "configuration_glm2.gLM2Config",
58
+ "AutoModel": "modeling_glm2.gLM2Model",
59
+ "AutoModelForMaskedLM": "modeling_glm2.gLM2ForMaskedLM",
60
+ }
glm_tokenizer.py ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Tokenizer for gLM2.
2
+
3
+ Wraps a BPE-style fast tokenizer with the upstream `tattabio/gLM2_*` vocabulary
4
+ (amino acids, nucleotides, strand markers). On top of the upstream behaviour
5
+ this version adds *automatic DNA preparation* so callers can pass plain DNA
6
+ sequences (e.g. mRNABench-style input) without manually lowercasing or adding
7
+ strand markers.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import re
13
+ from typing import List, Optional, Sequence, Union
14
+
15
+ from tokenizers import Tokenizer
16
+ from tokenizers.models import BPE
17
+ from transformers import PreTrainedTokenizerFast
18
+
19
+
20
+ _NUC_CHARS = set("acgtuACGTU")
21
+ _DNA_PREFIX_RE = re.compile(r"^\s*(<\+>|<->)")
22
+
23
+
24
+ def _is_pure_dna(seq: str) -> bool:
25
+ """True if `seq` only contains DNA/RNA characters (ATCGU, any case)."""
26
+ return len(seq) > 0 and all(c in _NUC_CHARS for c in seq)
27
+
28
+
29
+ def prepare_dna_sequence(seq: str, strand: str = "+") -> str:
30
+ """Normalize a plain DNA/RNA sequence for gLM2.
31
+
32
+ - Lower-cases nucleotides so they are tokenized as DNA (gLM2 uses
33
+ lower-case `a/t/c/g` for nucleotides; upper-case letters are amino
34
+ acids).
35
+ - Replaces `U`/`u` with `t` (gLM2's vocab has no uracil token).
36
+ - Prepends the strand marker (`<+>` or `<->`) if not already present.
37
+ """
38
+ if strand not in ("+", "-"):
39
+ raise ValueError(f"strand must be '+' or '-', got {strand!r}")
40
+ if _DNA_PREFIX_RE.match(seq):
41
+ return seq
42
+ cleaned = seq.lower().replace("u", "t")
43
+ return f"<{strand}>{cleaned}"
44
+
45
+
46
+ class gLM2Tokenizer(PreTrainedTokenizerFast):
47
+ """gLM2 fast tokenizer with optional automatic DNA preparation."""
48
+
49
+ VOCAB = [
50
+ "<cls>", "<pad>", "<eos>", "<unk>",
51
+ "L", "A", "G", "V", "S", "E", "R", "T", "I", "D", "P", "K",
52
+ "Q", "N", "F", "Y", "M", "H", "W", "C", "X", "B", "U", "Z",
53
+ "O", "a", "t", "c", "g", "<+>", "<->", "<mask>", "<sep>",
54
+ ]
55
+
56
+ def __init__(
57
+ self,
58
+ unk_token: str = "<unk>",
59
+ cls_token: str = "<cls>",
60
+ pad_token: str = "<pad>",
61
+ mask_token: str = "<mask>",
62
+ eos_token: str = "<eos>",
63
+ sep_token: str = "<sep>",
64
+ pos_token: str = "<+>",
65
+ neg_token: str = "<->",
66
+ auto_prepare_dna: bool = True,
67
+ model_max_length: int = 4096,
68
+ **kwargs,
69
+ ):
70
+ all_tokens = self.VOCAB
71
+ token_to_id = {tok: ind for ind, tok in enumerate(all_tokens)}
72
+
73
+ bpe = BPE(token_to_id, merges=[], unk_token=str(unk_token))
74
+ tokenizer = Tokenizer(bpe)
75
+ special_tokens = [
76
+ cls_token, pad_token, mask_token, eos_token, sep_token, pos_token, neg_token,
77
+ ]
78
+ tokenizer.add_special_tokens(special_tokens)
79
+
80
+ super().__init__(
81
+ tokenizer_object=tokenizer,
82
+ unk_token=unk_token,
83
+ cls_token=cls_token,
84
+ pad_token=pad_token,
85
+ mask_token=mask_token,
86
+ eos_token=eos_token,
87
+ sep_token=sep_token,
88
+ model_max_length=model_max_length,
89
+ **kwargs,
90
+ )
91
+ self.auto_prepare_dna = auto_prepare_dna
92
+
93
+ def _maybe_prepare(
94
+ self, text: Union[str, Sequence[str]]
95
+ ) -> Union[str, List[str]]:
96
+ if not self.auto_prepare_dna:
97
+ return text # type: ignore[return-value]
98
+ if isinstance(text, str):
99
+ return prepare_dna_sequence(text) if _is_pure_dna(text) else text
100
+ out: List[str] = []
101
+ for s in text:
102
+ if isinstance(s, str) and _is_pure_dna(s):
103
+ out.append(prepare_dna_sequence(s))
104
+ else:
105
+ out.append(s)
106
+ return out
107
+
108
+ def __call__(
109
+ self,
110
+ text: Union[str, Sequence[str], None] = None,
111
+ text_pair=None,
112
+ text_target=None,
113
+ text_pair_target=None,
114
+ *args,
115
+ **kwargs,
116
+ ):
117
+ if text is not None:
118
+ text = self._maybe_prepare(text)
119
+ return super().__call__(
120
+ text,
121
+ text_pair=text_pair,
122
+ text_target=text_target,
123
+ text_pair_target=text_pair_target,
124
+ *args,
125
+ **kwargs,
126
+ )
127
+
128
+ def encode(
129
+ self, text: Union[str, Sequence[str]], *args, **kwargs
130
+ ) -> List[int]:
131
+ text = self._maybe_prepare(text)
132
+ return super().encode(text, *args, **kwargs)
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:047facd39472afe082c985058fa042f43a7b10d4ffb2ab51b9a3e6c63e9f3834
3
+ size 609855088
modeling_glm2.py ADDED
@@ -0,0 +1,535 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """PyTorch gLM2 model.
2
+
3
+ Minimal HuggingFace port of tattabio/gLM2 with three attention implementations
4
+ (eager, sdpa, flash_attention_2) and standard HF outputs.
5
+
6
+ Architecture is unchanged from the upstream `tattabio/gLM2_*` checkpoints
7
+ (RMSNorm, rotary position embeddings, fused QKV, SwiGLU MLP). Weight names
8
+ match upstream so the same `model.safetensors` loads cleanly.
9
+ """
10
+
11
+ import math
12
+ from typing import Optional, Tuple, Union
13
+
14
+ import torch
15
+ import torch.nn.functional as F
16
+ from torch import nn
17
+ from torch.nn import CrossEntropyLoss
18
+
19
+ from transformers.modeling_outputs import BaseModelOutput, MaskedLMOutput
20
+ from transformers.modeling_utils import PreTrainedModel
21
+ from transformers.utils import logging
22
+
23
+ from .configuration_glm2 import gLM2Config
24
+
25
+ logger = logging.get_logger(__name__)
26
+
27
+
28
+ def rotate_half(x: torch.Tensor) -> torch.Tensor:
29
+ x1, x2 = x.chunk(2, dim=-1)
30
+ return torch.cat((-x2, x1), dim=-1)
31
+
32
+
33
+ def apply_rotary_emb_torch(
34
+ x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor
35
+ ) -> torch.Tensor:
36
+ """Apply rotary embeddings to `x`.
37
+
38
+ Args:
39
+ x: (batch, seqlen, nheads, headdim)
40
+ cos, sin: (seqlen, rotary_dim / 2) - rotary_dim must equal headdim.
41
+ """
42
+ seqlen = x.shape[1]
43
+ cos = cos[:seqlen]
44
+ sin = sin[:seqlen]
45
+ cos = cos.to(x.dtype)
46
+ sin = sin.to(x.dtype)
47
+ cos = cos.repeat_interleave(2, dim=-1) if False else torch.cat([cos, cos], dim=-1)
48
+ sin = torch.cat([sin, sin], dim=-1)
49
+ cos = cos.unsqueeze(-2)
50
+ sin = sin.unsqueeze(-2)
51
+ return x * cos + rotate_half(x) * sin
52
+
53
+
54
+ class RotaryEmbedding(nn.Module):
55
+ """Rotary position embeddings.
56
+
57
+ Identical numerics to the upstream `tattabio/gLM2_*` `RotaryEmbedding`
58
+ (non-interleaved, base 10000, no scaling), simplified to the path actually
59
+ used by the released checkpoints.
60
+ """
61
+
62
+ def __init__(self, dim: int, base: float = 10000.0):
63
+ super().__init__()
64
+ self.dim = dim
65
+ self.base = float(base)
66
+ inv_freq = 1.0 / (
67
+ self.base
68
+ ** (torch.arange(0, dim, 2, dtype=torch.float32) / dim)
69
+ )
70
+ self.register_buffer("inv_freq", inv_freq, persistent=False)
71
+
72
+ self._seq_len_cached = 0
73
+ self._cos_cached: Optional[torch.Tensor] = None
74
+ self._sin_cached: Optional[torch.Tensor] = None
75
+
76
+ def _update_cache(self, seqlen: int, device: torch.device, dtype: torch.dtype) -> None:
77
+ if (
78
+ seqlen > self._seq_len_cached
79
+ or self._cos_cached is None
80
+ or self._cos_cached.device != device
81
+ or self._cos_cached.dtype != dtype
82
+ ):
83
+ self._seq_len_cached = seqlen
84
+ inv_freq = self.inv_freq
85
+ if inv_freq.dtype != torch.float32:
86
+ inv_freq = 1.0 / (
87
+ self.base
88
+ ** (
89
+ torch.arange(0, self.dim, 2, device=device, dtype=torch.float32)
90
+ / self.dim
91
+ )
92
+ )
93
+ t = torch.arange(seqlen, device=device, dtype=torch.float32)
94
+ freqs = torch.outer(t, inv_freq.to(device=device, dtype=torch.float32))
95
+ self._cos_cached = torch.cos(freqs).to(dtype)
96
+ self._sin_cached = torch.sin(freqs).to(dtype)
97
+
98
+ def forward(self, qkv: torch.Tensor) -> torch.Tensor:
99
+ """Apply rotary embeddings to q and k. v is left untouched.
100
+
101
+ Args:
102
+ qkv: (batch, seqlen, 3, nheads, headdim)
103
+ """
104
+ seqlen = qkv.shape[1]
105
+ self._update_cache(seqlen, device=qkv.device, dtype=qkv.dtype)
106
+ cos = self._cos_cached
107
+ sin = self._sin_cached
108
+ q_rot = apply_rotary_emb_torch(qkv[:, :, 0], cos, sin)
109
+ k_rot = apply_rotary_emb_torch(qkv[:, :, 1], cos, sin)
110
+ return torch.stack((q_rot, k_rot, qkv[:, :, 2]), dim=2)
111
+
112
+
113
+ def rmsnorm_func(
114
+ hidden_states: torch.Tensor, weight: torch.Tensor, variance_epsilon: torch.Tensor
115
+ ) -> torch.Tensor:
116
+ input_dtype = hidden_states.dtype
117
+ hidden_states = hidden_states.to(torch.float32)
118
+ variance = hidden_states.pow(2).mean(-1, keepdim=True)
119
+ hidden_states = hidden_states * torch.rsqrt(variance + variance_epsilon)
120
+ return (weight * hidden_states).to(input_dtype)
121
+
122
+
123
+ class RMSNorm(nn.Module):
124
+ """Root-mean-square layer norm."""
125
+
126
+ def __init__(self, dim: int, eps: float = 1e-6):
127
+ super().__init__()
128
+ self.weight = nn.Parameter(torch.ones(dim))
129
+ self.register_buffer(
130
+ "variance_epsilon", torch.tensor(eps), persistent=False
131
+ )
132
+
133
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
134
+ return rmsnorm_func(hidden_states, self.weight, self.variance_epsilon)
135
+
136
+
137
+ class gLM2Attention(nn.Module):
138
+ """Eager multi-head attention with rotary embeddings."""
139
+
140
+ def __init__(self, config: gLM2Config):
141
+ super().__init__()
142
+ self.n_heads = config.heads
143
+ self.head_dim = config.dim // config.heads
144
+ self.dim = config.dim
145
+
146
+ self.wqkv = nn.Linear(config.dim, self.n_heads * self.head_dim * 3, bias=False)
147
+ self.wo = nn.Linear(self.n_heads * self.head_dim, config.dim, bias=False)
148
+ self.rotary_emb = RotaryEmbedding(self.head_dim)
149
+
150
+ def _qkv(self, x: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
151
+ bsz, seqlen, _ = x.shape
152
+ qkv = self.wqkv(x).view(bsz, seqlen, 3, self.n_heads, self.head_dim)
153
+ qkv = self.rotary_emb(qkv)
154
+ # qkv: (B, S, 3, H, D) -> (B, H, S, D) for q,k,v
155
+ qkv = qkv.permute(0, 3, 2, 1, 4) # (B, H, 3, S, D)
156
+ q = qkv[:, :, 0]
157
+ k = qkv[:, :, 1]
158
+ v = qkv[:, :, 2]
159
+ return q, k, v
160
+
161
+ def _output(self, attn_out: torch.Tensor) -> torch.Tensor:
162
+ # attn_out: (B, H, S, D) -> (B, S, H*D)
163
+ bsz, _, seqlen, _ = attn_out.shape
164
+ out = attn_out.permute(0, 2, 1, 3).contiguous().view(bsz, seqlen, self.n_heads * self.head_dim)
165
+ return self.wo(out)
166
+
167
+ def forward(
168
+ self,
169
+ x: torch.Tensor,
170
+ attention_mask: Optional[torch.Tensor] = None,
171
+ output_attentions: bool = False,
172
+ ) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
173
+ q, k, v = self._qkv(x)
174
+ scale = 1.0 / math.sqrt(self.head_dim)
175
+ # (B, H, S, S). Compute in fp32 for numerical stability under bf16/fp16
176
+ # (matches what flash-attn / SDPA do internally).
177
+ scores = torch.matmul(q.float(), k.float().transpose(-2, -1)) * scale
178
+ if attention_mask is not None:
179
+ mask = attention_mask[:, None, None, :]
180
+ scores = scores.masked_fill(mask == 0, torch.finfo(scores.dtype).min)
181
+ attn = scores.softmax(dim=-1)
182
+ attn_for_return = attn.to(q.dtype) if output_attentions else None
183
+ context = torch.matmul(attn, v.float()).to(q.dtype)
184
+ return self._output(context), attn_for_return
185
+
186
+
187
+ class gLM2SdpaAttention(gLM2Attention):
188
+ """SDPA-backed attention. Falls back to eager when output_attentions=True."""
189
+
190
+ def forward(
191
+ self,
192
+ x: torch.Tensor,
193
+ attention_mask: Optional[torch.Tensor] = None,
194
+ output_attentions: bool = False,
195
+ ) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
196
+ if output_attentions:
197
+ return super().forward(x, attention_mask=attention_mask, output_attentions=True)
198
+
199
+ q, k, v = self._qkv(x)
200
+ attn_mask = None
201
+ if attention_mask is not None:
202
+ # SDPA wants (B, 1, 1, S) bool mask where True = attend.
203
+ attn_mask = attention_mask[:, None, None, :].bool()
204
+ out = F.scaled_dot_product_attention(q, k, v, attn_mask=attn_mask)
205
+ return self._output(out), None
206
+
207
+
208
+ class gLM2FlashAttention2(gLM2Attention):
209
+ """flash-attn 2 backed attention. Falls back to eager when output_attentions=True."""
210
+
211
+ def forward(
212
+ self,
213
+ x: torch.Tensor,
214
+ attention_mask: Optional[torch.Tensor] = None,
215
+ output_attentions: bool = False,
216
+ ) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
217
+ if output_attentions:
218
+ return super().forward(x, attention_mask=attention_mask, output_attentions=True)
219
+
220
+ try:
221
+ from flash_attn import flash_attn_func, flash_attn_varlen_func
222
+ from flash_attn.bert_padding import pad_input, unpad_input
223
+ except ImportError as e:
224
+ raise ImportError(
225
+ "flash_attn is required for attn_implementation='flash_attention_2'. "
226
+ "Install with: pip install flash-attn --no-build-isolation"
227
+ ) from e
228
+
229
+ bsz, seqlen, _ = x.shape
230
+ qkv = self.wqkv(x).view(bsz, seqlen, 3, self.n_heads, self.head_dim)
231
+ qkv = self.rotary_emb(qkv)
232
+ # flash-attn wants (B, S, H, D) per q/k/v.
233
+ q = qkv[:, :, 0]
234
+ k = qkv[:, :, 1]
235
+ v = qkv[:, :, 2]
236
+
237
+ orig_dtype = q.dtype
238
+ if q.dtype not in (torch.float16, torch.bfloat16):
239
+ q = q.to(torch.bfloat16)
240
+ k = k.to(torch.bfloat16)
241
+ v = v.to(torch.bfloat16)
242
+
243
+ if attention_mask is not None and (attention_mask == 0).any():
244
+ attention_mask_bool = attention_mask.bool() # True = attend
245
+ q_unpad, indices_q, cu_q, max_q, _ = unpad_input(q, attention_mask_bool)
246
+ k_unpad, _, cu_k, max_k, _ = unpad_input(k, attention_mask_bool)
247
+ v_unpad, _, _, _, _ = unpad_input(v, attention_mask_bool)
248
+ out_unpad = flash_attn_varlen_func(
249
+ q_unpad,
250
+ k_unpad,
251
+ v_unpad,
252
+ cu_seqlens_q=cu_q,
253
+ cu_seqlens_k=cu_k,
254
+ max_seqlen_q=max_q,
255
+ max_seqlen_k=max_k,
256
+ causal=False,
257
+ )
258
+ out = pad_input(out_unpad, indices_q, bsz, seqlen)
259
+ else:
260
+ out = flash_attn_func(q, k, v, causal=False)
261
+
262
+ out = out.to(orig_dtype)
263
+ out = out.contiguous().view(bsz, seqlen, self.n_heads * self.head_dim)
264
+ return self.wo(out), None
265
+
266
+
267
+ GLM2_ATTENTION_CLASSES = {
268
+ "eager": gLM2Attention,
269
+ "sdpa": gLM2SdpaAttention,
270
+ "flash_attention_2": gLM2FlashAttention2,
271
+ }
272
+
273
+
274
+ class FeedForward(nn.Module):
275
+ """SwiGLU MLP."""
276
+
277
+ def __init__(
278
+ self,
279
+ dim: int,
280
+ hidden_dim: int,
281
+ multiple_of: int,
282
+ ffn_dim_multiplier: Optional[float],
283
+ ):
284
+ super().__init__()
285
+ hidden_dim = int(2 * hidden_dim / 3)
286
+ if ffn_dim_multiplier is not None:
287
+ hidden_dim = int(ffn_dim_multiplier * hidden_dim)
288
+ hidden_dim = multiple_of * ((hidden_dim + multiple_of - 1) // multiple_of)
289
+
290
+ self.w1 = nn.Linear(dim, hidden_dim, bias=False)
291
+ self.w2 = nn.Linear(hidden_dim, dim, bias=False)
292
+ self.w3 = nn.Linear(dim, hidden_dim, bias=False)
293
+
294
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
295
+ return self.w2(F.silu(self.w1(x)) * self.w3(x))
296
+
297
+
298
+ class TransformerBlock(nn.Module):
299
+ """Pre-norm transformer block."""
300
+
301
+ def __init__(self, config: gLM2Config):
302
+ super().__init__()
303
+ attn_impl = getattr(config, "_attn_implementation", "eager")
304
+ attn_cls = GLM2_ATTENTION_CLASSES[attn_impl]
305
+ self.attention = attn_cls(config)
306
+ self.feed_forward = FeedForward(
307
+ dim=config.dim,
308
+ hidden_dim=4 * config.dim,
309
+ multiple_of=config.swiglu_multiple_of,
310
+ ffn_dim_multiplier=config.ffn_dim_multiplier,
311
+ )
312
+ self.attention_norm = RMSNorm(config.dim, eps=config.norm_eps)
313
+ self.ffn_norm = RMSNorm(config.dim, eps=config.norm_eps)
314
+
315
+ def forward(
316
+ self,
317
+ x: torch.Tensor,
318
+ attention_mask: Optional[torch.Tensor] = None,
319
+ output_attentions: bool = False,
320
+ ) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
321
+ attn_out, attn_weights = self.attention(
322
+ self.attention_norm(x),
323
+ attention_mask=attention_mask,
324
+ output_attentions=output_attentions,
325
+ )
326
+ h = x + attn_out
327
+ out = h + self.feed_forward(self.ffn_norm(h))
328
+ return out, attn_weights
329
+
330
+
331
+ class TransformerLayers(nn.Module):
332
+ def __init__(self, config: gLM2Config):
333
+ super().__init__()
334
+ self.config = config
335
+ self.layers = nn.ModuleList(
336
+ [TransformerBlock(config) for _ in range(config.depth)]
337
+ )
338
+
339
+ def forward(
340
+ self,
341
+ x: torch.Tensor,
342
+ attention_mask: Optional[torch.Tensor] = None,
343
+ output_hidden_states: bool = False,
344
+ output_attentions: bool = False,
345
+ ) -> Tuple[torch.Tensor, Optional[Tuple[torch.Tensor, ...]], Optional[Tuple[torch.Tensor, ...]]]:
346
+ if x.shape[-1] != self.config.dim:
347
+ raise ValueError(
348
+ f"Input feature dim should be {self.config.dim}, but input has shape {x.shape}"
349
+ )
350
+ all_hidden_states: list = []
351
+ all_attentions: list = []
352
+ if output_hidden_states:
353
+ all_hidden_states.append(x)
354
+ for layer in self.layers:
355
+ x, attn_weights = layer(
356
+ x, attention_mask=attention_mask, output_attentions=output_attentions
357
+ )
358
+ if output_hidden_states:
359
+ all_hidden_states.append(x)
360
+ if output_attentions:
361
+ all_attentions.append(attn_weights)
362
+ hidden_tuple = tuple(all_hidden_states) if output_hidden_states else None
363
+ attn_tuple = tuple(all_attentions) if output_attentions else None
364
+ return x, hidden_tuple, attn_tuple
365
+
366
+
367
+ class gLM2PreTrainedModel(PreTrainedModel):
368
+ """Base class for gLM2 weight init / from_pretrained dispatch."""
369
+
370
+ config_class = gLM2Config
371
+ base_model_prefix = "glm2"
372
+ supports_gradient_checkpointing = False
373
+ _supports_sdpa = True
374
+ _supports_flash_attn_2 = True
375
+
376
+ def _init_weights(self, module):
377
+ std = getattr(self.config, "initializer_range", 0.02)
378
+ if isinstance(module, nn.Linear):
379
+ nn.init.normal_(module.weight, std=std)
380
+ if module.bias is not None:
381
+ nn.init.zeros_(module.bias)
382
+ elif isinstance(module, nn.Embedding):
383
+ nn.init.normal_(module.weight, std=std)
384
+ if module.padding_idx is not None:
385
+ with torch.no_grad():
386
+ module.weight[module.padding_idx].zero_()
387
+ elif isinstance(module, RotaryEmbedding):
388
+ inv_freq = 1.0 / (
389
+ module.base
390
+ ** (
391
+ torch.arange(
392
+ 0, module.dim, 2, device=module.inv_freq.device, dtype=torch.float32
393
+ )
394
+ / module.dim
395
+ )
396
+ )
397
+ with torch.no_grad():
398
+ module.inv_freq.copy_(inv_freq)
399
+ elif isinstance(module, RMSNorm):
400
+ with torch.no_grad():
401
+ module.variance_epsilon.fill_(self.config.norm_eps)
402
+
403
+
404
+ class gLM2Model(gLM2PreTrainedModel):
405
+ """gLM2 backbone (token embedding + transformer encoder)."""
406
+
407
+ def __init__(self, config: gLM2Config):
408
+ super().__init__(config)
409
+ self.config = config
410
+ self.tok_embeddings = nn.Embedding(config.vocab_size, config.dim)
411
+ self.encoder = TransformerLayers(config)
412
+ self.post_init()
413
+
414
+ def get_input_embeddings(self) -> nn.Embedding:
415
+ return self.tok_embeddings
416
+
417
+ def set_input_embeddings(self, value: nn.Embedding) -> None:
418
+ self.tok_embeddings = value
419
+
420
+ def forward(
421
+ self,
422
+ input_ids: torch.Tensor,
423
+ attention_mask: Optional[torch.Tensor] = None,
424
+ output_hidden_states: Optional[bool] = None,
425
+ output_attentions: Optional[bool] = None,
426
+ return_dict: Optional[bool] = None,
427
+ ) -> Union[Tuple[torch.Tensor, ...], BaseModelOutput]:
428
+ output_hidden_states = (
429
+ output_hidden_states
430
+ if output_hidden_states is not None
431
+ else self.config.output_hidden_states
432
+ )
433
+ output_attentions = (
434
+ output_attentions
435
+ if output_attentions is not None
436
+ else self.config.output_attentions
437
+ )
438
+ return_dict = (
439
+ return_dict if return_dict is not None else self.config.use_return_dict
440
+ )
441
+
442
+ h = self.tok_embeddings(input_ids)
443
+ sequence_output, all_hidden_states, all_attentions = self.encoder(
444
+ h,
445
+ attention_mask=attention_mask,
446
+ output_hidden_states=bool(output_hidden_states),
447
+ output_attentions=bool(output_attentions),
448
+ )
449
+
450
+ if not return_dict:
451
+ return tuple(
452
+ v
453
+ for v in (sequence_output, all_hidden_states, all_attentions)
454
+ if v is not None
455
+ )
456
+
457
+ return BaseModelOutput(
458
+ last_hidden_state=sequence_output,
459
+ hidden_states=all_hidden_states,
460
+ attentions=all_attentions,
461
+ )
462
+
463
+
464
+ class gLM2LMHead(nn.Module):
465
+ def __init__(self, config: gLM2Config):
466
+ super().__init__()
467
+ self.norm = RMSNorm(config.dim, eps=config.norm_eps)
468
+ self.proj_output = nn.Linear(config.dim, config.vocab_size, bias=False)
469
+
470
+ def forward(self, features: torch.Tensor) -> torch.Tensor:
471
+ return self.proj_output(self.norm(features))
472
+
473
+
474
+ class gLM2ForMaskedLM(gLM2PreTrainedModel):
475
+ """gLM2 with the masked-language-modeling head."""
476
+
477
+ _tied_weights_keys = []
478
+
479
+ def __init__(self, config: gLM2Config):
480
+ super().__init__(config)
481
+ self.glm2 = gLM2Model(config)
482
+ self.lm_head = gLM2LMHead(config)
483
+ self.post_init()
484
+
485
+ def get_output_embeddings(self) -> nn.Linear:
486
+ return self.lm_head.proj_output
487
+
488
+ def set_output_embeddings(self, new_embeddings: nn.Linear) -> None:
489
+ self.lm_head.proj_output = new_embeddings
490
+
491
+ def forward(
492
+ self,
493
+ input_ids: torch.Tensor,
494
+ attention_mask: Optional[torch.Tensor] = None,
495
+ labels: Optional[torch.LongTensor] = None,
496
+ output_hidden_states: Optional[bool] = None,
497
+ output_attentions: Optional[bool] = None,
498
+ return_dict: Optional[bool] = None,
499
+ ) -> Union[Tuple[torch.Tensor, ...], MaskedLMOutput]:
500
+ return_dict = (
501
+ return_dict if return_dict is not None else self.config.use_return_dict
502
+ )
503
+
504
+ outputs = self.glm2(
505
+ input_ids,
506
+ attention_mask=attention_mask,
507
+ output_hidden_states=output_hidden_states,
508
+ output_attentions=output_attentions,
509
+ return_dict=True,
510
+ )
511
+ sequence_output = outputs.last_hidden_state
512
+ prediction_scores = self.lm_head(sequence_output)
513
+
514
+ masked_lm_loss = None
515
+ if labels is not None:
516
+ loss_fct = CrossEntropyLoss()
517
+ labels = labels.to(prediction_scores.device)
518
+ masked_lm_loss = loss_fct(
519
+ prediction_scores.view(-1, self.config.vocab_size), labels.view(-1)
520
+ )
521
+
522
+ if not return_dict:
523
+ output = (prediction_scores,)
524
+ if outputs.hidden_states is not None:
525
+ output = output + (outputs.hidden_states,)
526
+ if outputs.attentions is not None:
527
+ output = output + (outputs.attentions,)
528
+ return ((masked_lm_loss,) + output) if masked_lm_loss is not None else output
529
+
530
+ return MaskedLMOutput(
531
+ loss=masked_lm_loss,
532
+ logits=prediction_scores,
533
+ hidden_states=outputs.hidden_states,
534
+ attentions=outputs.attentions,
535
+ )
special_tokens_map.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cls_token": "<cls>",
3
+ "eos_token": "<eos>",
4
+ "mask_token": "<mask>",
5
+ "pad_token": "<pad>",
6
+ "sep_token": "<sep>",
7
+ "unk_token": "<unk>"
8
+ }
tokenizer.json ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "version": "1.0",
3
+ "truncation": null,
4
+ "padding": null,
5
+ "added_tokens": [
6
+ {
7
+ "id": 0,
8
+ "content": "<cls>",
9
+ "single_word": false,
10
+ "lstrip": false,
11
+ "rstrip": false,
12
+ "normalized": false,
13
+ "special": true
14
+ },
15
+ {
16
+ "id": 1,
17
+ "content": "<pad>",
18
+ "single_word": false,
19
+ "lstrip": false,
20
+ "rstrip": false,
21
+ "normalized": false,
22
+ "special": true
23
+ },
24
+ {
25
+ "id": 2,
26
+ "content": "<eos>",
27
+ "single_word": false,
28
+ "lstrip": false,
29
+ "rstrip": false,
30
+ "normalized": false,
31
+ "special": true
32
+ },
33
+ {
34
+ "id": 3,
35
+ "content": "<unk>",
36
+ "single_word": false,
37
+ "lstrip": false,
38
+ "rstrip": false,
39
+ "normalized": false,
40
+ "special": true
41
+ },
42
+ {
43
+ "id": 33,
44
+ "content": "<+>",
45
+ "single_word": false,
46
+ "lstrip": false,
47
+ "rstrip": false,
48
+ "normalized": false,
49
+ "special": true
50
+ },
51
+ {
52
+ "id": 34,
53
+ "content": "<->",
54
+ "single_word": false,
55
+ "lstrip": false,
56
+ "rstrip": false,
57
+ "normalized": false,
58
+ "special": true
59
+ },
60
+ {
61
+ "id": 35,
62
+ "content": "<mask>",
63
+ "single_word": false,
64
+ "lstrip": false,
65
+ "rstrip": false,
66
+ "normalized": false,
67
+ "special": true
68
+ },
69
+ {
70
+ "id": 36,
71
+ "content": "<sep>",
72
+ "single_word": false,
73
+ "lstrip": false,
74
+ "rstrip": false,
75
+ "normalized": false,
76
+ "special": true
77
+ }
78
+ ],
79
+ "normalizer": null,
80
+ "pre_tokenizer": null,
81
+ "post_processor": null,
82
+ "decoder": null,
83
+ "model": {
84
+ "type": "BPE",
85
+ "dropout": null,
86
+ "unk_token": "<unk>",
87
+ "continuing_subword_prefix": null,
88
+ "end_of_word_suffix": null,
89
+ "fuse_unk": false,
90
+ "byte_fallback": false,
91
+ "vocab": {
92
+ "<cls>": 0,
93
+ "<pad>": 1,
94
+ "<eos>": 2,
95
+ "<unk>": 3,
96
+ "L": 4,
97
+ "A": 5,
98
+ "G": 6,
99
+ "V": 7,
100
+ "S": 8,
101
+ "E": 9,
102
+ "R": 10,
103
+ "T": 11,
104
+ "I": 12,
105
+ "D": 13,
106
+ "P": 14,
107
+ "K": 15,
108
+ "Q": 16,
109
+ "N": 17,
110
+ "F": 18,
111
+ "Y": 19,
112
+ "M": 20,
113
+ "H": 21,
114
+ "W": 22,
115
+ "C": 23,
116
+ "X": 24,
117
+ "B": 25,
118
+ "U": 26,
119
+ "Z": 27,
120
+ "O": 28,
121
+ "a": 29,
122
+ "t": 30,
123
+ "c": 31,
124
+ "g": 32,
125
+ "<+>": 33,
126
+ "<->": 34,
127
+ "<mask>": 35,
128
+ "<sep>": 36
129
+ },
130
+ "merges": []
131
+ }
132
+ }
tokenizer_config.json ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "added_tokens_decoder": {
3
+ "0": {
4
+ "content": "<cls>",
5
+ "lstrip": false,
6
+ "normalized": false,
7
+ "rstrip": false,
8
+ "single_word": false,
9
+ "special": true
10
+ },
11
+ "1": {
12
+ "content": "<pad>",
13
+ "lstrip": false,
14
+ "normalized": false,
15
+ "rstrip": false,
16
+ "single_word": false,
17
+ "special": true
18
+ },
19
+ "2": {
20
+ "content": "<eos>",
21
+ "lstrip": false,
22
+ "normalized": false,
23
+ "rstrip": false,
24
+ "single_word": false,
25
+ "special": true
26
+ },
27
+ "3": {
28
+ "content": "<unk>",
29
+ "lstrip": false,
30
+ "normalized": false,
31
+ "rstrip": false,
32
+ "single_word": false,
33
+ "special": true
34
+ },
35
+ "33": {
36
+ "content": "<+>",
37
+ "lstrip": false,
38
+ "normalized": false,
39
+ "rstrip": false,
40
+ "single_word": false,
41
+ "special": true
42
+ },
43
+ "34": {
44
+ "content": "<->",
45
+ "lstrip": false,
46
+ "normalized": false,
47
+ "rstrip": false,
48
+ "single_word": false,
49
+ "special": true
50
+ },
51
+ "35": {
52
+ "content": "<mask>",
53
+ "lstrip": false,
54
+ "normalized": false,
55
+ "rstrip": false,
56
+ "single_word": false,
57
+ "special": true
58
+ },
59
+ "36": {
60
+ "content": "<sep>",
61
+ "lstrip": false,
62
+ "normalized": false,
63
+ "rstrip": false,
64
+ "single_word": false,
65
+ "special": true
66
+ }
67
+ },
68
+ "auto_map": {
69
+ "AutoTokenizer": [
70
+ "glm_tokenizer.gLM2Tokenizer",
71
+ null
72
+ ]
73
+ },
74
+ "clean_up_tokenization_spaces": true,
75
+ "cls_token": "<cls>",
76
+ "eos_token": "<eos>",
77
+ "mask_token": "<mask>",
78
+ "model_max_length": 4096,
79
+ "pad_token": "<pad>",
80
+ "sep_token": "<sep>",
81
+ "tokenizer_class": "gLM2Tokenizer",
82
+ "unk_token": "<unk>"
83
+ }