chunking_test / modules /normalizer.py
leilaghomashchi's picture
Upload 5 files
dfbf6c3 verified
"""
🔄 نرمال‌سازی موجودیت‌ها
Entity Normalization for better matching
"""
import re
import logging
logger = logging.getLogger(__name__)
class EntityNormalizer:
"""
کلاس برای نرمال‌سازی موجودیت‌های مختلف
این کلاس موجودیت‌ها را به فرمت استاندارد تبدیل می‌کند تا:
- تطابق دقیق بهتر انجام شود
- fuzzy matching موثرتر باشد
- از تکرار جلوگیری شود
"""
def __init__(self):
"""مقداردهی اولیه normalizer"""
logger.info("✅ EntityNormalizer initialized")
# نقشه تبدیل اعداد فارسی به انگلیسی
self.persian_to_english = str.maketrans('۰۱۲۳۴۵۶۷۸۹', '0123456789')
def normalize(self, text: str, entity_type: str) -> str:
"""
نرمال‌سازی بر اساس نوع موجودیت
Args:
text: متن اصلی موجودیت
entity_type: نوع موجودیت (person/company/amount/percent)
Returns:
متن نرمال‌شده
Examples:
>>> normalizer = EntityNormalizer()
>>> normalizer.normalize("آقای علی احمدی", "person")
'علی احمدی'
>>> normalizer.normalize("۵۰ میلیارد ریال", "amount")
'50 میلیارد ریال'
"""
if not text:
return ""
# انتخاب متد مناسب بر اساس نوع
if entity_type == "person":
return self.normalize_person(text)
elif entity_type == "company":
return self.normalize_company(text)
elif entity_type == "amount":
return self.normalize_amount(text)
elif entity_type == "percent":
return self.normalize_percent(text)
else:
logger.warning(f"⚠️ Unknown entity type: {entity_type}, using basic normalization")
return self._basic_normalize(text)
def _basic_normalize(self, text: str) -> str:
"""نرمال‌سازی پایه برای هر متنی"""
text = text.strip().lower()
text = re.sub(r'\s+', ' ', text)
return text
def normalize_person(self, text: str) -> str:
"""
نرمال‌سازی اسامی اشخاص
- حذف فضاهای اضافی
- lowercase
- حذف عناوین (آقای، خانم، دکتر، ...)
Args:
text: نام شخص
Returns:
نام نرمال‌شده
Examples:
>>> normalizer.normalize_person("آقای علی احمدی")
'علی احمدی'
>>> normalizer.normalize_person("دکتر مریم کریمی")
'مریم کریمی'
"""
text = text.strip().lower()
# حذف فضاهای اضافی
text = re.sub(r'\s+', ' ', text)
# حذف عناوین رایج
titles = [
'آقای', 'خانم', 'خانوم',
'دکتر', 'دکتور', 'dr.',
'مهندس', 'استاد', 'اقای',
'جناب', 'سرکار',
]
for title in titles:
# حذف عنوان از ابتدای متن
pattern = rf'^{title}\s+'
text = re.sub(pattern, '', text, flags=re.IGNORECASE)
return text.strip()
def normalize_company(self, text: str) -> str:
"""
نرمال‌سازی نام شرکت‌ها
- حذف فضاهای اضافی
- lowercase
- استانداردسازی اختصارات (ش. → شرکت)
- حذف کلمات اضافی پایانی
Args:
text: نام شرکت
Returns:
نام نرمال‌شده
Examples:
>>> normalizer.normalize_company("ش. پارس")
'شرکت پارس'
>>> normalizer.normalize_company("شرکت ملی نفت ایران")
'شرکت ملی نفت'
"""
text = text.strip().lower()
# حذف فضاهای اضافی
text = re.sub(r'\s+', ' ', text)
# استانداردسازی اختصارات
replacements = {
'ش.': 'شرکت',
'ش ': 'شرکت ',
'شرکت‌': 'شرکت',
'بانک‌': 'بانک',
'سازمان‌': 'سازمان',
'موسسه‌': 'موسسه',
'گروه‌': 'گروه',
}
for old, new in replacements.items():
text = text.replace(old, new)
# حذف کلمات اضافی پایانی که معمولاً اختیاری هستند
# مثلاً "شرکت ملی نفت ایران" → "شرکت ملی نفت"
optional_suffixes = [
r'\s+ایران$',
r'\s+تهران$',
r'\s+خصوصی$',
r'\s+عام$',
r'\s+سهامی$',
r'\s+سهامی\s+عام$',
r'\s+سهامی\s+خاص$',
]
for pattern in optional_suffixes:
text = re.sub(pattern, '', text)
return text.strip()
def normalize_amount(self, text: str) -> str:
"""
نرمال‌سازی مبالغ مالی
- تبدیل اعداد فارسی به انگلیسی
- حذف فضاهای اضافی
- lowercase
- استانداردسازی واحدها
Args:
text: مبلغ مالی
Returns:
مبلغ نرمال‌شده
Examples:
>>> normalizer.normalize_amount("۵۰ میلیارد ریال")
'50 میلیارد ریال'
>>> normalizer.normalize_amount("30 میلیارد تومن")
'30 میلیارد تومان'
"""
# تبدیل اعداد فارسی به انگلیسی
text = text.translate(self.persian_to_english)
text = text.strip().lower()
# حذف فضاهای اضافی
text = re.sub(r'\s+', ' ', text)
# استانداردسازی واحدهای پولی
unit_map = {
'تومن': 'تومان',
'ریآل': 'ریال',
'ريال': 'ریال',
'دالر': 'دلار',
'يورو': 'یورو',
}
for old, new in unit_map.items():
text = text.replace(old, new)
# استانداردسازی واحدهای مقیاس
scale_map = {
'ميليارد': 'میلیارد',
'ميليون': 'میلیون',
'هزار': 'هزار',
'تریلیون': 'تریلیون',
}
for old, new in scale_map.items():
text = text.replace(old, new)
# حذف صفات اضافی (مثلاً "ریالی" → "ریال")
text = text.replace('ریالی', 'ریال')
text = text.replace('تومانی', 'تومان')
text = text.replace('دلاری', 'دلار')
return text.strip()
def normalize_percent(self, text: str) -> str:
"""
نرمال‌سازی درصدها
- تبدیل اعداد فارسی به انگلیسی
- یکسان‌سازی علامت درصد (%, ٪ → درصد)
- فرمت استاندارد: "عدد درصد"
Args:
text: درصد
Returns:
درصد نرمال‌شده
Examples:
>>> normalizer.normalize_percent("۱۵٪")
'15 درصد'
>>> normalizer.normalize_percent("20%")
'20 درصد'
>>> normalizer.normalize_percent("25 درصدی")
'25 درصد'
"""
# تبدیل اعداد فارسی به انگلیسی
text = text.translate(self.persian_to_english)
text = text.strip()
# حذف فضاهای اضافی
text = re.sub(r'\s+', ' ', text)
# یکسان‌سازی علامت‌های درصد
text = text.replace('٪', '%')
# تبدیل به فرمت استاندارد: "عدد درصد"
# مثال: "15%" → "15 درصد"
text = re.sub(r'(\d+(?:\.\d+)?)\s*[%٪]', r'\1 درصد', text)
# حذف "درصدی" و تبدیل به "درصد"
text = re.sub(r'(\d+(?:\.\d+)?)\s*درصدی', r'\1 درصد', text)
return text.strip()
# ✅ تست‌های سریع
if __name__ == "__main__":
print("=" * 60)
print("🧪 Testing Normalizer Module")
print("=" * 60)
normalizer = EntityNormalizer()
# تست 1: Person normalization
print("\n📊 Test 1: Person Normalization")
person_tests = [
"آقای علی احمدی",
"دکتر مریم کریمی",
"خانم سارا رضایی",
"علی محمدی"
]
for person in person_tests:
normalized = normalizer.normalize_person(person)
print(f" '{person}' → '{normalized}'")
# تست 2: Company normalization
print("\n📊 Test 2: Company Normalization")
company_tests = [
"شرکت پارس",
"ش. ملی نفت ایران",
"شرکت صبا سهامی خاص",
"بانک ملی ایران"
]
for company in company_tests:
normalized = normalizer.normalize_company(company)
print(f" '{company}' → '{normalized}'")
# تست 3: Amount normalization
print("\n📊 Test 3: Amount Normalization")
amount_tests = [
"۵۰ میلیارد ریال",
"30 میلیارد تومن",
"100 میلیارد ریالی",
"5 ميليون دلار"
]
for amount in amount_tests:
normalized = normalizer.normalize_amount(amount)
print(f" '{amount}' → '{normalized}'")
# تست 4: Percent normalization
print("\n📊 Test 4: Percent Normalization")
percent_tests = [
"۱۵٪",
"20%",
"25 درصدی",
"30 درصد"
]
for percent in percent_tests:
normalized = normalizer.normalize_percent(percent)
print(f" '{percent}' → '{normalized}'")
print("\n" + "=" * 60)
print("✅ All tests completed!")
print("=" * 60)