MaagDeveloper commited on
Commit
86b4919
ยท
verified ยท
1 Parent(s): 82acb35

Release NeoLM-Small-Base Stage 1 Foundation BF16

Browse files
README.md CHANGED
@@ -1,82 +1,127 @@
1
  ---
2
  language:
3
  - en
4
- datasets:
5
- - MaagDeveloper/NeoCorpus
6
  tags:
7
  - neolm
8
- - tokenizer
9
- - byte-level-bpe
10
- - pretraining
 
 
 
 
 
 
11
  ---
12
 
13
- # NeoLM-Small-Base
 
 
 
 
14
 
15
- NeoLM-Small-Base is a planned decoder-only language model
16
- in the NeoLM family, developed from scratch.
17
 
18
- **Current status: Tokenizer only. Model weights are not available yet.**
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  ## Tokenizer
21
 
 
 
22
  | Property | Value |
23
- |---|---|
24
  | Algorithm | ByteLevel BPE |
25
  | Vocabulary size | 49,152 |
26
  | Training data | NeoCorpus / foundation / train |
27
  | Training documents | 1,889,952 |
28
- | Pre-tokenization | GPT-style regex, 1โ€“3 digit groups |
29
- | EOS token | `<โ”‚endoftextโ”‚>` (ID 0) |
30
- | PAD token | `<โ”‚padโ”‚>` (ID 1) |
31
  | BOS token | None |
32
 
33
- The tokenizer was trained from scratch on the training split only.
34
 
35
- ## Load the Tokenizer
 
36
 
37
- from transformers import AutoTokenizer
38
 
39
- tokenizer = AutoTokenizer.from_pretrained(
40
- "MaagDeveloper/NeoLM-Small-Base"
41
- )
42
 
43
- ## Dataset
 
 
 
 
 
 
44
 
