alomari7 commited on
Commit
109193e
·
verified ·
1 Parent(s): 5501114

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +180 -678
app.py CHANGED
@@ -1,710 +1,212 @@
1
-
2
  # =============================================================================
3
-
4
  # Final Code for the Professional Interface (English Version)
5
-
6
  # =============================================================================
7
-
8
  import gradio as gr
9
-
10
  import joblib
11
-
12
  import re
13
-
14
  import pandas as pd
15
-
16
  from datetime import datetime
17
 
18
-
19
-
20
  # --- 1. Load Model and Knowledge Base ---
21
-
22
  try:
23
-
24
-     model = joblib.load('halal_classifier_model.pkl')
25
-
26
- except
27
-
28
-  FileNotFoundError:
29
-
30
-     print("Error: 'halal_classifier_model.pkl' not found.")
31
-
32
-     model = None
33
-
34
-
35
 
36
  # --- Use your complete knowledge base here ---
37
-
38
  comprehensive_ingredients_db = {
39
-
40
-
41
-
42
- #--------------------------------------------------------------------------
43
-
44
- #القسم الأول: مكونات محرمة بشكل قاطع (Haram)
45
-
46
- #--------------------------------------------------------------------------
47
-
48
-
49
-
50
- #--- مشتقات الخنزير (Pork Derivatives) ---
51
-
52
- 'pork': {'status': 'حرام', 'reason': 'لحم الخنزير محرم بالنص الصريح في القرآن الكريم.'},
53
-
54
- 'bacon': {'status': 'حرام', 'reason': 'نوع من لحم الخنزير المقدد والمعالج.'},
55
-
56
- 'ham': {'status': 'حرام', 'reason': 'لحم فخذ الخنزير، وهو محرم.'},
57
-
58
- 'lard': {'status': 'حرام', 'reason': 'دهن الخنزير، وهو محرم.'},
59
-
60
- 'swine': {'status': 'حرام', 'reason': 'اسم آخر للخنزير، وهو محرم.'},
61
-
62
- 'hog': {'status': 'حرام', 'reason': 'اسم آخر للخنزير، وهو محرم.'},
63
-
64
- 'boar': {'status': 'حرام', 'reason': 'الخنزير البري، وهو محرم.'},
65
-
66
- 'porcine': {'status': 'حرام', 'reason': 'كلمة لاتينية تعني أن المصدر من الخنزير.'},
67
-
68
- 'speck': {'status': 'حرام', 'reason': 'نوع من اللحم المقدد من الخنزير.'},
69
-
70
- 'schwein': {'status': 'حرام', 'reason': "كلمة ألمانية تعني 'خنزير'."},
71
-
72
- 'prosciutto': {'status': 'حرام', 'reason': 'نوع من لحم الخنزير الإيطالي المجفف.'},
73
-
74
-
75
-
76
- # --- الكحول والمسكرات (Alcohol and Intoxicants) ---
77
-
78
- 'alcohol': {'status': 'حرام', 'reason': 'كل مسكر خمر، وكل خمر حرام.'},
79
-
80
- 'ethanol': {'status': 'حرام', 'reason': 'الاسم الكيميائي للكحول المسكر.'},
81
-
82
- 'ethyl alcohol': {'status': 'حرام', 'reason': 'الاسم الكيميائي للكحول المسكر.'},
83
-
84
- 'wine': {'status': 'حرام', 'reason': 'الخمر، وهو محرم بالنص الصريح.'},
85
-
86
- 'beer': {'status': 'حرام', 'reason': 'نوع من المشروبات الكحولية المسكرة.'},
87
-
88
- 'liquor': {'status': 'حرام', 'reason': 'مصطلح عام للمشروبات الكحولية المقطرة.'},
89
-
90
- 'liqueur': {'status': 'حرام', 'reason': 'نوع من المشروبات الكحولية المحلاة.'},
91
-
92
- 'brandy': {'status': 'حرام', 'reason': 'نوع من المشروبات الكحولية المسكرة.'},
93
-
94
- 'cognac': {'status': 'حرام', 'reason': 'نوع من البراندي، وهو مسكر.'},
95
-
96
- 'gin': {'status': 'حرام', 'reason': 'نوع من المشروبات الكحولية المسكرة.'},
97
-
98
- 'rum': {'status': 'حرام', 'reason': 'نوع من المشروبات الكحولية المسكرة.'},
99
-
100
- 'vodka': {'status': 'حرام', 'reason': 'نوع من المشروبات الكحولية المسكرة.'},
101
-
102
- 'whisky': {'status': 'حرام', 'reason': 'نوع من المشروبات الكحولية المسكرة.'},
103
-
104
- 'whiskey': {'status': 'حرام', 'reason': 'نوع من المشروبات الكحولية المسكرة.'},
105
-
106
- 'champagne': {'status': 'حرام', 'reason': 'نوع من النبيذ الفوار المسكر.'},
107
-
108
- 'sake': {'status': 'حرام', 'reason': 'نبيذ الأرز الياباني، وهو مسكر.'},
109
-
110
- 'vermouth': {'status': 'حرام', 'reason': 'نبيذ مقوى ومنكّه، وهو مسكر.'},
111
-
112
- 'sherry': {'status': 'حرام', 'reason': 'نوع من النبيذ المقوى، وهو مسكر.'},
113
-
114
- 'port': {'status': 'حرام', 'reason': 'نوع من النبيذ المقوى، وهو مسكر.'},
115
-
116
- 'absinthe': {'status': 'حرام', 'reason': 'نوع من المشروبات الكحولية المسكرة.'},
117
-
118
-
119
-
120
- # --- حيوانات ومواد محرمة أخرى ---
121
-
122
- 'blood': {'status': 'حرام', 'reason': 'الدم المسفوح محرم بالنص الصريح.'},
123
-
124
- 'carrion': {'status': 'حرام', 'reason': 'الميتة (الحيوان الذي لم يذكَّ بالطريقة الشرعية).'},
125
-
126
- 'carmine': {'status': 'حرام', 'reason': 'صبغة (E120) تُستخرج من الحشرات، وهي محرمة عند جمهور العلماء.'},
127
-
128
- 'cochineal': {'status': 'حرام', 'reason': 'اسم آخر لصبغة كا��مين (E120) المستخرجة من الحشرات.'},
129
-
130
- 'e120': {'status': 'حرام', 'reason': 'الرمز الأوروبي لصبغة كارمين المستخرجة من الحشرات.'},
131
-
132
- 'e-120': {'status': 'حرام', 'reason': 'الرمز الأوروبي لصبغة كارمين المستخرجة من الحشرات.'},
133
-
134
- 'ci 75470': {'status': 'حرام', 'reason': 'الرمز الدولي لصبغة كارمين المستخرجة من الحشرات.'},
135
-
136
-
137
-
138
- #--------------------------------------------------------------------------
139
-
140
- # القسم الثاني: مكونات مشبوهة (Doubtful / Mashbooh)
141
-
142
- # هذه المكونات تحتاج إلى تدقيق للمصدر للتأكد من حليتها.
143
-
144
- #--------------------------------------------------------------------------
145
-
146
-
147
-
148
- # --- جيلاتين ومشتقاته ---
149
-
150
- 'gelatin': {'status': 'مشتبه فيه (يميل للتحريم)', 'reason': 'مصدره الغالب حيواني (خنزير أو غير مذكى). يتطلب شهادة حلال موثوقة.'},
151
-
152
- 'e441': {'status': 'مشتبه فيه (يميل للتحريم)', 'reason': 'الرمز الأوروبي القديم للجيلاتين. مصدره الغالب حيواني (خنزير أو غير مذكى).'},
153
-
154
- 'e-441': {'status': 'مشتبه فيه (يميل للتحريم)', 'reason': 'الرمز الأوروبي القديم للجيلاتين. مصدره الغالب حيواني (خنزير أو غير مذكى).'},
155
-
156
-
157
-
158
- # --- دهون، شحوم، ومستحلبات ذات مصدر دهني ---
159
-
160
- 'animal fat': {'status': 'مشتبه فيه', 'reason': 'دهن حيواني. يجب التأكد من أنه من مصدر مذكى شرعاً.'},
161
-
162
- 'animal shortening': {'status': 'مشتبه فيه', 'reason': 'دهن حيواني. يجب التأكد من أنه من مصدر مذكى شرعاً.'},
163
-
164
- 'fat': {'status': 'مشتبه فيه', 'reason': 'كلمة عامة للدهن. إذا لم يحدد المصدر (نباتي)، فهو مشبوه.'},
165
-
166
- 'tallow': {'status': 'مشتبه فيه', 'reason': 'الشحم الحيواني. يجب التأكد من أنه من مصدر مذكى شرعاً.'},
167
-
168
- 'shortening': {'status': 'مشتبه فيه', 'reason': 'دهن صناعي، قد يحتوي على دهون حيوانية. يجب التأكد من المصدر.'},
169
-
170
- 'margarine': {'status': 'مشتبه فيه', 'reason': 'قد يحتوي على دهون حيوانية أو مستحلبات مشبوهة المصدر.'},
171
-
172
- 'glycerin': {'status': 'مشتبه فيه', 'reason': 'قد يكون مصدره دهن حيواني أو نباتي. يجب التأكد من المصدر النباتي.'},
173
-
174
- 'glycerine': {'status': 'مشتبه فيه', 'reason': 'اسم آخر للجليسرين، قد يكون مصدره دهن حيواني أو نباتي.'},
175
-
176
- 'glycerol': {'status': 'مشتبه فيه', 'reason': 'اسم آخر للجليسرين (E422)، قد يكون مصدره دهن حيواني أو نباتي.'},
177
-
178
- 'e422': {'status': 'مشتبه فيه', 'reason': 'الرمز الأوروبي للجليسرين/الجليسرول. قد يكون مصدره دهن حيواني أو نباتي.'},
179
-
180
- 'e-422': {'status': 'مشتبه فيه', 'reason': 'الرمز الأوروبي للجليسرين/الجليسرول. قد يكون مصدره دهن حيواني أو نباتي.'},
181
-
182
- 'mono and diglycerides': {'status': 'مشتبه فيه', 'reason': 'مستحلبات (E471) قد تكون من مصدر دهني حيواني أو نباتي. يجب التحقق.'},
183
-
184
- 'monoglyceride': {'status': 'مشتبه فيه', 'reason': 'جزء من مستحلبات (E471). قد يكون مصدره دهني حيواني أو نباتي.'},
185
-
186
- 'diglyceride': {'status': 'مشتبه فيه', 'reason': 'جزء من مستحلبات (E471). قد يكون مصدره دهني حيواني أو نباتي.'},
187
-
188
- 'emulsifier': {'status': 'مشتبه فيه', 'reason': 'كلمة عامة للمستحلبات. العديد منها مشبوه المصدر (حيواني).'},
189
-
190
- 'emulsifiers': {'status': 'مشتبه فيه', 'reason': 'كلمة عامة للمستحلبات. العديد منها مشبوه المصدر (حيواني).'},
191
-
192
- 'stearic acid': {'status': 'مشتبه فيه', 'reason': 'حمض دهني (E570). قد يكون من مصدر حيواني أو نباتي.'},
193
-
194
- 'e570': {'status': 'مشتبه فيه', 'reason': 'الرمز الأوروبي لحمض الستياريك. قد يكون من مصدر حيواني أو نباتي.'},
195
-
196
- 'e-570': {'status': 'مشتبه فيه', 'reason': 'الرمز الأوروبي لحمض الستياريك. قد يكون من مصدر حيواني أو نباتي.'},
197
-
198
- 'calcium stearate': {'status': 'مشتبه فيه', 'reason': 'ملح حمض الستياريك. قد يكون مصدر الحمض دهن حيواني.'},
199
-
200
- 'magnesium stearate': {'status': 'مشتبه فيه', 'reason': 'ملح حمض الستياريك (E572). قد يكون مصدر الحمض دهن حيواني.'},
201
-
202
- 'e572': {'status': 'مشتبه فيه', 'reason': 'الرمز الأوروبي لـ Magnesium stearate. قد يكون مصدره دهن حيواني.'},
203
-
204
- 'e-572': {'status': 'مشتبه فيه', 'reason': 'الرمز الأوروبي لـ Magnesium stearate. قد يكون مصدره دهن حيواني.'},
205
-
206
-
207
-
208
- # --- بروتينات، إنزيمات، وأحماض أمينية ---
209
-
210
- 'collagen': {'status': 'مشتبه فيه', 'reason': 'بروتين حيواني المصدر، يخضع لنفس حكم الجيلاتين.'},
211
-
212
- 'hydrolyzed animal protein': {'status': 'مشتبه فيه', 'reason': 'بروتين حيواني متحلل. يجب التأكد من مصدر الحيوان وطريقة ذبحه.'},
213
-
214
- 'pepsin': {'status': 'مشتبه فيه', 'reason': 'إنزيم يستخرج غالباً من معدة الخنزير. يجب التحقق من المصدر النباتي أو الميكروبي.'},
215
-
216
- 'enzymes': {'status': 'مشتبه فيه', 'reason': 'قد تكون من مصدر حيواني محرم، أو بكتيري أو نباتي. يتطلب التحقق.'},
217
-
218
- 'enzyme': {'status': 'مشتبه فيه', 'reason': 'قد يكون من مصدر حيواني محرم، أو بكتيري أو نباتي. يتطلب التحقق.'},
219
-
220
- 'protease': {'status': 'مشتبه فيه', 'reason': 'نوع من الإنزيمات، قد يكون من مصدر حيواني محرم.'},
221
-
222
- 'rennet': {'status': 'مشتبه فيه', 'reason': 'منفحة الجبن، قد تكون من حيوان غير مذكى شرعاً.'},
223
-
224
- 'animal rennet': {'status': 'مشتبه فيه', 'reason': 'منفحة من مصدر حيواني، يجب التأكد من طريقة الذبح.'},
225
-
226
- 'whey': {'status': 'مشتبه فيه', 'reason': 'شرش اللبن، حكمه يعتمد على حكم المنفحة المستخدمة في صناعة الجبن.'},
227
-
228
- 'whey powder': {'status': 'مشتبه فيه', 'reason': 'مسحوق شرش اللبن، حكمه يعتمد على حكم المنفحة المستخدمة.'},
229
-
230
- 'casein': {'status': 'مشتبه فيه', 'reason': 'بروتين الحليب. قد تستخدم في معالجته إنزيمات مشبوهة كالمنفحة.'},
231
-
232
- 'caseinates': {'status': 'مشتبه فيه', 'reason': 'أملاح بروتين الحليب. قد تستخدم في معالجتها إنزيمات مشبوهة.'},
233
-
234
- 'amino acids': {'status': 'مشتبه فيه', 'reason': 'بعض الأحماض الأمينية (مثل ل-سيستين) قد تكون من مصدر حيواني أو آدمي.'},
235
-
236
- 'l-cysteine': {'status': 'مشتبه فيه', 'reason': 'حمض أميني (E920) يمكن استخراجه من شعر الإنسان (حرام) أو ريش الدواجن أو مصادر صناعية.'},
237
-
238
- 'e920': {'status': 'مشتبه فيه', 'reason': 'الرمز الأوروبي لـ ل-سيستين. قد يستخرج من شعر الإنسان أو ريش الدواجن.'},
239
-
240
- 'e-920': {'status': 'مشتبه فيه', 'reason': 'الرمز الأوروبي لـ ل-سيستين. قد يستخرج من شعر الإنسان أو ريش الدواجن.'},
241
-
242
- 'e921': {'status': 'مشتبه فيه', 'reason': 'الرمز الأوروبي لمشتقات ل-سيستين. حكمها مماثل لـ E920.'},
243
-
244
- 'e-921': {'status': 'مشتبه فيه', 'reason': 'الرمز الأوروبي لمشتقات ل-سيستين. حكمها مماثل لـ E920.'},
245
-
246
-
247
-
248
- # --- نكهات، مرق، ومكونات عامة ---
249
-
250
- 'stock': {'status': 'مشتبه فيه', 'reason': 'مرق قد يتم تحضيره من لحوم أو عظام حيوانات غير مذكاة.'},
251
-
252
- 'broth': {'status': 'مشتبه فيه', 'reason': 'مرق قد يتم تحضيره من لحوم أو عظام حيوانات غير مذكاة.'},
253
-
254
- 'bouillon': {'status': 'مشتبه فيه', 'reason': 'مكعبات مرق قد تحتوي على دهون أو بروتينات حيوانية مشبوهة.'},
255
-
256
- 'natural flavors': {'status': 'مشتبه فيه', 'reason': 'قد تحتوي على كحول كمذيب أو مشتقات حيوانية. تحتاج لتدقيق المصدر.'},
257
-
258
- 'flavouring': {'status': 'مشتبه فيه', 'reason': 'قد تحتوي على كحول كمذيب أو مشتقات حيوانية. تحتاج لتدقيق المصدر.'},
259
-
260
- 'vanilla extract': {'status': 'مشتبه فيه', 'reason': 'خلاصة الفانيليا التقليدية تحتوي على نسبة من الكحول كمذيب.'},
261
-
262
-
263
-
264
- # --- مواد مضافة أخرى مشبوهة (Additives) ---
265
-
266
- 'shellac': {'status': 'مشتبه فيه', 'reason': 'إفراز صمغي من حشرة اللاك (E904). هناك خلاف فقهي حول حكمه.'},
267
-
268
- 'e904': {'status': 'مشتبه فيه', 'reason': 'الرمز الأوروبي للشيلاك. إفراز حشري يوجد خلاف فقهي في حكمه.'},
269
-
270
- 'e-904': {'status': 'مشتبه فيه', 'reason': 'الرمز الأوروبي للشيلاك. إفراز حشري يوجد خلاف فقهي في حكمه.'},
271
-
272
- 'e542': {'status': 'مشتبه فيه', 'reason': 'فوسفات العظام. مصدره عظ��م الحيوانات التي غالباً ما تكون غير مذكاة.'},
273
-
274
- 'e-542': {'status': 'مشتبه فيه', 'reason': 'فوسفات العظام. مصدره عظام الحيوانات التي غالباً ما تكون غير مذكاة.'},
275
-
276
- 'edible bone phosphate': {'status': 'مشتبه فيه', 'reason': 'مصدره عظام الحيوانات التي غالباً ما تكون غير مذكاة.'},
277
-
278
- 'e631': {'status': 'مشتبه فيه', 'reason': 'مُحسِّن نكهة (Sodium inosinate)، قد يُنتج من اللحوم أو الأسماك. يتطلب التحقق.'},
279
-
280
- 'e-631': {'status': 'مشتبه فيه', 'reason': 'مُحسِّن نكهة (Sodium inosinate)، قد يُنتج من اللحوم أو الأسماك. يتطلب التحقق.'},
281
-
282
- 'e635': {'status': 'مشتبه فيه', 'reason': 'مُحسِّن نكهة (Sodium 5\'-ribonucleotide)، قد يكون من مصدر حيواني.'},
283
-
284
- 'e-635': {'status': 'مشتبه فيه', 'reason': 'مُحسِّن نكهة (Sodium 5\'-ribonucleotide)، قد يكون من مصدر حيواني.'},
285
-
286
- 'e640': {'status': 'مشتبه فيه', 'reason': 'حمض أميني (Glycine)، قد يكون مشتقًا من الجيلاتين. يتطلب التحقق.'},
287
-
288
- 'e-640': {'status': 'مشتبه فيه', 'reason': 'حمض أميني (Glycine)، قد يكون مشتقًا من الجيلاتين. يتطلب التحقق.'},
289
-
290
-
291
-
292
- # --- مجموعة المستحلبات والأملاح الدهنية المشبوهة ---
293
-
294
- # السبب العام: قد تكون مشتقة من دهون حيوانية. تتطلب التحقق من المصدر أو شهادة حلال.
295
-
296
- 'e304': {'status': 'مشتبه فيه', 'reason': 'مادة مضافة (Ascorbyl palmitate)، قد تكون من مصدر دهني حيواني.'},
297
-
298
- 'e-304': {'status': 'مشتبه فيه', 'reason': 'مادة مضافة (Ascorbyl palmitate)، قد تكون من مصدر دهني حيواني.'},
299
-
300
- 'e322': {'status': 'مشتبه فيه', 'reason': 'مادة الليسيثين. غالباً من الصويا أو البيض (حلال)، ولكن يوضع في الشبهة للاحتياط التام.'},
301
-
302
- 'e-322': {'status': 'مشتبه فيه', 'reason': 'مادة الليسيثين. غالباً من الصويا أو البيض (حلال)، ولكن يوضع في الشبهة للاحتياط التام.'},
303
-
304
- 'e325': {'status': 'مشتبه فيه', 'reason': 'مادة مضافة (Sodium Lactate)، قد تكون من مصدر حيواني.'},
305
-
306
- 'e-325': {'status': 'مشتبه فيه', 'reason': 'مادة مضافة (Sodium Lactate)، قد تكون من مصدر حيواني.'},
307
-
308
- 'e326': {'status': 'مشتبه فيه', 'reason': 'مادة مضافة (Potassium Lactate)، قد تكون من مصدر حيواني.'},
309
-
310
- 'e-326': {'status': 'مشتبه فيه', 'reason': 'مادة مضافة (Potassium Lactate)، قد تكون من مصدر حيواني.'},
311
-
312
- 'e327': {'status': 'مشتبه فيه', 'reason': 'مادة مضافة (Calcium Lactate)، قد تكون من مصدر حيواني.'},
313
-
314
- 'e-327': {'status': 'مشتبه فيه', 'reason': 'مادة مضافة (Calcium Lactate)، قد تكون من مصدر حيواني.'},
315
-
316
- 'e430': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
317
-
318
- 'e-430': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
319
-
320
- 'e431': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
321
-
322
- 'e-431': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
323
-
324
- 'e432': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Polysorbate 20)، قد يكون من مصدر دهني حيواني.'},
325
-
326
- 'e-432': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Polysorbate 20)، قد يكون من مصدر دهني حيواني.'},
327
-
328
- 'e433': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Polysorbate 80)، قد يكون من مصدر دهني حيواني.'},
329
-
330
- 'e-433': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Polysorbate 80)، قد يكون من مصدر دهني حيواني.'},
331
-
332
- 'e434': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Polysorbate 40)، قد يكون من مصدر دهني حيواني.'},
333
-
334
- 'e-434': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Polysorbate 40)، قد يكون من مصدر دهني حيواني.'},
335
-
336
- 'e435': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Polysorbate 60)، قد يكون من مصدر دهني حيواني.'},
337
-
338
- 'e-435': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Polysorbate 60)، قد يكون من مصدر دهني حيواني.'},
339
-
340
- 'e436': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
341
-
342
- 'e-436': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
343
-
344
- 'e442': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Ammonium phosphatides)، قد يكون من مصدر دهني حيواني.'},
345
-
346
- 'e-442': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Ammonium phosphatides)، قد يكون من مصدر دهني حيواني.'},
347
-
348
- 'e470': {'status': 'مشتبه فيه', 'reason': 'أملاح الأحماض الدهنية، قد يكون مصدرها حيوانياً.'},
349
-
350
- 'e-470': {'status': 'مشتبه فيه', 'reason': 'أملاح الأحماض الدهنية، قد يكون مصدرها حيوانياً.'},
351
-
352
- 'e470a': {'status': 'مشتبه فيه', 'reason': 'أملاح الأحماض الدهنية (صوديوم، بوتاسيوم، كالسيوم)، قد يكون مصدرها حيوانياً.'},
353
-
354
- 'e-470a': {'status': 'مشتبه فيه', 'reason': 'أملاح الأحماض الدهنية (صوديوم، بوتاسيوم، كالسيوم)، قد يكون مصدرها حيوانياً.'},
355
-
356
- 'e470b': {'status': 'مشتبه فيه', 'reason': 'أملاح المغنيسيوم للأحماض الدهنية، قد يكون مصدرها حيوانياً.'},
357
-
358
- 'e-470b': {'status': 'مشتبه فيه', 'reason': 'أملاح المغنيسيوم للأحماض الدهنية، قد يكون مصدرها حيوانياً.'},
359
-
360
- 'e471': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Mono- and diglycerides)، قد يكون من مصدر دهني حيواني أو نباتي.'},
361
-
362
- 'e-471': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Mono- and diglycerides)، قد يكون من مصدر دهني حيواني أو نباتي.'},
363
-
364
- 'e472': {'status': 'مشتبه فيه', 'reason': 'استرات متنوعة من E471، قد يكون مصدرها دهني حيواني.'},
365
-
366
- 'e-472': {'status': 'مشتبه فيه', 'reason': 'استرات متنوعة من E471، قد يكون مصدرها دهني حيواني.'},
367
-
368
- 'e472a': {'status': 'مشتبه فيه', 'reason': 'استرات من E471، قد يكون مصدرها دهني حيواني.'},
369
-
370
- 'e-472a': {'status': 'مشتبه فيه', 'reason': 'استرات من E471، قد يكون مصدرها دهني حيواني.'},
371
-
372
- 'e472b': {'status': 'مشتبه فيه', 'reason': 'استرات من E471، قد يكون مصدرها دهني حيواني.'},
373
-
374
- 'e-472b': {'status': 'مشتبه فيه', 'reason': 'استرات من E471، قد يكون مصدرها دهني حيواني.'},
375
-
376
- 'e472c': {'status': 'مشتبه فيه', 'reason': 'استرات من E471، قد يكون مصدرها دهني حيواني.'},
377
-
378
- 'e-472c': {'status': 'مشتبه فيه', 'reason': 'استرات من E471، قد يكون مصدرها دهني حيواني.'},
379
-
380
- 'e472d': {'status': 'مشتبه فيه', 'reason': 'استرات من E471، قد يكون مصدرها دهني حيواني.'},
381
-
382
- 'e-472d': {'status': 'مشتبه فيه', 'reason': 'استرات من E471، قد يكون مصدرها دهني حيواني.'},
383
-
384
- 'e472e': {'status': 'مشتبه فيه', 'reason': 'استرات من E471، قد يكون مصدرها دهني حيواني.'},
385
-
386
- 'e-472f': {'status': 'مشتبه فيه', 'reason': 'استرات من E471، قد يكون مصدرها دهني حيواني.'},
387
-
388
- 'e-472f': {'status': 'مشتبه فيه', 'reason': 'استرات من E471، قد يكون مصدرها دهني حيواني.'},
389
-
390
- 'e473': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Sucrose esters)، قد يكون من مصدر دهني حيواني.'},
391
-
392
- 'e-473': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Sucrose esters)، قد يكون من مصدر دهني حيواني.'},
393
-
394
- 'e474': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Sucroglycerides)، قد يكون من مصدر دهني حيواني.'},
395
-
396
- 'e-474': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Sucroglycerides)، قد يكون من مصدر دهني حيواني.'},
397
-
398
- 'e475': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Polyglycerol esters)، قد يكون من مصدر دهني حيواني.'},
399
-
400
- 'e-475': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Polyglycerol esters)، قد يكون من مصدر دهني حيواني.'},
401
-
402
- 'e476': {'status': 'مشتبه فيه', 'reason': 'مستحلب (PGPR)، قد يكون من مصدر دهني حيواني.'},
403
-
404
- 'e-476': {'status': 'مشتبه فيه', 'reason': 'مستحلب (PGPR)، قد يكون من مصدر دهني حيواني.'},
405
-
406
- 'e477': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
407
-
408
- 'e-477': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
409
-
410
- 'e478': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
411
-
412
- 'e-478': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
413
-
414
- 'e479b': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
415
-
416
- 'e-479b': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
417
-
418
- 'e481': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
419
-
420
- 'e-481': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
421
-
422
- 'e482': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
423
-
424
- 'e-482': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
425
-
426
- 'e483': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
427
-
428
- 'e-483': {'status': 'مشتبه فيه', 'reason': 'مستحلب مشتق من أحماض دهنية قد تكون حيوانية المصدر.'},
429
-
430
- 'e491': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Sorbitan monostearate)، قد يكون من مصدر دهني حيواني.'},
431
-
432
- 'e-491': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Sorbitan monostearate)، قد يكون من مصدر دهني حيواني.'},
433
-
434
- 'e492': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Sorbitan tristearate)، قد يكون من مصدر دهني حيواني.'},
435
-
436
- 'e-492': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Sorbitan tristearate)، قد يكون من مصدر دهني حيواني.'},
437
-
438
- 'e493': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Sorbitan monolaurate)، قد يكون من مصدر دهني حيواني.'},
439
-
440
- 'e-493': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Sorbitan monolaurate)، قد يكون من مصدر دهني حيواني.'},
441
-
442
- 'e494': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Sorbitan monooleate)، قد يكون من مصدر دهني حيواني.'},
443
-
444
- 'e-494': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Sorbitan monooleate)، قد يكون من مصدر دهني حيواني.'},
445
-
446
- 'e495': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Sorbitan monopalmitate)، قد يكون من مصدر دهني حيواني.'},
447
-
448
- 'e-495': {'status': 'مشتبه فيه', 'reason': 'مستحلب (Sorbitan monopalmitate)، قد يكون من مصدر دهني حيواني.'},
449
-
450
  }
