""" معالج المستندات للـ RAG Document Processor for HR Genie RAG System """ from typing import List, Set from utils.rag_chain import Document class DocumentProcessor: """معالج المستندات للـ RAG""" def __init__(self, chunk_size: int = 500, chunk_overlap: int = 50): """ تهيئة المعالج Args: chunk_size: حجم القطعة (عدد الأحرف) chunk_overlap: التداخل بين القطع """ self.chunk_size = chunk_size self.chunk_overlap = chunk_overlap def split_documents(self, documents: List[Document]) -> List[Document]: """ تقسيم المستندات إلى أجزاء صغيرة (مبسط) Args: documents: قائمة المستندات Returns: قائمة المستندات المقسمة """ # نظراً لأن المستندات صغيرة نسبياً (أسئلة وأجوبة)، لا نحتاج لتقسيمها # يمكن إضافة تقسيم مخصص إذا لزم الأمر return documents def process_for_rag(self, documents: List[Document]) -> List[Document]: """ معالجة المستندات للـ RAG Args: documents: قائمة المستندات الأصلية Returns: قائمة المستندات المعالجة """ processed = [] for doc in documents: # تنظيف المحتوى content = doc.page_content.strip() # تخطي المستندات الفارغة أو القصيرة جداً if len(content) < 20: continue # إضافة معلومات إضافية metadata = doc.metadata.copy() metadata['content_length'] = len(content) metadata['processed'] = True processed_doc = Document( page_content=content, metadata=metadata ) processed.append(processed_doc) print(f"✅ تم معالجة {len(processed)} مستند") return processed def deduplicate(self, documents: List[Document]) -> List[Document]: """ إزالة المستندات المكررة Args: documents: قائمة المستندات Returns: قائمة المستندات بدون تكرار """ seen_content: Set[str] = set() unique_docs: List[Document] = [] for doc in documents: # استخدام hash للمحتوى للكشف عن التكرار content_hash = hash(doc.page_content.strip().lower()) if content_hash not in seen_content: seen_content.add(content_hash) unique_docs.append(doc) removed_count = len(documents) - len(unique_docs) if removed_count > 0: print(f"🗑️ تم إزالة {removed_count} مستند مكرر") return unique_docs def enrich_metadata(self, documents: List[Document]) -> List[Document]: """ إثراء البيانات الوصفية للمستندات Args: documents: قائمة المستندات Returns: قائمة المستندات مع بيانات وصفية إضافية """ for doc in documents: content = doc.page_content.lower() # تصنيف تلقائي بناءً على الكلمات المفتاحية if any(word in content for word in ['إجازة', 'اجازة', 'عطلة', 'راحة']): doc.metadata['auto_category'] = 'الإجازات' elif any(word in content for word in ['راتب', 'مرتب', 'بدل', 'علاوة', 'مكافأة']): doc.metadata['auto_category'] = 'الرواتب والمزايا' elif any(word in content for word in ['تدريب', 'دورة', 'كورس', 'تطوير']): doc.metadata['auto_category'] = 'التدريب والتطوير' elif any(word in content for word in ['تأمين', 'صحي', 'طبي']): doc.metadata['auto_category'] = 'التأمين الصحي' elif any(word in content for word in ['استقالة', 'ترك', 'إنهاء']): doc.metadata['auto_category'] = 'الاستقالة' elif any(word in content for word in ['تقييم', 'أداء', 'ترقية']): doc.metadata['auto_category'] = 'تقييم الأداء' else: doc.metadata['auto_category'] = 'عام' # إضافة طول المحتوى doc.metadata['word_count'] = len(doc.page_content.split()) return documents def full_process(self, documents: List[Document], split: bool = False, dedupe: bool = True, enrich: bool = True) -> List[Document]: """ المعالجة الكاملة للمستندات Args: documents: قائمة المستندات split: تقسيم المستندات الكبيرة dedupe: إزالة التكرار enrich: إثراء البيانات الوصفية Returns: قائمة المستندات المعالجة """ print(f"📥 بداية المعالجة: {len(documents)} مستند") # المعالجة الأساسية processed = self.process_for_rag(documents) # تقسيم المستندات (اختياري) if split: processed = self.split_documents(processed) print(f"✂️ بعد التقسيم: {len(processed)} مستند") # إزالة التكرار if dedupe: processed = self.deduplicate(processed) # إثراء البيانات الوصفية if enrich: processed = self.enrich_metadata(processed) print(f"✅ المعالجة اكتملت: {len(processed)} مستند نهائي") return processed if __name__ == "__main__": # اختبار المعالج processor = DocumentProcessor() # إنشاء مستندات تجريبية test_docs = [ Document(page_content="كم عدد أيام الإجازة السنوية؟ يحق لكل موظف 21 يوم إجازة.", metadata={"source": "test"}), Document(page_content="متى يتم صرف الراتب؟ يتم صرف الرواتب يوم 27 من كل شهر.", metadata={"source": "test"}), ] processed = processor.full_process(test_docs) for doc in processed: print(f"📄 {doc.metadata.get('auto_category')}: {doc.page_content[:50]}...")