Spaces:
Paused
Paused
| """ | |
| خدمة استخراج البنود من المستندات | |
| """ | |
| import re | |
| import pandas as pd | |
| import numpy as np | |
| import nltk | |
| from nltk.tokenize import sent_tokenize | |
| from pathlib import Path | |
| import config | |
| class ItemExtractor: | |
| """استخراج البنود من المستندات""" | |
| def __init__(self): | |
| # تحميل موارد NLTK إذا لم تكن موجودة | |
| try: | |
| nltk.data.find('tokenizers/punkt') | |
| except LookupError: | |
| nltk.download('punkt') | |
| # قائمة الكلمات المفتاحية التي تشير إلى بداية البنود | |
| self.item_indicators = [ | |
| 'توريد', 'تركيب', 'تنفيذ', 'تصنيع', 'أعمال', 'تأمين', | |
| 'تقديم', 'إنشاء', 'صيانة', 'إزالة', 'نقل', 'تجهيز', | |
| 'فك', 'تسليم', 'تطبيق', 'تثبيت', 'تشطيب', 'تجهيز' | |
| ] | |
| # قائمة فئات البنود | |
| self.categories = { | |
| 'أعمال الأساسات': ['أساس', 'قاعدة', 'حفر', 'ردم', 'خرسانة', 'اسمنت', 'قواعد'], | |
| 'أعمال الهيكل الإنشائي': ['عمود', 'سقف', 'كمرة', 'خرسانة', 'حديد تسليح', 'بلاطة', 'هيكل'], | |
| 'أعمال التشطيبات': ['دهان', 'بلاط', 'سيراميك', 'رخام', 'جبس', 'زجاج', 'باب', 'نافذة', 'أرضية'], | |
| 'أعمال الكهرباء': ['كهرباء', 'إضاءة', 'مفتاح', 'سلك', 'لوحة', 'كابل', 'تمديد'], | |
| 'أعمال السباكة': ['ماء', 'صرف', 'مواسير', 'حمام', 'مغسلة', 'خزان', 'مضخة'], | |
| 'أعمال التكييف': ['تكييف', 'تبريد', 'تهوية', 'مكيف', 'مجرى هواء', 'فلتر'], | |
| 'أعمال الموقع': ['تسوية', 'تخطيط', 'أسوار', 'بوابات', 'طرق', 'رصف', 'تشجير'], | |
| 'المستندات': ['مخططات', 'رسومات', 'تقارير', 'شهادات', 'اختبارات'] | |
| } | |
| def extract_items(self, text): | |
| """استخراج البنود من النص""" | |
| if not text: | |
| return pd.DataFrame() | |
| # تقسيم النص إلى جمل | |
| sentences = sent_tokenize(text) | |
| # البحث عن البنود المحتملة | |
| items = [] | |
| item_id = 1 | |
| for sentence in sentences: | |
| # تحقق مما إذا كانت الجملة تحتوي على مؤشر بند | |
| if any(indicator in sentence for indicator in self.item_indicators): | |
| # تحديد الفئة | |
| category = self._determine_category(sentence) | |
| # تحديد الأهمية | |
| importance = self._determine_importance(sentence) | |
| # إضافة البند إلى القائمة | |
| items.append({ | |
| 'رقم البند': f"I{item_id:03d}", | |
| 'وصف البند': sentence.strip(), | |
| 'الفئة': category, | |
| 'الأهمية': importance, | |
| 'الثقة': round(np.random.uniform(0.75, 0.95), 2) # محاكاة ثقة التعرف | |
| }) | |
| item_id += 1 | |
| # تحويل القائمة إلى DataFrame | |
| items_df = pd.DataFrame(items) | |
| # التأكد من وجود بيانات | |
| if items_df.empty: | |
| # إنشاء DataFrame فارغ بالأعمدة المطلوبة | |
| items_df = pd.DataFrame(columns=[ | |
| 'رقم البند', 'وصف البند', 'الفئة', 'الأهمية', 'الثقة' | |
| ]) | |
| return items_df | |
| def _determine_category(self, text): | |
| """تحديد فئة البند بناءً على محتواه""" | |
| # البحث عن الكلمات المفتاحية في النص | |
| scores = {} | |
| for category, keywords in self.categories.items(): | |
| score = sum(1 for keyword in keywords if keyword in text.lower()) | |
| scores[category] = score | |
| # اختيار الفئة ذات الدرجة الأعلى | |
| if max(scores.values()) > 0: | |
| return max(scores.items(), key=lambda x: x[1])[0] | |
| else: | |
| return "أخرى" | |
| def _determine_importance(self, text): | |
| """تحديد أهمية البند بناءً على محتواه""" | |
| # كلمات تشير إلى أهمية عالية | |
| high_importance_words = [ | |
| 'ضروري', 'هام', 'أساسي', 'رئيسي', 'كبير', 'مهم', | |
| 'حرج', 'أمان', 'سلامة', 'صحة', 'بيئة' | |
| ] | |
| # كلمات تشير إلى أهمية منخفضة | |
| low_importance_words = [ | |
| 'ثانوي', 'إضافي', 'تجميلي', 'مكمل', 'اختياري' | |
| ] | |
| # حساب درجة الأهمية | |
| high_score = sum(1 for word in high_importance_words if word in text.lower()) | |
| low_score = sum(1 for word in low_importance_words if word in text.lower()) | |
| # تحديد الأهمية بناءً على الدرجات | |
| if high_score > low_score: | |
| return "عالية" | |
| elif low_score > high_score: | |
| return "منخفضة" | |
| else: | |
| return "متوسطة" |