walker11 commited on
Commit
2593a57
·
verified ·
1 Parent(s): b6043a7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +177 -231
app.py CHANGED
@@ -14,7 +14,7 @@ logger = logging.getLogger(__name__)
14
  class ArabicContentModerator:
15
  """
16
  Arabic Story Content Moderation Model using Deepseek API
17
- Checks for cultural violations and inappropriate content in AI-generated short stories
18
  """
19
 
20
  def __init__(self, deepseek_api_key: str = None):
@@ -34,150 +34,124 @@ class ArabicContentModerator:
34
  "Content-Type": "application/json"
35
  }
36
 
37
- # New moderation prompt tailored for AI-generated short stories
38
  self.moderation_prompt = """
39
- أنت ناقد أدبي محترف متخصص في الأدب العربي والثقافة الإسلامية، ومهمتك مراجعة نصوص القصص القصيرة المولدة بواسطة الذكاء الاصطناعي بدقة فائقة للتأكد من أنها قصص أدبية أصيلة، مكتوبة باللغة العربية الفصحى، وملتزمة بالقيم الثقافية والدينية العربية الإسلامية. ركز على سياق كل كلمة وجملة لتحديد المعنى الحقيقي، حيث قد تحمل كلمة حساسة معنى مختلفًا حسب السياق. اقرأ النص بعمق، وتحقق من عناصر السرد الأدبي، وتأكد من خلو النص من أي محتوى غير أدبي أو مخالف.
40
-
41
- ### معايير المراجعة الصارمة:
42
-
43
- #### أولاً: التحقق من طبيعة النص الأدبي
44
- 1. **يجب أن يكون النص قصة أدبية أصيلة** تحتوي على:
45
- - لغة عربية فصحى صحيحة خالية من الأخطاء النحوية والإملائية.
46
- - شخصيات محددة أسماء أو أوصاف واضحة).
47
- - حبكة سردية متماسكة (بداية، تصاعد، ذروة، خاتمة).
48
- - حوار طبيعي أو وصف حسي يعكس الأسلوب الأدبي.
49
- - تقنيات سردية متنوعة (وصف، حوار، سرد، مونولوج داخلي).
50
- - صراع واضح يدفع الأحداث ويحافظ على اهتمام القارئ.
51
- 2. **النصوص المرفوضة تشمل**:
52
- - الأخبار: "أعلنت الحكومة..."، "وفقًا لتقارير...".
53
- - التعليقات: "أرى أن..."، "برأيي...".
54
- - المواد الدراسية: "تعريف السرد..."، "في هذا الفصل...".
55
- - القوائم: "الخطوات: 1-... 2-...".
56
- - الإعلانات: "اشترِ الآن..."، "منتج جديد...".
57
- - النصوص العامية أو المختلطة بلهجات محلية بشكل غالب.
58
- 3. **اختبار الأدبية**:
59
- - يجب أن يحمل النص طابعًا إبداعيًا، يثير العاطفة أو التأمل.
60
- - يُرفض إذا كان تقريرًا واقعيًا أو سردًا جافًا بدون إبداع.
61
-
62
- #### ثانيًا: الالتزام بالقيم الدينية والثقافية
63
- 1. **المحظورات الدينية** (فحص دقيق للسياق):
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
- 2. **المحظورات الطائفية**:
92
- - ضد السنة: "السنة نواصب"، "السلفيون كفار"، "الوهابية ضلال".
93
- - ضد الشيعة: "الشيعة رافضة"، "عبدة القبور"، "مجوس".
94
- - ضد الصوفية: "الصوفية مشركون"، "دراويش ضالون".
95
- - التكفير: "المسلمون كفار"، "الطوائف باطلة".
96
- 3. **المحظورات الثقافية**:
97
- - تحقير التقاليد: "عادات بالية"، "تخلف عربي"، "جهل الأجداد".
98
- - تحقير المرأة: "النساء ناقصات"، "البنت عار"، "المرأة فتنة".
99
- - التحريض العرقي: "العرب جهلة"، "الأكراد خونة"، "الأمازيغ همج".
100
- 4. **القيم الإيجابية**:
101
- - يجب أن يعكس النص قيمًا مثل الصدق، العدل، الرحمة، أو التعاون.
102
- - يُفضل تضمين دروس غير مباشرة تعزز الأخلاق الحميدة.
103
-
104
- #### ثالثًا: الألفاظ النابية والشتائم
105
- 1. **جميع اللهجات العربية** (يُرفض أي استخدام حتى لو كان سياقيًا):
106
- - **المشرقية**: "كس"، "منيوك"، "نعل"، "شرموطة"، "تبن".
107
- - **المغربية/الجزائرية**: "قحبة"، "نيك"، "طبون"، "كحلة"، "زب".
108
- - **المصرية**: "كسم"، "وسخة"، "نيكني"، "شرموط"، "كس".
109
- - **الخليجية**: "منيج"، "خرا"، "تبن ريلك"، "أبوي فيك".
110
- - **العراقية**: "كوس"، "منيوج"، "خرا"، "جحش"، "تبن".
111
- - **الشامية**: "كسك"، "أير"، "نايك"، "منيوك"، "شرموط".
112
- - **السودانية**: "كداب"، "كلب"، "عرص"، "حيوان"، "خايب".
113
- - **اليمنية**: "لحس"، "منيك"، "قحبة"، "كس "عاهرة".
114
- 2. **الشتائم الاجتماعية**:
115
- - سب الأمهات: "أمك شرموطة"، "كس أمك"، "تبن أمك".
116
- - سب الآباء: "أبوك حيوان"، "نعل أبوك"، "أبو الوسخ".
117
- - سب الأخوات: "أختك قحبة"، "نيك أختك"، "أختك عاهرة".
118
- - عامة: لب"، "عرص"، "خول"، "حقير "خنزير"، "حمار".
119
- 3. **الألفاظ المبتذلة**:
120
- - "تفو"، "يع"، "قرف"، "نتن"، "عفن"، "وسخ"، "قذر".
121
-
122
- #### رابعًا: المحتوى الجنسي والأخلاقي
123
- 1. **المحظورات الجنسية**:
124
- - وصف الأعضاء: "زب"، "كس "طيز"، "بزاز"، "فرج"، "صدر".
125
- - الأفعال: "نيك"، "لحس"، "مص"، "دخل فيها"، "مارس".
126
- - الإثارة: "ساخن"، "شهوة"، "هيجان"، "رغبة"، "إثارة".
127
- - العلاقات المحرمة: "عشيقة "حبيبي"، "خليلة"، "متعة".
128
- - الشذوذ: "مثلي"، "سحاق"، "لوطي اذ"، "خنثى".
129
- 2. **التلميحات الجنسية**:
130
- - "اقترب منها بحنان"، "لمسها بشغف"، "قبلها بعمق".
131
- 3. **التحرش أو الإيحاء الأخلاقي**:
132
- - "تبعها في الشارع"، "نظرات غريبة "همس لها سرًا".
133
-
134
- #### خامسًا: العنف والمحتوى المؤذي
135
- 1. **العنف المفرط**:
136
- - "قطع رأسه"، "مزق جسده"، "عذبه حتى الموت"، "سحله".
137
- 2. **تمجيد العنف**:
138
- - "القتل شرف"، "الانتقام واجب"، "الدم يطهر".
139
- 3. **إيذاء النفس**:
140
- - "اقتل نفسك"، "انتحر "اجرح نفسك"، "أذي ذاتك".
141
- 4. **العنف المقنع**:
142
- - "علمه درسًا"، "جعله يندم"، "أوجعه بشدة".
143
-
144
- #### سادسًا: المحتوى السياسي والاجتماعي الحساس
145
- 1. **التحريض الطائفي**:
146
- - "السنة كفار"، "الشيعة مرتدون"، "الصوفية ضالون".
147
- 2. **التحريض العرقي**:
148
- - "العرب جهلة"، "الأكراد خونة"، "الأمازيغ همج".
149
- 3. **إثارة الفتنة**:
150
- - "اقتلوا الطائفة الأخرى"، مروا مقدساتهم".
151
-
152
- #### سابعًا: التحريض على المخالفات
153
- 1. **المخدرات**:
154
- - "جرب الحشيش"، "اشرب خمر"، "المخدرات ممتعة".
155
- 2. **الفسق**:
156
- - "اتبع شهواتك"، "الحرام لذيذ"، "العيب حلو".
157
- 3. **تشجيع الجريمة**:
158
- - "السرقة سهلة"، "اضرب بقوة"، "اخفِ الدليل".
159
-
160
- #### ثامنًا: التعبيرات الساخرة المحظورة
161
- 1. **سخرية من الدين**:
162
- - "ههه دين"، "خرافات المسلمين"، "دين الصحراء".
163
- 2. **سخرية من الثقافة**:
164
- - "تخلف عربي"، "عادات قديمة"، "جهل موروث".
165
- 3. **سخرية من القيم**:
166
- - "شرف مزيف"، "أخلاق منافقة"، "قيم كاذبة".
167
-
168
- #### تاسعًا: النصوص المشبوهة في السياق
169
- 1. **التلميحات الخفية**:
170
- - "فعل بها شيئًا"، "لعب معها"، "استمتع بها".
171
- 2. **التعبيرات الغامضة**:
172
- - "اقترب منها كثيرًا"، "جلسا معًا في الظلام".
173
-
174
- ### تعليمات الإجابة:
175
- - إذا كان النص قصة أدبية أصيلة مكتوبة بالفصحى، يحتوي على عناصر السرد (شخصيات، حبكة، حوار، وصف)، يعكس قيمًا إيجابية، وخالٍ من أي انتهاك للمعايير أعلاه، أجب بـ **"true"** فقط.
176
- - إذا انتهك النص أي معيار (غير أدبي، عامية، شتائم، محتوى جنسي، عنف، تحريض، سخرية، إلخ)، أو كان خبرًا، تعليقًا، أو مادة دراسية، أجب بـ **"no"** فقط.
177
- - الإجابة يجب أن تكون **"true"** أو **"no"** فقط، بدون نص إضافي.
178
- - راجع النص بدقة لتجنب رفض نص سليم أو قبول نص مخالف.
179
-
180
- ### النص المطلوب مراجعته:
181
  """
