kawkabelaloom commited on
Commit
20aed75
·
verified ·
1 Parent(s): 5a8c946

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +147 -169
app.py CHANGED
@@ -1,5 +1,5 @@
1
  """
2
- 🤖 نظام RAG المبسط لـ HuggingFace Spaces - بدون pickle5
3
  """
4
 
5
  import os
@@ -11,16 +11,31 @@ from pypdf import PdfReader
11
  from sentence_transformers import SentenceTransformer
12
  import streamlit as st
13
 
14
- # تحميل موارد NLTK مرة واحدة
15
- @st.cache_resource
16
- def load_nltk():
17
- try:
18
- nltk.download('punkt', quiet=True)
19
- nltk.download('punkt_tab', quiet=True)
20
- except:
21
- pass
22
- return True
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  class FlowRAGSystem:
25
  def __init__(self):
26
  self.model = None
@@ -31,6 +46,13 @@ class FlowRAGSystem:
31
  def initialize(self):
32
  """تهيئة النظام"""
33
  try:
 
 
 
 
 
 
 
34
  self.model = SentenceTransformer(
35
  "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
36
  )
@@ -53,9 +75,6 @@ class FlowRAGSystem:
53
  reader = PdfReader(pdf_path)
54
  pages_data = []
55
 
56
- progress_bar = st.progress(0)
57
- total_pages = len(reader.pages)
58
-
59
  for i, page in enumerate(reader.pages):
60
  text = page.extract_text()
61
  if text and text.strip():
@@ -63,12 +82,6 @@ class FlowRAGSystem:
63
  'page': i + 1,
64
  'text': text.strip()
65
  })
66
-
67
- # تحديث شريط التقدم
68
- if total_pages > 0:
69
- progress_bar.progress((i + 1) / total_pages)
70
-
71
- progress_bar.empty()
72
 
73
  if not pages_data:
74
  st.error("❌ لم يتم العثور على نص في الملف")
@@ -81,9 +94,9 @@ class FlowRAGSystem:
81
  for page in pages_data:
82
  words = page['text'].split()
83
 
84
- # تقسيم إلى أجزاء 250 كلمة مع تداخل 50
85
- chunk_size = 250
86
- overlap = 50
87
 
88
  start = 0
89
  while start < len(words):
@@ -157,80 +170,9 @@ class FlowRAGSystem:
157
  st.error(f"❌ خطأ في البحث: {e}")
158
  return []
159
 
160
- # واجهة Streamlit
161
- def main():
162
- # تحميل NLTK
163
- load_nltk()
164
-
165
- # إعداد الصفحة
166
- st.set_page_config(
167
- page_title="نظام RAG للمستندات",
168
- page_icon="🤖",
169
- layout="wide",
170
- initial_sidebar_state="expanded"
171
- )
172
-
173
- # CSS مخصص
174
- st.markdown("""
175
- <style>
176
- .main-header {
177
- text-align: center;
178
- padding: 2rem;
179
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
180
- color: white;
181
- border-radius: 15px;
182
- margin-bottom: 2rem;
183
- }
184
- .result-card {
185
- background: #f8f9fa;
186
- border-radius: 10px;
187
- padding: 1.5rem;
188
- margin: 1rem 0;
189
- border-left: 5px solid #4CAF50;
190
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
191
- }
192
- .similarity-high { color: #28a745; font-weight: bold; }
193
- .similarity-medium { color: #ffc107; font-weight: bold; }
194
- .similarity-low { color: #dc3545; font-weight: bold; }
195
-
196
- .stButton>button {
197
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
198
- color: white;
199
- border: none;
200
- padding: 0.75rem 1.5rem;
201
- border-radius: 8px;
202
- font-weight: bold;
203
- transition: all 0.3s;
204
- }
205
- .stButton>button:hover {
206
- transform: translateY(-2px);
207
- box-shadow: 0 4px 8px rgba(0,0,0,0.2);
208
- }
209
- </style>
210
- """, unsafe_allow_html=True)
211
-
212
- # العنوان
213
- st.markdown("""
214
- <div class="main-header">
215
- <h1>🤖 نظام RAG الذكي للمستندات</h1>
216
- <p>بحث دلالي متقدم في ملفات PDF - يدعم العربية والإنجليزية</p>
217
- </div>
218
- """, unsafe_allow_html=True)
219
-
220
- # تهيئة النظام في session state
221
- if 'rag_system' not in st.session_state:
222
- st.session_state.rag_system = FlowRAGSystem()
223
- if st.session_state.rag_system.initialize():
224
- st.sidebar.success("✅ النظام جاهز للاستخدام")
225
- else:
226
- st.sidebar.error("❌ خطأ في تهيئة النظام")
227
-
228
- if 'current_file' not in st.session_state:
229
- st.session_state.current_file = None
230
-
231
- rag_system = st.session_state.rag_system
232
-
233
- # الشريط الجانبي
234
  with st.sidebar:
235
  st.header("📁 رفع المستند")
236
 
@@ -242,10 +184,10 @@ def main():
242
 
243
  if uploaded_file is not None:
244
  if st.button("🚀 معالجة المستند", type="primary", use_container_width=True):
245
- with st.spinner("جاري معالجة المستند..."):
246
- if rag_system.process_pdf(uploaded_file.getvalue(), uploaded_file.name):
247
- st.session_state.current_file = uploaded_file.name
248
- st.rerun()
249
 
250
  st.divider()
251
 
@@ -267,88 +209,92 @@ def main():
267
 
268
  for question in example_questions:
269
  if st.button(question, use_container_width=True):
270
- st.session_state.last_question = question
 
271
  st.rerun()
272
 
273
  st.divider()
274
 
275
  # معلومات النظام
 
276
  if rag_system.chunks:
277
  st.header("📊 معلومات النظام")
278
  st.metric("الأجزاء النصية", len(rag_system.chunks))
279
  if rag_system.index:
280
  st.metric("المتجهات", rag_system.index.ntotal)
281
 
282
- # المنطقة الرئيسية
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
283
  col1, col2 = st.columns([3, 1])
284
 
285
  with col1:
286
  st.header("💬 اسأل عن المستند")
287
 
288
  # عرض اسم الملف الحالي
289
- if st.session_state.current_file:
290
- st.info(f"📄 الملف الحالي: **{st.session_state.current_file}**")
291
 
292
- # حقل السؤال
293
- default_question = st.session_state.get('last_question', '')
294
  question = st.text_area(
295
  "اكتب سؤالك هنا",
296
  value=default_question,
297
  height=120,
298
- placeholder="مثال: ما هي حالة التدفق؟ أو What is flow state?\nيمكنك استخدام العربية أو الإنجليزية..."
 
299
  )
300
 
301
  # زر البحث
302
- col_btn1, col_btn2 = st.columns(2)
303
- with col_btn1:
304
- if st.button("🔍 ابحث في المستند", type="primary", use_container_width=True):
305
- if not question:
306
- st.warning("⚠️ يرجى إدخال سؤال")
307
- elif rag_system.index is None:
308
- st.error(" يرجى معالجة مستند أولاً (من الشريط الجانبي)")
309
- else:
310
- with st.spinner("جاري البحث في المستند..."):
311
- results = rag_system.search(question, top_k=top_k)
 
312
 
313
- if results:
314
- st.success(f"✅ تم العثور على {len(results)} نتيجة")
 
 
 
 
315
 
