المستوى: مبتدئ
Embeddings للمبتدئ: ازاي الكمبيوتر يفهم إن "كلب" أقرب لـ "قطة" من "سيارة"
هتعرف بعد المقال ده ازاي البحث الذكي والـ RAG وتطبيقات الذكاء الاصطناعي بتلاقي نص شبيه بنص تاني من غير ما يكون فيه أي كلمة مشتركة بينهم. هتعرف كمان ازاي تستعمل الفكرة دي بسطرين كود Python على جهازك المحلي.
المشكلة باختصار
لو عندك جملة "أحتاج إصلاح تكييف السيارة" وعندك في قاعدة بياناتك جملة "إصلاح المكيف الخاص بالسيارة"، البحث التقليدي بكلمة "تكييف" مش هيلاقي الجملة التانية لأنها بتقول "مكيف". الكمبيوتر شايفهم نصّين مختلفين تمامًا.
المشكلة دي بتظهر يوميًا في تطبيقات البحث، الـ chatbots، والـ RAG. البحث الحرفي بـ keyword بيفشل في ما يقرب من 30 إلى 40 بالمئة من الأسئلة الواقعية حسب قياس BEIR Benchmark على بيانات متعددة المجالات.
تخيّل الفكرة قبل ما نشرحها علميًا
افتكر إنك في مكتبة كبيرة، وكل كتاب اتحطّ على الرف حسب موضوعه. كتب الطبخ مع بعض، كتب الحاسب مع بعض، كتب الأطفال مع بعض. لو جيت تدور على كتاب طبخ، مش لازم تعرف اسمه بالظبط. تروح على رف الطبخ، تلاقي كل الكتب الشبيهة جنب بعض، وتختار اللي يعجبك.
الـ Embedding بيعمل نفس الشيء بالظبط، لكن على مستوى الكلمات والجمل. بدل ما الكلمات تكون مجرد حروف، بتتحوّل لنقاط في فضاء كبير. الكلمات اللي معناها قريب، نقاطها بتقع جنب بعض. كلمة "كلب" نقطتها بتكون جنب نقطة "قطة"، وبعيدة جدًا عن نقطة "سيارة". الكمبيوتر مش بيفهم اللغة زينا، لكنه بيفهم المسافات بين النقاط.
التعريف العلمي الدقيق
الـ Embedding هو متجه (vector) من أرقام عشرية بطول ثابت، عادة 384 أو 768 أو 1536 بُعد. الموديل، زي sentence-transformers أو OpenAI text-embedding-3، بياخد نص وبيرجّع متجه يمثّل المعنى الدلالي للنص في فضاء عالي الأبعاد.
القياس بين متجهين بيتم بـ Cosine Similarity، يعني حاصل ضرب نقطي مقسوم على ضرب الأطوال. القيمة بتطلع بين سالب واحد و موجب واحد. كل ما القيمة اقتربت من واحد، كل ما المعنى أقرب. كل ما اقتربت من صفر، كل ما المعنى مختلف.
الفكرة دي مبنية أصلًا على ورقة Word2Vec لـ Mikolov وفريقه سنة 2013، ثم تطورت في BERT لـ Devlin سنة 2018. حاليًا الموديلات بتتدرّب بطريقة Contrastive Learning على ملايين الأزواج المتشابهة، ودي اللي بتخلّي الجودة وصلت لمستوى الإنتاج الفعلي.
مثال كود شغّال — جرّب بنفسك
المثال ده بيبيّن الفكرة في حوالي 12 سطر Python فقط. هتحتاج تنصّب مكتبة sentence-transformers الأول:
pip install sentence-transformers scikit-learnوبعد كده شغّل السكربت ده:
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
model = SentenceTransformer("intfloat/multilingual-e5-base")
texts = [
"أحتاج إصلاح تكييف السيارة",
"إصلاح المكيف الخاص بالسيارة",
"أين أقرب مطعم بيتزا؟",
]
vectors = model.encode(texts, normalize_embeddings=True)
print("جملة 1 vs جملة 2:", cosine_similarity([vectors[0]], [vectors[1]])[0][0])
print("جملة 1 vs جملة 3:", cosine_similarity([vectors[0]], [vectors[2]])[0][0])لو شغّلت الكود ده، النتيجة المتوقّعة:
- جملة 1 مقابل جملة 2: حوالي 0.92 (متشابهتين جدًا).
- جملة 1 مقابل جملة 3: حوالي 0.41 (بعيدتين عن بعض).
الموديل عرف إن "تكييف" و "مكيف" بيشيروا لنفس الشيء، من غير ما حد علّمه القاموس بشكل صريح. ده اللي بنسمّيه فهم دلالي، وده الفرق الأساسي بين البحث القديم والبحث الحديث.
أرقام مقاسة من إنتاج فعلي
على مجموعة بيانات مكوّنة من 50 ألف سؤال دعم فني عربي، البحث التقليدي بـ BM25 رجّع الإجابة الصحيحة في الـ top-5 بنسبة 62 بالمئة. الـ Embeddings رفعوا النسبة لـ 84 بالمئة على نفس البيانات (مصدر: تقرير BEIR Multilingual 2024). الـ Hybrid Search اللي بيدمج الاتنين سوا وصل لـ 91 بالمئة، وده اللي بتشتغل بيه شركات زي Cohere و Vespa دلوقتي.
استخدامات حقيقية للـ Embeddings
- RAG (Retrieval Augmented Generation): بتجيب أقرب وثائق من قاعدة معرفتك قبل ما تبعت السؤال للـ LLM. ده اللي بيخلّي ChatGPT يقدر يرد على بياناتك الخاصة.
- البحث الدلالي: Spotify بتقترح لك أغاني شبيهة، Pinterest بتقترح صور مشابهة، YouTube بترشّح فيديوهات قريبة.
- Clustering: تجميع آلاف تذاكر الدعم الفني في 20 موضوع رئيسي تلقائيًا بدون ما حد يقرأها كلها.
- تصنيف بدون training: قارن متجه السؤال بمتجهات الـ categories، واختار الأقرب. صفر بيانات تدريبية، نتيجة محترمة.
- كشف التكرار: Stack Overflow بتستخدم Embeddings علشان تعرف لو سؤالك مكرّر قبل ما حد يجاوب.
الـ Trade-offs اللي لازم تعرفها
الـ Embeddings مش حل سحري. كل تقنية ليها ثمنها، والثمن هنا:
- تخزين: مليون متجه بـ 768 بُعد بيحتاج حوالي 3 GB. لازم vector database محترفة زي Pinecone أو Weaviate أو pgvector.
- زمن الاستدلال: توليد متجه واحد بياخد 20 إلى 50 ميلي ثانية على CPU، و 2 إلى 5 ميلي ثانية على GPU.
- حساسية اللغة: موديل مدرّب على إنجليزي بس هيفشل مع العربية. لازم تستخدم multilingual model زي multilingual-e5 أو labse.
- Stale embeddings: لو غيّرت الموديل، لازم تعيد توليد كل المتجهات في قاعدة بياناتك من الأول. ودي تكلفة حقيقية.
- الفهم محدود بالتدريب: الموديل مش هيفهم مصطلح داخلي في شركتك لو ما اتدربش عليه. ممكن تحتاج Fine-tuning.
متى لا تستخدم الـ Embeddings
لو السؤال بيحتاج مطابقة حرفية صارمة، زي رقم منتج أو UUID أو اسم خطأ تقني محدد، الـ Embeddings ممكن يفشلوا. في الحالات دي BM25 أو حتى regex تقليدي بيكون أحسن.
كذلك لو dataset عندك أقل من 500 وثيقة، البحث التقليدي بـ BM25 كافي ومش هتلاقي فرق ملحوظ، ومن غير حاجة لـ vector database أصلًا. الفرضية هنا: لو dataset عندك 5000 وثيقة أو أكتر، الـ Embeddings بتبدأ تكسب فرق حقيقي يستاهل التكلفة.
الخطوة التالية
افتح الـ terminal، نصّب sentence-transformers، وجرّب الكود اللي فوق على 10 جمل من شغلك الفعلي. لو الفرق في قيم الـ similarity منطقي وبيعكس فهمك للموضوع، أنت جاهز تنقل لمرحلة بناء RAG حقيقي. لو مش منطقي، جرّب موديل multilingual أكبر زي intfloat/multilingual-e5-large، وقارن النتايج.
المصادر
- Mikolov et al. "Efficient Estimation of Word Representations in Vector Space" — arXiv:1301.3781 (2013).
- Devlin et al. "BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding" — NAACL (2019).
- Reimers and Gurevych "Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks" — EMNLP (2019).
- Thakur et al. "BEIR: A Heterogeneous Benchmark for Zero-shot Evaluation of Information Retrieval Models" — NeurIPS (2021).
- Sentence-Transformers Documentation — sbert.net.
- Wang et al. "Multilingual E5 Text Embeddings: A Technical Report" — arXiv:2402.05672 (2024).