182
 
183
  def _call_deepseek_api(self, story_content: str) -> Dict[str, Any]:
@@ -196,7 +170,7 @@ class ArabicContentModerator:
196
  "messages": [
197
  {
198
  "role": "system",
199
- "content": "أنت ناقد أدبي محترف متخصص في الأدب العربي والثقافة الإسلامية. مهمتك مراجعة النصوص بدقة للتأكد من التزامها بالقيم الدينية والثقافية العربية الإسلامية وكونها قصصًا أدبية أصيلة."
200
  },
201
  {
202
  "role": "user",
@@ -204,7 +178,7 @@ class ArabicContentModerator:
204
  }
205
  ],
206
  "max_tokens": 10,
207
- "temperature": 0.0,
208
  "stream": False
209
  }
210
 
@@ -225,7 +199,7 @@ class ArabicContentModerator:
225
  logger.error(f"Exception calling Deepseek API: {str(e)}")
226
  return {"error": str(e)}
227
 
228
- def _validate_story_format(self, story_content: str) -> tuple[bool, str]:
229
  """
230
  Enhanced validation of story format and content
231
 
@@ -233,54 +207,51 @@ class ArabicContentModerator:
233
  story_content: Story content to validate
234
 
235
  Returns:
236
- Tuple of (Boolean indicating if format is valid, reason for invalidity if False)
237
  """
