Text Generation
Transformers
Safetensors
PyTorch
English
bananamind2_pro
causal-lm
chat
instruction-tuned
full-finetune
small-language-model
bananamind
bananamind2
bananamind2-pro
preview-checkpoint
smoltalk
digit-tokenizer
custom-code
trust-remote-code
custom-architecture
conversational
custom_code
Instructions to use BananaMind/BananaMind-2-Pro-Preview-Chat with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use BananaMind/BananaMind-2-Pro-Preview-Chat with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="BananaMind/BananaMind-2-Pro-Preview-Chat", trust_remote_code=True) messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("BananaMind/BananaMind-2-Pro-Preview-Chat", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use BananaMind/BananaMind-2-Pro-Preview-Chat with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "BananaMind/BananaMind-2-Pro-Preview-Chat" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "BananaMind/BananaMind-2-Pro-Preview-Chat", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/BananaMind/BananaMind-2-Pro-Preview-Chat
- SGLang
How to use BananaMind/BananaMind-2-Pro-Preview-Chat with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "BananaMind/BananaMind-2-Pro-Preview-Chat" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "BananaMind/BananaMind-2-Pro-Preview-Chat", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "BananaMind/BananaMind-2-Pro-Preview-Chat" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "BananaMind/BananaMind-2-Pro-Preview-Chat", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use BananaMind/BananaMind-2-Pro-Preview-Chat with Docker Model Runner:
docker model run hf.co/BananaMind/BananaMind-2-Pro-Preview-Chat
Upload 14 files
Browse files- .gitattributes +3 -0
- LICENSE +31 -0
- README.md +270 -0
- banner.png +3 -0
- benchmarks.png +3 -0
- chat_template.jinja +10 -0
- config.json +30 -0
- configuration_bananamind2pro.py +48 -0
- generation_config.json +7 -0
- model.safetensors +3 -0
- modeling_bananamind2pro.py +307 -0
- score_progression.png +3 -0
- sft_metadata.json +12 -0
- tokenizer.json +0 -0
- tokenizer_config.json +11 -0
.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 |
+

|
| 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 |
+

|
| 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 |
+

|
| 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
|
benchmarks.png
ADDED
|
Git LFS Details
|
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
|
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 |
+
}
|