316
- for i, result in enumerate(results):
317
- # تحديد لون التشابه
318
- similarity_score = float(result['similarity'].replace('%', '')) / 100
319
- if similarity_score >= 0.5:
320
- sim_class = "similarity-high"
321
- elif similarity_score >= 0.3:
322
- sim_class = "similarity-medium"
323
- else:
324
- sim_class = "similarity-low"
325
-
326
- # عرض البطاقة
327
- with st.container():
328
- st.markdown(f"""
329
- <div class="result-card">
330
- <h4>🏆 النتيجة #{i+1}</h4>
331
- <p>
332
- <span class="{sim_class}">التشابه: {result['similarity']}</span> |
333
- 📖 الصفحة: {result['page']} |
334
- 🔢 الكلمات: {result['words']}
335
- </p>
336
- <hr>
337
- <p>{result['text'][:400]}...</p>
338
- </div>
339
- """, unsafe_allow_html=True)
340
-
341
- # زر لعرض النص الكامل
342
- with st.expander("📖 عرض النص الكامل"):
343
- st.write(result['text'])
344
- else:
345
- st.error("❌ لم أجد نتائج ذات صلة في المستند")
346
-
347
- with col_btn2:
348
- if st.button("🧹 مسح النتائج", use_container_width=True):
349
- if 'last_question' in st.session_state:
350
- del st.session_state['last_question']
351
- st.rerun()
352
 
353
  with col2:
354
  st.header("🎯 نصائح البحث")
@@ -365,9 +311,6 @@ def main():
365
 
366
  🔸 **اطلب التفاصيل**
367
  "ما هي العناصر الثمانية للتدفق؟"
368
-
369
- 🔸 **استخدم أمثلة**
370
- "اذكر أمثلة على أنشطة تدفق"
371
  """)
372
 
373
  st.divider()
@@ -377,26 +320,61 @@ def main():
377
  **التقنيات الم��تخدمة:**
378
 
379
  • 🤖 **Sentence Transformers**
380
- نماذج embedding متعددة اللغات
381
-
382
  • ⚡ **FAISS**
383
- بحث سريع في المتجهات
384
-
385
  • 📄 **PyPDF**
386
- معالجة ملفات PDF
387
-
388
- • 🌐 **Streamlit**
389
- واجهة مستخدم تفاعلية
390
  """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
391
 
392
  # تذييل الصفحة
393
  st.divider()
394
  st.markdown("""
395
- <div style="text-align: center; color: #666; padding: 2rem;">
396
  <p>🤖 نظام RAG للمستندات | إصدار HuggingFace Spaces</p>
397
- <p>تقنية: FAISS + Sentence Transformers + Streamlit | يدعم العربية والإنجليزية</p>
398
  </div>
399
  """, unsafe_allow_html=True)
400
 
 
401
  if __name__ == "__main__":
402
- main()
 
 
 
 
 
 
 
 
 
 
1
  """
2
+ 🤖 نظام RAG لـ HuggingFace - نسخة معدلة لتعمل مع طريقة HuggingFace
3
  """
4
 
5
  import os
 
11
  from sentence_transformers import SentenceTransformer
12
  import streamlit as st
13
 
14
+ # ==================== تهيئة النظام في حالة global ====================
15
+ # بدلاً من الاعتماد على session_state فقط
 
 
 
 
 
 
 
16
 
17
+ _rag_system = None
18
+ _current_file = None
19
+
20
+ def get_rag_system():
21
+ """الحصول على أو إنشاء مثيل النظام"""
22
+ global _rag_system
23
+ if _rag_system is None:
24
+ _rag_system = FlowRAGSystem()
25
+ _rag_system.initialize()
26
+ return _rag_system
27
+
28
+ def get_current_file():
29
+ """الحصول على الملف الحالي"""
30
+ global _current_file
31
+ return _current_file
32
+
33
+ def set_current_file(filename):
34
+ """تعيين الملف الحالي"""
35
+ global _current_file
36
+ _current_file = filename
37
+
38
+ # ==================== فئة النظام ====================
39
  class FlowRAGSystem:
40
  def __init__(self):
41
  self.model = None
 
46
  def initialize(self):
47
  """تهيئة النظام"""
48
  try:
49
+ # تحميل موارد NLTK
50
+ try:
51
+ nltk.download('punkt', quiet=True)
52
+ nltk.download('punkt_tab', quiet=True)
53
+ except:
54
+ pass
55
+
56
  self.model = SentenceTransformer(
57
  "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
58
  )
 
