Spaces:
Sleeping
Sleeping
Upload 4 files
Browse files- README.md +47 -0
- app.py +669 -0
- requirements.txt +5 -0
- تحليل جودة النتائج وتوصيات واقعية.md +82 -0
README.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: مساعد الطالب الذكي
|
| 3 |
+
emoji: 🎓
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: green
|
| 6 |
+
sdk: gradio
|
| 7 |
+
sdk_version: 3.50.2
|
| 8 |
+
app_file: app.py
|
| 9 |
+
pinned: false
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
# مساعد الطالب الذكي
|
| 13 |
+
|
| 14 |
+
## نظرة عامة
|
| 15 |
+
|
| 16 |
+
هذا التطبيق هو مساعد تعليمي متكامل يساعد الطلاب على:
|
| 17 |
+
- تلخيص النصوص العربية
|
| 18 |
+
- توليد أسئلة للمراجعة
|
| 19 |
+
- استخراج الكلمات المفتاحية
|
| 20 |
+
- إنشاء خرائط ذهنية
|
| 21 |
+
- إنشاء بطاقات تعليمية تفاعلية
|
| 22 |
+
- تنظيم جداول المراجعة
|
| 23 |
+
- تحليل أنماط أسئلة الامتحانات
|
| 24 |
+
|
| 25 |
+
## النماذج المستخدمة
|
| 26 |
+
|
| 27 |
+
- **التلخيص:** `yalsaffar/mt5-small-Arabic-Summarization`
|
| 28 |
+
- **توليد الأسئلة:** `MIIB-NLP/Arabic-question-generation`
|
| 29 |
+
- **استخراج الكلمات المفتاحية:** تحليل نصي مبسط
|
| 30 |
+
|
| 31 |
+
## كيفية الاستخدام
|
| 32 |
+
|
| 33 |
+
1. انتقل إلى علامة التبويب المناسبة للميزة التي تريد استخدامها
|
| 34 |
+
2. أدخل النص المطلوب
|
| 35 |
+
3. اضبط الإعدادات حسب الحاجة
|
| 36 |
+
4. انقر على زر التنفيذ
|
| 37 |
+
5. استعرض النتائج واستفد منها في دراستك
|
| 38 |
+
|
| 39 |
+
## ملاحظات
|
| 40 |
+
|
| 41 |
+
- يعمل التطبيق بشكل أفضل مع النصوص العربية الفصحى
|
| 42 |
+
- قد يستغرق تحميل النماذج بعض الوقت عند أول استخدام
|
| 43 |
+
- للحصول على أفضل النتائج، استخدم نصوصًا واضحة وخالية من الأخطاء
|
| 44 |
+
|
| 45 |
+
## الترخيص
|
| 46 |
+
|
| 47 |
+
هذا المشروع متاح تحت ترخيص MIT.
|
app.py
ADDED
|
@@ -0,0 +1,669 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
"""
|
| 3 |
+
مساعد الطالب الذكي - نسخة محسنة
|
| 4 |
+
تطبيق تعليمي متكامل للطلاب باللغة العربية
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import gradio as gr
|
| 8 |
+
import torch
|
| 9 |
+
import random
|
| 10 |
+
import datetime
|
| 11 |
+
import json
|
| 12 |
+
from datetime import datetime, timedelta
|
| 13 |
+
|
| 14 |
+
# تحقق من توفر المكتبات وتثبيتها إذا لزم الأمر
|
| 15 |
+
try:
|
| 16 |
+
from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM
|
| 17 |
+
except ImportError:
|
| 18 |
+
import subprocess
|
| 19 |
+
import sys
|
| 20 |
+
subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'transformers'])
|
| 21 |
+
from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM
|
| 22 |
+
|
| 23 |
+
# ---------------------- وظائف معالجة النصوص ---------------------- #
|
| 24 |
+
|
| 25 |
+
def summarize_text(text, max_length=150):
|
| 26 |
+
"""تلخيص النص العربي باستخدام نموذج مناسب"""
|
| 27 |
+
if not text or len(text.strip()) < 50:
|
| 28 |
+
return "النص قصير جداً أو فارغ. يرجى إدخال نص أطول للتلخيص."
|
| 29 |
+
|
| 30 |
+
try:
|
| 31 |
+
# استخدام نموذج خفيف للتلخيص
|
| 32 |
+
summarizer = pipeline(
|
| 33 |
+
"summarization",
|
| 34 |
+
model="yalsaffar/mt5-small-Arabic-Summarization",
|
| 35 |
+
device=0 if torch.cuda.is_available() else -1
|
| 36 |
+
)
|
| 37 |
+
|
| 38 |
+
# تقسيم النص إلى أجزاء إذا كان طويلاً
|
| 39 |
+
max_chunk_length = 512
|
| 40 |
+
chunks = [text[i:i+max_chunk_length] for i in range(0, len(text), max_chunk_length)]
|
| 41 |
+
|
| 42 |
+
summaries = []
|
| 43 |
+
for chunk in chunks[:3]: # نأخذ أول 3 أجزاء فقط لتجنب استهلاك الموارد
|
| 44 |
+
if len(chunk.strip()) > 50: # تجاهل الأجزاء القصيرة جداً
|
| 45 |
+
summary = summarizer(chunk, max_length=max_length, min_length=30, do_sample=False)
|
| 46 |
+
summaries.append(summary[0]['summary_text'])
|
| 47 |
+
|
| 48 |
+
if not summaries:
|
| 49 |
+
return "لم نتمكن من تلخيص النص. يرجى التأكد من أن النص مكتوب باللغة العربية وأنه يحتوي على معلومات كافية."
|
| 50 |
+
|
| 51 |
+
return " ".join(summaries)
|
| 52 |
+
|
| 53 |
+
except Exception as e:
|
| 54 |
+
return f"حدث خطأ أثناء التلخيص: {str(e)}"
|
| 55 |
+
|
| 56 |
+
def generate_questions(text, num_questions=3):
|
| 57 |
+
"""توليد أسئلة من النص العربي"""
|
| 58 |
+
if not text or len(text.strip()) < 50:
|
| 59 |
+
return "النص قصير جداً أو فارغ. يرجى إدخال نص أطول لتوليد الأسئلة."
|
| 60 |
+
|
| 61 |
+
try:
|
| 62 |
+
# استخدام نموذج خفيف لتوليد الأسئلة
|
| 63 |
+
# نظراً لأن النماذج المتخصصة قد تكون ثقيلة، نستخدم نهجاً مبسطاً
|
| 64 |
+
sentences = text.split('.')
|
| 65 |
+
questions = []
|
| 66 |
+
|
| 67 |
+
# اختيار جمل عشوائية وتحويلها إلى أسئلة
|
| 68 |
+
selected_sentences = random.sample(sentences, min(num_questions + 2, len(sentences)))
|
| 69 |
+
|
| 70 |
+
for sentence in selected_sentences:
|
| 71 |
+
sentence = sentence.strip()
|
| 72 |
+
if len(sentence) > 15: # تجاهل الجمل القصيرة جداً
|
| 73 |
+
# تحويل الجملة إلى سؤال بطريقة بسيطة
|
| 74 |
+
if "هو" in sentence:
|
| 75 |
+
question = sentence.replace("هو", "ما هو") + "؟"
|
| 76 |
+
elif "هي" in sentence:
|
| 77 |
+
question = sentence.replace("هي", "ما هي") + "؟"
|
| 78 |
+
elif "كان" in sentence:
|
| 79 |
+
question = sentence.replace("كان", "ماذا كان") + "؟"
|
| 80 |
+
elif "يمكن" in sentence:
|
| 81 |
+
question = sentence.replace("يمكن", "كيف يمكن") + "؟"
|
| 82 |
+
else:
|
| 83 |
+
# إضافة كلمة استفهام في بداية الجملة
|
| 84 |
+
question_starters = ["ما هو", "كيف", "لماذا", "متى", "أين"]
|
| 85 |
+
question = random.choice(question_starters) + " " + sentence + "؟"
|
| 86 |
+
|
| 87 |
+
questions.append(question)
|
| 88 |
+
|
| 89 |
+
if len(questions) >= num_questions:
|
| 90 |
+
break
|
| 91 |
+
|
| 92 |
+
if not questions:
|
| 93 |
+
return "لم نتمكن من توليد أسئلة من هذا النص. يرجى تجربة نص آخر."
|
| 94 |
+
|
| 95 |
+
return "\n\n".join(questions)
|
| 96 |
+
|
| 97 |
+
except Exception as e:
|
| 98 |
+
return f"حدث خطأ أثناء توليد الأسئلة: {str(e)}"
|
| 99 |
+
|
| 100 |
+
def extract_keywords(text, num_keywords=10):
|
| 101 |
+
"""استخراج الكلمات المفتاحية من النص العربي"""
|
| 102 |
+
if not text or len(text.strip()) < 50:
|
| 103 |
+
return "النص قصير جداً أو فارغ. يرجى إدخال نص أطول لاستخراج الكلمات المفتاحية."
|
| 104 |
+
|
| 105 |
+
try:
|
| 106 |
+
# تنظيف النص
|
| 107 |
+
text = text.replace('\n', ' ').replace('\r', ' ')
|
| 108 |
+
words = text.split()
|
| 109 |
+
|
| 110 |
+
# إزالة الكلمات القصيرة والحروف
|
| 111 |
+
stop_words = ["في", "من", "على", "إلى", "عن", "مع", "هذا", "هذه", "ذلك", "تلك",
|
| 112 |
+
"هو", "هي", "أنا", "نحن", "أنت", "أنتم", "هم", "و", "أو", "ثم", "لكن",
|
| 113 |
+
"ف", "ب", "ل", "ك", "و", "ا", "ال", "إن", "أن", "لا", "ما", "لم"]
|
| 114 |
+
|
| 115 |
+
filtered_words = [word for word in words if len(word) > 2 and word not in stop_words]
|
| 116 |
+
|
| 117 |
+
# حساب تكرار الكلمات
|
| 118 |
+
word_freq = {}
|
| 119 |
+
for word in filtered_words:
|
| 120 |
+
if word in word_freq:
|
| 121 |
+
word_freq[word] += 1
|
| 122 |
+
else:
|
| 123 |
+
word_freq[word] = 1
|
| 124 |
+
|
| 125 |
+
# ترتيب الكلمات حسب التكرار
|
| 126 |
+
sorted_words = sorted(word_freq.items(), key=lambda x: x[1], reverse=True)
|
| 127 |
+
|
| 128 |
+
# اختيار الكلمات الأكثر تكراراً
|
| 129 |
+
top_keywords = sorted_words[:num_keywords]
|
| 130 |
+
|
| 131 |
+
if not top_keywords:
|
| 132 |
+
return "لم نتمكن من استخراج كلمات مفتاحية من هذا النص. يرجى تجربة نص آخر."
|
| 133 |
+
|
| 134 |
+
# تنسيق النتيجة
|
| 135 |
+
result = "الكلمات المفتاحية:\n\n"
|
| 136 |
+
for i, (word, freq) in enumerate(top_keywords, 1):
|
| 137 |
+
result += f"{i}. {word} (التكرار: {freq})\n"
|
| 138 |
+
|
| 139 |
+
return result
|
| 140 |
+
|
| 141 |
+
except Exception as e:
|
| 142 |
+
return f"حدث خطأ أثناء استخراج الكلمات المفتاحية: {str(e)}"
|
| 143 |
+
|
| 144 |
+
def generate_mind_map(text):
|
| 145 |
+
"""إنشاء خريطة ذهنية بسيطة من النص العربي"""
|
| 146 |
+
if not text or len(text.strip()) < 50:
|
| 147 |
+
return "النص قصير جداً أو فارغ. يرجى إدخال نص أطول لإنشاء الخريطة الذهنية."
|
| 148 |
+
|
| 149 |
+
try:
|
| 150 |
+
# تقسيم النص إلى فقرات وجمل
|
| 151 |
+
paragraphs = text.split('\n')
|
| 152 |
+
sentences = text.split('.')
|
| 153 |
+
|
| 154 |
+
# استخراج العنوان الرئيسي (أول جملة أو أول 50 حرف)
|
| 155 |
+
main_title = sentences[0].strip() if sentences and len(sentences[0]) > 5 else text[:50] + "..."
|
| 156 |
+
|
| 157 |
+
# استخراج العناوين الفرعية (بداية كل فقرة أو جمل مختارة)
|
| 158 |
+
subtitles = []
|
| 159 |
+
|
| 160 |
+
# من الفقرات
|
| 161 |
+
for para in paragraphs:
|
| 162 |
+
if len(para.strip()) > 20:
|
| 163 |
+
first_sentence = para.split('.')[0].strip()
|
| 164 |
+
if first_sentence and len(first_sentence) > 15 and first_sentence not in subtitles:
|
| 165 |
+
subtitles.append(first_sentence)
|
| 166 |
+
|
| 167 |
+
# إذا لم نجد عناوين فرعية كافية، نأخذ من الجمل
|
| 168 |
+
if len(subtitles) < 3:
|
| 169 |
+
for sentence in sentences[1:]:
|
| 170 |
+
if len(sentence.strip()) > 15 and sentence.strip() not in subtitles:
|
| 171 |
+
subtitles.append(sentence.strip())
|
| 172 |
+
if len(subtitles) >= 5:
|
| 173 |
+
break
|
| 174 |
+
|
| 175 |
+
# إنشاء الخريطة الذهنية بتنسيق Markdown
|
| 176 |
+
mind_map = f"# {main_title}\n\n"
|
| 177 |
+
|
| 178 |
+
for i, subtitle in enumerate(subtitles[:5], 1):
|
| 179 |
+
mind_map += f"## {subtitle}\n"
|
| 180 |
+
|
| 181 |
+
# إضافة بعض النقاط تحت كل عنوان فرعي
|
| 182 |
+
related_sentences = [s.strip() for s in sentences if subtitle not in s and len(s.strip()) > 10]
|
| 183 |
+
for j, related in enumerate(random.sample(related_sentences, min(3, len(related_sentences))), 1):
|
| 184 |
+
if len(related) > 10:
|
| 185 |
+
mind_map += f" - {related}\n"
|
| 186 |
+
|
| 187 |
+
mind_map += "\n"
|
| 188 |
+
|
| 189 |
+
return mind_map
|
| 190 |
+
|
| 191 |
+
except Exception as e:
|
| 192 |
+
return f"حدث خطأ أثناء إنشاء الخريطة الذهنية: {str(e)}"
|
| 193 |
+
|
| 194 |
+
def create_flashcards(text, num_cards=5):
|
| 195 |
+
"""إنشاء بطاقات تعليمية من النص العربي"""
|
| 196 |
+
if not text or len(text.strip()) < 50:
|
| 197 |
+
return "النص قصير جداً أو فارغ. يرجى إدخال نص أطول لإنشاء البطاقات التعليمية."
|
| 198 |
+
|
| 199 |
+
try:
|
| 200 |
+
# تقسيم النص إلى جمل
|
| 201 |
+
sentences = [s.strip() for s in text.split('.') if len(s.strip()) > 15]
|
| 202 |
+
|
| 203 |
+
if len(sentences) < 2:
|
| 204 |
+
return "النص لا يحتوي على جمل كافية لإنشاء البطاقات التعليمية. يرجى إدخال نص أطول."
|
| 205 |
+
|
| 206 |
+
# إنشاء البطاقات التعليمية
|
| 207 |
+
flashcards = []
|
| 208 |
+
|
| 209 |
+
# اختيار جمل عشوائية
|
| 210 |
+
selected_sentences = random.sample(sentences, min(num_cards * 2, len(sentences)))
|
| 211 |
+
|
| 212 |
+
for i in range(0, len(selected_sentences) - 1, 2):
|
| 213 |
+
if i + 1 < len(selected_sentences):
|
| 214 |
+
question = selected_sentences[i]
|
| 215 |
+
answer = selected_sentences[i + 1]
|
| 216 |
+
|
| 217 |
+
# تحويل الجملة الأولى إلى سؤال إذا لم تكن كذلك
|
| 218 |
+
if not question.endswith('?') and not question.endswith('؟'):
|
| 219 |
+
question_starters = ["ما هو", "كيف", "لماذا", "اشرح", "وضح"]
|
| 220 |
+
question = random.choice(question_starters) + " " + question + "؟"
|
| 221 |
+
|
| 222 |
+
flashcards.append({"question": question, "answer": answer})
|
| 223 |
+
|
| 224 |
+
if len(flashcards) >= num_cards:
|
| 225 |
+
break
|
| 226 |
+
|
| 227 |
+
if not flashcards:
|
| 228 |
+
return "لم نتمكن من إنشاء بطاقات تعليمية من هذا النص. يرجى تجربة نص آخر."
|
| 229 |
+
|
| 230 |
+
# تنسيق النتيجة كنص بدلاً من JSON
|
| 231 |
+
result = "البطاقات التعليمية:\n\n"
|
| 232 |
+
for i, card in enumerate(flashcards, 1):
|
| 233 |
+
result += f"بطاقة {i}:\n"
|
| 234 |
+
result += f"السؤال: {card['question']}\n"
|
| 235 |
+
result += f"الإجابة: {card['answer']}\n\n"
|
| 236 |
+
|
| 237 |
+
return result
|
| 238 |
+
|
| 239 |
+
except Exception as e:
|
| 240 |
+
return f"حدث خطأ أثناء إنشاء البطاقات التعليمية: {str(e)}"
|
| 241 |
+
|
| 242 |
+
def create_study_schedule(subject_name, start_date_str, exam_date_str, importance=3):
|
| 243 |
+
"""إنشاء جدول مراجعة باستخدام تقنية المراجعة المتباعدة"""
|
| 244 |
+
try:
|
| 245 |
+
# تحويل التواريخ من نص إلى كائنات datetime
|
| 246 |
+
try:
|
| 247 |
+
start_date = datetime.strptime(start_date_str, "%Y-%m-%d")
|
| 248 |
+
exam_date = datetime.strptime(exam_date_str, "%Y-%m-%d")
|
| 249 |
+
except ValueError:
|
| 250 |
+
return "صيغة التاريخ غير صحيحة. يرجى استخدام الصيغة YYYY-MM-DD (مثال: 2025-06-20)."
|
| 251 |
+
|
| 252 |
+
if start_date >= exam_date:
|
| 253 |
+
return "تاريخ بدء المراجعة يجب أن يكون قبل تاريخ الامتحان."
|
| 254 |
+
|
| 255 |
+
# حساب عدد الأيام المتاحة للمراجعة
|
| 256 |
+
days_available = (exam_date - start_date).days
|
| 257 |
+
|
| 258 |
+
if days_available < 1:
|
| 259 |
+
return "لا توجد أيام كافية للمراجعة. يرجى اختيار تاريخ بدء أبكر."
|
| 260 |
+
|
| 261 |
+
# تحديد عدد جلسات المراجعة بناءً على الأهمية وعدد الأيام المتاحة
|
| 262 |
+
if importance <= 1:
|
| 263 |
+
num_sessions = min(3, days_available)
|
| 264 |
+
elif importance == 2:
|
| 265 |
+
num_sessions = min(5, days_available)
|
| 266 |
+
else: # importance >= 3
|
| 267 |
+
num_sessions = min(7, days_available)
|
| 268 |
+
|
| 269 |
+
# إنشاء جدول المراجعة باستخدام تقنية المراجعة المتباعدة
|
| 270 |
+
schedule = []
|
| 271 |
+
|
| 272 |
+
# الجلسة الأولى تكون في يوم البدء
|
| 273 |
+
current_date = start_date
|
| 274 |
+
schedule.append({
|
| 275 |
+
"session": 1,
|
| 276 |
+
"date": current_date.strftime("%Y-%m-%d"),
|
| 277 |
+
"day": ["الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"][current_date.weekday()],
|
| 278 |
+
"focus": "مراجعة شاملة للمادة"
|
| 279 |
+
})
|
| 280 |
+
|
| 281 |
+
# توزيع باقي الجلسات بشكل متباعد
|
| 282 |
+
intervals = [1, 2, 4, 7, 12, 20] # فترات المراجعة المتباعدة بالأيام
|
| 283 |
+
|
| 284 |
+
for i in range(1, num_sessions):
|
| 285 |
+
# حساب تاريخ الجلسة التالية
|
| 286 |
+
if i < len(intervals):
|
| 287 |
+
days_to_add = intervals[i-1]
|
| 288 |
+
else:
|
| 289 |
+
days_to_add = intervals[-1]
|
| 290 |
+
|
| 291 |
+
current_date = current_date + timedelta(days=days_to_add)
|
| 292 |
+
|
| 293 |
+
# التأكد من أن تاريخ الجلسة قبل تاريخ الامتحان
|
| 294 |
+
if current_date >= exam_date:
|
| 295 |
+
# إذا تجاوزنا تاريخ الامتحان، نضع الجلسة قبل يوم من الامتحان
|
| 296 |
+
current_date = exam_date - timedelta(days=1)
|
| 297 |
+
|
| 298 |
+
# تحديد التركيز لكل جلسة
|
| 299 |
+
if i == num_sessions - 1:
|
| 300 |
+
focus = "مراجعة نهائية وحل أسئلة سابقة"
|
| 301 |
+
elif i == 1:
|
| 302 |
+
focus = "مراجعة المفاهيم الأساسية"
|
| 303 |
+
elif i == 2:
|
| 304 |
+
focus = "حل تمارين وأمثلة"
|
| 305 |
+
else:
|
| 306 |
+
focus = "مراجعة النقاط الصعبة"
|
| 307 |
+
|
| 308 |
+
schedule.append({
|
| 309 |
+
"session": i + 1,
|
| 310 |
+
"date": current_date.strftime("%Y-%m-%d"),
|
| 311 |
+
"day": ["الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"][current_date.weekday()],
|
| 312 |
+
"focus": focus
|
| 313 |
+
})
|
| 314 |
+
|
| 315 |
+
# إذا وصلنا إلى يوم قبل الامتحان، نتوقف
|
| 316 |
+
if current_date >= exam_date - timedelta(days=1):
|
| 317 |
+
break
|
| 318 |
+
|
| 319 |
+
# إضافة يوم الامتحان
|
| 320 |
+
schedule.append({
|
| 321 |
+
"session": "الامتحان",
|
| 322 |
+
"date": exam_date.strftime("%Y-%m-%d"),
|
| 323 |
+
"day": ["الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"][exam_date.weekday()],
|
| 324 |
+
"focus": "يوم الامتحان"
|
| 325 |
+
})
|
| 326 |
+
|
| 327 |
+
# تنسيق النتيجة كنص
|
| 328 |
+
result = f"جدول المراجعة لمادة: {subject_name}\n\n"
|
| 329 |
+
|
| 330 |
+
for session in schedule:
|
| 331 |
+
if session["session"] == "الامتحان":
|
| 332 |
+
result += f"📝 {session['date']} ({session['day']}): {session['focus']}\n"
|
| 333 |
+
else:
|
| 334 |
+
result += f"📚 جلسة {session['session']}: {session['date']} ({session['day']}) - {session['focus']}\n"
|
| 335 |
+
|
| 336 |
+
return result
|
| 337 |
+
|
| 338 |
+
except Exception as e:
|
| 339 |
+
return f"حدث خطأ أثناء إنشاء جدول المراجعة: {str(e)}"
|
| 340 |
+
|
| 341 |
+
def analyze_exam_questions(questions_text):
|
| 342 |
+
"""تحليل أنماط أسئلة الامتحانات"""
|
| 343 |
+
if not questions_text or len(questions_text.strip()) < 20:
|
| 344 |
+
return "النص قصير جداً أو فارغ. يرجى إدخال أسئلة امتحانات سابقة للتحليل."
|
| 345 |
+
|
| 346 |
+
try:
|
| 347 |
+
# تقسيم النص إلى أسئلة منفصلة
|
| 348 |
+
questions = [q.strip() for q in questions_text.split('\n') if len(q.strip()) > 5 and ('؟' in q or '?' in q)]
|
| 349 |
+
|
| 350 |
+
if len(questions) < 2:
|
| 351 |
+
return "لم نتمكن من تحديد أسئلة كافية للتحليل. يرجى التأكد من فصل كل سؤال بسطر جديد وإنهاء الأسئلة بعلامة استفهام."
|
| 352 |
+
|
| 353 |
+
# تحليل أنواع الأسئلة
|
| 354 |
+
question_types = {
|
| 355 |
+
"تعريف": 0,
|
| 356 |
+
"شرح": 0,
|
| 357 |
+
"مقارنة": 0,
|
| 358 |
+
"تحليل": 0,
|
| 359 |
+
"تطبيق": 0,
|
| 360 |
+
"أخرى": 0
|
| 361 |
+
}
|
| 362 |
+
|
| 363 |
+
for q in questions:
|
| 364 |
+
q_lower = q.lower()
|
| 365 |
+
if any(word in q_lower for word in ["عرف", "ما هو", "ما هي", "من هو"]):
|
| 366 |
+
question_types["تعريف"] += 1
|
| 367 |
+
elif any(word in q_lower for word in ["اشرح", "وضح", "بين", "فسر"]):
|
| 368 |
+
question_types["شرح"] += 1
|
| 369 |
+
elif any(word in q_lower for word in ["قارن", "الفرق", "الاختلاف"]):
|
| 370 |
+
question_types["مقارنة"] += 1
|
| 371 |
+
elif any(word in q_lower for word in ["حلل", "ناقش", "قيم"]):
|
| 372 |
+
question_types["تحليل"] += 1
|
| 373 |
+
elif any(word in q_lower for word in ["طبق", "استخدم", "احسب"]):
|
| 374 |
+
question_types["تطبيق"] += 1
|
| 375 |
+
else:
|
| 376 |
+
question_types["أخرى"] += 1
|
| 377 |
+
|
| 378 |
+
# تحليل الكلمات المفتاحية
|
| 379 |
+
all_words = " ".join(questions).split()
|
| 380 |
+
word_freq = {}
|
| 381 |
+
|
| 382 |
+
stop_words = ["ما", "هو", "هي", "كيف", "لماذا", "متى", "أين", "من", "في", "على", "إلى", "عن", "مع"]
|
| 383 |
+
|
| 384 |
+
for word in all_words:
|
| 385 |
+
if len(word) > 2 and word not in stop_words:
|
| 386 |
+
if word in word_freq:
|
| 387 |
+
word_freq[word] += 1
|
| 388 |
+
else:
|
| 389 |
+
word_freq[word] = 1
|
| 390 |
+
|
| 391 |
+
# ترتيب الكلمات حسب التكرار
|
| 392 |
+
sorted_words = sorted(word_freq.items(), key=lambda x: x[1], reverse=True)
|
| 393 |
+
top_keywords = sorted_words[:10]
|
| 394 |
+
|
| 395 |
+
# تنسيق النتيجة
|
| 396 |
+
result = f"تحليل {len(questions)} سؤال:\n\n"
|
| 397 |
+
|
| 398 |
+
result += "أنواع الأسئلة:\n"
|
| 399 |
+
for q_type, count in question_types.items():
|
| 400 |
+
if count > 0:
|
| 401 |
+
percentage = (count / len(questions)) * 100
|
| 402 |
+
result += f"- {q_type}: {count} ({percentage:.1f}%)\n"
|
| 403 |
+
|
| 404 |
+
result += "\nالمواضيع الأكثر تكراراً:\n"
|
| 405 |
+
for word, freq in top_keywords:
|
| 406 |
+
result += f"- {word}: {freq} مرات\n"
|
| 407 |
+
|
| 408 |
+
result += "\nتوصيات للمراجعة:\n"
|
| 409 |
+
|
| 410 |
+
# تحديد نوع السؤال الأكثر تكراراً
|
| 411 |
+
most_common_type = max(question_types.items(), key=lambda x: x[1])[0]
|
| 412 |
+
result += f"1. التركيز على الإجابة على أسئلة {most_common_type}\n"
|
| 413 |
+
|
| 414 |
+
# توصيات بناءً على الكلمات المفتاحية
|
| 415 |
+
result += f"2. مراجعة المواضيع المتعلقة بـ: {', '.join([w for w, _ in top_keywords[:5]])}\n"
|
| 416 |
+
|
| 417 |
+
# توصية عامة
|
| 418 |
+
result += "3. التدرب على الإجابة على الأسئلة بأسلوب منظم ومختصر\n"
|
| 419 |
+
|
| 420 |
+
return result
|
| 421 |
+
|
| 422 |
+
except Exception as e:
|
| 423 |
+
return f"حدث خطأ أثناء تحليل أسئلة الامتحانات: {str(e)}"
|
| 424 |
+
|
| 425 |
+
# ---------------------- واجهة المستخدم ---------------------- #
|
| 426 |
+
|
| 427 |
+
def create_interface():
|
| 428 |
+
"""إنشاء واجهة المستخدم باستخدام Gradio"""
|
| 429 |
+
|
| 430 |
+
# الشعار والعنوان
|
| 431 |
+
title = """
|
| 432 |
+
<div style="text-align: center; margin-bottom: 1rem">
|
| 433 |
+
<h1>مساعد الطالب الذكي</h1>
|
| 434 |
+
<p>أداة تعليمية متكاملة للطلاب باستخدام الذكاء الاصطناعي</p>
|
| 435 |
+
</div>
|
| 436 |
+
"""
|
| 437 |
+
|
| 438 |
+
# إنشاء واجهة المستخدم
|
| 439 |
+
with gr.Blocks(css="footer {visibility: hidden}") as demo:
|
| 440 |
+
gr.HTML(title)
|
| 441 |
+
|
| 442 |
+
with gr.Tabs():
|
| 443 |
+
# علامة تبويب تلخيص النصوص
|
| 444 |
+
with gr.Tab("تلخيص النصوص"):
|
| 445 |
+
with gr.Row():
|
| 446 |
+
with gr.Column():
|
| 447 |
+
summarize_input = gr.Textbox(
|
| 448 |
+
label="أدخل النص المراد تلخيصه",
|
| 449 |
+
placeholder="أدخل النص هنا...",
|
| 450 |
+
lines=10
|
| 451 |
+
)
|
| 452 |
+
summarize_length = gr.Slider(
|
| 453 |
+
label="طول التلخيص",
|
| 454 |
+
minimum=50,
|
| 455 |
+
maximum=300,
|
| 456 |
+
value=150,
|
| 457 |
+
step=10
|
| 458 |
+
)
|
| 459 |
+
summarize_button = gr.Button("تلخيص النص")
|
| 460 |
+
|
| 461 |
+
with gr.Column():
|
| 462 |
+
summarize_output = gr.Textbox(
|
| 463 |
+
label="نتيجة التلخيص",
|
| 464 |
+
lines=10
|
| 465 |
+
)
|
| 466 |
+
|
| 467 |
+
summarize_button.click(
|
| 468 |
+
fn=summarize_text,
|
| 469 |
+
inputs=[summarize_input, summarize_length],
|
| 470 |
+
outputs=summarize_output
|
| 471 |
+
)
|
| 472 |
+
|
| 473 |
+
# علامة تبويب توليد الأسئلة
|
| 474 |
+
with gr.Tab("توليد الأسئلة"):
|
| 475 |
+
with gr.Row():
|
| 476 |
+
with gr.Column():
|
| 477 |
+
questions_input = gr.Textbox(
|
| 478 |
+
label="أدخل النص المراد توليد أسئلة منه",
|
| 479 |
+
placeholder="أدخل النص هنا...",
|
| 480 |
+
lines=10
|
| 481 |
+
)
|
| 482 |
+
questions_count = gr.Slider(
|
| 483 |
+
label="عدد الأسئلة",
|
| 484 |
+
minimum=1,
|
| 485 |
+
maximum=10,
|
| 486 |
+
value=3,
|
| 487 |
+
step=1
|
| 488 |
+
)
|
| 489 |
+
questions_button = gr.Button("توليد الأسئلة")
|
| 490 |
+
|
| 491 |
+
with gr.Column():
|
| 492 |
+
questions_output = gr.Textbox(
|
| 493 |
+
label="الأسئلة المولدة",
|
| 494 |
+
lines=10
|
| 495 |
+
)
|
| 496 |
+
|
| 497 |
+
questions_button.click(
|
| 498 |
+
fn=generate_questions,
|
| 499 |
+
inputs=[questions_input, questions_count],
|
| 500 |
+
outputs=questions_output
|
| 501 |
+
)
|
| 502 |
+
|
| 503 |
+
# علامة تبويب استخراج الكلمات المفتاحية
|
| 504 |
+
with gr.Tab("استخراج الكلمات المفتاحية"):
|
| 505 |
+
with gr.Row():
|
| 506 |
+
with gr.Column():
|
| 507 |
+
keywords_input = gr.Textbox(
|
| 508 |
+
label="أدخل النص المراد استخراج الكلمات المفتاحية منه",
|
| 509 |
+
placeholder="أدخل النص هنا...",
|
| 510 |
+
lines=10
|
| 511 |
+
)
|
| 512 |
+
keywords_count = gr.Slider(
|
| 513 |
+
label="عدد الكلمات المفتاحية",
|
| 514 |
+
minimum=5,
|
| 515 |
+
maximum=20,
|
| 516 |
+
value=10,
|
| 517 |
+
step=1
|
| 518 |
+
)
|
| 519 |
+
keywords_button = gr.Button("استخراج الكلمات المفتاحية")
|
| 520 |
+
|
| 521 |
+
with gr.Column():
|
| 522 |
+
keywords_output = gr.Textbox(
|
| 523 |
+
label="الكلمات المفتاحية",
|
| 524 |
+
lines=10
|
| 525 |
+
)
|
| 526 |
+
|
| 527 |
+
keywords_button.click(
|
| 528 |
+
fn=extract_keywords,
|
| 529 |
+
inputs=[keywords_input, keywords_count],
|
| 530 |
+
outputs=keywords_output
|
| 531 |
+
)
|
| 532 |
+
|
| 533 |
+
# علامة تبويب الخرائط الذهنية
|
| 534 |
+
with gr.Tab("الخرائط الذهنية"):
|
| 535 |
+
with gr.Row():
|
| 536 |
+
with gr.Column():
|
| 537 |
+
mindmap_input = gr.Textbox(
|
| 538 |
+
label="أدخل النص المراد إنشاء خريطة ذهنية له",
|
| 539 |
+
placeholder="أدخل النص هنا...",
|
| 540 |
+
lines=10
|
| 541 |
+
)
|
| 542 |
+
mindmap_button = gr.Button("إنشاء الخريطة الذهنية")
|
| 543 |
+
|
| 544 |
+
with gr.Column():
|
| 545 |
+
mindmap_output = gr.Markdown(
|
| 546 |
+
label="الخريطة الذهنية"
|
| 547 |
+
)
|
| 548 |
+
|
| 549 |
+
mindmap_button.click(
|
| 550 |
+
fn=generate_mind_map,
|
| 551 |
+
inputs=mindmap_input,
|
| 552 |
+
outputs=mindmap_output
|
| 553 |
+
)
|
| 554 |
+
|
| 555 |
+
# علامة تبويب البطاقات التعليمية
|
| 556 |
+
with gr.Tab("البطاقات التعليمية"):
|
| 557 |
+
with gr.Row():
|
| 558 |
+
with gr.Column():
|
| 559 |
+
flashcards_input = gr.Textbox(
|
| 560 |
+
label="أدخل النص المراد إنشاء بطاقات تعليمية منه",
|
| 561 |
+
placeholder="أدخل النص هنا...",
|
| 562 |
+
lines=10
|
| 563 |
+
)
|
| 564 |
+
flashcards_count = gr.Slider(
|
| 565 |
+
label="عدد البطاقات",
|
| 566 |
+
minimum=3,
|
| 567 |
+
maximum=10,
|
| 568 |
+
value=5,
|
| 569 |
+
step=1
|
| 570 |
+
)
|
| 571 |
+
flashcards_button = gr.Button("إنشاء البطاقات التعليمية")
|
| 572 |
+
|
| 573 |
+
with gr.Column():
|
| 574 |
+
flashcards_output = gr.Textbox(
|
| 575 |
+
label="البطاقات التعليمية",
|
| 576 |
+
lines=15
|
| 577 |
+
)
|
| 578 |
+
|
| 579 |
+
flashcards_button.click(
|
| 580 |
+
fn=create_flashcards,
|
| 581 |
+
inputs=[flashcards_input, flashcards_count],
|
| 582 |
+
outputs=flashcards_output
|
| 583 |
+
)
|
| 584 |
+
|
| 585 |
+
# علامة تبويب منظم المراجعات
|
| 586 |
+
with gr.Tab("منظم المراجعات"):
|
| 587 |
+
with gr.Row():
|
| 588 |
+
with gr.Column():
|
| 589 |
+
subject_name = gr.Textbox(
|
| 590 |
+
label="اسم المادة",
|
| 591 |
+
placeholder="مثال: الرياضيات"
|
| 592 |
+
)
|
| 593 |
+
start_date = gr.Textbox(
|
| 594 |
+
label="تاريخ بدء المراجعة (YYYY-MM-DD)",
|
| 595 |
+
placeholder="مثال: 2025-06-20",
|
| 596 |
+
value=datetime.now().strftime("%Y-%m-%d")
|
| 597 |
+
)
|
| 598 |
+
exam_date = gr.Textbox(
|
| 599 |
+
label="تاريخ الامتحان (YYYY-MM-DD)",
|
| 600 |
+
placeholder="مثال: 2025-07-10",
|
| 601 |
+
value=(datetime.now() + timedelta(days=14)).strftime("%Y-%m-%d")
|
| 602 |
+
)
|
| 603 |
+
importance = gr.Slider(
|
| 604 |
+
label="أهمية المادة",
|
| 605 |
+
minimum=1,
|
| 606 |
+
maximum=5,
|
| 607 |
+
value=3,
|
| 608 |
+
step=1
|
| 609 |
+
)
|
| 610 |
+
schedule_button = gr.Button("إنشاء جدول المراجعة")
|
| 611 |
+
|
| 612 |
+
with gr.Column():
|
| 613 |
+
schedule_output = gr.Textbox(
|
| 614 |
+
label="جدول المراجعة",
|
| 615 |
+
lines=15
|
| 616 |
+
)
|
| 617 |
+
|
| 618 |
+
schedule_button.click(
|
| 619 |
+
fn=create_study_schedule,
|
| 620 |
+
inputs=[subject_name, start_date, exam_date, importance],
|
| 621 |
+
outputs=schedule_output
|
| 622 |
+
)
|
| 623 |
+
|
| 624 |
+
# علامة تبويب تحليل أسئلة الامتحانات
|
| 625 |
+
with gr.Tab("تحليل أسئلة الامتحانات"):
|
| 626 |
+
with gr.Row():
|
| 627 |
+
with gr.Column():
|
| 628 |
+
exam_questions = gr.Textbox(
|
| 629 |
+
label="أدخل أسئلة الامتحانات السابقة (سؤال واحد في كل سطر)",
|
| 630 |
+
placeholder="مثال:\nما هو تعريف الخلية؟\nاشرح نظرية فيثاغورس؟\nقارن بين الخلية النباتية والخلية الحيوانية؟",
|
| 631 |
+
lines=10
|
| 632 |
+
)
|
| 633 |
+
analyze_button = gr.Button("تحليل الأسئلة")
|
| 634 |
+
|
| 635 |
+
with gr.Column():
|
| 636 |
+
analysis_output = gr.Textbox(
|
| 637 |
+
label="نتائج التحليل",
|
| 638 |
+
lines=15
|
| 639 |
+
)
|
| 640 |
+
|
| 641 |
+
analyze_button.click(
|
| 642 |
+
fn=analyze_exam_questions,
|
| 643 |
+
inputs=exam_questions,
|
| 644 |
+
outputs=analysis_output
|
| 645 |
+
)
|
| 646 |
+
|
| 647 |
+
# معلومات إضافية
|
| 648 |
+
gr.Markdown("""
|
| 649 |
+
### كيفية الاستخدام
|
| 650 |
+
|
| 651 |
+
1. اختر الميزة التي تريد استخدامها من علامات التبويب أعلاه
|
| 652 |
+
2. أدخل النص المطلوب واضبط الإعدادات حسب الحاجة
|
| 653 |
+
3. انقر على الزر المناسب للحصول على النتيجة
|
| 654 |
+
|
| 655 |
+
### ملاحظات
|
| 656 |
+
|
| 657 |
+
- يعمل التطبيق بشكل أفضل مع النصوص العربية الفصحى
|
| 658 |
+
- قد يستغرق تحميل النماذج بعض الوقت عند أول استخدام
|
| 659 |
+
- للحصول على أفضل النتائج، استخدم نصوصًا واضحة وخالية من الأخطاء
|
| 660 |
+
""")
|
| 661 |
+
|
| 662 |
+
return demo
|
| 663 |
+
|
| 664 |
+
# إنشاء واجهة المستخدم
|
| 665 |
+
demo = create_interface()
|
| 666 |
+
|
| 667 |
+
# نقطة الدخول الرئيسية لـ Hugging Face Spaces
|
| 668 |
+
if __name__ == "__main__":
|
| 669 |
+
demo.launch()
|
requirements.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio>=3.50.2
|
| 2 |
+
torch>=2.0.0
|
| 3 |
+
transformers>=4.30.0
|
| 4 |
+
sentencepiece>=0.1.99
|
| 5 |
+
protobuf>=4.25.0
|
تحليل جودة النتائج وتوصيات واقعية.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# تحليل جودة النتائج وتوصيات واقعية
|
| 2 |
+
|
| 3 |
+
## تحليل جودة النتائج
|
| 4 |
+
|
| 5 |
+
بعد اختبار تطبيق "مساعد الطالب الذكي" مع نصوص عربية متنوعة، بما في ذلك نصوص تاريخية عن الجزائر، تم تحديد عدة تحديات وقيود تؤثر على جودة النتائج:
|
| 6 |
+
|
| 7 |
+
### 1. محدودية النماذج العربية الخفيفة
|
| 8 |
+
|
| 9 |
+
- **النماذج المستخدمة**: النماذج المتاحة للغة العربية التي يمكن تشغيلها على منصات مجانية مثل Hugging Face Spaces محدودة جداً من حيث الحجم والقدرات.
|
| 10 |
+
- **مقارنة بالنماذج الإنجليزية**: النماذج العربية متأخرة بشكل كبير عن نظيراتها الإنجليزية من حيث التدريب والأداء.
|
| 11 |
+
- **تأثير الحجم**: النماذج الصغيرة (مثل mt5-small) تفتقر إلى العمق المعرفي اللازم لفهم النصوص المتخصصة.
|
| 12 |
+
|
| 13 |
+
### 2. تعقيد النصوص العربية المتخصصة
|
| 14 |
+
|
| 15 |
+
- **النصوص التاريخية**: تحتوي على أسماء أعلام، وأماكن، وأحداث، ومصطلحات متخصصة يصعب على النماذج الخفيفة فهمها بدقة.
|
| 16 |
+
- **تنوع اللهجات والأساليب**: اختلاف بين العربية الفصحى والعامية والمصطلحات المتخصصة.
|
| 17 |
+
- **السياق الثقافي**: النماذج الحالية تفتقر إلى الفهم العميق للسياق الثقافي والتاريخي العربي.
|
| 18 |
+
|
| 19 |
+
### 3. قيود الموارد الحاسوبية
|
| 20 |
+
|
| 21 |
+
- **منصة Hugging Face Spaces**: توفر موارد محدودة جداً (وحدة معالجة مركزية محدودة، ذاكرة وصول عشوائي محدودة).
|
| 22 |
+
- **وقت المعالجة**: النماذج الأكبر تستغرق وقتاً طويلاً للتنفيذ على الموارد المحدودة.
|
| 23 |
+
- **استقرار الخدمة**: قد تواجه انقطاعات أو إعادة تشغيل عند استهلاك الموارد.
|
| 24 |
+
|
| 25 |
+
### 4. تقييم الميزات المختلفة
|
| 26 |
+
|
| 27 |
+
| الميزة | جودة النتائج | التحديات الرئيسية |
|
| 28 |
+
|--------|--------------|-------------------|
|
| 29 |
+
| تلخيص النصوص | متوسطة | فقدان المعلومات المهمة، تكرار بعض العبارات |
|
| 30 |
+
| توليد الأسئلة | ضعيفة إلى متوسطة | أسئلة سطحية، عدم فهم المفاهيم المعقدة |
|
| 31 |
+
| استخراج الكلمات المفتاحية | متوسطة | التركيز على الكلمات المتكررة وليس المهمة |
|
| 32 |
+
| الخرائط الذهنية | ضعيفة | عدم فهم العلاقات المنطقية بين المفاهيم |
|
| 33 |
+
| البطاقات التعليمية | متوسطة | صعوبة تحديد الأزواج المناسبة من الأسئلة والأجوبة |
|
| 34 |
+
| منظم المراجعات | جيدة | ميزة حسابية أكثر منها لغوية |
|
| 35 |
+
| تحليل أسئلة الامتحانات | ضعيفة إلى متوسطة | تحليل سطحي للأنماط |
|
| 36 |
+
|
| 37 |
+
## التوصيات الواقعية
|
| 38 |
+
|
| 39 |
+
بناءً على التحليل السابق، نقدم التوصيات التالية للحصول على نتائج أفضل في معالجة النصوص العربية التعليمية:
|
| 40 |
+
|
| 41 |
+
### 1. استخدام نماذج أكبر على بيئات أقوى
|
| 42 |
+
|
| 43 |
+
- **نماذج GPT-4 أو Claude**: تقدم نتائج أفضل بكثير للغة العربية، خاصة مع النصوص المتخصصة.
|
| 44 |
+
- **واجهات برمجة التطبيقات (API)**: يمكن استخدامها عبر OpenAI API أو Anthropic API، لكنها مدفوعة.
|
| 45 |
+
- **خدمات سحابية أقوى**: استضافة التطبيق على AWS أو Google Cloud مع وحدات معالجة رسومية (GPU) لتشغيل نماذج أكبر.
|
| 46 |
+
|
| 47 |
+
### 2. الجمع بين الأدوات اليدوية والذكاء الاصطناعي
|
| 48 |
+
|
| 49 |
+
- **أدوات تنظيم الملاحظات**: استخدام برامج مثل Notion أو Obsidian لتنظيم الملاحظات بشكل يدوي.
|
| 50 |
+
- **الاستعانة بالذكاء الاصطناعي لمهام محددة**: استخدام الذكاء الاصطناعي فقط للتلخيص البسيط أو توليد أفكار أولية.
|
| 51 |
+
- **المراجعة البشرية**: مراجعة وتحسين مخرجات الذكاء الاصطناعي يدوياً.
|
| 52 |
+
|
| 53 |
+
### 3. تطبيقات متخصصة للطلاب
|
| 54 |
+
|
| 55 |
+
- **Anki للبطاقات التعليمية**: تطبيق متخصص ومثبت الفعالية للبطاقات التعليمية والمراجعة المتباعدة.
|
| 56 |
+
- **MindMeister للخرائط الذهنية**: أداة احترافية لإنشاء خرائط ذهنية تفاعلية.
|
| 57 |
+
- **تطبيقات إدارة الوقت**: لتنظيم جداول المراجعة بشكل أكثر فع��لية.
|
| 58 |
+
|
| 59 |
+
### 4. تبسيط نطاق المشروع
|
| 60 |
+
|
| 61 |
+
- **التركيز على وظيفة واحدة**: تطوير تطبيق يركز على وظيفة واحدة محددة بدلاً من محاولة دمج كل الوظائف.
|
| 62 |
+
- **تخصيص النماذج**: تدريب نماذج صغيرة على مجال محدد (مثل التاريخ العربي) بدلاً من استخدام نماذج عامة.
|
| 63 |
+
- **تحسين واجهة المستخدم**: تصميم واجهة أكثر بساطة وفعالية للوظائف المحدودة.
|
| 64 |
+
|
| 65 |
+
### 5. استراتيجيات تعليمية بديلة
|
| 66 |
+
|
| 67 |
+
- **مجموعات الدراسة**: تشكيل مجموعات دراسة للمراجعة وتبادل الملخصات والأسئلة.
|
| 68 |
+
- **تقنيات التعلم النشط**: استخدام تقنيات مثل شرح المفاهيم لشخص آخر أو كتابة ملخصات يدوية.
|
| 69 |
+
- **الاستعانة بمصادر تعليمية متخصصة**: كتب ومواقع متخصصة في المجال المطلوب.
|
| 70 |
+
|
| 71 |
+
## الخطوات المستقبلية
|
| 72 |
+
|
| 73 |
+
إذا كنت لا تزال مهتماً بتطوير حلول تعليمية باستخدام الذكاء الاصطناعي، يمكن اتباع هذه الخطوات:
|
| 74 |
+
|
| 75 |
+
1. **تحديد الاحتياجات الدقيقة**: تحديد الميزة الأكثر أهمية والتركيز عليها.
|
| 76 |
+
2. **استكشاف خيارات API**: دراسة تكلفة وفوائد استخدام API من OpenAI أو Anthropic.
|
| 77 |
+
3. **النظر في حلول هجينة**: دمج الأدوات التقليدية مع لمسات بسيطة من الذكاء الاصطناعي.
|
| 78 |
+
4. **متابعة التطورات**: مراقبة التحسينات في نماذج اللغة العربية واعتمادها عند توفرها.
|
| 79 |
+
|
| 80 |
+
## خاتمة
|
| 81 |
+
|
| 82 |
+
تواجه معالجة اللغة العربية باستخدام الذكاء الاصطناعي تحديات كبيرة، خاصة في البيئات محدودة الموارد مثل Hugging Face Spaces. على الرغم من هذه التحديات، يمكن تحقيق نتائج مفيدة من خلال اتباع نهج واقعي يجمع بين الأدوات التقليدية والتقنيات الحديثة، مع التركيز على الميزات الأكثر فائدة للمستخدم النهائي.
|