ViuAI commited on
Commit
4589ddd
·
verified ·
1 Parent(s): 712e06f

Upload code/build_sft_basic_chatbot.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. code/build_sft_basic_chatbot.py +220 -93
code/build_sft_basic_chatbot.py CHANGED
@@ -1,16 +1,18 @@
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
@@ -22,7 +24,6 @@ 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")
@@ -33,7 +34,7 @@ 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)
@@ -50,8 +51,9 @@ 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
  # ==============================================================================
@@ -77,7 +79,50 @@ 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
 
@@ -89,7 +134,7 @@ def is_duplicate(text: str) -> bool:
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:
@@ -121,12 +166,51 @@ def create_sample(instruction: str, response: str, domain_id: int):
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?",
@@ -153,7 +237,7 @@ def get_gold_foundation_anchors():
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
 
@@ -173,7 +257,7 @@ def is_prime(n):
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)!$):
@@ -188,7 +272,7 @@ def factorial(n):
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]`):
@@ -202,21 +286,20 @@ def reverse_string(s):
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:
@@ -225,7 +308,7 @@ print(is_palindrome("hello")) # Output: False
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:
@@ -243,9 +326,9 @@ def generate_fibonacci(n):
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
 
@@ -255,7 +338,7 @@ print(generate_fibonacci(7)) # Output: [0, 1, 1, 2, 3, 5, 8]
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:
@@ -263,7 +346,7 @@ print(generate_fibonacci(7)) # Output: [0, 1, 1, 2, 3, 5, 8]
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:
@@ -274,7 +357,7 @@ print(generate_fibonacci(7)) # Output: [0, 1, 1, 2, 3, 5, 8]
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}}$
@@ -284,7 +367,7 @@ print(generate_fibonacci(7)) # Output: [0, 1, 1, 2, 3, 5, 8]
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}$:
@@ -292,89 +375,89 @@ print(generate_fibonacci(7)) # Output: [0, 1, 1, 2, 3, 5, 8]
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.",
@@ -383,25 +466,25 @@ print(generate_fibonacci(7)) # Output: [0, 1, 1, 2, 3, 5, 8]
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)
@@ -416,10 +499,11 @@ 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
 
@@ -435,57 +519,102 @@ print(reversed_list) # [5, 4, 3, 2, 1]
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
@@ -496,7 +625,6 @@ def build_basic_chatbot_dataset():
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()
@@ -506,7 +634,7 @@ def build_basic_chatbot_dataset():
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
@@ -514,8 +642,8 @@ def build_basic_chatbot_dataset():
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
@@ -531,7 +659,7 @@ def build_basic_chatbot_dataset():
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
@@ -539,8 +667,8 @@ def build_basic_chatbot_dataset():
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
@@ -556,7 +684,7 @@ def build_basic_chatbot_dataset():
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
@@ -565,13 +693,13 @@ def build_basic_chatbot_dataset():
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)
@@ -615,13 +743,12 @@ def split_and_save(master_pool: list):
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
 
@@ -644,10 +771,10 @@ def upload_to_hf():
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()
 
1
  # ==============================================================================
2
+ # 🤖 ViuAI Sarus-500M — SFT v21 "Basic Conversational Chatbot" Master Builder
3
  # ==============================================================================
4
+ # Target: ~15,000 Clean, Human-Verified Conversational & Practical Samples
5
  #
6
+ # 🌟 KEY CAPABILITIES INCLUDED:
7
+ # 1. Natural Chit-Chat & Greetings (NO identity bleed)
8
+ # 2. Multi-Turn Context Retention (Causal turn masking across 2-4 turns)
9
+ # 3. Typo Robustness (Handles 'hlo', 'kse', 'pthon', 'btao', fast typing)
10
+ # 4. Pure Identity ONLY when explicitly asked ("Who made you?" -> ViuAI Sarus)
11
+ # 5. 100% Verified Indian GK (PM Modi, Rajendra Prasad, Samvidhan, ISRO, Taj Mahal)
12
+ # 6. Step-by-Step Clean Math (Unitary method, BODMAS, Discounts, Speed/Distance)
13
+ # 7. Verified Working Python Algorithms (Prime, Palindrome, Reverse, Factorial)
14
+ # 8. Clean Everyday Human Translation (En <-> Hi)
15
+ # 9. Professional workplace leave emails, recipes, and health wellness
16
  # ==============================================================================
17
 
18
  import os
 
24
  import shutil
25
  import random
26
  import numpy as np
 
27
 
28
  if hasattr(sys.stdout, "reconfigure"):
29
  sys.stdout.reconfigure(encoding="utf-8", errors="replace")
 
34
  MAX_SEQ_LEN = 2048
35
  VAL_SPLIT_RATIO = 0.02
36
  SEED = 42
37
+ MIN_TARGET_TOKENS = 8
38
 
39
  random.seed(SEED)
40
  np.random.seed(SEED)
 
51
  HF_DATA_REPO = "ViuAI/viuai-500m-sft-tokenized"
52
 
53
  print("=" * 85)
54
+ print(f"🤖 ViuAI Sarus-500M — SFT {VERSION.upper()} 'Basic Chatbot' Master Builder")
55
+ print(f" 🌟 Features: Multi-Turn Context + Typo Robustness + Clean GK & Math")
56
+ print(f" 📊 Target: ~15,000 Pristine Samples")
57
  print("=" * 85)
58
 
59
  # ==============================================================================
 
79
  assert all(x is not None for x in [USER_ID, ASSISTANT_ID, EOT_ID]), "Missing special tokens!"
80
 
81
  # ==============================================================================
82
+ # Section 2: Typo Injection Engine
83
+ # ==============================================================================
84
+ HINGLISH_ABBREVS = {
85
+ "karo": "kro", "batao": "btao", "kaise": "kse", "kya": "kyaa",
86
+ "bhai": "bhaii", "theek": "thik", "achha": "acha", "please": "plz",
87
+ "thanks": "thx", "because": "bcoz", "you": "u", "are": "r",
88
+ "hello": "hlo", "hai": "h", "nahi": "nhi", "mujhe": "mjhe",
89
+ "python": "pthon", "function": "func", "reverse": "rvrse"
90
+ }
91
+
92
+ KEYBOARD_ADJACENT = {
93
+ "q": "w", "w": "e", "e": "r", "r": "t", "t": "y", "y": "u",
94
+ "u": "i", "i": "o", "o": "p", "a": "s", "s": "d", "d": "f",
95
+ "f": "g", "g": "h", "h": "j", "j": "k", "k": "l", "z": "x",
96
+ "x": "c", "c": "v", "v": "b", "b": "n", "n": "m",
97
+ }
98
+
99
+ def inject_typo(text: str, typo_prob: float = 0.20) -> str:
100
+ """Inject realistic typing errors into prompt text."""
101
+ if random.random() > typo_prob or len(text) < 10:
102
+ return text
103
+ words = text.split()
104
+ result = []
105
+ for w in words:
106
+ wl = w.lower()
107
+ if wl in HINGLISH_ABBREVS and random.random() < 0.50:
108
+ result.append(HINGLISH_ABBREVS[wl])
109
+ elif len(w) > 4 and random.random() < 0.25:
110
+ chars = list(w)
111
+ idx = random.randint(1, max(1, len(chars) - 2))
112
+ op = random.choice(["swap", "adjacent", "drop_vowel"])
113
+ if op == "swap" and idx + 1 < len(chars):
114
+ chars[idx], chars[idx + 1] = chars[idx + 1], chars[idx]
115
+ elif op == "adjacent" and chars[idx].lower() in KEYBOARD_ADJACENT:
116
+ chars[idx] = KEYBOARD_ADJACENT[chars[idx].lower()]
117
+ elif op == "drop_vowel" and chars[idx].lower() in "aeiou":
118
+ chars.pop(idx)
119
+ result.append("".join(chars))
120
+ else:
121
+ result.append(w)
122
+ return " ".join(result)
123
+
124
+ # ==============================================================================
125
+ # Section 3: Deduplication & Sample Creators
126
  # ==============================================================================
127
  GLOBAL_SEEN_HASHES = set()
128
 
 
134
  GLOBAL_SEEN_HASHES.add(h)
135
  return False
136
 
137
+ def create_single_sample(instruction: str, response: str, domain_id: int):
138
  inst = instruction.strip()
139
  resp = response.strip()
140
  if len(inst) < 2 or len(resp) < 3:
 
166
  assert len(full_ids) == len(labels)
167
  return {"input_ids": list(full_ids), "labels": labels, "domain_id": domain_id}
168
 
169
+ def create_multiturn_sample(messages: list, domain_id: int):
170
+ """
171
+ Format multi-turn conversation with causal turn masking.
172
+ messages: [{"role": "user"|"assistant", "content": "..."}]
173
+ """
174
+ full_ids = []
175
+ labels = []
176
+
177
+ for msg in messages:
178
+ role = msg.get("role", "")
179
+ content = msg.get("content", "").strip()
180
+ if not content:
181
+ continue
182
+
183
+ if role == "user":
184
+ turn_str = f"<|user|>\n{content}<|endofturn|>\n"
185
+ turn_ids = tokenizer.encode(turn_str).ids
186
+ full_ids.extend(turn_ids)
187
+ labels.extend([-100] * len(turn_ids))
188
+ elif role == "assistant":
189
+ turn_prefix = "<|assistant|>\n"
190
+ prefix_ids = tokenizer.encode(turn_prefix).ids
191
+ full_ids.extend(prefix_ids)
192
+ labels.extend([-100] * len(prefix_ids))
193
+
194
+ resp_str = f"{content}<|endofturn|>\n"
195
+ resp_ids = tokenizer.encode(resp_str).ids
196
+ full_ids.extend(resp_ids)
197
+ labels.extend(resp_ids)
198
+
199
+ if len(full_ids) < 20 or len(full_ids) > MAX_SEQ_LEN:
200
+ return None
201
+
202
+ active_tokens = sum(1 for l in labels if l != -100)
203
+ if active_tokens < MIN_TARGET_TOKENS:
204
+ return None
205
+
206
+ assert len(full_ids) == len(labels)
207
+ return {"input_ids": list(full_ids), "labels": labels, "domain_id": domain_id}
208
+
209
 
210
  # ==============================================================================
211
+ # Section 4: Gold Foundation Anchors (100% Tested Ground Truth)
212
  # ==============================================================================
213
+ def get_gold_anchors():
 
214
  anchors = [
215
  # --- 1. Identity & Persona ---
216
  ("Who created you and what is your name?",
 
237
  "Sab badhiya chal raha hai bhai! Aap batao, sab kaisa chal raha hai aapki taraf?", 1),
238
  ("Namaste", "Namaste! Aapka din shubh ho. Bataiye aaj main aapki kya seva kar sakta hoon?", 1),
239
 
240
+ # --- 3. Python Coding ---
241
  ("Write a Python function to check if a number is prime.",
242
  '''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:
243
 
 
257
  # Example test:
258
  print(is_prime(17)) # Output: True
259
  print(is_prime(4)) # Output: False
260
+ ```''', 3),
261
 
262
  ("Write a Python function to calculate the factorial of a number using recursion.",
263
  '''Here is the recursive Python function to compute factorial ($n! = n \\times (n-1)!$):
 
