خان المُبرمجين (علي فاضل)
539 subscribers
91 photos
9 videos
115 links
قناة أنشر فيها ما أتعلمه خلال عملي على مشاريعي الخاصة 👀
Download Telegram
محطة جديدة في رحلة منصة باحث: الانتقال من ChromaDB إلى Qdrant 🚀

الحمدلله رب العالمين، خطوة الانتقال هذه كانت مؤجّلة منذ أشهر طويلة، ولكن بعد الانتقال من Kamal V1 إلى Kamal V2، وكمال هي الأداة المستخدمة في نشر (Deploy) منصة باحث، واجهت مشكلة مع ChromaDB أجبرتني على اتخاذ القرار والمضي قدمًا.

المضحك في الأمر أن الانتقال لم يستغرق سوى 5 أو 6 أيام فقط!

وهنا يظهر تأثير "الخوف من المجهول". كنت أؤجل هذه الخطوة مرارًا بسبب التفكير المستمر بها، لكن عندما اضطررت لخوض التجربة، تمّت بسلاسة وفي وقت ممتاز، بفضل الله.

الأحاديث الآن تعمل بالكامل على Qdrant
📚 والمكتبة الشاملة يتم تحويل صفحاتها إلى تضمينات (Embeddings) وستنتهي العملية خلال الأيام القادمة بإذن الله.

من أبرز فوائد الانتقال إلى Qdrant:
⚡️ سرعة أعلى في الإضافة والاسترجاع
🎯 دقة أفضل بفضل تحسين النماذج وأخذ النص الكامل بعين الاعتبار
🛠 تجربة برمجية أسهل وأكثر مرونة

لكل من يؤجل خطوة تقنية بسبب الخوف أو الغموض: أحيانًا نحتاج فقط إلى دفعة، والباقي يأتي تباعًا.

رابط منصة باحث:
https://baheth.ieasybooks.com
11
Media is too big
VIEW IN TELEGRAM
للمبرمجين: انتهينا من تحويل كافة كتب المكتبة الوقفية إلى نصوص 🚀

نستعرض في هذا المقطع كيفية الاستفادة من كتب المكتبة الوقفية بعد أن حوّلناها من ملفات PDF إلى نصوص باستخدام Google Document AI بصيغة TXT 📄 و DOCX 📝

يمكن الاستفادة من هذه البيانات في بناء تطبيقات للبحث أو التلخيص أو غيرها من قِبل المطوّرين ونشرها لتعم الفائدة بإذن الله

رابط المقطع على YouTube:
https://youtu.be/qxO0GTz-cp8

رابط مستودع البيانات غير المضغوطة
رابط مستودع البيانات المضغوطة
6
This media is not supported in your browser
VIEW IN TELEGRAM
لغير المبرمجين: واجهة لتحميل ملفات المكتبة الوقفية بصيغ PDF و TXT و DOCX 🚀

قمنا ببناء واجهة تسمح للمستخدم بالبحث في كتب المكتبة الوقفية باستخدام العنوان وفرز النتائج حسب التصنيف والمؤلف وتحميل ملفات الكتاب بأي صيغة شاء

رابط المقطع على YouTube:
https://youtu.be/VE3NJr5Fo8U

رابط واجهة البحث والتحميل
رابط منشور البارحة
4
خان المُبرمجين (علي فاضل)
Photo
كدت أُشلّ 🫠

أجريت بعض التعديلات على مكتبة تحويل خلال الأيام الماضية تسمح باستخدام أكثر من Service Account Credentials من GCP لتحويل أكثر من ملف PDF أو صورة في نفس الوقت إلى نصوص:
https://github.com/ieasybooks/tahweel

وبدأت باستخدام هذا التعديل وكانت النتائج مرضية، فأصبحت قادرا على تحويل الملفات بشكل أسرع من السابق، ولكن حاصرني سؤال قبل قليل: "مكتبة تحويل تُحوّل ملفات الـ PDF إلى صور قبل تحويلها إلى نصوص وتُخزّنها في مجلد واحد مشترك، فهل صور الملفات المختلفة تتداخل؟".

