Banaxi-Tech commited on
Commit
04011ee
·
verified ·
1 Parent(s): 6e04794

Upload 14 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ banner.png filter=lfs diff=lfs merge=lfs -text
37
+ benchmarks.png filter=lfs diff=lfs merge=lfs -text
38
+ score_progression.png filter=lfs diff=lfs merge=lfs -text
LICENSE ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ BananaMind Community License 1.0
2
+
3
+ Copyright (c) 2026 Banaxi-Tech
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the “Software”), to deal
6
+ in the Software without restriction except as stated in Section 1 below,
7
+ including without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to permit
9
+ persons to whom the Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ Section 1 — Commercial License Requirement.
13
+ If the Software (or any derivative work thereof) is used in a commercial
14
+ product or service that has more than 200,000 monthly active users, or more
15
+ than 500,000 US dollars (or the equivalent in other currencies) in monthly
16
+ revenue, you shall contact banaxitech@gmail.com and purchase a commercial
17
+ license from Banaxi-Tech. The permissions granted above terminate with respect
18
+ to that product or service if a commercial license is not obtained within 30
19
+ days of first exceeding either threshold.
20
+
21
+ Section 2 — Attribution.
22
+ The above copyright notice and this permission notice shall be included in all
23
+ copies or substantial portions of the Software.
24
+
25
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
+ SOFTWARE.
README.md ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: other
3
+ license_name: bananamind-community-license-1.0
4
+ license_link: LICENSE
5
+ language:
6
+ - en
7
+ library_name: transformers
8
+ pipeline_tag: text-generation
9
+ base_model: BananaMind/BananaMind-2-Pro-Preview
10
+ datasets:
11
+ - HuggingFaceTB/smol-smoltalk
12
+ tags:
13
+ - causal-lm
14
+ - chat
15
+ - instruction-tuned
16
+ - full-finetune
17
+ - small-language-model
18
+ - bananamind
19
+ - bananamind2
20
+ - bananamind2-pro
21
+ - preview-checkpoint
22
+ - smoltalk
23
+ - digit-tokenizer
24
+ - pytorch
25
+ - safetensors
26
+ - custom-code
27
+ - trust-remote-code
28
+ - custom-architecture
29
+ ---
30
+
31
+ ![BananaMind 2 Pro](banner.png)
32
+
33
+ # BananaMind-2-Pro-Preview-Chat
34
+
35
+ BananaMind-2-Pro-Preview-Chat is the instruction-tuned version of [BananaMind-2-Pro-Preview](https://huggingface.co/BananaMind/BananaMind-2-Pro-Preview). It was fully fine-tuned for one epoch on [HuggingFaceTB/smol-smoltalk](https://huggingface.co/datasets/HuggingFaceTB/smol-smoltalk), with loss applied only to assistant content and the assistant-ending EOS token.
36
+
37
+ The model has **138,971,520 parameters**, a **3,072-token context window**, and a custom **32,768-token digit-aware byte-level BPE tokenizer**. It supports system prompts, multi-turn conversations, grouped-query attention, QK normalization, RoPE, tied embeddings, and KV-cached generation.
38
+
39
+ This chat model is based on the 96K Pro Preview checkpoint, which was pretrained on **51,904,512,000 tokens**. It is a preview-derived instruction model rather than a fine-tune of the completed 100B-token BananaMind 2 Pro run.
40
+
41
+ ![BananaMind 2 Pro Preview Chat benchmark results](benchmarks.png)
42
+
43
+ ## Model Details
44
+
45
+ | Field | Value |
46
+ |---|---:|
47
+ | Parameters | 138,971,520 |
48
+ | Base model | `BananaMind/BananaMind-2-Pro-Preview` |
49
+ | Architecture | BananaMind2Pro decoder-only Transformer |
50
+ | Layers | 24 |
51
+ | Hidden size | 640 |
52
+ | Intermediate size | 1,920 |
53
+ | Attention heads | 8 |
54
+ | KV heads | 4 |
55
+ | Head dimension | 80 |
56
+ | Attention style | Grouped-query attention with QK norm |
57
+ | MLP | SwiGLU |
58
+ | Position embeddings | RoPE, theta 100,000 |
59
+ | Normalization | RMSNorm, epsilon 1e-6 |
60
+ | Vocabulary size | 32,768 |
61
+ | Context length | 3,072 |
62
+ | Embeddings | Tied input/output embeddings |
63
+ | Generation cache | KV cache supported |
64
+ | Weight format | safetensors |
65
+ | Training type | Full-parameter supervised fine-tuning |
66
+
67
+ ## Benchmarks
68
+
69
+ ### BananaMind Instruct Bench 1.1
70
+
71
+ Self-reported results from the official [BananaMind Instruct Bench 1.1](https://huggingface.co/datasets/BananaMind/BananaMind-Instruct-Bench-1.1) script. The benchmark contains 300 deterministic, difficulty- and category-weighted instruction tasks. The BananaMind models used their native chat templates; Supra 1.5 used the benchmark's Alpaca-style fallback. Evaluation used greedy decoding, `repetition_penalty=1.1`, and seed 42.
72
+
73
+ | Model | Overall Elo | General | Multi-turn | System Prompts | Context Recall | Code |
74
+ |---|---:|---:|---:|---:|---:|---:|
75
+ | **BananaMind-2-Pro-Preview-Chat** | **888** | **720** | **911** | **793** | **1,194** | **1,337** |
76
+ | [BananaMind-2-Medium-Chat](https://huggingface.co/BananaMind/BananaMind-2-Medium-Chat) | 787 | 534 | 872 | 666 | 1,085 | 1,291 |
77
+ | [BananaMind-2-Mini-Chat](https://huggingface.co/BananaMind/BananaMind-2-Mini-Chat) | 654 | 389 | 812 | 743 | 924 | 667 |
78
+ | [Supra 1.5 50M Instruct](https://huggingface.co/SupraLabs/Supra-1.5-50M-Instruct-exp) | 647 | 520 | 804 | 590 | 860 | 780 |
79
+ | [BananaMind-2-Nano-Chat](https://huggingface.co/BananaMind/BananaMind-2-Nano-Chat) | 643 | 353 | 796 | 600 | 978 | 885 |
80
+
81
+ **Detailed final result**
82
+
83
+ | Scope | Examples | Passed | Weighted Score | Elo |
84
+ |---|---:|---:|---:|---:|
85
+ | **Overall** | **300** | **98** | **27.09%** | **888** |
86
+ | General | 120 | 33 | 21.84% | 720 |
87
+ | Multi-turn | 75 | 26 | 26.32% | 911 |
88
+ | System Prompts | 60 | 9 | 11.84% | 793 |
89
+ | Context Recall | 30 | 19 | 50.53% | 1,194 |
90
+ | Code | 15 | 11 | 65.26% | 1,337 |
91
+
92
+ | Difficulty | Examples | Passed | Weighted Score | Elo |
93
+ |---|---:|---:|---:|---:|
94
+ | Easy | 100 | 59 | 60.58% | 1,014 |
95
+ | Medium | 100 | 31 | 32.59% | 900 |
96
+ | Hard | 100 | 8 | 8.53% | 756 |
97
+
98
+ The complete final run used CUDA, bfloat16, the native chat template, and no sampling. Scores can vary with benchmark revision, Transformers version, dtype, hardware, and generation settings.
99
+
100
+ ### Fine-tuning Progression
101
+
102
+ ![BananaMind 2 Pro Preview Chat score progression](score_progression.png)
103
+
104
+ | Optimizer step | Packed tokens | Overall Elo | Passed | Weighted Score |
105
+ |---:|---:|---:|---:|---:|
106
+ | 500 | 49,152,000 | 811 | 77/300 | 19.98% |
107
+ | 1,000 | 98,304,000 | 835 | 85/300 | 22.04% |
108
+ | 1,500 | 147,456,000 | 858 | 91/300 | 24.19% |
109
+ | 2,000 | 196,608,000 | 866 | 94/300 | 24.99% |
110
+ | 2,500 | 245,760,000 | 874 | 94/300 | 25.69% |
111
+ | 3,000 | 294,912,000 | 875 | 95/300 | 25.84% |
112
+ | 3,500 | 344,064,000 | 855 | 88/300 | 23.88% |
113
+ | **4,014 (final)** | **394,522,611** | **888** | **98/300** | **27.09%** |
114
+
115
+ The final export is the strongest measured checkpoint overall. Step 3,000 had a slightly higher code-category Elo of 1,345, but the final model passed more code tasks and scored higher overall.
116
+
117
+ ## Instruction Tuning
118
+
119
+ | Field | Value |
120
+ |---|---:|
121
+ | Dataset | `HuggingFaceTB/smol-smoltalk` |
122
+ | Dataset split | `train` |
123
+ | Dataset rows | 460,341 |
124
+ | Epochs | 1 |
125
+ | Final optimizer step | 4,014 |
126
+ | Packed tokens processed | 394,522,611 |
127
+ | Supervised assistant tokens | 301,938,934 |
128
+ | Sequence length | 3,072 |
129
+ | Micro batch | 4 |
130
+ | Gradient accumulation | 8 |
131
+ | Effective batch | 32 sequences |
132
+ | Peak learning rate | 1e-4 |
133
+ | Warmup | 100 steps |
134
+ | LR schedule | Constant after warmup |
135
+ | Optimizer | AdamW |
136
+ | Betas | 0.9, 0.95 |
137
+ | Weight decay | 0.1 |
138
+ | Gradient clipping | 1.0 |
139
+ | Compilation | PyTorch compile enabled |
140
+ | Seed | 1337 |
141
+
142
+ System and user messages were retained as context but masked from the loss. Only assistant content and the assistant-ending EOS token contributed to the objective. All model parameters were trainable; no adapters or LoRA modules were used.
143
+
144
+ ## Chat Template
145
+
146
+ The tokenizer includes a Jinja template for `system`, `user`, and `assistant` messages:
147
+
148
+ ```text
149
+ <BOS><|system|>
150
+ {system message}
151
+ <|user|>
152
+ {user message}
153
+ <|assistant|>
154
+ {assistant response}<EOS>
155
+ ```
156
+
157
+ The role markers are plain text encoded by the existing tokenizer. Fine-tuning did not add or resize any tokens, and the input and output embeddings remain tied.
158
+
159
+ ## Usage
160
+
161
+ This repository contains custom Transformers architecture code and must be loaded with `trust_remote_code=True`.
162
+
163
+ ```bash
164
+ pip install -U torch transformers safetensors
165
+ ```
166
+
167
+ ```python
168
+ import torch
169
+ from transformers import AutoModelForCausalLM, AutoTokenizer
170
+
171
+ model_id = "BananaMind/BananaMind-2-Pro-Preview-Chat"
172
+ device = "cuda" if torch.cuda.is_available() else "cpu"
173
+ dtype = (
174
+ torch.bfloat16
175
+ if device == "cuda" and torch.cuda.is_bf16_supported()
176
+ else torch.float32
177
+ )
178
+
179
+ tokenizer = AutoTokenizer.from_pretrained(
180
+ model_id,
181
+ trust_remote_code=True,
182
+ )
183
+ model = AutoModelForCausalLM.from_pretrained(
184
+ model_id,
185
+ trust_remote_code=True,
186
+ dtype=dtype,
187
+ ).to(device).eval()
188
+
189
+ messages = [
190
+ {
191
+ "role": "system",
192
+ "content": "You are a concise and helpful assistant.",
193
+ },
194
+ {
195
+ "role": "user",
196
+ "content": "Write a Python function that squares a number.",
197
+ },
198
+ ]
199
+
200
+ inputs = tokenizer.apply_chat_template(
201
+ messages,
202
+ add_generation_prompt=True,
203
+ return_tensors="pt",
204
+ return_dict=True,
205
+ )
206
+ inputs = {name: tensor.to(device) for name, tensor in inputs.items()}
207
+
208
+ with torch.inference_mode():
209
+ output = model.generate(
210
+ **inputs,
211
+ max_new_tokens=256,
212
+ do_sample=False,
213
+ repetition_penalty=1.1,
214
+ eos_token_id=tokenizer.eos_token_id,
215
+ pad_token_id=tokenizer.pad_token_id,
216
+ use_cache=True,
217
+ )
218
+
219
+ new_tokens = output[0, inputs["input_ids"].shape[1]:]
220
+ print(tokenizer.decode(new_tokens, skip_special_tokens=True))
221
+ ```
222
+
223
+ For multi-turn chat, append the generated assistant response and the next user message to `messages`, then render the full conversation with the chat template again.
224
+
225
+ ## Suggested Generation Settings
226
+
227
+ For stable responses:
228
+
229
+ - `do_sample=False`
230
+ - `repetition_penalty=1.1`
231
+ - `max_new_tokens=128` to `256`
232
+ - `use_cache=True`
233
+
234
+ For more varied responses:
235
+
236
+ - `do_sample=True`
237
+ - `temperature=0.6` to `0.8`
238
+ - `top_p=0.9`
239
+ - `repetition_penalty=1.1`
240
+ - `max_new_tokens=128` to `256`
241
+
242
+ Keep a finite generation limit. The combined prompt and generated output must fit within the 3,072-token context window.
243
+
244
+ ## Repository Files
245
+
246
+ | File | Description |
247
+ |---|---|
248
+ | `config.json` | Transformers model configuration |
249
+ | `model.safetensors` | Fine-tuned model weights |
250
+ | `tokenizer.json` | Custom 32,768-token tokenizer |
251
+ | `tokenizer_config.json` | Tokenizer metadata and context length |
252
+ | `chat_template.jinja` | System/user/assistant chat template |
253
+ | `generation_config.json` | Generation configuration |
254
+ | `configuration_bananamind2pro.py` | Custom Transformers config class |
255
+ | `modeling_bananamind2pro.py` | Custom Transformers causal LM class |
256
+ | `sft_metadata.json` | Fine-tuning provenance and token counts |
257
+ | `LICENSE` | BananaMind Community License 1.0 |
258
+ | `banner.png` | Model-card banner |
259
+ | `benchmarks.png` | Instruct Bench model comparison |
260
+ | `score_progression.png` | Instruct Bench Elo progression across fine-tuning checkpoints |
261
+
262
+ ## Intended Use and Limitations
263
+
264
+ BananaMind-2-Pro-Preview-Chat is intended for small-model research, local chat experiments, educational demonstrations, code-generation experiments, instruction-tuning studies, and compact-model comparisons.
265
+
266
+ The model has not received dedicated safety alignment. It can hallucinate facts, fail arithmetic or logical tasks, produce insecure or invalid code, misunderstand instructions, and generate biased, repetitive, or otherwise undesirable text. Do not rely on it for medical, legal, financial, safety-critical, or other high-stakes decisions.
267
+
268
+ ## License
269
+
270
+ This repository is released under the [BananaMind Community License 1.0](LICENSE). Commercial products or services exceeding either threshold in Section 1 require a separate commercial license from Banaxi-Tech.
banner.png ADDED

Git LFS Details

  • SHA256: b5a3c30d804445a2687bd44e321fcc7513f6cd7e245598ae245772987413d759
  • Pointer size: 132 Bytes
  • Size of remote file: 1.35 MB
benchmarks.png ADDED

Git LFS Details

  • SHA256: 45b0580137f05b5b0c132205c833c8698263fc76fe7ddaf80dc64db52b159238
  • Pointer size: 131 Bytes
  • Size of remote file: 955 kB
chat_template.jinja ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {{ bos_token }}{% for message in messages %}{% if message['role'] == 'assistant' %}<|assistant|>
2
+ {{ message['content'] }}{{ eos_token }}
3
+ {% elif message['role'] == 'system' %}<|system|>
4
+ {{ message['content'] }}
5
+ {% elif message['role'] == 'user' %}<|user|>
6
+ {{ message['content'] }}
7
+ {% else %}<|{{ message['role'] }}|>
8
+ {{ message['content'] }}
9
+ {% endif %}{% endfor %}{% if add_generation_prompt %}<|assistant|>
10
+ {% endif %}
config.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "BananaMind2ProForCausalLM"
4
+ ],
5
+ "auto_map": {
6
+ "AutoConfig": "configuration_bananamind2pro.BananaMind2ProConfig",
7
+ "AutoModelForCausalLM": "modeling_bananamind2pro.BananaMind2ProForCausalLM"
8
+ },
9
+ "bos_token_id": 1,
10
+ "dtype": "float32",
11
+ "eos_token_id": 2,
12
+ "head_dim": 80,
13
+ "hidden_size": 640,
14
+ "intermediate_size": 1920,
15
+ "max_position_embeddings": 3072,
16
+ "model_type": "bananamind2_pro",
17
+ "num_attention_heads": 8,
18
+ "num_hidden_layers": 24,
19
+ "num_key_value_heads": 4,
20
+ "pad_token_id": 0,
21
+ "rms_norm_eps": 1e-06,
22
+ "rope_theta": 100000.0,
23
+ "tie_word_embeddings": true,
24
+ "transformers_version": "5.7.0",
25
+ "unk_token_id": 3,
26
+ "use_cache": true,
27
+ "vocab_size": 32768,
28
+ "z_loss_coeff": 0.0,
29
+ "_name_or_path": "BananaMind/BananaMind-2-Pro-Preview-Chat"
30
+ }
configuration_bananamind2pro.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """BananaMind 2 Pro configuration."""
2
+ from transformers import PretrainedConfig
3
+
4
+
5
+ class BananaMind2ProConfig(PretrainedConfig):
6
+ model_type = "bananamind2_pro"
7
+
8
+ def __init__(
9
+ self,
10
+ vocab_size=32768,
11
+ hidden_size=640,
12
+ num_hidden_layers=24,
13
+ num_attention_heads=8,
14
+ num_key_value_heads=4,
15
+ head_dim=80,
16
+ intermediate_size=1920,
17
+ max_position_embeddings=3072,
18
+ rope_theta=100000.0,
19
+ rms_norm_eps=1e-6,
20
+ tie_word_embeddings=True,
21
+ use_cache=True,
22
+ z_loss_coeff=0.0,
23
+ bos_token_id=1,
24
+ eos_token_id=2,
25
+ pad_token_id=0,
26
+ unk_token_id=3,
27
+ **kwargs,
28
+ ):
29
+ self.vocab_size = vocab_size
30
+ self.hidden_size = hidden_size
31
+ self.num_hidden_layers = num_hidden_layers
32
+ self.num_attention_heads = num_attention_heads
33
+ self.num_key_value_heads = num_key_value_heads
34
+ self.head_dim = head_dim
35
+ self.intermediate_size = intermediate_size
36
+ self.max_position_embeddings = max_position_embeddings
37
+ self.rope_theta = rope_theta
38
+ self.rms_norm_eps = rms_norm_eps
39
+ self.use_cache = use_cache
40
+ self.z_loss_coeff = z_loss_coeff
41
+ super().__init__(
42
+ tie_word_embeddings=tie_word_embeddings,
43
+ bos_token_id=bos_token_id,
44
+ eos_token_id=eos_token_id,
45
+ pad_token_id=pad_token_id,
46
+ unk_token_id=unk_token_id,
47
+ **kwargs,
48
+ )
generation_config.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token_id": 1,
3
+ "eos_token_id": 2,
4
+ "pad_token_id": 0,
5
+ "transformers_version": "5.7.0",
6
+ "use_cache": true
7
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ee67bcfe1d111a9d35c366ac859fba22de5624fdbfd66b85d269bd7e28d6bd46
3
+ size 555914016
modeling_bananamind2pro.py ADDED
@@ -0,0 +1,307 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """BananaMind 2 Pro implementation for Hugging Face Transformers."""
2
+ import math
3
+ from typing import Optional
4
+
5
+ import torch
6
+ import torch.nn as nn
7
+ import torch.nn.functional as F
8
+ from transformers import PreTrainedModel
9
+ from transformers.cache_utils import Cache, DynamicCache
10
+ from transformers.generation.utils import GenerationMixin
11
+ from transformers.modeling_outputs import CausalLMOutputWithPast
12
+
13
+ from .configuration_bananamind2pro import BananaMind2ProConfig
14
+
15
+
16
+ class RMSNorm(nn.Module):
17
+ def __init__(self, dim, eps=1e-6):
18
+ super().__init__()
19
+ self.eps = eps
20
+ self.weight = nn.Parameter(torch.ones(dim))
21
+
22
+ def forward(self, x):
23
+ x_float = x.float()
24
+ rms = torch.rsqrt(x_float.pow(2).mean(-1, keepdim=True) + self.eps)
25
+ return (x_float * rms * self.weight.float()).type_as(x)
26
+
27
+
28
+ def build_rope_inv_freq(head_dim, theta=100000.0):
29
+ return 1.0 / (theta ** (torch.arange(0, head_dim, 2, dtype=torch.float32) / head_dim))
30
+
31
+
32
+ def precompute_freqs_cis(head_dim, seq_len, theta=100000.0):
33
+ freqs = build_rope_inv_freq(head_dim, theta)
34
+ positions = torch.arange(seq_len, dtype=torch.float32)
35
+ freqs = torch.outer(positions, freqs)
36
+ return torch.polar(torch.ones_like(freqs), freqs)
37
+
38
+
39
+ def apply_rotary_emb(q, k, freqs_cis):
40
+ q_complex = torch.view_as_complex(q.float().reshape(*q.shape[:-1], -1, 2))
41
+ k_complex = torch.view_as_complex(k.float().reshape(*k.shape[:-1], -1, 2))
42
+ freqs_cis = freqs_cis.unsqueeze(0).unsqueeze(0)
43
+ q_out = torch.view_as_real(q_complex * freqs_cis).flatten(-2)
44
+ k_out = torch.view_as_real(k_complex * freqs_cis).flatten(-2)
45
+ return q_out.type_as(q), k_out.type_as(k)
46
+
47
+
48
+ class BananaMind2ProAttention(nn.Module):
49
+ def __init__(self, config, layer_idx):
50
+ super().__init__()
51
+ self.layer_idx = layer_idx
52
+ self.n_head = config.num_attention_heads
53
+ self.n_kv_heads = config.num_key_value_heads
54
+ self.head_dim = config.head_dim
55
+ self.n_rep = self.n_head // self.n_kv_heads
56
+
57
+ self.q_proj = nn.Linear(config.hidden_size, self.n_head * self.head_dim, bias=False)
58
+ self.k_proj = nn.Linear(config.hidden_size, self.n_kv_heads * self.head_dim, bias=False)
59
+ self.v_proj = nn.Linear(config.hidden_size, self.n_kv_heads * self.head_dim, bias=False)
60
+ self.o_proj = nn.Linear(self.n_head * self.head_dim, config.hidden_size, bias=False)
61
+ self.q_norm = RMSNorm(self.head_dim, eps=config.rms_norm_eps)
62
+ self.k_norm = RMSNorm(self.head_dim, eps=config.rms_norm_eps)
63
+
64
+ def forward(
65
+ self,
66
+ x,
67
+ freqs_cis,
68
+ attention_mask=None,
69
+ past_key_values=None,
70
+ use_cache=False,
71
+ ):
72
+ batch_size, seq_len, _ = x.shape
73
+ q = self.q_proj(x).view(
74
+ batch_size,
75
+ seq_len,
76
+ self.n_head,
77
+ self.head_dim,
78
+ ).transpose(1, 2)
79
+ k = self.k_proj(x).view(
80
+ batch_size,
81
+ seq_len,
82
+ self.n_kv_heads,
83
+ self.head_dim,
84
+ ).transpose(1, 2)
85
+ v = self.v_proj(x).view(
86
+ batch_size,
87
+ seq_len,
88
+ self.n_kv_heads,
89
+ self.head_dim,
90
+ ).transpose(1, 2)
91
+
92
+ q = self.q_norm(q)
93
+ k = self.k_norm(k)
94
+ q, k = apply_rotary_emb(q, k, freqs_cis)
95
+
96
+ past_length = 0
97
+ if use_cache and past_key_values is not None:
98
+ past_length = past_key_values.get_seq_length(self.layer_idx)
99
+ k, v = past_key_values.update(k, v, self.layer_idx)
100
+
101
+ kv_len = k.size(-2)
102
+ k = k.unsqueeze(2).expand(
103
+ batch_size,
104
+ self.n_kv_heads,
105
+ self.n_rep,
106
+ kv_len,
107
+ self.head_dim,
108
+ ).reshape(batch_size, self.n_head, kv_len, self.head_dim)
109
+ v = v.unsqueeze(2).expand(
110
+ batch_size,
111
+ self.n_kv_heads,
112
+ self.n_rep,
113
+ kv_len,
114
+ self.head_dim,
115
+ ).reshape(batch_size, self.n_head, kv_len, self.head_dim)
116
+
117
+ attn_mask = None
118
+ is_causal = past_length == 0 and attention_mask is None
119
+ if not is_causal:
120
+ query_positions = past_length + torch.arange(seq_len, device=x.device)
121
+ key_positions = torch.arange(kv_len, device=x.device)
122
+ causal = key_positions.unsqueeze(0) <= query_positions.unsqueeze(1)
123
+ attn_mask = causal[None, None, :, :]
124
+ if attention_mask is not None:
125
+ key_padding = attention_mask.to(torch.bool)
126
+ if key_padding.size(-1) < kv_len:
127
+ cached_padding = torch.ones(
128
+ key_padding.size(0),
129
+ kv_len - key_padding.size(-1),
130
+ dtype=torch.bool,
131
+ device=key_padding.device,
132
+ )
133
+ key_padding = torch.cat((cached_padding, key_padding), dim=-1)
134
+ else:
135
+ key_padding = key_padding[:, -kv_len:]
136
+ attn_mask = attn_mask & key_padding[:, None, None, :]
137
+ is_causal = False
138
+
139
+ y = F.scaled_dot_product_attention(
140
+ q,
141
+ k,
142
+ v,
143
+ attn_mask=attn_mask,
144
+ is_causal=is_causal,
145
+ )
146
+ y = y.transpose(1, 2).contiguous().view(
147
+ batch_size,
148
+ seq_len,
149
+ self.n_head * self.head_dim,
150
+ )
151
+ return self.o_proj(y)
152
+
153
+
154
+ class BananaMind2ProSwiGLUMLP(nn.Module):
155
+ def __init__(self, config):
156
+ super().__init__()
157
+ self.w_gate = nn.Linear(config.hidden_size, config.intermediate_size, bias=False)
158
+ self.w_up = nn.Linear(config.hidden_size, config.intermediate_size, bias=False)
159
+ self.w_down = nn.Linear(config.intermediate_size, config.hidden_size, bias=False)
160
+
161
+ def forward(self, x):
162
+ return self.w_down(F.silu(self.w_gate(x)) * self.w_up(x))
163
+
164
+
165
+ class BananaMind2ProBlock(nn.Module):
166
+ def __init__(self, config, layer_idx):
167
+ super().__init__()
168
+ self.ln_1 = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
169
+ self.attn = BananaMind2ProAttention(config, layer_idx)
170
+ self.ln_2 = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
171
+ self.mlp = BananaMind2ProSwiGLUMLP(config)
172
+
173
+ def forward(
174
+ self,
175
+ x,
176
+ freqs_cis,
177
+ attention_mask=None,
178
+ past_key_values=None,
179
+ use_cache=False,
180
+ ):
181
+ x = x + self.attn(
182
+ self.ln_1(x),
183
+ freqs_cis,
184
+ attention_mask=attention_mask,
185
+ past_key_values=past_key_values,
186
+ use_cache=use_cache,
187
+ )
188
+ return x + self.mlp(self.ln_2(x))
189
+
190
+
191
+ class BananaMind2ProPreTrainedModel(PreTrainedModel):
192
+ config_class = BananaMind2ProConfig
193
+ base_model_prefix = "transformer"
194
+ supports_gradient_checkpointing = False
195
+
196
+ def _init_weights(self, module):
197
+ std = 0.02
198
+ if hasattr(module, "NANOGPT_SCALE_INIT"):
199
+ std *= 2 * self.config.num_hidden_layers ** -0.5
200
+ if isinstance(module, nn.Linear):
201
+ nn.init.normal_(module.weight, mean=0.0, std=std)
202
+ elif isinstance(module, nn.Embedding):
203
+ nn.init.normal_(module.weight, mean=0.0, std=0.02)
204
+
205
+
206
+ class BananaMind2ProForCausalLM(BananaMind2ProPreTrainedModel, GenerationMixin):
207
+ _tied_weights_keys = {"lm_head.weight": "transformer.wte.weight"}
208
+
209
+ def __init__(self, config):
210
+ super().__init__(config)
211
+ self.config = config
212
+ self.transformer = nn.ModuleDict(
213
+ {
214
+ "wte": nn.Embedding(config.vocab_size, config.hidden_size),
215
+ "h": nn.ModuleList(
216
+ [
217
+ BananaMind2ProBlock(config, layer_idx)
218
+ for layer_idx in range(config.num_hidden_layers)
219
+ ]
220
+ ),
221
+ "ln_f": RMSNorm(config.hidden_size, eps=config.rms_norm_eps),
222
+ }
223
+ )
224
+ self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
225
+ if config.tie_word_embeddings:
226
+ self.lm_head.weight = self.transformer["wte"].weight
227
+ self._embd_scale = math.sqrt(config.hidden_size)
228
+ self._freqs_cis_cache = None
229
+ self.post_init()
230
+
231
+ def get_input_embeddings(self):
232
+ return self.transformer["wte"]
233
+
234
+ def set_input_embeddings(self, value):
235
+ self.transformer["wte"] = value
236
+
237
+ def get_output_embeddings(self):
238
+ return self.lm_head
239
+
240
+ def set_output_embeddings(self, new_embeddings):
241
+ self.lm_head = new_embeddings
242
+
243
+ def _get_freqs_cis(self, seq_len, device):
244
+ cache = self._freqs_cis_cache
245
+ if cache is None or cache.device != device or cache.size(0) < seq_len:
246
+ cache = precompute_freqs_cis(
247
+ self.config.head_dim,
248
+ seq_len,
249
+ self.config.rope_theta,
250
+ ).to(device)
251
+ self._freqs_cis_cache = cache
252
+ return cache[:seq_len]
253
+
254
+ def forward(
255
+ self,
256
+ input_ids,
257
+ attention_mask=None,
258
+ labels=None,
259
+ past_key_values: Optional[Cache] = None,
260
+ use_cache=None,
261
+ **kwargs,
262
+ ):
263
+ _, seq_len = input_ids.shape
264
+ if use_cache is None:
265
+ use_cache = self.config.use_cache and labels is None
266
+ if use_cache and past_key_values is None:
267
+ past_key_values = DynamicCache(config=self.config)
268
+
269
+ past_length = past_key_values.get_seq_length() if use_cache else 0
270
+ total_length = past_length + seq_len
271
+ if total_length > self.config.max_position_embeddings:
272
+ raise ValueError(
273
+ f"Sequence length {total_length} exceeds the configured maximum "
274
+ f"of {self.config.max_position_embeddings}"
275
+ )
276
+
277
+ x = self.transformer["wte"](input_ids) * self._embd_scale
278
+ freqs_cis = self._get_freqs_cis(total_length, input_ids.device)[past_length:]
279
+
280
+ for block in self.transformer["h"]:
281
+ x = block(
282
+ x,
283
+ freqs_cis,
284
+ attention_mask=attention_mask,
285
+ past_key_values=past_key_values,
286
+ use_cache=use_cache,
287
+ )
288
+
289
+ x = self.transformer["ln_f"](x)
290
+ logits = self.lm_head(x)
291
+
292
+ loss = None
293
+ if labels is not None:
294
+ shift_logits = logits[..., :-1, :].contiguous()
295
+ shift_labels = labels[..., 1:].contiguous()
296
+ loss = F.cross_entropy(
297
+ shift_logits.float().reshape(-1, shift_logits.size(-1)),
298
+ shift_labels.reshape(-1),
299
+ )
300
+ if self.config.z_loss_coeff:
301
+ loss = loss + self.config.z_loss_coeff * logits.float().pow(2).mean()
302
+
303
+ return CausalLMOutputWithPast(
304
+ loss=loss,
305
+ logits=logits,
306
+ past_key_values=past_key_values if use_cache else None,
307
+ )
score_progression.png ADDED

Git LFS Details

  • SHA256: 424fff2cec6577ae740116f282ab86335db0a28224eeddce65e183df5205c75b
  • Pointer size: 131 Bytes
  • Size of remote file: 116 kB
sft_metadata.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "base_model": "BananaMind-2-Pro-Preview",
3
+ "dataset": "HuggingFaceTB/smol-smoltalk",
4
+ "dataset_config": "default",
5
+ "dataset_split": "train",
6
+ "training_type": "full_parameter_supervised_finetuning",
7
+ "loss_mask": "assistant_content_and_eos_only",
8
+ "global_step": 4014,
9
+ "tokens_seen": 394522611,
10
+ "supervised_tokens_seen": 301938934,
11
+ "repo_id": "BananaMind/BananaMind-2-Pro-Preview-Chat"
12
+ }
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "backend": "tokenizers",
3
+ "bos_token": "<|bos|>",
4
+ "eos_token": "<|eos|>",
5
+ "is_local": true,
6
+ "local_files_only": true,
7
+ "model_max_length": 3072,
8
+ "pad_token": "<|pad|>",
9
+ "tokenizer_class": "TokenizersBackend",
10
+ "unk_token": "<|unk|>"
11
+ }