Spaces:
Paused
Paused
""" | |
محمّل النماذج | |
يقوم بتحميل وإدارة نماذج الذكاء الاصطناعي المستخدمة في النظام | |
""" | |
import os | |
import logging | |
import torch | |
import gc | |
from typing import Dict, Any, Optional, Union, List | |
from pathlib import Path | |
logger = logging.getLogger(__name__) | |
class ModelLoader: | |
""" | |
محمّل النماذج | |
""" | |
def __init__(self, config=None, use_gpu=True): | |
""" | |
تهيئة محمّل النماذج | |
المعاملات: | |
---------- | |
config : Dict, optional | |
إعدادات محمّل النماذج | |
use_gpu : bool, optional | |
استخدام GPU إذا كان متاحًا | |
""" | |
self.config = config or {} | |
self.use_gpu = use_gpu and torch.cuda.is_available() | |
# التحقق من توفر GPU | |
if self.use_gpu: | |
self.device = torch.device("cuda") | |
logger.info(f"تم اكتشاف GPU: {torch.cuda.get_device_name(0)}") | |
logger.info(f"ذاكرة GPU المتاحة: {self._get_available_gpu_memory()} ميجابايت") | |
else: | |
self.device = torch.device("cpu") | |
logger.info("استخدام المعالج المركزي CPU") | |
# تهيئة قواميس لتخزين النماذج المحملة | |
self.models = {} | |
self.tokenizers = {} | |
# تحميل النماذج المطلوبة بشكل افتراضي | |
self._load_default_models() | |
logger.info("تم تهيئة محمّل النماذج") | |
def get_ner_model(self): | |
""" | |
الحصول على نموذج التعرف على الكيانات المسماة | |
المخرجات: | |
-------- | |
أي | |
نموذج التعرف على الكيانات المسماة | |
""" | |
if "ner" in self.models: | |
return self.models["ner"] | |
# تحميل النموذج إذا لم يكن محملاً | |
ner_model = self._load_ner_model() | |
return ner_model | |
def get_similarity_model(self): | |
""" | |
الحصول على نموذج التشابه النصي | |
المخرجات: | |
-------- | |
أي | |
نموذج التشابه النصي | |
""" | |
if "similarity" in self.models: | |
return self.models["similarity"] | |
# تحميل النموذج إذا لم يكن محملاً | |
similarity_model = self._load_similarity_model() | |
return similarity_model | |
def get_classification_model(self): | |
""" | |
الحصول على نموذج التصنيف | |
المخرجات: | |
-------- | |
أي | |
نموذج التصنيف | |
""" | |
if "classification" in self.models: | |
return self.models["classification"] | |
# تحميل النموذج إذا لم يكن محملاً | |
classification_model = self._load_classification_model() | |
return classification_model | |
def get_tokenizer(self, model_name): | |
""" | |
الحصول على محلل الترميز للنموذج | |
المعاملات: | |
---------- | |
model_name : str | |
اسم النموذج | |
المخرجات: | |
-------- | |
أي | |
محلل الترميز | |
""" | |
if model_name in self.tokenizers: | |
return self.tokenizers[model_name] | |
# تحميل محلل الترميز إذا لم يكن محملاً | |
if model_name == "ner": | |
tokenizer = self._load_tokenizer("aubmindlab/bert-base-arabertv02-ner") | |
elif model_name == "similarity": | |
tokenizer = self._load_tokenizer("UBC-NLP/ARBERT") | |
elif model_name == "classification": | |
tokenizer = self._load_tokenizer("CAMeL-Lab/bert-base-arabic-camelbert-mix") | |
else: | |
raise ValueError(f"محلل الترميز غير معروف: {model_name}") | |
self.tokenizers[model_name] = tokenizer | |
return tokenizer | |
def release_model(self, model_name): | |
""" | |
تحرير النموذج من الذاكرة | |
المعاملات: | |
---------- | |
model_name : str | |
اسم النموذج | |
""" | |
if model_name in self.models: | |
del self.models[model_name] | |
if self.use_gpu: | |
torch.cuda.empty_cache() | |
gc.collect() | |
logger.info(f"تم تحرير النموذج: {model_name}") | |
def release_all_models(self): | |
""" | |
تحرير جميع النماذج من الذاكرة | |
""" | |
self.models = {} | |
self.tokenizers = {} | |
if self.use_gpu: | |
torch.cuda.empty_cache() | |
gc.collect() | |
logger.info("تم تحرير جميع النماذج") | |
def get_available_memory(self): | |
""" | |
الحصول على كمية الذاكرة المتاحة | |
المخرجات: | |
-------- | |
int | |
كمية الذاكرة المتاحة بالميجابايت | |
""" | |
if self.use_gpu: | |
return self._get_available_gpu_memory() | |
else: | |
# ليس هناك طريقة موحدة للحصول على ذاكرة CPU | |
return 0 | |
def _load_default_models(self): | |
""" | |
تحميل النماذج الافتراضية | |
""" | |
default_models = self.config.get("default_models", []) | |
for model_name in default_models: | |
try: | |
if model_name == "ner": | |
self._load_ner_model() | |
elif model_name == "similarity": | |
self._load_similarity_model() | |
elif model_name == "classification": | |
self._load_classification_model() | |
else: | |
logger.warning(f"نموذج غير معروف: {model_name}") | |
except Exception as e: | |
logger.error(f"فشل في تحميل النموذج {model_name}: {str(e)}") | |
def _load_ner_model(self): | |
""" | |
تحميل نموذج التعرف على الكيانات المسماة | |
المخرجات: | |
-------- | |
أي | |
نموذج التعرف على الكيانات المسماة | |
""" | |
try: | |
from transformers import pipeline | |
logger.info("جاري تحميل نموذج التعرف على الكيانات المسماة...") | |
model_name = self.config.get("ner_model", "aubmindlab/bert-base-arabertv02-ner") | |
# تحميل النموذج | |
ner_model = pipeline( | |
"token-classification", | |
model=model_name, | |
aggregation_strategy="simple", | |
device=0 if self.use_gpu else -1 | |
) | |
self.models["ner"] = ner_model | |
logger.info(f"تم تحميل نموذج التعرف على الكيانات المسماة: {model_name}") | |
return ner_model | |
except Exception as e: | |
logger.error(f"فشل في تحميل نموذج التعرف على الكيانات المسماة: {str(e)}") | |
raise | |
def _load_similarity_model(self): | |
""" | |
تحميل نموذج التشابه النصي | |
المخرجات: | |
-------- | |
أي | |
نموذج التشابه النصي | |
""" | |
try: | |
from transformers import AutoModel | |
logger.info("جاري تحميل نموذج التشابه النصي...") | |
model_name = self.config.get("similarity_model", "UBC-NLP/ARBERT") | |
# تحميل النموذج | |
similarity_model = AutoModel.from_pretrained(model_name) | |
if self.use_gpu: | |
similarity_model = similarity_model.to(self.device) | |
self.models["similarity"] = similarity_model | |
logger.info(f"تم تحميل نموذج التشابه النصي: {model_name}") | |
return similarity_model | |
except Exception as e: | |
logger.error(f"فشل في تحميل نموذج التشابه النصي: {str(e)}") | |
raise | |
def _load_classification_model(self): | |
""" | |
تحميل نموذج التصنيف | |
المخرجات: | |
-------- | |
أي | |
نموذج التصنيف | |
""" | |
try: | |
from transformers import pipeline | |
logger.info("جاري تحميل نموذج التصنيف...") | |
model_name = self.config.get("classification_model", "CAMeL-Lab/bert-base-arabic-camelbert-mix") | |
# تحميل النموذج | |
classification_model = pipeline( | |
"text-classification", | |
model=model_name, | |
device=0 if self.use_gpu else -1 | |
) | |
self.models["classification"] = classification_model | |
logger.info(f"تم تحميل نموذج التصنيف: {model_name}") | |
return classification_model | |
except Exception as e: | |
logger.error(f"فشل في تحميل نموذج التصنيف: {str(e)}") | |
raise | |
def _load_tokenizer(self, model_name): | |
""" | |
تحميل محلل الترميز | |
المعاملات: | |
---------- | |
model_name : str | |
اسم النموذج | |
المخرجات: | |
-------- | |
أي | |
محلل الترميز | |
""" | |
try: | |
from transformers import AutoTokenizer | |
logger.info(f"جاري تحميل محلل الترميز: {model_name}...") | |
# تحميل محلل الترميز | |
tokenizer = AutoTokenizer.from_pretrained(model_name) | |
logger.info(f"تم تحميل محلل الترميز: {model_name}") | |
return tokenizer | |
except Exception as e: | |
logger.error(f"فشل في تحميل محلل الترميز {model_name}: {str(e)}") | |
raise | |
def _get_available_gpu_memory(self): | |
""" | |
الحصول على كمية ذاكرة GPU المتاحة | |
المخرجات: | |
-------- | |
int | |
كمية ذاكرة GPU المتاحة بالميجابايت | |
""" | |
if not self.use_gpu: | |
return 0 | |
try: | |
torch.cuda.empty_cache() | |
# الحصول على إجمالي ذاكرة GPU | |
total_memory = torch.cuda.get_device_properties(0).total_memory | |
# الحصول على ذاكرة GPU المستخدمة | |
allocated_memory = torch.cuda.memory_allocated(0) | |
# الحصول على ذاكرة GPU المحجوزة | |
reserved_memory = torch.cuda.memory_reserved(0) | |
# حساب الذاكرة المتاحة | |
available_memory = total_memory - allocated_memory - reserved_memory | |
# تحويل إلى ميجابايت | |
return available_memory / (1024 * 1024) | |
except Exception as e: | |
logger.error(f"فشل في الحصول على ذاكرة GPU المتاحة: {str(e)}") | |
return 0 |