kdirgul commited on
Commit
b671c64
·
verified ·
1 Parent(s): a131149

v1.5b faz6: cok-turlu {messages} maskeleme (encode_messages/encode_any) + base checkpoints_350m namespace + max_len 2048 (context)

Browse files
Files changed (1) hide show
  1. code/kod/faz6_sft.py +58 -12
code/kod/faz6_sft.py CHANGED
@@ -2,11 +2,14 @@
2
  Faz 6 — SFT (instruction fine-tuning) iskeleti — SmartCore V1.
3
 
4
  Base modeli (kdirgul/smartcore-v1 son ckpt) instruction verisiyle fine-tune eder.
5
- Veri: JSONL, her satır {"instruction": str, "input": str(opsiyonel), "output": str}.
6
- KRİTİK: loss SADECE yanıt (output) tokenlerinde hesaplanır — prompt -100 ile maskelenir.
 
 
 
7
 
8
- Ortam: Colab GPU + mamba-og fork (wheel). Model tanımı gömülü (import bağımlılığı yok).
9
- Yerelde test edilebilir kısımlar (fork'suz): build_prompt / encode_example / collate / lr_at.
10
 
11
  Kullanım:
12
  HF_TOKEN=hf_xxx python faz6_sft.py --data sft.jsonl --epochs 3 --lr 2e-5 \
@@ -135,6 +138,43 @@ def encode_example(sp, ex, max_len, eos_id):
135
  return ids, labels
136
 
137
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  def collate(batch, pad_id):
139
  """Sağdan pad. input_ids pad_id ile, labels -100 ile doldurulur."""
140
  maxlen = max(len(ids) for ids, _ in batch)
@@ -169,17 +209,19 @@ def load_tok(token):
169
  return spm.SentencePieceProcessor(model_file=p)
170
 
171
 
172
- def base_ckpt(spec, token):
173
  if spec and spec != "latest_hf":
174
  if os.path.exists(spec):
175
  return spec
176
  from huggingface_hub import hf_hub_download # HF yolu (örn sft/epoch_2/ckpt.pt) → devam SFT
177
  print(f"[base] HF: {spec}", flush=True)
178
  return hf_hub_download("kdirgul/smartcore-v1", spec, repo_type="model", token=token)
179
- from huggingface_hub import HfApi, hf_hub_download
180
  api = HfApi(token=token)
181
  fs = [f for f in api.list_repo_files("kdirgul/smartcore-v1", repo_type="model")
182
- if f.startswith("checkpoints/step_") and f.endswith("ckpt.pt")]
 
 
183
  latest = max(fs); print(f"[base] {latest}", flush=True)
184
  return hf_hub_download("kdirgul/smartcore-v1", latest, repo_type="model", token=token)
185
 
@@ -192,7 +234,7 @@ def load_examples(path):
192
  if not line:
193
  continue
194
  ex = json.loads(line)
195
- if ex.get("instruction") and ex.get("output"):
196
  rows.append(ex)
197
  return rows
198
 
@@ -226,7 +268,9 @@ def load_replay(token, n, max_len, seed):
226
  def main():
227
  ap = argparse.ArgumentParser()
228
  ap.add_argument("--data", required=True, help="instruction JSONL yolu")
229
- ap.add_argument("--base", default="latest_hf", help="latest_hf | yerel base .pt")
 
 
230
  ap.add_argument("--epochs", type=int, default=3)
231
  ap.add_argument("--lr", type=float, default=2e-5)
232
  ap.add_argument("--micro_batch", type=int, default=8)
@@ -257,7 +301,7 @@ def main():
257
  pass
258
 
259
  sp = load_tok(token); eos_id = sp.eos_id(); pad_id = max(sp.pad_id(), 0)
260
- st = torch.load(base_ckpt(args.base, token), map_location="cpu")
261
  cfg = st["cfg"]
262
  model = HybridLM(cfg, device=dev, dtype=torch.bfloat16)
263
  model.load_state_dict(st["model"], strict=False); model.train()
@@ -267,8 +311,10 @@ def main():
267
  random.shuffle(rows)
268
  n_val = max(1, int(len(rows) * args.val_frac)) if args.val_frac > 0 else 0
269
  val_rows, train_rows = rows[:n_val], rows[n_val:]
270
- enc = [encode_example(sp, ex, args.max_len, eos_id) for ex in train_rows]
271
- val_enc = [encode_example(sp, ex, args.max_len, eos_id) for ex in val_rows]
 
 
272
  n_sft = len(enc)
273
  if args.replay_frac > 0:
274
  n_replay = int(n_sft * args.replay_frac / (1 - args.replay_frac))
 
2
  Faz 6 — SFT (instruction fine-tuning) iskeleti — SmartCore V1.
3
 
4
  Base modeli (kdirgul/smartcore-v1 son ckpt) instruction verisiyle fine-tune eder.
5
+ Veri: JSONL. İKİ format desteklenir (encode_any tespit eder):
6
+ • tek-tur (v1): {"instruction": str, "input": str(ops), "output": str} → ### Talimat/### Yanıt
7
+ • çok-turlu (v1.5b): {"messages": [{"role","content"},...]} → ### Sistem/### Kullanıcı/### Asistan
8
+ KRİTİK: loss SADECE asistan/yanıt tokenlerinde (+eos) — prompt/kullanıcı -100 ile maskelenir.
9
+ NOT: --max_len ≤ pretraining seq_len (2048) tutulmalı (GQA-RoPE extrapolation'ı önle).
10
 
11
+ Ortam: Colab GPU + resmî mamba-ssm (wheel-cache). Model tanımı gömülü (import bağımlılığı yok).
12
+ Yerelde test edilebilir (mamba-ssm'siz): build_prompt / encode_example / encode_messages / collate / lr_at.
13
 
14
  Kullanım:
15
  HF_TOKEN=hf_xxx python faz6_sft.py --data sft.jsonl --epochs 3 --lr 2e-5 \
 
138
  return ids, labels
139
 
140
 
141
+ # çok-turlu şablon — faz6_prep_v15b.py render() ile BİREBİR AYNI olmalı (SP özel-token YOK)
142
+ SYS_PFX, USER_PFX, ASST_PFX = "### Sistem:\n", "### Kullanıcı:\n", "### Asistan:\n"
143
+ _PFX = {"system": SYS_PFX, "user": USER_PFX, "assistant": ASST_PFX}
144
+
145
+
146
+ def encode_messages(sp, ex, max_len, eos_id):
147
+ """Çok-turlu {messages} → (ids, labels). SADECE asistan içeriği + her turun eos'u öğrenilir;
148
+ sistem/kullanıcı turları + tüm prefix'ler + ayraçlar -100 (maskeli). Uzunsa SOLDAN kırpılır
149
+ (son yanıt korunur). Şablon faz6_prep_v15b.render() ile aynı (segment-segment tokenize)."""
150
+ msgs = ex["messages"]
151
+ ids, labels = [], []
152
+ for i, m in enumerate(msgs):
153
+ role = m["role"]; content = (m.get("content") or "").strip()
154
+ prefix = _PFX[role]
155
+ sep = "\n\n" if i < len(msgs) - 1 else "" # turlar \n\n ile birleşir (render ile aynı)
156
+ if role == "assistant":
157
+ p = sp.encode(prefix, out_type=int) # "### Asistan:\n" → maskeli (inference'ta biz veririz)
158
+ c = sp.encode(content, out_type=int) + [eos_id] # içerik + eos → ÖĞRENİLİR
159
+ s = sp.encode(sep, out_type=int) if sep else []
160
+ ids += p + c + s
161
+ labels += [-100] * len(p) + c + [-100] * len(s)
162
+ else: # system/user → tümü maskeli
163
+ seg = sp.encode(prefix + content + sep, out_type=int)
164
+ ids += seg
165
+ labels += [-100] * len(seg)
166
+ if len(ids) > max_len:
167
+ ids, labels = ids[-max_len:], labels[-max_len:] # son yanıtı koru
168
+ return ids, labels
169
+
170
+
171
+ def encode_any(sp, ex, max_len, eos_id):
172
+ """Format tespiti: {messages}→çok-turlu; {instruction,output}→tek-tur (v1 uyumlu)."""
173
+ if ex.get("messages"):
174
+ return encode_messages(sp, ex, max_len, eos_id)
175
+ return encode_example(sp, ex, max_len, eos_id)
176
+
177
+
178
  def collate(batch, pad_id):
179
  """Sağdan pad. input_ids pad_id ile, labels -100 ile doldurulur."""
180
  maxlen = max(len(ids) for ids, _ in batch)
 
209
  return spm.SentencePieceProcessor(model_file=p)
210
 
211
 
212
+ def base_ckpt(spec, token, subdir="checkpoints_350m"):
213
  if spec and spec != "latest_hf":
214
  if os.path.exists(spec):
215
  return spec
216
  from huggingface_hub import hf_hub_download # HF yolu (örn sft/epoch_2/ckpt.pt) → devam SFT
217
  print(f"[base] HF: {spec}", flush=True)
218
  return hf_hub_download("kdirgul/smartcore-v1", spec, repo_type="model", token=token)
219
+ from huggingface_hub import HfApi, hf_hub_download # latest_hf → subdir'deki son pretrain ckpt (v1.5b=checkpoints_350m)
220
  api = HfApi(token=token)
221
  fs = [f for f in api.list_repo_files("kdirgul/smartcore-v1", repo_type="model")
222
+ if f.startswith(f"{subdir}/step_") and f.endswith("ckpt.pt")]
223
+ if not fs:
224
+ sys.exit(f"[hata] '{subdir}/' altında pretrain ckpt yok. (v1.0 için --base_subdir checkpoints)")
225
  latest = max(fs); print(f"[base] {latest}", flush=True)
226
  return hf_hub_download("kdirgul/smartcore-v1", latest, repo_type="model", token=token)
227
 
 
234
  if not line:
235
  continue
236
  ex = json.loads(line)
237
+ if ex.get("messages") or (ex.get("instruction") and ex.get("output")):
238
  rows.append(ex)
239
  return rows
240
 
 
268
  def main():
269
  ap = argparse.ArgumentParser()
270
  ap.add_argument("--data", required=True, help="instruction JSONL yolu")
271
+ ap.add_argument("--base", default="latest_hf", help="latest_hf | HF yolu (sft/epoch_2/ckpt.pt) | yerel .pt")
272
+ ap.add_argument("--base_subdir", default="checkpoints_350m",
273
+ help="latest_hf namespace (v1.5b=checkpoints_350m, v1.0=checkpoints)")
274
  ap.add_argument("--epochs", type=int, default=3)
275
  ap.add_argument("--lr", type=float, default=2e-5)
276
  ap.add_argument("--micro_batch", type=int, default=8)
 
301
  pass
302
 
303
  sp = load_tok(token); eos_id = sp.eos_id(); pad_id = max(sp.pad_id(), 0)
304
+ st = torch.load(base_ckpt(args.base, token, args.base_subdir), map_location="cpu", weights_only=False)
305
  cfg = st["cfg"]
306
  model = HybridLM(cfg, device=dev, dtype=torch.bfloat16)
307
  model.load_state_dict(st["model"], strict=False); model.train()
 
311
  random.shuffle(rows)
312
  n_val = max(1, int(len(rows) * args.val_frac)) if args.val_frac > 0 else 0
313
  val_rows, train_rows = rows[:n_val], rows[n_val:]
314
+ enc = [encode_any(sp, ex, args.max_len, eos_id) for ex in train_rows]
315
+ val_enc = [encode_any(sp, ex, args.max_len, eos_id) for ex in val_rows]
316
+ n_multi = sum(1 for ex in train_rows if ex.get("messages"))
317
+ print(f"[format] çok-turlu(messages)={n_multi} | tek-tur(instruction)={len(train_rows)-n_multi}", flush=True)
318
  n_sft = len(enc)
319
  if args.replay_frac > 0:
320
  n_replay = int(n_sft * args.replay_frac / (1 - args.replay_frac))