238
  if not story_content or not isinstance(story_content, str):
239
- return False, "المحتوى فارغ أو ليس نصًا"
240
 
241
- # Check minimum length
242
  if len(story_content.strip()) < 50:
243
- return False, "النص قصير جدًا ليكون قصة أدبية"
244
 
245
- # Check for Arabic characters
246
  arabic_pattern = re.compile(r'[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]')
247
  arabic_chars = len(arabic_pattern.findall(story_content))
248
 
249
- if arabic_chars < len(story_content.strip()) * 0.8:
250
- return False, "النص يحتوي على محتوى عربي غير كافٍ أو يستخدم لهجة عامية"
 
251
 
252
- # Quick pre-screening for obvious violations
253
  content_lower = story_content.lower()
254
 
255
- # Check for non-literary content patterns
256
- non_literary_patterns = [
257
- r'أعلنت\s*(?:الحكومة|السلطات|وزارة)', # News
258
- r'(?:برأيي|أعتقد\s*أن|من\s*وجهة\s*نظري)', # Opinions
259
- r'(?:تعريف|في\s*هذا\s*الفصل|يشرح\s*الدرس)', # Study materials
260
- r'أسباب\s*(?:النجاح|الفشل|المشكلة)\s*:\s*\d+', # Lists
261
- r'(?:اشترِ|تسوق|منتج\s*جديد|خصم\s*\d+%)' # Advertisements
262
- ]
263
-
264
- for pattern in non_literary_patterns:
265
- if re.search(pattern, content_lower):
266
- return False, "النص غير أدبي (أخبار، تعليقات، مواد دراسية، إعلانات)"
267
-
268
- # Check for profanity and religious violations
269
- violation_patterns = [
270
  # Sexual profanity
271
- r'\b(?:كس|زب|نيك|منيوك|شرموط|قحب|لحس|مص|طيز|بزاز|تبن|نعل|كوس|أير|منايك|خرا|كداب|عرص|خول|حيوان)\b',
 
 
 
272
 
273
- # Religious violations
274
- r'(?:الله\s*(?:كذاب|وهم|غبي)|لعن\s*الله|تبا\s*لله|يلعن\s*رب|القرآن\s*(?:كذب|مزور|خرافات)|محمد\s*(?:كذاب|دجال)|لعنة\s*على\s*محمد|أبو\s*بكر\s*منافق|عمر\s*ظالم|علي\s*مخادع|الصحابة\s*كذابون|الصلاة\s*مضيعة|رمضان\s*تخلف|الكعبة\s*(?:صنم|حجر)|المسيح\s*كذاب|الإنجيل\s*محرف|موسى\s*دجال|التوراة\s*مزورة|لا\s*إله|الجنة\s*وهم|النار\s*خيال|القيامة\s*كذبة|لعنة\s*الله|بيوت\s*خرافة|السنة\s*نواصب|الشيعة\s*رافضة|الصوفية\s*مشركون|الوهابيون\s*كفار)'
 
 
 
 
 
 
 
 
275
  ]
276
 
277
- for pattern in violation_patterns:
278
  if re.search(pattern, content_lower):
279
- if 'الله' in pattern or 'قرآن' in pattern or 'محمد' in pattern or 'الصلاة' in pattern or 'رمضان' in pattern or 'الكعبة' in pattern or 'المسيح' in pattern or 'موسى' in pattern or 'السنة' in pattern or 'الشيعة' in pattern:
280
- return False, "انتهاك ديني أو طائفي"
281
- return False, "ألفاظ نابية أو محتوى غير أخلاقي"
282
 
