Text Generation
Transformers
Safetensors
English
dynamicmind_moe
dynamicmind
mixture-of-experts
sparse-moe
instruct
sft
conversational
custom-code
trust-remote-code
custom_code
Instructions to use DedeProGames/DynamicMind-MoE-Instruct with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use DedeProGames/DynamicMind-MoE-Instruct with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="DedeProGames/DynamicMind-MoE-Instruct", 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("DedeProGames/DynamicMind-MoE-Instruct", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use DedeProGames/DynamicMind-MoE-Instruct with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "DedeProGames/DynamicMind-MoE-Instruct" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "DedeProGames/DynamicMind-MoE-Instruct", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/DedeProGames/DynamicMind-MoE-Instruct
- SGLang
How to use DedeProGames/DynamicMind-MoE-Instruct 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 "DedeProGames/DynamicMind-MoE-Instruct" \ --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": "DedeProGames/DynamicMind-MoE-Instruct", "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 "DedeProGames/DynamicMind-MoE-Instruct" \ --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": "DedeProGames/DynamicMind-MoE-Instruct", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use DedeProGames/DynamicMind-MoE-Instruct with Docker Model Runner:
docker model run hf.co/DedeProGames/DynamicMind-MoE-Instruct
Add DynamicMind-MoE-Instruct: 2-epoch SFT on smol-smoltalk, custom MoE code, EOS-weighted loss
Browse files- README.md +115 -0
- config.json +36 -0
- configuration_dynamicmind_moe.py +74 -0
- eval/protocol/gpqa_generations.jsonl +0 -0
- eval/protocol/ifeval_generations.jsonl +0 -0
- eval/protocol/livebench_generations.jsonl +0 -0
- eval/protocol/summary.json +25 -0
- eval/recommended_sampling/ifeval_generations.jsonl +0 -0
- eval/recommended_sampling/summary.json +9 -0
- generation_config.json +10 -0
- model.safetensors +3 -0
- modeling_dynamicmind_moe.py +339 -0
- tokenizer.json +0 -0
- tokenizer_config.json +9 -0
README.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
language:
|
| 4 |
+
- en
|
| 5 |
+
library_name: transformers
|
| 6 |
+
pipeline_tag: text-generation
|
| 7 |
+
base_model: DedeProGames/DynamicMind-MoE
|
| 8 |
+
datasets:
|
| 9 |
+
- HuggingFaceTB/smol-smoltalk
|
| 10 |
+
tags:
|
| 11 |
+
- dynamicmind
|
| 12 |
+
- mixture-of-experts
|
| 13 |
+
- sparse-moe
|
| 14 |
+
- instruct
|
| 15 |
+
- sft
|
| 16 |
+
- conversational
|
| 17 |
+
- custom-code
|
| 18 |
+
- trust-remote-code
|
| 19 |
+
---
|
| 20 |
+
|
| 21 |
+
# DynamicMind-MoE-Instruct
|
| 22 |
+
|
| 23 |
+
An instruction-tuned version of [DynamicMind-MoE](https://huggingface.co/DedeProGames/DynamicMind-MoE), a sparse mixture-of-experts model with 30.2M total parameters and 8.9M active per token. It was fully fine-tuned for two epochs on [smol-smoltalk](https://huggingface.co/datasets/HuggingFaceTB/smol-smoltalk) with the loss computed only on assistant tokens (end-of-turn tokens weighted 5×, so the model learns to stop).
|
| 24 |
+
|
| 25 |
+
At this size it is a small research model. It follows the chat format and answers simple requests, but factual knowledge, reasoning and arithmetic are weak. See the limitations below.
|
| 26 |
+
|
| 27 |
+
## Quickstart
|
| 28 |
+
|
| 29 |
+
This model uses custom architecture code, so load it with `trust_remote_code=True`. Use the recommended sampling settings (stored in `generation_config.json`). With near-greedy decoding this model can fall into repetition loops.
|
| 30 |
+
|
| 31 |
+
```python
|
| 32 |
+
import torch
|
| 33 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 34 |
+
|
| 35 |
+
repo = "DedeProGames/DynamicMind-MoE-Instruct"
|
| 36 |
+
tokenizer = AutoTokenizer.from_pretrained(repo)
|
| 37 |
+
model = AutoModelForCausalLM.from_pretrained(repo, trust_remote_code=True, torch_dtype=torch.float32).eval()
|
| 38 |
+
|
| 39 |
+
messages = [{"role": "user", "content": "What is photosynthesis?"}]
|
| 40 |
+
input_ids = tokenizer.apply_chat_template(messages, add_generation_prompt=True, return_tensors="pt", return_dict=False)
|
| 41 |
+
out = model.generate(input_ids, max_new_tokens=256) # temperature 0.7, top-p 0.9, repetition penalty 1.1 from generation_config.json
|
| 42 |
+
print(tokenizer.decode(out[0, input_ids.shape[1]:], skip_special_tokens=True))
|
| 43 |
+
```
|
| 44 |
+
|
| 45 |
+
Keep prompt + answer within the 1,024-token context.
|
| 46 |
+
|
| 47 |
+
## Chat format
|
| 48 |
+
|
| 49 |
+
This vocabulary has no chat tokens, so the format is plain text. `apply_chat_template` renders it:
|
| 50 |
+
|
| 51 |
+
```text
|
| 52 |
+
<|endoftext|>### User:
|
| 53 |
+
{user message}
|
| 54 |
+
### Assistant:
|
| 55 |
+
{assistant reply}
|
| 56 |
+
<|endoftext|>### User:
|
| 57 |
+
...
|
| 58 |
+
```
|
| 59 |
+
|
| 60 |
+
`<|endoftext|>` (id 0) is the BOS, the end-of-turn token and the EOS.
|
| 61 |
+
|
| 62 |
+
## Architecture
|
| 63 |
+
|
| 64 |
+
Same as DynamicMind-MoE: 9 layers, hidden size 256, 8 attention heads with 2 KV heads, one always-on shared expert plus 14 routed experts per layer with the top 2 selected per token, auxiliary-loss-free balancing, tied embeddings, 8,192-token digit-aware vocabulary, 1,024-token context. 30,150,912 total parameters, 8,917,248 active per token. Weights in BF16 (`model.safetensors`, 60 MB).
|
| 65 |
+
|
| 66 |
+
## Training
|
| 67 |
+
|
| 68 |
+
| | |
|
| 69 |
+
|---|---|
|
| 70 |
+
| Base | DedeProGames/DynamicMind-MoE |
|
| 71 |
+
| Data | smol-smoltalk train split, conversations of up to 1,024 tokens (221,811 with this tokenizer; 68.9M supervised tokens) |
|
| 72 |
+
| Epochs | 2 (13,864 steps, batch 32 = 16 × 2 gradient accumulation) |
|
| 73 |
+
| Optimizer | AdamW (β = 0.9, 0.95), weight decay 0.1 on 2D matrices, grad clip 1.0 |
|
| 74 |
+
| Schedule | lr 1e-4 (the base model's pretraining peak), 300 warmup steps, cosine to 1e-5 |
|
| 75 |
+
| Loss | assistant tokens; `<|endoftext|>` weighted 5×; router balance loss (coefficient 0.01) added |
|
| 76 |
+
| Precision | bf16 autocast, fp32 master weights |
|
| 77 |
+
| Hardware | 1× NVIDIA RTX 3060 12 GB, 239 minutes |
|
| 78 |
+
|
| 79 |
+
Held-out loss on assistant tokens (smol-smoltalk test split): 1.422 at the end of training.
|
| 80 |
+
|
| 81 |
+
## Evaluation
|
| 82 |
+
|
| 83 |
+
Benchmarks follow the protocol of the [Kiyo-230M-Instruct](https://huggingface.co/DedeProGames/Kiyo-230M-Instruct) card: FP16, the model's own chat template, no system prompt, new-token limits IFEval 1,024, GPQA 384, LiveBench 512. The context is 1,024 tokens, so the generation limit is capped at 1,024 minus the prompt length. The main setting uses temperature 0.1, top-k 50 and repetition penalty 1.05, as on the card (GPQA is sampled at T = 0.6, as on the card). The second setting is the recommended one shipped in `generation_config.json`.
|
| 84 |
+
|
| 85 |
+
| Benchmark | Metric | DynamicMind-MoE-Instruct, protocol | DynamicMind-MoE-Instruct, recommended sampling |
|
| 86 |
+
|---|---|---:|---:|
|
| 87 |
+
| GPQA Diamond | pass@1 (198 × 5 samples, T = 0.6) | 12.32 | not run |
|
| 88 |
+
| IFEval | prompt-level strict | 18.85 | 14.97 |
|
| 89 |
+
| LiveBench instruction following | strict, 200 questions | 18.66 | not run |
|
| 90 |
+
| CaseReportBench | token F1 | not run (not on the Hub) | not run |
|
| 91 |
+
| EOS rate (IFEval) | share of answers that stop | 0.88 | 0.99 |
|
| 92 |
+
|
| 93 |
+
For reference, the Kiyo card reports (not re-run here): Kiyo-230M-Instruct GPQA 21.11, IFEval 17.38, LiveBench 18.77; SmolLM2-135M-Instruct GPQA 16.57, IFEval 20.89, LiveBench 24.23; BananaMind-2-Pro GPQA 15.05, IFEval 20.15, LiveBench 19.75; Supra2-100M-Instruct GPQA 5.56, IFEval 9.06, LiveBench 11.28.
|
| 94 |
+
|
| 95 |
+
Notes:
|
| 96 |
+
|
| 97 |
+
- With the protocol setting, about 12% of IFEval answers never stop and loop. Under the recommended sampling this drops to about 1%, at a cost of about 4 IFEval points.
|
| 98 |
+
- GPQA: only 46% of answers contain an identifiable option letter, and 40 prompts were truncated to fit the 1,024-token context. Among answered questions, accuracy is 26.6%, close to the 25% chance level.
|
| 99 |
+
- The GPQA prompt was written for this run, not taken from the Kiyo card, so the number is not strictly comparable.
|
| 100 |
+
- Single run, single seed. Differences of a point or two are within noise.
|
| 101 |
+
|
| 102 |
+
Per-sample outputs and summaries are in [`eval/`](eval/).
|
| 103 |
+
|
| 104 |
+
## Limitations
|
| 105 |
+
|
| 106 |
+
- It is small (8.9M active parameters per token). Expect factual errors, invented details, arithmetic mistakes, weak multi-step reasoning, and repetitive text in long answers.
|
| 107 |
+
- Under near-greedy decoding it can loop. Keep the recommended sampling settings.
|
| 108 |
+
- Context is 1,024 tokens.
|
| 109 |
+
- English only.
|
| 110 |
+
- Requires `trust_remote_code=True`, since the architecture is custom.
|
| 111 |
+
- No safety tuning and no safety evaluation. Do not use it for medical, legal, financial or other high-stakes decisions.
|
| 112 |
+
|
| 113 |
+
## License
|
| 114 |
+
|
| 115 |
+
Apache-2.0, as for the base model. The SFT data (smol-smoltalk) is also Apache-2.0.
|
config.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"DynamicMindMoEForCausalLM"
|
| 4 |
+
],
|
| 5 |
+
"attention_dropout": 0.0,
|
| 6 |
+
"auto_map": {
|
| 7 |
+
"AutoConfig": "configuration_dynamicmind_moe.DynamicMindMoEConfig",
|
| 8 |
+
"AutoModelForCausalLM": "modeling_dynamicmind_moe.DynamicMindMoEForCausalLM"
|
| 9 |
+
},
|
| 10 |
+
"bos_token_id": 0,
|
| 11 |
+
"dtype": "bfloat16",
|
| 12 |
+
"eos_token_id": 0,
|
| 13 |
+
"first_k_dense_layers": 0,
|
| 14 |
+
"hidden_size": 256,
|
| 15 |
+
"intermediate_size": 768,
|
| 16 |
+
"max_position_embeddings": 1024,
|
| 17 |
+
"model_type": "dynamicmind_moe",
|
| 18 |
+
"moe_intermediate_size": 256,
|
| 19 |
+
"norm_topk_prob": true,
|
| 20 |
+
"num_attention_heads": 8,
|
| 21 |
+
"num_experts_per_token": 2,
|
| 22 |
+
"num_hidden_layers": 9,
|
| 23 |
+
"num_key_value_heads": 2,
|
| 24 |
+
"num_routed_experts": 14,
|
| 25 |
+
"num_shared_experts": 1,
|
| 26 |
+
"pad_token_id": 1,
|
| 27 |
+
"rms_norm_eps": 1e-05,
|
| 28 |
+
"rope_theta": 10000.0,
|
| 29 |
+
"router_aux_loss_coef": 0.01,
|
| 30 |
+
"router_bias_update_rate": 0.001,
|
| 31 |
+
"router_z_loss_coef": 0.001,
|
| 32 |
+
"torch_dtype": "bfloat16",
|
| 33 |
+
"transformers_version": "4.53.3",
|
| 34 |
+
"use_aux_loss_free_balancing": true,
|
| 35 |
+
"vocab_size": 8192
|
| 36 |
+
}
|
configuration_dynamicmind_moe.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from transformers.configuration_utils import PretrainedConfig
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class DynamicMindMoEConfig(PretrainedConfig):
|
| 5 |
+
"""DynamicMind-MoE: sparse mixture-of-experts variant of DynamicMind-Mini.
|
| 6 |
+
|
| 7 |
+
The dense MLP (intermediate 768) is replaced by one always-on shared expert
|
| 8 |
+
plus `num_routed_experts` fine-grained experts (intermediate 256), of which
|
| 9 |
+
`num_experts_per_token` are selected. Shared + top-2 reproduces the dense
|
| 10 |
+
layer's exact active parameter count, so inference cost per token is
|
| 11 |
+
unchanged while total capacity grows ~3.4x.
|
| 12 |
+
"""
|
| 13 |
+
|
| 14 |
+
model_type = "dynamicmind_moe"
|
| 15 |
+
|
| 16 |
+
def __init__(
|
| 17 |
+
self,
|
| 18 |
+
vocab_size=8192,
|
| 19 |
+
hidden_size=256,
|
| 20 |
+
intermediate_size=768, # kept for dense layers / upcycling source
|
| 21 |
+
moe_intermediate_size=256, # per-expert width (768 / 3)
|
| 22 |
+
num_hidden_layers=9,
|
| 23 |
+
num_attention_heads=8,
|
| 24 |
+
num_key_value_heads=2,
|
| 25 |
+
num_routed_experts=14,
|
| 26 |
+
num_shared_experts=1,
|
| 27 |
+
num_experts_per_token=2,
|
| 28 |
+
first_k_dense_layers=0, # keep the first K blocks dense if desired
|
| 29 |
+
norm_topk_prob=True,
|
| 30 |
+
router_aux_loss_coef=0.01,
|
| 31 |
+
router_z_loss_coef=0.001,
|
| 32 |
+
router_bias_update_rate=0.001, # aux-loss-free balancing (DeepSeek-V3)
|
| 33 |
+
use_aux_loss_free_balancing=True,
|
| 34 |
+
max_position_embeddings=1024,
|
| 35 |
+
rms_norm_eps=1e-5,
|
| 36 |
+
rope_theta=10000.0,
|
| 37 |
+
attention_dropout=0.0,
|
| 38 |
+
tie_word_embeddings=True,
|
| 39 |
+
bos_token_id=0,
|
| 40 |
+
eos_token_id=0,
|
| 41 |
+
pad_token_id=1,
|
| 42 |
+
**kwargs,
|
| 43 |
+
):
|
| 44 |
+
super().__init__(
|
| 45 |
+
bos_token_id=bos_token_id,
|
| 46 |
+
eos_token_id=eos_token_id,
|
| 47 |
+
pad_token_id=pad_token_id,
|
| 48 |
+
tie_word_embeddings=tie_word_embeddings,
|
| 49 |
+
**kwargs,
|
| 50 |
+
)
|
| 51 |
+
|
| 52 |
+
self.vocab_size = vocab_size
|
| 53 |
+
self.hidden_size = hidden_size
|
| 54 |
+
self.intermediate_size = intermediate_size
|
| 55 |
+
self.moe_intermediate_size = moe_intermediate_size
|
| 56 |
+
self.num_hidden_layers = num_hidden_layers
|
| 57 |
+
self.num_attention_heads = num_attention_heads
|
| 58 |
+
self.num_key_value_heads = num_key_value_heads
|
| 59 |
+
|
| 60 |
+
self.num_routed_experts = num_routed_experts
|
| 61 |
+
self.num_shared_experts = num_shared_experts
|
| 62 |
+
self.num_experts_per_token = num_experts_per_token
|
| 63 |
+
self.first_k_dense_layers = first_k_dense_layers
|
| 64 |
+
self.norm_topk_prob = norm_topk_prob
|
| 65 |
+
|
| 66 |
+
self.router_aux_loss_coef = router_aux_loss_coef
|
| 67 |
+
self.router_z_loss_coef = router_z_loss_coef
|
| 68 |
+
self.router_bias_update_rate = router_bias_update_rate
|
| 69 |
+
self.use_aux_loss_free_balancing = use_aux_loss_free_balancing
|
| 70 |
+
|
| 71 |
+
self.max_position_embeddings = max_position_embeddings
|
| 72 |
+
self.rms_norm_eps = rms_norm_eps
|
| 73 |
+
self.rope_theta = rope_theta
|
| 74 |
+
self.attention_dropout = attention_dropout
|
eval/protocol/gpqa_generations.jsonl
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
eval/protocol/ifeval_generations.jsonl
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
eval/protocol/livebench_generations.jsonl
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
eval/protocol/summary.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"ifeval": {
|
| 3 |
+
"metric": "prompt-level strict",
|
| 4 |
+
"score": 18.853974121996302,
|
| 5 |
+
"n": 541,
|
| 6 |
+
"eos_rate": 0.8835489833641405,
|
| 7 |
+
"minutes": 29.08
|
| 8 |
+
},
|
| 9 |
+
"gpqa": {
|
| 10 |
+
"metric": "pass@1 (990 attempts, no-letter counts wrong)",
|
| 11 |
+
"score": 12.323232323232324,
|
| 12 |
+
"n_attempts": 990,
|
| 13 |
+
"answered_rate": 46.26262626262626,
|
| 14 |
+
"accuracy_among_answered": 26.637554585152838,
|
| 15 |
+
"prompts_truncated": 40,
|
| 16 |
+
"minutes": 25.69
|
| 17 |
+
},
|
| 18 |
+
"livebench": {
|
| 19 |
+
"metric": "per-question mean(all followed, fraction followed), strict",
|
| 20 |
+
"score": 18.658333333333335,
|
| 21 |
+
"n": 200,
|
| 22 |
+
"eos_rate": 0.835,
|
| 23 |
+
"minutes": 9.9
|
| 24 |
+
}
|
| 25 |
+
}
|
eval/recommended_sampling/ifeval_generations.jsonl
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
eval/recommended_sampling/summary.json
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"ifeval": {
|
| 3 |
+
"metric": "prompt-level strict",
|
| 4 |
+
"score": 14.972273567467653,
|
| 5 |
+
"n": 541,
|
| 6 |
+
"eos_rate": 0.988909426987061,
|
| 7 |
+
"minutes": 21.12
|
| 8 |
+
}
|
| 9 |
+
}
|
generation_config.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"bos_token_id": 0,
|
| 3 |
+
"pad_token_id": 1,
|
| 4 |
+
"eos_token_id": 0,
|
| 5 |
+
"do_sample": true,
|
| 6 |
+
"temperature": 0.7,
|
| 7 |
+
"top_p": 0.9,
|
| 8 |
+
"repetition_penalty": 1.1,
|
| 9 |
+
"max_new_tokens": 512
|
| 10 |
+
}
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7cba2db1a17845e805ce8806b7c31d3b5bc88ba3f566f5f43be69dec195629f1
|
| 3 |
+
size 60355044
|
modeling_dynamicmind_moe.py
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import torch.nn.functional as F
|
| 4 |
+
|
| 5 |
+
from transformers.modeling_utils import PreTrainedModel
|
| 6 |
+
from transformers.generation import GenerationMixin
|
| 7 |
+
from transformers.modeling_outputs import MoeCausalLMOutputWithPast
|
| 8 |
+
from transformers.cache_utils import Cache, DynamicCache
|
| 9 |
+
|
| 10 |
+
from .configuration_dynamicmind_moe import DynamicMindMoEConfig
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class DynamicMindRMSNorm(nn.Module):
|
| 14 |
+
def __init__(self, hidden_size, eps=1e-5):
|
| 15 |
+
super().__init__()
|
| 16 |
+
self.weight = nn.Parameter(torch.ones(hidden_size))
|
| 17 |
+
self.eps = eps
|
| 18 |
+
|
| 19 |
+
def forward(self, x):
|
| 20 |
+
dtype = x.dtype
|
| 21 |
+
x = x.float()
|
| 22 |
+
x = x * torch.rsqrt(x.pow(2).mean(dim=-1, keepdim=True) + self.eps)
|
| 23 |
+
return (self.weight * x).to(dtype)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class DynamicMindRotaryEmbedding(nn.Module):
|
| 27 |
+
"""RoPE with a cached inv_freq.
|
| 28 |
+
|
| 29 |
+
The dense model rebuilt inv_freq on every forward of every layer; caching it
|
| 30 |
+
removes 9 redundant allocations per step.
|
| 31 |
+
|
| 32 |
+
inv_freq is a constant derived from config, so persistent=False looks
|
| 33 |
+
correct — but from_pretrained materialises tensors straight from the
|
| 34 |
+
checkpoint onto meta-device modules, never running __init__'s value nor
|
| 35 |
+
_load_from_state_dict for it. A non-persistent buffer therefore survives
|
| 36 |
+
loading as uninitialised `torch.empty` garbage, silently scrambling RoPE:
|
| 37 |
+
measured 833 vs 908 Elo on identical weights. Persisting the 16 floats is
|
| 38 |
+
the only variant that loads correctly through every path.
|
| 39 |
+
"""
|
| 40 |
+
|
| 41 |
+
def __init__(self, head_dim, rope_theta, max_position_embeddings):
|
| 42 |
+
super().__init__()
|
| 43 |
+
self.head_dim = head_dim
|
| 44 |
+
self.rope_theta = rope_theta
|
| 45 |
+
self.register_buffer("inv_freq", self._compute(), persistent=True)
|
| 46 |
+
self.max_seq_len_cached = 0
|
| 47 |
+
|
| 48 |
+
def _compute(self):
|
| 49 |
+
return 1.0 / (self.rope_theta ** (
|
| 50 |
+
torch.arange(0, self.head_dim, 2).float() / self.head_dim))
|
| 51 |
+
|
| 52 |
+
def _load_from_state_dict(self, state_dict, prefix, *args, **kwargs):
|
| 53 |
+
super()._load_from_state_dict(state_dict, prefix, *args, **kwargs)
|
| 54 |
+
with torch.no_grad():
|
| 55 |
+
self.inv_freq.copy_(self._compute().to(self.inv_freq.device))
|
| 56 |
+
|
| 57 |
+
def forward(self, x, position_ids):
|
| 58 |
+
freqs = position_ids[:, :, None].float() * self.inv_freq[None, None, :]
|
| 59 |
+
return freqs.cos().to(x.dtype), freqs.sin().to(x.dtype)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def apply_rope(q, k, cos, sin):
|
| 63 |
+
cos = cos[:, None, :, :]
|
| 64 |
+
sin = sin[:, None, :, :]
|
| 65 |
+
|
| 66 |
+
def rotate(x):
|
| 67 |
+
even, odd = x[..., 0::2], x[..., 1::2]
|
| 68 |
+
return torch.stack((even * cos - odd * sin, even * sin + odd * cos), dim=-1).flatten(-2)
|
| 69 |
+
|
| 70 |
+
return rotate(q), rotate(k)
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
class DynamicMindAttention(nn.Module):
|
| 74 |
+
def __init__(self, config, layer_idx):
|
| 75 |
+
super().__init__()
|
| 76 |
+
self.layer_idx = layer_idx
|
| 77 |
+
self.num_heads = config.num_attention_heads
|
| 78 |
+
self.num_kv_heads = config.num_key_value_heads
|
| 79 |
+
self.head_dim = config.hidden_size // config.num_attention_heads
|
| 80 |
+
self.attention_dropout = config.attention_dropout
|
| 81 |
+
|
| 82 |
+
self.q_proj = nn.Linear(config.hidden_size, self.num_heads * self.head_dim, bias=False)
|
| 83 |
+
self.k_proj = nn.Linear(config.hidden_size, self.num_kv_heads * self.head_dim, bias=False)
|
| 84 |
+
self.v_proj = nn.Linear(config.hidden_size, self.num_kv_heads * self.head_dim, bias=False)
|
| 85 |
+
self.o_proj = nn.Linear(config.hidden_size, config.hidden_size, bias=False)
|
| 86 |
+
|
| 87 |
+
def forward(self, x, cos, sin, attention_mask=None, past_key_values=None, cache_position=None):
|
| 88 |
+
bsz, q_len, _ = x.shape
|
| 89 |
+
|
| 90 |
+
q = self.q_proj(x).view(bsz, q_len, self.num_heads, self.head_dim).transpose(1, 2)
|
| 91 |
+
k = self.k_proj(x).view(bsz, q_len, self.num_kv_heads, self.head_dim).transpose(1, 2)
|
| 92 |
+
v = self.v_proj(x).view(bsz, q_len, self.num_kv_heads, self.head_dim).transpose(1, 2)
|
| 93 |
+
|
| 94 |
+
q, k = apply_rope(q, k, cos, sin)
|
| 95 |
+
|
| 96 |
+
if past_key_values is not None:
|
| 97 |
+
k, v = past_key_values.update(k, v, self.layer_idx, {"cache_position": cache_position})
|
| 98 |
+
|
| 99 |
+
if self.num_kv_heads != self.num_heads:
|
| 100 |
+
repeats = self.num_heads // self.num_kv_heads
|
| 101 |
+
k = k.repeat_interleave(repeats, dim=1)
|
| 102 |
+
v = v.repeat_interleave(repeats, dim=1)
|
| 103 |
+
|
| 104 |
+
is_causal = attention_mask is None and q_len > 1
|
| 105 |
+
y = F.scaled_dot_product_attention(
|
| 106 |
+
q, k, v,
|
| 107 |
+
attn_mask=attention_mask,
|
| 108 |
+
dropout_p=self.attention_dropout if self.training else 0.0,
|
| 109 |
+
is_causal=is_causal,
|
| 110 |
+
)
|
| 111 |
+
y = y.transpose(1, 2).contiguous().view(bsz, q_len, -1)
|
| 112 |
+
return self.o_proj(y)
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
class DynamicMindMLP(nn.Module):
|
| 116 |
+
def __init__(self, hidden_size, intermediate_size):
|
| 117 |
+
super().__init__()
|
| 118 |
+
self.gate_proj = nn.Linear(hidden_size, intermediate_size, bias=False)
|
| 119 |
+
self.up_proj = nn.Linear(hidden_size, intermediate_size, bias=False)
|
| 120 |
+
self.down_proj = nn.Linear(intermediate_size, hidden_size, bias=False)
|
| 121 |
+
|
| 122 |
+
def forward(self, x):
|
| 123 |
+
return self.down_proj(F.silu(self.gate_proj(x)) * self.up_proj(x))
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
class DynamicMindMoE(nn.Module):
|
| 127 |
+
"""Shared expert + top-k routed fine-grained experts.
|
| 128 |
+
|
| 129 |
+
The shared expert runs on every token and absorbs knowledge common to all
|
| 130 |
+
inputs, so the routed experts are free to specialise instead of each
|
| 131 |
+
re-learning the same basics.
|
| 132 |
+
"""
|
| 133 |
+
|
| 134 |
+
def __init__(self, config):
|
| 135 |
+
super().__init__()
|
| 136 |
+
self.num_routed = config.num_routed_experts
|
| 137 |
+
self.top_k = config.num_experts_per_token
|
| 138 |
+
self.norm_topk_prob = config.norm_topk_prob
|
| 139 |
+
self.aux_free = config.use_aux_loss_free_balancing
|
| 140 |
+
|
| 141 |
+
self.experts = nn.ModuleList([
|
| 142 |
+
DynamicMindMLP(config.hidden_size, config.moe_intermediate_size)
|
| 143 |
+
for _ in range(self.num_routed)
|
| 144 |
+
])
|
| 145 |
+
self.shared_experts = nn.ModuleList([
|
| 146 |
+
DynamicMindMLP(config.hidden_size, config.moe_intermediate_size)
|
| 147 |
+
for _ in range(config.num_shared_experts)
|
| 148 |
+
])
|
| 149 |
+
|
| 150 |
+
self.router = nn.Linear(config.hidden_size, self.num_routed, bias=False)
|
| 151 |
+
|
| 152 |
+
# Aux-loss-free balancing: a per-expert bias nudged toward even load.
|
| 153 |
+
# It steers selection only — never the combining weights — so it costs
|
| 154 |
+
# no gradient interference, unlike an auxiliary loss.
|
| 155 |
+
self.register_buffer("expert_bias", torch.zeros(self.num_routed), persistent=True)
|
| 156 |
+
self.bias_update_rate = config.router_bias_update_rate
|
| 157 |
+
|
| 158 |
+
def forward(self, x):
|
| 159 |
+
bsz, seq_len, hidden = x.shape
|
| 160 |
+
flat = x.view(-1, hidden)
|
| 161 |
+
n_tokens = flat.size(0)
|
| 162 |
+
|
| 163 |
+
logits = self.router(flat) # [T, E]
|
| 164 |
+
probs = F.softmax(logits, dim=-1, dtype=torch.float)
|
| 165 |
+
|
| 166 |
+
scores = probs + self.expert_bias if self.aux_free else probs
|
| 167 |
+
_, topk_idx = torch.topk(scores, self.top_k, dim=-1)
|
| 168 |
+
topk_w = probs.gather(-1, topk_idx) # weights from unbiased probs
|
| 169 |
+
if self.norm_topk_prob:
|
| 170 |
+
topk_w = topk_w / topk_w.sum(dim=-1, keepdim=True).clamp_min(1e-9)
|
| 171 |
+
topk_w = topk_w.to(x.dtype)
|
| 172 |
+
|
| 173 |
+
out = torch.zeros_like(flat)
|
| 174 |
+
for expert in self.shared_experts:
|
| 175 |
+
out = out + expert(flat)
|
| 176 |
+
|
| 177 |
+
# one-hot over experts -> per-expert token lists
|
| 178 |
+
mask = torch.zeros(n_tokens, self.num_routed, dtype=torch.bool, device=x.device)
|
| 179 |
+
mask.scatter_(1, topk_idx, True)
|
| 180 |
+
load = mask.sum(0)
|
| 181 |
+
|
| 182 |
+
for e in range(self.num_routed):
|
| 183 |
+
idx = mask[:, e].nonzero(as_tuple=True)[0]
|
| 184 |
+
if idx.numel() == 0:
|
| 185 |
+
continue
|
| 186 |
+
slot = (topk_idx[idx] == e).float().argmax(dim=-1)
|
| 187 |
+
w = topk_w[idx].gather(-1, slot[:, None])
|
| 188 |
+
out.index_add_(0, idx, self.experts[e](flat[idx]) * w)
|
| 189 |
+
|
| 190 |
+
if self.training and self.aux_free:
|
| 191 |
+
with torch.no_grad():
|
| 192 |
+
target = n_tokens * self.top_k / self.num_routed
|
| 193 |
+
self.expert_bias += self.bias_update_rate * (target - load.float()).sign()
|
| 194 |
+
|
| 195 |
+
# Reported for logging even when aux-free balancing is on.
|
| 196 |
+
frac_tokens = load.float() / (n_tokens * self.top_k)
|
| 197 |
+
frac_probs = probs.mean(dim=0)
|
| 198 |
+
aux_loss = self.num_routed * (frac_tokens * frac_probs).sum()
|
| 199 |
+
z_loss = torch.logsumexp(logits.float(), dim=-1).pow(2).mean()
|
| 200 |
+
|
| 201 |
+
return out.view(bsz, seq_len, hidden), aux_loss, z_loss, load
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
class DynamicMindBlock(nn.Module):
|
| 205 |
+
def __init__(self, config, layer_idx):
|
| 206 |
+
super().__init__()
|
| 207 |
+
self.input_layernorm = DynamicMindRMSNorm(config.hidden_size, config.rms_norm_eps)
|
| 208 |
+
self.self_attn = DynamicMindAttention(config, layer_idx)
|
| 209 |
+
self.post_attention_layernorm = DynamicMindRMSNorm(config.hidden_size, config.rms_norm_eps)
|
| 210 |
+
|
| 211 |
+
self.is_moe = layer_idx >= config.first_k_dense_layers
|
| 212 |
+
if self.is_moe:
|
| 213 |
+
self.mlp = DynamicMindMoE(config)
|
| 214 |
+
else:
|
| 215 |
+
self.mlp = DynamicMindMLP(config.hidden_size, config.intermediate_size)
|
| 216 |
+
|
| 217 |
+
def forward(self, x, cos, sin, attention_mask=None, past_key_values=None, cache_position=None):
|
| 218 |
+
x = x + self.self_attn(self.input_layernorm(x), cos, sin,
|
| 219 |
+
attention_mask, past_key_values, cache_position)
|
| 220 |
+
h = self.post_attention_layernorm(x)
|
| 221 |
+
if self.is_moe:
|
| 222 |
+
delta, aux, z, load = self.mlp(h)
|
| 223 |
+
return x + delta, aux, z, load
|
| 224 |
+
return x + self.mlp(h), None, None, None
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
class DynamicMindMoEPreTrainedModel(PreTrainedModel):
|
| 228 |
+
config_class = DynamicMindMoEConfig
|
| 229 |
+
base_model_prefix = "model"
|
| 230 |
+
supports_gradient_checkpointing = True
|
| 231 |
+
_no_split_modules = ["DynamicMindBlock"]
|
| 232 |
+
|
| 233 |
+
def _init_weights(self, module):
|
| 234 |
+
if isinstance(module, nn.Linear):
|
| 235 |
+
nn.init.normal_(module.weight, mean=0.0, std=0.02)
|
| 236 |
+
if module.bias is not None:
|
| 237 |
+
nn.init.zeros_(module.bias)
|
| 238 |
+
elif isinstance(module, nn.Embedding):
|
| 239 |
+
nn.init.normal_(module.weight, mean=0.0, std=0.02)
|
| 240 |
+
|
| 241 |
+
|
| 242 |
+
class DynamicMindMoEForCausalLM(DynamicMindMoEPreTrainedModel, GenerationMixin):
|
| 243 |
+
_tied_weights_keys = {"lm_head.weight": "embed_tokens.weight"}
|
| 244 |
+
|
| 245 |
+
def __init__(self, config):
|
| 246 |
+
super().__init__(config)
|
| 247 |
+
self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size)
|
| 248 |
+
self.layers = nn.ModuleList([
|
| 249 |
+
DynamicMindBlock(config, i) for i in range(config.num_hidden_layers)
|
| 250 |
+
])
|
| 251 |
+
self.norm = DynamicMindRMSNorm(config.hidden_size, config.rms_norm_eps)
|
| 252 |
+
self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
|
| 253 |
+
self.rotary = DynamicMindRotaryEmbedding(
|
| 254 |
+
config.hidden_size // config.num_attention_heads,
|
| 255 |
+
config.rope_theta,
|
| 256 |
+
config.max_position_embeddings,
|
| 257 |
+
)
|
| 258 |
+
if config.tie_word_embeddings:
|
| 259 |
+
self.lm_head.weight = self.embed_tokens.weight
|
| 260 |
+
self.post_init()
|
| 261 |
+
|
| 262 |
+
def tie_weights(self, *args, **kwargs):
|
| 263 |
+
if getattr(self.config, "tie_word_embeddings", True):
|
| 264 |
+
self.lm_head.weight = self.embed_tokens.weight
|
| 265 |
+
|
| 266 |
+
def get_input_embeddings(self):
|
| 267 |
+
return self.embed_tokens
|
| 268 |
+
|
| 269 |
+
def set_input_embeddings(self, value):
|
| 270 |
+
self.embed_tokens = value
|
| 271 |
+
|
| 272 |
+
def forward(self, input_ids=None, attention_mask=None, position_ids=None,
|
| 273 |
+
past_key_values=None, labels=None, use_cache=True, **kwargs):
|
| 274 |
+
# cache_position is read from kwargs rather than declared: transformers
|
| 275 |
+
# warns about remote-code models whose signature expects it, and plans
|
| 276 |
+
# to stop passing it. It is derived below whenever it is absent.
|
| 277 |
+
cache_position = kwargs.get("cache_position")
|
| 278 |
+
x = self.embed_tokens(input_ids)
|
| 279 |
+
|
| 280 |
+
if use_cache and past_key_values is None:
|
| 281 |
+
past_key_values = DynamicCache()
|
| 282 |
+
past_len = past_key_values.get_seq_length() if isinstance(past_key_values, Cache) else 0
|
| 283 |
+
|
| 284 |
+
if cache_position is None:
|
| 285 |
+
cache_position = torch.arange(past_len, past_len + x.size(1), device=x.device)
|
| 286 |
+
if position_ids is None:
|
| 287 |
+
position_ids = cache_position[None, :]
|
| 288 |
+
|
| 289 |
+
cos, sin = self.rotary(x, position_ids)
|
| 290 |
+
|
| 291 |
+
causal_mask = None
|
| 292 |
+
if x.size(1) > 1:
|
| 293 |
+
total = past_len + x.size(1)
|
| 294 |
+
causal = torch.tril(torch.ones(x.size(1), total, dtype=torch.bool, device=x.device),
|
| 295 |
+
diagonal=past_len)
|
| 296 |
+
causal_mask = torch.zeros(x.size(1), total, dtype=x.dtype, device=x.device)
|
| 297 |
+
causal_mask.masked_fill_(~causal, torch.finfo(x.dtype).min)
|
| 298 |
+
causal_mask = causal_mask[None, None, :, :]
|
| 299 |
+
|
| 300 |
+
aux_total = x.new_zeros(())
|
| 301 |
+
z_total = x.new_zeros(())
|
| 302 |
+
loads = []
|
| 303 |
+
for layer in self.layers:
|
| 304 |
+
x, aux, z, load = layer(x, cos, sin, causal_mask, past_key_values, cache_position)
|
| 305 |
+
if aux is not None:
|
| 306 |
+
aux_total = aux_total + aux
|
| 307 |
+
z_total = z_total + z
|
| 308 |
+
loads.append(load)
|
| 309 |
+
|
| 310 |
+
logits = self.lm_head(self.norm(x))
|
| 311 |
+
|
| 312 |
+
loss = None
|
| 313 |
+
if labels is not None:
|
| 314 |
+
shift_labels = torch.cat(
|
| 315 |
+
[labels[:, 1:], labels.new_full((labels.size(0), 1), -100)], dim=1
|
| 316 |
+
)
|
| 317 |
+
loss = F.cross_entropy(logits.view(-1, logits.size(-1)), shift_labels.view(-1))
|
| 318 |
+
n_moe = max(len(loads), 1)
|
| 319 |
+
loss = loss + self.config.router_aux_loss_coef * aux_total / n_moe
|
| 320 |
+
loss = loss + self.config.router_z_loss_coef * z_total / n_moe
|
| 321 |
+
|
| 322 |
+
return MoeCausalLMOutputWithPast(
|
| 323 |
+
loss=loss,
|
| 324 |
+
logits=logits,
|
| 325 |
+
past_key_values=past_key_values if use_cache else None,
|
| 326 |
+
aux_loss=aux_total / max(len(loads), 1) if loads else None,
|
| 327 |
+
)
|
| 328 |
+
|
| 329 |
+
def expert_load(self):
|
| 330 |
+
"""Per-layer expert token counts from the last forward, for monitoring."""
|
| 331 |
+
return [m.expert_bias for m in self.modules() if isinstance(m, DynamicMindMoE)]
|
| 332 |
+
|
| 333 |
+
def state_dict(self, *args, **kwargs):
|
| 334 |
+
sd = super().state_dict(*args, **kwargs)
|
| 335 |
+
if getattr(self.config, "tie_word_embeddings", True):
|
| 336 |
+
for k in list(sd.keys()):
|
| 337 |
+
if k == "lm_head.weight" or k.endswith(".lm_head.weight"):
|
| 338 |
+
del sd[k]
|
| 339 |
+
return sd
|
tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"bos_token": "<|endoftext|>",
|
| 3 |
+
"eos_token": "<|endoftext|>",
|
| 4 |
+
"pad_token": "<|pad|>",
|
| 5 |
+
"unk_token": "<|unk|>",
|
| 6 |
+
"model_max_length": 1024,
|
| 7 |
+
"tokenizer_class": "PreTrainedTokenizerFast",
|
| 8 |
+
"chat_template": "{{- '<|endoftext|>' -}}{%- for message in messages -%}{%- if message['role'] == 'system' -%}{{ '### System:\n' + message['content'].strip() + '\n' }}{%- elif message['role'] == 'user' -%}{{ '### User:\n' + message['content'].strip() + '\n' }}{%- elif message['role'] == 'assistant' -%}{{ '### Assistant:\n' + message['content'].strip() + '\n<|endoftext|>' }}{%- endif -%}{%- endfor -%}{%- if add_generation_prompt -%}{{ '### Assistant:\n' }}{%- endif -%}"
|
| 9 |
+
}
|