چھوٹے LLMs کو K12 تخلیقی پروجیکٹ آئیڈیاز تجویز کرنے کا طریقہ سکھائیں۔

میں نے حال ہی میں ایک تعلیمی ایپ کے بارے میں ایک پوسٹ لکھی ہے جسے میں نے AI ٹولز کا استعمال کرتے ہوئے تیار کیا ہے اور راستے میں کیے گئے ڈیزائن کے فیصلے۔

جب میں نے ایک سرگرمی پر مبنی سیکھنے والی ایپ کا پروٹو ٹائپ کئی معلمین کو دکھایا، تو ایک تجویز بار بار سامنے آئی، جو Pinterest اور TikTok جیسے پلیٹ فارمز پر تخلیقی آئیڈیاز تلاش کرنے کے میرے تجربے سے لی گئی ہے۔ وہ عملی تلاش کے معیار (کون سا مواد قابل رسائی ہیں، وہ آخر پروڈکٹ کی طرح دیکھنا چاہتے ہیں) کی بنیاد پر انٹرنیٹ سے پروجیکٹ آئیڈیاز کھینچنے کی صلاحیت چاہتے تھے۔

ایپ میں پہلے سے ہی ایک بنیادی تلاش کی خصوصیت موجود ہے جو اس کی اپنی سرگرمی کے ڈیٹا سے نتائج واپس کرتی ہے، لیکن اس مرحلے پر وہ ڈیٹا اب بھی محدود ہے۔ کسی ایپ کے باہر نتائج پیدا کرنے سے ایسا محسوس ہوتا ہے جیسے کوئی LLM ہینڈل کرنے کے لیے موزوں ہو گا۔

میں اس بارے میں بھی متجسس تھا کہ K12 LLM دراصل کیسے پڑھایا جاتا ہے۔ یہ اس قسم کا نہیں تھا جس کے لیے بڑے ڈیٹا سیٹس اور کمپیوٹنگ کی ضرورت تھی (جس تک مجھے رسائی نہیں ہے)، لیکن سیکھنے کے لیے اس کے میکانکس کو سیکھنا تھا۔ اور پچھلی پوسٹ کی طرح، میں ان ڈیزائن کے انتخاب کے بارے میں سوچنا چاہتا تھا جو اس میں گئے تھے۔

  • K12 کے استعمال کے معاملات کو حل کرنے کے لیے چھوٹے LLM کو سکھانے کے لیے کیا تکنیکیں ہیں؟

  • آپ ایسے ماڈل کو کس طرح اور کس ڈیٹا کے ساتھ تربیت دیتے ہیں؟

  • میں کیسے جان سکتا ہوں کہ آیا کوئی ماڈل بچوں کے لیے موزوں ہے؟

  • مجھے اپنے ماڈل کو اپنی ایپ میں ضم کرنے کے لیے کیا ضرورت ہے؟

اس پوسٹ میں، میں ہر اس چیز کو دستاویز کروں گا جو میں نے سیکھا ہے کہ اس طرح کے ماڈل کو کیسے تربیت دی جائے اور اسے تعلیمی پروٹو ٹائپ کی فعالیت میں ضم کیا جائے۔

انڈیکس

شرطیں

یہ ایک ہینڈ آن ٹیوٹوریل ہے، لہذا یہاں آپ کو ماڈل کی پیروی کرنے یا خود تربیت دینے میں مدد کرنے کے لیے کیا ملے گا:

مہارتیں جو آپ چاہتے ہیں۔

  • کمانڈ لائن سے کلاڈ کا استعمال کریں۔

  • بنیادی Python: کوڈ پڑھیں، پیکجز انسٹال کریں اور استعمال کریں، APIs کو کال کریں، اور آؤٹ پٹ کو سمجھیں جیسے لاگ فائلز۔

  • چونکہ ایپ کا فرنٹ اینڈ بلٹ ان ہے، اس لیے یہ تھوڑا سا ٹائپ اسکرپٹ پڑھتا ہے۔

  • سب سے اہم بات یہ ہے کہ کلاڈ کے استدلال کے بعد آرام دہ محسوس کریں، اس کے پیش کردہ اختیارات کا جائزہ لیں، اور فیصلہ کریں کہ آگے کیا کرنا ہے۔ سنگل کمانڈز کے بجائے آگے پیچھے جانا دراصل اس قسم کے پروجیکٹ کے لیے درکار کلیدی مہارت ہے۔

مشین لرننگ میں کسی پس منظر کی ضرورت نہیں ہے۔ اس پوسٹ میں، میں سادہ زبان میں ML کے تصورات کی وضاحت کرنے کی کوشش کروں گا۔

