mohammed777 commited on
Commit
f71cd62
·
verified ·
1 Parent(s): 7d18ee7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +90 -42
app.py CHANGED
@@ -1,49 +1,85 @@
1
  import gradio as gr
2
  import json
3
- import matplotlib.pyplot as plt # استيراد Matplotlib
4
  import numpy as np # قد نحتاجه لبعض العمليات الحسابية البسيطة
 
 
 
5
 
6
- # استيراد الدالة مباشرة من ملف main.py
 
7
  from main import evaluate_youtube_playlist_individually_same_method2
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  async def evaluate_playlist_local(youtube_url: str, max_comments_per_video: int = 50, max_workers: int = 3):
10
  """
11
  تستدعي دالة تقييم قائمة تشغيل YouTube مباشرة من ملف main.py.
12
- وتعيد النتائج النصية في صندوق واحد ومخطط Matplotlib.
13
  """
14
  error_message = ""
15
 
16
- # تهيئة المخرجات الافتراضية في حالة وجود خطأ
17
  default_text_output = "الرجاء إدخال رابط صحيح وتشغيل التقييم."
18
- default_plot = plt.figure() # إنشاء شكل فارغ لتجنب الأخطاء
 
 
19
 
 
20
  if not youtube_url:
21
  error_message = "الرجاء إدخال رابط قائمة تشغيل أو فيديو يوتيوب."
22
- gr.Warning(error_message)
23
  return error_message, default_plot # إرجاع رسالة خطأ ومخطط فارغ
24
 
25
  try:
 
26
  result = await evaluate_youtube_playlist_individually_same_method2(
27
  youtube_url=youtube_url,
28
  max_comments_per_video=max_comments_per_video,
29
  max_workers=max_workers
30
  )
31
 
 
32
  if "error" in result:
33
  error_message = f"خطأ في المعالجة: {result['error']}"
34
- gr.Error(error_message) # عرض الخطأ كتحذير في Gradio
35
  return error_message, default_plot # إرجاع رسالة الخطأ ومخطط فارغ
36
 
37
- # استخراج النتائج المطلوبة
38
  overall_quality = result.get("overall_quality", "غير متوفر")
39
  composite_quality = result.get("composite_quality", "غير متوفر")
40
  composite_score = result.get("composite_score", "غير متوفر")
41
  percent_good_videos = result.get("percent_good_videos", "غير متوفر")
42
- positive_ratio = result.get("positive_ratio", 0.0) # تأكد من الحصول على قيمة عددية
43
- negative_ratio = result.get("negative_ratio", 0.0) # تأكد من الحصول على قيمة عددية
 
44
 
45
  # =======================================================
46
- # 1. إعداد النص الموحد في صندوق واحد
47
  # =======================================================
48
  formatted_output_text = f"""
49
  ## 📊 نتائج تقييم قائمة التشغيل:
@@ -54,65 +90,77 @@ async def evaluate_playlist_local(youtube_url: str, max_comments_per_video: int
54
  - **نسبة الفيديوهات الجيدة:** **{percent_good_videos}%**
55
  - **نسبة التعليقات الإيجابية:** **{positive_ratio}%**
56
  - **نسبة التعليقات السلبية:** **{negative_ratio}%**
57
-
58
- ---
59
  """
60
 
61
  # =======================================================
62
- # 2. رسم المخطط باستخدام Matplotlib
63
  # =======================================================
64
- fig, ax = plt.subplots(figsize=(6, 4)) # إنشاء شكل ومحاور
 
 
 
 
65
 
66
- labels = ['إيجابية', 'سلبية']
67
- sizes = [positive_ratio, negative_ratio]
68
- colors = ['#4CAF50', '#F44336'] # أخضر للإيجابي، أحمر للسلبي
69
- explode = (0.1, 0) # "تفجير" الشريحة الإيجابية قليلاً لإبرازها
 
 
 
70
 
71
- # مخطط دائري (Pie Chart) لنسبة التعليقات
72
- ax.pie(sizes, explode=explode, labels=labels, colors=colors,
73
  autopct='%1.1f%%', shadow=True, startangle=90, textprops={'fontsize': 12})
74
- ax.axis('equal') # يضمن أن يكون المخطط دائريًا.
75
- ax.set_title('توزيع التعليقات', fontsize=14, pad=20) # عنوان المخطط
76
-
77
- # يمكن أيضًا استخدام مخطط شريطي إذا فضلت ذلك:
78
- # ax.bar(labels, sizes, color=colors)
79
- # ax.set_ylabel('النسبة المئوية (%)')
80
- # ax.set_title('توزيع التعليقات')
81
- # ax.set_ylim(0, 100) # نطاق Y من 0 إلى 100
82
 