لم أستطع النوم ودخلت على الشيفرة البرمجية من الهاتف للتحقق فوجدت أنني أحتفظ بملفات الصور الخاصة بأكثر من ملف PDF في مجلد عشوائي مشترك 😨:
https://github.com/ieasybooks/tahweel/blob/main/tahweel/managers/pdf_file_manager.py#L19-L35

ببساطة، هذا يعني أن كل ما كنت أُفرّغه في الفترة الماضية من كتب يحتاج إلى إعادة نظر، خصوصا وأنني كنت أُحوّل مجموعات مختلفة من الكتب بالتوازي على نفس الحاسب.

قبل أن تبدأ نوبة الذعر الداخلية، شغّلت الحاسب ووضعت ملفَّي PDF في مجلد واحد، الأول باللغة العربية والثاني باللغة الإنجليزية وبدأت بتحويلهما إلى نصوص باستخدام تحويل ونظرت في النتائج لأكتشف أن النتائج لا مشكلة فيها، فأعدت الكرة مرة أخرى وكان الأمر نفسه.

في هذه اللحظة أوقفت الشيفرة البرمجية المسؤولة عن حذف ملفات الصور من المجلد المشترك لأنظر فيه وأتأكد من التداخل بين صور الملفات المختلفة بعيني:
https://github.com/ieasybooks/tahweel/blob/main/tahweel/managers/base_file_manager.py#L104-L106

فلما فتحت المجلد المشترك، رأيت ما هو موضّح في الصورة المرفقة مع المنشور 🤓

ببساطة، قلقي لم يكن في محله، فمكتبة pdf2image تستخدم UUID4 تلقائيا في تسمية ملفات الصور الخاصة بكل ملف PDF، فالتداخل شبه مستحيل 🥳

هذا لا يعني أن ما فعلته كان صحيحًا، فالأفضل إنشاء مجلد خاص لكل ملف PDF يجري تحويله إلى نص، ولكن هذا تعديل مستقبليّ قد يساهم أحدكم في تنفيذه 😁

والسلام عليكم 👋🏻
👍65
هذه المقالة مهمة لكل مطوِّري الواجهات، وخصوصا مُحبِّي React:
https://infrequently.org/2024/11/if-not-react-then-what

ومن وجهة نظري -التي لا يُعتد بها في أي محفل من المحافل المحلية أو الدولية- لا حاجة لاستخدام أي أُطر عمل أو مكتبات معقدة لبناء الواجهات في مُعظم الحالات والمواقع، باستثناء أشياء بسيطة وخفيفة جدا لإنجاز بعض المهام وترتيب بعض الملفات كـ StimulusJS، لا أكثر ولا أقل..
👍31
يوجد Just In Time Compiler (JIT) للغة Ruby اسمه YJIT، من تطوير شركة Shopify وأُضيف بعد تطويره إلى اللغة بشكل رسمي، وحقق نتائج ممتازة يمكن الاطلاع عليها من هنا:
https://speed.yjit.org

لمن يحب أن يتعرّف أكثر على الـ JIT Compilers فيمكنه مشاهدة هذه المادة (لم أجد شيئًا عربيًّا، فمن يجد يُشارك رجاءً):
https://www.youtube.com/watch?v=d7KHAVaX_Rs

قرأت البارحة خبرًا أن فريق شركة Shopify المُنتج لـ YJIT يعمل على JIT Compiler جديد للغة Ruby واسمه ZJIT (مُبدعون في الأسماء)، وهذه الـ Issue التي يقترح فيها الفريق دمج الشيفرة المصدرية المبدئية للـ JIT Compiler الجديد في مستودع لغة Ruby الأساسي:
https://bugs.ruby-lang.org/issues/21221

استوقفني أن المبرمجة التي أنشأت الـ Issue ليست مجرد مبرمجة هاوية تعلّمت البرمجة من YouTube وأصبحت بطريقة إعجازية في فريق إنشاء YJIT و ZJIT، إنما حصلت على درجة الدكتوراه في هذا المجال وتعمل في هذا الفريق بناء على ما درسته (بالإضافة إلى الخبرة العملية بكل تأكيد).

