kdirgul commited on
Commit
b80607a
·
verified ·
1 Parent(s): 3d07ab6

Upload code/kod/test_smartcore.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. code/kod/test_smartcore.py +242 -0
code/kod/test_smartcore.py ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ SmartCore V1 — SIFIRDAN Colab test (standalone / kendine yeten).
3
+
4
+ Final base modeli (kdirgul/smartcore-v1 son checkpoint) HF'den çeker, metin üretir.
5
+ Model tanımı faz3_train.py ile BİREBİR aynı (içine gömülü) → state_dict tam oturar,
6
+ faz3_train.py'ye bağımlılık YOK.
7
+
8
+ Ortam: Colab GPU + mamba-og fork (Faz 3a kurulu). CUDA şart (Triton kernel).
9
+ NOT: Bu bir BASE model (instruction yok) → soru-cevap DEĞİL, metin TAMAMLAMA yapar.
10
+
11
+ Kullanım:
12
+ HF_TOKEN=hf_xxx python test_smartcore.py --prompt "Türkiye'nin başkenti"
13
+ HF_TOKEN=hf_xxx python test_smartcore.py # interaktif REPL
14
+ python test_smartcore.py --ckpt /content/ck/step_022887/ckpt.pt # yerel .pt
15
+ """
16
+ import os, sys, math, argparse
17
+ import torch, torch.nn as nn, torch.nn.functional as F
18
+ from functools import partial
19
+
20
+ try:
21
+ from mamba_ssm.modules.block import Block
22
+ from mamba_ssm.modules.mamba3 import Mamba3
23
+ from mamba_ssm.modules.mlp import GatedMLP
24
+ from mamba_ssm.ops.triton.layer_norm import RMSNorm
25
+ except Exception as e:
26
+ sys.exit(f"[hata] mamba-og fork import edilemedi ({e!r}). Önce Faz 3a kurulum hücresini çalıştır (CUDA gerekir).")
27
+
28
+
29
+ # ───────────── model (faz3_train.py ile BİREBİR AYNI) ─────────────
30
+ def _rms(x, w, eps=1e-5):
31
+ return (x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + eps)) * w
32
+
33
+
34
+ def _rot_half(x):
35
+ a, b = x.chunk(2, -1)
36
+ return torch.cat((-b, a), -1)
37
+
38
+
39
+ class GQAMixer(nn.Module):
40
+ def __init__(self, dim, n_heads=12, n_kv=3, base=10000.0, layer_idx=None, device=None, dtype=None):
41
+ super().__init__()
42
+ self.nh, self.nkv, self.hd = n_heads, n_kv, dim // n_heads
43
+ self.rep = n_heads // n_kv
44
+ fk = {"device": device, "dtype": dtype}
45
+ self.q_proj = nn.Linear(dim, n_heads * self.hd, bias=False, **fk)
46
+ self.k_proj = nn.Linear(dim, n_kv * self.hd, bias=False, **fk)
47
+ self.v_proj = nn.Linear(dim, n_kv * self.hd, bias=False, **fk)
48
+ self.out_proj = nn.Linear(n_heads * self.hd, dim, bias=False, **fk)
49
+ self.qn = nn.Parameter(torch.ones(self.hd, **fk))
50
+ self.kn = nn.Parameter(torch.ones(self.hd, **fk))
51
+ self.register_buffer(
52
+ "inv", 1.0 / (base ** (torch.arange(0, self.hd, 2, device=device).float() / self.hd)),
53
+ persistent=False)
54
+
55
+ def _rope(self, x, T):
56
+ f = torch.outer(torch.arange(T, device=x.device, dtype=torch.float32), self.inv)
57
+ e = torch.cat((f, f), -1)
58
+ return (x * e.cos()[None, None] + _rot_half(x) * e.sin()[None, None]).to(x.dtype)
59
+
60
+ def forward(self, x, **kw):
61
+ B, T, _ = x.shape
62
+ q = self.q_proj(x).view(B, T, self.nh, self.hd).transpose(1, 2)
63
+ k = self.k_proj(x).view(B, T, self.nkv, self.hd).transpose(1, 2)
64
+ v = self.v_proj(x).view(B, T, self.nkv, self.hd).transpose(1, 2)
65
+ q = _rms(q.float(), self.qn.float()).to(x.dtype)
66
+ k = _rms(k.float(), self.kn.float()).to(x.dtype)
67
+ q, k = self._rope(q, T), self._rope(k, T)
68
+ k = k.repeat_interleave(self.rep, 1)
69
+ v = v.repeat_interleave(self.rep, 1)
70
+ y = F.scaled_dot_product_attention(q, k, v, is_causal=True)
71
+ return self.out_proj(y.transpose(1, 2).contiguous().view(B, T, -1))
72
+
73
+
74
+ class HybridLM(nn.Module):
75
+ def __init__(self, cfg, device=None, dtype=None):
76
+ super().__init__()
77
+ self.cfg = cfg
78
+ self.vocab = cfg["vocab_size"]
79
+ self.scaled_embed = cfg.get("scaled_embed", False)
80
+ d = cfg["d_model"]
81
+ self.embedding = nn.Embedding(self.vocab, d, device=device, dtype=dtype)
82
+ self.layers = nn.ModuleList()
83
+ self.attn_idx = []
84
+ for i in range(cfg["n_layers"]):
85
+ is_attn = ((i + 1) % cfg["attn_every"] == 0) and i != 0 and i != cfg["n_layers"] - 1
86
+ fk = {"device": device, "dtype": dtype}
87
+ if is_attn:
88
+ mixer_cls = partial(GQAMixer, n_heads=cfg["n_heads"], n_kv=cfg["n_kv_heads"],
89
+ layer_idx=i, **fk)
90
+ self.attn_idx.append(i)
91
+ else:
92
+ ssm = dict(d_state=cfg["d_state"], expand=cfg["expand"], headdim=cfg["head_dim"],
93
+ ngroups=cfg["ngroups"], rope_fraction=cfg["rope_fraction"],
94
+ is_outproj_norm=False, is_mimo=cfg["is_mimo"], mimo_rank=cfg["mimo_rank"],
95
+ chunk_size=cfg["chunk_size"])
96
+ mixer_cls = partial(Mamba3, layer_idx=i, **ssm, **fk)
97
+ blk = Block(d, mixer_cls,
98
+ partial(GatedMLP, hidden_features=cfg["d_intermediate"], out_features=d, **fk),
99
+ norm_cls=partial(RMSNorm, eps=1e-5, **fk),
100
+ fused_add_norm=True, residual_in_fp32=True)
101
+ blk.layer_idx = i
102
+ self.layers.append(blk)
103
+ self.norm_f = RMSNorm(d, eps=1e-5, device=device, dtype=dtype)
104
+ self.lm_head = nn.Linear(d, self.vocab, bias=False, device=device, dtype=dtype)
105
+ self.lm_head.weight = self.embedding.weight # tied
106
+
107
+ def forward(self, ids):
108
+ h = self.embedding(ids)
109
+ if self.scaled_embed:
110
+ h = h * (self.cfg["d_model"] ** 0.5)
111
+ res = None
112
+ for l in self.layers:
113
+ h, res = l(h, res)
114
+ h = self.norm_f((h + res) if res is not None else h)
115
+ return self.lm_head(h.to(self.lm_head.weight.dtype))
116
+
117
+
118
+ # ───────────── tokenizer + checkpoint ─────────────
119
+ def load_tok(path, token):
120
+ import sentencepiece as spm
121
+ if not (path and os.path.exists(path)):
122
+ from huggingface_hub import hf_hub_download
123
+ path = hf_hub_download("kdirgul/smartcore-v1", "tokenizer/tokenizer.model",
124
+ repo_type="model", token=token)
125
+ sp = spm.SentencePieceProcessor(model_file=path)
126
+ print(f"[tok] vocab={sp.get_piece_size()} eos={sp.eos_id()}", flush=True)
127
+ return sp
128
+
129
+
130
+ def resolve_ckpt(spec, repo, token):
131
+ if spec and spec != "latest_hf":
132
+ return spec
133
+ from huggingface_hub import HfApi, hf_hub_download
134
+ api = HfApi(token=token)
135
+ files = [f for f in api.list_repo_files(repo, repo_type="model")
136
+ if f.startswith("checkpoints/step_") and f.endswith("ckpt.pt")]
137
+ if not files:
138
+ sys.exit("[hata] HF'de checkpoint yok.")
139
+ latest = max(files)
140
+ print(f"[ckpt] HF'den indiriliyor: {latest}", flush=True)
141
+ return hf_hub_download(repo, latest, repo_type="model", token=token)
142
+
143
+
144
+ # ───────────── üretim ─────────────
145
+ @torch.no_grad()
146
+ def generate(model, sp, prompt, max_new=120, temperature=0.7, top_k=40, top_p=0.95,
147
+ rep_penalty=1.3, dev="cuda", seed=None):
148
+ if seed is not None:
149
+ torch.manual_seed(seed)
150
+ eos = sp.eos_id()
151
+ ids = sp.encode(prompt, out_type=int)
152
+ x = torch.tensor([ids], dtype=torch.long, device=dev)
153
+ out = list(ids)
154
+ for _ in range(max_new):
155
+ with torch.autocast(device_type="cuda", dtype=torch.bfloat16):
156
+ logits = model(x)[0, -1].float()
157
+ if rep_penalty and rep_penalty != 1.0:
158
+ for t in set(out):
159
+ logits[t] = logits[t] / rep_penalty if logits[t] > 0 else logits[t] * rep_penalty
160
+ if temperature <= 0:
161
+ nxt = int(logits.argmax())
162
+ else:
163
+ logits = logits / temperature
164
+ if top_k:
165
+ kth = torch.topk(logits, min(top_k, logits.numel())).values[-1]
166
+ logits[logits < kth] = -float("inf")
167
+ probs = F.softmax(logits, dim=-1)
168
+ if top_p and top_p < 1.0:
169
+ sp_, si = torch.sort(probs, descending=True)
170
+ cut = torch.cumsum(sp_, dim=-1) > top_p
171
+ cut[1:] = cut[:-1].clone(); cut[0] = False
172
+ sp_[cut] = 0.0
173
+ probs = torch.zeros_like(probs).scatter_(0, si, sp_)
174
+ probs /= probs.sum()
175
+ nxt = int(torch.multinomial(probs, 1))
176
+ if nxt == eos:
177
+ break
178
+ out.append(nxt)
179
+ x = torch.cat([x, torch.tensor([[nxt]], device=dev)], dim=1)
180
+ if x.shape[1] >= 2048:
181
+ x = x[:, -2048:]
182
+ return sp.decode([t for t in out if t != eos])
183
+
184
+
185
+ def main():
186
+ ap = argparse.ArgumentParser()
187
+ ap.add_argument("--ckpt", default="latest_hf", help="latest_hf | yerel .pt yolu")
188
+ ap.add_argument("--ckpt_repo", default="kdirgul/smartcore-v1")
189
+ ap.add_argument("--tokenizer", default=None)
190
+ ap.add_argument("--prompt", default=None, help="boşsa interaktif REPL")
191
+ ap.add_argument("--max_new", type=int, default=120)
192
+ ap.add_argument("--temperature", type=float, default=0.7)
193
+ ap.add_argument("--top_k", type=int, default=40)
194
+ ap.add_argument("--top_p", type=float, default=0.95)
195
+ ap.add_argument("--rep_penalty", type=float, default=1.3)
196
+ ap.add_argument("--seed", type=int, default=None)
197
+ args = ap.parse_args()
198
+
199
+ if not torch.cuda.is_available():
200
+ sys.exit("[hata] CUDA yok — Colab GPU gerekir (Triton kernel).")
201
+ dev = "cuda"
202
+ torch.set_float32_matmul_precision("high")
203
+ token = os.environ.get("HF_TOKEN")
204
+ if not token:
205
+ try:
206
+ from huggingface_hub import get_token
207
+ token = get_token()
208
+ except Exception:
209
+ token = None
210
+
211
+ sp = load_tok(args.tokenizer, token)
212
+ path = resolve_ckpt(args.ckpt, args.ckpt_repo, token)
213
+ st = torch.load(path, map_location="cpu")
214
+ cfg = st["cfg"]
215
+ print(f"[model] step={st.get('step','?')} | {'MIMO' if cfg.get('is_mimo') else 'SISO'} | "
216
+ f"n_layers={cfg['n_layers']} | vocab={cfg['vocab_size']}", flush=True)
217
+
218
+ model = HybridLM(cfg, device=dev, dtype=torch.bfloat16)
219
+ miss, unexp = model.load_state_dict(st["model"], strict=False)
220
+ if miss or unexp:
221
+ print(f"[uyarı] eksik={len(miss)} beklenmeyen={len(unexp)} (persistent olmayan buffer normal)", flush=True)
222
+ model.eval()
223
+ print("[hazır] BASE model — metin TAMAMLAR (soru-cevap değil).\n", flush=True)
224
+
225
+ g = lambda p: generate(model, sp, p, args.max_new, args.temperature, args.top_k,
226
+ args.top_p, args.rep_penalty, dev, args.seed)
227
+ if args.prompt is not None:
228
+ print(f"PROMPT: {args.prompt}\nÇIKTI : {g(args.prompt)}")
229
+ else:
230
+ print("İnteraktif — prompt yaz (boş/çık = quit).")
231
+ while True:
232
+ try:
233
+ p = input("\n> ").strip()
234
+ except (EOFError, KeyboardInterrupt):
235
+ break
236
+ if not p or p.lower() in ("quit", "exit", "çık"):
237
+ break
238
+ print(g(p))
239
+
240
+
241
+ if __name__ == "__main__":
242
+ main()