leilaghomashchi commited on
Commit
b31cee4
·
verified ·
1 Parent(s): 3adfc53

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -692
app.py DELETED
@@ -1,692 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- سیستم ناشناس‌سازی اصلاح شده - حل مشکلات آدرس کامل و شناسایی دقیق‌تر
5
- """
6
-
7
- import gradio as gr
8
- import re
9
- import os
10
- import requests
11
- import time
12
- import logging
13
-
14
- logging.basicConfig(level=logging.INFO)
15
- logger = logging.getLogger(__name__)
16
-
17
- class ImprovedDataAnonymizer:
18
- def __init__(self):
19
- self.mapping_table = {}
20
- self.pattern_categories = {
21
- 'personal_identity': {
22
- 'name_fa': 'اطلاعات شخصی و هویتی',
23
- 'name_en': 'Personal & Identity Information',
24
- 'patterns': ['PERSON', 'ID_NUMBER', 'MIXED_NAMES'],
25
- 'icon': '👤'
26
- },
27
- 'financial': {
28
- 'name_fa': 'اطلاعات مالی',
29
- 'name_en': 'Financial Information',
30
- 'patterns': ['AMOUNT', 'ACCOUNT', 'CARD_NUMBER'],
31
- 'icon': '💰'
32
- },
33
- 'temporal': {
34
- 'name_fa': 'اطلاعات زمانی',
35
- 'name_en': 'Temporal Information',
36
- 'patterns': ['DATE'],
37
- 'icon': '📅'
38
- },
39
- 'location': {
40
- 'name_fa': 'اطلاعات مکانی',
41
- 'name_en': 'Location Information',
42
- 'patterns': ['LOCATION', 'FULL_ADDRESS'],
43
- 'icon': '📍'
44
- },
45
- 'business': {
46
- 'name_fa': 'اطلاعات کسب‌وکار',
47
- 'name_en': 'Business Information',
48
- 'patterns': ['COMPANY', 'BRANCH'],
49
- 'icon': '🏢'
50
- },
51
- 'communication': {
52
- 'name_fa': 'اطلاعات ارتباطی',
53
- 'name_en': 'Communication Information',
54
- 'patterns': ['PHONE', 'EMAIL'],
55
- 'icon': '📞'
56
- }
57
- }
58
-
59
- self.counters = {
60
- 'PERSON': 0, 'ID_NUMBER': 0, 'MIXED_NAMES': 0,
61
- 'AMOUNT': 0, 'ACCOUNT': 0, 'CARD_NUMBER': 0,
62
- 'DATE': 0,
63
- 'LOCATION': 0, 'FULL_ADDRESS': 0,
64
- 'COMPANY': 0, 'BRANCH': 0,
65
- 'PHONE': 0, 'EMAIL': 0
66
- }
67
-
68
- self.api_key = os.getenv("OPENAI_API_KEY", "")
69
-
70
- def get_improved_patterns(self):
71
- """الگوهای بهبود یافته با حل مشکلات شناسایی آدرس کامل"""
72
- return {
73
- # اسامی اشخاص - الگوهای ساده‌تر
74
- 'PERSON': [
75
- r'آقای\s+[\u0600-\u06FF\s]+(?=\s+با|$|،|\.)',
76
- r'خانم\s+[\u0600-\u06FF\s]+(?=\s+با|$|،|\.)',
77
- r'مهندس\s+[\u0600-\u06FF\s]+(?=\s+با|$|،|\.)',
78
- r'دکتر\s+[\u0600-\u06FF\s]+(?=\s+با|$|،|\.)',
79
- r'Mr\.\s+[A-Z][a-z]+\s+[A-Z][a-z]+',
80
- r'Ms\.\s+[A-Z][a-z]+\s+[A-Z][a-z]+',
81
- r'Dr\.\s+[A-Z][a-z]+\s+[A-Z][a-z]+',
82
- ],
83
-
84
- # آدرس‌های کامل - الگوهای ساده‌تر
85
- 'FULL_ADDRESS': [
86
- # الگوی کلی: شهر، خیابان/کوچه، پلاک
87
- r'(?:تهران|اصفهان|مشهد|شیراز|کرج|اهواز|قم|رشت|کرمان|یزد|بوشهر|ارومیه|همدان|بندر عباس|ساری|اردبیل)،\s*(?:خیابان|کوچه|شهرک|بلوار|میدان|کوی|محله)\s+[\u0600-\u06FF\s\u06F0-\u06F9]+(?:،\s*(?:خیابان|کوچه|بلوار|کوی)\s+[\u0600-\u06FF\s\u06F0-\u06F9]+)?(?:،\s*پلاک\s+\d+)?(?:،\s*(?:طبقه|واحد)\s+[\u0600-\u06FF\s\u06F0-\u06F9\d]+)?',
88
-
89
- # الگوی ساده‌تر برای آدرس‌های کوتاه‌تر
90
- r'خیابان\s+[\u0600-\u06FF\s\u06F0-\u06F9]+،\s*کوچه\s+[\u0600-\u06FF\s\u06F0-\u06F9]+،\s*پلاک\s+\d+(?:،\s*(?:طبقه|واحد)\s+[\u0600-\u06FF\s\u06F0-\u06F9\d]+)?',
91
- ],
92
-
93
- # کدهای ملی و شناسه‌ها - جداسازی از شماره تلفن
94
- 'ID_NUMBER': [
95
- r'کد\s+ملی\s+\d{10}',
96
- r'شناسه\s+ملی\s+\d{11}',
97
- r'(?<![0-9])\d{10}(?![0-9])', # کد ملی 10 رقمی مستقل
98
- r'(?<![0-9])\d{11}(?![0-9])', # شناسه 11 رقمی مستقل
99
- ],
100
-
101
- # مبالغ مالی - جداسازی از شماره تلفن
102
- 'AMOUNT': [
103
- r'\d{6,}\s*تومان',
104
- r'مبلغ\s+\d{6,}(?:\s*تومان)?',
105
- r'موجودی\s+حساب\s+[^\s]+\s+حدود\s+\d{6,}\s*تومان',
106
- r'ارزش\s+روز\s+آن\s+\d{6,}\s*تومان',
107
- r'میانگین\s+موجودی\s+حساب\s+وی\s+حدود\s+\d{6,}\s*تومان',
108
- r'\$\d+(?:,\d{3})*(?:\.\d+)?',
109
- ],
110
-
111
- # شماره حساب و کارت بانکی - جداسازی دقیق
112
- 'ACCOUNT': [
113
- r'حساب\s+جاری\s+شماره\s+[\d-]+',
114
- r'شماره\s+[\d-]{8,}(?=\s+در)', # شماره حساب
115
- ],
116
-
117
- 'CARD_NUMBER': [
118
- r'شماره\s+\d{4}-\d{4}-\d{4}-\d{4}', # شماره کارت
119
- r'\d{4}-\d{4}-\d{4}-\d{4}(?=\s+نیز)',
120
- ],
121
-
122
- # شماره تلفن - دقیق‌تر شده
123
- 'PHONE': [
124
- r'شماره\s+تماس\s+09\d{9}',
125
- r'(?<![0-9])09\d{9}(?![0-9])', # شماره موبایل مستقل
126
- r'تلفن[\s:]*0\d{2,3}[-\s]?\d{7,8}',
127
- ],
128
-
129
- # تاریخ - ساده شده
130
- 'DATE': [
131
- r'\d{4}/\d{1,2}/\d{1,2}',
132
- r'\d{1,2}\s+(?:فروردین|اردیبهشت|خرداد|تیر|مرداد|شهریور|مهر|آبان|آذر|دی|بهمن|اسفند)\s+\d{4}',
133
- ],
134
-
135
- # شرکت‌ها - ساده شده
136
- 'COMPANY': [
137
- r'شرکت\s+[\u0600-\u06FF\s]+',
138
- r'بانک\s+[\u0600-\u06FF\s]+',
139
- r'[A-Z][a-zA-Z\s]+(?:Inc|Corp|Corporation|Company|Ltd|Limited|LLC)',
140
- ],
141
-
142
- # شعب و واحدهای تجاری - دقیق‌تر شده
143
- 'BRANCH': [
144
- r'شعبه\s+[\u0600-\u06FF\s]+\s+بانک\s+[\u0600-\u06FF\s]+',
145
- r'شعبه\s+مرکزی\s+بانک\s+[\u0600-\u06FF\s]+',
146
- ],
147
-
148
- # مکان‌ها - شهرها (فقط نام شهرها)
149
- 'LOCATION': [
150
- r'\b(?:تهران|اصفهان|مشهد|شیراز|کرج|اهواز|قم|رشت|کرمان|یزد|بوشهر|ارومیه|همدان|بندر عباس|ساری|اردبیل)\b(?!\s*،)', # فقط نام شهر تنها
151
- r'استان\s+[\u0600-\u06FF\s]+',
152
- r'شهر\s+[\u0600-\u06FF\s]+',
153
- ],
154
-
155
- # ایمیل
156
- 'EMAIL': [
157
- r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}',
158
- ],
159
- }
160
-
161
- def get_category_choices(self, language='fa'):
162
- """دریافت لیست دسته‌بندی‌ها برای چک‌باکس"""
163
- choices = []
164
- for cat_key, cat_info in self.pattern_categories.items():
165
- name = cat_info['name_fa'] if language == 'fa' else cat_info['name_en']
166
- icon = cat_info['icon']
167
- choices.append(f"{icon} {name}")
168
- return choices
169
-
170
- def get_selected_patterns(self, selected_categories, language='fa'):
171
- """تبدیل دسته‌بندی‌های انتخاب شده به لیست الگوها"""
172
- selected_patterns = []
173
-
174
- for cat_key, cat_info in self.pattern_categories.items():
175
- name = cat_info['name_fa'] if language == 'fa' else cat_info['name_en']
176
- icon = cat_info['icon']
177
- category_display = f"{icon} {name}"
178
-
179
- if category_display in selected_categories:
180
- selected_patterns.extend(cat_info['patterns'])
181
-
182
- return selected_patterns
183
-
184
- def anonymize_text(self, original_text, lang='fa', selected_categories=None):
185
- """ناشناس‌سازی متن با الگوهای بهبود یافته"""
186
- try:
187
- if not original_text or not original_text.strip():
188
- return "⚠ Please enter input text!" if lang == 'en' else "⚠ لطفاً متن ورودی را وارد کنید!"
189
-
190
- # ریست متغیرها
191
- self.mapping_table = {}
192
- self.counters = {key: 0 for key in self.counters.keys()}
193
-
194
- anonymized = original_text
195
- found_entities = set()
196
-
197
- # استخراج با الگوهای بهبود یافته
198
- patterns = self.get_improved_patterns()
199
-
200
- # فیلتر کردن الگوها بر اساس انتخاب کاربر
201
- if selected_categories:
202
- selected_pattern_types = self.get_selected_patterns(selected_categories, lang)
203
- patterns = {k: v for k, v in patterns.items() if k in selected_pattern_types}
204
-
205
- logger.info("🔍 Running improved regex extraction...")
206
- logger.info(f"📋 Selected patterns: {list(patterns.keys())}")
207
-
208
- processed_entities = set()
209
-
210
- # ترتیب اولویت بهبود یافته
211
- priority_order = [
212
- 'FULL_ADDRESS', # بالاترین اولویت
213
- 'EMAIL',
214
- 'ID_NUMBER',
215
- 'CARD_NUMBER',
216
- 'ACCOUNT',
217
- 'PHONE',
218
- 'AMOUNT',
219
- 'BRANCH',
220
- 'COMPANY',
221
- 'LOCATION',
222
- 'DATE',
223
- 'PERSON',
224
- 'MIXED_NAMES'
225
- ]
226
-
227
- for category in priority_order:
228
- if category in patterns:
229
- pattern_list = patterns[category]
230
- for pattern in pattern_list:
231
- try:
232
- matches = re.finditer(pattern, original_text, re.IGNORECASE | re.MULTILINE)
233
- for match in matches:
234
- full_match = match.group(0).strip()
235
-
236
- # بررسی تداخل
237
- overlaps = False
238
- match_start, match_end = match.span()
239
-
240
- for proc_start, proc_end in processed_entities:
241
- if not (match_end <= proc_start or match_start >= proc_end):
242
- overlaps = True
243
- break
244
-
245
- # شرایط قبولی - با فیلتر کلمات عمومی
246
- if (not overlaps and
247
- full_match not in found_entities and
248
- full_match not in self.mapping_table and
249
- len(full_match) >= 3 and
250
- not full_match.isspace() and
251
- not self._is_generic_word(full_match)):
252
-
253
- self.counters[category] += 1
254
- code = f"{category.lower()}_{self.counters[category]:03d}"
255
- self.mapping_table[full_match] = code
256
- found_entities.add(full_match)
257
- processed_entities.add((match_start, match_end))
258
-
259
- logger.info(f"✅ Found {category}: '{full_match}' → {code}")
260
-
261
- except re.error as e:
262
- logger.error(f"Regex error in pattern {pattern}: {e}")
263
- continue
264
-
265
- # جایگزینی در متن - طولانی‌ترین‌ها اول
266
- sorted_items = sorted(self.mapping_table.items(), key=lambda x: len(x[0]), reverse=True)
267
- logger.info(f"🔄 Replacing {len(sorted_items)} entities...")
268
-
269
- for original_item, code in sorted_items:
270
- anonymized = anonymized.replace(original_item, code)
271
- logger.info(f"🔄 Replaced: '{original_item}' → '{code}'")
272
-
273
- logger.info(f"✅ Anonymization completed. Found {len(self.mapping_table)} entities.")
274
-
275
- # اگر هیچ entity پیدا نشد
276
- if len(self.mapping_table) == 0:
277
- logger.warning("⚠ No entities found! Check if text contains recognizable patterns.")
278
- return original_text + "\n\n⚠ هیچ entity قابل شناسایی پیدا نشد! لطفاً متن را بررسی کنید."
279
-
280
- return anonymized
281
-
282
- except Exception as e:
283
- logger.error(f"Anonymization error: {e}")
284
- return f"⚠ Error in anonymization: {str(e)}" if lang == 'en' else f"⚠ خطا در ناشناس‌سازی: {str(e)}"
285
-
286
- def _is_generic_word(self, text):
287
- """بررسی کلمات عمومی که نباید entity محسوب شوند"""
288
- generic_words = {
289
- 'همین بانک', 'این بانک', 'آن بانک', 'بانک مذکور',
290
- 'همین شرکت', 'این شرکت', 'آن شرکت', 'شرکت مذکور',
291
- 'همین شعبه', 'این شعبه', 'آن شعبه', 'شعبه مذکور',
292
- 'همین شهر', 'این شهر', 'آن شهر',
293
- 'متقاضی', 'ایشان', 'وی', 'مشتری',
294
- 'بانک', 'شرکت', 'شعبه' # کلمات تنها
295
- }
296
- return text.strip() in generic_words or len(text.strip()) < 3
297
-
298
- def send_to_chatgpt(self, anonymized_text, lang='fa'):
299
- """ارسال به ChatGPT"""
300
- try:
301
- if not anonymized_text or not anonymized_text.strip():
302
- return "⚠ Anonymized text is empty!" if lang == 'en' else "⚠ متن ناشناس‌شده خالی است!"
303
-
304
- if not self.api_key:
305
- return "⚠ API Key not configured!" if lang == 'en' else "⚠ کلید API تنظیم نشده است!"
306
-
307
- system_msg = "You are a professional analyst. Answer questions accurately." if lang == 'en' else "شما یک تحلیل‌گر حرفه‌ای هستید. به سوالات با دقت پاسخ دهید."
308
-
309
- headers = {
310
- "Authorization": f"Bearer {self.api_key}",
311
- "Content-Type": "application/json"
312
- }
313
-
314
- data = {
315
- "model": "gpt-4o-mini",
316
- "messages": [
317
- {"role": "system", "content": system_msg},
318
- {"role": "user", "content": anonymized_text}
319
- ],
320
- "max_tokens": 2000,
321
- "temperature": 0.7
322
- }
323
-
324
- response = requests.post(
325
- "https://api.openai.com/v1/chat/completions",
326
- headers=headers,
327
- json=data,
328
- timeout=30
329
- )
330
-
331
- if response.status_code == 200:
332
- result = response.json()
333
- return result['choices'][0]['message']['content']
334
- else:
335
- error_data = response.json() if response.content else {}
336
- error_message = error_data.get('error', {}).get('message', response.text)
337
- return f"⚠ API Error: {error_message}"
338
-
339
- except Exception as e:
340
- return f"⚠ Error connecting to ChatGPT: {str(e)}" if lang == 'en' else f"⚠ خطا در ارتباط با ChatGPT: {str(e)}"
341
-
342
- def deanonymize_response(self, gpt_response, lang='fa'):
343
- """بازگردانی"""
344
- try:
345
- if not gpt_response or not gpt_response.strip():
346
- return "⚠ ChatGPT response is empty!" if lang == 'en' else "⚠ پاسخ ChatGPT خالی است!"
347
-
348
- if not self.mapping_table:
349
- return "⚠ Mapping table is empty!" if lang == 'en' else "⚠ جدول نگاشت خالی است!"
350
-
351
- final_result = gpt_response
352
- reverse_mapping = {code: original for original, code in self.mapping_table.items()}
353
-
354
- sorted_codes = sorted(reverse_mapping.items(), key=lambda x: len(x[0]), reverse=True)
355
- for code, original in sorted_codes:
356
- final_result = final_result.replace(code, original)
357
-
358
- return final_result
359
-
360
- except Exception as e:
361
- return f"⚠ Deanonymization error: {str(e)}" if lang == 'en' else f"⚠ خطا در بازگردانی: {str(e)}"
362
-
363
- def get_model_status(self):
364
- """وضعیت سیستم"""
365
- status = "🚀 **سیستم ناشناس‌سازی بهبود یافته - نسخه اصلاح شده:**\n\n"
366
-
367
- status += "• **مشکلات حل شده:**\n"
368
- status += " ✅ آدرس کامل به عنوان یک entity واحد\n"
369
- status += " ✅ حذف کلمات عمومی مثل 'همین بانک'\n"
370
- status += " ✅ اولویت‌بندی بهتر برای آدرس کامل\n"
371
- status += " ✅ جداسازی دقیق کد ملی از شماره تلفن\n"
372
- status += " ✅ جداسازی مبالغ مالی از شماره تلفن\n"
373
- status += " ✅ شماره حساب و کارت بانکی جداگانه\n"
374
- status += " ✅ debugging و logging بهتر\n\n"
375
-
376
- status += "• **بهبودهای الگو:**\n"
377
- status += " 🎯 الگوی جامع برای آدرس کامل فارسی\n"
378
- status += " 🎯 فیلتر کلمات عمومی\n"
379
- status += " 🎯 اولویت‌بندی بهتر پردازش\n"
380
- status += " 🎯 حذف تداخل‌های غلط\n"
381
- status += " 🎯 encoding صحیح فارسی\n\n"
382
-
383
- status += f"📊 **دسته‌بندی‌های موجود:**\n"
384
- for cat_key, cat_info in self.pattern_categories.items():
385
- icon = cat_info['icon']
386
- name_fa = cat_info['name_fa']
387
- pattern_count = len(cat_info['patterns'])
388
- status += f" {icon} {name_fa}: {pattern_count} الگو\n"
389
-
390
- return status
391
-
392
- # ایجاد instance
393
- anonymizer = ImprovedDataAnonymizer()
394
-
395
- def process_all_steps(input_text, language, selected_categories):
396
- """پردازش خودکار تمام مراحل - نسخه اصلاح شده"""
397
- lang = 'en' if language == 'English' else 'fa'
398
-
399
- if not input_text.strip():
400
- error_msg = "⚠ Please enter input text!" if lang == 'en' else "⚠ لطفاً متن ورودی را وارد کنید!"
401
- return error_msg, "", "", ""
402
-
403
- try:
404
- start_time = time.time()
405
-
406
- logger.info(f"🔄 Starting anonymization process...")
407
- logger.info(f"📝 Input text length: {len(input_text)} characters")
408
- logger.info(f"📋 Selected categories: {selected_categories}")
409
-
410
- anonymized_text = anonymizer.anonymize_text(input_text, lang, selected_categories)
411
- if anonymized_text.startswith("⚠"):
412
- return anonymized_text, "", "", ""
413
-
414
- gpt_response = anonymizer.send_to_chatgpt(anonymized_text, lang)
415
- if gpt_response.startswith("⚠"):
416
- entities_found = len(anonymizer.mapping_table)
417
- selected_count = len(selected_categories) if selected_categories else 0
418
-
419
- success_msg = (f"✅ ناشناس‌سازی اصلاح شده انجام شد!\n"
420
- f"📋 دسته‌های انتخابی: {selected_count} | 🔍 پردازش آدرس کامل\n"
421
- f"📊 کل entities محافظت شده: {entities_found} | 🎯 مشکلات حل شده!")
422
- return success_msg, anonymized_text, gpt_response, ""
423
-
424
- final_result = anonymizer.deanonymize_response(gpt_response, lang)
425
-
426
- total_time = time.time() - start_time
427
- entities_found = len(anonymizer.mapping_table)
428
- selected_count = len(selected_categories) if selected_categories else 6
429
-
430
- success_msg = (f"🎉 ناشناس‌سازی کامل و بازگردانی موفق!\n"
431
- f"🔧 روش: پردازش اصلاح شده | 📋 دسته‌ها: {selected_count}/6\n"
432
- f"📊 کل: {entities_found} entities | ⏱️ زمان: {total_time:.2f}s\n"
433
- f"⚡ مشکلات آدرس کامل حل شدند!")
434
-
435
- return success_msg, anonymized_text, gpt_response, final_result
436
-
437
- except Exception as e:
438
- error_msg = f"⚠ Processing error: {str(e)}" if lang == 'en' else f"⚠ خطا در پردازش: {str(e)}"
439
- logger.error(f"Processing error: {e}")
440
- return error_msg, "", "", ""
441
-
442
- def get_mapping_table(language):
443
- """نمایش جدول نگاشت"""
444
- lang = 'en' if language == 'English' else 'fa'
445
-
446
- if not anonymizer.mapping_table:
447
- return "⚠ Mapping table is empty!" if lang == 'en' else "⚠ جدول نگاشت خالی است!"
448
-
449
- result = "📋 **جدول نگاشت اصلاح شده:**\n\n"
450
-
451
- # نمایش آمار کلی
452
- result += f"📊 **آمار**: {len(anonymizer.mapping_table)} entity\n"
453
- result += f"🔍 **روش**: پردازش آدرس کامل اصلاح شده\n"
454
- result += f"⚡ **حالت**: شناسایی دقیق entities و فیلتر کلمات عمومی\n\n"
455
-
456
- # دسته‌بندی نتایج
457
- category_stats = {}
458
- for original, code in anonymizer.mapping_table.items():
459
- category = code.split('_')[0].upper()
460
- if category not in category_stats:
461
- category_stats[category] = []
462
- category_stats[category].append((original, code))
463
-
464
- # نمایش نتایج بر اساس دسته‌بندی
465
- for category, items in category_stats.items():
466
- if len(items) > 0:
467
- result += f"🔍 **{category}** ({len(items)} مورد):\n"
468
- for original, code in items:
469
- result += f" • `{original}` → `{code}`\n"
470
- result += "\n"
471
-
472
- result += "✨ **سیستم اصلاح شده**: تشخیص آدرس کامل و حذف کلمات عمومی!"
473
-
474
- return result
475
-
476
- def clear_all():
477
- """پاک کردن همه"""
478
- anonymizer.mapping_table = {}
479
- anonymizer.counters = {key: 0 for key in anonymizer.counters.keys()}
480
- logger.info("🗑️ All data cleared")
481
- return "", "", "", "", ""
482
-
483
- # رابط کاربری Gradio
484
- custom_css = """
485
- body, .gradio-container {
486
- font-family: 'Segoe UI', Tahoma, Arial, sans-serif !important;
487
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
488
- min-height: 100vh !important;
489
- padding: 20px !important;
490
- }
491
-
492
- .gradio-textbox {
493
- border-radius: 10px !important;
494
- box-shadow: 0 4px 15px rgba(0,0,0,0.1) !important;
495
- min-height: 300px !important;
496
- }
497
-
498
- .status-box {
499
- background: linear-gradient(135deg, #4CAF50, #45a049) !important;
500
- border: 3px solid #2E7D32 !important;
501
- border-radius: 15px !important;
502
- padding: 15px !important;
503
- margin: 10px 0 !important;
504
- box-shadow: 0 8px 32px rgba(76, 175, 80, 0.3) !important;
505
- }
506
-
507
- .gradio-button {
508
- border-radius: 25px !important;
509
- font-weight: bold !important;
510
- transition: all 0.3s ease !important;
511
- margin: 5px 0 !important;
512
- min-height: 50px !important;
513
- }
514
-
515
- h1 {
516
- background: linear-gradient(45deg, #FFD700, #FFA500) !important;
517
- -webkit-background-clip: text !important;
518
- -webkit-text-fill-color: transparent !important;
519
- background-clip: text !important;
520
- text-align: center !important;
521
- }
522
- """
523
-
524
- with gr.Blocks(title="🔧 سیستم ناشناس‌سازی اصلاح شده", theme=gr.themes.Soft(), css=custom_css) as app:
525
-
526
- with gr.Column():
527
- gr.HTML("<h1>🔧 سیستم ناشناس‌سازی اصلاح شده - حل مشکلات آدرس کامل</h1>")
528
-
529
- with gr.Row():
530
- language_selector = gr.Radio(
531
- choices=["فارسی", "English"],
532
- value="فارسی",
533
- label="Language / زبان",
534
- interactive=True
535
- )
536
-
537
- # بخش انتخاب دسته‌بندی‌ها
538
- with gr.Row():
539
- with gr.Column():
540
- gr.HTML("<h3 style='text-align: center; color: #1976D2;'>🎯 انتخاب دسته‌بندی‌های الگو</h3>")
541
-
542
- pattern_categories = gr.CheckboxGroup(
543
- choices=anonymizer.get_category_choices('fa'),
544
- value=anonymizer.get_category_choices('fa'),
545
- label="انتخاب دسته‌بندی‌های الگو:",
546
- interactive=True
547
- )
548
-
549
- gr.HTML("""
550
- <div style='background: rgba(255, 255, 255, 0.9); padding: 15px; border-radius: 10px; margin-top: 10px;'>
551
- <p style='margin: 0; color: #666; font-size: 0.9em; text-align: center;'>
552
- 🔧 <strong>اصلاحات:</strong> آدرس کامل، حذف کلمات عمومی، اولویت‌بندی بهتر
553
- </p>
554
- </div>
555
- """)
556
-
557
- with gr.Row():
558
- with gr.Column(scale=1):
559
- gr.HTML('<h2>📝 متن ورودی</h2>')
560
-
561
- input_text = gr.Textbox(
562
- lines=15,
563
- placeholder="""متن اصلی خود را اینجا وارد کنید...
564
- مثال متن مشکل‌دار شما:
565
- آقای علی احمدی با کد ملی 0123456789 در تاریخ 1402/09/15 درخواست تسهیلات بانکی به مبلغ 500000000 تومان از شعبه مرکزی بانک ملی ارائه نموده است. ایشان ساکن تهران، خیابان ولیعصر، کوچه نیلوفر، پلاک 128، طبقه سوم بوده و شماره تماس 09123456789 را اعلام نموده‌اند...
566
-
567
- 🔧 حالا مشکلات حل شده‌اند!""",
568
- label="",
569
- rtl=True
570
- )
571
-
572
- with gr.Row():
573
- process_btn = gr.Button("🚀 پردازش با الگوهای اصلاح شده", variant="primary")
574
- clear_btn = gr.Button("🗑️ پاک کردن همه", variant="stop")
575
-
576
- status = gr.Textbox(
577
- label="وضعیت",
578
- lines=4,
579
- interactive=False,
580
- rtl=True,
581
- elem_classes=["status-box"]
582
- )
583
-
584
- with gr.Column(scale=1):
585
- gr.HTML('<h2>🎭 متن ناشناس‌شده</h2>')
586
-
587
- anonymized_output = gr.Textbox(
588
- lines=15,
589
- placeholder="""متن ناشناس‌شده اینجا نمایش داده می‌شود...
590
- انتظار می‌رود:
591
- - person_001 به جای آقای علی احمدی
592
- - full_address_001 به جای تهران، خیابان ولیعصر، کوچه نیلوفر، پلاک 128، طبقه سوم
593
- - amount_001 به جای 500000000 تومان
594
- - و سایر موارد...""",
595
- label="",
596
- interactive=False,
597
- rtl=True
598
- )
599
-
600
- with gr.Row():
601
- with gr.Column(scale=1):
602
- gr.HTML('<h2>🤖 پاسخ خام ChatGPT</h2>')
603
-
604
- gpt_output = gr.Textbox(
605
- lines=10,
606
- placeholder="پاسخ خام ChatGPT اینجا نمایش داده می‌شود...",
607
- label="",
608
- interactive=False,
609
- rtl=True
610
- )
611
-
612
- with gr.Column(scale=1):
613
- gr.HTML('<h2>✅ پاسخ نهایی بازگردانده شده</h2>')
614
-
615
- final_output = gr.Textbox(
616
- lines=10,
617
- placeholder="پاسخ نهایی اینجا نمایش داده می‌شود...",
618
- label="",
619
- interactive=False,
620
- rtl=True
621
- )
622
-
623
- with gr.Row():
624
- with gr.Column():
625
- gr.HTML('<h2>📋 جدول نگاشت</h2>')
626
- mapping_btn = gr.Button("📋 نمایش جدول نگاشت اصلاح شده")
627
-
628
- mapping_output = gr.Textbox(
629
- lines=15,
630
- label="جدول نگاشت اطلاعات",
631
- interactive=False,
632
- visible=False,
633
- rtl=True
634
- )
635
-
636
- with gr.Row():
637
- with gr.Column():
638
- gr.HTML('<h2>⚙️ وضعیت سیستم</h2>')
639
- system_status_btn = gr.Button("📊 نمایش وضعیت سیستم اصلاح شده")
640
-
641
- system_status_output = gr.Textbox(
642
- lines=20,
643
- label="وضعیت سیستم",
644
- interactive=False,
645
- visible=False,
646
- rtl=True
647
- )
648
-
649
- # Event handlers
650
- process_btn.click(
651
- fn=process_all_steps,
652
- inputs=[input_text, language_selector, pattern_categories],
653
- outputs=[status, anonymized_output, gpt_output, final_output]
654
- )
655
-
656
- clear_btn.click(
657
- fn=clear_all,
658
- outputs=[input_text, anonymized_output, gpt_output, final_output, status]
659
- )
660
-
661
- mapping_btn.click(
662
- fn=get_mapping_table,
663
- inputs=[language_selector],
664
- outputs=[mapping_output]
665
- )
666
-
667
- mapping_btn.click(
668
- fn=lambda: gr.update(visible=True),
669
- outputs=[mapping_output]
670
- )
671
-
672
- system_status_btn.click(
673
- fn=lambda: anonymizer.get_model_status(),
674
- outputs=[system_status_output]
675
- )
676
-
677
- system_status_btn.click(
678
- fn=lambda: gr.update(visible=True),
679
- outputs=[system_status_output]
680
- )
681
-
682
- if __name__ == "__main__":
683
- logger.info("🔧 Starting Fixed Anonymization System...")
684
- logger.info("✅ Fixed issues: encoding, regex patterns, debugging")
685
- logger.info("🎯 Ready for accurate entity detection!")
686
-
687
- app.launch(
688
- share=False,
689
- server_name="0.0.0.0",
690
- server_port=7860,
691
- show_error=True
692
- )