فالمقصد أن شعارات "الجامعة لا تنفع" و"الدراسة الجامعية مضيعة للوقت" وغيرها من الشعارات من هذا النوع تحتاج إلى إعادة نظر وتسويقها قد يَضر ولا ينفع.

تستطيع تعلّم أُطر العمل وبناء المواقع والتطبيقات وغيرها الكثير من الأمور من YouTube وقد تتخصص في بعض الأمور، ولكن إخراج كفاءات بجودة عالية في مجالات دقيقة لا أظنه ممكنا من خلال YouTube وغيرها من المنصات دون الخبرة الحقيقية والدراسة المنهجية الأكاديمية "عالية الجودة".

والسلام عليكم 👋🏻
6
من أهم الأشياء عند إنشاء أي مكتبة أو Script لمعالجة مجموعات ضخمة من البيانات هو الاحتفاظ بتقدّم المُعالجة وعدم تنفيذ نفس العملية أكثر من مرة على نفس المدخلات.

سابقا، كنت أكتب بعض الـ Scripts -إما لمعالجة البيانات أو جمعها من بعض المواقع وغيرها من الأمور- دون التدقيق على هذا الأمر، فعند حدوث أي خطأ أثناء التنفيذ، أجد أنني خسرت كل التقدّم الذي أحرزته، وقد يكون هذا التقدم أياما أو حتى أسابيع.

يمكن الاحتفاظ بالتقدّم في المعالجة بطريقتين:
- حفظ التقدّم صراحةً على ملف خارجي أو في قاعدة بيانات مستقلّة
- حفظ التقدّم ضمنيًّا من خلال التأكد من وجود المخرجات المُتوقّعة

من أمثلة النوع الأول مكتبة yt-dlp، فهي تحتفظ بتقدّم تنزيل المقاطع من YouTube (أو غيره) في ملف TXT من خلال تمرير الاختيار download-archive-- للمكتبة عند تشغيلها.

ومن أمثلة النوع الثاني مكتبتَيْ تفريغ وتحويل، فهُما يتجاوزان أي ملف من ملفات المدخلات في حال وجود المخرجات المُتوقّعة منه.

من محاسن النوع الأول أنه لا يفترض أي افتراضات ويمكنك تعديل حالة التقدّم من خلال التعديل في مكان واحد، الملف أو قاعدة البيانات، ومن مساوئه أنك تحتاج للاحتفاظ بالمخرجات الحقيقية بجانب ملفات حالة التقدّم.

أما النوع الثاني فهو عكس الأول، فمن محاسنه أنك لا تحتاج للاحتفاظ بملفات حالة التقدّم، ولكنك تحتاج لحذف أجزاء من المخرجات الحقيقية في حال أردت معالجة جزء من البيانات مرة أخرى.

ختامًا، سواءً استخدمت الطريقة الأولى أو الثانية، فيجب عليك الاحتفاظ بحالة تقدّم معالجة البيانات التي تعمل عليها، لا تنسى هذا الأمر أبدا 😁

والسلام عليكم 👋🏻
👍41👌1
معلومة قد تفيدك

أحتاج أحيانا إلى البحث عن مشكلة في مكتبة من المكتبات التي أستخدمها في المشروع الذي أعمل عليه، ومن طرق البحث عن المشكلة تعديل ملفات المكتبة الموجودة على جهازي مباشرة والتحقق من مخرجات بعض الدوال أو مدخلاتها.

في لغة Python، يمكنك الوصول إلى مسار المكتبة التي تستخدمها على جهازك باستخدام __file__، فمثلا إذا أردت أن تصل إلى مسار مكتبة تفريغ يمكنك كتابة:

import tafrigh
print(tafrigh.__file__)


ثم تفتح مجلد المكتبة على محررك المفضل مثل VSCode.

كذلك في لغة Ruby، يمكنك فتح المكتبة بشكل مباشر من خلال الأمر:

