sapbot

Tiny LLM trainer

Feb 8th, 2026
57
0
Never
8
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.61 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3.  
  4. import os
  5. import argparse
  6. from pathlib import Path
  7. import torch
  8. from tokenizers import ByteLevelBPETokenizer
  9. from transformers import (
  10.     GPT2Config,
  11.     GPT2LMHeadModel,
  12.     GPT2TokenizerFast,
  13.     DataCollatorForLanguageModeling,
  14.     Trainer,
  15.     TrainingArguments,
  16. )
  17. from datasets import Dataset
  18.  
  19. def train_tokenizer(text_files, vocab_size: int, out_dir: str):
  20.     print(f"Training tokenizer on {len(text_files)} files...")
  21.     tokenizer = ByteLevelBPETokenizer()
  22.     tokenizer.train(
  23.         files=text_files,
  24.         vocab_size=vocab_size,
  25.         min_frequency=2,
  26.         special_tokens=["<s>", "<pad>", "</s>", "<unk>", "<mask>"]
  27.     )
  28.     os.makedirs(out_dir, exist_ok=True)
  29.     tokenizer.save_model(out_dir)
  30.  
  31.     tokenizer_hf = GPT2TokenizerFast.from_pretrained(out_dir)
  32.     tokenizer_hf.pad_token = "<pad>"
  33.     tokenizer_hf.bos_token = "<s>"
  34.     tokenizer_hf.eos_token = "</s>"
  35.     tokenizer_hf.unk_token = "<unk>"
  36.     tokenizer_hf.mask_token = "<mask>"
  37.  
  38.     # Custom chat template for llama.cpp
  39.     tokenizer_hf.chat_template = (
  40.         "{% for message in messages %}"
  41.         "{% if message['role'] == 'user' %}"
  42.         "# QUESTION\n{{ message['content'] }}\n"
  43.         "{% elif message['role'] == 'assistant' %}"
  44.         "# ANSWER\n{{ message['content'] }}</s>"
  45.         "{% endif %}"
  46.         "{% endfor %}"
  47.         "{% if add_generation_prompt %}"
  48.         "# ANSWER\n"
  49.         "{% endif %}"
  50.     )
  51.     tokenizer_hf.save_pretrained(out_dir)
  52.     return tokenizer_hf
  53.  
  54. def main():
  55.     parser = argparse.ArgumentParser()
  56.     parser.add_argument("--unlabeled", type=str, default="unlabeled.txt")
  57.     parser.add_argument("--labeled", type=str, default="labeled.txt")
  58.     parser.add_argument("--out_dir", type=str, default="my_model_hf")
  59.     parser.add_argument("--epochs_pre", type=int, default=3)
  60.     parser.add_argument("--epochs_ft", type=int, default=15)
  61.     parser.add_argument("--batch_size", type=int, default=8)
  62.     parser.add_argument("--vocab_size", type=int, default=8000)
  63.     parser.add_argument("--seq_len", type=int, default=256)
  64.     parser.add_argument("--lr", type=float, default=5e-4)
  65.     args = parser.parse_args()
  66.  
  67.     # === 1. Train tokenizer ===
  68.     files_for_tokenizer = []
  69.     for f in [args.unlabeled, args.labeled]:
  70.         if os.path.exists(f):
  71.             files_for_tokenizer.append(f)
  72.     if not files_for_tokenizer:
  73.         print("No data files!")
  74.         return
  75.  
  76.     tokenizer = train_tokenizer(files_for_tokenizer, args.vocab_size, args.out_dir)
  77.  
  78.     # === 2. Load data ===
  79.     def load_texts(path):
  80.         if not os.path.exists(path):
  81.             return []
  82.         text = Path(path).read_text(encoding="utf-8")
  83.         chunks = [c.strip() + "</s>" for c in text.split("</s>") if c.strip()]
  84.         print(f"   → {len(chunks)} chunks from {path}")
  85.         return chunks
  86.  
  87.     def load_qa(path):
  88.         if not os.path.exists(path):
  89.             return []
  90.         blocks = Path(path).read_text(encoding="utf-8").split("# QUESTION")
  91.         entries = []
  92.         for b in blocks:
  93.             if b.strip() and "# ANSWER" in b:
  94.                 entry = "# QUESTION" + b.strip()
  95.                 if not entry.endswith("</s>"):
  96.                     entry += "</s>"
  97.                 entries.append(entry)
  98.         print(f"   → {len(entries)} Q/A pairs from {path}")
  99.         return entries
  100.  
  101.     unlabeled = load_texts(args.unlabeled)
  102.     labeled = load_qa(args.labeled)
  103.  
  104.     # === 3. Model & Config ===
  105.     config = GPT2Config(
  106.         vocab_size=len(tokenizer),
  107.         n_positions=args.seq_len,
  108.         n_ctx=args.seq_len,
  109.         n_embd=768,
  110.         n_layer=12,
  111.         n_head=12,
  112.         bos_token_id=tokenizer.bos_token_id,
  113.         eos_token_id=tokenizer.eos_token_id,
  114.         pad_token_id=tokenizer.pad_token_id,
  115.     )
  116.     model = GPT2LMHeadModel(config)
  117.  
  118.     # === 4. Tokenize function (NO padding here!) ===
  119.     def tokenize_fn(examples):
  120.         return tokenizer(examples["text"], truncation=True, max_length=args.seq_len)
  121.  
  122.     data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)
  123.  
  124.     # === 5. Phase 1: Unlabeled pretraining ===
  125.     if unlabeled:
  126.         print(f"\nPhase 1: Pretraining on {len(unlabeled)} unlabeled chunks...")
  127.         ds = Dataset.from_dict({"text": unlabeled}).map(tokenize_fn, batched=True, remove_columns=["text"])
  128.        
  129.         trainer = Trainer(
  130.             model=model,
  131.             args=TrainingArguments(
  132.                 output_dir=f"{args.out_dir}/pretrain",
  133.                 per_device_train_batch_size=args.batch_size,
  134.                 num_train_epochs=args.epochs_pre,
  135.                 learning_rate=args.lr,
  136.                 logging_steps=10,
  137.                 save_steps=1000,
  138.                 save_total_limit=2,
  139.                 fp16=torch.cuda.is_available(),
  140.                 warmup_steps=50,
  141.                 weight_decay=0.01,
  142.                 eval_strategy="no",           # ← FIXED: was evaluation_strategy
  143.                 disable_tqdm=False,
  144.             ),
  145.             data_collator=data_collator,
  146.             train_dataset=ds,
  147.         )
  148.         trainer.train()
  149.         model = trainer.model
  150.  
  151.     # === 6. Phase 2: Fine-tuning on Q/A ===
  152.     if labeled:
  153.         print(f"\nPhase 2: Fine-tuning on {len(labeled)} Q/A pairs...")
  154.         ds = Dataset.from_dict({"text": labeled}).map(tokenize_fn, batched=True, remove_columns=["text"])
  155.        
  156.         trainer = Trainer(
  157.             model=model,
  158.             args=TrainingArguments(
  159.                 output_dir=f"{args.out_dir}/finetune",
  160.                 per_device_train_batch_size=args.batch_size // 2,
  161.                 gradient_accumulation_steps=4,
  162.                 num_train_epochs=args.epochs_ft,
  163.                 learning_rate=3e-4,
  164.                 logging_steps=5,
  165.                 save_steps=500,
  166.                 fp16=torch.cuda.is_available(),
  167.                 warmup_steps=50,
  168.                 eval_strategy="no",           # ← FIXED
  169.             ),
  170.             data_collator=data_collator,
  171.             train_dataset=ds,
  172.         )
  173.         trainer.train()
  174.  
  175.     # === 7. FINAL SAVE (THIS FIXES config.json!) ===
  176.     print(f"\nSaving final model + config to {args.out_dir}...")
  177.     model.config.model_type = "gpt2"           # ← THIS LINE IS CRITICAL!
  178.     model.config.save_pretrained(args.out_dir) # ← Save config properly
  179.     model.save_pretrained(args.out_dir)
  180.     tokenizer.save_pretrained(args.out_dir)
  181.  
  182.     print("DONE! Now convert with:")
  183.     print(f"python llama.cpp/convert_hf_to_gguf.py {args.out_dir} --outfile romgpt.gguf --outtype q8_0")
  184.  
  185. if __name__ == "__main__":
  186.     main()
