File size: 2,767 Bytes
743befd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import onnxruntime as ort
import re
import numpy as np
from transformers import AutoTokenizer
from functools import lru_cache
import multiprocessing

# ==============================
# إعداد النموذج والتوكنيزر - محسّن
# ==============================
MODEL_PATH = "lib/intfloat_multilingual-e5-small_merged_int8.onnx"
TOKENIZER_PATH = "./lib/"

# تحسين جلسة ONNX
session_options = ort.SessionOptions()
session_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
session_options.enable_cpu_mem_arena = True
session_options.intra_op_num_threads = multiprocessing.cpu_count()  # استخدام كل أنوية السيرفر
session_options.inter_op_num_threads = 1
session_options.optimized_model_filepath = "optimized_model.onnx"

session = ort.InferenceSession(
    MODEL_PATH,
    providers=[('CPUExecutionProvider', {})],
    sess_options=session_options
)

# تحميل التوكنيزر مع التخزين المؤقت
tokenizer = AutoTokenizer.from_pretrained(
    TOKENIZER_PATH,
    local_files_only=True,
    use_fast=True
)

# ==============================
# دوال مساعدة - محسّنة
# ==============================
@lru_cache(maxsize=1024)
def normalize_arabic(text: str) -> str:
    """تطبيع النص العربي مع تخزين مؤقت"""
    text = re.sub(r'[ًٌٍَُِّْـ]', '', text)
    text = re.sub(r'[إأآ]', 'ا', text)
    text = re.sub(r'ى', 'ي', text)
    text = re.sub(r'ؤ', 'و', text)
    text = re.sub(r'ئ', 'ي', text)
    text = re.sub(r'ة\b', 'ه', text)
    text = re.sub(r'[^\w\s]', ' ', text)
    text = re.sub(r'\s+', ' ', text)
    return text.strip()

# ==============================
# دالة Embedding المحسّنة
# ==============================
def query_to_embedding(query: str, normalize: bool = True) -> np.ndarray:
    """تحويل الاستعلام إلى embedding بكفاءة عالية"""
    if not query or not query.strip():
        return None
    
    query = query.strip()
    
    if normalize:
        query = normalize_arabic(query)
    
    # بما أن الاستعلام قصير (≤ 15 كلمة) نستخدم max_length صغير
    inputs = tokenizer(
        "query: " + query,
        return_tensors="np",
        truncation=True,
        padding="max_length",
        max_length=64,  # كافي للاستعلامات القصيرة
        return_attention_mask=True,
        return_token_type_ids=False
    )
    
    # تشغيل النموذج
    ort_outs = session.run(None, dict(inputs))
    vector = ort_outs[1][0]
    
    # تطبيع المتجه بكفاءة
    norm = np.linalg.norm(vector)
    if norm > 0:
        vector = vector / norm
    
    return vector.astype(np.float32)