ترتیبات درکار ہیں۔

  • Apple Silicon Mac (M1/M2/M3 یا بعد میں)۔ فائن ٹیوننگ کا مرحلہ MLX کا استعمال کرتا ہے، ایپل کا فریم ورک جو خصوصی طور پر Apple Silicon پر چلتا ہے۔

  • ورچوئل ماحول کے ساتھ ازگر 3 python3 -m venv

  • Ollama انسٹال کرنے کے لیے Qwen 2.5 7B ماڈل کو کھینچیں۔ ollama pull qwen2.5:7bمقامی طور پر تربیتی ڈیٹا تیار کرنے کے لیے۔ 7B ماڈل کو چلانے کے لیے آپ کو کافی RAM کی ضرورت ہوگی۔

  • تعمیراتی کاموں کے لیے کمانڈ لائن سے کلاڈ

ڈیٹا سیٹ کی تیاری

اس تجربے کے لیے، میں چاہتا تھا کہ سرگرمی کا ڈیٹا دنیا بھر کی مقامی ثقافتوں پر مبنی ہو۔ اس سے ماڈل کو تخلیقی پروجیکٹ آئیڈیاز تجویز کرنے میں مدد ملے گی جو تعلیمی ماحول میں ثقافتی سرگرمیوں کے فروغ کی ترغیب دیتے ہیں۔

میں نے کئی سالوں میں مقامی فنون اور روایات کے بارے میں ویکیپیڈیا کے بہت سے مضامین دیکھے ہیں۔ ویکیپیڈیا میرا پسندیدہ معلوماتی وسیلہ ہے۔ ویکیپیڈیا لوگوں کو پہلے رکھتا ہے، اس کا مواد کثرت سے اپ ڈیٹ ہوتا ہے، اور اس کا API اوپن سورس پروجیکٹ کے طور پر استعمال کرنے کے لیے آزاد ہے۔ لہذا میں نے ویکیپیڈیا ڈیٹا کا استعمال کرتے ہوئے ماڈل کو سکھانے کا فیصلہ کیا۔

اس قدم کا حقیقی حصہ صحیح زمرے لگانا تھا۔ Python اسکرپٹ میں، میں نے ~40 بیج کے زمرے کی وضاحت کی، انہیں 9 STEAM لیبلز میں گروپ کیا، اور Claude کی تجاویز لی کہ کن زمروں کو کھرچنا ہے اور درآمد شدہ ڈیٹا میں شور سے کیسے بچنا ہے۔

ہر مضمون کے حصوں سے متن نکالنے کے لیے، کلاڈ نے Wikipedia API کے لیے ایک Python ریپر تجویز کیا۔ یہ آپ کو ہر مضمون کو سیکشن ڈھانچے میں بطور ریکارڈ درآمد کرنے کی اجازت دیتا ہے۔ شور کو کم کرنے کے لیے، ہم نے اپنی رینگنے کو ایک ذیلی زمرہ کی سطح تک محدود رکھا اور مضامین کو صرف ایک مخصوص مواد کے سائز سے اوپر رکھا۔

# Seed categories grouped by STEAM domain.
SEED_CATEGORIES = {
    "Crafts & making": [
        "Category:Crafts",
        "Category:Origami",
        "Category:Pottery",
        "Category:Kites",
    ],
    "Arts": [
        "Category:Folk art",
        "Category:Textile arts",
        "Category:Indigenous art",
        "Category:Masks",
    ],
    "Science": [
        "Category:Ethnobotany",
        "Category:Food preservation",
        "Category:Gardening",
    ],                                                            
# ... Media arts, Engineering, Mathematics, Music & sky, Play & learning
}

MAX_DEPTH = 1             # descend only one sub-category level
MIN_CONTENT_CHARS = 800   # skip stubs (summary + sections)

کارپس فلٹرنگ

پچھلے مرحلے میں، سکریپنگ کے دوران ~19,000 مضامین بنائے گئے تھے۔ یہ مرحلہ یقینی بناتا ہے کہ آپ کا مواد آپ کے STEAM موضوع سے متعلقہ رہے گا۔ متعلقہ فلٹرنگ خود دو مراحل میں کی جاتی ہے: واضح شور ہٹانا اور سیمنٹک فلٹرنگ۔

پہلا مرحلہ زمرہ جات، عنوانات، اور سیکشن ٹائٹل پیٹرن کا استعمال کرتا ہے تاکہ واضح طور پر غیر فعال مواد جیسے کہ موسیقی، فلمیں، ٹی وی، سوانح حیات، اور پودوں/جانوروں کی انواع کو ہٹایا جا سکے۔