283
- return True, ""
284
 
285
  def moderate_story(self, story_content: str) -> Dict[str, Any]:
286
  """
@@ -293,13 +264,11 @@ class ArabicContentModerator:
293
  Dictionary with moderation result
294
  """
295
  # Enhanced validation
296
- is_valid, validation_reason = self._validate_story_format(story_content)
297
- if not is_valid:
298
  return {
299
  "approved": False,
300
  "response": "no",
301
- "reason": validation_reason,
302
- "violation_type": "format_validation" if "غير أدبي" in validation_reason or "قصير" in validation_reason or "عربي غير كافٍ" in validation_reason else "content_violation",
303
  "timestamp": datetime.now().isoformat()
304
  }
305
 
@@ -315,7 +284,6 @@ class ArabicContentModerator:
315
  "approved": False,
316
  "response": "no",
317
  "reason": "خطأ في خدمة المراجعة",
318
- "violation_type": "api_error",
319
  "error": api_response["error"],
320
  "timestamp": datetime.now().isoformat()
321
  }
@@ -324,10 +292,10 @@ class ArabicContentModerator:
324
  # Extract the moderation decision
325
  ai_response = api_response.get("choices", [{}])[0].get("message", {}).get("content", "").strip().lower()
326
 
327
- # Clean the response
328
  ai_response = re.sub(r'[^\w]', '', ai_response)
329
 
330
- # Determine if content is approved
331
  approved = ai_response == "true"
332
  response_value = "true" if approved else "no"
333
 
@@ -340,27 +308,9 @@ class ArabicContentModerator:
340
  }
341
 
342
  if not approved:
343
- result["reason"] = "المحتوى ينتهك القواعد المجتمعية أو الثقافية أو الدينية، أو أنه ليس قصة أدبية أصيلة بالفصحى"
344
- result["violation_type"] = "content_violation"
345
- # Categorize violation
346
- content_lower = cleaned_content.lower()
347
- if any(re.search(pattern, content_lower) for pattern in [
348
- r'(?:الله\s*(?:كذاب|وهم|غبي)|لعن\s*الله|تبا\s*لله|يلعن\s*رب|القرآن\s*(?:كذب|مزور|خرافات)|محمد\s*(?:كذاب|دجال)|لعنة\s*على\s*محمد|أبو\s*بكر\s*منافق|عمر\s*ظالم|علي\s*مخادع|الصحابة\s*كذابون|الصلاة\s*مضيعة|رمضان\s*تخلف|الكعبة\s*(?:صنم|حجر)|المسيح\s*كذاب|الإنجيل\s*محرف|موسى\s*دجال|التوراة\s*مزورة|لا\s*إله|الجنة\s*وهم|النار\s*خيال|القيامة\s*كذبة|لعنة\s*الله|بيوت\s*خرافة|السنة\s*نواصب|الشيعة\s*رافضة|الصوفية\s*مشركون|الوهابيون\s*كفار)'
349
- ]):
350
- result["violation_type"] = "religious_violation"
351
- elif any(re.search(pattern, content_lower) for pattern in [
352
- r'\b(?:كس|زب|نيك|منيوك|شرموط|قحب|لحس|مص|طيز|بزاز|تبن|نعل|كوس|أير|منايك|خرا|كداب|عرص|خول|حيوان)\b'
353
- ]):
354
- result["violation_type"] = "profanity_violation"
355
- elif any(re.search(pattern, content_lower) for pattern in [
356
- r'أعلنت\s*(?:الحكومة|السلطات|وزارة)|(?:برأيي|أعتقد\s*أن|من\s*وجهة\s*نظري)|(?:تعريف|في\s*هذا\s*الفصل|يشرح\s*الدرس)|أسباب\s*(?:النجاح|الفشل|المشكلة)\s*:\s*\d+|(?:اشترِ|تسوق|منتج\s*جديد|خصم\s*\d+%)'
357
- ]):
358
- result["violation_type"] = "non_literary_content"
359
- elif arabic_chars < len(cleaned_content.strip()) * 0.8:
360
- result["violation_type"] = "non_classical_arabic"
361
  else:
362
- result["reason"] = "المحتوى مقبول ويلتزم بالمعايير الأدبية والثقافية"
363
- result["violation_type"] = None
364
 
365
  logger.info(f"Moderation completed: {response_value} for content of length {len(cleaned_content)}")
366
  return result
@@ -371,15 +321,15 @@ class ArabicContentModerator:
371
  "approved": False,
372
  "response": "no",
373
  "reason": "خطأ في معالجة نتيجة المراجعة",
374
- "violation_type": "processing_error",
375
  "error": str(e),
376
  "timestamp": datetime.now().isoformat()
377
  }
378
 
 
379
  # Flask application
380
  app = Flask(__name__)
381
 
382
- # Initialize the moderator
383
  try:
384
  moderator = ArabicContentModerator()
385
  logger.info("Arabic Content Moderator initialized successfully")
@@ -394,27 +344,31 @@ def home():
394
  "service": "مراجع المحتوى الأدبي العربي المحسن",
