""" وحدة المساعد الذكي لنظام إدارة المناقصات - Hybrid Face """ import os import logging import threading import datetime import json import re from pathlib import Path # تهيئة السجل logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger('ai_assistant') class AIAssistant: """المساعد الذكي""" def __init__(self, config=None, db=None): """تهيئة المساعد الذكي""" self.config = config self.db = db self.processing_in_progress = False self.current_query = None self.processing_results = {} self.conversation_history = [] # إعدادات المساعد الذكي self.ai_model = config.AI_MODEL if config and hasattr(config, 'AI_MODEL') else "gpt-4" self.ai_temperature = config.AI_TEMPERATURE if config and hasattr(config, 'AI_TEMPERATURE') else 0.7 self.ai_max_tokens = config.AI_MAX_TOKENS if config and hasattr(config, 'AI_MAX_TOKENS') else 2000 # إنشاء مجلد المساعد الذكي إذا لم يكن موجوداً if config and hasattr(config, 'EXPORTS_PATH'): self.exports_path = Path(config.EXPORTS_PATH) else: self.exports_path = Path('data/exports') if not self.exports_path.exists(): self.exports_path.mkdir(parents=True, exist_ok=True) def process_query(self, query, context=None, callback=None): """معالجة استعلام المستخدم""" if self.processing_in_progress: logger.warning("هناك عملية معالجة جارية بالفعل") return False self.processing_in_progress = True self.current_query = query self.processing_results = { "query": query, "context": context, "processing_start_time": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "status": "جاري المعالجة", "response": "", "suggestions": [], "references": [] } # إضافة الاستعلام إلى سجل المحادثة self.conversation_history.append({ "role": "user", "content": query, "timestamp": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') }) # بدء المعالجة في خيط منفصل thread = threading.Thread( target=self._process_query_thread, args=(query, context, callback) ) thread.daemon = True thread.start() return True def _process_query_thread(self, query, context, callback): """خيط معالجة الاستعلام""" try: # تحليل الاستعلام query_type = self._analyze_query(query) # معالجة الاستعلام بناءً على نوعه if query_type == "document_analysis": response = self._handle_document_analysis_query(query, context) elif query_type == "pricing": response = self._handle_pricing_query(query, context) elif query_type == "risk_analysis": response = self._handle_risk_analysis_query(query, context) elif query_type == "project_management": response = self._handle_project_management_query(query, context) elif query_type == "reporting": response = self._handle_reporting_query(query, context) else: response = self._handle_general_query(query, context) # توليد اقتراحات suggestions = self._generate_suggestions(query_type, query, response) # تحديث نتائج المعالجة self.processing_results["response"] = response self.processing_results["query_type"] = query_type self.processing_results["suggestions"] = suggestions self.processing_results["status"] = "اكتملت المعالجة" self.processing_results["processing_end_time"] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') # إضافة الاستجابة إلى سجل المحادثة self.conversation_history.append({ "role": "assistant", "content": response, "timestamp": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') }) logger.info(f"اكتملت معالجة الاستعلام: {query[:50]}...") except Exception as e: logger.error(f"خطأ في معالجة الاستعلام: {str(e)}") self.processing_results["status"] = "فشلت المعالجة" self.processing_results["error"] = str(e) # إضافة رسالة الخطأ إلى سجل المحادثة self.conversation_history.append({ "role": "system", "content": f"حدث خطأ أثناء معالجة الاستعلام: {str(e)}", "timestamp": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') }) finally: self.processing_in_progress = False # استدعاء دالة الاستجابة إذا تم توفيرها if callback and callable(callback): callback(self.processing_results) def _analyze_query(self, query): """تحليل نوع الاستعلام""" query = query.lower() # تحديد نوع الاستعلام بناءً على الكلمات المفتاحية if any(keyword in query for keyword in ["تحليل المستند", "تحليل وثيقة", "استخراج بيانات", "قراءة مستند"]): return "document_analysis" elif any(keyword in query for keyword in ["تسعير", "سعر", "تكلفة", "ميزانية", "تقدير"]): return "pricing" elif any(keyword in query for keyword in ["مخاطر", "تحليل المخاطر", "تقييم المخاطر"]): return "risk_analysis" elif any(keyword in query for keyword in ["مشروع", "إدارة المشروع", "جدول زمني", "خطة"]): return "project_management" elif any(keyword in query for keyword in ["تقرير", "إحصائيات", "تحليل البيانات", "رسم بياني"]): return "reporting" else: return "general" def _handle_document_analysis_query(self, query, context): """معالجة استعلام تحليل المستندات""" # محاكاة استجابة المساعد الذكي لاستعلام تحليل المستندات response = """ يمكنني مساعدتك في تحليل المستندات واستخراج المعلومات المهمة منها. لتحليل مستند، يرجى اتباع الخطوات التالية: 1. انتقل إلى وحدة "تحليل المستندات" من القائمة الجانبية. 2. انقر على زر "تحميل مستند" واختر المستند المراد تحليله. 3. حدد نوع المستند (مناقصة، عقد، مواصفات فنية، إلخ). 4. انقر على زر "تحليل" لبدء عملية التحليل. سيقوم النظام باستخراج المعلومات التالية من المستند: - البنود والكميات - الكيانات (العميل، الموقع، المقاول، إلخ) - التواريخ المهمة - المبالغ والتكاليف - المخاطر المحتملة بعد اكتمال التحليل، يمكنك مراجعة النتائج وتعديلها إذا لزم الأمر، ثم استخدامها في وحدات النظام الأخرى مثل التسعير وتحليل المخاطر. """ # إضافة مراجع ذات صلة self.processing_results["references"] = [ {"title": "دليل استخدام وحدة تحليل المستندات", "type": "manual"}, {"title": "أنواع المستندات المدعومة", "type": "documentation"}, {"title": "تقنيات استخراج البيانات من المستندات", "type": "article"} ] return response def _handle_pricing_query(self, query, context): """معالجة استعلام التسعير""" # محاكاة استجابة المساعد الذكي لاستعلام التسعير response = """ يمكنني مساعدتك في تسعير المشاريع وتقدير التكاليف. لإنشاء تسعير لمشروع، يرجى اتباع الخطوات التالية: 1. انتقل إلى وحدة "التسعير المتكامل" من القائمة الجانبية. 2. اختر المشروع المراد تسعيره أو أنشئ مشروعاً جديداً. 3. أدخل بنود المشروع والكميات التقديرية (يمكن استيرادها من نتائج تحليل المستندات). 4. حدد الموارد المطلوبة (مواد، معدات، عمالة). 5. اختر استراتيجية التسعير المناسبة: - شاملة: تغطية كاملة للتكاليف والمخاطر مع هامش ربح مناسب. - تنافسية: تخفيض الهوامش لتقديم سعر تنافسي. - متوازنة: توازن بين الربحية والتنافسية. 6. انقر على زر "حساب التسعير" لإنشاء التسعير. سيقوم النظام بحساب: - التكاليف المباشرة (بنود المشروع) - التكاليف غير المباشرة (نفقات عامة، إدارية، ربح) - تكاليف المخاطر - ضريبة القيمة المضافة - السعر النهائي يمكنك تعديل المعلمات وإعادة حساب التسعير، ثم تصدير النتائج إلى تقرير مفصل. """ # إضافة مراجع ذات صلة self.processing_results["references"] = [ {"title": "دليل استخدام وحدة التسعير المتكامل", "type": "manual"}, {"title": "استراتيجيات التسعير", "type": "documentation"}, {"title": "حساب التكاليف غير المباشرة", "type": "article"} ] return response def _handle_risk_analysis_query(self, query, context): """معالجة استعلام تحليل المخاطر""" # محاكاة استجابة المساعد الذكي لاستعلام تحليل المخاطر response = """ يمكنني مساعدتك في تحليل وإدارة مخاطر المشروع. لإجراء تحليل للمخاطر، يرجى اتباع الخطوات التالية: 1. انتقل إلى وحدة "تحليل المخاطر" من القائمة الجانبية. 2. اختر المشروع المراد تحليل مخاطره. 3. اختر طريقة التحليل: - شاملة: تحليل مفصل يغطي جميع جوانب المشروع. - أساسية: تحليل سريع للمخاطر الرئيسية. 4. انقر على زر "تحليل المخاطر" لبدء التحليل. سيقوم النظام بما يلي: - تحديد المخاطر المحتملة بناءً على بيانات المشروع - تصنيف المخاطر إلى فئات (فني، مالي، إداري، إلخ) - إنشاء مصفوفة المخاطر (الاحتمالية × التأثير) - تطوير استراتيجيات التخفيف لكل مخاطرة - إنشاء ملخص للمخاطر وتوصيات يمكنك مراجعة نتائج التحليل وتعديلها، ثم تصدير التقرير النهائي واستخدامه في خطة إدارة المشروع. """ # إضافة مراجع ذات صلة self.processing_results["references"] = [ {"title": "دليل استخدام وحدة تحليل المخاطر", "type": "manual"}, {"title": "منهجيات تحليل المخاطر", "type": "documentation"}, {"title": "استراتيجيات التخفيف من المخاطر", "type": "article"} ] return response def _handle_project_management_query(self, query, context): """معالجة استعلام إدارة المشاريع""" # محاكاة استجابة المساعد الذكي لاستعلام إدارة المشاريع response = """ يمكنني مساعدتك في إدارة المشاريع وتتبع تقدمها. لإدارة مشروع، يرجى اتباع الخطوات التالية: 1. انتقل إلى وحدة "إدارة المشاريع" من القائمة الجانبية. 2. أنشئ مشروعاً جديداً أو اختر مشروعاً موجوداً. 3. أدخل معلومات المشروع الأساسية (الاسم، العميل، الوصف، التواريخ). 4. أضف بنود المشروع (يمكن استيرادها من نتائج تحليل المستندات). 5. أنشئ الجدول الزمني للمشروع وحدد المراحل والمهام. 6. عين الموارد للمهام وحدد التبعيات بينها. يمكنك استخدام وحدة إدارة المشاريع لـ: - تتبع تقدم المشروع ومقارنته بالخطة - إدارة الموارد وتوزيعها - متابعة المشكلات والمخاطر - إدارة التغييرات في نطاق العمل - إنشاء تقارير حالة المشروع كما يمكنك دمج نتائج التسعير وتحليل المخاطر في خطة المشروع لإدارة شاملة. """ # إضافة مراجع ذات صلة self.processing_results["references"] = [ {"title": "دليل استخدام وحدة إدارة المشاريع", "type": "manual"}, {"title": "أفضل ممارسات إدارة المشاريع", "type": "documentation"}, {"title": "إنشاء جداول زمنية فعالة", "type": "article"} ] return response def _handle_reporting_query(self, query, context): """معالجة استعلام التقارير""" # محاكاة استجابة المساعد الذكي لاستعلام التقارير response = """ يمكنني مساعدتك في إنشاء تقارير وتحليلات للمشاريع والمناقصات. لإنشاء تقرير، يرجى اتباع الخطوات التالية: 1. انتقل إلى وحدة "التقارير والتحليلات" من القائمة الجانبية. 2. اختر نوع التقرير: - تقرير المشروع: معلومات شاملة عن مشروع محدد - تقرير التسعير: تفاصيل تسعير مشروع أو مناقصة - تقرير المخاطر: تحليل مخاطر المشروع واستراتيجيات التخفيف - تقرير الأداء: مقارنة الأداء الفعلي بالمخطط - تقرير مالي: تحليل مالي للمشاريع والمناقصات 3. حدد معلمات التقرير (المشروع، الفترة الزمنية، إلخ). 4. انقر على زر "إنشاء التقرير". يمكنك تخصيص التقارير بإضافة أو إزالة أقسام، وتغيير طريقة عرض البيانات (جداول، رسوم بيانية، إلخ). التقارير المنشأة يمكن: - تصديرها بتنسيقات مختلفة (PDF، Excel، Word) - مشاركتها مع أعضاء الفريق أو العملاء - جدولتها للإنشاء التلقائي بشكل دوري - حفظها كقوالب لاستخدامها في المستقبل """ # إضافة مراجع ذات صلة self.processing_results["references"] = [ {"title": "دليل استخدام وحدة التقارير والتحليلات", "type": "manual"}, {"title": "أنواع التقارير المتاحة", "type": "documentation"}, {"title": "إنشاء رسوم بيانية فعالة", "type": "article"} ] return response def _handle_general_query(self, query, context): """معالجة استعلام عام""" # محاكاة استجابة المساعد الذكي لاستعلام عام response = """ مرحباً بك في المساعد الذكي لنظام إدارة المناقصات Hybrid Face. يمكنني مساعدتك في مجموعة متنوعة من المهام المتعلقة بإدارة المناقصات والمشاريع. يمكنني مساعدتك في: - تحليل مستندات المناقصات واستخراج المعلومات المهمة منها - تسعير المشاريع وتقدير التكاليف - تحليل وإدارة مخاطر المشاريع - إدارة المشاريع وتتبع تقدمها - إنشاء تقارير وتحليلات للحصول على مساعدة محددة، يرجى طرح سؤال يتعلق بإحدى هذه المجالات. على سبيل المثال: - "كيف يمكنني تحليل مستند مناقصة؟" - "ساعدني في تسعير مشروع جديد" - "كيف أقوم بتحليل مخاطر المشروع؟" - "أريد إنشاء تقرير عن حالة المشروع" يمكنك أيضاً استخدام الوحدات المختلفة في النظام مباشرة من القائمة الجانبية. """ # إضافة مراجع ذات صلة self.processing_results["references"] = [ {"title": "دليل المستخدم الشامل", "type": "manual"}, {"title": "نظرة عامة على النظام", "type": "documentation"}, {"title": "الأسئلة الشائعة", "type": "faq"} ] return response def _generate_suggestions(self, query_type, query, response): """توليد اقتراحات للمستخدم بناءً على الاستعلام والاستجابة""" suggestions = [] if query_type == "document_analysis": suggestions = [ "كيف يمكنني استيراد نتائج تحليل المستندات إلى وحدة التسعير؟", "ما هي أنواع المستندات المدعومة للتحليل؟", "كيف يمكنني تحسين دقة تحليل المستندات؟" ] elif query_type == "pricing": suggestions = [ "ما هي استراتيجية التسعير المناسبة لمشروعي؟", "كيف يمكنني حساب التكاليف غير المباشرة؟", "كيف أضيف تكاليف المخاطر إلى التسعير؟" ] elif query_type == "risk_analysis": suggestions = [ "ما هي أفضل استراتيجيات التخفيف من المخاطر؟", "كيف يمكنني تحديد المخاطر الحرجة في المشروع؟", "كيف أدمج تحليل المخاطر في خطة المشروع؟" ] elif query_type == "project_management": suggestions = [ "كيف أنشئ جدولاً زمنياً فعالاً للمشروع؟", "كيف أتتبع تقدم المشروع مقارنة بالخطة؟", "كيف أدير التغييرات في نطاق المشروع؟" ] elif query_type == "reporting": suggestions = [ "ما هي أنواع التقارير المتاحة في النظام؟", "كيف يمكنني تخصيص تقرير المشروع؟", "كيف أقوم بجدولة إنشاء تقارير دورية؟" ] else: suggestions = [ "كيف يمكنني البدء باستخدام النظام؟", "ما هي الوحدات المتاحة في النظام؟", "كيف يمكنني إنشاء مشروع جديد؟" ] return suggestions def get_processing_status(self): """الحصول على حالة المعالجة الحالية""" if not self.processing_in_progress: if not self.processing_results: return {"status": "لا توجد معالجة جارية"} else: return {"status": self.processing_results.get("status", "غير معروف")} return { "status": "جاري المعالجة", "query": self.current_query, "start_time": self.processing_results.get("processing_start_time") } def get_processing_results(self): """الحصول على نتائج المعالجة""" return self.processing_results def get_conversation_history(self, limit=10): """الحصول على سجل المحادثة""" if limit and limit > 0: return self.conversation_history[-limit:] return self.conversation_history def clear_conversation_history(self): """مسح سجل المحادثة""" self.conversation_history = [] return True def export_conversation_history(self, output_path=None): """تصدير سجل المحادثة إلى ملف JSON""" if not self.conversation_history: logger.warning("لا يوجد سجل محادثة للتصدير") return None if not output_path: # إنشاء اسم ملف افتراضي timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S') filename = f"conversation_history_{timestamp}.json" output_path = os.path.join(self.exports_path, filename) try: with open(output_path, 'w', encoding='utf-8') as f: json.dump(self.conversation_history, f, ensure_ascii=False, indent=4) logger.info(f"تم تصدير سجل المحادثة إلى: {output_path}") return output_path except Exception as e: logger.error(f"خطأ في تصدير سجل المحادثة: {str(e)}") return None