# ============================================================================= # Final Code for the Professional Interface (English Version) # ============================================================================= import gradio as gr import joblib import re import pandas as pd from datetime import datetime # --- 1. Load Model and Knowledge Base --- try: model = joblib.load('halal_classifier_model.pkl') except FileNotFoundError: print("Error: 'halal_classifier_model.pkl' not found.") model = None # --- Use your complete knowledge base here --- comprehensive_ingredients_db = { #========================================================================== # القسم الأول: مكونات محرمة بشكل قاطع (Haram) #========================================================================== 'pork': {'status': 'Haram', 'reason': 'Pork is explicitly forbidden in the Quran.'}, 'bacon': {'status': 'Haram', 'reason': 'A type of cured pork.'}, 'ham': {'status': 'Haram', 'reason': 'Meat from the thigh of a pig.'}, 'lard': {'status': 'Haram', 'reason': 'Fat from the abdomen of a pig.'}, 'swine': {'status': 'Haram', 'reason': 'Another name for a pig.'}, 'hog': {'status': 'Haram', 'reason': 'Another name for a pig.'}, 'boar': {'status': 'Haram', 'reason': 'A wild pig.'}, 'porcine': {'status': 'Haram', 'reason': 'Derived from pigs.'}, 'speck': {'status': 'Haram', 'reason': 'A type of cured pork belly.'}, 'schwein': {'status': 'Haram', 'reason': "German word for 'pig'."}, 'prosciutto': {'status': 'Haram', 'reason': 'Italian dry-cured ham.'}, 'alcohol': {'status': 'Haram', 'reason': 'All intoxicants are forbidden.'}, 'ethanol': {'status': 'Haram', 'reason': 'The chemical name for intoxicating alcohol.'}, 'ethyl alcohol': {'status': 'Haram', 'reason': 'The chemical name for intoxicating alcohol.'}, 'wine': {'status': 'Haram', 'reason': 'Wine is explicitly forbidden.'}, 'beer': {'status': 'Haram', 'reason': 'An intoxicating alcoholic beverage.'}, 'liquor': {'status': 'Haram', 'reason': 'A general term for distilled alcoholic drinks.'}, 'liqueur': {'status': 'Haram', 'reason': 'A sweetened alcoholic beverage.'}, 'brandy': {'status': 'Haram', 'reason': 'An intoxicating alcoholic beverage.'}, 'cognac': {'status': 'Haram', 'reason': 'A type of brandy, which is an intoxicant.'}, 'gin': {'status': 'Haram', 'reason': 'An intoxicating alcoholic beverage.'}, 'rum': {'status': 'Haram', 'reason': 'An intoxicating alcoholic beverage.'}, 'vodka': {'status': 'Haram', 'reason': 'An intoxicating alcoholic beverage.'}, 'whisky': {'status': 'Haram', 'reason': 'An intoxicating alcoholic beverage.'}, 'whiskey': {'status': 'Haram', 'reason': 'An intoxicating alcoholic beverage.'}, 'champagne': {'status': 'Haram', 'reason': 'A sparkling wine, which is an intoxicant.'}, 'sake': {'status': 'Haram', 'reason': 'Japanese rice wine, which is an intoxicant.'}, 'vermouth': {'status': 'Haram', 'reason': 'A fortified and flavored wine, which is an intoxicant.'}, 'sherry': {'status': 'Haram', 'reason': 'A type of fortified wine, which is an intoxicant.'}, 'port': {'status': 'Haram', 'reason': 'A type of fortified wine, which is an intoxicant.'}, 'absinthe': {'status': 'Haram', 'reason': 'An intoxicating alcoholic beverage.'}, 'blood': {'status': 'Haram', 'reason': 'Flowing blood is explicitly forbidden.'}, 'carrion': {'status': 'Haram', 'reason': 'Meat from an animal that was not slaughtered according to Islamic law.'}, 'carmine': {'status': 'Haram', 'reason': 'A red pigment (E120) derived from insects, considered forbidden by the majority of scholars.'}, 'cochineal': {'status': 'Haram', 'reason': 'Another name for carmine dye (E120) from insects.'}, 'e120': {'status': 'Haram', 'reason': 'The E-number for carmine dye from insects.'}, 'e-120': {'status': 'Haram', 'reason': 'The E-number for carmine dye from insects.'}, 'ci 75470': {'status': 'Haram', 'reason': 'The international color index for carmine dye from insects.'}, #========================================================================== # القسم الثاني: مكونات مشبوهة (Doubtful / Mashbooh) #========================================================================== 'gelatin': {'status': 'Doubtful (leaning towards Haram)', 'reason': 'Its source is mostly animal (pork or not slaughtered correctly). Requires a reliable Halal certificate.'}, 'e441': {'status': 'Doubtful (leaning towards Haram)', 'reason': 'Old E-number for Gelatin. Its source is often animal-based (pork or not slaughtered correctly).'}, 'e-441': {'status': 'Doubtful (leaning towards Haram)', 'reason': 'Old E-number for Gelatin. Its source is often animal-based (pork or not slaughtered correctly).'}, 'animal fat': {'status': 'Doubtful', 'reason': 'Animal fat. Must be from a Halal-slaughtered animal.'}, 'animal shortening': {'status': 'Doubtful', 'reason': 'Animal shortening. Must be from a Halal-slaughtered animal.'}, 'fat': {'status': 'Doubtful', 'reason': 'A general term for fat. If the source is not specified as vegetable, it is doubtful.'}, 'tallow': {'status': 'Doubtful', 'reason': 'Animal fat. Must be confirmed to be from a Halal source.'}, 'shortening': {'status': 'Doubtful', 'reason': 'An industrial fat that may contain animal fats. The source must be verified.'}, 'margarine': {'status': 'Doubtful', 'reason': 'May contain animal fats or doubtful emulsifiers.'}, 'glycerin': {'status': 'Doubtful', 'reason': 'Can be of animal or vegetable origin. The vegetable source must be confirmed.'}, 'glycerine': {'status': 'Doubtful', 'reason': 'Another name for Glycerin; can be of animal or vegetable origin.'}, 'glycerol': {'status': 'Doubtful', 'reason': 'Another name for Glycerin (E422); can be of animal or vegetable origin.'}, 'e422': {'status': 'Doubtful', 'reason': 'E-number for Glycerin/Glycerol. Can be of animal or vegetable origin.'}, 'e-422': {'status': 'Doubtful', 'reason': 'E-number for Glycerin/Glycerol. Can be of animal or vegetable origin.'}, 'mono and diglycerides': {'status': 'Doubtful', 'reason': 'Emulsifiers (E471) that can be from animal or vegetable fat. Must be verified.'}, 'emulsifier': {'status': 'Doubtful', 'reason': 'A general term for emulsifiers. Many are of doubtful (animal) origin.'}, 'whey': {'status': 'Doubtful', 'reason': 'Its ruling depends on the rennet used in cheese making.'}, 'rennet': {'status': 'Doubtful', 'reason': 'Cheese rennet, which can be from an animal not slaughtered according to Islamic law.'}, 'pepsin': {'status': 'Doubtful', 'reason': 'An enzyme often extracted from pig stomachs. Must be verified to be from a plant or microbial source.'}, } FEEDBACK_FILE = 'feedback_log_en.csv' # --- 2. Define Backend Functions (Now in English) --- def predict_and_explain(text_input): if not model or not text_input.strip(): return "", "", gr.update(visible=False) prediction = model.predict([text_input])[0] # Translate prediction for consistency if your model outputs Arabic status_map = { "حرام": "Haram", "حلال": "Halal", "مشتبه فيه": "Doubtful", "مشتبه فيه (يميل للتحريم)": "Doubtful (leaning towards Haram)" } prediction_en = status_map.get(prediction, "Doubtful") reason = "No direct reason found in the knowledge base." if prediction_en != 'Halal': for ingredient, details in comprehensive_ingredients_db.items(): if re.search(r'\b' + re.escape(ingredient) + r'\b', text_input, re.IGNORECASE): reason = details.get('reason', "Reason not specified.") # Use .get for safety break else: reason = "No clear forbidden or doubtful ingredients were found based on the current database." return prediction_en, reason, gr.update(visible=True) def handle_feedback(original_text, model_prediction, user_correction, user_comment): try: feedback_data = pd.DataFrame({ 'timestamp': [datetime.now()], 'original_text': [original_text], 'model_prediction': [model_prediction], 'user_correction': [user_correction], 'user_comment': [user_comment] }) try: pd.read_csv(FEEDBACK_FILE) write_header = False except FileNotFoundError: write_header = True feedback_data.to_csv(FEEDBACK_FILE, mode='a', header=write_header, index=False, encoding='utf-8-sig') return "✅ Thank you for your contribution! Your feedback has been saved." except Exception as e: return f"❌ An error occurred while saving feedback: {e}" # --- 3. Build the Themed Interface with gr.Blocks --- theme = gr.themes.Soft( primary_hue="blue", secondary_hue="blue", ).set( button_primary_background_fill='*primary_500', button_primary_background_fill_hover='*primary_600', ) with gr.Blocks(theme=theme) as iface: gr.Markdown( """
An intelligent system to classify food products by analyzing their ingredients.
Developed by Engineers
Ali Al-Qawas | Tareq Al-Omari | Abdulrahman Sinan