عالم عِلم البيانات قد يكون مربكًا للمبتدئين، مليئًا بالمصطلحات المعقدة والمفاهيم المتشابكة. ولكن ماذا لو كان لديك مساعد ذكاء اصطناعي بجانبك، جاهز لشرح هذه المفاهيم بعبارات بسيطة وإرشادك خلال عملية التعلم؟ هنا تبرز قوة تقنية توليد المعلومات المدعوم بالاسترجاع (RAG). في هذا الدرس، سننطلق في رحلة تطبيقية لبناء أداة توضيحية مدعومة بالذكاء الاصطناعي للمفاهيم الأساسية في علم البيانات باستخدام نموذج RAG ونموذج اللغة Gemma.
لماذا RAG وGemma؟
تقنية RAG هي أداة قوية تجمع بين نموذج استرجاع (لتحديد المعلومات ذات الصلة) ونموذج توليد (لإنشاء نص يشبه الأسلوب البشري). وهذا يجعلها مثالية لمهام مثل شرح المواضيع المعقدة، حيث يمكنها الوصول إلى كميات هائلة من المعلومات ومعالجتها، ثم تقديمها بشكل واضح ومفهوم.
لقد اخترنا نموذج اللغة Gemma-1.1-2b-it، الذي طورته Google AI، كنموذج التوليد لدينا. يعد Gemma معروفًا بدقته وكفاءته وسهولة استخدامه، مما يجعله رفيقًا مثاليًا لنظام RAG الخاص بنا.
توليد المعلومات المدعوم بالاسترجاع (RAG) باستخدام Gemma لشرح المفاهيم الأساسية في علم البيانات
في هذا الدرس، سنستخدم نموذج توليد المعلومات المدعوم بالاسترجاع (RAG) لشرح المفاهيم الأساسية في علم البيانات. RAG يجمع بين نموذج استرجاع ونموذج لغة لتقديم استجابات ذات صلة ودقيقة للأسئلة المطروحة.
الخطوة الأولى: تثبيت الحزم المطلوبة
أولاً، لنقم بتثبيت الحزم الضرورية باستخدام pip
pip install transformers accelerate bitsandbytes langchain sentence-transformers chromadb gradio huggingface_hub
يجب إعادة تشغيل دفتر الملاحظات الخاص بك لتجنب أخطاء حزمة Gradio.
الخطوة الثانية: استيراد المكتبات المطلوبة
بعد ذلك، لنقم باستيراد المكتبات التي سنحتاجها
import os
import gradio as gr
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import Chroma
from langchain.chains import ConversationalRetrievalChain
from langchain_community.embeddings.sentence_transformer import SentenceTransformerEmbeddings
from langchain_community.llms import HuggingFaceEndpoint
الخطوة الثالثة: تحميل البيانات
دعونا نقوم بتحميل البيانات من مصدر على الويب. في هذا المثال، سنستخدم معجم مصطلحات علم البيانات
loader = WebBaseLoader("https://www.datascienceglossary.org/")
data = loader.load()
شرح الكود
إنشاء كائن تحميل (Loader Object) مصمم لاستدعاء ومعالجة البيانات من معجم علم البيانات
loader = WebBaseLoader("https://www.datascienceglossary.org/")
استدعاء طريقة load الخاصة بكائن التحميل. غالبًا ما تقوم هذه الطريقة بالخطوات التالية:
جلب محتوى الموقع
استخراج البيانات ذات الصلة (مثل التعريفات، قوائم المصطلحات)
هيكلة البيانات المستخرجة
data = loader.load()
الخطوة الرابعة: تقسيم المستندات
لتحسين الكفاءة، سنقوم بتقسيم المستندات إلى أجزاء أصغر
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)
splits = text_splitter.split_documents(data)
شرح الكود
الغرض: يهدف هذا الكود إلى تقسيم المستندات النصية الكبيرة إلى أجزاء أصغر وأكثر قابلية لإدارتها بسهولة. غالبًا ما يتم ذلك لتحسين الكفاءة في مهام معالجة اللغة الطبيعية، حيث قد تكون لدى النماذج قيود على كمية النصوص التي يمكن معالجتها في الدفعة الواحدة.
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)
يقوم هذا السطر بإنشاء كائن (object) يسمى text_splitter والذي ينتمي إلى فئة (class) RecursiveCharacterTextSplitter. تم تصميم هذه الفئة لتقسيم النص إلى أجزاء.
chunk_size=500 يتحكم هذا المعامل في الحجم الأقصى لكل جزء نصي. هنا، سيكون حجم كل جزء حوالي 500 حرف.
chunk_overlap=0 هذا المعامل يحدد مقدار التداخل بين الأجزاء. في هذا المثال، لن يكون هناك أي تداخل.
splits = text_splitter.split_documents(data)
يقوم هذا السطر بأخذ قائمة المستندات (التي نفترض أنها مخزنة في المتغير data)، ومن ثم تطبيق منطق تقسيم النصوص الذي تم تعريفه سابقاً على كل مستند.
نتيجة هذه العملية يتم تخزينها في المتغير splits، على الأرجح كقائمة جديدة يحتوي كل عنصر فيها على جزء أصغر من النص.
الخطوة الخامسة: إنشاء قاعدة بيانات المتجهات
سنستخدم SentenceTransformer لتضمين النص وإنشاء قاعدة بيانات المتجهات:
embedding = SentenceTransformerEmbeddings(model_name='all-MiniLM-L6-v2')
vectordb = Chroma.from_documents(documents=splits, embedding=embedding)
شرح الكود
الغرض: تهدف هذه الخطوة إلى تحويل البيانات النصية إلى متجهات رقمية (تضمينات - Embedding) وتخزينها في قاعدة بيانات متخصصة مصممة لعمليات البحث السريعة ومقارنة المتشابهات.
SentenceTransformerEmbeddings
embedding = SentenceTransformerEmbeddings(model_name='all-MiniLM-L6-v2')
يقوم هذا السطر بإنشاء كائنًا باسم embedding مسؤول عن توليد تضمينات للنصوص.
نستخدم هنا نموذج Sentence Transformers مدرب مسبقًا، يسمى 'all-MiniLM-L6-v2'. يقوم هذا النموذج بتحويل الجمل أو الفقرات إلى متجهات رقمية.
قاعدة بيانات المتجهات Chroma
vectordb = Chroma.from_documents(documents=splits, embedding=embedding)
يقوم هذا السطر بإنشاء قاعدة بيانات متجهة باسم vectordb مستخدما مكتبة كروما (Chroma).
documents=splits يستخدم النصوص المجزأة splits -التي تم إنشاؤها مسبقًا - كمدخلات.
embedding=embedding يحدد نموذج التضمين المستخدم لتوليد المتجهات لكل جزء نصي.
الخطوة السادسة: إنشاء مسترجع (Retriever)
الآن، سنقوم بإنشاء مسترجع باستخدام قاعدة بيانات المتجهات
retriever = vectordb.as_retriever(search_type="similarity", search_kwargs={"k": 2})
شرح الكود
الغرض: تهدف هذه الخطوة إلى إعداد آلية للبحث داخل قاعدة بيانات المتجهات التي تم إنشاءها مسبقًا. سيساعد المسترجع في العثور على أجزاء نصية مشابهة لغويًا لاستعلام معين.
retriever = vectordb.as_retriever(...)
يُنشِئ هذا السطر كائن المسترجع Retriever باستخدام vectordb (قاعدة بياناتك المتجهة من Chroma).
تُستَخدم طريقة .as_retriever() في Chroma لتحديد كيفية البحث داخل قاعدة البيانات.
search_type="similarity"
هذا المعامل يحدد نوع البحث. عند تعيينه إلى similarity، نخبر المسترجع بأن يبحث عن الأجزاء النصية في قاعدة البيانات بناءً على التشابه الدلالي مع مفردة الاستعلام بدلاً من التطابق التام أو طرق أخرى للبحث.
search_kwargs={"k": 2}
يتيح هذا المعامل تخصيص إعدادات البحث. في هذا المثال، k=2 يخبر المسترجع بإعادة أكثر جزأين تشابهًا مع مفردة الاستعلام من قاعدة البيانات.
هذا العدد يمكن تغييره حسب الحاجة، ليعيد المسترجع عددًا أكبر أو أقل من النتائج المتشابهة.
الخطوة السابعة: تحميل نموذج اللغة
سنستخدم نموذج لغة مُدرّب مسبقًا من Hugging Face
os.environ["HUGGINGFACEHUB_API_TOKEN"] = 'API_TOKEN'
repo_id = "google/gemma-1.1-2b-it"
llm = HuggingFaceEndpoint( repo_id=repo_id, max_length=1024, temperature=0.1)
شرح الكود
الغرض: تهدف هذه الخطوة إلى تحميل نموذج لغوي قوي مدرَّب مسبقًا يُدعى Gemma 1.1-2b-it من منصة Hugging Face. سيعمل هذا النموذج كمحور أساسي لتطبيقك، حيث يتيح له توليد النصوص، والإجابة على الأسئلة، وتنفيذ مهام لغوية أخرى.
إعداد رمز API
os.environ["HUGGINGFACEHUB_API_TOKEN"] = 'API_TOKEN'
يقوم هذا السطر بإعداد رمز API الخاص بمنصة Hugging Face، وهو ضروري للوصول إلى النماذج وتنزيلها من المنصة.
تحديد معرف النموذج
repo_id = "google/gemma-1.1-2b-it"
يحدد هذا السطر المعرف الفريد للنموذج المراد استخدامه من على منصة Hugging Face، حيث هنا يشير إلى النموذج Gemma 1.1-2b-it الذي تم تطويره بواسطة Google. يتيح هذا المعرف الكامل تحميل النموذج الصحيح من مستودع النماذج المتوفر على منصة Hugging Face.
تحميل النموذج
llm = HuggingFaceEndpoint(repo_id=repo_id, max_length=1024, temperature=0.1)
يقوم هذا السطر بإنشاء كائن بإسم llm من نوع HuggingFaceEndpoint. هذا الكائن يوفر واجهة تفاعلية مع النموذج اللغوي المحمَّل.
max_length=1024 يحدد الحد الأقصى لعدد الرموز (كلمات أو أجزاء من كلمات) التي يمكن للنموذج معالجتها في وقت واحد. يتيح هذا التحكم بطول النص الذي يتم معالجته أو توليده.
temperature=0.1 يضبط مقدار العشوائية في عملية توليد النص. القيم المنخفضة تجعل النص الناتج أكثر قابلية للتنبؤ وثباتًا، مما يؤدي إلى إجابات أكثر اتساقًا وموضوعية.
الخطوة الثامنة: إنشاء سلسلة مسترجع للمحادثات
سنجمع بين المسترجع المستند إلى المتجهات والنموذج اللغوي في مكون موحد لإنشاء تجربة محادثة طبيعية.
qa = ConversationalRetrievalChain.from_llm(llm, retriever)
شرح الكود
الغرض: تهدف هذه الخطوة إلى دمج المسترجع القائم على المتجهات (للبحث عن المعلومات ذات الصلة) مع النموذج اللغوي (لتوليد الإجابات) في مكوّن واحد قوي ومتكامل، مما يتيح إنشاء تجربة سؤال وجواب طبيعية وفعّالة للمستخدمين.
qa = ...
هذا السطر ينشئ كائنًا جديدًا يسمى qa يمثل سلسلة المسترجع للمحادثات. هذا الكائن سيكون المسؤول عن إدارة عملية البحث وتوليد النصوص للإجابة على أسئلة المستخدم.
ConversationalRetrievalChain.from_llm(llm, retriever)
ConversationalRetrievalChain هي فئة (class) توفرها مكتبة مثل langchain، وهي مصممة لإنشاء سلاسل تجمع بين نماذج لغوية أو مكونات أخرى، وتسمح بدمج مسترجعات مع نماذج توليد النصوص.
.from_llm() هي طريقة توفر وسيلة مبسطة لإنشاء السلسلة باستخدام نموذج لغوي. تختصر هذه الطريقة الخطوات المطلوبة لربط النموذج اللغوي بالمسترجع، مما يسهل إعداد السلسلة.
llm كائن llm يمثل النموذج اللغوي الذي تم تحميله مسبقًا، وهو المسؤول عن توليد النصوص بناءً على السياق والاستعلامات التي يقدمها المستخدم.
retriever يمثل المسترجع الذي قمت بإنشائه في الخطوات السابقة. حيث يقوم بالبحث في قاعدة بيانات المتجهات للعثور على المعلومات الأكثر ارتباطًا بمفردة الاستعلام.
الخطوة التاسعة: تعريف دالة تنفيذ المحادثة
def execute_conversation(question):
chat_history = []
result = qa({"question": question, "chat_history": chat_history})
chat_history.append(result["answer"])
return result["answer"]
شرح الكود
الغرض: تهدف هذه الخطوة إلى إعداد دالة بإسم execute_conversation تتولى تنفيذ المنطق الأساسي للتفاعل مع نظام الذكاء الاصطناعي الخاص بالمحادثات. تقوم الدالة باستقبال سؤال من المستخدم وتولد الإجابة باستخدام سلسلة المسترجع التي تم إنشاؤها سابقًا، مما يتيح تجربة محادثة متكاملة.
chat_history = []
يتم إنشاء قائمة فارغة باسم chat_history لتخزين تطور المحادثة. هذه القائمة ستحتفظ بتسلسل الأسئلة والإجابات، مما يضمن تتابع المحادثة واستمرارية السياق.
result = qa({"question": question, "chat_history": chat_history})
يتم استدعاء كائن qa، الذي يمثل سلسلة المسترجع للمحادثات.
يتم تمرير قاموس يحتوي على مُدخلين
question يحتوي على السؤال الحالي الذي طرحه المستخدم.
chat_history يتضمن سجل المحادثة حتى اللحظة.
تقوم سلسلة المسترجع بتحليل المدخل وتوليد نتيجة تحتوي على إجابة تناسب السؤال المطروح وتستند إلى المعلومات ذات الصلة.
chat_history.append(result["answer"])
يتم إضافة الإجابة التي تم توليدها والمخزنة في result["answer"] إلى chat_history، مما يسمح للنظام بتحديث سياق المحادثة وتذكر الإجابات السابقة عند التعامل مع أسئلة جديدة.
return result["answer"]
يقوم هذا السطر بإرجاع الإجابة الناتجة التي تم توليدها كمُخرج نهائي للدالة
الخطوة العاشرة: تعريف الأسئلة والحصول على الإجابات
الآن يمكنك تعريف الأسئلة والحصول على إجابات باستخدام دالة execute_conversation
من الأفضل اختيار الأسئلة من هذه الصفحة 🔗 لضمان الحصول على أجوبة دقيقة وذات صلة.
question1="What is data science?"
print(execute_conversation(question1))
question2="What is correlation?"
print(execute_conversation(question2))
question3="What is Mean Squared Error?"
print(execute_conversation(question3))
الخطوة الحادية عشر: إنشاء واجهة Gradio
في هذه الخطوة الأخيرة، سنقوم بإنشاء واجهة تفاعلية باستخدام مكتبة Gradio للتفاعل بسهولة مع النموذج.
من الأفضل اختيار الأسئلة من هذه الصفحة 🔗 لضمان الحصول على أجوبة دقيقة وذات صلة.
chatbot = gr.Interface(
fn=execute_conversation,
inputs="text",
outputs="text",
live=False,
title="RAG using Gemma to explain basic data science concepts.",
description="Enter your question",
)
chatbot.launch()
ما هو Gradio؟
Gradio هي مكتبة بايثون تُسهل إنشاء واجهات ويب بصرية بشكل سريع لعرض نماذج تعلم الآلة وتفاعل المستخدمين معها. توفر Gradio طريقة ملائمة لعرض واختبار ومشاركة النموذج اللغوي مع المستخدمين.
شرح الكود
الغرض: تهدف هذه الخطوة إلى إنشاء واجهة تفاعلية باستخدام مكتبة Gradio للتفاعل والتواصل مع النموذج.
fn=execute_conversation
fn تحدد هذه الخاصية الدالة الرئيسية التي ستستخدمها الواجهة لمعالجة مدخلات المستخدم وإنتاج المخرجات. في هذه الحالة، تم اختيار دالة execute_conversation والتي تُنفذ منطق نموذج RAG الذي تم تصميمه مسبقًا.
inputs="text"
يحدد أن الواجهة ستحتوي على حقل إدخال نصي حيث يمكن للمستخدم كتابة سؤاله.
outputs="text"
يوضح أن الاستجابة الناتجة من النموذج ستظهر كنص.
live=False
يعني أن الواجهة لن تقوم بتحديث وعرض النتيجة تلقائيًا مع الكتابة، بل سيُعالج السؤال فقط بعد أن يضغط المستخدم على زر الإرسال.
title="..."
يحدد عنوان واجهة Gradio الذي يظهر في تبويب المتصفح.
description="..."
يوفر تعليمات قصيرة أو توجيهًا للمستخدم أسفل حقل الإدخال.
كيفية عمل الواجهة في سياق RAG
إدخال المستخدم عند الدخول إلى الواجهة، يقوم المستخدم بكتابة سؤاله حول مفهوم معين في علم البيانات في حقل الإدخال المخصص للنص.
معالجة السؤال بعد إرسال السؤال، تقوم Gradio باستدعاء الدالة execute_conversation لمعالجة المدخل، حيث يحدث ما يلي:
الاسترجاع يعتمد نموذج RAG على قاعدة البيانات لاسترجاع الوثائق أو المقاطع النصية ذات الصلة من قاعدة المعرفة.
التوليد يولد النموذج إجابة شاملة باستخدام المعلومات المسترجعة ومعرفته بمفاهيم علم البيانات.
إخراج النتيجة تُرسَل الإجابة المولدة إلى واجهة Gradio وتُعرض في منطقة النص المخصصة للنتائج.
تشغيل الواجهة
chatbot.launch()
يقوم هذا السطر بتشغيل الخادم الخاص بـ Gradio وعرض واجهة المحادثة في المتصفح، مما يتيح الوصول بسهولة إلى تطبيق الدردشة لطرح الأسئلة والحصول على إجابات فورية.
الخاتمة
في هذا الدرس، استعرضنا كيفية استخدام نموذج اللغة Gemma مع تقنية RAG لتوضيح مفاهيم علم البيانات الأساسية. من خلال دمج قدرات Gemma مع ميزات الاسترجاع والتوليد الخاصة بـ RAG، يمكننا إنشاء أداة فعالة تساعد على فهم وشرح المفاهيم المعقدة بطريقة مبسطة وسهلة للمستخدم.
اطلع على المشروع في دفتر الملاحظات
هذا الدرس قُدّم كمشاركة في مسابقة "كيجل - Kaggle"
@misc{data-assistants-with-gemma,
author = {Paul Mooney, Ashley Chow},
title = {Google – AI Assistants for Data Tasks with Gemma},
publisher = {Kaggle},
year = {2024},
url = {https://kaggle.com/competitions/data-assistants-with-gemma}
}