45
- Source: [NeoCorpus](https://huggingface.co/datasets/MaagDeveloper/NeoCorpus)
46
 
47
- Configuration: `foundation`
48
 
49
- The source dataset is derived from NVIDIA Nemotron-ClimbMix
50
- through Andrej Karpathy's globally shuffled redistribution.
51
 
52
- The dataset is published under CC BY-NC 4.0 licensing conditions.
53
 
54
- ## Model Development
55
 
56
- The following details have not been finalized:
 
 
57
 
58
- - Transformer architecture and parameter count
59
- - Context length
60
- - Training configuration and compute budget
61
- - Evaluation metrics and benchmarks
62
- - Pretraining checkpoints
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
- Training stages will be recorded as versioned revisions
65
- after the corresponding checkpoints are available.
66
 
67
- ## Limitations
68
 
69
- This repository currently contains a tokenizer, not a trained
70
- language model. It cannot generate text or perform inference.
71
 
72
- The tokenizer has passed local encoding, decoding, EOS,
73
- and save/reload checks.
74
 
75
- ## Attribution
76
 
77
- Dataset sources:
78
- - [NVIDIA Nemotron-ClimbMix](https://huggingface.co/datasets/nvidia/Nemotron-ClimbMix)
79
- - [Karpathy ClimbMix Shuffle](https://huggingface.co/datasets/karpathy/climbmix-400b-shuffle)
80
 
81
- NeoLM is an independent project and is not affiliated with
82
- NVIDIA, Andrej Karpathy, or Hugging Face.
 
1
  ---
2
  language:
3
  - en
 
 
4
  tags:
5
  - neolm
6
+ - causal-lm
7
+ - text-generation
8
+ - custom-code
9
+ - pretrained
10
+ - foundation
11
+ - pytorch
12
+ datasets:
13
+ - MaagDeveloper/NeoCorpus
14
+ pipeline_tag: text-generation
15
  ---
16
 
17
+ # NeoLM-Small-Base โ€” Stage 1: Foundation
18
+
19
+ **NeoLM-Small-Base** is an English-focused, decoder-only Transformer language model trained from scratch with PyTorch and Hugging Face Transformers. This repository publishes the **Stage 1 Foundation** base-model checkpoint in **bfloat16** format. It is a **base next-token prediction model**, not an instruction-tuned chat assistant.
20
+
21
+ The fixed Foundation release can be loaded using the `stage1-foundation` revision after the release tag is created.
22
 
23
+ ## Architecture
 
24
 
25
+ | Property | Value |
26
+ | --- | --- |
27
+ | Parameters (unique, tied embeddings) | 61,356,032 |
28
+ | Layers | 12 |
29
+ | Hidden dimension | 512 |
30
+ | Query heads / KV heads | 8 / 2 (GQA) |
31
+ | MLP | SwiGLU, intermediate size 1,536 |
32
+ | Normalization | RMSNorm, QK Norm |
33
+ | Positional encoding | RoPE |
34
+ | Context length | 1,024 tokens |
35
+ | Vocabulary | 49,152 (custom ByteLevel BPE) |
36
+ | Special tokens | EOS ID 0, PAD ID 1; no BOS |
37
+ | Weight format | BF16, safetensors |
38
+ | Model implementation | Custom `NeoLMForCausalLM` (`trust_remote_code=True`) |
39
 
40
  ## Tokenizer
41
 
42
+ NeoLM uses a **custom ByteLevel BPE tokenizer trained from scratch**, not a tokenizer borrowed from another model. It was trained exclusively on the **1,889,952 documents** in `NeoCorpus / foundation / train`; validation and test documents were excluded from tokenizer training.
43
+
44
  | Property | Value |
45
+ | --- | --- |
46
  | Algorithm | ByteLevel BPE |
47
  | Vocabulary size | 49,152 |
48
  | Training data | NeoCorpus / foundation / train |
49
  | Training documents | 1,889,952 |
50
+ | Pre-tokenization | GPT-style regex with 1โ€“3 digit groups |
 
 
51
  | BOS token | None |
52
 
53
+ Special-token spellings and IDs (kept outside the Markdown table to preserve literal pipe characters):
54
 
55
+ - EOS: `<|endoftext|>` โ€” ID **0**
56
+ - PAD: `<|pad|>` โ€” ID **1**
57
 
58
+ The tokenizer passed local encode/decode round-trip, special-token, and save/reload checks. It can also be loaded **without loading model weights**:
59
 
60
+ ```python
61
+ from transformers import AutoTokenizer
 
62
 
63
+ tokenizer = AutoTokenizer.from_pretrained(
64
+ "MaagDeveloper/NeoLM-Small-Base",
65
+ revision="stage1-foundation",
66
+ trust_remote_code=True,
67
+ )
68
+ print(tokenizer.encode("Hello, NeoLM!"))
69
+ ```
70
 
71
+ ## Training data
72
 
73
+ Foundation pretraining uses the **`foundation`** configuration of [NeoCorpus](https://huggingface.co/datasets/MaagDeveloper/NeoCorpus), derived from a filtered English-focused subset of [Karpathy ClimbMix Shuffle](https://huggingface.co/datasets/karpathy/climbmix-400b-shuffle), based on [NVIDIA Nemotron-ClimbMix](https://huggingface.co/datasets/nvidia/Nemotron-ClimbMix). The train split contains **1,889,952 documents** and **1,147,218,931 tokens**, counted with this release's tokenizer (including document EOS separators). Validation and test splits are kept separate. See the dataset card for data preparation, attribution, and licensing information.
74
 
75
+ This is a released training checkpoint rather than a claim of complete convergence or optimal training duration. The intended three-epoch schedule was not completed. Exact released-checkpoint step and full Foundation validation/test perplexity have **not been documented in this card**; downstream task results should not be confused with base-language-model perplexity.
 
76
 
77
+ ## Load and generate text
78
 
79
+ Install compatible versions of `torch` and `transformers`. The model requires custom Python code, so review the repository code before enabling `trust_remote_code=True`.
80
 
81
+ ```python
82
+ import torch
83
+ from transformers import AutoTokenizer, AutoModelForCausalLM
84
 
85
+ repo_id = "MaagDeveloper/NeoLM-Small-Base"
86
+ revision = "stage1-foundation"
87
+
88
+ tokenizer = AutoTokenizer.from_pretrained(
89
+ repo_id, revision=revision, trust_remote_code=True
90
+ )
91
+ model = AutoModelForCausalLM.from_pretrained(
92
+ repo_id, revision=revision, trust_remote_code=True,
93
+ dtype=torch.bfloat16,
94
+ ).eval()
95
+
96
+ # For a CPU that does not support BF16 well, load with dtype=torch.float32 instead.
97
+ prompt = "The future of artificial intelligence"
98
+ inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=1024)
99
+ with torch.no_grad():
100
+ outputs = model.generate(
101
+ **inputs,
102
+ max_new_tokens=64,
103
+ do_sample=True,
104
+ temperature=0.8,
105
+ top_p=0.9,
106
+ repetition_penalty=1.15,
107
+ eos_token_id=tokenizer.eos_token_id,
108
+ pad_token_id=tokenizer.pad_token_id,
109
+ )
110
+ print(tokenizer.decode(outputs[0], skip_special_tokens=True))
111
+ ```
112
 
113
+ The code above is **text completion**, not role-based chat. NeoLM-Small-Base may not reliably follow instructions, answer factual questions, or perform multi-step reasoning. A separate instruction-tuned model belongs in a distinct repository.
 
114
 
115
+ ## Evaluation and limitations
116
 
117
+ The base model demonstrated decreasing training and held-out validation next-token loss during Foundation pretraining. Separate fine-tuning experiments have shown that this architecture can adapt to QA and text classification, but **those fine-tuned results are not performance claims for this Base checkpoint**.
 
118
 
119
+ Full Foundation validation/test loss and perplexity for the released checkpoint are not reported here until measured and verified. The model is small, English-focused, and can hallucinate, repeat text, produce harmful or biased content, and fail on complex reasoning, factual recall, or instruction-following tasks. Do not treat generated material as verified information.
 
120
 
121
+ ## Provenance and licensing
122
 
123
+ - Dataset: [MaagDeveloper/NeoCorpus](https://huggingface.co/datasets/MaagDeveloper/NeoCorpus), `foundation` configuration.
124
+ - NeoCorpus's attribution and CC BY-NC 4.0 notice do not automatically establish a separate license for model weights. **Please verify the appropriate model-weight license and source-data obligations before commercial use.**
125
+ - The `stage1-foundation` tag is intended to preserve an immutable reference to this release before later training stages.
126
 
127
+ NeoLM is an independent project and is not affiliated with NVIDIA, Andrej Karpathy, or Hugging Face.
 
config.json ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "NeoLMForCausalLM"
4
+ ],
5
+ "auto_map": {
6
+ "AutoConfig": "configuration_neolm.NeoLMConfig",
7
+ "AutoModelForCausalLM": "modeling_neolm.NeoLMForCausalLM",
8
+ "AutoModelForSequenceClassification": "modeling_neolm.NeoLMForSequenceClassification"
9
+ },
10
+ "bos_token_id": null,
11
+ "dropout": 0.1,
12
+ "dtype": "bfloat16",
13
+ "eos_token_id": 0,
14
+ "hidden_size": 512,
15
+ "intermediate_size": 1536,
16
+ "max_position_embeddings": 1024,
17
+ "mlp_multiple_of": 256,
18
+ "model_type": "neolm",
19
+ "num_attention_heads": 8,
20
+ "num_hidden_layers": 12,
21
+ "num_key_value_heads": 2,
22
+ "pad_token_id": 1,
23
+ "qk_norm": true,
24
+ "rms_norm_eps": 1e-06,
25
+ "rope_base": 10000,
26
+ "scale_residual_init": true,
27
+ "tie_word_embeddings": true,
28
+ "transformers_version": "5.14.1",
29
+ "use_cache": false,
30
+ "vocab_size": 49152
31
+ }
configuration_neolm.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ from transformers import PretrainedConfig
3
+
4
+ class NeoLMConfig(PretrainedConfig):
5
+ model_type = "neolm"
6
+
7
+ def __init__(
8
+ self,
9
+ vocab_size: int = 32000,
10
+ max_position_embeddings: int = 512,
11
+ hidden_size: int = 512,
12
+ num_attention_heads: int = 8,
13
+ num_key_value_heads: int | None = None,
14
+ num_hidden_layers: int = 8,
15
+ intermediate_size: int = None,
16
+ dropout: float = 0.0,
17
+ tie_word_embeddings: bool = True,
18
+ rope_base: int = 10_000,
19
+ mlp_multiple_of: int = 256,
20
+ rms_norm_eps: float = 1e-6,
21
+ qk_norm: bool = True,
22
+ scale_residual_init: bool = True,
23
+ use_cache: bool = False,
24
+ pad_token_id: int = None,
25
+ bos_token_id: int = None,
26
+ eos_token_id: int = None,
27
+ **kwargs,
28
+ ):
29
+ super().__init__(
30
+ pad_token_id=pad_token_id,
31
+ bos_token_id=bos_token_id,
32
+ eos_token_id=eos_token_id,
33
+ **kwargs,
34
+ )
35
+
36
+ assert hidden_size % num_attention_heads == 0, (
37
+ f"hidden_size ({hidden_size}) ูŠุฌุจ ุฃู† ูŠู‚ุณู… ุนู„ู‰ num_attention_heads ({num_attention_heads})"
38
+ )
39
+
40
+ if num_key_value_heads is None:
41
+ num_key_value_heads = num_attention_heads
42
+
43
+ if not (
44
+ 1 <= num_key_value_heads <= num_attention_heads
45
+ and num_attention_heads % num_key_value_heads == 0
46
+ ):
47
+ raise ValueError(
48
+ "num_key_value_heads must be positive "
49
+ "and divide num_attention_heads"
50
+ )
51
+
52
+ if intermediate_size is None:
53
+ intermediate_size = mlp_multiple_of * math.ceil(
54
+ int(8 * hidden_size / 3) / mlp_multiple_of
55
+ )
56
+
57
+ self.vocab_size = vocab_size
58
+ self.max_position_embeddings = max_position_embeddings
59
+ self.hidden_size = hidden_size
60
+ self.num_attention_heads = num_attention_heads
61
+ self.num_key_value_heads = num_key_value_heads
62
+ self.num_hidden_layers = num_hidden_layers
63
+ self.intermediate_size = intermediate_size
64
+ self.dropout = dropout
65
+ self.tie_word_embeddings = tie_word_embeddings
66
+ self.rope_base = rope_base
67
+ self.mlp_multiple_of = mlp_multiple_of
68
+ self.rms_norm_eps = rms_norm_eps
69
+ self.qk_norm = qk_norm
70
+ self.scale_residual_init = scale_residual_init
71
+ self.use_cache = use_cache
generation_config.json ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_from_model_config": true,
3
+ "eos_token_id": [
4
+ 0
5
+ ],
6
+ "output_attentions": false,
7
+ "output_hidden_states": false,
8
+ "pad_token_id": 1,
9
+ "transformers_version": "5.14.1",
10
+ "use_cache": false
11
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:74222b78cb0c83319fe588052fda4e335a6fe88dfd67d186e0b9e2390c1a054f
3
+ size 122723096
modeling_neolm.py ADDED
@@ -0,0 +1,639 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import torch
3
+ import torch.nn as nn
4
+ import torch.nn.functional as F
5
+
6
+ from transformers import PreTrainedModel
7
+ from transformers import initialization as init
8
+ from transformers.generation import GenerationMixin
9
+ from transformers.modeling_outputs import CausalLMOutputWithPast, SequenceClassifierOutput
10
+ from transformers.cache_utils import Cache, DynamicCache
11
+
12
+ from .configuration_neolm import NeoLMConfig
13
+
14
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
15
+ # RMSNorm
16
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
17
+
18
+ class RMSNorm(nn.Module):
19
+ def __init__(self, dim: int, eps: float = 1e-6):
20
+ super().__init__()
21
+ self.eps = eps
22
+ self.weight = nn.Parameter(torch.ones(dim))
23
+
24
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
25
+ return self.weight * x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)
26
+
27
+
28
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
29
+ # RoPE
30
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
31
+
32
+ def precompute_rope_freqs(head_dim: int, seq_len: int, base: int = 10_000):
33
+ assert head_dim % 2 == 0
34
+ # float64 ุนุดุงู† ู†ุชุฌู†ุจ overflow
35
+ inv_freq = 1.0 / (base ** (torch.arange(0, head_dim, 2).double() / head_dim))
36
+ t = torch.arange(seq_len).double()
37
+ freqs = torch.outer(t, inv_freq)
38
+ return freqs.cos().float(), freqs.sin().float()
39
+
40
+ def apply_rope(
41
+ x: torch.Tensor,
42
+ cos: torch.Tensor,
43
+ sin: torch.Tensor,
44
+ offset: int = 0,
45
+ base: int = 10_000,
46
+ ):
47
+ B, H, T, D = x.shape
48
+ needed = offset + T
49
+
50
+ if needed > cos.shape[0]:
51
+ cos, sin = precompute_rope_freqs(
52
+ head_dim=D,
53
+ seq_len=needed + 64,
54
+ base=base,
55
+ )
56
+
57
+ cos = cos[offset:offset + T].to(
58
+ device=x.device, dtype=x.dtype
59
+ )[None, None]
60
+
61
+ sin = sin[offset:offset + T].to(
62
+ device=x.device, dtype=x.dtype
63
+ )[None, None]
64
+
65
+ x1 = x[..., ::2]
66
+ x2 = x[..., 1::2]
67
+
68
+ out = torch.empty_like(x)
69
+ out[..., ::2] = x1 * cos - x2 * sin
70
+ out[..., 1::2] = x1 * sin + x2 * cos
71
+
72
+ return out
73
+
74
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
75
+ # Causal Self-Attention (ู…ุน KV Cache)
76
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
77
+
78
+ class CausalSelfAttention(nn.Module):
79
+ def __init__(self, config: NeoLMConfig):
80
+ super().__init__()
81
+ self.num_heads = config.num_attention_heads
82
+ self.hidden_size = config.hidden_size
83
+ self.head_dim = config.hidden_size // config.num_attention_heads
84
+
85
+ self.num_key_value_heads = config.num_key_value_heads
86
+ self.num_key_value_groups = (
87
+ self.num_heads // self.num_key_value_heads
88
+ )
89
+ self.kv_dim = self.num_key_value_heads * self.head_dim
90
+
91
+ self.qk_norm = config.qk_norm
92
+
93
+ self.q_norm = (
94
+ RMSNorm(self.head_dim, config.rms_norm_eps)
95
+ if self.qk_norm else None
96
+ )
97
+
98
+ self.k_norm = (
99
+ RMSNorm(self.head_dim, config.rms_norm_eps)
100
+ if self.qk_norm else None
101
+ )
102
+
103
+ self.rope_base = config.rope_base
104
+ self.dropout = config.dropout
105
+
106
+ self.qkv = nn.Linear(config.hidden_size, config.hidden_size + 2 * self.kv_dim, bias=False)
107
+ self.proj = nn.Linear(config.hidden_size, config.hidden_size, bias=False)
108
+ self.proj._residual_projection = config.scale_residual_init
109
+
110
+ cos, sin = precompute_rope_freqs(
111
+ self.head_dim, config.max_position_embeddings, config.rope_base
112
+ )
113
+ # persistent=False โ†’ ู…ุด ุจุชุชุญูุธ ููŠ ุงู„ู€ checkpointุŒ ุจุชุชุญุณุจ ู…ู† ุฌุฏูŠุฏ ุนู†ุฏ ุงู„ู€ init
114
+ self.register_buffer("rope_cos", cos, persistent=False)
115
+ self.register_buffer("rope_sin", sin, persistent=False)
116
+
117
+ def forward(
118
+ self,
119
+ x: torch.Tensor,
120
+ past_key_value: Cache | None = None,
121
+ use_cache: bool = False,
122
+ layer_idx: int = 0,
123
+ attention_mask: torch.Tensor | None = None,
124
+ ) -> tuple[torch.Tensor, Cache | None]:
125
+
126
+ B, T, C = x.shape
127
+
128
+ q, k, v = self.qkv(x).split(
129
+ [
130
+ self.hidden_size,
131
+ self.kv_dim,
132
+ self.kv_dim,
133
+ ],
134
+ dim=-1,
135
+ )
136
+
137
+ def reshape(t, num_heads):
138
+ return t.view(
139
+ B, T, num_heads, self.head_dim
140
+ ).transpose(1, 2)
141
+
142
+ q = reshape(q, self.num_heads)
143
+ k = reshape(k, self.num_key_value_heads)
144
+ v = reshape(v, self.num_key_value_heads)
145
+
146
+ # QK-Norm: normalize queries and keys per attention head
147
+ if self.qk_norm:
148
+ q = self.q_norm(q)
149
+ k = self.k_norm(k)
150
+
151
+ # offset = ุนุฏุฏ ุงู„ู€ tokens ุงู„ู…ุญููˆุธุฉ ููŠ ุงู„ู€ cache
152
+ offset = 0
153
+ if use_cache and past_key_value is not None:
154
+ offset = past_key_value.get_seq_length(layer_idx)
155
+
156
+ q = apply_rope(
157
+ q,
158
+ self.rope_cos,
159
+ self.rope_sin,
160
+ offset=offset,
161
+ base=self.rope_base,
162
+ )
163
+
164
+ k = apply_rope(
165
+ k,
166
+ self.rope_cos,
167
+ self.rope_sin,
168
+ offset=offset,
169
+ base=self.rope_base,
170
+ )
171
+
172
+ # KV Cache: update ุจูŠุถูŠู ุงู„ู€ current k,v ูˆุจูŠุฑุฌุน ุงู„ูƒู„
173
+ if use_cache and past_key_value is not None:
174
+ k, v = past_key_value.update(k, v, layer_idx)
175
+
176
+
177
+
178
+ # Causal + Padding Mask
179
+ key_length = k.size(-2)
180
+
181
+ if attention_mask is not None:
182
+ if (
183
+ attention_mask.ndim != 2
184
+ or attention_mask.shape[0] != B
185
+ or attention_mask.shape[1] < key_length
186
+ ):
187
+ raise ValueError(
188
+ "Invalid attention_mask shape"
189
+ )
190
+
191
+ valid_keys = attention_mask[
192
+ :, -key_length:
193
+ ].to(device=q.device, dtype=torch.bool)
194
+
195
+ q_pos = offset + torch.arange(
196
+ T, device=q.device
197
+ )
198
+ k_pos = torch.arange(
199
+ key_length, device=q.device
200
+ )
201
+
202
+ causal = k_pos[None, :] <= q_pos[:, None]
203
+
204
+ attn_mask = (
205
+ valid_keys[:, None, None, :]
206
+ & causal[None, None, :, :]
207
+ )
208
+ is_causal = False
209
+
210
+ elif offset == 0:
211
+ attn_mask = None
212
+ is_causal = True
213
+
214
+ elif T == 1:
215
+ attn_mask = None
216
+ is_causal = False
217
+
218
+ else:
219
+ q_pos = offset + torch.arange(T, device=q.device)
220
+ k_pos = torch.arange(key_length, device=q.device)
221
+
222
+ attn_mask = k_pos[None, :] <= q_pos[:, None]
223
+ is_causal = False
224
+
225
+ y = F.scaled_dot_product_attention(
226
+ q, k, v,
227
+ attn_mask=attn_mask,
228
+ dropout_p=self.dropout if self.training else 0.0,
229
+ is_causal=is_causal,
230
+ enable_gqa=(
231
+ self.num_heads != self.num_key_value_heads
232
+ ),
233
+ )
234
+
235
+ y = y.transpose(1, 2).contiguous().view(B, T, C)
236
+ return self.proj(y), past_key_value
237
+
238
+
239
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
240
+ # SwiGLU MLP
241
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
242
+
243
+ class SwiGLU(nn.Module):
244
+ def __init__(self, config: NeoLMConfig):
245
+ super().__init__()
246
+ # intermediate_size ู…ุญุณูˆุจ ููŠ ุงู„ู€ config ู…ุฑุฉ ูˆุงุญุฏุฉ
247
+ hidden = config.intermediate_size
248
+
249
+ self.w1 = nn.Linear(config.hidden_size, hidden, bias=False)
250
+ self.w2 = nn.Linear(hidden, config.hidden_size, bias=False)
251
+ self.w3 = nn.Linear(config.hidden_size, hidden, bias=False)
252
+ self.w2._residual_projection = config.scale_residual_init
253
+ self.drop = nn.Dropout(config.dropout)
254
+
255
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
256
+ return self.drop(self.w2(F.silu(self.w1(x)) * self.w3(x)))
257
+
258
+
259
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
260
+ # Transformer Block
261
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
262
+
263
+ class NeoLMBlock(nn.Module):
264
+ def __init__(self, config: NeoLMConfig, layer_idx: int):
265
+ super().__init__()
266
+ self.layer_idx = layer_idx
267
+ self.ln1 = RMSNorm(config.hidden_size, config.rms_norm_eps)
268
+ self.attn = CausalSelfAttention(config)
269
+ self.ln2 = RMSNorm(config.hidden_size, config.rms_norm_eps)
270
+ self.mlp = SwiGLU(config)
271
+
272
+ def forward(
273
+ self,
274
+ x: torch.Tensor,
275
+ past_key_value: Cache | None = None,
276
+ use_cache: bool = False,
277
+ attention_mask: torch.Tensor | None = None,
278
+ ) -> tuple[torch.Tensor, Cache | None]:
279
+ attn_out, past_key_value = self.attn(
280
+ self.ln1(x),
281
+ past_key_value=past_key_value,
282
+ use_cache=use_cache,
283
+ layer_idx=self.layer_idx,
284
+ attention_mask=attention_mask,
285
+ )
286
+ x = x + attn_out
287
+ x = x + self.mlp(self.ln2(x))
288
+ return x, past_key_value
289
+
290
+
291
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
292
+ # Base PreTrainedModel
293
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
294
+
295
+ class NeoLMPreTrainedModel(PreTrainedModel):
296
+ config_class = NeoLMConfig
297
+ base_model_prefix = "model"
298
+ supports_gradient_checkpointing = True
299
+
300
+ def _init_weights(self, module: nn.Module):
301
+
302
+ if isinstance(module, nn.Linear):
303
+ std = 0.02
304
+
305
+ if (
306
+ self.config.scale_residual_init
307
+ and getattr(module, "_residual_projection", False)
308
+ ):
309
+ std /= math.sqrt(
310
+ 2 * self.config.num_hidden_layers
311
+ )
312
+
313
+ init.normal_(
314
+ module.weight,
315
+ mean=0.0,
316
+ std=std,
317
+ )
318
+
319
+ if module.bias is not None:
320
+ init.zeros_(module.bias)
321
+
322
+ elif isinstance(module, nn.Embedding):
323
+ init.normal_(
324
+ module.weight,
325
+ mean=0.0,
326
+ std=0.02,
327
+ )
328
+
329
+ elif isinstance(module, RMSNorm):
330
+ init.ones_(module.weight)
331
+
332
+
333
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
334
+ # NeoLMModel โ€” Backbone
335
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
336
+
337
+ class NeoLMModel(NeoLMPreTrainedModel):
338
+
339
+ def __init__(self, config: NeoLMConfig):
340
+ super().__init__(config)
341
+ self.token_emb = nn.Embedding(config.vocab_size, config.hidden_size)
342
+ self.blocks = nn.ModuleList([
343
+ NeoLMBlock(config, layer_idx=i)
344
+ for i in range(config.num_hidden_layers)
345
+ ])
346
+ self.ln_f = RMSNorm(config.hidden_size, config.rms_norm_eps)
347
+ self.post_init()
348
+
349
+ def get_input_embeddings(self):
350
+ return self.token_emb
351
+
352
+ def set_input_embeddings(self, value):
353
+ self.token_emb = value
354
+
355
+ def forward(
356
+ self,
357
+ input_ids: torch.Tensor,
358
+ past_key_values: Cache | None = None,
359
+ use_cache: bool = False,
360
+ attention_mask: torch.Tensor | None = None,
361
+ **kwargs,
362
+ ) -> tuple[torch.Tensor, Cache | None]:
363
+
364
+ B, T = input_ids.shape
365
+ x = self.token_emb(input_ids)
366
+
367
+ if use_cache and past_key_values is None:
368
+ past_key_values = DynamicCache()
369
+
370
+ for block in self.blocks:
371
+ x, past_key_values = block(
372
+ x,
373
+ past_key_value=past_key_values,
374
+ use_cache=use_cache,
375
+ attention_mask=attention_mask,
376
+ )
377
+
378
+ x = self.ln_f(x)
379
+ return x, past_key_values
380
+
381
+
382
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
383
+ # _TiedWeightsKeys โ€” ู…ุชูˆุงูู‚ ู…ุน ูƒู„ ุฅุตุฏุงุฑุงุช HF
384
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
385
+
386
+ class _TiedWeightsKeys(dict):
387
+ """
388
+ ุงู„ุฅุตุฏุงุฑุงุช ุงู„ุฌุฏูŠุฏุฉ ุชุนู…ู„ .keys() โ†’ dict โœ…
389
+ ุงู„ุฅุตุฏุงุฑุงุช ุงู„ู‚ุฏูŠู…ุฉ ุชุนู…ู„ iteration โ†’ dict iteration = keys โœ…
390
+ """
391
+ pass
392
+
393
+
394
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
395
+ # NeoLMForCausalLM โ€” ุงู„ู…ูˆุฏูŠู„ ุงู„ูƒุงู…ู„
396
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
397
+
398
+ class NeoLMForCausalLM(NeoLMPreTrainedModel, GenerationMixin):
399
+
400
+ _tied_weights_keys = _TiedWeightsKeys({"lm_head.weight": "model.token_emb.weight"})
401
+ _keys_to_ignore_on_load_missing = [r"lm_head\.weight"]
402
+
403
+ def __init__(self, config: NeoLMConfig):
404
+ super().__init__(config)
405
+ self.model = NeoLMModel(config)
406
+ self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
407
+ self.post_init()
408
+ self._recompute_rope_buffers()
409
+
410
+ # โ”€โ”€ RoPE recompute (ูŠู…ู†ุน garbage values ู…ู† ุงู„ู‚ุฏูŠู… checkpoints) โ”€โ”€
411
+
412
+ def _recompute_rope_buffers(self):
413
+ device = next(self.parameters()).device
414
+ for block in self.model.blocks:
415
+ attn = block.attn
416
+ cos, sin = precompute_rope_freqs(
417
+ attn.head_dim,
418
+ self.config.max_position_embeddings,
419
+ self.config.rope_base,
420
+ )
421
+ attn.rope_cos = cos.to(device)
422
+ attn.rope_sin = sin.to(device)
423
+
424
+ @classmethod
425
+ def from_pretrained(cls, pretrained_model_name_or_path, *args, **kwargs):
426
+ model = super().from_pretrained(pretrained_model_name_or_path, *args, **kwargs)
427
+ model._recompute_rope_buffers()
428
+ return model
429
+
430
+ # โ”€โ”€ Embeddings helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€๏ฟฝ๏ฟฝโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
431
+
432
+ def get_input_embeddings(self):
433
+ return self.model.token_emb
434
+
435
+ def set_input_embeddings(self, value):
436
+ self.model.token_emb = value
437
+
438
+ def get_output_embeddings(self):
439
+ return self.lm_head
440
+
441
+ def set_output_embeddings(self, value):
442
+ self.lm_head = value
443
+
444
+ def tie_weights(self, **kwargs):
445
+ if self.config.tie_word_embeddings:
446
+ self.lm_head.weight = self.model.token_emb.weight
447
+ super().tie_weights(**kwargs)
448
+
449
+ # โ”€โ”€ Forward โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
450
+
451
+ def forward(
452
+ self,
453
+ input_ids: torch.Tensor,
454
+ labels: torch.Tensor | None = None,
455
+ attention_mask: torch.Tensor | None = None, # ู„ู„ุชูˆุงูู‚ ู…ุน Trainer
456
+ past_key_values: Cache | None = None,
457
+ use_cache: bool | None = None,
458
+ **kwargs,
459
+ ) -> CausalLMOutputWithPast:
460
+
461
+ use_cache = use_cache if use_cache is not None else self.config.use_cache
462
+ # ู„ุง ู†ุณุชุฎุฏู… cache ูˆู‚ุช ุงู„ุชุฏุฑูŠุจ
463
+ if self.training:
464
+ use_cache = False
465
+
466
+ hidden, past_key_values = self.model(
467
+ input_ids,
468
+ past_key_values=past_key_values,
469
+ use_cache=use_cache,
470
+ attention_mask=attention_mask,
471
+ )
472
+ logits = self.lm_head(hidden)
473
+
474
+ loss = None
475
+ if labels is not None:
476
+ shift_logits = logits[:, :-1, :].contiguous()
477
+ shift_labels = labels[:, 1:].contiguous()
478
+ loss = F.cross_entropy(
479
+ shift_logits.view(-1, shift_logits.size(-1)),
480
+ shift_labels.view(-1),
481
+ ignore_index=-100,
482
+ )
483
+
484
+ return CausalLMOutputWithPast(
485
+ loss=loss,
486
+ logits=logits,
487
+ past_key_values=past_key_values if use_cache else None,
488
+ hidden_states=(hidden,) if kwargs.get("output_hidden_states", False) else None
489
+ )
490
+ # return CausalLMOutputWithPast(
491
+ # loss=loss,
492
+ # logits=logits,
493
+ # past_key_values=past_key_values if use_cache else None,
494
+ # )
495
+
496
+ # โ”€โ”€ Generate helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
497
+
498
+ def prepare_inputs_for_generation(
499
+ self,
500
+ input_ids: torch.Tensor,
501
+ past_key_values: Cache | None = None,
502
+ **kwargs,
503
+ ) -> dict:
504
+ past_len = past_key_values.get_seq_length() if past_key_values is not None else 0
505
+
506
+ if past_len > 0:
507
+ # ููŠ cache โ†’ ู†ุจุนุช ุขุฎุฑ token ุจุณ
508
+ input_ids = input_ids[:, -1:]
509
+ else:
510
+ # ุฃูˆู„ call โ†’ ู†ู‚ุชุต ู„ูˆ ุงู„ู€ prompt ุฃุทูˆู„ ู…ู† max_position_embeddings
511
+ max_len = self.config.max_position_embeddings
512
+ if input_ids.shape[1] > max_len:
513
+ input_ids = input_ids[:, -max_len:]
514
+
515
+ return {
516
+ "input_ids": input_ids,
517
+ "past_key_values": past_key_values,
518
+ "use_cache": kwargs.get("use_cache", True),
519
+ "attention_mask": kwargs.get("attention_mask", None),
520
+ }
521
+
522
+ class NeoLMForSequenceClassification(NeoLMPreTrainedModel):
523
+
524
+ def __init__(self, config: NeoLMConfig):
525
+
526
+ super().__init__(config)
527
+
528
+ self.num_labels = config.num_labels
529
+
530
+ # backbone
531
+ self.model = NeoLMModel(config)
532
+
533
+ # classifier head
534
+ self.score = nn.Linear(
535
+ config.hidden_size,
536
+ config.num_labels,
537
+ bias=True,
538
+ )
539
+
540
+ self.dropout = nn.Dropout(config.dropout)
541
+
542
+ self.post_init()
543
+ self._recompute_rope_buffers()
544
+
545
+ def _recompute_rope_buffers(self):
546
+ device = next(self.parameters()).device
547
+
548
+ for block in self.model.blocks:
549
+ attn = block.attn
550
+ cos, sin = precompute_rope_freqs(
551
+ attn.head_dim,
552
+ self.config.max_position_embeddings,
553
+ self.config.rope_base,
554
+ )
555
+ attn.rope_cos = cos.to(device)
556
+ attn.rope_sin = sin.to(device)
557
+
558
+ @classmethod
559
+ def from_pretrained(cls, pretrained_model_name_or_path, *args, **kwargs):
560
+ model = super().from_pretrained(
561
+ pretrained_model_name_or_path, *args, **kwargs
562
+ )
563
+ model._recompute_rope_buffers()
564
+ return model
565
+
566
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
567
+ # Embeddings Helpers
568
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
569
+
570
+ def get_input_embeddings(self):
571
+ return self.model.token_emb
572
+
573
+ def set_input_embeddings(self, value):
574
+ self.model.token_emb = value
575
+
576
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
577
+ # Forward
578
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
579
+
580
+ def forward(
581
+
582
+ self,
583
+
584
+ input_ids: torch.Tensor,
585
+
586
+ labels: torch.Tensor | None = None,
587
+
588
+ attention_mask: torch.Tensor | None = None,
589
+
590
+ **kwargs,
591
+
592
+ ) -> SequenceClassifierOutput:
593
+
594
+ # =====================================
595
+ # Backbone
596
+ # =====================================
597
+
598
+ hidden, _ = self.model(
599
+ input_ids=input_ids,
600
+ attention_mask=attention_mask,
601
+ use_cache=False,
602
+ )
603
+
604
+ # =====================================
605
+ # Pooling
606
+ # =====================================
607
+
608
+ if attention_mask is not None:
609
+ mask = attention_mask.unsqueeze(-1).float()
610
+ pooled = (hidden * mask).sum(dim=1) / mask.sum(dim=1).clamp_min(1.0)
611
+ else:
612
+ pooled = hidden.mean(dim=1)
613
+
614
+ pooled = self.dropout(pooled)
615
+
616
+ # =====================================
617
+ # Classification Head
618
+ # =====================================
619
+
620
+ logits = self.score(pooled)
621
+
622
+ # =====================================
623
+ # Loss
624
+ # =====================================
625
+
626
+ loss = None
627
+
628
+ if labels is not None:
629
+
630
+ loss = F.cross_entropy(
631
+ logits.view(-1, self.num_labels),
632
+ labels.view(-1),
633
+ )
634
+
635
+ return SequenceClassifierOutput(
636
+ loss=loss,
637
+ logits=logits,
638
+ hidden_states=(hidden,) if kwargs.get("output_hidden_states", False) else None,
639
+ )
tokenizer_config.json CHANGED
@@ -2,6 +2,8 @@
2
  "backend": "tokenizers",
3
  "bos_token": null,
4
  "eos_token": "<|endoftext|>",
 
 
5
  "model_max_length": 1000000000000000019884624838656,
6
  "pad_token": "<|pad|>",
7
  "tokenizer_class": "TokenizersBackend"
 
2
  "backend": "tokenizers",
3
  "bos_token": null,
4
  "eos_token": "<|endoftext|>",
5
+ "is_local": true,
6
+ "local_files_only": false,
7
  "model_max_length": 1000000000000000019884624838656,
8
  "pad_token": "<|pad|>",
9
  "tokenizer_class": "TokenizersBackend"