451
 
452
-
453
-
454
  FEEDBACK_FILE = 'feedback_log_en.csv'
455
 
456
-
457
-
458
  # --- 2. Define Backend Functions (Now in English) ---
459
-
460
  def predict_and_explain(text_input):
461
-
462
-     if not model or not text_input.strip():
463
-
464
-         return "", "", gr.update(visible=False)
465
-
466
-
467
-
468
-     prediction = model.predict([text_input])[0]
469
-
470
-     # Translate prediction for consistency if your model outputs Arabic
471
-
472
-     if prediction == "حرام":
473
-
474
-         prediction = "Haram"
475
-
476
-     elif prediction == "حلال":
477
-
478
-         prediction = "Halal"
479
-
480
-     else: # Handles all "Doubtful" cases
481
-
482
-         prediction = "Doubtful"
483
-
484
-         
485
-
486
-     reason = "No direct reason found in the knowledge base."
487
-
488
-     
489
-
490
-     if prediction != 'Halal':
491
-
492
-         for ingredient, details in comprehensive_ingredients_db.items():
493
-
494
-             if re.search(r'\b' + re.escape(ingredient) + r'\b', text_input, re.IGNORECASE):
495
-
496
-                 reason = details['reason']
497
-
498
-                 break
499
-
500
-     else:
501
-
502
-         reason = "No clear forbidden or doubtful ingredients were found based on the current database."
503
-
504
-     
505
-
506
-     return prediction, reason, gr.update(visible=True)
507
-
508
-
509
 
