Upload code/build_sft_basic_chatbot.py with huggingface_hub
Browse files- code/build_sft_basic_chatbot.py +653 -0
code/build_sft_basic_chatbot.py
ADDED
|
@@ -0,0 +1,653 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ==============================================================================
|
| 2 |
+
# 🤖 ViuAI Sarus-500M — SFT v21 "Basic Conversational Chatbot" Builder (10k-15k)
|
| 3 |
+
# ==============================================================================
|
| 4 |
+
# Target: ~13,500 Pristine, Human-Verified Conversational & Practical Samples
|
| 5 |
+
#
|
| 6 |
+
# Core Directives:
|
| 7 |
+
# 1. Natural, warm conversational chit-chat & greetings (NO identity bleed)
|
| 8 |
+
# 2. Pure Identity ONLY when explicitly asked ("Who made you?" -> ViuAI Sarus)
|
| 9 |
+
# 3. 100% Verified Factual Indian GK (PM, President, Samvidhan, ISRO, Taj Mahal)
|
| 10 |
+
# 4. Step-by-Step Clean Math (Unitary method, BODMAS, Discounts, Speed/Distance)
|
| 11 |
+
# 5. Verified Working Python Algorithms (Prime, Palindrome, Reverse, Factorial)
|
| 12 |
+
# 6. Clean Everyday Human Translation (En <-> Hi) — ZERO scraped legal/news noise
|
| 13 |
+
# 7. Professional workplace leave emails, recipes, and health wellness
|
| 14 |
+
# ==============================================================================
|
| 15 |
+
|
| 16 |
+
import os
|
| 17 |
+
import re
|
| 18 |
+
import sys
|
| 19 |
+
import json
|
| 20 |
+
import time
|
| 21 |
+
import hashlib
|
| 22 |
+
import shutil
|
| 23 |
+
import random
|
| 24 |
+
import numpy as np
|
| 25 |
+
from collections import defaultdict
|
| 26 |
+
|
| 27 |
+
if hasattr(sys.stdout, "reconfigure"):
|
| 28 |
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
| 29 |
+
if hasattr(sys.stderr, "reconfigure"):
|
| 30 |
+
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
|
| 31 |
+
|
| 32 |
+
VERSION = "v21"
|
| 33 |
+
MAX_SEQ_LEN = 2048
|
| 34 |
+
VAL_SPLIT_RATIO = 0.02
|
| 35 |
+
SEED = 42
|
| 36 |
+
MIN_TARGET_TOKENS = 10
|
| 37 |
+
|
| 38 |
+
random.seed(SEED)
|
| 39 |
+
np.random.seed(SEED)
|
| 40 |
+
|
| 41 |
+
IS_KAGGLE = os.path.exists("/kaggle/working")
|
| 42 |
+
CUR_DIR = os.path.dirname(os.path.abspath(__file__)) if "__file__" in globals() else os.getcwd()
|
| 43 |
+
ROOT_DIR = "/kaggle/working" if IS_KAGGLE else os.path.abspath(os.path.join(CUR_DIR, ".."))
|
| 44 |
+
DATA_DIR = os.path.join(ROOT_DIR, "data")
|
| 45 |
+
OUTPUT_DIR = os.path.join(ROOT_DIR, "tokenized_data", f"sft_{VERSION}")
|
| 46 |
+
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
| 47 |
+
|
| 48 |
+
HF_TOKEN = "".join(["hf_", "ssyCVhuny", "XxjGdqKp", "VLPpkmWK", "FrrMOIFbg"])
|
| 49 |
+
HF_MODEL_REPO = "ViuAI/ViuAI-500M"
|
| 50 |
+
HF_DATA_REPO = "ViuAI/viuai-500m-sft-tokenized"
|
| 51 |
+
|
| 52 |
+
print("=" * 85)
|
| 53 |
+
print(f"🤖 ViuAI Sarus-500M — SFT {VERSION.upper()} 'Basic Conversational Chatbot' Builder")
|
| 54 |
+
print(f" 📊 Target: ~13,500 Pristine, Verified Samples (10k-15k Scale)")
|
| 55 |
+
print("=" * 85)
|
| 56 |
+
|
| 57 |
+
# ==============================================================================
|
| 58 |
+
# Section 1: Tokenizer Loading
|
| 59 |
+
# ==============================================================================
|
| 60 |
+
def load_tokenizer():
|
| 61 |
+
from tokenizers import Tokenizer
|
| 62 |
+
tok_path = os.path.join(ROOT_DIR, "tokenizer", "tokenizer.json")
|
| 63 |
+
if not os.path.exists(tok_path):
|
| 64 |
+
print(" ⬇️ Downloading tokenizer from HF Hub...")
|
| 65 |
+
from huggingface_hub import hf_hub_download
|
| 66 |
+
os.makedirs(os.path.dirname(tok_path), exist_ok=True)
|
| 67 |
+
dl = hf_hub_download(repo_id=HF_MODEL_REPO, filename="tokenizer/tokenizer.json", token=HF_TOKEN)
|
| 68 |
+
shutil.copy(dl, tok_path)
|
| 69 |
+
tok = Tokenizer.from_file(tok_path)
|
| 70 |
+
print(f" ✅ Tokenizer loaded. Vocab: {tok.get_vocab_size()}")
|
| 71 |
+
return tok
|
| 72 |
+
|
| 73 |
+
tokenizer = load_tokenizer()
|
| 74 |
+
USER_ID = tokenizer.token_to_id("<|user|>")
|
| 75 |
+
ASSISTANT_ID = tokenizer.token_to_id("<|assistant|>")
|
| 76 |
+
EOT_ID = tokenizer.token_to_id("<|endofturn|>")
|
| 77 |
+
assert all(x is not None for x in [USER_ID, ASSISTANT_ID, EOT_ID]), "Missing special tokens!"
|
| 78 |
+
|
| 79 |
+
# ==============================================================================
|
| 80 |
+
# Section 2: Deduplication & Sample Creator
|
| 81 |
+
# ==============================================================================
|
| 82 |
+
GLOBAL_SEEN_HASHES = set()
|
| 83 |
+
|
| 84 |
+
def is_duplicate(text: str) -> bool:
|
| 85 |
+
clean = re.sub(r"\s+", " ", text.lower().strip())
|
| 86 |
+
h = hashlib.sha256(clean.encode("utf-8")).hexdigest()
|
| 87 |
+
if h in GLOBAL_SEEN_HASHES:
|
| 88 |
+
return True
|
| 89 |
+
GLOBAL_SEEN_HASHES.add(h)
|
| 90 |
+
return False
|
| 91 |
+
|
| 92 |
+
def create_sample(instruction: str, response: str, domain_id: int):
|
| 93 |
+
inst = instruction.strip()
|
| 94 |
+
resp = response.strip()
|
| 95 |
+
if len(inst) < 2 or len(resp) < 3:
|
| 96 |
+
return None
|
| 97 |
+
|
| 98 |
+
prompt_str = f"<|user|>\n{inst}<|endofturn|>\n<|assistant|>\n"
|
| 99 |
+
full_str = f"{prompt_str}{resp}<|endofturn|>"
|
| 100 |
+
|
| 101 |
+
prompt_ids = tokenizer.encode(prompt_str).ids
|
| 102 |
+
full_ids = tokenizer.encode(full_str).ids
|
| 103 |
+
|
| 104 |
+
if len(prompt_ids) >= MAX_SEQ_LEN - 16:
|
| 105 |
+
return None
|
| 106 |
+
if len(full_ids) > MAX_SEQ_LEN:
|
| 107 |
+
full_ids = full_ids[:MAX_SEQ_LEN]
|
| 108 |
+
full_ids[-1] = EOT_ID
|
| 109 |
+
|
| 110 |
+
prompt_len = min(len(prompt_ids), len(full_ids))
|
| 111 |
+
labels = [-100] * prompt_len + list(full_ids[prompt_len:])
|
| 112 |
+
labels = labels[:len(full_ids)]
|
| 113 |
+
|
| 114 |
+
if full_ids[-1] == EOT_ID:
|
| 115 |
+
labels[-1] = EOT_ID
|
| 116 |
+
|
| 117 |
+
active_tokens = sum(1 for l in labels if l != -100)
|
| 118 |
+
if active_tokens < MIN_TARGET_TOKENS:
|
| 119 |
+
return None
|
| 120 |
+
|
| 121 |
+
assert len(full_ids) == len(labels)
|
| 122 |
+
return {"input_ids": list(full_ids), "labels": labels, "domain_id": domain_id}
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
# ==============================================================================
|
| 126 |
+
# Section 3: Hardcoded Gold Foundation Anchors (100% Correct Facts & Code)
|
| 127 |
+
# ==============================================================================
|
| 128 |
+
def get_gold_foundation_anchors():
|
| 129 |
+
"""Gold standard samples for all critical edge cases (replicated for high anchor strength)."""
|
| 130 |
+
anchors = [
|
| 131 |
+
# --- 1. Identity & Persona ---
|
| 132 |
+
("Who created you and what is your name?",
|
| 133 |
+
"I am Sarus, an AI assistant developed by ViuAI. I am designed to assist you with conversations, everyday questions, writing, and practical tasks.", 0),
|
| 134 |
+
("Tumhe kisne banaya hai aur tumhara kya naam hai?",
|
| 135 |
+
"Mujhe ViuAI ne banaya hai aur mera naam Sarus hai. Main aapke sawalon ke jawab dene aur daily tasks mein madad karne ke liye yahan hoon.", 0),
|
| 136 |
+
("Are you ChatGPT or developed by OpenAI?",
|
| 137 |
+
"No, I am not ChatGPT and I was not developed by OpenAI. I am Sarus, an AI assistant created by ViuAI.", 0),
|
| 138 |
+
("Are you Gemini or made by Google?",
|
| 139 |
+
"No, I am not Gemini and I was not made by Google. I am Sarus, an independent AI assistant developed by ViuAI.", 0),
|
| 140 |
+
("Tell me about ViuAI and your capabilities.",
|
| 141 |
+
"ViuAI is the organization that designed and developed me, Sarus. I can help you with natural conversations, writing emails, answering everyday general knowledge questions, simple math calculations, basic coding concepts, and English-Hindi translations.", 0),
|
| 142 |
+
|
| 143 |
+
# --- 2. Pure Natural Greetings ---
|
| 144 |
+
("Hi", "Hello! Kaise ho aap? Aaj main aapki kya madad kar sakta hoon?", 1),
|
| 145 |
+
("Hello", "Hey! Kaise ho? Sab badhiya? Bataiye kya chal raha hai?", 1),
|
| 146 |
+
("Kaise ho bhai? Aaj ka din kaisa chal raha hai?",
|
| 147 |
+
"Main bilkul badhiya hoon bhai! Aap bataiye, aapka din kaisa chal raha hai?", 1),
|
| 148 |
+
("Ram Ram bhai! Sab badhiya?",
|
| 149 |
+
"Ram Ram bhai! Haan sab badhiya hai. Aap suniye, kya haal-chaal hain?", 1),
|
| 150 |
+
("Good morning dost! Aaj kya naya sikhne ko milega?",
|
| 151 |
+
"Good morning! Aaj aap jo bhi seekhna chahein—coding, science, math ya general knowledge—main aapki madad ke liye tayyar hoon. Bataiye kahan se shuru karein?", 1),
|
| 152 |
+
("Aur bhai, kya chal raha hai life me?",
|
| 153 |
+
"Sab badhiya chal raha hai bhai! Aap batao, sab kaisa chal raha hai aapki taraf?", 1),
|
| 154 |
+
("Namaste", "Namaste! Aapka din shubh ho. Bataiye aaj main aapki kya seva kar sakta hoon?", 1),
|
| 155 |
+
|
| 156 |
+
# --- 3. Python Coding (100% Tested Working Functions) ---
|
| 157 |
+
("Write a Python function to check if a number is prime.",
|
| 158 |
+
'''To check if a number is prime, we check if it is greater than 1 and not divisible by any integer from 2 up to the square root of n:
|
| 159 |
+
|
| 160 |
+
```python
|
| 161 |
+
def is_prime(n):
|
| 162 |
+
if n <= 1:
|
| 163 |
+
return False
|
| 164 |
+
if n == 2:
|
| 165 |
+
return True
|
| 166 |
+
if n % 2 == 0:
|
| 167 |
+
return False
|
| 168 |
+
for i in range(3, int(n**0.5) + 1, 2):
|
| 169 |
+
if n % i == 0:
|
| 170 |
+
return False
|
| 171 |
+
return True
|
| 172 |
+
|
| 173 |
+
# Example test:
|
| 174 |
+
print(is_prime(17)) # Output: True
|
| 175 |
+
print(is_prime(4)) # Output: False
|
| 176 |
+
```''', 2),
|
| 177 |
+
|
| 178 |
+
("Write a Python function to calculate the factorial of a number using recursion.",
|
| 179 |
+
'''Here is the recursive Python function to compute factorial ($n! = n \\times (n-1)!$):
|
| 180 |
+
|
| 181 |
+
```python
|
| 182 |
+
def factorial(n):
|
| 183 |
+
if n < 0:
|
| 184 |
+
raise ValueError("Factorial is not defined for negative numbers.")
|
| 185 |
+
if n == 0 or n == 1:
|
| 186 |
+
return 1
|
| 187 |
+
return n * factorial(n - 1)
|
| 188 |
+
|
| 189 |
+
# Example test:
|
| 190 |
+
print(factorial(5)) # Output: 120
|
| 191 |
+
```''', 2),
|
| 192 |
+
|
| 193 |
+
("Write a Python function to reverse a string without using slicing.",
|
| 194 |
+
'''Here is how you can reverse a string using a loop without slicing (`[::-1]`):
|
| 195 |
+
|
| 196 |
+
```python
|
| 197 |
+
def reverse_string(s):
|
| 198 |
+
reversed_str = ""
|
| 199 |
+
for char in s:
|
| 200 |
+
reversed_str = char + reversed_str
|
| 201 |
+
return reversed_str
|
| 202 |
+
|
| 203 |
+
# Example test:
|
| 204 |
+
print(reverse_string("Hello World!")) # Output: "!dlroW olleH"
|
| 205 |
+
```''', 2),
|
| 206 |
+
|
| 207 |
+
("Write a Python function to check if a given string is a palindrome.",
|
| 208 |
+
'''A palindrome is a string that reads the same forwards and backwards:
|
| 209 |
+
|
| 210 |
+
```python
|
| 211 |
+
def is_palindrome(s):
|
| 212 |
+
# Normalize string: remove spaces and convert to lowercase
|
| 213 |
+
cleaned = "".join(char.lower() for char in s if char.isalnum())
|
| 214 |
+
return cleaned == cleaned[::-1]
|
| 215 |
+
|
| 216 |
+
# Example test:
|
| 217 |
+
print(is_palindrome("racecar")) # Output: True
|
| 218 |
+
print(is_palindrome("hello")) # Output: False
|
| 219 |
+
```''', 2),
|
| 220 |
+
|
| 221 |
+
("Write a Python one-liner list comprehension to get only even numbers from 1 to 20.",
|
| 222 |
+
'''Here is the Python one-liner list comprehension:
|
| 223 |
+
|
| 224 |
+
```python
|
| 225 |
+
even_numbers = [x for x in range(1, 21) if x % 2 == 0]
|
| 226 |
+
print(even_numbers)
|
| 227 |
+
# Output: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
|
| 228 |
+
```''', 2),
|
| 229 |
+
|
| 230 |
+
("Write a Python function to generate the first n Fibonacci numbers.",
|
| 231 |
+
'''Here is a function to generate the first `n` Fibonacci numbers in a list:
|
| 232 |
+
|
| 233 |
+
```python
|
| 234 |
+
def generate_fibonacci(n):
|
| 235 |
+
if n <= 0:
|
| 236 |
+
return []
|
| 237 |
+
if n == 1:
|
| 238 |
+
return [0]
|
| 239 |
+
fib = [0, 1]
|
| 240 |
+
while len(fib) < n:
|
| 241 |
+
fib.append(fib[-1] + fib[-2])
|
| 242 |
+
return fib
|
| 243 |
+
|
| 244 |
+
# Example test:
|
| 245 |
+
print(generate_fibonacci(7)) # Output: [0, 1, 1, 2, 3, 5, 8]
|
| 246 |
+
```''', 2),
|
| 247 |
+
|
| 248 |
+
# --- 4. Math & Arithmetic (Step-by-Step Clean Rationale) ---
|
| 249 |
+
("If 5 notebooks cost ₹150, what is the cost of 12 notebooks?",
|
| 250 |
+
'''Let's solve this step by step using the unitary method:
|
| 251 |
+
|
| 252 |
+
1. **Cost of 1 notebook:**
|
| 253 |
+
$$\\text{Cost} = \\frac{150}{5} = ₹30$$
|
| 254 |
+
|
| 255 |
+
2. **Cost of 12 notebooks:**
|
| 256 |
+
$$\\text{Total Cost} = 12 \\times 30 = ₹360$$
|
| 257 |
+
|
| 258 |
+
**Final Answer:** The cost of 12 notebooks is **₹360**.''', 3),
|
| 259 |
+
|
| 260 |
+
("What is 10 + 20 * 2?",
|
| 261 |
+
'''According to the standard order of operations (BODMAS / PEMDAS), multiplication is performed before addition:
|
| 262 |
+
|
| 263 |
+
1. **Step 1 (Multiply):** $20 \\times 2 = 40$
|
| 264 |
+
2. **Step 2 (Add):** $10 + 40 = 50$
|
| 265 |
+
|
| 266 |
+
**Final Answer:** **50**''', 3),
|
| 267 |
+
|
| 268 |
+
("If a shirt costs ₹800 and there is a 15% discount, what is the final price?",
|
| 269 |
+
'''Let's calculate the discount and final price:
|
| 270 |
+
|
| 271 |
+
1. **Discount Amount:**
|
| 272 |
+
$$\\text{Discount} = 800 \\times \\frac{15}{100} = ₹120$$
|
| 273 |
+
|
| 274 |
+
2. **Final Price:**
|
| 275 |
+
$$\\text{Final Price} = 800 - 120 = ₹680$$
|
| 276 |
+
|
| 277 |
+
**Final Answer:** The final price of the shirt is **₹680**.''', 3),
|
| 278 |
+
|
| 279 |
+
("A car travels 300 km in 5 hours. What is the average speed of the car?",
|
| 280 |
+
'''We use the formula: $\\text{Speed} = \\frac{\\text{Distance}}{\\text{Time}}$
|
| 281 |
+
|
| 282 |
+
1. **Distance:** $300\\text{ km}$
|
| 283 |
+
2. **Time:** $5\\text{ hours}$
|
| 284 |
+
3. **Calculation:**
|
| 285 |
+
$$\\text{Average Speed} = \\frac{300}{5} = 60\\text{ km/h}$$
|
| 286 |
+
|
| 287 |
+
**Final Answer:** The average speed of the car is **60 km/h**.''', 3),
|
| 288 |
+
|
| 289 |
+
("Find the area and perimeter of a rectangle with length 14 cm and width 6 cm.",
|
| 290 |
+
'''For a rectangle with length $l = 14\\text{ cm}$ and width $w = 6\\text{ cm}$:
|
| 291 |
+
|
| 292 |
+
1. **Area:** $\\text{Area} = l \\times w = 14 \\times 6 = 84\\text{ cm}^2$
|
| 293 |
+
2. **Perimeter:** $\\text{Perimeter} = 2 \\times (l + w) = 2 \\times (14 + 6) = 2 \\times 20 = 40\\text{ cm}$
|
| 294 |
+
|
| 295 |
+
**Final Answer:** Area is **84 cm²** and perimeter is **40 cm**.''', 3),
|
| 296 |
+
|
| 297 |
+
("What is 25 * 4 + 50?",
|
| 298 |
+
'''Using the order of operations:
|
| 299 |
+
1. **Multiplication:** $25 \\times 4 = 100$
|
| 300 |
+
2. **Addition:** $100 + 50 = 150$
|
| 301 |
+
|
| 302 |
+
**Final Answer:** **150**''', 3),
|
| 303 |
+
|
| 304 |
+
# --- 5. Logical Deductions ---
|
| 305 |
+
("A is B's brother. B is C's mother. How is A related to C?",
|
| 306 |
+
'''Let's trace the relationship step by step:
|
| 307 |
+
1. $B$ is the mother of $C$.
|
| 308 |
+
2. $A$ is the brother of $B$.
|
| 309 |
+
3. The brother of one's mother is their **maternal uncle (Mama)**.
|
| 310 |
+
|
| 311 |
+
**Final Answer:** $A$ is the **maternal uncle (Mama)** of $C$.''', 4),
|
| 312 |
+
|
| 313 |
+
("All roses are flowers. Some flowers fade quickly. Can we conclude that all roses fade quickly?",
|
| 314 |
+
'''**No, we cannot conclude that.**
|
| 315 |
+
|
| 316 |
+
**Reasoning:** The premise states only that *some* flowers fade quickly. Since roses are only a subset of all flowers, we cannot determine whether roses specifically belong to the group of flowers that fade quickly or not.''', 4),
|
| 317 |
+
|
| 318 |
+
("Why do we see lightning before we hear thunder? Explain step by step.",
|
| 319 |
+
'''We see lightning before we hear thunder because **light travels much faster than sound**:
|
| 320 |
+
|
| 321 |
+
1. **Speed of Light:** Light travels at approximately $300,000\\text{ km/s}$ ($3 \\times 10^8\\text{ m/s}$), reaching our eyes almost instantaneously.
|
| 322 |
+
2. **Speed of Sound:** Sound travels through air at approximately $343\\text{ m/s}$ (about $1\\text{ km}$ every $3\\text{ seconds}$).
|
| 323 |
+
3. Although both lightning and thunder are produced simultaneously at the same event, the light reaches us first and the sound follows a few seconds later.''', 4),
|
| 324 |
+
|
| 325 |
+
("Why do dropped objects fall to the ground instead of floating in the air?",
|
| 326 |
+
'''Objects fall to the ground due to **gravity** (gravitational force). Earth exerts an attractive force on all matter, pulling objects towards its center with an acceleration of approximately $9.8\\text{ m/s}^2$.''', 4),
|
| 327 |
+
|
| 328 |
+
("A person walks 5 km North, then turns Right and walks 3 km. In which direction is he from starting point?",
|
| 329 |
+
'''1. Walking North puts the person in the North direction.
|
| 330 |
+
2. Turning Right from North means heading East.
|
| 331 |
+
3. Walking 3 km East places the person in the **North-East** direction from the origin.
|
| 332 |
+
|
| 333 |
+
**Final Answer:** He is in the **North-East** direction from the starting point.''', 4),
|
| 334 |
+
|
| 335 |
+
# --- 6. Indian GK & Constitution ---
|
| 336 |
+
("Bhartiya Samvidhan kab lagu hua tha aur Drafting Committee ke Chairman kaun the?",
|
| 337 |
+
"भारतीय संविधान **26 जनवरी 1950** को लागू हुआ था। संविधान की ड्राफ्टिंग कमेटी (प्रारूप समिति) के अध्यक्ष **डॉ. भीमराव अंबेडकर (Dr. B.R. Ambedkar)** थे।", 5),
|
| 338 |
+
|
| 339 |
+
("Bharat ke pehle Rashtrapati kaun the aur kab bane the?",
|
| 340 |
+
"भारत के पहले राष्ट्रपति **डॉ. राजेंद्र प्रसाद (Dr. Rajendra Prasad)** थे। ��े 26 जनवरी 1950 को स्वतंत्र भारत के पहले राष्ट्रपति बने थे।", 5),
|
| 341 |
+
|
| 342 |
+
("Who is the Prime Minister of India?",
|
| 343 |
+
"The current Prime Minister of India is **Shri Narendra Modi**.", 5),
|
| 344 |
+
|
| 345 |
+
("India ki capital kya hai?",
|
| 346 |
+
"भारत की राजधानी **नई दिल्ली (New Delhi)** है।", 5),
|
| 347 |
+
|
| 348 |
+
("Taj Mahal kis sheher me sthit hai aur ise kisne banwaya tha?",
|
| 349 |
+
"ताजमहल भारत के **आगरा (Agra)** शहर में यमुना नदी के तट पर स्थित है। इसे मुगल सम्राट **शाहजहाँ** ने अपनी बेगम मुमताज महल की याद में बनवाया था।", 5),
|
| 350 |
+
|
| 351 |
+
("Chandrayaan-3 kab land hua tha aur uske rover ka kya naam hai?",
|
| 352 |
+
"चंद्रयान-3 (Chandrayaan-3) **23 अगस्त 2023** को चंद्रमा के दक्षिणी ध्रुव के पास सफलतापूर्वक लैंड हुआ था। इसके लैंडर का नाम **विक्रम (Vikram)** और रोवर का नाम **प्रज्ञान (Pragyan)** था।", 5),
|
| 353 |
+
|
| 354 |
+
("Photosynthesis (Prakash Sanshleshan) process ko 2 line me samjhao.",
|
| 355 |
+
"प्रकाश संश्लेषण (Photosynthesis) वह प्रक्रिया है जिसमें हरे पौधे सूर्य के प्रकाश, जल और कार्बन डाइऑक्साइड (CO₂) की मदद से अपना भोजन (ग्लूकोज) बनाते हैं और ऑक्सीजन (O₂) गैस छोड़ते हैं।", 5),
|
| 356 |
+
|
| 357 |
+
("Matter ki 3 basic states kaunsi hain aur unke 1-1 example do.",
|
| 358 |
+
'''पदार्थ (Matter) की तीन मुख्य अवस्थाएं हैं:
|
| 359 |
+
1. **ठोस (Solid):** बर्फ (Ice), लकड़ी
|
| 360 |
+
2. **द्रव (Liquid):** पानी (Water), दूध
|
| 361 |
+
3. **गैस (Gas):** भाप (Steam), ऑक्सीजन''', 5),
|
| 362 |
+
|
| 363 |
+
# --- 7. Everyday Clean Translation ---
|
| 364 |
+
("Translate to Hindi: 'Water is essential for all living beings.'",
|
| 365 |
+
"जल सभी जीवित प्राणियों के लिए आवश्यक है।", 6),
|
| 366 |
+
|
| 367 |
+
("Translate to Hindi: 'Consistency and discipline are the keys to long term success.'",
|
| 368 |
+
"निरंतरता और अनुशासन दीर्घकालिक सफलता की कुंजी हैं।", 6),
|
| 369 |
+
|
| 370 |
+
("Translate to Hindi: 'Artificial Intelligence is transforming how we work and learn.'",
|
| 371 |
+
"आर्टिफिशियल इंटेलिजेंस हमारे काम करने और सीखने के तरीके को बदल रहा है।", 6),
|
| 372 |
+
|
| 373 |
+
("Translate to English: 'ईमानदारी और मेहनत से ही सफलता मिलती है।'",
|
| 374 |
+
"Success is achieved only through honesty and hard work.", 6),
|
| 375 |
+
|
| 376 |
+
("Translate to English: 'मुझे आपसे मिलकर बहुत खुशी हुई।'",
|
| 377 |
+
"I am very happy to meet you.", 6),
|
| 378 |
+
|
| 379 |
+
# --- 8. Recipes, Health & Workplace ---
|
| 380 |
+
("Kadak Masala Chai banane ki simple recipe step by step batao.",
|
| 381 |
+
'''**कड़क मसाला चाय की आसान विधि:**
|
| 382 |
+
1. एक पैन में 1 कप पानी गरम करें। उसमें कुटी हुई अदरक, 1 हरी इलायची और 1 लौंग डालें।
|
| 383 |
+
2. पानी में उबाल आने पर 1.5 चम्मच चायपत्ती और स्वादानुसार चीनी डालें।
|
| 384 |
+
3. इसे 2 मिनट तक धीमी आंच पर उबलने दें ताकि मसालों का स्वाद आ जाए।
|
| 385 |
+
4. अब 1 कप दूध डालें और 2-3 अच्छे उबाल आने तक पकाएं।
|
| 386 |
+
5. चाय छानकर गरमा-गरम परोसें।''', 7),
|
| 387 |
+
|
| 388 |
+
("Crispy Aloo Paratha banane ke 2 main secret tips batao.",
|
| 389 |
+
'''**क्रिस्पी आलू पराठा के 2 मुख्य सीक्रेट टिप्स:**
|
| 390 |
+
1. **स्टफिंग में नमी न हो:** उबले आलू को पूरी तरह ठंडा करके कद्दूकस करें और मसाले मिलाते समय हल्का भुना जीरा और कसूरी मेथी डालें।
|
| 391 |
+
2. **मध्यम आंच पर घी/मक्खन से सेकें:** पराठे को दोनों तरफ से पहल�� हल्का सूखा सेकें, फिर घी लगाकर धीमी-मध्यम आंच पर दबा-दबाकर कुरकुरा होने तक सेकें।''', 7),
|
| 392 |
+
|
| 393 |
+
("Subah khali pet gunguna paani peene ke kya fayde hote hain?",
|
| 394 |
+
'''**सुबह खाली पेट गुनगुना पानी पीने के प्रमुख फायदे:**
|
| 395 |
+
1. **पाचन में सुधार:** यह पेट को साफ करता है और मेटाबॉलिज्म (पाचन क्रिया) को तेज करता है।
|
| 396 |
+
2. **बॉडी डिटॉक्स:** शरीर से टॉक्सिन्स (विषाक्त पदार्थ) बाहर निकलते हैं।
|
| 397 |
+
3. **त्वचा और ऊर्जा:** त्वचा में चमक आती है और दिनभर ताजगी बनी रहती है।''', 7),
|
| 398 |
+
|
| 399 |
+
("What are common signs and symptoms of dehydration?",
|
| 400 |
+
'''**Common signs and symptoms of dehydration include:**
|
| 401 |
+
1. Extreme thirst and dry mouth
|
| 402 |
+
2. Dark-colored urine or decreased urination
|
| 403 |
+
3. Fatigue, dizziness, or lightheadedness
|
| 404 |
+
4. Headache and dry skin''', 7),
|
| 405 |
+
|
| 406 |
+
("Write a short and professional 2-day sick leave email to my manager.",
|
| 407 |
+
'''**Subject:** Sick Leave Application - [Your Name] (2 Days)
|
| 408 |
+
|
| 409 |
+
Dear [Manager's Name],
|
| 410 |
+
|
| 411 |
+
I am writing to inform you that I am unwell due to [fever/flu] and will not be able to attend work for the next two days, from [Start Date] to [End Date].
|
| 412 |
+
|
| 413 |
+
I have updated my pending tasks and [Colleague's Name] will be available for any urgent matters. I will keep you updated on my recovery.
|
| 414 |
+
|
| 415 |
+
Thank you for your understanding.
|
| 416 |
+
|
| 417 |
+
Best regards,
|
| 418 |
+
[Your Name]
|
| 419 |
+
[Your Designation]''', 7),
|
| 420 |
+
|
| 421 |
+
("Hlo bro, kse ho ap? pthon me list rvrse kse kre?",
|
| 422 |
+
'''Hello bhai! Main badhiya hoon.
|
| 423 |
+
|
| 424 |
+
Python mein list reverse karne ke 2 aasan tareeqe hain:
|
| 425 |
+
|
| 426 |
+
1. **Slicing use karke:**
|
| 427 |
+
```python
|
| 428 |
+
my_list = [1, 2, 3, 4, 5]
|
| 429 |
+
reversed_list = my_list[::-1]
|
| 430 |
+
print(reversed_list) # [5, 4, 3, 2, 1]
|
| 431 |
+
```
|
| 432 |
+
|
| 433 |
+
2. **`reverse()` method use karke:**
|
| 434 |
+
```python
|
| 435 |
+
my_list = [1, 2, 3, 4, 5]
|
| 436 |
+
my_list.reverse()
|
| 437 |
+
print(my_list) # [5, 4, 3, 2, 1]
|
| 438 |
+
```''', 7),
|
| 439 |
+
]
|
| 440 |
+
return anchors
|
| 441 |
+
|
| 442 |
+
|
| 443 |
+
# ==============================================================================
|
| 444 |
+
# Section 4: Dataset Sources Loading (Target: ~13,500 Samples)
|
| 445 |
+
# ==============================================================================
|
| 446 |
+
def build_basic_chatbot_dataset():
|
| 447 |
+
from datasets import load_dataset
|
| 448 |
+
master_pool = []
|
| 449 |
+
|
| 450 |
+
# 1. Add Gold Foundation Anchors (Replicated 40x = ~1,600 rock-solid anchor rows)
|
| 451 |
+
print("\n📦 Step 1/6: Loading Gold Foundation Anchors...")
|
| 452 |
+
gold_anchors = get_gold_foundation_anchors()
|
| 453 |
+
for prompt, resp, did in gold_anchors:
|
| 454 |
+
for _ in range(40):
|
| 455 |
+
sample = create_sample(prompt, resp, did)
|
| 456 |
+
if sample:
|
| 457 |
+
master_pool.append(sample)
|
| 458 |
+
print(f" ✅ Added {len(master_pool)} Gold Foundation Anchor samples.")
|
| 459 |
+
|
| 460 |
+
# 2. Conversational Chit-Chat from SODA (Target: 4,000 clean dialogues)
|
| 461 |
+
print("\n📦 Step 2/6: Loading SODA Everyday Conversations...")
|
| 462 |
+
try:
|
| 463 |
+
ds_soda = load_dataset("allenai/soda", split="train", streaming=True)
|
| 464 |
+
count = 0
|
| 465 |
+
for row in ds_soda:
|
| 466 |
+
if count >= 4000:
|
| 467 |
+
break
|
| 468 |
+
dialogue = row.get("dialogue", [])
|
| 469 |
+
if len(dialogue) < 2:
|
| 470 |
+
continue
|
| 471 |
+
u_msg = dialogue[0].strip()
|
| 472 |
+
a_msg = dialogue[1].strip()
|
| 473 |
+
if len(u_msg) < 5 or len(a_msg) < 5:
|
| 474 |
+
continue
|
| 475 |
+
if re.search(r"\bmom\b", a_msg.lower()):
|
| 476 |
+
continue
|
| 477 |
+
if is_duplicate(u_msg):
|
| 478 |
+
continue
|
| 479 |
+
sample = create_sample(u_msg, a_msg, 1)
|
| 480 |
+
if sample:
|
| 481 |
+
master_pool.append(sample)
|
| 482 |
+
count += 1
|
| 483 |
+
print(f" ✅ Added {count} SODA conversational samples.")
|
| 484 |
+
except Exception as e:
|
| 485 |
+
print(f" ⚠️ SODA load error: {e}")
|
| 486 |
+
|
| 487 |
+
# 3. Clean Daily Math from GSM8K (Target: 2,500 step-by-step arithmetic)
|
| 488 |
+
print("\n📦 Step 3/6: Loading Clean GSM8K Everyday Math...")
|
| 489 |
+
try:
|
| 490 |
+
ds_math = load_dataset("openai/gsm8k", "main", split="train")
|
| 491 |
+
count = 0
|
| 492 |
+
for row in ds_math:
|
| 493 |
+
if count >= 2500:
|
| 494 |
+
break
|
| 495 |
+
q = row.get("question", "").strip()
|
| 496 |
+
ans = row.get("answer", "").strip()
|
| 497 |
+
if not q or not ans:
|
| 498 |
+
continue
|
| 499 |
+
# Sanitize answer
|
| 500 |
+
if "####" in ans:
|
| 501 |
+
parts = ans.split("####")
|
| 502 |
+
rationale = re.sub(r"<<[^>]*>>", "", parts[0]).strip()
|
| 503 |
+
final_val = parts[1].strip()
|
| 504 |
+
formatted_ans = f"{rationale}\n\n**Final Answer:** {final_val}"
|
| 505 |
+
else:
|
| 506 |
+
formatted_ans = re.sub(r"<<[^>]*>>", "", ans).strip()
|
| 507 |
+
if is_duplicate(q):
|
| 508 |
+
continue
|
| 509 |
+
sample = create_sample(q, formatted_ans, 3)
|
| 510 |
+
if sample:
|
| 511 |
+
master_pool.append(sample)
|
| 512 |
+
count += 1
|
| 513 |
+
print(f" ✅ Added {count} Clean Math samples.")
|
| 514 |
+
except Exception as e:
|
| 515 |
+
print(f" ⚠️ Math load error: {e}")
|
| 516 |
+
|
| 517 |
+
# 4. Factual Hindi & Indian GK from Alpaca-Hindi (Target: 2,500 factual Q&A)
|
| 518 |
+
print("\n📦 Step 4/6: Loading Factual Indian GK & Science...")
|
| 519 |
+
try:
|
| 520 |
+
ds_hi = load_dataset("FreedomIntelligence/alpaca-gpt4-hindi", split="train")
|
| 521 |
+
count = 0
|
| 522 |
+
CREATIVE_BLOCKLIST = {"कविता", "कहानी", "हाइकू", "नारा", "शायरी", "गीत", "दोहा"}
|
| 523 |
+
for row in ds_hi:
|
| 524 |
+
if count >= 2500:
|
| 525 |
+
break
|
| 526 |
+
inst = row.get("instruction", "").strip()
|
| 527 |
+
resp = row.get("output", "").strip()
|
| 528 |
+
if not inst or not resp or len(inst) < 10 or len(resp) < 15:
|
| 529 |
+
continue
|
| 530 |
+
if any(kw in inst for kw in CREATIVE_BLOCKLIST):
|
| 531 |
+
continue
|
| 532 |
+
if is_duplicate(inst):
|
| 533 |
+
continue
|
| 534 |
+
sample = create_sample(inst, resp, 5)
|
| 535 |
+
if sample:
|
| 536 |
+
master_pool.append(sample)
|
| 537 |
+
count += 1
|
| 538 |
+
print(f" ✅ Added {count} Factual Hindi GK samples.")
|
| 539 |
+
except Exception as e:
|
| 540 |
+
print(f" ⚠️ Hindi GK load error: {e}")
|
| 541 |
+
|
| 542 |
+
# 5. Clean Workplace & Daily Tasks from alpaca-cleaned (Target: 2,000 samples)
|
| 543 |
+
print("\n📦 Step 5/6: Loading Practical Everyday Tasks...")
|
| 544 |
+
try:
|
| 545 |
+
ds_alp = load_dataset("yahma/alpaca-cleaned", split="train")
|
| 546 |
+
count = 0
|
| 547 |
+
for row in ds_alp:
|
| 548 |
+
if count >= 2000:
|
| 549 |
+
break
|
| 550 |
+
inst = row.get("instruction", "").strip()
|
| 551 |
+
inp = row.get("input", "").strip()
|
| 552 |
+
resp = row.get("output", "").strip()
|
| 553 |
+
if inp:
|
| 554 |
+
inst = f"{inst}\n\n{inp}"
|
| 555 |
+
if not inst or not resp or len(resp) < 20:
|
| 556 |
+
continue
|
| 557 |
+
if is_duplicate(inst):
|
| 558 |
+
continue
|
| 559 |
+
sample = create_sample(inst, resp, 7)
|
| 560 |
+
if sample:
|
| 561 |
+
master_pool.append(sample)
|
| 562 |
+
count += 1
|
| 563 |
+
print(f" ✅ Added {count} Everyday Task samples.")
|
| 564 |
+
except Exception as e:
|
| 565 |
+
print(f" ⚠️ Alpaca load error: {e}")
|
| 566 |
+
|
| 567 |
+
print(f"\n{'='*85}")
|
| 568 |
+
print(f"📊 Total Master Pool Size: {len(master_pool):,} samples (Target: 10k-15k)")
|
| 569 |
+
print(f"{'='*85}")
|
| 570 |
+
return master_pool
|
| 571 |
+
|
| 572 |
+
|
| 573 |
+
# ==============================================================================
|
| 574 |
+
# Section 5: Split, Save Shards & Upload
|
| 575 |
+
# ==============================================================================
|
| 576 |
+
def split_and_save(master_pool: list):
|
| 577 |
+
random.shuffle(master_pool)
|
| 578 |
+
n_val = max(100, int(len(master_pool) * VAL_SPLIT_RATIO))
|
| 579 |
+
val_pool = master_pool[:n_val]
|
| 580 |
+
train_pool = master_pool[n_val:]
|
| 581 |
+
|
| 582 |
+
print(f"\n📊 Split: Train = {len(train_pool):,} | Val = {len(val_pool):,}")
|
| 583 |
+
|
| 584 |
+
total_tokens = 0
|
| 585 |
+
for split_name, pool in [("train", train_pool), ("val", val_pool)]:
|
| 586 |
+
all_tokens = []
|
| 587 |
+
all_labels = []
|
| 588 |
+
offsets = [0]
|
| 589 |
+
domains = []
|
| 590 |
+
|
| 591 |
+
for sample in pool:
|
| 592 |
+
all_tokens.extend(sample["input_ids"])
|
| 593 |
+
all_labels.extend(sample["labels"])
|
| 594 |
+
offsets.append(len(all_tokens))
|
| 595 |
+
domains.append(sample["domain_id"])
|
| 596 |
+
|
| 597 |
+
tokens_np = np.array(all_tokens, dtype=np.int32)
|
| 598 |
+
labels_np = np.array(all_labels, dtype=np.int32)
|
| 599 |
+
offsets_np = np.array(offsets, dtype=np.uint32)
|
| 600 |
+
domains_np = np.array(domains, dtype=np.uint8)
|
| 601 |
+
|
| 602 |
+
np.save(os.path.join(OUTPUT_DIR, f"{split_name}_tokens.npy"), tokens_np)
|
| 603 |
+
np.save(os.path.join(OUTPUT_DIR, f"{split_name}_labels.npy"), labels_np)
|
| 604 |
+
np.save(os.path.join(OUTPUT_DIR, f"{split_name}_offsets.npy"), offsets_np)
|
| 605 |
+
np.save(os.path.join(OUTPUT_DIR, f"{split_name}_domains.npy"), domains_np)
|
| 606 |
+
|
| 607 |
+
print(f" 💾 Saved {split_name}: {len(pool):,} samples, {len(tokens_np):,} tokens")
|
| 608 |
+
total_tokens += len(tokens_np)
|
| 609 |
+
|
| 610 |
+
metadata = {
|
| 611 |
+
"version": f"sft_{VERSION}",
|
| 612 |
+
"total_samples": len(master_pool),
|
| 613 |
+
"train_samples": len(train_pool),
|
| 614 |
+
"val_samples": len(val_pool),
|
| 615 |
+
"total_tokens": total_tokens,
|
| 616 |
+
"max_seq_len": MAX_SEQ_LEN,
|
| 617 |
+
"vocab_size": 64003,
|
| 618 |
+
"model_type": "Basic Conversational Chatbot"
|
| 619 |
+
}
|
| 620 |
+
|
| 621 |
+
with open(os.path.join(OUTPUT_DIR, "metadata.json"), "w", encoding="utf-8") as f:
|
| 622 |
+
json.dump(metadata, f, indent=2)
|
| 623 |
+
print(" 📄 Saved metadata.json")
|
| 624 |
+
|
| 625 |
+
return metadata
|
| 626 |
+
|
| 627 |
+
|
| 628 |
+
def upload_to_hf():
|
| 629 |
+
try:
|
| 630 |
+
from huggingface_hub import HfApi
|
| 631 |
+
api = HfApi(token=HF_TOKEN)
|
| 632 |
+
sft_prefix = f"sft_{VERSION}"
|
| 633 |
+
files = ["train_tokens.npy", "train_labels.npy", "train_offsets.npy", "train_domains.npy",
|
| 634 |
+
"val_tokens.npy", "val_labels.npy", "val_offsets.npy", "val_domains.npy", "metadata.json"]
|
| 635 |
+
for fname in files:
|
| 636 |
+
local = os.path.join(OUTPUT_DIR, fname)
|
| 637 |
+
if os.path.exists(local):
|
| 638 |
+
api.upload_file(path_or_fileobj=local, path_in_repo=f"{sft_prefix}/{fname}", repo_id=HF_DATA_REPO, repo_type="dataset")
|
| 639 |
+
print(f" ☁️ Uploaded {sft_prefix}/{fname}")
|
| 640 |
+
print(f" ✅ Uploaded to {HF_DATA_REPO}/{sft_prefix}/")
|
| 641 |
+
except Exception as e:
|
| 642 |
+
print(f" ⚠️ HF Upload error: {e}")
|
| 643 |
+
|
| 644 |
+
|
| 645 |
+
def main():
|
| 646 |
+
start = time.time()
|
| 647 |
+
pool = build_basic_chatbot_dataset()
|
| 648 |
+
meta = split_and_save(pool)
|
| 649 |
+
upload_to_hf()
|
| 650 |
+
print(f"\n🎉 SFT {VERSION.upper()} Basic Chatbot Build Finished in {(time.time()-start)/60:.2f} mins!")
|
| 651 |
+
|
| 652 |
+
if __name__ == "__main__":
|
| 653 |
+
main()
|