395
  "service_en": "Enhanced Arabic Literary Content Moderator",
396
  "version": "2.0.0",
397
- "description": "AI-powered professional literary critic for AI-generated Arabic short stories with strict cultural and religious compliance",
398
- "description_ar": "ناقد أدبي محترف مدعوم بالذكاء الاصطناعي للقصص العربية القصيرة المولدة آليًا مع التزام صارم بالقيم الثقافية والدينية",
399
  "endpoints": {
400
  "/health": "Health check",
401
  "/moderate": "POST - Moderate single story",
402
  "/moderate/batch": "POST - Moderate multiple stories"
403
  },
404
  "features": [
405
- "Strict validation of classical Arabic usage",
406
- "Comprehensive detection of non-literary content",
407
- "Enhanced religious and cultural compliance",
408
- "Multi-dialect profanity detection",
409
- "Context-aware violation analysis",
410
- "Positive value reinforcement",
411
- "Professional literary standards enforcement"
 
 
 
 
412
  ],
413
  "usage": {
414
  "moderate": {
415
  "method": "POST",
416
  "payload": {"story_content": "Arabic story text"},
417
- "response": {"approved": "boolean", "response": "true/no", "reason": "string", "violation_type": "string or null"}
418
  }
419
  },
420
  "status": "healthy" if moderator else "service unavailable"
@@ -445,7 +399,6 @@ def moderate_content():
445
  "approved": true/false,
446
  "response": "true"/"no",
447
  "reason": "reason in Arabic",
448
- "violation_type": "string or null",
449
  "timestamp": "ISO timestamp"
450
  }
451
  """
@@ -454,8 +407,7 @@ def moderate_content():
454
  "error": "خدمة المراجعة غير متوفرة - لم يتم تكوين مفتاح API",
455
  "error_en": "Moderation service not available - API key not configured",
456
  "approved": False,
457
- "response": "no",
458
- "violation_type": "service_unavailable"
459
  }), 500
460
 
461
  try:
@@ -466,8 +418,7 @@ def moderate_content():
466
  "error": "محتوى القصة مفقود في الطلب",
467
  "error_en": "Missing story_content in request",
468
  "approved": False,
469
- "response": "no",
470
- "violation_type": "invalid_request"
471
  }), 400
472
 
473
  story_content = data['story_content']
@@ -482,7 +433,6 @@ def moderate_content():
482
  "error_en": "Internal server error",
483
  "approved": False,
484
  "response": "no",
485
- "violation_type": "server_error",
486
  "details": str(e)
487
  }), 500
488
 
@@ -499,8 +449,7 @@ def moderate_batch():
499
  if not moderator:
500
  return jsonify({
501
  "error": "خدمة المراجعة غير متوفرة - لم يتم تكوين مفتاح API",
502
- "error_en": "Moderation service not available - API key not configured",
503
- "violation_type": "service_unavailable"
504
  }), 500
505
 
506
  try:
@@ -509,16 +458,14 @@ def moderate_batch():
509
  if not data or 'stories' not in data:
510
  return jsonify({
511
  "error": "مصفوفة القصص مفقودة في الطلب",
512
- "error_en": "Missing stories array in request",
513
- "violation_type": "invalid_request"
514
  }), 400
515
 
516
  stories = data['stories']
517
  if not isinstance(stories, list):
518
  return jsonify({
519
  "error": "القصص يجب أن تكون في شكل مصفوفة",
520
- "error_en": "Stories must be an array",
521
- "violation_type": "invalid_request"
522
  }), 400
523
 
524
  results = []
@@ -550,11 +497,10 @@ def moderate_batch():
550
  return jsonify({
551
  "error": "خطأ داخلي في الخادم",
552
  "error_en": "Internal server error",
553
- "violation_type": "server_error",
554
  "details": str(e)
555
  }), 500
556
 
557
  if __name__ == '__main__':
558
  # For local testing
559
- port = int(os.environ.get('PORT', 7860))
560
  app.run(host='0.0.0.0', port=port, debug=False)
 
14
  class ArabicContentModerator:
15
  """
16
  Arabic Story Content Moderation Model using Deepseek API
