""" مستخرج الكيانات العربية - نموذج جاهز محسن استخدام نموذج CAMeL-Lab المُدرب مسبقاً """ import gradio as gr from transformers import pipeline import re import logging # إعداد التسجيل logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # النماذج الموثوقة المُدربة مسبقاً AVAILABLE_MODELS = { "CAMeL-Lab Arabic BERT": "CAMeL-Lab/bert-base-arabic-camelbert-msa-ner", "AraBERT v02": "aubmindlab/bert-base-arabertv02", "Arabic BERT": "asafaya/bert-base-arabic", "نموذجنا المدرب": "hanyarafaosman/my-arabic-ner" } class ArabicNERProcessor: def __init__(self): self.current_model = None self.current_pipeline = None self.model_name = None def load_model(self, model_choice: str): """تحميل النموذج المختار""" try: model_name = AVAILABLE_MODELS[model_choice] logger.info(f"🔄 تحميل النموذج: {model_choice}") # تحميل النموذج self.current_pipeline = pipeline( "ner", model=model_name, aggregation_strategy="simple", device=-1 # استخدام CPU للاستقرار ) self.current_model = model_choice self.model_name = model_name logger.info(f"✅ تم تحميل {model_choice} بنجاح!") return f"✅ تم تحميل {model_choice} بنجاح!" except Exception as e: error_msg = f"❌ خطأ في تحميل {model_choice}: {str(e)}" logger.error(error_msg) return error_msg def clean_entity_text(self, text: str) -> str: """تنظيف النص من الرموز غير المرغوبة""" # إزالة رموز ## من BERT tokenization text = text.replace('##', '').strip() # إزالة المسافات الزائدة text = re.sub(r'\s+', ' ', text).strip() return text def extract_entities(self, text: str, confidence_threshold: float = 0.5): """استخراج الكيانات من النص""" if not self.current_pipeline: return {"error": "لم يتم تحميل أي نموذج"} if not text.strip(): return {"info": "النص فارغ"} try: # استخراج الكيانات entities = self.current_pipeline(text) # تجميع وتنظيف النتائج grouped_entities = {} for entity in entities: entity_type = entity.get('entity_group', entity.get('label', 'MISC')) entity_text = self.clean_entity_text(entity['word']) confidence = entity.get('score', 0) # فلترة بناءً على مستوى الثقة if confidence >= confidence_threshold and len(entity_text) > 1: if entity_type not in grouped_entities: grouped_entities[entity_type] = [] # إضافة الكيان مع درجة الثقة entity_info = { 'text': entity_text, 'confidence': confidence, 'start': entity.get('start', 0), 'end': entity.get('end', 0) } # تجنب التكرار if not any(e['text'] == entity_text for e in grouped_entities[entity_type]): grouped_entities[entity_type].append(entity_info) return grouped_entities except Exception as e: logger.error(f"خطأ في استخراج الكيانات: {e}") return {"error": f"خطأ في الاستخراج: {str(e)}"} def format_results(self, entities: dict, show_confidence: bool = True) -> str: """تنسيق النتائج للعرض""" if not entities: return "❌ لم يتم العثور على كيانات" if "error" in entities: return f"❌ {entities['error']}" if "info" in entities: return f"ℹ️ {entities['info']}" # ترجمة أنواع الكيانات entity_labels = { "PER": "👤 الأشخاص", "PERSON": "👤 الأشخاص", "ORG": "🏢 المؤسسات", "ORGANIZATION": "🏢 المؤسسات", "LOC": "📍 الأماكن", "LOCATION": "📍 الأماكن", "MISC": "🏷️ متنوع", "DATE": "📅 التواريخ", "TIME": "⏰ الأوقات", "MONEY": "💰 المبالغ المالية", "PERCENT": "📊 النسب المئوية", "ID": "🆔 أرقام الهوية", "PHONE": "📞 أرقام الهاتف" } result = f"🎯 **النتائج من نموذج: {self.current_model}**\n\n" total_entities = sum(len(entities_list) for entities_list in entities.values()) result += f"📊 **إجمالي الكيانات المكتشفة:** {total_entities}\n\n" for entity_type, entities_list in entities.items(): if entities_list: # التأكد من وجود كيانات label = entity_labels.get(entity_type, f"🏷️ {entity_type}") result += f"**{label}:**\n" # ترتيب حسب درجة الثقة sorted_entities = sorted(entities_list, key=lambda x: x['confidence'], reverse=True) for entity_info in sorted_entities[:5]: # أفضل 5 كيانات text = entity_info['text'] confidence = entity_info['confidence'] if show_confidence: result += f" • **{text}** (ثقة: {confidence:.2f})\n" else: result += f" • **{text}**\n" if len(entities_list) > 5: result += f" ... و {len(entities_list) - 5} كيان إضافي\n" result += "\n" return result # إنشاء معالج الكيانات processor = ArabicNERProcessor() def extract_entities_interface(text: str, model_choice: str, confidence_threshold: float, show_confidence: bool): """واجهة استخراج الكيانات للتطبيق""" # تحميل النموذج إذا تغير if processor.current_model != model_choice: status = processor.load_model(model_choice) if "❌" in status: return status # استخراج الكيانات entities = processor.extract_entities(text, confidence_threshold) # تنسيق النتائج result = processor.format_results(entities, show_confidence) return result # إعداد واجهة Gradio المحسنة def create_interface(): """إنشاء واجهة التطبيق""" # أمثلة متنوعة للاختبار examples = [ ["اسمي أحمد محمد وأعمل في شركة أرامكو في الرياض", "CAMeL-Lab Arabic BERT", 0.7, True], ["تواصل معي على رقم 0501234567 أو بريد ahmed@example.com", "AraBERT v02", 0.6, True], ["وُلدت في مكة المكرمة عام 1400هـ والهوية رقم 1234567890", "CAMeL-Lab Arabic BERT", 0.8, False], ["أعمل في جامعة الملك سعود منذ 15 عاماً", "Arabic BERT", 0.5, True] ] with gr.Blocks(title="مستخرج الكيانات العربية المتقدم", css="footer {visibility: hidden}") as demo: gr.HTML("""
نماذج متعددة - دقة عالية - سهولة في الاستخدام