bundle open {gem name}


بهذه الطريقة تستطيع تعديل الملفات وتشغيل مشروعك واختبار التعديلات دون الحاجة لأي تفاصيل إضافية مثل تنزيل الشيفرة البرمجية للمكتبة عندك وإجراء التعديلات المطلوبة ثم تثبيتها والتجربة.

هذه الطريقة تفيد في التجارب السريعة وإجراء تعديلات المرة الواحدة.
2
نصائح عامة (أتَّبعها شخصيًّا) عند العمل على المشاريع البرمجية "المشتركة":

📝 اتبع تنسيق المشروع الموجود مسبقًا ولو لم يعجبك، فالمشاريع الموجودة لها تنسيق بالفعل ولا يجب تغييره إلا عند الحاجة المُلِحة.

🔄 لا تُجرِ أي تعديلات مباشرة على المستودع وافتح PR جديدًا لكل تعديل، إلا في الحالات الشاذة وبالاتفاق مع الفريق.

🎯 حاول إنشاء PR مُركّزة ولا تُجرِ تعديلين مختلفين في نفس الـ PR.

📦 حاول تقسيم العمل ضمن نفس الـ PR على مجموعة من الـ commits وضع رسائل مفهومة تشرح التعديل ضمن الـ commit الواحد.

📄 حاول توثيق التعديل في الـ PR من خلال إضافة التفاصيل المهمة مثل التحسينات على الأداء وغيرها.

🧪 لا تفتح أي PR بدون إضافة حالات اختبار منطقية ومفيدة لها.

📚 لا تنسَ دائمًا تحديث التوثيق الخاص بالمشروع سواء في ملف README.md أو غيره.

🖼️ في الحالات المثالية، لا يجب أن يحتاج زميلك إلى اختبار تعديلك على جهازه، فأضِف التفاصيل المهمة في الـ PR نفسها مثل صورة لشكل الواجهة الجديدة أو مقطع مرئي تُظهر فيه التعديل الذي أجريته على أكثر من صفحة.

💬 لا تفترض أنك حللت المشكلة التي علّق بها زميلك على الـ PR وتغلق التعليق، إنما رد على تعليق زميلك بأنك حللت المشكلة وانتظر رده أو إغلاقه للتعليق.

🔀 عندما يُوافق زميلك على الـ PR الخاصة بك، فيجب عليك أن تدمجها مع المستودع من خلال استخدام خيار Squash and Merge.

🤝 زميلك لا يُريد إحراجك في التعليقات، هو فقط يُحاول أن يُحافظ على استمرارية المشروع من خلال ضمان جودة الشيفرة البرمجية المكتوبة.

أخيرًا، اترك المكان أفضل مما كان، من خلال تحسين طريقة الكتابة في الملف الذي تعدل عليه أو إضافة حالة اختبار جديدة مثلًا.

والسلام عليكم 👋🏻
7👍3
جولة في الشيفرة المصدرية لميزة "تواصل معنا" في منصة باحث 👨‍💻
https://www.youtube.com/watch?v=u3bqCpmoQ7g

لمن أراد أن يتعرّف على Ruby on Rails والشيفرة المصدرية لمنصة باحث بشكل أكبر، وأعتذر على كثرت التفاصيل في المقطع ولكن حاولت المرور على كامل الميزة من بداية إنشاء جدول قاعدة البيانات إلى إضافة حالات الاختبار
7🔥1
خان المُبرمجين (علي فاضل)
Photo
جمعة مباركة 🕌

نشرت في اليومين الماضيين مقطعين على قناتي -لعلها تكون عودة بعد انقطاع- وأصر أحد أصدقائي عليَّ لإضافة فصول (Chapters) إلى المقاطع، ففكّرت في الاستعانة بـ Gemini 2.5 Flash لإنجاز المهمة 😁

أرسلت له رابط المقطع الثاني من YouTube، وهو الأقصر، وقلت له:

Generate YouTube chapters for the given video in Arabic.