510
  def handle_feedback(original_text, model_prediction, user_correction, user_comment):
511
-
512
-     try:
513
-
514
-         feedback_data = pd.DataFrame({
515
-
516
-             'timestamp': [datetime.now()],
517
-
518
-             'original_text': [original_text],
519
-
520
-             'model_prediction': [model_prediction],
521
-
522
-             'user_correction': [user_correction],
523
-
524
-             'user_comment': [user_comment]
525
-
526
-         })
527
-
528
-         try:
529
-
530
-             pd.read_csv(FEEDBACK_FILE)
531
-
532
-             write_header = False
533
-
534
-         except FileNotFoundError:
535
-
536
-             write_header = True
537
-
538
-             
539
-
540
-         feedback_data.to_csv(FEEDBACK_FILE, mode='a', header=write_header, index=False, encoding='utf-8-sig')
541
-
542
-         return "✅ Thank you for your contribution! Your feedback has been saved."
543
-
544
-     except Exception as e:
545
-
546
-         return f"❌ An error occurred while saving feedback: {e}"
547
-
548
-
549
 
550
  # --- 3. Build the Themed Interface with gr.Blocks ---
551
-
552
- # Using gr.themes.Soft() for a clean look that adapts to light/dark mode
553
-
554
  theme = gr.themes.Soft(
555
-
556
-     primary_hue="blue",
557
-
558
-     secondary_hue="blue",
559
-
560
  ).set(
561
-
562
-     button_primary_background_fill='*primary_500',
563
-
564
-     button_primary_background_fill_hover='*primary_600',
565
-
566
  )