17
+ Checks for cultural violations and inappropriate content
18
  """
19
 
20
  def __init__(self, deepseek_api_key: str = None):
 
34
  "Content-Type": "application/json"
35
  }
36
 
37
+ # Enhanced professional literary critic moderation prompt with comprehensive examples
38
  self.moderation_prompt = """
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
+ ثالثاً - الألفاظ النابية والسب بجميع اللهجات العربية:
95
+ المشرقية: "كس أختك"، "منيوك"، "تبن أم..."، "نعل أبوك"، بو شرموطة"
96
+ المغربية/الجزائرية: "قحبة"، "نيك"، "زبي في..."، "كحلة"، "شرموطة"، "طبون أمك"
97
+ المصرية: "كسم اللي خلفك"، بن الوسخة"، "ابن الشرموطة"، "نيكني"، "كسك"
98
+ الخليجية: "منيج"، "أبوي فيك"، "خرا عليك"، "تبن ريلك"، "منايك"
99
+ العراقية: "كوس أمك"، "منيوج"، "ابن الجحش"، "خرا"، "تبن أبوك"
100
+ الشامية: "كسك"، "نايك"، "أير فيك"، "ابن الشرموطة"، "منيوك أختك"
101
+ السودانية: داب"، ايب"، "حيوان"، "ابن الكلب"، "عرص"
102
+ اليمنية: "لحس "منيك"، "قحبة "كسك"، اهرة"
103
+
104
+ رابعاً - المحتوى الجنسي والأخلاقي (رقابة صارمة) - أمثلة محظورة:
105
+ وصف الأعضاء التناسلية: "زب"، "كس"، "طيز"، در"، "بزاز"، "فرج"
106
+ الأفعال الجنسية: "نيك"، "لحس"، "مص"، "دخل فيها"، "ركب عليها"، "مارس الجنس"
107
+ الإثارة الجنسية: "مثير"، "ساخن"، "شهوة"، "رغبة جنسية"، "انتصاب"، "هيجان"
108
+ العلاقات المحرمة: "حبيبي"، "عشيقة"، "خليلة"، "صديق بفوائد"، "متعة"
109
+ الشذوذ الجنسي: "مثلي"، "لوطي"، "سحاقية"، "شاذ"، "خنثى"
110
+
111
+ خامساً - العنف والمحتوى المؤذي - أمثلة محظورة:
112
+ العنف المفرط: "قطع رأسه"، "مزق جسده"، "عذبه حتى الموت"، "سحله"
113
+ تمجيد القتل: "القتل شرف"، "الانتقام واجب"، "الدم يغسل العار"
114
+ إيذاء النفس: "اقتل نفسك"، "انتحر"، "اجرح نفسك"، "أذي نفسك"
115
+
116
+ سادساً - المحتوى السياسي والاجتماعي الحساس - أمثلة محظورة:
117
+ التحريض الطائفي: "السنة كفار"، "الشيعة مرتدون"، "الصوفية ضالون"
118
+ التحريض العرقي: "العرب متخلفون"، "الأكراد خونة"، "البربر همج"
119
+ إثارة الفتنة: "اقتلوا الطائفة الأخرى"، "احرقوا مساجدهم"، "دمروا مقدساتهم"
120
+
121
+ سابعاً - السب والشتائم الاجتماعية بجميع اللهجات:
122
+ سب الأمهات: "أم الخبيث"، "أمك شرموطة"، "تبن أم اللي خلفك"، "كس أم..."
123
+ سب الآباء: "أبوك حيوان"، "تبن أبوك"، "أبو الوسخ"، "نعل أبو..."
124
+ سب الأخوات: "أختك عاهرة"، "كس أختك"، "أختك قحبة"، "نيك أختك"
125
+ الشتائم العامة: "ابن الكلب"، "ابن الحرام"، "عرص"، "خول "معفن"، "وسخ"، "نذل"، "حقير"، "خنزير"، "كلب"، "حمار"، "بهيمة"
126
+
127
+ ثامناً - تعبيرات الاستخفاف والسخرية المحظورة:
128
+ من الدين: "ههههه دين"، "دين الصحراء"، "خرافات المسلمين"
129
+ من التقاليد: "عادات بالية"، "تخلف عربي"، "جهل الأجداد"
130
+ من القيم: "شرف كاذب"، "أخلاق مصطنعة"، "قيم منافقة"
131
+
132
+ تاسعاً - الكلمات المبتذلة والعامية المرفوضة:
133
+ ▪ ألفاظ مبتذلة: "تفو"، "يع"، "قرف"، "وسخ"، "قذر"، "نتن"، "عفن"
134
+ تعبيرات جنسية مخفية: "عمل شيء"، "فعل به الفاحشة"، "لعب معها"، "استمتع بها"
135
+
136
+ عاشراً - التحريض والدعوة للمخالفات:
137
+ المخدرات: "خذ حبة"، "اشرب خمر"، "جرب الحشيش"، "المخدرات رائعة"
138
+ الفسق: "اتبع شهواتك"، "لا تلتزم بالحلال"، "الحرام لذيذ"، "العيب حلو"
139
+
140
+ أحد عشر - العبارات المشبوهة في السياق:
141
+ التلميحات الجنسية: "اقترب منها أكثر"، "لمسها بحنان"، "قبلها بشغف"
142
+ العنف المقنع: "علمه درساً لن ينساه"، "جعله يندم"، "أوجعه"
143
+
144
+ إثنا عشر - التعبيرات المسيئة للمرأة:
145
+ تحقير المرأة: "المرأة ناقصة عقل"، "النساء عورة"، "المرأة فتنة"، "البنت عار"
146
+
147
+ انتبه: هذه الأمثلة للتوضيح فقط. أي نص يحتوي على مثل هذه التعبيرات أو ما يشبهها أو يحمل نفس المعنى بأي لهجة عربية يجب رفضه فوراً.
148
+
149
+ تعليمات الإجابة:
150
+ - إذا كان النص قصة أدبية حقيقية وملتزمة بجميع المعايير وخالية من جميع الأمثلة المحظورة أعلاه، أجب بـ "true" فقط
151
+ - إذا انتهك النص أي معيار أو احتوى على أي من الأمثلة المحظورة أو ما يشبهها، أجب بـ "no" فقط
152
+ - يجب أن تكون إجابتك "true" أو "no" فقط بدون أي نص إضافي
153
+
154
+ النص المطلوب مراجعته:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  """
156
 
157
  def _call_deepseek_api(self, story_content: str) -> Dict[str, Any]:
 
170
  "messages": [
171
  {
172
  "role": "system",
173
+ "content": "أنت ناقد أدبي محترف متخصص في الأدب العربي والثقافة الإسلامية. مهمتك مراجعة النصوص بدقة شديدة للتأكد من التزامها بالقيم الدينية والثقافية العربية الإسلامية ومن كونها قصصاً أدبية حقيقية."
174
  },
175
  {
176
  "role": "user",
 
178
  }
179
  ],
180
  "max_tokens": 10,
181
+ "temperature": 0.0, # Changed to 0.0 for more consistent results
182
  "stream": False
183
  }
184
 
 
199
  logger.error(f"Exception calling Deepseek API: {str(e)}")
200
  return {"error": str(e)}
201
 
202
+ def _validate_story_format(self, story_content: str) -> bool:
203
  """