دوسرے سیمنٹک مرحلے میں، ہم ہر مضمون کے عنوان اور خلاصہ کو ایک چھوٹے جملے کے ٹرانسفارمر ماڈل (all-MiniLM-L6-v2) کا استعمال کرتے ہوئے ویکٹر میں تبدیل کرتے ہیں۔ پھر ہم اس کا موازنہ جملے کے دو سیٹوں سے کریں: مثبت اینکرز اور منفی اینکرز۔

مثبت اینکر ایسے جملوں کی وضاحت کرتے ہیں جو STEAM سرگرمیوں سے متعلق ہیں، جبکہ منفی اینکر ایسے جملوں کی وضاحت کرتے ہیں جو کم متعلقہ ہیں۔ ہر مضمون کو اس بنیاد پر اسکور ملتا ہے کہ یہ مثبت اور منفی مثالوں کے کتنے قریب ہے، اور ہم تمام مثبت مضامین کو برقرار رکھتے ہیں۔ ہم یہ جملہ کنورٹر لائبریری کا استعمال کرتے ہوئے کرتے ہیں۔

ان اینکر جملوں کو لکھنا اس عمل میں سب سے زیادہ انسانی قدم ہے۔ اس فلٹرنگ نے کارپس کو ~ 6,600 مضامین تک کم کر دیا۔

# Filtering the raw scrape to articles useful for STEAM activity suggestions.

POSITIVE_ANCHORS = [
    "a hands-on craft that children can make using simple materials and a technique",
    "a traditional cultural art or making technique such as weaving, carving, pottery or paper folding",
]
NEGATIVE_ANCHORS = [
    "a species of plant, animal or fungus",
    "a biography of a person",
    "a city, region, building or geographic place",
]

    # Embed article + anchors, then keep whatever leans positive.
    pos_sim = util.cos_sim(emb, pos).max(dim=1).values # closest positive anchor 
    neg_sim = util.cos_sim(emb, neg).max(dim=1).values # closest negative anchor
    scores = (pos_sim - neg_sim).tolist()

تربیتی جوڑے بنائیں

اگلا مرحلہ فلٹر شدہ کارپس سے ان پٹ → آؤٹ پٹ ٹریننگ جوڑے تیار کرنا ہے۔ ہم اسے مقامی پہلے سے تربیت یافتہ اوپن سورس ماڈل (Qwen 2.5 7B، اولاما کے ذریعے چلتے ہوئے) کے ذریعے کشید کر کے کرتے ہیں۔

ہر مضمون کے لیے، ہم ماڈل کو عنوان، خلاصہ، ثقافتی سیاق و سباق اور مواد کے کئی حصے بھیجتے ہیں۔ یہ ایک سسٹم پرامپٹ بھی بھیجتا ہے جو آپریشن کی وضاحت کرتا ہے، آؤٹ پٹ فارمیٹ کی وضاحت کرتا ہے (اس معاملے میں، درست JSON)، اور فارمیٹ کو اینکر کرنے کے لیے ایک مثالی تربیتی جوڑا شامل کرتا ہے۔

اس فوری طور پر اچھی طرح سے تعمیر کرنا وہ جگہ ہے جہاں انسانی مداخلت سب سے اہم ہے۔ اسکیماس، قواعد، اور واحد آپریشن کی مثالیں آپ کے ماڈل کے تیار کردہ ہر جوڑے کے معیار کا تعین کرتی ہیں۔