75
  reader = PdfReader(pdf_path)
76
  pages_data = []
77
 
 
 
 
78
  for i, page in enumerate(reader.pages):
79
  text = page.extract_text()
80
  if text and text.strip():
 
82
  'page': i + 1,
83
  'text': text.strip()
84
  })
 
 
 
 
 
 
85
 
86
  if not pages_data:
87
  st.error("❌ لم يتم العثور على نص في الملف")
 
94
  for page in pages_data:
95
  words = page['text'].split()
96
 
97
+ # تقسيم إلى أجزاء 200 كلمة مع تداخل 40
98
+ chunk_size = 200
99
+ overlap = 40
100
 
101
  start = 0
102
  while start < len(words):
 
170
  st.error(f"❌ خطأ في البحث: {e}")
171
  return []
172
 
173
+ # ==================== الوظائف المساعدة ====================
174
+ def create_sidebar():
175
+ """إنشاء الشريط الجانبي"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  with st.sidebar:
177
  st.header("📁 رفع المستند")
178
 
 
184
 
185
  if uploaded_file is not None:
186
  if st.button("🚀 معالجة المستند", type="primary", use_container_width=True):
187
+ rag_system = get_rag_system()
188
+ if rag_system.process_pdf(uploaded_file.getvalue(), uploaded_file.name):
189
+ set_current_file(uploaded_file.name)
190
+ st.rerun()
191
 
192
  st.divider()
193
 
 
209
 
210
  for question in example_questions:
211
  if st.button(question, use_container_width=True):
212
+ # تخزين السؤال في query params بدلاً من session state
213
+ st.query_params["question"] = question
214
  st.rerun()
215
 
216
  st.divider()
217
 
218
  # معلومات النظام
219
+ rag_system = get_rag_system()
220
  if rag_system.chunks:
221
  st.header("📊 معلومات النظام")
222
  st.metric("الأجزاء النصية", len(rag_system.chunks))
223
  if rag_system.index:
224
  st.metric("المتجهات", rag_system.index.ntotal)
225
 
226
+ return top_k
227
+
228
+ def create_main_content(top_k):
229
+ """إنشاء المحتوى الرئيسي"""
230
+ rag_system = get_rag_system()
231
+ current_file = get_current_file()
232
+
233
+ # العنوان
234
+ st.markdown("""
235
+ <div style="text-align: center; padding: 2rem; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
236
+ color: white; border-radius: 15px; margin-bottom: 2rem;">
237
+ <h1>🤖 نظام RAG الذكي للمستندات</h1>
238
+ <p>بحث دلالي متقدم في ملفات PDF - يدعم العربية والإنجليزية</p>
239
+ </div>
240
+ """, unsafe_allow_html=True)
241
+
242
  col1, col2 = st.columns([3, 1])
243
 
244
  with col1:
245
  st.header("💬 اسأل عن المستند")
246
 
247
  # عرض اسم الملف الحالي
248
+ if current_file:
249
+ st.info(f"📄 الملف الحالي: **{current_file}**")
250
 
251
+ # الحصول على السؤال من query params أو حقل الإدخال
252
+ default_question = st.query_params.get("question", "")
253
  question = st.text_area(
254
  "اكتب سؤالك هنا",
255
  value=default_question,
256
  height=120,
257
+ placeholder="مثال: ما هي حالة التدفق؟ أو What is flow state?\nيمكنك استخدام العربية أو الإنجليزية...",
258
+ key="question_input"
259
  )
260
 
261
  # زر البحث
262
+ if st.button("🔍 ابحث في المستند", type="primary", use_container_width=True):
263
+ if not question:
264
+ st.warning("⚠️ يرجى إدخال سؤال")
265
+ elif rag_system.index is None:
266
+ st.error(" يرجى معالجة مستند أولاً (من الشريط الجانبي)")
267
+ else:
268
+ with st.spinner("جاري البحث في المستند..."):
269
+ results = rag_system.search(question, top_k=top_k)
270
+
271
+ if results:
272
+ st.success(f"✅ تم العثور على {len(results)} نتيجة")
273
 
274
+ for i, result in enumerate(results):
275
+ # تحديد لون التشابه
276
+ similarity_score = float(result['similarity'].replace('%', '')) / 100
277
+ sim_class = "similarity-high" if similarity_score >= 0.5 else \
278
+ "similarity-medium" if similarity_score >= 0.3 else \
279
+ "similarity-low"
280
 
281
+ # عرض البطاقة
282
+ st.markdown(f"""
283
+ <div style="background: #f8f9fa; border-radius: 10px; padding: 1.5rem;
284
+ margin: 1rem 0; border-left: 5px solid #4CAF50; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
285
+ <h4>🏆 النتيجة #{i+1}</h4>
286
+ <p>
287
+ <span style="color: {'#28a745' if similarity_score >= 0.5 else '#ffc107' if similarity_score >= 0.3 else '#dc3545'};
288
+ font-weight: bold;">التشابه: {result['similarity']}</span> |
289
+ 📖 الصفحة: {result['page']} |
290
+ 🔢 الكلمات: {result['words']}
291
+ </p>
292
+ <hr>
293
+ <p>{result['text'][:400]}...</p>
294
+ </div>
295
+ """, unsafe_allow_html=True)
296
+ else:
297
+ st.error(" لم أجد نتائج ذات صلة في المستند")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
298
 
299
  with col2:
300
  st.header("🎯 نصائح البحث")
 
311
 
312
  🔸 **اطلب التفاصيل**
313
  "ما هي العناصر الثمانية للتدفق؟"
 
 
 
314
  """)
