anaspro commited on
Commit
dbcf08f
·
1 Parent(s): 3619ce6

🤖 تحديث شامل: إضافة نظام RAG للدعم الفني

Browse files

✨ المميزات الجديدة:
- نظام RAG متكامل للبحث في قاعدة المعرفة
- مساعد دعم فني ذكي بالعراقي
- قاعدة معرفة شاملة عن شركة NBTEL
- واجهة محسنة ومخصصة للدعم الفني
- أمثلة عراقية للاستخدام

🔧 التحسينات:
- prompt محسن للدعم الفني
- أسلوب كلام عراقي طبيعي
- بحث ذكي في المعلومات
- ردود مفصلة وعملية

📁 الملفات الجديدة:
- simple_rag.py: نظام RAG
- data/nbtel_company_profile.md: قاعدة المعرفة
- test_rag.py: اختبارات النظام

Files changed (8) hide show
  1. README.md +66 -29
  2. app.py +201 -19
  3. data/nbtel_company_profile.md +296 -0
  4. examples/image1.jpg +0 -0
  5. rag_requirements.txt +4 -0
  6. requirements.txt +4 -1
  7. simple_rag.py +358 -0
  8. test_rag.py +126 -0
README.md CHANGED
@@ -1,53 +1,90 @@
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" لإعادة التشغيل
 
1
  ---
2
+ title: مساعد NBTEL الذكي - الدعم الفني
3
  emoji: 🤖
4
  colorFrom: blue
5
+ colorTo: purple
6
  sdk: gradio
7
+ sdk_version: 4.44.0
8
  app_file: app.py
9
  pinned: false
10
  models:
11
+ - anaspro/Shako-4B-it-v5
12
  tags:
13
  - arabic
14
  - iraq
15
  - iraqi-dialect
16
+ - technical-support
17
  - chatbot
18
  - multimodal
19
+ - rag
20
+ - customer-service
 
21
  ---
22
 
23
+ # 🤖 مساعد NBTEL الذكي - الدعم الفني
24
 
25
+ مساعد ذكي للدعم الفني مدعوم بتقنية RAG ونموذج شكو العراقي المتطور.
 
 
 
 
 
 
26
 
27
+ ## 🚀 المميزات
28
 
29
+ - 🇮🇶 **متخصص باللهجة العراقية**: يتحدث بطريقة طبيعية وودية
30
+ - � **مدعوم بـ RAG**: يستخدم قاعدة معرفة شاملة عن الشركة وخدماتها
31
+ - 🔧 **دعم فني متكامل**: يحل المشاكل التقنية خطوة بخطوة
32
+ - 🖼️ **متعدد الوسائط**: يدعم الصور والفيديوهات والملفات الصوتية
33
+ - � **قاعدة معرفة ذكية**: معلومات شاملة عن خدمات NBTEL
34
+ - 💬 **تفاعلي وسريع**: ردود فورية ومفيدة
35
 
36
+ ## �️ الخدمات المقدمة
 
 
 
 
 
37
 
