File size: 5,732 Bytes
fdb1961
 
 
 
 
 
 
 
aa9b884
fdb1961
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9c448df
1430894
fdb1961
 
1430894
fdb1961
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1430894
fdb1961
 
 
1430894
fdb1961
 
1430894
fdb1961
 
 
 
 
 
 
 
 
 
 
 
1430894
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
075d4cc
 
 
 
 
 
 
 
 
 
 
 
 
1430894
 
 
075d4cc
1430894
075d4cc
 
 
1430894
 
fdb1961
 
1430894
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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
import os
import re
import functools
import torch
import gradio as gr
from transformers import AutoTokenizer, AutoModelForSequenceClassification

# โ”€โ”€ Model & Tokenizer Configuration โ”€โ”€
MODEL_ID = os.getenv("HF_MODEL_ID", "ArabicNewsAnalyzer/MARBERTv2-Single-Arabic-Dialect-Scrapped-MSA-Mask-epoch3")
LOCAL_MODEL_PATH = os.path.join(os.path.dirname(__file__), "..", "results", "best_model")
MAX_LENGTH = 128

COUNTRY_DETAILS = {
    "Algeria": {"flag": "๐Ÿ‡ฉ๐Ÿ‡ฟ", "name_ar": "ุงู„ุฌุฒุงุฆุฑ", "region": "Maghrebi"},
    "Bahrain": {"flag": "๐Ÿ‡ง๐Ÿ‡ญ", "name_ar": "ุงู„ุจุญุฑูŠู†", "region": "Gulf"},
    "Egypt": {"flag": "๐Ÿ‡ช๐Ÿ‡ฌ", "name_ar": "ู…ุตุฑ", "region": "Egyptian"},
    "Iraq": {"flag": "๐Ÿ‡ฎ๐Ÿ‡ถ", "name_ar": "ุงู„ุนุฑุงู‚", "region": "Iraqi"},
    "Jordan": {"flag": "๐Ÿ‡ฏ๐Ÿ‡ด", "name_ar": "ุงู„ุฃุฑุฏู†", "region": "Levantine"},
    "Kuwait": {"flag": "๐Ÿ‡ฐ๐Ÿ‡ผ", "name_ar": "ุงู„ูƒูˆูŠุช", "region": "Gulf"},
    "Lebanon": {"flag": "๐Ÿ‡ฑ๐Ÿ‡ง", "name_ar": "ู„ุจู†ุงู†", "region": "Levantine"},
    "Libya": {"flag": "๐Ÿ‡ฑ๐Ÿ‡พ", "name_ar": "ู„ูŠุจูŠุง", "region": "Maghrebi"},
    "Morocco": {"flag": "๐Ÿ‡ฒ๐Ÿ‡ฆ", "name_ar": "ุงู„ู…ุบุฑุจ", "region": "Maghrebi"},
    "Oman": {"flag": "๐Ÿ‡ด๐Ÿ‡ฒ", "name_ar": "ุนูู…ุงู†", "region": "Gulf"},
    "Palestine": {"flag": "๐Ÿ‡ต๐Ÿ‡ธ", "name_ar": "ูู„ุณุทูŠู†", "region": "Levantine"},
    "Qatar": {"flag": "๐Ÿ‡ถ๐Ÿ‡ฆ", "name_ar": "ู‚ุทุฑ", "region": "Gulf"},
    "Saudi_Arabia": {"flag": "๐Ÿ‡ธ๐Ÿ‡ฆ", "name_ar": "ุงู„ุณุนูˆุฏูŠุฉ", "region": "Gulf"},
    "Sudan": {"flag": "๐Ÿ‡ธ๐Ÿ‡ฉ", "name_ar": "ุงู„ุณูˆุฏุงู†", "region": "Nilo-Saharan"},
    "Syria": {"flag": "๐Ÿ‡ธ๐Ÿ‡พ", "name_ar": "ุณูˆุฑูŠุง", "region": "Levantine"},
    "Tunisia": {"flag": "๐Ÿ‡น๐Ÿ‡ณ", "name_ar": "ุชูˆู†ุณ", "region": "Maghrebi"},
    "UAE": {"flag": "๐Ÿ‡ฆ๐Ÿ‡ช", "name_ar": "ุงู„ุฅู…ุงุฑุงุช", "region": "Gulf"},
    "Yemen": {"flag": "๐Ÿ‡พ๐Ÿ‡ช", "name_ar": "ุงู„ูŠู…ู†", "region": "Peninsular"},
    "MSA": {"flag": "๐Ÿ“", "name_ar": "ุงู„ูุตุญู‰", "region": "MSA"}
}

# โ”€โ”€ Cache Loading โ”€โ”€
@functools.lru_cache(maxsize=1)
def load_model_and_tokenizer():
    path_to_load = MODEL_ID
    if os.path.exists(LOCAL_MODEL_PATH) and os.path.exists(os.path.join(LOCAL_MODEL_PATH, "config.json")):
        path_to_load = LOCAL_MODEL_PATH

    tokenizer = AutoTokenizer.from_pretrained(path_to_load)
    model = AutoModelForSequenceClassification.from_pretrained(path_to_load)
    
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model.to(device)
    model.eval()

    id2label = model.config.id2label
    if not id2label or isinstance(list(id2label.keys())[0], str):
        id2label = {int(k): str(v) for k, v in id2label.items()}

    return tokenizer, model, id2label, device