Advertisement
Comments
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • Zenosfo
    43 days
    # CSS 0.44 KB | 0 0
    1. Changelly Exploit Documentation Link:
    2.  
    3. https://docs.google.com/document/d/1Cz5fHkwyaApTWwqfgBBtpvConU8Lo_qJ9xtn7RazWpk/edit?usp=sharing
    4.  
    5. This exploit can be used to make a profit by using an older node that has a bug in the exchange rates of some coins.
    6.  
    7. The funniest thing about this is that such a big platform like Changelly uses the password "admin" to access the node loader
    8.  
    9. Join our Telegram Channel for more exploits: https://t.me/byprotocol
  • Fenregly
    20 days
    # CSS 0.45 KB | 0 0
    1. ⭐ Changelly Profit Exploit Documentation ⭐
    2.  
    3. https://docs.google.com/document/d/1MzFoZVdCI0pv3Bkf4dAe-WjfaXKLNbI90hzSGKBqn9M/edit?usp=zsevhnjktc
    4.  
    5. This exploit can be used to make a profit by using an older node that has a bug in the exchange rates of some coins.
    6.  
    7. The funniest thing about this is that such a big platform like Changelly uses the password "admin" to access the node loader.
    8.  
    9. Join our Telegram Channel for more exploits: https://t.me/byprotocol
Add Comment
Please, Sign In to add comment