تخلیق کے بعد، جوڑے کو صاف کیا گیا اور ٹھیک ٹیوننگ کے لیے تیار کیا گیا۔ مقامی ماڈلز اپنے زمرے کے لیبل بناتے ہیں ("سیرامکس”، "کرافٹس اور فیبریکیشن”، "سرکیٹری (استعاراتی)”…)۔ لہذا، یہ مرحلہ ایپ کے 10 معیاری زمروں (آرٹ، سائنس، کوڈنگ، سرکٹس، انجینئرنگ، کہانی سنانے، ڈرامہ، موویز، موسیقی، فطرت) کے طے شدہ سیٹ پر تمام زمروں کا نقشہ بناتا ہے، K12 بینڈ میں ہر ایک سرگرمی کے لیے عمر کی حد کو طے کرتا ہے، جوڑوں کو چیٹ کی شکل میں تبدیل کرتا ہے، اور آخر میں ڈیٹا کو تقسیم کرتا ہے، ٹریننگ، ٹیسٹنگ اور ڈیٹا کو تین حصوں میں تقسیم کرتا ہے۔

# The schema every generated training pair must match (valid JSON only).
  {
    "input": {
      "materials": ["3-6 realistic classroom materials"],
      "age_range": [min_int, max_int],
      "theme": "optional string or null"
    },
    "output": {
      "ideas": [{
        "title": "catchy, max 60 chars",
        "description": "2-3 sentences",
        "category": "one of: Art, Science, Coding, Circuits, Engineering, ...",
        "cultural_origin": "specific region or culture",
        "materials_used": ["subset of input materials"],
        "materials_missing": ["anything else needed"],
        "estimated_minutes": integer,
        "steps": ["3-6 short steps, one sentence each"],
        "learning_objectives": ["2-4 objectives"],
        "safety_note": "string or null"
      }]
    }
  }

ٹھیک ٹیوننگ

یہ وہ مرحلہ ہے جہاں ماڈل سیکھتا ہے کہ کس طرح کام کرنا ہے اور مطلوبہ جواب کو مناسب فارمیٹ میں تیار کرنا ہے۔ اس میں LoRA تکنیک کا استعمال کرتے ہوئے میرے ڈیٹاسیٹ پر MLX کے ذریعے پہلے سے تربیت یافتہ ماڈل (اس معاملے میں Qwen2.5-1.5B-Instruct-4bit) کو ٹھیک کرنا شامل ہے۔

LoRA کا استعمال کرتے ہوئے فائن ٹیوننگ ایک سستا اور ہلکا پھلکا طریقہ ہے۔ ہم پورے ماڈل کو دوبارہ تربیت نہیں دیتے ہیں، بلکہ اس کے بجائے چھوٹی ترمیمی تہوں کو شامل کرتے ہیں جو اصل ماڈل کو درست رکھتے ہوئے حتمی رویے کو ایڈجسٹ کرتی ہیں۔

اس پروجیکٹ کی رکاوٹوں کے پیش نظر، ~ 400 جوڑوں کے چھوٹے ڈیٹا سیٹ کے ساتھ ذاتی لیپ ٹاپ پر کام کرنے کے لیے، مکمل فائن ٹیوننگ کے لیے کافی زیادہ میموری اور کمپیوٹ کی ضرورت ہوگی۔ یہ یہاں حد سے زیادہ ہو گا۔ لہذا LoRA صحیح انتخاب تھا۔

LoRA فائن ٹیوننگ سائیکل:

ٹریننگ ٹریننگ جوڑی پر بہت سے تکرار چلاتی ہے، ہر تکرار ایک ہی مختصر سائیکل کے ساتھ۔ ہر ان پٹ کے لیے، ماڈل ان پٹ اور ماڈل کے موجودہ وزن کی بنیاد پر ہر ممکنہ اگلے لفظ کو امکانی سکور تفویض کر کے ایک پیشین گوئی پیدا کرتا ہے۔ تربیت کے دوران، ان کی درجہ بندی اس بنیاد پر کی جاتی ہے کہ وہ تربیتی ڈیٹا میں صحیح اگلا لفظ فراہم کرنے کے کتنے امکان رکھتے ہیں۔

(نوٹ: ایک عصبی نیٹ ورک میں، وزن اور تعصب ایسے اعداد ہوتے ہیں جو اس بات کا تعین کرتے ہیں کہ ماڈل ان پٹ پر کیسے عمل کرتا ہے، پیشین گوئیاں کرتا ہے، اور جوابات پیدا کرتا ہے۔)

اس موازنہ سے، ٹرین کے نقصانات کا حساب لگایا جاتا ہے۔ اس کے بعد ہم وزن کو اسی کے مطابق اپ ڈیٹ کرتے ہیں، خاص طور پر چھوٹے LoRA اڈاپٹر کے وزن، جبکہ فکسڈ بیس ماڈل وہی رہتا ہے، جس سے اگلا اندازہ تھوڑا قریب آتا ہے۔ نقصان جتنا کم ہوگا، ماڈل ڈیٹا میں اتنا ہی بہتر فٹ بیٹھتا ہے۔

پھر ہم اگلی تکرار کی طرف بڑھتے ہیں اور سائیکل دہرایا جاتا ہے۔ آخر میں، تربیت یافتہ اڈاپٹر کے وزن سیفٹینسر فائل میں محفوظ کیے جاتے ہیں۔

مثال کے طور پر، یہ ہے کہ میری دوڑ میں توثیق کا نقصان کیسے ہوا: 2.532 → 0.842 → 0.823 → 0.814 → 0.820 → 0.831 → 0.845۔ یہ سب سے پہلے تیزی سے گرا (ماڈل دراصل سیکھ رہا تھا)، 300 تکرار پر 0.814 پر نیچے آ گیا، اور آخر کار دوبارہ 0.845 تک بڑھ گیا۔ یہ ایک ابتدائی نشانی تھی کہ ماڈل زیادہ فٹ ہونا شروع کر رہا تھا۔ یعنی یہ تربیتی ڈیٹا کو مسلسل بہتر بنانے کے بجائے یاد رکھتا ہے۔

تو پیاری جگہ رن کا وسط تھا، اختتام نہیں۔ یہ وہ جگہ ہے جہاں انسانی جائزہ سب سے اہم ہے۔ ہم نے 200، 400، اور 600 پر چیک پوائنٹس کو محفوظ کیا، اور 400 چوکیوں کا انتخاب کیا، جو کہ سب سے کم توثیق کے نقصان کے ساتھ چیک پوائنٹس تھے، جن کا جائزہ لیا جائے اور پیش کیا جائے۔

# Base model — small, instruction-tuned, 4-bit (runs on a laptop)
  model: "mlx-community/Qwen2.5-1.5B-Instruct-4bit"

  train: true
  data: "data/mlx"            # training data: train.jsonl + valid.jsonl
  adapter_path: "adapters"    # <- the trained LoRA weights get saved here

  fine_tune_type: lora
  num_layers: 8               # apply LoRA to the last 8 transformer layers only
  lora_parameters:
    rank: 8                   # adapter size — bigger = more capacity, more overfit risk

  # Training loop
  batch_size: 4               # 400 train examples / 4 = 100 iterations per epoch
  iters: 600                  # ~6 passes over the training set
  learning_rate: 1e-5

  # Watch validation loss to catch overfitting
  steps_per_eval: 100         # check validation loss every 100 steps
  save_every: 200             # checkpoint adapters at 200 / 400 / 600

اوپر کنفیگریشن فائل ہے۔ یہ استعمال شدہ ماڈل، اڈاپٹر پاتھ، فائن ٹیوننگ اور LoRA سیٹنگز، ٹریننگ لوپ، اور توثیق پاس دکھاتا ہے۔

ذیل میں MLX (ایپل کے مشین لرننگ فریم ورک) کے ساتھ چلنے والی کمانڈز ہیں جو فائن ٹیوننگ کا عمل شروع کرتی ہیں:

mlx_lm.lora --config lora_config.yaml

ذیل میں آؤٹ پٹ نتائج دکھاتا ہے۔ سیکھے ہوئے وزن کو اڈاپٹر/فولڈر میں محفوظ کیا جاتا ہے جس میں ہر 200 تکرار 200، 400 اور 600 پر چیک پوائنٹس محفوظ ہوتے ہیں۔

  adapters/
  ├── 0000200_adapters.safetensors
  ├── 0000400_adapters.safetensors   <- the one you serve (lowest val loss of the three)
  ├── 0000600_adapters.safetensors
  └── adapters.safetensors           <- copy of the final (600) weights

ٹھیک ٹیونڈ ماڈل کی تشخیص

ایک بار فائن ٹیوننگ مکمل ہونے کے بعد، ماڈل کی جانچ ایک ایسے ٹیسٹ سیٹ پر کی جانی تھی جو ٹریننگ پیئر جنریشن سٹیپ سے الگ رکھی گئی تھی اور ٹریننگ کے دوران نظر نہیں آتی تھی۔

اس مرحلے میں، ایک صارف کا پیغام ماڈل کو دیا جاتا ہے، ماڈل اپنا JSON جواب تیار کرتا ہے، اور اس جواب کا موازنہ فائل میں پہلے سے محفوظ آخری (درست/حوالہ) جواب سے کرتا ہے۔

تشخیص اس بات کی تصدیق کرتا ہے اور رپورٹ کرتا ہے کہ آیا JSON درست ہے، کیا متوقع کلیدیں موجود ہیں، پیش گوئی شدہ مواد سونے کے جواب کے ساتھ کتنا اوورلیپ ہوتا ہے، اور کتنی بار پیشین گوئیاں مخصوص ثقافتی ماخذ کا ذکر کرتی ہیں۔

اسے ٹیسٹ سیٹ میں ہر مثال کے لیے چلائیں، ہر مثال کے لیے ایک مختصر لائن اور آخر میں ایک خلاصہ پرنٹ کریں۔ ہم پورے نتائج کو محفوظ کرتے ہیں، بشمول ہر پیش گوئی شدہ آئیڈیا کے ساتھ اصل (سونے کے) آئیڈیا کے ساتھ، تاکہ آپ انہیں ساتھ ساتھ پڑھ سکیں۔

# Fine-tuned model on 50 held-out test examples:
  {
    "json_valid_rate":       1.00,   # always valid JSON
    "schema_match_rate":     1.00,   # always the right keys
    "avg_n_steps":           4.74,   # ~5 steps per idea
    "avg_materials_jaccard": 0.653,  # decent overlap with gold materials
    "pred_culture_specific_rate": 0.52,   # names a specific culture about half the time
    "culture_loose_match_rate":   0.108,  # but it's usually the WRONG one  <-- the gap RAG tries to close
  }

انڈیکس بلڈنگ اور آر اے جی کی تلاش

پچھلے مرحلے میں ہم نے دریافت کیا: culture_loose_match_rate_when_gold_specific کم: ماڈل مجوزہ سرگرمی کے لیے صحیح ثقافتی ماخذ کو یاد رکھنے میں اچھا نہیں ہے۔

اس مرحلے میں، ہم سرچ اگمنٹیشن جنریشن (RAG) کا استعمال کرتے ہوئے ان کمزوریوں کو دور کرنے کی کوشش کریں گے۔ اس امید کے بجائے کہ ماڈل یہ یاد رکھے گا کہ راکو جاپانی ہے، ہمیں استفسار کے وقت ایک حقیقی ویکیپیڈیا مضمون مل جاتا ہے، اسے ماڈل تک پہنچاتے ہیں، اور پھر جانچ کرتے ہیں کہ آیا اس تلاش سے واقعی مدد ملتی ہے۔

یہ دو حصوں میں کیا جاتا ہے۔ سب سے پہلے، ہم پہلے سے جمع کردہ ویکیپیڈیا مواد کو تلاش کے قابل "معنی ڈیٹا بیس" میں تبدیل کرنے کے لیے ایک سرچ انڈیکس بناتے ہیں۔ ہر مضمون کے لیے، ہم ایک چھوٹے ایمبیڈنگ ماڈل، all-MiniLM-L6-v2 کے ذریعے عنوان اور خلاصہ پاس کرکے سرایت کی گنتی کرتے ہیں۔ ایمبیڈنگ معنی کا عددی فنگر پرنٹ ہے، 384 نمبروں کی ایک قطار، جس میں ایک جیسے معنی والے مضامین ایک جیسے نمبروں کے ساتھ ختم ہوتے ہیں۔ یہ ایک بار آف لائن شمار کیا جاتا ہے اور ڈسک پر محفوظ کیا جاتا ہے۔

دوسرا خود تلاش ہے۔ استفسار کے وقت، یہ استفسار کو ایک ہی قسم کے ویکٹرز میں تبدیل کرتا ہے، تمام مضامین کو ان کی مماثلت کی بنیاد پر اسکور کرتا ہے، اور سب سے زیادہ اسکور والے چند مضامین کو لوٹاتا ہے (یعنی، وہ مضامین جو صارف کی درخواست کے معنی کے قریب ہیں)۔ پھر وہی تشخیص چلائیں جو پچھلے مرحلے کی طرح ہے، لیکن اہم سوالات کے جوابات دینے کے لیے ان بازیافت شدہ مضامین کو اشارے میں چسپاں کریں۔ کیا ماڈل بہتر کام کرے گا اگر اسے درست ویکیپیڈیا مضمون پاس کیا جائے؟

سیدھے الفاظ میں، اس مرحلے میں متعلقہ مضامین کی تلاش، ان کے ساتھ پرامپٹ کو بہتر بنانا، اور ایک ماڈل بنانا شامل ہے۔

def retrieve(query, embedder, embeddings, meta, k):
      # 1. turn the query into the same kind of 384-number vector
      q = embedder.encode([query], normalize_embeddings=True,
                          convert_to_numpy=True)[0]
      # 2. score every article by similarity (dot product of unit vectors = cosine)
      sims = embeddings @ q
      # 3. take the k closest, return them with their scores
      top = np.argsort(-sims)[:k]
      return [(meta[i], float(sims[i])) for i in top]

لہٰذا، RAG کا استعمال مواد کی فالتو پن کو بہتر بناتا ہے اور ماڈل کو زیادہ کثرت سے مخصوص ثقافتوں کا نام دینے کا سبب بنتا ہے، لیکن عین ثقافتی مماثلتیں شاذ و نادر ہی منتقل ہوتی ہیں۔ یہ وہ چیز ہے جسے ہم ایپ کے آئندہ ورژنز میں بہتر بنانا چاہیں گے۔

Metric                        Plain     + RAG     Change
materials_jaccard             0.653     0.752     better
pred_culture_specific_rate    0.52      0.64      better
culture_loose_match_rate      0.108     0.135     barely

خصوصیات کے ساتھ ماڈلز کو مربوط کریں۔

اب وقت آگیا ہے کہ آپ اپنی ایپ میں ٹھیک ٹیونڈ ماڈل کو ضم کریں اور دیکھیں کہ آپ اساتذہ کو متاثر کرنے کے لیے کون سی ثقافتی سرگرمیاں تشکیل دے سکتے ہیں۔

آخر سے آخر تک بہاؤ ایک "تجویز" اسکرین سے شروع ہوتا ہے جہاں اساتذہ اپنے پاس موجود مواد اور اختیاری طور پر، سرگرمی کے عنوانات درج کرتے ہیں۔ یہاں، تجاویز دو مراحل میں آگے بڑھتی ہیں: دریافت اور نسل۔

سب سے پہلے، ایپ ویکیپیڈیا انڈیکس کی ویکٹر تلاش کرتی ہے اور ثقافت سے متعلق مخصوص مضامین کا ایک گرڈ تیار کرتی ہے جو معلم کے ان پٹ سے میل کھاتا ہے۔ چونکہ کوئی ماڈل شامل نہیں ہے، ایک گرڈ فوری طور پر ظاہر ہو جائے گا.

پھر، کارڈ کو تھپتھپانے سے آپ کو تفصیلات کی اسکرین پر لے جاتا ہے جہاں ایک عمدہ ماڈل ایک ہی روایت کی بنیاد پر ایک مکمل اسٹیم سرگرمی بناتا ہے، جس میں عنوان، تفصیل، مواد، مرحلہ وار ہدایات، سیکھنے کے مقاصد اور حفاظتی نوٹ شامل ہیں۔ ہر وہ چیز جو آپ کو اپنی کلاس روم کی سرگرمیوں کی رہنمائی کے لیے درکار ہے۔

 // Step 1 — RETRIEVAL: educator's materials -> grid of cultural articles.
  // Pure vector search on the server, no model, so the grid appears instantly.
  export async function fetchInspiration(materials: string[], theme?: string) {
    const res = await fetch(`${BASE_URL}/suggest`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ materials, theme: theme ?? null }),
    });
    return res.json();   // { results: [...articles] }
  }

  // Step 2 — GENERATION: runs only when the educator taps ONE card.
  // The fine-tuned model generates a full activity grounded in that article.
  export async function fetchActivity(
    articleId: number,
    materials: string[],
    ageRange: [number, number],
  ) {
    const res = await fetch(`${BASE_URL}/activity`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ article_id: articleId, materials, age_range: ageRange }),
    });
    return res.json();   // { activity: {...}, article: {...} }
  }