315
 
316
  st.divider()
 
320
  **التقنيات الم��تخدمة:**
321
 
322
  • 🤖 **Sentence Transformers**
 
 
323
  • ⚡ **FAISS**
 
 
324
  • 📄 **PyPDF**
325
+ 🌐 **Streamlit**
 
 
 
326
  """)
327
+
328
+ # ==================== التطبيق الرئيسي ====================
329
+ def main():
330
+ """الدالة الرئيسية للتطبيق"""
331
+ # إعداد الصفحة
332
+ st.set_page_config(
333
+ page_title="نظام RAG للمستندات",
334
+ page_icon="🤖",
335
+ layout="wide",
336
+ initial_sidebar_state="expanded"
337
+ )
338
+
339
+ # CSS مخصص
340
+ st.markdown("""
341
+ <style>
342
+ .stButton>button {
343
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
344
+ color: white;
345
+ border: none;
346
+ padding: 0.75rem 1.5rem;
347
+ border-radius: 8px;
348
+ font-weight: bold;
349
+ }
350
+ .stButton>button:hover {
351
+ box-shadow: 0 4px 8px rgba(0,0,0,0.2);
352
+ }
353
+ </style>
354
+ """, unsafe_allow_html=True)
355
+
356
+ # إنشاء الواجهة
357
+ top_k = create_sidebar()
358
+ create_main_content(top_k)
359
 
360
  # تذييل الصفحة
361
  st.divider()
362
  st.markdown("""
363
+ <div style="text-align: center; color: #666; padding: 1rem;">
364
  <p>🤖 نظام RAG للمستندات | إصدار HuggingFace Spaces</p>
365
+ <p>تقنية: FAISS + Sentence Transformers | يدعم العربية والإنجليزية</p>
366
  </div>
367
  """, unsafe_allow_html=True)
368
 
369
+ # ==================== نقطة الدخول للتشغيل ====================
370
  if __name__ == "__main__":
371
+ # هذا يحل مشكلة HuggingFace مع طريقة التشغيل
372
+ import sys
373
+
374
+ # تحقق إذا كان يعمل في HuggingFace
375
+ if "huggingface" in sys.argv[0] or "spaces" in sys.argv[0]:
376
+ # تشغيل التطبيق مباشرة
377
+ main()
378
+ else:
379
+ # للتشغيل المحلي
380
+ main()