الدرس 2 من 9

المعنى كأرقام: Embeddings

أهم فكرة في المرحلة دي كلها، وأساس البحث الذكي والـ RAG.

من رقم لمتجه

رقم الـ token لوحده مالوش معنى: token رقم 500 مش «أقرب» لـ 501. عشان كده الموديل بيحول كل token (أو جملة كاملة) لمتجه فيه مئات الأرقام اسمه embedding. والموديل بيتعلم يحط الحاجات اللي معناها قريب في أماكن قريبة.

🗺️ زي الخريطةتخيل خريطة: مصر الجديدة جنب مدينة نصر، وبعيدة عن إسكندرية. الـ embeddings خريطة للمعاني فيها مئات الأبعاد بدل اتنين: «قطة» جنب «كلب»، و«سعر الدولار» جنب «سعر الصرف»، وبعيدين عن بعض.

جرّب بنفسك: عربي وإنجليزي مع بعض

هنستخدم موديل embeddings بيفهم لغات كتير منها العربي، ونقيس التشابه بالـ cosine similarity اللي اتعلمناها في المرحلة ٣:

embeddings.py
from sentence_transformers import SentenceTransformer
from sentence_transformers.util import cos_sim

model = SentenceTransformer("sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2")

sentences = [
    "القطة نايمة على الكنبة",
    "The cat is sleeping on the sofa",
    "في كلب نايم على السرير",
    "سعر الدولار ارتفع النهارده",
]
vectors = model.encode(sentences)
print("vector size:", vectors.shape[1])

sims = cos_sim(vectors[0], vectors)[0]
for s, score in zip(sentences, sims):
    print(f"{score:.2f}  {s}")

الجملة الإنجليزي اللي بنفس المعنى جت قريبة جداً من العربي، رغم إن مفيش ولا كلمة مشتركة! وجملة الكلب النايم أقرب شوية من جملة الدولار اللي بعيدة خالص. الموديل بيقارن معنى مش حروف.

البحث بالمعنى (Semantic Search)

البحث العادي بيدور على نفس الكلمات. لو كتبت «إزاي أرجع الفلوس» وصفحة المساعدة مكتوب فيها «سياسة الاسترداد»، مش هيلاقيها. البحث بالـ embeddings هيلاقيها لأن المعنى قريب:

semantic_search.py
from sentence_transformers import SentenceTransformer
from sentence_transformers.util import cos_sim

help_pages = [
    "إزاي ترجع فلوسك: تقدر تسترد المبلغ خلال 14 يوم من الاستلام",
    "مواعيد الشحن والتوصيل لكل المحافظات",
    "إزاي تغير الباسورد بتاع حسابك",
    "طرق الدفع: فيزا وكاش ومحافظ إلكترونية",
]
query = "عايز فلوسي ترجعلي"

for name in ["sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2",   # small, ~470MB
             "BAAI/bge-m3"]:                                                  # strong, ~2.2GB
    model = SentenceTransformer(name)
    scores = cos_sim(model.encode(query), model.encode(help_pages))[0]
    print(f"{name.split('/')[-1]:40} -> {help_pages[scores.argmax()]}")

الموديل الصغير اتلخبط وجاب صفحة الباسورد! ليه؟ لأنه مش قوي كفاية في العربي والعامية المصرية، فمسك في حاجات سطحية في شكل الجملة بدل معناها. الموديل الأقوى جاب الإجابة الصح. الدرس المهم: موديل الـ embeddings بيفرق جداً، وخصوصاً مع العربي. اختبره دايماً على أسئلة حقيقية بلغة اليوزرز بتوعك قبل ما تعتمد عليه.

💡 embeddings للنص الطويلالموديلات دي بتحوّل جملة أو فقرة كاملة لمتجه واحد. لو عندك مستند ١٠٠ صفحة، بتقطعه فقرات وتعمل embedding لكل فقرة. هنعمل ده بالظبط في درس الـ RAG.
الدرس اللي فات