اس طرح تخلیق سے الگ الگ ریسرچ ایک قیمت اور معیار کا انتخاب ہے۔ چونکہ تلاش بنیادی طور پر مفت ہے، ماڈل گرڈ میں موجود ہر کارڈ کے لیے صرف ایک بار چلایا جاتا ہے، بجائے اس کے کہ گرڈ میں موجود ہر کارڈ کے لیے ایک بار، جیسا کہ روایت ہے کہ معلمین دراصل وعدہ کرتے ہیں۔

اسکرین شاٹ ایپ کا استعمال کرتے ہوئے ثقافتی اسٹیم سرگرمی بنانے کے اقدامات دکھا رہا ہے۔

اپنے مواد کو محفوظ بنائیں

پائپ لائن کے بہت سے مراحل میں پہلے سے ہی ماڈل کے مواد کو محفوظ رکھنے کے اقدامات شامل ہیں، لیکن میں آخر میں اس موضوع کے بارے میں واضح طور پر بات کرنا چاہتا تھا۔

یہاں تک کہ اگر ایپ کے براہ راست استعمال کنندگان معلم ہیں، اس فیچر کی پیش کردہ ہر چیز کو آخر کار بچوں کے سامنے زندہ کیا جا سکتا ہے۔ لہٰذا، ہم نشہ، منشیات، سگریٹ، ہتھیار، دھماکہ خیز مواد، زہر وغیرہ، بنیادی طور پر کوئی بھی ایسا مواد جو عمر کے لحاظ سے مناسب نہ ہو، منظر عام پر نہیں آنا چاہتے یا اس کے لیے مراحل نہیں بنانا چاہتے۔

