Mazenbs commited on
Commit
aebb2e6
·
verified ·
1 Parent(s): ffebc11

Update embeddingonnx.py

Browse files
Files changed (1) hide show
  1. embeddingonnx.py +94 -26
embeddingonnx.py CHANGED
@@ -1,52 +1,120 @@
1
  import onnxruntime as ort
 
2
  import numpy as np
3
  from transformers import AutoTokenizer
4
 
5
  # ==============================
6
- # المسارات المحلية للملفات
7
  # ==============================
8
- TOKENIZER_PATH = "./"
9
  MODEL_PATH = "intfloat_multilingual-e5-small_merged_int8.onnx"
 
10
 
11
- # ==============================
12
- # تحميل الـ Tokenizer المحلي
13
- # ==============================
 
14
  tokenizer = AutoTokenizer.from_pretrained(TOKENIZER_PATH, local_files_only=True)
15
 
16
  # ==============================
17
- # تحميل نموذج ONNX
18
  # ==============================
19
- session = ort.InferenceSession(MODEL_PATH)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
  # ==============================
22
- # دالة تحويل النص إلى embedding
23
  # ==============================
24
- def text_to_embedding(text, normalize=True):
25
- if not text.strip():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  return None
27
 
28
- # تحويل النص إلى input_ids
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  inputs = tokenizer(
30
- text,
31
  return_tensors="np",
32
  truncation=True,
33
- max_length=512, # يمكن تعديل الحد الأقصى
34
- padding="max_length"
35
  )
36
 
37
- # تشغيل النموذج ONNX
38
  ort_inputs = {k: v for k, v in inputs.items()}
39
- outputs = session.run(None, ort_inputs)
40
- vector = outputs[1][0] # استخراج embedding
41
 
42
- # تطبيع المتجه
43
- if normalize:
44
- vector = vector / (np.linalg.norm(vector) + 1e-10)
45
 
46
- return vector
 
47
 
48
- # ==============================
49
- # دالة تحويل الاستعلام (query)
50
- # ==============================
51
- def query_to_embedding(text, normalize=True):
52
- return text_to_embedding(text, normalize=normalize)
 
1
  import onnxruntime as ort
2
+ import re
3
  import numpy as np
4
  from transformers import AutoTokenizer
5
 
6
  # ==============================
7
+ # إعداد النموذج والتوكنيزر
8
  # ==============================
 
9
  MODEL_PATH = "intfloat_multilingual-e5-small_merged_int8.onnx"
10
+ TOKENIZER_PATH = "./"
11
 
12
+ # جلسة ONNX
13
+ session = ort.InferenceSession(MODEL_PATH, providers=['CPUExecutionProvider'])
14
+
15
+ # توكنيزر محلي (بدون تحميل من الإنترنت)
16
  tokenizer = AutoTokenizer.from_pretrained(TOKENIZER_PATH, local_files_only=True)
17
 
18
  # ==============================
19
+ # دوال مساعدة
20
  # ==============================
21
+ def normalize_arabic(text: str) -> str:
22
+ """
23
+ تطبيع كامل للنص العربي عند normalize=True
24
+ """
25
+ text = re.sub(r'[ًٌٍَُِّْـ]', '', text) # إزالة التشكيل
26
+ text = re.sub(r'[إأآ]', 'ا', text) # توحيد الهمزات
27
+ text = re.sub(r'ى', 'ي', text)
28
+ text = re.sub(r'ؤ', 'و', text)
29
+ text = re.sub(r'ئ', 'ي', text)
30
+ text = re.sub(r'ة\b', 'ه', text) # ة → ه آخر الكلمة
31
+ text = re.sub(r'[^\w\s]', ' ', text) # إزالة الرموز
32
+ text = re.sub(r'\s+', ' ', text)
33
+ return text.strip()
34
+
35
+
36
+ def split_sentences(text: str):
37
+ sentences = re.split(r'[.\n:؛؟!]', text)
38
+ return [s.strip() for s in sentences if len(s.strip()) > 0]
39
 
40
  # ==============================
41
+ # الدالة الرئيسية لتحويل النص إلى متجه
42
  # ==============================
43
+ def text_to_embedding(text: str, normalize: bool = True) -> np.ndarray:
44
+ """
45
+ تحويل نص إلى متجه واحد صالح للتخزين في Supabase.
46
+ تتعامل مع النصوص الطويلة عن طريق تقسيمها إلى جمل وأخذ متوسط متجهاتها.
47
+
48
+ Args:
49
+ text (str): النص العربي المراد تحويله.
50
+ normalize (bool): إذا كان True، سيتم تطبيع النص العربي قبل التحويل.
51
+
52
+ Returns:
53
+ np.ndarray: متجه 1D بحجم 384.
54
+ """
55
+ if normalize:
56
+ text = normalize_arabic(text)
57
+
58
+ # تقسيم النص إلى جمل
59
+ sentences = split_sentences(text)
60
+ if not sentences:
61
  return None
62
 
63
+ vectors = []
64
+ for s in sentences:
65
+ input_text = "passage: " + s
66
+ inputs = tokenizer(
67
+ input_text,
68
+ return_tensors="np",
69
+ truncation=True,
70
+ max_length=256
71
+ )
72
+ ort_inputs = {k: v for k, v in inputs.items()}
73
+ ort_outs = session.run(None, ort_inputs)
74
+
75
+ # استخدام CLS pooled output (384D)
76
+ vector = ort_outs[1][0]
77
+ vector = vector / (np.linalg.norm(vector) + 1e-10)
78
+ vectors.append(vector)
79
+
80
+ # المتوسط لإنتاج متجه واحد 1D
81
+ embedding = np.mean(np.stack(vectors, axis=0), axis=0)
82
+ embedding = embedding / (np.linalg.norm(embedding) + 1e-10)
83
+
84
+ return embedding.astype(np.float32)
85
+
86
+ def query_to_embedding(query: str, normalize: bool = True) -> np.ndarray:
87
+ """
88
+ إنشاء embedding لعملية البحث باستخدام 'query:'
89
+ وتستخدم لاستعلامات المستخدم فقط.
90
+ """
91
+ if not query.strip():
92
+ return None
93
+
94
+ # تطبيع النص (اختياري)
95
+ if normalize:
96
+ query = normalize_arabic(query)
97
+
98
+ # تجهيز النص للنموذج
99
+ input_text = "query: " + query
100
+
101
+ # تحويل التوكنيزر إلى مدخلات ONNX
102
  inputs = tokenizer(
103
+ input_text,
104
  return_tensors="np",
105
  truncation=True,
106
+ max_length=256
 
107
  )
108
 
 
109
  ort_inputs = {k: v for k, v in inputs.items()}
 
 
110
 
111
+ # تشغيل النموذج
112
+ ort_outs = session.run(None, ort_inputs)
 
113
 
114
+ # استخدام CLS pooled output (الأفضل للبحث)
115
+ vector = ort_outs[1][0] # (384D)
116
 
117
+ # تطبيع المتجه
118
+ vector = vector / (np.linalg.norm(vector) + 1e-10)
119
+
120
+ return vector.astype(np.float32)