272
 
273
  # Example test:
274
  print(factorial(5)) # Output: 120
275
+ ```''', 3),
276
 
277
  ("Write a Python function to reverse a string without using slicing.",
278
  '''Here is how you can reverse a string using a loop without slicing (`[::-1]`):
 
286
 
287
  # Example test:
288
  print(reverse_string("Hello World!")) # Output: "!dlroW olleH"
289
+ ```''', 3),
290
 
291
  ("Write a Python function to check if a given string is a palindrome.",
292
  '''A palindrome is a string that reads the same forwards and backwards:
293
 
294
  ```python
295
  def is_palindrome(s):
 
296
  cleaned = "".join(char.lower() for char in s if char.isalnum())
297
  return cleaned == cleaned[::-1]
298
 
299
  # Example test:
300
  print(is_palindrome("racecar")) # Output: True
301
  print(is_palindrome("hello")) # Output: False
302
+ ```''', 3),
303
 
304
  ("Write a Python one-liner list comprehension to get only even numbers from 1 to 20.",
305
  '''Here is the Python one-liner list comprehension:
 
308
  even_numbers = [x for x in range(1, 21) if x % 2 == 0]
309
  print(even_numbers)
310
  # Output: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
311
+ ```''', 3),
312
 
313
  ("Write a Python function to generate the first n Fibonacci numbers.",
314
  '''Here is a function to generate the first `n` Fibonacci numbers in a list:
 
326
 
327
  # Example test:
328
  print(generate_fibonacci(7)) # Output: [0, 1, 1, 2, 3, 5, 8]
329
+ ```''', 3),
330
 
331
+ # --- 4. Math & Word Problems ---
332
  ("If 5 notebooks cost ₹150, what is the cost of 12 notebooks?",
333
  '''Let's solve this step by step using the unitary method:
