# -*- coding: utf-8 -*- """ مساعد الطالب الذكي - نسخة محسنة تطبيق تعليمي متكامل للطلاب باللغة العربية """ import gradio as gr import torch import random import datetime import json from datetime import datetime, timedelta # تحقق من توفر المكتبات وتثبيتها إذا لزم الأمر try: from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM except ImportError: import subprocess import sys subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'transformers']) from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM # ---------------------- وظائف معالجة النصوص ---------------------- # def summarize_text(text, max_length=150): """تلخيص النص العربي باستخدام نموذج مناسب""" if not text or len(text.strip()) < 50: return "النص قصير جداً أو فارغ. يرجى إدخال نص أطول للتلخيص." try: # استخدام نموذج خفيف للتلخيص summarizer = pipeline( "summarization", model="yalsaffar/mt5-small-Arabic-Summarization", device=0 if torch.cuda.is_available() else -1 ) # تقسيم النص إلى أجزاء إذا كان طويلاً max_chunk_length = 512 chunks = [text[i:i+max_chunk_length] for i in range(0, len(text), max_chunk_length)] summaries = [] for chunk in chunks[:3]: # نأخذ أول 3 أجزاء فقط لتجنب استهلاك الموارد if len(chunk.strip()) > 50: # تجاهل الأجزاء القصيرة جداً summary = summarizer(chunk, max_length=max_length, min_length=30, do_sample=False) summaries.append(summary[0]['summary_text']) if not summaries: return "لم نتمكن من تلخيص النص. يرجى التأكد من أن النص مكتوب باللغة العربية وأنه يحتوي على معلومات كافية." return " ".join(summaries) except Exception as e: return f"حدث خطأ أثناء التلخيص: {str(e)}" def generate_questions(text, num_questions=3): """توليد أسئلة من النص العربي""" if not text or len(text.strip()) < 50: return "النص قصير جداً أو فارغ. يرجى إدخال نص أطول لتوليد الأسئلة." try: # استخدام نموذج خفيف لتوليد الأسئلة # نظراً لأن النماذج المتخصصة قد تكون ثقيلة، نستخدم نهجاً مبسطاً sentences = text.split('.') questions = [] # اختيار جمل عشوائية وتحويلها إلى أسئلة selected_sentences = random.sample(sentences, min(num_questions + 2, len(sentences))) for sentence in selected_sentences: sentence = sentence.strip() if len(sentence) > 15: # تجاهل الجمل القصيرة جداً # تحويل الجملة إلى سؤال بطريقة بسيطة if "هو" in sentence: question = sentence.replace("هو", "ما هو") + "؟" elif "هي" in sentence: question = sentence.replace("هي", "ما هي") + "؟" elif "كان" in sentence: question = sentence.replace("كان", "ماذا كان") + "؟" elif "يمكن" in sentence: question = sentence.replace("يمكن", "كيف يمكن") + "؟" else: # إضافة كلمة استفهام في بداية الجملة question_starters = ["ما هو", "كيف", "لماذا", "متى", "أين"] question = random.choice(question_starters) + " " + sentence + "؟" questions.append(question) if len(questions) >= num_questions: break if not questions: return "لم نتمكن من توليد أسئلة من هذا النص. يرجى تجربة نص آخر." return "\n\n".join(questions) except Exception as e: return f"حدث خطأ أثناء توليد الأسئلة: {str(e)}" def extract_keywords(text, num_keywords=10): """استخراج الكلمات المفتاحية من النص العربي""" if not text or len(text.strip()) < 50: return "النص قصير جداً أو فارغ. يرجى إدخال نص أطول لاستخراج الكلمات المفتاحية." try: # تنظيف النص text = text.replace('\n', ' ').replace('\r', ' ') words = text.split() # إزالة الكلمات القصيرة والحروف stop_words = ["في", "من", "على", "إلى", "عن", "مع", "هذا", "هذه", "ذلك", "تلك", "هو", "هي", "أنا", "نحن", "أنت", "أنتم", "هم", "و", "أو", "ثم", "لكن", "ف", "ب", "ل", "ك", "و", "ا", "ال", "إن", "أن", "لا", "ما", "لم"] filtered_words = [word for word in words if len(word) > 2 and word not in stop_words] # حساب تكرار الكلمات word_freq = {} for word in filtered_words: if word in word_freq: word_freq[word] += 1 else: word_freq[word] = 1 # ترتيب الكلمات حسب التكرار sorted_words = sorted(word_freq.items(), key=lambda x: x[1], reverse=True) # اختيار الكلمات الأكثر تكراراً top_keywords = sorted_words[:num_keywords] if not top_keywords: return "لم نتمكن من استخراج كلمات مفتاحية من هذا النص. يرجى تجربة نص آخر." # تنسيق النتيجة result = "الكلمات المفتاحية:\n\n" for i, (word, freq) in enumerate(top_keywords, 1): result += f"{i}. {word} (التكرار: {freq})\n" return result except Exception as e: return f"حدث خطأ أثناء استخراج الكلمات المفتاحية: {str(e)}" def generate_mind_map(text): """إنشاء خريطة ذهنية بسيطة من النص العربي""" if not text or len(text.strip()) < 50: return "النص قصير جداً أو فارغ. يرجى إدخال نص أطول لإنشاء الخريطة الذهنية." try: # تقسيم النص إلى فقرات وجمل paragraphs = text.split('\n') sentences = text.split('.') # استخراج العنوان الرئيسي (أول جملة أو أول 50 حرف) main_title = sentences[0].strip() if sentences and len(sentences[0]) > 5 else text[:50] + "..." # استخراج العناوين الفرعية (بداية كل فقرة أو جمل مختارة) subtitles = [] # من الفقرات for para in paragraphs: if len(para.strip()) > 20: first_sentence = para.split('.')[0].strip() if first_sentence and len(first_sentence) > 15 and first_sentence not in subtitles: subtitles.append(first_sentence) # إذا لم نجد عناوين فرعية كافية، نأخذ من الجمل if len(subtitles) < 3: for sentence in sentences[1:]: if len(sentence.strip()) > 15 and sentence.strip() not in subtitles: subtitles.append(sentence.strip()) if len(subtitles) >= 5: break # إنشاء الخريطة الذهنية بتنسيق Markdown mind_map = f"# {main_title}\n\n" for i, subtitle in enumerate(subtitles[:5], 1): mind_map += f"## {subtitle}\n" # إضافة بعض النقاط تحت كل عنوان فرعي related_sentences = [s.strip() for s in sentences if subtitle not in s and len(s.strip()) > 10] for j, related in enumerate(random.sample(related_sentences, min(3, len(related_sentences))), 1): if len(related) > 10: mind_map += f" - {related}\n" mind_map += "\n" return mind_map except Exception as e: return f"حدث خطأ أثناء إنشاء الخريطة الذهنية: {str(e)}" def create_flashcards(text, num_cards=5): """إنشاء بطاقات تعليمية من النص العربي""" if not text or len(text.strip()) < 50: return "النص قصير جداً أو فارغ. يرجى إدخال نص أطول لإنشاء البطاقات التعليمية." try: # تقسيم النص إلى جمل sentences = [s.strip() for s in text.split('.') if len(s.strip()) > 15] if len(sentences) < 2: return "النص لا يحتوي على جمل كافية لإنشاء البطاقات التعليمية. يرجى إدخال نص أطول." # إنشاء البطاقات التعليمية flashcards = [] # اختيار جمل عشوائية selected_sentences = random.sample(sentences, min(num_cards * 2, len(sentences))) for i in range(0, len(selected_sentences) - 1, 2): if i + 1 < len(selected_sentences): question = selected_sentences[i] answer = selected_sentences[i + 1] # تحويل الجملة الأولى إلى سؤال إذا لم تكن كذلك if not question.endswith('?') and not question.endswith('؟'): question_starters = ["ما هو", "كيف", "لماذا", "اشرح", "وضح"] question = random.choice(question_starters) + " " + question + "؟" flashcards.append({"question": question, "answer": answer}) if len(flashcards) >= num_cards: break if not flashcards: return "لم نتمكن من إنشاء بطاقات تعليمية من هذا النص. يرجى تجربة نص آخر." # تنسيق النتيجة كنص بدلاً من JSON result = "البطاقات التعليمية:\n\n" for i, card in enumerate(flashcards, 1): result += f"بطاقة {i}:\n" result += f"السؤال: {card['question']}\n" result += f"الإجابة: {card['answer']}\n\n" return result except Exception as e: return f"حدث خطأ أثناء إنشاء البطاقات التعليمية: {str(e)}" def create_study_schedule(subject_name, start_date_str, exam_date_str, importance=3): """إنشاء جدول مراجعة باستخدام تقنية المراجعة المتباعدة""" try: # تحويل التواريخ من نص إلى كائنات datetime try: start_date = datetime.strptime(start_date_str, "%Y-%m-%d") exam_date = datetime.strptime(exam_date_str, "%Y-%m-%d") except ValueError: return "صيغة التاريخ غير صحيحة. يرجى استخدام الصيغة YYYY-MM-DD (مثال: 2025-06-20)." if start_date >= exam_date: return "تاريخ بدء المراجعة يجب أن يكون قبل تاريخ الامتحان." # حساب عدد الأيام المتاحة للمراجعة days_available = (exam_date - start_date).days if days_available < 1: return "لا توجد أيام كافية للمراجعة. يرجى اختيار تاريخ بدء أبكر." # تحديد عدد جلسات المراجعة بناءً على الأهمية وعدد الأيام المتاحة if importance <= 1: num_sessions = min(3, days_available) elif importance == 2: num_sessions = min(5, days_available) else: # importance >= 3 num_sessions = min(7, days_available) # إنشاء جدول المراجعة باستخدام تقنية المراجعة المتباعدة schedule = [] # الجلسة الأولى تكون في يوم البدء current_date = start_date schedule.append({ "session": 1, "date": current_date.strftime("%Y-%m-%d"), "day": ["الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"][current_date.weekday()], "focus": "مراجعة شاملة للمادة" }) # توزيع باقي الجلسات بشكل متباعد intervals = [1, 2, 4, 7, 12, 20] # فترات المراجعة المتباعدة بالأيام for i in range(1, num_sessions): # حساب تاريخ الجلسة التالية if i < len(intervals): days_to_add = intervals[i-1] else: days_to_add = intervals[-1] current_date = current_date + timedelta(days=days_to_add) # التأكد من أن تاريخ الجلسة قبل تاريخ الامتحان if current_date >= exam_date: # إذا تجاوزنا تاريخ الامتحان، نضع الجلسة قبل يوم من الامتحان current_date = exam_date - timedelta(days=1) # تحديد التركيز لكل جلسة if i == num_sessions - 1: focus = "مراجعة نهائية وحل أسئلة سابقة" elif i == 1: focus = "مراجعة المفاهيم الأساسية" elif i == 2: focus = "حل تمارين وأمثلة" else: focus = "مراجعة النقاط الصعبة" schedule.append({ "session": i + 1, "date": current_date.strftime("%Y-%m-%d"), "day": ["الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"][current_date.weekday()], "focus": focus }) # إذا وصلنا إلى يوم قبل الامتحان، نتوقف if current_date >= exam_date - timedelta(days=1): break # إضافة يوم الامتحان schedule.append({ "session": "الامتحان", "date": exam_date.strftime("%Y-%m-%d"), "day": ["الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"][exam_date.weekday()], "focus": "يوم الامتحان" }) # تنسيق النتيجة كنص result = f"جدول المراجعة لمادة: {subject_name}\n\n" for session in schedule: if session["session"] == "الامتحان": result += f"📝 {session['date']} ({session['day']}): {session['focus']}\n" else: result += f"📚 جلسة {session['session']}: {session['date']} ({session['day']}) - {session['focus']}\n" return result except Exception as e: return f"حدث خطأ أثناء إنشاء جدول المراجعة: {str(e)}" def analyze_exam_questions(questions_text): """تحليل أنماط أسئلة الامتحانات""" if not questions_text or len(questions_text.strip()) < 20: return "النص قصير جداً أو فارغ. يرجى إدخال أسئلة امتحانات سابقة للتحليل." try: # تقسيم النص إلى أسئلة منفصلة questions = [q.strip() for q in questions_text.split('\n') if len(q.strip()) > 5 and ('؟' in q or '?' in q)] if len(questions) < 2: return "لم نتمكن من تحديد أسئلة كافية للتحليل. يرجى التأكد من فصل كل سؤال بسطر جديد وإنهاء الأسئلة بعلامة استفهام." # تحليل أنواع الأسئلة question_types = { "تعريف": 0, "شرح": 0, "مقارنة": 0, "تحليل": 0, "تطبيق": 0, "أخرى": 0 } for q in questions: q_lower = q.lower() if any(word in q_lower for word in ["عرف", "ما هو", "ما هي", "من هو"]): question_types["تعريف"] += 1 elif any(word in q_lower for word in ["اشرح", "وضح", "بين", "فسر"]): question_types["شرح"] += 1 elif any(word in q_lower for word in ["قارن", "الفرق", "الاختلاف"]): question_types["مقارنة"] += 1 elif any(word in q_lower for word in ["حلل", "ناقش", "قيم"]): question_types["تحليل"] += 1 elif any(word in q_lower for word in ["طبق", "استخدم", "احسب"]): question_types["تطبيق"] += 1 else: question_types["أخرى"] += 1 # تحليل الكلمات المفتاحية all_words = " ".join(questions).split() word_freq = {} stop_words = ["ما", "هو", "هي", "كيف", "لماذا", "متى", "أين", "من", "في", "على", "إلى", "عن", "مع"] for word in all_words: if len(word) > 2 and word not in stop_words: if word in word_freq: word_freq[word] += 1 else: word_freq[word] = 1 # ترتيب الكلمات حسب التكرار sorted_words = sorted(word_freq.items(), key=lambda x: x[1], reverse=True) top_keywords = sorted_words[:10] # تنسيق النتيجة result = f"تحليل {len(questions)} سؤال:\n\n" result += "أنواع الأسئلة:\n" for q_type, count in question_types.items(): if count > 0: percentage = (count / len(questions)) * 100 result += f"- {q_type}: {count} ({percentage:.1f}%)\n" result += "\nالمواضيع الأكثر تكراراً:\n" for word, freq in top_keywords: result += f"- {word}: {freq} مرات\n" result += "\nتوصيات للمراجعة:\n" # تحديد نوع السؤال الأكثر تكراراً most_common_type = max(question_types.items(), key=lambda x: x[1])[0] result += f"1. التركيز على الإجابة على أسئلة {most_common_type}\n" # توصيات بناءً على الكلمات المفتاحية result += f"2. مراجعة المواضيع المتعلقة بـ: {', '.join([w for w, _ in top_keywords[:5]])}\n" # توصية عامة result += "3. التدرب على الإجابة على الأسئلة بأسلوب منظم ومختصر\n" return result except Exception as e: return f"حدث خطأ أثناء تحليل أسئلة الامتحانات: {str(e)}" # ---------------------- واجهة المستخدم ---------------------- # def create_interface(): """إنشاء واجهة المستخدم باستخدام Gradio""" # الشعار والعنوان title = """
أداة تعليمية متكاملة للطلاب باستخدام الذكاء الاصطناعي