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() |