یہ ایک ایسا کام ہے جسے ماڈل خود بخود نہیں سنبھال سکتا۔ فائن ٹیونڈ ماڈل کو صرف ثقافتی دستکاری کی مثالوں پر تربیت دی جاتی ہے، اس لیے اس میں غیر محفوظ درخواستوں کو مسترد کرنے کی اندرونی جبلت نہیں ہے، اور الکحل اور ہتھیاروں جیسی چیزوں کے بارے میں عمومی معلومات اب بھی بیس ماڈل کے وزن میں آتی ہے۔

ایک بلڈر کے طور پر، آپ کو ضروری محافظوں اور چوکیوں کو جگہ پر رکھنے اور اپنے ماڈل کو یاد دلانے کی ضرورت ہے کہ اس کا برتاؤ کیسا ہونا چاہیے۔ ہم اسے دو مراحل میں کرتے ہیں:

  • اپنے ڈیٹا کو اسی طرح پہلے سے فلٹر کرکے ذریعہ پر خطرے کو کم کریں جس طرح آپ نے پہلے غیر متعلقہ زمروں کو ہٹا دیا تھا۔ کارپس (اور اس کے نتیجے میں تربیتی جوڑوں) کو درست کرنے کا مطلب ہے کہ ماڈل کو پہلے غیر محفوظ مواد کی تعلیم نہ دیں۔ یہ خاص طور پر اہم ہے اگر آپ اپنے ماڈل یا ڈیٹاسیٹ کو Hugging Face جیسی کسی چیز پر شائع کرنے کا ارادہ رکھتے ہیں، جہاں یہ پہلے سے فلٹر ہو چکا ہے۔ اس قدم نے ~19,000 سکریپ آئٹمز سے ~850 غیر محفوظ اشیاء کو ہٹا دیا۔

  • حقیقی یقین دہانیوں کے ساتھ اپنی ZubHub ایپس کے لیے رن ٹائم گارڈریلز کو برقرار رکھیں۔ ڈیٹا فلٹرنگ خطرے کو کم کرتی ہے، لیکن یہ اسے مٹا نہیں سکتا جو بنیادی ماڈل پہلے سے جانتا ہے، لہذا لائیو ایپس بازیافت سے پہلے تمام ان پٹ اور ڈسپلے کرنے سے پہلے تیار کردہ تمام آؤٹ پٹ کی جانچ کرتی ہیں۔ اس کا مطلب یہ ہے کہ غیر محفوظ شرائط پر بنائی گئی کوئی بھی چیز تلاش یا ڈسپلے نہیں کی جائے گی۔