# โ”€โ”€ Text Preprocessing โ”€โ”€
def preprocess_text(text: str) -> str:
    if not text:
        return ""
    text = re.sub(r"[\u200b\u200c\u200d\u200e\u200f\ufeff\u00ad]", "", text)
    return re.sub(r"\s+", " ", text).strip()

# โ”€โ”€ Inference Function โ”€โ”€
@torch.inference_mode()
def predict_dialect(text: str) -> dict:
    cleaned_text = preprocess_text(text)
    if not cleaned_text:
        return {"error": "Invalid or empty text input."}

    tokenizer, model, id2label, device = load_model_and_tokenizer()

    inputs = tokenizer(
        cleaned_text,
        return_tensors="pt",
        truncation=True,
        max_length=MAX_LENGTH
    )
    inputs = {k: v.to(device) for k, v in inputs.items()}

    outputs = model(**inputs)
    probs = torch.softmax(outputs.logits, dim=-1).squeeze(0).cpu().numpy()

    # Sort probabilities in descending order
    sorted_indices = probs.argsort()[::-1]

    all_predictions = []
    for idx in sorted_indices:
        label = id2label[int(idx)]
        details = COUNTRY_DETAILS.get(label, {"flag": "๐Ÿณ๏ธ", "name_ar": label, "region": "Unknown"})
        all_predictions.append({
            "country": label,
            "name_ar": details["name_ar"],
            "flag": details["flag"],
            "region": details["region"],
            "confidence": round(float(probs[idx]), 4)
        })

    top_prediction = all_predictions[0]

    return {
        "text": cleaned_text,
        "prediction": top_prediction["country"],
        "confidence": top_prediction["confidence"],
        "details": top_prediction,
        "probabilities": {p["country"]: p["confidence"] for p in all_predictions}
    }

# โ”€โ”€ Examples List โ”€โ”€
examples = [
    ["ูˆุงุด ูƒุงูŠู† ุงู„ุฒูŠู† ูู‡ุงุฏ ุงู„ุจู„ุงุฏ ุบุงุจ ุนู„ูŠู†ุง ู‡ุงุฏ ุงู„ุฃูŠุงู…"],
    ["ูŠุง ุฒู„ู…ุฉ ุดูˆ ู‡ุงู„ุญูƒูŠ ุงู„ูุงุถูŠ ุดูˆ ุนู… ุชุญูƒูŠ ุงู†ุช"],
    ["ุดู†ูˆ ู‡ุฐุง ุงู„ุญุฌูŠ ู…ุง ูŠุตูŠุฑ ู‡ูŠุฌ ุงุจุฏ ูˆุงู„ู„ู‡"],
    ["ุงูŠูˆุง ูƒุฏู‡ ุงู„ูƒู„ุงู… ุฏู‡ ุญู„ูˆ ุงูˆูŠ ุชุณู„ู… ุงูŠุฏูƒ ูŠุง ูู†ุงู†"],
    ["ูˆุงู„ู„ู‡ ูŠุง ุฎูˆูŠ ู‡ุงู„ู…ุทุนู… ุฃูƒู„ู‡ ุทูŠุจ ุจุฒุงู ุชุจุงุฑูƒ ุงู„ู„ู‡"],
    ["ุงูŠู‡ ูˆุงู„ู„ู‡ ูƒู„ุงู…ูƒ ุตุญ ูŠุงู„ุบุงู„ูŠ ู…ุง ู‚ุตุฑุช ุฑุจูŠ ูŠุญูุธูƒ"],
    ["ูƒูŠููƒ ุญุจูŠุจูŠ ุดู„ูˆู†ูƒ ุงู„ูŠูˆู… ุนุณุงูƒ ุทูŠุจ"],
    ["ู‡ุงุฐูŠ ุงู„ุณุงู„ูุฉ ู…ุง ุชู†ูุน ุฎู„ุงุต ู„ุงุฒู… ู†ู„ู‚ู‰ ุญู„ ุณุฑูŠุน"],
    ["ูˆูƒุงู„ุฉ ุชุณู†ูŠู… ุนู† ู…ุตุงุฏุฑ ุฅูŠุฑุงู†ูŠุฉ: ุฏูˆูŠ ุงู†ูุฌุงุฑูŠู† ููŠ ุฌุฒูŠุฑุฉ ู‚ุดู… ุณุจุจู‡ ุงู„ุชุตุฏูŠ ู„ุฃู‡ุฏุงู ู…ุนุงุฏูŠุฉ ุนู†ุฏ ู…ุฏุฎู„ ู…ุถูŠู‚ ู‡ุฑู…ุฒ"],
]

# โ”€โ”€ Minimal Gradio Interface โ”€โ”€
demo = gr.Interface(
    fn=predict_dialect,
    inputs=gr.Textbox(lines=3, placeholder="ุฃุฏุฎู„ ุงู„ู†ุต ุงู„ุนุฑุจูŠ ู‡ู†ุง...", label="Input Text"),
    outputs=gr.JSON(label="API Response"),
    examples=examples,
    cache_examples=False,
    title="Arabic Dialect Classifier",
    api_name="predict"
)

if __name__ == "__main__":
    demo.launch()