567
 
568
-
569
-
570
  with gr.Blocks(theme=theme) as iface:
571
-
572
-     
573
-
574
-     # <-- MODIFICATION 1: Title and Description in English -->
575
-
576
-     gr.Markdown(
577
-
578
-         """
579
-
580
-         <div style="text-align: center; font-family: 'Arial', sans-serif; padding-bottom: 15px;">
581
-
582
-             <h1 style="color: #2c3e50;">Yaqeen</h1>
583
-
584
-             <p style="font-size: 1.2em; color: #34495e;">
585
-
586
-                 An intelligent system to classify food products by analyzing their ingredients.
587
-
588
-             </p>
589
-
590
-         </div>
591
-
592
-         """
593
-
594
-     )
595
-
596
-     
597
-
598
-     with gr.Row():
599
-
600
-         with gr.Column(scale=2):
601
-
602
-             text_input = gr.Textbox(lines=8, label="Enter Product Name & Ingredients", placeholder="e.g., Milk Chocolate, Ingredients: Sugar, cocoa butter, milk powder, soy lecithin E322, vanilla flavor...")
603
-
604
-             submit_btn = gr.Button("🔍 Analyze Product", variant="primary")
605
-
606
-         
607
-
608
-         with gr.Column(scale=3):
609
-
610
-             status_output = gr.Textbox(label="Predicted Status", interactive=False)
611
-
612
-             reason_output = gr.Textbox(label="Potential Reason", interactive=False)
613
-
614
-
615
-
616
-     with gr.Group(visible=False) as feedback_box:
617
-
618
-         gr.Markdown("---")
619
-
620
-         gr.Markdown("<h3 style='text-align:center;'>Was this prediction correct?</h3>")
621
-
622
-         with gr.Row():
623
-
624
-             correction_dropdown = gr.Dropdown(
625
-
626
-                 choices=["Halal", "Haram", "Doubtful"],
627
-
628
-                 label="If not, what is the correct status?"
629
-
630
-             )
631
-
632
-             comment_box = gr.Textbox(label="Additional Comments (Optional)", placeholder="e.g., This product contains Halal beef gelatin...")
633
-
634
-         
635
-
636
-         feedback_btn = gr.Button("📩 Submit Feedback")
637
-
638
-         feedback_status = gr.Textbox(label="Submission Status", interactive=False)
639
-
640
-
641
-
642
-     gr.Examples(
643
-
644
-         examples=[
645
-
646
-             ["Prosciutto crudo, E252"],
647
-
648
-             ["Cheddar cheese, water, salt, rennet, whey"],
649
-
650
-             ["Gummy candy with sugar, corn syrup, gelatin, citric acid, carmine color"],
651
-
652
-         ],
653
-
654
-         inputs=text_input
655
-
656
-     )
657
-
658
-     
659
-
660
-     # <-- MODIFICATION 2: Credits in English -->
661
-
662
-     gr.Markdown(
663
-
664
-         """
665
-
666
-         <hr>
667
-
668
-         <div style='text-align: center; font-size: 0.9em; color: #7f8c8d;'>
669
-
670
-             <p>Developed by Engineers</p>
671
-
672
-             <p><strong>Ali Al-Qawas &nbsp;|&nbsp; Tareq Al-Omari &nbsp;|&nbsp; Abdulrahman Sinan</strong></p>
673
-
674
-         </div>
675
-
676
-         """
677
-
678
-     )
679
-
680
-
681
-
682
-     # --- Link Functions to Components ---
683
-
684
-     submit_btn.click(
685
-
686
-         fn=predict_and_explain,
687
-
688
-         inputs=[text_input],
689
-
690
-         outputs=[status_output, reason_output, feedback_box]
691
-
692
-     )
693
-
694
-     
695
-
696
-     feedback_btn.click(
697
-
698
-         fn=handle_feedback,
699
-
700
-         inputs=[text_input, status_output, correction_dropdown, comment_box],
701
-
702
-         outputs=[feedback_status]
703
-
704
-     )
705
-
706
-
707
 