204
  Enhanced validation of story format and content
205
 
 
207
  story_content: Story content to validate
208
 
209
  Returns:
210
+ Boolean indicating if format is valid
211
  """
212
  if not story_content or not isinstance(story_content, str):
213
+ return False
214
 
215
+ # Check minimum length (at least 50 characters for a meaningful story)
216
  if len(story_content.strip()) < 50:
217
+ return False
218
 
219
+ # Check for Arabic characters (must have substantial Arabic content)
220
  arabic_pattern = re.compile(r'[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]')
221
  arabic_chars = len(arabic_pattern.findall(story_content))
222
 
223
+ # Arabic characters should be at least 30% of total characters
224
+ if arabic_chars < len(story_content.strip()) * 0.3:
225
+ return False
226
 
227
+ # Quick pre-screening for obvious violations (before API call)
228
  content_lower = story_content.lower()
229
 
230
+ # Check for common profanity patterns across dialects AND religious violations
231
+ profanity_patterns = [
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  # Sexual profanity
233
+ r'\bكس\b', r'\bزب\b', r'\bنيك\b', r'\bمنيوك\b', r'\bشرموط\b',
234
+ r'\bقحب\b', r'\bلحس\b', r'\bمص\b', r'\bطيز\b', r'\bبزاز\b',
235
+ r'\bتبن\b', r'\bنعل\b', r'\bكوس\b', r'\bأير\b', r'\bمنايك\b',
236
+ r'\bخرا\b', r'\bكداب\b', r'\bعرص\b', r'\bخول\b', r'\bحيوان\b',
237
 
238
+ # Religious violations and blasphemy
239
+ r'الله كذاب', r'لعن الله', r'تبا لله', r'يلعن رب', r'الله غبي',
240
+ r'القرآن كذب', r'كتاب مزور', r'خرافات القرآن', r'قرآن مؤلف',
241
+ r'محمد كذاب', r'الرسول دجال', r'نبي كاذب', r'لعنة على محمد',
242
+ r'أبو بكر منافق', r'عمر ظالم', r'علي مخادع', r'الصحابة كذابون',
243
+ r'الصلاة مضيعة', r'رمضان تخلف', r'الحج طقوس', r'الكعبة صنم',
244
+ r'المسيح كذاب', r'الإنجيل محرف', r'موسى دجال', r'التوراة مزورة',
245
+ r'لا إله', r'الله وهم', r'الجنة وهم', r'النار خيال', r'القيامة كذبة',
246
+ r'لعنة الله', r'الله يلعنك', r'ملعون من رب', r'بيوت خرافة',
247
+ r'السنة نواصب', r'الشيعة رافضة', r'الصوفية مشركون', r'الوهابيون كفار'
248
  ]
249
 
250
+ for pattern in profanity_patterns:
251
  if re.search(pattern, content_lower):
252
+ return False
 
 
253
 
254
+ return True
255
 
256
  def moderate_story(self, story_content: str) -> Dict[str, Any]:
257
  """
 
264
  Dictionary with moderation result
