Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -19,6 +19,21 @@ class UniversalAnonymizer:
|
|
| 19 |
'percent': 0
|
| 20 |
}
|
| 21 |
self.api_key = os.getenv("OPENAI_API_KEY", "")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
def anonymize_text(self, original_text, lang='fa'):
|
| 24 |
"""ناشناسسازی جامع با تشخیص خودکار الگوها"""
|
|
@@ -97,13 +112,22 @@ class UniversalAnonymizer:
|
|
| 97 |
|
| 98 |
# الگوهای جامع مبالغ مالی
|
| 99 |
amount_patterns = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
# مبالغ با کاما و نقطه
|
| 101 |
r'\d+,\d{3},\d{3} میلیون ریال',
|
| 102 |
r'\d+\.\d{3}\.\d{3} میلیون ریال',
|
| 103 |
r'\d+,\d{3} میلیارد ریال',
|
| 104 |
r'\d+\.\d{3} میلیارد ریال',
|
| 105 |
|
| 106 |
-
# مبالغ با واحد همت
|
|
|
|
|
|
|
| 107 |
r'\d+\.?\d* همت',
|
| 108 |
r'بیش از \d+\.?\d* همت',
|
| 109 |
r'نزدیک به \d+\.?\d* همت',
|
|
@@ -215,6 +239,9 @@ class UniversalAnonymizer:
|
|
| 215 |
|
| 216 |
# الگوهای جامع نامهای اشخاص
|
| 217 |
person_patterns = [
|
|
|
|
|
|
|
|
|
|
| 218 |
# نامهای کامل با عناوین
|
| 219 |
r'دکتر\s+[آ-ی]+\s+[آ-ی]+\s+[آ-ی]+',
|
| 220 |
r'مهندس\s+[آ-ی]+\s+[آ-ی]+\s+[آ-ی]+',
|
|
@@ -228,12 +255,9 @@ class UniversalAnonymizer:
|
|
| 228 |
r'سیدمحمد\s+[آ-ی]+',
|
| 229 |
r'سیدحسن\s+[آ-ی]+',
|
| 230 |
|
| 231 |
-
# نام و نام خانوادگی ساده
|
| 232 |
-
r'[آ-ی]{3,}\s+[آ-ی]{3,}(?:\s+[آ-ی]{3,})?',
|
| 233 |
-
|
| 234 |
# نامهایی که با مدیرعامل همراه هستند
|
| 235 |
-
r'[آ-ی]+\s+[آ-ی]+\s*،?\s*مدیرعامل',
|
| 236 |
r'[آ-ی]+\s+[آ-ی]+\s+[آ-ی]+\s*،?\s*مدیرعامل',
|
|
|
|
| 237 |
|
| 238 |
# نامهایی که با سمت همراه هستند
|
| 239 |
r'[آ-ی]+\s+[آ-ی]+\s*،?\s*رئیس',
|
|
@@ -245,6 +269,9 @@ class UniversalAnonymizer:
|
|
| 245 |
r'علیرضا\s+[آ-ی]+',
|
| 246 |
r'محمدعلی\s+[آ-ی]+',
|
| 247 |
r'حسینعلی\s+[آ-ی]+',
|
|
|
|
|
|
|
|
|
|
| 248 |
]
|
| 249 |
|
| 250 |
return self._apply_patterns(text, person_patterns, 'person')
|
|
@@ -254,6 +281,12 @@ class UniversalAnonymizer:
|
|
| 254 |
|
| 255 |
# الگوهای جامع نامهای شرکتها
|
| 256 |
company_patterns = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 257 |
# شرکتهای کامل با پرانتز
|
| 258 |
r'شرکت\s+[آ-ی\s]+\([آ-ی\s]+\)',
|
| 259 |
r'بانک\s+[آ-ی\s]+\([آ-ی\s]+\)',
|
|
@@ -264,6 +297,7 @@ class UniversalAnonymizer:
|
|
| 264 |
r'شرکت\s+[آ-ی\s]{5,}',
|
| 265 |
r'شرکت\s+گروه\s+[آ-ی\s]+',
|
| 266 |
r'شرکت\s+سرمایهگذاری\s+[آ-ی\s]+',
|
|
|
|
| 267 |
r'شرکت\s+بیمه\s+[آ-ی\s]+',
|
| 268 |
r'شرکت\s+پتروشیمی\s+[آ-ی\s]+',
|
| 269 |
r'شرکت\s+فولاد\s+[آ-ی\s]+',
|
|
@@ -296,7 +330,8 @@ class UniversalAnonymizer:
|
|
| 296 |
|
| 297 |
# نامهای کوتاه شرکتها (باید در آخر باشند)
|
| 298 |
r'همراه\s+اول',
|
| 299 |
-
r'
|
|
|
|
| 300 |
r'فولاد\s+مبارکه',
|
| 301 |
|
| 302 |
# مجلهها و نشریات
|
|
@@ -319,6 +354,10 @@ class UniversalAnonymizer:
|
|
| 319 |
for match in matches:
|
| 320 |
matched_text = match.group(0)
|
| 321 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 322 |
# اگر قبلاً جایگزین نشده باشد
|
| 323 |
if matched_text not in self.mapping_table and matched_text in text:
|
| 324 |
# بررسی که کلمه کامل باشد (نه بخشی از کلمه بزرگتر)
|
|
@@ -331,6 +370,13 @@ class UniversalAnonymizer:
|
|
| 331 |
|
| 332 |
return text
|
| 333 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 334 |
def _is_complete_word(self, text, match):
|
| 335 |
"""بررسی اینکه آیا کلمه کامل است یا بخشی از کلمه بزرگتر"""
|
| 336 |
start, end = match.span()
|
|
@@ -532,7 +578,7 @@ def update_interface(language):
|
|
| 532 |
|
| 533 |
return [
|
| 534 |
gr.update(value=f"<h1 style='text-align: center; color: #FFD700; font-size: 3.5em; font-weight: bold; text-shadow: 3px 3px 6px rgba(0,0,0,0.5); margin: 20px 0; background: linear-gradient(45deg, #FFD700, #FFA500); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;'>📊 {ui_text['title']}</h1>"),
|
| 535 |
-
gr.update(value=f"<h2 style='direction: {ui_text['direction']};'
|
| 536 |
gr.update(placeholder=ui_text['input_placeholder'], rtl=not is_english),
|
| 537 |
gr.update(value=f"🚀 {ui_text['process_btn']}"),
|
| 538 |
gr.update(value=f"🗑️ {ui_text['clear_btn']}"),
|
|
@@ -647,7 +693,7 @@ with gr.Blocks(title="📊 Universal Anonymization System", theme=gr.themes.Soft
|
|
| 647 |
|
| 648 |
with gr.Row(elem_classes="workflow rtl") as workflow_row:
|
| 649 |
with gr.Column():
|
| 650 |
-
step1_title = gr.HTML('<h2 style="direction: rtl;"
|
| 651 |
|
| 652 |
input_text = gr.Textbox(
|
| 653 |
lines=15,
|
|
@@ -745,8 +791,11 @@ with gr.Blocks(title="📊 Universal Anonymization System", theme=gr.themes.Soft
|
|
| 745 |
)
|
| 746 |
|
| 747 |
if __name__ == "__main__":
|
| 748 |
-
# تست سیستم با
|
| 749 |
-
test_text = """مهدی اخوان
|
|
|
|
|
|
|
|
|
|
| 750 |
|
| 751 |
anonymizer_test = UniversalAnonymizer()
|
| 752 |
result = anonymizer_test.anonymize_text(test_text)
|
|
@@ -756,4 +805,4 @@ if __name__ == "__main__":
|
|
| 756 |
for original, code in anonymizer_test.mapping_table.items():
|
| 757 |
print(f"{original} -> {code}")
|
| 758 |
|
| 759 |
-
app.launch()
|
|
|
|
| 19 |
'percent': 0
|
| 20 |
}
|
| 21 |
self.api_key = os.getenv("OPENAI_API_KEY", "")
|
| 22 |
+
|
| 23 |
+
# لیست عبارات عمومی که نباید ناشناسسازی شوند
|
| 24 |
+
self.common_phrases = [
|
| 25 |
+
'مجمع عمومی عادی سالیانه',
|
| 26 |
+
'مجمع عمومی فوقالعاده',
|
| 27 |
+
'هیئت مدیره',
|
| 28 |
+
'سهامداران محترم',
|
| 29 |
+
'صورتهای مالی',
|
| 30 |
+
'شرکت اصلی',
|
| 31 |
+
'درآمد عملیاتی',
|
| 32 |
+
'سود عملیاتی',
|
| 33 |
+
'زیان انباشته',
|
| 34 |
+
'محصولات گرم',
|
| 35 |
+
'محصولات سرد',
|
| 36 |
+
]
|
| 37 |
|
| 38 |
def anonymize_text(self, original_text, lang='fa'):
|
| 39 |
"""ناشناسسازی جامع با تشخیص خودکار الگوها"""
|
|
|
|
| 112 |
|
| 113 |
# الگوهای جامع مبالغ مالی
|
| 114 |
amount_patterns = [
|
| 115 |
+
# مبالغ با پسوند "ی" - مهم: باید قبل از الگوهای بدون "ی" باشد
|
| 116 |
+
r'\d+ میلیارد تومانی',
|
| 117 |
+
r'\d+ میلیون تومانی',
|
| 118 |
+
r'\d+ هزار تومانی',
|
| 119 |
+
r'\d+\.?\d* میلیارد تومانی',
|
| 120 |
+
r'\d+\.?\d* میلیون تومانی',
|
| 121 |
+
|
| 122 |
# مبالغ با کاما و نقطه
|
| 123 |
r'\d+,\d{3},\d{3} میلیون ریال',
|
| 124 |
r'\d+\.\d{3}\.\d{3} میلیون ریال',
|
| 125 |
r'\d+,\d{3} میلیارد ریال',
|
| 126 |
r'\d+\.\d{3} میلیارد ریال',
|
| 127 |
|
| 128 |
+
# مبالغ با واحد همت - با و بدون اعشار
|
| 129 |
+
r'\d+ همت',
|
| 130 |
+
r'\d+\.\d+ همت',
|
| 131 |
r'\d+\.?\d* همت',
|
| 132 |
r'بیش از \d+\.?\d* همت',
|
| 133 |
r'نزدیک به \d+\.?\d* همت',
|
|
|
|
| 239 |
|
| 240 |
# الگوهای جامع نامهای اشخاص
|
| 241 |
person_patterns = [
|
| 242 |
+
# نامهای خاص که در متن ذکر شده
|
| 243 |
+
r'مهدی اخوان بهابادی',
|
| 244 |
+
|
| 245 |
# نامهای کامل با عناوین
|
| 246 |
r'دکتر\s+[آ-ی]+\s+[آ-ی]+\s+[آ-ی]+',
|
| 247 |
r'مهندس\s+[آ-ی]+\s+[آ-ی]+\s+[آ-ی]+',
|
|
|
|
| 255 |
r'سیدمحمد\s+[آ-ی]+',
|
| 256 |
r'سیدحسن\s+[آ-ی]+',
|
| 257 |
|
|
|
|
|
|
|
|
|
|
| 258 |
# نامهایی که با مدیرعامل همراه هستند
|
|
|
|
| 259 |
r'[آ-ی]+\s+[آ-ی]+\s+[آ-ی]+\s*،?\s*مدیرعامل',
|
| 260 |
+
r'[آ-ی]+\s+[آ-ی]+\s*،?\s*مدیرعامل',
|
| 261 |
|
| 262 |
# نامهایی که با سمت همراه هستند
|
| 263 |
r'[آ-ی]+\s+[آ-ی]+\s*،?\s*رئیس',
|
|
|
|
| 269 |
r'علیرضا\s+[آ-ی]+',
|
| 270 |
r'محمدعلی\s+[آ-ی]+',
|
| 271 |
r'حسینعلی\s+[آ-ی]+',
|
| 272 |
+
|
| 273 |
+
# نام و نام خانوادگی ساده - حداقل 3 حرف برای هر کلمه
|
| 274 |
+
r'[آ-ی]{3,}\s+[آ-ی]{3,}(?:\s+[آ-ی]{3,})?',
|
| 275 |
]
|
| 276 |
|
| 277 |
return self._apply_patterns(text, person_patterns, 'person')
|
|
|
|
| 281 |
|
| 282 |
# الگوهای جامع نامهای شرکتها
|
| 283 |
company_patterns = [
|
| 284 |
+
# نامهای خاص که در متن ذکر شده
|
| 285 |
+
r'شرکت سرمایه گذاری پارسیان',
|
| 286 |
+
r'شرکت سرمایهگذاری پارسیان',
|
| 287 |
+
r'بانک پارسیان',
|
| 288 |
+
r'گروه مالی پارسیان',
|
| 289 |
+
|
| 290 |
# شرکتهای کامل با پرانتز
|
| 291 |
r'شرکت\s+[آ-ی\s]+\([آ-ی\s]+\)',
|
| 292 |
r'بانک\s+[آ-ی\s]+\([آ-ی\s]+\)',
|
|
|
|
| 297 |
r'شرکت\s+[آ-ی\s]{5,}',
|
| 298 |
r'شرکت\s+گروه\s+[آ-ی\s]+',
|
| 299 |
r'شرکت\s+سرمایهگذاری\s+[آ-ی\s]+',
|
| 300 |
+
r'شرکت\s+سرمایه گذاری\s+[آ-ی\s]+',
|
| 301 |
r'شرکت\s+بیمه\s+[آ-ی\s]+',
|
| 302 |
r'شرکت\s+پتروشیمی\s+[آ-ی\s]+',
|
| 303 |
r'شرکت\s+فولاد\s+[آ-ی\s]+',
|
|
|
|
| 330 |
|
| 331 |
# نامهای کوتاه شرکتها (باید در آخر باشند)
|
| 332 |
r'همراه\s+اول',
|
| 333 |
+
r'ایرانخودرو',
|
| 334 |
+
r'ایران خودرو',
|
| 335 |
r'فولاد\s+مبارکه',
|
| 336 |
|
| 337 |
# مجلهها و نشریات
|
|
|
|
| 354 |
for match in matches:
|
| 355 |
matched_text = match.group(0)
|
| 356 |
|
| 357 |
+
# بررسی اینکه آیا عبارت جزو عبارات عمومی است
|
| 358 |
+
if self._is_common_phrase(matched_text):
|
| 359 |
+
continue
|
| 360 |
+
|
| 361 |
# اگر قبلاً جایگزین نشده باشد
|
| 362 |
if matched_text not in self.mapping_table and matched_text in text:
|
| 363 |
# بررسی که کلمه کامل باشد (نه بخشی از کلمه بزرگتر)
|
|
|
|
| 370 |
|
| 371 |
return text
|
| 372 |
|
| 373 |
+
def _is_common_phrase(self, text):
|
| 374 |
+
"""بررسی اینکه آیا عبارت جزو عبارات عمومی است"""
|
| 375 |
+
for phrase in self.common_phrases:
|
| 376 |
+
if phrase.lower() in text.lower():
|
| 377 |
+
return True
|
| 378 |
+
return False
|
| 379 |
+
|
| 380 |
def _is_complete_word(self, text, match):
|
| 381 |
"""بررسی اینکه آیا کلمه کامل است یا بخشی از کلمه بزرگتر"""
|
| 382 |
start, end = match.span()
|
|
|
|
| 578 |
|
| 579 |
return [
|
| 580 |
gr.update(value=f"<h1 style='text-align: center; color: #FFD700; font-size: 3.5em; font-weight: bold; text-shadow: 3px 3px 6px rgba(0,0,0,0.5); margin: 20px 0; background: linear-gradient(45deg, #FFD700, #FFA500); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;'>📊 {ui_text['title']}</h1>"),
|
| 581 |
+
gr.update(value=f"<h2 style='direction: {ui_text['direction']};'>📝 {ui_text['step1']}</h2>"),
|
| 582 |
gr.update(placeholder=ui_text['input_placeholder'], rtl=not is_english),
|
| 583 |
gr.update(value=f"🚀 {ui_text['process_btn']}"),
|
| 584 |
gr.update(value=f"🗑️ {ui_text['clear_btn']}"),
|
|
|
|
| 693 |
|
| 694 |
with gr.Row(elem_classes="workflow rtl") as workflow_row:
|
| 695 |
with gr.Column():
|
| 696 |
+
step1_title = gr.HTML('<h2 style="direction: rtl;">📝 متن ورودی و تنظیمات</h2>')
|
| 697 |
|
| 698 |
input_text = gr.Textbox(
|
| 699 |
lines=15,
|
|
|
|
| 791 |
)
|
| 792 |
|
| 793 |
if __name__ == "__main__":
|
| 794 |
+
# تست سیستم با نمونههای ذکر شده
|
| 795 |
+
test_text = """مهدی اخوان بهابادی در مجمع عمومی عادی سالیانه اعلام کرد درآمد عملیاتی شرکت اصلی به 178 میلیارد تومانی رسیده است.
|
| 796 |
+
در خودروسازان حالا از مرز 305 همت عبور کرده و در سال گذشته سود عملیاتی داشته اما زیان انباشته این شرکت 7.6 همت زیاد شده است.
|
| 797 |
+
تولید محصولات گرم این شرکت به 1000 هزار تن و محصولات سرد به 1378 هزار تن رسید.
|
| 798 |
+
شرکت سرمایه گذاری پارسیان سود خوبی را نشان داد. بانک پارسیان و گروه مالی پارسیان هم عملکرد مثبتی داشتند."""
|
| 799 |
|
| 800 |
anonymizer_test = UniversalAnonymizer()
|
| 801 |
result = anonymizer_test.anonymize_text(test_text)
|
|
|
|
| 805 |
for original, code in anonymizer_test.mapping_table.items():
|
| 806 |
print(f"{original} -> {code}")
|
| 807 |
|
| 808 |
+
app.launch()
|