334
 
 
338
  2. **Cost of 12 notebooks:**
339
  $$\\text{Total Cost} = 12 \\times 30 = ₹360$$
340
 
341
+ **Final Answer:** The cost of 12 notebooks is **₹360**.''', 4),
342
 
343
  ("What is 10 + 20 * 2?",
344
  '''According to the standard order of operations (BODMAS / PEMDAS), multiplication is performed before addition:
 
346
  1. **Step 1 (Multiply):** $20 \\times 2 = 40$
347
  2. **Step 2 (Add):** $10 + 40 = 50$
348
 
349
+ **Final Answer:** **50**''', 4),
350
 
351
  ("If a shirt costs ₹800 and there is a 15% discount, what is the final price?",
352
  '''Let's calculate the discount and final price:
 
357
  2. **Final Price:**
358
  $$\\text{Final Price} = 800 - 120 = ₹680$$
359
 
360
+ **Final Answer:** The final price of the shirt is **₹680**.''', 4),
361
 
362
  ("A car travels 300 km in 5 hours. What is the average speed of the car?",
363
  '''We use the formula: $\\text{Speed} = \\frac{\\text{Distance}}{\\text{Time}}$
 
367
  3. **Calculation:**
368
  $$\\text{Average Speed} = \\frac{300}{5} = 60\\text{ km/h}$$