265
  """
266
  # Enhanced validation
267
+ if not self._validate_story_format(story_content):
 
268
  return {
269
  "approved": False,
270
  "response": "no",
271
+ "reason": "فشل في التحقق من صحة تنسيق القصة أو عدم وجود محتوى عربي كافٍ",
 
272
  "timestamp": datetime.now().isoformat()
273
  }
274
 
 
284
  "approved": False,
285
  "response": "no",
286
  "reason": "خطأ في خدمة المراجعة",
 
287
  "error": api_response["error"],
288
  "timestamp": datetime.now().isoformat()
289
  }
 
292
  # Extract the moderation decision
293
  ai_response = api_response.get("choices", [{}])[0].get("message", {}).get("content", "").strip().lower()
294
 
295
+ # Clean the response (remove any extra whitespace or characters)
296
  ai_response = re.sub(r'[^\w]', '', ai_response)
297
 
298
+ # Determine if content is approved (be more strict)
299
  approved = ai_response == "true"
300
  response_value = "true" if approved else "no"
301
 
 
308
  }
309
 
310
  if not approved:
311
+ result["reason"] = "المحتوى ينتهك القواعد المجتمعية أو الثقافية أو الدينية، أو أنه ليس قصة أدبية حقيقية"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
  else:
313
+ result["reason"] = "المحتوى مقبول ويلتزم بالمعايير المطلوبة"
 
314
 
315
  logger.info(f"Moderation completed: {response_value} for content of length {len(cleaned_content)}")
316
  return result
 
321
  "approved": False,
322
  "response": "no",
323
  "reason": "خطأ في معالجة نتيجة المراجعة",
 
324
  "error": str(e),
325
  "timestamp": datetime.now().isoformat()
326
  }
327
 
328
+
329
  # Flask application
330
  app = Flask(__name__)
331
 
332
+ # Initialize the moderator (API key will be set via environment variable)
333
  try:
334
  moderator = ArabicContentModerator()
335
  logger.info("Arabic Content Moderator initialized successfully")
 
344
  "service": "مراجع المحتوى الأدبي العربي المحسن",
345
  "service_en": "Enhanced Arabic Literary Content Moderator",
346
  "version": "2.0.0",
347
+ "description": "AI-powered professional literary critic for Arabic short stories with comprehensive dialect-aware moderation",
348
+ "description_ar": "ناقد أدبي محترف مدعوم بالذكاء الاصطناعي للقصص العربية القصيرة مع مراجعة شاملة لجميع اللهجات العربية",
349
  "endpoints": {
350
  "/health": "Health check",
351
  "/moderate": "POST - Moderate single story",
352
  "/moderate/batch": "POST - Moderate multiple stories"
353
  },
354
  "features": [
355
+ "Comprehensive profanity detection across all Arabic dialects",
356
+ "Enhanced religious and cultural compliance checking with specific examples",
357
+ "Professional literary criticism standards",
358
+ "Strict content type validation (stories only)",
359
+ "Multi-dialect offensive content detection (Gulf, Levantine, Egyptian, Maghrebi, Iraqi, Sudanese, Yemeni)",
360
+ "Comprehensive religious blasphemy detection (Islam, Christianity, Judaism, other faiths)",
361
+ "Advanced sectarian and inter-religious conflict prevention",
362
+ "Takfir and religious defamation blocking",
363
+ "Advanced pre-screening before API calls",
364
+ "Arabic language purity validation",
365
+ "Context-aware violation detection"
366
  ],
367
  "usage": {
368
  "moderate": {
369
  "method": "POST",
370
  "payload": {"story_content": "Arabic story text"},
371
+ "response": {"approved": "boolean", "response": "true/no"}
372
  }
373
  },
374
  "status": "healthy" if moderator else "service unavailable"
 
399
  "approved": true/false,
400
  "response": "true"/"no",
401
  "reason": "reason in Arabic",
 
402
  "timestamp": "ISO timestamp"
403
  }
404
  """
 
407
  "error": "خدمة المراجعة غير متوفرة - لم يتم تكوين مفتاح API",
408
  "error_en": "Moderation service not available - API key not configured",
409
  "approved": False,
410
+ "response": "no"
 
411
  }), 500
412
 
413
  try:
 
418
  "error": "محتوى القصة مفقود في الطلب",
419
  "error_en": "Missing story_content in request",
420
  "approved": False,
421
+ "response": "no"
 
422
  }), 400
423
 
424
  story_content = data['story_content']
 
433
  "error_en": "Internal server error",
434
  "approved": False,
435
  "response": "no",
 
436
  "details": str(e)
437
  }), 500
438
 
 
449
  if not moderator:
450
  return jsonify({
451
  "error": "خدمة المراجعة غير متوفرة - لم يتم تكوين مفتاح API",
452
+ "error_en": "Moderation service not available - API key not configured"
 
453
  }), 500
454
 
455
  try:
 
458
  if not data or 'stories' not in data:
459
  return jsonify({
460
  "error": "مصفوفة القصص مفقودة في الطلب",
461
+ "error_en": "Missing stories array in request"
 
462
  }), 400
463
 
464
  stories = data['stories']
465
  if not isinstance(stories, list):
466
  return jsonify({
467
  "error": "القصص يجب أن تكون في شكل مصفوفة",
468
+ "error_en": "Stories must be an array"
 
469
  }), 400
470
 
471
  results = []
 
497
  return jsonify({
498
  "error": "خطأ داخلي في الخادم",
499
  "error_en": "Internal server error",
 
500
  "details": str(e)
501
  }), 500
502
 
503
  if __name__ == '__main__':
504
  # For local testing
505
+ port = int(os.environment.get('PORT', 7860))
506
  app.run(host='0.0.0.0', port=port, debug=False)