83
- plt.close(fig) # مهم: أغلق الشكل لتجنب عرض المخططات المكررة في Gradio
 
84
 
85
- return formatted_output_text, fig # إرجاع النص والمخطط
 
86
 
87
  except Exception as e:
 
88
  error_message = f"حدث خطأ غير متوقع أثناء المعالجة: {e}"
89
- gr.Error(error_message)
90
- return error_message, default_plot # في حالة أي خطأ، أرجع رسالة الخطأ ومخطط فارغ
91
 
92
 
93
- # بناء واجهة Gradio
94
  with gr.Blocks(title="تقييم قائمة تشغيل يوتيوب") as demo:
 
95
  gr.Markdown("# 📊 تقييم جودة قائمة تشغيل يوتيوب")
96
  gr.Markdown("أدخل رابط قائمة تشغيل أو فيديو يوتيوب لتقييم جودتها بناءً على التحليلات والمشاعر.")
97
 
 
98
  with gr.Row():
99
- with gr.Column(scale=1): # العمود الأول للمدخلات
 
100
  youtube_url_input = gr.Textbox(label="رابط قائمة تشغيل/فيديو يوتيوب", placeholder="الصق رابط يوتيوب هنا...", interactive=True)
101
  max_comments_input = gr.Slider(minimum=10, maximum=200, value=50, step=10, label="الحد الأقصى للتعليقات لكل فيديو", interactive=True)
102
  max_workers_input = gr.Slider(minimum=1, maximum=10, value=3, step=1, label="الحد الأقصى للعمال المتوازيين", interactive=True)
103
- submit_button = gr.Button("🚀 تقييم قائمة التشغيل", variant="primary") # زر رئيسي
104
 
105
- with gr.Column(scale=2): # العمود الثاني للمخرجات (أكبر)
106
- # صندوق نصي واحد لجميع النتائج
107
- output_text_box = gr.Markdown(label="النتائج النهائية للتقييم", ) # استخدم Markdown لعرض النص المنسق
108
- # مخطط Matplotlib
 
109
  output_plot = gr.Plot(label="توزيع التعليقات (إيجابية مقابل سلبية)")
110
 
111
- # ربط الزر بالدالة وتحديد المدخلات والمخرجات
 
 
112
  submit_button.click(
113
- evaluate_playlist_local,
114
  inputs=[youtube_url_input, max_comments_input, max_workers_input],
115
  outputs=[output_text_box, output_plot]
116
  )
117
 
 
118
  demo.launch(debug=True)
 
1
  import gradio as gr
2
  import json
3
+ import matplotlib.pyplot as plt # استيراد مكتبة Matplotlib لرسم المخططات
4
  import numpy as np # قد نحتاجه لبعض العمليات الحسابية البسيطة
5
+ import matplotlib.font_manager as fm # استيراد font_manager للتحكم في الخطوط
6
+ import arabic_reshaper # لاستعادة شكل الحروف العربية
7
+ from bidi.algorithm import get_display # لضبط اتجاه النص RTL
8
 
9
+ # استيراد الدالة الرئيسية لتقييم قائمة تشغيل YouTube من ملف main.py
10
+ # تأكد أن ملف main.py موجود في نفس المجلد وأن النماذج (.pkl) متاحة له
11
  from main import evaluate_youtube_playlist_individually_same_method2
12
 
13
+ # =======================================================
14
+ # إعداد الخطوط لـ Matplotlib لدعم اللغة العربية
15
+ # =======================================================
16
+ # يجب التأكد من تثبيت خط عربي في بيئة Docker الخاصة بـ Hugging Face Space.
17
+ # مثال على التثبيت في Dockerfile: RUN apt-get update && apt-get install -y fonts-noto-arabic
18
+ # سنبحث عن خط Noto Sans Arabic، وإذا لم نجده، سيظل Matplotlib يستخدم الخط الافتراضي
19
+ font_path = None
20
+ # البحث عن خط Noto Sans Arabic أو Tajawal (يمكنك تغيير هذا بناءً على الخط الذي تفضله وتثبته)
21
+ for font in fm.findSystemFonts(fontpaths=None):
22
+ if 'NotoSansArabic' in font or 'Tajawal' in font or 'Amiri' in font:
23
+ font_path = font
24
+ break
25
+
26
+ if font_path:
27
+ # إضافة الخط العربي إلى قائمة الخطوط الافتراضية لـ Matplotlib
28
+ plt.rcParams['font.sans-serif'] = [fm.FontProperties(fname=font_path).get_name()] + plt.rcParams['font.sans-serif']
29
+ # تعطيل عرض علامة السالب كـ "صندوق" في بعض الخطوط
30
+ plt.rcParams['axes.unicode_minus'] = False
31
+ # تعيين عائلة الخط الافتراضية
32
+ plt.rcParams['font.family'] = 'sans-serif'
33
+ print(f"تم تعيين الخط العربي لـ Matplotlib: {font_path}") # لغرض التصحيح في السجلات
34
+ else:
35
+ print("تحذير: لم يتم العثور على خط عربي مناسب. قد لا يظهر النص العربي بشكل صحيح في المخطط.")
36
+ gr.Warning("تحذير: لم يتم العثور على خط عربي مناسب. قد لا يظهر النص العربي بشكل صحيح في المخطط.")
37
+
38
+
39
  async def evaluate_playlist_local(youtube_url: str, max_comments_per_video: int = 50, max_workers: int = 3):