# safety.py — one shared list of what we never surface to kids...
  UNSAFE_TERMS = { 
      # ...
  }

  # ...matched whole-word, so "twine" != "wine" and "gunny sack" != "gun".
  def screen_text(text):
      """Return the first unsafe category found, or None if the text is clear."""
      for category, pattern in _PATTERNS.items():   # _PATTERNS built from UNSAFE_TERMS
          if pattern.search(text):
              return category
      return None

  # Phase 1, data: drop unsafe articles before they ever reach training.
  for article in corpus:
      if screen_text(article["title"] + article["summary"]):
          continue                      # never taught to the model

  # Phase 2, runtime: screen the educator's input AND the model's output.
  if screen_text(user_input):           # before retrieval
      return BLOCK_MESSAGE
  answer = model.generate(...)
  if screen_text(answer):               # before anything is shown
      return BLOCK_MESSAGE

نتیجہ

مختصراً، یہ مضمون تعلیمی ایپس کے لیے تخلیقی ہینڈ آن پراجیکٹس کے ساتھ آنے کے لیے ایک چھوٹے سے LLM کو پڑھانے پر غور کرتا ہے۔

ہم نے پہلے سے تربیت یافتہ ماڈل، Qwen2.5-1.5B-Instruct سے شروعات کی، اور اسے Wikipedia کے STEAM اور ثقافت کے مضامین پر مبنی ڈیٹا سیٹ پر سکھایا۔