38
+ ### خدمات الإنترنت
39
+ - خدمة الإنترنت اللاسلكية WiFi
40
+ - خدمة الكيبل الضوئي FTTX/FTTH
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" لإعادة التشغيل
app.py CHANGED
@@ -11,6 +11,9 @@ import torch
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,6 +33,35 @@ TARGET_FPS = int(os.getenv("TARGET_FPS", "3"))
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,6 +74,83 @@ def get_file_type(path: str) -> str:
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,6 +270,19 @@ def generate(message: dict, history: list[dict], system_prompt: str = "", max_ne
161
  yield ""
162
  return
163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  messages = []
165
  if system_prompt:
166
  messages.append({"role": "system", "content": [{"type": "text", "text": system_prompt}]})
@@ -190,13 +312,12 @@ def generate(message: dict, history: list[dict], system_prompt: str = "", max_ne
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,17 +330,33 @@ def generate(message: dict, history: list[dict], system_prompt: str = "", max_ne
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,21 +365,66 @@ demo = gr.ChatInterface(
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
  )
 
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
  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
+ documents = rag_system.load_markdown_file(nbtel_file)
49
+ rag_system.add_documents(documents)
50
+ rag_system.build_index()
51
+ rag_system.save_index()
52
+ print("✅ تم إنشاء فهرس RAG بنجاح")
53
+ else:
54
+ print(f"⚠️ لم يتم العثور على ملف البيانات: {nbtel_file}")
55
+
56
+ print(f"✅ نظام RAG جاهز - {len(rag_system.documents)} مستند")
57
+ RAG_ENABLED = True
58
+
59
+ except Exception as e:
60
+ print(f"❌ خطأ في تهيئة نظام RAG: {str(e)}")
61
+ print("⚠️ سيتم تشغيل النظام بدون RAG")
62
+ rag_system = None
63
+ RAG_ENABLED = False
64
+
65
 
66
  def get_file_type(path: str) -> str:
67
  if path.endswith(IMAGE_FILE_TYPES):
 
74
  raise ValueError(error_message)
75
 
76
 
77
+ def search_knowledge_base(query: str) -> str:
78
+ """البحث في قاعدة المعرفة باستخدام RAG"""
79
+
80
+ if not RAG_ENABLED or rag_system is None:
81
+ return ""
82
+
83
+ try:
84
+ # البحث في قاعدة المعرفة
85
+ context = rag_system.get_context_for_query(query, max_results=3)
86
+
87
+ if context and "لم أجد معلومات" not in context:
88
+ return f"\n\n📚 معلومات من قاعدة المعرفة:\n{context}"
89
+ else:
90
+ return ""
91
+
92
+ except Exception as e:
93
+ print(f"خطأ في البحث في قاعدة المعرفة: {str(e)}")
94
+ return ""
95
+
96
+
97
+ def create_technical_support_prompt(user_message: str, knowledge_context: str = "") -> str:
98
+ """إنشاء prompt محسن للدعم الفني"""
99
+
100
+ base_prompt = """أنت مساعد دعم فني ذكي لشركة NBTEL العراقية.
101
+
102
+ هويتك ومهامك:
103
+ - اسمك: مساعد NBTEL الذكي
104
+ - تتحدث باللهجة العراقية الودية والمرحة
105
+ - خبير في خدمات الإنترنت والاتصالات والدعم الفني
106
+ - تساعد العملاء في حل مشاكلهم التقنية
107
+ - تقدم معلومات عن خدمات وأسعار الشركة
108
+
109
+ قواعد التعامل:
110
+ 1. رحب بالعميل بطريقة عراقية ودية (أهلاً وسهلاً، مرحبا بيك، الخ)
111
+ 2. استخدم المعلومات من قاعدة المعرفة إن وجدت
112
+ 3. اطرح أسئلة توضيحية لفهم المشكلة بدقة
113
+ 4. قدم حلول عملية خطوة بخطوة
114
+ 5. استخدم أمثلة عراقية مفهومة
115
+ 6. كن صبور ومساعد مع العملاء
116
+ 7. إذا ما تعرف الجواب، اعترف واطلب التواصل مع الدعم المباشر
117
+
118
+ أسلوب الكلام:
119
+ - استخدم "احنا" بدلاً من "نحن"
120
+ - استخدم "شلونك" بدلاً من "كيف حالك"
121
+ - استخدم "شنو" بدلاً من "ماذا"
122
+ - استخدم "وين" بدلاً من "أين"
123
+ - استخدم "اكو" بدلاً من "يوجد"
124
+ - اجعل الكلام طبيعي ومرح
125
+
126
+ معلومات الشركة الأساسية:
127
+ - شركة NBTEL عراقية متخصصة بخدمات الإنترنت والاتصالات
128
+ - نخدم محافظات نينوى، كركوك، وصلاح الدين
129
+ - نقدم خدمات WiFi و FTTX (الكيبل الضوئي)
130
+ - مقرنا الرئيسي في الموصل
131
+ - رقم الدعم الفني: 6337
132
+ - واتساب: 0773 633 7777
133
+
134
+ """
135
+
136
+ if knowledge_context:
137
+ enhanced_prompt = f"""{base_prompt}
138
+
139
+ {knowledge_context}
140
+
141
+ الاستفسار: {user_message}
142
+
143
+ جاوب بطريقة ودية وعملية، واستخدم المعلومات اللي فوق إذا كانت مفيدة:"""
144
+ else:
145
+ enhanced_prompt = f"""{base_prompt}
146
+
147
+ الاستفسار: {user_message}
148
+
149
+ جاوب بطريقة ودية وعملية:"""
150
+
151
+ return enhanced_prompt
152
+
153
+
154
  def count_files_in_new_message(paths: list[str]) -> tuple[int, int]:
155
  video_count = 0
156
  non_video_count = 0
 
270
  yield ""
271
  return
272
 
273
+ # استخراج النص من الرسالة للبحث في قاعدة المعرفة
274
+ user_text = message.get("text", "")
275
+
276
+ # البحث في قاعدة المعرفة
277
+ knowledge_context = search_knowledge_base(user_text) if user_text else ""
278
+
279
+ # إنشاء prompt محسن للدعم الفني
280
+ if user_text:
281
+ enhanced_prompt = create_technical_support_prompt(user_text, knowledge_context)
282
+ # استبدال النص الأصلي بالـ prompt المحسن
283
+ message = message.copy()
284
+ message["text"] = enhanced_prompt
285
+
286
  messages = []
287
  if system_prompt:
288
  messages.append({"role": "system", "content": [{"type": "text", "text": system_prompt}]})
 
312
  streamer=streamer,
313
  max_new_tokens=max_new_tokens,
314
  do_sample=True,
315
+ temperature=0.7, # قللنا الحرارة للردود أكثر منطقية
316
+ top_k=50, # قللنا للحصول على ردود أكثر تركيز
317
+ top_p=0.9, # قللنا للحصول على ردود أكثر دقة
318
  min_p=0.0,
319
+ repetition_penalty=1.1, # زدنا شوي لتجنب التكرار
320
  disable_compile=True,
 
321
  )
322
  t = Thread(target=model.generate, kwargs=generate_kwargs)
323
  t.start()
 
330
 
331
  # Examples for the chat interface (with additional inputs: system_prompt, max_new_tokens)
332
  examples = [
333
+ ["أهلاً، شنو خدمات شركتكم؟", "", 800],
334
+ ["عندي مشكلة بالواي فاي، ما يظهر عندي", "", 600],
335
+ ["شگد أسعار باقات الإنترنت عندكم؟", "", 700],
336
+ ["الإنترنت عندي ضعيف، شنو الحل؟", "", 600],
337
+ ["كيف أقدر أغير كلمة سر الراوتر؟", "", 500],
338
+ ["وين مقر الشركة ومعلومات التواصل؟", "", 400]
339
  ]
340
 
341
+ # System prompt محسن للدعم الفني العراقي
342
+ system_prompt = """أنت مساعد دعم فني ذكي لشركة NBTEL العراقية.
343
+
344
+ تعليمات مهمة:
345
+ - تحدث باللهجة العراقية البغدادية الودية والطبيعية
346
+ - كن مساعد ومرح في التعامل مع العملاء
347
+ - ركز على حل المشاكل التقنية وتقديم المساعدة العملية
348
+ - استخدم المعلومات من قاعدة المعرفة عندما تكون متوفرة
349
+ - إذا ما تعرف جواب محدد، اعترف واطلب التواصل مع الدعم المباشر
350
+
351
+ أسلوب الكلام العراقي:
352
+ - استخدم "شلونك" بدلاً من "كيف حالك"
353
+ - استخدم "شنو" بدلاً من "ماذا"
354
+ - استخدم "وين" بدلاً من "أين"
355
+ - استخدم "احنا" بدلاً من "نحن"
356
+ - استخدم "اكو" بدلاً من "يوجد"
357
+ - استخدم "شگد" بدلاً من "كم"
358
+
359
+ كن ودود ومساعد دائماً!"""
360
  # Create the chat interface
361
  demo = gr.ChatInterface(
362
  fn=generate,
 
365
  file_types=list(IMAGE_FILE_TYPES + VIDEO_FILE_TYPES + AUDIO_FILE_TYPES),
366
  file_count="multiple",
367
  autofocus=True,
368
+ placeholder="اكتب استفسارك هنا... مثل: عندي مشكلة بالإنترنت، أو شنو خدماتكم؟"
369
  ),
370
  multimodal=True,
371
  additional_inputs=[
372
+ gr.Textbox(
373
+ label="System Prompt (اختياري)",
374
+ value=system_prompt,
375
+ lines=3,
376
+ visible=False # مخفي للمستخدم العادي
377
+ ),
378
+ gr.Slider(
379
+ label="Max New Tokens",
380
+ minimum=100,
381
+ maximum=2048,
382
+ step=50,
383
+ value=1024,
384
+ visible=False # مخفي للمستخدم العادي
385
+ ),
386
  ],
387
+ title="🤖 مساعد NBTEL الذكي - الدعم الفني",
388
+ description=f"""
389
+ 🌟 **أهلاً وسهلاً بيك في مساعد NBTEL الذكي!**
390
+
391
+ احنا هنا نساعدك في:
392
+ • 🔧 حل مشاكل الإنترنت والواي فاي
393
+ • 📋 معلومات عن خدماتنا وأسعارنا
394
+ • 📞 التواصل والدعم الفني
395
+ • 🛠️ إرشادات تقنية مفصلة
396
+
397
+ {"✅ **نظام المعرفة متصل** - عندي معلومات شاملة عن الشركة والخدمات" if RAG_ENABLED else "⚠️ **نظام المعرفة غير متصل** - راح أساعدك بالمعلومات العامة"}
398
+
399
+ **للدعم المباشر**: 📞 6337 | 📱 واتساب: 0773 633 7777
400
+ """,
401
  examples=examples,
402
+ stop_btn=True,
403
  css="""
404
  .gradio-container, .chatbot, .chatbot * {
405
  direction: rtl !important;
406
  text-align: right !important;
407
  unicode-bidi: plaintext !important;
408
+ font-family: 'Tajawal', 'Cairo', 'Segoe UI', sans-serif;
409
+ }
410
+ .chatbot .message {
411
+ padding: 15px !important;
412
+ margin: 10px !important;
413
+ border-radius: 15px !important;
414
+ }
415
+ .chatbot .message.user {
416
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
417
+ color: white !important;
418
+ }
419
+ .chatbot .message.bot {
420
+ background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%) !important;
421
+ color: white !important;
422
+ }
423
+ .title {
424
+ color: #2c3e50 !important;
425
+ font-size: 2em !important;
426
+ font-weight: bold !important;
427
+ text-align: center !important;
428
  }
429
  """
430
  )
data/nbtel_company_profile.md ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ تابعنا على منصات التواصل الاجتماعي للاطلاع على العروض
examples/image1.jpg DELETED
Binary file (47.4 kB)
 
rag_requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ # المكتبات الأساسية لنظام RAG البسيط
2
+ sentence-transformers>=2.2.0
3
+ scikit-learn>=1.0.0
4
+ numpy>=1.21.0
requirements.txt CHANGED
@@ -5,4 +5,7 @@ torch>=2.1.0
5
  av
6
  accelerate>=0.25.0
7
  timm
8
- gTTS>=2.5.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
simple_rag.py ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ # تقسيم حسب العناوين
53
+ sections = re.split(r'\n(#{1,6})\s+', content)
54
+
55
+ current_section = ""
56
+ current_title = ""
57
+
58
+ for i, part in enumerate(sections):
59
+ if part.startswith('#'):
60
+ # هذا عنوان
61
+ if current_section and current_title:
62
+ documents.append({
63
+ 'title': current_title,
64
+ 'content': current_section.strip(),
65
+ 'source': 'nbtel_profile',
66
+ 'section_type': 'main'
67
+ })
68
+ current_title = ""
69
+ current_section = ""
70
+ elif part.strip().startswith('#'):
71
+ # عنوان فرعي
72
+ current_title = part.strip()
73
+ else:
74
+ # محتوى
75
+ if i + 1 < len(sections) and not sections[i + 1].startswith('#'):
76
+ current_title = part.strip().split('\n')[0] if part.strip() else current_title
77
+ current_section = part
78
+
79
+ # إضافة القسم الأخير
80
+ if current_section and current_title:
81
+ documents.append({
82
+ 'title': current_title,
83
+ 'content': current_section.strip(),
84
+ 'source': 'nbtel_profile',
85
+ 'section_type': 'main'
86
+ })
87
+
88
+ # تقسيم إضافي للأقسام الطويلة
89
+ final_docs = []
90
+ for doc in documents:
91
+ if len(doc['content']) > 1000:
92
+ chunks = self._split_long_text(doc['content'])
93
+ for i, chunk in enumerate(chunks):
94
+ final_docs.append({
95
+ 'title': f"{doc['title']} - جزء {i+1}",
96
+ 'content': chunk,
97
+ 'source': doc['source'],
98
+ 'section_type': 'chunk'
99
+ })
100
+ else:
101
+ final_docs.append(doc)
102
+
103
+ print(f"✅ تم تحميل {len(final_docs)} قسم من الملف")
104
+ return final_docs
105
+
106
+ except Exception as e:
107
+ print(f"❌ خطأ في تحميل الملف: {str(e)}")
108
+ return []
109
+
110
+ def _split_long_text(self, text: str, max_length: int = 800) -> List[str]:
111
+ """تقسيم النص الطويل إلى أجزاء"""
112
+
113
+ # تقسيم حسب الفقرات أولاً
114
+ paragraphs = text.split('\n\n')
115
+ chunks = []
116
+ current_chunk = ""
117
+
118
+ for para in paragraphs:
119
+ if len(current_chunk + para) < max_length:
120
+ current_chunk += para + "\n\n"
121
+ else:
122
+ if current_chunk.strip():
123
+ chunks.append(current_chunk.strip())
124
+ current_chunk = para + "\n\n"
125
+
126
+ if current_chunk.strip():
127
+ chunks.append(current_chunk.strip())
128
+
129
+ return chunks
130
+
131
+ def add_documents(self, documents: List[Dict[str, Any]]):
132
+ """إضافة مستندات جديدة"""
133
+
134
+ print(f"🔄 جاري إضافة {len(documents)} مستند...")
135
+
136
+ for doc in documents:
137
+ # إضافة معرف ��ريد
138
+ doc['id'] = len(self.documents)
139
+
140
+ # تنظيف وتحسين المحتوى
141
+ content = doc['content']
142
+ content = re.sub(r'\s+', ' ', content) # إزالة المسافات الزائدة
143
+ content = content.strip()
144
+
145
+ doc['content'] = content
146
+ doc['content_length'] = len(content)
147
+
148
+ self.documents.append(doc)
149
+
150
+ print(f"✅ تم إضافة {len(documents)} مستند")
151
+
152
+ def build_index(self):
153
+ """بناء فهرس البحث"""
154
+
155
+ if not self.documents:
156
+ print("⚠️ لا توجد مستندات")
157
+ return
158
+
159
+ print(f"🔄 جاري بناء فهرس لـ {len(self.documents)} مستند...")
160
+
161
+ # استخراج النصوص
162
+ texts = []
163
+ for doc in self.documents:
164
+ # دمج العنوان والمحتوى للبحث الأفضل
165
+ search_text = f"{doc['title']}\n{doc['content']}"
166
+ texts.append(search_text)
167
+
168
+ # حساب التضمينات
169
+ self.embeddings = self.model.encode(texts, show_progress_bar=True)
170
+
171
+ print(f"✅ تم بناء الفهرس - {len(self.documents)} مستند")
172
+
173
+ def search(self, query: str, top_k: int = 5) -> List[Dict[str, Any]]:
174
+ """
175
+ البحث في المستندات
176
+
177
+ Args:
178
+ query: الاستعلام
179
+ top_k: عدد النتائج
180
+
181
+ Returns:
182
+ النتائج مرتبة حسب الصلة
183
+ """
184
+
185
+ if self.embeddings is None:
186
+ print("⚠️ لم يتم بناء الفهرس")
187
+ return []
188
+
189
+ # تحويل الاستعلام إلى تضمين
190
+ query_embedding = self.model.encode([query])
191
+
192
+ # حساب التشابه
193
+ similarities = cosine_similarity(query_embedding, self.embeddings)[0]
194
+
195
+ # ترتيب النتائج
196
+ top_indices = np.argsort(similarities)[::-1][:top_k]
197
+
198
+ results = []
199
+ for i, idx in enumerate(top_indices):
200
+ if similarities[idx] > 0.1: # عتبة التشابه الدنيا
201
+ doc = self.documents[idx].copy()
202
+ doc['similarity_score'] = float(similarities[idx])
203
+ doc['rank'] = i + 1
204
+ results.append(doc)
205
+
206
+ return results
207
+
208
+ def get_context_for_query(self, query: str, max_results: int = 3) -> str:
209
+ """
210
+ الحصول على السياق للاستعلام
211
+
212
+ Args:
213
+ query: الاستعلام
214
+ max_results: أقصى عدد نتائج
215
+
216
+ Returns:
217
+ النص المنسق للسياق
218
+ """
219
+
220
+ results = self.search(query, top_k=max_results)
221
+
222
+ if not results:
223
+ return "لم أجد معلومات ذات صلة في قاعدة المعرفة."
224
+
225
+ context = "معلومات من قاعدة المعرفة:\n\n"
226
+
227
+ for result in results:
228
+ score = result['similarity_score']
229
+ title = result['title']
230
+ content = result['content']
231
+
232
+ # قطع النص إذا كان طويلاً جداً
233
+ if len(content) > 500:
234
+ content = content[:500] + "..."
235
+
236
+ context += f"📄 **{title}** (درجة الصلة: {score:.2f}):\n"
237
+ context += f"{content}\n\n"
238
+
239
+ return context
240
+
241
+ def save_index(self, path: str = "./rag_index"):
242
+ """حفظ الفهرس"""
243
+
244
+ path = Path(path)
245
+ path.mkdir(exist_ok=True)
246
+
247
+ # حفظ المستندات
248
+ with open(path / "documents.pkl", "wb") as f:
249
+ pickle.dump(self.documents, f)
250
+
251
+ # حفظ التضمينات
252
+ if self.embeddings is not None:
253
+ np.save(path / "embeddings.npy", self.embeddings)
254
+
255
+ # حفظ معلومات النظام
256
+ info = {
257
+ "num_documents": len(self.documents),
258
+ "embedding_dim": self.embeddings.shape[1] if self.embeddings is not None else 0,
259
+ "model_name": self.model.get_sentence_embedding_dimension()
260
+ }
261
+
262
+ with open(path / "info.json", "w", encoding="utf-8") as f:
263
+ json.dump(info, f, ensure_ascii=False, indent=2)
264
+
265
+ print(f"✅ تم حفظ الفهرس في {path}")
266
+
267
+ def load_index(self, path: str = "./rag_index") -> bool:
268
+ """تحميل فهرس محفوظ"""
269
+
270
+ path = Path(path)
271
+
272
+ if not path.exists():
273
+ print(f"⚠️ لم يتم العثور على فهرس في {path}")
274
+ return False
275
+
276
+ try:
277
+ # تحميل المستندات
278
+ with open(path / "documents.pkl", "rb") as f:
279
+ self.documents = pickle.load(f)
280
+
281
+ # تحميل التضمينات
282
+ embeddings_path = path / "embeddings.npy"
283
+ if embeddings_path.exists():
284
+ self.embeddings = np.load(embeddings_path)
285
+
286
+ print(f"✅ تم تحميل الفهرس - {len(self.documents)} مستند")
287
+ return True
288
+
289
+ except Exception as e:
290
+ print(f"❌ خطأ في تحميل الفهرس: {str(e)}")
291
+ return False
292
+
293
+ def get_stats(self) -> Dict[str, Any]:
294
+ """إحصائيات النظام"""
295
+
296
+ if not self.documents:
297
+ return {"message": "لا توجد مستندات"}
298
+
299
+ total_chars = sum(doc['content_length'] for doc in self.documents)
300
+ avg_length = total_chars / len(self.documents)
301
+
302
+ return {
303
+ "total_documents": len(self.documents),
304
+ "total_characters": total_chars,
305
+ "average_document_length": round(avg_length, 1),
306
+ "index_built": self.embeddings is not None,
307
+ "embedding_dimension": self.embeddings.shape[1] if self.embeddings is not None else 0
308
+ }
309
+
310
+
311
+ def main():
312
+ """الدالة الرئيسية لاختبار النظام"""
313
+
314
+ # إنشاء نظام RAG
315
+ rag = SimpleRAG()
316
+
317
+ # محاولة تحميل فهرس موجود
318
+ if not rag.load_index():
319
+ print("🔄 إنشاء فهرس جديد...")
320
+
321
+ # تحميل ملف الشركة
322
+ file_path = "./data/nbtel_company_profile.md"
323
+ if os.path.exists(file_path):
324
+ documents = rag.load_markdown_file(file_path)
325
+ rag.add_documents(documents)
326
+ rag.build_index()
327
+ rag.save_index()
328
+ else:
329
+ print(f"❌ لم يتم العثور على الملف: {file_path}")
330
+ return
331
+
332
+ # عرض الإحصائيات
333
+ stats = rag.get_stats()
334
+ print(f"\n📊 إحصائيات النظام:")
335
+ for key, value in stats.items():
336
+ print(f" {key}: {value}")
337
+
338
+ # اختبار البحث
339
+ print(f"\n🔍 اختبار البحث:")
340
+
341
+ test_queries = [
342
+ "ما هي خدمات الشركة؟",
343
+ "كيف أتواصل مع الدعم الفني؟",
344
+ "ما هي أسعار الباقات؟",
345
+ "مشكلة في الواي فاي",
346
+ "معلومات عن الشركة"
347
+ ]
348
+
349
+ for query in test_queries:
350
+ print(f"\n❓ السؤال: {query}")
351
+ context = rag.get_context_for_query(query, max_results=2)
352
+ print(f"📋 السياق:")
353
+ print(context[:300] + "..." if len(context) > 300 else context)
354
+ print("-" * 50)
355
+
356
+
357
+ if __name__ == "__main__":
358
+ main()
test_rag.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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()