369
 
370
+ **Final Answer:** The average speed of the car is **60 km/h**.''', 4),
371
 
372
  ("Find the area and perimeter of a rectangle with length 14 cm and width 6 cm.",
373
  '''For a rectangle with length $l = 14\\text{ cm}$ and width $w = 6\\text{ cm}$:
 
375
  1. **Area:** $\\text{Area} = l \\times w = 14 \\times 6 = 84\\text{ cm}^2$
376
  2. **Perimeter:** $\\text{Perimeter} = 2 \\times (l + w) = 2 \\times (14 + 6) = 2 \\times 20 = 40\\text{ cm}$
377
 
378
+ **Final Answer:** Area is **84 cm²** and perimeter is **40 cm**.''', 4),
379
 
380
  ("What is 25 * 4 + 50?",
381
  '''Using the order of operations:
382
  1. **Multiplication:** $25 \\times 4 = 100$
383
  2. **Addition:** $100 + 50 = 150$
384
 
385
+ **Final Answer:** **150**''', 4),
386
 
387
  # --- 5. Logical Deductions ---
388
  ("A is B's brother. B is C's mother. How is A related to C?",
389
+ '''Let's trace the relationship:
390
  1. $B$ is the mother of $C$.
391
  2. $A$ is the brother of $B$.
392
  3. The brother of one's mother is their **maternal uncle (Mama)**.
393
 
394
+ **Final Answer:** $A$ is the **maternal uncle (Mama)** of $C$.''', 5),
395
 
396
  ("All roses are flowers. Some flowers fade quickly. Can we conclude that all roses fade quickly?",
397
  '''**No, we cannot conclude that.**