مع تفعيل خيار المخرجات المنظمة أو Structured Output وتمرير الـ Schema الموضّحة في الصورة، وكانت النتائج ممتازة "مع بعض التعديلات"، يمكنك الاطلاع عليها من خلال المقطع نفسه:
https://www.youtube.com/watch?v=S3EPbM7Eh28

بدأت بعدها في المقطع الأول، وللأسف كان عدد الرموز (Tokens) أطول من السياق (Context) الذي يستطيع النموذج التعامل معه، فقررت استخدام الملف الصوتي بصيغة MP3 بدلا من المقطع المرئي لتقليل الرموز، ولكن النتائج كانت سيئة جدا.

فحمَّلت التفريغ النصي للمقطع بصيغة SRT من YouTube باستخدام موقع كهذا:
https://downsub.com

وغيّرت صيغة الملف إلى TXT لأن Gemini لا يدعم SRT ورفعت الملف مع نفس الجملة وتفعيل خيار المخرجات المنظمة بنفس الـ Schema:

Generate YouTube chapters for the given video in Arabic.

وكانت النتائج ممتازة "مع بعض التعديلات"، ويمكنك الاطلاع عليها من خلال المقطع نفسه:
https://www.youtube.com/watch?v=u3bqCpmoQ7g

لم يستغرق الأمر أكثر من 20 دقيقة، مع الأخذ بعين الاعتبار الوقت الضائع في استكشاف النموذج وتطويعه لهذه المهمة، أما في المستقبل فسيكون أسرع بإذن الله.

والسلام عليكم 👋🏻
6
السلام عليكم ورحمة الله وبركاته،

هذه نصيحة موجَّهة لكل من يستخدم الذكاء الاصطناعي في الأمور الشرعية. ولعلّي أكون مخطئًا فيها، ولكن هذا ما انتهى إليه علمي المتواضع.

الذكاء الاصطناعي ليس ذكاءً حقيقيًا، وإنما مجرد نموذج إحصائي يتنبّأ بالكلمة التالية بناءً على السياق السابق لها.

لذلك، لا تطلب منه أن يقدّم لك عشرة أحاديث في فضل صيام شهر رمضان، أو أن يأتيك بكل ما ذكره ابن القيّم في كتبه عن مسألة معيّنة، أو غير ذلك من الأمثلة التي تحتاج إلى بحث دقيق والرجوع إلى مصادر موثوقة لاستخراجها.

استخدم الذكاء الاصطناعي في تلخيص الكتب واستخلاص المعلومات منها بعد أن تزوده بالكتاب بصيغة PDF أو نحوها.

ولا تعتمد على قدرته على الاسترجاع من "ذاكرته" أو من المواد التي "تدرّب" عليها.

وهذا يشمل جميع النماذج من مختلف الشركات، بما فيها ChatGPT و Gemini و Claude وغيرها، ولا يشمل الحلول المتخصصة المبنية على قواعد بيانات شرعية يعتمد عليها النموذج في البحث والإجابة.
14👏1
نداء إلى المصممين 🎨

بدأت العمل على مشروع جديد منذ شهر تقريباً، وخلال عملي، بحثت طويلاً ولم أجد أيقونة بصيغة PNG أو SVG تُعبّر عن عملية "إخفاء/إظهار التشكيل".

نحتاج في المشاريع المُتعلّقة باللغة العربية إلى أيقونة لاستخدامها في زر "إخفاء/إظهار التشكيل" تشبه الأيقونات الموجودة في هذا الموقع: https://phlex-icons.fun

ويُفضّل أن تكون هذه الأيقونة بصيغة SVG.

فمن كان له خبرة وهِمَّة في تصميم شيء كهذا أكن له (وكل من يعمل على هذا النوع من المشاريع) من الشاكرين 😁
6
"إن كان لا بد من تكرار العمل أكثر من ثلاث مرات، فالأَولى أتمتته"

خلال السنوات الأخيرة أنشأت العديد من مشاريع Ruby on Rails الجانبية، منها ما يعمل إلى هذه اللحظة ومنها ما كان مجرد فكرة للتجربة.

