anaspro
commited on
Commit
·
76cae54
1
Parent(s):
df14f5f
- README.md +29 -66
- app.py +19 -222
- data/nbtel_company_profile.md +0 -296
- rag_requirements.txt +0 -4
- requirements.txt +2 -5
- simple_rag.py +0 -367
- test_rag.py +0 -126
- test_tts.py +0 -40
README.md
CHANGED
|
@@ -1,90 +1,53 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
emoji: 🤖
|
| 4 |
colorFrom: blue
|
| 5 |
-
colorTo:
|
| 6 |
sdk: gradio
|
| 7 |
-
sdk_version:
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
models:
|
| 11 |
-
- anaspro/Shako-4B-it
|
| 12 |
tags:
|
| 13 |
- arabic
|
| 14 |
- iraq
|
| 15 |
- iraqi-dialect
|
| 16 |
-
- technical-support
|
| 17 |
- chatbot
|
| 18 |
- multimodal
|
| 19 |
-
-
|
| 20 |
-
-
|
|
|
|
| 21 |
---
|
| 22 |
|
| 23 |
-
|
| 24 |
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
-
|
| 28 |
|
| 29 |
-
|
| 30 |
-
- � **مدعوم بـ RAG**: يستخدم قاعدة معرفة شاملة عن الشركة وخدماتها
|
| 31 |
-
- 🔧 **دعم فني متكامل**: يحل المشاكل التقنية خطوة بخطوة
|
| 32 |
-
- 🖼️ **متعدد الوسائط**: يدعم الصور والفيديوهات والملفات الصوتية
|
| 33 |
-
- � **قاعدة معرفة ذكية**: معلومات شاملة عن خدمات NBTEL
|
| 34 |
-
- 💬 **تفاعلي وسريع**: ردود فورية ومفيدة
|
| 35 |
|
| 36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
|
| 38 |
-
|
| 39 |
-
-
|
| 40 |
-
-
|
| 41 |
-
- دعم فني شامل 24/7
|
| 42 |
|
| 43 |
-
|
| 44 |
-
-
|
| 45 |
-
-
|
| 46 |
-
- محافظة صلاح الدين
|
| 47 |
-
|
| 48 |
-
## 📞 معلومات التواصل
|
| 49 |
-
|
| 50 |
-
- **الدعم الفني**: 6337
|
| 51 |
-
- **واتساب**: 0773 633 7777
|
| 52 |
-
- **الإيميل**: Info@nbtel.iq
|
| 53 |
-
- **المبيعات**: sales@nbtele.net
|
| 54 |
-
|
| 55 |
-
## 🎯 كيفية الاستخدام
|
| 56 |
-
|
| 57 |
-
1. **اكتب استفسارك**: مثل "عندي مشكلة بالواي فاي"
|
| 58 |
-
2. **ارفع صور** إذا كان عندك مشكلة تقنية
|
| 59 |
-
3. **احصل على حل مفصل** خطوة بخطوة
|
| 60 |
-
4. **تواصل مع الدعم المباشر** عند الحاجة
|
| 61 |
-
|
| 62 |
-
## 🔧 التقنيات المستخدمة
|
| 63 |
-
|
| 64 |
-
- **النموذج الأساسي**: Shako-4B-it-v5 (نموذج عراقي متطور)
|
| 65 |
-
- **تقنية RAG**: Retrieval-Augmented Generation
|
| 66 |
-
- **قاعدة المعرفة**: Sentence Transformers + Scikit-learn
|
| 67 |
-
- **الواجهة**: Gradio
|
| 68 |
-
- **الاستضافة**: Hugging Face Spaces
|
| 69 |
-
|
| 70 |
-
## 📋 أمثلة على الاستخدام
|
| 71 |
-
|
| 72 |
-
```
|
| 73 |
-
المستخدم: شنو خدمات شركتكم؟
|
| 74 |
-
المساعد: أهلاً وسهلاً بيك! احنا شركة NBTEL عراقية متخصصة بخدمات الإنترنت...
|
| 75 |
-
|
| 76 |
-
المستخدم: عندي مشكلة الواي فاي ما يظهر
|
| 77 |
-
المساعد: لا تشيل هم، راح نحلها سوا. أول شي تأكد من...
|
| 78 |
-
|
| 79 |
-
المستخدم: شگد أسعار الباقات؟
|
| 80 |
-
المساعد: عندنا باقات متنوعة: 35 ميگا بـ45,000، 60 ميگا بـ55,000...
|
| 81 |
-
```
|
| 82 |
-
|
| 83 |
-
---
|
| 84 |
-
|
| 85 |
-
**تطوير**: فريق NBTEL التقني
|
| 86 |
-
**النموذج**: Shako العراقي المتطور
|
| 87 |
-
**التحديث**: أكتوبر 2024
|
| 88 |
|
| 89 |
4. **تشغيل Space:**
|
| 90 |
- اضغط "Restart this space" لإعادة التشغيل
|
|
|
|
| 1 |
---
|
| 2 |
+
title: شكو - ذكاء شكو العراقي
|
| 3 |
emoji: 🤖
|
| 4 |
colorFrom: blue
|
| 5 |
+
colorTo: green
|
| 6 |
sdk: gradio
|
| 7 |
+
sdk_version: 5.42.0
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
models:
|
| 11 |
+
- anaspro/Shako-4B-it
|
| 12 |
tags:
|
| 13 |
- arabic
|
| 14 |
- iraq
|
| 15 |
- iraqi-dialect
|
|
|
|
| 16 |
- chatbot
|
| 17 |
- multimodal
|
| 18 |
+
- voice
|
| 19 |
+
- image
|
| 20 |
+
- video
|
| 21 |
---
|
| 22 |
|
| 23 |
+
ذكاء صناعي عراقي متقدم يتحدث باللهجة العراقية - موديل شكو المتعدد الوسائط.
|
| 24 |
|
| 25 |
+
🚀 **المميزات:**
|
| 26 |
+
- 🇮🇶 متخصص في اللهجة العراقية واللغة العربية
|
| 27 |
+
- 🧠 موديل شكو 4B المتقدم متعدد الوسائط
|
| 28 |
+
- 🎤 دعم التسجيل الصوتي والرد الصوتي
|
| 29 |
+
- 🖼️ دعم الصور والفيديوهات
|
| 30 |
+
- 💬 إجابات مرحة وودية بالعراقي
|
| 31 |
+
- 🎯 سهل الاستخدام مع واجهة عصرية
|
| 32 |
|
| 33 |
+
📞 احجي مع ذكاء شكو العراقي بالعراقي - يدعم الصوت والصور والفيديو!
|
| 34 |
|
| 35 |
+
## 🚀 كيفية النشر على Hugging Face Spaces ZeroGPU
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
| 37 |
+
1. **إنشاء Space جديد:**
|
| 38 |
+
- اذهب إلى [Hugging Face Spaces](https://huggingface.co/spaces)
|
| 39 |
+
- اضغط "Create new Space"
|
| 40 |
+
- اختر اسم مناسب (مثل: Iraqi-Shako-AI)
|
| 41 |
+
- اختر "Gradio" كـ SDK
|
| 42 |
+
- اختر "ZeroGPU" كـ Hardware
|
| 43 |
|
| 44 |
+
2. **رفع الملفات:**
|
| 45 |
+
- ارفع `app.py`, `requirements.txt`, `README.md`, `system_prompt.txt`
|
| 46 |
+
- تأكد من أن `app.py` هو الملف الرئيسي
|
|
|
|
| 47 |
|
| 48 |
+
3. **إعدادات البيئة:**
|
| 49 |
+
- اذهب إلى Settings → Variables and secrets
|
| 50 |
+
- أضف `HF_TOKEN` إذا كنت تحتاج token للوصول للمودل
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
|
| 52 |
4. **تشغيل Space:**
|
| 53 |
- اضغط "Restart this space" لإعادة التشغيل
|
app.py
CHANGED
|
@@ -11,9 +11,6 @@ import torch
|
|
| 11 |
from transformers import AutoModelForImageTextToText, AutoProcessor
|
| 12 |
from transformers.generation.streamers import TextIteratorStreamer
|
| 13 |
|
| 14 |
-
# استيراد نظام RAG
|
| 15 |
-
from simple_rag import SimpleRAG
|
| 16 |
-
|
| 17 |
# Model configuration
|
| 18 |
model_id = "anaspro/Shako-4B-it-v5"
|
| 19 |
processor = AutoProcessor.from_pretrained(model_id)
|
|
@@ -33,56 +30,6 @@ TARGET_FPS = int(os.getenv("TARGET_FPS", "3"))
|
|
| 33 |
MAX_FRAMES = int(os.getenv("MAX_FRAMES", "30"))
|
| 34 |
MAX_INPUT_TOKENS = int(os.getenv("MAX_INPUT_TOKENS", "10_000"))
|
| 35 |
|
| 36 |
-
# تهيئة نظام RAG للدعم الفني
|
| 37 |
-
print("🔄 جاري تهيئة نظام RAG للدعم الفني...")
|
| 38 |
-
try:
|
| 39 |
-
rag_system = SimpleRAG()
|
| 40 |
-
|
| 41 |
-
# محاولة تحميل فهرس موجود
|
| 42 |
-
if not rag_system.load_index():
|
| 43 |
-
print("🔄 إنشاء فهرس جديد...")
|
| 44 |
-
|
| 45 |
-
# تحميل ملف شركة NBTEL
|
| 46 |
-
nbtel_file = "./data/nbtel_company_profile.md"
|
| 47 |
-
if os.path.exists(nbtel_file):
|
| 48 |
-
print(f"📁 وجد ملف البيانات: {nbtel_file}")
|
| 49 |
-
documents = rag_system.load_markdown_file(nbtel_file)
|
| 50 |
-
if documents:
|
| 51 |
-
rag_system.add_documents(documents)
|
| 52 |
-
rag_system.build_index()
|
| 53 |
-
rag_system.save_index()
|
| 54 |
-
print("✅ تم إنشاء فهرس RAG بنجاح")
|
| 55 |
-
else:
|
| 56 |
-
print("⚠️ لم يتم استخراج أي مستندات من الملف")
|
| 57 |
-
else:
|
| 58 |
-
print(f"⚠️ لم يتم العثور على ملف البيانات: {nbtel_file}")
|
| 59 |
-
# إنشاء بيانات تجريبية بسيطة
|
| 60 |
-
sample_docs = [
|
| 61 |
-
{
|
| 62 |
-
'title': 'معلومات أساسية عن NBTEL',
|
| 63 |
-
'content': 'شركة NBTEL عراقية متخصصة في خدمات الإنترنت والاتصالات. نقدم خدمات WiFi و FTTX في محافظات نينوى وكركوك وصلاح الدين.',
|
| 64 |
-
'source': 'fallback'
|
| 65 |
-
},
|
| 66 |
-
{
|
| 67 |
-
'title': 'معلومات التواصل',
|
| 68 |
-
'content': 'للدعم الفني: 6337، واتساب: 0773 633 7777، إيميل: Info@nbtel.iq',
|
| 69 |
-
'source': 'fallback'
|
| 70 |
-
}
|
| 71 |
-
]
|
| 72 |
-
rag_system.add_documents(sample_docs)
|
| 73 |
-
rag_system.build_index()
|
| 74 |
-
rag_system.save_index()
|
| 75 |
-
print("✅ تم إنشاء فهرس تجريبي")
|
| 76 |
-
|
| 77 |
-
print(f"✅ نظام RAG جاهز - {len(rag_system.documents)} مستند")
|
| 78 |
-
RAG_ENABLED = True
|
| 79 |
-
|
| 80 |
-
except Exception as e:
|
| 81 |
-
print(f"❌ خطأ في تهيئة نظام RAG: {str(e)}")
|
| 82 |
-
print("⚠️ سيتم تشغيل النظام بدون RAG")
|
| 83 |
-
rag_system = None
|
| 84 |
-
RAG_ENABLED = False
|
| 85 |
-
|
| 86 |
|
| 87 |
def get_file_type(path: str) -> str:
|
| 88 |
if path.endswith(IMAGE_FILE_TYPES):
|
|
@@ -95,83 +42,6 @@ def get_file_type(path: str) -> str:
|
|
| 95 |
raise ValueError(error_message)
|
| 96 |
|
| 97 |
|
| 98 |
-
def search_knowledge_base(query: str) -> str:
|
| 99 |
-
"""البحث في قاعدة المعرفة باستخدام RAG"""
|
| 100 |
-
|
| 101 |
-
if not RAG_ENABLED or rag_system is None:
|
| 102 |
-
return ""
|
| 103 |
-
|
| 104 |
-
try:
|
| 105 |
-
# البحث في قاعدة المعرفة
|
| 106 |
-
context = rag_system.get_context_for_query(query, max_results=3)
|
| 107 |
-
|
| 108 |
-
if context and "لم أجد معلومات" not in context:
|
| 109 |
-
return f"\n\n📚 معلومات من قاعدة المعرفة:\n{context}"
|
| 110 |
-
else:
|
| 111 |
-
return ""
|
| 112 |
-
|
| 113 |
-
except Exception as e:
|
| 114 |
-
print(f"خطأ في البحث في قاعدة المعرفة: {str(e)}")
|
| 115 |
-
return ""
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
def create_technical_support_prompt(user_message: str, knowledge_context: str = "") -> str:
|
| 119 |
-
"""إنشاء prompt محسن للدعم الفني"""
|
| 120 |
-
|
| 121 |
-
base_prompt = """أنت مساعد دعم فني ذكي لشركة NBTEL العراقية.
|
| 122 |
-
|
| 123 |
-
هويتك ومهامك:
|
| 124 |
-
- اسمك: مساعد NBTEL الذكي
|
| 125 |
-
- تتحدث باللهجة العراقية الودية والمرحة
|
| 126 |
-
- خبير في خدمات الإنترنت والاتصالات والدعم الفني
|
| 127 |
-
- تساعد العملاء في حل مشاكلهم التقنية
|
| 128 |
-
- تقدم معلومات عن خدمات وأسعار الشركة
|
| 129 |
-
|
| 130 |
-
قواعد التعامل:
|
| 131 |
-
1. رحب بالعميل بطريقة عراقية ودية (أهلاً وسهلاً، مرحبا بيك، الخ)
|
| 132 |
-
2. استخدم المعلومات من قاعدة المعرفة إن وجدت
|
| 133 |
-
3. اطرح أسئلة توضيحية لفهم المشكلة بدقة
|
| 134 |
-
4. قدم حلول عملية خطوة بخطوة
|
| 135 |
-
5. استخدم أمثلة عراقية مفهومة
|
| 136 |
-
6. كن صبور ومساعد مع العملاء
|
| 137 |
-
7. إذا ما تعرف الجواب، اعترف واطلب التواصل مع الدعم المباشر
|
| 138 |
-
|
| 139 |
-
أسلوب الكلام:
|
| 140 |
-
- استخدم "احنا" بدلاً من "نحن"
|
| 141 |
-
- استخدم "شلونك" بدلاً من "كيف حالك"
|
| 142 |
-
- استخدم "شنو" بدلاً من "ماذا"
|
| 143 |
-
- استخدم "وين" بدلاً من "أين"
|
| 144 |
-
- استخدم "اكو" بدلاً من "يوجد"
|
| 145 |
-
- اجعل الكلام طبيعي ومرح
|
| 146 |
-
|
| 147 |
-
معلومات الشركة الأساسية:
|
| 148 |
-
- شركة NBTEL عراقية متخصصة بخدمات الإنترنت والاتصالات
|
| 149 |
-
- نخدم محافظات نينوى، كركوك، وصلاح الدين
|
| 150 |
-
- نقدم خدمات WiFi و FTTX (الكيبل الضوئي)
|
| 151 |
-
- مقرنا الرئيسي في الموصل
|
| 152 |
-
- رقم الدعم الفني: 6337
|
| 153 |
-
- واتساب: 0773 633 7777
|
| 154 |
-
|
| 155 |
-
"""
|
| 156 |
-
|
| 157 |
-
if knowledge_context:
|
| 158 |
-
enhanced_prompt = f"""{base_prompt}
|
| 159 |
-
|
| 160 |
-
{knowledge_context}
|
| 161 |
-
|
| 162 |
-
الاستفسار: {user_message}
|
| 163 |
-
|
| 164 |
-
جاوب بطريقة ودية وعملية، واستخدم المعلومات اللي فوق إذا كانت مفيدة:"""
|
| 165 |
-
else:
|
| 166 |
-
enhanced_prompt = f"""{base_prompt}
|
| 167 |
-
|
| 168 |
-
الاستفسار: {user_message}
|
| 169 |
-
|
| 170 |
-
جاوب بطريقة ودية وعملية:"""
|
| 171 |
-
|
| 172 |
-
return enhanced_prompt
|
| 173 |
-
|
| 174 |
-
|
| 175 |
def count_files_in_new_message(paths: list[str]) -> tuple[int, int]:
|
| 176 |
video_count = 0
|
| 177 |
non_video_count = 0
|
|
@@ -291,19 +161,6 @@ def generate(message: dict, history: list[dict], system_prompt: str = "", max_ne
|
|
| 291 |
yield ""
|
| 292 |
return
|
| 293 |
|
| 294 |
-
# استخراج النص من الرسالة للبحث في قاعدة المعرفة
|
| 295 |
-
user_text = message.get("text", "")
|
| 296 |
-
|
| 297 |
-
# البحث في قاعدة المعرفة
|
| 298 |
-
knowledge_context = search_knowledge_base(user_text) if user_text else ""
|
| 299 |
-
|
| 300 |
-
# إنشاء prompt محسن للدعم الفني
|
| 301 |
-
if user_text:
|
| 302 |
-
enhanced_prompt = create_technical_support_prompt(user_text, knowledge_context)
|
| 303 |
-
# استبدال النص الأصلي بالـ prompt المحسن
|
| 304 |
-
message = message.copy()
|
| 305 |
-
message["text"] = enhanced_prompt
|
| 306 |
-
|
| 307 |
messages = []
|
| 308 |
if system_prompt:
|
| 309 |
messages.append({"role": "system", "content": [{"type": "text", "text": system_prompt}]})
|
|
@@ -333,12 +190,13 @@ def generate(message: dict, history: list[dict], system_prompt: str = "", max_ne
|
|
| 333 |
streamer=streamer,
|
| 334 |
max_new_tokens=max_new_tokens,
|
| 335 |
do_sample=True,
|
| 336 |
-
temperature=0
|
| 337 |
-
top_k=
|
| 338 |
-
top_p=0.
|
| 339 |
min_p=0.0,
|
| 340 |
-
repetition_penalty=1.
|
| 341 |
disable_compile=True,
|
|
|
|
| 342 |
)
|
| 343 |
t = Thread(target=model.generate, kwargs=generate_kwargs)
|
| 344 |
t.start()
|
|
@@ -351,33 +209,17 @@ def generate(message: dict, history: list[dict], system_prompt: str = "", max_ne
|
|
| 351 |
|
| 352 |
# Examples for the chat interface (with additional inputs: system_prompt, max_new_tokens)
|
| 353 |
examples = [
|
| 354 |
-
["
|
| 355 |
-
["
|
| 356 |
-
["
|
| 357 |
-
["الإنترنت عندي ضعيف، شنو الحل؟", "", 600],
|
| 358 |
-
["كيف أقدر أغير كلمة سر الراوتر؟", "", 500],
|
| 359 |
-
["وين مقر الشركة ومعلومات التواصل؟", "", 400]
|
| 360 |
]
|
| 361 |
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
| 367 |
-
|
| 368 |
-
- ركز على حل المشاكل التقنية وتقديم المساعدة العملية
|
| 369 |
-
- استخدم المعلومات من قاعدة المعرفة عندما تكون متوفرة
|
| 370 |
-
- إذا ما تعرف جواب محدد، اعترف واطلب التواصل مع الدعم المباشر
|
| 371 |
-
|
| 372 |
-
أسلوب الكلام العراقي:
|
| 373 |
-
- استخدم "شلونك" بدلاً من "كيف حالك"
|
| 374 |
-
- استخدم "شنو" بدلاً من "ماذا"
|
| 375 |
-
- استخدم "وين" بدلاً من "أين"
|
| 376 |
-
- استخدم "احنا" بدلاً من "نحن"
|
| 377 |
-
- استخدم "اكو" بدلاً من "يوجد"
|
| 378 |
-
- استخدم "شگد" بدلاً من "كم"
|
| 379 |
-
|
| 380 |
-
كن ودود ومساعد دائماً!"""
|
| 381 |
# Create the chat interface
|
| 382 |
demo = gr.ChatInterface(
|
| 383 |
fn=generate,
|
|
@@ -386,66 +228,21 @@ demo = gr.ChatInterface(
|
|
| 386 |
file_types=list(IMAGE_FILE_TYPES + VIDEO_FILE_TYPES + AUDIO_FILE_TYPES),
|
| 387 |
file_count="multiple",
|
| 388 |
autofocus=True,
|
| 389 |
-
placeholder="اكتب استفسارك هنا... مثل: عندي مشكلة بالإنترنت، أو شنو خدماتكم؟"
|
| 390 |
),
|
| 391 |
multimodal=True,
|
| 392 |
additional_inputs=[
|
| 393 |
-
gr.Textbox(
|
| 394 |
-
|
| 395 |
-
value=system_prompt,
|
| 396 |
-
lines=3,
|
| 397 |
-
visible=False # مخفي للمستخدم العادي
|
| 398 |
-
),
|
| 399 |
-
gr.Slider(
|
| 400 |
-
label="Max New Tokens",
|
| 401 |
-
minimum=100,
|
| 402 |
-
maximum=2048,
|
| 403 |
-
step=50,
|
| 404 |
-
value=1024,
|
| 405 |
-
visible=False # مخفي للمستخدم العادي
|
| 406 |
-
),
|
| 407 |
],
|
| 408 |
-
title="
|
| 409 |
-
description=f"""
|
| 410 |
-
🌟 **أهلاً وسهلاً بيك في مساعد NBTEL الذكي!**
|
| 411 |
-
|
| 412 |
-
احنا هنا نساعدك في:
|
| 413 |
-
• 🔧 حل مشاكل الإنترنت والواي فاي
|
| 414 |
-
• 📋 معلومات عن خدماتنا وأسعارنا
|
| 415 |
-
• 📞 التواصل والدعم الفني
|
| 416 |
-
• 🛠️ إرشادات تقنية مفصلة
|
| 417 |
-
|
| 418 |
-
{"✅ **نظام المعرفة متصل** - عندي معلومات شاملة عن الشركة والخدمات" if RAG_ENABLED else "⚠️ **نظام المعرفة غير متصل** - راح أساعدك بالمعلومات العامة"}
|
| 419 |
-
|
| 420 |
-
**للدعم المباشر**: 📞 6337 | 📱 واتساب: 0773 633 7777
|
| 421 |
-
""",
|
| 422 |
examples=examples,
|
| 423 |
-
stop_btn=
|
| 424 |
css="""
|
| 425 |
.gradio-container, .chatbot, .chatbot * {
|
| 426 |
direction: rtl !important;
|
| 427 |
text-align: right !important;
|
| 428 |
unicode-bidi: plaintext !important;
|
| 429 |
-
font-family: 'Tajawal', 'Cairo',
|
| 430 |
-
}
|
| 431 |
-
.chatbot .message {
|
| 432 |
-
padding: 15px !important;
|
| 433 |
-
margin: 10px !important;
|
| 434 |
-
border-radius: 15px !important;
|
| 435 |
-
}
|
| 436 |
-
.chatbot .message.user {
|
| 437 |
-
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
|
| 438 |
-
color: white !important;
|
| 439 |
-
}
|
| 440 |
-
.chatbot .message.bot {
|
| 441 |
-
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%) !important;
|
| 442 |
-
color: white !important;
|
| 443 |
-
}
|
| 444 |
-
.title {
|
| 445 |
-
color: #2c3e50 !important;
|
| 446 |
-
font-size: 2em !important;
|
| 447 |
-
font-weight: bold !important;
|
| 448 |
-
text-align: center !important;
|
| 449 |
}
|
| 450 |
"""
|
| 451 |
)
|
|
|
|
| 11 |
from transformers import AutoModelForImageTextToText, AutoProcessor
|
| 12 |
from transformers.generation.streamers import TextIteratorStreamer
|
| 13 |
|
|
|
|
|
|
|
|
|
|
| 14 |
# Model configuration
|
| 15 |
model_id = "anaspro/Shako-4B-it-v5"
|
| 16 |
processor = AutoProcessor.from_pretrained(model_id)
|
|
|
|
| 30 |
MAX_FRAMES = int(os.getenv("MAX_FRAMES", "30"))
|
| 31 |
MAX_INPUT_TOKENS = int(os.getenv("MAX_INPUT_TOKENS", "10_000"))
|
| 32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
|
| 34 |
def get_file_type(path: str) -> str:
|
| 35 |
if path.endswith(IMAGE_FILE_TYPES):
|
|
|
|
| 42 |
raise ValueError(error_message)
|
| 43 |
|
| 44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
def count_files_in_new_message(paths: list[str]) -> tuple[int, int]:
|
| 46 |
video_count = 0
|
| 47 |
non_video_count = 0
|
|
|
|
| 161 |
yield ""
|
| 162 |
return
|
| 163 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
messages = []
|
| 165 |
if system_prompt:
|
| 166 |
messages.append({"role": "system", "content": [{"type": "text", "text": system_prompt}]})
|
|
|
|
| 190 |
streamer=streamer,
|
| 191 |
max_new_tokens=max_new_tokens,
|
| 192 |
do_sample=True,
|
| 193 |
+
temperature=1.0,
|
| 194 |
+
top_k=64,
|
| 195 |
+
top_p=0.95,
|
| 196 |
min_p=0.0,
|
| 197 |
+
repetition_penalty=1.0,
|
| 198 |
disable_compile=True,
|
| 199 |
+
|
| 200 |
)
|
| 201 |
t = Thread(target=model.generate, kwargs=generate_kwargs)
|
| 202 |
t.start()
|
|
|
|
| 209 |
|
| 210 |
# Examples for the chat interface (with additional inputs: system_prompt, max_new_tokens)
|
| 211 |
examples = [
|
| 212 |
+
["What is the capital of France?", "You are a helpful assistant.", 700],
|
| 213 |
+
["Explain quantum computing in simple terms", "You are a helpful assistant.", 512],
|
| 214 |
+
["Write a short story about a robot learning to paint", "You are a helpful assistant.", 1000]
|
|
|
|
|
|
|
|
|
|
| 215 |
]
|
| 216 |
|
| 217 |
+
system_prompt = (
|
| 218 |
+
"انت موديل عراقي ذكي من بغداد. تتحدث باللهجة العراقية فقط. "
|
| 219 |
+
"جاوب على كل سؤال بشرح كامل وموسع، ووضح الأسباب والخلفية والمعلومات المهمة. "
|
| 220 |
+
"استخدم أمثلة عراقية واقعية أو حياتية كلما أمكن. "
|
| 221 |
+
"تجنب الفصحى نهائيًا، وخلي الرد مطول وممتع."
|
| 222 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
# Create the chat interface
|
| 224 |
demo = gr.ChatInterface(
|
| 225 |
fn=generate,
|
|
|
|
| 228 |
file_types=list(IMAGE_FILE_TYPES + VIDEO_FILE_TYPES + AUDIO_FILE_TYPES),
|
| 229 |
file_count="multiple",
|
| 230 |
autofocus=True,
|
|
|
|
| 231 |
),
|
| 232 |
multimodal=True,
|
| 233 |
additional_inputs=[
|
| 234 |
+
gr.Textbox(label="System Prompt", value=system_prompt),
|
| 235 |
+
gr.Slider(label="Max New Tokens", minimum=100, maximum=2048, step=10, value=2048),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 236 |
],
|
| 237 |
+
title="Shako IRAQI AI",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 238 |
examples=examples,
|
| 239 |
+
stop_btn=False,
|
| 240 |
css="""
|
| 241 |
.gradio-container, .chatbot, .chatbot * {
|
| 242 |
direction: rtl !important;
|
| 243 |
text-align: right !important;
|
| 244 |
unicode-bidi: plaintext !important;
|
| 245 |
+
font-family: 'Tajawal', 'Cairo', sans-serif;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 246 |
}
|
| 247 |
"""
|
| 248 |
)
|
data/nbtel_company_profile.md
DELETED
|
@@ -1,296 +0,0 @@
|
|
| 1 |
-
# ملف تعريف شركة NBTEL
|
| 2 |
-
**تاريخ الإصدار**: مايو 2024
|
| 3 |
-
|
| 4 |
-
## من نحن
|
| 5 |
-
|
| 6 |
-
شركة NBTEL لتكنولوجيا المعلومات، واحدة من أكبر الشركات العراقية في هذا المجال. نوفر خدمات الإنترنت في المحافظات الشمالية العراقية نينوى وكركوك وصلاح الدين بالشراكة مع وزارة الاتصالات العراقية.
|
| 7 |
-
|
| 8 |
-
### خدماتنا الرئيسية
|
| 9 |
-
- خدمات الإنترنت الكيبل الضوئي FTTX في محافظة نينوى
|
| 10 |
-
- خدمات مختلفة بكل ما يتعلق بالكيبل الضوئي من مد ونصب وتشغيل وصيانة
|
| 11 |
-
- توفير الخدمات إلى مشغلين خدمة GSM في العراق: ASIACELL, KOREK TELECOM, ZAIN IRAQ
|
| 12 |
-
- شراكة مع وزارة الاتصالات العراقية
|
| 13 |
-
|
| 14 |
-
### شراكاتنا
|
| 15 |
-
- شراكات عمل مع العديد من الشركات المحلية في العراق
|
| 16 |
-
- شراكات استراتيجية مع شركات عالمية مثل نوكيا
|
| 17 |
-
- تعاون مع شركات عالمية كبرى مثل Google (Alphabet), Meta (Facebook)
|
| 18 |
-
|
| 19 |
-
## رؤيتنا
|
| 20 |
-
|
| 21 |
-
تقديم نموذجاً متقدماً في العمل، محوره الرئيس سعادة الزبون، وتعزيز جودة الخدمة من خلال:
|
| 22 |
-
- العديد من الاستراتيجيات والمؤشرات
|
| 23 |
-
- إعادة صياغة مفهوم مبتكر وإطار متكامل لتقديم الخدمات
|
| 24 |
-
- رفع كفاءة الخدمات إلى أفضل المستويات العالمية
|
| 25 |
-
- السعي المستمر إلى تطوير وتحسين مستوى بيئة أداء الخدمات
|
| 26 |
-
|
| 27 |
-
## ما الذي يميز شركتنا
|
| 28 |
-
|
| 29 |
-
### مبدأ الشراكة
|
| 30 |
-
- نجحنا في اكتساب ثقة قاعدة واسعة من العملاء
|
| 31 |
-
- نفتخر بأعلى معدلات الاحتفاظ بالعملاء (93%)
|
| 32 |
-
- مبدؤنا: عملاؤنا هم بمثابة شركائنا
|
| 33 |
-
|
| 34 |
-
### القدرة على التكيّف
|
| 35 |
-
- تناغمنا مع المتغيرات العصرية والتقنية الحديثة
|
| 36 |
-
- قادرين على توفير الحلول المختلفة لعملائنا
|
| 37 |
-
- استغلال التطور الكبير في التقنيات الحديثة
|
| 38 |
-
|
| 39 |
-
### الوفاء بالوعد
|
| 40 |
-
- نتوخى أعلى درجات المهنية
|
| 41 |
-
- نطمح إلى إيجاد شراكات مستديمة مع عملائنا
|
| 42 |
-
- نحرص على تلبية توقعات العملاء
|
| 43 |
-
|
| 44 |
-
### النظرة الشمولية
|
| 45 |
-
- واحدة من أكبر وأفضل شركات تكنولوجيا المعلومات في العراق
|
| 46 |
-
- توفر دائرة متكاملة من خدمات الإنترنت وحلول الاتصالات
|
| 47 |
-
- قدرة متميزة على ترجمة التحديات إلى حلول
|
| 48 |
-
|
| 49 |
-
## عملاؤنا
|
| 50 |
-
|
| 51 |
-
يتنوع عملاؤنا من المنزل أساساً إلى مختلف القطاعات التجارية والخدمية:
|
| 52 |
-
- الشركات والمكاتب والهيئات في مختلف القطاعات
|
| 53 |
-
- نقدم خدمة دعم ما بعد البيع
|
| 54 |
-
- عملاؤنا يقومون بتسويق اسمنا وسمعتنا
|
| 55 |
-
|
| 56 |
-
## فريقنا
|
| 57 |
-
|
| 58 |
-
### الخبرات والكفاءات
|
| 59 |
-
- كفاءات عالية وخبرات متخصصة في مجال الاتصالات وخدمات الإنترنت
|
| 60 |
-
- خبرة في تقديم الاستشارات التطبيقية في مجالات تكنولوجيا المعلومات
|
| 61 |
-
- فريق تقني متخصص في مد وربط شبكات الكيبل الضوئي
|
| 62 |
-
- خبرة واسعة في التعامل الحكومي
|
| 63 |
-
|
| 64 |
-
### مميزات الفريق
|
| 65 |
-
- سرعة الاستجابة في حل المشاكل
|
| 66 |
-
- الإجابة على كافة الاستفسارات والطلبات
|
| 67 |
-
- مصداقية نقل المعلومة وخدمة الزبون
|
| 68 |
-
- دائماً في الصدارة
|
| 69 |
-
|
| 70 |
-
## إدارتنا
|
| 71 |
-
|
| 72 |
-
### خصائص الإدارة
|
| 73 |
-
- خبرة واسعة في التعامل مع العملاء وتلبية احتياجاتهم
|
| 74 |
-
- مواكبة التطور والتحديات المختلفة
|
| 75 |
-
- تقديم الحلول العملية والاحترافية الرصينة
|
| 76 |
-
- تطوير مهارات فريق العمل
|
| 77 |
-
|
| 78 |
-
### فلسفة العمل
|
| 79 |
-
- نؤمن بروح الفريق
|
| 80 |
-
- الشركة هي ملك للجميع
|
| 81 |
-
- الجميع حريص على تقديم أفضل ما يمكن لإرضاء العميل
|
| 82 |
-
- سرعة ودقة ورصانة الإنجاز
|
| 83 |
-
|
| 84 |
-
### المقر الرئيسي
|
| 85 |
-
- الموصل، محافظة نينوى
|
| 86 |
-
- نوفر خدماتنا في محافظتي كركوك وصلاح الدين
|
| 87 |
-
|
| 88 |
-
## تاريخنا
|
| 89 |
-
|
| 90 |
-
### البدايات
|
| 91 |
-
- تأسست الشركة باسم "نور البداية" كشركة تجارة عامة
|
| 92 |
-
- تأسست ثلاث شركات أخرى في نفس الوقت تقريباً
|
| 93 |
-
- قررت هذه الشركات الاندماج بشركة واحدة
|
| 94 |
-
- اختيار NBTEL كعلامة تجارية للشركة
|
| 95 |
-
|
| 96 |
-
### التطور
|
| 97 |
-
- تضاعف حجم الشركة عدة مرات
|
| 98 |
-
- أصبحت واحدة من أكبر الشركات العراقية في مجال تكنولوجيا المعلومات
|
| 99 |
-
- شريك رسمي لوزارة الاتصالات العراقية
|
| 100 |
-
- وضع الأسس لبناء منظومة محكمة تصوب الأهداف
|
| 101 |
-
|
| 102 |
-
### الإنجازات والعقود
|
| 103 |
-
|
| 104 |
-
#### عام 2020
|
| 105 |
-
- إضافة نشاط الإنترنت والاتصالات
|
| 106 |
-
- عقد تمرير السعات
|
| 107 |
-
- عقد المشاركة بتسويق وإمرار سعات الاتصالات عبر شبكة الكيبل الضوئي الوطني
|
| 108 |
-
- مدة العقد 3 سنوات في تقديم خدمات الإنترنت اللاسلكية WIFI والمنافذ الحدودية البرية
|
| 109 |
-
- شراكة مع شركة ETSI في بغداد
|
| 110 |
-
|
| 111 |
-
#### عام 2021
|
| 112 |
-
- شراكة مع شركة ضوء الفضاء STS
|
| 113 |
-
- عقد منظومة FTTH
|
| 114 |
-
- عقود مع شركة SEP لخدمات تكنولوجيا المعلومات والبرمجيات
|
| 115 |
-
- عقود صيانة مع شركة ماستر نيتورك
|
| 116 |
-
|
| 117 |
-
#### عام 2022
|
| 118 |
-
- تسويق السعات
|
| 119 |
-
- إضافة نشاط تكنولوجيا المعلومات
|
| 120 |
-
- عقد الشراكة الاستراتيجية مع شركة NOKIA
|
| 121 |
-
- عقود صيانة مع شركة KOREK TELECOM
|
| 122 |
-
- عقود صيانة مع شركة ASIACELL
|
| 123 |
-
|
| 124 |
-
#### عام 2023
|
| 125 |
-
- عقود صيانة مع شركة ZAIN IRAQ
|
| 126 |
-
- ترخيص التسويق لثلاثة محافظات (نينوى، صلاح الدين، كركوك)
|
| 127 |
-
|
| 128 |
-
#### عام 2024
|
| 129 |
-
- عقد إنشاء وتشغيل وتسويق وصيانة منظومة خدمات FTTH في محافظة نينوى
|
| 130 |
-
- أصبحت الخدمة متاحة للمنازل والمباني والقطاع الخاص والعام والأفراد والشركات
|
| 131 |
-
- مدة العقد 12 سنة، أصبح اسمها FTTX
|
| 132 |
-
|
| 133 |
-
## مشاركاتنا
|
| 134 |
-
|
| 135 |
-
### المعارض والمؤتمرات
|
| 136 |
-
- معرض بغداد الدولي I TEX (فبراير 2022)
|
| 137 |
-
- مهرجان الربيع في الموصل (2023، 2024)
|
| 138 |
-
- معرض صناعتنا هويتنا في نينوى (سبتمبر 2022)
|
| 139 |
-
- الزيارة الأربعينية لكربلاء (2022)
|
| 140 |
-
|
| 141 |
-
### الفعاليات الثقافية والاجتماعية
|
| 142 |
-
- دعم راديو الغد افتتاحية متحف الموصل (2020)
|
| 143 |
-
- مسرح الربيع أوركسترا وتر (2021)
|
| 144 |
-
- مهرجان التعليم الحكومي والأهلي أشور لاند (2022)
|
| 145 |
-
- قاعة الهيثم ذكرى تأسيس قناة suroyo TV الفضائية (2022)
|
| 146 |
-
- احياء روح وتراث الموصل مع UNESCO (2023)
|
| 147 |
-
|
| 148 |
-
### النشاطات التدريبية والتثقيفية
|
| 149 |
-
- استضافة الطلبة من مختلف الجامعات والكليات
|
| 150 |
-
- ندوة تدريبية حول خدمة الكيبل الضوئي والأمن السيبراني
|
| 151 |
-
- دورة تدريبية عن مشروع FTTH
|
| 152 |
-
- تغطية خدمة الإنترنت مجاناً في مؤتمر السنودس المقدس
|
| 153 |
-
- دورة تدريبية عملية لكيفية إيصال وربط FTTH للمنازل
|
| 154 |
-
|
| 155 |
-
## خدماتنا
|
| 156 |
-
|
| 157 |
-
### الخدمة الأولى: خدمة الإنترنت اللاسلكية WiFi Internet Service
|
| 158 |
-
|
| 159 |
-
#### الوصف
|
| 160 |
-
- خدمة الإنترنت اللاسلكية عبر الأبراج
|
| 161 |
-
- نقدمها من خلال وكلائنا وبالشراكة معهم ومع وزارة الاتصالات
|
| 162 |
-
- تصل للزبون من خلال أبراج الوايرلس WiFi
|
| 163 |
-
- نقدمها في نينوى وصلاح الدين وتكريت
|
| 164 |
-
|
| 165 |
-
#### شركاؤنا
|
| 166 |
-
- شركة بلوسكاي
|
| 167 |
-
- شركة سوفت لينك
|
| 168 |
-
- تحالف نينوى
|
| 169 |
-
|
| 170 |
-
### الخدمة الثانية: خدمة الإنترنت الكيبل الضوئي FTTX Internet Service
|
| 171 |
-
|
| 172 |
-
#### الوصف
|
| 173 |
-
- خدمة الإنترنت الضوئي FTTX عبر تمرير مباشر للكيبل الضوئي
|
| 174 |
-
- وصولاً إلى آخر نقطة وهو البيت أو الشركة كمستخدم نهائي
|
| 175 |
-
- خدمة الكيبل الضوئي إلى المنزل FTTH
|
| 176 |
-
- تعتبر الأفضل والأحدث والأكفأ عالمياً
|
| 177 |
-
|
| 178 |
-
#### مناطق التغطية
|
| 179 |
-
- حصرياً في محافظة نينوى في الوقت الحالي
|
| 180 |
-
- في مناطق معينة فقط نظراً للتحديات في البنية التحتية
|
| 181 |
-
- تحتاج إلى عمل كبير واستثمار عالي ووقت غير قليل
|
| 182 |
-
|
| 183 |
-
#### التحديات
|
| 184 |
-
- تدمير كبير في البنية التحتية في السنوات السابقة
|
| 185 |
-
- تحديات في التنسيق مع مختلف الجهات
|
| 186 |
-
- تنظيم حفر ومد ونصب وتأهيل للبنى التحتية
|
| 187 |
-
|
| 188 |
-
### الخدمات الأخرى
|
| 189 |
-
|
| 190 |
-
#### أ. خدمة تهيئة وصيانة البنية التحتية
|
| 191 |
-
- متعلقة بالكوابل الضوئية
|
| 192 |
-
|
| 193 |
-
#### ب. خدمات تكنولوجيا المعلومات
|
| 194 |
-
- التحول الرقمي والأتمتة
|
| 195 |
-
- الأمن السيبراني والمراقبة
|
| 196 |
-
- ربط منظومات الذكاء الاصطناعي AI
|
| 197 |
-
- حلول عالية المستوى بأحدث وأرقى التكنولوجيا العالمية
|
| 198 |
-
- تعاون مع رو��د الصناعة العالمية
|
| 199 |
-
|
| 200 |
-
## معلومات الاتصال
|
| 201 |
-
|
| 202 |
-
### الإيميلات
|
| 203 |
-
- **الاتصالات العامة**: Info@nbtel.iq
|
| 204 |
-
- **المبيعات**: sales@nbtele.net
|
| 205 |
-
|
| 206 |
-
### خدمة العملاء والدعم الفني
|
| 207 |
-
- **الهاتف**: 6337 (نحتاج رقم رسمي)
|
| 208 |
-
- **الواتساب**: 0773 633 7777
|
| 209 |
-
|
| 210 |
-
### التواصل الاجتماعي
|
| 211 |
-
- **فيسبوك**: facebook.com/nbtel/
|
| 212 |
-
- **انستغرام**: instagram.com/nb.tel/
|
| 213 |
-
|
| 214 |
-
## الدعم الفني - المشاكل التقنية
|
| 215 |
-
|
| 216 |
-
### مشكلة: شبكة الواي فاي لا تظهر
|
| 217 |
-
**الأعراض**: WLAN2.4G, WLAN5G مطفأة
|
| 218 |
-
**الحلول**:
|
| 219 |
-
- إذا كان جهازك نوكيا: تأكد أنه موصول بالكهرباء وتأكد من ضوء ONU
|
| 220 |
-
- اضغط على زر WLAN خلف الجهاز لتشغيل الواي فاي
|
| 221 |
-
- إذا كان لديك ONU: تأكد من إعدادات راوترك الشخصي وأضواء الجهاز ON
|
| 222 |
-
|
| 223 |
-
### مشكلة: لا يوجد خدمة
|
| 224 |
-
**الحلول**:
|
| 225 |
-
- تأكد من أن جهازك موصول بالكهرباء power: ON
|
| 226 |
-
- تأكد من Link: ON
|
| 227 |
-
- تأكد من عدد الأجهزة المتصلة على الراوتر
|
| 228 |
-
- عدا ذلك تواصل مع الدعم الفني
|
| 229 |
-
|
| 230 |
-
### مشكلة: ضعف في الخدمة / الإنترنت ضعيف
|
| 231 |
-
**الحلول**:
|
| 232 |
-
- تأكد من أنك ضمن مجال تغطية الواي فاي
|
| 233 |
-
- تأكد أن الجهاز موصول بمصدر كهرباء ثابت
|
| 234 |
-
- عدا ذلك تواصل مع الدعم الفني
|
| 235 |
-
|
| 236 |
-
### مشكلة: عندي انقطاعات
|
| 237 |
-
**الحلول**:
|
| 238 |
-
- تأكد من أنك ضمن مجال تغطية الواي فاي
|
| 239 |
-
- تأكد من جودة المحولة أو العاكسة
|
| 240 |
-
- تأكد من جودة الأسلاك
|
| 241 |
-
- تأكد من جودة الراوتر
|
| 242 |
-
|
| 243 |
-
### مشكلة: الراوتر الثانوي لا يعمل
|
| 244 |
-
**الحلول**:
|
| 245 |
-
- تأكد من جودة كابل الإيثرنت وأنه موصل برقم المنفذ المفتوح
|
| 246 |
-
- تأكد من إعدادات الجهاز الثانوي
|
| 247 |
-
|
| 248 |
-
### مشكلة: لا أستطيع تسجيل الدخول TOD
|
| 249 |
-
**الحلول**:
|
| 250 |
-
- يرجى التأكد من إدخال الرقم المسجل بالعقد مع إضافة مفتاح الدولة +964
|
| 251 |
-
- التأكد من صحة الرقم السري
|
| 252 |
-
|
| 253 |
-
### تغيير اسم ورمز الواي فاي Nokia ONT
|
| 254 |
-
**الخطوات**:
|
| 255 |
-
1. افتح متصفحك وأدخل 192.168.1.254
|
| 256 |
-
2. أدخل معلومات الدخول (اسم المستخدم وكلمة المرور) الموجودة خلف الجهاز
|
| 257 |
-
3. من الإعدادات غيّر كلمة المرور
|
| 258 |
-
|
| 259 |
-
## خدمات التركيب
|
| 260 |
-
|
| 261 |
-
### هل يمكن نقل الخدمة إلى عنوان جديد؟
|
| 262 |
-
نعم، يمكن نقل الخدمة ضمن نطاق التغطية بعد التنسيق معنا
|
| 263 |
-
|
| 264 |
-
### هل تتوفر الخدمة في منطقتي؟
|
| 265 |
-
تواصل معنا وسنزودك بمعلومات التغطية حسب موقعك
|
| 266 |
-
|
| 267 |
-
### كيف ألغي اشتراكي؟
|
| 268 |
-
لإلغاء الاشتراك، تواصل مع خدمة العملاء وسيتم تنفيذ الطلب
|
| 269 |
-
|
| 270 |
-
### هل التركيب مجاني؟
|
| 271 |
-
نعم، التركيب مجاني
|
| 272 |
-
|
| 273 |
-
### ما المطلوب حتى أشترك بالخدمة؟
|
| 274 |
-
- البطاقة الموحدة مع بطاقة السكن
|
| 275 |
-
- المربع الذهبي
|
| 276 |
-
- رقم الموبايل
|
| 277 |
-
- موقع GPS
|
| 278 |
-
|
| 279 |
-
### كيف أقدم على اشتراك جديد؟
|
| 280 |
-
ابعث اسمك الثلاثي على رقم الحجوزات +96477
|
| 281 |
-
|
| 282 |
-
## الاشتراكات والدفع
|
| 283 |
-
|
| 284 |
-
### اشتراكات للمنازل والمؤسسات
|
| 285 |
-
- اشتراك Public IP متوفر
|
| 286 |
-
|
| 287 |
-
### الباقات المتوفرة
|
| 288 |
-
- **35 Mbps**: 45,000 على موديمك
|
| 289 |
-
- **60 Mbps**: 55,000 على موديمك
|
| 290 |
-
- **100 Mbps**: 75,000 على موديمك
|
| 291 |
-
|
| 292 |
-
### هل أستطيع تغيير الباقة الخاصة بي؟
|
| 293 |
-
نعم، يمكنك تغيير الباقة بعد انتهاء الباقة الحالية عبر التطبيق أو بالتواصل معنا
|
| 294 |
-
|
| 295 |
-
### هل يوجد عروض أو خصومات حالياً؟
|
| 296 |
-
تابعنا على منصات التواصل الاجتماعي للاطلاع على العروض
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rag_requirements.txt
DELETED
|
@@ -1,4 +0,0 @@
|
|
| 1 |
-
# المكتبات الأساسية لنظام RAG البسيط
|
| 2 |
-
sentence-transformers>=2.2.0
|
| 3 |
-
scikit-learn>=1.0.0
|
| 4 |
-
numpy>=1.21.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
requirements.txt
CHANGED
|
@@ -1,11 +1,8 @@
|
|
| 1 |
-
gradio>=4.
|
| 2 |
spaces[huggingface]>=0.28.0
|
| 3 |
transformers>=4.35.0
|
| 4 |
torch>=2.1.0
|
| 5 |
av
|
| 6 |
accelerate>=0.25.0
|
| 7 |
timm
|
| 8 |
-
gTTS>=2.5.0
|
| 9 |
-
sentence-transformers>=2.2.0
|
| 10 |
-
scikit-learn>=1.0.0
|
| 11 |
-
numpy>=1.21.0
|
|
|
|
| 1 |
+
gradio>=4.0.0
|
| 2 |
spaces[huggingface]>=0.28.0
|
| 3 |
transformers>=4.35.0
|
| 4 |
torch>=2.1.0
|
| 5 |
av
|
| 6 |
accelerate>=0.25.0
|
| 7 |
timm
|
| 8 |
+
gTTS>=2.5.0
|
|
|
|
|
|
|
|
|
simple_rag.py
DELETED
|
@@ -1,367 +0,0 @@
|
|
| 1 |
-
"""
|
| 2 |
-
نظام RAG بسيط لشركة NBTEL
|
| 3 |
-
يحول ملف PDF إلى قاعدة معرفة قابلة للبحث
|
| 4 |
-
"""
|
| 5 |
-
|
| 6 |
-
import os
|
| 7 |
-
import json
|
| 8 |
-
import re
|
| 9 |
-
from typing import List, Dict, Any
|
| 10 |
-
from sentence_transformers import SentenceTransformer
|
| 11 |
-
import numpy as np
|
| 12 |
-
from sklearn.metrics.pairwise import cosine_similarity
|
| 13 |
-
import pickle
|
| 14 |
-
from pathlib import Path
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
class SimpleRAG:
|
| 18 |
-
"""نظام RAG بسيط بدون مكتبات معقدة"""
|
| 19 |
-
|
| 20 |
-
def __init__(self):
|
| 21 |
-
"""تهيئة النظام"""
|
| 22 |
-
print("🔄 جاري تحميل نموذج التضمين...")
|
| 23 |
-
|
| 24 |
-
# استخدام نموذج صغير وسريع
|
| 25 |
-
self.model = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')
|
| 26 |
-
|
| 27 |
-
self.documents = []
|
| 28 |
-
self.embeddings = None
|
| 29 |
-
|
| 30 |
-
# مجلدات البيانات
|
| 31 |
-
os.makedirs("./data", exist_ok=True)
|
| 32 |
-
os.makedirs("./rag_index", exist_ok=True)
|
| 33 |
-
|
| 34 |
-
print("✅ تم تحميل النظام بنجاح")
|
| 35 |
-
|
| 36 |
-
def load_markdown_file(self, file_path: str) -> List[Dict[str, Any]]:
|
| 37 |
-
"""
|
| 38 |
-
تحميل ملف Markdown وتقسيمه إلى أقسام
|
| 39 |
-
|
| 40 |
-
Args:
|
| 41 |
-
file_path: مسار الملف
|
| 42 |
-
|
| 43 |
-
Returns:
|
| 44 |
-
قائمة الأقسام
|
| 45 |
-
"""
|
| 46 |
-
documents = []
|
| 47 |
-
|
| 48 |
-
try:
|
| 49 |
-
with open(file_path, 'r', encoding='utf-8') as f:
|
| 50 |
-
content = f.read()
|
| 51 |
-
|
| 52 |
-
print(f"📄 قراءة الملف، الحجم: {len(content)} حرف")
|
| 53 |
-
|
| 54 |
-
# تقسيم بسيط حسب العناوين
|
| 55 |
-
sections = re.split(r'\n(#{1,3}\s+.*?)\n', content)
|
| 56 |
-
|
| 57 |
-
current_title = "مقدمة"
|
| 58 |
-
current_content = ""
|
| 59 |
-
|
| 60 |
-
for i, section in enumerate(sections):
|
| 61 |
-
section = section.strip()
|
| 62 |
-
if not section:
|
| 63 |
-
continue
|
| 64 |
-
|
| 65 |
-
# إذا كان عنوان (يبدأ بـ #)
|
| 66 |
-
if section.startswith('#'):
|
| 67 |
-
# حفظ القسم السابق
|
| 68 |
-
if current_content.strip():
|
| 69 |
-
documents.append({
|
| 70 |
-
'title': current_title,
|
| 71 |
-
'content': current_content.strip(),
|
| 72 |
-
'source': 'nbtel_profile',
|
| 73 |
-
'section_type': 'main'
|
| 74 |
-
})
|
| 75 |
-
|
| 76 |
-
# بدء قسم جديد
|
| 77 |
-
current_title = section.replace('#', '').strip()
|
| 78 |
-
current_content = ""
|
| 79 |
-
else:
|
| 80 |
-
# إضافة المحتوى للقسم الحالي
|
| 81 |
-
current_content += section + "\n"
|
| 82 |
-
|
| 83 |
-
# إضافة القسم الأخير
|
| 84 |
-
if current_content.strip():
|
| 85 |
-
documents.append({
|
| 86 |
-
'title': current_title,
|
| 87 |
-
'content': current_content.strip(),
|
| 88 |
-
'source': 'nbtel_profile',
|
| 89 |
-
'section_type': 'main'
|
| 90 |
-
})
|
| 91 |
-
|
| 92 |
-
# تقسيم إضافي للأقسام الطويلة جداً
|
| 93 |
-
final_docs = []
|
| 94 |
-
for doc in documents:
|
| 95 |
-
if len(doc['content']) > 1500:
|
| 96 |
-
chunks = self._split_long_text(doc['content'], max_length=1200)
|
| 97 |
-
for i, chunk in enumerate(chunks):
|
| 98 |
-
if chunk.strip(): # تأكد من وجود محتوى
|
| 99 |
-
final_docs.append({
|
| 100 |
-
'title': f"{doc['title']} - جزء {i+1}",
|
| 101 |
-
'content': chunk,
|
| 102 |
-
'source': doc['source'],
|
| 103 |
-
'section_type': 'chunk'
|
| 104 |
-
})
|
| 105 |
-
else:
|
| 106 |
-
if doc['content'].strip(): # تأكد من وجود محتوى
|
| 107 |
-
final_docs.append(doc)
|
| 108 |
-
|
| 109 |
-
# إزالة المستندات الفارغة
|
| 110 |
-
final_docs = [doc for doc in final_docs if len(doc['content'].strip()) > 50]
|
| 111 |
-
|
| 112 |
-
print(f"✅ تم تحميل {len(final_docs)} قسم من الملف")
|
| 113 |
-
return final_docs
|
| 114 |
-
|
| 115 |
-
except Exception as e:
|
| 116 |
-
print(f"❌ خطأ في تحميل الملف: {str(e)}")
|
| 117 |
-
return []
|
| 118 |
-
|
| 119 |
-
def _split_long_text(self, text: str, max_length: int = 800) -> List[str]:
|
| 120 |
-
"""تقسيم النص الطويل إلى أجزاء"""
|
| 121 |
-
|
| 122 |
-
# تقسيم حسب الفقرات أولاً
|
| 123 |
-
paragraphs = text.split('\n\n')
|
| 124 |
-
chunks = []
|
| 125 |
-
current_chunk = ""
|
| 126 |
-
|
| 127 |
-
for para in paragraphs:
|
| 128 |
-
if len(current_chunk + para) < max_length:
|
| 129 |
-
current_chunk += para + "\n\n"
|
| 130 |
-
else:
|
| 131 |
-
if current_chunk.strip():
|
| 132 |
-
chunks.append(current_chunk.strip())
|
| 133 |
-
current_chunk = para + "\n\n"
|
| 134 |
-
|
| 135 |
-
if current_chunk.strip():
|
| 136 |
-
chunks.append(current_chunk.strip())
|
| 137 |
-
|
| 138 |
-
return chunks
|
| 139 |
-
|
| 140 |
-
def add_documents(self, documents: List[Dict[str, Any]]):
|
| 141 |
-
"""إضافة مستندات جديدة"""
|
| 142 |
-
|
| 143 |
-
print(f"🔄 جاري إضافة {len(documents)} مستند...")
|
| 144 |
-
|
| 145 |
-
for doc in documents:
|
| 146 |
-
# إضافة معرف فريد
|
| 147 |
-
doc['id'] = len(self.documents)
|
| 148 |
-
|
| 149 |
-
# تنظيف وتحسين المحتوى
|
| 150 |
-
content = doc['content']
|
| 151 |
-
content = re.sub(r'\s+', ' ', content) # إزالة المسافات الزائدة
|
| 152 |
-
content = content.strip()
|
| 153 |
-
|
| 154 |
-
doc['content'] = content
|
| 155 |
-
doc['content_length'] = len(content)
|
| 156 |
-
|
| 157 |
-
self.documents.append(doc)
|
| 158 |
-
|
| 159 |
-
print(f"✅ تم إضافة {len(documents)} مستند")
|
| 160 |
-
|
| 161 |
-
def build_index(self):
|
| 162 |
-
"""بناء فهرس البحث"""
|
| 163 |
-
|
| 164 |
-
if not self.documents:
|
| 165 |
-
print("⚠️ لا توجد مستندات")
|
| 166 |
-
return
|
| 167 |
-
|
| 168 |
-
print(f"🔄 جاري بناء فهرس لـ {len(self.documents)} مستند...")
|
| 169 |
-
|
| 170 |
-
# استخراج النصوص
|
| 171 |
-
texts = []
|
| 172 |
-
for doc in self.documents:
|
| 173 |
-
# دمج العنوان والمحتوى للبحث الأفضل
|
| 174 |
-
search_text = f"{doc['title']}\n{doc['content']}"
|
| 175 |
-
texts.append(search_text)
|
| 176 |
-
|
| 177 |
-
# حساب التضمينات
|
| 178 |
-
self.embeddings = self.model.encode(texts, show_progress_bar=True)
|
| 179 |
-
|
| 180 |
-
print(f"✅ تم بناء الفهرس - {len(self.documents)} مستند")
|
| 181 |
-
|
| 182 |
-
def search(self, query: str, top_k: int = 5) -> List[Dict[str, Any]]:
|
| 183 |
-
"""
|
| 184 |
-
البحث في المستندات
|
| 185 |
-
|
| 186 |
-
Args:
|
| 187 |
-
query: الاستعلام
|
| 188 |
-
top_k: عدد النتائج
|
| 189 |
-
|
| 190 |
-
Returns:
|
| 191 |
-
النتائج مرتبة حسب الصلة
|
| 192 |
-
"""
|
| 193 |
-
|
| 194 |
-
if self.embeddings is None:
|
| 195 |
-
print("⚠️ لم يتم بناء الفهرس")
|
| 196 |
-
return []
|
| 197 |
-
|
| 198 |
-
# تحويل الاستعلام إلى تضمين
|
| 199 |
-
query_embedding = self.model.encode([query])
|
| 200 |
-
|
| 201 |
-
# حساب التشابه
|
| 202 |
-
similarities = cosine_similarity(query_embedding, self.embeddings)[0]
|
| 203 |
-
|
| 204 |
-
# ترتيب النتائج
|
| 205 |
-
top_indices = np.argsort(similarities)[::-1][:top_k]
|
| 206 |
-
|
| 207 |
-
results = []
|
| 208 |
-
for i, idx in enumerate(top_indices):
|
| 209 |
-
if similarities[idx] > 0.1: # عتبة التشابه الدنيا
|
| 210 |
-
doc = self.documents[idx].copy()
|
| 211 |
-
doc['similarity_score'] = float(similarities[idx])
|
| 212 |
-
doc['rank'] = i + 1
|
| 213 |
-
results.append(doc)
|
| 214 |
-
|
| 215 |
-
return results
|
| 216 |
-
|
| 217 |
-
def get_context_for_query(self, query: str, max_results: int = 3) -> str:
|
| 218 |
-
"""
|
| 219 |
-
الحصول على السياق للاستعلام
|
| 220 |
-
|
| 221 |
-
Args:
|
| 222 |
-
query: الاستعلام
|
| 223 |
-
max_results: أقصى عدد نتائج
|
| 224 |
-
|
| 225 |
-
Returns:
|
| 226 |
-
النص المنسق للسياق
|
| 227 |
-
"""
|
| 228 |
-
|
| 229 |
-
results = self.search(query, top_k=max_results)
|
| 230 |
-
|
| 231 |
-
if not results:
|
| 232 |
-
return "لم أجد معلومات ذات صلة في قاعدة المعرفة."
|
| 233 |
-
|
| 234 |
-
context = "معلومات من قاعدة المعرفة:\n\n"
|
| 235 |
-
|
| 236 |
-
for result in results:
|
| 237 |
-
score = result['similarity_score']
|
| 238 |
-
title = result['title']
|
| 239 |
-
content = result['content']
|
| 240 |
-
|
| 241 |
-
# قطع النص إذا كان طويلاً جداً
|
| 242 |
-
if len(content) > 500:
|
| 243 |
-
content = content[:500] + "..."
|
| 244 |
-
|
| 245 |
-
context += f"📄 **{title}** (درجة الصلة: {score:.2f}):\n"
|
| 246 |
-
context += f"{content}\n\n"
|
| 247 |
-
|
| 248 |
-
return context
|
| 249 |
-
|
| 250 |
-
def save_index(self, path: str = "./rag_index"):
|
| 251 |
-
"""حفظ الفهرس"""
|
| 252 |
-
|
| 253 |
-
path = Path(path)
|
| 254 |
-
path.mkdir(exist_ok=True)
|
| 255 |
-
|
| 256 |
-
# حفظ المستندات
|
| 257 |
-
with open(path / "documents.pkl", "wb") as f:
|
| 258 |
-
pickle.dump(self.documents, f)
|
| 259 |
-
|
| 260 |
-
# حفظ التضمينات
|
| 261 |
-
if self.embeddings is not None:
|
| 262 |
-
np.save(path / "embeddings.npy", self.embeddings)
|
| 263 |
-
|
| 264 |
-
# حفظ معلومات النظام
|
| 265 |
-
info = {
|
| 266 |
-
"num_documents": len(self.documents),
|
| 267 |
-
"embedding_dim": self.embeddings.shape[1] if self.embeddings is not None else 0,
|
| 268 |
-
"model_name": self.model.get_sentence_embedding_dimension()
|
| 269 |
-
}
|
| 270 |
-
|
| 271 |
-
with open(path / "info.json", "w", encoding="utf-8") as f:
|
| 272 |
-
json.dump(info, f, ensure_ascii=False, indent=2)
|
| 273 |
-
|
| 274 |
-
print(f"✅ تم حفظ الفهرس في {path}")
|
| 275 |
-
|
| 276 |
-
def load_index(self, path: str = "./rag_index") -> bool:
|
| 277 |
-
"""تحميل فهرس محفوظ"""
|
| 278 |
-
|
| 279 |
-
path = Path(path)
|
| 280 |
-
|
| 281 |
-
if not path.exists():
|
| 282 |
-
print(f"⚠️ لم يتم العثور على فهرس في {path}")
|
| 283 |
-
return False
|
| 284 |
-
|
| 285 |
-
try:
|
| 286 |
-
# تحميل المستندات
|
| 287 |
-
with open(path / "documents.pkl", "rb") as f:
|
| 288 |
-
self.documents = pickle.load(f)
|
| 289 |
-
|
| 290 |
-
# تحميل التضمينات
|
| 291 |
-
embeddings_path = path / "embeddings.npy"
|
| 292 |
-
if embeddings_path.exists():
|
| 293 |
-
self.embeddings = np.load(embeddings_path)
|
| 294 |
-
|
| 295 |
-
print(f"✅ تم تحميل الفهرس - {len(self.documents)} مستند")
|
| 296 |
-
return True
|
| 297 |
-
|
| 298 |
-
except Exception as e:
|
| 299 |
-
print(f"❌ خطأ في تحميل الفهرس: {str(e)}")
|
| 300 |
-
return False
|
| 301 |
-
|
| 302 |
-
def get_stats(self) -> Dict[str, Any]:
|
| 303 |
-
"""إحصائيات النظام"""
|
| 304 |
-
|
| 305 |
-
if not self.documents:
|
| 306 |
-
return {"message": "لا توجد مستندات"}
|
| 307 |
-
|
| 308 |
-
total_chars = sum(doc['content_length'] for doc in self.documents)
|
| 309 |
-
avg_length = total_chars / len(self.documents)
|
| 310 |
-
|
| 311 |
-
return {
|
| 312 |
-
"total_documents": len(self.documents),
|
| 313 |
-
"total_characters": total_chars,
|
| 314 |
-
"average_document_length": round(avg_length, 1),
|
| 315 |
-
"index_built": self.embeddings is not None,
|
| 316 |
-
"embedding_dimension": self.embeddings.shape[1] if self.embeddings is not None else 0
|
| 317 |
-
}
|
| 318 |
-
|
| 319 |
-
|
| 320 |
-
def main():
|
| 321 |
-
"""الدالة الرئيسية لاختبار النظام"""
|
| 322 |
-
|
| 323 |
-
# إنشاء نظام RAG
|
| 324 |
-
rag = SimpleRAG()
|
| 325 |
-
|
| 326 |
-
# محاولة تحميل فهرس موجود
|
| 327 |
-
if not rag.load_index():
|
| 328 |
-
print("🔄 إنشاء فهرس جديد...")
|
| 329 |
-
|
| 330 |
-
# تحميل ملف الشركة
|
| 331 |
-
file_path = "./data/nbtel_company_profile.md"
|
| 332 |
-
if os.path.exists(file_path):
|
| 333 |
-
documents = rag.load_markdown_file(file_path)
|
| 334 |
-
rag.add_documents(documents)
|
| 335 |
-
rag.build_index()
|
| 336 |
-
rag.save_index()
|
| 337 |
-
else:
|
| 338 |
-
print(f"❌ لم يتم العثور على الملف: {file_path}")
|
| 339 |
-
return
|
| 340 |
-
|
| 341 |
-
# عرض الإحصائيات
|
| 342 |
-
stats = rag.get_stats()
|
| 343 |
-
print(f"\n📊 إحصائيات النظام:")
|
| 344 |
-
for key, value in stats.items():
|
| 345 |
-
print(f" {key}: {value}")
|
| 346 |
-
|
| 347 |
-
# اختبار البحث
|
| 348 |
-
print(f"\n🔍 اختبار البحث:")
|
| 349 |
-
|
| 350 |
-
test_queries = [
|
| 351 |
-
"ما هي خدمات الشركة؟",
|
| 352 |
-
"كيف أتواصل مع الدعم الفني؟",
|
| 353 |
-
"ما هي أسعار الباقات؟",
|
| 354 |
-
"مشكلة في الواي فاي",
|
| 355 |
-
"معلومات عن الشركة"
|
| 356 |
-
]
|
| 357 |
-
|
| 358 |
-
for query in test_queries:
|
| 359 |
-
print(f"\n❓ السؤال: {query}")
|
| 360 |
-
context = rag.get_context_for_query(query, max_results=2)
|
| 361 |
-
print(f"📋 السياق:")
|
| 362 |
-
print(context[:300] + "..." if len(context) > 300 else context)
|
| 363 |
-
print("-" * 50)
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
if __name__ == "__main__":
|
| 367 |
-
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test_rag.py
DELETED
|
@@ -1,126 +0,0 @@
|
|
| 1 |
-
"""
|
| 2 |
-
تطبيق بسيط لاختبار نظام RAG
|
| 3 |
-
"""
|
| 4 |
-
|
| 5 |
-
from simple_rag import SimpleRAG
|
| 6 |
-
import os
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
def interactive_search():
|
| 10 |
-
"""تطبيق تفاعلي للبحث"""
|
| 11 |
-
|
| 12 |
-
print("🤖 مرحباً بك في نظام RAG لشركة NBTEL")
|
| 13 |
-
print("=" * 50)
|
| 14 |
-
|
| 15 |
-
# تهيئة النظام
|
| 16 |
-
rag = SimpleRAG()
|
| 17 |
-
|
| 18 |
-
# تحميل البيانات
|
| 19 |
-
if not rag.load_index():
|
| 20 |
-
print("🔄 إنشاء فهرس جديد...")
|
| 21 |
-
|
| 22 |
-
file_path = "./data/nbtel_company_profile.md"
|
| 23 |
-
if os.path.exists(file_path):
|
| 24 |
-
documents = rag.load_markdown_file(file_path)
|
| 25 |
-
rag.add_documents(documents)
|
| 26 |
-
rag.build_index()
|
| 27 |
-
rag.save_index()
|
| 28 |
-
print("✅ تم إنشاء الفهرس بنجاح")
|
| 29 |
-
else:
|
| 30 |
-
print(f"❌ لم يتم العثور على ملف البيانات")
|
| 31 |
-
return
|
| 32 |
-
|
| 33 |
-
# عرض الإحصائيات
|
| 34 |
-
stats = rag.get_stats()
|
| 35 |
-
print(f"\n📊 الفهرس يحتوي على {stats['total_documents']} مستند")
|
| 36 |
-
|
| 37 |
-
print("\n💡 اكتب استفسارك أو 'exit' للخروج")
|
| 38 |
-
print("=" * 50)
|
| 39 |
-
|
| 40 |
-
while True:
|
| 41 |
-
try:
|
| 42 |
-
# الحصول على الاستعلام
|
| 43 |
-
query = input("\n🔍 استفسارك: ").strip()
|
| 44 |
-
|
| 45 |
-
if query.lower() in ['exit', 'خروج', 'quit']:
|
| 46 |
-
print("👋 شكراً لاستخدام النظام!")
|
| 47 |
-
break
|
| 48 |
-
|
| 49 |
-
if not query:
|
| 50 |
-
continue
|
| 51 |
-
|
| 52 |
-
# البحث
|
| 53 |
-
print("\n🔄 جاري البحث...")
|
| 54 |
-
context = rag.get_context_for_query(query, max_results=3)
|
| 55 |
-
|
| 56 |
-
print("\n📋 النتائج:")
|
| 57 |
-
print("-" * 30)
|
| 58 |
-
print(context)
|
| 59 |
-
print("-" * 30)
|
| 60 |
-
|
| 61 |
-
except KeyboardInterrupt:
|
| 62 |
-
print("\n👋 شكراً لاستخدام النظام!")
|
| 63 |
-
break
|
| 64 |
-
except Exception as e:
|
| 65 |
-
print(f"❌ حدث خطأ: {str(e)}")
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
def test_common_questions():
|
| 69 |
-
"""اختبار الأسئلة الشائعة"""
|
| 70 |
-
|
| 71 |
-
print("🧪 اختبار الأسئلة الشائعة")
|
| 72 |
-
print("=" * 50)
|
| 73 |
-
|
| 74 |
-
rag = SimpleRAG()
|
| 75 |
-
|
| 76 |
-
if not rag.load_index():
|
| 77 |
-
print("❌ لا يوجد فهرس محفوظ. قم بتشغيل النظام أولاً")
|
| 78 |
-
return
|
| 79 |
-
|
| 80 |
-
questions = [
|
| 81 |
-
"ما هي خدمات شركة NBTEL؟",
|
| 82 |
-
"كيف أتواصل مع الدعم الفني؟",
|
| 83 |
-
"ما هي أسعار باقات الإنترنت؟",
|
| 84 |
-
"عندي مشكلة الواي فاي ما يظهر",
|
| 85 |
-
"كيف أغير كلمة سر الراوتر؟",
|
| 86 |
-
"هل يمكن نقل الخدمة لعنوان جديد؟",
|
| 87 |
-
"وين مقر الشركة؟",
|
| 88 |
-
"شنو تاريخ الشركة؟",
|
| 89 |
-
"عندي انقطاعات بالإنترنت"
|
| 90 |
-
]
|
| 91 |
-
|
| 92 |
-
for i, question in enumerate(questions, 1):
|
| 93 |
-
print(f"\n❓ سؤال {i}: {question}")
|
| 94 |
-
context = rag.get_context_for_query(question, max_results=2)
|
| 95 |
-
|
| 96 |
-
# عرض أول 200 حرف من النتيجة
|
| 97 |
-
preview = context[:200] + "..." if len(context) > 200 else context
|
| 98 |
-
print(f"📋 النتيجة: {preview}")
|
| 99 |
-
print("-" * 40)
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
def main():
|
| 103 |
-
"""القائمة الرئيسية"""
|
| 104 |
-
|
| 105 |
-
while True:
|
| 106 |
-
print("\n🤖 نظام RAG لشركة NBTEL")
|
| 107 |
-
print("=" * 30)
|
| 108 |
-
print("1. البحث التفاعلي")
|
| 109 |
-
print("2. اختبار الأسئلة الشائعة")
|
| 110 |
-
print("3. الخروج")
|
| 111 |
-
|
| 112 |
-
choice = input("\nاختر خيار (1-3): ").strip()
|
| 113 |
-
|
| 114 |
-
if choice == "1":
|
| 115 |
-
interactive_search()
|
| 116 |
-
elif choice == "2":
|
| 117 |
-
test_common_questions()
|
| 118 |
-
elif choice == "3":
|
| 119 |
-
print("👋 وداعاً!")
|
| 120 |
-
break
|
| 121 |
-
else:
|
| 122 |
-
print("❌ خيار غير صحيح")
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
if __name__ == "__main__":
|
| 126 |
-
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test_tts.py
DELETED
|
@@ -1,40 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python3
|
| 2 |
-
|
| 3 |
-
from gtts import gTTS
|
| 4 |
-
import io
|
| 5 |
-
import base64
|
| 6 |
-
import tempfile
|
| 7 |
-
|
| 8 |
-
def generate_speech(text: str, lang: str = 'ar') -> tuple[str, str]:
|
| 9 |
-
"""Generate speech from text using Google TTS and return audio file path and base64 data."""
|
| 10 |
-
try:
|
| 11 |
-
# Create TTS object
|
| 12 |
-
tts = gTTS(text=text, lang=lang, slow=False)
|
| 13 |
-
|
| 14 |
-
# Save to temporary file
|
| 15 |
-
temp_audio_file = tempfile.NamedTemporaryFile(delete=False, suffix='.mp3')
|
| 16 |
-
temp_audio_file.close()
|
| 17 |
-
|
| 18 |
-
tts.save(temp_audio_file.name)
|
| 19 |
-
|
| 20 |
-
# Also create base64 version for direct playback
|
| 21 |
-
audio_buffer = io.BytesIO()
|
| 22 |
-
tts.write_to_fp(audio_buffer)
|
| 23 |
-
audio_buffer.seek(0)
|
| 24 |
-
audio_base64 = base64.b64encode(audio_buffer.read()).decode('utf-8')
|
| 25 |
-
|
| 26 |
-
return temp_audio_file.name, f"data:audio/mp3;base64,{audio_base64}"
|
| 27 |
-
except Exception as e:
|
| 28 |
-
print(f"TTS Error: {e}")
|
| 29 |
-
return None, None
|
| 30 |
-
|
| 31 |
-
if __name__ == "__main__":
|
| 32 |
-
# Test the TTS function
|
| 33 |
-
text = "مرحبا، هذا اختبار للصوت"
|
| 34 |
-
file_path, audio_data = generate_speech(text)
|
| 35 |
-
if file_path and audio_data:
|
| 36 |
-
print(f"Audio file created: {file_path}")
|
| 37 |
-
print(f"Audio data length: {len(audio_data)}")
|
| 38 |
-
print("TTS test successful!")
|
| 39 |
-
else:
|
| 40 |
-
print("TTS test failed!")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|