EGYADMIN commited on
Commit
849c31b
·
verified ·
1 Parent(s): 072e37a

Update modules/ai_assistant/ai_app.py

Browse files
Files changed (1) hide show
  1. modules/ai_assistant/ai_app.py +288 -1361
modules/ai_assistant/ai_app.py CHANGED
@@ -1,1361 +1,288 @@
1
- # -*- coding: utf-8 -*-
2
- """
3
- وحدة مساعد الذكاء الاصطناعي
4
- """
5
-
6
- import streamlit as st
7
- import pandas as pd
8
- import numpy as np
9
- import matplotlib.pyplot as plt
10
- import plotly.express as px
11
- import plotly.graph_objects as go
12
- import seaborn as sns
13
- from datetime import datetime
14
- import time
15
- import os
16
- import sys
17
- import json
18
- import requests
19
- from pathlib import Path
20
- import io
21
- import base64
22
- import re
23
- from PIL import Image
24
- import PyPDF2
25
- import docx
26
- import anthropic
27
- import tempfile
28
-
29
- # إضافة المسار للوصول إلى الوحدات الأخرى
30
- current_dir = os.path.dirname(os.path.abspath(__file__))
31
- parent_dir = os.path.dirname(os.path.dirname(current_dir))
32
- if parent_dir not in sys.path:
33
- sys.path.append(parent_dir)
34
-
35
- class AIAssistantApp:
36
- """تطبيق مساعد الذكاء الاصطناعي"""
37
-
38
- def __init__(self):
39
- """تهيئة تطبيق مساعد الذكاء الاصطناعي"""
40
- self.uploaded_files = {}
41
- self.analysis_results = {}
42
-
43
- # تهيئة مفاتيح API لنماذج هجين فيس
44
- # تحميل المفاتيح من متغيرات البيئة أو من الإعدادات
45
- if 'ai_api_key' not in st.session_state:
46
- # محاولة الحصول على المفتاح من متغيرات البيئة أولاً
47
- ai_key = os.environ.get('AI_API_KEY', '')
48
- # إذا لم يكن موجودًا، حاول الحصول عليه من أسرار هجين فيس
49
- if not ai_key and os.path.exists('/home/user/.huggingface/token'):
50
- with open('/home/user/.huggingface/token', 'r') as f:
51
- ai_key = f.read().strip()
52
- # إذا لم يكن موجودًا، استخدم المفتاح المقدم في وحدة المعرفة
53
- if not ai_key:
54
- ai_key = ""
55
- st.session_state.ai_api_key = ai_key
56
-
57
- if 'anthropic_api_key' not in st.session_state:
58
- # محاولة الحصول على المفتاح من متغيرات البيئة أولاً
59
- anthropic_key = os.environ.get('ANTHROPIC_API_KEY', '')
60
- # إذا لم يكن موجودًا، حاول الحصول عليه من أسرار هجين فيس
61
- if not anthropic_key:
62
- # استخدم نفس المفتاح لـ anthropic مؤقتًا
63
- anthropic_key = st.session_state.ai_api_key
64
- st.session_state.anthropic_api_key = anthropic_key
65
-
66
- # تهيئة محادثة الذكاء الاصطناعي
67
- if 'messages' not in st.session_state:
68
- st.session_state.messages = []
69
-
70
- if 'selected_model' not in st.session_state:
71
- st.session_state.selected_model = "anthropic"
72
-
73
- def run(self):
74
- """تشغيل تطبيق مساعد الذكاء الاصطناعي"""
75
- # عرض عنوان التطبيق
76
- st.title("مساعد الذكاء الاصطناعي")
77
-
78
- # إنشاء تبويبات التطبيق
79
- tabs = st.tabs([
80
- "المحادثة",
81
- "تحليل المستندات",
82
- "تحليل العقود",
83
- "تقدير التكاليف",
84
- "تحليل المخاطر",
85
- "الإعدادات"
86
- ])
87
-
88
- # عرض محتوى كل تبويب
89
- with tabs[0]:
90
- self._render_chat_tab()
91
-
92
- with tabs[1]:
93
- self._render_document_analysis_tab()
94
-
95
- with tabs[2]:
96
- self._render_contract_analysis_tab()
97
-
98
- with tabs[3]:
99
- self._render_cost_estimation_tab()
100
-
101
- with tabs[4]:
102
- self._render_risk_analysis_tab()
103
-
104
- with tabs[5]:
105
- self._render_settings_tab()
106
-
107
- def _render_chat_tab(self):
108
- """عرض تبويب المحادثة مع الذكاء الاصطناعي"""
109
- st.markdown("### المحادثة مع الذكاء الاصطناعي")
110
-
111
- # اختيار نموذج الذكاء الاصطناعي
112
- selected_model = st.selectbox(
113
- "اختر نموذج الذكاء الاصطناعي:",
114
- ["anthropic", "ai"],
115
- index=0 if st.session_state.selected_model == "anthropic" else 1
116
- )
117
-
118
- # تحديث النموذج المختار إذا تغير
119
- if selected_model != st.session_state.selected_model:
120
- st.session_state.selected_model = selected_model
121
- st.rerun() # تم تعديل هذا من st.experimental_rerun()
122
-
123
- # التحقق من وجود مفتاح API للنموذج المختار
124
- api_key_available = False
125
- if selected_model == "anthropic" and st.session_state.anthropic_api_key:
126
- api_key_available = True
127
- elif selected_model == "ai" and st.session_state.ai_api_key:
128
- api_key_available = True
129
-
130
- # عرض رسائل المحادثة
131
- for message in st.session_state.messages:
132
- with st.chat_message(message["role"]):
133
- st.markdown(message["content"])
134
-
135
- # إذا لم يكن مفتاح API متاحًا، عرض رسالة خطأ
136
- if not api_key_available:
137
- st.error(f"لم يتم تكوين مفتاح API لنموذج {selected_model}. يرجى تكوين المفتاح في الإعدادات.")
138
- else:
139
- # مربع إدخال الرسالة
140
- if prompt := st.chat_input("اكتب رسالتك هنا:"):
141
- # إضافة رسالة المستخدم إلى المحادثة
142
- st.session_state.messages.append({"role": "user", "content": prompt})
143
-
144
- # عرض رسالة المستخدم
145
- with st.chat_message("user"):
146
- st.markdown(prompt)
147
-
148
- # عرض مؤشر التحميل أثناء معالجة الرسالة
149
- with st.chat_message("assistant"):
150
- message_placeholder = st.empty()
151
- message_placeholder.markdown("جاري التفكير...")
152
-
153
- try:
154
- # الحصول على رد من النموذج المختار
155
- if selected_model == "anthropic":
156
- response = self._get_anthropic_response(prompt)
157
- else:
158
- response = self._get_ai_response(prompt)
159
-
160
- # عرض الرد
161
- message_placeholder.markdown(response)
162
-
163
- # إضافة رد المساعد إلى المحادثة
164
- st.session_state.messages.append({"role": "assistant", "content": response})
165
- except Exception as e:
166
- message_placeholder.markdown(f"حدث خطأ: {str(e)}")
167
-
168
- # زر لمسح المحادثة
169
- if st.button("مسح المحادثة"):
170
- st.session_state.messages = []
171
- st.rerun() # تم تعديل هذا من st.experimental_rerun()
172
-
173
- def _render_document_analysis_tab(self):
174
- """عرض تبويب تحليل المستندات"""
175
- st.markdown("### تحليل المستندات")
176
-
177
- st.markdown("""
178
- يمكنك استخدام هذه الأداة لتحليل المستندات والتقارير باستخدام الذكاء الاصطناعي.
179
- الأداة تدعم تحليل الملفات التالية:
180
- - ملفات PDF
181
- - ملفات Word
182
- - ملفات النصوص TXT
183
- """)
184
-
185
- # إنشاء تبويبات فرعية
186
- doc_tabs = st.tabs([
187
- "تحميل المستندات",
188
- "استخراج النص",
189
- "تحليل المحتوى",
190
- "الملخص والتوصيات"
191
- ])
192
-
193
- # تبويب تحميل المستندات
194
- with doc_tabs[0]:
195
- st.markdown("#### تحميل المستندات")
196
-
197
- uploaded_file = st.file_uploader(
198
- "اختر ملفًا للتحليل (PDF, DOCX, TXT)",
199
- type=["pdf", "docx", "txt"],
200
- key="document_file_uploader"
201
- )
202
-
203
- if uploaded_file is not None:
204
- # حفظ الملف المرفوع
205
- file_details = {
206
- "filename": uploaded_file.name,
207
- "filetype": uploaded_file.type,
208
- "filesize": uploaded_file.size
209
- }
210
-
211
- st.write("### تفاصيل الملف")
212
- st.write(f"اسم الملف: {file_details['filename']}")
213
- st.write(f"نوع الملف: {file_details['filetype']}")
214
- st.write(f"حجم الملف: {file_details['filesize']} بايت")
215
-
216
- # حفظ الملف في الذاكرة المؤقتة
217
- self.uploaded_files["document"] = uploaded_file
218
-
219
- st.success(f"تم تحميل الملف {uploaded_file.name} بنجاح!")
220
-
221
- # تبويب استخراج النص
222
- with doc_tabs[1]:
223
- st.markdown("#### استخراج النص")
224
-
225
- if "document" not in self.uploaded_files:
226
- st.info("الرجاء تحميل مستند أولاً من تبويب 'تحميل المستندات'")
227
- else:
228
- if st.button("استخراج النص من المستند"):
229
- with st.spinner("��اري استخراج النص..."):
230
- # استخراج النص من الملف
231
- extracted_text = self._extract_text_from_file(self.uploaded_files["document"])
232
-
233
- # حفظ النص المستخرج
234
- self.analysis_results["extracted_text"] = extracted_text
235
-
236
- # عرض النص المستخرج
237
- st.markdown("### النص المستخرج")
238
- st.text_area("النص:", value=extracted_text, height=400, disabled=True)
239
-
240
- st.success("تم استخراج النص بنجاح!")
241
-
242
- # إذا كان النص قد تم استخراجه بالفعل، عرضه
243
- if "extracted_text" in self.analysis_results:
244
- st.markdown("### النص المستخرج")
245
- st.text_area("النص:", value=self.analysis_results["extracted_text"], height=400, disabled=True)
246
-
247
- # تبويب تحليل المحتوى
248
- with doc_tabs[2]:
249
- st.markdown("#### تحليل المحتوى")
250
-
251
- if "extracted_text" not in self.analysis_results:
252
- st.info("الرجاء استخراج النص أولاً من تبويب 'استخراج النص'")
253
- else:
254
- if st.button("تحليل المحتوى"):
255
- with st.spinner("جاري تحليل المحتوى..."):
256
- # تحليل المحتوى باستخدام الذكاء الاصطناعي
257
- analysis_prompt = f"""
258
- قم بتحليل النص التالي وتقديم:
259
- 1. الموضوعات الرئيسية
260
- 2. الكلمات المفتاحية
261
- 3. الأفكار الرئيسية
262
- 4. أي معلومات مهمة أخرى
263
-
264
- النص:
265
- {self.analysis_results["extracted_text"][:4000]}
266
- """
267
-
268
- # الحصول على التحليل من النموذج المختار
269
- if st.session_state.selected_model == "anthropic":
270
- analysis_result = self._get_anthropic_response(analysis_prompt)
271
- else:
272
- analysis_result = self._get_ai_response(analysis_prompt)
273
-
274
- # حفظ نتيجة التحليل
275
- self.analysis_results["content_analysis"] = analysis_result
276
-
277
- # عرض نتيجة التحليل
278
- st.markdown("### نتيجة التحليل")
279
- st.markdown(analysis_result)
280
-
281
- st.success("تم تحليل المحتوى بنجاح!")
282
-
283
- # إذا كان التحليل قد تم بالفعل، عرضه
284
- if "content_analysis" in self.analysis_results:
285
- st.markdown("### نتيجة التحليل")
286
- st.markdown(self.analysis_results["content_analysis"])
287
-
288
- # تبويب الملخص والتوصيات
289
- with doc_tabs[3]:
290
- st.markdown("#### الملخص والتوصيات")
291
-
292
- if "content_analysis" not in self.analysis_results:
293
- st.info("الرجاء تحليل المحتوى أولاً من تبويب 'تحليل المحتوى'")
294
- else:
295
- if st.button("إنشاء ملخص وتوصيات"):
296
- with st.spinner("جاري إنشاء الملخص والتوصيات..."):
297
- # إنشاء ملخص وتوصيات باستخدام الذكاء الاصطناعي
298
- summary_prompt = f"""
299
- بناءً على التحليل التالي، قم بإنشاء:
300
- 1. ملخص موجز (لا يزيد عن 300 كلمة)
301
- 2. توصيات عملية (3-5 توصيات)
302
-
303
- التحليل:
304
- {self.analysis_results["content_analysis"]}
305
- """
306
-
307
- # الحصول على الملخص والتوصيات من النموذج المختار
308
- if st.session_state.selected_model == "anthropic":
309
- summary_result = self._get_anthropic_response(summary_prompt)
310
- else:
311
- summary_result = self._get_ai_response(summary_prompt)
312
-
313
- # حفظ الملخص والتوصيات
314
- self.analysis_results["summary_recommendations"] = summary_result
315
-
316
- # عرض الملخص والتوصيات
317
- st.markdown("### الملخص والتوصيات")
318
- st.markdown(summary_result)
319
-
320
- st.success("تم إنشاء الملخص والتوصيات بنجاح!")
321
-
322
- # إذا كان الملخص والتوصيات قد تم إنشاؤهما بالفعل، عرضهما
323
- if "summary_recommendations" in self.analysis_results:
324
- st.markdown("### الملخص والتوصيات")
325
- st.markdown(self.analysis_results["summary_recommendations"])
326
-
327
- # زر لتصدير التقرير
328
- report_content = f"""
329
- # تقرير تحليل المستند
330
-
331
- ## معلومات الملف
332
- - اسم الملف: {self.uploaded_files["document"].name}
333
- - نوع الملف: {self.uploaded_files["document"].type}
334
- - حجم الملف: {self.uploaded_files["document"].size} بايت
335
-
336
- ## تحليل المحتوى
337
- {self.analysis_results["content_analysis"]}
338
-
339
- ## الملخص والتوصيات
340
- {self.analysis_results["summary_recommendations"]}
341
-
342
- ## تم إنشاء هذا التقرير بواسطة مساعد الذكاء الاصطناعي
343
- تاريخ الإنشاء: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
344
- """
345
-
346
- st.download_button(
347
- label="تصدير التقرير (PDF)",
348
- data=report_content.encode('utf-8'),
349
- file_name=f"تقرير_تحليل_المستند_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf",
350
- mime="application/pdf",
351
- key="export_document_report_pdf"
352
- )
353
-
354
- def _render_contract_analysis_tab(self):
355
- """عرض تبويب تحليل العقود"""
356
- st.markdown("### تحليل العقود")
357
-
358
- st.markdown("""
359
- يمكنك استخدام هذه الأداة لتحليل العقود واستخراج البنود المهمة باستخدام الذكاء الاصطناعي.
360
- الأداة تدعم تحليل الملفات التالية:
361
- - ملفات PDF
362
- - ملفات Word
363
- - ملفات النصوص TXT
364
- """)
365
-
366
- # إنشاء تبويبات فرعية
367
- contract_tabs = st.tabs([
368
- "تحميل العقد",
369
- "استخراج البنود",
370
- "تحليل المخاطر",
371
- "التقرير النهائي"
372
- ])
373
-
374
- # تبويب تحميل العقد
375
- with contract_tabs[0]:
376
- st.markdown("#### تحميل العقد")
377
-
378
- uploaded_file = st.file_uploader(
379
- "اختر ملف العقد للتحليل (PDF, DOCX, TXT)",
380
- type=["pdf", "docx", "txt"],
381
- key="contract_file_uploader"
382
- )
383
-
384
- if uploaded_file is not None:
385
- # حفظ الملف المرفوع
386
- file_details = {
387
- "filename": uploaded_file.name,
388
- "filetype": uploaded_file.type,
389
- "filesize": uploaded_file.size
390
- }
391
-
392
- st.write("### تفاصيل الملف")
393
- st.write(f"اسم الملف: {file_details['filename']}")
394
- st.write(f"نوع الملف: {file_details['filetype']}")
395
- st.write(f"حجم الملف: {file_details['filesize']} بايت")
396
-
397
- # حفظ الملف في الذاكرة المؤقتة
398
- self.uploaded_files["contract"] = uploaded_file
399
-
400
- st.success(f"تم تحميل الملف {uploaded_file.name} بنجاح!")
401
-
402
- # تبويب استخراج البنود
403
- with contract_tabs[1]:
404
- st.markdown("#### استخراج البنود")
405
-
406
- if "contract" not in self.uploaded_files:
407
- st.info("الرجاء تحميل ملف العقد أولاً من تبويب 'تحميل العقد'")
408
- else:
409
- if st.button("استخراج البنود من العقد"):
410
- with st.spinner("جاري استخراج البنود..."):
411
- # استخراج النص من الم��ف
412
- extracted_text = self._extract_text_from_file(self.uploaded_files["contract"])
413
-
414
- # حفظ النص المستخرج
415
- self.analysis_results["contract_text"] = extracted_text
416
-
417
- # استخراج البنود باستخدام الذكاء الاصطناعي
418
- clauses_prompt = f"""
419
- قم بتحليل نص العقد التالي واستخراج البنود المهمة التالية:
420
- 1. الأطراف المتعاقدة
421
- 2. موضوع العقد
422
- 3. مدة العقد
423
- 4. قيمة العقد
424
- 5. شروط الدفع
425
- 6. الالتزامات والمسؤوليات
426
- 7. شروط الإنهاء
427
- 8. تسوية النزاعات
428
- 9. القانون الحاكم
429
- 10. أي بنود أخرى مهمة
430
-
431
- نص العقد:
432
- {extracted_text[:4000]}
433
- """
434
-
435
- # الحصول على البنود من النموذج المختار
436
- if st.session_state.selected_model == "anthropic":
437
- clauses_result = self._get_anthropic_response(clauses_prompt)
438
- else:
439
- clauses_result = self._get_ai_response(clauses_prompt)
440
-
441
- # حفظ البنود المستخرجة
442
- self.analysis_results["contract_clauses"] = clauses_result
443
-
444
- # عرض البنود المستخرجة
445
- st.markdown("### البنود المستخرجة")
446
- st.markdown(clauses_result)
447
-
448
- st.success("تم استخراج البنود بنجاح!")
449
-
450
- # إذا كانت البنود قد تم استخراجها بالفعل، عرضها
451
- if "contract_clauses" in self.analysis_results:
452
- st.markdown("### البنود المستخرجة")
453
- st.markdown(self.analysis_results["contract_clauses"])
454
-
455
- # تبويب تحليل المخاطر
456
- with contract_tabs[2]:
457
- st.markdown("#### تحليل المخاطر")
458
-
459
- if "contract_clauses" not in self.analysis_results:
460
- st.info("الرجاء استخراج البنود أولاً من تبويب 'استخراج البنود'")
461
- else:
462
- if st.button("تحليل المخاطر في العقد"):
463
- with st.spinner("جاري تحليل المخاطر..."):
464
- # تحليل المخاطر باستخدام الذكاء الاصطناعي
465
- risks_prompt = f"""
466
- بناءً على البنود المستخرجة من العقد، قم بتحليل المخاطر المحتملة:
467
- 1. المخاطر القانونية
468
- 2. المخاطر المالية
469
- 3. مخاطر التنفيذ
470
- 4. مخاطر الجدول الزمني
471
- 5. أي مخاطر أخرى
472
-
473
- لكل مخاطرة، قدم:
474
- - وصف المخاطرة
475
- - احتمالية حدوثها (منخفضة، متوسطة، عالية)
476
- - تأثيرها (منخفض، متوسط، عالي)
477
- - توصيات للتخفيف من المخاطرة
478
-
479
- البنود المستخرجة:
480
- {self.analysis_results["contract_clauses"]}
481
- """
482
-
483
- # الحصول على تحليل المخاطر من النموذج المختار
484
- if st.session_state.selected_model == "anthropic":
485
- risks_result = self._get_anthropic_response(risks_prompt)
486
- else:
487
- risks_result = self._get_ai_response(risks_prompt)
488
-
489
- # حفظ تحليل المخاطر
490
- self.analysis_results["contract_risks"] = risks_result
491
-
492
- # عرض تحليل المخاطر
493
- st.markdown("### تحليل المخاطر")
494
- st.markdown(risks_result)
495
-
496
- st.success("تم تحليل المخاطر بنجاح!")
497
-
498
- # إذا كان تحليل المخاطر قد تم بالفعل، عرضه
499
- if "contract_risks" in self.analysis_results:
500
- st.markdown("### تحليل المخاطر")
501
- st.markdown(self.analysis_results["contract_risks"])
502
-
503
- # تبويب التقرير النهائي
504
- with contract_tabs[3]:
505
- st.markdown("#### التقرير النهائي")
506
-
507
- if "contract_risks" not in self.analysis_results:
508
- st.info("الرجاء تحليل المخاطر أولاً من تبويب 'تحليل المخاطر'")
509
- else:
510
- if st.button("إنشاء التقرير النهائي"):
511
- with st.spinner("جاري إنشاء التقرير النهائي..."):
512
- # إنشاء التقرير النهائي باستخدام الذكاء الاصطناعي
513
- report_prompt = f"""
514
- بناءً على البنود المستخرجة وتحليل المخاطر، قم بإنشاء تقرير نهائي يتضمن:
515
- 1. ملخص تنفيذي
516
- 2. تحليل البنود الرئيسية
517
- 3. تحليل المخاطر
518
- 4. التوصيات
519
- 5. الخلاصة
520
-
521
- البنود المستخرجة:
522
- {self.analysis_results["contract_clauses"]}
523
-
524
- تحليل المخاطر:
525
- {self.analysis_results["contract_risks"]}
526
- """
527
-
528
- # الحصول على التقرير النهائي من النموذج المختار
529
- if st.session_state.selected_model == "anthropic":
530
- report_result = self._get_anthropic_response(report_prompt)
531
- else:
532
- report_result = self._get_ai_response(report_prompt)
533
-
534
- # حفظ التقرير النهائي
535
- self.analysis_results["contract_report"] = report_result
536
-
537
- # عرض التقرير النهائي
538
- st.markdown("### التقرير النهائي")
539
- st.markdown(report_result)
540
-
541
- st.success("تم إنشاء التقرير النهائي بنجاح!")
542
-
543
- # إذا كان التقرير النهائي قد تم إنشاؤه بالفعل، عرضه
544
- if "contract_report" in self.analysis_results:
545
- st.markdown("### التقرير النهائي")
546
- st.markdown(self.analysis_results["contract_report"])
547
-
548
- # زر لتصدير التقرير
549
- report_content = f"""
550
- # تقرير تحليل العقد
551
-
552
- ## معلومات الملف
553
- - اسم الملف: {self.uploaded_files["contract"].name}
554
- - نوع الملف: {self.uploaded_files["contract"].type}
555
- - حجم الملف: {self.uploaded_files["contract"].size} بايت
556
-
557
- ## البنود المستخرجة
558
- {self.analysis_results["contract_clauses"]}
559
-
560
- ## تحليل المخاطر
561
- {self.analysis_results["contract_risks"]}
562
-
563
- ## التقرير النهائي
564
- {self.analysis_results["contract_report"]}
565
-
566
- ## تم إنشاء هذا التقرير بواسطة مساعد الذكاء الاصطناعي
567
- تاريخ الإنشاء: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
568
- """
569
-
570
- st.download_button(
571
- label="تصدير التقرير (PDF)",
572
- data=report_content.encode('utf-8'),
573
- file_name=f"تقرير_تحليل_العقد_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf",
574
- mime="application/pdf",
575
- key="export_contract_report_pdf"
576
- )
577
-
578
- def _render_cost_estimation_tab(self):
579
- """عرض تبويب تقدير التكاليف باستخدام نماذج هجين فيس"""
580
-
581
- st.markdown("### تقدير التكاليف")
582
-
583
- st.markdown("""
584
- يمكنك استخدام هذه الأداة لتقدير تكاليف المشاريع باستخدام نماذج الذكاء الاصطناعي المتقدمة من بيئة هجين فيس.
585
- الأداة تدعم تحليل الملفات التالية:
586
- - ملفات PDF (كراسات الشروط، المواصفات الفنية)
587
- - ملفات DWG (المخططات الهندسية)
588
- - ملفات Excel (جداول الكميات، التكاليف)
589
- - ملفات Word (العقود، المستندات)
590
- - ملفات النصوص TXT
591
- - ملفات الصور (PNG, JPG) للمخططات والرسومات
592
- """)
593
-
594
- # إنشاء تبويبات فرعية
595
- cost_tabs = st.tabs([
596
- "تحميل الملفات",
597
- "تقدير التكاليف",
598
- "تحليل البنود",
599
- "المقارنة مع السوق",
600
- "التقارير"
601
- ])
602
-
603
- # تبويب تحميل الملفات
604
- with cost_tabs[0]:
605
- st.markdown("#### تحميل ملفات المشروع")
606
-
607
- uploaded_files = st.file_uploader(
608
- "اختر ملفات المشروع للتحليل",
609
- type=["pdf", "dwg", "xlsx", "docx", "txt", "png", "jpg"],
610
- accept_multiple_files=True,
611
- key="cost_files_uploader"
612
- )
613
-
614
- if uploaded_files:
615
- st.write("### الملفات المرفوعة")
616
-
617
- for uploaded_file in uploaded_files:
618
- file_details = {
619
- "filename": uploaded_file.name,
620
- "filetype": uploaded_file.type,
621
- "filesize": uploaded_file.size
622
- }
623
-
624
- # حفظ الملف في الذاكرة المؤقتة
625
- self.uploaded_files[uploaded_file.name] = uploaded_file
626
-
627
- # عرض تفاصيل الملف
628
- col1, col2, col3, col4 = st.columns([3, 2, 2, 1])
629
- with col1:
630
- st.write(f"**{file_details['filename']}**")
631
- with col2:
632
- st.write(f"النوع: {self._detect_file_type(file_details['filename'])}")
633
- with col3:
634
- st.write(f"الحجم: {file_details['filesize']} بايت")
635
- with col4:
636
- if st.button("حذف", key=f"delete_{file_details['filename']}"):
637
- del self.uploaded_files[file_details['filename']]
638
- st.rerun() # تم تعديل هذا من st.experimental_rerun()
639
-
640
- st.success(f"تم تحميل {len(uploaded_files)} ملف بنجاح!")
641
-
642
- # تبويب تقدير التكاليف
643
- with cost_tabs[1]:
644
- st.markdown("#### تقدير التكاليف")
645
-
646
- if not self.uploaded_files:
647
- st.info("الرجاء تحميل ملفات المشروع أولاً من تبويب 'تحميل الملفات'")
648
- else:
649
- # نموذج إدخال معلومات المشروع
650
- st.markdown("### معلومات المشروع")
651
-
652
- col1, col2 = st.columns(2)
653
- with col1:
654
- project_name = st.text_input("اسم المشروع")
655
- project_location = st.text_input("موقع المشروع")
656
- project_type = st.selectbox(
657
- "نوع المشروع",
658
- ["سكني", "تجاري", "صناعي", "بنية تحتية", "آخر"]
659
- )
660
-
661
- with col2:
662
- project_area = st.number_input("مساحة المشروع (م²)", min_value=0.0, step=100.0)
663
- project_duration = st.number_input("مدة المشروع (بالأشهر)", min_value=1, step=1)
664
- project_quality = st.select_slider(
665
- "مستوى الجودة",
666
- options=["اقتصادي", "متوسط", "عالي", "فاخر"]
667
- )
668
-
669
- # زر لبدء تقدير التكاليف
670
- if st.button("تقدير التكاليف"):
671
- with st.spinner("جاري تقدير التكاليف..."):
672
- # إنشاء تقدير التكاليف باستخدام الذكاء الاصطناعي
673
-
674
- # تجميع معلومات المشروع
675
- project_info = f"""
676
- اسم المشروع: {project_name}
677
- موقع المشروع: {project_location}
678
- نوع المشروع: {project_type}
679
- مساحة المشروع: {project_area} م²
680
- مدة المشروع: {project_duration} أشهر
681
- مستوى الجودة: {project_quality}
682
-
683
- الملفات المرفوعة:
684
- {', '.join(self.uploaded_files.keys())}
685
- """
686
-
687
- # إنشاء تقدير التكاليف
688
- estimation_prompt = f"""
689
- أنت خبير في تقدير تكاليف مشاريع البناء في المملكة العربية السعودية.
690
- قم بتقدير تكاليف المشروع التالي بناءً على المعلومات المقدمة:
691
-
692
- {project_info}
693
-
694
- قدم تقديرًا مفصلاً للتكاليف يتضمن:
695
- 1. تكلفة المواد الرئيسية (الخرسانة، حديد التسليح، الطوب، إلخ)
696
- 2. تكلفة العمالة
697
- 3. تكلفة المعدات
698
- 4. التكاليف غير المباشرة
699
- 5. هامش الربح المقترح
700
- 6. إجمالي التكلفة المقدرة
701
- 7. تكلفة المتر المربع
702
-
703
- استخدم أسعار السوق الحالية في المملكة العربية السعودية لعام 2025.
704
- """
705
-
706
- # الحصول على تقدير التكاليف من النموذج المختار
707
- if st.session_state.selected_model == "anthropic":
708
- estimation_result = self._get_anthropic_response(estimation_prompt)
709
- else:
710
- estimation_result = self._get_ai_response(estimation_prompt)
711
-
712
- # حفظ تقدير التكاليف
713
- self.analysis_results["cost_estimation"] = estimation_result
714
-
715
- # عرض تقدير التكاليف
716
- st.markdown("### تقدير التكاليف")
717
- st.markdown(estimation_result)
718
-
719
- st.success("تم تقدير التكاليف بنجاح!")
720
-
721
- # إذا كان تقدير التكاليف قد تم بالفعل، عرضه
722
- if "cost_estimation" in self.analysis_results:
723
- st.markdown("### تقدير التكاليف")
724
- st.markdown(self.analysis_results["cost_estimation"])
725
-
726
- # زر لتصدير التقرير
727
- st.download_button(
728
- label="تصدير التقرير (PDF)",
729
- data="تقرير تقدير التكاليف".encode('utf-8'), # تم تعديل هذا من b"تقرير تقدير التكاليف"
730
- file_name=f"تقرير_تقدير_التكاليف_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf",
731
- mime="application/pdf",
732
- key="export_cost_report_pdf"
733
- )
734
-
735
- st.download_button(
736
- label="تصدير البيانات (Excel)",
737
- data="بيانات تقدير التكاليف".encode('utf-8'), # تم تعديل هذا من b"بيانات تقدير التكاليف"
738
- file_name=f"بيانات_تقدير_التكاليف_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx",
739
- mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
740
- key="export_cost_data_excel"
741
- )
742
-
743
- # تبويب تحليل البنود
744
- with cost_tabs[2]:
745
- st.markdown("#### تحليل البنود")
746
-
747
- if "cost_estimation" not in self.analysis_results:
748
- st.info("الرجاء تقدير التكاليف أولاً من تبويب 'تقدير التكاليف'")
749
- else:
750
- # إنشاء تحليل البنود باستخدام الذكاء الاصطناعي
751
- if st.button("تحليل البنود"):
752
- with st.spinner("جاري تحليل البنود..."):
753
- # تحليل البنود
754
- items_prompt = f"""
755
- بناءً على تقدير التكاليف التالي، قم بتحليل البنود الرئيسية:
756
-
757
- {self.analysis_results["cost_estimation"]}
758
-
759
- قدم تحليلاً مفصلاً للبنود يتضمن:
760
- 1. البنود ذات التكلفة الأعلى
761
- 2. البنود التي يمكن تقليل تكلفتها
762
- 3. البنود التي قد تتغير أسعارها بشكل كبير
763
- 4. توصيات لتحسين التكلفة الإجمالية
764
-
765
- قدم البيانات في شكل جدول حيثما أمكن.
766
- """
767
-
768
- # الحصول على تحليل البنود من النموذج المختار
769
- if st.session_state.selected_model == "anthropic":
770
- items_result = self._get_anthropic_response(items_prompt)
771
- else:
772
- items_result = self._get_ai_response(items_prompt)
773
-
774
- # حفظ تحليل البنود
775
- self.analysis_results["items_analysis"] = items_result
776
-
777
- # عرض تحليل البنود
778
- st.markdown("### تحليل البنود")
779
- st.markdown(items_result)
780
-
781
- st.success("تم تحليل البنود بنجاح!")
782
-
783
- # إذا كان تحليل البنود قد تم بالفعل، عرضه
784
- if "items_analysis" in self.analysis_results:
785
- st.markdown("### تحليل البنود")
786
- st.markdown(self.analysis_results["items_analysis"])
787
-
788
- # تبويب المقارنة مع السوق
789
- with cost_tabs[3]:
790
- st.markdown("#### المقارنة مع السوق")
791
-
792
- if "items_analysis" not in self.analysis_results:
793
- st.info("الرجاء تحليل البنود أولاً من تبويب 'تحليل البنود'")
794
- else:
795
- # إنشاء مقارنة مع السوق باستخدام الذكاء الاصطناعي
796
- if st.button("مقارنة مع السوق"):
797
- with st.spinner("جاري إجراء المقارنة مع السوق..."):
798
- # مقارنة مع السوق
799
- market_prompt = f"""
800
- بناءً على تقدير التكاليف وتحليل البنود التاليين، قم بإجراء مقارنة مع أسعار السوق الحالية في المملكة العربية السعودية:
801
-
802
- تقدير التكاليف:
803
- {self.analysis_results["cost_estimation"]}
804
-
805
- تحليل البنود:
806
- {self.analysis_results["items_analysis"]}
807
-
808
- قدم مقارنة مفصلة تتضمن:
809
- 1. مقارنة أسعار المواد الرئيسية مع متوسط أسعار السوق
810
- 2. مقارنة تكلفة المتر المربع مع المشاريع المماثلة
811
- 3. تحليل الفروقات وأسبابها
812
- 4. توصيات للحصول على أفضل الأسعار
813
-
814
- استخدم أسعار السوق الحالية في المملكة العربية السعودية لعام 2025.
815
- """
816
-
817
- # الحصول على مقارنة مع السوق من النموذج المختار
818
- if st.session_state.selected_model == "anthropic":
819
- market_result = self._get_anthropic_response(market_prompt)
820
- else:
821
- market_result = self._get_ai_response(market_prompt)
822
-
823
- # حفظ مقارنة مع السوق
824
- self.analysis_results["market_comparison"] = market_result
825
-
826
- # عرض مقارنة مع السوق
827
- st.markdown("### المقارنة مع السوق")
828
- st.markdown(market_result)
829
-
830
- st.success("تمت المقارنة مع السوق بنجاح!")
831
-
832
- # إذا كانت المقارنة مع السوق قد تمت بالفعل، عرضها
833
- if "market_comparison" in self.analysis_results:
834
- st.markdown("### المقارنة مع السوق")
835
- st.markdown(self.analysis_results["market_comparison"])
836
-
837
- # تبويب التقارير
838
- with cost_tabs[4]:
839
- st.markdown("#### التقارير")
840
-
841
- if "market_comparison" not in self.analysis_results:
842
- st.info("الرجاء إجراء المقارنة مع السوق أولاً من تبويب 'المقارنة مع السوق'")
843
- else:
844
- # إنشاء التقرير النهائي
845
- if st.button("إنشاء التقرير النهائي"):
846
- with st.spinner("جاري إنشاء التقرير النهائي..."):
847
- # إنشاء التقرير النهائي
848
- report_prompt = f"""
849
- بناءً على المعلومات التالية، قم بإنشاء تقرير نهائي شامل لتقدير تكاليف المشروع:
850
-
851
- تقدير التكاليف:
852
- {self.analysis_results["cost_estimation"]}
853
-
854
- تحليل البنود:
855
- {self.analysis_results["items_analysis"]}
856
-
857
- المقارنة مع السوق:
858
- {self.analysis_results["market_comparison"]}
859
-
860
- قدم تقريرًا شاملاً يتضمن:
861
- 1. ملخص تنفيذي
862
- 2. معلومات المشروع
863
- 3. منهجية تقدير التكاليف
864
- 4. تقدير التكاليف المفصل
865
- 5. تحليل البنود
866
- 6. المقارنة مع السوق
867
- 7. التوصيات
868
- 8. الخلاصة
869
-
870
- نسق التقرير بشكل احترافي وقابل للطباعة.
871
- """
872
-
873
- # الحصول على التقرير النهائي من النموذج المختار
874
- if st.session_state.selected_model == "anthropic":
875
- report_result = self._get_anthropic_response(report_prompt)
876
- else:
877
- report_result = self._get_ai_response(report_prompt)
878
-
879
- # حفظ التقرير النهائي
880
- self.analysis_results["final_report"] = report_result
881
-
882
- # عرض التقرير النهائي
883
- st.markdown("### التقرير النهائي")
884
- st.markdown(report_result)
885
-
886
- st.success("تم إنشاء التقرير النهائي بنجاح!")
887
-
888
- # إذا كان التقرير النهائي قد تم إنشاؤه بالفعل، عرضه
889
- if "final_report" in self.analysis_results:
890
- st.markdown("### التقرير النهائي")
891
- st.markdown(self.analysis_results["final_report"])
892
-
893
- # اسم ملف التقرير
894
- report_file_name = f"تقرير_تقدير_تكاليف_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
895
-
896
- # أزرار لتنزيل التقرير بصيغ مختلفة
897
- st.download_button(
898
- label="تنزيل التقرير (PDF)",
899
- data="تقرير تقدير التكاليف".encode('utf-8'), # تم تعديل هذا من b"تقرير تقدير التكاليف"
900
- file_name=f"{report_file_name}.pdf",
901
- mime="application/pdf",
902
- key="download_report_pdf"
903
- )
904
-
905
- st.download_button(
906
- label="تنزيل التقرير (Excel)",
907
- data="بيانات تقدير التكاليف".encode('utf-8'), # تم تعديل هذا من b"بيانات تقدير التكاليف"
908
- file_name=f"{report_file_name}.xlsx",
909
- mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
910
- key="download_report_excel"
911
- )
912
-
913
- st.download_button(
914
- label="تنزيل التقرير (Word)",
915
- data="تقرير تقدير التكاليف".encode('utf-8'), # تم تعديل هذا من b"تقرير تقدير التكاليف"
916
- file_name=f"{report_file_name}.docx",
917
- mime="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
918
- key="download_report_word"
919
- )
920
-
921
- def _render_risk_analysis_tab(self):
922
- """عرض تبويب تحليل المخاطر"""
923
- st.markdown("### تحليل المخاطر")
924
-
925
- st.markdown("""
926
- يمكنك استخدام هذه الأداة لتحليل المخاطر المحتملة في المشاريع باستخدام الذكاء الاصطناعي.
927
- """)
928
-
929
- # إنشاء تبويبات فرعية
930
- risk_tabs = st.tabs([
931
- "تحديد المخاطر",
932
- "تقييم المخاطر",
933
- "خطة الاستجابة",
934
- "التقرير النهائي"
935
- ])
936
-
937
- # تبويب تحديد المخاطر
938
- with risk_tabs[0]:
939
- st.markdown("#### تحديد المخاطر")
940
-
941
- # نموذج إدخال معلومات المشروع
942
- st.markdown("### معلومات المشروع")
943
-
944
- col1, col2 = st.columns(2)
945
- with col1:
946
- project_name = st.text_input("اسم المشروع", key="risk_project_name")
947
- project_location = st.text_input("موقع المشروع", key="risk_project_location")
948
- project_type = st.selectbox(
949
- "نوع المشروع",
950
- ["سكني", "تجاري", "صناعي", "بنية تحتية", "آخر"],
951
- key="risk_project_type"
952
- )
953
-
954
- with col2:
955
- project_budget = st.number_input("ميزانية المشروع (ريال سعودي)", min_value=0.0, step=100000.0)
956
- project_duration = st.number_input("مدة المشروع (بالأشهر)", min_value=1, step=1, key="risk_project_duration")
957
- project_complexity = st.select_slider(
958
- "مستوى تعقيد المشروع",
959
- options=["بسيط", "متوسط", "معقد", "معقد جدًا"]
960
- )
961
-
962
- # وصف المشروع
963
- project_description = st.text_area("وصف المشروع", height=150)
964
-
965
- # زر لتحديد المخاطر
966
- if st.button("تحديد المخاطر"):
967
- with st.spinner("جاري تحديد المخاطر..."):
968
- # تجميع معلومات المشروع
969
- project_info = f"""
970
- اسم المشروع: {project_name}
971
- موقع المشروع: {project_location}
972
- نوع المشروع: {project_type}
973
- ميزانية المشروع: {project_budget} ريال سعودي
974
- مدة المشروع: {project_duration} أشهر
975
- مستوى تعقيد المشروع: {project_complexity}
976
-
977
- وصف المشروع:
978
- {project_description}
979
- """
980
-
981
- # تحديد المخاطر باستخدام الذكاء الاصطناعي
982
- risks_prompt = f"""
983
- أنت خبير في إدارة المخاطر في مشاريع البناء في المملكة العربية السعودية.
984
- قم بتحديد المخاطر المحتملة للمشروع التالي:
985
-
986
- {project_info}
987
-
988
- حدد المخاطر في الفئات التالية:
989
- 1. المخاطر الفنية
990
- 2. المخاطر الإدارية
991
- 3. المخاطر المالية
992
- 4. المخاطر التعاقدية
993
- 5. المخاطر البيئية
994
- 6. مخاطر الجدول الزمني
995
- 7. مخاطر الموارد البشرية
996
- 8. مخاطر الصحة والسلامة
997
- 9. المخاطر القانونية والتنظيمية
998
- 10. مخاطر أخرى
999
-
1000
- لكل فئة، قدم قائمة بالمخاطر المحتملة مع وصف موجز لكل مخاطرة.
1001
- """
1002
-
1003
- # الحصول على تحديد المخاطر من النموذج المختار
1004
- if st.session_state.selected_model == "anthropic":
1005
- risks_result = self._get_anthropic_response(risks_prompt)
1006
- else:
1007
- risks_result = self._get_ai_response(risks_prompt)
1008
-
1009
- # حفظ تحديد المخاطر
1010
- self.analysis_results["identified_risks"] = risks_result
1011
-
1012
- # حفظ معلومات المشروع
1013
- self.analysis_results["risk_project_info"] = project_info
1014
-
1015
- # عرض تحديد المخاطر
1016
- st.markdown("### المخاطر المحددة")
1017
- st.markdown(risks_result)
1018
-
1019
- st.success("تم تحديد المخاطر بنجاح!")
1020
-
1021
- # إذا كان تحديد المخاطر قد تم بالفعل، عرضه
1022
- if "identified_risks" in self.analysis_results:
1023
- st.markdown("### المخاطر المحددة")
1024
- st.markdown(self.analysis_results["identified_risks"])
1025
-
1026
- # تبويب تقييم المخاطر
1027
- with risk_tabs[1]:
1028
- st.markdown("#### تقييم المخاطر")
1029
-
1030
- if "identified_risks" not in self.analysis_results:
1031
- st.info("الرجاء تحديد المخاطر أولاً من تبويب 'تحديد المخاطر'")
1032
- else:
1033
- # زر لتقييم المخاطر
1034
- if st.button("تقييم المخاطر"):
1035
- with st.spinner("جاري تقييم المخاطر..."):
1036
- # تقييم المخاطر باستخدام الذكاء الاصطناعي
1037
- assessment_prompt = f"""
1038
- بناءً على المخاطر المحددة للمشروع، قم بتقييم كل مخاطرة من حيث:
1039
-
1040
- 1. احتمالية الحدوث (منخفضة، متوسطة، عالية)
1041
- 2. التأثير (منخفض، متوسط، عالي)
1042
- 3. درجة المخاطرة (منخفضة، متوسطة، عالية، حرجة)
1043
-
1044
- معلومات المشروع:
1045
- {self.analysis_results["risk_project_info"]}
1046
-
1047
- المخاطر المحددة:
1048
- {self.analysis_results["identified_risks"]}
1049
-
1050
- قدم تقييمًا مفصلاً لكل مخاطرة في شكل جدول يتضمن:
1051
- - وصف المخاطرة
1052
- - الفئة
1053
- - احتمالية الحدوث
1054
- - التأثير
1055
- - درجة المخاطرة
1056
-
1057
- ثم قم بترتيب المخاطر حسب درجة المخاطرة من الأعلى إلى الأدنى.
1058
- """
1059
-
1060
- # الحصول على تقييم المخاطر من النموذج المختار
1061
- if st.session_state.selected_model == "anthropic":
1062
- assessment_result = self._get_anthropic_response(assessment_prompt)
1063
- else:
1064
- assessment_result = self._get_ai_response(assessment_prompt)
1065
-
1066
- # حفظ تقييم المخاطر
1067
- self.analysis_results["risk_assessment"] = assessment_result
1068
-
1069
- # عرض تقييم المخاطر
1070
- st.markdown("### تقييم المخاطر")
1071
- st.markdown(assessment_result)
1072
-
1073
- st.success("تم تقييم المخاطر بنجاح!")
1074
-
1075
- # إذا كان تقييم المخاطر قد تم بالفعل، عرضه
1076
- if "risk_assessment" in self.analysis_results:
1077
- st.markdown("### تقييم المخاطر")
1078
- st.markdown(self.analysis_results["risk_assessment"])
1079
-
1080
- # تبويب خطة الاستجابة
1081
- with risk_tabs[2]:
1082
- st.markdown("#### خطة الاستجابة")
1083
-
1084
- if "risk_assessment" not in self.analysis_results:
1085
- st.info("الرجاء تقييم المخاطر أولاً من تبويب 'تقييم المخاطر'")
1086
- else:
1087
- # زر لإنشاء خطة الاستجابة
1088
- if st.button("إنشاء خطة الاستجابة"):
1089
- with st.spinner("جاري إنشاء خطة الاستجابة..."):
1090
- # إنشاء خطة الاستجابة باستخدام الذكاء الاصطناعي
1091
- response_prompt = f"""
1092
- بناءً على تقييم المخاطر للمشروع، قم بإنشاء خطة استجابة لكل مخاطرة تتضمن:
1093
-
1094
- 1. استراتيجية الاستجابة (تجنب، تخفيف، نقل، قبول)
1095
- 2. الإجراءات المحددة
1096
- 3. المسؤول عن التنفيذ
1097
- 4. الموارد المطلوبة
1098
- 5. الجدول الزمني
1099
-
1100
- معلومات المشروع:
1101
- {self.analysis_results["risk_project_info"]}
1102
-
1103
- تقييم المخاطر:
1104
- {self.analysis_results["risk_assessment"]}
1105
-
1106
- قدم خطة استجابة مفصلة لكل مخاطرة، مع التركيز على المخاطر ذات الدرجة العالية والحرجة.
1107
- """
1108
-
1109
- # الحصول على خطة الاستجابة من النموذج المختار
1110
- if st.session_state.selected_model == "anthropic":
1111
- response_result = self._get_anthropic_response(response_prompt)
1112
- else:
1113
- response_result = self._get_ai_response(response_prompt)
1114
-
1115
- # حفظ خطة الاستجابة
1116
- self.analysis_results["risk_response"] = response_result
1117
-
1118
- # عرض خطة الاستجابة
1119
- st.markdown("### خطة الاستجابة")
1120
- st.markdown(response_result)
1121
-
1122
- st.success("تم إنشاء خطة الاستجابة بنجاح!")
1123
-
1124
- # إذا كانت خطة الاستجابة قد تم إنشاؤها بالفعل، عرضها
1125
- if "risk_response" in self.analysis_results:
1126
- st.markdown("### خطة الاستجابة")
1127
- st.markdown(self.analysis_results["risk_response"])
1128
-
1129
- # تبويب التقرير النهائي
1130
- with risk_tabs[3]:
1131
- st.markdown("#### التقرير النهائي")
1132
-
1133
- if "risk_response" not in self.analysis_results:
1134
- st.info("الرجاء إنشاء خطة الاستجابة أولاً من تبويب 'خطة الاستجابة'")
1135
- else:
1136
- # زر لإنشاء التقرير النهائي
1137
- if st.button("إنشاء التقرير النهائي"):
1138
- with st.spinner("جاري إنشاء التقرير النهائي..."):
1139
- # إنشاء التقرير النهائي باستخدام الذكاء الاصطناعي
1140
- report_prompt = f"""
1141
- بناءً على المعلومات التالية، قم بإنشاء تقرير نهائي شامل لتحليل المخاطر في المشروع:
1142
-
1143
- معلومات المشروع:
1144
- {self.analysis_results["risk_project_info"]}
1145
-
1146
- المخاطر المحددة:
1147
- {self.analysis_results["identified_risks"]}
1148
-
1149
- تقييم المخاطر:
1150
- {self.analysis_results["risk_assessment"]}
1151
-
1152
- خطة الاستجابة:
1153
- {self.analysis_results["risk_response"]}
1154
-
1155
- قدم تقريرًا شاملاً يتضمن:
1156
- 1. ملخص تنفيذي
1157
- 2. معلومات المشروع
1158
- 3. منهجية تحليل المخاطر
1159
- 4. المخاطر المحددة
1160
- 5. تقييم المخاطر
1161
- 6. خطة الاستجابة
1162
- 7. خطة المراقبة والتحكم
1163
- 8. التوصيات
1164
- 9. الخلاصة
1165
-
1166
- نسق التقرير بشكل احترافي وقابل للطباعة.
1167
- """
1168
-
1169
- # الحصول على التقرير النهائي من النموذج المختار
1170
- if st.session_state.selected_model == "anthropic":
1171
- report_result = self._get_anthropic_response(report_prompt)
1172
- else:
1173
- report_result = self._get_ai_response(report_prompt)
1174
-
1175
- # حفظ التقرير النهائي
1176
- self.analysis_results["risk_report"] = report_result
1177
-
1178
- # عرض التقرير النهائي
1179
- st.markdown("### التقري�� النهائي")
1180
- st.markdown(report_result)
1181
-
1182
- st.success("تم إنشاء التقرير النهائي بنجاح!")
1183
-
1184
- # إذا كان التقرير النهائي قد تم إنشاؤه بالفعل، عرضه
1185
- if "risk_report" in self.analysis_results:
1186
- st.markdown("### التقرير النهائي")
1187
- st.markdown(self.analysis_results["risk_report"])
1188
-
1189
- # اسم ملف التقرير
1190
- report_file_name = f"تقرير_تحليل_المخاطر_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
1191
-
1192
- # أزرار لتنزيل التقرير بصيغ مختلفة
1193
- st.download_button(
1194
- label="تنزيل التقرير (PDF)",
1195
- data="تقرير تحليل المخاطر".encode('utf-8'), # تم تعديل هذا من b"تقرير تحليل المخاطر"
1196
- file_name=f"{report_file_name}.pdf",
1197
- mime="application/pdf",
1198
- key="download_risk_report_pdf"
1199
- )
1200
-
1201
- st.download_button(
1202
- label="تنزيل التقرير (Word)",
1203
- data="تقرير تحليل المخاطر".encode('utf-8'), # تم تعديل هذا من b"تقرير تحليل المخاطر"
1204
- file_name=f"{report_file_name}.docx",
1205
- mime="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
1206
- key="download_risk_report_word"
1207
- )
1208
-
1209
- def _render_settings_tab(self):
1210
- """عرض تبويب الإعدادات"""
1211
- st.markdown("### الإعدادات")
1212
-
1213
- st.markdown("#### إعدادات نماذج الذكاء الاصطناعي")
1214
-
1215
- # إعدادات مفاتيح API
1216
- st.markdown("##### مفاتيح API")
1217
-
1218
- # مفتاح API لنموذج ai
1219
- ai_api_key = st.text_input(
1220
- "مفتاح API لنموذج ai",
1221
- value=st.session_state.ai_api_key,
1222
- type="password"
1223
- )
1224
-
1225
- # مفتاح API لنموذج anthropic
1226
- anthropic_api_key = st.text_input(
1227
- "مفتاح API لنموذج anthropic",
1228
- value=st.session_state.anthropic_api_key,
1229
- type="password"
1230
- )
1231
-
1232
- # زر لحفظ الإعدادات
1233
- if st.button("حفظ الإعدادات"):
1234
- # تحديث مفاتيح API
1235
- st.session_state.ai_api_key = ai_api_key
1236
- st.session_state.anthropic_api_key = anthropic_api_key
1237
-
1238
- st.success("تم حفظ الإعدادات بنجاح!")
1239
-
1240
- def _get_anthropic_response(self, prompt):
1241
- """الحصول على رد من نموذج anthropic"""
1242
- try:
1243
- # التحقق من وجود مفتاح API
1244
- if not st.session_state.anthropic_api_key:
1245
- return "لم يتم تكوين مفتاح API لنموذج anthropic. يرجى تكوين المفتاح في الإعدادات."
1246
-
1247
- # إنشاء عميل anthropic
1248
- client = anthropic.Anthropic(api_key=st.session_state.anthropic_api_key)
1249
-
1250
- # إرسال الطلب إلى النموذج
1251
- response = client.messages.create(
1252
- model="claude-3-opus-20240229",
1253
- max_tokens=4000,
1254
- temperature=0.7,
1255
- system="أنت مساعد ذكي متخصص في تحليل مشاريع البناء والمقاولات في المملكة العربية السعودية. تقدم تحليلات دقيقة وتوصيات عملية بناءً على البيانات المقدمة.",
1256
- messages=[
1257
- {"role": "user", "content": prompt}
1258
- ]
1259
- )
1260
-
1261
- # إرجاع الرد
1262
- return response.content[0].text
1263
- except Exception as e:
1264
- return f"حدث خطأ أثناء الاتصال بنموذج anthropic: {str(e)}"
1265
-
1266
- def _get_ai_response(self, prompt):
1267
- """الحصول على رد من نموذج ai"""
1268
- try:
1269
- # التحقق من وجود مفتاح API
1270
- if not st.session_state.ai_api_key:
1271
- return "لم يتم تكوين مفتاح API لنموذج ai. يرجى تكوين المفتاح في الإعدادات."
1272
-
1273
- # إعداد رأس الطلب
1274
- headers = {
1275
- "Authorization": f"Bearer {st.session_state.ai_api_key}",
1276
- "Content-Type": "application/json"
1277
- }
1278
-
1279
- # إعداد بيانات الطلب
1280
- data = {
1281
- "model": "gpt-4",
1282
- "messages": [
1283
- {
1284
- "role": "system",
1285
- "content": "أنت مساعد ذكي متخصص في تحليل مشاريع البناء والمقاولات في المملكة العربية السعودية. تقدم تحليلات دقيقة وتوصيات عملية بناءً على البيانات المقدمة."
1286
- },
1287
- {
1288
- "role": "user",
1289
- "content": prompt
1290
- }
1291
- ],
1292
- "temperature": 0.7,
1293
- "max_tokens": 4000
1294
- }
1295
-
1296
- # إرسال الطلب إلى النموذج
1297
- response = requests.post(
1298
- "https://api.openai.com/v1/chat/completions",
1299
- headers=headers,
1300
- json=data
1301
- )
1302
-
1303
- # التحقق من نجاح الطلب
1304
- if response.status_code == 200:
1305
- # إرجاع الرد
1306
- return response.json()["choices"][0]["message"]["content"]
1307
- else:
1308
- return f"حدث خطأ أثناء الاتصال بنموذج ai: {response.text}"
1309
- except Exception as e:
1310
- return f"حدث خطأ أثناء الاتصال بنموذج ai: {str(e)}"
1311
-
1312
- def _extract_text_from_file(self, file):
1313
- """استخراج النص من الملف"""
1314
- try:
1315
- # تحديد نوع الملف
1316
- file_name = file.name
1317
- file_extension = file_name.split('.')[-1].lower()
1318
-
1319
- # استخراج النص حسب نوع الملف
1320
- if file_extension == 'pdf':
1321
- # استخراج النص من ملف PDF
1322
- pdf_reader = PyPDF2.PdfReader(file)
1323
- text = ""
1324
- for page in pdf_reader.pages:
1325
- text += page.extract_text() + "\n"
1326
- return text
1327
- elif file_extension in ['docx', 'doc']:
1328
- # استخراج النص من ملف Word
1329
- doc = docx.Document(file)
1330
- text = ""
1331
- for para in doc.paragraphs:
1332
- text += para.text + "\n"
1333
- return text
1334
- elif file_extension == 'txt':
1335
- # استخراج النص من ملف نصي
1336
- return file.getvalue().decode('utf-8')
1337
- else:
1338
- return f"نوع الملف {file_extension} غير مدعوم لاستخراج النص."
1339
- except Exception as e:
1340
- return f"حدث خطأ أثناء استخراج النص من الملف: {str(e)}"
1341
-
1342
- def _detect_file_type(self, file_name):
1343
- """تحديد نوع الملف بناءً على الامتداد"""
1344
- extension = file_name.split('.')[-1].lower()
1345
-
1346
- if extension in ['pdf']:
1347
- return 'application/pdf'
1348
- elif extension in ['dwg']:
1349
- return 'application/acad'
1350
- elif extension in ['xlsx', 'xls']:
1351
- return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
1352
- elif extension in ['docx', 'doc']:
1353
- return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
1354
- elif extension in ['txt']:
1355
- return 'text/plain'
1356
- elif extension in ['png']:
1357
- return 'image/png'
1358
- elif extension in ['jpg', 'jpeg']:
1359
- return 'image/jpeg'
1360
- else:
1361
- return 'application/octet-stream'
 
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ وحدة مساعد الذكاء الاصطناعي
4
+ """
5
+
6
+ import streamlit as st
7
+ import pandas as pd
8
+ import numpy as np
9
+ import matplotlib.pyplot as plt
10
+ import plotly.express as px
11
+ import plotly.graph_objects as go
12
+ import seaborn as sns
13
+ from datetime import datetime
14
+ import time
15
+ import os
16
+ import sys
17
+ import json
18
+ import requests
19
+ from pathlib import Path
20
+ import io
21
+ import base64
22
+ import re
23
+ from PIL import Image
24
+ import PyPDF2
25
+ import docx
26
+ import anthropic
27
+ import tempfile
28
+
29
+ # إضافة المسار للوصول إلى الوحدات الأخرى
30
+ current_dir = os.path.dirname(os.path.abspath(__file__))
31
+ parent_dir = os.path.dirname(os.path.dirname(current_dir))
32
+ if parent_dir not in sys.path:
33
+ sys.path.append(parent_dir)
34
+
35
+ class AIAssistantApp:
36
+ """تطبيق مساعد الذكاء الاصطناعي"""
37
+
38
+ def __init__(self):
39
+ """تهيئة تطبيق مساعد الذكاء الاصطناعي"""
40
+ self.uploaded_files = {}
41
+ self.analysis_results = {}
42
+
43
+ # تهيئة مفاتيح API لنماذج هجين فيس
44
+ # تحميل المفاتيح من أسرار هجين فيس (Hugging Face Secrets)
45
+ if 'ai_api_key' not in st.session_state:
46
+ # الحصول على المفتاح من أسرار هجين فيس
47
+ ai_key = self._get_huggingface_secret('ai')
48
+ st.session_state.ai_api_key = ai_key
49
+
50
+ if 'anthropic_api_key' not in st.session_state:
51
+ # الحصول على المفتاح من أسرار هجين فيس
52
+ anthropic_key = self._get_huggingface_secret('anthropic')
53
+ st.session_state.anthropic_api_key = anthropic_key
54
+
55
+ # تهيئة محادثة الذكاء الاصطناعي
56
+ if 'messages' not in st.session_state:
57
+ st.session_state.messages = []
58
+
59
+ if 'selected_model' not in st.session_state:
60
+ st.session_state.selected_model = "anthropic"
61
+
62
+ def _get_huggingface_secret(self, secret_name):
63
+ """
64
+ الحصول على قيمة السر من أسرار هجين فيس
65
+
66
+ في بيئة هجين فيس، الأسرار متاحة كمتغيرات بيئة بالتنسيق HF_SECRET_<SECRET_NAME>
67
+ """
68
+ # تحويل اسم السر إلى الصيغة المستخدمة في متغيرات البيئة في هجين فيس
69
+ env_var_name = f"HF_SECRET_{secret_name.upper()}"
70
+ secret_value = os.environ.get(env_var_name, '')
71
+
72
+ # إذا لم يتم العثور على السر، نعرض رسالة تحذير (في وضع التطوير فقط)
73
+ if not secret_value and st.secrets.get("dev_mode", False):
74
+ st.warning(f"لم يتم العثور على السر: {secret_name}. تأكد من إضافته في إعدادات الأسرار في هجين فيس.")
75
+
76
+ return secret_value
77
+
78
+ def run(self):
79
+ """تشغيل تطبيق مساعد الذكاء الاصطناعي"""
80
+ # عرض عنوان التطبيق
81
+ st.title("مساعد الذكاء الاصطناعي")
82
+
83
+ # إنشاء تبويبات التطبيق
84
+ tabs = st.tabs([
85
+ "المحادثة",
86
+ "تحليل المستندات",
87
+ "تحليل العقود",
88
+ "تقدير التكاليف",
89
+ "تحليل المخاطر",
90
+ "الإعدادات"
91
+ ])
92
+
93
+ # عرض محتوى كل تبويب
94
+ with tabs[0]:
95
+ self._render_chat_tab()
96
+
97
+ with tabs[1]:
98
+ self._render_document_analysis_tab()
99
+
100
+ with tabs[2]:
101
+ self._render_contract_analysis_tab()
102
+
103
+ with tabs[3]:
104
+ self._render_cost_estimation_tab()
105
+
106
+ with tabs[4]:
107
+ self._render_risk_analysis_tab()
108
+
109
+ with tabs[5]:
110
+ self._render_settings_tab()
111
+
112
+ def _render_chat_tab(self):
113
+ """عرض تبويب المحادثة مع الذكاء الاصطناعي"""
114
+ st.markdown("### المحادثة مع الذكاء الاصطناعي")
115
+
116
+ # اختيار نموذج الذكاء الاصطناعي
117
+ selected_model = st.selectbox(
118
+ "اختر نموذج الذكاء الاصطناعي:",
119
+ ["anthropic", "ai"],
120
+ index=0 if st.session_state.selected_model == "anthropic" else 1
121
+ )
122
+
123
+ # تحديث النموذج المختار إذا تغير
124
+ if selected_model != st.session_state.selected_model:
125
+ st.session_state.selected_model = selected_model
126
+ st.rerun()
127
+
128
+ # التحقق من وجود مفتاح API للنموذج المختار
129
+ api_key_available = False
130
+ if selected_model == "anthropic" and st.session_state.anthropic_api_key:
131
+ api_key_available = True
132
+ elif selected_model == "ai" and st.session_state.ai_api_key:
133
+ api_key_available = True
134
+
135
+ if not api_key_available:
136
+ st.error(f"مفتاح API لنموذج {selected_model} غير متوفر. يرجى إضافته في إعدادات الأسرار في هجين فيس.")
137
+ return
138
+
139
+ # عرض المحادثة السابقة
140
+ for message in st.session_state.messages:
141
+ with st.chat_message(message["role"]):
142
+ st.markdown(message["content"])
143
+
144
+ # إدخال رسالة جديدة
145
+ if prompt := st.chat_input("اكتب رسالتك هنا..."):
146
+ # إضافة رسالة المستخدم إلى المحادثة
147
+ st.session_state.messages.append({"role": "user", "content": prompt})
148
+ with st.chat_message("user"):
149
+ st.markdown(prompt)
150
+
151
+ # إضافة رسالة المساعد إلى المحادثة
152
+ with st.chat_message("assistant"):
153
+ message_placeholder = st.empty()
154
+ full_response = ""
155
+
156
+ # الحصول على الرد من نموذج الذكاء الاصطناعي
157
+ try:
158
+ if selected_model == "anthropic":
159
+ response = self._get_anthropic_response(prompt)
160
+ else: # ai
161
+ response = self._get_ai_response(prompt)
162
+
163
+ # عرض الرد بشكل تدريجي
164
+ for chunk in response.split():
165
+ full_response += chunk + " "
166
+ time.sleep(0.05)
167
+ message_placeholder.markdown(full_response + "▌")
168
+
169
+ message_placeholder.markdown(full_response)
170
+
171
+ # إضافة الرد إلى المحادثة
172
+ st.session_state.messages.append({"role": "assistant", "content": full_response})
173
+ except Exception as e:
174
+ st.error(f"حدث خطأ أثناء الاتصال بنموذج {selected_model}: {str(e)}")
175
+
176
+ def _get_anthropic_response(self, prompt):
177
+ """الحصول على رد من نموذج Anthropic"""
178
+ try:
179
+ client = anthropic.Anthropic(api_key=st.session_state.anthropic_api_key)
180
+
181
+ # إنشاء سلسلة المحادثة
182
+ messages = []
183
+ for msg in st.session_state.messages:
184
+ if msg["role"] == "user":
185
+ messages.append({"role": "user", "content": msg["content"]})
186
+ else:
187
+ messages.append({"role": "assistant", "content": msg["content"]})
188
+
189
+ # إضافة الرسالة الحالية
190
+ messages.append({"role": "user", "content": prompt})
191
+
192
+ # الحصول على الرد
193
+ response = client.messages.create(
194
+ model="claude-3-opus-20240229",
195
+ max_tokens=2000,
196
+ messages=messages
197
+ )
198
+
199
+ return response.content[0].text
200
+ except Exception as e:
201
+ st.error(f"خطأ في الاتصال بـ Anthropic: {str(e)}")
202
+ return "عذرًا، حدث خطأ أثناء الاتصال بنموذج Anthropic."
203
+
204
+ def _get_ai_response(self, prompt):
205
+ """الحصول على رد من نموذج AI"""
206
+ try:
207
+ # هنا يمكن استبدال هذا بالكود الفعلي للاتصال بنموذج AI
208
+ # هذا مجرد مثال
209
+ headers = {
210
+ "Authorization": f"Bearer {st.session_state.ai_api_key}",
211
+ "Content-Type": "application/json"
212
+ }
213
+
214
+ data = {
215
+ "model": "gpt-4",
216
+ "messages": [{"role": "user", "content": prompt}],
217
+ "max_tokens": 2000
218
+ }
219
+
220
+ response = requests.post(
221
+ "https://api.openai.com/v1/chat/completions",
222
+ headers=headers,
223
+ json=data
224
+ )
225
+
226
+ if response.status_code == 200:
227
+ return response.json()["choices"][0]["message"]["content"]
228
+ else:
229
+ st.error(f"خطأ في الاستجابة: {response.status_code} - {response.text}")
230
+ return "عذرًا، حدث خطأ أثناء الاتصال بنموذج AI."
231
+ except Exception as e:
232
+ st.error(f"خطأ في الاتصال بـ AI: {str(e)}")
233
+ return "عذرًا، حدث خطأ أثناء الاتصال بنموذج AI."
234
+
235
+ def _render_document_analysis_tab(self):
236
+ """عرض تبويب تحليل المستندات"""
237
+ st.markdown("### تحليل المستندات")
238
+ st.write("هذه الميزة قيد التطوير.")
239
+
240
+ def _render_contract_analysis_tab(self):
241
+ """عرض تبويب تحليل العقود"""
242
+ st.markdown("### تحليل العقود")
243
+ st.write("هذه الميزة قيد التطوير.")
244
+
245
+ def _render_cost_estimation_tab(self):
246
+ """عرض تبويب تقدير التكاليف"""
247
+ st.markdown("### تقدير التكاليف")
248
+ st.write("هذه الميزة قيد التطوير.")
249
+
250
+ def _render_risk_analysis_tab(self):
251
+ """عرض تبويب تحليل المخاطر"""
252
+ st.markdown("### تحليل المخاطر")
253
+ st.write("هذه الميزة قيد التطوير.")
254
+
255
+ def _render_settings_tab(self):
256
+ """عرض تبويب الإعدادات"""
257
+ st.markdown("### إعدادات التطبيق")
258
+
259
+ # عرض حالة مفاتيح API
260
+ st.subheader("حالة مفاتيح API")
261
+
262
+ # التحقق من حالة مفتاح Anthropic
263
+ anthropic_key_status = "✅ متوفر" if st.session_state.anthropic_api_key else "❌ غير متوفر"
264
+ st.markdown(f"**مفتاح Anthropic:** {anthropic_key_status}")
265
+
266
+ # التحقق من حالة مفتاح AI
267
+ ai_key_status = "✅ متوفر" if st.session_state.ai_api_key else "❌ غير متوفر"
268
+ st.markdown(f"**مفتاح AI:** {ai_key_status}")
269
+
270
+ # إضافة معلومات حول كيفية إضافة المفاتيح
271
+ st.markdown("""
272
+ ### كيفية إضافة مفاتيح API
273
+
274
+ لإضافة مفاتيح API إلى التطبيق، يرجى اتباع الخطوات التالية:
275
+
276
+ 1. انتقل إلى إعدادات التطبيق في منصة هجين فيس (Hugging Face)
277
+ 2. اختر قسم "الأسرار" (Secrets)
278
+ 3. أضف المفاتيح التالية:
279
+ - `ai`: مفتاح API لنموذج AI
280
+ - `anthropic`: مفتاح API لنموذج Anthropic
281
+
282
+ بعد إضافة المفاتيح، قم بإعادة تشغيل التطبيق لتطبيق التغييرات.
283
+ """)
284
+
285
+ # تشغيل التطبيق
286
+ if __name__ == "__main__":
287
+ app = AIAssistantApp()
288
+ app.run()