في كل مرة كنت أبدأ في بناء المشروع من الصفر وأُضيف المكتبات التي أحتاجها وأُعدّها، وكان ذلك يستغرق وقتًا طويلًا وينتج عنه بعض الأخطاء أحيانا، وكان يتخلله كثير من النسخ واللصق.

إلى أن قررت في الأسابيع الماضية أن أُنشئ قالبًا يُمكن إعادة استخدامه في كافة مشاريع Ruby on Rails المستقبلية.

يتضمن القالب العديد من الاختيارات الشخصية، قد تتفق معها أو تختلف، لكنه قد يفيدك بمنحك فكرة جديدة أو نظرة على مكتبات لم تكن تعلم عنها من قبل.

يمكنك الاطلاع على القالب والبدء في استخدامه من هنا:
https://github.com/ieasybooks/ruby-on-rails-template

من ميزات القالب:
- بيئة تطوير جاهزة للاستخدام بكافة تفاصيلها
- التكامل مع محرك بحث Meilisearch
- أدوات لمراقبة أداء مشروعك مُعدّة مسبقا
- إمكانية بناء واجهات قابلة لإعادة الاستخدام

وهناك المزيد من التفاصيل يمكنك الاطلاع عليها من خلال الرابط أعلاه ⬆️

والسلام عليكم 👋🏻
5
خلال العمل على أحد المشاريع في الشهرين الماضيين (لعله ينطلق خلال أيام بإذن الله) بدأت باستخدام أداة active_record_doctor الجديدة بالنسبة لي، والقديمة بالنسبة للكثيرين.

مهمة الأداة مراقبة قاعدة البيانات الخاصة بالمشروع وتنبيهك إلى بعض الأمور التي من شأنها تحسين أداءها أو تقليل الأخطاء.

على سبيل المثال، نبهتني الأداة بالأمس أنني أستخدم dependent: :destroy بدلا من dependent: :delete_all عند تعريف العلاقة بين جدولين في Ruby on Rails دون الحاجة لاستخدام destroy، ولكن ما هي هذه العلاقات؟

في Ruby on Rails، يمكنك تحديد العلاقات بين الجداول بطريقة سهلة. فمثلا، إذا كان في مشروعك جدول للمستخدمين وجدول لمنشوراتهم، يمكنك تعريف العلاقات كما هو موضّح في الصورة.

عند تعريف علاقة المستخدم بالمنشور نستخدم has_many، أي أن كل مستخدم له العديد من المنشورات، وعند تعريف علاقة المنشور بالمستخدم نستخدم belongs_to، أي أن كل منشور ينتمي إلى مستخدم واحد.

في has_many نستطيع تحديد الخيار dependent والذي بدوره يُحدد كيف سنتعامل مع المنشورات في حال حذف المستخدم.

الخيار destroy يحذف المنشورات في حال حذف المستخدم، وكذلك الخيار delete_all ولكن باختلاف بسيط.

الخيار destroy يحذف كل منشور على حدة ويتأكد من أن الـ Callbacks تعمل كما ينبغي (كأن تحذف المنشور من مُحرّك البحث بعد حذفه من قاعدة البيانات).

أما delete_all يتأكد من حذف المنشورات من قاعدة البيانات دفعة واحدة، دون تشغيل الـ Callbacks، وهي مفيدة في حال عدم وجود أي Callbacks تحتاج لتشغيلها.

في حالتي، كنت أستخدم destroy مع عدم وجود Callbacks، مما يسبب بُطأً في حذف بعض الصفوف، وهنا نبهتني active_record_doctor 😁

ليس لدي شك أن لكل إطار عمل أو لغة برمجة أداة مشابهة لـ active_record_doctor، فابحث عنها واستخدمها في مشاريعك، والأفضل، استخدمها في GitHub Actions (أو ما يشبهها) لتتأكد أن قاعدة بياناتك خالية من المشاكل البسيطة والقابلة للاكتشاف.

رابط active_record_doctor:
https://github.com/gregnavis/active_record_doctor

والسلام عليكم 👋🏻
3