40
  """
41
  تستدعي دالة تقييم قائمة تشغيل YouTube مباشرة من ملف main.py.
42
+ وتعيد النتائج النصية مجمعة في صندوق واحد، بالإضافة إلى مخطط Matplotlib يوضح نسب التعليقات.
43
  """
44
  error_message = ""
45
 
46
+ # تهيئة المخرجات الافتراضية في حالة وجود خطأ أو عدم وجود رابط
47
  default_text_output = "الرجاء إدخال رابط صحيح وتشغيل التقييم."
48
+ # إنشاء شكل Matplotlib فارغ لتجنب الأخطاء في حالة عدم وجود بيانات للمخطط
49
+ default_plot = plt.figure()
50
+ plt.close(default_plot) # إغلاق الشكل الافتراضي لمنع عرضه غير الضروري
51
 
52
+ # التحقق من أن الرابط ليس فارغًا قبل المتابعة
53
  if not youtube_url:
54
  error_message = "الرجاء إدخال رابط قائمة تشغيل أو فيديو يوتيوب."
55
+ gr.Warning(error_message) # عرض تحذير للمستخدم في واجهة Gradio
56
  return error_message, default_plot # إرجاع رسالة خطأ ومخطط فارغ
57
 
58
  try:
59
+ # استدعاء الدالة الرئيسية لمعالجة قائمة التشغيل/الفيديو
60
  result = await evaluate_youtube_playlist_individually_same_method2(
61
  youtube_url=youtube_url,
62
  max_comments_per_video=max_comments_per_video,
63
  max_workers=max_workers
64
  )
65
 
66
+ # التحقق مما إذا كانت الدالة قد أعادت خطأ
67
  if "error" in result:
68
  error_message = f"خطأ في المعالجة: {result['error']}"
69
+ gr.Error(error_message) # عرض الخطأ كرسالة خطأ حمراء في Gradio
70
  return error_message, default_plot # إرجاع رسالة الخطأ ومخطط فارغ
71
 
72
+ # استخراج النتائج المطلوبة من كائن JSON المُعاد
73
  overall_quality = result.get("overall_quality", "غير متوفر")
74
  composite_quality = result.get("composite_quality", "غير متوفر")
75
  composite_score = result.get("composite_score", "غير متوفر")
76
  percent_good_videos = result.get("percent_good_videos", "غير متوفر")
77
+ # التأكد من أن النسب عددية، وإلا سيتم تعيينها إلى 0.0
78
+ positive_ratio = result.get("positive_ratio", 0.0)
79
+ negative_ratio = result.get("negative_ratio", 0.0)
80
 
81
  # =======================================================
82
+ # 1. إعداد النص الموحد ليتم عرضه في صندوق واحد (باستخدام Markdown للتنسيق)
83
  # =======================================================
84
  formatted_output_text = f"""
85
  ## 📊 نتائج تقييم قائمة التشغيل:
 
90
  - **نسبة الفيديوهات الجيدة:** **{percent_good_videos}%**
91
  - **نسبة التعليقات الإيجابية:** **{positive_ratio}%**
92
  - **نسبة التعليقات السلبية:** **{negative_ratio}%**
 
 
93
  """
94
 
95
  # =======================================================
96
+ # 2. رسم المخطط باستخدام Matplotlib (مخطط دائري)
97
  # =======================================================
98
+ # إنشاء شكل ومحاور للمخطط بحجم مناسب
99
+ fig, ax = plt.subplots(figsize=(6, 4))
100
+
101
+ # النصوص العربية التي ستظهر على المخطط
102
+ labels_arabic = ['إيجابية', 'سلبية']
103
 
