يا جماعة الخير، السلام عليكم ورحمة الله. معكم أخوكم أبو عمر.
بتذكر قبل كم سنة، كنا في الشركة شغالين على نظام أرشفة وبحث داخلي. الهدف كان بسيط: أي موظف جديد أو قديم يقدر يلاقي أي معلومة يحتاجها بسرعة. من سياسات الموارد البشرية للمستندات التقنية. الأمور كانت تبدو سهلة، لكن الواقع كان إشي ثاني خالص.
في يوم من الأيام، إجاني “تيكت” (طلب دعم فني) من موظف جديد، شب حماس وشاطر، خلينا نسميه خالد. خالد كان كاتب في التيكت: “يا جماعة، صارلي ساعة بحاول ألاقي معلومة عن الإجازة المرضية ومش ملاقي إشي! نظام البحث تبعكم شكله خربان”.
أنا بصراحة استغربت، ورحت بنفسي أجرب. كتبت في البحث: “كيفية الحصول على إجازة مرضية”. وفعلاً، النتائج كانت صفر! إما صفحات ما إلها علاقة بالمرة، أو لا شيء على الإطلاق. وقتها حسيت بغصة، كيف نظام صرفنا عليه وقت وجهد زي هيك يفشل في مهمة بسيطة؟
بعد شوية حفر وتنقيب، اكتشفت المصيبة. المستند الرسمي اللي فيه كل المعلومات كان عنوانه الرسمي “إجراءات وسياسة الإجازات السنوية والطارئة”. النظام تبعنا، اللي كان مبني على البحث بالكلمات المفتاحية (Keyword Search)، كان زي الأطرش في الزفة. هو بدور على كلمة “مرضية” وكلمة “إجازة” جنب بعض، ولما ما لقاهم، اعتبر إنه ما في إشي. ما قدر يفهم إنه “الإجازات الطارئة” هي نفسها اللي ممكن تشمل “الإجازة المرضية”. كان نظامنا يفهم الكلمات، لكنه كان أعمى تمامًا عن المعاني. كانت شغلانة بتجيب وجع الراس.
هذه الحادثة الصغيرة كانت الشرارة اللي خلتنا نغوص في عالم جديد وقتها، عالم أنقذنا من جحيم البحث الحرفي. عالم “التضمينات المتجهة” أو الـ Vector Embeddings.
المشكلة الكبيرة: لعنة البحث بالكلمات المفتاحية
قبل ما نحكي عن الحل السحري، خلينا نفهم أصل المشكلة. معظم أنظمة البحث القديمة (والكثير من الأنظمة الحالية للأسف) بتعتمد على طرق مثل:
- المطابقة الحرفية (Exact Match): لازم الكلمة تكون موجودة بالحرف في المستند.
- التكرار (TF-IDF): بتعطي وزن أكبر للكلمات النادرة والمهمة في المستند مقارنة بباقي المستندات.
- البحث الصرفي (Stemming/Lemmatization): بترجع الكلمات لأصلها (مثلاً “مكتبة”، “كتاب”، “كاتب” بترجعهم لجذر “ك ت ب”).
هذه الطرق ممتازة، وما زلنا نستخدمها، لكن عندها مشكلة جوهرية: هي لا تفهم السياق أو المعنى. الكمبيوتر بالنسبة له، كلمة “سيارة” وكلمة “مركبة” هما مجرد سلسلتين مختلفتين من الحروف. ما بيعرف إنهم بيشيروا لنفس المفهوم تقريبًا.
وهذا هو بالضبط ما حدث في قصة خالد. بالنسبة للنظام، جملة “إجازة مرضية” لا تشبه أبدًا جملة “سياسة الإجازات الطارئة”.
الحل الثوري: مرحباً بالتضمينات المتجهة (Vector Embeddings)
القصة وما فيها، إن جماعة الذكاء الاصطناعي فكروا وقالوا: “ليش ما نعلّم الكمبيوتر يفهم معاني الكلمات زي ما البشر بيفهموها؟”. الفكرة كانت بتحويل الكلمات والجمل إلى… أرقام. نعم، أرقام! بس مش أي أرقام، بل “متجهات” (Vectors) في فضاء رياضي متعدد الأبعاد.
طيب شو يعني “تضمين متجه” يا أبو عمر؟
تخيل معي عندك مكتبة ضخمة. بدل ما ترتب الكتب أبجديًا، قررت ترتبها حسب الموضوع. حطيت كل كتب التاريخ جنب بعض، وكتب الفيزياء في رف آخر، وكتب الطبخ في زاوية لحالها. الآن لو سألتك وين كتاب عن “الحملة الصليبية”، رح تروح مباشرة على قسم التاريخ، صح؟
التضمينات المتجهة بتعمل نفس الإشي بس للكلمات والجمل. هي عبارة عن خوارزميات ذكية (مثل Word2Vec, GloVe, BERT) بتقرأ مليارات النصوص من الإنترنت وبتتعلم العلاقات بين الكلمات.
النتيجة؟ كل كلمة أو جملة بتتحول لمتجه (قائمة طويلة من الأرقام، مثلاً 300 أو 768 رقم). والجمال هنا يكمن في أن الكلمات ذات المعاني المتشابهة يكون لها متجهات “قريبة” من بعضها في ذلك الفضاء الرياضي.
بمعنى آخر، متجه كلمة “ملك” سيكون قريبًا جدًا من متجه كلمة “سلطان”، ومتجه كلمة “تفاحة” سيكون قريبًا من “برتقالة” أكثر من قربه من “سيارة”.
الأجمل من هيك، إنها بتفهم علاقات أكثر تعقيدًا. المعادلة الشهيرة في هذا المجال هي:
متجه “ملك” – متجه “رجل” + متجه “امرأة” ≈ متجه “ملكة”
هذا يُظهر أن النموذج لم يحفظ الكلمات فقط، بل فهم العلاقة بينها (علاقة الجنس في هذه الحالة).
التطبيق العملي: كيف استخدمناها لحل مشكلة البحث؟
الآن نرجع لقصتنا. كيف حلينا مشكلة البحث باستخدام الـ Embeddings؟ العملية بتتم على خطوتين رئيسيتين:
- مرحلة التكشيف (Indexing):
- أولاً، مررنا على كل مستند في قاعدة بياناتنا (سياسات الموارد البشرية، الأدلة التقنية، إلخ).
- لكل مستند، استخدمنا نموذج ذكاء اصطناعي (Language Model) لتحويل محتوى المستند (أو فقرات منه) إلى متجه رقمي (Vector Embedding).
- خزّنا هذه المتجهات في قاعدة بيانات خاصة تسمى “قاعدة بيانات المتجهات” (Vector Database) مثل FAISS أو Pinecone، مع مؤشر يربط كل متجه بالمستند الأصلي.
- مرحلة البحث (Querying):
- لما يجي مستخدم زي خالد ويكتب في مربع البحث “كيف آخذ إجازة مرضية؟”.
- بنأخذ جملة البحث هذه، وبنفس النموذج، بنحولها هي كمان لمتجه رقمي.
- الآن، بدل ما نبحث عن كلمات، بنروح على قاعدة بيانات المتجهات وبنسأل: “يا قاعدة البيانات، أعطيني أكثر 5 متجهات مخزنة عندك قربًا من متجه البحث هذا؟”.
- النتائج اللي بترجع بتكون هي المستندات اللي معناها قريب من معنى سؤال المستخدم، حتى لو ما فيها نفس الكلمات بالضبط!
وبهذه الطريقة، لما بحثنا عن “إجازة مرضية”، النظام صار ذكي كفاية ليفهم إنها قريبة بالمعنى من “سياسة الإجازات الطارئة” ورجّعها كأول نتيجة. مشكلة خالد انحلت، وأبو عمر قدر يرجع يشرب فنجان قهوته براحة بال.
مثال بالكود (Python) للمطورين
حتى ما يكون كلامنا كله نظري، هاي قطعة كود بسيطة باستخدام مكتبة sentence-transformers الشهيرة بتوضح الفكرة. المكتبة هذه بتبسط العملية بشكل كبير.
# أولاً، لازم نثبّت المكتبات اللازمة
# pip install sentence-transformers scikit-learn
from sentence_transformers import SentenceTransformer, util
import torch
# الخطوة 1: تحميل نموذج مدرب مسبقًا (هذا النموذج متعدد اللغات ويدعم العربية)
# هذا النموذج سيقوم بتحويل الجمل إلى متجهات (vectors)
model = SentenceTransformer('distiluse-base-multilingual-cased-v1')
# الخطوة 2: تجهيز المستندات (قاعدة المعرفة تبعتنا)
# هذه هي المستندات اللي عنا في النظام
documents = [
"سياسة الشركة بخصوص الإجازات السنوية والطارئة.",
"دليل الموظف الجديد للتعرف على أقسام الشركة.",
"كيفية طلب جهاز كمبيوتر محمول جديد من قسم تقنية المعلومات.",
"مواعيد صرف الرواتب الشهرية.",
"فوائد أكل التفاح يومياً للصحة." # مستند ما إله علاقة عشان نشوف ذكاء النظام
]
# الخطوة 3: تحويل المستندات إلى متجهات (Embeddings)
# هذه العملية تسمى التكشيف أو Indexing
document_embeddings = model.encode(documents, convert_to_tensor=True)
# الخطوة 4: كتابة سؤال المستخدم (الـ Query)
query = "كيف آخذ إجازة مرضية؟"
# الخطوة 5: تحويل سؤال المستخدم إلى متجه
query_embedding = model.encode(query, convert_to_tensor=True)
# الخطوة 6: حساب التشابه بين متجه السؤال وكل متجهات المستندات
# نستخدم دالة "التشابه الجيبي" (Cosine Similarity) اللي بتقيس الزاوية بين المتجهات
# كلما كانت الزاوية أصغر، كان التشابه أكبر
cosine_scores = util.cos_sim(query_embedding, document_embeddings)
# الخطوة 7: إيجاد المستند الأكثر تشابهًا وعرض النتائج
# رح نربط كل نتيجة بالمستند الأصلي تبعها
results = []
for i in range(len(documents)):
results.append({
"document": documents[i],
"score": cosine_scores[0][i].item()
})
# ترتيب النتائج من الأعلى للأقل بناءً على درجة التشابه
sorted_results = sorted(results, key=lambda x: x['score'], reverse=True)
print(f"سؤال البحث: {query}n")
print("النتائج (مرتبة حسب التشابه الدلالي):")
for result in sorted_results:
print(f"- المستند: "{result['document']}" (درجة التشابه: {result['score']:.4f})")
لو شغلت هذا الكود، رح تلاحظ إن النتيجة الأولى على الأغلب رح تكون “سياسة الشركة بخصوص الإجازات السنوية والطارئة”، مع إن كلمة “مرضية” مش موجودة فيها. هذا هو سحر البحث الدلالي!
نصائح من خبرة أبو عمر
بعد شغل طويل في هذا المجال، هاي شوية نصائح عملية من أخوكم:
- اختر النموذج المناسب: مش كل النماذج زي بعض. في نماذج أفضل للغة العربية، نماذج أسرع بس أقل دقة، ونماذج أكبر وأكثر دقة بس بطيئة. ابدأ بنماذج متعددة اللغات مثل اللي في المثال فهي حل جيد كبداية.
- التنظيف المسبق لا يزال مهمًا: صحيح إن النماذج الحديثة قوية، لكن إزالة الحروف الزائدة، الأخطاء الإملائية، وتوحيد النص (Normalization) بيساعد في تحسين دقة النتائج.
- استخدم قواعد بيانات متخصصة للمشاريع الكبيرة: المثال اللي فوق ممتاز للبداية. لكن لو عندك ملايين المستندات، البحث في مصفوفة بسيطة بصير بطيء جداً. هنا يأتي دور قواعد بيانات المتجهات مثل
Pinecone,Weaviate,Milvus, أو حتى مكتبةFAISSمن فيسبوك، فهي مصممة للبحث في مليارات المتجهات بسرعة فائقة. - لا تنسَ البحث التقليدي: أحيانًا، دمج البحث الدلالي (Semantic Search) مع البحث بالكلمات المفتاحية (Keyword Search) بيعطي أفضل النتائج. هذا ما يسمى بالبحث الهجين (Hybrid Search).
الخلاصة: من الكلمات إلى ما يشبه الوعي 🚀
الانتقال من البحث الحرفي إلى البحث الدلالي باستخدام التضمينات المتجهة كان نقلة نوعية، مش بس في شركتنا، بل في عالم التكنولوجيا كله. صرنا قادرين نبني أنظمة بتفهم “قصد” المستخدم، مش بس الكلمات اللي بيكتبها.
هذه التقنية هي أساس الكثير من التطبيقات اللي بنستخدمها اليوم بدون ما نحس: توصيات يوتيوب ونتفليكس، أنظمة الإجابة على الأسئلة زي ChatGPT، وحتى لما تبحث في صور جوجل عن “عناق” فيرجعلك صور ناس بتحضن بعض بدون ما تكون كلمة “عناق” مكتوبة على الصورة.
نصيحتي الأخيرة إلك: لا تخاف من المصطلحات الكبيرة. الفكرة الأساسية بسيطة زي ما شرحنا. ابدأ بمثال صغير، جرب الكود، وغير فيه، وشوف بعينك كيف الكمبيوتر بدأ “يفهم” لأول مرة. صدقني، الشعور رائع.
والله ولي التوفيق.