398
 
399
+ **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.''', 5),
400
 
401
  ("Why do we see lightning before we hear thunder? Explain step by step.",
402
  '''We see lightning before we hear thunder because **light travels much faster than sound**:
403
 
404
  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.
405
  2. **Speed of Sound:** Sound travels through air at approximately $343\\text{ m/s}$ (about $1\\text{ km}$ every $3\\text{ seconds}$).
406
+ 3. Although both lightning and thunder are produced simultaneously, the light reaches us first and the sound follows a few seconds later.''', 5),
407
 
408
  ("Why do dropped objects fall to the ground instead of floating in the air?",
409
+ '''Objects fall to the ground due to **gravity** (gravitational force). Earth exerts an attractive force pulling objects towards its center with an acceleration of approximately $9.8\\text{ m/s}^2$.''', 5),
410
 
411
  ("A person walks 5 km North, then turns Right and walks 3 km. In which direction is he from starting point?",
412
  '''1. Walking North puts the person in the North direction.
413
  2. Turning Right from North means heading East.
414
  3. Walking 3 km East places the person in the **North-East** direction from the origin.
415
 
416
+ **Final Answer:** He is in the **North-East** direction from the starting point.''', 5),
417
 
418
  # --- 6. Indian GK & Constitution ---
419
  ("Bhartiya Samvidhan kab lagu hua tha aur Drafting Committee ke Chairman kaun the?",
420
+ "भारतीय संविधान **26 जनवरी 1950** को लागू हुआ था। संविधान की ड्राफ्टिंग कमेटी (प्रारूप समिति) के अध्यक्ष **डॉ. भीमराव अंबेडकर (Dr. B.R. Ambedkar)** थे।", 6),
421
 
422
  ("Bharat ke pehle Rashtrapati kaun the aur kab bane the?",
423
+ "भारत के पहले राष्ट्रपति **डॉ. राजेंद्र प्रसाद (Dr. Rajendra Prasad)** थे। वे 26 जनवरी 1950 को स्वतंत्र भारत के पहले राष्ट्रपति बने थे।", 6),
424
 
425
  ("Who is the Prime Minister of India?",
426
+ "The current Prime Minister of India is **Shri Narendra Modi**.", 6),
427
 
428
  ("India ki capital kya hai?",
429
+ "भारत की राजधानी **नई दिल्ली (New Delhi)** है।", 6),
430
 
431
  ("Taj Mahal kis sheher me sthit hai aur ise kisne banwaya tha?",
432
+ "ताजमहल भारत के **आगरा (Agra)** शहर में यमुना नदी के तट पर स्थित है। इसे मुगल सम्राट **शाहजहाँ** ने अपनी बेगम मुमताज महल की याद में बनवाया था।", 6),
433
 
434
  ("Chandrayaan-3 kab land hua tha aur uske rover ka kya naam hai?",
435
+ "चंद्रयान-3 (Chandrayaan-3) **23 अगस्त 2023** को चंद्रमा के दक्षिणी ध्रुव के पास सफलतापूर्वक लैंड हुआ था। इसके लैंडर का नाम **विक्रम (Vikram)** और रोवर का नाम **प्रज्ञान (Pragyan)** था।", 6),
436
 
437
  ("Photosynthesis (Prakash Sanshleshan) process ko 2 line me samjhao.",
438
+ "प्रकाश संश्लेषण (Photosynthesis) वह प्रक्रिया है जिसमें हरे पौधे सूर्य के प्रकाश, जल और कार्बन डाइऑक्साइड (CO₂) की मदद से अपना भोजन (ग्लूकोज) बनाते हैं और ऑक्सीजन (O₂) गैस छोड़ते हैं।", 6),
439
 
440
  ("Matter ki 3 basic states kaunsi hain aur unke 1-1 example do.",
441
  '''पदार्थ (Matter) की तीन मुख्य अवस्थाएं हैं:
442
  1. **ठोस (Solid):** बर्फ (Ice), लकड़ी
