leilaghomashchi commited on
Commit
da4ac67
·
verified ·
1 Parent(s): eb9ab1a

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -459
app.py DELETED
@@ -1,459 +0,0 @@
1
- import gradio as gr
2
- import re
3
- import os
4
- import requests
5
- import logging
6
- from typing import Dict, List, Tuple
7
-
8
- logging.basicConfig(level=logging.INFO)
9
- logger = logging.getLogger(__name__)
10
-
11
- class AnonymizerAdvanced:
12
- """ناشناس‌ساز پیشرفته با روش‌های متعدد"""
13
-
14
- def __init__(self, cerebras_key: str = None, gpt_key: str = None):
15
- self.cerebras_key = cerebras_key or os.getenv("CEREBRAS_API_KEY")
16
- self.gpt_key = gpt_key or os.getenv("OPENAI_API_KEY")
17
- self.mapping_table = {} # {placeholder: original_text}
18
- self.reverse_mapping = {} # {original_text: placeholder}
19
-
20
- logger.info("✅ Anonymizer Advanced مقداردهی شد")
21
-
22
- def anonymize_with_regex(self, text: str) -> Tuple[str, Dict]:
23
- """ناشناس‌سازی با Regex"""
24
- logger.info("🔍 روش Regex...")
25
-
26
- anonymized = text
27
- mapping = {}
28
- counters = {'person': 0, 'company': 0, 'amount': 0, 'percent': 0}
29
-
30
- patterns = [
31
- ('percent', r'\d+(?:\.\d+)?\s*(?:درصد|%|درصدی)'),
32
- ('amount', r'\d+(?:\.\d+)?\s*(?:میلیارد|میلیون|هزار|تومان|ریال|دلار|تن|دستگاه|یورو)'),
33
- ('company', r'(?:شرکت|بانک|سازمان|گروه|هلدینگ|گمرک|دپارتمان|شعبه|اداره)\s+[ء-ي]+(?:\s+[ء-ي]+)*'),
34
- ('person', r'\b[ء-ي]+\s+[ء-ي]+(?:\s+[ء-ي]+)*\b'),
35
- ]
36
-
37
- for entity_type, pattern in patterns:
38
- for match in re.finditer(pattern, anonymized):
39
- text_match = match.group()
40
- key = text_match.lower().strip()
41
-
42
- if key not in mapping:
43
- counters[entity_type] += 1
44
- placeholder = f"{entity_type}-{counters[entity_type]:02d}"
45
- mapping[key] = {'placeholder': placeholder, 'type': entity_type}
46
- self.mapping_table[placeholder] = text_match
47
- self.reverse_mapping[text_match] = placeholder
48
-
49
- # جایگزینی متن
50
- for original, info in mapping.items():
51
- anonymized = anonymized.replace(original, info['placeholder'])
52
-
53
- logger.info(f"✅ Regex: {sum(counters.values())} موجودیت")
54
- return anonymized, self.mapping_table
55
-
56
- def anonymize_with_cerebras(self, text: str) -> Tuple[str, Dict]:
57
- """ناشناس‌سازی با Cerebras"""
58
- logger.info("🧠 روش Cerebras...")
59
-
60
- if not self.cerebras_key:
61
- logger.warning("⚠️ Cerebras API Key نیست - استفاده از Regex")
62
- return self.anonymize_with_regex(text)
63
-
64
- try:
65
- prompt = f"""متن زیر را ناشناس کنید. قوانین:
66
- 1. اسامی اشخاص → person-01, person-02, ...
67
- 2. نام شرکت‌ها/سازمان‌ها → company-01, company-02, ...
68
- 3. مقادیر پولی → amount-01, amount-02, ...
69
- 4. درصدها → percent-01, percent-02, ...
70
- 5. فقط این توکن‌ها استفاده کنید
71
- 6. شماره‌های نسخه را درست حفظ کنید
72
- 7. اگر موجودیت تکرار شود از شماره قدیمی استفاده کنید
73
-
74
- متن:
75
- {text}
76
-
77
- خروجی: فقط متن ناشناس شده"""
78
-
79
- response = requests.post(
80
- "https://api.cerebras.ai/v1/chat/completions",
81
- headers={
82
- "Authorization": f"Bearer {self.cerebras_key}",
83
- "Content-Type": "application/json"
84
- },
85
- json={
86
- "model": "llama-3.3-70b",
87
- "messages": [{"role": "user", "content": prompt}],
88
- "max_tokens": 4096,
89
- "temperature": 0.1
90
- },
91
- timeout=60
92
- )
93
-
94
- if response.status_code == 200:
95
- anonymized_text = response.json()['choices'][0]['message']['content'].strip()
96
- logger.info("✅ Cerebras: موفق")
97
-
98
- # استخراج mapping از متن
99
- self._extract_mapping_from_text(text, anonymized_text)
100
- return anonymized_text, self.mapping_table
101
- else:
102
- logger.error(f"❌ Cerebras Error")
103
- return self.anonymize_with_regex(text)
104
-
105
- except Exception as e:
106
- logger.error(f"❌ Cerebras Exception: {e}")
107
- return self.anonymize_with_regex(text)
108
-
109
- def anonymize_combined(self, text: str) -> Tuple[str, Dict]:
110
- """روش ترکیبی: Regex + Cerebras"""
111
- logger.info("⚙️ روش ترکیبی...")
112
-
113
- # Step 1: Regex برای شناسایی سریع
114
- anonymized_regex, _ = self.anonymize_with_regex(text)
115
-
116
- # Step 2: اگر Cerebras موجود باشد، بهبود دهد
117
- if self.cerebras_key:
118
- try:
119
- prompt = f"""متن اصلی:
120
- {text}
121
-
122
- متن ناشناس شده توسط Regex:
123
- {anonymized_regex}
124
-
125
- قوانین:
126
- 1. تمام موجودیت‌های حساس را شناسایی کنید
127
- 2. اگر Regex چیزی را از دست داده است، اضافه کنید
128
- 3. شماره‌گذاری را حفظ کنید (person-01 همان person-01 بماند)
129
- 4. تنها متن ناشناس شده را برگردانید"""
130
-
131
- response = requests.post(
132
- "https://api.cerebras.ai/v1/chat/completions",
133
- headers={
134
- "Authorization": f"Bearer {self.cerebras_key}",
135
- "Content-Type": "application/json"
136
- },
137
- json={
138
- "model": "llama-3.3-70b",
139
- "messages": [{"role": "user", "content": prompt}],
140
- "max_tokens": 4096,
141
- "temperature": 0.1
142
- },
143
- timeout=60
144
- )
145
-
146
- if response.status_code == 200:
147
- enhanced = response.json()['choices'][0]['message']['content'].strip()
148
- self._extract_mapping_from_text(text, enhanced)
149
- logger.info("✅ ترکیبی: بهبود شده")
150
- return enhanced, self.mapping_table
151
- except:
152
- pass
153
-
154
- logger.info("✅ ترکیبی: Regex نتیجه")
155
- return anonymized_regex, self.mapping_table
156
-
157
- def _extract_mapping_from_text(self, original: str, anonymized: str):
158
- """استخراج mapping از متن‌های اصلی و ناشناس شده"""
159
- # الگوهای موجودیت
160
- patterns = {
161
- 'person': r'\b[ء-ي]+\s+[ء-ي]+(?:\s+[ء-ي]+)*\b',
162
- 'company': r'(?:شرکت|بانک|سازمان|گروه|هلدینگ)\s+[ء-ي]+(?:\s+[ء-ي]+)*',
163
- 'amount': r'\d+\s*(?:میلیارد|میلیون|هزار|تومان|ریال|دلار|تن)',
164
- 'percent': r'\d+\s*(?:درصد|%|درصدی)',
165
- }
166
-
167
- for entity_type, pattern in patterns.items():
168
- for match in re.finditer(pattern, original):
169
- text_match = match.group()
170
- tokens = re.findall(f'{entity_type}-\\d+', anonymized)
171
- if tokens:
172
- for token in tokens:
173
- if token not in self.mapping_table:
174
- self.mapping_table[token] = text_match
175
- self.reverse_mapping[text_match] = token
176
-
177
- def analyze_with_gpt(self, anonymized_text: str) -> str:
178
- """تحلیل متن ناشناس‌شده با ChatGPT"""
179
- logger.info("🤖 ChatGPT تحلیل...")
180
-
181
- if not self.gpt_key:
182
- logger.warning("⚠️ GPT API Key نیست")
183
- return "❌ API Key موجود نیست"
184
-
185
- try:
186
- prompt = f"""متن مالی ناشناس‌شده زیر را تحلیل و خلاصه کنید:
187
-
188
- متن:
189
- {anonymized_text}
190
-
191
- لطفاً:
192
- 1. خلاصه‌ای مختصر و معنادار بنویسید
193
- 2. نکات اصلی را مشخص کنید
194
- 3. تمام توکن‌های ناشناس (person-01, company-01, amount-01, percent-01) را حفظ کنید
195
- 4. تنها اطلاعات موجود در متن را بیان کنید"""
196
-
197
- response = requests.post(
198
- "https://api.openai.com/v1/chat/completions",
199
- headers={
200
- "Authorization": f"Bearer {self.gpt_key}",
201
- "Content-Type": "application/json"
202
- },
203
- json={
204
- "model": "gpt-4o-mini",
205
- "messages": [
206
- {
207
- "role": "system",
208
- "content": "شما دستیار تحلیل متون مالی فارسی هستید. توکن‌های ناشناس را حفظ کنید."
209
- },
210
- {"role": "user", "content": prompt}
211
- ],
212
- "max_tokens": 1500,
213
- "temperature": 0.7
214
- },
215
- timeout=60
216
- )
217
-
218
- if response.status_code == 200:
219
- gpt_response = response.json()['choices'][0]['message']['content']
220
- logger.info("✅ ChatGPT: تحلیل کامل")
221
- return gpt_response
222
- else:
223
- logger.error(f"❌ GPT Error: {response.status_code}")
224
- return "❌ خطای ChatGPT"
225
-
226
- except Exception as e:
227
- logger.error(f"❌ GPT Exception: {e}")
228
- return f"❌ خطا: {str(e)}"
229
-
230
- def restore_text(self, anonymized_text: str) -> str:
231
- """بازگردانی متن اصلی"""
232
- logger.info("🔄 بازگردانی...")
233
-
234
- restored = anonymized_text
235
- for placeholder, original in sorted(self.mapping_table.items()):
236
- restored = restored.replace(placeholder, original)
237
-
238
- logger.info("✅ بازگردانی کامل")
239
- return restored
240
-
241
- def get_mapping_table_md(self) -> str:
242
- """تبدیل جدول نگاشت به Markdown"""
243
- if not self.mapping_table:
244
- return "### 📋 جدول نگاشت\n\nهیچ موجودیتی شناسایی نشد"
245
-
246
- table = "### 📋 جدول نگاشت\n\n"
247
- table += "| شناسه | متن اصلی |\n"
248
- table += "|-------|----------|\n"
249
-
250
- for token, original in sorted(self.mapping_table.items()):
251
- table += f"| **{token}** | {original} |\n"
252
-
253
- return table
254
-
255
- # متغیر سراسری
256
- anonymizer = None
257
-
258
- def process(input_text: str, method: str = "combined"):
259
- """پردازش متن - 4 مرحله"""
260
- global anonymizer
261
-
262
- if not input_text.strip():
263
- return "", "", "", ""
264
-
265
- cerebras_key = os.getenv("CEREBRAS_API_KEY")
266
- gpt_key = os.getenv("OPENAI_API_KEY")
267
-
268
- if not anonymizer:
269
- anonymizer = AnonymizerAdvanced(cerebras_key, gpt_key)
270
- else:
271
- anonymizer.mapping_table = {}
272
- anonymizer.reverse_mapping = {}
273
-
274
- try:
275
- logger.info("=" * 70)
276
- logger.info(f"🚀 شروع پردازش - روش: {method}")
277
- logger.info("=" * 70)
278
-
279
- # ============================================
280
- # مرحله 1: ناشناس‌سازی
281
- # ============================================
282
- logger.info("📝 مرحله 1: ناشناس‌سازی...")
283
-
284
- if method == "regex":
285
- anonymized_text, _ = anonymizer.anonymize_with_regex(input_text)
286
- elif method == "cerebras":
287
- anonymized_text, _ = anonymizer.anonymize_with_cerebras(input_text)
288
- else: # combined
289
- anonymized_text, _ = anonymizer.anonymize_combined(input_text)
290
-
291
- logger.info(f"✅ ناشناس‌سازی: {len(anonymized_text)} کاراکتر")
292
-
293
- # ============================================
294
- # مرحله 2: تحلیل ChatGPT
295
- # ============================================
296
- logger.info("🤖 مرحله 2: تحلیل ChatGPT...")
297
- gpt_response = anonymizer.analyze_with_gpt(anonymized_text)
298
- logger.info(f"✅ تحلیل: {len(gpt_response)} کاراکتر")
299
-
300
- # ============================================
301
- # مرحله 3: بازگردانی
302
- # ============================================
303
- logger.info("🔄 مرحله 3: بازگردانی...")
304
- restored_text = anonymizer.restore_text(anonymized_text)
305
- logger.info("✅ بازگردانی کامل")
306
-
307
- # ============================================
308
- # مرحله 4: جدول نگاشت
309
- # ============================================
310
- logger.info("📋 مرحله 4: جدول نگاشت...")
311
- mapping_str = anonymizer.get_mapping_table_md()
312
- logger.info(f"✅ {len(anonymizer.mapping_table)} موجودیت")
313
-
314
- logger.info("=" * 70)
315
- logger.info("✅ تمام مراحل کامل!")
316
- logger.info("=" * 70)
317
-
318
- return anonymized_text, gpt_response, restored_text, mapping_str
319
-
320
- except Exception as e:
321
- logger.error(f"❌ خطا: {str(e)}", exc_info=True)
322
- return "", f"❌ خطا: {str(e)}", "", ""
323
-
324
- def clear_all():
325
- """پاک کردن همه"""
326
- return "", "", "", ""
327
-
328
- # Gradio Interface
329
- css_rtl = """
330
- .input-box { direction: rtl; text-align: right; }
331
- .textbox textarea { direction: rtl; text-align: right; font-family: 'Tahoma', serif; }
332
- """
333
-
334
- with gr.Blocks(title="سیستم ناشناس‌سازی متون", theme=gr.themes.Soft(), css=css_rtl) as app:
335
-
336
- gr.Markdown("# 🔐 سیستم ناشناس‌سازی متون مالی فارسی", elem_classes="input-box")
337
- gr.Markdown("#### استخراج و ناشناس‌سازی موجودیت‌های حساس", elem_classes="input-box")
338
-
339
- # ============================================
340
- # صفحه اول: ورودی (راست) + دکمه‌ها (چپ)
341
- # ============================================
342
- with gr.Row():
343
- # سمت راست: متن ورودی (بزرگ‌تر)
344
- with gr.Column(scale=3):
345
- input_text = gr.Textbox(
346
- lines=14,
347
- placeholder="متن مالی/خبری را وارد کنید...",
348
- label="📝 متن ورودی",
349
- elem_classes="textbox"
350
- )
351
-
352
- # سمت چپ: دکمه‌ها و تنظیمات
353
- with gr.Column(scale=1):
354
- gr.Markdown("### ⚙️ تنظیمات", elem_classes="input-box")
355
-
356
- method = gr.Radio(
357
- ["regex", "cerebras", "combined"],
358
- value="combined",
359
- label="🔧 روش پردازش",
360
- elem_classes="input-box"
361
- )
362
-
363
- gr.Markdown("---")
364
-
365
- with gr.Column():
366
- process_btn = gr.Button(
367
- "▶️ پردازش",
368
- variant="primary",
369
- size="lg"
370
- )
371
-
372
- clear_btn = gr.Button(
373
- "🗑️ پاک کردن",
374
- variant="stop",
375
- size="lg"
376
- )
377
-
378
- # ============================================
379
- # صفحه دوم: 3 باکس نتایج (وسط)
380
- # ============================================
381
- gr.Markdown("---")
382
- gr.Markdown("## 📊 نتایج پردازش", elem_classes="input-box")
383
-
384
- with gr.Row():
385
- # باکس 1: متن ناشناس‌شده (راست)
386
- with gr.Column(scale=1):
387
- anonymized_text = gr.Textbox(
388
- lines=12,
389
- label="🔒 متن ناشناس‌شده",
390
- interactive=False,
391
- elem_classes="textbox"
392
- )
393
-
394
- # باکس 2: تحلیل ChatGPT (وسط)
395
- with gr.Column(scale=1):
396
- gpt_analysis = gr.Textbox(
397
- lines=12,
398
- label="🤖 تحلیل ChatGPT",
399
- interactive=False,
400
- elem_classes="textbox"
401
- )
402
-
403
- # باکس 3: متن بازگردانی شده (چپ)
404
- with gr.Column(scale=1):
405
- restored_text = gr.Textbox(
406
- lines=12,
407
- label="✅ متن بازگردانی شده",
408
- interactive=False,
409
- elem_classes="textbox"
410
- )
411
-
412
- # ============================================
413
- # پایین: جدول نگاشت
414
- # ============================================
415
- gr.Markdown("---")
416
-
417
- mapping_table = gr.Textbox(
418
- lines=10,
419
- label="📋 جدول نگاشت",
420
- interactive=False,
421
- elem_classes="textbox"
422
- )
423
-
424
- # ============================================
425
- # Event Handlers
426
- # ============================================
427
- process_btn.click(
428
- fn=process,
429
- inputs=[input_text, method],
430
- outputs=[anonymized_text, gpt_analysis, restored_text, mapping_table]
431
- )
432
-
433
- clear_btn.click(
434
- fn=clear_all,
435
- outputs=[input_text, anonymized_text, gpt_analysis, restored_text, mapping_table]
436
- )
437
-
438
- if __name__ == "__main__":
439
- print("\n" + "=" * 70)
440
- print("🚀 سیستم ناشناس‌سازی متون در حال راه‌اندازی...")
441
- print("=" * 70)
442
- print("\n📋 نحوه استفاده:\n")
443
- print("1. CEREBRAS_API_KEY و OPENAI_API_KEY را تنظیم کنید (اختیاری)")
444
- print("2. http://localhost:7860 را باز کنید")
445
- print("3. متن را وارد کنید")
446
- print("4. روش را انتخاب کنید (توصیه: ترکیبی)")
447
- print("5. 'پردازش' را کلیک کنید\n")
448
- print("روش‌های دستیس:")
449
- print(" ✅ regex: سریع، بدون API")
450
- print(" ✅ cerebras: دقیق، با API Cerebras")
451
- print(" ✅ combined: بهترین (ترکیبی)\n")
452
- print("=" * 70 + "\n")
453
-
454
- app.launch(
455
- server_name="0.0.0.0",
456
- server_port=7860,
457
- share=False,
458
- show_error=True
459
- )