MarkProMaster229 commited on
Commit
2b839f9
·
verified ·
1 Parent(s): ec51d55

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +235 -0
README.md CHANGED
@@ -1,3 +1,238 @@
1
  ---
2
  license: apache-2.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  license: apache-2.0
3
+ datasets:
4
+ - krplt/ru-fictext-nsfw
5
+ - MarkProMaster229/taiga_proza_small
6
+ language:
7
+ - ru
8
+ pipeline_tag: text-generation
9
+ tags:
10
+ - russian
11
+ - pretrained
12
+ - language-model
13
+ - mamba
14
+ - attention
15
+ - gqa
16
+ - hybrid
17
+ - causal-lm
18
+ - text-generation
19
+ - from-scratch
20
+ - small-language-model
21
+ - research
22
  ---
23
+ # Big-CoMAttn
24
+
25
+ Небольшая-предтрен языковая модель на русском языке, обученная с нуля на эксперементальной - гибридной архитектуре Mamba + Attention.
26
+
27
+
28
+ ## Архитектура
29
+
30
+ Гибридная архитектура,Mamba (State Space Model)aceGrouped Query Attention (GQA)tion (GQA)**. Общая схема:
31
+
32
+ ```
33
+ ┌────────────────────────────────────────────────────┐
34
+ │ Layer 1: MambaBlock │
35
+ │ LayerNorm → Mamba │
36
+ ├────────────────────────────────────────────────────┤
37
+ │ Layer 2: TransformerBlockBig │
38
+ │ LayerNorm → GQA Attention │
39
+ │ LayerNorm → MLP (6×) │
40
+ ├────────────────────────────────────────────────────┤
41
+ │ Layer 3: MambaBlock │
42
+ │ LayerNorm → Mamba │
43
+ ├────────────────────────────────────────────────────┤
44
+ │ Layer 4: MambaBlock │
45
+ │ LayerNorm → Mamba │
46
+ ├────────────────────────────────────────────────────┤
47
+ │ Layer 5: AttnMambaBlock │
48
+ │ LayerNorm → GQA Attention │
49
+ │ LayerNorm → Mamba │
50
+ ├────────────────────────────────────────────────────┤
51
+ │ Layer 6: MambaBlock │
52
+ │ LayerNorm → Mamba │
53
+ ├────────────────────────────────────────────────────┤
54
+ │ Layer 7: MambaBlock │
55
+ │ LayerNorm → Mamba │
56
+ ├────────────────────────────────────────────────────┤
57
+ │ Layer 8: FinalBlock │
58
+ │ LayerNorm → GQA Attention │
59
+ │ LayerNorm → MLP (2×) │
60
+ └────────────────────────────────────────────────────┘
61
+ ```
62
+ lm_head.weight толстенький пирожок 31% от всей модели что было ошибкой, в последствии стоит использовать свой токенизатор.
63
+ tying - многократно ухудшал результаты было принято решение отказаться.
64
+
65
+ ### Mamba
66
+
67
+ Все Mamba-слои используют одинаковые параметры:
68
+
69
+ Mamba(
70
+ d_model=512,
71
+ d_state=16,
72
+ d_conv=4,
73
+ expand=2,
74
+ )
75
+ Grouped Query Attention (GQA)
76
+
77
+ Все attention-слои используют GQA с отвязанным head_dim:
78
+
79
+ GQAAttention(
80
+ d_model=512,
81
+ n_heads_q=16,
82
+ n_heads_kv=4, # GQA ratio = 4:1
83
+ head_dim=64, # отвязано от d_model // n_heads_q
84
+ dropout=0.1,
85
+ )
86
+
87
+ Используется F.scaled_dot_product_attention с broadcasting для GQA (без repeat_interleave — без копий K/V).
88
+
89
+ MLP
90
+
91
+ · Слой 2: Linear(512 → 3072) → GELU → Linear(3072 → 512) — 6×
92
+ · Слой 8: Linear(512 → 1024) → GELU → Linear(1024 → 512) — 2×
93
+
94
+ Узкий MLP в финальном слое выбран намеренно(эмпирически): на выходе модели нужна только нелинейность.
95
+
96
+ Инициализация
97
+
98
+ GPT-стиль инициализации (N(0, 0.02)) - Attention.
99
+ ### Пример использования
100
+ ```python
101
+ import os
102
+ os.environ["TOKENIZERS_PARALLELISM"] = "false"
103
+
104
+ import torch
105
+ import torch.nn.functional as F
106
+ from huggingface_hub import snapshot_download
107
+ from safetensors.torch import load_file
108
+ from transformers import AutoTokenizer
109
+
110
+ from mambaMain import build_model
111
+
112
+
113
+ REPO_ID = "algorithms-learning/Big-CoMAttn"
114
+ CACHE_DIR = "./hf_cache"
115
+ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
116
+
117
+ TEMPERATURE = 0.3
118
+ TOP_K = 50
119
+ TOP_P = 0.95
120
+ REPETITION_PENALTY = 1.2
121
+ MAX_NEW_TOKENS = 150
122
+
123
+
124
+
125
+ def download_model(repo_id=REPO_ID, cache_dir=CACHE_DIR):
126
+ path = snapshot_download(
127
+ repo_id=repo_id,
128
+ cache_dir=cache_dir,
129
+ allow_patterns=[
130
+ "*.safetensors",
131
+ "*.json",
132
+ "*.model",
133
+ "README.md",
134
+ ],
135
+ )
136
+ return path
137
+
138
+
139
+ def load_model_and_tokenizer(model_dir):
140
+ tokenizer = AutoTokenizer.from_pretrained(model_dir)
141
+ tokenizer.pad_token = tokenizer.eos_token
142
+ print(f"Tokenizer loaded. Vocab: {len(tokenizer)}")
143
+
144
+ model = build_model(len(tokenizer), config={
145
+ "d_model": 512,
146
+ "max_len": 1024,
147
+ "n_heads_q": 16,
148
+ "n_heads_kv": 4,
149
+ "head_dim": 64,
150
+ "dropout": 0.1,
151
+ }).to(DEVICE)
152
+
153
+ state_dict = load_file(
154
+ os.path.join(model_dir, "model.safetensors"),
155
+ device=DEVICE,
156
+ )
157
+ model.load_state_dict(state_dict)
158
+ model.eval()
159
+
160
+ n_params = sum(p.numel() for p in model.parameters())
161
+ print(f"Model loaded. Params: {n_params/1e6:.2f}M")
162
+ return model, tokenizer
163
+
164
+
165
+ def generate(model, tokenizer, prompt,
166
+ max_new_tokens=MAX_NEW_TOKENS,
167
+ temperature=TEMPERATURE,
168
+ top_k=TOP_K, top_p=TOP_P,
169
+ rep_penalty=REPETITION_PENALTY):
170
+ """Sampling: temperature + top-k + top-p + repetition penalty."""
171
+ ids = tokenizer.encode(prompt, return_tensors="pt").to(DEVICE)
172
+
173
+ with torch.no_grad():
174
+ for _ in range(max_new_tokens):
175
+ input_ids = ids[:, -1024:]
176
+ logits = model(input_ids)[:, -1, :].float()
177
+
178
+ if rep_penalty != 1.0:
179
+ for token_id in set(ids[0, -50:].tolist()):
180
+ if logits[0, token_id] > 0:
181
+ logits[0, token_id] /= rep_penalty
182
+ else:
183
+ logits[0, token_id] *= rep_penalty
184
+
185
+
186
+ logits = logits / temperature
187
+
188
+ if top_k > 0:
189
+ top_k_vals, _ = torch.topk(logits, top_k)
190
+ min_val = top_k_vals[0, -1]
191
+ logits[logits < min_val] = float("-inf")
192
+
193
+ if top_p < 1.0:
194
+ sorted_logits, sorted_idx = torch.sort(logits, descending=True)
195
+ probs = F.softmax(sorted_logits, dim=-1)
196
+ cum_probs = torch.cumsum(probs, dim=-1)
197
+ sorted_mask = cum_probs > top_p
198
+ sorted_mask[..., 1:] = sorted_mask[..., :-1].clone()
199
+ sorted_mask[..., 0] = False
200
+ indices_to_remove = sorted_mask.scatter(1, sorted_idx, sorted_mask)
201
+ logits[indices_to_remove] = float("-inf")
202
+
203
+ probs = F.softmax(logits, dim=-1)
204
+ next_token = torch.multinomial(probs, num_samples=1)
205
+ ids = torch.cat([ids, next_token], dim=1)
206
+
207
+ if next_token.item() == tokenizer.eos_token_id:
208
+ break
209
+
210
+ return tokenizer.decode(ids[0], skip_special_tokens=True)
211
+
212
+ def main():
213
+ model_dir = download_model()
214
+ print(f"Model dir: {model_dir}\n")
215
+
216
+ model, tokenizer = load_model_and_tokenizer(model_dir)
217
+ print()
218
+
219
+ prompts = [
220
+ "В твоей модели мира число звёзд бесконечно",
221
+ "Привет, как дела? Я хотел тебе сказать",
222
+ "Он посмотрел на неё и понял, что",
223
+ "Вчера в Москве произошло странное событие",
224
+ "Анон, объясни мне пожалуйста",
225
+ ]
226
+
227
+ for i, p in enumerate(prompts, 1):
228
+ print("=" * 60)
229
+ print(f"[{i}] PROMPT: {p}")
230
+ print("-" * 60)
231
+ result = generate(model, tokenizer, p)
232
+ print(result)
233
+ print()
234
+
235
+ if __name__ == "__main__":
236
+ main()
237
+
238
+ ```