708
  # --- 4. Launch the Interface ---
709
-
710
  iface.launch()
 
 
1
  # =============================================================================
 
2
  # Final Code for the Professional Interface (English Version)
 
3
  # =============================================================================
 
4
  import gradio as gr
 
5
  import joblib
 
6
  import re
 
7
  import pandas as pd
 
8
  from datetime import datetime
9
 
 
 
10
  # --- 1. Load Model and Knowledge Base ---
 
11
  try:
12
+ model = joblib.load('halal_classifier_model.pkl')
13
+ except FileNotFoundError:
14
+ print("Error: 'halal_classifier_model.pkl' not found.")
15
+ model = None
 
 
 
 
 
 
 
 
16
 
17
  # --- Use your complete knowledge base here ---
 
18
  comprehensive_ingredients_db = {
19
+ #==========================================================================
20
+ # القسم الأول: مكونات محرمة بشكل قاطع (Haram)
21
+ #==========================================================================
22
+ 'pork': {'status': 'Haram', 'reason': 'Pork is explicitly forbidden in the Quran.'},
23
+ 'bacon': {'status': 'Haram', 'reason': 'A type of cured pork.'},
24
+ 'ham': {'status': 'Haram', 'reason': 'Meat from the thigh of a pig.'},
25
+ 'lard': {'status': 'Haram', 'reason': 'Fat from the abdomen of a pig.'},
26
+ 'swine': {'status': 'Haram', 'reason': 'Another name for a pig.'},
27
+ 'hog': {'status': 'Haram', 'reason': 'Another name for a pig.'},
28
+ 'boar': {'status': 'Haram', 'reason': 'A wild pig.'},
29
+ 'porcine': {'status': 'Haram', 'reason': 'Derived from pigs.'},
30
+ 'speck': {'status': 'Haram', 'reason': 'A type of cured pork belly.'},
31
+ 'schwein': {'status': 'Haram', 'reason': "German word for 'pig'."},
32
+ 'prosciutto': {'status': 'Haram', 'reason': 'Italian dry-cured ham.'},
33
+ 'alcohol': {'status': 'Haram', 'reason': 'All intoxicants are forbidden.'},
34
+ 'ethanol': {'status': 'Haram', 'reason': 'The chemical name for intoxicating alcohol.'},
35
+ 'ethyl alcohol': {'status': 'Haram', 'reason': 'The chemical name for intoxicating alcohol.'},
36
+ 'wine': {'status': 'Haram', 'reason': 'Wine is explicitly forbidden.'},
37
+ 'beer': {'status': 'Haram', 'reason': 'An intoxicating alcoholic beverage.'},
38
+ 'liquor': {'status': 'Haram', 'reason': 'A general term for distilled alcoholic drinks.'},
39
+ 'liqueur': {'status': 'Haram', 'reason': 'A sweetened alcoholic beverage.'},
40
+ 'brandy': {'status': 'Haram', 'reason': 'An intoxicating alcoholic beverage.'},
41
+ 'cognac': {'status': 'Haram', 'reason': 'A type of brandy, which is an intoxicant.'},
42
+ 'gin': {'status': 'Haram', 'reason': 'An intoxicating alcoholic beverage.'},
43
+ 'rum': {'status': 'Haram', 'reason': 'An intoxicating alcoholic beverage.'},
44
+ 'vodka': {'status': 'Haram', 'reason': 'An intoxicating alcoholic beverage.'},
45
+ 'whisky': {'status': 'Haram', 'reason': 'An intoxicating alcoholic beverage.'},
46
+ 'whiskey': {'status': 'Haram', 'reason': 'An intoxicating alcoholic beverage.'},
47
+ 'champagne': {'status': 'Haram', 'reason': 'A sparkling wine, which is an intoxicant.'},
48
+ 'sake': {'status': 'Haram', 'reason': 'Japanese rice wine, which is an intoxicant.'},
49
+ 'vermouth': {'status': 'Haram', 'reason': 'A fortified and flavored wine, which is an intoxicant.'},
50
+ 'sherry': {'status': 'Haram', 'reason': 'A type of fortified wine, which is an intoxicant.'},
51
+ 'port': {'status': 'Haram', 'reason': 'A type of fortified wine, which is an intoxicant.'},
52
+ 'absinthe': {'status': 'Haram', 'reason': 'An intoxicating alcoholic beverage.'},
53
+ 'blood': {'status': 'Haram', 'reason': 'Flowing blood is explicitly forbidden.'},
54
+ 'carrion': {'status': 'Haram', 'reason': 'Meat from an animal that was not slaughtered according to Islamic law.'},
55
+ 'carmine': {'status': 'Haram', 'reason': 'A red pigment (E120) derived from insects, considered forbidden by the majority of scholars.'},
56
+ 'cochineal': {'status': 'Haram', 'reason': 'Another name for carmine dye (E120) from insects.'},
57
+ 'e120': {'status': 'Haram', 'reason': 'The E-number for carmine dye from insects.'},
58
+ 'e-120': {'status': 'Haram', 'reason': 'The E-number for carmine dye from insects.'},
59
+ 'ci 75470': {'status': 'Haram', 'reason': 'The international color index for carmine dye from insects.'},
60
+ #==========================================================================
61
+ # القسم الثاني: مكونات مشبوهة (Doubtful / Mashbooh)
62
+ #==========================================================================
63
+ 'gelatin': {'status': 'Doubtful (leaning towards Haram)', 'reason': 'Its source is mostly animal (pork or not slaughtered correctly). Requires a reliable Halal certificate.'},
64
+ 'e441': {'status': 'Doubtful (leaning towards Haram)', 'reason': 'Old E-number for Gelatin. Its source is often animal-based (pork or not slaughtered correctly).'},
65
+ 'e-441': {'status': 'Doubtful (leaning towards Haram)', 'reason': 'Old E-number for Gelatin. Its source is often animal-based (pork or not slaughtered correctly).'},
66
+ 'animal fat': {'status': 'Doubtful', 'reason': 'Animal fat. Must be from a Halal-slaughtered animal.'},
67
+ 'animal shortening': {'status': 'Doubtful', 'reason': 'Animal shortening. Must be from a Halal-slaughtered animal.'},
68
+ 'fat': {'status': 'Doubtful', 'reason': 'A general term for fat. If the source is not specified as vegetable, it is doubtful.'},
69
+ 'tallow': {'status': 'Doubtful', 'reason': 'Animal fat. Must be confirmed to be from a Halal source.'},
70
+ 'shortening': {'status': 'Doubtful', 'reason': 'An industrial fat that may contain animal fats. The source must be verified.'},
71
+ 'margarine': {'status': 'Doubtful', 'reason': 'May contain animal fats or doubtful emulsifiers.'},
72
+ 'glycerin': {'status': 'Doubtful', 'reason': 'Can be of animal or vegetable origin. The vegetable source must be confirmed.'},
73
+ 'glycerine': {'status': 'Doubtful', 'reason': 'Another name for Glycerin; can be of animal or vegetable origin.'},
74
+ 'glycerol': {'status': 'Doubtful', 'reason': 'Another name for Glycerin (E422); can be of animal or vegetable origin.'},
75
+ 'e422': {'status': 'Doubtful', 'reason': 'E-number for Glycerin/Glycerol. Can be of animal or vegetable origin.'},
76
+ 'e-422': {'status': 'Doubtful', 'reason': 'E-number for Glycerin/Glycerol. Can be of animal or vegetable origin.'},
77
+ 'mono and diglycerides': {'status': 'Doubtful', 'reason': 'Emulsifiers (E471) that can be from animal or vegetable fat. Must be verified.'},
78
+ 'emulsifier': {'status': 'Doubtful', 'reason': 'A general term for emulsifiers. Many are of doubtful (animal) origin.'},
79
+ 'whey': {'status': 'Doubtful', 'reason': 'Its ruling depends on the rennet used in cheese making.'},
80
+ 'rennet': {'status': 'Doubtful', 'reason': 'Cheese rennet, which can be from an animal not slaughtered according to Islamic law.'},
81
+ 'pepsin': {'status': 'Doubtful', 'reason': 'An enzyme often extracted from pig stomachs. Must be verified to be from a plant or microbial source.'},
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  }
83
 
 
 