104
+ # تطبيق arabic_reshaper و get_display على التسميات العربية
105
+ # هذا هو الجزء الذي يحل مشكلة قلب النص وتقطيعه
106
+ reshaped_labels = [get_display(arabic_reshaper.reshape(label)) for label in labels_arabic]
107
+
108
+ sizes = [positive_ratio, negative_ratio] # قيم النسب المئوية
109
+ colors = ['#4CAF50', '#F44336'] # ألوان الشرائح (أخضر للإيجابي، أحمر للسلبي)
110
+ explode = (0.1, 0) # "تفجير" الشريحة الإيجابية قليلاً لإبرازها (اختياري)
111
 
112
+ # رسم المخطط الدائري باستخدام التسميات المصححة
113
+ ax.pie(sizes, explode=explode, labels=reshaped_labels, colors=colors,
114
  autopct='%1.1f%%', shadow=True, startangle=90, textprops={'fontsize': 12})
115
+ ax.axis('equal') # يضمن أن يكون المخطط دائريًا متناسبًا.
116
+
117
+ # تطبيق arabic_reshaper و get_display على عنوان المخطط
118
+ reshaped_title = get_display(arabic_reshaper.reshape('توزيع التعليقات'))
119
+ ax.set_title(reshaped_title, fontsize=14, pad=20)
 
 
 
120
 
121
+ # إغلاق الشكل لمنع Matplotlib من عرضه تلقائيًا في الخلفية، Gradio سيتولى العرض.
122
+ plt.close(fig)
123
 
124
+ # إرجاع النص المنسق والمخطط كناتجين للدالة
125
+ return formatted_output_text, fig
126
 
127
  except Exception as e:
128
+ # التقاط أي أخطاء غير متوقعة أثناء المعالجة
129
  error_message = f"حدث خطأ غير متوقع أثناء المعالجة: {e}"
130
+ gr.Error(error_message) # عرض رسالة الخطأ للمستخدم
131
+ return error_message, default_plot # إرجاع رسالة الخطأ ومخطط فارغ في حالة الفشل
132
 
133
 
134
+ # بناء واجهة Gradio باستخدام gr.Blocks للتحكم في التخطيط
135
  with gr.Blocks(title="تقييم قائمة تشغيل يوتيوب") as demo:
136
+ # عنوان ووصف الواجهة
137
  gr.Markdown("# 📊 تقييم جودة قائمة تشغيل يوتيوب")
138
  gr.Markdown("أدخل رابط قائمة تشغيل أو فيديو يوتيوب لتقييم جودتها بناءً على التحليلات والمشاعر.")
139
 
140
+ # تقسيم الواجهة إلى صفين (Row) لأعمدة المدخلات والمخرجات
141
  with gr.Row():
142
+ # العمود الأول للمدخلات
143
+ with gr.Column(scale=1):
144
  youtube_url_input = gr.Textbox(label="رابط قائمة تشغيل/فيديو يوتيوب", placeholder="الصق رابط يوتيوب هنا...", interactive=True)
145
  max_comments_input = gr.Slider(minimum=10, maximum=200, value=50, step=10, label="الحد الأقصى للتعليقات لكل فيديو", interactive=True)
146
  max_workers_input = gr.Slider(minimum=1, maximum=10, value=3, step=1, label="الحد الأقصى للعمال المتوازيين", interactive=True)
147
+ submit_button = gr.Button("🚀 تقييم قائمة التشغيل", variant="primary") # زر الإرسال الرئيسي
148
 
149
+ # العمود الثاني للمخرجات (بجعل scale=2 ليكون أكبر)
150
+ with gr.Column(scale=2):
151
+ # صندوق نصي واحد لعرض جميع النتائج النصية المنسقة
152
+ output_text_box = gr.Markdown(label="النتائج النهائية للتقييم")
153
+ # عنصر Gradio لعرض مخطط Matplotlib
154
  output_plot = gr.Plot(label="توزيع التعليقات (إيجابية مقابل سلبية)")
155
 
156
+ # ربط زر الإرسال بالدالة evaluate_playlist_local
157
+ # المدخلات هي عناصر واجهة المستخدم التي توفر البيانات للدالة
158
+ # المخرجات هي عناصر واجهة المستخدم التي ستعرض النتائج من الدالة
159
  submit_button.click(
160
+ evaluate_playlist_local,
161
  inputs=[youtube_url_input, max_comments_input, max_workers_input],
162
  outputs=[output_text_box, output_plot]
163
  )
164
 
165
+ # تشغيل واجهة Gradio
166
  demo.launch(debug=True)