443
  2. **द्रव (Liquid):** पानी (Water), दूध
444
+ 3. **गैस (Gas):** भाप (Steam), ऑक्सीजन''', 6),
445
 
446
  # --- 7. Everyday Clean Translation ---
447
  ("Translate to Hindi: 'Water is essential for all living beings.'",
448
+ "जल सभी जीवित प्राणियों के लिए आवश्यक है।", 7),
449
 
450
  ("Translate to Hindi: 'Consistency and discipline are the keys to long term success.'",
451
+ "निरंतरता और अनुशासन दीर्घकालिक सफलता की कुंजी हैं।", 7),
452
 
453
  ("Translate to Hindi: 'Artificial Intelligence is transforming how we work and learn.'",
454
+ "आर्टिफिशियल इंटेलिजेंस हमारे काम करने और सीखने के तरीके को बदल रहा है।", 7),
455
 
456
  ("Translate to English: 'ईमानदारी और मेहनत से ही सफलता मिलती है।'",
457
+ "Success is achieved only through honesty and hard work.", 7),
458
 
459
  ("Translate to English: 'मुझे आपसे मिलकर बहुत खुशी हुई।'",
460
+ "I am very happy to meet you.", 7),
461
 
462
  # --- 8. Recipes, Health & Workplace ---
463
  ("Kadak Masala Chai banane ki simple recipe step by step batao.",
 
466
  2. पानी में उबाल आने पर 1.5 चम्मच चायपत्ती और स्वादानुसार चीनी डालें।
467
  3. इसे 2 मिनट तक धीमी आंच पर उबलने दें ताकि मसालों का स्वाद आ जाए।
468
  4. अब 1 कप दूध डालें और 2-3 अच्छे उबाल आने तक पकाएं।
469
+ 5. चाय छानकर गरमा-गरम परोसें।''', 8),
470
 
471
  ("Crispy Aloo Paratha banane ke 2 main secret tips batao.",
472
  '''**क्रिस्पी आलू पराठा के 2 मुख्य सीक्रेट टिप्स:**
473
  1. **स्टफिंग में नमी न हो:** उबले आलू को पूरी तरह ठंडा करके कद्दूकस करें और मसाले मिलाते समय हल्का भुना जीरा और कसूरी मेथी डालें।
474
+ 2. **मध्यम आंच पर घी/मक्खन से सेकें:** पराठे को दोनों तरफ से पहले हल्का सूखा सेकें, फिर घी लगाकर धीमी-मध्यम आंच पर दबा-दबाकर कुरकुरा होने तक सेकें।''', 8),
475
 
476
  ("Subah khali pet gunguna paani peene ke kya fayde hote hain?",
477
  '''**सुबह खाली पेट गुनगुना पानी पीने के प्रमुख फायदे:**
478
  1. **पाचन में सुधार:** यह पेट को साफ करता है और मेटाबॉलिज्म (पा���न क्रिया) को तेज करता है।
479
  2. **बॉडी डिटॉक्स:** शरीर से टॉक्सिन्स (विषाक्त पदार्थ) बाहर निकलते हैं।
480
+ 3. **त्वचा और ऊर्जा:** त्वचा में चमक आती है और दिनभर ताजगी बनी रहती है।''', 8),
481
 
482
  ("What are common signs and symptoms of dehydration?",
483
  '''**Common signs and symptoms of dehydration include:**
484
  1. Extreme thirst and dry mouth
485
  2. Dark-colored urine or decreased urination
486
  3. Fatigue, dizziness, or lightheadedness
487
+ 4. Headache and dry skin''', 8),
488
 
489
  ("Write a short and professional 2-day sick leave email to my manager.",
490
  '''**Subject:** Sick Leave Application - [Your Name] (2 Days)
 
499
 
500
  Best regards,
501
  [Your Name]
502
+ [Your Designation]''', 8),
503
 