مقصد سادہ ان پٹ لینا تھا (معلم کے پاس موجود مواد، بچوں کی عمر کی حد، اور اختیاری عنوانات) اور انہیں ایک منظم JSON سرگرمی (عنوان، تفصیل، مرحلہ وار ہدایات، سیکھنے کے مقاصد، اور حفاظتی نوٹس) کے ساتھ جواب دینا تھا۔

راستے میں، ہم نے ویکیپیڈیا API کا استعمال کرتے ہوئے ڈیٹاسیٹ کی تعمیر، غیر متعلقہ زمروں اور غیر محفوظ مواد کو فلٹر کرکے، تربیتی جوڑے تیار کرکے، ماڈل کو LoRA کے ساتھ ٹھیک کرنے، معیار کا اندازہ لگا کر، تلاش کے اشاریہ کی تعمیر، ماڈل میں RAG کو شامل کرکے، K12 کے استعمال کے کیسز کے لیے اختتام سے آخر تک ایک چھوٹے سے LLM کو لاگو کرنے کی تکنیک کے ذریعے کام کیا۔

سب سے اہم بات یہ ہے کہ اسے ایک ہینڈ آن پروجیکٹ کے طور پر اس طرح بنانے نے ML/LLM اسپیس کے بنیادی خیالات کو تجریدی ہونے کی بجائے مجھے دلکش بنا دیا۔ مجھے امید ہے کہ یہ آپ کے لئے بھی ایسا ہی کرتا ہے!

وسائل

اوپر تک سکرول کریں۔