84
  FEEDBACK_FILE = 'feedback_log_en.csv'
85
 
 
 
86
  # --- 2. Define Backend Functions (Now in English) ---
 
87
  def predict_and_explain(text_input):
88
+ if not model or not text_input.strip():
89
+ return "", "", gr.update(visible=False)
90
+
91
+ prediction = model.predict([text_input])[0]
92
+
93
+ # Translate prediction for consistency if your model outputs Arabic
94
+ status_map = {
95
+ "حرام": "Haram",
96
+ "حلال": "Halal",
97
+ "مشتبه فيه": "Doubtful",
98
+ "مشتبه فيه (يميل للتحريم)": "Doubtful (leaning towards Haram)"
99
+ }
100
+ prediction_en = status_map.get(prediction, "Doubtful")
101
+
102
+ reason = "No direct reason found in the knowledge base."
103
+
104
+ if prediction_en != 'Halal':
105
+ for ingredient, details in comprehensive_ingredients_db.items():
106
+ if re.search(r'\b' + re.escape(ingredient) + r'\b', text_input, re.IGNORECASE):
107
+ reason = details.get('reason', "Reason not specified.") # Use .get for safety
108
+ break
109
+ else:
110
+ reason = "No clear forbidden or doubtful ingredients were found based on the current database."
111
+
112
+ return prediction_en, reason, gr.update(visible=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
 
114
  def handle_feedback(original_text, model_prediction, user_correction, user_comment):
115
+ try:
116
+ feedback_data = pd.DataFrame({
117
+ 'timestamp': [datetime.now()],
118
+ 'original_text': [original_text],
119
+ 'model_prediction': [model_prediction],
120
+ 'user_correction': [user_correction],
121
+ 'user_comment': [user_comment]
122
+ })
123
+ try:
124
+ pd.read_csv(FEEDBACK_FILE)
125
+ write_header = False
126
+ except FileNotFoundError:
127
+ write_header = True
128
+
129
+ feedback_data.to_csv(FEEDBACK_FILE, mode='a', header=write_header, index=False, encoding='utf-8-sig')
130
+ return "✅ Thank you for your contribution! Your feedback has been saved."
131
+ except Exception as e:
132
+ return f"❌ An error occurred while saving feedback: {e}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
  # --- 3. Build the Themed Interface with gr.Blocks ---
 
 
 
135
  theme = gr.themes.Soft(
136
+ primary_hue="blue",
137
+ secondary_hue="blue",
 
 
 
138
  ).set(
139
+ button_primary_background_fill='*primary_500',
140
+ button_primary_background_fill_hover='*primary_600',
 
 
 
141
  )
142
 
 
 
143
  with gr.Blocks(theme=theme) as iface:
144
+
145
+ gr.Markdown(
146
+ """
147
+ <div style="text-align: center; font-family: 'Arial', sans-serif; padding-bottom: 15px;">
148
+ <h1 style="color: #2c3e50;">Yaqeen</h1>
149
+ <p style="font-size: 1.2em; color: #34495e;">
150
+ An intelligent system to classify food products by analyzing their ingredients.
151
+ </p>
152
+ </div>
153
+ """
154
+ )
155
+
156
+ with gr.Row():
157
+ with gr.Column(scale=2):
158
+ text_input = gr.Textbox(lines=8, label="Enter Product Name & Ingredients", placeholder="e.g., Milk Chocolate, Ingredients: Sugar, cocoa butter, milk powder, soy lecithin E322, vanilla flavor...")
159
+ submit_btn = gr.Button("🔍 Analyze Product", variant="primary")
160
+
161
+ with gr.Column(scale=3):
162
+ status_output = gr.Textbox(label="Predicted Status", interactive=False)
163
+ reason_output = gr.Textbox(label="Potential Reason", interactive=False)
164
+
165
+ with gr.Group(visible=False) as feedback_box:
166
+ gr.Markdown("---")
167
+ gr.Markdown("<h3 style='text-align:center;'>Was this prediction correct?</h3>")
168
+ with gr.Row():
169
+ correction_dropdown = gr.Dropdown(
170
+ choices=["Halal", "Haram", "Doubtful", "Doubtful (leaning towards Haram)"],
171
+ label="If not, what is the correct status?"
172
+ )
173
+ comment_box = gr.Textbox(label="Additional Comments (Optional)", placeholder="e.g., This product contains Halal beef gelatin...")
174
+
175
+ feedback_btn = gr.Button("📩 Submit Feedback")
176
+ feedback_status = gr.Textbox(label="Submission Status", interactive=False)
177
+
178
+ gr.Examples(
179
+ examples=[
180
+ ["Prosciutto crudo, E252"],
181
+ ["Cheddar cheese, water, salt, rennet, whey"],
182
+ ["Gummy candy with sugar, corn syrup, gelatin, citric acid, carmine color"],
183
+ ],
184
+ inputs=text_input,
185
+ label="Examples"
186
+ )
187
+
188
+ gr.Markdown(
189
+ """
190
+ <hr>
191
+ <div style='text-align: center; font-size: 0.9em; color: #7f8c8d;'>
192
+ <p>Developed by Engineers</p>
193
+ <p><strong>Ali Al-Qawas &nbsp;|&nbsp; Tareq Al-Omari &nbsp;|&nbsp; Abdulrahman Sinan</strong></p>
194
+ </div>
195
+ """
196
+ )
197
+
198
+ # --- Link Functions to Components ---
199
+ submit_btn.click(
200
+ fn=predict_and_explain,
201
+ inputs=[text_input],
202
+ outputs=[status_output, reason_output, feedback_box]
203
+ )
204
+
205
+ feedback_btn.click(
206
+ fn=handle_feedback,
207
+ inputs=[text_input, status_output, correction_dropdown, comment_box],
208
+ outputs=[feedback_status]
209
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
 
211
  # --- 4. Launch the Interface ---
 
212
  iface.launch()