504
+ # --- 9. Typo Robustness Anchors ---
505
  ("Hlo bro, kse ho ap? pthon me list rvrse kse kre?",
506
+ '''Hello bhai! Main bilkul badhiya hoon.
507
 
508
  Python mein list reverse karne ke 2 aasan tareeqe hain:
509
 
 
519
  my_list = [1, 2, 3, 4, 5]
520
  my_list.reverse()
521
  print(my_list) # [5, 4, 3, 2, 1]
522
+ ```''', 9),
523
+
524
+ ("Hlo, prime nmbr chk krne ka pythn func btao",
525
+ '''Hello! Yeh raha Python function jo check karta hai ki number prime hai ya nahi:
526
+
527
+ ```python
528
+ def is_prime(n):
529
+ if n <= 1:
530
+ return False
531
+ if n == 2:
532
+ return True
533
+ if n % 2 == 0:
534
+ return False
535
+ for i in range(3, int(n**0.5) + 1, 2):
536
+ if n % i == 0:
537
+ return False
538
+ return True
539
+
540
+ print(is_prime(19)) # True
541
+ print(is_prime(10)) # False
542
+ ```''', 9)
543
  ]
544
  return anchors
545
 
546
 
547
  # ==============================================================================
548
+ # Section 5: Master Dataset Assembly (~15,000 Samples)
549
  # ==============================================================================
550
+ def build_master_dataset():
551
  from datasets import load_dataset
552
  master_pool = []
553
+
554
+ # 1. Gold Foundation Anchors (Replicated 35x = ~1,500 rock-solid anchor rows)
555
+ print("\n📦 Step 1/7: Loading Gold Foundation Anchors...")
556
+ gold_anchors = get_gold_anchors()
557
  for prompt, resp, did in gold_anchors:
558
+ for _ in range(35):
559
+ # Apply slight typo injection to 20% of anchor copies
560
+ p = inject_typo(prompt, typo_prob=0.20)
561
+ sample = create_single_sample(p, resp, did)
562
  if sample:
563
  master_pool.append(sample)
564
  print(f" ✅ Added {len(master_pool)} Gold Foundation Anchor samples.")
565
 
566
+ # 2. Multi-Turn Conversations from SODA & Smoltalk (Target: 3,500 multi-turn dialogues)
567
+ print("\n📦 Step 2/7: Loading Multi-Turn Context Conversations...")
568
  try:
569
  ds_soda = load_dataset("allenai/soda", split="train", streaming=True)
570
  count = 0
571
  for row in ds_soda:
572
+ if count >= 3500:
573
+ break
574
+ dialogue = row.get("dialogue", [])
575
+ if len(dialogue) < 4: # At least 2 full turns (4 messages)
576
+ continue
577
+ messages = []
578
+ for i, d in enumerate(dialogue[:6]): # Up to 3 turns
579
+ role = "user" if i % 2 == 0 else "assistant"
580
+ messages.append({"role": role, "content": d})
581
+ sample = create_multiturn_sample(messages, 2)
582
+ if sample:
583
+ master_pool.append(sample)
584
+ count += 1
585
+ print(f" ✅ Added {count} Multi-Turn Conversation samples.")
586
+ except Exception as e:
587
+ print(f" ⚠️ Multi-turn load error: {e}")
588
+
589
+ # 3. Single-Turn Chitchat from SODA with Typo injection (Target: 3,000 clean chats)
590
+ print("\n📦 Step 3/7: Loading Conversational Chitchat (with Typo engine)...")
591
+ try:
592
+ ds_soda_single = load_dataset("allenai/soda", split="train", streaming=True)
593
+ count = 0
594
+ for row in ds_soda_single:
595
+ if count >= 3000:
596
  break
597
  dialogue = row.get("dialogue", [])
598
  if len(dialogue) < 2:
599
  continue
600
  u_msg = dialogue[0].strip()
601
  a_msg = dialogue[1].strip()
602
+ if len(u_msg) < 5 or len(a_msg) < 5 or "mom" in a_msg.lower():
 
 
603
  continue
604
  if is_duplicate(u_msg):
605
  continue
606
+ # Apply typo engine to 15% of prompts
607
+ u_final = inject_typo(u_msg, typo_prob=0.15)
608
+ sample = create_single_sample(u_final, a_msg, 1)
609
  if sample:
610
  master_pool.append(sample)
611
  count += 1
612
+ print(f" ✅ Added {count} Conversational Chitchat samples.")
613
  except Exception as e:
614
+ print(f" ⚠️ Chitchat load error: {e}")
615
 
616
+ # 4. Clean Daily Math from GSM8K (Target: 2,500 clean step-by-step arithmetic)
617
+ print("\n📦 Step 4/7: Loading Clean GSM8K Everyday Math...")
618
  try:
619
  ds_math = load_dataset("openai/gsm8k", "main", split="train")
620
  count = 0
 
625
  ans = row.get("answer", "").strip()
626
  if not q or not ans:
627
  continue
 
628
  if "####" in ans:
629
  parts = ans.split("####")
630
  rationale = re.sub(r"<<[^>]*>>", "", parts[0]).strip()
 
634
  formatted_ans = re.sub(r"<<[^>]*>>", "", ans).strip()
635
  if is_duplicate(q):
636
  continue
637
+ sample = create_single_sample(q, formatted_ans, 4)
638
  if sample:
639
  master_pool.append(sample)
640
  count += 1
 
642
  except Exception as e:
643
  print(f" ⚠️ Math load error: {e}")
644
 
645
+ # 5. Factual Indian GK & Science from Alpaca-Hindi (Target: 2,500 samples)
646
+ print("\n📦 Step 5/7: Loading Factual Indian GK & Science...")
647
  try:
648
  ds_hi = load_dataset("FreedomIntelligence/alpaca-gpt4-hindi", split="train")
649
  count = 0
 
659
  continue
660
  if is_duplicate(inst):
661
  continue
662
+ sample = create_single_sample(inst, resp, 6)
663
  if sample:
664
  master_pool.append(sample)
665
  count += 1
 
667
  except Exception as e:
668
  print(f" ⚠️ Hindi GK load error: {e}")
669
 
670
+ # 6. Clean Workplace & Daily Tasks from alpaca-cleaned (Target: 2,000 samples)
671
+ print("\n📦 Step 6/7: Loading Practical Everyday Tasks...")
672
  try:
673
  ds_alp = load_dataset("yahma/alpaca-cleaned", split="train")
674
  count = 0
 
684
  continue
685
  if is_duplicate(inst):
686
  continue
687
+ sample = create_single_sample(inst, resp, 8)
688
  if sample:
689
  master_pool.append(sample)
690
  count += 1
 
693
  print(f" ⚠️ Alpaca load error: {e}")
694
 
695
  print(f"\n{'='*85}")
696
+ print(f"📊 Total Master Pool Size: {len(master_pool):,} samples (Target: ~15,000)")
697
  print(f"{'='*85}")
698
  return master_pool
699
 
700
 
701
  # ==============================================================================
702
+ # Section 6: Split, Save Shards & Auto-Upload to HF
703
  # ==============================================================================
704
  def split_and_save(master_pool: list):
705
  random.shuffle(master_pool)
 
743
  "total_tokens": total_tokens,
744
  "max_seq_len": MAX_SEQ_LEN,
745
  "vocab_size": 64003,
746
+ "features": ["Multi-Turn Context", "Typo Robustness", "Clean Math", "Verified Code", "Factual Indian GK"]
747
  }
748
 
749
  with open(os.path.join(OUTPUT_DIR, "metadata.json"), "w", encoding="utf-8") as f:
750
  json.dump(metadata, f, indent=2)
751
  print(" 📄 Saved metadata.json")
 
752
  return metadata
753
 
754
 
 
771
 
772
  def main():
773
  start = time.time()
774
+ pool = build_master_dataset()
775
  meta = split_and_save(pool)
776
  upload_to_hf()
777
+ print(f"\n🎉 SFT {VERSION.upper()} Master Builder Finished in {(time.time()-start)/60:.2f} mins!")
778
 
779
  if __name__ == "__main__":
780
  main()